From 93c77f5728ef992017c8d81cf281066e66fd77f5 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 10:48:52 +0200 Subject: [PATCH 01/52] enabled video export --- .../internal/convertercontroller.cpp | 10 +-- .../videoexport/internal/videowriter.cpp | 81 +++++++++++++------ .../videoexport/internal/videowriter.h | 17 ++-- .../videoexport/videoexportmodule.cpp | 8 +- .../internal/exportprojectscenario.cpp | 7 +- .../qml/MuseScore/Project/CMakeLists.txt | 1 + .../internal/Export/Mp4SettingsPage.qml | 27 +++++++ .../internal/Export/exportdialogmodel.cpp | 8 ++ 8 files changed, 115 insertions(+), 44 deletions(-) create mode 100644 src/project/qml/MuseScore/Project/internal/Export/Mp4SettingsPage.qml diff --git a/src/converter/internal/convertercontroller.cpp b/src/converter/internal/convertercontroller.cpp index ab04b47ed149e..a624c0f70d9d6 100644 --- a/src/converter/internal/convertercontroller.cpp +++ b/src/converter/internal/convertercontroller.cpp @@ -713,7 +713,7 @@ Ret ConverterController::exportScoreVideo(const muse::io::path_t& in, const muse } std::string suffix = io::suffix(out); - auto writer = projectRW()->writer(suffix); + auto writer = writers()->writer(suffix); if (!writer) { return make_ret(Err::ConvertTypeUnknown); } @@ -724,13 +724,7 @@ Ret ConverterController::exportScoreVideo(const muse::io::path_t& in, const muse return make_ret(Err::InFileFailedLoad); } - ret = writer->write(notationProject, out); - if (!ret) { - LOGE() << "failed write, err: " << ret.toString() << ", path: " << out; - return make_ret(Err::OutFileFailedWrite); - } - - return make_ret(Ret::Code::Ok); + return convertFullNotation(writer, notationProject->masterNotation()->notation(), out); } Ret ConverterController::updateSource(const muse::io::path_t& in, const std::string& newSource, bool forceMode) diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index 9be1e398813c0..7b28612abcbd7 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -27,8 +27,12 @@ #include "engraving/dom/repeatlist.h" #include "engraving/dom/masterscore.h" +#include "notation/imasternotation.h" +#include "notation/notationtypes.h" + #include "notationscene/qml/MuseScore/NotationScene/playbackcursor.h" +#include "defer.h" #include "log.h" #include @@ -39,7 +43,7 @@ using namespace mu::notation; using namespace muse::draw; using namespace muse::midi; -std::vector VideoWriter::supportedUnitTypes() const +std::vector VideoWriter::supportedUnitTypes() const { return { UnitType::PER_PART }; } @@ -50,14 +54,13 @@ bool VideoWriter::supportsUnitType(UnitType unitType) const return std::find(unitTypes.cbegin(), unitTypes.cend(), unitType) != unitTypes.cend(); } -muse::Ret VideoWriter::write(INotationProjectPtr, QIODevice&, const Options&) +muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, const Options&) { - NOT_SUPPORTED; - return make_ret(muse::Ret::Code::NotSupported); -} + std::string filePath = device.meta("file_path"); + IF_ASSERT_FAILED(!filePath.empty()) { + return make_ret(muse::Ret::Code::InternalError); + } -muse::Ret VideoWriter::write(INotationProjectPtr project, const muse::io::path_t& filePath, const Options&) -{ Config cfg; cfg.fps = configuration()->fps(); @@ -107,26 +110,46 @@ muse::Ret VideoWriter::write(INotationProjectPtr project, const muse::io::path_t cfg.leadingSec = configuration()->leadingSec(); cfg.trailingSec = configuration()->trailingSec(); - muse::Ret ret = generatePagedOriginalVideo(project, filePath, cfg); - return ret; + return generatePagedOriginalVideo(notation, muse::io::path_t(filePath), cfg); +} + +muse::Ret VideoWriter::writeList(const INotationPtrList&, muse::io::IODevice&, const Options&) +{ + NOT_SUPPORTED; + return make_ret(muse::Ret::Code::NotSupported); +} + +muse::Progress* VideoWriter::progress() +{ + return &m_progress; } -muse::Ret VideoWriter::generatePagedOriginalVideo(INotationProjectPtr project, const muse::io::path_t& filePath, const Config& config) +void VideoWriter::abort() { - // --score-video -o ./simple5.mp4 ./simple5.mscz + m_abort = true; +} +muse::Ret VideoWriter::generatePagedOriginalVideo(INotationPtr notation, const muse::io::path_t& filePath, const Config& config) +{ VideoEncoder encoder; if (!encoder.open(filePath, config.width, config.height, config.bitrate, config.fps / 2, config.fps)) { LOGE() << "failed open encoder"; return make_ret(muse::Ret::Code::UnknownError); } - IMasterNotationPtr masterNotation = project->masterNotation(); + engraving::MasterScore* score = notation->elements()->msScore()->masterScore(); + + notation::ViewMode originalViewMode = notation->viewMode(); + engraving::MStyle originalStyle = score->style(); - engraving::MasterScore* score = masterNotation->notation()->elements()->msScore()->masterScore(); + DEFER { + score->style() = originalStyle; + score->setLayoutAll(); + score->update(); + notation->setViewMode(originalViewMode); + }; - // Setup Score view - masterNotation->notation()->setViewMode(notation::ViewMode::PAGE); + notation->setViewMode(notation::ViewMode::PAGE); score->setShowFrames(false); score->setShowInstrumentNames(false); score->setShowInvisible(false); @@ -136,7 +159,7 @@ muse::Ret VideoWriter::generatePagedOriginalVideo(INotationProjectPtr project, c score->doLayout(); - PageList pages = masterNotation->notation()->elements()->pages(); + PageList pages = notation->elements()->pages(); if (pages.empty()) { LOGE() << "No pages"; return make_ret(muse::Ret::Code::UnknownError); @@ -188,18 +211,17 @@ muse::Ret VideoWriter::generatePagedOriginalVideo(INotationProjectPtr project, c Painter painter(&qp, "video_writer"); - auto painting = masterNotation->notation()->painting(); + auto painting = notation->painting(); // Setup duration - INotationPlaybackPtr playback = masterNotation->playback(); + INotationPlaybackPtr playback = notation->masterNotation()->playback(); float totalPlayTimeSec = playback->totalPlayTime(); - LOGI() << "totalPlayTime: " << totalPlayTimeSec << " sec"; - int frameCount = (totalPlayTimeSec + config.leadingSec + config.trailingSec) * config.fps; + LOGI() << "totalPlayTime: " << totalPlayTimeSec << " sec" << " frame count " << frameCount; //! NOTE: After setting the score above, the number of pages may change - get them again - pages = masterNotation->notation()->elements()->pages(); + pages = notation->elements()->pages(); auto pageByTick = [](const PageList& pages, tick_t tick) -> const Page* { for (const Page* p : pages) { @@ -212,10 +234,21 @@ muse::Ret VideoWriter::generatePagedOriginalVideo(INotationProjectPtr project, c const Color CURSOR_COLOR = Color(0, 0, 255, 50); - PlaybackCursor cursor(application()->iocContext()); - cursor.setNotation(masterNotation->notation()); + PlaybackCursor cursor(iocContext()); + cursor.setNotation(notation); + + m_abort = false; + m_progress.start(); for (int f = 0; f < frameCount; f++) { + if (m_abort) { + encoder.close(); + m_progress.finish(make_ret(muse::Ret::Code::Cancel)); + return make_ret(muse::Ret::Code::Cancel); + } + + m_progress.progress(f, frameCount); + float currentTimeSec = (qreal)f / config.fps; currentTimeSec -= config.leadingSec; if (currentTimeSec <= 0) { @@ -254,5 +287,7 @@ muse::Ret VideoWriter::generatePagedOriginalVideo(INotationProjectPtr project, c encoder.close(); + m_progress.finish(muse::make_ok()); + return muse::make_ok(); } diff --git a/src/importexport/videoexport/internal/videowriter.h b/src/importexport/videoexport/internal/videowriter.h index 6a49dcd6a9cff..dc10e64d62e06 100644 --- a/src/importexport/videoexport/internal/videowriter.h +++ b/src/importexport/videoexport/internal/videowriter.h @@ -26,10 +26,10 @@ #include "../ivideoexportconfiguration.h" #include "iapplication.h" -#include "project/iprojectwriter.h" +#include "project/inotationwriter.h" namespace mu::iex::videoexport { -class VideoWriter : public project::IProjectWriter +class VideoWriter : public project::INotationWriter, public muse::Contextable { muse::GlobalInject configuration; muse::GlobalInject application; @@ -38,8 +38,12 @@ class VideoWriter : public project::IProjectWriter std::vector supportedUnitTypes() const override; bool supportsUnitType(UnitType unitType) const override; - muse::Ret write(project::INotationProjectPtr project, QIODevice& device, const Options& options = Options()) override; - muse::Ret write(project::INotationProjectPtr project, const muse::io::path_t& filePath, const Options& options = Options()) override; + muse::Ret write(notation::INotationPtr notation, muse::io::IODevice& device, const Options& options = Options()) override; + muse::Ret writeList(const notation::INotationPtrList& notations, muse::io::IODevice& device, + const Options& options = Options()) override; + + muse::Progress* progress() override; + void abort() override; private: @@ -53,7 +57,10 @@ class VideoWriter : public project::IProjectWriter float trailingSec = 3.; }; - muse::Ret generatePagedOriginalVideo(project::INotationProjectPtr project, const muse::io::path_t& filePath, const Config& config); + muse::Ret generatePagedOriginalVideo(notation::INotationPtr notation, const muse::io::path_t& filePath, const Config& config); + + muse::Progress m_progress; + bool m_abort = false; }; } diff --git a/src/importexport/videoexport/videoexportmodule.cpp b/src/importexport/videoexport/videoexportmodule.cpp index 3f7008560dd3d..0da4cc4ecda2b 100644 --- a/src/importexport/videoexport/videoexportmodule.cpp +++ b/src/importexport/videoexport/videoexportmodule.cpp @@ -26,7 +26,7 @@ #include "internal/videoexportconfiguration.h" #include "internal/videowriter.h" -#include "project/iprojectrwregister.h" +#include "project/inotationwritersregister.h" using namespace mu::iex::videoexport; using namespace mu::project; @@ -46,8 +46,8 @@ void VideoExportModule::registerExports() void VideoExportModule::resolveImports() { - auto projectRWreg = globalIoc()->resolve(moduleName()); - if (projectRWreg) { - projectRWreg->regWriter({ "mp4" }, std::make_shared()); + auto writers = ioc()->resolve(moduleName()); + if (writers) { + writers->reg({ "mp4" }, std::make_shared(iocContext())); } } diff --git a/src/project/internal/exportprojectscenario.cpp b/src/project/internal/exportprojectscenario.cpp index 2f62cd9661950..032d7a598c079 100644 --- a/src/project/internal/exportprojectscenario.cpp +++ b/src/project/internal/exportprojectscenario.cpp @@ -39,12 +39,11 @@ std::vector ExportProjectScenario::supportedUnitTypes return {}; } - auto writer = writers()->writer(exportType.suffixes.front().toStdString()); - if (!writer) { - return {}; + if (auto writer = writers()->writer(exportType.suffixes.front().toStdString())) { + return writer->supportedUnitTypes(); } - return writer->supportedUnitTypes(); + return {}; } RetVal ExportProjectScenario::askExportPath(const INotationPtrList& notations, const ExportType& exportType, diff --git a/src/project/qml/MuseScore/Project/CMakeLists.txt b/src/project/qml/MuseScore/Project/CMakeLists.txt index fbbc69b10510e..522fe39b9802f 100644 --- a/src/project/qml/MuseScore/Project/CMakeLists.txt +++ b/src/project/qml/MuseScore/Project/CMakeLists.txt @@ -70,6 +70,7 @@ qt_add_qml_module(project_qml internal/Export/MidiSettingsPage.qml internal/Export/MnxSettingsPage.qml internal/Export/Mp3SettingsPage.qml + internal/Export/Mp4SettingsPage.qml internal/Export/MusicXmlSettingsPage.qml internal/Export/OggSettingsPage.qml internal/Export/PdfSettingsPage.qml diff --git a/src/project/qml/MuseScore/Project/internal/Export/Mp4SettingsPage.qml b/src/project/qml/MuseScore/Project/internal/Export/Mp4SettingsPage.qml new file mode 100644 index 0000000000000..ad663822c87ad --- /dev/null +++ b/src/project/qml/MuseScore/Project/internal/Export/Mp4SettingsPage.qml @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import QtQuick + +AudioSettingsPage { + showBitRateControl: true +} + diff --git a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp index bad5c3ff4c6b8..c1df2a14a6726 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp +++ b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp @@ -25,6 +25,8 @@ #include +#include "app_config.h" + #include "async/async.h" #include "translation.h" #include "log.h" @@ -77,6 +79,12 @@ ExportDialogModel::ExportDialogModel(QObject* parent) muse::qtrc("project/export", "MP3 audio"), muse::qtrc("project/export", "MP3 audio files"), "Mp3SettingsPage.qml"), +#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE + ExportType::makeWithSuffixes({ "mp4" }, + muse::qtrc("project/export", "Video mp4"), + muse::qtrc("project/export", "Video mp4 files"), + "Mp4SettingsPage.qml"), +#endif ExportType::makeWithSuffixes({ "wav" }, muse::qtrc("project/export", "WAV audio"), muse::qtrc("project/export", "WAV audio files"), From d1caaa6640bdf769cf90e346e943ade8c28091c0 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 2 Mar 2026 14:47:58 +0200 Subject: [PATCH 02/52] moved video writing to separate thread --- src/importexport/videoexport/CMakeLists.txt | 2 +- .../videoexport/internal/videowriter.cpp | 37 +++++++++++++++---- .../videoexport/internal/videowriter.h | 4 +- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/importexport/videoexport/CMakeLists.txt b/src/importexport/videoexport/CMakeLists.txt index 9575de59c4269..a25ae27eb8a68 100644 --- a/src/importexport/videoexport/CMakeLists.txt +++ b/src/importexport/videoexport/CMakeLists.txt @@ -35,7 +35,7 @@ target_sources(iex_videoexport PRIVATE internal/ffmpeg.h ) -target_link_libraries(iex_videoexport PRIVATE engraving) +target_link_libraries(iex_videoexport PRIVATE Qt::Concurrent engraving) # FFmpeg find_package(FFmpeg REQUIRED) diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index 7b28612abcbd7..50345378fc592 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -32,10 +32,13 @@ #include "notationscene/qml/MuseScore/NotationScene/playbackcursor.h" +#include "global/concurrency/concurrent.h" + #include "defer.h" #include "log.h" #include +#include using namespace mu::iex::videoexport; using namespace mu::project; @@ -110,7 +113,20 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, cfg.leadingSec = configuration()->leadingSec(); cfg.trailingSec = configuration()->trailingSec(); - return generatePagedOriginalVideo(notation, muse::io::path_t(filePath), cfg); + m_isCompleted = false; + m_abort = false; + m_writeRet = muse::Ret(); + + muse::Concurrent::run([this, notation, filePath, cfg]() { + doGenerate(notation, muse::io::path_t(filePath), cfg); + }); + + while (!m_isCompleted) { + application()->processEvents(); + QThread::yieldCurrentThread(); + } + + return m_writeRet; } muse::Ret VideoWriter::writeList(const INotationPtrList&, muse::io::IODevice&, const Options&) @@ -129,12 +145,14 @@ void VideoWriter::abort() m_abort = true; } -muse::Ret VideoWriter::generatePagedOriginalVideo(INotationPtr notation, const muse::io::path_t& filePath, const Config& config) +void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& filePath, const Config& config) { VideoEncoder encoder; if (!encoder.open(filePath, config.width, config.height, config.bitrate, config.fps / 2, config.fps)) { LOGE() << "failed open encoder"; - return make_ret(muse::Ret::Code::UnknownError); + m_writeRet = make_ret(muse::Ret::Code::UnknownError); + m_isCompleted = true; + return; } engraving::MasterScore* score = notation->elements()->msScore()->masterScore(); @@ -162,7 +180,9 @@ muse::Ret VideoWriter::generatePagedOriginalVideo(INotationPtr notation, const m PageList pages = notation->elements()->pages(); if (pages.empty()) { LOGE() << "No pages"; - return make_ret(muse::Ret::Code::UnknownError); + m_writeRet = make_ret(muse::Ret::Code::UnknownError); + m_isCompleted = true; + return; } double CANVAS_DPI = 300; @@ -237,14 +257,15 @@ muse::Ret VideoWriter::generatePagedOriginalVideo(INotationPtr notation, const m PlaybackCursor cursor(iocContext()); cursor.setNotation(notation); - m_abort = false; m_progress.start(); for (int f = 0; f < frameCount; f++) { if (m_abort) { encoder.close(); + m_writeRet = make_ret(muse::Ret::Code::Cancel); m_progress.finish(make_ret(muse::Ret::Code::Cancel)); - return make_ret(muse::Ret::Code::Cancel); + m_isCompleted = true; + return; } m_progress.progress(f, frameCount); @@ -287,7 +308,7 @@ muse::Ret VideoWriter::generatePagedOriginalVideo(INotationPtr notation, const m encoder.close(); + m_writeRet = muse::make_ok(); m_progress.finish(muse::make_ok()); - - return muse::make_ok(); + m_isCompleted = true; } diff --git a/src/importexport/videoexport/internal/videowriter.h b/src/importexport/videoexport/internal/videowriter.h index dc10e64d62e06..27636e32a5140 100644 --- a/src/importexport/videoexport/internal/videowriter.h +++ b/src/importexport/videoexport/internal/videowriter.h @@ -57,10 +57,12 @@ class VideoWriter : public project::INotationWriter, public muse::Contextable float trailingSec = 3.; }; - muse::Ret generatePagedOriginalVideo(notation::INotationPtr notation, const muse::io::path_t& filePath, const Config& config); + void doGenerate(notation::INotationPtr notation, const muse::io::path_t& filePath, const Config& config); muse::Progress m_progress; bool m_abort = false; + bool m_isCompleted = false; + muse::Ret m_writeRet; }; } From 3e5a0a406ed62903c3546bedbe589ef58774a1b4 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 10:50:14 +0200 Subject: [PATCH 03/52] added audio to video exporting --- .../internal/abstractaudiowriter.cpp | 40 +++-- .../internal/abstractaudiowriter.h | 3 +- .../audioexport/internal/flacwriter.cpp | 4 +- .../audioexport/internal/mp3writer.cpp | 4 +- .../audioexport/internal/oggwriter.cpp | 4 +- .../audioexport/internal/wavewriter.cpp | 4 +- .../videoexport/internal/videoencoder.cpp | 154 ++++++++++++++++++ .../videoexport/internal/videoencoder.h | 5 + .../videoexport/internal/videowriter.cpp | 98 +++++++++-- .../videoexport/internal/videowriter.h | 16 +- src/project/inotationwriter.h | 3 +- 11 files changed, 295 insertions(+), 40 deletions(-) diff --git a/src/importexport/audioexport/internal/abstractaudiowriter.cpp b/src/importexport/audioexport/internal/abstractaudiowriter.cpp index 7373f348c8bbc..914275a58ac11 100644 --- a/src/importexport/audioexport/internal/abstractaudiowriter.cpp +++ b/src/importexport/audioexport/internal/abstractaudiowriter.cpp @@ -90,8 +90,9 @@ muse::Progress* AbstractAudioWriter::progress() } Ret AbstractAudioWriter::doWriteAndWait(INotationPtr notation, - io::IODevice& dstDevice, - const SoundTrackFormat& format) + io::IODevice& destinationDevice, + const SoundTrackFormat& format, + const Options& options) { //! NOTE Temporary fix for the context injection m_iocContext = notation->iocContext(); @@ -114,14 +115,14 @@ Ret AbstractAudioWriter::doWriteAndWait(INotationPtr notation, doWrite(dstDevice, format); - while (!m_isCompleted) { - application()->processEvents(); - QThread::yieldCurrentThread(); + bool waitForCompletion = muse::value(options, OptionKey::WAIT_FOR_COMPLETION, Val(true)).toBool(); + if (waitForCompletion) { + while (!m_isCompleted) { + application()->processEvents(); + QThread::yieldCurrentThread(); + } } - playbackController()->setIsExportingAudio(false); - playbackController()->setNotation(globalContext()->currentNotation()); - return m_writeRet; } @@ -130,6 +131,11 @@ void AbstractAudioWriter::doWrite(io::IODevice& dstDevice, const SoundTrackForma muse::ContextInject playback = { m_iocContext }; const std::string processingOnlineSoundsMsg = trc("iex_audio", "Processing online sounds…"); + auto restoreState = [this]() { + playbackController()->setIsExportingAudio(false); + playbackController()->setNotation(globalContext()->currentNotation()); + }; + auto sendProgress = [this, processingOnlineSoundsMsg](int64_t current, int64_t total, SaveSoundTrackStage stage) { switch (stage) { case SaveSoundTrackStage::ProcessingOnlineSounds: @@ -143,7 +149,7 @@ void AbstractAudioWriter::doWrite(io::IODevice& dstDevice, const SoundTrackForma }; playback()->sequenceIdList() - .onResolve(this, [this, playback, &dstDevice, format, sendProgress](const TrackSequenceIdList& sequenceIdList) { + .onResolve(this, [this, playback, &dstDevice, format, sendProgress, restoreState](const TrackSequenceIdList& sequenceIdList) { m_progress.start(); for (const TrackSequenceId sequenceId : sequenceIdList) { @@ -152,27 +158,33 @@ void AbstractAudioWriter::doWrite(io::IODevice& dstDevice, const SoundTrackForma sendProgress(current, total, stage); }); - playback()->saveSoundTrack(sequenceId, std::move(format), dstDevice) - .onResolve(this, [this, sequenceId](const bool /*result*/) { - LOGI() << "Successfully saved sound track"; + playback()->saveSoundTrack(sequenceId, muse::io::path_t(path), std::move(format)) + .onResolve(this, [this, path, sequenceId, restoreState](const bool /*result*/) { + LOGI() << "Successfully saved sound track by path: " << path; m_writeRet = muse::make_ok(); m_isCompleted = true; m_progress.finish(muse::make_ok()); muse::ContextInject playback = { m_iocContext }; playback()->saveSoundTrackProgressChanged(sequenceId).disconnect(this); + + restoreState(); }) - .onReject(this, [this, sequenceId](int errorCode, const std::string& msg) { + .onReject(this, [this, sequenceId, restoreState](int errorCode, const std::string& msg) { m_writeRet = Ret(errorCode, msg); m_isCompleted = true; m_progress.finish(make_ret(errorCode, msg)); muse::ContextInject playback = { m_iocContext }; playback()->saveSoundTrackProgressChanged(sequenceId).disconnect(this); + + restoreState(); }); } }) - .onReject(this, [this](int errorCode, const std::string& msg) { + .onReject(this, [this, restoreState](int errorCode, const std::string& msg) { LOGE() << "errorCode: " << errorCode << ", " << msg; m_isCompleted = true; + + restoreState(); }); } diff --git a/src/importexport/audioexport/internal/abstractaudiowriter.h b/src/importexport/audioexport/internal/abstractaudiowriter.h index 41d7fc023a4d5..e712c8d65a51f 100644 --- a/src/importexport/audioexport/internal/abstractaudiowriter.h +++ b/src/importexport/audioexport/internal/abstractaudiowriter.h @@ -55,7 +55,8 @@ class AbstractAudioWriter : public project::INotationWriter, public muse::Contex void abort() override; protected: - muse::Ret doWriteAndWait(notation::INotationPtr notation, muse::io::IODevice& dstDevice, const muse::audio::SoundTrackFormat& format); + muse::Ret doWriteAndWait(notation::INotationPtr notation, muse::io::IODevice& dstDevice, const muse::audio::SoundTrackFormat& format, + const Options& options = Options()); private: void doWrite(muse::io::IODevice& dstDevice, const muse::audio::SoundTrackFormat& format); diff --git a/src/importexport/audioexport/internal/flacwriter.cpp b/src/importexport/audioexport/internal/flacwriter.cpp index f7bd8d25c80cb..ed10998c4b687 100644 --- a/src/importexport/audioexport/internal/flacwriter.cpp +++ b/src/importexport/audioexport/internal/flacwriter.cpp @@ -28,7 +28,7 @@ using namespace muse::audio; using namespace mu::iex::audioexport; using namespace muse::io; -muse::Ret FlacWriter::write(notation::INotationPtr notation, muse::io::IODevice& destinationDevice, const Options&) +muse::Ret FlacWriter::write(notation::INotationPtr notation, muse::io::IODevice& destinationDevice, const Options& options) { const SoundTrackFormat format { SoundTrackType::FLAC, @@ -41,5 +41,5 @@ muse::Ret FlacWriter::write(notation::INotationPtr notation, muse::io::IODevice& 0 /* bitRate */ }; - return doWriteAndWait(notation, destinationDevice, format); + return doWriteAndWait(notation, destinationDevice, format, options); } diff --git a/src/importexport/audioexport/internal/mp3writer.cpp b/src/importexport/audioexport/internal/mp3writer.cpp index d8905f70101e1..2cb6b57712d4e 100644 --- a/src/importexport/audioexport/internal/mp3writer.cpp +++ b/src/importexport/audioexport/internal/mp3writer.cpp @@ -28,7 +28,7 @@ using namespace muse; using namespace muse::audio; using namespace mu::iex::audioexport; -Ret Mp3Writer::write(notation::INotationPtr notation, io::IODevice& destinationDevice, const Options&) +Ret Mp3Writer::write(notation::INotationPtr notation, io::IODevice& destinationDevice, const Options& options) { const SoundTrackFormat format { SoundTrackType::MP3, @@ -41,5 +41,5 @@ Ret Mp3Writer::write(notation::INotationPtr notation, io::IODevice& destinationD configuration()->exportMp3Bitrate() }; - return doWriteAndWait(notation, destinationDevice, format); + return doWriteAndWait(notation, destinationDevice, format, options); } diff --git a/src/importexport/audioexport/internal/oggwriter.cpp b/src/importexport/audioexport/internal/oggwriter.cpp index 22e620dd4d0be..21be5b623ad3f 100644 --- a/src/importexport/audioexport/internal/oggwriter.cpp +++ b/src/importexport/audioexport/internal/oggwriter.cpp @@ -29,7 +29,7 @@ using namespace mu::iex::audioexport; using namespace muse; using namespace muse::io; -Ret OggWriter::write(notation::INotationPtr notation, io::IODevice& destinationDevice, const Options&) +Ret OggWriter::write(notation::INotationPtr notation, io::IODevice& destinationDevice, const Options& options) { const SoundTrackFormat format { SoundTrackType::OGG, @@ -42,5 +42,5 @@ Ret OggWriter::write(notation::INotationPtr notation, io::IODevice& destinationD 128 /* bitRate */ }; - return doWriteAndWait(notation, destinationDevice, format); + return doWriteAndWait(notation, destinationDevice, format, options); } diff --git a/src/importexport/audioexport/internal/wavewriter.cpp b/src/importexport/audioexport/internal/wavewriter.cpp index 0c583add3c51c..ec844c96aa23c 100644 --- a/src/importexport/audioexport/internal/wavewriter.cpp +++ b/src/importexport/audioexport/internal/wavewriter.cpp @@ -28,7 +28,7 @@ using namespace muse; using namespace muse::audio; using namespace mu::iex::audioexport; -Ret WaveWriter::write(notation::INotationPtr notation, io::IODevice& destinationDevice, const Options&) +Ret WaveWriter::write(notation::INotationPtr notation, io::IODevice& destinationDevice, const Options& options) { const SoundTrackFormat format { SoundTrackType::WAV, @@ -41,5 +41,5 @@ Ret WaveWriter::write(notation::INotationPtr notation, io::IODevice& destination 0 /* bitRate */ }; - return doWriteAndWait(notation, destinationDevice, format); + return doWriteAndWait(notation, destinationDevice, format, options); } diff --git a/src/importexport/videoexport/internal/videoencoder.cpp b/src/importexport/videoexport/internal/videoencoder.cpp index 31dab14d009b6..abff25f09b48a 100644 --- a/src/importexport/videoexport/internal/videoencoder.cpp +++ b/src/importexport/videoexport/internal/videoencoder.cpp @@ -416,6 +416,160 @@ bool VideoEncoder::encodeImage(const QImage& img) return true; } +bool VideoEncoder::muxAudioVideo(const muse::io::path_t& videoPath, + const muse::io::path_t& audioPath, + const muse::io::path_t& outputPath, + double audioOffsetSec) +{ + AVFormatContext* videoFmtCtx = nullptr; + AVFormatContext* audioFmtCtx = nullptr; + AVFormatContext* outputFmtCtx = nullptr; + bool ok = false; + + auto cleanup = [&]() { + if (videoFmtCtx) { + avformat_close_input(&videoFmtCtx); + } + if (audioFmtCtx) { + avformat_close_input(&audioFmtCtx); + } + if (outputFmtCtx) { + if (outputFmtCtx->pb) { + avio_close(outputFmtCtx->pb); + } + avformat_free_context(outputFmtCtx); + } + }; + + if (avformat_open_input(&videoFmtCtx, videoPath.c_str(), nullptr, nullptr) < 0) { + LOGE() << "mux: failed to open video input: " << videoPath; + cleanup(); + return false; + } + if (avformat_find_stream_info(videoFmtCtx, nullptr) < 0) { + LOGE() << "mux: failed to find video stream info"; + cleanup(); + return false; + } + + if (avformat_open_input(&audioFmtCtx, audioPath.c_str(), nullptr, nullptr) < 0) { + LOGE() << "mux: failed to open audio input: " << audioPath; + cleanup(); + return false; + } + if (avformat_find_stream_info(audioFmtCtx, nullptr) < 0) { + LOGE() << "mux: failed to find audio stream info"; + cleanup(); + return false; + } + + avformat_alloc_output_context2(&outputFmtCtx, nullptr, "mp4", outputPath.c_str()); + if (!outputFmtCtx) { + LOGE() << "mux: failed to allocate output context"; + cleanup(); + return false; + } + + int videoInIdx = -1; + int audioInIdx = -1; + int outVideoIdx = -1; + int outAudioIdx = -1; + + for (unsigned i = 0; i < videoFmtCtx->nb_streams; i++) { + if (videoFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + videoInIdx = static_cast(i); + AVStream* outStream = avformat_new_stream(outputFmtCtx, nullptr); + if (!outStream) { + LOGE() << "mux: failed to create output video stream"; + cleanup(); + return false; + } + avcodec_parameters_copy(outStream->codecpar, videoFmtCtx->streams[i]->codecpar); + outStream->codecpar->codec_tag = 0; + outStream->time_base = videoFmtCtx->streams[i]->time_base; + outVideoIdx = outStream->index; + break; + } + } + + for (unsigned i = 0; i < audioFmtCtx->nb_streams; i++) { + if (audioFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + audioInIdx = static_cast(i); + AVStream* outStream = avformat_new_stream(outputFmtCtx, nullptr); + if (!outStream) { + LOGE() << "mux: failed to create output audio stream"; + cleanup(); + return false; + } + avcodec_parameters_copy(outStream->codecpar, audioFmtCtx->streams[i]->codecpar); + outStream->codecpar->codec_tag = 0; + outStream->time_base = audioFmtCtx->streams[i]->time_base; + outAudioIdx = outStream->index; + break; + } + } + + if (videoInIdx < 0 || audioInIdx < 0) { + LOGE() << "mux: could not find video or audio stream"; + cleanup(); + return false; + } + + if (avio_open(&outputFmtCtx->pb, outputPath.c_str(), AVIO_FLAG_WRITE) < 0) { + LOGE() << "mux: failed to open output file: " << outputPath; + cleanup(); + return false; + } + + if (avformat_write_header(outputFmtCtx, nullptr) < 0) { + LOGE() << "mux: failed to write header"; + cleanup(); + return false; + } + + int64_t audioOffsetPts = 0; + { + AVStream* audioOutStream = outputFmtCtx->streams[outAudioIdx]; + audioOffsetPts = static_cast(audioOffsetSec * audioOutStream->time_base.den / audioOutStream->time_base.num); + } + + AVPacket* pkt = av_packet_alloc(); + + // Copy video packets + while (av_read_frame(videoFmtCtx, pkt) >= 0) { + if (pkt->stream_index == videoInIdx) { + pkt->stream_index = outVideoIdx; + av_packet_rescale_ts(pkt, videoFmtCtx->streams[videoInIdx]->time_base, + outputFmtCtx->streams[outVideoIdx]->time_base); + pkt->pos = -1; + av_interleaved_write_frame(outputFmtCtx, pkt); + } + av_packet_unref(pkt); + } + + // Copy audio packets with offset + while (av_read_frame(audioFmtCtx, pkt) >= 0) { + if (pkt->stream_index == audioInIdx) { + pkt->stream_index = outAudioIdx; + av_packet_rescale_ts(pkt, audioFmtCtx->streams[audioInIdx]->time_base, + outputFmtCtx->streams[outAudioIdx]->time_base); + pkt->pts += audioOffsetPts; + pkt->dts += audioOffsetPts; + pkt->pos = -1; + av_interleaved_write_frame(outputFmtCtx, pkt); + } + av_packet_unref(pkt); + } + + av_packet_free(&pkt); + + av_write_trailer(outputFmtCtx); + + ok = true; + cleanup(); + return ok; +} + bool VideoEncoder::convertImage_sws(const QImage& img) { // Check if the image matches the size diff --git a/src/importexport/videoexport/internal/videoencoder.h b/src/importexport/videoexport/internal/videoencoder.h index 0dbf08de1eb0d..d0499a756e276 100644 --- a/src/importexport/videoexport/internal/videoencoder.h +++ b/src/importexport/videoexport/internal/videoencoder.h @@ -39,6 +39,11 @@ class VideoEncoder bool encodeImage(const QImage& img); + static bool muxAudioVideo(const muse::io::path_t& videoPath, + const muse::io::path_t& audioPath, + const muse::io::path_t& outputPath, + double audioOffsetSec); + private: bool convertImage_sws(const QImage& img); diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index 50345378fc592..77bc3254e2238 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -21,7 +21,12 @@ */ #include "videowriter.h" -#include "videoencoder.h" +#include +#include + +#include "global/concurrency/concurrent.h" +#include "io/buffer.h" +#include "io/file.h" #include "engraving/dom/page.h" #include "engraving/dom/repeatlist.h" @@ -32,14 +37,11 @@ #include "notationscene/qml/MuseScore/NotationScene/playbackcursor.h" -#include "global/concurrency/concurrent.h" +#include "videoencoder.h" #include "defer.h" #include "log.h" -#include -#include - using namespace mu::iex::videoexport; using namespace mu::project; using namespace mu::notation; @@ -64,6 +66,51 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, return make_ret(muse::Ret::Code::InternalError); } + Config cfg = makeConfig(); + + muse::io::path_t finalPath(filePath); + muse::io::path_t tempVideoPath = finalPath + ".tmp_video.mp4"; + muse::io::path_t tempAudioPath = finalPath + ".tmp_audio.mp3"; + + m_isCompleted = false; + m_audioCompleted = false; + m_abort = false; + m_writeRet = muse::Ret(); + m_audioRet = muse::Ret(); + + startVideoExport(notation, tempVideoPath, cfg); + startAudioExport(notation, tempAudioPath); + + while (!m_isCompleted || !m_audioCompleted) { + application()->processEvents(); + QThread::yieldCurrentThread(); + } + + if (m_audioWriter) { + m_audioWriter->progress()->finished().disconnect(this); + m_audioWriter = nullptr; + } + + muse::Ret result = m_writeRet; + + if (result && m_audioRet) { + if (!VideoEncoder::muxAudioVideo(tempVideoPath, tempAudioPath, finalPath, cfg.leadingSec)) { + result = make_ret(muse::Ret::Code::UnknownError); + } + } else if (!result) { + // keep video error + } else { + result = m_audioRet; + } + + muse::io::File::remove(tempVideoPath); + muse::io::File::remove(tempAudioPath); + + return result; +} + +VideoWriter::Config VideoWriter::makeConfig() const +{ Config cfg; cfg.fps = configuration()->fps(); @@ -113,20 +160,39 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, cfg.leadingSec = configuration()->leadingSec(); cfg.trailingSec = configuration()->trailingSec(); - m_isCompleted = false; - m_abort = false; - m_writeRet = muse::Ret(); + return cfg; +} - muse::Concurrent::run([this, notation, filePath, cfg]() { - doGenerate(notation, muse::io::path_t(filePath), cfg); +void VideoWriter::startVideoExport(INotationPtr notation, const muse::io::path_t& videoPath, const Config& cfg) +{ + muse::Concurrent::run([this, notation, videoPath, cfg]() { + doGenerate(notation, videoPath, cfg); }); +} - while (!m_isCompleted) { - application()->processEvents(); - QThread::yieldCurrentThread(); +void VideoWriter::startAudioExport(INotationPtr notation, const muse::io::path_t& audioPath) +{ + m_audioWriter = writers()->writer("mp3"); + if (!m_audioWriter) { + LOGE() << "mp3 writer not found"; + m_audioRet = make_ret(muse::Ret::Code::InternalError); + m_audioCompleted = true; + return; } - return m_writeRet; + m_audioWriter->progress()->finished().onReceive(this, [this](const muse::ProgressResult& res) { + m_audioRet = res.ret; + m_audioCompleted = true; + }); + + Options audioOpts; + audioOpts[OptionKey::WAIT_FOR_COMPLETION] = muse::Val(false); + + muse::io::Buffer audioDevice; + audioDevice.setMeta("file_path", audioPath.toStdString()); + audioDevice.open(muse::io::IODevice::WriteOnly); + + m_audioWriter->write(notation, audioDevice, audioOpts); } muse::Ret VideoWriter::writeList(const INotationPtrList&, muse::io::IODevice&, const Options&) @@ -143,6 +209,10 @@ muse::Progress* VideoWriter::progress() void VideoWriter::abort() { m_abort = true; + + if (m_audioWriter) { + m_audioWriter->abort(); + } } void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& filePath, const Config& config) diff --git a/src/importexport/videoexport/internal/videowriter.h b/src/importexport/videoexport/internal/videowriter.h index 27636e32a5140..9cbb9772c44a3 100644 --- a/src/importexport/videoexport/internal/videowriter.h +++ b/src/importexport/videoexport/internal/videowriter.h @@ -22,17 +22,20 @@ #ifndef MU_IMPORTEXPORT_VIDEOWRITER_H #define MU_IMPORTEXPORT_VIDEOWRITER_H +#include "async/asyncable.h" #include "modularity/ioc.h" #include "../ivideoexportconfiguration.h" #include "iapplication.h" #include "project/inotationwriter.h" +#include "project/inotationwritersregister.h" namespace mu::iex::videoexport { -class VideoWriter : public project::INotationWriter, public muse::Contextable +class VideoWriter : public project::INotationWriter, public muse::Contextable, public muse::async::Asyncable { muse::GlobalInject configuration; - muse::GlobalInject application; + muse::ContextInject application = { this }; + muse::ContextInject writers = { this }; public: std::vector supportedUnitTypes() const override; @@ -57,12 +60,21 @@ class VideoWriter : public project::INotationWriter, public muse::Contextable float trailingSec = 3.; }; + Config makeConfig() const; + + void startVideoExport(notation::INotationPtr notation, const muse::io::path_t& videoPath, const Config& cfg); + void startAudioExport(notation::INotationPtr notation, const muse::io::path_t& audioPath); + void doGenerate(notation::INotationPtr notation, const muse::io::path_t& filePath, const Config& config); muse::Progress m_progress; bool m_abort = false; bool m_isCompleted = false; muse::Ret m_writeRet; + + project::INotationWriterPtr m_audioWriter; + bool m_audioCompleted = false; + muse::Ret m_audioRet; }; } diff --git a/src/project/inotationwriter.h b/src/project/inotationwriter.h index 810ff3f5f7b37..ad4760178b632 100644 --- a/src/project/inotationwriter.h +++ b/src/project/inotationwriter.h @@ -49,7 +49,8 @@ class INotationWriter UNIT_TYPE, PAGE_NUMBER, TRANSPARENT_BACKGROUND, - BEATS_COLORS + BEATS_COLORS, + WAIT_FOR_COMPLETION }; using Options = std::map; From 75d34c18f98ec0bb7c30a38382fc1b4c0c46d218 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 2 Mar 2026 17:20:06 +0200 Subject: [PATCH 04/52] added setting video resolution --- src/project/inotationwriter.h | 1 - .../qml/MuseScore/Project/CMakeLists.txt | 4 +- ...udioSettingsPage.qml => AudioSettings.qml} | 35 +++++++------- .../internal/Export/FlacSettingsPage.qml | 42 +++++++++++++++++ .../internal/Export/Mp3SettingsPage.qml | 21 ++++++++- .../internal/Export/Mp4SettingsPage.qml | 46 +++++++++++++++++-- .../internal/Export/OggSettingsPage.qml | 21 ++++++++- .../internal/Export/WavSettingsPage.qml | 42 +++++++++++++++++ .../internal/Export/exportdialogmodel.cpp | 39 +++++++++++++++- .../internal/Export/exportdialogmodel.h | 16 +++++++ 10 files changed, 239 insertions(+), 28 deletions(-) rename src/project/qml/MuseScore/Project/internal/Export/{AudioSettingsPage.qml => AudioSettings.qml} (77%) create mode 100644 src/project/qml/MuseScore/Project/internal/Export/FlacSettingsPage.qml create mode 100644 src/project/qml/MuseScore/Project/internal/Export/WavSettingsPage.qml diff --git a/src/project/inotationwriter.h b/src/project/inotationwriter.h index ad4760178b632..7573d689b31cf 100644 --- a/src/project/inotationwriter.h +++ b/src/project/inotationwriter.h @@ -28,7 +28,6 @@ #include "global/types/ret.h" #include "global/types/val.h" #include "global/io/iodevice.h" -#include "global/async/channel.h" #include "global/progress.h" #include "notation/inotation.h" diff --git a/src/project/qml/MuseScore/Project/CMakeLists.txt b/src/project/qml/MuseScore/Project/CMakeLists.txt index 522fe39b9802f..0fcba96f96b3b 100644 --- a/src/project/qml/MuseScore/Project/CMakeLists.txt +++ b/src/project/qml/MuseScore/Project/CMakeLists.txt @@ -60,7 +60,7 @@ qt_add_qml_module(project_qml AudioGenerationSettings.qml AudioGenerationSettingsDialog.qml ExportDialog.qml - internal/Export/AudioSettingsPage.qml + internal/Export/AudioSettings.qml internal/Export/ExportOptionItem.qml internal/Export/ExportOptionsView.qml internal/Export/ExportScoresListView.qml @@ -73,6 +73,8 @@ qt_add_qml_module(project_qml internal/Export/Mp4SettingsPage.qml internal/Export/MusicXmlSettingsPage.qml internal/Export/OggSettingsPage.qml + internal/Export/FlacSettingsPage.qml + internal/Export/WavSettingsPage.qml internal/Export/PdfSettingsPage.qml internal/Export/PngSettingsPage.qml internal/Export/SvgSettingsPage.qml diff --git a/src/project/qml/MuseScore/Project/internal/Export/AudioSettingsPage.qml b/src/project/qml/MuseScore/Project/internal/Export/AudioSettings.qml similarity index 77% rename from src/project/qml/MuseScore/Project/internal/Export/AudioSettingsPage.qml rename to src/project/qml/MuseScore/Project/internal/Export/AudioSettings.qml index 51291705a7ea3..80129ac54d673 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/AudioSettingsPage.qml +++ b/src/project/qml/MuseScore/Project/internal/Export/AudioSettings.qml @@ -26,12 +26,20 @@ import Muse.UiComponents import Muse.Ui import MuseScore.Project -ExportSettingsPage { +Row { id: root + property ExportDialogModel model + property NavigationPanel navigationPanel: null + property int navigationOrder: 0 + property bool showBitRateControl: false property bool showSampleRateControl: true + width: parent ? parent.width : implicitWidth + + spacing: 12 + ExportOptionItem { id: sampleRateLabel visible: root.showSampleRateControl @@ -45,11 +53,11 @@ ExportSettingsPage { navigation.row: root.navigationOrder + 1 navigation.accessible.name: sampleRateLabel.text + " " + currentText - model: root.model.availableSampleRates().map(function(sampleRate) { + model: root.model ? root.model.availableSampleRates().map(function(sampleRate) { return { text: qsTrc("project/export", "%1 Hz").arg(sampleRate), value: sampleRate } - }) + }) : [] - currentIndex: indexOfValue(root.model.sampleRate) + currentIndex: root.model ? indexOfValue(root.model.sampleRate) : -1 onActivated: function(index, value) { root.model.sampleRate = value @@ -70,11 +78,11 @@ ExportSettingsPage { navigation.row: root.navigationOrder + 2 navigation.accessible.name: bitrateLabel.text + " " + currentText - model: root.model.availableBitRates().map(function(bitRate) { + model: root.model ? root.model.availableBitRates().map(function(bitRate) { return { text: qsTrc("project/export", "%1 kBit/s").arg(bitRate), value: bitRate } - }) + }) : [] - currentIndex: indexOfValue(root.model.bitRate) + currentIndex: root.model ? indexOfValue(root.model.bitRate) : -1 onActivated: function(index, value) { root.model.bitRate = value @@ -84,7 +92,7 @@ ExportSettingsPage { ExportOptionItem { id: sampleFormatLabel - visible: root.model.availableSampleFormats.length > 0 + visible: root.model ? root.model.availableSampleFormats.length > 0 : false text: qsTrc("project/export", "Sample format:") StyledDropdown { @@ -95,20 +103,13 @@ ExportSettingsPage { navigation.row: root.navigationOrder + 3 navigation.accessible.name: sampleFormatLabel.text + " " + currentText - model: root.model.availableSampleFormats + model: root.model ? root.model.availableSampleFormats : [] - currentIndex: indexOfValue(root.model.selectedSampleFormat) + currentIndex: root.model ? indexOfValue(root.model.selectedSampleFormat) : -1 onActivated: function(index, value) { root.model.selectedSampleFormat = value } } } - - StyledTextLabel { - width: parent.width - text: qsTrc("project/export", "Each selected part will be exported as a separate audio file.") - horizontalAlignment: Text.AlignLeft - wrapMode: Text.WordWrap - } } diff --git a/src/project/qml/MuseScore/Project/internal/Export/FlacSettingsPage.qml b/src/project/qml/MuseScore/Project/internal/Export/FlacSettingsPage.qml new file mode 100644 index 0000000000000..0362dbdc6df8a --- /dev/null +++ b/src/project/qml/MuseScore/Project/internal/Export/FlacSettingsPage.qml @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import QtQuick + +import Muse.UiComponents +import MuseScore.Project + +ExportSettingsPage { + id: root + + AudioSettings { + model: root.model + navigationPanel: root.navigationPanel + navigationOrder: root.navigationOrder + } + + StyledTextLabel { + width: parent.width + text: qsTrc("project/export", "Each selected part will be exported as a separate audio file.") + horizontalAlignment: Text.AlignLeft + wrapMode: Text.WordWrap + } +} diff --git a/src/project/qml/MuseScore/Project/internal/Export/Mp3SettingsPage.qml b/src/project/qml/MuseScore/Project/internal/Export/Mp3SettingsPage.qml index d8917b697fe14..e0cd8c0151311 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/Mp3SettingsPage.qml +++ b/src/project/qml/MuseScore/Project/internal/Export/Mp3SettingsPage.qml @@ -21,6 +21,23 @@ */ import QtQuick -AudioSettingsPage { - showBitRateControl: true +import Muse.UiComponents +import MuseScore.Project + +ExportSettingsPage { + id: root + + AudioSettings { + model: root.model + navigationPanel: root.navigationPanel + navigationOrder: root.navigationOrder + showBitRateControl: true + } + + StyledTextLabel { + width: parent.width + text: qsTrc("project/export", "Each selected part will be exported as a separate audio file.") + horizontalAlignment: Text.AlignLeft + wrapMode: Text.WordWrap + } } diff --git a/src/project/qml/MuseScore/Project/internal/Export/Mp4SettingsPage.qml b/src/project/qml/MuseScore/Project/internal/Export/Mp4SettingsPage.qml index ad663822c87ad..4d5598546a763 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/Mp4SettingsPage.qml +++ b/src/project/qml/MuseScore/Project/internal/Export/Mp4SettingsPage.qml @@ -20,8 +20,48 @@ * along with this program. If not, see . */ import QtQuick +import QtQuick.Layouts -AudioSettingsPage { - showBitRateControl: true -} +import Muse.UiComponents +import Muse.Ui +import MuseScore.Project + +ExportSettingsPage { + id: root + + AudioSettings { + model: root.model + navigationPanel: root.navigationPanel + navigationOrder: root.navigationOrder + showBitRateControl: true + } + + ExportOptionItem { + id: videoResolutionLabel + text: qsTrc("project/export", "Video resolution:") + + StyledDropdown { + Layout.preferredWidth: 126 + navigation.name: "VideoResolutionDropdown" + navigation.panel: root.navigationPanel + navigation.row: root.navigationOrder + 10 + navigation.accessible.name: videoResolutionLabel.text + " " + currentText + + model: root.model ? root.model.availableVideoResolutions() : [] + + currentIndex: root.model ? indexOfValue(root.model.videoResolution) : -1 + + onActivated: function(index, value) { + root.model.videoResolution = value + } + } + } + + StyledTextLabel { + width: parent.width + text: qsTrc("project/export", "Each selected part will be exported as a separate audio file.") + horizontalAlignment: Text.AlignLeft + wrapMode: Text.WordWrap + } +} diff --git a/src/project/qml/MuseScore/Project/internal/Export/OggSettingsPage.qml b/src/project/qml/MuseScore/Project/internal/Export/OggSettingsPage.qml index 79f47b4530ae9..bcfa85e5e760d 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/OggSettingsPage.qml +++ b/src/project/qml/MuseScore/Project/internal/Export/OggSettingsPage.qml @@ -21,6 +21,23 @@ */ import QtQuick -AudioSettingsPage { - showSampleRateControl: false +import Muse.UiComponents +import MuseScore.Project + +ExportSettingsPage { + id: root + + AudioSettings { + model: root.model + navigationPanel: root.navigationPanel + navigationOrder: root.navigationOrder + showSampleRateControl: false + } + + StyledTextLabel { + width: parent.width + text: qsTrc("project/export", "Each selected part will be exported as a separate audio file.") + horizontalAlignment: Text.AlignLeft + wrapMode: Text.WordWrap + } } diff --git a/src/project/qml/MuseScore/Project/internal/Export/WavSettingsPage.qml b/src/project/qml/MuseScore/Project/internal/Export/WavSettingsPage.qml new file mode 100644 index 0000000000000..0362dbdc6df8a --- /dev/null +++ b/src/project/qml/MuseScore/Project/internal/Export/WavSettingsPage.qml @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import QtQuick + +import Muse.UiComponents +import MuseScore.Project + +ExportSettingsPage { + id: root + + AudioSettings { + model: root.model + navigationPanel: root.navigationPanel + navigationOrder: root.navigationOrder + } + + StyledTextLabel { + width: parent.width + text: qsTrc("project/export", "Each selected part will be exported as a separate audio file.") + horizontalAlignment: Text.AlignLeft + wrapMode: Text.WordWrap + } +} diff --git a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp index c1df2a14a6726..094f0be70d651 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp +++ b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp @@ -88,7 +88,7 @@ ExportDialogModel::ExportDialogModel(QObject* parent) ExportType::makeWithSuffixes({ "wav" }, muse::qtrc("project/export", "WAV audio"), muse::qtrc("project/export", "WAV audio files"), - "AudioSettingsPage.qml"), + "WavSettingsPage.qml"), ExportType::makeWithSuffixes({ "ogg" }, muse::qtrc("project/export", "OGG audio"), muse::qtrc("project/export", "OGG audio files"), @@ -96,7 +96,7 @@ ExportDialogModel::ExportDialogModel(QObject* parent) ExportType::makeWithSuffixes({ "flac" }, muse::qtrc("project/export", "FLAC audio"), muse::qtrc("project/export", "FLAC audio files"), - "AudioSettingsPage.qml"), + "FlacSettingsPage.qml"), ExportType::makeWithSuffixes({ "mid", "midi", "kar" }, muse::qtrc("project/export", "MIDI file"), muse::qtrc("project/export", "MIDI files"), @@ -560,6 +560,41 @@ void ExportDialogModel::setSvgIllustratorCompat(bool compat) emit svgIllustratorCompatChanged(compat); } +QVariantList ExportDialogModel::availableVideoResolutions() const +{ + static const QStringList resolutions = { "2160p", "1440p", "1080p", "720p", "480p", "360p" }; + + QVariantList result; + for (const QString& res : resolutions) { + QVariantMap obj; + obj["text"] = res; + obj["value"] = res; + result << obj; + } + return result; +} + +QString ExportDialogModel::videoResolution() const +{ +#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE + return QString::fromStdString(videoExportConfiguration()->resolution()); +#else + return "1080p"; +#endif +} + +void ExportDialogModel::setVideoResolution(const QString& resolution) +{ + if (resolution == videoResolution()) { + return; + } + +#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE + videoExportConfiguration()->setResolution(resolution.toStdString()); +#endif + emit videoResolutionChanged(resolution); +} + QList ExportDialogModel::availableSampleRates() const { const std::vector& rates = audioExportConfiguration()->availableSampleRates(); diff --git a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h index 4fcde5ad0453f..37f3a0e2c8212 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h +++ b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h @@ -26,6 +26,8 @@ #include #include +#include "app_config.h" + #include "modularity/ioc.h" #include "async/asyncable.h" @@ -36,6 +38,9 @@ #include "importexport/musicxml/imusicxmlconfiguration.h" #include "importexport/midi/imidiconfiguration.h" #include "importexport/audioexport/iaudioexportconfiguration.h" +#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE +#include "importexport/videoexport/ivideoexportconfiguration.h" +#endif #include "importexport/mei/imeiconfiguration.h" #include "importexport/lyricsexport/ilyricsexportconfiguration.h" #include "importexport/mnx/imnxconfiguration.h" @@ -74,6 +79,8 @@ class ExportDialogModel : public QAbstractListModel, public QQmlParserStatus, pu bool svgTransparentBackground READ svgTransparentBackground WRITE setSvgTransparentBackground NOTIFY svgTransparentBackgroundChanged) Q_PROPERTY(bool svgIllustratorCompat READ svgIllustratorCompat WRITE setSvgIllustratorCompat NOTIFY svgIllustratorCompatChanged FINAL) + Q_PROPERTY(QString videoResolution READ videoResolution WRITE setVideoResolution NOTIFY videoResolutionChanged) + Q_PROPERTY(int sampleRate READ sampleRate WRITE setSampleRate NOTIFY sampleRateChanged) Q_PROPERTY(int bitRate READ bitRate WRITE setBitRate NOTIFY bitRateChanged) Q_PROPERTY(QVariantList availableSampleFormats READ availableSampleFormats NOTIFY availableSampleFormatsChanged) @@ -106,6 +113,9 @@ class ExportDialogModel : public QAbstractListModel, public QQmlParserStatus, pu muse::GlobalInject lrcConfiguration; muse::GlobalInject mnxConfiguration; muse::GlobalInject configuration; +#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE + muse::GlobalInject videoExportConfiguration; +#endif muse::GlobalInject imageExportConfiguration; muse::GlobalInject writers; muse::ContextInject interactive = { this }; @@ -161,6 +171,10 @@ class ExportDialogModel : public QAbstractListModel, public QQmlParserStatus, pu bool svgIllustratorCompat() const; void setSvgIllustratorCompat(bool compat); + Q_INVOKABLE QVariantList availableVideoResolutions() const; + QString videoResolution() const; + void setVideoResolution(const QString& resolution); + Q_INVOKABLE QList availableSampleRates() const; int sampleRate() const; void setSampleRate(int sampleRate); @@ -231,6 +245,8 @@ class ExportDialogModel : public QAbstractListModel, public QQmlParserStatus, pu void svgTransparentBackgroundChanged(bool transparent); void svgIllustratorCompatChanged(bool compat); + void videoResolutionChanged(const QString& resolution); + void availableSampleRatesChanged(); void sampleRateChanged(int sampleRate); void availableBitRatesChanged(); From 79b1c709c0bddbf2836b044895f5459208a6952b Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 10:52:02 +0200 Subject: [PATCH 05/52] tmp: disabled audio when exporting video in cli --- .../internal/convertercontroller.cpp | 11 ++++-- src/converter/internal/convertercontroller.h | 3 +- .../videoexport/internal/videowriter.cpp | 36 ++++++++++++------- src/project/inotationwriter.h | 4 ++- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/converter/internal/convertercontroller.cpp b/src/converter/internal/convertercontroller.cpp index a624c0f70d9d6..315b40b4feb68 100644 --- a/src/converter/internal/convertercontroller.cpp +++ b/src/converter/internal/convertercontroller.cpp @@ -490,12 +490,13 @@ muse::Ret ConverterController::convertPage(INotationWriterPtr writer, INotationP return make_ok(); } -Ret ConverterController::convertFullNotation(INotationWriterPtr writer, INotationPtr notation, const muse::io::path_t& out) const +Ret ConverterController::convertFullNotation(INotationWriterPtr writer, INotationPtr notation, const muse::io::path_t& out, + const project::INotationWriter::Options& options) const { auto outBuf = Buffer::opened(IODevice::WriteOnly); outBuf.setMeta("file_path", out.toStdString()); - Ret ret = writer->write(notation, outBuf); + Ret ret = writer->write(notation, outBuf, options); if (!ret) { LOGE() << "failed write, err: " << ret.toString() << ", path: " << out; return make_ret(Err::OutFileFailedWrite); @@ -724,7 +725,11 @@ Ret ConverterController::exportScoreVideo(const muse::io::path_t& in, const muse return make_ret(Err::InFileFailedLoad); } - return convertFullNotation(writer, notationProject->masterNotation()->notation(), out); + const INotationWriter::Options options { + { INotationWriter::OptionKey::WITH_AUDIO, Val(false) }, + }; + + return convertFullNotation(writer, notationProject->masterNotation()->notation(), out, options); } Ret ConverterController::updateSource(const muse::io::path_t& in, const std::string& newSource, bool forceMode) diff --git a/src/converter/internal/convertercontroller.h b/src/converter/internal/convertercontroller.h index 7efe2639ddca0..16fb228c6c892 100644 --- a/src/converter/internal/convertercontroller.h +++ b/src/converter/internal/convertercontroller.h @@ -109,7 +109,8 @@ class ConverterController : public IConverterController, public muse::Contextabl muse::Ret convertPageByPage(project::INotationWriterPtr writer, notation::INotationPtr notation, const muse::io::path_t& out) const; muse::Ret convertPage(project::INotationWriterPtr writer, notation::INotationPtr notation, const size_t pageNum, const muse::io::path_t& filePath, const muse::io::path_t& dirPath = {}) const; - muse::Ret convertFullNotation(project::INotationWriterPtr writer, notation::INotationPtr notation, const muse::io::path_t& out) const; + muse::Ret convertFullNotation(project::INotationWriterPtr writer, notation::INotationPtr notation, const muse::io::path_t& out, + const project::INotationWriter::Options& options = {}) const; muse::Ret convertScorePartsToPdf(project::INotationWriterPtr writer, notation::IMasterNotationPtr masterNotation, const muse::io::path_t& out) const; diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index 77bc3254e2238..86275654733a2 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -59,17 +59,19 @@ bool VideoWriter::supportsUnitType(UnitType unitType) const return std::find(unitTypes.cbegin(), unitTypes.cend(), unitType) != unitTypes.cend(); } -muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, const Options&) +muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, const Options& options) { std::string filePath = device.meta("file_path"); IF_ASSERT_FAILED(!filePath.empty()) { return make_ret(muse::Ret::Code::InternalError); } + bool withAudio = muse::value(options, OptionKey::WITH_AUDIO, muse::Val(true)).toBool(); + Config cfg = makeConfig(); muse::io::path_t finalPath(filePath); - muse::io::path_t tempVideoPath = finalPath + ".tmp_video.mp4"; + muse::io::path_t tempVideoPath = withAudio ? finalPath + ".tmp_video.mp4" : finalPath; muse::io::path_t tempAudioPath = finalPath + ".tmp_audio.mp3"; m_isCompleted = false; @@ -79,7 +81,13 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, m_audioRet = muse::Ret(); startVideoExport(notation, tempVideoPath, cfg); - startAudioExport(notation, tempAudioPath); + + if (withAudio) { + startAudioExport(notation, tempAudioPath); + } else { + m_audioCompleted = true; + m_audioRet = muse::make_ok(); + } while (!m_isCompleted || !m_audioCompleted) { application()->processEvents(); @@ -93,18 +101,20 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, muse::Ret result = m_writeRet; - if (result && m_audioRet) { - if (!VideoEncoder::muxAudioVideo(tempVideoPath, tempAudioPath, finalPath, cfg.leadingSec)) { - result = make_ret(muse::Ret::Code::UnknownError); + if (withAudio) { + if (result && m_audioRet) { + if (!VideoEncoder::muxAudioVideo(tempVideoPath, tempAudioPath, finalPath, cfg.leadingSec)) { + result = make_ret(muse::Ret::Code::UnknownError); + } + } else if (!result) { + // keep video error + } else { + result = m_audioRet; } - } else if (!result) { - // keep video error - } else { - result = m_audioRet; - } - muse::io::File::remove(tempVideoPath); - muse::io::File::remove(tempAudioPath); + muse::io::File::remove(tempVideoPath); + muse::io::File::remove(tempAudioPath); + } return result; } diff --git a/src/project/inotationwriter.h b/src/project/inotationwriter.h index 7573d689b31cf..58b128edf03d6 100644 --- a/src/project/inotationwriter.h +++ b/src/project/inotationwriter.h @@ -49,7 +49,9 @@ class INotationWriter PAGE_NUMBER, TRANSPARENT_BACKGROUND, BEATS_COLORS, - WAIT_FOR_COMPLETION + WAIT_FOR_COMPLETION, + + WITH_AUDIO, // todo: delete after stabilization of the video export + audio }; using Options = std::map; From 0e1f1154fdbfe8c2fc11cce30439422710986760 Mon Sep 17 00:00:00 2001 From: Eism Date: Tue, 3 Mar 2026 15:40:23 +0200 Subject: [PATCH 06/52] moved availableResolutions to configuration --- .../videoexport/internal/videoencoder.h | 4 +--- .../internal/videoexportconfiguration.cpp | 7 +++++++ .../internal/videoexportconfiguration.h | 1 + .../videoexport/ivideoexportconfiguration.h | 2 ++ .../internal/Export/Mp4SettingsPage.qml | 4 +++- .../internal/Export/exportdialogmodel.cpp | 20 +++++++++---------- .../internal/Export/exportdialogmodel.h | 2 +- 7 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/importexport/videoexport/internal/videoencoder.h b/src/importexport/videoexport/internal/videoencoder.h index d0499a756e276..75c0b379decdc 100644 --- a/src/importexport/videoexport/internal/videoencoder.h +++ b/src/importexport/videoexport/internal/videoencoder.h @@ -39,9 +39,7 @@ class VideoEncoder bool encodeImage(const QImage& img); - static bool muxAudioVideo(const muse::io::path_t& videoPath, - const muse::io::path_t& audioPath, - const muse::io::path_t& outputPath, + static bool muxAudioVideo(const muse::io::path_t& videoPath, const muse::io::path_t& audioPath, const muse::io::path_t& outputPath, double audioOffsetSec); private: diff --git a/src/importexport/videoexport/internal/videoexportconfiguration.cpp b/src/importexport/videoexport/internal/videoexportconfiguration.cpp index 373c9f8a3e1f3..f1f0b967c4eba 100644 --- a/src/importexport/videoexport/internal/videoexportconfiguration.cpp +++ b/src/importexport/videoexport/internal/videoexportconfiguration.cpp @@ -31,6 +31,8 @@ static const int DEFAULT_FPS = 24; static const double DEFAULT_LEADING_SEC = 3.0; static const double DEFAULT_TRAILING_SECONDS = 3.0; +static const std::vector AVAILABLE_RESOLUTIONS = { "2160p", "1440p", "1080p", "720p", "480p", "360p" }; + ViewMode VideoExportConfiguration::viewMode() const { return m_viewMode ? m_viewMode.value() : DEFAULT_VIEW_MODE; @@ -71,6 +73,11 @@ void VideoExportConfiguration::setResolution(std::optional resoluti m_resolution = resolution; } +const std::vector& VideoExportConfiguration::availableResolutions() const +{ + return AVAILABLE_RESOLUTIONS; +} + int VideoExportConfiguration::fps() const { return m_fps ? m_fps.value() : DEFAULT_FPS; diff --git a/src/importexport/videoexport/internal/videoexportconfiguration.h b/src/importexport/videoexport/internal/videoexportconfiguration.h index 683da52ff36f6..c9453c93efe04 100644 --- a/src/importexport/videoexport/internal/videoexportconfiguration.h +++ b/src/importexport/videoexport/internal/videoexportconfiguration.h @@ -42,6 +42,7 @@ class VideoExportConfiguration : public IVideoExportConfiguration std::string resolution() const override; void setResolution(std::optional resolution) override; + const std::vector& availableResolutions() const override; int fps() const override; void setFps(std::optional fps) override; diff --git a/src/importexport/videoexport/ivideoexportconfiguration.h b/src/importexport/videoexport/ivideoexportconfiguration.h index 4f9b261a9214c..8a5a0164c01ec 100644 --- a/src/importexport/videoexport/ivideoexportconfiguration.h +++ b/src/importexport/videoexport/ivideoexportconfiguration.h @@ -23,6 +23,7 @@ #define MU_IMPORTEXPORT_IVIDEOEXPORTCONFIGURATION_H #include +#include #include #include "modularity/imoduleinterface.h" @@ -47,6 +48,7 @@ class IVideoExportConfiguration : MODULE_GLOBAL_INTERFACE virtual std::string resolution() const = 0; virtual void setResolution(std::optional resolution) = 0; + virtual const std::vector& availableResolutions() const = 0; virtual int fps() const = 0; virtual void setFps(std::optional fps) = 0; diff --git a/src/project/qml/MuseScore/Project/internal/Export/Mp4SettingsPage.qml b/src/project/qml/MuseScore/Project/internal/Export/Mp4SettingsPage.qml index 4d5598546a763..e7df53a22b79a 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/Mp4SettingsPage.qml +++ b/src/project/qml/MuseScore/Project/internal/Export/Mp4SettingsPage.qml @@ -48,7 +48,9 @@ ExportSettingsPage { navigation.row: root.navigationOrder + 10 navigation.accessible.name: videoResolutionLabel.text + " " + currentText - model: root.model ? root.model.availableVideoResolutions() : [] + model: root.model ? root.model.availableVideoResolutions().map(function(res) { + return { text: res, value: res } + }) : [] currentIndex: root.model ? indexOfValue(root.model.videoResolution) : -1 diff --git a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp index 094f0be70d651..22a9b15ba6be5 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp +++ b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp @@ -560,18 +560,18 @@ void ExportDialogModel::setSvgIllustratorCompat(bool compat) emit svgIllustratorCompatChanged(compat); } -QVariantList ExportDialogModel::availableVideoResolutions() const +QStringList ExportDialogModel::availableVideoResolutions() const { - static const QStringList resolutions = { "2160p", "1440p", "1080p", "720p", "480p", "360p" }; - - QVariantList result; - for (const QString& res : resolutions) { - QVariantMap obj; - obj["text"] = res; - obj["value"] = res; - result << obj; +#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE + const std::vector& resolutions = videoExportConfiguration()->availableResolutions(); + QStringList result; + for (const std::string& res : resolutions) { + result << QString::fromStdString(res); } return result; +#else + return { }; +#endif } QString ExportDialogModel::videoResolution() const @@ -579,7 +579,7 @@ QString ExportDialogModel::videoResolution() const #ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE return QString::fromStdString(videoExportConfiguration()->resolution()); #else - return "1080p"; + return ""; #endif } diff --git a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h index 37f3a0e2c8212..ac5fab60246cf 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h +++ b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h @@ -171,7 +171,7 @@ class ExportDialogModel : public QAbstractListModel, public QQmlParserStatus, pu bool svgIllustratorCompat() const; void setSvgIllustratorCompat(bool compat); - Q_INVOKABLE QVariantList availableVideoResolutions() const; + Q_INVOKABLE QStringList availableVideoResolutions() const; QString videoResolution() const; void setVideoResolution(const QString& resolution); From 34c70cd966e507470abeb4aff71ed64bff901fc7 Mon Sep 17 00:00:00 2001 From: Eism Date: Thu, 5 Mar 2026 11:51:41 +0200 Subject: [PATCH 07/52] fixed crash when exporting video from cli --- .../videoexport/internal/videowriter.cpp | 86 +++++++++++++------ .../videoexport/internal/videowriter.h | 23 +++++ 2 files changed, 85 insertions(+), 24 deletions(-) diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index 86275654733a2..4e572aba9020b 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -48,6 +48,8 @@ using namespace mu::notation; using namespace muse::draw; using namespace muse::midi; +double CANVAS_DPI = 300; + std::vector VideoWriter::supportedUnitTypes() const { return { UnitType::PER_PART }; @@ -225,29 +227,24 @@ void VideoWriter::abort() } } -void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& filePath, const Config& config) +std::optional VideoWriter::prepareScore(INotationPtr notation, const Config& config) { - VideoEncoder encoder; - if (!encoder.open(filePath, config.width, config.height, config.bitrate, config.fps / 2, config.fps)) { - LOGE() << "failed open encoder"; - m_writeRet = make_ret(muse::Ret::Code::UnknownError); - m_isCompleted = true; - return; - } + ScoreRestoreData result; + engraving::Score* score = notation->elements()->msScore(); - engraving::MasterScore* score = notation->elements()->msScore()->masterScore(); + result.style = score->style(); - notation::ViewMode originalViewMode = notation->viewMode(); - engraving::MStyle originalStyle = score->style(); + result.viewMode = notation->viewMode(); - DEFER { - score->style() = originalStyle; - score->setLayoutAll(); - score->update(); - notation->setViewMode(originalViewMode); - }; + result.showFrames = score->showFrames(); + result.showInstrumentNames = score->showInstrumentNames(); + result.showInvisible = score->isShowInvisible(); + result.showPageborders = score->showPageborders(); + result.showUnprintable = score->showUnprintable(); + result.showVBox = score->layoutOptions().isShowVBox; notation->setViewMode(notation::ViewMode::PAGE); + score->setShowFrames(false); score->setShowInstrumentNames(false); score->setShowInvisible(false); @@ -260,13 +257,10 @@ void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& file PageList pages = notation->elements()->pages(); if (pages.empty()) { LOGE() << "No pages"; - m_writeRet = make_ret(muse::Ret::Code::UnknownError); - m_isCompleted = true; - return; + restoreScore(notation, result); + return std::nullopt; } - double CANVAS_DPI = 300; - const Page* page = pages.front(); if (score->staves().size() > 3) { //! NOTE: Calculate the dpi to display all page elements @@ -299,6 +293,52 @@ void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& file score->setLayoutAll(); score->update(); + return result; +} + +void VideoWriter::restoreScore(INotationPtr notation, const ScoreRestoreData& data) +{ + engraving::Score* score = notation->elements()->msScore(); + + score->style() = data.style; + + score->setShowFrames(data.showFrames); + score->setShowInstrumentNames(data.showInstrumentNames); + score->setShowInvisible(data.showInvisible); + score->setShowPageborders(data.showPageborders); + score->setShowUnprintable(data.showUnprintable); + score->setShowVBox(data.showVBox); + + notation->setViewMode(data.viewMode); + + score->setLayoutAll(); + score->update(); +} + +void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& filePath, const Config& config) +{ + VideoEncoder encoder; + if (!encoder.open(filePath, config.width, config.height, config.bitrate, config.fps / 2, config.fps)) { + LOGE() << "failed open encoder"; + m_writeRet = make_ret(muse::Ret::Code::UnknownError); + m_isCompleted = true; + return; + } + + auto restoreData = prepareScore(notation, config); + if (!restoreData) { + m_writeRet = make_ret(muse::Ret::Code::UnknownError); + m_isCompleted = true; + return; + } + + DEFER { + restoreScore(notation, restoreData.value()); + m_isCompleted = true; + }; + + PageList pages = notation->elements()->pages(); + // Setup painting QImage frame(config.width, config.height, QImage::Format_RGB32); frame.setDotsPerMeterX(std::lrint((CANVAS_DPI * 1000) / engraving::INCH)); @@ -344,7 +384,6 @@ void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& file encoder.close(); m_writeRet = make_ret(muse::Ret::Code::Cancel); m_progress.finish(make_ret(muse::Ret::Code::Cancel)); - m_isCompleted = true; return; } @@ -390,5 +429,4 @@ void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& file m_writeRet = muse::make_ok(); m_progress.finish(muse::make_ok()); - m_isCompleted = true; } diff --git a/src/importexport/videoexport/internal/videowriter.h b/src/importexport/videoexport/internal/videowriter.h index 9cbb9772c44a3..5f14330e0d5dd 100644 --- a/src/importexport/videoexport/internal/videowriter.h +++ b/src/importexport/videoexport/internal/videowriter.h @@ -22,7 +22,12 @@ #ifndef MU_IMPORTEXPORT_VIDEOWRITER_H #define MU_IMPORTEXPORT_VIDEOWRITER_H +#include + #include "async/asyncable.h" + +#include "engraving/style/style.h" + #include "modularity/ioc.h" #include "../ivideoexportconfiguration.h" #include "iapplication.h" @@ -30,6 +35,8 @@ #include "project/inotationwriter.h" #include "project/inotationwritersregister.h" +#include "notation/notationtypes.h" + namespace mu::iex::videoexport { class VideoWriter : public project::INotationWriter, public muse::Contextable, public muse::async::Asyncable { @@ -67,6 +74,22 @@ class VideoWriter : public project::INotationWriter, public muse::Contextable, p void doGenerate(notation::INotationPtr notation, const muse::io::path_t& filePath, const Config& config); + struct ScoreRestoreData + { + engraving::MStyle style; + notation::ViewMode viewMode = notation::ViewMode::PAGE; + + bool showFrames = true; + bool showInstrumentNames = true; + bool showInvisible = true; + bool showPageborders = false; + bool showUnprintable = true; + bool showVBox = true; + }; + + std::optional prepareScore(notation::INotationPtr notation, const Config& config); + void restoreScore(notation::INotationPtr notation, const ScoreRestoreData& data); + muse::Progress m_progress; bool m_abort = false; bool m_isCompleted = false; From e55b7567166f50cdfb7c22771f1c2ad3d111984e Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 11:02:45 +0200 Subject: [PATCH 08/52] fixed build after cherry-pick --- .../audioexport/internal/abstractaudiowriter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/importexport/audioexport/internal/abstractaudiowriter.cpp b/src/importexport/audioexport/internal/abstractaudiowriter.cpp index 914275a58ac11..3f0bb2ae7583d 100644 --- a/src/importexport/audioexport/internal/abstractaudiowriter.cpp +++ b/src/importexport/audioexport/internal/abstractaudiowriter.cpp @@ -90,7 +90,7 @@ muse::Progress* AbstractAudioWriter::progress() } Ret AbstractAudioWriter::doWriteAndWait(INotationPtr notation, - io::IODevice& destinationDevice, + io::IODevice& dstDevice, const SoundTrackFormat& format, const Options& options) { @@ -158,9 +158,9 @@ void AbstractAudioWriter::doWrite(io::IODevice& dstDevice, const SoundTrackForma sendProgress(current, total, stage); }); - playback()->saveSoundTrack(sequenceId, muse::io::path_t(path), std::move(format)) - .onResolve(this, [this, path, sequenceId, restoreState](const bool /*result*/) { - LOGI() << "Successfully saved sound track by path: " << path; + playback()->saveSoundTrack(sequenceId, std::move(format), dstDevice) + .onResolve(this, [this, sequenceId, restoreState](const bool /*result*/) { + LOGI() << "Successfully saved sound track"; m_writeRet = muse::make_ok(); m_isCompleted = true; m_progress.finish(muse::make_ok()); From 5ce63c772ef6358acf8e97b03f941f7a5fbd5250 Mon Sep 17 00:00:00 2001 From: Eism Date: Fri, 6 Mar 2026 09:55:32 +0200 Subject: [PATCH 09/52] created media module and moved the video encoder into it --- src/app/CMakeLists.txt | 1 + src/app/appfactory.cpp | 9 ++++ src/framework/CMakeLists.txt | 4 ++ src/framework/cmake/MuseDeclareOptions.cmake | 1 + src/framework/cmake/MuseModules.cmake | 1 + .../cmake/muse_framework_config.h.in | 4 ++ src/framework/media/CMakeLists.txt | 37 +++++++++++++++ .../media}/internal/ffmpeg.h | 8 ++-- .../media}/internal/videoencoder.cpp | 11 +++-- .../media}/internal/videoencoder.h | 28 +++++------- src/framework/media/ivideoencoder.h | 45 +++++++++++++++++++ src/framework/media/mediamodule.cpp | 39 ++++++++++++++++ src/framework/media/mediamodule.h | 35 +++++++++++++++ src/framework/stubs/CMakeLists.txt | 4 ++ src/framework/stubs/media/CMakeLists.txt | 28 ++++++++++++ src/framework/stubs/media/mediastubmodule.cpp | 40 +++++++++++++++++ src/framework/stubs/media/mediastubmodule.h | 36 +++++++++++++++ .../stubs/media/videoencoderstub.cpp | 44 ++++++++++++++++++ src/framework/stubs/media/videoencoderstub.h | 39 ++++++++++++++++ src/importexport/videoexport/CMakeLists.txt | 11 +---- .../videoexport/internal/videowriter.cpp | 13 +++--- .../videoexport/internal/videowriter.h | 10 ++--- 22 files changed, 396 insertions(+), 52 deletions(-) create mode 100644 src/framework/media/CMakeLists.txt rename src/{importexport/videoexport => framework/media}/internal/ffmpeg.h (88%) rename src/{importexport/videoexport => framework/media}/internal/videoencoder.cpp (98%) rename src/{importexport/videoexport => framework/media}/internal/videoencoder.h (61%) create mode 100644 src/framework/media/ivideoencoder.h create mode 100644 src/framework/media/mediamodule.cpp create mode 100644 src/framework/media/mediamodule.h create mode 100644 src/framework/stubs/media/CMakeLists.txt create mode 100644 src/framework/stubs/media/mediastubmodule.cpp create mode 100644 src/framework/stubs/media/mediastubmodule.h create mode 100644 src/framework/stubs/media/videoencoderstub.cpp create mode 100644 src/framework/stubs/media/videoencoderstub.h diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index b5f1231afe94d..92ac2c2918895 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -130,6 +130,7 @@ add_to_link_if_exists(muse::extensions) add_to_link_if_exists(muse::interactive) add_to_link_if_exists(muse::languages) add_to_link_if_exists(muse::learn) +add_to_link_if_exists(muse::media) add_to_link_if_exists(muse::midi) add_to_link_if_exists(muse::mpe) add_to_link_if_exists(muse::multiwindows) diff --git a/src/app/appfactory.cpp b/src/app/appfactory.cpp index 2085dbe2e9da3..3a0c941f239de 100644 --- a/src/app/appfactory.cpp +++ b/src/app/appfactory.cpp @@ -50,6 +50,12 @@ #include "framework/stubs/learn/learnmodule.h" #endif +#ifdef MUSE_MODULE_MEDIA +#include "framework/media/mediamodule.h" +#else +#include "framework/stubs/media/mediastubmodule.h" +#endif + #ifdef MUSE_MODULE_MIDI #include "framework/midi/midimodule.h" #else @@ -326,6 +332,7 @@ std::shared_ptr AppFactory::newGuiApp(const CmdOptions& opti #endif app->addModule(new muse::tours::ToursModule()); app->addModule(new muse::vst::VSTModule()); + app->addModule(new muse::media::MediaModule()); // modules #ifdef MUE_BUILD_APPSHELL_MODULE @@ -461,6 +468,8 @@ static void addConsoleModules(std::shared_ptr app) app->addModule(new muse::autobot::AutobotModule()); #endif + app->addModule(new muse::media::MediaModule()); + app->addModule(new mu::context::ContextModule()); #ifdef MUE_BUILD_CONVERTER_MODULE diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index ba071d31ad4df..186f29e13eabb 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -109,6 +109,10 @@ if (MUSE_MODULE_LEARN) add_subdirectory(learn) endif() +if (MUSE_MODULE_MEDIA) + add_subdirectory(media) +endif() + if (MUSE_MODULE_EXTENSIONS) add_subdirectory(extensions) endif() diff --git a/src/framework/cmake/MuseDeclareOptions.cmake b/src/framework/cmake/MuseDeclareOptions.cmake index 8ed2295e3f072..4651d0064ccf8 100644 --- a/src/framework/cmake/MuseDeclareOptions.cmake +++ b/src/framework/cmake/MuseDeclareOptions.cmake @@ -63,6 +63,7 @@ option(MUSE_MODULE_INTERACTIVE_SYNC_SUPPORTED "Sync interactive supported" ON) declare_muse_module_opt(LANGUAGES ON) declare_muse_module_opt(LEARN ON) +declare_muse_module_opt(MEDIA ON) declare_muse_module_opt(MIDI ON) declare_muse_module_opt(MPE ON) diff --git a/src/framework/cmake/MuseModules.cmake b/src/framework/cmake/MuseModules.cmake index bab3feaabd952..d934ae35d5f04 100644 --- a/src/framework/cmake/MuseModules.cmake +++ b/src/framework/cmake/MuseModules.cmake @@ -14,6 +14,7 @@ set(MUSE_FRAMEWORK_MODULES INTERACTIVE LANGUAGES LEARN + MEDIA MIDI MPE MULTIWINDOWS diff --git a/src/framework/cmake/muse_framework_config.h.in b/src/framework/cmake/muse_framework_config.h.in index 5a3889037fdf8..a611f5c6d4b2c 100644 --- a/src/framework/cmake/muse_framework_config.h.in +++ b/src/framework/cmake/muse_framework_config.h.in @@ -111,6 +111,10 @@ #cmakedefine MUSE_MODULE_LEARN_TESTS 1 #cmakedefine MUSE_MODULE_LEARN_API 1 +#cmakedefine MUSE_MODULE_MEDIA 1 +#cmakedefine MUSE_MODULE_MEDIA_TESTS 1 +#cmakedefine MUSE_MODULE_MEDIA_API 1 + #cmakedefine MUSE_MODULE_MIDI 1 #cmakedefine MUSE_MODULE_MIDI_TESTS 1 #cmakedefine MUSE_MODULE_MIDI_API 1 diff --git a/src/framework/media/CMakeLists.txt b/src/framework/media/CMakeLists.txt new file mode 100644 index 0000000000000..ab40348b64249 --- /dev/null +++ b/src/framework/media/CMakeLists.txt @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-3.0-only +# MuseScore-Studio-CLA-applies +# +# MuseScore Studio +# Music Composition & Notation +# +# Copyright (C) 2025 MuseScore Limited +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +muse_create_module(muse_media ALIAS muse::media) + +target_sources(muse_media PRIVATE + mediamodule.cpp + mediamodule.h + ivideoencoder.h + + internal/videoencoder.cpp + internal/videoencoder.h + internal/ffmpeg.h +) + +# FFmpeg +find_package(FFmpeg REQUIRED) + +target_include_directories(muse_media PRIVATE ${FFMPEG_INCLUDE_DIRS}) +target_link_libraries(muse_media PRIVATE ${FFMPEG_LIBRARIES}) diff --git a/src/importexport/videoexport/internal/ffmpeg.h b/src/framework/media/internal/ffmpeg.h similarity index 88% rename from src/importexport/videoexport/internal/ffmpeg.h rename to src/framework/media/internal/ffmpeg.h index dd4d4e685d7c6..feb99c3552850 100644 --- a/src/importexport/videoexport/internal/ffmpeg.h +++ b/src/framework/media/internal/ffmpeg.h @@ -5,7 +5,7 @@ * MuseScore Studio * Music Composition & Notation * - * Copyright (C) 2021 MuseScore Limited + * Copyright (C) 2025 MuseScore Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -19,8 +19,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef MU_IMPORTEXPORT_FFMPEG_H -#define MU_IMPORTEXPORT_FFMPEG_H + +#pragma once #include @@ -36,5 +36,3 @@ extern "C" { #include "libavutil/imgutils.h" #endif } - -#endif // MU_IMPORTEXPORT_FFMPEG_H diff --git a/src/importexport/videoexport/internal/videoencoder.cpp b/src/framework/media/internal/videoencoder.cpp similarity index 98% rename from src/importexport/videoexport/internal/videoencoder.cpp rename to src/framework/media/internal/videoencoder.cpp index abff25f09b48a..a604ff33c8f0f 100644 --- a/src/importexport/videoexport/internal/videoencoder.cpp +++ b/src/framework/media/internal/videoencoder.cpp @@ -5,7 +5,7 @@ * MuseScore Studio * Music Composition & Notation * - * Copyright (C) 2021 MuseScore Limited + * Copyright (C) 2025 MuseScore Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -25,9 +25,9 @@ #include "log.h" -using namespace mu::iex::videoexport; +using namespace muse::media; -struct mu::iex::videoexport::FFmpeg { +struct muse::media::FFmpeg { int width = 0; int height = 0; unsigned int ptsCounter = 0; @@ -78,7 +78,8 @@ VideoEncoder::~VideoEncoder() delete m_ffmpeg; } -bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) +bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, + unsigned fps) { m_ffmpeg->ptsCounter = 0; @@ -185,8 +186,6 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign #endif } - //av_dump_format(m_ffmpeg->formatCtx, 0, fileName.c_str(), 1); - // open_video #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) // find the video encoder diff --git a/src/importexport/videoexport/internal/videoencoder.h b/src/framework/media/internal/videoencoder.h similarity index 61% rename from src/importexport/videoexport/internal/videoencoder.h rename to src/framework/media/internal/videoencoder.h index 75c0b379decdc..089047152120c 100644 --- a/src/importexport/videoexport/internal/videoencoder.h +++ b/src/framework/media/internal/videoencoder.h @@ -5,7 +5,7 @@ * MuseScore Studio * Music Composition & Notation * - * Copyright (C) 2021 MuseScore Limited + * Copyright (C) 2025 MuseScore Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -19,35 +19,29 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef MU_IMPORTEXPORT_VIDEOENCODER_H -#define MU_IMPORTEXPORT_VIDEOENCODER_H -#include +#pragma once -#include "io/path.h" +#include "../ivideoencoder.h" -namespace mu::iex::videoexport { +namespace muse::media { struct FFmpeg; -class VideoEncoder +class VideoEncoder : public IVideoEncoder { public: VideoEncoder(); - ~VideoEncoder(); + ~VideoEncoder() override; - bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps); - void close(); + bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; + void close() override; - bool encodeImage(const QImage& img); - - static bool muxAudioVideo(const muse::io::path_t& videoPath, const muse::io::path_t& audioPath, const muse::io::path_t& outputPath, - double audioOffsetSec); + bool encodeImage(const QImage& img) override; + bool muxAudioVideo(const muse::io::path_t& videoPath, const muse::io::path_t& audioPath, const muse::io::path_t& outputPath, + double audioOffsetSec) override; private: - bool convertImage_sws(const QImage& img); FFmpeg* m_ffmpeg = nullptr; }; } - -#endif // MU_IMPORTEXPORT_VIDEOENCODER_H diff --git a/src/framework/media/ivideoencoder.h b/src/framework/media/ivideoencoder.h new file mode 100644 index 0000000000000..0a37b9c8c63af --- /dev/null +++ b/src/framework/media/ivideoencoder.h @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#include "io/path.h" + +#include "modularity/imoduleinterface.h" + +namespace muse::media { +class IVideoEncoder : MODULE_GLOBAL_INTERFACE +{ + INTERFACE_ID(IVideoEncoder) + +public: + virtual ~IVideoEncoder() = default; + + virtual bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) = 0; + virtual void close() = 0; + virtual bool encodeImage(const QImage& img) = 0; + virtual bool muxAudioVideo(const muse::io::path_t& videoPath, const muse::io::path_t& audioPath, const muse::io::path_t& outputPath, + double audioOffsetSec) = 0; +}; +} diff --git a/src/framework/media/mediamodule.cpp b/src/framework/media/mediamodule.cpp new file mode 100644 index 0000000000000..1242c37ea7561 --- /dev/null +++ b/src/framework/media/mediamodule.cpp @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "mediamodule.h" + +#include "modularity/ioc.h" + +#include "internal/videoencoder.h" + +using namespace muse::media; +using namespace muse::modularity; + +std::string MediaModule::moduleName() const +{ + return "media"; +} + +void MediaModule::registerExports() +{ + ioc()->registerExport(moduleName(), std::make_shared()); +} diff --git a/src/framework/media/mediamodule.h b/src/framework/media/mediamodule.h new file mode 100644 index 0000000000000..2fc6af2c3b39d --- /dev/null +++ b/src/framework/media/mediamodule.h @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "modularity/imodulesetup.h" + +namespace muse::media { +class MediaModule : public modularity::IModuleSetup +{ +public: + std::string moduleName() const override; + + void registerExports() override; +}; +} diff --git a/src/framework/stubs/CMakeLists.txt b/src/framework/stubs/CMakeLists.txt index d70577b6c6d00..005dc1a57e9d2 100644 --- a/src/framework/stubs/CMakeLists.txt +++ b/src/framework/stubs/CMakeLists.txt @@ -42,6 +42,10 @@ if (NOT MUSE_MODULE_LEARN) add_subdirectory(learn) endif() +if (NOT MUSE_MODULE_MEDIA) + add_subdirectory(media) +endif() + if (NOT MUSE_MODULE_MIDI) add_subdirectory(midi) endif() diff --git a/src/framework/stubs/media/CMakeLists.txt b/src/framework/stubs/media/CMakeLists.txt new file mode 100644 index 0000000000000..fd3eb94641a1a --- /dev/null +++ b/src/framework/stubs/media/CMakeLists.txt @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-3.0-only +# MuseScore-Studio-CLA-applies +# +# MuseScore Studio +# Music Composition & Notation +# +# Copyright (C) 2025 MuseScore Limited +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +muse_create_module(muse_media ALIAS muse::media STUB) + +target_sources(muse_media PRIVATE + mediastubmodule.cpp + mediastubmodule.h + videoencoderstub.cpp + videoencoderstub.h +) diff --git a/src/framework/stubs/media/mediastubmodule.cpp b/src/framework/stubs/media/mediastubmodule.cpp new file mode 100644 index 0000000000000..9827af972e3df --- /dev/null +++ b/src/framework/stubs/media/mediastubmodule.cpp @@ -0,0 +1,40 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "mediastubmodule.h" + +#include "framework/media/ivideoencoder.h" +#include "modularity/ioc.h" + +#include "videoencoderstub.h" + +using namespace muse::media; +using namespace muse::modularity; + +std::string MediaModule::moduleName() const +{ + return "media_stub"; +} + +void MediaModule::registerExports() +{ + ioc()->registerExport(moduleName(), std::make_shared()); +} diff --git a/src/framework/stubs/media/mediastubmodule.h b/src/framework/stubs/media/mediastubmodule.h new file mode 100644 index 0000000000000..7684f458c2240 --- /dev/null +++ b/src/framework/stubs/media/mediastubmodule.h @@ -0,0 +1,36 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "modularity/imodulesetup.h" + +namespace muse::media { +class MediaModule : public modularity::IModuleSetup +{ +public: + MediaModule() = default; + + std::string moduleName() const override; + void registerExports() override; +}; +} diff --git a/src/framework/stubs/media/videoencoderstub.cpp b/src/framework/stubs/media/videoencoderstub.cpp new file mode 100644 index 0000000000000..3aaf1f3874c77 --- /dev/null +++ b/src/framework/stubs/media/videoencoderstub.cpp @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "videoencoderstub.h" + +using namespace muse::media; + +bool VideoEncoderStub::open(const muse::io::path_t&, unsigned, unsigned, unsigned, unsigned, unsigned) +{ + return false; +} + +void VideoEncoderStub::close() +{ +} + +bool VideoEncoderStub::encodeImage(const QImage&) +{ + return false; +} + +bool VideoEncoderStub::muxAudioVideo(const muse::io::path_t&, const muse::io::path_t&, + const muse::io::path_t&, double) +{ + return false; +} diff --git a/src/framework/stubs/media/videoencoderstub.h b/src/framework/stubs/media/videoencoderstub.h new file mode 100644 index 0000000000000..343ea918671cd --- /dev/null +++ b/src/framework/stubs/media/videoencoderstub.h @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "framework/media/ivideoencoder.h" + +namespace muse::media { +class VideoEncoderStub : public IVideoEncoder +{ +public: + VideoEncoderStub() = default; + + bool open(const muse::io::path_t&, unsigned, unsigned, unsigned, unsigned, unsigned) override; + void close() override; + bool encodeImage(const QImage&) override; + bool muxAudioVideo(const muse::io::path_t&, const muse::io::path_t&, const muse::io::path_t&, + double) override; +}; +} diff --git a/src/importexport/videoexport/CMakeLists.txt b/src/importexport/videoexport/CMakeLists.txt index a25ae27eb8a68..5c3ef1adf9047 100644 --- a/src/importexport/videoexport/CMakeLists.txt +++ b/src/importexport/videoexport/CMakeLists.txt @@ -30,15 +30,6 @@ target_sources(iex_videoexport PRIVATE internal/videoexportconfiguration.h internal/videowriter.cpp internal/videowriter.h - internal/videoencoder.cpp - internal/videoencoder.h - internal/ffmpeg.h ) -target_link_libraries(iex_videoexport PRIVATE Qt::Concurrent engraving) - -# FFmpeg -find_package(FFmpeg REQUIRED) - -target_include_directories(iex_videoexport PRIVATE ${FFMPEG_INCLUDE_DIRS}) -target_link_libraries(iex_videoexport PRIVATE ${FFMPEG_LIBRARIES}) +target_link_libraries(iex_videoexport PRIVATE Qt::Concurrent muse::media engraving) diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index 4e572aba9020b..ce299b385a8d3 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -37,8 +37,6 @@ #include "notationscene/qml/MuseScore/NotationScene/playbackcursor.h" -#include "videoencoder.h" - #include "defer.h" #include "log.h" @@ -105,7 +103,7 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, if (withAudio) { if (result && m_audioRet) { - if (!VideoEncoder::muxAudioVideo(tempVideoPath, tempAudioPath, finalPath, cfg.leadingSec)) { + if (!videoEncoder()->muxAudioVideo(tempVideoPath, tempAudioPath, finalPath, cfg.leadingSec)) { result = make_ret(muse::Ret::Code::UnknownError); } } else if (!result) { @@ -317,8 +315,7 @@ void VideoWriter::restoreScore(INotationPtr notation, const ScoreRestoreData& da void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& filePath, const Config& config) { - VideoEncoder encoder; - if (!encoder.open(filePath, config.width, config.height, config.bitrate, config.fps / 2, config.fps)) { + if (!videoEncoder()->open(filePath, config.width, config.height, config.bitrate, config.fps / 2, config.fps)) { LOGE() << "failed open encoder"; m_writeRet = make_ret(muse::Ret::Code::UnknownError); m_isCompleted = true; @@ -381,7 +378,7 @@ void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& file for (int f = 0; f < frameCount; f++) { if (m_abort) { - encoder.close(); + videoEncoder()->close(); m_writeRet = make_ret(muse::Ret::Code::Cancel); m_progress.finish(make_ret(muse::Ret::Code::Cancel)); return; @@ -422,10 +419,10 @@ void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& file painter.fillRect(cursorAbsRect, CURSOR_COLOR); - encoder.encodeImage(frame); + videoEncoder()->encodeImage(frame); } - encoder.close(); + videoEncoder()->close(); m_writeRet = muse::make_ok(); m_progress.finish(muse::make_ok()); diff --git a/src/importexport/videoexport/internal/videowriter.h b/src/importexport/videoexport/internal/videowriter.h index 5f14330e0d5dd..c8c8526f0881a 100644 --- a/src/importexport/videoexport/internal/videowriter.h +++ b/src/importexport/videoexport/internal/videowriter.h @@ -19,18 +19,17 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef MU_IMPORTEXPORT_VIDEOWRITER_H -#define MU_IMPORTEXPORT_VIDEOWRITER_H -#include +#pragma once #include "async/asyncable.h" #include "engraving/style/style.h" #include "modularity/ioc.h" +#include "global/iapplication.h" +#include "media/ivideoencoder.h" #include "../ivideoexportconfiguration.h" -#include "iapplication.h" #include "project/inotationwriter.h" #include "project/inotationwritersregister.h" @@ -42,6 +41,7 @@ class VideoWriter : public project::INotationWriter, public muse::Contextable, p { muse::GlobalInject configuration; muse::ContextInject application = { this }; + muse::ContextInject videoEncoder = { this }; muse::ContextInject writers = { this }; public: @@ -100,5 +100,3 @@ class VideoWriter : public project::INotationWriter, public muse::Contextable, p muse::Ret m_audioRet; }; } - -#endif // MU_IMPORTEXPORT_VIDEOWRITER_H From 32df9ec1235a9415555c0a5aeb337c913d7ad060 Mon Sep 17 00:00:00 2001 From: Eism Date: Wed, 4 Mar 2026 15:54:56 +0200 Subject: [PATCH 10/52] scripts for copying FFmpeg headers to MuseScore --- src/framework/media/thirdparty/.untidy | 0 .../media/thirdparty/ffmpeg/README.md | 36 +++++ .../thirdparty/ffmpeg/copy_ffmpeg_headers.sh | 75 +++++++++ .../ffmpeg/download_ffmpeg_headers.sh | 104 +++++++++++++ .../thirdparty/ffmpeg/v8/libavutil/mem.h | 147 ++++++++++++++++++ 5 files changed, 362 insertions(+) create mode 100644 src/framework/media/thirdparty/.untidy create mode 100644 src/framework/media/thirdparty/ffmpeg/README.md create mode 100755 src/framework/media/thirdparty/ffmpeg/copy_ffmpeg_headers.sh create mode 100644 src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/mem.h diff --git a/src/framework/media/thirdparty/.untidy b/src/framework/media/thirdparty/.untidy new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/framework/media/thirdparty/ffmpeg/README.md b/src/framework/media/thirdparty/ffmpeg/README.md new file mode 100644 index 0000000000000..709379a134823 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/README.md @@ -0,0 +1,36 @@ +# FFmpeg headers for MuseScore + +Minimal set of FFmpeg header files for MuseScore video export. +Each folder contains headers from the corresponding FFmpeg version, copied as-is from the official FFmpeg source. + +- **v4** — from FFmpeg n4.4 +- **v5** — from FFmpeg n5.1 +- **v6** — from FFmpeg n6.1 +- **v7** — from FFmpeg n7.0 +- **v8** — from FFmpeg n8.0 + +Components: libavcodec, libavformat, libavutil, libswscale. + +Note: `avconfig.h` is generated by FFmpeg's configure and not in the source tree; a minimal version is provided for little-endian systems. + +## Updating headers + +To download FFmpeg headers, run the script from the MuseScore repository root: + +```bash +./src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh +``` + +or: + +```bash +bash src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh +``` + +The script will: +1. Clone FFmpeg (sparse checkout) +2. For each version (4–8), checkout the corresponding tag and copy required headers to `vN` +3. Add `avconfig.h` (generated by configure, not present in source) +4. Remove the temporary FFmpeg clone + +Requirements: git, python3. diff --git a/src/framework/media/thirdparty/ffmpeg/copy_ffmpeg_headers.sh b/src/framework/media/thirdparty/ffmpeg/copy_ffmpeg_headers.sh new file mode 100755 index 0000000000000..945d5fd36bcab --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/copy_ffmpeg_headers.sh @@ -0,0 +1,75 @@ +#!/bin/sh +# +# Copy FFmpeg headers for MuseScore - extracts minimal needed headers. +# Run from FFmpeg source root. Output: list of header paths to copy. +# + +ROOT_INCLUDES="libavcodec/avcodec.h +libavformat/avformat.h +libavutil/mathematics.h +libavutil/rational.h +libavutil/avstring.h +libavutil/opt.h +libavutil/mem.h +libswscale/swscale.h +libavutil/imgutils.h" + +NL=' +' + +# Resolve include path: if contains "/" use as-is, else prepend parent dir of $2 +resolve_include() { + inc=$(echo "$1" | tr -d ' \t') + from="$2" + [ -z "$inc" ] && return 1 + if echo "$inc" | grep -q '/'; then + echo "$inc" + else + parent="${from%/*}" + [ -n "$parent" ] && echo "${parent}/${inc}" || echo "$inc" + fi +} + +# Check if line is in list (newline-separated) +line_in_list() { + line="$1" + list="$2" + echo "$list" | grep -qFx "$line" 2>/dev/null +} + +# Collect all headers recursively +collect_headers() { + root="$1" + collected="" + to_process="$ROOT_INCLUDES" + + while [ -n "$to_process" ]; do + next_process="" + for rel_path in $to_process; do + if line_in_list "$rel_path" "$collected"; then + continue + fi + collected="${collected}${collected:+$NL}$rel_path" + full_path="${root}/${rel_path}" + if [ ! -f "$full_path" ]; then + continue + fi + # Extract #include "..." (local includes only) + while IFS= read -r line; do + inc=$(echo "$line" | sed -n 's/^[[:space:]]*#include[[:space:]]*"\([^"]*\)".*/\1/p') + [ -z "$inc" ] && continue + resolved=$(resolve_include "$inc" "$rel_path") + [ -z "$resolved" ] && continue + if ! line_in_list "$resolved" "$collected" && ! line_in_list "$resolved" "$next_process"; then + next_process="${next_process}${next_process:+$NL}$resolved" + fi + done < "$full_path" + done + to_process="$next_process" + done + echo "$collected" +} + +root=$(pwd) +headers=$(collect_headers "$root") +echo "$headers" | sort -u diff --git a/src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh b/src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh new file mode 100644 index 0000000000000..8d9d1a6a52cbe --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Download FFmpeg headers for MuseScore (versions 4, 5, 6, 7, 8) +# Run from MuseScore repository root +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../../../../.." && pwd)" +FFMPEG_DIR="$REPO_ROOT/.ffmpeg_temp" +TARGET_BASE="$SCRIPT_DIR" + +VERSIONS=( + "4:n4.4" + "5:n5.1" + "6:n6.1" + "7:n7.0" + "8:n8.0" +) + +write_avconfig() { + local dest="$1" + cat > "$dest" << 'AVCONFIG_EOF' +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVCONFIG_H +#define AVUTIL_AVCONFIG_H + +#define AV_HAVE_BIGENDIAN 0 + +#endif /* AVUTIL_AVCONFIG_H */ +AVCONFIG_EOF +} + +echo "=== Downloading FFmpeg headers for MuseScore ===" + +# Clone FFmpeg if not present +if [ ! -d "$FFMPEG_DIR" ]; then + echo "Cloning FFmpeg (sparse checkout)..." + git clone --depth 1 --filter=blob:none --sparse https://github.com/FFmpeg/FFmpeg.git "$FFMPEG_DIR" + cd "$FFMPEG_DIR" + git sparse-checkout set libavcodec libavformat libavutil libswscale + cd - > /dev/null +else + echo "Using existing FFmpeg clone: $FFMPEG_DIR" +fi + +cd "$FFMPEG_DIR" + +for ver_spec in "${VERSIONS[@]}"; do + ver="${ver_spec%%:*}" + tag="${ver_spec#*:}" + target="$TARGET_BASE/v$ver" + + echo "" + echo "--- Processing FFmpeg $tag (v$ver) ---" + + git fetch --depth 1 origin tag "$tag" 2>/dev/null || true + git checkout "$tag" + git sparse-checkout set libavcodec libavformat libavutil libswscale + + mkdir -p "$target" + + "$SCRIPT_DIR/copy_ffmpeg_headers.sh" 2>/dev/null | grep -v avconfig | while read -r h; do + if [ -n "$h" ] && [ -f "$h" ]; then + mkdir -p "$target/$(dirname "$h")" + cp "$h" "$target/$h" + echo " copied $h" + fi + done + + # avconfig.h is generated by FFmpeg configure, not in source; add minimal version + if [ -f "$target/libavutil/macros.h" ] && grep -q avconfig.h "$target/libavutil/macros.h" 2>/dev/null; then + mkdir -p "$target/libavutil" + write_avconfig "$target/libavutil/avconfig.h" + echo " added libavutil/avconfig.h" + fi + + count=$(find "$target" -name "*.h" | wc -l) + echo " -> $count headers in v$ver" +done + +cd - > /dev/null + +echo "" +echo "Removing temporary clone..." +rm -rf "$FFMPEG_DIR" + +echo "" +echo "Done. Headers in: $TARGET_BASE" diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/mem.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/mem.h new file mode 100644 index 0000000000000..22c3c9c3b36db --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/mem.h @@ -0,0 +1,147 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_mem + * Memory handling functions + */ + +#ifndef AVUTIL_MEM_H +#define AVUTIL_MEM_H + +#include +#include + +#include "attributes.h" +#include "avutil.h" +#include "version.h" + +/** + * @addtogroup lavu_mem + * Utilities for manipulating memory. + * + * FFmpeg has several applications of memory that are not required of a typical + * program. For example, the computing-heavy components like video decoding and + * encoding can be sped up significantly through the use of aligned memory. + * + * However, for each of FFmpeg's applications of memory, there might not be a + * recognized or standardized API for that specific use. Memory alignment, for + * instance, varies wildly depending on operating systems, architectures, and + * compilers. Hence, this component of @ref libavutil is created to make + * dealing with memory consistently possible on all platforms. + * + * @{ + */ + +#if defined(FF_API_DECLARE_ALIGNED) && FF_API_DECLARE_ALIGNED +/** + * + * @defgroup lavu_mem_macros Alignment Macros + * Helper macros for declaring aligned variables. + * @{ + */ + +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v +#elif defined(__DJGPP__) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v + #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v +#elif defined(__GNUC__) || defined(__clang__) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v +#elif defined(_MSC_VER) + #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v +#else + #define DECLARE_ALIGNED(n,t,v) t v + #define DECLARE_ASM_ALIGNED(n,t,v) t v + #define DECLARE_ASM_CONST(n,t,v) static const t v +#endif + +/** + * @} + */ +#endif + +/** + * @defgroup lavu_mem_attrs Function Attributes + * @{ + */ + +#if AV_GCC_VERSION_AT_LEAST(3,1) + #define av_malloc_attrib __attribute__((__malloc__)) +#else + #define av_malloc_attrib +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,3) + #define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__))) +#else + #define av_alloc_size(...) +#endif + +/** + * @} + */ + +/** + * @defgroup lavu_mem_funcs Heap Management + * @{ + */ + +void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1); +void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1); +av_alloc_size(1, 2) void *av_malloc_array(size_t nmemb, size_t size); +void *av_calloc(size_t nmemb, size_t size) av_malloc_attrib av_alloc_size(1, 2); +void *av_realloc(void *ptr, size_t size) av_alloc_size(2); +av_warn_unused_result +int av_reallocp(void *ptr, size_t size); +void *av_realloc_f(void *ptr, size_t nelem, size_t elsize); +av_alloc_size(2, 3) void *av_realloc_array(void *ptr, size_t nmemb, size_t size); +int av_reallocp_array(void *ptr, size_t nmemb, size_t size); +void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size); +void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size); +void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size); +void av_free(void *ptr); +void av_freep(void *ptr); +char *av_strdup(const char *s) av_malloc_attrib; +char *av_strndup(const char *s, size_t len) av_malloc_attrib; +void *av_memdup(const void *p, size_t size); +void av_memcpy_backptr(uint8_t *dst, int back, int cnt); +void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem); +av_warn_unused_result +int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem); +void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, + const uint8_t *elem_data); +int av_size_mult(size_t a, size_t b, size_t *r); +void av_max_alloc(size_t max); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_MEM_H */ From e80241c5ffc93216bcdd472b5da7313189f38aed Mon Sep 17 00:00:00 2001 From: Eism Date: Wed, 4 Mar 2026 15:55:20 +0200 Subject: [PATCH 11/52] copied FFmpeg headers --- .../thirdparty/ffmpeg/v4/libavcodec/avcodec.h | 4184 +++++++++++++++++ .../thirdparty/ffmpeg/v4/libavcodec/bsf.h | 325 ++ .../thirdparty/ffmpeg/v4/libavcodec/codec.h | 480 ++ .../ffmpeg/v4/libavcodec/codec_desc.h | 128 + .../ffmpeg/v4/libavcodec/codec_id.h | 592 +++ .../ffmpeg/v4/libavcodec/codec_par.h | 229 + .../thirdparty/ffmpeg/v4/libavcodec/packet.h | 774 +++ .../thirdparty/ffmpeg/v4/libavcodec/version.h | 172 + .../ffmpeg/v4/libavformat/avformat.h | 3012 ++++++++++++ .../thirdparty/ffmpeg/v4/libavformat/avio.h | 888 ++++ .../ffmpeg/v4/libavformat/version.h | 123 + .../ffmpeg/v4/libavutil/attributes.h | 173 + .../thirdparty/ffmpeg/v4/libavutil/avstring.h | 437 ++ .../thirdparty/ffmpeg/v4/libavutil/avutil.h | 365 ++ .../thirdparty/ffmpeg/v4/libavutil/buffer.h | 353 ++ .../ffmpeg/v4/libavutil/channel_layout.h | 238 + .../thirdparty/ffmpeg/v4/libavutil/common.h | 608 +++ .../thirdparty/ffmpeg/v4/libavutil/cpu.h | 133 + .../thirdparty/ffmpeg/v4/libavutil/dict.h | 200 + .../thirdparty/ffmpeg/v4/libavutil/error.h | 126 + .../thirdparty/ffmpeg/v4/libavutil/frame.h | 997 ++++ .../ffmpeg/v4/libavutil/hwcontext.h | 605 +++ .../thirdparty/ffmpeg/v4/libavutil/imgutils.h | 291 ++ .../thirdparty/ffmpeg/v4/libavutil/intfloat.h | 77 + .../thirdparty/ffmpeg/v4/libavutil/log.h | 401 ++ .../thirdparty/ffmpeg/v4/libavutil/macros.h | 50 + .../ffmpeg/v4/libavutil/mathematics.h | 242 + .../thirdparty/ffmpeg/v4/libavutil/mem.h | 706 +++ .../thirdparty/ffmpeg/v4/libavutil/opt.h | 886 ++++ .../thirdparty/ffmpeg/v4/libavutil/pixdesc.h | 442 ++ .../thirdparty/ffmpeg/v4/libavutil/pixfmt.h | 616 +++ .../thirdparty/ffmpeg/v4/libavutil/rational.h | 220 + .../ffmpeg/v4/libavutil/samplefmt.h | 272 ++ .../thirdparty/ffmpeg/v4/libavutil/version.h | 150 + .../thirdparty/ffmpeg/v4/libswscale/swscale.h | 336 ++ .../thirdparty/ffmpeg/v4/libswscale/version.h | 53 + .../thirdparty/ffmpeg/v5/libavcodec/avcodec.h | 3169 +++++++++++++ .../thirdparty/ffmpeg/v5/libavcodec/codec.h | 387 ++ .../ffmpeg/v5/libavcodec/codec_desc.h | 128 + .../ffmpeg/v5/libavcodec/codec_id.h | 634 +++ .../ffmpeg/v5/libavcodec/codec_par.h | 246 + .../thirdparty/ffmpeg/v5/libavcodec/defs.h | 170 + .../thirdparty/ffmpeg/v5/libavcodec/packet.h | 731 +++ .../thirdparty/ffmpeg/v5/libavcodec/version.h | 45 + .../ffmpeg/v5/libavcodec/version_major.h | 54 + .../ffmpeg/v5/libavformat/avformat.h | 2907 ++++++++++++ .../thirdparty/ffmpeg/v5/libavformat/avio.h | 842 ++++ .../ffmpeg/v5/libavformat/version.h | 47 + .../ffmpeg/v5/libavformat/version_major.h | 53 + .../ffmpeg/v5/libavutil/attributes.h | 173 + .../thirdparty/ffmpeg/v5/libavutil/avconfig.h | 24 + .../thirdparty/ffmpeg/v5/libavutil/avstring.h | 437 ++ .../thirdparty/ffmpeg/v5/libavutil/avutil.h | 371 ++ .../thirdparty/ffmpeg/v5/libavutil/buffer.h | 322 ++ .../ffmpeg/v5/libavutil/channel_layout.h | 749 +++ .../thirdparty/ffmpeg/v5/libavutil/common.h | 578 +++ .../thirdparty/ffmpeg/v5/libavutil/dict.h | 198 + .../thirdparty/ffmpeg/v5/libavutil/error.h | 128 + .../thirdparty/ffmpeg/v5/libavutil/frame.h | 947 ++++ .../ffmpeg/v5/libavutil/hwcontext.h | 609 +++ .../thirdparty/ffmpeg/v5/libavutil/imgutils.h | 311 ++ .../thirdparty/ffmpeg/v5/libavutil/intfloat.h | 77 + .../thirdparty/ffmpeg/v5/libavutil/log.h | 387 ++ .../thirdparty/ffmpeg/v5/libavutil/macros.h | 80 + .../ffmpeg/v5/libavutil/mathematics.h | 243 + .../thirdparty/ffmpeg/v5/libavutil/mem.h | 696 +++ .../thirdparty/ffmpeg/v5/libavutil/opt.h | 891 ++++ .../thirdparty/ffmpeg/v5/libavutil/pixdesc.h | 410 ++ .../thirdparty/ffmpeg/v5/libavutil/pixfmt.h | 629 +++ .../thirdparty/ffmpeg/v5/libavutil/rational.h | 220 + .../ffmpeg/v5/libavutil/samplefmt.h | 268 ++ .../thirdparty/ffmpeg/v5/libavutil/version.h | 123 + .../thirdparty/ffmpeg/v5/libswscale/swscale.h | 431 ++ .../thirdparty/ffmpeg/v5/libswscale/version.h | 44 + .../ffmpeg/v5/libswscale/version_major.h | 35 + .../thirdparty/ffmpeg/v6/libavcodec/avcodec.h | 3154 +++++++++++++ .../thirdparty/ffmpeg/v6/libavcodec/codec.h | 378 ++ .../ffmpeg/v6/libavcodec/codec_desc.h | 134 + .../ffmpeg/v6/libavcodec/codec_id.h | 668 +++ .../ffmpeg/v6/libavcodec/codec_par.h | 262 ++ .../thirdparty/ffmpeg/v6/libavcodec/defs.h | 335 ++ .../thirdparty/ffmpeg/v6/libavcodec/packet.h | 846 ++++ .../thirdparty/ffmpeg/v6/libavcodec/version.h | 45 + .../ffmpeg/v6/libavcodec/version_major.h | 59 + .../ffmpeg/v6/libavformat/avformat.h | 2858 +++++++++++ .../thirdparty/ffmpeg/v6/libavformat/avio.h | 850 ++++ .../ffmpeg/v6/libavformat/version.h | 47 + .../ffmpeg/v6/libavformat/version_major.h | 56 + .../ffmpeg/v6/libavutil/attributes.h | 173 + .../thirdparty/ffmpeg/v6/libavutil/avconfig.h | 24 + .../thirdparty/ffmpeg/v6/libavutil/avstring.h | 428 ++ .../thirdparty/ffmpeg/v6/libavutil/avutil.h | 375 ++ .../thirdparty/ffmpeg/v6/libavutil/buffer.h | 322 ++ .../ffmpeg/v6/libavutil/channel_layout.h | 807 ++++ .../thirdparty/ffmpeg/v6/libavutil/common.h | 579 +++ .../thirdparty/ffmpeg/v6/libavutil/dict.h | 241 + .../thirdparty/ffmpeg/v6/libavutil/error.h | 128 + .../thirdparty/ffmpeg/v6/libavutil/frame.h | 1056 +++++ .../ffmpeg/v6/libavutil/hwcontext.h | 610 +++ .../thirdparty/ffmpeg/v6/libavutil/imgutils.h | 347 ++ .../thirdparty/ffmpeg/v6/libavutil/intfloat.h | 77 + .../thirdparty/ffmpeg/v6/libavutil/log.h | 387 ++ .../thirdparty/ffmpeg/v6/libavutil/macros.h | 80 + .../ffmpeg/v6/libavutil/mathematics.h | 300 ++ .../thirdparty/ffmpeg/v6/libavutil/mem.h | 607 +++ .../thirdparty/ffmpeg/v6/libavutil/opt.h | 891 ++++ .../thirdparty/ffmpeg/v6/libavutil/pixdesc.h | 435 ++ .../thirdparty/ffmpeg/v6/libavutil/pixfmt.h | 703 +++ .../thirdparty/ffmpeg/v6/libavutil/rational.h | 221 + .../ffmpeg/v6/libavutil/samplefmt.h | 269 ++ .../thirdparty/ffmpeg/v6/libavutil/version.h | 128 + .../thirdparty/ffmpeg/v6/libswscale/swscale.h | 436 ++ .../thirdparty/ffmpeg/v6/libswscale/version.h | 44 + .../ffmpeg/v6/libswscale/version_major.h | 35 + .../thirdparty/ffmpeg/v7/libavcodec/avcodec.h | 3087 ++++++++++++ .../thirdparty/ffmpeg/v7/libavcodec/codec.h | 371 ++ .../ffmpeg/v7/libavcodec/codec_desc.h | 134 + .../ffmpeg/v7/libavcodec/codec_id.h | 667 +++ .../ffmpeg/v7/libavcodec/codec_par.h | 248 + .../thirdparty/ffmpeg/v7/libavcodec/defs.h | 335 ++ .../thirdparty/ffmpeg/v7/libavcodec/packet.h | 870 ++++ .../thirdparty/ffmpeg/v7/libavcodec/version.h | 45 + .../ffmpeg/v7/libavcodec/version_major.h | 51 + .../ffmpeg/v7/libavformat/avformat.h | 3067 ++++++++++++ .../thirdparty/ffmpeg/v7/libavformat/avio.h | 831 ++++ .../ffmpeg/v7/libavformat/version.h | 47 + .../ffmpeg/v7/libavformat/version_major.h | 53 + .../ffmpeg/v7/libavutil/attributes.h | 173 + .../thirdparty/ffmpeg/v7/libavutil/avconfig.h | 24 + .../thirdparty/ffmpeg/v7/libavutil/avstring.h | 428 ++ .../thirdparty/ffmpeg/v7/libavutil/avutil.h | 362 ++ .../thirdparty/ffmpeg/v7/libavutil/buffer.h | 322 ++ .../ffmpeg/v7/libavutil/channel_layout.h | 733 +++ .../thirdparty/ffmpeg/v7/libavutil/common.h | 573 +++ .../thirdparty/ffmpeg/v7/libavutil/dict.h | 241 + .../thirdparty/ffmpeg/v7/libavutil/error.h | 128 + .../thirdparty/ffmpeg/v7/libavutil/frame.h | 1081 +++++ .../ffmpeg/v7/libavutil/hwcontext.h | 598 +++ .../thirdparty/ffmpeg/v7/libavutil/imgutils.h | 377 ++ .../thirdparty/ffmpeg/v7/libavutil/intfloat.h | 77 + .../thirdparty/ffmpeg/v7/libavutil/log.h | 387 ++ .../thirdparty/ffmpeg/v7/libavutil/macros.h | 80 + .../ffmpeg/v7/libavutil/mathematics.h | 300 ++ .../thirdparty/ffmpeg/v7/libavutil/mem.h | 607 +++ .../thirdparty/ffmpeg/v7/libavutil/opt.h | 998 ++++ .../thirdparty/ffmpeg/v7/libavutil/pixdesc.h | 440 ++ .../thirdparty/ffmpeg/v7/libavutil/pixfmt.h | 713 +++ .../thirdparty/ffmpeg/v7/libavutil/rational.h | 225 + .../ffmpeg/v7/libavutil/samplefmt.h | 269 ++ .../thirdparty/ffmpeg/v7/libavutil/version.h | 121 + .../thirdparty/ffmpeg/v7/libswscale/swscale.h | 436 ++ .../thirdparty/ffmpeg/v7/libswscale/version.h | 44 + .../ffmpeg/v7/libswscale/version_major.h | 35 + .../thirdparty/ffmpeg/v8/libavcodec/avcodec.h | 2947 ++++++++++++ .../thirdparty/ffmpeg/v8/libavcodec/codec.h | 367 ++ .../ffmpeg/v8/libavcodec/codec_desc.h | 134 + .../ffmpeg/v8/libavcodec/codec_id.h | 683 +++ .../ffmpeg/v8/libavcodec/codec_par.h | 248 + .../thirdparty/ffmpeg/v8/libavcodec/defs.h | 362 ++ .../thirdparty/ffmpeg/v8/libavcodec/packet.h | 907 ++++ .../thirdparty/ffmpeg/v8/libavcodec/version.h | 45 + .../ffmpeg/v8/libavcodec/version_major.h | 55 + .../ffmpeg/v8/libavformat/avformat.h | 3004 ++++++++++++ .../thirdparty/ffmpeg/v8/libavformat/avio.h | 831 ++++ .../ffmpeg/v8/libavformat/version.h | 47 + .../ffmpeg/v8/libavformat/version_major.h | 52 + .../ffmpeg/v8/libavutil/attributes.h | 175 + .../thirdparty/ffmpeg/v8/libavutil/avconfig.h | 24 + .../thirdparty/ffmpeg/v8/libavutil/avstring.h | 428 ++ .../thirdparty/ffmpeg/v8/libavutil/avutil.h | 364 ++ .../thirdparty/ffmpeg/v8/libavutil/buffer.h | 322 ++ .../ffmpeg/v8/libavutil/channel_layout.h | 762 +++ .../thirdparty/ffmpeg/v8/libavutil/common.h | 589 +++ .../thirdparty/ffmpeg/v8/libavutil/dict.h | 242 + .../thirdparty/ffmpeg/v8/libavutil/error.h | 129 + .../thirdparty/ffmpeg/v8/libavutil/frame.h | 1163 +++++ .../ffmpeg/v8/libavutil/hwcontext.h | 601 +++ .../thirdparty/ffmpeg/v8/libavutil/imgutils.h | 377 ++ .../thirdparty/ffmpeg/v8/libavutil/intfloat.h | 77 + .../thirdparty/ffmpeg/v8/libavutil/log.h | 427 ++ .../thirdparty/ffmpeg/v8/libavutil/macros.h | 80 + .../ffmpeg/v8/libavutil/mathematics.h | 300 ++ .../thirdparty/ffmpeg/v8/libavutil/mem.h | 530 ++- .../thirdparty/ffmpeg/v8/libavutil/opt.h | 1194 +++++ .../thirdparty/ffmpeg/v8/libavutil/pixdesc.h | 440 ++ .../thirdparty/ffmpeg/v8/libavutil/pixfmt.h | 797 ++++ .../thirdparty/ffmpeg/v8/libavutil/rational.h | 225 + .../ffmpeg/v8/libavutil/samplefmt.h | 269 ++ .../thirdparty/ffmpeg/v8/libavutil/version.h | 119 + .../thirdparty/ffmpeg/v8/libswscale/swscale.h | 683 +++ .../thirdparty/ffmpeg/v8/libswscale/version.h | 44 + .../ffmpeg/v8/libswscale/version_major.h | 35 + 192 files changed, 97694 insertions(+), 35 deletions(-) create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavcodec/avcodec.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavcodec/bsf.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec_desc.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec_id.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec_par.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavcodec/packet.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavcodec/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavformat/avformat.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavformat/avio.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavformat/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/attributes.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/avstring.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/avutil.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/buffer.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/channel_layout.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/common.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/cpu.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/dict.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/error.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/frame.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/hwcontext.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/imgutils.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/intfloat.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/log.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/macros.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/mathematics.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/mem.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/opt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/pixdesc.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/pixfmt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/rational.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/samplefmt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libswscale/swscale.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libswscale/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavcodec/avcodec.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec_desc.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec_id.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec_par.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavcodec/defs.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavcodec/packet.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavcodec/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavcodec/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavformat/avformat.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavformat/avio.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavformat/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavformat/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/attributes.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/avconfig.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/avstring.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/avutil.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/buffer.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/channel_layout.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/common.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/dict.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/error.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/frame.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/hwcontext.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/imgutils.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/intfloat.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/log.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/macros.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/mathematics.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/mem.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/opt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/pixdesc.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/pixfmt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/rational.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/samplefmt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libavutil/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libswscale/swscale.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libswscale/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libswscale/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavcodec/avcodec.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec_desc.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec_id.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec_par.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavcodec/defs.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavcodec/packet.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavcodec/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavcodec/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavformat/avformat.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavformat/avio.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavformat/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavformat/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/attributes.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/avconfig.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/avstring.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/avutil.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/buffer.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/channel_layout.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/common.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/dict.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/error.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/frame.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/hwcontext.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/imgutils.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/intfloat.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/log.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/macros.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/mathematics.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/mem.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/opt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/pixdesc.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/pixfmt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/rational.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/samplefmt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libavutil/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libswscale/swscale.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libswscale/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libswscale/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavcodec/avcodec.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec_desc.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec_id.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec_par.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavcodec/defs.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavcodec/packet.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavcodec/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavcodec/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavformat/avformat.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavformat/avio.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavformat/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavformat/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/attributes.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/avconfig.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/avstring.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/avutil.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/buffer.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/channel_layout.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/common.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/dict.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/error.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/frame.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/hwcontext.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/imgutils.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/intfloat.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/log.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/macros.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/mathematics.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/mem.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/opt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/pixdesc.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/pixfmt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/rational.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/samplefmt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libavutil/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libswscale/swscale.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libswscale/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libswscale/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavcodec/avcodec.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec_desc.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec_id.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec_par.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavcodec/defs.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavcodec/packet.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavcodec/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavcodec/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavformat/avformat.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavformat/avio.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavformat/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavformat/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/attributes.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/avconfig.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/avstring.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/avutil.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/buffer.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/channel_layout.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/common.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/dict.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/error.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/frame.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/hwcontext.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/imgutils.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/intfloat.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/log.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/macros.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/mathematics.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/opt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/pixdesc.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/pixfmt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/rational.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/samplefmt.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libavutil/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libswscale/swscale.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libswscale/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libswscale/version_major.h diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/avcodec.h b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/avcodec.h new file mode 100644 index 0000000000000..8a71c042308e3 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/avcodec.h @@ -0,0 +1,4184 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AVCODEC_H +#define AVCODEC_AVCODEC_H + +/** + * @file + * @ingroup libavc + * Libavcodec external API header + */ + +#include +#include "libavutil/samplefmt.h" +#include "libavutil/attributes.h" +#include "libavutil/avutil.h" +#include "libavutil/buffer.h" +#include "libavutil/cpu.h" +#include "libavutil/channel_layout.h" +#include "libavutil/dict.h" +#include "libavutil/frame.h" +#include "libavutil/hwcontext.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +#include "bsf.h" +#include "codec.h" +#include "codec_desc.h" +#include "codec_par.h" +#include "codec_id.h" +#include "packet.h" +#include "version.h" + +/** + * @defgroup libavc libavcodec + * Encoding/Decoding Library + * + * @{ + * + * @defgroup lavc_decoding Decoding + * @{ + * @} + * + * @defgroup lavc_encoding Encoding + * @{ + * @} + * + * @defgroup lavc_codec Codecs + * @{ + * @defgroup lavc_codec_native Native Codecs + * @{ + * @} + * @defgroup lavc_codec_wrappers External library wrappers + * @{ + * @} + * @defgroup lavc_codec_hwaccel Hardware Accelerators bridge + * @{ + * @} + * @} + * @defgroup lavc_internal Internal + * @{ + * @} + * @} + */ + +/** + * @ingroup libavc + * @defgroup lavc_encdec send/receive encoding and decoding API overview + * @{ + * + * The avcodec_send_packet()/avcodec_receive_frame()/avcodec_send_frame()/ + * avcodec_receive_packet() functions provide an encode/decode API, which + * decouples input and output. + * + * The API is very similar for encoding/decoding and audio/video, and works as + * follows: + * - Set up and open the AVCodecContext as usual. + * - Send valid input: + * - For decoding, call avcodec_send_packet() to give the decoder raw + * compressed data in an AVPacket. + * - For encoding, call avcodec_send_frame() to give the encoder an AVFrame + * containing uncompressed audio or video. + * + * In both cases, it is recommended that AVPackets and AVFrames are + * refcounted, or libavcodec might have to copy the input data. (libavformat + * always returns refcounted AVPackets, and av_frame_get_buffer() allocates + * refcounted AVFrames.) + * - Receive output in a loop. Periodically call one of the avcodec_receive_*() + * functions and process their output: + * - For decoding, call avcodec_receive_frame(). On success, it will return + * an AVFrame containing uncompressed audio or video data. + * - For encoding, call avcodec_receive_packet(). On success, it will return + * an AVPacket with a compressed frame. + * + * Repeat this call until it returns AVERROR(EAGAIN) or an error. The + * AVERROR(EAGAIN) return value means that new input data is required to + * return new output. In this case, continue with sending input. For each + * input frame/packet, the codec will typically return 1 output frame/packet, + * but it can also be 0 or more than 1. + * + * At the beginning of decoding or encoding, the codec might accept multiple + * input frames/packets without returning a frame, until its internal buffers + * are filled. This situation is handled transparently if you follow the steps + * outlined above. + * + * In theory, sending input can result in EAGAIN - this should happen only if + * not all output was received. You can use this to structure alternative decode + * or encode loops other than the one suggested above. For example, you could + * try sending new input on each iteration, and try to receive output if that + * returns EAGAIN. + * + * End of stream situations. These require "flushing" (aka draining) the codec, + * as the codec might buffer multiple frames or packets internally for + * performance or out of necessity (consider B-frames). + * This is handled as follows: + * - Instead of valid input, send NULL to the avcodec_send_packet() (decoding) + * or avcodec_send_frame() (encoding) functions. This will enter draining + * mode. + * - Call avcodec_receive_frame() (decoding) or avcodec_receive_packet() + * (encoding) in a loop until AVERROR_EOF is returned. The functions will + * not return AVERROR(EAGAIN), unless you forgot to enter draining mode. + * - Before decoding can be resumed again, the codec has to be reset with + * avcodec_flush_buffers(). + * + * Using the API as outlined above is highly recommended. But it is also + * possible to call functions outside of this rigid schema. For example, you can + * call avcodec_send_packet() repeatedly without calling + * avcodec_receive_frame(). In this case, avcodec_send_packet() will succeed + * until the codec's internal buffer has been filled up (which is typically of + * size 1 per output frame, after initial input), and then reject input with + * AVERROR(EAGAIN). Once it starts rejecting input, you have no choice but to + * read at least some output. + * + * Not all codecs will follow a rigid and predictable dataflow; the only + * guarantee is that an AVERROR(EAGAIN) return value on a send/receive call on + * one end implies that a receive/send call on the other end will succeed, or + * at least will not fail with AVERROR(EAGAIN). In general, no codec will + * permit unlimited buffering of input or output. + * + * This API replaces the following legacy functions: + * - avcodec_decode_video2() and avcodec_decode_audio4(): + * Use avcodec_send_packet() to feed input to the decoder, then use + * avcodec_receive_frame() to receive decoded frames after each packet. + * Unlike with the old video decoding API, multiple frames might result from + * a packet. For audio, splitting the input packet into frames by partially + * decoding packets becomes transparent to the API user. You never need to + * feed an AVPacket to the API twice (unless it is rejected with AVERROR(EAGAIN) - then + * no data was read from the packet). + * Additionally, sending a flush/draining packet is required only once. + * - avcodec_encode_video2()/avcodec_encode_audio2(): + * Use avcodec_send_frame() to feed input to the encoder, then use + * avcodec_receive_packet() to receive encoded packets. + * Providing user-allocated buffers for avcodec_receive_packet() is not + * possible. + * - The new API does not handle subtitles yet. + * + * Mixing new and old function calls on the same AVCodecContext is not allowed, + * and will result in undefined behavior. + * + * Some codecs might require using the new API; using the old API will return + * an error when calling it. All codecs support the new API. + * + * A codec is not allowed to return AVERROR(EAGAIN) for both sending and receiving. This + * would be an invalid state, which could put the codec user into an endless + * loop. The API has no concept of time either: it cannot happen that trying to + * do avcodec_send_packet() results in AVERROR(EAGAIN), but a repeated call 1 second + * later accepts the packet (with no other receive/flush API calls involved). + * The API is a strict state machine, and the passage of time is not supposed + * to influence it. Some timing-dependent behavior might still be deemed + * acceptable in certain cases. But it must never result in both send/receive + * returning EAGAIN at the same time at any point. It must also absolutely be + * avoided that the current state is "unstable" and can "flip-flop" between + * the send/receive APIs allowing progress. For example, it's not allowed that + * the codec randomly decides that it actually wants to consume a packet now + * instead of returning a frame, after it just returned AVERROR(EAGAIN) on an + * avcodec_send_packet() call. + * @} + */ + +/** + * @defgroup lavc_core Core functions/structures. + * @ingroup libavc + * + * Basic definitions, functions for querying libavcodec capabilities, + * allocating core structures, etc. + * @{ + */ + +/** + * @ingroup lavc_decoding + * Required number of additionally allocated bytes at the end of the input bitstream for decoding. + * This is mainly needed because some optimized bitstream readers read + * 32 or 64 bit at once and could read over the end.
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged + * MPEG bitstreams could cause overread and segfault. + */ +#define AV_INPUT_BUFFER_PADDING_SIZE 64 + +/** + * @ingroup lavc_encoding + * minimum encoding buffer size + * Used to avoid some checks during header writing. + */ +#define AV_INPUT_BUFFER_MIN_SIZE 16384 + +/** + * @ingroup lavc_decoding + */ +enum AVDiscard{ + /* We leave some space between them for extensions (drop some + * keyframes for intra-only or drop just some bidir frames). */ + AVDISCARD_NONE =-16, ///< discard nothing + AVDISCARD_DEFAULT = 0, ///< discard useless packets like 0 size packets in avi + AVDISCARD_NONREF = 8, ///< discard all non reference + AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames + AVDISCARD_NONINTRA= 24, ///< discard all non intra frames + AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes + AVDISCARD_ALL = 48, ///< discard all +}; + +enum AVAudioServiceType { + AV_AUDIO_SERVICE_TYPE_MAIN = 0, + AV_AUDIO_SERVICE_TYPE_EFFECTS = 1, + AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED = 2, + AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED = 3, + AV_AUDIO_SERVICE_TYPE_DIALOGUE = 4, + AV_AUDIO_SERVICE_TYPE_COMMENTARY = 5, + AV_AUDIO_SERVICE_TYPE_EMERGENCY = 6, + AV_AUDIO_SERVICE_TYPE_VOICE_OVER = 7, + AV_AUDIO_SERVICE_TYPE_KARAOKE = 8, + AV_AUDIO_SERVICE_TYPE_NB , ///< Not part of ABI +}; + +/** + * @ingroup lavc_encoding + */ +typedef struct RcOverride{ + int start_frame; + int end_frame; + int qscale; // If this is 0 then quality_factor will be used instead. + float quality_factor; +} RcOverride; + +/* encoding support + These flags can be passed in AVCodecContext.flags before initialization. + Note: Not everything is supported yet. +*/ + +/** + * Allow decoders to produce frames with data planes that are not aligned + * to CPU requirements (e.g. due to cropping). + */ +#define AV_CODEC_FLAG_UNALIGNED (1 << 0) +/** + * Use fixed qscale. + */ +#define AV_CODEC_FLAG_QSCALE (1 << 1) +/** + * 4 MV per MB allowed / advanced prediction for H.263. + */ +#define AV_CODEC_FLAG_4MV (1 << 2) +/** + * Output even those frames that might be corrupted. + */ +#define AV_CODEC_FLAG_OUTPUT_CORRUPT (1 << 3) +/** + * Use qpel MC. + */ +#define AV_CODEC_FLAG_QPEL (1 << 4) +/** + * Don't output frames whose parameters differ from first + * decoded frame in stream. + */ +#define AV_CODEC_FLAG_DROPCHANGED (1 << 5) +/** + * Use internal 2pass ratecontrol in first pass mode. + */ +#define AV_CODEC_FLAG_PASS1 (1 << 9) +/** + * Use internal 2pass ratecontrol in second pass mode. + */ +#define AV_CODEC_FLAG_PASS2 (1 << 10) +/** + * loop filter. + */ +#define AV_CODEC_FLAG_LOOP_FILTER (1 << 11) +/** + * Only decode/encode grayscale. + */ +#define AV_CODEC_FLAG_GRAY (1 << 13) +/** + * error[?] variables will be set during encoding. + */ +#define AV_CODEC_FLAG_PSNR (1 << 15) +/** + * Input bitstream might be truncated at a random location + * instead of only at frame boundaries. + */ +#define AV_CODEC_FLAG_TRUNCATED (1 << 16) +/** + * Use interlaced DCT. + */ +#define AV_CODEC_FLAG_INTERLACED_DCT (1 << 18) +/** + * Force low delay. + */ +#define AV_CODEC_FLAG_LOW_DELAY (1 << 19) +/** + * Place global headers in extradata instead of every keyframe. + */ +#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22) +/** + * Use only bitexact stuff (except (I)DCT). + */ +#define AV_CODEC_FLAG_BITEXACT (1 << 23) +/* Fx : Flag for H.263+ extra options */ +/** + * H.263 advanced intra coding / MPEG-4 AC prediction + */ +#define AV_CODEC_FLAG_AC_PRED (1 << 24) +/** + * interlaced motion estimation + */ +#define AV_CODEC_FLAG_INTERLACED_ME (1 << 29) +#define AV_CODEC_FLAG_CLOSED_GOP (1U << 31) + +/** + * Allow non spec compliant speedup tricks. + */ +#define AV_CODEC_FLAG2_FAST (1 << 0) +/** + * Skip bitstream encoding. + */ +#define AV_CODEC_FLAG2_NO_OUTPUT (1 << 2) +/** + * Place global headers at every keyframe instead of in extradata. + */ +#define AV_CODEC_FLAG2_LOCAL_HEADER (1 << 3) + +/** + * timecode is in drop frame format. DEPRECATED!!!! + */ +#define AV_CODEC_FLAG2_DROP_FRAME_TIMECODE (1 << 13) + +/** + * Input bitstream might be truncated at a packet boundaries + * instead of only at frame boundaries. + */ +#define AV_CODEC_FLAG2_CHUNKS (1 << 15) +/** + * Discard cropping information from SPS. + */ +#define AV_CODEC_FLAG2_IGNORE_CROP (1 << 16) + +/** + * Show all frames before the first keyframe + */ +#define AV_CODEC_FLAG2_SHOW_ALL (1 << 22) +/** + * Export motion vectors through frame side data + */ +#define AV_CODEC_FLAG2_EXPORT_MVS (1 << 28) +/** + * Do not skip samples and export skip information as frame side data + */ +#define AV_CODEC_FLAG2_SKIP_MANUAL (1 << 29) +/** + * Do not reset ASS ReadOrder field on flush (subtitles decoding) + */ +#define AV_CODEC_FLAG2_RO_FLUSH_NOOP (1 << 30) + +/* Unsupported options : + * Syntax Arithmetic coding (SAC) + * Reference Picture Selection + * Independent Segment Decoding */ +/* /Fx */ +/* codec capabilities */ + +/* Exported side data. + These flags can be passed in AVCodecContext.export_side_data before initialization. +*/ +/** + * Export motion vectors through frame side data + */ +#define AV_CODEC_EXPORT_DATA_MVS (1 << 0) +/** + * Export encoder Producer Reference Time through packet side data + */ +#define AV_CODEC_EXPORT_DATA_PRFT (1 << 1) +/** + * Decoding only. + * Export the AVVideoEncParams structure through frame side data. + */ +#define AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS (1 << 2) +/** + * Decoding only. + * Do not apply film grain, export it instead. + */ +#define AV_CODEC_EXPORT_DATA_FILM_GRAIN (1 << 3) + +/** + * Pan Scan area. + * This specifies the area which should be displayed. + * Note there may be multiple such areas for one frame. + */ +typedef struct AVPanScan { + /** + * id + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int id; + + /** + * width and height in 1/16 pel + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int width; + int height; + + /** + * position of the top left corner in 1/16 pel for up to 3 fields/frames + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int16_t position[3][2]; +} AVPanScan; + +/** + * This structure describes the bitrate properties of an encoded bitstream. It + * roughly corresponds to a subset the VBV parameters for MPEG-2 or HRD + * parameters for H.264/HEVC. + */ +typedef struct AVCPBProperties { + /** + * Maximum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ +#if FF_API_UNSANITIZED_BITRATES + int max_bitrate; +#else + int64_t max_bitrate; +#endif + /** + * Minimum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ +#if FF_API_UNSANITIZED_BITRATES + int min_bitrate; +#else + int64_t min_bitrate; +#endif + /** + * Average bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ +#if FF_API_UNSANITIZED_BITRATES + int avg_bitrate; +#else + int64_t avg_bitrate; +#endif + + /** + * The size of the buffer to which the ratecontrol is applied, in bits. + * Zero if unknown or unspecified. + */ + int buffer_size; + + /** + * The delay between the time the packet this structure is associated with + * is received and the time when it should be decoded, in periods of a 27MHz + * clock. + * + * UINT64_MAX when unknown or unspecified. + */ + uint64_t vbv_delay; +} AVCPBProperties; + +/** + * This structure supplies correlation between a packet timestamp and a wall clock + * production time. The definition follows the Producer Reference Time ('prft') + * as defined in ISO/IEC 14496-12 + */ +typedef struct AVProducerReferenceTime { + /** + * A UTC timestamp, in microseconds, since Unix epoch (e.g, av_gettime()). + */ + int64_t wallclock; + int flags; +} AVProducerReferenceTime; + +/** + * The decoder will keep a reference to the frame and may reuse it later. + */ +#define AV_GET_BUFFER_FLAG_REF (1 << 0) + +/** + * The encoder will keep a reference to the packet and may reuse it later. + */ +#define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0) + +struct AVCodecInternal; + +/** + * main external API structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * You can use AVOptions (av_opt* / av_set/get*()) to access these fields from user + * applications. + * The name string for AVOptions options matches the associated command line + * parameter name and can be found in libavcodec/options_table.h + * The AVOption/command line parameter names differ in some cases from the C + * structure field names for historic reasons or brevity. + * sizeof(AVCodecContext) must not be used outside libav*. + */ +typedef struct AVCodecContext { + /** + * information on struct for av_log + * - set by avcodec_alloc_context3 + */ + const AVClass *av_class; + int log_level_offset; + + enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ + const struct AVCodec *codec; + enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ + + /** + * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * This is used to work around some encoder bugs. + * A demuxer should set this to what is stored in the field used to identify the codec. + * If there are multiple such fields in a container then the demuxer should choose the one + * which maximizes the information about the used codec. + * If the codec tag field in a container is larger than 32 bits then the demuxer should + * remap the longer ID to 32 bits with a table or other structure. Alternatively a new + * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated + * first. + * - encoding: Set by user, if not then the default based on codec_id will be used. + * - decoding: Set by user, will be converted to uppercase by libavcodec during init. + */ + unsigned int codec_tag; + + void *priv_data; + + /** + * Private context used for internal data. + * + * Unlike priv_data, this is not codec-specific. It is used in general + * libavcodec functions. + */ + struct AVCodecInternal *internal; + + /** + * Private data of the user, can be used to carry app specific stuff. + * - encoding: Set by user. + * - decoding: Set by user. + */ + void *opaque; + + /** + * the average bitrate + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: Set by user, may be overwritten by libavcodec + * if this info is available in the stream + */ + int64_t bit_rate; + + /** + * number of bits the bitstream is allowed to diverge from the reference. + * the reference can be CBR (for CBR pass1) or VBR (for pass2) + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: unused + */ + int bit_rate_tolerance; + + /** + * Global quality for codecs which cannot change it per frame. + * This should be proportional to MPEG-1/2/4 qscale. + * - encoding: Set by user. + * - decoding: unused + */ + int global_quality; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int compression_level; +#define FF_COMPRESSION_DEFAULT -1 + + /** + * AV_CODEC_FLAG_*. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags; + + /** + * AV_CODEC_FLAG2_* + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags2; + + /** + * some codecs need / can use extradata like Huffman tables. + * MJPEG: Huffman tables + * rv10: additional flags + * MPEG-4: global headers (they can be in the bitstream or here) + * The allocated memory should be AV_INPUT_BUFFER_PADDING_SIZE bytes larger + * than extradata_size to avoid problems if it is read with the bitstream reader. + * The bytewise contents of extradata must not depend on the architecture or CPU endianness. + * Must be allocated with the av_malloc() family of functions. + * - encoding: Set/allocated/freed by libavcodec. + * - decoding: Set/allocated/freed by user. + */ + uint8_t *extradata; + int extradata_size; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. For fixed-fps content, + * timebase should be 1/framerate and timestamp increments should be + * identically 1. + * This often, but not always is the inverse of the frame rate or field rate + * for video. 1/time_base is not the average frame rate if the frame rate is not + * constant. + * + * Like containers, elementary streams also can store timestamps, 1/time_base + * is the unit in which these timestamps are specified. + * As example of such codec time base see ISO/IEC 14496-2:2001(E) + * vop_time_increment_resolution and fixed_vop_rate + * (fixed_vop_rate == 0 implies that it is different from the framerate) + * + * - encoding: MUST be set by user. + * - decoding: the use of this field for decoding is deprecated. + * Use framerate instead. + */ + AVRational time_base; + + /** + * For some codecs, the time base is closer to the field rate than the frame rate. + * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration + * if no telecine is used ... + * + * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. + */ + int ticks_per_frame; + + /** + * Codec delay. + * + * Encoding: Number of frames delay there will be from the encoder input to + * the decoder output. (we assume the decoder matches the spec) + * Decoding: Number of frames delay in addition to what a standard decoder + * as specified in the spec would produce. + * + * Video: + * Number of frames the decoded output will be delayed relative to the + * encoded input. + * + * Audio: + * For encoding, this field is unused (see initial_padding). + * + * For decoding, this is the number of samples the decoder needs to + * output before the decoder's output is valid. When seeking, you should + * start decoding this many samples prior to your desired seek point. + * + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int delay; + + + /* video only */ + /** + * picture width / height. + * + * @note Those fields may not match the values of the last + * AVFrame output by avcodec_decode_video2 due frame + * reordering. + * + * - encoding: MUST be set by user. + * - decoding: May be set by the user before opening the decoder if known e.g. + * from the container. Some decoders will require the dimensions + * to be set by the caller. During decoding, the decoder may + * overwrite those values as required while parsing the data. + */ + int width, height; + + /** + * Bitstream width / height, may be different from width/height e.g. when + * the decoded frame is cropped before being output or lowres is enabled. + * + * @note Those field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: unused + * - decoding: May be set by the user before opening the decoder if known + * e.g. from the container. During decoding, the decoder may + * overwrite those values as required while parsing the data. + */ + int coded_width, coded_height; + + /** + * the number of pictures in a group of pictures, or 0 for intra_only + * - encoding: Set by user. + * - decoding: unused + */ + int gop_size; + + /** + * Pixel format, see AV_PIX_FMT_xxx. + * May be set by the demuxer if known from headers. + * May be overridden by the decoder if it knows better. + * + * @note This field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: Set by user. + * - decoding: Set by user if known, overridden by libavcodec while + * parsing the data. + */ + enum AVPixelFormat pix_fmt; + + /** + * If non NULL, 'draw_horiz_band' is called by the libavcodec + * decoder to draw a horizontal band. It improves cache usage. Not + * all codecs can do that. You must check the codec capabilities + * beforehand. + * When multithreading is used, it may be called from multiple threads + * at the same time; threads might draw different parts of the same AVFrame, + * or multiple AVFrames, and there is no guarantee that slices will be drawn + * in order. + * The function is also used by hardware acceleration APIs. + * It is called at least once during frame decoding to pass + * the data needed for hardware render. + * In that mode instead of pixel data, AVFrame points to + * a structure specific to the acceleration API. The application + * reads the structure and can change some fields to indicate progress + * or mark state. + * - encoding: unused + * - decoding: Set by user. + * @param height the height of the slice + * @param y the y position of the slice + * @param type 1->top field, 2->bottom field, 3->frame + * @param offset offset into the AVFrame.data from which the slice should be read + */ + void (*draw_horiz_band)(struct AVCodecContext *s, + const AVFrame *src, int offset[AV_NUM_DATA_POINTERS], + int y, int type, int height); + + /** + * callback to negotiate the pixelFormat + * @param fmt is the list of formats which are supported by the codec, + * it is terminated by -1 as 0 is a valid format, the formats are ordered by quality. + * The first is always the native one. + * @note The callback may be called again immediately if initialization for + * the selected (hardware-accelerated) pixel format failed. + * @warning Behavior is undefined if the callback returns a value not + * in the fmt list of formats. + * @return the chosen format + * - encoding: unused + * - decoding: Set by user, if not set the native format will be chosen. + */ + enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + + /** + * maximum number of B-frames between non-B-frames + * Note: The output will be delayed by max_b_frames+1 relative to the input. + * - encoding: Set by user. + * - decoding: unused + */ + int max_b_frames; + + /** + * qscale factor between IP and B-frames + * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_factor; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int b_frame_strategy; +#endif + + /** + * qscale offset between IP and B-frames + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_offset; + + /** + * Size of the frame reordering buffer in the decoder. + * For MPEG-2 it is 1 IPB or 0 low delay IP. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int has_b_frames; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int mpeg_quant; +#endif + + /** + * qscale factor between P- and I-frames + * If > 0 then the last P-frame quantizer will be used (q = lastp_q * factor + offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_factor; + + /** + * qscale offset between P and I-frames + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_offset; + + /** + * luminance masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float lumi_masking; + + /** + * temporary complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float temporal_cplx_masking; + + /** + * spatial complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float spatial_cplx_masking; + + /** + * p block masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float p_masking; + + /** + * darkness masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float dark_masking; + + /** + * slice count + * - encoding: Set by libavcodec. + * - decoding: Set by user (or 0). + */ + int slice_count; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int prediction_method; +#define FF_PRED_LEFT 0 +#define FF_PRED_PLANE 1 +#define FF_PRED_MEDIAN 2 +#endif + + /** + * slice offsets in the frame in bytes + * - encoding: Set/allocated by libavcodec. + * - decoding: Set/allocated by user (or NULL). + */ + int *slice_offset; + + /** + * sample aspect ratio (0 if unknown) + * That is the width of a pixel divided by the height of the pixel. + * Numerator and denominator must be relatively prime and smaller than 256 for some video standards. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVRational sample_aspect_ratio; + + /** + * motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_cmp; + /** + * subpixel motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_sub_cmp; + /** + * macroblock comparison function (not supported yet) + * - encoding: Set by user. + * - decoding: unused + */ + int mb_cmp; + /** + * interlaced DCT comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int ildct_cmp; +#define FF_CMP_SAD 0 +#define FF_CMP_SSE 1 +#define FF_CMP_SATD 2 +#define FF_CMP_DCT 3 +#define FF_CMP_PSNR 4 +#define FF_CMP_BIT 5 +#define FF_CMP_RD 6 +#define FF_CMP_ZERO 7 +#define FF_CMP_VSAD 8 +#define FF_CMP_VSSE 9 +#define FF_CMP_NSSE 10 +#define FF_CMP_W53 11 +#define FF_CMP_W97 12 +#define FF_CMP_DCTMAX 13 +#define FF_CMP_DCT264 14 +#define FF_CMP_MEDIAN_SAD 15 +#define FF_CMP_CHROMA 256 + + /** + * ME diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int dia_size; + + /** + * amount of previous MV predictors (2a+1 x 2a+1 square) + * - encoding: Set by user. + * - decoding: unused + */ + int last_predictor_count; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int pre_me; +#endif + + /** + * motion estimation prepass comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_pre_cmp; + + /** + * ME prepass diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int pre_dia_size; + + /** + * subpel ME quality + * - encoding: Set by user. + * - decoding: unused + */ + int me_subpel_quality; + + /** + * maximum motion estimation search range in subpel units + * If 0 then no limit. + * + * - encoding: Set by user. + * - decoding: unused + */ + int me_range; + + /** + * slice flags + * - encoding: unused + * - decoding: Set by user. + */ + int slice_flags; +#define SLICE_FLAG_CODED_ORDER 0x0001 ///< draw_horiz_band() is called in coded order instead of display +#define SLICE_FLAG_ALLOW_FIELD 0x0002 ///< allow draw_horiz_band() with field slices (MPEG-2 field pics) +#define SLICE_FLAG_ALLOW_PLANE 0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1) + + /** + * macroblock decision mode + * - encoding: Set by user. + * - decoding: unused + */ + int mb_decision; +#define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp +#define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits +#define FF_MB_DECISION_RD 2 ///< rate distortion + + /** + * custom intra quantization matrix + * Must be allocated with the av_malloc() family of functions, and will be freed in + * avcodec_free_context(). + * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL. + * - decoding: Set/allocated/freed by libavcodec. + */ + uint16_t *intra_matrix; + + /** + * custom inter quantization matrix + * Must be allocated with the av_malloc() family of functions, and will be freed in + * avcodec_free_context(). + * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL. + * - decoding: Set/allocated/freed by libavcodec. + */ + uint16_t *inter_matrix; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int scenechange_threshold; + + /** @deprecated use encoder private options instead */ + attribute_deprecated + int noise_reduction; +#endif + + /** + * precision of the intra DC coefficient - 8 + * - encoding: Set by user. + * - decoding: Set by libavcodec + */ + int intra_dc_precision; + + /** + * Number of macroblock rows at the top which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_top; + + /** + * Number of macroblock rows at the bottom which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_bottom; + + /** + * minimum MB Lagrange multiplier + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmin; + + /** + * maximum MB Lagrange multiplier + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmax; + +#if FF_API_PRIVATE_OPT + /** + * @deprecated use encoder private options instead + */ + attribute_deprecated + int me_penalty_compensation; +#endif + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int bidir_refine; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int brd_scale; +#endif + + /** + * minimum GOP size + * - encoding: Set by user. + * - decoding: unused + */ + int keyint_min; + + /** + * number of reference frames + * - encoding: Set by user. + * - decoding: Set by lavc. + */ + int refs; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int chromaoffset; +#endif + + /** + * Note: Value depends upon the compare function used for fullpel ME. + * - encoding: Set by user. + * - decoding: unused + */ + int mv0_threshold; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int b_sensitivity; +#endif + + /** + * Chromaticity coordinates of the source primaries. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorPrimaries color_primaries; + + /** + * Color Transfer Characteristic. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorRange color_range; + + /** + * This defines the location of chroma samples. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVChromaLocation chroma_sample_location; + + /** + * Number of slices. + * Indicates number of picture subdivisions. Used for parallelized + * decoding. + * - encoding: Set by user + * - decoding: unused + */ + int slices; + + /** Field order + * - encoding: set by libavcodec + * - decoding: Set by user. + */ + enum AVFieldOrder field_order; + + /* audio only */ + int sample_rate; ///< samples per second + int channels; ///< number of audio channels + + /** + * audio sample format + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVSampleFormat sample_fmt; ///< sample format + + /* The following data should not be initialized. */ + /** + * Number of samples per channel in an audio frame. + * + * - encoding: set by libavcodec in avcodec_open2(). Each submitted frame + * except the last must contain exactly frame_size samples per channel. + * May be 0 when the codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE set, then the + * frame size is not restricted. + * - decoding: may be set by some decoders to indicate constant frame size + */ + int frame_size; + + /** + * Frame counter, set by libavcodec. + * + * - decoding: total number of frames returned from the decoder so far. + * - encoding: total number of frames passed to the encoder so far. + * + * @note the counter is not incremented if encoding/decoding resulted in + * an error. + */ + int frame_number; + + /** + * number of bytes per packet if constant and known or 0 + * Used by some WAV based audio codecs. + */ + int block_align; + + /** + * Audio cutoff bandwidth (0 means "automatic") + * - encoding: Set by user. + * - decoding: unused + */ + int cutoff; + + /** + * Audio channel layout. + * - encoding: set by user. + * - decoding: set by user, may be overwritten by libavcodec. + */ + uint64_t channel_layout; + + /** + * Request decoder to use this channel layout if it can (0 for default) + * - encoding: unused + * - decoding: Set by user. + */ + uint64_t request_channel_layout; + + /** + * Type of service that the audio stream conveys. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVAudioServiceType audio_service_type; + + /** + * desired sample format + * - encoding: Not used. + * - decoding: Set by user. + * Decoder will decode to this format if it can. + */ + enum AVSampleFormat request_sample_fmt; + + /** + * This callback is called at the beginning of each frame to get data + * buffer(s) for it. There may be one contiguous buffer for all the data or + * there may be a buffer per each data plane or anything in between. What + * this means is, you may set however many entries in buf[] you feel necessary. + * Each buffer must be reference-counted using the AVBuffer API (see description + * of buf[] below). + * + * The following fields will be set in the frame before this callback is + * called: + * - format + * - width, height (video only) + * - sample_rate, channel_layout, nb_samples (audio only) + * Their values may differ from the corresponding values in + * AVCodecContext. This callback must use the frame values, not the codec + * context values, to calculate the required buffer size. + * + * This callback must fill the following fields in the frame: + * - data[] + * - linesize[] + * - extended_data: + * * if the data is planar audio with more than 8 channels, then this + * callback must allocate and fill extended_data to contain all pointers + * to all data planes. data[] must hold as many pointers as it can. + * extended_data must be allocated with av_malloc() and will be freed in + * av_frame_unref(). + * * otherwise extended_data must point to data + * - buf[] must contain one or more pointers to AVBufferRef structures. Each of + * the frame's data and extended_data pointers must be contained in these. That + * is, one AVBufferRef for each allocated chunk of memory, not necessarily one + * AVBufferRef per data[] entry. See: av_buffer_create(), av_buffer_alloc(), + * and av_buffer_ref(). + * - extended_buf and nb_extended_buf must be allocated with av_malloc() by + * this callback and filled with the extra buffers if there are more + * buffers than buf[] can hold. extended_buf will be freed in + * av_frame_unref(). + * + * If AV_CODEC_CAP_DR1 is not set then get_buffer2() must call + * avcodec_default_get_buffer2() instead of providing buffers allocated by + * some other means. + * + * Each data plane must be aligned to the maximum required by the target + * CPU. + * + * @see avcodec_default_get_buffer2() + * + * Video: + * + * If AV_GET_BUFFER_FLAG_REF is set in flags then the frame may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * avcodec_align_dimensions2() should be used to find the required width and + * height, as they normally need to be rounded up to the next multiple of 16. + * + * Some decoders do not support linesizes changing between frames. + * + * If frame multithreading is used, this callback may be called from a + * different thread, but not from more than one at once. Does not need to be + * reentrant. + * + * @see avcodec_align_dimensions2() + * + * Audio: + * + * Decoders request a buffer of a particular size by setting + * AVFrame.nb_samples prior to calling get_buffer2(). The decoder may, + * however, utilize only part of the buffer by setting AVFrame.nb_samples + * to a smaller value in the output frame. + * + * As a convenience, av_samples_get_buffer_size() and + * av_samples_fill_arrays() in libavutil may be used by custom get_buffer2() + * functions to find the required data size and to fill data pointers and + * linesize. In AVFrame.linesize, only linesize[0] may be set for audio + * since all planes must be the same size. + * + * @see av_samples_get_buffer_size(), av_samples_fill_arrays() + * + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + */ + int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags); + +#if FF_API_OLD_ENCDEC + /** + * If non-zero, the decoded audio and video frames returned from + * avcodec_decode_video2() and avcodec_decode_audio4() are reference-counted + * and are valid indefinitely. The caller must free them with + * av_frame_unref() when they are not needed anymore. + * Otherwise, the decoded frames must not be freed by the caller and are + * only valid until the next decode call. + * + * This is always automatically enabled if avcodec_receive_frame() is used. + * + * - encoding: unused + * - decoding: set by the caller before avcodec_open2(). + */ + attribute_deprecated + int refcounted_frames; +#endif + + /* - encoding parameters */ + float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0) + float qblur; ///< amount of qscale smoothing over time (0.0-1.0) + + /** + * minimum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmin; + + /** + * maximum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmax; + + /** + * maximum quantizer difference between frames + * - encoding: Set by user. + * - decoding: unused + */ + int max_qdiff; + + /** + * decoder bitstream buffer size + * - encoding: Set by user. + * - decoding: unused + */ + int rc_buffer_size; + + /** + * ratecontrol override, see RcOverride + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + int rc_override_count; + RcOverride *rc_override; + + /** + * maximum bitrate + * - encoding: Set by user. + * - decoding: Set by user, may be overwritten by libavcodec. + */ + int64_t rc_max_rate; + + /** + * minimum bitrate + * - encoding: Set by user. + * - decoding: unused + */ + int64_t rc_min_rate; + + /** + * Ratecontrol attempt to use, at maximum, of what can be used without an underflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_max_available_vbv_use; + + /** + * Ratecontrol attempt to use, at least, times the amount needed to prevent a vbv overflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_min_vbv_overflow_use; + + /** + * Number of bits which should be loaded into the rc buffer before decoding starts. + * - encoding: Set by user. + * - decoding: unused + */ + int rc_initial_buffer_occupancy; + +#if FF_API_CODER_TYPE +#define FF_CODER_TYPE_VLC 0 +#define FF_CODER_TYPE_AC 1 +#define FF_CODER_TYPE_RAW 2 +#define FF_CODER_TYPE_RLE 3 + /** + * @deprecated use encoder private options instead + */ + attribute_deprecated + int coder_type; +#endif /* FF_API_CODER_TYPE */ + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int context_model; +#endif + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int frame_skip_threshold; + + /** @deprecated use encoder private options instead */ + attribute_deprecated + int frame_skip_factor; + + /** @deprecated use encoder private options instead */ + attribute_deprecated + int frame_skip_exp; + + /** @deprecated use encoder private options instead */ + attribute_deprecated + int frame_skip_cmp; +#endif /* FF_API_PRIVATE_OPT */ + + /** + * trellis RD quantization + * - encoding: Set by user. + * - decoding: unused + */ + int trellis; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int min_prediction_order; + + /** @deprecated use encoder private options instead */ + attribute_deprecated + int max_prediction_order; + + /** @deprecated use encoder private options instead */ + attribute_deprecated + int64_t timecode_frame_start; +#endif + +#if FF_API_RTP_CALLBACK + /** + * @deprecated unused + */ + /* The RTP callback: This function is called */ + /* every time the encoder has a packet to send. */ + /* It depends on the encoder if the data starts */ + /* with a Start Code (it should). H.263 does. */ + /* mb_nb contains the number of macroblocks */ + /* encoded in the RTP payload. */ + attribute_deprecated + void (*rtp_callback)(struct AVCodecContext *avctx, void *data, int size, int mb_nb); +#endif + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int rtp_payload_size; /* The size of the RTP payload: the coder will */ + /* do its best to deliver a chunk with size */ + /* below rtp_payload_size, the chunk will start */ + /* with a start code on some codecs like H.263. */ + /* This doesn't take account of any particular */ + /* headers inside the transmitted RTP payload. */ +#endif + +#if FF_API_STAT_BITS + /* statistics, used for 2-pass encoding */ + attribute_deprecated + int mv_bits; + attribute_deprecated + int header_bits; + attribute_deprecated + int i_tex_bits; + attribute_deprecated + int p_tex_bits; + attribute_deprecated + int i_count; + attribute_deprecated + int p_count; + attribute_deprecated + int skip_count; + attribute_deprecated + int misc_bits; + + /** @deprecated this field is unused */ + attribute_deprecated + int frame_bits; +#endif + + /** + * pass1 encoding statistics output buffer + * - encoding: Set by libavcodec. + * - decoding: unused + */ + char *stats_out; + + /** + * pass2 encoding statistics input buffer + * Concatenated stuff from stats_out of pass1 should be placed here. + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + char *stats_in; + + /** + * Work around bugs in encoders which sometimes cannot be detected automatically. + * - encoding: Set by user + * - decoding: Set by user + */ + int workaround_bugs; +#define FF_BUG_AUTODETECT 1 ///< autodetection +#define FF_BUG_XVID_ILACE 4 +#define FF_BUG_UMP4 8 +#define FF_BUG_NO_PADDING 16 +#define FF_BUG_AMV 32 +#define FF_BUG_QPEL_CHROMA 64 +#define FF_BUG_STD_QPEL 128 +#define FF_BUG_QPEL_CHROMA2 256 +#define FF_BUG_DIRECT_BLOCKSIZE 512 +#define FF_BUG_EDGE 1024 +#define FF_BUG_HPEL_CHROMA 2048 +#define FF_BUG_DC_CLIP 4096 +#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders. +#define FF_BUG_TRUNCATED 16384 +#define FF_BUG_IEDGE 32768 + + /** + * strictly follow the standard (MPEG-4, ...). + * - encoding: Set by user. + * - decoding: Set by user. + * Setting this to STRICT or higher means the encoder and decoder will + * generally do stupid things, whereas setting it to unofficial or lower + * will mean the encoder might produce output that is not supported by all + * spec-compliant decoders. Decoders don't differentiate between normal, + * unofficial and experimental (that is, they always try to decode things + * when they can) unless they are explicitly asked to behave stupidly + * (=strictly conform to the specs) + */ + int strict_std_compliance; +#define FF_COMPLIANCE_VERY_STRICT 2 ///< Strictly conform to an older more strict version of the spec or reference software. +#define FF_COMPLIANCE_STRICT 1 ///< Strictly conform to all the things in the spec no matter what consequences. +#define FF_COMPLIANCE_NORMAL 0 +#define FF_COMPLIANCE_UNOFFICIAL -1 ///< Allow unofficial extensions +#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things. + + /** + * error concealment flags + * - encoding: unused + * - decoding: Set by user. + */ + int error_concealment; +#define FF_EC_GUESS_MVS 1 +#define FF_EC_DEBLOCK 2 +#define FF_EC_FAVOR_INTER 256 + + /** + * debug + * - encoding: Set by user. + * - decoding: Set by user. + */ + int debug; +#define FF_DEBUG_PICT_INFO 1 +#define FF_DEBUG_RC 2 +#define FF_DEBUG_BITSTREAM 4 +#define FF_DEBUG_MB_TYPE 8 +#define FF_DEBUG_QP 16 +#define FF_DEBUG_DCT_COEFF 0x00000040 +#define FF_DEBUG_SKIP 0x00000080 +#define FF_DEBUG_STARTCODE 0x00000100 +#define FF_DEBUG_ER 0x00000400 +#define FF_DEBUG_MMCO 0x00000800 +#define FF_DEBUG_BUGS 0x00001000 +#define FF_DEBUG_BUFFERS 0x00008000 +#define FF_DEBUG_THREADS 0x00010000 +#define FF_DEBUG_GREEN_MD 0x00800000 +#define FF_DEBUG_NOMC 0x01000000 + + /** + * Error recognition; may misdetect some more or less valid parts as errors. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int err_recognition; + +/** + * Verify checksums embedded in the bitstream (could be of either encoded or + * decoded data, depending on the codec) and print an error message on mismatch. + * If AV_EF_EXPLODE is also set, a mismatching checksum will result in the + * decoder returning an error. + */ +#define AV_EF_CRCCHECK (1<<0) +#define AV_EF_BITSTREAM (1<<1) ///< detect bitstream specification deviations +#define AV_EF_BUFFER (1<<2) ///< detect improper bitstream length +#define AV_EF_EXPLODE (1<<3) ///< abort decoding on minor error detection + +#define AV_EF_IGNORE_ERR (1<<15) ///< ignore errors and continue +#define AV_EF_CAREFUL (1<<16) ///< consider things that violate the spec, are fast to calculate and have not been seen in the wild as errors +#define AV_EF_COMPLIANT (1<<17) ///< consider all spec non compliances as errors +#define AV_EF_AGGRESSIVE (1<<18) ///< consider things that a sane encoder should not do as an error + + + /** + * opaque 64-bit number (generally a PTS) that will be reordered and + * output in AVFrame.reordered_opaque + * - encoding: Set by libavcodec to the reordered_opaque of the input + * frame corresponding to the last returned packet. Only + * supported by encoders with the + * AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability. + * - decoding: Set by user. + */ + int64_t reordered_opaque; + + /** + * Hardware accelerator in use + * - encoding: unused. + * - decoding: Set by libavcodec + */ + const struct AVHWAccel *hwaccel; + + /** + * Hardware accelerator context. + * For some hardware accelerators, a global context needs to be + * provided by the user. In that case, this holds display-dependent + * data FFmpeg cannot instantiate itself. Please refer to the + * FFmpeg HW accelerator documentation to know how to fill this + * is. e.g. for VA API, this is a struct vaapi_context. + * - encoding: unused + * - decoding: Set by user + */ + void *hwaccel_context; + + /** + * error + * - encoding: Set by libavcodec if flags & AV_CODEC_FLAG_PSNR. + * - decoding: unused + */ + uint64_t error[AV_NUM_DATA_POINTERS]; + + /** + * DCT algorithm, see FF_DCT_* below + * - encoding: Set by user. + * - decoding: unused + */ + int dct_algo; +#define FF_DCT_AUTO 0 +#define FF_DCT_FASTINT 1 +#define FF_DCT_INT 2 +#define FF_DCT_MMX 3 +#define FF_DCT_ALTIVEC 5 +#define FF_DCT_FAAN 6 + + /** + * IDCT algorithm, see FF_IDCT_* below. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int idct_algo; +#define FF_IDCT_AUTO 0 +#define FF_IDCT_INT 1 +#define FF_IDCT_SIMPLE 2 +#define FF_IDCT_SIMPLEMMX 3 +#define FF_IDCT_ARM 7 +#define FF_IDCT_ALTIVEC 8 +#define FF_IDCT_SIMPLEARM 10 +#define FF_IDCT_XVID 14 +#define FF_IDCT_SIMPLEARMV5TE 16 +#define FF_IDCT_SIMPLEARMV6 17 +#define FF_IDCT_FAAN 20 +#define FF_IDCT_SIMPLENEON 22 +#define FF_IDCT_NONE 24 /* Used by XvMC to extract IDCT coefficients with FF_IDCT_PERM_NONE */ +#define FF_IDCT_SIMPLEAUTO 128 + + /** + * bits per sample/pixel from the demuxer (needed for huffyuv). + * - encoding: Set by libavcodec. + * - decoding: Set by user. + */ + int bits_per_coded_sample; + + /** + * Bits per sample/pixel of internal libavcodec pixel/sample format. + * - encoding: set by user. + * - decoding: set by libavcodec. + */ + int bits_per_raw_sample; + + /** + * low resolution decoding, 1-> 1/2 size, 2->1/4 size + * - encoding: unused + * - decoding: Set by user. + */ + int lowres; + +#if FF_API_CODED_FRAME + /** + * the picture in the bitstream + * - encoding: Set by libavcodec. + * - decoding: unused + * + * @deprecated use the quality factor packet side data instead + */ + attribute_deprecated AVFrame *coded_frame; +#endif + + /** + * thread count + * is used to decide how many independent tasks should be passed to execute() + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_count; + + /** + * Which multithreading methods to use. + * Use of FF_THREAD_FRAME will increase decoding delay by one frame per thread, + * so clients which cannot provide future frames should not use it. + * + * - encoding: Set by user, otherwise the default is used. + * - decoding: Set by user, otherwise the default is used. + */ + int thread_type; +#define FF_THREAD_FRAME 1 ///< Decode more than one frame at once +#define FF_THREAD_SLICE 2 ///< Decode more than one part of a single frame at once + + /** + * Which multithreading methods are in use by the codec. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int active_thread_type; + +#if FF_API_THREAD_SAFE_CALLBACKS + /** + * Set by the client if its custom get_buffer() callback can be called + * synchronously from another thread, which allows faster multithreaded decoding. + * draw_horiz_band() will be called from other threads regardless of this setting. + * Ignored if the default get_buffer() is used. + * - encoding: Set by user. + * - decoding: Set by user. + * + * @deprecated the custom get_buffer2() callback should always be + * thread-safe. Thread-unsafe get_buffer2() implementations will be + * invalid starting with LIBAVCODEC_VERSION_MAJOR=60; in other words, + * libavcodec will behave as if this field was always set to 1. + * Callers that want to be forward compatible with future libavcodec + * versions should wrap access to this field in + * #if LIBAVCODEC_VERSION_MAJOR < 60 + */ + attribute_deprecated + int thread_safe_callbacks; +#endif + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param count the number of things to execute + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size); + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * Also see avcodec_thread_init and e.g. the --enable-pthread configure option. + * @param c context passed also to func + * @param count the number of things to execute + * @param arg2 argument passed unchanged to func + * @param ret return values of executed functions, must have space for "count" values. May be NULL. + * @param func function that will be called count times, with jobnr from 0 to count-1. + * threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no + * two instances of func executing at the same time will have the same threadnr. + * @return always 0 currently, but code should handle a future improvement where when any call to func + * returns < 0 no further calls to func may be done and < 0 is returned. + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count); + + /** + * noise vs. sse weight for the nsse comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int nsse_weight; + + /** + * profile + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int profile; +#define FF_PROFILE_UNKNOWN -99 +#define FF_PROFILE_RESERVED -100 + +#define FF_PROFILE_AAC_MAIN 0 +#define FF_PROFILE_AAC_LOW 1 +#define FF_PROFILE_AAC_SSR 2 +#define FF_PROFILE_AAC_LTP 3 +#define FF_PROFILE_AAC_HE 4 +#define FF_PROFILE_AAC_HE_V2 28 +#define FF_PROFILE_AAC_LD 22 +#define FF_PROFILE_AAC_ELD 38 +#define FF_PROFILE_MPEG2_AAC_LOW 128 +#define FF_PROFILE_MPEG2_AAC_HE 131 + +#define FF_PROFILE_DNXHD 0 +#define FF_PROFILE_DNXHR_LB 1 +#define FF_PROFILE_DNXHR_SQ 2 +#define FF_PROFILE_DNXHR_HQ 3 +#define FF_PROFILE_DNXHR_HQX 4 +#define FF_PROFILE_DNXHR_444 5 + +#define FF_PROFILE_DTS 20 +#define FF_PROFILE_DTS_ES 30 +#define FF_PROFILE_DTS_96_24 40 +#define FF_PROFILE_DTS_HD_HRA 50 +#define FF_PROFILE_DTS_HD_MA 60 +#define FF_PROFILE_DTS_EXPRESS 70 + +#define FF_PROFILE_MPEG2_422 0 +#define FF_PROFILE_MPEG2_HIGH 1 +#define FF_PROFILE_MPEG2_SS 2 +#define FF_PROFILE_MPEG2_SNR_SCALABLE 3 +#define FF_PROFILE_MPEG2_MAIN 4 +#define FF_PROFILE_MPEG2_SIMPLE 5 + +#define FF_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag +#define FF_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag + +#define FF_PROFILE_H264_BASELINE 66 +#define FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED) +#define FF_PROFILE_H264_MAIN 77 +#define FF_PROFILE_H264_EXTENDED 88 +#define FF_PROFILE_H264_HIGH 100 +#define FF_PROFILE_H264_HIGH_10 110 +#define FF_PROFILE_H264_HIGH_10_INTRA (110|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_MULTIVIEW_HIGH 118 +#define FF_PROFILE_H264_HIGH_422 122 +#define FF_PROFILE_H264_HIGH_422_INTRA (122|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_STEREO_HIGH 128 +#define FF_PROFILE_H264_HIGH_444 144 +#define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244 +#define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_CAVLC_444 44 + +#define FF_PROFILE_VC1_SIMPLE 0 +#define FF_PROFILE_VC1_MAIN 1 +#define FF_PROFILE_VC1_COMPLEX 2 +#define FF_PROFILE_VC1_ADVANCED 3 + +#define FF_PROFILE_MPEG4_SIMPLE 0 +#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE 1 +#define FF_PROFILE_MPEG4_CORE 2 +#define FF_PROFILE_MPEG4_MAIN 3 +#define FF_PROFILE_MPEG4_N_BIT 4 +#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE 5 +#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6 +#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7 +#define FF_PROFILE_MPEG4_HYBRID 8 +#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME 9 +#define FF_PROFILE_MPEG4_CORE_SCALABLE 10 +#define FF_PROFILE_MPEG4_ADVANCED_CODING 11 +#define FF_PROFILE_MPEG4_ADVANCED_CORE 12 +#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13 +#define FF_PROFILE_MPEG4_SIMPLE_STUDIO 14 +#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE 15 + +#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 1 +#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 2 +#define FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION 32768 +#define FF_PROFILE_JPEG2000_DCINEMA_2K 3 +#define FF_PROFILE_JPEG2000_DCINEMA_4K 4 + +#define FF_PROFILE_VP9_0 0 +#define FF_PROFILE_VP9_1 1 +#define FF_PROFILE_VP9_2 2 +#define FF_PROFILE_VP9_3 3 + +#define FF_PROFILE_HEVC_MAIN 1 +#define FF_PROFILE_HEVC_MAIN_10 2 +#define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 +#define FF_PROFILE_HEVC_REXT 4 + +#define FF_PROFILE_VVC_MAIN_10 1 +#define FF_PROFILE_VVC_MAIN_10_444 33 + +#define FF_PROFILE_AV1_MAIN 0 +#define FF_PROFILE_AV1_HIGH 1 +#define FF_PROFILE_AV1_PROFESSIONAL 2 + +#define FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT 0xc0 +#define FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1 +#define FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT 0xc2 +#define FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3 +#define FF_PROFILE_MJPEG_JPEG_LS 0xf7 + +#define FF_PROFILE_SBC_MSBC 1 + +#define FF_PROFILE_PRORES_PROXY 0 +#define FF_PROFILE_PRORES_LT 1 +#define FF_PROFILE_PRORES_STANDARD 2 +#define FF_PROFILE_PRORES_HQ 3 +#define FF_PROFILE_PRORES_4444 4 +#define FF_PROFILE_PRORES_XQ 5 + +#define FF_PROFILE_ARIB_PROFILE_A 0 +#define FF_PROFILE_ARIB_PROFILE_C 1 + +#define FF_PROFILE_KLVA_SYNC 0 +#define FF_PROFILE_KLVA_ASYNC 1 + + /** + * level + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int level; +#define FF_LEVEL_UNKNOWN -99 + + /** + * Skip loop filtering for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_loop_filter; + + /** + * Skip IDCT/dequantization for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_idct; + + /** + * Skip decoding for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_frame; + + /** + * Header containing style information for text subtitles. + * For SUBTITLE_ASS subtitle type, it should contain the whole ASS + * [Script Info] and [V4+ Styles] section, plus the [Events] line and + * the Format line following. It shouldn't include any Dialogue line. + * - encoding: Set/allocated/freed by user (before avcodec_open2()) + * - decoding: Set/allocated/freed by libavcodec (by avcodec_open2()) + */ + uint8_t *subtitle_header; + int subtitle_header_size; + +#if FF_API_VBV_DELAY + /** + * VBV delay coded in the last frame (in periods of a 27 MHz clock). + * Used for compliant TS muxing. + * - encoding: Set by libavcodec. + * - decoding: unused. + * @deprecated this value is now exported as a part of + * AV_PKT_DATA_CPB_PROPERTIES packet side data + */ + attribute_deprecated + uint64_t vbv_delay; +#endif + +#if FF_API_SIDEDATA_ONLY_PKT + /** + * Encoding only and set by default. Allow encoders to output packets + * that do not contain any encoded data, only side data. + * + * Some encoders need to output such packets, e.g. to update some stream + * parameters at the end of encoding. + * + * @deprecated this field disables the default behaviour and + * it is kept only for compatibility. + */ + attribute_deprecated + int side_data_only_packets; +#endif + + /** + * Audio only. The number of "priming" samples (padding) inserted by the + * encoder at the beginning of the audio. I.e. this number of leading + * decoded samples must be discarded by the caller to get the original audio + * without leading padding. + * + * - decoding: unused + * - encoding: Set by libavcodec. The timestamps on the output packets are + * adjusted by the encoder so that they always refer to the + * first sample of the data actually contained in the packet, + * including any added padding. E.g. if the timebase is + * 1/samplerate and the timestamp of the first input sample is + * 0, the timestamp of the first output packet will be + * -initial_padding. + */ + int initial_padding; + + /** + * - decoding: For codecs that store a framerate value in the compressed + * bitstream, the decoder may export it here. { 0, 1} when + * unknown. + * - encoding: May be used to signal the framerate of CFR content to an + * encoder. + */ + AVRational framerate; + + /** + * Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx. + * - encoding: unused. + * - decoding: Set by libavcodec before calling get_format() + */ + enum AVPixelFormat sw_pix_fmt; + + /** + * Timebase in which pkt_dts/pts and AVPacket.dts/pts are. + * - encoding unused. + * - decoding set by user. + */ + AVRational pkt_timebase; + + /** + * AVCodecDescriptor + * - encoding: unused. + * - decoding: set by libavcodec. + */ + const AVCodecDescriptor *codec_descriptor; + + /** + * Current statistics for PTS correction. + * - decoding: maintained and used by libavcodec, not intended to be used by user apps + * - encoding: unused + */ + int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far + int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far + int64_t pts_correction_last_pts; /// PTS of the last frame + int64_t pts_correction_last_dts; /// DTS of the last frame + + /** + * Character encoding of the input subtitles file. + * - decoding: set by user + * - encoding: unused + */ + char *sub_charenc; + + /** + * Subtitles character encoding mode. Formats or codecs might be adjusting + * this setting (if they are doing the conversion themselves for instance). + * - decoding: set by libavcodec + * - encoding: unused + */ + int sub_charenc_mode; +#define FF_SUB_CHARENC_MODE_DO_NOTHING -1 ///< do nothing (demuxer outputs a stream supposed to be already in UTF-8, or the codec is bitmap for instance) +#define FF_SUB_CHARENC_MODE_AUTOMATIC 0 ///< libavcodec will select the mode itself +#define FF_SUB_CHARENC_MODE_PRE_DECODER 1 ///< the AVPacket data needs to be recoded to UTF-8 before being fed to the decoder, requires iconv +#define FF_SUB_CHARENC_MODE_IGNORE 2 ///< neither convert the subtitles, nor check them for valid UTF-8 + + /** + * Skip processing alpha if supported by codec. + * Note that if the format uses pre-multiplied alpha (common with VP6, + * and recommended due to better video quality/compression) + * the image will look as if alpha-blended onto a black background. + * However for formats that do not use pre-multiplied alpha + * there might be serious artefacts (though e.g. libswscale currently + * assumes pre-multiplied alpha anyway). + * + * - decoding: set by user + * - encoding: unused + */ + int skip_alpha; + + /** + * Number of samples to skip after a discontinuity + * - decoding: unused + * - encoding: set by libavcodec + */ + int seek_preroll; + +#if FF_API_DEBUG_MV + /** + * @deprecated unused + */ + attribute_deprecated + int debug_mv; +#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 //visualize forward predicted MVs of P frames +#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 //visualize forward predicted MVs of B frames +#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames +#endif + + /** + * custom intra quantization matrix + * - encoding: Set by user, can be NULL. + * - decoding: unused. + */ + uint16_t *chroma_intra_matrix; + + /** + * dump format separator. + * can be ", " or "\n " or anything else + * - encoding: Set by user. + * - decoding: Set by user. + */ + uint8_t *dump_separator; + + /** + * ',' separated list of allowed decoders. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *codec_whitelist; + + /** + * Properties of the stream that gets decoded + * - encoding: unused + * - decoding: set by libavcodec + */ + unsigned properties; +#define FF_CODEC_PROPERTY_LOSSLESS 0x00000001 +#define FF_CODEC_PROPERTY_CLOSED_CAPTIONS 0x00000002 + + /** + * Additional data associated with the entire coded stream. + * + * - decoding: unused + * - encoding: may be set by libavcodec after avcodec_open2(). + */ + AVPacketSideData *coded_side_data; + int nb_coded_side_data; + + /** + * A reference to the AVHWFramesContext describing the input (for encoding) + * or output (decoding) frames. The reference is set by the caller and + * afterwards owned (and freed) by libavcodec - it should never be read by + * the caller after being set. + * + * - decoding: This field should be set by the caller from the get_format() + * callback. The previous reference (if any) will always be + * unreffed by libavcodec before the get_format() call. + * + * If the default get_buffer2() is used with a hwaccel pixel + * format, then this AVHWFramesContext will be used for + * allocating the frame buffers. + * + * - encoding: For hardware encoders configured to use a hwaccel pixel + * format, this field should be set by the caller to a reference + * to the AVHWFramesContext describing input frames. + * AVHWFramesContext.format must be equal to + * AVCodecContext.pix_fmt. + * + * This field should be set before avcodec_open2() is called. + */ + AVBufferRef *hw_frames_ctx; + + /** + * Control the form of AVSubtitle.rects[N]->ass + * - decoding: set by user + * - encoding: unused + */ + int sub_text_format; +#define FF_SUB_TEXT_FMT_ASS 0 +#if FF_API_ASS_TIMING +#define FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS 1 +#endif + + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + * + * - decoding: unused + * - encoding: unused + */ + int trailing_padding; + + /** + * The number of pixels per image to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_pixels; + + /** + * A reference to the AVHWDeviceContext describing the device which will + * be used by a hardware encoder/decoder. The reference is set by the + * caller and afterwards owned (and freed) by libavcodec. + * + * This should be used if either the codec device does not require + * hardware frames or any that are used are to be allocated internally by + * libavcodec. If the user wishes to supply any of the frames used as + * encoder input or decoder output then hw_frames_ctx should be used + * instead. When hw_frames_ctx is set in get_format() for a decoder, this + * field will be ignored while decoding the associated stream segment, but + * may again be used on a following one after another get_format() call. + * + * For both encoders and decoders this field should be set before + * avcodec_open2() is called and must not be written to thereafter. + * + * Note that some decoders may require this field to be set initially in + * order to support hw_frames_ctx at all - in that case, all frames + * contexts used must be created on the same device. + */ + AVBufferRef *hw_device_ctx; + + /** + * Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated + * decoding (if active). + * - encoding: unused + * - decoding: Set by user (either before avcodec_open2(), or in the + * AVCodecContext.get_format callback) + */ + int hwaccel_flags; + + /** + * Video decoding only. Certain video codecs support cropping, meaning that + * only a sub-rectangle of the decoded frame is intended for display. This + * option controls how cropping is handled by libavcodec. + * + * When set to 1 (the default), libavcodec will apply cropping internally. + * I.e. it will modify the output frame width/height fields and offset the + * data pointers (only by as much as possible while preserving alignment, or + * by the full amount if the AV_CODEC_FLAG_UNALIGNED flag is set) so that + * the frames output by the decoder refer only to the cropped area. The + * crop_* fields of the output frames will be zero. + * + * When set to 0, the width/height fields of the output frames will be set + * to the coded dimensions and the crop_* fields will describe the cropping + * rectangle. Applying the cropping is left to the caller. + * + * @warning When hardware acceleration with opaque output frames is used, + * libavcodec is unable to apply cropping from the top/left border. + * + * @note when this option is set to zero, the width/height fields of the + * AVCodecContext and output AVFrames have different meanings. The codec + * context fields store display dimensions (with the coded dimensions in + * coded_width/height), while the frame fields store the coded dimensions + * (with the display dimensions being determined by the crop_* fields). + */ + int apply_cropping; + + /* + * Video decoding only. Sets the number of extra hardware frames which + * the decoder will allocate for use by the caller. This must be set + * before avcodec_open2() is called. + * + * Some hardware decoders require all frames that they will use for + * output to be defined in advance before decoding starts. For such + * decoders, the hardware frame pool must therefore be of a fixed size. + * The extra frames set here are on top of any number that the decoder + * needs internally in order to operate normally (for example, frames + * used as reference pictures). + */ + int extra_hw_frames; + + /** + * The percentage of damaged samples to discard a frame. + * + * - decoding: set by user + * - encoding: unused + */ + int discard_damaged_percentage; + + /** + * The number of samples per frame to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_samples; + + /** + * Bit set of AV_CODEC_EXPORT_DATA_* flags, which affects the kind of + * metadata exported in frame, packet, or coded stream side data by + * decoders and encoders. + * + * - decoding: set by user + * - encoding: set by user + */ + int export_side_data; + + /** + * This callback is called at the beginning of each packet to get a data + * buffer for it. + * + * The following field will be set in the packet before this callback is + * called: + * - size + * This callback must use the above value to calculate the required buffer size, + * which must padded by at least AV_INPUT_BUFFER_PADDING_SIZE bytes. + * + * This callback must fill the following fields in the packet: + * - data: alignment requirements for AVPacket apply, if any. Some architectures and + * encoders may benefit from having aligned data. + * - buf: must contain a pointer to an AVBufferRef structure. The packet's + * data pointer must be contained in it. See: av_buffer_create(), av_buffer_alloc(), + * and av_buffer_ref(). + * + * If AV_CODEC_CAP_DR1 is not set then get_encode_buffer() must call + * avcodec_default_get_encode_buffer() instead of providing a buffer allocated by + * some other means. + * + * The flags field may contain a combination of AV_GET_ENCODE_BUFFER_FLAG_ flags. + * They may be used for example to hint what use the buffer may get after being + * created. + * Implementations of this callback may ignore flags they don't understand. + * If AV_GET_ENCODE_BUFFER_FLAG_REF is set in flags then the packet may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * This callback must be thread-safe, as when frame threading is used, it may + * be called from multiple threads simultaneously. + * + * @see avcodec_default_get_encode_buffer() + * + * - encoding: Set by libavcodec, user can override. + * - decoding: unused + */ + int (*get_encode_buffer)(struct AVCodecContext *s, AVPacket *pkt, int flags); +} AVCodecContext; + +#if FF_API_CODEC_GET_SET +/** + * Accessors for some AVCodecContext fields. These used to be provided for ABI + * compatibility, and do not need to be used anymore. + */ +attribute_deprecated +AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); +attribute_deprecated +void av_codec_set_pkt_timebase (AVCodecContext *avctx, AVRational val); + +attribute_deprecated +const AVCodecDescriptor *av_codec_get_codec_descriptor(const AVCodecContext *avctx); +attribute_deprecated +void av_codec_set_codec_descriptor(AVCodecContext *avctx, const AVCodecDescriptor *desc); + +attribute_deprecated +unsigned av_codec_get_codec_properties(const AVCodecContext *avctx); + +attribute_deprecated +int av_codec_get_lowres(const AVCodecContext *avctx); +attribute_deprecated +void av_codec_set_lowres(AVCodecContext *avctx, int val); + +attribute_deprecated +int av_codec_get_seek_preroll(const AVCodecContext *avctx); +attribute_deprecated +void av_codec_set_seek_preroll(AVCodecContext *avctx, int val); + +attribute_deprecated +uint16_t *av_codec_get_chroma_intra_matrix(const AVCodecContext *avctx); +attribute_deprecated +void av_codec_set_chroma_intra_matrix(AVCodecContext *avctx, uint16_t *val); +#endif + +struct AVSubtitle; + +#if FF_API_CODEC_GET_SET +attribute_deprecated +int av_codec_get_max_lowres(const AVCodec *codec); +#endif + +struct MpegEncContext; + +/** + * @defgroup lavc_hwaccel AVHWAccel + * + * @note Nothing in this structure should be accessed by the user. At some + * point in future it will not be externally visible at all. + * + * @{ + */ +typedef struct AVHWAccel { + /** + * Name of the hardware accelerated codec. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + */ + const char *name; + + /** + * Type of codec implemented by the hardware accelerator. + * + * See AVMEDIA_TYPE_xxx + */ + enum AVMediaType type; + + /** + * Codec implemented by the hardware accelerator. + * + * See AV_CODEC_ID_xxx + */ + enum AVCodecID id; + + /** + * Supported pixel format. + * + * Only hardware accelerated formats are supported here. + */ + enum AVPixelFormat pix_fmt; + + /** + * Hardware accelerated codec capabilities. + * see AV_HWACCEL_CODEC_CAP_* + */ + int capabilities; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavcodec and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + + /** + * Allocate a custom buffer + */ + int (*alloc_frame)(AVCodecContext *avctx, AVFrame *frame); + + /** + * Called at the beginning of each frame or field picture. + * + * Meaningful frame information (codec specific) is guaranteed to + * be parsed at this point. This function is mandatory. + * + * Note that buf can be NULL along with buf_size set to 0. + * Otherwise, this means the whole frame is available at this point. + * + * @param avctx the codec context + * @param buf the frame data buffer base + * @param buf_size the size of the frame in bytes + * @return zero if successful, a negative value otherwise + */ + int (*start_frame)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size); + + /** + * Callback for parameter data (SPS/PPS/VPS etc). + * + * Useful for hardware decoders which keep persistent state about the + * video parameters, and need to receive any changes to update that state. + * + * @param avctx the codec context + * @param type the nal unit type + * @param buf the nal unit data buffer + * @param buf_size the size of the nal unit in bytes + * @return zero if successful, a negative value otherwise + */ + int (*decode_params)(AVCodecContext *avctx, int type, const uint8_t *buf, uint32_t buf_size); + + /** + * Callback for each slice. + * + * Meaningful slice information (codec specific) is guaranteed to + * be parsed at this point. This function is mandatory. + * The only exception is XvMC, that works on MB level. + * + * @param avctx the codec context + * @param buf the slice data buffer base + * @param buf_size the size of the slice in bytes + * @return zero if successful, a negative value otherwise + */ + int (*decode_slice)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size); + + /** + * Called at the end of each frame or field picture. + * + * The whole picture is parsed at this point and can now be sent + * to the hardware accelerator. This function is mandatory. + * + * @param avctx the codec context + * @return zero if successful, a negative value otherwise + */ + int (*end_frame)(AVCodecContext *avctx); + + /** + * Size of per-frame hardware accelerator private data. + * + * Private data is allocated with av_mallocz() before + * AVCodecContext.get_buffer() and deallocated after + * AVCodecContext.release_buffer(). + */ + int frame_priv_data_size; + + /** + * Called for every Macroblock in a slice. + * + * XvMC uses it to replace the ff_mpv_reconstruct_mb(). + * Instead of decoding to raw picture, MB parameters are + * stored in an array provided by the video driver. + * + * @param s the mpeg context + */ + void (*decode_mb)(struct MpegEncContext *s); + + /** + * Initialize the hwaccel private data. + * + * This will be called from ff_get_format(), after hwaccel and + * hwaccel_context are set and the hwaccel private data in AVCodecInternal + * is allocated. + */ + int (*init)(AVCodecContext *avctx); + + /** + * Uninitialize the hwaccel private data. + * + * This will be called from get_format() or avcodec_close(), after hwaccel + * and hwaccel_context are already uninitialized. + */ + int (*uninit)(AVCodecContext *avctx); + + /** + * Size of the private data to allocate in + * AVCodecInternal.hwaccel_priv_data. + */ + int priv_data_size; + + /** + * Internal hwaccel capabilities. + */ + int caps_internal; + + /** + * Fill the given hw_frames context with current codec parameters. Called + * from get_format. Refer to avcodec_get_hw_frames_parameters() for + * details. + * + * This CAN be called before AVHWAccel.init is called, and you must assume + * that avctx->hwaccel_priv_data is invalid. + */ + int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); +} AVHWAccel; + +/** + * HWAccel is experimental and is thus avoided in favor of non experimental + * codecs + */ +#define AV_HWACCEL_CODEC_CAP_EXPERIMENTAL 0x0200 + +/** + * Hardware acceleration should be used for decoding even if the codec level + * used is unknown or higher than the maximum supported level reported by the + * hardware driver. + * + * It's generally a good idea to pass this flag unless you have a specific + * reason not to, as hardware tends to under-report supported levels. + */ +#define AV_HWACCEL_FLAG_IGNORE_LEVEL (1 << 0) + +/** + * Hardware acceleration can output YUV pixel formats with a different chroma + * sampling than 4:2:0 and/or other than 8 bits per component. + */ +#define AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH (1 << 1) + +/** + * Hardware acceleration should still be attempted for decoding when the + * codec profile does not match the reported capabilities of the hardware. + * + * For example, this can be used to try to decode baseline profile H.264 + * streams in hardware - it will often succeed, because many streams marked + * as baseline profile actually conform to constrained baseline profile. + * + * @warning If the stream is actually not supported then the behaviour is + * undefined, and may include returning entirely incorrect output + * while indicating success. + */ +#define AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH (1 << 2) + +/** + * @} + */ + +#if FF_API_AVPICTURE +/** + * @defgroup lavc_picture AVPicture + * + * Functions for working with AVPicture + * @{ + */ + +/** + * Picture data structure. + * + * Up to four components can be stored into it, the last component is + * alpha. + * @deprecated use AVFrame or imgutils functions instead + */ +typedef struct AVPicture { + attribute_deprecated + uint8_t *data[AV_NUM_DATA_POINTERS]; ///< pointers to the image data planes + attribute_deprecated + int linesize[AV_NUM_DATA_POINTERS]; ///< number of bytes per line +} AVPicture; + +/** + * @} + */ +#endif + +enum AVSubtitleType { + SUBTITLE_NONE, + + SUBTITLE_BITMAP, ///< A bitmap, pict will be set + + /** + * Plain text, the text field must be set by the decoder and is + * authoritative. ass and pict fields may contain approximations. + */ + SUBTITLE_TEXT, + + /** + * Formatted text, the ass field must be set by the decoder and is + * authoritative. pict and text fields may contain approximations. + */ + SUBTITLE_ASS, +}; + +#define AV_SUBTITLE_FLAG_FORCED 0x00000001 + +typedef struct AVSubtitleRect { + int x; ///< top left corner of pict, undefined when pict is not set + int y; ///< top left corner of pict, undefined when pict is not set + int w; ///< width of pict, undefined when pict is not set + int h; ///< height of pict, undefined when pict is not set + int nb_colors; ///< number of colors in pict, undefined when pict is not set + +#if FF_API_AVPICTURE + /** + * @deprecated unused + */ + attribute_deprecated + AVPicture pict; +#endif + /** + * data+linesize for the bitmap of this subtitle. + * Can be set for text/ass as well once they are rendered. + */ + uint8_t *data[4]; + int linesize[4]; + + enum AVSubtitleType type; + + char *text; ///< 0 terminated plain UTF-8 text + + /** + * 0 terminated ASS/SSA compatible event line. + * The presentation of this is unaffected by the other values in this + * struct. + */ + char *ass; + + int flags; +} AVSubtitleRect; + +typedef struct AVSubtitle { + uint16_t format; /* 0 = graphics */ + uint32_t start_display_time; /* relative to packet pts, in ms */ + uint32_t end_display_time; /* relative to packet pts, in ms */ + unsigned num_rects; + AVSubtitleRect **rects; + int64_t pts; ///< Same as packet pts, in AV_TIME_BASE +} AVSubtitle; + +#if FF_API_NEXT +/** + * If c is NULL, returns the first registered codec, + * if c is non-NULL, returns the next registered codec after c, + * or NULL if c is the last one. + */ +attribute_deprecated +AVCodec *av_codec_next(const AVCodec *c); +#endif + +/** + * Return the LIBAVCODEC_VERSION_INT constant. + */ +unsigned avcodec_version(void); + +/** + * Return the libavcodec build-time configuration. + */ +const char *avcodec_configuration(void); + +/** + * Return the libavcodec license. + */ +const char *avcodec_license(void); + +#if FF_API_NEXT +/** + * @deprecated Calling this function is unnecessary. + */ +attribute_deprecated +void avcodec_register(AVCodec *codec); + +/** + * @deprecated Calling this function is unnecessary. + */ +attribute_deprecated +void avcodec_register_all(void); +#endif + +/** + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct should be freed with avcodec_free_context(). + * + * @param codec if non-NULL, allocate private data and initialize defaults + * for the given codec. It is illegal to then call avcodec_open2() + * with a different codec. + * If NULL, then the codec-specific defaults won't be initialized, + * which may result in suboptimal default settings (this is + * important mainly for encoders, e.g. libx264). + * + * @return An AVCodecContext filled with default values or NULL on failure. + */ +AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); + +/** + * Free the codec context and everything associated with it and write NULL to + * the provided pointer. + */ +void avcodec_free_context(AVCodecContext **avctx); + +#if FF_API_GET_CONTEXT_DEFAULTS +/** + * @deprecated This function should not be used, as closing and opening a codec + * context multiple time is not supported. A new codec context should be + * allocated for each new use. + */ +int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec); +#endif + +/** + * Get the AVClass for AVCodecContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_class(void); + +#if FF_API_GET_FRAME_CLASS +/** + * @deprecated This function should not be used. + */ +attribute_deprecated +const AVClass *avcodec_get_frame_class(void); +#endif + +/** + * Get the AVClass for AVSubtitleRect. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_subtitle_rect_class(void); + +#if FF_API_COPY_CONTEXT +/** + * Copy the settings of the source AVCodecContext into the destination + * AVCodecContext. The resulting destination codec context will be + * unopened, i.e. you are required to call avcodec_open2() before you + * can use this AVCodecContext to decode/encode video/audio data. + * + * @param dest target codec context, should be initialized with + * avcodec_alloc_context3(NULL), but otherwise uninitialized + * @param src source codec context + * @return AVERROR() on error (e.g. memory allocation error), 0 on success + * + * @deprecated The semantics of this function are ill-defined and it should not + * be used. If you need to transfer the stream parameters from one codec context + * to another, use an intermediate AVCodecParameters instance and the + * avcodec_parameters_from_context() / avcodec_parameters_to_context() + * functions. + */ +attribute_deprecated +int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src); +#endif + +/** + * Fill the parameters struct based on the values from the supplied codec + * context. Any allocated fields in par are freed and replaced with duplicates + * of the corresponding fields in codec. + * + * @return >= 0 on success, a negative AVERROR code on failure + */ +int avcodec_parameters_from_context(AVCodecParameters *par, + const AVCodecContext *codec); + +/** + * Fill the codec context based on the values from the supplied codec + * parameters. Any allocated fields in codec that have a corresponding field in + * par are freed and replaced with duplicates of the corresponding field in par. + * Fields in codec that do not have a counterpart in par are not touched. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_to_context(AVCodecContext *codec, + const AVCodecParameters *par); + +/** + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated with avcodec_alloc_context3(). + * + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. + * + * @warning This function is not thread safe! + * + * @note Always call this function before using decoding routines (such as + * @ref avcodec_receive_frame()). + * + * @code + * av_dict_set(&opts, "b", "2.5M", 0); + * codec = avcodec_find_decoder(AV_CODEC_ID_H264); + * if (!codec) + * exit(1); + * + * context = avcodec_alloc_context3(codec); + * + * if (avcodec_open2(context, codec, opts) < 0) + * exit(1); + * @endcode + * + * @param avctx The context to initialize. + * @param codec The codec to open this context for. If a non-NULL codec has been + * previously passed to avcodec_alloc_context3() or + * for this context, then this parameter MUST be either NULL or + * equal to the previously passed codec. + * @param options A dictionary filled with AVCodecContext and codec-private options. + * On return this object will be filled with options that were not found. + * + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), + * av_dict_set(), av_opt_find(). + */ +int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); + +/** + * Close a given AVCodecContext and free all the data associated with it + * (but not the AVCodecContext itself). + * + * Calling this function on an AVCodecContext that hasn't been opened will free + * the codec-specific data allocated in avcodec_alloc_context3() with a non-NULL + * codec. Subsequent calls will do nothing. + * + * @note Do not use this function. Use avcodec_free_context() to destroy a + * codec context (either open or closed). Opening and closing a codec context + * multiple times is not supported anymore -- use multiple codec contexts + * instead. + */ +int avcodec_close(AVCodecContext *avctx); + +/** + * Free all allocated data in the given subtitle struct. + * + * @param sub AVSubtitle to free. + */ +void avsubtitle_free(AVSubtitle *sub); + +/** + * @} + */ + +/** + * @addtogroup lavc_decoding + * @{ + */ + +/** + * The default callback for AVCodecContext.get_buffer2(). It is made public so + * it can be called by custom get_buffer2() implementations for decoders without + * AV_CODEC_CAP_DR1 set. + */ +int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags); + +/** + * The default callback for AVCodecContext.get_encode_buffer(). It is made public so + * it can be called by custom get_encode_buffer() implementations for encoders without + * AV_CODEC_CAP_DR1 set. + */ +int avcodec_default_get_encode_buffer(AVCodecContext *s, AVPacket *pkt, int flags); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you do not use any horizontal + * padding. + * + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. + */ +void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you also ensure that all + * line sizes are a multiple of the respective linesize_align[i]. + * + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. + */ +void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, + int linesize_align[AV_NUM_DATA_POINTERS]); + +/** + * Converts AVChromaLocation to swscale x/y chroma position. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + */ +int avcodec_enum_to_chroma_pos(int *xpos, int *ypos, enum AVChromaLocation pos); + +/** + * Converts swscale x/y chroma position to AVChromaLocation. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + */ +enum AVChromaLocation avcodec_chroma_pos_to_enum(int xpos, int ypos); + +#if FF_API_OLD_ENCDEC +/** + * Decode the audio frame of size avpkt->size from avpkt->data into frame. + * + * Some decoders may support multiple frames in a single AVPacket. Such + * decoders would then just decode the first frame and the return value would be + * less than the packet size. In this case, avcodec_decode_audio4 has to be + * called again with an AVPacket containing the remaining data in order to + * decode the second frame, etc... Even if no frames are returned, the packet + * needs to be fed to the decoder with remaining data until it is completely + * consumed or an error occurs. + * + * Some decoders (those marked with AV_CODEC_CAP_DELAY) have a delay between input + * and output. This means that for some packets they will not immediately + * produce decoded output and need to be flushed at the end of decoding to get + * all the decoded data. Flushing is done by calling this function with packets + * with avpkt->data set to NULL and avpkt->size set to 0 until it stops + * returning samples. It is safe to flush even those decoders that are not + * marked with AV_CODEC_CAP_DELAY, then no samples will be returned. + * + * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE + * larger than the actual read bytes because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx the codec context + * @param[out] frame The AVFrame in which to store decoded audio samples. + * The decoder will allocate a buffer for the decoded frame by + * calling the AVCodecContext.get_buffer2() callback. + * When AVCodecContext.refcounted_frames is set to 1, the frame is + * reference counted and the returned reference belongs to the + * caller. The caller must release the frame using av_frame_unref() + * when the frame is no longer needed. The caller may safely write + * to the frame if av_frame_is_writable() returns 1. + * When AVCodecContext.refcounted_frames is set to 0, the returned + * reference belongs to the decoder and is valid only until the + * next call to this function or until closing or flushing the + * decoder. The caller may not write to it. + * @param[out] got_frame_ptr Zero if no frame could be decoded, otherwise it is + * non-zero. Note that this field being set to zero + * does not mean that an error has occurred. For + * decoders with AV_CODEC_CAP_DELAY set, no given decode + * call is guaranteed to produce a frame. + * @param[in] avpkt The input AVPacket containing the input buffer. + * At least avpkt->data and avpkt->size should be set. Some + * decoders might also require additional fields to be set. + * @return A negative error code is returned if an error occurred during + * decoding, otherwise the number of bytes consumed from the input + * AVPacket is returned. + * +* @deprecated Use avcodec_send_packet() and avcodec_receive_frame(). + */ +attribute_deprecated +int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, const AVPacket *avpkt); + +/** + * Decode the video frame of size avpkt->size from avpkt->data into picture. + * Some decoders may support multiple frames in a single AVPacket, such + * decoders would then just decode the first frame. + * + * @warning The input buffer must be AV_INPUT_BUFFER_PADDING_SIZE larger than + * the actual read bytes because some optimized bitstream readers read 32 or 64 + * bits at once and could read over the end. + * + * @warning The end of the input buffer buf should be set to 0 to ensure that + * no overreading happens for damaged MPEG streams. + * + * @note Codecs which have the AV_CODEC_CAP_DELAY capability set have a delay + * between input and output, these need to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to return the remaining frames. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx the codec context + * @param[out] picture The AVFrame in which the decoded video frame will be stored. + * Use av_frame_alloc() to get an AVFrame. The codec will + * allocate memory for the actual bitmap by calling the + * AVCodecContext.get_buffer2() callback. + * When AVCodecContext.refcounted_frames is set to 1, the frame is + * reference counted and the returned reference belongs to the + * caller. The caller must release the frame using av_frame_unref() + * when the frame is no longer needed. The caller may safely write + * to the frame if av_frame_is_writable() returns 1. + * When AVCodecContext.refcounted_frames is set to 0, the returned + * reference belongs to the decoder and is valid only until the + * next call to this function or until closing or flushing the + * decoder. The caller may not write to it. + * + * @param[in] avpkt The input AVPacket containing the input buffer. + * You can create such packet with av_init_packet() and by then setting + * data and size, some decoders might in addition need other fields like + * flags&AV_PKT_FLAG_KEY. All decoders are designed to use the least + * fields possible. + * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero. + * @return On error a negative value is returned, otherwise the number of bytes + * used or zero if no frame could be decompressed. + * + * @deprecated Use avcodec_send_packet() and avcodec_receive_frame(). + */ +attribute_deprecated +int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, + int *got_picture_ptr, + const AVPacket *avpkt); +#endif + +/** + * Decode a subtitle message. + * Return a negative value on error, otherwise return the number of bytes used. + * If no subtitle could be decompressed, got_sub_ptr is zero. + * Otherwise, the subtitle is stored in *sub. + * Note that AV_CODEC_CAP_DR1 is not available for subtitle codecs. This is for + * simplicity, because the performance difference is expected to be negligible + * and reusing a get_buffer written for video codecs would probably perform badly + * due to a potentially very different allocation pattern. + * + * Some decoders (those marked with AV_CODEC_CAP_DELAY) have a delay between input + * and output. This means that for some packets they will not immediately + * produce decoded output and need to be flushed at the end of decoding to get + * all the decoded data. Flushing is done by calling this function with packets + * with avpkt->data set to NULL and avpkt->size set to 0 until it stops + * returning subtitles. It is safe to flush even those decoders that are not + * marked with AV_CODEC_CAP_DELAY, then no subtitles will be returned. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx the codec context + * @param[out] sub The preallocated AVSubtitle in which the decoded subtitle will be stored, + * must be freed with avsubtitle_free if *got_sub_ptr is set. + * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. + * @param[in] avpkt The input AVPacket containing the input buffer. + */ +int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, + AVPacket *avpkt); + +/** + * Supply raw packet data as input to a decoder. + * + * Internally, this call will copy relevant AVCodecContext fields, which can + * influence decoding per-packet, and apply them when the packet is actually + * decoded. (For example AVCodecContext.skip_frame, which might direct the + * decoder to drop the frame contained by the packet sent with this function.) + * + * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE + * larger than the actual read bytes because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end. + * + * @warning Do not mix this API with the legacy API (like avcodec_decode_video2()) + * on the same AVCodecContext. It will return unexpected results now + * or in future libavcodec versions. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx codec context + * @param[in] avpkt The input AVPacket. Usually, this will be a single video + * frame, or several complete audio frames. + * Ownership of the packet remains with the caller, and the + * decoder will not write to the packet. The decoder may create + * a reference to the packet data (or copy it if the packet is + * not reference-counted). + * Unlike with older APIs, the packet is always fully consumed, + * and if it contains multiple frames (e.g. some audio codecs), + * will require you to call avcodec_receive_frame() multiple + * times afterwards before you can send a new packet. + * It can be NULL (or an AVPacket with data set to NULL and + * size set to 0); in this case, it is considered a flush + * packet, which signals the end of the stream. Sending the + * first flush packet will return success. Subsequent ones are + * unnecessary and will return AVERROR_EOF. If the decoder + * still has frames buffered, it will return them after sending + * a flush packet. + * + * @return 0 on success, otherwise negative error code: + * AVERROR(EAGAIN): input is not accepted in the current state - user + * must read output with avcodec_receive_frame() (once + * all output is read, the packet should be resent, and + * the call will not fail with EAGAIN). + * AVERROR_EOF: the decoder has been flushed, and no new packets can + * be sent to it (also returned if more than 1 flush + * packet is sent) + * AVERROR(EINVAL): codec not opened, it is an encoder, or requires flush + * AVERROR(ENOMEM): failed to add packet to internal queue, or similar + * other errors: legitimate decoding errors + */ +int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); + +/** + * Return decoded output data from a decoder. + * + * @param avctx codec context + * @param frame This will be set to a reference-counted video or audio + * frame (depending on the decoder type) allocated by the + * decoder. Note that the function will always call + * av_frame_unref(frame) before doing anything else. + * + * @return + * 0: success, a frame was returned + * AVERROR(EAGAIN): output is not available in this state - user must try + * to send new input + * AVERROR_EOF: the decoder has been fully flushed, and there will be + * no more output frames + * AVERROR(EINVAL): codec not opened, or it is an encoder + * AVERROR_INPUT_CHANGED: current decoded frame has changed parameters + * with respect to first decoded frame. Applicable + * when flag AV_CODEC_FLAG_DROPCHANGED is set. + * other negative values: legitimate decoding errors + */ +int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); + +/** + * Supply a raw video or audio frame to the encoder. Use avcodec_receive_packet() + * to retrieve buffered output packets. + * + * @param avctx codec context + * @param[in] frame AVFrame containing the raw audio or video frame to be encoded. + * Ownership of the frame remains with the caller, and the + * encoder will not write to the frame. The encoder may create + * a reference to the frame data (or copy it if the frame is + * not reference-counted). + * It can be NULL, in which case it is considered a flush + * packet. This signals the end of the stream. If the encoder + * still has packets buffered, it will return them after this + * call. Once flushing mode has been entered, additional flush + * packets are ignored, and sending frames will return + * AVERROR_EOF. + * + * For audio: + * If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * can have any number of samples. + * If it is not set, frame->nb_samples must be equal to + * avctx->frame_size for all frames except the last. + * The final frame may be smaller than avctx->frame_size. + * @return 0 on success, otherwise negative error code: + * AVERROR(EAGAIN): input is not accepted in the current state - user + * must read output with avcodec_receive_packet() (once + * all output is read, the packet should be resent, and + * the call will not fail with EAGAIN). + * AVERROR_EOF: the encoder has been flushed, and no new frames can + * be sent to it + * AVERROR(EINVAL): codec not opened, refcounted_frames not set, it is a + * decoder, or requires flush + * AVERROR(ENOMEM): failed to add packet to internal queue, or similar + * other errors: legitimate encoding errors + */ +int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); + +/** + * Read encoded data from the encoder. + * + * @param avctx codec context + * @param avpkt This will be set to a reference-counted packet allocated by the + * encoder. Note that the function will always call + * av_packet_unref(avpkt) before doing anything else. + * @return 0 on success, otherwise negative error code: + * AVERROR(EAGAIN): output is not available in the current state - user + * must try to send input + * AVERROR_EOF: the encoder has been fully flushed, and there will be + * no more output packets + * AVERROR(EINVAL): codec not opened, or it is a decoder + * other errors: legitimate encoding errors + */ +int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); + +/** + * Create and return a AVHWFramesContext with values adequate for hardware + * decoding. This is meant to get called from the get_format callback, and is + * a helper for preparing a AVHWFramesContext for AVCodecContext.hw_frames_ctx. + * This API is for decoding with certain hardware acceleration modes/APIs only. + * + * The returned AVHWFramesContext is not initialized. The caller must do this + * with av_hwframe_ctx_init(). + * + * Calling this function is not a requirement, but makes it simpler to avoid + * codec or hardware API specific details when manually allocating frames. + * + * Alternatively to this, an API user can set AVCodecContext.hw_device_ctx, + * which sets up AVCodecContext.hw_frames_ctx fully automatically, and makes + * it unnecessary to call this function or having to care about + * AVHWFramesContext initialization at all. + * + * There are a number of requirements for calling this function: + * + * - It must be called from get_format with the same avctx parameter that was + * passed to get_format. Calling it outside of get_format is not allowed, and + * can trigger undefined behavior. + * - The function is not always supported (see description of return values). + * Even if this function returns successfully, hwaccel initialization could + * fail later. (The degree to which implementations check whether the stream + * is actually supported varies. Some do this check only after the user's + * get_format callback returns.) + * - The hw_pix_fmt must be one of the choices suggested by get_format. If the + * user decides to use a AVHWFramesContext prepared with this API function, + * the user must return the same hw_pix_fmt from get_format. + * - The device_ref passed to this function must support the given hw_pix_fmt. + * - After calling this API function, it is the user's responsibility to + * initialize the AVHWFramesContext (returned by the out_frames_ref parameter), + * and to set AVCodecContext.hw_frames_ctx to it. If done, this must be done + * before returning from get_format (this is implied by the normal + * AVCodecContext.hw_frames_ctx API rules). + * - The AVHWFramesContext parameters may change every time time get_format is + * called. Also, AVCodecContext.hw_frames_ctx is reset before get_format. So + * you are inherently required to go through this process again on every + * get_format call. + * - It is perfectly possible to call this function without actually using + * the resulting AVHWFramesContext. One use-case might be trying to reuse a + * previously initialized AVHWFramesContext, and calling this API function + * only to test whether the required frame parameters have changed. + * - Fields that use dynamically allocated values of any kind must not be set + * by the user unless setting them is explicitly allowed by the documentation. + * If the user sets AVHWFramesContext.free and AVHWFramesContext.user_opaque, + * the new free callback must call the potentially set previous free callback. + * This API call may set any dynamically allocated fields, including the free + * callback. + * + * The function will set at least the following fields on AVHWFramesContext + * (potentially more, depending on hwaccel API): + * + * - All fields set by av_hwframe_ctx_alloc(). + * - Set the format field to hw_pix_fmt. + * - Set the sw_format field to the most suited and most versatile format. (An + * implication is that this will prefer generic formats over opaque formats + * with arbitrary restrictions, if possible.) + * - Set the width/height fields to the coded frame size, rounded up to the + * API-specific minimum alignment. + * - Only _if_ the hwaccel requires a pre-allocated pool: set the initial_pool_size + * field to the number of maximum reference surfaces possible with the codec, + * plus 1 surface for the user to work (meaning the user can safely reference + * at most 1 decoded surface at a time), plus additional buffering introduced + * by frame threading. If the hwaccel does not require pre-allocation, the + * field is left to 0, and the decoder will allocate new surfaces on demand + * during decoding. + * - Possibly AVHWFramesContext.hwctx fields, depending on the underlying + * hardware API. + * + * Essentially, out_frames_ref returns the same as av_hwframe_ctx_alloc(), but + * with basic frame parameters set. + * + * The function is stateless, and does not change the AVCodecContext or the + * device_ref AVHWDeviceContext. + * + * @param avctx The context which is currently calling get_format, and which + * implicitly contains all state needed for filling the returned + * AVHWFramesContext properly. + * @param device_ref A reference to the AVHWDeviceContext describing the device + * which will be used by the hardware decoder. + * @param hw_pix_fmt The hwaccel format you are going to return from get_format. + * @param out_frames_ref On success, set to a reference to an _uninitialized_ + * AVHWFramesContext, created from the given device_ref. + * Fields will be set to values required for decoding. + * Not changed if an error is returned. + * @return zero on success, a negative value on error. The following error codes + * have special semantics: + * AVERROR(ENOENT): the decoder does not support this functionality. Setup + * is always manual, or it is a decoder which does not + * support setting AVCodecContext.hw_frames_ctx at all, + * or it is a software format. + * AVERROR(EINVAL): it is known that hardware decoding is not supported for + * this configuration, or the device_ref is not supported + * for the hwaccel referenced by hw_pix_fmt. + */ +int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, + AVBufferRef *device_ref, + enum AVPixelFormat hw_pix_fmt, + AVBufferRef **out_frames_ref); + + + +/** + * @defgroup lavc_parsing Frame parsing + * @{ + */ + +enum AVPictureStructure { + AV_PICTURE_STRUCTURE_UNKNOWN, //< unknown + AV_PICTURE_STRUCTURE_TOP_FIELD, //< coded as top field + AV_PICTURE_STRUCTURE_BOTTOM_FIELD, //< coded as bottom field + AV_PICTURE_STRUCTURE_FRAME, //< coded as frame +}; + +typedef struct AVCodecParserContext { + void *priv_data; + struct AVCodecParser *parser; + int64_t frame_offset; /* offset of the current frame */ + int64_t cur_offset; /* current offset + (incremented by each av_parser_parse()) */ + int64_t next_frame_offset; /* offset of the next frame */ + /* video info */ + int pict_type; /* XXX: Put it back in AVCodecContext. */ + /** + * This field is used for proper frame duration computation in lavf. + * It signals, how much longer the frame duration of the current frame + * is compared to normal frame duration. + * + * frame_duration = (1 + repeat_pict) * time_base + * + * It is used by codecs like H.264 to display telecined material. + */ + int repeat_pict; /* XXX: Put it back in AVCodecContext. */ + int64_t pts; /* pts of the current frame */ + int64_t dts; /* dts of the current frame */ + + /* private data */ + int64_t last_pts; + int64_t last_dts; + int fetch_timestamp; + +#define AV_PARSER_PTS_NB 4 + int cur_frame_start_index; + int64_t cur_frame_offset[AV_PARSER_PTS_NB]; + int64_t cur_frame_pts[AV_PARSER_PTS_NB]; + int64_t cur_frame_dts[AV_PARSER_PTS_NB]; + + int flags; +#define PARSER_FLAG_COMPLETE_FRAMES 0x0001 +#define PARSER_FLAG_ONCE 0x0002 +/// Set if the parser has a valid file offset +#define PARSER_FLAG_FETCHED_OFFSET 0x0004 +#define PARSER_FLAG_USE_CODEC_TS 0x1000 + + int64_t offset; ///< byte offset from starting packet start + int64_t cur_frame_end[AV_PARSER_PTS_NB]; + + /** + * Set by parser to 1 for key frames and 0 for non-key frames. + * It is initialized to -1, so if the parser doesn't set this flag, + * old-style fallback using AV_PICTURE_TYPE_I picture type as key frames + * will be used. + */ + int key_frame; + +#if FF_API_CONVERGENCE_DURATION + /** + * @deprecated unused + */ + attribute_deprecated + int64_t convergence_duration; +#endif + + // Timestamp generation support: + /** + * Synchronization point for start of timestamp generation. + * + * Set to >0 for sync point, 0 for no sync point and <0 for undefined + * (default). + * + * For example, this corresponds to presence of H.264 buffering period + * SEI message. + */ + int dts_sync_point; + + /** + * Offset of the current timestamp against last timestamp sync point in + * units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain a valid timestamp offset. + * + * Note that the timestamp of sync point has usually a nonzero + * dts_ref_dts_delta, which refers to the previous sync point. Offset of + * the next frame after timestamp sync point will be usually 1. + * + * For example, this corresponds to H.264 cpb_removal_delay. + */ + int dts_ref_dts_delta; + + /** + * Presentation delay of current frame in units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain valid non-negative timestamp delta (presentation time of a frame + * must not lie in the past). + * + * This delay represents the difference between decoding and presentation + * time of the frame. + * + * For example, this corresponds to H.264 dpb_output_delay. + */ + int pts_dts_delta; + + /** + * Position of the packet in file. + * + * Analogous to cur_frame_pts/dts + */ + int64_t cur_frame_pos[AV_PARSER_PTS_NB]; + + /** + * Byte position of currently parsed frame in stream. + */ + int64_t pos; + + /** + * Previous frame byte position. + */ + int64_t last_pos; + + /** + * Duration of the current frame. + * For audio, this is in units of 1 / AVCodecContext.sample_rate. + * For all other types, this is in units of AVCodecContext.time_base. + */ + int duration; + + enum AVFieldOrder field_order; + + /** + * Indicate whether a picture is coded as a frame, top field or bottom field. + * + * For example, H.264 field_pic_flag equal to 0 corresponds to + * AV_PICTURE_STRUCTURE_FRAME. An H.264 picture with field_pic_flag + * equal to 1 and bottom_field_flag equal to 0 corresponds to + * AV_PICTURE_STRUCTURE_TOP_FIELD. + */ + enum AVPictureStructure picture_structure; + + /** + * Picture number incremented in presentation or output order. + * This field may be reinitialized at the first picture of a new sequence. + * + * For example, this corresponds to H.264 PicOrderCnt. + */ + int output_picture_number; + + /** + * Dimensions of the decoded video intended for presentation. + */ + int width; + int height; + + /** + * Dimensions of the coded video. + */ + int coded_width; + int coded_height; + + /** + * The format of the coded data, corresponds to enum AVPixelFormat for video + * and for enum AVSampleFormat for audio. + * + * Note that a decoder can have considerable freedom in how exactly it + * decodes the data, so the format reported here might be different from the + * one returned by a decoder. + */ + int format; +} AVCodecParserContext; + +typedef struct AVCodecParser { + int codec_ids[5]; /* several codec IDs are permitted */ + int priv_data_size; + int (*parser_init)(AVCodecParserContext *s); + /* This callback never returns an error, a negative value means that + * the frame start was in a previous packet. */ + int (*parser_parse)(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size); + void (*parser_close)(AVCodecParserContext *s); + int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size); +#if FF_API_NEXT + attribute_deprecated + struct AVCodecParser *next; +#endif +} AVCodecParser; + +/** + * Iterate over all registered codec parsers. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec parser or NULL when the iteration is + * finished + */ +const AVCodecParser *av_parser_iterate(void **opaque); + +#if FF_API_NEXT +attribute_deprecated +AVCodecParser *av_parser_next(const AVCodecParser *c); + +attribute_deprecated +void av_register_codec_parser(AVCodecParser *parser); +#endif +AVCodecParserContext *av_parser_init(int codec_id); + +/** + * Parse a packet. + * + * @param s parser context. + * @param avctx codec context. + * @param poutbuf set to pointer to parsed buffer or NULL if not yet finished. + * @param poutbuf_size set to size of parsed buffer or zero if not yet finished. + * @param buf input buffer. + * @param buf_size buffer size in bytes without the padding. I.e. the full buffer + size is assumed to be buf_size + AV_INPUT_BUFFER_PADDING_SIZE. + To signal EOF, this should be 0 (so that the last frame + can be output). + * @param pts input presentation timestamp. + * @param dts input decoding timestamp. + * @param pos input byte position in stream. + * @return the number of bytes of the input bitstream used. + * + * Example: + * @code + * while(in_len){ + * len = av_parser_parse2(myparser, AVCodecContext, &data, &size, + * in_data, in_len, + * pts, dts, pos); + * in_data += len; + * in_len -= len; + * + * if(size) + * decode_frame(data, size); + * } + * @endcode + */ +int av_parser_parse2(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int64_t pts, int64_t dts, + int64_t pos); + +#if FF_API_PARSER_CHANGE +/** + * @return 0 if the output buffer is a subset of the input, 1 if it is allocated and must be freed + * @deprecated Use dump_extradata, remove_extra or extract_extradata + * bitstream filters instead. + */ +attribute_deprecated +int av_parser_change(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe); +#endif +void av_parser_close(AVCodecParserContext *s); + +/** + * @} + * @} + */ + +/** + * @addtogroup lavc_encoding + * @{ + */ + +#if FF_API_OLD_ENCDEC +/** + * Encode a frame of audio. + * + * Takes input samples from frame and writes the next output packet, if + * available, to avpkt. The output packet does not necessarily contain data for + * the most recent frame, as encoders can delay, split, and combine input frames + * internally as needed. + * + * @param avctx codec context + * @param avpkt output AVPacket. + * The user can supply an output buffer by setting + * avpkt->data and avpkt->size prior to calling the + * function, but if the size of the user-provided data is not + * large enough, encoding will fail. If avpkt->data and + * avpkt->size are set, avpkt->destruct must also be set. All + * other AVPacket fields will be reset by the encoder using + * av_init_packet(). If avpkt->data is NULL, the encoder will + * allocate it. The encoder will set avpkt->size to the size + * of the output packet. + * + * If this function fails or produces no output, avpkt will be + * freed using av_packet_unref(). + * @param[in] frame AVFrame containing the raw audio data to be encoded. + * May be NULL when flushing an encoder that has the + * AV_CODEC_CAP_DELAY capability set. + * If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * can have any number of samples. + * If it is not set, frame->nb_samples must be equal to + * avctx->frame_size for all frames except the last. + * The final frame may be smaller than avctx->frame_size. + * @param[out] got_packet_ptr This field is set to 1 by libavcodec if the + * output packet is non-empty, and to 0 if it is + * empty. If the function returns an error, the + * packet can be assumed to be invalid, and the + * value of got_packet_ptr is undefined and should + * not be used. + * @return 0 on success, negative error code on failure + * + * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead. + * If allowed and required, set AVCodecContext.get_encode_buffer to + * a custom function to pass user supplied output buffers. + */ +attribute_deprecated +int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr); + +/** + * Encode a frame of video. + * + * Takes input raw video data from frame and writes the next output packet, if + * available, to avpkt. The output packet does not necessarily contain data for + * the most recent frame, as encoders can delay and reorder input frames + * internally as needed. + * + * @param avctx codec context + * @param avpkt output AVPacket. + * The user can supply an output buffer by setting + * avpkt->data and avpkt->size prior to calling the + * function, but if the size of the user-provided data is not + * large enough, encoding will fail. All other AVPacket fields + * will be reset by the encoder using av_init_packet(). If + * avpkt->data is NULL, the encoder will allocate it. + * The encoder will set avpkt->size to the size of the + * output packet. The returned data (if any) belongs to the + * caller, he is responsible for freeing it. + * + * If this function fails or produces no output, avpkt will be + * freed using av_packet_unref(). + * @param[in] frame AVFrame containing the raw video data to be encoded. + * May be NULL when flushing an encoder that has the + * AV_CODEC_CAP_DELAY capability set. + * @param[out] got_packet_ptr This field is set to 1 by libavcodec if the + * output packet is non-empty, and to 0 if it is + * empty. If the function returns an error, the + * packet can be assumed to be invalid, and the + * value of got_packet_ptr is undefined and should + * not be used. + * @return 0 on success, negative error code on failure + * + * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead. + * If allowed and required, set AVCodecContext.get_encode_buffer to + * a custom function to pass user supplied output buffers. + */ +attribute_deprecated +int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr); +#endif + +int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVSubtitle *sub); + + +/** + * @} + */ + +#if FF_API_AVPICTURE +/** + * @addtogroup lavc_picture + * @{ + */ + +/** + * @deprecated unused + */ +attribute_deprecated +int avpicture_alloc(AVPicture *picture, enum AVPixelFormat pix_fmt, int width, int height); + +/** + * @deprecated unused + */ +attribute_deprecated +void avpicture_free(AVPicture *picture); + +/** + * @deprecated use av_image_fill_arrays() instead. + */ +attribute_deprecated +int avpicture_fill(AVPicture *picture, const uint8_t *ptr, + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * @deprecated use av_image_copy_to_buffer() instead. + */ +attribute_deprecated +int avpicture_layout(const AVPicture *src, enum AVPixelFormat pix_fmt, + int width, int height, + unsigned char *dest, int dest_size); + +/** + * @deprecated use av_image_get_buffer_size() instead. + */ +attribute_deprecated +int avpicture_get_size(enum AVPixelFormat pix_fmt, int width, int height); + +/** + * @deprecated av_image_copy() instead. + */ +attribute_deprecated +void av_picture_copy(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * @deprecated unused + */ +attribute_deprecated +int av_picture_crop(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int top_band, int left_band); + +/** + * @deprecated unused + */ +attribute_deprecated +int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, enum AVPixelFormat pix_fmt, + int padtop, int padbottom, int padleft, int padright, int *color); + +/** + * @} + */ +#endif + +/** + * @defgroup lavc_misc Utility functions + * @ingroup libavc + * + * Miscellaneous utility functions related to both encoding and decoding + * (or neither). + * @{ + */ + +/** + * @defgroup lavc_misc_pixfmt Pixel formats + * + * Functions for working with pixel formats. + * @{ + */ + +#if FF_API_GETCHROMA +/** + * @deprecated Use av_pix_fmt_get_chroma_sub_sample + */ + +attribute_deprecated +void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift); +#endif + +/** + * Return a value representing the fourCC code associated to the + * pixel format pix_fmt, or 0 if no associated fourCC code can be + * found. + */ +unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt); + +/** + * Find the best pixel format to convert to given a certain source pixel + * format. When converting from one pixel format to another, information loss + * may occur. For example, when converting from RGB24 to GRAY, the color + * information will be lost. Similarly, other losses occur when converting from + * some formats to other formats. avcodec_find_best_pix_fmt_of_2() searches which of + * the given pixel formats should be used to suffer the least amount of loss. + * The pixel formats from which it chooses one, are determined by the + * pix_fmt_list parameter. + * + * + * @param[in] pix_fmt_list AV_PIX_FMT_NONE terminated array of pixel formats to choose from + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. + * @return The best pixel format to convert to or -1 if none was found. + */ +enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *pix_fmt_list, + enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); + +#if FF_API_AVCODEC_PIX_FMT +/** + * @deprecated see av_get_pix_fmt_loss() + */ +attribute_deprecated +int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt, + int has_alpha); +/** + * @deprecated see av_find_best_pix_fmt_of_2() + */ +attribute_deprecated +enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); + +attribute_deprecated +enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); +#endif + +enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + +/** + * @} + */ + +#if FF_API_TAG_STRING +/** + * Put a string representing the codec tag codec_tag in buf. + * + * @param buf buffer to place codec tag in + * @param buf_size size in bytes of buf + * @param codec_tag codec tag to assign + * @return the length of the string that would have been generated if + * enough space had been available, excluding the trailing null + * + * @deprecated see av_fourcc_make_string() and av_fourcc2str(). + */ +attribute_deprecated +size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_tag); +#endif + +void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); + +/** + * Return a name for the specified profile, if available. + * + * @param codec the codec that is searched for the given profile + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + */ +const char *av_get_profile_name(const AVCodec *codec, int profile); + +/** + * Return a name for the specified profile, if available. + * + * @param codec_id the ID of the codec to which the requested profile belongs + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + * + * @note unlike av_get_profile_name(), which searches a list of profiles + * supported by a specific decoder or encoder implementation, this + * function searches the list of profiles from the AVCodecDescriptor + */ +const char *avcodec_profile_name(enum AVCodecID codec_id, int profile); + +int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); +int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count); +//FIXME func typedef + +/** + * Fill AVFrame audio data and linesize pointers. + * + * The buffer buf must be a preallocated buffer with a size big enough + * to contain the specified samples amount. The filled AVFrame data + * pointers will point to this buffer. + * + * AVFrame extended_data channel pointers are allocated if necessary for + * planar audio. + * + * @param frame the AVFrame + * frame->nb_samples must be set prior to calling the + * function. This function fills in frame->data, + * frame->extended_data, frame->linesize[0]. + * @param nb_channels channel count + * @param sample_fmt sample format + * @param buf buffer to use for frame data + * @param buf_size size of buffer + * @param align plane size sample alignment (0 = default) + * @return >=0 on success, negative error code on failure + * @todo return the size in bytes required to store the samples in + * case of success, at the next libavutil bump + */ +int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, + enum AVSampleFormat sample_fmt, const uint8_t *buf, + int buf_size, int align); + +/** + * Reset the internal codec state / flush internal buffers. Should be called + * e.g. when seeking or when switching to a different stream. + * + * @note for decoders, when refcounted frames are not used + * (i.e. avctx->refcounted_frames is 0), this invalidates the frames previously + * returned from the decoder. When refcounted frames are used, the decoder just + * releases any references it might keep internally, but the caller's reference + * remains valid. + * + * @note for encoders, this function will only do something if the encoder + * declares support for AV_CODEC_CAP_ENCODER_FLUSH. When called, the encoder + * will drain any remaining packets, and can then be re-used for a different + * stream (as opposed to sending a null frame which will leave the encoder + * in a permanent EOF state after draining). This can be desirable if the + * cost of tearing down and replacing the encoder instance is high. + */ +void avcodec_flush_buffers(AVCodecContext *avctx); + +/** + * Return codec bits per sample. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return the PCM codec associated with a sample format. + * @param be endianness, 0 for little, 1 for big, + * -1 (or anything else) for native + * @return AV_CODEC_ID_PCM_* or AV_CODEC_ID_NONE + */ +enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be); + +/** + * Return codec bits per sample. + * Only return non-zero if the bits per sample is exactly correct, not an + * approximation. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_exact_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return audio frame duration. + * + * @param avctx codec context + * @param frame_bytes size of the frame, or 0 if unknown + * @return frame duration, in samples, if known. 0 if not able to + * determine. + */ +int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes); + +/** + * This function is the same as av_get_audio_frame_duration(), except it works + * with AVCodecParameters instead of an AVCodecContext. + */ +int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes); + +#if FF_API_OLD_BSF +typedef struct AVBitStreamFilterContext { + void *priv_data; + const struct AVBitStreamFilter *filter; + AVCodecParserContext *parser; + struct AVBitStreamFilterContext *next; + /** + * Internal default arguments, used if NULL is passed to av_bitstream_filter_filter(). + * Not for access by library users. + */ + char *args; +} AVBitStreamFilterContext; + +/** + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use the new bitstream filtering API (using AVBSFContext). + */ +attribute_deprecated +void av_register_bitstream_filter(AVBitStreamFilter *bsf); +/** + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use av_bsf_get_by_name(), av_bsf_alloc(), and av_bsf_init() + * from the new bitstream filtering API (using AVBSFContext). + */ +attribute_deprecated +AVBitStreamFilterContext *av_bitstream_filter_init(const char *name); +/** + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use av_bsf_send_packet() and av_bsf_receive_packet() from the + * new bitstream filtering API (using AVBSFContext). + */ +attribute_deprecated +int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc, + AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe); +/** + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use av_bsf_free() from the new bitstream filtering API (using + * AVBSFContext). + */ +attribute_deprecated +void av_bitstream_filter_close(AVBitStreamFilterContext *bsf); +/** + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use av_bsf_iterate() from the new bitstream filtering API (using + * AVBSFContext). + */ +attribute_deprecated +const AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f); +#endif + +#if FF_API_NEXT +attribute_deprecated +const AVBitStreamFilter *av_bsf_next(void **opaque); +#endif + +/* memory */ + +/** + * Same behaviour av_fast_malloc but the buffer has additional + * AV_INPUT_BUFFER_PADDING_SIZE at the end which will always be 0. + * + * In addition the whole buffer will initially and after resizes + * be 0-initialized so that no uninitialized data will ever appear. + */ +void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Same behaviour av_fast_padded_malloc except that buffer will always + * be 0-initialized after call. + */ +void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * Encode extradata length to a buffer. Used by xiph codecs. + * + * @param s buffer to write to; must be at least (v/255+1) bytes long + * @param v size of extradata in bytes + * @return number of bytes written to the buffer. + */ +unsigned int av_xiphlacing(unsigned char *s, unsigned int v); + +#if FF_API_USER_VISIBLE_AVHWACCEL +/** + * Register the hardware accelerator hwaccel. + * + * @deprecated This function doesn't do anything. + */ +attribute_deprecated +void av_register_hwaccel(AVHWAccel *hwaccel); + +/** + * If hwaccel is NULL, returns the first registered hardware accelerator, + * if hwaccel is non-NULL, returns the next registered hardware accelerator + * after hwaccel, or NULL if hwaccel is the last one. + * + * @deprecated AVHWaccel structures contain no user-serviceable parts, so + * this function should not be used. + */ +attribute_deprecated +AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel); +#endif + +#if FF_API_LOCKMGR +/** + * Lock operation used by lockmgr + * + * @deprecated Deprecated together with av_lockmgr_register(). + */ +enum AVLockOp { + AV_LOCK_CREATE, ///< Create a mutex + AV_LOCK_OBTAIN, ///< Lock the mutex + AV_LOCK_RELEASE, ///< Unlock the mutex + AV_LOCK_DESTROY, ///< Free mutex resources +}; + +/** + * Register a user provided lock manager supporting the operations + * specified by AVLockOp. The "mutex" argument to the function points + * to a (void *) where the lockmgr should store/get a pointer to a user + * allocated mutex. It is NULL upon AV_LOCK_CREATE and equal to the + * value left by the last call for all other ops. If the lock manager is + * unable to perform the op then it should leave the mutex in the same + * state as when it was called and return a non-zero value. However, + * when called with AV_LOCK_DESTROY the mutex will always be assumed to + * have been successfully destroyed. If av_lockmgr_register succeeds + * it will return a non-negative value, if it fails it will return a + * negative value and destroy all mutex and unregister all callbacks. + * av_lockmgr_register is not thread-safe, it must be called from a + * single thread before any calls which make use of locking are used. + * + * @param cb User defined callback. av_lockmgr_register invokes calls + * to this callback and the previously registered callback. + * The callback will be used to create more than one mutex + * each of which must be backed by its own underlying locking + * mechanism (i.e. do not use a single static object to + * implement your lock manager). If cb is set to NULL the + * lockmgr will be unregistered. + * + * @deprecated This function does nothing, and always returns 0. Be sure to + * build with thread support to get basic thread safety. + */ +attribute_deprecated +int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)); +#endif + +/** + * @return a positive value if s is open (i.e. avcodec_open2() was called on it + * with no corresponding avcodec_close()), 0 otherwise. + */ +int avcodec_is_open(AVCodecContext *s); + +/** + * Allocate a CPB properties structure and initialize its fields to default + * values. + * + * @param size if non-NULL, the size of the allocated struct will be written + * here. This is useful for embedding it in side data. + * + * @return the newly allocated struct or NULL on failure + */ +AVCPBProperties *av_cpb_properties_alloc(size_t *size); + +/** + * @} + */ + +#endif /* AVCODEC_AVCODEC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/bsf.h b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/bsf.h new file mode 100644 index 0000000000000..3b5faa85cb513 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/bsf.h @@ -0,0 +1,325 @@ +/* + * Bitstream filters public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_BSF_H +#define AVCODEC_BSF_H + +#include "libavutil/dict.h" +#include "libavutil/log.h" +#include "libavutil/rational.h" + +#include "codec_id.h" +#include "codec_par.h" +#include "packet.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +typedef struct AVBSFInternal AVBSFInternal; + +/** + * The bitstream filter state. + * + * This struct must be allocated with av_bsf_alloc() and freed with + * av_bsf_free(). + * + * The fields in the struct will only be changed (by the caller or by the + * filter) as described in their documentation, and are to be considered + * immutable otherwise. + */ +typedef struct AVBSFContext { + /** + * A class for logging and AVOptions + */ + const AVClass *av_class; + + /** + * The bitstream filter this context is an instance of. + */ + const struct AVBitStreamFilter *filter; + + /** + * Opaque libavcodec internal data. Must not be touched by the caller in any + * way. + */ + AVBSFInternal *internal; + + /** + * Opaque filter-specific private data. If filter->priv_class is non-NULL, + * this is an AVOptions-enabled struct. + */ + void *priv_data; + + /** + * Parameters of the input stream. This field is allocated in + * av_bsf_alloc(), it needs to be filled by the caller before + * av_bsf_init(). + */ + AVCodecParameters *par_in; + + /** + * Parameters of the output stream. This field is allocated in + * av_bsf_alloc(), it is set by the filter in av_bsf_init(). + */ + AVCodecParameters *par_out; + + /** + * The timebase used for the timestamps of the input packets. Set by the + * caller before av_bsf_init(). + */ + AVRational time_base_in; + + /** + * The timebase used for the timestamps of the output packets. Set by the + * filter in av_bsf_init(). + */ + AVRational time_base_out; +} AVBSFContext; + +typedef struct AVBitStreamFilter { + const char *name; + + /** + * A list of codec ids supported by the filter, terminated by + * AV_CODEC_ID_NONE. + * May be NULL, in that case the bitstream filter works with any codec id. + */ + const enum AVCodecID *codec_ids; + + /** + * A class for the private data, used to declare bitstream filter private + * AVOptions. This field is NULL for bitstream filters that do not declare + * any options. + * + * If this field is non-NULL, the first member of the filter private data + * must be a pointer to AVClass, which will be set by libavcodec generic + * code to this class. + */ + const AVClass *priv_class; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavcodec and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + + int priv_data_size; + int (*init)(AVBSFContext *ctx); + int (*filter)(AVBSFContext *ctx, AVPacket *pkt); + void (*close)(AVBSFContext *ctx); + void (*flush)(AVBSFContext *ctx); +} AVBitStreamFilter; + +/** + * @return a bitstream filter with the specified name or NULL if no such + * bitstream filter exists. + */ +const AVBitStreamFilter *av_bsf_get_by_name(const char *name); + +/** + * Iterate over all registered bitstream filters. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered bitstream filter or NULL when the iteration is + * finished + */ +const AVBitStreamFilter *av_bsf_iterate(void **opaque); + +/** + * Allocate a context for a given bitstream filter. The caller must fill in the + * context parameters as described in the documentation and then call + * av_bsf_init() before sending any data to the filter. + * + * @param filter the filter for which to allocate an instance. + * @param ctx a pointer into which the pointer to the newly-allocated context + * will be written. It must be freed with av_bsf_free() after the + * filtering is done. + * + * @return 0 on success, a negative AVERROR code on failure + */ +int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx); + +/** + * Prepare the filter for use, after all the parameters and options have been + * set. + */ +int av_bsf_init(AVBSFContext *ctx); + +/** + * Submit a packet for filtering. + * + * After sending each packet, the filter must be completely drained by calling + * av_bsf_receive_packet() repeatedly until it returns AVERROR(EAGAIN) or + * AVERROR_EOF. + * + * @param pkt the packet to filter. The bitstream filter will take ownership of + * the packet and reset the contents of pkt. pkt is not touched if an error occurs. + * If pkt is empty (i.e. NULL, or pkt->data is NULL and pkt->side_data_elems zero), + * it signals the end of the stream (i.e. no more non-empty packets will be sent; + * sending more empty packets does nothing) and will cause the filter to output + * any packets it may have buffered internally. + * + * @return 0 on success. AVERROR(EAGAIN) if packets need to be retrieved from the + * filter (using av_bsf_receive_packet()) before new input can be consumed. Another + * negative AVERROR value if an error occurs. + */ +int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt); + +/** + * Retrieve a filtered packet. + * + * @param[out] pkt this struct will be filled with the contents of the filtered + * packet. It is owned by the caller and must be freed using + * av_packet_unref() when it is no longer needed. + * This parameter should be "clean" (i.e. freshly allocated + * with av_packet_alloc() or unreffed with av_packet_unref()) + * when this function is called. If this function returns + * successfully, the contents of pkt will be completely + * overwritten by the returned data. On failure, pkt is not + * touched. + * + * @return 0 on success. AVERROR(EAGAIN) if more packets need to be sent to the + * filter (using av_bsf_send_packet()) to get more output. AVERROR_EOF if there + * will be no further output from the filter. Another negative AVERROR value if + * an error occurs. + * + * @note one input packet may result in several output packets, so after sending + * a packet with av_bsf_send_packet(), this function needs to be called + * repeatedly until it stops returning 0. It is also possible for a filter to + * output fewer packets than were sent to it, so this function may return + * AVERROR(EAGAIN) immediately after a successful av_bsf_send_packet() call. + */ +int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt); + +/** + * Reset the internal bitstream filter state. Should be called e.g. when seeking. + */ +void av_bsf_flush(AVBSFContext *ctx); + +/** + * Free a bitstream filter context and everything associated with it; write NULL + * into the supplied pointer. + */ +void av_bsf_free(AVBSFContext **ctx); + +/** + * Get the AVClass for AVBSFContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *av_bsf_get_class(void); + +/** + * Structure for chain/list of bitstream filters. + * Empty list can be allocated by av_bsf_list_alloc(). + */ +typedef struct AVBSFList AVBSFList; + +/** + * Allocate empty list of bitstream filters. + * The list must be later freed by av_bsf_list_free() + * or finalized by av_bsf_list_finalize(). + * + * @return Pointer to @ref AVBSFList on success, NULL in case of failure + */ +AVBSFList *av_bsf_list_alloc(void); + +/** + * Free list of bitstream filters. + * + * @param lst Pointer to pointer returned by av_bsf_list_alloc() + */ +void av_bsf_list_free(AVBSFList **lst); + +/** + * Append bitstream filter to the list of bitstream filters. + * + * @param lst List to append to + * @param bsf Filter context to be appended + * + * @return >=0 on success, negative AVERROR in case of failure + */ +int av_bsf_list_append(AVBSFList *lst, AVBSFContext *bsf); + +/** + * Construct new bitstream filter context given it's name and options + * and append it to the list of bitstream filters. + * + * @param lst List to append to + * @param bsf_name Name of the bitstream filter + * @param options Options for the bitstream filter, can be set to NULL + * + * @return >=0 on success, negative AVERROR in case of failure + */ +int av_bsf_list_append2(AVBSFList *lst, const char * bsf_name, AVDictionary **options); +/** + * Finalize list of bitstream filters. + * + * This function will transform @ref AVBSFList to single @ref AVBSFContext, + * so the whole chain of bitstream filters can be treated as single filter + * freshly allocated by av_bsf_alloc(). + * If the call is successful, @ref AVBSFList structure is freed and lst + * will be set to NULL. In case of failure, caller is responsible for + * freeing the structure by av_bsf_list_free() + * + * @param lst Filter list structure to be transformed + * @param[out] bsf Pointer to be set to newly created @ref AVBSFContext structure + * representing the chain of bitstream filters + * + * @return >=0 on success, negative AVERROR in case of failure + */ +int av_bsf_list_finalize(AVBSFList **lst, AVBSFContext **bsf); + +/** + * Parse string describing list of bitstream filters and create single + * @ref AVBSFContext describing the whole chain of bitstream filters. + * Resulting @ref AVBSFContext can be treated as any other @ref AVBSFContext freshly + * allocated by av_bsf_alloc(). + * + * @param str String describing chain of bitstream filters in format + * `bsf1[=opt1=val1:opt2=val2][,bsf2]` + * @param[out] bsf Pointer to be set to newly created @ref AVBSFContext structure + * representing the chain of bitstream filters + * + * @return >=0 on success, negative AVERROR in case of failure + */ +int av_bsf_list_parse_str(const char *str, AVBSFContext **bsf); + +/** + * Get null/pass-through bitstream filter. + * + * @param[out] bsf Pointer to be set to new instance of pass-through bitstream filter + * + * @return + */ +int av_bsf_get_null_filter(AVBSFContext **bsf); + +/** + * @} + */ + +#endif // AVCODEC_BSF_H diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec.h b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec.h new file mode 100644 index 0000000000000..50a22f6e3cb0a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec.h @@ -0,0 +1,480 @@ +/* + * AVCodec public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_H +#define AVCODEC_CODEC_H + +#include + +#include "libavutil/avutil.h" +#include "libavutil/hwcontext.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" +#include "libavutil/samplefmt.h" + +#include "libavcodec/codec_id.h" +#include "libavcodec/version.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * Decoder can use draw_horiz_band callback. + */ +#define AV_CODEC_CAP_DRAW_HORIZ_BAND (1 << 0) +/** + * Codec uses get_buffer() or get_encode_buffer() for allocating buffers and + * supports custom allocators. + * If not set, it might not use get_buffer() or get_encode_buffer() at all, or + * use operations that assume the buffer was allocated by + * avcodec_default_get_buffer2 or avcodec_default_get_encode_buffer. + */ +#define AV_CODEC_CAP_DR1 (1 << 1) +#define AV_CODEC_CAP_TRUNCATED (1 << 3) +/** + * Encoder or decoder requires flushing with NULL input at the end in order to + * give the complete and correct output. + * + * NOTE: If this flag is not set, the codec is guaranteed to never be fed with + * with NULL data. The user can still send NULL data to the public encode + * or decode function, but libavcodec will not pass it along to the codec + * unless this flag is set. + * + * Decoders: + * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to get the delayed data until the decoder no longer + * returns frames. + * + * Encoders: + * The encoder needs to be fed with NULL data at the end of encoding until the + * encoder no longer returns data. + * + * NOTE: For encoders implementing the AVCodec.encode2() function, setting this + * flag also means that the encoder must set the pts and duration for + * each output packet. If this flag is not set, the pts and duration will + * be determined by libavcodec from the input frame. + */ +#define AV_CODEC_CAP_DELAY (1 << 5) +/** + * Codec can be fed a final frame with a smaller size. + * This can be used to prevent truncation of the last audio samples. + */ +#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6) + +/** + * Codec can output multiple frames per AVPacket + * Normally demuxers return one frame at a time, demuxers which do not do + * are connected to a parser to split what they return into proper frames. + * This flag is reserved to the very rare category of codecs which have a + * bitstream that cannot be split into frames without timeconsuming + * operations like full decoding. Demuxers carrying such bitstreams thus + * may return multiple frames in a packet. This has many disadvantages like + * prohibiting stream copy in many cases thus it should only be considered + * as a last resort. + */ +#define AV_CODEC_CAP_SUBFRAMES (1 << 8) +/** + * Codec is experimental and is thus avoided in favor of non experimental + * encoders + */ +#define AV_CODEC_CAP_EXPERIMENTAL (1 << 9) +/** + * Codec should fill in channel configuration and samplerate instead of container + */ +#define AV_CODEC_CAP_CHANNEL_CONF (1 << 10) +/** + * Codec supports frame-level multithreading. + */ +#define AV_CODEC_CAP_FRAME_THREADS (1 << 12) +/** + * Codec supports slice-based (or partition-based) multithreading. + */ +#define AV_CODEC_CAP_SLICE_THREADS (1 << 13) +/** + * Codec supports changed parameters at any point. + */ +#define AV_CODEC_CAP_PARAM_CHANGE (1 << 14) +/** + * Codec supports multithreading through a method other than slice- or + * frame-level multithreading. Typically this marks wrappers around + * multithreading-capable external libraries. + */ +#define AV_CODEC_CAP_OTHER_THREADS (1 << 15) +#if FF_API_AUTO_THREADS +#define AV_CODEC_CAP_AUTO_THREADS AV_CODEC_CAP_OTHER_THREADS +#endif +/** + * Audio encoder supports receiving a different number of samples in each call. + */ +#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16) +/** + * Decoder is not a preferred choice for probing. + * This indicates that the decoder is not a good choice for probing. + * It could for example be an expensive to spin up hardware decoder, + * or it could simply not provide a lot of useful information about + * the stream. + * A decoder marked with this flag should only be used as last resort + * choice for probing. + */ +#define AV_CODEC_CAP_AVOID_PROBING (1 << 17) + +#if FF_API_UNUSED_CODEC_CAPS +/** + * Deprecated and unused. Use AVCodecDescriptor.props instead + */ +#define AV_CODEC_CAP_INTRA_ONLY 0x40000000 +/** + * Deprecated and unused. Use AVCodecDescriptor.props instead + */ +#define AV_CODEC_CAP_LOSSLESS 0x80000000 +#endif + +/** + * Codec is backed by a hardware implementation. Typically used to + * identify a non-hwaccel hardware decoder. For information about hwaccels, use + * avcodec_get_hw_config() instead. + */ +#define AV_CODEC_CAP_HARDWARE (1 << 18) + +/** + * Codec is potentially backed by a hardware implementation, but not + * necessarily. This is used instead of AV_CODEC_CAP_HARDWARE, if the + * implementation provides some sort of internal fallback. + */ +#define AV_CODEC_CAP_HYBRID (1 << 19) + +/** + * This codec takes the reordered_opaque field from input AVFrames + * and returns it in the corresponding field in AVCodecContext after + * encoding. + */ +#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE (1 << 20) + +/** + * This encoder can be flushed using avcodec_flush_buffers(). If this flag is + * not set, the encoder must be closed and reopened to ensure that no frames + * remain pending. + */ +#define AV_CODEC_CAP_ENCODER_FLUSH (1 << 21) + +/** + * AVProfile. + */ +typedef struct AVProfile { + int profile; + const char *name; ///< short name for the profile +} AVProfile; + +typedef struct AVCodecDefault AVCodecDefault; + +struct AVCodecContext; +struct AVSubtitle; +struct AVPacket; + +/** + * AVCodec. + */ +typedef struct AVCodec { + /** + * Name of the codec implementation. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + * This is the primary way to find a codec from the user perspective. + */ + const char *name; + /** + * Descriptive name for the codec, meant to be more human readable than name. + * You should use the NULL_IF_CONFIG_SMALL() macro to define it. + */ + const char *long_name; + enum AVMediaType type; + enum AVCodecID id; + /** + * Codec capabilities. + * see AV_CODEC_CAP_* + */ + int capabilities; + const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} + const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 + const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 + const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 + const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 + uint8_t max_lowres; ///< maximum value for lowres supported by the decoder + const AVClass *priv_class; ///< AVClass for the private context + const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN} + + /** + * Group name of the codec implementation. + * This is a short symbolic name of the wrapper backing this codec. A + * wrapper uses some kind of external implementation for the codec, such + * as an external library, or a codec implementation provided by the OS or + * the hardware. + * If this field is NULL, this is a builtin, libavcodec native codec. + * If non-NULL, this will be the suffix in AVCodec.name in most cases + * (usually AVCodec.name will be of the form "_"). + */ + const char *wrapper_name; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavcodec and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + int priv_data_size; +#if FF_API_NEXT + struct AVCodec *next; +#endif + /** + * @name Frame-level threading support functions + * @{ + */ + /** + * Copy necessary context variables from a previous thread context to the current one. + * If not defined, the next thread will start automatically; otherwise, the codec + * must call ff_thread_finish_setup(). + * + * dst and src will (rarely) point to the same context, in which case memcpy should be skipped. + */ + int (*update_thread_context)(struct AVCodecContext *dst, const struct AVCodecContext *src); + /** @} */ + + /** + * Private codec-specific defaults. + */ + const AVCodecDefault *defaults; + + /** + * Initialize codec static data, called from av_codec_iterate(). + * + * This is not intended for time consuming operations as it is + * run for every codec regardless of that codec being used. + */ + void (*init_static_data)(struct AVCodec *codec); + + int (*init)(struct AVCodecContext *); + int (*encode_sub)(struct AVCodecContext *, uint8_t *buf, int buf_size, + const struct AVSubtitle *sub); + /** + * Encode data to an AVPacket. + * + * @param avctx codec context + * @param avpkt output AVPacket + * @param[in] frame AVFrame containing the raw data to be encoded + * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a + * non-empty packet was returned in avpkt. + * @return 0 on success, negative error code on failure + */ + int (*encode2)(struct AVCodecContext *avctx, struct AVPacket *avpkt, + const struct AVFrame *frame, int *got_packet_ptr); + /** + * Decode picture or subtitle data. + * + * @param avctx codec context + * @param outdata codec type dependent output struct + * @param[out] got_frame_ptr decoder sets to 0 or 1 to indicate that a + * non-empty frame or subtitle was returned in + * outdata. + * @param[in] avpkt AVPacket containing the data to be decoded + * @return amount of bytes read from the packet on success, negative error + * code on failure + */ + int (*decode)(struct AVCodecContext *avctx, void *outdata, + int *got_frame_ptr, struct AVPacket *avpkt); + int (*close)(struct AVCodecContext *); + /** + * Encode API with decoupled frame/packet dataflow. This function is called + * to get one output packet. It should call ff_encode_get_frame() to obtain + * input data. + */ + int (*receive_packet)(struct AVCodecContext *avctx, struct AVPacket *avpkt); + + /** + * Decode API with decoupled packet/frame dataflow. This function is called + * to get one output frame. It should call ff_decode_get_packet() to obtain + * input data. + */ + int (*receive_frame)(struct AVCodecContext *avctx, struct AVFrame *frame); + /** + * Flush buffers. + * Will be called when seeking + */ + void (*flush)(struct AVCodecContext *); + /** + * Internal codec capabilities. + * See FF_CODEC_CAP_* in internal.h + */ + int caps_internal; + + /** + * Decoding only, a comma-separated list of bitstream filters to apply to + * packets before decoding. + */ + const char *bsfs; + + /** + * Array of pointers to hardware configurations supported by the codec, + * or NULL if no hardware supported. The array is terminated by a NULL + * pointer. + * + * The user can only access this field via avcodec_get_hw_config(). + */ + const struct AVCodecHWConfigInternal *const *hw_configs; + + /** + * List of supported codec_tags, terminated by FF_CODEC_TAGS_END. + */ + const uint32_t *codec_tags; +} AVCodec; + +/** + * Iterate over all registered codecs. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec or NULL when the iteration is + * finished + */ +const AVCodec *av_codec_iterate(void **opaque); + +/** + * Find a registered decoder with a matching codec ID. + * + * @param id AVCodecID of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_decoder(enum AVCodecID id); + +/** + * Find a registered decoder with the specified name. + * + * @param name name of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_decoder_by_name(const char *name); + +/** + * Find a registered encoder with a matching codec ID. + * + * @param id AVCodecID of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_encoder(enum AVCodecID id); + +/** + * Find a registered encoder with the specified name. + * + * @param name name of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_encoder_by_name(const char *name); +/** + * @return a non-zero number if codec is an encoder, zero otherwise + */ +int av_codec_is_encoder(const AVCodec *codec); + +/** + * @return a non-zero number if codec is a decoder, zero otherwise + */ +int av_codec_is_decoder(const AVCodec *codec); + +enum { + /** + * The codec supports this format via the hw_device_ctx interface. + * + * When selecting this format, AVCodecContext.hw_device_ctx should + * have been set to a device of the specified type before calling + * avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01, + /** + * The codec supports this format via the hw_frames_ctx interface. + * + * When selecting this format for a decoder, + * AVCodecContext.hw_frames_ctx should be set to a suitable frames + * context inside the get_format() callback. The frames context + * must have been created on a device of the specified type. + * + * When selecting this format for an encoder, + * AVCodecContext.hw_frames_ctx should be set to the context which + * will be used for the input frames before calling avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02, + /** + * The codec supports this format by some internal method. + * + * This format can be selected without any additional configuration - + * no device or frames context is required. + */ + AV_CODEC_HW_CONFIG_METHOD_INTERNAL = 0x04, + /** + * The codec supports this format by some ad-hoc method. + * + * Additional settings and/or function calls are required. See the + * codec-specific documentation for details. (Methods requiring + * this sort of configuration are deprecated and others should be + * used in preference.) + */ + AV_CODEC_HW_CONFIG_METHOD_AD_HOC = 0x08, +}; + +typedef struct AVCodecHWConfig { + /** + * For decoders, a hardware pixel format which that decoder may be + * able to decode to if suitable hardware is available. + * + * For encoders, a pixel format which the encoder may be able to + * accept. If set to AV_PIX_FMT_NONE, this applies to all pixel + * formats supported by the codec. + */ + enum AVPixelFormat pix_fmt; + /** + * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible + * setup methods which can be used with this configuration. + */ + int methods; + /** + * The device type associated with the configuration. + * + * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and + * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused. + */ + enum AVHWDeviceType device_type; +} AVCodecHWConfig; + +/** + * Retrieve supported hardware configurations for a codec. + * + * Values of index from zero to some maximum return the indexed configuration + * descriptor; all other values return NULL. If the codec does not support + * any hardware configurations then it will always return NULL. + */ +const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index); + +/** + * @} + */ + +#endif /* AVCODEC_CODEC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec_desc.h b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec_desc.h new file mode 100644 index 0000000000000..126b52df47629 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec_desc.h @@ -0,0 +1,128 @@ +/* + * Codec descriptors public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_DESC_H +#define AVCODEC_CODEC_DESC_H + +#include "libavutil/avutil.h" + +#include "codec_id.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * This struct describes the properties of a single codec described by an + * AVCodecID. + * @see avcodec_descriptor_get() + */ +typedef struct AVCodecDescriptor { + enum AVCodecID id; + enum AVMediaType type; + /** + * Name of the codec described by this descriptor. It is non-empty and + * unique for each codec descriptor. It should contain alphanumeric + * characters and '_' only. + */ + const char *name; + /** + * A more descriptive name for this codec. May be NULL. + */ + const char *long_name; + /** + * Codec properties, a combination of AV_CODEC_PROP_* flags. + */ + int props; + /** + * MIME type(s) associated with the codec. + * May be NULL; if not, a NULL-terminated array of MIME types. + * The first item is always non-NULL and is the preferred MIME type. + */ + const char *const *mime_types; + /** + * If non-NULL, an array of profiles recognized for this codec. + * Terminated with FF_PROFILE_UNKNOWN. + */ + const struct AVProfile *profiles; +} AVCodecDescriptor; + +/** + * Codec uses only intra compression. + * Video and audio codecs only. + */ +#define AV_CODEC_PROP_INTRA_ONLY (1 << 0) +/** + * Codec supports lossy compression. Audio and video codecs only. + * @note a codec may support both lossy and lossless + * compression modes + */ +#define AV_CODEC_PROP_LOSSY (1 << 1) +/** + * Codec supports lossless compression. Audio and video codecs only. + */ +#define AV_CODEC_PROP_LOSSLESS (1 << 2) +/** + * Codec supports frame reordering. That is, the coded order (the order in which + * the encoded packets are output by the encoders / stored / input to the + * decoders) may be different from the presentation order of the corresponding + * frames. + * + * For codecs that do not have this property set, PTS and DTS should always be + * equal. + */ +#define AV_CODEC_PROP_REORDER (1 << 3) +/** + * Subtitle codec is bitmap based + * Decoded AVSubtitle data can be read from the AVSubtitleRect->pict field. + */ +#define AV_CODEC_PROP_BITMAP_SUB (1 << 16) +/** + * Subtitle codec is text based. + * Decoded AVSubtitle data can be read from the AVSubtitleRect->ass field. + */ +#define AV_CODEC_PROP_TEXT_SUB (1 << 17) + +/** + * @return descriptor for given codec ID or NULL if no descriptor exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id); + +/** + * Iterate over all codec descriptors known to libavcodec. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); + +/** + * @return codec descriptor with the given name or NULL if no such descriptor + * exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_DESC_H diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec_id.h b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec_id.h new file mode 100644 index 0000000000000..ab7bc68ee2c43 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec_id.h @@ -0,0 +1,592 @@ +/* + * Codec IDs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_ID_H +#define AVCODEC_CODEC_ID_H + +#include "libavutil/avutil.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * Identify the syntax and semantics of the bitstream. + * The principle is roughly: + * Two decoders with the same ID can decode the same streams. + * Two encoders with the same ID can encode compatible streams. + * There may be slight deviations from the principle due to implementation + * details. + * + * If you add a codec ID to this list, add it so that + * 1. no value of an existing codec ID changes (that would break ABI), + * 2. it is as close as possible to similar codecs + * + * After adding new codec IDs, do not forget to add an entry to the codec + * descriptor list and bump libavcodec minor version. + */ +enum AVCodecID { + AV_CODEC_ID_NONE, + + /* video codecs */ + AV_CODEC_ID_MPEG1VIDEO, + AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding + AV_CODEC_ID_H261, + AV_CODEC_ID_H263, + AV_CODEC_ID_RV10, + AV_CODEC_ID_RV20, + AV_CODEC_ID_MJPEG, + AV_CODEC_ID_MJPEGB, + AV_CODEC_ID_LJPEG, + AV_CODEC_ID_SP5X, + AV_CODEC_ID_JPEGLS, + AV_CODEC_ID_MPEG4, + AV_CODEC_ID_RAWVIDEO, + AV_CODEC_ID_MSMPEG4V1, + AV_CODEC_ID_MSMPEG4V2, + AV_CODEC_ID_MSMPEG4V3, + AV_CODEC_ID_WMV1, + AV_CODEC_ID_WMV2, + AV_CODEC_ID_H263P, + AV_CODEC_ID_H263I, + AV_CODEC_ID_FLV1, + AV_CODEC_ID_SVQ1, + AV_CODEC_ID_SVQ3, + AV_CODEC_ID_DVVIDEO, + AV_CODEC_ID_HUFFYUV, + AV_CODEC_ID_CYUV, + AV_CODEC_ID_H264, + AV_CODEC_ID_INDEO3, + AV_CODEC_ID_VP3, + AV_CODEC_ID_THEORA, + AV_CODEC_ID_ASV1, + AV_CODEC_ID_ASV2, + AV_CODEC_ID_FFV1, + AV_CODEC_ID_4XM, + AV_CODEC_ID_VCR1, + AV_CODEC_ID_CLJR, + AV_CODEC_ID_MDEC, + AV_CODEC_ID_ROQ, + AV_CODEC_ID_INTERPLAY_VIDEO, + AV_CODEC_ID_XAN_WC3, + AV_CODEC_ID_XAN_WC4, + AV_CODEC_ID_RPZA, + AV_CODEC_ID_CINEPAK, + AV_CODEC_ID_WS_VQA, + AV_CODEC_ID_MSRLE, + AV_CODEC_ID_MSVIDEO1, + AV_CODEC_ID_IDCIN, + AV_CODEC_ID_8BPS, + AV_CODEC_ID_SMC, + AV_CODEC_ID_FLIC, + AV_CODEC_ID_TRUEMOTION1, + AV_CODEC_ID_VMDVIDEO, + AV_CODEC_ID_MSZH, + AV_CODEC_ID_ZLIB, + AV_CODEC_ID_QTRLE, + AV_CODEC_ID_TSCC, + AV_CODEC_ID_ULTI, + AV_CODEC_ID_QDRAW, + AV_CODEC_ID_VIXL, + AV_CODEC_ID_QPEG, + AV_CODEC_ID_PNG, + AV_CODEC_ID_PPM, + AV_CODEC_ID_PBM, + AV_CODEC_ID_PGM, + AV_CODEC_ID_PGMYUV, + AV_CODEC_ID_PAM, + AV_CODEC_ID_FFVHUFF, + AV_CODEC_ID_RV30, + AV_CODEC_ID_RV40, + AV_CODEC_ID_VC1, + AV_CODEC_ID_WMV3, + AV_CODEC_ID_LOCO, + AV_CODEC_ID_WNV1, + AV_CODEC_ID_AASC, + AV_CODEC_ID_INDEO2, + AV_CODEC_ID_FRAPS, + AV_CODEC_ID_TRUEMOTION2, + AV_CODEC_ID_BMP, + AV_CODEC_ID_CSCD, + AV_CODEC_ID_MMVIDEO, + AV_CODEC_ID_ZMBV, + AV_CODEC_ID_AVS, + AV_CODEC_ID_SMACKVIDEO, + AV_CODEC_ID_NUV, + AV_CODEC_ID_KMVC, + AV_CODEC_ID_FLASHSV, + AV_CODEC_ID_CAVS, + AV_CODEC_ID_JPEG2000, + AV_CODEC_ID_VMNC, + AV_CODEC_ID_VP5, + AV_CODEC_ID_VP6, + AV_CODEC_ID_VP6F, + AV_CODEC_ID_TARGA, + AV_CODEC_ID_DSICINVIDEO, + AV_CODEC_ID_TIERTEXSEQVIDEO, + AV_CODEC_ID_TIFF, + AV_CODEC_ID_GIF, + AV_CODEC_ID_DXA, + AV_CODEC_ID_DNXHD, + AV_CODEC_ID_THP, + AV_CODEC_ID_SGI, + AV_CODEC_ID_C93, + AV_CODEC_ID_BETHSOFTVID, + AV_CODEC_ID_PTX, + AV_CODEC_ID_TXD, + AV_CODEC_ID_VP6A, + AV_CODEC_ID_AMV, + AV_CODEC_ID_VB, + AV_CODEC_ID_PCX, + AV_CODEC_ID_SUNRAST, + AV_CODEC_ID_INDEO4, + AV_CODEC_ID_INDEO5, + AV_CODEC_ID_MIMIC, + AV_CODEC_ID_RL2, + AV_CODEC_ID_ESCAPE124, + AV_CODEC_ID_DIRAC, + AV_CODEC_ID_BFI, + AV_CODEC_ID_CMV, + AV_CODEC_ID_MOTIONPIXELS, + AV_CODEC_ID_TGV, + AV_CODEC_ID_TGQ, + AV_CODEC_ID_TQI, + AV_CODEC_ID_AURA, + AV_CODEC_ID_AURA2, + AV_CODEC_ID_V210X, + AV_CODEC_ID_TMV, + AV_CODEC_ID_V210, + AV_CODEC_ID_DPX, + AV_CODEC_ID_MAD, + AV_CODEC_ID_FRWU, + AV_CODEC_ID_FLASHSV2, + AV_CODEC_ID_CDGRAPHICS, + AV_CODEC_ID_R210, + AV_CODEC_ID_ANM, + AV_CODEC_ID_BINKVIDEO, + AV_CODEC_ID_IFF_ILBM, +#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM + AV_CODEC_ID_KGV1, + AV_CODEC_ID_YOP, + AV_CODEC_ID_VP8, + AV_CODEC_ID_PICTOR, + AV_CODEC_ID_ANSI, + AV_CODEC_ID_A64_MULTI, + AV_CODEC_ID_A64_MULTI5, + AV_CODEC_ID_R10K, + AV_CODEC_ID_MXPEG, + AV_CODEC_ID_LAGARITH, + AV_CODEC_ID_PRORES, + AV_CODEC_ID_JV, + AV_CODEC_ID_DFA, + AV_CODEC_ID_WMV3IMAGE, + AV_CODEC_ID_VC1IMAGE, + AV_CODEC_ID_UTVIDEO, + AV_CODEC_ID_BMV_VIDEO, + AV_CODEC_ID_VBLE, + AV_CODEC_ID_DXTORY, + AV_CODEC_ID_V410, + AV_CODEC_ID_XWD, + AV_CODEC_ID_CDXL, + AV_CODEC_ID_XBM, + AV_CODEC_ID_ZEROCODEC, + AV_CODEC_ID_MSS1, + AV_CODEC_ID_MSA1, + AV_CODEC_ID_TSCC2, + AV_CODEC_ID_MTS2, + AV_CODEC_ID_CLLC, + AV_CODEC_ID_MSS2, + AV_CODEC_ID_VP9, + AV_CODEC_ID_AIC, + AV_CODEC_ID_ESCAPE130, + AV_CODEC_ID_G2M, + AV_CODEC_ID_WEBP, + AV_CODEC_ID_HNM4_VIDEO, + AV_CODEC_ID_HEVC, +#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC + AV_CODEC_ID_FIC, + AV_CODEC_ID_ALIAS_PIX, + AV_CODEC_ID_BRENDER_PIX, + AV_CODEC_ID_PAF_VIDEO, + AV_CODEC_ID_EXR, + AV_CODEC_ID_VP7, + AV_CODEC_ID_SANM, + AV_CODEC_ID_SGIRLE, + AV_CODEC_ID_MVC1, + AV_CODEC_ID_MVC2, + AV_CODEC_ID_HQX, + AV_CODEC_ID_TDSC, + AV_CODEC_ID_HQ_HQA, + AV_CODEC_ID_HAP, + AV_CODEC_ID_DDS, + AV_CODEC_ID_DXV, + AV_CODEC_ID_SCREENPRESSO, + AV_CODEC_ID_RSCC, + AV_CODEC_ID_AVS2, + AV_CODEC_ID_PGX, + AV_CODEC_ID_AVS3, + AV_CODEC_ID_MSP2, + AV_CODEC_ID_VVC, +#define AV_CODEC_ID_H266 AV_CODEC_ID_VVC + + AV_CODEC_ID_Y41P = 0x8000, + AV_CODEC_ID_AVRP, + AV_CODEC_ID_012V, + AV_CODEC_ID_AVUI, + AV_CODEC_ID_AYUV, + AV_CODEC_ID_TARGA_Y216, + AV_CODEC_ID_V308, + AV_CODEC_ID_V408, + AV_CODEC_ID_YUV4, + AV_CODEC_ID_AVRN, + AV_CODEC_ID_CPIA, + AV_CODEC_ID_XFACE, + AV_CODEC_ID_SNOW, + AV_CODEC_ID_SMVJPEG, + AV_CODEC_ID_APNG, + AV_CODEC_ID_DAALA, + AV_CODEC_ID_CFHD, + AV_CODEC_ID_TRUEMOTION2RT, + AV_CODEC_ID_M101, + AV_CODEC_ID_MAGICYUV, + AV_CODEC_ID_SHEERVIDEO, + AV_CODEC_ID_YLC, + AV_CODEC_ID_PSD, + AV_CODEC_ID_PIXLET, + AV_CODEC_ID_SPEEDHQ, + AV_CODEC_ID_FMVC, + AV_CODEC_ID_SCPR, + AV_CODEC_ID_CLEARVIDEO, + AV_CODEC_ID_XPM, + AV_CODEC_ID_AV1, + AV_CODEC_ID_BITPACKED, + AV_CODEC_ID_MSCC, + AV_CODEC_ID_SRGC, + AV_CODEC_ID_SVG, + AV_CODEC_ID_GDV, + AV_CODEC_ID_FITS, + AV_CODEC_ID_IMM4, + AV_CODEC_ID_PROSUMER, + AV_CODEC_ID_MWSC, + AV_CODEC_ID_WCMV, + AV_CODEC_ID_RASC, + AV_CODEC_ID_HYMT, + AV_CODEC_ID_ARBC, + AV_CODEC_ID_AGM, + AV_CODEC_ID_LSCR, + AV_CODEC_ID_VP4, + AV_CODEC_ID_IMM5, + AV_CODEC_ID_MVDV, + AV_CODEC_ID_MVHA, + AV_CODEC_ID_CDTOONS, + AV_CODEC_ID_MV30, + AV_CODEC_ID_NOTCHLC, + AV_CODEC_ID_PFM, + AV_CODEC_ID_MOBICLIP, + AV_CODEC_ID_PHOTOCD, + AV_CODEC_ID_IPU, + AV_CODEC_ID_ARGO, + AV_CODEC_ID_CRI, + AV_CODEC_ID_SIMBIOSIS_IMX, + AV_CODEC_ID_SGA_VIDEO, + + /* various PCM "codecs" */ + AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs + AV_CODEC_ID_PCM_S16LE = 0x10000, + AV_CODEC_ID_PCM_S16BE, + AV_CODEC_ID_PCM_U16LE, + AV_CODEC_ID_PCM_U16BE, + AV_CODEC_ID_PCM_S8, + AV_CODEC_ID_PCM_U8, + AV_CODEC_ID_PCM_MULAW, + AV_CODEC_ID_PCM_ALAW, + AV_CODEC_ID_PCM_S32LE, + AV_CODEC_ID_PCM_S32BE, + AV_CODEC_ID_PCM_U32LE, + AV_CODEC_ID_PCM_U32BE, + AV_CODEC_ID_PCM_S24LE, + AV_CODEC_ID_PCM_S24BE, + AV_CODEC_ID_PCM_U24LE, + AV_CODEC_ID_PCM_U24BE, + AV_CODEC_ID_PCM_S24DAUD, + AV_CODEC_ID_PCM_ZORK, + AV_CODEC_ID_PCM_S16LE_PLANAR, + AV_CODEC_ID_PCM_DVD, + AV_CODEC_ID_PCM_F32BE, + AV_CODEC_ID_PCM_F32LE, + AV_CODEC_ID_PCM_F64BE, + AV_CODEC_ID_PCM_F64LE, + AV_CODEC_ID_PCM_BLURAY, + AV_CODEC_ID_PCM_LXF, + AV_CODEC_ID_S302M, + AV_CODEC_ID_PCM_S8_PLANAR, + AV_CODEC_ID_PCM_S24LE_PLANAR, + AV_CODEC_ID_PCM_S32LE_PLANAR, + AV_CODEC_ID_PCM_S16BE_PLANAR, + + AV_CODEC_ID_PCM_S64LE = 0x10800, + AV_CODEC_ID_PCM_S64BE, + AV_CODEC_ID_PCM_F16LE, + AV_CODEC_ID_PCM_F24LE, + AV_CODEC_ID_PCM_VIDC, + AV_CODEC_ID_PCM_SGA, + + /* various ADPCM codecs */ + AV_CODEC_ID_ADPCM_IMA_QT = 0x11000, + AV_CODEC_ID_ADPCM_IMA_WAV, + AV_CODEC_ID_ADPCM_IMA_DK3, + AV_CODEC_ID_ADPCM_IMA_DK4, + AV_CODEC_ID_ADPCM_IMA_WS, + AV_CODEC_ID_ADPCM_IMA_SMJPEG, + AV_CODEC_ID_ADPCM_MS, + AV_CODEC_ID_ADPCM_4XM, + AV_CODEC_ID_ADPCM_XA, + AV_CODEC_ID_ADPCM_ADX, + AV_CODEC_ID_ADPCM_EA, + AV_CODEC_ID_ADPCM_G726, + AV_CODEC_ID_ADPCM_CT, + AV_CODEC_ID_ADPCM_SWF, + AV_CODEC_ID_ADPCM_YAMAHA, + AV_CODEC_ID_ADPCM_SBPRO_4, + AV_CODEC_ID_ADPCM_SBPRO_3, + AV_CODEC_ID_ADPCM_SBPRO_2, + AV_CODEC_ID_ADPCM_THP, + AV_CODEC_ID_ADPCM_IMA_AMV, + AV_CODEC_ID_ADPCM_EA_R1, + AV_CODEC_ID_ADPCM_EA_R3, + AV_CODEC_ID_ADPCM_EA_R2, + AV_CODEC_ID_ADPCM_IMA_EA_SEAD, + AV_CODEC_ID_ADPCM_IMA_EA_EACS, + AV_CODEC_ID_ADPCM_EA_XAS, + AV_CODEC_ID_ADPCM_EA_MAXIS_XA, + AV_CODEC_ID_ADPCM_IMA_ISS, + AV_CODEC_ID_ADPCM_G722, + AV_CODEC_ID_ADPCM_IMA_APC, + AV_CODEC_ID_ADPCM_VIMA, + + AV_CODEC_ID_ADPCM_AFC = 0x11800, + AV_CODEC_ID_ADPCM_IMA_OKI, + AV_CODEC_ID_ADPCM_DTK, + AV_CODEC_ID_ADPCM_IMA_RAD, + AV_CODEC_ID_ADPCM_G726LE, + AV_CODEC_ID_ADPCM_THP_LE, + AV_CODEC_ID_ADPCM_PSX, + AV_CODEC_ID_ADPCM_AICA, + AV_CODEC_ID_ADPCM_IMA_DAT4, + AV_CODEC_ID_ADPCM_MTAF, + AV_CODEC_ID_ADPCM_AGM, + AV_CODEC_ID_ADPCM_ARGO, + AV_CODEC_ID_ADPCM_IMA_SSI, + AV_CODEC_ID_ADPCM_ZORK, + AV_CODEC_ID_ADPCM_IMA_APM, + AV_CODEC_ID_ADPCM_IMA_ALP, + AV_CODEC_ID_ADPCM_IMA_MTF, + AV_CODEC_ID_ADPCM_IMA_CUNNING, + AV_CODEC_ID_ADPCM_IMA_MOFLEX, + + /* AMR */ + AV_CODEC_ID_AMR_NB = 0x12000, + AV_CODEC_ID_AMR_WB, + + /* RealAudio codecs*/ + AV_CODEC_ID_RA_144 = 0x13000, + AV_CODEC_ID_RA_288, + + /* various DPCM codecs */ + AV_CODEC_ID_ROQ_DPCM = 0x14000, + AV_CODEC_ID_INTERPLAY_DPCM, + AV_CODEC_ID_XAN_DPCM, + AV_CODEC_ID_SOL_DPCM, + + AV_CODEC_ID_SDX2_DPCM = 0x14800, + AV_CODEC_ID_GREMLIN_DPCM, + AV_CODEC_ID_DERF_DPCM, + + /* audio codecs */ + AV_CODEC_ID_MP2 = 0x15000, + AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 + AV_CODEC_ID_AAC, + AV_CODEC_ID_AC3, + AV_CODEC_ID_DTS, + AV_CODEC_ID_VORBIS, + AV_CODEC_ID_DVAUDIO, + AV_CODEC_ID_WMAV1, + AV_CODEC_ID_WMAV2, + AV_CODEC_ID_MACE3, + AV_CODEC_ID_MACE6, + AV_CODEC_ID_VMDAUDIO, + AV_CODEC_ID_FLAC, + AV_CODEC_ID_MP3ADU, + AV_CODEC_ID_MP3ON4, + AV_CODEC_ID_SHORTEN, + AV_CODEC_ID_ALAC, + AV_CODEC_ID_WESTWOOD_SND1, + AV_CODEC_ID_GSM, ///< as in Berlin toast format + AV_CODEC_ID_QDM2, + AV_CODEC_ID_COOK, + AV_CODEC_ID_TRUESPEECH, + AV_CODEC_ID_TTA, + AV_CODEC_ID_SMACKAUDIO, + AV_CODEC_ID_QCELP, + AV_CODEC_ID_WAVPACK, + AV_CODEC_ID_DSICINAUDIO, + AV_CODEC_ID_IMC, + AV_CODEC_ID_MUSEPACK7, + AV_CODEC_ID_MLP, + AV_CODEC_ID_GSM_MS, /* as found in WAV */ + AV_CODEC_ID_ATRAC3, + AV_CODEC_ID_APE, + AV_CODEC_ID_NELLYMOSER, + AV_CODEC_ID_MUSEPACK8, + AV_CODEC_ID_SPEEX, + AV_CODEC_ID_WMAVOICE, + AV_CODEC_ID_WMAPRO, + AV_CODEC_ID_WMALOSSLESS, + AV_CODEC_ID_ATRAC3P, + AV_CODEC_ID_EAC3, + AV_CODEC_ID_SIPR, + AV_CODEC_ID_MP1, + AV_CODEC_ID_TWINVQ, + AV_CODEC_ID_TRUEHD, + AV_CODEC_ID_MP4ALS, + AV_CODEC_ID_ATRAC1, + AV_CODEC_ID_BINKAUDIO_RDFT, + AV_CODEC_ID_BINKAUDIO_DCT, + AV_CODEC_ID_AAC_LATM, + AV_CODEC_ID_QDMC, + AV_CODEC_ID_CELT, + AV_CODEC_ID_G723_1, + AV_CODEC_ID_G729, + AV_CODEC_ID_8SVX_EXP, + AV_CODEC_ID_8SVX_FIB, + AV_CODEC_ID_BMV_AUDIO, + AV_CODEC_ID_RALF, + AV_CODEC_ID_IAC, + AV_CODEC_ID_ILBC, + AV_CODEC_ID_OPUS, + AV_CODEC_ID_COMFORT_NOISE, + AV_CODEC_ID_TAK, + AV_CODEC_ID_METASOUND, + AV_CODEC_ID_PAF_AUDIO, + AV_CODEC_ID_ON2AVC, + AV_CODEC_ID_DSS_SP, + AV_CODEC_ID_CODEC2, + + AV_CODEC_ID_FFWAVESYNTH = 0x15800, + AV_CODEC_ID_SONIC, + AV_CODEC_ID_SONIC_LS, + AV_CODEC_ID_EVRC, + AV_CODEC_ID_SMV, + AV_CODEC_ID_DSD_LSBF, + AV_CODEC_ID_DSD_MSBF, + AV_CODEC_ID_DSD_LSBF_PLANAR, + AV_CODEC_ID_DSD_MSBF_PLANAR, + AV_CODEC_ID_4GV, + AV_CODEC_ID_INTERPLAY_ACM, + AV_CODEC_ID_XMA1, + AV_CODEC_ID_XMA2, + AV_CODEC_ID_DST, + AV_CODEC_ID_ATRAC3AL, + AV_CODEC_ID_ATRAC3PAL, + AV_CODEC_ID_DOLBY_E, + AV_CODEC_ID_APTX, + AV_CODEC_ID_APTX_HD, + AV_CODEC_ID_SBC, + AV_CODEC_ID_ATRAC9, + AV_CODEC_ID_HCOM, + AV_CODEC_ID_ACELP_KELVIN, + AV_CODEC_ID_MPEGH_3D_AUDIO, + AV_CODEC_ID_SIREN, + AV_CODEC_ID_HCA, + AV_CODEC_ID_FASTAUDIO, + + /* subtitle codecs */ + AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. + AV_CODEC_ID_DVD_SUBTITLE = 0x17000, + AV_CODEC_ID_DVB_SUBTITLE, + AV_CODEC_ID_TEXT, ///< raw UTF-8 text + AV_CODEC_ID_XSUB, + AV_CODEC_ID_SSA, + AV_CODEC_ID_MOV_TEXT, + AV_CODEC_ID_HDMV_PGS_SUBTITLE, + AV_CODEC_ID_DVB_TELETEXT, + AV_CODEC_ID_SRT, + + AV_CODEC_ID_MICRODVD = 0x17800, + AV_CODEC_ID_EIA_608, + AV_CODEC_ID_JACOSUB, + AV_CODEC_ID_SAMI, + AV_CODEC_ID_REALTEXT, + AV_CODEC_ID_STL, + AV_CODEC_ID_SUBVIEWER1, + AV_CODEC_ID_SUBVIEWER, + AV_CODEC_ID_SUBRIP, + AV_CODEC_ID_WEBVTT, + AV_CODEC_ID_MPL2, + AV_CODEC_ID_VPLAYER, + AV_CODEC_ID_PJS, + AV_CODEC_ID_ASS, + AV_CODEC_ID_HDMV_TEXT_SUBTITLE, + AV_CODEC_ID_TTML, + AV_CODEC_ID_ARIB_CAPTION, + + /* other specific kind of codecs (generally used for attachments) */ + AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. + AV_CODEC_ID_TTF = 0x18000, + + AV_CODEC_ID_SCTE_35, ///< Contain timestamp estimated through PCR of program stream. + AV_CODEC_ID_EPG, + AV_CODEC_ID_BINTEXT = 0x18800, + AV_CODEC_ID_XBIN, + AV_CODEC_ID_IDF, + AV_CODEC_ID_OTF, + AV_CODEC_ID_SMPTE_KLV, + AV_CODEC_ID_DVD_NAV, + AV_CODEC_ID_TIMED_ID3, + AV_CODEC_ID_BIN_DATA, + + + AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it + + AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + * stream (only used by libavformat) */ + AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems + * stream (only used by libavformat) */ + AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. + AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket +}; + +/** + * Get the type of the given codec. + */ +enum AVMediaType avcodec_get_type(enum AVCodecID codec_id); + +/** + * Get the name of a codec. + * @return a static string identifying the codec; never NULL + */ +const char *avcodec_get_name(enum AVCodecID id); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_ID_H diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec_par.h b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec_par.h new file mode 100644 index 0000000000000..948758e2373d1 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/codec_par.h @@ -0,0 +1,229 @@ +/* + * Codec parameters public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_PAR_H +#define AVCODEC_CODEC_PAR_H + +#include + +#include "libavutil/avutil.h" +#include "libavutil/rational.h" +#include "libavutil/pixfmt.h" + +#include "codec_id.h" + +/** + * @addtogroup lavc_core + */ + +enum AVFieldOrder { + AV_FIELD_UNKNOWN, + AV_FIELD_PROGRESSIVE, + AV_FIELD_TT, //< Top coded_first, top displayed first + AV_FIELD_BB, //< Bottom coded first, bottom displayed first + AV_FIELD_TB, //< Top coded first, bottom displayed first + AV_FIELD_BT, //< Bottom coded first, top displayed first +}; + +/** + * This struct describes the properties of an encoded stream. + * + * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must + * be allocated with avcodec_parameters_alloc() and freed with + * avcodec_parameters_free(). + */ +typedef struct AVCodecParameters { + /** + * General type of the encoded data. + */ + enum AVMediaType codec_type; + /** + * Specific type of the encoded data (the codec used). + */ + enum AVCodecID codec_id; + /** + * Additional information about the codec (corresponds to the AVI FOURCC). + */ + uint32_t codec_tag; + + /** + * Extra binary data needed for initializing the decoder, codec-dependent. + * + * Must be allocated with av_malloc() and will be freed by + * avcodec_parameters_free(). The allocated size of extradata must be at + * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding + * bytes zeroed. + */ + uint8_t *extradata; + /** + * Size of the extradata content in bytes. + */ + int extradata_size; + + /** + * - video: the pixel format, the value corresponds to enum AVPixelFormat. + * - audio: the sample format, the value corresponds to enum AVSampleFormat. + */ + int format; + + /** + * The average bitrate of the encoded data (in bits per second). + */ + int64_t bit_rate; + + /** + * The number of bits per sample in the codedwords. + * + * This is basically the bitrate per sample. It is mandatory for a bunch of + * formats to actually decode them. It's the number of bits for one sample in + * the actual coded bitstream. + * + * This could be for example 4 for ADPCM + * For PCM formats this matches bits_per_raw_sample + * Can be 0 + */ + int bits_per_coded_sample; + + /** + * This is the number of valid bits in each output sample. If the + * sample format has more bits, the least significant bits are additional + * padding bits, which are always 0. Use right shifts to reduce the sample + * to its actual size. For example, audio formats with 24 bit samples will + * have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32. + * To get the original sample use "(int32_t)sample >> 8"." + * + * For ADPCM this might be 12 or 16 or similar + * Can be 0 + */ + int bits_per_raw_sample; + + /** + * Codec-specific bitstream restrictions that the stream conforms to. + */ + int profile; + int level; + + /** + * Video only. The dimensions of the video frame in pixels. + */ + int width; + int height; + + /** + * Video only. The aspect ratio (width / height) which a single pixel + * should have when displayed. + * + * When the aspect ratio is unknown / undefined, the numerator should be + * set to 0 (the denominator may have any value). + */ + AVRational sample_aspect_ratio; + + /** + * Video only. The order of the fields in interlaced video. + */ + enum AVFieldOrder field_order; + + /** + * Video only. Additional colorspace characteristics. + */ + enum AVColorRange color_range; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace color_space; + enum AVChromaLocation chroma_location; + + /** + * Video only. Number of delayed frames. + */ + int video_delay; + + /** + * Audio only. The channel layout bitmask. May be 0 if the channel layout is + * unknown or unspecified, otherwise the number of bits set must be equal to + * the channels field. + */ + uint64_t channel_layout; + /** + * Audio only. The number of audio channels. + */ + int channels; + /** + * Audio only. The number of audio samples per second. + */ + int sample_rate; + /** + * Audio only. The number of bytes per coded audio frame, required by some + * formats. + * + * Corresponds to nBlockAlign in WAVEFORMATEX. + */ + int block_align; + /** + * Audio only. Audio frame size, if known. Required by some formats to be static. + */ + int frame_size; + + /** + * Audio only. The amount of padding (in samples) inserted by the encoder at + * the beginning of the audio. I.e. this number of leading decoded samples + * must be discarded by the caller to get the original audio without leading + * padding. + */ + int initial_padding; + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + */ + int trailing_padding; + /** + * Audio only. Number of samples to skip after a discontinuity. + */ + int seek_preroll; +} AVCodecParameters; + +/** + * Allocate a new AVCodecParameters and set its fields to default values + * (unknown/invalid/0). The returned struct must be freed with + * avcodec_parameters_free(). + */ +AVCodecParameters *avcodec_parameters_alloc(void); + +/** + * Free an AVCodecParameters instance and everything associated with it and + * write NULL to the supplied pointer. + */ +void avcodec_parameters_free(AVCodecParameters **par); + +/** + * Copy the contents of src to dst. Any allocated fields in dst are freed and + * replaced with newly allocated duplicates of the corresponding fields in src. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src); + + +/** + * @} + */ + +#endif // AVCODEC_CODEC_PAR_H diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/packet.h b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/packet.h new file mode 100644 index 0000000000000..ca18ae631f362 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/packet.h @@ -0,0 +1,774 @@ +/* + * AVPacket public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_PACKET_H +#define AVCODEC_PACKET_H + +#include +#include + +#include "libavutil/attributes.h" +#include "libavutil/buffer.h" +#include "libavutil/dict.h" +#include "libavutil/rational.h" + +#include "libavcodec/version.h" + +/** + * @defgroup lavc_packet AVPacket + * + * Types and functions for working with AVPacket. + * @{ + */ +enum AVPacketSideDataType { + /** + * An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE + * bytes worth of palette. This side data signals that a new palette is + * present. + */ + AV_PKT_DATA_PALETTE, + + /** + * The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format + * that the extradata buffer was changed and the receiving side should + * act upon it appropriately. The new extradata is embedded in the side + * data buffer and should be immediately used for processing the current + * frame or packet. + */ + AV_PKT_DATA_NEW_EXTRADATA, + + /** + * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows: + * @code + * u32le param_flags + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) + * s32le channel_count + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) + * u64le channel_layout + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) + * s32le sample_rate + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) + * s32le width + * s32le height + * @endcode + */ + AV_PKT_DATA_PARAM_CHANGE, + + /** + * An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of + * structures with info about macroblocks relevant to splitting the + * packet into smaller packets on macroblock edges (e.g. as for RFC 2190). + * That is, it does not necessarily contain info about all macroblocks, + * as long as the distance between macroblocks in the info is smaller + * than the target payload size. + * Each MB info structure is 12 bytes, and is laid out as follows: + * @code + * u32le bit offset from the start of the packet + * u8 current quantizer at the start of the macroblock + * u8 GOB number + * u16le macroblock address within the GOB + * u8 horizontal MV predictor + * u8 vertical MV predictor + * u8 horizontal MV predictor for block number 3 + * u8 vertical MV predictor for block number 3 + * @endcode + */ + AV_PKT_DATA_H263_MB_INFO, + + /** + * This side data should be associated with an audio stream and contains + * ReplayGain information in form of the AVReplayGain struct. + */ + AV_PKT_DATA_REPLAYGAIN, + + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the decoded video frames for + * correct presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_PKT_DATA_DISPLAYMATRIX, + + /** + * This side data should be associated with a video stream and contains + * Stereoscopic 3D information in form of the AVStereo3D struct. + */ + AV_PKT_DATA_STEREO3D, + + /** + * This side data should be associated with an audio stream and corresponds + * to enum AVAudioServiceType. + */ + AV_PKT_DATA_AUDIO_SERVICE_TYPE, + + /** + * This side data contains quality related information from the encoder. + * @code + * u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad). + * u8 picture type + * u8 error count + * u16 reserved + * u64le[error count] sum of squared differences between encoder in and output + * @endcode + */ + AV_PKT_DATA_QUALITY_STATS, + + /** + * This side data contains an integer value representing the stream index + * of a "fallback" track. A fallback track indicates an alternate + * track to use when the current track can not be decoded for some reason. + * e.g. no decoder available for codec. + */ + AV_PKT_DATA_FALLBACK_TRACK, + + /** + * This side data corresponds to the AVCPBProperties struct. + */ + AV_PKT_DATA_CPB_PROPERTIES, + + /** + * Recommmends skipping the specified number of samples + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_PKT_DATA_SKIP_SAMPLES, + + /** + * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that + * the packet may contain "dual mono" audio specific to Japanese DTV + * and if it is true, recommends only the selected channel to be used. + * @code + * u8 selected channels (0=mail/left, 1=sub/right, 2=both) + * @endcode + */ + AV_PKT_DATA_JP_DUALMONO, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. + */ + AV_PKT_DATA_STRINGS_METADATA, + + /** + * Subtitle event position + * @code + * u32le x1 + * u32le y1 + * u32le x2 + * u32le y2 + * @endcode + */ + AV_PKT_DATA_SUBTITLE_POSITION, + + /** + * Data found in BlockAdditional element of matroska container. There is + * no end marker for the data, so it is required to rely on the side data + * size to recognize the end. 8 byte id (as found in BlockAddId) followed + * by data. + */ + AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + + /** + * The optional first identifier line of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_IDENTIFIER, + + /** + * The optional settings (rendering instructions) that immediately + * follow the timestamp specifier of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_SETTINGS, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. This + * side data includes updated metadata which appeared in the stream. + */ + AV_PKT_DATA_METADATA_UPDATE, + + /** + * MPEGTS stream ID as uint8_t, this is required to pass the stream ID + * information from the demuxer to the corresponding muxer. + */ + AV_PKT_DATA_MPEGTS_STREAM_ID, + + /** + * Mastering display metadata (based on SMPTE-2086:2014). This metadata + * should be associated with a video stream and contains data in the form + * of the AVMasteringDisplayMetadata struct. + */ + AV_PKT_DATA_MASTERING_DISPLAY_METADATA, + + /** + * This side data should be associated with a video stream and corresponds + * to the AVSphericalMapping structure. + */ + AV_PKT_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This metadata should be + * associated with a video stream and contains data in the form of the + * AVContentLightMetadata struct. + */ + AV_PKT_DATA_CONTENT_LIGHT_LEVEL, + + /** + * ATSC A53 Part 4 Closed Captions. This metadata should be associated with + * a video stream. A53 CC bitstream is stored as uint8_t in AVPacketSideData.data. + * The number of bytes of CC data is AVPacketSideData.size. + */ + AV_PKT_DATA_A53_CC, + + /** + * This side data is encryption initialization data. + * The format is not part of ABI, use av_encryption_init_info_* methods to + * access. + */ + AV_PKT_DATA_ENCRYPTION_INIT_INFO, + + /** + * This side data contains encryption info for how to decrypt the packet. + * The format is not part of ABI, use av_encryption_info_* methods to access. + */ + AV_PKT_DATA_ENCRYPTION_INFO, + + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_PKT_DATA_AFD, + + /** + * Producer Reference Time data corresponding to the AVProducerReferenceTime struct, + * usually exported by some encoders (on demand through the prft flag set in the + * AVCodecContext export_side_data field). + */ + AV_PKT_DATA_PRFT, + + /** + * ICC profile data consisting of an opaque octet buffer following the + * format described by ISO 15076-1. + */ + AV_PKT_DATA_ICC_PROFILE, + + /** + * DOVI configuration + * ref: + * dolby-vision-bitstreams-within-the-iso-base-media-file-format-v2.1.2, section 2.2 + * dolby-vision-bitstreams-in-mpeg-2-transport-stream-multiplex-v1.2, section 3.3 + * Tags are stored in struct AVDOVIDecoderConfigurationRecord. + */ + AV_PKT_DATA_DOVI_CONF, + + /** + * Timecode which conforms to SMPTE ST 12-1:2014. The data is an array of 4 uint32_t + * where the first uint32_t describes how many (1-3) of the other timecodes are used. + * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.h. + */ + AV_PKT_DATA_S12M_TIMECODE, + + /** + * The number of side data types. + * This is not part of the public API/ABI in the sense that it may + * change when new side data types are added. + * This must stay the last enum value. + * If its value becomes huge, some code using it + * needs to be updated as it assumes it to be smaller than other limits. + */ + AV_PKT_DATA_NB +}; + +#define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED + +typedef struct AVPacketSideData { + uint8_t *data; +#if FF_API_BUFFER_SIZE_T + int size; +#else + size_t size; +#endif + enum AVPacketSideDataType type; +} AVPacketSideData; + +/** + * This structure stores compressed data. It is typically exported by demuxers + * and then passed as input to decoders, or received as output from encoders and + * then passed to muxers. + * + * For video, it should typically contain one compressed frame. For audio it may + * contain several compressed frames. Encoders are allowed to output empty + * packets, with no compressed data, containing only side data + * (e.g. to update some stream parameters at the end of encoding). + * + * The semantics of data ownership depends on the buf field. + * If it is set, the packet data is dynamically allocated and is + * valid indefinitely until a call to av_packet_unref() reduces the + * reference count to 0. + * + * If the buf field is not set av_packet_ref() would make a copy instead + * of increasing the reference count. + * + * The side data is always allocated with av_malloc(), copied by + * av_packet_ref() and freed by av_packet_unref(). + * + * sizeof(AVPacket) being a part of the public ABI is deprecated. once + * av_init_packet() is removed, new packets will only be able to be allocated + * with av_packet_alloc(), and new fields may be added to the end of the struct + * with a minor bump. + * + * @see av_packet_alloc + * @see av_packet_ref + * @see av_packet_unref + */ +typedef struct AVPacket { + /** + * A reference to the reference-counted buffer where the packet data is + * stored. + * May be NULL, then the packet data is not reference-counted. + */ + AVBufferRef *buf; + /** + * Presentation timestamp in AVStream->time_base units; the time at which + * the decompressed packet will be presented to the user. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + * pts MUST be larger or equal to dts as presentation cannot happen before + * decompression, unless one wants to view hex dumps. Some formats misuse + * the terms dts and pts/cts to mean something different. Such timestamps + * must be converted to true pts/dts before they are stored in AVPacket. + */ + int64_t pts; + /** + * Decompression timestamp in AVStream->time_base units; the time at which + * the packet is decompressed. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + */ + int64_t dts; + uint8_t *data; + int size; + int stream_index; + /** + * A combination of AV_PKT_FLAG values + */ + int flags; + /** + * Additional packet data that can be provided by the container. + * Packet can contain several types of side information. + */ + AVPacketSideData *side_data; + int side_data_elems; + + /** + * Duration of this packet in AVStream->time_base units, 0 if unknown. + * Equals next_pts - this_pts in presentation order. + */ + int64_t duration; + + int64_t pos; ///< byte position in stream, -1 if unknown + +#if FF_API_CONVERGENCE_DURATION + /** + * @deprecated Same as the duration field, but as int64_t. This was required + * for Matroska subtitles, whose duration values could overflow when the + * duration field was still an int. + */ + attribute_deprecated + int64_t convergence_duration; +#endif +} AVPacket; + +#if FF_API_INIT_PACKET +attribute_deprecated +typedef struct AVPacketList { + AVPacket pkt; + struct AVPacketList *next; +} AVPacketList; +#endif + +#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe +#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted +/** + * Flag is used to discard packets which are required to maintain valid + * decoder state but are not required for output and should be dropped + * after decoding. + **/ +#define AV_PKT_FLAG_DISCARD 0x0004 +/** + * The packet comes from a trusted source. + * + * Otherwise-unsafe constructs such as arbitrary pointers to data + * outside the packet may be followed. + */ +#define AV_PKT_FLAG_TRUSTED 0x0008 +/** + * Flag is used to indicate packets that contain frames that can + * be discarded by the decoder. I.e. Non-reference frames. + */ +#define AV_PKT_FLAG_DISPOSABLE 0x0010 + +enum AVSideDataParamChangeFlags { + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002, + AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004, + AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008, +}; + +/** + * Allocate an AVPacket and set its fields to default values. The resulting + * struct must be freed using av_packet_free(). + * + * @return An AVPacket filled with default values or NULL on failure. + * + * @note this only allocates the AVPacket itself, not the data buffers. Those + * must be allocated through other means such as av_new_packet. + * + * @see av_new_packet + */ +AVPacket *av_packet_alloc(void); + +/** + * Create a new packet that references the same data as src. + * + * This is a shortcut for av_packet_alloc()+av_packet_ref(). + * + * @return newly created AVPacket on success, NULL on error. + * + * @see av_packet_alloc + * @see av_packet_ref + */ +AVPacket *av_packet_clone(const AVPacket *src); + +/** + * Free the packet, if the packet is reference counted, it will be + * unreferenced first. + * + * @param pkt packet to be freed. The pointer will be set to NULL. + * @note passing NULL is a no-op. + */ +void av_packet_free(AVPacket **pkt); + +#if FF_API_INIT_PACKET +/** + * Initialize optional fields of a packet with default values. + * + * Note, this does not touch the data and size members, which have to be + * initialized separately. + * + * @param pkt packet + * + * @see av_packet_alloc + * @see av_packet_unref + * + * @deprecated This function is deprecated. Once it's removed, + sizeof(AVPacket) will not be a part of the ABI anymore. + */ +attribute_deprecated +void av_init_packet(AVPacket *pkt); +#endif + +/** + * Allocate the payload of a packet and initialize its fields with + * default values. + * + * @param pkt packet + * @param size wanted payload size + * @return 0 if OK, AVERROR_xxx otherwise + */ +int av_new_packet(AVPacket *pkt, int size); + +/** + * Reduce packet size, correctly zeroing padding + * + * @param pkt packet + * @param size new size + */ +void av_shrink_packet(AVPacket *pkt, int size); + +/** + * Increase packet size, correctly zeroing padding + * + * @param pkt packet + * @param grow_by number of bytes by which to increase the size of the packet + */ +int av_grow_packet(AVPacket *pkt, int grow_by); + +/** + * Initialize a reference-counted packet from av_malloc()ed data. + * + * @param pkt packet to be initialized. This function will set the data, size, + * and buf fields, all others are left untouched. + * @param data Data allocated by av_malloc() to be used as packet data. If this + * function returns successfully, the data is owned by the underlying AVBuffer. + * The caller may not access the data through other means. + * @param size size of data in bytes, without the padding. I.e. the full buffer + * size is assumed to be size + AV_INPUT_BUFFER_PADDING_SIZE. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size); + +#if FF_API_AVPACKET_OLD_API +/** + * @warning This is a hack - the packet memory allocation stuff is broken. The + * packet is allocated if it was not really allocated. + * + * @deprecated Use av_packet_ref or av_packet_make_refcounted + */ +attribute_deprecated +int av_dup_packet(AVPacket *pkt); +/** + * Copy packet, including contents + * + * @return 0 on success, negative AVERROR on fail + * + * @deprecated Use av_packet_ref + */ +attribute_deprecated +int av_copy_packet(AVPacket *dst, const AVPacket *src); + +/** + * Copy packet side data + * + * @return 0 on success, negative AVERROR on fail + * + * @deprecated Use av_packet_copy_props + */ +attribute_deprecated +int av_copy_packet_side_data(AVPacket *dst, const AVPacket *src); + +/** + * Free a packet. + * + * @deprecated Use av_packet_unref + * + * @param pkt packet to free + */ +attribute_deprecated +void av_free_packet(AVPacket *pkt); +#endif +/** + * Allocate new information of a packet. + * + * @param pkt packet + * @param type side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, +#if FF_API_BUFFER_SIZE_T + int size); +#else + size_t size); +#endif + +/** + * Wrap an existing array as a packet side data. + * + * @param pkt packet + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * pkt. + * @param size side information size + * @return a non-negative number on success, a negative AVERROR code on + * failure. On failure, the packet is unchanged and the data remains + * owned by the caller. + */ +int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + +/** + * Shrink the already allocated side data buffer + * + * @param pkt packet + * @param type side information type + * @param size new side information size + * @return 0 on success, < 0 on failure + */ +int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, +#if FF_API_BUFFER_SIZE_T + int size); +#else + size_t size); +#endif + +/** + * Get side information from packet. + * + * @param pkt packet + * @param type desired side information type + * @param size If supplied, *size will be set to the size of the side data + * or to zero if the desired side data is not present. + * @return pointer to data if present or NULL otherwise + */ +uint8_t* av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, +#if FF_API_BUFFER_SIZE_T + int *size); +#else + size_t *size); +#endif + +#if FF_API_MERGE_SD_API +attribute_deprecated +int av_packet_merge_side_data(AVPacket *pkt); + +attribute_deprecated +int av_packet_split_side_data(AVPacket *pkt); +#endif + +const char *av_packet_side_data_name(enum AVPacketSideDataType type); + +/** + * Pack a dictionary for use in side_data. + * + * @param dict The dictionary to pack. + * @param size pointer to store the size of the returned data + * @return pointer to data if successful, NULL otherwise + */ +#if FF_API_BUFFER_SIZE_T +uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size); +#else +uint8_t *av_packet_pack_dictionary(AVDictionary *dict, size_t *size); +#endif +/** + * Unpack a dictionary from side_data. + * + * @param data data from side_data + * @param size size of the data + * @param dict the metadata storage dictionary + * @return 0 on success, < 0 on failure + */ +#if FF_API_BUFFER_SIZE_T +int av_packet_unpack_dictionary(const uint8_t *data, int size, AVDictionary **dict); +#else +int av_packet_unpack_dictionary(const uint8_t *data, size_t size, + AVDictionary **dict); +#endif + +/** + * Convenience function to free all the side data stored. + * All the other fields stay untouched. + * + * @param pkt packet + */ +void av_packet_free_side_data(AVPacket *pkt); + +/** + * Setup a new reference to the data described by a given packet + * + * If src is reference-counted, setup dst as a new reference to the + * buffer in src. Otherwise allocate a new buffer in dst and copy the + * data from src into it. + * + * All the other fields are copied from src. + * + * @see av_packet_unref + * + * @param dst Destination packet. Will be completely overwritten. + * @param src Source packet + * + * @return 0 on success, a negative AVERROR on error. On error, dst + * will be blank (as if returned by av_packet_alloc()). + */ +int av_packet_ref(AVPacket *dst, const AVPacket *src); + +/** + * Wipe the packet. + * + * Unreference the buffer referenced by the packet and reset the + * remaining packet fields to their default values. + * + * @param pkt The packet to be unreferenced. + */ +void av_packet_unref(AVPacket *pkt); + +/** + * Move every field in src to dst and reset src. + * + * @see av_packet_unref + * + * @param src Source packet, will be reset + * @param dst Destination packet + */ +void av_packet_move_ref(AVPacket *dst, AVPacket *src); + +/** + * Copy only "properties" fields from src to dst. + * + * Properties for the purpose of this function are all the fields + * beside those related to the packet data (buf, data, size) + * + * @param dst Destination packet + * @param src Source packet + * + * @return 0 on success AVERROR on failure. + */ +int av_packet_copy_props(AVPacket *dst, const AVPacket *src); + +/** + * Ensure the data described by a given packet is reference counted. + * + * @note This function does not ensure that the reference will be writable. + * Use av_packet_make_writable instead for that purpose. + * + * @see av_packet_ref + * @see av_packet_make_writable + * + * @param pkt packet whose data should be made reference counted. + * + * @return 0 on success, a negative AVERROR on error. On failure, the + * packet is unchanged. + */ +int av_packet_make_refcounted(AVPacket *pkt); + +/** + * Create a writable reference for the data described by a given packet, + * avoiding data copy if possible. + * + * @param pkt Packet whose data should be made writable. + * + * @return 0 on success, a negative AVERROR on failure. On failure, the + * packet is unchanged. + */ +int av_packet_make_writable(AVPacket *pkt); + +/** + * Convert valid timing fields (timestamps / durations) in a packet from one + * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be + * ignored. + * + * @param pkt packet on which the conversion will be performed + * @param tb_src source timebase, in which the timing fields in pkt are + * expressed + * @param tb_dst destination timebase, to which the timing fields will be + * converted + */ +void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst); + +/** + * @} + */ + +#endif // AVCODEC_PACKET_H diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/version.h b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/version.h new file mode 100644 index 0000000000000..cfdde469600bd --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavcodec/version.h @@ -0,0 +1,172 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VERSION_H +#define AVCODEC_VERSION_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#include "libavutil/version.h" + +#define LIBAVCODEC_VERSION_MAJOR 58 +#define LIBAVCODEC_VERSION_MINOR 134 +#define LIBAVCODEC_VERSION_MICRO 100 + +#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT + +#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + */ + +#ifndef FF_API_AVCTX_TIMEBASE +#define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CODED_FRAME +#define FF_API_CODED_FRAME (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_SIDEDATA_ONLY_PKT +#define FF_API_SIDEDATA_ONLY_PKT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_VDPAU_PROFILE +#define FF_API_VDPAU_PROFILE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CONVERGENCE_DURATION +#define FF_API_CONVERGENCE_DURATION (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_AVPICTURE +#define FF_API_AVPICTURE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_AVPACKET_OLD_API +#define FF_API_AVPACKET_OLD_API (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_RTP_CALLBACK +#define FF_API_RTP_CALLBACK (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_VBV_DELAY +#define FF_API_VBV_DELAY (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CODER_TYPE +#define FF_API_CODER_TYPE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_STAT_BITS +#define FF_API_STAT_BITS (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_PRIVATE_OPT +#define FF_API_PRIVATE_OPT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_ASS_TIMING +#define FF_API_ASS_TIMING (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_OLD_BSF +#define FF_API_OLD_BSF (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_COPY_CONTEXT +#define FF_API_COPY_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_GET_CONTEXT_DEFAULTS +#define FF_API_GET_CONTEXT_DEFAULTS (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_NVENC_OLD_NAME +#define FF_API_NVENC_OLD_NAME (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_STRUCT_VAAPI_CONTEXT +#define FF_API_STRUCT_VAAPI_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_MERGE_SD_API +#define FF_API_MERGE_SD_API (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_TAG_STRING +#define FF_API_TAG_STRING (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_GETCHROMA +#define FF_API_GETCHROMA (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CODEC_GET_SET +#define FF_API_CODEC_GET_SET (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_USER_VISIBLE_AVHWACCEL +#define FF_API_USER_VISIBLE_AVHWACCEL (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_LOCKMGR +#define FF_API_LOCKMGR (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_NEXT +#define FF_API_NEXT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_UNSANITIZED_BITRATES +#define FF_API_UNSANITIZED_BITRATES (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_OPENH264_SLICE_MODE +#define FF_API_OPENH264_SLICE_MODE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_OPENH264_CABAC +#define FF_API_OPENH264_CABAC (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_UNUSED_CODEC_CAPS +#define FF_API_UNUSED_CODEC_CAPS (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_AVPRIV_PUT_BITS +#define FF_API_AVPRIV_PUT_BITS (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_OLD_ENCDEC +#define FF_API_OLD_ENCDEC (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_AVCODEC_PIX_FMT +#define FF_API_AVCODEC_PIX_FMT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_MPV_RC_STRATEGY +#define FF_API_MPV_RC_STRATEGY (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_PARSER_CHANGE +#define FF_API_PARSER_CHANGE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_THREAD_SAFE_CALLBACKS +#define FF_API_THREAD_SAFE_CALLBACKS (LIBAVCODEC_VERSION_MAJOR < 60) +#endif +#ifndef FF_API_DEBUG_MV +#define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 60) +#endif +#ifndef FF_API_GET_FRAME_CLASS +#define FF_API_GET_FRAME_CLASS (LIBAVCODEC_VERSION_MAJOR < 60) +#endif +#ifndef FF_API_AUTO_THREADS +#define FF_API_AUTO_THREADS (LIBAVCODEC_VERSION_MAJOR < 60) +#endif +#ifndef FF_API_INIT_PACKET +#define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 60) +#endif + +#endif /* AVCODEC_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavformat/avformat.h b/src/framework/media/thirdparty/ffmpeg/v4/libavformat/avformat.h new file mode 100644 index 0000000000000..56708c02410ef --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavformat/avformat.h @@ -0,0 +1,3012 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_AVFORMAT_H +#define AVFORMAT_AVFORMAT_H + +/** + * @file + * @ingroup libavf + * Main libavformat public API header + */ + +/** + * @defgroup libavf libavformat + * I/O and Muxing/Demuxing Library + * + * Libavformat (lavf) is a library for dealing with various media container + * formats. Its main two purposes are demuxing - i.e. splitting a media file + * into component streams, and the reverse process of muxing - writing supplied + * data in a specified container format. It also has an @ref lavf_io + * "I/O module" which supports a number of protocols for accessing the data (e.g. + * file, tcp, http and others). + * Unless you are absolutely sure you won't use libavformat's network + * capabilities, you should also call avformat_network_init(). + * + * A supported input format is described by an AVInputFormat struct, conversely + * an output format is described by AVOutputFormat. You can iterate over all + * input/output formats using the av_demuxer_iterate / av_muxer_iterate() functions. + * The protocols layer is not part of the public API, so you can only get the names + * of supported protocols with the avio_enum_protocols() function. + * + * Main lavf structure used for both muxing and demuxing is AVFormatContext, + * which exports all information about the file being read or written. As with + * most Libavformat structures, its size is not part of public ABI, so it cannot be + * allocated on stack or directly with av_malloc(). To create an + * AVFormatContext, use avformat_alloc_context() (some functions, like + * avformat_open_input() might do that for you). + * + * Most importantly an AVFormatContext contains: + * @li the @ref AVFormatContext.iformat "input" or @ref AVFormatContext.oformat + * "output" format. It is either autodetected or set by user for input; + * always set by user for output. + * @li an @ref AVFormatContext.streams "array" of AVStreams, which describe all + * elementary streams stored in the file. AVStreams are typically referred to + * using their index in this array. + * @li an @ref AVFormatContext.pb "I/O context". It is either opened by lavf or + * set by user for input, always set by user for output (unless you are dealing + * with an AVFMT_NOFILE format). + * + * @section lavf_options Passing options to (de)muxers + * It is possible to configure lavf muxers and demuxers using the @ref avoptions + * mechanism. Generic (format-independent) libavformat options are provided by + * AVFormatContext, they can be examined from a user program by calling + * av_opt_next() / av_opt_find() on an allocated AVFormatContext (or its AVClass + * from avformat_get_class()). Private (format-specific) options are provided by + * AVFormatContext.priv_data if and only if AVInputFormat.priv_class / + * AVOutputFormat.priv_class of the corresponding format struct is non-NULL. + * Further options may be provided by the @ref AVFormatContext.pb "I/O context", + * if its AVClass is non-NULL, and the protocols layer. See the discussion on + * nesting in @ref avoptions documentation to learn how to access those. + * + * @section urls + * URL strings in libavformat are made of a scheme/protocol, a ':', and a + * scheme specific string. URLs without a scheme and ':' used for local files + * are supported but deprecated. "file:" should be used for local files. + * + * It is important that the scheme string is not taken from untrusted + * sources without checks. + * + * Note that some schemes/protocols are quite powerful, allowing access to + * both local and remote files, parts of them, concatenations of them, local + * audio and video devices and so on. + * + * @{ + * + * @defgroup lavf_decoding Demuxing + * @{ + * Demuxers read a media file and split it into chunks of data (@em packets). A + * @ref AVPacket "packet" contains one or more encoded frames which belongs to a + * single elementary stream. In the lavf API this process is represented by the + * avformat_open_input() function for opening a file, av_read_frame() for + * reading a single packet and finally avformat_close_input(), which does the + * cleanup. + * + * @section lavf_decoding_open Opening a media file + * The minimum information required to open a file is its URL, which + * is passed to avformat_open_input(), as in the following code: + * @code + * const char *url = "file:in.mp3"; + * AVFormatContext *s = NULL; + * int ret = avformat_open_input(&s, url, NULL, NULL); + * if (ret < 0) + * abort(); + * @endcode + * The above code attempts to allocate an AVFormatContext, open the + * specified file (autodetecting the format) and read the header, exporting the + * information stored there into s. Some formats do not have a header or do not + * store enough information there, so it is recommended that you call the + * avformat_find_stream_info() function which tries to read and decode a few + * frames to find missing information. + * + * In some cases you might want to preallocate an AVFormatContext yourself with + * avformat_alloc_context() and do some tweaking on it before passing it to + * avformat_open_input(). One such case is when you want to use custom functions + * for reading input data instead of lavf internal I/O layer. + * To do that, create your own AVIOContext with avio_alloc_context(), passing + * your reading callbacks to it. Then set the @em pb field of your + * AVFormatContext to newly created AVIOContext. + * + * Since the format of the opened file is in general not known until after + * avformat_open_input() has returned, it is not possible to set demuxer private + * options on a preallocated context. Instead, the options should be passed to + * avformat_open_input() wrapped in an AVDictionary: + * @code + * AVDictionary *options = NULL; + * av_dict_set(&options, "video_size", "640x480", 0); + * av_dict_set(&options, "pixel_format", "rgb24", 0); + * + * if (avformat_open_input(&s, url, NULL, &options) < 0) + * abort(); + * av_dict_free(&options); + * @endcode + * This code passes the private options 'video_size' and 'pixel_format' to the + * demuxer. They would be necessary for e.g. the rawvideo demuxer, since it + * cannot know how to interpret raw video data otherwise. If the format turns + * out to be something different than raw video, those options will not be + * recognized by the demuxer and therefore will not be applied. Such unrecognized + * options are then returned in the options dictionary (recognized options are + * consumed). The calling program can handle such unrecognized options as it + * wishes, e.g. + * @code + * AVDictionaryEntry *e; + * if (e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX)) { + * fprintf(stderr, "Option %s not recognized by the demuxer.\n", e->key); + * abort(); + * } + * @endcode + * + * After you have finished reading the file, you must close it with + * avformat_close_input(). It will free everything associated with the file. + * + * @section lavf_decoding_read Reading from an opened file + * Reading data from an opened AVFormatContext is done by repeatedly calling + * av_read_frame() on it. Each call, if successful, will return an AVPacket + * containing encoded data for one AVStream, identified by + * AVPacket.stream_index. This packet may be passed straight into the libavcodec + * decoding functions avcodec_send_packet() or avcodec_decode_subtitle2() if the + * caller wishes to decode the data. + * + * AVPacket.pts, AVPacket.dts and AVPacket.duration timing information will be + * set if known. They may also be unset (i.e. AV_NOPTS_VALUE for + * pts/dts, 0 for duration) if the stream does not provide them. The timing + * information will be in AVStream.time_base units, i.e. it has to be + * multiplied by the timebase to convert them to seconds. + * + * A packet returned by av_read_frame() is always reference-counted, + * i.e. AVPacket.buf is set and the user may keep it indefinitely. + * The packet must be freed with av_packet_unref() when it is no + * longer needed. + * + * @section lavf_decoding_seek Seeking + * @} + * + * @defgroup lavf_encoding Muxing + * @{ + * Muxers take encoded data in the form of @ref AVPacket "AVPackets" and write + * it into files or other output bytestreams in the specified container format. + * + * The main API functions for muxing are avformat_write_header() for writing the + * file header, av_write_frame() / av_interleaved_write_frame() for writing the + * packets and av_write_trailer() for finalizing the file. + * + * At the beginning of the muxing process, the caller must first call + * avformat_alloc_context() to create a muxing context. The caller then sets up + * the muxer by filling the various fields in this context: + * + * - The @ref AVFormatContext.oformat "oformat" field must be set to select the + * muxer that will be used. + * - Unless the format is of the AVFMT_NOFILE type, the @ref AVFormatContext.pb + * "pb" field must be set to an opened IO context, either returned from + * avio_open2() or a custom one. + * - Unless the format is of the AVFMT_NOSTREAMS type, at least one stream must + * be created with the avformat_new_stream() function. The caller should fill + * the @ref AVStream.codecpar "stream codec parameters" information, such as the + * codec @ref AVCodecParameters.codec_type "type", @ref AVCodecParameters.codec_id + * "id" and other parameters (e.g. width / height, the pixel or sample format, + * etc.) as known. The @ref AVStream.time_base "stream timebase" should + * be set to the timebase that the caller desires to use for this stream (note + * that the timebase actually used by the muxer can be different, as will be + * described later). + * - It is advised to manually initialize only the relevant fields in + * AVCodecParameters, rather than using @ref avcodec_parameters_copy() during + * remuxing: there is no guarantee that the codec context values remain valid + * for both input and output format contexts. + * - The caller may fill in additional information, such as @ref + * AVFormatContext.metadata "global" or @ref AVStream.metadata "per-stream" + * metadata, @ref AVFormatContext.chapters "chapters", @ref + * AVFormatContext.programs "programs", etc. as described in the + * AVFormatContext documentation. Whether such information will actually be + * stored in the output depends on what the container format and the muxer + * support. + * + * When the muxing context is fully set up, the caller must call + * avformat_write_header() to initialize the muxer internals and write the file + * header. Whether anything actually is written to the IO context at this step + * depends on the muxer, but this function must always be called. Any muxer + * private options must be passed in the options parameter to this function. + * + * The data is then sent to the muxer by repeatedly calling av_write_frame() or + * av_interleaved_write_frame() (consult those functions' documentation for + * discussion on the difference between them; only one of them may be used with + * a single muxing context, they should not be mixed). Do note that the timing + * information on the packets sent to the muxer must be in the corresponding + * AVStream's timebase. That timebase is set by the muxer (in the + * avformat_write_header() step) and may be different from the timebase + * requested by the caller. + * + * Once all the data has been written, the caller must call av_write_trailer() + * to flush any buffered packets and finalize the output file, then close the IO + * context (if any) and finally free the muxing context with + * avformat_free_context(). + * @} + * + * @defgroup lavf_io I/O Read/Write + * @{ + * @section lavf_io_dirlist Directory listing + * The directory listing API makes it possible to list files on remote servers. + * + * Some of possible use cases: + * - an "open file" dialog to choose files from a remote location, + * - a recursive media finder providing a player with an ability to play all + * files from a given directory. + * + * @subsection lavf_io_dirlist_open Opening a directory + * At first, a directory needs to be opened by calling avio_open_dir() + * supplied with a URL and, optionally, ::AVDictionary containing + * protocol-specific parameters. The function returns zero or positive + * integer and allocates AVIODirContext on success. + * + * @code + * AVIODirContext *ctx = NULL; + * if (avio_open_dir(&ctx, "smb://example.com/some_dir", NULL) < 0) { + * fprintf(stderr, "Cannot open directory.\n"); + * abort(); + * } + * @endcode + * + * This code tries to open a sample directory using smb protocol without + * any additional parameters. + * + * @subsection lavf_io_dirlist_read Reading entries + * Each directory's entry (i.e. file, another directory, anything else + * within ::AVIODirEntryType) is represented by AVIODirEntry. + * Reading consecutive entries from an opened AVIODirContext is done by + * repeatedly calling avio_read_dir() on it. Each call returns zero or + * positive integer if successful. Reading can be stopped right after the + * NULL entry has been read -- it means there are no entries left to be + * read. The following code reads all entries from a directory associated + * with ctx and prints their names to standard output. + * @code + * AVIODirEntry *entry = NULL; + * for (;;) { + * if (avio_read_dir(ctx, &entry) < 0) { + * fprintf(stderr, "Cannot list directory.\n"); + * abort(); + * } + * if (!entry) + * break; + * printf("%s\n", entry->name); + * avio_free_directory_entry(&entry); + * } + * @endcode + * @} + * + * @defgroup lavf_codec Demuxers + * @{ + * @defgroup lavf_codec_native Native Demuxers + * @{ + * @} + * @defgroup lavf_codec_wrappers External library wrappers + * @{ + * @} + * @} + * @defgroup lavf_protos I/O Protocols + * @{ + * @} + * @defgroup lavf_internal Internal + * @{ + * @} + * @} + */ + +#include +#include /* FILE */ +#include "libavcodec/avcodec.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" + +#include "avio.h" +#include "libavformat/version.h" + +struct AVFormatContext; + +struct AVDeviceInfoList; +struct AVDeviceCapabilitiesQuery; + +/** + * @defgroup metadata_api Public Metadata API + * @{ + * @ingroup libavf + * The metadata API allows libavformat to export metadata tags to a client + * application when demuxing. Conversely it allows a client application to + * set metadata when muxing. + * + * Metadata is exported or set as pairs of key/value strings in the 'metadata' + * fields of the AVFormatContext, AVStream, AVChapter and AVProgram structs + * using the @ref lavu_dict "AVDictionary" API. Like all strings in FFmpeg, + * metadata is assumed to be UTF-8 encoded Unicode. Note that metadata + * exported by demuxers isn't checked to be valid UTF-8 in most cases. + * + * Important concepts to keep in mind: + * - Keys are unique; there can never be 2 tags with the same key. This is + * also meant semantically, i.e., a demuxer should not knowingly produce + * several keys that are literally different but semantically identical. + * E.g., key=Author5, key=Author6. In this example, all authors must be + * placed in the same tag. + * - Metadata is flat, not hierarchical; there are no subtags. If you + * want to store, e.g., the email address of the child of producer Alice + * and actor Bob, that could have key=alice_and_bobs_childs_email_address. + * - Several modifiers can be applied to the tag name. This is done by + * appending a dash character ('-') and the modifier name in the order + * they appear in the list below -- e.g. foo-eng-sort, not foo-sort-eng. + * - language -- a tag whose value is localized for a particular language + * is appended with the ISO 639-2/B 3-letter language code. + * For example: Author-ger=Michael, Author-eng=Mike + * The original/default language is in the unqualified "Author" tag. + * A demuxer should set a default if it sets any translated tag. + * - sorting -- a modified version of a tag that should be used for + * sorting will have '-sort' appended. E.g. artist="The Beatles", + * artist-sort="Beatles, The". + * - Some protocols and demuxers support metadata updates. After a successful + * call to av_read_frame(), AVFormatContext.event_flags or AVStream.event_flags + * will be updated to indicate if metadata changed. In order to detect metadata + * changes on a stream, you need to loop through all streams in the AVFormatContext + * and check their individual event_flags. + * + * - Demuxers attempt to export metadata in a generic format, however tags + * with no generic equivalents are left as they are stored in the container. + * Follows a list of generic tag names: + * + @verbatim + album -- name of the set this work belongs to + album_artist -- main creator of the set/album, if different from artist. + e.g. "Various Artists" for compilation albums. + artist -- main creator of the work + comment -- any additional description of the file. + composer -- who composed the work, if different from artist. + copyright -- name of copyright holder. + creation_time-- date when the file was created, preferably in ISO 8601. + date -- date when the work was created, preferably in ISO 8601. + disc -- number of a subset, e.g. disc in a multi-disc collection. + encoder -- name/settings of the software/hardware that produced the file. + encoded_by -- person/group who created the file. + filename -- original name of the file. + genre -- . + language -- main language in which the work is performed, preferably + in ISO 639-2 format. Multiple languages can be specified by + separating them with commas. + performer -- artist who performed the work, if different from artist. + E.g for "Also sprach Zarathustra", artist would be "Richard + Strauss" and performer "London Philharmonic Orchestra". + publisher -- name of the label/publisher. + service_name -- name of the service in broadcasting (channel name). + service_provider -- name of the service provider in broadcasting. + title -- name of the work. + track -- number of this work in the set, can be in form current/total. + variant_bitrate -- the total bitrate of the bitrate variant that the current stream is part of + @endverbatim + * + * Look in the examples section for an application example how to use the Metadata API. + * + * @} + */ + +/* packet functions */ + + +/** + * Allocate and read the payload of a packet and initialize its + * fields with default values. + * + * @param s associated IO context + * @param pkt packet + * @param size desired payload size + * @return >0 (read size) if OK, AVERROR_xxx otherwise + */ +int av_get_packet(AVIOContext *s, AVPacket *pkt, int size); + + +/** + * Read data and append it to the current content of the AVPacket. + * If pkt->size is 0 this is identical to av_get_packet. + * Note that this uses av_grow_packet and thus involves a realloc + * which is inefficient. Thus this function should only be used + * when there is no reasonable way to know (an upper bound of) + * the final size. + * + * @param s associated IO context + * @param pkt packet + * @param size amount of data to read + * @return >0 (read size) if OK, AVERROR_xxx otherwise, previous data + * will not be lost even if an error occurs. + */ +int av_append_packet(AVIOContext *s, AVPacket *pkt, int size); + +/*************************************************/ +/* input/output formats */ + +struct AVCodecTag; + +/** + * This structure contains the data a format has to probe a file. + */ +typedef struct AVProbeData { + const char *filename; + unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */ + int buf_size; /**< Size of buf except extra allocated bytes */ + const char *mime_type; /**< mime_type, when known. */ +} AVProbeData; + +#define AVPROBE_SCORE_RETRY (AVPROBE_SCORE_MAX/4) +#define AVPROBE_SCORE_STREAM_RETRY (AVPROBE_SCORE_MAX/4-1) + +#define AVPROBE_SCORE_EXTENSION 50 ///< score for file extension +#define AVPROBE_SCORE_MIME 75 ///< score for file mime type +#define AVPROBE_SCORE_MAX 100 ///< maximum score + +#define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer + +/// Demuxer will use avio_open, no opened file should be provided by the caller. +#define AVFMT_NOFILE 0x0001 +#define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */ +#define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */ +#define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */ +#define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */ +#define AVFMT_GENERIC_INDEX 0x0100 /**< Use generic index building code. */ +#define AVFMT_TS_DISCONT 0x0200 /**< Format allows timestamp discontinuities. Note, muxers always require valid (monotone) timestamps */ +#define AVFMT_VARIABLE_FPS 0x0400 /**< Format allows variable fps. */ +#define AVFMT_NODIMENSIONS 0x0800 /**< Format does not need width/height */ +#define AVFMT_NOSTREAMS 0x1000 /**< Format does not require any streams */ +#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fall back on binary search via read_timestamp */ +#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fall back on generic search */ +#define AVFMT_NO_BYTE_SEEK 0x8000 /**< Format does not allow seeking by bytes */ +#define AVFMT_ALLOW_FLUSH 0x10000 /**< Format allows flushing. If not set, the muxer will not receive a NULL packet in the write_packet function. */ +#define AVFMT_TS_NONSTRICT 0x20000 /**< Format does not require strictly + increasing timestamps, but they must + still be monotonic */ +#define AVFMT_TS_NEGATIVE 0x40000 /**< Format allows muxing negative + timestamps. If not set the timestamp + will be shifted in av_write_frame and + av_interleaved_write_frame so they + start from 0. + The user or muxer can override this through + AVFormatContext.avoid_negative_ts + */ + +#define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */ + +/** + * @addtogroup lavf_encoding + * @{ + */ +typedef struct AVOutputFormat { + const char *name; + /** + * Descriptive name for the format, meant to be more human-readable + * than name. You should use the NULL_IF_CONFIG_SMALL() macro + * to define it. + */ + const char *long_name; + const char *mime_type; + const char *extensions; /**< comma-separated filename extensions */ + /* output support */ + enum AVCodecID audio_codec; /**< default audio codec */ + enum AVCodecID video_codec; /**< default video codec */ + enum AVCodecID subtitle_codec; /**< default subtitle codec */ + /** + * can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, + * AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, + * AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH, + * AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE + */ + int flags; + + /** + * List of supported codec_id-codec_tag pairs, ordered by "better + * choice first". The arrays are all terminated by AV_CODEC_ID_NONE. + */ + const struct AVCodecTag * const *codec_tag; + + + const AVClass *priv_class; ///< AVClass for the private context + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + /** + * The ff_const59 define is not part of the public API and will + * be removed without further warning. + */ +#if FF_API_AVIOFORMAT +#define ff_const59 +#else +#define ff_const59 const +#endif +#if FF_API_NEXT + ff_const59 struct AVOutputFormat *next; +#endif + /** + * size of private data so that it can be allocated in the wrapper + */ + int priv_data_size; + + int (*write_header)(struct AVFormatContext *); + /** + * Write a packet. If AVFMT_ALLOW_FLUSH is set in flags, + * pkt can be NULL in order to flush data buffered in the muxer. + * When flushing, return 0 if there still is more data to flush, + * or 1 if everything was flushed and there is no more buffered + * data. + */ + int (*write_packet)(struct AVFormatContext *, AVPacket *pkt); + int (*write_trailer)(struct AVFormatContext *); + /** + * A format-specific function for interleavement. + * If unset, packets will be interleaved by dts. + */ + int (*interleave_packet)(struct AVFormatContext *, AVPacket *out, + AVPacket *in, int flush); + /** + * Test if the given codec can be stored in this container. + * + * @return 1 if the codec is supported, 0 if it is not. + * A negative number if unknown. + * MKTAG('A', 'P', 'I', 'C') if the codec is only supported as AV_DISPOSITION_ATTACHED_PIC + */ + int (*query_codec)(enum AVCodecID id, int std_compliance); + + void (*get_output_timestamp)(struct AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall); + /** + * Allows sending messages from application to device. + */ + int (*control_message)(struct AVFormatContext *s, int type, + void *data, size_t data_size); + + /** + * Write an uncoded AVFrame. + * + * See av_write_uncoded_frame() for details. + * + * The library will free *frame afterwards, but the muxer can prevent it + * by setting the pointer to NULL. + */ + int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index, + AVFrame **frame, unsigned flags); + /** + * Returns device list with it properties. + * @see avdevice_list_devices() for more details. + */ + int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list); +#if LIBAVFORMAT_VERSION_MAJOR < 59 + /** + * Initialize device capabilities submodule. + * @see avdevice_capabilities_create() for more details. + */ + int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps); + /** + * Free device capabilities submodule. + * @see avdevice_capabilities_free() for more details. + */ + int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps); +#endif + enum AVCodecID data_codec; /**< default data codec */ + /** + * Initialize format. May allocate data here, and set any AVFormatContext or + * AVStream parameters that need to be set before packets are sent. + * This method must not write output. + * + * Return 0 if streams were fully configured, 1 if not, negative AVERROR on failure + * + * Any allocations made here must be freed in deinit(). + */ + int (*init)(struct AVFormatContext *); + /** + * Deinitialize format. If present, this is called whenever the muxer is being + * destroyed, regardless of whether or not the header has been written. + * + * If a trailer is being written, this is called after write_trailer(). + * + * This is called if init() fails as well. + */ + void (*deinit)(struct AVFormatContext *); + /** + * Set up any necessary bitstream filtering and extract any extra data needed + * for the global header. + * Return 0 if more packets from this stream must be checked; 1 if not. + */ + int (*check_bitstream)(struct AVFormatContext *, const AVPacket *pkt); +} AVOutputFormat; +/** + * @} + */ + +/** + * @addtogroup lavf_decoding + * @{ + */ +typedef struct AVInputFormat { + /** + * A comma separated list of short names for the format. New names + * may be appended with a minor bump. + */ + const char *name; + + /** + * Descriptive name for the format, meant to be more human-readable + * than name. You should use the NULL_IF_CONFIG_SMALL() macro + * to define it. + */ + const char *long_name; + + /** + * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS, + * AVFMT_NOTIMESTAMPS, AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH, + * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS. + */ + int flags; + + /** + * If extensions are defined, then no probe is done. You should + * usually not use extension format guessing because it is not + * reliable enough + */ + const char *extensions; + + const struct AVCodecTag * const *codec_tag; + + const AVClass *priv_class; ///< AVClass for the private context + + /** + * Comma-separated list of mime types. + * It is used check for matching mime types while probing. + * @see av_probe_input_format2 + */ + const char *mime_type; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ +#if FF_API_NEXT + ff_const59 struct AVInputFormat *next; +#endif + + /** + * Raw demuxers store their codec ID here. + */ + int raw_codec_id; + + /** + * Size of private data so that it can be allocated in the wrapper. + */ + int priv_data_size; + + /** + * Tell if a given file has a chance of being parsed as this format. + * The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes + * big so you do not have to check for that unless you need more. + */ + int (*read_probe)(const AVProbeData *); + + /** + * Read the format header and initialize the AVFormatContext + * structure. Return 0 if OK. 'avformat_new_stream' should be + * called to create new streams. + */ + int (*read_header)(struct AVFormatContext *); + + /** + * Read one packet and put it in 'pkt'. pts and flags are also + * set. 'avformat_new_stream' can be called only if the flag + * AVFMTCTX_NOHEADER is used and only in the calling thread (not in a + * background thread). + * @return 0 on success, < 0 on error. + * Upon returning an error, pkt must be unreferenced by the caller. + */ + int (*read_packet)(struct AVFormatContext *, AVPacket *pkt); + + /** + * Close the stream. The AVFormatContext and AVStreams are not + * freed by this function + */ + int (*read_close)(struct AVFormatContext *); + + /** + * Seek to a given timestamp relative to the frames in + * stream component stream_index. + * @param stream_index Must not be -1. + * @param flags Selects which direction should be preferred if no exact + * match is available. + * @return >= 0 on success (but not necessarily the new offset) + */ + int (*read_seek)(struct AVFormatContext *, + int stream_index, int64_t timestamp, int flags); + + /** + * Get the next timestamp in stream[stream_index].time_base units. + * @return the timestamp or AV_NOPTS_VALUE if an error occurred + */ + int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index, + int64_t *pos, int64_t pos_limit); + + /** + * Start/resume playing - only meaningful if using a network-based format + * (RTSP). + */ + int (*read_play)(struct AVFormatContext *); + + /** + * Pause playing - only meaningful if using a network-based format + * (RTSP). + */ + int (*read_pause)(struct AVFormatContext *); + + /** + * Seek to timestamp ts. + * Seeking will be done so that the point from which all active streams + * can be presented successfully will be closest to ts and within min/max_ts. + * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL. + */ + int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); + + /** + * Returns device list with it properties. + * @see avdevice_list_devices() for more details. + */ + int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list); + +#if LIBAVFORMAT_VERSION_MAJOR < 59 + /** + * Initialize device capabilities submodule. + * @see avdevice_capabilities_create() for more details. + */ + int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps); + + /** + * Free device capabilities submodule. + * @see avdevice_capabilities_free() for more details. + */ + int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps); +#endif +} AVInputFormat; +/** + * @} + */ + +enum AVStreamParseType { + AVSTREAM_PARSE_NONE, + AVSTREAM_PARSE_FULL, /**< full parsing and repack */ + AVSTREAM_PARSE_HEADERS, /**< Only parse headers, do not repack. */ + AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on a packet boundary */ + AVSTREAM_PARSE_FULL_ONCE, /**< full parsing and repack of the first frame only, only implemented for H.264 currently */ + AVSTREAM_PARSE_FULL_RAW, /**< full parsing and repack with timestamp and position generation by parser for raw + this assumes that each packet in the file contains no demuxer level headers and + just codec level data, otherwise position generation would fail */ +}; + +typedef struct AVIndexEntry { + int64_t pos; + int64_t timestamp; /**< + * Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are available + * when seeking to this entry. That means preferable PTS on keyframe based formats. + * But demuxers can choose to store a different timestamp, if it is more convenient for the implementation or nothing better + * is known + */ +#define AVINDEX_KEYFRAME 0x0001 +#define AVINDEX_DISCARD_FRAME 0x0002 /** + * Flag is used to indicate which frame should be discarded after decoding. + */ + int flags:2; + int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment). + int min_distance; /**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. */ +} AVIndexEntry; + +#define AV_DISPOSITION_DEFAULT 0x0001 +#define AV_DISPOSITION_DUB 0x0002 +#define AV_DISPOSITION_ORIGINAL 0x0004 +#define AV_DISPOSITION_COMMENT 0x0008 +#define AV_DISPOSITION_LYRICS 0x0010 +#define AV_DISPOSITION_KARAOKE 0x0020 + +/** + * Track should be used during playback by default. + * Useful for subtitle track that should be displayed + * even when user did not explicitly ask for subtitles. + */ +#define AV_DISPOSITION_FORCED 0x0040 +#define AV_DISPOSITION_HEARING_IMPAIRED 0x0080 /**< stream for hearing impaired audiences */ +#define AV_DISPOSITION_VISUAL_IMPAIRED 0x0100 /**< stream for visual impaired audiences */ +#define AV_DISPOSITION_CLEAN_EFFECTS 0x0200 /**< stream without voice */ +/** + * The stream is stored in the file as an attached picture/"cover art" (e.g. + * APIC frame in ID3v2). The first (usually only) packet associated with it + * will be returned among the first few packets read from the file unless + * seeking takes place. It can also be accessed at any time in + * AVStream.attached_pic. + */ +#define AV_DISPOSITION_ATTACHED_PIC 0x0400 +/** + * The stream is sparse, and contains thumbnail images, often corresponding + * to chapter markers. Only ever used with AV_DISPOSITION_ATTACHED_PIC. + */ +#define AV_DISPOSITION_TIMED_THUMBNAILS 0x0800 + +typedef struct AVStreamInternal AVStreamInternal; + +/** + * To specify text track kind (different from subtitles default). + */ +#define AV_DISPOSITION_CAPTIONS 0x10000 +#define AV_DISPOSITION_DESCRIPTIONS 0x20000 +#define AV_DISPOSITION_METADATA 0x40000 +#define AV_DISPOSITION_DEPENDENT 0x80000 ///< dependent audio stream (mix_type=0 in mpegts) +#define AV_DISPOSITION_STILL_IMAGE 0x100000 ///< still images in video stream (still_picture_flag=1 in mpegts) + +/** + * Options for behavior on timestamp wrap detection. + */ +#define AV_PTS_WRAP_IGNORE 0 ///< ignore the wrap +#define AV_PTS_WRAP_ADD_OFFSET 1 ///< add the format specific offset on wrap detection +#define AV_PTS_WRAP_SUB_OFFSET -1 ///< subtract the format specific offset on wrap detection + +/** + * Stream structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVStream) must not be used outside libav*. + */ +typedef struct AVStream { + int index; /**< stream index in AVFormatContext */ + /** + * Format-specific stream ID. + * decoding: set by libavformat + * encoding: set by the user, replaced by libavformat if left unset + */ + int id; +#if FF_API_LAVF_AVCTX + /** + * @deprecated use the codecpar struct instead + */ + attribute_deprecated + AVCodecContext *codec; +#endif + void *priv_data; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. + * + * decoding: set by libavformat + * encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the desired timebase. In + * avformat_write_header(), the muxer will overwrite this field + * with the timebase that will actually be used for the timestamps + * written into the file (which may or may not be related to the + * user-provided one, depending on the format). + */ + AVRational time_base; + + /** + * Decoding: pts of the first frame of the stream in presentation order, in stream time base. + * Only set this if you are absolutely 100% sure that the value you set + * it to really is the pts of the first frame. + * This may be undefined (AV_NOPTS_VALUE). + * @note The ASF header does NOT contain a correct start_time the ASF + * demuxer must NOT set this. + */ + int64_t start_time; + + /** + * Decoding: duration of the stream, in stream time base. + * If a source file does not specify a duration, but does specify + * a bitrate, this value will be estimated from bitrate and file size. + * + * Encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the estimated duration. + */ + int64_t duration; + + int64_t nb_frames; ///< number of frames in this stream if known or 0 + + int disposition; /**< AV_DISPOSITION_* bit field */ + + enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed. + + /** + * sample aspect ratio (0 if unknown) + * - encoding: Set by user. + * - decoding: Set by libavformat. + */ + AVRational sample_aspect_ratio; + + AVDictionary *metadata; + + /** + * Average framerate + * + * - demuxing: May be set by libavformat when creating the stream or in + * avformat_find_stream_info(). + * - muxing: May be set by the caller before avformat_write_header(). + */ + AVRational avg_frame_rate; + + /** + * For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet + * will contain the attached picture. + * + * decoding: set by libavformat, must not be modified by the caller. + * encoding: unused + */ + AVPacket attached_pic; + + /** + * An array of side data that applies to the whole stream (i.e. the + * container does not allow it to change between packets). + * + * There may be no overlap between the side data in this array and side data + * in the packets. I.e. a given side data is either exported by the muxer + * (demuxing) / set by the caller (muxing) in this array, then it never + * appears in the packets, or the side data is exported / sent through + * the packets (always in the first packet where the value becomes known or + * changes), then it does not appear in this array. + * + * - demuxing: Set by libavformat when the stream is created. + * - muxing: May be set by the caller before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + * + * @see av_format_inject_global_side_data() + */ + AVPacketSideData *side_data; + /** + * The number of elements in the AVStream.side_data array. + */ + int nb_side_data; + + /** + * Flags indicating events happening on the stream, a combination of + * AVSTREAM_EVENT_FLAG_*. + * + * - demuxing: may be set by the demuxer in avformat_open_input(), + * avformat_find_stream_info() and av_read_frame(). Flags must be cleared + * by the user once the event has been handled. + * - muxing: may be set by the user after avformat_write_header(). to + * indicate a user-triggered event. The muxer will clear the flags for + * events it has handled in av_[interleaved]_write_frame(). + */ + int event_flags; +/** + * - demuxing: the demuxer read new metadata from the file and updated + * AVStream.metadata accordingly + * - muxing: the user updated AVStream.metadata and wishes the muxer to write + * it into the file + */ +#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 +/** + * - demuxing: new packets for this stream were read from the file. This + * event is informational only and does not guarantee that new packets + * for this stream will necessarily be returned from av_read_frame(). + */ +#define AVSTREAM_EVENT_FLAG_NEW_PACKETS (1 << 1) + + /** + * Real base framerate of the stream. + * This is the lowest framerate with which all timestamps can be + * represented accurately (it is the least common multiple of all + * framerates in the stream). Note, this value is just a guess! + * For example, if the time base is 1/90000 and all frames have either + * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1. + */ + AVRational r_frame_rate; + +#if FF_API_LAVF_FFSERVER + /** + * String containing pairs of key and values describing recommended encoder configuration. + * Pairs are separated by ','. + * Keys are separated from values by '='. + * + * @deprecated unused + */ + attribute_deprecated + char *recommended_encoder_configuration; +#endif + + /** + * Codec parameters associated with this stream. Allocated and freed by + * libavformat in avformat_new_stream() and avformat_free_context() + * respectively. + * + * - demuxing: filled by libavformat on stream creation or in + * avformat_find_stream_info() + * - muxing: filled by the caller before avformat_write_header() + */ + AVCodecParameters *codecpar; + + /***************************************************************** + * All fields below this line are not part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * Internal note: be aware that physically removing these fields + * will break ABI. Replace removed fields with dummy fields, and + * add new fields to AVStreamInternal. + ***************************************************************** + */ + +#if LIBAVFORMAT_VERSION_MAJOR < 59 + // kept for ABI compatibility only, do not access in any way + void *unused; +#endif + + int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */ + + // Timestamp generation support: + /** + * Timestamp corresponding to the last dts sync point. + * + * Initialized when AVCodecParserContext.dts_sync_point >= 0 and + * a DTS is received from the underlying container. Otherwise set to + * AV_NOPTS_VALUE by default. + */ + int64_t first_dts; + int64_t cur_dts; + int64_t last_IP_pts; + int last_IP_duration; + + /** + * Number of packets to buffer for codec probing + */ + int probe_packets; + + /** + * Number of frames that have been demuxed during avformat_find_stream_info() + */ + int codec_info_nb_frames; + + /* av_read_frame() support */ + enum AVStreamParseType need_parsing; + struct AVCodecParserContext *parser; + +#if LIBAVFORMAT_VERSION_MAJOR < 59 + // kept for ABI compatibility only, do not access in any way + void *unused7; + AVProbeData unused6; + int64_t unused5[16+1]; +#endif + AVIndexEntry *index_entries; /**< Only used if the format does not + support seeking natively. */ + int nb_index_entries; + unsigned int index_entries_allocated_size; + + /** + * Stream Identifier + * This is the MPEG-TS stream identifier +1 + * 0 means unknown + */ + int stream_identifier; + +#if LIBAVFORMAT_VERSION_MAJOR < 59 + // kept for ABI compatibility only, do not access in any way + int unused8; + int unused9; + int unused10; +#endif + + /** + * An opaque field for libavformat internal usage. + * Must not be accessed in any way by callers. + */ + AVStreamInternal *internal; +} AVStream; + +#if FF_API_FORMAT_GET_SET +/** + * Accessors for some AVStream fields. These used to be provided for ABI + * compatibility, and do not need to be used anymore. + */ +attribute_deprecated +AVRational av_stream_get_r_frame_rate(const AVStream *s); +attribute_deprecated +void av_stream_set_r_frame_rate(AVStream *s, AVRational r); +#if FF_API_LAVF_FFSERVER +attribute_deprecated +char* av_stream_get_recommended_encoder_configuration(const AVStream *s); +attribute_deprecated +void av_stream_set_recommended_encoder_configuration(AVStream *s, char *configuration); +#endif +#endif + +struct AVCodecParserContext *av_stream_get_parser(const AVStream *s); + +/** + * Returns the pts of the last muxed packet + its duration + * + * the retuned value is undefined when used with a demuxer. + */ +int64_t av_stream_get_end_pts(const AVStream *st); + +#define AV_PROGRAM_RUNNING 1 + +/** + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVProgram) must not be used outside libav*. + */ +typedef struct AVProgram { + int id; + int flags; + enum AVDiscard discard; ///< selects which program to discard and which to feed to the caller + unsigned int *stream_index; + unsigned int nb_stream_indexes; + AVDictionary *metadata; + + int program_num; + int pmt_pid; + int pcr_pid; + int pmt_version; + + /***************************************************************** + * All fields below this line are not part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + int64_t start_time; + int64_t end_time; + + int64_t pts_wrap_reference; ///< reference dts for wrap detection + int pts_wrap_behavior; ///< behavior on wrap detection +} AVProgram; + +#define AVFMTCTX_NOHEADER 0x0001 /**< signal that no header is present + (streams are added dynamically) */ +#define AVFMTCTX_UNSEEKABLE 0x0002 /**< signal that the stream is definitely + not seekable, and attempts to call the + seek function will fail. For some + network protocols (e.g. HLS), this can + change dynamically at runtime. */ + +typedef struct AVChapter { +#if FF_API_CHAPTER_ID_INT + int id; ///< unique ID to identify the chapter +#else + int64_t id; ///< unique ID to identify the chapter +#endif + AVRational time_base; ///< time base in which the start/end timestamps are specified + int64_t start, end; ///< chapter start/end time in time_base units + AVDictionary *metadata; +} AVChapter; + + +/** + * Callback used by devices to communicate with application. + */ +typedef int (*av_format_control_message)(struct AVFormatContext *s, int type, + void *data, size_t data_size); + +typedef int (*AVOpenCallback)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, + const AVIOInterruptCB *int_cb, AVDictionary **options); + +/** + * The duration of a video can be estimated through various ways, and this enum can be used + * to know how the duration was estimated. + */ +enum AVDurationEstimationMethod { + AVFMT_DURATION_FROM_PTS, ///< Duration accurately estimated from PTSes + AVFMT_DURATION_FROM_STREAM, ///< Duration estimated from a stream with a known duration + AVFMT_DURATION_FROM_BITRATE ///< Duration estimated from bitrate (less accurate) +}; + +typedef struct AVFormatInternal AVFormatInternal; + +/** + * Format I/O context. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVFormatContext) must not be used outside libav*, use + * avformat_alloc_context() to create an AVFormatContext. + * + * Fields can be accessed through AVOptions (av_opt*), + * the name string used matches the associated command line parameter name and + * can be found in libavformat/options_table.h. + * The AVOption/command line parameter names differ in some cases from the C + * structure field names for historic reasons or brevity. + */ +typedef struct AVFormatContext { + /** + * A class for logging and @ref avoptions. Set by avformat_alloc_context(). + * Exports (de)muxer private options if they exist. + */ + const AVClass *av_class; + + /** + * The input container format. + * + * Demuxing only, set by avformat_open_input(). + */ + ff_const59 struct AVInputFormat *iformat; + + /** + * The output container format. + * + * Muxing only, must be set by the caller before avformat_write_header(). + */ + ff_const59 struct AVOutputFormat *oformat; + + /** + * Format private data. This is an AVOptions-enabled struct + * if and only if iformat/oformat.priv_class is not NULL. + * + * - muxing: set by avformat_write_header() + * - demuxing: set by avformat_open_input() + */ + void *priv_data; + + /** + * I/O context. + * + * - demuxing: either set by the user before avformat_open_input() (then + * the user must close it manually) or set by avformat_open_input(). + * - muxing: set by the user before avformat_write_header(). The caller must + * take care of closing / freeing the IO context. + * + * Do NOT set this field if AVFMT_NOFILE flag is set in + * iformat/oformat.flags. In such a case, the (de)muxer will handle + * I/O in some other way and this field will be NULL. + */ + AVIOContext *pb; + + /* stream info */ + /** + * Flags signalling stream properties. A combination of AVFMTCTX_*. + * Set by libavformat. + */ + int ctx_flags; + + /** + * Number of elements in AVFormatContext.streams. + * + * Set by avformat_new_stream(), must not be modified by any other code. + */ + unsigned int nb_streams; + /** + * A list of all streams in the file. New streams are created with + * avformat_new_stream(). + * + * - demuxing: streams are created by libavformat in avformat_open_input(). + * If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also + * appear in av_read_frame(). + * - muxing: streams are created by the user before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + */ + AVStream **streams; + +#if FF_API_FORMAT_FILENAME + /** + * input or output filename + * + * - demuxing: set by avformat_open_input() + * - muxing: may be set by the caller before avformat_write_header() + * + * @deprecated Use url instead. + */ + attribute_deprecated + char filename[1024]; +#endif + + /** + * input or output URL. Unlike the old filename field, this field has no + * length restriction. + * + * - demuxing: set by avformat_open_input(), initialized to an empty + * string if url parameter was NULL in avformat_open_input(). + * - muxing: may be set by the caller before calling avformat_write_header() + * (or avformat_init_output() if that is called first) to a string + * which is freeable by av_free(). Set to an empty string if it + * was NULL in avformat_init_output(). + * + * Freed by libavformat in avformat_free_context(). + */ + char *url; + + /** + * Position of the first frame of the component, in + * AV_TIME_BASE fractional seconds. NEVER set this value directly: + * It is deduced from the AVStream values. + * + * Demuxing only, set by libavformat. + */ + int64_t start_time; + + /** + * Duration of the stream, in AV_TIME_BASE fractional + * seconds. Only set this value if you know none of the individual stream + * durations and also do not set any of them. This is deduced from the + * AVStream values if not set. + * + * Demuxing only, set by libavformat. + */ + int64_t duration; + + /** + * Total stream bitrate in bit/s, 0 if not + * available. Never set it directly if the file_size and the + * duration are known as FFmpeg can compute it automatically. + */ + int64_t bit_rate; + + unsigned int packet_size; + int max_delay; + + /** + * Flags modifying the (de)muxer behaviour. A combination of AVFMT_FLAG_*. + * Set by the user before avformat_open_input() / avformat_write_header(). + */ + int flags; +#define AVFMT_FLAG_GENPTS 0x0001 ///< Generate missing pts even if it requires parsing future frames. +#define AVFMT_FLAG_IGNIDX 0x0002 ///< Ignore index. +#define AVFMT_FLAG_NONBLOCK 0x0004 ///< Do not block when reading packets from input. +#define AVFMT_FLAG_IGNDTS 0x0008 ///< Ignore DTS on frames that contain both DTS & PTS +#define AVFMT_FLAG_NOFILLIN 0x0010 ///< Do not infer any values from other values, just return what is stored in the container +#define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled +#define AVFMT_FLAG_NOBUFFER 0x0040 ///< Do not buffer frames when possible +#define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it. +#define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted +#define AVFMT_FLAG_FLUSH_PACKETS 0x0200 ///< Flush the AVIOContext every packet. +/** + * When muxing, try to avoid writing any random/volatile data to the output. + * This includes any random IDs, real-time timestamps/dates, muxer version, etc. + * + * This flag is mainly intended for testing. + */ +#define AVFMT_FLAG_BITEXACT 0x0400 +#if FF_API_LAVF_MP4A_LATM +#define AVFMT_FLAG_MP4A_LATM 0x8000 ///< Deprecated, does nothing. +#endif +#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down) +#if FF_API_LAVF_PRIV_OPT +#define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (deprecated, will do nothing once av_demuxer_open() is removed) +#endif +#if FF_API_LAVF_KEEPSIDE_FLAG +#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Deprecated, does nothing. +#endif +#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats +#define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops. +#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer + + /** + * Maximum size of the data read from input for determining + * the input container format. + * Demuxing only, set by the caller before avformat_open_input(). + */ + int64_t probesize; + + /** + * Maximum duration (in AV_TIME_BASE units) of the data read + * from input in avformat_find_stream_info(). + * Demuxing only, set by the caller before avformat_find_stream_info(). + * Can be set to 0 to let avformat choose using a heuristic. + */ + int64_t max_analyze_duration; + + const uint8_t *key; + int keylen; + + unsigned int nb_programs; + AVProgram **programs; + + /** + * Forced video codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID video_codec_id; + + /** + * Forced audio codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID audio_codec_id; + + /** + * Forced subtitle codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID subtitle_codec_id; + + /** + * Maximum amount of memory in bytes to use for the index of each stream. + * If the index exceeds this size, entries will be discarded as + * needed to maintain a smaller size. This can lead to slower or less + * accurate seeking (depends on demuxer). + * Demuxers for which a full in-memory index is mandatory will ignore + * this. + * - muxing: unused + * - demuxing: set by user + */ + unsigned int max_index_size; + + /** + * Maximum amount of memory in bytes to use for buffering frames + * obtained from realtime capture devices. + */ + unsigned int max_picture_buffer; + + /** + * Number of chapters in AVChapter array. + * When muxing, chapters are normally written in the file header, + * so nb_chapters should normally be initialized before write_header + * is called. Some muxers (e.g. mov and mkv) can also write chapters + * in the trailer. To write chapters in the trailer, nb_chapters + * must be zero when write_header is called and non-zero when + * write_trailer is called. + * - muxing: set by user + * - demuxing: set by libavformat + */ + unsigned int nb_chapters; + AVChapter **chapters; + + /** + * Metadata that applies to the whole file. + * + * - demuxing: set by libavformat in avformat_open_input() + * - muxing: may be set by the caller before avformat_write_header() + * + * Freed by libavformat in avformat_free_context(). + */ + AVDictionary *metadata; + + /** + * Start time of the stream in real world time, in microseconds + * since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the + * stream was captured at this real world time. + * - muxing: Set by the caller before avformat_write_header(). If set to + * either 0 or AV_NOPTS_VALUE, then the current wall-time will + * be used. + * - demuxing: Set by libavformat. AV_NOPTS_VALUE if unknown. Note that + * the value may become known after some number of frames + * have been received. + */ + int64_t start_time_realtime; + + /** + * The number of frames used for determining the framerate in + * avformat_find_stream_info(). + * Demuxing only, set by the caller before avformat_find_stream_info(). + */ + int fps_probe_size; + + /** + * Error recognition; higher values will detect more errors but may + * misdetect some more or less valid parts as errors. + * Demuxing only, set by the caller before avformat_open_input(). + */ + int error_recognition; + + /** + * Custom interrupt callbacks for the I/O layer. + * + * demuxing: set by the user before avformat_open_input(). + * muxing: set by the user before avformat_write_header() + * (mainly useful for AVFMT_NOFILE formats). The callback + * should also be passed to avio_open2() if it's used to + * open the file. + */ + AVIOInterruptCB interrupt_callback; + + /** + * Flags to enable debugging. + */ + int debug; +#define FF_FDEBUG_TS 0x0001 + + /** + * Maximum buffering duration for interleaving. + * + * To ensure all the streams are interleaved correctly, + * av_interleaved_write_frame() will wait until it has at least one packet + * for each stream before actually writing any packets to the output file. + * When some streams are "sparse" (i.e. there are large gaps between + * successive packets), this can result in excessive buffering. + * + * This field specifies the maximum difference between the timestamps of the + * first and the last packet in the muxing queue, above which libavformat + * will output a packet regardless of whether it has queued a packet for all + * the streams. + * + * Muxing only, set by the caller before avformat_write_header(). + */ + int64_t max_interleave_delta; + + /** + * Allow non-standard and experimental extension + * @see AVCodecContext.strict_std_compliance + */ + int strict_std_compliance; + + /** + * Flags indicating events happening on the file, a combination of + * AVFMT_EVENT_FLAG_*. + * + * - demuxing: may be set by the demuxer in avformat_open_input(), + * avformat_find_stream_info() and av_read_frame(). Flags must be cleared + * by the user once the event has been handled. + * - muxing: may be set by the user after avformat_write_header() to + * indicate a user-triggered event. The muxer will clear the flags for + * events it has handled in av_[interleaved]_write_frame(). + */ + int event_flags; +/** + * - demuxing: the demuxer read new metadata from the file and updated + * AVFormatContext.metadata accordingly + * - muxing: the user updated AVFormatContext.metadata and wishes the muxer to + * write it into the file + */ +#define AVFMT_EVENT_FLAG_METADATA_UPDATED 0x0001 + + /** + * Maximum number of packets to read while waiting for the first timestamp. + * Decoding only. + */ + int max_ts_probe; + + /** + * Avoid negative timestamps during muxing. + * Any value of the AVFMT_AVOID_NEG_TS_* constants. + * Note, this only works when using av_interleaved_write_frame. (interleave_packet_per_dts is in use) + * - muxing: Set by user + * - demuxing: unused + */ + int avoid_negative_ts; +#define AVFMT_AVOID_NEG_TS_AUTO -1 ///< Enabled when required by target format +#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative +#define AVFMT_AVOID_NEG_TS_MAKE_ZERO 2 ///< Shift timestamps so that they start at 0 + + /** + * Transport stream id. + * This will be moved into demuxer private options. Thus no API/ABI compatibility + */ + int ts_id; + + /** + * Audio preload in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int audio_preload; + + /** + * Max chunk time in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int max_chunk_duration; + + /** + * Max chunk size in bytes + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int max_chunk_size; + + /** + * forces the use of wallclock timestamps as pts/dts of packets + * This has undefined results in the presence of B frames. + * - encoding: unused + * - decoding: Set by user + */ + int use_wallclock_as_timestamps; + + /** + * avio flags, used to force AVIO_FLAG_DIRECT. + * - encoding: unused + * - decoding: Set by user + */ + int avio_flags; + + /** + * The duration field can be estimated through various ways, and this field can be used + * to know how the duration was estimated. + * - encoding: unused + * - decoding: Read by user + */ + enum AVDurationEstimationMethod duration_estimation_method; + + /** + * Skip initial bytes when opening stream + * - encoding: unused + * - decoding: Set by user + */ + int64_t skip_initial_bytes; + + /** + * Correct single timestamp overflows + * - encoding: unused + * - decoding: Set by user + */ + unsigned int correct_ts_overflow; + + /** + * Force seeking to any (also non key) frames. + * - encoding: unused + * - decoding: Set by user + */ + int seek2any; + + /** + * Flush the I/O context after each packet. + * - encoding: Set by user + * - decoding: unused + */ + int flush_packets; + + /** + * format probing score. + * The maximal score is AVPROBE_SCORE_MAX, its set when the demuxer probes + * the format. + * - encoding: unused + * - decoding: set by avformat, read by user + */ + int probe_score; + + /** + * number of bytes to read maximally to identify format. + * - encoding: unused + * - decoding: set by user + */ + int format_probesize; + + /** + * ',' separated list of allowed decoders. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *codec_whitelist; + + /** + * ',' separated list of allowed demuxers. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *format_whitelist; + + /** + * An opaque field for libavformat internal usage. + * Must not be accessed in any way by callers. + */ + AVFormatInternal *internal; + + /** + * IO repositioned flag. + * This is set by avformat when the underlaying IO context read pointer + * is repositioned, for example when doing byte based seeking. + * Demuxers can use the flag to detect such changes. + */ + int io_repositioned; + + /** + * Forced video codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + AVCodec *video_codec; + + /** + * Forced audio codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + AVCodec *audio_codec; + + /** + * Forced subtitle codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + AVCodec *subtitle_codec; + + /** + * Forced data codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + AVCodec *data_codec; + + /** + * Number of bytes to be written as padding in a metadata header. + * Demuxing: Unused. + * Muxing: Set by user via av_format_set_metadata_header_padding. + */ + int metadata_header_padding; + + /** + * User data. + * This is a place for some private data of the user. + */ + void *opaque; + + /** + * Callback used by devices to communicate with application. + */ + av_format_control_message control_message_cb; + + /** + * Output timestamp offset, in microseconds. + * Muxing: set by user + */ + int64_t output_ts_offset; + + /** + * dump format separator. + * can be ", " or "\n " or anything else + * - muxing: Set by user. + * - demuxing: Set by user. + */ + uint8_t *dump_separator; + + /** + * Forced Data codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID data_codec_id; + +#if FF_API_OLD_OPEN_CALLBACKS + /** + * Called to open further IO contexts when needed for demuxing. + * + * This can be set by the user application to perform security checks on + * the URLs before opening them. + * The function should behave like avio_open2(), AVFormatContext is provided + * as contextual information and to reach AVFormatContext.opaque. + * + * If NULL then some simple checks are used together with avio_open2(). + * + * Must not be accessed directly from outside avformat. + * @See av_format_set_open_cb() + * + * Demuxing: Set by user. + * + * @deprecated Use io_open and io_close. + */ + attribute_deprecated + int (*open_cb)(struct AVFormatContext *s, AVIOContext **p, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options); +#endif + + /** + * ',' separated list of allowed protocols. + * - encoding: unused + * - decoding: set by user + */ + char *protocol_whitelist; + + /** + * A callback for opening new IO streams. + * + * Whenever a muxer or a demuxer needs to open an IO stream (typically from + * avformat_open_input() for demuxers, but for certain formats can happen at + * other times as well), it will call this callback to obtain an IO context. + * + * @param s the format context + * @param pb on success, the newly opened IO context should be returned here + * @param url the url to open + * @param flags a combination of AVIO_FLAG_* + * @param options a dictionary of additional options, with the same + * semantics as in avio_open2() + * @return 0 on success, a negative AVERROR code on failure + * + * @note Certain muxers and demuxers do nesting, i.e. they open one or more + * additional internal format contexts. Thus the AVFormatContext pointer + * passed to this callback may be different from the one facing the caller. + * It will, however, have the same 'opaque' field. + */ + int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, + int flags, AVDictionary **options); + + /** + * A callback for closing the streams opened with AVFormatContext.io_open(). + */ + void (*io_close)(struct AVFormatContext *s, AVIOContext *pb); + + /** + * ',' separated list of disallowed protocols. + * - encoding: unused + * - decoding: set by user + */ + char *protocol_blacklist; + + /** + * The maximum number of streams. + * - encoding: unused + * - decoding: set by user + */ + int max_streams; + + /** + * Skip duration calcuation in estimate_timings_from_pts. + * - encoding: unused + * - decoding: set by user + */ + int skip_estimate_duration_from_pts; + + /** + * Maximum number of packets that can be probed + * - encoding: unused + * - decoding: set by user + */ + int max_probe_packets; +} AVFormatContext; + +#if FF_API_FORMAT_GET_SET +/** + * Accessors for some AVFormatContext fields. These used to be provided for ABI + * compatibility, and do not need to be used anymore. + */ +attribute_deprecated +int av_format_get_probe_score(const AVFormatContext *s); +attribute_deprecated +AVCodec * av_format_get_video_codec(const AVFormatContext *s); +attribute_deprecated +void av_format_set_video_codec(AVFormatContext *s, AVCodec *c); +attribute_deprecated +AVCodec * av_format_get_audio_codec(const AVFormatContext *s); +attribute_deprecated +void av_format_set_audio_codec(AVFormatContext *s, AVCodec *c); +attribute_deprecated +AVCodec * av_format_get_subtitle_codec(const AVFormatContext *s); +attribute_deprecated +void av_format_set_subtitle_codec(AVFormatContext *s, AVCodec *c); +attribute_deprecated +AVCodec * av_format_get_data_codec(const AVFormatContext *s); +attribute_deprecated +void av_format_set_data_codec(AVFormatContext *s, AVCodec *c); +attribute_deprecated +int av_format_get_metadata_header_padding(const AVFormatContext *s); +attribute_deprecated +void av_format_set_metadata_header_padding(AVFormatContext *s, int c); +attribute_deprecated +void * av_format_get_opaque(const AVFormatContext *s); +attribute_deprecated +void av_format_set_opaque(AVFormatContext *s, void *opaque); +attribute_deprecated +av_format_control_message av_format_get_control_message_cb(const AVFormatContext *s); +attribute_deprecated +void av_format_set_control_message_cb(AVFormatContext *s, av_format_control_message callback); +#if FF_API_OLD_OPEN_CALLBACKS +attribute_deprecated AVOpenCallback av_format_get_open_cb(const AVFormatContext *s); +attribute_deprecated void av_format_set_open_cb(AVFormatContext *s, AVOpenCallback callback); +#endif +#endif + +/** + * This function will cause global side data to be injected in the next packet + * of each stream as well as after any subsequent seek. + */ +void av_format_inject_global_side_data(AVFormatContext *s); + +/** + * Returns the method used to set ctx->duration. + * + * @return AVFMT_DURATION_FROM_PTS, AVFMT_DURATION_FROM_STREAM, or AVFMT_DURATION_FROM_BITRATE. + */ +enum AVDurationEstimationMethod av_fmt_ctx_get_duration_estimation_method(const AVFormatContext* ctx); + +/** + * @defgroup lavf_core Core functions + * @ingroup libavf + * + * Functions for querying libavformat capabilities, allocating core structures, + * etc. + * @{ + */ + +/** + * Return the LIBAVFORMAT_VERSION_INT constant. + */ +unsigned avformat_version(void); + +/** + * Return the libavformat build-time configuration. + */ +const char *avformat_configuration(void); + +/** + * Return the libavformat license. + */ +const char *avformat_license(void); + +#if FF_API_NEXT +/** + * Initialize libavformat and register all the muxers, demuxers and + * protocols. If you do not call this function, then you can select + * exactly which formats you want to support. + * + * @see av_register_input_format() + * @see av_register_output_format() + */ +attribute_deprecated +void av_register_all(void); + +attribute_deprecated +void av_register_input_format(AVInputFormat *format); +attribute_deprecated +void av_register_output_format(AVOutputFormat *format); +#endif + +/** + * Do global initialization of network libraries. This is optional, + * and not recommended anymore. + * + * This functions only exists to work around thread-safety issues + * with older GnuTLS or OpenSSL libraries. If libavformat is linked + * to newer versions of those libraries, or if you do not use them, + * calling this function is unnecessary. Otherwise, you need to call + * this function before any other threads using them are started. + * + * This function will be deprecated once support for older GnuTLS and + * OpenSSL libraries is removed, and this function has no purpose + * anymore. + */ +int avformat_network_init(void); + +/** + * Undo the initialization done by avformat_network_init. Call it only + * once for each time you called avformat_network_init. + */ +int avformat_network_deinit(void); + +#if FF_API_NEXT +/** + * If f is NULL, returns the first registered input format, + * if f is non-NULL, returns the next registered input format after f + * or NULL if f is the last one. + */ +attribute_deprecated +AVInputFormat *av_iformat_next(const AVInputFormat *f); + +/** + * If f is NULL, returns the first registered output format, + * if f is non-NULL, returns the next registered output format after f + * or NULL if f is the last one. + */ +attribute_deprecated +AVOutputFormat *av_oformat_next(const AVOutputFormat *f); +#endif + +/** + * Iterate over all registered muxers. + * + * @param opaque a pointer where libavformat will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered muxer or NULL when the iteration is + * finished + */ +const AVOutputFormat *av_muxer_iterate(void **opaque); + +/** + * Iterate over all registered demuxers. + * + * @param opaque a pointer where libavformat will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered demuxer or NULL when the iteration is + * finished + */ +const AVInputFormat *av_demuxer_iterate(void **opaque); + +/** + * Allocate an AVFormatContext. + * avformat_free_context() can be used to free the context and everything + * allocated by the framework within it. + */ +AVFormatContext *avformat_alloc_context(void); + +/** + * Free an AVFormatContext and all its streams. + * @param s context to free + */ +void avformat_free_context(AVFormatContext *s); + +/** + * Get the AVClass for AVFormatContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avformat_get_class(void); + +/** + * Add a new stream to a media file. + * + * When demuxing, it is called by the demuxer in read_header(). If the + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also + * be called in read_packet(). + * + * When muxing, should be called by the user before avformat_write_header(). + * + * User is required to call avcodec_close() and avformat_free_context() to + * clean up the allocation by avformat_new_stream(). + * + * @param s media file handle + * @param c If non-NULL, the AVCodecContext corresponding to the new stream + * will be initialized to use this codec. This is needed for e.g. codec-specific + * defaults to be set, so codec should be provided if it is known. + * + * @return newly created stream or NULL on error. + */ +AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c); + +/** + * Wrap an existing array as stream side data. + * + * @param st stream + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * st. + * @param size side information size + * @return zero on success, a negative AVERROR code on failure. On failure, + * the stream is unchanged and the data remains owned by the caller. + */ +int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + +/** + * Allocate new information from stream. + * + * @param stream stream + * @param type desired side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t *av_stream_new_side_data(AVStream *stream, +#if FF_API_BUFFER_SIZE_T + enum AVPacketSideDataType type, int size); +#else + enum AVPacketSideDataType type, size_t size); +#endif +/** + * Get side information from stream. + * + * @param stream stream + * @param type desired side information type + * @param size If supplied, *size will be set to the size of the side data + * or to zero if the desired side data is not present. + * @return pointer to data if present or NULL otherwise + */ +uint8_t *av_stream_get_side_data(const AVStream *stream, +#if FF_API_BUFFER_SIZE_T + enum AVPacketSideDataType type, int *size); +#else + enum AVPacketSideDataType type, size_t *size); +#endif + +AVProgram *av_new_program(AVFormatContext *s, int id); + +/** + * @} + */ + + +/** + * Allocate an AVFormatContext for an output format. + * avformat_free_context() can be used to free the context and + * everything allocated by the framework within it. + * + * @param *ctx is set to the created format context, or to NULL in + * case of failure + * @param oformat format to use for allocating the context, if NULL + * format_name and filename are used instead + * @param format_name the name of output format to use for allocating the + * context, if NULL filename is used instead + * @param filename the name of the filename to use for allocating the + * context, may be NULL + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int avformat_alloc_output_context2(AVFormatContext **ctx, ff_const59 AVOutputFormat *oformat, + const char *format_name, const char *filename); + +/** + * @addtogroup lavf_decoding + * @{ + */ + +/** + * Find AVInputFormat based on the short name of the input format. + */ +ff_const59 AVInputFormat *av_find_input_format(const char *short_name); + +/** + * Guess the file format. + * + * @param pd data to be probed + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + */ +ff_const59 AVInputFormat *av_probe_input_format(ff_const59 AVProbeData *pd, int is_opened); + +/** + * Guess the file format. + * + * @param pd data to be probed + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_max A probe score larger that this is required to accept a + * detection, the variable is set to the actual detection + * score afterwards. + * If the score is <= AVPROBE_SCORE_MAX / 4 it is recommended + * to retry with a larger probe buffer. + */ +ff_const59 AVInputFormat *av_probe_input_format2(ff_const59 AVProbeData *pd, int is_opened, int *score_max); + +/** + * Guess the file format. + * + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_ret The score of the best detection. + */ +ff_const59 AVInputFormat *av_probe_input_format3(ff_const59 AVProbeData *pd, int is_opened, int *score_ret); + +/** + * Probe a bytestream to determine the input format. Each time a probe returns + * with a score that is too low, the probe buffer size is increased and another + * attempt is made. When the maximum probe size is reached, the input format + * with the highest score is returned. + * + * @param pb the bytestream to probe + * @param fmt the input format is put here + * @param url the url of the stream + * @param logctx the log context + * @param offset the offset within the bytestream to probe from + * @param max_probe_size the maximum probe buffer size (zero for default) + * @return the score in case of success, a negative value corresponding to an + * the maximal score is AVPROBE_SCORE_MAX + * AVERROR code otherwise + */ +int av_probe_input_buffer2(AVIOContext *pb, ff_const59 AVInputFormat **fmt, + const char *url, void *logctx, + unsigned int offset, unsigned int max_probe_size); + +/** + * Like av_probe_input_buffer2() but returns 0 on success + */ +int av_probe_input_buffer(AVIOContext *pb, ff_const59 AVInputFormat **fmt, + const char *url, void *logctx, + unsigned int offset, unsigned int max_probe_size); + +/** + * Open an input stream and read the header. The codecs are not opened. + * The stream must be closed with avformat_close_input(). + * + * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context). + * May be a pointer to NULL, in which case an AVFormatContext is allocated by this + * function and written into ps. + * Note that a user-supplied AVFormatContext will be freed on failure. + * @param url URL of the stream to open. + * @param fmt If non-NULL, this parameter forces a specific input format. + * Otherwise the format is autodetected. + * @param options A dictionary filled with AVFormatContext and demuxer-private options. + * On return this parameter will be destroyed and replaced with a dict containing + * options that were not found. May be NULL. + * + * @return 0 on success, a negative AVERROR on failure. + * + * @note If you want to use custom IO, preallocate the format context and set its pb field. + */ +int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options); + +#if FF_API_DEMUXER_OPEN +/** + * @deprecated Use an AVDictionary to pass options to a demuxer. + */ +attribute_deprecated +int av_demuxer_open(AVFormatContext *ic); +#endif + +/** + * Read packets of a media file to get stream information. This + * is useful for file formats with no headers such as MPEG. This + * function also computes the real framerate in case of MPEG-2 repeat + * frame mode. + * The logical file position is not changed by this function; + * examined packets may be buffered for later processing. + * + * @param ic media file handle + * @param options If non-NULL, an ic.nb_streams long array of pointers to + * dictionaries, where i-th member contains options for + * codec corresponding to i-th stream. + * On return each dictionary will be filled with options that were not found. + * @return >=0 if OK, AVERROR_xxx on error + * + * @note this function isn't guaranteed to open all the codecs, so + * options being non-empty at return is a perfectly normal behavior. + * + * @todo Let the user decide somehow what information is needed so that + * we do not waste time getting stuff the user does not need. + */ +int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); + +/** + * Find the programs which belong to a given stream. + * + * @param ic media file handle + * @param last the last found program, the search will start after this + * program, or from the beginning if it is NULL + * @param s stream index + * @return the next program which belongs to s, NULL if no program is found or + * the last program is not among the programs of ic. + */ +AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s); + +void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx); + +/** + * Find the "best" stream in the file. + * The best stream is determined according to various heuristics as the most + * likely to be what the user expects. + * If the decoder parameter is non-NULL, av_find_best_stream will find the + * default decoder for the stream's codec; streams for which no decoder can + * be found are ignored. + * + * @param ic media file handle + * @param type stream type: video, audio, subtitles, etc. + * @param wanted_stream_nb user-requested stream number, + * or -1 for automatic selection + * @param related_stream try to find a stream related (eg. in the same + * program) to this one, or -1 if none + * @param decoder_ret if non-NULL, returns the decoder for the + * selected stream + * @param flags flags; none are currently defined + * @return the non-negative stream number in case of success, + * AVERROR_STREAM_NOT_FOUND if no stream with the requested type + * could be found, + * AVERROR_DECODER_NOT_FOUND if streams were found but no decoder + * @note If av_find_best_stream returns successfully and decoder_ret is not + * NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec. + */ +int av_find_best_stream(AVFormatContext *ic, + enum AVMediaType type, + int wanted_stream_nb, + int related_stream, + AVCodec **decoder_ret, + int flags); + +/** + * Return the next frame of a stream. + * This function returns what is stored in the file, and does not validate + * that what is there are valid frames for the decoder. It will split what is + * stored in the file into frames and return one for each call. It will not + * omit invalid data between valid frames so as to give the decoder the maximum + * information possible for decoding. + * + * On success, the returned packet is reference-counted (pkt->buf is set) and + * valid indefinitely. The packet must be freed with av_packet_unref() when + * it is no longer needed. For video, the packet contains exactly one frame. + * For audio, it contains an integer number of frames if each frame has + * a known fixed size (e.g. PCM or ADPCM data). If the audio frames have + * a variable size (e.g. MPEG audio), then it contains one frame. + * + * pkt->pts, pkt->dts and pkt->duration are always set to correct + * values in AVStream.time_base units (and guessed if the format cannot + * provide them). pkt->pts can be AV_NOPTS_VALUE if the video format + * has B-frames, so it is better to rely on pkt->dts if you do not + * decompress the payload. + * + * @return 0 if OK, < 0 on error or end of file. On error, pkt will be blank + * (as if it came from av_packet_alloc()). + * + * @note pkt will be initialized, so it may be uninitialized, but it must not + * contain data that needs to be freed. + */ +int av_read_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Seek to the keyframe at timestamp. + * 'timestamp' in 'stream_index'. + * + * @param s media file handle + * @param stream_index If stream_index is (-1), a default + * stream is selected, and timestamp is automatically converted + * from AV_TIME_BASE units to the stream specific time_base. + * @param timestamp Timestamp in AVStream.time_base units + * or, if no stream is specified, in AV_TIME_BASE units. + * @param flags flags which select direction and seeking mode + * @return >= 0 on success + */ +int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, + int flags); + +/** + * Seek to timestamp ts. + * Seeking will be done so that the point from which all active streams + * can be presented successfully will be closest to ts and within min/max_ts. + * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL. + * + * If flags contain AVSEEK_FLAG_BYTE, then all timestamps are in bytes and + * are the file position (this may not be supported by all demuxers). + * If flags contain AVSEEK_FLAG_FRAME, then all timestamps are in frames + * in the stream with stream_index (this may not be supported by all demuxers). + * Otherwise all timestamps are in units of the stream selected by stream_index + * or if stream_index is -1, in AV_TIME_BASE units. + * If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as + * keyframes (this may not be supported by all demuxers). + * If flags contain AVSEEK_FLAG_BACKWARD, it is ignored. + * + * @param s media file handle + * @param stream_index index of the stream which is used as time base reference + * @param min_ts smallest acceptable timestamp + * @param ts target timestamp + * @param max_ts largest acceptable timestamp + * @param flags flags + * @return >=0 on success, error code otherwise + * + * @note This is part of the new seek API which is still under construction. + */ +int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); + +/** + * Discard all internally buffered data. This can be useful when dealing with + * discontinuities in the byte stream. Generally works only with formats that + * can resync. This includes headerless formats like MPEG-TS/TS but should also + * work with NUT, Ogg and in a limited way AVI for example. + * + * The set of streams, the detected duration, stream parameters and codecs do + * not change when calling this function. If you want a complete reset, it's + * better to open a new AVFormatContext. + * + * This does not flush the AVIOContext (s->pb). If necessary, call + * avio_flush(s->pb) before calling this function. + * + * @param s media file handle + * @return >=0 on success, error code otherwise + */ +int avformat_flush(AVFormatContext *s); + +/** + * Start playing a network-based stream (e.g. RTSP stream) at the + * current position. + */ +int av_read_play(AVFormatContext *s); + +/** + * Pause a network-based stream (e.g. RTSP stream). + * + * Use av_read_play() to resume it. + */ +int av_read_pause(AVFormatContext *s); + +/** + * Close an opened input AVFormatContext. Free it and all its contents + * and set *s to NULL. + */ +void avformat_close_input(AVFormatContext **s); +/** + * @} + */ + +#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward +#define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes +#define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes +#define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number + +/** + * @addtogroup lavf_encoding + * @{ + */ + +#define AVSTREAM_INIT_IN_WRITE_HEADER 0 ///< stream parameters initialized in avformat_write_header +#define AVSTREAM_INIT_IN_INIT_OUTPUT 1 ///< stream parameters initialized in avformat_init_output + +/** + * Allocate the stream private data and write the stream header to + * an output media file. + * + * @param s Media file handle, must be allocated with avformat_alloc_context(). + * Its oformat field must be set to the desired output format; + * Its pb field must be set to an already opened AVIOContext. + * @param options An AVDictionary filled with AVFormatContext and muxer-private options. + * On return this parameter will be destroyed and replaced with a dict containing + * options that were not found. May be NULL. + * + * @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec had not already been fully initialized in avformat_init, + * AVSTREAM_INIT_IN_INIT_OUTPUT on success if the codec had already been fully initialized in avformat_init, + * negative AVERROR on failure. + * + * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_init_output. + */ +av_warn_unused_result +int avformat_write_header(AVFormatContext *s, AVDictionary **options); + +/** + * Allocate the stream private data and initialize the codec, but do not write the header. + * May optionally be used before avformat_write_header to initialize stream parameters + * before actually writing the header. + * If using this function, do not pass the same options to avformat_write_header. + * + * @param s Media file handle, must be allocated with avformat_alloc_context(). + * Its oformat field must be set to the desired output format; + * Its pb field must be set to an already opened AVIOContext. + * @param options An AVDictionary filled with AVFormatContext and muxer-private options. + * On return this parameter will be destroyed and replaced with a dict containing + * options that were not found. May be NULL. + * + * @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec requires avformat_write_header to fully initialize, + * AVSTREAM_INIT_IN_INIT_OUTPUT on success if the codec has been fully initialized, + * negative AVERROR on failure. + * + * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_write_header. + */ +av_warn_unused_result +int avformat_init_output(AVFormatContext *s, AVDictionary **options); + +/** + * Write a packet to an output media file. + * + * This function passes the packet directly to the muxer, without any buffering + * or reordering. The caller is responsible for correctly interleaving the + * packets if the format requires it. Callers that want libavformat to handle + * the interleaving should call av_interleaved_write_frame() instead of this + * function. + * + * @param s media file handle + * @param pkt The packet containing the data to be written. Note that unlike + * av_interleaved_write_frame(), this function does not take + * ownership of the packet passed to it (though some muxers may make + * an internal reference to the input packet). + *
+ * This parameter can be NULL (at any time, not just at the end), in + * order to immediately flush data buffered within the muxer, for + * muxers that buffer up data internally before writing it to the + * output. + *
+ * Packet's @ref AVPacket.stream_index "stream_index" field must be + * set to the index of the corresponding stream in @ref + * AVFormatContext.streams "s->streams". + *
+ * The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts") + * must be set to correct values in the stream's timebase (unless the + * output format is flagged with the AVFMT_NOTIMESTAMPS flag, then + * they can be set to AV_NOPTS_VALUE). + * The dts for subsequent packets passed to this function must be strictly + * increasing when compared in their respective timebases (unless the + * output format is flagged with the AVFMT_TS_NONSTRICT, then they + * merely have to be nondecreasing). @ref AVPacket.duration + * "duration") should also be set if known. + * @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush + * + * @see av_interleaved_write_frame() + */ +int av_write_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Write a packet to an output media file ensuring correct interleaving. + * + * This function will buffer the packets internally as needed to make sure the + * packets in the output file are properly interleaved in the order of + * increasing dts. Callers doing their own interleaving should call + * av_write_frame() instead of this function. + * + * Using this function instead of av_write_frame() can give muxers advance + * knowledge of future packets, improving e.g. the behaviour of the mp4 + * muxer for VFR content in fragmenting mode. + * + * @param s media file handle + * @param pkt The packet containing the data to be written. + *
+ * If the packet is reference-counted, this function will take + * ownership of this reference and unreference it later when it sees + * fit. + * The caller must not access the data through this reference after + * this function returns. If the packet is not reference-counted, + * libavformat will make a copy. + *
+ * This parameter can be NULL (at any time, not just at the end), to + * flush the interleaving queues. + *
+ * Packet's @ref AVPacket.stream_index "stream_index" field must be + * set to the index of the corresponding stream in @ref + * AVFormatContext.streams "s->streams". + *
+ * The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts") + * must be set to correct values in the stream's timebase (unless the + * output format is flagged with the AVFMT_NOTIMESTAMPS flag, then + * they can be set to AV_NOPTS_VALUE). + * The dts for subsequent packets in one stream must be strictly + * increasing (unless the output format is flagged with the + * AVFMT_TS_NONSTRICT, then they merely have to be nondecreasing). + * @ref AVPacket.duration "duration") should also be set if known. + * + * @return 0 on success, a negative AVERROR on error. Libavformat will always + * take care of freeing the packet, even if this function fails. + * + * @see av_write_frame(), AVFormatContext.max_interleave_delta + */ +int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Write an uncoded frame to an output media file. + * + * The frame must be correctly interleaved according to the container + * specification; if not, av_interleaved_write_uncoded_frame() must be used. + * + * See av_interleaved_write_uncoded_frame() for details. + */ +int av_write_uncoded_frame(AVFormatContext *s, int stream_index, + AVFrame *frame); + +/** + * Write an uncoded frame to an output media file. + * + * If the muxer supports it, this function makes it possible to write an AVFrame + * structure directly, without encoding it into a packet. + * It is mostly useful for devices and similar special muxers that use raw + * video or PCM data and will not serialize it into a byte stream. + * + * To test whether it is possible to use it with a given muxer and stream, + * use av_write_uncoded_frame_query(). + * + * The caller gives up ownership of the frame and must not access it + * afterwards. + * + * @return >=0 for success, a negative code on error + */ +int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index, + AVFrame *frame); + +/** + * Test whether a muxer supports uncoded frame. + * + * @return >=0 if an uncoded frame can be written to that muxer and stream, + * <0 if not + */ +int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index); + +/** + * Write the stream trailer to an output media file and free the + * file private data. + * + * May only be called after a successful call to avformat_write_header. + * + * @param s media file handle + * @return 0 if OK, AVERROR_xxx on error + */ +int av_write_trailer(AVFormatContext *s); + +/** + * Return the output format in the list of registered output formats + * which best matches the provided parameters, or return NULL if + * there is no match. + * + * @param short_name if non-NULL checks if short_name matches with the + * names of the registered formats + * @param filename if non-NULL checks if filename terminates with the + * extensions of the registered formats + * @param mime_type if non-NULL checks if mime_type matches with the + * MIME type of the registered formats + */ +ff_const59 AVOutputFormat *av_guess_format(const char *short_name, + const char *filename, + const char *mime_type); + +/** + * Guess the codec ID based upon muxer and filename. + */ +enum AVCodecID av_guess_codec(ff_const59 AVOutputFormat *fmt, const char *short_name, + const char *filename, const char *mime_type, + enum AVMediaType type); + +/** + * Get timing information for the data currently output. + * The exact meaning of "currently output" depends on the format. + * It is mostly relevant for devices that have an internal buffer and/or + * work in real time. + * @param s media file handle + * @param stream stream in the media file + * @param[out] dts DTS of the last packet output for the stream, in stream + * time_base units + * @param[out] wall absolute time when that packet whas output, + * in microsecond + * @return 0 if OK, AVERROR(ENOSYS) if the format does not support it + * Note: some formats or devices may not allow to measure dts and wall + * atomically. + */ +int av_get_output_timestamp(struct AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall); + + +/** + * @} + */ + + +/** + * @defgroup lavf_misc Utility functions + * @ingroup libavf + * @{ + * + * Miscellaneous utility functions related to both muxing and demuxing + * (or neither). + */ + +/** + * Send a nice hexadecimal dump of a buffer to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump_log, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump(FILE *f, const uint8_t *buf, int size); + +/** + * Send a nice hexadecimal dump of a buffer to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size); + +/** + * Send a nice dump of a packet to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st); + + +/** + * Send a nice dump of a packet to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload, + const AVStream *st); + +/** + * Get the AVCodecID for the given codec tag tag. + * If no codec id is found returns AV_CODEC_ID_NONE. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param tag codec tag to match to a codec ID + */ +enum AVCodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned int tag); + +/** + * Get the codec tag for the given codec id id. + * If no codec tag is found returns 0. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param id codec ID to match to a codec tag + */ +unsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum AVCodecID id); + +/** + * Get the codec tag for the given codec id. + * + * @param tags list of supported codec_id - codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param id codec id that should be searched for in the list + * @param tag A pointer to the found tag + * @return 0 if id was not found in tags, > 0 if it was found + */ +int av_codec_get_tag2(const struct AVCodecTag * const *tags, enum AVCodecID id, + unsigned int *tag); + +int av_find_default_stream_index(AVFormatContext *s); + +/** + * Get the index for a specific timestamp. + * + * @param st stream that the timestamp belongs to + * @param timestamp timestamp to retrieve the index for + * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond + * to the timestamp which is <= the requested one, if backward + * is 0, then it will be >= + * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise + * @return < 0 if no such timestamp could be found + */ +int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags); + +/** + * Add an index entry into a sorted list. Update the entry if the list + * already contains it. + * + * @param timestamp timestamp in the time base of the given stream + */ +int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, + int size, int distance, int flags); + + +/** + * Split a URL string into components. + * + * The pointers to buffers for storing individual components may be null, + * in order to ignore that component. Buffers for components not found are + * set to empty strings. If the port is not found, it is set to a negative + * value. + * + * @param proto the buffer for the protocol + * @param proto_size the size of the proto buffer + * @param authorization the buffer for the authorization + * @param authorization_size the size of the authorization buffer + * @param hostname the buffer for the host name + * @param hostname_size the size of the hostname buffer + * @param port_ptr a pointer to store the port number in + * @param path the buffer for the path + * @param path_size the size of the path buffer + * @param url the URL to split + */ +void av_url_split(char *proto, int proto_size, + char *authorization, int authorization_size, + char *hostname, int hostname_size, + int *port_ptr, + char *path, int path_size, + const char *url); + + +/** + * Print detailed information about the input or output format, such as + * duration, bitrate, streams, container, programs, metadata, side data, + * codec and time base. + * + * @param ic the context to analyze + * @param index index of the stream to dump information about + * @param url the URL to print, such as source or destination file + * @param is_output Select whether the specified context is an input(0) or output(1) + */ +void av_dump_format(AVFormatContext *ic, + int index, + const char *url, + int is_output); + + +#define AV_FRAME_FILENAME_FLAGS_MULTIPLE 1 ///< Allow multiple %d + +/** + * Return in 'buf' the path with '%d' replaced by a number. + * + * Also handles the '%0nd' format where 'n' is the total number + * of digits and '%%'. + * + * @param buf destination buffer + * @param buf_size destination buffer size + * @param path numbered sequence string + * @param number frame number + * @param flags AV_FRAME_FILENAME_FLAGS_* + * @return 0 if OK, -1 on format error + */ +int av_get_frame_filename2(char *buf, int buf_size, + const char *path, int number, int flags); + +int av_get_frame_filename(char *buf, int buf_size, + const char *path, int number); + +/** + * Check whether filename actually is a numbered sequence generator. + * + * @param filename possible numbered sequence string + * @return 1 if a valid numbered sequence string, 0 otherwise + */ +int av_filename_number_test(const char *filename); + +/** + * Generate an SDP for an RTP session. + * + * Note, this overwrites the id values of AVStreams in the muxer contexts + * for getting unique dynamic payload types. + * + * @param ac array of AVFormatContexts describing the RTP streams. If the + * array is composed by only one context, such context can contain + * multiple AVStreams (one AVStream per RTP stream). Otherwise, + * all the contexts in the array (an AVCodecContext per RTP stream) + * must contain only one AVStream. + * @param n_files number of AVCodecContexts contained in ac + * @param buf buffer where the SDP will be stored (must be allocated by + * the caller) + * @param size the size of the buffer + * @return 0 if OK, AVERROR_xxx on error + */ +int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size); + +/** + * Return a positive value if the given filename has one of the given + * extensions, 0 otherwise. + * + * @param filename file name to check against the given extensions + * @param extensions a comma-separated list of filename extensions + */ +int av_match_ext(const char *filename, const char *extensions); + +/** + * Test if the given container can store a codec. + * + * @param ofmt container to check for compatibility + * @param codec_id codec to potentially store in container + * @param std_compliance standards compliance level, one of FF_COMPLIANCE_* + * + * @return 1 if codec with ID codec_id can be stored in ofmt, 0 if it cannot. + * A negative number if this information is not available. + */ +int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id, + int std_compliance); + +/** + * @defgroup riff_fourcc RIFF FourCCs + * @{ + * Get the tables mapping RIFF FourCCs to libavcodec AVCodecIDs. The tables are + * meant to be passed to av_codec_get_id()/av_codec_get_tag() as in the + * following code: + * @code + * uint32_t tag = MKTAG('H', '2', '6', '4'); + * const struct AVCodecTag *table[] = { avformat_get_riff_video_tags(), 0 }; + * enum AVCodecID id = av_codec_get_id(table, tag); + * @endcode + */ +/** + * @return the table mapping RIFF FourCCs for video to libavcodec AVCodecID. + */ +const struct AVCodecTag *avformat_get_riff_video_tags(void); +/** + * @return the table mapping RIFF FourCCs for audio to AVCodecID. + */ +const struct AVCodecTag *avformat_get_riff_audio_tags(void); +/** + * @return the table mapping MOV FourCCs for video to libavcodec AVCodecID. + */ +const struct AVCodecTag *avformat_get_mov_video_tags(void); +/** + * @return the table mapping MOV FourCCs for audio to AVCodecID. + */ +const struct AVCodecTag *avformat_get_mov_audio_tags(void); + +/** + * @} + */ + +/** + * Guess the sample aspect ratio of a frame, based on both the stream and the + * frame aspect ratio. + * + * Since the frame aspect ratio is set by the codec but the stream aspect ratio + * is set by the demuxer, these two may not be equal. This function tries to + * return the value that you should use if you would like to display the frame. + * + * Basic logic is to use the stream aspect ratio if it is set to something sane + * otherwise use the frame aspect ratio. This way a container setting, which is + * usually easy to modify can override the coded value in the frames. + * + * @param format the format context which the stream is part of + * @param stream the stream which the frame is part of + * @param frame the frame with the aspect ratio to be determined + * @return the guessed (valid) sample_aspect_ratio, 0/1 if no idea + */ +AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame); + +/** + * Guess the frame rate, based on both the container and codec information. + * + * @param ctx the format context which the stream is part of + * @param stream the stream which the frame is part of + * @param frame the frame for which the frame rate should be determined, may be NULL + * @return the guessed (valid) frame rate, 0/1 if no idea + */ +AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, AVFrame *frame); + +/** + * Check if the stream st contained in s is matched by the stream specifier + * spec. + * + * See the "stream specifiers" chapter in the documentation for the syntax + * of spec. + * + * @return >0 if st is matched by spec; + * 0 if st is not matched by spec; + * AVERROR code if spec is invalid + * + * @note A stream specifier can match several streams in the format. + */ +int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, + const char *spec); + +int avformat_queue_attached_pictures(AVFormatContext *s); + +#if FF_API_OLD_BSF +/** + * Apply a list of bitstream filters to a packet. + * + * @param codec AVCodecContext, usually from an AVStream + * @param pkt the packet to apply filters to. If, on success, the returned + * packet has size == 0 and side_data_elems == 0, it indicates that + * the packet should be dropped + * @param bsfc a NULL-terminated list of filters to apply + * @return >=0 on success; + * AVERROR code on failure + */ +attribute_deprecated +int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt, + AVBitStreamFilterContext *bsfc); +#endif + +enum AVTimebaseSource { + AVFMT_TBCF_AUTO = -1, + AVFMT_TBCF_DECODER, + AVFMT_TBCF_DEMUXER, +#if FF_API_R_FRAME_RATE + AVFMT_TBCF_R_FRAMERATE, +#endif +}; + +/** + * Transfer internal timing information from one stream to another. + * + * This function is useful when doing stream copy. + * + * @param ofmt target output format for ost + * @param ost output stream which needs timings copy and adjustments + * @param ist reference input stream to copy timings from + * @param copy_tb define from where the stream codec timebase needs to be imported + */ +int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, + AVStream *ost, const AVStream *ist, + enum AVTimebaseSource copy_tb); + +/** + * Get the internal codec timebase from a stream. + * + * @param st input stream to extract the timebase from + */ +AVRational av_stream_get_codec_timebase(const AVStream *st); + +/** + * @} + */ + +#endif /* AVFORMAT_AVFORMAT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavformat/avio.h b/src/framework/media/thirdparty/ffmpeg/v4/libavformat/avio.h new file mode 100644 index 0000000000000..d022820a6edf3 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavformat/avio.h @@ -0,0 +1,888 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef AVFORMAT_AVIO_H +#define AVFORMAT_AVIO_H + +/** + * @file + * @ingroup lavf_io + * Buffered I/O operations + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" + +#include "libavformat/version.h" + +/** + * Seeking works like for a local file. + */ +#define AVIO_SEEKABLE_NORMAL (1 << 0) + +/** + * Seeking by timestamp with avio_seek_time() is possible. + */ +#define AVIO_SEEKABLE_TIME (1 << 1) + +/** + * Callback for checking whether to abort blocking functions. + * AVERROR_EXIT is returned in this case by the interrupted + * function. During blocking operations, callback is called with + * opaque as parameter. If the callback returns 1, the + * blocking operation will be aborted. + * + * No members can be added to this struct without a major bump, if + * new elements have been added after this struct in AVFormatContext + * or AVIOContext. + */ +typedef struct AVIOInterruptCB { + int (*callback)(void*); + void *opaque; +} AVIOInterruptCB; + +/** + * Directory entry types. + */ +enum AVIODirEntryType { + AVIO_ENTRY_UNKNOWN, + AVIO_ENTRY_BLOCK_DEVICE, + AVIO_ENTRY_CHARACTER_DEVICE, + AVIO_ENTRY_DIRECTORY, + AVIO_ENTRY_NAMED_PIPE, + AVIO_ENTRY_SYMBOLIC_LINK, + AVIO_ENTRY_SOCKET, + AVIO_ENTRY_FILE, + AVIO_ENTRY_SERVER, + AVIO_ENTRY_SHARE, + AVIO_ENTRY_WORKGROUP, +}; + +/** + * Describes single entry of the directory. + * + * Only name and type fields are guaranteed be set. + * Rest of fields are protocol or/and platform dependent and might be unknown. + */ +typedef struct AVIODirEntry { + char *name; /**< Filename */ + int type; /**< Type of the entry */ + int utf8; /**< Set to 1 when name is encoded with UTF-8, 0 otherwise. + Name can be encoded with UTF-8 even though 0 is set. */ + int64_t size; /**< File size in bytes, -1 if unknown. */ + int64_t modification_timestamp; /**< Time of last modification in microseconds since unix + epoch, -1 if unknown. */ + int64_t access_timestamp; /**< Time of last access in microseconds since unix epoch, + -1 if unknown. */ + int64_t status_change_timestamp; /**< Time of last status change in microseconds since unix + epoch, -1 if unknown. */ + int64_t user_id; /**< User ID of owner, -1 if unknown. */ + int64_t group_id; /**< Group ID of owner, -1 if unknown. */ + int64_t filemode; /**< Unix file mode, -1 if unknown. */ +} AVIODirEntry; + +typedef struct AVIODirContext { + struct URLContext *url_context; +} AVIODirContext; + +/** + * Different data types that can be returned via the AVIO + * write_data_type callback. + */ +enum AVIODataMarkerType { + /** + * Header data; this needs to be present for the stream to be decodeable. + */ + AVIO_DATA_MARKER_HEADER, + /** + * A point in the output bytestream where a decoder can start decoding + * (i.e. a keyframe). A demuxer/decoder given the data flagged with + * AVIO_DATA_MARKER_HEADER, followed by any AVIO_DATA_MARKER_SYNC_POINT, + * should give decodeable results. + */ + AVIO_DATA_MARKER_SYNC_POINT, + /** + * A point in the output bytestream where a demuxer can start parsing + * (for non self synchronizing bytestream formats). That is, any + * non-keyframe packet start point. + */ + AVIO_DATA_MARKER_BOUNDARY_POINT, + /** + * This is any, unlabelled data. It can either be a muxer not marking + * any positions at all, it can be an actual boundary/sync point + * that the muxer chooses not to mark, or a later part of a packet/fragment + * that is cut into multiple write callbacks due to limited IO buffer size. + */ + AVIO_DATA_MARKER_UNKNOWN, + /** + * Trailer data, which doesn't contain actual content, but only for + * finalizing the output file. + */ + AVIO_DATA_MARKER_TRAILER, + /** + * A point in the output bytestream where the underlying AVIOContext might + * flush the buffer depending on latency or buffering requirements. Typically + * means the end of a packet. + */ + AVIO_DATA_MARKER_FLUSH_POINT, +}; + +/** + * Bytestream IO Context. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVIOContext) must not be used outside libav*. + * + * @note None of the function pointers in AVIOContext should be called + * directly, they should only be set by the client application + * when implementing custom I/O. Normally these are set to the + * function pointers specified in avio_alloc_context() + */ +typedef struct AVIOContext { + /** + * A class for private options. + * + * If this AVIOContext is created by avio_open2(), av_class is set and + * passes the options down to protocols. + * + * If this AVIOContext is manually allocated, then av_class may be set by + * the caller. + * + * warning -- this field can be NULL, be sure to not pass this AVIOContext + * to any av_opt_* functions in that case. + */ + const AVClass *av_class; + + /* + * The following shows the relationship between buffer, buf_ptr, + * buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing + * (since AVIOContext is used for both): + * + ********************************************************************************** + * READING + ********************************************************************************** + * + * | buffer_size | + * |---------------------------------------| + * | | + * + * buffer buf_ptr buf_end + * +---------------+-----------------------+ + * |/ / / / / / / /|/ / / / / / /| | + * read buffer: |/ / consumed / | to be read /| | + * |/ / / / / / / /|/ / / / / / /| | + * +---------------+-----------------------+ + * + * pos + * +-------------------------------------------+-----------------+ + * input file: | | | + * +-------------------------------------------+-----------------+ + * + * + ********************************************************************************** + * WRITING + ********************************************************************************** + * + * | buffer_size | + * |--------------------------------------| + * | | + * + * buf_ptr_max + * buffer (buf_ptr) buf_end + * +-----------------------+--------------+ + * |/ / / / / / / / / / / /| | + * write buffer: | / / to be flushed / / | | + * |/ / / / / / / / / / / /| | + * +-----------------------+--------------+ + * buf_ptr can be in this + * due to a backward seek + * + * pos + * +-------------+----------------------------------------------+ + * output file: | | | + * +-------------+----------------------------------------------+ + * + */ + unsigned char *buffer; /**< Start of the buffer. */ + int buffer_size; /**< Maximum buffer size */ + unsigned char *buf_ptr; /**< Current position in the buffer */ + unsigned char *buf_end; /**< End of the data, may be less than + buffer+buffer_size if the read function returned + less data than requested, e.g. for streams where + no more data has been received yet. */ + void *opaque; /**< A private pointer, passed to the read/write/seek/... + functions. */ + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size); + int (*write_packet)(void *opaque, uint8_t *buf, int buf_size); + int64_t (*seek)(void *opaque, int64_t offset, int whence); + int64_t pos; /**< position in the file of the current buffer */ + int eof_reached; /**< true if was unable to read due to error or eof */ + int write_flag; /**< true if open for writing */ + int max_packet_size; + unsigned long checksum; + unsigned char *checksum_ptr; + unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size); + int error; /**< contains the error code or 0 if no error happened */ + /** + * Pause or resume playback for network streaming protocols - e.g. MMS. + */ + int (*read_pause)(void *opaque, int pause); + /** + * Seek to a given timestamp in stream with the specified stream_index. + * Needed for some network streaming protocols which don't support seeking + * to byte position. + */ + int64_t (*read_seek)(void *opaque, int stream_index, + int64_t timestamp, int flags); + /** + * A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable. + */ + int seekable; + + /** + * max filesize, used to limit allocations + * This field is internal to libavformat and access from outside is not allowed. + */ + int64_t maxsize; + + /** + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ + int direct; + + /** + * Bytes read statistic + * This field is internal to libavformat and access from outside is not allowed. + */ + int64_t bytes_read; + + /** + * seek statistic + * This field is internal to libavformat and access from outside is not allowed. + */ + int seek_count; + + /** + * writeout statistic + * This field is internal to libavformat and access from outside is not allowed. + */ + int writeout_count; + + /** + * Original buffer size + * used internally after probing and ensure seekback to reset the buffer size + * This field is internal to libavformat and access from outside is not allowed. + */ + int orig_buffer_size; + + /** + * Threshold to favor readahead over seek. + * This is current internal only, do not use from outside. + */ + int short_seek_threshold; + + /** + * ',' separated list of allowed protocols. + */ + const char *protocol_whitelist; + + /** + * ',' separated list of disallowed protocols. + */ + const char *protocol_blacklist; + + /** + * A callback that is used instead of write_packet. + */ + int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size, + enum AVIODataMarkerType type, int64_t time); + /** + * If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT, + * but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly + * small chunks of data returned from the callback). + */ + int ignore_boundary_point; + + /** + * Internal, not meant to be used from outside of AVIOContext. + */ + enum AVIODataMarkerType current_type; + int64_t last_time; + + /** + * A callback that is used instead of short_seek_threshold. + * This is current internal only, do not use from outside. + */ + int (*short_seek_get)(void *opaque); + + int64_t written; + + /** + * Maximum reached position before a backward seek in the write buffer, + * used keeping track of already written data for a later flush. + */ + unsigned char *buf_ptr_max; + + /** + * Try to buffer at least this amount of data before flushing it + */ + int min_packet_size; +} AVIOContext; + +/** + * Return the name of the protocol that will handle the passed URL. + * + * NULL is returned if no protocol could be found for the given URL. + * + * @return Name of the protocol or NULL. + */ +const char *avio_find_protocol_name(const char *url); + +/** + * Return AVIO_FLAG_* access flags corresponding to the access permissions + * of the resource in url, or a negative value corresponding to an + * AVERROR code in case of failure. The returned access flags are + * masked by the value in flags. + * + * @note This function is intrinsically unsafe, in the sense that the + * checked resource may change its existence or permission status from + * one call to another. Thus you should not trust the returned value, + * unless you are sure that no other processes are accessing the + * checked resource. + */ +int avio_check(const char *url, int flags); + +/** + * Move or rename a resource. + * + * @note url_src and url_dst should share the same protocol and authority. + * + * @param url_src url to resource to be moved + * @param url_dst new url to resource if the operation succeeded + * @return >=0 on success or negative on error. + */ +int avpriv_io_move(const char *url_src, const char *url_dst); + +/** + * Delete a resource. + * + * @param url resource to be deleted. + * @return >=0 on success or negative on error. + */ +int avpriv_io_delete(const char *url); + +/** + * Open directory for reading. + * + * @param s directory read context. Pointer to a NULL pointer must be passed. + * @param url directory to be listed. + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dictionary + * containing options that were not found. May be NULL. + * @return >=0 on success or negative on error. + */ +int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options); + +/** + * Get next directory entry. + * + * Returned entry must be freed with avio_free_directory_entry(). In particular + * it may outlive AVIODirContext. + * + * @param s directory read context. + * @param[out] next next entry or NULL when no more entries. + * @return >=0 on success or negative on error. End of list is not considered an + * error. + */ +int avio_read_dir(AVIODirContext *s, AVIODirEntry **next); + +/** + * Close directory. + * + * @note Entries created using avio_read_dir() are not deleted and must be + * freeded with avio_free_directory_entry(). + * + * @param s directory read context. + * @return >=0 on success or negative on error. + */ +int avio_close_dir(AVIODirContext **s); + +/** + * Free entry allocated by avio_read_dir(). + * + * @param entry entry to be freed. + */ +void avio_free_directory_entry(AVIODirEntry **entry); + +/** + * Allocate and initialize an AVIOContext for buffered I/O. It must be later + * freed with avio_context_free(). + * + * @param buffer Memory block for input/output operations via AVIOContext. + * The buffer must be allocated with av_malloc() and friends. + * It may be freed and replaced with a new buffer by libavformat. + * AVIOContext.buffer holds the buffer currently in use, + * which must be later freed with av_free(). + * @param buffer_size The buffer size is very important for performance. + * For protocols with fixed blocksize it should be set to this blocksize. + * For others a typical size is a cache page, e.g. 4kb. + * @param write_flag Set to 1 if the buffer should be writable, 0 otherwise. + * @param opaque An opaque pointer to user-specific data. + * @param read_packet A function for refilling the buffer, may be NULL. + * For stream protocols, must never return 0 but rather + * a proper AVERROR code. + * @param write_packet A function for writing the buffer contents, may be NULL. + * The function may not change the input buffers content. + * @param seek A function for seeking to specified byte position, may be NULL. + * + * @return Allocated AVIOContext or NULL on failure. + */ +AVIOContext *avio_alloc_context( + unsigned char *buffer, + int buffer_size, + int write_flag, + void *opaque, + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), + int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), + int64_t (*seek)(void *opaque, int64_t offset, int whence)); + +/** + * Free the supplied IO context and everything associated with it. + * + * @param s Double pointer to the IO context. This function will write NULL + * into s. + */ +void avio_context_free(AVIOContext **s); + +void avio_w8(AVIOContext *s, int b); +void avio_write(AVIOContext *s, const unsigned char *buf, int size); +void avio_wl64(AVIOContext *s, uint64_t val); +void avio_wb64(AVIOContext *s, uint64_t val); +void avio_wl32(AVIOContext *s, unsigned int val); +void avio_wb32(AVIOContext *s, unsigned int val); +void avio_wl24(AVIOContext *s, unsigned int val); +void avio_wb24(AVIOContext *s, unsigned int val); +void avio_wl16(AVIOContext *s, unsigned int val); +void avio_wb16(AVIOContext *s, unsigned int val); + +/** + * Write a NULL-terminated string. + * @return number of bytes written. + */ +int avio_put_str(AVIOContext *s, const char *str); + +/** + * Convert an UTF-8 string to UTF-16LE and write it. + * @param s the AVIOContext + * @param str NULL-terminated UTF-8 string + * + * @return number of bytes written. + */ +int avio_put_str16le(AVIOContext *s, const char *str); + +/** + * Convert an UTF-8 string to UTF-16BE and write it. + * @param s the AVIOContext + * @param str NULL-terminated UTF-8 string + * + * @return number of bytes written. + */ +int avio_put_str16be(AVIOContext *s, const char *str); + +/** + * Mark the written bytestream as a specific type. + * + * Zero-length ranges are omitted from the output. + * + * @param time the stream time the current bytestream pos corresponds to + * (in AV_TIME_BASE units), or AV_NOPTS_VALUE if unknown or not + * applicable + * @param type the kind of data written starting at the current pos + */ +void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type); + +/** + * ORing this as the "whence" parameter to a seek function causes it to + * return the filesize without seeking anywhere. Supporting this is optional. + * If it is not supported then the seek function will return <0. + */ +#define AVSEEK_SIZE 0x10000 + +/** + * Passing this flag as the "whence" parameter to a seek function causes it to + * seek by any means (like reopening and linear reading) or other normally unreasonable + * means that can be extremely slow. + * This may be ignored by the seek code. + */ +#define AVSEEK_FORCE 0x20000 + +/** + * fseek() equivalent for AVIOContext. + * @return new position or AVERROR. + */ +int64_t avio_seek(AVIOContext *s, int64_t offset, int whence); + +/** + * Skip given number of bytes forward + * @return new position or AVERROR. + */ +int64_t avio_skip(AVIOContext *s, int64_t offset); + +/** + * ftell() equivalent for AVIOContext. + * @return position or AVERROR. + */ +static av_always_inline int64_t avio_tell(AVIOContext *s) +{ + return avio_seek(s, 0, SEEK_CUR); +} + +/** + * Get the filesize. + * @return filesize or AVERROR + */ +int64_t avio_size(AVIOContext *s); + +/** + * Similar to feof() but also returns nonzero on read errors. + * @return non zero if and only if at end of file or a read error happened when reading. + */ +int avio_feof(AVIOContext *s); + +/** + * Writes a formatted string to the context. + * @return number of bytes written, < 0 on error. + */ +int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3); + +/** + * Write a NULL terminated array of strings to the context. + * Usually you don't need to use this function directly but its macro wrapper, + * avio_print. + */ +void avio_print_string_array(AVIOContext *s, const char *strings[]); + +/** + * Write strings (const char *) to the context. + * This is a convenience macro around avio_print_string_array and it + * automatically creates the string array from the variable argument list. + * For simple string concatenations this function is more performant than using + * avio_printf since it does not need a temporary buffer. + */ +#define avio_print(s, ...) \ + avio_print_string_array(s, (const char*[]){__VA_ARGS__, NULL}) + +/** + * Force flushing of buffered data. + * + * For write streams, force the buffered data to be immediately written to the output, + * without to wait to fill the internal buffer. + * + * For read streams, discard all currently buffered data, and advance the + * reported file position to that of the underlying stream. This does not + * read new data, and does not perform any seeks. + */ +void avio_flush(AVIOContext *s); + +/** + * Read size bytes from AVIOContext into buf. + * @return number of bytes read or AVERROR + */ +int avio_read(AVIOContext *s, unsigned char *buf, int size); + +/** + * Read size bytes from AVIOContext into buf. Unlike avio_read(), this is allowed + * to read fewer bytes than requested. The missing bytes can be read in the next + * call. This always tries to read at least 1 byte. + * Useful to reduce latency in certain cases. + * @return number of bytes read or AVERROR + */ +int avio_read_partial(AVIOContext *s, unsigned char *buf, int size); + +/** + * @name Functions for reading from AVIOContext + * @{ + * + * @note return 0 if EOF, so you cannot use it if EOF handling is + * necessary + */ +int avio_r8 (AVIOContext *s); +unsigned int avio_rl16(AVIOContext *s); +unsigned int avio_rl24(AVIOContext *s); +unsigned int avio_rl32(AVIOContext *s); +uint64_t avio_rl64(AVIOContext *s); +unsigned int avio_rb16(AVIOContext *s); +unsigned int avio_rb24(AVIOContext *s); +unsigned int avio_rb32(AVIOContext *s); +uint64_t avio_rb64(AVIOContext *s); +/** + * @} + */ + +/** + * Read a string from pb into buf. The reading will terminate when either + * a NULL character was encountered, maxlen bytes have been read, or nothing + * more can be read from pb. The result is guaranteed to be NULL-terminated, it + * will be truncated if buf is too small. + * Note that the string is not interpreted or validated in any way, it + * might get truncated in the middle of a sequence for multi-byte encodings. + * + * @return number of bytes read (is always <= maxlen). + * If reading ends on EOF or error, the return value will be one more than + * bytes actually read. + */ +int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen); + +/** + * Read a UTF-16 string from pb and convert it to UTF-8. + * The reading will terminate when either a null or invalid character was + * encountered or maxlen bytes have been read. + * @return number of bytes read (is always <= maxlen) + */ +int avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen); +int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen); + + +/** + * @name URL open modes + * The flags argument to avio_open must be one of the following + * constants, optionally ORed with other flags. + * @{ + */ +#define AVIO_FLAG_READ 1 /**< read-only */ +#define AVIO_FLAG_WRITE 2 /**< write-only */ +#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE) /**< read-write pseudo flag */ +/** + * @} + */ + +/** + * Use non-blocking mode. + * If this flag is set, operations on the context will return + * AVERROR(EAGAIN) if they can not be performed immediately. + * If this flag is not set, operations on the context will never return + * AVERROR(EAGAIN). + * Note that this flag does not affect the opening/connecting of the + * context. Connecting a protocol will always block if necessary (e.g. on + * network protocols) but never hang (e.g. on busy devices). + * Warning: non-blocking protocols is work-in-progress; this flag may be + * silently ignored. + */ +#define AVIO_FLAG_NONBLOCK 8 + +/** + * Use direct mode. + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ +#define AVIO_FLAG_DIRECT 0x8000 + +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param url resource to access + * @param flags flags which control how the resource indicated by url + * is to be opened + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open(AVIOContext **s, const char *url, int flags); + +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param url resource to access + * @param flags flags which control how the resource indicated by url + * is to be opened + * @param int_cb an interrupt callback to be used at the protocols level + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dict containing options + * that were not found. May be NULL. + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open2(AVIOContext **s, const char *url, int flags, + const AVIOInterruptCB *int_cb, AVDictionary **options); + +/** + * Close the resource accessed by the AVIOContext s and free it. + * This function can only be used if s was opened by avio_open(). + * + * The internal buffer is automatically flushed before closing the + * resource. + * + * @return 0 on success, an AVERROR < 0 on error. + * @see avio_closep + */ +int avio_close(AVIOContext *s); + +/** + * Close the resource accessed by the AVIOContext *s, free it + * and set the pointer pointing to it to NULL. + * This function can only be used if s was opened by avio_open(). + * + * The internal buffer is automatically flushed before closing the + * resource. + * + * @return 0 on success, an AVERROR < 0 on error. + * @see avio_close + */ +int avio_closep(AVIOContext **s); + + +/** + * Open a write only memory stream. + * + * @param s new IO context + * @return zero if no error. + */ +int avio_open_dyn_buf(AVIOContext **s); + +/** + * Return the written size and a pointer to the buffer. + * The AVIOContext stream is left intact. + * The buffer must NOT be freed. + * No padding is added to the buffer. + * + * @param s IO context + * @param pbuffer pointer to a byte buffer + * @return the length of the byte buffer + */ +int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + +/** + * Return the written size and a pointer to the buffer. The buffer + * must be freed with av_free(). + * Padding of AV_INPUT_BUFFER_PADDING_SIZE is added to the buffer. + * + * @param s IO context + * @param pbuffer pointer to a byte buffer + * @return the length of the byte buffer + */ +int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + +/** + * Iterate through names of available protocols. + * + * @param opaque A private pointer representing current protocol. + * It must be a pointer to NULL on first iteration and will + * be updated by successive calls to avio_enum_protocols. + * @param output If set to 1, iterate over output protocols, + * otherwise over input protocols. + * + * @return A static string containing the name of current protocol or NULL + */ +const char *avio_enum_protocols(void **opaque, int output); + +/** + * Get AVClass by names of available protocols. + * + * @return A AVClass of input protocol name or NULL + */ +const AVClass *avio_protocol_get_class(const char *name); + +/** + * Pause and resume playing - only meaningful if using a network streaming + * protocol (e.g. MMS). + * + * @param h IO context from which to call the read_pause function pointer + * @param pause 1 for pause, 0 for resume + */ +int avio_pause(AVIOContext *h, int pause); + +/** + * Seek to a given timestamp relative to some component stream. + * Only meaningful if using a network streaming protocol (e.g. MMS.). + * + * @param h IO context from which to call the seek function pointers + * @param stream_index The stream index that the timestamp is relative to. + * If stream_index is (-1) the timestamp should be in AV_TIME_BASE + * units from the beginning of the presentation. + * If a stream_index >= 0 is used and the protocol does not support + * seeking based on component streams, the call will fail. + * @param timestamp timestamp in AVStream.time_base units + * or if there is no stream specified then in AV_TIME_BASE units. + * @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE + * and AVSEEK_FLAG_ANY. The protocol may silently ignore + * AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will + * fail if used and not supported. + * @return >= 0 on success + * @see AVInputFormat::read_seek + */ +int64_t avio_seek_time(AVIOContext *h, int stream_index, + int64_t timestamp, int flags); + +/* Avoid a warning. The header can not be included because it breaks c++. */ +struct AVBPrint; + +/** + * Read contents of h into print buffer, up to max_size bytes, or up to EOF. + * + * @return 0 for success (max_size bytes read or EOF reached), negative error + * code otherwise + */ +int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size); + +/** + * Accept and allocate a client context on a server context. + * @param s the server context + * @param c the client context, must be unallocated + * @return >= 0 on success or a negative value corresponding + * to an AVERROR on failure + */ +int avio_accept(AVIOContext *s, AVIOContext **c); + +/** + * Perform one step of the protocol handshake to accept a new client. + * This function must be called on a client returned by avio_accept() before + * using it as a read/write context. + * It is separate from avio_accept() because it may block. + * A step of the handshake is defined by places where the application may + * decide to change the proceedings. + * For example, on a protocol with a request header and a reply header, each + * one can constitute a step because the application may use the parameters + * from the request to change parameters in the reply; or each individual + * chunk of the request can constitute a step. + * If the handshake is already finished, avio_handshake() does nothing and + * returns 0 immediately. + * + * @param c the client context to perform the handshake on + * @return 0 on a complete and successful handshake + * > 0 if the handshake progressed, but is not complete + * < 0 for an AVERROR code + */ +int avio_handshake(AVIOContext *c); +#endif /* AVFORMAT_AVIO_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavformat/version.h b/src/framework/media/thirdparty/ffmpeg/v4/libavformat/version.h new file mode 100644 index 0000000000000..46dc51a227fd1 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavformat/version.h @@ -0,0 +1,123 @@ +/* + * Version macros. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_VERSION_H +#define AVFORMAT_VERSION_H + +/** + * @file + * @ingroup libavf + * Libavformat version macros + */ + +#include "libavutil/version.h" + +// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) +// Also please add any ticket numbers that you believe might be affected here +#define LIBAVFORMAT_VERSION_MAJOR 58 +#define LIBAVFORMAT_VERSION_MINOR 76 +#define LIBAVFORMAT_VERSION_MICRO 100 + +#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT + +#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + * + */ +#ifndef FF_API_COMPUTE_PKT_FIELDS2 +#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_OLD_OPEN_CALLBACKS +#define FF_API_OLD_OPEN_CALLBACKS (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_LAVF_AVCTX +#define FF_API_LAVF_AVCTX (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_HTTP_USER_AGENT +#define FF_API_HTTP_USER_AGENT (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_HLS_WRAP +#define FF_API_HLS_WRAP (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_HLS_USE_LOCALTIME +#define FF_API_HLS_USE_LOCALTIME (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_LAVF_KEEPSIDE_FLAG +#define FF_API_LAVF_KEEPSIDE_FLAG (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_OLD_ROTATE_API +#define FF_API_OLD_ROTATE_API (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_FORMAT_GET_SET +#define FF_API_FORMAT_GET_SET (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_OLD_AVIO_EOF_0 +#define FF_API_OLD_AVIO_EOF_0 (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_LAVF_FFSERVER +#define FF_API_LAVF_FFSERVER (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_FORMAT_FILENAME +#define FF_API_FORMAT_FILENAME (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_OLD_RTSP_OPTIONS +#define FF_API_OLD_RTSP_OPTIONS (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_NEXT +#define FF_API_NEXT (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_DASH_MIN_SEG_DURATION +#define FF_API_DASH_MIN_SEG_DURATION (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_LAVF_MP4A_LATM +#define FF_API_LAVF_MP4A_LATM (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_AVIOFORMAT +#define FF_API_AVIOFORMAT (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_DEMUXER_OPEN +#define FF_API_DEMUXER_OPEN (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CHAPTER_ID_INT +#define FF_API_CHAPTER_ID_INT (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_LAVF_PRIV_OPT +#define FF_API_LAVF_PRIV_OPT (LIBAVFORMAT_VERSION_MAJOR < 60) +#endif + + +#ifndef FF_API_R_FRAME_RATE +#define FF_API_R_FRAME_RATE 1 +#endif +#endif /* AVFORMAT_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/attributes.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/attributes.h new file mode 100644 index 0000000000000..5cb9fe345288e --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/attributes.h @@ -0,0 +1,173 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Macro definitions for various function/variable attributes + */ + +#ifndef AVUTIL_ATTRIBUTES_H +#define AVUTIL_ATTRIBUTES_H + +#ifdef __GNUC__ +# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) +# define AV_GCC_VERSION_AT_MOST(x,y) (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y)) +#else +# define AV_GCC_VERSION_AT_LEAST(x,y) 0 +# define AV_GCC_VERSION_AT_MOST(x,y) 0 +#endif + +#ifdef __has_builtin +# define AV_HAS_BUILTIN(x) __has_builtin(x) +#else +# define AV_HAS_BUILTIN(x) 0 +#endif + +#ifndef av_always_inline +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_always_inline __attribute__((always_inline)) inline +#elif defined(_MSC_VER) +# define av_always_inline __forceinline +#else +# define av_always_inline inline +#endif +#endif + +#ifndef av_extern_inline +#if defined(__ICL) && __ICL >= 1210 || defined(__GNUC_STDC_INLINE__) +# define av_extern_inline extern inline +#else +# define av_extern_inline inline +#endif +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,4) +# define av_warn_unused_result __attribute__((warn_unused_result)) +#else +# define av_warn_unused_result +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_noinline __attribute__((noinline)) +#elif defined(_MSC_VER) +# define av_noinline __declspec(noinline) +#else +# define av_noinline +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) +# define av_pure __attribute__((pure)) +#else +# define av_pure +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,6) || defined(__clang__) +# define av_const __attribute__((const)) +#else +# define av_const +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,3) || defined(__clang__) +# define av_cold __attribute__((cold)) +#else +# define av_cold +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,1) && !defined(__llvm__) +# define av_flatten __attribute__((flatten)) +#else +# define av_flatten +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define attribute_deprecated __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define attribute_deprecated __declspec(deprecated) +#else +# define attribute_deprecated +#endif + +/** + * Disable warnings about deprecated features + * This is useful for sections of code kept for backward compatibility and + * scheduled for removal. + */ +#ifndef AV_NOWARN_DEPRECATED +#if AV_GCC_VERSION_AT_LEAST(4,6) +# define AV_NOWARN_DEPRECATED(code) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \ + code \ + _Pragma("GCC diagnostic pop") +#elif defined(_MSC_VER) +# define AV_NOWARN_DEPRECATED(code) \ + __pragma(warning(push)) \ + __pragma(warning(disable : 4996)) \ + code; \ + __pragma(warning(pop)) +#else +# define AV_NOWARN_DEPRECATED(code) code +#endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define av_unused __attribute__((unused)) +#else +# define av_unused +#endif + +/** + * Mark a variable as used and prevent the compiler from optimizing it + * away. This is useful for variables accessed only from inline + * assembler without the compiler being aware. + */ +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) +# define av_used __attribute__((used)) +#else +# define av_used +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,3) || defined(__clang__) +# define av_alias __attribute__((may_alias)) +#else +# define av_alias +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__INTEL_COMPILER) +# define av_uninit(x) x=x +#else +# define av_uninit(x) x +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define av_builtin_constant_p __builtin_constant_p +# define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos))) +#else +# define av_builtin_constant_p(x) 0 +# define av_printf_format(fmtpos, attrpos) +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,5) || defined(__clang__) +# define av_noreturn __attribute__((noreturn)) +#else +# define av_noreturn +#endif + +#endif /* AVUTIL_ATTRIBUTES_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/avstring.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/avstring.h new file mode 100644 index 0000000000000..fae446c302744 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/avstring.h @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2007 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVSTRING_H +#define AVUTIL_AVSTRING_H + +#include +#include +#include "attributes.h" +#include "version.h" + +/** + * @addtogroup lavu_string + * @{ + */ + +/** + * Return non-zero if pfx is a prefix of str. If it is, *ptr is set to + * the address of the first character in str after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_strstart(const char *str, const char *pfx, const char **ptr); + +/** + * Return non-zero if pfx is a prefix of str independent of case. If + * it is, *ptr is set to the address of the first character in str + * after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_stristart(const char *str, const char *pfx, const char **ptr); + +/** + * Locate the first case-independent occurrence in the string haystack + * of the string needle. A zero-length string needle is considered to + * match at the start of haystack. + * + * This function is a case-insensitive version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_stristr(const char *haystack, const char *needle); + +/** + * Locate the first occurrence of the string needle in the string haystack + * where not more than hay_length characters are searched. A zero-length + * string needle is considered to match at the start of haystack. + * + * This function is a length-limited version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @param hay_length length of string to search in + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_strnstr(const char *haystack, const char *needle, size_t hay_length); + +/** + * Copy the string src to dst, but no more than size - 1 bytes, and + * null-terminate dst. + * + * This function is the same as BSD strlcpy(). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the length of src + * + * @warning since the return value is the length of src, src absolutely + * _must_ be a properly 0-terminated string, otherwise this will read beyond + * the end of the buffer and possibly crash. + */ +size_t av_strlcpy(char *dst, const char *src, size_t size); + +/** + * Append the string src to the string dst, but to a total length of + * no more than size - 1 bytes, and null-terminate dst. + * + * This function is similar to BSD strlcat(), but differs when + * size <= strlen(dst). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the total length of src and dst + * + * @warning since the return value use the length of src and dst, these + * absolutely _must_ be a properly 0-terminated strings, otherwise this + * will read beyond the end of the buffer and possibly crash. + */ +size_t av_strlcat(char *dst, const char *src, size_t size); + +/** + * Append output to a string, according to a format. Never write out of + * the destination buffer, and always put a terminating 0 within + * the buffer. + * @param dst destination buffer (string to which the output is + * appended) + * @param size total size of the destination buffer + * @param fmt printf-compatible format string, specifying how the + * following parameters are used + * @return the length of the string that would have been generated + * if enough space had been available + */ +size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Get the count of continuous non zero chars starting from the beginning. + * + * @param len maximum number of characters to check in the string, that + * is the maximum value which is returned by the function + */ +static inline size_t av_strnlen(const char *s, size_t len) +{ + size_t i; + for (i = 0; i < len && s[i]; i++) + ; + return i; +} + +/** + * Print arguments following specified format into a large enough auto + * allocated buffer. It is similar to GNU asprintf(). + * @param fmt printf-compatible format string, specifying how the + * following parameters are used. + * @return the allocated string + * @note You have to free the string yourself with av_free(). + */ +char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2); + +#if FF_API_D2STR +/** + * Convert a number to an av_malloced string. + * @deprecated use av_asprintf() with "%f" or a more specific format + */ +attribute_deprecated +char *av_d2str(double d); +#endif + +/** + * Unescape the given string until a non escaped terminating char, + * and return the token corresponding to the unescaped string. + * + * The normal \ and ' escaping is supported. Leading and trailing + * whitespaces are removed, unless they are escaped with '\' or are + * enclosed between ''. + * + * @param buf the buffer to parse, buf will be updated to point to the + * terminating char + * @param term a 0-terminated list of terminating chars + * @return the malloced unescaped string, which must be av_freed by + * the user, NULL in case of allocation failure + */ +char *av_get_token(const char **buf, const char *term); + +/** + * Split the string into several tokens which can be accessed by + * successive calls to av_strtok(). + * + * A token is defined as a sequence of characters not belonging to the + * set specified in delim. + * + * On the first call to av_strtok(), s should point to the string to + * parse, and the value of saveptr is ignored. In subsequent calls, s + * should be NULL, and saveptr should be unchanged since the previous + * call. + * + * This function is similar to strtok_r() defined in POSIX.1. + * + * @param s the string to parse, may be NULL + * @param delim 0-terminated list of token delimiters, must be non-NULL + * @param saveptr user-provided pointer which points to stored + * information necessary for av_strtok() to continue scanning the same + * string. saveptr is updated to point to the next character after the + * first delimiter found, or to NULL if the string was terminated + * @return the found token, or NULL when no token is found + */ +char *av_strtok(char *s, const char *delim, char **saveptr); + +/** + * Locale-independent conversion of ASCII isdigit. + */ +static inline av_const int av_isdigit(int c) +{ + return c >= '0' && c <= '9'; +} + +/** + * Locale-independent conversion of ASCII isgraph. + */ +static inline av_const int av_isgraph(int c) +{ + return c > 32 && c < 127; +} + +/** + * Locale-independent conversion of ASCII isspace. + */ +static inline av_const int av_isspace(int c) +{ + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || + c == '\v'; +} + +/** + * Locale-independent conversion of ASCII characters to uppercase. + */ +static inline av_const int av_toupper(int c) +{ + if (c >= 'a' && c <= 'z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII characters to lowercase. + */ +static inline av_const int av_tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII isxdigit. + */ +static inline av_const int av_isxdigit(int c) +{ + c = av_tolower(c); + return av_isdigit(c) || (c >= 'a' && c <= 'f'); +} + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strcasecmp(const char *a, const char *b); + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strncasecmp(const char *a, const char *b, size_t n); + +/** + * Locale-independent strings replace. + * @note This means only ASCII-range characters are replace + */ +char *av_strireplace(const char *str, const char *from, const char *to); + +/** + * Thread safe basename. + * @param path the string to parse, on DOS both \ and / are considered separators. + * @return pointer to the basename substring. + * If path does not contain a slash, the function returns a copy of path. + * If path is a NULL pointer or points to an empty string, a pointer + * to a string "." is returned. + */ +const char *av_basename(const char *path); + +/** + * Thread safe dirname. + * @param path the string to parse, on DOS both \ and / are considered separators. + * @return A pointer to a string that's the parent directory of path. + * If path is a NULL pointer or points to an empty string, a pointer + * to a string "." is returned. + * @note the function may modify the contents of the path, so copies should be passed. + */ +const char *av_dirname(char *path); + +/** + * Match instances of a name in a comma-separated list of names. + * List entries are checked from the start to the end of the names list, + * the first match ends further processing. If an entry prefixed with '-' + * matches, then 0 is returned. The "ALL" list entry is considered to + * match all names. + * + * @param name Name to look for. + * @param names List of names. + * @return 1 on match, 0 otherwise. + */ +int av_match_name(const char *name, const char *names); + +/** + * Append path component to the existing path. + * Path separator '/' is placed between when needed. + * Resulting string have to be freed with av_free(). + * @param path base path + * @param component component to be appended + * @return new path or NULL on error. + */ +char *av_append_path_component(const char *path, const char *component); + +enum AVEscapeMode { + AV_ESCAPE_MODE_AUTO, ///< Use auto-selected escaping mode. + AV_ESCAPE_MODE_BACKSLASH, ///< Use backslash escaping. + AV_ESCAPE_MODE_QUOTE, ///< Use single-quote escaping. + AV_ESCAPE_MODE_XML, ///< Use XML non-markup character data escaping. +}; + +/** + * Consider spaces special and escape them even in the middle of the + * string. + * + * This is equivalent to adding the whitespace characters to the special + * characters lists, except it is guaranteed to use the exact same list + * of whitespace characters as the rest of libavutil. + */ +#define AV_ESCAPE_FLAG_WHITESPACE (1 << 0) + +/** + * Escape only specified special characters. + * Without this flag, escape also any characters that may be considered + * special by av_get_token(), such as the single quote. + */ +#define AV_ESCAPE_FLAG_STRICT (1 << 1) + +/** + * Within AV_ESCAPE_MODE_XML, additionally escape single quotes for single + * quoted attributes. + */ +#define AV_ESCAPE_FLAG_XML_SINGLE_QUOTES (1 << 2) + +/** + * Within AV_ESCAPE_MODE_XML, additionally escape double quotes for double + * quoted attributes. + */ +#define AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES (1 << 3) + + +/** + * Escape string in src, and put the escaped string in an allocated + * string in *dst, which must be freed with av_free(). + * + * @param dst pointer where an allocated string is put + * @param src string to escape, must be non-NULL + * @param special_chars string containing the special characters which + * need to be escaped, can be NULL + * @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros. + * Any unknown value for mode will be considered equivalent to + * AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without + * notice. + * @param flags flags which control how to escape, see AV_ESCAPE_FLAG_ macros + * @return the length of the allocated string, or a negative error code in case of error + * @see av_bprint_escape() + */ +av_warn_unused_result +int av_escape(char **dst, const char *src, const char *special_chars, + enum AVEscapeMode mode, int flags); + +#define AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES 1 ///< accept codepoints over 0x10FFFF +#define AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS 2 ///< accept non-characters - 0xFFFE and 0xFFFF +#define AV_UTF8_FLAG_ACCEPT_SURROGATES 4 ///< accept UTF-16 surrogates codes +#define AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES 8 ///< exclude control codes not accepted by XML + +#define AV_UTF8_FLAG_ACCEPT_ALL \ + AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES|AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS|AV_UTF8_FLAG_ACCEPT_SURROGATES + +/** + * Read and decode a single UTF-8 code point (character) from the + * buffer in *buf, and update *buf to point to the next byte to + * decode. + * + * In case of an invalid byte sequence, the pointer will be updated to + * the next byte after the invalid sequence and the function will + * return an error code. + * + * Depending on the specified flags, the function will also fail in + * case the decoded code point does not belong to a valid range. + * + * @note For speed-relevant code a carefully implemented use of + * GET_UTF8() may be preferred. + * + * @param codep pointer used to return the parsed code in case of success. + * The value in *codep is set even in case the range check fails. + * @param bufp pointer to the address the first byte of the sequence + * to decode, updated by the function to point to the + * byte next after the decoded sequence + * @param buf_end pointer to the end of the buffer, points to the next + * byte past the last in the buffer. This is used to + * avoid buffer overreads (in case of an unfinished + * UTF-8 sequence towards the end of the buffer). + * @param flags a collection of AV_UTF8_FLAG_* flags + * @return >= 0 in case a sequence was successfully read, a negative + * value in case of invalid sequence + */ +av_warn_unused_result +int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end, + unsigned int flags); + +/** + * Check if a name is in a list. + * @returns 0 if not found, or the 1 based index where it has been found in the + * list. + */ +int av_match_list(const char *name, const char *list, char separator); + +/** + * See libc sscanf manual for more information. + * Locale-independent sscanf implementation. + */ +int av_sscanf(const char *string, const char *format, ...); + +/** + * @} + */ + +#endif /* AVUTIL_AVSTRING_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/avutil.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/avutil.h new file mode 100644 index 0000000000000..4d633156d14df --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/avutil.h @@ -0,0 +1,365 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVUTIL_H +#define AVUTIL_AVUTIL_H + +/** + * @file + * @ingroup lavu + * Convenience header that includes @ref lavu "libavutil"'s core. + */ + +/** + * @mainpage + * + * @section ffmpeg_intro Introduction + * + * This document describes the usage of the different libraries + * provided by FFmpeg. + * + * @li @ref libavc "libavcodec" encoding/decoding library + * @li @ref lavfi "libavfilter" graph-based frame editing library + * @li @ref libavf "libavformat" I/O and muxing/demuxing library + * @li @ref lavd "libavdevice" special devices muxing/demuxing library + * @li @ref lavu "libavutil" common utility library + * @li @ref lswr "libswresample" audio resampling, format conversion and mixing + * @li @ref lpp "libpostproc" post processing library + * @li @ref libsws "libswscale" color conversion and scaling library + * + * @section ffmpeg_versioning Versioning and compatibility + * + * Each of the FFmpeg libraries contains a version.h header, which defines a + * major, minor and micro version number with the + * LIBRARYNAME_VERSION_{MAJOR,MINOR,MICRO} macros. The major version + * number is incremented with backward incompatible changes - e.g. removing + * parts of the public API, reordering public struct members, etc. The minor + * version number is incremented for backward compatible API changes or major + * new features - e.g. adding a new public function or a new decoder. The micro + * version number is incremented for smaller changes that a calling program + * might still want to check for - e.g. changing behavior in a previously + * unspecified situation. + * + * FFmpeg guarantees backward API and ABI compatibility for each library as long + * as its major version number is unchanged. This means that no public symbols + * will be removed or renamed. Types and names of the public struct members and + * values of public macros and enums will remain the same (unless they were + * explicitly declared as not part of the public API). Documented behavior will + * not change. + * + * In other words, any correct program that works with a given FFmpeg snapshot + * should work just as well without any changes with any later snapshot with the + * same major versions. This applies to both rebuilding the program against new + * FFmpeg versions or to replacing the dynamic FFmpeg libraries that a program + * links against. + * + * However, new public symbols may be added and new members may be appended to + * public structs whose size is not part of public ABI (most public structs in + * FFmpeg). New macros and enum values may be added. Behavior in undocumented + * situations may change slightly (and be documented). All those are accompanied + * by an entry in doc/APIchanges and incrementing either the minor or micro + * version number. + */ + +/** + * @defgroup lavu libavutil + * Common code shared across all FFmpeg libraries. + * + * @note + * libavutil is designed to be modular. In most cases, in order to use the + * functions provided by one component of libavutil you must explicitly include + * the specific header containing that feature. If you are only using + * media-related components, you could simply include libavutil/avutil.h, which + * brings in most of the "core" components. + * + * @{ + * + * @defgroup lavu_crypto Crypto and Hashing + * + * @{ + * @} + * + * @defgroup lavu_math Mathematics + * @{ + * + * @} + * + * @defgroup lavu_string String Manipulation + * + * @{ + * + * @} + * + * @defgroup lavu_mem Memory Management + * + * @{ + * + * @} + * + * @defgroup lavu_data Data Structures + * @{ + * + * @} + * + * @defgroup lavu_video Video related + * + * @{ + * + * @} + * + * @defgroup lavu_audio Audio related + * + * @{ + * + * @} + * + * @defgroup lavu_error Error Codes + * + * @{ + * + * @} + * + * @defgroup lavu_log Logging Facility + * + * @{ + * + * @} + * + * @defgroup lavu_misc Other + * + * @{ + * + * @defgroup preproc_misc Preprocessor String Macros + * + * @{ + * + * @} + * + * @defgroup version_utils Library Version Macros + * + * @{ + * + * @} + */ + + +/** + * @addtogroup lavu_ver + * @{ + */ + +/** + * Return the LIBAVUTIL_VERSION_INT constant. + */ +unsigned avutil_version(void); + +/** + * Return an informative version string. This usually is the actual release + * version number or a git commit description. This string has no fixed format + * and can change any time. It should never be parsed by code. + */ +const char *av_version_info(void); + +/** + * Return the libavutil build-time configuration. + */ +const char *avutil_configuration(void); + +/** + * Return the libavutil license. + */ +const char *avutil_license(void); + +/** + * @} + */ + +/** + * @addtogroup lavu_media Media Type + * @brief Media Type + */ + +enum AVMediaType { + AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA + AVMEDIA_TYPE_VIDEO, + AVMEDIA_TYPE_AUDIO, + AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous + AVMEDIA_TYPE_SUBTITLE, + AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse + AVMEDIA_TYPE_NB +}; + +/** + * Return a string describing the media_type enum, NULL if media_type + * is unknown. + */ +const char *av_get_media_type_string(enum AVMediaType media_type); + +/** + * @defgroup lavu_const Constants + * @{ + * + * @defgroup lavu_enc Encoding specific + * + * @note those definition should move to avcodec + * @{ + */ + +#define FF_LAMBDA_SHIFT 7 +#define FF_LAMBDA_SCALE (1< +#include + +#include "version.h" + +/** + * @defgroup lavu_buffer AVBuffer + * @ingroup lavu_data + * + * @{ + * AVBuffer is an API for reference-counted data buffers. + * + * There are two core objects in this API -- AVBuffer and AVBufferRef. AVBuffer + * represents the data buffer itself; it is opaque and not meant to be accessed + * by the caller directly, but only through AVBufferRef. However, the caller may + * e.g. compare two AVBuffer pointers to check whether two different references + * are describing the same data buffer. AVBufferRef represents a single + * reference to an AVBuffer and it is the object that may be manipulated by the + * caller directly. + * + * There are two functions provided for creating a new AVBuffer with a single + * reference -- av_buffer_alloc() to just allocate a new buffer, and + * av_buffer_create() to wrap an existing array in an AVBuffer. From an existing + * reference, additional references may be created with av_buffer_ref(). + * Use av_buffer_unref() to free a reference (this will automatically free the + * data once all the references are freed). + * + * The convention throughout this API and the rest of FFmpeg is such that the + * buffer is considered writable if there exists only one reference to it (and + * it has not been marked as read-only). The av_buffer_is_writable() function is + * provided to check whether this is true and av_buffer_make_writable() will + * automatically create a new writable buffer when necessary. + * Of course nothing prevents the calling code from violating this convention, + * however that is safe only when all the existing references are under its + * control. + * + * @note Referencing and unreferencing the buffers is thread-safe and thus + * may be done from multiple threads simultaneously without any need for + * additional locking. + * + * @note Two different references to the same buffer can point to different + * parts of the buffer (i.e. their AVBufferRef.data will not be equal). + */ + +/** + * A reference counted buffer type. It is opaque and is meant to be used through + * references (AVBufferRef). + */ +typedef struct AVBuffer AVBuffer; + +/** + * A reference to a data buffer. + * + * The size of this struct is not a part of the public ABI and it is not meant + * to be allocated directly. + */ +typedef struct AVBufferRef { + AVBuffer *buffer; + + /** + * The data buffer. It is considered writable if and only if + * this is the only reference to the buffer, in which case + * av_buffer_is_writable() returns 1. + */ + uint8_t *data; + /** + * Size of data in bytes. + */ +#if FF_API_BUFFER_SIZE_T + int size; +#else + size_t size; +#endif +} AVBufferRef; + +/** + * Allocate an AVBuffer of the given size using av_malloc(). + * + * @return an AVBufferRef of given size or NULL when out of memory + */ +#if FF_API_BUFFER_SIZE_T +AVBufferRef *av_buffer_alloc(int size); +#else +AVBufferRef *av_buffer_alloc(size_t size); +#endif + +/** + * Same as av_buffer_alloc(), except the returned buffer will be initialized + * to zero. + */ +#if FF_API_BUFFER_SIZE_T +AVBufferRef *av_buffer_allocz(int size); +#else +AVBufferRef *av_buffer_allocz(size_t size); +#endif + +/** + * Always treat the buffer as read-only, even when it has only one + * reference. + */ +#define AV_BUFFER_FLAG_READONLY (1 << 0) + +/** + * Create an AVBuffer from an existing array. + * + * If this function is successful, data is owned by the AVBuffer. The caller may + * only access data through the returned AVBufferRef and references derived from + * it. + * If this function fails, data is left untouched. + * @param data data array + * @param size size of data in bytes + * @param free a callback for freeing this buffer's data + * @param opaque parameter to be got for processing or passed to free + * @param flags a combination of AV_BUFFER_FLAG_* + * + * @return an AVBufferRef referring to data on success, NULL on failure. + */ +#if FF_API_BUFFER_SIZE_T +AVBufferRef *av_buffer_create(uint8_t *data, int size, +#else +AVBufferRef *av_buffer_create(uint8_t *data, size_t size, +#endif + void (*free)(void *opaque, uint8_t *data), + void *opaque, int flags); + +/** + * Default free callback, which calls av_free() on the buffer data. + * This function is meant to be passed to av_buffer_create(), not called + * directly. + */ +void av_buffer_default_free(void *opaque, uint8_t *data); + +/** + * Create a new reference to an AVBuffer. + * + * @return a new AVBufferRef referring to the same AVBuffer as buf or NULL on + * failure. + */ +AVBufferRef *av_buffer_ref(AVBufferRef *buf); + +/** + * Free a given reference and automatically free the buffer if there are no more + * references to it. + * + * @param buf the reference to be freed. The pointer is set to NULL on return. + */ +void av_buffer_unref(AVBufferRef **buf); + +/** + * @return 1 if the caller may write to the data referred to by buf (which is + * true if and only if buf is the only reference to the underlying AVBuffer). + * Return 0 otherwise. + * A positive answer is valid until av_buffer_ref() is called on buf. + */ +int av_buffer_is_writable(const AVBufferRef *buf); + +/** + * @return the opaque parameter set by av_buffer_create. + */ +void *av_buffer_get_opaque(const AVBufferRef *buf); + +int av_buffer_get_ref_count(const AVBufferRef *buf); + +/** + * Create a writable reference from a given buffer reference, avoiding data copy + * if possible. + * + * @param buf buffer reference to make writable. On success, buf is either left + * untouched, or it is unreferenced and a new writable AVBufferRef is + * written in its place. On failure, buf is left untouched. + * @return 0 on success, a negative AVERROR on failure. + */ +int av_buffer_make_writable(AVBufferRef **buf); + +/** + * Reallocate a given buffer. + * + * @param buf a buffer reference to reallocate. On success, buf will be + * unreferenced and a new reference with the required size will be + * written in its place. On failure buf will be left untouched. *buf + * may be NULL, then a new buffer is allocated. + * @param size required new buffer size. + * @return 0 on success, a negative AVERROR on failure. + * + * @note the buffer is actually reallocated with av_realloc() only if it was + * initially allocated through av_buffer_realloc(NULL) and there is only one + * reference to it (i.e. the one passed to this function). In all other cases + * a new buffer is allocated and the data is copied. + */ +#if FF_API_BUFFER_SIZE_T +int av_buffer_realloc(AVBufferRef **buf, int size); +#else +int av_buffer_realloc(AVBufferRef **buf, size_t size); +#endif + +/** + * Ensure dst refers to the same data as src. + * + * When *dst is already equivalent to src, do nothing. Otherwise unreference dst + * and replace it with a new reference to src. + * + * @param dst Pointer to either a valid buffer reference or NULL. On success, + * this will point to a buffer reference equivalent to src. On + * failure, dst will be left untouched. + * @param src A buffer reference to replace dst with. May be NULL, then this + * function is equivalent to av_buffer_unref(dst). + * @return 0 on success + * AVERROR(ENOMEM) on memory allocation failure. + */ +int av_buffer_replace(AVBufferRef **dst, AVBufferRef *src); + +/** + * @} + */ + +/** + * @defgroup lavu_bufferpool AVBufferPool + * @ingroup lavu_data + * + * @{ + * AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers. + * + * Frequently allocating and freeing large buffers may be slow. AVBufferPool is + * meant to solve this in cases when the caller needs a set of buffers of the + * same size (the most obvious use case being buffers for raw video or audio + * frames). + * + * At the beginning, the user must call av_buffer_pool_init() to create the + * buffer pool. Then whenever a buffer is needed, call av_buffer_pool_get() to + * get a reference to a new buffer, similar to av_buffer_alloc(). This new + * reference works in all aspects the same way as the one created by + * av_buffer_alloc(). However, when the last reference to this buffer is + * unreferenced, it is returned to the pool instead of being freed and will be + * reused for subsequent av_buffer_pool_get() calls. + * + * When the caller is done with the pool and no longer needs to allocate any new + * buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable. + * Once all the buffers are released, it will automatically be freed. + * + * Allocating and releasing buffers with this API is thread-safe as long as + * either the default alloc callback is used, or the user-supplied one is + * thread-safe. + */ + +/** + * The buffer pool. This structure is opaque and not meant to be accessed + * directly. It is allocated with av_buffer_pool_init() and freed with + * av_buffer_pool_uninit(). + */ +typedef struct AVBufferPool AVBufferPool; + +/** + * Allocate and initialize a buffer pool. + * + * @param size size of each buffer in this pool + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be used + * (av_buffer_alloc()). + * @return newly created buffer pool on success, NULL on error. + */ +#if FF_API_BUFFER_SIZE_T +AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)); +#else +AVBufferPool *av_buffer_pool_init(size_t size, AVBufferRef* (*alloc)(size_t size)); +#endif + +/** + * Allocate and initialize a buffer pool with a more complex allocator. + * + * @param size size of each buffer in this pool + * @param opaque arbitrary user data used by the allocator + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be + * used (av_buffer_alloc()). + * @param pool_free a function that will be called immediately before the pool + * is freed. I.e. after av_buffer_pool_uninit() is called + * by the caller and all the frames are returned to the pool + * and freed. It is intended to uninitialize the user opaque + * data. May be NULL. + * @return newly created buffer pool on success, NULL on error. + */ +#if FF_API_BUFFER_SIZE_T +AVBufferPool *av_buffer_pool_init2(int size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, int size), +#else +AVBufferPool *av_buffer_pool_init2(size_t size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, size_t size), +#endif + void (*pool_free)(void *opaque)); + +/** + * Mark the pool as being available for freeing. It will actually be freed only + * once all the allocated buffers associated with the pool are released. Thus it + * is safe to call this function while some of the allocated buffers are still + * in use. + * + * @param pool pointer to the pool to be freed. It will be set to NULL. + */ +void av_buffer_pool_uninit(AVBufferPool **pool); + +/** + * Allocate a new AVBuffer, reusing an old buffer from the pool when available. + * This function may be called simultaneously from multiple threads. + * + * @return a reference to the new buffer on success, NULL on error. + */ +AVBufferRef *av_buffer_pool_get(AVBufferPool *pool); + +/** + * Query the original opaque parameter of an allocated buffer in the pool. + * + * @param ref a buffer reference to a buffer returned by av_buffer_pool_get. + * @return the opaque parameter set by the buffer allocator function of the + * buffer pool. + * + * @note the opaque parameter of ref is used by the buffer pool implementation, + * therefore you have to use this function to access the original opaque + * parameter of an allocated buffer. + */ +void *av_buffer_pool_buffer_get_opaque(AVBufferRef *ref); + +/** + * @} + */ + +#endif /* AVUTIL_BUFFER_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/channel_layout.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/channel_layout.h new file mode 100644 index 0000000000000..d39ae1177afea --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/channel_layout.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2006 Michael Niedermayer + * Copyright (c) 2008 Peter Ross + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_CHANNEL_LAYOUT_H +#define AVUTIL_CHANNEL_LAYOUT_H + +#include + +/** + * @file + * audio channel layout utility functions + */ + +/** + * @addtogroup lavu_audio + * @{ + */ + +/** + * @defgroup channel_masks Audio channel masks + * + * A channel layout is a 64-bits integer with a bit set for every channel. + * The number of bits set must be equal to the number of channels. + * The value 0 means that the channel layout is not known. + * @note this data structure is not powerful enough to handle channels + * combinations that have the same channel multiple times, such as + * dual-mono. + * + * @{ + */ +#define AV_CH_FRONT_LEFT 0x00000001 +#define AV_CH_FRONT_RIGHT 0x00000002 +#define AV_CH_FRONT_CENTER 0x00000004 +#define AV_CH_LOW_FREQUENCY 0x00000008 +#define AV_CH_BACK_LEFT 0x00000010 +#define AV_CH_BACK_RIGHT 0x00000020 +#define AV_CH_FRONT_LEFT_OF_CENTER 0x00000040 +#define AV_CH_FRONT_RIGHT_OF_CENTER 0x00000080 +#define AV_CH_BACK_CENTER 0x00000100 +#define AV_CH_SIDE_LEFT 0x00000200 +#define AV_CH_SIDE_RIGHT 0x00000400 +#define AV_CH_TOP_CENTER 0x00000800 +#define AV_CH_TOP_FRONT_LEFT 0x00001000 +#define AV_CH_TOP_FRONT_CENTER 0x00002000 +#define AV_CH_TOP_FRONT_RIGHT 0x00004000 +#define AV_CH_TOP_BACK_LEFT 0x00008000 +#define AV_CH_TOP_BACK_CENTER 0x00010000 +#define AV_CH_TOP_BACK_RIGHT 0x00020000 +#define AV_CH_STEREO_LEFT 0x20000000 ///< Stereo downmix. +#define AV_CH_STEREO_RIGHT 0x40000000 ///< See AV_CH_STEREO_LEFT. +#define AV_CH_WIDE_LEFT 0x0000000080000000ULL +#define AV_CH_WIDE_RIGHT 0x0000000100000000ULL +#define AV_CH_SURROUND_DIRECT_LEFT 0x0000000200000000ULL +#define AV_CH_SURROUND_DIRECT_RIGHT 0x0000000400000000ULL +#define AV_CH_LOW_FREQUENCY_2 0x0000000800000000ULL +#define AV_CH_TOP_SIDE_LEFT 0x0000001000000000ULL +#define AV_CH_TOP_SIDE_RIGHT 0x0000002000000000ULL +#define AV_CH_BOTTOM_FRONT_CENTER 0x0000004000000000ULL +#define AV_CH_BOTTOM_FRONT_LEFT 0x0000008000000000ULL +#define AV_CH_BOTTOM_FRONT_RIGHT 0x0000010000000000ULL + +/** Channel mask value used for AVCodecContext.request_channel_layout + to indicate that the user requests the channel order of the decoder output + to be the native codec channel order. */ +#define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL + +/** + * @} + * @defgroup channel_mask_c Audio channel layouts + * @{ + * */ +#define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT) +#define AV_CH_LAYOUT_2POINT1 (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_3POINT1 (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_4POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_4POINT1 (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_2 (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_QUAD (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_5POINT0_BACK (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT1_BACK (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_6POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT0_FRONT (AV_CH_LAYOUT_2_2|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_HEXAGONAL (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_FRONT (AV_CH_LAYOUT_6POINT0_FRONT|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_7POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT0_FRONT (AV_CH_LAYOUT_5POINT0|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1_WIDE_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_HEXADECAGONAL (AV_CH_LAYOUT_OCTAGONAL|AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT) +#define AV_CH_LAYOUT_22POINT2 (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER|AV_CH_BACK_CENTER|AV_CH_LOW_FREQUENCY_2|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_CENTER|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_SIDE_LEFT|AV_CH_TOP_SIDE_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_BOTTOM_FRONT_CENTER|AV_CH_BOTTOM_FRONT_LEFT|AV_CH_BOTTOM_FRONT_RIGHT) + +enum AVMatrixEncoding { + AV_MATRIX_ENCODING_NONE, + AV_MATRIX_ENCODING_DOLBY, + AV_MATRIX_ENCODING_DPLII, + AV_MATRIX_ENCODING_DPLIIX, + AV_MATRIX_ENCODING_DPLIIZ, + AV_MATRIX_ENCODING_DOLBYEX, + AV_MATRIX_ENCODING_DOLBYHEADPHONE, + AV_MATRIX_ENCODING_NB +}; + +/** + * Return a channel layout id that matches name, or 0 if no match is found. + * + * name can be one or several of the following notations, + * separated by '+' or '|': + * - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0, + * 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix); + * - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC, + * SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR); + * - a number of channels, in decimal, followed by 'c', yielding + * the default channel layout for that number of channels (@see + * av_get_default_channel_layout); + * - a channel layout mask, in hexadecimal starting with "0x" (see the + * AV_CH_* macros). + * + * Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7" + */ +uint64_t av_get_channel_layout(const char *name); + +/** + * Return a channel layout and the number of channels based on the specified name. + * + * This function is similar to (@see av_get_channel_layout), but can also parse + * unknown channel layout specifications. + * + * @param[in] name channel layout specification string + * @param[out] channel_layout parsed channel layout (0 if unknown) + * @param[out] nb_channels number of channels + * + * @return 0 on success, AVERROR(EINVAL) if the parsing fails. + */ +int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels); + +/** + * Return a description of a channel layout. + * If nb_channels is <= 0, it is guessed from the channel_layout. + * + * @param buf put here the string containing the channel layout + * @param buf_size size in bytes of the buffer + */ +void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout); + +struct AVBPrint; +/** + * Append a description of a channel layout to a bprint buffer. + */ +void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout); + +/** + * Return the number of channels in the channel layout. + */ +int av_get_channel_layout_nb_channels(uint64_t channel_layout); + +/** + * Return default channel layout for a given number of channels. + */ +int64_t av_get_default_channel_layout(int nb_channels); + +/** + * Get the index of a channel in channel_layout. + * + * @param channel a channel layout describing exactly one channel which must be + * present in channel_layout. + * + * @return index of channel in channel_layout on success, a negative AVERROR + * on error. + */ +int av_get_channel_layout_channel_index(uint64_t channel_layout, + uint64_t channel); + +/** + * Get the channel with the given index in channel_layout. + */ +uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index); + +/** + * Get the name of a given channel. + * + * @return channel name on success, NULL on error. + */ +const char *av_get_channel_name(uint64_t channel); + +/** + * Get the description of a given channel. + * + * @param channel a channel layout with a single channel + * @return channel description on success, NULL on error + */ +const char *av_get_channel_description(uint64_t channel); + +/** + * Get the value and name of a standard channel layout. + * + * @param[in] index index in an internal list, starting at 0 + * @param[out] layout channel layout mask + * @param[out] name name of the layout + * @return 0 if the layout exists, + * <0 if index is beyond the limits + */ +int av_get_standard_channel_layout(unsigned index, uint64_t *layout, + const char **name); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_CHANNEL_LAYOUT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/common.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/common.h new file mode 100644 index 0000000000000..aee353d3993d1 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/common.h @@ -0,0 +1,608 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * common internal and external API header + */ + +#ifndef AVUTIL_COMMON_H +#define AVUTIL_COMMON_H + +#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) && !defined(UINT64_C) +#error missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "macros.h" +#include "version.h" +#include "libavutil/avconfig.h" + +#if AV_HAVE_BIGENDIAN +# define AV_NE(be, le) (be) +#else +# define AV_NE(be, le) (le) +#endif + +//rounded division & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>=0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +/* Fast a/(1<=0 and b>=0 */ +#define AV_CEIL_RSHIFT(a,b) (!av_builtin_constant_p(b) ? -((-(a)) >> (b)) \ + : ((a) + (1<<(b)) - 1) >> (b)) +/* Backwards compat. */ +#define FF_CEIL_RSHIFT AV_CEIL_RSHIFT + +#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b)) +#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b)) + +/** + * Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they + * are not representable as absolute values of their type. This is the same + * as with *abs() + * @see FFNABS() + */ +#define FFABS(a) ((a) >= 0 ? (a) : (-(a))) +#define FFSIGN(a) ((a) > 0 ? 1 : -1) + +/** + * Negative Absolute value. + * this works for all integers of all types. + * As with many macros, this evaluates its argument twice, it thus must not have + * a sideeffect, that is FFNABS(x++) has undefined behavior. + */ +#define FFNABS(a) ((a) <= 0 ? (a) : (-(a))) + +/** + * Unsigned Absolute value. + * This takes the absolute value of a signed int and returns it as a unsigned. + * This also works with INT_MIN which would otherwise not be representable + * As with many macros, this evaluates its argument twice. + */ +#define FFABSU(a) ((a) <= 0 ? -(unsigned)(a) : (unsigned)(a)) +#define FFABS64U(a) ((a) <= 0 ? -(uint64_t)(a) : (uint64_t)(a)) + +/** + * Comparator. + * For two numerical expressions x and y, gives 1 if x > y, -1 if x < y, and 0 + * if x == y. This is useful for instance in a qsort comparator callback. + * Furthermore, compilers are able to optimize this to branchless code, and + * there is no risk of overflow with signed types. + * As with many macros, this evaluates its argument multiple times, it thus + * must not have a side-effect. + */ +#define FFDIFFSIGN(x,y) (((x)>(y)) - ((x)<(y))) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) +#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c) + +#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0) +#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) + +/* misc math functions */ + +#ifdef HAVE_AV_CONFIG_H +# include "config.h" +# include "intmath.h" +#endif + +#ifndef av_ceil_log2 +# define av_ceil_log2 av_ceil_log2_c +#endif +#ifndef av_clip +# define av_clip av_clip_c +#endif +#ifndef av_clip64 +# define av_clip64 av_clip64_c +#endif +#ifndef av_clip_uint8 +# define av_clip_uint8 av_clip_uint8_c +#endif +#ifndef av_clip_int8 +# define av_clip_int8 av_clip_int8_c +#endif +#ifndef av_clip_uint16 +# define av_clip_uint16 av_clip_uint16_c +#endif +#ifndef av_clip_int16 +# define av_clip_int16 av_clip_int16_c +#endif +#ifndef av_clipl_int32 +# define av_clipl_int32 av_clipl_int32_c +#endif +#ifndef av_clip_intp2 +# define av_clip_intp2 av_clip_intp2_c +#endif +#ifndef av_clip_uintp2 +# define av_clip_uintp2 av_clip_uintp2_c +#endif +#ifndef av_mod_uintp2 +# define av_mod_uintp2 av_mod_uintp2_c +#endif +#ifndef av_sat_add32 +# define av_sat_add32 av_sat_add32_c +#endif +#ifndef av_sat_dadd32 +# define av_sat_dadd32 av_sat_dadd32_c +#endif +#ifndef av_sat_sub32 +# define av_sat_sub32 av_sat_sub32_c +#endif +#ifndef av_sat_dsub32 +# define av_sat_dsub32 av_sat_dsub32_c +#endif +#ifndef av_sat_add64 +# define av_sat_add64 av_sat_add64_c +#endif +#ifndef av_sat_sub64 +# define av_sat_sub64 av_sat_sub64_c +#endif +#ifndef av_clipf +# define av_clipf av_clipf_c +#endif +#ifndef av_clipd +# define av_clipd av_clipd_c +#endif +#ifndef av_popcount +# define av_popcount av_popcount_c +#endif +#ifndef av_popcount64 +# define av_popcount64 av_popcount64_c +#endif +#ifndef av_parity +# define av_parity av_parity_c +#endif + +#ifndef av_log2 +av_const int av_log2(unsigned v); +#endif + +#ifndef av_log2_16bit +av_const int av_log2_16bit(unsigned v); +#endif + +/** + * Clip a signed integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int av_clip_c(int a, int amin, int amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed 64bit integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, int64_t amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed integer value into the 0-255 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint8_t av_clip_uint8_c(int a) +{ + if (a&(~0xFF)) return (~a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -128,127 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int8_t av_clip_int8_c(int a) +{ + if ((a+0x80U) & ~0xFF) return (a>>31) ^ 0x7F; + else return a; +} + +/** + * Clip a signed integer value into the 0-65535 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint16_t av_clip_uint16_c(int a) +{ + if (a&(~0xFFFF)) return (~a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -32768,32767 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int16_t av_clip_int16_c(int a) +{ + if ((a+0x8000U) & ~0xFFFF) return (a>>31) ^ 0x7FFF; + else return a; +} + +/** + * Clip a signed 64-bit integer value into the -2147483648,2147483647 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a) +{ + if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (int32_t)((a>>63) ^ 0x7FFFFFFF); + else return (int32_t)a; +} + +/** + * Clip a signed integer into the -(2^p),(2^p-1) range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const int av_clip_intp2_c(int a, int p) +{ + if (((unsigned)a + (1 << p)) & ~((2 << p) - 1)) + return (a >> 31) ^ ((1 << p) - 1); + else + return a; +} + +/** + * Clip a signed integer to an unsigned power of two range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p) +{ + if (a & ~((1<> 31 & ((1<= 0) + return INT64_MAX ^ (b >> 63); + return s; +#endif +} + +/** + * Subtract two signed 64-bit values with saturation. + * + * @param a one value + * @param b another value + * @return difference with signed saturation + */ +static av_always_inline int64_t av_sat_sub64_c(int64_t a, int64_t b) { +#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_sub_overflow) + int64_t tmp; + return !__builtin_sub_overflow(a, b, &tmp) ? tmp : (tmp < 0 ? INT64_MAX : INT64_MIN); +#else + if (b <= 0 && a >= INT64_MAX + b) + return INT64_MAX; + if (b >= 0 && a <= INT64_MIN + b) + return INT64_MIN; + return a - b; +#endif +} + +/** + * Clip a float value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const float av_clipf_c(float a, float amin, float amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a double value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const double av_clipd_c(double a, double amin, double amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** Compute ceil(log2(x)). + * @param x value used to compute ceil(log2(x)) + * @return computed ceiling of log2(x) + */ +static av_always_inline av_const int av_ceil_log2_c(int x) +{ + return av_log2((x - 1U) << 1); +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount_c(uint32_t x) +{ + x -= (x >> 1) & 0x55555555; + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x += x >> 8; + return (x + (x >> 16)) & 0x3F; +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount64_c(uint64_t x) +{ + return av_popcount((uint32_t)x) + av_popcount((uint32_t)(x >> 32)); +} + +static av_always_inline av_const int av_parity_c(uint32_t v) +{ + return av_popcount(v) & 1; +} + +#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24)) +#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24)) + +/** + * Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_BYTE Expression reading one byte from the input. + * Evaluated up to 7 times (4 for the currently + * assigned Unicode range). With a memory buffer + * input, this could be *ptr++, or if you want to make sure + * that *ptr stops at the end of a NULL terminated string then + * *ptr ? *ptr++ : 0 + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + * + * @warning ERROR should not contain a loop control statement which + * could interact with the internal while loop, and should force an + * exit from the macro code (e.g. through a goto or a return) in order + * to prevent undefined results. + */ +#define GET_UTF8(val, GET_BYTE, ERROR)\ + val= (GET_BYTE);\ + {\ + uint32_t top = (val & 128) >> 1;\ + if ((val & 0xc0) == 0x80 || val >= 0xFE)\ + {ERROR}\ + while (val & top) {\ + unsigned int tmp = (GET_BYTE) - 128;\ + if(tmp>>6)\ + {ERROR}\ + val= (val<<6) + tmp;\ + top <<= 5;\ + }\ + val &= (top << 1) - 1;\ + } + +/** + * Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_16BIT Expression returning two bytes of UTF-16 data converted + * to native byte order. Evaluated one or two times. + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + */ +#define GET_UTF16(val, GET_16BIT, ERROR)\ + val = (GET_16BIT);\ + {\ + unsigned int hi = val - 0xD800;\ + if (hi < 0x800) {\ + val = (GET_16BIT) - 0xDC00;\ + if (val > 0x3FFU || hi > 0x3FFU)\ + {ERROR}\ + val += (hi<<10) + 0x10000;\ + }\ + }\ + +/** + * @def PUT_UTF8(val, tmp, PUT_BYTE) + * Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-8. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint8_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_BYTE. + * @param PUT_BYTE writes the converted UTF-8 bytes to any proper destination. + * It could be a function or a statement, and uses tmp as the input byte. + * For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be + * executed up to 4 times for values in the valid UTF-8 range and up to + * 7 times in the general case, depending on the length of the converted + * Unicode character. + */ +#define PUT_UTF8(val, tmp, PUT_BYTE)\ + {\ + int bytes, shift;\ + uint32_t in = val;\ + if (in < 0x80) {\ + tmp = in;\ + PUT_BYTE\ + } else {\ + bytes = (av_log2(in) + 4) / 5;\ + shift = (bytes - 1) * 6;\ + tmp = (256 - (256 >> bytes)) | (in >> shift);\ + PUT_BYTE\ + while (shift >= 6) {\ + shift -= 6;\ + tmp = 0x80 | ((in >> shift) & 0x3f);\ + PUT_BYTE\ + }\ + }\ + } + +/** + * @def PUT_UTF16(val, tmp, PUT_16BIT) + * Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-16. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint16_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_16BIT. + * @param PUT_16BIT writes the converted UTF-16 data to any proper destination + * in desired endianness. It could be a function or a statement, and uses tmp + * as the input byte. For example, PUT_BYTE could be "*output++ = tmp;" + * PUT_BYTE will be executed 1 or 2 times depending on input character. + */ +#define PUT_UTF16(val, tmp, PUT_16BIT)\ + {\ + uint32_t in = val;\ + if (in < 0x10000) {\ + tmp = in;\ + PUT_16BIT\ + } else {\ + tmp = 0xD800 | ((in - 0x10000) >> 10);\ + PUT_16BIT\ + tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\ + PUT_16BIT\ + }\ + }\ + + + +#include "mem.h" + +#ifdef HAVE_AV_CONFIG_H +# include "internal.h" +#endif /* HAVE_AV_CONFIG_H */ + +#endif /* AVUTIL_COMMON_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/cpu.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/cpu.h new file mode 100644 index 0000000000000..83099dd969730 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/cpu.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_CPU_H +#define AVUTIL_CPU_H + +#include + +#include "attributes.h" + +#define AV_CPU_FLAG_FORCE 0x80000000 /* force usage of selected flags (OR) */ + + /* lower 16 bits - CPU features */ +#define AV_CPU_FLAG_MMX 0x0001 ///< standard MMX +#define AV_CPU_FLAG_MMXEXT 0x0002 ///< SSE integer functions or AMD MMX ext +#define AV_CPU_FLAG_MMX2 0x0002 ///< SSE integer functions or AMD MMX ext +#define AV_CPU_FLAG_3DNOW 0x0004 ///< AMD 3DNOW +#define AV_CPU_FLAG_SSE 0x0008 ///< SSE functions +#define AV_CPU_FLAG_SSE2 0x0010 ///< PIV SSE2 functions +#define AV_CPU_FLAG_SSE2SLOW 0x40000000 ///< SSE2 supported, but usually not faster + ///< than regular MMX/SSE (e.g. Core1) +#define AV_CPU_FLAG_3DNOWEXT 0x0020 ///< AMD 3DNowExt +#define AV_CPU_FLAG_SSE3 0x0040 ///< Prescott SSE3 functions +#define AV_CPU_FLAG_SSE3SLOW 0x20000000 ///< SSE3 supported, but usually not faster + ///< than regular MMX/SSE (e.g. Core1) +#define AV_CPU_FLAG_SSSE3 0x0080 ///< Conroe SSSE3 functions +#define AV_CPU_FLAG_SSSE3SLOW 0x4000000 ///< SSSE3 supported, but usually not faster +#define AV_CPU_FLAG_ATOM 0x10000000 ///< Atom processor, some SSSE3 instructions are slower +#define AV_CPU_FLAG_SSE4 0x0100 ///< Penryn SSE4.1 functions +#define AV_CPU_FLAG_SSE42 0x0200 ///< Nehalem SSE4.2 functions +#define AV_CPU_FLAG_AESNI 0x80000 ///< Advanced Encryption Standard functions +#define AV_CPU_FLAG_AVX 0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used +#define AV_CPU_FLAG_AVXSLOW 0x8000000 ///< AVX supported, but slow when using YMM registers (e.g. Bulldozer) +#define AV_CPU_FLAG_XOP 0x0400 ///< Bulldozer XOP functions +#define AV_CPU_FLAG_FMA4 0x0800 ///< Bulldozer FMA4 functions +#define AV_CPU_FLAG_CMOV 0x1000 ///< supports cmov instruction +#define AV_CPU_FLAG_AVX2 0x8000 ///< AVX2 functions: requires OS support even if YMM registers aren't used +#define AV_CPU_FLAG_FMA3 0x10000 ///< Haswell FMA3 functions +#define AV_CPU_FLAG_BMI1 0x20000 ///< Bit Manipulation Instruction Set 1 +#define AV_CPU_FLAG_BMI2 0x40000 ///< Bit Manipulation Instruction Set 2 +#define AV_CPU_FLAG_AVX512 0x100000 ///< AVX-512 functions: requires OS support even if YMM/ZMM registers aren't used + +#define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard +#define AV_CPU_FLAG_VSX 0x0002 ///< ISA 2.06 +#define AV_CPU_FLAG_POWER8 0x0004 ///< ISA 2.07 + +#define AV_CPU_FLAG_ARMV5TE (1 << 0) +#define AV_CPU_FLAG_ARMV6 (1 << 1) +#define AV_CPU_FLAG_ARMV6T2 (1 << 2) +#define AV_CPU_FLAG_VFP (1 << 3) +#define AV_CPU_FLAG_VFPV3 (1 << 4) +#define AV_CPU_FLAG_NEON (1 << 5) +#define AV_CPU_FLAG_ARMV8 (1 << 6) +#define AV_CPU_FLAG_VFP_VM (1 << 7) ///< VFPv2 vector mode, deprecated in ARMv7-A and unavailable in various CPUs implementations +#define AV_CPU_FLAG_SETEND (1 <<16) + +#define AV_CPU_FLAG_MMI (1 << 0) +#define AV_CPU_FLAG_MSA (1 << 1) + +/** + * Return the flags which specify extensions supported by the CPU. + * The returned value is affected by av_force_cpu_flags() if that was used + * before. So av_get_cpu_flags() can easily be used in an application to + * detect the enabled cpu flags. + */ +int av_get_cpu_flags(void); + +/** + * Disables cpu detection and forces the specified flags. + * -1 is a special case that disables forcing of specific flags. + */ +void av_force_cpu_flags(int flags); + +/** + * Set a mask on flags returned by av_get_cpu_flags(). + * This function is mainly useful for testing. + * Please use av_force_cpu_flags() and av_get_cpu_flags() instead which are more flexible + */ +attribute_deprecated void av_set_cpu_flags_mask(int mask); + +/** + * Parse CPU flags from a string. + * + * The returned flags contain the specified flags as well as related unspecified flags. + * + * This function exists only for compatibility with libav. + * Please use av_parse_cpu_caps() when possible. + * @return a combination of AV_CPU_* flags, negative on error. + */ +attribute_deprecated +int av_parse_cpu_flags(const char *s); + +/** + * Parse CPU caps from a string and update the given AV_CPU_* flags based on that. + * + * @return negative on error. + */ +int av_parse_cpu_caps(unsigned *flags, const char *s); + +/** + * @return the number of logical CPU cores present. + */ +int av_cpu_count(void); + +/** + * Get the maximum data alignment that may be required by FFmpeg. + * + * Note that this is affected by the build configuration and the CPU flags mask, + * so e.g. if the CPU supports AVX, but libavutil has been built with + * --disable-avx or the AV_CPU_FLAG_AVX flag has been disabled through + * av_set_cpu_flags_mask(), then this function will behave as if AVX is not + * present. + */ +size_t av_cpu_max_align(void); + +#endif /* AVUTIL_CPU_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/dict.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/dict.h new file mode 100644 index 0000000000000..118f1f00ed204 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/dict.h @@ -0,0 +1,200 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Public dictionary API. + * @deprecated + * AVDictionary is provided for compatibility with libav. It is both in + * implementation as well as API inefficient. It does not scale and is + * extremely slow with large dictionaries. + * It is recommended that new code uses our tree container from tree.c/h + * where applicable, which uses AVL trees to achieve O(log n) performance. + */ + +#ifndef AVUTIL_DICT_H +#define AVUTIL_DICT_H + +#include + +#include "version.h" + +/** + * @addtogroup lavu_dict AVDictionary + * @ingroup lavu_data + * + * @brief Simple key:value store + * + * @{ + * Dictionaries are used for storing key:value pairs. To create + * an AVDictionary, simply pass an address of a NULL pointer to + * av_dict_set(). NULL can be used as an empty dictionary wherever + * a pointer to an AVDictionary is required. + * Use av_dict_get() to retrieve an entry or iterate over all + * entries and finally av_dict_free() to free the dictionary + * and all its contents. + * + @code + AVDictionary *d = NULL; // "create" an empty dictionary + AVDictionaryEntry *t = NULL; + + av_dict_set(&d, "foo", "bar", 0); // add an entry + + char *k = av_strdup("key"); // if your strings are already allocated, + char *v = av_strdup("value"); // you can avoid copying them like this + av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); + + while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) { + <....> // iterate over all entries in d + } + av_dict_free(&d); + @endcode + */ + +#define AV_DICT_MATCH_CASE 1 /**< Only get an entry with exact-case key match. Only relevant in av_dict_get(). */ +#define AV_DICT_IGNORE_SUFFIX 2 /**< Return first entry in a dictionary whose first part corresponds to the search key, + ignoring the suffix of the found key string. Only relevant in av_dict_get(). */ +#define AV_DICT_DONT_STRDUP_KEY 4 /**< Take ownership of a key that's been + allocated with av_malloc() or another memory allocation function. */ +#define AV_DICT_DONT_STRDUP_VAL 8 /**< Take ownership of a value that's been + allocated with av_malloc() or another memory allocation function. */ +#define AV_DICT_DONT_OVERWRITE 16 ///< Don't overwrite existing entries. +#define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no + delimiter is added, the strings are simply concatenated. */ +#define AV_DICT_MULTIKEY 64 /**< Allow to store several equal keys in the dictionary */ + +typedef struct AVDictionaryEntry { + char *key; + char *value; +} AVDictionaryEntry; + +typedef struct AVDictionary AVDictionary; + +/** + * Get a dictionary entry with matching key. + * + * The returned entry key or value must not be changed, or it will + * cause undefined behavior. + * + * To iterate through all the dictionary entries, you can set the matching key + * to the null string "" and set the AV_DICT_IGNORE_SUFFIX flag. + * + * @param prev Set to the previous matching element to find the next. + * If set to NULL the first matching element is returned. + * @param key matching key + * @param flags a collection of AV_DICT_* flags controlling how the entry is retrieved + * @return found entry or NULL in case no matching entry was found in the dictionary + */ +AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key, + const AVDictionaryEntry *prev, int flags); + +/** + * Get number of entries in dictionary. + * + * @param m dictionary + * @return number of entries in dictionary + */ +int av_dict_count(const AVDictionary *m); + +/** + * Set the given entry in *pm, overwriting an existing entry. + * + * Note: If AV_DICT_DONT_STRDUP_KEY or AV_DICT_DONT_STRDUP_VAL is set, + * these arguments will be freed on error. + * + * Warning: Adding a new entry to a dictionary invalidates all existing entries + * previously returned with av_dict_get. + * + * @param pm pointer to a pointer to a dictionary struct. If *pm is NULL + * a dictionary struct is allocated and put in *pm. + * @param key entry key to add to *pm (will either be av_strduped or added as a new key depending on flags) + * @param value entry value to add to *pm (will be av_strduped or added as a new key depending on flags). + * Passing a NULL value will cause an existing entry to be deleted. + * @return >= 0 on success otherwise an error code <0 + */ +int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags); + +/** + * Convenience wrapper for av_dict_set that converts the value to a string + * and stores it. + * + * Note: If AV_DICT_DONT_STRDUP_KEY is set, key will be freed on error. + */ +int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags); + +/** + * Parse the key/value pairs list and add the parsed entries to a dictionary. + * + * In case of failure, all the successfully set entries are stored in + * *pm. You may need to manually free the created dictionary. + * + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other + * @param flags flags to use when adding to dictionary. + * AV_DICT_DONT_STRDUP_KEY and AV_DICT_DONT_STRDUP_VAL + * are ignored since the key/value tokens will always + * be duplicated. + * @return 0 on success, negative AVERROR code on failure + */ +int av_dict_parse_string(AVDictionary **pm, const char *str, + const char *key_val_sep, const char *pairs_sep, + int flags); + +/** + * Copy entries from one AVDictionary struct into another. + * @param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL, + * this function will allocate a struct for you and put it in *dst + * @param src pointer to source AVDictionary struct + * @param flags flags to use when setting entries in *dst + * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag + * @return 0 on success, negative AVERROR code on failure. If dst was allocated + * by this function, callers should free the associated memory. + */ +int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags); + +/** + * Free all the memory allocated for an AVDictionary struct + * and all keys and values. + */ +void av_dict_free(AVDictionary **m); + +/** + * Get dictionary entries as a string. + * + * Create a string containing dictionary's entries. + * Such string may be passed back to av_dict_parse_string(). + * @note String is escaped with backslashes ('\'). + * + * @param[in] m dictionary + * @param[out] buffer Pointer to buffer that will be allocated with string containg entries. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep character used to separate key from value + * @param[in] pairs_sep character used to separate two pairs from each other + * @return >= 0 on success, negative on error + * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same. + */ +int av_dict_get_string(const AVDictionary *m, char **buffer, + const char key_val_sep, const char pairs_sep); + +/** + * @} + */ + +#endif /* AVUTIL_DICT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/error.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/error.h new file mode 100644 index 0000000000000..71df4da353b9c --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/error.h @@ -0,0 +1,126 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * error code definitions + */ + +#ifndef AVUTIL_ERROR_H +#define AVUTIL_ERROR_H + +#include +#include + +/** + * @addtogroup lavu_error + * + * @{ + */ + + +/* error handling */ +#if EDOM > 0 +#define AVERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions. +#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value. +#else +/* Some platforms have E* and errno already negated. */ +#define AVERROR(e) (e) +#define AVUNERROR(e) (e) +#endif + +#define FFERRTAG(a, b, c, d) (-(int)MKTAG(a, b, c, d)) + +#define AVERROR_BSF_NOT_FOUND FFERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found +#define AVERROR_BUG FFERRTAG( 'B','U','G','!') ///< Internal bug, also see AVERROR_BUG2 +#define AVERROR_BUFFER_TOO_SMALL FFERRTAG( 'B','U','F','S') ///< Buffer too small +#define AVERROR_DECODER_NOT_FOUND FFERRTAG(0xF8,'D','E','C') ///< Decoder not found +#define AVERROR_DEMUXER_NOT_FOUND FFERRTAG(0xF8,'D','E','M') ///< Demuxer not found +#define AVERROR_ENCODER_NOT_FOUND FFERRTAG(0xF8,'E','N','C') ///< Encoder not found +#define AVERROR_EOF FFERRTAG( 'E','O','F',' ') ///< End of file +#define AVERROR_EXIT FFERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted +#define AVERROR_EXTERNAL FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library +#define AVERROR_FILTER_NOT_FOUND FFERRTAG(0xF8,'F','I','L') ///< Filter not found +#define AVERROR_INVALIDDATA FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input +#define AVERROR_MUXER_NOT_FOUND FFERRTAG(0xF8,'M','U','X') ///< Muxer not found +#define AVERROR_OPTION_NOT_FOUND FFERRTAG(0xF8,'O','P','T') ///< Option not found +#define AVERROR_PATCHWELCOME FFERRTAG( 'P','A','W','E') ///< Not yet implemented in FFmpeg, patches welcome +#define AVERROR_PROTOCOL_NOT_FOUND FFERRTAG(0xF8,'P','R','O') ///< Protocol not found + +#define AVERROR_STREAM_NOT_FOUND FFERRTAG(0xF8,'S','T','R') ///< Stream not found +/** + * This is semantically identical to AVERROR_BUG + * it has been introduced in Libav after our AVERROR_BUG and with a modified value. + */ +#define AVERROR_BUG2 FFERRTAG( 'B','U','G',' ') +#define AVERROR_UNKNOWN FFERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library +#define AVERROR_EXPERIMENTAL (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it. +#define AVERROR_INPUT_CHANGED (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED) +#define AVERROR_OUTPUT_CHANGED (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED) +/* HTTP & RTSP errors */ +#define AVERROR_HTTP_BAD_REQUEST FFERRTAG(0xF8,'4','0','0') +#define AVERROR_HTTP_UNAUTHORIZED FFERRTAG(0xF8,'4','0','1') +#define AVERROR_HTTP_FORBIDDEN FFERRTAG(0xF8,'4','0','3') +#define AVERROR_HTTP_NOT_FOUND FFERRTAG(0xF8,'4','0','4') +#define AVERROR_HTTP_OTHER_4XX FFERRTAG(0xF8,'4','X','X') +#define AVERROR_HTTP_SERVER_ERROR FFERRTAG(0xF8,'5','X','X') + +#define AV_ERROR_MAX_STRING_SIZE 64 + +/** + * Put a description of the AVERROR code errnum in errbuf. + * In case of failure the global variable errno is set to indicate the + * error. Even in case of failure av_strerror() will print a generic + * error message indicating the errnum provided to errbuf. + * + * @param errnum error code to describe + * @param errbuf buffer to which description is written + * @param errbuf_size the size in bytes of errbuf + * @return 0 on success, a negative value if a description for errnum + * cannot be found + */ +int av_strerror(int errnum, char *errbuf, size_t errbuf_size); + +/** + * Fill the provided buffer with a string containing an error string + * corresponding to the AVERROR code errnum. + * + * @param errbuf a buffer + * @param errbuf_size size in bytes of errbuf + * @param errnum error code to describe + * @return the buffer in input, filled with the error description + * @see av_strerror() + */ +static inline char *av_make_error_string(char *errbuf, size_t errbuf_size, int errnum) +{ + av_strerror(errnum, errbuf, errbuf_size); + return errbuf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_err2str(errnum) \ + av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum) + +/** + * @} + */ + +#endif /* AVUTIL_ERROR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/frame.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/frame.h new file mode 100644 index 0000000000000..7d1f8e293579c --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/frame.h @@ -0,0 +1,997 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_frame + * reference-counted frame API + */ + +#ifndef AVUTIL_FRAME_H +#define AVUTIL_FRAME_H + +#include +#include + +#include "avutil.h" +#include "buffer.h" +#include "dict.h" +#include "rational.h" +#include "samplefmt.h" +#include "pixfmt.h" +#include "version.h" + + +/** + * @defgroup lavu_frame AVFrame + * @ingroup lavu_data + * + * @{ + * AVFrame is an abstraction for reference-counted raw multimedia data. + */ + +enum AVFrameSideDataType { + /** + * The data is the AVPanScan struct defined in libavcodec. + */ + AV_FRAME_DATA_PANSCAN, + /** + * ATSC A53 Part 4 Closed Captions. + * A53 CC bitstream is stored as uint8_t in AVFrameSideData.data. + * The number of bytes of CC data is AVFrameSideData.size. + */ + AV_FRAME_DATA_A53_CC, + /** + * Stereoscopic 3d metadata. + * The data is the AVStereo3D struct defined in libavutil/stereo3d.h. + */ + AV_FRAME_DATA_STEREO3D, + /** + * The data is the AVMatrixEncoding enum defined in libavutil/channel_layout.h. + */ + AV_FRAME_DATA_MATRIXENCODING, + /** + * Metadata relevant to a downmix procedure. + * The data is the AVDownmixInfo struct defined in libavutil/downmix_info.h. + */ + AV_FRAME_DATA_DOWNMIX_INFO, + /** + * ReplayGain information in the form of the AVReplayGain struct. + */ + AV_FRAME_DATA_REPLAYGAIN, + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the frame for correct + * presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_FRAME_DATA_DISPLAYMATRIX, + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_FRAME_DATA_AFD, + /** + * Motion vectors exported by some codecs (on demand through the export_mvs + * flag set in the libavcodec AVCodecContext flags2 option). + * The data is the AVMotionVector struct defined in + * libavutil/motion_vector.h. + */ + AV_FRAME_DATA_MOTION_VECTORS, + /** + * Recommmends skipping the specified number of samples. This is exported + * only if the "skip_manual" AVOption is set in libavcodec. + * This has the same format as AV_PKT_DATA_SKIP_SAMPLES. + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_FRAME_DATA_SKIP_SAMPLES, + /** + * This side data must be associated with an audio frame and corresponds to + * enum AVAudioServiceType defined in avcodec.h. + */ + AV_FRAME_DATA_AUDIO_SERVICE_TYPE, + /** + * Mastering display metadata associated with a video frame. The payload is + * an AVMasteringDisplayMetadata type and contains information about the + * mastering display color volume. + */ + AV_FRAME_DATA_MASTERING_DISPLAY_METADATA, + /** + * The GOP timecode in 25 bit timecode format. Data format is 64-bit integer. + * This is set on the first frame of a GOP that has a temporal reference of 0. + */ + AV_FRAME_DATA_GOP_TIMECODE, + + /** + * The data represents the AVSphericalMapping structure defined in + * libavutil/spherical.h. + */ + AV_FRAME_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This payload contains data in + * the form of the AVContentLightMetadata struct. + */ + AV_FRAME_DATA_CONTENT_LIGHT_LEVEL, + + /** + * The data contains an ICC profile as an opaque octet buffer following the + * format described by ISO 15076-1 with an optional name defined in the + * metadata key entry "name". + */ + AV_FRAME_DATA_ICC_PROFILE, + +#if FF_API_FRAME_QP + /** + * Implementation-specific description of the format of AV_FRAME_QP_TABLE_DATA. + * The contents of this side data are undocumented and internal; use + * av_frame_set_qp_table() and av_frame_get_qp_table() to access this in a + * meaningful way instead. + */ + AV_FRAME_DATA_QP_TABLE_PROPERTIES, + + /** + * Raw QP table data. Its format is described by + * AV_FRAME_DATA_QP_TABLE_PROPERTIES. Use av_frame_set_qp_table() and + * av_frame_get_qp_table() to access this instead. + */ + AV_FRAME_DATA_QP_TABLE_DATA, +#endif + + /** + * Timecode which conforms to SMPTE ST 12-1. The data is an array of 4 uint32_t + * where the first uint32_t describes how many (1-3) of the other timecodes are used. + * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.h. + */ + AV_FRAME_DATA_S12M_TIMECODE, + + /** + * HDR dynamic metadata associated with a video frame. The payload is + * an AVDynamicHDRPlus type and contains information for color + * volume transform - application 4 of SMPTE 2094-40:2016 standard. + */ + AV_FRAME_DATA_DYNAMIC_HDR_PLUS, + + /** + * Regions Of Interest, the data is an array of AVRegionOfInterest type, the number of + * array element is implied by AVFrameSideData.size / AVRegionOfInterest.self_size. + */ + AV_FRAME_DATA_REGIONS_OF_INTEREST, + + /** + * Encoding parameters for a video frame, as described by AVVideoEncParams. + */ + AV_FRAME_DATA_VIDEO_ENC_PARAMS, + + /** + * User data unregistered metadata associated with a video frame. + * This is the H.26[45] UDU SEI message, and shouldn't be used for any other purpose + * The data is stored as uint8_t in AVFrameSideData.data which is 16 bytes of + * uuid_iso_iec_11578 followed by AVFrameSideData.size - 16 bytes of user_data_payload_byte. + */ + AV_FRAME_DATA_SEI_UNREGISTERED, + + /** + * Film grain parameters for a frame, described by AVFilmGrainParams. + * Must be present for every frame which should have film grain applied. + */ + AV_FRAME_DATA_FILM_GRAIN_PARAMS, +}; + +enum AVActiveFormatDescription { + AV_AFD_SAME = 8, + AV_AFD_4_3 = 9, + AV_AFD_16_9 = 10, + AV_AFD_14_9 = 11, + AV_AFD_4_3_SP_14_9 = 13, + AV_AFD_16_9_SP_14_9 = 14, + AV_AFD_SP_4_3 = 15, +}; + + +/** + * Structure to hold side data for an AVFrame. + * + * sizeof(AVFrameSideData) is not a part of the public ABI, so new fields may be added + * to the end with a minor bump. + */ +typedef struct AVFrameSideData { + enum AVFrameSideDataType type; + uint8_t *data; +#if FF_API_BUFFER_SIZE_T + int size; +#else + size_t size; +#endif + AVDictionary *metadata; + AVBufferRef *buf; +} AVFrameSideData; + +/** + * Structure describing a single Region Of Interest. + * + * When multiple regions are defined in a single side-data block, they + * should be ordered from most to least important - some encoders are only + * capable of supporting a limited number of distinct regions, so will have + * to truncate the list. + * + * When overlapping regions are defined, the first region containing a given + * area of the frame applies. + */ +typedef struct AVRegionOfInterest { + /** + * Must be set to the size of this data structure (that is, + * sizeof(AVRegionOfInterest)). + */ + uint32_t self_size; + /** + * Distance in pixels from the top edge of the frame to the top and + * bottom edges and from the left edge of the frame to the left and + * right edges of the rectangle defining this region of interest. + * + * The constraints on a region are encoder dependent, so the region + * actually affected may be slightly larger for alignment or other + * reasons. + */ + int top; + int bottom; + int left; + int right; + /** + * Quantisation offset. + * + * Must be in the range -1 to +1. A value of zero indicates no quality + * change. A negative value asks for better quality (less quantisation), + * while a positive value asks for worse quality (greater quantisation). + * + * The range is calibrated so that the extreme values indicate the + * largest possible offset - if the rest of the frame is encoded with the + * worst possible quality, an offset of -1 indicates that this region + * should be encoded with the best possible quality anyway. Intermediate + * values are then interpolated in some codec-dependent way. + * + * For example, in 10-bit H.264 the quantisation parameter varies between + * -12 and 51. A typical qoffset value of -1/10 therefore indicates that + * this region should be encoded with a QP around one-tenth of the full + * range better than the rest of the frame. So, if most of the frame + * were to be encoded with a QP of around 30, this region would get a QP + * of around 24 (an offset of approximately -1/10 * (51 - -12) = -6.3). + * An extreme value of -1 would indicate that this region should be + * encoded with the best possible quality regardless of the treatment of + * the rest of the frame - that is, should be encoded at a QP of -12. + */ + AVRational qoffset; +} AVRegionOfInterest; + +/** + * This structure describes decoded (raw) audio or video data. + * + * AVFrame must be allocated using av_frame_alloc(). Note that this only + * allocates the AVFrame itself, the buffers for the data must be managed + * through other means (see below). + * AVFrame must be freed with av_frame_free(). + * + * AVFrame is typically allocated once and then reused multiple times to hold + * different data (e.g. a single AVFrame to hold frames received from a + * decoder). In such a case, av_frame_unref() will free any references held by + * the frame and reset it to its original clean state before it + * is reused again. + * + * The data described by an AVFrame is usually reference counted through the + * AVBuffer API. The underlying buffer references are stored in AVFrame.buf / + * AVFrame.extended_buf. An AVFrame is considered to be reference counted if at + * least one reference is set, i.e. if AVFrame.buf[0] != NULL. In such a case, + * every single data plane must be contained in one of the buffers in + * AVFrame.buf or AVFrame.extended_buf. + * There may be a single buffer for all the data, or one separate buffer for + * each plane, or anything in between. + * + * sizeof(AVFrame) is not a part of the public ABI, so new fields may be added + * to the end with a minor bump. + * + * Fields can be accessed through AVOptions, the name string used, matches the + * C structure field name for fields accessible through AVOptions. The AVClass + * for AVFrame can be obtained from avcodec_get_frame_class() + */ +typedef struct AVFrame { +#define AV_NUM_DATA_POINTERS 8 + /** + * pointer to the picture/channel planes. + * This might be different from the first allocated byte + * + * Some decoders access areas outside 0,0 - width,height, please + * see avcodec_align_dimensions2(). Some filters and swscale can read + * up to 16 bytes beyond the planes, if these filters are to be used, + * then 16 extra bytes must be allocated. + * + * NOTE: Except for hwaccel formats, pointers not needed by the format + * MUST be set to NULL. + */ + uint8_t *data[AV_NUM_DATA_POINTERS]; + + /** + * For video, size in bytes of each picture line. + * For audio, size in bytes of each plane. + * + * For audio, only linesize[0] may be set. For planar audio, each channel + * plane must be the same size. + * + * For video the linesizes should be multiples of the CPUs alignment + * preference, this is 16 or 32 for modern desktop CPUs. + * Some code requires such alignment other code can be slower without + * correct alignment, for yet other it makes no difference. + * + * @note The linesize may be larger than the size of usable data -- there + * may be extra padding present for performance reasons. + */ + int linesize[AV_NUM_DATA_POINTERS]; + + /** + * pointers to the data planes/channels. + * + * For video, this should simply point to data[]. + * + * For planar audio, each channel has a separate data pointer, and + * linesize[0] contains the size of each channel buffer. + * For packed audio, there is just one data pointer, and linesize[0] + * contains the total size of the buffer for all channels. + * + * Note: Both data and extended_data should always be set in a valid frame, + * but for planar audio with more channels that can fit in data, + * extended_data must be used in order to access all channels. + */ + uint8_t **extended_data; + + /** + * @name Video dimensions + * Video frames only. The coded dimensions (in pixels) of the video frame, + * i.e. the size of the rectangle that contains some well-defined values. + * + * @note The part of the frame intended for display/presentation is further + * restricted by the @ref cropping "Cropping rectangle". + * @{ + */ + int width, height; + /** + * @} + */ + + /** + * number of audio samples (per channel) described by this frame + */ + int nb_samples; + + /** + * format of the frame, -1 if unknown or unset + * Values correspond to enum AVPixelFormat for video frames, + * enum AVSampleFormat for audio) + */ + int format; + + /** + * 1 -> keyframe, 0-> not + */ + int key_frame; + + /** + * Picture type of the frame. + */ + enum AVPictureType pict_type; + + /** + * Sample aspect ratio for the video frame, 0/1 if unknown/unspecified. + */ + AVRational sample_aspect_ratio; + + /** + * Presentation timestamp in time_base units (time when frame should be shown to user). + */ + int64_t pts; + +#if FF_API_PKT_PTS + /** + * PTS copied from the AVPacket that was decoded to produce this frame. + * @deprecated use the pts field instead + */ + attribute_deprecated + int64_t pkt_pts; +#endif + + /** + * DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used) + * This is also the Presentation time of this AVFrame calculated from + * only AVPacket.dts values without pts values. + */ + int64_t pkt_dts; + + /** + * picture number in bitstream order + */ + int coded_picture_number; + /** + * picture number in display order + */ + int display_picture_number; + + /** + * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) + */ + int quality; + + /** + * for some private data of the user + */ + void *opaque; + +#if FF_API_ERROR_FRAME + /** + * @deprecated unused + */ + attribute_deprecated + uint64_t error[AV_NUM_DATA_POINTERS]; +#endif + + /** + * When decoding, this signals how much the picture must be delayed. + * extra_delay = repeat_pict / (2*fps) + */ + int repeat_pict; + + /** + * The content of the picture is interlaced. + */ + int interlaced_frame; + + /** + * If the content is interlaced, is top field displayed first. + */ + int top_field_first; + + /** + * Tell user application that palette has changed from previous frame. + */ + int palette_has_changed; + + /** + * reordered opaque 64 bits (generally an integer or a double precision float + * PTS but can be anything). + * The user sets AVCodecContext.reordered_opaque to represent the input at + * that time, + * the decoder reorders values as needed and sets AVFrame.reordered_opaque + * to exactly one of the values provided by the user through AVCodecContext.reordered_opaque + */ + int64_t reordered_opaque; + + /** + * Sample rate of the audio data. + */ + int sample_rate; + + /** + * Channel layout of the audio data. + */ + uint64_t channel_layout; + + /** + * AVBuffer references backing the data for this frame. If all elements of + * this array are NULL, then this frame is not reference counted. This array + * must be filled contiguously -- if buf[i] is non-NULL then buf[j] must + * also be non-NULL for all j < i. + * + * There may be at most one AVBuffer per data plane, so for video this array + * always contains all the references. For planar audio with more than + * AV_NUM_DATA_POINTERS channels, there may be more buffers than can fit in + * this array. Then the extra AVBufferRef pointers are stored in the + * extended_buf array. + */ + AVBufferRef *buf[AV_NUM_DATA_POINTERS]; + + /** + * For planar audio which requires more than AV_NUM_DATA_POINTERS + * AVBufferRef pointers, this array will hold all the references which + * cannot fit into AVFrame.buf. + * + * Note that this is different from AVFrame.extended_data, which always + * contains all the pointers. This array only contains the extra pointers, + * which cannot fit into AVFrame.buf. + * + * This array is always allocated using av_malloc() by whoever constructs + * the frame. It is freed in av_frame_unref(). + */ + AVBufferRef **extended_buf; + /** + * Number of elements in extended_buf. + */ + int nb_extended_buf; + + AVFrameSideData **side_data; + int nb_side_data; + +/** + * @defgroup lavu_frame_flags AV_FRAME_FLAGS + * @ingroup lavu_frame + * Flags describing additional frame properties. + * + * @{ + */ + +/** + * The frame data may be corrupted, e.g. due to decoding errors. + */ +#define AV_FRAME_FLAG_CORRUPT (1 << 0) +/** + * A flag to mark the frames which need to be decoded, but shouldn't be output. + */ +#define AV_FRAME_FLAG_DISCARD (1 << 2) +/** + * @} + */ + + /** + * Frame flags, a combination of @ref lavu_frame_flags + */ + int flags; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorRange color_range; + + enum AVColorPrimaries color_primaries; + + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + enum AVChromaLocation chroma_location; + + /** + * frame timestamp estimated using various heuristics, in stream time base + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int64_t best_effort_timestamp; + + /** + * reordered pos from the last AVPacket that has been input into the decoder + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_pos; + + /** + * duration of the corresponding packet, expressed in + * AVStream->time_base units, 0 if unknown. + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_duration; + + /** + * metadata. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVDictionary *metadata; + + /** + * decode error flags of the frame, set to a combination of + * FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there + * were errors during the decoding. + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int decode_error_flags; +#define FF_DECODE_ERROR_INVALID_BITSTREAM 1 +#define FF_DECODE_ERROR_MISSING_REFERENCE 2 +#define FF_DECODE_ERROR_CONCEALMENT_ACTIVE 4 +#define FF_DECODE_ERROR_DECODE_SLICES 8 + + /** + * number of audio channels, only used for audio. + * - encoding: unused + * - decoding: Read by user. + */ + int channels; + + /** + * size of the corresponding packet containing the compressed + * frame. + * It is set to a negative value if unknown. + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int pkt_size; + +#if FF_API_FRAME_QP + /** + * QP table + */ + attribute_deprecated + int8_t *qscale_table; + /** + * QP store stride + */ + attribute_deprecated + int qstride; + + attribute_deprecated + int qscale_type; + + attribute_deprecated + AVBufferRef *qp_table_buf; +#endif + /** + * For hwaccel-format frames, this should be a reference to the + * AVHWFramesContext describing the frame. + */ + AVBufferRef *hw_frames_ctx; + + /** + * AVBufferRef for free use by the API user. FFmpeg will never check the + * contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when + * the frame is unreferenced. av_frame_copy_props() calls create a new + * reference with av_buffer_ref() for the target frame's opaque_ref field. + * + * This is unrelated to the opaque field, although it serves a similar + * purpose. + */ + AVBufferRef *opaque_ref; + + /** + * @anchor cropping + * @name Cropping + * Video frames only. The number of pixels to discard from the the + * top/bottom/left/right border of the frame to obtain the sub-rectangle of + * the frame intended for presentation. + * @{ + */ + size_t crop_top; + size_t crop_bottom; + size_t crop_left; + size_t crop_right; + /** + * @} + */ + + /** + * AVBufferRef for internal use by a single libav* library. + * Must not be used to transfer data between libraries. + * Has to be NULL when ownership of the frame leaves the respective library. + * + * Code outside the FFmpeg libs should never check or change the contents of the buffer ref. + * + * FFmpeg calls av_buffer_unref() on it when the frame is unreferenced. + * av_frame_copy_props() calls create a new reference with av_buffer_ref() + * for the target frame's private_ref field. + */ + AVBufferRef *private_ref; +} AVFrame; + +#if FF_API_FRAME_GET_SET +/** + * Accessors for some AVFrame fields. These used to be provided for ABI + * compatibility, and do not need to be used anymore. + */ +attribute_deprecated +int64_t av_frame_get_best_effort_timestamp(const AVFrame *frame); +attribute_deprecated +void av_frame_set_best_effort_timestamp(AVFrame *frame, int64_t val); +attribute_deprecated +int64_t av_frame_get_pkt_duration (const AVFrame *frame); +attribute_deprecated +void av_frame_set_pkt_duration (AVFrame *frame, int64_t val); +attribute_deprecated +int64_t av_frame_get_pkt_pos (const AVFrame *frame); +attribute_deprecated +void av_frame_set_pkt_pos (AVFrame *frame, int64_t val); +attribute_deprecated +int64_t av_frame_get_channel_layout (const AVFrame *frame); +attribute_deprecated +void av_frame_set_channel_layout (AVFrame *frame, int64_t val); +attribute_deprecated +int av_frame_get_channels (const AVFrame *frame); +attribute_deprecated +void av_frame_set_channels (AVFrame *frame, int val); +attribute_deprecated +int av_frame_get_sample_rate (const AVFrame *frame); +attribute_deprecated +void av_frame_set_sample_rate (AVFrame *frame, int val); +attribute_deprecated +AVDictionary *av_frame_get_metadata (const AVFrame *frame); +attribute_deprecated +void av_frame_set_metadata (AVFrame *frame, AVDictionary *val); +attribute_deprecated +int av_frame_get_decode_error_flags (const AVFrame *frame); +attribute_deprecated +void av_frame_set_decode_error_flags (AVFrame *frame, int val); +attribute_deprecated +int av_frame_get_pkt_size(const AVFrame *frame); +attribute_deprecated +void av_frame_set_pkt_size(AVFrame *frame, int val); +#if FF_API_FRAME_QP +attribute_deprecated +int8_t *av_frame_get_qp_table(AVFrame *f, int *stride, int *type); +attribute_deprecated +int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int type); +#endif +attribute_deprecated +enum AVColorSpace av_frame_get_colorspace(const AVFrame *frame); +attribute_deprecated +void av_frame_set_colorspace(AVFrame *frame, enum AVColorSpace val); +attribute_deprecated +enum AVColorRange av_frame_get_color_range(const AVFrame *frame); +attribute_deprecated +void av_frame_set_color_range(AVFrame *frame, enum AVColorRange val); +#endif + +/** + * Get the name of a colorspace. + * @return a static string identifying the colorspace; can be NULL. + */ +const char *av_get_colorspace_name(enum AVColorSpace val); + +/** + * Allocate an AVFrame and set its fields to default values. The resulting + * struct must be freed using av_frame_free(). + * + * @return An AVFrame filled with default values or NULL on failure. + * + * @note this only allocates the AVFrame itself, not the data buffers. Those + * must be allocated through other means, e.g. with av_frame_get_buffer() or + * manually. + */ +AVFrame *av_frame_alloc(void); + +/** + * Free the frame and any dynamically allocated objects in it, + * e.g. extended_data. If the frame is reference counted, it will be + * unreferenced first. + * + * @param frame frame to be freed. The pointer will be set to NULL. + */ +void av_frame_free(AVFrame **frame); + +/** + * Set up a new reference to the data described by the source frame. + * + * Copy frame properties from src to dst and create a new reference for each + * AVBufferRef from src. + * + * If src is not reference counted, new buffers are allocated and the data is + * copied. + * + * @warning: dst MUST have been either unreferenced with av_frame_unref(dst), + * or newly allocated with av_frame_alloc() before calling this + * function, or undefined behavior will occur. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_frame_ref(AVFrame *dst, const AVFrame *src); + +/** + * Create a new frame that references the same data as src. + * + * This is a shortcut for av_frame_alloc()+av_frame_ref(). + * + * @return newly created AVFrame on success, NULL on error. + */ +AVFrame *av_frame_clone(const AVFrame *src); + +/** + * Unreference all the buffers referenced by frame and reset the frame fields. + */ +void av_frame_unref(AVFrame *frame); + +/** + * Move everything contained in src to dst and reset src. + * + * @warning: dst is not unreferenced, but directly overwritten without reading + * or deallocating its contents. Call av_frame_unref(dst) manually + * before calling this function to ensure that no memory is leaked. + */ +void av_frame_move_ref(AVFrame *dst, AVFrame *src); + +/** + * Allocate new buffer(s) for audio or video data. + * + * The following fields must be set on frame before calling this function: + * - format (pixel format for video, sample format for audio) + * - width and height for video + * - nb_samples and channel_layout for audio + * + * This function will fill AVFrame.data and AVFrame.buf arrays and, if + * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf. + * For planar formats, one buffer will be allocated for each plane. + * + * @warning: if frame already has been allocated, calling this function will + * leak memory. In addition, undefined behavior can occur in certain + * cases. + * + * @param frame frame in which to store the new buffers. + * @param align Required buffer size alignment. If equal to 0, alignment will be + * chosen automatically for the current CPU. It is highly + * recommended to pass 0 here unless you know what you are doing. + * + * @return 0 on success, a negative AVERROR on error. + */ +int av_frame_get_buffer(AVFrame *frame, int align); + +/** + * Check if the frame data is writable. + * + * @return A positive value if the frame data is writable (which is true if and + * only if each of the underlying buffers has only one reference, namely the one + * stored in this frame). Return 0 otherwise. + * + * If 1 is returned the answer is valid until av_buffer_ref() is called on any + * of the underlying AVBufferRefs (e.g. through av_frame_ref() or directly). + * + * @see av_frame_make_writable(), av_buffer_is_writable() + */ +int av_frame_is_writable(AVFrame *frame); + +/** + * Ensure that the frame data is writable, avoiding data copy if possible. + * + * Do nothing if the frame is writable, allocate new buffers and copy the data + * if it is not. + * + * @return 0 on success, a negative AVERROR on error. + * + * @see av_frame_is_writable(), av_buffer_is_writable(), + * av_buffer_make_writable() + */ +int av_frame_make_writable(AVFrame *frame); + +/** + * Copy the frame data from src to dst. + * + * This function does not allocate anything, dst must be already initialized and + * allocated with the same parameters as src. + * + * This function only copies the frame data (i.e. the contents of the data / + * extended data arrays), not any other properties. + * + * @return >= 0 on success, a negative AVERROR on error. + */ +int av_frame_copy(AVFrame *dst, const AVFrame *src); + +/** + * Copy only "metadata" fields from src to dst. + * + * Metadata for the purpose of this function are those fields that do not affect + * the data layout in the buffers. E.g. pts, sample rate (for audio) or sample + * aspect ratio (for video), but not width/height or channel layout. + * Side data is also copied. + */ +int av_frame_copy_props(AVFrame *dst, const AVFrame *src); + +/** + * Get the buffer reference a given data plane is stored in. + * + * @param plane index of the data plane of interest in frame->extended_data. + * + * @return the buffer reference that contains the plane or NULL if the input + * frame is not valid. + */ +AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane); + +/** + * Add a new side data to a frame. + * + * @param frame a frame to which the side data should be added + * @param type type of the added side data + * @param size size of the side data + * + * @return newly added side data on success, NULL on error + */ +AVFrameSideData *av_frame_new_side_data(AVFrame *frame, + enum AVFrameSideDataType type, +#if FF_API_BUFFER_SIZE_T + int size); +#else + size_t size); +#endif + +/** + * Add a new side data to a frame from an existing AVBufferRef + * + * @param frame a frame to which the side data should be added + * @param type the type of the added side data + * @param buf an AVBufferRef to add as side data. The ownership of + * the reference is transferred to the frame. + * + * @return newly added side data on success, NULL on error. On failure + * the frame is unchanged and the AVBufferRef remains owned by + * the caller. + */ +AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame, + enum AVFrameSideDataType type, + AVBufferRef *buf); + +/** + * @return a pointer to the side data of a given type on success, NULL if there + * is no side data with such type in this frame. + */ +AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, + enum AVFrameSideDataType type); + +/** + * Remove and free all side data instances of the given type. + */ +void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type); + + +/** + * Flags for frame cropping. + */ +enum { + /** + * Apply the maximum possible cropping, even if it requires setting the + * AVFrame.data[] entries to unaligned pointers. Passing unaligned data + * to FFmpeg API is generally not allowed, and causes undefined behavior + * (such as crashes). You can pass unaligned data only to FFmpeg APIs that + * are explicitly documented to accept it. Use this flag only if you + * absolutely know what you are doing. + */ + AV_FRAME_CROP_UNALIGNED = 1 << 0, +}; + +/** + * Crop the given video AVFrame according to its crop_left/crop_top/crop_right/ + * crop_bottom fields. If cropping is successful, the function will adjust the + * data pointers and the width/height fields, and set the crop fields to 0. + * + * In all cases, the cropping boundaries will be rounded to the inherent + * alignment of the pixel format. In some cases, such as for opaque hwaccel + * formats, the left/top cropping is ignored. The crop fields are set to 0 even + * if the cropping was rounded or ignored. + * + * @param frame the frame which should be cropped + * @param flags Some combination of AV_FRAME_CROP_* flags, or 0. + * + * @return >= 0 on success, a negative AVERROR on error. If the cropping fields + * were invalid, AVERROR(ERANGE) is returned, and nothing is changed. + */ +int av_frame_apply_cropping(AVFrame *frame, int flags); + +/** + * @return a string identifying the side data type + */ +const char *av_frame_side_data_name(enum AVFrameSideDataType type); + +/** + * @} + */ + +#endif /* AVUTIL_FRAME_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/hwcontext.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/hwcontext.h new file mode 100644 index 0000000000000..04d19d89c2b85 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/hwcontext.h @@ -0,0 +1,605 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_H +#define AVUTIL_HWCONTEXT_H + +#include "buffer.h" +#include "frame.h" +#include "log.h" +#include "pixfmt.h" + +enum AVHWDeviceType { + AV_HWDEVICE_TYPE_NONE, + AV_HWDEVICE_TYPE_VDPAU, + AV_HWDEVICE_TYPE_CUDA, + AV_HWDEVICE_TYPE_VAAPI, + AV_HWDEVICE_TYPE_DXVA2, + AV_HWDEVICE_TYPE_QSV, + AV_HWDEVICE_TYPE_VIDEOTOOLBOX, + AV_HWDEVICE_TYPE_D3D11VA, + AV_HWDEVICE_TYPE_DRM, + AV_HWDEVICE_TYPE_OPENCL, + AV_HWDEVICE_TYPE_MEDIACODEC, + AV_HWDEVICE_TYPE_VULKAN, +}; + +typedef struct AVHWDeviceInternal AVHWDeviceInternal; + +/** + * This struct aggregates all the (hardware/vendor-specific) "high-level" state, + * i.e. state that is not tied to a concrete processing configuration. + * E.g., in an API that supports hardware-accelerated encoding and decoding, + * this struct will (if possible) wrap the state that is common to both encoding + * and decoding and from which specific instances of encoders or decoders can be + * derived. + * + * This struct is reference-counted with the AVBuffer mechanism. The + * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field + * points to the actual AVHWDeviceContext. Further objects derived from + * AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with + * specific properties) will hold an internal reference to it. After all the + * references are released, the AVHWDeviceContext itself will be freed, + * optionally invoking a user-specified callback for uninitializing the hardware + * state. + */ +typedef struct AVHWDeviceContext { + /** + * A class for logging. Set by av_hwdevice_ctx_alloc(). + */ + const AVClass *av_class; + + /** + * Private data used internally by libavutil. Must not be accessed in any + * way by the caller. + */ + AVHWDeviceInternal *internal; + + /** + * This field identifies the underlying API used for hardware access. + * + * This field is set when this struct is allocated and never changed + * afterwards. + */ + enum AVHWDeviceType type; + + /** + * The format-specific data, allocated and freed by libavutil along with + * this context. + * + * Should be cast by the user to the format-specific context defined in the + * corresponding header (hwcontext_*.h) and filled as described in the + * documentation before calling av_hwdevice_ctx_init(). + * + * After calling av_hwdevice_ctx_init() this struct should not be modified + * by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwdevice_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + * + * @note when other objects (e.g an AVHWFramesContext) are derived from this + * struct, this callback will be invoked after all such child objects + * are fully uninitialized and their respective destructors invoked. + */ + void (*free)(struct AVHWDeviceContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; +} AVHWDeviceContext; + +typedef struct AVHWFramesInternal AVHWFramesInternal; + +/** + * This struct describes a set or pool of "hardware" frames (i.e. those with + * data not located in normal system memory). All the frames in the pool are + * assumed to be allocated in the same way and interchangeable. + * + * This struct is reference-counted with the AVBuffer mechanism and tied to a + * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor + * yields a reference, whose data field points to the actual AVHWFramesContext + * struct. + */ +typedef struct AVHWFramesContext { + /** + * A class for logging. + */ + const AVClass *av_class; + + /** + * Private data used internally by libavutil. Must not be accessed in any + * way by the caller. + */ + AVHWFramesInternal *internal; + + /** + * A reference to the parent AVHWDeviceContext. This reference is owned and + * managed by the enclosing AVHWFramesContext, but the caller may derive + * additional references from it. + */ + AVBufferRef *device_ref; + + /** + * The parent AVHWDeviceContext. This is simply a pointer to + * device_ref->data provided for convenience. + * + * Set by libavutil in av_hwframe_ctx_init(). + */ + AVHWDeviceContext *device_ctx; + + /** + * The format-specific data, allocated and freed automatically along with + * this context. + * + * Should be cast by the user to the format-specific context defined in the + * corresponding header (hwframe_*.h) and filled as described in the + * documentation before calling av_hwframe_ctx_init(). + * + * After any frames using this context are created, the contents of this + * struct should not be modified by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + */ + void (*free)(struct AVHWFramesContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; + + /** + * A pool from which the frames are allocated by av_hwframe_get_buffer(). + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * The buffers returned by calling av_buffer_pool_get() on this pool must + * have the properties described in the documentation in the corresponding hw + * type's header (hwcontext_*.h). The pool will be freed strictly before + * this struct's free() callback is invoked. + * + * This field may be NULL, then libavutil will attempt to allocate a pool + * internally. Note that certain device types enforce pools allocated at + * fixed size (frame count), which cannot be extended dynamically. In such a + * case, initial_pool_size must be set appropriately. + */ + AVBufferPool *pool; + + /** + * Initial size of the frame pool. If a device type does not support + * dynamically resizing the pool, then this is also the maximum pool size. + * + * May be set by the caller before calling av_hwframe_ctx_init(). Must be + * set if pool is NULL and the device type does not support dynamic pools. + */ + int initial_pool_size; + + /** + * The pixel format identifying the underlying HW surface type. + * + * Must be a hwaccel format, i.e. the corresponding descriptor must have the + * AV_PIX_FMT_FLAG_HWACCEL flag set. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + enum AVPixelFormat format; + + /** + * The pixel format identifying the actual data layout of the hardware + * frames. + * + * Must be set by the caller before calling av_hwframe_ctx_init(). + * + * @note when the underlying API does not provide the exact data layout, but + * only the colorspace/bit depth, this field should be set to the fully + * planar version of that format (e.g. for 8-bit 420 YUV it should be + * AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else). + */ + enum AVPixelFormat sw_format; + + /** + * The allocated dimensions of the frames in this pool. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + int width, height; +} AVHWFramesContext; + +/** + * Look up an AVHWDeviceType by name. + * + * @param name String name of the device type (case-insensitive). + * @return The type from enum AVHWDeviceType, or AV_HWDEVICE_TYPE_NONE if + * not found. + */ +enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name); + +/** Get the string name of an AVHWDeviceType. + * + * @param type Type from enum AVHWDeviceType. + * @return Pointer to a static string containing the name, or NULL if the type + * is not valid. + */ +const char *av_hwdevice_get_type_name(enum AVHWDeviceType type); + +/** + * Iterate over supported device types. + * + * @param type AV_HWDEVICE_TYPE_NONE initially, then the previous type + * returned by this function in subsequent iterations. + * @return The next usable device type from enum AVHWDeviceType, or + * AV_HWDEVICE_TYPE_NONE if there are no more. + */ +enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev); + +/** + * Allocate an AVHWDeviceContext for a given hardware type. + * + * @param type the type of the hardware device to allocate. + * @return a reference to the newly created AVHWDeviceContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type); + +/** + * Finalize the device context before use. This function must be called after + * the context is filled with all the required information and before it is + * used in any way. + * + * @param ref a reference to the AVHWDeviceContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwdevice_ctx_init(AVBufferRef *ref); + +/** + * Open a device of the specified type and create an AVHWDeviceContext for it. + * + * This is a convenience function intended to cover the simple cases. Callers + * who need to fine-tune device creation/management should open the device + * manually and then wrap it in an AVHWDeviceContext using + * av_hwdevice_ctx_alloc()/av_hwdevice_ctx_init(). + * + * The returned context is already initialized and ready for use, the caller + * should not call av_hwdevice_ctx_init() on it. The user_opaque/free fields of + * the created AVHWDeviceContext are set by this function and should not be + * touched by the caller. + * + * @param device_ctx On success, a reference to the newly-created device context + * will be written here. The reference is owned by the caller + * and must be released with av_buffer_unref() when no longer + * needed. On failure, NULL will be written to this pointer. + * @param type The type of the device to create. + * @param device A type-specific string identifying the device to open. + * @param opts A dictionary of additional (type-specific) options to use in + * opening the device. The dictionary remains owned by the caller. + * @param flags currently unused + * + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type, + const char *device, AVDictionary *opts, int flags); + +/** + * Create a new device of the specified type from an existing device. + * + * If the source device is a device of the target type or was originally + * derived from such a device (possibly through one or more intermediate + * devices of other types), then this will return a reference to the + * existing device of the same type as is requested. + * + * Otherwise, it will attempt to derive a new device from the given source + * device. If direct derivation to the new type is not implemented, it will + * attempt the same derivation from each ancestor of the source device in + * turn looking for an implemented derivation method. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, int flags); + +/** + * Create a new device of the specified type from an existing device. + * + * This function performs the same action as av_hwdevice_ctx_create_derived, + * however, it is able to set options for the new device to be derived. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param options Options for the new device to create, same format as in + * av_hwdevice_ctx_create. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, + AVDictionary *options, int flags); + +/** + * Allocate an AVHWFramesContext tied to a given device context. + * + * @param device_ctx a reference to a AVHWDeviceContext. This function will make + * a new reference for internal use, the one passed to the + * function remains owned by the caller. + * @return a reference to the newly created AVHWFramesContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx); + +/** + * Finalize the context before use. This function must be called after the + * context is filled with all the required information and before it is attached + * to any frames. + * + * @param ref a reference to the AVHWFramesContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_ctx_init(AVBufferRef *ref); + +/** + * Allocate a new frame attached to the given AVHWFramesContext. + * + * @param hwframe_ctx a reference to an AVHWFramesContext + * @param frame an empty (freshly allocated or unreffed) frame to be filled with + * newly allocated buffers. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags); + +/** + * Copy data to or from a hw surface. At least one of dst/src must have an + * AVHWFramesContext attached. + * + * If src has an AVHWFramesContext attached, then the format of dst (if set) + * must use one of the formats returned by av_hwframe_transfer_get_formats(src, + * AV_HWFRAME_TRANSFER_DIRECTION_FROM). + * If dst has an AVHWFramesContext attached, then the format of src must use one + * of the formats returned by av_hwframe_transfer_get_formats(dst, + * AV_HWFRAME_TRANSFER_DIRECTION_TO) + * + * dst may be "clean" (i.e. with data/buf pointers unset), in which case the + * data buffers will be allocated by this function using av_frame_get_buffer(). + * If dst->format is set, then this format will be used, otherwise (when + * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen. + * + * The two frames must have matching allocated dimensions (i.e. equal to + * AVHWFramesContext.width/height), since not all device types support + * transferring a sub-rectangle of the whole surface. The display dimensions + * (i.e. AVFrame.width/height) may be smaller than the allocated dimensions, but + * also have to be equal for both frames. When the display dimensions are + * smaller than the allocated dimensions, the content of the padding in the + * destination frame is unspecified. + * + * @param dst the destination frame. dst is not touched on failure. + * @param src the source frame. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR error code on failure. + */ +int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags); + +enum AVHWFrameTransferDirection { + /** + * Transfer the data from the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_FROM, + + /** + * Transfer the data to the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_TO, +}; + +/** + * Get a list of possible source or target formats usable in + * av_hwframe_transfer_data(). + * + * @param hwframe_ctx the frame context to obtain the information for + * @param dir the direction of the transfer + * @param formats the pointer to the output format list will be written here. + * The list is terminated with AV_PIX_FMT_NONE and must be freed + * by the caller when no longer needed using av_free(). + * If this function returns successfully, the format list will + * have at least one item (not counting the terminator). + * On failure, the contents of this pointer are unspecified. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats, int flags); + + +/** + * This struct describes the constraints on hardware frames attached to + * a given device with a hardware-specific configuration. This is returned + * by av_hwdevice_get_hwframe_constraints() and must be freed by + * av_hwframe_constraints_free() after use. + */ +typedef struct AVHWFramesConstraints { + /** + * A list of possible values for format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. This member will always be filled. + */ + enum AVPixelFormat *valid_hw_formats; + + /** + * A list of possible values for sw_format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. Can be NULL if this information is + * not known. + */ + enum AVPixelFormat *valid_sw_formats; + + /** + * The minimum size of frames in this hw_frames_ctx. + * (Zero if not known.) + */ + int min_width; + int min_height; + + /** + * The maximum size of frames in this hw_frames_ctx. + * (INT_MAX if not known / no limit.) + */ + int max_width; + int max_height; +} AVHWFramesConstraints; + +/** + * Allocate a HW-specific configuration structure for a given HW device. + * After use, the user must free all members as required by the specific + * hardware structure being used, then free the structure itself with + * av_free(). + * + * @param device_ctx a reference to the associated AVHWDeviceContext. + * @return The newly created HW-specific configuration structure on + * success or NULL on failure. + */ +void *av_hwdevice_hwconfig_alloc(AVBufferRef *device_ctx); + +/** + * Get the constraints on HW frames given a device and the HW-specific + * configuration to be used with that device. If no HW-specific + * configuration is provided, returns the maximum possible capabilities + * of the device. + * + * @param ref a reference to the associated AVHWDeviceContext. + * @param hwconfig a filled HW-specific configuration structure, or NULL + * to return the maximum possible capabilities of the device. + * @return AVHWFramesConstraints structure describing the constraints + * on the device, or NULL if not available. + */ +AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, + const void *hwconfig); + +/** + * Free an AVHWFrameConstraints structure. + * + * @param constraints The (filled or unfilled) AVHWFrameConstraints structure. + */ +void av_hwframe_constraints_free(AVHWFramesConstraints **constraints); + + +/** + * Flags to apply to frame mappings. + */ +enum { + /** + * The mapping must be readable. + */ + AV_HWFRAME_MAP_READ = 1 << 0, + /** + * The mapping must be writeable. + */ + AV_HWFRAME_MAP_WRITE = 1 << 1, + /** + * The mapped frame will be overwritten completely in subsequent + * operations, so the current frame data need not be loaded. Any values + * which are not overwritten are unspecified. + */ + AV_HWFRAME_MAP_OVERWRITE = 1 << 2, + /** + * The mapping must be direct. That is, there must not be any copying in + * the map or unmap steps. Note that performance of direct mappings may + * be much lower than normal memory. + */ + AV_HWFRAME_MAP_DIRECT = 1 << 3, +}; + +/** + * Map a hardware frame. + * + * This has a number of different possible effects, depending on the format + * and origin of the src and dst frames. On input, src should be a usable + * frame with valid buffers and dst should be blank (typically as just created + * by av_frame_alloc()). src should have an associated hwframe context, and + * dst may optionally have a format and associated hwframe context. + * + * If src was created by mapping a frame from the hwframe context of dst, + * then this function undoes the mapping - dst is replaced by a reference to + * the frame that src was originally mapped from. + * + * If both src and dst have an associated hwframe context, then this function + * attempts to map the src frame from its hardware context to that of dst and + * then fill dst with appropriate data to be usable there. This will only be + * possible if the hwframe contexts and associated devices are compatible - + * given compatible devices, av_hwframe_ctx_create_derived() can be used to + * create a hwframe context for dst in which mapping should be possible. + * + * If src has a hwframe context but dst does not, then the src frame is + * mapped to normal memory and should thereafter be usable as a normal frame. + * If the format is set on dst, then the mapping will attempt to create dst + * with that format and fail if it is not possible. If format is unset (is + * AV_PIX_FMT_NONE) then dst will be mapped with whatever the most appropriate + * format to use is (probably the sw_format of the src hwframe context). + * + * A return value of AVERROR(ENOSYS) indicates that the mapping is not + * possible with the given arguments and hwframe setup, while other return + * values indicate that it failed somehow. + * + * @param dst Destination frame, to contain the mapping. + * @param src Source frame, to be mapped. + * @param flags Some combination of AV_HWFRAME_MAP_* flags. + * @return Zero on success, negative AVERROR code on failure. + */ +int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags); + + +/** + * Create and initialise an AVHWFramesContext as a mapping of another existing + * AVHWFramesContext on a different device. + * + * av_hwframe_ctx_init() should not be called after this. + * + * @param derived_frame_ctx On success, a reference to the newly created + * AVHWFramesContext. + * @param derived_device_ctx A reference to the device to create the new + * AVHWFramesContext on. + * @param source_frame_ctx A reference to an existing AVHWFramesContext + * which will be mapped to the derived context. + * @param flags Some combination of AV_HWFRAME_MAP_* flags, defining the + * mapping parameters to apply to frames which are allocated + * in the derived device. + * @return Zero on success, negative AVERROR code on failure. + */ +int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, + enum AVPixelFormat format, + AVBufferRef *derived_device_ctx, + AVBufferRef *source_frame_ctx, + int flags); + +#endif /* AVUTIL_HWCONTEXT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/imgutils.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/imgutils.h new file mode 100644 index 0000000000000..5eccbf0bf7871 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/imgutils.h @@ -0,0 +1,291 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_IMGUTILS_H +#define AVUTIL_IMGUTILS_H + +/** + * @file + * misc image utilities + * + * @addtogroup lavu_picture + * @{ + */ + +#include "avutil.h" +#include "pixdesc.h" +#include "rational.h" + +/** + * Compute the max pixel step for each plane of an image with a + * format described by pixdesc. + * + * The pixel step is the distance in bytes between the first byte of + * the group of bytes which describe a pixel component and the first + * byte of the successive group in the same plane for the same + * component. + * + * @param max_pixsteps an array which is filled with the max pixel step + * for each plane. Since a plane may contain different pixel + * components, the computed max_pixsteps[plane] is relative to the + * component in the plane with the max pixel step. + * @param max_pixstep_comps an array which is filled with the component + * for each plane which has the max pixel step. May be NULL. + */ +void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], + const AVPixFmtDescriptor *pixdesc); + +/** + * Compute the size of an image line with format pix_fmt and width + * width for the plane plane. + * + * @return the computed size in bytes + */ +int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane); + +/** + * Fill plane linesizes for an image with pixel format pix_fmt and + * width width. + * + * @param linesizes array to be filled with the linesize for each plane + * @return >= 0 in case of success, a negative error code otherwise + */ +int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width); + +/** + * Fill plane sizes for an image with pixel format pix_fmt and height height. + * + * @param size the array to be filled with the size of each image plane + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return >= 0 in case of success, a negative error code otherwise + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_fill_linesizes(). + */ +int av_image_fill_plane_sizes(size_t size[4], enum AVPixelFormat pix_fmt, + int height, const ptrdiff_t linesizes[4]); + +/** + * Fill plane data pointers for an image with pixel format pix_fmt and + * height height. + * + * @param data pointers array to be filled with the pointer for each image plane + * @param ptr the pointer to a buffer which will contain the image + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, + uint8_t *ptr, const int linesizes[4]); + +/** + * Allocate an image with size w and h and pixel format pix_fmt, and + * fill pointers and linesizes accordingly. + * The allocated image buffer has to be freed by using + * av_freep(&pointers[0]). + * + * @param align the value to use for buffer size alignment + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_alloc(uint8_t *pointers[4], int linesizes[4], + int w, int h, enum AVPixelFormat pix_fmt, int align); + +/** + * Copy image plane from src to dst. + * That is, copy "height" number of lines of "bytewidth" bytes each. + * The first byte of each successive line is separated by *_linesize + * bytes. + * + * bytewidth must be contained by both absolute values of dst_linesize + * and src_linesize, otherwise the function behavior is undefined. + * + * @param dst_linesize linesize for the image plane in dst + * @param src_linesize linesize for the image plane in src + */ +void av_image_copy_plane(uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, + int bytewidth, int height); + +/** + * Copy image in src_data to dst_data. + * + * @param dst_linesizes linesizes for the image in dst_data + * @param src_linesizes linesizes for the image in src_data + */ +void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], + const uint8_t *src_data[4], const int src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Copy image data located in uncacheable (e.g. GPU mapped) memory. Where + * available, this function will use special functionality for reading from such + * memory, which may result in greatly improved performance compared to plain + * av_image_copy(). + * + * The data pointers and the linesizes must be aligned to the maximum required + * by the CPU architecture. + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_copy(). + * @note On x86, the linesizes currently need to be aligned to the cacheline + * size (i.e. 64) to get improved performance. + */ +void av_image_copy_uc_from(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4], + const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Setup the data pointers and linesizes based on the specified image + * parameters and the provided array. + * + * The fields of the given image are filled in by using the src + * address which points to the image data buffer. Depending on the + * specified pixel format, one or multiple image data pointers and + * line sizes will be set. If a planar format is specified, several + * pointers will be set pointing to the different picture planes and + * the line sizes of the different planes will be stored in the + * lines_sizes array. Call with src == NULL to get the required + * size for the src buffer. + * + * To allocate the buffer and fill in the dst_data and dst_linesize in + * one call, use av_image_alloc(). + * + * @param dst_data data pointers to be filled in + * @param dst_linesize linesizes for the image in dst_data to be filled in + * @param src buffer which will contain or contains the actual image data, can be NULL + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the value used in src for linesize alignment + * @return the size in bytes required for src, a negative error code + * in case of failure + */ +int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Return the size in bytes of the amount of data required to store an + * image with the given parameters. + * + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the assumed linesize alignment + * @return the buffer size in bytes, a negative error code in case of failure + */ +int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Copy image data from an image into a buffer. + * + * av_image_get_buffer_size() can be used to compute the required size + * for the buffer to fill. + * + * @param dst a buffer into which picture data will be copied + * @param dst_size the size in bytes of dst + * @param src_data pointers containing the source image data + * @param src_linesize linesizes for the image in src_data + * @param pix_fmt the pixel format of the source image + * @param width the width of the source image in pixels + * @param height the height of the source image in pixels + * @param align the assumed linesize alignment for dst + * @return the number of bytes written to dst, or a negative value + * (error code) on error + */ +int av_image_copy_to_buffer(uint8_t *dst, int dst_size, + const uint8_t * const src_data[4], const int src_linesize[4], + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of the image can be addressed with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of a plane of an image with the specified pix_fmt can be addressed + * with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param max_pixels the maximum number of pixels the user wants to accept + * @param pix_fmt the pixel format, can be AV_PIX_FMT_NONE if unknown. + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx); + +/** + * Check if the given sample aspect ratio of an image is valid. + * + * It is considered invalid if the denominator is 0 or if applying the ratio + * to the image size would make the smaller dimension less than 1. If the + * sar numerator is 0, it is considered unknown and will return as valid. + * + * @param w width of the image + * @param h height of the image + * @param sar sample aspect ratio of the image + * @return 0 if valid, a negative AVERROR code otherwise + */ +int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar); + +/** + * Overwrite the image data with black. This is suitable for filling a + * sub-rectangle of an image, meaning the padding between the right most pixel + * and the left most pixel on the next line will not be overwritten. For some + * formats, the image size might be rounded up due to inherent alignment. + * + * If the pixel format has alpha, the alpha is cleared to opaque. + * + * This can return an error if the pixel format is not supported. Normally, all + * non-hwaccel pixel formats should be supported. + * + * Passing NULL for dst_data is allowed. Then the function returns whether the + * operation would have succeeded. (It can return an error if the pix_fmt is + * not supported.) + * + * @param dst_data data pointers to destination image + * @param dst_linesize linesizes for the destination image + * @param pix_fmt the pixel format of the image + * @param range the color range of the image (important for colorspaces such as YUV) + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @return 0 if the image data was cleared, a negative AVERROR code otherwise + */ +int av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4], + enum AVPixelFormat pix_fmt, enum AVColorRange range, + int width, int height); + +/** + * @} + */ + + +#endif /* AVUTIL_IMGUTILS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/intfloat.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/intfloat.h new file mode 100644 index 0000000000000..fe3d7ec4a5b6f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/intfloat.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_INTFLOAT_H +#define AVUTIL_INTFLOAT_H + +#include +#include "attributes.h" + +union av_intfloat32 { + uint32_t i; + float f; +}; + +union av_intfloat64 { + uint64_t i; + double f; +}; + +/** + * Reinterpret a 32-bit integer as a float. + */ +static av_always_inline float av_int2float(uint32_t i) +{ + union av_intfloat32 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a float as a 32-bit integer. + */ +static av_always_inline uint32_t av_float2int(float f) +{ + union av_intfloat32 v; + v.f = f; + return v.i; +} + +/** + * Reinterpret a 64-bit integer as a double. + */ +static av_always_inline double av_int2double(uint64_t i) +{ + union av_intfloat64 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a double as a 64-bit integer. + */ +static av_always_inline uint64_t av_double2int(double f) +{ + union av_intfloat64 v; + v.f = f; + return v.i; +} + +#endif /* AVUTIL_INTFLOAT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/log.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/log.h new file mode 100644 index 0000000000000..8edd6bbf2b8bd --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/log.h @@ -0,0 +1,401 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_LOG_H +#define AVUTIL_LOG_H + +#include +#include "avutil.h" +#include "attributes.h" +#include "version.h" + +typedef enum { + AV_CLASS_CATEGORY_NA = 0, + AV_CLASS_CATEGORY_INPUT, + AV_CLASS_CATEGORY_OUTPUT, + AV_CLASS_CATEGORY_MUXER, + AV_CLASS_CATEGORY_DEMUXER, + AV_CLASS_CATEGORY_ENCODER, + AV_CLASS_CATEGORY_DECODER, + AV_CLASS_CATEGORY_FILTER, + AV_CLASS_CATEGORY_BITSTREAM_FILTER, + AV_CLASS_CATEGORY_SWSCALER, + AV_CLASS_CATEGORY_SWRESAMPLER, + AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT = 40, + AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT, + AV_CLASS_CATEGORY_NB ///< not part of ABI/API +}AVClassCategory; + +#define AV_IS_INPUT_DEVICE(category) \ + (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_INPUT)) + +#define AV_IS_OUTPUT_DEVICE(category) \ + (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_OUTPUT)) + +struct AVOptionRanges; + +/** + * Describe the class of an AVClass context structure. That is an + * arbitrary struct of which the first field is a pointer to an + * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.). + */ +typedef struct AVClass { + /** + * The name of the class; usually it is the same name as the + * context structure type to which the AVClass is associated. + */ + const char* class_name; + + /** + * A pointer to a function which returns the name of a context + * instance ctx associated with the class. + */ + const char* (*item_name)(void* ctx); + + /** + * a pointer to the first option specified in the class if any or NULL + * + * @see av_set_default_options() + */ + const struct AVOption *option; + + /** + * LIBAVUTIL_VERSION with which this structure was created. + * This is used to allow fields to be added without requiring major + * version bumps everywhere. + */ + + int version; + + /** + * Offset in the structure where log_level_offset is stored. + * 0 means there is no such variable + */ + int log_level_offset_offset; + + /** + * Offset in the structure where a pointer to the parent context for + * logging is stored. For example a decoder could pass its AVCodecContext + * to eval as such a parent context, which an av_log() implementation + * could then leverage to display the parent context. + * The offset can be NULL. + */ + int parent_log_context_offset; + + /** + * Return next AVOptions-enabled child or NULL + */ + void* (*child_next)(void *obj, void *prev); + +#if FF_API_CHILD_CLASS_NEXT + /** + * Return an AVClass corresponding to the next potential + * AVOptions-enabled child. + * + * The difference between child_next and this is that + * child_next iterates over _already existing_ objects, while + * child_class_next iterates over _all possible_ children. + */ + attribute_deprecated + const struct AVClass* (*child_class_next)(const struct AVClass *prev); +#endif + + /** + * Category used for visualization (like color) + * This is only set if the category is equal for all objects using this class. + * available since version (51 << 16 | 56 << 8 | 100) + */ + AVClassCategory category; + + /** + * Callback to return the category. + * available since version (51 << 16 | 59 << 8 | 100) + */ + AVClassCategory (*get_category)(void* ctx); + + /** + * Callback to return the supported/allowed ranges. + * available since version (52.12) + */ + int (*query_ranges)(struct AVOptionRanges **, void *obj, const char *key, int flags); + + /** + * Iterate over the AVClasses corresponding to potential AVOptions-enabled + * children. + * + * @param iter pointer to opaque iteration state. The caller must initialize + * *iter to NULL before the first call. + * @return AVClass for the next AVOptions-enabled child or NULL if there are + * no more such children. + * + * @note The difference between child_next and this is that child_next + * iterates over _already existing_ objects, while child_class_iterate + * iterates over _all possible_ children. + */ + const struct AVClass* (*child_class_iterate)(void **iter); +} AVClass; + +/** + * @addtogroup lavu_log + * + * @{ + * + * @defgroup lavu_log_constants Logging Constants + * + * @{ + */ + +/** + * Print no output. + */ +#define AV_LOG_QUIET -8 + +/** + * Something went really wrong and we will crash now. + */ +#define AV_LOG_PANIC 0 + +/** + * Something went wrong and recovery is not possible. + * For example, no header was found for a format which depends + * on headers or an illegal combination of parameters is used. + */ +#define AV_LOG_FATAL 8 + +/** + * Something went wrong and cannot losslessly be recovered. + * However, not all future data is affected. + */ +#define AV_LOG_ERROR 16 + +/** + * Something somehow does not look correct. This may or may not + * lead to problems. An example would be the use of '-vstrict -2'. + */ +#define AV_LOG_WARNING 24 + +/** + * Standard information. + */ +#define AV_LOG_INFO 32 + +/** + * Detailed information. + */ +#define AV_LOG_VERBOSE 40 + +/** + * Stuff which is only useful for libav* developers. + */ +#define AV_LOG_DEBUG 48 + +/** + * Extremely verbose debugging, useful for libav* development. + */ +#define AV_LOG_TRACE 56 + +#define AV_LOG_MAX_OFFSET (AV_LOG_TRACE - AV_LOG_QUIET) + +/** + * @} + */ + +/** + * Sets additional colors for extended debugging sessions. + * @code + av_log(ctx, AV_LOG_DEBUG|AV_LOG_C(134), "Message in purple\n"); + @endcode + * Requires 256color terminal support. Uses outside debugging is not + * recommended. + */ +#define AV_LOG_C(x) ((x) << 8) + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log_set_callback + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct or NULL if general log. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + */ +void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Send the specified message to the log once with the initial_level and then with + * the subsequent_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct or NULL if general log. + * @param initial_level importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant" for the first occurance. + * @param subsequent_level importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant" after the first occurance. + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param state a variable to keep trak of if a message has already been printed + * this must be initialized to 0 before the first use. The same state + * must not be accessed by 2 Threads simultaneously. + */ +void av_log_once(void* avcl, int initial_level, int subsequent_level, int *state, const char *fmt, ...) av_printf_format(5, 6); + + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log_set_callback + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param vl The arguments referenced by the format string. + */ +void av_vlog(void *avcl, int level, const char *fmt, va_list vl); + +/** + * Get the current log level + * + * @see lavu_log_constants + * + * @return Current log level + */ +int av_log_get_level(void); + +/** + * Set the log level + * + * @see lavu_log_constants + * + * @param level Logging level + */ +void av_log_set_level(int level); + +/** + * Set the logging callback + * + * @note The callback must be thread safe, even if the application does not use + * threads itself as some codecs are multithreaded. + * + * @see av_log_default_callback + * + * @param callback A logging function with a compatible signature. + */ +void av_log_set_callback(void (*callback)(void*, int, const char*, va_list)); + +/** + * Default logging callback + * + * It prints the message to stderr, optionally colorizing it. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param vl The arguments referenced by the format string. + */ +void av_log_default_callback(void *avcl, int level, const char *fmt, + va_list vl); + +/** + * Return the context name + * + * @param ctx The AVClass context + * + * @return The AVClass class_name + */ +const char* av_default_item_name(void* ctx); +AVClassCategory av_default_get_category(void *ptr); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formatted line + * @param line_size size of the buffer + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + */ +void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formatted line; + * may be NULL if line_size is 0 + * @param line_size size of the buffer; at most line_size-1 characters will + * be written to the buffer, plus one null terminator + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + * @return Returns a negative value if an error occurred, otherwise returns + * the number of characters that would have been written for a + * sufficiently large buffer, not including the terminating null + * character. If the return value is not less than line_size, it means + * that the log message was truncated to fit the buffer. + */ +int av_log_format_line2(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * Skip repeated messages, this requires the user app to use av_log() instead of + * (f)printf as the 2 would otherwise interfere and lead to + * "Last message repeated x times" messages below (f)printf messages with some + * bad luck. + * Also to receive the last, "last repeated" line if any, the user app must + * call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end + */ +#define AV_LOG_SKIP_REPEATED 1 + +/** + * Include the log severity in messages originating from codecs. + * + * Results in messages such as: + * [rawvideo @ 0xDEADBEEF] [error] encode did not produce valid pts + */ +#define AV_LOG_PRINT_LEVEL 2 + +void av_log_set_flags(int arg); +int av_log_get_flags(void); + +/** + * @} + */ + +#endif /* AVUTIL_LOG_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/macros.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/macros.h new file mode 100644 index 0000000000000..2007ee5619871 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/macros.h @@ -0,0 +1,50 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu + * Utility Preprocessor macros + */ + +#ifndef AVUTIL_MACROS_H +#define AVUTIL_MACROS_H + +/** + * @addtogroup preproc_misc Preprocessor String Macros + * + * String manipulation macros + * + * @{ + */ + +#define AV_STRINGIFY(s) AV_TOSTRING(s) +#define AV_TOSTRING(s) #s + +#define AV_GLUE(a, b) a ## b +#define AV_JOIN(a, b) AV_GLUE(a, b) + +/** + * @} + */ + +#define AV_PRAGMA(s) _Pragma(#s) + +#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1)) + +#endif /* AVUTIL_MACROS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/mathematics.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/mathematics.h new file mode 100644 index 0000000000000..54901800ba6ad --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/mathematics.h @@ -0,0 +1,242 @@ +/* + * copyright (c) 2005-2012 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @addtogroup lavu_math + * Mathematical utilities for working with timestamp and time base. + */ + +#ifndef AVUTIL_MATHEMATICS_H +#define AVUTIL_MATHEMATICS_H + +#include +#include +#include "attributes.h" +#include "rational.h" +#include "intfloat.h" + +#ifndef M_E +#define M_E 2.7182818284590452354 /* e */ +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#endif +#ifndef M_LOG2_10 +#define M_LOG2_10 3.32192809488736234787 /* log_2 10 */ +#endif +#ifndef M_PHI +#define M_PHI 1.61803398874989484820 /* phi / golden ratio */ +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#endif +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#endif +#ifndef NAN +#define NAN av_int2float(0x7fc00000) +#endif +#ifndef INFINITY +#define INFINITY av_int2float(0x7f800000) +#endif + +/** + * @addtogroup lavu_math + * + * @{ + */ + +/** + * Rounding methods. + */ +enum AVRounding { + AV_ROUND_ZERO = 0, ///< Round toward zero. + AV_ROUND_INF = 1, ///< Round away from zero. + AV_ROUND_DOWN = 2, ///< Round toward -infinity. + AV_ROUND_UP = 3, ///< Round toward +infinity. + AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero. + /** + * Flag telling rescaling functions to pass `INT64_MIN`/`MAX` through + * unchanged, avoiding special cases for #AV_NOPTS_VALUE. + * + * Unlike other values of the enumeration AVRounding, this value is a + * bitmask that must be used in conjunction with another value of the + * enumeration through a bitwise OR, in order to set behavior for normal + * cases. + * + * @code{.c} + * av_rescale_rnd(3, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + * // Rescaling 3: + * // Calculating 3 * 1 / 2 + * // 3 / 2 is rounded up to 2 + * // => 2 + * + * av_rescale_rnd(AV_NOPTS_VALUE, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + * // Rescaling AV_NOPTS_VALUE: + * // AV_NOPTS_VALUE == INT64_MIN + * // AV_NOPTS_VALUE is passed through + * // => AV_NOPTS_VALUE + * @endcode + */ + AV_ROUND_PASS_MINMAX = 8192, +}; + +/** + * Compute the greatest common divisor of two integer operands. + * + * @param a,b Operands + * @return GCD of a and b up to sign; if a >= 0 and b >= 0, return value is >= 0; + * if a == 0 and b == 0, returns 0. + */ +int64_t av_const av_gcd(int64_t a, int64_t b); + +/** + * Rescale a 64-bit integer with rounding to nearest. + * + * The operation is mathematically equivalent to `a * b / c`, but writing that + * directly can overflow. + * + * This function is equivalent to av_rescale_rnd() with #AV_ROUND_NEAR_INF. + * + * @see av_rescale_rnd(), av_rescale_q(), av_rescale_q_rnd() + */ +int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const; + +/** + * Rescale a 64-bit integer with specified rounding. + * + * The operation is mathematically equivalent to `a * b / c`, but writing that + * directly can overflow, and does not support different rounding methods. + * + * @see av_rescale(), av_rescale_q(), av_rescale_q_rnd() + */ +int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers. + * + * The operation is mathematically equivalent to `a * bq / cq`. + * + * This function is equivalent to av_rescale_q_rnd() with #AV_ROUND_NEAR_INF. + * + * @see av_rescale(), av_rescale_rnd(), av_rescale_q_rnd() + */ +int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers with specified rounding. + * + * The operation is mathematically equivalent to `a * bq / cq`. + * + * @see av_rescale(), av_rescale_rnd(), av_rescale_q() + */ +int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, + enum AVRounding rnd) av_const; + +/** + * Compare two timestamps each in its own time base. + * + * @return One of the following values: + * - -1 if `ts_a` is before `ts_b` + * - 1 if `ts_a` is after `ts_b` + * - 0 if they represent the same position + * + * @warning + * The result of the function is undefined if one of the timestamps is outside + * the `int64_t` range when represented in the other's timebase. + */ +int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b); + +/** + * Compare the remainders of two integer operands divided by a common divisor. + * + * In other words, compare the least significant `log2(mod)` bits of integers + * `a` and `b`. + * + * @code{.c} + * av_compare_mod(0x11, 0x02, 0x10) < 0 // since 0x11 % 0x10 (0x1) < 0x02 % 0x10 (0x2) + * av_compare_mod(0x11, 0x02, 0x20) > 0 // since 0x11 % 0x20 (0x11) > 0x02 % 0x20 (0x02) + * @endcode + * + * @param a,b Operands + * @param mod Divisor; must be a power of 2 + * @return + * - a negative value if `a % mod < b % mod` + * - a positive value if `a % mod > b % mod` + * - zero if `a % mod == b % mod` + */ +int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod); + +/** + * Rescale a timestamp while preserving known durations. + * + * This function is designed to be called per audio packet to scale the input + * timestamp to a different time base. Compared to a simple av_rescale_q() + * call, this function is robust against possible inconsistent frame durations. + * + * The `last` parameter is a state variable that must be preserved for all + * subsequent calls for the same stream. For the first call, `*last` should be + * initialized to #AV_NOPTS_VALUE. + * + * @param[in] in_tb Input time base + * @param[in] in_ts Input timestamp + * @param[in] fs_tb Duration time base; typically this is finer-grained + * (greater) than `in_tb` and `out_tb` + * @param[in] duration Duration till the next call to this function (i.e. + * duration of the current packet/frame) + * @param[in,out] last Pointer to a timestamp expressed in terms of + * `fs_tb`, acting as a state variable + * @param[in] out_tb Output timebase + * @return Timestamp expressed in terms of `out_tb` + * + * @note In the context of this function, "duration" is in term of samples, not + * seconds. + */ +int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb); + +/** + * Add a value to a timestamp. + * + * This function guarantees that when the same value is repeatly added that + * no accumulation of rounding errors occurs. + * + * @param[in] ts Input timestamp + * @param[in] ts_tb Input timestamp time base + * @param[in] inc Value to be added + * @param[in] inc_tb Time base of `inc` + */ +int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc); + + +/** + * @} + */ + +#endif /* AVUTIL_MATHEMATICS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/mem.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/mem.h new file mode 100644 index 0000000000000..e21a1feaaeab1 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/mem.h @@ -0,0 +1,706 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_mem + * Memory handling functions + */ + +#ifndef AVUTIL_MEM_H +#define AVUTIL_MEM_H + +#include +#include + +#include "attributes.h" +#include "error.h" +#include "avutil.h" +#include "version.h" + +/** + * @addtogroup lavu_mem + * Utilities for manipulating memory. + * + * FFmpeg has several applications of memory that are not required of a typical + * program. For example, the computing-heavy components like video decoding and + * encoding can be sped up significantly through the use of aligned memory. + * + * However, for each of FFmpeg's applications of memory, there might not be a + * recognized or standardized API for that specific use. Memory alignment, for + * instance, varies wildly depending on operating systems, architectures, and + * compilers. Hence, this component of @ref libavutil is created to make + * dealing with memory consistently possible on all platforms. + * + * @{ + */ + +#if FF_API_DECLARE_ALIGNED +/** + * + * @defgroup lavu_mem_macros Alignment Macros + * Helper macros for declaring aligned variables. + * @{ + */ + +/** + * @def DECLARE_ALIGNED(n,t,v) + * Declare a variable that is aligned in memory. + * + * @code{.c} + * DECLARE_ALIGNED(16, uint16_t, aligned_int) = 42; + * DECLARE_ALIGNED(32, uint8_t, aligned_array)[128]; + * + * // The default-alignment equivalent would be + * uint16_t aligned_int = 42; + * uint8_t aligned_array[128]; + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + +/** + * @def DECLARE_ASM_ALIGNED(n,t,v) + * Declare an aligned variable appropriate for use in inline assembly code. + * + * @code{.c} + * DECLARE_ASM_ALIGNED(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008); + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + +/** + * @def DECLARE_ASM_CONST(n,t,v) + * Declare a static constant aligned variable appropriate for use in inline + * assembly code. + * + * @code{.c} + * DECLARE_ASM_CONST(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008); + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v +#elif defined(__DJGPP__) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v + #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v +#elif defined(__GNUC__) || defined(__clang__) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v +#elif defined(_MSC_VER) + #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v +#else + #define DECLARE_ALIGNED(n,t,v) t v + #define DECLARE_ASM_ALIGNED(n,t,v) t v + #define DECLARE_ASM_CONST(n,t,v) static const t v +#endif + +/** + * @} + */ +#endif + +/** + * @defgroup lavu_mem_attrs Function Attributes + * Function attributes applicable to memory handling functions. + * + * These function attributes can help compilers emit more useful warnings, or + * generate better code. + * @{ + */ + +/** + * @def av_malloc_attrib + * Function attribute denoting a malloc-like function. + * + * @see Function attribute `malloc` in GCC's documentation + */ + +#if AV_GCC_VERSION_AT_LEAST(3,1) + #define av_malloc_attrib __attribute__((__malloc__)) +#else + #define av_malloc_attrib +#endif + +/** + * @def av_alloc_size(...) + * Function attribute used on a function that allocates memory, whose size is + * given by the specified parameter(s). + * + * @code{.c} + * void *av_malloc(size_t size) av_alloc_size(1); + * void *av_calloc(size_t nmemb, size_t size) av_alloc_size(1, 2); + * @endcode + * + * @param ... One or two parameter indexes, separated by a comma + * + * @see Function attribute `alloc_size` in GCC's documentation + */ + +#if AV_GCC_VERSION_AT_LEAST(4,3) + #define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__))) +#else + #define av_alloc_size(...) +#endif + +/** + * @} + */ + +/** + * @defgroup lavu_mem_funcs Heap Management + * Functions responsible for allocating, freeing, and copying memory. + * + * All memory allocation functions have a built-in upper limit of `INT_MAX` + * bytes. This may be changed with av_max_alloc(), although exercise extreme + * caution when doing so. + * + * @{ + */ + +/** + * Allocate a memory block with alignment suitable for all memory accesses + * (including vectors if available on the CPU). + * + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * @see av_mallocz() + */ +void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a memory block with alignment suitable for all memory accesses + * (including vectors if available on the CPU) and zero all the bytes of the + * block. + * + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if it cannot be allocated + * @see av_malloc() + */ +void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a memory block for an array with av_malloc(). + * + * The allocated memory will have size `size * nmemb` bytes. + * + * @param nmemb Number of element + * @param size Size of a single element + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * @see av_malloc() + */ +av_alloc_size(1, 2) void *av_malloc_array(size_t nmemb, size_t size); + +/** + * Allocate a memory block for an array with av_mallocz(). + * + * The allocated memory will have size `size * nmemb` bytes. + * + * @param nmemb Number of elements + * @param size Size of the single element + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * + * @see av_mallocz() + * @see av_malloc_array() + */ +av_alloc_size(1, 2) void *av_mallocz_array(size_t nmemb, size_t size); + +/** + * Non-inlined equivalent of av_mallocz_array(). + * + * Created for symmetry with the calloc() C function. + */ +void *av_calloc(size_t nmemb, size_t size) av_malloc_attrib; + +/** + * Allocate, reallocate, or free a block of memory. + * + * If `ptr` is `NULL` and `size` > 0, allocate a new block. If `size` is + * zero, free the memory block pointed to by `ptr`. Otherwise, expand or + * shrink that block of memory according to `size`. + * + * @param ptr Pointer to a memory block already allocated with + * av_realloc() or `NULL` + * @param size Size in bytes of the memory block to be allocated or + * reallocated + * + * @return Pointer to a newly-reallocated block or `NULL` if the block + * cannot be reallocated or the function is used to free the memory block + * + * @warning Unlike av_malloc(), the returned pointer is not guaranteed to be + * correctly aligned. + * @see av_fast_realloc() + * @see av_reallocp() + */ +void *av_realloc(void *ptr, size_t size) av_alloc_size(2); + +/** + * Allocate, reallocate, or free a block of memory through a pointer to a + * pointer. + * + * If `*ptr` is `NULL` and `size` > 0, allocate a new block. If `size` is + * zero, free the memory block pointed to by `*ptr`. Otherwise, expand or + * shrink that block of memory according to `size`. + * + * @param[in,out] ptr Pointer to a pointer to a memory block already allocated + * with av_realloc(), or a pointer to `NULL`. The pointer + * is updated on success, or freed on failure. + * @param[in] size Size in bytes for the memory block to be allocated or + * reallocated + * + * @return Zero on success, an AVERROR error code on failure + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. + */ +av_warn_unused_result +int av_reallocp(void *ptr, size_t size); + +/** + * Allocate, reallocate, or free a block of memory. + * + * This function does the same thing as av_realloc(), except: + * - It takes two size arguments and allocates `nelem * elsize` bytes, + * after checking the result of the multiplication for integer overflow. + * - It frees the input block in case of failure, thus avoiding the memory + * leak with the classic + * @code{.c} + * buf = realloc(buf); + * if (!buf) + * return -1; + * @endcode + * pattern. + */ +void *av_realloc_f(void *ptr, size_t nelem, size_t elsize); + +/** + * Allocate, reallocate, or free an array. + * + * If `ptr` is `NULL` and `nmemb` > 0, allocate a new block. If + * `nmemb` is zero, free the memory block pointed to by `ptr`. + * + * @param ptr Pointer to a memory block already allocated with + * av_realloc() or `NULL` + * @param nmemb Number of elements in the array + * @param size Size of the single element of the array + * + * @return Pointer to a newly-reallocated block or NULL if the block + * cannot be reallocated or the function is used to free the memory block + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. + * @see av_reallocp_array() + */ +av_alloc_size(2, 3) void *av_realloc_array(void *ptr, size_t nmemb, size_t size); + +/** + * Allocate, reallocate, or free an array through a pointer to a pointer. + * + * If `*ptr` is `NULL` and `nmemb` > 0, allocate a new block. If `nmemb` is + * zero, free the memory block pointed to by `*ptr`. + * + * @param[in,out] ptr Pointer to a pointer to a memory block already + * allocated with av_realloc(), or a pointer to `NULL`. + * The pointer is updated on success, or freed on failure. + * @param[in] nmemb Number of elements + * @param[in] size Size of the single element + * + * @return Zero on success, an AVERROR error code on failure + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. + */ +int av_reallocp_array(void *ptr, size_t nmemb, size_t size); + +/** + * Reallocate the given buffer if it is not large enough, otherwise do nothing. + * + * If the given buffer is `NULL`, then a new uninitialized buffer is allocated. + * + * If the given buffer is not large enough, and reallocation fails, `NULL` is + * returned and `*size` is set to 0, but the original buffer is not changed or + * freed. + * + * A typical use pattern follows: + * + * @code{.c} + * uint8_t *buf = ...; + * uint8_t *new_buf = av_fast_realloc(buf, ¤t_size, size_needed); + * if (!new_buf) { + * // Allocation failed; clean up original buffer + * av_freep(&buf); + * return AVERROR(ENOMEM); + * } + * @endcode + * + * @param[in,out] ptr Already allocated buffer, or `NULL` + * @param[in,out] size Pointer to the size of buffer `ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `ptr` + * @return `ptr` if the buffer is large enough, a pointer to newly reallocated + * buffer if the buffer was not large enough, or `NULL` in case of + * error + * @see av_realloc() + * @see av_fast_malloc() + */ +void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate a buffer, reusing the given one if large enough. + * + * Contrary to av_fast_realloc(), the current buffer contents might not be + * preserved and on error the old buffer is freed, thus no special handling to + * avoid memleaks is necessary. + * + * `*ptr` is allowed to be `NULL`, in which case allocation always happens if + * `size_needed` is greater than 0. + * + * @code{.c} + * uint8_t *buf = ...; + * av_fast_malloc(&buf, ¤t_size, size_needed); + * if (!buf) { + * // Allocation failed; buf already freed + * return AVERROR(ENOMEM); + * } + * @endcode + * + * @param[in,out] ptr Pointer to pointer to an already allocated buffer. + * `*ptr` will be overwritten with pointer to new + * buffer on success or `NULL` on failure + * @param[in,out] size Pointer to the size of buffer `*ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `*ptr` + * @see av_realloc() + * @see av_fast_mallocz() + */ +void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate and clear a buffer, reusing the given one if large enough. + * + * Like av_fast_malloc(), but all newly allocated space is initially cleared. + * Reused buffer is not cleared. + * + * `*ptr` is allowed to be `NULL`, in which case allocation always happens if + * `size_needed` is greater than 0. + * + * @param[in,out] ptr Pointer to pointer to an already allocated buffer. + * `*ptr` will be overwritten with pointer to new + * buffer on success or `NULL` on failure + * @param[in,out] size Pointer to the size of buffer `*ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `*ptr` + * @see av_fast_malloc() + */ +void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * Free a memory block which has been allocated with a function of av_malloc() + * or av_realloc() family. + * + * @param ptr Pointer to the memory block which should be freed. + * + * @note `ptr = NULL` is explicitly allowed. + * @note It is recommended that you use av_freep() instead, to prevent leaving + * behind dangling pointers. + * @see av_freep() + */ +void av_free(void *ptr); + +/** + * Free a memory block which has been allocated with a function of av_malloc() + * or av_realloc() family, and set the pointer pointing to it to `NULL`. + * + * @code{.c} + * uint8_t *buf = av_malloc(16); + * av_free(buf); + * // buf now contains a dangling pointer to freed memory, and accidental + * // dereference of buf will result in a use-after-free, which may be a + * // security risk. + * + * uint8_t *buf = av_malloc(16); + * av_freep(&buf); + * // buf is now NULL, and accidental dereference will only result in a + * // NULL-pointer dereference. + * @endcode + * + * @param ptr Pointer to the pointer to the memory block which should be freed + * @note `*ptr = NULL` is safe and leads to no action. + * @see av_free() + */ +void av_freep(void *ptr); + +/** + * Duplicate a string. + * + * @param s String to be duplicated + * @return Pointer to a newly-allocated string containing a + * copy of `s` or `NULL` if the string cannot be allocated + * @see av_strndup() + */ +char *av_strdup(const char *s) av_malloc_attrib; + +/** + * Duplicate a substring of a string. + * + * @param s String to be duplicated + * @param len Maximum length of the resulting string (not counting the + * terminating byte) + * @return Pointer to a newly-allocated string containing a + * substring of `s` or `NULL` if the string cannot be allocated + */ +char *av_strndup(const char *s, size_t len) av_malloc_attrib; + +/** + * Duplicate a buffer with av_malloc(). + * + * @param p Buffer to be duplicated + * @param size Size in bytes of the buffer copied + * @return Pointer to a newly allocated buffer containing a + * copy of `p` or `NULL` if the buffer cannot be allocated + */ +void *av_memdup(const void *p, size_t size); + +/** + * Overlapping memcpy() implementation. + * + * @param dst Destination buffer + * @param back Number of bytes back to start copying (i.e. the initial size of + * the overlapping window); must be > 0 + * @param cnt Number of bytes to copy; must be >= 0 + * + * @note `cnt > back` is valid, this will copy the bytes we just copied, + * thus creating a repeating pattern with a period length of `back`. + */ +void av_memcpy_backptr(uint8_t *dst, int back, int cnt); + +/** + * @} + */ + +/** + * @defgroup lavu_mem_dynarray Dynamic Array + * + * Utilities to make an array grow when needed. + * + * Sometimes, the programmer would want to have an array that can grow when + * needed. The libavutil dynamic array utilities fill that need. + * + * libavutil supports two systems of appending elements onto a dynamically + * allocated array, the first one storing the pointer to the value in the + * array, and the second storing the value directly. In both systems, the + * caller is responsible for maintaining a variable containing the length of + * the array, as well as freeing of the array after use. + * + * The first system stores pointers to values in a block of dynamically + * allocated memory. Since only pointers are stored, the function does not need + * to know the size of the type. Both av_dynarray_add() and + * av_dynarray_add_nofree() implement this system. + * + * @code + * type **array = NULL; //< an array of pointers to values + * int nb = 0; //< a variable to keep track of the length of the array + * + * type to_be_added = ...; + * type to_be_added2 = ...; + * + * av_dynarray_add(&array, &nb, &to_be_added); + * if (nb == 0) + * return AVERROR(ENOMEM); + * + * av_dynarray_add(&array, &nb, &to_be_added2); + * if (nb == 0) + * return AVERROR(ENOMEM); + * + * // Now: + * // nb == 2 + * // &to_be_added == array[0] + * // &to_be_added2 == array[1] + * + * av_freep(&array); + * @endcode + * + * The second system stores the value directly in a block of memory. As a + * result, the function has to know the size of the type. av_dynarray2_add() + * implements this mechanism. + * + * @code + * type *array = NULL; //< an array of values + * int nb = 0; //< a variable to keep track of the length of the array + * + * type to_be_added = ...; + * type to_be_added2 = ...; + * + * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), NULL); + * if (!addr) + * return AVERROR(ENOMEM); + * memcpy(addr, &to_be_added, sizeof(to_be_added)); + * + * // Shortcut of the above. + * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), + * (const void *)&to_be_added2); + * if (!addr) + * return AVERROR(ENOMEM); + * + * // Now: + * // nb == 2 + * // to_be_added == array[0] + * // to_be_added2 == array[1] + * + * av_freep(&array); + * @endcode + * + * @{ + */ + +/** + * Add the pointer to an element to a dynamic array. + * + * The array to grow is supposed to be an array of pointers to + * structures, and the element to add must be a pointer to an already + * allocated structure. + * + * The array is reallocated when its size reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the number pointed to by `nb_ptr` + * is incremented. + * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and + * `*nb_ptr` is set to 0. + * + * @param[in,out] tab_ptr Pointer to the array to grow + * @param[in,out] nb_ptr Pointer to the number of elements in the array + * @param[in] elem Element to add + * @see av_dynarray_add_nofree(), av_dynarray2_add() + */ +void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element to a dynamic array. + * + * Function has the same functionality as av_dynarray_add(), + * but it doesn't free memory on fails. It returns error code + * instead and leave current buffer untouched. + * + * @return >=0 on success, negative otherwise + * @see av_dynarray_add(), av_dynarray2_add() + */ +av_warn_unused_result +int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element of size `elem_size` to a dynamic array. + * + * The array is reallocated when its number of elements reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the number pointed to by `nb_ptr` + * is incremented. + * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and + * `*nb_ptr` is set to 0. + * + * @param[in,out] tab_ptr Pointer to the array to grow + * @param[in,out] nb_ptr Pointer to the number of elements in the array + * @param[in] elem_size Size in bytes of an element in the array + * @param[in] elem_data Pointer to the data of the element to add. If + * `NULL`, the space of the newly added element is + * allocated but left uninitialized. + * + * @return Pointer to the data of the element to copy in the newly allocated + * space + * @see av_dynarray_add(), av_dynarray_add_nofree() + */ +void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, + const uint8_t *elem_data); + +/** + * @} + */ + +/** + * @defgroup lavu_mem_misc Miscellaneous Functions + * + * Other functions related to memory allocation. + * + * @{ + */ + +/** + * Multiply two `size_t` values checking for overflow. + * + * @param[in] a,b Operands of multiplication + * @param[out] r Pointer to the result of the operation + * @return 0 on success, AVERROR(EINVAL) on overflow + */ +static inline int av_size_mult(size_t a, size_t b, size_t *r) +{ + size_t t = a * b; + /* Hack inspired from glibc: don't try the division if nelem and elsize + * are both less than sqrt(SIZE_MAX). */ + if ((a | b) >= ((size_t)1 << (sizeof(size_t) * 4)) && a && t / a != b) + return AVERROR(EINVAL); + *r = t; + return 0; +} + +/** + * Set the maximum size that may be allocated in one block. + * + * The value specified with this function is effective for all libavutil's @ref + * lavu_mem_funcs "heap management functions." + * + * By default, the max value is defined as `INT_MAX`. + * + * @param max Value to be set as the new maximum size + * + * @warning Exercise extreme caution when using this function. Don't touch + * this if you do not understand the full consequence of doing so. + */ +void av_max_alloc(size_t max); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_MEM_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/opt.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/opt.h new file mode 100644 index 0000000000000..8dc020a8200af --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/opt.h @@ -0,0 +1,886 @@ +/* + * AVOptions + * copyright (c) 2005 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_OPT_H +#define AVUTIL_OPT_H + +/** + * @file + * AVOptions + */ + +#include "rational.h" +#include "avutil.h" +#include "dict.h" +#include "log.h" +#include "pixfmt.h" +#include "samplefmt.h" +#include "version.h" + +/** + * @defgroup avoptions AVOptions + * @ingroup lavu_data + * @{ + * AVOptions provide a generic system to declare options on arbitrary structs + * ("objects"). An option can have a help text, a type and a range of possible + * values. Options may then be enumerated, read and written to. + * + * @section avoptions_implement Implementing AVOptions + * This section describes how to add AVOptions capabilities to a struct. + * + * All AVOptions-related information is stored in an AVClass. Therefore + * the first member of the struct should be a pointer to an AVClass describing it. + * The option field of the AVClass must be set to a NULL-terminated static array + * of AVOptions. Each AVOption must have a non-empty name, a type, a default + * value and for number-type AVOptions also a range of allowed values. It must + * also declare an offset in bytes from the start of the struct, where the field + * associated with this AVOption is located. Other fields in the AVOption struct + * should also be set when applicable, but are not required. + * + * The following example illustrates an AVOptions-enabled struct: + * @code + * typedef struct test_struct { + * const AVClass *class; + * int int_opt; + * char *str_opt; + * uint8_t *bin_opt; + * int bin_len; + * } test_struct; + * + * static const AVOption test_options[] = { + * { "test_int", "This is a test option of int type.", offsetof(test_struct, int_opt), + * AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX }, + * { "test_str", "This is a test option of string type.", offsetof(test_struct, str_opt), + * AV_OPT_TYPE_STRING }, + * { "test_bin", "This is a test option of binary type.", offsetof(test_struct, bin_opt), + * AV_OPT_TYPE_BINARY }, + * { NULL }, + * }; + * + * static const AVClass test_class = { + * .class_name = "test class", + * .item_name = av_default_item_name, + * .option = test_options, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * @endcode + * + * Next, when allocating your struct, you must ensure that the AVClass pointer + * is set to the correct value. Then, av_opt_set_defaults() can be called to + * initialize defaults. After that the struct is ready to be used with the + * AVOptions API. + * + * When cleaning up, you may use the av_opt_free() function to automatically + * free all the allocated string and binary options. + * + * Continuing with the above example: + * + * @code + * test_struct *alloc_test_struct(void) + * { + * test_struct *ret = av_mallocz(sizeof(*ret)); + * ret->class = &test_class; + * av_opt_set_defaults(ret); + * return ret; + * } + * void free_test_struct(test_struct **foo) + * { + * av_opt_free(*foo); + * av_freep(foo); + * } + * @endcode + * + * @subsection avoptions_implement_nesting Nesting + * It may happen that an AVOptions-enabled struct contains another + * AVOptions-enabled struct as a member (e.g. AVCodecContext in + * libavcodec exports generic options, while its priv_data field exports + * codec-specific options). In such a case, it is possible to set up the + * parent struct to export a child's options. To do that, simply + * implement AVClass.child_next() and AVClass.child_class_iterate() in the + * parent struct's AVClass. + * Assuming that the test_struct from above now also contains a + * child_struct field: + * + * @code + * typedef struct child_struct { + * AVClass *class; + * int flags_opt; + * } child_struct; + * static const AVOption child_opts[] = { + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX }, + * { NULL }, + * }; + * static const AVClass child_class = { + * .class_name = "child class", + * .item_name = av_default_item_name, + * .option = child_opts, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * + * void *child_next(void *obj, void *prev) + * { + * test_struct *t = obj; + * if (!prev && t->child_struct) + * return t->child_struct; + * return NULL + * } + * const AVClass child_class_iterate(void **iter) + * { + * const AVClass *c = *iter ? NULL : &child_class; + * *iter = (void*)(uintptr_t)c; + * return c; + * } + * @endcode + * Putting child_next() and child_class_iterate() as defined above into + * test_class will now make child_struct's options accessible through + * test_struct (again, proper setup as described above needs to be done on + * child_struct right after it is created). + * + * From the above example it might not be clear why both child_next() + * and child_class_iterate() are needed. The distinction is that child_next() + * iterates over actually existing objects, while child_class_iterate() + * iterates over all possible child classes. E.g. if an AVCodecContext + * was initialized to use a codec which has private options, then its + * child_next() will return AVCodecContext.priv_data and finish + * iterating. OTOH child_class_iterate() on AVCodecContext.av_class will + * iterate over all available codecs with private options. + * + * @subsection avoptions_implement_named_constants Named constants + * It is possible to create named constants for options. Simply set the unit + * field of the option the constants should apply to a string and + * create the constants themselves as options of type AV_OPT_TYPE_CONST + * with their unit field set to the same string. + * Their default_val field should contain the value of the named + * constant. + * For example, to add some named constants for the test_flags option + * above, put the following into the child_opts array: + * @code + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, "test_unit" }, + * { "flag1", "This is a flag with value 16", 0, AV_OPT_TYPE_CONST, { .i64 = 16 }, 0, 0, "test_unit" }, + * @endcode + * + * @section avoptions_use Using AVOptions + * This section deals with accessing options in an AVOptions-enabled struct. + * Such structs in FFmpeg are e.g. AVCodecContext in libavcodec or + * AVFormatContext in libavformat. + * + * @subsection avoptions_use_examine Examining AVOptions + * The basic functions for examining options are av_opt_next(), which iterates + * over all options defined for one object, and av_opt_find(), which searches + * for an option with the given name. + * + * The situation is more complicated with nesting. An AVOptions-enabled struct + * may have AVOptions-enabled children. Passing the AV_OPT_SEARCH_CHILDREN flag + * to av_opt_find() will make the function search children recursively. + * + * For enumerating there are basically two cases. The first is when you want to + * get all options that may potentially exist on the struct and its children + * (e.g. when constructing documentation). In that case you should call + * av_opt_child_class_iterate() recursively on the parent struct's AVClass. The + * second case is when you have an already initialized struct with all its + * children and you want to get all options that can be actually written or read + * from it. In that case you should call av_opt_child_next() recursively (and + * av_opt_next() on each result). + * + * @subsection avoptions_use_get_set Reading and writing AVOptions + * When setting options, you often have a string read directly from the + * user. In such a case, simply passing it to av_opt_set() is enough. For + * non-string type options, av_opt_set() will parse the string according to the + * option type. + * + * Similarly av_opt_get() will read any option type and convert it to a string + * which will be returned. Do not forget that the string is allocated, so you + * have to free it with av_free(). + * + * In some cases it may be more convenient to put all options into an + * AVDictionary and call av_opt_set_dict() on it. A specific case of this + * are the format/codec open functions in lavf/lavc which take a dictionary + * filled with option as a parameter. This makes it possible to set some options + * that cannot be set otherwise, since e.g. the input file format is not known + * before the file is actually opened. + */ + +enum AVOptionType{ + AV_OPT_TYPE_FLAGS, + AV_OPT_TYPE_INT, + AV_OPT_TYPE_INT64, + AV_OPT_TYPE_DOUBLE, + AV_OPT_TYPE_FLOAT, + AV_OPT_TYPE_STRING, + AV_OPT_TYPE_RATIONAL, + AV_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length + AV_OPT_TYPE_DICT, + AV_OPT_TYPE_UINT64, + AV_OPT_TYPE_CONST, + AV_OPT_TYPE_IMAGE_SIZE, ///< offset must point to two consecutive integers + AV_OPT_TYPE_PIXEL_FMT, + AV_OPT_TYPE_SAMPLE_FMT, + AV_OPT_TYPE_VIDEO_RATE, ///< offset must point to AVRational + AV_OPT_TYPE_DURATION, + AV_OPT_TYPE_COLOR, + AV_OPT_TYPE_CHANNEL_LAYOUT, + AV_OPT_TYPE_BOOL, +}; + +/** + * AVOption + */ +typedef struct AVOption { + const char *name; + + /** + * short English help text + * @todo What about other languages? + */ + const char *help; + + /** + * The offset relative to the context structure where the option + * value is stored. It should be 0 for named constants. + */ + int offset; + enum AVOptionType type; + + /** + * the default value for scalar options + */ + union { + int64_t i64; + double dbl; + const char *str; + /* TODO those are unused now */ + AVRational q; + } default_val; + double min; ///< minimum valid value for the option + double max; ///< maximum valid value for the option + + int flags; +#define AV_OPT_FLAG_ENCODING_PARAM 1 ///< a generic parameter which can be set by the user for muxing or encoding +#define AV_OPT_FLAG_DECODING_PARAM 2 ///< a generic parameter which can be set by the user for demuxing or decoding +#define AV_OPT_FLAG_AUDIO_PARAM 8 +#define AV_OPT_FLAG_VIDEO_PARAM 16 +#define AV_OPT_FLAG_SUBTITLE_PARAM 32 +/** + * The option is intended for exporting values to the caller. + */ +#define AV_OPT_FLAG_EXPORT 64 +/** + * The option may not be set through the AVOptions API, only read. + * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set. + */ +#define AV_OPT_FLAG_READONLY 128 +#define AV_OPT_FLAG_BSF_PARAM (1<<8) ///< a generic parameter which can be set by the user for bit stream filtering +#define AV_OPT_FLAG_RUNTIME_PARAM (1<<15) ///< a generic parameter which can be set by the user at runtime +#define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering +#define AV_OPT_FLAG_DEPRECATED (1<<17) ///< set if option is deprecated, users should refer to AVOption.help text for more information +#define AV_OPT_FLAG_CHILD_CONSTS (1<<18) ///< set if option constants can also reside in child objects +//FIXME think about enc-audio, ... style flags + + /** + * The logical unit to which the option belongs. Non-constant + * options and corresponding named constants share the same + * unit. May be NULL. + */ + const char *unit; +} AVOption; + +/** + * A single allowed range of values, or a single allowed value. + */ +typedef struct AVOptionRange { + const char *str; + /** + * Value range. + * For string ranges this represents the min/max length. + * For dimensions this represents the min/max pixel count or width/height in multi-component case. + */ + double value_min, value_max; + /** + * Value's component range. + * For string this represents the unicode range for chars, 0-127 limits to ASCII. + */ + double component_min, component_max; + /** + * Range flag. + * If set to 1 the struct encodes a range, if set to 0 a single value. + */ + int is_range; +} AVOptionRange; + +/** + * List of AVOptionRange structs. + */ +typedef struct AVOptionRanges { + /** + * Array of option ranges. + * + * Most of option types use just one component. + * Following describes multi-component option types: + * + * AV_OPT_TYPE_IMAGE_SIZE: + * component index 0: range of pixel count (width * height). + * component index 1: range of width. + * component index 2: range of height. + * + * @note To obtain multi-component version of this structure, user must + * provide AV_OPT_MULTI_COMPONENT_RANGE to av_opt_query_ranges or + * av_opt_query_ranges_default function. + * + * Multi-component range can be read as in following example: + * + * @code + * int range_index, component_index; + * AVOptionRanges *ranges; + * AVOptionRange *range[3]; //may require more than 3 in the future. + * av_opt_query_ranges(&ranges, obj, key, AV_OPT_MULTI_COMPONENT_RANGE); + * for (range_index = 0; range_index < ranges->nb_ranges; range_index++) { + * for (component_index = 0; component_index < ranges->nb_components; component_index++) + * range[component_index] = ranges->range[ranges->nb_ranges * component_index + range_index]; + * //do something with range here. + * } + * av_opt_freep_ranges(&ranges); + * @endcode + */ + AVOptionRange **range; + /** + * Number of ranges per component. + */ + int nb_ranges; + /** + * Number of componentes. + */ + int nb_components; +} AVOptionRanges; + +/** + * Show the obj options. + * + * @param req_flags requested flags for the options to show. Show only the + * options for which it is opt->flags & req_flags. + * @param rej_flags rejected flags for the options to show. Show only the + * options for which it is !(opt->flags & req_flags). + * @param av_log_obj log context to use for showing the options + */ +int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); + +/** + * Set the values of all AVOption fields to their default values. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + */ +void av_opt_set_defaults(void *s); + +/** + * Set the values of all AVOption fields to their default values. Only these + * AVOption fields for which (opt->flags & mask) == flags will have their + * default applied to s. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + * @param mask combination of AV_OPT_FLAG_* + * @param flags combination of AV_OPT_FLAG_* + */ +void av_opt_set_defaults2(void *s, int mask, int flags); + +/** + * Parse the key/value pairs list in opts. For each key/value pair + * found, stores the value in the field in ctx that is named like the + * key. ctx must be an AVClass context, storing is done using + * AVOptions. + * + * @param opts options string to parse, may be NULL + * @param key_val_sep a 0-terminated list of characters used to + * separate key from value + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other + * @return the number of successfully set key/value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_opt_set() if a key/value pair + * cannot be set + */ +int av_set_options_string(void *ctx, const char *opts, + const char *key_val_sep, const char *pairs_sep); + +/** + * Parse the key-value pairs list in opts. For each key=value pair found, + * set the value of the corresponding option in ctx. + * + * @param ctx the AVClass object to set options on + * @param opts the options string, key-value pairs separated by a + * delimiter + * @param shorthand a NULL-terminated array of options names for shorthand + * notation: if the first field in opts has no key part, + * the key is taken from the first element of shorthand; + * then again for the second, etc., until either opts is + * finished, shorthand is finished or a named option is + * found; after that, all options must be named + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @return the number of successfully set key=value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_set_string3() if a key/value pair + * cannot be set + * + * Options names must use only the following characters: a-z A-Z 0-9 - . / _ + * Separators must use characters distinct from option names and from each + * other. + */ +int av_opt_set_from_string(void *ctx, const char *opts, + const char *const *shorthand, + const char *key_val_sep, const char *pairs_sep); +/** + * Free all allocated objects in obj. + */ +void av_opt_free(void *obj); + +/** + * Check whether a particular flag is set in a flags field. + * + * @param field_name the name of the flag field option + * @param flag_name the name of the flag to check + * @return non-zero if the flag is set, zero if the flag isn't set, + * isn't of the right type, or the flags field doesn't exist. + */ +int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name); + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict(void *obj, struct AVDictionary **options); + + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags); + +/** + * Extract a key-value pair from the beginning of a string. + * + * @param ropts pointer to the options string, will be updated to + * point to the rest of the string (one of the pairs_sep + * or the final NUL) + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @param flags flags; see the AV_OPT_FLAG_* values below + * @param rkey parsed key; must be freed using av_free() + * @param rval parsed value; must be freed using av_free() + * + * @return >=0 for success, or a negative value corresponding to an + * AVERROR code in case of error; in particular: + * AVERROR(EINVAL) if no key is present + * + */ +int av_opt_get_key_value(const char **ropts, + const char *key_val_sep, const char *pairs_sep, + unsigned flags, + char **rkey, char **rval); + +enum { + + /** + * Accept to parse a value without a key; the key will then be returned + * as NULL. + */ + AV_OPT_FLAG_IMPLICIT_KEY = 1, +}; + +/** + * @defgroup opt_eval_funcs Evaluating option strings + * @{ + * This group of functions can be used to evaluate option strings + * and get numbers out of them. They do the same thing as av_opt_set(), + * except the result is written into the caller-supplied pointer. + * + * @param obj a struct whose first element is a pointer to AVClass. + * @param o an option for which the string is to be evaluated. + * @param val string to be evaluated. + * @param *_out value of the string will be written here. + * + * @return 0 on success, a negative number on failure. + */ +int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out); +int av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out); +int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out); +int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out); +int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double *double_out); +int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out); +/** + * @} + */ + +#define AV_OPT_SEARCH_CHILDREN (1 << 0) /**< Search in possible children of the + given object first. */ +/** + * The obj passed to av_opt_find() is fake -- only a double pointer to AVClass + * instead of a required pointer to a struct containing AVClass. This is + * useful for searching for options without needing to allocate the corresponding + * object. + */ +#define AV_OPT_SEARCH_FAKE_OBJ (1 << 1) + +/** + * In av_opt_get, return NULL if the option has a pointer type and is set to NULL, + * rather than returning an empty string. + */ +#define AV_OPT_ALLOW_NULL (1 << 2) + +/** + * Allows av_opt_query_ranges and av_opt_query_ranges_default to return more than + * one component for certain option types. + * @see AVOptionRanges for details. + */ +#define AV_OPT_MULTI_COMPONENT_RANGE (1 << 12) + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return A pointer to the option found, or NULL if no option + * was found. + * + * @note Options found with AV_OPT_SEARCH_CHILDREN flag may not be settable + * directly with av_opt_set(). Use special calls which take an options + * AVDictionary (e.g. avformat_open_input()) to set options found with this + * flag. + */ +const AVOption *av_opt_find(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags); + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * @param[out] target_obj if non-NULL, an object to which the option belongs will be + * written here. It may be different from obj if AV_OPT_SEARCH_CHILDREN is present + * in search_flags. This parameter is ignored if search_flags contain + * AV_OPT_SEARCH_FAKE_OBJ. + * + * @return A pointer to the option found, or NULL if no option + * was found. + */ +const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags, void **target_obj); + +/** + * Iterate over all AVOptions belonging to obj. + * + * @param obj an AVOptions-enabled struct or a double pointer to an + * AVClass describing it. + * @param prev result of the previous call to av_opt_next() on this object + * or NULL + * @return next AVOption or NULL + */ +const AVOption *av_opt_next(const void *obj, const AVOption *prev); + +/** + * Iterate over AVOptions-enabled children of obj. + * + * @param prev result of a previous call to this function or NULL + * @return next AVOptions-enabled child or NULL + */ +void *av_opt_child_next(void *obj, void *prev); + +#if FF_API_CHILD_CLASS_NEXT +/** + * Iterate over potential AVOptions-enabled children of parent. + * + * @param prev result of a previous call to this function or NULL + * @return AVClass corresponding to next potential child or NULL + * + * @deprecated use av_opt_child_class_iterate + */ +attribute_deprecated +const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev); +#endif + +/** + * Iterate over potential AVOptions-enabled children of parent. + * + * @param iter a pointer where iteration state is stored. + * @return AVClass corresponding to next potential child or NULL + */ +const AVClass *av_opt_child_class_iterate(const AVClass *parent, void **iter); + +/** + * @defgroup opt_set_funcs Option setting functions + * @{ + * Those functions set the field of obj with the given name to value. + * + * @param[in] obj A struct whose first element is a pointer to an AVClass. + * @param[in] name the name of the field to set + * @param[in] val The value to set. In case of av_opt_set() if the field is not + * of a string type, then the given string is parsed. + * SI postfixes and some named scalars are supported. + * If the field is of a numeric type, it has to be a numeric or named + * scalar. Behavior with more than one scalar and +- infix operators + * is undefined. + * If the field is of a flags type, it has to be a sequence of numeric + * scalars or named flags separated by '+' or '-'. Prefixing a flag + * with '+' causes it to be set without affecting the other flags; + * similarly, '-' unsets a flag. + * If the field is of a dictionary type, it has to be a ':' separated list of + * key=value parameters. Values containing ':' special characters must be + * escaped. + * @param search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be set on a child of obj. + * + * @return 0 if the value has been set, or an AVERROR code in case of + * error: + * AVERROR_OPTION_NOT_FOUND if no matching option exists + * AVERROR(ERANGE) if the value is out of range + * AVERROR(EINVAL) if the value is not valid + */ +int av_opt_set (void *obj, const char *name, const char *val, int search_flags); +int av_opt_set_int (void *obj, const char *name, int64_t val, int search_flags); +int av_opt_set_double (void *obj, const char *name, double val, int search_flags); +int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags); +int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, int search_flags); +int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags); +int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags); +int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags); +int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags); +int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags); +/** + * @note Any old dictionary present is discarded and replaced with a copy of the new one. The + * caller still owns val is and responsible for freeing it. + */ +int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags); + +/** + * Set a binary option to an integer list. + * + * @param obj AVClass object to set options on + * @param name name of the binary option + * @param val pointer to an integer list (must have the correct type with + * regard to the contents of the list) + * @param term list terminator (usually 0 or -1) + * @param flags search flags + */ +#define av_opt_set_int_list(obj, name, val, term, flags) \ + (av_int_list_length(val, term) > INT_MAX / sizeof(*(val)) ? \ + AVERROR(EINVAL) : \ + av_opt_set_bin(obj, name, (const uint8_t *)(val), \ + av_int_list_length(val, term) * sizeof(*(val)), flags)) + +/** + * @} + */ + +/** + * @defgroup opt_get_funcs Option getting functions + * @{ + * Those functions get a value of the option with the given name from an object. + * + * @param[in] obj a struct whose first element is a pointer to an AVClass. + * @param[in] name name of the option to get. + * @param[in] search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be found in a child of obj. + * @param[out] out_val value of the option will be written here + * @return >=0 on success, a negative error code otherwise + */ +/** + * @note the returned string will be av_malloc()ed and must be av_free()ed by the caller + * + * @note if AV_OPT_ALLOW_NULL is set in search_flags in av_opt_get, and the + * option is of type AV_OPT_TYPE_STRING, AV_OPT_TYPE_BINARY or AV_OPT_TYPE_DICT + * and is set to NULL, *out_val will be set to NULL instead of an allocated + * empty string. + */ +int av_opt_get (void *obj, const char *name, int search_flags, uint8_t **out_val); +int av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val); +int av_opt_get_double (void *obj, const char *name, int search_flags, double *out_val); +int av_opt_get_q (void *obj, const char *name, int search_flags, AVRational *out_val); +int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out); +int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt); +int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt); +int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val); +int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout); +/** + * @param[out] out_val The returned dictionary is a copy of the actual value and must + * be freed with av_dict_free() by the caller + */ +int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val); +/** + * @} + */ +/** + * Gets a pointer to the requested field in a struct. + * This function allows accessing a struct even when its fields are moved or + * renamed since the application making the access has been compiled, + * + * @returns a pointer to the field, it can be cast to the correct type and read + * or written to. + */ +void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name); + +/** + * Free an AVOptionRanges struct and set it to NULL. + */ +void av_opt_freep_ranges(AVOptionRanges **ranges); + +/** + * Get a list of allowed ranges for the given option. + * + * The returned list may depend on other fields in obj like for example profile. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_freep_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * Copy options from src object into dest object. + * + * Options that require memory allocation (e.g. string or binary) are malloc'ed in dest object. + * Original memory allocated for such options is freed unless both src and dest options points to the same memory. + * + * @param dest Object to copy from + * @param src Object to copy into + * @return 0 on success, negative on error + */ +int av_opt_copy(void *dest, const void *src); + +/** + * Get a default list of allowed ranges for the given option. + * + * This list is constructed without using the AVClass.query_ranges() callback + * and can be used as fallback from within the callback. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_free_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * Check if given option is set to its default value. + * + * Options o must belong to the obj. This function must not be called to check child's options state. + * @see av_opt_is_set_to_default_by_name(). + * + * @param obj AVClass object to check option on + * @param o option to be checked + * @return >0 when option is set to its default, + * 0 when option is not set its default, + * <0 on error + */ +int av_opt_is_set_to_default(void *obj, const AVOption *o); + +/** + * Check if given option is set to its default value. + * + * @param obj AVClass object to check option on + * @param name option name + * @param search_flags combination of AV_OPT_SEARCH_* + * @return >0 when option is set to its default, + * 0 when option is not set its default, + * <0 on error + */ +int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags); + + +#define AV_OPT_SERIALIZE_SKIP_DEFAULTS 0x00000001 ///< Serialize options that are not set to default values only. +#define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT 0x00000002 ///< Serialize options that exactly match opt_flags only. + +/** + * Serialize object's options. + * + * Create a string containing object's serialized options. + * Such string may be passed back to av_opt_set_from_string() in order to restore option values. + * A key/value or pairs separator occurring in the serialized value or + * name string are escaped through the av_escape() function. + * + * @param[in] obj AVClass object to serialize + * @param[in] opt_flags serialize options with all the specified flags set (AV_OPT_FLAG) + * @param[in] flags combination of AV_OPT_SERIALIZE_* flags + * @param[out] buffer Pointer to buffer that will be allocated with string containg serialized options. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep character used to separate key from value + * @param[in] pairs_sep character used to separate two pairs from each other + * @return >= 0 on success, negative on error + * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same. + */ +int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, + const char key_val_sep, const char pairs_sep); +/** + * @} + */ + +#endif /* AVUTIL_OPT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/pixdesc.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/pixdesc.h new file mode 100644 index 0000000000000..9b9d386ae96e8 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/pixdesc.h @@ -0,0 +1,442 @@ +/* + * pixel format descriptor + * Copyright (c) 2009 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXDESC_H +#define AVUTIL_PIXDESC_H + +#include + +#include "attributes.h" +#include "pixfmt.h" +#include "version.h" + +typedef struct AVComponentDescriptor { + /** + * Which of the 4 planes contains the component. + */ + int plane; + + /** + * Number of elements between 2 horizontally consecutive pixels. + * Elements are bits for bitstream formats, bytes otherwise. + */ + int step; + + /** + * Number of elements before the component of the first pixel. + * Elements are bits for bitstream formats, bytes otherwise. + */ + int offset; + + /** + * Number of least significant bits that must be shifted away + * to get the value. + */ + int shift; + + /** + * Number of bits in the component. + */ + int depth; + +#if FF_API_PLUS1_MINUS1 + /** deprecated, use step instead */ + attribute_deprecated int step_minus1; + + /** deprecated, use depth instead */ + attribute_deprecated int depth_minus1; + + /** deprecated, use offset instead */ + attribute_deprecated int offset_plus1; +#endif +} AVComponentDescriptor; + +/** + * Descriptor that unambiguously describes how the bits of a pixel are + * stored in the up to 4 data planes of an image. It also stores the + * subsampling factors and number of components. + * + * @note This is separate of the colorspace (RGB, YCbCr, YPbPr, JPEG-style YUV + * and all the YUV variants) AVPixFmtDescriptor just stores how values + * are stored not what these values represent. + */ +typedef struct AVPixFmtDescriptor { + const char *name; + uint8_t nb_components; ///< The number of components each pixel has, (1-4) + + /** + * Amount to shift the luma width right to find the chroma width. + * For YV12 this is 1 for example. + * chroma_width = AV_CEIL_RSHIFT(luma_width, log2_chroma_w) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_w; + + /** + * Amount to shift the luma height right to find the chroma height. + * For YV12 this is 1 for example. + * chroma_height= AV_CEIL_RSHIFT(luma_height, log2_chroma_h) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_h; + + /** + * Combination of AV_PIX_FMT_FLAG_... flags. + */ + uint64_t flags; + + /** + * Parameters that describe how pixels are packed. + * If the format has 1 or 2 components, then luma is 0. + * If the format has 3 or 4 components: + * if the RGB flag is set then 0 is red, 1 is green and 2 is blue; + * otherwise 0 is luma, 1 is chroma-U and 2 is chroma-V. + * + * If present, the Alpha channel is always the last component. + */ + AVComponentDescriptor comp[4]; + + /** + * Alternative comma-separated names. + */ + const char *alias; +} AVPixFmtDescriptor; + +/** + * Pixel format is big-endian. + */ +#define AV_PIX_FMT_FLAG_BE (1 << 0) +/** + * Pixel format has a palette in data[1], values are indexes in this palette. + */ +#define AV_PIX_FMT_FLAG_PAL (1 << 1) +/** + * All values of a component are bit-wise packed end to end. + */ +#define AV_PIX_FMT_FLAG_BITSTREAM (1 << 2) +/** + * Pixel format is an HW accelerated format. + */ +#define AV_PIX_FMT_FLAG_HWACCEL (1 << 3) +/** + * At least one pixel component is not in the first data plane. + */ +#define AV_PIX_FMT_FLAG_PLANAR (1 << 4) +/** + * The pixel format contains RGB-like data (as opposed to YUV/grayscale). + */ +#define AV_PIX_FMT_FLAG_RGB (1 << 5) + +#if FF_API_PSEUDOPAL +/** + * The pixel format is "pseudo-paletted". This means that it contains a + * fixed palette in the 2nd plane but the palette is fixed/constant for each + * PIX_FMT. This allows interpreting the data as if it was PAL8, which can + * in some cases be simpler. Or the data can be interpreted purely based on + * the pixel format without using the palette. + * An example of a pseudo-paletted format is AV_PIX_FMT_GRAY8 + * + * @deprecated This flag is deprecated, and will be removed. When it is removed, + * the extra palette allocation in AVFrame.data[1] is removed as well. Only + * actual paletted formats (as indicated by AV_PIX_FMT_FLAG_PAL) will have a + * palette. Starting with FFmpeg versions which have this flag deprecated, the + * extra "pseudo" palette is already ignored, and API users are not required to + * allocate a palette for AV_PIX_FMT_FLAG_PSEUDOPAL formats (it was required + * before the deprecation, though). + */ +#define AV_PIX_FMT_FLAG_PSEUDOPAL (1 << 6) +#endif + +/** + * The pixel format has an alpha channel. This is set on all formats that + * support alpha in some way, including AV_PIX_FMT_PAL8. The alpha is always + * straight, never pre-multiplied. + * + * If a codec or a filter does not support alpha, it should set all alpha to + * opaque, or use the equivalent pixel formats without alpha component, e.g. + * AV_PIX_FMT_RGB0 (or AV_PIX_FMT_RGB24 etc.) instead of AV_PIX_FMT_RGBA. + */ +#define AV_PIX_FMT_FLAG_ALPHA (1 << 7) + +/** + * The pixel format is following a Bayer pattern + */ +#define AV_PIX_FMT_FLAG_BAYER (1 << 8) + +/** + * The pixel format contains IEEE-754 floating point values. Precision (double, + * single, or half) should be determined by the pixel size (64, 32, or 16 bits). + */ +#define AV_PIX_FMT_FLAG_FLOAT (1 << 9) + +/** + * Return the number of bits per pixel used by the pixel format + * described by pixdesc. Note that this is not the same as the number + * of bits per sample. + * + * The returned number of bits refers to the number of bits actually + * used for storing the pixel information, that is padding bits are + * not counted. + */ +int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * Return the number of bits per pixel for the pixel format + * described by pixdesc, including any padding or unused bits. + */ +int av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * @return a pixel format descriptor for provided pixel format or NULL if + * this pixel format is unknown. + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt); + +/** + * Iterate over all pixel format descriptors known to libavutil. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_next(const AVPixFmtDescriptor *prev); + +/** + * @return an AVPixelFormat id described by desc, or AV_PIX_FMT_NONE if desc + * is not a valid pointer to a pixel format descriptor. + */ +enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); + +/** + * Utility function to access log2_chroma_w log2_chroma_h from + * the pixel format AVPixFmtDescriptor. + * + * @param[in] pix_fmt the pixel format + * @param[out] h_shift store log2_chroma_w (horizontal/width shift) + * @param[out] v_shift store log2_chroma_h (vertical/height shift) + * + * @return 0 on success, AVERROR(ENOSYS) on invalid or unknown pixel format + */ +int av_pix_fmt_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, + int *h_shift, int *v_shift); + +/** + * @return number of planes in pix_fmt, a negative AVERROR if pix_fmt is not a + * valid pixel format. + */ +int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt); + +/** + * @return the name for provided color range or NULL if unknown. + */ +const char *av_color_range_name(enum AVColorRange range); + +/** + * @return the AVColorRange value for name or an AVError if not found. + */ +int av_color_range_from_name(const char *name); + +/** + * @return the name for provided color primaries or NULL if unknown. + */ +const char *av_color_primaries_name(enum AVColorPrimaries primaries); + +/** + * @return the AVColorPrimaries value for name or an AVError if not found. + */ +int av_color_primaries_from_name(const char *name); + +/** + * @return the name for provided color transfer or NULL if unknown. + */ +const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer); + +/** + * @return the AVColorTransferCharacteristic value for name or an AVError if not found. + */ +int av_color_transfer_from_name(const char *name); + +/** + * @return the name for provided color space or NULL if unknown. + */ +const char *av_color_space_name(enum AVColorSpace space); + +/** + * @return the AVColorSpace value for name or an AVError if not found. + */ +int av_color_space_from_name(const char *name); + +/** + * @return the name for provided chroma location or NULL if unknown. + */ +const char *av_chroma_location_name(enum AVChromaLocation location); + +/** + * @return the AVChromaLocation value for name or an AVError if not found. + */ +int av_chroma_location_from_name(const char *name); + +/** + * Return the pixel format corresponding to name. + * + * If there is no pixel format with name name, then looks for a + * pixel format with the name corresponding to the native endian + * format of name. + * For example in a little-endian system, first looks for "gray16", + * then for "gray16le". + * + * Finally if no pixel format has been found, returns AV_PIX_FMT_NONE. + */ +enum AVPixelFormat av_get_pix_fmt(const char *name); + +/** + * Return the short name for a pixel format, NULL in case pix_fmt is + * unknown. + * + * @see av_get_pix_fmt(), av_get_pix_fmt_string() + */ +const char *av_get_pix_fmt_name(enum AVPixelFormat pix_fmt); + +/** + * Print in buf the string corresponding to the pixel format with + * number pix_fmt, or a header if pix_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param pix_fmt the number of the pixel format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + */ +char *av_get_pix_fmt_string(char *buf, int buf_size, + enum AVPixelFormat pix_fmt); + +/** + * Read a line from an image, and write the values of the + * pixel format component c to dst. + * + * @param data the array containing the pointers to the planes of the image + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to read + * @param y the vertical coordinate of the first pixel to read + * @param w the width of the line to read, that is the number of + * values to write to dst + * @param read_pal_component if not zero and the format is a paletted + * format writes the values corresponding to the palette + * component c in data[1] to dst, rather than the palette indexes in + * data[0]. The behavior is undefined if the format is not paletted. + * @param dst_element_size size of elements in dst array (2 or 4 byte) + */ +void av_read_image_line2(void *dst, const uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int read_pal_component, + int dst_element_size); + +void av_read_image_line(uint16_t *dst, const uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int read_pal_component); + +/** + * Write the values from src to the pixel format component c of an + * image line. + * + * @param src array containing the values to write + * @param data the array containing the pointers to the planes of the + * image to write into. It is supposed to be zeroed. + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to write + * @param y the vertical coordinate of the first pixel to write + * @param w the width of the line to write, that is the number of + * values to write to the image line + * @param src_element_size size of elements in src array (2 or 4 byte) + */ +void av_write_image_line2(const void *src, uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int src_element_size); + +void av_write_image_line(const uint16_t *src, uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w); + +/** + * Utility function to swap the endianness of a pixel format. + * + * @param[in] pix_fmt the pixel format + * + * @return pixel format with swapped endianness if it exists, + * otherwise AV_PIX_FMT_NONE + */ +enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt); + +#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + int has_alpha); + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); + +#endif /* AVUTIL_PIXDESC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/pixfmt.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/pixfmt.h new file mode 100644 index 0000000000000..46ef211add113 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/pixfmt.h @@ -0,0 +1,616 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXFMT_H +#define AVUTIL_PIXFMT_H + +/** + * @file + * pixel format definitions + */ + +#include "libavutil/avconfig.h" +#include "version.h" + +#define AVPALETTE_SIZE 1024 +#define AVPALETTE_COUNT 256 + +/** + * Pixel format. + * + * @note + * AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA + * color is put together as: + * (A << 24) | (R << 16) | (G << 8) | B + * This is stored as BGRA on little-endian CPU architectures and ARGB on + * big-endian CPUs. + * + * @note + * If the resolution is not a multiple of the chroma subsampling factor + * then the chroma plane resolution must be rounded up. + * + * @par + * When the pixel format is palettized RGB32 (AV_PIX_FMT_PAL8), the palettized + * image data is stored in AVFrame.data[0]. The palette is transported in + * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is + * formatted the same as in AV_PIX_FMT_RGB32 described above (i.e., it is + * also endian-specific). Note also that the individual RGB32 palette + * components stored in AVFrame.data[1] should be in the range 0..255. + * This is important as many custom PAL8 video codecs that were designed + * to run on the IBM VGA graphics adapter use 6-bit palette components. + * + * @par + * For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like + * for pal8. This palette is filled in automatically by the function + * allocating the picture. + */ +enum AVPixelFormat { + AV_PIX_FMT_NONE = -1, + AV_PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) + AV_PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr + AV_PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB... + AV_PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR... + AV_PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) + AV_PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples) + AV_PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) + AV_PIX_FMT_GRAY8, ///< Y , 8bpp + AV_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_PAL8, ///< 8 bits with AV_PIX_FMT_RGB32 palette + AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range + AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range + AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range + AV_PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 + AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 + AV_PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) + AV_PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb) + AV_PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb) + AV_PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) + AV_PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV21, ///< as above, but U and V bytes are swapped + + AV_PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... + AV_PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA... + AV_PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR... + AV_PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA... + + AV_PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian + AV_PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian + AV_PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) + AV_PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range + AV_PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) + AV_PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian + + AV_PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian + AV_PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian + AV_PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined + + AV_PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian + AV_PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian + AV_PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined + +#if FF_API_VAAPI + /** @name Deprecated pixel formats */ + /**@{*/ + AV_PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers + AV_PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers + AV_PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a VASurfaceID + /**@}*/ + AV_PIX_FMT_VAAPI = AV_PIX_FMT_VAAPI_VLD, +#else + /** + * Hardware acceleration through VA-API, data[3] contains a + * VASurfaceID. + */ + AV_PIX_FMT_VAAPI, +#endif + + AV_PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer + + AV_PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_YA8, ///< 8 bits gray, 8 bits alpha + + AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + AV_PIX_FMT_GRAY8A= AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + + AV_PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian + + /** + * The following 12 formats have the disadvantage of needing 1 format for each bit depth. + * Notice that each 9/10 bits sample is stored in 16 bits with extra padding. + * If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better. + */ + AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp + AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP + AV_PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big-endian + AV_PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little-endian + AV_PIX_FMT_GBRP10BE, ///< planar GBR 4:4:4 30bpp, big-endian + AV_PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little-endian + AV_PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little-endian + AV_PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + AV_PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + AV_PIX_FMT_YUVA420P9BE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian + AV_PIX_FMT_YUVA420P9LE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian + AV_PIX_FMT_YUVA422P9BE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA422P9LE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA444P9BE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA444P9LE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA420P10BE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P10LE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P10BE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P10LE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P10BE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P10LE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA420P16BE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P16LE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P16BE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P16LE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P16BE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P16LE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + + AV_PIX_FMT_VDPAU, ///< HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface + + AV_PIX_FMT_XYZ12LE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_XYZ12BE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_NV16, ///< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_NV20LE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_NV20BE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + + AV_PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + + AV_PIX_FMT_YVYU422, ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb + + AV_PIX_FMT_YA16BE, ///< 16 bits gray, 16 bits alpha (big-endian) + AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian) + + AV_PIX_FMT_GBRAP, ///< planar GBRA 4:4:4:4 32bpp + AV_PIX_FMT_GBRAP16BE, ///< planar GBRA 4:4:4:4 64bpp, big-endian + AV_PIX_FMT_GBRAP16LE, ///< planar GBRA 4:4:4:4 64bpp, little-endian + /** + * HW acceleration through QSV, data[3] contains a pointer to the + * mfxFrameSurface1 structure. + */ + AV_PIX_FMT_QSV, + /** + * HW acceleration though MMAL, data[3] contains a pointer to the + * MMAL_BUFFER_HEADER_T structure. + */ + AV_PIX_FMT_MMAL, + + AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer + + /** + * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers + * exactly as for system memory frames. + */ + AV_PIX_FMT_CUDA, + + AV_PIX_FMT_0RGB, ///< packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined + AV_PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined + AV_PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined + AV_PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined + + AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_GBRP12BE, ///< planar GBR 4:4:4 36bpp, big-endian + AV_PIX_FMT_GBRP12LE, ///< planar GBR 4:4:4 36bpp, little-endian + AV_PIX_FMT_GBRP14BE, ///< planar GBR 4:4:4 42bpp, big-endian + AV_PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little-endian + AV_PIX_FMT_YUVJ411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV411P and setting color_range + + AV_PIX_FMT_BAYER_BGGR8, ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples + AV_PIX_FMT_BAYER_RGGB8, ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples + AV_PIX_FMT_BAYER_GBRG8, ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples + AV_PIX_FMT_BAYER_GRBG8, ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples + AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian + + AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing + + AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_YUV440P12LE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P12BE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_AYUV64LE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_AYUV64BE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + + AV_PIX_FMT_VIDEOTOOLBOX, ///< hardware decoding through Videotoolbox + + AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian + AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian + + AV_PIX_FMT_GBRAP12BE, ///< planar GBR 4:4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRAP12LE, ///< planar GBR 4:4:4:4 48bpp, little-endian + + AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian + AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian + + AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec + + AV_PIX_FMT_GRAY12BE, ///< Y , 12bpp, big-endian + AV_PIX_FMT_GRAY12LE, ///< Y , 12bpp, little-endian + AV_PIX_FMT_GRAY10BE, ///< Y , 10bpp, big-endian + AV_PIX_FMT_GRAY10LE, ///< Y , 10bpp, little-endian + + AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian + AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian + + /** + * Hardware surfaces for Direct3D11. + * + * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11 + * hwaccel API and filtering support AV_PIX_FMT_D3D11 only. + * + * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the + * texture array index of the frame as intptr_t if the ID3D11Texture2D is + * an array texture (or always 0 if it's a normal texture). + */ + AV_PIX_FMT_D3D11, + + AV_PIX_FMT_GRAY9BE, ///< Y , 9bpp, big-endian + AV_PIX_FMT_GRAY9LE, ///< Y , 9bpp, little-endian + + AV_PIX_FMT_GBRPF32BE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, big-endian + AV_PIX_FMT_GBRPF32LE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, little-endian + AV_PIX_FMT_GBRAPF32BE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian + AV_PIX_FMT_GBRAPF32LE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian + + /** + * DRM-managed buffers exposed through PRIME buffer sharing. + * + * data[0] points to an AVDRMFrameDescriptor. + */ + AV_PIX_FMT_DRM_PRIME, + /** + * Hardware surfaces for OpenCL. + * + * data[i] contain 2D image objects (typed in C as cl_mem, used + * in OpenCL as image2d_t) for each plane of the surface. + */ + AV_PIX_FMT_OPENCL, + + AV_PIX_FMT_GRAY14BE, ///< Y , 14bpp, big-endian + AV_PIX_FMT_GRAY14LE, ///< Y , 14bpp, little-endian + + AV_PIX_FMT_GRAYF32BE, ///< IEEE-754 single precision Y, 32bpp, big-endian + AV_PIX_FMT_GRAYF32LE, ///< IEEE-754 single precision Y, 32bpp, little-endian + + AV_PIX_FMT_YUVA422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, little-endian + AV_PIX_FMT_YUVA444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, little-endian + + AV_PIX_FMT_NV24, ///< planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV42, ///< as above, but U and V bytes are swapped + + /** + * Vulkan hardware images. + * + * data[0] points to an AVVkFrame + */ + AV_PIX_FMT_VULKAN, + + AV_PIX_FMT_Y210BE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_Y210LE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, little-endian + + AV_PIX_FMT_X2RGB10LE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_X2RGB10BE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions +}; + +#if AV_HAVE_BIGENDIAN +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##be +#else +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##le +#endif + +#define AV_PIX_FMT_RGB32 AV_PIX_FMT_NE(ARGB, BGRA) +#define AV_PIX_FMT_RGB32_1 AV_PIX_FMT_NE(RGBA, ABGR) +#define AV_PIX_FMT_BGR32 AV_PIX_FMT_NE(ABGR, RGBA) +#define AV_PIX_FMT_BGR32_1 AV_PIX_FMT_NE(BGRA, ARGB) +#define AV_PIX_FMT_0RGB32 AV_PIX_FMT_NE(0RGB, BGR0) +#define AV_PIX_FMT_0BGR32 AV_PIX_FMT_NE(0BGR, RGB0) + +#define AV_PIX_FMT_GRAY9 AV_PIX_FMT_NE(GRAY9BE, GRAY9LE) +#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE) +#define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE) +#define AV_PIX_FMT_GRAY14 AV_PIX_FMT_NE(GRAY14BE, GRAY14LE) +#define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE) +#define AV_PIX_FMT_YA16 AV_PIX_FMT_NE(YA16BE, YA16LE) +#define AV_PIX_FMT_RGB48 AV_PIX_FMT_NE(RGB48BE, RGB48LE) +#define AV_PIX_FMT_RGB565 AV_PIX_FMT_NE(RGB565BE, RGB565LE) +#define AV_PIX_FMT_RGB555 AV_PIX_FMT_NE(RGB555BE, RGB555LE) +#define AV_PIX_FMT_RGB444 AV_PIX_FMT_NE(RGB444BE, RGB444LE) +#define AV_PIX_FMT_RGBA64 AV_PIX_FMT_NE(RGBA64BE, RGBA64LE) +#define AV_PIX_FMT_BGR48 AV_PIX_FMT_NE(BGR48BE, BGR48LE) +#define AV_PIX_FMT_BGR565 AV_PIX_FMT_NE(BGR565BE, BGR565LE) +#define AV_PIX_FMT_BGR555 AV_PIX_FMT_NE(BGR555BE, BGR555LE) +#define AV_PIX_FMT_BGR444 AV_PIX_FMT_NE(BGR444BE, BGR444LE) +#define AV_PIX_FMT_BGRA64 AV_PIX_FMT_NE(BGRA64BE, BGRA64LE) + +#define AV_PIX_FMT_YUV420P9 AV_PIX_FMT_NE(YUV420P9BE , YUV420P9LE) +#define AV_PIX_FMT_YUV422P9 AV_PIX_FMT_NE(YUV422P9BE , YUV422P9LE) +#define AV_PIX_FMT_YUV444P9 AV_PIX_FMT_NE(YUV444P9BE , YUV444P9LE) +#define AV_PIX_FMT_YUV420P10 AV_PIX_FMT_NE(YUV420P10BE, YUV420P10LE) +#define AV_PIX_FMT_YUV422P10 AV_PIX_FMT_NE(YUV422P10BE, YUV422P10LE) +#define AV_PIX_FMT_YUV440P10 AV_PIX_FMT_NE(YUV440P10BE, YUV440P10LE) +#define AV_PIX_FMT_YUV444P10 AV_PIX_FMT_NE(YUV444P10BE, YUV444P10LE) +#define AV_PIX_FMT_YUV420P12 AV_PIX_FMT_NE(YUV420P12BE, YUV420P12LE) +#define AV_PIX_FMT_YUV422P12 AV_PIX_FMT_NE(YUV422P12BE, YUV422P12LE) +#define AV_PIX_FMT_YUV440P12 AV_PIX_FMT_NE(YUV440P12BE, YUV440P12LE) +#define AV_PIX_FMT_YUV444P12 AV_PIX_FMT_NE(YUV444P12BE, YUV444P12LE) +#define AV_PIX_FMT_YUV420P14 AV_PIX_FMT_NE(YUV420P14BE, YUV420P14LE) +#define AV_PIX_FMT_YUV422P14 AV_PIX_FMT_NE(YUV422P14BE, YUV422P14LE) +#define AV_PIX_FMT_YUV444P14 AV_PIX_FMT_NE(YUV444P14BE, YUV444P14LE) +#define AV_PIX_FMT_YUV420P16 AV_PIX_FMT_NE(YUV420P16BE, YUV420P16LE) +#define AV_PIX_FMT_YUV422P16 AV_PIX_FMT_NE(YUV422P16BE, YUV422P16LE) +#define AV_PIX_FMT_YUV444P16 AV_PIX_FMT_NE(YUV444P16BE, YUV444P16LE) + +#define AV_PIX_FMT_GBRP9 AV_PIX_FMT_NE(GBRP9BE , GBRP9LE) +#define AV_PIX_FMT_GBRP10 AV_PIX_FMT_NE(GBRP10BE, GBRP10LE) +#define AV_PIX_FMT_GBRP12 AV_PIX_FMT_NE(GBRP12BE, GBRP12LE) +#define AV_PIX_FMT_GBRP14 AV_PIX_FMT_NE(GBRP14BE, GBRP14LE) +#define AV_PIX_FMT_GBRP16 AV_PIX_FMT_NE(GBRP16BE, GBRP16LE) +#define AV_PIX_FMT_GBRAP10 AV_PIX_FMT_NE(GBRAP10BE, GBRAP10LE) +#define AV_PIX_FMT_GBRAP12 AV_PIX_FMT_NE(GBRAP12BE, GBRAP12LE) +#define AV_PIX_FMT_GBRAP16 AV_PIX_FMT_NE(GBRAP16BE, GBRAP16LE) + +#define AV_PIX_FMT_BAYER_BGGR16 AV_PIX_FMT_NE(BAYER_BGGR16BE, BAYER_BGGR16LE) +#define AV_PIX_FMT_BAYER_RGGB16 AV_PIX_FMT_NE(BAYER_RGGB16BE, BAYER_RGGB16LE) +#define AV_PIX_FMT_BAYER_GBRG16 AV_PIX_FMT_NE(BAYER_GBRG16BE, BAYER_GBRG16LE) +#define AV_PIX_FMT_BAYER_GRBG16 AV_PIX_FMT_NE(BAYER_GRBG16BE, BAYER_GRBG16LE) + +#define AV_PIX_FMT_GBRPF32 AV_PIX_FMT_NE(GBRPF32BE, GBRPF32LE) +#define AV_PIX_FMT_GBRAPF32 AV_PIX_FMT_NE(GBRAPF32BE, GBRAPF32LE) + +#define AV_PIX_FMT_GRAYF32 AV_PIX_FMT_NE(GRAYF32BE, GRAYF32LE) + +#define AV_PIX_FMT_YUVA420P9 AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE) +#define AV_PIX_FMT_YUVA422P9 AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE) +#define AV_PIX_FMT_YUVA444P9 AV_PIX_FMT_NE(YUVA444P9BE , YUVA444P9LE) +#define AV_PIX_FMT_YUVA420P10 AV_PIX_FMT_NE(YUVA420P10BE, YUVA420P10LE) +#define AV_PIX_FMT_YUVA422P10 AV_PIX_FMT_NE(YUVA422P10BE, YUVA422P10LE) +#define AV_PIX_FMT_YUVA444P10 AV_PIX_FMT_NE(YUVA444P10BE, YUVA444P10LE) +#define AV_PIX_FMT_YUVA422P12 AV_PIX_FMT_NE(YUVA422P12BE, YUVA422P12LE) +#define AV_PIX_FMT_YUVA444P12 AV_PIX_FMT_NE(YUVA444P12BE, YUVA444P12LE) +#define AV_PIX_FMT_YUVA420P16 AV_PIX_FMT_NE(YUVA420P16BE, YUVA420P16LE) +#define AV_PIX_FMT_YUVA422P16 AV_PIX_FMT_NE(YUVA422P16BE, YUVA422P16LE) +#define AV_PIX_FMT_YUVA444P16 AV_PIX_FMT_NE(YUVA444P16BE, YUVA444P16LE) + +#define AV_PIX_FMT_XYZ12 AV_PIX_FMT_NE(XYZ12BE, XYZ12LE) +#define AV_PIX_FMT_NV20 AV_PIX_FMT_NE(NV20BE, NV20LE) +#define AV_PIX_FMT_AYUV64 AV_PIX_FMT_NE(AYUV64BE, AYUV64LE) +#define AV_PIX_FMT_P010 AV_PIX_FMT_NE(P010BE, P010LE) +#define AV_PIX_FMT_P016 AV_PIX_FMT_NE(P016BE, P016LE) + +#define AV_PIX_FMT_Y210 AV_PIX_FMT_NE(Y210BE, Y210LE) +#define AV_PIX_FMT_X2RGB10 AV_PIX_FMT_NE(X2RGB10BE, X2RGB10LE) + +/** + * Chromaticity coordinates of the source primaries. + * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.1. + */ +enum AVColorPrimaries { + AVCOL_PRI_RESERVED0 = 0, + AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B + AVCOL_PRI_UNSPECIFIED = 2, + AVCOL_PRI_RESERVED = 3, + AVCOL_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + + AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + AVCOL_PRI_SMPTE240M = 7, ///< functionally identical to above + AVCOL_PRI_FILM = 8, ///< colour filters using Illuminant C + AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020 + AVCOL_PRI_SMPTE428 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ) + AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428, + AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) / DCI P3 + AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3 + AVCOL_PRI_EBU3213 = 22, ///< EBU Tech. 3213-E / JEDEC P22 phosphors + AVCOL_PRI_JEDEC_P22 = AVCOL_PRI_EBU3213, + AVCOL_PRI_NB ///< Not part of ABI +}; + +/** + * Color Transfer Characteristic. + * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.2. + */ +enum AVColorTransferCharacteristic { + AVCOL_TRC_RESERVED0 = 0, + AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361 + AVCOL_TRC_UNSPECIFIED = 2, + AVCOL_TRC_RESERVED = 3, + AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG + AVCOL_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC + AVCOL_TRC_SMPTE240M = 7, + AVCOL_TRC_LINEAR = 8, ///< "Linear transfer characteristics" + AVCOL_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)" + AVCOL_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" + AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4 + AVCOL_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut + AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC) + AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10-bit system + AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12-bit system + AVCOL_TRC_SMPTE2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084, + AVCOL_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1 + AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428, + AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma" + AVCOL_TRC_NB ///< Not part of ABI +}; + +/** + * YUV colorspace type. + * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.3. + */ +enum AVColorSpace { + AVCOL_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB) + AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B + AVCOL_SPC_UNSPECIFIED = 2, + AVCOL_SPC_RESERVED = 3, + AVCOL_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 + AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + AVCOL_SPC_SMPTE240M = 7, ///< functionally identical to above + AVCOL_SPC_YCGCO = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + AVCOL_SPC_YCOCG = AVCOL_SPC_YCGCO, + AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system + AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system + AVCOL_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x + AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system + AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system + AVCOL_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp + AVCOL_SPC_NB ///< Not part of ABI +}; + +/** + * Visual content value range. + * + * These values are based on definitions that can be found in multiple + * specifications, such as ITU-T BT.709 (3.4 - Quantization of RGB, luminance + * and colour-difference signals), ITU-T BT.2020 (Table 5 - Digital + * Representation) as well as ITU-T BT.2100 (Table 9 - Digital 10- and 12-bit + * integer representation). At the time of writing, the BT.2100 one is + * recommended, as it also defines the full range representation. + * + * Common definitions: + * - For RGB and luminance planes such as Y in YCbCr and I in ICtCp, + * 'E' is the original value in range of 0.0 to 1.0. + * - For chrominance planes such as Cb,Cr and Ct,Cp, 'E' is the original + * value in range of -0.5 to 0.5. + * - 'n' is the output bit depth. + * - For additional definitions such as rounding and clipping to valid n + * bit unsigned integer range, please refer to BT.2100 (Table 9). + */ +enum AVColorRange { + AVCOL_RANGE_UNSPECIFIED = 0, + + /** + * Narrow or limited range content. + * + * - For luminance planes: + * + * (219 * E + 16) * 2^(n-8) + * + * F.ex. the range of 16-235 for 8 bits + * + * - For chrominance planes: + * + * (224 * E + 128) * 2^(n-8) + * + * F.ex. the range of 16-240 for 8 bits + */ + AVCOL_RANGE_MPEG = 1, + + /** + * Full range content. + * + * - For RGB and luminance planes: + * + * (2^n - 1) * E + * + * F.ex. the range of 0-255 for 8 bits + * + * - For chrominance planes: + * + * (2^n - 1) * E + 2^(n - 1) + * + * F.ex. the range of 1-255 for 8 bits + */ + AVCOL_RANGE_JPEG = 2, + AVCOL_RANGE_NB ///< Not part of ABI +}; + +/** + * Location of chroma samples. + * + * Illustration showing the location of the first (top left) chroma sample of the + * image, the left shows only luma, the right + * shows the location of the chroma sample, the 2 could be imagined to overlay + * each other but are drawn separately due to limitations of ASCII + * + * 1st 2nd 1st 2nd horizontal luma sample positions + * v v v v + * ______ ______ + *1st luma line > |X X ... |3 4 X ... X are luma samples, + * | |1 2 1-6 are possible chroma positions + *2nd luma line > |X X ... |5 6 X ... 0 is undefined/unknown position + */ +enum AVChromaLocation { + AVCHROMA_LOC_UNSPECIFIED = 0, + AVCHROMA_LOC_LEFT = 1, ///< MPEG-2/4 4:2:0, H.264 default for 4:2:0 + AVCHROMA_LOC_CENTER = 2, ///< MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0 + AVCHROMA_LOC_TOPLEFT = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2 + AVCHROMA_LOC_TOP = 4, + AVCHROMA_LOC_BOTTOMLEFT = 5, + AVCHROMA_LOC_BOTTOM = 6, + AVCHROMA_LOC_NB ///< Not part of ABI +}; + +#endif /* AVUTIL_PIXFMT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/rational.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/rational.h new file mode 100644 index 0000000000000..cbb08a0baf16d --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/rational.h @@ -0,0 +1,220 @@ +/* + * rational numbers + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_math_rational + * Utilties for rational number calculation. + * @author Michael Niedermayer + */ + +#ifndef AVUTIL_RATIONAL_H +#define AVUTIL_RATIONAL_H + +#include +#include +#include "attributes.h" + +/** + * @defgroup lavu_math_rational AVRational + * @ingroup lavu_math + * Rational number calculation. + * + * While rational numbers can be expressed as floating-point numbers, the + * conversion process is a lossy one, so are floating-point operations. On the + * other hand, the nature of FFmpeg demands highly accurate calculation of + * timestamps. This set of rational number utilities serves as a generic + * interface for manipulating rational numbers as pairs of numerators and + * denominators. + * + * Many of the functions that operate on AVRational's have the suffix `_q`, in + * reference to the mathematical symbol "ℚ" (Q) which denotes the set of all + * rational numbers. + * + * @{ + */ + +/** + * Rational number (pair of numerator and denominator). + */ +typedef struct AVRational{ + int num; ///< Numerator + int den; ///< Denominator +} AVRational; + +/** + * Create an AVRational. + * + * Useful for compilers that do not support compound literals. + * + * @note The return value is not reduced. + * @see av_reduce() + */ +static inline AVRational av_make_q(int num, int den) +{ + AVRational r = { num, den }; + return r; +} + +/** + * Compare two rationals. + * + * @param a First rational + * @param b Second rational + * + * @return One of the following values: + * - 0 if `a == b` + * - 1 if `a > b` + * - -1 if `a < b` + * - `INT_MIN` if one of the values is of the form `0 / 0` + */ +static inline int av_cmp_q(AVRational a, AVRational b){ + const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den; + + if(tmp) return (int)((tmp ^ a.den ^ b.den)>>63)|1; + else if(b.den && a.den) return 0; + else if(a.num && b.num) return (a.num>>31) - (b.num>>31); + else return INT_MIN; +} + +/** + * Convert an AVRational to a `double`. + * @param a AVRational to convert + * @return `a` in floating-point form + * @see av_d2q() + */ +static inline double av_q2d(AVRational a){ + return a.num / (double) a.den; +} + +/** + * Reduce a fraction. + * + * This is useful for framerate calculations. + * + * @param[out] dst_num Destination numerator + * @param[out] dst_den Destination denominator + * @param[in] num Source numerator + * @param[in] den Source denominator + * @param[in] max Maximum allowed values for `dst_num` & `dst_den` + * @return 1 if the operation is exact, 0 otherwise + */ +int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max); + +/** + * Multiply two rationals. + * @param b First rational + * @param c Second rational + * @return b*c + */ +AVRational av_mul_q(AVRational b, AVRational c) av_const; + +/** + * Divide one rational by another. + * @param b First rational + * @param c Second rational + * @return b/c + */ +AVRational av_div_q(AVRational b, AVRational c) av_const; + +/** + * Add two rationals. + * @param b First rational + * @param c Second rational + * @return b+c + */ +AVRational av_add_q(AVRational b, AVRational c) av_const; + +/** + * Subtract one rational from another. + * @param b First rational + * @param c Second rational + * @return b-c + */ +AVRational av_sub_q(AVRational b, AVRational c) av_const; + +/** + * Invert a rational. + * @param q value + * @return 1 / q + */ +static av_always_inline AVRational av_inv_q(AVRational q) +{ + AVRational r = { q.den, q.num }; + return r; +} + +/** + * Convert a double precision floating point number to a rational. + * + * In case of infinity, the returned value is expressed as `{1, 0}` or + * `{-1, 0}` depending on the sign. + * + * @param d `double` to convert + * @param max Maximum allowed numerator and denominator + * @return `d` in AVRational form + * @see av_q2d() + */ +AVRational av_d2q(double d, int max) av_const; + +/** + * Find which of the two rationals is closer to another rational. + * + * @param q Rational to be compared against + * @param q1,q2 Rationals to be tested + * @return One of the following values: + * - 1 if `q1` is nearer to `q` than `q2` + * - -1 if `q2` is nearer to `q` than `q1` + * - 0 if they have the same distance + */ +int av_nearer_q(AVRational q, AVRational q1, AVRational q2); + +/** + * Find the value in a list of rationals nearest a given reference rational. + * + * @param q Reference rational + * @param q_list Array of rationals terminated by `{0, 0}` + * @return Index of the nearest value found in the array + */ +int av_find_nearest_q_idx(AVRational q, const AVRational* q_list); + +/** + * Convert an AVRational to a IEEE 32-bit `float` expressed in fixed-point + * format. + * + * @param q Rational to be converted + * @return Equivalent floating-point value, expressed as an unsigned 32-bit + * integer. + * @note The returned value is platform-indepedant. + */ +uint32_t av_q2intfloat(AVRational q); + +/** + * Return the best rational so that a and b are multiple of it. + * If the resulting denominator is larger than max_den, return def. + */ +AVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def); + +/** + * @} + */ + +#endif /* AVUTIL_RATIONAL_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/samplefmt.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/samplefmt.h new file mode 100644 index 0000000000000..8cd43ae8568a8 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/samplefmt.h @@ -0,0 +1,272 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_SAMPLEFMT_H +#define AVUTIL_SAMPLEFMT_H + +#include + +#include "avutil.h" +#include "attributes.h" + +/** + * @addtogroup lavu_audio + * @{ + * + * @defgroup lavu_sampfmts Audio sample formats + * + * Audio sample format enumeration and related convenience functions. + * @{ + */ + +/** + * Audio sample formats + * + * - The data described by the sample format is always in native-endian order. + * Sample values can be expressed by native C types, hence the lack of a signed + * 24-bit sample format even though it is a common raw audio data format. + * + * - The floating-point formats are based on full volume being in the range + * [-1.0, 1.0]. Any values outside this range are beyond full volume level. + * + * - The data layout as used in av_samples_fill_arrays() and elsewhere in FFmpeg + * (such as AVFrame in libavcodec) is as follows: + * + * @par + * For planar sample formats, each audio channel is in a separate data plane, + * and linesize is the buffer size, in bytes, for a single plane. All data + * planes must be the same size. For packed sample formats, only the first data + * plane is used, and samples for each channel are interleaved. In this case, + * linesize is the buffer size, in bytes, for the 1 plane. + * + */ +enum AVSampleFormat { + AV_SAMPLE_FMT_NONE = -1, + AV_SAMPLE_FMT_U8, ///< unsigned 8 bits + AV_SAMPLE_FMT_S16, ///< signed 16 bits + AV_SAMPLE_FMT_S32, ///< signed 32 bits + AV_SAMPLE_FMT_FLT, ///< float + AV_SAMPLE_FMT_DBL, ///< double + + AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar + AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar + AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar + AV_SAMPLE_FMT_FLTP, ///< float, planar + AV_SAMPLE_FMT_DBLP, ///< double, planar + AV_SAMPLE_FMT_S64, ///< signed 64 bits + AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar + + AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically +}; + +/** + * Return the name of sample_fmt, or NULL if sample_fmt is not + * recognized. + */ +const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt); + +/** + * Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE + * on error. + */ +enum AVSampleFormat av_get_sample_fmt(const char *name); + +/** + * Return the planar<->packed alternative form of the given sample format, or + * AV_SAMPLE_FMT_NONE on error. If the passed sample_fmt is already in the + * requested planar/packed format, the format returned is the same as the + * input. + */ +enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar); + +/** + * Get the packed alternative form of the given sample format. + * + * If the passed sample_fmt is already in packed format, the format returned is + * the same as the input. + * + * @return the packed alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Get the planar alternative form of the given sample format. + * + * If the passed sample_fmt is already in planar format, the format returned is + * the same as the input. + * + * @return the planar alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Generate a string corresponding to the sample format with + * sample_fmt, or a header if sample_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param sample_fmt the number of the sample format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + * @return the pointer to the filled buffer or NULL if sample_fmt is + * unknown or in case of other errors + */ +char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt); + +/** + * Return number of bytes per sample. + * + * @param sample_fmt the sample format + * @return number of bytes per sample or zero if unknown for the given + * sample format + */ +int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt); + +/** + * Check if the sample format is planar. + * + * @param sample_fmt the sample format to inspect + * @return 1 if the sample format is planar, 0 if it is interleaved + */ +int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt); + +/** + * Get the required buffer size for the given audio parameters. + * + * @param[out] linesize calculated linesize, may be NULL + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return required buffer size, or negative error code on failure + */ +int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * @} + * + * @defgroup lavu_sampmanip Samples manipulation + * + * Functions that manipulate audio samples + * @{ + */ + +/** + * Fill plane data pointers and linesize for samples with sample + * format sample_fmt. + * + * The audio_data array is filled with the pointers to the samples data planes: + * for planar, set the start point of each channel's data within the buffer, + * for packed, set the start point of the entire buffer only. + * + * The value pointed to by linesize is set to the aligned size of each + * channel's data buffer for planar layout, or to the aligned size of the + * buffer for all channels for packed layout. + * + * The buffer in buf must be big enough to contain all the samples + * (use av_samples_get_buffer_size() to compute its minimum size), + * otherwise the audio_data pointers will point to invalid data. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize calculated linesize, may be NULL + * @param buf the pointer to a buffer containing the samples + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return >=0 on success or a negative error code on failure + * @todo return minimum size in bytes required for the buffer in case + * of success at the next bump + */ +int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, + const uint8_t *buf, + int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a samples buffer for nb_samples samples, and fill data pointers and + * linesize accordingly. + * The allocated samples buffer can be freed by using av_freep(&audio_data[0]) + * Allocated data will be initialized to silence. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize aligned size for audio buffer(s), may be NULL + * @param nb_channels number of audio channels + * @param nb_samples number of samples per channel + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return >=0 on success or a negative error code on failure + * @todo return the size of the allocated buffer in case of success at the next bump + * @see av_samples_fill_arrays() + * @see av_samples_alloc_array_and_samples() + */ +int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a data pointers array, samples buffer for nb_samples + * samples, and fill data pointers and linesize accordingly. + * + * This is the same as av_samples_alloc(), but also allocates the data + * pointers array. + * + * @see av_samples_alloc() + */ +int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Copy samples from src to dst. + * + * @param dst destination array of pointers to data planes + * @param src source array of pointers to data planes + * @param dst_offset offset in samples at which the data will be written to dst + * @param src_offset offset in samples at which the data will be read from src + * @param nb_samples number of samples to be copied + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_copy(uint8_t **dst, uint8_t * const *src, int dst_offset, + int src_offset, int nb_samples, int nb_channels, + enum AVSampleFormat sample_fmt); + +/** + * Fill an audio buffer with silence. + * + * @param audio_data array of pointers to data planes + * @param offset offset in samples at which to start filling + * @param nb_samples number of samples to fill + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples, + int nb_channels, enum AVSampleFormat sample_fmt); + +/** + * @} + * @} + */ +#endif /* AVUTIL_SAMPLEFMT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/version.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/version.h new file mode 100644 index 0000000000000..f888dbb2dc12e --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/version.h @@ -0,0 +1,150 @@ +/* + * copyright (c) 2003 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu + * Libavutil version macros + */ + +#ifndef AVUTIL_VERSION_H +#define AVUTIL_VERSION_H + +#include "macros.h" + +/** + * @addtogroup version_utils + * + * Useful to check and match library version in order to maintain + * backward compatibility. + * + * The FFmpeg libraries follow a versioning sheme very similar to + * Semantic Versioning (http://semver.org/) + * The difference is that the component called PATCH is called MICRO in FFmpeg + * and its value is reset to 100 instead of 0 to keep it above or equal to 100. + * Also we do not increase MICRO for every bugfix or change in git master. + * + * Prior to FFmpeg 3.2 point releases did not change any lib version number to + * avoid aliassing different git master checkouts. + * Starting with FFmpeg 3.2, the released library versions will occupy + * a separate MAJOR.MINOR that is not used on the master development branch. + * That is if we branch a release of master 55.10.123 we will bump to 55.11.100 + * for the release and master will continue at 55.12.100 after it. Each new + * point release will then bump the MICRO improving the usefulness of the lib + * versions. + * + * @{ + */ + +#define AV_VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c)) +#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c +#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c) + +/** + * Extract version components from the full ::AV_VERSION_INT int as returned + * by functions like ::avformat_version() and ::avcodec_version() + */ +#define AV_VERSION_MAJOR(a) ((a) >> 16) +#define AV_VERSION_MINOR(a) (((a) & 0x00FF00) >> 8) +#define AV_VERSION_MICRO(a) ((a) & 0xFF) + +/** + * @} + */ + +/** + * @defgroup lavu_ver Version and Build diagnostics + * + * Macros and function useful to check at compiletime and at runtime + * which version of libavutil is in use. + * + * @{ + */ + +#define LIBAVUTIL_VERSION_MAJOR 56 +#define LIBAVUTIL_VERSION_MINOR 70 +#define LIBAVUTIL_VERSION_MICRO 100 + +#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT + +#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION) + +/** + * @defgroup lavu_depr_guards Deprecation Guards + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + * + * @{ + */ + +#ifndef FF_API_VAAPI +#define FF_API_VAAPI (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_FRAME_QP +#define FF_API_FRAME_QP (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_PLUS1_MINUS1 +#define FF_API_PLUS1_MINUS1 (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_ERROR_FRAME +#define FF_API_ERROR_FRAME (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_PKT_PTS +#define FF_API_PKT_PTS (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_CRYPTO_SIZE_T +#define FF_API_CRYPTO_SIZE_T (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_FRAME_GET_SET +#define FF_API_FRAME_GET_SET (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_PSEUDOPAL +#define FF_API_PSEUDOPAL (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_CHILD_CLASS_NEXT +#define FF_API_CHILD_CLASS_NEXT (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_BUFFER_SIZE_T +#define FF_API_BUFFER_SIZE_T (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_D2STR +#define FF_API_D2STR (LIBAVUTIL_VERSION_MAJOR < 58) +#endif +#ifndef FF_API_DECLARE_ALIGNED +#define FF_API_DECLARE_ALIGNED (LIBAVUTIL_VERSION_MAJOR < 58) +#endif + +/** + * @} + * @} + */ + +#endif /* AVUTIL_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libswscale/swscale.h b/src/framework/media/thirdparty/ffmpeg/v4/libswscale/swscale.h new file mode 100644 index 0000000000000..7713f51ec6629 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libswscale/swscale.h @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2001-2011 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_SWSCALE_H +#define SWSCALE_SWSCALE_H + +/** + * @file + * @ingroup libsws + * external API header + */ + +#include + +#include "libavutil/avutil.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "version.h" + +/** + * @defgroup libsws libswscale + * Color conversion and scaling library. + * + * @{ + * + * Return the LIBSWSCALE_VERSION_INT constant. + */ +unsigned swscale_version(void); + +/** + * Return the libswscale build-time configuration. + */ +const char *swscale_configuration(void); + +/** + * Return the libswscale license. + */ +const char *swscale_license(void); + +/* values for the flags, the stuff on the command line is different */ +#define SWS_FAST_BILINEAR 1 +#define SWS_BILINEAR 2 +#define SWS_BICUBIC 4 +#define SWS_X 8 +#define SWS_POINT 0x10 +#define SWS_AREA 0x20 +#define SWS_BICUBLIN 0x40 +#define SWS_GAUSS 0x80 +#define SWS_SINC 0x100 +#define SWS_LANCZOS 0x200 +#define SWS_SPLINE 0x400 + +#define SWS_SRC_V_CHR_DROP_MASK 0x30000 +#define SWS_SRC_V_CHR_DROP_SHIFT 16 + +#define SWS_PARAM_DEFAULT 123456 + +#define SWS_PRINT_INFO 0x1000 + +//the following 3 flags are not completely implemented +//internal chrominance subsampling info +#define SWS_FULL_CHR_H_INT 0x2000 +//input subsampling info +#define SWS_FULL_CHR_H_INP 0x4000 +#define SWS_DIRECT_BGR 0x8000 +#define SWS_ACCURATE_RND 0x40000 +#define SWS_BITEXACT 0x80000 +#define SWS_ERROR_DIFFUSION 0x800000 + +#define SWS_MAX_REDUCE_CUTOFF 0.002 + +#define SWS_CS_ITU709 1 +#define SWS_CS_FCC 4 +#define SWS_CS_ITU601 5 +#define SWS_CS_ITU624 5 +#define SWS_CS_SMPTE170M 5 +#define SWS_CS_SMPTE240M 7 +#define SWS_CS_DEFAULT 5 +#define SWS_CS_BT2020 9 + +/** + * Return a pointer to yuv<->rgb coefficients for the given colorspace + * suitable for sws_setColorspaceDetails(). + * + * @param colorspace One of the SWS_CS_* macros. If invalid, + * SWS_CS_DEFAULT is used. + */ +const int *sws_getCoefficients(int colorspace); + +// when used for filters they must have an odd number of elements +// coeffs cannot be shared between vectors +typedef struct SwsVector { + double *coeff; ///< pointer to the list of coefficients + int length; ///< number of coefficients in the vector +} SwsVector; + +// vectors can be shared +typedef struct SwsFilter { + SwsVector *lumH; + SwsVector *lumV; + SwsVector *chrH; + SwsVector *chrV; +} SwsFilter; + +struct SwsContext; + +/** + * Return a positive value if pix_fmt is a supported input format, 0 + * otherwise. + */ +int sws_isSupportedInput(enum AVPixelFormat pix_fmt); + +/** + * Return a positive value if pix_fmt is a supported output format, 0 + * otherwise. + */ +int sws_isSupportedOutput(enum AVPixelFormat pix_fmt); + +/** + * @param[in] pix_fmt the pixel format + * @return a positive value if an endianness conversion for pix_fmt is + * supported, 0 otherwise. + */ +int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt); + +/** + * Allocate an empty SwsContext. This must be filled and passed to + * sws_init_context(). For filling see AVOptions, options.c and + * sws_setColorspaceDetails(). + */ +struct SwsContext *sws_alloc_context(void); + +/** + * Initialize the swscaler context sws_context. + * + * @return zero or positive value on success, a negative value on + * error + */ +av_warn_unused_result +int sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter); + +/** + * Free the swscaler context swsContext. + * If swsContext is NULL, then does nothing. + */ +void sws_freeContext(struct SwsContext *swsContext); + +/** + * Allocate and return an SwsContext. You need it to perform + * scaling/conversion operations using sws_scale(). + * + * @param srcW the width of the source image + * @param srcH the height of the source image + * @param srcFormat the source image format + * @param dstW the width of the destination image + * @param dstH the height of the destination image + * @param dstFormat the destination image format + * @param flags specify which algorithm and options to use for rescaling + * @param param extra parameters to tune the used scaler + * For SWS_BICUBIC param[0] and [1] tune the shape of the basis + * function, param[0] tunes f(1) and param[1] f´(1) + * For SWS_GAUSS param[0] tunes the exponent and thus cutoff + * frequency + * For SWS_LANCZOS param[0] tunes the width of the window function + * @return a pointer to an allocated context, or NULL in case of error + * @note this function is to be removed after a saner alternative is + * written + */ +struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, + int dstW, int dstH, enum AVPixelFormat dstFormat, + int flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param); + +/** + * Scale the image slice in srcSlice and put the resulting scaled + * slice in the image in dst. A slice is a sequence of consecutive + * rows in an image. + * + * Slices have to be provided in sequential order, either in + * top-bottom or bottom-top order. If slices are provided in + * non-sequential order the behavior of the function is undefined. + * + * @param c the scaling context previously created with + * sws_getContext() + * @param srcSlice the array containing the pointers to the planes of + * the source slice + * @param srcStride the array containing the strides for each plane of + * the source image + * @param srcSliceY the position in the source image of the slice to + * process, that is the number (counted starting from + * zero) in the image of the first row of the slice + * @param srcSliceH the height of the source slice, that is the number + * of rows in the slice + * @param dst the array containing the pointers to the planes of + * the destination image + * @param dstStride the array containing the strides for each plane of + * the destination image + * @return the height of the output slice + */ +int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], + const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *const dst[], const int dstStride[]); + +/** + * @param dstRange flag indicating the while-black range of the output (1=jpeg / 0=mpeg) + * @param srcRange flag indicating the while-black range of the input (1=jpeg / 0=mpeg) + * @param table the yuv2rgb coefficients describing the output yuv space, normally ff_yuv2rgb_coeffs[x] + * @param inv_table the yuv2rgb coefficients describing the input yuv space, normally ff_yuv2rgb_coeffs[x] + * @param brightness 16.16 fixed point brightness correction + * @param contrast 16.16 fixed point contrast correction + * @param saturation 16.16 fixed point saturation correction + * @return -1 if not supported + */ +int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], + int srcRange, const int table[4], int dstRange, + int brightness, int contrast, int saturation); + +/** + * @return -1 if not supported + */ +int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table, + int *srcRange, int **table, int *dstRange, + int *brightness, int *contrast, int *saturation); + +/** + * Allocate and return an uninitialized vector with length coefficients. + */ +SwsVector *sws_allocVec(int length); + +/** + * Return a normalized Gaussian curve used to filter stuff + * quality = 3 is high quality, lower is lower quality. + */ +SwsVector *sws_getGaussianVec(double variance, double quality); + +/** + * Scale all the coefficients of a by the scalar value. + */ +void sws_scaleVec(SwsVector *a, double scalar); + +/** + * Scale all the coefficients of a so that their sum equals height. + */ +void sws_normalizeVec(SwsVector *a, double height); + +#if FF_API_SWS_VECTOR +attribute_deprecated SwsVector *sws_getConstVec(double c, int length); +attribute_deprecated SwsVector *sws_getIdentityVec(void); +attribute_deprecated void sws_convVec(SwsVector *a, SwsVector *b); +attribute_deprecated void sws_addVec(SwsVector *a, SwsVector *b); +attribute_deprecated void sws_subVec(SwsVector *a, SwsVector *b); +attribute_deprecated void sws_shiftVec(SwsVector *a, int shift); +attribute_deprecated SwsVector *sws_cloneVec(SwsVector *a); +attribute_deprecated void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level); +#endif + +void sws_freeVec(SwsVector *a); + +SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, + float lumaSharpen, float chromaSharpen, + float chromaHShift, float chromaVShift, + int verbose); +void sws_freeFilter(SwsFilter *filter); + +/** + * Check if context can be reused, otherwise reallocate a new one. + * + * If context is NULL, just calls sws_getContext() to get a new + * context. Otherwise, checks if the parameters are the ones already + * saved in context. If that is the case, returns the current + * context. Otherwise, frees context and gets a new context with + * the new parameters. + * + * Be warned that srcFilter and dstFilter are not checked, they + * are assumed to remain the same. + */ +struct SwsContext *sws_getCachedContext(struct SwsContext *context, + int srcW, int srcH, enum AVPixelFormat srcFormat, + int dstW, int dstH, enum AVPixelFormat dstFormat, + int flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 32 bits. + * + * The output frame will have the same packed format as the palette. + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 24 bits. + * + * With the palette format "ABCD", the destination frame ends up with the format "ABC". + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Get the AVClass for swsContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *sws_get_class(void); + +/** + * @} + */ + +#endif /* SWSCALE_SWSCALE_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libswscale/version.h b/src/framework/media/thirdparty/ffmpeg/v4/libswscale/version.h new file mode 100644 index 0000000000000..bc61201a87722 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libswscale/version.h @@ -0,0 +1,53 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_VERSION_H +#define SWSCALE_VERSION_H + +/** + * @file + * swscale version macros + */ + +#include "libavutil/version.h" + +#define LIBSWSCALE_VERSION_MAJOR 5 +#define LIBSWSCALE_VERSION_MINOR 9 +#define LIBSWSCALE_VERSION_MICRO 100 + +#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_VERSION AV_VERSION(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_BUILD LIBSWSCALE_VERSION_INT + +#define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION) + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + */ + +#ifndef FF_API_SWS_VECTOR +#define FF_API_SWS_VECTOR (LIBSWSCALE_VERSION_MAJOR < 6) +#endif + +#endif /* SWSCALE_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/avcodec.h b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/avcodec.h new file mode 100644 index 0000000000000..cb5c25bf631cb --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/avcodec.h @@ -0,0 +1,3169 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AVCODEC_H +#define AVCODEC_AVCODEC_H + +/** + * @file + * @ingroup libavc + * Libavcodec external API header + */ + +#include "libavutil/samplefmt.h" +#include "libavutil/attributes.h" +#include "libavutil/avutil.h" +#include "libavutil/buffer.h" +#include "libavutil/dict.h" +#include "libavutil/frame.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +#include "codec.h" +#include "codec_desc.h" +#include "codec_par.h" +#include "codec_id.h" +#include "defs.h" +#include "packet.h" +#include "version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "version.h" +#endif + +/** + * @defgroup libavc libavcodec + * Encoding/Decoding Library + * + * @{ + * + * @defgroup lavc_decoding Decoding + * @{ + * @} + * + * @defgroup lavc_encoding Encoding + * @{ + * @} + * + * @defgroup lavc_codec Codecs + * @{ + * @defgroup lavc_codec_native Native Codecs + * @{ + * @} + * @defgroup lavc_codec_wrappers External library wrappers + * @{ + * @} + * @defgroup lavc_codec_hwaccel Hardware Accelerators bridge + * @{ + * @} + * @} + * @defgroup lavc_internal Internal + * @{ + * @} + * @} + */ + +/** + * @ingroup libavc + * @defgroup lavc_encdec send/receive encoding and decoding API overview + * @{ + * + * The avcodec_send_packet()/avcodec_receive_frame()/avcodec_send_frame()/ + * avcodec_receive_packet() functions provide an encode/decode API, which + * decouples input and output. + * + * The API is very similar for encoding/decoding and audio/video, and works as + * follows: + * - Set up and open the AVCodecContext as usual. + * - Send valid input: + * - For decoding, call avcodec_send_packet() to give the decoder raw + * compressed data in an AVPacket. + * - For encoding, call avcodec_send_frame() to give the encoder an AVFrame + * containing uncompressed audio or video. + * + * In both cases, it is recommended that AVPackets and AVFrames are + * refcounted, or libavcodec might have to copy the input data. (libavformat + * always returns refcounted AVPackets, and av_frame_get_buffer() allocates + * refcounted AVFrames.) + * - Receive output in a loop. Periodically call one of the avcodec_receive_*() + * functions and process their output: + * - For decoding, call avcodec_receive_frame(). On success, it will return + * an AVFrame containing uncompressed audio or video data. + * - For encoding, call avcodec_receive_packet(). On success, it will return + * an AVPacket with a compressed frame. + * + * Repeat this call until it returns AVERROR(EAGAIN) or an error. The + * AVERROR(EAGAIN) return value means that new input data is required to + * return new output. In this case, continue with sending input. For each + * input frame/packet, the codec will typically return 1 output frame/packet, + * but it can also be 0 or more than 1. + * + * At the beginning of decoding or encoding, the codec might accept multiple + * input frames/packets without returning a frame, until its internal buffers + * are filled. This situation is handled transparently if you follow the steps + * outlined above. + * + * In theory, sending input can result in EAGAIN - this should happen only if + * not all output was received. You can use this to structure alternative decode + * or encode loops other than the one suggested above. For example, you could + * try sending new input on each iteration, and try to receive output if that + * returns EAGAIN. + * + * End of stream situations. These require "flushing" (aka draining) the codec, + * as the codec might buffer multiple frames or packets internally for + * performance or out of necessity (consider B-frames). + * This is handled as follows: + * - Instead of valid input, send NULL to the avcodec_send_packet() (decoding) + * or avcodec_send_frame() (encoding) functions. This will enter draining + * mode. + * - Call avcodec_receive_frame() (decoding) or avcodec_receive_packet() + * (encoding) in a loop until AVERROR_EOF is returned. The functions will + * not return AVERROR(EAGAIN), unless you forgot to enter draining mode. + * - Before decoding can be resumed again, the codec has to be reset with + * avcodec_flush_buffers(). + * + * Using the API as outlined above is highly recommended. But it is also + * possible to call functions outside of this rigid schema. For example, you can + * call avcodec_send_packet() repeatedly without calling + * avcodec_receive_frame(). In this case, avcodec_send_packet() will succeed + * until the codec's internal buffer has been filled up (which is typically of + * size 1 per output frame, after initial input), and then reject input with + * AVERROR(EAGAIN). Once it starts rejecting input, you have no choice but to + * read at least some output. + * + * Not all codecs will follow a rigid and predictable dataflow; the only + * guarantee is that an AVERROR(EAGAIN) return value on a send/receive call on + * one end implies that a receive/send call on the other end will succeed, or + * at least will not fail with AVERROR(EAGAIN). In general, no codec will + * permit unlimited buffering of input or output. + * + * A codec is not allowed to return AVERROR(EAGAIN) for both sending and receiving. This + * would be an invalid state, which could put the codec user into an endless + * loop. The API has no concept of time either: it cannot happen that trying to + * do avcodec_send_packet() results in AVERROR(EAGAIN), but a repeated call 1 second + * later accepts the packet (with no other receive/flush API calls involved). + * The API is a strict state machine, and the passage of time is not supposed + * to influence it. Some timing-dependent behavior might still be deemed + * acceptable in certain cases. But it must never result in both send/receive + * returning EAGAIN at the same time at any point. It must also absolutely be + * avoided that the current state is "unstable" and can "flip-flop" between + * the send/receive APIs allowing progress. For example, it's not allowed that + * the codec randomly decides that it actually wants to consume a packet now + * instead of returning a frame, after it just returned AVERROR(EAGAIN) on an + * avcodec_send_packet() call. + * @} + */ + +/** + * @defgroup lavc_core Core functions/structures. + * @ingroup libavc + * + * Basic definitions, functions for querying libavcodec capabilities, + * allocating core structures, etc. + * @{ + */ + +/** + * @ingroup lavc_encoding + * minimum encoding buffer size + * Used to avoid some checks during header writing. + */ +#define AV_INPUT_BUFFER_MIN_SIZE 16384 + +/** + * @ingroup lavc_encoding + */ +typedef struct RcOverride{ + int start_frame; + int end_frame; + int qscale; // If this is 0 then quality_factor will be used instead. + float quality_factor; +} RcOverride; + +/* encoding support + These flags can be passed in AVCodecContext.flags before initialization. + Note: Not everything is supported yet. +*/ + +/** + * Allow decoders to produce frames with data planes that are not aligned + * to CPU requirements (e.g. due to cropping). + */ +#define AV_CODEC_FLAG_UNALIGNED (1 << 0) +/** + * Use fixed qscale. + */ +#define AV_CODEC_FLAG_QSCALE (1 << 1) +/** + * 4 MV per MB allowed / advanced prediction for H.263. + */ +#define AV_CODEC_FLAG_4MV (1 << 2) +/** + * Output even those frames that might be corrupted. + */ +#define AV_CODEC_FLAG_OUTPUT_CORRUPT (1 << 3) +/** + * Use qpel MC. + */ +#define AV_CODEC_FLAG_QPEL (1 << 4) +/** + * Don't output frames whose parameters differ from first + * decoded frame in stream. + */ +#define AV_CODEC_FLAG_DROPCHANGED (1 << 5) +/** + * Use internal 2pass ratecontrol in first pass mode. + */ +#define AV_CODEC_FLAG_PASS1 (1 << 9) +/** + * Use internal 2pass ratecontrol in second pass mode. + */ +#define AV_CODEC_FLAG_PASS2 (1 << 10) +/** + * loop filter. + */ +#define AV_CODEC_FLAG_LOOP_FILTER (1 << 11) +/** + * Only decode/encode grayscale. + */ +#define AV_CODEC_FLAG_GRAY (1 << 13) +/** + * error[?] variables will be set during encoding. + */ +#define AV_CODEC_FLAG_PSNR (1 << 15) +#if FF_API_FLAG_TRUNCATED +/** + * Input bitstream might be truncated at a random location + * instead of only at frame boundaries. + * + * @deprecated use codec parsers for packetizing input + */ +#define AV_CODEC_FLAG_TRUNCATED (1 << 16) +#endif +/** + * Use interlaced DCT. + */ +#define AV_CODEC_FLAG_INTERLACED_DCT (1 << 18) +/** + * Force low delay. + */ +#define AV_CODEC_FLAG_LOW_DELAY (1 << 19) +/** + * Place global headers in extradata instead of every keyframe. + */ +#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22) +/** + * Use only bitexact stuff (except (I)DCT). + */ +#define AV_CODEC_FLAG_BITEXACT (1 << 23) +/* Fx : Flag for H.263+ extra options */ +/** + * H.263 advanced intra coding / MPEG-4 AC prediction + */ +#define AV_CODEC_FLAG_AC_PRED (1 << 24) +/** + * interlaced motion estimation + */ +#define AV_CODEC_FLAG_INTERLACED_ME (1 << 29) +#define AV_CODEC_FLAG_CLOSED_GOP (1U << 31) + +/** + * Allow non spec compliant speedup tricks. + */ +#define AV_CODEC_FLAG2_FAST (1 << 0) +/** + * Skip bitstream encoding. + */ +#define AV_CODEC_FLAG2_NO_OUTPUT (1 << 2) +/** + * Place global headers at every keyframe instead of in extradata. + */ +#define AV_CODEC_FLAG2_LOCAL_HEADER (1 << 3) + +/** + * timecode is in drop frame format. DEPRECATED!!!! + */ +#define AV_CODEC_FLAG2_DROP_FRAME_TIMECODE (1 << 13) + +/** + * Input bitstream might be truncated at a packet boundaries + * instead of only at frame boundaries. + */ +#define AV_CODEC_FLAG2_CHUNKS (1 << 15) +/** + * Discard cropping information from SPS. + */ +#define AV_CODEC_FLAG2_IGNORE_CROP (1 << 16) + +/** + * Show all frames before the first keyframe + */ +#define AV_CODEC_FLAG2_SHOW_ALL (1 << 22) +/** + * Export motion vectors through frame side data + */ +#define AV_CODEC_FLAG2_EXPORT_MVS (1 << 28) +/** + * Do not skip samples and export skip information as frame side data + */ +#define AV_CODEC_FLAG2_SKIP_MANUAL (1 << 29) +/** + * Do not reset ASS ReadOrder field on flush (subtitles decoding) + */ +#define AV_CODEC_FLAG2_RO_FLUSH_NOOP (1 << 30) + +/* Unsupported options : + * Syntax Arithmetic coding (SAC) + * Reference Picture Selection + * Independent Segment Decoding */ +/* /Fx */ +/* codec capabilities */ + +/* Exported side data. + These flags can be passed in AVCodecContext.export_side_data before initialization. +*/ +/** + * Export motion vectors through frame side data + */ +#define AV_CODEC_EXPORT_DATA_MVS (1 << 0) +/** + * Export encoder Producer Reference Time through packet side data + */ +#define AV_CODEC_EXPORT_DATA_PRFT (1 << 1) +/** + * Decoding only. + * Export the AVVideoEncParams structure through frame side data. + */ +#define AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS (1 << 2) +/** + * Decoding only. + * Do not apply film grain, export it instead. + */ +#define AV_CODEC_EXPORT_DATA_FILM_GRAIN (1 << 3) + +/** + * The decoder will keep a reference to the frame and may reuse it later. + */ +#define AV_GET_BUFFER_FLAG_REF (1 << 0) + +/** + * The encoder will keep a reference to the packet and may reuse it later. + */ +#define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0) + +struct AVCodecInternal; + +/** + * main external API structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * You can use AVOptions (av_opt* / av_set/get*()) to access these fields from user + * applications. + * The name string for AVOptions options matches the associated command line + * parameter name and can be found in libavcodec/options_table.h + * The AVOption/command line parameter names differ in some cases from the C + * structure field names for historic reasons or brevity. + * sizeof(AVCodecContext) must not be used outside libav*. + */ +typedef struct AVCodecContext { + /** + * information on struct for av_log + * - set by avcodec_alloc_context3 + */ + const AVClass *av_class; + int log_level_offset; + + enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ + const struct AVCodec *codec; + enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ + + /** + * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * This is used to work around some encoder bugs. + * A demuxer should set this to what is stored in the field used to identify the codec. + * If there are multiple such fields in a container then the demuxer should choose the one + * which maximizes the information about the used codec. + * If the codec tag field in a container is larger than 32 bits then the demuxer should + * remap the longer ID to 32 bits with a table or other structure. Alternatively a new + * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated + * first. + * - encoding: Set by user, if not then the default based on codec_id will be used. + * - decoding: Set by user, will be converted to uppercase by libavcodec during init. + */ + unsigned int codec_tag; + + void *priv_data; + + /** + * Private context used for internal data. + * + * Unlike priv_data, this is not codec-specific. It is used in general + * libavcodec functions. + */ + struct AVCodecInternal *internal; + + /** + * Private data of the user, can be used to carry app specific stuff. + * - encoding: Set by user. + * - decoding: Set by user. + */ + void *opaque; + + /** + * the average bitrate + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: Set by user, may be overwritten by libavcodec + * if this info is available in the stream + */ + int64_t bit_rate; + + /** + * number of bits the bitstream is allowed to diverge from the reference. + * the reference can be CBR (for CBR pass1) or VBR (for pass2) + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: unused + */ + int bit_rate_tolerance; + + /** + * Global quality for codecs which cannot change it per frame. + * This should be proportional to MPEG-1/2/4 qscale. + * - encoding: Set by user. + * - decoding: unused + */ + int global_quality; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int compression_level; +#define FF_COMPRESSION_DEFAULT -1 + + /** + * AV_CODEC_FLAG_*. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags; + + /** + * AV_CODEC_FLAG2_* + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags2; + + /** + * some codecs need / can use extradata like Huffman tables. + * MJPEG: Huffman tables + * rv10: additional flags + * MPEG-4: global headers (they can be in the bitstream or here) + * The allocated memory should be AV_INPUT_BUFFER_PADDING_SIZE bytes larger + * than extradata_size to avoid problems if it is read with the bitstream reader. + * The bytewise contents of extradata must not depend on the architecture or CPU endianness. + * Must be allocated with the av_malloc() family of functions. + * - encoding: Set/allocated/freed by libavcodec. + * - decoding: Set/allocated/freed by user. + */ + uint8_t *extradata; + int extradata_size; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. For fixed-fps content, + * timebase should be 1/framerate and timestamp increments should be + * identically 1. + * This often, but not always is the inverse of the frame rate or field rate + * for video. 1/time_base is not the average frame rate if the frame rate is not + * constant. + * + * Like containers, elementary streams also can store timestamps, 1/time_base + * is the unit in which these timestamps are specified. + * As example of such codec time base see ISO/IEC 14496-2:2001(E) + * vop_time_increment_resolution and fixed_vop_rate + * (fixed_vop_rate == 0 implies that it is different from the framerate) + * + * - encoding: MUST be set by user. + * - decoding: the use of this field for decoding is deprecated. + * Use framerate instead. + */ + AVRational time_base; + + /** + * For some codecs, the time base is closer to the field rate than the frame rate. + * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration + * if no telecine is used ... + * + * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. + */ + int ticks_per_frame; + + /** + * Codec delay. + * + * Encoding: Number of frames delay there will be from the encoder input to + * the decoder output. (we assume the decoder matches the spec) + * Decoding: Number of frames delay in addition to what a standard decoder + * as specified in the spec would produce. + * + * Video: + * Number of frames the decoded output will be delayed relative to the + * encoded input. + * + * Audio: + * For encoding, this field is unused (see initial_padding). + * + * For decoding, this is the number of samples the decoder needs to + * output before the decoder's output is valid. When seeking, you should + * start decoding this many samples prior to your desired seek point. + * + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int delay; + + + /* video only */ + /** + * picture width / height. + * + * @note Those fields may not match the values of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: MUST be set by user. + * - decoding: May be set by the user before opening the decoder if known e.g. + * from the container. Some decoders will require the dimensions + * to be set by the caller. During decoding, the decoder may + * overwrite those values as required while parsing the data. + */ + int width, height; + + /** + * Bitstream width / height, may be different from width/height e.g. when + * the decoded frame is cropped before being output or lowres is enabled. + * + * @note Those field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: unused + * - decoding: May be set by the user before opening the decoder if known + * e.g. from the container. During decoding, the decoder may + * overwrite those values as required while parsing the data. + */ + int coded_width, coded_height; + + /** + * the number of pictures in a group of pictures, or 0 for intra_only + * - encoding: Set by user. + * - decoding: unused + */ + int gop_size; + + /** + * Pixel format, see AV_PIX_FMT_xxx. + * May be set by the demuxer if known from headers. + * May be overridden by the decoder if it knows better. + * + * @note This field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: Set by user. + * - decoding: Set by user if known, overridden by libavcodec while + * parsing the data. + */ + enum AVPixelFormat pix_fmt; + + /** + * If non NULL, 'draw_horiz_band' is called by the libavcodec + * decoder to draw a horizontal band. It improves cache usage. Not + * all codecs can do that. You must check the codec capabilities + * beforehand. + * When multithreading is used, it may be called from multiple threads + * at the same time; threads might draw different parts of the same AVFrame, + * or multiple AVFrames, and there is no guarantee that slices will be drawn + * in order. + * The function is also used by hardware acceleration APIs. + * It is called at least once during frame decoding to pass + * the data needed for hardware render. + * In that mode instead of pixel data, AVFrame points to + * a structure specific to the acceleration API. The application + * reads the structure and can change some fields to indicate progress + * or mark state. + * - encoding: unused + * - decoding: Set by user. + * @param height the height of the slice + * @param y the y position of the slice + * @param type 1->top field, 2->bottom field, 3->frame + * @param offset offset into the AVFrame.data from which the slice should be read + */ + void (*draw_horiz_band)(struct AVCodecContext *s, + const AVFrame *src, int offset[AV_NUM_DATA_POINTERS], + int y, int type, int height); + + /** + * Callback to negotiate the pixel format. Decoding only, may be set by the + * caller before avcodec_open2(). + * + * Called by some decoders to select the pixel format that will be used for + * the output frames. This is mainly used to set up hardware acceleration, + * then the provided format list contains the corresponding hwaccel pixel + * formats alongside the "software" one. The software pixel format may also + * be retrieved from \ref sw_pix_fmt. + * + * This callback will be called when the coded frame properties (such as + * resolution, pixel format, etc.) change and more than one output format is + * supported for those new properties. If a hardware pixel format is chosen + * and initialization for it fails, the callback may be called again + * immediately. + * + * This callback may be called from different threads if the decoder is + * multi-threaded, but not from more than one thread simultaneously. + * + * @param fmt list of formats which may be used in the current + * configuration, terminated by AV_PIX_FMT_NONE. + * @warning Behavior is undefined if the callback returns a value other + * than one of the formats in fmt or AV_PIX_FMT_NONE. + * @return the chosen format or AV_PIX_FMT_NONE + */ + enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + + /** + * maximum number of B-frames between non-B-frames + * Note: The output will be delayed by max_b_frames+1 relative to the input. + * - encoding: Set by user. + * - decoding: unused + */ + int max_b_frames; + + /** + * qscale factor between IP and B-frames + * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_factor; + + /** + * qscale offset between IP and B-frames + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_offset; + + /** + * Size of the frame reordering buffer in the decoder. + * For MPEG-2 it is 1 IPB or 0 low delay IP. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int has_b_frames; + + /** + * qscale factor between P- and I-frames + * If > 0 then the last P-frame quantizer will be used (q = lastp_q * factor + offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_factor; + + /** + * qscale offset between P and I-frames + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_offset; + + /** + * luminance masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float lumi_masking; + + /** + * temporary complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float temporal_cplx_masking; + + /** + * spatial complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float spatial_cplx_masking; + + /** + * p block masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float p_masking; + + /** + * darkness masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float dark_masking; + + /** + * slice count + * - encoding: Set by libavcodec. + * - decoding: Set by user (or 0). + */ + int slice_count; + + /** + * slice offsets in the frame in bytes + * - encoding: Set/allocated by libavcodec. + * - decoding: Set/allocated by user (or NULL). + */ + int *slice_offset; + + /** + * sample aspect ratio (0 if unknown) + * That is the width of a pixel divided by the height of the pixel. + * Numerator and denominator must be relatively prime and smaller than 256 for some video standards. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVRational sample_aspect_ratio; + + /** + * motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_cmp; + /** + * subpixel motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_sub_cmp; + /** + * macroblock comparison function (not supported yet) + * - encoding: Set by user. + * - decoding: unused + */ + int mb_cmp; + /** + * interlaced DCT comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int ildct_cmp; +#define FF_CMP_SAD 0 +#define FF_CMP_SSE 1 +#define FF_CMP_SATD 2 +#define FF_CMP_DCT 3 +#define FF_CMP_PSNR 4 +#define FF_CMP_BIT 5 +#define FF_CMP_RD 6 +#define FF_CMP_ZERO 7 +#define FF_CMP_VSAD 8 +#define FF_CMP_VSSE 9 +#define FF_CMP_NSSE 10 +#define FF_CMP_W53 11 +#define FF_CMP_W97 12 +#define FF_CMP_DCTMAX 13 +#define FF_CMP_DCT264 14 +#define FF_CMP_MEDIAN_SAD 15 +#define FF_CMP_CHROMA 256 + + /** + * ME diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int dia_size; + + /** + * amount of previous MV predictors (2a+1 x 2a+1 square) + * - encoding: Set by user. + * - decoding: unused + */ + int last_predictor_count; + + /** + * motion estimation prepass comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_pre_cmp; + + /** + * ME prepass diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int pre_dia_size; + + /** + * subpel ME quality + * - encoding: Set by user. + * - decoding: unused + */ + int me_subpel_quality; + + /** + * maximum motion estimation search range in subpel units + * If 0 then no limit. + * + * - encoding: Set by user. + * - decoding: unused + */ + int me_range; + + /** + * slice flags + * - encoding: unused + * - decoding: Set by user. + */ + int slice_flags; +#define SLICE_FLAG_CODED_ORDER 0x0001 ///< draw_horiz_band() is called in coded order instead of display +#define SLICE_FLAG_ALLOW_FIELD 0x0002 ///< allow draw_horiz_band() with field slices (MPEG-2 field pics) +#define SLICE_FLAG_ALLOW_PLANE 0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1) + + /** + * macroblock decision mode + * - encoding: Set by user. + * - decoding: unused + */ + int mb_decision; +#define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp +#define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits +#define FF_MB_DECISION_RD 2 ///< rate distortion + + /** + * custom intra quantization matrix + * Must be allocated with the av_malloc() family of functions, and will be freed in + * avcodec_free_context(). + * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL. + * - decoding: Set/allocated/freed by libavcodec. + */ + uint16_t *intra_matrix; + + /** + * custom inter quantization matrix + * Must be allocated with the av_malloc() family of functions, and will be freed in + * avcodec_free_context(). + * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL. + * - decoding: Set/allocated/freed by libavcodec. + */ + uint16_t *inter_matrix; + + /** + * precision of the intra DC coefficient - 8 + * - encoding: Set by user. + * - decoding: Set by libavcodec + */ + int intra_dc_precision; + + /** + * Number of macroblock rows at the top which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_top; + + /** + * Number of macroblock rows at the bottom which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_bottom; + + /** + * minimum MB Lagrange multiplier + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmin; + + /** + * maximum MB Lagrange multiplier + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmax; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int bidir_refine; + + /** + * minimum GOP size + * - encoding: Set by user. + * - decoding: unused + */ + int keyint_min; + + /** + * number of reference frames + * - encoding: Set by user. + * - decoding: Set by lavc. + */ + int refs; + + /** + * Note: Value depends upon the compare function used for fullpel ME. + * - encoding: Set by user. + * - decoding: unused + */ + int mv0_threshold; + + /** + * Chromaticity coordinates of the source primaries. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorPrimaries color_primaries; + + /** + * Color Transfer Characteristic. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorRange color_range; + + /** + * This defines the location of chroma samples. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVChromaLocation chroma_sample_location; + + /** + * Number of slices. + * Indicates number of picture subdivisions. Used for parallelized + * decoding. + * - encoding: Set by user + * - decoding: unused + */ + int slices; + + /** Field order + * - encoding: set by libavcodec + * - decoding: Set by user. + */ + enum AVFieldOrder field_order; + + /* audio only */ + int sample_rate; ///< samples per second + +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * number of audio channels + * @deprecated use ch_layout.nb_channels + */ + attribute_deprecated + int channels; +#endif + + /** + * audio sample format + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVSampleFormat sample_fmt; ///< sample format + + /* The following data should not be initialized. */ + /** + * Number of samples per channel in an audio frame. + * + * - encoding: set by libavcodec in avcodec_open2(). Each submitted frame + * except the last must contain exactly frame_size samples per channel. + * May be 0 when the codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE set, then the + * frame size is not restricted. + * - decoding: may be set by some decoders to indicate constant frame size + */ + int frame_size; + + /** + * Frame counter, set by libavcodec. + * + * - decoding: total number of frames returned from the decoder so far. + * - encoding: total number of frames passed to the encoder so far. + * + * @note the counter is not incremented if encoding/decoding resulted in + * an error. + */ + int frame_number; + + /** + * number of bytes per packet if constant and known or 0 + * Used by some WAV based audio codecs. + */ + int block_align; + + /** + * Audio cutoff bandwidth (0 means "automatic") + * - encoding: Set by user. + * - decoding: unused + */ + int cutoff; + +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * Audio channel layout. + * - encoding: set by user. + * - decoding: set by user, may be overwritten by libavcodec. + * @deprecated use ch_layout + */ + attribute_deprecated + uint64_t channel_layout; + + /** + * Request decoder to use this channel layout if it can (0 for default) + * - encoding: unused + * - decoding: Set by user. + * @deprecated use "downmix" codec private option + */ + attribute_deprecated + uint64_t request_channel_layout; +#endif + + /** + * Type of service that the audio stream conveys. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVAudioServiceType audio_service_type; + + /** + * desired sample format + * - encoding: Not used. + * - decoding: Set by user. + * Decoder will decode to this format if it can. + */ + enum AVSampleFormat request_sample_fmt; + + /** + * This callback is called at the beginning of each frame to get data + * buffer(s) for it. There may be one contiguous buffer for all the data or + * there may be a buffer per each data plane or anything in between. What + * this means is, you may set however many entries in buf[] you feel necessary. + * Each buffer must be reference-counted using the AVBuffer API (see description + * of buf[] below). + * + * The following fields will be set in the frame before this callback is + * called: + * - format + * - width, height (video only) + * - sample_rate, channel_layout, nb_samples (audio only) + * Their values may differ from the corresponding values in + * AVCodecContext. This callback must use the frame values, not the codec + * context values, to calculate the required buffer size. + * + * This callback must fill the following fields in the frame: + * - data[] + * - linesize[] + * - extended_data: + * * if the data is planar audio with more than 8 channels, then this + * callback must allocate and fill extended_data to contain all pointers + * to all data planes. data[] must hold as many pointers as it can. + * extended_data must be allocated with av_malloc() and will be freed in + * av_frame_unref(). + * * otherwise extended_data must point to data + * - buf[] must contain one or more pointers to AVBufferRef structures. Each of + * the frame's data and extended_data pointers must be contained in these. That + * is, one AVBufferRef for each allocated chunk of memory, not necessarily one + * AVBufferRef per data[] entry. See: av_buffer_create(), av_buffer_alloc(), + * and av_buffer_ref(). + * - extended_buf and nb_extended_buf must be allocated with av_malloc() by + * this callback and filled with the extra buffers if there are more + * buffers than buf[] can hold. extended_buf will be freed in + * av_frame_unref(). + * + * If AV_CODEC_CAP_DR1 is not set then get_buffer2() must call + * avcodec_default_get_buffer2() instead of providing buffers allocated by + * some other means. + * + * Each data plane must be aligned to the maximum required by the target + * CPU. + * + * @see avcodec_default_get_buffer2() + * + * Video: + * + * If AV_GET_BUFFER_FLAG_REF is set in flags then the frame may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * avcodec_align_dimensions2() should be used to find the required width and + * height, as they normally need to be rounded up to the next multiple of 16. + * + * Some decoders do not support linesizes changing between frames. + * + * If frame multithreading is used, this callback may be called from a + * different thread, but not from more than one at once. Does not need to be + * reentrant. + * + * @see avcodec_align_dimensions2() + * + * Audio: + * + * Decoders request a buffer of a particular size by setting + * AVFrame.nb_samples prior to calling get_buffer2(). The decoder may, + * however, utilize only part of the buffer by setting AVFrame.nb_samples + * to a smaller value in the output frame. + * + * As a convenience, av_samples_get_buffer_size() and + * av_samples_fill_arrays() in libavutil may be used by custom get_buffer2() + * functions to find the required data size and to fill data pointers and + * linesize. In AVFrame.linesize, only linesize[0] may be set for audio + * since all planes must be the same size. + * + * @see av_samples_get_buffer_size(), av_samples_fill_arrays() + * + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + */ + int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags); + + /* - encoding parameters */ + float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0) + float qblur; ///< amount of qscale smoothing over time (0.0-1.0) + + /** + * minimum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmin; + + /** + * maximum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmax; + + /** + * maximum quantizer difference between frames + * - encoding: Set by user. + * - decoding: unused + */ + int max_qdiff; + + /** + * decoder bitstream buffer size + * - encoding: Set by user. + * - decoding: unused + */ + int rc_buffer_size; + + /** + * ratecontrol override, see RcOverride + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + int rc_override_count; + RcOverride *rc_override; + + /** + * maximum bitrate + * - encoding: Set by user. + * - decoding: Set by user, may be overwritten by libavcodec. + */ + int64_t rc_max_rate; + + /** + * minimum bitrate + * - encoding: Set by user. + * - decoding: unused + */ + int64_t rc_min_rate; + + /** + * Ratecontrol attempt to use, at maximum, of what can be used without an underflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_max_available_vbv_use; + + /** + * Ratecontrol attempt to use, at least, times the amount needed to prevent a vbv overflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_min_vbv_overflow_use; + + /** + * Number of bits which should be loaded into the rc buffer before decoding starts. + * - encoding: Set by user. + * - decoding: unused + */ + int rc_initial_buffer_occupancy; + + /** + * trellis RD quantization + * - encoding: Set by user. + * - decoding: unused + */ + int trellis; + + /** + * pass1 encoding statistics output buffer + * - encoding: Set by libavcodec. + * - decoding: unused + */ + char *stats_out; + + /** + * pass2 encoding statistics input buffer + * Concatenated stuff from stats_out of pass1 should be placed here. + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + char *stats_in; + + /** + * Work around bugs in encoders which sometimes cannot be detected automatically. + * - encoding: Set by user + * - decoding: Set by user + */ + int workaround_bugs; +#define FF_BUG_AUTODETECT 1 ///< autodetection +#define FF_BUG_XVID_ILACE 4 +#define FF_BUG_UMP4 8 +#define FF_BUG_NO_PADDING 16 +#define FF_BUG_AMV 32 +#define FF_BUG_QPEL_CHROMA 64 +#define FF_BUG_STD_QPEL 128 +#define FF_BUG_QPEL_CHROMA2 256 +#define FF_BUG_DIRECT_BLOCKSIZE 512 +#define FF_BUG_EDGE 1024 +#define FF_BUG_HPEL_CHROMA 2048 +#define FF_BUG_DC_CLIP 4096 +#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders. +#define FF_BUG_TRUNCATED 16384 +#define FF_BUG_IEDGE 32768 + + /** + * strictly follow the standard (MPEG-4, ...). + * - encoding: Set by user. + * - decoding: Set by user. + * Setting this to STRICT or higher means the encoder and decoder will + * generally do stupid things, whereas setting it to unofficial or lower + * will mean the encoder might produce output that is not supported by all + * spec-compliant decoders. Decoders don't differentiate between normal, + * unofficial and experimental (that is, they always try to decode things + * when they can) unless they are explicitly asked to behave stupidly + * (=strictly conform to the specs) + */ + int strict_std_compliance; +#define FF_COMPLIANCE_VERY_STRICT 2 ///< Strictly conform to an older more strict version of the spec or reference software. +#define FF_COMPLIANCE_STRICT 1 ///< Strictly conform to all the things in the spec no matter what consequences. +#define FF_COMPLIANCE_NORMAL 0 +#define FF_COMPLIANCE_UNOFFICIAL -1 ///< Allow unofficial extensions +#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things. + + /** + * error concealment flags + * - encoding: unused + * - decoding: Set by user. + */ + int error_concealment; +#define FF_EC_GUESS_MVS 1 +#define FF_EC_DEBLOCK 2 +#define FF_EC_FAVOR_INTER 256 + + /** + * debug + * - encoding: Set by user. + * - decoding: Set by user. + */ + int debug; +#define FF_DEBUG_PICT_INFO 1 +#define FF_DEBUG_RC 2 +#define FF_DEBUG_BITSTREAM 4 +#define FF_DEBUG_MB_TYPE 8 +#define FF_DEBUG_QP 16 +#define FF_DEBUG_DCT_COEFF 0x00000040 +#define FF_DEBUG_SKIP 0x00000080 +#define FF_DEBUG_STARTCODE 0x00000100 +#define FF_DEBUG_ER 0x00000400 +#define FF_DEBUG_MMCO 0x00000800 +#define FF_DEBUG_BUGS 0x00001000 +#define FF_DEBUG_BUFFERS 0x00008000 +#define FF_DEBUG_THREADS 0x00010000 +#define FF_DEBUG_GREEN_MD 0x00800000 +#define FF_DEBUG_NOMC 0x01000000 + + /** + * Error recognition; may misdetect some more or less valid parts as errors. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int err_recognition; + +/** + * Verify checksums embedded in the bitstream (could be of either encoded or + * decoded data, depending on the codec) and print an error message on mismatch. + * If AV_EF_EXPLODE is also set, a mismatching checksum will result in the + * decoder returning an error. + */ +#define AV_EF_CRCCHECK (1<<0) +#define AV_EF_BITSTREAM (1<<1) ///< detect bitstream specification deviations +#define AV_EF_BUFFER (1<<2) ///< detect improper bitstream length +#define AV_EF_EXPLODE (1<<3) ///< abort decoding on minor error detection + +#define AV_EF_IGNORE_ERR (1<<15) ///< ignore errors and continue +#define AV_EF_CAREFUL (1<<16) ///< consider things that violate the spec, are fast to calculate and have not been seen in the wild as errors +#define AV_EF_COMPLIANT (1<<17) ///< consider all spec non compliances as errors +#define AV_EF_AGGRESSIVE (1<<18) ///< consider things that a sane encoder should not do as an error + + + /** + * opaque 64-bit number (generally a PTS) that will be reordered and + * output in AVFrame.reordered_opaque + * - encoding: Set by libavcodec to the reordered_opaque of the input + * frame corresponding to the last returned packet. Only + * supported by encoders with the + * AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability. + * - decoding: Set by user. + */ + int64_t reordered_opaque; + + /** + * Hardware accelerator in use + * - encoding: unused. + * - decoding: Set by libavcodec + */ + const struct AVHWAccel *hwaccel; + + /** + * Hardware accelerator context. + * For some hardware accelerators, a global context needs to be + * provided by the user. In that case, this holds display-dependent + * data FFmpeg cannot instantiate itself. Please refer to the + * FFmpeg HW accelerator documentation to know how to fill this. + * - encoding: unused + * - decoding: Set by user + */ + void *hwaccel_context; + + /** + * error + * - encoding: Set by libavcodec if flags & AV_CODEC_FLAG_PSNR. + * - decoding: unused + */ + uint64_t error[AV_NUM_DATA_POINTERS]; + + /** + * DCT algorithm, see FF_DCT_* below + * - encoding: Set by user. + * - decoding: unused + */ + int dct_algo; +#define FF_DCT_AUTO 0 +#define FF_DCT_FASTINT 1 +#define FF_DCT_INT 2 +#define FF_DCT_MMX 3 +#define FF_DCT_ALTIVEC 5 +#define FF_DCT_FAAN 6 + + /** + * IDCT algorithm, see FF_IDCT_* below. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int idct_algo; +#define FF_IDCT_AUTO 0 +#define FF_IDCT_INT 1 +#define FF_IDCT_SIMPLE 2 +#define FF_IDCT_SIMPLEMMX 3 +#define FF_IDCT_ARM 7 +#define FF_IDCT_ALTIVEC 8 +#define FF_IDCT_SIMPLEARM 10 +#define FF_IDCT_XVID 14 +#define FF_IDCT_SIMPLEARMV5TE 16 +#define FF_IDCT_SIMPLEARMV6 17 +#define FF_IDCT_FAAN 20 +#define FF_IDCT_SIMPLENEON 22 +#if FF_API_IDCT_NONE +// formerly used by xvmc +#define FF_IDCT_NONE 24 +#endif +#define FF_IDCT_SIMPLEAUTO 128 + + /** + * bits per sample/pixel from the demuxer (needed for huffyuv). + * - encoding: Set by libavcodec. + * - decoding: Set by user. + */ + int bits_per_coded_sample; + + /** + * Bits per sample/pixel of internal libavcodec pixel/sample format. + * - encoding: set by user. + * - decoding: set by libavcodec. + */ + int bits_per_raw_sample; + + /** + * low resolution decoding, 1-> 1/2 size, 2->1/4 size + * - encoding: unused + * - decoding: Set by user. + */ + int lowres; + + /** + * thread count + * is used to decide how many independent tasks should be passed to execute() + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_count; + + /** + * Which multithreading methods to use. + * Use of FF_THREAD_FRAME will increase decoding delay by one frame per thread, + * so clients which cannot provide future frames should not use it. + * + * - encoding: Set by user, otherwise the default is used. + * - decoding: Set by user, otherwise the default is used. + */ + int thread_type; +#define FF_THREAD_FRAME 1 ///< Decode more than one frame at once +#define FF_THREAD_SLICE 2 ///< Decode more than one part of a single frame at once + + /** + * Which multithreading methods are in use by the codec. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int active_thread_type; + +#if FF_API_THREAD_SAFE_CALLBACKS + /** + * Set by the client if its custom get_buffer() callback can be called + * synchronously from another thread, which allows faster multithreaded decoding. + * draw_horiz_band() will be called from other threads regardless of this setting. + * Ignored if the default get_buffer() is used. + * - encoding: Set by user. + * - decoding: Set by user. + * + * @deprecated the custom get_buffer2() callback should always be + * thread-safe. Thread-unsafe get_buffer2() implementations will be + * invalid starting with LIBAVCODEC_VERSION_MAJOR=60; in other words, + * libavcodec will behave as if this field was always set to 1. + * Callers that want to be forward compatible with future libavcodec + * versions should wrap access to this field in + * #if LIBAVCODEC_VERSION_MAJOR < 60 + */ + attribute_deprecated + int thread_safe_callbacks; +#endif + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param count the number of things to execute + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size); + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param c context passed also to func + * @param count the number of things to execute + * @param arg2 argument passed unchanged to func + * @param ret return values of executed functions, must have space for "count" values. May be NULL. + * @param func function that will be called count times, with jobnr from 0 to count-1. + * threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no + * two instances of func executing at the same time will have the same threadnr. + * @return always 0 currently, but code should handle a future improvement where when any call to func + * returns < 0 no further calls to func may be done and < 0 is returned. + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count); + + /** + * noise vs. sse weight for the nsse comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int nsse_weight; + + /** + * profile + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int profile; +#define FF_PROFILE_UNKNOWN -99 +#define FF_PROFILE_RESERVED -100 + +#define FF_PROFILE_AAC_MAIN 0 +#define FF_PROFILE_AAC_LOW 1 +#define FF_PROFILE_AAC_SSR 2 +#define FF_PROFILE_AAC_LTP 3 +#define FF_PROFILE_AAC_HE 4 +#define FF_PROFILE_AAC_HE_V2 28 +#define FF_PROFILE_AAC_LD 22 +#define FF_PROFILE_AAC_ELD 38 +#define FF_PROFILE_MPEG2_AAC_LOW 128 +#define FF_PROFILE_MPEG2_AAC_HE 131 + +#define FF_PROFILE_DNXHD 0 +#define FF_PROFILE_DNXHR_LB 1 +#define FF_PROFILE_DNXHR_SQ 2 +#define FF_PROFILE_DNXHR_HQ 3 +#define FF_PROFILE_DNXHR_HQX 4 +#define FF_PROFILE_DNXHR_444 5 + +#define FF_PROFILE_DTS 20 +#define FF_PROFILE_DTS_ES 30 +#define FF_PROFILE_DTS_96_24 40 +#define FF_PROFILE_DTS_HD_HRA 50 +#define FF_PROFILE_DTS_HD_MA 60 +#define FF_PROFILE_DTS_EXPRESS 70 + +#define FF_PROFILE_MPEG2_422 0 +#define FF_PROFILE_MPEG2_HIGH 1 +#define FF_PROFILE_MPEG2_SS 2 +#define FF_PROFILE_MPEG2_SNR_SCALABLE 3 +#define FF_PROFILE_MPEG2_MAIN 4 +#define FF_PROFILE_MPEG2_SIMPLE 5 + +#define FF_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag +#define FF_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag + +#define FF_PROFILE_H264_BASELINE 66 +#define FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED) +#define FF_PROFILE_H264_MAIN 77 +#define FF_PROFILE_H264_EXTENDED 88 +#define FF_PROFILE_H264_HIGH 100 +#define FF_PROFILE_H264_HIGH_10 110 +#define FF_PROFILE_H264_HIGH_10_INTRA (110|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_MULTIVIEW_HIGH 118 +#define FF_PROFILE_H264_HIGH_422 122 +#define FF_PROFILE_H264_HIGH_422_INTRA (122|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_STEREO_HIGH 128 +#define FF_PROFILE_H264_HIGH_444 144 +#define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244 +#define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_CAVLC_444 44 + +#define FF_PROFILE_VC1_SIMPLE 0 +#define FF_PROFILE_VC1_MAIN 1 +#define FF_PROFILE_VC1_COMPLEX 2 +#define FF_PROFILE_VC1_ADVANCED 3 + +#define FF_PROFILE_MPEG4_SIMPLE 0 +#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE 1 +#define FF_PROFILE_MPEG4_CORE 2 +#define FF_PROFILE_MPEG4_MAIN 3 +#define FF_PROFILE_MPEG4_N_BIT 4 +#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE 5 +#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6 +#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7 +#define FF_PROFILE_MPEG4_HYBRID 8 +#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME 9 +#define FF_PROFILE_MPEG4_CORE_SCALABLE 10 +#define FF_PROFILE_MPEG4_ADVANCED_CODING 11 +#define FF_PROFILE_MPEG4_ADVANCED_CORE 12 +#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13 +#define FF_PROFILE_MPEG4_SIMPLE_STUDIO 14 +#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE 15 + +#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 1 +#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 2 +#define FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION 32768 +#define FF_PROFILE_JPEG2000_DCINEMA_2K 3 +#define FF_PROFILE_JPEG2000_DCINEMA_4K 4 + +#define FF_PROFILE_VP9_0 0 +#define FF_PROFILE_VP9_1 1 +#define FF_PROFILE_VP9_2 2 +#define FF_PROFILE_VP9_3 3 + +#define FF_PROFILE_HEVC_MAIN 1 +#define FF_PROFILE_HEVC_MAIN_10 2 +#define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 +#define FF_PROFILE_HEVC_REXT 4 + +#define FF_PROFILE_VVC_MAIN_10 1 +#define FF_PROFILE_VVC_MAIN_10_444 33 + +#define FF_PROFILE_AV1_MAIN 0 +#define FF_PROFILE_AV1_HIGH 1 +#define FF_PROFILE_AV1_PROFESSIONAL 2 + +#define FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT 0xc0 +#define FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1 +#define FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT 0xc2 +#define FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3 +#define FF_PROFILE_MJPEG_JPEG_LS 0xf7 + +#define FF_PROFILE_SBC_MSBC 1 + +#define FF_PROFILE_PRORES_PROXY 0 +#define FF_PROFILE_PRORES_LT 1 +#define FF_PROFILE_PRORES_STANDARD 2 +#define FF_PROFILE_PRORES_HQ 3 +#define FF_PROFILE_PRORES_4444 4 +#define FF_PROFILE_PRORES_XQ 5 + +#define FF_PROFILE_ARIB_PROFILE_A 0 +#define FF_PROFILE_ARIB_PROFILE_C 1 + +#define FF_PROFILE_KLVA_SYNC 0 +#define FF_PROFILE_KLVA_ASYNC 1 + + /** + * level + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int level; +#define FF_LEVEL_UNKNOWN -99 + + /** + * Skip loop filtering for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_loop_filter; + + /** + * Skip IDCT/dequantization for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_idct; + + /** + * Skip decoding for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_frame; + + /** + * Header containing style information for text subtitles. + * For SUBTITLE_ASS subtitle type, it should contain the whole ASS + * [Script Info] and [V4+ Styles] section, plus the [Events] line and + * the Format line following. It shouldn't include any Dialogue line. + * - encoding: Set/allocated/freed by user (before avcodec_open2()) + * - decoding: Set/allocated/freed by libavcodec (by avcodec_open2()) + */ + uint8_t *subtitle_header; + int subtitle_header_size; + + /** + * Audio only. The number of "priming" samples (padding) inserted by the + * encoder at the beginning of the audio. I.e. this number of leading + * decoded samples must be discarded by the caller to get the original audio + * without leading padding. + * + * - decoding: unused + * - encoding: Set by libavcodec. The timestamps on the output packets are + * adjusted by the encoder so that they always refer to the + * first sample of the data actually contained in the packet, + * including any added padding. E.g. if the timebase is + * 1/samplerate and the timestamp of the first input sample is + * 0, the timestamp of the first output packet will be + * -initial_padding. + */ + int initial_padding; + + /** + * - decoding: For codecs that store a framerate value in the compressed + * bitstream, the decoder may export it here. { 0, 1} when + * unknown. + * - encoding: May be used to signal the framerate of CFR content to an + * encoder. + */ + AVRational framerate; + + /** + * Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx. + * - encoding: unused. + * - decoding: Set by libavcodec before calling get_format() + */ + enum AVPixelFormat sw_pix_fmt; + + /** + * Timebase in which pkt_dts/pts and AVPacket.dts/pts are. + * - encoding unused. + * - decoding set by user. + */ + AVRational pkt_timebase; + + /** + * AVCodecDescriptor + * - encoding: unused. + * - decoding: set by libavcodec. + */ + const AVCodecDescriptor *codec_descriptor; + + /** + * Current statistics for PTS correction. + * - decoding: maintained and used by libavcodec, not intended to be used by user apps + * - encoding: unused + */ + int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far + int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far + int64_t pts_correction_last_pts; /// PTS of the last frame + int64_t pts_correction_last_dts; /// DTS of the last frame + + /** + * Character encoding of the input subtitles file. + * - decoding: set by user + * - encoding: unused + */ + char *sub_charenc; + + /** + * Subtitles character encoding mode. Formats or codecs might be adjusting + * this setting (if they are doing the conversion themselves for instance). + * - decoding: set by libavcodec + * - encoding: unused + */ + int sub_charenc_mode; +#define FF_SUB_CHARENC_MODE_DO_NOTHING -1 ///< do nothing (demuxer outputs a stream supposed to be already in UTF-8, or the codec is bitmap for instance) +#define FF_SUB_CHARENC_MODE_AUTOMATIC 0 ///< libavcodec will select the mode itself +#define FF_SUB_CHARENC_MODE_PRE_DECODER 1 ///< the AVPacket data needs to be recoded to UTF-8 before being fed to the decoder, requires iconv +#define FF_SUB_CHARENC_MODE_IGNORE 2 ///< neither convert the subtitles, nor check them for valid UTF-8 + + /** + * Skip processing alpha if supported by codec. + * Note that if the format uses pre-multiplied alpha (common with VP6, + * and recommended due to better video quality/compression) + * the image will look as if alpha-blended onto a black background. + * However for formats that do not use pre-multiplied alpha + * there might be serious artefacts (though e.g. libswscale currently + * assumes pre-multiplied alpha anyway). + * + * - decoding: set by user + * - encoding: unused + */ + int skip_alpha; + + /** + * Number of samples to skip after a discontinuity + * - decoding: unused + * - encoding: set by libavcodec + */ + int seek_preroll; + +#if FF_API_DEBUG_MV + /** + * @deprecated unused + */ + attribute_deprecated + int debug_mv; +#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 //visualize forward predicted MVs of P frames +#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 //visualize forward predicted MVs of B frames +#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames +#endif + + /** + * custom intra quantization matrix + * - encoding: Set by user, can be NULL. + * - decoding: unused. + */ + uint16_t *chroma_intra_matrix; + + /** + * dump format separator. + * can be ", " or "\n " or anything else + * - encoding: Set by user. + * - decoding: Set by user. + */ + uint8_t *dump_separator; + + /** + * ',' separated list of allowed decoders. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *codec_whitelist; + + /** + * Properties of the stream that gets decoded + * - encoding: unused + * - decoding: set by libavcodec + */ + unsigned properties; +#define FF_CODEC_PROPERTY_LOSSLESS 0x00000001 +#define FF_CODEC_PROPERTY_CLOSED_CAPTIONS 0x00000002 +#define FF_CODEC_PROPERTY_FILM_GRAIN 0x00000004 + + /** + * Additional data associated with the entire coded stream. + * + * - decoding: unused + * - encoding: may be set by libavcodec after avcodec_open2(). + */ + AVPacketSideData *coded_side_data; + int nb_coded_side_data; + + /** + * A reference to the AVHWFramesContext describing the input (for encoding) + * or output (decoding) frames. The reference is set by the caller and + * afterwards owned (and freed) by libavcodec - it should never be read by + * the caller after being set. + * + * - decoding: This field should be set by the caller from the get_format() + * callback. The previous reference (if any) will always be + * unreffed by libavcodec before the get_format() call. + * + * If the default get_buffer2() is used with a hwaccel pixel + * format, then this AVHWFramesContext will be used for + * allocating the frame buffers. + * + * - encoding: For hardware encoders configured to use a hwaccel pixel + * format, this field should be set by the caller to a reference + * to the AVHWFramesContext describing input frames. + * AVHWFramesContext.format must be equal to + * AVCodecContext.pix_fmt. + * + * This field should be set before avcodec_open2() is called. + */ + AVBufferRef *hw_frames_ctx; + +#if FF_API_SUB_TEXT_FORMAT + /** + * @deprecated unused + */ + attribute_deprecated + int sub_text_format; +#define FF_SUB_TEXT_FMT_ASS 0 +#endif + + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + * + * - decoding: unused + * - encoding: unused + */ + int trailing_padding; + + /** + * The number of pixels per image to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_pixels; + + /** + * A reference to the AVHWDeviceContext describing the device which will + * be used by a hardware encoder/decoder. The reference is set by the + * caller and afterwards owned (and freed) by libavcodec. + * + * This should be used if either the codec device does not require + * hardware frames or any that are used are to be allocated internally by + * libavcodec. If the user wishes to supply any of the frames used as + * encoder input or decoder output then hw_frames_ctx should be used + * instead. When hw_frames_ctx is set in get_format() for a decoder, this + * field will be ignored while decoding the associated stream segment, but + * may again be used on a following one after another get_format() call. + * + * For both encoders and decoders this field should be set before + * avcodec_open2() is called and must not be written to thereafter. + * + * Note that some decoders may require this field to be set initially in + * order to support hw_frames_ctx at all - in that case, all frames + * contexts used must be created on the same device. + */ + AVBufferRef *hw_device_ctx; + + /** + * Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated + * decoding (if active). + * - encoding: unused + * - decoding: Set by user (either before avcodec_open2(), or in the + * AVCodecContext.get_format callback) + */ + int hwaccel_flags; + + /** + * Video decoding only. Certain video codecs support cropping, meaning that + * only a sub-rectangle of the decoded frame is intended for display. This + * option controls how cropping is handled by libavcodec. + * + * When set to 1 (the default), libavcodec will apply cropping internally. + * I.e. it will modify the output frame width/height fields and offset the + * data pointers (only by as much as possible while preserving alignment, or + * by the full amount if the AV_CODEC_FLAG_UNALIGNED flag is set) so that + * the frames output by the decoder refer only to the cropped area. The + * crop_* fields of the output frames will be zero. + * + * When set to 0, the width/height fields of the output frames will be set + * to the coded dimensions and the crop_* fields will describe the cropping + * rectangle. Applying the cropping is left to the caller. + * + * @warning When hardware acceleration with opaque output frames is used, + * libavcodec is unable to apply cropping from the top/left border. + * + * @note when this option is set to zero, the width/height fields of the + * AVCodecContext and output AVFrames have different meanings. The codec + * context fields store display dimensions (with the coded dimensions in + * coded_width/height), while the frame fields store the coded dimensions + * (with the display dimensions being determined by the crop_* fields). + */ + int apply_cropping; + + /* + * Video decoding only. Sets the number of extra hardware frames which + * the decoder will allocate for use by the caller. This must be set + * before avcodec_open2() is called. + * + * Some hardware decoders require all frames that they will use for + * output to be defined in advance before decoding starts. For such + * decoders, the hardware frame pool must therefore be of a fixed size. + * The extra frames set here are on top of any number that the decoder + * needs internally in order to operate normally (for example, frames + * used as reference pictures). + */ + int extra_hw_frames; + + /** + * The percentage of damaged samples to discard a frame. + * + * - decoding: set by user + * - encoding: unused + */ + int discard_damaged_percentage; + + /** + * The number of samples per frame to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_samples; + + /** + * Bit set of AV_CODEC_EXPORT_DATA_* flags, which affects the kind of + * metadata exported in frame, packet, or coded stream side data by + * decoders and encoders. + * + * - decoding: set by user + * - encoding: set by user + */ + int export_side_data; + + /** + * This callback is called at the beginning of each packet to get a data + * buffer for it. + * + * The following field will be set in the packet before this callback is + * called: + * - size + * This callback must use the above value to calculate the required buffer size, + * which must padded by at least AV_INPUT_BUFFER_PADDING_SIZE bytes. + * + * In some specific cases, the encoder may not use the entire buffer allocated by this + * callback. This will be reflected in the size value in the packet once returned by + * avcodec_receive_packet(). + * + * This callback must fill the following fields in the packet: + * - data: alignment requirements for AVPacket apply, if any. Some architectures and + * encoders may benefit from having aligned data. + * - buf: must contain a pointer to an AVBufferRef structure. The packet's + * data pointer must be contained in it. See: av_buffer_create(), av_buffer_alloc(), + * and av_buffer_ref(). + * + * If AV_CODEC_CAP_DR1 is not set then get_encode_buffer() must call + * avcodec_default_get_encode_buffer() instead of providing a buffer allocated by + * some other means. + * + * The flags field may contain a combination of AV_GET_ENCODE_BUFFER_FLAG_ flags. + * They may be used for example to hint what use the buffer may get after being + * created. + * Implementations of this callback may ignore flags they don't understand. + * If AV_GET_ENCODE_BUFFER_FLAG_REF is set in flags then the packet may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * This callback must be thread-safe, as when frame threading is used, it may + * be called from multiple threads simultaneously. + * + * @see avcodec_default_get_encode_buffer() + * + * - encoding: Set by libavcodec, user can override. + * - decoding: unused + */ + int (*get_encode_buffer)(struct AVCodecContext *s, AVPacket *pkt, int flags); + + /** + * Audio channel layout. + * - encoding: must be set by the caller, to one of AVCodec.ch_layouts. + * - decoding: may be set by the caller if known e.g. from the container. + * The decoder can then override during decoding as needed. + */ + AVChannelLayout ch_layout; +} AVCodecContext; + +/** + * @defgroup lavc_hwaccel AVHWAccel + * + * @note Nothing in this structure should be accessed by the user. At some + * point in future it will not be externally visible at all. + * + * @{ + */ +typedef struct AVHWAccel { + /** + * Name of the hardware accelerated codec. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + */ + const char *name; + + /** + * Type of codec implemented by the hardware accelerator. + * + * See AVMEDIA_TYPE_xxx + */ + enum AVMediaType type; + + /** + * Codec implemented by the hardware accelerator. + * + * See AV_CODEC_ID_xxx + */ + enum AVCodecID id; + + /** + * Supported pixel format. + * + * Only hardware accelerated formats are supported here. + */ + enum AVPixelFormat pix_fmt; + + /** + * Hardware accelerated codec capabilities. + * see AV_HWACCEL_CODEC_CAP_* + */ + int capabilities; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavcodec and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + + /** + * Allocate a custom buffer + */ + int (*alloc_frame)(AVCodecContext *avctx, AVFrame *frame); + + /** + * Called at the beginning of each frame or field picture. + * + * Meaningful frame information (codec specific) is guaranteed to + * be parsed at this point. This function is mandatory. + * + * Note that buf can be NULL along with buf_size set to 0. + * Otherwise, this means the whole frame is available at this point. + * + * @param avctx the codec context + * @param buf the frame data buffer base + * @param buf_size the size of the frame in bytes + * @return zero if successful, a negative value otherwise + */ + int (*start_frame)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size); + + /** + * Callback for parameter data (SPS/PPS/VPS etc). + * + * Useful for hardware decoders which keep persistent state about the + * video parameters, and need to receive any changes to update that state. + * + * @param avctx the codec context + * @param type the nal unit type + * @param buf the nal unit data buffer + * @param buf_size the size of the nal unit in bytes + * @return zero if successful, a negative value otherwise + */ + int (*decode_params)(AVCodecContext *avctx, int type, const uint8_t *buf, uint32_t buf_size); + + /** + * Callback for each slice. + * + * Meaningful slice information (codec specific) is guaranteed to + * be parsed at this point. This function is mandatory. + * + * @param avctx the codec context + * @param buf the slice data buffer base + * @param buf_size the size of the slice in bytes + * @return zero if successful, a negative value otherwise + */ + int (*decode_slice)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size); + + /** + * Called at the end of each frame or field picture. + * + * The whole picture is parsed at this point and can now be sent + * to the hardware accelerator. This function is mandatory. + * + * @param avctx the codec context + * @return zero if successful, a negative value otherwise + */ + int (*end_frame)(AVCodecContext *avctx); + + /** + * Size of per-frame hardware accelerator private data. + * + * Private data is allocated with av_mallocz() before + * AVCodecContext.get_buffer() and deallocated after + * AVCodecContext.release_buffer(). + */ + int frame_priv_data_size; + + /** + * Initialize the hwaccel private data. + * + * This will be called from ff_get_format(), after hwaccel and + * hwaccel_context are set and the hwaccel private data in AVCodecInternal + * is allocated. + */ + int (*init)(AVCodecContext *avctx); + + /** + * Uninitialize the hwaccel private data. + * + * This will be called from get_format() or avcodec_close(), after hwaccel + * and hwaccel_context are already uninitialized. + */ + int (*uninit)(AVCodecContext *avctx); + + /** + * Size of the private data to allocate in + * AVCodecInternal.hwaccel_priv_data. + */ + int priv_data_size; + + /** + * Internal hwaccel capabilities. + */ + int caps_internal; + + /** + * Fill the given hw_frames context with current codec parameters. Called + * from get_format. Refer to avcodec_get_hw_frames_parameters() for + * details. + * + * This CAN be called before AVHWAccel.init is called, and you must assume + * that avctx->hwaccel_priv_data is invalid. + */ + int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); +} AVHWAccel; + +/** + * HWAccel is experimental and is thus avoided in favor of non experimental + * codecs + */ +#define AV_HWACCEL_CODEC_CAP_EXPERIMENTAL 0x0200 + +/** + * Hardware acceleration should be used for decoding even if the codec level + * used is unknown or higher than the maximum supported level reported by the + * hardware driver. + * + * It's generally a good idea to pass this flag unless you have a specific + * reason not to, as hardware tends to under-report supported levels. + */ +#define AV_HWACCEL_FLAG_IGNORE_LEVEL (1 << 0) + +/** + * Hardware acceleration can output YUV pixel formats with a different chroma + * sampling than 4:2:0 and/or other than 8 bits per component. + */ +#define AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH (1 << 1) + +/** + * Hardware acceleration should still be attempted for decoding when the + * codec profile does not match the reported capabilities of the hardware. + * + * For example, this can be used to try to decode baseline profile H.264 + * streams in hardware - it will often succeed, because many streams marked + * as baseline profile actually conform to constrained baseline profile. + * + * @warning If the stream is actually not supported then the behaviour is + * undefined, and may include returning entirely incorrect output + * while indicating success. + */ +#define AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH (1 << 2) + +/** + * @} + */ + +enum AVSubtitleType { + SUBTITLE_NONE, + + SUBTITLE_BITMAP, ///< A bitmap, pict will be set + + /** + * Plain text, the text field must be set by the decoder and is + * authoritative. ass and pict fields may contain approximations. + */ + SUBTITLE_TEXT, + + /** + * Formatted text, the ass field must be set by the decoder and is + * authoritative. pict and text fields may contain approximations. + */ + SUBTITLE_ASS, +}; + +#define AV_SUBTITLE_FLAG_FORCED 0x00000001 + +typedef struct AVSubtitleRect { + int x; ///< top left corner of pict, undefined when pict is not set + int y; ///< top left corner of pict, undefined when pict is not set + int w; ///< width of pict, undefined when pict is not set + int h; ///< height of pict, undefined when pict is not set + int nb_colors; ///< number of colors in pict, undefined when pict is not set + + /** + * data+linesize for the bitmap of this subtitle. + * Can be set for text/ass as well once they are rendered. + */ + uint8_t *data[4]; + int linesize[4]; + + enum AVSubtitleType type; + + char *text; ///< 0 terminated plain UTF-8 text + + /** + * 0 terminated ASS/SSA compatible event line. + * The presentation of this is unaffected by the other values in this + * struct. + */ + char *ass; + + int flags; +} AVSubtitleRect; + +typedef struct AVSubtitle { + uint16_t format; /* 0 = graphics */ + uint32_t start_display_time; /* relative to packet pts, in ms */ + uint32_t end_display_time; /* relative to packet pts, in ms */ + unsigned num_rects; + AVSubtitleRect **rects; + int64_t pts; ///< Same as packet pts, in AV_TIME_BASE +} AVSubtitle; + +/** + * Return the LIBAVCODEC_VERSION_INT constant. + */ +unsigned avcodec_version(void); + +/** + * Return the libavcodec build-time configuration. + */ +const char *avcodec_configuration(void); + +/** + * Return the libavcodec license. + */ +const char *avcodec_license(void); + +/** + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct should be freed with avcodec_free_context(). + * + * @param codec if non-NULL, allocate private data and initialize defaults + * for the given codec. It is illegal to then call avcodec_open2() + * with a different codec. + * If NULL, then the codec-specific defaults won't be initialized, + * which may result in suboptimal default settings (this is + * important mainly for encoders, e.g. libx264). + * + * @return An AVCodecContext filled with default values or NULL on failure. + */ +AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); + +/** + * Free the codec context and everything associated with it and write NULL to + * the provided pointer. + */ +void avcodec_free_context(AVCodecContext **avctx); + +/** + * Get the AVClass for AVCodecContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_class(void); + +#if FF_API_GET_FRAME_CLASS +/** + * @deprecated This function should not be used. + */ +attribute_deprecated +const AVClass *avcodec_get_frame_class(void); +#endif + +/** + * Get the AVClass for AVSubtitleRect. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_subtitle_rect_class(void); + +/** + * Fill the parameters struct based on the values from the supplied codec + * context. Any allocated fields in par are freed and replaced with duplicates + * of the corresponding fields in codec. + * + * @return >= 0 on success, a negative AVERROR code on failure + */ +int avcodec_parameters_from_context(AVCodecParameters *par, + const AVCodecContext *codec); + +/** + * Fill the codec context based on the values from the supplied codec + * parameters. Any allocated fields in codec that have a corresponding field in + * par are freed and replaced with duplicates of the corresponding field in par. + * Fields in codec that do not have a counterpart in par are not touched. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_to_context(AVCodecContext *codec, + const AVCodecParameters *par); + +/** + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated with avcodec_alloc_context3(). + * + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. + * + * @note Always call this function before using decoding routines (such as + * @ref avcodec_receive_frame()). + * + * @code + * av_dict_set(&opts, "b", "2.5M", 0); + * codec = avcodec_find_decoder(AV_CODEC_ID_H264); + * if (!codec) + * exit(1); + * + * context = avcodec_alloc_context3(codec); + * + * if (avcodec_open2(context, codec, opts) < 0) + * exit(1); + * @endcode + * + * @param avctx The context to initialize. + * @param codec The codec to open this context for. If a non-NULL codec has been + * previously passed to avcodec_alloc_context3() or + * for this context, then this parameter MUST be either NULL or + * equal to the previously passed codec. + * @param options A dictionary filled with AVCodecContext and codec-private options. + * On return this object will be filled with options that were not found. + * + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), + * av_dict_set(), av_opt_find(). + */ +int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); + +/** + * Close a given AVCodecContext and free all the data associated with it + * (but not the AVCodecContext itself). + * + * Calling this function on an AVCodecContext that hasn't been opened will free + * the codec-specific data allocated in avcodec_alloc_context3() with a non-NULL + * codec. Subsequent calls will do nothing. + * + * @note Do not use this function. Use avcodec_free_context() to destroy a + * codec context (either open or closed). Opening and closing a codec context + * multiple times is not supported anymore -- use multiple codec contexts + * instead. + */ +int avcodec_close(AVCodecContext *avctx); + +/** + * Free all allocated data in the given subtitle struct. + * + * @param sub AVSubtitle to free. + */ +void avsubtitle_free(AVSubtitle *sub); + +/** + * @} + */ + +/** + * @addtogroup lavc_decoding + * @{ + */ + +/** + * The default callback for AVCodecContext.get_buffer2(). It is made public so + * it can be called by custom get_buffer2() implementations for decoders without + * AV_CODEC_CAP_DR1 set. + */ +int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags); + +/** + * The default callback for AVCodecContext.get_encode_buffer(). It is made public so + * it can be called by custom get_encode_buffer() implementations for encoders without + * AV_CODEC_CAP_DR1 set. + */ +int avcodec_default_get_encode_buffer(AVCodecContext *s, AVPacket *pkt, int flags); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you do not use any horizontal + * padding. + * + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. + */ +void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you also ensure that all + * line sizes are a multiple of the respective linesize_align[i]. + * + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. + */ +void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, + int linesize_align[AV_NUM_DATA_POINTERS]); + +/** + * Converts AVChromaLocation to swscale x/y chroma position. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + */ +int avcodec_enum_to_chroma_pos(int *xpos, int *ypos, enum AVChromaLocation pos); + +/** + * Converts swscale x/y chroma position to AVChromaLocation. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + */ +enum AVChromaLocation avcodec_chroma_pos_to_enum(int xpos, int ypos); + +/** + * Decode a subtitle message. + * Return a negative value on error, otherwise return the number of bytes used. + * If no subtitle could be decompressed, got_sub_ptr is zero. + * Otherwise, the subtitle is stored in *sub. + * Note that AV_CODEC_CAP_DR1 is not available for subtitle codecs. This is for + * simplicity, because the performance difference is expected to be negligible + * and reusing a get_buffer written for video codecs would probably perform badly + * due to a potentially very different allocation pattern. + * + * Some decoders (those marked with AV_CODEC_CAP_DELAY) have a delay between input + * and output. This means that for some packets they will not immediately + * produce decoded output and need to be flushed at the end of decoding to get + * all the decoded data. Flushing is done by calling this function with packets + * with avpkt->data set to NULL and avpkt->size set to 0 until it stops + * returning subtitles. It is safe to flush even those decoders that are not + * marked with AV_CODEC_CAP_DELAY, then no subtitles will be returned. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx the codec context + * @param[out] sub The preallocated AVSubtitle in which the decoded subtitle will be stored, + * must be freed with avsubtitle_free if *got_sub_ptr is set. + * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. + * @param[in] avpkt The input AVPacket containing the input buffer. + */ +int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, + AVPacket *avpkt); + +/** + * Supply raw packet data as input to a decoder. + * + * Internally, this call will copy relevant AVCodecContext fields, which can + * influence decoding per-packet, and apply them when the packet is actually + * decoded. (For example AVCodecContext.skip_frame, which might direct the + * decoder to drop the frame contained by the packet sent with this function.) + * + * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE + * larger than the actual read bytes because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx codec context + * @param[in] avpkt The input AVPacket. Usually, this will be a single video + * frame, or several complete audio frames. + * Ownership of the packet remains with the caller, and the + * decoder will not write to the packet. The decoder may create + * a reference to the packet data (or copy it if the packet is + * not reference-counted). + * Unlike with older APIs, the packet is always fully consumed, + * and if it contains multiple frames (e.g. some audio codecs), + * will require you to call avcodec_receive_frame() multiple + * times afterwards before you can send a new packet. + * It can be NULL (or an AVPacket with data set to NULL and + * size set to 0); in this case, it is considered a flush + * packet, which signals the end of the stream. Sending the + * first flush packet will return success. Subsequent ones are + * unnecessary and will return AVERROR_EOF. If the decoder + * still has frames buffered, it will return them after sending + * a flush packet. + * + * @return 0 on success, otherwise negative error code: + * AVERROR(EAGAIN): input is not accepted in the current state - user + * must read output with avcodec_receive_frame() (once + * all output is read, the packet should be resent, and + * the call will not fail with EAGAIN). + * AVERROR_EOF: the decoder has been flushed, and no new packets can + * be sent to it (also returned if more than 1 flush + * packet is sent) + * AVERROR(EINVAL): codec not opened, it is an encoder, or requires flush + * AVERROR(ENOMEM): failed to add packet to internal queue, or similar + * other errors: legitimate decoding errors + */ +int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); + +/** + * Return decoded output data from a decoder. + * + * @param avctx codec context + * @param frame This will be set to a reference-counted video or audio + * frame (depending on the decoder type) allocated by the + * decoder. Note that the function will always call + * av_frame_unref(frame) before doing anything else. + * + * @return + * 0: success, a frame was returned + * AVERROR(EAGAIN): output is not available in this state - user must try + * to send new input + * AVERROR_EOF: the decoder has been fully flushed, and there will be + * no more output frames + * AVERROR(EINVAL): codec not opened, or it is an encoder + * AVERROR_INPUT_CHANGED: current decoded frame has changed parameters + * with respect to first decoded frame. Applicable + * when flag AV_CODEC_FLAG_DROPCHANGED is set. + * other negative values: legitimate decoding errors + */ +int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); + +/** + * Supply a raw video or audio frame to the encoder. Use avcodec_receive_packet() + * to retrieve buffered output packets. + * + * @param avctx codec context + * @param[in] frame AVFrame containing the raw audio or video frame to be encoded. + * Ownership of the frame remains with the caller, and the + * encoder will not write to the frame. The encoder may create + * a reference to the frame data (or copy it if the frame is + * not reference-counted). + * It can be NULL, in which case it is considered a flush + * packet. This signals the end of the stream. If the encoder + * still has packets buffered, it will return them after this + * call. Once flushing mode has been entered, additional flush + * packets are ignored, and sending frames will return + * AVERROR_EOF. + * + * For audio: + * If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * can have any number of samples. + * If it is not set, frame->nb_samples must be equal to + * avctx->frame_size for all frames except the last. + * The final frame may be smaller than avctx->frame_size. + * @return 0 on success, otherwise negative error code: + * AVERROR(EAGAIN): input is not accepted in the current state - user + * must read output with avcodec_receive_packet() (once + * all output is read, the packet should be resent, and + * the call will not fail with EAGAIN). + * AVERROR_EOF: the encoder has been flushed, and no new frames can + * be sent to it + * AVERROR(EINVAL): codec not opened, it is a decoder, or requires flush + * AVERROR(ENOMEM): failed to add packet to internal queue, or similar + * other errors: legitimate encoding errors + */ +int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); + +/** + * Read encoded data from the encoder. + * + * @param avctx codec context + * @param avpkt This will be set to a reference-counted packet allocated by the + * encoder. Note that the function will always call + * av_packet_unref(avpkt) before doing anything else. + * @return 0 on success, otherwise negative error code: + * AVERROR(EAGAIN): output is not available in the current state - user + * must try to send input + * AVERROR_EOF: the encoder has been fully flushed, and there will be + * no more output packets + * AVERROR(EINVAL): codec not opened, or it is a decoder + * other errors: legitimate encoding errors + */ +int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); + +/** + * Create and return a AVHWFramesContext with values adequate for hardware + * decoding. This is meant to get called from the get_format callback, and is + * a helper for preparing a AVHWFramesContext for AVCodecContext.hw_frames_ctx. + * This API is for decoding with certain hardware acceleration modes/APIs only. + * + * The returned AVHWFramesContext is not initialized. The caller must do this + * with av_hwframe_ctx_init(). + * + * Calling this function is not a requirement, but makes it simpler to avoid + * codec or hardware API specific details when manually allocating frames. + * + * Alternatively to this, an API user can set AVCodecContext.hw_device_ctx, + * which sets up AVCodecContext.hw_frames_ctx fully automatically, and makes + * it unnecessary to call this function or having to care about + * AVHWFramesContext initialization at all. + * + * There are a number of requirements for calling this function: + * + * - It must be called from get_format with the same avctx parameter that was + * passed to get_format. Calling it outside of get_format is not allowed, and + * can trigger undefined behavior. + * - The function is not always supported (see description of return values). + * Even if this function returns successfully, hwaccel initialization could + * fail later. (The degree to which implementations check whether the stream + * is actually supported varies. Some do this check only after the user's + * get_format callback returns.) + * - The hw_pix_fmt must be one of the choices suggested by get_format. If the + * user decides to use a AVHWFramesContext prepared with this API function, + * the user must return the same hw_pix_fmt from get_format. + * - The device_ref passed to this function must support the given hw_pix_fmt. + * - After calling this API function, it is the user's responsibility to + * initialize the AVHWFramesContext (returned by the out_frames_ref parameter), + * and to set AVCodecContext.hw_frames_ctx to it. If done, this must be done + * before returning from get_format (this is implied by the normal + * AVCodecContext.hw_frames_ctx API rules). + * - The AVHWFramesContext parameters may change every time time get_format is + * called. Also, AVCodecContext.hw_frames_ctx is reset before get_format. So + * you are inherently required to go through this process again on every + * get_format call. + * - It is perfectly possible to call this function without actually using + * the resulting AVHWFramesContext. One use-case might be trying to reuse a + * previously initialized AVHWFramesContext, and calling this API function + * only to test whether the required frame parameters have changed. + * - Fields that use dynamically allocated values of any kind must not be set + * by the user unless setting them is explicitly allowed by the documentation. + * If the user sets AVHWFramesContext.free and AVHWFramesContext.user_opaque, + * the new free callback must call the potentially set previous free callback. + * This API call may set any dynamically allocated fields, including the free + * callback. + * + * The function will set at least the following fields on AVHWFramesContext + * (potentially more, depending on hwaccel API): + * + * - All fields set by av_hwframe_ctx_alloc(). + * - Set the format field to hw_pix_fmt. + * - Set the sw_format field to the most suited and most versatile format. (An + * implication is that this will prefer generic formats over opaque formats + * with arbitrary restrictions, if possible.) + * - Set the width/height fields to the coded frame size, rounded up to the + * API-specific minimum alignment. + * - Only _if_ the hwaccel requires a pre-allocated pool: set the initial_pool_size + * field to the number of maximum reference surfaces possible with the codec, + * plus 1 surface for the user to work (meaning the user can safely reference + * at most 1 decoded surface at a time), plus additional buffering introduced + * by frame threading. If the hwaccel does not require pre-allocation, the + * field is left to 0, and the decoder will allocate new surfaces on demand + * during decoding. + * - Possibly AVHWFramesContext.hwctx fields, depending on the underlying + * hardware API. + * + * Essentially, out_frames_ref returns the same as av_hwframe_ctx_alloc(), but + * with basic frame parameters set. + * + * The function is stateless, and does not change the AVCodecContext or the + * device_ref AVHWDeviceContext. + * + * @param avctx The context which is currently calling get_format, and which + * implicitly contains all state needed for filling the returned + * AVHWFramesContext properly. + * @param device_ref A reference to the AVHWDeviceContext describing the device + * which will be used by the hardware decoder. + * @param hw_pix_fmt The hwaccel format you are going to return from get_format. + * @param out_frames_ref On success, set to a reference to an _uninitialized_ + * AVHWFramesContext, created from the given device_ref. + * Fields will be set to values required for decoding. + * Not changed if an error is returned. + * @return zero on success, a negative value on error. The following error codes + * have special semantics: + * AVERROR(ENOENT): the decoder does not support this functionality. Setup + * is always manual, or it is a decoder which does not + * support setting AVCodecContext.hw_frames_ctx at all, + * or it is a software format. + * AVERROR(EINVAL): it is known that hardware decoding is not supported for + * this configuration, or the device_ref is not supported + * for the hwaccel referenced by hw_pix_fmt. + */ +int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, + AVBufferRef *device_ref, + enum AVPixelFormat hw_pix_fmt, + AVBufferRef **out_frames_ref); + + + +/** + * @defgroup lavc_parsing Frame parsing + * @{ + */ + +enum AVPictureStructure { + AV_PICTURE_STRUCTURE_UNKNOWN, //< unknown + AV_PICTURE_STRUCTURE_TOP_FIELD, //< coded as top field + AV_PICTURE_STRUCTURE_BOTTOM_FIELD, //< coded as bottom field + AV_PICTURE_STRUCTURE_FRAME, //< coded as frame +}; + +typedef struct AVCodecParserContext { + void *priv_data; + const struct AVCodecParser *parser; + int64_t frame_offset; /* offset of the current frame */ + int64_t cur_offset; /* current offset + (incremented by each av_parser_parse()) */ + int64_t next_frame_offset; /* offset of the next frame */ + /* video info */ + int pict_type; /* XXX: Put it back in AVCodecContext. */ + /** + * This field is used for proper frame duration computation in lavf. + * It signals, how much longer the frame duration of the current frame + * is compared to normal frame duration. + * + * frame_duration = (1 + repeat_pict) * time_base + * + * It is used by codecs like H.264 to display telecined material. + */ + int repeat_pict; /* XXX: Put it back in AVCodecContext. */ + int64_t pts; /* pts of the current frame */ + int64_t dts; /* dts of the current frame */ + + /* private data */ + int64_t last_pts; + int64_t last_dts; + int fetch_timestamp; + +#define AV_PARSER_PTS_NB 4 + int cur_frame_start_index; + int64_t cur_frame_offset[AV_PARSER_PTS_NB]; + int64_t cur_frame_pts[AV_PARSER_PTS_NB]; + int64_t cur_frame_dts[AV_PARSER_PTS_NB]; + + int flags; +#define PARSER_FLAG_COMPLETE_FRAMES 0x0001 +#define PARSER_FLAG_ONCE 0x0002 +/// Set if the parser has a valid file offset +#define PARSER_FLAG_FETCHED_OFFSET 0x0004 +#define PARSER_FLAG_USE_CODEC_TS 0x1000 + + int64_t offset; ///< byte offset from starting packet start + int64_t cur_frame_end[AV_PARSER_PTS_NB]; + + /** + * Set by parser to 1 for key frames and 0 for non-key frames. + * It is initialized to -1, so if the parser doesn't set this flag, + * old-style fallback using AV_PICTURE_TYPE_I picture type as key frames + * will be used. + */ + int key_frame; + + // Timestamp generation support: + /** + * Synchronization point for start of timestamp generation. + * + * Set to >0 for sync point, 0 for no sync point and <0 for undefined + * (default). + * + * For example, this corresponds to presence of H.264 buffering period + * SEI message. + */ + int dts_sync_point; + + /** + * Offset of the current timestamp against last timestamp sync point in + * units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain a valid timestamp offset. + * + * Note that the timestamp of sync point has usually a nonzero + * dts_ref_dts_delta, which refers to the previous sync point. Offset of + * the next frame after timestamp sync point will be usually 1. + * + * For example, this corresponds to H.264 cpb_removal_delay. + */ + int dts_ref_dts_delta; + + /** + * Presentation delay of current frame in units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain valid non-negative timestamp delta (presentation time of a frame + * must not lie in the past). + * + * This delay represents the difference between decoding and presentation + * time of the frame. + * + * For example, this corresponds to H.264 dpb_output_delay. + */ + int pts_dts_delta; + + /** + * Position of the packet in file. + * + * Analogous to cur_frame_pts/dts + */ + int64_t cur_frame_pos[AV_PARSER_PTS_NB]; + + /** + * Byte position of currently parsed frame in stream. + */ + int64_t pos; + + /** + * Previous frame byte position. + */ + int64_t last_pos; + + /** + * Duration of the current frame. + * For audio, this is in units of 1 / AVCodecContext.sample_rate. + * For all other types, this is in units of AVCodecContext.time_base. + */ + int duration; + + enum AVFieldOrder field_order; + + /** + * Indicate whether a picture is coded as a frame, top field or bottom field. + * + * For example, H.264 field_pic_flag equal to 0 corresponds to + * AV_PICTURE_STRUCTURE_FRAME. An H.264 picture with field_pic_flag + * equal to 1 and bottom_field_flag equal to 0 corresponds to + * AV_PICTURE_STRUCTURE_TOP_FIELD. + */ + enum AVPictureStructure picture_structure; + + /** + * Picture number incremented in presentation or output order. + * This field may be reinitialized at the first picture of a new sequence. + * + * For example, this corresponds to H.264 PicOrderCnt. + */ + int output_picture_number; + + /** + * Dimensions of the decoded video intended for presentation. + */ + int width; + int height; + + /** + * Dimensions of the coded video. + */ + int coded_width; + int coded_height; + + /** + * The format of the coded data, corresponds to enum AVPixelFormat for video + * and for enum AVSampleFormat for audio. + * + * Note that a decoder can have considerable freedom in how exactly it + * decodes the data, so the format reported here might be different from the + * one returned by a decoder. + */ + int format; +} AVCodecParserContext; + +typedef struct AVCodecParser { + int codec_ids[7]; /* several codec IDs are permitted */ + int priv_data_size; + int (*parser_init)(AVCodecParserContext *s); + /* This callback never returns an error, a negative value means that + * the frame start was in a previous packet. */ + int (*parser_parse)(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size); + void (*parser_close)(AVCodecParserContext *s); + int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size); +} AVCodecParser; + +/** + * Iterate over all registered codec parsers. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec parser or NULL when the iteration is + * finished + */ +const AVCodecParser *av_parser_iterate(void **opaque); + +AVCodecParserContext *av_parser_init(int codec_id); + +/** + * Parse a packet. + * + * @param s parser context. + * @param avctx codec context. + * @param poutbuf set to pointer to parsed buffer or NULL if not yet finished. + * @param poutbuf_size set to size of parsed buffer or zero if not yet finished. + * @param buf input buffer. + * @param buf_size buffer size in bytes without the padding. I.e. the full buffer + size is assumed to be buf_size + AV_INPUT_BUFFER_PADDING_SIZE. + To signal EOF, this should be 0 (so that the last frame + can be output). + * @param pts input presentation timestamp. + * @param dts input decoding timestamp. + * @param pos input byte position in stream. + * @return the number of bytes of the input bitstream used. + * + * Example: + * @code + * while(in_len){ + * len = av_parser_parse2(myparser, AVCodecContext, &data, &size, + * in_data, in_len, + * pts, dts, pos); + * in_data += len; + * in_len -= len; + * + * if(size) + * decode_frame(data, size); + * } + * @endcode + */ +int av_parser_parse2(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int64_t pts, int64_t dts, + int64_t pos); + +void av_parser_close(AVCodecParserContext *s); + +/** + * @} + * @} + */ + +/** + * @addtogroup lavc_encoding + * @{ + */ + +int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVSubtitle *sub); + + +/** + * @} + */ + +/** + * @defgroup lavc_misc Utility functions + * @ingroup libavc + * + * Miscellaneous utility functions related to both encoding and decoding + * (or neither). + * @{ + */ + +/** + * @defgroup lavc_misc_pixfmt Pixel formats + * + * Functions for working with pixel formats. + * @{ + */ + +/** + * Return a value representing the fourCC code associated to the + * pixel format pix_fmt, or 0 if no associated fourCC code can be + * found. + */ +unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt); + +/** + * Find the best pixel format to convert to given a certain source pixel + * format. When converting from one pixel format to another, information loss + * may occur. For example, when converting from RGB24 to GRAY, the color + * information will be lost. Similarly, other losses occur when converting from + * some formats to other formats. avcodec_find_best_pix_fmt_of_2() searches which of + * the given pixel formats should be used to suffer the least amount of loss. + * The pixel formats from which it chooses one, are determined by the + * pix_fmt_list parameter. + * + * + * @param[in] pix_fmt_list AV_PIX_FMT_NONE terminated array of pixel formats to choose from + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. + * @return The best pixel format to convert to or -1 if none was found. + */ +enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *pix_fmt_list, + enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); + +enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + +/** + * @} + */ + +void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); + +int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); +int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count); +//FIXME func typedef + +/** + * Fill AVFrame audio data and linesize pointers. + * + * The buffer buf must be a preallocated buffer with a size big enough + * to contain the specified samples amount. The filled AVFrame data + * pointers will point to this buffer. + * + * AVFrame extended_data channel pointers are allocated if necessary for + * planar audio. + * + * @param frame the AVFrame + * frame->nb_samples must be set prior to calling the + * function. This function fills in frame->data, + * frame->extended_data, frame->linesize[0]. + * @param nb_channels channel count + * @param sample_fmt sample format + * @param buf buffer to use for frame data + * @param buf_size size of buffer + * @param align plane size sample alignment (0 = default) + * @return >=0 on success, negative error code on failure + * @todo return the size in bytes required to store the samples in + * case of success, at the next libavutil bump + */ +int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, + enum AVSampleFormat sample_fmt, const uint8_t *buf, + int buf_size, int align); + +/** + * Reset the internal codec state / flush internal buffers. Should be called + * e.g. when seeking or when switching to a different stream. + * + * @note for decoders, this function just releases any references the decoder + * might keep internally, but the caller's references remain valid. + * + * @note for encoders, this function will only do something if the encoder + * declares support for AV_CODEC_CAP_ENCODER_FLUSH. When called, the encoder + * will drain any remaining packets, and can then be re-used for a different + * stream (as opposed to sending a null frame which will leave the encoder + * in a permanent EOF state after draining). This can be desirable if the + * cost of tearing down and replacing the encoder instance is high. + */ +void avcodec_flush_buffers(AVCodecContext *avctx); + +/** + * Return audio frame duration. + * + * @param avctx codec context + * @param frame_bytes size of the frame, or 0 if unknown + * @return frame duration, in samples, if known. 0 if not able to + * determine. + */ +int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes); + +/* memory */ + +/** + * Same behaviour av_fast_malloc but the buffer has additional + * AV_INPUT_BUFFER_PADDING_SIZE at the end which will always be 0. + * + * In addition the whole buffer will initially and after resizes + * be 0-initialized so that no uninitialized data will ever appear. + */ +void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Same behaviour av_fast_padded_malloc except that buffer will always + * be 0-initialized after call. + */ +void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * @return a positive value if s is open (i.e. avcodec_open2() was called on it + * with no corresponding avcodec_close()), 0 otherwise. + */ +int avcodec_is_open(AVCodecContext *s); + +/** + * @} + */ + +#endif /* AVCODEC_AVCODEC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec.h b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec.h new file mode 100644 index 0000000000000..03e8be90a2fed --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec.h @@ -0,0 +1,387 @@ +/* + * AVCodec public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_H +#define AVCODEC_CODEC_H + +#include + +#include "libavutil/avutil.h" +#include "libavutil/hwcontext.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" +#include "libavutil/samplefmt.h" + +#include "libavcodec/codec_id.h" +#include "libavcodec/version_major.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * Decoder can use draw_horiz_band callback. + */ +#define AV_CODEC_CAP_DRAW_HORIZ_BAND (1 << 0) +/** + * Codec uses get_buffer() or get_encode_buffer() for allocating buffers and + * supports custom allocators. + * If not set, it might not use get_buffer() or get_encode_buffer() at all, or + * use operations that assume the buffer was allocated by + * avcodec_default_get_buffer2 or avcodec_default_get_encode_buffer. + */ +#define AV_CODEC_CAP_DR1 (1 << 1) +#if FF_API_FLAG_TRUNCATED +/** + * @deprecated Use parsers to always send proper frames. + */ +#define AV_CODEC_CAP_TRUNCATED (1 << 3) +#endif +/** + * Encoder or decoder requires flushing with NULL input at the end in order to + * give the complete and correct output. + * + * NOTE: If this flag is not set, the codec is guaranteed to never be fed with + * with NULL data. The user can still send NULL data to the public encode + * or decode function, but libavcodec will not pass it along to the codec + * unless this flag is set. + * + * Decoders: + * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to get the delayed data until the decoder no longer + * returns frames. + * + * Encoders: + * The encoder needs to be fed with NULL data at the end of encoding until the + * encoder no longer returns data. + * + * NOTE: For encoders implementing the AVCodec.encode2() function, setting this + * flag also means that the encoder must set the pts and duration for + * each output packet. If this flag is not set, the pts and duration will + * be determined by libavcodec from the input frame. + */ +#define AV_CODEC_CAP_DELAY (1 << 5) +/** + * Codec can be fed a final frame with a smaller size. + * This can be used to prevent truncation of the last audio samples. + */ +#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6) + +/** + * Codec can output multiple frames per AVPacket + * Normally demuxers return one frame at a time, demuxers which do not do + * are connected to a parser to split what they return into proper frames. + * This flag is reserved to the very rare category of codecs which have a + * bitstream that cannot be split into frames without timeconsuming + * operations like full decoding. Demuxers carrying such bitstreams thus + * may return multiple frames in a packet. This has many disadvantages like + * prohibiting stream copy in many cases thus it should only be considered + * as a last resort. + */ +#define AV_CODEC_CAP_SUBFRAMES (1 << 8) +/** + * Codec is experimental and is thus avoided in favor of non experimental + * encoders + */ +#define AV_CODEC_CAP_EXPERIMENTAL (1 << 9) +/** + * Codec should fill in channel configuration and samplerate instead of container + */ +#define AV_CODEC_CAP_CHANNEL_CONF (1 << 10) +/** + * Codec supports frame-level multithreading. + */ +#define AV_CODEC_CAP_FRAME_THREADS (1 << 12) +/** + * Codec supports slice-based (or partition-based) multithreading. + */ +#define AV_CODEC_CAP_SLICE_THREADS (1 << 13) +/** + * Codec supports changed parameters at any point. + */ +#define AV_CODEC_CAP_PARAM_CHANGE (1 << 14) +/** + * Codec supports multithreading through a method other than slice- or + * frame-level multithreading. Typically this marks wrappers around + * multithreading-capable external libraries. + */ +#define AV_CODEC_CAP_OTHER_THREADS (1 << 15) +#if FF_API_AUTO_THREADS +#define AV_CODEC_CAP_AUTO_THREADS AV_CODEC_CAP_OTHER_THREADS +#endif +/** + * Audio encoder supports receiving a different number of samples in each call. + */ +#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16) +/** + * Decoder is not a preferred choice for probing. + * This indicates that the decoder is not a good choice for probing. + * It could for example be an expensive to spin up hardware decoder, + * or it could simply not provide a lot of useful information about + * the stream. + * A decoder marked with this flag should only be used as last resort + * choice for probing. + */ +#define AV_CODEC_CAP_AVOID_PROBING (1 << 17) + +#if FF_API_UNUSED_CODEC_CAPS +/** + * Deprecated and unused. Use AVCodecDescriptor.props instead + */ +#define AV_CODEC_CAP_INTRA_ONLY 0x40000000 +/** + * Deprecated and unused. Use AVCodecDescriptor.props instead + */ +#define AV_CODEC_CAP_LOSSLESS 0x80000000 +#endif + +/** + * Codec is backed by a hardware implementation. Typically used to + * identify a non-hwaccel hardware decoder. For information about hwaccels, use + * avcodec_get_hw_config() instead. + */ +#define AV_CODEC_CAP_HARDWARE (1 << 18) + +/** + * Codec is potentially backed by a hardware implementation, but not + * necessarily. This is used instead of AV_CODEC_CAP_HARDWARE, if the + * implementation provides some sort of internal fallback. + */ +#define AV_CODEC_CAP_HYBRID (1 << 19) + +/** + * This codec takes the reordered_opaque field from input AVFrames + * and returns it in the corresponding field in AVCodecContext after + * encoding. + */ +#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE (1 << 20) + +/** + * This encoder can be flushed using avcodec_flush_buffers(). If this flag is + * not set, the encoder must be closed and reopened to ensure that no frames + * remain pending. + */ +#define AV_CODEC_CAP_ENCODER_FLUSH (1 << 21) + +/** + * AVProfile. + */ +typedef struct AVProfile { + int profile; + const char *name; ///< short name for the profile +} AVProfile; + +/** + * AVCodec. + */ +typedef struct AVCodec { + /** + * Name of the codec implementation. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + * This is the primary way to find a codec from the user perspective. + */ + const char *name; + /** + * Descriptive name for the codec, meant to be more human readable than name. + * You should use the NULL_IF_CONFIG_SMALL() macro to define it. + */ + const char *long_name; + enum AVMediaType type; + enum AVCodecID id; + /** + * Codec capabilities. + * see AV_CODEC_CAP_* + */ + int capabilities; + uint8_t max_lowres; ///< maximum value for lowres supported by the decoder + const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} + const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 + const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 + const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * @deprecated use ch_layouts instead + */ + attribute_deprecated + const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 +#endif + const AVClass *priv_class; ///< AVClass for the private context + const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN} + + /** + * Group name of the codec implementation. + * This is a short symbolic name of the wrapper backing this codec. A + * wrapper uses some kind of external implementation for the codec, such + * as an external library, or a codec implementation provided by the OS or + * the hardware. + * If this field is NULL, this is a builtin, libavcodec native codec. + * If non-NULL, this will be the suffix in AVCodec.name in most cases + * (usually AVCodec.name will be of the form "_"). + */ + const char *wrapper_name; + + /** + * Array of supported channel layouts, terminated with a zeroed layout. + */ + const AVChannelLayout *ch_layouts; +} AVCodec; + +/** + * Iterate over all registered codecs. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec or NULL when the iteration is + * finished + */ +const AVCodec *av_codec_iterate(void **opaque); + +/** + * Find a registered decoder with a matching codec ID. + * + * @param id AVCodecID of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_decoder(enum AVCodecID id); + +/** + * Find a registered decoder with the specified name. + * + * @param name name of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_decoder_by_name(const char *name); + +/** + * Find a registered encoder with a matching codec ID. + * + * @param id AVCodecID of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_encoder(enum AVCodecID id); + +/** + * Find a registered encoder with the specified name. + * + * @param name name of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_encoder_by_name(const char *name); +/** + * @return a non-zero number if codec is an encoder, zero otherwise + */ +int av_codec_is_encoder(const AVCodec *codec); + +/** + * @return a non-zero number if codec is a decoder, zero otherwise + */ +int av_codec_is_decoder(const AVCodec *codec); + +/** + * Return a name for the specified profile, if available. + * + * @param codec the codec that is searched for the given profile + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + */ +const char *av_get_profile_name(const AVCodec *codec, int profile); + +enum { + /** + * The codec supports this format via the hw_device_ctx interface. + * + * When selecting this format, AVCodecContext.hw_device_ctx should + * have been set to a device of the specified type before calling + * avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01, + /** + * The codec supports this format via the hw_frames_ctx interface. + * + * When selecting this format for a decoder, + * AVCodecContext.hw_frames_ctx should be set to a suitable frames + * context inside the get_format() callback. The frames context + * must have been created on a device of the specified type. + * + * When selecting this format for an encoder, + * AVCodecContext.hw_frames_ctx should be set to the context which + * will be used for the input frames before calling avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02, + /** + * The codec supports this format by some internal method. + * + * This format can be selected without any additional configuration - + * no device or frames context is required. + */ + AV_CODEC_HW_CONFIG_METHOD_INTERNAL = 0x04, + /** + * The codec supports this format by some ad-hoc method. + * + * Additional settings and/or function calls are required. See the + * codec-specific documentation for details. (Methods requiring + * this sort of configuration are deprecated and others should be + * used in preference.) + */ + AV_CODEC_HW_CONFIG_METHOD_AD_HOC = 0x08, +}; + +typedef struct AVCodecHWConfig { + /** + * For decoders, a hardware pixel format which that decoder may be + * able to decode to if suitable hardware is available. + * + * For encoders, a pixel format which the encoder may be able to + * accept. If set to AV_PIX_FMT_NONE, this applies to all pixel + * formats supported by the codec. + */ + enum AVPixelFormat pix_fmt; + /** + * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible + * setup methods which can be used with this configuration. + */ + int methods; + /** + * The device type associated with the configuration. + * + * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and + * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused. + */ + enum AVHWDeviceType device_type; +} AVCodecHWConfig; + +/** + * Retrieve supported hardware configurations for a codec. + * + * Values of index from zero to some maximum return the indexed configuration + * descriptor; all other values return NULL. If the codec does not support + * any hardware configurations then it will always return NULL. + */ +const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index); + +/** + * @} + */ + +#endif /* AVCODEC_CODEC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec_desc.h b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec_desc.h new file mode 100644 index 0000000000000..126b52df47629 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec_desc.h @@ -0,0 +1,128 @@ +/* + * Codec descriptors public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_DESC_H +#define AVCODEC_CODEC_DESC_H + +#include "libavutil/avutil.h" + +#include "codec_id.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * This struct describes the properties of a single codec described by an + * AVCodecID. + * @see avcodec_descriptor_get() + */ +typedef struct AVCodecDescriptor { + enum AVCodecID id; + enum AVMediaType type; + /** + * Name of the codec described by this descriptor. It is non-empty and + * unique for each codec descriptor. It should contain alphanumeric + * characters and '_' only. + */ + const char *name; + /** + * A more descriptive name for this codec. May be NULL. + */ + const char *long_name; + /** + * Codec properties, a combination of AV_CODEC_PROP_* flags. + */ + int props; + /** + * MIME type(s) associated with the codec. + * May be NULL; if not, a NULL-terminated array of MIME types. + * The first item is always non-NULL and is the preferred MIME type. + */ + const char *const *mime_types; + /** + * If non-NULL, an array of profiles recognized for this codec. + * Terminated with FF_PROFILE_UNKNOWN. + */ + const struct AVProfile *profiles; +} AVCodecDescriptor; + +/** + * Codec uses only intra compression. + * Video and audio codecs only. + */ +#define AV_CODEC_PROP_INTRA_ONLY (1 << 0) +/** + * Codec supports lossy compression. Audio and video codecs only. + * @note a codec may support both lossy and lossless + * compression modes + */ +#define AV_CODEC_PROP_LOSSY (1 << 1) +/** + * Codec supports lossless compression. Audio and video codecs only. + */ +#define AV_CODEC_PROP_LOSSLESS (1 << 2) +/** + * Codec supports frame reordering. That is, the coded order (the order in which + * the encoded packets are output by the encoders / stored / input to the + * decoders) may be different from the presentation order of the corresponding + * frames. + * + * For codecs that do not have this property set, PTS and DTS should always be + * equal. + */ +#define AV_CODEC_PROP_REORDER (1 << 3) +/** + * Subtitle codec is bitmap based + * Decoded AVSubtitle data can be read from the AVSubtitleRect->pict field. + */ +#define AV_CODEC_PROP_BITMAP_SUB (1 << 16) +/** + * Subtitle codec is text based. + * Decoded AVSubtitle data can be read from the AVSubtitleRect->ass field. + */ +#define AV_CODEC_PROP_TEXT_SUB (1 << 17) + +/** + * @return descriptor for given codec ID or NULL if no descriptor exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id); + +/** + * Iterate over all codec descriptors known to libavcodec. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); + +/** + * @return codec descriptor with the given name or NULL if no such descriptor + * exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_DESC_H diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec_id.h b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec_id.h new file mode 100644 index 0000000000000..81fb316cff632 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec_id.h @@ -0,0 +1,634 @@ +/* + * Codec IDs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_ID_H +#define AVCODEC_CODEC_ID_H + +#include "libavutil/avutil.h" +#include "libavutil/samplefmt.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * Identify the syntax and semantics of the bitstream. + * The principle is roughly: + * Two decoders with the same ID can decode the same streams. + * Two encoders with the same ID can encode compatible streams. + * There may be slight deviations from the principle due to implementation + * details. + * + * If you add a codec ID to this list, add it so that + * 1. no value of an existing codec ID changes (that would break ABI), + * 2. it is as close as possible to similar codecs + * + * After adding new codec IDs, do not forget to add an entry to the codec + * descriptor list and bump libavcodec minor version. + */ +enum AVCodecID { + AV_CODEC_ID_NONE, + + /* video codecs */ + AV_CODEC_ID_MPEG1VIDEO, + AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding + AV_CODEC_ID_H261, + AV_CODEC_ID_H263, + AV_CODEC_ID_RV10, + AV_CODEC_ID_RV20, + AV_CODEC_ID_MJPEG, + AV_CODEC_ID_MJPEGB, + AV_CODEC_ID_LJPEG, + AV_CODEC_ID_SP5X, + AV_CODEC_ID_JPEGLS, + AV_CODEC_ID_MPEG4, + AV_CODEC_ID_RAWVIDEO, + AV_CODEC_ID_MSMPEG4V1, + AV_CODEC_ID_MSMPEG4V2, + AV_CODEC_ID_MSMPEG4V3, + AV_CODEC_ID_WMV1, + AV_CODEC_ID_WMV2, + AV_CODEC_ID_H263P, + AV_CODEC_ID_H263I, + AV_CODEC_ID_FLV1, + AV_CODEC_ID_SVQ1, + AV_CODEC_ID_SVQ3, + AV_CODEC_ID_DVVIDEO, + AV_CODEC_ID_HUFFYUV, + AV_CODEC_ID_CYUV, + AV_CODEC_ID_H264, + AV_CODEC_ID_INDEO3, + AV_CODEC_ID_VP3, + AV_CODEC_ID_THEORA, + AV_CODEC_ID_ASV1, + AV_CODEC_ID_ASV2, + AV_CODEC_ID_FFV1, + AV_CODEC_ID_4XM, + AV_CODEC_ID_VCR1, + AV_CODEC_ID_CLJR, + AV_CODEC_ID_MDEC, + AV_CODEC_ID_ROQ, + AV_CODEC_ID_INTERPLAY_VIDEO, + AV_CODEC_ID_XAN_WC3, + AV_CODEC_ID_XAN_WC4, + AV_CODEC_ID_RPZA, + AV_CODEC_ID_CINEPAK, + AV_CODEC_ID_WS_VQA, + AV_CODEC_ID_MSRLE, + AV_CODEC_ID_MSVIDEO1, + AV_CODEC_ID_IDCIN, + AV_CODEC_ID_8BPS, + AV_CODEC_ID_SMC, + AV_CODEC_ID_FLIC, + AV_CODEC_ID_TRUEMOTION1, + AV_CODEC_ID_VMDVIDEO, + AV_CODEC_ID_MSZH, + AV_CODEC_ID_ZLIB, + AV_CODEC_ID_QTRLE, + AV_CODEC_ID_TSCC, + AV_CODEC_ID_ULTI, + AV_CODEC_ID_QDRAW, + AV_CODEC_ID_VIXL, + AV_CODEC_ID_QPEG, + AV_CODEC_ID_PNG, + AV_CODEC_ID_PPM, + AV_CODEC_ID_PBM, + AV_CODEC_ID_PGM, + AV_CODEC_ID_PGMYUV, + AV_CODEC_ID_PAM, + AV_CODEC_ID_FFVHUFF, + AV_CODEC_ID_RV30, + AV_CODEC_ID_RV40, + AV_CODEC_ID_VC1, + AV_CODEC_ID_WMV3, + AV_CODEC_ID_LOCO, + AV_CODEC_ID_WNV1, + AV_CODEC_ID_AASC, + AV_CODEC_ID_INDEO2, + AV_CODEC_ID_FRAPS, + AV_CODEC_ID_TRUEMOTION2, + AV_CODEC_ID_BMP, + AV_CODEC_ID_CSCD, + AV_CODEC_ID_MMVIDEO, + AV_CODEC_ID_ZMBV, + AV_CODEC_ID_AVS, + AV_CODEC_ID_SMACKVIDEO, + AV_CODEC_ID_NUV, + AV_CODEC_ID_KMVC, + AV_CODEC_ID_FLASHSV, + AV_CODEC_ID_CAVS, + AV_CODEC_ID_JPEG2000, + AV_CODEC_ID_VMNC, + AV_CODEC_ID_VP5, + AV_CODEC_ID_VP6, + AV_CODEC_ID_VP6F, + AV_CODEC_ID_TARGA, + AV_CODEC_ID_DSICINVIDEO, + AV_CODEC_ID_TIERTEXSEQVIDEO, + AV_CODEC_ID_TIFF, + AV_CODEC_ID_GIF, + AV_CODEC_ID_DXA, + AV_CODEC_ID_DNXHD, + AV_CODEC_ID_THP, + AV_CODEC_ID_SGI, + AV_CODEC_ID_C93, + AV_CODEC_ID_BETHSOFTVID, + AV_CODEC_ID_PTX, + AV_CODEC_ID_TXD, + AV_CODEC_ID_VP6A, + AV_CODEC_ID_AMV, + AV_CODEC_ID_VB, + AV_CODEC_ID_PCX, + AV_CODEC_ID_SUNRAST, + AV_CODEC_ID_INDEO4, + AV_CODEC_ID_INDEO5, + AV_CODEC_ID_MIMIC, + AV_CODEC_ID_RL2, + AV_CODEC_ID_ESCAPE124, + AV_CODEC_ID_DIRAC, + AV_CODEC_ID_BFI, + AV_CODEC_ID_CMV, + AV_CODEC_ID_MOTIONPIXELS, + AV_CODEC_ID_TGV, + AV_CODEC_ID_TGQ, + AV_CODEC_ID_TQI, + AV_CODEC_ID_AURA, + AV_CODEC_ID_AURA2, + AV_CODEC_ID_V210X, + AV_CODEC_ID_TMV, + AV_CODEC_ID_V210, + AV_CODEC_ID_DPX, + AV_CODEC_ID_MAD, + AV_CODEC_ID_FRWU, + AV_CODEC_ID_FLASHSV2, + AV_CODEC_ID_CDGRAPHICS, + AV_CODEC_ID_R210, + AV_CODEC_ID_ANM, + AV_CODEC_ID_BINKVIDEO, + AV_CODEC_ID_IFF_ILBM, +#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM + AV_CODEC_ID_KGV1, + AV_CODEC_ID_YOP, + AV_CODEC_ID_VP8, + AV_CODEC_ID_PICTOR, + AV_CODEC_ID_ANSI, + AV_CODEC_ID_A64_MULTI, + AV_CODEC_ID_A64_MULTI5, + AV_CODEC_ID_R10K, + AV_CODEC_ID_MXPEG, + AV_CODEC_ID_LAGARITH, + AV_CODEC_ID_PRORES, + AV_CODEC_ID_JV, + AV_CODEC_ID_DFA, + AV_CODEC_ID_WMV3IMAGE, + AV_CODEC_ID_VC1IMAGE, + AV_CODEC_ID_UTVIDEO, + AV_CODEC_ID_BMV_VIDEO, + AV_CODEC_ID_VBLE, + AV_CODEC_ID_DXTORY, + AV_CODEC_ID_V410, + AV_CODEC_ID_XWD, + AV_CODEC_ID_CDXL, + AV_CODEC_ID_XBM, + AV_CODEC_ID_ZEROCODEC, + AV_CODEC_ID_MSS1, + AV_CODEC_ID_MSA1, + AV_CODEC_ID_TSCC2, + AV_CODEC_ID_MTS2, + AV_CODEC_ID_CLLC, + AV_CODEC_ID_MSS2, + AV_CODEC_ID_VP9, + AV_CODEC_ID_AIC, + AV_CODEC_ID_ESCAPE130, + AV_CODEC_ID_G2M, + AV_CODEC_ID_WEBP, + AV_CODEC_ID_HNM4_VIDEO, + AV_CODEC_ID_HEVC, +#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC + AV_CODEC_ID_FIC, + AV_CODEC_ID_ALIAS_PIX, + AV_CODEC_ID_BRENDER_PIX, + AV_CODEC_ID_PAF_VIDEO, + AV_CODEC_ID_EXR, + AV_CODEC_ID_VP7, + AV_CODEC_ID_SANM, + AV_CODEC_ID_SGIRLE, + AV_CODEC_ID_MVC1, + AV_CODEC_ID_MVC2, + AV_CODEC_ID_HQX, + AV_CODEC_ID_TDSC, + AV_CODEC_ID_HQ_HQA, + AV_CODEC_ID_HAP, + AV_CODEC_ID_DDS, + AV_CODEC_ID_DXV, + AV_CODEC_ID_SCREENPRESSO, + AV_CODEC_ID_RSCC, + AV_CODEC_ID_AVS2, + AV_CODEC_ID_PGX, + AV_CODEC_ID_AVS3, + AV_CODEC_ID_MSP2, + AV_CODEC_ID_VVC, +#define AV_CODEC_ID_H266 AV_CODEC_ID_VVC + AV_CODEC_ID_Y41P, + AV_CODEC_ID_AVRP, + AV_CODEC_ID_012V, + AV_CODEC_ID_AVUI, + AV_CODEC_ID_AYUV, + AV_CODEC_ID_TARGA_Y216, + AV_CODEC_ID_V308, + AV_CODEC_ID_V408, + AV_CODEC_ID_YUV4, + AV_CODEC_ID_AVRN, + AV_CODEC_ID_CPIA, + AV_CODEC_ID_XFACE, + AV_CODEC_ID_SNOW, + AV_CODEC_ID_SMVJPEG, + AV_CODEC_ID_APNG, + AV_CODEC_ID_DAALA, + AV_CODEC_ID_CFHD, + AV_CODEC_ID_TRUEMOTION2RT, + AV_CODEC_ID_M101, + AV_CODEC_ID_MAGICYUV, + AV_CODEC_ID_SHEERVIDEO, + AV_CODEC_ID_YLC, + AV_CODEC_ID_PSD, + AV_CODEC_ID_PIXLET, + AV_CODEC_ID_SPEEDHQ, + AV_CODEC_ID_FMVC, + AV_CODEC_ID_SCPR, + AV_CODEC_ID_CLEARVIDEO, + AV_CODEC_ID_XPM, + AV_CODEC_ID_AV1, + AV_CODEC_ID_BITPACKED, + AV_CODEC_ID_MSCC, + AV_CODEC_ID_SRGC, + AV_CODEC_ID_SVG, + AV_CODEC_ID_GDV, + AV_CODEC_ID_FITS, + AV_CODEC_ID_IMM4, + AV_CODEC_ID_PROSUMER, + AV_CODEC_ID_MWSC, + AV_CODEC_ID_WCMV, + AV_CODEC_ID_RASC, + AV_CODEC_ID_HYMT, + AV_CODEC_ID_ARBC, + AV_CODEC_ID_AGM, + AV_CODEC_ID_LSCR, + AV_CODEC_ID_VP4, + AV_CODEC_ID_IMM5, + AV_CODEC_ID_MVDV, + AV_CODEC_ID_MVHA, + AV_CODEC_ID_CDTOONS, + AV_CODEC_ID_MV30, + AV_CODEC_ID_NOTCHLC, + AV_CODEC_ID_PFM, + AV_CODEC_ID_MOBICLIP, + AV_CODEC_ID_PHOTOCD, + AV_CODEC_ID_IPU, + AV_CODEC_ID_ARGO, + AV_CODEC_ID_CRI, + AV_CODEC_ID_SIMBIOSIS_IMX, + AV_CODEC_ID_SGA_VIDEO, + AV_CODEC_ID_GEM, + AV_CODEC_ID_VBN, + AV_CODEC_ID_JPEGXL, + AV_CODEC_ID_QOI, + AV_CODEC_ID_PHM, + + /* various PCM "codecs" */ + AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs + AV_CODEC_ID_PCM_S16LE = 0x10000, + AV_CODEC_ID_PCM_S16BE, + AV_CODEC_ID_PCM_U16LE, + AV_CODEC_ID_PCM_U16BE, + AV_CODEC_ID_PCM_S8, + AV_CODEC_ID_PCM_U8, + AV_CODEC_ID_PCM_MULAW, + AV_CODEC_ID_PCM_ALAW, + AV_CODEC_ID_PCM_S32LE, + AV_CODEC_ID_PCM_S32BE, + AV_CODEC_ID_PCM_U32LE, + AV_CODEC_ID_PCM_U32BE, + AV_CODEC_ID_PCM_S24LE, + AV_CODEC_ID_PCM_S24BE, + AV_CODEC_ID_PCM_U24LE, + AV_CODEC_ID_PCM_U24BE, + AV_CODEC_ID_PCM_S24DAUD, + AV_CODEC_ID_PCM_ZORK, + AV_CODEC_ID_PCM_S16LE_PLANAR, + AV_CODEC_ID_PCM_DVD, + AV_CODEC_ID_PCM_F32BE, + AV_CODEC_ID_PCM_F32LE, + AV_CODEC_ID_PCM_F64BE, + AV_CODEC_ID_PCM_F64LE, + AV_CODEC_ID_PCM_BLURAY, + AV_CODEC_ID_PCM_LXF, + AV_CODEC_ID_S302M, + AV_CODEC_ID_PCM_S8_PLANAR, + AV_CODEC_ID_PCM_S24LE_PLANAR, + AV_CODEC_ID_PCM_S32LE_PLANAR, + AV_CODEC_ID_PCM_S16BE_PLANAR, + AV_CODEC_ID_PCM_S64LE, + AV_CODEC_ID_PCM_S64BE, + AV_CODEC_ID_PCM_F16LE, + AV_CODEC_ID_PCM_F24LE, + AV_CODEC_ID_PCM_VIDC, + AV_CODEC_ID_PCM_SGA, + + /* various ADPCM codecs */ + AV_CODEC_ID_ADPCM_IMA_QT = 0x11000, + AV_CODEC_ID_ADPCM_IMA_WAV, + AV_CODEC_ID_ADPCM_IMA_DK3, + AV_CODEC_ID_ADPCM_IMA_DK4, + AV_CODEC_ID_ADPCM_IMA_WS, + AV_CODEC_ID_ADPCM_IMA_SMJPEG, + AV_CODEC_ID_ADPCM_MS, + AV_CODEC_ID_ADPCM_4XM, + AV_CODEC_ID_ADPCM_XA, + AV_CODEC_ID_ADPCM_ADX, + AV_CODEC_ID_ADPCM_EA, + AV_CODEC_ID_ADPCM_G726, + AV_CODEC_ID_ADPCM_CT, + AV_CODEC_ID_ADPCM_SWF, + AV_CODEC_ID_ADPCM_YAMAHA, + AV_CODEC_ID_ADPCM_SBPRO_4, + AV_CODEC_ID_ADPCM_SBPRO_3, + AV_CODEC_ID_ADPCM_SBPRO_2, + AV_CODEC_ID_ADPCM_THP, + AV_CODEC_ID_ADPCM_IMA_AMV, + AV_CODEC_ID_ADPCM_EA_R1, + AV_CODEC_ID_ADPCM_EA_R3, + AV_CODEC_ID_ADPCM_EA_R2, + AV_CODEC_ID_ADPCM_IMA_EA_SEAD, + AV_CODEC_ID_ADPCM_IMA_EA_EACS, + AV_CODEC_ID_ADPCM_EA_XAS, + AV_CODEC_ID_ADPCM_EA_MAXIS_XA, + AV_CODEC_ID_ADPCM_IMA_ISS, + AV_CODEC_ID_ADPCM_G722, + AV_CODEC_ID_ADPCM_IMA_APC, + AV_CODEC_ID_ADPCM_VIMA, + AV_CODEC_ID_ADPCM_AFC, + AV_CODEC_ID_ADPCM_IMA_OKI, + AV_CODEC_ID_ADPCM_DTK, + AV_CODEC_ID_ADPCM_IMA_RAD, + AV_CODEC_ID_ADPCM_G726LE, + AV_CODEC_ID_ADPCM_THP_LE, + AV_CODEC_ID_ADPCM_PSX, + AV_CODEC_ID_ADPCM_AICA, + AV_CODEC_ID_ADPCM_IMA_DAT4, + AV_CODEC_ID_ADPCM_MTAF, + AV_CODEC_ID_ADPCM_AGM, + AV_CODEC_ID_ADPCM_ARGO, + AV_CODEC_ID_ADPCM_IMA_SSI, + AV_CODEC_ID_ADPCM_ZORK, + AV_CODEC_ID_ADPCM_IMA_APM, + AV_CODEC_ID_ADPCM_IMA_ALP, + AV_CODEC_ID_ADPCM_IMA_MTF, + AV_CODEC_ID_ADPCM_IMA_CUNNING, + AV_CODEC_ID_ADPCM_IMA_MOFLEX, + AV_CODEC_ID_ADPCM_IMA_ACORN, + + /* AMR */ + AV_CODEC_ID_AMR_NB = 0x12000, + AV_CODEC_ID_AMR_WB, + + /* RealAudio codecs*/ + AV_CODEC_ID_RA_144 = 0x13000, + AV_CODEC_ID_RA_288, + + /* various DPCM codecs */ + AV_CODEC_ID_ROQ_DPCM = 0x14000, + AV_CODEC_ID_INTERPLAY_DPCM, + AV_CODEC_ID_XAN_DPCM, + AV_CODEC_ID_SOL_DPCM, + AV_CODEC_ID_SDX2_DPCM, + AV_CODEC_ID_GREMLIN_DPCM, + AV_CODEC_ID_DERF_DPCM, + + /* audio codecs */ + AV_CODEC_ID_MP2 = 0x15000, + AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 + AV_CODEC_ID_AAC, + AV_CODEC_ID_AC3, + AV_CODEC_ID_DTS, + AV_CODEC_ID_VORBIS, + AV_CODEC_ID_DVAUDIO, + AV_CODEC_ID_WMAV1, + AV_CODEC_ID_WMAV2, + AV_CODEC_ID_MACE3, + AV_CODEC_ID_MACE6, + AV_CODEC_ID_VMDAUDIO, + AV_CODEC_ID_FLAC, + AV_CODEC_ID_MP3ADU, + AV_CODEC_ID_MP3ON4, + AV_CODEC_ID_SHORTEN, + AV_CODEC_ID_ALAC, + AV_CODEC_ID_WESTWOOD_SND1, + AV_CODEC_ID_GSM, ///< as in Berlin toast format + AV_CODEC_ID_QDM2, + AV_CODEC_ID_COOK, + AV_CODEC_ID_TRUESPEECH, + AV_CODEC_ID_TTA, + AV_CODEC_ID_SMACKAUDIO, + AV_CODEC_ID_QCELP, + AV_CODEC_ID_WAVPACK, + AV_CODEC_ID_DSICINAUDIO, + AV_CODEC_ID_IMC, + AV_CODEC_ID_MUSEPACK7, + AV_CODEC_ID_MLP, + AV_CODEC_ID_GSM_MS, /* as found in WAV */ + AV_CODEC_ID_ATRAC3, + AV_CODEC_ID_APE, + AV_CODEC_ID_NELLYMOSER, + AV_CODEC_ID_MUSEPACK8, + AV_CODEC_ID_SPEEX, + AV_CODEC_ID_WMAVOICE, + AV_CODEC_ID_WMAPRO, + AV_CODEC_ID_WMALOSSLESS, + AV_CODEC_ID_ATRAC3P, + AV_CODEC_ID_EAC3, + AV_CODEC_ID_SIPR, + AV_CODEC_ID_MP1, + AV_CODEC_ID_TWINVQ, + AV_CODEC_ID_TRUEHD, + AV_CODEC_ID_MP4ALS, + AV_CODEC_ID_ATRAC1, + AV_CODEC_ID_BINKAUDIO_RDFT, + AV_CODEC_ID_BINKAUDIO_DCT, + AV_CODEC_ID_AAC_LATM, + AV_CODEC_ID_QDMC, + AV_CODEC_ID_CELT, + AV_CODEC_ID_G723_1, + AV_CODEC_ID_G729, + AV_CODEC_ID_8SVX_EXP, + AV_CODEC_ID_8SVX_FIB, + AV_CODEC_ID_BMV_AUDIO, + AV_CODEC_ID_RALF, + AV_CODEC_ID_IAC, + AV_CODEC_ID_ILBC, + AV_CODEC_ID_OPUS, + AV_CODEC_ID_COMFORT_NOISE, + AV_CODEC_ID_TAK, + AV_CODEC_ID_METASOUND, + AV_CODEC_ID_PAF_AUDIO, + AV_CODEC_ID_ON2AVC, + AV_CODEC_ID_DSS_SP, + AV_CODEC_ID_CODEC2, + AV_CODEC_ID_FFWAVESYNTH, + AV_CODEC_ID_SONIC, + AV_CODEC_ID_SONIC_LS, + AV_CODEC_ID_EVRC, + AV_CODEC_ID_SMV, + AV_CODEC_ID_DSD_LSBF, + AV_CODEC_ID_DSD_MSBF, + AV_CODEC_ID_DSD_LSBF_PLANAR, + AV_CODEC_ID_DSD_MSBF_PLANAR, + AV_CODEC_ID_4GV, + AV_CODEC_ID_INTERPLAY_ACM, + AV_CODEC_ID_XMA1, + AV_CODEC_ID_XMA2, + AV_CODEC_ID_DST, + AV_CODEC_ID_ATRAC3AL, + AV_CODEC_ID_ATRAC3PAL, + AV_CODEC_ID_DOLBY_E, + AV_CODEC_ID_APTX, + AV_CODEC_ID_APTX_HD, + AV_CODEC_ID_SBC, + AV_CODEC_ID_ATRAC9, + AV_CODEC_ID_HCOM, + AV_CODEC_ID_ACELP_KELVIN, + AV_CODEC_ID_MPEGH_3D_AUDIO, + AV_CODEC_ID_SIREN, + AV_CODEC_ID_HCA, + AV_CODEC_ID_FASTAUDIO, + AV_CODEC_ID_MSNSIREN, + AV_CODEC_ID_DFPWM, + + /* subtitle codecs */ + AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. + AV_CODEC_ID_DVD_SUBTITLE = 0x17000, + AV_CODEC_ID_DVB_SUBTITLE, + AV_CODEC_ID_TEXT, ///< raw UTF-8 text + AV_CODEC_ID_XSUB, + AV_CODEC_ID_SSA, + AV_CODEC_ID_MOV_TEXT, + AV_CODEC_ID_HDMV_PGS_SUBTITLE, + AV_CODEC_ID_DVB_TELETEXT, + AV_CODEC_ID_SRT, + AV_CODEC_ID_MICRODVD, + AV_CODEC_ID_EIA_608, + AV_CODEC_ID_JACOSUB, + AV_CODEC_ID_SAMI, + AV_CODEC_ID_REALTEXT, + AV_CODEC_ID_STL, + AV_CODEC_ID_SUBVIEWER1, + AV_CODEC_ID_SUBVIEWER, + AV_CODEC_ID_SUBRIP, + AV_CODEC_ID_WEBVTT, + AV_CODEC_ID_MPL2, + AV_CODEC_ID_VPLAYER, + AV_CODEC_ID_PJS, + AV_CODEC_ID_ASS, + AV_CODEC_ID_HDMV_TEXT_SUBTITLE, + AV_CODEC_ID_TTML, + AV_CODEC_ID_ARIB_CAPTION, + + /* other specific kind of codecs (generally used for attachments) */ + AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. + AV_CODEC_ID_TTF = 0x18000, + + AV_CODEC_ID_SCTE_35, ///< Contain timestamp estimated through PCR of program stream. + AV_CODEC_ID_EPG, + AV_CODEC_ID_BINTEXT, + AV_CODEC_ID_XBIN, + AV_CODEC_ID_IDF, + AV_CODEC_ID_OTF, + AV_CODEC_ID_SMPTE_KLV, + AV_CODEC_ID_DVD_NAV, + AV_CODEC_ID_TIMED_ID3, + AV_CODEC_ID_BIN_DATA, + + + AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it + + AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + * stream (only used by libavformat) */ + AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems + * stream (only used by libavformat) */ + AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. + AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket +}; + +/** + * Get the type of the given codec. + */ +enum AVMediaType avcodec_get_type(enum AVCodecID codec_id); + +/** + * Get the name of a codec. + * @return a static string identifying the codec; never NULL + */ +const char *avcodec_get_name(enum AVCodecID id); + +/** + * Return codec bits per sample. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return codec bits per sample. + * Only return non-zero if the bits per sample is exactly correct, not an + * approximation. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_exact_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return a name for the specified profile, if available. + * + * @param codec_id the ID of the codec to which the requested profile belongs + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + * + * @note unlike av_get_profile_name(), which searches a list of profiles + * supported by a specific decoder or encoder implementation, this + * function searches the list of profiles from the AVCodecDescriptor + */ +const char *avcodec_profile_name(enum AVCodecID codec_id, int profile); + +/** + * Return the PCM codec associated with a sample format. + * @param be endianness, 0 for little, 1 for big, + * -1 (or anything else) for native + * @return AV_CODEC_ID_PCM_* or AV_CODEC_ID_NONE + */ +enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_ID_H diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec_par.h b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec_par.h new file mode 100644 index 0000000000000..7660791a12e2a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/codec_par.h @@ -0,0 +1,246 @@ +/* + * Codec parameters public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_PAR_H +#define AVCODEC_CODEC_PAR_H + +#include + +#include "libavutil/avutil.h" +#include "libavutil/channel_layout.h" +#include "libavutil/rational.h" +#include "libavutil/pixfmt.h" + +#include "codec_id.h" + +/** + * @addtogroup lavc_core + */ + +enum AVFieldOrder { + AV_FIELD_UNKNOWN, + AV_FIELD_PROGRESSIVE, + AV_FIELD_TT, //< Top coded_first, top displayed first + AV_FIELD_BB, //< Bottom coded first, bottom displayed first + AV_FIELD_TB, //< Top coded first, bottom displayed first + AV_FIELD_BT, //< Bottom coded first, top displayed first +}; + +/** + * This struct describes the properties of an encoded stream. + * + * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must + * be allocated with avcodec_parameters_alloc() and freed with + * avcodec_parameters_free(). + */ +typedef struct AVCodecParameters { + /** + * General type of the encoded data. + */ + enum AVMediaType codec_type; + /** + * Specific type of the encoded data (the codec used). + */ + enum AVCodecID codec_id; + /** + * Additional information about the codec (corresponds to the AVI FOURCC). + */ + uint32_t codec_tag; + + /** + * Extra binary data needed for initializing the decoder, codec-dependent. + * + * Must be allocated with av_malloc() and will be freed by + * avcodec_parameters_free(). The allocated size of extradata must be at + * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding + * bytes zeroed. + */ + uint8_t *extradata; + /** + * Size of the extradata content in bytes. + */ + int extradata_size; + + /** + * - video: the pixel format, the value corresponds to enum AVPixelFormat. + * - audio: the sample format, the value corresponds to enum AVSampleFormat. + */ + int format; + + /** + * The average bitrate of the encoded data (in bits per second). + */ + int64_t bit_rate; + + /** + * The number of bits per sample in the codedwords. + * + * This is basically the bitrate per sample. It is mandatory for a bunch of + * formats to actually decode them. It's the number of bits for one sample in + * the actual coded bitstream. + * + * This could be for example 4 for ADPCM + * For PCM formats this matches bits_per_raw_sample + * Can be 0 + */ + int bits_per_coded_sample; + + /** + * This is the number of valid bits in each output sample. If the + * sample format has more bits, the least significant bits are additional + * padding bits, which are always 0. Use right shifts to reduce the sample + * to its actual size. For example, audio formats with 24 bit samples will + * have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32. + * To get the original sample use "(int32_t)sample >> 8"." + * + * For ADPCM this might be 12 or 16 or similar + * Can be 0 + */ + int bits_per_raw_sample; + + /** + * Codec-specific bitstream restrictions that the stream conforms to. + */ + int profile; + int level; + + /** + * Video only. The dimensions of the video frame in pixels. + */ + int width; + int height; + + /** + * Video only. The aspect ratio (width / height) which a single pixel + * should have when displayed. + * + * When the aspect ratio is unknown / undefined, the numerator should be + * set to 0 (the denominator may have any value). + */ + AVRational sample_aspect_ratio; + + /** + * Video only. The order of the fields in interlaced video. + */ + enum AVFieldOrder field_order; + + /** + * Video only. Additional colorspace characteristics. + */ + enum AVColorRange color_range; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace color_space; + enum AVChromaLocation chroma_location; + + /** + * Video only. Number of delayed frames. + */ + int video_delay; + +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * Audio only. The channel layout bitmask. May be 0 if the channel layout is + * unknown or unspecified, otherwise the number of bits set must be equal to + * the channels field. + * @deprecated use ch_layout + */ + attribute_deprecated + uint64_t channel_layout; + /** + * Audio only. The number of audio channels. + * @deprecated use ch_layout.nb_channels + */ + attribute_deprecated + int channels; +#endif + /** + * Audio only. The number of audio samples per second. + */ + int sample_rate; + /** + * Audio only. The number of bytes per coded audio frame, required by some + * formats. + * + * Corresponds to nBlockAlign in WAVEFORMATEX. + */ + int block_align; + /** + * Audio only. Audio frame size, if known. Required by some formats to be static. + */ + int frame_size; + + /** + * Audio only. The amount of padding (in samples) inserted by the encoder at + * the beginning of the audio. I.e. this number of leading decoded samples + * must be discarded by the caller to get the original audio without leading + * padding. + */ + int initial_padding; + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + */ + int trailing_padding; + /** + * Audio only. Number of samples to skip after a discontinuity. + */ + int seek_preroll; + + /** + * Audio only. The channel layout and number of channels. + */ + AVChannelLayout ch_layout; +} AVCodecParameters; + +/** + * Allocate a new AVCodecParameters and set its fields to default values + * (unknown/invalid/0). The returned struct must be freed with + * avcodec_parameters_free(). + */ +AVCodecParameters *avcodec_parameters_alloc(void); + +/** + * Free an AVCodecParameters instance and everything associated with it and + * write NULL to the supplied pointer. + */ +void avcodec_parameters_free(AVCodecParameters **par); + +/** + * Copy the contents of src to dst. Any allocated fields in dst are freed and + * replaced with newly allocated duplicates of the corresponding fields in src. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src); + +/** + * This function is the same as av_get_audio_frame_duration(), except it works + * with AVCodecParameters instead of an AVCodecContext. + */ +int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_PAR_H diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/defs.h b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/defs.h new file mode 100644 index 0000000000000..420a042b8ff45 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/defs.h @@ -0,0 +1,170 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DEFS_H +#define AVCODEC_DEFS_H + +/** + * @file + * @ingroup libavc + * Misc types and constants that do not belong anywhere else. + */ + +#include +#include + +/** + * @ingroup lavc_decoding + * Required number of additionally allocated bytes at the end of the input bitstream for decoding. + * This is mainly needed because some optimized bitstream readers read + * 32 or 64 bit at once and could read over the end.
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged + * MPEG bitstreams could cause overread and segfault. + */ +#define AV_INPUT_BUFFER_PADDING_SIZE 64 + +/** + * @ingroup lavc_decoding + */ +enum AVDiscard{ + /* We leave some space between them for extensions (drop some + * keyframes for intra-only or drop just some bidir frames). */ + AVDISCARD_NONE =-16, ///< discard nothing + AVDISCARD_DEFAULT = 0, ///< discard useless packets like 0 size packets in avi + AVDISCARD_NONREF = 8, ///< discard all non reference + AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames + AVDISCARD_NONINTRA= 24, ///< discard all non intra frames + AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes + AVDISCARD_ALL = 48, ///< discard all +}; + +enum AVAudioServiceType { + AV_AUDIO_SERVICE_TYPE_MAIN = 0, + AV_AUDIO_SERVICE_TYPE_EFFECTS = 1, + AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED = 2, + AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED = 3, + AV_AUDIO_SERVICE_TYPE_DIALOGUE = 4, + AV_AUDIO_SERVICE_TYPE_COMMENTARY = 5, + AV_AUDIO_SERVICE_TYPE_EMERGENCY = 6, + AV_AUDIO_SERVICE_TYPE_VOICE_OVER = 7, + AV_AUDIO_SERVICE_TYPE_KARAOKE = 8, + AV_AUDIO_SERVICE_TYPE_NB , ///< Not part of ABI +}; + +/** + * Pan Scan area. + * This specifies the area which should be displayed. + * Note there may be multiple such areas for one frame. + */ +typedef struct AVPanScan { + /** + * id + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int id; + + /** + * width and height in 1/16 pel + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int width; + int height; + + /** + * position of the top left corner in 1/16 pel for up to 3 fields/frames + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int16_t position[3][2]; +} AVPanScan; + +/** + * This structure describes the bitrate properties of an encoded bitstream. It + * roughly corresponds to a subset the VBV parameters for MPEG-2 or HRD + * parameters for H.264/HEVC. + */ +typedef struct AVCPBProperties { + /** + * Maximum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int64_t max_bitrate; + /** + * Minimum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int64_t min_bitrate; + /** + * Average bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int64_t avg_bitrate; + + /** + * The size of the buffer to which the ratecontrol is applied, in bits. + * Zero if unknown or unspecified. + */ + int64_t buffer_size; + + /** + * The delay between the time the packet this structure is associated with + * is received and the time when it should be decoded, in periods of a 27MHz + * clock. + * + * UINT64_MAX when unknown or unspecified. + */ + uint64_t vbv_delay; +} AVCPBProperties; + +/** + * Allocate a CPB properties structure and initialize its fields to default + * values. + * + * @param size if non-NULL, the size of the allocated struct will be written + * here. This is useful for embedding it in side data. + * + * @return the newly allocated struct or NULL on failure + */ +AVCPBProperties *av_cpb_properties_alloc(size_t *size); + +/** + * This structure supplies correlation between a packet timestamp and a wall clock + * production time. The definition follows the Producer Reference Time ('prft') + * as defined in ISO/IEC 14496-12 + */ +typedef struct AVProducerReferenceTime { + /** + * A UTC timestamp, in microseconds, since Unix epoch (e.g, av_gettime()). + */ + int64_t wallclock; + int flags; +} AVProducerReferenceTime; + +/** + * Encode extradata length to a buffer. Used by xiph codecs. + * + * @param s buffer to write to; must be at least (v/255+1) bytes long + * @param v size of extradata in bytes + * @return number of bytes written to the buffer. + */ +unsigned int av_xiphlacing(unsigned char *s, unsigned int v); + +#endif // AVCODEC_DEFS_H diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/packet.h b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/packet.h new file mode 100644 index 0000000000000..404d520071ee1 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/packet.h @@ -0,0 +1,731 @@ +/* + * AVPacket public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_PACKET_H +#define AVCODEC_PACKET_H + +#include +#include + +#include "libavutil/attributes.h" +#include "libavutil/buffer.h" +#include "libavutil/dict.h" +#include "libavutil/rational.h" +#include "libavutil/version.h" + +#include "libavcodec/version_major.h" + +/** + * @defgroup lavc_packet AVPacket + * + * Types and functions for working with AVPacket. + * @{ + */ +enum AVPacketSideDataType { + /** + * An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE + * bytes worth of palette. This side data signals that a new palette is + * present. + */ + AV_PKT_DATA_PALETTE, + + /** + * The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format + * that the extradata buffer was changed and the receiving side should + * act upon it appropriately. The new extradata is embedded in the side + * data buffer and should be immediately used for processing the current + * frame or packet. + */ + AV_PKT_DATA_NEW_EXTRADATA, + + /** + * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows: + * @code + * u32le param_flags + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) + * s32le channel_count + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) + * u64le channel_layout + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) + * s32le sample_rate + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) + * s32le width + * s32le height + * @endcode + */ + AV_PKT_DATA_PARAM_CHANGE, + + /** + * An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of + * structures with info about macroblocks relevant to splitting the + * packet into smaller packets on macroblock edges (e.g. as for RFC 2190). + * That is, it does not necessarily contain info about all macroblocks, + * as long as the distance between macroblocks in the info is smaller + * than the target payload size. + * Each MB info structure is 12 bytes, and is laid out as follows: + * @code + * u32le bit offset from the start of the packet + * u8 current quantizer at the start of the macroblock + * u8 GOB number + * u16le macroblock address within the GOB + * u8 horizontal MV predictor + * u8 vertical MV predictor + * u8 horizontal MV predictor for block number 3 + * u8 vertical MV predictor for block number 3 + * @endcode + */ + AV_PKT_DATA_H263_MB_INFO, + + /** + * This side data should be associated with an audio stream and contains + * ReplayGain information in form of the AVReplayGain struct. + */ + AV_PKT_DATA_REPLAYGAIN, + + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the decoded video frames for + * correct presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_PKT_DATA_DISPLAYMATRIX, + + /** + * This side data should be associated with a video stream and contains + * Stereoscopic 3D information in form of the AVStereo3D struct. + */ + AV_PKT_DATA_STEREO3D, + + /** + * This side data should be associated with an audio stream and corresponds + * to enum AVAudioServiceType. + */ + AV_PKT_DATA_AUDIO_SERVICE_TYPE, + + /** + * This side data contains quality related information from the encoder. + * @code + * u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad). + * u8 picture type + * u8 error count + * u16 reserved + * u64le[error count] sum of squared differences between encoder in and output + * @endcode + */ + AV_PKT_DATA_QUALITY_STATS, + + /** + * This side data contains an integer value representing the stream index + * of a "fallback" track. A fallback track indicates an alternate + * track to use when the current track can not be decoded for some reason. + * e.g. no decoder available for codec. + */ + AV_PKT_DATA_FALLBACK_TRACK, + + /** + * This side data corresponds to the AVCPBProperties struct. + */ + AV_PKT_DATA_CPB_PROPERTIES, + + /** + * Recommmends skipping the specified number of samples + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_PKT_DATA_SKIP_SAMPLES, + + /** + * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that + * the packet may contain "dual mono" audio specific to Japanese DTV + * and if it is true, recommends only the selected channel to be used. + * @code + * u8 selected channels (0=mail/left, 1=sub/right, 2=both) + * @endcode + */ + AV_PKT_DATA_JP_DUALMONO, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. + */ + AV_PKT_DATA_STRINGS_METADATA, + + /** + * Subtitle event position + * @code + * u32le x1 + * u32le y1 + * u32le x2 + * u32le y2 + * @endcode + */ + AV_PKT_DATA_SUBTITLE_POSITION, + + /** + * Data found in BlockAdditional element of matroska container. There is + * no end marker for the data, so it is required to rely on the side data + * size to recognize the end. 8 byte id (as found in BlockAddId) followed + * by data. + */ + AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + + /** + * The optional first identifier line of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_IDENTIFIER, + + /** + * The optional settings (rendering instructions) that immediately + * follow the timestamp specifier of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_SETTINGS, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. This + * side data includes updated metadata which appeared in the stream. + */ + AV_PKT_DATA_METADATA_UPDATE, + + /** + * MPEGTS stream ID as uint8_t, this is required to pass the stream ID + * information from the demuxer to the corresponding muxer. + */ + AV_PKT_DATA_MPEGTS_STREAM_ID, + + /** + * Mastering display metadata (based on SMPTE-2086:2014). This metadata + * should be associated with a video stream and contains data in the form + * of the AVMasteringDisplayMetadata struct. + */ + AV_PKT_DATA_MASTERING_DISPLAY_METADATA, + + /** + * This side data should be associated with a video stream and corresponds + * to the AVSphericalMapping structure. + */ + AV_PKT_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This metadata should be + * associated with a video stream and contains data in the form of the + * AVContentLightMetadata struct. + */ + AV_PKT_DATA_CONTENT_LIGHT_LEVEL, + + /** + * ATSC A53 Part 4 Closed Captions. This metadata should be associated with + * a video stream. A53 CC bitstream is stored as uint8_t in AVPacketSideData.data. + * The number of bytes of CC data is AVPacketSideData.size. + */ + AV_PKT_DATA_A53_CC, + + /** + * This side data is encryption initialization data. + * The format is not part of ABI, use av_encryption_init_info_* methods to + * access. + */ + AV_PKT_DATA_ENCRYPTION_INIT_INFO, + + /** + * This side data contains encryption info for how to decrypt the packet. + * The format is not part of ABI, use av_encryption_info_* methods to access. + */ + AV_PKT_DATA_ENCRYPTION_INFO, + + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_PKT_DATA_AFD, + + /** + * Producer Reference Time data corresponding to the AVProducerReferenceTime struct, + * usually exported by some encoders (on demand through the prft flag set in the + * AVCodecContext export_side_data field). + */ + AV_PKT_DATA_PRFT, + + /** + * ICC profile data consisting of an opaque octet buffer following the + * format described by ISO 15076-1. + */ + AV_PKT_DATA_ICC_PROFILE, + + /** + * DOVI configuration + * ref: + * dolby-vision-bitstreams-within-the-iso-base-media-file-format-v2.1.2, section 2.2 + * dolby-vision-bitstreams-in-mpeg-2-transport-stream-multiplex-v1.2, section 3.3 + * Tags are stored in struct AVDOVIDecoderConfigurationRecord. + */ + AV_PKT_DATA_DOVI_CONF, + + /** + * Timecode which conforms to SMPTE ST 12-1:2014. The data is an array of 4 uint32_t + * where the first uint32_t describes how many (1-3) of the other timecodes are used. + * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.h. + */ + AV_PKT_DATA_S12M_TIMECODE, + + /** + * HDR10+ dynamic metadata associated with a video frame. The metadata is in + * the form of the AVDynamicHDRPlus struct and contains + * information for color volume transform - application 4 of + * SMPTE 2094-40:2016 standard. + */ + AV_PKT_DATA_DYNAMIC_HDR10_PLUS, + + /** + * The number of side data types. + * This is not part of the public API/ABI in the sense that it may + * change when new side data types are added. + * This must stay the last enum value. + * If its value becomes huge, some code using it + * needs to be updated as it assumes it to be smaller than other limits. + */ + AV_PKT_DATA_NB +}; + +#define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED + +typedef struct AVPacketSideData { + uint8_t *data; + size_t size; + enum AVPacketSideDataType type; +} AVPacketSideData; + +/** + * This structure stores compressed data. It is typically exported by demuxers + * and then passed as input to decoders, or received as output from encoders and + * then passed to muxers. + * + * For video, it should typically contain one compressed frame. For audio it may + * contain several compressed frames. Encoders are allowed to output empty + * packets, with no compressed data, containing only side data + * (e.g. to update some stream parameters at the end of encoding). + * + * The semantics of data ownership depends on the buf field. + * If it is set, the packet data is dynamically allocated and is + * valid indefinitely until a call to av_packet_unref() reduces the + * reference count to 0. + * + * If the buf field is not set av_packet_ref() would make a copy instead + * of increasing the reference count. + * + * The side data is always allocated with av_malloc(), copied by + * av_packet_ref() and freed by av_packet_unref(). + * + * sizeof(AVPacket) being a part of the public ABI is deprecated. once + * av_init_packet() is removed, new packets will only be able to be allocated + * with av_packet_alloc(), and new fields may be added to the end of the struct + * with a minor bump. + * + * @see av_packet_alloc + * @see av_packet_ref + * @see av_packet_unref + */ +typedef struct AVPacket { + /** + * A reference to the reference-counted buffer where the packet data is + * stored. + * May be NULL, then the packet data is not reference-counted. + */ + AVBufferRef *buf; + /** + * Presentation timestamp in AVStream->time_base units; the time at which + * the decompressed packet will be presented to the user. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + * pts MUST be larger or equal to dts as presentation cannot happen before + * decompression, unless one wants to view hex dumps. Some formats misuse + * the terms dts and pts/cts to mean something different. Such timestamps + * must be converted to true pts/dts before they are stored in AVPacket. + */ + int64_t pts; + /** + * Decompression timestamp in AVStream->time_base units; the time at which + * the packet is decompressed. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + */ + int64_t dts; + uint8_t *data; + int size; + int stream_index; + /** + * A combination of AV_PKT_FLAG values + */ + int flags; + /** + * Additional packet data that can be provided by the container. + * Packet can contain several types of side information. + */ + AVPacketSideData *side_data; + int side_data_elems; + + /** + * Duration of this packet in AVStream->time_base units, 0 if unknown. + * Equals next_pts - this_pts in presentation order. + */ + int64_t duration; + + int64_t pos; ///< byte position in stream, -1 if unknown + + /** + * for some private data of the user + */ + void *opaque; + + /** + * AVBufferRef for free use by the API user. FFmpeg will never check the + * contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when + * the packet is unreferenced. av_packet_copy_props() calls create a new + * reference with av_buffer_ref() for the target packet's opaque_ref field. + * + * This is unrelated to the opaque field, although it serves a similar + * purpose. + */ + AVBufferRef *opaque_ref; + + /** + * Time base of the packet's timestamps. + * In the future, this field may be set on packets output by encoders or + * demuxers, but its value will be by default ignored on input to decoders + * or muxers. + */ + AVRational time_base; +} AVPacket; + +#if FF_API_INIT_PACKET +attribute_deprecated +typedef struct AVPacketList { + AVPacket pkt; + struct AVPacketList *next; +} AVPacketList; +#endif + +#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe +#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted +/** + * Flag is used to discard packets which are required to maintain valid + * decoder state but are not required for output and should be dropped + * after decoding. + **/ +#define AV_PKT_FLAG_DISCARD 0x0004 +/** + * The packet comes from a trusted source. + * + * Otherwise-unsafe constructs such as arbitrary pointers to data + * outside the packet may be followed. + */ +#define AV_PKT_FLAG_TRUSTED 0x0008 +/** + * Flag is used to indicate packets that contain frames that can + * be discarded by the decoder. I.e. Non-reference frames. + */ +#define AV_PKT_FLAG_DISPOSABLE 0x0010 + +enum AVSideDataParamChangeFlags { +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * @deprecated those are not used by any decoder + */ + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002, +#endif + AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004, + AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008, +}; + +/** + * Allocate an AVPacket and set its fields to default values. The resulting + * struct must be freed using av_packet_free(). + * + * @return An AVPacket filled with default values or NULL on failure. + * + * @note this only allocates the AVPacket itself, not the data buffers. Those + * must be allocated through other means such as av_new_packet. + * + * @see av_new_packet + */ +AVPacket *av_packet_alloc(void); + +/** + * Create a new packet that references the same data as src. + * + * This is a shortcut for av_packet_alloc()+av_packet_ref(). + * + * @return newly created AVPacket on success, NULL on error. + * + * @see av_packet_alloc + * @see av_packet_ref + */ +AVPacket *av_packet_clone(const AVPacket *src); + +/** + * Free the packet, if the packet is reference counted, it will be + * unreferenced first. + * + * @param pkt packet to be freed. The pointer will be set to NULL. + * @note passing NULL is a no-op. + */ +void av_packet_free(AVPacket **pkt); + +#if FF_API_INIT_PACKET +/** + * Initialize optional fields of a packet with default values. + * + * Note, this does not touch the data and size members, which have to be + * initialized separately. + * + * @param pkt packet + * + * @see av_packet_alloc + * @see av_packet_unref + * + * @deprecated This function is deprecated. Once it's removed, + sizeof(AVPacket) will not be a part of the ABI anymore. + */ +attribute_deprecated +void av_init_packet(AVPacket *pkt); +#endif + +/** + * Allocate the payload of a packet and initialize its fields with + * default values. + * + * @param pkt packet + * @param size wanted payload size + * @return 0 if OK, AVERROR_xxx otherwise + */ +int av_new_packet(AVPacket *pkt, int size); + +/** + * Reduce packet size, correctly zeroing padding + * + * @param pkt packet + * @param size new size + */ +void av_shrink_packet(AVPacket *pkt, int size); + +/** + * Increase packet size, correctly zeroing padding + * + * @param pkt packet + * @param grow_by number of bytes by which to increase the size of the packet + */ +int av_grow_packet(AVPacket *pkt, int grow_by); + +/** + * Initialize a reference-counted packet from av_malloc()ed data. + * + * @param pkt packet to be initialized. This function will set the data, size, + * and buf fields, all others are left untouched. + * @param data Data allocated by av_malloc() to be used as packet data. If this + * function returns successfully, the data is owned by the underlying AVBuffer. + * The caller may not access the data through other means. + * @param size size of data in bytes, without the padding. I.e. the full buffer + * size is assumed to be size + AV_INPUT_BUFFER_PADDING_SIZE. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size); + +/** + * Allocate new information of a packet. + * + * @param pkt packet + * @param type side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + size_t size); + +/** + * Wrap an existing array as a packet side data. + * + * @param pkt packet + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * pkt. + * @param size side information size + * @return a non-negative number on success, a negative AVERROR code on + * failure. On failure, the packet is unchanged and the data remains + * owned by the caller. + */ +int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + +/** + * Shrink the already allocated side data buffer + * + * @param pkt packet + * @param type side information type + * @param size new side information size + * @return 0 on success, < 0 on failure + */ +int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + size_t size); + +/** + * Get side information from packet. + * + * @param pkt packet + * @param type desired side information type + * @param size If supplied, *size will be set to the size of the side data + * or to zero if the desired side data is not present. + * @return pointer to data if present or NULL otherwise + */ +uint8_t* av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, + size_t *size); + +const char *av_packet_side_data_name(enum AVPacketSideDataType type); + +/** + * Pack a dictionary for use in side_data. + * + * @param dict The dictionary to pack. + * @param size pointer to store the size of the returned data + * @return pointer to data if successful, NULL otherwise + */ +uint8_t *av_packet_pack_dictionary(AVDictionary *dict, size_t *size); +/** + * Unpack a dictionary from side_data. + * + * @param data data from side_data + * @param size size of the data + * @param dict the metadata storage dictionary + * @return 0 on success, < 0 on failure + */ +int av_packet_unpack_dictionary(const uint8_t *data, size_t size, + AVDictionary **dict); + +/** + * Convenience function to free all the side data stored. + * All the other fields stay untouched. + * + * @param pkt packet + */ +void av_packet_free_side_data(AVPacket *pkt); + +/** + * Setup a new reference to the data described by a given packet + * + * If src is reference-counted, setup dst as a new reference to the + * buffer in src. Otherwise allocate a new buffer in dst and copy the + * data from src into it. + * + * All the other fields are copied from src. + * + * @see av_packet_unref + * + * @param dst Destination packet. Will be completely overwritten. + * @param src Source packet + * + * @return 0 on success, a negative AVERROR on error. On error, dst + * will be blank (as if returned by av_packet_alloc()). + */ +int av_packet_ref(AVPacket *dst, const AVPacket *src); + +/** + * Wipe the packet. + * + * Unreference the buffer referenced by the packet and reset the + * remaining packet fields to their default values. + * + * @param pkt The packet to be unreferenced. + */ +void av_packet_unref(AVPacket *pkt); + +/** + * Move every field in src to dst and reset src. + * + * @see av_packet_unref + * + * @param src Source packet, will be reset + * @param dst Destination packet + */ +void av_packet_move_ref(AVPacket *dst, AVPacket *src); + +/** + * Copy only "properties" fields from src to dst. + * + * Properties for the purpose of this function are all the fields + * beside those related to the packet data (buf, data, size) + * + * @param dst Destination packet + * @param src Source packet + * + * @return 0 on success AVERROR on failure. + */ +int av_packet_copy_props(AVPacket *dst, const AVPacket *src); + +/** + * Ensure the data described by a given packet is reference counted. + * + * @note This function does not ensure that the reference will be writable. + * Use av_packet_make_writable instead for that purpose. + * + * @see av_packet_ref + * @see av_packet_make_writable + * + * @param pkt packet whose data should be made reference counted. + * + * @return 0 on success, a negative AVERROR on error. On failure, the + * packet is unchanged. + */ +int av_packet_make_refcounted(AVPacket *pkt); + +/** + * Create a writable reference for the data described by a given packet, + * avoiding data copy if possible. + * + * @param pkt Packet whose data should be made writable. + * + * @return 0 on success, a negative AVERROR on failure. On failure, the + * packet is unchanged. + */ +int av_packet_make_writable(AVPacket *pkt); + +/** + * Convert valid timing fields (timestamps / durations) in a packet from one + * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be + * ignored. + * + * @param pkt packet on which the conversion will be performed + * @param tb_src source timebase, in which the timing fields in pkt are + * expressed + * @param tb_dst destination timebase, to which the timing fields will be + * converted + */ +void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst); + +/** + * @} + */ + +#endif // AVCODEC_PACKET_H diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/version.h b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/version.h new file mode 100644 index 0000000000000..376388c5bb7a0 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/version.h @@ -0,0 +1,45 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VERSION_H +#define AVCODEC_VERSION_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBAVCODEC_VERSION_MINOR 37 +#define LIBAVCODEC_VERSION_MICRO 100 + +#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT + +#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) + +#endif /* AVCODEC_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/version_major.h b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/version_major.h new file mode 100644 index 0000000000000..1e23ed5e03e3f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavcodec/version_major.h @@ -0,0 +1,54 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VERSION_MAJOR_H +#define AVCODEC_VERSION_MAJOR_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#define LIBAVCODEC_VERSION_MAJOR 59 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + */ + +#define FF_API_OPENH264_SLICE_MODE (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_OPENH264_CABAC (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_UNUSED_CODEC_CAPS (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_THREAD_SAFE_CALLBACKS (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_GET_FRAME_CLASS (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_AUTO_THREADS (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_FLAG_TRUNCATED (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_SUB_TEXT_FORMAT (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_IDCT_NONE (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_SVTAV1_OPTS (LIBAVCODEC_VERSION_MAJOR < 60) + +#endif /* AVCODEC_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavformat/avformat.h b/src/framework/media/thirdparty/ffmpeg/v5/libavformat/avformat.h new file mode 100644 index 0000000000000..f12fa7d904e7e --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavformat/avformat.h @@ -0,0 +1,2907 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_AVFORMAT_H +#define AVFORMAT_AVFORMAT_H + +/** + * @file + * @ingroup libavf + * Main libavformat public API header + */ + +/** + * @defgroup libavf libavformat + * I/O and Muxing/Demuxing Library + * + * Libavformat (lavf) is a library for dealing with various media container + * formats. Its main two purposes are demuxing - i.e. splitting a media file + * into component streams, and the reverse process of muxing - writing supplied + * data in a specified container format. It also has an @ref lavf_io + * "I/O module" which supports a number of protocols for accessing the data (e.g. + * file, tcp, http and others). + * Unless you are absolutely sure you won't use libavformat's network + * capabilities, you should also call avformat_network_init(). + * + * A supported input format is described by an AVInputFormat struct, conversely + * an output format is described by AVOutputFormat. You can iterate over all + * input/output formats using the av_demuxer_iterate / av_muxer_iterate() functions. + * The protocols layer is not part of the public API, so you can only get the names + * of supported protocols with the avio_enum_protocols() function. + * + * Main lavf structure used for both muxing and demuxing is AVFormatContext, + * which exports all information about the file being read or written. As with + * most Libavformat structures, its size is not part of public ABI, so it cannot be + * allocated on stack or directly with av_malloc(). To create an + * AVFormatContext, use avformat_alloc_context() (some functions, like + * avformat_open_input() might do that for you). + * + * Most importantly an AVFormatContext contains: + * @li the @ref AVFormatContext.iformat "input" or @ref AVFormatContext.oformat + * "output" format. It is either autodetected or set by user for input; + * always set by user for output. + * @li an @ref AVFormatContext.streams "array" of AVStreams, which describe all + * elementary streams stored in the file. AVStreams are typically referred to + * using their index in this array. + * @li an @ref AVFormatContext.pb "I/O context". It is either opened by lavf or + * set by user for input, always set by user for output (unless you are dealing + * with an AVFMT_NOFILE format). + * + * @section lavf_options Passing options to (de)muxers + * It is possible to configure lavf muxers and demuxers using the @ref avoptions + * mechanism. Generic (format-independent) libavformat options are provided by + * AVFormatContext, they can be examined from a user program by calling + * av_opt_next() / av_opt_find() on an allocated AVFormatContext (or its AVClass + * from avformat_get_class()). Private (format-specific) options are provided by + * AVFormatContext.priv_data if and only if AVInputFormat.priv_class / + * AVOutputFormat.priv_class of the corresponding format struct is non-NULL. + * Further options may be provided by the @ref AVFormatContext.pb "I/O context", + * if its AVClass is non-NULL, and the protocols layer. See the discussion on + * nesting in @ref avoptions documentation to learn how to access those. + * + * @section urls + * URL strings in libavformat are made of a scheme/protocol, a ':', and a + * scheme specific string. URLs without a scheme and ':' used for local files + * are supported but deprecated. "file:" should be used for local files. + * + * It is important that the scheme string is not taken from untrusted + * sources without checks. + * + * Note that some schemes/protocols are quite powerful, allowing access to + * both local and remote files, parts of them, concatenations of them, local + * audio and video devices and so on. + * + * @{ + * + * @defgroup lavf_decoding Demuxing + * @{ + * Demuxers read a media file and split it into chunks of data (@em packets). A + * @ref AVPacket "packet" contains one or more encoded frames which belongs to a + * single elementary stream. In the lavf API this process is represented by the + * avformat_open_input() function for opening a file, av_read_frame() for + * reading a single packet and finally avformat_close_input(), which does the + * cleanup. + * + * @section lavf_decoding_open Opening a media file + * The minimum information required to open a file is its URL, which + * is passed to avformat_open_input(), as in the following code: + * @code + * const char *url = "file:in.mp3"; + * AVFormatContext *s = NULL; + * int ret = avformat_open_input(&s, url, NULL, NULL); + * if (ret < 0) + * abort(); + * @endcode + * The above code attempts to allocate an AVFormatContext, open the + * specified file (autodetecting the format) and read the header, exporting the + * information stored there into s. Some formats do not have a header or do not + * store enough information there, so it is recommended that you call the + * avformat_find_stream_info() function which tries to read and decode a few + * frames to find missing information. + * + * In some cases you might want to preallocate an AVFormatContext yourself with + * avformat_alloc_context() and do some tweaking on it before passing it to + * avformat_open_input(). One such case is when you want to use custom functions + * for reading input data instead of lavf internal I/O layer. + * To do that, create your own AVIOContext with avio_alloc_context(), passing + * your reading callbacks to it. Then set the @em pb field of your + * AVFormatContext to newly created AVIOContext. + * + * Since the format of the opened file is in general not known until after + * avformat_open_input() has returned, it is not possible to set demuxer private + * options on a preallocated context. Instead, the options should be passed to + * avformat_open_input() wrapped in an AVDictionary: + * @code + * AVDictionary *options = NULL; + * av_dict_set(&options, "video_size", "640x480", 0); + * av_dict_set(&options, "pixel_format", "rgb24", 0); + * + * if (avformat_open_input(&s, url, NULL, &options) < 0) + * abort(); + * av_dict_free(&options); + * @endcode + * This code passes the private options 'video_size' and 'pixel_format' to the + * demuxer. They would be necessary for e.g. the rawvideo demuxer, since it + * cannot know how to interpret raw video data otherwise. If the format turns + * out to be something different than raw video, those options will not be + * recognized by the demuxer and therefore will not be applied. Such unrecognized + * options are then returned in the options dictionary (recognized options are + * consumed). The calling program can handle such unrecognized options as it + * wishes, e.g. + * @code + * AVDictionaryEntry *e; + * if (e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX)) { + * fprintf(stderr, "Option %s not recognized by the demuxer.\n", e->key); + * abort(); + * } + * @endcode + * + * After you have finished reading the file, you must close it with + * avformat_close_input(). It will free everything associated with the file. + * + * @section lavf_decoding_read Reading from an opened file + * Reading data from an opened AVFormatContext is done by repeatedly calling + * av_read_frame() on it. Each call, if successful, will return an AVPacket + * containing encoded data for one AVStream, identified by + * AVPacket.stream_index. This packet may be passed straight into the libavcodec + * decoding functions avcodec_send_packet() or avcodec_decode_subtitle2() if the + * caller wishes to decode the data. + * + * AVPacket.pts, AVPacket.dts and AVPacket.duration timing information will be + * set if known. They may also be unset (i.e. AV_NOPTS_VALUE for + * pts/dts, 0 for duration) if the stream does not provide them. The timing + * information will be in AVStream.time_base units, i.e. it has to be + * multiplied by the timebase to convert them to seconds. + * + * A packet returned by av_read_frame() is always reference-counted, + * i.e. AVPacket.buf is set and the user may keep it indefinitely. + * The packet must be freed with av_packet_unref() when it is no + * longer needed. + * + * @section lavf_decoding_seek Seeking + * @} + * + * @defgroup lavf_encoding Muxing + * @{ + * Muxers take encoded data in the form of @ref AVPacket "AVPackets" and write + * it into files or other output bytestreams in the specified container format. + * + * The main API functions for muxing are avformat_write_header() for writing the + * file header, av_write_frame() / av_interleaved_write_frame() for writing the + * packets and av_write_trailer() for finalizing the file. + * + * At the beginning of the muxing process, the caller must first call + * avformat_alloc_context() to create a muxing context. The caller then sets up + * the muxer by filling the various fields in this context: + * + * - The @ref AVFormatContext.oformat "oformat" field must be set to select the + * muxer that will be used. + * - Unless the format is of the AVFMT_NOFILE type, the @ref AVFormatContext.pb + * "pb" field must be set to an opened IO context, either returned from + * avio_open2() or a custom one. + * - Unless the format is of the AVFMT_NOSTREAMS type, at least one stream must + * be created with the avformat_new_stream() function. The caller should fill + * the @ref AVStream.codecpar "stream codec parameters" information, such as the + * codec @ref AVCodecParameters.codec_type "type", @ref AVCodecParameters.codec_id + * "id" and other parameters (e.g. width / height, the pixel or sample format, + * etc.) as known. The @ref AVStream.time_base "stream timebase" should + * be set to the timebase that the caller desires to use for this stream (note + * that the timebase actually used by the muxer can be different, as will be + * described later). + * - It is advised to manually initialize only the relevant fields in + * AVCodecParameters, rather than using @ref avcodec_parameters_copy() during + * remuxing: there is no guarantee that the codec context values remain valid + * for both input and output format contexts. + * - The caller may fill in additional information, such as @ref + * AVFormatContext.metadata "global" or @ref AVStream.metadata "per-stream" + * metadata, @ref AVFormatContext.chapters "chapters", @ref + * AVFormatContext.programs "programs", etc. as described in the + * AVFormatContext documentation. Whether such information will actually be + * stored in the output depends on what the container format and the muxer + * support. + * + * When the muxing context is fully set up, the caller must call + * avformat_write_header() to initialize the muxer internals and write the file + * header. Whether anything actually is written to the IO context at this step + * depends on the muxer, but this function must always be called. Any muxer + * private options must be passed in the options parameter to this function. + * + * The data is then sent to the muxer by repeatedly calling av_write_frame() or + * av_interleaved_write_frame() (consult those functions' documentation for + * discussion on the difference between them; only one of them may be used with + * a single muxing context, they should not be mixed). Do note that the timing + * information on the packets sent to the muxer must be in the corresponding + * AVStream's timebase. That timebase is set by the muxer (in the + * avformat_write_header() step) and may be different from the timebase + * requested by the caller. + * + * Once all the data has been written, the caller must call av_write_trailer() + * to flush any buffered packets and finalize the output file, then close the IO + * context (if any) and finally free the muxing context with + * avformat_free_context(). + * @} + * + * @defgroup lavf_io I/O Read/Write + * @{ + * @section lavf_io_dirlist Directory listing + * The directory listing API makes it possible to list files on remote servers. + * + * Some of possible use cases: + * - an "open file" dialog to choose files from a remote location, + * - a recursive media finder providing a player with an ability to play all + * files from a given directory. + * + * @subsection lavf_io_dirlist_open Opening a directory + * At first, a directory needs to be opened by calling avio_open_dir() + * supplied with a URL and, optionally, ::AVDictionary containing + * protocol-specific parameters. The function returns zero or positive + * integer and allocates AVIODirContext on success. + * + * @code + * AVIODirContext *ctx = NULL; + * if (avio_open_dir(&ctx, "smb://example.com/some_dir", NULL) < 0) { + * fprintf(stderr, "Cannot open directory.\n"); + * abort(); + * } + * @endcode + * + * This code tries to open a sample directory using smb protocol without + * any additional parameters. + * + * @subsection lavf_io_dirlist_read Reading entries + * Each directory's entry (i.e. file, another directory, anything else + * within ::AVIODirEntryType) is represented by AVIODirEntry. + * Reading consecutive entries from an opened AVIODirContext is done by + * repeatedly calling avio_read_dir() on it. Each call returns zero or + * positive integer if successful. Reading can be stopped right after the + * NULL entry has been read -- it means there are no entries left to be + * read. The following code reads all entries from a directory associated + * with ctx and prints their names to standard output. + * @code + * AVIODirEntry *entry = NULL; + * for (;;) { + * if (avio_read_dir(ctx, &entry) < 0) { + * fprintf(stderr, "Cannot list directory.\n"); + * abort(); + * } + * if (!entry) + * break; + * printf("%s\n", entry->name); + * avio_free_directory_entry(&entry); + * } + * @endcode + * @} + * + * @defgroup lavf_codec Demuxers + * @{ + * @defgroup lavf_codec_native Native Demuxers + * @{ + * @} + * @defgroup lavf_codec_wrappers External library wrappers + * @{ + * @} + * @} + * @defgroup lavf_protos I/O Protocols + * @{ + * @} + * @defgroup lavf_internal Internal + * @{ + * @} + * @} + */ + +#include +#include /* FILE */ + +#include "libavcodec/codec.h" +#include "libavcodec/codec_par.h" +#include "libavcodec/defs.h" +#include "libavcodec/packet.h" + +#include "libavutil/dict.h" +#include "libavutil/log.h" + +#include "avio.h" +#include "libavformat/version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "libavformat/version.h" +#endif + +struct AVFormatContext; +struct AVStream; + +struct AVDeviceInfoList; +struct AVDeviceCapabilitiesQuery; + +/** + * @defgroup metadata_api Public Metadata API + * @{ + * @ingroup libavf + * The metadata API allows libavformat to export metadata tags to a client + * application when demuxing. Conversely it allows a client application to + * set metadata when muxing. + * + * Metadata is exported or set as pairs of key/value strings in the 'metadata' + * fields of the AVFormatContext, AVStream, AVChapter and AVProgram structs + * using the @ref lavu_dict "AVDictionary" API. Like all strings in FFmpeg, + * metadata is assumed to be UTF-8 encoded Unicode. Note that metadata + * exported by demuxers isn't checked to be valid UTF-8 in most cases. + * + * Important concepts to keep in mind: + * - Keys are unique; there can never be 2 tags with the same key. This is + * also meant semantically, i.e., a demuxer should not knowingly produce + * several keys that are literally different but semantically identical. + * E.g., key=Author5, key=Author6. In this example, all authors must be + * placed in the same tag. + * - Metadata is flat, not hierarchical; there are no subtags. If you + * want to store, e.g., the email address of the child of producer Alice + * and actor Bob, that could have key=alice_and_bobs_childs_email_address. + * - Several modifiers can be applied to the tag name. This is done by + * appending a dash character ('-') and the modifier name in the order + * they appear in the list below -- e.g. foo-eng-sort, not foo-sort-eng. + * - language -- a tag whose value is localized for a particular language + * is appended with the ISO 639-2/B 3-letter language code. + * For example: Author-ger=Michael, Author-eng=Mike + * The original/default language is in the unqualified "Author" tag. + * A demuxer should set a default if it sets any translated tag. + * - sorting -- a modified version of a tag that should be used for + * sorting will have '-sort' appended. E.g. artist="The Beatles", + * artist-sort="Beatles, The". + * - Some protocols and demuxers support metadata updates. After a successful + * call to av_read_frame(), AVFormatContext.event_flags or AVStream.event_flags + * will be updated to indicate if metadata changed. In order to detect metadata + * changes on a stream, you need to loop through all streams in the AVFormatContext + * and check their individual event_flags. + * + * - Demuxers attempt to export metadata in a generic format, however tags + * with no generic equivalents are left as they are stored in the container. + * Follows a list of generic tag names: + * + @verbatim + album -- name of the set this work belongs to + album_artist -- main creator of the set/album, if different from artist. + e.g. "Various Artists" for compilation albums. + artist -- main creator of the work + comment -- any additional description of the file. + composer -- who composed the work, if different from artist. + copyright -- name of copyright holder. + creation_time-- date when the file was created, preferably in ISO 8601. + date -- date when the work was created, preferably in ISO 8601. + disc -- number of a subset, e.g. disc in a multi-disc collection. + encoder -- name/settings of the software/hardware that produced the file. + encoded_by -- person/group who created the file. + filename -- original name of the file. + genre -- . + language -- main language in which the work is performed, preferably + in ISO 639-2 format. Multiple languages can be specified by + separating them with commas. + performer -- artist who performed the work, if different from artist. + E.g for "Also sprach Zarathustra", artist would be "Richard + Strauss" and performer "London Philharmonic Orchestra". + publisher -- name of the label/publisher. + service_name -- name of the service in broadcasting (channel name). + service_provider -- name of the service provider in broadcasting. + title -- name of the work. + track -- number of this work in the set, can be in form current/total. + variant_bitrate -- the total bitrate of the bitrate variant that the current stream is part of + @endverbatim + * + * Look in the examples section for an application example how to use the Metadata API. + * + * @} + */ + +/* packet functions */ + + +/** + * Allocate and read the payload of a packet and initialize its + * fields with default values. + * + * @param s associated IO context + * @param pkt packet + * @param size desired payload size + * @return >0 (read size) if OK, AVERROR_xxx otherwise + */ +int av_get_packet(AVIOContext *s, AVPacket *pkt, int size); + + +/** + * Read data and append it to the current content of the AVPacket. + * If pkt->size is 0 this is identical to av_get_packet. + * Note that this uses av_grow_packet and thus involves a realloc + * which is inefficient. Thus this function should only be used + * when there is no reasonable way to know (an upper bound of) + * the final size. + * + * @param s associated IO context + * @param pkt packet + * @param size amount of data to read + * @return >0 (read size) if OK, AVERROR_xxx otherwise, previous data + * will not be lost even if an error occurs. + */ +int av_append_packet(AVIOContext *s, AVPacket *pkt, int size); + +/*************************************************/ +/* input/output formats */ + +struct AVCodecTag; + +/** + * This structure contains the data a format has to probe a file. + */ +typedef struct AVProbeData { + const char *filename; + unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */ + int buf_size; /**< Size of buf except extra allocated bytes */ + const char *mime_type; /**< mime_type, when known. */ +} AVProbeData; + +#define AVPROBE_SCORE_RETRY (AVPROBE_SCORE_MAX/4) +#define AVPROBE_SCORE_STREAM_RETRY (AVPROBE_SCORE_MAX/4-1) + +#define AVPROBE_SCORE_EXTENSION 50 ///< score for file extension +#define AVPROBE_SCORE_MIME 75 ///< score for file mime type +#define AVPROBE_SCORE_MAX 100 ///< maximum score + +#define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer + +/// Demuxer will use avio_open, no opened file should be provided by the caller. +#define AVFMT_NOFILE 0x0001 +#define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */ +/** + * The muxer/demuxer is experimental and should be used with caution. + * + * - demuxers: will not be selected automatically by probing, must be specified + * explicitly. + */ +#define AVFMT_EXPERIMENTAL 0x0004 +#define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */ +#define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */ +#define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */ +#define AVFMT_GENERIC_INDEX 0x0100 /**< Use generic index building code. */ +#define AVFMT_TS_DISCONT 0x0200 /**< Format allows timestamp discontinuities. Note, muxers always require valid (monotone) timestamps */ +#define AVFMT_VARIABLE_FPS 0x0400 /**< Format allows variable fps. */ +#define AVFMT_NODIMENSIONS 0x0800 /**< Format does not need width/height */ +#define AVFMT_NOSTREAMS 0x1000 /**< Format does not require any streams */ +#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fall back on binary search via read_timestamp */ +#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fall back on generic search */ +#define AVFMT_NO_BYTE_SEEK 0x8000 /**< Format does not allow seeking by bytes */ +#define AVFMT_ALLOW_FLUSH 0x10000 /**< Format allows flushing. If not set, the muxer will not receive a NULL packet in the write_packet function. */ +#define AVFMT_TS_NONSTRICT 0x20000 /**< Format does not require strictly + increasing timestamps, but they must + still be monotonic */ +#define AVFMT_TS_NEGATIVE 0x40000 /**< Format allows muxing negative + timestamps. If not set the timestamp + will be shifted in av_write_frame and + av_interleaved_write_frame so they + start from 0. + The user or muxer can override this through + AVFormatContext.avoid_negative_ts + */ + +#define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */ + +/** + * @addtogroup lavf_encoding + * @{ + */ +typedef struct AVOutputFormat { + const char *name; + /** + * Descriptive name for the format, meant to be more human-readable + * than name. You should use the NULL_IF_CONFIG_SMALL() macro + * to define it. + */ + const char *long_name; + const char *mime_type; + const char *extensions; /**< comma-separated filename extensions */ + /* output support */ + enum AVCodecID audio_codec; /**< default audio codec */ + enum AVCodecID video_codec; /**< default video codec */ + enum AVCodecID subtitle_codec; /**< default subtitle codec */ + /** + * can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, + * AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, + * AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH, + * AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE + */ + int flags; + + /** + * List of supported codec_id-codec_tag pairs, ordered by "better + * choice first". The arrays are all terminated by AV_CODEC_ID_NONE. + */ + const struct AVCodecTag * const *codec_tag; + + + const AVClass *priv_class; ///< AVClass for the private context + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + /** + * size of private data so that it can be allocated in the wrapper + */ + int priv_data_size; + + /** + * Internal flags. See FF_FMT_FLAG_* in internal.h. + */ + int flags_internal; + + int (*write_header)(struct AVFormatContext *); + /** + * Write a packet. If AVFMT_ALLOW_FLUSH is set in flags, + * pkt can be NULL in order to flush data buffered in the muxer. + * When flushing, return 0 if there still is more data to flush, + * or 1 if everything was flushed and there is no more buffered + * data. + */ + int (*write_packet)(struct AVFormatContext *, AVPacket *pkt); + int (*write_trailer)(struct AVFormatContext *); + /** + * A format-specific function for interleavement. + * If unset, packets will be interleaved by dts. + * + * @param s An AVFormatContext for output. pkt will be added to + * resp. taken from its packet buffer. + * @param[in,out] pkt A packet to be interleaved if has_packet is set; + * also used to return packets. If no packet is returned + * (e.g. on error), pkt is blank on return. + * @param flush 1 if no further packets are available as input and + * all remaining packets should be output. + * @param has_packet If set, pkt contains a packet to be interleaved + * on input; otherwise pkt is blank on input. + * @return 1 if a packet was output, 0 if no packet could be output, + * < 0 if an error occurred + */ + int (*interleave_packet)(struct AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet); + /** + * Test if the given codec can be stored in this container. + * + * @return 1 if the codec is supported, 0 if it is not. + * A negative number if unknown. + * MKTAG('A', 'P', 'I', 'C') if the codec is only supported as AV_DISPOSITION_ATTACHED_PIC + */ + int (*query_codec)(enum AVCodecID id, int std_compliance); + + void (*get_output_timestamp)(struct AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall); + /** + * Allows sending messages from application to device. + */ + int (*control_message)(struct AVFormatContext *s, int type, + void *data, size_t data_size); + + /** + * Write an uncoded AVFrame. + * + * See av_write_uncoded_frame() for details. + * + * The library will free *frame afterwards, but the muxer can prevent it + * by setting the pointer to NULL. + */ + int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index, + AVFrame **frame, unsigned flags); + /** + * Returns device list with it properties. + * @see avdevice_list_devices() for more details. + */ + int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list); + enum AVCodecID data_codec; /**< default data codec */ + /** + * Initialize format. May allocate data here, and set any AVFormatContext or + * AVStream parameters that need to be set before packets are sent. + * This method must not write output. + * + * Return 0 if streams were fully configured, 1 if not, negative AVERROR on failure + * + * Any allocations made here must be freed in deinit(). + */ + int (*init)(struct AVFormatContext *); + /** + * Deinitialize format. If present, this is called whenever the muxer is being + * destroyed, regardless of whether or not the header has been written. + * + * If a trailer is being written, this is called after write_trailer(). + * + * This is called if init() fails as well. + */ + void (*deinit)(struct AVFormatContext *); + /** + * Set up any necessary bitstream filtering and extract any extra data needed + * for the global header. + * + * @note pkt might have been directly forwarded by a meta-muxer; therefore + * pkt->stream_index as well as the pkt's timebase might be invalid. + * Return 0 if more packets from this stream must be checked; 1 if not. + */ + int (*check_bitstream)(struct AVFormatContext *s, struct AVStream *st, + const AVPacket *pkt); +} AVOutputFormat; +/** + * @} + */ + +/** + * @addtogroup lavf_decoding + * @{ + */ +typedef struct AVInputFormat { + /** + * A comma separated list of short names for the format. New names + * may be appended with a minor bump. + */ + const char *name; + + /** + * Descriptive name for the format, meant to be more human-readable + * than name. You should use the NULL_IF_CONFIG_SMALL() macro + * to define it. + */ + const char *long_name; + + /** + * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS, + * AVFMT_NOTIMESTAMPS, AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH, + * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS. + */ + int flags; + + /** + * If extensions are defined, then no probe is done. You should + * usually not use extension format guessing because it is not + * reliable enough + */ + const char *extensions; + + const struct AVCodecTag * const *codec_tag; + + const AVClass *priv_class; ///< AVClass for the private context + + /** + * Comma-separated list of mime types. + * It is used check for matching mime types while probing. + * @see av_probe_input_format2 + */ + const char *mime_type; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + /** + * Raw demuxers store their codec ID here. + */ + int raw_codec_id; + + /** + * Size of private data so that it can be allocated in the wrapper. + */ + int priv_data_size; + + /** + * Internal flags. See FF_FMT_FLAG_* in internal.h. + */ + int flags_internal; + + /** + * Tell if a given file has a chance of being parsed as this format. + * The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes + * big so you do not have to check for that unless you need more. + */ + int (*read_probe)(const AVProbeData *); + + /** + * Read the format header and initialize the AVFormatContext + * structure. Return 0 if OK. 'avformat_new_stream' should be + * called to create new streams. + */ + int (*read_header)(struct AVFormatContext *); + + /** + * Read one packet and put it in 'pkt'. pts and flags are also + * set. 'avformat_new_stream' can be called only if the flag + * AVFMTCTX_NOHEADER is used and only in the calling thread (not in a + * background thread). + * @return 0 on success, < 0 on error. + * Upon returning an error, pkt must be unreferenced by the caller. + */ + int (*read_packet)(struct AVFormatContext *, AVPacket *pkt); + + /** + * Close the stream. The AVFormatContext and AVStreams are not + * freed by this function + */ + int (*read_close)(struct AVFormatContext *); + + /** + * Seek to a given timestamp relative to the frames in + * stream component stream_index. + * @param stream_index Must not be -1. + * @param flags Selects which direction should be preferred if no exact + * match is available. + * @return >= 0 on success (but not necessarily the new offset) + */ + int (*read_seek)(struct AVFormatContext *, + int stream_index, int64_t timestamp, int flags); + + /** + * Get the next timestamp in stream[stream_index].time_base units. + * @return the timestamp or AV_NOPTS_VALUE if an error occurred + */ + int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index, + int64_t *pos, int64_t pos_limit); + + /** + * Start/resume playing - only meaningful if using a network-based format + * (RTSP). + */ + int (*read_play)(struct AVFormatContext *); + + /** + * Pause playing - only meaningful if using a network-based format + * (RTSP). + */ + int (*read_pause)(struct AVFormatContext *); + + /** + * Seek to timestamp ts. + * Seeking will be done so that the point from which all active streams + * can be presented successfully will be closest to ts and within min/max_ts. + * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL. + */ + int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); + + /** + * Returns device list with it properties. + * @see avdevice_list_devices() for more details. + */ + int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list); + +} AVInputFormat; +/** + * @} + */ + +enum AVStreamParseType { + AVSTREAM_PARSE_NONE, + AVSTREAM_PARSE_FULL, /**< full parsing and repack */ + AVSTREAM_PARSE_HEADERS, /**< Only parse headers, do not repack. */ + AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on a packet boundary */ + AVSTREAM_PARSE_FULL_ONCE, /**< full parsing and repack of the first frame only, only implemented for H.264 currently */ + AVSTREAM_PARSE_FULL_RAW, /**< full parsing and repack with timestamp and position generation by parser for raw + this assumes that each packet in the file contains no demuxer level headers and + just codec level data, otherwise position generation would fail */ +}; + +typedef struct AVIndexEntry { + int64_t pos; + int64_t timestamp; /**< + * Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are available + * when seeking to this entry. That means preferable PTS on keyframe based formats. + * But demuxers can choose to store a different timestamp, if it is more convenient for the implementation or nothing better + * is known + */ +#define AVINDEX_KEYFRAME 0x0001 +#define AVINDEX_DISCARD_FRAME 0x0002 /** + * Flag is used to indicate which frame should be discarded after decoding. + */ + int flags:2; + int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment). + int min_distance; /**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. */ +} AVIndexEntry; + +/** + * The stream should be chosen by default among other streams of the same type, + * unless the user has explicitly specified otherwise. + */ +#define AV_DISPOSITION_DEFAULT (1 << 0) +/** + * The stream is not in original language. + * + * @note AV_DISPOSITION_ORIGINAL is the inverse of this disposition. At most + * one of them should be set in properly tagged streams. + * @note This disposition may apply to any stream type, not just audio. + */ +#define AV_DISPOSITION_DUB (1 << 1) +/** + * The stream is in original language. + * + * @see the notes for AV_DISPOSITION_DUB + */ +#define AV_DISPOSITION_ORIGINAL (1 << 2) +/** + * The stream is a commentary track. + */ +#define AV_DISPOSITION_COMMENT (1 << 3) +/** + * The stream contains song lyrics. + */ +#define AV_DISPOSITION_LYRICS (1 << 4) +/** + * The stream contains karaoke audio. + */ +#define AV_DISPOSITION_KARAOKE (1 << 5) + +/** + * Track should be used during playback by default. + * Useful for subtitle track that should be displayed + * even when user did not explicitly ask for subtitles. + */ +#define AV_DISPOSITION_FORCED (1 << 6) +/** + * The stream is intended for hearing impaired audiences. + */ +#define AV_DISPOSITION_HEARING_IMPAIRED (1 << 7) +/** + * The stream is intended for visually impaired audiences. + */ +#define AV_DISPOSITION_VISUAL_IMPAIRED (1 << 8) +/** + * The audio stream contains music and sound effects without voice. + */ +#define AV_DISPOSITION_CLEAN_EFFECTS (1 << 9) +/** + * The stream is stored in the file as an attached picture/"cover art" (e.g. + * APIC frame in ID3v2). The first (usually only) packet associated with it + * will be returned among the first few packets read from the file unless + * seeking takes place. It can also be accessed at any time in + * AVStream.attached_pic. + */ +#define AV_DISPOSITION_ATTACHED_PIC (1 << 10) +/** + * The stream is sparse, and contains thumbnail images, often corresponding + * to chapter markers. Only ever used with AV_DISPOSITION_ATTACHED_PIC. + */ +#define AV_DISPOSITION_TIMED_THUMBNAILS (1 << 11) + +/** + * The stream is intended to be mixed with a spatial audio track. For example, + * it could be used for narration or stereo music, and may remain unchanged by + * listener head rotation. + */ +#define AV_DISPOSITION_NON_DIEGETIC (1 << 12) + +/** + * The subtitle stream contains captions, providing a transcription and possibly + * a translation of audio. Typically intended for hearing-impaired audiences. + */ +#define AV_DISPOSITION_CAPTIONS (1 << 16) +/** + * The subtitle stream contains a textual description of the video content. + * Typically intended for visually-impaired audiences or for the cases where the + * video cannot be seen. + */ +#define AV_DISPOSITION_DESCRIPTIONS (1 << 17) +/** + * The subtitle stream contains time-aligned metadata that is not intended to be + * directly presented to the user. + */ +#define AV_DISPOSITION_METADATA (1 << 18) +/** + * The audio stream is intended to be mixed with another stream before + * presentation. + * Corresponds to mix_type=0 in mpegts. + */ +#define AV_DISPOSITION_DEPENDENT (1 << 19) +/** + * The video stream contains still images. + */ +#define AV_DISPOSITION_STILL_IMAGE (1 << 20) + +/** + * @return The AV_DISPOSITION_* flag corresponding to disp or a negative error + * code if disp does not correspond to a known stream disposition. + */ +int av_disposition_from_string(const char *disp); + +/** + * @param disposition a combination of AV_DISPOSITION_* values + * @return The string description corresponding to the lowest set bit in + * disposition. NULL when the lowest set bit does not correspond + * to a known disposition or when disposition is 0. + */ +const char *av_disposition_to_string(int disposition); + +/** + * Options for behavior on timestamp wrap detection. + */ +#define AV_PTS_WRAP_IGNORE 0 ///< ignore the wrap +#define AV_PTS_WRAP_ADD_OFFSET 1 ///< add the format specific offset on wrap detection +#define AV_PTS_WRAP_SUB_OFFSET -1 ///< subtract the format specific offset on wrap detection + +/** + * Stream structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVStream) must not be used outside libav*. + */ +typedef struct AVStream { +#if FF_API_AVSTREAM_CLASS + /** + * A class for @ref avoptions. Set on stream creation. + */ + const AVClass *av_class; +#endif + + int index; /**< stream index in AVFormatContext */ + /** + * Format-specific stream ID. + * decoding: set by libavformat + * encoding: set by the user, replaced by libavformat if left unset + */ + int id; + + void *priv_data; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. + * + * decoding: set by libavformat + * encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the desired timebase. In + * avformat_write_header(), the muxer will overwrite this field + * with the timebase that will actually be used for the timestamps + * written into the file (which may or may not be related to the + * user-provided one, depending on the format). + */ + AVRational time_base; + + /** + * Decoding: pts of the first frame of the stream in presentation order, in stream time base. + * Only set this if you are absolutely 100% sure that the value you set + * it to really is the pts of the first frame. + * This may be undefined (AV_NOPTS_VALUE). + * @note The ASF header does NOT contain a correct start_time the ASF + * demuxer must NOT set this. + */ + int64_t start_time; + + /** + * Decoding: duration of the stream, in stream time base. + * If a source file does not specify a duration, but does specify + * a bitrate, this value will be estimated from bitrate and file size. + * + * Encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the estimated duration. + */ + int64_t duration; + + int64_t nb_frames; ///< number of frames in this stream if known or 0 + + /** + * Stream disposition - a combination of AV_DISPOSITION_* flags. + * - demuxing: set by libavformat when creating the stream or in + * avformat_find_stream_info(). + * - muxing: may be set by the caller before avformat_write_header(). + */ + int disposition; + + enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed. + + /** + * sample aspect ratio (0 if unknown) + * - encoding: Set by user. + * - decoding: Set by libavformat. + */ + AVRational sample_aspect_ratio; + + AVDictionary *metadata; + + /** + * Average framerate + * + * - demuxing: May be set by libavformat when creating the stream or in + * avformat_find_stream_info(). + * - muxing: May be set by the caller before avformat_write_header(). + */ + AVRational avg_frame_rate; + + /** + * For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet + * will contain the attached picture. + * + * decoding: set by libavformat, must not be modified by the caller. + * encoding: unused + */ + AVPacket attached_pic; + + /** + * An array of side data that applies to the whole stream (i.e. the + * container does not allow it to change between packets). + * + * There may be no overlap between the side data in this array and side data + * in the packets. I.e. a given side data is either exported by the muxer + * (demuxing) / set by the caller (muxing) in this array, then it never + * appears in the packets, or the side data is exported / sent through + * the packets (always in the first packet where the value becomes known or + * changes), then it does not appear in this array. + * + * - demuxing: Set by libavformat when the stream is created. + * - muxing: May be set by the caller before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + * + * @see av_format_inject_global_side_data() + */ + AVPacketSideData *side_data; + /** + * The number of elements in the AVStream.side_data array. + */ + int nb_side_data; + + /** + * Flags indicating events happening on the stream, a combination of + * AVSTREAM_EVENT_FLAG_*. + * + * - demuxing: may be set by the demuxer in avformat_open_input(), + * avformat_find_stream_info() and av_read_frame(). Flags must be cleared + * by the user once the event has been handled. + * - muxing: may be set by the user after avformat_write_header(). to + * indicate a user-triggered event. The muxer will clear the flags for + * events it has handled in av_[interleaved]_write_frame(). + */ + int event_flags; +/** + * - demuxing: the demuxer read new metadata from the file and updated + * AVStream.metadata accordingly + * - muxing: the user updated AVStream.metadata and wishes the muxer to write + * it into the file + */ +#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 +/** + * - demuxing: new packets for this stream were read from the file. This + * event is informational only and does not guarantee that new packets + * for this stream will necessarily be returned from av_read_frame(). + */ +#define AVSTREAM_EVENT_FLAG_NEW_PACKETS (1 << 1) + + /** + * Real base framerate of the stream. + * This is the lowest framerate with which all timestamps can be + * represented accurately (it is the least common multiple of all + * framerates in the stream). Note, this value is just a guess! + * For example, if the time base is 1/90000 and all frames have either + * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1. + */ + AVRational r_frame_rate; + + /** + * Codec parameters associated with this stream. Allocated and freed by + * libavformat in avformat_new_stream() and avformat_free_context() + * respectively. + * + * - demuxing: filled by libavformat on stream creation or in + * avformat_find_stream_info() + * - muxing: filled by the caller before avformat_write_header() + */ + AVCodecParameters *codecpar; + + /** + * Number of bits in timestamps. Used for wrapping control. + * + * - demuxing: set by libavformat + * - muxing: set by libavformat + * + */ + int pts_wrap_bits; +} AVStream; + +struct AVCodecParserContext *av_stream_get_parser(const AVStream *s); + +/** + * Returns the pts of the last muxed packet + its duration + * + * the retuned value is undefined when used with a demuxer. + */ +int64_t av_stream_get_end_pts(const AVStream *st); + +#define AV_PROGRAM_RUNNING 1 + +/** + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVProgram) must not be used outside libav*. + */ +typedef struct AVProgram { + int id; + int flags; + enum AVDiscard discard; ///< selects which program to discard and which to feed to the caller + unsigned int *stream_index; + unsigned int nb_stream_indexes; + AVDictionary *metadata; + + int program_num; + int pmt_pid; + int pcr_pid; + int pmt_version; + + /***************************************************************** + * All fields below this line are not part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + int64_t start_time; + int64_t end_time; + + int64_t pts_wrap_reference; ///< reference dts for wrap detection + int pts_wrap_behavior; ///< behavior on wrap detection +} AVProgram; + +#define AVFMTCTX_NOHEADER 0x0001 /**< signal that no header is present + (streams are added dynamically) */ +#define AVFMTCTX_UNSEEKABLE 0x0002 /**< signal that the stream is definitely + not seekable, and attempts to call the + seek function will fail. For some + network protocols (e.g. HLS), this can + change dynamically at runtime. */ + +typedef struct AVChapter { + int64_t id; ///< unique ID to identify the chapter + AVRational time_base; ///< time base in which the start/end timestamps are specified + int64_t start, end; ///< chapter start/end time in time_base units + AVDictionary *metadata; +} AVChapter; + + +/** + * Callback used by devices to communicate with application. + */ +typedef int (*av_format_control_message)(struct AVFormatContext *s, int type, + void *data, size_t data_size); + +typedef int (*AVOpenCallback)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, + const AVIOInterruptCB *int_cb, AVDictionary **options); + +/** + * The duration of a video can be estimated through various ways, and this enum can be used + * to know how the duration was estimated. + */ +enum AVDurationEstimationMethod { + AVFMT_DURATION_FROM_PTS, ///< Duration accurately estimated from PTSes + AVFMT_DURATION_FROM_STREAM, ///< Duration estimated from a stream with a known duration + AVFMT_DURATION_FROM_BITRATE ///< Duration estimated from bitrate (less accurate) +}; + +/** + * Format I/O context. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVFormatContext) must not be used outside libav*, use + * avformat_alloc_context() to create an AVFormatContext. + * + * Fields can be accessed through AVOptions (av_opt*), + * the name string used matches the associated command line parameter name and + * can be found in libavformat/options_table.h. + * The AVOption/command line parameter names differ in some cases from the C + * structure field names for historic reasons or brevity. + */ +typedef struct AVFormatContext { + /** + * A class for logging and @ref avoptions. Set by avformat_alloc_context(). + * Exports (de)muxer private options if they exist. + */ + const AVClass *av_class; + + /** + * The input container format. + * + * Demuxing only, set by avformat_open_input(). + */ + const struct AVInputFormat *iformat; + + /** + * The output container format. + * + * Muxing only, must be set by the caller before avformat_write_header(). + */ + const struct AVOutputFormat *oformat; + + /** + * Format private data. This is an AVOptions-enabled struct + * if and only if iformat/oformat.priv_class is not NULL. + * + * - muxing: set by avformat_write_header() + * - demuxing: set by avformat_open_input() + */ + void *priv_data; + + /** + * I/O context. + * + * - demuxing: either set by the user before avformat_open_input() (then + * the user must close it manually) or set by avformat_open_input(). + * - muxing: set by the user before avformat_write_header(). The caller must + * take care of closing / freeing the IO context. + * + * Do NOT set this field if AVFMT_NOFILE flag is set in + * iformat/oformat.flags. In such a case, the (de)muxer will handle + * I/O in some other way and this field will be NULL. + */ + AVIOContext *pb; + + /* stream info */ + /** + * Flags signalling stream properties. A combination of AVFMTCTX_*. + * Set by libavformat. + */ + int ctx_flags; + + /** + * Number of elements in AVFormatContext.streams. + * + * Set by avformat_new_stream(), must not be modified by any other code. + */ + unsigned int nb_streams; + /** + * A list of all streams in the file. New streams are created with + * avformat_new_stream(). + * + * - demuxing: streams are created by libavformat in avformat_open_input(). + * If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also + * appear in av_read_frame(). + * - muxing: streams are created by the user before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + */ + AVStream **streams; + + /** + * input or output URL. Unlike the old filename field, this field has no + * length restriction. + * + * - demuxing: set by avformat_open_input(), initialized to an empty + * string if url parameter was NULL in avformat_open_input(). + * - muxing: may be set by the caller before calling avformat_write_header() + * (or avformat_init_output() if that is called first) to a string + * which is freeable by av_free(). Set to an empty string if it + * was NULL in avformat_init_output(). + * + * Freed by libavformat in avformat_free_context(). + */ + char *url; + + /** + * Position of the first frame of the component, in + * AV_TIME_BASE fractional seconds. NEVER set this value directly: + * It is deduced from the AVStream values. + * + * Demuxing only, set by libavformat. + */ + int64_t start_time; + + /** + * Duration of the stream, in AV_TIME_BASE fractional + * seconds. Only set this value if you know none of the individual stream + * durations and also do not set any of them. This is deduced from the + * AVStream values if not set. + * + * Demuxing only, set by libavformat. + */ + int64_t duration; + + /** + * Total stream bitrate in bit/s, 0 if not + * available. Never set it directly if the file_size and the + * duration are known as FFmpeg can compute it automatically. + */ + int64_t bit_rate; + + unsigned int packet_size; + int max_delay; + + /** + * Flags modifying the (de)muxer behaviour. A combination of AVFMT_FLAG_*. + * Set by the user before avformat_open_input() / avformat_write_header(). + */ + int flags; +#define AVFMT_FLAG_GENPTS 0x0001 ///< Generate missing pts even if it requires parsing future frames. +#define AVFMT_FLAG_IGNIDX 0x0002 ///< Ignore index. +#define AVFMT_FLAG_NONBLOCK 0x0004 ///< Do not block when reading packets from input. +#define AVFMT_FLAG_IGNDTS 0x0008 ///< Ignore DTS on frames that contain both DTS & PTS +#define AVFMT_FLAG_NOFILLIN 0x0010 ///< Do not infer any values from other values, just return what is stored in the container +#define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled +#define AVFMT_FLAG_NOBUFFER 0x0040 ///< Do not buffer frames when possible +#define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it. +#define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted +#define AVFMT_FLAG_FLUSH_PACKETS 0x0200 ///< Flush the AVIOContext every packet. +/** + * When muxing, try to avoid writing any random/volatile data to the output. + * This includes any random IDs, real-time timestamps/dates, muxer version, etc. + * + * This flag is mainly intended for testing. + */ +#define AVFMT_FLAG_BITEXACT 0x0400 +#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down) +#if FF_API_LAVF_PRIV_OPT +#define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (deprecated, does nothing) +#endif +#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats +#define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops. +#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer + + /** + * Maximum number of bytes read from input in order to determine stream + * properties. Used when reading the global header and in + * avformat_find_stream_info(). + * + * Demuxing only, set by the caller before avformat_open_input(). + * + * @note this is \e not used for determining the \ref AVInputFormat + * "input format" + * @sa format_probesize + */ + int64_t probesize; + + /** + * Maximum duration (in AV_TIME_BASE units) of the data read + * from input in avformat_find_stream_info(). + * Demuxing only, set by the caller before avformat_find_stream_info(). + * Can be set to 0 to let avformat choose using a heuristic. + */ + int64_t max_analyze_duration; + + const uint8_t *key; + int keylen; + + unsigned int nb_programs; + AVProgram **programs; + + /** + * Forced video codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID video_codec_id; + + /** + * Forced audio codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID audio_codec_id; + + /** + * Forced subtitle codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID subtitle_codec_id; + + /** + * Maximum amount of memory in bytes to use for the index of each stream. + * If the index exceeds this size, entries will be discarded as + * needed to maintain a smaller size. This can lead to slower or less + * accurate seeking (depends on demuxer). + * Demuxers for which a full in-memory index is mandatory will ignore + * this. + * - muxing: unused + * - demuxing: set by user + */ + unsigned int max_index_size; + + /** + * Maximum amount of memory in bytes to use for buffering frames + * obtained from realtime capture devices. + */ + unsigned int max_picture_buffer; + + /** + * Number of chapters in AVChapter array. + * When muxing, chapters are normally written in the file header, + * so nb_chapters should normally be initialized before write_header + * is called. Some muxers (e.g. mov and mkv) can also write chapters + * in the trailer. To write chapters in the trailer, nb_chapters + * must be zero when write_header is called and non-zero when + * write_trailer is called. + * - muxing: set by user + * - demuxing: set by libavformat + */ + unsigned int nb_chapters; + AVChapter **chapters; + + /** + * Metadata that applies to the whole file. + * + * - demuxing: set by libavformat in avformat_open_input() + * - muxing: may be set by the caller before avformat_write_header() + * + * Freed by libavformat in avformat_free_context(). + */ + AVDictionary *metadata; + + /** + * Start time of the stream in real world time, in microseconds + * since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the + * stream was captured at this real world time. + * - muxing: Set by the caller before avformat_write_header(). If set to + * either 0 or AV_NOPTS_VALUE, then the current wall-time will + * be used. + * - demuxing: Set by libavformat. AV_NOPTS_VALUE if unknown. Note that + * the value may become known after some number of frames + * have been received. + */ + int64_t start_time_realtime; + + /** + * The number of frames used for determining the framerate in + * avformat_find_stream_info(). + * Demuxing only, set by the caller before avformat_find_stream_info(). + */ + int fps_probe_size; + + /** + * Error recognition; higher values will detect more errors but may + * misdetect some more or less valid parts as errors. + * Demuxing only, set by the caller before avformat_open_input(). + */ + int error_recognition; + + /** + * Custom interrupt callbacks for the I/O layer. + * + * demuxing: set by the user before avformat_open_input(). + * muxing: set by the user before avformat_write_header() + * (mainly useful for AVFMT_NOFILE formats). The callback + * should also be passed to avio_open2() if it's used to + * open the file. + */ + AVIOInterruptCB interrupt_callback; + + /** + * Flags to enable debugging. + */ + int debug; +#define FF_FDEBUG_TS 0x0001 + + /** + * Maximum buffering duration for interleaving. + * + * To ensure all the streams are interleaved correctly, + * av_interleaved_write_frame() will wait until it has at least one packet + * for each stream before actually writing any packets to the output file. + * When some streams are "sparse" (i.e. there are large gaps between + * successive packets), this can result in excessive buffering. + * + * This field specifies the maximum difference between the timestamps of the + * first and the last packet in the muxing queue, above which libavformat + * will output a packet regardless of whether it has queued a packet for all + * the streams. + * + * Muxing only, set by the caller before avformat_write_header(). + */ + int64_t max_interleave_delta; + + /** + * Allow non-standard and experimental extension + * @see AVCodecContext.strict_std_compliance + */ + int strict_std_compliance; + + /** + * Flags indicating events happening on the file, a combination of + * AVFMT_EVENT_FLAG_*. + * + * - demuxing: may be set by the demuxer in avformat_open_input(), + * avformat_find_stream_info() and av_read_frame(). Flags must be cleared + * by the user once the event has been handled. + * - muxing: may be set by the user after avformat_write_header() to + * indicate a user-triggered event. The muxer will clear the flags for + * events it has handled in av_[interleaved]_write_frame(). + */ + int event_flags; +/** + * - demuxing: the demuxer read new metadata from the file and updated + * AVFormatContext.metadata accordingly + * - muxing: the user updated AVFormatContext.metadata and wishes the muxer to + * write it into the file + */ +#define AVFMT_EVENT_FLAG_METADATA_UPDATED 0x0001 + + /** + * Maximum number of packets to read while waiting for the first timestamp. + * Decoding only. + */ + int max_ts_probe; + + /** + * Avoid negative timestamps during muxing. + * Any value of the AVFMT_AVOID_NEG_TS_* constants. + * Note, this works better when using av_interleaved_write_frame(). + * - muxing: Set by user + * - demuxing: unused + */ + int avoid_negative_ts; +#define AVFMT_AVOID_NEG_TS_AUTO -1 ///< Enabled when required by target format +#define AVFMT_AVOID_NEG_TS_DISABLED 0 ///< Do not shift timestamps even when they are negative. +#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative +#define AVFMT_AVOID_NEG_TS_MAKE_ZERO 2 ///< Shift timestamps so that they start at 0 + + /** + * Transport stream id. + * This will be moved into demuxer private options. Thus no API/ABI compatibility + */ + int ts_id; + + /** + * Audio preload in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int audio_preload; + + /** + * Max chunk time in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int max_chunk_duration; + + /** + * Max chunk size in bytes + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int max_chunk_size; + + /** + * forces the use of wallclock timestamps as pts/dts of packets + * This has undefined results in the presence of B frames. + * - encoding: unused + * - decoding: Set by user + */ + int use_wallclock_as_timestamps; + + /** + * avio flags, used to force AVIO_FLAG_DIRECT. + * - encoding: unused + * - decoding: Set by user + */ + int avio_flags; + + /** + * The duration field can be estimated through various ways, and this field can be used + * to know how the duration was estimated. + * - encoding: unused + * - decoding: Read by user + */ + enum AVDurationEstimationMethod duration_estimation_method; + + /** + * Skip initial bytes when opening stream + * - encoding: unused + * - decoding: Set by user + */ + int64_t skip_initial_bytes; + + /** + * Correct single timestamp overflows + * - encoding: unused + * - decoding: Set by user + */ + unsigned int correct_ts_overflow; + + /** + * Force seeking to any (also non key) frames. + * - encoding: unused + * - decoding: Set by user + */ + int seek2any; + + /** + * Flush the I/O context after each packet. + * - encoding: Set by user + * - decoding: unused + */ + int flush_packets; + + /** + * format probing score. + * The maximal score is AVPROBE_SCORE_MAX, its set when the demuxer probes + * the format. + * - encoding: unused + * - decoding: set by avformat, read by user + */ + int probe_score; + + /** + * Maximum number of bytes read from input in order to identify the + * \ref AVInputFormat "input format". Only used when the format is not set + * explicitly by the caller. + * + * Demuxing only, set by the caller before avformat_open_input(). + * + * @sa probesize + */ + int format_probesize; + + /** + * ',' separated list of allowed decoders. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *codec_whitelist; + + /** + * ',' separated list of allowed demuxers. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *format_whitelist; + + /** + * IO repositioned flag. + * This is set by avformat when the underlaying IO context read pointer + * is repositioned, for example when doing byte based seeking. + * Demuxers can use the flag to detect such changes. + */ + int io_repositioned; + + /** + * Forced video codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const AVCodec *video_codec; + + /** + * Forced audio codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const AVCodec *audio_codec; + + /** + * Forced subtitle codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const AVCodec *subtitle_codec; + + /** + * Forced data codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const AVCodec *data_codec; + + /** + * Number of bytes to be written as padding in a metadata header. + * Demuxing: Unused. + * Muxing: Set by user via av_format_set_metadata_header_padding. + */ + int metadata_header_padding; + + /** + * User data. + * This is a place for some private data of the user. + */ + void *opaque; + + /** + * Callback used by devices to communicate with application. + */ + av_format_control_message control_message_cb; + + /** + * Output timestamp offset, in microseconds. + * Muxing: set by user + */ + int64_t output_ts_offset; + + /** + * dump format separator. + * can be ", " or "\n " or anything else + * - muxing: Set by user. + * - demuxing: Set by user. + */ + uint8_t *dump_separator; + + /** + * Forced Data codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID data_codec_id; + + /** + * ',' separated list of allowed protocols. + * - encoding: unused + * - decoding: set by user + */ + char *protocol_whitelist; + + /** + * A callback for opening new IO streams. + * + * Whenever a muxer or a demuxer needs to open an IO stream (typically from + * avformat_open_input() for demuxers, but for certain formats can happen at + * other times as well), it will call this callback to obtain an IO context. + * + * @param s the format context + * @param pb on success, the newly opened IO context should be returned here + * @param url the url to open + * @param flags a combination of AVIO_FLAG_* + * @param options a dictionary of additional options, with the same + * semantics as in avio_open2() + * @return 0 on success, a negative AVERROR code on failure + * + * @note Certain muxers and demuxers do nesting, i.e. they open one or more + * additional internal format contexts. Thus the AVFormatContext pointer + * passed to this callback may be different from the one facing the caller. + * It will, however, have the same 'opaque' field. + */ + int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, + int flags, AVDictionary **options); + + /** + * A callback for closing the streams opened with AVFormatContext.io_open(). + */ + void (*io_close)(struct AVFormatContext *s, AVIOContext *pb); + + /** + * ',' separated list of disallowed protocols. + * - encoding: unused + * - decoding: set by user + */ + char *protocol_blacklist; + + /** + * The maximum number of streams. + * - encoding: unused + * - decoding: set by user + */ + int max_streams; + + /** + * Skip duration calcuation in estimate_timings_from_pts. + * - encoding: unused + * - decoding: set by user + */ + int skip_estimate_duration_from_pts; + + /** + * Maximum number of packets that can be probed + * - encoding: unused + * - decoding: set by user + */ + int max_probe_packets; + + /** + * A callback for closing the streams opened with AVFormatContext.io_open(). + * + * Using this is preferred over io_close, because this can return an error. + * Therefore this callback is used instead of io_close by the generic + * libavformat code if io_close is NULL or the default. + * + * @param s the format context + * @param pb IO context to be closed and freed + * @return 0 on success, a negative AVERROR code on failure + */ + int (*io_close2)(struct AVFormatContext *s, AVIOContext *pb); +} AVFormatContext; + +/** + * This function will cause global side data to be injected in the next packet + * of each stream as well as after any subsequent seek. + */ +void av_format_inject_global_side_data(AVFormatContext *s); + +/** + * Returns the method used to set ctx->duration. + * + * @return AVFMT_DURATION_FROM_PTS, AVFMT_DURATION_FROM_STREAM, or AVFMT_DURATION_FROM_BITRATE. + */ +enum AVDurationEstimationMethod av_fmt_ctx_get_duration_estimation_method(const AVFormatContext* ctx); + +/** + * @defgroup lavf_core Core functions + * @ingroup libavf + * + * Functions for querying libavformat capabilities, allocating core structures, + * etc. + * @{ + */ + +/** + * Return the LIBAVFORMAT_VERSION_INT constant. + */ +unsigned avformat_version(void); + +/** + * Return the libavformat build-time configuration. + */ +const char *avformat_configuration(void); + +/** + * Return the libavformat license. + */ +const char *avformat_license(void); + +/** + * Do global initialization of network libraries. This is optional, + * and not recommended anymore. + * + * This functions only exists to work around thread-safety issues + * with older GnuTLS or OpenSSL libraries. If libavformat is linked + * to newer versions of those libraries, or if you do not use them, + * calling this function is unnecessary. Otherwise, you need to call + * this function before any other threads using them are started. + * + * This function will be deprecated once support for older GnuTLS and + * OpenSSL libraries is removed, and this function has no purpose + * anymore. + */ +int avformat_network_init(void); + +/** + * Undo the initialization done by avformat_network_init. Call it only + * once for each time you called avformat_network_init. + */ +int avformat_network_deinit(void); + +/** + * Iterate over all registered muxers. + * + * @param opaque a pointer where libavformat will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered muxer or NULL when the iteration is + * finished + */ +const AVOutputFormat *av_muxer_iterate(void **opaque); + +/** + * Iterate over all registered demuxers. + * + * @param opaque a pointer where libavformat will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered demuxer or NULL when the iteration is + * finished + */ +const AVInputFormat *av_demuxer_iterate(void **opaque); + +/** + * Allocate an AVFormatContext. + * avformat_free_context() can be used to free the context and everything + * allocated by the framework within it. + */ +AVFormatContext *avformat_alloc_context(void); + +/** + * Free an AVFormatContext and all its streams. + * @param s context to free + */ +void avformat_free_context(AVFormatContext *s); + +/** + * Get the AVClass for AVFormatContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avformat_get_class(void); + +/** + * Get the AVClass for AVStream. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *av_stream_get_class(void); + +/** + * Add a new stream to a media file. + * + * When demuxing, it is called by the demuxer in read_header(). If the + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also + * be called in read_packet(). + * + * When muxing, should be called by the user before avformat_write_header(). + * + * User is required to call avformat_free_context() to clean up the allocation + * by avformat_new_stream(). + * + * @param s media file handle + * @param c unused, does nothing + * + * @return newly created stream or NULL on error. + */ +AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c); + +/** + * Wrap an existing array as stream side data. + * + * @param st stream + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * st. + * @param size side information size + * @return zero on success, a negative AVERROR code on failure. On failure, + * the stream is unchanged and the data remains owned by the caller. + */ +int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + +/** + * Allocate new information from stream. + * + * @param stream stream + * @param type desired side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t *av_stream_new_side_data(AVStream *stream, + enum AVPacketSideDataType type, size_t size); +/** + * Get side information from stream. + * + * @param stream stream + * @param type desired side information type + * @param size If supplied, *size will be set to the size of the side data + * or to zero if the desired side data is not present. + * @return pointer to data if present or NULL otherwise + */ +uint8_t *av_stream_get_side_data(const AVStream *stream, + enum AVPacketSideDataType type, size_t *size); + +AVProgram *av_new_program(AVFormatContext *s, int id); + +/** + * @} + */ + + +/** + * Allocate an AVFormatContext for an output format. + * avformat_free_context() can be used to free the context and + * everything allocated by the framework within it. + * + * @param *ctx is set to the created format context, or to NULL in + * case of failure + * @param oformat format to use for allocating the context, if NULL + * format_name and filename are used instead + * @param format_name the name of output format to use for allocating the + * context, if NULL filename is used instead + * @param filename the name of the filename to use for allocating the + * context, may be NULL + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int avformat_alloc_output_context2(AVFormatContext **ctx, const AVOutputFormat *oformat, + const char *format_name, const char *filename); + +/** + * @addtogroup lavf_decoding + * @{ + */ + +/** + * Find AVInputFormat based on the short name of the input format. + */ +const AVInputFormat *av_find_input_format(const char *short_name); + +/** + * Guess the file format. + * + * @param pd data to be probed + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + */ +const AVInputFormat *av_probe_input_format(const AVProbeData *pd, int is_opened); + +/** + * Guess the file format. + * + * @param pd data to be probed + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_max A probe score larger that this is required to accept a + * detection, the variable is set to the actual detection + * score afterwards. + * If the score is <= AVPROBE_SCORE_MAX / 4 it is recommended + * to retry with a larger probe buffer. + */ +const AVInputFormat *av_probe_input_format2(const AVProbeData *pd, + int is_opened, int *score_max); + +/** + * Guess the file format. + * + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_ret The score of the best detection. + */ +const AVInputFormat *av_probe_input_format3(const AVProbeData *pd, + int is_opened, int *score_ret); + +/** + * Probe a bytestream to determine the input format. Each time a probe returns + * with a score that is too low, the probe buffer size is increased and another + * attempt is made. When the maximum probe size is reached, the input format + * with the highest score is returned. + * + * @param pb the bytestream to probe + * @param fmt the input format is put here + * @param url the url of the stream + * @param logctx the log context + * @param offset the offset within the bytestream to probe from + * @param max_probe_size the maximum probe buffer size (zero for default) + * @return the score in case of success, a negative value corresponding to an + * the maximal score is AVPROBE_SCORE_MAX + * AVERROR code otherwise + */ +int av_probe_input_buffer2(AVIOContext *pb, const AVInputFormat **fmt, + const char *url, void *logctx, + unsigned int offset, unsigned int max_probe_size); + +/** + * Like av_probe_input_buffer2() but returns 0 on success + */ +int av_probe_input_buffer(AVIOContext *pb, const AVInputFormat **fmt, + const char *url, void *logctx, + unsigned int offset, unsigned int max_probe_size); + +/** + * Open an input stream and read the header. The codecs are not opened. + * The stream must be closed with avformat_close_input(). + * + * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context). + * May be a pointer to NULL, in which case an AVFormatContext is allocated by this + * function and written into ps. + * Note that a user-supplied AVFormatContext will be freed on failure. + * @param url URL of the stream to open. + * @param fmt If non-NULL, this parameter forces a specific input format. + * Otherwise the format is autodetected. + * @param options A dictionary filled with AVFormatContext and demuxer-private options. + * On return this parameter will be destroyed and replaced with a dict containing + * options that were not found. May be NULL. + * + * @return 0 on success, a negative AVERROR on failure. + * + * @note If you want to use custom IO, preallocate the format context and set its pb field. + */ +int avformat_open_input(AVFormatContext **ps, const char *url, + const AVInputFormat *fmt, AVDictionary **options); + +/** + * Read packets of a media file to get stream information. This + * is useful for file formats with no headers such as MPEG. This + * function also computes the real framerate in case of MPEG-2 repeat + * frame mode. + * The logical file position is not changed by this function; + * examined packets may be buffered for later processing. + * + * @param ic media file handle + * @param options If non-NULL, an ic.nb_streams long array of pointers to + * dictionaries, where i-th member contains options for + * codec corresponding to i-th stream. + * On return each dictionary will be filled with options that were not found. + * @return >=0 if OK, AVERROR_xxx on error + * + * @note this function isn't guaranteed to open all the codecs, so + * options being non-empty at return is a perfectly normal behavior. + * + * @todo Let the user decide somehow what information is needed so that + * we do not waste time getting stuff the user does not need. + */ +int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); + +/** + * Find the programs which belong to a given stream. + * + * @param ic media file handle + * @param last the last found program, the search will start after this + * program, or from the beginning if it is NULL + * @param s stream index + * @return the next program which belongs to s, NULL if no program is found or + * the last program is not among the programs of ic. + */ +AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s); + +void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx); + +/** + * Find the "best" stream in the file. + * The best stream is determined according to various heuristics as the most + * likely to be what the user expects. + * If the decoder parameter is non-NULL, av_find_best_stream will find the + * default decoder for the stream's codec; streams for which no decoder can + * be found are ignored. + * + * @param ic media file handle + * @param type stream type: video, audio, subtitles, etc. + * @param wanted_stream_nb user-requested stream number, + * or -1 for automatic selection + * @param related_stream try to find a stream related (eg. in the same + * program) to this one, or -1 if none + * @param decoder_ret if non-NULL, returns the decoder for the + * selected stream + * @param flags flags; none are currently defined + * @return the non-negative stream number in case of success, + * AVERROR_STREAM_NOT_FOUND if no stream with the requested type + * could be found, + * AVERROR_DECODER_NOT_FOUND if streams were found but no decoder + * @note If av_find_best_stream returns successfully and decoder_ret is not + * NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec. + */ +int av_find_best_stream(AVFormatContext *ic, + enum AVMediaType type, + int wanted_stream_nb, + int related_stream, + const AVCodec **decoder_ret, + int flags); + +/** + * Return the next frame of a stream. + * This function returns what is stored in the file, and does not validate + * that what is there are valid frames for the decoder. It will split what is + * stored in the file into frames and return one for each call. It will not + * omit invalid data between valid frames so as to give the decoder the maximum + * information possible for decoding. + * + * On success, the returned packet is reference-counted (pkt->buf is set) and + * valid indefinitely. The packet must be freed with av_packet_unref() when + * it is no longer needed. For video, the packet contains exactly one frame. + * For audio, it contains an integer number of frames if each frame has + * a known fixed size (e.g. PCM or ADPCM data). If the audio frames have + * a variable size (e.g. MPEG audio), then it contains one frame. + * + * pkt->pts, pkt->dts and pkt->duration are always set to correct + * values in AVStream.time_base units (and guessed if the format cannot + * provide them). pkt->pts can be AV_NOPTS_VALUE if the video format + * has B-frames, so it is better to rely on pkt->dts if you do not + * decompress the payload. + * + * @return 0 if OK, < 0 on error or end of file. On error, pkt will be blank + * (as if it came from av_packet_alloc()). + * + * @note pkt will be initialized, so it may be uninitialized, but it must not + * contain data that needs to be freed. + */ +int av_read_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Seek to the keyframe at timestamp. + * 'timestamp' in 'stream_index'. + * + * @param s media file handle + * @param stream_index If stream_index is (-1), a default + * stream is selected, and timestamp is automatically converted + * from AV_TIME_BASE units to the stream specific time_base. + * @param timestamp Timestamp in AVStream.time_base units + * or, if no stream is specified, in AV_TIME_BASE units. + * @param flags flags which select direction and seeking mode + * @return >= 0 on success + */ +int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, + int flags); + +/** + * Seek to timestamp ts. + * Seeking will be done so that the point from which all active streams + * can be presented successfully will be closest to ts and within min/max_ts. + * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL. + * + * If flags contain AVSEEK_FLAG_BYTE, then all timestamps are in bytes and + * are the file position (this may not be supported by all demuxers). + * If flags contain AVSEEK_FLAG_FRAME, then all timestamps are in frames + * in the stream with stream_index (this may not be supported by all demuxers). + * Otherwise all timestamps are in units of the stream selected by stream_index + * or if stream_index is -1, in AV_TIME_BASE units. + * If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as + * keyframes (this may not be supported by all demuxers). + * If flags contain AVSEEK_FLAG_BACKWARD, it is ignored. + * + * @param s media file handle + * @param stream_index index of the stream which is used as time base reference + * @param min_ts smallest acceptable timestamp + * @param ts target timestamp + * @param max_ts largest acceptable timestamp + * @param flags flags + * @return >=0 on success, error code otherwise + * + * @note This is part of the new seek API which is still under construction. + */ +int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); + +/** + * Discard all internally buffered data. This can be useful when dealing with + * discontinuities in the byte stream. Generally works only with formats that + * can resync. This includes headerless formats like MPEG-TS/TS but should also + * work with NUT, Ogg and in a limited way AVI for example. + * + * The set of streams, the detected duration, stream parameters and codecs do + * not change when calling this function. If you want a complete reset, it's + * better to open a new AVFormatContext. + * + * This does not flush the AVIOContext (s->pb). If necessary, call + * avio_flush(s->pb) before calling this function. + * + * @param s media file handle + * @return >=0 on success, error code otherwise + */ +int avformat_flush(AVFormatContext *s); + +/** + * Start playing a network-based stream (e.g. RTSP stream) at the + * current position. + */ +int av_read_play(AVFormatContext *s); + +/** + * Pause a network-based stream (e.g. RTSP stream). + * + * Use av_read_play() to resume it. + */ +int av_read_pause(AVFormatContext *s); + +/** + * Close an opened input AVFormatContext. Free it and all its contents + * and set *s to NULL. + */ +void avformat_close_input(AVFormatContext **s); +/** + * @} + */ + +#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward +#define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes +#define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes +#define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number + +/** + * @addtogroup lavf_encoding + * @{ + */ + +#define AVSTREAM_INIT_IN_WRITE_HEADER 0 ///< stream parameters initialized in avformat_write_header +#define AVSTREAM_INIT_IN_INIT_OUTPUT 1 ///< stream parameters initialized in avformat_init_output + +/** + * Allocate the stream private data and write the stream header to + * an output media file. + * + * @param s Media file handle, must be allocated with avformat_alloc_context(). + * Its oformat field must be set to the desired output format; + * Its pb field must be set to an already opened AVIOContext. + * @param options An AVDictionary filled with AVFormatContext and muxer-private options. + * On return this parameter will be destroyed and replaced with a dict containing + * options that were not found. May be NULL. + * + * @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec had not already been fully initialized in avformat_init, + * AVSTREAM_INIT_IN_INIT_OUTPUT on success if the codec had already been fully initialized in avformat_init, + * negative AVERROR on failure. + * + * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_init_output. + */ +av_warn_unused_result +int avformat_write_header(AVFormatContext *s, AVDictionary **options); + +/** + * Allocate the stream private data and initialize the codec, but do not write the header. + * May optionally be used before avformat_write_header to initialize stream parameters + * before actually writing the header. + * If using this function, do not pass the same options to avformat_write_header. + * + * @param s Media file handle, must be allocated with avformat_alloc_context(). + * Its oformat field must be set to the desired output format; + * Its pb field must be set to an already opened AVIOContext. + * @param options An AVDictionary filled with AVFormatContext and muxer-private options. + * On return this parameter will be destroyed and replaced with a dict containing + * options that were not found. May be NULL. + * + * @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec requires avformat_write_header to fully initialize, + * AVSTREAM_INIT_IN_INIT_OUTPUT on success if the codec has been fully initialized, + * negative AVERROR on failure. + * + * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_write_header. + */ +av_warn_unused_result +int avformat_init_output(AVFormatContext *s, AVDictionary **options); + +/** + * Write a packet to an output media file. + * + * This function passes the packet directly to the muxer, without any buffering + * or reordering. The caller is responsible for correctly interleaving the + * packets if the format requires it. Callers that want libavformat to handle + * the interleaving should call av_interleaved_write_frame() instead of this + * function. + * + * @param s media file handle + * @param pkt The packet containing the data to be written. Note that unlike + * av_interleaved_write_frame(), this function does not take + * ownership of the packet passed to it (though some muxers may make + * an internal reference to the input packet). + *
+ * This parameter can be NULL (at any time, not just at the end), in + * order to immediately flush data buffered within the muxer, for + * muxers that buffer up data internally before writing it to the + * output. + *
+ * Packet's @ref AVPacket.stream_index "stream_index" field must be + * set to the index of the corresponding stream in @ref + * AVFormatContext.streams "s->streams". + *
+ * The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts") + * must be set to correct values in the stream's timebase (unless the + * output format is flagged with the AVFMT_NOTIMESTAMPS flag, then + * they can be set to AV_NOPTS_VALUE). + * The dts for subsequent packets passed to this function must be strictly + * increasing when compared in their respective timebases (unless the + * output format is flagged with the AVFMT_TS_NONSTRICT, then they + * merely have to be nondecreasing). @ref AVPacket.duration + * "duration") should also be set if known. + * @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush + * + * @see av_interleaved_write_frame() + */ +int av_write_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Write a packet to an output media file ensuring correct interleaving. + * + * This function will buffer the packets internally as needed to make sure the + * packets in the output file are properly interleaved, usually ordered by + * increasing dts. Callers doing their own interleaving should call + * av_write_frame() instead of this function. + * + * Using this function instead of av_write_frame() can give muxers advance + * knowledge of future packets, improving e.g. the behaviour of the mp4 + * muxer for VFR content in fragmenting mode. + * + * @param s media file handle + * @param pkt The packet containing the data to be written. + *
+ * If the packet is reference-counted, this function will take + * ownership of this reference and unreference it later when it sees + * fit. If the packet is not reference-counted, libavformat will + * make a copy. + * The returned packet will be blank (as if returned from + * av_packet_alloc()), even on error. + *
+ * This parameter can be NULL (at any time, not just at the end), to + * flush the interleaving queues. + *
+ * Packet's @ref AVPacket.stream_index "stream_index" field must be + * set to the index of the corresponding stream in @ref + * AVFormatContext.streams "s->streams". + *
+ * The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts") + * must be set to correct values in the stream's timebase (unless the + * output format is flagged with the AVFMT_NOTIMESTAMPS flag, then + * they can be set to AV_NOPTS_VALUE). + * The dts for subsequent packets in one stream must be strictly + * increasing (unless the output format is flagged with the + * AVFMT_TS_NONSTRICT, then they merely have to be nondecreasing). + * @ref AVPacket.duration "duration" should also be set if known. + * + * @return 0 on success, a negative AVERROR on error. + * + * @see av_write_frame(), AVFormatContext.max_interleave_delta + */ +int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Write an uncoded frame to an output media file. + * + * The frame must be correctly interleaved according to the container + * specification; if not, av_interleaved_write_uncoded_frame() must be used. + * + * See av_interleaved_write_uncoded_frame() for details. + */ +int av_write_uncoded_frame(AVFormatContext *s, int stream_index, + AVFrame *frame); + +/** + * Write an uncoded frame to an output media file. + * + * If the muxer supports it, this function makes it possible to write an AVFrame + * structure directly, without encoding it into a packet. + * It is mostly useful for devices and similar special muxers that use raw + * video or PCM data and will not serialize it into a byte stream. + * + * To test whether it is possible to use it with a given muxer and stream, + * use av_write_uncoded_frame_query(). + * + * The caller gives up ownership of the frame and must not access it + * afterwards. + * + * @return >=0 for success, a negative code on error + */ +int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index, + AVFrame *frame); + +/** + * Test whether a muxer supports uncoded frame. + * + * @return >=0 if an uncoded frame can be written to that muxer and stream, + * <0 if not + */ +int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index); + +/** + * Write the stream trailer to an output media file and free the + * file private data. + * + * May only be called after a successful call to avformat_write_header. + * + * @param s media file handle + * @return 0 if OK, AVERROR_xxx on error + */ +int av_write_trailer(AVFormatContext *s); + +/** + * Return the output format in the list of registered output formats + * which best matches the provided parameters, or return NULL if + * there is no match. + * + * @param short_name if non-NULL checks if short_name matches with the + * names of the registered formats + * @param filename if non-NULL checks if filename terminates with the + * extensions of the registered formats + * @param mime_type if non-NULL checks if mime_type matches with the + * MIME type of the registered formats + */ +const AVOutputFormat *av_guess_format(const char *short_name, + const char *filename, + const char *mime_type); + +/** + * Guess the codec ID based upon muxer and filename. + */ +enum AVCodecID av_guess_codec(const AVOutputFormat *fmt, const char *short_name, + const char *filename, const char *mime_type, + enum AVMediaType type); + +/** + * Get timing information for the data currently output. + * The exact meaning of "currently output" depends on the format. + * It is mostly relevant for devices that have an internal buffer and/or + * work in real time. + * @param s media file handle + * @param stream stream in the media file + * @param[out] dts DTS of the last packet output for the stream, in stream + * time_base units + * @param[out] wall absolute time when that packet whas output, + * in microsecond + * @return 0 if OK, AVERROR(ENOSYS) if the format does not support it + * Note: some formats or devices may not allow to measure dts and wall + * atomically. + */ +int av_get_output_timestamp(struct AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall); + + +/** + * @} + */ + + +/** + * @defgroup lavf_misc Utility functions + * @ingroup libavf + * @{ + * + * Miscellaneous utility functions related to both muxing and demuxing + * (or neither). + */ + +/** + * Send a nice hexadecimal dump of a buffer to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump_log, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump(FILE *f, const uint8_t *buf, int size); + +/** + * Send a nice hexadecimal dump of a buffer to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size); + +/** + * Send a nice dump of a packet to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st); + + +/** + * Send a nice dump of a packet to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload, + const AVStream *st); + +/** + * Get the AVCodecID for the given codec tag tag. + * If no codec id is found returns AV_CODEC_ID_NONE. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param tag codec tag to match to a codec ID + */ +enum AVCodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned int tag); + +/** + * Get the codec tag for the given codec id id. + * If no codec tag is found returns 0. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param id codec ID to match to a codec tag + */ +unsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum AVCodecID id); + +/** + * Get the codec tag for the given codec id. + * + * @param tags list of supported codec_id - codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param id codec id that should be searched for in the list + * @param tag A pointer to the found tag + * @return 0 if id was not found in tags, > 0 if it was found + */ +int av_codec_get_tag2(const struct AVCodecTag * const *tags, enum AVCodecID id, + unsigned int *tag); + +int av_find_default_stream_index(AVFormatContext *s); + +/** + * Get the index for a specific timestamp. + * + * @param st stream that the timestamp belongs to + * @param timestamp timestamp to retrieve the index for + * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond + * to the timestamp which is <= the requested one, if backward + * is 0, then it will be >= + * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise + * @return < 0 if no such timestamp could be found + */ +int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags); + +/** + * Get the index entry count for the given AVStream. + * + * @param st stream + * @return the number of index entries in the stream + */ +int avformat_index_get_entries_count(const AVStream *st); + +/** + * Get the AVIndexEntry corresponding to the given index. + * + * @param st Stream containing the requested AVIndexEntry. + * @param idx The desired index. + * @return A pointer to the requested AVIndexEntry if it exists, NULL otherwise. + * + * @note The pointer returned by this function is only guaranteed to be valid + * until any function that takes the stream or the parent AVFormatContext + * as input argument is called. + */ +const AVIndexEntry *avformat_index_get_entry(AVStream *st, int idx); + +/** + * Get the AVIndexEntry corresponding to the given timestamp. + * + * @param st Stream containing the requested AVIndexEntry. + * @param timestamp Timestamp to retrieve the index entry for. + * @param flags If AVSEEK_FLAG_BACKWARD then the returned entry will correspond + * to the timestamp which is <= the requested one, if backward + * is 0, then it will be >= + * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise. + * @return A pointer to the requested AVIndexEntry if it exists, NULL otherwise. + * + * @note The pointer returned by this function is only guaranteed to be valid + * until any function that takes the stream or the parent AVFormatContext + * as input argument is called. + */ +const AVIndexEntry *avformat_index_get_entry_from_timestamp(AVStream *st, + int64_t wanted_timestamp, + int flags); +/** + * Add an index entry into a sorted list. Update the entry if the list + * already contains it. + * + * @param timestamp timestamp in the time base of the given stream + */ +int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, + int size, int distance, int flags); + + +/** + * Split a URL string into components. + * + * The pointers to buffers for storing individual components may be null, + * in order to ignore that component. Buffers for components not found are + * set to empty strings. If the port is not found, it is set to a negative + * value. + * + * @param proto the buffer for the protocol + * @param proto_size the size of the proto buffer + * @param authorization the buffer for the authorization + * @param authorization_size the size of the authorization buffer + * @param hostname the buffer for the host name + * @param hostname_size the size of the hostname buffer + * @param port_ptr a pointer to store the port number in + * @param path the buffer for the path + * @param path_size the size of the path buffer + * @param url the URL to split + */ +void av_url_split(char *proto, int proto_size, + char *authorization, int authorization_size, + char *hostname, int hostname_size, + int *port_ptr, + char *path, int path_size, + const char *url); + + +/** + * Print detailed information about the input or output format, such as + * duration, bitrate, streams, container, programs, metadata, side data, + * codec and time base. + * + * @param ic the context to analyze + * @param index index of the stream to dump information about + * @param url the URL to print, such as source or destination file + * @param is_output Select whether the specified context is an input(0) or output(1) + */ +void av_dump_format(AVFormatContext *ic, + int index, + const char *url, + int is_output); + + +#define AV_FRAME_FILENAME_FLAGS_MULTIPLE 1 ///< Allow multiple %d + +/** + * Return in 'buf' the path with '%d' replaced by a number. + * + * Also handles the '%0nd' format where 'n' is the total number + * of digits and '%%'. + * + * @param buf destination buffer + * @param buf_size destination buffer size + * @param path numbered sequence string + * @param number frame number + * @param flags AV_FRAME_FILENAME_FLAGS_* + * @return 0 if OK, -1 on format error + */ +int av_get_frame_filename2(char *buf, int buf_size, + const char *path, int number, int flags); + +int av_get_frame_filename(char *buf, int buf_size, + const char *path, int number); + +/** + * Check whether filename actually is a numbered sequence generator. + * + * @param filename possible numbered sequence string + * @return 1 if a valid numbered sequence string, 0 otherwise + */ +int av_filename_number_test(const char *filename); + +/** + * Generate an SDP for an RTP session. + * + * Note, this overwrites the id values of AVStreams in the muxer contexts + * for getting unique dynamic payload types. + * + * @param ac array of AVFormatContexts describing the RTP streams. If the + * array is composed by only one context, such context can contain + * multiple AVStreams (one AVStream per RTP stream). Otherwise, + * all the contexts in the array (an AVCodecContext per RTP stream) + * must contain only one AVStream. + * @param n_files number of AVCodecContexts contained in ac + * @param buf buffer where the SDP will be stored (must be allocated by + * the caller) + * @param size the size of the buffer + * @return 0 if OK, AVERROR_xxx on error + */ +int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size); + +/** + * Return a positive value if the given filename has one of the given + * extensions, 0 otherwise. + * + * @param filename file name to check against the given extensions + * @param extensions a comma-separated list of filename extensions + */ +int av_match_ext(const char *filename, const char *extensions); + +/** + * Test if the given container can store a codec. + * + * @param ofmt container to check for compatibility + * @param codec_id codec to potentially store in container + * @param std_compliance standards compliance level, one of FF_COMPLIANCE_* + * + * @return 1 if codec with ID codec_id can be stored in ofmt, 0 if it cannot. + * A negative number if this information is not available. + */ +int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id, + int std_compliance); + +/** + * @defgroup riff_fourcc RIFF FourCCs + * @{ + * Get the tables mapping RIFF FourCCs to libavcodec AVCodecIDs. The tables are + * meant to be passed to av_codec_get_id()/av_codec_get_tag() as in the + * following code: + * @code + * uint32_t tag = MKTAG('H', '2', '6', '4'); + * const struct AVCodecTag *table[] = { avformat_get_riff_video_tags(), 0 }; + * enum AVCodecID id = av_codec_get_id(table, tag); + * @endcode + */ +/** + * @return the table mapping RIFF FourCCs for video to libavcodec AVCodecID. + */ +const struct AVCodecTag *avformat_get_riff_video_tags(void); +/** + * @return the table mapping RIFF FourCCs for audio to AVCodecID. + */ +const struct AVCodecTag *avformat_get_riff_audio_tags(void); +/** + * @return the table mapping MOV FourCCs for video to libavcodec AVCodecID. + */ +const struct AVCodecTag *avformat_get_mov_video_tags(void); +/** + * @return the table mapping MOV FourCCs for audio to AVCodecID. + */ +const struct AVCodecTag *avformat_get_mov_audio_tags(void); + +/** + * @} + */ + +/** + * Guess the sample aspect ratio of a frame, based on both the stream and the + * frame aspect ratio. + * + * Since the frame aspect ratio is set by the codec but the stream aspect ratio + * is set by the demuxer, these two may not be equal. This function tries to + * return the value that you should use if you would like to display the frame. + * + * Basic logic is to use the stream aspect ratio if it is set to something sane + * otherwise use the frame aspect ratio. This way a container setting, which is + * usually easy to modify can override the coded value in the frames. + * + * @param format the format context which the stream is part of + * @param stream the stream which the frame is part of + * @param frame the frame with the aspect ratio to be determined + * @return the guessed (valid) sample_aspect_ratio, 0/1 if no idea + */ +AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame); + +/** + * Guess the frame rate, based on both the container and codec information. + * + * @param ctx the format context which the stream is part of + * @param stream the stream which the frame is part of + * @param frame the frame for which the frame rate should be determined, may be NULL + * @return the guessed (valid) frame rate, 0/1 if no idea + */ +AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, AVFrame *frame); + +/** + * Check if the stream st contained in s is matched by the stream specifier + * spec. + * + * See the "stream specifiers" chapter in the documentation for the syntax + * of spec. + * + * @return >0 if st is matched by spec; + * 0 if st is not matched by spec; + * AVERROR code if spec is invalid + * + * @note A stream specifier can match several streams in the format. + */ +int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, + const char *spec); + +int avformat_queue_attached_pictures(AVFormatContext *s); + +enum AVTimebaseSource { + AVFMT_TBCF_AUTO = -1, + AVFMT_TBCF_DECODER, + AVFMT_TBCF_DEMUXER, +#if FF_API_R_FRAME_RATE + AVFMT_TBCF_R_FRAMERATE, +#endif +}; + +/** + * Transfer internal timing information from one stream to another. + * + * This function is useful when doing stream copy. + * + * @param ofmt target output format for ost + * @param ost output stream which needs timings copy and adjustments + * @param ist reference input stream to copy timings from + * @param copy_tb define from where the stream codec timebase needs to be imported + */ +int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, + AVStream *ost, const AVStream *ist, + enum AVTimebaseSource copy_tb); + +/** + * Get the internal codec timebase from a stream. + * + * @param st input stream to extract the timebase from + */ +AVRational av_stream_get_codec_timebase(const AVStream *st); + +/** + * @} + */ + +#endif /* AVFORMAT_AVFORMAT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavformat/avio.h b/src/framework/media/thirdparty/ffmpeg/v5/libavformat/avio.h new file mode 100644 index 0000000000000..36c3d7b43062b --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavformat/avio.h @@ -0,0 +1,842 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef AVFORMAT_AVIO_H +#define AVFORMAT_AVIO_H + +/** + * @file + * @ingroup lavf_io + * Buffered I/O operations + */ + +#include +#include + +#include "libavutil/attributes.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" + +#include "libavformat/version_major.h" + +/** + * Seeking works like for a local file. + */ +#define AVIO_SEEKABLE_NORMAL (1 << 0) + +/** + * Seeking by timestamp with avio_seek_time() is possible. + */ +#define AVIO_SEEKABLE_TIME (1 << 1) + +/** + * Callback for checking whether to abort blocking functions. + * AVERROR_EXIT is returned in this case by the interrupted + * function. During blocking operations, callback is called with + * opaque as parameter. If the callback returns 1, the + * blocking operation will be aborted. + * + * No members can be added to this struct without a major bump, if + * new elements have been added after this struct in AVFormatContext + * or AVIOContext. + */ +typedef struct AVIOInterruptCB { + int (*callback)(void*); + void *opaque; +} AVIOInterruptCB; + +/** + * Directory entry types. + */ +enum AVIODirEntryType { + AVIO_ENTRY_UNKNOWN, + AVIO_ENTRY_BLOCK_DEVICE, + AVIO_ENTRY_CHARACTER_DEVICE, + AVIO_ENTRY_DIRECTORY, + AVIO_ENTRY_NAMED_PIPE, + AVIO_ENTRY_SYMBOLIC_LINK, + AVIO_ENTRY_SOCKET, + AVIO_ENTRY_FILE, + AVIO_ENTRY_SERVER, + AVIO_ENTRY_SHARE, + AVIO_ENTRY_WORKGROUP, +}; + +/** + * Describes single entry of the directory. + * + * Only name and type fields are guaranteed be set. + * Rest of fields are protocol or/and platform dependent and might be unknown. + */ +typedef struct AVIODirEntry { + char *name; /**< Filename */ + int type; /**< Type of the entry */ + int utf8; /**< Set to 1 when name is encoded with UTF-8, 0 otherwise. + Name can be encoded with UTF-8 even though 0 is set. */ + int64_t size; /**< File size in bytes, -1 if unknown. */ + int64_t modification_timestamp; /**< Time of last modification in microseconds since unix + epoch, -1 if unknown. */ + int64_t access_timestamp; /**< Time of last access in microseconds since unix epoch, + -1 if unknown. */ + int64_t status_change_timestamp; /**< Time of last status change in microseconds since unix + epoch, -1 if unknown. */ + int64_t user_id; /**< User ID of owner, -1 if unknown. */ + int64_t group_id; /**< Group ID of owner, -1 if unknown. */ + int64_t filemode; /**< Unix file mode, -1 if unknown. */ +} AVIODirEntry; + +typedef struct AVIODirContext { + struct URLContext *url_context; +} AVIODirContext; + +/** + * Different data types that can be returned via the AVIO + * write_data_type callback. + */ +enum AVIODataMarkerType { + /** + * Header data; this needs to be present for the stream to be decodeable. + */ + AVIO_DATA_MARKER_HEADER, + /** + * A point in the output bytestream where a decoder can start decoding + * (i.e. a keyframe). A demuxer/decoder given the data flagged with + * AVIO_DATA_MARKER_HEADER, followed by any AVIO_DATA_MARKER_SYNC_POINT, + * should give decodeable results. + */ + AVIO_DATA_MARKER_SYNC_POINT, + /** + * A point in the output bytestream where a demuxer can start parsing + * (for non self synchronizing bytestream formats). That is, any + * non-keyframe packet start point. + */ + AVIO_DATA_MARKER_BOUNDARY_POINT, + /** + * This is any, unlabelled data. It can either be a muxer not marking + * any positions at all, it can be an actual boundary/sync point + * that the muxer chooses not to mark, or a later part of a packet/fragment + * that is cut into multiple write callbacks due to limited IO buffer size. + */ + AVIO_DATA_MARKER_UNKNOWN, + /** + * Trailer data, which doesn't contain actual content, but only for + * finalizing the output file. + */ + AVIO_DATA_MARKER_TRAILER, + /** + * A point in the output bytestream where the underlying AVIOContext might + * flush the buffer depending on latency or buffering requirements. Typically + * means the end of a packet. + */ + AVIO_DATA_MARKER_FLUSH_POINT, +}; + +/** + * Bytestream IO Context. + * New public fields can be added with minor version bumps. + * Removal, reordering and changes to existing public fields require + * a major version bump. + * sizeof(AVIOContext) must not be used outside libav*. + * + * @note None of the function pointers in AVIOContext should be called + * directly, they should only be set by the client application + * when implementing custom I/O. Normally these are set to the + * function pointers specified in avio_alloc_context() + */ +typedef struct AVIOContext { + /** + * A class for private options. + * + * If this AVIOContext is created by avio_open2(), av_class is set and + * passes the options down to protocols. + * + * If this AVIOContext is manually allocated, then av_class may be set by + * the caller. + * + * warning -- this field can be NULL, be sure to not pass this AVIOContext + * to any av_opt_* functions in that case. + */ + const AVClass *av_class; + + /* + * The following shows the relationship between buffer, buf_ptr, + * buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing + * (since AVIOContext is used for both): + * + ********************************************************************************** + * READING + ********************************************************************************** + * + * | buffer_size | + * |---------------------------------------| + * | | + * + * buffer buf_ptr buf_end + * +---------------+-----------------------+ + * |/ / / / / / / /|/ / / / / / /| | + * read buffer: |/ / consumed / | to be read /| | + * |/ / / / / / / /|/ / / / / / /| | + * +---------------+-----------------------+ + * + * pos + * +-------------------------------------------+-----------------+ + * input file: | | | + * +-------------------------------------------+-----------------+ + * + * + ********************************************************************************** + * WRITING + ********************************************************************************** + * + * | buffer_size | + * |--------------------------------------| + * | | + * + * buf_ptr_max + * buffer (buf_ptr) buf_end + * +-----------------------+--------------+ + * |/ / / / / / / / / / / /| | + * write buffer: | / / to be flushed / / | | + * |/ / / / / / / / / / / /| | + * +-----------------------+--------------+ + * buf_ptr can be in this + * due to a backward seek + * + * pos + * +-------------+----------------------------------------------+ + * output file: | | | + * +-------------+----------------------------------------------+ + * + */ + unsigned char *buffer; /**< Start of the buffer. */ + int buffer_size; /**< Maximum buffer size */ + unsigned char *buf_ptr; /**< Current position in the buffer */ + unsigned char *buf_end; /**< End of the data, may be less than + buffer+buffer_size if the read function returned + less data than requested, e.g. for streams where + no more data has been received yet. */ + void *opaque; /**< A private pointer, passed to the read/write/seek/... + functions. */ + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size); + int (*write_packet)(void *opaque, uint8_t *buf, int buf_size); + int64_t (*seek)(void *opaque, int64_t offset, int whence); + int64_t pos; /**< position in the file of the current buffer */ + int eof_reached; /**< true if was unable to read due to error or eof */ + int error; /**< contains the error code or 0 if no error happened */ + int write_flag; /**< true if open for writing */ + int max_packet_size; + int min_packet_size; /**< Try to buffer at least this amount of data + before flushing it. */ + unsigned long checksum; + unsigned char *checksum_ptr; + unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size); + /** + * Pause or resume playback for network streaming protocols - e.g. MMS. + */ + int (*read_pause)(void *opaque, int pause); + /** + * Seek to a given timestamp in stream with the specified stream_index. + * Needed for some network streaming protocols which don't support seeking + * to byte position. + */ + int64_t (*read_seek)(void *opaque, int stream_index, + int64_t timestamp, int flags); + /** + * A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable. + */ + int seekable; + + /** + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ + int direct; + + /** + * ',' separated list of allowed protocols. + */ + const char *protocol_whitelist; + + /** + * ',' separated list of disallowed protocols. + */ + const char *protocol_blacklist; + + /** + * A callback that is used instead of write_packet. + */ + int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size, + enum AVIODataMarkerType type, int64_t time); + /** + * If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT, + * but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly + * small chunks of data returned from the callback). + */ + int ignore_boundary_point; + +#if FF_API_AVIOCONTEXT_WRITTEN + /** + * @deprecated field utilized privately by libavformat. For a public + * statistic of how many bytes were written out, see + * AVIOContext::bytes_written. + */ + attribute_deprecated + int64_t written; +#endif + + /** + * Maximum reached position before a backward seek in the write buffer, + * used keeping track of already written data for a later flush. + */ + unsigned char *buf_ptr_max; + + /** + * Read-only statistic of bytes read for this AVIOContext. + */ + int64_t bytes_read; + + /** + * Read-only statistic of bytes written for this AVIOContext. + */ + int64_t bytes_written; +} AVIOContext; + +/** + * Return the name of the protocol that will handle the passed URL. + * + * NULL is returned if no protocol could be found for the given URL. + * + * @return Name of the protocol or NULL. + */ +const char *avio_find_protocol_name(const char *url); + +/** + * Return AVIO_FLAG_* access flags corresponding to the access permissions + * of the resource in url, or a negative value corresponding to an + * AVERROR code in case of failure. The returned access flags are + * masked by the value in flags. + * + * @note This function is intrinsically unsafe, in the sense that the + * checked resource may change its existence or permission status from + * one call to another. Thus you should not trust the returned value, + * unless you are sure that no other processes are accessing the + * checked resource. + */ +int avio_check(const char *url, int flags); + +/** + * Open directory for reading. + * + * @param s directory read context. Pointer to a NULL pointer must be passed. + * @param url directory to be listed. + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dictionary + * containing options that were not found. May be NULL. + * @return >=0 on success or negative on error. + */ +int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options); + +/** + * Get next directory entry. + * + * Returned entry must be freed with avio_free_directory_entry(). In particular + * it may outlive AVIODirContext. + * + * @param s directory read context. + * @param[out] next next entry or NULL when no more entries. + * @return >=0 on success or negative on error. End of list is not considered an + * error. + */ +int avio_read_dir(AVIODirContext *s, AVIODirEntry **next); + +/** + * Close directory. + * + * @note Entries created using avio_read_dir() are not deleted and must be + * freeded with avio_free_directory_entry(). + * + * @param s directory read context. + * @return >=0 on success or negative on error. + */ +int avio_close_dir(AVIODirContext **s); + +/** + * Free entry allocated by avio_read_dir(). + * + * @param entry entry to be freed. + */ +void avio_free_directory_entry(AVIODirEntry **entry); + +/** + * Allocate and initialize an AVIOContext for buffered I/O. It must be later + * freed with avio_context_free(). + * + * @param buffer Memory block for input/output operations via AVIOContext. + * The buffer must be allocated with av_malloc() and friends. + * It may be freed and replaced with a new buffer by libavformat. + * AVIOContext.buffer holds the buffer currently in use, + * which must be later freed with av_free(). + * @param buffer_size The buffer size is very important for performance. + * For protocols with fixed blocksize it should be set to this blocksize. + * For others a typical size is a cache page, e.g. 4kb. + * @param write_flag Set to 1 if the buffer should be writable, 0 otherwise. + * @param opaque An opaque pointer to user-specific data. + * @param read_packet A function for refilling the buffer, may be NULL. + * For stream protocols, must never return 0 but rather + * a proper AVERROR code. + * @param write_packet A function for writing the buffer contents, may be NULL. + * The function may not change the input buffers content. + * @param seek A function for seeking to specified byte position, may be NULL. + * + * @return Allocated AVIOContext or NULL on failure. + */ +AVIOContext *avio_alloc_context( + unsigned char *buffer, + int buffer_size, + int write_flag, + void *opaque, + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), + int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), + int64_t (*seek)(void *opaque, int64_t offset, int whence)); + +/** + * Free the supplied IO context and everything associated with it. + * + * @param s Double pointer to the IO context. This function will write NULL + * into s. + */ +void avio_context_free(AVIOContext **s); + +void avio_w8(AVIOContext *s, int b); +void avio_write(AVIOContext *s, const unsigned char *buf, int size); +void avio_wl64(AVIOContext *s, uint64_t val); +void avio_wb64(AVIOContext *s, uint64_t val); +void avio_wl32(AVIOContext *s, unsigned int val); +void avio_wb32(AVIOContext *s, unsigned int val); +void avio_wl24(AVIOContext *s, unsigned int val); +void avio_wb24(AVIOContext *s, unsigned int val); +void avio_wl16(AVIOContext *s, unsigned int val); +void avio_wb16(AVIOContext *s, unsigned int val); + +/** + * Write a NULL-terminated string. + * @return number of bytes written. + */ +int avio_put_str(AVIOContext *s, const char *str); + +/** + * Convert an UTF-8 string to UTF-16LE and write it. + * @param s the AVIOContext + * @param str NULL-terminated UTF-8 string + * + * @return number of bytes written. + */ +int avio_put_str16le(AVIOContext *s, const char *str); + +/** + * Convert an UTF-8 string to UTF-16BE and write it. + * @param s the AVIOContext + * @param str NULL-terminated UTF-8 string + * + * @return number of bytes written. + */ +int avio_put_str16be(AVIOContext *s, const char *str); + +/** + * Mark the written bytestream as a specific type. + * + * Zero-length ranges are omitted from the output. + * + * @param time the stream time the current bytestream pos corresponds to + * (in AV_TIME_BASE units), or AV_NOPTS_VALUE if unknown or not + * applicable + * @param type the kind of data written starting at the current pos + */ +void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type); + +/** + * ORing this as the "whence" parameter to a seek function causes it to + * return the filesize without seeking anywhere. Supporting this is optional. + * If it is not supported then the seek function will return <0. + */ +#define AVSEEK_SIZE 0x10000 + +/** + * Passing this flag as the "whence" parameter to a seek function causes it to + * seek by any means (like reopening and linear reading) or other normally unreasonable + * means that can be extremely slow. + * This may be ignored by the seek code. + */ +#define AVSEEK_FORCE 0x20000 + +/** + * fseek() equivalent for AVIOContext. + * @return new position or AVERROR. + */ +int64_t avio_seek(AVIOContext *s, int64_t offset, int whence); + +/** + * Skip given number of bytes forward + * @return new position or AVERROR. + */ +int64_t avio_skip(AVIOContext *s, int64_t offset); + +/** + * ftell() equivalent for AVIOContext. + * @return position or AVERROR. + */ +static av_always_inline int64_t avio_tell(AVIOContext *s) +{ + return avio_seek(s, 0, SEEK_CUR); +} + +/** + * Get the filesize. + * @return filesize or AVERROR + */ +int64_t avio_size(AVIOContext *s); + +/** + * Similar to feof() but also returns nonzero on read errors. + * @return non zero if and only if at end of file or a read error happened when reading. + */ +int avio_feof(AVIOContext *s); + +/** + * Writes a formatted string to the context taking a va_list. + * @return number of bytes written, < 0 on error. + */ +int avio_vprintf(AVIOContext *s, const char *fmt, va_list ap); + +/** + * Writes a formatted string to the context. + * @return number of bytes written, < 0 on error. + */ +int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3); + +/** + * Write a NULL terminated array of strings to the context. + * Usually you don't need to use this function directly but its macro wrapper, + * avio_print. + */ +void avio_print_string_array(AVIOContext *s, const char *strings[]); + +/** + * Write strings (const char *) to the context. + * This is a convenience macro around avio_print_string_array and it + * automatically creates the string array from the variable argument list. + * For simple string concatenations this function is more performant than using + * avio_printf since it does not need a temporary buffer. + */ +#define avio_print(s, ...) \ + avio_print_string_array(s, (const char*[]){__VA_ARGS__, NULL}) + +/** + * Force flushing of buffered data. + * + * For write streams, force the buffered data to be immediately written to the output, + * without to wait to fill the internal buffer. + * + * For read streams, discard all currently buffered data, and advance the + * reported file position to that of the underlying stream. This does not + * read new data, and does not perform any seeks. + */ +void avio_flush(AVIOContext *s); + +/** + * Read size bytes from AVIOContext into buf. + * @return number of bytes read or AVERROR + */ +int avio_read(AVIOContext *s, unsigned char *buf, int size); + +/** + * Read size bytes from AVIOContext into buf. Unlike avio_read(), this is allowed + * to read fewer bytes than requested. The missing bytes can be read in the next + * call. This always tries to read at least 1 byte. + * Useful to reduce latency in certain cases. + * @return number of bytes read or AVERROR + */ +int avio_read_partial(AVIOContext *s, unsigned char *buf, int size); + +/** + * @name Functions for reading from AVIOContext + * @{ + * + * @note return 0 if EOF, so you cannot use it if EOF handling is + * necessary + */ +int avio_r8 (AVIOContext *s); +unsigned int avio_rl16(AVIOContext *s); +unsigned int avio_rl24(AVIOContext *s); +unsigned int avio_rl32(AVIOContext *s); +uint64_t avio_rl64(AVIOContext *s); +unsigned int avio_rb16(AVIOContext *s); +unsigned int avio_rb24(AVIOContext *s); +unsigned int avio_rb32(AVIOContext *s); +uint64_t avio_rb64(AVIOContext *s); +/** + * @} + */ + +/** + * Read a string from pb into buf. The reading will terminate when either + * a NULL character was encountered, maxlen bytes have been read, or nothing + * more can be read from pb. The result is guaranteed to be NULL-terminated, it + * will be truncated if buf is too small. + * Note that the string is not interpreted or validated in any way, it + * might get truncated in the middle of a sequence for multi-byte encodings. + * + * @return number of bytes read (is always <= maxlen). + * If reading ends on EOF or error, the return value will be one more than + * bytes actually read. + */ +int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen); + +/** + * Read a UTF-16 string from pb and convert it to UTF-8. + * The reading will terminate when either a null or invalid character was + * encountered or maxlen bytes have been read. + * @return number of bytes read (is always <= maxlen) + */ +int avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen); +int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen); + + +/** + * @name URL open modes + * The flags argument to avio_open must be one of the following + * constants, optionally ORed with other flags. + * @{ + */ +#define AVIO_FLAG_READ 1 /**< read-only */ +#define AVIO_FLAG_WRITE 2 /**< write-only */ +#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE) /**< read-write pseudo flag */ +/** + * @} + */ + +/** + * Use non-blocking mode. + * If this flag is set, operations on the context will return + * AVERROR(EAGAIN) if they can not be performed immediately. + * If this flag is not set, operations on the context will never return + * AVERROR(EAGAIN). + * Note that this flag does not affect the opening/connecting of the + * context. Connecting a protocol will always block if necessary (e.g. on + * network protocols) but never hang (e.g. on busy devices). + * Warning: non-blocking protocols is work-in-progress; this flag may be + * silently ignored. + */ +#define AVIO_FLAG_NONBLOCK 8 + +/** + * Use direct mode. + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ +#define AVIO_FLAG_DIRECT 0x8000 + +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param url resource to access + * @param flags flags which control how the resource indicated by url + * is to be opened + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open(AVIOContext **s, const char *url, int flags); + +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param url resource to access + * @param flags flags which control how the resource indicated by url + * is to be opened + * @param int_cb an interrupt callback to be used at the protocols level + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dict containing options + * that were not found. May be NULL. + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open2(AVIOContext **s, const char *url, int flags, + const AVIOInterruptCB *int_cb, AVDictionary **options); + +/** + * Close the resource accessed by the AVIOContext s and free it. + * This function can only be used if s was opened by avio_open(). + * + * The internal buffer is automatically flushed before closing the + * resource. + * + * @return 0 on success, an AVERROR < 0 on error. + * @see avio_closep + */ +int avio_close(AVIOContext *s); + +/** + * Close the resource accessed by the AVIOContext *s, free it + * and set the pointer pointing to it to NULL. + * This function can only be used if s was opened by avio_open(). + * + * The internal buffer is automatically flushed before closing the + * resource. + * + * @return 0 on success, an AVERROR < 0 on error. + * @see avio_close + */ +int avio_closep(AVIOContext **s); + + +/** + * Open a write only memory stream. + * + * @param s new IO context + * @return zero if no error. + */ +int avio_open_dyn_buf(AVIOContext **s); + +/** + * Return the written size and a pointer to the buffer. + * The AVIOContext stream is left intact. + * The buffer must NOT be freed. + * No padding is added to the buffer. + * + * @param s IO context + * @param pbuffer pointer to a byte buffer + * @return the length of the byte buffer + */ +int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + +/** + * Return the written size and a pointer to the buffer. The buffer + * must be freed with av_free(). + * Padding of AV_INPUT_BUFFER_PADDING_SIZE is added to the buffer. + * + * @param s IO context + * @param pbuffer pointer to a byte buffer + * @return the length of the byte buffer + */ +int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + +/** + * Iterate through names of available protocols. + * + * @param opaque A private pointer representing current protocol. + * It must be a pointer to NULL on first iteration and will + * be updated by successive calls to avio_enum_protocols. + * @param output If set to 1, iterate over output protocols, + * otherwise over input protocols. + * + * @return A static string containing the name of current protocol or NULL + */ +const char *avio_enum_protocols(void **opaque, int output); + +/** + * Get AVClass by names of available protocols. + * + * @return A AVClass of input protocol name or NULL + */ +const AVClass *avio_protocol_get_class(const char *name); + +/** + * Pause and resume playing - only meaningful if using a network streaming + * protocol (e.g. MMS). + * + * @param h IO context from which to call the read_pause function pointer + * @param pause 1 for pause, 0 for resume + */ +int avio_pause(AVIOContext *h, int pause); + +/** + * Seek to a given timestamp relative to some component stream. + * Only meaningful if using a network streaming protocol (e.g. MMS.). + * + * @param h IO context from which to call the seek function pointers + * @param stream_index The stream index that the timestamp is relative to. + * If stream_index is (-1) the timestamp should be in AV_TIME_BASE + * units from the beginning of the presentation. + * If a stream_index >= 0 is used and the protocol does not support + * seeking based on component streams, the call will fail. + * @param timestamp timestamp in AVStream.time_base units + * or if there is no stream specified then in AV_TIME_BASE units. + * @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE + * and AVSEEK_FLAG_ANY. The protocol may silently ignore + * AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will + * fail if used and not supported. + * @return >= 0 on success + * @see AVInputFormat::read_seek + */ +int64_t avio_seek_time(AVIOContext *h, int stream_index, + int64_t timestamp, int flags); + +/* Avoid a warning. The header can not be included because it breaks c++. */ +struct AVBPrint; + +/** + * Read contents of h into print buffer, up to max_size bytes, or up to EOF. + * + * @return 0 for success (max_size bytes read or EOF reached), negative error + * code otherwise + */ +int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size); + +/** + * Accept and allocate a client context on a server context. + * @param s the server context + * @param c the client context, must be unallocated + * @return >= 0 on success or a negative value corresponding + * to an AVERROR on failure + */ +int avio_accept(AVIOContext *s, AVIOContext **c); + +/** + * Perform one step of the protocol handshake to accept a new client. + * This function must be called on a client returned by avio_accept() before + * using it as a read/write context. + * It is separate from avio_accept() because it may block. + * A step of the handshake is defined by places where the application may + * decide to change the proceedings. + * For example, on a protocol with a request header and a reply header, each + * one can constitute a step because the application may use the parameters + * from the request to change parameters in the reply; or each individual + * chunk of the request can constitute a step. + * If the handshake is already finished, avio_handshake() does nothing and + * returns 0 immediately. + * + * @param c the client context to perform the handshake on + * @return 0 on a complete and successful handshake + * > 0 if the handshake progressed, but is not complete + * < 0 for an AVERROR code + */ +int avio_handshake(AVIOContext *c); +#endif /* AVFORMAT_AVIO_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavformat/version.h b/src/framework/media/thirdparty/ffmpeg/v5/libavformat/version.h new file mode 100644 index 0000000000000..b234218b10bd9 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavformat/version.h @@ -0,0 +1,47 @@ +/* + * Version macros. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_VERSION_H +#define AVFORMAT_VERSION_H + +/** + * @file + * @ingroup libavf + * Libavformat version macros + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBAVFORMAT_VERSION_MINOR 27 +#define LIBAVFORMAT_VERSION_MICRO 100 + +#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT + +#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) + +#endif /* AVFORMAT_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavformat/version_major.h b/src/framework/media/thirdparty/ffmpeg/v5/libavformat/version_major.h new file mode 100644 index 0000000000000..5f71298bcc73b --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavformat/version_major.h @@ -0,0 +1,53 @@ +/* + * Version macros. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_VERSION_MAJOR_H +#define AVFORMAT_VERSION_MAJOR_H + +/** + * @file + * @ingroup libavf + * Libavformat version macros + */ + +// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) +// Also please add any ticket numbers that you believe might be affected here +#define LIBAVFORMAT_VERSION_MAJOR 59 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + * + */ +#define FF_API_LAVF_PRIV_OPT (LIBAVFORMAT_VERSION_MAJOR < 60) +#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 60) +#define FF_API_AVIOCONTEXT_WRITTEN (LIBAVFORMAT_VERSION_MAJOR < 60) +#define FF_HLS_TS_OPTIONS (LIBAVFORMAT_VERSION_MAJOR < 60) +#define FF_API_AVSTREAM_CLASS (LIBAVFORMAT_VERSION_MAJOR > 59) + + +#define FF_API_R_FRAME_RATE 1 + +#endif /* AVFORMAT_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/attributes.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/attributes.h new file mode 100644 index 0000000000000..04c615c952c46 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/attributes.h @@ -0,0 +1,173 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Macro definitions for various function/variable attributes + */ + +#ifndef AVUTIL_ATTRIBUTES_H +#define AVUTIL_ATTRIBUTES_H + +#ifdef __GNUC__ +# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) +# define AV_GCC_VERSION_AT_MOST(x,y) (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y)) +#else +# define AV_GCC_VERSION_AT_LEAST(x,y) 0 +# define AV_GCC_VERSION_AT_MOST(x,y) 0 +#endif + +#ifdef __has_builtin +# define AV_HAS_BUILTIN(x) __has_builtin(x) +#else +# define AV_HAS_BUILTIN(x) 0 +#endif + +#ifndef av_always_inline +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_always_inline __attribute__((always_inline)) inline +#elif defined(_MSC_VER) +# define av_always_inline __forceinline +#else +# define av_always_inline inline +#endif +#endif + +#ifndef av_extern_inline +#if defined(__ICL) && __ICL >= 1210 || defined(__GNUC_STDC_INLINE__) +# define av_extern_inline extern inline +#else +# define av_extern_inline inline +#endif +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,4) +# define av_warn_unused_result __attribute__((warn_unused_result)) +#else +# define av_warn_unused_result +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_noinline __attribute__((noinline)) +#elif defined(_MSC_VER) +# define av_noinline __declspec(noinline) +#else +# define av_noinline +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) +# define av_pure __attribute__((pure)) +#else +# define av_pure +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,6) || defined(__clang__) +# define av_const __attribute__((const)) +#else +# define av_const +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,3) || defined(__clang__) +# define av_cold __attribute__((cold)) +#else +# define av_cold +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,1) && !defined(__llvm__) +# define av_flatten __attribute__((flatten)) +#else +# define av_flatten +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define attribute_deprecated __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define attribute_deprecated __declspec(deprecated) +#else +# define attribute_deprecated +#endif + +/** + * Disable warnings about deprecated features + * This is useful for sections of code kept for backward compatibility and + * scheduled for removal. + */ +#ifndef AV_NOWARN_DEPRECATED +#if AV_GCC_VERSION_AT_LEAST(4,6) || defined(__clang__) +# define AV_NOWARN_DEPRECATED(code) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \ + code \ + _Pragma("GCC diagnostic pop") +#elif defined(_MSC_VER) +# define AV_NOWARN_DEPRECATED(code) \ + __pragma(warning(push)) \ + __pragma(warning(disable : 4996)) \ + code; \ + __pragma(warning(pop)) +#else +# define AV_NOWARN_DEPRECATED(code) code +#endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define av_unused __attribute__((unused)) +#else +# define av_unused +#endif + +/** + * Mark a variable as used and prevent the compiler from optimizing it + * away. This is useful for variables accessed only from inline + * assembler without the compiler being aware. + */ +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) +# define av_used __attribute__((used)) +#else +# define av_used +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,3) || defined(__clang__) +# define av_alias __attribute__((may_alias)) +#else +# define av_alias +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__INTEL_COMPILER) +# define av_uninit(x) x=x +#else +# define av_uninit(x) x +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define av_builtin_constant_p __builtin_constant_p +# define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos))) +#else +# define av_builtin_constant_p(x) 0 +# define av_printf_format(fmtpos, attrpos) +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,5) || defined(__clang__) +# define av_noreturn __attribute__((noreturn)) +#else +# define av_noreturn +#endif + +#endif /* AVUTIL_ATTRIBUTES_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/avconfig.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/avconfig.h new file mode 100644 index 0000000000000..f13252f7d2c25 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/avconfig.h @@ -0,0 +1,24 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVCONFIG_H +#define AVUTIL_AVCONFIG_H + +#define AV_HAVE_BIGENDIAN 0 + +#endif /* AVUTIL_AVCONFIG_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/avstring.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/avstring.h new file mode 100644 index 0000000000000..fae446c302744 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/avstring.h @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2007 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVSTRING_H +#define AVUTIL_AVSTRING_H + +#include +#include +#include "attributes.h" +#include "version.h" + +/** + * @addtogroup lavu_string + * @{ + */ + +/** + * Return non-zero if pfx is a prefix of str. If it is, *ptr is set to + * the address of the first character in str after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_strstart(const char *str, const char *pfx, const char **ptr); + +/** + * Return non-zero if pfx is a prefix of str independent of case. If + * it is, *ptr is set to the address of the first character in str + * after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_stristart(const char *str, const char *pfx, const char **ptr); + +/** + * Locate the first case-independent occurrence in the string haystack + * of the string needle. A zero-length string needle is considered to + * match at the start of haystack. + * + * This function is a case-insensitive version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_stristr(const char *haystack, const char *needle); + +/** + * Locate the first occurrence of the string needle in the string haystack + * where not more than hay_length characters are searched. A zero-length + * string needle is considered to match at the start of haystack. + * + * This function is a length-limited version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @param hay_length length of string to search in + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_strnstr(const char *haystack, const char *needle, size_t hay_length); + +/** + * Copy the string src to dst, but no more than size - 1 bytes, and + * null-terminate dst. + * + * This function is the same as BSD strlcpy(). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the length of src + * + * @warning since the return value is the length of src, src absolutely + * _must_ be a properly 0-terminated string, otherwise this will read beyond + * the end of the buffer and possibly crash. + */ +size_t av_strlcpy(char *dst, const char *src, size_t size); + +/** + * Append the string src to the string dst, but to a total length of + * no more than size - 1 bytes, and null-terminate dst. + * + * This function is similar to BSD strlcat(), but differs when + * size <= strlen(dst). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the total length of src and dst + * + * @warning since the return value use the length of src and dst, these + * absolutely _must_ be a properly 0-terminated strings, otherwise this + * will read beyond the end of the buffer and possibly crash. + */ +size_t av_strlcat(char *dst, const char *src, size_t size); + +/** + * Append output to a string, according to a format. Never write out of + * the destination buffer, and always put a terminating 0 within + * the buffer. + * @param dst destination buffer (string to which the output is + * appended) + * @param size total size of the destination buffer + * @param fmt printf-compatible format string, specifying how the + * following parameters are used + * @return the length of the string that would have been generated + * if enough space had been available + */ +size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Get the count of continuous non zero chars starting from the beginning. + * + * @param len maximum number of characters to check in the string, that + * is the maximum value which is returned by the function + */ +static inline size_t av_strnlen(const char *s, size_t len) +{ + size_t i; + for (i = 0; i < len && s[i]; i++) + ; + return i; +} + +/** + * Print arguments following specified format into a large enough auto + * allocated buffer. It is similar to GNU asprintf(). + * @param fmt printf-compatible format string, specifying how the + * following parameters are used. + * @return the allocated string + * @note You have to free the string yourself with av_free(). + */ +char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2); + +#if FF_API_D2STR +/** + * Convert a number to an av_malloced string. + * @deprecated use av_asprintf() with "%f" or a more specific format + */ +attribute_deprecated +char *av_d2str(double d); +#endif + +/** + * Unescape the given string until a non escaped terminating char, + * and return the token corresponding to the unescaped string. + * + * The normal \ and ' escaping is supported. Leading and trailing + * whitespaces are removed, unless they are escaped with '\' or are + * enclosed between ''. + * + * @param buf the buffer to parse, buf will be updated to point to the + * terminating char + * @param term a 0-terminated list of terminating chars + * @return the malloced unescaped string, which must be av_freed by + * the user, NULL in case of allocation failure + */ +char *av_get_token(const char **buf, const char *term); + +/** + * Split the string into several tokens which can be accessed by + * successive calls to av_strtok(). + * + * A token is defined as a sequence of characters not belonging to the + * set specified in delim. + * + * On the first call to av_strtok(), s should point to the string to + * parse, and the value of saveptr is ignored. In subsequent calls, s + * should be NULL, and saveptr should be unchanged since the previous + * call. + * + * This function is similar to strtok_r() defined in POSIX.1. + * + * @param s the string to parse, may be NULL + * @param delim 0-terminated list of token delimiters, must be non-NULL + * @param saveptr user-provided pointer which points to stored + * information necessary for av_strtok() to continue scanning the same + * string. saveptr is updated to point to the next character after the + * first delimiter found, or to NULL if the string was terminated + * @return the found token, or NULL when no token is found + */ +char *av_strtok(char *s, const char *delim, char **saveptr); + +/** + * Locale-independent conversion of ASCII isdigit. + */ +static inline av_const int av_isdigit(int c) +{ + return c >= '0' && c <= '9'; +} + +/** + * Locale-independent conversion of ASCII isgraph. + */ +static inline av_const int av_isgraph(int c) +{ + return c > 32 && c < 127; +} + +/** + * Locale-independent conversion of ASCII isspace. + */ +static inline av_const int av_isspace(int c) +{ + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || + c == '\v'; +} + +/** + * Locale-independent conversion of ASCII characters to uppercase. + */ +static inline av_const int av_toupper(int c) +{ + if (c >= 'a' && c <= 'z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII characters to lowercase. + */ +static inline av_const int av_tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII isxdigit. + */ +static inline av_const int av_isxdigit(int c) +{ + c = av_tolower(c); + return av_isdigit(c) || (c >= 'a' && c <= 'f'); +} + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strcasecmp(const char *a, const char *b); + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strncasecmp(const char *a, const char *b, size_t n); + +/** + * Locale-independent strings replace. + * @note This means only ASCII-range characters are replace + */ +char *av_strireplace(const char *str, const char *from, const char *to); + +/** + * Thread safe basename. + * @param path the string to parse, on DOS both \ and / are considered separators. + * @return pointer to the basename substring. + * If path does not contain a slash, the function returns a copy of path. + * If path is a NULL pointer or points to an empty string, a pointer + * to a string "." is returned. + */ +const char *av_basename(const char *path); + +/** + * Thread safe dirname. + * @param path the string to parse, on DOS both \ and / are considered separators. + * @return A pointer to a string that's the parent directory of path. + * If path is a NULL pointer or points to an empty string, a pointer + * to a string "." is returned. + * @note the function may modify the contents of the path, so copies should be passed. + */ +const char *av_dirname(char *path); + +/** + * Match instances of a name in a comma-separated list of names. + * List entries are checked from the start to the end of the names list, + * the first match ends further processing. If an entry prefixed with '-' + * matches, then 0 is returned. The "ALL" list entry is considered to + * match all names. + * + * @param name Name to look for. + * @param names List of names. + * @return 1 on match, 0 otherwise. + */ +int av_match_name(const char *name, const char *names); + +/** + * Append path component to the existing path. + * Path separator '/' is placed between when needed. + * Resulting string have to be freed with av_free(). + * @param path base path + * @param component component to be appended + * @return new path or NULL on error. + */ +char *av_append_path_component(const char *path, const char *component); + +enum AVEscapeMode { + AV_ESCAPE_MODE_AUTO, ///< Use auto-selected escaping mode. + AV_ESCAPE_MODE_BACKSLASH, ///< Use backslash escaping. + AV_ESCAPE_MODE_QUOTE, ///< Use single-quote escaping. + AV_ESCAPE_MODE_XML, ///< Use XML non-markup character data escaping. +}; + +/** + * Consider spaces special and escape them even in the middle of the + * string. + * + * This is equivalent to adding the whitespace characters to the special + * characters lists, except it is guaranteed to use the exact same list + * of whitespace characters as the rest of libavutil. + */ +#define AV_ESCAPE_FLAG_WHITESPACE (1 << 0) + +/** + * Escape only specified special characters. + * Without this flag, escape also any characters that may be considered + * special by av_get_token(), such as the single quote. + */ +#define AV_ESCAPE_FLAG_STRICT (1 << 1) + +/** + * Within AV_ESCAPE_MODE_XML, additionally escape single quotes for single + * quoted attributes. + */ +#define AV_ESCAPE_FLAG_XML_SINGLE_QUOTES (1 << 2) + +/** + * Within AV_ESCAPE_MODE_XML, additionally escape double quotes for double + * quoted attributes. + */ +#define AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES (1 << 3) + + +/** + * Escape string in src, and put the escaped string in an allocated + * string in *dst, which must be freed with av_free(). + * + * @param dst pointer where an allocated string is put + * @param src string to escape, must be non-NULL + * @param special_chars string containing the special characters which + * need to be escaped, can be NULL + * @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros. + * Any unknown value for mode will be considered equivalent to + * AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without + * notice. + * @param flags flags which control how to escape, see AV_ESCAPE_FLAG_ macros + * @return the length of the allocated string, or a negative error code in case of error + * @see av_bprint_escape() + */ +av_warn_unused_result +int av_escape(char **dst, const char *src, const char *special_chars, + enum AVEscapeMode mode, int flags); + +#define AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES 1 ///< accept codepoints over 0x10FFFF +#define AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS 2 ///< accept non-characters - 0xFFFE and 0xFFFF +#define AV_UTF8_FLAG_ACCEPT_SURROGATES 4 ///< accept UTF-16 surrogates codes +#define AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES 8 ///< exclude control codes not accepted by XML + +#define AV_UTF8_FLAG_ACCEPT_ALL \ + AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES|AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS|AV_UTF8_FLAG_ACCEPT_SURROGATES + +/** + * Read and decode a single UTF-8 code point (character) from the + * buffer in *buf, and update *buf to point to the next byte to + * decode. + * + * In case of an invalid byte sequence, the pointer will be updated to + * the next byte after the invalid sequence and the function will + * return an error code. + * + * Depending on the specified flags, the function will also fail in + * case the decoded code point does not belong to a valid range. + * + * @note For speed-relevant code a carefully implemented use of + * GET_UTF8() may be preferred. + * + * @param codep pointer used to return the parsed code in case of success. + * The value in *codep is set even in case the range check fails. + * @param bufp pointer to the address the first byte of the sequence + * to decode, updated by the function to point to the + * byte next after the decoded sequence + * @param buf_end pointer to the end of the buffer, points to the next + * byte past the last in the buffer. This is used to + * avoid buffer overreads (in case of an unfinished + * UTF-8 sequence towards the end of the buffer). + * @param flags a collection of AV_UTF8_FLAG_* flags + * @return >= 0 in case a sequence was successfully read, a negative + * value in case of invalid sequence + */ +av_warn_unused_result +int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end, + unsigned int flags); + +/** + * Check if a name is in a list. + * @returns 0 if not found, or the 1 based index where it has been found in the + * list. + */ +int av_match_list(const char *name, const char *list, char separator); + +/** + * See libc sscanf manual for more information. + * Locale-independent sscanf implementation. + */ +int av_sscanf(const char *string, const char *format, ...); + +/** + * @} + */ + +#endif /* AVUTIL_AVSTRING_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/avutil.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/avutil.h new file mode 100644 index 0000000000000..64b68bdbd33cc --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/avutil.h @@ -0,0 +1,371 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVUTIL_H +#define AVUTIL_AVUTIL_H + +/** + * @file + * @ingroup lavu + * Convenience header that includes @ref lavu "libavutil"'s core. + */ + +/** + * @mainpage + * + * @section ffmpeg_intro Introduction + * + * This document describes the usage of the different libraries + * provided by FFmpeg. + * + * @li @ref libavc "libavcodec" encoding/decoding library + * @li @ref lavfi "libavfilter" graph-based frame editing library + * @li @ref libavf "libavformat" I/O and muxing/demuxing library + * @li @ref lavd "libavdevice" special devices muxing/demuxing library + * @li @ref lavu "libavutil" common utility library + * @li @ref lswr "libswresample" audio resampling, format conversion and mixing + * @li @ref lpp "libpostproc" post processing library + * @li @ref libsws "libswscale" color conversion and scaling library + * + * @section ffmpeg_versioning Versioning and compatibility + * + * Each of the FFmpeg libraries contains a version.h header, which defines a + * major, minor and micro version number with the + * LIBRARYNAME_VERSION_{MAJOR,MINOR,MICRO} macros. The major version + * number is incremented with backward incompatible changes - e.g. removing + * parts of the public API, reordering public struct members, etc. The minor + * version number is incremented for backward compatible API changes or major + * new features - e.g. adding a new public function or a new decoder. The micro + * version number is incremented for smaller changes that a calling program + * might still want to check for - e.g. changing behavior in a previously + * unspecified situation. + * + * FFmpeg guarantees backward API and ABI compatibility for each library as long + * as its major version number is unchanged. This means that no public symbols + * will be removed or renamed. Types and names of the public struct members and + * values of public macros and enums will remain the same (unless they were + * explicitly declared as not part of the public API). Documented behavior will + * not change. + * + * In other words, any correct program that works with a given FFmpeg snapshot + * should work just as well without any changes with any later snapshot with the + * same major versions. This applies to both rebuilding the program against new + * FFmpeg versions or to replacing the dynamic FFmpeg libraries that a program + * links against. + * + * However, new public symbols may be added and new members may be appended to + * public structs whose size is not part of public ABI (most public structs in + * FFmpeg). New macros and enum values may be added. Behavior in undocumented + * situations may change slightly (and be documented). All those are accompanied + * by an entry in doc/APIchanges and incrementing either the minor or micro + * version number. + */ + +/** + * @defgroup lavu libavutil + * Common code shared across all FFmpeg libraries. + * + * @note + * libavutil is designed to be modular. In most cases, in order to use the + * functions provided by one component of libavutil you must explicitly include + * the specific header containing that feature. If you are only using + * media-related components, you could simply include libavutil/avutil.h, which + * brings in most of the "core" components. + * + * @{ + * + * @defgroup lavu_crypto Crypto and Hashing + * + * @{ + * @} + * + * @defgroup lavu_math Mathematics + * @{ + * + * @} + * + * @defgroup lavu_string String Manipulation + * + * @{ + * + * @} + * + * @defgroup lavu_mem Memory Management + * + * @{ + * + * @} + * + * @defgroup lavu_data Data Structures + * @{ + * + * @} + * + * @defgroup lavu_video Video related + * + * @{ + * + * @} + * + * @defgroup lavu_audio Audio related + * + * @{ + * + * @} + * + * @defgroup lavu_error Error Codes + * + * @{ + * + * @} + * + * @defgroup lavu_log Logging Facility + * + * @{ + * + * @} + * + * @defgroup lavu_misc Other + * + * @{ + * + * @defgroup preproc_misc Preprocessor String Macros + * + * @{ + * + * @} + * + * @defgroup version_utils Library Version Macros + * + * @{ + * + * @} + */ + + +/** + * @addtogroup lavu_ver + * @{ + */ + +/** + * Return the LIBAVUTIL_VERSION_INT constant. + */ +unsigned avutil_version(void); + +/** + * Return an informative version string. This usually is the actual release + * version number or a git commit description. This string has no fixed format + * and can change any time. It should never be parsed by code. + */ +const char *av_version_info(void); + +/** + * Return the libavutil build-time configuration. + */ +const char *avutil_configuration(void); + +/** + * Return the libavutil license. + */ +const char *avutil_license(void); + +/** + * @} + */ + +/** + * @addtogroup lavu_media Media Type + * @brief Media Type + */ + +enum AVMediaType { + AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA + AVMEDIA_TYPE_VIDEO, + AVMEDIA_TYPE_AUDIO, + AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous + AVMEDIA_TYPE_SUBTITLE, + AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse + AVMEDIA_TYPE_NB +}; + +/** + * Return a string describing the media_type enum, NULL if media_type + * is unknown. + */ +const char *av_get_media_type_string(enum AVMediaType media_type); + +/** + * @defgroup lavu_const Constants + * @{ + * + * @defgroup lavu_enc Encoding specific + * + * @note those definition should move to avcodec + * @{ + */ + +#define FF_LAMBDA_SHIFT 7 +#define FF_LAMBDA_SCALE (1< +#include + +/** + * @defgroup lavu_buffer AVBuffer + * @ingroup lavu_data + * + * @{ + * AVBuffer is an API for reference-counted data buffers. + * + * There are two core objects in this API -- AVBuffer and AVBufferRef. AVBuffer + * represents the data buffer itself; it is opaque and not meant to be accessed + * by the caller directly, but only through AVBufferRef. However, the caller may + * e.g. compare two AVBuffer pointers to check whether two different references + * are describing the same data buffer. AVBufferRef represents a single + * reference to an AVBuffer and it is the object that may be manipulated by the + * caller directly. + * + * There are two functions provided for creating a new AVBuffer with a single + * reference -- av_buffer_alloc() to just allocate a new buffer, and + * av_buffer_create() to wrap an existing array in an AVBuffer. From an existing + * reference, additional references may be created with av_buffer_ref(). + * Use av_buffer_unref() to free a reference (this will automatically free the + * data once all the references are freed). + * + * The convention throughout this API and the rest of FFmpeg is such that the + * buffer is considered writable if there exists only one reference to it (and + * it has not been marked as read-only). The av_buffer_is_writable() function is + * provided to check whether this is true and av_buffer_make_writable() will + * automatically create a new writable buffer when necessary. + * Of course nothing prevents the calling code from violating this convention, + * however that is safe only when all the existing references are under its + * control. + * + * @note Referencing and unreferencing the buffers is thread-safe and thus + * may be done from multiple threads simultaneously without any need for + * additional locking. + * + * @note Two different references to the same buffer can point to different + * parts of the buffer (i.e. their AVBufferRef.data will not be equal). + */ + +/** + * A reference counted buffer type. It is opaque and is meant to be used through + * references (AVBufferRef). + */ +typedef struct AVBuffer AVBuffer; + +/** + * A reference to a data buffer. + * + * The size of this struct is not a part of the public ABI and it is not meant + * to be allocated directly. + */ +typedef struct AVBufferRef { + AVBuffer *buffer; + + /** + * The data buffer. It is considered writable if and only if + * this is the only reference to the buffer, in which case + * av_buffer_is_writable() returns 1. + */ + uint8_t *data; + /** + * Size of data in bytes. + */ + size_t size; +} AVBufferRef; + +/** + * Allocate an AVBuffer of the given size using av_malloc(). + * + * @return an AVBufferRef of given size or NULL when out of memory + */ +AVBufferRef *av_buffer_alloc(size_t size); + +/** + * Same as av_buffer_alloc(), except the returned buffer will be initialized + * to zero. + */ +AVBufferRef *av_buffer_allocz(size_t size); + +/** + * Always treat the buffer as read-only, even when it has only one + * reference. + */ +#define AV_BUFFER_FLAG_READONLY (1 << 0) + +/** + * Create an AVBuffer from an existing array. + * + * If this function is successful, data is owned by the AVBuffer. The caller may + * only access data through the returned AVBufferRef and references derived from + * it. + * If this function fails, data is left untouched. + * @param data data array + * @param size size of data in bytes + * @param free a callback for freeing this buffer's data + * @param opaque parameter to be got for processing or passed to free + * @param flags a combination of AV_BUFFER_FLAG_* + * + * @return an AVBufferRef referring to data on success, NULL on failure. + */ +AVBufferRef *av_buffer_create(uint8_t *data, size_t size, + void (*free)(void *opaque, uint8_t *data), + void *opaque, int flags); + +/** + * Default free callback, which calls av_free() on the buffer data. + * This function is meant to be passed to av_buffer_create(), not called + * directly. + */ +void av_buffer_default_free(void *opaque, uint8_t *data); + +/** + * Create a new reference to an AVBuffer. + * + * @return a new AVBufferRef referring to the same AVBuffer as buf or NULL on + * failure. + */ +AVBufferRef *av_buffer_ref(const AVBufferRef *buf); + +/** + * Free a given reference and automatically free the buffer if there are no more + * references to it. + * + * @param buf the reference to be freed. The pointer is set to NULL on return. + */ +void av_buffer_unref(AVBufferRef **buf); + +/** + * @return 1 if the caller may write to the data referred to by buf (which is + * true if and only if buf is the only reference to the underlying AVBuffer). + * Return 0 otherwise. + * A positive answer is valid until av_buffer_ref() is called on buf. + */ +int av_buffer_is_writable(const AVBufferRef *buf); + +/** + * @return the opaque parameter set by av_buffer_create. + */ +void *av_buffer_get_opaque(const AVBufferRef *buf); + +int av_buffer_get_ref_count(const AVBufferRef *buf); + +/** + * Create a writable reference from a given buffer reference, avoiding data copy + * if possible. + * + * @param buf buffer reference to make writable. On success, buf is either left + * untouched, or it is unreferenced and a new writable AVBufferRef is + * written in its place. On failure, buf is left untouched. + * @return 0 on success, a negative AVERROR on failure. + */ +int av_buffer_make_writable(AVBufferRef **buf); + +/** + * Reallocate a given buffer. + * + * @param buf a buffer reference to reallocate. On success, buf will be + * unreferenced and a new reference with the required size will be + * written in its place. On failure buf will be left untouched. *buf + * may be NULL, then a new buffer is allocated. + * @param size required new buffer size. + * @return 0 on success, a negative AVERROR on failure. + * + * @note the buffer is actually reallocated with av_realloc() only if it was + * initially allocated through av_buffer_realloc(NULL) and there is only one + * reference to it (i.e. the one passed to this function). In all other cases + * a new buffer is allocated and the data is copied. + */ +int av_buffer_realloc(AVBufferRef **buf, size_t size); + +/** + * Ensure dst refers to the same data as src. + * + * When *dst is already equivalent to src, do nothing. Otherwise unreference dst + * and replace it with a new reference to src. + * + * @param dst Pointer to either a valid buffer reference or NULL. On success, + * this will point to a buffer reference equivalent to src. On + * failure, dst will be left untouched. + * @param src A buffer reference to replace dst with. May be NULL, then this + * function is equivalent to av_buffer_unref(dst). + * @return 0 on success + * AVERROR(ENOMEM) on memory allocation failure. + */ +int av_buffer_replace(AVBufferRef **dst, const AVBufferRef *src); + +/** + * @} + */ + +/** + * @defgroup lavu_bufferpool AVBufferPool + * @ingroup lavu_data + * + * @{ + * AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers. + * + * Frequently allocating and freeing large buffers may be slow. AVBufferPool is + * meant to solve this in cases when the caller needs a set of buffers of the + * same size (the most obvious use case being buffers for raw video or audio + * frames). + * + * At the beginning, the user must call av_buffer_pool_init() to create the + * buffer pool. Then whenever a buffer is needed, call av_buffer_pool_get() to + * get a reference to a new buffer, similar to av_buffer_alloc(). This new + * reference works in all aspects the same way as the one created by + * av_buffer_alloc(). However, when the last reference to this buffer is + * unreferenced, it is returned to the pool instead of being freed and will be + * reused for subsequent av_buffer_pool_get() calls. + * + * When the caller is done with the pool and no longer needs to allocate any new + * buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable. + * Once all the buffers are released, it will automatically be freed. + * + * Allocating and releasing buffers with this API is thread-safe as long as + * either the default alloc callback is used, or the user-supplied one is + * thread-safe. + */ + +/** + * The buffer pool. This structure is opaque and not meant to be accessed + * directly. It is allocated with av_buffer_pool_init() and freed with + * av_buffer_pool_uninit(). + */ +typedef struct AVBufferPool AVBufferPool; + +/** + * Allocate and initialize a buffer pool. + * + * @param size size of each buffer in this pool + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be used + * (av_buffer_alloc()). + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init(size_t size, AVBufferRef* (*alloc)(size_t size)); + +/** + * Allocate and initialize a buffer pool with a more complex allocator. + * + * @param size size of each buffer in this pool + * @param opaque arbitrary user data used by the allocator + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be + * used (av_buffer_alloc()). + * @param pool_free a function that will be called immediately before the pool + * is freed. I.e. after av_buffer_pool_uninit() is called + * by the caller and all the frames are returned to the pool + * and freed. It is intended to uninitialize the user opaque + * data. May be NULL. + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init2(size_t size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, size_t size), + void (*pool_free)(void *opaque)); + +/** + * Mark the pool as being available for freeing. It will actually be freed only + * once all the allocated buffers associated with the pool are released. Thus it + * is safe to call this function while some of the allocated buffers are still + * in use. + * + * @param pool pointer to the pool to be freed. It will be set to NULL. + */ +void av_buffer_pool_uninit(AVBufferPool **pool); + +/** + * Allocate a new AVBuffer, reusing an old buffer from the pool when available. + * This function may be called simultaneously from multiple threads. + * + * @return a reference to the new buffer on success, NULL on error. + */ +AVBufferRef *av_buffer_pool_get(AVBufferPool *pool); + +/** + * Query the original opaque parameter of an allocated buffer in the pool. + * + * @param ref a buffer reference to a buffer returned by av_buffer_pool_get. + * @return the opaque parameter set by the buffer allocator function of the + * buffer pool. + * + * @note the opaque parameter of ref is used by the buffer pool implementation, + * therefore you have to use this function to access the original opaque + * parameter of an allocated buffer. + */ +void *av_buffer_pool_buffer_get_opaque(const AVBufferRef *ref); + +/** + * @} + */ + +#endif /* AVUTIL_BUFFER_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/channel_layout.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/channel_layout.h new file mode 100644 index 0000000000000..4dd6614de9006 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/channel_layout.h @@ -0,0 +1,749 @@ +/* + * Copyright (c) 2006 Michael Niedermayer + * Copyright (c) 2008 Peter Ross + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_CHANNEL_LAYOUT_H +#define AVUTIL_CHANNEL_LAYOUT_H + +#include +#include + +#include "version.h" +#include "attributes.h" + +/** + * @file + * audio channel layout utility functions + */ + +/** + * @addtogroup lavu_audio + * @{ + */ + +enum AVChannel { + ///< Invalid channel index + AV_CHAN_NONE = -1, + AV_CHAN_FRONT_LEFT, + AV_CHAN_FRONT_RIGHT, + AV_CHAN_FRONT_CENTER, + AV_CHAN_LOW_FREQUENCY, + AV_CHAN_BACK_LEFT, + AV_CHAN_BACK_RIGHT, + AV_CHAN_FRONT_LEFT_OF_CENTER, + AV_CHAN_FRONT_RIGHT_OF_CENTER, + AV_CHAN_BACK_CENTER, + AV_CHAN_SIDE_LEFT, + AV_CHAN_SIDE_RIGHT, + AV_CHAN_TOP_CENTER, + AV_CHAN_TOP_FRONT_LEFT, + AV_CHAN_TOP_FRONT_CENTER, + AV_CHAN_TOP_FRONT_RIGHT, + AV_CHAN_TOP_BACK_LEFT, + AV_CHAN_TOP_BACK_CENTER, + AV_CHAN_TOP_BACK_RIGHT, + /** Stereo downmix. */ + AV_CHAN_STEREO_LEFT = 29, + /** See above. */ + AV_CHAN_STEREO_RIGHT, + AV_CHAN_WIDE_LEFT, + AV_CHAN_WIDE_RIGHT, + AV_CHAN_SURROUND_DIRECT_LEFT, + AV_CHAN_SURROUND_DIRECT_RIGHT, + AV_CHAN_LOW_FREQUENCY_2, + AV_CHAN_TOP_SIDE_LEFT, + AV_CHAN_TOP_SIDE_RIGHT, + AV_CHAN_BOTTOM_FRONT_CENTER, + AV_CHAN_BOTTOM_FRONT_LEFT, + AV_CHAN_BOTTOM_FRONT_RIGHT, + + /** Channel is empty can be safely skipped. */ + AV_CHAN_UNUSED = 0x200, + + /** Channel contains data, but its position is unknown. */ + AV_CHAN_UNKNOWN = 0x300, + + /** + * Range of channels between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END represent Ambisonic components using the ACN system. + * + * Given a channel id between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END (inclusive), the ACN index of the channel is + * = - AV_CHAN_AMBISONIC_BASE. + * + * @note these values are only used for AV_CHANNEL_ORDER_CUSTOM channel + * orderings, the AV_CHANNEL_ORDER_AMBISONIC ordering orders the channels + * implicitly by their position in the stream. + */ + AV_CHAN_AMBISONIC_BASE = 0x400, + // leave space for 1024 ids, which correspond to maximum order-32 harmonics, + // which should be enough for the foreseeable use cases + AV_CHAN_AMBISONIC_END = 0x7ff, +}; + +enum AVChannelOrder { + /** + * Only the channel count is specified, without any further information + * about the channel order. + */ + AV_CHANNEL_ORDER_UNSPEC, + /** + * The native channel order, i.e. the channels are in the same order in + * which they are defined in the AVChannel enum. This supports up to 63 + * different channels. + */ + AV_CHANNEL_ORDER_NATIVE, + /** + * The channel order does not correspond to any other predefined order and + * is stored as an explicit map. For example, this could be used to support + * layouts with 64 or more channels, or with empty/skipped (AV_CHAN_SILENCE) + * channels at arbitrary positions. + */ + AV_CHANNEL_ORDER_CUSTOM, + /** + * The audio is represented as the decomposition of the sound field into + * spherical harmonics. Each channel corresponds to a single expansion + * component. Channels are ordered according to ACN (Ambisonic Channel + * Number). + * + * The channel with the index n in the stream contains the spherical + * harmonic of degree l and order m given by + * @code{.unparsed} + * l = floor(sqrt(n)), + * m = n - l * (l + 1). + * @endcode + * + * Conversely given a spherical harmonic of degree l and order m, the + * corresponding channel index n is given by + * @code{.unparsed} + * n = l * (l + 1) + m. + * @endcode + * + * Normalization is assumed to be SN3D (Schmidt Semi-Normalization) + * as defined in AmbiX format $ 2.1. + */ + AV_CHANNEL_ORDER_AMBISONIC, +}; + + +/** + * @defgroup channel_masks Audio channel masks + * + * A channel layout is a 64-bits integer with a bit set for every channel. + * The number of bits set must be equal to the number of channels. + * The value 0 means that the channel layout is not known. + * @note this data structure is not powerful enough to handle channels + * combinations that have the same channel multiple times, such as + * dual-mono. + * + * @{ + */ +#define AV_CH_FRONT_LEFT (1ULL << AV_CHAN_FRONT_LEFT ) +#define AV_CH_FRONT_RIGHT (1ULL << AV_CHAN_FRONT_RIGHT ) +#define AV_CH_FRONT_CENTER (1ULL << AV_CHAN_FRONT_CENTER ) +#define AV_CH_LOW_FREQUENCY (1ULL << AV_CHAN_LOW_FREQUENCY ) +#define AV_CH_BACK_LEFT (1ULL << AV_CHAN_BACK_LEFT ) +#define AV_CH_BACK_RIGHT (1ULL << AV_CHAN_BACK_RIGHT ) +#define AV_CH_FRONT_LEFT_OF_CENTER (1ULL << AV_CHAN_FRONT_LEFT_OF_CENTER ) +#define AV_CH_FRONT_RIGHT_OF_CENTER (1ULL << AV_CHAN_FRONT_RIGHT_OF_CENTER) +#define AV_CH_BACK_CENTER (1ULL << AV_CHAN_BACK_CENTER ) +#define AV_CH_SIDE_LEFT (1ULL << AV_CHAN_SIDE_LEFT ) +#define AV_CH_SIDE_RIGHT (1ULL << AV_CHAN_SIDE_RIGHT ) +#define AV_CH_TOP_CENTER (1ULL << AV_CHAN_TOP_CENTER ) +#define AV_CH_TOP_FRONT_LEFT (1ULL << AV_CHAN_TOP_FRONT_LEFT ) +#define AV_CH_TOP_FRONT_CENTER (1ULL << AV_CHAN_TOP_FRONT_CENTER ) +#define AV_CH_TOP_FRONT_RIGHT (1ULL << AV_CHAN_TOP_FRONT_RIGHT ) +#define AV_CH_TOP_BACK_LEFT (1ULL << AV_CHAN_TOP_BACK_LEFT ) +#define AV_CH_TOP_BACK_CENTER (1ULL << AV_CHAN_TOP_BACK_CENTER ) +#define AV_CH_TOP_BACK_RIGHT (1ULL << AV_CHAN_TOP_BACK_RIGHT ) +#define AV_CH_STEREO_LEFT (1ULL << AV_CHAN_STEREO_LEFT ) +#define AV_CH_STEREO_RIGHT (1ULL << AV_CHAN_STEREO_RIGHT ) +#define AV_CH_WIDE_LEFT (1ULL << AV_CHAN_WIDE_LEFT ) +#define AV_CH_WIDE_RIGHT (1ULL << AV_CHAN_WIDE_RIGHT ) +#define AV_CH_SURROUND_DIRECT_LEFT (1ULL << AV_CHAN_SURROUND_DIRECT_LEFT ) +#define AV_CH_SURROUND_DIRECT_RIGHT (1ULL << AV_CHAN_SURROUND_DIRECT_RIGHT) +#define AV_CH_LOW_FREQUENCY_2 (1ULL << AV_CHAN_LOW_FREQUENCY_2 ) +#define AV_CH_TOP_SIDE_LEFT (1ULL << AV_CHAN_TOP_SIDE_LEFT ) +#define AV_CH_TOP_SIDE_RIGHT (1ULL << AV_CHAN_TOP_SIDE_RIGHT ) +#define AV_CH_BOTTOM_FRONT_CENTER (1ULL << AV_CHAN_BOTTOM_FRONT_CENTER ) +#define AV_CH_BOTTOM_FRONT_LEFT (1ULL << AV_CHAN_BOTTOM_FRONT_LEFT ) +#define AV_CH_BOTTOM_FRONT_RIGHT (1ULL << AV_CHAN_BOTTOM_FRONT_RIGHT ) + +#if FF_API_OLD_CHANNEL_LAYOUT +/** Channel mask value used for AVCodecContext.request_channel_layout + to indicate that the user requests the channel order of the decoder output + to be the native codec channel order. + @deprecated channel order is now indicated in a special field in + AVChannelLayout + */ +#define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL +#endif + +/** + * @} + * @defgroup channel_mask_c Audio channel layouts + * @{ + * */ +#define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT) +#define AV_CH_LAYOUT_2POINT1 (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_3POINT1 (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_4POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_4POINT1 (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_2 (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_QUAD (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_5POINT0_BACK (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT1_BACK (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_6POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT0_FRONT (AV_CH_LAYOUT_2_2|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_HEXAGONAL (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_FRONT (AV_CH_LAYOUT_6POINT0_FRONT|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_7POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT0_FRONT (AV_CH_LAYOUT_5POINT0|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1_WIDE_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_HEXADECAGONAL (AV_CH_LAYOUT_OCTAGONAL|AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT) +#define AV_CH_LAYOUT_22POINT2 (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER|AV_CH_BACK_CENTER|AV_CH_LOW_FREQUENCY_2|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_CENTER|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_SIDE_LEFT|AV_CH_TOP_SIDE_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_BOTTOM_FRONT_CENTER|AV_CH_BOTTOM_FRONT_LEFT|AV_CH_BOTTOM_FRONT_RIGHT) + +enum AVMatrixEncoding { + AV_MATRIX_ENCODING_NONE, + AV_MATRIX_ENCODING_DOLBY, + AV_MATRIX_ENCODING_DPLII, + AV_MATRIX_ENCODING_DPLIIX, + AV_MATRIX_ENCODING_DPLIIZ, + AV_MATRIX_ENCODING_DOLBYEX, + AV_MATRIX_ENCODING_DOLBYHEADPHONE, + AV_MATRIX_ENCODING_NB +}; + +/** + * @} + */ + +/** + * An AVChannelCustom defines a single channel within a custom order layout + * + * Unlike most structures in FFmpeg, sizeof(AVChannelCustom) is a part of the + * public ABI. + * + * No new fields may be added to it without a major version bump. + */ +typedef struct AVChannelCustom { + enum AVChannel id; + char name[16]; + void *opaque; +} AVChannelCustom; + +/** + * An AVChannelLayout holds information about the channel layout of audio data. + * + * A channel layout here is defined as a set of channels ordered in a specific + * way (unless the channel order is AV_CHANNEL_ORDER_UNSPEC, in which case an + * AVChannelLayout carries only the channel count). + * + * Unlike most structures in Libav, sizeof(AVChannelLayout) is a part of the + * public ABI and may be used by the caller. E.g. it may be allocated on stack + * or embedded in caller-defined structs. + * + * AVChannelLayout can be initialized as follows: + * - default initialization with {0}, followed by setting all used fields + * correctly; + * - by assigning one of the predefined AV_CHANNEL_LAYOUT_* initializers; + * - with a constructor function, such as av_channel_layout_default(), + * av_channel_layout_from_mask() or av_channel_layout_from_string(). + * + * The channel layout must be unitialized with av_channel_layout_uninit() + * + * Copying an AVChannelLayout via assigning is forbidden, + * av_channel_layout_copy() must be used instead (and its return value should + * be checked) + * + * No new fields may be added to it without a major version bump, except for + * new elements of the union fitting in sizeof(uint64_t). + */ +typedef struct AVChannelLayout { + /** + * Channel order used in this layout. + * This is a mandatory field. + */ + enum AVChannelOrder order; + + /** + * Number of channels in this layout. Mandatory field. + */ + int nb_channels; + + /** + * Details about which channels are present in this layout. + * For AV_CHANNEL_ORDER_UNSPEC, this field is undefined and must not be + * used. + */ + union { + /** + * This member must be used for AV_CHANNEL_ORDER_NATIVE, and may be used + * for AV_CHANNEL_ORDER_AMBISONIC to signal non-diegetic channels. + * It is a bitmask, where the position of each set bit means that the + * AVChannel with the corresponding value is present. + * + * I.e. when (mask & (1 << AV_CHAN_FOO)) is non-zero, then AV_CHAN_FOO + * is present in the layout. Otherwise it is not present. + * + * @note when a channel layout using a bitmask is constructed or + * modified manually (i.e. not using any of the av_channel_layout_* + * functions), the code doing it must ensure that the number of set bits + * is equal to nb_channels. + */ + uint64_t mask; + /** + * This member must be used when the channel order is + * AV_CHANNEL_ORDER_CUSTOM. It is a nb_channels-sized array, with each + * element signalling the presence of the AVChannel with the + * corresponding value in map[i].id. + * + * I.e. when map[i].id is equal to AV_CHAN_FOO, then AV_CH_FOO is the + * i-th channel in the audio data. + * + * When map[i].id is in the range between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END (inclusive), the channel contains an ambisonic + * component with ACN index (as defined above) + * n = map[i].id - AV_CHAN_AMBISONIC_BASE. + * + * map[i].name may be filled with a 0-terminated string, in which case + * it will be used for the purpose of identifying the channel with the + * convenience functions below. Otherise it must be zeroed. + */ + AVChannelCustom *map; + } u; + + /** + * For some private data of the user. + */ + void *opaque; +} AVChannelLayout; + +#define AV_CHANNEL_LAYOUT_MASK(nb, m) \ + { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = (nb), .u = { .mask = (m) }} + +#define AV_CHANNEL_LAYOUT_MONO AV_CHANNEL_LAYOUT_MASK(1, AV_CH_LAYOUT_MONO) +#define AV_CHANNEL_LAYOUT_STEREO AV_CHANNEL_LAYOUT_MASK(2, AV_CH_LAYOUT_STEREO) +#define AV_CHANNEL_LAYOUT_2POINT1 AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_2POINT1) +#define AV_CHANNEL_LAYOUT_2_1 AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_2_1) +#define AV_CHANNEL_LAYOUT_SURROUND AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_SURROUND) +#define AV_CHANNEL_LAYOUT_3POINT1 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_3POINT1) +#define AV_CHANNEL_LAYOUT_4POINT0 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_4POINT0) +#define AV_CHANNEL_LAYOUT_4POINT1 AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_4POINT1) +#define AV_CHANNEL_LAYOUT_2_2 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_2_2) +#define AV_CHANNEL_LAYOUT_QUAD AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_QUAD) +#define AV_CHANNEL_LAYOUT_5POINT0 AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_5POINT0) +#define AV_CHANNEL_LAYOUT_5POINT1 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_5POINT1) +#define AV_CHANNEL_LAYOUT_5POINT0_BACK AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_5POINT0_BACK) +#define AV_CHANNEL_LAYOUT_5POINT1_BACK AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_5POINT1_BACK) +#define AV_CHANNEL_LAYOUT_6POINT0 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_6POINT0) +#define AV_CHANNEL_LAYOUT_6POINT0_FRONT AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_6POINT0_FRONT) +#define AV_CHANNEL_LAYOUT_HEXAGONAL AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_HEXAGONAL) +#define AV_CHANNEL_LAYOUT_6POINT1 AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1) +#define AV_CHANNEL_LAYOUT_6POINT1_BACK AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1_BACK) +#define AV_CHANNEL_LAYOUT_6POINT1_FRONT AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1_FRONT) +#define AV_CHANNEL_LAYOUT_7POINT0 AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_7POINT0) +#define AV_CHANNEL_LAYOUT_7POINT0_FRONT AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_7POINT0_FRONT) +#define AV_CHANNEL_LAYOUT_7POINT1 AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1) +#define AV_CHANNEL_LAYOUT_7POINT1_WIDE AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1_WIDE) +#define AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1_WIDE_BACK) +#define AV_CHANNEL_LAYOUT_OCTAGONAL AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_OCTAGONAL) +#define AV_CHANNEL_LAYOUT_HEXADECAGONAL AV_CHANNEL_LAYOUT_MASK(16, AV_CH_LAYOUT_HEXADECAGONAL) +#define AV_CHANNEL_LAYOUT_STEREO_DOWNMIX AV_CHANNEL_LAYOUT_MASK(2, AV_CH_LAYOUT_STEREO_DOWNMIX) +#define AV_CHANNEL_LAYOUT_22POINT2 AV_CHANNEL_LAYOUT_MASK(24, AV_CH_LAYOUT_22POINT2) +#define AV_CHANNEL_LAYOUT_AMBISONIC_FIRST_ORDER \ + { .order = AV_CHANNEL_ORDER_AMBISONIC, .nb_channels = 4, .u = { .mask = 0 }} + +struct AVBPrint; + +#if FF_API_OLD_CHANNEL_LAYOUT +/** + * Return a channel layout id that matches name, or 0 if no match is found. + * + * name can be one or several of the following notations, + * separated by '+' or '|': + * - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0, + * 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix); + * - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC, + * SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR); + * - a number of channels, in decimal, followed by 'c', yielding + * the default channel layout for that number of channels (@see + * av_get_default_channel_layout); + * - a channel layout mask, in hexadecimal starting with "0x" (see the + * AV_CH_* macros). + * + * Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7" + * + * @deprecated use av_channel_layout_from_string() + */ +attribute_deprecated +uint64_t av_get_channel_layout(const char *name); + +/** + * Return a channel layout and the number of channels based on the specified name. + * + * This function is similar to (@see av_get_channel_layout), but can also parse + * unknown channel layout specifications. + * + * @param[in] name channel layout specification string + * @param[out] channel_layout parsed channel layout (0 if unknown) + * @param[out] nb_channels number of channels + * + * @return 0 on success, AVERROR(EINVAL) if the parsing fails. + * @deprecated use av_channel_layout_from_string() + */ +attribute_deprecated +int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels); + +/** + * Return a description of a channel layout. + * If nb_channels is <= 0, it is guessed from the channel_layout. + * + * @param buf put here the string containing the channel layout + * @param buf_size size in bytes of the buffer + * @deprecated use av_channel_layout_describe() + */ +attribute_deprecated +void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout); + +/** + * Append a description of a channel layout to a bprint buffer. + * @deprecated use av_channel_layout_describe() + */ +attribute_deprecated +void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout); + +/** + * Return the number of channels in the channel layout. + * @deprecated use AVChannelLayout.nb_channels + */ +attribute_deprecated +int av_get_channel_layout_nb_channels(uint64_t channel_layout); + +/** + * Return default channel layout for a given number of channels. + * + * @deprecated use av_channel_layout_default() + */ +attribute_deprecated +int64_t av_get_default_channel_layout(int nb_channels); + +/** + * Get the index of a channel in channel_layout. + * + * @param channel a channel layout describing exactly one channel which must be + * present in channel_layout. + * + * @return index of channel in channel_layout on success, a negative AVERROR + * on error. + * + * @deprecated use av_channel_layout_index_from_channel() + */ +attribute_deprecated +int av_get_channel_layout_channel_index(uint64_t channel_layout, + uint64_t channel); + +/** + * Get the channel with the given index in channel_layout. + * @deprecated use av_channel_layout_channel_from_index() + */ +attribute_deprecated +uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index); + +/** + * Get the name of a given channel. + * + * @return channel name on success, NULL on error. + * + * @deprecated use av_channel_name() + */ +attribute_deprecated +const char *av_get_channel_name(uint64_t channel); + +/** + * Get the description of a given channel. + * + * @param channel a channel layout with a single channel + * @return channel description on success, NULL on error + * @deprecated use av_channel_description() + */ +attribute_deprecated +const char *av_get_channel_description(uint64_t channel); + +/** + * Get the value and name of a standard channel layout. + * + * @param[in] index index in an internal list, starting at 0 + * @param[out] layout channel layout mask + * @param[out] name name of the layout + * @return 0 if the layout exists, + * <0 if index is beyond the limits + * @deprecated use av_channel_layout_standard() + */ +attribute_deprecated +int av_get_standard_channel_layout(unsigned index, uint64_t *layout, + const char **name); +#endif + +/** + * Get a human readable string in an abbreviated form describing a given channel. + * This is the inverse function of @ref av_channel_from_string(). + * + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel); + +/** + * bprint variant of av_channel_name(). + * + * @note the string will be appended to the bprint buffer. + */ +void av_channel_name_bprint(struct AVBPrint *bp, enum AVChannel channel_id); + +/** + * Get a human readable string describing a given channel. + * + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel); + +/** + * bprint variant of av_channel_description(). + * + * @note the string will be appended to the bprint buffer. + */ +void av_channel_description_bprint(struct AVBPrint *bp, enum AVChannel channel_id); + +/** + * This is the inverse function of @ref av_channel_name(). + * + * @return the channel with the given name + * AV_CHAN_NONE when name does not identify a known channel + */ +enum AVChannel av_channel_from_string(const char *name); + +/** + * Initialize a native channel layout from a bitmask indicating which channels + * are present. + * + * @param channel_layout the layout structure to be initialized + * @param mask bitmask describing the channel layout + * + * @return 0 on success + * AVERROR(EINVAL) for invalid mask values + */ +int av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask); + +/** + * Initialize a channel layout from a given string description. + * The input string can be represented by: + * - the formal channel layout name (returned by av_channel_layout_describe()) + * - single or multiple channel names (returned by av_channel_name(), eg. "FL", + * or concatenated with "+", each optionally containing a custom name after + * a "@", eg. "FL@Left+FR@Right+LFE") + * - a decimal or hexadecimal value of a native channel layout (eg. "4" or "0x4") + * - the number of channels with default layout (eg. "4c") + * - the number of unordered channels (eg. "4C" or "4 channels") + * - the ambisonic order followed by optional non-diegetic channels (eg. + * "ambisonic 2+stereo") + * + * @param channel_layout input channel layout + * @param str string describing the channel layout + * @return 0 channel layout was detected, AVERROR_INVALIDATATA otherwise + */ +int av_channel_layout_from_string(AVChannelLayout *channel_layout, + const char *str); + +/** + * Get the default channel layout for a given number of channels. + * + * @param channel_layout the layout structure to be initialized + * @param nb_channels number of channels + */ +void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels); + +/** + * Iterate over all standard channel layouts. + * + * @param opaque a pointer where libavutil will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the standard channel layout or NULL when the iteration is + * finished + */ +const AVChannelLayout *av_channel_layout_standard(void **opaque); + +/** + * Free any allocated data in the channel layout and reset the channel + * count to 0. + * + * @param channel_layout the layout structure to be uninitialized + */ +void av_channel_layout_uninit(AVChannelLayout *channel_layout); + +/** + * Make a copy of a channel layout. This differs from just assigning src to dst + * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM. + * + * @note the destination channel_layout will be always uninitialized before copy. + * + * @param dst destination channel layout + * @param src source channel layout + * @return 0 on success, a negative AVERROR on error. + */ +int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src); + +/** + * Get a human-readable string describing the channel layout properties. + * The string will be in the same format that is accepted by + * @ref av_channel_layout_from_string(), allowing to rebuild the same + * channel layout, except for opaque pointers. + * + * @param channel_layout channel layout to be described + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_layout_describe(const AVChannelLayout *channel_layout, + char *buf, size_t buf_size); + +/** + * bprint variant of av_channel_layout_describe(). + * + * @note the string will be appended to the bprint buffer. + * @return 0 on success, or a negative AVERROR value on failure. + */ +int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout, + struct AVBPrint *bp); + +/** + * Get the channel with the given index in a channel layout. + * + * @param channel_layout input channel layout + * @return channel with the index idx in channel_layout on success or + * AV_CHAN_NONE on failure (if idx is not valid or the channel order is + * unspecified) + */ +enum AVChannel +av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx); + +/** + * Get the index of a given channel in a channel layout. In case multiple + * channels are found, only the first match will be returned. + * + * @param channel_layout input channel layout + * @return index of channel in channel_layout on success or a negative number if + * channel is not present in channel_layout. + */ +int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, + enum AVChannel channel); + +/** + * Get the index in a channel layout of a channel described by the given string. + * In case multiple channels are found, only the first match will be returned. + * + * This function accepts channel names in the same format as + * @ref av_channel_from_string(). + * + * @param channel_layout input channel layout + * @return a channel index described by the given string, or a negative AVERROR + * value. + */ +int av_channel_layout_index_from_string(const AVChannelLayout *channel_layout, + const char *name); + +/** + * Get a channel described by the given string. + * + * This function accepts channel names in the same format as + * @ref av_channel_from_string(). + * + * @param channel_layout input channel layout + * @return a channel described by the given string in channel_layout on success + * or AV_CHAN_NONE on failure (if the string is not valid or the channel + * order is unspecified) + */ +enum AVChannel +av_channel_layout_channel_from_string(const AVChannelLayout *channel_layout, + const char *name); + +/** + * Find out what channels from a given set are present in a channel layout, + * without regard for their positions. + * + * @param channel_layout input channel layout + * @param mask a combination of AV_CH_* representing a set of channels + * @return a bitfield representing all the channels from mask that are present + * in channel_layout + */ +uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout, + uint64_t mask); + +/** + * Check whether a channel layout is valid, i.e. can possibly describe audio + * data. + * + * @param channel_layout input channel layout + * @return 1 if channel_layout is valid, 0 otherwise. + */ +int av_channel_layout_check(const AVChannelLayout *channel_layout); + +/** + * Check whether two channel layouts are semantically the same, i.e. the same + * channels are present on the same positions in both. + * + * If one of the channel layouts is AV_CHANNEL_ORDER_UNSPEC, while the other is + * not, they are considered to be unequal. If both are AV_CHANNEL_ORDER_UNSPEC, + * they are considered equal iff the channel counts are the same in both. + * + * @param chl input channel layout + * @param chl1 input channel layout + * @return 0 if chl and chl1 are equal, 1 if they are not equal. A negative + * AVERROR code if one or both are invalid. + */ +int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_CHANNEL_LAYOUT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/common.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/common.h new file mode 100644 index 0000000000000..fd1404be6cf3e --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/common.h @@ -0,0 +1,578 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * common internal and external API header + */ + +#ifndef AVUTIL_COMMON_H +#define AVUTIL_COMMON_H + +#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) && !defined(UINT64_C) +#error missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "macros.h" + +//rounded division & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>=0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +/* Fast a/(1<=0 and b>=0 */ +#define AV_CEIL_RSHIFT(a,b) (!av_builtin_constant_p(b) ? -((-(a)) >> (b)) \ + : ((a) + (1<<(b)) - 1) >> (b)) +/* Backwards compat. */ +#define FF_CEIL_RSHIFT AV_CEIL_RSHIFT + +#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b)) +#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b)) + +/** + * Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they + * are not representable as absolute values of their type. This is the same + * as with *abs() + * @see FFNABS() + */ +#define FFABS(a) ((a) >= 0 ? (a) : (-(a))) +#define FFSIGN(a) ((a) > 0 ? 1 : -1) + +/** + * Negative Absolute value. + * this works for all integers of all types. + * As with many macros, this evaluates its argument twice, it thus must not have + * a sideeffect, that is FFNABS(x++) has undefined behavior. + */ +#define FFNABS(a) ((a) <= 0 ? (a) : (-(a))) + +/** + * Unsigned Absolute value. + * This takes the absolute value of a signed int and returns it as a unsigned. + * This also works with INT_MIN which would otherwise not be representable + * As with many macros, this evaluates its argument twice. + */ +#define FFABSU(a) ((a) <= 0 ? -(unsigned)(a) : (unsigned)(a)) +#define FFABS64U(a) ((a) <= 0 ? -(uint64_t)(a) : (uint64_t)(a)) + +/* misc math functions */ + +#ifdef HAVE_AV_CONFIG_H +# include "config.h" +# include "intmath.h" +#endif + +#ifndef av_ceil_log2 +# define av_ceil_log2 av_ceil_log2_c +#endif +#ifndef av_clip +# define av_clip av_clip_c +#endif +#ifndef av_clip64 +# define av_clip64 av_clip64_c +#endif +#ifndef av_clip_uint8 +# define av_clip_uint8 av_clip_uint8_c +#endif +#ifndef av_clip_int8 +# define av_clip_int8 av_clip_int8_c +#endif +#ifndef av_clip_uint16 +# define av_clip_uint16 av_clip_uint16_c +#endif +#ifndef av_clip_int16 +# define av_clip_int16 av_clip_int16_c +#endif +#ifndef av_clipl_int32 +# define av_clipl_int32 av_clipl_int32_c +#endif +#ifndef av_clip_intp2 +# define av_clip_intp2 av_clip_intp2_c +#endif +#ifndef av_clip_uintp2 +# define av_clip_uintp2 av_clip_uintp2_c +#endif +#ifndef av_mod_uintp2 +# define av_mod_uintp2 av_mod_uintp2_c +#endif +#ifndef av_sat_add32 +# define av_sat_add32 av_sat_add32_c +#endif +#ifndef av_sat_dadd32 +# define av_sat_dadd32 av_sat_dadd32_c +#endif +#ifndef av_sat_sub32 +# define av_sat_sub32 av_sat_sub32_c +#endif +#ifndef av_sat_dsub32 +# define av_sat_dsub32 av_sat_dsub32_c +#endif +#ifndef av_sat_add64 +# define av_sat_add64 av_sat_add64_c +#endif +#ifndef av_sat_sub64 +# define av_sat_sub64 av_sat_sub64_c +#endif +#ifndef av_clipf +# define av_clipf av_clipf_c +#endif +#ifndef av_clipd +# define av_clipd av_clipd_c +#endif +#ifndef av_popcount +# define av_popcount av_popcount_c +#endif +#ifndef av_popcount64 +# define av_popcount64 av_popcount64_c +#endif +#ifndef av_parity +# define av_parity av_parity_c +#endif + +#ifndef av_log2 +av_const int av_log2(unsigned v); +#endif + +#ifndef av_log2_16bit +av_const int av_log2_16bit(unsigned v); +#endif + +/** + * Clip a signed integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int av_clip_c(int a, int amin, int amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed 64bit integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, int64_t amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed integer value into the 0-255 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint8_t av_clip_uint8_c(int a) +{ + if (a&(~0xFF)) return (~a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -128,127 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int8_t av_clip_int8_c(int a) +{ + if ((a+0x80U) & ~0xFF) return (a>>31) ^ 0x7F; + else return a; +} + +/** + * Clip a signed integer value into the 0-65535 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint16_t av_clip_uint16_c(int a) +{ + if (a&(~0xFFFF)) return (~a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -32768,32767 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int16_t av_clip_int16_c(int a) +{ + if ((a+0x8000U) & ~0xFFFF) return (a>>31) ^ 0x7FFF; + else return a; +} + +/** + * Clip a signed 64-bit integer value into the -2147483648,2147483647 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a) +{ + if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (int32_t)((a>>63) ^ 0x7FFFFFFF); + else return (int32_t)a; +} + +/** + * Clip a signed integer into the -(2^p),(2^p-1) range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const int av_clip_intp2_c(int a, int p) +{ + if (((unsigned)a + (1 << p)) & ~((2 << p) - 1)) + return (a >> 31) ^ ((1 << p) - 1); + else + return a; +} + +/** + * Clip a signed integer to an unsigned power of two range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p) +{ + if (a & ~((1<> 31 & ((1<= 0) + return INT64_MAX ^ (b >> 63); + return s; +#endif +} + +/** + * Subtract two signed 64-bit values with saturation. + * + * @param a one value + * @param b another value + * @return difference with signed saturation + */ +static av_always_inline int64_t av_sat_sub64_c(int64_t a, int64_t b) { +#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_sub_overflow) + int64_t tmp; + return !__builtin_sub_overflow(a, b, &tmp) ? tmp : (tmp < 0 ? INT64_MAX : INT64_MIN); +#else + if (b <= 0 && a >= INT64_MAX + b) + return INT64_MAX; + if (b >= 0 && a <= INT64_MIN + b) + return INT64_MIN; + return a - b; +#endif +} + +/** + * Clip a float value into the amin-amax range. + * If a is nan or -inf amin will be returned. + * If a is +inf amax will be returned. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const float av_clipf_c(float a, float amin, float amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + return FFMIN(FFMAX(a, amin), amax); +} + +/** + * Clip a double value into the amin-amax range. + * If a is nan or -inf amin will be returned. + * If a is +inf amax will be returned. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const double av_clipd_c(double a, double amin, double amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + return FFMIN(FFMAX(a, amin), amax); +} + +/** Compute ceil(log2(x)). + * @param x value used to compute ceil(log2(x)) + * @return computed ceiling of log2(x) + */ +static av_always_inline av_const int av_ceil_log2_c(int x) +{ + return av_log2((x - 1U) << 1); +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount_c(uint32_t x) +{ + x -= (x >> 1) & 0x55555555; + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x += x >> 8; + return (x + (x >> 16)) & 0x3F; +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount64_c(uint64_t x) +{ + return av_popcount((uint32_t)x) + av_popcount((uint32_t)(x >> 32)); +} + +static av_always_inline av_const int av_parity_c(uint32_t v) +{ + return av_popcount(v) & 1; +} + +/** + * Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_BYTE Expression reading one byte from the input. + * Evaluated up to 7 times (4 for the currently + * assigned Unicode range). With a memory buffer + * input, this could be *ptr++, or if you want to make sure + * that *ptr stops at the end of a NULL terminated string then + * *ptr ? *ptr++ : 0 + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + * + * @warning ERROR should not contain a loop control statement which + * could interact with the internal while loop, and should force an + * exit from the macro code (e.g. through a goto or a return) in order + * to prevent undefined results. + */ +#define GET_UTF8(val, GET_BYTE, ERROR)\ + val= (GET_BYTE);\ + {\ + uint32_t top = (val & 128) >> 1;\ + if ((val & 0xc0) == 0x80 || val >= 0xFE)\ + {ERROR}\ + while (val & top) {\ + unsigned int tmp = (GET_BYTE) - 128;\ + if(tmp>>6)\ + {ERROR}\ + val= (val<<6) + tmp;\ + top <<= 5;\ + }\ + val &= (top << 1) - 1;\ + } + +/** + * Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_16BIT Expression returning two bytes of UTF-16 data converted + * to native byte order. Evaluated one or two times. + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + */ +#define GET_UTF16(val, GET_16BIT, ERROR)\ + val = (GET_16BIT);\ + {\ + unsigned int hi = val - 0xD800;\ + if (hi < 0x800) {\ + val = (GET_16BIT) - 0xDC00;\ + if (val > 0x3FFU || hi > 0x3FFU)\ + {ERROR}\ + val += (hi<<10) + 0x10000;\ + }\ + }\ + +/** + * @def PUT_UTF8(val, tmp, PUT_BYTE) + * Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-8. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint8_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_BYTE. + * @param PUT_BYTE writes the converted UTF-8 bytes to any proper destination. + * It could be a function or a statement, and uses tmp as the input byte. + * For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be + * executed up to 4 times for values in the valid UTF-8 range and up to + * 7 times in the general case, depending on the length of the converted + * Unicode character. + */ +#define PUT_UTF8(val, tmp, PUT_BYTE)\ + {\ + int bytes, shift;\ + uint32_t in = val;\ + if (in < 0x80) {\ + tmp = in;\ + PUT_BYTE\ + } else {\ + bytes = (av_log2(in) + 4) / 5;\ + shift = (bytes - 1) * 6;\ + tmp = (256 - (256 >> bytes)) | (in >> shift);\ + PUT_BYTE\ + while (shift >= 6) {\ + shift -= 6;\ + tmp = 0x80 | ((in >> shift) & 0x3f);\ + PUT_BYTE\ + }\ + }\ + } + +/** + * @def PUT_UTF16(val, tmp, PUT_16BIT) + * Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-16. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint16_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_16BIT. + * @param PUT_16BIT writes the converted UTF-16 data to any proper destination + * in desired endianness. It could be a function or a statement, and uses tmp + * as the input byte. For example, PUT_BYTE could be "*output++ = tmp;" + * PUT_BYTE will be executed 1 or 2 times depending on input character. + */ +#define PUT_UTF16(val, tmp, PUT_16BIT)\ + {\ + uint32_t in = val;\ + if (in < 0x10000) {\ + tmp = in;\ + PUT_16BIT\ + } else {\ + tmp = 0xD800 | ((in - 0x10000) >> 10);\ + PUT_16BIT\ + tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\ + PUT_16BIT\ + }\ + }\ + + + +#include "mem.h" + +#ifdef HAVE_AV_CONFIG_H +# include "internal.h" +#endif /* HAVE_AV_CONFIG_H */ + +#endif /* AVUTIL_COMMON_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/dict.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/dict.h new file mode 100644 index 0000000000000..0d1afc6c64abc --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/dict.h @@ -0,0 +1,198 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Public dictionary API. + * @deprecated + * AVDictionary is provided for compatibility with libav. It is both in + * implementation as well as API inefficient. It does not scale and is + * extremely slow with large dictionaries. + * It is recommended that new code uses our tree container from tree.c/h + * where applicable, which uses AVL trees to achieve O(log n) performance. + */ + +#ifndef AVUTIL_DICT_H +#define AVUTIL_DICT_H + +#include + +/** + * @addtogroup lavu_dict AVDictionary + * @ingroup lavu_data + * + * @brief Simple key:value store + * + * @{ + * Dictionaries are used for storing key:value pairs. To create + * an AVDictionary, simply pass an address of a NULL pointer to + * av_dict_set(). NULL can be used as an empty dictionary wherever + * a pointer to an AVDictionary is required. + * Use av_dict_get() to retrieve an entry or iterate over all + * entries and finally av_dict_free() to free the dictionary + * and all its contents. + * + @code + AVDictionary *d = NULL; // "create" an empty dictionary + AVDictionaryEntry *t = NULL; + + av_dict_set(&d, "foo", "bar", 0); // add an entry + + char *k = av_strdup("key"); // if your strings are already allocated, + char *v = av_strdup("value"); // you can avoid copying them like this + av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); + + while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) { + <....> // iterate over all entries in d + } + av_dict_free(&d); + @endcode + */ + +#define AV_DICT_MATCH_CASE 1 /**< Only get an entry with exact-case key match. Only relevant in av_dict_get(). */ +#define AV_DICT_IGNORE_SUFFIX 2 /**< Return first entry in a dictionary whose first part corresponds to the search key, + ignoring the suffix of the found key string. Only relevant in av_dict_get(). */ +#define AV_DICT_DONT_STRDUP_KEY 4 /**< Take ownership of a key that's been + allocated with av_malloc() or another memory allocation function. */ +#define AV_DICT_DONT_STRDUP_VAL 8 /**< Take ownership of a value that's been + allocated with av_malloc() or another memory allocation function. */ +#define AV_DICT_DONT_OVERWRITE 16 ///< Don't overwrite existing entries. +#define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no + delimiter is added, the strings are simply concatenated. */ +#define AV_DICT_MULTIKEY 64 /**< Allow to store several equal keys in the dictionary */ + +typedef struct AVDictionaryEntry { + char *key; + char *value; +} AVDictionaryEntry; + +typedef struct AVDictionary AVDictionary; + +/** + * Get a dictionary entry with matching key. + * + * The returned entry key or value must not be changed, or it will + * cause undefined behavior. + * + * To iterate through all the dictionary entries, you can set the matching key + * to the null string "" and set the AV_DICT_IGNORE_SUFFIX flag. + * + * @param prev Set to the previous matching element to find the next. + * If set to NULL the first matching element is returned. + * @param key matching key + * @param flags a collection of AV_DICT_* flags controlling how the entry is retrieved + * @return found entry or NULL in case no matching entry was found in the dictionary + */ +AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key, + const AVDictionaryEntry *prev, int flags); + +/** + * Get number of entries in dictionary. + * + * @param m dictionary + * @return number of entries in dictionary + */ +int av_dict_count(const AVDictionary *m); + +/** + * Set the given entry in *pm, overwriting an existing entry. + * + * Note: If AV_DICT_DONT_STRDUP_KEY or AV_DICT_DONT_STRDUP_VAL is set, + * these arguments will be freed on error. + * + * Warning: Adding a new entry to a dictionary invalidates all existing entries + * previously returned with av_dict_get. + * + * @param pm pointer to a pointer to a dictionary struct. If *pm is NULL + * a dictionary struct is allocated and put in *pm. + * @param key entry key to add to *pm (will either be av_strduped or added as a new key depending on flags) + * @param value entry value to add to *pm (will be av_strduped or added as a new key depending on flags). + * Passing a NULL value will cause an existing entry to be deleted. + * @return >= 0 on success otherwise an error code <0 + */ +int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags); + +/** + * Convenience wrapper for av_dict_set that converts the value to a string + * and stores it. + * + * Note: If AV_DICT_DONT_STRDUP_KEY is set, key will be freed on error. + */ +int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags); + +/** + * Parse the key/value pairs list and add the parsed entries to a dictionary. + * + * In case of failure, all the successfully set entries are stored in + * *pm. You may need to manually free the created dictionary. + * + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other + * @param flags flags to use when adding to dictionary. + * AV_DICT_DONT_STRDUP_KEY and AV_DICT_DONT_STRDUP_VAL + * are ignored since the key/value tokens will always + * be duplicated. + * @return 0 on success, negative AVERROR code on failure + */ +int av_dict_parse_string(AVDictionary **pm, const char *str, + const char *key_val_sep, const char *pairs_sep, + int flags); + +/** + * Copy entries from one AVDictionary struct into another. + * @param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL, + * this function will allocate a struct for you and put it in *dst + * @param src pointer to source AVDictionary struct + * @param flags flags to use when setting entries in *dst + * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag + * @return 0 on success, negative AVERROR code on failure. If dst was allocated + * by this function, callers should free the associated memory. + */ +int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags); + +/** + * Free all the memory allocated for an AVDictionary struct + * and all keys and values. + */ +void av_dict_free(AVDictionary **m); + +/** + * Get dictionary entries as a string. + * + * Create a string containing dictionary's entries. + * Such string may be passed back to av_dict_parse_string(). + * @note String is escaped with backslashes ('\'). + * + * @param[in] m dictionary + * @param[out] buffer Pointer to buffer that will be allocated with string containg entries. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep character used to separate key from value + * @param[in] pairs_sep character used to separate two pairs from each other + * @return >= 0 on success, negative on error + * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same. + */ +int av_dict_get_string(const AVDictionary *m, char **buffer, + const char key_val_sep, const char pairs_sep); + +/** + * @} + */ + +#endif /* AVUTIL_DICT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/error.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/error.h new file mode 100644 index 0000000000000..0d3269aa6da13 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/error.h @@ -0,0 +1,128 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * error code definitions + */ + +#ifndef AVUTIL_ERROR_H +#define AVUTIL_ERROR_H + +#include +#include + +#include "macros.h" + +/** + * @addtogroup lavu_error + * + * @{ + */ + + +/* error handling */ +#if EDOM > 0 +#define AVERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions. +#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value. +#else +/* Some platforms have E* and errno already negated. */ +#define AVERROR(e) (e) +#define AVUNERROR(e) (e) +#endif + +#define FFERRTAG(a, b, c, d) (-(int)MKTAG(a, b, c, d)) + +#define AVERROR_BSF_NOT_FOUND FFERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found +#define AVERROR_BUG FFERRTAG( 'B','U','G','!') ///< Internal bug, also see AVERROR_BUG2 +#define AVERROR_BUFFER_TOO_SMALL FFERRTAG( 'B','U','F','S') ///< Buffer too small +#define AVERROR_DECODER_NOT_FOUND FFERRTAG(0xF8,'D','E','C') ///< Decoder not found +#define AVERROR_DEMUXER_NOT_FOUND FFERRTAG(0xF8,'D','E','M') ///< Demuxer not found +#define AVERROR_ENCODER_NOT_FOUND FFERRTAG(0xF8,'E','N','C') ///< Encoder not found +#define AVERROR_EOF FFERRTAG( 'E','O','F',' ') ///< End of file +#define AVERROR_EXIT FFERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted +#define AVERROR_EXTERNAL FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library +#define AVERROR_FILTER_NOT_FOUND FFERRTAG(0xF8,'F','I','L') ///< Filter not found +#define AVERROR_INVALIDDATA FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input +#define AVERROR_MUXER_NOT_FOUND FFERRTAG(0xF8,'M','U','X') ///< Muxer not found +#define AVERROR_OPTION_NOT_FOUND FFERRTAG(0xF8,'O','P','T') ///< Option not found +#define AVERROR_PATCHWELCOME FFERRTAG( 'P','A','W','E') ///< Not yet implemented in FFmpeg, patches welcome +#define AVERROR_PROTOCOL_NOT_FOUND FFERRTAG(0xF8,'P','R','O') ///< Protocol not found + +#define AVERROR_STREAM_NOT_FOUND FFERRTAG(0xF8,'S','T','R') ///< Stream not found +/** + * This is semantically identical to AVERROR_BUG + * it has been introduced in Libav after our AVERROR_BUG and with a modified value. + */ +#define AVERROR_BUG2 FFERRTAG( 'B','U','G',' ') +#define AVERROR_UNKNOWN FFERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library +#define AVERROR_EXPERIMENTAL (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it. +#define AVERROR_INPUT_CHANGED (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED) +#define AVERROR_OUTPUT_CHANGED (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED) +/* HTTP & RTSP errors */ +#define AVERROR_HTTP_BAD_REQUEST FFERRTAG(0xF8,'4','0','0') +#define AVERROR_HTTP_UNAUTHORIZED FFERRTAG(0xF8,'4','0','1') +#define AVERROR_HTTP_FORBIDDEN FFERRTAG(0xF8,'4','0','3') +#define AVERROR_HTTP_NOT_FOUND FFERRTAG(0xF8,'4','0','4') +#define AVERROR_HTTP_OTHER_4XX FFERRTAG(0xF8,'4','X','X') +#define AVERROR_HTTP_SERVER_ERROR FFERRTAG(0xF8,'5','X','X') + +#define AV_ERROR_MAX_STRING_SIZE 64 + +/** + * Put a description of the AVERROR code errnum in errbuf. + * In case of failure the global variable errno is set to indicate the + * error. Even in case of failure av_strerror() will print a generic + * error message indicating the errnum provided to errbuf. + * + * @param errnum error code to describe + * @param errbuf buffer to which description is written + * @param errbuf_size the size in bytes of errbuf + * @return 0 on success, a negative value if a description for errnum + * cannot be found + */ +int av_strerror(int errnum, char *errbuf, size_t errbuf_size); + +/** + * Fill the provided buffer with a string containing an error string + * corresponding to the AVERROR code errnum. + * + * @param errbuf a buffer + * @param errbuf_size size in bytes of errbuf + * @param errnum error code to describe + * @return the buffer in input, filled with the error description + * @see av_strerror() + */ +static inline char *av_make_error_string(char *errbuf, size_t errbuf_size, int errnum) +{ + av_strerror(errnum, errbuf, errbuf_size); + return errbuf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_err2str(errnum) \ + av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum) + +/** + * @} + */ + +#endif /* AVUTIL_ERROR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/frame.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/frame.h new file mode 100644 index 0000000000000..33fac2054cf10 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/frame.h @@ -0,0 +1,947 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_frame + * reference-counted frame API + */ + +#ifndef AVUTIL_FRAME_H +#define AVUTIL_FRAME_H + +#include +#include + +#include "avutil.h" +#include "buffer.h" +#include "channel_layout.h" +#include "dict.h" +#include "rational.h" +#include "samplefmt.h" +#include "pixfmt.h" +#include "version.h" + + +/** + * @defgroup lavu_frame AVFrame + * @ingroup lavu_data + * + * @{ + * AVFrame is an abstraction for reference-counted raw multimedia data. + */ + +enum AVFrameSideDataType { + /** + * The data is the AVPanScan struct defined in libavcodec. + */ + AV_FRAME_DATA_PANSCAN, + /** + * ATSC A53 Part 4 Closed Captions. + * A53 CC bitstream is stored as uint8_t in AVFrameSideData.data. + * The number of bytes of CC data is AVFrameSideData.size. + */ + AV_FRAME_DATA_A53_CC, + /** + * Stereoscopic 3d metadata. + * The data is the AVStereo3D struct defined in libavutil/stereo3d.h. + */ + AV_FRAME_DATA_STEREO3D, + /** + * The data is the AVMatrixEncoding enum defined in libavutil/channel_layout.h. + */ + AV_FRAME_DATA_MATRIXENCODING, + /** + * Metadata relevant to a downmix procedure. + * The data is the AVDownmixInfo struct defined in libavutil/downmix_info.h. + */ + AV_FRAME_DATA_DOWNMIX_INFO, + /** + * ReplayGain information in the form of the AVReplayGain struct. + */ + AV_FRAME_DATA_REPLAYGAIN, + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the frame for correct + * presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_FRAME_DATA_DISPLAYMATRIX, + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_FRAME_DATA_AFD, + /** + * Motion vectors exported by some codecs (on demand through the export_mvs + * flag set in the libavcodec AVCodecContext flags2 option). + * The data is the AVMotionVector struct defined in + * libavutil/motion_vector.h. + */ + AV_FRAME_DATA_MOTION_VECTORS, + /** + * Recommmends skipping the specified number of samples. This is exported + * only if the "skip_manual" AVOption is set in libavcodec. + * This has the same format as AV_PKT_DATA_SKIP_SAMPLES. + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_FRAME_DATA_SKIP_SAMPLES, + /** + * This side data must be associated with an audio frame and corresponds to + * enum AVAudioServiceType defined in avcodec.h. + */ + AV_FRAME_DATA_AUDIO_SERVICE_TYPE, + /** + * Mastering display metadata associated with a video frame. The payload is + * an AVMasteringDisplayMetadata type and contains information about the + * mastering display color volume. + */ + AV_FRAME_DATA_MASTERING_DISPLAY_METADATA, + /** + * The GOP timecode in 25 bit timecode format. Data format is 64-bit integer. + * This is set on the first frame of a GOP that has a temporal reference of 0. + */ + AV_FRAME_DATA_GOP_TIMECODE, + + /** + * The data represents the AVSphericalMapping structure defined in + * libavutil/spherical.h. + */ + AV_FRAME_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This payload contains data in + * the form of the AVContentLightMetadata struct. + */ + AV_FRAME_DATA_CONTENT_LIGHT_LEVEL, + + /** + * The data contains an ICC profile as an opaque octet buffer following the + * format described by ISO 15076-1 with an optional name defined in the + * metadata key entry "name". + */ + AV_FRAME_DATA_ICC_PROFILE, + + /** + * Timecode which conforms to SMPTE ST 12-1. The data is an array of 4 uint32_t + * where the first uint32_t describes how many (1-3) of the other timecodes are used. + * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.h. + */ + AV_FRAME_DATA_S12M_TIMECODE, + + /** + * HDR dynamic metadata associated with a video frame. The payload is + * an AVDynamicHDRPlus type and contains information for color + * volume transform - application 4 of SMPTE 2094-40:2016 standard. + */ + AV_FRAME_DATA_DYNAMIC_HDR_PLUS, + + /** + * Regions Of Interest, the data is an array of AVRegionOfInterest type, the number of + * array element is implied by AVFrameSideData.size / AVRegionOfInterest.self_size. + */ + AV_FRAME_DATA_REGIONS_OF_INTEREST, + + /** + * Encoding parameters for a video frame, as described by AVVideoEncParams. + */ + AV_FRAME_DATA_VIDEO_ENC_PARAMS, + + /** + * User data unregistered metadata associated with a video frame. + * This is the H.26[45] UDU SEI message, and shouldn't be used for any other purpose + * The data is stored as uint8_t in AVFrameSideData.data which is 16 bytes of + * uuid_iso_iec_11578 followed by AVFrameSideData.size - 16 bytes of user_data_payload_byte. + */ + AV_FRAME_DATA_SEI_UNREGISTERED, + + /** + * Film grain parameters for a frame, described by AVFilmGrainParams. + * Must be present for every frame which should have film grain applied. + */ + AV_FRAME_DATA_FILM_GRAIN_PARAMS, + + /** + * Bounding boxes for object detection and classification, + * as described by AVDetectionBBoxHeader. + */ + AV_FRAME_DATA_DETECTION_BBOXES, + + /** + * Dolby Vision RPU raw data, suitable for passing to x265 + * or other libraries. Array of uint8_t, with NAL emulation + * bytes intact. + */ + AV_FRAME_DATA_DOVI_RPU_BUFFER, + + /** + * Parsed Dolby Vision metadata, suitable for passing to a software + * implementation. The payload is the AVDOVIMetadata struct defined in + * libavutil/dovi_meta.h. + */ + AV_FRAME_DATA_DOVI_METADATA, + + /** + * HDR Vivid dynamic metadata associated with a video frame. The payload is + * an AVDynamicHDRVivid type and contains information for color + * volume transform - CUVA 005.1-2021. + */ + AV_FRAME_DATA_DYNAMIC_HDR_VIVID, +}; + +enum AVActiveFormatDescription { + AV_AFD_SAME = 8, + AV_AFD_4_3 = 9, + AV_AFD_16_9 = 10, + AV_AFD_14_9 = 11, + AV_AFD_4_3_SP_14_9 = 13, + AV_AFD_16_9_SP_14_9 = 14, + AV_AFD_SP_4_3 = 15, +}; + + +/** + * Structure to hold side data for an AVFrame. + * + * sizeof(AVFrameSideData) is not a part of the public ABI, so new fields may be added + * to the end with a minor bump. + */ +typedef struct AVFrameSideData { + enum AVFrameSideDataType type; + uint8_t *data; + size_t size; + AVDictionary *metadata; + AVBufferRef *buf; +} AVFrameSideData; + +/** + * Structure describing a single Region Of Interest. + * + * When multiple regions are defined in a single side-data block, they + * should be ordered from most to least important - some encoders are only + * capable of supporting a limited number of distinct regions, so will have + * to truncate the list. + * + * When overlapping regions are defined, the first region containing a given + * area of the frame applies. + */ +typedef struct AVRegionOfInterest { + /** + * Must be set to the size of this data structure (that is, + * sizeof(AVRegionOfInterest)). + */ + uint32_t self_size; + /** + * Distance in pixels from the top edge of the frame to the top and + * bottom edges and from the left edge of the frame to the left and + * right edges of the rectangle defining this region of interest. + * + * The constraints on a region are encoder dependent, so the region + * actually affected may be slightly larger for alignment or other + * reasons. + */ + int top; + int bottom; + int left; + int right; + /** + * Quantisation offset. + * + * Must be in the range -1 to +1. A value of zero indicates no quality + * change. A negative value asks for better quality (less quantisation), + * while a positive value asks for worse quality (greater quantisation). + * + * The range is calibrated so that the extreme values indicate the + * largest possible offset - if the rest of the frame is encoded with the + * worst possible quality, an offset of -1 indicates that this region + * should be encoded with the best possible quality anyway. Intermediate + * values are then interpolated in some codec-dependent way. + * + * For example, in 10-bit H.264 the quantisation parameter varies between + * -12 and 51. A typical qoffset value of -1/10 therefore indicates that + * this region should be encoded with a QP around one-tenth of the full + * range better than the rest of the frame. So, if most of the frame + * were to be encoded with a QP of around 30, this region would get a QP + * of around 24 (an offset of approximately -1/10 * (51 - -12) = -6.3). + * An extreme value of -1 would indicate that this region should be + * encoded with the best possible quality regardless of the treatment of + * the rest of the frame - that is, should be encoded at a QP of -12. + */ + AVRational qoffset; +} AVRegionOfInterest; + +/** + * This structure describes decoded (raw) audio or video data. + * + * AVFrame must be allocated using av_frame_alloc(). Note that this only + * allocates the AVFrame itself, the buffers for the data must be managed + * through other means (see below). + * AVFrame must be freed with av_frame_free(). + * + * AVFrame is typically allocated once and then reused multiple times to hold + * different data (e.g. a single AVFrame to hold frames received from a + * decoder). In such a case, av_frame_unref() will free any references held by + * the frame and reset it to its original clean state before it + * is reused again. + * + * The data described by an AVFrame is usually reference counted through the + * AVBuffer API. The underlying buffer references are stored in AVFrame.buf / + * AVFrame.extended_buf. An AVFrame is considered to be reference counted if at + * least one reference is set, i.e. if AVFrame.buf[0] != NULL. In such a case, + * every single data plane must be contained in one of the buffers in + * AVFrame.buf or AVFrame.extended_buf. + * There may be a single buffer for all the data, or one separate buffer for + * each plane, or anything in between. + * + * sizeof(AVFrame) is not a part of the public ABI, so new fields may be added + * to the end with a minor bump. + * + * Fields can be accessed through AVOptions, the name string used, matches the + * C structure field name for fields accessible through AVOptions. The AVClass + * for AVFrame can be obtained from avcodec_get_frame_class() + */ +typedef struct AVFrame { +#define AV_NUM_DATA_POINTERS 8 + /** + * pointer to the picture/channel planes. + * This might be different from the first allocated byte. For video, + * it could even point to the end of the image data. + * + * All pointers in data and extended_data must point into one of the + * AVBufferRef in buf or extended_buf. + * + * Some decoders access areas outside 0,0 - width,height, please + * see avcodec_align_dimensions2(). Some filters and swscale can read + * up to 16 bytes beyond the planes, if these filters are to be used, + * then 16 extra bytes must be allocated. + * + * NOTE: Pointers not needed by the format MUST be set to NULL. + * + * @attention In case of video, the data[] pointers can point to the + * end of image data in order to reverse line order, when used in + * combination with negative values in the linesize[] array. + */ + uint8_t *data[AV_NUM_DATA_POINTERS]; + + /** + * For video, a positive or negative value, which is typically indicating + * the size in bytes of each picture line, but it can also be: + * - the negative byte size of lines for vertical flipping + * (with data[n] pointing to the end of the data + * - a positive or negative multiple of the byte size as for accessing + * even and odd fields of a frame (possibly flipped) + * + * For audio, only linesize[0] may be set. For planar audio, each channel + * plane must be the same size. + * + * For video the linesizes should be multiples of the CPUs alignment + * preference, this is 16 or 32 for modern desktop CPUs. + * Some code requires such alignment other code can be slower without + * correct alignment, for yet other it makes no difference. + * + * @note The linesize may be larger than the size of usable data -- there + * may be extra padding present for performance reasons. + * + * @attention In case of video, line size values can be negative to achieve + * a vertically inverted iteration over image lines. + */ + int linesize[AV_NUM_DATA_POINTERS]; + + /** + * pointers to the data planes/channels. + * + * For video, this should simply point to data[]. + * + * For planar audio, each channel has a separate data pointer, and + * linesize[0] contains the size of each channel buffer. + * For packed audio, there is just one data pointer, and linesize[0] + * contains the total size of the buffer for all channels. + * + * Note: Both data and extended_data should always be set in a valid frame, + * but for planar audio with more channels that can fit in data, + * extended_data must be used in order to access all channels. + */ + uint8_t **extended_data; + + /** + * @name Video dimensions + * Video frames only. The coded dimensions (in pixels) of the video frame, + * i.e. the size of the rectangle that contains some well-defined values. + * + * @note The part of the frame intended for display/presentation is further + * restricted by the @ref cropping "Cropping rectangle". + * @{ + */ + int width, height; + /** + * @} + */ + + /** + * number of audio samples (per channel) described by this frame + */ + int nb_samples; + + /** + * format of the frame, -1 if unknown or unset + * Values correspond to enum AVPixelFormat for video frames, + * enum AVSampleFormat for audio) + */ + int format; + + /** + * 1 -> keyframe, 0-> not + */ + int key_frame; + + /** + * Picture type of the frame. + */ + enum AVPictureType pict_type; + + /** + * Sample aspect ratio for the video frame, 0/1 if unknown/unspecified. + */ + AVRational sample_aspect_ratio; + + /** + * Presentation timestamp in time_base units (time when frame should be shown to user). + */ + int64_t pts; + + /** + * DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used) + * This is also the Presentation time of this AVFrame calculated from + * only AVPacket.dts values without pts values. + */ + int64_t pkt_dts; + + /** + * Time base for the timestamps in this frame. + * In the future, this field may be set on frames output by decoders or + * filters, but its value will be by default ignored on input to encoders + * or filters. + */ + AVRational time_base; + + /** + * picture number in bitstream order + */ + int coded_picture_number; + /** + * picture number in display order + */ + int display_picture_number; + + /** + * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) + */ + int quality; + + /** + * for some private data of the user + */ + void *opaque; + + /** + * When decoding, this signals how much the picture must be delayed. + * extra_delay = repeat_pict / (2*fps) + */ + int repeat_pict; + + /** + * The content of the picture is interlaced. + */ + int interlaced_frame; + + /** + * If the content is interlaced, is top field displayed first. + */ + int top_field_first; + + /** + * Tell user application that palette has changed from previous frame. + */ + int palette_has_changed; + + /** + * reordered opaque 64 bits (generally an integer or a double precision float + * PTS but can be anything). + * The user sets AVCodecContext.reordered_opaque to represent the input at + * that time, + * the decoder reorders values as needed and sets AVFrame.reordered_opaque + * to exactly one of the values provided by the user through AVCodecContext.reordered_opaque + */ + int64_t reordered_opaque; + + /** + * Sample rate of the audio data. + */ + int sample_rate; + +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * Channel layout of the audio data. + * @deprecated use ch_layout instead + */ + attribute_deprecated + uint64_t channel_layout; +#endif + + /** + * AVBuffer references backing the data for this frame. All the pointers in + * data and extended_data must point inside one of the buffers in buf or + * extended_buf. This array must be filled contiguously -- if buf[i] is + * non-NULL then buf[j] must also be non-NULL for all j < i. + * + * There may be at most one AVBuffer per data plane, so for video this array + * always contains all the references. For planar audio with more than + * AV_NUM_DATA_POINTERS channels, there may be more buffers than can fit in + * this array. Then the extra AVBufferRef pointers are stored in the + * extended_buf array. + */ + AVBufferRef *buf[AV_NUM_DATA_POINTERS]; + + /** + * For planar audio which requires more than AV_NUM_DATA_POINTERS + * AVBufferRef pointers, this array will hold all the references which + * cannot fit into AVFrame.buf. + * + * Note that this is different from AVFrame.extended_data, which always + * contains all the pointers. This array only contains the extra pointers, + * which cannot fit into AVFrame.buf. + * + * This array is always allocated using av_malloc() by whoever constructs + * the frame. It is freed in av_frame_unref(). + */ + AVBufferRef **extended_buf; + /** + * Number of elements in extended_buf. + */ + int nb_extended_buf; + + AVFrameSideData **side_data; + int nb_side_data; + +/** + * @defgroup lavu_frame_flags AV_FRAME_FLAGS + * @ingroup lavu_frame + * Flags describing additional frame properties. + * + * @{ + */ + +/** + * The frame data may be corrupted, e.g. due to decoding errors. + */ +#define AV_FRAME_FLAG_CORRUPT (1 << 0) +/** + * A flag to mark the frames which need to be decoded, but shouldn't be output. + */ +#define AV_FRAME_FLAG_DISCARD (1 << 2) +/** + * @} + */ + + /** + * Frame flags, a combination of @ref lavu_frame_flags + */ + int flags; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorRange color_range; + + enum AVColorPrimaries color_primaries; + + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + enum AVChromaLocation chroma_location; + + /** + * frame timestamp estimated using various heuristics, in stream time base + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int64_t best_effort_timestamp; + + /** + * reordered pos from the last AVPacket that has been input into the decoder + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_pos; + + /** + * duration of the corresponding packet, expressed in + * AVStream->time_base units, 0 if unknown. + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_duration; + + /** + * metadata. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVDictionary *metadata; + + /** + * decode error flags of the frame, set to a combination of + * FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there + * were errors during the decoding. + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int decode_error_flags; +#define FF_DECODE_ERROR_INVALID_BITSTREAM 1 +#define FF_DECODE_ERROR_MISSING_REFERENCE 2 +#define FF_DECODE_ERROR_CONCEALMENT_ACTIVE 4 +#define FF_DECODE_ERROR_DECODE_SLICES 8 + +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * number of audio channels, only used for audio. + * - encoding: unused + * - decoding: Read by user. + * @deprecated use ch_layout instead + */ + attribute_deprecated + int channels; +#endif + + /** + * size of the corresponding packet containing the compressed + * frame. + * It is set to a negative value if unknown. + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int pkt_size; + + /** + * For hwaccel-format frames, this should be a reference to the + * AVHWFramesContext describing the frame. + */ + AVBufferRef *hw_frames_ctx; + + /** + * AVBufferRef for free use by the API user. FFmpeg will never check the + * contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when + * the frame is unreferenced. av_frame_copy_props() calls create a new + * reference with av_buffer_ref() for the target frame's opaque_ref field. + * + * This is unrelated to the opaque field, although it serves a similar + * purpose. + */ + AVBufferRef *opaque_ref; + + /** + * @anchor cropping + * @name Cropping + * Video frames only. The number of pixels to discard from the the + * top/bottom/left/right border of the frame to obtain the sub-rectangle of + * the frame intended for presentation. + * @{ + */ + size_t crop_top; + size_t crop_bottom; + size_t crop_left; + size_t crop_right; + /** + * @} + */ + + /** + * AVBufferRef for internal use by a single libav* library. + * Must not be used to transfer data between libraries. + * Has to be NULL when ownership of the frame leaves the respective library. + * + * Code outside the FFmpeg libs should never check or change the contents of the buffer ref. + * + * FFmpeg calls av_buffer_unref() on it when the frame is unreferenced. + * av_frame_copy_props() calls create a new reference with av_buffer_ref() + * for the target frame's private_ref field. + */ + AVBufferRef *private_ref; + + /** + * Channel layout of the audio data. + */ + AVChannelLayout ch_layout; +} AVFrame; + + +#if FF_API_COLORSPACE_NAME +/** + * Get the name of a colorspace. + * @return a static string identifying the colorspace; can be NULL. + * @deprecated use av_color_space_name() + */ +attribute_deprecated +const char *av_get_colorspace_name(enum AVColorSpace val); +#endif +/** + * Allocate an AVFrame and set its fields to default values. The resulting + * struct must be freed using av_frame_free(). + * + * @return An AVFrame filled with default values or NULL on failure. + * + * @note this only allocates the AVFrame itself, not the data buffers. Those + * must be allocated through other means, e.g. with av_frame_get_buffer() or + * manually. + */ +AVFrame *av_frame_alloc(void); + +/** + * Free the frame and any dynamically allocated objects in it, + * e.g. extended_data. If the frame is reference counted, it will be + * unreferenced first. + * + * @param frame frame to be freed. The pointer will be set to NULL. + */ +void av_frame_free(AVFrame **frame); + +/** + * Set up a new reference to the data described by the source frame. + * + * Copy frame properties from src to dst and create a new reference for each + * AVBufferRef from src. + * + * If src is not reference counted, new buffers are allocated and the data is + * copied. + * + * @warning: dst MUST have been either unreferenced with av_frame_unref(dst), + * or newly allocated with av_frame_alloc() before calling this + * function, or undefined behavior will occur. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_frame_ref(AVFrame *dst, const AVFrame *src); + +/** + * Create a new frame that references the same data as src. + * + * This is a shortcut for av_frame_alloc()+av_frame_ref(). + * + * @return newly created AVFrame on success, NULL on error. + */ +AVFrame *av_frame_clone(const AVFrame *src); + +/** + * Unreference all the buffers referenced by frame and reset the frame fields. + */ +void av_frame_unref(AVFrame *frame); + +/** + * Move everything contained in src to dst and reset src. + * + * @warning: dst is not unreferenced, but directly overwritten without reading + * or deallocating its contents. Call av_frame_unref(dst) manually + * before calling this function to ensure that no memory is leaked. + */ +void av_frame_move_ref(AVFrame *dst, AVFrame *src); + +/** + * Allocate new buffer(s) for audio or video data. + * + * The following fields must be set on frame before calling this function: + * - format (pixel format for video, sample format for audio) + * - width and height for video + * - nb_samples and ch_layout for audio + * + * This function will fill AVFrame.data and AVFrame.buf arrays and, if + * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf. + * For planar formats, one buffer will be allocated for each plane. + * + * @warning: if frame already has been allocated, calling this function will + * leak memory. In addition, undefined behavior can occur in certain + * cases. + * + * @param frame frame in which to store the new buffers. + * @param align Required buffer size alignment. If equal to 0, alignment will be + * chosen automatically for the current CPU. It is highly + * recommended to pass 0 here unless you know what you are doing. + * + * @return 0 on success, a negative AVERROR on error. + */ +int av_frame_get_buffer(AVFrame *frame, int align); + +/** + * Check if the frame data is writable. + * + * @return A positive value if the frame data is writable (which is true if and + * only if each of the underlying buffers has only one reference, namely the one + * stored in this frame). Return 0 otherwise. + * + * If 1 is returned the answer is valid until av_buffer_ref() is called on any + * of the underlying AVBufferRefs (e.g. through av_frame_ref() or directly). + * + * @see av_frame_make_writable(), av_buffer_is_writable() + */ +int av_frame_is_writable(AVFrame *frame); + +/** + * Ensure that the frame data is writable, avoiding data copy if possible. + * + * Do nothing if the frame is writable, allocate new buffers and copy the data + * if it is not. + * + * @return 0 on success, a negative AVERROR on error. + * + * @see av_frame_is_writable(), av_buffer_is_writable(), + * av_buffer_make_writable() + */ +int av_frame_make_writable(AVFrame *frame); + +/** + * Copy the frame data from src to dst. + * + * This function does not allocate anything, dst must be already initialized and + * allocated with the same parameters as src. + * + * This function only copies the frame data (i.e. the contents of the data / + * extended data arrays), not any other properties. + * + * @return >= 0 on success, a negative AVERROR on error. + */ +int av_frame_copy(AVFrame *dst, const AVFrame *src); + +/** + * Copy only "metadata" fields from src to dst. + * + * Metadata for the purpose of this function are those fields that do not affect + * the data layout in the buffers. E.g. pts, sample rate (for audio) or sample + * aspect ratio (for video), but not width/height or channel layout. + * Side data is also copied. + */ +int av_frame_copy_props(AVFrame *dst, const AVFrame *src); + +/** + * Get the buffer reference a given data plane is stored in. + * + * @param plane index of the data plane of interest in frame->extended_data. + * + * @return the buffer reference that contains the plane or NULL if the input + * frame is not valid. + */ +AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane); + +/** + * Add a new side data to a frame. + * + * @param frame a frame to which the side data should be added + * @param type type of the added side data + * @param size size of the side data + * + * @return newly added side data on success, NULL on error + */ +AVFrameSideData *av_frame_new_side_data(AVFrame *frame, + enum AVFrameSideDataType type, + size_t size); + +/** + * Add a new side data to a frame from an existing AVBufferRef + * + * @param frame a frame to which the side data should be added + * @param type the type of the added side data + * @param buf an AVBufferRef to add as side data. The ownership of + * the reference is transferred to the frame. + * + * @return newly added side data on success, NULL on error. On failure + * the frame is unchanged and the AVBufferRef remains owned by + * the caller. + */ +AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame, + enum AVFrameSideDataType type, + AVBufferRef *buf); + +/** + * @return a pointer to the side data of a given type on success, NULL if there + * is no side data with such type in this frame. + */ +AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, + enum AVFrameSideDataType type); + +/** + * Remove and free all side data instances of the given type. + */ +void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type); + + +/** + * Flags for frame cropping. + */ +enum { + /** + * Apply the maximum possible cropping, even if it requires setting the + * AVFrame.data[] entries to unaligned pointers. Passing unaligned data + * to FFmpeg API is generally not allowed, and causes undefined behavior + * (such as crashes). You can pass unaligned data only to FFmpeg APIs that + * are explicitly documented to accept it. Use this flag only if you + * absolutely know what you are doing. + */ + AV_FRAME_CROP_UNALIGNED = 1 << 0, +}; + +/** + * Crop the given video AVFrame according to its crop_left/crop_top/crop_right/ + * crop_bottom fields. If cropping is successful, the function will adjust the + * data pointers and the width/height fields, and set the crop fields to 0. + * + * In all cases, the cropping boundaries will be rounded to the inherent + * alignment of the pixel format. In some cases, such as for opaque hwaccel + * formats, the left/top cropping is ignored. The crop fields are set to 0 even + * if the cropping was rounded or ignored. + * + * @param frame the frame which should be cropped + * @param flags Some combination of AV_FRAME_CROP_* flags, or 0. + * + * @return >= 0 on success, a negative AVERROR on error. If the cropping fields + * were invalid, AVERROR(ERANGE) is returned, and nothing is changed. + */ +int av_frame_apply_cropping(AVFrame *frame, int flags); + +/** + * @return a string identifying the side data type + */ +const char *av_frame_side_data_name(enum AVFrameSideDataType type); + +/** + * @} + */ + +#endif /* AVUTIL_FRAME_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/hwcontext.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/hwcontext.h new file mode 100644 index 0000000000000..c18b7e1e8b316 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/hwcontext.h @@ -0,0 +1,609 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_H +#define AVUTIL_HWCONTEXT_H + +#include "buffer.h" +#include "frame.h" +#include "log.h" +#include "pixfmt.h" + +enum AVHWDeviceType { + AV_HWDEVICE_TYPE_NONE, + AV_HWDEVICE_TYPE_VDPAU, + AV_HWDEVICE_TYPE_CUDA, + AV_HWDEVICE_TYPE_VAAPI, + AV_HWDEVICE_TYPE_DXVA2, + AV_HWDEVICE_TYPE_QSV, + AV_HWDEVICE_TYPE_VIDEOTOOLBOX, + AV_HWDEVICE_TYPE_D3D11VA, + AV_HWDEVICE_TYPE_DRM, + AV_HWDEVICE_TYPE_OPENCL, + AV_HWDEVICE_TYPE_MEDIACODEC, + AV_HWDEVICE_TYPE_VULKAN, +}; + +typedef struct AVHWDeviceInternal AVHWDeviceInternal; + +/** + * This struct aggregates all the (hardware/vendor-specific) "high-level" state, + * i.e. state that is not tied to a concrete processing configuration. + * E.g., in an API that supports hardware-accelerated encoding and decoding, + * this struct will (if possible) wrap the state that is common to both encoding + * and decoding and from which specific instances of encoders or decoders can be + * derived. + * + * This struct is reference-counted with the AVBuffer mechanism. The + * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field + * points to the actual AVHWDeviceContext. Further objects derived from + * AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with + * specific properties) will hold an internal reference to it. After all the + * references are released, the AVHWDeviceContext itself will be freed, + * optionally invoking a user-specified callback for uninitializing the hardware + * state. + */ +typedef struct AVHWDeviceContext { + /** + * A class for logging. Set by av_hwdevice_ctx_alloc(). + */ + const AVClass *av_class; + + /** + * Private data used internally by libavutil. Must not be accessed in any + * way by the caller. + */ + AVHWDeviceInternal *internal; + + /** + * This field identifies the underlying API used for hardware access. + * + * This field is set when this struct is allocated and never changed + * afterwards. + */ + enum AVHWDeviceType type; + + /** + * The format-specific data, allocated and freed by libavutil along with + * this context. + * + * Should be cast by the user to the format-specific context defined in the + * corresponding header (hwcontext_*.h) and filled as described in the + * documentation before calling av_hwdevice_ctx_init(). + * + * After calling av_hwdevice_ctx_init() this struct should not be modified + * by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwdevice_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + * + * @note when other objects (e.g an AVHWFramesContext) are derived from this + * struct, this callback will be invoked after all such child objects + * are fully uninitialized and their respective destructors invoked. + */ + void (*free)(struct AVHWDeviceContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; +} AVHWDeviceContext; + +typedef struct AVHWFramesInternal AVHWFramesInternal; + +/** + * This struct describes a set or pool of "hardware" frames (i.e. those with + * data not located in normal system memory). All the frames in the pool are + * assumed to be allocated in the same way and interchangeable. + * + * This struct is reference-counted with the AVBuffer mechanism and tied to a + * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor + * yields a reference, whose data field points to the actual AVHWFramesContext + * struct. + */ +typedef struct AVHWFramesContext { + /** + * A class for logging. + */ + const AVClass *av_class; + + /** + * Private data used internally by libavutil. Must not be accessed in any + * way by the caller. + */ + AVHWFramesInternal *internal; + + /** + * A reference to the parent AVHWDeviceContext. This reference is owned and + * managed by the enclosing AVHWFramesContext, but the caller may derive + * additional references from it. + */ + AVBufferRef *device_ref; + + /** + * The parent AVHWDeviceContext. This is simply a pointer to + * device_ref->data provided for convenience. + * + * Set by libavutil in av_hwframe_ctx_init(). + */ + AVHWDeviceContext *device_ctx; + + /** + * The format-specific data, allocated and freed automatically along with + * this context. + * + * Should be cast by the user to the format-specific context defined in the + * corresponding header (hwframe_*.h) and filled as described in the + * documentation before calling av_hwframe_ctx_init(). + * + * After any frames using this context are created, the contents of this + * struct should not be modified by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + */ + void (*free)(struct AVHWFramesContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; + + /** + * A pool from which the frames are allocated by av_hwframe_get_buffer(). + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * The buffers returned by calling av_buffer_pool_get() on this pool must + * have the properties described in the documentation in the corresponding hw + * type's header (hwcontext_*.h). The pool will be freed strictly before + * this struct's free() callback is invoked. + * + * This field may be NULL, then libavutil will attempt to allocate a pool + * internally. Note that certain device types enforce pools allocated at + * fixed size (frame count), which cannot be extended dynamically. In such a + * case, initial_pool_size must be set appropriately. + */ + AVBufferPool *pool; + + /** + * Initial size of the frame pool. If a device type does not support + * dynamically resizing the pool, then this is also the maximum pool size. + * + * May be set by the caller before calling av_hwframe_ctx_init(). Must be + * set if pool is NULL and the device type does not support dynamic pools. + */ + int initial_pool_size; + + /** + * The pixel format identifying the underlying HW surface type. + * + * Must be a hwaccel format, i.e. the corresponding descriptor must have the + * AV_PIX_FMT_FLAG_HWACCEL flag set. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + enum AVPixelFormat format; + + /** + * The pixel format identifying the actual data layout of the hardware + * frames. + * + * Must be set by the caller before calling av_hwframe_ctx_init(). + * + * @note when the underlying API does not provide the exact data layout, but + * only the colorspace/bit depth, this field should be set to the fully + * planar version of that format (e.g. for 8-bit 420 YUV it should be + * AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else). + */ + enum AVPixelFormat sw_format; + + /** + * The allocated dimensions of the frames in this pool. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + int width, height; +} AVHWFramesContext; + +/** + * Look up an AVHWDeviceType by name. + * + * @param name String name of the device type (case-insensitive). + * @return The type from enum AVHWDeviceType, or AV_HWDEVICE_TYPE_NONE if + * not found. + */ +enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name); + +/** Get the string name of an AVHWDeviceType. + * + * @param type Type from enum AVHWDeviceType. + * @return Pointer to a static string containing the name, or NULL if the type + * is not valid. + */ +const char *av_hwdevice_get_type_name(enum AVHWDeviceType type); + +/** + * Iterate over supported device types. + * + * @param type AV_HWDEVICE_TYPE_NONE initially, then the previous type + * returned by this function in subsequent iterations. + * @return The next usable device type from enum AVHWDeviceType, or + * AV_HWDEVICE_TYPE_NONE if there are no more. + */ +enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev); + +/** + * Allocate an AVHWDeviceContext for a given hardware type. + * + * @param type the type of the hardware device to allocate. + * @return a reference to the newly created AVHWDeviceContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type); + +/** + * Finalize the device context before use. This function must be called after + * the context is filled with all the required information and before it is + * used in any way. + * + * @param ref a reference to the AVHWDeviceContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwdevice_ctx_init(AVBufferRef *ref); + +/** + * Open a device of the specified type and create an AVHWDeviceContext for it. + * + * This is a convenience function intended to cover the simple cases. Callers + * who need to fine-tune device creation/management should open the device + * manually and then wrap it in an AVHWDeviceContext using + * av_hwdevice_ctx_alloc()/av_hwdevice_ctx_init(). + * + * The returned context is already initialized and ready for use, the caller + * should not call av_hwdevice_ctx_init() on it. The user_opaque/free fields of + * the created AVHWDeviceContext are set by this function and should not be + * touched by the caller. + * + * @param device_ctx On success, a reference to the newly-created device context + * will be written here. The reference is owned by the caller + * and must be released with av_buffer_unref() when no longer + * needed. On failure, NULL will be written to this pointer. + * @param type The type of the device to create. + * @param device A type-specific string identifying the device to open. + * @param opts A dictionary of additional (type-specific) options to use in + * opening the device. The dictionary remains owned by the caller. + * @param flags currently unused + * + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type, + const char *device, AVDictionary *opts, int flags); + +/** + * Create a new device of the specified type from an existing device. + * + * If the source device is a device of the target type or was originally + * derived from such a device (possibly through one or more intermediate + * devices of other types), then this will return a reference to the + * existing device of the same type as is requested. + * + * Otherwise, it will attempt to derive a new device from the given source + * device. If direct derivation to the new type is not implemented, it will + * attempt the same derivation from each ancestor of the source device in + * turn looking for an implemented derivation method. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, int flags); + +/** + * Create a new device of the specified type from an existing device. + * + * This function performs the same action as av_hwdevice_ctx_create_derived, + * however, it is able to set options for the new device to be derived. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param options Options for the new device to create, same format as in + * av_hwdevice_ctx_create. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, + AVDictionary *options, int flags); + +/** + * Allocate an AVHWFramesContext tied to a given device context. + * + * @param device_ctx a reference to a AVHWDeviceContext. This function will make + * a new reference for internal use, the one passed to the + * function remains owned by the caller. + * @return a reference to the newly created AVHWFramesContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx); + +/** + * Finalize the context before use. This function must be called after the + * context is filled with all the required information and before it is attached + * to any frames. + * + * @param ref a reference to the AVHWFramesContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_ctx_init(AVBufferRef *ref); + +/** + * Allocate a new frame attached to the given AVHWFramesContext. + * + * @param hwframe_ctx a reference to an AVHWFramesContext + * @param frame an empty (freshly allocated or unreffed) frame to be filled with + * newly allocated buffers. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags); + +/** + * Copy data to or from a hw surface. At least one of dst/src must have an + * AVHWFramesContext attached. + * + * If src has an AVHWFramesContext attached, then the format of dst (if set) + * must use one of the formats returned by av_hwframe_transfer_get_formats(src, + * AV_HWFRAME_TRANSFER_DIRECTION_FROM). + * If dst has an AVHWFramesContext attached, then the format of src must use one + * of the formats returned by av_hwframe_transfer_get_formats(dst, + * AV_HWFRAME_TRANSFER_DIRECTION_TO) + * + * dst may be "clean" (i.e. with data/buf pointers unset), in which case the + * data buffers will be allocated by this function using av_frame_get_buffer(). + * If dst->format is set, then this format will be used, otherwise (when + * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen. + * + * The two frames must have matching allocated dimensions (i.e. equal to + * AVHWFramesContext.width/height), since not all device types support + * transferring a sub-rectangle of the whole surface. The display dimensions + * (i.e. AVFrame.width/height) may be smaller than the allocated dimensions, but + * also have to be equal for both frames. When the display dimensions are + * smaller than the allocated dimensions, the content of the padding in the + * destination frame is unspecified. + * + * @param dst the destination frame. dst is not touched on failure. + * @param src the source frame. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR error code on failure. + */ +int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags); + +enum AVHWFrameTransferDirection { + /** + * Transfer the data from the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_FROM, + + /** + * Transfer the data to the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_TO, +}; + +/** + * Get a list of possible source or target formats usable in + * av_hwframe_transfer_data(). + * + * @param hwframe_ctx the frame context to obtain the information for + * @param dir the direction of the transfer + * @param formats the pointer to the output format list will be written here. + * The list is terminated with AV_PIX_FMT_NONE and must be freed + * by the caller when no longer needed using av_free(). + * If this function returns successfully, the format list will + * have at least one item (not counting the terminator). + * On failure, the contents of this pointer are unspecified. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats, int flags); + + +/** + * This struct describes the constraints on hardware frames attached to + * a given device with a hardware-specific configuration. This is returned + * by av_hwdevice_get_hwframe_constraints() and must be freed by + * av_hwframe_constraints_free() after use. + */ +typedef struct AVHWFramesConstraints { + /** + * A list of possible values for format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. This member will always be filled. + */ + enum AVPixelFormat *valid_hw_formats; + + /** + * A list of possible values for sw_format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. Can be NULL if this information is + * not known. + */ + enum AVPixelFormat *valid_sw_formats; + + /** + * The minimum size of frames in this hw_frames_ctx. + * (Zero if not known.) + */ + int min_width; + int min_height; + + /** + * The maximum size of frames in this hw_frames_ctx. + * (INT_MAX if not known / no limit.) + */ + int max_width; + int max_height; +} AVHWFramesConstraints; + +/** + * Allocate a HW-specific configuration structure for a given HW device. + * After use, the user must free all members as required by the specific + * hardware structure being used, then free the structure itself with + * av_free(). + * + * @param device_ctx a reference to the associated AVHWDeviceContext. + * @return The newly created HW-specific configuration structure on + * success or NULL on failure. + */ +void *av_hwdevice_hwconfig_alloc(AVBufferRef *device_ctx); + +/** + * Get the constraints on HW frames given a device and the HW-specific + * configuration to be used with that device. If no HW-specific + * configuration is provided, returns the maximum possible capabilities + * of the device. + * + * @param ref a reference to the associated AVHWDeviceContext. + * @param hwconfig a filled HW-specific configuration structure, or NULL + * to return the maximum possible capabilities of the device. + * @return AVHWFramesConstraints structure describing the constraints + * on the device, or NULL if not available. + */ +AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, + const void *hwconfig); + +/** + * Free an AVHWFrameConstraints structure. + * + * @param constraints The (filled or unfilled) AVHWFrameConstraints structure. + */ +void av_hwframe_constraints_free(AVHWFramesConstraints **constraints); + + +/** + * Flags to apply to frame mappings. + */ +enum { + /** + * The mapping must be readable. + */ + AV_HWFRAME_MAP_READ = 1 << 0, + /** + * The mapping must be writeable. + */ + AV_HWFRAME_MAP_WRITE = 1 << 1, + /** + * The mapped frame will be overwritten completely in subsequent + * operations, so the current frame data need not be loaded. Any values + * which are not overwritten are unspecified. + */ + AV_HWFRAME_MAP_OVERWRITE = 1 << 2, + /** + * The mapping must be direct. That is, there must not be any copying in + * the map or unmap steps. Note that performance of direct mappings may + * be much lower than normal memory. + */ + AV_HWFRAME_MAP_DIRECT = 1 << 3, +}; + +/** + * Map a hardware frame. + * + * This has a number of different possible effects, depending on the format + * and origin of the src and dst frames. On input, src should be a usable + * frame with valid buffers and dst should be blank (typically as just created + * by av_frame_alloc()). src should have an associated hwframe context, and + * dst may optionally have a format and associated hwframe context. + * + * If src was created by mapping a frame from the hwframe context of dst, + * then this function undoes the mapping - dst is replaced by a reference to + * the frame that src was originally mapped from. + * + * If both src and dst have an associated hwframe context, then this function + * attempts to map the src frame from its hardware context to that of dst and + * then fill dst with appropriate data to be usable there. This will only be + * possible if the hwframe contexts and associated devices are compatible - + * given compatible devices, av_hwframe_ctx_create_derived() can be used to + * create a hwframe context for dst in which mapping should be possible. + * + * If src has a hwframe context but dst does not, then the src frame is + * mapped to normal memory and should thereafter be usable as a normal frame. + * If the format is set on dst, then the mapping will attempt to create dst + * with that format and fail if it is not possible. If format is unset (is + * AV_PIX_FMT_NONE) then dst will be mapped with whatever the most appropriate + * format to use is (probably the sw_format of the src hwframe context). + * + * A return value of AVERROR(ENOSYS) indicates that the mapping is not + * possible with the given arguments and hwframe setup, while other return + * values indicate that it failed somehow. + * + * On failure, the destination frame will be left blank, except for the + * hw_frames_ctx/format fields thay may have been set by the caller - those will + * be preserved as they were. + * + * @param dst Destination frame, to contain the mapping. + * @param src Source frame, to be mapped. + * @param flags Some combination of AV_HWFRAME_MAP_* flags. + * @return Zero on success, negative AVERROR code on failure. + */ +int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags); + + +/** + * Create and initialise an AVHWFramesContext as a mapping of another existing + * AVHWFramesContext on a different device. + * + * av_hwframe_ctx_init() should not be called after this. + * + * @param derived_frame_ctx On success, a reference to the newly created + * AVHWFramesContext. + * @param derived_device_ctx A reference to the device to create the new + * AVHWFramesContext on. + * @param source_frame_ctx A reference to an existing AVHWFramesContext + * which will be mapped to the derived context. + * @param flags Some combination of AV_HWFRAME_MAP_* flags, defining the + * mapping parameters to apply to frames which are allocated + * in the derived device. + * @return Zero on success, negative AVERROR code on failure. + */ +int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, + enum AVPixelFormat format, + AVBufferRef *derived_device_ctx, + AVBufferRef *source_frame_ctx, + int flags); + +#endif /* AVUTIL_HWCONTEXT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/imgutils.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/imgutils.h new file mode 100644 index 0000000000000..be53335568fad --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/imgutils.h @@ -0,0 +1,311 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_IMGUTILS_H +#define AVUTIL_IMGUTILS_H + +/** + * @file + * misc image utilities + * + * @addtogroup lavu_picture + * @{ + */ + +#include +#include +#include "pixdesc.h" +#include "pixfmt.h" +#include "rational.h" + +/** + * Compute the max pixel step for each plane of an image with a + * format described by pixdesc. + * + * The pixel step is the distance in bytes between the first byte of + * the group of bytes which describe a pixel component and the first + * byte of the successive group in the same plane for the same + * component. + * + * @param max_pixsteps an array which is filled with the max pixel step + * for each plane. Since a plane may contain different pixel + * components, the computed max_pixsteps[plane] is relative to the + * component in the plane with the max pixel step. + * @param max_pixstep_comps an array which is filled with the component + * for each plane which has the max pixel step. May be NULL. + */ +void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], + const AVPixFmtDescriptor *pixdesc); + +/** + * Compute the size of an image line with format pix_fmt and width + * width for the plane plane. + * + * @return the computed size in bytes + */ +int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane); + +/** + * Fill plane linesizes for an image with pixel format pix_fmt and + * width width. + * + * @param linesizes array to be filled with the linesize for each plane + * @return >= 0 in case of success, a negative error code otherwise + */ +int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width); + +/** + * Fill plane sizes for an image with pixel format pix_fmt and height height. + * + * @param size the array to be filled with the size of each image plane + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return >= 0 in case of success, a negative error code otherwise + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_fill_linesizes(). + */ +int av_image_fill_plane_sizes(size_t size[4], enum AVPixelFormat pix_fmt, + int height, const ptrdiff_t linesizes[4]); + +/** + * Fill plane data pointers for an image with pixel format pix_fmt and + * height height. + * + * @param data pointers array to be filled with the pointer for each image plane + * @param ptr the pointer to a buffer which will contain the image + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, + uint8_t *ptr, const int linesizes[4]); + +/** + * Allocate an image with size w and h and pixel format pix_fmt, and + * fill pointers and linesizes accordingly. + * The allocated image buffer has to be freed by using + * av_freep(&pointers[0]). + * + * @param align the value to use for buffer size alignment + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_alloc(uint8_t *pointers[4], int linesizes[4], + int w, int h, enum AVPixelFormat pix_fmt, int align); + +/** + * Copy image plane from src to dst. + * That is, copy "height" number of lines of "bytewidth" bytes each. + * The first byte of each successive line is separated by *_linesize + * bytes. + * + * bytewidth must be contained by both absolute values of dst_linesize + * and src_linesize, otherwise the function behavior is undefined. + * + * @param dst_linesize linesize for the image plane in dst + * @param src_linesize linesize for the image plane in src + */ +void av_image_copy_plane(uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, + int bytewidth, int height); + +/** + * Copy image data located in uncacheable (e.g. GPU mapped) memory. Where + * available, this function will use special functionality for reading from such + * memory, which may result in greatly improved performance compared to plain + * av_image_copy_plane(). + * + * bytewidth must be contained by both absolute values of dst_linesize + * and src_linesize, otherwise the function behavior is undefined. + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_copy_plane(). + * @note On x86, the linesizes currently need to be aligned to the cacheline + * size (i.e. 64) to get improved performance. + */ +void av_image_copy_plane_uc_from(uint8_t *dst, ptrdiff_t dst_linesize, + const uint8_t *src, ptrdiff_t src_linesize, + ptrdiff_t bytewidth, int height); + +/** + * Copy image in src_data to dst_data. + * + * @param dst_linesizes linesizes for the image in dst_data + * @param src_linesizes linesizes for the image in src_data + */ +void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], + const uint8_t *src_data[4], const int src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Copy image data located in uncacheable (e.g. GPU mapped) memory. Where + * available, this function will use special functionality for reading from such + * memory, which may result in greatly improved performance compared to plain + * av_image_copy(). + * + * The data pointers and the linesizes must be aligned to the maximum required + * by the CPU architecture. + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_copy(). + * @note On x86, the linesizes currently need to be aligned to the cacheline + * size (i.e. 64) to get improved performance. + */ +void av_image_copy_uc_from(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4], + const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Setup the data pointers and linesizes based on the specified image + * parameters and the provided array. + * + * The fields of the given image are filled in by using the src + * address which points to the image data buffer. Depending on the + * specified pixel format, one or multiple image data pointers and + * line sizes will be set. If a planar format is specified, several + * pointers will be set pointing to the different picture planes and + * the line sizes of the different planes will be stored in the + * lines_sizes array. Call with src == NULL to get the required + * size for the src buffer. + * + * To allocate the buffer and fill in the dst_data and dst_linesize in + * one call, use av_image_alloc(). + * + * @param dst_data data pointers to be filled in + * @param dst_linesize linesizes for the image in dst_data to be filled in + * @param src buffer which will contain or contains the actual image data, can be NULL + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the value used in src for linesize alignment + * @return the size in bytes required for src, a negative error code + * in case of failure + */ +int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Return the size in bytes of the amount of data required to store an + * image with the given parameters. + * + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the assumed linesize alignment + * @return the buffer size in bytes, a negative error code in case of failure + */ +int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Copy image data from an image into a buffer. + * + * av_image_get_buffer_size() can be used to compute the required size + * for the buffer to fill. + * + * @param dst a buffer into which picture data will be copied + * @param dst_size the size in bytes of dst + * @param src_data pointers containing the source image data + * @param src_linesize linesizes for the image in src_data + * @param pix_fmt the pixel format of the source image + * @param width the width of the source image in pixels + * @param height the height of the source image in pixels + * @param align the assumed linesize alignment for dst + * @return the number of bytes written to dst, or a negative value + * (error code) on error + */ +int av_image_copy_to_buffer(uint8_t *dst, int dst_size, + const uint8_t * const src_data[4], const int src_linesize[4], + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of the image can be addressed with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of a plane of an image with the specified pix_fmt can be addressed + * with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param max_pixels the maximum number of pixels the user wants to accept + * @param pix_fmt the pixel format, can be AV_PIX_FMT_NONE if unknown. + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx); + +/** + * Check if the given sample aspect ratio of an image is valid. + * + * It is considered invalid if the denominator is 0 or if applying the ratio + * to the image size would make the smaller dimension less than 1. If the + * sar numerator is 0, it is considered unknown and will return as valid. + * + * @param w width of the image + * @param h height of the image + * @param sar sample aspect ratio of the image + * @return 0 if valid, a negative AVERROR code otherwise + */ +int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar); + +/** + * Overwrite the image data with black. This is suitable for filling a + * sub-rectangle of an image, meaning the padding between the right most pixel + * and the left most pixel on the next line will not be overwritten. For some + * formats, the image size might be rounded up due to inherent alignment. + * + * If the pixel format has alpha, the alpha is cleared to opaque. + * + * This can return an error if the pixel format is not supported. Normally, all + * non-hwaccel pixel formats should be supported. + * + * Passing NULL for dst_data is allowed. Then the function returns whether the + * operation would have succeeded. (It can return an error if the pix_fmt is + * not supported.) + * + * @param dst_data data pointers to destination image + * @param dst_linesize linesizes for the destination image + * @param pix_fmt the pixel format of the image + * @param range the color range of the image (important for colorspaces such as YUV) + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @return 0 if the image data was cleared, a negative AVERROR code otherwise + */ +int av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4], + enum AVPixelFormat pix_fmt, enum AVColorRange range, + int width, int height); + +/** + * @} + */ + + +#endif /* AVUTIL_IMGUTILS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/intfloat.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/intfloat.h new file mode 100644 index 0000000000000..fe3d7ec4a5b6f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/intfloat.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_INTFLOAT_H +#define AVUTIL_INTFLOAT_H + +#include +#include "attributes.h" + +union av_intfloat32 { + uint32_t i; + float f; +}; + +union av_intfloat64 { + uint64_t i; + double f; +}; + +/** + * Reinterpret a 32-bit integer as a float. + */ +static av_always_inline float av_int2float(uint32_t i) +{ + union av_intfloat32 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a float as a 32-bit integer. + */ +static av_always_inline uint32_t av_float2int(float f) +{ + union av_intfloat32 v; + v.f = f; + return v.i; +} + +/** + * Reinterpret a 64-bit integer as a double. + */ +static av_always_inline double av_int2double(uint64_t i) +{ + union av_intfloat64 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a double as a 64-bit integer. + */ +static av_always_inline uint64_t av_double2int(double f) +{ + union av_intfloat64 v; + v.f = f; + return v.i; +} + +#endif /* AVUTIL_INTFLOAT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/log.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/log.h new file mode 100644 index 0000000000000..ab7ceabe2234a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/log.h @@ -0,0 +1,387 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_LOG_H +#define AVUTIL_LOG_H + +#include +#include "attributes.h" +#include "version.h" + +typedef enum { + AV_CLASS_CATEGORY_NA = 0, + AV_CLASS_CATEGORY_INPUT, + AV_CLASS_CATEGORY_OUTPUT, + AV_CLASS_CATEGORY_MUXER, + AV_CLASS_CATEGORY_DEMUXER, + AV_CLASS_CATEGORY_ENCODER, + AV_CLASS_CATEGORY_DECODER, + AV_CLASS_CATEGORY_FILTER, + AV_CLASS_CATEGORY_BITSTREAM_FILTER, + AV_CLASS_CATEGORY_SWSCALER, + AV_CLASS_CATEGORY_SWRESAMPLER, + AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT = 40, + AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT, + AV_CLASS_CATEGORY_NB ///< not part of ABI/API +}AVClassCategory; + +#define AV_IS_INPUT_DEVICE(category) \ + (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_INPUT)) + +#define AV_IS_OUTPUT_DEVICE(category) \ + (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_OUTPUT)) + +struct AVOptionRanges; + +/** + * Describe the class of an AVClass context structure. That is an + * arbitrary struct of which the first field is a pointer to an + * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.). + */ +typedef struct AVClass { + /** + * The name of the class; usually it is the same name as the + * context structure type to which the AVClass is associated. + */ + const char* class_name; + + /** + * A pointer to a function which returns the name of a context + * instance ctx associated with the class. + */ + const char* (*item_name)(void* ctx); + + /** + * a pointer to the first option specified in the class if any or NULL + * + * @see av_set_default_options() + */ + const struct AVOption *option; + + /** + * LIBAVUTIL_VERSION with which this structure was created. + * This is used to allow fields to be added without requiring major + * version bumps everywhere. + */ + + int version; + + /** + * Offset in the structure where log_level_offset is stored. + * 0 means there is no such variable + */ + int log_level_offset_offset; + + /** + * Offset in the structure where a pointer to the parent context for + * logging is stored. For example a decoder could pass its AVCodecContext + * to eval as such a parent context, which an av_log() implementation + * could then leverage to display the parent context. + * The offset can be NULL. + */ + int parent_log_context_offset; + + /** + * Category used for visualization (like color) + * This is only set if the category is equal for all objects using this class. + * available since version (51 << 16 | 56 << 8 | 100) + */ + AVClassCategory category; + + /** + * Callback to return the category. + * available since version (51 << 16 | 59 << 8 | 100) + */ + AVClassCategory (*get_category)(void* ctx); + + /** + * Callback to return the supported/allowed ranges. + * available since version (52.12) + */ + int (*query_ranges)(struct AVOptionRanges **, void *obj, const char *key, int flags); + + /** + * Return next AVOptions-enabled child or NULL + */ + void* (*child_next)(void *obj, void *prev); + + /** + * Iterate over the AVClasses corresponding to potential AVOptions-enabled + * children. + * + * @param iter pointer to opaque iteration state. The caller must initialize + * *iter to NULL before the first call. + * @return AVClass for the next AVOptions-enabled child or NULL if there are + * no more such children. + * + * @note The difference between child_next and this is that child_next + * iterates over _already existing_ objects, while child_class_iterate + * iterates over _all possible_ children. + */ + const struct AVClass* (*child_class_iterate)(void **iter); +} AVClass; + +/** + * @addtogroup lavu_log + * + * @{ + * + * @defgroup lavu_log_constants Logging Constants + * + * @{ + */ + +/** + * Print no output. + */ +#define AV_LOG_QUIET -8 + +/** + * Something went really wrong and we will crash now. + */ +#define AV_LOG_PANIC 0 + +/** + * Something went wrong and recovery is not possible. + * For example, no header was found for a format which depends + * on headers or an illegal combination of parameters is used. + */ +#define AV_LOG_FATAL 8 + +/** + * Something went wrong and cannot losslessly be recovered. + * However, not all future data is affected. + */ +#define AV_LOG_ERROR 16 + +/** + * Something somehow does not look correct. This may or may not + * lead to problems. An example would be the use of '-vstrict -2'. + */ +#define AV_LOG_WARNING 24 + +/** + * Standard information. + */ +#define AV_LOG_INFO 32 + +/** + * Detailed information. + */ +#define AV_LOG_VERBOSE 40 + +/** + * Stuff which is only useful for libav* developers. + */ +#define AV_LOG_DEBUG 48 + +/** + * Extremely verbose debugging, useful for libav* development. + */ +#define AV_LOG_TRACE 56 + +#define AV_LOG_MAX_OFFSET (AV_LOG_TRACE - AV_LOG_QUIET) + +/** + * @} + */ + +/** + * Sets additional colors for extended debugging sessions. + * @code + av_log(ctx, AV_LOG_DEBUG|AV_LOG_C(134), "Message in purple\n"); + @endcode + * Requires 256color terminal support. Uses outside debugging is not + * recommended. + */ +#define AV_LOG_C(x) ((x) << 8) + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log_set_callback + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct or NULL if general log. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + */ +void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Send the specified message to the log once with the initial_level and then with + * the subsequent_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct or NULL if general log. + * @param initial_level importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant" for the first occurance. + * @param subsequent_level importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant" after the first occurance. + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param state a variable to keep trak of if a message has already been printed + * this must be initialized to 0 before the first use. The same state + * must not be accessed by 2 Threads simultaneously. + */ +void av_log_once(void* avcl, int initial_level, int subsequent_level, int *state, const char *fmt, ...) av_printf_format(5, 6); + + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log_set_callback + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param vl The arguments referenced by the format string. + */ +void av_vlog(void *avcl, int level, const char *fmt, va_list vl); + +/** + * Get the current log level + * + * @see lavu_log_constants + * + * @return Current log level + */ +int av_log_get_level(void); + +/** + * Set the log level + * + * @see lavu_log_constants + * + * @param level Logging level + */ +void av_log_set_level(int level); + +/** + * Set the logging callback + * + * @note The callback must be thread safe, even if the application does not use + * threads itself as some codecs are multithreaded. + * + * @see av_log_default_callback + * + * @param callback A logging function with a compatible signature. + */ +void av_log_set_callback(void (*callback)(void*, int, const char*, va_list)); + +/** + * Default logging callback + * + * It prints the message to stderr, optionally colorizing it. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param vl The arguments referenced by the format string. + */ +void av_log_default_callback(void *avcl, int level, const char *fmt, + va_list vl); + +/** + * Return the context name + * + * @param ctx The AVClass context + * + * @return The AVClass class_name + */ +const char* av_default_item_name(void* ctx); +AVClassCategory av_default_get_category(void *ptr); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formatted line + * @param line_size size of the buffer + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + */ +void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formatted line; + * may be NULL if line_size is 0 + * @param line_size size of the buffer; at most line_size-1 characters will + * be written to the buffer, plus one null terminator + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + * @return Returns a negative value if an error occurred, otherwise returns + * the number of characters that would have been written for a + * sufficiently large buffer, not including the terminating null + * character. If the return value is not less than line_size, it means + * that the log message was truncated to fit the buffer. + */ +int av_log_format_line2(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * Skip repeated messages, this requires the user app to use av_log() instead of + * (f)printf as the 2 would otherwise interfere and lead to + * "Last message repeated x times" messages below (f)printf messages with some + * bad luck. + * Also to receive the last, "last repeated" line if any, the user app must + * call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end + */ +#define AV_LOG_SKIP_REPEATED 1 + +/** + * Include the log severity in messages originating from codecs. + * + * Results in messages such as: + * [rawvideo @ 0xDEADBEEF] [error] encode did not produce valid pts + */ +#define AV_LOG_PRINT_LEVEL 2 + +void av_log_set_flags(int arg); +int av_log_get_flags(void); + +/** + * @} + */ + +#endif /* AVUTIL_LOG_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/macros.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/macros.h new file mode 100644 index 0000000000000..2a7567c3ea8fb --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/macros.h @@ -0,0 +1,80 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu + * Utility Preprocessor macros + */ + +#ifndef AVUTIL_MACROS_H +#define AVUTIL_MACROS_H + +#include "libavutil/avconfig.h" + +#if AV_HAVE_BIGENDIAN +# define AV_NE(be, le) (be) +#else +# define AV_NE(be, le) (le) +#endif + +/** + * Comparator. + * For two numerical expressions x and y, gives 1 if x > y, -1 if x < y, and 0 + * if x == y. This is useful for instance in a qsort comparator callback. + * Furthermore, compilers are able to optimize this to branchless code, and + * there is no risk of overflow with signed types. + * As with many macros, this evaluates its argument multiple times, it thus + * must not have a side-effect. + */ +#define FFDIFFSIGN(x,y) (((x)>(y)) - ((x)<(y))) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) +#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c) + +#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0) +#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) + +#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24)) +#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24)) + +/** + * @addtogroup preproc_misc Preprocessor String Macros + * + * String manipulation macros + * + * @{ + */ + +#define AV_STRINGIFY(s) AV_TOSTRING(s) +#define AV_TOSTRING(s) #s + +#define AV_GLUE(a, b) a ## b +#define AV_JOIN(a, b) AV_GLUE(a, b) + +/** + * @} + */ + +#define AV_PRAGMA(s) _Pragma(#s) + +#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1)) + +#endif /* AVUTIL_MACROS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/mathematics.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/mathematics.h new file mode 100644 index 0000000000000..64d4137a60274 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/mathematics.h @@ -0,0 +1,243 @@ +/* + * copyright (c) 2005-2012 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @addtogroup lavu_math + * Mathematical utilities for working with timestamp and time base. + */ + +#ifndef AVUTIL_MATHEMATICS_H +#define AVUTIL_MATHEMATICS_H + +#include +#include +#include "attributes.h" +#include "rational.h" +#include "intfloat.h" + +#ifndef M_E +#define M_E 2.7182818284590452354 /* e */ +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#endif +#ifndef M_LOG2_10 +#define M_LOG2_10 3.32192809488736234787 /* log_2 10 */ +#endif +#ifndef M_PHI +#define M_PHI 1.61803398874989484820 /* phi / golden ratio */ +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#endif +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#endif +#ifndef NAN +#define NAN av_int2float(0x7fc00000) +#endif +#ifndef INFINITY +#define INFINITY av_int2float(0x7f800000) +#endif + +/** + * @addtogroup lavu_math + * + * @{ + */ + +/** + * Rounding methods. + */ +enum AVRounding { + AV_ROUND_ZERO = 0, ///< Round toward zero. + AV_ROUND_INF = 1, ///< Round away from zero. + AV_ROUND_DOWN = 2, ///< Round toward -infinity. + AV_ROUND_UP = 3, ///< Round toward +infinity. + AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero. + /** + * Flag telling rescaling functions to pass `INT64_MIN`/`MAX` through + * unchanged, avoiding special cases for #AV_NOPTS_VALUE. + * + * Unlike other values of the enumeration AVRounding, this value is a + * bitmask that must be used in conjunction with another value of the + * enumeration through a bitwise OR, in order to set behavior for normal + * cases. + * + * @code{.c} + * av_rescale_rnd(3, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + * // Rescaling 3: + * // Calculating 3 * 1 / 2 + * // 3 / 2 is rounded up to 2 + * // => 2 + * + * av_rescale_rnd(AV_NOPTS_VALUE, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + * // Rescaling AV_NOPTS_VALUE: + * // AV_NOPTS_VALUE == INT64_MIN + * // AV_NOPTS_VALUE is passed through + * // => AV_NOPTS_VALUE + * @endcode + */ + AV_ROUND_PASS_MINMAX = 8192, +}; + +/** + * Compute the greatest common divisor of two integer operands. + * + * @param a,b Operands + * @return GCD of a and b up to sign; if a >= 0 and b >= 0, return value is >= 0; + * if a == 0 and b == 0, returns 0. + */ +int64_t av_const av_gcd(int64_t a, int64_t b); + +/** + * Rescale a 64-bit integer with rounding to nearest. + * + * The operation is mathematically equivalent to `a * b / c`, but writing that + * directly can overflow. + * + * This function is equivalent to av_rescale_rnd() with #AV_ROUND_NEAR_INF. + * + * @see av_rescale_rnd(), av_rescale_q(), av_rescale_q_rnd() + */ +int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const; + +/** + * Rescale a 64-bit integer with specified rounding. + * + * The operation is mathematically equivalent to `a * b / c`, but writing that + * directly can overflow, and does not support different rounding methods. + * If the result is not representable then INT64_MIN is returned. + * + * @see av_rescale(), av_rescale_q(), av_rescale_q_rnd() + */ +int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers. + * + * The operation is mathematically equivalent to `a * bq / cq`. + * + * This function is equivalent to av_rescale_q_rnd() with #AV_ROUND_NEAR_INF. + * + * @see av_rescale(), av_rescale_rnd(), av_rescale_q_rnd() + */ +int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers with specified rounding. + * + * The operation is mathematically equivalent to `a * bq / cq`. + * + * @see av_rescale(), av_rescale_rnd(), av_rescale_q() + */ +int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, + enum AVRounding rnd) av_const; + +/** + * Compare two timestamps each in its own time base. + * + * @return One of the following values: + * - -1 if `ts_a` is before `ts_b` + * - 1 if `ts_a` is after `ts_b` + * - 0 if they represent the same position + * + * @warning + * The result of the function is undefined if one of the timestamps is outside + * the `int64_t` range when represented in the other's timebase. + */ +int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b); + +/** + * Compare the remainders of two integer operands divided by a common divisor. + * + * In other words, compare the least significant `log2(mod)` bits of integers + * `a` and `b`. + * + * @code{.c} + * av_compare_mod(0x11, 0x02, 0x10) < 0 // since 0x11 % 0x10 (0x1) < 0x02 % 0x10 (0x2) + * av_compare_mod(0x11, 0x02, 0x20) > 0 // since 0x11 % 0x20 (0x11) > 0x02 % 0x20 (0x02) + * @endcode + * + * @param a,b Operands + * @param mod Divisor; must be a power of 2 + * @return + * - a negative value if `a % mod < b % mod` + * - a positive value if `a % mod > b % mod` + * - zero if `a % mod == b % mod` + */ +int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod); + +/** + * Rescale a timestamp while preserving known durations. + * + * This function is designed to be called per audio packet to scale the input + * timestamp to a different time base. Compared to a simple av_rescale_q() + * call, this function is robust against possible inconsistent frame durations. + * + * The `last` parameter is a state variable that must be preserved for all + * subsequent calls for the same stream. For the first call, `*last` should be + * initialized to #AV_NOPTS_VALUE. + * + * @param[in] in_tb Input time base + * @param[in] in_ts Input timestamp + * @param[in] fs_tb Duration time base; typically this is finer-grained + * (greater) than `in_tb` and `out_tb` + * @param[in] duration Duration till the next call to this function (i.e. + * duration of the current packet/frame) + * @param[in,out] last Pointer to a timestamp expressed in terms of + * `fs_tb`, acting as a state variable + * @param[in] out_tb Output timebase + * @return Timestamp expressed in terms of `out_tb` + * + * @note In the context of this function, "duration" is in term of samples, not + * seconds. + */ +int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb); + +/** + * Add a value to a timestamp. + * + * This function guarantees that when the same value is repeatly added that + * no accumulation of rounding errors occurs. + * + * @param[in] ts Input timestamp + * @param[in] ts_tb Input timestamp time base + * @param[in] inc Value to be added + * @param[in] inc_tb Time base of `inc` + */ +int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc); + + +/** + * @} + */ + +#endif /* AVUTIL_MATHEMATICS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/mem.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/mem.h new file mode 100644 index 0000000000000..d91174196c9ca --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/mem.h @@ -0,0 +1,696 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_mem + * Memory handling functions + */ + +#ifndef AVUTIL_MEM_H +#define AVUTIL_MEM_H + +#include +#include + +#include "attributes.h" +#include "avutil.h" +#include "version.h" + +/** + * @addtogroup lavu_mem + * Utilities for manipulating memory. + * + * FFmpeg has several applications of memory that are not required of a typical + * program. For example, the computing-heavy components like video decoding and + * encoding can be sped up significantly through the use of aligned memory. + * + * However, for each of FFmpeg's applications of memory, there might not be a + * recognized or standardized API for that specific use. Memory alignment, for + * instance, varies wildly depending on operating systems, architectures, and + * compilers. Hence, this component of @ref libavutil is created to make + * dealing with memory consistently possible on all platforms. + * + * @{ + */ + +#if FF_API_DECLARE_ALIGNED +/** + * + * @defgroup lavu_mem_macros Alignment Macros + * Helper macros for declaring aligned variables. + * @{ + */ + +/** + * @def DECLARE_ALIGNED(n,t,v) + * Declare a variable that is aligned in memory. + * + * @code{.c} + * DECLARE_ALIGNED(16, uint16_t, aligned_int) = 42; + * DECLARE_ALIGNED(32, uint8_t, aligned_array)[128]; + * + * // The default-alignment equivalent would be + * uint16_t aligned_int = 42; + * uint8_t aligned_array[128]; + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + +/** + * @def DECLARE_ASM_ALIGNED(n,t,v) + * Declare an aligned variable appropriate for use in inline assembly code. + * + * @code{.c} + * DECLARE_ASM_ALIGNED(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008); + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + +/** + * @def DECLARE_ASM_CONST(n,t,v) + * Declare a static constant aligned variable appropriate for use in inline + * assembly code. + * + * @code{.c} + * DECLARE_ASM_CONST(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008); + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v +#elif defined(__DJGPP__) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v + #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v +#elif defined(__GNUC__) || defined(__clang__) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v +#elif defined(_MSC_VER) + #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v +#else + #define DECLARE_ALIGNED(n,t,v) t v + #define DECLARE_ASM_ALIGNED(n,t,v) t v + #define DECLARE_ASM_CONST(n,t,v) static const t v +#endif + +/** + * @} + */ +#endif + +/** + * @defgroup lavu_mem_attrs Function Attributes + * Function attributes applicable to memory handling functions. + * + * These function attributes can help compilers emit more useful warnings, or + * generate better code. + * @{ + */ + +/** + * @def av_malloc_attrib + * Function attribute denoting a malloc-like function. + * + * @see Function attribute `malloc` in GCC's documentation + */ + +#if AV_GCC_VERSION_AT_LEAST(3,1) + #define av_malloc_attrib __attribute__((__malloc__)) +#else + #define av_malloc_attrib +#endif + +/** + * @def av_alloc_size(...) + * Function attribute used on a function that allocates memory, whose size is + * given by the specified parameter(s). + * + * @code{.c} + * void *av_malloc(size_t size) av_alloc_size(1); + * void *av_calloc(size_t nmemb, size_t size) av_alloc_size(1, 2); + * @endcode + * + * @param ... One or two parameter indexes, separated by a comma + * + * @see Function attribute `alloc_size` in GCC's documentation + */ + +#if AV_GCC_VERSION_AT_LEAST(4,3) + #define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__))) +#else + #define av_alloc_size(...) +#endif + +/** + * @} + */ + +/** + * @defgroup lavu_mem_funcs Heap Management + * Functions responsible for allocating, freeing, and copying memory. + * + * All memory allocation functions have a built-in upper limit of `INT_MAX` + * bytes. This may be changed with av_max_alloc(), although exercise extreme + * caution when doing so. + * + * @{ + */ + +/** + * Allocate a memory block with alignment suitable for all memory accesses + * (including vectors if available on the CPU). + * + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * @see av_mallocz() + */ +void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a memory block with alignment suitable for all memory accesses + * (including vectors if available on the CPU) and zero all the bytes of the + * block. + * + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if it cannot be allocated + * @see av_malloc() + */ +void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a memory block for an array with av_malloc(). + * + * The allocated memory will have size `size * nmemb` bytes. + * + * @param nmemb Number of element + * @param size Size of a single element + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * @see av_malloc() + */ +av_alloc_size(1, 2) void *av_malloc_array(size_t nmemb, size_t size); + +/** + * Allocate a memory block for an array with av_mallocz(). + * + * The allocated memory will have size `size * nmemb` bytes. + * + * @param nmemb Number of elements + * @param size Size of the single element + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * + * @see av_mallocz() + * @see av_malloc_array() + */ +void *av_calloc(size_t nmemb, size_t size) av_malloc_attrib av_alloc_size(1, 2); + +#if FF_API_AV_MALLOCZ_ARRAY +/** + * @deprecated use av_calloc() + */ +attribute_deprecated +void *av_mallocz_array(size_t nmemb, size_t size) av_malloc_attrib av_alloc_size(1, 2); +#endif + +/** + * Allocate, reallocate, or free a block of memory. + * + * If `ptr` is `NULL` and `size` > 0, allocate a new block. Otherwise, expand or + * shrink that block of memory according to `size`. + * + * @param ptr Pointer to a memory block already allocated with + * av_realloc() or `NULL` + * @param size Size in bytes of the memory block to be allocated or + * reallocated + * + * @return Pointer to a newly-reallocated block or `NULL` if the block + * cannot be reallocated + * + * @warning Unlike av_malloc(), the returned pointer is not guaranteed to be + * correctly aligned. The returned pointer must be freed after even + * if size is zero. + * @see av_fast_realloc() + * @see av_reallocp() + */ +void *av_realloc(void *ptr, size_t size) av_alloc_size(2); + +/** + * Allocate, reallocate, or free a block of memory through a pointer to a + * pointer. + * + * If `*ptr` is `NULL` and `size` > 0, allocate a new block. If `size` is + * zero, free the memory block pointed to by `*ptr`. Otherwise, expand or + * shrink that block of memory according to `size`. + * + * @param[in,out] ptr Pointer to a pointer to a memory block already allocated + * with av_realloc(), or a pointer to `NULL`. The pointer + * is updated on success, or freed on failure. + * @param[in] size Size in bytes for the memory block to be allocated or + * reallocated + * + * @return Zero on success, an AVERROR error code on failure + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. + */ +av_warn_unused_result +int av_reallocp(void *ptr, size_t size); + +/** + * Allocate, reallocate, or free a block of memory. + * + * This function does the same thing as av_realloc(), except: + * - It takes two size arguments and allocates `nelem * elsize` bytes, + * after checking the result of the multiplication for integer overflow. + * - It frees the input block in case of failure, thus avoiding the memory + * leak with the classic + * @code{.c} + * buf = realloc(buf); + * if (!buf) + * return -1; + * @endcode + * pattern. + */ +void *av_realloc_f(void *ptr, size_t nelem, size_t elsize); + +/** + * Allocate, reallocate, or free an array. + * + * If `ptr` is `NULL` and `nmemb` > 0, allocate a new block. + * + * @param ptr Pointer to a memory block already allocated with + * av_realloc() or `NULL` + * @param nmemb Number of elements in the array + * @param size Size of the single element of the array + * + * @return Pointer to a newly-reallocated block or NULL if the block + * cannot be reallocated + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. The returned pointer must be freed after even if + * nmemb is zero. + * @see av_reallocp_array() + */ +av_alloc_size(2, 3) void *av_realloc_array(void *ptr, size_t nmemb, size_t size); + +/** + * Allocate, reallocate an array through a pointer to a pointer. + * + * If `*ptr` is `NULL` and `nmemb` > 0, allocate a new block. + * + * @param[in,out] ptr Pointer to a pointer to a memory block already + * allocated with av_realloc(), or a pointer to `NULL`. + * The pointer is updated on success, or freed on failure. + * @param[in] nmemb Number of elements + * @param[in] size Size of the single element + * + * @return Zero on success, an AVERROR error code on failure + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. *ptr must be freed after even if nmemb is zero. + */ +int av_reallocp_array(void *ptr, size_t nmemb, size_t size); + +/** + * Reallocate the given buffer if it is not large enough, otherwise do nothing. + * + * If the given buffer is `NULL`, then a new uninitialized buffer is allocated. + * + * If the given buffer is not large enough, and reallocation fails, `NULL` is + * returned and `*size` is set to 0, but the original buffer is not changed or + * freed. + * + * A typical use pattern follows: + * + * @code{.c} + * uint8_t *buf = ...; + * uint8_t *new_buf = av_fast_realloc(buf, ¤t_size, size_needed); + * if (!new_buf) { + * // Allocation failed; clean up original buffer + * av_freep(&buf); + * return AVERROR(ENOMEM); + * } + * @endcode + * + * @param[in,out] ptr Already allocated buffer, or `NULL` + * @param[in,out] size Pointer to the size of buffer `ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `ptr` + * @return `ptr` if the buffer is large enough, a pointer to newly reallocated + * buffer if the buffer was not large enough, or `NULL` in case of + * error + * @see av_realloc() + * @see av_fast_malloc() + */ +void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate a buffer, reusing the given one if large enough. + * + * Contrary to av_fast_realloc(), the current buffer contents might not be + * preserved and on error the old buffer is freed, thus no special handling to + * avoid memleaks is necessary. + * + * `*ptr` is allowed to be `NULL`, in which case allocation always happens if + * `size_needed` is greater than 0. + * + * @code{.c} + * uint8_t *buf = ...; + * av_fast_malloc(&buf, ¤t_size, size_needed); + * if (!buf) { + * // Allocation failed; buf already freed + * return AVERROR(ENOMEM); + * } + * @endcode + * + * @param[in,out] ptr Pointer to pointer to an already allocated buffer. + * `*ptr` will be overwritten with pointer to new + * buffer on success or `NULL` on failure + * @param[in,out] size Pointer to the size of buffer `*ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `*ptr` + * @see av_realloc() + * @see av_fast_mallocz() + */ +void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate and clear a buffer, reusing the given one if large enough. + * + * Like av_fast_malloc(), but all newly allocated space is initially cleared. + * Reused buffer is not cleared. + * + * `*ptr` is allowed to be `NULL`, in which case allocation always happens if + * `size_needed` is greater than 0. + * + * @param[in,out] ptr Pointer to pointer to an already allocated buffer. + * `*ptr` will be overwritten with pointer to new + * buffer on success or `NULL` on failure + * @param[in,out] size Pointer to the size of buffer `*ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `*ptr` + * @see av_fast_malloc() + */ +void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * Free a memory block which has been allocated with a function of av_malloc() + * or av_realloc() family. + * + * @param ptr Pointer to the memory block which should be freed. + * + * @note `ptr = NULL` is explicitly allowed. + * @note It is recommended that you use av_freep() instead, to prevent leaving + * behind dangling pointers. + * @see av_freep() + */ +void av_free(void *ptr); + +/** + * Free a memory block which has been allocated with a function of av_malloc() + * or av_realloc() family, and set the pointer pointing to it to `NULL`. + * + * @code{.c} + * uint8_t *buf = av_malloc(16); + * av_free(buf); + * // buf now contains a dangling pointer to freed memory, and accidental + * // dereference of buf will result in a use-after-free, which may be a + * // security risk. + * + * uint8_t *buf = av_malloc(16); + * av_freep(&buf); + * // buf is now NULL, and accidental dereference will only result in a + * // NULL-pointer dereference. + * @endcode + * + * @param ptr Pointer to the pointer to the memory block which should be freed + * @note `*ptr = NULL` is safe and leads to no action. + * @see av_free() + */ +void av_freep(void *ptr); + +/** + * Duplicate a string. + * + * @param s String to be duplicated + * @return Pointer to a newly-allocated string containing a + * copy of `s` or `NULL` if the string cannot be allocated + * @see av_strndup() + */ +char *av_strdup(const char *s) av_malloc_attrib; + +/** + * Duplicate a substring of a string. + * + * @param s String to be duplicated + * @param len Maximum length of the resulting string (not counting the + * terminating byte) + * @return Pointer to a newly-allocated string containing a + * substring of `s` or `NULL` if the string cannot be allocated + */ +char *av_strndup(const char *s, size_t len) av_malloc_attrib; + +/** + * Duplicate a buffer with av_malloc(). + * + * @param p Buffer to be duplicated + * @param size Size in bytes of the buffer copied + * @return Pointer to a newly allocated buffer containing a + * copy of `p` or `NULL` if the buffer cannot be allocated + */ +void *av_memdup(const void *p, size_t size); + +/** + * Overlapping memcpy() implementation. + * + * @param dst Destination buffer + * @param back Number of bytes back to start copying (i.e. the initial size of + * the overlapping window); must be > 0 + * @param cnt Number of bytes to copy; must be >= 0 + * + * @note `cnt > back` is valid, this will copy the bytes we just copied, + * thus creating a repeating pattern with a period length of `back`. + */ +void av_memcpy_backptr(uint8_t *dst, int back, int cnt); + +/** + * @} + */ + +/** + * @defgroup lavu_mem_dynarray Dynamic Array + * + * Utilities to make an array grow when needed. + * + * Sometimes, the programmer would want to have an array that can grow when + * needed. The libavutil dynamic array utilities fill that need. + * + * libavutil supports two systems of appending elements onto a dynamically + * allocated array, the first one storing the pointer to the value in the + * array, and the second storing the value directly. In both systems, the + * caller is responsible for maintaining a variable containing the length of + * the array, as well as freeing of the array after use. + * + * The first system stores pointers to values in a block of dynamically + * allocated memory. Since only pointers are stored, the function does not need + * to know the size of the type. Both av_dynarray_add() and + * av_dynarray_add_nofree() implement this system. + * + * @code + * type **array = NULL; //< an array of pointers to values + * int nb = 0; //< a variable to keep track of the length of the array + * + * type to_be_added = ...; + * type to_be_added2 = ...; + * + * av_dynarray_add(&array, &nb, &to_be_added); + * if (nb == 0) + * return AVERROR(ENOMEM); + * + * av_dynarray_add(&array, &nb, &to_be_added2); + * if (nb == 0) + * return AVERROR(ENOMEM); + * + * // Now: + * // nb == 2 + * // &to_be_added == array[0] + * // &to_be_added2 == array[1] + * + * av_freep(&array); + * @endcode + * + * The second system stores the value directly in a block of memory. As a + * result, the function has to know the size of the type. av_dynarray2_add() + * implements this mechanism. + * + * @code + * type *array = NULL; //< an array of values + * int nb = 0; //< a variable to keep track of the length of the array + * + * type to_be_added = ...; + * type to_be_added2 = ...; + * + * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), NULL); + * if (!addr) + * return AVERROR(ENOMEM); + * memcpy(addr, &to_be_added, sizeof(to_be_added)); + * + * // Shortcut of the above. + * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), + * (const void *)&to_be_added2); + * if (!addr) + * return AVERROR(ENOMEM); + * + * // Now: + * // nb == 2 + * // to_be_added == array[0] + * // to_be_added2 == array[1] + * + * av_freep(&array); + * @endcode + * + * @{ + */ + +/** + * Add the pointer to an element to a dynamic array. + * + * The array to grow is supposed to be an array of pointers to + * structures, and the element to add must be a pointer to an already + * allocated structure. + * + * The array is reallocated when its size reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the number pointed to by `nb_ptr` + * is incremented. + * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and + * `*nb_ptr` is set to 0. + * + * @param[in,out] tab_ptr Pointer to the array to grow + * @param[in,out] nb_ptr Pointer to the number of elements in the array + * @param[in] elem Element to add + * @see av_dynarray_add_nofree(), av_dynarray2_add() + */ +void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element to a dynamic array. + * + * Function has the same functionality as av_dynarray_add(), + * but it doesn't free memory on fails. It returns error code + * instead and leave current buffer untouched. + * + * @return >=0 on success, negative otherwise + * @see av_dynarray_add(), av_dynarray2_add() + */ +av_warn_unused_result +int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element of size `elem_size` to a dynamic array. + * + * The array is reallocated when its number of elements reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the number pointed to by `nb_ptr` + * is incremented. + * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and + * `*nb_ptr` is set to 0. + * + * @param[in,out] tab_ptr Pointer to the array to grow + * @param[in,out] nb_ptr Pointer to the number of elements in the array + * @param[in] elem_size Size in bytes of an element in the array + * @param[in] elem_data Pointer to the data of the element to add. If + * `NULL`, the space of the newly added element is + * allocated but left uninitialized. + * + * @return Pointer to the data of the element to copy in the newly allocated + * space + * @see av_dynarray_add(), av_dynarray_add_nofree() + */ +void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, + const uint8_t *elem_data); + +/** + * @} + */ + +/** + * @defgroup lavu_mem_misc Miscellaneous Functions + * + * Other functions related to memory allocation. + * + * @{ + */ + +/** + * Multiply two `size_t` values checking for overflow. + * + * @param[in] a,b Operands of multiplication + * @param[out] r Pointer to the result of the operation + * @return 0 on success, AVERROR(EINVAL) on overflow + */ +int av_size_mult(size_t a, size_t b, size_t *r); + +/** + * Set the maximum size that may be allocated in one block. + * + * The value specified with this function is effective for all libavutil's @ref + * lavu_mem_funcs "heap management functions." + * + * By default, the max value is defined as `INT_MAX`. + * + * @param max Value to be set as the new maximum size + * + * @warning Exercise extreme caution when using this function. Don't touch + * this if you do not understand the full consequence of doing so. + */ +void av_max_alloc(size_t max); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_MEM_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/opt.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/opt.h new file mode 100644 index 0000000000000..461b5d3b6bb2a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/opt.h @@ -0,0 +1,891 @@ +/* + * AVOptions + * copyright (c) 2005 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_OPT_H +#define AVUTIL_OPT_H + +/** + * @file + * AVOptions + */ + +#include "rational.h" +#include "avutil.h" +#include "channel_layout.h" +#include "dict.h" +#include "log.h" +#include "pixfmt.h" +#include "samplefmt.h" + +/** + * @defgroup avoptions AVOptions + * @ingroup lavu_data + * @{ + * AVOptions provide a generic system to declare options on arbitrary structs + * ("objects"). An option can have a help text, a type and a range of possible + * values. Options may then be enumerated, read and written to. + * + * @section avoptions_implement Implementing AVOptions + * This section describes how to add AVOptions capabilities to a struct. + * + * All AVOptions-related information is stored in an AVClass. Therefore + * the first member of the struct should be a pointer to an AVClass describing it. + * The option field of the AVClass must be set to a NULL-terminated static array + * of AVOptions. Each AVOption must have a non-empty name, a type, a default + * value and for number-type AVOptions also a range of allowed values. It must + * also declare an offset in bytes from the start of the struct, where the field + * associated with this AVOption is located. Other fields in the AVOption struct + * should also be set when applicable, but are not required. + * + * The following example illustrates an AVOptions-enabled struct: + * @code + * typedef struct test_struct { + * const AVClass *class; + * int int_opt; + * char *str_opt; + * uint8_t *bin_opt; + * int bin_len; + * } test_struct; + * + * static const AVOption test_options[] = { + * { "test_int", "This is a test option of int type.", offsetof(test_struct, int_opt), + * AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX }, + * { "test_str", "This is a test option of string type.", offsetof(test_struct, str_opt), + * AV_OPT_TYPE_STRING }, + * { "test_bin", "This is a test option of binary type.", offsetof(test_struct, bin_opt), + * AV_OPT_TYPE_BINARY }, + * { NULL }, + * }; + * + * static const AVClass test_class = { + * .class_name = "test class", + * .item_name = av_default_item_name, + * .option = test_options, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * @endcode + * + * Next, when allocating your struct, you must ensure that the AVClass pointer + * is set to the correct value. Then, av_opt_set_defaults() can be called to + * initialize defaults. After that the struct is ready to be used with the + * AVOptions API. + * + * When cleaning up, you may use the av_opt_free() function to automatically + * free all the allocated string and binary options. + * + * Continuing with the above example: + * + * @code + * test_struct *alloc_test_struct(void) + * { + * test_struct *ret = av_mallocz(sizeof(*ret)); + * ret->class = &test_class; + * av_opt_set_defaults(ret); + * return ret; + * } + * void free_test_struct(test_struct **foo) + * { + * av_opt_free(*foo); + * av_freep(foo); + * } + * @endcode + * + * @subsection avoptions_implement_nesting Nesting + * It may happen that an AVOptions-enabled struct contains another + * AVOptions-enabled struct as a member (e.g. AVCodecContext in + * libavcodec exports generic options, while its priv_data field exports + * codec-specific options). In such a case, it is possible to set up the + * parent struct to export a child's options. To do that, simply + * implement AVClass.child_next() and AVClass.child_class_iterate() in the + * parent struct's AVClass. + * Assuming that the test_struct from above now also contains a + * child_struct field: + * + * @code + * typedef struct child_struct { + * AVClass *class; + * int flags_opt; + * } child_struct; + * static const AVOption child_opts[] = { + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX }, + * { NULL }, + * }; + * static const AVClass child_class = { + * .class_name = "child class", + * .item_name = av_default_item_name, + * .option = child_opts, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * + * void *child_next(void *obj, void *prev) + * { + * test_struct *t = obj; + * if (!prev && t->child_struct) + * return t->child_struct; + * return NULL + * } + * const AVClass child_class_iterate(void **iter) + * { + * const AVClass *c = *iter ? NULL : &child_class; + * *iter = (void*)(uintptr_t)c; + * return c; + * } + * @endcode + * Putting child_next() and child_class_iterate() as defined above into + * test_class will now make child_struct's options accessible through + * test_struct (again, proper setup as described above needs to be done on + * child_struct right after it is created). + * + * From the above example it might not be clear why both child_next() + * and child_class_iterate() are needed. The distinction is that child_next() + * iterates over actually existing objects, while child_class_iterate() + * iterates over all possible child classes. E.g. if an AVCodecContext + * was initialized to use a codec which has private options, then its + * child_next() will return AVCodecContext.priv_data and finish + * iterating. OTOH child_class_iterate() on AVCodecContext.av_class will + * iterate over all available codecs with private options. + * + * @subsection avoptions_implement_named_constants Named constants + * It is possible to create named constants for options. Simply set the unit + * field of the option the constants should apply to a string and + * create the constants themselves as options of type AV_OPT_TYPE_CONST + * with their unit field set to the same string. + * Their default_val field should contain the value of the named + * constant. + * For example, to add some named constants for the test_flags option + * above, put the following into the child_opts array: + * @code + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, "test_unit" }, + * { "flag1", "This is a flag with value 16", 0, AV_OPT_TYPE_CONST, { .i64 = 16 }, 0, 0, "test_unit" }, + * @endcode + * + * @section avoptions_use Using AVOptions + * This section deals with accessing options in an AVOptions-enabled struct. + * Such structs in FFmpeg are e.g. AVCodecContext in libavcodec or + * AVFormatContext in libavformat. + * + * @subsection avoptions_use_examine Examining AVOptions + * The basic functions for examining options are av_opt_next(), which iterates + * over all options defined for one object, and av_opt_find(), which searches + * for an option with the given name. + * + * The situation is more complicated with nesting. An AVOptions-enabled struct + * may have AVOptions-enabled children. Passing the AV_OPT_SEARCH_CHILDREN flag + * to av_opt_find() will make the function search children recursively. + * + * For enumerating there are basically two cases. The first is when you want to + * get all options that may potentially exist on the struct and its children + * (e.g. when constructing documentation). In that case you should call + * av_opt_child_class_iterate() recursively on the parent struct's AVClass. The + * second case is when you have an already initialized struct with all its + * children and you want to get all options that can be actually written or read + * from it. In that case you should call av_opt_child_next() recursively (and + * av_opt_next() on each result). + * + * @subsection avoptions_use_get_set Reading and writing AVOptions + * When setting options, you often have a string read directly from the + * user. In such a case, simply passing it to av_opt_set() is enough. For + * non-string type options, av_opt_set() will parse the string according to the + * option type. + * + * Similarly av_opt_get() will read any option type and convert it to a string + * which will be returned. Do not forget that the string is allocated, so you + * have to free it with av_free(). + * + * In some cases it may be more convenient to put all options into an + * AVDictionary and call av_opt_set_dict() on it. A specific case of this + * are the format/codec open functions in lavf/lavc which take a dictionary + * filled with option as a parameter. This makes it possible to set some options + * that cannot be set otherwise, since e.g. the input file format is not known + * before the file is actually opened. + */ + +enum AVOptionType{ + AV_OPT_TYPE_FLAGS, + AV_OPT_TYPE_INT, + AV_OPT_TYPE_INT64, + AV_OPT_TYPE_DOUBLE, + AV_OPT_TYPE_FLOAT, + AV_OPT_TYPE_STRING, + AV_OPT_TYPE_RATIONAL, + AV_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length + AV_OPT_TYPE_DICT, + AV_OPT_TYPE_UINT64, + AV_OPT_TYPE_CONST, + AV_OPT_TYPE_IMAGE_SIZE, ///< offset must point to two consecutive integers + AV_OPT_TYPE_PIXEL_FMT, + AV_OPT_TYPE_SAMPLE_FMT, + AV_OPT_TYPE_VIDEO_RATE, ///< offset must point to AVRational + AV_OPT_TYPE_DURATION, + AV_OPT_TYPE_COLOR, +#if FF_API_OLD_CHANNEL_LAYOUT + AV_OPT_TYPE_CHANNEL_LAYOUT, +#endif + AV_OPT_TYPE_BOOL, + AV_OPT_TYPE_CHLAYOUT, +}; + +/** + * AVOption + */ +typedef struct AVOption { + const char *name; + + /** + * short English help text + * @todo What about other languages? + */ + const char *help; + + /** + * The offset relative to the context structure where the option + * value is stored. It should be 0 for named constants. + */ + int offset; + enum AVOptionType type; + + /** + * the default value for scalar options + */ + union { + int64_t i64; + double dbl; + const char *str; + /* TODO those are unused now */ + AVRational q; + } default_val; + double min; ///< minimum valid value for the option + double max; ///< maximum valid value for the option + + int flags; +#define AV_OPT_FLAG_ENCODING_PARAM 1 ///< a generic parameter which can be set by the user for muxing or encoding +#define AV_OPT_FLAG_DECODING_PARAM 2 ///< a generic parameter which can be set by the user for demuxing or decoding +#define AV_OPT_FLAG_AUDIO_PARAM 8 +#define AV_OPT_FLAG_VIDEO_PARAM 16 +#define AV_OPT_FLAG_SUBTITLE_PARAM 32 +/** + * The option is intended for exporting values to the caller. + */ +#define AV_OPT_FLAG_EXPORT 64 +/** + * The option may not be set through the AVOptions API, only read. + * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set. + */ +#define AV_OPT_FLAG_READONLY 128 +#define AV_OPT_FLAG_BSF_PARAM (1<<8) ///< a generic parameter which can be set by the user for bit stream filtering +#define AV_OPT_FLAG_RUNTIME_PARAM (1<<15) ///< a generic parameter which can be set by the user at runtime +#define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering +#define AV_OPT_FLAG_DEPRECATED (1<<17) ///< set if option is deprecated, users should refer to AVOption.help text for more information +#define AV_OPT_FLAG_CHILD_CONSTS (1<<18) ///< set if option constants can also reside in child objects +//FIXME think about enc-audio, ... style flags + + /** + * The logical unit to which the option belongs. Non-constant + * options and corresponding named constants share the same + * unit. May be NULL. + */ + const char *unit; +} AVOption; + +/** + * A single allowed range of values, or a single allowed value. + */ +typedef struct AVOptionRange { + const char *str; + /** + * Value range. + * For string ranges this represents the min/max length. + * For dimensions this represents the min/max pixel count or width/height in multi-component case. + */ + double value_min, value_max; + /** + * Value's component range. + * For string this represents the unicode range for chars, 0-127 limits to ASCII. + */ + double component_min, component_max; + /** + * Range flag. + * If set to 1 the struct encodes a range, if set to 0 a single value. + */ + int is_range; +} AVOptionRange; + +/** + * List of AVOptionRange structs. + */ +typedef struct AVOptionRanges { + /** + * Array of option ranges. + * + * Most of option types use just one component. + * Following describes multi-component option types: + * + * AV_OPT_TYPE_IMAGE_SIZE: + * component index 0: range of pixel count (width * height). + * component index 1: range of width. + * component index 2: range of height. + * + * @note To obtain multi-component version of this structure, user must + * provide AV_OPT_MULTI_COMPONENT_RANGE to av_opt_query_ranges or + * av_opt_query_ranges_default function. + * + * Multi-component range can be read as in following example: + * + * @code + * int range_index, component_index; + * AVOptionRanges *ranges; + * AVOptionRange *range[3]; //may require more than 3 in the future. + * av_opt_query_ranges(&ranges, obj, key, AV_OPT_MULTI_COMPONENT_RANGE); + * for (range_index = 0; range_index < ranges->nb_ranges; range_index++) { + * for (component_index = 0; component_index < ranges->nb_components; component_index++) + * range[component_index] = ranges->range[ranges->nb_ranges * component_index + range_index]; + * //do something with range here. + * } + * av_opt_freep_ranges(&ranges); + * @endcode + */ + AVOptionRange **range; + /** + * Number of ranges per component. + */ + int nb_ranges; + /** + * Number of componentes. + */ + int nb_components; +} AVOptionRanges; + +/** + * Show the obj options. + * + * @param req_flags requested flags for the options to show. Show only the + * options for which it is opt->flags & req_flags. + * @param rej_flags rejected flags for the options to show. Show only the + * options for which it is !(opt->flags & req_flags). + * @param av_log_obj log context to use for showing the options + */ +int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); + +/** + * Set the values of all AVOption fields to their default values. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + */ +void av_opt_set_defaults(void *s); + +/** + * Set the values of all AVOption fields to their default values. Only these + * AVOption fields for which (opt->flags & mask) == flags will have their + * default applied to s. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + * @param mask combination of AV_OPT_FLAG_* + * @param flags combination of AV_OPT_FLAG_* + */ +void av_opt_set_defaults2(void *s, int mask, int flags); + +/** + * Parse the key/value pairs list in opts. For each key/value pair + * found, stores the value in the field in ctx that is named like the + * key. ctx must be an AVClass context, storing is done using + * AVOptions. + * + * @param opts options string to parse, may be NULL + * @param key_val_sep a 0-terminated list of characters used to + * separate key from value + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other + * @return the number of successfully set key/value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_opt_set() if a key/value pair + * cannot be set + */ +int av_set_options_string(void *ctx, const char *opts, + const char *key_val_sep, const char *pairs_sep); + +/** + * Parse the key-value pairs list in opts. For each key=value pair found, + * set the value of the corresponding option in ctx. + * + * @param ctx the AVClass object to set options on + * @param opts the options string, key-value pairs separated by a + * delimiter + * @param shorthand a NULL-terminated array of options names for shorthand + * notation: if the first field in opts has no key part, + * the key is taken from the first element of shorthand; + * then again for the second, etc., until either opts is + * finished, shorthand is finished or a named option is + * found; after that, all options must be named + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @return the number of successfully set key=value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_set_string3() if a key/value pair + * cannot be set + * + * Options names must use only the following characters: a-z A-Z 0-9 - . / _ + * Separators must use characters distinct from option names and from each + * other. + */ +int av_opt_set_from_string(void *ctx, const char *opts, + const char *const *shorthand, + const char *key_val_sep, const char *pairs_sep); +/** + * Free all allocated objects in obj. + */ +void av_opt_free(void *obj); + +/** + * Check whether a particular flag is set in a flags field. + * + * @param field_name the name of the flag field option + * @param flag_name the name of the flag to check + * @return non-zero if the flag is set, zero if the flag isn't set, + * isn't of the right type, or the flags field doesn't exist. + */ +int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name); + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict(void *obj, struct AVDictionary **options); + + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags); + +/** + * Extract a key-value pair from the beginning of a string. + * + * @param ropts pointer to the options string, will be updated to + * point to the rest of the string (one of the pairs_sep + * or the final NUL) + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @param flags flags; see the AV_OPT_FLAG_* values below + * @param rkey parsed key; must be freed using av_free() + * @param rval parsed value; must be freed using av_free() + * + * @return >=0 for success, or a negative value corresponding to an + * AVERROR code in case of error; in particular: + * AVERROR(EINVAL) if no key is present + * + */ +int av_opt_get_key_value(const char **ropts, + const char *key_val_sep, const char *pairs_sep, + unsigned flags, + char **rkey, char **rval); + +enum { + + /** + * Accept to parse a value without a key; the key will then be returned + * as NULL. + */ + AV_OPT_FLAG_IMPLICIT_KEY = 1, +}; + +/** + * @defgroup opt_eval_funcs Evaluating option strings + * @{ + * This group of functions can be used to evaluate option strings + * and get numbers out of them. They do the same thing as av_opt_set(), + * except the result is written into the caller-supplied pointer. + * + * @param obj a struct whose first element is a pointer to AVClass. + * @param o an option for which the string is to be evaluated. + * @param val string to be evaluated. + * @param *_out value of the string will be written here. + * + * @return 0 on success, a negative number on failure. + */ +int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out); +int av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out); +int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out); +int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out); +int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double *double_out); +int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out); +/** + * @} + */ + +#define AV_OPT_SEARCH_CHILDREN (1 << 0) /**< Search in possible children of the + given object first. */ +/** + * The obj passed to av_opt_find() is fake -- only a double pointer to AVClass + * instead of a required pointer to a struct containing AVClass. This is + * useful for searching for options without needing to allocate the corresponding + * object. + */ +#define AV_OPT_SEARCH_FAKE_OBJ (1 << 1) + +/** + * In av_opt_get, return NULL if the option has a pointer type and is set to NULL, + * rather than returning an empty string. + */ +#define AV_OPT_ALLOW_NULL (1 << 2) + +/** + * Allows av_opt_query_ranges and av_opt_query_ranges_default to return more than + * one component for certain option types. + * @see AVOptionRanges for details. + */ +#define AV_OPT_MULTI_COMPONENT_RANGE (1 << 12) + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return A pointer to the option found, or NULL if no option + * was found. + * + * @note Options found with AV_OPT_SEARCH_CHILDREN flag may not be settable + * directly with av_opt_set(). Use special calls which take an options + * AVDictionary (e.g. avformat_open_input()) to set options found with this + * flag. + */ +const AVOption *av_opt_find(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags); + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * @param[out] target_obj if non-NULL, an object to which the option belongs will be + * written here. It may be different from obj if AV_OPT_SEARCH_CHILDREN is present + * in search_flags. This parameter is ignored if search_flags contain + * AV_OPT_SEARCH_FAKE_OBJ. + * + * @return A pointer to the option found, or NULL if no option + * was found. + */ +const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags, void **target_obj); + +/** + * Iterate over all AVOptions belonging to obj. + * + * @param obj an AVOptions-enabled struct or a double pointer to an + * AVClass describing it. + * @param prev result of the previous call to av_opt_next() on this object + * or NULL + * @return next AVOption or NULL + */ +const AVOption *av_opt_next(const void *obj, const AVOption *prev); + +/** + * Iterate over AVOptions-enabled children of obj. + * + * @param prev result of a previous call to this function or NULL + * @return next AVOptions-enabled child or NULL + */ +void *av_opt_child_next(void *obj, void *prev); + +/** + * Iterate over potential AVOptions-enabled children of parent. + * + * @param iter a pointer where iteration state is stored. + * @return AVClass corresponding to next potential child or NULL + */ +const AVClass *av_opt_child_class_iterate(const AVClass *parent, void **iter); + +/** + * @defgroup opt_set_funcs Option setting functions + * @{ + * Those functions set the field of obj with the given name to value. + * + * @param[in] obj A struct whose first element is a pointer to an AVClass. + * @param[in] name the name of the field to set + * @param[in] val The value to set. In case of av_opt_set() if the field is not + * of a string type, then the given string is parsed. + * SI postfixes and some named scalars are supported. + * If the field is of a numeric type, it has to be a numeric or named + * scalar. Behavior with more than one scalar and +- infix operators + * is undefined. + * If the field is of a flags type, it has to be a sequence of numeric + * scalars or named flags separated by '+' or '-'. Prefixing a flag + * with '+' causes it to be set without affecting the other flags; + * similarly, '-' unsets a flag. + * If the field is of a dictionary type, it has to be a ':' separated list of + * key=value parameters. Values containing ':' special characters must be + * escaped. + * @param search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be set on a child of obj. + * + * @return 0 if the value has been set, or an AVERROR code in case of + * error: + * AVERROR_OPTION_NOT_FOUND if no matching option exists + * AVERROR(ERANGE) if the value is out of range + * AVERROR(EINVAL) if the value is not valid + */ +int av_opt_set (void *obj, const char *name, const char *val, int search_flags); +int av_opt_set_int (void *obj, const char *name, int64_t val, int search_flags); +int av_opt_set_double (void *obj, const char *name, double val, int search_flags); +int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags); +int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, int search_flags); +int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags); +int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags); +int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags); +int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags); +#if FF_API_OLD_CHANNEL_LAYOUT +attribute_deprecated +int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags); +#endif +int av_opt_set_chlayout(void *obj, const char *name, const AVChannelLayout *layout, int search_flags); +/** + * @note Any old dictionary present is discarded and replaced with a copy of the new one. The + * caller still owns val is and responsible for freeing it. + */ +int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags); + +/** + * Set a binary option to an integer list. + * + * @param obj AVClass object to set options on + * @param name name of the binary option + * @param val pointer to an integer list (must have the correct type with + * regard to the contents of the list) + * @param term list terminator (usually 0 or -1) + * @param flags search flags + */ +#define av_opt_set_int_list(obj, name, val, term, flags) \ + (av_int_list_length(val, term) > INT_MAX / sizeof(*(val)) ? \ + AVERROR(EINVAL) : \ + av_opt_set_bin(obj, name, (const uint8_t *)(val), \ + av_int_list_length(val, term) * sizeof(*(val)), flags)) + +/** + * @} + */ + +/** + * @defgroup opt_get_funcs Option getting functions + * @{ + * Those functions get a value of the option with the given name from an object. + * + * @param[in] obj a struct whose first element is a pointer to an AVClass. + * @param[in] name name of the option to get. + * @param[in] search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be found in a child of obj. + * @param[out] out_val value of the option will be written here + * @return >=0 on success, a negative error code otherwise + */ +/** + * @note the returned string will be av_malloc()ed and must be av_free()ed by the caller + * + * @note if AV_OPT_ALLOW_NULL is set in search_flags in av_opt_get, and the + * option is of type AV_OPT_TYPE_STRING, AV_OPT_TYPE_BINARY or AV_OPT_TYPE_DICT + * and is set to NULL, *out_val will be set to NULL instead of an allocated + * empty string. + */ +int av_opt_get (void *obj, const char *name, int search_flags, uint8_t **out_val); +int av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val); +int av_opt_get_double (void *obj, const char *name, int search_flags, double *out_val); +int av_opt_get_q (void *obj, const char *name, int search_flags, AVRational *out_val); +int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out); +int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt); +int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt); +int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val); +#if FF_API_OLD_CHANNEL_LAYOUT +attribute_deprecated +int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout); +#endif +int av_opt_get_chlayout(void *obj, const char *name, int search_flags, AVChannelLayout *layout); +/** + * @param[out] out_val The returned dictionary is a copy of the actual value and must + * be freed with av_dict_free() by the caller + */ +int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val); +/** + * @} + */ +/** + * Gets a pointer to the requested field in a struct. + * This function allows accessing a struct even when its fields are moved or + * renamed since the application making the access has been compiled, + * + * @returns a pointer to the field, it can be cast to the correct type and read + * or written to. + */ +void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name); + +/** + * Free an AVOptionRanges struct and set it to NULL. + */ +void av_opt_freep_ranges(AVOptionRanges **ranges); + +/** + * Get a list of allowed ranges for the given option. + * + * The returned list may depend on other fields in obj like for example profile. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_freep_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * Copy options from src object into dest object. + * + * The underlying AVClass of both src and dest must coincide. The guarantee + * below does not apply if this is not fulfilled. + * + * Options that require memory allocation (e.g. string or binary) are malloc'ed in dest object. + * Original memory allocated for such options is freed unless both src and dest options points to the same memory. + * + * Even on error it is guaranteed that allocated options from src and dest + * no longer alias each other afterwards; in particular calling av_opt_free() + * on both src and dest is safe afterwards if dest has been memdup'ed from src. + * + * @param dest Object to copy from + * @param src Object to copy into + * @return 0 on success, negative on error + */ +int av_opt_copy(void *dest, const void *src); + +/** + * Get a default list of allowed ranges for the given option. + * + * This list is constructed without using the AVClass.query_ranges() callback + * and can be used as fallback from within the callback. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_free_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * Check if given option is set to its default value. + * + * Options o must belong to the obj. This function must not be called to check child's options state. + * @see av_opt_is_set_to_default_by_name(). + * + * @param obj AVClass object to check option on + * @param o option to be checked + * @return >0 when option is set to its default, + * 0 when option is not set its default, + * <0 on error + */ +int av_opt_is_set_to_default(void *obj, const AVOption *o); + +/** + * Check if given option is set to its default value. + * + * @param obj AVClass object to check option on + * @param name option name + * @param search_flags combination of AV_OPT_SEARCH_* + * @return >0 when option is set to its default, + * 0 when option is not set its default, + * <0 on error + */ +int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags); + + +#define AV_OPT_SERIALIZE_SKIP_DEFAULTS 0x00000001 ///< Serialize options that are not set to default values only. +#define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT 0x00000002 ///< Serialize options that exactly match opt_flags only. + +/** + * Serialize object's options. + * + * Create a string containing object's serialized options. + * Such string may be passed back to av_opt_set_from_string() in order to restore option values. + * A key/value or pairs separator occurring in the serialized value or + * name string are escaped through the av_escape() function. + * + * @param[in] obj AVClass object to serialize + * @param[in] opt_flags serialize options with all the specified flags set (AV_OPT_FLAG) + * @param[in] flags combination of AV_OPT_SERIALIZE_* flags + * @param[out] buffer Pointer to buffer that will be allocated with string containg serialized options. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep character used to separate key from value + * @param[in] pairs_sep character used to separate two pairs from each other + * @return >= 0 on success, negative on error + * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same. + */ +int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, + const char key_val_sep, const char pairs_sep); +/** + * @} + */ + +#endif /* AVUTIL_OPT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/pixdesc.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/pixdesc.h new file mode 100644 index 0000000000000..f8a195ffcd6eb --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/pixdesc.h @@ -0,0 +1,410 @@ +/* + * pixel format descriptor + * Copyright (c) 2009 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXDESC_H +#define AVUTIL_PIXDESC_H + +#include + +#include "attributes.h" +#include "pixfmt.h" + +typedef struct AVComponentDescriptor { + /** + * Which of the 4 planes contains the component. + */ + int plane; + + /** + * Number of elements between 2 horizontally consecutive pixels. + * Elements are bits for bitstream formats, bytes otherwise. + */ + int step; + + /** + * Number of elements before the component of the first pixel. + * Elements are bits for bitstream formats, bytes otherwise. + */ + int offset; + + /** + * Number of least significant bits that must be shifted away + * to get the value. + */ + int shift; + + /** + * Number of bits in the component. + */ + int depth; +} AVComponentDescriptor; + +/** + * Descriptor that unambiguously describes how the bits of a pixel are + * stored in the up to 4 data planes of an image. It also stores the + * subsampling factors and number of components. + * + * @note This is separate of the colorspace (RGB, YCbCr, YPbPr, JPEG-style YUV + * and all the YUV variants) AVPixFmtDescriptor just stores how values + * are stored not what these values represent. + */ +typedef struct AVPixFmtDescriptor { + const char *name; + uint8_t nb_components; ///< The number of components each pixel has, (1-4) + + /** + * Amount to shift the luma width right to find the chroma width. + * For YV12 this is 1 for example. + * chroma_width = AV_CEIL_RSHIFT(luma_width, log2_chroma_w) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_w; + + /** + * Amount to shift the luma height right to find the chroma height. + * For YV12 this is 1 for example. + * chroma_height= AV_CEIL_RSHIFT(luma_height, log2_chroma_h) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_h; + + /** + * Combination of AV_PIX_FMT_FLAG_... flags. + */ + uint64_t flags; + + /** + * Parameters that describe how pixels are packed. + * If the format has 1 or 2 components, then luma is 0. + * If the format has 3 or 4 components: + * if the RGB flag is set then 0 is red, 1 is green and 2 is blue; + * otherwise 0 is luma, 1 is chroma-U and 2 is chroma-V. + * + * If present, the Alpha channel is always the last component. + */ + AVComponentDescriptor comp[4]; + + /** + * Alternative comma-separated names. + */ + const char *alias; +} AVPixFmtDescriptor; + +/** + * Pixel format is big-endian. + */ +#define AV_PIX_FMT_FLAG_BE (1 << 0) +/** + * Pixel format has a palette in data[1], values are indexes in this palette. + */ +#define AV_PIX_FMT_FLAG_PAL (1 << 1) +/** + * All values of a component are bit-wise packed end to end. + */ +#define AV_PIX_FMT_FLAG_BITSTREAM (1 << 2) +/** + * Pixel format is an HW accelerated format. + */ +#define AV_PIX_FMT_FLAG_HWACCEL (1 << 3) +/** + * At least one pixel component is not in the first data plane. + */ +#define AV_PIX_FMT_FLAG_PLANAR (1 << 4) +/** + * The pixel format contains RGB-like data (as opposed to YUV/grayscale). + */ +#define AV_PIX_FMT_FLAG_RGB (1 << 5) + +/** + * The pixel format has an alpha channel. This is set on all formats that + * support alpha in some way, including AV_PIX_FMT_PAL8. The alpha is always + * straight, never pre-multiplied. + * + * If a codec or a filter does not support alpha, it should set all alpha to + * opaque, or use the equivalent pixel formats without alpha component, e.g. + * AV_PIX_FMT_RGB0 (or AV_PIX_FMT_RGB24 etc.) instead of AV_PIX_FMT_RGBA. + */ +#define AV_PIX_FMT_FLAG_ALPHA (1 << 7) + +/** + * The pixel format is following a Bayer pattern + */ +#define AV_PIX_FMT_FLAG_BAYER (1 << 8) + +/** + * The pixel format contains IEEE-754 floating point values. Precision (double, + * single, or half) should be determined by the pixel size (64, 32, or 16 bits). + */ +#define AV_PIX_FMT_FLAG_FLOAT (1 << 9) + +/** + * Return the number of bits per pixel used by the pixel format + * described by pixdesc. Note that this is not the same as the number + * of bits per sample. + * + * The returned number of bits refers to the number of bits actually + * used for storing the pixel information, that is padding bits are + * not counted. + */ +int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * Return the number of bits per pixel for the pixel format + * described by pixdesc, including any padding or unused bits. + */ +int av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * @return a pixel format descriptor for provided pixel format or NULL if + * this pixel format is unknown. + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt); + +/** + * Iterate over all pixel format descriptors known to libavutil. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_next(const AVPixFmtDescriptor *prev); + +/** + * @return an AVPixelFormat id described by desc, or AV_PIX_FMT_NONE if desc + * is not a valid pointer to a pixel format descriptor. + */ +enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); + +/** + * Utility function to access log2_chroma_w log2_chroma_h from + * the pixel format AVPixFmtDescriptor. + * + * @param[in] pix_fmt the pixel format + * @param[out] h_shift store log2_chroma_w (horizontal/width shift) + * @param[out] v_shift store log2_chroma_h (vertical/height shift) + * + * @return 0 on success, AVERROR(ENOSYS) on invalid or unknown pixel format + */ +int av_pix_fmt_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, + int *h_shift, int *v_shift); + +/** + * @return number of planes in pix_fmt, a negative AVERROR if pix_fmt is not a + * valid pixel format. + */ +int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt); + +/** + * @return the name for provided color range or NULL if unknown. + */ +const char *av_color_range_name(enum AVColorRange range); + +/** + * @return the AVColorRange value for name or an AVError if not found. + */ +int av_color_range_from_name(const char *name); + +/** + * @return the name for provided color primaries or NULL if unknown. + */ +const char *av_color_primaries_name(enum AVColorPrimaries primaries); + +/** + * @return the AVColorPrimaries value for name or an AVError if not found. + */ +int av_color_primaries_from_name(const char *name); + +/** + * @return the name for provided color transfer or NULL if unknown. + */ +const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer); + +/** + * @return the AVColorTransferCharacteristic value for name or an AVError if not found. + */ +int av_color_transfer_from_name(const char *name); + +/** + * @return the name for provided color space or NULL if unknown. + */ +const char *av_color_space_name(enum AVColorSpace space); + +/** + * @return the AVColorSpace value for name or an AVError if not found. + */ +int av_color_space_from_name(const char *name); + +/** + * @return the name for provided chroma location or NULL if unknown. + */ +const char *av_chroma_location_name(enum AVChromaLocation location); + +/** + * @return the AVChromaLocation value for name or an AVError if not found. + */ +int av_chroma_location_from_name(const char *name); + +/** + * Return the pixel format corresponding to name. + * + * If there is no pixel format with name name, then looks for a + * pixel format with the name corresponding to the native endian + * format of name. + * For example in a little-endian system, first looks for "gray16", + * then for "gray16le". + * + * Finally if no pixel format has been found, returns AV_PIX_FMT_NONE. + */ +enum AVPixelFormat av_get_pix_fmt(const char *name); + +/** + * Return the short name for a pixel format, NULL in case pix_fmt is + * unknown. + * + * @see av_get_pix_fmt(), av_get_pix_fmt_string() + */ +const char *av_get_pix_fmt_name(enum AVPixelFormat pix_fmt); + +/** + * Print in buf the string corresponding to the pixel format with + * number pix_fmt, or a header if pix_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param pix_fmt the number of the pixel format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + */ +char *av_get_pix_fmt_string(char *buf, int buf_size, + enum AVPixelFormat pix_fmt); + +/** + * Read a line from an image, and write the values of the + * pixel format component c to dst. + * + * @param data the array containing the pointers to the planes of the image + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to read + * @param y the vertical coordinate of the first pixel to read + * @param w the width of the line to read, that is the number of + * values to write to dst + * @param read_pal_component if not zero and the format is a paletted + * format writes the values corresponding to the palette + * component c in data[1] to dst, rather than the palette indexes in + * data[0]. The behavior is undefined if the format is not paletted. + * @param dst_element_size size of elements in dst array (2 or 4 byte) + */ +void av_read_image_line2(void *dst, const uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int read_pal_component, + int dst_element_size); + +void av_read_image_line(uint16_t *dst, const uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int read_pal_component); + +/** + * Write the values from src to the pixel format component c of an + * image line. + * + * @param src array containing the values to write + * @param data the array containing the pointers to the planes of the + * image to write into. It is supposed to be zeroed. + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to write + * @param y the vertical coordinate of the first pixel to write + * @param w the width of the line to write, that is the number of + * values to write to the image line + * @param src_element_size size of elements in src array (2 or 4 byte) + */ +void av_write_image_line2(const void *src, uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int src_element_size); + +void av_write_image_line(const uint16_t *src, uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w); + +/** + * Utility function to swap the endianness of a pixel format. + * + * @param[in] pix_fmt the pixel format + * + * @return pixel format with swapped endianness if it exists, + * otherwise AV_PIX_FMT_NONE + */ +enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt); + +#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + int has_alpha); + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); + +#endif /* AVUTIL_PIXDESC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/pixfmt.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/pixfmt.h new file mode 100644 index 0000000000000..2d3927cc3f641 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/pixfmt.h @@ -0,0 +1,629 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXFMT_H +#define AVUTIL_PIXFMT_H + +/** + * @file + * pixel format definitions + */ + +#include "libavutil/avconfig.h" +#include "version.h" + +#define AVPALETTE_SIZE 1024 +#define AVPALETTE_COUNT 256 + +/** + * Pixel format. + * + * @note + * AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA + * color is put together as: + * (A << 24) | (R << 16) | (G << 8) | B + * This is stored as BGRA on little-endian CPU architectures and ARGB on + * big-endian CPUs. + * + * @note + * If the resolution is not a multiple of the chroma subsampling factor + * then the chroma plane resolution must be rounded up. + * + * @par + * When the pixel format is palettized RGB32 (AV_PIX_FMT_PAL8), the palettized + * image data is stored in AVFrame.data[0]. The palette is transported in + * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is + * formatted the same as in AV_PIX_FMT_RGB32 described above (i.e., it is + * also endian-specific). Note also that the individual RGB32 palette + * components stored in AVFrame.data[1] should be in the range 0..255. + * This is important as many custom PAL8 video codecs that were designed + * to run on the IBM VGA graphics adapter use 6-bit palette components. + * + * @par + * For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like + * for pal8. This palette is filled in automatically by the function + * allocating the picture. + */ +enum AVPixelFormat { + AV_PIX_FMT_NONE = -1, + AV_PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) + AV_PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr + AV_PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB... + AV_PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR... + AV_PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) + AV_PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples) + AV_PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) + AV_PIX_FMT_GRAY8, ///< Y , 8bpp + AV_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_PAL8, ///< 8 bits with AV_PIX_FMT_RGB32 palette + AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range + AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range + AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range + AV_PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 + AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 + AV_PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) + AV_PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb) + AV_PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb) + AV_PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) + AV_PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV21, ///< as above, but U and V bytes are swapped + + AV_PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... + AV_PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA... + AV_PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR... + AV_PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA... + + AV_PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian + AV_PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian + AV_PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) + AV_PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range + AV_PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) + AV_PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian + + AV_PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian + AV_PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian + AV_PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined + + AV_PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian + AV_PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian + AV_PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined + + /** + * Hardware acceleration through VA-API, data[3] contains a + * VASurfaceID. + */ + AV_PIX_FMT_VAAPI, + + AV_PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer + + AV_PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_YA8, ///< 8 bits gray, 8 bits alpha + + AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + AV_PIX_FMT_GRAY8A= AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + + AV_PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian + + /** + * The following 12 formats have the disadvantage of needing 1 format for each bit depth. + * Notice that each 9/10 bits sample is stored in 16 bits with extra padding. + * If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better. + */ + AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp + AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP + AV_PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big-endian + AV_PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little-endian + AV_PIX_FMT_GBRP10BE, ///< planar GBR 4:4:4 30bpp, big-endian + AV_PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little-endian + AV_PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little-endian + AV_PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + AV_PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + AV_PIX_FMT_YUVA420P9BE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian + AV_PIX_FMT_YUVA420P9LE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian + AV_PIX_FMT_YUVA422P9BE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA422P9LE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA444P9BE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA444P9LE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA420P10BE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P10LE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P10BE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P10LE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P10BE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P10LE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA420P16BE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P16LE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P16BE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P16LE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P16BE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P16LE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + + AV_PIX_FMT_VDPAU, ///< HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface + + AV_PIX_FMT_XYZ12LE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_XYZ12BE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_NV16, ///< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_NV20LE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_NV20BE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + + AV_PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + + AV_PIX_FMT_YVYU422, ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb + + AV_PIX_FMT_YA16BE, ///< 16 bits gray, 16 bits alpha (big-endian) + AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian) + + AV_PIX_FMT_GBRAP, ///< planar GBRA 4:4:4:4 32bpp + AV_PIX_FMT_GBRAP16BE, ///< planar GBRA 4:4:4:4 64bpp, big-endian + AV_PIX_FMT_GBRAP16LE, ///< planar GBRA 4:4:4:4 64bpp, little-endian + /** + * HW acceleration through QSV, data[3] contains a pointer to the + * mfxFrameSurface1 structure. + */ + AV_PIX_FMT_QSV, + /** + * HW acceleration though MMAL, data[3] contains a pointer to the + * MMAL_BUFFER_HEADER_T structure. + */ + AV_PIX_FMT_MMAL, + + AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer + + /** + * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers + * exactly as for system memory frames. + */ + AV_PIX_FMT_CUDA, + + AV_PIX_FMT_0RGB, ///< packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined + AV_PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined + AV_PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined + AV_PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined + + AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_GBRP12BE, ///< planar GBR 4:4:4 36bpp, big-endian + AV_PIX_FMT_GBRP12LE, ///< planar GBR 4:4:4 36bpp, little-endian + AV_PIX_FMT_GBRP14BE, ///< planar GBR 4:4:4 42bpp, big-endian + AV_PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little-endian + AV_PIX_FMT_YUVJ411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV411P and setting color_range + + AV_PIX_FMT_BAYER_BGGR8, ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples + AV_PIX_FMT_BAYER_RGGB8, ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples + AV_PIX_FMT_BAYER_GBRG8, ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples + AV_PIX_FMT_BAYER_GRBG8, ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples + AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian + +#if FF_API_XVMC + AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing +#endif + + AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_YUV440P12LE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P12BE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_AYUV64LE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_AYUV64BE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + + AV_PIX_FMT_VIDEOTOOLBOX, ///< hardware decoding through Videotoolbox + + AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian + AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian + + AV_PIX_FMT_GBRAP12BE, ///< planar GBR 4:4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRAP12LE, ///< planar GBR 4:4:4:4 48bpp, little-endian + + AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian + AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian + + AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec + + AV_PIX_FMT_GRAY12BE, ///< Y , 12bpp, big-endian + AV_PIX_FMT_GRAY12LE, ///< Y , 12bpp, little-endian + AV_PIX_FMT_GRAY10BE, ///< Y , 10bpp, big-endian + AV_PIX_FMT_GRAY10LE, ///< Y , 10bpp, little-endian + + AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian + AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian + + /** + * Hardware surfaces for Direct3D11. + * + * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11 + * hwaccel API and filtering support AV_PIX_FMT_D3D11 only. + * + * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the + * texture array index of the frame as intptr_t if the ID3D11Texture2D is + * an array texture (or always 0 if it's a normal texture). + */ + AV_PIX_FMT_D3D11, + + AV_PIX_FMT_GRAY9BE, ///< Y , 9bpp, big-endian + AV_PIX_FMT_GRAY9LE, ///< Y , 9bpp, little-endian + + AV_PIX_FMT_GBRPF32BE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, big-endian + AV_PIX_FMT_GBRPF32LE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, little-endian + AV_PIX_FMT_GBRAPF32BE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian + AV_PIX_FMT_GBRAPF32LE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian + + /** + * DRM-managed buffers exposed through PRIME buffer sharing. + * + * data[0] points to an AVDRMFrameDescriptor. + */ + AV_PIX_FMT_DRM_PRIME, + /** + * Hardware surfaces for OpenCL. + * + * data[i] contain 2D image objects (typed in C as cl_mem, used + * in OpenCL as image2d_t) for each plane of the surface. + */ + AV_PIX_FMT_OPENCL, + + AV_PIX_FMT_GRAY14BE, ///< Y , 14bpp, big-endian + AV_PIX_FMT_GRAY14LE, ///< Y , 14bpp, little-endian + + AV_PIX_FMT_GRAYF32BE, ///< IEEE-754 single precision Y, 32bpp, big-endian + AV_PIX_FMT_GRAYF32LE, ///< IEEE-754 single precision Y, 32bpp, little-endian + + AV_PIX_FMT_YUVA422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, little-endian + AV_PIX_FMT_YUVA444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, little-endian + + AV_PIX_FMT_NV24, ///< planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV42, ///< as above, but U and V bytes are swapped + + /** + * Vulkan hardware images. + * + * data[0] points to an AVVkFrame + */ + AV_PIX_FMT_VULKAN, + + AV_PIX_FMT_Y210BE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_Y210LE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, little-endian + + AV_PIX_FMT_X2RGB10LE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_X2RGB10BE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_X2BGR10LE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_X2BGR10BE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), big-endian, X=unused/undefined + + AV_PIX_FMT_P210BE, ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_P210LE, ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, little-endian + + AV_PIX_FMT_P410BE, ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, big-endian + AV_PIX_FMT_P410LE, ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, little-endian + + AV_PIX_FMT_P216BE, ///< interleaved chroma YUV 4:2:2, 32bpp, big-endian + AV_PIX_FMT_P216LE, ///< interleaved chroma YUV 4:2:2, 32bpp, little-endian + + AV_PIX_FMT_P416BE, ///< interleaved chroma YUV 4:4:4, 48bpp, big-endian + AV_PIX_FMT_P416LE, ///< interleaved chroma YUV 4:4:4, 48bpp, little-endian + + AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions +}; + +#if AV_HAVE_BIGENDIAN +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##be +#else +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##le +#endif + +#define AV_PIX_FMT_RGB32 AV_PIX_FMT_NE(ARGB, BGRA) +#define AV_PIX_FMT_RGB32_1 AV_PIX_FMT_NE(RGBA, ABGR) +#define AV_PIX_FMT_BGR32 AV_PIX_FMT_NE(ABGR, RGBA) +#define AV_PIX_FMT_BGR32_1 AV_PIX_FMT_NE(BGRA, ARGB) +#define AV_PIX_FMT_0RGB32 AV_PIX_FMT_NE(0RGB, BGR0) +#define AV_PIX_FMT_0BGR32 AV_PIX_FMT_NE(0BGR, RGB0) + +#define AV_PIX_FMT_GRAY9 AV_PIX_FMT_NE(GRAY9BE, GRAY9LE) +#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE) +#define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE) +#define AV_PIX_FMT_GRAY14 AV_PIX_FMT_NE(GRAY14BE, GRAY14LE) +#define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE) +#define AV_PIX_FMT_YA16 AV_PIX_FMT_NE(YA16BE, YA16LE) +#define AV_PIX_FMT_RGB48 AV_PIX_FMT_NE(RGB48BE, RGB48LE) +#define AV_PIX_FMT_RGB565 AV_PIX_FMT_NE(RGB565BE, RGB565LE) +#define AV_PIX_FMT_RGB555 AV_PIX_FMT_NE(RGB555BE, RGB555LE) +#define AV_PIX_FMT_RGB444 AV_PIX_FMT_NE(RGB444BE, RGB444LE) +#define AV_PIX_FMT_RGBA64 AV_PIX_FMT_NE(RGBA64BE, RGBA64LE) +#define AV_PIX_FMT_BGR48 AV_PIX_FMT_NE(BGR48BE, BGR48LE) +#define AV_PIX_FMT_BGR565 AV_PIX_FMT_NE(BGR565BE, BGR565LE) +#define AV_PIX_FMT_BGR555 AV_PIX_FMT_NE(BGR555BE, BGR555LE) +#define AV_PIX_FMT_BGR444 AV_PIX_FMT_NE(BGR444BE, BGR444LE) +#define AV_PIX_FMT_BGRA64 AV_PIX_FMT_NE(BGRA64BE, BGRA64LE) + +#define AV_PIX_FMT_YUV420P9 AV_PIX_FMT_NE(YUV420P9BE , YUV420P9LE) +#define AV_PIX_FMT_YUV422P9 AV_PIX_FMT_NE(YUV422P9BE , YUV422P9LE) +#define AV_PIX_FMT_YUV444P9 AV_PIX_FMT_NE(YUV444P9BE , YUV444P9LE) +#define AV_PIX_FMT_YUV420P10 AV_PIX_FMT_NE(YUV420P10BE, YUV420P10LE) +#define AV_PIX_FMT_YUV422P10 AV_PIX_FMT_NE(YUV422P10BE, YUV422P10LE) +#define AV_PIX_FMT_YUV440P10 AV_PIX_FMT_NE(YUV440P10BE, YUV440P10LE) +#define AV_PIX_FMT_YUV444P10 AV_PIX_FMT_NE(YUV444P10BE, YUV444P10LE) +#define AV_PIX_FMT_YUV420P12 AV_PIX_FMT_NE(YUV420P12BE, YUV420P12LE) +#define AV_PIX_FMT_YUV422P12 AV_PIX_FMT_NE(YUV422P12BE, YUV422P12LE) +#define AV_PIX_FMT_YUV440P12 AV_PIX_FMT_NE(YUV440P12BE, YUV440P12LE) +#define AV_PIX_FMT_YUV444P12 AV_PIX_FMT_NE(YUV444P12BE, YUV444P12LE) +#define AV_PIX_FMT_YUV420P14 AV_PIX_FMT_NE(YUV420P14BE, YUV420P14LE) +#define AV_PIX_FMT_YUV422P14 AV_PIX_FMT_NE(YUV422P14BE, YUV422P14LE) +#define AV_PIX_FMT_YUV444P14 AV_PIX_FMT_NE(YUV444P14BE, YUV444P14LE) +#define AV_PIX_FMT_YUV420P16 AV_PIX_FMT_NE(YUV420P16BE, YUV420P16LE) +#define AV_PIX_FMT_YUV422P16 AV_PIX_FMT_NE(YUV422P16BE, YUV422P16LE) +#define AV_PIX_FMT_YUV444P16 AV_PIX_FMT_NE(YUV444P16BE, YUV444P16LE) + +#define AV_PIX_FMT_GBRP9 AV_PIX_FMT_NE(GBRP9BE , GBRP9LE) +#define AV_PIX_FMT_GBRP10 AV_PIX_FMT_NE(GBRP10BE, GBRP10LE) +#define AV_PIX_FMT_GBRP12 AV_PIX_FMT_NE(GBRP12BE, GBRP12LE) +#define AV_PIX_FMT_GBRP14 AV_PIX_FMT_NE(GBRP14BE, GBRP14LE) +#define AV_PIX_FMT_GBRP16 AV_PIX_FMT_NE(GBRP16BE, GBRP16LE) +#define AV_PIX_FMT_GBRAP10 AV_PIX_FMT_NE(GBRAP10BE, GBRAP10LE) +#define AV_PIX_FMT_GBRAP12 AV_PIX_FMT_NE(GBRAP12BE, GBRAP12LE) +#define AV_PIX_FMT_GBRAP16 AV_PIX_FMT_NE(GBRAP16BE, GBRAP16LE) + +#define AV_PIX_FMT_BAYER_BGGR16 AV_PIX_FMT_NE(BAYER_BGGR16BE, BAYER_BGGR16LE) +#define AV_PIX_FMT_BAYER_RGGB16 AV_PIX_FMT_NE(BAYER_RGGB16BE, BAYER_RGGB16LE) +#define AV_PIX_FMT_BAYER_GBRG16 AV_PIX_FMT_NE(BAYER_GBRG16BE, BAYER_GBRG16LE) +#define AV_PIX_FMT_BAYER_GRBG16 AV_PIX_FMT_NE(BAYER_GRBG16BE, BAYER_GRBG16LE) + +#define AV_PIX_FMT_GBRPF32 AV_PIX_FMT_NE(GBRPF32BE, GBRPF32LE) +#define AV_PIX_FMT_GBRAPF32 AV_PIX_FMT_NE(GBRAPF32BE, GBRAPF32LE) + +#define AV_PIX_FMT_GRAYF32 AV_PIX_FMT_NE(GRAYF32BE, GRAYF32LE) + +#define AV_PIX_FMT_YUVA420P9 AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE) +#define AV_PIX_FMT_YUVA422P9 AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE) +#define AV_PIX_FMT_YUVA444P9 AV_PIX_FMT_NE(YUVA444P9BE , YUVA444P9LE) +#define AV_PIX_FMT_YUVA420P10 AV_PIX_FMT_NE(YUVA420P10BE, YUVA420P10LE) +#define AV_PIX_FMT_YUVA422P10 AV_PIX_FMT_NE(YUVA422P10BE, YUVA422P10LE) +#define AV_PIX_FMT_YUVA444P10 AV_PIX_FMT_NE(YUVA444P10BE, YUVA444P10LE) +#define AV_PIX_FMT_YUVA422P12 AV_PIX_FMT_NE(YUVA422P12BE, YUVA422P12LE) +#define AV_PIX_FMT_YUVA444P12 AV_PIX_FMT_NE(YUVA444P12BE, YUVA444P12LE) +#define AV_PIX_FMT_YUVA420P16 AV_PIX_FMT_NE(YUVA420P16BE, YUVA420P16LE) +#define AV_PIX_FMT_YUVA422P16 AV_PIX_FMT_NE(YUVA422P16BE, YUVA422P16LE) +#define AV_PIX_FMT_YUVA444P16 AV_PIX_FMT_NE(YUVA444P16BE, YUVA444P16LE) + +#define AV_PIX_FMT_XYZ12 AV_PIX_FMT_NE(XYZ12BE, XYZ12LE) +#define AV_PIX_FMT_NV20 AV_PIX_FMT_NE(NV20BE, NV20LE) +#define AV_PIX_FMT_AYUV64 AV_PIX_FMT_NE(AYUV64BE, AYUV64LE) +#define AV_PIX_FMT_P010 AV_PIX_FMT_NE(P010BE, P010LE) +#define AV_PIX_FMT_P016 AV_PIX_FMT_NE(P016BE, P016LE) + +#define AV_PIX_FMT_Y210 AV_PIX_FMT_NE(Y210BE, Y210LE) +#define AV_PIX_FMT_X2RGB10 AV_PIX_FMT_NE(X2RGB10BE, X2RGB10LE) +#define AV_PIX_FMT_X2BGR10 AV_PIX_FMT_NE(X2BGR10BE, X2BGR10LE) + +#define AV_PIX_FMT_P210 AV_PIX_FMT_NE(P210BE, P210LE) +#define AV_PIX_FMT_P410 AV_PIX_FMT_NE(P410BE, P410LE) +#define AV_PIX_FMT_P216 AV_PIX_FMT_NE(P216BE, P216LE) +#define AV_PIX_FMT_P416 AV_PIX_FMT_NE(P416BE, P416LE) + +/** + * Chromaticity coordinates of the source primaries. + * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.1 and ITU-T H.273. + */ +enum AVColorPrimaries { + AVCOL_PRI_RESERVED0 = 0, + AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP 177 Annex B + AVCOL_PRI_UNSPECIFIED = 2, + AVCOL_PRI_RESERVED = 3, + AVCOL_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + + AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + AVCOL_PRI_SMPTE240M = 7, ///< identical to above, also called "SMPTE C" even though it uses D65 + AVCOL_PRI_FILM = 8, ///< colour filters using Illuminant C + AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020 + AVCOL_PRI_SMPTE428 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ) + AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428, + AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) / DCI P3 + AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3 + AVCOL_PRI_EBU3213 = 22, ///< EBU Tech. 3213-E (nothing there) / one of JEDEC P22 group phosphors + AVCOL_PRI_JEDEC_P22 = AVCOL_PRI_EBU3213, + AVCOL_PRI_NB ///< Not part of ABI +}; + +/** + * Color Transfer Characteristic. + * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.2. + */ +enum AVColorTransferCharacteristic { + AVCOL_TRC_RESERVED0 = 0, + AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361 + AVCOL_TRC_UNSPECIFIED = 2, + AVCOL_TRC_RESERVED = 3, + AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG + AVCOL_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC + AVCOL_TRC_SMPTE240M = 7, + AVCOL_TRC_LINEAR = 8, ///< "Linear transfer characteristics" + AVCOL_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)" + AVCOL_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" + AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4 + AVCOL_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut + AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC) + AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10-bit system + AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12-bit system + AVCOL_TRC_SMPTE2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084, + AVCOL_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1 + AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428, + AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma" + AVCOL_TRC_NB ///< Not part of ABI +}; + +/** + * YUV colorspace type. + * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.3. + */ +enum AVColorSpace { + AVCOL_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1 + AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B + AVCOL_SPC_UNSPECIFIED = 2, + AVCOL_SPC_RESERVED = 3, ///< reserved for future use by ITU-T and ISO/IEC just like 15-255 are + AVCOL_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 + AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above + AVCOL_SPC_SMPTE240M = 7, ///< derived from 170M primaries and D65 white point, 170M is derived from BT470 System M's primaries + AVCOL_SPC_YCGCO = 8, ///< used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + AVCOL_SPC_YCOCG = AVCOL_SPC_YCGCO, + AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system + AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system + AVCOL_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x + AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system + AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system + AVCOL_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp + AVCOL_SPC_NB ///< Not part of ABI +}; + +/** + * Visual content value range. + * + * These values are based on definitions that can be found in multiple + * specifications, such as ITU-T BT.709 (3.4 - Quantization of RGB, luminance + * and colour-difference signals), ITU-T BT.2020 (Table 5 - Digital + * Representation) as well as ITU-T BT.2100 (Table 9 - Digital 10- and 12-bit + * integer representation). At the time of writing, the BT.2100 one is + * recommended, as it also defines the full range representation. + * + * Common definitions: + * - For RGB and luma planes such as Y in YCbCr and I in ICtCp, + * 'E' is the original value in range of 0.0 to 1.0. + * - For chroma planes such as Cb,Cr and Ct,Cp, 'E' is the original + * value in range of -0.5 to 0.5. + * - 'n' is the output bit depth. + * - For additional definitions such as rounding and clipping to valid n + * bit unsigned integer range, please refer to BT.2100 (Table 9). + */ +enum AVColorRange { + AVCOL_RANGE_UNSPECIFIED = 0, + + /** + * Narrow or limited range content. + * + * - For luma planes: + * + * (219 * E + 16) * 2^(n-8) + * + * F.ex. the range of 16-235 for 8 bits + * + * - For chroma planes: + * + * (224 * E + 128) * 2^(n-8) + * + * F.ex. the range of 16-240 for 8 bits + */ + AVCOL_RANGE_MPEG = 1, + + /** + * Full range content. + * + * - For RGB and luma planes: + * + * (2^n - 1) * E + * + * F.ex. the range of 0-255 for 8 bits + * + * - For chroma planes: + * + * (2^n - 1) * E + 2^(n - 1) + * + * F.ex. the range of 1-255 for 8 bits + */ + AVCOL_RANGE_JPEG = 2, + AVCOL_RANGE_NB ///< Not part of ABI +}; + +/** + * Location of chroma samples. + * + * Illustration showing the location of the first (top left) chroma sample of the + * image, the left shows only luma, the right + * shows the location of the chroma sample, the 2 could be imagined to overlay + * each other but are drawn separately due to limitations of ASCII + * + * 1st 2nd 1st 2nd horizontal luma sample positions + * v v v v + * ______ ______ + *1st luma line > |X X ... |3 4 X ... X are luma samples, + * | |1 2 1-6 are possible chroma positions + *2nd luma line > |X X ... |5 6 X ... 0 is undefined/unknown position + */ +enum AVChromaLocation { + AVCHROMA_LOC_UNSPECIFIED = 0, + AVCHROMA_LOC_LEFT = 1, ///< MPEG-2/4 4:2:0, H.264 default for 4:2:0 + AVCHROMA_LOC_CENTER = 2, ///< MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0 + AVCHROMA_LOC_TOPLEFT = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2 + AVCHROMA_LOC_TOP = 4, + AVCHROMA_LOC_BOTTOMLEFT = 5, + AVCHROMA_LOC_BOTTOM = 6, + AVCHROMA_LOC_NB ///< Not part of ABI +}; + +#endif /* AVUTIL_PIXFMT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/rational.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/rational.h new file mode 100644 index 0000000000000..cbb08a0baf16d --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/rational.h @@ -0,0 +1,220 @@ +/* + * rational numbers + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_math_rational + * Utilties for rational number calculation. + * @author Michael Niedermayer + */ + +#ifndef AVUTIL_RATIONAL_H +#define AVUTIL_RATIONAL_H + +#include +#include +#include "attributes.h" + +/** + * @defgroup lavu_math_rational AVRational + * @ingroup lavu_math + * Rational number calculation. + * + * While rational numbers can be expressed as floating-point numbers, the + * conversion process is a lossy one, so are floating-point operations. On the + * other hand, the nature of FFmpeg demands highly accurate calculation of + * timestamps. This set of rational number utilities serves as a generic + * interface for manipulating rational numbers as pairs of numerators and + * denominators. + * + * Many of the functions that operate on AVRational's have the suffix `_q`, in + * reference to the mathematical symbol "ℚ" (Q) which denotes the set of all + * rational numbers. + * + * @{ + */ + +/** + * Rational number (pair of numerator and denominator). + */ +typedef struct AVRational{ + int num; ///< Numerator + int den; ///< Denominator +} AVRational; + +/** + * Create an AVRational. + * + * Useful for compilers that do not support compound literals. + * + * @note The return value is not reduced. + * @see av_reduce() + */ +static inline AVRational av_make_q(int num, int den) +{ + AVRational r = { num, den }; + return r; +} + +/** + * Compare two rationals. + * + * @param a First rational + * @param b Second rational + * + * @return One of the following values: + * - 0 if `a == b` + * - 1 if `a > b` + * - -1 if `a < b` + * - `INT_MIN` if one of the values is of the form `0 / 0` + */ +static inline int av_cmp_q(AVRational a, AVRational b){ + const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den; + + if(tmp) return (int)((tmp ^ a.den ^ b.den)>>63)|1; + else if(b.den && a.den) return 0; + else if(a.num && b.num) return (a.num>>31) - (b.num>>31); + else return INT_MIN; +} + +/** + * Convert an AVRational to a `double`. + * @param a AVRational to convert + * @return `a` in floating-point form + * @see av_d2q() + */ +static inline double av_q2d(AVRational a){ + return a.num / (double) a.den; +} + +/** + * Reduce a fraction. + * + * This is useful for framerate calculations. + * + * @param[out] dst_num Destination numerator + * @param[out] dst_den Destination denominator + * @param[in] num Source numerator + * @param[in] den Source denominator + * @param[in] max Maximum allowed values for `dst_num` & `dst_den` + * @return 1 if the operation is exact, 0 otherwise + */ +int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max); + +/** + * Multiply two rationals. + * @param b First rational + * @param c Second rational + * @return b*c + */ +AVRational av_mul_q(AVRational b, AVRational c) av_const; + +/** + * Divide one rational by another. + * @param b First rational + * @param c Second rational + * @return b/c + */ +AVRational av_div_q(AVRational b, AVRational c) av_const; + +/** + * Add two rationals. + * @param b First rational + * @param c Second rational + * @return b+c + */ +AVRational av_add_q(AVRational b, AVRational c) av_const; + +/** + * Subtract one rational from another. + * @param b First rational + * @param c Second rational + * @return b-c + */ +AVRational av_sub_q(AVRational b, AVRational c) av_const; + +/** + * Invert a rational. + * @param q value + * @return 1 / q + */ +static av_always_inline AVRational av_inv_q(AVRational q) +{ + AVRational r = { q.den, q.num }; + return r; +} + +/** + * Convert a double precision floating point number to a rational. + * + * In case of infinity, the returned value is expressed as `{1, 0}` or + * `{-1, 0}` depending on the sign. + * + * @param d `double` to convert + * @param max Maximum allowed numerator and denominator + * @return `d` in AVRational form + * @see av_q2d() + */ +AVRational av_d2q(double d, int max) av_const; + +/** + * Find which of the two rationals is closer to another rational. + * + * @param q Rational to be compared against + * @param q1,q2 Rationals to be tested + * @return One of the following values: + * - 1 if `q1` is nearer to `q` than `q2` + * - -1 if `q2` is nearer to `q` than `q1` + * - 0 if they have the same distance + */ +int av_nearer_q(AVRational q, AVRational q1, AVRational q2); + +/** + * Find the value in a list of rationals nearest a given reference rational. + * + * @param q Reference rational + * @param q_list Array of rationals terminated by `{0, 0}` + * @return Index of the nearest value found in the array + */ +int av_find_nearest_q_idx(AVRational q, const AVRational* q_list); + +/** + * Convert an AVRational to a IEEE 32-bit `float` expressed in fixed-point + * format. + * + * @param q Rational to be converted + * @return Equivalent floating-point value, expressed as an unsigned 32-bit + * integer. + * @note The returned value is platform-indepedant. + */ +uint32_t av_q2intfloat(AVRational q); + +/** + * Return the best rational so that a and b are multiple of it. + * If the resulting denominator is larger than max_den, return def. + */ +AVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def); + +/** + * @} + */ + +#endif /* AVUTIL_RATIONAL_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/samplefmt.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/samplefmt.h new file mode 100644 index 0000000000000..1999c9bca62d3 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/samplefmt.h @@ -0,0 +1,268 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_SAMPLEFMT_H +#define AVUTIL_SAMPLEFMT_H + +#include + +/** + * @addtogroup lavu_audio + * @{ + * + * @defgroup lavu_sampfmts Audio sample formats + * + * Audio sample format enumeration and related convenience functions. + * @{ + */ + +/** + * Audio sample formats + * + * - The data described by the sample format is always in native-endian order. + * Sample values can be expressed by native C types, hence the lack of a signed + * 24-bit sample format even though it is a common raw audio data format. + * + * - The floating-point formats are based on full volume being in the range + * [-1.0, 1.0]. Any values outside this range are beyond full volume level. + * + * - The data layout as used in av_samples_fill_arrays() and elsewhere in FFmpeg + * (such as AVFrame in libavcodec) is as follows: + * + * @par + * For planar sample formats, each audio channel is in a separate data plane, + * and linesize is the buffer size, in bytes, for a single plane. All data + * planes must be the same size. For packed sample formats, only the first data + * plane is used, and samples for each channel are interleaved. In this case, + * linesize is the buffer size, in bytes, for the 1 plane. + * + */ +enum AVSampleFormat { + AV_SAMPLE_FMT_NONE = -1, + AV_SAMPLE_FMT_U8, ///< unsigned 8 bits + AV_SAMPLE_FMT_S16, ///< signed 16 bits + AV_SAMPLE_FMT_S32, ///< signed 32 bits + AV_SAMPLE_FMT_FLT, ///< float + AV_SAMPLE_FMT_DBL, ///< double + + AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar + AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar + AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar + AV_SAMPLE_FMT_FLTP, ///< float, planar + AV_SAMPLE_FMT_DBLP, ///< double, planar + AV_SAMPLE_FMT_S64, ///< signed 64 bits + AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar + + AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically +}; + +/** + * Return the name of sample_fmt, or NULL if sample_fmt is not + * recognized. + */ +const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt); + +/** + * Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE + * on error. + */ +enum AVSampleFormat av_get_sample_fmt(const char *name); + +/** + * Return the planar<->packed alternative form of the given sample format, or + * AV_SAMPLE_FMT_NONE on error. If the passed sample_fmt is already in the + * requested planar/packed format, the format returned is the same as the + * input. + */ +enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar); + +/** + * Get the packed alternative form of the given sample format. + * + * If the passed sample_fmt is already in packed format, the format returned is + * the same as the input. + * + * @return the packed alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Get the planar alternative form of the given sample format. + * + * If the passed sample_fmt is already in planar format, the format returned is + * the same as the input. + * + * @return the planar alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Generate a string corresponding to the sample format with + * sample_fmt, or a header if sample_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param sample_fmt the number of the sample format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + * @return the pointer to the filled buffer or NULL if sample_fmt is + * unknown or in case of other errors + */ +char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt); + +/** + * Return number of bytes per sample. + * + * @param sample_fmt the sample format + * @return number of bytes per sample or zero if unknown for the given + * sample format + */ +int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt); + +/** + * Check if the sample format is planar. + * + * @param sample_fmt the sample format to inspect + * @return 1 if the sample format is planar, 0 if it is interleaved + */ +int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt); + +/** + * Get the required buffer size for the given audio parameters. + * + * @param[out] linesize calculated linesize, may be NULL + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return required buffer size, or negative error code on failure + */ +int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * @} + * + * @defgroup lavu_sampmanip Samples manipulation + * + * Functions that manipulate audio samples + * @{ + */ + +/** + * Fill plane data pointers and linesize for samples with sample + * format sample_fmt. + * + * The audio_data array is filled with the pointers to the samples data planes: + * for planar, set the start point of each channel's data within the buffer, + * for packed, set the start point of the entire buffer only. + * + * The value pointed to by linesize is set to the aligned size of each + * channel's data buffer for planar layout, or to the aligned size of the + * buffer for all channels for packed layout. + * + * The buffer in buf must be big enough to contain all the samples + * (use av_samples_get_buffer_size() to compute its minimum size), + * otherwise the audio_data pointers will point to invalid data. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize calculated linesize, may be NULL + * @param buf the pointer to a buffer containing the samples + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return minimum size in bytes required for the buffer on success, + * or a negative error code on failure + */ +int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, + const uint8_t *buf, + int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a samples buffer for nb_samples samples, and fill data pointers and + * linesize accordingly. + * The allocated samples buffer can be freed by using av_freep(&audio_data[0]) + * Allocated data will be initialized to silence. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize aligned size for audio buffer(s), may be NULL + * @param nb_channels number of audio channels + * @param nb_samples number of samples per channel + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return >=0 on success or a negative error code on failure + * @todo return the size of the allocated buffer in case of success at the next bump + * @see av_samples_fill_arrays() + * @see av_samples_alloc_array_and_samples() + */ +int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a data pointers array, samples buffer for nb_samples + * samples, and fill data pointers and linesize accordingly. + * + * This is the same as av_samples_alloc(), but also allocates the data + * pointers array. + * + * @see av_samples_alloc() + */ +int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Copy samples from src to dst. + * + * @param dst destination array of pointers to data planes + * @param src source array of pointers to data planes + * @param dst_offset offset in samples at which the data will be written to dst + * @param src_offset offset in samples at which the data will be read from src + * @param nb_samples number of samples to be copied + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_copy(uint8_t **dst, uint8_t * const *src, int dst_offset, + int src_offset, int nb_samples, int nb_channels, + enum AVSampleFormat sample_fmt); + +/** + * Fill an audio buffer with silence. + * + * @param audio_data array of pointers to data planes + * @param offset offset in samples at which to start filling + * @param nb_samples number of samples to fill + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples, + int nb_channels, enum AVSampleFormat sample_fmt); + +/** + * @} + * @} + */ +#endif /* AVUTIL_SAMPLEFMT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libavutil/version.h b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/version.h new file mode 100644 index 0000000000000..87178e9e9a21f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libavutil/version.h @@ -0,0 +1,123 @@ +/* + * copyright (c) 2003 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu + * Libavutil version macros + */ + +#ifndef AVUTIL_VERSION_H +#define AVUTIL_VERSION_H + +#include "macros.h" + +/** + * @addtogroup version_utils + * + * Useful to check and match library version in order to maintain + * backward compatibility. + * + * The FFmpeg libraries follow a versioning sheme very similar to + * Semantic Versioning (http://semver.org/) + * The difference is that the component called PATCH is called MICRO in FFmpeg + * and its value is reset to 100 instead of 0 to keep it above or equal to 100. + * Also we do not increase MICRO for every bugfix or change in git master. + * + * Prior to FFmpeg 3.2 point releases did not change any lib version number to + * avoid aliassing different git master checkouts. + * Starting with FFmpeg 3.2, the released library versions will occupy + * a separate MAJOR.MINOR that is not used on the master development branch. + * That is if we branch a release of master 55.10.123 we will bump to 55.11.100 + * for the release and master will continue at 55.12.100 after it. Each new + * point release will then bump the MICRO improving the usefulness of the lib + * versions. + * + * @{ + */ + +#define AV_VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c)) +#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c +#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c) + +/** + * Extract version components from the full ::AV_VERSION_INT int as returned + * by functions like ::avformat_version() and ::avcodec_version() + */ +#define AV_VERSION_MAJOR(a) ((a) >> 16) +#define AV_VERSION_MINOR(a) (((a) & 0x00FF00) >> 8) +#define AV_VERSION_MICRO(a) ((a) & 0xFF) + +/** + * @} + */ + +/** + * @defgroup lavu_ver Version and Build diagnostics + * + * Macros and function useful to check at compiletime and at runtime + * which version of libavutil is in use. + * + * @{ + */ + +#define LIBAVUTIL_VERSION_MAJOR 57 +#define LIBAVUTIL_VERSION_MINOR 28 +#define LIBAVUTIL_VERSION_MICRO 100 + +#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT + +#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION) + +/** + * @defgroup lavu_depr_guards Deprecation Guards + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + * + * @{ + */ + +#define FF_API_D2STR (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_DECLARE_ALIGNED (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_COLORSPACE_NAME (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_AV_MALLOCZ_ARRAY (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_FIFO_PEEK2 (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_FIFO_OLD_API (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_XVMC (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_OLD_CHANNEL_LAYOUT (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_AV_FOPEN_UTF8 (LIBAVUTIL_VERSION_MAJOR < 58) + +/** + * @} + * @} + */ + +#endif /* AVUTIL_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libswscale/swscale.h b/src/framework/media/thirdparty/ffmpeg/v5/libswscale/swscale.h new file mode 100644 index 0000000000000..3ebf7c698d31a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libswscale/swscale.h @@ -0,0 +1,431 @@ +/* + * Copyright (C) 2001-2011 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_SWSCALE_H +#define SWSCALE_SWSCALE_H + +/** + * @file + * @ingroup libsws + * external API header + */ + +#include + +#include "libavutil/avutil.h" +#include "libavutil/frame.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "version.h" +#endif + +/** + * @defgroup libsws libswscale + * Color conversion and scaling library. + * + * @{ + * + * Return the LIBSWSCALE_VERSION_INT constant. + */ +unsigned swscale_version(void); + +/** + * Return the libswscale build-time configuration. + */ +const char *swscale_configuration(void); + +/** + * Return the libswscale license. + */ +const char *swscale_license(void); + +/* values for the flags, the stuff on the command line is different */ +#define SWS_FAST_BILINEAR 1 +#define SWS_BILINEAR 2 +#define SWS_BICUBIC 4 +#define SWS_X 8 +#define SWS_POINT 0x10 +#define SWS_AREA 0x20 +#define SWS_BICUBLIN 0x40 +#define SWS_GAUSS 0x80 +#define SWS_SINC 0x100 +#define SWS_LANCZOS 0x200 +#define SWS_SPLINE 0x400 + +#define SWS_SRC_V_CHR_DROP_MASK 0x30000 +#define SWS_SRC_V_CHR_DROP_SHIFT 16 + +#define SWS_PARAM_DEFAULT 123456 + +#define SWS_PRINT_INFO 0x1000 + +//the following 3 flags are not completely implemented +//internal chrominance subsampling info +#define SWS_FULL_CHR_H_INT 0x2000 +//input subsampling info +#define SWS_FULL_CHR_H_INP 0x4000 +#define SWS_DIRECT_BGR 0x8000 +#define SWS_ACCURATE_RND 0x40000 +#define SWS_BITEXACT 0x80000 +#define SWS_ERROR_DIFFUSION 0x800000 + +#define SWS_MAX_REDUCE_CUTOFF 0.002 + +#define SWS_CS_ITU709 1 +#define SWS_CS_FCC 4 +#define SWS_CS_ITU601 5 +#define SWS_CS_ITU624 5 +#define SWS_CS_SMPTE170M 5 +#define SWS_CS_SMPTE240M 7 +#define SWS_CS_DEFAULT 5 +#define SWS_CS_BT2020 9 + +/** + * Return a pointer to yuv<->rgb coefficients for the given colorspace + * suitable for sws_setColorspaceDetails(). + * + * @param colorspace One of the SWS_CS_* macros. If invalid, + * SWS_CS_DEFAULT is used. + */ +const int *sws_getCoefficients(int colorspace); + +// when used for filters they must have an odd number of elements +// coeffs cannot be shared between vectors +typedef struct SwsVector { + double *coeff; ///< pointer to the list of coefficients + int length; ///< number of coefficients in the vector +} SwsVector; + +// vectors can be shared +typedef struct SwsFilter { + SwsVector *lumH; + SwsVector *lumV; + SwsVector *chrH; + SwsVector *chrV; +} SwsFilter; + +struct SwsContext; + +/** + * Return a positive value if pix_fmt is a supported input format, 0 + * otherwise. + */ +int sws_isSupportedInput(enum AVPixelFormat pix_fmt); + +/** + * Return a positive value if pix_fmt is a supported output format, 0 + * otherwise. + */ +int sws_isSupportedOutput(enum AVPixelFormat pix_fmt); + +/** + * @param[in] pix_fmt the pixel format + * @return a positive value if an endianness conversion for pix_fmt is + * supported, 0 otherwise. + */ +int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt); + +/** + * Allocate an empty SwsContext. This must be filled and passed to + * sws_init_context(). For filling see AVOptions, options.c and + * sws_setColorspaceDetails(). + */ +struct SwsContext *sws_alloc_context(void); + +/** + * Initialize the swscaler context sws_context. + * + * @return zero or positive value on success, a negative value on + * error + */ +av_warn_unused_result +int sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter); + +/** + * Free the swscaler context swsContext. + * If swsContext is NULL, then does nothing. + */ +void sws_freeContext(struct SwsContext *swsContext); + +/** + * Allocate and return an SwsContext. You need it to perform + * scaling/conversion operations using sws_scale(). + * + * @param srcW the width of the source image + * @param srcH the height of the source image + * @param srcFormat the source image format + * @param dstW the width of the destination image + * @param dstH the height of the destination image + * @param dstFormat the destination image format + * @param flags specify which algorithm and options to use for rescaling + * @param param extra parameters to tune the used scaler + * For SWS_BICUBIC param[0] and [1] tune the shape of the basis + * function, param[0] tunes f(1) and param[1] f´(1) + * For SWS_GAUSS param[0] tunes the exponent and thus cutoff + * frequency + * For SWS_LANCZOS param[0] tunes the width of the window function + * @return a pointer to an allocated context, or NULL in case of error + * @note this function is to be removed after a saner alternative is + * written + */ +struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, + int dstW, int dstH, enum AVPixelFormat dstFormat, + int flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param); + +/** + * Scale the image slice in srcSlice and put the resulting scaled + * slice in the image in dst. A slice is a sequence of consecutive + * rows in an image. + * + * Slices have to be provided in sequential order, either in + * top-bottom or bottom-top order. If slices are provided in + * non-sequential order the behavior of the function is undefined. + * + * @param c the scaling context previously created with + * sws_getContext() + * @param srcSlice the array containing the pointers to the planes of + * the source slice + * @param srcStride the array containing the strides for each plane of + * the source image + * @param srcSliceY the position in the source image of the slice to + * process, that is the number (counted starting from + * zero) in the image of the first row of the slice + * @param srcSliceH the height of the source slice, that is the number + * of rows in the slice + * @param dst the array containing the pointers to the planes of + * the destination image + * @param dstStride the array containing the strides for each plane of + * the destination image + * @return the height of the output slice + */ +int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], + const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *const dst[], const int dstStride[]); + +/** + * Scale source data from src and write the output to dst. + * + * This is merely a convenience wrapper around + * - sws_frame_start() + * - sws_send_slice(0, src->height) + * - sws_receive_slice(0, dst->height) + * - sws_frame_end() + * + * @param dst The destination frame. See documentation for sws_frame_start() for + * more details. + * @param src The source frame. + * + * @return 0 on success, a negative AVERROR code on failure + */ +int sws_scale_frame(struct SwsContext *c, AVFrame *dst, const AVFrame *src); + +/** + * Initialize the scaling process for a given pair of source/destination frames. + * Must be called before any calls to sws_send_slice() and sws_receive_slice(). + * + * This function will retain references to src and dst, so they must both use + * refcounted buffers (if allocated by the caller, in case of dst). + * + * @param dst The destination frame. + * + * The data buffers may either be already allocated by the caller or + * left clear, in which case they will be allocated by the scaler. + * The latter may have performance advantages - e.g. in certain cases + * some output planes may be references to input planes, rather than + * copies. + * + * Output data will be written into this frame in successful + * sws_receive_slice() calls. + * @param src The source frame. The data buffers must be allocated, but the + * frame data does not have to be ready at this point. Data + * availability is then signalled by sws_send_slice(). + * @return 0 on success, a negative AVERROR code on failure + * + * @see sws_frame_end() + */ +int sws_frame_start(struct SwsContext *c, AVFrame *dst, const AVFrame *src); + +/** + * Finish the scaling process for a pair of source/destination frames previously + * submitted with sws_frame_start(). Must be called after all sws_send_slice() + * and sws_receive_slice() calls are done, before any new sws_frame_start() + * calls. + */ +void sws_frame_end(struct SwsContext *c); + +/** + * Indicate that a horizontal slice of input data is available in the source + * frame previously provided to sws_frame_start(). The slices may be provided in + * any order, but may not overlap. For vertically subsampled pixel formats, the + * slices must be aligned according to subsampling. + * + * @param slice_start first row of the slice + * @param slice_height number of rows in the slice + * + * @return a non-negative number on success, a negative AVERROR code on failure. + */ +int sws_send_slice(struct SwsContext *c, unsigned int slice_start, + unsigned int slice_height); + +/** + * Request a horizontal slice of the output data to be written into the frame + * previously provided to sws_frame_start(). + * + * @param slice_start first row of the slice; must be a multiple of + * sws_receive_slice_alignment() + * @param slice_height number of rows in the slice; must be a multiple of + * sws_receive_slice_alignment(), except for the last slice + * (i.e. when slice_start+slice_height is equal to output + * frame height) + * + * @return a non-negative number if the data was successfully written into the output + * AVERROR(EAGAIN) if more input data needs to be provided before the + * output can be produced + * another negative AVERROR code on other kinds of scaling failure + */ +int sws_receive_slice(struct SwsContext *c, unsigned int slice_start, + unsigned int slice_height); + +/** + * @return alignment required for output slices requested with sws_receive_slice(). + * Slice offsets and sizes passed to sws_receive_slice() must be + * multiples of the value returned from this function. + */ +unsigned int sws_receive_slice_alignment(const struct SwsContext *c); + +/** + * @param dstRange flag indicating the while-black range of the output (1=jpeg / 0=mpeg) + * @param srcRange flag indicating the while-black range of the input (1=jpeg / 0=mpeg) + * @param table the yuv2rgb coefficients describing the output yuv space, normally ff_yuv2rgb_coeffs[x] + * @param inv_table the yuv2rgb coefficients describing the input yuv space, normally ff_yuv2rgb_coeffs[x] + * @param brightness 16.16 fixed point brightness correction + * @param contrast 16.16 fixed point contrast correction + * @param saturation 16.16 fixed point saturation correction +#if LIBSWSCALE_VERSION_MAJOR > 6 + * @return negative error code on error, non negative otherwise +#else + * @return -1 if not supported +#endif + */ +int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], + int srcRange, const int table[4], int dstRange, + int brightness, int contrast, int saturation); + +/** +#if LIBSWSCALE_VERSION_MAJOR > 6 + * @return negative error code on error, non negative otherwise +#else + * @return -1 if not supported +#endif + */ +int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table, + int *srcRange, int **table, int *dstRange, + int *brightness, int *contrast, int *saturation); + +/** + * Allocate and return an uninitialized vector with length coefficients. + */ +SwsVector *sws_allocVec(int length); + +/** + * Return a normalized Gaussian curve used to filter stuff + * quality = 3 is high quality, lower is lower quality. + */ +SwsVector *sws_getGaussianVec(double variance, double quality); + +/** + * Scale all the coefficients of a by the scalar value. + */ +void sws_scaleVec(SwsVector *a, double scalar); + +/** + * Scale all the coefficients of a so that their sum equals height. + */ +void sws_normalizeVec(SwsVector *a, double height); + +void sws_freeVec(SwsVector *a); + +SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, + float lumaSharpen, float chromaSharpen, + float chromaHShift, float chromaVShift, + int verbose); +void sws_freeFilter(SwsFilter *filter); + +/** + * Check if context can be reused, otherwise reallocate a new one. + * + * If context is NULL, just calls sws_getContext() to get a new + * context. Otherwise, checks if the parameters are the ones already + * saved in context. If that is the case, returns the current + * context. Otherwise, frees context and gets a new context with + * the new parameters. + * + * Be warned that srcFilter and dstFilter are not checked, they + * are assumed to remain the same. + */ +struct SwsContext *sws_getCachedContext(struct SwsContext *context, + int srcW, int srcH, enum AVPixelFormat srcFormat, + int dstW, int dstH, enum AVPixelFormat dstFormat, + int flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 32 bits. + * + * The output frame will have the same packed format as the palette. + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 24 bits. + * + * With the palette format "ABCD", the destination frame ends up with the format "ABC". + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Get the AVClass for swsContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *sws_get_class(void); + +/** + * @} + */ + +#endif /* SWSCALE_SWSCALE_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libswscale/version.h b/src/framework/media/thirdparty/ffmpeg/v5/libswscale/version.h new file mode 100644 index 0000000000000..4c6af261e6852 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libswscale/version.h @@ -0,0 +1,44 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_VERSION_H +#define SWSCALE_VERSION_H + +/** + * @file + * swscale version macros + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBSWSCALE_VERSION_MINOR 7 +#define LIBSWSCALE_VERSION_MICRO 100 + +#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_VERSION AV_VERSION(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_BUILD LIBSWSCALE_VERSION_INT + +#define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION) + +#endif /* SWSCALE_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libswscale/version_major.h b/src/framework/media/thirdparty/ffmpeg/v5/libswscale/version_major.h new file mode 100644 index 0000000000000..2f8418780cdb2 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libswscale/version_major.h @@ -0,0 +1,35 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_VERSION_MAJOR_H +#define SWSCALE_VERSION_MAJOR_H + +/** + * @file + * swscale version macros + */ + +#define LIBSWSCALE_VERSION_MAJOR 6 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + */ + +#endif /* SWSCALE_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/avcodec.h b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/avcodec.h new file mode 100644 index 0000000000000..7fb44e28f4581 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/avcodec.h @@ -0,0 +1,3154 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AVCODEC_H +#define AVCODEC_AVCODEC_H + +/** + * @file + * @ingroup libavc + * Libavcodec external API header + */ + +#include "libavutil/samplefmt.h" +#include "libavutil/attributes.h" +#include "libavutil/avutil.h" +#include "libavutil/buffer.h" +#include "libavutil/channel_layout.h" +#include "libavutil/dict.h" +#include "libavutil/frame.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +#include "codec.h" +#include "codec_id.h" +#include "defs.h" +#include "packet.h" +#include "version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "version.h" + +#include "codec_desc.h" +#include "codec_par.h" +#endif + +struct AVCodecParameters; + +/** + * @defgroup libavc libavcodec + * Encoding/Decoding Library + * + * @{ + * + * @defgroup lavc_decoding Decoding + * @{ + * @} + * + * @defgroup lavc_encoding Encoding + * @{ + * @} + * + * @defgroup lavc_codec Codecs + * @{ + * @defgroup lavc_codec_native Native Codecs + * @{ + * @} + * @defgroup lavc_codec_wrappers External library wrappers + * @{ + * @} + * @defgroup lavc_codec_hwaccel Hardware Accelerators bridge + * @{ + * @} + * @} + * @defgroup lavc_internal Internal + * @{ + * @} + * @} + */ + +/** + * @ingroup libavc + * @defgroup lavc_encdec send/receive encoding and decoding API overview + * @{ + * + * The avcodec_send_packet()/avcodec_receive_frame()/avcodec_send_frame()/ + * avcodec_receive_packet() functions provide an encode/decode API, which + * decouples input and output. + * + * The API is very similar for encoding/decoding and audio/video, and works as + * follows: + * - Set up and open the AVCodecContext as usual. + * - Send valid input: + * - For decoding, call avcodec_send_packet() to give the decoder raw + * compressed data in an AVPacket. + * - For encoding, call avcodec_send_frame() to give the encoder an AVFrame + * containing uncompressed audio or video. + * + * In both cases, it is recommended that AVPackets and AVFrames are + * refcounted, or libavcodec might have to copy the input data. (libavformat + * always returns refcounted AVPackets, and av_frame_get_buffer() allocates + * refcounted AVFrames.) + * - Receive output in a loop. Periodically call one of the avcodec_receive_*() + * functions and process their output: + * - For decoding, call avcodec_receive_frame(). On success, it will return + * an AVFrame containing uncompressed audio or video data. + * - For encoding, call avcodec_receive_packet(). On success, it will return + * an AVPacket with a compressed frame. + * + * Repeat this call until it returns AVERROR(EAGAIN) or an error. The + * AVERROR(EAGAIN) return value means that new input data is required to + * return new output. In this case, continue with sending input. For each + * input frame/packet, the codec will typically return 1 output frame/packet, + * but it can also be 0 or more than 1. + * + * At the beginning of decoding or encoding, the codec might accept multiple + * input frames/packets without returning a frame, until its internal buffers + * are filled. This situation is handled transparently if you follow the steps + * outlined above. + * + * In theory, sending input can result in EAGAIN - this should happen only if + * not all output was received. You can use this to structure alternative decode + * or encode loops other than the one suggested above. For example, you could + * try sending new input on each iteration, and try to receive output if that + * returns EAGAIN. + * + * End of stream situations. These require "flushing" (aka draining) the codec, + * as the codec might buffer multiple frames or packets internally for + * performance or out of necessity (consider B-frames). + * This is handled as follows: + * - Instead of valid input, send NULL to the avcodec_send_packet() (decoding) + * or avcodec_send_frame() (encoding) functions. This will enter draining + * mode. + * - Call avcodec_receive_frame() (decoding) or avcodec_receive_packet() + * (encoding) in a loop until AVERROR_EOF is returned. The functions will + * not return AVERROR(EAGAIN), unless you forgot to enter draining mode. + * - Before decoding can be resumed again, the codec has to be reset with + * avcodec_flush_buffers(). + * + * Using the API as outlined above is highly recommended. But it is also + * possible to call functions outside of this rigid schema. For example, you can + * call avcodec_send_packet() repeatedly without calling + * avcodec_receive_frame(). In this case, avcodec_send_packet() will succeed + * until the codec's internal buffer has been filled up (which is typically of + * size 1 per output frame, after initial input), and then reject input with + * AVERROR(EAGAIN). Once it starts rejecting input, you have no choice but to + * read at least some output. + * + * Not all codecs will follow a rigid and predictable dataflow; the only + * guarantee is that an AVERROR(EAGAIN) return value on a send/receive call on + * one end implies that a receive/send call on the other end will succeed, or + * at least will not fail with AVERROR(EAGAIN). In general, no codec will + * permit unlimited buffering of input or output. + * + * A codec is not allowed to return AVERROR(EAGAIN) for both sending and receiving. This + * would be an invalid state, which could put the codec user into an endless + * loop. The API has no concept of time either: it cannot happen that trying to + * do avcodec_send_packet() results in AVERROR(EAGAIN), but a repeated call 1 second + * later accepts the packet (with no other receive/flush API calls involved). + * The API is a strict state machine, and the passage of time is not supposed + * to influence it. Some timing-dependent behavior might still be deemed + * acceptable in certain cases. But it must never result in both send/receive + * returning EAGAIN at the same time at any point. It must also absolutely be + * avoided that the current state is "unstable" and can "flip-flop" between + * the send/receive APIs allowing progress. For example, it's not allowed that + * the codec randomly decides that it actually wants to consume a packet now + * instead of returning a frame, after it just returned AVERROR(EAGAIN) on an + * avcodec_send_packet() call. + * @} + */ + +/** + * @defgroup lavc_core Core functions/structures. + * @ingroup libavc + * + * Basic definitions, functions for querying libavcodec capabilities, + * allocating core structures, etc. + * @{ + */ + +/** + * @ingroup lavc_encoding + * minimum encoding buffer size + * Used to avoid some checks during header writing. + */ +#define AV_INPUT_BUFFER_MIN_SIZE 16384 + +/** + * @ingroup lavc_encoding + */ +typedef struct RcOverride{ + int start_frame; + int end_frame; + int qscale; // If this is 0 then quality_factor will be used instead. + float quality_factor; +} RcOverride; + +/* encoding support + These flags can be passed in AVCodecContext.flags before initialization. + Note: Not everything is supported yet. +*/ + +/** + * Allow decoders to produce frames with data planes that are not aligned + * to CPU requirements (e.g. due to cropping). + */ +#define AV_CODEC_FLAG_UNALIGNED (1 << 0) +/** + * Use fixed qscale. + */ +#define AV_CODEC_FLAG_QSCALE (1 << 1) +/** + * 4 MV per MB allowed / advanced prediction for H.263. + */ +#define AV_CODEC_FLAG_4MV (1 << 2) +/** + * Output even those frames that might be corrupted. + */ +#define AV_CODEC_FLAG_OUTPUT_CORRUPT (1 << 3) +/** + * Use qpel MC. + */ +#define AV_CODEC_FLAG_QPEL (1 << 4) +#if FF_API_DROPCHANGED +/** + * Don't output frames whose parameters differ from first + * decoded frame in stream. + * + * @deprecated callers should implement this functionality in their own code + */ +#define AV_CODEC_FLAG_DROPCHANGED (1 << 5) +#endif +/** + * Request the encoder to output reconstructed frames, i.e.\ frames that would + * be produced by decoding the encoded bistream. These frames may be retrieved + * by calling avcodec_receive_frame() immediately after a successful call to + * avcodec_receive_packet(). + * + * Should only be used with encoders flagged with the + * @ref AV_CODEC_CAP_ENCODER_RECON_FRAME capability. + * + * @note + * Each reconstructed frame returned by the encoder corresponds to the last + * encoded packet, i.e. the frames are returned in coded order rather than + * presentation order. + * + * @note + * Frame parameters (like pixel format or dimensions) do not have to match the + * AVCodecContext values. Make sure to use the values from the returned frame. + */ +#define AV_CODEC_FLAG_RECON_FRAME (1 << 6) +/** + * @par decoding + * Request the decoder to propagate each packet's AVPacket.opaque and + * AVPacket.opaque_ref to its corresponding output AVFrame. + * + * @par encoding: + * Request the encoder to propagate each frame's AVFrame.opaque and + * AVFrame.opaque_ref values to its corresponding output AVPacket. + * + * @par + * May only be set on encoders that have the + * @ref AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability flag. + * + * @note + * While in typical cases one input frame produces exactly one output packet + * (perhaps after a delay), in general the mapping of frames to packets is + * M-to-N, so + * - Any number of input frames may be associated with any given output packet. + * This includes zero - e.g. some encoders may output packets that carry only + * metadata about the whole stream. + * - A given input frame may be associated with any number of output packets. + * Again this includes zero - e.g. some encoders may drop frames under certain + * conditions. + * . + * This implies that when using this flag, the caller must NOT assume that + * - a given input frame's opaques will necessarily appear on some output packet; + * - every output packet will have some non-NULL opaque value. + * . + * When an output packet contains multiple frames, the opaque values will be + * taken from the first of those. + * + * @note + * The converse holds for decoders, with frames and packets switched. + */ +#define AV_CODEC_FLAG_COPY_OPAQUE (1 << 7) +/** + * Signal to the encoder that the values of AVFrame.duration are valid and + * should be used (typically for transferring them to output packets). + * + * If this flag is not set, frame durations are ignored. + */ +#define AV_CODEC_FLAG_FRAME_DURATION (1 << 8) +/** + * Use internal 2pass ratecontrol in first pass mode. + */ +#define AV_CODEC_FLAG_PASS1 (1 << 9) +/** + * Use internal 2pass ratecontrol in second pass mode. + */ +#define AV_CODEC_FLAG_PASS2 (1 << 10) +/** + * loop filter. + */ +#define AV_CODEC_FLAG_LOOP_FILTER (1 << 11) +/** + * Only decode/encode grayscale. + */ +#define AV_CODEC_FLAG_GRAY (1 << 13) +/** + * error[?] variables will be set during encoding. + */ +#define AV_CODEC_FLAG_PSNR (1 << 15) +/** + * Use interlaced DCT. + */ +#define AV_CODEC_FLAG_INTERLACED_DCT (1 << 18) +/** + * Force low delay. + */ +#define AV_CODEC_FLAG_LOW_DELAY (1 << 19) +/** + * Place global headers in extradata instead of every keyframe. + */ +#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22) +/** + * Use only bitexact stuff (except (I)DCT). + */ +#define AV_CODEC_FLAG_BITEXACT (1 << 23) +/* Fx : Flag for H.263+ extra options */ +/** + * H.263 advanced intra coding / MPEG-4 AC prediction + */ +#define AV_CODEC_FLAG_AC_PRED (1 << 24) +/** + * interlaced motion estimation + */ +#define AV_CODEC_FLAG_INTERLACED_ME (1 << 29) +#define AV_CODEC_FLAG_CLOSED_GOP (1U << 31) + +/** + * Allow non spec compliant speedup tricks. + */ +#define AV_CODEC_FLAG2_FAST (1 << 0) +/** + * Skip bitstream encoding. + */ +#define AV_CODEC_FLAG2_NO_OUTPUT (1 << 2) +/** + * Place global headers at every keyframe instead of in extradata. + */ +#define AV_CODEC_FLAG2_LOCAL_HEADER (1 << 3) + +/** + * Input bitstream might be truncated at a packet boundaries + * instead of only at frame boundaries. + */ +#define AV_CODEC_FLAG2_CHUNKS (1 << 15) +/** + * Discard cropping information from SPS. + */ +#define AV_CODEC_FLAG2_IGNORE_CROP (1 << 16) + +/** + * Show all frames before the first keyframe + */ +#define AV_CODEC_FLAG2_SHOW_ALL (1 << 22) +/** + * Export motion vectors through frame side data + */ +#define AV_CODEC_FLAG2_EXPORT_MVS (1 << 28) +/** + * Do not skip samples and export skip information as frame side data + */ +#define AV_CODEC_FLAG2_SKIP_MANUAL (1 << 29) +/** + * Do not reset ASS ReadOrder field on flush (subtitles decoding) + */ +#define AV_CODEC_FLAG2_RO_FLUSH_NOOP (1 << 30) +/** + * Generate/parse ICC profiles on encode/decode, as appropriate for the type of + * file. No effect on codecs which cannot contain embedded ICC profiles, or + * when compiled without support for lcms2. + */ +#define AV_CODEC_FLAG2_ICC_PROFILES (1U << 31) + +/* Exported side data. + These flags can be passed in AVCodecContext.export_side_data before initialization. +*/ +/** + * Export motion vectors through frame side data + */ +#define AV_CODEC_EXPORT_DATA_MVS (1 << 0) +/** + * Export encoder Producer Reference Time through packet side data + */ +#define AV_CODEC_EXPORT_DATA_PRFT (1 << 1) +/** + * Decoding only. + * Export the AVVideoEncParams structure through frame side data. + */ +#define AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS (1 << 2) +/** + * Decoding only. + * Do not apply film grain, export it instead. + */ +#define AV_CODEC_EXPORT_DATA_FILM_GRAIN (1 << 3) + +/** + * The decoder will keep a reference to the frame and may reuse it later. + */ +#define AV_GET_BUFFER_FLAG_REF (1 << 0) + +/** + * The encoder will keep a reference to the packet and may reuse it later. + */ +#define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0) + +/** + * main external API structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * You can use AVOptions (av_opt* / av_set/get*()) to access these fields from user + * applications. + * The name string for AVOptions options matches the associated command line + * parameter name and can be found in libavcodec/options_table.h + * The AVOption/command line parameter names differ in some cases from the C + * structure field names for historic reasons or brevity. + * sizeof(AVCodecContext) must not be used outside libav*. + */ +typedef struct AVCodecContext { + /** + * information on struct for av_log + * - set by avcodec_alloc_context3 + */ + const AVClass *av_class; + int log_level_offset; + + enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ + const struct AVCodec *codec; + enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ + + /** + * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * This is used to work around some encoder bugs. + * A demuxer should set this to what is stored in the field used to identify the codec. + * If there are multiple such fields in a container then the demuxer should choose the one + * which maximizes the information about the used codec. + * If the codec tag field in a container is larger than 32 bits then the demuxer should + * remap the longer ID to 32 bits with a table or other structure. Alternatively a new + * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated + * first. + * - encoding: Set by user, if not then the default based on codec_id will be used. + * - decoding: Set by user, will be converted to uppercase by libavcodec during init. + */ + unsigned int codec_tag; + + void *priv_data; + + /** + * Private context used for internal data. + * + * Unlike priv_data, this is not codec-specific. It is used in general + * libavcodec functions. + */ + struct AVCodecInternal *internal; + + /** + * Private data of the user, can be used to carry app specific stuff. + * - encoding: Set by user. + * - decoding: Set by user. + */ + void *opaque; + + /** + * the average bitrate + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: Set by user, may be overwritten by libavcodec + * if this info is available in the stream + */ + int64_t bit_rate; + + /** + * number of bits the bitstream is allowed to diverge from the reference. + * the reference can be CBR (for CBR pass1) or VBR (for pass2) + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: unused + */ + int bit_rate_tolerance; + + /** + * Global quality for codecs which cannot change it per frame. + * This should be proportional to MPEG-1/2/4 qscale. + * - encoding: Set by user. + * - decoding: unused + */ + int global_quality; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int compression_level; +#define FF_COMPRESSION_DEFAULT -1 + + /** + * AV_CODEC_FLAG_*. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags; + + /** + * AV_CODEC_FLAG2_* + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags2; + + /** + * some codecs need / can use extradata like Huffman tables. + * MJPEG: Huffman tables + * rv10: additional flags + * MPEG-4: global headers (they can be in the bitstream or here) + * The allocated memory should be AV_INPUT_BUFFER_PADDING_SIZE bytes larger + * than extradata_size to avoid problems if it is read with the bitstream reader. + * The bytewise contents of extradata must not depend on the architecture or CPU endianness. + * Must be allocated with the av_malloc() family of functions. + * - encoding: Set/allocated/freed by libavcodec. + * - decoding: Set/allocated/freed by user. + */ + uint8_t *extradata; + int extradata_size; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. For fixed-fps content, + * timebase should be 1/framerate and timestamp increments should be + * identically 1. + * This often, but not always is the inverse of the frame rate or field rate + * for video. 1/time_base is not the average frame rate if the frame rate is not + * constant. + * + * Like containers, elementary streams also can store timestamps, 1/time_base + * is the unit in which these timestamps are specified. + * As example of such codec time base see ISO/IEC 14496-2:2001(E) + * vop_time_increment_resolution and fixed_vop_rate + * (fixed_vop_rate == 0 implies that it is different from the framerate) + * + * - encoding: MUST be set by user. + * - decoding: unused. + */ + AVRational time_base; + +#if FF_API_TICKS_PER_FRAME + /** + * For some codecs, the time base is closer to the field rate than the frame rate. + * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration + * if no telecine is used ... + * + * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. + * + * @deprecated + * - decoding: Use AVCodecDescriptor.props & AV_CODEC_PROP_FIELDS + * - encoding: Set AVCodecContext.framerate instead + * + */ + attribute_deprecated + int ticks_per_frame; +#endif + + /** + * Codec delay. + * + * Encoding: Number of frames delay there will be from the encoder input to + * the decoder output. (we assume the decoder matches the spec) + * Decoding: Number of frames delay in addition to what a standard decoder + * as specified in the spec would produce. + * + * Video: + * Number of frames the decoded output will be delayed relative to the + * encoded input. + * + * Audio: + * For encoding, this field is unused (see initial_padding). + * + * For decoding, this is the number of samples the decoder needs to + * output before the decoder's output is valid. When seeking, you should + * start decoding this many samples prior to your desired seek point. + * + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int delay; + + + /* video only */ + /** + * picture width / height. + * + * @note Those fields may not match the values of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: MUST be set by user. + * - decoding: May be set by the user before opening the decoder if known e.g. + * from the container. Some decoders will require the dimensions + * to be set by the caller. During decoding, the decoder may + * overwrite those values as required while parsing the data. + */ + int width, height; + + /** + * Bitstream width / height, may be different from width/height e.g. when + * the decoded frame is cropped before being output or lowres is enabled. + * + * @note Those field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: unused + * - decoding: May be set by the user before opening the decoder if known + * e.g. from the container. During decoding, the decoder may + * overwrite those values as required while parsing the data. + */ + int coded_width, coded_height; + + /** + * the number of pictures in a group of pictures, or 0 for intra_only + * - encoding: Set by user. + * - decoding: unused + */ + int gop_size; + + /** + * Pixel format, see AV_PIX_FMT_xxx. + * May be set by the demuxer if known from headers. + * May be overridden by the decoder if it knows better. + * + * @note This field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: Set by user. + * - decoding: Set by user if known, overridden by libavcodec while + * parsing the data. + */ + enum AVPixelFormat pix_fmt; + + /** + * If non NULL, 'draw_horiz_band' is called by the libavcodec + * decoder to draw a horizontal band. It improves cache usage. Not + * all codecs can do that. You must check the codec capabilities + * beforehand. + * When multithreading is used, it may be called from multiple threads + * at the same time; threads might draw different parts of the same AVFrame, + * or multiple AVFrames, and there is no guarantee that slices will be drawn + * in order. + * The function is also used by hardware acceleration APIs. + * It is called at least once during frame decoding to pass + * the data needed for hardware render. + * In that mode instead of pixel data, AVFrame points to + * a structure specific to the acceleration API. The application + * reads the structure and can change some fields to indicate progress + * or mark state. + * - encoding: unused + * - decoding: Set by user. + * @param height the height of the slice + * @param y the y position of the slice + * @param type 1->top field, 2->bottom field, 3->frame + * @param offset offset into the AVFrame.data from which the slice should be read + */ + void (*draw_horiz_band)(struct AVCodecContext *s, + const AVFrame *src, int offset[AV_NUM_DATA_POINTERS], + int y, int type, int height); + + /** + * Callback to negotiate the pixel format. Decoding only, may be set by the + * caller before avcodec_open2(). + * + * Called by some decoders to select the pixel format that will be used for + * the output frames. This is mainly used to set up hardware acceleration, + * then the provided format list contains the corresponding hwaccel pixel + * formats alongside the "software" one. The software pixel format may also + * be retrieved from \ref sw_pix_fmt. + * + * This callback will be called when the coded frame properties (such as + * resolution, pixel format, etc.) change and more than one output format is + * supported for those new properties. If a hardware pixel format is chosen + * and initialization for it fails, the callback may be called again + * immediately. + * + * This callback may be called from different threads if the decoder is + * multi-threaded, but not from more than one thread simultaneously. + * + * @param fmt list of formats which may be used in the current + * configuration, terminated by AV_PIX_FMT_NONE. + * @warning Behavior is undefined if the callback returns a value other + * than one of the formats in fmt or AV_PIX_FMT_NONE. + * @return the chosen format or AV_PIX_FMT_NONE + */ + enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + + /** + * maximum number of B-frames between non-B-frames + * Note: The output will be delayed by max_b_frames+1 relative to the input. + * - encoding: Set by user. + * - decoding: unused + */ + int max_b_frames; + + /** + * qscale factor between IP and B-frames + * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_factor; + + /** + * qscale offset between IP and B-frames + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_offset; + + /** + * Size of the frame reordering buffer in the decoder. + * For MPEG-2 it is 1 IPB or 0 low delay IP. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int has_b_frames; + + /** + * qscale factor between P- and I-frames + * If > 0 then the last P-frame quantizer will be used (q = lastp_q * factor + offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_factor; + + /** + * qscale offset between P and I-frames + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_offset; + + /** + * luminance masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float lumi_masking; + + /** + * temporary complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float temporal_cplx_masking; + + /** + * spatial complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float spatial_cplx_masking; + + /** + * p block masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float p_masking; + + /** + * darkness masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float dark_masking; + +#if FF_API_SLICE_OFFSET + /** + * slice count + * - encoding: Set by libavcodec. + * - decoding: Set by user (or 0). + */ + attribute_deprecated + int slice_count; + + /** + * slice offsets in the frame in bytes + * - encoding: Set/allocated by libavcodec. + * - decoding: Set/allocated by user (or NULL). + */ + attribute_deprecated + int *slice_offset; +#endif + + /** + * sample aspect ratio (0 if unknown) + * That is the width of a pixel divided by the height of the pixel. + * Numerator and denominator must be relatively prime and smaller than 256 for some video standards. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVRational sample_aspect_ratio; + + /** + * motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_cmp; + /** + * subpixel motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_sub_cmp; + /** + * macroblock comparison function (not supported yet) + * - encoding: Set by user. + * - decoding: unused + */ + int mb_cmp; + /** + * interlaced DCT comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int ildct_cmp; +#define FF_CMP_SAD 0 +#define FF_CMP_SSE 1 +#define FF_CMP_SATD 2 +#define FF_CMP_DCT 3 +#define FF_CMP_PSNR 4 +#define FF_CMP_BIT 5 +#define FF_CMP_RD 6 +#define FF_CMP_ZERO 7 +#define FF_CMP_VSAD 8 +#define FF_CMP_VSSE 9 +#define FF_CMP_NSSE 10 +#define FF_CMP_W53 11 +#define FF_CMP_W97 12 +#define FF_CMP_DCTMAX 13 +#define FF_CMP_DCT264 14 +#define FF_CMP_MEDIAN_SAD 15 +#define FF_CMP_CHROMA 256 + + /** + * ME diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int dia_size; + + /** + * amount of previous MV predictors (2a+1 x 2a+1 square) + * - encoding: Set by user. + * - decoding: unused + */ + int last_predictor_count; + + /** + * motion estimation prepass comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_pre_cmp; + + /** + * ME prepass diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int pre_dia_size; + + /** + * subpel ME quality + * - encoding: Set by user. + * - decoding: unused + */ + int me_subpel_quality; + + /** + * maximum motion estimation search range in subpel units + * If 0 then no limit. + * + * - encoding: Set by user. + * - decoding: unused + */ + int me_range; + + /** + * slice flags + * - encoding: unused + * - decoding: Set by user. + */ + int slice_flags; +#define SLICE_FLAG_CODED_ORDER 0x0001 ///< draw_horiz_band() is called in coded order instead of display +#define SLICE_FLAG_ALLOW_FIELD 0x0002 ///< allow draw_horiz_band() with field slices (MPEG-2 field pics) +#define SLICE_FLAG_ALLOW_PLANE 0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1) + + /** + * macroblock decision mode + * - encoding: Set by user. + * - decoding: unused + */ + int mb_decision; +#define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp +#define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits +#define FF_MB_DECISION_RD 2 ///< rate distortion + + /** + * custom intra quantization matrix + * Must be allocated with the av_malloc() family of functions, and will be freed in + * avcodec_free_context(). + * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL. + * - decoding: Set/allocated/freed by libavcodec. + */ + uint16_t *intra_matrix; + + /** + * custom inter quantization matrix + * Must be allocated with the av_malloc() family of functions, and will be freed in + * avcodec_free_context(). + * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL. + * - decoding: Set/allocated/freed by libavcodec. + */ + uint16_t *inter_matrix; + + /** + * precision of the intra DC coefficient - 8 + * - encoding: Set by user. + * - decoding: Set by libavcodec + */ + int intra_dc_precision; + + /** + * Number of macroblock rows at the top which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_top; + + /** + * Number of macroblock rows at the bottom which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_bottom; + + /** + * minimum MB Lagrange multiplier + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmin; + + /** + * maximum MB Lagrange multiplier + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmax; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int bidir_refine; + + /** + * minimum GOP size + * - encoding: Set by user. + * - decoding: unused + */ + int keyint_min; + + /** + * number of reference frames + * - encoding: Set by user. + * - decoding: Set by lavc. + */ + int refs; + + /** + * Note: Value depends upon the compare function used for fullpel ME. + * - encoding: Set by user. + * - decoding: unused + */ + int mv0_threshold; + + /** + * Chromaticity coordinates of the source primaries. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorPrimaries color_primaries; + + /** + * Color Transfer Characteristic. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user to override the default output color range value, + * If not specified, libavcodec sets the color range depending on the + * output format. + * - decoding: Set by libavcodec, can be set by the user to propagate the + * color range to components reading from the decoder context. + */ + enum AVColorRange color_range; + + /** + * This defines the location of chroma samples. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVChromaLocation chroma_sample_location; + + /** + * Number of slices. + * Indicates number of picture subdivisions. Used for parallelized + * decoding. + * - encoding: Set by user + * - decoding: unused + */ + int slices; + + /** Field order + * - encoding: set by libavcodec + * - decoding: Set by user. + */ + enum AVFieldOrder field_order; + + /* audio only */ + int sample_rate; ///< samples per second + +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * number of audio channels + * @deprecated use ch_layout.nb_channels + */ + attribute_deprecated + int channels; +#endif + + /** + * audio sample format + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVSampleFormat sample_fmt; ///< sample format + + /* The following data should not be initialized. */ + /** + * Number of samples per channel in an audio frame. + * + * - encoding: set by libavcodec in avcodec_open2(). Each submitted frame + * except the last must contain exactly frame_size samples per channel. + * May be 0 when the codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE set, then the + * frame size is not restricted. + * - decoding: may be set by some decoders to indicate constant frame size + */ + int frame_size; + +#if FF_API_AVCTX_FRAME_NUMBER + /** + * Frame counter, set by libavcodec. + * + * - decoding: total number of frames returned from the decoder so far. + * - encoding: total number of frames passed to the encoder so far. + * + * @note the counter is not incremented if encoding/decoding resulted in + * an error. + * @deprecated use frame_num instead + */ + attribute_deprecated + int frame_number; +#endif + + /** + * number of bytes per packet if constant and known or 0 + * Used by some WAV based audio codecs. + */ + int block_align; + + /** + * Audio cutoff bandwidth (0 means "automatic") + * - encoding: Set by user. + * - decoding: unused + */ + int cutoff; + +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * Audio channel layout. + * - encoding: set by user. + * - decoding: set by user, may be overwritten by libavcodec. + * @deprecated use ch_layout + */ + attribute_deprecated + uint64_t channel_layout; + + /** + * Request decoder to use this channel layout if it can (0 for default) + * - encoding: unused + * - decoding: Set by user. + * @deprecated use "downmix" codec private option + */ + attribute_deprecated + uint64_t request_channel_layout; +#endif + + /** + * Type of service that the audio stream conveys. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVAudioServiceType audio_service_type; + + /** + * desired sample format + * - encoding: Not used. + * - decoding: Set by user. + * Decoder will decode to this format if it can. + */ + enum AVSampleFormat request_sample_fmt; + + /** + * This callback is called at the beginning of each frame to get data + * buffer(s) for it. There may be one contiguous buffer for all the data or + * there may be a buffer per each data plane or anything in between. What + * this means is, you may set however many entries in buf[] you feel necessary. + * Each buffer must be reference-counted using the AVBuffer API (see description + * of buf[] below). + * + * The following fields will be set in the frame before this callback is + * called: + * - format + * - width, height (video only) + * - sample_rate, channel_layout, nb_samples (audio only) + * Their values may differ from the corresponding values in + * AVCodecContext. This callback must use the frame values, not the codec + * context values, to calculate the required buffer size. + * + * This callback must fill the following fields in the frame: + * - data[] + * - linesize[] + * - extended_data: + * * if the data is planar audio with more than 8 channels, then this + * callback must allocate and fill extended_data to contain all pointers + * to all data planes. data[] must hold as many pointers as it can. + * extended_data must be allocated with av_malloc() and will be freed in + * av_frame_unref(). + * * otherwise extended_data must point to data + * - buf[] must contain one or more pointers to AVBufferRef structures. Each of + * the frame's data and extended_data pointers must be contained in these. That + * is, one AVBufferRef for each allocated chunk of memory, not necessarily one + * AVBufferRef per data[] entry. See: av_buffer_create(), av_buffer_alloc(), + * and av_buffer_ref(). + * - extended_buf and nb_extended_buf must be allocated with av_malloc() by + * this callback and filled with the extra buffers if there are more + * buffers than buf[] can hold. extended_buf will be freed in + * av_frame_unref(). + * + * If AV_CODEC_CAP_DR1 is not set then get_buffer2() must call + * avcodec_default_get_buffer2() instead of providing buffers allocated by + * some other means. + * + * Each data plane must be aligned to the maximum required by the target + * CPU. + * + * @see avcodec_default_get_buffer2() + * + * Video: + * + * If AV_GET_BUFFER_FLAG_REF is set in flags then the frame may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * avcodec_align_dimensions2() should be used to find the required width and + * height, as they normally need to be rounded up to the next multiple of 16. + * + * Some decoders do not support linesizes changing between frames. + * + * If frame multithreading is used, this callback may be called from a + * different thread, but not from more than one at once. Does not need to be + * reentrant. + * + * @see avcodec_align_dimensions2() + * + * Audio: + * + * Decoders request a buffer of a particular size by setting + * AVFrame.nb_samples prior to calling get_buffer2(). The decoder may, + * however, utilize only part of the buffer by setting AVFrame.nb_samples + * to a smaller value in the output frame. + * + * As a convenience, av_samples_get_buffer_size() and + * av_samples_fill_arrays() in libavutil may be used by custom get_buffer2() + * functions to find the required data size and to fill data pointers and + * linesize. In AVFrame.linesize, only linesize[0] may be set for audio + * since all planes must be the same size. + * + * @see av_samples_get_buffer_size(), av_samples_fill_arrays() + * + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + */ + int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags); + + /* - encoding parameters */ + float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0) + float qblur; ///< amount of qscale smoothing over time (0.0-1.0) + + /** + * minimum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmin; + + /** + * maximum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmax; + + /** + * maximum quantizer difference between frames + * - encoding: Set by user. + * - decoding: unused + */ + int max_qdiff; + + /** + * decoder bitstream buffer size + * - encoding: Set by user. + * - decoding: May be set by libavcodec. + */ + int rc_buffer_size; + + /** + * ratecontrol override, see RcOverride + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + int rc_override_count; + RcOverride *rc_override; + + /** + * maximum bitrate + * - encoding: Set by user. + * - decoding: Set by user, may be overwritten by libavcodec. + */ + int64_t rc_max_rate; + + /** + * minimum bitrate + * - encoding: Set by user. + * - decoding: unused + */ + int64_t rc_min_rate; + + /** + * Ratecontrol attempt to use, at maximum, of what can be used without an underflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_max_available_vbv_use; + + /** + * Ratecontrol attempt to use, at least, times the amount needed to prevent a vbv overflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_min_vbv_overflow_use; + + /** + * Number of bits which should be loaded into the rc buffer before decoding starts. + * - encoding: Set by user. + * - decoding: unused + */ + int rc_initial_buffer_occupancy; + + /** + * trellis RD quantization + * - encoding: Set by user. + * - decoding: unused + */ + int trellis; + + /** + * pass1 encoding statistics output buffer + * - encoding: Set by libavcodec. + * - decoding: unused + */ + char *stats_out; + + /** + * pass2 encoding statistics input buffer + * Concatenated stuff from stats_out of pass1 should be placed here. + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + char *stats_in; + + /** + * Work around bugs in encoders which sometimes cannot be detected automatically. + * - encoding: Set by user + * - decoding: Set by user + */ + int workaround_bugs; +#define FF_BUG_AUTODETECT 1 ///< autodetection +#define FF_BUG_XVID_ILACE 4 +#define FF_BUG_UMP4 8 +#define FF_BUG_NO_PADDING 16 +#define FF_BUG_AMV 32 +#define FF_BUG_QPEL_CHROMA 64 +#define FF_BUG_STD_QPEL 128 +#define FF_BUG_QPEL_CHROMA2 256 +#define FF_BUG_DIRECT_BLOCKSIZE 512 +#define FF_BUG_EDGE 1024 +#define FF_BUG_HPEL_CHROMA 2048 +#define FF_BUG_DC_CLIP 4096 +#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders. +#define FF_BUG_TRUNCATED 16384 +#define FF_BUG_IEDGE 32768 + + /** + * strictly follow the standard (MPEG-4, ...). + * - encoding: Set by user. + * - decoding: Set by user. + * Setting this to STRICT or higher means the encoder and decoder will + * generally do stupid things, whereas setting it to unofficial or lower + * will mean the encoder might produce output that is not supported by all + * spec-compliant decoders. Decoders don't differentiate between normal, + * unofficial and experimental (that is, they always try to decode things + * when they can) unless they are explicitly asked to behave stupidly + * (=strictly conform to the specs) + * This may only be set to one of the FF_COMPLIANCE_* values in defs.h. + */ + int strict_std_compliance; + + /** + * error concealment flags + * - encoding: unused + * - decoding: Set by user. + */ + int error_concealment; +#define FF_EC_GUESS_MVS 1 +#define FF_EC_DEBLOCK 2 +#define FF_EC_FAVOR_INTER 256 + + /** + * debug + * - encoding: Set by user. + * - decoding: Set by user. + */ + int debug; +#define FF_DEBUG_PICT_INFO 1 +#define FF_DEBUG_RC 2 +#define FF_DEBUG_BITSTREAM 4 +#define FF_DEBUG_MB_TYPE 8 +#define FF_DEBUG_QP 16 +#define FF_DEBUG_DCT_COEFF 0x00000040 +#define FF_DEBUG_SKIP 0x00000080 +#define FF_DEBUG_STARTCODE 0x00000100 +#define FF_DEBUG_ER 0x00000400 +#define FF_DEBUG_MMCO 0x00000800 +#define FF_DEBUG_BUGS 0x00001000 +#define FF_DEBUG_BUFFERS 0x00008000 +#define FF_DEBUG_THREADS 0x00010000 +#define FF_DEBUG_GREEN_MD 0x00800000 +#define FF_DEBUG_NOMC 0x01000000 + + /** + * Error recognition; may misdetect some more or less valid parts as errors. + * This is a bitfield of the AV_EF_* values defined in defs.h. + * + * - encoding: Set by user. + * - decoding: Set by user. + */ + int err_recognition; + +#if FF_API_REORDERED_OPAQUE + /** + * opaque 64-bit number (generally a PTS) that will be reordered and + * output in AVFrame.reordered_opaque + * - encoding: Set by libavcodec to the reordered_opaque of the input + * frame corresponding to the last returned packet. Only + * supported by encoders with the + * AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability. + * - decoding: Set by user. + * + * @deprecated Use AV_CODEC_FLAG_COPY_OPAQUE instead + */ + attribute_deprecated + int64_t reordered_opaque; +#endif + + /** + * Hardware accelerator in use + * - encoding: unused. + * - decoding: Set by libavcodec + */ + const struct AVHWAccel *hwaccel; + + /** + * Legacy hardware accelerator context. + * + * For some hardware acceleration methods, the caller may use this field to + * signal hwaccel-specific data to the codec. The struct pointed to by this + * pointer is hwaccel-dependent and defined in the respective header. Please + * refer to the FFmpeg HW accelerator documentation to know how to fill + * this. + * + * In most cases this field is optional - the necessary information may also + * be provided to libavcodec through @ref hw_frames_ctx or @ref + * hw_device_ctx (see avcodec_get_hw_config()). However, in some cases it + * may be the only method of signalling some (optional) information. + * + * The struct and its contents are owned by the caller. + * + * - encoding: May be set by the caller before avcodec_open2(). Must remain + * valid until avcodec_free_context(). + * - decoding: May be set by the caller in the get_format() callback. + * Must remain valid until the next get_format() call, + * or avcodec_free_context() (whichever comes first). + */ + void *hwaccel_context; + + /** + * error + * - encoding: Set by libavcodec if flags & AV_CODEC_FLAG_PSNR. + * - decoding: unused + */ + uint64_t error[AV_NUM_DATA_POINTERS]; + + /** + * DCT algorithm, see FF_DCT_* below + * - encoding: Set by user. + * - decoding: unused + */ + int dct_algo; +#define FF_DCT_AUTO 0 +#define FF_DCT_FASTINT 1 +#define FF_DCT_INT 2 +#define FF_DCT_MMX 3 +#define FF_DCT_ALTIVEC 5 +#define FF_DCT_FAAN 6 + + /** + * IDCT algorithm, see FF_IDCT_* below. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int idct_algo; +#define FF_IDCT_AUTO 0 +#define FF_IDCT_INT 1 +#define FF_IDCT_SIMPLE 2 +#define FF_IDCT_SIMPLEMMX 3 +#define FF_IDCT_ARM 7 +#define FF_IDCT_ALTIVEC 8 +#define FF_IDCT_SIMPLEARM 10 +#define FF_IDCT_XVID 14 +#define FF_IDCT_SIMPLEARMV5TE 16 +#define FF_IDCT_SIMPLEARMV6 17 +#define FF_IDCT_FAAN 20 +#define FF_IDCT_SIMPLENEON 22 +#if FF_API_IDCT_NONE +// formerly used by xvmc +#define FF_IDCT_NONE 24 +#endif +#define FF_IDCT_SIMPLEAUTO 128 + + /** + * bits per sample/pixel from the demuxer (needed for huffyuv). + * - encoding: Set by libavcodec. + * - decoding: Set by user. + */ + int bits_per_coded_sample; + + /** + * Bits per sample/pixel of internal libavcodec pixel/sample format. + * - encoding: set by user. + * - decoding: set by libavcodec. + */ + int bits_per_raw_sample; + + /** + * low resolution decoding, 1-> 1/2 size, 2->1/4 size + * - encoding: unused + * - decoding: Set by user. + */ + int lowres; + + /** + * thread count + * is used to decide how many independent tasks should be passed to execute() + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_count; + + /** + * Which multithreading methods to use. + * Use of FF_THREAD_FRAME will increase decoding delay by one frame per thread, + * so clients which cannot provide future frames should not use it. + * + * - encoding: Set by user, otherwise the default is used. + * - decoding: Set by user, otherwise the default is used. + */ + int thread_type; +#define FF_THREAD_FRAME 1 ///< Decode more than one frame at once +#define FF_THREAD_SLICE 2 ///< Decode more than one part of a single frame at once + + /** + * Which multithreading methods are in use by the codec. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int active_thread_type; + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param count the number of things to execute + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size); + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param c context passed also to func + * @param count the number of things to execute + * @param arg2 argument passed unchanged to func + * @param ret return values of executed functions, must have space for "count" values. May be NULL. + * @param func function that will be called count times, with jobnr from 0 to count-1. + * threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no + * two instances of func executing at the same time will have the same threadnr. + * @return always 0 currently, but code should handle a future improvement where when any call to func + * returns < 0 no further calls to func may be done and < 0 is returned. + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count); + + /** + * noise vs. sse weight for the nsse comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int nsse_weight; + + /** + * profile + * - encoding: Set by user. + * - decoding: Set by libavcodec. + * See the AV_PROFILE_* defines in defs.h. + */ + int profile; +#if FF_API_FF_PROFILE_LEVEL + /** @deprecated The following defines are deprecated; use AV_PROFILE_* + * in defs.h instead. */ +#define FF_PROFILE_UNKNOWN -99 +#define FF_PROFILE_RESERVED -100 + +#define FF_PROFILE_AAC_MAIN 0 +#define FF_PROFILE_AAC_LOW 1 +#define FF_PROFILE_AAC_SSR 2 +#define FF_PROFILE_AAC_LTP 3 +#define FF_PROFILE_AAC_HE 4 +#define FF_PROFILE_AAC_HE_V2 28 +#define FF_PROFILE_AAC_LD 22 +#define FF_PROFILE_AAC_ELD 38 +#define FF_PROFILE_MPEG2_AAC_LOW 128 +#define FF_PROFILE_MPEG2_AAC_HE 131 + +#define FF_PROFILE_DNXHD 0 +#define FF_PROFILE_DNXHR_LB 1 +#define FF_PROFILE_DNXHR_SQ 2 +#define FF_PROFILE_DNXHR_HQ 3 +#define FF_PROFILE_DNXHR_HQX 4 +#define FF_PROFILE_DNXHR_444 5 + +#define FF_PROFILE_DTS 20 +#define FF_PROFILE_DTS_ES 30 +#define FF_PROFILE_DTS_96_24 40 +#define FF_PROFILE_DTS_HD_HRA 50 +#define FF_PROFILE_DTS_HD_MA 60 +#define FF_PROFILE_DTS_EXPRESS 70 +#define FF_PROFILE_DTS_HD_MA_X 61 +#define FF_PROFILE_DTS_HD_MA_X_IMAX 62 + + +#define FF_PROFILE_EAC3_DDP_ATMOS 30 + +#define FF_PROFILE_TRUEHD_ATMOS 30 + +#define FF_PROFILE_MPEG2_422 0 +#define FF_PROFILE_MPEG2_HIGH 1 +#define FF_PROFILE_MPEG2_SS 2 +#define FF_PROFILE_MPEG2_SNR_SCALABLE 3 +#define FF_PROFILE_MPEG2_MAIN 4 +#define FF_PROFILE_MPEG2_SIMPLE 5 + +#define FF_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag +#define FF_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag + +#define FF_PROFILE_H264_BASELINE 66 +#define FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED) +#define FF_PROFILE_H264_MAIN 77 +#define FF_PROFILE_H264_EXTENDED 88 +#define FF_PROFILE_H264_HIGH 100 +#define FF_PROFILE_H264_HIGH_10 110 +#define FF_PROFILE_H264_HIGH_10_INTRA (110|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_MULTIVIEW_HIGH 118 +#define FF_PROFILE_H264_HIGH_422 122 +#define FF_PROFILE_H264_HIGH_422_INTRA (122|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_STEREO_HIGH 128 +#define FF_PROFILE_H264_HIGH_444 144 +#define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244 +#define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_CAVLC_444 44 + +#define FF_PROFILE_VC1_SIMPLE 0 +#define FF_PROFILE_VC1_MAIN 1 +#define FF_PROFILE_VC1_COMPLEX 2 +#define FF_PROFILE_VC1_ADVANCED 3 + +#define FF_PROFILE_MPEG4_SIMPLE 0 +#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE 1 +#define FF_PROFILE_MPEG4_CORE 2 +#define FF_PROFILE_MPEG4_MAIN 3 +#define FF_PROFILE_MPEG4_N_BIT 4 +#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE 5 +#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6 +#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7 +#define FF_PROFILE_MPEG4_HYBRID 8 +#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME 9 +#define FF_PROFILE_MPEG4_CORE_SCALABLE 10 +#define FF_PROFILE_MPEG4_ADVANCED_CODING 11 +#define FF_PROFILE_MPEG4_ADVANCED_CORE 12 +#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13 +#define FF_PROFILE_MPEG4_SIMPLE_STUDIO 14 +#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE 15 + +#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 1 +#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 2 +#define FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION 32768 +#define FF_PROFILE_JPEG2000_DCINEMA_2K 3 +#define FF_PROFILE_JPEG2000_DCINEMA_4K 4 + +#define FF_PROFILE_VP9_0 0 +#define FF_PROFILE_VP9_1 1 +#define FF_PROFILE_VP9_2 2 +#define FF_PROFILE_VP9_3 3 + +#define FF_PROFILE_HEVC_MAIN 1 +#define FF_PROFILE_HEVC_MAIN_10 2 +#define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 +#define FF_PROFILE_HEVC_REXT 4 +#define FF_PROFILE_HEVC_SCC 9 + +#define FF_PROFILE_VVC_MAIN_10 1 +#define FF_PROFILE_VVC_MAIN_10_444 33 + +#define FF_PROFILE_AV1_MAIN 0 +#define FF_PROFILE_AV1_HIGH 1 +#define FF_PROFILE_AV1_PROFESSIONAL 2 + +#define FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT 0xc0 +#define FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1 +#define FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT 0xc2 +#define FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3 +#define FF_PROFILE_MJPEG_JPEG_LS 0xf7 + +#define FF_PROFILE_SBC_MSBC 1 + +#define FF_PROFILE_PRORES_PROXY 0 +#define FF_PROFILE_PRORES_LT 1 +#define FF_PROFILE_PRORES_STANDARD 2 +#define FF_PROFILE_PRORES_HQ 3 +#define FF_PROFILE_PRORES_4444 4 +#define FF_PROFILE_PRORES_XQ 5 + +#define FF_PROFILE_ARIB_PROFILE_A 0 +#define FF_PROFILE_ARIB_PROFILE_C 1 + +#define FF_PROFILE_KLVA_SYNC 0 +#define FF_PROFILE_KLVA_ASYNC 1 + +#define FF_PROFILE_EVC_BASELINE 0 +#define FF_PROFILE_EVC_MAIN 1 +#endif + + /** + * Encoding level descriptor. + * - encoding: Set by user, corresponds to a specific level defined by the + * codec, usually corresponding to the profile level, if not specified it + * is set to FF_LEVEL_UNKNOWN. + * - decoding: Set by libavcodec. + * See AV_LEVEL_* in defs.h. + */ + int level; +#if FF_API_FF_PROFILE_LEVEL + /** @deprecated The following define is deprecated; use AV_LEVEL_UNKOWN + * in defs.h instead. */ +#define FF_LEVEL_UNKNOWN -99 +#endif + + /** + * Skip loop filtering for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_loop_filter; + + /** + * Skip IDCT/dequantization for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_idct; + + /** + * Skip decoding for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_frame; + + /** + * Header containing style information for text subtitles. + * For SUBTITLE_ASS subtitle type, it should contain the whole ASS + * [Script Info] and [V4+ Styles] section, plus the [Events] line and + * the Format line following. It shouldn't include any Dialogue line. + * - encoding: Set/allocated/freed by user (before avcodec_open2()) + * - decoding: Set/allocated/freed by libavcodec (by avcodec_open2()) + */ + uint8_t *subtitle_header; + int subtitle_header_size; + + /** + * Audio only. The number of "priming" samples (padding) inserted by the + * encoder at the beginning of the audio. I.e. this number of leading + * decoded samples must be discarded by the caller to get the original audio + * without leading padding. + * + * - decoding: unused + * - encoding: Set by libavcodec. The timestamps on the output packets are + * adjusted by the encoder so that they always refer to the + * first sample of the data actually contained in the packet, + * including any added padding. E.g. if the timebase is + * 1/samplerate and the timestamp of the first input sample is + * 0, the timestamp of the first output packet will be + * -initial_padding. + */ + int initial_padding; + + /** + * - decoding: For codecs that store a framerate value in the compressed + * bitstream, the decoder may export it here. { 0, 1} when + * unknown. + * - encoding: May be used to signal the framerate of CFR content to an + * encoder. + */ + AVRational framerate; + + /** + * Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx. + * - encoding: unused. + * - decoding: Set by libavcodec before calling get_format() + */ + enum AVPixelFormat sw_pix_fmt; + + /** + * Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed. + * - encoding: unused. + * - decoding: set by user. + */ + AVRational pkt_timebase; + + /** + * AVCodecDescriptor + * - encoding: unused. + * - decoding: set by libavcodec. + */ + const struct AVCodecDescriptor *codec_descriptor; + + /** + * Current statistics for PTS correction. + * - decoding: maintained and used by libavcodec, not intended to be used by user apps + * - encoding: unused + */ + int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far + int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far + int64_t pts_correction_last_pts; /// PTS of the last frame + int64_t pts_correction_last_dts; /// DTS of the last frame + + /** + * Character encoding of the input subtitles file. + * - decoding: set by user + * - encoding: unused + */ + char *sub_charenc; + + /** + * Subtitles character encoding mode. Formats or codecs might be adjusting + * this setting (if they are doing the conversion themselves for instance). + * - decoding: set by libavcodec + * - encoding: unused + */ + int sub_charenc_mode; +#define FF_SUB_CHARENC_MODE_DO_NOTHING -1 ///< do nothing (demuxer outputs a stream supposed to be already in UTF-8, or the codec is bitmap for instance) +#define FF_SUB_CHARENC_MODE_AUTOMATIC 0 ///< libavcodec will select the mode itself +#define FF_SUB_CHARENC_MODE_PRE_DECODER 1 ///< the AVPacket data needs to be recoded to UTF-8 before being fed to the decoder, requires iconv +#define FF_SUB_CHARENC_MODE_IGNORE 2 ///< neither convert the subtitles, nor check them for valid UTF-8 + + /** + * Skip processing alpha if supported by codec. + * Note that if the format uses pre-multiplied alpha (common with VP6, + * and recommended due to better video quality/compression) + * the image will look as if alpha-blended onto a black background. + * However for formats that do not use pre-multiplied alpha + * there might be serious artefacts (though e.g. libswscale currently + * assumes pre-multiplied alpha anyway). + * + * - decoding: set by user + * - encoding: unused + */ + int skip_alpha; + + /** + * Number of samples to skip after a discontinuity + * - decoding: unused + * - encoding: set by libavcodec + */ + int seek_preroll; + + /** + * custom intra quantization matrix + * - encoding: Set by user, can be NULL. + * - decoding: unused. + */ + uint16_t *chroma_intra_matrix; + + /** + * dump format separator. + * can be ", " or "\n " or anything else + * - encoding: Set by user. + * - decoding: Set by user. + */ + uint8_t *dump_separator; + + /** + * ',' separated list of allowed decoders. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *codec_whitelist; + + /** + * Properties of the stream that gets decoded + * - encoding: unused + * - decoding: set by libavcodec + */ + unsigned properties; +#define FF_CODEC_PROPERTY_LOSSLESS 0x00000001 +#define FF_CODEC_PROPERTY_CLOSED_CAPTIONS 0x00000002 +#define FF_CODEC_PROPERTY_FILM_GRAIN 0x00000004 + + /** + * Additional data associated with the entire coded stream. + * + * - decoding: may be set by user before calling avcodec_open2(). + * - encoding: may be set by libavcodec after avcodec_open2(). + */ + AVPacketSideData *coded_side_data; + int nb_coded_side_data; + + /** + * A reference to the AVHWFramesContext describing the input (for encoding) + * or output (decoding) frames. The reference is set by the caller and + * afterwards owned (and freed) by libavcodec - it should never be read by + * the caller after being set. + * + * - decoding: This field should be set by the caller from the get_format() + * callback. The previous reference (if any) will always be + * unreffed by libavcodec before the get_format() call. + * + * If the default get_buffer2() is used with a hwaccel pixel + * format, then this AVHWFramesContext will be used for + * allocating the frame buffers. + * + * - encoding: For hardware encoders configured to use a hwaccel pixel + * format, this field should be set by the caller to a reference + * to the AVHWFramesContext describing input frames. + * AVHWFramesContext.format must be equal to + * AVCodecContext.pix_fmt. + * + * This field should be set before avcodec_open2() is called. + */ + AVBufferRef *hw_frames_ctx; + + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + * + * - decoding: unused + * - encoding: unused + */ + int trailing_padding; + + /** + * The number of pixels per image to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_pixels; + + /** + * A reference to the AVHWDeviceContext describing the device which will + * be used by a hardware encoder/decoder. The reference is set by the + * caller and afterwards owned (and freed) by libavcodec. + * + * This should be used if either the codec device does not require + * hardware frames or any that are used are to be allocated internally by + * libavcodec. If the user wishes to supply any of the frames used as + * encoder input or decoder output then hw_frames_ctx should be used + * instead. When hw_frames_ctx is set in get_format() for a decoder, this + * field will be ignored while decoding the associated stream segment, but + * may again be used on a following one after another get_format() call. + * + * For both encoders and decoders this field should be set before + * avcodec_open2() is called and must not be written to thereafter. + * + * Note that some decoders may require this field to be set initially in + * order to support hw_frames_ctx at all - in that case, all frames + * contexts used must be created on the same device. + */ + AVBufferRef *hw_device_ctx; + + /** + * Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated + * decoding (if active). + * - encoding: unused + * - decoding: Set by user (either before avcodec_open2(), or in the + * AVCodecContext.get_format callback) + */ + int hwaccel_flags; + + /** + * Video decoding only. Certain video codecs support cropping, meaning that + * only a sub-rectangle of the decoded frame is intended for display. This + * option controls how cropping is handled by libavcodec. + * + * When set to 1 (the default), libavcodec will apply cropping internally. + * I.e. it will modify the output frame width/height fields and offset the + * data pointers (only by as much as possible while preserving alignment, or + * by the full amount if the AV_CODEC_FLAG_UNALIGNED flag is set) so that + * the frames output by the decoder refer only to the cropped area. The + * crop_* fields of the output frames will be zero. + * + * When set to 0, the width/height fields of the output frames will be set + * to the coded dimensions and the crop_* fields will describe the cropping + * rectangle. Applying the cropping is left to the caller. + * + * @warning When hardware acceleration with opaque output frames is used, + * libavcodec is unable to apply cropping from the top/left border. + * + * @note when this option is set to zero, the width/height fields of the + * AVCodecContext and output AVFrames have different meanings. The codec + * context fields store display dimensions (with the coded dimensions in + * coded_width/height), while the frame fields store the coded dimensions + * (with the display dimensions being determined by the crop_* fields). + */ + int apply_cropping; + + /* + * Video decoding only. Sets the number of extra hardware frames which + * the decoder will allocate for use by the caller. This must be set + * before avcodec_open2() is called. + * + * Some hardware decoders require all frames that they will use for + * output to be defined in advance before decoding starts. For such + * decoders, the hardware frame pool must therefore be of a fixed size. + * The extra frames set here are on top of any number that the decoder + * needs internally in order to operate normally (for example, frames + * used as reference pictures). + */ + int extra_hw_frames; + + /** + * The percentage of damaged samples to discard a frame. + * + * - decoding: set by user + * - encoding: unused + */ + int discard_damaged_percentage; + + /** + * The number of samples per frame to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_samples; + + /** + * Bit set of AV_CODEC_EXPORT_DATA_* flags, which affects the kind of + * metadata exported in frame, packet, or coded stream side data by + * decoders and encoders. + * + * - decoding: set by user + * - encoding: set by user + */ + int export_side_data; + + /** + * This callback is called at the beginning of each packet to get a data + * buffer for it. + * + * The following field will be set in the packet before this callback is + * called: + * - size + * This callback must use the above value to calculate the required buffer size, + * which must padded by at least AV_INPUT_BUFFER_PADDING_SIZE bytes. + * + * In some specific cases, the encoder may not use the entire buffer allocated by this + * callback. This will be reflected in the size value in the packet once returned by + * avcodec_receive_packet(). + * + * This callback must fill the following fields in the packet: + * - data: alignment requirements for AVPacket apply, if any. Some architectures and + * encoders may benefit from having aligned data. + * - buf: must contain a pointer to an AVBufferRef structure. The packet's + * data pointer must be contained in it. See: av_buffer_create(), av_buffer_alloc(), + * and av_buffer_ref(). + * + * If AV_CODEC_CAP_DR1 is not set then get_encode_buffer() must call + * avcodec_default_get_encode_buffer() instead of providing a buffer allocated by + * some other means. + * + * The flags field may contain a combination of AV_GET_ENCODE_BUFFER_FLAG_ flags. + * They may be used for example to hint what use the buffer may get after being + * created. + * Implementations of this callback may ignore flags they don't understand. + * If AV_GET_ENCODE_BUFFER_FLAG_REF is set in flags then the packet may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * This callback must be thread-safe, as when frame threading is used, it may + * be called from multiple threads simultaneously. + * + * @see avcodec_default_get_encode_buffer() + * + * - encoding: Set by libavcodec, user can override. + * - decoding: unused + */ + int (*get_encode_buffer)(struct AVCodecContext *s, AVPacket *pkt, int flags); + + /** + * Audio channel layout. + * - encoding: must be set by the caller, to one of AVCodec.ch_layouts. + * - decoding: may be set by the caller if known e.g. from the container. + * The decoder can then override during decoding as needed. + */ + AVChannelLayout ch_layout; + + /** + * Frame counter, set by libavcodec. + * + * - decoding: total number of frames returned from the decoder so far. + * - encoding: total number of frames passed to the encoder so far. + * + * @note the counter is not incremented if encoding/decoding resulted in + * an error. + */ + int64_t frame_num; +} AVCodecContext; + +/** + * @defgroup lavc_hwaccel AVHWAccel + * + * @note Nothing in this structure should be accessed by the user. At some + * point in future it will not be externally visible at all. + * + * @{ + */ +typedef struct AVHWAccel { + /** + * Name of the hardware accelerated codec. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + */ + const char *name; + + /** + * Type of codec implemented by the hardware accelerator. + * + * See AVMEDIA_TYPE_xxx + */ + enum AVMediaType type; + + /** + * Codec implemented by the hardware accelerator. + * + * See AV_CODEC_ID_xxx + */ + enum AVCodecID id; + + /** + * Supported pixel format. + * + * Only hardware accelerated formats are supported here. + */ + enum AVPixelFormat pix_fmt; + + /** + * Hardware accelerated codec capabilities. + * see AV_HWACCEL_CODEC_CAP_* + */ + int capabilities; +} AVHWAccel; + +/** + * HWAccel is experimental and is thus avoided in favor of non experimental + * codecs + */ +#define AV_HWACCEL_CODEC_CAP_EXPERIMENTAL 0x0200 + +/** + * Hardware acceleration should be used for decoding even if the codec level + * used is unknown or higher than the maximum supported level reported by the + * hardware driver. + * + * It's generally a good idea to pass this flag unless you have a specific + * reason not to, as hardware tends to under-report supported levels. + */ +#define AV_HWACCEL_FLAG_IGNORE_LEVEL (1 << 0) + +/** + * Hardware acceleration can output YUV pixel formats with a different chroma + * sampling than 4:2:0 and/or other than 8 bits per component. + */ +#define AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH (1 << 1) + +/** + * Hardware acceleration should still be attempted for decoding when the + * codec profile does not match the reported capabilities of the hardware. + * + * For example, this can be used to try to decode baseline profile H.264 + * streams in hardware - it will often succeed, because many streams marked + * as baseline profile actually conform to constrained baseline profile. + * + * @warning If the stream is actually not supported then the behaviour is + * undefined, and may include returning entirely incorrect output + * while indicating success. + */ +#define AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH (1 << 2) + +/** + * Some hardware decoders (namely nvdec) can either output direct decoder + * surfaces, or make an on-device copy and return said copy. + * There is a hard limit on how many decoder surfaces there can be, and it + * cannot be accurately guessed ahead of time. + * For some processing chains, this can be okay, but others will run into the + * limit and in turn produce very confusing errors that require fine tuning of + * more or less obscure options by the user, or in extreme cases cannot be + * resolved at all without inserting an avfilter that forces a copy. + * + * Thus, the hwaccel will by default make a copy for safety and resilience. + * If a users really wants to minimize the amount of copies, they can set this + * flag and ensure their processing chain does not exhaust the surface pool. + */ +#define AV_HWACCEL_FLAG_UNSAFE_OUTPUT (1 << 3) + +/** + * @} + */ + +enum AVSubtitleType { + SUBTITLE_NONE, + + SUBTITLE_BITMAP, ///< A bitmap, pict will be set + + /** + * Plain text, the text field must be set by the decoder and is + * authoritative. ass and pict fields may contain approximations. + */ + SUBTITLE_TEXT, + + /** + * Formatted text, the ass field must be set by the decoder and is + * authoritative. pict and text fields may contain approximations. + */ + SUBTITLE_ASS, +}; + +#define AV_SUBTITLE_FLAG_FORCED 0x00000001 + +typedef struct AVSubtitleRect { + int x; ///< top left corner of pict, undefined when pict is not set + int y; ///< top left corner of pict, undefined when pict is not set + int w; ///< width of pict, undefined when pict is not set + int h; ///< height of pict, undefined when pict is not set + int nb_colors; ///< number of colors in pict, undefined when pict is not set + + /** + * data+linesize for the bitmap of this subtitle. + * Can be set for text/ass as well once they are rendered. + */ + uint8_t *data[4]; + int linesize[4]; + + enum AVSubtitleType type; + + char *text; ///< 0 terminated plain UTF-8 text + + /** + * 0 terminated ASS/SSA compatible event line. + * The presentation of this is unaffected by the other values in this + * struct. + */ + char *ass; + + int flags; +} AVSubtitleRect; + +typedef struct AVSubtitle { + uint16_t format; /* 0 = graphics */ + uint32_t start_display_time; /* relative to packet pts, in ms */ + uint32_t end_display_time; /* relative to packet pts, in ms */ + unsigned num_rects; + AVSubtitleRect **rects; + int64_t pts; ///< Same as packet pts, in AV_TIME_BASE +} AVSubtitle; + +/** + * Return the LIBAVCODEC_VERSION_INT constant. + */ +unsigned avcodec_version(void); + +/** + * Return the libavcodec build-time configuration. + */ +const char *avcodec_configuration(void); + +/** + * Return the libavcodec license. + */ +const char *avcodec_license(void); + +/** + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct should be freed with avcodec_free_context(). + * + * @param codec if non-NULL, allocate private data and initialize defaults + * for the given codec. It is illegal to then call avcodec_open2() + * with a different codec. + * If NULL, then the codec-specific defaults won't be initialized, + * which may result in suboptimal default settings (this is + * important mainly for encoders, e.g. libx264). + * + * @return An AVCodecContext filled with default values or NULL on failure. + */ +AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); + +/** + * Free the codec context and everything associated with it and write NULL to + * the provided pointer. + */ +void avcodec_free_context(AVCodecContext **avctx); + +/** + * Get the AVClass for AVCodecContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_class(void); + +/** + * Get the AVClass for AVSubtitleRect. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_subtitle_rect_class(void); + +/** + * Fill the parameters struct based on the values from the supplied codec + * context. Any allocated fields in par are freed and replaced with duplicates + * of the corresponding fields in codec. + * + * @return >= 0 on success, a negative AVERROR code on failure + */ +int avcodec_parameters_from_context(struct AVCodecParameters *par, + const AVCodecContext *codec); + +/** + * Fill the codec context based on the values from the supplied codec + * parameters. Any allocated fields in codec that have a corresponding field in + * par are freed and replaced with duplicates of the corresponding field in par. + * Fields in codec that do not have a counterpart in par are not touched. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_to_context(AVCodecContext *codec, + const struct AVCodecParameters *par); + +/** + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated with avcodec_alloc_context3(). + * + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. + * + * Depending on the codec, you might need to set options in the codec context + * also for decoding (e.g. width, height, or the pixel or audio sample format in + * the case the information is not available in the bitstream, as when decoding + * raw audio or video). + * + * Options in the codec context can be set either by setting them in the options + * AVDictionary, or by setting the values in the context itself, directly or by + * using the av_opt_set() API before calling this function. + * + * Example: + * @code + * av_dict_set(&opts, "b", "2.5M", 0); + * codec = avcodec_find_decoder(AV_CODEC_ID_H264); + * if (!codec) + * exit(1); + * + * context = avcodec_alloc_context3(codec); + * + * if (avcodec_open2(context, codec, opts) < 0) + * exit(1); + * @endcode + * + * In the case AVCodecParameters are available (e.g. when demuxing a stream + * using libavformat, and accessing the AVStream contained in the demuxer), the + * codec parameters can be copied to the codec context using + * avcodec_parameters_to_context(), as in the following example: + * + * @code + * AVStream *stream = ...; + * context = avcodec_alloc_context3(codec); + * if (avcodec_parameters_to_context(context, stream->codecpar) < 0) + * exit(1); + * if (avcodec_open2(context, codec, NULL) < 0) + * exit(1); + * @endcode + * + * @note Always call this function before using decoding routines (such as + * @ref avcodec_receive_frame()). + * + * @param avctx The context to initialize. + * @param codec The codec to open this context for. If a non-NULL codec has been + * previously passed to avcodec_alloc_context3() or + * for this context, then this parameter MUST be either NULL or + * equal to the previously passed codec. + * @param options A dictionary filled with AVCodecContext and codec-private + * options, which are set on top of the options already set in + * avctx, can be NULL. On return this object will be filled with + * options that were not found in the avctx codec context. + * + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), + * av_dict_set(), av_opt_set(), av_opt_find(), avcodec_parameters_to_context() + */ +int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); + +/** + * Close a given AVCodecContext and free all the data associated with it + * (but not the AVCodecContext itself). + * + * Calling this function on an AVCodecContext that hasn't been opened will free + * the codec-specific data allocated in avcodec_alloc_context3() with a non-NULL + * codec. Subsequent calls will do nothing. + * + * @note Do not use this function. Use avcodec_free_context() to destroy a + * codec context (either open or closed). Opening and closing a codec context + * multiple times is not supported anymore -- use multiple codec contexts + * instead. + */ +int avcodec_close(AVCodecContext *avctx); + +/** + * Free all allocated data in the given subtitle struct. + * + * @param sub AVSubtitle to free. + */ +void avsubtitle_free(AVSubtitle *sub); + +/** + * @} + */ + +/** + * @addtogroup lavc_decoding + * @{ + */ + +/** + * The default callback for AVCodecContext.get_buffer2(). It is made public so + * it can be called by custom get_buffer2() implementations for decoders without + * AV_CODEC_CAP_DR1 set. + */ +int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags); + +/** + * The default callback for AVCodecContext.get_encode_buffer(). It is made public so + * it can be called by custom get_encode_buffer() implementations for encoders without + * AV_CODEC_CAP_DR1 set. + */ +int avcodec_default_get_encode_buffer(AVCodecContext *s, AVPacket *pkt, int flags); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you do not use any horizontal + * padding. + * + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. + */ +void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you also ensure that all + * line sizes are a multiple of the respective linesize_align[i]. + * + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. + */ +void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, + int linesize_align[AV_NUM_DATA_POINTERS]); + +#ifdef FF_API_AVCODEC_CHROMA_POS +/** + * Converts AVChromaLocation to swscale x/y chroma position. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + * @deprecated Use av_chroma_location_enum_to_pos() instead. + */ + attribute_deprecated +int avcodec_enum_to_chroma_pos(int *xpos, int *ypos, enum AVChromaLocation pos); + +/** + * Converts swscale x/y chroma position to AVChromaLocation. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + * @deprecated Use av_chroma_location_pos_to_enum() instead. + */ + attribute_deprecated +enum AVChromaLocation avcodec_chroma_pos_to_enum(int xpos, int ypos); +#endif + +/** + * Decode a subtitle message. + * Return a negative value on error, otherwise return the number of bytes used. + * If no subtitle could be decompressed, got_sub_ptr is zero. + * Otherwise, the subtitle is stored in *sub. + * Note that AV_CODEC_CAP_DR1 is not available for subtitle codecs. This is for + * simplicity, because the performance difference is expected to be negligible + * and reusing a get_buffer written for video codecs would probably perform badly + * due to a potentially very different allocation pattern. + * + * Some decoders (those marked with AV_CODEC_CAP_DELAY) have a delay between input + * and output. This means that for some packets they will not immediately + * produce decoded output and need to be flushed at the end of decoding to get + * all the decoded data. Flushing is done by calling this function with packets + * with avpkt->data set to NULL and avpkt->size set to 0 until it stops + * returning subtitles. It is safe to flush even those decoders that are not + * marked with AV_CODEC_CAP_DELAY, then no subtitles will be returned. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx the codec context + * @param[out] sub The preallocated AVSubtitle in which the decoded subtitle will be stored, + * must be freed with avsubtitle_free if *got_sub_ptr is set. + * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. + * @param[in] avpkt The input AVPacket containing the input buffer. + */ +int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt); + +/** + * Supply raw packet data as input to a decoder. + * + * Internally, this call will copy relevant AVCodecContext fields, which can + * influence decoding per-packet, and apply them when the packet is actually + * decoded. (For example AVCodecContext.skip_frame, which might direct the + * decoder to drop the frame contained by the packet sent with this function.) + * + * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE + * larger than the actual read bytes because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx codec context + * @param[in] avpkt The input AVPacket. Usually, this will be a single video + * frame, or several complete audio frames. + * Ownership of the packet remains with the caller, and the + * decoder will not write to the packet. The decoder may create + * a reference to the packet data (or copy it if the packet is + * not reference-counted). + * Unlike with older APIs, the packet is always fully consumed, + * and if it contains multiple frames (e.g. some audio codecs), + * will require you to call avcodec_receive_frame() multiple + * times afterwards before you can send a new packet. + * It can be NULL (or an AVPacket with data set to NULL and + * size set to 0); in this case, it is considered a flush + * packet, which signals the end of the stream. Sending the + * first flush packet will return success. Subsequent ones are + * unnecessary and will return AVERROR_EOF. If the decoder + * still has frames buffered, it will return them after sending + * a flush packet. + * + * @retval 0 success + * @retval AVERROR(EAGAIN) input is not accepted in the current state - user + * must read output with avcodec_receive_frame() (once + * all output is read, the packet should be resent, + * and the call will not fail with EAGAIN). + * @retval AVERROR_EOF the decoder has been flushed, and no new packets can be + * sent to it (also returned if more than 1 flush + * packet is sent) + * @retval AVERROR(EINVAL) codec not opened, it is an encoder, or requires flush + * @retval AVERROR(ENOMEM) failed to add packet to internal queue, or similar + * @retval "another negative error code" legitimate decoding errors + */ +int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); + +/** + * Return decoded output data from a decoder or encoder (when the + * @ref AV_CODEC_FLAG_RECON_FRAME flag is used). + * + * @param avctx codec context + * @param frame This will be set to a reference-counted video or audio + * frame (depending on the decoder type) allocated by the + * codec. Note that the function will always call + * av_frame_unref(frame) before doing anything else. + * + * @retval 0 success, a frame was returned + * @retval AVERROR(EAGAIN) output is not available in this state - user must + * try to send new input + * @retval AVERROR_EOF the codec has been fully flushed, and there will be + * no more output frames + * @retval AVERROR(EINVAL) codec not opened, or it is an encoder without the + * @ref AV_CODEC_FLAG_RECON_FRAME flag enabled + * @retval "other negative error code" legitimate decoding errors + */ +int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); + +/** + * Supply a raw video or audio frame to the encoder. Use avcodec_receive_packet() + * to retrieve buffered output packets. + * + * @param avctx codec context + * @param[in] frame AVFrame containing the raw audio or video frame to be encoded. + * Ownership of the frame remains with the caller, and the + * encoder will not write to the frame. The encoder may create + * a reference to the frame data (or copy it if the frame is + * not reference-counted). + * It can be NULL, in which case it is considered a flush + * packet. This signals the end of the stream. If the encoder + * still has packets buffered, it will return them after this + * call. Once flushing mode has been entered, additional flush + * packets are ignored, and sending frames will return + * AVERROR_EOF. + * + * For audio: + * If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * can have any number of samples. + * If it is not set, frame->nb_samples must be equal to + * avctx->frame_size for all frames except the last. + * The final frame may be smaller than avctx->frame_size. + * @retval 0 success + * @retval AVERROR(EAGAIN) input is not accepted in the current state - user must + * read output with avcodec_receive_packet() (once all + * output is read, the packet should be resent, and the + * call will not fail with EAGAIN). + * @retval AVERROR_EOF the encoder has been flushed, and no new frames can + * be sent to it + * @retval AVERROR(EINVAL) codec not opened, it is a decoder, or requires flush + * @retval AVERROR(ENOMEM) failed to add packet to internal queue, or similar + * @retval "another negative error code" legitimate encoding errors + */ +int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); + +/** + * Read encoded data from the encoder. + * + * @param avctx codec context + * @param avpkt This will be set to a reference-counted packet allocated by the + * encoder. Note that the function will always call + * av_packet_unref(avpkt) before doing anything else. + * @retval 0 success + * @retval AVERROR(EAGAIN) output is not available in the current state - user must + * try to send input + * @retval AVERROR_EOF the encoder has been fully flushed, and there will be no + * more output packets + * @retval AVERROR(EINVAL) codec not opened, or it is a decoder + * @retval "another negative error code" legitimate encoding errors + */ +int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); + +/** + * Create and return a AVHWFramesContext with values adequate for hardware + * decoding. This is meant to get called from the get_format callback, and is + * a helper for preparing a AVHWFramesContext for AVCodecContext.hw_frames_ctx. + * This API is for decoding with certain hardware acceleration modes/APIs only. + * + * The returned AVHWFramesContext is not initialized. The caller must do this + * with av_hwframe_ctx_init(). + * + * Calling this function is not a requirement, but makes it simpler to avoid + * codec or hardware API specific details when manually allocating frames. + * + * Alternatively to this, an API user can set AVCodecContext.hw_device_ctx, + * which sets up AVCodecContext.hw_frames_ctx fully automatically, and makes + * it unnecessary to call this function or having to care about + * AVHWFramesContext initialization at all. + * + * There are a number of requirements for calling this function: + * + * - It must be called from get_format with the same avctx parameter that was + * passed to get_format. Calling it outside of get_format is not allowed, and + * can trigger undefined behavior. + * - The function is not always supported (see description of return values). + * Even if this function returns successfully, hwaccel initialization could + * fail later. (The degree to which implementations check whether the stream + * is actually supported varies. Some do this check only after the user's + * get_format callback returns.) + * - The hw_pix_fmt must be one of the choices suggested by get_format. If the + * user decides to use a AVHWFramesContext prepared with this API function, + * the user must return the same hw_pix_fmt from get_format. + * - The device_ref passed to this function must support the given hw_pix_fmt. + * - After calling this API function, it is the user's responsibility to + * initialize the AVHWFramesContext (returned by the out_frames_ref parameter), + * and to set AVCodecContext.hw_frames_ctx to it. If done, this must be done + * before returning from get_format (this is implied by the normal + * AVCodecContext.hw_frames_ctx API rules). + * - The AVHWFramesContext parameters may change every time time get_format is + * called. Also, AVCodecContext.hw_frames_ctx is reset before get_format. So + * you are inherently required to go through this process again on every + * get_format call. + * - It is perfectly possible to call this function without actually using + * the resulting AVHWFramesContext. One use-case might be trying to reuse a + * previously initialized AVHWFramesContext, and calling this API function + * only to test whether the required frame parameters have changed. + * - Fields that use dynamically allocated values of any kind must not be set + * by the user unless setting them is explicitly allowed by the documentation. + * If the user sets AVHWFramesContext.free and AVHWFramesContext.user_opaque, + * the new free callback must call the potentially set previous free callback. + * This API call may set any dynamically allocated fields, including the free + * callback. + * + * The function will set at least the following fields on AVHWFramesContext + * (potentially more, depending on hwaccel API): + * + * - All fields set by av_hwframe_ctx_alloc(). + * - Set the format field to hw_pix_fmt. + * - Set the sw_format field to the most suited and most versatile format. (An + * implication is that this will prefer generic formats over opaque formats + * with arbitrary restrictions, if possible.) + * - Set the width/height fields to the coded frame size, rounded up to the + * API-specific minimum alignment. + * - Only _if_ the hwaccel requires a pre-allocated pool: set the initial_pool_size + * field to the number of maximum reference surfaces possible with the codec, + * plus 1 surface for the user to work (meaning the user can safely reference + * at most 1 decoded surface at a time), plus additional buffering introduced + * by frame threading. If the hwaccel does not require pre-allocation, the + * field is left to 0, and the decoder will allocate new surfaces on demand + * during decoding. + * - Possibly AVHWFramesContext.hwctx fields, depending on the underlying + * hardware API. + * + * Essentially, out_frames_ref returns the same as av_hwframe_ctx_alloc(), but + * with basic frame parameters set. + * + * The function is stateless, and does not change the AVCodecContext or the + * device_ref AVHWDeviceContext. + * + * @param avctx The context which is currently calling get_format, and which + * implicitly contains all state needed for filling the returned + * AVHWFramesContext properly. + * @param device_ref A reference to the AVHWDeviceContext describing the device + * which will be used by the hardware decoder. + * @param hw_pix_fmt The hwaccel format you are going to return from get_format. + * @param out_frames_ref On success, set to a reference to an _uninitialized_ + * AVHWFramesContext, created from the given device_ref. + * Fields will be set to values required for decoding. + * Not changed if an error is returned. + * @return zero on success, a negative value on error. The following error codes + * have special semantics: + * AVERROR(ENOENT): the decoder does not support this functionality. Setup + * is always manual, or it is a decoder which does not + * support setting AVCodecContext.hw_frames_ctx at all, + * or it is a software format. + * AVERROR(EINVAL): it is known that hardware decoding is not supported for + * this configuration, or the device_ref is not supported + * for the hwaccel referenced by hw_pix_fmt. + */ +int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, + AVBufferRef *device_ref, + enum AVPixelFormat hw_pix_fmt, + AVBufferRef **out_frames_ref); + + + +/** + * @defgroup lavc_parsing Frame parsing + * @{ + */ + +enum AVPictureStructure { + AV_PICTURE_STRUCTURE_UNKNOWN, ///< unknown + AV_PICTURE_STRUCTURE_TOP_FIELD, ///< coded as top field + AV_PICTURE_STRUCTURE_BOTTOM_FIELD, ///< coded as bottom field + AV_PICTURE_STRUCTURE_FRAME, ///< coded as frame +}; + +typedef struct AVCodecParserContext { + void *priv_data; + const struct AVCodecParser *parser; + int64_t frame_offset; /* offset of the current frame */ + int64_t cur_offset; /* current offset + (incremented by each av_parser_parse()) */ + int64_t next_frame_offset; /* offset of the next frame */ + /* video info */ + int pict_type; /* XXX: Put it back in AVCodecContext. */ + /** + * This field is used for proper frame duration computation in lavf. + * It signals, how much longer the frame duration of the current frame + * is compared to normal frame duration. + * + * frame_duration = (1 + repeat_pict) * time_base + * + * It is used by codecs like H.264 to display telecined material. + */ + int repeat_pict; /* XXX: Put it back in AVCodecContext. */ + int64_t pts; /* pts of the current frame */ + int64_t dts; /* dts of the current frame */ + + /* private data */ + int64_t last_pts; + int64_t last_dts; + int fetch_timestamp; + +#define AV_PARSER_PTS_NB 4 + int cur_frame_start_index; + int64_t cur_frame_offset[AV_PARSER_PTS_NB]; + int64_t cur_frame_pts[AV_PARSER_PTS_NB]; + int64_t cur_frame_dts[AV_PARSER_PTS_NB]; + + int flags; +#define PARSER_FLAG_COMPLETE_FRAMES 0x0001 +#define PARSER_FLAG_ONCE 0x0002 +/// Set if the parser has a valid file offset +#define PARSER_FLAG_FETCHED_OFFSET 0x0004 +#define PARSER_FLAG_USE_CODEC_TS 0x1000 + + int64_t offset; ///< byte offset from starting packet start + int64_t cur_frame_end[AV_PARSER_PTS_NB]; + + /** + * Set by parser to 1 for key frames and 0 for non-key frames. + * It is initialized to -1, so if the parser doesn't set this flag, + * old-style fallback using AV_PICTURE_TYPE_I picture type as key frames + * will be used. + */ + int key_frame; + + // Timestamp generation support: + /** + * Synchronization point for start of timestamp generation. + * + * Set to >0 for sync point, 0 for no sync point and <0 for undefined + * (default). + * + * For example, this corresponds to presence of H.264 buffering period + * SEI message. + */ + int dts_sync_point; + + /** + * Offset of the current timestamp against last timestamp sync point in + * units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain a valid timestamp offset. + * + * Note that the timestamp of sync point has usually a nonzero + * dts_ref_dts_delta, which refers to the previous sync point. Offset of + * the next frame after timestamp sync point will be usually 1. + * + * For example, this corresponds to H.264 cpb_removal_delay. + */ + int dts_ref_dts_delta; + + /** + * Presentation delay of current frame in units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain valid non-negative timestamp delta (presentation time of a frame + * must not lie in the past). + * + * This delay represents the difference between decoding and presentation + * time of the frame. + * + * For example, this corresponds to H.264 dpb_output_delay. + */ + int pts_dts_delta; + + /** + * Position of the packet in file. + * + * Analogous to cur_frame_pts/dts + */ + int64_t cur_frame_pos[AV_PARSER_PTS_NB]; + + /** + * Byte position of currently parsed frame in stream. + */ + int64_t pos; + + /** + * Previous frame byte position. + */ + int64_t last_pos; + + /** + * Duration of the current frame. + * For audio, this is in units of 1 / AVCodecContext.sample_rate. + * For all other types, this is in units of AVCodecContext.time_base. + */ + int duration; + + enum AVFieldOrder field_order; + + /** + * Indicate whether a picture is coded as a frame, top field or bottom field. + * + * For example, H.264 field_pic_flag equal to 0 corresponds to + * AV_PICTURE_STRUCTURE_FRAME. An H.264 picture with field_pic_flag + * equal to 1 and bottom_field_flag equal to 0 corresponds to + * AV_PICTURE_STRUCTURE_TOP_FIELD. + */ + enum AVPictureStructure picture_structure; + + /** + * Picture number incremented in presentation or output order. + * This field may be reinitialized at the first picture of a new sequence. + * + * For example, this corresponds to H.264 PicOrderCnt. + */ + int output_picture_number; + + /** + * Dimensions of the decoded video intended for presentation. + */ + int width; + int height; + + /** + * Dimensions of the coded video. + */ + int coded_width; + int coded_height; + + /** + * The format of the coded data, corresponds to enum AVPixelFormat for video + * and for enum AVSampleFormat for audio. + * + * Note that a decoder can have considerable freedom in how exactly it + * decodes the data, so the format reported here might be different from the + * one returned by a decoder. + */ + int format; +} AVCodecParserContext; + +typedef struct AVCodecParser { + int codec_ids[7]; /* several codec IDs are permitted */ + int priv_data_size; + int (*parser_init)(AVCodecParserContext *s); + /* This callback never returns an error, a negative value means that + * the frame start was in a previous packet. */ + int (*parser_parse)(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size); + void (*parser_close)(AVCodecParserContext *s); + int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size); +} AVCodecParser; + +/** + * Iterate over all registered codec parsers. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec parser or NULL when the iteration is + * finished + */ +const AVCodecParser *av_parser_iterate(void **opaque); + +AVCodecParserContext *av_parser_init(int codec_id); + +/** + * Parse a packet. + * + * @param s parser context. + * @param avctx codec context. + * @param poutbuf set to pointer to parsed buffer or NULL if not yet finished. + * @param poutbuf_size set to size of parsed buffer or zero if not yet finished. + * @param buf input buffer. + * @param buf_size buffer size in bytes without the padding. I.e. the full buffer + size is assumed to be buf_size + AV_INPUT_BUFFER_PADDING_SIZE. + To signal EOF, this should be 0 (so that the last frame + can be output). + * @param pts input presentation timestamp. + * @param dts input decoding timestamp. + * @param pos input byte position in stream. + * @return the number of bytes of the input bitstream used. + * + * Example: + * @code + * while(in_len){ + * len = av_parser_parse2(myparser, AVCodecContext, &data, &size, + * in_data, in_len, + * pts, dts, pos); + * in_data += len; + * in_len -= len; + * + * if(size) + * decode_frame(data, size); + * } + * @endcode + */ +int av_parser_parse2(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int64_t pts, int64_t dts, + int64_t pos); + +void av_parser_close(AVCodecParserContext *s); + +/** + * @} + * @} + */ + +/** + * @addtogroup lavc_encoding + * @{ + */ + +int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVSubtitle *sub); + + +/** + * @} + */ + +/** + * @defgroup lavc_misc Utility functions + * @ingroup libavc + * + * Miscellaneous utility functions related to both encoding and decoding + * (or neither). + * @{ + */ + +/** + * @defgroup lavc_misc_pixfmt Pixel formats + * + * Functions for working with pixel formats. + * @{ + */ + +/** + * Return a value representing the fourCC code associated to the + * pixel format pix_fmt, or 0 if no associated fourCC code can be + * found. + */ +unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt); + +/** + * Find the best pixel format to convert to given a certain source pixel + * format. When converting from one pixel format to another, information loss + * may occur. For example, when converting from RGB24 to GRAY, the color + * information will be lost. Similarly, other losses occur when converting from + * some formats to other formats. avcodec_find_best_pix_fmt_of_2() searches which of + * the given pixel formats should be used to suffer the least amount of loss. + * The pixel formats from which it chooses one, are determined by the + * pix_fmt_list parameter. + * + * + * @param[in] pix_fmt_list AV_PIX_FMT_NONE terminated array of pixel formats to choose from + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. + * @return The best pixel format to convert to or -1 if none was found. + */ +enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *pix_fmt_list, + enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); + +enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + +/** + * @} + */ + +void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); + +int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); +int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count); +//FIXME func typedef + +/** + * Fill AVFrame audio data and linesize pointers. + * + * The buffer buf must be a preallocated buffer with a size big enough + * to contain the specified samples amount. The filled AVFrame data + * pointers will point to this buffer. + * + * AVFrame extended_data channel pointers are allocated if necessary for + * planar audio. + * + * @param frame the AVFrame + * frame->nb_samples must be set prior to calling the + * function. This function fills in frame->data, + * frame->extended_data, frame->linesize[0]. + * @param nb_channels channel count + * @param sample_fmt sample format + * @param buf buffer to use for frame data + * @param buf_size size of buffer + * @param align plane size sample alignment (0 = default) + * @return >=0 on success, negative error code on failure + * @todo return the size in bytes required to store the samples in + * case of success, at the next libavutil bump + */ +int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, + enum AVSampleFormat sample_fmt, const uint8_t *buf, + int buf_size, int align); + +/** + * Reset the internal codec state / flush internal buffers. Should be called + * e.g. when seeking or when switching to a different stream. + * + * @note for decoders, this function just releases any references the decoder + * might keep internally, but the caller's references remain valid. + * + * @note for encoders, this function will only do something if the encoder + * declares support for AV_CODEC_CAP_ENCODER_FLUSH. When called, the encoder + * will drain any remaining packets, and can then be re-used for a different + * stream (as opposed to sending a null frame which will leave the encoder + * in a permanent EOF state after draining). This can be desirable if the + * cost of tearing down and replacing the encoder instance is high. + */ +void avcodec_flush_buffers(AVCodecContext *avctx); + +/** + * Return audio frame duration. + * + * @param avctx codec context + * @param frame_bytes size of the frame, or 0 if unknown + * @return frame duration, in samples, if known. 0 if not able to + * determine. + */ +int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes); + +/* memory */ + +/** + * Same behaviour av_fast_malloc but the buffer has additional + * AV_INPUT_BUFFER_PADDING_SIZE at the end which will always be 0. + * + * In addition the whole buffer will initially and after resizes + * be 0-initialized so that no uninitialized data will ever appear. + */ +void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Same behaviour av_fast_padded_malloc except that buffer will always + * be 0-initialized after call. + */ +void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * @return a positive value if s is open (i.e. avcodec_open2() was called on it + * with no corresponding avcodec_close()), 0 otherwise. + */ +int avcodec_is_open(AVCodecContext *s); + +/** + * @} + */ + +#endif /* AVCODEC_AVCODEC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec.h b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec.h new file mode 100644 index 0000000000000..8034f1a53c98d --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec.h @@ -0,0 +1,378 @@ +/* + * AVCodec public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_H +#define AVCODEC_CODEC_H + +#include + +#include "libavutil/avutil.h" +#include "libavutil/hwcontext.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" +#include "libavutil/samplefmt.h" + +#include "libavcodec/codec_id.h" +#include "libavcodec/version_major.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * Decoder can use draw_horiz_band callback. + */ +#define AV_CODEC_CAP_DRAW_HORIZ_BAND (1 << 0) +/** + * Codec uses get_buffer() or get_encode_buffer() for allocating buffers and + * supports custom allocators. + * If not set, it might not use get_buffer() or get_encode_buffer() at all, or + * use operations that assume the buffer was allocated by + * avcodec_default_get_buffer2 or avcodec_default_get_encode_buffer. + */ +#define AV_CODEC_CAP_DR1 (1 << 1) +/** + * Encoder or decoder requires flushing with NULL input at the end in order to + * give the complete and correct output. + * + * NOTE: If this flag is not set, the codec is guaranteed to never be fed with + * with NULL data. The user can still send NULL data to the public encode + * or decode function, but libavcodec will not pass it along to the codec + * unless this flag is set. + * + * Decoders: + * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to get the delayed data until the decoder no longer + * returns frames. + * + * Encoders: + * The encoder needs to be fed with NULL data at the end of encoding until the + * encoder no longer returns data. + * + * NOTE: For encoders implementing the AVCodec.encode2() function, setting this + * flag also means that the encoder must set the pts and duration for + * each output packet. If this flag is not set, the pts and duration will + * be determined by libavcodec from the input frame. + */ +#define AV_CODEC_CAP_DELAY (1 << 5) +/** + * Codec can be fed a final frame with a smaller size. + * This can be used to prevent truncation of the last audio samples. + */ +#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6) + +#if FF_API_SUBFRAMES +/** + * Codec can output multiple frames per AVPacket + * Normally demuxers return one frame at a time, demuxers which do not do + * are connected to a parser to split what they return into proper frames. + * This flag is reserved to the very rare category of codecs which have a + * bitstream that cannot be split into frames without timeconsuming + * operations like full decoding. Demuxers carrying such bitstreams thus + * may return multiple frames in a packet. This has many disadvantages like + * prohibiting stream copy in many cases thus it should only be considered + * as a last resort. + */ +#define AV_CODEC_CAP_SUBFRAMES (1 << 8) +#endif + +/** + * Codec is experimental and is thus avoided in favor of non experimental + * encoders + */ +#define AV_CODEC_CAP_EXPERIMENTAL (1 << 9) +/** + * Codec should fill in channel configuration and samplerate instead of container + */ +#define AV_CODEC_CAP_CHANNEL_CONF (1 << 10) +/** + * Codec supports frame-level multithreading. + */ +#define AV_CODEC_CAP_FRAME_THREADS (1 << 12) +/** + * Codec supports slice-based (or partition-based) multithreading. + */ +#define AV_CODEC_CAP_SLICE_THREADS (1 << 13) +/** + * Codec supports changed parameters at any point. + */ +#define AV_CODEC_CAP_PARAM_CHANGE (1 << 14) +/** + * Codec supports multithreading through a method other than slice- or + * frame-level multithreading. Typically this marks wrappers around + * multithreading-capable external libraries. + */ +#define AV_CODEC_CAP_OTHER_THREADS (1 << 15) +/** + * Audio encoder supports receiving a different number of samples in each call. + */ +#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16) +/** + * Decoder is not a preferred choice for probing. + * This indicates that the decoder is not a good choice for probing. + * It could for example be an expensive to spin up hardware decoder, + * or it could simply not provide a lot of useful information about + * the stream. + * A decoder marked with this flag should only be used as last resort + * choice for probing. + */ +#define AV_CODEC_CAP_AVOID_PROBING (1 << 17) + +/** + * Codec is backed by a hardware implementation. Typically used to + * identify a non-hwaccel hardware decoder. For information about hwaccels, use + * avcodec_get_hw_config() instead. + */ +#define AV_CODEC_CAP_HARDWARE (1 << 18) + +/** + * Codec is potentially backed by a hardware implementation, but not + * necessarily. This is used instead of AV_CODEC_CAP_HARDWARE, if the + * implementation provides some sort of internal fallback. + */ +#define AV_CODEC_CAP_HYBRID (1 << 19) + +/** + * This encoder can reorder user opaque values from input AVFrames and return + * them with corresponding output packets. + * @see AV_CODEC_FLAG_COPY_OPAQUE + */ +#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE (1 << 20) + +/** + * This encoder can be flushed using avcodec_flush_buffers(). If this flag is + * not set, the encoder must be closed and reopened to ensure that no frames + * remain pending. + */ +#define AV_CODEC_CAP_ENCODER_FLUSH (1 << 21) + +/** + * The encoder is able to output reconstructed frame data, i.e. raw frames that + * would be produced by decoding the encoded bitstream. + * + * Reconstructed frame output is enabled by the AV_CODEC_FLAG_RECON_FRAME flag. + */ +#define AV_CODEC_CAP_ENCODER_RECON_FRAME (1 << 22) + +/** + * AVProfile. + */ +typedef struct AVProfile { + int profile; + const char *name; ///< short name for the profile +} AVProfile; + +/** + * AVCodec. + */ +typedef struct AVCodec { + /** + * Name of the codec implementation. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + * This is the primary way to find a codec from the user perspective. + */ + const char *name; + /** + * Descriptive name for the codec, meant to be more human readable than name. + * You should use the NULL_IF_CONFIG_SMALL() macro to define it. + */ + const char *long_name; + enum AVMediaType type; + enum AVCodecID id; + /** + * Codec capabilities. + * see AV_CODEC_CAP_* + */ + int capabilities; + uint8_t max_lowres; ///< maximum value for lowres supported by the decoder + const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} + const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 + const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 + const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * @deprecated use ch_layouts instead + */ + attribute_deprecated + const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 +#endif + const AVClass *priv_class; ///< AVClass for the private context + const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {AV_PROFILE_UNKNOWN} + + /** + * Group name of the codec implementation. + * This is a short symbolic name of the wrapper backing this codec. A + * wrapper uses some kind of external implementation for the codec, such + * as an external library, or a codec implementation provided by the OS or + * the hardware. + * If this field is NULL, this is a builtin, libavcodec native codec. + * If non-NULL, this will be the suffix in AVCodec.name in most cases + * (usually AVCodec.name will be of the form "_"). + */ + const char *wrapper_name; + + /** + * Array of supported channel layouts, terminated with a zeroed layout. + */ + const AVChannelLayout *ch_layouts; +} AVCodec; + +/** + * Iterate over all registered codecs. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec or NULL when the iteration is + * finished + */ +const AVCodec *av_codec_iterate(void **opaque); + +/** + * Find a registered decoder with a matching codec ID. + * + * @param id AVCodecID of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_decoder(enum AVCodecID id); + +/** + * Find a registered decoder with the specified name. + * + * @param name name of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_decoder_by_name(const char *name); + +/** + * Find a registered encoder with a matching codec ID. + * + * @param id AVCodecID of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_encoder(enum AVCodecID id); + +/** + * Find a registered encoder with the specified name. + * + * @param name name of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_encoder_by_name(const char *name); +/** + * @return a non-zero number if codec is an encoder, zero otherwise + */ +int av_codec_is_encoder(const AVCodec *codec); + +/** + * @return a non-zero number if codec is a decoder, zero otherwise + */ +int av_codec_is_decoder(const AVCodec *codec); + +/** + * Return a name for the specified profile, if available. + * + * @param codec the codec that is searched for the given profile + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + */ +const char *av_get_profile_name(const AVCodec *codec, int profile); + +enum { + /** + * The codec supports this format via the hw_device_ctx interface. + * + * When selecting this format, AVCodecContext.hw_device_ctx should + * have been set to a device of the specified type before calling + * avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01, + /** + * The codec supports this format via the hw_frames_ctx interface. + * + * When selecting this format for a decoder, + * AVCodecContext.hw_frames_ctx should be set to a suitable frames + * context inside the get_format() callback. The frames context + * must have been created on a device of the specified type. + * + * When selecting this format for an encoder, + * AVCodecContext.hw_frames_ctx should be set to the context which + * will be used for the input frames before calling avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02, + /** + * The codec supports this format by some internal method. + * + * This format can be selected without any additional configuration - + * no device or frames context is required. + */ + AV_CODEC_HW_CONFIG_METHOD_INTERNAL = 0x04, + /** + * The codec supports this format by some ad-hoc method. + * + * Additional settings and/or function calls are required. See the + * codec-specific documentation for details. (Methods requiring + * this sort of configuration are deprecated and others should be + * used in preference.) + */ + AV_CODEC_HW_CONFIG_METHOD_AD_HOC = 0x08, +}; + +typedef struct AVCodecHWConfig { + /** + * For decoders, a hardware pixel format which that decoder may be + * able to decode to if suitable hardware is available. + * + * For encoders, a pixel format which the encoder may be able to + * accept. If set to AV_PIX_FMT_NONE, this applies to all pixel + * formats supported by the codec. + */ + enum AVPixelFormat pix_fmt; + /** + * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible + * setup methods which can be used with this configuration. + */ + int methods; + /** + * The device type associated with the configuration. + * + * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and + * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused. + */ + enum AVHWDeviceType device_type; +} AVCodecHWConfig; + +/** + * Retrieve supported hardware configurations for a codec. + * + * Values of index from zero to some maximum return the indexed configuration + * descriptor; all other values return NULL. If the codec does not support + * any hardware configurations then it will always return NULL. + */ +const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index); + +/** + * @} + */ + +#endif /* AVCODEC_CODEC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec_desc.h b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec_desc.h new file mode 100644 index 0000000000000..96afd20208b3d --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec_desc.h @@ -0,0 +1,134 @@ +/* + * Codec descriptors public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_DESC_H +#define AVCODEC_CODEC_DESC_H + +#include "libavutil/avutil.h" + +#include "codec_id.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * This struct describes the properties of a single codec described by an + * AVCodecID. + * @see avcodec_descriptor_get() + */ +typedef struct AVCodecDescriptor { + enum AVCodecID id; + enum AVMediaType type; + /** + * Name of the codec described by this descriptor. It is non-empty and + * unique for each codec descriptor. It should contain alphanumeric + * characters and '_' only. + */ + const char *name; + /** + * A more descriptive name for this codec. May be NULL. + */ + const char *long_name; + /** + * Codec properties, a combination of AV_CODEC_PROP_* flags. + */ + int props; + /** + * MIME type(s) associated with the codec. + * May be NULL; if not, a NULL-terminated array of MIME types. + * The first item is always non-NULL and is the preferred MIME type. + */ + const char *const *mime_types; + /** + * If non-NULL, an array of profiles recognized for this codec. + * Terminated with AV_PROFILE_UNKNOWN. + */ + const struct AVProfile *profiles; +} AVCodecDescriptor; + +/** + * Codec uses only intra compression. + * Video and audio codecs only. + */ +#define AV_CODEC_PROP_INTRA_ONLY (1 << 0) +/** + * Codec supports lossy compression. Audio and video codecs only. + * @note a codec may support both lossy and lossless + * compression modes + */ +#define AV_CODEC_PROP_LOSSY (1 << 1) +/** + * Codec supports lossless compression. Audio and video codecs only. + */ +#define AV_CODEC_PROP_LOSSLESS (1 << 2) +/** + * Codec supports frame reordering. That is, the coded order (the order in which + * the encoded packets are output by the encoders / stored / input to the + * decoders) may be different from the presentation order of the corresponding + * frames. + * + * For codecs that do not have this property set, PTS and DTS should always be + * equal. + */ +#define AV_CODEC_PROP_REORDER (1 << 3) + +/** + * Video codec supports separate coding of fields in interlaced frames. + */ +#define AV_CODEC_PROP_FIELDS (1 << 4) + +/** + * Subtitle codec is bitmap based + * Decoded AVSubtitle data can be read from the AVSubtitleRect->pict field. + */ +#define AV_CODEC_PROP_BITMAP_SUB (1 << 16) +/** + * Subtitle codec is text based. + * Decoded AVSubtitle data can be read from the AVSubtitleRect->ass field. + */ +#define AV_CODEC_PROP_TEXT_SUB (1 << 17) + +/** + * @return descriptor for given codec ID or NULL if no descriptor exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id); + +/** + * Iterate over all codec descriptors known to libavcodec. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); + +/** + * @return codec descriptor with the given name or NULL if no such descriptor + * exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_DESC_H diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec_id.h b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec_id.h new file mode 100644 index 0000000000000..29b410b8d3fb4 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec_id.h @@ -0,0 +1,668 @@ +/* + * Codec IDs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_ID_H +#define AVCODEC_CODEC_ID_H + +#include "libavutil/avutil.h" +#include "libavutil/samplefmt.h" + +#include "version_major.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * Identify the syntax and semantics of the bitstream. + * The principle is roughly: + * Two decoders with the same ID can decode the same streams. + * Two encoders with the same ID can encode compatible streams. + * There may be slight deviations from the principle due to implementation + * details. + * + * If you add a codec ID to this list, add it so that + * 1. no value of an existing codec ID changes (that would break ABI), + * 2. it is as close as possible to similar codecs + * + * After adding new codec IDs, do not forget to add an entry to the codec + * descriptor list and bump libavcodec minor version. + */ +enum AVCodecID { + AV_CODEC_ID_NONE, + + /* video codecs */ + AV_CODEC_ID_MPEG1VIDEO, + AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding + AV_CODEC_ID_H261, + AV_CODEC_ID_H263, + AV_CODEC_ID_RV10, + AV_CODEC_ID_RV20, + AV_CODEC_ID_MJPEG, + AV_CODEC_ID_MJPEGB, + AV_CODEC_ID_LJPEG, + AV_CODEC_ID_SP5X, + AV_CODEC_ID_JPEGLS, + AV_CODEC_ID_MPEG4, + AV_CODEC_ID_RAWVIDEO, + AV_CODEC_ID_MSMPEG4V1, + AV_CODEC_ID_MSMPEG4V2, + AV_CODEC_ID_MSMPEG4V3, + AV_CODEC_ID_WMV1, + AV_CODEC_ID_WMV2, + AV_CODEC_ID_H263P, + AV_CODEC_ID_H263I, + AV_CODEC_ID_FLV1, + AV_CODEC_ID_SVQ1, + AV_CODEC_ID_SVQ3, + AV_CODEC_ID_DVVIDEO, + AV_CODEC_ID_HUFFYUV, + AV_CODEC_ID_CYUV, + AV_CODEC_ID_H264, + AV_CODEC_ID_INDEO3, + AV_CODEC_ID_VP3, + AV_CODEC_ID_THEORA, + AV_CODEC_ID_ASV1, + AV_CODEC_ID_ASV2, + AV_CODEC_ID_FFV1, + AV_CODEC_ID_4XM, + AV_CODEC_ID_VCR1, + AV_CODEC_ID_CLJR, + AV_CODEC_ID_MDEC, + AV_CODEC_ID_ROQ, + AV_CODEC_ID_INTERPLAY_VIDEO, + AV_CODEC_ID_XAN_WC3, + AV_CODEC_ID_XAN_WC4, + AV_CODEC_ID_RPZA, + AV_CODEC_ID_CINEPAK, + AV_CODEC_ID_WS_VQA, + AV_CODEC_ID_MSRLE, + AV_CODEC_ID_MSVIDEO1, + AV_CODEC_ID_IDCIN, + AV_CODEC_ID_8BPS, + AV_CODEC_ID_SMC, + AV_CODEC_ID_FLIC, + AV_CODEC_ID_TRUEMOTION1, + AV_CODEC_ID_VMDVIDEO, + AV_CODEC_ID_MSZH, + AV_CODEC_ID_ZLIB, + AV_CODEC_ID_QTRLE, + AV_CODEC_ID_TSCC, + AV_CODEC_ID_ULTI, + AV_CODEC_ID_QDRAW, + AV_CODEC_ID_VIXL, + AV_CODEC_ID_QPEG, + AV_CODEC_ID_PNG, + AV_CODEC_ID_PPM, + AV_CODEC_ID_PBM, + AV_CODEC_ID_PGM, + AV_CODEC_ID_PGMYUV, + AV_CODEC_ID_PAM, + AV_CODEC_ID_FFVHUFF, + AV_CODEC_ID_RV30, + AV_CODEC_ID_RV40, + AV_CODEC_ID_VC1, + AV_CODEC_ID_WMV3, + AV_CODEC_ID_LOCO, + AV_CODEC_ID_WNV1, + AV_CODEC_ID_AASC, + AV_CODEC_ID_INDEO2, + AV_CODEC_ID_FRAPS, + AV_CODEC_ID_TRUEMOTION2, + AV_CODEC_ID_BMP, + AV_CODEC_ID_CSCD, + AV_CODEC_ID_MMVIDEO, + AV_CODEC_ID_ZMBV, + AV_CODEC_ID_AVS, + AV_CODEC_ID_SMACKVIDEO, + AV_CODEC_ID_NUV, + AV_CODEC_ID_KMVC, + AV_CODEC_ID_FLASHSV, + AV_CODEC_ID_CAVS, + AV_CODEC_ID_JPEG2000, + AV_CODEC_ID_VMNC, + AV_CODEC_ID_VP5, + AV_CODEC_ID_VP6, + AV_CODEC_ID_VP6F, + AV_CODEC_ID_TARGA, + AV_CODEC_ID_DSICINVIDEO, + AV_CODEC_ID_TIERTEXSEQVIDEO, + AV_CODEC_ID_TIFF, + AV_CODEC_ID_GIF, + AV_CODEC_ID_DXA, + AV_CODEC_ID_DNXHD, + AV_CODEC_ID_THP, + AV_CODEC_ID_SGI, + AV_CODEC_ID_C93, + AV_CODEC_ID_BETHSOFTVID, + AV_CODEC_ID_PTX, + AV_CODEC_ID_TXD, + AV_CODEC_ID_VP6A, + AV_CODEC_ID_AMV, + AV_CODEC_ID_VB, + AV_CODEC_ID_PCX, + AV_CODEC_ID_SUNRAST, + AV_CODEC_ID_INDEO4, + AV_CODEC_ID_INDEO5, + AV_CODEC_ID_MIMIC, + AV_CODEC_ID_RL2, + AV_CODEC_ID_ESCAPE124, + AV_CODEC_ID_DIRAC, + AV_CODEC_ID_BFI, + AV_CODEC_ID_CMV, + AV_CODEC_ID_MOTIONPIXELS, + AV_CODEC_ID_TGV, + AV_CODEC_ID_TGQ, + AV_CODEC_ID_TQI, + AV_CODEC_ID_AURA, + AV_CODEC_ID_AURA2, + AV_CODEC_ID_V210X, + AV_CODEC_ID_TMV, + AV_CODEC_ID_V210, + AV_CODEC_ID_DPX, + AV_CODEC_ID_MAD, + AV_CODEC_ID_FRWU, + AV_CODEC_ID_FLASHSV2, + AV_CODEC_ID_CDGRAPHICS, + AV_CODEC_ID_R210, + AV_CODEC_ID_ANM, + AV_CODEC_ID_BINKVIDEO, + AV_CODEC_ID_IFF_ILBM, +#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM + AV_CODEC_ID_KGV1, + AV_CODEC_ID_YOP, + AV_CODEC_ID_VP8, + AV_CODEC_ID_PICTOR, + AV_CODEC_ID_ANSI, + AV_CODEC_ID_A64_MULTI, + AV_CODEC_ID_A64_MULTI5, + AV_CODEC_ID_R10K, + AV_CODEC_ID_MXPEG, + AV_CODEC_ID_LAGARITH, + AV_CODEC_ID_PRORES, + AV_CODEC_ID_JV, + AV_CODEC_ID_DFA, + AV_CODEC_ID_WMV3IMAGE, + AV_CODEC_ID_VC1IMAGE, + AV_CODEC_ID_UTVIDEO, + AV_CODEC_ID_BMV_VIDEO, + AV_CODEC_ID_VBLE, + AV_CODEC_ID_DXTORY, + AV_CODEC_ID_V410, + AV_CODEC_ID_XWD, + AV_CODEC_ID_CDXL, + AV_CODEC_ID_XBM, + AV_CODEC_ID_ZEROCODEC, + AV_CODEC_ID_MSS1, + AV_CODEC_ID_MSA1, + AV_CODEC_ID_TSCC2, + AV_CODEC_ID_MTS2, + AV_CODEC_ID_CLLC, + AV_CODEC_ID_MSS2, + AV_CODEC_ID_VP9, + AV_CODEC_ID_AIC, + AV_CODEC_ID_ESCAPE130, + AV_CODEC_ID_G2M, + AV_CODEC_ID_WEBP, + AV_CODEC_ID_HNM4_VIDEO, + AV_CODEC_ID_HEVC, +#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC + AV_CODEC_ID_FIC, + AV_CODEC_ID_ALIAS_PIX, + AV_CODEC_ID_BRENDER_PIX, + AV_CODEC_ID_PAF_VIDEO, + AV_CODEC_ID_EXR, + AV_CODEC_ID_VP7, + AV_CODEC_ID_SANM, + AV_CODEC_ID_SGIRLE, + AV_CODEC_ID_MVC1, + AV_CODEC_ID_MVC2, + AV_CODEC_ID_HQX, + AV_CODEC_ID_TDSC, + AV_CODEC_ID_HQ_HQA, + AV_CODEC_ID_HAP, + AV_CODEC_ID_DDS, + AV_CODEC_ID_DXV, + AV_CODEC_ID_SCREENPRESSO, + AV_CODEC_ID_RSCC, + AV_CODEC_ID_AVS2, + AV_CODEC_ID_PGX, + AV_CODEC_ID_AVS3, + AV_CODEC_ID_MSP2, + AV_CODEC_ID_VVC, +#define AV_CODEC_ID_H266 AV_CODEC_ID_VVC + AV_CODEC_ID_Y41P, + AV_CODEC_ID_AVRP, + AV_CODEC_ID_012V, + AV_CODEC_ID_AVUI, +#if FF_API_AYUV_CODECID + AV_CODEC_ID_AYUV, +#endif + AV_CODEC_ID_TARGA_Y216, + AV_CODEC_ID_V308, + AV_CODEC_ID_V408, + AV_CODEC_ID_YUV4, + AV_CODEC_ID_AVRN, + AV_CODEC_ID_CPIA, + AV_CODEC_ID_XFACE, + AV_CODEC_ID_SNOW, + AV_CODEC_ID_SMVJPEG, + AV_CODEC_ID_APNG, + AV_CODEC_ID_DAALA, + AV_CODEC_ID_CFHD, + AV_CODEC_ID_TRUEMOTION2RT, + AV_CODEC_ID_M101, + AV_CODEC_ID_MAGICYUV, + AV_CODEC_ID_SHEERVIDEO, + AV_CODEC_ID_YLC, + AV_CODEC_ID_PSD, + AV_CODEC_ID_PIXLET, + AV_CODEC_ID_SPEEDHQ, + AV_CODEC_ID_FMVC, + AV_CODEC_ID_SCPR, + AV_CODEC_ID_CLEARVIDEO, + AV_CODEC_ID_XPM, + AV_CODEC_ID_AV1, + AV_CODEC_ID_BITPACKED, + AV_CODEC_ID_MSCC, + AV_CODEC_ID_SRGC, + AV_CODEC_ID_SVG, + AV_CODEC_ID_GDV, + AV_CODEC_ID_FITS, + AV_CODEC_ID_IMM4, + AV_CODEC_ID_PROSUMER, + AV_CODEC_ID_MWSC, + AV_CODEC_ID_WCMV, + AV_CODEC_ID_RASC, + AV_CODEC_ID_HYMT, + AV_CODEC_ID_ARBC, + AV_CODEC_ID_AGM, + AV_CODEC_ID_LSCR, + AV_CODEC_ID_VP4, + AV_CODEC_ID_IMM5, + AV_CODEC_ID_MVDV, + AV_CODEC_ID_MVHA, + AV_CODEC_ID_CDTOONS, + AV_CODEC_ID_MV30, + AV_CODEC_ID_NOTCHLC, + AV_CODEC_ID_PFM, + AV_CODEC_ID_MOBICLIP, + AV_CODEC_ID_PHOTOCD, + AV_CODEC_ID_IPU, + AV_CODEC_ID_ARGO, + AV_CODEC_ID_CRI, + AV_CODEC_ID_SIMBIOSIS_IMX, + AV_CODEC_ID_SGA_VIDEO, + AV_CODEC_ID_GEM, + AV_CODEC_ID_VBN, + AV_CODEC_ID_JPEGXL, + AV_CODEC_ID_QOI, + AV_CODEC_ID_PHM, + AV_CODEC_ID_RADIANCE_HDR, + AV_CODEC_ID_WBMP, + AV_CODEC_ID_MEDIA100, + AV_CODEC_ID_VQC, + AV_CODEC_ID_PDV, + AV_CODEC_ID_EVC, + AV_CODEC_ID_RTV1, + AV_CODEC_ID_VMIX, + + /* various PCM "codecs" */ + AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs + AV_CODEC_ID_PCM_S16LE = 0x10000, + AV_CODEC_ID_PCM_S16BE, + AV_CODEC_ID_PCM_U16LE, + AV_CODEC_ID_PCM_U16BE, + AV_CODEC_ID_PCM_S8, + AV_CODEC_ID_PCM_U8, + AV_CODEC_ID_PCM_MULAW, + AV_CODEC_ID_PCM_ALAW, + AV_CODEC_ID_PCM_S32LE, + AV_CODEC_ID_PCM_S32BE, + AV_CODEC_ID_PCM_U32LE, + AV_CODEC_ID_PCM_U32BE, + AV_CODEC_ID_PCM_S24LE, + AV_CODEC_ID_PCM_S24BE, + AV_CODEC_ID_PCM_U24LE, + AV_CODEC_ID_PCM_U24BE, + AV_CODEC_ID_PCM_S24DAUD, + AV_CODEC_ID_PCM_ZORK, + AV_CODEC_ID_PCM_S16LE_PLANAR, + AV_CODEC_ID_PCM_DVD, + AV_CODEC_ID_PCM_F32BE, + AV_CODEC_ID_PCM_F32LE, + AV_CODEC_ID_PCM_F64BE, + AV_CODEC_ID_PCM_F64LE, + AV_CODEC_ID_PCM_BLURAY, + AV_CODEC_ID_PCM_LXF, + AV_CODEC_ID_S302M, + AV_CODEC_ID_PCM_S8_PLANAR, + AV_CODEC_ID_PCM_S24LE_PLANAR, + AV_CODEC_ID_PCM_S32LE_PLANAR, + AV_CODEC_ID_PCM_S16BE_PLANAR, + AV_CODEC_ID_PCM_S64LE, + AV_CODEC_ID_PCM_S64BE, + AV_CODEC_ID_PCM_F16LE, + AV_CODEC_ID_PCM_F24LE, + AV_CODEC_ID_PCM_VIDC, + AV_CODEC_ID_PCM_SGA, + + /* various ADPCM codecs */ + AV_CODEC_ID_ADPCM_IMA_QT = 0x11000, + AV_CODEC_ID_ADPCM_IMA_WAV, + AV_CODEC_ID_ADPCM_IMA_DK3, + AV_CODEC_ID_ADPCM_IMA_DK4, + AV_CODEC_ID_ADPCM_IMA_WS, + AV_CODEC_ID_ADPCM_IMA_SMJPEG, + AV_CODEC_ID_ADPCM_MS, + AV_CODEC_ID_ADPCM_4XM, + AV_CODEC_ID_ADPCM_XA, + AV_CODEC_ID_ADPCM_ADX, + AV_CODEC_ID_ADPCM_EA, + AV_CODEC_ID_ADPCM_G726, + AV_CODEC_ID_ADPCM_CT, + AV_CODEC_ID_ADPCM_SWF, + AV_CODEC_ID_ADPCM_YAMAHA, + AV_CODEC_ID_ADPCM_SBPRO_4, + AV_CODEC_ID_ADPCM_SBPRO_3, + AV_CODEC_ID_ADPCM_SBPRO_2, + AV_CODEC_ID_ADPCM_THP, + AV_CODEC_ID_ADPCM_IMA_AMV, + AV_CODEC_ID_ADPCM_EA_R1, + AV_CODEC_ID_ADPCM_EA_R3, + AV_CODEC_ID_ADPCM_EA_R2, + AV_CODEC_ID_ADPCM_IMA_EA_SEAD, + AV_CODEC_ID_ADPCM_IMA_EA_EACS, + AV_CODEC_ID_ADPCM_EA_XAS, + AV_CODEC_ID_ADPCM_EA_MAXIS_XA, + AV_CODEC_ID_ADPCM_IMA_ISS, + AV_CODEC_ID_ADPCM_G722, + AV_CODEC_ID_ADPCM_IMA_APC, + AV_CODEC_ID_ADPCM_VIMA, + AV_CODEC_ID_ADPCM_AFC, + AV_CODEC_ID_ADPCM_IMA_OKI, + AV_CODEC_ID_ADPCM_DTK, + AV_CODEC_ID_ADPCM_IMA_RAD, + AV_CODEC_ID_ADPCM_G726LE, + AV_CODEC_ID_ADPCM_THP_LE, + AV_CODEC_ID_ADPCM_PSX, + AV_CODEC_ID_ADPCM_AICA, + AV_CODEC_ID_ADPCM_IMA_DAT4, + AV_CODEC_ID_ADPCM_MTAF, + AV_CODEC_ID_ADPCM_AGM, + AV_CODEC_ID_ADPCM_ARGO, + AV_CODEC_ID_ADPCM_IMA_SSI, + AV_CODEC_ID_ADPCM_ZORK, + AV_CODEC_ID_ADPCM_IMA_APM, + AV_CODEC_ID_ADPCM_IMA_ALP, + AV_CODEC_ID_ADPCM_IMA_MTF, + AV_CODEC_ID_ADPCM_IMA_CUNNING, + AV_CODEC_ID_ADPCM_IMA_MOFLEX, + AV_CODEC_ID_ADPCM_IMA_ACORN, + AV_CODEC_ID_ADPCM_XMD, + + /* AMR */ + AV_CODEC_ID_AMR_NB = 0x12000, + AV_CODEC_ID_AMR_WB, + + /* RealAudio codecs*/ + AV_CODEC_ID_RA_144 = 0x13000, + AV_CODEC_ID_RA_288, + + /* various DPCM codecs */ + AV_CODEC_ID_ROQ_DPCM = 0x14000, + AV_CODEC_ID_INTERPLAY_DPCM, + AV_CODEC_ID_XAN_DPCM, + AV_CODEC_ID_SOL_DPCM, + AV_CODEC_ID_SDX2_DPCM, + AV_CODEC_ID_GREMLIN_DPCM, + AV_CODEC_ID_DERF_DPCM, + AV_CODEC_ID_WADY_DPCM, + AV_CODEC_ID_CBD2_DPCM, + + /* audio codecs */ + AV_CODEC_ID_MP2 = 0x15000, + AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 + AV_CODEC_ID_AAC, + AV_CODEC_ID_AC3, + AV_CODEC_ID_DTS, + AV_CODEC_ID_VORBIS, + AV_CODEC_ID_DVAUDIO, + AV_CODEC_ID_WMAV1, + AV_CODEC_ID_WMAV2, + AV_CODEC_ID_MACE3, + AV_CODEC_ID_MACE6, + AV_CODEC_ID_VMDAUDIO, + AV_CODEC_ID_FLAC, + AV_CODEC_ID_MP3ADU, + AV_CODEC_ID_MP3ON4, + AV_CODEC_ID_SHORTEN, + AV_CODEC_ID_ALAC, + AV_CODEC_ID_WESTWOOD_SND1, + AV_CODEC_ID_GSM, ///< as in Berlin toast format + AV_CODEC_ID_QDM2, + AV_CODEC_ID_COOK, + AV_CODEC_ID_TRUESPEECH, + AV_CODEC_ID_TTA, + AV_CODEC_ID_SMACKAUDIO, + AV_CODEC_ID_QCELP, + AV_CODEC_ID_WAVPACK, + AV_CODEC_ID_DSICINAUDIO, + AV_CODEC_ID_IMC, + AV_CODEC_ID_MUSEPACK7, + AV_CODEC_ID_MLP, + AV_CODEC_ID_GSM_MS, /* as found in WAV */ + AV_CODEC_ID_ATRAC3, + AV_CODEC_ID_APE, + AV_CODEC_ID_NELLYMOSER, + AV_CODEC_ID_MUSEPACK8, + AV_CODEC_ID_SPEEX, + AV_CODEC_ID_WMAVOICE, + AV_CODEC_ID_WMAPRO, + AV_CODEC_ID_WMALOSSLESS, + AV_CODEC_ID_ATRAC3P, + AV_CODEC_ID_EAC3, + AV_CODEC_ID_SIPR, + AV_CODEC_ID_MP1, + AV_CODEC_ID_TWINVQ, + AV_CODEC_ID_TRUEHD, + AV_CODEC_ID_MP4ALS, + AV_CODEC_ID_ATRAC1, + AV_CODEC_ID_BINKAUDIO_RDFT, + AV_CODEC_ID_BINKAUDIO_DCT, + AV_CODEC_ID_AAC_LATM, + AV_CODEC_ID_QDMC, + AV_CODEC_ID_CELT, + AV_CODEC_ID_G723_1, + AV_CODEC_ID_G729, + AV_CODEC_ID_8SVX_EXP, + AV_CODEC_ID_8SVX_FIB, + AV_CODEC_ID_BMV_AUDIO, + AV_CODEC_ID_RALF, + AV_CODEC_ID_IAC, + AV_CODEC_ID_ILBC, + AV_CODEC_ID_OPUS, + AV_CODEC_ID_COMFORT_NOISE, + AV_CODEC_ID_TAK, + AV_CODEC_ID_METASOUND, + AV_CODEC_ID_PAF_AUDIO, + AV_CODEC_ID_ON2AVC, + AV_CODEC_ID_DSS_SP, + AV_CODEC_ID_CODEC2, + AV_CODEC_ID_FFWAVESYNTH, + AV_CODEC_ID_SONIC, + AV_CODEC_ID_SONIC_LS, + AV_CODEC_ID_EVRC, + AV_CODEC_ID_SMV, + AV_CODEC_ID_DSD_LSBF, + AV_CODEC_ID_DSD_MSBF, + AV_CODEC_ID_DSD_LSBF_PLANAR, + AV_CODEC_ID_DSD_MSBF_PLANAR, + AV_CODEC_ID_4GV, + AV_CODEC_ID_INTERPLAY_ACM, + AV_CODEC_ID_XMA1, + AV_CODEC_ID_XMA2, + AV_CODEC_ID_DST, + AV_CODEC_ID_ATRAC3AL, + AV_CODEC_ID_ATRAC3PAL, + AV_CODEC_ID_DOLBY_E, + AV_CODEC_ID_APTX, + AV_CODEC_ID_APTX_HD, + AV_CODEC_ID_SBC, + AV_CODEC_ID_ATRAC9, + AV_CODEC_ID_HCOM, + AV_CODEC_ID_ACELP_KELVIN, + AV_CODEC_ID_MPEGH_3D_AUDIO, + AV_CODEC_ID_SIREN, + AV_CODEC_ID_HCA, + AV_CODEC_ID_FASTAUDIO, + AV_CODEC_ID_MSNSIREN, + AV_CODEC_ID_DFPWM, + AV_CODEC_ID_BONK, + AV_CODEC_ID_MISC4, + AV_CODEC_ID_APAC, + AV_CODEC_ID_FTR, + AV_CODEC_ID_WAVARC, + AV_CODEC_ID_RKA, + AV_CODEC_ID_AC4, + AV_CODEC_ID_OSQ, + + /* subtitle codecs */ + AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. + AV_CODEC_ID_DVD_SUBTITLE = 0x17000, + AV_CODEC_ID_DVB_SUBTITLE, + AV_CODEC_ID_TEXT, ///< raw UTF-8 text + AV_CODEC_ID_XSUB, + AV_CODEC_ID_SSA, + AV_CODEC_ID_MOV_TEXT, + AV_CODEC_ID_HDMV_PGS_SUBTITLE, + AV_CODEC_ID_DVB_TELETEXT, + AV_CODEC_ID_SRT, + AV_CODEC_ID_MICRODVD, + AV_CODEC_ID_EIA_608, + AV_CODEC_ID_JACOSUB, + AV_CODEC_ID_SAMI, + AV_CODEC_ID_REALTEXT, + AV_CODEC_ID_STL, + AV_CODEC_ID_SUBVIEWER1, + AV_CODEC_ID_SUBVIEWER, + AV_CODEC_ID_SUBRIP, + AV_CODEC_ID_WEBVTT, + AV_CODEC_ID_MPL2, + AV_CODEC_ID_VPLAYER, + AV_CODEC_ID_PJS, + AV_CODEC_ID_ASS, + AV_CODEC_ID_HDMV_TEXT_SUBTITLE, + AV_CODEC_ID_TTML, + AV_CODEC_ID_ARIB_CAPTION, + + /* other specific kind of codecs (generally used for attachments) */ + AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. + AV_CODEC_ID_TTF = 0x18000, + + AV_CODEC_ID_SCTE_35, ///< Contain timestamp estimated through PCR of program stream. + AV_CODEC_ID_EPG, + AV_CODEC_ID_BINTEXT, + AV_CODEC_ID_XBIN, + AV_CODEC_ID_IDF, + AV_CODEC_ID_OTF, + AV_CODEC_ID_SMPTE_KLV, + AV_CODEC_ID_DVD_NAV, + AV_CODEC_ID_TIMED_ID3, + AV_CODEC_ID_BIN_DATA, + AV_CODEC_ID_SMPTE_2038, + + + AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it + + AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + * stream (only used by libavformat) */ + AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems + * stream (only used by libavformat) */ + AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. + AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket + /** + * Dummy null video codec, useful mainly for development and debugging. + * Null encoder/decoder discard all input and never return any output. + */ + AV_CODEC_ID_VNULL, + /** + * Dummy null audio codec, useful mainly for development and debugging. + * Null encoder/decoder discard all input and never return any output. + */ + AV_CODEC_ID_ANULL, +}; + +/** + * Get the type of the given codec. + */ +enum AVMediaType avcodec_get_type(enum AVCodecID codec_id); + +/** + * Get the name of a codec. + * @return a static string identifying the codec; never NULL + */ +const char *avcodec_get_name(enum AVCodecID id); + +/** + * Return codec bits per sample. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return codec bits per sample. + * Only return non-zero if the bits per sample is exactly correct, not an + * approximation. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_exact_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return a name for the specified profile, if available. + * + * @param codec_id the ID of the codec to which the requested profile belongs + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + * + * @note unlike av_get_profile_name(), which searches a list of profiles + * supported by a specific decoder or encoder implementation, this + * function searches the list of profiles from the AVCodecDescriptor + */ +const char *avcodec_profile_name(enum AVCodecID codec_id, int profile); + +/** + * Return the PCM codec associated with a sample format. + * @param be endianness, 0 for little, 1 for big, + * -1 (or anything else) for native + * @return AV_CODEC_ID_PCM_* or AV_CODEC_ID_NONE + */ +enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_ID_H diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec_par.h b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec_par.h new file mode 100644 index 0000000000000..64882a97264e5 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/codec_par.h @@ -0,0 +1,262 @@ +/* + * Codec parameters public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_PAR_H +#define AVCODEC_CODEC_PAR_H + +#include + +#include "libavutil/avutil.h" +#include "libavutil/channel_layout.h" +#include "libavutil/rational.h" +#include "libavutil/pixfmt.h" + +#include "codec_id.h" +#include "defs.h" +#include "packet.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * This struct describes the properties of an encoded stream. + * + * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must + * be allocated with avcodec_parameters_alloc() and freed with + * avcodec_parameters_free(). + */ +typedef struct AVCodecParameters { + /** + * General type of the encoded data. + */ + enum AVMediaType codec_type; + /** + * Specific type of the encoded data (the codec used). + */ + enum AVCodecID codec_id; + /** + * Additional information about the codec (corresponds to the AVI FOURCC). + */ + uint32_t codec_tag; + + /** + * Extra binary data needed for initializing the decoder, codec-dependent. + * + * Must be allocated with av_malloc() and will be freed by + * avcodec_parameters_free(). The allocated size of extradata must be at + * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding + * bytes zeroed. + */ + uint8_t *extradata; + /** + * Size of the extradata content in bytes. + */ + int extradata_size; + + /** + * - video: the pixel format, the value corresponds to enum AVPixelFormat. + * - audio: the sample format, the value corresponds to enum AVSampleFormat. + */ + int format; + + /** + * The average bitrate of the encoded data (in bits per second). + */ + int64_t bit_rate; + + /** + * The number of bits per sample in the codedwords. + * + * This is basically the bitrate per sample. It is mandatory for a bunch of + * formats to actually decode them. It's the number of bits for one sample in + * the actual coded bitstream. + * + * This could be for example 4 for ADPCM + * For PCM formats this matches bits_per_raw_sample + * Can be 0 + */ + int bits_per_coded_sample; + + /** + * This is the number of valid bits in each output sample. If the + * sample format has more bits, the least significant bits are additional + * padding bits, which are always 0. Use right shifts to reduce the sample + * to its actual size. For example, audio formats with 24 bit samples will + * have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32. + * To get the original sample use "(int32_t)sample >> 8"." + * + * For ADPCM this might be 12 or 16 or similar + * Can be 0 + */ + int bits_per_raw_sample; + + /** + * Codec-specific bitstream restrictions that the stream conforms to. + */ + int profile; + int level; + + /** + * Video only. The dimensions of the video frame in pixels. + */ + int width; + int height; + + /** + * Video only. The aspect ratio (width / height) which a single pixel + * should have when displayed. + * + * When the aspect ratio is unknown / undefined, the numerator should be + * set to 0 (the denominator may have any value). + */ + AVRational sample_aspect_ratio; + + /** + * Video only. The order of the fields in interlaced video. + */ + enum AVFieldOrder field_order; + + /** + * Video only. Additional colorspace characteristics. + */ + enum AVColorRange color_range; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace color_space; + enum AVChromaLocation chroma_location; + + /** + * Video only. Number of delayed frames. + */ + int video_delay; + +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * Audio only. The channel layout bitmask. May be 0 if the channel layout is + * unknown or unspecified, otherwise the number of bits set must be equal to + * the channels field. + * @deprecated use ch_layout + */ + attribute_deprecated + uint64_t channel_layout; + /** + * Audio only. The number of audio channels. + * @deprecated use ch_layout.nb_channels + */ + attribute_deprecated + int channels; +#endif + /** + * Audio only. The number of audio samples per second. + */ + int sample_rate; + /** + * Audio only. The number of bytes per coded audio frame, required by some + * formats. + * + * Corresponds to nBlockAlign in WAVEFORMATEX. + */ + int block_align; + /** + * Audio only. Audio frame size, if known. Required by some formats to be static. + */ + int frame_size; + + /** + * Audio only. The amount of padding (in samples) inserted by the encoder at + * the beginning of the audio. I.e. this number of leading decoded samples + * must be discarded by the caller to get the original audio without leading + * padding. + */ + int initial_padding; + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + */ + int trailing_padding; + /** + * Audio only. Number of samples to skip after a discontinuity. + */ + int seek_preroll; + + /** + * Audio only. The channel layout and number of channels. + */ + AVChannelLayout ch_layout; + + /** + * Video only. Number of frames per second, for streams with constant frame + * durations. Should be set to { 0, 1 } when some frames have differing + * durations or if the value is not known. + * + * @note This field correponds to values that are stored in codec-level + * headers and is typically overridden by container/transport-layer + * timestamps, when available. It should thus be used only as a last resort, + * when no higher-level timing information is available. + */ + AVRational framerate; + + /** + * Additional data associated with the entire stream. + */ + AVPacketSideData *coded_side_data; + + /** + * Amount of entries in @ref coded_side_data. + */ + int nb_coded_side_data; +} AVCodecParameters; + +/** + * Allocate a new AVCodecParameters and set its fields to default values + * (unknown/invalid/0). The returned struct must be freed with + * avcodec_parameters_free(). + */ +AVCodecParameters *avcodec_parameters_alloc(void); + +/** + * Free an AVCodecParameters instance and everything associated with it and + * write NULL to the supplied pointer. + */ +void avcodec_parameters_free(AVCodecParameters **par); + +/** + * Copy the contents of src to dst. Any allocated fields in dst are freed and + * replaced with newly allocated duplicates of the corresponding fields in src. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src); + +/** + * This function is the same as av_get_audio_frame_duration(), except it works + * with AVCodecParameters instead of an AVCodecContext. + */ +int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_PAR_H diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/defs.h b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/defs.h new file mode 100644 index 0000000000000..00d840ec19b6f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/defs.h @@ -0,0 +1,335 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DEFS_H +#define AVCODEC_DEFS_H + +/** + * @file + * @ingroup libavc + * Misc types and constants that do not belong anywhere else. + */ + +#include +#include + +/** + * @ingroup lavc_decoding + * Required number of additionally allocated bytes at the end of the input bitstream for decoding. + * This is mainly needed because some optimized bitstream readers read + * 32 or 64 bit at once and could read over the end.
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged + * MPEG bitstreams could cause overread and segfault. + */ +#define AV_INPUT_BUFFER_PADDING_SIZE 64 + +/** + * Verify checksums embedded in the bitstream (could be of either encoded or + * decoded data, depending on the format) and print an error message on mismatch. + * If AV_EF_EXPLODE is also set, a mismatching checksum will result in the + * decoder/demuxer returning an error. + */ +#define AV_EF_CRCCHECK (1<<0) +#define AV_EF_BITSTREAM (1<<1) ///< detect bitstream specification deviations +#define AV_EF_BUFFER (1<<2) ///< detect improper bitstream length +#define AV_EF_EXPLODE (1<<3) ///< abort decoding on minor error detection + +#define AV_EF_IGNORE_ERR (1<<15) ///< ignore errors and continue +#define AV_EF_CAREFUL (1<<16) ///< consider things that violate the spec, are fast to calculate and have not been seen in the wild as errors +#define AV_EF_COMPLIANT (1<<17) ///< consider all spec non compliances as errors +#define AV_EF_AGGRESSIVE (1<<18) ///< consider things that a sane encoder/muxer should not do as an error + +#define FF_COMPLIANCE_VERY_STRICT 2 ///< Strictly conform to an older more strict version of the spec or reference software. +#define FF_COMPLIANCE_STRICT 1 ///< Strictly conform to all the things in the spec no matter what consequences. +#define FF_COMPLIANCE_NORMAL 0 +#define FF_COMPLIANCE_UNOFFICIAL -1 ///< Allow unofficial extensions +#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things. + + +#define AV_PROFILE_UNKNOWN -99 +#define AV_PROFILE_RESERVED -100 + +#define AV_PROFILE_AAC_MAIN 0 +#define AV_PROFILE_AAC_LOW 1 +#define AV_PROFILE_AAC_SSR 2 +#define AV_PROFILE_AAC_LTP 3 +#define AV_PROFILE_AAC_HE 4 +#define AV_PROFILE_AAC_HE_V2 28 +#define AV_PROFILE_AAC_LD 22 +#define AV_PROFILE_AAC_ELD 38 +#define AV_PROFILE_MPEG2_AAC_LOW 128 +#define AV_PROFILE_MPEG2_AAC_HE 131 + +#define AV_PROFILE_DNXHD 0 +#define AV_PROFILE_DNXHR_LB 1 +#define AV_PROFILE_DNXHR_SQ 2 +#define AV_PROFILE_DNXHR_HQ 3 +#define AV_PROFILE_DNXHR_HQX 4 +#define AV_PROFILE_DNXHR_444 5 + +#define AV_PROFILE_DTS 20 +#define AV_PROFILE_DTS_ES 30 +#define AV_PROFILE_DTS_96_24 40 +#define AV_PROFILE_DTS_HD_HRA 50 +#define AV_PROFILE_DTS_HD_MA 60 +#define AV_PROFILE_DTS_EXPRESS 70 +#define AV_PROFILE_DTS_HD_MA_X 61 +#define AV_PROFILE_DTS_HD_MA_X_IMAX 62 + +#define AV_PROFILE_EAC3_DDP_ATMOS 30 + +#define AV_PROFILE_TRUEHD_ATMOS 30 + +#define AV_PROFILE_MPEG2_422 0 +#define AV_PROFILE_MPEG2_HIGH 1 +#define AV_PROFILE_MPEG2_SS 2 +#define AV_PROFILE_MPEG2_SNR_SCALABLE 3 +#define AV_PROFILE_MPEG2_MAIN 4 +#define AV_PROFILE_MPEG2_SIMPLE 5 + +#define AV_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag +#define AV_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag + +#define AV_PROFILE_H264_BASELINE 66 +#define AV_PROFILE_H264_CONSTRAINED_BASELINE (66|AV_PROFILE_H264_CONSTRAINED) +#define AV_PROFILE_H264_MAIN 77 +#define AV_PROFILE_H264_EXTENDED 88 +#define AV_PROFILE_H264_HIGH 100 +#define AV_PROFILE_H264_HIGH_10 110 +#define AV_PROFILE_H264_HIGH_10_INTRA (110|AV_PROFILE_H264_INTRA) +#define AV_PROFILE_H264_MULTIVIEW_HIGH 118 +#define AV_PROFILE_H264_HIGH_422 122 +#define AV_PROFILE_H264_HIGH_422_INTRA (122|AV_PROFILE_H264_INTRA) +#define AV_PROFILE_H264_STEREO_HIGH 128 +#define AV_PROFILE_H264_HIGH_444 144 +#define AV_PROFILE_H264_HIGH_444_PREDICTIVE 244 +#define AV_PROFILE_H264_HIGH_444_INTRA (244|AV_PROFILE_H264_INTRA) +#define AV_PROFILE_H264_CAVLC_444 44 + +#define AV_PROFILE_VC1_SIMPLE 0 +#define AV_PROFILE_VC1_MAIN 1 +#define AV_PROFILE_VC1_COMPLEX 2 +#define AV_PROFILE_VC1_ADVANCED 3 + +#define AV_PROFILE_MPEG4_SIMPLE 0 +#define AV_PROFILE_MPEG4_SIMPLE_SCALABLE 1 +#define AV_PROFILE_MPEG4_CORE 2 +#define AV_PROFILE_MPEG4_MAIN 3 +#define AV_PROFILE_MPEG4_N_BIT 4 +#define AV_PROFILE_MPEG4_SCALABLE_TEXTURE 5 +#define AV_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6 +#define AV_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7 +#define AV_PROFILE_MPEG4_HYBRID 8 +#define AV_PROFILE_MPEG4_ADVANCED_REAL_TIME 9 +#define AV_PROFILE_MPEG4_CORE_SCALABLE 10 +#define AV_PROFILE_MPEG4_ADVANCED_CODING 11 +#define AV_PROFILE_MPEG4_ADVANCED_CORE 12 +#define AV_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13 +#define AV_PROFILE_MPEG4_SIMPLE_STUDIO 14 +#define AV_PROFILE_MPEG4_ADVANCED_SIMPLE 15 + +#define AV_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 1 +#define AV_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 2 +#define AV_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION 32768 +#define AV_PROFILE_JPEG2000_DCINEMA_2K 3 +#define AV_PROFILE_JPEG2000_DCINEMA_4K 4 + +#define AV_PROFILE_VP9_0 0 +#define AV_PROFILE_VP9_1 1 +#define AV_PROFILE_VP9_2 2 +#define AV_PROFILE_VP9_3 3 + +#define AV_PROFILE_HEVC_MAIN 1 +#define AV_PROFILE_HEVC_MAIN_10 2 +#define AV_PROFILE_HEVC_MAIN_STILL_PICTURE 3 +#define AV_PROFILE_HEVC_REXT 4 +#define AV_PROFILE_HEVC_SCC 9 + +#define AV_PROFILE_VVC_MAIN_10 1 +#define AV_PROFILE_VVC_MAIN_10_444 33 + +#define AV_PROFILE_AV1_MAIN 0 +#define AV_PROFILE_AV1_HIGH 1 +#define AV_PROFILE_AV1_PROFESSIONAL 2 + +#define AV_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT 0xc0 +#define AV_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1 +#define AV_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT 0xc2 +#define AV_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3 +#define AV_PROFILE_MJPEG_JPEG_LS 0xf7 + +#define AV_PROFILE_SBC_MSBC 1 + +#define AV_PROFILE_PRORES_PROXY 0 +#define AV_PROFILE_PRORES_LT 1 +#define AV_PROFILE_PRORES_STANDARD 2 +#define AV_PROFILE_PRORES_HQ 3 +#define AV_PROFILE_PRORES_4444 4 +#define AV_PROFILE_PRORES_XQ 5 + +#define AV_PROFILE_ARIB_PROFILE_A 0 +#define AV_PROFILE_ARIB_PROFILE_C 1 + +#define AV_PROFILE_KLVA_SYNC 0 +#define AV_PROFILE_KLVA_ASYNC 1 + +#define AV_PROFILE_EVC_BASELINE 0 +#define AV_PROFILE_EVC_MAIN 1 + + +#define AV_LEVEL_UNKNOWN -99 + +enum AVFieldOrder { + AV_FIELD_UNKNOWN, + AV_FIELD_PROGRESSIVE, + AV_FIELD_TT, ///< Top coded_first, top displayed first + AV_FIELD_BB, ///< Bottom coded first, bottom displayed first + AV_FIELD_TB, ///< Top coded first, bottom displayed first + AV_FIELD_BT, ///< Bottom coded first, top displayed first +}; + +/** + * @ingroup lavc_decoding + */ +enum AVDiscard{ + /* We leave some space between them for extensions (drop some + * keyframes for intra-only or drop just some bidir frames). */ + AVDISCARD_NONE =-16, ///< discard nothing + AVDISCARD_DEFAULT = 0, ///< discard useless packets like 0 size packets in avi + AVDISCARD_NONREF = 8, ///< discard all non reference + AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames + AVDISCARD_NONINTRA= 24, ///< discard all non intra frames + AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes + AVDISCARD_ALL = 48, ///< discard all +}; + +enum AVAudioServiceType { + AV_AUDIO_SERVICE_TYPE_MAIN = 0, + AV_AUDIO_SERVICE_TYPE_EFFECTS = 1, + AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED = 2, + AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED = 3, + AV_AUDIO_SERVICE_TYPE_DIALOGUE = 4, + AV_AUDIO_SERVICE_TYPE_COMMENTARY = 5, + AV_AUDIO_SERVICE_TYPE_EMERGENCY = 6, + AV_AUDIO_SERVICE_TYPE_VOICE_OVER = 7, + AV_AUDIO_SERVICE_TYPE_KARAOKE = 8, + AV_AUDIO_SERVICE_TYPE_NB , ///< Not part of ABI +}; + +/** + * Pan Scan area. + * This specifies the area which should be displayed. + * Note there may be multiple such areas for one frame. + */ +typedef struct AVPanScan { + /** + * id + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int id; + + /** + * width and height in 1/16 pel + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int width; + int height; + + /** + * position of the top left corner in 1/16 pel for up to 3 fields/frames + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int16_t position[3][2]; +} AVPanScan; + +/** + * This structure describes the bitrate properties of an encoded bitstream. It + * roughly corresponds to a subset the VBV parameters for MPEG-2 or HRD + * parameters for H.264/HEVC. + */ +typedef struct AVCPBProperties { + /** + * Maximum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int64_t max_bitrate; + /** + * Minimum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int64_t min_bitrate; + /** + * Average bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int64_t avg_bitrate; + + /** + * The size of the buffer to which the ratecontrol is applied, in bits. + * Zero if unknown or unspecified. + */ + int64_t buffer_size; + + /** + * The delay between the time the packet this structure is associated with + * is received and the time when it should be decoded, in periods of a 27MHz + * clock. + * + * UINT64_MAX when unknown or unspecified. + */ + uint64_t vbv_delay; +} AVCPBProperties; + +/** + * Allocate a CPB properties structure and initialize its fields to default + * values. + * + * @param size if non-NULL, the size of the allocated struct will be written + * here. This is useful for embedding it in side data. + * + * @return the newly allocated struct or NULL on failure + */ +AVCPBProperties *av_cpb_properties_alloc(size_t *size); + +/** + * This structure supplies correlation between a packet timestamp and a wall clock + * production time. The definition follows the Producer Reference Time ('prft') + * as defined in ISO/IEC 14496-12 + */ +typedef struct AVProducerReferenceTime { + /** + * A UTC timestamp, in microseconds, since Unix epoch (e.g, av_gettime()). + */ + int64_t wallclock; + int flags; +} AVProducerReferenceTime; + +/** + * Encode extradata length to a buffer. Used by xiph codecs. + * + * @param s buffer to write to; must be at least (v/255+1) bytes long + * @param v size of extradata in bytes + * @return number of bytes written to the buffer. + */ +unsigned int av_xiphlacing(unsigned char *s, unsigned int v); + +#endif // AVCODEC_DEFS_H diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/packet.h b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/packet.h new file mode 100644 index 0000000000000..b19409b7192b0 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/packet.h @@ -0,0 +1,846 @@ +/* + * AVPacket public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_PACKET_H +#define AVCODEC_PACKET_H + +#include +#include + +#include "libavutil/attributes.h" +#include "libavutil/buffer.h" +#include "libavutil/dict.h" +#include "libavutil/rational.h" +#include "libavutil/version.h" + +#include "libavcodec/version_major.h" + +/** + * @defgroup lavc_packet_side_data AVPacketSideData + * + * Types and functions for working with AVPacketSideData. + * @{ + */ +enum AVPacketSideDataType { + /** + * An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE + * bytes worth of palette. This side data signals that a new palette is + * present. + */ + AV_PKT_DATA_PALETTE, + + /** + * The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format + * that the extradata buffer was changed and the receiving side should + * act upon it appropriately. The new extradata is embedded in the side + * data buffer and should be immediately used for processing the current + * frame or packet. + */ + AV_PKT_DATA_NEW_EXTRADATA, + + /** + * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows: + * @code + * u32le param_flags + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) + * s32le channel_count + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) + * u64le channel_layout + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) + * s32le sample_rate + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) + * s32le width + * s32le height + * @endcode + */ + AV_PKT_DATA_PARAM_CHANGE, + + /** + * An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of + * structures with info about macroblocks relevant to splitting the + * packet into smaller packets on macroblock edges (e.g. as for RFC 2190). + * That is, it does not necessarily contain info about all macroblocks, + * as long as the distance between macroblocks in the info is smaller + * than the target payload size. + * Each MB info structure is 12 bytes, and is laid out as follows: + * @code + * u32le bit offset from the start of the packet + * u8 current quantizer at the start of the macroblock + * u8 GOB number + * u16le macroblock address within the GOB + * u8 horizontal MV predictor + * u8 vertical MV predictor + * u8 horizontal MV predictor for block number 3 + * u8 vertical MV predictor for block number 3 + * @endcode + */ + AV_PKT_DATA_H263_MB_INFO, + + /** + * This side data should be associated with an audio stream and contains + * ReplayGain information in form of the AVReplayGain struct. + */ + AV_PKT_DATA_REPLAYGAIN, + + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the decoded video frames for + * correct presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_PKT_DATA_DISPLAYMATRIX, + + /** + * This side data should be associated with a video stream and contains + * Stereoscopic 3D information in form of the AVStereo3D struct. + */ + AV_PKT_DATA_STEREO3D, + + /** + * This side data should be associated with an audio stream and corresponds + * to enum AVAudioServiceType. + */ + AV_PKT_DATA_AUDIO_SERVICE_TYPE, + + /** + * This side data contains quality related information from the encoder. + * @code + * u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad). + * u8 picture type + * u8 error count + * u16 reserved + * u64le[error count] sum of squared differences between encoder in and output + * @endcode + */ + AV_PKT_DATA_QUALITY_STATS, + + /** + * This side data contains an integer value representing the stream index + * of a "fallback" track. A fallback track indicates an alternate + * track to use when the current track can not be decoded for some reason. + * e.g. no decoder available for codec. + */ + AV_PKT_DATA_FALLBACK_TRACK, + + /** + * This side data corresponds to the AVCPBProperties struct. + */ + AV_PKT_DATA_CPB_PROPERTIES, + + /** + * Recommmends skipping the specified number of samples + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_PKT_DATA_SKIP_SAMPLES, + + /** + * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that + * the packet may contain "dual mono" audio specific to Japanese DTV + * and if it is true, recommends only the selected channel to be used. + * @code + * u8 selected channels (0=main/left, 1=sub/right, 2=both) + * @endcode + */ + AV_PKT_DATA_JP_DUALMONO, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. + */ + AV_PKT_DATA_STRINGS_METADATA, + + /** + * Subtitle event position + * @code + * u32le x1 + * u32le y1 + * u32le x2 + * u32le y2 + * @endcode + */ + AV_PKT_DATA_SUBTITLE_POSITION, + + /** + * Data found in BlockAdditional element of matroska container. There is + * no end marker for the data, so it is required to rely on the side data + * size to recognize the end. 8 byte id (as found in BlockAddId) followed + * by data. + */ + AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + + /** + * The optional first identifier line of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_IDENTIFIER, + + /** + * The optional settings (rendering instructions) that immediately + * follow the timestamp specifier of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_SETTINGS, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. This + * side data includes updated metadata which appeared in the stream. + */ + AV_PKT_DATA_METADATA_UPDATE, + + /** + * MPEGTS stream ID as uint8_t, this is required to pass the stream ID + * information from the demuxer to the corresponding muxer. + */ + AV_PKT_DATA_MPEGTS_STREAM_ID, + + /** + * Mastering display metadata (based on SMPTE-2086:2014). This metadata + * should be associated with a video stream and contains data in the form + * of the AVMasteringDisplayMetadata struct. + */ + AV_PKT_DATA_MASTERING_DISPLAY_METADATA, + + /** + * This side data should be associated with a video stream and corresponds + * to the AVSphericalMapping structure. + */ + AV_PKT_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This metadata should be + * associated with a video stream and contains data in the form of the + * AVContentLightMetadata struct. + */ + AV_PKT_DATA_CONTENT_LIGHT_LEVEL, + + /** + * ATSC A53 Part 4 Closed Captions. This metadata should be associated with + * a video stream. A53 CC bitstream is stored as uint8_t in AVPacketSideData.data. + * The number of bytes of CC data is AVPacketSideData.size. + */ + AV_PKT_DATA_A53_CC, + + /** + * This side data is encryption initialization data. + * The format is not part of ABI, use av_encryption_init_info_* methods to + * access. + */ + AV_PKT_DATA_ENCRYPTION_INIT_INFO, + + /** + * This side data contains encryption info for how to decrypt the packet. + * The format is not part of ABI, use av_encryption_info_* methods to access. + */ + AV_PKT_DATA_ENCRYPTION_INFO, + + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_PKT_DATA_AFD, + + /** + * Producer Reference Time data corresponding to the AVProducerReferenceTime struct, + * usually exported by some encoders (on demand through the prft flag set in the + * AVCodecContext export_side_data field). + */ + AV_PKT_DATA_PRFT, + + /** + * ICC profile data consisting of an opaque octet buffer following the + * format described by ISO 15076-1. + */ + AV_PKT_DATA_ICC_PROFILE, + + /** + * DOVI configuration + * ref: + * dolby-vision-bitstreams-within-the-iso-base-media-file-format-v2.1.2, section 2.2 + * dolby-vision-bitstreams-in-mpeg-2-transport-stream-multiplex-v1.2, section 3.3 + * Tags are stored in struct AVDOVIDecoderConfigurationRecord. + */ + AV_PKT_DATA_DOVI_CONF, + + /** + * Timecode which conforms to SMPTE ST 12-1:2014. The data is an array of 4 uint32_t + * where the first uint32_t describes how many (1-3) of the other timecodes are used. + * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.h. + */ + AV_PKT_DATA_S12M_TIMECODE, + + /** + * HDR10+ dynamic metadata associated with a video frame. The metadata is in + * the form of the AVDynamicHDRPlus struct and contains + * information for color volume transform - application 4 of + * SMPTE 2094-40:2016 standard. + */ + AV_PKT_DATA_DYNAMIC_HDR10_PLUS, + + /** + * The number of side data types. + * This is not part of the public API/ABI in the sense that it may + * change when new side data types are added. + * This must stay the last enum value. + * If its value becomes huge, some code using it + * needs to be updated as it assumes it to be smaller than other limits. + */ + AV_PKT_DATA_NB +}; + +#define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED + +/** + * This structure stores auxiliary information for decoding, presenting, or + * otherwise processing the coded stream. It is typically exported by demuxers + * and encoders and can be fed to decoders and muxers either in a per packet + * basis, or as global side data (applying to the entire coded stream). + * + * Global side data is handled as follows: + * - During demuxing, it may be exported through + * @ref AVStream.codecpar.side_data "AVStream's codec parameters", which can + * then be passed as input to decoders through the + * @ref AVCodecContext.coded_side_data "decoder context's side data", for + * initialization. + * - For muxing, it can be fed through @ref AVStream.codecpar.side_data + * "AVStream's codec parameters", typically the output of encoders through + * the @ref AVCodecContext.coded_side_data "encoder context's side data", for + * initialization. + * + * Packet specific side data is handled as follows: + * - During demuxing, it may be exported through @ref AVPacket.side_data + * "AVPacket's side data", which can then be passed as input to decoders. + * - For muxing, it can be fed through @ref AVPacket.side_data "AVPacket's + * side data", typically the output of encoders. + * + * Different modules may accept or export different types of side data + * depending on media type and codec. Refer to @ref AVPacketSideDataType for a + * list of defined types and where they may be found or used. + */ +typedef struct AVPacketSideData { + uint8_t *data; + size_t size; + enum AVPacketSideDataType type; +} AVPacketSideData; + +/** + * Allocate a new packet side data. + * + * @param sd pointer to an array of side data to which the side data should + * be added. *sd may be NULL, in which case the array will be + * initialized. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. The integer value will be increased by 1 on success. + * @param type side data type + * @param size desired side data size + * @param flags currently unused. Must be zero + * + * @return pointer to freshly allocated side data on success, or NULL otherwise. + */ +AVPacketSideData *av_packet_side_data_new(AVPacketSideData **psd, int *pnb_sd, + enum AVPacketSideDataType type, + size_t size, int flags); + +/** + * Wrap existing data as packet side data. + * + * @param sd pointer to an array of side data to which the side data should + * be added. *sd may be NULL, in which case the array will be + * initialized + * @param nb_sd pointer to an integer containing the number of entries in + * the array. The integer value will be increased by 1 on success. + * @param type side data type + * @param data a data array. It must be allocated with the av_malloc() family + * of functions. The ownership of the data is transferred to the + * side data array on success + * @param size size of the data array + * @param flags currently unused. Must be zero + * + * @return pointer to freshly allocated side data on success, or NULL otherwise + * On failure, the side data array is unchanged and the data remains + * owned by the caller. + */ +AVPacketSideData *av_packet_side_data_add(AVPacketSideData **sd, int *nb_sd, + enum AVPacketSideDataType type, + void *data, size_t size, int flags); + +/** + * Get side information from a side data array. + * + * @param sd the array from which the side data should be fetched + * @param nb_sd value containing the number of entries in the array. + * @param type desired side information type + * + * @return pointer to side data if present or NULL otherwise + */ +const AVPacketSideData *av_packet_side_data_get(const AVPacketSideData *sd, + int nb_sd, + enum AVPacketSideDataType type); + +/** + * Remove side data of the given type from a side data array. + * + * @param sd the array from which the side data should be removed + * @param nb_sd pointer to an integer containing the number of entries in + * the array. Will be reduced by the amount of entries removed + * upon return + * @param type side information type + */ +void av_packet_side_data_remove(AVPacketSideData *sd, int *nb_sd, + enum AVPacketSideDataType type); + +/** + * Convenience function to free all the side data stored in an array, and + * the array itself. + * + * @param sd pointer to array of side data to free. Will be set to NULL + * upon return. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. Will be set to 0 upon return. + */ +void av_packet_side_data_free(AVPacketSideData **sd, int *nb_sd); + +const char *av_packet_side_data_name(enum AVPacketSideDataType type); + +/** + * @} + */ + +/** + * @defgroup lavc_packet AVPacket + * + * Types and functions for working with AVPacket. + * @{ + */ + +/** + * This structure stores compressed data. It is typically exported by demuxers + * and then passed as input to decoders, or received as output from encoders and + * then passed to muxers. + * + * For video, it should typically contain one compressed frame. For audio it may + * contain several compressed frames. Encoders are allowed to output empty + * packets, with no compressed data, containing only side data + * (e.g. to update some stream parameters at the end of encoding). + * + * The semantics of data ownership depends on the buf field. + * If it is set, the packet data is dynamically allocated and is + * valid indefinitely until a call to av_packet_unref() reduces the + * reference count to 0. + * + * If the buf field is not set av_packet_ref() would make a copy instead + * of increasing the reference count. + * + * The side data is always allocated with av_malloc(), copied by + * av_packet_ref() and freed by av_packet_unref(). + * + * sizeof(AVPacket) being a part of the public ABI is deprecated. once + * av_init_packet() is removed, new packets will only be able to be allocated + * with av_packet_alloc(), and new fields may be added to the end of the struct + * with a minor bump. + * + * @see av_packet_alloc + * @see av_packet_ref + * @see av_packet_unref + */ +typedef struct AVPacket { + /** + * A reference to the reference-counted buffer where the packet data is + * stored. + * May be NULL, then the packet data is not reference-counted. + */ + AVBufferRef *buf; + /** + * Presentation timestamp in AVStream->time_base units; the time at which + * the decompressed packet will be presented to the user. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + * pts MUST be larger or equal to dts as presentation cannot happen before + * decompression, unless one wants to view hex dumps. Some formats misuse + * the terms dts and pts/cts to mean something different. Such timestamps + * must be converted to true pts/dts before they are stored in AVPacket. + */ + int64_t pts; + /** + * Decompression timestamp in AVStream->time_base units; the time at which + * the packet is decompressed. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + */ + int64_t dts; + uint8_t *data; + int size; + int stream_index; + /** + * A combination of AV_PKT_FLAG values + */ + int flags; + /** + * Additional packet data that can be provided by the container. + * Packet can contain several types of side information. + */ + AVPacketSideData *side_data; + int side_data_elems; + + /** + * Duration of this packet in AVStream->time_base units, 0 if unknown. + * Equals next_pts - this_pts in presentation order. + */ + int64_t duration; + + int64_t pos; ///< byte position in stream, -1 if unknown + + /** + * for some private data of the user + */ + void *opaque; + + /** + * AVBufferRef for free use by the API user. FFmpeg will never check the + * contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when + * the packet is unreferenced. av_packet_copy_props() calls create a new + * reference with av_buffer_ref() for the target packet's opaque_ref field. + * + * This is unrelated to the opaque field, although it serves a similar + * purpose. + */ + AVBufferRef *opaque_ref; + + /** + * Time base of the packet's timestamps. + * In the future, this field may be set on packets output by encoders or + * demuxers, but its value will be by default ignored on input to decoders + * or muxers. + */ + AVRational time_base; +} AVPacket; + +#if FF_API_INIT_PACKET +attribute_deprecated +typedef struct AVPacketList { + AVPacket pkt; + struct AVPacketList *next; +} AVPacketList; +#endif + +#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe +#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted +/** + * Flag is used to discard packets which are required to maintain valid + * decoder state but are not required for output and should be dropped + * after decoding. + **/ +#define AV_PKT_FLAG_DISCARD 0x0004 +/** + * The packet comes from a trusted source. + * + * Otherwise-unsafe constructs such as arbitrary pointers to data + * outside the packet may be followed. + */ +#define AV_PKT_FLAG_TRUSTED 0x0008 +/** + * Flag is used to indicate packets that contain frames that can + * be discarded by the decoder. I.e. Non-reference frames. + */ +#define AV_PKT_FLAG_DISPOSABLE 0x0010 + +enum AVSideDataParamChangeFlags { +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * @deprecated those are not used by any decoder + */ + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002, +#endif + AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004, + AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008, +}; + +/** + * Allocate an AVPacket and set its fields to default values. The resulting + * struct must be freed using av_packet_free(). + * + * @return An AVPacket filled with default values or NULL on failure. + * + * @note this only allocates the AVPacket itself, not the data buffers. Those + * must be allocated through other means such as av_new_packet. + * + * @see av_new_packet + */ +AVPacket *av_packet_alloc(void); + +/** + * Create a new packet that references the same data as src. + * + * This is a shortcut for av_packet_alloc()+av_packet_ref(). + * + * @return newly created AVPacket on success, NULL on error. + * + * @see av_packet_alloc + * @see av_packet_ref + */ +AVPacket *av_packet_clone(const AVPacket *src); + +/** + * Free the packet, if the packet is reference counted, it will be + * unreferenced first. + * + * @param pkt packet to be freed. The pointer will be set to NULL. + * @note passing NULL is a no-op. + */ +void av_packet_free(AVPacket **pkt); + +#if FF_API_INIT_PACKET +/** + * Initialize optional fields of a packet with default values. + * + * Note, this does not touch the data and size members, which have to be + * initialized separately. + * + * @param pkt packet + * + * @see av_packet_alloc + * @see av_packet_unref + * + * @deprecated This function is deprecated. Once it's removed, + sizeof(AVPacket) will not be a part of the ABI anymore. + */ +attribute_deprecated +void av_init_packet(AVPacket *pkt); +#endif + +/** + * Allocate the payload of a packet and initialize its fields with + * default values. + * + * @param pkt packet + * @param size wanted payload size + * @return 0 if OK, AVERROR_xxx otherwise + */ +int av_new_packet(AVPacket *pkt, int size); + +/** + * Reduce packet size, correctly zeroing padding + * + * @param pkt packet + * @param size new size + */ +void av_shrink_packet(AVPacket *pkt, int size); + +/** + * Increase packet size, correctly zeroing padding + * + * @param pkt packet + * @param grow_by number of bytes by which to increase the size of the packet + */ +int av_grow_packet(AVPacket *pkt, int grow_by); + +/** + * Initialize a reference-counted packet from av_malloc()ed data. + * + * @param pkt packet to be initialized. This function will set the data, size, + * and buf fields, all others are left untouched. + * @param data Data allocated by av_malloc() to be used as packet data. If this + * function returns successfully, the data is owned by the underlying AVBuffer. + * The caller may not access the data through other means. + * @param size size of data in bytes, without the padding. I.e. the full buffer + * size is assumed to be size + AV_INPUT_BUFFER_PADDING_SIZE. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size); + +/** + * Allocate new information of a packet. + * + * @param pkt packet + * @param type side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + size_t size); + +/** + * Wrap an existing array as a packet side data. + * + * @param pkt packet + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * pkt. + * @param size side information size + * @return a non-negative number on success, a negative AVERROR code on + * failure. On failure, the packet is unchanged and the data remains + * owned by the caller. + */ +int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + +/** + * Shrink the already allocated side data buffer + * + * @param pkt packet + * @param type side information type + * @param size new side information size + * @return 0 on success, < 0 on failure + */ +int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + size_t size); + +/** + * Get side information from packet. + * + * @param pkt packet + * @param type desired side information type + * @param size If supplied, *size will be set to the size of the side data + * or to zero if the desired side data is not present. + * @return pointer to data if present or NULL otherwise + */ +uint8_t* av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, + size_t *size); + +/** + * Pack a dictionary for use in side_data. + * + * @param dict The dictionary to pack. + * @param size pointer to store the size of the returned data + * @return pointer to data if successful, NULL otherwise + */ +uint8_t *av_packet_pack_dictionary(AVDictionary *dict, size_t *size); +/** + * Unpack a dictionary from side_data. + * + * @param data data from side_data + * @param size size of the data + * @param dict the metadata storage dictionary + * @return 0 on success, < 0 on failure + */ +int av_packet_unpack_dictionary(const uint8_t *data, size_t size, + AVDictionary **dict); + +/** + * Convenience function to free all the side data stored. + * All the other fields stay untouched. + * + * @param pkt packet + */ +void av_packet_free_side_data(AVPacket *pkt); + +/** + * Setup a new reference to the data described by a given packet + * + * If src is reference-counted, setup dst as a new reference to the + * buffer in src. Otherwise allocate a new buffer in dst and copy the + * data from src into it. + * + * All the other fields are copied from src. + * + * @see av_packet_unref + * + * @param dst Destination packet. Will be completely overwritten. + * @param src Source packet + * + * @return 0 on success, a negative AVERROR on error. On error, dst + * will be blank (as if returned by av_packet_alloc()). + */ +int av_packet_ref(AVPacket *dst, const AVPacket *src); + +/** + * Wipe the packet. + * + * Unreference the buffer referenced by the packet and reset the + * remaining packet fields to their default values. + * + * @param pkt The packet to be unreferenced. + */ +void av_packet_unref(AVPacket *pkt); + +/** + * Move every field in src to dst and reset src. + * + * @see av_packet_unref + * + * @param src Source packet, will be reset + * @param dst Destination packet + */ +void av_packet_move_ref(AVPacket *dst, AVPacket *src); + +/** + * Copy only "properties" fields from src to dst. + * + * Properties for the purpose of this function are all the fields + * beside those related to the packet data (buf, data, size) + * + * @param dst Destination packet + * @param src Source packet + * + * @return 0 on success AVERROR on failure. + */ +int av_packet_copy_props(AVPacket *dst, const AVPacket *src); + +/** + * Ensure the data described by a given packet is reference counted. + * + * @note This function does not ensure that the reference will be writable. + * Use av_packet_make_writable instead for that purpose. + * + * @see av_packet_ref + * @see av_packet_make_writable + * + * @param pkt packet whose data should be made reference counted. + * + * @return 0 on success, a negative AVERROR on error. On failure, the + * packet is unchanged. + */ +int av_packet_make_refcounted(AVPacket *pkt); + +/** + * Create a writable reference for the data described by a given packet, + * avoiding data copy if possible. + * + * @param pkt Packet whose data should be made writable. + * + * @return 0 on success, a negative AVERROR on failure. On failure, the + * packet is unchanged. + */ +int av_packet_make_writable(AVPacket *pkt); + +/** + * Convert valid timing fields (timestamps / durations) in a packet from one + * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be + * ignored. + * + * @param pkt packet on which the conversion will be performed + * @param tb_src source timebase, in which the timing fields in pkt are + * expressed + * @param tb_dst destination timebase, to which the timing fields will be + * converted + */ +void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst); + +/** + * @} + */ + +#endif // AVCODEC_PACKET_H diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/version.h b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/version.h new file mode 100644 index 0000000000000..1cf965139144d --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/version.h @@ -0,0 +1,45 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VERSION_H +#define AVCODEC_VERSION_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBAVCODEC_VERSION_MINOR 31 +#define LIBAVCODEC_VERSION_MICRO 102 + +#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT + +#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) + +#endif /* AVCODEC_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/version_major.h b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/version_major.h new file mode 100644 index 0000000000000..b9164fe5c628d --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavcodec/version_major.h @@ -0,0 +1,59 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VERSION_MAJOR_H +#define AVCODEC_VERSION_MAJOR_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#define LIBAVCODEC_VERSION_MAJOR 60 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + */ + +#define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_IDCT_NONE (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_SVTAV1_OPTS (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_AYUV_CODECID (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_VT_OUTPUT_CALLBACK (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_AVCODEC_CHROMA_POS (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_VT_HWACCEL_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_AVCTX_FRAME_NUMBER (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_SLICE_OFFSET (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_SUBFRAMES (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_TICKS_PER_FRAME (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_DROPCHANGED (LIBAVCODEC_VERSION_MAJOR < 61) + +#define FF_API_AVFFT (LIBAVCODEC_VERSION_MAJOR < 62) +#define FF_API_FF_PROFILE_LEVEL (LIBAVCODEC_VERSION_MAJOR < 62) + +// reminder to remove CrystalHD decoders on next major bump +#define FF_CODEC_CRYSTAL_HD (LIBAVCODEC_VERSION_MAJOR < 61) + +#endif /* AVCODEC_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavformat/avformat.h b/src/framework/media/thirdparty/ffmpeg/v6/libavformat/avformat.h new file mode 100644 index 0000000000000..9e7eca007eef3 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavformat/avformat.h @@ -0,0 +1,2858 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_AVFORMAT_H +#define AVFORMAT_AVFORMAT_H + +/** + * @file + * @ingroup libavf + * Main libavformat public API header + */ + +/** + * @defgroup libavf libavformat + * I/O and Muxing/Demuxing Library + * + * Libavformat (lavf) is a library for dealing with various media container + * formats. Its main two purposes are demuxing - i.e. splitting a media file + * into component streams, and the reverse process of muxing - writing supplied + * data in a specified container format. It also has an @ref lavf_io + * "I/O module" which supports a number of protocols for accessing the data (e.g. + * file, tcp, http and others). + * Unless you are absolutely sure you won't use libavformat's network + * capabilities, you should also call avformat_network_init(). + * + * A supported input format is described by an AVInputFormat struct, conversely + * an output format is described by AVOutputFormat. You can iterate over all + * input/output formats using the av_demuxer_iterate / av_muxer_iterate() functions. + * The protocols layer is not part of the public API, so you can only get the names + * of supported protocols with the avio_enum_protocols() function. + * + * Main lavf structure used for both muxing and demuxing is AVFormatContext, + * which exports all information about the file being read or written. As with + * most Libavformat structures, its size is not part of public ABI, so it cannot be + * allocated on stack or directly with av_malloc(). To create an + * AVFormatContext, use avformat_alloc_context() (some functions, like + * avformat_open_input() might do that for you). + * + * Most importantly an AVFormatContext contains: + * @li the @ref AVFormatContext.iformat "input" or @ref AVFormatContext.oformat + * "output" format. It is either autodetected or set by user for input; + * always set by user for output. + * @li an @ref AVFormatContext.streams "array" of AVStreams, which describe all + * elementary streams stored in the file. AVStreams are typically referred to + * using their index in this array. + * @li an @ref AVFormatContext.pb "I/O context". It is either opened by lavf or + * set by user for input, always set by user for output (unless you are dealing + * with an AVFMT_NOFILE format). + * + * @section lavf_options Passing options to (de)muxers + * It is possible to configure lavf muxers and demuxers using the @ref avoptions + * mechanism. Generic (format-independent) libavformat options are provided by + * AVFormatContext, they can be examined from a user program by calling + * av_opt_next() / av_opt_find() on an allocated AVFormatContext (or its AVClass + * from avformat_get_class()). Private (format-specific) options are provided by + * AVFormatContext.priv_data if and only if AVInputFormat.priv_class / + * AVOutputFormat.priv_class of the corresponding format struct is non-NULL. + * Further options may be provided by the @ref AVFormatContext.pb "I/O context", + * if its AVClass is non-NULL, and the protocols layer. See the discussion on + * nesting in @ref avoptions documentation to learn how to access those. + * + * @section urls + * URL strings in libavformat are made of a scheme/protocol, a ':', and a + * scheme specific string. URLs without a scheme and ':' used for local files + * are supported but deprecated. "file:" should be used for local files. + * + * It is important that the scheme string is not taken from untrusted + * sources without checks. + * + * Note that some schemes/protocols are quite powerful, allowing access to + * both local and remote files, parts of them, concatenations of them, local + * audio and video devices and so on. + * + * @{ + * + * @defgroup lavf_decoding Demuxing + * @{ + * Demuxers read a media file and split it into chunks of data (@em packets). A + * @ref AVPacket "packet" contains one or more encoded frames which belongs to a + * single elementary stream. In the lavf API this process is represented by the + * avformat_open_input() function for opening a file, av_read_frame() for + * reading a single packet and finally avformat_close_input(), which does the + * cleanup. + * + * @section lavf_decoding_open Opening a media file + * The minimum information required to open a file is its URL, which + * is passed to avformat_open_input(), as in the following code: + * @code + * const char *url = "file:in.mp3"; + * AVFormatContext *s = NULL; + * int ret = avformat_open_input(&s, url, NULL, NULL); + * if (ret < 0) + * abort(); + * @endcode + * The above code attempts to allocate an AVFormatContext, open the + * specified file (autodetecting the format) and read the header, exporting the + * information stored there into s. Some formats do not have a header or do not + * store enough information there, so it is recommended that you call the + * avformat_find_stream_info() function which tries to read and decode a few + * frames to find missing information. + * + * In some cases you might want to preallocate an AVFormatContext yourself with + * avformat_alloc_context() and do some tweaking on it before passing it to + * avformat_open_input(). One such case is when you want to use custom functions + * for reading input data instead of lavf internal I/O layer. + * To do that, create your own AVIOContext with avio_alloc_context(), passing + * your reading callbacks to it. Then set the @em pb field of your + * AVFormatContext to newly created AVIOContext. + * + * Since the format of the opened file is in general not known until after + * avformat_open_input() has returned, it is not possible to set demuxer private + * options on a preallocated context. Instead, the options should be passed to + * avformat_open_input() wrapped in an AVDictionary: + * @code + * AVDictionary *options = NULL; + * av_dict_set(&options, "video_size", "640x480", 0); + * av_dict_set(&options, "pixel_format", "rgb24", 0); + * + * if (avformat_open_input(&s, url, NULL, &options) < 0) + * abort(); + * av_dict_free(&options); + * @endcode + * This code passes the private options 'video_size' and 'pixel_format' to the + * demuxer. They would be necessary for e.g. the rawvideo demuxer, since it + * cannot know how to interpret raw video data otherwise. If the format turns + * out to be something different than raw video, those options will not be + * recognized by the demuxer and therefore will not be applied. Such unrecognized + * options are then returned in the options dictionary (recognized options are + * consumed). The calling program can handle such unrecognized options as it + * wishes, e.g. + * @code + * AVDictionaryEntry *e; + * if (e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX)) { + * fprintf(stderr, "Option %s not recognized by the demuxer.\n", e->key); + * abort(); + * } + * @endcode + * + * After you have finished reading the file, you must close it with + * avformat_close_input(). It will free everything associated with the file. + * + * @section lavf_decoding_read Reading from an opened file + * Reading data from an opened AVFormatContext is done by repeatedly calling + * av_read_frame() on it. Each call, if successful, will return an AVPacket + * containing encoded data for one AVStream, identified by + * AVPacket.stream_index. This packet may be passed straight into the libavcodec + * decoding functions avcodec_send_packet() or avcodec_decode_subtitle2() if the + * caller wishes to decode the data. + * + * AVPacket.pts, AVPacket.dts and AVPacket.duration timing information will be + * set if known. They may also be unset (i.e. AV_NOPTS_VALUE for + * pts/dts, 0 for duration) if the stream does not provide them. The timing + * information will be in AVStream.time_base units, i.e. it has to be + * multiplied by the timebase to convert them to seconds. + * + * A packet returned by av_read_frame() is always reference-counted, + * i.e. AVPacket.buf is set and the user may keep it indefinitely. + * The packet must be freed with av_packet_unref() when it is no + * longer needed. + * + * @section lavf_decoding_seek Seeking + * @} + * + * @defgroup lavf_encoding Muxing + * @{ + * Muxers take encoded data in the form of @ref AVPacket "AVPackets" and write + * it into files or other output bytestreams in the specified container format. + * + * The main API functions for muxing are avformat_write_header() for writing the + * file header, av_write_frame() / av_interleaved_write_frame() for writing the + * packets and av_write_trailer() for finalizing the file. + * + * At the beginning of the muxing process, the caller must first call + * avformat_alloc_context() to create a muxing context. The caller then sets up + * the muxer by filling the various fields in this context: + * + * - The @ref AVFormatContext.oformat "oformat" field must be set to select the + * muxer that will be used. + * - Unless the format is of the AVFMT_NOFILE type, the @ref AVFormatContext.pb + * "pb" field must be set to an opened IO context, either returned from + * avio_open2() or a custom one. + * - Unless the format is of the AVFMT_NOSTREAMS type, at least one stream must + * be created with the avformat_new_stream() function. The caller should fill + * the @ref AVStream.codecpar "stream codec parameters" information, such as the + * codec @ref AVCodecParameters.codec_type "type", @ref AVCodecParameters.codec_id + * "id" and other parameters (e.g. width / height, the pixel or sample format, + * etc.) as known. The @ref AVStream.time_base "stream timebase" should + * be set to the timebase that the caller desires to use for this stream (note + * that the timebase actually used by the muxer can be different, as will be + * described later). + * - It is advised to manually initialize only the relevant fields in + * AVCodecParameters, rather than using @ref avcodec_parameters_copy() during + * remuxing: there is no guarantee that the codec context values remain valid + * for both input and output format contexts. + * - The caller may fill in additional information, such as @ref + * AVFormatContext.metadata "global" or @ref AVStream.metadata "per-stream" + * metadata, @ref AVFormatContext.chapters "chapters", @ref + * AVFormatContext.programs "programs", etc. as described in the + * AVFormatContext documentation. Whether such information will actually be + * stored in the output depends on what the container format and the muxer + * support. + * + * When the muxing context is fully set up, the caller must call + * avformat_write_header() to initialize the muxer internals and write the file + * header. Whether anything actually is written to the IO context at this step + * depends on the muxer, but this function must always be called. Any muxer + * private options must be passed in the options parameter to this function. + * + * The data is then sent to the muxer by repeatedly calling av_write_frame() or + * av_interleaved_write_frame() (consult those functions' documentation for + * discussion on the difference between them; only one of them may be used with + * a single muxing context, they should not be mixed). Do note that the timing + * information on the packets sent to the muxer must be in the corresponding + * AVStream's timebase. That timebase is set by the muxer (in the + * avformat_write_header() step) and may be different from the timebase + * requested by the caller. + * + * Once all the data has been written, the caller must call av_write_trailer() + * to flush any buffered packets and finalize the output file, then close the IO + * context (if any) and finally free the muxing context with + * avformat_free_context(). + * @} + * + * @defgroup lavf_io I/O Read/Write + * @{ + * @section lavf_io_dirlist Directory listing + * The directory listing API makes it possible to list files on remote servers. + * + * Some of possible use cases: + * - an "open file" dialog to choose files from a remote location, + * - a recursive media finder providing a player with an ability to play all + * files from a given directory. + * + * @subsection lavf_io_dirlist_open Opening a directory + * At first, a directory needs to be opened by calling avio_open_dir() + * supplied with a URL and, optionally, ::AVDictionary containing + * protocol-specific parameters. The function returns zero or positive + * integer and allocates AVIODirContext on success. + * + * @code + * AVIODirContext *ctx = NULL; + * if (avio_open_dir(&ctx, "smb://example.com/some_dir", NULL) < 0) { + * fprintf(stderr, "Cannot open directory.\n"); + * abort(); + * } + * @endcode + * + * This code tries to open a sample directory using smb protocol without + * any additional parameters. + * + * @subsection lavf_io_dirlist_read Reading entries + * Each directory's entry (i.e. file, another directory, anything else + * within ::AVIODirEntryType) is represented by AVIODirEntry. + * Reading consecutive entries from an opened AVIODirContext is done by + * repeatedly calling avio_read_dir() on it. Each call returns zero or + * positive integer if successful. Reading can be stopped right after the + * NULL entry has been read -- it means there are no entries left to be + * read. The following code reads all entries from a directory associated + * with ctx and prints their names to standard output. + * @code + * AVIODirEntry *entry = NULL; + * for (;;) { + * if (avio_read_dir(ctx, &entry) < 0) { + * fprintf(stderr, "Cannot list directory.\n"); + * abort(); + * } + * if (!entry) + * break; + * printf("%s\n", entry->name); + * avio_free_directory_entry(&entry); + * } + * @endcode + * @} + * + * @defgroup lavf_codec Demuxers + * @{ + * @defgroup lavf_codec_native Native Demuxers + * @{ + * @} + * @defgroup lavf_codec_wrappers External library wrappers + * @{ + * @} + * @} + * @defgroup lavf_protos I/O Protocols + * @{ + * @} + * @defgroup lavf_internal Internal + * @{ + * @} + * @} + */ + +#include /* FILE */ + +#include "libavcodec/codec_par.h" +#include "libavcodec/defs.h" +#include "libavcodec/packet.h" + +#include "libavutil/dict.h" +#include "libavutil/log.h" + +#include "avio.h" +#include "libavformat/version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "libavformat/version.h" + +#include "libavutil/frame.h" +#include "libavcodec/codec.h" +#endif + +struct AVFormatContext; +struct AVFrame; +struct AVDeviceInfoList; + +/** + * @defgroup metadata_api Public Metadata API + * @{ + * @ingroup libavf + * The metadata API allows libavformat to export metadata tags to a client + * application when demuxing. Conversely it allows a client application to + * set metadata when muxing. + * + * Metadata is exported or set as pairs of key/value strings in the 'metadata' + * fields of the AVFormatContext, AVStream, AVChapter and AVProgram structs + * using the @ref lavu_dict "AVDictionary" API. Like all strings in FFmpeg, + * metadata is assumed to be UTF-8 encoded Unicode. Note that metadata + * exported by demuxers isn't checked to be valid UTF-8 in most cases. + * + * Important concepts to keep in mind: + * - Keys are unique; there can never be 2 tags with the same key. This is + * also meant semantically, i.e., a demuxer should not knowingly produce + * several keys that are literally different but semantically identical. + * E.g., key=Author5, key=Author6. In this example, all authors must be + * placed in the same tag. + * - Metadata is flat, not hierarchical; there are no subtags. If you + * want to store, e.g., the email address of the child of producer Alice + * and actor Bob, that could have key=alice_and_bobs_childs_email_address. + * - Several modifiers can be applied to the tag name. This is done by + * appending a dash character ('-') and the modifier name in the order + * they appear in the list below -- e.g. foo-eng-sort, not foo-sort-eng. + * - language -- a tag whose value is localized for a particular language + * is appended with the ISO 639-2/B 3-letter language code. + * For example: Author-ger=Michael, Author-eng=Mike + * The original/default language is in the unqualified "Author" tag. + * A demuxer should set a default if it sets any translated tag. + * - sorting -- a modified version of a tag that should be used for + * sorting will have '-sort' appended. E.g. artist="The Beatles", + * artist-sort="Beatles, The". + * - Some protocols and demuxers support metadata updates. After a successful + * call to av_read_frame(), AVFormatContext.event_flags or AVStream.event_flags + * will be updated to indicate if metadata changed. In order to detect metadata + * changes on a stream, you need to loop through all streams in the AVFormatContext + * and check their individual event_flags. + * + * - Demuxers attempt to export metadata in a generic format, however tags + * with no generic equivalents are left as they are stored in the container. + * Follows a list of generic tag names: + * + @verbatim + album -- name of the set this work belongs to + album_artist -- main creator of the set/album, if different from artist. + e.g. "Various Artists" for compilation albums. + artist -- main creator of the work + comment -- any additional description of the file. + composer -- who composed the work, if different from artist. + copyright -- name of copyright holder. + creation_time-- date when the file was created, preferably in ISO 8601. + date -- date when the work was created, preferably in ISO 8601. + disc -- number of a subset, e.g. disc in a multi-disc collection. + encoder -- name/settings of the software/hardware that produced the file. + encoded_by -- person/group who created the file. + filename -- original name of the file. + genre -- . + language -- main language in which the work is performed, preferably + in ISO 639-2 format. Multiple languages can be specified by + separating them with commas. + performer -- artist who performed the work, if different from artist. + E.g for "Also sprach Zarathustra", artist would be "Richard + Strauss" and performer "London Philharmonic Orchestra". + publisher -- name of the label/publisher. + service_name -- name of the service in broadcasting (channel name). + service_provider -- name of the service provider in broadcasting. + title -- name of the work. + track -- number of this work in the set, can be in form current/total. + variant_bitrate -- the total bitrate of the bitrate variant that the current stream is part of + @endverbatim + * + * Look in the examples section for an application example how to use the Metadata API. + * + * @} + */ + +/* packet functions */ + + +/** + * Allocate and read the payload of a packet and initialize its + * fields with default values. + * + * @param s associated IO context + * @param pkt packet + * @param size desired payload size + * @return >0 (read size) if OK, AVERROR_xxx otherwise + */ +int av_get_packet(AVIOContext *s, AVPacket *pkt, int size); + + +/** + * Read data and append it to the current content of the AVPacket. + * If pkt->size is 0 this is identical to av_get_packet. + * Note that this uses av_grow_packet and thus involves a realloc + * which is inefficient. Thus this function should only be used + * when there is no reasonable way to know (an upper bound of) + * the final size. + * + * @param s associated IO context + * @param pkt packet + * @param size amount of data to read + * @return >0 (read size) if OK, AVERROR_xxx otherwise, previous data + * will not be lost even if an error occurs. + */ +int av_append_packet(AVIOContext *s, AVPacket *pkt, int size); + +/*************************************************/ +/* input/output formats */ + +struct AVCodecTag; + +/** + * This structure contains the data a format has to probe a file. + */ +typedef struct AVProbeData { + const char *filename; + unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */ + int buf_size; /**< Size of buf except extra allocated bytes */ + const char *mime_type; /**< mime_type, when known. */ +} AVProbeData; + +#define AVPROBE_SCORE_RETRY (AVPROBE_SCORE_MAX/4) +#define AVPROBE_SCORE_STREAM_RETRY (AVPROBE_SCORE_MAX/4-1) + +#define AVPROBE_SCORE_EXTENSION 50 ///< score for file extension +#define AVPROBE_SCORE_MIME 75 ///< score for file mime type +#define AVPROBE_SCORE_MAX 100 ///< maximum score + +#define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer + +/// Demuxer will use avio_open, no opened file should be provided by the caller. +#define AVFMT_NOFILE 0x0001 +#define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */ +/** + * The muxer/demuxer is experimental and should be used with caution. + * + * - demuxers: will not be selected automatically by probing, must be specified + * explicitly. + */ +#define AVFMT_EXPERIMENTAL 0x0004 +#define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */ +#define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */ +#define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */ +#define AVFMT_GENERIC_INDEX 0x0100 /**< Use generic index building code. */ +#define AVFMT_TS_DISCONT 0x0200 /**< Format allows timestamp discontinuities. Note, muxers always require valid (monotone) timestamps */ +#define AVFMT_VARIABLE_FPS 0x0400 /**< Format allows variable fps. */ +#define AVFMT_NODIMENSIONS 0x0800 /**< Format does not need width/height */ +#define AVFMT_NOSTREAMS 0x1000 /**< Format does not require any streams */ +#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fall back on binary search via read_timestamp */ +#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fall back on generic search */ +#define AVFMT_NO_BYTE_SEEK 0x8000 /**< Format does not allow seeking by bytes */ +#if FF_API_ALLOW_FLUSH +#define AVFMT_ALLOW_FLUSH 0x10000 /**< @deprecated: Just send a NULL packet if you want to flush a muxer. */ +#endif +#define AVFMT_TS_NONSTRICT 0x20000 /**< Format does not require strictly + increasing timestamps, but they must + still be monotonic */ +#define AVFMT_TS_NEGATIVE 0x40000 /**< Format allows muxing negative + timestamps. If not set the timestamp + will be shifted in av_write_frame and + av_interleaved_write_frame so they + start from 0. + The user or muxer can override this through + AVFormatContext.avoid_negative_ts + */ + +#define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */ + +/** + * @addtogroup lavf_encoding + * @{ + */ +typedef struct AVOutputFormat { + const char *name; + /** + * Descriptive name for the format, meant to be more human-readable + * than name. You should use the NULL_IF_CONFIG_SMALL() macro + * to define it. + */ + const char *long_name; + const char *mime_type; + const char *extensions; /**< comma-separated filename extensions */ + /* output support */ + enum AVCodecID audio_codec; /**< default audio codec */ + enum AVCodecID video_codec; /**< default video codec */ + enum AVCodecID subtitle_codec; /**< default subtitle codec */ + /** + * can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, + * AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, + * AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, + * AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE + */ + int flags; + + /** + * List of supported codec_id-codec_tag pairs, ordered by "better + * choice first". The arrays are all terminated by AV_CODEC_ID_NONE. + */ + const struct AVCodecTag * const *codec_tag; + + + const AVClass *priv_class; ///< AVClass for the private context +} AVOutputFormat; +/** + * @} + */ + +/** + * @addtogroup lavf_decoding + * @{ + */ +typedef struct AVInputFormat { + /** + * A comma separated list of short names for the format. New names + * may be appended with a minor bump. + */ + const char *name; + + /** + * Descriptive name for the format, meant to be more human-readable + * than name. You should use the NULL_IF_CONFIG_SMALL() macro + * to define it. + */ + const char *long_name; + + /** + * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS, + * AVFMT_NOTIMESTAMPS, AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH, + * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS. + */ + int flags; + + /** + * If extensions are defined, then no probe is done. You should + * usually not use extension format guessing because it is not + * reliable enough + */ + const char *extensions; + + const struct AVCodecTag * const *codec_tag; + + const AVClass *priv_class; ///< AVClass for the private context + + /** + * Comma-separated list of mime types. + * It is used check for matching mime types while probing. + * @see av_probe_input_format2 + */ + const char *mime_type; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + /** + * Raw demuxers store their codec ID here. + */ + int raw_codec_id; + + /** + * Size of private data so that it can be allocated in the wrapper. + */ + int priv_data_size; + + /** + * Internal flags. See FF_FMT_FLAG_* in internal.h. + */ + int flags_internal; + + /** + * Tell if a given file has a chance of being parsed as this format. + * The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes + * big so you do not have to check for that unless you need more. + */ + int (*read_probe)(const AVProbeData *); + + /** + * Read the format header and initialize the AVFormatContext + * structure. Return 0 if OK. 'avformat_new_stream' should be + * called to create new streams. + */ + int (*read_header)(struct AVFormatContext *); + + /** + * Read one packet and put it in 'pkt'. pts and flags are also + * set. 'avformat_new_stream' can be called only if the flag + * AVFMTCTX_NOHEADER is used and only in the calling thread (not in a + * background thread). + * @return 0 on success, < 0 on error. + * Upon returning an error, pkt must be unreferenced by the caller. + */ + int (*read_packet)(struct AVFormatContext *, AVPacket *pkt); + + /** + * Close the stream. The AVFormatContext and AVStreams are not + * freed by this function + */ + int (*read_close)(struct AVFormatContext *); + + /** + * Seek to a given timestamp relative to the frames in + * stream component stream_index. + * @param stream_index Must not be -1. + * @param flags Selects which direction should be preferred if no exact + * match is available. + * @return >= 0 on success (but not necessarily the new offset) + */ + int (*read_seek)(struct AVFormatContext *, + int stream_index, int64_t timestamp, int flags); + + /** + * Get the next timestamp in stream[stream_index].time_base units. + * @return the timestamp or AV_NOPTS_VALUE if an error occurred + */ + int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index, + int64_t *pos, int64_t pos_limit); + + /** + * Start/resume playing - only meaningful if using a network-based format + * (RTSP). + */ + int (*read_play)(struct AVFormatContext *); + + /** + * Pause playing - only meaningful if using a network-based format + * (RTSP). + */ + int (*read_pause)(struct AVFormatContext *); + + /** + * Seek to timestamp ts. + * Seeking will be done so that the point from which all active streams + * can be presented successfully will be closest to ts and within min/max_ts. + * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL. + */ + int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); + + /** + * Returns device list with it properties. + * @see avdevice_list_devices() for more details. + */ + int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list); + +} AVInputFormat; +/** + * @} + */ + +enum AVStreamParseType { + AVSTREAM_PARSE_NONE, + AVSTREAM_PARSE_FULL, /**< full parsing and repack */ + AVSTREAM_PARSE_HEADERS, /**< Only parse headers, do not repack. */ + AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on a packet boundary */ + AVSTREAM_PARSE_FULL_ONCE, /**< full parsing and repack of the first frame only, only implemented for H.264 currently */ + AVSTREAM_PARSE_FULL_RAW, /**< full parsing and repack with timestamp and position generation by parser for raw + this assumes that each packet in the file contains no demuxer level headers and + just codec level data, otherwise position generation would fail */ +}; + +typedef struct AVIndexEntry { + int64_t pos; + int64_t timestamp; /**< + * Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are available + * when seeking to this entry. That means preferable PTS on keyframe based formats. + * But demuxers can choose to store a different timestamp, if it is more convenient for the implementation or nothing better + * is known + */ +#define AVINDEX_KEYFRAME 0x0001 +#define AVINDEX_DISCARD_FRAME 0x0002 /** + * Flag is used to indicate which frame should be discarded after decoding. + */ + int flags:2; + int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment). + int min_distance; /**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. */ +} AVIndexEntry; + +/** + * The stream should be chosen by default among other streams of the same type, + * unless the user has explicitly specified otherwise. + */ +#define AV_DISPOSITION_DEFAULT (1 << 0) +/** + * The stream is not in original language. + * + * @note AV_DISPOSITION_ORIGINAL is the inverse of this disposition. At most + * one of them should be set in properly tagged streams. + * @note This disposition may apply to any stream type, not just audio. + */ +#define AV_DISPOSITION_DUB (1 << 1) +/** + * The stream is in original language. + * + * @see the notes for AV_DISPOSITION_DUB + */ +#define AV_DISPOSITION_ORIGINAL (1 << 2) +/** + * The stream is a commentary track. + */ +#define AV_DISPOSITION_COMMENT (1 << 3) +/** + * The stream contains song lyrics. + */ +#define AV_DISPOSITION_LYRICS (1 << 4) +/** + * The stream contains karaoke audio. + */ +#define AV_DISPOSITION_KARAOKE (1 << 5) + +/** + * Track should be used during playback by default. + * Useful for subtitle track that should be displayed + * even when user did not explicitly ask for subtitles. + */ +#define AV_DISPOSITION_FORCED (1 << 6) +/** + * The stream is intended for hearing impaired audiences. + */ +#define AV_DISPOSITION_HEARING_IMPAIRED (1 << 7) +/** + * The stream is intended for visually impaired audiences. + */ +#define AV_DISPOSITION_VISUAL_IMPAIRED (1 << 8) +/** + * The audio stream contains music and sound effects without voice. + */ +#define AV_DISPOSITION_CLEAN_EFFECTS (1 << 9) +/** + * The stream is stored in the file as an attached picture/"cover art" (e.g. + * APIC frame in ID3v2). The first (usually only) packet associated with it + * will be returned among the first few packets read from the file unless + * seeking takes place. It can also be accessed at any time in + * AVStream.attached_pic. + */ +#define AV_DISPOSITION_ATTACHED_PIC (1 << 10) +/** + * The stream is sparse, and contains thumbnail images, often corresponding + * to chapter markers. Only ever used with AV_DISPOSITION_ATTACHED_PIC. + */ +#define AV_DISPOSITION_TIMED_THUMBNAILS (1 << 11) + +/** + * The stream is intended to be mixed with a spatial audio track. For example, + * it could be used for narration or stereo music, and may remain unchanged by + * listener head rotation. + */ +#define AV_DISPOSITION_NON_DIEGETIC (1 << 12) + +/** + * The subtitle stream contains captions, providing a transcription and possibly + * a translation of audio. Typically intended for hearing-impaired audiences. + */ +#define AV_DISPOSITION_CAPTIONS (1 << 16) +/** + * The subtitle stream contains a textual description of the video content. + * Typically intended for visually-impaired audiences or for the cases where the + * video cannot be seen. + */ +#define AV_DISPOSITION_DESCRIPTIONS (1 << 17) +/** + * The subtitle stream contains time-aligned metadata that is not intended to be + * directly presented to the user. + */ +#define AV_DISPOSITION_METADATA (1 << 18) +/** + * The audio stream is intended to be mixed with another stream before + * presentation. + * Corresponds to mix_type=0 in mpegts. + */ +#define AV_DISPOSITION_DEPENDENT (1 << 19) +/** + * The video stream contains still images. + */ +#define AV_DISPOSITION_STILL_IMAGE (1 << 20) + +/** + * @return The AV_DISPOSITION_* flag corresponding to disp or a negative error + * code if disp does not correspond to a known stream disposition. + */ +int av_disposition_from_string(const char *disp); + +/** + * @param disposition a combination of AV_DISPOSITION_* values + * @return The string description corresponding to the lowest set bit in + * disposition. NULL when the lowest set bit does not correspond + * to a known disposition or when disposition is 0. + */ +const char *av_disposition_to_string(int disposition); + +/** + * Options for behavior on timestamp wrap detection. + */ +#define AV_PTS_WRAP_IGNORE 0 ///< ignore the wrap +#define AV_PTS_WRAP_ADD_OFFSET 1 ///< add the format specific offset on wrap detection +#define AV_PTS_WRAP_SUB_OFFSET -1 ///< subtract the format specific offset on wrap detection + +/** + * Stream structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVStream) must not be used outside libav*. + */ +typedef struct AVStream { + /** + * A class for @ref avoptions. Set on stream creation. + */ + const AVClass *av_class; + + int index; /**< stream index in AVFormatContext */ + /** + * Format-specific stream ID. + * decoding: set by libavformat + * encoding: set by the user, replaced by libavformat if left unset + */ + int id; + + /** + * Codec parameters associated with this stream. Allocated and freed by + * libavformat in avformat_new_stream() and avformat_free_context() + * respectively. + * + * - demuxing: filled by libavformat on stream creation or in + * avformat_find_stream_info() + * - muxing: filled by the caller before avformat_write_header() + */ + AVCodecParameters *codecpar; + + void *priv_data; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. + * + * decoding: set by libavformat + * encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the desired timebase. In + * avformat_write_header(), the muxer will overwrite this field + * with the timebase that will actually be used for the timestamps + * written into the file (which may or may not be related to the + * user-provided one, depending on the format). + */ + AVRational time_base; + + /** + * Decoding: pts of the first frame of the stream in presentation order, in stream time base. + * Only set this if you are absolutely 100% sure that the value you set + * it to really is the pts of the first frame. + * This may be undefined (AV_NOPTS_VALUE). + * @note The ASF header does NOT contain a correct start_time the ASF + * demuxer must NOT set this. + */ + int64_t start_time; + + /** + * Decoding: duration of the stream, in stream time base. + * If a source file does not specify a duration, but does specify + * a bitrate, this value will be estimated from bitrate and file size. + * + * Encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the estimated duration. + */ + int64_t duration; + + int64_t nb_frames; ///< number of frames in this stream if known or 0 + + /** + * Stream disposition - a combination of AV_DISPOSITION_* flags. + * - demuxing: set by libavformat when creating the stream or in + * avformat_find_stream_info(). + * - muxing: may be set by the caller before avformat_write_header(). + */ + int disposition; + + enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed. + + /** + * sample aspect ratio (0 if unknown) + * - encoding: Set by user. + * - decoding: Set by libavformat. + */ + AVRational sample_aspect_ratio; + + AVDictionary *metadata; + + /** + * Average framerate + * + * - demuxing: May be set by libavformat when creating the stream or in + * avformat_find_stream_info(). + * - muxing: May be set by the caller before avformat_write_header(). + */ + AVRational avg_frame_rate; + + /** + * For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet + * will contain the attached picture. + * + * decoding: set by libavformat, must not be modified by the caller. + * encoding: unused + */ + AVPacket attached_pic; + +#if FF_API_AVSTREAM_SIDE_DATA + /** + * An array of side data that applies to the whole stream (i.e. the + * container does not allow it to change between packets). + * + * There may be no overlap between the side data in this array and side data + * in the packets. I.e. a given side data is either exported by the muxer + * (demuxing) / set by the caller (muxing) in this array, then it never + * appears in the packets, or the side data is exported / sent through + * the packets (always in the first packet where the value becomes known or + * changes), then it does not appear in this array. + * + * - demuxing: Set by libavformat when the stream is created. + * - muxing: May be set by the caller before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + * + * @deprecated use AVStream's @ref AVCodecParameters.coded_side_data + * "codecpar side data". + */ + attribute_deprecated + AVPacketSideData *side_data; + /** + * The number of elements in the AVStream.side_data array. + * + * @deprecated use AVStream's @ref AVCodecParameters.nb_coded_side_data + * "codecpar side data". + */ + attribute_deprecated + int nb_side_data; +#endif + + /** + * Flags indicating events happening on the stream, a combination of + * AVSTREAM_EVENT_FLAG_*. + * + * - demuxing: may be set by the demuxer in avformat_open_input(), + * avformat_find_stream_info() and av_read_frame(). Flags must be cleared + * by the user once the event has been handled. + * - muxing: may be set by the user after avformat_write_header(). to + * indicate a user-triggered event. The muxer will clear the flags for + * events it has handled in av_[interleaved]_write_frame(). + */ + int event_flags; +/** + * - demuxing: the demuxer read new metadata from the file and updated + * AVStream.metadata accordingly + * - muxing: the user updated AVStream.metadata and wishes the muxer to write + * it into the file + */ +#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 +/** + * - demuxing: new packets for this stream were read from the file. This + * event is informational only and does not guarantee that new packets + * for this stream will necessarily be returned from av_read_frame(). + */ +#define AVSTREAM_EVENT_FLAG_NEW_PACKETS (1 << 1) + + /** + * Real base framerate of the stream. + * This is the lowest framerate with which all timestamps can be + * represented accurately (it is the least common multiple of all + * framerates in the stream). Note, this value is just a guess! + * For example, if the time base is 1/90000 and all frames have either + * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1. + */ + AVRational r_frame_rate; + + /** + * Number of bits in timestamps. Used for wrapping control. + * + * - demuxing: set by libavformat + * - muxing: set by libavformat + * + */ + int pts_wrap_bits; +} AVStream; + +struct AVCodecParserContext *av_stream_get_parser(const AVStream *s); + +#if FF_API_GET_END_PTS +/** + * Returns the pts of the last muxed packet + its duration + * + * the retuned value is undefined when used with a demuxer. + */ +attribute_deprecated +int64_t av_stream_get_end_pts(const AVStream *st); +#endif + +#define AV_PROGRAM_RUNNING 1 + +/** + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVProgram) must not be used outside libav*. + */ +typedef struct AVProgram { + int id; + int flags; + enum AVDiscard discard; ///< selects which program to discard and which to feed to the caller + unsigned int *stream_index; + unsigned int nb_stream_indexes; + AVDictionary *metadata; + + int program_num; + int pmt_pid; + int pcr_pid; + int pmt_version; + + /***************************************************************** + * All fields below this line are not part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + int64_t start_time; + int64_t end_time; + + int64_t pts_wrap_reference; ///< reference dts for wrap detection + int pts_wrap_behavior; ///< behavior on wrap detection +} AVProgram; + +#define AVFMTCTX_NOHEADER 0x0001 /**< signal that no header is present + (streams are added dynamically) */ +#define AVFMTCTX_UNSEEKABLE 0x0002 /**< signal that the stream is definitely + not seekable, and attempts to call the + seek function will fail. For some + network protocols (e.g. HLS), this can + change dynamically at runtime. */ + +typedef struct AVChapter { + int64_t id; ///< unique ID to identify the chapter + AVRational time_base; ///< time base in which the start/end timestamps are specified + int64_t start, end; ///< chapter start/end time in time_base units + AVDictionary *metadata; +} AVChapter; + + +/** + * Callback used by devices to communicate with application. + */ +typedef int (*av_format_control_message)(struct AVFormatContext *s, int type, + void *data, size_t data_size); + +typedef int (*AVOpenCallback)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, + const AVIOInterruptCB *int_cb, AVDictionary **options); + +/** + * The duration of a video can be estimated through various ways, and this enum can be used + * to know how the duration was estimated. + */ +enum AVDurationEstimationMethod { + AVFMT_DURATION_FROM_PTS, ///< Duration accurately estimated from PTSes + AVFMT_DURATION_FROM_STREAM, ///< Duration estimated from a stream with a known duration + AVFMT_DURATION_FROM_BITRATE ///< Duration estimated from bitrate (less accurate) +}; + +/** + * Format I/O context. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVFormatContext) must not be used outside libav*, use + * avformat_alloc_context() to create an AVFormatContext. + * + * Fields can be accessed through AVOptions (av_opt*), + * the name string used matches the associated command line parameter name and + * can be found in libavformat/options_table.h. + * The AVOption/command line parameter names differ in some cases from the C + * structure field names for historic reasons or brevity. + */ +typedef struct AVFormatContext { + /** + * A class for logging and @ref avoptions. Set by avformat_alloc_context(). + * Exports (de)muxer private options if they exist. + */ + const AVClass *av_class; + + /** + * The input container format. + * + * Demuxing only, set by avformat_open_input(). + */ + const struct AVInputFormat *iformat; + + /** + * The output container format. + * + * Muxing only, must be set by the caller before avformat_write_header(). + */ + const struct AVOutputFormat *oformat; + + /** + * Format private data. This is an AVOptions-enabled struct + * if and only if iformat/oformat.priv_class is not NULL. + * + * - muxing: set by avformat_write_header() + * - demuxing: set by avformat_open_input() + */ + void *priv_data; + + /** + * I/O context. + * + * - demuxing: either set by the user before avformat_open_input() (then + * the user must close it manually) or set by avformat_open_input(). + * - muxing: set by the user before avformat_write_header(). The caller must + * take care of closing / freeing the IO context. + * + * Do NOT set this field if AVFMT_NOFILE flag is set in + * iformat/oformat.flags. In such a case, the (de)muxer will handle + * I/O in some other way and this field will be NULL. + */ + AVIOContext *pb; + + /* stream info */ + /** + * Flags signalling stream properties. A combination of AVFMTCTX_*. + * Set by libavformat. + */ + int ctx_flags; + + /** + * Number of elements in AVFormatContext.streams. + * + * Set by avformat_new_stream(), must not be modified by any other code. + */ + unsigned int nb_streams; + /** + * A list of all streams in the file. New streams are created with + * avformat_new_stream(). + * + * - demuxing: streams are created by libavformat in avformat_open_input(). + * If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also + * appear in av_read_frame(). + * - muxing: streams are created by the user before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + */ + AVStream **streams; + + /** + * input or output URL. Unlike the old filename field, this field has no + * length restriction. + * + * - demuxing: set by avformat_open_input(), initialized to an empty + * string if url parameter was NULL in avformat_open_input(). + * - muxing: may be set by the caller before calling avformat_write_header() + * (or avformat_init_output() if that is called first) to a string + * which is freeable by av_free(). Set to an empty string if it + * was NULL in avformat_init_output(). + * + * Freed by libavformat in avformat_free_context(). + */ + char *url; + + /** + * Position of the first frame of the component, in + * AV_TIME_BASE fractional seconds. NEVER set this value directly: + * It is deduced from the AVStream values. + * + * Demuxing only, set by libavformat. + */ + int64_t start_time; + + /** + * Duration of the stream, in AV_TIME_BASE fractional + * seconds. Only set this value if you know none of the individual stream + * durations and also do not set any of them. This is deduced from the + * AVStream values if not set. + * + * Demuxing only, set by libavformat. + */ + int64_t duration; + + /** + * Total stream bitrate in bit/s, 0 if not + * available. Never set it directly if the file_size and the + * duration are known as FFmpeg can compute it automatically. + */ + int64_t bit_rate; + + unsigned int packet_size; + int max_delay; + + /** + * Flags modifying the (de)muxer behaviour. A combination of AVFMT_FLAG_*. + * Set by the user before avformat_open_input() / avformat_write_header(). + */ + int flags; +#define AVFMT_FLAG_GENPTS 0x0001 ///< Generate missing pts even if it requires parsing future frames. +#define AVFMT_FLAG_IGNIDX 0x0002 ///< Ignore index. +#define AVFMT_FLAG_NONBLOCK 0x0004 ///< Do not block when reading packets from input. +#define AVFMT_FLAG_IGNDTS 0x0008 ///< Ignore DTS on frames that contain both DTS & PTS +#define AVFMT_FLAG_NOFILLIN 0x0010 ///< Do not infer any values from other values, just return what is stored in the container +#define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled +#define AVFMT_FLAG_NOBUFFER 0x0040 ///< Do not buffer frames when possible +#define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it. +#define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted +#define AVFMT_FLAG_FLUSH_PACKETS 0x0200 ///< Flush the AVIOContext every packet. +/** + * When muxing, try to avoid writing any random/volatile data to the output. + * This includes any random IDs, real-time timestamps/dates, muxer version, etc. + * + * This flag is mainly intended for testing. + */ +#define AVFMT_FLAG_BITEXACT 0x0400 +#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down) +#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats +#if FF_API_LAVF_SHORTEST +#define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops. +#endif +#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer + + /** + * Maximum number of bytes read from input in order to determine stream + * properties. Used when reading the global header and in + * avformat_find_stream_info(). + * + * Demuxing only, set by the caller before avformat_open_input(). + * + * @note this is \e not used for determining the \ref AVInputFormat + * "input format" + * @sa format_probesize + */ + int64_t probesize; + + /** + * Maximum duration (in AV_TIME_BASE units) of the data read + * from input in avformat_find_stream_info(). + * Demuxing only, set by the caller before avformat_find_stream_info(). + * Can be set to 0 to let avformat choose using a heuristic. + */ + int64_t max_analyze_duration; + + const uint8_t *key; + int keylen; + + unsigned int nb_programs; + AVProgram **programs; + + /** + * Forced video codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID video_codec_id; + + /** + * Forced audio codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID audio_codec_id; + + /** + * Forced subtitle codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID subtitle_codec_id; + + /** + * Maximum amount of memory in bytes to use for the index of each stream. + * If the index exceeds this size, entries will be discarded as + * needed to maintain a smaller size. This can lead to slower or less + * accurate seeking (depends on demuxer). + * Demuxers for which a full in-memory index is mandatory will ignore + * this. + * - muxing: unused + * - demuxing: set by user + */ + unsigned int max_index_size; + + /** + * Maximum amount of memory in bytes to use for buffering frames + * obtained from realtime capture devices. + */ + unsigned int max_picture_buffer; + + /** + * Number of chapters in AVChapter array. + * When muxing, chapters are normally written in the file header, + * so nb_chapters should normally be initialized before write_header + * is called. Some muxers (e.g. mov and mkv) can also write chapters + * in the trailer. To write chapters in the trailer, nb_chapters + * must be zero when write_header is called and non-zero when + * write_trailer is called. + * - muxing: set by user + * - demuxing: set by libavformat + */ + unsigned int nb_chapters; + AVChapter **chapters; + + /** + * Metadata that applies to the whole file. + * + * - demuxing: set by libavformat in avformat_open_input() + * - muxing: may be set by the caller before avformat_write_header() + * + * Freed by libavformat in avformat_free_context(). + */ + AVDictionary *metadata; + + /** + * Start time of the stream in real world time, in microseconds + * since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the + * stream was captured at this real world time. + * - muxing: Set by the caller before avformat_write_header(). If set to + * either 0 or AV_NOPTS_VALUE, then the current wall-time will + * be used. + * - demuxing: Set by libavformat. AV_NOPTS_VALUE if unknown. Note that + * the value may become known after some number of frames + * have been received. + */ + int64_t start_time_realtime; + + /** + * The number of frames used for determining the framerate in + * avformat_find_stream_info(). + * Demuxing only, set by the caller before avformat_find_stream_info(). + */ + int fps_probe_size; + + /** + * Error recognition; higher values will detect more errors but may + * misdetect some more or less valid parts as errors. + * Demuxing only, set by the caller before avformat_open_input(). + */ + int error_recognition; + + /** + * Custom interrupt callbacks for the I/O layer. + * + * demuxing: set by the user before avformat_open_input(). + * muxing: set by the user before avformat_write_header() + * (mainly useful for AVFMT_NOFILE formats). The callback + * should also be passed to avio_open2() if it's used to + * open the file. + */ + AVIOInterruptCB interrupt_callback; + + /** + * Flags to enable debugging. + */ + int debug; +#define FF_FDEBUG_TS 0x0001 + + /** + * Maximum buffering duration for interleaving. + * + * To ensure all the streams are interleaved correctly, + * av_interleaved_write_frame() will wait until it has at least one packet + * for each stream before actually writing any packets to the output file. + * When some streams are "sparse" (i.e. there are large gaps between + * successive packets), this can result in excessive buffering. + * + * This field specifies the maximum difference between the timestamps of the + * first and the last packet in the muxing queue, above which libavformat + * will output a packet regardless of whether it has queued a packet for all + * the streams. + * + * Muxing only, set by the caller before avformat_write_header(). + */ + int64_t max_interleave_delta; + + /** + * Allow non-standard and experimental extension + * @see AVCodecContext.strict_std_compliance + */ + int strict_std_compliance; + + /** + * Flags indicating events happening on the file, a combination of + * AVFMT_EVENT_FLAG_*. + * + * - demuxing: may be set by the demuxer in avformat_open_input(), + * avformat_find_stream_info() and av_read_frame(). Flags must be cleared + * by the user once the event has been handled. + * - muxing: may be set by the user after avformat_write_header() to + * indicate a user-triggered event. The muxer will clear the flags for + * events it has handled in av_[interleaved]_write_frame(). + */ + int event_flags; +/** + * - demuxing: the demuxer read new metadata from the file and updated + * AVFormatContext.metadata accordingly + * - muxing: the user updated AVFormatContext.metadata and wishes the muxer to + * write it into the file + */ +#define AVFMT_EVENT_FLAG_METADATA_UPDATED 0x0001 + + /** + * Maximum number of packets to read while waiting for the first timestamp. + * Decoding only. + */ + int max_ts_probe; + + /** + * Avoid negative timestamps during muxing. + * Any value of the AVFMT_AVOID_NEG_TS_* constants. + * Note, this works better when using av_interleaved_write_frame(). + * - muxing: Set by user + * - demuxing: unused + */ + int avoid_negative_ts; +#define AVFMT_AVOID_NEG_TS_AUTO -1 ///< Enabled when required by target format +#define AVFMT_AVOID_NEG_TS_DISABLED 0 ///< Do not shift timestamps even when they are negative. +#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative +#define AVFMT_AVOID_NEG_TS_MAKE_ZERO 2 ///< Shift timestamps so that they start at 0 + + /** + * Transport stream id. + * This will be moved into demuxer private options. Thus no API/ABI compatibility + */ + int ts_id; + + /** + * Audio preload in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int audio_preload; + + /** + * Max chunk time in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int max_chunk_duration; + + /** + * Max chunk size in bytes + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int max_chunk_size; + + /** + * forces the use of wallclock timestamps as pts/dts of packets + * This has undefined results in the presence of B frames. + * - encoding: unused + * - decoding: Set by user + */ + int use_wallclock_as_timestamps; + + /** + * avio flags, used to force AVIO_FLAG_DIRECT. + * - encoding: unused + * - decoding: Set by user + */ + int avio_flags; + + /** + * The duration field can be estimated through various ways, and this field can be used + * to know how the duration was estimated. + * - encoding: unused + * - decoding: Read by user + */ + enum AVDurationEstimationMethod duration_estimation_method; + + /** + * Skip initial bytes when opening stream + * - encoding: unused + * - decoding: Set by user + */ + int64_t skip_initial_bytes; + + /** + * Correct single timestamp overflows + * - encoding: unused + * - decoding: Set by user + */ + unsigned int correct_ts_overflow; + + /** + * Force seeking to any (also non key) frames. + * - encoding: unused + * - decoding: Set by user + */ + int seek2any; + + /** + * Flush the I/O context after each packet. + * - encoding: Set by user + * - decoding: unused + */ + int flush_packets; + + /** + * format probing score. + * The maximal score is AVPROBE_SCORE_MAX, its set when the demuxer probes + * the format. + * - encoding: unused + * - decoding: set by avformat, read by user + */ + int probe_score; + + /** + * Maximum number of bytes read from input in order to identify the + * \ref AVInputFormat "input format". Only used when the format is not set + * explicitly by the caller. + * + * Demuxing only, set by the caller before avformat_open_input(). + * + * @sa probesize + */ + int format_probesize; + + /** + * ',' separated list of allowed decoders. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *codec_whitelist; + + /** + * ',' separated list of allowed demuxers. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *format_whitelist; + + /** + * IO repositioned flag. + * This is set by avformat when the underlaying IO context read pointer + * is repositioned, for example when doing byte based seeking. + * Demuxers can use the flag to detect such changes. + */ + int io_repositioned; + + /** + * Forced video codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const struct AVCodec *video_codec; + + /** + * Forced audio codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const struct AVCodec *audio_codec; + + /** + * Forced subtitle codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const struct AVCodec *subtitle_codec; + + /** + * Forced data codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const struct AVCodec *data_codec; + + /** + * Number of bytes to be written as padding in a metadata header. + * Demuxing: Unused. + * Muxing: Set by user via av_format_set_metadata_header_padding. + */ + int metadata_header_padding; + + /** + * User data. + * This is a place for some private data of the user. + */ + void *opaque; + + /** + * Callback used by devices to communicate with application. + */ + av_format_control_message control_message_cb; + + /** + * Output timestamp offset, in microseconds. + * Muxing: set by user + */ + int64_t output_ts_offset; + + /** + * dump format separator. + * can be ", " or "\n " or anything else + * - muxing: Set by user. + * - demuxing: Set by user. + */ + uint8_t *dump_separator; + + /** + * Forced Data codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID data_codec_id; + + /** + * ',' separated list of allowed protocols. + * - encoding: unused + * - decoding: set by user + */ + char *protocol_whitelist; + + /** + * A callback for opening new IO streams. + * + * Whenever a muxer or a demuxer needs to open an IO stream (typically from + * avformat_open_input() for demuxers, but for certain formats can happen at + * other times as well), it will call this callback to obtain an IO context. + * + * @param s the format context + * @param pb on success, the newly opened IO context should be returned here + * @param url the url to open + * @param flags a combination of AVIO_FLAG_* + * @param options a dictionary of additional options, with the same + * semantics as in avio_open2() + * @return 0 on success, a negative AVERROR code on failure + * + * @note Certain muxers and demuxers do nesting, i.e. they open one or more + * additional internal format contexts. Thus the AVFormatContext pointer + * passed to this callback may be different from the one facing the caller. + * It will, however, have the same 'opaque' field. + */ + int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, + int flags, AVDictionary **options); + +#if FF_API_AVFORMAT_IO_CLOSE + /** + * A callback for closing the streams opened with AVFormatContext.io_open(). + * + * @deprecated use io_close2 + */ + attribute_deprecated + void (*io_close)(struct AVFormatContext *s, AVIOContext *pb); +#endif + + /** + * ',' separated list of disallowed protocols. + * - encoding: unused + * - decoding: set by user + */ + char *protocol_blacklist; + + /** + * The maximum number of streams. + * - encoding: unused + * - decoding: set by user + */ + int max_streams; + + /** + * Skip duration calcuation in estimate_timings_from_pts. + * - encoding: unused + * - decoding: set by user + */ + int skip_estimate_duration_from_pts; + + /** + * Maximum number of packets that can be probed + * - encoding: unused + * - decoding: set by user + */ + int max_probe_packets; + + /** + * A callback for closing the streams opened with AVFormatContext.io_open(). + * + * Using this is preferred over io_close, because this can return an error. + * Therefore this callback is used instead of io_close by the generic + * libavformat code if io_close is NULL or the default. + * + * @param s the format context + * @param pb IO context to be closed and freed + * @return 0 on success, a negative AVERROR code on failure + */ + int (*io_close2)(struct AVFormatContext *s, AVIOContext *pb); +} AVFormatContext; + +/** + * This function will cause global side data to be injected in the next packet + * of each stream as well as after any subsequent seek. + * + * @note global side data is always available in every AVStream's + * @ref AVCodecParameters.coded_side_data "codecpar side data" array, and + * in a @ref AVCodecContext.coded_side_data "decoder's side data" array if + * initialized with said stream's codecpar. + * @see av_packet_side_data_get() + */ +void av_format_inject_global_side_data(AVFormatContext *s); + +/** + * Returns the method used to set ctx->duration. + * + * @return AVFMT_DURATION_FROM_PTS, AVFMT_DURATION_FROM_STREAM, or AVFMT_DURATION_FROM_BITRATE. + */ +enum AVDurationEstimationMethod av_fmt_ctx_get_duration_estimation_method(const AVFormatContext* ctx); + +/** + * @defgroup lavf_core Core functions + * @ingroup libavf + * + * Functions for querying libavformat capabilities, allocating core structures, + * etc. + * @{ + */ + +/** + * Return the LIBAVFORMAT_VERSION_INT constant. + */ +unsigned avformat_version(void); + +/** + * Return the libavformat build-time configuration. + */ +const char *avformat_configuration(void); + +/** + * Return the libavformat license. + */ +const char *avformat_license(void); + +/** + * Do global initialization of network libraries. This is optional, + * and not recommended anymore. + * + * This functions only exists to work around thread-safety issues + * with older GnuTLS or OpenSSL libraries. If libavformat is linked + * to newer versions of those libraries, or if you do not use them, + * calling this function is unnecessary. Otherwise, you need to call + * this function before any other threads using them are started. + * + * This function will be deprecated once support for older GnuTLS and + * OpenSSL libraries is removed, and this function has no purpose + * anymore. + */ +int avformat_network_init(void); + +/** + * Undo the initialization done by avformat_network_init. Call it only + * once for each time you called avformat_network_init. + */ +int avformat_network_deinit(void); + +/** + * Iterate over all registered muxers. + * + * @param opaque a pointer where libavformat will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered muxer or NULL when the iteration is + * finished + */ +const AVOutputFormat *av_muxer_iterate(void **opaque); + +/** + * Iterate over all registered demuxers. + * + * @param opaque a pointer where libavformat will store the iteration state. + * Must point to NULL to start the iteration. + * + * @return the next registered demuxer or NULL when the iteration is + * finished + */ +const AVInputFormat *av_demuxer_iterate(void **opaque); + +/** + * Allocate an AVFormatContext. + * avformat_free_context() can be used to free the context and everything + * allocated by the framework within it. + */ +AVFormatContext *avformat_alloc_context(void); + +/** + * Free an AVFormatContext and all its streams. + * @param s context to free + */ +void avformat_free_context(AVFormatContext *s); + +/** + * Get the AVClass for AVFormatContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avformat_get_class(void); + +/** + * Get the AVClass for AVStream. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *av_stream_get_class(void); + +/** + * Add a new stream to a media file. + * + * When demuxing, it is called by the demuxer in read_header(). If the + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also + * be called in read_packet(). + * + * When muxing, should be called by the user before avformat_write_header(). + * + * User is required to call avformat_free_context() to clean up the allocation + * by avformat_new_stream(). + * + * @param s media file handle + * @param c unused, does nothing + * + * @return newly created stream or NULL on error. + */ +AVStream *avformat_new_stream(AVFormatContext *s, const struct AVCodec *c); + +#if FF_API_AVSTREAM_SIDE_DATA +/** + * Wrap an existing array as stream side data. + * + * @param st stream + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * st. + * @param size side information size + * + * @return zero on success, a negative AVERROR code on failure. On failure, + * the stream is unchanged and the data remains owned by the caller. + * @deprecated use av_packet_side_data_add() with the stream's + * @ref AVCodecParameters.coded_side_data "codecpar side data" + */ +attribute_deprecated +int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + +/** + * Allocate new information from stream. + * + * @param stream stream + * @param type desired side information type + * @param size side information size + * + * @return pointer to fresh allocated data or NULL otherwise + * @deprecated use av_packet_side_data_new() with the stream's + * @ref AVCodecParameters.coded_side_data "codecpar side data" + */ +attribute_deprecated +uint8_t *av_stream_new_side_data(AVStream *stream, + enum AVPacketSideDataType type, size_t size); +/** + * Get side information from stream. + * + * @param stream stream + * @param type desired side information type + * @param size If supplied, *size will be set to the size of the side data + * or to zero if the desired side data is not present. + * + * @return pointer to data if present or NULL otherwise + * @deprecated use av_packet_side_data_get() with the stream's + * @ref AVCodecParameters.coded_side_data "codecpar side data" + */ +attribute_deprecated +uint8_t *av_stream_get_side_data(const AVStream *stream, + enum AVPacketSideDataType type, size_t *size); +#endif + +AVProgram *av_new_program(AVFormatContext *s, int id); + +/** + * @} + */ + + +/** + * Allocate an AVFormatContext for an output format. + * avformat_free_context() can be used to free the context and + * everything allocated by the framework within it. + * + * @param ctx pointee is set to the created format context, + * or to NULL in case of failure + * @param oformat format to use for allocating the context, if NULL + * format_name and filename are used instead + * @param format_name the name of output format to use for allocating the + * context, if NULL filename is used instead + * @param filename the name of the filename to use for allocating the + * context, may be NULL + * + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int avformat_alloc_output_context2(AVFormatContext **ctx, const AVOutputFormat *oformat, + const char *format_name, const char *filename); + +/** + * @addtogroup lavf_decoding + * @{ + */ + +/** + * Find AVInputFormat based on the short name of the input format. + */ +const AVInputFormat *av_find_input_format(const char *short_name); + +/** + * Guess the file format. + * + * @param pd data to be probed + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + */ +const AVInputFormat *av_probe_input_format(const AVProbeData *pd, int is_opened); + +/** + * Guess the file format. + * + * @param pd data to be probed + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_max A probe score larger that this is required to accept a + * detection, the variable is set to the actual detection + * score afterwards. + * If the score is <= AVPROBE_SCORE_MAX / 4 it is recommended + * to retry with a larger probe buffer. + */ +const AVInputFormat *av_probe_input_format2(const AVProbeData *pd, + int is_opened, int *score_max); + +/** + * Guess the file format. + * + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_ret The score of the best detection. + */ +const AVInputFormat *av_probe_input_format3(const AVProbeData *pd, + int is_opened, int *score_ret); + +/** + * Probe a bytestream to determine the input format. Each time a probe returns + * with a score that is too low, the probe buffer size is increased and another + * attempt is made. When the maximum probe size is reached, the input format + * with the highest score is returned. + * + * @param pb the bytestream to probe + * @param fmt the input format is put here + * @param url the url of the stream + * @param logctx the log context + * @param offset the offset within the bytestream to probe from + * @param max_probe_size the maximum probe buffer size (zero for default) + * + * @return the score in case of success, a negative value corresponding to an + * the maximal score is AVPROBE_SCORE_MAX + * AVERROR code otherwise + */ +int av_probe_input_buffer2(AVIOContext *pb, const AVInputFormat **fmt, + const char *url, void *logctx, + unsigned int offset, unsigned int max_probe_size); + +/** + * Like av_probe_input_buffer2() but returns 0 on success + */ +int av_probe_input_buffer(AVIOContext *pb, const AVInputFormat **fmt, + const char *url, void *logctx, + unsigned int offset, unsigned int max_probe_size); + +/** + * Open an input stream and read the header. The codecs are not opened. + * The stream must be closed with avformat_close_input(). + * + * @param ps Pointer to user-supplied AVFormatContext (allocated by + * avformat_alloc_context). May be a pointer to NULL, in + * which case an AVFormatContext is allocated by this + * function and written into ps. + * Note that a user-supplied AVFormatContext will be freed + * on failure. + * @param url URL of the stream to open. + * @param fmt If non-NULL, this parameter forces a specific input format. + * Otherwise the format is autodetected. + * @param options A dictionary filled with AVFormatContext and demuxer-private + * options. + * On return this parameter will be destroyed and replaced with + * a dict containing options that were not found. May be NULL. + * + * @return 0 on success, a negative AVERROR on failure. + * + * @note If you want to use custom IO, preallocate the format context and set its pb field. + */ +int avformat_open_input(AVFormatContext **ps, const char *url, + const AVInputFormat *fmt, AVDictionary **options); + +/** + * Read packets of a media file to get stream information. This + * is useful for file formats with no headers such as MPEG. This + * function also computes the real framerate in case of MPEG-2 repeat + * frame mode. + * The logical file position is not changed by this function; + * examined packets may be buffered for later processing. + * + * @param ic media file handle + * @param options If non-NULL, an ic.nb_streams long array of pointers to + * dictionaries, where i-th member contains options for + * codec corresponding to i-th stream. + * On return each dictionary will be filled with options that were not found. + * @return >=0 if OK, AVERROR_xxx on error + * + * @note this function isn't guaranteed to open all the codecs, so + * options being non-empty at return is a perfectly normal behavior. + * + * @todo Let the user decide somehow what information is needed so that + * we do not waste time getting stuff the user does not need. + */ +int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); + +/** + * Find the programs which belong to a given stream. + * + * @param ic media file handle + * @param last the last found program, the search will start after this + * program, or from the beginning if it is NULL + * @param s stream index + * + * @return the next program which belongs to s, NULL if no program is found or + * the last program is not among the programs of ic. + */ +AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s); + +void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx); + +/** + * Find the "best" stream in the file. + * The best stream is determined according to various heuristics as the most + * likely to be what the user expects. + * If the decoder parameter is non-NULL, av_find_best_stream will find the + * default decoder for the stream's codec; streams for which no decoder can + * be found are ignored. + * + * @param ic media file handle + * @param type stream type: video, audio, subtitles, etc. + * @param wanted_stream_nb user-requested stream number, + * or -1 for automatic selection + * @param related_stream try to find a stream related (eg. in the same + * program) to this one, or -1 if none + * @param decoder_ret if non-NULL, returns the decoder for the + * selected stream + * @param flags flags; none are currently defined + * + * @return the non-negative stream number in case of success, + * AVERROR_STREAM_NOT_FOUND if no stream with the requested type + * could be found, + * AVERROR_DECODER_NOT_FOUND if streams were found but no decoder + * + * @note If av_find_best_stream returns successfully and decoder_ret is not + * NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec. + */ +int av_find_best_stream(AVFormatContext *ic, + enum AVMediaType type, + int wanted_stream_nb, + int related_stream, + const struct AVCodec **decoder_ret, + int flags); + +/** + * Return the next frame of a stream. + * This function returns what is stored in the file, and does not validate + * that what is there are valid frames for the decoder. It will split what is + * stored in the file into frames and return one for each call. It will not + * omit invalid data between valid frames so as to give the decoder the maximum + * information possible for decoding. + * + * On success, the returned packet is reference-counted (pkt->buf is set) and + * valid indefinitely. The packet must be freed with av_packet_unref() when + * it is no longer needed. For video, the packet contains exactly one frame. + * For audio, it contains an integer number of frames if each frame has + * a known fixed size (e.g. PCM or ADPCM data). If the audio frames have + * a variable size (e.g. MPEG audio), then it contains one frame. + * + * pkt->pts, pkt->dts and pkt->duration are always set to correct + * values in AVStream.time_base units (and guessed if the format cannot + * provide them). pkt->pts can be AV_NOPTS_VALUE if the video format + * has B-frames, so it is better to rely on pkt->dts if you do not + * decompress the payload. + * + * @return 0 if OK, < 0 on error or end of file. On error, pkt will be blank + * (as if it came from av_packet_alloc()). + * + * @note pkt will be initialized, so it may be uninitialized, but it must not + * contain data that needs to be freed. + */ +int av_read_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Seek to the keyframe at timestamp. + * 'timestamp' in 'stream_index'. + * + * @param s media file handle + * @param stream_index If stream_index is (-1), a default stream is selected, + * and timestamp is automatically converted from + * AV_TIME_BASE units to the stream specific time_base. + * @param timestamp Timestamp in AVStream.time_base units or, if no stream + * is specified, in AV_TIME_BASE units. + * @param flags flags which select direction and seeking mode + * + * @return >= 0 on success + */ +int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, + int flags); + +/** + * Seek to timestamp ts. + * Seeking will be done so that the point from which all active streams + * can be presented successfully will be closest to ts and within min/max_ts. + * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL. + * + * If flags contain AVSEEK_FLAG_BYTE, then all timestamps are in bytes and + * are the file position (this may not be supported by all demuxers). + * If flags contain AVSEEK_FLAG_FRAME, then all timestamps are in frames + * in the stream with stream_index (this may not be supported by all demuxers). + * Otherwise all timestamps are in units of the stream selected by stream_index + * or if stream_index is -1, in AV_TIME_BASE units. + * If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as + * keyframes (this may not be supported by all demuxers). + * If flags contain AVSEEK_FLAG_BACKWARD, it is ignored. + * + * @param s media file handle + * @param stream_index index of the stream which is used as time base reference + * @param min_ts smallest acceptable timestamp + * @param ts target timestamp + * @param max_ts largest acceptable timestamp + * @param flags flags + * @return >=0 on success, error code otherwise + * + * @note This is part of the new seek API which is still under construction. + */ +int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); + +/** + * Discard all internally buffered data. This can be useful when dealing with + * discontinuities in the byte stream. Generally works only with formats that + * can resync. This includes headerless formats like MPEG-TS/TS but should also + * work with NUT, Ogg and in a limited way AVI for example. + * + * The set of streams, the detected duration, stream parameters and codecs do + * not change when calling this function. If you want a complete reset, it's + * better to open a new AVFormatContext. + * + * This does not flush the AVIOContext (s->pb). If necessary, call + * avio_flush(s->pb) before calling this function. + * + * @param s media file handle + * @return >=0 on success, error code otherwise + */ +int avformat_flush(AVFormatContext *s); + +/** + * Start playing a network-based stream (e.g. RTSP stream) at the + * current position. + */ +int av_read_play(AVFormatContext *s); + +/** + * Pause a network-based stream (e.g. RTSP stream). + * + * Use av_read_play() to resume it. + */ +int av_read_pause(AVFormatContext *s); + +/** + * Close an opened input AVFormatContext. Free it and all its contents + * and set *s to NULL. + */ +void avformat_close_input(AVFormatContext **s); +/** + * @} + */ + +#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward +#define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes +#define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes +#define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number + +/** + * @addtogroup lavf_encoding + * @{ + */ + +#define AVSTREAM_INIT_IN_WRITE_HEADER 0 ///< stream parameters initialized in avformat_write_header +#define AVSTREAM_INIT_IN_INIT_OUTPUT 1 ///< stream parameters initialized in avformat_init_output + +/** + * Allocate the stream private data and write the stream header to + * an output media file. + * + * @param s Media file handle, must be allocated with + * avformat_alloc_context(). + * Its \ref AVFormatContext.oformat "oformat" field must be set + * to the desired output format; + * Its \ref AVFormatContext.pb "pb" field must be set to an + * already opened ::AVIOContext. + * @param options An ::AVDictionary filled with AVFormatContext and + * muxer-private options. + * On return this parameter will be destroyed and replaced with + * a dict containing options that were not found. May be NULL. + * + * @retval AVSTREAM_INIT_IN_WRITE_HEADER On success, if the codec had not already been + * fully initialized in avformat_init_output(). + * @retval AVSTREAM_INIT_IN_INIT_OUTPUT On success, if the codec had already been fully + * initialized in avformat_init_output(). + * @retval AVERROR A negative AVERROR on failure. + * + * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_init_output. + */ +av_warn_unused_result +int avformat_write_header(AVFormatContext *s, AVDictionary **options); + +/** + * Allocate the stream private data and initialize the codec, but do not write the header. + * May optionally be used before avformat_write_header() to initialize stream parameters + * before actually writing the header. + * If using this function, do not pass the same options to avformat_write_header(). + * + * @param s Media file handle, must be allocated with + * avformat_alloc_context(). + * Its \ref AVFormatContext.oformat "oformat" field must be set + * to the desired output format; + * Its \ref AVFormatContext.pb "pb" field must be set to an + * already opened ::AVIOContext. + * @param options An ::AVDictionary filled with AVFormatContext and + * muxer-private options. + * On return this parameter will be destroyed and replaced with + * a dict containing options that were not found. May be NULL. + * + * @retval AVSTREAM_INIT_IN_WRITE_HEADER On success, if the codec requires + * avformat_write_header to fully initialize. + * @retval AVSTREAM_INIT_IN_INIT_OUTPUT On success, if the codec has been fully + * initialized. + * @retval AVERROR Anegative AVERROR on failure. + * + * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_write_header. + */ +av_warn_unused_result +int avformat_init_output(AVFormatContext *s, AVDictionary **options); + +/** + * Write a packet to an output media file. + * + * This function passes the packet directly to the muxer, without any buffering + * or reordering. The caller is responsible for correctly interleaving the + * packets if the format requires it. Callers that want libavformat to handle + * the interleaving should call av_interleaved_write_frame() instead of this + * function. + * + * @param s media file handle + * @param pkt The packet containing the data to be written. Note that unlike + * av_interleaved_write_frame(), this function does not take + * ownership of the packet passed to it (though some muxers may make + * an internal reference to the input packet). + *
+ * This parameter can be NULL (at any time, not just at the end), in + * order to immediately flush data buffered within the muxer, for + * muxers that buffer up data internally before writing it to the + * output. + *
+ * Packet's @ref AVPacket.stream_index "stream_index" field must be + * set to the index of the corresponding stream in @ref + * AVFormatContext.streams "s->streams". + *
+ * The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts") + * must be set to correct values in the stream's timebase (unless the + * output format is flagged with the AVFMT_NOTIMESTAMPS flag, then + * they can be set to AV_NOPTS_VALUE). + * The dts for subsequent packets passed to this function must be strictly + * increasing when compared in their respective timebases (unless the + * output format is flagged with the AVFMT_TS_NONSTRICT, then they + * merely have to be nondecreasing). @ref AVPacket.duration + * "duration") should also be set if known. + * @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush + * + * @see av_interleaved_write_frame() + */ +int av_write_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Write a packet to an output media file ensuring correct interleaving. + * + * This function will buffer the packets internally as needed to make sure the + * packets in the output file are properly interleaved, usually ordered by + * increasing dts. Callers doing their own interleaving should call + * av_write_frame() instead of this function. + * + * Using this function instead of av_write_frame() can give muxers advance + * knowledge of future packets, improving e.g. the behaviour of the mp4 + * muxer for VFR content in fragmenting mode. + * + * @param s media file handle + * @param pkt The packet containing the data to be written. + *
+ * If the packet is reference-counted, this function will take + * ownership of this reference and unreference it later when it sees + * fit. If the packet is not reference-counted, libavformat will + * make a copy. + * The returned packet will be blank (as if returned from + * av_packet_alloc()), even on error. + *
+ * This parameter can be NULL (at any time, not just at the end), to + * flush the interleaving queues. + *
+ * Packet's @ref AVPacket.stream_index "stream_index" field must be + * set to the index of the corresponding stream in @ref + * AVFormatContext.streams "s->streams". + *
+ * The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts") + * must be set to correct values in the stream's timebase (unless the + * output format is flagged with the AVFMT_NOTIMESTAMPS flag, then + * they can be set to AV_NOPTS_VALUE). + * The dts for subsequent packets in one stream must be strictly + * increasing (unless the output format is flagged with the + * AVFMT_TS_NONSTRICT, then they merely have to be nondecreasing). + * @ref AVPacket.duration "duration" should also be set if known. + * + * @return 0 on success, a negative AVERROR on error. + * + * @see av_write_frame(), AVFormatContext.max_interleave_delta + */ +int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Write an uncoded frame to an output media file. + * + * The frame must be correctly interleaved according to the container + * specification; if not, av_interleaved_write_uncoded_frame() must be used. + * + * See av_interleaved_write_uncoded_frame() for details. + */ +int av_write_uncoded_frame(AVFormatContext *s, int stream_index, + struct AVFrame *frame); + +/** + * Write an uncoded frame to an output media file. + * + * If the muxer supports it, this function makes it possible to write an AVFrame + * structure directly, without encoding it into a packet. + * It is mostly useful for devices and similar special muxers that use raw + * video or PCM data and will not serialize it into a byte stream. + * + * To test whether it is possible to use it with a given muxer and stream, + * use av_write_uncoded_frame_query(). + * + * The caller gives up ownership of the frame and must not access it + * afterwards. + * + * @return >=0 for success, a negative code on error + */ +int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index, + struct AVFrame *frame); + +/** + * Test whether a muxer supports uncoded frame. + * + * @return >=0 if an uncoded frame can be written to that muxer and stream, + * <0 if not + */ +int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index); + +/** + * Write the stream trailer to an output media file and free the + * file private data. + * + * May only be called after a successful call to avformat_write_header. + * + * @param s media file handle + * @return 0 if OK, AVERROR_xxx on error + */ +int av_write_trailer(AVFormatContext *s); + +/** + * Return the output format in the list of registered output formats + * which best matches the provided parameters, or return NULL if + * there is no match. + * + * @param short_name if non-NULL checks if short_name matches with the + * names of the registered formats + * @param filename if non-NULL checks if filename terminates with the + * extensions of the registered formats + * @param mime_type if non-NULL checks if mime_type matches with the + * MIME type of the registered formats + */ +const AVOutputFormat *av_guess_format(const char *short_name, + const char *filename, + const char *mime_type); + +/** + * Guess the codec ID based upon muxer and filename. + */ +enum AVCodecID av_guess_codec(const AVOutputFormat *fmt, const char *short_name, + const char *filename, const char *mime_type, + enum AVMediaType type); + +/** + * Get timing information for the data currently output. + * The exact meaning of "currently output" depends on the format. + * It is mostly relevant for devices that have an internal buffer and/or + * work in real time. + * @param s media file handle + * @param stream stream in the media file + * @param[out] dts DTS of the last packet output for the stream, in stream + * time_base units + * @param[out] wall absolute time when that packet whas output, + * in microsecond + * @retval 0 Success + * @retval AVERROR(ENOSYS) The format does not support it + * + * @note Some formats or devices may not allow to measure dts and wall + * atomically. + */ +int av_get_output_timestamp(struct AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall); + + +/** + * @} + */ + + +/** + * @defgroup lavf_misc Utility functions + * @ingroup libavf + * @{ + * + * Miscellaneous utility functions related to both muxing and demuxing + * (or neither). + */ + +/** + * Send a nice hexadecimal dump of a buffer to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump_log, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump(FILE *f, const uint8_t *buf, int size); + +/** + * Send a nice hexadecimal dump of a buffer to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size); + +/** + * Send a nice dump of a packet to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st); + + +/** + * Send a nice dump of a packet to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload, + const AVStream *st); + +/** + * Get the AVCodecID for the given codec tag tag. + * If no codec id is found returns AV_CODEC_ID_NONE. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param tag codec tag to match to a codec ID + */ +enum AVCodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned int tag); + +/** + * Get the codec tag for the given codec id id. + * If no codec tag is found returns 0. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param id codec ID to match to a codec tag + */ +unsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum AVCodecID id); + +/** + * Get the codec tag for the given codec id. + * + * @param tags list of supported codec_id - codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param id codec id that should be searched for in the list + * @param tag A pointer to the found tag + * @return 0 if id was not found in tags, > 0 if it was found + */ +int av_codec_get_tag2(const struct AVCodecTag * const *tags, enum AVCodecID id, + unsigned int *tag); + +int av_find_default_stream_index(AVFormatContext *s); + +/** + * Get the index for a specific timestamp. + * + * @param st stream that the timestamp belongs to + * @param timestamp timestamp to retrieve the index for + * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond + * to the timestamp which is <= the requested one, if backward + * is 0, then it will be >= + * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise + * @return < 0 if no such timestamp could be found + */ +int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags); + +/** + * Get the index entry count for the given AVStream. + * + * @param st stream + * @return the number of index entries in the stream + */ +int avformat_index_get_entries_count(const AVStream *st); + +/** + * Get the AVIndexEntry corresponding to the given index. + * + * @param st Stream containing the requested AVIndexEntry. + * @param idx The desired index. + * @return A pointer to the requested AVIndexEntry if it exists, NULL otherwise. + * + * @note The pointer returned by this function is only guaranteed to be valid + * until any function that takes the stream or the parent AVFormatContext + * as input argument is called. + */ +const AVIndexEntry *avformat_index_get_entry(AVStream *st, int idx); + +/** + * Get the AVIndexEntry corresponding to the given timestamp. + * + * @param st Stream containing the requested AVIndexEntry. + * @param wanted_timestamp Timestamp to retrieve the index entry for. + * @param flags If AVSEEK_FLAG_BACKWARD then the returned entry will correspond + * to the timestamp which is <= the requested one, if backward + * is 0, then it will be >= + * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise. + * @return A pointer to the requested AVIndexEntry if it exists, NULL otherwise. + * + * @note The pointer returned by this function is only guaranteed to be valid + * until any function that takes the stream or the parent AVFormatContext + * as input argument is called. + */ +const AVIndexEntry *avformat_index_get_entry_from_timestamp(AVStream *st, + int64_t wanted_timestamp, + int flags); +/** + * Add an index entry into a sorted list. Update the entry if the list + * already contains it. + * + * @param timestamp timestamp in the time base of the given stream + */ +int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, + int size, int distance, int flags); + + +/** + * Split a URL string into components. + * + * The pointers to buffers for storing individual components may be null, + * in order to ignore that component. Buffers for components not found are + * set to empty strings. If the port is not found, it is set to a negative + * value. + * + * @param proto the buffer for the protocol + * @param proto_size the size of the proto buffer + * @param authorization the buffer for the authorization + * @param authorization_size the size of the authorization buffer + * @param hostname the buffer for the host name + * @param hostname_size the size of the hostname buffer + * @param port_ptr a pointer to store the port number in + * @param path the buffer for the path + * @param path_size the size of the path buffer + * @param url the URL to split + */ +void av_url_split(char *proto, int proto_size, + char *authorization, int authorization_size, + char *hostname, int hostname_size, + int *port_ptr, + char *path, int path_size, + const char *url); + + +/** + * Print detailed information about the input or output format, such as + * duration, bitrate, streams, container, programs, metadata, side data, + * codec and time base. + * + * @param ic the context to analyze + * @param index index of the stream to dump information about + * @param url the URL to print, such as source or destination file + * @param is_output Select whether the specified context is an input(0) or output(1) + */ +void av_dump_format(AVFormatContext *ic, + int index, + const char *url, + int is_output); + + +#define AV_FRAME_FILENAME_FLAGS_MULTIPLE 1 ///< Allow multiple %d + +/** + * Return in 'buf' the path with '%d' replaced by a number. + * + * Also handles the '%0nd' format where 'n' is the total number + * of digits and '%%'. + * + * @param buf destination buffer + * @param buf_size destination buffer size + * @param path numbered sequence string + * @param number frame number + * @param flags AV_FRAME_FILENAME_FLAGS_* + * @return 0 if OK, -1 on format error + */ +int av_get_frame_filename2(char *buf, int buf_size, + const char *path, int number, int flags); + +int av_get_frame_filename(char *buf, int buf_size, + const char *path, int number); + +/** + * Check whether filename actually is a numbered sequence generator. + * + * @param filename possible numbered sequence string + * @return 1 if a valid numbered sequence string, 0 otherwise + */ +int av_filename_number_test(const char *filename); + +/** + * Generate an SDP for an RTP session. + * + * Note, this overwrites the id values of AVStreams in the muxer contexts + * for getting unique dynamic payload types. + * + * @param ac array of AVFormatContexts describing the RTP streams. If the + * array is composed by only one context, such context can contain + * multiple AVStreams (one AVStream per RTP stream). Otherwise, + * all the contexts in the array (an AVCodecContext per RTP stream) + * must contain only one AVStream. + * @param n_files number of AVCodecContexts contained in ac + * @param buf buffer where the SDP will be stored (must be allocated by + * the caller) + * @param size the size of the buffer + * @return 0 if OK, AVERROR_xxx on error + */ +int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size); + +/** + * Return a positive value if the given filename has one of the given + * extensions, 0 otherwise. + * + * @param filename file name to check against the given extensions + * @param extensions a comma-separated list of filename extensions + */ +int av_match_ext(const char *filename, const char *extensions); + +/** + * Test if the given container can store a codec. + * + * @param ofmt container to check for compatibility + * @param codec_id codec to potentially store in container + * @param std_compliance standards compliance level, one of FF_COMPLIANCE_* + * + * @return 1 if codec with ID codec_id can be stored in ofmt, 0 if it cannot. + * A negative number if this information is not available. + */ +int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id, + int std_compliance); + +/** + * @defgroup riff_fourcc RIFF FourCCs + * @{ + * Get the tables mapping RIFF FourCCs to libavcodec AVCodecIDs. The tables are + * meant to be passed to av_codec_get_id()/av_codec_get_tag() as in the + * following code: + * @code + * uint32_t tag = MKTAG('H', '2', '6', '4'); + * const struct AVCodecTag *table[] = { avformat_get_riff_video_tags(), 0 }; + * enum AVCodecID id = av_codec_get_id(table, tag); + * @endcode + */ +/** + * @return the table mapping RIFF FourCCs for video to libavcodec AVCodecID. + */ +const struct AVCodecTag *avformat_get_riff_video_tags(void); +/** + * @return the table mapping RIFF FourCCs for audio to AVCodecID. + */ +const struct AVCodecTag *avformat_get_riff_audio_tags(void); +/** + * @return the table mapping MOV FourCCs for video to libavcodec AVCodecID. + */ +const struct AVCodecTag *avformat_get_mov_video_tags(void); +/** + * @return the table mapping MOV FourCCs for audio to AVCodecID. + */ +const struct AVCodecTag *avformat_get_mov_audio_tags(void); + +/** + * @} + */ + +/** + * Guess the sample aspect ratio of a frame, based on both the stream and the + * frame aspect ratio. + * + * Since the frame aspect ratio is set by the codec but the stream aspect ratio + * is set by the demuxer, these two may not be equal. This function tries to + * return the value that you should use if you would like to display the frame. + * + * Basic logic is to use the stream aspect ratio if it is set to something sane + * otherwise use the frame aspect ratio. This way a container setting, which is + * usually easy to modify can override the coded value in the frames. + * + * @param format the format context which the stream is part of + * @param stream the stream which the frame is part of + * @param frame the frame with the aspect ratio to be determined + * @return the guessed (valid) sample_aspect_ratio, 0/1 if no idea + */ +AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, + struct AVFrame *frame); + +/** + * Guess the frame rate, based on both the container and codec information. + * + * @param ctx the format context which the stream is part of + * @param stream the stream which the frame is part of + * @param frame the frame for which the frame rate should be determined, may be NULL + * @return the guessed (valid) frame rate, 0/1 if no idea + */ +AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, + struct AVFrame *frame); + +/** + * Check if the stream st contained in s is matched by the stream specifier + * spec. + * + * See the "stream specifiers" chapter in the documentation for the syntax + * of spec. + * + * @return >0 if st is matched by spec; + * 0 if st is not matched by spec; + * AVERROR code if spec is invalid + * + * @note A stream specifier can match several streams in the format. + */ +int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, + const char *spec); + +int avformat_queue_attached_pictures(AVFormatContext *s); + +enum AVTimebaseSource { + AVFMT_TBCF_AUTO = -1, + AVFMT_TBCF_DECODER, + AVFMT_TBCF_DEMUXER, +#if FF_API_R_FRAME_RATE + AVFMT_TBCF_R_FRAMERATE, +#endif +}; + +/** + * Transfer internal timing information from one stream to another. + * + * This function is useful when doing stream copy. + * + * @param ofmt target output format for ost + * @param ost output stream which needs timings copy and adjustments + * @param ist reference input stream to copy timings from + * @param copy_tb define from where the stream codec timebase needs to be imported + */ +int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, + AVStream *ost, const AVStream *ist, + enum AVTimebaseSource copy_tb); + +/** + * Get the internal codec timebase from a stream. + * + * @param st input stream to extract the timebase from + */ +AVRational av_stream_get_codec_timebase(const AVStream *st); + +/** + * @} + */ + +#endif /* AVFORMAT_AVFORMAT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavformat/avio.h b/src/framework/media/thirdparty/ffmpeg/v6/libavformat/avio.h new file mode 100644 index 0000000000000..887a397c3788c --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavformat/avio.h @@ -0,0 +1,850 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef AVFORMAT_AVIO_H +#define AVFORMAT_AVIO_H + +/** + * @file + * @ingroup lavf_io + * Buffered I/O operations + */ + +#include +#include + +#include "libavutil/attributes.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" + +#include "libavformat/version_major.h" + +/** + * Seeking works like for a local file. + */ +#define AVIO_SEEKABLE_NORMAL (1 << 0) + +/** + * Seeking by timestamp with avio_seek_time() is possible. + */ +#define AVIO_SEEKABLE_TIME (1 << 1) + +/** + * Callback for checking whether to abort blocking functions. + * AVERROR_EXIT is returned in this case by the interrupted + * function. During blocking operations, callback is called with + * opaque as parameter. If the callback returns 1, the + * blocking operation will be aborted. + * + * No members can be added to this struct without a major bump, if + * new elements have been added after this struct in AVFormatContext + * or AVIOContext. + */ +typedef struct AVIOInterruptCB { + int (*callback)(void*); + void *opaque; +} AVIOInterruptCB; + +/** + * Directory entry types. + */ +enum AVIODirEntryType { + AVIO_ENTRY_UNKNOWN, + AVIO_ENTRY_BLOCK_DEVICE, + AVIO_ENTRY_CHARACTER_DEVICE, + AVIO_ENTRY_DIRECTORY, + AVIO_ENTRY_NAMED_PIPE, + AVIO_ENTRY_SYMBOLIC_LINK, + AVIO_ENTRY_SOCKET, + AVIO_ENTRY_FILE, + AVIO_ENTRY_SERVER, + AVIO_ENTRY_SHARE, + AVIO_ENTRY_WORKGROUP, +}; + +/** + * Describes single entry of the directory. + * + * Only name and type fields are guaranteed be set. + * Rest of fields are protocol or/and platform dependent and might be unknown. + */ +typedef struct AVIODirEntry { + char *name; /**< Filename */ + int type; /**< Type of the entry */ + int utf8; /**< Set to 1 when name is encoded with UTF-8, 0 otherwise. + Name can be encoded with UTF-8 even though 0 is set. */ + int64_t size; /**< File size in bytes, -1 if unknown. */ + int64_t modification_timestamp; /**< Time of last modification in microseconds since unix + epoch, -1 if unknown. */ + int64_t access_timestamp; /**< Time of last access in microseconds since unix epoch, + -1 if unknown. */ + int64_t status_change_timestamp; /**< Time of last status change in microseconds since unix + epoch, -1 if unknown. */ + int64_t user_id; /**< User ID of owner, -1 if unknown. */ + int64_t group_id; /**< Group ID of owner, -1 if unknown. */ + int64_t filemode; /**< Unix file mode, -1 if unknown. */ +} AVIODirEntry; + +#if FF_API_AVIODIRCONTEXT +typedef struct AVIODirContext { + struct URLContext *url_context; +} AVIODirContext; +#else +typedef struct AVIODirContext AVIODirContext; +#endif + +/** + * Different data types that can be returned via the AVIO + * write_data_type callback. + */ +enum AVIODataMarkerType { + /** + * Header data; this needs to be present for the stream to be decodeable. + */ + AVIO_DATA_MARKER_HEADER, + /** + * A point in the output bytestream where a decoder can start decoding + * (i.e. a keyframe). A demuxer/decoder given the data flagged with + * AVIO_DATA_MARKER_HEADER, followed by any AVIO_DATA_MARKER_SYNC_POINT, + * should give decodeable results. + */ + AVIO_DATA_MARKER_SYNC_POINT, + /** + * A point in the output bytestream where a demuxer can start parsing + * (for non self synchronizing bytestream formats). That is, any + * non-keyframe packet start point. + */ + AVIO_DATA_MARKER_BOUNDARY_POINT, + /** + * This is any, unlabelled data. It can either be a muxer not marking + * any positions at all, it can be an actual boundary/sync point + * that the muxer chooses not to mark, or a later part of a packet/fragment + * that is cut into multiple write callbacks due to limited IO buffer size. + */ + AVIO_DATA_MARKER_UNKNOWN, + /** + * Trailer data, which doesn't contain actual content, but only for + * finalizing the output file. + */ + AVIO_DATA_MARKER_TRAILER, + /** + * A point in the output bytestream where the underlying AVIOContext might + * flush the buffer depending on latency or buffering requirements. Typically + * means the end of a packet. + */ + AVIO_DATA_MARKER_FLUSH_POINT, +}; + +/** + * Bytestream IO Context. + * New public fields can be added with minor version bumps. + * Removal, reordering and changes to existing public fields require + * a major version bump. + * sizeof(AVIOContext) must not be used outside libav*. + * + * @note None of the function pointers in AVIOContext should be called + * directly, they should only be set by the client application + * when implementing custom I/O. Normally these are set to the + * function pointers specified in avio_alloc_context() + */ +typedef struct AVIOContext { + /** + * A class for private options. + * + * If this AVIOContext is created by avio_open2(), av_class is set and + * passes the options down to protocols. + * + * If this AVIOContext is manually allocated, then av_class may be set by + * the caller. + * + * warning -- this field can be NULL, be sure to not pass this AVIOContext + * to any av_opt_* functions in that case. + */ + const AVClass *av_class; + + /* + * The following shows the relationship between buffer, buf_ptr, + * buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing + * (since AVIOContext is used for both): + * + ********************************************************************************** + * READING + ********************************************************************************** + * + * | buffer_size | + * |---------------------------------------| + * | | + * + * buffer buf_ptr buf_end + * +---------------+-----------------------+ + * |/ / / / / / / /|/ / / / / / /| | + * read buffer: |/ / consumed / | to be read /| | + * |/ / / / / / / /|/ / / / / / /| | + * +---------------+-----------------------+ + * + * pos + * +-------------------------------------------+-----------------+ + * input file: | | | + * +-------------------------------------------+-----------------+ + * + * + ********************************************************************************** + * WRITING + ********************************************************************************** + * + * | buffer_size | + * |--------------------------------------| + * | | + * + * buf_ptr_max + * buffer (buf_ptr) buf_end + * +-----------------------+--------------+ + * |/ / / / / / / / / / / /| | + * write buffer: | / / to be flushed / / | | + * |/ / / / / / / / / / / /| | + * +-----------------------+--------------+ + * buf_ptr can be in this + * due to a backward seek + * + * pos + * +-------------+----------------------------------------------+ + * output file: | | | + * +-------------+----------------------------------------------+ + * + */ + unsigned char *buffer; /**< Start of the buffer. */ + int buffer_size; /**< Maximum buffer size */ + unsigned char *buf_ptr; /**< Current position in the buffer */ + unsigned char *buf_end; /**< End of the data, may be less than + buffer+buffer_size if the read function returned + less data than requested, e.g. for streams where + no more data has been received yet. */ + void *opaque; /**< A private pointer, passed to the read/write/seek/... + functions. */ + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size); +#if FF_API_AVIO_WRITE_NONCONST + int (*write_packet)(void *opaque, uint8_t *buf, int buf_size); +#else + int (*write_packet)(void *opaque, const uint8_t *buf, int buf_size); +#endif + int64_t (*seek)(void *opaque, int64_t offset, int whence); + int64_t pos; /**< position in the file of the current buffer */ + int eof_reached; /**< true if was unable to read due to error or eof */ + int error; /**< contains the error code or 0 if no error happened */ + int write_flag; /**< true if open for writing */ + int max_packet_size; + int min_packet_size; /**< Try to buffer at least this amount of data + before flushing it. */ + unsigned long checksum; + unsigned char *checksum_ptr; + unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size); + /** + * Pause or resume playback for network streaming protocols - e.g. MMS. + */ + int (*read_pause)(void *opaque, int pause); + /** + * Seek to a given timestamp in stream with the specified stream_index. + * Needed for some network streaming protocols which don't support seeking + * to byte position. + */ + int64_t (*read_seek)(void *opaque, int stream_index, + int64_t timestamp, int flags); + /** + * A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable. + */ + int seekable; + + /** + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ + int direct; + + /** + * ',' separated list of allowed protocols. + */ + const char *protocol_whitelist; + + /** + * ',' separated list of disallowed protocols. + */ + const char *protocol_blacklist; + + /** + * A callback that is used instead of write_packet. + */ +#if FF_API_AVIO_WRITE_NONCONST + int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size, + enum AVIODataMarkerType type, int64_t time); +#else + int (*write_data_type)(void *opaque, const uint8_t *buf, int buf_size, + enum AVIODataMarkerType type, int64_t time); +#endif + /** + * If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT, + * but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly + * small chunks of data returned from the callback). + */ + int ignore_boundary_point; + + /** + * Maximum reached position before a backward seek in the write buffer, + * used keeping track of already written data for a later flush. + */ + unsigned char *buf_ptr_max; + + /** + * Read-only statistic of bytes read for this AVIOContext. + */ + int64_t bytes_read; + + /** + * Read-only statistic of bytes written for this AVIOContext. + */ + int64_t bytes_written; +} AVIOContext; + +/** + * Return the name of the protocol that will handle the passed URL. + * + * NULL is returned if no protocol could be found for the given URL. + * + * @return Name of the protocol or NULL. + */ +const char *avio_find_protocol_name(const char *url); + +/** + * Return AVIO_FLAG_* access flags corresponding to the access permissions + * of the resource in url, or a negative value corresponding to an + * AVERROR code in case of failure. The returned access flags are + * masked by the value in flags. + * + * @note This function is intrinsically unsafe, in the sense that the + * checked resource may change its existence or permission status from + * one call to another. Thus you should not trust the returned value, + * unless you are sure that no other processes are accessing the + * checked resource. + */ +int avio_check(const char *url, int flags); + +/** + * Open directory for reading. + * + * @param s directory read context. Pointer to a NULL pointer must be passed. + * @param url directory to be listed. + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dictionary + * containing options that were not found. May be NULL. + * @return >=0 on success or negative on error. + */ +int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options); + +/** + * Get next directory entry. + * + * Returned entry must be freed with avio_free_directory_entry(). In particular + * it may outlive AVIODirContext. + * + * @param s directory read context. + * @param[out] next next entry or NULL when no more entries. + * @return >=0 on success or negative on error. End of list is not considered an + * error. + */ +int avio_read_dir(AVIODirContext *s, AVIODirEntry **next); + +/** + * Close directory. + * + * @note Entries created using avio_read_dir() are not deleted and must be + * freeded with avio_free_directory_entry(). + * + * @param s directory read context. + * @return >=0 on success or negative on error. + */ +int avio_close_dir(AVIODirContext **s); + +/** + * Free entry allocated by avio_read_dir(). + * + * @param entry entry to be freed. + */ +void avio_free_directory_entry(AVIODirEntry **entry); + +/** + * Allocate and initialize an AVIOContext for buffered I/O. It must be later + * freed with avio_context_free(). + * + * @param buffer Memory block for input/output operations via AVIOContext. + * The buffer must be allocated with av_malloc() and friends. + * It may be freed and replaced with a new buffer by libavformat. + * AVIOContext.buffer holds the buffer currently in use, + * which must be later freed with av_free(). + * @param buffer_size The buffer size is very important for performance. + * For protocols with fixed blocksize it should be set to this blocksize. + * For others a typical size is a cache page, e.g. 4kb. + * @param write_flag Set to 1 if the buffer should be writable, 0 otherwise. + * @param opaque An opaque pointer to user-specific data. + * @param read_packet A function for refilling the buffer, may be NULL. + * For stream protocols, must never return 0 but rather + * a proper AVERROR code. + * @param write_packet A function for writing the buffer contents, may be NULL. + * The function may not change the input buffers content. + * @param seek A function for seeking to specified byte position, may be NULL. + * + * @return Allocated AVIOContext or NULL on failure. + */ +AVIOContext *avio_alloc_context( + unsigned char *buffer, + int buffer_size, + int write_flag, + void *opaque, + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), +#if FF_API_AVIO_WRITE_NONCONST + int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), +#else + int (*write_packet)(void *opaque, const uint8_t *buf, int buf_size), +#endif + int64_t (*seek)(void *opaque, int64_t offset, int whence)); + +/** + * Free the supplied IO context and everything associated with it. + * + * @param s Double pointer to the IO context. This function will write NULL + * into s. + */ +void avio_context_free(AVIOContext **s); + +void avio_w8(AVIOContext *s, int b); +void avio_write(AVIOContext *s, const unsigned char *buf, int size); +void avio_wl64(AVIOContext *s, uint64_t val); +void avio_wb64(AVIOContext *s, uint64_t val); +void avio_wl32(AVIOContext *s, unsigned int val); +void avio_wb32(AVIOContext *s, unsigned int val); +void avio_wl24(AVIOContext *s, unsigned int val); +void avio_wb24(AVIOContext *s, unsigned int val); +void avio_wl16(AVIOContext *s, unsigned int val); +void avio_wb16(AVIOContext *s, unsigned int val); + +/** + * Write a NULL-terminated string. + * @return number of bytes written. + */ +int avio_put_str(AVIOContext *s, const char *str); + +/** + * Convert an UTF-8 string to UTF-16LE and write it. + * @param s the AVIOContext + * @param str NULL-terminated UTF-8 string + * + * @return number of bytes written. + */ +int avio_put_str16le(AVIOContext *s, const char *str); + +/** + * Convert an UTF-8 string to UTF-16BE and write it. + * @param s the AVIOContext + * @param str NULL-terminated UTF-8 string + * + * @return number of bytes written. + */ +int avio_put_str16be(AVIOContext *s, const char *str); + +/** + * Mark the written bytestream as a specific type. + * + * Zero-length ranges are omitted from the output. + * + * @param s the AVIOContext + * @param time the stream time the current bytestream pos corresponds to + * (in AV_TIME_BASE units), or AV_NOPTS_VALUE if unknown or not + * applicable + * @param type the kind of data written starting at the current pos + */ +void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type); + +/** + * ORing this as the "whence" parameter to a seek function causes it to + * return the filesize without seeking anywhere. Supporting this is optional. + * If it is not supported then the seek function will return <0. + */ +#define AVSEEK_SIZE 0x10000 + +/** + * Passing this flag as the "whence" parameter to a seek function causes it to + * seek by any means (like reopening and linear reading) or other normally unreasonable + * means that can be extremely slow. + * This may be ignored by the seek code. + */ +#define AVSEEK_FORCE 0x20000 + +/** + * fseek() equivalent for AVIOContext. + * @return new position or AVERROR. + */ +int64_t avio_seek(AVIOContext *s, int64_t offset, int whence); + +/** + * Skip given number of bytes forward + * @return new position or AVERROR. + */ +int64_t avio_skip(AVIOContext *s, int64_t offset); + +/** + * ftell() equivalent for AVIOContext. + * @return position or AVERROR. + */ +static av_always_inline int64_t avio_tell(AVIOContext *s) +{ + return avio_seek(s, 0, SEEK_CUR); +} + +/** + * Get the filesize. + * @return filesize or AVERROR + */ +int64_t avio_size(AVIOContext *s); + +/** + * Similar to feof() but also returns nonzero on read errors. + * @return non zero if and only if at end of file or a read error happened when reading. + */ +int avio_feof(AVIOContext *s); + +/** + * Writes a formatted string to the context taking a va_list. + * @return number of bytes written, < 0 on error. + */ +int avio_vprintf(AVIOContext *s, const char *fmt, va_list ap); + +/** + * Writes a formatted string to the context. + * @return number of bytes written, < 0 on error. + */ +int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3); + +/** + * Write a NULL terminated array of strings to the context. + * Usually you don't need to use this function directly but its macro wrapper, + * avio_print. + */ +void avio_print_string_array(AVIOContext *s, const char *strings[]); + +/** + * Write strings (const char *) to the context. + * This is a convenience macro around avio_print_string_array and it + * automatically creates the string array from the variable argument list. + * For simple string concatenations this function is more performant than using + * avio_printf since it does not need a temporary buffer. + */ +#define avio_print(s, ...) \ + avio_print_string_array(s, (const char*[]){__VA_ARGS__, NULL}) + +/** + * Force flushing of buffered data. + * + * For write streams, force the buffered data to be immediately written to the output, + * without to wait to fill the internal buffer. + * + * For read streams, discard all currently buffered data, and advance the + * reported file position to that of the underlying stream. This does not + * read new data, and does not perform any seeks. + */ +void avio_flush(AVIOContext *s); + +/** + * Read size bytes from AVIOContext into buf. + * @return number of bytes read or AVERROR + */ +int avio_read(AVIOContext *s, unsigned char *buf, int size); + +/** + * Read size bytes from AVIOContext into buf. Unlike avio_read(), this is allowed + * to read fewer bytes than requested. The missing bytes can be read in the next + * call. This always tries to read at least 1 byte. + * Useful to reduce latency in certain cases. + * @return number of bytes read or AVERROR + */ +int avio_read_partial(AVIOContext *s, unsigned char *buf, int size); + +/** + * @name Functions for reading from AVIOContext + * @{ + * + * @note return 0 if EOF, so you cannot use it if EOF handling is + * necessary + */ +int avio_r8 (AVIOContext *s); +unsigned int avio_rl16(AVIOContext *s); +unsigned int avio_rl24(AVIOContext *s); +unsigned int avio_rl32(AVIOContext *s); +uint64_t avio_rl64(AVIOContext *s); +unsigned int avio_rb16(AVIOContext *s); +unsigned int avio_rb24(AVIOContext *s); +unsigned int avio_rb32(AVIOContext *s); +uint64_t avio_rb64(AVIOContext *s); +/** + * @} + */ + +/** + * Read a string from pb into buf. The reading will terminate when either + * a NULL character was encountered, maxlen bytes have been read, or nothing + * more can be read from pb. The result is guaranteed to be NULL-terminated, it + * will be truncated if buf is too small. + * Note that the string is not interpreted or validated in any way, it + * might get truncated in the middle of a sequence for multi-byte encodings. + * + * @return number of bytes read (is always <= maxlen). + * If reading ends on EOF or error, the return value will be one more than + * bytes actually read. + */ +int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen); + +/** + * Read a UTF-16 string from pb and convert it to UTF-8. + * The reading will terminate when either a null or invalid character was + * encountered or maxlen bytes have been read. + * @return number of bytes read (is always <= maxlen) + */ +int avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen); +int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen); + + +/** + * @name URL open modes + * The flags argument to avio_open must be one of the following + * constants, optionally ORed with other flags. + * @{ + */ +#define AVIO_FLAG_READ 1 /**< read-only */ +#define AVIO_FLAG_WRITE 2 /**< write-only */ +#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE) /**< read-write pseudo flag */ +/** + * @} + */ + +/** + * Use non-blocking mode. + * If this flag is set, operations on the context will return + * AVERROR(EAGAIN) if they can not be performed immediately. + * If this flag is not set, operations on the context will never return + * AVERROR(EAGAIN). + * Note that this flag does not affect the opening/connecting of the + * context. Connecting a protocol will always block if necessary (e.g. on + * network protocols) but never hang (e.g. on busy devices). + * Warning: non-blocking protocols is work-in-progress; this flag may be + * silently ignored. + */ +#define AVIO_FLAG_NONBLOCK 8 + +/** + * Use direct mode. + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ +#define AVIO_FLAG_DIRECT 0x8000 + +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param url resource to access + * @param flags flags which control how the resource indicated by url + * is to be opened + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open(AVIOContext **s, const char *url, int flags); + +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param url resource to access + * @param flags flags which control how the resource indicated by url + * is to be opened + * @param int_cb an interrupt callback to be used at the protocols level + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dict containing options + * that were not found. May be NULL. + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open2(AVIOContext **s, const char *url, int flags, + const AVIOInterruptCB *int_cb, AVDictionary **options); + +/** + * Close the resource accessed by the AVIOContext s and free it. + * This function can only be used if s was opened by avio_open(). + * + * The internal buffer is automatically flushed before closing the + * resource. + * + * @return 0 on success, an AVERROR < 0 on error. + * @see avio_closep + */ +int avio_close(AVIOContext *s); + +/** + * Close the resource accessed by the AVIOContext *s, free it + * and set the pointer pointing to it to NULL. + * This function can only be used if s was opened by avio_open(). + * + * The internal buffer is automatically flushed before closing the + * resource. + * + * @return 0 on success, an AVERROR < 0 on error. + * @see avio_close + */ +int avio_closep(AVIOContext **s); + + +/** + * Open a write only memory stream. + * + * @param s new IO context + * @return zero if no error. + */ +int avio_open_dyn_buf(AVIOContext **s); + +/** + * Return the written size and a pointer to the buffer. + * The AVIOContext stream is left intact. + * The buffer must NOT be freed. + * No padding is added to the buffer. + * + * @param s IO context + * @param pbuffer pointer to a byte buffer + * @return the length of the byte buffer + */ +int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + +/** + * Return the written size and a pointer to the buffer. The buffer + * must be freed with av_free(). + * Padding of AV_INPUT_BUFFER_PADDING_SIZE is added to the buffer. + * + * @param s IO context + * @param pbuffer pointer to a byte buffer + * @return the length of the byte buffer + */ +int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + +/** + * Iterate through names of available protocols. + * + * @param opaque A private pointer representing current protocol. + * It must be a pointer to NULL on first iteration and will + * be updated by successive calls to avio_enum_protocols. + * @param output If set to 1, iterate over output protocols, + * otherwise over input protocols. + * + * @return A static string containing the name of current protocol or NULL + */ +const char *avio_enum_protocols(void **opaque, int output); + +/** + * Get AVClass by names of available protocols. + * + * @return A AVClass of input protocol name or NULL + */ +const AVClass *avio_protocol_get_class(const char *name); + +/** + * Pause and resume playing - only meaningful if using a network streaming + * protocol (e.g. MMS). + * + * @param h IO context from which to call the read_pause function pointer + * @param pause 1 for pause, 0 for resume + */ +int avio_pause(AVIOContext *h, int pause); + +/** + * Seek to a given timestamp relative to some component stream. + * Only meaningful if using a network streaming protocol (e.g. MMS.). + * + * @param h IO context from which to call the seek function pointers + * @param stream_index The stream index that the timestamp is relative to. + * If stream_index is (-1) the timestamp should be in AV_TIME_BASE + * units from the beginning of the presentation. + * If a stream_index >= 0 is used and the protocol does not support + * seeking based on component streams, the call will fail. + * @param timestamp timestamp in AVStream.time_base units + * or if there is no stream specified then in AV_TIME_BASE units. + * @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE + * and AVSEEK_FLAG_ANY. The protocol may silently ignore + * AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will + * fail if used and not supported. + * @return >= 0 on success + * @see AVInputFormat::read_seek + */ +int64_t avio_seek_time(AVIOContext *h, int stream_index, + int64_t timestamp, int flags); + +/* Avoid a warning. The header can not be included because it breaks c++. */ +struct AVBPrint; + +/** + * Read contents of h into print buffer, up to max_size bytes, or up to EOF. + * + * @return 0 for success (max_size bytes read or EOF reached), negative error + * code otherwise + */ +int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size); + +/** + * Accept and allocate a client context on a server context. + * @param s the server context + * @param c the client context, must be unallocated + * @return >= 0 on success or a negative value corresponding + * to an AVERROR on failure + */ +int avio_accept(AVIOContext *s, AVIOContext **c); + +/** + * Perform one step of the protocol handshake to accept a new client. + * This function must be called on a client returned by avio_accept() before + * using it as a read/write context. + * It is separate from avio_accept() because it may block. + * A step of the handshake is defined by places where the application may + * decide to change the proceedings. + * For example, on a protocol with a request header and a reply header, each + * one can constitute a step because the application may use the parameters + * from the request to change parameters in the reply; or each individual + * chunk of the request can constitute a step. + * If the handshake is already finished, avio_handshake() does nothing and + * returns 0 immediately. + * + * @param c the client context to perform the handshake on + * @return 0 on a complete and successful handshake + * > 0 if the handshake progressed, but is not complete + * < 0 for an AVERROR code + */ +int avio_handshake(AVIOContext *c); +#endif /* AVFORMAT_AVIO_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavformat/version.h b/src/framework/media/thirdparty/ffmpeg/v6/libavformat/version.h new file mode 100644 index 0000000000000..9e1f484db4c41 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavformat/version.h @@ -0,0 +1,47 @@ +/* + * Version macros. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_VERSION_H +#define AVFORMAT_VERSION_H + +/** + * @file + * @ingroup libavf + * Libavformat version macros + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBAVFORMAT_VERSION_MINOR 16 +#define LIBAVFORMAT_VERSION_MICRO 100 + +#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT + +#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) + +#endif /* AVFORMAT_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavformat/version_major.h b/src/framework/media/thirdparty/ffmpeg/v6/libavformat/version_major.h new file mode 100644 index 0000000000000..224fdacf2350f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavformat/version_major.h @@ -0,0 +1,56 @@ +/* + * Version macros. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_VERSION_MAJOR_H +#define AVFORMAT_VERSION_MAJOR_H + +/** + * @file + * @ingroup libavf + * Libavformat version macros + */ + +// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) +// Also please add any ticket numbers that you believe might be affected here +#define LIBAVFORMAT_VERSION_MAJOR 60 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + * + */ +#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 61) +#define FF_API_GET_END_PTS (LIBAVFORMAT_VERSION_MAJOR < 61) +#define FF_API_AVIODIRCONTEXT (LIBAVFORMAT_VERSION_MAJOR < 61) +#define FF_API_AVFORMAT_IO_CLOSE (LIBAVFORMAT_VERSION_MAJOR < 61) +#define FF_API_AVIO_WRITE_NONCONST (LIBAVFORMAT_VERSION_MAJOR < 61) +#define FF_API_LAVF_SHORTEST (LIBAVFORMAT_VERSION_MAJOR < 61) +#define FF_API_ALLOW_FLUSH (LIBAVFORMAT_VERSION_MAJOR < 61) +#define FF_API_AVSTREAM_SIDE_DATA (LIBAVFORMAT_VERSION_MAJOR < 61) + + +#define FF_API_R_FRAME_RATE 1 + +#endif /* AVFORMAT_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/attributes.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/attributes.h new file mode 100644 index 0000000000000..04c615c952c46 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/attributes.h @@ -0,0 +1,173 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Macro definitions for various function/variable attributes + */ + +#ifndef AVUTIL_ATTRIBUTES_H +#define AVUTIL_ATTRIBUTES_H + +#ifdef __GNUC__ +# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) +# define AV_GCC_VERSION_AT_MOST(x,y) (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y)) +#else +# define AV_GCC_VERSION_AT_LEAST(x,y) 0 +# define AV_GCC_VERSION_AT_MOST(x,y) 0 +#endif + +#ifdef __has_builtin +# define AV_HAS_BUILTIN(x) __has_builtin(x) +#else +# define AV_HAS_BUILTIN(x) 0 +#endif + +#ifndef av_always_inline +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_always_inline __attribute__((always_inline)) inline +#elif defined(_MSC_VER) +# define av_always_inline __forceinline +#else +# define av_always_inline inline +#endif +#endif + +#ifndef av_extern_inline +#if defined(__ICL) && __ICL >= 1210 || defined(__GNUC_STDC_INLINE__) +# define av_extern_inline extern inline +#else +# define av_extern_inline inline +#endif +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,4) +# define av_warn_unused_result __attribute__((warn_unused_result)) +#else +# define av_warn_unused_result +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_noinline __attribute__((noinline)) +#elif defined(_MSC_VER) +# define av_noinline __declspec(noinline) +#else +# define av_noinline +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) +# define av_pure __attribute__((pure)) +#else +# define av_pure +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,6) || defined(__clang__) +# define av_const __attribute__((const)) +#else +# define av_const +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,3) || defined(__clang__) +# define av_cold __attribute__((cold)) +#else +# define av_cold +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,1) && !defined(__llvm__) +# define av_flatten __attribute__((flatten)) +#else +# define av_flatten +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define attribute_deprecated __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define attribute_deprecated __declspec(deprecated) +#else +# define attribute_deprecated +#endif + +/** + * Disable warnings about deprecated features + * This is useful for sections of code kept for backward compatibility and + * scheduled for removal. + */ +#ifndef AV_NOWARN_DEPRECATED +#if AV_GCC_VERSION_AT_LEAST(4,6) || defined(__clang__) +# define AV_NOWARN_DEPRECATED(code) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \ + code \ + _Pragma("GCC diagnostic pop") +#elif defined(_MSC_VER) +# define AV_NOWARN_DEPRECATED(code) \ + __pragma(warning(push)) \ + __pragma(warning(disable : 4996)) \ + code; \ + __pragma(warning(pop)) +#else +# define AV_NOWARN_DEPRECATED(code) code +#endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define av_unused __attribute__((unused)) +#else +# define av_unused +#endif + +/** + * Mark a variable as used and prevent the compiler from optimizing it + * away. This is useful for variables accessed only from inline + * assembler without the compiler being aware. + */ +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) +# define av_used __attribute__((used)) +#else +# define av_used +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,3) || defined(__clang__) +# define av_alias __attribute__((may_alias)) +#else +# define av_alias +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__INTEL_COMPILER) +# define av_uninit(x) x=x +#else +# define av_uninit(x) x +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define av_builtin_constant_p __builtin_constant_p +# define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos))) +#else +# define av_builtin_constant_p(x) 0 +# define av_printf_format(fmtpos, attrpos) +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,5) || defined(__clang__) +# define av_noreturn __attribute__((noreturn)) +#else +# define av_noreturn +#endif + +#endif /* AVUTIL_ATTRIBUTES_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/avconfig.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/avconfig.h new file mode 100644 index 0000000000000..f13252f7d2c25 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/avconfig.h @@ -0,0 +1,24 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVCONFIG_H +#define AVUTIL_AVCONFIG_H + +#define AV_HAVE_BIGENDIAN 0 + +#endif /* AVUTIL_AVCONFIG_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/avstring.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/avstring.h new file mode 100644 index 0000000000000..fc095349d2652 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/avstring.h @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2007 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVSTRING_H +#define AVUTIL_AVSTRING_H + +#include +#include +#include "attributes.h" + +/** + * @addtogroup lavu_string + * @{ + */ + +/** + * Return non-zero if pfx is a prefix of str. If it is, *ptr is set to + * the address of the first character in str after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_strstart(const char *str, const char *pfx, const char **ptr); + +/** + * Return non-zero if pfx is a prefix of str independent of case. If + * it is, *ptr is set to the address of the first character in str + * after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_stristart(const char *str, const char *pfx, const char **ptr); + +/** + * Locate the first case-independent occurrence in the string haystack + * of the string needle. A zero-length string needle is considered to + * match at the start of haystack. + * + * This function is a case-insensitive version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_stristr(const char *haystack, const char *needle); + +/** + * Locate the first occurrence of the string needle in the string haystack + * where not more than hay_length characters are searched. A zero-length + * string needle is considered to match at the start of haystack. + * + * This function is a length-limited version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @param hay_length length of string to search in + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_strnstr(const char *haystack, const char *needle, size_t hay_length); + +/** + * Copy the string src to dst, but no more than size - 1 bytes, and + * null-terminate dst. + * + * This function is the same as BSD strlcpy(). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the length of src + * + * @warning since the return value is the length of src, src absolutely + * _must_ be a properly 0-terminated string, otherwise this will read beyond + * the end of the buffer and possibly crash. + */ +size_t av_strlcpy(char *dst, const char *src, size_t size); + +/** + * Append the string src to the string dst, but to a total length of + * no more than size - 1 bytes, and null-terminate dst. + * + * This function is similar to BSD strlcat(), but differs when + * size <= strlen(dst). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the total length of src and dst + * + * @warning since the return value use the length of src and dst, these + * absolutely _must_ be a properly 0-terminated strings, otherwise this + * will read beyond the end of the buffer and possibly crash. + */ +size_t av_strlcat(char *dst, const char *src, size_t size); + +/** + * Append output to a string, according to a format. Never write out of + * the destination buffer, and always put a terminating 0 within + * the buffer. + * @param dst destination buffer (string to which the output is + * appended) + * @param size total size of the destination buffer + * @param fmt printf-compatible format string, specifying how the + * following parameters are used + * @return the length of the string that would have been generated + * if enough space had been available + */ +size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Get the count of continuous non zero chars starting from the beginning. + * + * @param s the string whose length to count + * @param len maximum number of characters to check in the string, that + * is the maximum value which is returned by the function + */ +static inline size_t av_strnlen(const char *s, size_t len) +{ + size_t i; + for (i = 0; i < len && s[i]; i++) + ; + return i; +} + +/** + * Print arguments following specified format into a large enough auto + * allocated buffer. It is similar to GNU asprintf(). + * @param fmt printf-compatible format string, specifying how the + * following parameters are used. + * @return the allocated string + * @note You have to free the string yourself with av_free(). + */ +char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2); + +/** + * Unescape the given string until a non escaped terminating char, + * and return the token corresponding to the unescaped string. + * + * The normal \ and ' escaping is supported. Leading and trailing + * whitespaces are removed, unless they are escaped with '\' or are + * enclosed between ''. + * + * @param buf the buffer to parse, buf will be updated to point to the + * terminating char + * @param term a 0-terminated list of terminating chars + * @return the malloced unescaped string, which must be av_freed by + * the user, NULL in case of allocation failure + */ +char *av_get_token(const char **buf, const char *term); + +/** + * Split the string into several tokens which can be accessed by + * successive calls to av_strtok(). + * + * A token is defined as a sequence of characters not belonging to the + * set specified in delim. + * + * On the first call to av_strtok(), s should point to the string to + * parse, and the value of saveptr is ignored. In subsequent calls, s + * should be NULL, and saveptr should be unchanged since the previous + * call. + * + * This function is similar to strtok_r() defined in POSIX.1. + * + * @param s the string to parse, may be NULL + * @param delim 0-terminated list of token delimiters, must be non-NULL + * @param saveptr user-provided pointer which points to stored + * information necessary for av_strtok() to continue scanning the same + * string. saveptr is updated to point to the next character after the + * first delimiter found, or to NULL if the string was terminated + * @return the found token, or NULL when no token is found + */ +char *av_strtok(char *s, const char *delim, char **saveptr); + +/** + * Locale-independent conversion of ASCII isdigit. + */ +static inline av_const int av_isdigit(int c) +{ + return c >= '0' && c <= '9'; +} + +/** + * Locale-independent conversion of ASCII isgraph. + */ +static inline av_const int av_isgraph(int c) +{ + return c > 32 && c < 127; +} + +/** + * Locale-independent conversion of ASCII isspace. + */ +static inline av_const int av_isspace(int c) +{ + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || + c == '\v'; +} + +/** + * Locale-independent conversion of ASCII characters to uppercase. + */ +static inline av_const int av_toupper(int c) +{ + if (c >= 'a' && c <= 'z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII characters to lowercase. + */ +static inline av_const int av_tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII isxdigit. + */ +static inline av_const int av_isxdigit(int c) +{ + c = av_tolower(c); + return av_isdigit(c) || (c >= 'a' && c <= 'f'); +} + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strcasecmp(const char *a, const char *b); + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strncasecmp(const char *a, const char *b, size_t n); + +/** + * Locale-independent strings replace. + * @note This means only ASCII-range characters are replaced. + */ +char *av_strireplace(const char *str, const char *from, const char *to); + +/** + * Thread safe basename. + * @param path the string to parse, on DOS both \ and / are considered separators. + * @return pointer to the basename substring. + * If path does not contain a slash, the function returns a copy of path. + * If path is a NULL pointer or points to an empty string, a pointer + * to a string "." is returned. + */ +const char *av_basename(const char *path); + +/** + * Thread safe dirname. + * @param path the string to parse, on DOS both \ and / are considered separators. + * @return A pointer to a string that's the parent directory of path. + * If path is a NULL pointer or points to an empty string, a pointer + * to a string "." is returned. + * @note the function may modify the contents of the path, so copies should be passed. + */ +const char *av_dirname(char *path); + +/** + * Match instances of a name in a comma-separated list of names. + * List entries are checked from the start to the end of the names list, + * the first match ends further processing. If an entry prefixed with '-' + * matches, then 0 is returned. The "ALL" list entry is considered to + * match all names. + * + * @param name Name to look for. + * @param names List of names. + * @return 1 on match, 0 otherwise. + */ +int av_match_name(const char *name, const char *names); + +/** + * Append path component to the existing path. + * Path separator '/' is placed between when needed. + * Resulting string have to be freed with av_free(). + * @param path base path + * @param component component to be appended + * @return new path or NULL on error. + */ +char *av_append_path_component(const char *path, const char *component); + +enum AVEscapeMode { + AV_ESCAPE_MODE_AUTO, ///< Use auto-selected escaping mode. + AV_ESCAPE_MODE_BACKSLASH, ///< Use backslash escaping. + AV_ESCAPE_MODE_QUOTE, ///< Use single-quote escaping. + AV_ESCAPE_MODE_XML, ///< Use XML non-markup character data escaping. +}; + +/** + * Consider spaces special and escape them even in the middle of the + * string. + * + * This is equivalent to adding the whitespace characters to the special + * characters lists, except it is guaranteed to use the exact same list + * of whitespace characters as the rest of libavutil. + */ +#define AV_ESCAPE_FLAG_WHITESPACE (1 << 0) + +/** + * Escape only specified special characters. + * Without this flag, escape also any characters that may be considered + * special by av_get_token(), such as the single quote. + */ +#define AV_ESCAPE_FLAG_STRICT (1 << 1) + +/** + * Within AV_ESCAPE_MODE_XML, additionally escape single quotes for single + * quoted attributes. + */ +#define AV_ESCAPE_FLAG_XML_SINGLE_QUOTES (1 << 2) + +/** + * Within AV_ESCAPE_MODE_XML, additionally escape double quotes for double + * quoted attributes. + */ +#define AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES (1 << 3) + + +/** + * Escape string in src, and put the escaped string in an allocated + * string in *dst, which must be freed with av_free(). + * + * @param dst pointer where an allocated string is put + * @param src string to escape, must be non-NULL + * @param special_chars string containing the special characters which + * need to be escaped, can be NULL + * @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros. + * Any unknown value for mode will be considered equivalent to + * AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without + * notice. + * @param flags flags which control how to escape, see AV_ESCAPE_FLAG_ macros + * @return the length of the allocated string, or a negative error code in case of error + * @see av_bprint_escape() + */ +av_warn_unused_result +int av_escape(char **dst, const char *src, const char *special_chars, + enum AVEscapeMode mode, int flags); + +#define AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES 1 ///< accept codepoints over 0x10FFFF +#define AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS 2 ///< accept non-characters - 0xFFFE and 0xFFFF +#define AV_UTF8_FLAG_ACCEPT_SURROGATES 4 ///< accept UTF-16 surrogates codes +#define AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES 8 ///< exclude control codes not accepted by XML + +#define AV_UTF8_FLAG_ACCEPT_ALL \ + AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES|AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS|AV_UTF8_FLAG_ACCEPT_SURROGATES + +/** + * Read and decode a single UTF-8 code point (character) from the + * buffer in *buf, and update *buf to point to the next byte to + * decode. + * + * In case of an invalid byte sequence, the pointer will be updated to + * the next byte after the invalid sequence and the function will + * return an error code. + * + * Depending on the specified flags, the function will also fail in + * case the decoded code point does not belong to a valid range. + * + * @note For speed-relevant code a carefully implemented use of + * GET_UTF8() may be preferred. + * + * @param codep pointer used to return the parsed code in case of success. + * The value in *codep is set even in case the range check fails. + * @param bufp pointer to the address the first byte of the sequence + * to decode, updated by the function to point to the + * byte next after the decoded sequence + * @param buf_end pointer to the end of the buffer, points to the next + * byte past the last in the buffer. This is used to + * avoid buffer overreads (in case of an unfinished + * UTF-8 sequence towards the end of the buffer). + * @param flags a collection of AV_UTF8_FLAG_* flags + * @return >= 0 in case a sequence was successfully read, a negative + * value in case of invalid sequence + */ +av_warn_unused_result +int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end, + unsigned int flags); + +/** + * Check if a name is in a list. + * @returns 0 if not found, or the 1 based index where it has been found in the + * list. + */ +int av_match_list(const char *name, const char *list, char separator); + +/** + * See libc sscanf manual for more information. + * Locale-independent sscanf implementation. + */ +int av_sscanf(const char *string, const char *format, ...); + +/** + * @} + */ + +#endif /* AVUTIL_AVSTRING_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/avutil.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/avutil.h new file mode 100644 index 0000000000000..a362c8baa831a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/avutil.h @@ -0,0 +1,375 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVUTIL_H +#define AVUTIL_AVUTIL_H + +/** + * @file + * @ingroup lavu + * Convenience header that includes @ref lavu "libavutil"'s core. + */ + +/** + * @mainpage + * + * @section ffmpeg_intro Introduction + * + * This document describes the usage of the different libraries + * provided by FFmpeg. + * + * @li @ref libavc "libavcodec" encoding/decoding library + * @li @ref lavfi "libavfilter" graph-based frame editing library + * @li @ref libavf "libavformat" I/O and muxing/demuxing library + * @li @ref lavd "libavdevice" special devices muxing/demuxing library + * @li @ref lavu "libavutil" common utility library + * @li @ref lswr "libswresample" audio resampling, format conversion and mixing + * @li @ref lpp "libpostproc" post processing library + * @li @ref libsws "libswscale" color conversion and scaling library + * + * @section ffmpeg_versioning Versioning and compatibility + * + * Each of the FFmpeg libraries contains a version.h header, which defines a + * major, minor and micro version number with the + * LIBRARYNAME_VERSION_{MAJOR,MINOR,MICRO} macros. The major version + * number is incremented with backward incompatible changes - e.g. removing + * parts of the public API, reordering public struct members, etc. The minor + * version number is incremented for backward compatible API changes or major + * new features - e.g. adding a new public function or a new decoder. The micro + * version number is incremented for smaller changes that a calling program + * might still want to check for - e.g. changing behavior in a previously + * unspecified situation. + * + * FFmpeg guarantees backward API and ABI compatibility for each library as long + * as its major version number is unchanged. This means that no public symbols + * will be removed or renamed. Types and names of the public struct members and + * values of public macros and enums will remain the same (unless they were + * explicitly declared as not part of the public API). Documented behavior will + * not change. + * + * In other words, any correct program that works with a given FFmpeg snapshot + * should work just as well without any changes with any later snapshot with the + * same major versions. This applies to both rebuilding the program against new + * FFmpeg versions or to replacing the dynamic FFmpeg libraries that a program + * links against. + * + * However, new public symbols may be added and new members may be appended to + * public structs whose size is not part of public ABI (most public structs in + * FFmpeg). New macros and enum values may be added. Behavior in undocumented + * situations may change slightly (and be documented). All those are accompanied + * by an entry in doc/APIchanges and incrementing either the minor or micro + * version number. + */ + +/** + * @defgroup lavu libavutil + * Common code shared across all FFmpeg libraries. + * + * @note + * libavutil is designed to be modular. In most cases, in order to use the + * functions provided by one component of libavutil you must explicitly include + * the specific header containing that feature. If you are only using + * media-related components, you could simply include libavutil/avutil.h, which + * brings in most of the "core" components. + * + * @{ + * + * @defgroup lavu_crypto Crypto and Hashing + * + * @{ + * @} + * + * @defgroup lavu_math Mathematics + * @{ + * + * @} + * + * @defgroup lavu_string String Manipulation + * + * @{ + * + * @} + * + * @defgroup lavu_mem Memory Management + * + * @{ + * + * @} + * + * @defgroup lavu_data Data Structures + * @{ + * + * @} + * + * @defgroup lavu_video Video related + * + * @{ + * + * @} + * + * @defgroup lavu_audio Audio related + * + * @{ + * + * @} + * + * @defgroup lavu_error Error Codes + * + * @{ + * + * @} + * + * @defgroup lavu_log Logging Facility + * + * @{ + * + * @} + * + * @defgroup lavu_misc Other + * + * @{ + * + * @defgroup preproc_misc Preprocessor String Macros + * + * @{ + * + * @} + * + * @defgroup version_utils Library Version Macros + * + * @{ + * + * @} + */ + + +/** + * @addtogroup lavu_ver + * @{ + */ + +/** + * Return the LIBAVUTIL_VERSION_INT constant. + */ +unsigned avutil_version(void); + +/** + * Return an informative version string. This usually is the actual release + * version number or a git commit description. This string has no fixed format + * and can change any time. It should never be parsed by code. + */ +const char *av_version_info(void); + +/** + * Return the libavutil build-time configuration. + */ +const char *avutil_configuration(void); + +/** + * Return the libavutil license. + */ +const char *avutil_license(void); + +/** + * @} + */ + +/** + * @addtogroup lavu_media Media Type + * @brief Media Type + */ + +enum AVMediaType { + AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA + AVMEDIA_TYPE_VIDEO, + AVMEDIA_TYPE_AUDIO, + AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous + AVMEDIA_TYPE_SUBTITLE, + AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse + AVMEDIA_TYPE_NB +}; + +/** + * Return a string describing the media_type enum, NULL if media_type + * is unknown. + */ +const char *av_get_media_type_string(enum AVMediaType media_type); + +/** + * @defgroup lavu_const Constants + * @{ + * + * @defgroup lavu_enc Encoding specific + * + * @note those definition should move to avcodec + * @{ + */ + +#define FF_LAMBDA_SHIFT 7 +#define FF_LAMBDA_SCALE (1< +#include + +/** + * @defgroup lavu_buffer AVBuffer + * @ingroup lavu_data + * + * @{ + * AVBuffer is an API for reference-counted data buffers. + * + * There are two core objects in this API -- AVBuffer and AVBufferRef. AVBuffer + * represents the data buffer itself; it is opaque and not meant to be accessed + * by the caller directly, but only through AVBufferRef. However, the caller may + * e.g. compare two AVBuffer pointers to check whether two different references + * are describing the same data buffer. AVBufferRef represents a single + * reference to an AVBuffer and it is the object that may be manipulated by the + * caller directly. + * + * There are two functions provided for creating a new AVBuffer with a single + * reference -- av_buffer_alloc() to just allocate a new buffer, and + * av_buffer_create() to wrap an existing array in an AVBuffer. From an existing + * reference, additional references may be created with av_buffer_ref(). + * Use av_buffer_unref() to free a reference (this will automatically free the + * data once all the references are freed). + * + * The convention throughout this API and the rest of FFmpeg is such that the + * buffer is considered writable if there exists only one reference to it (and + * it has not been marked as read-only). The av_buffer_is_writable() function is + * provided to check whether this is true and av_buffer_make_writable() will + * automatically create a new writable buffer when necessary. + * Of course nothing prevents the calling code from violating this convention, + * however that is safe only when all the existing references are under its + * control. + * + * @note Referencing and unreferencing the buffers is thread-safe and thus + * may be done from multiple threads simultaneously without any need for + * additional locking. + * + * @note Two different references to the same buffer can point to different + * parts of the buffer (i.e. their AVBufferRef.data will not be equal). + */ + +/** + * A reference counted buffer type. It is opaque and is meant to be used through + * references (AVBufferRef). + */ +typedef struct AVBuffer AVBuffer; + +/** + * A reference to a data buffer. + * + * The size of this struct is not a part of the public ABI and it is not meant + * to be allocated directly. + */ +typedef struct AVBufferRef { + AVBuffer *buffer; + + /** + * The data buffer. It is considered writable if and only if + * this is the only reference to the buffer, in which case + * av_buffer_is_writable() returns 1. + */ + uint8_t *data; + /** + * Size of data in bytes. + */ + size_t size; +} AVBufferRef; + +/** + * Allocate an AVBuffer of the given size using av_malloc(). + * + * @return an AVBufferRef of given size or NULL when out of memory + */ +AVBufferRef *av_buffer_alloc(size_t size); + +/** + * Same as av_buffer_alloc(), except the returned buffer will be initialized + * to zero. + */ +AVBufferRef *av_buffer_allocz(size_t size); + +/** + * Always treat the buffer as read-only, even when it has only one + * reference. + */ +#define AV_BUFFER_FLAG_READONLY (1 << 0) + +/** + * Create an AVBuffer from an existing array. + * + * If this function is successful, data is owned by the AVBuffer. The caller may + * only access data through the returned AVBufferRef and references derived from + * it. + * If this function fails, data is left untouched. + * @param data data array + * @param size size of data in bytes + * @param free a callback for freeing this buffer's data + * @param opaque parameter to be got for processing or passed to free + * @param flags a combination of AV_BUFFER_FLAG_* + * + * @return an AVBufferRef referring to data on success, NULL on failure. + */ +AVBufferRef *av_buffer_create(uint8_t *data, size_t size, + void (*free)(void *opaque, uint8_t *data), + void *opaque, int flags); + +/** + * Default free callback, which calls av_free() on the buffer data. + * This function is meant to be passed to av_buffer_create(), not called + * directly. + */ +void av_buffer_default_free(void *opaque, uint8_t *data); + +/** + * Create a new reference to an AVBuffer. + * + * @return a new AVBufferRef referring to the same AVBuffer as buf or NULL on + * failure. + */ +AVBufferRef *av_buffer_ref(const AVBufferRef *buf); + +/** + * Free a given reference and automatically free the buffer if there are no more + * references to it. + * + * @param buf the reference to be freed. The pointer is set to NULL on return. + */ +void av_buffer_unref(AVBufferRef **buf); + +/** + * @return 1 if the caller may write to the data referred to by buf (which is + * true if and only if buf is the only reference to the underlying AVBuffer). + * Return 0 otherwise. + * A positive answer is valid until av_buffer_ref() is called on buf. + */ +int av_buffer_is_writable(const AVBufferRef *buf); + +/** + * @return the opaque parameter set by av_buffer_create. + */ +void *av_buffer_get_opaque(const AVBufferRef *buf); + +int av_buffer_get_ref_count(const AVBufferRef *buf); + +/** + * Create a writable reference from a given buffer reference, avoiding data copy + * if possible. + * + * @param buf buffer reference to make writable. On success, buf is either left + * untouched, or it is unreferenced and a new writable AVBufferRef is + * written in its place. On failure, buf is left untouched. + * @return 0 on success, a negative AVERROR on failure. + */ +int av_buffer_make_writable(AVBufferRef **buf); + +/** + * Reallocate a given buffer. + * + * @param buf a buffer reference to reallocate. On success, buf will be + * unreferenced and a new reference with the required size will be + * written in its place. On failure buf will be left untouched. *buf + * may be NULL, then a new buffer is allocated. + * @param size required new buffer size. + * @return 0 on success, a negative AVERROR on failure. + * + * @note the buffer is actually reallocated with av_realloc() only if it was + * initially allocated through av_buffer_realloc(NULL) and there is only one + * reference to it (i.e. the one passed to this function). In all other cases + * a new buffer is allocated and the data is copied. + */ +int av_buffer_realloc(AVBufferRef **buf, size_t size); + +/** + * Ensure dst refers to the same data as src. + * + * When *dst is already equivalent to src, do nothing. Otherwise unreference dst + * and replace it with a new reference to src. + * + * @param dst Pointer to either a valid buffer reference or NULL. On success, + * this will point to a buffer reference equivalent to src. On + * failure, dst will be left untouched. + * @param src A buffer reference to replace dst with. May be NULL, then this + * function is equivalent to av_buffer_unref(dst). + * @return 0 on success + * AVERROR(ENOMEM) on memory allocation failure. + */ +int av_buffer_replace(AVBufferRef **dst, const AVBufferRef *src); + +/** + * @} + */ + +/** + * @defgroup lavu_bufferpool AVBufferPool + * @ingroup lavu_data + * + * @{ + * AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers. + * + * Frequently allocating and freeing large buffers may be slow. AVBufferPool is + * meant to solve this in cases when the caller needs a set of buffers of the + * same size (the most obvious use case being buffers for raw video or audio + * frames). + * + * At the beginning, the user must call av_buffer_pool_init() to create the + * buffer pool. Then whenever a buffer is needed, call av_buffer_pool_get() to + * get a reference to a new buffer, similar to av_buffer_alloc(). This new + * reference works in all aspects the same way as the one created by + * av_buffer_alloc(). However, when the last reference to this buffer is + * unreferenced, it is returned to the pool instead of being freed and will be + * reused for subsequent av_buffer_pool_get() calls. + * + * When the caller is done with the pool and no longer needs to allocate any new + * buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable. + * Once all the buffers are released, it will automatically be freed. + * + * Allocating and releasing buffers with this API is thread-safe as long as + * either the default alloc callback is used, or the user-supplied one is + * thread-safe. + */ + +/** + * The buffer pool. This structure is opaque and not meant to be accessed + * directly. It is allocated with av_buffer_pool_init() and freed with + * av_buffer_pool_uninit(). + */ +typedef struct AVBufferPool AVBufferPool; + +/** + * Allocate and initialize a buffer pool. + * + * @param size size of each buffer in this pool + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be used + * (av_buffer_alloc()). + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init(size_t size, AVBufferRef* (*alloc)(size_t size)); + +/** + * Allocate and initialize a buffer pool with a more complex allocator. + * + * @param size size of each buffer in this pool + * @param opaque arbitrary user data used by the allocator + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be + * used (av_buffer_alloc()). + * @param pool_free a function that will be called immediately before the pool + * is freed. I.e. after av_buffer_pool_uninit() is called + * by the caller and all the frames are returned to the pool + * and freed. It is intended to uninitialize the user opaque + * data. May be NULL. + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init2(size_t size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, size_t size), + void (*pool_free)(void *opaque)); + +/** + * Mark the pool as being available for freeing. It will actually be freed only + * once all the allocated buffers associated with the pool are released. Thus it + * is safe to call this function while some of the allocated buffers are still + * in use. + * + * @param pool pointer to the pool to be freed. It will be set to NULL. + */ +void av_buffer_pool_uninit(AVBufferPool **pool); + +/** + * Allocate a new AVBuffer, reusing an old buffer from the pool when available. + * This function may be called simultaneously from multiple threads. + * + * @return a reference to the new buffer on success, NULL on error. + */ +AVBufferRef *av_buffer_pool_get(AVBufferPool *pool); + +/** + * Query the original opaque parameter of an allocated buffer in the pool. + * + * @param ref a buffer reference to a buffer returned by av_buffer_pool_get. + * @return the opaque parameter set by the buffer allocator function of the + * buffer pool. + * + * @note the opaque parameter of ref is used by the buffer pool implementation, + * therefore you have to use this function to access the original opaque + * parameter of an allocated buffer. + */ +void *av_buffer_pool_buffer_get_opaque(const AVBufferRef *ref); + +/** + * @} + */ + +#endif /* AVUTIL_BUFFER_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/channel_layout.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/channel_layout.h new file mode 100644 index 0000000000000..c9c404ef18571 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/channel_layout.h @@ -0,0 +1,807 @@ +/* + * Copyright (c) 2006 Michael Niedermayer + * Copyright (c) 2008 Peter Ross + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_CHANNEL_LAYOUT_H +#define AVUTIL_CHANNEL_LAYOUT_H + +#include +#include + +#include "version.h" +#include "attributes.h" + +/** + * @file + * @ingroup lavu_audio_channels + * Public libavutil channel layout APIs header. + */ + + +/** + * @defgroup lavu_audio_channels Audio channels + * @ingroup lavu_audio + * + * Audio channel layout utility functions + * + * @{ + */ + +enum AVChannel { + ///< Invalid channel index + AV_CHAN_NONE = -1, + AV_CHAN_FRONT_LEFT, + AV_CHAN_FRONT_RIGHT, + AV_CHAN_FRONT_CENTER, + AV_CHAN_LOW_FREQUENCY, + AV_CHAN_BACK_LEFT, + AV_CHAN_BACK_RIGHT, + AV_CHAN_FRONT_LEFT_OF_CENTER, + AV_CHAN_FRONT_RIGHT_OF_CENTER, + AV_CHAN_BACK_CENTER, + AV_CHAN_SIDE_LEFT, + AV_CHAN_SIDE_RIGHT, + AV_CHAN_TOP_CENTER, + AV_CHAN_TOP_FRONT_LEFT, + AV_CHAN_TOP_FRONT_CENTER, + AV_CHAN_TOP_FRONT_RIGHT, + AV_CHAN_TOP_BACK_LEFT, + AV_CHAN_TOP_BACK_CENTER, + AV_CHAN_TOP_BACK_RIGHT, + /** Stereo downmix. */ + AV_CHAN_STEREO_LEFT = 29, + /** See above. */ + AV_CHAN_STEREO_RIGHT, + AV_CHAN_WIDE_LEFT, + AV_CHAN_WIDE_RIGHT, + AV_CHAN_SURROUND_DIRECT_LEFT, + AV_CHAN_SURROUND_DIRECT_RIGHT, + AV_CHAN_LOW_FREQUENCY_2, + AV_CHAN_TOP_SIDE_LEFT, + AV_CHAN_TOP_SIDE_RIGHT, + AV_CHAN_BOTTOM_FRONT_CENTER, + AV_CHAN_BOTTOM_FRONT_LEFT, + AV_CHAN_BOTTOM_FRONT_RIGHT, + + /** Channel is empty can be safely skipped. */ + AV_CHAN_UNUSED = 0x200, + + /** Channel contains data, but its position is unknown. */ + AV_CHAN_UNKNOWN = 0x300, + + /** + * Range of channels between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END represent Ambisonic components using the ACN system. + * + * Given a channel id `` between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END (inclusive), the ACN index of the channel `` is + * ` = - AV_CHAN_AMBISONIC_BASE`. + * + * @note these values are only used for AV_CHANNEL_ORDER_CUSTOM channel + * orderings, the AV_CHANNEL_ORDER_AMBISONIC ordering orders the channels + * implicitly by their position in the stream. + */ + AV_CHAN_AMBISONIC_BASE = 0x400, + // leave space for 1024 ids, which correspond to maximum order-32 harmonics, + // which should be enough for the foreseeable use cases + AV_CHAN_AMBISONIC_END = 0x7ff, +}; + +enum AVChannelOrder { + /** + * Only the channel count is specified, without any further information + * about the channel order. + */ + AV_CHANNEL_ORDER_UNSPEC, + /** + * The native channel order, i.e. the channels are in the same order in + * which they are defined in the AVChannel enum. This supports up to 63 + * different channels. + */ + AV_CHANNEL_ORDER_NATIVE, + /** + * The channel order does not correspond to any other predefined order and + * is stored as an explicit map. For example, this could be used to support + * layouts with 64 or more channels, or with empty/skipped (AV_CHAN_SILENCE) + * channels at arbitrary positions. + */ + AV_CHANNEL_ORDER_CUSTOM, + /** + * The audio is represented as the decomposition of the sound field into + * spherical harmonics. Each channel corresponds to a single expansion + * component. Channels are ordered according to ACN (Ambisonic Channel + * Number). + * + * The channel with the index n in the stream contains the spherical + * harmonic of degree l and order m given by + * @code{.unparsed} + * l = floor(sqrt(n)), + * m = n - l * (l + 1). + * @endcode + * + * Conversely given a spherical harmonic of degree l and order m, the + * corresponding channel index n is given by + * @code{.unparsed} + * n = l * (l + 1) + m. + * @endcode + * + * Normalization is assumed to be SN3D (Schmidt Semi-Normalization) + * as defined in AmbiX format $ 2.1. + */ + AV_CHANNEL_ORDER_AMBISONIC, +}; + + +/** + * @defgroup channel_masks Audio channel masks + * + * A channel layout is a 64-bits integer with a bit set for every channel. + * The number of bits set must be equal to the number of channels. + * The value 0 means that the channel layout is not known. + * @note this data structure is not powerful enough to handle channels + * combinations that have the same channel multiple times, such as + * dual-mono. + * + * @{ + */ +#define AV_CH_FRONT_LEFT (1ULL << AV_CHAN_FRONT_LEFT ) +#define AV_CH_FRONT_RIGHT (1ULL << AV_CHAN_FRONT_RIGHT ) +#define AV_CH_FRONT_CENTER (1ULL << AV_CHAN_FRONT_CENTER ) +#define AV_CH_LOW_FREQUENCY (1ULL << AV_CHAN_LOW_FREQUENCY ) +#define AV_CH_BACK_LEFT (1ULL << AV_CHAN_BACK_LEFT ) +#define AV_CH_BACK_RIGHT (1ULL << AV_CHAN_BACK_RIGHT ) +#define AV_CH_FRONT_LEFT_OF_CENTER (1ULL << AV_CHAN_FRONT_LEFT_OF_CENTER ) +#define AV_CH_FRONT_RIGHT_OF_CENTER (1ULL << AV_CHAN_FRONT_RIGHT_OF_CENTER) +#define AV_CH_BACK_CENTER (1ULL << AV_CHAN_BACK_CENTER ) +#define AV_CH_SIDE_LEFT (1ULL << AV_CHAN_SIDE_LEFT ) +#define AV_CH_SIDE_RIGHT (1ULL << AV_CHAN_SIDE_RIGHT ) +#define AV_CH_TOP_CENTER (1ULL << AV_CHAN_TOP_CENTER ) +#define AV_CH_TOP_FRONT_LEFT (1ULL << AV_CHAN_TOP_FRONT_LEFT ) +#define AV_CH_TOP_FRONT_CENTER (1ULL << AV_CHAN_TOP_FRONT_CENTER ) +#define AV_CH_TOP_FRONT_RIGHT (1ULL << AV_CHAN_TOP_FRONT_RIGHT ) +#define AV_CH_TOP_BACK_LEFT (1ULL << AV_CHAN_TOP_BACK_LEFT ) +#define AV_CH_TOP_BACK_CENTER (1ULL << AV_CHAN_TOP_BACK_CENTER ) +#define AV_CH_TOP_BACK_RIGHT (1ULL << AV_CHAN_TOP_BACK_RIGHT ) +#define AV_CH_STEREO_LEFT (1ULL << AV_CHAN_STEREO_LEFT ) +#define AV_CH_STEREO_RIGHT (1ULL << AV_CHAN_STEREO_RIGHT ) +#define AV_CH_WIDE_LEFT (1ULL << AV_CHAN_WIDE_LEFT ) +#define AV_CH_WIDE_RIGHT (1ULL << AV_CHAN_WIDE_RIGHT ) +#define AV_CH_SURROUND_DIRECT_LEFT (1ULL << AV_CHAN_SURROUND_DIRECT_LEFT ) +#define AV_CH_SURROUND_DIRECT_RIGHT (1ULL << AV_CHAN_SURROUND_DIRECT_RIGHT) +#define AV_CH_LOW_FREQUENCY_2 (1ULL << AV_CHAN_LOW_FREQUENCY_2 ) +#define AV_CH_TOP_SIDE_LEFT (1ULL << AV_CHAN_TOP_SIDE_LEFT ) +#define AV_CH_TOP_SIDE_RIGHT (1ULL << AV_CHAN_TOP_SIDE_RIGHT ) +#define AV_CH_BOTTOM_FRONT_CENTER (1ULL << AV_CHAN_BOTTOM_FRONT_CENTER ) +#define AV_CH_BOTTOM_FRONT_LEFT (1ULL << AV_CHAN_BOTTOM_FRONT_LEFT ) +#define AV_CH_BOTTOM_FRONT_RIGHT (1ULL << AV_CHAN_BOTTOM_FRONT_RIGHT ) + +#if FF_API_OLD_CHANNEL_LAYOUT +/** Channel mask value used for AVCodecContext.request_channel_layout + to indicate that the user requests the channel order of the decoder output + to be the native codec channel order. + @deprecated channel order is now indicated in a special field in + AVChannelLayout + */ +#define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL +#endif + +/** + * @} + * @defgroup channel_mask_c Audio channel layouts + * @{ + * */ +#define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT) +#define AV_CH_LAYOUT_2POINT1 (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_3POINT1 (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_4POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_4POINT1 (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_2 (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_QUAD (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_5POINT0_BACK (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT1_BACK (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_6POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT0_FRONT (AV_CH_LAYOUT_2_2|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_HEXAGONAL (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_3POINT1POINT2 (AV_CH_LAYOUT_3POINT1|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_6POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_FRONT (AV_CH_LAYOUT_6POINT0_FRONT|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_7POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT0_FRONT (AV_CH_LAYOUT_5POINT0|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1_WIDE_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_5POINT1POINT2_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_CUBE (AV_CH_LAYOUT_QUAD|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT1POINT4_BACK (AV_CH_LAYOUT_5POINT1POINT2_BACK|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT1POINT2 (AV_CH_LAYOUT_7POINT1|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_7POINT1POINT4_BACK (AV_CH_LAYOUT_7POINT1POINT2|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT) +#define AV_CH_LAYOUT_HEXADECAGONAL (AV_CH_LAYOUT_OCTAGONAL|AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT) +#define AV_CH_LAYOUT_22POINT2 (AV_CH_LAYOUT_7POINT1POINT4_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER|AV_CH_BACK_CENTER|AV_CH_LOW_FREQUENCY_2|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_CENTER|AV_CH_TOP_SIDE_LEFT|AV_CH_TOP_SIDE_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_BOTTOM_FRONT_CENTER|AV_CH_BOTTOM_FRONT_LEFT|AV_CH_BOTTOM_FRONT_RIGHT) + +#define AV_CH_LAYOUT_7POINT1_TOP_BACK AV_CH_LAYOUT_5POINT1POINT2_BACK + +enum AVMatrixEncoding { + AV_MATRIX_ENCODING_NONE, + AV_MATRIX_ENCODING_DOLBY, + AV_MATRIX_ENCODING_DPLII, + AV_MATRIX_ENCODING_DPLIIX, + AV_MATRIX_ENCODING_DPLIIZ, + AV_MATRIX_ENCODING_DOLBYEX, + AV_MATRIX_ENCODING_DOLBYHEADPHONE, + AV_MATRIX_ENCODING_NB +}; + +/** + * @} + */ + +/** + * An AVChannelCustom defines a single channel within a custom order layout + * + * Unlike most structures in FFmpeg, sizeof(AVChannelCustom) is a part of the + * public ABI. + * + * No new fields may be added to it without a major version bump. + */ +typedef struct AVChannelCustom { + enum AVChannel id; + char name[16]; + void *opaque; +} AVChannelCustom; + +/** + * An AVChannelLayout holds information about the channel layout of audio data. + * + * A channel layout here is defined as a set of channels ordered in a specific + * way (unless the channel order is AV_CHANNEL_ORDER_UNSPEC, in which case an + * AVChannelLayout carries only the channel count). + * All orders may be treated as if they were AV_CHANNEL_ORDER_UNSPEC by + * ignoring everything but the channel count, as long as av_channel_layout_check() + * considers they are valid. + * + * Unlike most structures in FFmpeg, sizeof(AVChannelLayout) is a part of the + * public ABI and may be used by the caller. E.g. it may be allocated on stack + * or embedded in caller-defined structs. + * + * AVChannelLayout can be initialized as follows: + * - default initialization with {0}, followed by setting all used fields + * correctly; + * - by assigning one of the predefined AV_CHANNEL_LAYOUT_* initializers; + * - with a constructor function, such as av_channel_layout_default(), + * av_channel_layout_from_mask() or av_channel_layout_from_string(). + * + * The channel layout must be unitialized with av_channel_layout_uninit() + * + * Copying an AVChannelLayout via assigning is forbidden, + * av_channel_layout_copy() must be used instead (and its return value should + * be checked) + * + * No new fields may be added to it without a major version bump, except for + * new elements of the union fitting in sizeof(uint64_t). + */ +typedef struct AVChannelLayout { + /** + * Channel order used in this layout. + * This is a mandatory field. + */ + enum AVChannelOrder order; + + /** + * Number of channels in this layout. Mandatory field. + */ + int nb_channels; + + /** + * Details about which channels are present in this layout. + * For AV_CHANNEL_ORDER_UNSPEC, this field is undefined and must not be + * used. + */ + union { + /** + * This member must be used for AV_CHANNEL_ORDER_NATIVE, and may be used + * for AV_CHANNEL_ORDER_AMBISONIC to signal non-diegetic channels. + * It is a bitmask, where the position of each set bit means that the + * AVChannel with the corresponding value is present. + * + * I.e. when (mask & (1 << AV_CHAN_FOO)) is non-zero, then AV_CHAN_FOO + * is present in the layout. Otherwise it is not present. + * + * @note when a channel layout using a bitmask is constructed or + * modified manually (i.e. not using any of the av_channel_layout_* + * functions), the code doing it must ensure that the number of set bits + * is equal to nb_channels. + */ + uint64_t mask; + /** + * This member must be used when the channel order is + * AV_CHANNEL_ORDER_CUSTOM. It is a nb_channels-sized array, with each + * element signalling the presence of the AVChannel with the + * corresponding value in map[i].id. + * + * I.e. when map[i].id is equal to AV_CHAN_FOO, then AV_CH_FOO is the + * i-th channel in the audio data. + * + * When map[i].id is in the range between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END (inclusive), the channel contains an ambisonic + * component with ACN index (as defined above) + * n = map[i].id - AV_CHAN_AMBISONIC_BASE. + * + * map[i].name may be filled with a 0-terminated string, in which case + * it will be used for the purpose of identifying the channel with the + * convenience functions below. Otherise it must be zeroed. + */ + AVChannelCustom *map; + } u; + + /** + * For some private data of the user. + */ + void *opaque; +} AVChannelLayout; + +/** + * Macro to define native channel layouts + * + * @note This doesn't use designated initializers for compatibility with C++ 17 and older. + */ +#define AV_CHANNEL_LAYOUT_MASK(nb, m) \ + { /* .order */ AV_CHANNEL_ORDER_NATIVE, \ + /* .nb_channels */ (nb), \ + /* .u.mask */ { m }, \ + /* .opaque */ NULL } + +/** + * @name Common pre-defined channel layouts + * @{ + */ +#define AV_CHANNEL_LAYOUT_MONO AV_CHANNEL_LAYOUT_MASK(1, AV_CH_LAYOUT_MONO) +#define AV_CHANNEL_LAYOUT_STEREO AV_CHANNEL_LAYOUT_MASK(2, AV_CH_LAYOUT_STEREO) +#define AV_CHANNEL_LAYOUT_2POINT1 AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_2POINT1) +#define AV_CHANNEL_LAYOUT_2_1 AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_2_1) +#define AV_CHANNEL_LAYOUT_SURROUND AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_SURROUND) +#define AV_CHANNEL_LAYOUT_3POINT1 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_3POINT1) +#define AV_CHANNEL_LAYOUT_4POINT0 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_4POINT0) +#define AV_CHANNEL_LAYOUT_4POINT1 AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_4POINT1) +#define AV_CHANNEL_LAYOUT_2_2 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_2_2) +#define AV_CHANNEL_LAYOUT_QUAD AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_QUAD) +#define AV_CHANNEL_LAYOUT_5POINT0 AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_5POINT0) +#define AV_CHANNEL_LAYOUT_5POINT1 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_5POINT1) +#define AV_CHANNEL_LAYOUT_5POINT0_BACK AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_5POINT0_BACK) +#define AV_CHANNEL_LAYOUT_5POINT1_BACK AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_5POINT1_BACK) +#define AV_CHANNEL_LAYOUT_6POINT0 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_6POINT0) +#define AV_CHANNEL_LAYOUT_6POINT0_FRONT AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_6POINT0_FRONT) +#define AV_CHANNEL_LAYOUT_3POINT1POINT2 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_3POINT1POINT2) +#define AV_CHANNEL_LAYOUT_HEXAGONAL AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_HEXAGONAL) +#define AV_CHANNEL_LAYOUT_6POINT1 AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1) +#define AV_CHANNEL_LAYOUT_6POINT1_BACK AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1_BACK) +#define AV_CHANNEL_LAYOUT_6POINT1_FRONT AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1_FRONT) +#define AV_CHANNEL_LAYOUT_7POINT0 AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_7POINT0) +#define AV_CHANNEL_LAYOUT_7POINT0_FRONT AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_7POINT0_FRONT) +#define AV_CHANNEL_LAYOUT_7POINT1 AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1) +#define AV_CHANNEL_LAYOUT_7POINT1_WIDE AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1_WIDE) +#define AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1_WIDE_BACK) +#define AV_CHANNEL_LAYOUT_5POINT1POINT2_BACK AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_5POINT1POINT2_BACK) +#define AV_CHANNEL_LAYOUT_OCTAGONAL AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_OCTAGONAL) +#define AV_CHANNEL_LAYOUT_CUBE AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_CUBE) +#define AV_CHANNEL_LAYOUT_5POINT1POINT4_BACK AV_CHANNEL_LAYOUT_MASK(10, AV_CH_LAYOUT_5POINT1POINT4_BACK) +#define AV_CHANNEL_LAYOUT_7POINT1POINT2 AV_CHANNEL_LAYOUT_MASK(10, AV_CH_LAYOUT_7POINT1POINT2) +#define AV_CHANNEL_LAYOUT_7POINT1POINT4_BACK AV_CHANNEL_LAYOUT_MASK(12, AV_CH_LAYOUT_7POINT1POINT4_BACK) +#define AV_CHANNEL_LAYOUT_HEXADECAGONAL AV_CHANNEL_LAYOUT_MASK(16, AV_CH_LAYOUT_HEXADECAGONAL) +#define AV_CHANNEL_LAYOUT_STEREO_DOWNMIX AV_CHANNEL_LAYOUT_MASK(2, AV_CH_LAYOUT_STEREO_DOWNMIX) +#define AV_CHANNEL_LAYOUT_22POINT2 AV_CHANNEL_LAYOUT_MASK(24, AV_CH_LAYOUT_22POINT2) + +#define AV_CHANNEL_LAYOUT_7POINT1_TOP_BACK AV_CHANNEL_LAYOUT_5POINT1POINT2_BACK + +#define AV_CHANNEL_LAYOUT_AMBISONIC_FIRST_ORDER \ + { /* .order */ AV_CHANNEL_ORDER_AMBISONIC, \ + /* .nb_channels */ 4, \ + /* .u.mask */ { 0 }, \ + /* .opaque */ NULL } +/** @} */ + +struct AVBPrint; + +#if FF_API_OLD_CHANNEL_LAYOUT +/** + * @name Deprecated Functions + * @{ + */ + +/** + * Return a channel layout id that matches name, or 0 if no match is found. + * + * name can be one or several of the following notations, + * separated by '+' or '|': + * - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0, + * 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix); + * - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC, + * SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR); + * - a number of channels, in decimal, followed by 'c', yielding + * the default channel layout for that number of channels (@see + * av_get_default_channel_layout); + * - a channel layout mask, in hexadecimal starting with "0x" (see the + * AV_CH_* macros). + * + * Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7" + * + * @deprecated use av_channel_layout_from_string() + */ +attribute_deprecated +uint64_t av_get_channel_layout(const char *name); + +/** + * Return a channel layout and the number of channels based on the specified name. + * + * This function is similar to (@see av_get_channel_layout), but can also parse + * unknown channel layout specifications. + * + * @param[in] name channel layout specification string + * @param[out] channel_layout parsed channel layout (0 if unknown) + * @param[out] nb_channels number of channels + * + * @return 0 on success, AVERROR(EINVAL) if the parsing fails. + * @deprecated use av_channel_layout_from_string() + */ +attribute_deprecated +int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels); + +/** + * Return a description of a channel layout. + * If nb_channels is <= 0, it is guessed from the channel_layout. + * + * @param buf put here the string containing the channel layout + * @param buf_size size in bytes of the buffer + * @param nb_channels number of channels + * @param channel_layout channel layout bitset + * @deprecated use av_channel_layout_describe() + */ +attribute_deprecated +void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout); + +/** + * Append a description of a channel layout to a bprint buffer. + * @deprecated use av_channel_layout_describe() + */ +attribute_deprecated +void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout); + +/** + * Return the number of channels in the channel layout. + * @deprecated use AVChannelLayout.nb_channels + */ +attribute_deprecated +int av_get_channel_layout_nb_channels(uint64_t channel_layout); + +/** + * Return default channel layout for a given number of channels. + * + * @deprecated use av_channel_layout_default() + */ +attribute_deprecated +int64_t av_get_default_channel_layout(int nb_channels); + +/** + * Get the index of a channel in channel_layout. + * + * @param channel_layout channel layout bitset + * @param channel a channel layout describing exactly one channel which must be + * present in channel_layout. + * + * @return index of channel in channel_layout on success, a negative AVERROR + * on error. + * + * @deprecated use av_channel_layout_index_from_channel() + */ +attribute_deprecated +int av_get_channel_layout_channel_index(uint64_t channel_layout, + uint64_t channel); + +/** + * Get the channel with the given index in channel_layout. + * @deprecated use av_channel_layout_channel_from_index() + */ +attribute_deprecated +uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index); + +/** + * Get the name of a given channel. + * + * @return channel name on success, NULL on error. + * + * @deprecated use av_channel_name() + */ +attribute_deprecated +const char *av_get_channel_name(uint64_t channel); + +/** + * Get the description of a given channel. + * + * @param channel a channel layout with a single channel + * @return channel description on success, NULL on error + * @deprecated use av_channel_description() + */ +attribute_deprecated +const char *av_get_channel_description(uint64_t channel); + +/** + * Get the value and name of a standard channel layout. + * + * @param[in] index index in an internal list, starting at 0 + * @param[out] layout channel layout mask + * @param[out] name name of the layout + * @return 0 if the layout exists, + * <0 if index is beyond the limits + * @deprecated use av_channel_layout_standard() + */ +attribute_deprecated +int av_get_standard_channel_layout(unsigned index, uint64_t *layout, + const char **name); +/** + * @} + */ +#endif + +/** + * Get a human readable string in an abbreviated form describing a given channel. + * This is the inverse function of @ref av_channel_from_string(). + * + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @param channel the AVChannel whose name to get + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel); + +/** + * bprint variant of av_channel_name(). + * + * @note the string will be appended to the bprint buffer. + */ +void av_channel_name_bprint(struct AVBPrint *bp, enum AVChannel channel_id); + +/** + * Get a human readable string describing a given channel. + * + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @param channel the AVChannel whose description to get + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel); + +/** + * bprint variant of av_channel_description(). + * + * @note the string will be appended to the bprint buffer. + */ +void av_channel_description_bprint(struct AVBPrint *bp, enum AVChannel channel_id); + +/** + * This is the inverse function of @ref av_channel_name(). + * + * @return the channel with the given name + * AV_CHAN_NONE when name does not identify a known channel + */ +enum AVChannel av_channel_from_string(const char *name); + +/** + * Initialize a native channel layout from a bitmask indicating which channels + * are present. + * + * @param channel_layout the layout structure to be initialized + * @param mask bitmask describing the channel layout + * + * @return 0 on success + * AVERROR(EINVAL) for invalid mask values + */ +int av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask); + +/** + * Initialize a channel layout from a given string description. + * The input string can be represented by: + * - the formal channel layout name (returned by av_channel_layout_describe()) + * - single or multiple channel names (returned by av_channel_name(), eg. "FL", + * or concatenated with "+", each optionally containing a custom name after + * a "@", eg. "FL@Left+FR@Right+LFE") + * - a decimal or hexadecimal value of a native channel layout (eg. "4" or "0x4") + * - the number of channels with default layout (eg. "4c") + * - the number of unordered channels (eg. "4C" or "4 channels") + * - the ambisonic order followed by optional non-diegetic channels (eg. + * "ambisonic 2+stereo") + * + * @param channel_layout input channel layout + * @param str string describing the channel layout + * @return 0 channel layout was detected, AVERROR_INVALIDATATA otherwise + */ +int av_channel_layout_from_string(AVChannelLayout *channel_layout, + const char *str); + +/** + * Get the default channel layout for a given number of channels. + * + * @param ch_layout the layout structure to be initialized + * @param nb_channels number of channels + */ +void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels); + +/** + * Iterate over all standard channel layouts. + * + * @param opaque a pointer where libavutil will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the standard channel layout or NULL when the iteration is + * finished + */ +const AVChannelLayout *av_channel_layout_standard(void **opaque); + +/** + * Free any allocated data in the channel layout and reset the channel + * count to 0. + * + * @param channel_layout the layout structure to be uninitialized + */ +void av_channel_layout_uninit(AVChannelLayout *channel_layout); + +/** + * Make a copy of a channel layout. This differs from just assigning src to dst + * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM. + * + * @note the destination channel_layout will be always uninitialized before copy. + * + * @param dst destination channel layout + * @param src source channel layout + * @return 0 on success, a negative AVERROR on error. + */ +int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src); + +/** + * Get a human-readable string describing the channel layout properties. + * The string will be in the same format that is accepted by + * @ref av_channel_layout_from_string(), allowing to rebuild the same + * channel layout, except for opaque pointers. + * + * @param channel_layout channel layout to be described + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_layout_describe(const AVChannelLayout *channel_layout, + char *buf, size_t buf_size); + +/** + * bprint variant of av_channel_layout_describe(). + * + * @note the string will be appended to the bprint buffer. + * @return 0 on success, or a negative AVERROR value on failure. + */ +int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout, + struct AVBPrint *bp); + +/** + * Get the channel with the given index in a channel layout. + * + * @param channel_layout input channel layout + * @param idx index of the channel + * @return channel with the index idx in channel_layout on success or + * AV_CHAN_NONE on failure (if idx is not valid or the channel order is + * unspecified) + */ +enum AVChannel +av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx); + +/** + * Get the index of a given channel in a channel layout. In case multiple + * channels are found, only the first match will be returned. + * + * @param channel_layout input channel layout + * @param channel the channel whose index to obtain + * @return index of channel in channel_layout on success or a negative number if + * channel is not present in channel_layout. + */ +int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, + enum AVChannel channel); + +/** + * Get the index in a channel layout of a channel described by the given string. + * In case multiple channels are found, only the first match will be returned. + * + * This function accepts channel names in the same format as + * @ref av_channel_from_string(). + * + * @param channel_layout input channel layout + * @param name string describing the channel whose index to obtain + * @return a channel index described by the given string, or a negative AVERROR + * value. + */ +int av_channel_layout_index_from_string(const AVChannelLayout *channel_layout, + const char *name); + +/** + * Get a channel described by the given string. + * + * This function accepts channel names in the same format as + * @ref av_channel_from_string(). + * + * @param channel_layout input channel layout + * @param name string describing the channel to obtain + * @return a channel described by the given string in channel_layout on success + * or AV_CHAN_NONE on failure (if the string is not valid or the channel + * order is unspecified) + */ +enum AVChannel +av_channel_layout_channel_from_string(const AVChannelLayout *channel_layout, + const char *name); + +/** + * Find out what channels from a given set are present in a channel layout, + * without regard for their positions. + * + * @param channel_layout input channel layout + * @param mask a combination of AV_CH_* representing a set of channels + * @return a bitfield representing all the channels from mask that are present + * in channel_layout + */ +uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout, + uint64_t mask); + +/** + * Check whether a channel layout is valid, i.e. can possibly describe audio + * data. + * + * @param channel_layout input channel layout + * @return 1 if channel_layout is valid, 0 otherwise. + */ +int av_channel_layout_check(const AVChannelLayout *channel_layout); + +/** + * Check whether two channel layouts are semantically the same, i.e. the same + * channels are present on the same positions in both. + * + * If one of the channel layouts is AV_CHANNEL_ORDER_UNSPEC, while the other is + * not, they are considered to be unequal. If both are AV_CHANNEL_ORDER_UNSPEC, + * they are considered equal iff the channel counts are the same in both. + * + * @param chl input channel layout + * @param chl1 input channel layout + * @return 0 if chl and chl1 are equal, 1 if they are not equal. A negative + * AVERROR code if one or both are invalid. + */ +int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1); + +/** + * @} + */ + +#endif /* AVUTIL_CHANNEL_LAYOUT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/common.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/common.h new file mode 100644 index 0000000000000..de2140a678670 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/common.h @@ -0,0 +1,579 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * common internal and external API header + */ + +#ifndef AVUTIL_COMMON_H +#define AVUTIL_COMMON_H + +#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) && !defined(UINT64_C) +#error missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "error.h" +#include "macros.h" + +//rounded division & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>=0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +/* Fast a/(1<=0 and b>=0 */ +#define AV_CEIL_RSHIFT(a,b) (!av_builtin_constant_p(b) ? -((-(a)) >> (b)) \ + : ((a) + (1<<(b)) - 1) >> (b)) +/* Backwards compat. */ +#define FF_CEIL_RSHIFT AV_CEIL_RSHIFT + +#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b)) +#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b)) + +/** + * Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they + * are not representable as absolute values of their type. This is the same + * as with *abs() + * @see FFNABS() + */ +#define FFABS(a) ((a) >= 0 ? (a) : (-(a))) +#define FFSIGN(a) ((a) > 0 ? 1 : -1) + +/** + * Negative Absolute value. + * this works for all integers of all types. + * As with many macros, this evaluates its argument twice, it thus must not have + * a sideeffect, that is FFNABS(x++) has undefined behavior. + */ +#define FFNABS(a) ((a) <= 0 ? (a) : (-(a))) + +/** + * Unsigned Absolute value. + * This takes the absolute value of a signed int and returns it as a unsigned. + * This also works with INT_MIN which would otherwise not be representable + * As with many macros, this evaluates its argument twice. + */ +#define FFABSU(a) ((a) <= 0 ? -(unsigned)(a) : (unsigned)(a)) +#define FFABS64U(a) ((a) <= 0 ? -(uint64_t)(a) : (uint64_t)(a)) + +/* misc math functions */ + +#ifdef HAVE_AV_CONFIG_H +# include "config.h" +# include "intmath.h" +#endif + +#ifndef av_ceil_log2 +# define av_ceil_log2 av_ceil_log2_c +#endif +#ifndef av_clip +# define av_clip av_clip_c +#endif +#ifndef av_clip64 +# define av_clip64 av_clip64_c +#endif +#ifndef av_clip_uint8 +# define av_clip_uint8 av_clip_uint8_c +#endif +#ifndef av_clip_int8 +# define av_clip_int8 av_clip_int8_c +#endif +#ifndef av_clip_uint16 +# define av_clip_uint16 av_clip_uint16_c +#endif +#ifndef av_clip_int16 +# define av_clip_int16 av_clip_int16_c +#endif +#ifndef av_clipl_int32 +# define av_clipl_int32 av_clipl_int32_c +#endif +#ifndef av_clip_intp2 +# define av_clip_intp2 av_clip_intp2_c +#endif +#ifndef av_clip_uintp2 +# define av_clip_uintp2 av_clip_uintp2_c +#endif +#ifndef av_mod_uintp2 +# define av_mod_uintp2 av_mod_uintp2_c +#endif +#ifndef av_sat_add32 +# define av_sat_add32 av_sat_add32_c +#endif +#ifndef av_sat_dadd32 +# define av_sat_dadd32 av_sat_dadd32_c +#endif +#ifndef av_sat_sub32 +# define av_sat_sub32 av_sat_sub32_c +#endif +#ifndef av_sat_dsub32 +# define av_sat_dsub32 av_sat_dsub32_c +#endif +#ifndef av_sat_add64 +# define av_sat_add64 av_sat_add64_c +#endif +#ifndef av_sat_sub64 +# define av_sat_sub64 av_sat_sub64_c +#endif +#ifndef av_clipf +# define av_clipf av_clipf_c +#endif +#ifndef av_clipd +# define av_clipd av_clipd_c +#endif +#ifndef av_popcount +# define av_popcount av_popcount_c +#endif +#ifndef av_popcount64 +# define av_popcount64 av_popcount64_c +#endif +#ifndef av_parity +# define av_parity av_parity_c +#endif + +#ifndef av_log2 +av_const int av_log2(unsigned v); +#endif + +#ifndef av_log2_16bit +av_const int av_log2_16bit(unsigned v); +#endif + +/** + * Clip a signed integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int av_clip_c(int a, int amin, int amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed 64bit integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, int64_t amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed integer value into the 0-255 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint8_t av_clip_uint8_c(int a) +{ + if (a&(~0xFF)) return (~a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -128,127 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int8_t av_clip_int8_c(int a) +{ + if ((a+0x80U) & ~0xFF) return (a>>31) ^ 0x7F; + else return a; +} + +/** + * Clip a signed integer value into the 0-65535 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint16_t av_clip_uint16_c(int a) +{ + if (a&(~0xFFFF)) return (~a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -32768,32767 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int16_t av_clip_int16_c(int a) +{ + if ((a+0x8000U) & ~0xFFFF) return (a>>31) ^ 0x7FFF; + else return a; +} + +/** + * Clip a signed 64-bit integer value into the -2147483648,2147483647 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a) +{ + if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (int32_t)((a>>63) ^ 0x7FFFFFFF); + else return (int32_t)a; +} + +/** + * Clip a signed integer into the -(2^p),(2^p-1) range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const int av_clip_intp2_c(int a, int p) +{ + if (((unsigned)a + (1 << p)) & ~((2 << p) - 1)) + return (a >> 31) ^ ((1 << p) - 1); + else + return a; +} + +/** + * Clip a signed integer to an unsigned power of two range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p) +{ + if (a & ~((1<> 31 & ((1<= 0) + return INT64_MAX ^ (b >> 63); + return s; +#endif +} + +/** + * Subtract two signed 64-bit values with saturation. + * + * @param a one value + * @param b another value + * @return difference with signed saturation + */ +static av_always_inline int64_t av_sat_sub64_c(int64_t a, int64_t b) { +#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_sub_overflow) + int64_t tmp; + return !__builtin_sub_overflow(a, b, &tmp) ? tmp : (tmp < 0 ? INT64_MAX : INT64_MIN); +#else + if (b <= 0 && a >= INT64_MAX + b) + return INT64_MAX; + if (b >= 0 && a <= INT64_MIN + b) + return INT64_MIN; + return a - b; +#endif +} + +/** + * Clip a float value into the amin-amax range. + * If a is nan or -inf amin will be returned. + * If a is +inf amax will be returned. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const float av_clipf_c(float a, float amin, float amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + return FFMIN(FFMAX(a, amin), amax); +} + +/** + * Clip a double value into the amin-amax range. + * If a is nan or -inf amin will be returned. + * If a is +inf amax will be returned. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const double av_clipd_c(double a, double amin, double amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + return FFMIN(FFMAX(a, amin), amax); +} + +/** Compute ceil(log2(x)). + * @param x value used to compute ceil(log2(x)) + * @return computed ceiling of log2(x) + */ +static av_always_inline av_const int av_ceil_log2_c(int x) +{ + return av_log2((x - 1U) << 1); +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount_c(uint32_t x) +{ + x -= (x >> 1) & 0x55555555; + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x += x >> 8; + return (x + (x >> 16)) & 0x3F; +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount64_c(uint64_t x) +{ + return av_popcount((uint32_t)x) + av_popcount((uint32_t)(x >> 32)); +} + +static av_always_inline av_const int av_parity_c(uint32_t v) +{ + return av_popcount(v) & 1; +} + +/** + * Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_BYTE Expression reading one byte from the input. + * Evaluated up to 7 times (4 for the currently + * assigned Unicode range). With a memory buffer + * input, this could be *ptr++, or if you want to make sure + * that *ptr stops at the end of a NULL terminated string then + * *ptr ? *ptr++ : 0 + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + * + * @warning ERROR should not contain a loop control statement which + * could interact with the internal while loop, and should force an + * exit from the macro code (e.g. through a goto or a return) in order + * to prevent undefined results. + */ +#define GET_UTF8(val, GET_BYTE, ERROR)\ + val= (GET_BYTE);\ + {\ + uint32_t top = (val & 128) >> 1;\ + if ((val & 0xc0) == 0x80 || val >= 0xFE)\ + {ERROR}\ + while (val & top) {\ + unsigned int tmp = (GET_BYTE) - 128;\ + if(tmp>>6)\ + {ERROR}\ + val= (val<<6) + tmp;\ + top <<= 5;\ + }\ + val &= (top << 1) - 1;\ + } + +/** + * Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_16BIT Expression returning two bytes of UTF-16 data converted + * to native byte order. Evaluated one or two times. + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + */ +#define GET_UTF16(val, GET_16BIT, ERROR)\ + val = (GET_16BIT);\ + {\ + unsigned int hi = val - 0xD800;\ + if (hi < 0x800) {\ + val = (GET_16BIT) - 0xDC00;\ + if (val > 0x3FFU || hi > 0x3FFU)\ + {ERROR}\ + val += (hi<<10) + 0x10000;\ + }\ + }\ + +/** + * @def PUT_UTF8(val, tmp, PUT_BYTE) + * Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-8. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint8_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_BYTE. + * @param PUT_BYTE writes the converted UTF-8 bytes to any proper destination. + * It could be a function or a statement, and uses tmp as the input byte. + * For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be + * executed up to 4 times for values in the valid UTF-8 range and up to + * 7 times in the general case, depending on the length of the converted + * Unicode character. + */ +#define PUT_UTF8(val, tmp, PUT_BYTE)\ + {\ + int bytes, shift;\ + uint32_t in = val;\ + if (in < 0x80) {\ + tmp = in;\ + PUT_BYTE\ + } else {\ + bytes = (av_log2(in) + 4) / 5;\ + shift = (bytes - 1) * 6;\ + tmp = (256 - (256 >> bytes)) | (in >> shift);\ + PUT_BYTE\ + while (shift >= 6) {\ + shift -= 6;\ + tmp = 0x80 | ((in >> shift) & 0x3f);\ + PUT_BYTE\ + }\ + }\ + } + +/** + * @def PUT_UTF16(val, tmp, PUT_16BIT) + * Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-16. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint16_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_16BIT. + * @param PUT_16BIT writes the converted UTF-16 data to any proper destination + * in desired endianness. It could be a function or a statement, and uses tmp + * as the input byte. For example, PUT_BYTE could be "*output++ = tmp;" + * PUT_BYTE will be executed 1 or 2 times depending on input character. + */ +#define PUT_UTF16(val, tmp, PUT_16BIT)\ + {\ + uint32_t in = val;\ + if (in < 0x10000) {\ + tmp = in;\ + PUT_16BIT\ + } else {\ + tmp = 0xD800 | ((in - 0x10000) >> 10);\ + PUT_16BIT\ + tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\ + PUT_16BIT\ + }\ + }\ + + + +#include "mem.h" + +#ifdef HAVE_AV_CONFIG_H +# include "internal.h" +#endif /* HAVE_AV_CONFIG_H */ + +#endif /* AVUTIL_COMMON_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/dict.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/dict.h new file mode 100644 index 0000000000000..713c9e361af83 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/dict.h @@ -0,0 +1,241 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Public dictionary API. + * @deprecated + * AVDictionary is provided for compatibility with libav. It is both in + * implementation as well as API inefficient. It does not scale and is + * extremely slow with large dictionaries. + * It is recommended that new code uses our tree container from tree.c/h + * where applicable, which uses AVL trees to achieve O(log n) performance. + */ + +#ifndef AVUTIL_DICT_H +#define AVUTIL_DICT_H + +#include + +/** + * @addtogroup lavu_dict AVDictionary + * @ingroup lavu_data + * + * @brief Simple key:value store + * + * @{ + * Dictionaries are used for storing key-value pairs. + * + * - To **create an AVDictionary**, simply pass an address of a NULL + * pointer to av_dict_set(). NULL can be used as an empty dictionary + * wherever a pointer to an AVDictionary is required. + * - To **insert an entry**, use av_dict_set(). + * - Use av_dict_get() to **retrieve an entry**. + * - To **iterate over all entries**, use av_dict_iterate(). + * - In order to **free the dictionary and all its contents**, use av_dict_free(). + * + @code + AVDictionary *d = NULL; // "create" an empty dictionary + AVDictionaryEntry *t = NULL; + + av_dict_set(&d, "foo", "bar", 0); // add an entry + + char *k = av_strdup("key"); // if your strings are already allocated, + char *v = av_strdup("value"); // you can avoid copying them like this + av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); + + while ((t = av_dict_iterate(d, t))) { + <....> // iterate over all entries in d + } + av_dict_free(&d); + @endcode + */ + +/** + * @name AVDictionary Flags + * Flags that influence behavior of the matching of keys or insertion to the dictionary. + * @{ + */ +#define AV_DICT_MATCH_CASE 1 /**< Only get an entry with exact-case key match. Only relevant in av_dict_get(). */ +#define AV_DICT_IGNORE_SUFFIX 2 /**< Return first entry in a dictionary whose first part corresponds to the search key, + ignoring the suffix of the found key string. Only relevant in av_dict_get(). */ +#define AV_DICT_DONT_STRDUP_KEY 4 /**< Take ownership of a key that's been + allocated with av_malloc() or another memory allocation function. */ +#define AV_DICT_DONT_STRDUP_VAL 8 /**< Take ownership of a value that's been + allocated with av_malloc() or another memory allocation function. */ +#define AV_DICT_DONT_OVERWRITE 16 /**< Don't overwrite existing entries. */ +#define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no + delimiter is added, the strings are simply concatenated. */ +#define AV_DICT_MULTIKEY 64 /**< Allow to store several equal keys in the dictionary */ +/** + * @} + */ + +typedef struct AVDictionaryEntry { + char *key; + char *value; +} AVDictionaryEntry; + +typedef struct AVDictionary AVDictionary; + +/** + * Get a dictionary entry with matching key. + * + * The returned entry key or value must not be changed, or it will + * cause undefined behavior. + * + * @param prev Set to the previous matching element to find the next. + * If set to NULL the first matching element is returned. + * @param key Matching key + * @param flags A collection of AV_DICT_* flags controlling how the + * entry is retrieved + * + * @return Found entry or NULL in case no matching entry was found in the dictionary + */ +AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key, + const AVDictionaryEntry *prev, int flags); + +/** + * Iterate over a dictionary + * + * Iterates through all entries in the dictionary. + * + * @warning The returned AVDictionaryEntry key/value must not be changed. + * + * @warning As av_dict_set() invalidates all previous entries returned + * by this function, it must not be called while iterating over the dict. + * + * Typical usage: + * @code + * const AVDictionaryEntry *e = NULL; + * while ((e = av_dict_iterate(m, e))) { + * // ... + * } + * @endcode + * + * @param m The dictionary to iterate over + * @param prev Pointer to the previous AVDictionaryEntry, NULL initially + * + * @retval AVDictionaryEntry* The next element in the dictionary + * @retval NULL No more elements in the dictionary + */ +const AVDictionaryEntry *av_dict_iterate(const AVDictionary *m, + const AVDictionaryEntry *prev); + +/** + * Get number of entries in dictionary. + * + * @param m dictionary + * @return number of entries in dictionary + */ +int av_dict_count(const AVDictionary *m); + +/** + * Set the given entry in *pm, overwriting an existing entry. + * + * Note: If AV_DICT_DONT_STRDUP_KEY or AV_DICT_DONT_STRDUP_VAL is set, + * these arguments will be freed on error. + * + * @warning Adding a new entry to a dictionary invalidates all existing entries + * previously returned with av_dict_get() or av_dict_iterate(). + * + * @param pm Pointer to a pointer to a dictionary struct. If *pm is NULL + * a dictionary struct is allocated and put in *pm. + * @param key Entry key to add to *pm (will either be av_strduped or added as a new key depending on flags) + * @param value Entry value to add to *pm (will be av_strduped or added as a new key depending on flags). + * Passing a NULL value will cause an existing entry to be deleted. + * + * @return >= 0 on success otherwise an error code <0 + */ +int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags); + +/** + * Convenience wrapper for av_dict_set() that converts the value to a string + * and stores it. + * + * Note: If ::AV_DICT_DONT_STRDUP_KEY is set, key will be freed on error. + */ +int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags); + +/** + * Parse the key/value pairs list and add the parsed entries to a dictionary. + * + * In case of failure, all the successfully set entries are stored in + * *pm. You may need to manually free the created dictionary. + * + * @param key_val_sep A 0-terminated list of characters used to separate + * key from value + * @param pairs_sep A 0-terminated list of characters used to separate + * two pairs from each other + * @param flags Flags to use when adding to the dictionary. + * ::AV_DICT_DONT_STRDUP_KEY and ::AV_DICT_DONT_STRDUP_VAL + * are ignored since the key/value tokens will always + * be duplicated. + * + * @return 0 on success, negative AVERROR code on failure + */ +int av_dict_parse_string(AVDictionary **pm, const char *str, + const char *key_val_sep, const char *pairs_sep, + int flags); + +/** + * Copy entries from one AVDictionary struct into another. + * + * @note Metadata is read using the ::AV_DICT_IGNORE_SUFFIX flag + * + * @param dst Pointer to a pointer to a AVDictionary struct to copy into. If *dst is NULL, + * this function will allocate a struct for you and put it in *dst + * @param src Pointer to the source AVDictionary struct to copy items from. + * @param flags Flags to use when setting entries in *dst + * + * @return 0 on success, negative AVERROR code on failure. If dst was allocated + * by this function, callers should free the associated memory. + */ +int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags); + +/** + * Free all the memory allocated for an AVDictionary struct + * and all keys and values. + */ +void av_dict_free(AVDictionary **m); + +/** + * Get dictionary entries as a string. + * + * Create a string containing dictionary's entries. + * Such string may be passed back to av_dict_parse_string(). + * @note String is escaped with backslashes ('\'). + * + * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same. + * + * @param[in] m The dictionary + * @param[out] buffer Pointer to buffer that will be allocated with string containg entries. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep Character used to separate key from value + * @param[in] pairs_sep Character used to separate two pairs from each other + * + * @return >= 0 on success, negative on error + */ +int av_dict_get_string(const AVDictionary *m, char **buffer, + const char key_val_sep, const char pairs_sep); + +/** + * @} + */ + +#endif /* AVUTIL_DICT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/error.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/error.h new file mode 100644 index 0000000000000..0d3269aa6da13 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/error.h @@ -0,0 +1,128 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * error code definitions + */ + +#ifndef AVUTIL_ERROR_H +#define AVUTIL_ERROR_H + +#include +#include + +#include "macros.h" + +/** + * @addtogroup lavu_error + * + * @{ + */ + + +/* error handling */ +#if EDOM > 0 +#define AVERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions. +#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value. +#else +/* Some platforms have E* and errno already negated. */ +#define AVERROR(e) (e) +#define AVUNERROR(e) (e) +#endif + +#define FFERRTAG(a, b, c, d) (-(int)MKTAG(a, b, c, d)) + +#define AVERROR_BSF_NOT_FOUND FFERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found +#define AVERROR_BUG FFERRTAG( 'B','U','G','!') ///< Internal bug, also see AVERROR_BUG2 +#define AVERROR_BUFFER_TOO_SMALL FFERRTAG( 'B','U','F','S') ///< Buffer too small +#define AVERROR_DECODER_NOT_FOUND FFERRTAG(0xF8,'D','E','C') ///< Decoder not found +#define AVERROR_DEMUXER_NOT_FOUND FFERRTAG(0xF8,'D','E','M') ///< Demuxer not found +#define AVERROR_ENCODER_NOT_FOUND FFERRTAG(0xF8,'E','N','C') ///< Encoder not found +#define AVERROR_EOF FFERRTAG( 'E','O','F',' ') ///< End of file +#define AVERROR_EXIT FFERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted +#define AVERROR_EXTERNAL FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library +#define AVERROR_FILTER_NOT_FOUND FFERRTAG(0xF8,'F','I','L') ///< Filter not found +#define AVERROR_INVALIDDATA FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input +#define AVERROR_MUXER_NOT_FOUND FFERRTAG(0xF8,'M','U','X') ///< Muxer not found +#define AVERROR_OPTION_NOT_FOUND FFERRTAG(0xF8,'O','P','T') ///< Option not found +#define AVERROR_PATCHWELCOME FFERRTAG( 'P','A','W','E') ///< Not yet implemented in FFmpeg, patches welcome +#define AVERROR_PROTOCOL_NOT_FOUND FFERRTAG(0xF8,'P','R','O') ///< Protocol not found + +#define AVERROR_STREAM_NOT_FOUND FFERRTAG(0xF8,'S','T','R') ///< Stream not found +/** + * This is semantically identical to AVERROR_BUG + * it has been introduced in Libav after our AVERROR_BUG and with a modified value. + */ +#define AVERROR_BUG2 FFERRTAG( 'B','U','G',' ') +#define AVERROR_UNKNOWN FFERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library +#define AVERROR_EXPERIMENTAL (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it. +#define AVERROR_INPUT_CHANGED (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED) +#define AVERROR_OUTPUT_CHANGED (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED) +/* HTTP & RTSP errors */ +#define AVERROR_HTTP_BAD_REQUEST FFERRTAG(0xF8,'4','0','0') +#define AVERROR_HTTP_UNAUTHORIZED FFERRTAG(0xF8,'4','0','1') +#define AVERROR_HTTP_FORBIDDEN FFERRTAG(0xF8,'4','0','3') +#define AVERROR_HTTP_NOT_FOUND FFERRTAG(0xF8,'4','0','4') +#define AVERROR_HTTP_OTHER_4XX FFERRTAG(0xF8,'4','X','X') +#define AVERROR_HTTP_SERVER_ERROR FFERRTAG(0xF8,'5','X','X') + +#define AV_ERROR_MAX_STRING_SIZE 64 + +/** + * Put a description of the AVERROR code errnum in errbuf. + * In case of failure the global variable errno is set to indicate the + * error. Even in case of failure av_strerror() will print a generic + * error message indicating the errnum provided to errbuf. + * + * @param errnum error code to describe + * @param errbuf buffer to which description is written + * @param errbuf_size the size in bytes of errbuf + * @return 0 on success, a negative value if a description for errnum + * cannot be found + */ +int av_strerror(int errnum, char *errbuf, size_t errbuf_size); + +/** + * Fill the provided buffer with a string containing an error string + * corresponding to the AVERROR code errnum. + * + * @param errbuf a buffer + * @param errbuf_size size in bytes of errbuf + * @param errnum error code to describe + * @return the buffer in input, filled with the error description + * @see av_strerror() + */ +static inline char *av_make_error_string(char *errbuf, size_t errbuf_size, int errnum) +{ + av_strerror(errnum, errbuf, errbuf_size); + return errbuf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_err2str(errnum) \ + av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum) + +/** + * @} + */ + +#endif /* AVUTIL_ERROR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/frame.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/frame.h new file mode 100644 index 0000000000000..c0c1b23db7ced --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/frame.h @@ -0,0 +1,1056 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_frame + * reference-counted frame API + */ + +#ifndef AVUTIL_FRAME_H +#define AVUTIL_FRAME_H + +#include +#include + +#include "avutil.h" +#include "buffer.h" +#include "channel_layout.h" +#include "dict.h" +#include "rational.h" +#include "samplefmt.h" +#include "pixfmt.h" +#include "version.h" + + +/** + * @defgroup lavu_frame AVFrame + * @ingroup lavu_data + * + * @{ + * AVFrame is an abstraction for reference-counted raw multimedia data. + */ + +enum AVFrameSideDataType { + /** + * The data is the AVPanScan struct defined in libavcodec. + */ + AV_FRAME_DATA_PANSCAN, + /** + * ATSC A53 Part 4 Closed Captions. + * A53 CC bitstream is stored as uint8_t in AVFrameSideData.data. + * The number of bytes of CC data is AVFrameSideData.size. + */ + AV_FRAME_DATA_A53_CC, + /** + * Stereoscopic 3d metadata. + * The data is the AVStereo3D struct defined in libavutil/stereo3d.h. + */ + AV_FRAME_DATA_STEREO3D, + /** + * The data is the AVMatrixEncoding enum defined in libavutil/channel_layout.h. + */ + AV_FRAME_DATA_MATRIXENCODING, + /** + * Metadata relevant to a downmix procedure. + * The data is the AVDownmixInfo struct defined in libavutil/downmix_info.h. + */ + AV_FRAME_DATA_DOWNMIX_INFO, + /** + * ReplayGain information in the form of the AVReplayGain struct. + */ + AV_FRAME_DATA_REPLAYGAIN, + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the frame for correct + * presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_FRAME_DATA_DISPLAYMATRIX, + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_FRAME_DATA_AFD, + /** + * Motion vectors exported by some codecs (on demand through the export_mvs + * flag set in the libavcodec AVCodecContext flags2 option). + * The data is the AVMotionVector struct defined in + * libavutil/motion_vector.h. + */ + AV_FRAME_DATA_MOTION_VECTORS, + /** + * Recommmends skipping the specified number of samples. This is exported + * only if the "skip_manual" AVOption is set in libavcodec. + * This has the same format as AV_PKT_DATA_SKIP_SAMPLES. + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_FRAME_DATA_SKIP_SAMPLES, + /** + * This side data must be associated with an audio frame and corresponds to + * enum AVAudioServiceType defined in avcodec.h. + */ + AV_FRAME_DATA_AUDIO_SERVICE_TYPE, + /** + * Mastering display metadata associated with a video frame. The payload is + * an AVMasteringDisplayMetadata type and contains information about the + * mastering display color volume. + */ + AV_FRAME_DATA_MASTERING_DISPLAY_METADATA, + /** + * The GOP timecode in 25 bit timecode format. Data format is 64-bit integer. + * This is set on the first frame of a GOP that has a temporal reference of 0. + */ + AV_FRAME_DATA_GOP_TIMECODE, + + /** + * The data represents the AVSphericalMapping structure defined in + * libavutil/spherical.h. + */ + AV_FRAME_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This payload contains data in + * the form of the AVContentLightMetadata struct. + */ + AV_FRAME_DATA_CONTENT_LIGHT_LEVEL, + + /** + * The data contains an ICC profile as an opaque octet buffer following the + * format described by ISO 15076-1 with an optional name defined in the + * metadata key entry "name". + */ + AV_FRAME_DATA_ICC_PROFILE, + + /** + * Timecode which conforms to SMPTE ST 12-1. The data is an array of 4 uint32_t + * where the first uint32_t describes how many (1-3) of the other timecodes are used. + * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.h. + */ + AV_FRAME_DATA_S12M_TIMECODE, + + /** + * HDR dynamic metadata associated with a video frame. The payload is + * an AVDynamicHDRPlus type and contains information for color + * volume transform - application 4 of SMPTE 2094-40:2016 standard. + */ + AV_FRAME_DATA_DYNAMIC_HDR_PLUS, + + /** + * Regions Of Interest, the data is an array of AVRegionOfInterest type, the number of + * array element is implied by AVFrameSideData.size / AVRegionOfInterest.self_size. + */ + AV_FRAME_DATA_REGIONS_OF_INTEREST, + + /** + * Encoding parameters for a video frame, as described by AVVideoEncParams. + */ + AV_FRAME_DATA_VIDEO_ENC_PARAMS, + + /** + * User data unregistered metadata associated with a video frame. + * This is the H.26[45] UDU SEI message, and shouldn't be used for any other purpose + * The data is stored as uint8_t in AVFrameSideData.data which is 16 bytes of + * uuid_iso_iec_11578 followed by AVFrameSideData.size - 16 bytes of user_data_payload_byte. + */ + AV_FRAME_DATA_SEI_UNREGISTERED, + + /** + * Film grain parameters for a frame, described by AVFilmGrainParams. + * Must be present for every frame which should have film grain applied. + */ + AV_FRAME_DATA_FILM_GRAIN_PARAMS, + + /** + * Bounding boxes for object detection and classification, + * as described by AVDetectionBBoxHeader. + */ + AV_FRAME_DATA_DETECTION_BBOXES, + + /** + * Dolby Vision RPU raw data, suitable for passing to x265 + * or other libraries. Array of uint8_t, with NAL emulation + * bytes intact. + */ + AV_FRAME_DATA_DOVI_RPU_BUFFER, + + /** + * Parsed Dolby Vision metadata, suitable for passing to a software + * implementation. The payload is the AVDOVIMetadata struct defined in + * libavutil/dovi_meta.h. + */ + AV_FRAME_DATA_DOVI_METADATA, + + /** + * HDR Vivid dynamic metadata associated with a video frame. The payload is + * an AVDynamicHDRVivid type and contains information for color + * volume transform - CUVA 005.1-2021. + */ + AV_FRAME_DATA_DYNAMIC_HDR_VIVID, + + /** + * Ambient viewing environment metadata, as defined by H.274. + */ + AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT, + + /** + * Provide encoder-specific hinting information about changed/unchanged + * portions of a frame. It can be used to pass information about which + * macroblocks can be skipped because they didn't change from the + * corresponding ones in the previous frame. This could be useful for + * applications which know this information in advance to speed up + * encoding. + */ + AV_FRAME_DATA_VIDEO_HINT, +}; + +enum AVActiveFormatDescription { + AV_AFD_SAME = 8, + AV_AFD_4_3 = 9, + AV_AFD_16_9 = 10, + AV_AFD_14_9 = 11, + AV_AFD_4_3_SP_14_9 = 13, + AV_AFD_16_9_SP_14_9 = 14, + AV_AFD_SP_4_3 = 15, +}; + + +/** + * Structure to hold side data for an AVFrame. + * + * sizeof(AVFrameSideData) is not a part of the public ABI, so new fields may be added + * to the end with a minor bump. + */ +typedef struct AVFrameSideData { + enum AVFrameSideDataType type; + uint8_t *data; + size_t size; + AVDictionary *metadata; + AVBufferRef *buf; +} AVFrameSideData; + +/** + * Structure describing a single Region Of Interest. + * + * When multiple regions are defined in a single side-data block, they + * should be ordered from most to least important - some encoders are only + * capable of supporting a limited number of distinct regions, so will have + * to truncate the list. + * + * When overlapping regions are defined, the first region containing a given + * area of the frame applies. + */ +typedef struct AVRegionOfInterest { + /** + * Must be set to the size of this data structure (that is, + * sizeof(AVRegionOfInterest)). + */ + uint32_t self_size; + /** + * Distance in pixels from the top edge of the frame to the top and + * bottom edges and from the left edge of the frame to the left and + * right edges of the rectangle defining this region of interest. + * + * The constraints on a region are encoder dependent, so the region + * actually affected may be slightly larger for alignment or other + * reasons. + */ + int top; + int bottom; + int left; + int right; + /** + * Quantisation offset. + * + * Must be in the range -1 to +1. A value of zero indicates no quality + * change. A negative value asks for better quality (less quantisation), + * while a positive value asks for worse quality (greater quantisation). + * + * The range is calibrated so that the extreme values indicate the + * largest possible offset - if the rest of the frame is encoded with the + * worst possible quality, an offset of -1 indicates that this region + * should be encoded with the best possible quality anyway. Intermediate + * values are then interpolated in some codec-dependent way. + * + * For example, in 10-bit H.264 the quantisation parameter varies between + * -12 and 51. A typical qoffset value of -1/10 therefore indicates that + * this region should be encoded with a QP around one-tenth of the full + * range better than the rest of the frame. So, if most of the frame + * were to be encoded with a QP of around 30, this region would get a QP + * of around 24 (an offset of approximately -1/10 * (51 - -12) = -6.3). + * An extreme value of -1 would indicate that this region should be + * encoded with the best possible quality regardless of the treatment of + * the rest of the frame - that is, should be encoded at a QP of -12. + */ + AVRational qoffset; +} AVRegionOfInterest; + +/** + * This structure describes decoded (raw) audio or video data. + * + * AVFrame must be allocated using av_frame_alloc(). Note that this only + * allocates the AVFrame itself, the buffers for the data must be managed + * through other means (see below). + * AVFrame must be freed with av_frame_free(). + * + * AVFrame is typically allocated once and then reused multiple times to hold + * different data (e.g. a single AVFrame to hold frames received from a + * decoder). In such a case, av_frame_unref() will free any references held by + * the frame and reset it to its original clean state before it + * is reused again. + * + * The data described by an AVFrame is usually reference counted through the + * AVBuffer API. The underlying buffer references are stored in AVFrame.buf / + * AVFrame.extended_buf. An AVFrame is considered to be reference counted if at + * least one reference is set, i.e. if AVFrame.buf[0] != NULL. In such a case, + * every single data plane must be contained in one of the buffers in + * AVFrame.buf or AVFrame.extended_buf. + * There may be a single buffer for all the data, or one separate buffer for + * each plane, or anything in between. + * + * sizeof(AVFrame) is not a part of the public ABI, so new fields may be added + * to the end with a minor bump. + * + * Fields can be accessed through AVOptions, the name string used, matches the + * C structure field name for fields accessible through AVOptions. The AVClass + * for AVFrame can be obtained from avcodec_get_frame_class() + */ +typedef struct AVFrame { +#define AV_NUM_DATA_POINTERS 8 + /** + * pointer to the picture/channel planes. + * This might be different from the first allocated byte. For video, + * it could even point to the end of the image data. + * + * All pointers in data and extended_data must point into one of the + * AVBufferRef in buf or extended_buf. + * + * Some decoders access areas outside 0,0 - width,height, please + * see avcodec_align_dimensions2(). Some filters and swscale can read + * up to 16 bytes beyond the planes, if these filters are to be used, + * then 16 extra bytes must be allocated. + * + * NOTE: Pointers not needed by the format MUST be set to NULL. + * + * @attention In case of video, the data[] pointers can point to the + * end of image data in order to reverse line order, when used in + * combination with negative values in the linesize[] array. + */ + uint8_t *data[AV_NUM_DATA_POINTERS]; + + /** + * For video, a positive or negative value, which is typically indicating + * the size in bytes of each picture line, but it can also be: + * - the negative byte size of lines for vertical flipping + * (with data[n] pointing to the end of the data + * - a positive or negative multiple of the byte size as for accessing + * even and odd fields of a frame (possibly flipped) + * + * For audio, only linesize[0] may be set. For planar audio, each channel + * plane must be the same size. + * + * For video the linesizes should be multiples of the CPUs alignment + * preference, this is 16 or 32 for modern desktop CPUs. + * Some code requires such alignment other code can be slower without + * correct alignment, for yet other it makes no difference. + * + * @note The linesize may be larger than the size of usable data -- there + * may be extra padding present for performance reasons. + * + * @attention In case of video, line size values can be negative to achieve + * a vertically inverted iteration over image lines. + */ + int linesize[AV_NUM_DATA_POINTERS]; + + /** + * pointers to the data planes/channels. + * + * For video, this should simply point to data[]. + * + * For planar audio, each channel has a separate data pointer, and + * linesize[0] contains the size of each channel buffer. + * For packed audio, there is just one data pointer, and linesize[0] + * contains the total size of the buffer for all channels. + * + * Note: Both data and extended_data should always be set in a valid frame, + * but for planar audio with more channels that can fit in data, + * extended_data must be used in order to access all channels. + */ + uint8_t **extended_data; + + /** + * @name Video dimensions + * Video frames only. The coded dimensions (in pixels) of the video frame, + * i.e. the size of the rectangle that contains some well-defined values. + * + * @note The part of the frame intended for display/presentation is further + * restricted by the @ref cropping "Cropping rectangle". + * @{ + */ + int width, height; + /** + * @} + */ + + /** + * number of audio samples (per channel) described by this frame + */ + int nb_samples; + + /** + * format of the frame, -1 if unknown or unset + * Values correspond to enum AVPixelFormat for video frames, + * enum AVSampleFormat for audio) + */ + int format; + +#if FF_API_FRAME_KEY + /** + * 1 -> keyframe, 0-> not + * + * @deprecated Use AV_FRAME_FLAG_KEY instead + */ + attribute_deprecated + int key_frame; +#endif + + /** + * Picture type of the frame. + */ + enum AVPictureType pict_type; + + /** + * Sample aspect ratio for the video frame, 0/1 if unknown/unspecified. + */ + AVRational sample_aspect_ratio; + + /** + * Presentation timestamp in time_base units (time when frame should be shown to user). + */ + int64_t pts; + + /** + * DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used) + * This is also the Presentation time of this AVFrame calculated from + * only AVPacket.dts values without pts values. + */ + int64_t pkt_dts; + + /** + * Time base for the timestamps in this frame. + * In the future, this field may be set on frames output by decoders or + * filters, but its value will be by default ignored on input to encoders + * or filters. + */ + AVRational time_base; + +#if FF_API_FRAME_PICTURE_NUMBER + /** + * picture number in bitstream order + */ + attribute_deprecated + int coded_picture_number; + /** + * picture number in display order + */ + attribute_deprecated + int display_picture_number; +#endif + + /** + * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) + */ + int quality; + + /** + * Frame owner's private data. + * + * This field may be set by the code that allocates/owns the frame data. + * It is then not touched by any library functions, except: + * - it is copied to other references by av_frame_copy_props() (and hence by + * av_frame_ref()); + * - it is set to NULL when the frame is cleared by av_frame_unref() + * - on the caller's explicit request. E.g. libavcodec encoders/decoders + * will copy this field to/from @ref AVPacket "AVPackets" if the caller sets + * @ref AV_CODEC_FLAG_COPY_OPAQUE. + * + * @see opaque_ref the reference-counted analogue + */ + void *opaque; + + /** + * Number of fields in this frame which should be repeated, i.e. the total + * duration of this frame should be repeat_pict + 2 normal field durations. + * + * For interlaced frames this field may be set to 1, which signals that this + * frame should be presented as 3 fields: beginning with the first field (as + * determined by AV_FRAME_FLAG_TOP_FIELD_FIRST being set or not), followed + * by the second field, and then the first field again. + * + * For progressive frames this field may be set to a multiple of 2, which + * signals that this frame's duration should be (repeat_pict + 2) / 2 + * normal frame durations. + * + * @note This field is computed from MPEG2 repeat_first_field flag and its + * associated flags, H.264 pic_struct from picture timing SEI, and + * their analogues in other codecs. Typically it should only be used when + * higher-layer timing information is not available. + */ + int repeat_pict; + +#if FF_API_INTERLACED_FRAME + /** + * The content of the picture is interlaced. + * + * @deprecated Use AV_FRAME_FLAG_INTERLACED instead + */ + attribute_deprecated + int interlaced_frame; + + /** + * If the content is interlaced, is top field displayed first. + * + * @deprecated Use AV_FRAME_FLAG_TOP_FIELD_FIRST instead + */ + attribute_deprecated + int top_field_first; +#endif + +#if FF_API_PALETTE_HAS_CHANGED + /** + * Tell user application that palette has changed from previous frame. + */ + attribute_deprecated + int palette_has_changed; +#endif + +#if FF_API_REORDERED_OPAQUE + /** + * reordered opaque 64 bits (generally an integer or a double precision float + * PTS but can be anything). + * The user sets AVCodecContext.reordered_opaque to represent the input at + * that time, + * the decoder reorders values as needed and sets AVFrame.reordered_opaque + * to exactly one of the values provided by the user through AVCodecContext.reordered_opaque + * + * @deprecated Use AV_CODEC_FLAG_COPY_OPAQUE instead + */ + attribute_deprecated + int64_t reordered_opaque; +#endif + + /** + * Sample rate of the audio data. + */ + int sample_rate; + +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * Channel layout of the audio data. + * @deprecated use ch_layout instead + */ + attribute_deprecated + uint64_t channel_layout; +#endif + + /** + * AVBuffer references backing the data for this frame. All the pointers in + * data and extended_data must point inside one of the buffers in buf or + * extended_buf. This array must be filled contiguously -- if buf[i] is + * non-NULL then buf[j] must also be non-NULL for all j < i. + * + * There may be at most one AVBuffer per data plane, so for video this array + * always contains all the references. For planar audio with more than + * AV_NUM_DATA_POINTERS channels, there may be more buffers than can fit in + * this array. Then the extra AVBufferRef pointers are stored in the + * extended_buf array. + */ + AVBufferRef *buf[AV_NUM_DATA_POINTERS]; + + /** + * For planar audio which requires more than AV_NUM_DATA_POINTERS + * AVBufferRef pointers, this array will hold all the references which + * cannot fit into AVFrame.buf. + * + * Note that this is different from AVFrame.extended_data, which always + * contains all the pointers. This array only contains the extra pointers, + * which cannot fit into AVFrame.buf. + * + * This array is always allocated using av_malloc() by whoever constructs + * the frame. It is freed in av_frame_unref(). + */ + AVBufferRef **extended_buf; + /** + * Number of elements in extended_buf. + */ + int nb_extended_buf; + + AVFrameSideData **side_data; + int nb_side_data; + +/** + * @defgroup lavu_frame_flags AV_FRAME_FLAGS + * @ingroup lavu_frame + * Flags describing additional frame properties. + * + * @{ + */ + +/** + * The frame data may be corrupted, e.g. due to decoding errors. + */ +#define AV_FRAME_FLAG_CORRUPT (1 << 0) +/** + * A flag to mark frames that are keyframes. + */ +#define AV_FRAME_FLAG_KEY (1 << 1) +/** + * A flag to mark the frames which need to be decoded, but shouldn't be output. + */ +#define AV_FRAME_FLAG_DISCARD (1 << 2) +/** + * A flag to mark frames whose content is interlaced. + */ +#define AV_FRAME_FLAG_INTERLACED (1 << 3) +/** + * A flag to mark frames where the top field is displayed first if the content + * is interlaced. + */ +#define AV_FRAME_FLAG_TOP_FIELD_FIRST (1 << 4) +/** + * @} + */ + + /** + * Frame flags, a combination of @ref lavu_frame_flags + */ + int flags; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorRange color_range; + + enum AVColorPrimaries color_primaries; + + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + enum AVChromaLocation chroma_location; + + /** + * frame timestamp estimated using various heuristics, in stream time base + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int64_t best_effort_timestamp; + +#if FF_API_FRAME_PKT + /** + * reordered pos from the last AVPacket that has been input into the decoder + * - encoding: unused + * - decoding: Read by user. + * @deprecated use AV_CODEC_FLAG_COPY_OPAQUE to pass through arbitrary user + * data from packets to frames + */ + attribute_deprecated + int64_t pkt_pos; +#endif + +#if FF_API_PKT_DURATION + /** + * duration of the corresponding packet, expressed in + * AVStream->time_base units, 0 if unknown. + * - encoding: unused + * - decoding: Read by user. + * + * @deprecated use duration instead + */ + attribute_deprecated + int64_t pkt_duration; +#endif + + /** + * metadata. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVDictionary *metadata; + + /** + * decode error flags of the frame, set to a combination of + * FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there + * were errors during the decoding. + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int decode_error_flags; +#define FF_DECODE_ERROR_INVALID_BITSTREAM 1 +#define FF_DECODE_ERROR_MISSING_REFERENCE 2 +#define FF_DECODE_ERROR_CONCEALMENT_ACTIVE 4 +#define FF_DECODE_ERROR_DECODE_SLICES 8 + +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * number of audio channels, only used for audio. + * - encoding: unused + * - decoding: Read by user. + * @deprecated use ch_layout instead + */ + attribute_deprecated + int channels; +#endif + +#if FF_API_FRAME_PKT + /** + * size of the corresponding packet containing the compressed + * frame. + * It is set to a negative value if unknown. + * - encoding: unused + * - decoding: set by libavcodec, read by user. + * @deprecated use AV_CODEC_FLAG_COPY_OPAQUE to pass through arbitrary user + * data from packets to frames + */ + attribute_deprecated + int pkt_size; +#endif + + /** + * For hwaccel-format frames, this should be a reference to the + * AVHWFramesContext describing the frame. + */ + AVBufferRef *hw_frames_ctx; + + /** + * Frame owner's private data. + * + * This field may be set by the code that allocates/owns the frame data. + * It is then not touched by any library functions, except: + * - a new reference to the underlying buffer is propagated by + * av_frame_copy_props() (and hence by av_frame_ref()); + * - it is unreferenced in av_frame_unref(); + * - on the caller's explicit request. E.g. libavcodec encoders/decoders + * will propagate a new reference to/from @ref AVPacket "AVPackets" if the + * caller sets @ref AV_CODEC_FLAG_COPY_OPAQUE. + * + * @see opaque the plain pointer analogue + */ + AVBufferRef *opaque_ref; + + /** + * @anchor cropping + * @name Cropping + * Video frames only. The number of pixels to discard from the the + * top/bottom/left/right border of the frame to obtain the sub-rectangle of + * the frame intended for presentation. + * @{ + */ + size_t crop_top; + size_t crop_bottom; + size_t crop_left; + size_t crop_right; + /** + * @} + */ + + /** + * AVBufferRef for internal use by a single libav* library. + * Must not be used to transfer data between libraries. + * Has to be NULL when ownership of the frame leaves the respective library. + * + * Code outside the FFmpeg libs should never check or change the contents of the buffer ref. + * + * FFmpeg calls av_buffer_unref() on it when the frame is unreferenced. + * av_frame_copy_props() calls create a new reference with av_buffer_ref() + * for the target frame's private_ref field. + */ + AVBufferRef *private_ref; + + /** + * Channel layout of the audio data. + */ + AVChannelLayout ch_layout; + + /** + * Duration of the frame, in the same units as pts. 0 if unknown. + */ + int64_t duration; +} AVFrame; + + +/** + * Allocate an AVFrame and set its fields to default values. The resulting + * struct must be freed using av_frame_free(). + * + * @return An AVFrame filled with default values or NULL on failure. + * + * @note this only allocates the AVFrame itself, not the data buffers. Those + * must be allocated through other means, e.g. with av_frame_get_buffer() or + * manually. + */ +AVFrame *av_frame_alloc(void); + +/** + * Free the frame and any dynamically allocated objects in it, + * e.g. extended_data. If the frame is reference counted, it will be + * unreferenced first. + * + * @param frame frame to be freed. The pointer will be set to NULL. + */ +void av_frame_free(AVFrame **frame); + +/** + * Set up a new reference to the data described by the source frame. + * + * Copy frame properties from src to dst and create a new reference for each + * AVBufferRef from src. + * + * If src is not reference counted, new buffers are allocated and the data is + * copied. + * + * @warning: dst MUST have been either unreferenced with av_frame_unref(dst), + * or newly allocated with av_frame_alloc() before calling this + * function, or undefined behavior will occur. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_frame_ref(AVFrame *dst, const AVFrame *src); + +/** + * Ensure the destination frame refers to the same data described by the source + * frame, either by creating a new reference for each AVBufferRef from src if + * they differ from those in dst, by allocating new buffers and copying data if + * src is not reference counted, or by unrefencing it if src is empty. + * + * Frame properties on dst will be replaced by those from src. + * + * @return 0 on success, a negative AVERROR on error. On error, dst is + * unreferenced. + */ +int av_frame_replace(AVFrame *dst, const AVFrame *src); + +/** + * Create a new frame that references the same data as src. + * + * This is a shortcut for av_frame_alloc()+av_frame_ref(). + * + * @return newly created AVFrame on success, NULL on error. + */ +AVFrame *av_frame_clone(const AVFrame *src); + +/** + * Unreference all the buffers referenced by frame and reset the frame fields. + */ +void av_frame_unref(AVFrame *frame); + +/** + * Move everything contained in src to dst and reset src. + * + * @warning: dst is not unreferenced, but directly overwritten without reading + * or deallocating its contents. Call av_frame_unref(dst) manually + * before calling this function to ensure that no memory is leaked. + */ +void av_frame_move_ref(AVFrame *dst, AVFrame *src); + +/** + * Allocate new buffer(s) for audio or video data. + * + * The following fields must be set on frame before calling this function: + * - format (pixel format for video, sample format for audio) + * - width and height for video + * - nb_samples and ch_layout for audio + * + * This function will fill AVFrame.data and AVFrame.buf arrays and, if + * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf. + * For planar formats, one buffer will be allocated for each plane. + * + * @warning: if frame already has been allocated, calling this function will + * leak memory. In addition, undefined behavior can occur in certain + * cases. + * + * @param frame frame in which to store the new buffers. + * @param align Required buffer size alignment. If equal to 0, alignment will be + * chosen automatically for the current CPU. It is highly + * recommended to pass 0 here unless you know what you are doing. + * + * @return 0 on success, a negative AVERROR on error. + */ +int av_frame_get_buffer(AVFrame *frame, int align); + +/** + * Check if the frame data is writable. + * + * @return A positive value if the frame data is writable (which is true if and + * only if each of the underlying buffers has only one reference, namely the one + * stored in this frame). Return 0 otherwise. + * + * If 1 is returned the answer is valid until av_buffer_ref() is called on any + * of the underlying AVBufferRefs (e.g. through av_frame_ref() or directly). + * + * @see av_frame_make_writable(), av_buffer_is_writable() + */ +int av_frame_is_writable(AVFrame *frame); + +/** + * Ensure that the frame data is writable, avoiding data copy if possible. + * + * Do nothing if the frame is writable, allocate new buffers and copy the data + * if it is not. Non-refcounted frames behave as non-writable, i.e. a copy + * is always made. + * + * @return 0 on success, a negative AVERROR on error. + * + * @see av_frame_is_writable(), av_buffer_is_writable(), + * av_buffer_make_writable() + */ +int av_frame_make_writable(AVFrame *frame); + +/** + * Copy the frame data from src to dst. + * + * This function does not allocate anything, dst must be already initialized and + * allocated with the same parameters as src. + * + * This function only copies the frame data (i.e. the contents of the data / + * extended data arrays), not any other properties. + * + * @return >= 0 on success, a negative AVERROR on error. + */ +int av_frame_copy(AVFrame *dst, const AVFrame *src); + +/** + * Copy only "metadata" fields from src to dst. + * + * Metadata for the purpose of this function are those fields that do not affect + * the data layout in the buffers. E.g. pts, sample rate (for audio) or sample + * aspect ratio (for video), but not width/height or channel layout. + * Side data is also copied. + */ +int av_frame_copy_props(AVFrame *dst, const AVFrame *src); + +/** + * Get the buffer reference a given data plane is stored in. + * + * @param frame the frame to get the plane's buffer from + * @param plane index of the data plane of interest in frame->extended_data. + * + * @return the buffer reference that contains the plane or NULL if the input + * frame is not valid. + */ +AVBufferRef *av_frame_get_plane_buffer(const AVFrame *frame, int plane); + +/** + * Add a new side data to a frame. + * + * @param frame a frame to which the side data should be added + * @param type type of the added side data + * @param size size of the side data + * + * @return newly added side data on success, NULL on error + */ +AVFrameSideData *av_frame_new_side_data(AVFrame *frame, + enum AVFrameSideDataType type, + size_t size); + +/** + * Add a new side data to a frame from an existing AVBufferRef + * + * @param frame a frame to which the side data should be added + * @param type the type of the added side data + * @param buf an AVBufferRef to add as side data. The ownership of + * the reference is transferred to the frame. + * + * @return newly added side data on success, NULL on error. On failure + * the frame is unchanged and the AVBufferRef remains owned by + * the caller. + */ +AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame, + enum AVFrameSideDataType type, + AVBufferRef *buf); + +/** + * @return a pointer to the side data of a given type on success, NULL if there + * is no side data with such type in this frame. + */ +AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, + enum AVFrameSideDataType type); + +/** + * Remove and free all side data instances of the given type. + */ +void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type); + + +/** + * Flags for frame cropping. + */ +enum { + /** + * Apply the maximum possible cropping, even if it requires setting the + * AVFrame.data[] entries to unaligned pointers. Passing unaligned data + * to FFmpeg API is generally not allowed, and causes undefined behavior + * (such as crashes). You can pass unaligned data only to FFmpeg APIs that + * are explicitly documented to accept it. Use this flag only if you + * absolutely know what you are doing. + */ + AV_FRAME_CROP_UNALIGNED = 1 << 0, +}; + +/** + * Crop the given video AVFrame according to its crop_left/crop_top/crop_right/ + * crop_bottom fields. If cropping is successful, the function will adjust the + * data pointers and the width/height fields, and set the crop fields to 0. + * + * In all cases, the cropping boundaries will be rounded to the inherent + * alignment of the pixel format. In some cases, such as for opaque hwaccel + * formats, the left/top cropping is ignored. The crop fields are set to 0 even + * if the cropping was rounded or ignored. + * + * @param frame the frame which should be cropped + * @param flags Some combination of AV_FRAME_CROP_* flags, or 0. + * + * @return >= 0 on success, a negative AVERROR on error. If the cropping fields + * were invalid, AVERROR(ERANGE) is returned, and nothing is changed. + */ +int av_frame_apply_cropping(AVFrame *frame, int flags); + +/** + * @return a string identifying the side data type + */ +const char *av_frame_side_data_name(enum AVFrameSideDataType type); + +/** + * @} + */ + +#endif /* AVUTIL_FRAME_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/hwcontext.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/hwcontext.h new file mode 100644 index 0000000000000..7ff08c86085f3 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/hwcontext.h @@ -0,0 +1,610 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_H +#define AVUTIL_HWCONTEXT_H + +#include "buffer.h" +#include "frame.h" +#include "log.h" +#include "pixfmt.h" + +enum AVHWDeviceType { + AV_HWDEVICE_TYPE_NONE, + AV_HWDEVICE_TYPE_VDPAU, + AV_HWDEVICE_TYPE_CUDA, + AV_HWDEVICE_TYPE_VAAPI, + AV_HWDEVICE_TYPE_DXVA2, + AV_HWDEVICE_TYPE_QSV, + AV_HWDEVICE_TYPE_VIDEOTOOLBOX, + AV_HWDEVICE_TYPE_D3D11VA, + AV_HWDEVICE_TYPE_DRM, + AV_HWDEVICE_TYPE_OPENCL, + AV_HWDEVICE_TYPE_MEDIACODEC, + AV_HWDEVICE_TYPE_VULKAN, +}; + +typedef struct AVHWDeviceInternal AVHWDeviceInternal; + +/** + * This struct aggregates all the (hardware/vendor-specific) "high-level" state, + * i.e. state that is not tied to a concrete processing configuration. + * E.g., in an API that supports hardware-accelerated encoding and decoding, + * this struct will (if possible) wrap the state that is common to both encoding + * and decoding and from which specific instances of encoders or decoders can be + * derived. + * + * This struct is reference-counted with the AVBuffer mechanism. The + * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field + * points to the actual AVHWDeviceContext. Further objects derived from + * AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with + * specific properties) will hold an internal reference to it. After all the + * references are released, the AVHWDeviceContext itself will be freed, + * optionally invoking a user-specified callback for uninitializing the hardware + * state. + */ +typedef struct AVHWDeviceContext { + /** + * A class for logging. Set by av_hwdevice_ctx_alloc(). + */ + const AVClass *av_class; + + /** + * Private data used internally by libavutil. Must not be accessed in any + * way by the caller. + */ + AVHWDeviceInternal *internal; + + /** + * This field identifies the underlying API used for hardware access. + * + * This field is set when this struct is allocated and never changed + * afterwards. + */ + enum AVHWDeviceType type; + + /** + * The format-specific data, allocated and freed by libavutil along with + * this context. + * + * Should be cast by the user to the format-specific context defined in the + * corresponding header (hwcontext_*.h) and filled as described in the + * documentation before calling av_hwdevice_ctx_init(). + * + * After calling av_hwdevice_ctx_init() this struct should not be modified + * by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwdevice_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + * + * @note when other objects (e.g an AVHWFramesContext) are derived from this + * struct, this callback will be invoked after all such child objects + * are fully uninitialized and their respective destructors invoked. + */ + void (*free)(struct AVHWDeviceContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; +} AVHWDeviceContext; + +typedef struct AVHWFramesInternal AVHWFramesInternal; + +/** + * This struct describes a set or pool of "hardware" frames (i.e. those with + * data not located in normal system memory). All the frames in the pool are + * assumed to be allocated in the same way and interchangeable. + * + * This struct is reference-counted with the AVBuffer mechanism and tied to a + * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor + * yields a reference, whose data field points to the actual AVHWFramesContext + * struct. + */ +typedef struct AVHWFramesContext { + /** + * A class for logging. + */ + const AVClass *av_class; + + /** + * Private data used internally by libavutil. Must not be accessed in any + * way by the caller. + */ + AVHWFramesInternal *internal; + + /** + * A reference to the parent AVHWDeviceContext. This reference is owned and + * managed by the enclosing AVHWFramesContext, but the caller may derive + * additional references from it. + */ + AVBufferRef *device_ref; + + /** + * The parent AVHWDeviceContext. This is simply a pointer to + * device_ref->data provided for convenience. + * + * Set by libavutil in av_hwframe_ctx_init(). + */ + AVHWDeviceContext *device_ctx; + + /** + * The format-specific data, allocated and freed automatically along with + * this context. + * + * Should be cast by the user to the format-specific context defined in the + * corresponding header (hwframe_*.h) and filled as described in the + * documentation before calling av_hwframe_ctx_init(). + * + * After any frames using this context are created, the contents of this + * struct should not be modified by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + */ + void (*free)(struct AVHWFramesContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; + + /** + * A pool from which the frames are allocated by av_hwframe_get_buffer(). + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * The buffers returned by calling av_buffer_pool_get() on this pool must + * have the properties described in the documentation in the corresponding hw + * type's header (hwcontext_*.h). The pool will be freed strictly before + * this struct's free() callback is invoked. + * + * This field may be NULL, then libavutil will attempt to allocate a pool + * internally. Note that certain device types enforce pools allocated at + * fixed size (frame count), which cannot be extended dynamically. In such a + * case, initial_pool_size must be set appropriately. + */ + AVBufferPool *pool; + + /** + * Initial size of the frame pool. If a device type does not support + * dynamically resizing the pool, then this is also the maximum pool size. + * + * May be set by the caller before calling av_hwframe_ctx_init(). Must be + * set if pool is NULL and the device type does not support dynamic pools. + */ + int initial_pool_size; + + /** + * The pixel format identifying the underlying HW surface type. + * + * Must be a hwaccel format, i.e. the corresponding descriptor must have the + * AV_PIX_FMT_FLAG_HWACCEL flag set. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + enum AVPixelFormat format; + + /** + * The pixel format identifying the actual data layout of the hardware + * frames. + * + * Must be set by the caller before calling av_hwframe_ctx_init(). + * + * @note when the underlying API does not provide the exact data layout, but + * only the colorspace/bit depth, this field should be set to the fully + * planar version of that format (e.g. for 8-bit 420 YUV it should be + * AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else). + */ + enum AVPixelFormat sw_format; + + /** + * The allocated dimensions of the frames in this pool. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + int width, height; +} AVHWFramesContext; + +/** + * Look up an AVHWDeviceType by name. + * + * @param name String name of the device type (case-insensitive). + * @return The type from enum AVHWDeviceType, or AV_HWDEVICE_TYPE_NONE if + * not found. + */ +enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name); + +/** Get the string name of an AVHWDeviceType. + * + * @param type Type from enum AVHWDeviceType. + * @return Pointer to a static string containing the name, or NULL if the type + * is not valid. + */ +const char *av_hwdevice_get_type_name(enum AVHWDeviceType type); + +/** + * Iterate over supported device types. + * + * @param prev AV_HWDEVICE_TYPE_NONE initially, then the previous type + * returned by this function in subsequent iterations. + * @return The next usable device type from enum AVHWDeviceType, or + * AV_HWDEVICE_TYPE_NONE if there are no more. + */ +enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev); + +/** + * Allocate an AVHWDeviceContext for a given hardware type. + * + * @param type the type of the hardware device to allocate. + * @return a reference to the newly created AVHWDeviceContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type); + +/** + * Finalize the device context before use. This function must be called after + * the context is filled with all the required information and before it is + * used in any way. + * + * @param ref a reference to the AVHWDeviceContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwdevice_ctx_init(AVBufferRef *ref); + +/** + * Open a device of the specified type and create an AVHWDeviceContext for it. + * + * This is a convenience function intended to cover the simple cases. Callers + * who need to fine-tune device creation/management should open the device + * manually and then wrap it in an AVHWDeviceContext using + * av_hwdevice_ctx_alloc()/av_hwdevice_ctx_init(). + * + * The returned context is already initialized and ready for use, the caller + * should not call av_hwdevice_ctx_init() on it. The user_opaque/free fields of + * the created AVHWDeviceContext are set by this function and should not be + * touched by the caller. + * + * @param device_ctx On success, a reference to the newly-created device context + * will be written here. The reference is owned by the caller + * and must be released with av_buffer_unref() when no longer + * needed. On failure, NULL will be written to this pointer. + * @param type The type of the device to create. + * @param device A type-specific string identifying the device to open. + * @param opts A dictionary of additional (type-specific) options to use in + * opening the device. The dictionary remains owned by the caller. + * @param flags currently unused + * + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type, + const char *device, AVDictionary *opts, int flags); + +/** + * Create a new device of the specified type from an existing device. + * + * If the source device is a device of the target type or was originally + * derived from such a device (possibly through one or more intermediate + * devices of other types), then this will return a reference to the + * existing device of the same type as is requested. + * + * Otherwise, it will attempt to derive a new device from the given source + * device. If direct derivation to the new type is not implemented, it will + * attempt the same derivation from each ancestor of the source device in + * turn looking for an implemented derivation method. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, int flags); + +/** + * Create a new device of the specified type from an existing device. + * + * This function performs the same action as av_hwdevice_ctx_create_derived, + * however, it is able to set options for the new device to be derived. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param options Options for the new device to create, same format as in + * av_hwdevice_ctx_create. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, + AVDictionary *options, int flags); + +/** + * Allocate an AVHWFramesContext tied to a given device context. + * + * @param device_ctx a reference to a AVHWDeviceContext. This function will make + * a new reference for internal use, the one passed to the + * function remains owned by the caller. + * @return a reference to the newly created AVHWFramesContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx); + +/** + * Finalize the context before use. This function must be called after the + * context is filled with all the required information and before it is attached + * to any frames. + * + * @param ref a reference to the AVHWFramesContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_ctx_init(AVBufferRef *ref); + +/** + * Allocate a new frame attached to the given AVHWFramesContext. + * + * @param hwframe_ctx a reference to an AVHWFramesContext + * @param frame an empty (freshly allocated or unreffed) frame to be filled with + * newly allocated buffers. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags); + +/** + * Copy data to or from a hw surface. At least one of dst/src must have an + * AVHWFramesContext attached. + * + * If src has an AVHWFramesContext attached, then the format of dst (if set) + * must use one of the formats returned by av_hwframe_transfer_get_formats(src, + * AV_HWFRAME_TRANSFER_DIRECTION_FROM). + * If dst has an AVHWFramesContext attached, then the format of src must use one + * of the formats returned by av_hwframe_transfer_get_formats(dst, + * AV_HWFRAME_TRANSFER_DIRECTION_TO) + * + * dst may be "clean" (i.e. with data/buf pointers unset), in which case the + * data buffers will be allocated by this function using av_frame_get_buffer(). + * If dst->format is set, then this format will be used, otherwise (when + * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen. + * + * The two frames must have matching allocated dimensions (i.e. equal to + * AVHWFramesContext.width/height), since not all device types support + * transferring a sub-rectangle of the whole surface. The display dimensions + * (i.e. AVFrame.width/height) may be smaller than the allocated dimensions, but + * also have to be equal for both frames. When the display dimensions are + * smaller than the allocated dimensions, the content of the padding in the + * destination frame is unspecified. + * + * @param dst the destination frame. dst is not touched on failure. + * @param src the source frame. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR error code on failure. + */ +int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags); + +enum AVHWFrameTransferDirection { + /** + * Transfer the data from the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_FROM, + + /** + * Transfer the data to the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_TO, +}; + +/** + * Get a list of possible source or target formats usable in + * av_hwframe_transfer_data(). + * + * @param hwframe_ctx the frame context to obtain the information for + * @param dir the direction of the transfer + * @param formats the pointer to the output format list will be written here. + * The list is terminated with AV_PIX_FMT_NONE and must be freed + * by the caller when no longer needed using av_free(). + * If this function returns successfully, the format list will + * have at least one item (not counting the terminator). + * On failure, the contents of this pointer are unspecified. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats, int flags); + + +/** + * This struct describes the constraints on hardware frames attached to + * a given device with a hardware-specific configuration. This is returned + * by av_hwdevice_get_hwframe_constraints() and must be freed by + * av_hwframe_constraints_free() after use. + */ +typedef struct AVHWFramesConstraints { + /** + * A list of possible values for format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. This member will always be filled. + */ + enum AVPixelFormat *valid_hw_formats; + + /** + * A list of possible values for sw_format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. Can be NULL if this information is + * not known. + */ + enum AVPixelFormat *valid_sw_formats; + + /** + * The minimum size of frames in this hw_frames_ctx. + * (Zero if not known.) + */ + int min_width; + int min_height; + + /** + * The maximum size of frames in this hw_frames_ctx. + * (INT_MAX if not known / no limit.) + */ + int max_width; + int max_height; +} AVHWFramesConstraints; + +/** + * Allocate a HW-specific configuration structure for a given HW device. + * After use, the user must free all members as required by the specific + * hardware structure being used, then free the structure itself with + * av_free(). + * + * @param device_ctx a reference to the associated AVHWDeviceContext. + * @return The newly created HW-specific configuration structure on + * success or NULL on failure. + */ +void *av_hwdevice_hwconfig_alloc(AVBufferRef *device_ctx); + +/** + * Get the constraints on HW frames given a device and the HW-specific + * configuration to be used with that device. If no HW-specific + * configuration is provided, returns the maximum possible capabilities + * of the device. + * + * @param ref a reference to the associated AVHWDeviceContext. + * @param hwconfig a filled HW-specific configuration structure, or NULL + * to return the maximum possible capabilities of the device. + * @return AVHWFramesConstraints structure describing the constraints + * on the device, or NULL if not available. + */ +AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, + const void *hwconfig); + +/** + * Free an AVHWFrameConstraints structure. + * + * @param constraints The (filled or unfilled) AVHWFrameConstraints structure. + */ +void av_hwframe_constraints_free(AVHWFramesConstraints **constraints); + + +/** + * Flags to apply to frame mappings. + */ +enum { + /** + * The mapping must be readable. + */ + AV_HWFRAME_MAP_READ = 1 << 0, + /** + * The mapping must be writeable. + */ + AV_HWFRAME_MAP_WRITE = 1 << 1, + /** + * The mapped frame will be overwritten completely in subsequent + * operations, so the current frame data need not be loaded. Any values + * which are not overwritten are unspecified. + */ + AV_HWFRAME_MAP_OVERWRITE = 1 << 2, + /** + * The mapping must be direct. That is, there must not be any copying in + * the map or unmap steps. Note that performance of direct mappings may + * be much lower than normal memory. + */ + AV_HWFRAME_MAP_DIRECT = 1 << 3, +}; + +/** + * Map a hardware frame. + * + * This has a number of different possible effects, depending on the format + * and origin of the src and dst frames. On input, src should be a usable + * frame with valid buffers and dst should be blank (typically as just created + * by av_frame_alloc()). src should have an associated hwframe context, and + * dst may optionally have a format and associated hwframe context. + * + * If src was created by mapping a frame from the hwframe context of dst, + * then this function undoes the mapping - dst is replaced by a reference to + * the frame that src was originally mapped from. + * + * If both src and dst have an associated hwframe context, then this function + * attempts to map the src frame from its hardware context to that of dst and + * then fill dst with appropriate data to be usable there. This will only be + * possible if the hwframe contexts and associated devices are compatible - + * given compatible devices, av_hwframe_ctx_create_derived() can be used to + * create a hwframe context for dst in which mapping should be possible. + * + * If src has a hwframe context but dst does not, then the src frame is + * mapped to normal memory and should thereafter be usable as a normal frame. + * If the format is set on dst, then the mapping will attempt to create dst + * with that format and fail if it is not possible. If format is unset (is + * AV_PIX_FMT_NONE) then dst will be mapped with whatever the most appropriate + * format to use is (probably the sw_format of the src hwframe context). + * + * A return value of AVERROR(ENOSYS) indicates that the mapping is not + * possible with the given arguments and hwframe setup, while other return + * values indicate that it failed somehow. + * + * On failure, the destination frame will be left blank, except for the + * hw_frames_ctx/format fields thay may have been set by the caller - those will + * be preserved as they were. + * + * @param dst Destination frame, to contain the mapping. + * @param src Source frame, to be mapped. + * @param flags Some combination of AV_HWFRAME_MAP_* flags. + * @return Zero on success, negative AVERROR code on failure. + */ +int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags); + + +/** + * Create and initialise an AVHWFramesContext as a mapping of another existing + * AVHWFramesContext on a different device. + * + * av_hwframe_ctx_init() should not be called after this. + * + * @param derived_frame_ctx On success, a reference to the newly created + * AVHWFramesContext. + * @param format The AVPixelFormat for the derived context. + * @param derived_device_ctx A reference to the device to create the new + * AVHWFramesContext on. + * @param source_frame_ctx A reference to an existing AVHWFramesContext + * which will be mapped to the derived context. + * @param flags Some combination of AV_HWFRAME_MAP_* flags, defining the + * mapping parameters to apply to frames which are allocated + * in the derived device. + * @return Zero on success, negative AVERROR code on failure. + */ +int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, + enum AVPixelFormat format, + AVBufferRef *derived_device_ctx, + AVBufferRef *source_frame_ctx, + int flags); + +#endif /* AVUTIL_HWCONTEXT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/imgutils.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/imgutils.h new file mode 100644 index 0000000000000..fa3bb101b1391 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/imgutils.h @@ -0,0 +1,347 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_IMGUTILS_H +#define AVUTIL_IMGUTILS_H + +/** + * @file + * misc image utilities + * + * @addtogroup lavu_picture + * @{ + */ + +#include +#include +#include "pixdesc.h" +#include "pixfmt.h" +#include "rational.h" + +/** + * Compute the max pixel step for each plane of an image with a + * format described by pixdesc. + * + * The pixel step is the distance in bytes between the first byte of + * the group of bytes which describe a pixel component and the first + * byte of the successive group in the same plane for the same + * component. + * + * @param max_pixsteps an array which is filled with the max pixel step + * for each plane. Since a plane may contain different pixel + * components, the computed max_pixsteps[plane] is relative to the + * component in the plane with the max pixel step. + * @param max_pixstep_comps an array which is filled with the component + * for each plane which has the max pixel step. May be NULL. + * @param pixdesc the AVPixFmtDescriptor for the image, describing its format + */ +void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], + const AVPixFmtDescriptor *pixdesc); + +/** + * Compute the size of an image line with format pix_fmt and width + * width for the plane plane. + * + * @return the computed size in bytes + */ +int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane); + +/** + * Fill plane linesizes for an image with pixel format pix_fmt and + * width width. + * + * @param linesizes array to be filled with the linesize for each plane + * @param pix_fmt the AVPixelFormat of the image + * @param width width of the image in pixels + * @return >= 0 in case of success, a negative error code otherwise + */ +int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width); + +/** + * Fill plane sizes for an image with pixel format pix_fmt and height height. + * + * @param size the array to be filled with the size of each image plane + * @param pix_fmt the AVPixelFormat of the image + * @param height height of the image in pixels + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return >= 0 in case of success, a negative error code otherwise + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_fill_linesizes(). + */ +int av_image_fill_plane_sizes(size_t size[4], enum AVPixelFormat pix_fmt, + int height, const ptrdiff_t linesizes[4]); + +/** + * Fill plane data pointers for an image with pixel format pix_fmt and + * height height. + * + * @param data pointers array to be filled with the pointer for each image plane + * @param pix_fmt the AVPixelFormat of the image + * @param height height of the image in pixels + * @param ptr the pointer to a buffer which will contain the image + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, + uint8_t *ptr, const int linesizes[4]); + +/** + * Allocate an image with size w and h and pixel format pix_fmt, and + * fill pointers and linesizes accordingly. + * The allocated image buffer has to be freed by using + * av_freep(&pointers[0]). + * + * @param pointers array to be filled with the pointer for each image plane + * @param linesizes the array filled with the linesize for each plane + * @param w width of the image in pixels + * @param h height of the image in pixels + * @param pix_fmt the AVPixelFormat of the image + * @param align the value to use for buffer size alignment + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_alloc(uint8_t *pointers[4], int linesizes[4], + int w, int h, enum AVPixelFormat pix_fmt, int align); + +/** + * Copy image plane from src to dst. + * That is, copy "height" number of lines of "bytewidth" bytes each. + * The first byte of each successive line is separated by *_linesize + * bytes. + * + * bytewidth must be contained by both absolute values of dst_linesize + * and src_linesize, otherwise the function behavior is undefined. + * + * @param dst destination plane to copy to + * @param dst_linesize linesize for the image plane in dst + * @param src source plane to copy from + * @param src_linesize linesize for the image plane in src + * @param height height (number of lines) of the plane + */ +void av_image_copy_plane(uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, + int bytewidth, int height); + +/** + * Copy image data located in uncacheable (e.g. GPU mapped) memory. Where + * available, this function will use special functionality for reading from such + * memory, which may result in greatly improved performance compared to plain + * av_image_copy_plane(). + * + * bytewidth must be contained by both absolute values of dst_linesize + * and src_linesize, otherwise the function behavior is undefined. + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_copy_plane(). + * @note On x86, the linesizes currently need to be aligned to the cacheline + * size (i.e. 64) to get improved performance. + */ +void av_image_copy_plane_uc_from(uint8_t *dst, ptrdiff_t dst_linesize, + const uint8_t *src, ptrdiff_t src_linesize, + ptrdiff_t bytewidth, int height); + +/** + * Copy image in src_data to dst_data. + * + * @param dst_data destination image data buffer to copy to + * @param dst_linesizes linesizes for the image in dst_data + * @param src_data source image data buffer to copy from + * @param src_linesizes linesizes for the image in src_data + * @param pix_fmt the AVPixelFormat of the image + * @param width width of the image in pixels + * @param height height of the image in pixels + */ +void av_image_copy(uint8_t * const dst_data[4], const int dst_linesizes[4], + const uint8_t * const src_data[4], const int src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Wrapper around av_image_copy() to workaround the limitation + * that the conversion from uint8_t * const * to const uint8_t * const * + * is not performed automatically in C. + * @see av_image_copy() + */ +static inline +void av_image_copy2(uint8_t * const dst_data[4], const int dst_linesizes[4], + uint8_t * const src_data[4], const int src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height) +{ + av_image_copy(dst_data, dst_linesizes, + (const uint8_t * const *)src_data, src_linesizes, + pix_fmt, width, height); +} + +/** + * Copy image data located in uncacheable (e.g. GPU mapped) memory. Where + * available, this function will use special functionality for reading from such + * memory, which may result in greatly improved performance compared to plain + * av_image_copy(). + * + * The data pointers and the linesizes must be aligned to the maximum required + * by the CPU architecture. + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_copy(). + * @note On x86, the linesizes currently need to be aligned to the cacheline + * size (i.e. 64) to get improved performance. + */ +void av_image_copy_uc_from(uint8_t * const dst_data[4], const ptrdiff_t dst_linesizes[4], + const uint8_t * const src_data[4], const ptrdiff_t src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Setup the data pointers and linesizes based on the specified image + * parameters and the provided array. + * + * The fields of the given image are filled in by using the src + * address which points to the image data buffer. Depending on the + * specified pixel format, one or multiple image data pointers and + * line sizes will be set. If a planar format is specified, several + * pointers will be set pointing to the different picture planes and + * the line sizes of the different planes will be stored in the + * lines_sizes array. Call with src == NULL to get the required + * size for the src buffer. + * + * To allocate the buffer and fill in the dst_data and dst_linesize in + * one call, use av_image_alloc(). + * + * @param dst_data data pointers to be filled in + * @param dst_linesize linesizes for the image in dst_data to be filled in + * @param src buffer which will contain or contains the actual image data, can be NULL + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the value used in src for linesize alignment + * @return the size in bytes required for src, a negative error code + * in case of failure + */ +int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Return the size in bytes of the amount of data required to store an + * image with the given parameters. + * + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the assumed linesize alignment + * @return the buffer size in bytes, a negative error code in case of failure + */ +int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Copy image data from an image into a buffer. + * + * av_image_get_buffer_size() can be used to compute the required size + * for the buffer to fill. + * + * @param dst a buffer into which picture data will be copied + * @param dst_size the size in bytes of dst + * @param src_data pointers containing the source image data + * @param src_linesize linesizes for the image in src_data + * @param pix_fmt the pixel format of the source image + * @param width the width of the source image in pixels + * @param height the height of the source image in pixels + * @param align the assumed linesize alignment for dst + * @return the number of bytes written to dst, or a negative value + * (error code) on error + */ +int av_image_copy_to_buffer(uint8_t *dst, int dst_size, + const uint8_t * const src_data[4], const int src_linesize[4], + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of the image can be addressed with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of a plane of an image with the specified pix_fmt can be addressed + * with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param max_pixels the maximum number of pixels the user wants to accept + * @param pix_fmt the pixel format, can be AV_PIX_FMT_NONE if unknown. + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx); + +/** + * Check if the given sample aspect ratio of an image is valid. + * + * It is considered invalid if the denominator is 0 or if applying the ratio + * to the image size would make the smaller dimension less than 1. If the + * sar numerator is 0, it is considered unknown and will return as valid. + * + * @param w width of the image + * @param h height of the image + * @param sar sample aspect ratio of the image + * @return 0 if valid, a negative AVERROR code otherwise + */ +int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar); + +/** + * Overwrite the image data with black. This is suitable for filling a + * sub-rectangle of an image, meaning the padding between the right most pixel + * and the left most pixel on the next line will not be overwritten. For some + * formats, the image size might be rounded up due to inherent alignment. + * + * If the pixel format has alpha, the alpha is cleared to opaque. + * + * This can return an error if the pixel format is not supported. Normally, all + * non-hwaccel pixel formats should be supported. + * + * Passing NULL for dst_data is allowed. Then the function returns whether the + * operation would have succeeded. (It can return an error if the pix_fmt is + * not supported.) + * + * @param dst_data data pointers to destination image + * @param dst_linesize linesizes for the destination image + * @param pix_fmt the pixel format of the image + * @param range the color range of the image (important for colorspaces such as YUV) + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @return 0 if the image data was cleared, a negative AVERROR code otherwise + */ +int av_image_fill_black(uint8_t * const dst_data[4], const ptrdiff_t dst_linesize[4], + enum AVPixelFormat pix_fmt, enum AVColorRange range, + int width, int height); + +/** + * @} + */ + + +#endif /* AVUTIL_IMGUTILS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/intfloat.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/intfloat.h new file mode 100644 index 0000000000000..fe3d7ec4a5b6f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/intfloat.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_INTFLOAT_H +#define AVUTIL_INTFLOAT_H + +#include +#include "attributes.h" + +union av_intfloat32 { + uint32_t i; + float f; +}; + +union av_intfloat64 { + uint64_t i; + double f; +}; + +/** + * Reinterpret a 32-bit integer as a float. + */ +static av_always_inline float av_int2float(uint32_t i) +{ + union av_intfloat32 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a float as a 32-bit integer. + */ +static av_always_inline uint32_t av_float2int(float f) +{ + union av_intfloat32 v; + v.f = f; + return v.i; +} + +/** + * Reinterpret a 64-bit integer as a double. + */ +static av_always_inline double av_int2double(uint64_t i) +{ + union av_intfloat64 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a double as a 64-bit integer. + */ +static av_always_inline uint64_t av_double2int(double f) +{ + union av_intfloat64 v; + v.f = f; + return v.i; +} + +#endif /* AVUTIL_INTFLOAT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/log.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/log.h new file mode 100644 index 0000000000000..ab7ceabe2234a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/log.h @@ -0,0 +1,387 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_LOG_H +#define AVUTIL_LOG_H + +#include +#include "attributes.h" +#include "version.h" + +typedef enum { + AV_CLASS_CATEGORY_NA = 0, + AV_CLASS_CATEGORY_INPUT, + AV_CLASS_CATEGORY_OUTPUT, + AV_CLASS_CATEGORY_MUXER, + AV_CLASS_CATEGORY_DEMUXER, + AV_CLASS_CATEGORY_ENCODER, + AV_CLASS_CATEGORY_DECODER, + AV_CLASS_CATEGORY_FILTER, + AV_CLASS_CATEGORY_BITSTREAM_FILTER, + AV_CLASS_CATEGORY_SWSCALER, + AV_CLASS_CATEGORY_SWRESAMPLER, + AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT = 40, + AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT, + AV_CLASS_CATEGORY_NB ///< not part of ABI/API +}AVClassCategory; + +#define AV_IS_INPUT_DEVICE(category) \ + (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_INPUT)) + +#define AV_IS_OUTPUT_DEVICE(category) \ + (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_OUTPUT)) + +struct AVOptionRanges; + +/** + * Describe the class of an AVClass context structure. That is an + * arbitrary struct of which the first field is a pointer to an + * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.). + */ +typedef struct AVClass { + /** + * The name of the class; usually it is the same name as the + * context structure type to which the AVClass is associated. + */ + const char* class_name; + + /** + * A pointer to a function which returns the name of a context + * instance ctx associated with the class. + */ + const char* (*item_name)(void* ctx); + + /** + * a pointer to the first option specified in the class if any or NULL + * + * @see av_set_default_options() + */ + const struct AVOption *option; + + /** + * LIBAVUTIL_VERSION with which this structure was created. + * This is used to allow fields to be added without requiring major + * version bumps everywhere. + */ + + int version; + + /** + * Offset in the structure where log_level_offset is stored. + * 0 means there is no such variable + */ + int log_level_offset_offset; + + /** + * Offset in the structure where a pointer to the parent context for + * logging is stored. For example a decoder could pass its AVCodecContext + * to eval as such a parent context, which an av_log() implementation + * could then leverage to display the parent context. + * The offset can be NULL. + */ + int parent_log_context_offset; + + /** + * Category used for visualization (like color) + * This is only set if the category is equal for all objects using this class. + * available since version (51 << 16 | 56 << 8 | 100) + */ + AVClassCategory category; + + /** + * Callback to return the category. + * available since version (51 << 16 | 59 << 8 | 100) + */ + AVClassCategory (*get_category)(void* ctx); + + /** + * Callback to return the supported/allowed ranges. + * available since version (52.12) + */ + int (*query_ranges)(struct AVOptionRanges **, void *obj, const char *key, int flags); + + /** + * Return next AVOptions-enabled child or NULL + */ + void* (*child_next)(void *obj, void *prev); + + /** + * Iterate over the AVClasses corresponding to potential AVOptions-enabled + * children. + * + * @param iter pointer to opaque iteration state. The caller must initialize + * *iter to NULL before the first call. + * @return AVClass for the next AVOptions-enabled child or NULL if there are + * no more such children. + * + * @note The difference between child_next and this is that child_next + * iterates over _already existing_ objects, while child_class_iterate + * iterates over _all possible_ children. + */ + const struct AVClass* (*child_class_iterate)(void **iter); +} AVClass; + +/** + * @addtogroup lavu_log + * + * @{ + * + * @defgroup lavu_log_constants Logging Constants + * + * @{ + */ + +/** + * Print no output. + */ +#define AV_LOG_QUIET -8 + +/** + * Something went really wrong and we will crash now. + */ +#define AV_LOG_PANIC 0 + +/** + * Something went wrong and recovery is not possible. + * For example, no header was found for a format which depends + * on headers or an illegal combination of parameters is used. + */ +#define AV_LOG_FATAL 8 + +/** + * Something went wrong and cannot losslessly be recovered. + * However, not all future data is affected. + */ +#define AV_LOG_ERROR 16 + +/** + * Something somehow does not look correct. This may or may not + * lead to problems. An example would be the use of '-vstrict -2'. + */ +#define AV_LOG_WARNING 24 + +/** + * Standard information. + */ +#define AV_LOG_INFO 32 + +/** + * Detailed information. + */ +#define AV_LOG_VERBOSE 40 + +/** + * Stuff which is only useful for libav* developers. + */ +#define AV_LOG_DEBUG 48 + +/** + * Extremely verbose debugging, useful for libav* development. + */ +#define AV_LOG_TRACE 56 + +#define AV_LOG_MAX_OFFSET (AV_LOG_TRACE - AV_LOG_QUIET) + +/** + * @} + */ + +/** + * Sets additional colors for extended debugging sessions. + * @code + av_log(ctx, AV_LOG_DEBUG|AV_LOG_C(134), "Message in purple\n"); + @endcode + * Requires 256color terminal support. Uses outside debugging is not + * recommended. + */ +#define AV_LOG_C(x) ((x) << 8) + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log_set_callback + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct or NULL if general log. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + */ +void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Send the specified message to the log once with the initial_level and then with + * the subsequent_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct or NULL if general log. + * @param initial_level importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant" for the first occurance. + * @param subsequent_level importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant" after the first occurance. + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param state a variable to keep trak of if a message has already been printed + * this must be initialized to 0 before the first use. The same state + * must not be accessed by 2 Threads simultaneously. + */ +void av_log_once(void* avcl, int initial_level, int subsequent_level, int *state, const char *fmt, ...) av_printf_format(5, 6); + + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log_set_callback + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param vl The arguments referenced by the format string. + */ +void av_vlog(void *avcl, int level, const char *fmt, va_list vl); + +/** + * Get the current log level + * + * @see lavu_log_constants + * + * @return Current log level + */ +int av_log_get_level(void); + +/** + * Set the log level + * + * @see lavu_log_constants + * + * @param level Logging level + */ +void av_log_set_level(int level); + +/** + * Set the logging callback + * + * @note The callback must be thread safe, even if the application does not use + * threads itself as some codecs are multithreaded. + * + * @see av_log_default_callback + * + * @param callback A logging function with a compatible signature. + */ +void av_log_set_callback(void (*callback)(void*, int, const char*, va_list)); + +/** + * Default logging callback + * + * It prints the message to stderr, optionally colorizing it. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param vl The arguments referenced by the format string. + */ +void av_log_default_callback(void *avcl, int level, const char *fmt, + va_list vl); + +/** + * Return the context name + * + * @param ctx The AVClass context + * + * @return The AVClass class_name + */ +const char* av_default_item_name(void* ctx); +AVClassCategory av_default_get_category(void *ptr); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formatted line + * @param line_size size of the buffer + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + */ +void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formatted line; + * may be NULL if line_size is 0 + * @param line_size size of the buffer; at most line_size-1 characters will + * be written to the buffer, plus one null terminator + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + * @return Returns a negative value if an error occurred, otherwise returns + * the number of characters that would have been written for a + * sufficiently large buffer, not including the terminating null + * character. If the return value is not less than line_size, it means + * that the log message was truncated to fit the buffer. + */ +int av_log_format_line2(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * Skip repeated messages, this requires the user app to use av_log() instead of + * (f)printf as the 2 would otherwise interfere and lead to + * "Last message repeated x times" messages below (f)printf messages with some + * bad luck. + * Also to receive the last, "last repeated" line if any, the user app must + * call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end + */ +#define AV_LOG_SKIP_REPEATED 1 + +/** + * Include the log severity in messages originating from codecs. + * + * Results in messages such as: + * [rawvideo @ 0xDEADBEEF] [error] encode did not produce valid pts + */ +#define AV_LOG_PRINT_LEVEL 2 + +void av_log_set_flags(int arg); +int av_log_get_flags(void); + +/** + * @} + */ + +#endif /* AVUTIL_LOG_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/macros.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/macros.h new file mode 100644 index 0000000000000..2a7567c3ea8fb --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/macros.h @@ -0,0 +1,80 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu + * Utility Preprocessor macros + */ + +#ifndef AVUTIL_MACROS_H +#define AVUTIL_MACROS_H + +#include "libavutil/avconfig.h" + +#if AV_HAVE_BIGENDIAN +# define AV_NE(be, le) (be) +#else +# define AV_NE(be, le) (le) +#endif + +/** + * Comparator. + * For two numerical expressions x and y, gives 1 if x > y, -1 if x < y, and 0 + * if x == y. This is useful for instance in a qsort comparator callback. + * Furthermore, compilers are able to optimize this to branchless code, and + * there is no risk of overflow with signed types. + * As with many macros, this evaluates its argument multiple times, it thus + * must not have a side-effect. + */ +#define FFDIFFSIGN(x,y) (((x)>(y)) - ((x)<(y))) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) +#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c) + +#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0) +#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) + +#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24)) +#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24)) + +/** + * @addtogroup preproc_misc Preprocessor String Macros + * + * String manipulation macros + * + * @{ + */ + +#define AV_STRINGIFY(s) AV_TOSTRING(s) +#define AV_TOSTRING(s) #s + +#define AV_GLUE(a, b) a ## b +#define AV_JOIN(a, b) AV_GLUE(a, b) + +/** + * @} + */ + +#define AV_PRAGMA(s) _Pragma(#s) + +#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1)) + +#endif /* AVUTIL_MACROS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/mathematics.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/mathematics.h new file mode 100644 index 0000000000000..e213bab68c9c9 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/mathematics.h @@ -0,0 +1,300 @@ +/* + * copyright (c) 2005-2012 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @addtogroup lavu_math + * Mathematical utilities for working with timestamp and time base. + */ + +#ifndef AVUTIL_MATHEMATICS_H +#define AVUTIL_MATHEMATICS_H + +#include +#include +#include "attributes.h" +#include "rational.h" +#include "intfloat.h" + +#ifndef M_E +#define M_E 2.7182818284590452354 /* e */ +#endif +#ifndef M_Ef +#define M_Ef 2.7182818284590452354f /* e */ +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#endif +#ifndef M_LN2f +#define M_LN2f 0.69314718055994530942f /* log_e 2 */ +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#endif +#ifndef M_LN10f +#define M_LN10f 2.30258509299404568402f /* log_e 10 */ +#endif +#ifndef M_LOG2_10 +#define M_LOG2_10 3.32192809488736234787 /* log_2 10 */ +#endif +#ifndef M_LOG2_10f +#define M_LOG2_10f 3.32192809488736234787f /* log_2 10 */ +#endif +#ifndef M_PHI +#define M_PHI 1.61803398874989484820 /* phi / golden ratio */ +#endif +#ifndef M_PHIf +#define M_PHIf 1.61803398874989484820f /* phi / golden ratio */ +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif +#ifndef M_PIf +#define M_PIf 3.14159265358979323846f /* pi */ +#endif +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#endif +#ifndef M_PI_2f +#define M_PI_2f 1.57079632679489661923f /* pi/2 */ +#endif +#ifndef M_PI_4 +#define M_PI_4 0.78539816339744830962 /* pi/4 */ +#endif +#ifndef M_PI_4f +#define M_PI_4f 0.78539816339744830962f /* pi/4 */ +#endif +#ifndef M_1_PI +#define M_1_PI 0.31830988618379067154 /* 1/pi */ +#endif +#ifndef M_1_PIf +#define M_1_PIf 0.31830988618379067154f /* 1/pi */ +#endif +#ifndef M_2_PI +#define M_2_PI 0.63661977236758134308 /* 2/pi */ +#endif +#ifndef M_2_PIf +#define M_2_PIf 0.63661977236758134308f /* 2/pi */ +#endif +#ifndef M_2_SQRTPI +#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +#endif +#ifndef M_2_SQRTPIf +#define M_2_SQRTPIf 1.12837916709551257390f /* 2/sqrt(pi) */ +#endif +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif +#ifndef M_SQRT1_2f +#define M_SQRT1_2f 0.70710678118654752440f /* 1/sqrt(2) */ +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#endif +#ifndef M_SQRT2f +#define M_SQRT2f 1.41421356237309504880f /* sqrt(2) */ +#endif +#ifndef NAN +#define NAN av_int2float(0x7fc00000) +#endif +#ifndef INFINITY +#define INFINITY av_int2float(0x7f800000) +#endif + +/** + * @addtogroup lavu_math + * + * @{ + */ + +/** + * Rounding methods. + */ +enum AVRounding { + AV_ROUND_ZERO = 0, ///< Round toward zero. + AV_ROUND_INF = 1, ///< Round away from zero. + AV_ROUND_DOWN = 2, ///< Round toward -infinity. + AV_ROUND_UP = 3, ///< Round toward +infinity. + AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero. + /** + * Flag telling rescaling functions to pass `INT64_MIN`/`MAX` through + * unchanged, avoiding special cases for #AV_NOPTS_VALUE. + * + * Unlike other values of the enumeration AVRounding, this value is a + * bitmask that must be used in conjunction with another value of the + * enumeration through a bitwise OR, in order to set behavior for normal + * cases. + * + * @code{.c} + * av_rescale_rnd(3, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + * // Rescaling 3: + * // Calculating 3 * 1 / 2 + * // 3 / 2 is rounded up to 2 + * // => 2 + * + * av_rescale_rnd(AV_NOPTS_VALUE, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + * // Rescaling AV_NOPTS_VALUE: + * // AV_NOPTS_VALUE == INT64_MIN + * // AV_NOPTS_VALUE is passed through + * // => AV_NOPTS_VALUE + * @endcode + */ + AV_ROUND_PASS_MINMAX = 8192, +}; + +/** + * Compute the greatest common divisor of two integer operands. + * + * @param a Operand + * @param b Operand + * @return GCD of a and b up to sign; if a >= 0 and b >= 0, return value is >= 0; + * if a == 0 and b == 0, returns 0. + */ +int64_t av_const av_gcd(int64_t a, int64_t b); + +/** + * Rescale a 64-bit integer with rounding to nearest. + * + * The operation is mathematically equivalent to `a * b / c`, but writing that + * directly can overflow. + * + * This function is equivalent to av_rescale_rnd() with #AV_ROUND_NEAR_INF. + * + * @see av_rescale_rnd(), av_rescale_q(), av_rescale_q_rnd() + */ +int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const; + +/** + * Rescale a 64-bit integer with specified rounding. + * + * The operation is mathematically equivalent to `a * b / c`, but writing that + * directly can overflow, and does not support different rounding methods. + * If the result is not representable then INT64_MIN is returned. + * + * @see av_rescale(), av_rescale_q(), av_rescale_q_rnd() + */ +int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers. + * + * The operation is mathematically equivalent to `a * bq / cq`. + * + * This function is equivalent to av_rescale_q_rnd() with #AV_ROUND_NEAR_INF. + * + * @see av_rescale(), av_rescale_rnd(), av_rescale_q_rnd() + */ +int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers with specified rounding. + * + * The operation is mathematically equivalent to `a * bq / cq`. + * + * @see av_rescale(), av_rescale_rnd(), av_rescale_q() + */ +int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, + enum AVRounding rnd) av_const; + +/** + * Compare two timestamps each in its own time base. + * + * @return One of the following values: + * - -1 if `ts_a` is before `ts_b` + * - 1 if `ts_a` is after `ts_b` + * - 0 if they represent the same position + * + * @warning + * The result of the function is undefined if one of the timestamps is outside + * the `int64_t` range when represented in the other's timebase. + */ +int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b); + +/** + * Compare the remainders of two integer operands divided by a common divisor. + * + * In other words, compare the least significant `log2(mod)` bits of integers + * `a` and `b`. + * + * @code{.c} + * av_compare_mod(0x11, 0x02, 0x10) < 0 // since 0x11 % 0x10 (0x1) < 0x02 % 0x10 (0x2) + * av_compare_mod(0x11, 0x02, 0x20) > 0 // since 0x11 % 0x20 (0x11) > 0x02 % 0x20 (0x02) + * @endcode + * + * @param a Operand + * @param b Operand + * @param mod Divisor; must be a power of 2 + * @return + * - a negative value if `a % mod < b % mod` + * - a positive value if `a % mod > b % mod` + * - zero if `a % mod == b % mod` + */ +int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod); + +/** + * Rescale a timestamp while preserving known durations. + * + * This function is designed to be called per audio packet to scale the input + * timestamp to a different time base. Compared to a simple av_rescale_q() + * call, this function is robust against possible inconsistent frame durations. + * + * The `last` parameter is a state variable that must be preserved for all + * subsequent calls for the same stream. For the first call, `*last` should be + * initialized to #AV_NOPTS_VALUE. + * + * @param[in] in_tb Input time base + * @param[in] in_ts Input timestamp + * @param[in] fs_tb Duration time base; typically this is finer-grained + * (greater) than `in_tb` and `out_tb` + * @param[in] duration Duration till the next call to this function (i.e. + * duration of the current packet/frame) + * @param[in,out] last Pointer to a timestamp expressed in terms of + * `fs_tb`, acting as a state variable + * @param[in] out_tb Output timebase + * @return Timestamp expressed in terms of `out_tb` + * + * @note In the context of this function, "duration" is in term of samples, not + * seconds. + */ +int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb); + +/** + * Add a value to a timestamp. + * + * This function guarantees that when the same value is repeatly added that + * no accumulation of rounding errors occurs. + * + * @param[in] ts Input timestamp + * @param[in] ts_tb Input timestamp time base + * @param[in] inc Value to be added + * @param[in] inc_tb Time base of `inc` + */ +int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc); + +/** + * 0th order modified bessel function of the first kind. + */ +double av_bessel_i0(double x); + +/** + * @} + */ + +#endif /* AVUTIL_MATHEMATICS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/mem.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/mem.h new file mode 100644 index 0000000000000..ab7648ac5705f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/mem.h @@ -0,0 +1,607 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_mem + * Memory handling functions + */ + +#ifndef AVUTIL_MEM_H +#define AVUTIL_MEM_H + +#include +#include + +#include "attributes.h" + +/** + * @addtogroup lavu_mem + * Utilities for manipulating memory. + * + * FFmpeg has several applications of memory that are not required of a typical + * program. For example, the computing-heavy components like video decoding and + * encoding can be sped up significantly through the use of aligned memory. + * + * However, for each of FFmpeg's applications of memory, there might not be a + * recognized or standardized API for that specific use. Memory alignment, for + * instance, varies wildly depending on operating systems, architectures, and + * compilers. Hence, this component of @ref libavutil is created to make + * dealing with memory consistently possible on all platforms. + * + * @{ + */ + +/** + * @defgroup lavu_mem_attrs Function Attributes + * Function attributes applicable to memory handling functions. + * + * These function attributes can help compilers emit more useful warnings, or + * generate better code. + * @{ + */ + +/** + * @def av_malloc_attrib + * Function attribute denoting a malloc-like function. + * + * @see Function attribute `malloc` in GCC's documentation + */ + +#if AV_GCC_VERSION_AT_LEAST(3,1) + #define av_malloc_attrib __attribute__((__malloc__)) +#else + #define av_malloc_attrib +#endif + +/** + * @def av_alloc_size(...) + * Function attribute used on a function that allocates memory, whose size is + * given by the specified parameter(s). + * + * @code{.c} + * void *av_malloc(size_t size) av_alloc_size(1); + * void *av_calloc(size_t nmemb, size_t size) av_alloc_size(1, 2); + * @endcode + * + * @param ... One or two parameter indexes, separated by a comma + * + * @see Function attribute `alloc_size` in GCC's documentation + */ + +#if AV_GCC_VERSION_AT_LEAST(4,3) + #define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__))) +#else + #define av_alloc_size(...) +#endif + +/** + * @} + */ + +/** + * @defgroup lavu_mem_funcs Heap Management + * Functions responsible for allocating, freeing, and copying memory. + * + * All memory allocation functions have a built-in upper limit of `INT_MAX` + * bytes. This may be changed with av_max_alloc(), although exercise extreme + * caution when doing so. + * + * @{ + */ + +/** + * Allocate a memory block with alignment suitable for all memory accesses + * (including vectors if available on the CPU). + * + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * @see av_mallocz() + */ +void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a memory block with alignment suitable for all memory accesses + * (including vectors if available on the CPU) and zero all the bytes of the + * block. + * + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if it cannot be allocated + * @see av_malloc() + */ +void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a memory block for an array with av_malloc(). + * + * The allocated memory will have size `size * nmemb` bytes. + * + * @param nmemb Number of element + * @param size Size of a single element + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * @see av_malloc() + */ +av_alloc_size(1, 2) void *av_malloc_array(size_t nmemb, size_t size); + +/** + * Allocate a memory block for an array with av_mallocz(). + * + * The allocated memory will have size `size * nmemb` bytes. + * + * @param nmemb Number of elements + * @param size Size of the single element + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * + * @see av_mallocz() + * @see av_malloc_array() + */ +void *av_calloc(size_t nmemb, size_t size) av_malloc_attrib av_alloc_size(1, 2); + +/** + * Allocate, reallocate, or free a block of memory. + * + * If `ptr` is `NULL` and `size` > 0, allocate a new block. Otherwise, expand or + * shrink that block of memory according to `size`. + * + * @param ptr Pointer to a memory block already allocated with + * av_realloc() or `NULL` + * @param size Size in bytes of the memory block to be allocated or + * reallocated + * + * @return Pointer to a newly-reallocated block or `NULL` if the block + * cannot be reallocated + * + * @warning Unlike av_malloc(), the returned pointer is not guaranteed to be + * correctly aligned. The returned pointer must be freed after even + * if size is zero. + * @see av_fast_realloc() + * @see av_reallocp() + */ +void *av_realloc(void *ptr, size_t size) av_alloc_size(2); + +/** + * Allocate, reallocate, or free a block of memory through a pointer to a + * pointer. + * + * If `*ptr` is `NULL` and `size` > 0, allocate a new block. If `size` is + * zero, free the memory block pointed to by `*ptr`. Otherwise, expand or + * shrink that block of memory according to `size`. + * + * @param[in,out] ptr Pointer to a pointer to a memory block already allocated + * with av_realloc(), or a pointer to `NULL`. The pointer + * is updated on success, or freed on failure. + * @param[in] size Size in bytes for the memory block to be allocated or + * reallocated + * + * @return Zero on success, an AVERROR error code on failure + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. + */ +av_warn_unused_result +int av_reallocp(void *ptr, size_t size); + +/** + * Allocate, reallocate, or free a block of memory. + * + * This function does the same thing as av_realloc(), except: + * - It takes two size arguments and allocates `nelem * elsize` bytes, + * after checking the result of the multiplication for integer overflow. + * - It frees the input block in case of failure, thus avoiding the memory + * leak with the classic + * @code{.c} + * buf = realloc(buf); + * if (!buf) + * return -1; + * @endcode + * pattern. + */ +void *av_realloc_f(void *ptr, size_t nelem, size_t elsize); + +/** + * Allocate, reallocate, or free an array. + * + * If `ptr` is `NULL` and `nmemb` > 0, allocate a new block. + * + * @param ptr Pointer to a memory block already allocated with + * av_realloc() or `NULL` + * @param nmemb Number of elements in the array + * @param size Size of the single element of the array + * + * @return Pointer to a newly-reallocated block or NULL if the block + * cannot be reallocated + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. The returned pointer must be freed after even if + * nmemb is zero. + * @see av_reallocp_array() + */ +av_alloc_size(2, 3) void *av_realloc_array(void *ptr, size_t nmemb, size_t size); + +/** + * Allocate, reallocate an array through a pointer to a pointer. + * + * If `*ptr` is `NULL` and `nmemb` > 0, allocate a new block. + * + * @param[in,out] ptr Pointer to a pointer to a memory block already + * allocated with av_realloc(), or a pointer to `NULL`. + * The pointer is updated on success, or freed on failure. + * @param[in] nmemb Number of elements + * @param[in] size Size of the single element + * + * @return Zero on success, an AVERROR error code on failure + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. *ptr must be freed after even if nmemb is zero. + */ +int av_reallocp_array(void *ptr, size_t nmemb, size_t size); + +/** + * Reallocate the given buffer if it is not large enough, otherwise do nothing. + * + * If the given buffer is `NULL`, then a new uninitialized buffer is allocated. + * + * If the given buffer is not large enough, and reallocation fails, `NULL` is + * returned and `*size` is set to 0, but the original buffer is not changed or + * freed. + * + * A typical use pattern follows: + * + * @code{.c} + * uint8_t *buf = ...; + * uint8_t *new_buf = av_fast_realloc(buf, ¤t_size, size_needed); + * if (!new_buf) { + * // Allocation failed; clean up original buffer + * av_freep(&buf); + * return AVERROR(ENOMEM); + * } + * @endcode + * + * @param[in,out] ptr Already allocated buffer, or `NULL` + * @param[in,out] size Pointer to the size of buffer `ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `ptr` + * @return `ptr` if the buffer is large enough, a pointer to newly reallocated + * buffer if the buffer was not large enough, or `NULL` in case of + * error + * @see av_realloc() + * @see av_fast_malloc() + */ +void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate a buffer, reusing the given one if large enough. + * + * Contrary to av_fast_realloc(), the current buffer contents might not be + * preserved and on error the old buffer is freed, thus no special handling to + * avoid memleaks is necessary. + * + * `*ptr` is allowed to be `NULL`, in which case allocation always happens if + * `size_needed` is greater than 0. + * + * @code{.c} + * uint8_t *buf = ...; + * av_fast_malloc(&buf, ¤t_size, size_needed); + * if (!buf) { + * // Allocation failed; buf already freed + * return AVERROR(ENOMEM); + * } + * @endcode + * + * @param[in,out] ptr Pointer to pointer to an already allocated buffer. + * `*ptr` will be overwritten with pointer to new + * buffer on success or `NULL` on failure + * @param[in,out] size Pointer to the size of buffer `*ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `*ptr` + * @see av_realloc() + * @see av_fast_mallocz() + */ +void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate and clear a buffer, reusing the given one if large enough. + * + * Like av_fast_malloc(), but all newly allocated space is initially cleared. + * Reused buffer is not cleared. + * + * `*ptr` is allowed to be `NULL`, in which case allocation always happens if + * `size_needed` is greater than 0. + * + * @param[in,out] ptr Pointer to pointer to an already allocated buffer. + * `*ptr` will be overwritten with pointer to new + * buffer on success or `NULL` on failure + * @param[in,out] size Pointer to the size of buffer `*ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `*ptr` + * @see av_fast_malloc() + */ +void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * Free a memory block which has been allocated with a function of av_malloc() + * or av_realloc() family. + * + * @param ptr Pointer to the memory block which should be freed. + * + * @note `ptr = NULL` is explicitly allowed. + * @note It is recommended that you use av_freep() instead, to prevent leaving + * behind dangling pointers. + * @see av_freep() + */ +void av_free(void *ptr); + +/** + * Free a memory block which has been allocated with a function of av_malloc() + * or av_realloc() family, and set the pointer pointing to it to `NULL`. + * + * @code{.c} + * uint8_t *buf = av_malloc(16); + * av_free(buf); + * // buf now contains a dangling pointer to freed memory, and accidental + * // dereference of buf will result in a use-after-free, which may be a + * // security risk. + * + * uint8_t *buf = av_malloc(16); + * av_freep(&buf); + * // buf is now NULL, and accidental dereference will only result in a + * // NULL-pointer dereference. + * @endcode + * + * @param ptr Pointer to the pointer to the memory block which should be freed + * @note `*ptr = NULL` is safe and leads to no action. + * @see av_free() + */ +void av_freep(void *ptr); + +/** + * Duplicate a string. + * + * @param s String to be duplicated + * @return Pointer to a newly-allocated string containing a + * copy of `s` or `NULL` if the string cannot be allocated + * @see av_strndup() + */ +char *av_strdup(const char *s) av_malloc_attrib; + +/** + * Duplicate a substring of a string. + * + * @param s String to be duplicated + * @param len Maximum length of the resulting string (not counting the + * terminating byte) + * @return Pointer to a newly-allocated string containing a + * substring of `s` or `NULL` if the string cannot be allocated + */ +char *av_strndup(const char *s, size_t len) av_malloc_attrib; + +/** + * Duplicate a buffer with av_malloc(). + * + * @param p Buffer to be duplicated + * @param size Size in bytes of the buffer copied + * @return Pointer to a newly allocated buffer containing a + * copy of `p` or `NULL` if the buffer cannot be allocated + */ +void *av_memdup(const void *p, size_t size); + +/** + * Overlapping memcpy() implementation. + * + * @param dst Destination buffer + * @param back Number of bytes back to start copying (i.e. the initial size of + * the overlapping window); must be > 0 + * @param cnt Number of bytes to copy; must be >= 0 + * + * @note `cnt > back` is valid, this will copy the bytes we just copied, + * thus creating a repeating pattern with a period length of `back`. + */ +void av_memcpy_backptr(uint8_t *dst, int back, int cnt); + +/** + * @} + */ + +/** + * @defgroup lavu_mem_dynarray Dynamic Array + * + * Utilities to make an array grow when needed. + * + * Sometimes, the programmer would want to have an array that can grow when + * needed. The libavutil dynamic array utilities fill that need. + * + * libavutil supports two systems of appending elements onto a dynamically + * allocated array, the first one storing the pointer to the value in the + * array, and the second storing the value directly. In both systems, the + * caller is responsible for maintaining a variable containing the length of + * the array, as well as freeing of the array after use. + * + * The first system stores pointers to values in a block of dynamically + * allocated memory. Since only pointers are stored, the function does not need + * to know the size of the type. Both av_dynarray_add() and + * av_dynarray_add_nofree() implement this system. + * + * @code + * type **array = NULL; //< an array of pointers to values + * int nb = 0; //< a variable to keep track of the length of the array + * + * type to_be_added = ...; + * type to_be_added2 = ...; + * + * av_dynarray_add(&array, &nb, &to_be_added); + * if (nb == 0) + * return AVERROR(ENOMEM); + * + * av_dynarray_add(&array, &nb, &to_be_added2); + * if (nb == 0) + * return AVERROR(ENOMEM); + * + * // Now: + * // nb == 2 + * // &to_be_added == array[0] + * // &to_be_added2 == array[1] + * + * av_freep(&array); + * @endcode + * + * The second system stores the value directly in a block of memory. As a + * result, the function has to know the size of the type. av_dynarray2_add() + * implements this mechanism. + * + * @code + * type *array = NULL; //< an array of values + * int nb = 0; //< a variable to keep track of the length of the array + * + * type to_be_added = ...; + * type to_be_added2 = ...; + * + * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), NULL); + * if (!addr) + * return AVERROR(ENOMEM); + * memcpy(addr, &to_be_added, sizeof(to_be_added)); + * + * // Shortcut of the above. + * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), + * (const void *)&to_be_added2); + * if (!addr) + * return AVERROR(ENOMEM); + * + * // Now: + * // nb == 2 + * // to_be_added == array[0] + * // to_be_added2 == array[1] + * + * av_freep(&array); + * @endcode + * + * @{ + */ + +/** + * Add the pointer to an element to a dynamic array. + * + * The array to grow is supposed to be an array of pointers to + * structures, and the element to add must be a pointer to an already + * allocated structure. + * + * The array is reallocated when its size reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the number pointed to by `nb_ptr` + * is incremented. + * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and + * `*nb_ptr` is set to 0. + * + * @param[in,out] tab_ptr Pointer to the array to grow + * @param[in,out] nb_ptr Pointer to the number of elements in the array + * @param[in] elem Element to add + * @see av_dynarray_add_nofree(), av_dynarray2_add() + */ +void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element to a dynamic array. + * + * Function has the same functionality as av_dynarray_add(), + * but it doesn't free memory on fails. It returns error code + * instead and leave current buffer untouched. + * + * @return >=0 on success, negative otherwise + * @see av_dynarray_add(), av_dynarray2_add() + */ +av_warn_unused_result +int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element of size `elem_size` to a dynamic array. + * + * The array is reallocated when its number of elements reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the number pointed to by `nb_ptr` + * is incremented. + * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and + * `*nb_ptr` is set to 0. + * + * @param[in,out] tab_ptr Pointer to the array to grow + * @param[in,out] nb_ptr Pointer to the number of elements in the array + * @param[in] elem_size Size in bytes of an element in the array + * @param[in] elem_data Pointer to the data of the element to add. If + * `NULL`, the space of the newly added element is + * allocated but left uninitialized. + * + * @return Pointer to the data of the element to copy in the newly allocated + * space + * @see av_dynarray_add(), av_dynarray_add_nofree() + */ +void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, + const uint8_t *elem_data); + +/** + * @} + */ + +/** + * @defgroup lavu_mem_misc Miscellaneous Functions + * + * Other functions related to memory allocation. + * + * @{ + */ + +/** + * Multiply two `size_t` values checking for overflow. + * + * @param[in] a Operand of multiplication + * @param[in] b Operand of multiplication + * @param[out] r Pointer to the result of the operation + * @return 0 on success, AVERROR(EINVAL) on overflow + */ +int av_size_mult(size_t a, size_t b, size_t *r); + +/** + * Set the maximum size that may be allocated in one block. + * + * The value specified with this function is effective for all libavutil's @ref + * lavu_mem_funcs "heap management functions." + * + * By default, the max value is defined as `INT_MAX`. + * + * @param max Value to be set as the new maximum size + * + * @warning Exercise extreme caution when using this function. Don't touch + * this if you do not understand the full consequence of doing so. + */ +void av_max_alloc(size_t max); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_MEM_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/opt.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/opt.h new file mode 100644 index 0000000000000..461b5d3b6bb2a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/opt.h @@ -0,0 +1,891 @@ +/* + * AVOptions + * copyright (c) 2005 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_OPT_H +#define AVUTIL_OPT_H + +/** + * @file + * AVOptions + */ + +#include "rational.h" +#include "avutil.h" +#include "channel_layout.h" +#include "dict.h" +#include "log.h" +#include "pixfmt.h" +#include "samplefmt.h" + +/** + * @defgroup avoptions AVOptions + * @ingroup lavu_data + * @{ + * AVOptions provide a generic system to declare options on arbitrary structs + * ("objects"). An option can have a help text, a type and a range of possible + * values. Options may then be enumerated, read and written to. + * + * @section avoptions_implement Implementing AVOptions + * This section describes how to add AVOptions capabilities to a struct. + * + * All AVOptions-related information is stored in an AVClass. Therefore + * the first member of the struct should be a pointer to an AVClass describing it. + * The option field of the AVClass must be set to a NULL-terminated static array + * of AVOptions. Each AVOption must have a non-empty name, a type, a default + * value and for number-type AVOptions also a range of allowed values. It must + * also declare an offset in bytes from the start of the struct, where the field + * associated with this AVOption is located. Other fields in the AVOption struct + * should also be set when applicable, but are not required. + * + * The following example illustrates an AVOptions-enabled struct: + * @code + * typedef struct test_struct { + * const AVClass *class; + * int int_opt; + * char *str_opt; + * uint8_t *bin_opt; + * int bin_len; + * } test_struct; + * + * static const AVOption test_options[] = { + * { "test_int", "This is a test option of int type.", offsetof(test_struct, int_opt), + * AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX }, + * { "test_str", "This is a test option of string type.", offsetof(test_struct, str_opt), + * AV_OPT_TYPE_STRING }, + * { "test_bin", "This is a test option of binary type.", offsetof(test_struct, bin_opt), + * AV_OPT_TYPE_BINARY }, + * { NULL }, + * }; + * + * static const AVClass test_class = { + * .class_name = "test class", + * .item_name = av_default_item_name, + * .option = test_options, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * @endcode + * + * Next, when allocating your struct, you must ensure that the AVClass pointer + * is set to the correct value. Then, av_opt_set_defaults() can be called to + * initialize defaults. After that the struct is ready to be used with the + * AVOptions API. + * + * When cleaning up, you may use the av_opt_free() function to automatically + * free all the allocated string and binary options. + * + * Continuing with the above example: + * + * @code + * test_struct *alloc_test_struct(void) + * { + * test_struct *ret = av_mallocz(sizeof(*ret)); + * ret->class = &test_class; + * av_opt_set_defaults(ret); + * return ret; + * } + * void free_test_struct(test_struct **foo) + * { + * av_opt_free(*foo); + * av_freep(foo); + * } + * @endcode + * + * @subsection avoptions_implement_nesting Nesting + * It may happen that an AVOptions-enabled struct contains another + * AVOptions-enabled struct as a member (e.g. AVCodecContext in + * libavcodec exports generic options, while its priv_data field exports + * codec-specific options). In such a case, it is possible to set up the + * parent struct to export a child's options. To do that, simply + * implement AVClass.child_next() and AVClass.child_class_iterate() in the + * parent struct's AVClass. + * Assuming that the test_struct from above now also contains a + * child_struct field: + * + * @code + * typedef struct child_struct { + * AVClass *class; + * int flags_opt; + * } child_struct; + * static const AVOption child_opts[] = { + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX }, + * { NULL }, + * }; + * static const AVClass child_class = { + * .class_name = "child class", + * .item_name = av_default_item_name, + * .option = child_opts, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * + * void *child_next(void *obj, void *prev) + * { + * test_struct *t = obj; + * if (!prev && t->child_struct) + * return t->child_struct; + * return NULL + * } + * const AVClass child_class_iterate(void **iter) + * { + * const AVClass *c = *iter ? NULL : &child_class; + * *iter = (void*)(uintptr_t)c; + * return c; + * } + * @endcode + * Putting child_next() and child_class_iterate() as defined above into + * test_class will now make child_struct's options accessible through + * test_struct (again, proper setup as described above needs to be done on + * child_struct right after it is created). + * + * From the above example it might not be clear why both child_next() + * and child_class_iterate() are needed. The distinction is that child_next() + * iterates over actually existing objects, while child_class_iterate() + * iterates over all possible child classes. E.g. if an AVCodecContext + * was initialized to use a codec which has private options, then its + * child_next() will return AVCodecContext.priv_data and finish + * iterating. OTOH child_class_iterate() on AVCodecContext.av_class will + * iterate over all available codecs with private options. + * + * @subsection avoptions_implement_named_constants Named constants + * It is possible to create named constants for options. Simply set the unit + * field of the option the constants should apply to a string and + * create the constants themselves as options of type AV_OPT_TYPE_CONST + * with their unit field set to the same string. + * Their default_val field should contain the value of the named + * constant. + * For example, to add some named constants for the test_flags option + * above, put the following into the child_opts array: + * @code + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, "test_unit" }, + * { "flag1", "This is a flag with value 16", 0, AV_OPT_TYPE_CONST, { .i64 = 16 }, 0, 0, "test_unit" }, + * @endcode + * + * @section avoptions_use Using AVOptions + * This section deals with accessing options in an AVOptions-enabled struct. + * Such structs in FFmpeg are e.g. AVCodecContext in libavcodec or + * AVFormatContext in libavformat. + * + * @subsection avoptions_use_examine Examining AVOptions + * The basic functions for examining options are av_opt_next(), which iterates + * over all options defined for one object, and av_opt_find(), which searches + * for an option with the given name. + * + * The situation is more complicated with nesting. An AVOptions-enabled struct + * may have AVOptions-enabled children. Passing the AV_OPT_SEARCH_CHILDREN flag + * to av_opt_find() will make the function search children recursively. + * + * For enumerating there are basically two cases. The first is when you want to + * get all options that may potentially exist on the struct and its children + * (e.g. when constructing documentation). In that case you should call + * av_opt_child_class_iterate() recursively on the parent struct's AVClass. The + * second case is when you have an already initialized struct with all its + * children and you want to get all options that can be actually written or read + * from it. In that case you should call av_opt_child_next() recursively (and + * av_opt_next() on each result). + * + * @subsection avoptions_use_get_set Reading and writing AVOptions + * When setting options, you often have a string read directly from the + * user. In such a case, simply passing it to av_opt_set() is enough. For + * non-string type options, av_opt_set() will parse the string according to the + * option type. + * + * Similarly av_opt_get() will read any option type and convert it to a string + * which will be returned. Do not forget that the string is allocated, so you + * have to free it with av_free(). + * + * In some cases it may be more convenient to put all options into an + * AVDictionary and call av_opt_set_dict() on it. A specific case of this + * are the format/codec open functions in lavf/lavc which take a dictionary + * filled with option as a parameter. This makes it possible to set some options + * that cannot be set otherwise, since e.g. the input file format is not known + * before the file is actually opened. + */ + +enum AVOptionType{ + AV_OPT_TYPE_FLAGS, + AV_OPT_TYPE_INT, + AV_OPT_TYPE_INT64, + AV_OPT_TYPE_DOUBLE, + AV_OPT_TYPE_FLOAT, + AV_OPT_TYPE_STRING, + AV_OPT_TYPE_RATIONAL, + AV_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length + AV_OPT_TYPE_DICT, + AV_OPT_TYPE_UINT64, + AV_OPT_TYPE_CONST, + AV_OPT_TYPE_IMAGE_SIZE, ///< offset must point to two consecutive integers + AV_OPT_TYPE_PIXEL_FMT, + AV_OPT_TYPE_SAMPLE_FMT, + AV_OPT_TYPE_VIDEO_RATE, ///< offset must point to AVRational + AV_OPT_TYPE_DURATION, + AV_OPT_TYPE_COLOR, +#if FF_API_OLD_CHANNEL_LAYOUT + AV_OPT_TYPE_CHANNEL_LAYOUT, +#endif + AV_OPT_TYPE_BOOL, + AV_OPT_TYPE_CHLAYOUT, +}; + +/** + * AVOption + */ +typedef struct AVOption { + const char *name; + + /** + * short English help text + * @todo What about other languages? + */ + const char *help; + + /** + * The offset relative to the context structure where the option + * value is stored. It should be 0 for named constants. + */ + int offset; + enum AVOptionType type; + + /** + * the default value for scalar options + */ + union { + int64_t i64; + double dbl; + const char *str; + /* TODO those are unused now */ + AVRational q; + } default_val; + double min; ///< minimum valid value for the option + double max; ///< maximum valid value for the option + + int flags; +#define AV_OPT_FLAG_ENCODING_PARAM 1 ///< a generic parameter which can be set by the user for muxing or encoding +#define AV_OPT_FLAG_DECODING_PARAM 2 ///< a generic parameter which can be set by the user for demuxing or decoding +#define AV_OPT_FLAG_AUDIO_PARAM 8 +#define AV_OPT_FLAG_VIDEO_PARAM 16 +#define AV_OPT_FLAG_SUBTITLE_PARAM 32 +/** + * The option is intended for exporting values to the caller. + */ +#define AV_OPT_FLAG_EXPORT 64 +/** + * The option may not be set through the AVOptions API, only read. + * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set. + */ +#define AV_OPT_FLAG_READONLY 128 +#define AV_OPT_FLAG_BSF_PARAM (1<<8) ///< a generic parameter which can be set by the user for bit stream filtering +#define AV_OPT_FLAG_RUNTIME_PARAM (1<<15) ///< a generic parameter which can be set by the user at runtime +#define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering +#define AV_OPT_FLAG_DEPRECATED (1<<17) ///< set if option is deprecated, users should refer to AVOption.help text for more information +#define AV_OPT_FLAG_CHILD_CONSTS (1<<18) ///< set if option constants can also reside in child objects +//FIXME think about enc-audio, ... style flags + + /** + * The logical unit to which the option belongs. Non-constant + * options and corresponding named constants share the same + * unit. May be NULL. + */ + const char *unit; +} AVOption; + +/** + * A single allowed range of values, or a single allowed value. + */ +typedef struct AVOptionRange { + const char *str; + /** + * Value range. + * For string ranges this represents the min/max length. + * For dimensions this represents the min/max pixel count or width/height in multi-component case. + */ + double value_min, value_max; + /** + * Value's component range. + * For string this represents the unicode range for chars, 0-127 limits to ASCII. + */ + double component_min, component_max; + /** + * Range flag. + * If set to 1 the struct encodes a range, if set to 0 a single value. + */ + int is_range; +} AVOptionRange; + +/** + * List of AVOptionRange structs. + */ +typedef struct AVOptionRanges { + /** + * Array of option ranges. + * + * Most of option types use just one component. + * Following describes multi-component option types: + * + * AV_OPT_TYPE_IMAGE_SIZE: + * component index 0: range of pixel count (width * height). + * component index 1: range of width. + * component index 2: range of height. + * + * @note To obtain multi-component version of this structure, user must + * provide AV_OPT_MULTI_COMPONENT_RANGE to av_opt_query_ranges or + * av_opt_query_ranges_default function. + * + * Multi-component range can be read as in following example: + * + * @code + * int range_index, component_index; + * AVOptionRanges *ranges; + * AVOptionRange *range[3]; //may require more than 3 in the future. + * av_opt_query_ranges(&ranges, obj, key, AV_OPT_MULTI_COMPONENT_RANGE); + * for (range_index = 0; range_index < ranges->nb_ranges; range_index++) { + * for (component_index = 0; component_index < ranges->nb_components; component_index++) + * range[component_index] = ranges->range[ranges->nb_ranges * component_index + range_index]; + * //do something with range here. + * } + * av_opt_freep_ranges(&ranges); + * @endcode + */ + AVOptionRange **range; + /** + * Number of ranges per component. + */ + int nb_ranges; + /** + * Number of componentes. + */ + int nb_components; +} AVOptionRanges; + +/** + * Show the obj options. + * + * @param req_flags requested flags for the options to show. Show only the + * options for which it is opt->flags & req_flags. + * @param rej_flags rejected flags for the options to show. Show only the + * options for which it is !(opt->flags & req_flags). + * @param av_log_obj log context to use for showing the options + */ +int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); + +/** + * Set the values of all AVOption fields to their default values. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + */ +void av_opt_set_defaults(void *s); + +/** + * Set the values of all AVOption fields to their default values. Only these + * AVOption fields for which (opt->flags & mask) == flags will have their + * default applied to s. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + * @param mask combination of AV_OPT_FLAG_* + * @param flags combination of AV_OPT_FLAG_* + */ +void av_opt_set_defaults2(void *s, int mask, int flags); + +/** + * Parse the key/value pairs list in opts. For each key/value pair + * found, stores the value in the field in ctx that is named like the + * key. ctx must be an AVClass context, storing is done using + * AVOptions. + * + * @param opts options string to parse, may be NULL + * @param key_val_sep a 0-terminated list of characters used to + * separate key from value + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other + * @return the number of successfully set key/value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_opt_set() if a key/value pair + * cannot be set + */ +int av_set_options_string(void *ctx, const char *opts, + const char *key_val_sep, const char *pairs_sep); + +/** + * Parse the key-value pairs list in opts. For each key=value pair found, + * set the value of the corresponding option in ctx. + * + * @param ctx the AVClass object to set options on + * @param opts the options string, key-value pairs separated by a + * delimiter + * @param shorthand a NULL-terminated array of options names for shorthand + * notation: if the first field in opts has no key part, + * the key is taken from the first element of shorthand; + * then again for the second, etc., until either opts is + * finished, shorthand is finished or a named option is + * found; after that, all options must be named + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @return the number of successfully set key=value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_set_string3() if a key/value pair + * cannot be set + * + * Options names must use only the following characters: a-z A-Z 0-9 - . / _ + * Separators must use characters distinct from option names and from each + * other. + */ +int av_opt_set_from_string(void *ctx, const char *opts, + const char *const *shorthand, + const char *key_val_sep, const char *pairs_sep); +/** + * Free all allocated objects in obj. + */ +void av_opt_free(void *obj); + +/** + * Check whether a particular flag is set in a flags field. + * + * @param field_name the name of the flag field option + * @param flag_name the name of the flag to check + * @return non-zero if the flag is set, zero if the flag isn't set, + * isn't of the right type, or the flags field doesn't exist. + */ +int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name); + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict(void *obj, struct AVDictionary **options); + + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags); + +/** + * Extract a key-value pair from the beginning of a string. + * + * @param ropts pointer to the options string, will be updated to + * point to the rest of the string (one of the pairs_sep + * or the final NUL) + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @param flags flags; see the AV_OPT_FLAG_* values below + * @param rkey parsed key; must be freed using av_free() + * @param rval parsed value; must be freed using av_free() + * + * @return >=0 for success, or a negative value corresponding to an + * AVERROR code in case of error; in particular: + * AVERROR(EINVAL) if no key is present + * + */ +int av_opt_get_key_value(const char **ropts, + const char *key_val_sep, const char *pairs_sep, + unsigned flags, + char **rkey, char **rval); + +enum { + + /** + * Accept to parse a value without a key; the key will then be returned + * as NULL. + */ + AV_OPT_FLAG_IMPLICIT_KEY = 1, +}; + +/** + * @defgroup opt_eval_funcs Evaluating option strings + * @{ + * This group of functions can be used to evaluate option strings + * and get numbers out of them. They do the same thing as av_opt_set(), + * except the result is written into the caller-supplied pointer. + * + * @param obj a struct whose first element is a pointer to AVClass. + * @param o an option for which the string is to be evaluated. + * @param val string to be evaluated. + * @param *_out value of the string will be written here. + * + * @return 0 on success, a negative number on failure. + */ +int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out); +int av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out); +int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out); +int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out); +int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double *double_out); +int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out); +/** + * @} + */ + +#define AV_OPT_SEARCH_CHILDREN (1 << 0) /**< Search in possible children of the + given object first. */ +/** + * The obj passed to av_opt_find() is fake -- only a double pointer to AVClass + * instead of a required pointer to a struct containing AVClass. This is + * useful for searching for options without needing to allocate the corresponding + * object. + */ +#define AV_OPT_SEARCH_FAKE_OBJ (1 << 1) + +/** + * In av_opt_get, return NULL if the option has a pointer type and is set to NULL, + * rather than returning an empty string. + */ +#define AV_OPT_ALLOW_NULL (1 << 2) + +/** + * Allows av_opt_query_ranges and av_opt_query_ranges_default to return more than + * one component for certain option types. + * @see AVOptionRanges for details. + */ +#define AV_OPT_MULTI_COMPONENT_RANGE (1 << 12) + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return A pointer to the option found, or NULL if no option + * was found. + * + * @note Options found with AV_OPT_SEARCH_CHILDREN flag may not be settable + * directly with av_opt_set(). Use special calls which take an options + * AVDictionary (e.g. avformat_open_input()) to set options found with this + * flag. + */ +const AVOption *av_opt_find(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags); + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * @param[out] target_obj if non-NULL, an object to which the option belongs will be + * written here. It may be different from obj if AV_OPT_SEARCH_CHILDREN is present + * in search_flags. This parameter is ignored if search_flags contain + * AV_OPT_SEARCH_FAKE_OBJ. + * + * @return A pointer to the option found, or NULL if no option + * was found. + */ +const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags, void **target_obj); + +/** + * Iterate over all AVOptions belonging to obj. + * + * @param obj an AVOptions-enabled struct or a double pointer to an + * AVClass describing it. + * @param prev result of the previous call to av_opt_next() on this object + * or NULL + * @return next AVOption or NULL + */ +const AVOption *av_opt_next(const void *obj, const AVOption *prev); + +/** + * Iterate over AVOptions-enabled children of obj. + * + * @param prev result of a previous call to this function or NULL + * @return next AVOptions-enabled child or NULL + */ +void *av_opt_child_next(void *obj, void *prev); + +/** + * Iterate over potential AVOptions-enabled children of parent. + * + * @param iter a pointer where iteration state is stored. + * @return AVClass corresponding to next potential child or NULL + */ +const AVClass *av_opt_child_class_iterate(const AVClass *parent, void **iter); + +/** + * @defgroup opt_set_funcs Option setting functions + * @{ + * Those functions set the field of obj with the given name to value. + * + * @param[in] obj A struct whose first element is a pointer to an AVClass. + * @param[in] name the name of the field to set + * @param[in] val The value to set. In case of av_opt_set() if the field is not + * of a string type, then the given string is parsed. + * SI postfixes and some named scalars are supported. + * If the field is of a numeric type, it has to be a numeric or named + * scalar. Behavior with more than one scalar and +- infix operators + * is undefined. + * If the field is of a flags type, it has to be a sequence of numeric + * scalars or named flags separated by '+' or '-'. Prefixing a flag + * with '+' causes it to be set without affecting the other flags; + * similarly, '-' unsets a flag. + * If the field is of a dictionary type, it has to be a ':' separated list of + * key=value parameters. Values containing ':' special characters must be + * escaped. + * @param search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be set on a child of obj. + * + * @return 0 if the value has been set, or an AVERROR code in case of + * error: + * AVERROR_OPTION_NOT_FOUND if no matching option exists + * AVERROR(ERANGE) if the value is out of range + * AVERROR(EINVAL) if the value is not valid + */ +int av_opt_set (void *obj, const char *name, const char *val, int search_flags); +int av_opt_set_int (void *obj, const char *name, int64_t val, int search_flags); +int av_opt_set_double (void *obj, const char *name, double val, int search_flags); +int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags); +int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, int search_flags); +int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags); +int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags); +int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags); +int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags); +#if FF_API_OLD_CHANNEL_LAYOUT +attribute_deprecated +int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags); +#endif +int av_opt_set_chlayout(void *obj, const char *name, const AVChannelLayout *layout, int search_flags); +/** + * @note Any old dictionary present is discarded and replaced with a copy of the new one. The + * caller still owns val is and responsible for freeing it. + */ +int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags); + +/** + * Set a binary option to an integer list. + * + * @param obj AVClass object to set options on + * @param name name of the binary option + * @param val pointer to an integer list (must have the correct type with + * regard to the contents of the list) + * @param term list terminator (usually 0 or -1) + * @param flags search flags + */ +#define av_opt_set_int_list(obj, name, val, term, flags) \ + (av_int_list_length(val, term) > INT_MAX / sizeof(*(val)) ? \ + AVERROR(EINVAL) : \ + av_opt_set_bin(obj, name, (const uint8_t *)(val), \ + av_int_list_length(val, term) * sizeof(*(val)), flags)) + +/** + * @} + */ + +/** + * @defgroup opt_get_funcs Option getting functions + * @{ + * Those functions get a value of the option with the given name from an object. + * + * @param[in] obj a struct whose first element is a pointer to an AVClass. + * @param[in] name name of the option to get. + * @param[in] search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be found in a child of obj. + * @param[out] out_val value of the option will be written here + * @return >=0 on success, a negative error code otherwise + */ +/** + * @note the returned string will be av_malloc()ed and must be av_free()ed by the caller + * + * @note if AV_OPT_ALLOW_NULL is set in search_flags in av_opt_get, and the + * option is of type AV_OPT_TYPE_STRING, AV_OPT_TYPE_BINARY or AV_OPT_TYPE_DICT + * and is set to NULL, *out_val will be set to NULL instead of an allocated + * empty string. + */ +int av_opt_get (void *obj, const char *name, int search_flags, uint8_t **out_val); +int av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val); +int av_opt_get_double (void *obj, const char *name, int search_flags, double *out_val); +int av_opt_get_q (void *obj, const char *name, int search_flags, AVRational *out_val); +int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out); +int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt); +int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt); +int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val); +#if FF_API_OLD_CHANNEL_LAYOUT +attribute_deprecated +int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout); +#endif +int av_opt_get_chlayout(void *obj, const char *name, int search_flags, AVChannelLayout *layout); +/** + * @param[out] out_val The returned dictionary is a copy of the actual value and must + * be freed with av_dict_free() by the caller + */ +int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val); +/** + * @} + */ +/** + * Gets a pointer to the requested field in a struct. + * This function allows accessing a struct even when its fields are moved or + * renamed since the application making the access has been compiled, + * + * @returns a pointer to the field, it can be cast to the correct type and read + * or written to. + */ +void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name); + +/** + * Free an AVOptionRanges struct and set it to NULL. + */ +void av_opt_freep_ranges(AVOptionRanges **ranges); + +/** + * Get a list of allowed ranges for the given option. + * + * The returned list may depend on other fields in obj like for example profile. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_freep_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * Copy options from src object into dest object. + * + * The underlying AVClass of both src and dest must coincide. The guarantee + * below does not apply if this is not fulfilled. + * + * Options that require memory allocation (e.g. string or binary) are malloc'ed in dest object. + * Original memory allocated for such options is freed unless both src and dest options points to the same memory. + * + * Even on error it is guaranteed that allocated options from src and dest + * no longer alias each other afterwards; in particular calling av_opt_free() + * on both src and dest is safe afterwards if dest has been memdup'ed from src. + * + * @param dest Object to copy from + * @param src Object to copy into + * @return 0 on success, negative on error + */ +int av_opt_copy(void *dest, const void *src); + +/** + * Get a default list of allowed ranges for the given option. + * + * This list is constructed without using the AVClass.query_ranges() callback + * and can be used as fallback from within the callback. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_free_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * Check if given option is set to its default value. + * + * Options o must belong to the obj. This function must not be called to check child's options state. + * @see av_opt_is_set_to_default_by_name(). + * + * @param obj AVClass object to check option on + * @param o option to be checked + * @return >0 when option is set to its default, + * 0 when option is not set its default, + * <0 on error + */ +int av_opt_is_set_to_default(void *obj, const AVOption *o); + +/** + * Check if given option is set to its default value. + * + * @param obj AVClass object to check option on + * @param name option name + * @param search_flags combination of AV_OPT_SEARCH_* + * @return >0 when option is set to its default, + * 0 when option is not set its default, + * <0 on error + */ +int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags); + + +#define AV_OPT_SERIALIZE_SKIP_DEFAULTS 0x00000001 ///< Serialize options that are not set to default values only. +#define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT 0x00000002 ///< Serialize options that exactly match opt_flags only. + +/** + * Serialize object's options. + * + * Create a string containing object's serialized options. + * Such string may be passed back to av_opt_set_from_string() in order to restore option values. + * A key/value or pairs separator occurring in the serialized value or + * name string are escaped through the av_escape() function. + * + * @param[in] obj AVClass object to serialize + * @param[in] opt_flags serialize options with all the specified flags set (AV_OPT_FLAG) + * @param[in] flags combination of AV_OPT_SERIALIZE_* flags + * @param[out] buffer Pointer to buffer that will be allocated with string containg serialized options. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep character used to separate key from value + * @param[in] pairs_sep character used to separate two pairs from each other + * @return >= 0 on success, negative on error + * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same. + */ +int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, + const char key_val_sep, const char pairs_sep); +/** + * @} + */ + +#endif /* AVUTIL_OPT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/pixdesc.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/pixdesc.h new file mode 100644 index 0000000000000..0df73e6efe3b1 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/pixdesc.h @@ -0,0 +1,435 @@ +/* + * pixel format descriptor + * Copyright (c) 2009 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXDESC_H +#define AVUTIL_PIXDESC_H + +#include + +#include "attributes.h" +#include "pixfmt.h" + +typedef struct AVComponentDescriptor { + /** + * Which of the 4 planes contains the component. + */ + int plane; + + /** + * Number of elements between 2 horizontally consecutive pixels. + * Elements are bits for bitstream formats, bytes otherwise. + */ + int step; + + /** + * Number of elements before the component of the first pixel. + * Elements are bits for bitstream formats, bytes otherwise. + */ + int offset; + + /** + * Number of least significant bits that must be shifted away + * to get the value. + */ + int shift; + + /** + * Number of bits in the component. + */ + int depth; +} AVComponentDescriptor; + +/** + * Descriptor that unambiguously describes how the bits of a pixel are + * stored in the up to 4 data planes of an image. It also stores the + * subsampling factors and number of components. + * + * @note This is separate of the colorspace (RGB, YCbCr, YPbPr, JPEG-style YUV + * and all the YUV variants) AVPixFmtDescriptor just stores how values + * are stored not what these values represent. + */ +typedef struct AVPixFmtDescriptor { + const char *name; + uint8_t nb_components; ///< The number of components each pixel has, (1-4) + + /** + * Amount to shift the luma width right to find the chroma width. + * For YV12 this is 1 for example. + * chroma_width = AV_CEIL_RSHIFT(luma_width, log2_chroma_w) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_w; + + /** + * Amount to shift the luma height right to find the chroma height. + * For YV12 this is 1 for example. + * chroma_height= AV_CEIL_RSHIFT(luma_height, log2_chroma_h) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_h; + + /** + * Combination of AV_PIX_FMT_FLAG_... flags. + */ + uint64_t flags; + + /** + * Parameters that describe how pixels are packed. + * If the format has 1 or 2 components, then luma is 0. + * If the format has 3 or 4 components: + * if the RGB flag is set then 0 is red, 1 is green and 2 is blue; + * otherwise 0 is luma, 1 is chroma-U and 2 is chroma-V. + * + * If present, the Alpha channel is always the last component. + */ + AVComponentDescriptor comp[4]; + + /** + * Alternative comma-separated names. + */ + const char *alias; +} AVPixFmtDescriptor; + +/** + * Pixel format is big-endian. + */ +#define AV_PIX_FMT_FLAG_BE (1 << 0) +/** + * Pixel format has a palette in data[1], values are indexes in this palette. + */ +#define AV_PIX_FMT_FLAG_PAL (1 << 1) +/** + * All values of a component are bit-wise packed end to end. + */ +#define AV_PIX_FMT_FLAG_BITSTREAM (1 << 2) +/** + * Pixel format is an HW accelerated format. + */ +#define AV_PIX_FMT_FLAG_HWACCEL (1 << 3) +/** + * At least one pixel component is not in the first data plane. + */ +#define AV_PIX_FMT_FLAG_PLANAR (1 << 4) +/** + * The pixel format contains RGB-like data (as opposed to YUV/grayscale). + */ +#define AV_PIX_FMT_FLAG_RGB (1 << 5) + +/** + * The pixel format has an alpha channel. This is set on all formats that + * support alpha in some way, including AV_PIX_FMT_PAL8. The alpha is always + * straight, never pre-multiplied. + * + * If a codec or a filter does not support alpha, it should set all alpha to + * opaque, or use the equivalent pixel formats without alpha component, e.g. + * AV_PIX_FMT_RGB0 (or AV_PIX_FMT_RGB24 etc.) instead of AV_PIX_FMT_RGBA. + */ +#define AV_PIX_FMT_FLAG_ALPHA (1 << 7) + +/** + * The pixel format is following a Bayer pattern + */ +#define AV_PIX_FMT_FLAG_BAYER (1 << 8) + +/** + * The pixel format contains IEEE-754 floating point values. Precision (double, + * single, or half) should be determined by the pixel size (64, 32, or 16 bits). + */ +#define AV_PIX_FMT_FLAG_FLOAT (1 << 9) + +/** + * Return the number of bits per pixel used by the pixel format + * described by pixdesc. Note that this is not the same as the number + * of bits per sample. + * + * The returned number of bits refers to the number of bits actually + * used for storing the pixel information, that is padding bits are + * not counted. + */ +int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * Return the number of bits per pixel for the pixel format + * described by pixdesc, including any padding or unused bits. + */ +int av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * @return a pixel format descriptor for provided pixel format or NULL if + * this pixel format is unknown. + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt); + +/** + * Iterate over all pixel format descriptors known to libavutil. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_next(const AVPixFmtDescriptor *prev); + +/** + * @return an AVPixelFormat id described by desc, or AV_PIX_FMT_NONE if desc + * is not a valid pointer to a pixel format descriptor. + */ +enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); + +/** + * Utility function to access log2_chroma_w log2_chroma_h from + * the pixel format AVPixFmtDescriptor. + * + * @param[in] pix_fmt the pixel format + * @param[out] h_shift store log2_chroma_w (horizontal/width shift) + * @param[out] v_shift store log2_chroma_h (vertical/height shift) + * + * @return 0 on success, AVERROR(ENOSYS) on invalid or unknown pixel format + */ +int av_pix_fmt_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, + int *h_shift, int *v_shift); + +/** + * @return number of planes in pix_fmt, a negative AVERROR if pix_fmt is not a + * valid pixel format. + */ +int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt); + +/** + * @return the name for provided color range or NULL if unknown. + */ +const char *av_color_range_name(enum AVColorRange range); + +/** + * @return the AVColorRange value for name or an AVError if not found. + */ +int av_color_range_from_name(const char *name); + +/** + * @return the name for provided color primaries or NULL if unknown. + */ +const char *av_color_primaries_name(enum AVColorPrimaries primaries); + +/** + * @return the AVColorPrimaries value for name or an AVError if not found. + */ +int av_color_primaries_from_name(const char *name); + +/** + * @return the name for provided color transfer or NULL if unknown. + */ +const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer); + +/** + * @return the AVColorTransferCharacteristic value for name or an AVError if not found. + */ +int av_color_transfer_from_name(const char *name); + +/** + * @return the name for provided color space or NULL if unknown. + */ +const char *av_color_space_name(enum AVColorSpace space); + +/** + * @return the AVColorSpace value for name or an AVError if not found. + */ +int av_color_space_from_name(const char *name); + +/** + * @return the name for provided chroma location or NULL if unknown. + */ +const char *av_chroma_location_name(enum AVChromaLocation location); + +/** + * @return the AVChromaLocation value for name or an AVError if not found. + */ +int av_chroma_location_from_name(const char *name); + +/** + * Converts AVChromaLocation to swscale x/y chroma position. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + */ +int av_chroma_location_enum_to_pos(int *xpos, int *ypos, enum AVChromaLocation pos); + +/** + * Converts swscale x/y chroma position to AVChromaLocation. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + */ +enum AVChromaLocation av_chroma_location_pos_to_enum(int xpos, int ypos); + +/** + * Return the pixel format corresponding to name. + * + * If there is no pixel format with name name, then looks for a + * pixel format with the name corresponding to the native endian + * format of name. + * For example in a little-endian system, first looks for "gray16", + * then for "gray16le". + * + * Finally if no pixel format has been found, returns AV_PIX_FMT_NONE. + */ +enum AVPixelFormat av_get_pix_fmt(const char *name); + +/** + * Return the short name for a pixel format, NULL in case pix_fmt is + * unknown. + * + * @see av_get_pix_fmt(), av_get_pix_fmt_string() + */ +const char *av_get_pix_fmt_name(enum AVPixelFormat pix_fmt); + +/** + * Print in buf the string corresponding to the pixel format with + * number pix_fmt, or a header if pix_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param pix_fmt the number of the pixel format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + */ +char *av_get_pix_fmt_string(char *buf, int buf_size, + enum AVPixelFormat pix_fmt); + +/** + * Read a line from an image, and write the values of the + * pixel format component c to dst. + * + * @param data the array containing the pointers to the planes of the image + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to read + * @param y the vertical coordinate of the first pixel to read + * @param w the width of the line to read, that is the number of + * values to write to dst + * @param read_pal_component if not zero and the format is a paletted + * format writes the values corresponding to the palette + * component c in data[1] to dst, rather than the palette indexes in + * data[0]. The behavior is undefined if the format is not paletted. + * @param dst_element_size size of elements in dst array (2 or 4 byte) + */ +void av_read_image_line2(void *dst, const uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int read_pal_component, + int dst_element_size); + +void av_read_image_line(uint16_t *dst, const uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int read_pal_component); + +/** + * Write the values from src to the pixel format component c of an + * image line. + * + * @param src array containing the values to write + * @param data the array containing the pointers to the planes of the + * image to write into. It is supposed to be zeroed. + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to write + * @param y the vertical coordinate of the first pixel to write + * @param w the width of the line to write, that is the number of + * values to write to the image line + * @param src_element_size size of elements in src array (2 or 4 byte) + */ +void av_write_image_line2(const void *src, uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int src_element_size); + +void av_write_image_line(const uint16_t *src, uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w); + +/** + * Utility function to swap the endianness of a pixel format. + * + * @param[in] pix_fmt the pixel format + * + * @return pixel format with swapped endianness if it exists, + * otherwise AV_PIX_FMT_NONE + */ +enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt); + +#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ +#define FF_LOSS_EXCESS_RESOLUTION 0x0040 /**< loss due to unneeded extra resolution */ +#define FF_LOSS_EXCESS_DEPTH 0x0080 /**< loss due to unneeded extra color depth */ + + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + int has_alpha); + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); + +#endif /* AVUTIL_PIXDESC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/pixfmt.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/pixfmt.h new file mode 100644 index 0000000000000..a26c72d56be52 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/pixfmt.h @@ -0,0 +1,703 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXFMT_H +#define AVUTIL_PIXFMT_H + +/** + * @file + * pixel format definitions + */ + +#include "libavutil/avconfig.h" +#include "version.h" + +#define AVPALETTE_SIZE 1024 +#define AVPALETTE_COUNT 256 + +/** + * Pixel format. + * + * @note + * AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA + * color is put together as: + * (A << 24) | (R << 16) | (G << 8) | B + * This is stored as BGRA on little-endian CPU architectures and ARGB on + * big-endian CPUs. + * + * @note + * If the resolution is not a multiple of the chroma subsampling factor + * then the chroma plane resolution must be rounded up. + * + * @par + * When the pixel format is palettized RGB32 (AV_PIX_FMT_PAL8), the palettized + * image data is stored in AVFrame.data[0]. The palette is transported in + * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is + * formatted the same as in AV_PIX_FMT_RGB32 described above (i.e., it is + * also endian-specific). Note also that the individual RGB32 palette + * components stored in AVFrame.data[1] should be in the range 0..255. + * This is important as many custom PAL8 video codecs that were designed + * to run on the IBM VGA graphics adapter use 6-bit palette components. + * + * @par + * For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like + * for pal8. This palette is filled in automatically by the function + * allocating the picture. + */ +enum AVPixelFormat { + AV_PIX_FMT_NONE = -1, + AV_PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) + AV_PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr + AV_PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB... + AV_PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR... + AV_PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) + AV_PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples) + AV_PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) + AV_PIX_FMT_GRAY8, ///< Y , 8bpp + AV_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_PAL8, ///< 8 bits with AV_PIX_FMT_RGB32 palette + AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range + AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range + AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range + AV_PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 + AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 + AV_PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) + AV_PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb) + AV_PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb) + AV_PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) + AV_PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV21, ///< as above, but U and V bytes are swapped + + AV_PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... + AV_PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA... + AV_PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR... + AV_PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA... + + AV_PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian + AV_PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian + AV_PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) + AV_PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range + AV_PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) + AV_PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian + + AV_PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian + AV_PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian + AV_PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined + + AV_PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian + AV_PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian + AV_PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined + + /** + * Hardware acceleration through VA-API, data[3] contains a + * VASurfaceID. + */ + AV_PIX_FMT_VAAPI, + + AV_PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer + + AV_PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_YA8, ///< 8 bits gray, 8 bits alpha + + AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + AV_PIX_FMT_GRAY8A= AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + + AV_PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian + + /** + * The following 12 formats have the disadvantage of needing 1 format for each bit depth. + * Notice that each 9/10 bits sample is stored in 16 bits with extra padding. + * If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better. + */ + AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp + AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP + AV_PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big-endian + AV_PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little-endian + AV_PIX_FMT_GBRP10BE, ///< planar GBR 4:4:4 30bpp, big-endian + AV_PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little-endian + AV_PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little-endian + AV_PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + AV_PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + AV_PIX_FMT_YUVA420P9BE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian + AV_PIX_FMT_YUVA420P9LE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian + AV_PIX_FMT_YUVA422P9BE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA422P9LE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA444P9BE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA444P9LE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA420P10BE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P10LE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P10BE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P10LE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P10BE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P10LE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA420P16BE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P16LE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P16BE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P16LE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P16BE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P16LE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + + AV_PIX_FMT_VDPAU, ///< HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface + + AV_PIX_FMT_XYZ12LE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_XYZ12BE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_NV16, ///< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_NV20LE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_NV20BE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + + AV_PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + + AV_PIX_FMT_YVYU422, ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb + + AV_PIX_FMT_YA16BE, ///< 16 bits gray, 16 bits alpha (big-endian) + AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian) + + AV_PIX_FMT_GBRAP, ///< planar GBRA 4:4:4:4 32bpp + AV_PIX_FMT_GBRAP16BE, ///< planar GBRA 4:4:4:4 64bpp, big-endian + AV_PIX_FMT_GBRAP16LE, ///< planar GBRA 4:4:4:4 64bpp, little-endian + /** + * HW acceleration through QSV, data[3] contains a pointer to the + * mfxFrameSurface1 structure. + * + * Before FFmpeg 5.0: + * mfxFrameSurface1.Data.MemId contains a pointer when importing + * the following frames as QSV frames: + * + * VAAPI: + * mfxFrameSurface1.Data.MemId contains a pointer to VASurfaceID + * + * DXVA2: + * mfxFrameSurface1.Data.MemId contains a pointer to IDirect3DSurface9 + * + * FFmpeg 5.0 and above: + * mfxFrameSurface1.Data.MemId contains a pointer to the mfxHDLPair + * structure when importing the following frames as QSV frames: + * + * VAAPI: + * mfxHDLPair.first contains a VASurfaceID pointer. + * mfxHDLPair.second is always MFX_INFINITE. + * + * DXVA2: + * mfxHDLPair.first contains IDirect3DSurface9 pointer. + * mfxHDLPair.second is always MFX_INFINITE. + * + * D3D11: + * mfxHDLPair.first contains a ID3D11Texture2D pointer. + * mfxHDLPair.second contains the texture array index of the frame if the + * ID3D11Texture2D is an array texture, or always MFX_INFINITE if it is a + * normal texture. + */ + AV_PIX_FMT_QSV, + /** + * HW acceleration though MMAL, data[3] contains a pointer to the + * MMAL_BUFFER_HEADER_T structure. + */ + AV_PIX_FMT_MMAL, + + AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer + + /** + * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers + * exactly as for system memory frames. + */ + AV_PIX_FMT_CUDA, + + AV_PIX_FMT_0RGB, ///< packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined + AV_PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined + AV_PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined + AV_PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined + + AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_GBRP12BE, ///< planar GBR 4:4:4 36bpp, big-endian + AV_PIX_FMT_GBRP12LE, ///< planar GBR 4:4:4 36bpp, little-endian + AV_PIX_FMT_GBRP14BE, ///< planar GBR 4:4:4 42bpp, big-endian + AV_PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little-endian + AV_PIX_FMT_YUVJ411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV411P and setting color_range + + AV_PIX_FMT_BAYER_BGGR8, ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples + AV_PIX_FMT_BAYER_RGGB8, ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples + AV_PIX_FMT_BAYER_GBRG8, ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples + AV_PIX_FMT_BAYER_GRBG8, ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples + AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian + +#if FF_API_XVMC + AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing +#endif + + AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_YUV440P12LE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P12BE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_AYUV64LE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_AYUV64BE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + + AV_PIX_FMT_VIDEOTOOLBOX, ///< hardware decoding through Videotoolbox + + AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian + AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian + + AV_PIX_FMT_GBRAP12BE, ///< planar GBR 4:4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRAP12LE, ///< planar GBR 4:4:4:4 48bpp, little-endian + + AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian + AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian + + AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec + + AV_PIX_FMT_GRAY12BE, ///< Y , 12bpp, big-endian + AV_PIX_FMT_GRAY12LE, ///< Y , 12bpp, little-endian + AV_PIX_FMT_GRAY10BE, ///< Y , 10bpp, big-endian + AV_PIX_FMT_GRAY10LE, ///< Y , 10bpp, little-endian + + AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian + AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian + + /** + * Hardware surfaces for Direct3D11. + * + * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11 + * hwaccel API and filtering support AV_PIX_FMT_D3D11 only. + * + * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the + * texture array index of the frame as intptr_t if the ID3D11Texture2D is + * an array texture (or always 0 if it's a normal texture). + */ + AV_PIX_FMT_D3D11, + + AV_PIX_FMT_GRAY9BE, ///< Y , 9bpp, big-endian + AV_PIX_FMT_GRAY9LE, ///< Y , 9bpp, little-endian + + AV_PIX_FMT_GBRPF32BE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, big-endian + AV_PIX_FMT_GBRPF32LE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, little-endian + AV_PIX_FMT_GBRAPF32BE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian + AV_PIX_FMT_GBRAPF32LE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian + + /** + * DRM-managed buffers exposed through PRIME buffer sharing. + * + * data[0] points to an AVDRMFrameDescriptor. + */ + AV_PIX_FMT_DRM_PRIME, + /** + * Hardware surfaces for OpenCL. + * + * data[i] contain 2D image objects (typed in C as cl_mem, used + * in OpenCL as image2d_t) for each plane of the surface. + */ + AV_PIX_FMT_OPENCL, + + AV_PIX_FMT_GRAY14BE, ///< Y , 14bpp, big-endian + AV_PIX_FMT_GRAY14LE, ///< Y , 14bpp, little-endian + + AV_PIX_FMT_GRAYF32BE, ///< IEEE-754 single precision Y, 32bpp, big-endian + AV_PIX_FMT_GRAYF32LE, ///< IEEE-754 single precision Y, 32bpp, little-endian + + AV_PIX_FMT_YUVA422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, little-endian + AV_PIX_FMT_YUVA444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, little-endian + + AV_PIX_FMT_NV24, ///< planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV42, ///< as above, but U and V bytes are swapped + + /** + * Vulkan hardware images. + * + * data[0] points to an AVVkFrame + */ + AV_PIX_FMT_VULKAN, + + AV_PIX_FMT_Y210BE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_Y210LE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, little-endian + + AV_PIX_FMT_X2RGB10LE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_X2RGB10BE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_X2BGR10LE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_X2BGR10BE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), big-endian, X=unused/undefined + + AV_PIX_FMT_P210BE, ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_P210LE, ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, little-endian + + AV_PIX_FMT_P410BE, ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, big-endian + AV_PIX_FMT_P410LE, ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, little-endian + + AV_PIX_FMT_P216BE, ///< interleaved chroma YUV 4:2:2, 32bpp, big-endian + AV_PIX_FMT_P216LE, ///< interleaved chroma YUV 4:2:2, 32bpp, little-endian + + AV_PIX_FMT_P416BE, ///< interleaved chroma YUV 4:4:4, 48bpp, big-endian + AV_PIX_FMT_P416LE, ///< interleaved chroma YUV 4:4:4, 48bpp, little-endian + + AV_PIX_FMT_VUYA, ///< packed VUYA 4:4:4, 32bpp, VUYAVUYA... + + AV_PIX_FMT_RGBAF16BE, ///< IEEE-754 half precision packed RGBA 16:16:16:16, 64bpp, RGBARGBA..., big-endian + AV_PIX_FMT_RGBAF16LE, ///< IEEE-754 half precision packed RGBA 16:16:16:16, 64bpp, RGBARGBA..., little-endian + + AV_PIX_FMT_VUYX, ///< packed VUYX 4:4:4, 32bpp, Variant of VUYA where alpha channel is left undefined + + AV_PIX_FMT_P012LE, ///< like NV12, with 12bpp per component, data in the high bits, zeros in the low bits, little-endian + AV_PIX_FMT_P012BE, ///< like NV12, with 12bpp per component, data in the high bits, zeros in the low bits, big-endian + + AV_PIX_FMT_Y212BE, ///< packed YUV 4:2:2 like YUYV422, 24bpp, data in the high bits, zeros in the low bits, big-endian + AV_PIX_FMT_Y212LE, ///< packed YUV 4:2:2 like YUYV422, 24bpp, data in the high bits, zeros in the low bits, little-endian + + AV_PIX_FMT_XV30BE, ///< packed XVYU 4:4:4, 32bpp, (msb)2X 10V 10Y 10U(lsb), big-endian, variant of Y410 where alpha channel is left undefined + AV_PIX_FMT_XV30LE, ///< packed XVYU 4:4:4, 32bpp, (msb)2X 10V 10Y 10U(lsb), little-endian, variant of Y410 where alpha channel is left undefined + + AV_PIX_FMT_XV36BE, ///< packed XVYU 4:4:4, 48bpp, data in the high bits, zeros in the low bits, big-endian, variant of Y412 where alpha channel is left undefined + AV_PIX_FMT_XV36LE, ///< packed XVYU 4:4:4, 48bpp, data in the high bits, zeros in the low bits, little-endian, variant of Y412 where alpha channel is left undefined + + AV_PIX_FMT_RGBF32BE, ///< IEEE-754 single precision packed RGB 32:32:32, 96bpp, RGBRGB..., big-endian + AV_PIX_FMT_RGBF32LE, ///< IEEE-754 single precision packed RGB 32:32:32, 96bpp, RGBRGB..., little-endian + + AV_PIX_FMT_RGBAF32BE, ///< IEEE-754 single precision packed RGBA 32:32:32:32, 128bpp, RGBARGBA..., big-endian + AV_PIX_FMT_RGBAF32LE, ///< IEEE-754 single precision packed RGBA 32:32:32:32, 128bpp, RGBARGBA..., little-endian + + AV_PIX_FMT_P212BE, ///< interleaved chroma YUV 4:2:2, 24bpp, data in the high bits, big-endian + AV_PIX_FMT_P212LE, ///< interleaved chroma YUV 4:2:2, 24bpp, data in the high bits, little-endian + + AV_PIX_FMT_P412BE, ///< interleaved chroma YUV 4:4:4, 36bpp, data in the high bits, big-endian + AV_PIX_FMT_P412LE, ///< interleaved chroma YUV 4:4:4, 36bpp, data in the high bits, little-endian + + AV_PIX_FMT_GBRAP14BE, ///< planar GBR 4:4:4:4 56bpp, big-endian + AV_PIX_FMT_GBRAP14LE, ///< planar GBR 4:4:4:4 56bpp, little-endian + + AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions +}; + +#if AV_HAVE_BIGENDIAN +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##be +#else +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##le +#endif + +#define AV_PIX_FMT_RGB32 AV_PIX_FMT_NE(ARGB, BGRA) +#define AV_PIX_FMT_RGB32_1 AV_PIX_FMT_NE(RGBA, ABGR) +#define AV_PIX_FMT_BGR32 AV_PIX_FMT_NE(ABGR, RGBA) +#define AV_PIX_FMT_BGR32_1 AV_PIX_FMT_NE(BGRA, ARGB) +#define AV_PIX_FMT_0RGB32 AV_PIX_FMT_NE(0RGB, BGR0) +#define AV_PIX_FMT_0BGR32 AV_PIX_FMT_NE(0BGR, RGB0) + +#define AV_PIX_FMT_GRAY9 AV_PIX_FMT_NE(GRAY9BE, GRAY9LE) +#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE) +#define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE) +#define AV_PIX_FMT_GRAY14 AV_PIX_FMT_NE(GRAY14BE, GRAY14LE) +#define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE) +#define AV_PIX_FMT_YA16 AV_PIX_FMT_NE(YA16BE, YA16LE) +#define AV_PIX_FMT_RGB48 AV_PIX_FMT_NE(RGB48BE, RGB48LE) +#define AV_PIX_FMT_RGB565 AV_PIX_FMT_NE(RGB565BE, RGB565LE) +#define AV_PIX_FMT_RGB555 AV_PIX_FMT_NE(RGB555BE, RGB555LE) +#define AV_PIX_FMT_RGB444 AV_PIX_FMT_NE(RGB444BE, RGB444LE) +#define AV_PIX_FMT_RGBA64 AV_PIX_FMT_NE(RGBA64BE, RGBA64LE) +#define AV_PIX_FMT_BGR48 AV_PIX_FMT_NE(BGR48BE, BGR48LE) +#define AV_PIX_FMT_BGR565 AV_PIX_FMT_NE(BGR565BE, BGR565LE) +#define AV_PIX_FMT_BGR555 AV_PIX_FMT_NE(BGR555BE, BGR555LE) +#define AV_PIX_FMT_BGR444 AV_PIX_FMT_NE(BGR444BE, BGR444LE) +#define AV_PIX_FMT_BGRA64 AV_PIX_FMT_NE(BGRA64BE, BGRA64LE) + +#define AV_PIX_FMT_YUV420P9 AV_PIX_FMT_NE(YUV420P9BE , YUV420P9LE) +#define AV_PIX_FMT_YUV422P9 AV_PIX_FMT_NE(YUV422P9BE , YUV422P9LE) +#define AV_PIX_FMT_YUV444P9 AV_PIX_FMT_NE(YUV444P9BE , YUV444P9LE) +#define AV_PIX_FMT_YUV420P10 AV_PIX_FMT_NE(YUV420P10BE, YUV420P10LE) +#define AV_PIX_FMT_YUV422P10 AV_PIX_FMT_NE(YUV422P10BE, YUV422P10LE) +#define AV_PIX_FMT_YUV440P10 AV_PIX_FMT_NE(YUV440P10BE, YUV440P10LE) +#define AV_PIX_FMT_YUV444P10 AV_PIX_FMT_NE(YUV444P10BE, YUV444P10LE) +#define AV_PIX_FMT_YUV420P12 AV_PIX_FMT_NE(YUV420P12BE, YUV420P12LE) +#define AV_PIX_FMT_YUV422P12 AV_PIX_FMT_NE(YUV422P12BE, YUV422P12LE) +#define AV_PIX_FMT_YUV440P12 AV_PIX_FMT_NE(YUV440P12BE, YUV440P12LE) +#define AV_PIX_FMT_YUV444P12 AV_PIX_FMT_NE(YUV444P12BE, YUV444P12LE) +#define AV_PIX_FMT_YUV420P14 AV_PIX_FMT_NE(YUV420P14BE, YUV420P14LE) +#define AV_PIX_FMT_YUV422P14 AV_PIX_FMT_NE(YUV422P14BE, YUV422P14LE) +#define AV_PIX_FMT_YUV444P14 AV_PIX_FMT_NE(YUV444P14BE, YUV444P14LE) +#define AV_PIX_FMT_YUV420P16 AV_PIX_FMT_NE(YUV420P16BE, YUV420P16LE) +#define AV_PIX_FMT_YUV422P16 AV_PIX_FMT_NE(YUV422P16BE, YUV422P16LE) +#define AV_PIX_FMT_YUV444P16 AV_PIX_FMT_NE(YUV444P16BE, YUV444P16LE) + +#define AV_PIX_FMT_GBRP9 AV_PIX_FMT_NE(GBRP9BE , GBRP9LE) +#define AV_PIX_FMT_GBRP10 AV_PIX_FMT_NE(GBRP10BE, GBRP10LE) +#define AV_PIX_FMT_GBRP12 AV_PIX_FMT_NE(GBRP12BE, GBRP12LE) +#define AV_PIX_FMT_GBRP14 AV_PIX_FMT_NE(GBRP14BE, GBRP14LE) +#define AV_PIX_FMT_GBRP16 AV_PIX_FMT_NE(GBRP16BE, GBRP16LE) +#define AV_PIX_FMT_GBRAP10 AV_PIX_FMT_NE(GBRAP10BE, GBRAP10LE) +#define AV_PIX_FMT_GBRAP12 AV_PIX_FMT_NE(GBRAP12BE, GBRAP12LE) +#define AV_PIX_FMT_GBRAP14 AV_PIX_FMT_NE(GBRAP14BE, GBRAP14LE) +#define AV_PIX_FMT_GBRAP16 AV_PIX_FMT_NE(GBRAP16BE, GBRAP16LE) + +#define AV_PIX_FMT_BAYER_BGGR16 AV_PIX_FMT_NE(BAYER_BGGR16BE, BAYER_BGGR16LE) +#define AV_PIX_FMT_BAYER_RGGB16 AV_PIX_FMT_NE(BAYER_RGGB16BE, BAYER_RGGB16LE) +#define AV_PIX_FMT_BAYER_GBRG16 AV_PIX_FMT_NE(BAYER_GBRG16BE, BAYER_GBRG16LE) +#define AV_PIX_FMT_BAYER_GRBG16 AV_PIX_FMT_NE(BAYER_GRBG16BE, BAYER_GRBG16LE) + +#define AV_PIX_FMT_GBRPF32 AV_PIX_FMT_NE(GBRPF32BE, GBRPF32LE) +#define AV_PIX_FMT_GBRAPF32 AV_PIX_FMT_NE(GBRAPF32BE, GBRAPF32LE) + +#define AV_PIX_FMT_GRAYF32 AV_PIX_FMT_NE(GRAYF32BE, GRAYF32LE) + +#define AV_PIX_FMT_YUVA420P9 AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE) +#define AV_PIX_FMT_YUVA422P9 AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE) +#define AV_PIX_FMT_YUVA444P9 AV_PIX_FMT_NE(YUVA444P9BE , YUVA444P9LE) +#define AV_PIX_FMT_YUVA420P10 AV_PIX_FMT_NE(YUVA420P10BE, YUVA420P10LE) +#define AV_PIX_FMT_YUVA422P10 AV_PIX_FMT_NE(YUVA422P10BE, YUVA422P10LE) +#define AV_PIX_FMT_YUVA444P10 AV_PIX_FMT_NE(YUVA444P10BE, YUVA444P10LE) +#define AV_PIX_FMT_YUVA422P12 AV_PIX_FMT_NE(YUVA422P12BE, YUVA422P12LE) +#define AV_PIX_FMT_YUVA444P12 AV_PIX_FMT_NE(YUVA444P12BE, YUVA444P12LE) +#define AV_PIX_FMT_YUVA420P16 AV_PIX_FMT_NE(YUVA420P16BE, YUVA420P16LE) +#define AV_PIX_FMT_YUVA422P16 AV_PIX_FMT_NE(YUVA422P16BE, YUVA422P16LE) +#define AV_PIX_FMT_YUVA444P16 AV_PIX_FMT_NE(YUVA444P16BE, YUVA444P16LE) + +#define AV_PIX_FMT_XYZ12 AV_PIX_FMT_NE(XYZ12BE, XYZ12LE) +#define AV_PIX_FMT_NV20 AV_PIX_FMT_NE(NV20BE, NV20LE) +#define AV_PIX_FMT_AYUV64 AV_PIX_FMT_NE(AYUV64BE, AYUV64LE) +#define AV_PIX_FMT_P010 AV_PIX_FMT_NE(P010BE, P010LE) +#define AV_PIX_FMT_P012 AV_PIX_FMT_NE(P012BE, P012LE) +#define AV_PIX_FMT_P016 AV_PIX_FMT_NE(P016BE, P016LE) + +#define AV_PIX_FMT_Y210 AV_PIX_FMT_NE(Y210BE, Y210LE) +#define AV_PIX_FMT_Y212 AV_PIX_FMT_NE(Y212BE, Y212LE) +#define AV_PIX_FMT_XV30 AV_PIX_FMT_NE(XV30BE, XV30LE) +#define AV_PIX_FMT_XV36 AV_PIX_FMT_NE(XV36BE, XV36LE) +#define AV_PIX_FMT_X2RGB10 AV_PIX_FMT_NE(X2RGB10BE, X2RGB10LE) +#define AV_PIX_FMT_X2BGR10 AV_PIX_FMT_NE(X2BGR10BE, X2BGR10LE) + +#define AV_PIX_FMT_P210 AV_PIX_FMT_NE(P210BE, P210LE) +#define AV_PIX_FMT_P410 AV_PIX_FMT_NE(P410BE, P410LE) +#define AV_PIX_FMT_P212 AV_PIX_FMT_NE(P212BE, P212LE) +#define AV_PIX_FMT_P412 AV_PIX_FMT_NE(P412BE, P412LE) +#define AV_PIX_FMT_P216 AV_PIX_FMT_NE(P216BE, P216LE) +#define AV_PIX_FMT_P416 AV_PIX_FMT_NE(P416BE, P416LE) + +#define AV_PIX_FMT_RGBAF16 AV_PIX_FMT_NE(RGBAF16BE, RGBAF16LE) + +#define AV_PIX_FMT_RGBF32 AV_PIX_FMT_NE(RGBF32BE, RGBF32LE) +#define AV_PIX_FMT_RGBAF32 AV_PIX_FMT_NE(RGBAF32BE, RGBAF32LE) + +/** + * Chromaticity coordinates of the source primaries. + * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.1 and ITU-T H.273. + */ +enum AVColorPrimaries { + AVCOL_PRI_RESERVED0 = 0, + AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP 177 Annex B + AVCOL_PRI_UNSPECIFIED = 2, + AVCOL_PRI_RESERVED = 3, + AVCOL_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + + AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + AVCOL_PRI_SMPTE240M = 7, ///< identical to above, also called "SMPTE C" even though it uses D65 + AVCOL_PRI_FILM = 8, ///< colour filters using Illuminant C + AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020 + AVCOL_PRI_SMPTE428 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ) + AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428, + AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) / DCI P3 + AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3 + AVCOL_PRI_EBU3213 = 22, ///< EBU Tech. 3213-E (nothing there) / one of JEDEC P22 group phosphors + AVCOL_PRI_JEDEC_P22 = AVCOL_PRI_EBU3213, + AVCOL_PRI_NB ///< Not part of ABI +}; + +/** + * Color Transfer Characteristic. + * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.2. + */ +enum AVColorTransferCharacteristic { + AVCOL_TRC_RESERVED0 = 0, + AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361 + AVCOL_TRC_UNSPECIFIED = 2, + AVCOL_TRC_RESERVED = 3, + AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG + AVCOL_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC + AVCOL_TRC_SMPTE240M = 7, + AVCOL_TRC_LINEAR = 8, ///< "Linear transfer characteristics" + AVCOL_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)" + AVCOL_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" + AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4 + AVCOL_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut + AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC) + AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10-bit system + AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12-bit system + AVCOL_TRC_SMPTE2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084, + AVCOL_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1 + AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428, + AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma" + AVCOL_TRC_NB ///< Not part of ABI +}; + +/** + * YUV colorspace type. + * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.3. + */ +enum AVColorSpace { + AVCOL_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1 + AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B + AVCOL_SPC_UNSPECIFIED = 2, + AVCOL_SPC_RESERVED = 3, ///< reserved for future use by ITU-T and ISO/IEC just like 15-255 are + AVCOL_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 + AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above + AVCOL_SPC_SMPTE240M = 7, ///< derived from 170M primaries and D65 white point, 170M is derived from BT470 System M's primaries + AVCOL_SPC_YCGCO = 8, ///< used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + AVCOL_SPC_YCOCG = AVCOL_SPC_YCGCO, + AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system + AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system + AVCOL_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x + AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system + AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system + AVCOL_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp + AVCOL_SPC_NB ///< Not part of ABI +}; + +/** + * Visual content value range. + * + * These values are based on definitions that can be found in multiple + * specifications, such as ITU-T BT.709 (3.4 - Quantization of RGB, luminance + * and colour-difference signals), ITU-T BT.2020 (Table 5 - Digital + * Representation) as well as ITU-T BT.2100 (Table 9 - Digital 10- and 12-bit + * integer representation). At the time of writing, the BT.2100 one is + * recommended, as it also defines the full range representation. + * + * Common definitions: + * - For RGB and luma planes such as Y in YCbCr and I in ICtCp, + * 'E' is the original value in range of 0.0 to 1.0. + * - For chroma planes such as Cb,Cr and Ct,Cp, 'E' is the original + * value in range of -0.5 to 0.5. + * - 'n' is the output bit depth. + * - For additional definitions such as rounding and clipping to valid n + * bit unsigned integer range, please refer to BT.2100 (Table 9). + */ +enum AVColorRange { + AVCOL_RANGE_UNSPECIFIED = 0, + + /** + * Narrow or limited range content. + * + * - For luma planes: + * + * (219 * E + 16) * 2^(n-8) + * + * F.ex. the range of 16-235 for 8 bits + * + * - For chroma planes: + * + * (224 * E + 128) * 2^(n-8) + * + * F.ex. the range of 16-240 for 8 bits + */ + AVCOL_RANGE_MPEG = 1, + + /** + * Full range content. + * + * - For RGB and luma planes: + * + * (2^n - 1) * E + * + * F.ex. the range of 0-255 for 8 bits + * + * - For chroma planes: + * + * (2^n - 1) * E + 2^(n - 1) + * + * F.ex. the range of 1-255 for 8 bits + */ + AVCOL_RANGE_JPEG = 2, + AVCOL_RANGE_NB ///< Not part of ABI +}; + +/** + * Location of chroma samples. + * + * Illustration showing the location of the first (top left) chroma sample of the + * image, the left shows only luma, the right + * shows the location of the chroma sample, the 2 could be imagined to overlay + * each other but are drawn separately due to limitations of ASCII + * + * 1st 2nd 1st 2nd horizontal luma sample positions + * v v v v + * ______ ______ + *1st luma line > |X X ... |3 4 X ... X are luma samples, + * | |1 2 1-6 are possible chroma positions + *2nd luma line > |X X ... |5 6 X ... 0 is undefined/unknown position + */ +enum AVChromaLocation { + AVCHROMA_LOC_UNSPECIFIED = 0, + AVCHROMA_LOC_LEFT = 1, ///< MPEG-2/4 4:2:0, H.264 default for 4:2:0 + AVCHROMA_LOC_CENTER = 2, ///< MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0 + AVCHROMA_LOC_TOPLEFT = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2 + AVCHROMA_LOC_TOP = 4, + AVCHROMA_LOC_BOTTOMLEFT = 5, + AVCHROMA_LOC_BOTTOM = 6, + AVCHROMA_LOC_NB ///< Not part of ABI +}; + +#endif /* AVUTIL_PIXFMT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/rational.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/rational.h new file mode 100644 index 0000000000000..8cbfc8e066983 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/rational.h @@ -0,0 +1,221 @@ +/* + * rational numbers + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_math_rational + * Utilties for rational number calculation. + * @author Michael Niedermayer + */ + +#ifndef AVUTIL_RATIONAL_H +#define AVUTIL_RATIONAL_H + +#include +#include +#include "attributes.h" + +/** + * @defgroup lavu_math_rational AVRational + * @ingroup lavu_math + * Rational number calculation. + * + * While rational numbers can be expressed as floating-point numbers, the + * conversion process is a lossy one, so are floating-point operations. On the + * other hand, the nature of FFmpeg demands highly accurate calculation of + * timestamps. This set of rational number utilities serves as a generic + * interface for manipulating rational numbers as pairs of numerators and + * denominators. + * + * Many of the functions that operate on AVRational's have the suffix `_q`, in + * reference to the mathematical symbol "ℚ" (Q) which denotes the set of all + * rational numbers. + * + * @{ + */ + +/** + * Rational number (pair of numerator and denominator). + */ +typedef struct AVRational{ + int num; ///< Numerator + int den; ///< Denominator +} AVRational; + +/** + * Create an AVRational. + * + * Useful for compilers that do not support compound literals. + * + * @note The return value is not reduced. + * @see av_reduce() + */ +static inline AVRational av_make_q(int num, int den) +{ + AVRational r = { num, den }; + return r; +} + +/** + * Compare two rationals. + * + * @param a First rational + * @param b Second rational + * + * @return One of the following values: + * - 0 if `a == b` + * - 1 if `a > b` + * - -1 if `a < b` + * - `INT_MIN` if one of the values is of the form `0 / 0` + */ +static inline int av_cmp_q(AVRational a, AVRational b){ + const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den; + + if(tmp) return (int)((tmp ^ a.den ^ b.den)>>63)|1; + else if(b.den && a.den) return 0; + else if(a.num && b.num) return (a.num>>31) - (b.num>>31); + else return INT_MIN; +} + +/** + * Convert an AVRational to a `double`. + * @param a AVRational to convert + * @return `a` in floating-point form + * @see av_d2q() + */ +static inline double av_q2d(AVRational a){ + return a.num / (double) a.den; +} + +/** + * Reduce a fraction. + * + * This is useful for framerate calculations. + * + * @param[out] dst_num Destination numerator + * @param[out] dst_den Destination denominator + * @param[in] num Source numerator + * @param[in] den Source denominator + * @param[in] max Maximum allowed values for `dst_num` & `dst_den` + * @return 1 if the operation is exact, 0 otherwise + */ +int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max); + +/** + * Multiply two rationals. + * @param b First rational + * @param c Second rational + * @return b*c + */ +AVRational av_mul_q(AVRational b, AVRational c) av_const; + +/** + * Divide one rational by another. + * @param b First rational + * @param c Second rational + * @return b/c + */ +AVRational av_div_q(AVRational b, AVRational c) av_const; + +/** + * Add two rationals. + * @param b First rational + * @param c Second rational + * @return b+c + */ +AVRational av_add_q(AVRational b, AVRational c) av_const; + +/** + * Subtract one rational from another. + * @param b First rational + * @param c Second rational + * @return b-c + */ +AVRational av_sub_q(AVRational b, AVRational c) av_const; + +/** + * Invert a rational. + * @param q value + * @return 1 / q + */ +static av_always_inline AVRational av_inv_q(AVRational q) +{ + AVRational r = { q.den, q.num }; + return r; +} + +/** + * Convert a double precision floating point number to a rational. + * + * In case of infinity, the returned value is expressed as `{1, 0}` or + * `{-1, 0}` depending on the sign. + * + * @param d `double` to convert + * @param max Maximum allowed numerator and denominator + * @return `d` in AVRational form + * @see av_q2d() + */ +AVRational av_d2q(double d, int max) av_const; + +/** + * Find which of the two rationals is closer to another rational. + * + * @param q Rational to be compared against + * @param q1 Rational to be tested + * @param q2 Rational to be tested + * @return One of the following values: + * - 1 if `q1` is nearer to `q` than `q2` + * - -1 if `q2` is nearer to `q` than `q1` + * - 0 if they have the same distance + */ +int av_nearer_q(AVRational q, AVRational q1, AVRational q2); + +/** + * Find the value in a list of rationals nearest a given reference rational. + * + * @param q Reference rational + * @param q_list Array of rationals terminated by `{0, 0}` + * @return Index of the nearest value found in the array + */ +int av_find_nearest_q_idx(AVRational q, const AVRational* q_list); + +/** + * Convert an AVRational to a IEEE 32-bit `float` expressed in fixed-point + * format. + * + * @param q Rational to be converted + * @return Equivalent floating-point value, expressed as an unsigned 32-bit + * integer. + * @note The returned value is platform-indepedant. + */ +uint32_t av_q2intfloat(AVRational q); + +/** + * Return the best rational so that a and b are multiple of it. + * If the resulting denominator is larger than max_den, return def. + */ +AVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def); + +/** + * @} + */ + +#endif /* AVUTIL_RATIONAL_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/samplefmt.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/samplefmt.h new file mode 100644 index 0000000000000..43a57a422cdbf --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/samplefmt.h @@ -0,0 +1,269 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_SAMPLEFMT_H +#define AVUTIL_SAMPLEFMT_H + +#include + +/** + * @addtogroup lavu_audio + * @{ + * + * @defgroup lavu_sampfmts Audio sample formats + * + * Audio sample format enumeration and related convenience functions. + * @{ + */ + +/** + * Audio sample formats + * + * - The data described by the sample format is always in native-endian order. + * Sample values can be expressed by native C types, hence the lack of a signed + * 24-bit sample format even though it is a common raw audio data format. + * + * - The floating-point formats are based on full volume being in the range + * [-1.0, 1.0]. Any values outside this range are beyond full volume level. + * + * - The data layout as used in av_samples_fill_arrays() and elsewhere in FFmpeg + * (such as AVFrame in libavcodec) is as follows: + * + * @par + * For planar sample formats, each audio channel is in a separate data plane, + * and linesize is the buffer size, in bytes, for a single plane. All data + * planes must be the same size. For packed sample formats, only the first data + * plane is used, and samples for each channel are interleaved. In this case, + * linesize is the buffer size, in bytes, for the 1 plane. + * + */ +enum AVSampleFormat { + AV_SAMPLE_FMT_NONE = -1, + AV_SAMPLE_FMT_U8, ///< unsigned 8 bits + AV_SAMPLE_FMT_S16, ///< signed 16 bits + AV_SAMPLE_FMT_S32, ///< signed 32 bits + AV_SAMPLE_FMT_FLT, ///< float + AV_SAMPLE_FMT_DBL, ///< double + + AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar + AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar + AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar + AV_SAMPLE_FMT_FLTP, ///< float, planar + AV_SAMPLE_FMT_DBLP, ///< double, planar + AV_SAMPLE_FMT_S64, ///< signed 64 bits + AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar + + AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically +}; + +/** + * Return the name of sample_fmt, or NULL if sample_fmt is not + * recognized. + */ +const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt); + +/** + * Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE + * on error. + */ +enum AVSampleFormat av_get_sample_fmt(const char *name); + +/** + * Return the planar<->packed alternative form of the given sample format, or + * AV_SAMPLE_FMT_NONE on error. If the passed sample_fmt is already in the + * requested planar/packed format, the format returned is the same as the + * input. + */ +enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar); + +/** + * Get the packed alternative form of the given sample format. + * + * If the passed sample_fmt is already in packed format, the format returned is + * the same as the input. + * + * @return the packed alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Get the planar alternative form of the given sample format. + * + * If the passed sample_fmt is already in planar format, the format returned is + * the same as the input. + * + * @return the planar alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Generate a string corresponding to the sample format with + * sample_fmt, or a header if sample_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param sample_fmt the number of the sample format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + * @return the pointer to the filled buffer or NULL if sample_fmt is + * unknown or in case of other errors + */ +char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt); + +/** + * Return number of bytes per sample. + * + * @param sample_fmt the sample format + * @return number of bytes per sample or zero if unknown for the given + * sample format + */ +int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt); + +/** + * Check if the sample format is planar. + * + * @param sample_fmt the sample format to inspect + * @return 1 if the sample format is planar, 0 if it is interleaved + */ +int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt); + +/** + * Get the required buffer size for the given audio parameters. + * + * @param[out] linesize calculated linesize, may be NULL + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return required buffer size, or negative error code on failure + */ +int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * @} + * + * @defgroup lavu_sampmanip Samples manipulation + * + * Functions that manipulate audio samples + * @{ + */ + +/** + * Fill plane data pointers and linesize for samples with sample + * format sample_fmt. + * + * The audio_data array is filled with the pointers to the samples data planes: + * for planar, set the start point of each channel's data within the buffer, + * for packed, set the start point of the entire buffer only. + * + * The value pointed to by linesize is set to the aligned size of each + * channel's data buffer for planar layout, or to the aligned size of the + * buffer for all channels for packed layout. + * + * The buffer in buf must be big enough to contain all the samples + * (use av_samples_get_buffer_size() to compute its minimum size), + * otherwise the audio_data pointers will point to invalid data. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize calculated linesize, may be NULL + * @param buf the pointer to a buffer containing the samples + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return minimum size in bytes required for the buffer on success, + * or a negative error code on failure + */ +int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, + const uint8_t *buf, + int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a samples buffer for nb_samples samples, and fill data pointers and + * linesize accordingly. + * The allocated samples buffer can be freed by using av_freep(&audio_data[0]) + * Allocated data will be initialized to silence. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize aligned size for audio buffer(s), may be NULL + * @param nb_channels number of audio channels + * @param nb_samples number of samples per channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return >=0 on success or a negative error code on failure + * @todo return the size of the allocated buffer in case of success at the next bump + * @see av_samples_fill_arrays() + * @see av_samples_alloc_array_and_samples() + */ +int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a data pointers array, samples buffer for nb_samples + * samples, and fill data pointers and linesize accordingly. + * + * This is the same as av_samples_alloc(), but also allocates the data + * pointers array. + * + * @see av_samples_alloc() + */ +int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Copy samples from src to dst. + * + * @param dst destination array of pointers to data planes + * @param src source array of pointers to data planes + * @param dst_offset offset in samples at which the data will be written to dst + * @param src_offset offset in samples at which the data will be read from src + * @param nb_samples number of samples to be copied + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_copy(uint8_t * const *dst, uint8_t * const *src, int dst_offset, + int src_offset, int nb_samples, int nb_channels, + enum AVSampleFormat sample_fmt); + +/** + * Fill an audio buffer with silence. + * + * @param audio_data array of pointers to data planes + * @param offset offset in samples at which to start filling + * @param nb_samples number of samples to fill + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_set_silence(uint8_t * const *audio_data, int offset, int nb_samples, + int nb_channels, enum AVSampleFormat sample_fmt); + +/** + * @} + * @} + */ +#endif /* AVUTIL_SAMPLEFMT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libavutil/version.h b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/version.h new file mode 100644 index 0000000000000..7c0600da22f15 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libavutil/version.h @@ -0,0 +1,128 @@ +/* + * copyright (c) 2003 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu + * Libavutil version macros + */ + +#ifndef AVUTIL_VERSION_H +#define AVUTIL_VERSION_H + +#include "macros.h" + +/** + * @addtogroup version_utils + * + * Useful to check and match library version in order to maintain + * backward compatibility. + * + * The FFmpeg libraries follow a versioning sheme very similar to + * Semantic Versioning (http://semver.org/) + * The difference is that the component called PATCH is called MICRO in FFmpeg + * and its value is reset to 100 instead of 0 to keep it above or equal to 100. + * Also we do not increase MICRO for every bugfix or change in git master. + * + * Prior to FFmpeg 3.2 point releases did not change any lib version number to + * avoid aliassing different git master checkouts. + * Starting with FFmpeg 3.2, the released library versions will occupy + * a separate MAJOR.MINOR that is not used on the master development branch. + * That is if we branch a release of master 55.10.123 we will bump to 55.11.100 + * for the release and master will continue at 55.12.100 after it. Each new + * point release will then bump the MICRO improving the usefulness of the lib + * versions. + * + * @{ + */ + +#define AV_VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c)) +#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c +#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c) + +/** + * Extract version components from the full ::AV_VERSION_INT int as returned + * by functions like ::avformat_version() and ::avcodec_version() + */ +#define AV_VERSION_MAJOR(a) ((a) >> 16) +#define AV_VERSION_MINOR(a) (((a) & 0x00FF00) >> 8) +#define AV_VERSION_MICRO(a) ((a) & 0xFF) + +/** + * @} + */ + +/** + * @defgroup lavu_ver Version and Build diagnostics + * + * Macros and function useful to check at compiletime and at runtime + * which version of libavutil is in use. + * + * @{ + */ + +#define LIBAVUTIL_VERSION_MAJOR 58 +#define LIBAVUTIL_VERSION_MINOR 29 +#define LIBAVUTIL_VERSION_MICRO 100 + +#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT + +#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION) + +/** + * @defgroup lavu_depr_guards Deprecation Guards + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + * + * @{ + */ + +#define FF_API_FIFO_PEEK2 (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_FIFO_OLD_API (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_XVMC (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_OLD_CHANNEL_LAYOUT (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_AV_FOPEN_UTF8 (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_PKT_DURATION (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_REORDERED_OPAQUE (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_FRAME_PICTURE_NUMBER (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_HDR_VIVID_THREE_SPLINE (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_FRAME_PKT (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_INTERLACED_FRAME (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_FRAME_KEY (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_PALETTE_HAS_CHANGED (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_VULKAN_CONTIGUOUS_MEMORY (LIBAVUTIL_VERSION_MAJOR < 59) + +/** + * @} + * @} + */ + +#endif /* AVUTIL_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libswscale/swscale.h b/src/framework/media/thirdparty/ffmpeg/v6/libswscale/swscale.h new file mode 100644 index 0000000000000..9d4612aaf3a64 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libswscale/swscale.h @@ -0,0 +1,436 @@ +/* + * Copyright (C) 2001-2011 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_SWSCALE_H +#define SWSCALE_SWSCALE_H + +/** + * @file + * @ingroup libsws + * external API header + */ + +#include + +#include "libavutil/avutil.h" +#include "libavutil/frame.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "version.h" +#endif + +/** + * @defgroup libsws libswscale + * Color conversion and scaling library. + * + * @{ + * + * Return the LIBSWSCALE_VERSION_INT constant. + */ +unsigned swscale_version(void); + +/** + * Return the libswscale build-time configuration. + */ +const char *swscale_configuration(void); + +/** + * Return the libswscale license. + */ +const char *swscale_license(void); + +/* values for the flags, the stuff on the command line is different */ +#define SWS_FAST_BILINEAR 1 +#define SWS_BILINEAR 2 +#define SWS_BICUBIC 4 +#define SWS_X 8 +#define SWS_POINT 0x10 +#define SWS_AREA 0x20 +#define SWS_BICUBLIN 0x40 +#define SWS_GAUSS 0x80 +#define SWS_SINC 0x100 +#define SWS_LANCZOS 0x200 +#define SWS_SPLINE 0x400 + +#define SWS_SRC_V_CHR_DROP_MASK 0x30000 +#define SWS_SRC_V_CHR_DROP_SHIFT 16 + +#define SWS_PARAM_DEFAULT 123456 + +#define SWS_PRINT_INFO 0x1000 + +//the following 3 flags are not completely implemented +//internal chrominance subsampling info +#define SWS_FULL_CHR_H_INT 0x2000 +//input subsampling info +#define SWS_FULL_CHR_H_INP 0x4000 +#define SWS_DIRECT_BGR 0x8000 +#define SWS_ACCURATE_RND 0x40000 +#define SWS_BITEXACT 0x80000 +#define SWS_ERROR_DIFFUSION 0x800000 + +#define SWS_MAX_REDUCE_CUTOFF 0.002 + +#define SWS_CS_ITU709 1 +#define SWS_CS_FCC 4 +#define SWS_CS_ITU601 5 +#define SWS_CS_ITU624 5 +#define SWS_CS_SMPTE170M 5 +#define SWS_CS_SMPTE240M 7 +#define SWS_CS_DEFAULT 5 +#define SWS_CS_BT2020 9 + +/** + * Return a pointer to yuv<->rgb coefficients for the given colorspace + * suitable for sws_setColorspaceDetails(). + * + * @param colorspace One of the SWS_CS_* macros. If invalid, + * SWS_CS_DEFAULT is used. + */ +const int *sws_getCoefficients(int colorspace); + +// when used for filters they must have an odd number of elements +// coeffs cannot be shared between vectors +typedef struct SwsVector { + double *coeff; ///< pointer to the list of coefficients + int length; ///< number of coefficients in the vector +} SwsVector; + +// vectors can be shared +typedef struct SwsFilter { + SwsVector *lumH; + SwsVector *lumV; + SwsVector *chrH; + SwsVector *chrV; +} SwsFilter; + +struct SwsContext; + +/** + * Return a positive value if pix_fmt is a supported input format, 0 + * otherwise. + */ +int sws_isSupportedInput(enum AVPixelFormat pix_fmt); + +/** + * Return a positive value if pix_fmt is a supported output format, 0 + * otherwise. + */ +int sws_isSupportedOutput(enum AVPixelFormat pix_fmt); + +/** + * @param[in] pix_fmt the pixel format + * @return a positive value if an endianness conversion for pix_fmt is + * supported, 0 otherwise. + */ +int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt); + +/** + * Allocate an empty SwsContext. This must be filled and passed to + * sws_init_context(). For filling see AVOptions, options.c and + * sws_setColorspaceDetails(). + */ +struct SwsContext *sws_alloc_context(void); + +/** + * Initialize the swscaler context sws_context. + * + * @return zero or positive value on success, a negative value on + * error + */ +av_warn_unused_result +int sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter); + +/** + * Free the swscaler context swsContext. + * If swsContext is NULL, then does nothing. + */ +void sws_freeContext(struct SwsContext *swsContext); + +/** + * Allocate and return an SwsContext. You need it to perform + * scaling/conversion operations using sws_scale(). + * + * @param srcW the width of the source image + * @param srcH the height of the source image + * @param srcFormat the source image format + * @param dstW the width of the destination image + * @param dstH the height of the destination image + * @param dstFormat the destination image format + * @param flags specify which algorithm and options to use for rescaling + * @param param extra parameters to tune the used scaler + * For SWS_BICUBIC param[0] and [1] tune the shape of the basis + * function, param[0] tunes f(1) and param[1] f´(1) + * For SWS_GAUSS param[0] tunes the exponent and thus cutoff + * frequency + * For SWS_LANCZOS param[0] tunes the width of the window function + * @return a pointer to an allocated context, or NULL in case of error + * @note this function is to be removed after a saner alternative is + * written + */ +struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, + int dstW, int dstH, enum AVPixelFormat dstFormat, + int flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param); + +/** + * Scale the image slice in srcSlice and put the resulting scaled + * slice in the image in dst. A slice is a sequence of consecutive + * rows in an image. + * + * Slices have to be provided in sequential order, either in + * top-bottom or bottom-top order. If slices are provided in + * non-sequential order the behavior of the function is undefined. + * + * @param c the scaling context previously created with + * sws_getContext() + * @param srcSlice the array containing the pointers to the planes of + * the source slice + * @param srcStride the array containing the strides for each plane of + * the source image + * @param srcSliceY the position in the source image of the slice to + * process, that is the number (counted starting from + * zero) in the image of the first row of the slice + * @param srcSliceH the height of the source slice, that is the number + * of rows in the slice + * @param dst the array containing the pointers to the planes of + * the destination image + * @param dstStride the array containing the strides for each plane of + * the destination image + * @return the height of the output slice + */ +int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], + const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *const dst[], const int dstStride[]); + +/** + * Scale source data from src and write the output to dst. + * + * This is merely a convenience wrapper around + * - sws_frame_start() + * - sws_send_slice(0, src->height) + * - sws_receive_slice(0, dst->height) + * - sws_frame_end() + * + * @param c The scaling context + * @param dst The destination frame. See documentation for sws_frame_start() for + * more details. + * @param src The source frame. + * + * @return 0 on success, a negative AVERROR code on failure + */ +int sws_scale_frame(struct SwsContext *c, AVFrame *dst, const AVFrame *src); + +/** + * Initialize the scaling process for a given pair of source/destination frames. + * Must be called before any calls to sws_send_slice() and sws_receive_slice(). + * + * This function will retain references to src and dst, so they must both use + * refcounted buffers (if allocated by the caller, in case of dst). + * + * @param c The scaling context + * @param dst The destination frame. + * + * The data buffers may either be already allocated by the caller or + * left clear, in which case they will be allocated by the scaler. + * The latter may have performance advantages - e.g. in certain cases + * some output planes may be references to input planes, rather than + * copies. + * + * Output data will be written into this frame in successful + * sws_receive_slice() calls. + * @param src The source frame. The data buffers must be allocated, but the + * frame data does not have to be ready at this point. Data + * availability is then signalled by sws_send_slice(). + * @return 0 on success, a negative AVERROR code on failure + * + * @see sws_frame_end() + */ +int sws_frame_start(struct SwsContext *c, AVFrame *dst, const AVFrame *src); + +/** + * Finish the scaling process for a pair of source/destination frames previously + * submitted with sws_frame_start(). Must be called after all sws_send_slice() + * and sws_receive_slice() calls are done, before any new sws_frame_start() + * calls. + * + * @param c The scaling context + */ +void sws_frame_end(struct SwsContext *c); + +/** + * Indicate that a horizontal slice of input data is available in the source + * frame previously provided to sws_frame_start(). The slices may be provided in + * any order, but may not overlap. For vertically subsampled pixel formats, the + * slices must be aligned according to subsampling. + * + * @param c The scaling context + * @param slice_start first row of the slice + * @param slice_height number of rows in the slice + * + * @return a non-negative number on success, a negative AVERROR code on failure. + */ +int sws_send_slice(struct SwsContext *c, unsigned int slice_start, + unsigned int slice_height); + +/** + * Request a horizontal slice of the output data to be written into the frame + * previously provided to sws_frame_start(). + * + * @param c The scaling context + * @param slice_start first row of the slice; must be a multiple of + * sws_receive_slice_alignment() + * @param slice_height number of rows in the slice; must be a multiple of + * sws_receive_slice_alignment(), except for the last slice + * (i.e. when slice_start+slice_height is equal to output + * frame height) + * + * @return a non-negative number if the data was successfully written into the output + * AVERROR(EAGAIN) if more input data needs to be provided before the + * output can be produced + * another negative AVERROR code on other kinds of scaling failure + */ +int sws_receive_slice(struct SwsContext *c, unsigned int slice_start, + unsigned int slice_height); + +/** + * Get the alignment required for slices + * + * @param c The scaling context + * @return alignment required for output slices requested with sws_receive_slice(). + * Slice offsets and sizes passed to sws_receive_slice() must be + * multiples of the value returned from this function. + */ +unsigned int sws_receive_slice_alignment(const struct SwsContext *c); + +/** + * @param c the scaling context + * @param dstRange flag indicating the while-black range of the output (1=jpeg / 0=mpeg) + * @param srcRange flag indicating the while-black range of the input (1=jpeg / 0=mpeg) + * @param table the yuv2rgb coefficients describing the output yuv space, normally ff_yuv2rgb_coeffs[x] + * @param inv_table the yuv2rgb coefficients describing the input yuv space, normally ff_yuv2rgb_coeffs[x] + * @param brightness 16.16 fixed point brightness correction + * @param contrast 16.16 fixed point contrast correction + * @param saturation 16.16 fixed point saturation correction + * + * @return A negative error code on error, non negative otherwise. + * If `LIBSWSCALE_VERSION_MAJOR < 7`, returns -1 if not supported. + */ +int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], + int srcRange, const int table[4], int dstRange, + int brightness, int contrast, int saturation); + +/** + * @return A negative error code on error, non negative otherwise. + * If `LIBSWSCALE_VERSION_MAJOR < 7`, returns -1 if not supported. + */ +int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table, + int *srcRange, int **table, int *dstRange, + int *brightness, int *contrast, int *saturation); + +/** + * Allocate and return an uninitialized vector with length coefficients. + */ +SwsVector *sws_allocVec(int length); + +/** + * Return a normalized Gaussian curve used to filter stuff + * quality = 3 is high quality, lower is lower quality. + */ +SwsVector *sws_getGaussianVec(double variance, double quality); + +/** + * Scale all the coefficients of a by the scalar value. + */ +void sws_scaleVec(SwsVector *a, double scalar); + +/** + * Scale all the coefficients of a so that their sum equals height. + */ +void sws_normalizeVec(SwsVector *a, double height); + +void sws_freeVec(SwsVector *a); + +SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, + float lumaSharpen, float chromaSharpen, + float chromaHShift, float chromaVShift, + int verbose); +void sws_freeFilter(SwsFilter *filter); + +/** + * Check if context can be reused, otherwise reallocate a new one. + * + * If context is NULL, just calls sws_getContext() to get a new + * context. Otherwise, checks if the parameters are the ones already + * saved in context. If that is the case, returns the current + * context. Otherwise, frees context and gets a new context with + * the new parameters. + * + * Be warned that srcFilter and dstFilter are not checked, they + * are assumed to remain the same. + */ +struct SwsContext *sws_getCachedContext(struct SwsContext *context, + int srcW, int srcH, enum AVPixelFormat srcFormat, + int dstW, int dstH, enum AVPixelFormat dstFormat, + int flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 32 bits. + * + * The output frame will have the same packed format as the palette. + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 24 bits. + * + * With the palette format "ABCD", the destination frame ends up with the format "ABC". + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Get the AVClass for swsContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *sws_get_class(void); + +/** + * @} + */ + +#endif /* SWSCALE_SWSCALE_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libswscale/version.h b/src/framework/media/thirdparty/ffmpeg/v6/libswscale/version.h new file mode 100644 index 0000000000000..c13db31c432f1 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libswscale/version.h @@ -0,0 +1,44 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_VERSION_H +#define SWSCALE_VERSION_H + +/** + * @file + * swscale version macros + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBSWSCALE_VERSION_MINOR 5 +#define LIBSWSCALE_VERSION_MICRO 100 + +#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_VERSION AV_VERSION(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_BUILD LIBSWSCALE_VERSION_INT + +#define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION) + +#endif /* SWSCALE_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libswscale/version_major.h b/src/framework/media/thirdparty/ffmpeg/v6/libswscale/version_major.h new file mode 100644 index 0000000000000..88577a2b42a55 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libswscale/version_major.h @@ -0,0 +1,35 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_VERSION_MAJOR_H +#define SWSCALE_VERSION_MAJOR_H + +/** + * @file + * swscale version macros + */ + +#define LIBSWSCALE_VERSION_MAJOR 7 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + */ + +#endif /* SWSCALE_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/avcodec.h b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/avcodec.h new file mode 100644 index 0000000000000..83dc487251cf7 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/avcodec.h @@ -0,0 +1,3087 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AVCODEC_H +#define AVCODEC_AVCODEC_H + +/** + * @file + * @ingroup libavc + * Libavcodec external API header + */ + +#include "libavutil/samplefmt.h" +#include "libavutil/attributes.h" +#include "libavutil/avutil.h" +#include "libavutil/buffer.h" +#include "libavutil/channel_layout.h" +#include "libavutil/dict.h" +#include "libavutil/frame.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +#include "codec.h" +#include "codec_id.h" +#include "defs.h" +#include "packet.h" +#include "version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "version.h" + +#include "codec_desc.h" +#include "codec_par.h" +#endif + +struct AVCodecParameters; + +/** + * @defgroup libavc libavcodec + * Encoding/Decoding Library + * + * @{ + * + * @defgroup lavc_decoding Decoding + * @{ + * @} + * + * @defgroup lavc_encoding Encoding + * @{ + * @} + * + * @defgroup lavc_codec Codecs + * @{ + * @defgroup lavc_codec_native Native Codecs + * @{ + * @} + * @defgroup lavc_codec_wrappers External library wrappers + * @{ + * @} + * @defgroup lavc_codec_hwaccel Hardware Accelerators bridge + * @{ + * @} + * @} + * @defgroup lavc_internal Internal + * @{ + * @} + * @} + */ + +/** + * @ingroup libavc + * @defgroup lavc_encdec send/receive encoding and decoding API overview + * @{ + * + * The avcodec_send_packet()/avcodec_receive_frame()/avcodec_send_frame()/ + * avcodec_receive_packet() functions provide an encode/decode API, which + * decouples input and output. + * + * The API is very similar for encoding/decoding and audio/video, and works as + * follows: + * - Set up and open the AVCodecContext as usual. + * - Send valid input: + * - For decoding, call avcodec_send_packet() to give the decoder raw + * compressed data in an AVPacket. + * - For encoding, call avcodec_send_frame() to give the encoder an AVFrame + * containing uncompressed audio or video. + * + * In both cases, it is recommended that AVPackets and AVFrames are + * refcounted, or libavcodec might have to copy the input data. (libavformat + * always returns refcounted AVPackets, and av_frame_get_buffer() allocates + * refcounted AVFrames.) + * - Receive output in a loop. Periodically call one of the avcodec_receive_*() + * functions and process their output: + * - For decoding, call avcodec_receive_frame(). On success, it will return + * an AVFrame containing uncompressed audio or video data. + * - For encoding, call avcodec_receive_packet(). On success, it will return + * an AVPacket with a compressed frame. + * + * Repeat this call until it returns AVERROR(EAGAIN) or an error. The + * AVERROR(EAGAIN) return value means that new input data is required to + * return new output. In this case, continue with sending input. For each + * input frame/packet, the codec will typically return 1 output frame/packet, + * but it can also be 0 or more than 1. + * + * At the beginning of decoding or encoding, the codec might accept multiple + * input frames/packets without returning a frame, until its internal buffers + * are filled. This situation is handled transparently if you follow the steps + * outlined above. + * + * In theory, sending input can result in EAGAIN - this should happen only if + * not all output was received. You can use this to structure alternative decode + * or encode loops other than the one suggested above. For example, you could + * try sending new input on each iteration, and try to receive output if that + * returns EAGAIN. + * + * End of stream situations. These require "flushing" (aka draining) the codec, + * as the codec might buffer multiple frames or packets internally for + * performance or out of necessity (consider B-frames). + * This is handled as follows: + * - Instead of valid input, send NULL to the avcodec_send_packet() (decoding) + * or avcodec_send_frame() (encoding) functions. This will enter draining + * mode. + * - Call avcodec_receive_frame() (decoding) or avcodec_receive_packet() + * (encoding) in a loop until AVERROR_EOF is returned. The functions will + * not return AVERROR(EAGAIN), unless you forgot to enter draining mode. + * - Before decoding can be resumed again, the codec has to be reset with + * avcodec_flush_buffers(). + * + * Using the API as outlined above is highly recommended. But it is also + * possible to call functions outside of this rigid schema. For example, you can + * call avcodec_send_packet() repeatedly without calling + * avcodec_receive_frame(). In this case, avcodec_send_packet() will succeed + * until the codec's internal buffer has been filled up (which is typically of + * size 1 per output frame, after initial input), and then reject input with + * AVERROR(EAGAIN). Once it starts rejecting input, you have no choice but to + * read at least some output. + * + * Not all codecs will follow a rigid and predictable dataflow; the only + * guarantee is that an AVERROR(EAGAIN) return value on a send/receive call on + * one end implies that a receive/send call on the other end will succeed, or + * at least will not fail with AVERROR(EAGAIN). In general, no codec will + * permit unlimited buffering of input or output. + * + * A codec is not allowed to return AVERROR(EAGAIN) for both sending and receiving. This + * would be an invalid state, which could put the codec user into an endless + * loop. The API has no concept of time either: it cannot happen that trying to + * do avcodec_send_packet() results in AVERROR(EAGAIN), but a repeated call 1 second + * later accepts the packet (with no other receive/flush API calls involved). + * The API is a strict state machine, and the passage of time is not supposed + * to influence it. Some timing-dependent behavior might still be deemed + * acceptable in certain cases. But it must never result in both send/receive + * returning EAGAIN at the same time at any point. It must also absolutely be + * avoided that the current state is "unstable" and can "flip-flop" between + * the send/receive APIs allowing progress. For example, it's not allowed that + * the codec randomly decides that it actually wants to consume a packet now + * instead of returning a frame, after it just returned AVERROR(EAGAIN) on an + * avcodec_send_packet() call. + * @} + */ + +/** + * @defgroup lavc_core Core functions/structures. + * @ingroup libavc + * + * Basic definitions, functions for querying libavcodec capabilities, + * allocating core structures, etc. + * @{ + */ + +#if FF_API_BUFFER_MIN_SIZE +/** + * @ingroup lavc_encoding + * minimum encoding buffer size + * Used to avoid some checks during header writing. + * @deprecated Unused: avcodec_receive_packet() does not work + * with preallocated packet buffers. + */ +#define AV_INPUT_BUFFER_MIN_SIZE 16384 +#endif + +/** + * @ingroup lavc_encoding + */ +typedef struct RcOverride{ + int start_frame; + int end_frame; + int qscale; // If this is 0 then quality_factor will be used instead. + float quality_factor; +} RcOverride; + +/* encoding support + These flags can be passed in AVCodecContext.flags before initialization. + Note: Not everything is supported yet. +*/ + +/** + * Allow decoders to produce frames with data planes that are not aligned + * to CPU requirements (e.g. due to cropping). + */ +#define AV_CODEC_FLAG_UNALIGNED (1 << 0) +/** + * Use fixed qscale. + */ +#define AV_CODEC_FLAG_QSCALE (1 << 1) +/** + * 4 MV per MB allowed / advanced prediction for H.263. + */ +#define AV_CODEC_FLAG_4MV (1 << 2) +/** + * Output even those frames that might be corrupted. + */ +#define AV_CODEC_FLAG_OUTPUT_CORRUPT (1 << 3) +/** + * Use qpel MC. + */ +#define AV_CODEC_FLAG_QPEL (1 << 4) +#if FF_API_DROPCHANGED +/** + * Don't output frames whose parameters differ from first + * decoded frame in stream. + * + * @deprecated callers should implement this functionality in their own code + */ +#define AV_CODEC_FLAG_DROPCHANGED (1 << 5) +#endif +/** + * Request the encoder to output reconstructed frames, i.e.\ frames that would + * be produced by decoding the encoded bistream. These frames may be retrieved + * by calling avcodec_receive_frame() immediately after a successful call to + * avcodec_receive_packet(). + * + * Should only be used with encoders flagged with the + * @ref AV_CODEC_CAP_ENCODER_RECON_FRAME capability. + * + * @note + * Each reconstructed frame returned by the encoder corresponds to the last + * encoded packet, i.e. the frames are returned in coded order rather than + * presentation order. + * + * @note + * Frame parameters (like pixel format or dimensions) do not have to match the + * AVCodecContext values. Make sure to use the values from the returned frame. + */ +#define AV_CODEC_FLAG_RECON_FRAME (1 << 6) +/** + * @par decoding + * Request the decoder to propagate each packet's AVPacket.opaque and + * AVPacket.opaque_ref to its corresponding output AVFrame. + * + * @par encoding: + * Request the encoder to propagate each frame's AVFrame.opaque and + * AVFrame.opaque_ref values to its corresponding output AVPacket. + * + * @par + * May only be set on encoders that have the + * @ref AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability flag. + * + * @note + * While in typical cases one input frame produces exactly one output packet + * (perhaps after a delay), in general the mapping of frames to packets is + * M-to-N, so + * - Any number of input frames may be associated with any given output packet. + * This includes zero - e.g. some encoders may output packets that carry only + * metadata about the whole stream. + * - A given input frame may be associated with any number of output packets. + * Again this includes zero - e.g. some encoders may drop frames under certain + * conditions. + * . + * This implies that when using this flag, the caller must NOT assume that + * - a given input frame's opaques will necessarily appear on some output packet; + * - every output packet will have some non-NULL opaque value. + * . + * When an output packet contains multiple frames, the opaque values will be + * taken from the first of those. + * + * @note + * The converse holds for decoders, with frames and packets switched. + */ +#define AV_CODEC_FLAG_COPY_OPAQUE (1 << 7) +/** + * Signal to the encoder that the values of AVFrame.duration are valid and + * should be used (typically for transferring them to output packets). + * + * If this flag is not set, frame durations are ignored. + */ +#define AV_CODEC_FLAG_FRAME_DURATION (1 << 8) +/** + * Use internal 2pass ratecontrol in first pass mode. + */ +#define AV_CODEC_FLAG_PASS1 (1 << 9) +/** + * Use internal 2pass ratecontrol in second pass mode. + */ +#define AV_CODEC_FLAG_PASS2 (1 << 10) +/** + * loop filter. + */ +#define AV_CODEC_FLAG_LOOP_FILTER (1 << 11) +/** + * Only decode/encode grayscale. + */ +#define AV_CODEC_FLAG_GRAY (1 << 13) +/** + * error[?] variables will be set during encoding. + */ +#define AV_CODEC_FLAG_PSNR (1 << 15) +/** + * Use interlaced DCT. + */ +#define AV_CODEC_FLAG_INTERLACED_DCT (1 << 18) +/** + * Force low delay. + */ +#define AV_CODEC_FLAG_LOW_DELAY (1 << 19) +/** + * Place global headers in extradata instead of every keyframe. + */ +#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22) +/** + * Use only bitexact stuff (except (I)DCT). + */ +#define AV_CODEC_FLAG_BITEXACT (1 << 23) +/* Fx : Flag for H.263+ extra options */ +/** + * H.263 advanced intra coding / MPEG-4 AC prediction + */ +#define AV_CODEC_FLAG_AC_PRED (1 << 24) +/** + * interlaced motion estimation + */ +#define AV_CODEC_FLAG_INTERLACED_ME (1 << 29) +#define AV_CODEC_FLAG_CLOSED_GOP (1U << 31) + +/** + * Allow non spec compliant speedup tricks. + */ +#define AV_CODEC_FLAG2_FAST (1 << 0) +/** + * Skip bitstream encoding. + */ +#define AV_CODEC_FLAG2_NO_OUTPUT (1 << 2) +/** + * Place global headers at every keyframe instead of in extradata. + */ +#define AV_CODEC_FLAG2_LOCAL_HEADER (1 << 3) + +/** + * Input bitstream might be truncated at a packet boundaries + * instead of only at frame boundaries. + */ +#define AV_CODEC_FLAG2_CHUNKS (1 << 15) +/** + * Discard cropping information from SPS. + */ +#define AV_CODEC_FLAG2_IGNORE_CROP (1 << 16) + +/** + * Show all frames before the first keyframe + */ +#define AV_CODEC_FLAG2_SHOW_ALL (1 << 22) +/** + * Export motion vectors through frame side data + */ +#define AV_CODEC_FLAG2_EXPORT_MVS (1 << 28) +/** + * Do not skip samples and export skip information as frame side data + */ +#define AV_CODEC_FLAG2_SKIP_MANUAL (1 << 29) +/** + * Do not reset ASS ReadOrder field on flush (subtitles decoding) + */ +#define AV_CODEC_FLAG2_RO_FLUSH_NOOP (1 << 30) +/** + * Generate/parse ICC profiles on encode/decode, as appropriate for the type of + * file. No effect on codecs which cannot contain embedded ICC profiles, or + * when compiled without support for lcms2. + */ +#define AV_CODEC_FLAG2_ICC_PROFILES (1U << 31) + +/* Exported side data. + These flags can be passed in AVCodecContext.export_side_data before initialization. +*/ +/** + * Export motion vectors through frame side data + */ +#define AV_CODEC_EXPORT_DATA_MVS (1 << 0) +/** + * Export encoder Producer Reference Time through packet side data + */ +#define AV_CODEC_EXPORT_DATA_PRFT (1 << 1) +/** + * Decoding only. + * Export the AVVideoEncParams structure through frame side data. + */ +#define AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS (1 << 2) +/** + * Decoding only. + * Do not apply film grain, export it instead. + */ +#define AV_CODEC_EXPORT_DATA_FILM_GRAIN (1 << 3) + +/** + * The decoder will keep a reference to the frame and may reuse it later. + */ +#define AV_GET_BUFFER_FLAG_REF (1 << 0) + +/** + * The encoder will keep a reference to the packet and may reuse it later. + */ +#define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0) + +/** + * main external API structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * You can use AVOptions (av_opt* / av_set/get*()) to access these fields from user + * applications. + * The name string for AVOptions options matches the associated command line + * parameter name and can be found in libavcodec/options_table.h + * The AVOption/command line parameter names differ in some cases from the C + * structure field names for historic reasons or brevity. + * sizeof(AVCodecContext) must not be used outside libav*. + */ +typedef struct AVCodecContext { + /** + * information on struct for av_log + * - set by avcodec_alloc_context3 + */ + const AVClass *av_class; + int log_level_offset; + + enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ + const struct AVCodec *codec; + enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ + + /** + * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * This is used to work around some encoder bugs. + * A demuxer should set this to what is stored in the field used to identify the codec. + * If there are multiple such fields in a container then the demuxer should choose the one + * which maximizes the information about the used codec. + * If the codec tag field in a container is larger than 32 bits then the demuxer should + * remap the longer ID to 32 bits with a table or other structure. Alternatively a new + * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated + * first. + * - encoding: Set by user, if not then the default based on codec_id will be used. + * - decoding: Set by user, will be converted to uppercase by libavcodec during init. + */ + unsigned int codec_tag; + + void *priv_data; + + /** + * Private context used for internal data. + * + * Unlike priv_data, this is not codec-specific. It is used in general + * libavcodec functions. + */ + struct AVCodecInternal *internal; + + /** + * Private data of the user, can be used to carry app specific stuff. + * - encoding: Set by user. + * - decoding: Set by user. + */ + void *opaque; + + /** + * the average bitrate + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: Set by user, may be overwritten by libavcodec + * if this info is available in the stream + */ + int64_t bit_rate; + + /** + * AV_CODEC_FLAG_*. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags; + + /** + * AV_CODEC_FLAG2_* + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags2; + + /** + * some codecs need / can use extradata like Huffman tables. + * MJPEG: Huffman tables + * rv10: additional flags + * MPEG-4: global headers (they can be in the bitstream or here) + * The allocated memory should be AV_INPUT_BUFFER_PADDING_SIZE bytes larger + * than extradata_size to avoid problems if it is read with the bitstream reader. + * The bytewise contents of extradata must not depend on the architecture or CPU endianness. + * Must be allocated with the av_malloc() family of functions. + * - encoding: Set/allocated/freed by libavcodec. + * - decoding: Set/allocated/freed by user. + */ + uint8_t *extradata; + int extradata_size; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. For fixed-fps content, + * timebase should be 1/framerate and timestamp increments should be + * identically 1. + * This often, but not always is the inverse of the frame rate or field rate + * for video. 1/time_base is not the average frame rate if the frame rate is not + * constant. + * + * Like containers, elementary streams also can store timestamps, 1/time_base + * is the unit in which these timestamps are specified. + * As example of such codec time base see ISO/IEC 14496-2:2001(E) + * vop_time_increment_resolution and fixed_vop_rate + * (fixed_vop_rate == 0 implies that it is different from the framerate) + * + * - encoding: MUST be set by user. + * - decoding: unused. + */ + AVRational time_base; + + /** + * Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed. + * - encoding: unused. + * - decoding: set by user. + */ + AVRational pkt_timebase; + + /** + * - decoding: For codecs that store a framerate value in the compressed + * bitstream, the decoder may export it here. { 0, 1} when + * unknown. + * - encoding: May be used to signal the framerate of CFR content to an + * encoder. + */ + AVRational framerate; + +#if FF_API_TICKS_PER_FRAME + /** + * For some codecs, the time base is closer to the field rate than the frame rate. + * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration + * if no telecine is used ... + * + * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. + * + * @deprecated + * - decoding: Use AVCodecDescriptor.props & AV_CODEC_PROP_FIELDS + * - encoding: Set AVCodecContext.framerate instead + * + */ + attribute_deprecated + int ticks_per_frame; +#endif + + /** + * Codec delay. + * + * Encoding: Number of frames delay there will be from the encoder input to + * the decoder output. (we assume the decoder matches the spec) + * Decoding: Number of frames delay in addition to what a standard decoder + * as specified in the spec would produce. + * + * Video: + * Number of frames the decoded output will be delayed relative to the + * encoded input. + * + * Audio: + * For encoding, this field is unused (see initial_padding). + * + * For decoding, this is the number of samples the decoder needs to + * output before the decoder's output is valid. When seeking, you should + * start decoding this many samples prior to your desired seek point. + * + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int delay; + + + /* video only */ + /** + * picture width / height. + * + * @note Those fields may not match the values of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: MUST be set by user. + * - decoding: May be set by the user before opening the decoder if known e.g. + * from the container. Some decoders will require the dimensions + * to be set by the caller. During decoding, the decoder may + * overwrite those values as required while parsing the data. + */ + int width, height; + + /** + * Bitstream width / height, may be different from width/height e.g. when + * the decoded frame is cropped before being output or lowres is enabled. + * + * @note Those field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: unused + * - decoding: May be set by the user before opening the decoder if known + * e.g. from the container. During decoding, the decoder may + * overwrite those values as required while parsing the data. + */ + int coded_width, coded_height; + + /** + * sample aspect ratio (0 if unknown) + * That is the width of a pixel divided by the height of the pixel. + * Numerator and denominator must be relatively prime and smaller than 256 for some video standards. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVRational sample_aspect_ratio; + + /** + * Pixel format, see AV_PIX_FMT_xxx. + * May be set by the demuxer if known from headers. + * May be overridden by the decoder if it knows better. + * + * @note This field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: Set by user. + * - decoding: Set by user if known, overridden by libavcodec while + * parsing the data. + */ + enum AVPixelFormat pix_fmt; + + /** + * Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx. + * - encoding: unused. + * - decoding: Set by libavcodec before calling get_format() + */ + enum AVPixelFormat sw_pix_fmt; + + /** + * Chromaticity coordinates of the source primaries. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorPrimaries color_primaries; + + /** + * Color Transfer Characteristic. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user to override the default output color range value, + * If not specified, libavcodec sets the color range depending on the + * output format. + * - decoding: Set by libavcodec, can be set by the user to propagate the + * color range to components reading from the decoder context. + */ + enum AVColorRange color_range; + + /** + * This defines the location of chroma samples. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVChromaLocation chroma_sample_location; + + /** Field order + * - encoding: set by libavcodec + * - decoding: Set by user. + */ + enum AVFieldOrder field_order; + + /** + * number of reference frames + * - encoding: Set by user. + * - decoding: Set by lavc. + */ + int refs; + + /** + * Size of the frame reordering buffer in the decoder. + * For MPEG-2 it is 1 IPB or 0 low delay IP. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int has_b_frames; + + /** + * slice flags + * - encoding: unused + * - decoding: Set by user. + */ + int slice_flags; +#define SLICE_FLAG_CODED_ORDER 0x0001 ///< draw_horiz_band() is called in coded order instead of display +#define SLICE_FLAG_ALLOW_FIELD 0x0002 ///< allow draw_horiz_band() with field slices (MPEG-2 field pics) +#define SLICE_FLAG_ALLOW_PLANE 0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1) + + /** + * If non NULL, 'draw_horiz_band' is called by the libavcodec + * decoder to draw a horizontal band. It improves cache usage. Not + * all codecs can do that. You must check the codec capabilities + * beforehand. + * When multithreading is used, it may be called from multiple threads + * at the same time; threads might draw different parts of the same AVFrame, + * or multiple AVFrames, and there is no guarantee that slices will be drawn + * in order. + * The function is also used by hardware acceleration APIs. + * It is called at least once during frame decoding to pass + * the data needed for hardware render. + * In that mode instead of pixel data, AVFrame points to + * a structure specific to the acceleration API. The application + * reads the structure and can change some fields to indicate progress + * or mark state. + * - encoding: unused + * - decoding: Set by user. + * @param height the height of the slice + * @param y the y position of the slice + * @param type 1->top field, 2->bottom field, 3->frame + * @param offset offset into the AVFrame.data from which the slice should be read + */ + void (*draw_horiz_band)(struct AVCodecContext *s, + const AVFrame *src, int offset[AV_NUM_DATA_POINTERS], + int y, int type, int height); + + /** + * Callback to negotiate the pixel format. Decoding only, may be set by the + * caller before avcodec_open2(). + * + * Called by some decoders to select the pixel format that will be used for + * the output frames. This is mainly used to set up hardware acceleration, + * then the provided format list contains the corresponding hwaccel pixel + * formats alongside the "software" one. The software pixel format may also + * be retrieved from \ref sw_pix_fmt. + * + * This callback will be called when the coded frame properties (such as + * resolution, pixel format, etc.) change and more than one output format is + * supported for those new properties. If a hardware pixel format is chosen + * and initialization for it fails, the callback may be called again + * immediately. + * + * This callback may be called from different threads if the decoder is + * multi-threaded, but not from more than one thread simultaneously. + * + * @param fmt list of formats which may be used in the current + * configuration, terminated by AV_PIX_FMT_NONE. + * @warning Behavior is undefined if the callback returns a value other + * than one of the formats in fmt or AV_PIX_FMT_NONE. + * @return the chosen format or AV_PIX_FMT_NONE + */ + enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + + /** + * maximum number of B-frames between non-B-frames + * Note: The output will be delayed by max_b_frames+1 relative to the input. + * - encoding: Set by user. + * - decoding: unused + */ + int max_b_frames; + + /** + * qscale factor between IP and B-frames + * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_factor; + + /** + * qscale offset between IP and B-frames + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_offset; + + /** + * qscale factor between P- and I-frames + * If > 0 then the last P-frame quantizer will be used (q = lastp_q * factor + offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_factor; + + /** + * qscale offset between P and I-frames + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_offset; + + /** + * luminance masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float lumi_masking; + + /** + * temporary complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float temporal_cplx_masking; + + /** + * spatial complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float spatial_cplx_masking; + + /** + * p block masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float p_masking; + + /** + * darkness masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float dark_masking; + + /** + * noise vs. sse weight for the nsse comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int nsse_weight; + + /** + * motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_cmp; + /** + * subpixel motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_sub_cmp; + /** + * macroblock comparison function (not supported yet) + * - encoding: Set by user. + * - decoding: unused + */ + int mb_cmp; + /** + * interlaced DCT comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int ildct_cmp; +#define FF_CMP_SAD 0 +#define FF_CMP_SSE 1 +#define FF_CMP_SATD 2 +#define FF_CMP_DCT 3 +#define FF_CMP_PSNR 4 +#define FF_CMP_BIT 5 +#define FF_CMP_RD 6 +#define FF_CMP_ZERO 7 +#define FF_CMP_VSAD 8 +#define FF_CMP_VSSE 9 +#define FF_CMP_NSSE 10 +#define FF_CMP_W53 11 +#define FF_CMP_W97 12 +#define FF_CMP_DCTMAX 13 +#define FF_CMP_DCT264 14 +#define FF_CMP_MEDIAN_SAD 15 +#define FF_CMP_CHROMA 256 + + /** + * ME diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int dia_size; + + /** + * amount of previous MV predictors (2a+1 x 2a+1 square) + * - encoding: Set by user. + * - decoding: unused + */ + int last_predictor_count; + + /** + * motion estimation prepass comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_pre_cmp; + + /** + * ME prepass diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int pre_dia_size; + + /** + * subpel ME quality + * - encoding: Set by user. + * - decoding: unused + */ + int me_subpel_quality; + + /** + * maximum motion estimation search range in subpel units + * If 0 then no limit. + * + * - encoding: Set by user. + * - decoding: unused + */ + int me_range; + + /** + * macroblock decision mode + * - encoding: Set by user. + * - decoding: unused + */ + int mb_decision; +#define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp +#define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits +#define FF_MB_DECISION_RD 2 ///< rate distortion + + /** + * custom intra quantization matrix + * Must be allocated with the av_malloc() family of functions, and will be freed in + * avcodec_free_context(). + * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL. + * - decoding: Set/allocated/freed by libavcodec. + */ + uint16_t *intra_matrix; + + /** + * custom inter quantization matrix + * Must be allocated with the av_malloc() family of functions, and will be freed in + * avcodec_free_context(). + * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL. + * - decoding: Set/allocated/freed by libavcodec. + */ + uint16_t *inter_matrix; + + /** + * custom intra quantization matrix + * - encoding: Set by user, can be NULL. + * - decoding: unused. + */ + uint16_t *chroma_intra_matrix; + + /** + * precision of the intra DC coefficient - 8 + * - encoding: Set by user. + * - decoding: Set by libavcodec + */ + int intra_dc_precision; + + /** + * minimum MB Lagrange multiplier + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmin; + + /** + * maximum MB Lagrange multiplier + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmax; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int bidir_refine; + + /** + * minimum GOP size + * - encoding: Set by user. + * - decoding: unused + */ + int keyint_min; + + /** + * the number of pictures in a group of pictures, or 0 for intra_only + * - encoding: Set by user. + * - decoding: unused + */ + int gop_size; + + /** + * Note: Value depends upon the compare function used for fullpel ME. + * - encoding: Set by user. + * - decoding: unused + */ + int mv0_threshold; + + /** + * Number of slices. + * Indicates number of picture subdivisions. Used for parallelized + * decoding. + * - encoding: Set by user + * - decoding: unused + */ + int slices; + + /* audio only */ + int sample_rate; ///< samples per second + + /** + * audio sample format + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVSampleFormat sample_fmt; ///< sample format + + /** + * Audio channel layout. + * - encoding: must be set by the caller, to one of AVCodec.ch_layouts. + * - decoding: may be set by the caller if known e.g. from the container. + * The decoder can then override during decoding as needed. + */ + AVChannelLayout ch_layout; + + /* The following data should not be initialized. */ + /** + * Number of samples per channel in an audio frame. + * + * - encoding: set by libavcodec in avcodec_open2(). Each submitted frame + * except the last must contain exactly frame_size samples per channel. + * May be 0 when the codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE set, then the + * frame size is not restricted. + * - decoding: may be set by some decoders to indicate constant frame size + */ + int frame_size; + + /** + * number of bytes per packet if constant and known or 0 + * Used by some WAV based audio codecs. + */ + int block_align; + + /** + * Audio cutoff bandwidth (0 means "automatic") + * - encoding: Set by user. + * - decoding: unused + */ + int cutoff; + + /** + * Type of service that the audio stream conveys. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVAudioServiceType audio_service_type; + + /** + * desired sample format + * - encoding: Not used. + * - decoding: Set by user. + * Decoder will decode to this format if it can. + */ + enum AVSampleFormat request_sample_fmt; + + /** + * Audio only. The number of "priming" samples (padding) inserted by the + * encoder at the beginning of the audio. I.e. this number of leading + * decoded samples must be discarded by the caller to get the original audio + * without leading padding. + * + * - decoding: unused + * - encoding: Set by libavcodec. The timestamps on the output packets are + * adjusted by the encoder so that they always refer to the + * first sample of the data actually contained in the packet, + * including any added padding. E.g. if the timebase is + * 1/samplerate and the timestamp of the first input sample is + * 0, the timestamp of the first output packet will be + * -initial_padding. + */ + int initial_padding; + + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + * + * - decoding: unused + * - encoding: unused + */ + int trailing_padding; + + /** + * Number of samples to skip after a discontinuity + * - decoding: unused + * - encoding: set by libavcodec + */ + int seek_preroll; + + /** + * This callback is called at the beginning of each frame to get data + * buffer(s) for it. There may be one contiguous buffer for all the data or + * there may be a buffer per each data plane or anything in between. What + * this means is, you may set however many entries in buf[] you feel necessary. + * Each buffer must be reference-counted using the AVBuffer API (see description + * of buf[] below). + * + * The following fields will be set in the frame before this callback is + * called: + * - format + * - width, height (video only) + * - sample_rate, channel_layout, nb_samples (audio only) + * Their values may differ from the corresponding values in + * AVCodecContext. This callback must use the frame values, not the codec + * context values, to calculate the required buffer size. + * + * This callback must fill the following fields in the frame: + * - data[] + * - linesize[] + * - extended_data: + * * if the data is planar audio with more than 8 channels, then this + * callback must allocate and fill extended_data to contain all pointers + * to all data planes. data[] must hold as many pointers as it can. + * extended_data must be allocated with av_malloc() and will be freed in + * av_frame_unref(). + * * otherwise extended_data must point to data + * - buf[] must contain one or more pointers to AVBufferRef structures. Each of + * the frame's data and extended_data pointers must be contained in these. That + * is, one AVBufferRef for each allocated chunk of memory, not necessarily one + * AVBufferRef per data[] entry. See: av_buffer_create(), av_buffer_alloc(), + * and av_buffer_ref(). + * - extended_buf and nb_extended_buf must be allocated with av_malloc() by + * this callback and filled with the extra buffers if there are more + * buffers than buf[] can hold. extended_buf will be freed in + * av_frame_unref(). + * + * If AV_CODEC_CAP_DR1 is not set then get_buffer2() must call + * avcodec_default_get_buffer2() instead of providing buffers allocated by + * some other means. + * + * Each data plane must be aligned to the maximum required by the target + * CPU. + * + * @see avcodec_default_get_buffer2() + * + * Video: + * + * If AV_GET_BUFFER_FLAG_REF is set in flags then the frame may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * avcodec_align_dimensions2() should be used to find the required width and + * height, as they normally need to be rounded up to the next multiple of 16. + * + * Some decoders do not support linesizes changing between frames. + * + * If frame multithreading is used, this callback may be called from a + * different thread, but not from more than one at once. Does not need to be + * reentrant. + * + * @see avcodec_align_dimensions2() + * + * Audio: + * + * Decoders request a buffer of a particular size by setting + * AVFrame.nb_samples prior to calling get_buffer2(). The decoder may, + * however, utilize only part of the buffer by setting AVFrame.nb_samples + * to a smaller value in the output frame. + * + * As a convenience, av_samples_get_buffer_size() and + * av_samples_fill_arrays() in libavutil may be used by custom get_buffer2() + * functions to find the required data size and to fill data pointers and + * linesize. In AVFrame.linesize, only linesize[0] may be set for audio + * since all planes must be the same size. + * + * @see av_samples_get_buffer_size(), av_samples_fill_arrays() + * + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + */ + int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags); + + /* - encoding parameters */ + /** + * number of bits the bitstream is allowed to diverge from the reference. + * the reference can be CBR (for CBR pass1) or VBR (for pass2) + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: unused + */ + int bit_rate_tolerance; + + /** + * Global quality for codecs which cannot change it per frame. + * This should be proportional to MPEG-1/2/4 qscale. + * - encoding: Set by user. + * - decoding: unused + */ + int global_quality; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int compression_level; +#define FF_COMPRESSION_DEFAULT -1 + + float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0) + float qblur; ///< amount of qscale smoothing over time (0.0-1.0) + + /** + * minimum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmin; + + /** + * maximum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmax; + + /** + * maximum quantizer difference between frames + * - encoding: Set by user. + * - decoding: unused + */ + int max_qdiff; + + /** + * decoder bitstream buffer size + * - encoding: Set by user. + * - decoding: May be set by libavcodec. + */ + int rc_buffer_size; + + /** + * ratecontrol override, see RcOverride + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + int rc_override_count; + RcOverride *rc_override; + + /** + * maximum bitrate + * - encoding: Set by user. + * - decoding: Set by user, may be overwritten by libavcodec. + */ + int64_t rc_max_rate; + + /** + * minimum bitrate + * - encoding: Set by user. + * - decoding: unused + */ + int64_t rc_min_rate; + + /** + * Ratecontrol attempt to use, at maximum, of what can be used without an underflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_max_available_vbv_use; + + /** + * Ratecontrol attempt to use, at least, times the amount needed to prevent a vbv overflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_min_vbv_overflow_use; + + /** + * Number of bits which should be loaded into the rc buffer before decoding starts. + * - encoding: Set by user. + * - decoding: unused + */ + int rc_initial_buffer_occupancy; + + /** + * trellis RD quantization + * - encoding: Set by user. + * - decoding: unused + */ + int trellis; + + /** + * pass1 encoding statistics output buffer + * - encoding: Set by libavcodec. + * - decoding: unused + */ + char *stats_out; + + /** + * pass2 encoding statistics input buffer + * Concatenated stuff from stats_out of pass1 should be placed here. + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + char *stats_in; + + /** + * Work around bugs in encoders which sometimes cannot be detected automatically. + * - encoding: Set by user + * - decoding: Set by user + */ + int workaround_bugs; +#define FF_BUG_AUTODETECT 1 ///< autodetection +#define FF_BUG_XVID_ILACE 4 +#define FF_BUG_UMP4 8 +#define FF_BUG_NO_PADDING 16 +#define FF_BUG_AMV 32 +#define FF_BUG_QPEL_CHROMA 64 +#define FF_BUG_STD_QPEL 128 +#define FF_BUG_QPEL_CHROMA2 256 +#define FF_BUG_DIRECT_BLOCKSIZE 512 +#define FF_BUG_EDGE 1024 +#define FF_BUG_HPEL_CHROMA 2048 +#define FF_BUG_DC_CLIP 4096 +#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders. +#define FF_BUG_TRUNCATED 16384 +#define FF_BUG_IEDGE 32768 + + /** + * strictly follow the standard (MPEG-4, ...). + * - encoding: Set by user. + * - decoding: Set by user. + * Setting this to STRICT or higher means the encoder and decoder will + * generally do stupid things, whereas setting it to unofficial or lower + * will mean the encoder might produce output that is not supported by all + * spec-compliant decoders. Decoders don't differentiate between normal, + * unofficial and experimental (that is, they always try to decode things + * when they can) unless they are explicitly asked to behave stupidly + * (=strictly conform to the specs) + * This may only be set to one of the FF_COMPLIANCE_* values in defs.h. + */ + int strict_std_compliance; + + /** + * error concealment flags + * - encoding: unused + * - decoding: Set by user. + */ + int error_concealment; +#define FF_EC_GUESS_MVS 1 +#define FF_EC_DEBLOCK 2 +#define FF_EC_FAVOR_INTER 256 + + /** + * debug + * - encoding: Set by user. + * - decoding: Set by user. + */ + int debug; +#define FF_DEBUG_PICT_INFO 1 +#define FF_DEBUG_RC 2 +#define FF_DEBUG_BITSTREAM 4 +#define FF_DEBUG_MB_TYPE 8 +#define FF_DEBUG_QP 16 +#define FF_DEBUG_DCT_COEFF 0x00000040 +#define FF_DEBUG_SKIP 0x00000080 +#define FF_DEBUG_STARTCODE 0x00000100 +#define FF_DEBUG_ER 0x00000400 +#define FF_DEBUG_MMCO 0x00000800 +#define FF_DEBUG_BUGS 0x00001000 +#define FF_DEBUG_BUFFERS 0x00008000 +#define FF_DEBUG_THREADS 0x00010000 +#define FF_DEBUG_GREEN_MD 0x00800000 +#define FF_DEBUG_NOMC 0x01000000 + + /** + * Error recognition; may misdetect some more or less valid parts as errors. + * This is a bitfield of the AV_EF_* values defined in defs.h. + * + * - encoding: Set by user. + * - decoding: Set by user. + */ + int err_recognition; + + /** + * Hardware accelerator in use + * - encoding: unused. + * - decoding: Set by libavcodec + */ + const struct AVHWAccel *hwaccel; + + /** + * Legacy hardware accelerator context. + * + * For some hardware acceleration methods, the caller may use this field to + * signal hwaccel-specific data to the codec. The struct pointed to by this + * pointer is hwaccel-dependent and defined in the respective header. Please + * refer to the FFmpeg HW accelerator documentation to know how to fill + * this. + * + * In most cases this field is optional - the necessary information may also + * be provided to libavcodec through @ref hw_frames_ctx or @ref + * hw_device_ctx (see avcodec_get_hw_config()). However, in some cases it + * may be the only method of signalling some (optional) information. + * + * The struct and its contents are owned by the caller. + * + * - encoding: May be set by the caller before avcodec_open2(). Must remain + * valid until avcodec_free_context(). + * - decoding: May be set by the caller in the get_format() callback. + * Must remain valid until the next get_format() call, + * or avcodec_free_context() (whichever comes first). + */ + void *hwaccel_context; + + /** + * A reference to the AVHWFramesContext describing the input (for encoding) + * or output (decoding) frames. The reference is set by the caller and + * afterwards owned (and freed) by libavcodec - it should never be read by + * the caller after being set. + * + * - decoding: This field should be set by the caller from the get_format() + * callback. The previous reference (if any) will always be + * unreffed by libavcodec before the get_format() call. + * + * If the default get_buffer2() is used with a hwaccel pixel + * format, then this AVHWFramesContext will be used for + * allocating the frame buffers. + * + * - encoding: For hardware encoders configured to use a hwaccel pixel + * format, this field should be set by the caller to a reference + * to the AVHWFramesContext describing input frames. + * AVHWFramesContext.format must be equal to + * AVCodecContext.pix_fmt. + * + * This field should be set before avcodec_open2() is called. + */ + AVBufferRef *hw_frames_ctx; + + /** + * A reference to the AVHWDeviceContext describing the device which will + * be used by a hardware encoder/decoder. The reference is set by the + * caller and afterwards owned (and freed) by libavcodec. + * + * This should be used if either the codec device does not require + * hardware frames or any that are used are to be allocated internally by + * libavcodec. If the user wishes to supply any of the frames used as + * encoder input or decoder output then hw_frames_ctx should be used + * instead. When hw_frames_ctx is set in get_format() for a decoder, this + * field will be ignored while decoding the associated stream segment, but + * may again be used on a following one after another get_format() call. + * + * For both encoders and decoders this field should be set before + * avcodec_open2() is called and must not be written to thereafter. + * + * Note that some decoders may require this field to be set initially in + * order to support hw_frames_ctx at all - in that case, all frames + * contexts used must be created on the same device. + */ + AVBufferRef *hw_device_ctx; + + /** + * Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated + * decoding (if active). + * - encoding: unused + * - decoding: Set by user (either before avcodec_open2(), or in the + * AVCodecContext.get_format callback) + */ + int hwaccel_flags; + + /** + * Video decoding only. Sets the number of extra hardware frames which + * the decoder will allocate for use by the caller. This must be set + * before avcodec_open2() is called. + * + * Some hardware decoders require all frames that they will use for + * output to be defined in advance before decoding starts. For such + * decoders, the hardware frame pool must therefore be of a fixed size. + * The extra frames set here are on top of any number that the decoder + * needs internally in order to operate normally (for example, frames + * used as reference pictures). + */ + int extra_hw_frames; + + /** + * error + * - encoding: Set by libavcodec if flags & AV_CODEC_FLAG_PSNR. + * - decoding: unused + */ + uint64_t error[AV_NUM_DATA_POINTERS]; + + /** + * DCT algorithm, see FF_DCT_* below + * - encoding: Set by user. + * - decoding: unused + */ + int dct_algo; +#define FF_DCT_AUTO 0 +#define FF_DCT_FASTINT 1 +#define FF_DCT_INT 2 +#define FF_DCT_MMX 3 +#define FF_DCT_ALTIVEC 5 +#define FF_DCT_FAAN 6 + + /** + * IDCT algorithm, see FF_IDCT_* below. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int idct_algo; +#define FF_IDCT_AUTO 0 +#define FF_IDCT_INT 1 +#define FF_IDCT_SIMPLE 2 +#define FF_IDCT_SIMPLEMMX 3 +#define FF_IDCT_ARM 7 +#define FF_IDCT_ALTIVEC 8 +#define FF_IDCT_SIMPLEARM 10 +#define FF_IDCT_XVID 14 +#define FF_IDCT_SIMPLEARMV5TE 16 +#define FF_IDCT_SIMPLEARMV6 17 +#define FF_IDCT_FAAN 20 +#define FF_IDCT_SIMPLENEON 22 +#define FF_IDCT_SIMPLEAUTO 128 + + /** + * bits per sample/pixel from the demuxer (needed for huffyuv). + * - encoding: Set by libavcodec. + * - decoding: Set by user. + */ + int bits_per_coded_sample; + + /** + * Bits per sample/pixel of internal libavcodec pixel/sample format. + * - encoding: set by user. + * - decoding: set by libavcodec. + */ + int bits_per_raw_sample; + + /** + * thread count + * is used to decide how many independent tasks should be passed to execute() + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_count; + + /** + * Which multithreading methods to use. + * Use of FF_THREAD_FRAME will increase decoding delay by one frame per thread, + * so clients which cannot provide future frames should not use it. + * + * - encoding: Set by user, otherwise the default is used. + * - decoding: Set by user, otherwise the default is used. + */ + int thread_type; +#define FF_THREAD_FRAME 1 ///< Decode more than one frame at once +#define FF_THREAD_SLICE 2 ///< Decode more than one part of a single frame at once + + /** + * Which multithreading methods are in use by the codec. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int active_thread_type; + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param count the number of things to execute + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size); + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param c context passed also to func + * @param count the number of things to execute + * @param arg2 argument passed unchanged to func + * @param ret return values of executed functions, must have space for "count" values. May be NULL. + * @param func function that will be called count times, with jobnr from 0 to count-1. + * threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no + * two instances of func executing at the same time will have the same threadnr. + * @return always 0 currently, but code should handle a future improvement where when any call to func + * returns < 0 no further calls to func may be done and < 0 is returned. + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count); + + /** + * profile + * - encoding: Set by user. + * - decoding: Set by libavcodec. + * See the AV_PROFILE_* defines in defs.h. + */ + int profile; +#if FF_API_FF_PROFILE_LEVEL + /** @deprecated The following defines are deprecated; use AV_PROFILE_* + * in defs.h instead. */ +#define FF_PROFILE_UNKNOWN -99 +#define FF_PROFILE_RESERVED -100 + +#define FF_PROFILE_AAC_MAIN 0 +#define FF_PROFILE_AAC_LOW 1 +#define FF_PROFILE_AAC_SSR 2 +#define FF_PROFILE_AAC_LTP 3 +#define FF_PROFILE_AAC_HE 4 +#define FF_PROFILE_AAC_HE_V2 28 +#define FF_PROFILE_AAC_LD 22 +#define FF_PROFILE_AAC_ELD 38 +#define FF_PROFILE_MPEG2_AAC_LOW 128 +#define FF_PROFILE_MPEG2_AAC_HE 131 + +#define FF_PROFILE_DNXHD 0 +#define FF_PROFILE_DNXHR_LB 1 +#define FF_PROFILE_DNXHR_SQ 2 +#define FF_PROFILE_DNXHR_HQ 3 +#define FF_PROFILE_DNXHR_HQX 4 +#define FF_PROFILE_DNXHR_444 5 + +#define FF_PROFILE_DTS 20 +#define FF_PROFILE_DTS_ES 30 +#define FF_PROFILE_DTS_96_24 40 +#define FF_PROFILE_DTS_HD_HRA 50 +#define FF_PROFILE_DTS_HD_MA 60 +#define FF_PROFILE_DTS_EXPRESS 70 +#define FF_PROFILE_DTS_HD_MA_X 61 +#define FF_PROFILE_DTS_HD_MA_X_IMAX 62 + + +#define FF_PROFILE_EAC3_DDP_ATMOS 30 + +#define FF_PROFILE_TRUEHD_ATMOS 30 + +#define FF_PROFILE_MPEG2_422 0 +#define FF_PROFILE_MPEG2_HIGH 1 +#define FF_PROFILE_MPEG2_SS 2 +#define FF_PROFILE_MPEG2_SNR_SCALABLE 3 +#define FF_PROFILE_MPEG2_MAIN 4 +#define FF_PROFILE_MPEG2_SIMPLE 5 + +#define FF_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag +#define FF_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag + +#define FF_PROFILE_H264_BASELINE 66 +#define FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED) +#define FF_PROFILE_H264_MAIN 77 +#define FF_PROFILE_H264_EXTENDED 88 +#define FF_PROFILE_H264_HIGH 100 +#define FF_PROFILE_H264_HIGH_10 110 +#define FF_PROFILE_H264_HIGH_10_INTRA (110|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_MULTIVIEW_HIGH 118 +#define FF_PROFILE_H264_HIGH_422 122 +#define FF_PROFILE_H264_HIGH_422_INTRA (122|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_STEREO_HIGH 128 +#define FF_PROFILE_H264_HIGH_444 144 +#define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244 +#define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_CAVLC_444 44 + +#define FF_PROFILE_VC1_SIMPLE 0 +#define FF_PROFILE_VC1_MAIN 1 +#define FF_PROFILE_VC1_COMPLEX 2 +#define FF_PROFILE_VC1_ADVANCED 3 + +#define FF_PROFILE_MPEG4_SIMPLE 0 +#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE 1 +#define FF_PROFILE_MPEG4_CORE 2 +#define FF_PROFILE_MPEG4_MAIN 3 +#define FF_PROFILE_MPEG4_N_BIT 4 +#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE 5 +#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6 +#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7 +#define FF_PROFILE_MPEG4_HYBRID 8 +#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME 9 +#define FF_PROFILE_MPEG4_CORE_SCALABLE 10 +#define FF_PROFILE_MPEG4_ADVANCED_CODING 11 +#define FF_PROFILE_MPEG4_ADVANCED_CORE 12 +#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13 +#define FF_PROFILE_MPEG4_SIMPLE_STUDIO 14 +#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE 15 + +#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 1 +#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 2 +#define FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION 32768 +#define FF_PROFILE_JPEG2000_DCINEMA_2K 3 +#define FF_PROFILE_JPEG2000_DCINEMA_4K 4 + +#define FF_PROFILE_VP9_0 0 +#define FF_PROFILE_VP9_1 1 +#define FF_PROFILE_VP9_2 2 +#define FF_PROFILE_VP9_3 3 + +#define FF_PROFILE_HEVC_MAIN 1 +#define FF_PROFILE_HEVC_MAIN_10 2 +#define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 +#define FF_PROFILE_HEVC_REXT 4 +#define FF_PROFILE_HEVC_SCC 9 + +#define FF_PROFILE_VVC_MAIN_10 1 +#define FF_PROFILE_VVC_MAIN_10_444 33 + +#define FF_PROFILE_AV1_MAIN 0 +#define FF_PROFILE_AV1_HIGH 1 +#define FF_PROFILE_AV1_PROFESSIONAL 2 + +#define FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT 0xc0 +#define FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1 +#define FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT 0xc2 +#define FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3 +#define FF_PROFILE_MJPEG_JPEG_LS 0xf7 + +#define FF_PROFILE_SBC_MSBC 1 + +#define FF_PROFILE_PRORES_PROXY 0 +#define FF_PROFILE_PRORES_LT 1 +#define FF_PROFILE_PRORES_STANDARD 2 +#define FF_PROFILE_PRORES_HQ 3 +#define FF_PROFILE_PRORES_4444 4 +#define FF_PROFILE_PRORES_XQ 5 + +#define FF_PROFILE_ARIB_PROFILE_A 0 +#define FF_PROFILE_ARIB_PROFILE_C 1 + +#define FF_PROFILE_KLVA_SYNC 0 +#define FF_PROFILE_KLVA_ASYNC 1 + +#define FF_PROFILE_EVC_BASELINE 0 +#define FF_PROFILE_EVC_MAIN 1 +#endif + + /** + * Encoding level descriptor. + * - encoding: Set by user, corresponds to a specific level defined by the + * codec, usually corresponding to the profile level, if not specified it + * is set to FF_LEVEL_UNKNOWN. + * - decoding: Set by libavcodec. + * See AV_LEVEL_* in defs.h. + */ + int level; +#if FF_API_FF_PROFILE_LEVEL + /** @deprecated The following define is deprecated; use AV_LEVEL_UNKOWN + * in defs.h instead. */ +#define FF_LEVEL_UNKNOWN -99 +#endif + + /** + * Properties of the stream that gets decoded + * - encoding: unused + * - decoding: set by libavcodec + */ + unsigned properties; +#define FF_CODEC_PROPERTY_LOSSLESS 0x00000001 +#define FF_CODEC_PROPERTY_CLOSED_CAPTIONS 0x00000002 +#define FF_CODEC_PROPERTY_FILM_GRAIN 0x00000004 + + /** + * Skip loop filtering for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_loop_filter; + + /** + * Skip IDCT/dequantization for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_idct; + + /** + * Skip decoding for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_frame; + + /** + * Skip processing alpha if supported by codec. + * Note that if the format uses pre-multiplied alpha (common with VP6, + * and recommended due to better video quality/compression) + * the image will look as if alpha-blended onto a black background. + * However for formats that do not use pre-multiplied alpha + * there might be serious artefacts (though e.g. libswscale currently + * assumes pre-multiplied alpha anyway). + * + * - decoding: set by user + * - encoding: unused + */ + int skip_alpha; + + /** + * Number of macroblock rows at the top which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_top; + + /** + * Number of macroblock rows at the bottom which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_bottom; + + /** + * low resolution decoding, 1-> 1/2 size, 2->1/4 size + * - encoding: unused + * - decoding: Set by user. + */ + int lowres; + + /** + * AVCodecDescriptor + * - encoding: unused. + * - decoding: set by libavcodec. + */ + const struct AVCodecDescriptor *codec_descriptor; + + /** + * Character encoding of the input subtitles file. + * - decoding: set by user + * - encoding: unused + */ + char *sub_charenc; + + /** + * Subtitles character encoding mode. Formats or codecs might be adjusting + * this setting (if they are doing the conversion themselves for instance). + * - decoding: set by libavcodec + * - encoding: unused + */ + int sub_charenc_mode; +#define FF_SUB_CHARENC_MODE_DO_NOTHING -1 ///< do nothing (demuxer outputs a stream supposed to be already in UTF-8, or the codec is bitmap for instance) +#define FF_SUB_CHARENC_MODE_AUTOMATIC 0 ///< libavcodec will select the mode itself +#define FF_SUB_CHARENC_MODE_PRE_DECODER 1 ///< the AVPacket data needs to be recoded to UTF-8 before being fed to the decoder, requires iconv +#define FF_SUB_CHARENC_MODE_IGNORE 2 ///< neither convert the subtitles, nor check them for valid UTF-8 + + /** + * Header containing style information for text subtitles. + * For SUBTITLE_ASS subtitle type, it should contain the whole ASS + * [Script Info] and [V4+ Styles] section, plus the [Events] line and + * the Format line following. It shouldn't include any Dialogue line. + * - encoding: Set/allocated/freed by user (before avcodec_open2()) + * - decoding: Set/allocated/freed by libavcodec (by avcodec_open2()) + */ + int subtitle_header_size; + uint8_t *subtitle_header; + + /** + * dump format separator. + * can be ", " or "\n " or anything else + * - encoding: Set by user. + * - decoding: Set by user. + */ + uint8_t *dump_separator; + + /** + * ',' separated list of allowed decoders. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *codec_whitelist; + + /** + * Additional data associated with the entire coded stream. + * + * - decoding: may be set by user before calling avcodec_open2(). + * - encoding: may be set by libavcodec after avcodec_open2(). + */ + AVPacketSideData *coded_side_data; + int nb_coded_side_data; + + /** + * Bit set of AV_CODEC_EXPORT_DATA_* flags, which affects the kind of + * metadata exported in frame, packet, or coded stream side data by + * decoders and encoders. + * + * - decoding: set by user + * - encoding: set by user + */ + int export_side_data; + + /** + * The number of pixels per image to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_pixels; + + /** + * Video decoding only. Certain video codecs support cropping, meaning that + * only a sub-rectangle of the decoded frame is intended for display. This + * option controls how cropping is handled by libavcodec. + * + * When set to 1 (the default), libavcodec will apply cropping internally. + * I.e. it will modify the output frame width/height fields and offset the + * data pointers (only by as much as possible while preserving alignment, or + * by the full amount if the AV_CODEC_FLAG_UNALIGNED flag is set) so that + * the frames output by the decoder refer only to the cropped area. The + * crop_* fields of the output frames will be zero. + * + * When set to 0, the width/height fields of the output frames will be set + * to the coded dimensions and the crop_* fields will describe the cropping + * rectangle. Applying the cropping is left to the caller. + * + * @warning When hardware acceleration with opaque output frames is used, + * libavcodec is unable to apply cropping from the top/left border. + * + * @note when this option is set to zero, the width/height fields of the + * AVCodecContext and output AVFrames have different meanings. The codec + * context fields store display dimensions (with the coded dimensions in + * coded_width/height), while the frame fields store the coded dimensions + * (with the display dimensions being determined by the crop_* fields). + */ + int apply_cropping; + + /** + * The percentage of damaged samples to discard a frame. + * + * - decoding: set by user + * - encoding: unused + */ + int discard_damaged_percentage; + + /** + * The number of samples per frame to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_samples; + + /** + * This callback is called at the beginning of each packet to get a data + * buffer for it. + * + * The following field will be set in the packet before this callback is + * called: + * - size + * This callback must use the above value to calculate the required buffer size, + * which must padded by at least AV_INPUT_BUFFER_PADDING_SIZE bytes. + * + * In some specific cases, the encoder may not use the entire buffer allocated by this + * callback. This will be reflected in the size value in the packet once returned by + * avcodec_receive_packet(). + * + * This callback must fill the following fields in the packet: + * - data: alignment requirements for AVPacket apply, if any. Some architectures and + * encoders may benefit from having aligned data. + * - buf: must contain a pointer to an AVBufferRef structure. The packet's + * data pointer must be contained in it. See: av_buffer_create(), av_buffer_alloc(), + * and av_buffer_ref(). + * + * If AV_CODEC_CAP_DR1 is not set then get_encode_buffer() must call + * avcodec_default_get_encode_buffer() instead of providing a buffer allocated by + * some other means. + * + * The flags field may contain a combination of AV_GET_ENCODE_BUFFER_FLAG_ flags. + * They may be used for example to hint what use the buffer may get after being + * created. + * Implementations of this callback may ignore flags they don't understand. + * If AV_GET_ENCODE_BUFFER_FLAG_REF is set in flags then the packet may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * This callback must be thread-safe, as when frame threading is used, it may + * be called from multiple threads simultaneously. + * + * @see avcodec_default_get_encode_buffer() + * + * - encoding: Set by libavcodec, user can override. + * - decoding: unused + */ + int (*get_encode_buffer)(struct AVCodecContext *s, AVPacket *pkt, int flags); + + /** + * Frame counter, set by libavcodec. + * + * - decoding: total number of frames returned from the decoder so far. + * - encoding: total number of frames passed to the encoder so far. + * + * @note the counter is not incremented if encoding/decoding resulted in + * an error. + */ + int64_t frame_num; + + /** + * Decoding only. May be set by the caller before avcodec_open2() to an + * av_malloc()'ed array (or via AVOptions). Owned and freed by the decoder + * afterwards. + * + * Side data attached to decoded frames may come from several sources: + * 1. coded_side_data, which the decoder will for certain types translate + * from packet-type to frame-type and attach to frames; + * 2. side data attached to an AVPacket sent for decoding (same + * considerations as above); + * 3. extracted from the coded bytestream. + * The first two cases are supplied by the caller and typically come from a + * container. + * + * This array configures decoder behaviour in cases when side data of the + * same type is present both in the coded bytestream and in the + * user-supplied side data (items 1. and 2. above). In all cases, at most + * one instance of each side data type will be attached to output frames. By + * default it will be the bytestream side data. Adding an + * AVPacketSideDataType value to this array will flip the preference for + * this type, thus making the decoder prefer user-supplied side data over + * bytestream. In case side data of the same type is present both in + * coded_data and attacked to a packet, the packet instance always has + * priority. + * + * The array may also contain a single -1, in which case the preference is + * switched for all side data types. + */ + int *side_data_prefer_packet; + /** + * Number of entries in side_data_prefer_packet. + */ + unsigned nb_side_data_prefer_packet; + + /** + * Array containing static side data, such as HDR10 CLL / MDCV structures. + * Side data entries should be allocated by usage of helpers defined in + * libavutil/frame.h. + * + * - encoding: may be set by user before calling avcodec_open2() for + * encoder configuration. Afterwards owned and freed by the + * encoder. + * - decoding: unused + */ + AVFrameSideData **decoded_side_data; + int nb_decoded_side_data; +} AVCodecContext; + +/** + * @defgroup lavc_hwaccel AVHWAccel + * + * @note Nothing in this structure should be accessed by the user. At some + * point in future it will not be externally visible at all. + * + * @{ + */ +typedef struct AVHWAccel { + /** + * Name of the hardware accelerated codec. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + */ + const char *name; + + /** + * Type of codec implemented by the hardware accelerator. + * + * See AVMEDIA_TYPE_xxx + */ + enum AVMediaType type; + + /** + * Codec implemented by the hardware accelerator. + * + * See AV_CODEC_ID_xxx + */ + enum AVCodecID id; + + /** + * Supported pixel format. + * + * Only hardware accelerated formats are supported here. + */ + enum AVPixelFormat pix_fmt; + + /** + * Hardware accelerated codec capabilities. + * see AV_HWACCEL_CODEC_CAP_* + */ + int capabilities; +} AVHWAccel; + +/** + * HWAccel is experimental and is thus avoided in favor of non experimental + * codecs + */ +#define AV_HWACCEL_CODEC_CAP_EXPERIMENTAL 0x0200 + +/** + * Hardware acceleration should be used for decoding even if the codec level + * used is unknown or higher than the maximum supported level reported by the + * hardware driver. + * + * It's generally a good idea to pass this flag unless you have a specific + * reason not to, as hardware tends to under-report supported levels. + */ +#define AV_HWACCEL_FLAG_IGNORE_LEVEL (1 << 0) + +/** + * Hardware acceleration can output YUV pixel formats with a different chroma + * sampling than 4:2:0 and/or other than 8 bits per component. + */ +#define AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH (1 << 1) + +/** + * Hardware acceleration should still be attempted for decoding when the + * codec profile does not match the reported capabilities of the hardware. + * + * For example, this can be used to try to decode baseline profile H.264 + * streams in hardware - it will often succeed, because many streams marked + * as baseline profile actually conform to constrained baseline profile. + * + * @warning If the stream is actually not supported then the behaviour is + * undefined, and may include returning entirely incorrect output + * while indicating success. + */ +#define AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH (1 << 2) + +/** + * Some hardware decoders (namely nvdec) can either output direct decoder + * surfaces, or make an on-device copy and return said copy. + * There is a hard limit on how many decoder surfaces there can be, and it + * cannot be accurately guessed ahead of time. + * For some processing chains, this can be okay, but others will run into the + * limit and in turn produce very confusing errors that require fine tuning of + * more or less obscure options by the user, or in extreme cases cannot be + * resolved at all without inserting an avfilter that forces a copy. + * + * Thus, the hwaccel will by default make a copy for safety and resilience. + * If a users really wants to minimize the amount of copies, they can set this + * flag and ensure their processing chain does not exhaust the surface pool. + */ +#define AV_HWACCEL_FLAG_UNSAFE_OUTPUT (1 << 3) + +/** + * @} + */ + +enum AVSubtitleType { + SUBTITLE_NONE, + + SUBTITLE_BITMAP, ///< A bitmap, pict will be set + + /** + * Plain text, the text field must be set by the decoder and is + * authoritative. ass and pict fields may contain approximations. + */ + SUBTITLE_TEXT, + + /** + * Formatted text, the ass field must be set by the decoder and is + * authoritative. pict and text fields may contain approximations. + */ + SUBTITLE_ASS, +}; + +#define AV_SUBTITLE_FLAG_FORCED 0x00000001 + +typedef struct AVSubtitleRect { + int x; ///< top left corner of pict, undefined when pict is not set + int y; ///< top left corner of pict, undefined when pict is not set + int w; ///< width of pict, undefined when pict is not set + int h; ///< height of pict, undefined when pict is not set + int nb_colors; ///< number of colors in pict, undefined when pict is not set + + /** + * data+linesize for the bitmap of this subtitle. + * Can be set for text/ass as well once they are rendered. + */ + uint8_t *data[4]; + int linesize[4]; + + int flags; + enum AVSubtitleType type; + + char *text; ///< 0 terminated plain UTF-8 text + + /** + * 0 terminated ASS/SSA compatible event line. + * The presentation of this is unaffected by the other values in this + * struct. + */ + char *ass; +} AVSubtitleRect; + +typedef struct AVSubtitle { + uint16_t format; /* 0 = graphics */ + uint32_t start_display_time; /* relative to packet pts, in ms */ + uint32_t end_display_time; /* relative to packet pts, in ms */ + unsigned num_rects; + AVSubtitleRect **rects; + int64_t pts; ///< Same as packet pts, in AV_TIME_BASE +} AVSubtitle; + +/** + * Return the LIBAVCODEC_VERSION_INT constant. + */ +unsigned avcodec_version(void); + +/** + * Return the libavcodec build-time configuration. + */ +const char *avcodec_configuration(void); + +/** + * Return the libavcodec license. + */ +const char *avcodec_license(void); + +/** + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct should be freed with avcodec_free_context(). + * + * @param codec if non-NULL, allocate private data and initialize defaults + * for the given codec. It is illegal to then call avcodec_open2() + * with a different codec. + * If NULL, then the codec-specific defaults won't be initialized, + * which may result in suboptimal default settings (this is + * important mainly for encoders, e.g. libx264). + * + * @return An AVCodecContext filled with default values or NULL on failure. + */ +AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); + +/** + * Free the codec context and everything associated with it and write NULL to + * the provided pointer. + */ +void avcodec_free_context(AVCodecContext **avctx); + +/** + * Get the AVClass for AVCodecContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_class(void); + +/** + * Get the AVClass for AVSubtitleRect. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_subtitle_rect_class(void); + +/** + * Fill the parameters struct based on the values from the supplied codec + * context. Any allocated fields in par are freed and replaced with duplicates + * of the corresponding fields in codec. + * + * @return >= 0 on success, a negative AVERROR code on failure + */ +int avcodec_parameters_from_context(struct AVCodecParameters *par, + const AVCodecContext *codec); + +/** + * Fill the codec context based on the values from the supplied codec + * parameters. Any allocated fields in codec that have a corresponding field in + * par are freed and replaced with duplicates of the corresponding field in par. + * Fields in codec that do not have a counterpart in par are not touched. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_to_context(AVCodecContext *codec, + const struct AVCodecParameters *par); + +/** + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated with avcodec_alloc_context3(). + * + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. + * + * Depending on the codec, you might need to set options in the codec context + * also for decoding (e.g. width, height, or the pixel or audio sample format in + * the case the information is not available in the bitstream, as when decoding + * raw audio or video). + * + * Options in the codec context can be set either by setting them in the options + * AVDictionary, or by setting the values in the context itself, directly or by + * using the av_opt_set() API before calling this function. + * + * Example: + * @code + * av_dict_set(&opts, "b", "2.5M", 0); + * codec = avcodec_find_decoder(AV_CODEC_ID_H264); + * if (!codec) + * exit(1); + * + * context = avcodec_alloc_context3(codec); + * + * if (avcodec_open2(context, codec, opts) < 0) + * exit(1); + * @endcode + * + * In the case AVCodecParameters are available (e.g. when demuxing a stream + * using libavformat, and accessing the AVStream contained in the demuxer), the + * codec parameters can be copied to the codec context using + * avcodec_parameters_to_context(), as in the following example: + * + * @code + * AVStream *stream = ...; + * context = avcodec_alloc_context3(codec); + * if (avcodec_parameters_to_context(context, stream->codecpar) < 0) + * exit(1); + * if (avcodec_open2(context, codec, NULL) < 0) + * exit(1); + * @endcode + * + * @note Always call this function before using decoding routines (such as + * @ref avcodec_receive_frame()). + * + * @param avctx The context to initialize. + * @param codec The codec to open this context for. If a non-NULL codec has been + * previously passed to avcodec_alloc_context3() or + * for this context, then this parameter MUST be either NULL or + * equal to the previously passed codec. + * @param options A dictionary filled with AVCodecContext and codec-private + * options, which are set on top of the options already set in + * avctx, can be NULL. On return this object will be filled with + * options that were not found in the avctx codec context. + * + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), + * av_dict_set(), av_opt_set(), av_opt_find(), avcodec_parameters_to_context() + */ +int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); + +#if FF_API_AVCODEC_CLOSE +/** + * Close a given AVCodecContext and free all the data associated with it + * (but not the AVCodecContext itself). + * + * Calling this function on an AVCodecContext that hasn't been opened will free + * the codec-specific data allocated in avcodec_alloc_context3() with a non-NULL + * codec. Subsequent calls will do nothing. + * + * @deprecated Do not use this function. Use avcodec_free_context() to destroy a + * codec context (either open or closed). Opening and closing a codec context + * multiple times is not supported anymore -- use multiple codec contexts + * instead. + */ +attribute_deprecated +int avcodec_close(AVCodecContext *avctx); +#endif + +/** + * Free all allocated data in the given subtitle struct. + * + * @param sub AVSubtitle to free. + */ +void avsubtitle_free(AVSubtitle *sub); + +/** + * @} + */ + +/** + * @addtogroup lavc_decoding + * @{ + */ + +/** + * The default callback for AVCodecContext.get_buffer2(). It is made public so + * it can be called by custom get_buffer2() implementations for decoders without + * AV_CODEC_CAP_DR1 set. + */ +int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags); + +/** + * The default callback for AVCodecContext.get_encode_buffer(). It is made public so + * it can be called by custom get_encode_buffer() implementations for encoders without + * AV_CODEC_CAP_DR1 set. + */ +int avcodec_default_get_encode_buffer(AVCodecContext *s, AVPacket *pkt, int flags); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you do not use any horizontal + * padding. + * + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. + */ +void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you also ensure that all + * line sizes are a multiple of the respective linesize_align[i]. + * + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. + */ +void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, + int linesize_align[AV_NUM_DATA_POINTERS]); + +/** + * Decode a subtitle message. + * Return a negative value on error, otherwise return the number of bytes used. + * If no subtitle could be decompressed, got_sub_ptr is zero. + * Otherwise, the subtitle is stored in *sub. + * Note that AV_CODEC_CAP_DR1 is not available for subtitle codecs. This is for + * simplicity, because the performance difference is expected to be negligible + * and reusing a get_buffer written for video codecs would probably perform badly + * due to a potentially very different allocation pattern. + * + * Some decoders (those marked with AV_CODEC_CAP_DELAY) have a delay between input + * and output. This means that for some packets they will not immediately + * produce decoded output and need to be flushed at the end of decoding to get + * all the decoded data. Flushing is done by calling this function with packets + * with avpkt->data set to NULL and avpkt->size set to 0 until it stops + * returning subtitles. It is safe to flush even those decoders that are not + * marked with AV_CODEC_CAP_DELAY, then no subtitles will be returned. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx the codec context + * @param[out] sub The preallocated AVSubtitle in which the decoded subtitle will be stored, + * must be freed with avsubtitle_free if *got_sub_ptr is set. + * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. + * @param[in] avpkt The input AVPacket containing the input buffer. + */ +int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt); + +/** + * Supply raw packet data as input to a decoder. + * + * Internally, this call will copy relevant AVCodecContext fields, which can + * influence decoding per-packet, and apply them when the packet is actually + * decoded. (For example AVCodecContext.skip_frame, which might direct the + * decoder to drop the frame contained by the packet sent with this function.) + * + * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE + * larger than the actual read bytes because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx codec context + * @param[in] avpkt The input AVPacket. Usually, this will be a single video + * frame, or several complete audio frames. + * Ownership of the packet remains with the caller, and the + * decoder will not write to the packet. The decoder may create + * a reference to the packet data (or copy it if the packet is + * not reference-counted). + * Unlike with older APIs, the packet is always fully consumed, + * and if it contains multiple frames (e.g. some audio codecs), + * will require you to call avcodec_receive_frame() multiple + * times afterwards before you can send a new packet. + * It can be NULL (or an AVPacket with data set to NULL and + * size set to 0); in this case, it is considered a flush + * packet, which signals the end of the stream. Sending the + * first flush packet will return success. Subsequent ones are + * unnecessary and will return AVERROR_EOF. If the decoder + * still has frames buffered, it will return them after sending + * a flush packet. + * + * @retval 0 success + * @retval AVERROR(EAGAIN) input is not accepted in the current state - user + * must read output with avcodec_receive_frame() (once + * all output is read, the packet should be resent, + * and the call will not fail with EAGAIN). + * @retval AVERROR_EOF the decoder has been flushed, and no new packets can be + * sent to it (also returned if more than 1 flush + * packet is sent) + * @retval AVERROR(EINVAL) codec not opened, it is an encoder, or requires flush + * @retval AVERROR(ENOMEM) failed to add packet to internal queue, or similar + * @retval "another negative error code" legitimate decoding errors + */ +int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); + +/** + * Return decoded output data from a decoder or encoder (when the + * @ref AV_CODEC_FLAG_RECON_FRAME flag is used). + * + * @param avctx codec context + * @param frame This will be set to a reference-counted video or audio + * frame (depending on the decoder type) allocated by the + * codec. Note that the function will always call + * av_frame_unref(frame) before doing anything else. + * + * @retval 0 success, a frame was returned + * @retval AVERROR(EAGAIN) output is not available in this state - user must + * try to send new input + * @retval AVERROR_EOF the codec has been fully flushed, and there will be + * no more output frames + * @retval AVERROR(EINVAL) codec not opened, or it is an encoder without the + * @ref AV_CODEC_FLAG_RECON_FRAME flag enabled + * @retval "other negative error code" legitimate decoding errors + */ +int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); + +/** + * Supply a raw video or audio frame to the encoder. Use avcodec_receive_packet() + * to retrieve buffered output packets. + * + * @param avctx codec context + * @param[in] frame AVFrame containing the raw audio or video frame to be encoded. + * Ownership of the frame remains with the caller, and the + * encoder will not write to the frame. The encoder may create + * a reference to the frame data (or copy it if the frame is + * not reference-counted). + * It can be NULL, in which case it is considered a flush + * packet. This signals the end of the stream. If the encoder + * still has packets buffered, it will return them after this + * call. Once flushing mode has been entered, additional flush + * packets are ignored, and sending frames will return + * AVERROR_EOF. + * + * For audio: + * If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * can have any number of samples. + * If it is not set, frame->nb_samples must be equal to + * avctx->frame_size for all frames except the last. + * The final frame may be smaller than avctx->frame_size. + * @retval 0 success + * @retval AVERROR(EAGAIN) input is not accepted in the current state - user must + * read output with avcodec_receive_packet() (once all + * output is read, the packet should be resent, and the + * call will not fail with EAGAIN). + * @retval AVERROR_EOF the encoder has been flushed, and no new frames can + * be sent to it + * @retval AVERROR(EINVAL) codec not opened, it is a decoder, or requires flush + * @retval AVERROR(ENOMEM) failed to add packet to internal queue, or similar + * @retval "another negative error code" legitimate encoding errors + */ +int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); + +/** + * Read encoded data from the encoder. + * + * @param avctx codec context + * @param avpkt This will be set to a reference-counted packet allocated by the + * encoder. Note that the function will always call + * av_packet_unref(avpkt) before doing anything else. + * @retval 0 success + * @retval AVERROR(EAGAIN) output is not available in the current state - user must + * try to send input + * @retval AVERROR_EOF the encoder has been fully flushed, and there will be no + * more output packets + * @retval AVERROR(EINVAL) codec not opened, or it is a decoder + * @retval "another negative error code" legitimate encoding errors + */ +int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); + +/** + * Create and return a AVHWFramesContext with values adequate for hardware + * decoding. This is meant to get called from the get_format callback, and is + * a helper for preparing a AVHWFramesContext for AVCodecContext.hw_frames_ctx. + * This API is for decoding with certain hardware acceleration modes/APIs only. + * + * The returned AVHWFramesContext is not initialized. The caller must do this + * with av_hwframe_ctx_init(). + * + * Calling this function is not a requirement, but makes it simpler to avoid + * codec or hardware API specific details when manually allocating frames. + * + * Alternatively to this, an API user can set AVCodecContext.hw_device_ctx, + * which sets up AVCodecContext.hw_frames_ctx fully automatically, and makes + * it unnecessary to call this function or having to care about + * AVHWFramesContext initialization at all. + * + * There are a number of requirements for calling this function: + * + * - It must be called from get_format with the same avctx parameter that was + * passed to get_format. Calling it outside of get_format is not allowed, and + * can trigger undefined behavior. + * - The function is not always supported (see description of return values). + * Even if this function returns successfully, hwaccel initialization could + * fail later. (The degree to which implementations check whether the stream + * is actually supported varies. Some do this check only after the user's + * get_format callback returns.) + * - The hw_pix_fmt must be one of the choices suggested by get_format. If the + * user decides to use a AVHWFramesContext prepared with this API function, + * the user must return the same hw_pix_fmt from get_format. + * - The device_ref passed to this function must support the given hw_pix_fmt. + * - After calling this API function, it is the user's responsibility to + * initialize the AVHWFramesContext (returned by the out_frames_ref parameter), + * and to set AVCodecContext.hw_frames_ctx to it. If done, this must be done + * before returning from get_format (this is implied by the normal + * AVCodecContext.hw_frames_ctx API rules). + * - The AVHWFramesContext parameters may change every time time get_format is + * called. Also, AVCodecContext.hw_frames_ctx is reset before get_format. So + * you are inherently required to go through this process again on every + * get_format call. + * - It is perfectly possible to call this function without actually using + * the resulting AVHWFramesContext. One use-case might be trying to reuse a + * previously initialized AVHWFramesContext, and calling this API function + * only to test whether the required frame parameters have changed. + * - Fields that use dynamically allocated values of any kind must not be set + * by the user unless setting them is explicitly allowed by the documentation. + * If the user sets AVHWFramesContext.free and AVHWFramesContext.user_opaque, + * the new free callback must call the potentially set previous free callback. + * This API call may set any dynamically allocated fields, including the free + * callback. + * + * The function will set at least the following fields on AVHWFramesContext + * (potentially more, depending on hwaccel API): + * + * - All fields set by av_hwframe_ctx_alloc(). + * - Set the format field to hw_pix_fmt. + * - Set the sw_format field to the most suited and most versatile format. (An + * implication is that this will prefer generic formats over opaque formats + * with arbitrary restrictions, if possible.) + * - Set the width/height fields to the coded frame size, rounded up to the + * API-specific minimum alignment. + * - Only _if_ the hwaccel requires a pre-allocated pool: set the initial_pool_size + * field to the number of maximum reference surfaces possible with the codec, + * plus 1 surface for the user to work (meaning the user can safely reference + * at most 1 decoded surface at a time), plus additional buffering introduced + * by frame threading. If the hwaccel does not require pre-allocation, the + * field is left to 0, and the decoder will allocate new surfaces on demand + * during decoding. + * - Possibly AVHWFramesContext.hwctx fields, depending on the underlying + * hardware API. + * + * Essentially, out_frames_ref returns the same as av_hwframe_ctx_alloc(), but + * with basic frame parameters set. + * + * The function is stateless, and does not change the AVCodecContext or the + * device_ref AVHWDeviceContext. + * + * @param avctx The context which is currently calling get_format, and which + * implicitly contains all state needed for filling the returned + * AVHWFramesContext properly. + * @param device_ref A reference to the AVHWDeviceContext describing the device + * which will be used by the hardware decoder. + * @param hw_pix_fmt The hwaccel format you are going to return from get_format. + * @param out_frames_ref On success, set to a reference to an _uninitialized_ + * AVHWFramesContext, created from the given device_ref. + * Fields will be set to values required for decoding. + * Not changed if an error is returned. + * @return zero on success, a negative value on error. The following error codes + * have special semantics: + * AVERROR(ENOENT): the decoder does not support this functionality. Setup + * is always manual, or it is a decoder which does not + * support setting AVCodecContext.hw_frames_ctx at all, + * or it is a software format. + * AVERROR(EINVAL): it is known that hardware decoding is not supported for + * this configuration, or the device_ref is not supported + * for the hwaccel referenced by hw_pix_fmt. + */ +int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, + AVBufferRef *device_ref, + enum AVPixelFormat hw_pix_fmt, + AVBufferRef **out_frames_ref); + + + +/** + * @defgroup lavc_parsing Frame parsing + * @{ + */ + +enum AVPictureStructure { + AV_PICTURE_STRUCTURE_UNKNOWN, ///< unknown + AV_PICTURE_STRUCTURE_TOP_FIELD, ///< coded as top field + AV_PICTURE_STRUCTURE_BOTTOM_FIELD, ///< coded as bottom field + AV_PICTURE_STRUCTURE_FRAME, ///< coded as frame +}; + +typedef struct AVCodecParserContext { + void *priv_data; + const struct AVCodecParser *parser; + int64_t frame_offset; /* offset of the current frame */ + int64_t cur_offset; /* current offset + (incremented by each av_parser_parse()) */ + int64_t next_frame_offset; /* offset of the next frame */ + /* video info */ + int pict_type; /* XXX: Put it back in AVCodecContext. */ + /** + * This field is used for proper frame duration computation in lavf. + * It signals, how much longer the frame duration of the current frame + * is compared to normal frame duration. + * + * frame_duration = (1 + repeat_pict) * time_base + * + * It is used by codecs like H.264 to display telecined material. + */ + int repeat_pict; /* XXX: Put it back in AVCodecContext. */ + int64_t pts; /* pts of the current frame */ + int64_t dts; /* dts of the current frame */ + + /* private data */ + int64_t last_pts; + int64_t last_dts; + int fetch_timestamp; + +#define AV_PARSER_PTS_NB 4 + int cur_frame_start_index; + int64_t cur_frame_offset[AV_PARSER_PTS_NB]; + int64_t cur_frame_pts[AV_PARSER_PTS_NB]; + int64_t cur_frame_dts[AV_PARSER_PTS_NB]; + + int flags; +#define PARSER_FLAG_COMPLETE_FRAMES 0x0001 +#define PARSER_FLAG_ONCE 0x0002 +/// Set if the parser has a valid file offset +#define PARSER_FLAG_FETCHED_OFFSET 0x0004 +#define PARSER_FLAG_USE_CODEC_TS 0x1000 + + int64_t offset; ///< byte offset from starting packet start + int64_t cur_frame_end[AV_PARSER_PTS_NB]; + + /** + * Set by parser to 1 for key frames and 0 for non-key frames. + * It is initialized to -1, so if the parser doesn't set this flag, + * old-style fallback using AV_PICTURE_TYPE_I picture type as key frames + * will be used. + */ + int key_frame; + + // Timestamp generation support: + /** + * Synchronization point for start of timestamp generation. + * + * Set to >0 for sync point, 0 for no sync point and <0 for undefined + * (default). + * + * For example, this corresponds to presence of H.264 buffering period + * SEI message. + */ + int dts_sync_point; + + /** + * Offset of the current timestamp against last timestamp sync point in + * units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain a valid timestamp offset. + * + * Note that the timestamp of sync point has usually a nonzero + * dts_ref_dts_delta, which refers to the previous sync point. Offset of + * the next frame after timestamp sync point will be usually 1. + * + * For example, this corresponds to H.264 cpb_removal_delay. + */ + int dts_ref_dts_delta; + + /** + * Presentation delay of current frame in units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain valid non-negative timestamp delta (presentation time of a frame + * must not lie in the past). + * + * This delay represents the difference between decoding and presentation + * time of the frame. + * + * For example, this corresponds to H.264 dpb_output_delay. + */ + int pts_dts_delta; + + /** + * Position of the packet in file. + * + * Analogous to cur_frame_pts/dts + */ + int64_t cur_frame_pos[AV_PARSER_PTS_NB]; + + /** + * Byte position of currently parsed frame in stream. + */ + int64_t pos; + + /** + * Previous frame byte position. + */ + int64_t last_pos; + + /** + * Duration of the current frame. + * For audio, this is in units of 1 / AVCodecContext.sample_rate. + * For all other types, this is in units of AVCodecContext.time_base. + */ + int duration; + + enum AVFieldOrder field_order; + + /** + * Indicate whether a picture is coded as a frame, top field or bottom field. + * + * For example, H.264 field_pic_flag equal to 0 corresponds to + * AV_PICTURE_STRUCTURE_FRAME. An H.264 picture with field_pic_flag + * equal to 1 and bottom_field_flag equal to 0 corresponds to + * AV_PICTURE_STRUCTURE_TOP_FIELD. + */ + enum AVPictureStructure picture_structure; + + /** + * Picture number incremented in presentation or output order. + * This field may be reinitialized at the first picture of a new sequence. + * + * For example, this corresponds to H.264 PicOrderCnt. + */ + int output_picture_number; + + /** + * Dimensions of the decoded video intended for presentation. + */ + int width; + int height; + + /** + * Dimensions of the coded video. + */ + int coded_width; + int coded_height; + + /** + * The format of the coded data, corresponds to enum AVPixelFormat for video + * and for enum AVSampleFormat for audio. + * + * Note that a decoder can have considerable freedom in how exactly it + * decodes the data, so the format reported here might be different from the + * one returned by a decoder. + */ + int format; +} AVCodecParserContext; + +typedef struct AVCodecParser { + int codec_ids[7]; /* several codec IDs are permitted */ + int priv_data_size; + int (*parser_init)(AVCodecParserContext *s); + /* This callback never returns an error, a negative value means that + * the frame start was in a previous packet. */ + int (*parser_parse)(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size); + void (*parser_close)(AVCodecParserContext *s); + int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size); +} AVCodecParser; + +/** + * Iterate over all registered codec parsers. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec parser or NULL when the iteration is + * finished + */ +const AVCodecParser *av_parser_iterate(void **opaque); + +AVCodecParserContext *av_parser_init(int codec_id); + +/** + * Parse a packet. + * + * @param s parser context. + * @param avctx codec context. + * @param poutbuf set to pointer to parsed buffer or NULL if not yet finished. + * @param poutbuf_size set to size of parsed buffer or zero if not yet finished. + * @param buf input buffer. + * @param buf_size buffer size in bytes without the padding. I.e. the full buffer + size is assumed to be buf_size + AV_INPUT_BUFFER_PADDING_SIZE. + To signal EOF, this should be 0 (so that the last frame + can be output). + * @param pts input presentation timestamp. + * @param dts input decoding timestamp. + * @param pos input byte position in stream. + * @return the number of bytes of the input bitstream used. + * + * Example: + * @code + * while(in_len){ + * len = av_parser_parse2(myparser, AVCodecContext, &data, &size, + * in_data, in_len, + * pts, dts, pos); + * in_data += len; + * in_len -= len; + * + * if(size) + * decode_frame(data, size); + * } + * @endcode + */ +int av_parser_parse2(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int64_t pts, int64_t dts, + int64_t pos); + +void av_parser_close(AVCodecParserContext *s); + +/** + * @} + * @} + */ + +/** + * @addtogroup lavc_encoding + * @{ + */ + +int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVSubtitle *sub); + + +/** + * @} + */ + +/** + * @defgroup lavc_misc Utility functions + * @ingroup libavc + * + * Miscellaneous utility functions related to both encoding and decoding + * (or neither). + * @{ + */ + +/** + * @defgroup lavc_misc_pixfmt Pixel formats + * + * Functions for working with pixel formats. + * @{ + */ + +/** + * Return a value representing the fourCC code associated to the + * pixel format pix_fmt, or 0 if no associated fourCC code can be + * found. + */ +unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt); + +/** + * Find the best pixel format to convert to given a certain source pixel + * format. When converting from one pixel format to another, information loss + * may occur. For example, when converting from RGB24 to GRAY, the color + * information will be lost. Similarly, other losses occur when converting from + * some formats to other formats. avcodec_find_best_pix_fmt_of_2() searches which of + * the given pixel formats should be used to suffer the least amount of loss. + * The pixel formats from which it chooses one, are determined by the + * pix_fmt_list parameter. + * + * + * @param[in] pix_fmt_list AV_PIX_FMT_NONE terminated array of pixel formats to choose from + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. + * @return The best pixel format to convert to or -1 if none was found. + */ +enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *pix_fmt_list, + enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); + +enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + +/** + * @} + */ + +void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); + +int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); +int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count); +//FIXME func typedef + +/** + * Fill AVFrame audio data and linesize pointers. + * + * The buffer buf must be a preallocated buffer with a size big enough + * to contain the specified samples amount. The filled AVFrame data + * pointers will point to this buffer. + * + * AVFrame extended_data channel pointers are allocated if necessary for + * planar audio. + * + * @param frame the AVFrame + * frame->nb_samples must be set prior to calling the + * function. This function fills in frame->data, + * frame->extended_data, frame->linesize[0]. + * @param nb_channels channel count + * @param sample_fmt sample format + * @param buf buffer to use for frame data + * @param buf_size size of buffer + * @param align plane size sample alignment (0 = default) + * @return >=0 on success, negative error code on failure + * @todo return the size in bytes required to store the samples in + * case of success, at the next libavutil bump + */ +int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, + enum AVSampleFormat sample_fmt, const uint8_t *buf, + int buf_size, int align); + +/** + * Reset the internal codec state / flush internal buffers. Should be called + * e.g. when seeking or when switching to a different stream. + * + * @note for decoders, this function just releases any references the decoder + * might keep internally, but the caller's references remain valid. + * + * @note for encoders, this function will only do something if the encoder + * declares support for AV_CODEC_CAP_ENCODER_FLUSH. When called, the encoder + * will drain any remaining packets, and can then be re-used for a different + * stream (as opposed to sending a null frame which will leave the encoder + * in a permanent EOF state after draining). This can be desirable if the + * cost of tearing down and replacing the encoder instance is high. + */ +void avcodec_flush_buffers(AVCodecContext *avctx); + +/** + * Return audio frame duration. + * + * @param avctx codec context + * @param frame_bytes size of the frame, or 0 if unknown + * @return frame duration, in samples, if known. 0 if not able to + * determine. + */ +int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes); + +/* memory */ + +/** + * Same behaviour av_fast_malloc but the buffer has additional + * AV_INPUT_BUFFER_PADDING_SIZE at the end which will always be 0. + * + * In addition the whole buffer will initially and after resizes + * be 0-initialized so that no uninitialized data will ever appear. + */ +void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Same behaviour av_fast_padded_malloc except that buffer will always + * be 0-initialized after call. + */ +void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * @return a positive value if s is open (i.e. avcodec_open2() was called on it + * with no corresponding avcodec_close()), 0 otherwise. + */ +int avcodec_is_open(AVCodecContext *s); + +/** + * @} + */ + +#endif /* AVCODEC_AVCODEC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec.h b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec.h new file mode 100644 index 0000000000000..6f9b42760d782 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec.h @@ -0,0 +1,371 @@ +/* + * AVCodec public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_H +#define AVCODEC_CODEC_H + +#include + +#include "libavutil/avutil.h" +#include "libavutil/hwcontext.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" +#include "libavutil/samplefmt.h" + +#include "libavcodec/codec_id.h" +#include "libavcodec/version_major.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * Decoder can use draw_horiz_band callback. + */ +#define AV_CODEC_CAP_DRAW_HORIZ_BAND (1 << 0) +/** + * Codec uses get_buffer() or get_encode_buffer() for allocating buffers and + * supports custom allocators. + * If not set, it might not use get_buffer() or get_encode_buffer() at all, or + * use operations that assume the buffer was allocated by + * avcodec_default_get_buffer2 or avcodec_default_get_encode_buffer. + */ +#define AV_CODEC_CAP_DR1 (1 << 1) +/** + * Encoder or decoder requires flushing with NULL input at the end in order to + * give the complete and correct output. + * + * NOTE: If this flag is not set, the codec is guaranteed to never be fed with + * with NULL data. The user can still send NULL data to the public encode + * or decode function, but libavcodec will not pass it along to the codec + * unless this flag is set. + * + * Decoders: + * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to get the delayed data until the decoder no longer + * returns frames. + * + * Encoders: + * The encoder needs to be fed with NULL data at the end of encoding until the + * encoder no longer returns data. + * + * NOTE: For encoders implementing the AVCodec.encode2() function, setting this + * flag also means that the encoder must set the pts and duration for + * each output packet. If this flag is not set, the pts and duration will + * be determined by libavcodec from the input frame. + */ +#define AV_CODEC_CAP_DELAY (1 << 5) +/** + * Codec can be fed a final frame with a smaller size. + * This can be used to prevent truncation of the last audio samples. + */ +#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6) + +#if FF_API_SUBFRAMES +/** + * Codec can output multiple frames per AVPacket + * Normally demuxers return one frame at a time, demuxers which do not do + * are connected to a parser to split what they return into proper frames. + * This flag is reserved to the very rare category of codecs which have a + * bitstream that cannot be split into frames without timeconsuming + * operations like full decoding. Demuxers carrying such bitstreams thus + * may return multiple frames in a packet. This has many disadvantages like + * prohibiting stream copy in many cases thus it should only be considered + * as a last resort. + */ +#define AV_CODEC_CAP_SUBFRAMES (1 << 8) +#endif + +/** + * Codec is experimental and is thus avoided in favor of non experimental + * encoders + */ +#define AV_CODEC_CAP_EXPERIMENTAL (1 << 9) +/** + * Codec should fill in channel configuration and samplerate instead of container + */ +#define AV_CODEC_CAP_CHANNEL_CONF (1 << 10) +/** + * Codec supports frame-level multithreading. + */ +#define AV_CODEC_CAP_FRAME_THREADS (1 << 12) +/** + * Codec supports slice-based (or partition-based) multithreading. + */ +#define AV_CODEC_CAP_SLICE_THREADS (1 << 13) +/** + * Codec supports changed parameters at any point. + */ +#define AV_CODEC_CAP_PARAM_CHANGE (1 << 14) +/** + * Codec supports multithreading through a method other than slice- or + * frame-level multithreading. Typically this marks wrappers around + * multithreading-capable external libraries. + */ +#define AV_CODEC_CAP_OTHER_THREADS (1 << 15) +/** + * Audio encoder supports receiving a different number of samples in each call. + */ +#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16) +/** + * Decoder is not a preferred choice for probing. + * This indicates that the decoder is not a good choice for probing. + * It could for example be an expensive to spin up hardware decoder, + * or it could simply not provide a lot of useful information about + * the stream. + * A decoder marked with this flag should only be used as last resort + * choice for probing. + */ +#define AV_CODEC_CAP_AVOID_PROBING (1 << 17) + +/** + * Codec is backed by a hardware implementation. Typically used to + * identify a non-hwaccel hardware decoder. For information about hwaccels, use + * avcodec_get_hw_config() instead. + */ +#define AV_CODEC_CAP_HARDWARE (1 << 18) + +/** + * Codec is potentially backed by a hardware implementation, but not + * necessarily. This is used instead of AV_CODEC_CAP_HARDWARE, if the + * implementation provides some sort of internal fallback. + */ +#define AV_CODEC_CAP_HYBRID (1 << 19) + +/** + * This encoder can reorder user opaque values from input AVFrames and return + * them with corresponding output packets. + * @see AV_CODEC_FLAG_COPY_OPAQUE + */ +#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE (1 << 20) + +/** + * This encoder can be flushed using avcodec_flush_buffers(). If this flag is + * not set, the encoder must be closed and reopened to ensure that no frames + * remain pending. + */ +#define AV_CODEC_CAP_ENCODER_FLUSH (1 << 21) + +/** + * The encoder is able to output reconstructed frame data, i.e. raw frames that + * would be produced by decoding the encoded bitstream. + * + * Reconstructed frame output is enabled by the AV_CODEC_FLAG_RECON_FRAME flag. + */ +#define AV_CODEC_CAP_ENCODER_RECON_FRAME (1 << 22) + +/** + * AVProfile. + */ +typedef struct AVProfile { + int profile; + const char *name; ///< short name for the profile +} AVProfile; + +/** + * AVCodec. + */ +typedef struct AVCodec { + /** + * Name of the codec implementation. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + * This is the primary way to find a codec from the user perspective. + */ + const char *name; + /** + * Descriptive name for the codec, meant to be more human readable than name. + * You should use the NULL_IF_CONFIG_SMALL() macro to define it. + */ + const char *long_name; + enum AVMediaType type; + enum AVCodecID id; + /** + * Codec capabilities. + * see AV_CODEC_CAP_* + */ + int capabilities; + uint8_t max_lowres; ///< maximum value for lowres supported by the decoder + const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} + const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 + const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 + const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 + const AVClass *priv_class; ///< AVClass for the private context + const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {AV_PROFILE_UNKNOWN} + + /** + * Group name of the codec implementation. + * This is a short symbolic name of the wrapper backing this codec. A + * wrapper uses some kind of external implementation for the codec, such + * as an external library, or a codec implementation provided by the OS or + * the hardware. + * If this field is NULL, this is a builtin, libavcodec native codec. + * If non-NULL, this will be the suffix in AVCodec.name in most cases + * (usually AVCodec.name will be of the form "_"). + */ + const char *wrapper_name; + + /** + * Array of supported channel layouts, terminated with a zeroed layout. + */ + const AVChannelLayout *ch_layouts; +} AVCodec; + +/** + * Iterate over all registered codecs. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec or NULL when the iteration is + * finished + */ +const AVCodec *av_codec_iterate(void **opaque); + +/** + * Find a registered decoder with a matching codec ID. + * + * @param id AVCodecID of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_decoder(enum AVCodecID id); + +/** + * Find a registered decoder with the specified name. + * + * @param name name of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_decoder_by_name(const char *name); + +/** + * Find a registered encoder with a matching codec ID. + * + * @param id AVCodecID of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_encoder(enum AVCodecID id); + +/** + * Find a registered encoder with the specified name. + * + * @param name name of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_encoder_by_name(const char *name); +/** + * @return a non-zero number if codec is an encoder, zero otherwise + */ +int av_codec_is_encoder(const AVCodec *codec); + +/** + * @return a non-zero number if codec is a decoder, zero otherwise + */ +int av_codec_is_decoder(const AVCodec *codec); + +/** + * Return a name for the specified profile, if available. + * + * @param codec the codec that is searched for the given profile + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + */ +const char *av_get_profile_name(const AVCodec *codec, int profile); + +enum { + /** + * The codec supports this format via the hw_device_ctx interface. + * + * When selecting this format, AVCodecContext.hw_device_ctx should + * have been set to a device of the specified type before calling + * avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01, + /** + * The codec supports this format via the hw_frames_ctx interface. + * + * When selecting this format for a decoder, + * AVCodecContext.hw_frames_ctx should be set to a suitable frames + * context inside the get_format() callback. The frames context + * must have been created on a device of the specified type. + * + * When selecting this format for an encoder, + * AVCodecContext.hw_frames_ctx should be set to the context which + * will be used for the input frames before calling avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02, + /** + * The codec supports this format by some internal method. + * + * This format can be selected without any additional configuration - + * no device or frames context is required. + */ + AV_CODEC_HW_CONFIG_METHOD_INTERNAL = 0x04, + /** + * The codec supports this format by some ad-hoc method. + * + * Additional settings and/or function calls are required. See the + * codec-specific documentation for details. (Methods requiring + * this sort of configuration are deprecated and others should be + * used in preference.) + */ + AV_CODEC_HW_CONFIG_METHOD_AD_HOC = 0x08, +}; + +typedef struct AVCodecHWConfig { + /** + * For decoders, a hardware pixel format which that decoder may be + * able to decode to if suitable hardware is available. + * + * For encoders, a pixel format which the encoder may be able to + * accept. If set to AV_PIX_FMT_NONE, this applies to all pixel + * formats supported by the codec. + */ + enum AVPixelFormat pix_fmt; + /** + * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible + * setup methods which can be used with this configuration. + */ + int methods; + /** + * The device type associated with the configuration. + * + * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and + * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused. + */ + enum AVHWDeviceType device_type; +} AVCodecHWConfig; + +/** + * Retrieve supported hardware configurations for a codec. + * + * Values of index from zero to some maximum return the indexed configuration + * descriptor; all other values return NULL. If the codec does not support + * any hardware configurations then it will always return NULL. + */ +const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index); + +/** + * @} + */ + +#endif /* AVCODEC_CODEC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec_desc.h b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec_desc.h new file mode 100644 index 0000000000000..96afd20208b3d --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec_desc.h @@ -0,0 +1,134 @@ +/* + * Codec descriptors public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_DESC_H +#define AVCODEC_CODEC_DESC_H + +#include "libavutil/avutil.h" + +#include "codec_id.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * This struct describes the properties of a single codec described by an + * AVCodecID. + * @see avcodec_descriptor_get() + */ +typedef struct AVCodecDescriptor { + enum AVCodecID id; + enum AVMediaType type; + /** + * Name of the codec described by this descriptor. It is non-empty and + * unique for each codec descriptor. It should contain alphanumeric + * characters and '_' only. + */ + const char *name; + /** + * A more descriptive name for this codec. May be NULL. + */ + const char *long_name; + /** + * Codec properties, a combination of AV_CODEC_PROP_* flags. + */ + int props; + /** + * MIME type(s) associated with the codec. + * May be NULL; if not, a NULL-terminated array of MIME types. + * The first item is always non-NULL and is the preferred MIME type. + */ + const char *const *mime_types; + /** + * If non-NULL, an array of profiles recognized for this codec. + * Terminated with AV_PROFILE_UNKNOWN. + */ + const struct AVProfile *profiles; +} AVCodecDescriptor; + +/** + * Codec uses only intra compression. + * Video and audio codecs only. + */ +#define AV_CODEC_PROP_INTRA_ONLY (1 << 0) +/** + * Codec supports lossy compression. Audio and video codecs only. + * @note a codec may support both lossy and lossless + * compression modes + */ +#define AV_CODEC_PROP_LOSSY (1 << 1) +/** + * Codec supports lossless compression. Audio and video codecs only. + */ +#define AV_CODEC_PROP_LOSSLESS (1 << 2) +/** + * Codec supports frame reordering. That is, the coded order (the order in which + * the encoded packets are output by the encoders / stored / input to the + * decoders) may be different from the presentation order of the corresponding + * frames. + * + * For codecs that do not have this property set, PTS and DTS should always be + * equal. + */ +#define AV_CODEC_PROP_REORDER (1 << 3) + +/** + * Video codec supports separate coding of fields in interlaced frames. + */ +#define AV_CODEC_PROP_FIELDS (1 << 4) + +/** + * Subtitle codec is bitmap based + * Decoded AVSubtitle data can be read from the AVSubtitleRect->pict field. + */ +#define AV_CODEC_PROP_BITMAP_SUB (1 << 16) +/** + * Subtitle codec is text based. + * Decoded AVSubtitle data can be read from the AVSubtitleRect->ass field. + */ +#define AV_CODEC_PROP_TEXT_SUB (1 << 17) + +/** + * @return descriptor for given codec ID or NULL if no descriptor exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id); + +/** + * Iterate over all codec descriptors known to libavcodec. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); + +/** + * @return codec descriptor with the given name or NULL if no such descriptor + * exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_DESC_H diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec_id.h b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec_id.h new file mode 100644 index 0000000000000..c8dc21da740c9 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec_id.h @@ -0,0 +1,667 @@ +/* + * Codec IDs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_ID_H +#define AVCODEC_CODEC_ID_H + +#include "libavutil/avutil.h" +#include "libavutil/samplefmt.h" + +#include "version_major.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * Identify the syntax and semantics of the bitstream. + * The principle is roughly: + * Two decoders with the same ID can decode the same streams. + * Two encoders with the same ID can encode compatible streams. + * There may be slight deviations from the principle due to implementation + * details. + * + * If you add a codec ID to this list, add it so that + * 1. no value of an existing codec ID changes (that would break ABI), + * 2. it is as close as possible to similar codecs + * + * After adding new codec IDs, do not forget to add an entry to the codec + * descriptor list and bump libavcodec minor version. + */ +enum AVCodecID { + AV_CODEC_ID_NONE, + + /* video codecs */ + AV_CODEC_ID_MPEG1VIDEO, + AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding + AV_CODEC_ID_H261, + AV_CODEC_ID_H263, + AV_CODEC_ID_RV10, + AV_CODEC_ID_RV20, + AV_CODEC_ID_MJPEG, + AV_CODEC_ID_MJPEGB, + AV_CODEC_ID_LJPEG, + AV_CODEC_ID_SP5X, + AV_CODEC_ID_JPEGLS, + AV_CODEC_ID_MPEG4, + AV_CODEC_ID_RAWVIDEO, + AV_CODEC_ID_MSMPEG4V1, + AV_CODEC_ID_MSMPEG4V2, + AV_CODEC_ID_MSMPEG4V3, + AV_CODEC_ID_WMV1, + AV_CODEC_ID_WMV2, + AV_CODEC_ID_H263P, + AV_CODEC_ID_H263I, + AV_CODEC_ID_FLV1, + AV_CODEC_ID_SVQ1, + AV_CODEC_ID_SVQ3, + AV_CODEC_ID_DVVIDEO, + AV_CODEC_ID_HUFFYUV, + AV_CODEC_ID_CYUV, + AV_CODEC_ID_H264, + AV_CODEC_ID_INDEO3, + AV_CODEC_ID_VP3, + AV_CODEC_ID_THEORA, + AV_CODEC_ID_ASV1, + AV_CODEC_ID_ASV2, + AV_CODEC_ID_FFV1, + AV_CODEC_ID_4XM, + AV_CODEC_ID_VCR1, + AV_CODEC_ID_CLJR, + AV_CODEC_ID_MDEC, + AV_CODEC_ID_ROQ, + AV_CODEC_ID_INTERPLAY_VIDEO, + AV_CODEC_ID_XAN_WC3, + AV_CODEC_ID_XAN_WC4, + AV_CODEC_ID_RPZA, + AV_CODEC_ID_CINEPAK, + AV_CODEC_ID_WS_VQA, + AV_CODEC_ID_MSRLE, + AV_CODEC_ID_MSVIDEO1, + AV_CODEC_ID_IDCIN, + AV_CODEC_ID_8BPS, + AV_CODEC_ID_SMC, + AV_CODEC_ID_FLIC, + AV_CODEC_ID_TRUEMOTION1, + AV_CODEC_ID_VMDVIDEO, + AV_CODEC_ID_MSZH, + AV_CODEC_ID_ZLIB, + AV_CODEC_ID_QTRLE, + AV_CODEC_ID_TSCC, + AV_CODEC_ID_ULTI, + AV_CODEC_ID_QDRAW, + AV_CODEC_ID_VIXL, + AV_CODEC_ID_QPEG, + AV_CODEC_ID_PNG, + AV_CODEC_ID_PPM, + AV_CODEC_ID_PBM, + AV_CODEC_ID_PGM, + AV_CODEC_ID_PGMYUV, + AV_CODEC_ID_PAM, + AV_CODEC_ID_FFVHUFF, + AV_CODEC_ID_RV30, + AV_CODEC_ID_RV40, + AV_CODEC_ID_VC1, + AV_CODEC_ID_WMV3, + AV_CODEC_ID_LOCO, + AV_CODEC_ID_WNV1, + AV_CODEC_ID_AASC, + AV_CODEC_ID_INDEO2, + AV_CODEC_ID_FRAPS, + AV_CODEC_ID_TRUEMOTION2, + AV_CODEC_ID_BMP, + AV_CODEC_ID_CSCD, + AV_CODEC_ID_MMVIDEO, + AV_CODEC_ID_ZMBV, + AV_CODEC_ID_AVS, + AV_CODEC_ID_SMACKVIDEO, + AV_CODEC_ID_NUV, + AV_CODEC_ID_KMVC, + AV_CODEC_ID_FLASHSV, + AV_CODEC_ID_CAVS, + AV_CODEC_ID_JPEG2000, + AV_CODEC_ID_VMNC, + AV_CODEC_ID_VP5, + AV_CODEC_ID_VP6, + AV_CODEC_ID_VP6F, + AV_CODEC_ID_TARGA, + AV_CODEC_ID_DSICINVIDEO, + AV_CODEC_ID_TIERTEXSEQVIDEO, + AV_CODEC_ID_TIFF, + AV_CODEC_ID_GIF, + AV_CODEC_ID_DXA, + AV_CODEC_ID_DNXHD, + AV_CODEC_ID_THP, + AV_CODEC_ID_SGI, + AV_CODEC_ID_C93, + AV_CODEC_ID_BETHSOFTVID, + AV_CODEC_ID_PTX, + AV_CODEC_ID_TXD, + AV_CODEC_ID_VP6A, + AV_CODEC_ID_AMV, + AV_CODEC_ID_VB, + AV_CODEC_ID_PCX, + AV_CODEC_ID_SUNRAST, + AV_CODEC_ID_INDEO4, + AV_CODEC_ID_INDEO5, + AV_CODEC_ID_MIMIC, + AV_CODEC_ID_RL2, + AV_CODEC_ID_ESCAPE124, + AV_CODEC_ID_DIRAC, + AV_CODEC_ID_BFI, + AV_CODEC_ID_CMV, + AV_CODEC_ID_MOTIONPIXELS, + AV_CODEC_ID_TGV, + AV_CODEC_ID_TGQ, + AV_CODEC_ID_TQI, + AV_CODEC_ID_AURA, + AV_CODEC_ID_AURA2, + AV_CODEC_ID_V210X, + AV_CODEC_ID_TMV, + AV_CODEC_ID_V210, + AV_CODEC_ID_DPX, + AV_CODEC_ID_MAD, + AV_CODEC_ID_FRWU, + AV_CODEC_ID_FLASHSV2, + AV_CODEC_ID_CDGRAPHICS, + AV_CODEC_ID_R210, + AV_CODEC_ID_ANM, + AV_CODEC_ID_BINKVIDEO, + AV_CODEC_ID_IFF_ILBM, +#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM + AV_CODEC_ID_KGV1, + AV_CODEC_ID_YOP, + AV_CODEC_ID_VP8, + AV_CODEC_ID_PICTOR, + AV_CODEC_ID_ANSI, + AV_CODEC_ID_A64_MULTI, + AV_CODEC_ID_A64_MULTI5, + AV_CODEC_ID_R10K, + AV_CODEC_ID_MXPEG, + AV_CODEC_ID_LAGARITH, + AV_CODEC_ID_PRORES, + AV_CODEC_ID_JV, + AV_CODEC_ID_DFA, + AV_CODEC_ID_WMV3IMAGE, + AV_CODEC_ID_VC1IMAGE, + AV_CODEC_ID_UTVIDEO, + AV_CODEC_ID_BMV_VIDEO, + AV_CODEC_ID_VBLE, + AV_CODEC_ID_DXTORY, + AV_CODEC_ID_V410, + AV_CODEC_ID_XWD, + AV_CODEC_ID_CDXL, + AV_CODEC_ID_XBM, + AV_CODEC_ID_ZEROCODEC, + AV_CODEC_ID_MSS1, + AV_CODEC_ID_MSA1, + AV_CODEC_ID_TSCC2, + AV_CODEC_ID_MTS2, + AV_CODEC_ID_CLLC, + AV_CODEC_ID_MSS2, + AV_CODEC_ID_VP9, + AV_CODEC_ID_AIC, + AV_CODEC_ID_ESCAPE130, + AV_CODEC_ID_G2M, + AV_CODEC_ID_WEBP, + AV_CODEC_ID_HNM4_VIDEO, + AV_CODEC_ID_HEVC, +#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC + AV_CODEC_ID_FIC, + AV_CODEC_ID_ALIAS_PIX, + AV_CODEC_ID_BRENDER_PIX, + AV_CODEC_ID_PAF_VIDEO, + AV_CODEC_ID_EXR, + AV_CODEC_ID_VP7, + AV_CODEC_ID_SANM, + AV_CODEC_ID_SGIRLE, + AV_CODEC_ID_MVC1, + AV_CODEC_ID_MVC2, + AV_CODEC_ID_HQX, + AV_CODEC_ID_TDSC, + AV_CODEC_ID_HQ_HQA, + AV_CODEC_ID_HAP, + AV_CODEC_ID_DDS, + AV_CODEC_ID_DXV, + AV_CODEC_ID_SCREENPRESSO, + AV_CODEC_ID_RSCC, + AV_CODEC_ID_AVS2, + AV_CODEC_ID_PGX, + AV_CODEC_ID_AVS3, + AV_CODEC_ID_MSP2, + AV_CODEC_ID_VVC, +#define AV_CODEC_ID_H266 AV_CODEC_ID_VVC + AV_CODEC_ID_Y41P, + AV_CODEC_ID_AVRP, + AV_CODEC_ID_012V, + AV_CODEC_ID_AVUI, + AV_CODEC_ID_TARGA_Y216, + AV_CODEC_ID_V308, + AV_CODEC_ID_V408, + AV_CODEC_ID_YUV4, + AV_CODEC_ID_AVRN, + AV_CODEC_ID_CPIA, + AV_CODEC_ID_XFACE, + AV_CODEC_ID_SNOW, + AV_CODEC_ID_SMVJPEG, + AV_CODEC_ID_APNG, + AV_CODEC_ID_DAALA, + AV_CODEC_ID_CFHD, + AV_CODEC_ID_TRUEMOTION2RT, + AV_CODEC_ID_M101, + AV_CODEC_ID_MAGICYUV, + AV_CODEC_ID_SHEERVIDEO, + AV_CODEC_ID_YLC, + AV_CODEC_ID_PSD, + AV_CODEC_ID_PIXLET, + AV_CODEC_ID_SPEEDHQ, + AV_CODEC_ID_FMVC, + AV_CODEC_ID_SCPR, + AV_CODEC_ID_CLEARVIDEO, + AV_CODEC_ID_XPM, + AV_CODEC_ID_AV1, + AV_CODEC_ID_BITPACKED, + AV_CODEC_ID_MSCC, + AV_CODEC_ID_SRGC, + AV_CODEC_ID_SVG, + AV_CODEC_ID_GDV, + AV_CODEC_ID_FITS, + AV_CODEC_ID_IMM4, + AV_CODEC_ID_PROSUMER, + AV_CODEC_ID_MWSC, + AV_CODEC_ID_WCMV, + AV_CODEC_ID_RASC, + AV_CODEC_ID_HYMT, + AV_CODEC_ID_ARBC, + AV_CODEC_ID_AGM, + AV_CODEC_ID_LSCR, + AV_CODEC_ID_VP4, + AV_CODEC_ID_IMM5, + AV_CODEC_ID_MVDV, + AV_CODEC_ID_MVHA, + AV_CODEC_ID_CDTOONS, + AV_CODEC_ID_MV30, + AV_CODEC_ID_NOTCHLC, + AV_CODEC_ID_PFM, + AV_CODEC_ID_MOBICLIP, + AV_CODEC_ID_PHOTOCD, + AV_CODEC_ID_IPU, + AV_CODEC_ID_ARGO, + AV_CODEC_ID_CRI, + AV_CODEC_ID_SIMBIOSIS_IMX, + AV_CODEC_ID_SGA_VIDEO, + AV_CODEC_ID_GEM, + AV_CODEC_ID_VBN, + AV_CODEC_ID_JPEGXL, + AV_CODEC_ID_QOI, + AV_CODEC_ID_PHM, + AV_CODEC_ID_RADIANCE_HDR, + AV_CODEC_ID_WBMP, + AV_CODEC_ID_MEDIA100, + AV_CODEC_ID_VQC, + AV_CODEC_ID_PDV, + AV_CODEC_ID_EVC, + AV_CODEC_ID_RTV1, + AV_CODEC_ID_VMIX, + AV_CODEC_ID_LEAD, + + /* various PCM "codecs" */ + AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs + AV_CODEC_ID_PCM_S16LE = 0x10000, + AV_CODEC_ID_PCM_S16BE, + AV_CODEC_ID_PCM_U16LE, + AV_CODEC_ID_PCM_U16BE, + AV_CODEC_ID_PCM_S8, + AV_CODEC_ID_PCM_U8, + AV_CODEC_ID_PCM_MULAW, + AV_CODEC_ID_PCM_ALAW, + AV_CODEC_ID_PCM_S32LE, + AV_CODEC_ID_PCM_S32BE, + AV_CODEC_ID_PCM_U32LE, + AV_CODEC_ID_PCM_U32BE, + AV_CODEC_ID_PCM_S24LE, + AV_CODEC_ID_PCM_S24BE, + AV_CODEC_ID_PCM_U24LE, + AV_CODEC_ID_PCM_U24BE, + AV_CODEC_ID_PCM_S24DAUD, + AV_CODEC_ID_PCM_ZORK, + AV_CODEC_ID_PCM_S16LE_PLANAR, + AV_CODEC_ID_PCM_DVD, + AV_CODEC_ID_PCM_F32BE, + AV_CODEC_ID_PCM_F32LE, + AV_CODEC_ID_PCM_F64BE, + AV_CODEC_ID_PCM_F64LE, + AV_CODEC_ID_PCM_BLURAY, + AV_CODEC_ID_PCM_LXF, + AV_CODEC_ID_S302M, + AV_CODEC_ID_PCM_S8_PLANAR, + AV_CODEC_ID_PCM_S24LE_PLANAR, + AV_CODEC_ID_PCM_S32LE_PLANAR, + AV_CODEC_ID_PCM_S16BE_PLANAR, + AV_CODEC_ID_PCM_S64LE, + AV_CODEC_ID_PCM_S64BE, + AV_CODEC_ID_PCM_F16LE, + AV_CODEC_ID_PCM_F24LE, + AV_CODEC_ID_PCM_VIDC, + AV_CODEC_ID_PCM_SGA, + + /* various ADPCM codecs */ + AV_CODEC_ID_ADPCM_IMA_QT = 0x11000, + AV_CODEC_ID_ADPCM_IMA_WAV, + AV_CODEC_ID_ADPCM_IMA_DK3, + AV_CODEC_ID_ADPCM_IMA_DK4, + AV_CODEC_ID_ADPCM_IMA_WS, + AV_CODEC_ID_ADPCM_IMA_SMJPEG, + AV_CODEC_ID_ADPCM_MS, + AV_CODEC_ID_ADPCM_4XM, + AV_CODEC_ID_ADPCM_XA, + AV_CODEC_ID_ADPCM_ADX, + AV_CODEC_ID_ADPCM_EA, + AV_CODEC_ID_ADPCM_G726, + AV_CODEC_ID_ADPCM_CT, + AV_CODEC_ID_ADPCM_SWF, + AV_CODEC_ID_ADPCM_YAMAHA, + AV_CODEC_ID_ADPCM_SBPRO_4, + AV_CODEC_ID_ADPCM_SBPRO_3, + AV_CODEC_ID_ADPCM_SBPRO_2, + AV_CODEC_ID_ADPCM_THP, + AV_CODEC_ID_ADPCM_IMA_AMV, + AV_CODEC_ID_ADPCM_EA_R1, + AV_CODEC_ID_ADPCM_EA_R3, + AV_CODEC_ID_ADPCM_EA_R2, + AV_CODEC_ID_ADPCM_IMA_EA_SEAD, + AV_CODEC_ID_ADPCM_IMA_EA_EACS, + AV_CODEC_ID_ADPCM_EA_XAS, + AV_CODEC_ID_ADPCM_EA_MAXIS_XA, + AV_CODEC_ID_ADPCM_IMA_ISS, + AV_CODEC_ID_ADPCM_G722, + AV_CODEC_ID_ADPCM_IMA_APC, + AV_CODEC_ID_ADPCM_VIMA, + AV_CODEC_ID_ADPCM_AFC, + AV_CODEC_ID_ADPCM_IMA_OKI, + AV_CODEC_ID_ADPCM_DTK, + AV_CODEC_ID_ADPCM_IMA_RAD, + AV_CODEC_ID_ADPCM_G726LE, + AV_CODEC_ID_ADPCM_THP_LE, + AV_CODEC_ID_ADPCM_PSX, + AV_CODEC_ID_ADPCM_AICA, + AV_CODEC_ID_ADPCM_IMA_DAT4, + AV_CODEC_ID_ADPCM_MTAF, + AV_CODEC_ID_ADPCM_AGM, + AV_CODEC_ID_ADPCM_ARGO, + AV_CODEC_ID_ADPCM_IMA_SSI, + AV_CODEC_ID_ADPCM_ZORK, + AV_CODEC_ID_ADPCM_IMA_APM, + AV_CODEC_ID_ADPCM_IMA_ALP, + AV_CODEC_ID_ADPCM_IMA_MTF, + AV_CODEC_ID_ADPCM_IMA_CUNNING, + AV_CODEC_ID_ADPCM_IMA_MOFLEX, + AV_CODEC_ID_ADPCM_IMA_ACORN, + AV_CODEC_ID_ADPCM_XMD, + + /* AMR */ + AV_CODEC_ID_AMR_NB = 0x12000, + AV_CODEC_ID_AMR_WB, + + /* RealAudio codecs*/ + AV_CODEC_ID_RA_144 = 0x13000, + AV_CODEC_ID_RA_288, + + /* various DPCM codecs */ + AV_CODEC_ID_ROQ_DPCM = 0x14000, + AV_CODEC_ID_INTERPLAY_DPCM, + AV_CODEC_ID_XAN_DPCM, + AV_CODEC_ID_SOL_DPCM, + AV_CODEC_ID_SDX2_DPCM, + AV_CODEC_ID_GREMLIN_DPCM, + AV_CODEC_ID_DERF_DPCM, + AV_CODEC_ID_WADY_DPCM, + AV_CODEC_ID_CBD2_DPCM, + + /* audio codecs */ + AV_CODEC_ID_MP2 = 0x15000, + AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 + AV_CODEC_ID_AAC, + AV_CODEC_ID_AC3, + AV_CODEC_ID_DTS, + AV_CODEC_ID_VORBIS, + AV_CODEC_ID_DVAUDIO, + AV_CODEC_ID_WMAV1, + AV_CODEC_ID_WMAV2, + AV_CODEC_ID_MACE3, + AV_CODEC_ID_MACE6, + AV_CODEC_ID_VMDAUDIO, + AV_CODEC_ID_FLAC, + AV_CODEC_ID_MP3ADU, + AV_CODEC_ID_MP3ON4, + AV_CODEC_ID_SHORTEN, + AV_CODEC_ID_ALAC, + AV_CODEC_ID_WESTWOOD_SND1, + AV_CODEC_ID_GSM, ///< as in Berlin toast format + AV_CODEC_ID_QDM2, + AV_CODEC_ID_COOK, + AV_CODEC_ID_TRUESPEECH, + AV_CODEC_ID_TTA, + AV_CODEC_ID_SMACKAUDIO, + AV_CODEC_ID_QCELP, + AV_CODEC_ID_WAVPACK, + AV_CODEC_ID_DSICINAUDIO, + AV_CODEC_ID_IMC, + AV_CODEC_ID_MUSEPACK7, + AV_CODEC_ID_MLP, + AV_CODEC_ID_GSM_MS, /* as found in WAV */ + AV_CODEC_ID_ATRAC3, + AV_CODEC_ID_APE, + AV_CODEC_ID_NELLYMOSER, + AV_CODEC_ID_MUSEPACK8, + AV_CODEC_ID_SPEEX, + AV_CODEC_ID_WMAVOICE, + AV_CODEC_ID_WMAPRO, + AV_CODEC_ID_WMALOSSLESS, + AV_CODEC_ID_ATRAC3P, + AV_CODEC_ID_EAC3, + AV_CODEC_ID_SIPR, + AV_CODEC_ID_MP1, + AV_CODEC_ID_TWINVQ, + AV_CODEC_ID_TRUEHD, + AV_CODEC_ID_MP4ALS, + AV_CODEC_ID_ATRAC1, + AV_CODEC_ID_BINKAUDIO_RDFT, + AV_CODEC_ID_BINKAUDIO_DCT, + AV_CODEC_ID_AAC_LATM, + AV_CODEC_ID_QDMC, + AV_CODEC_ID_CELT, + AV_CODEC_ID_G723_1, + AV_CODEC_ID_G729, + AV_CODEC_ID_8SVX_EXP, + AV_CODEC_ID_8SVX_FIB, + AV_CODEC_ID_BMV_AUDIO, + AV_CODEC_ID_RALF, + AV_CODEC_ID_IAC, + AV_CODEC_ID_ILBC, + AV_CODEC_ID_OPUS, + AV_CODEC_ID_COMFORT_NOISE, + AV_CODEC_ID_TAK, + AV_CODEC_ID_METASOUND, + AV_CODEC_ID_PAF_AUDIO, + AV_CODEC_ID_ON2AVC, + AV_CODEC_ID_DSS_SP, + AV_CODEC_ID_CODEC2, + AV_CODEC_ID_FFWAVESYNTH, + AV_CODEC_ID_SONIC, + AV_CODEC_ID_SONIC_LS, + AV_CODEC_ID_EVRC, + AV_CODEC_ID_SMV, + AV_CODEC_ID_DSD_LSBF, + AV_CODEC_ID_DSD_MSBF, + AV_CODEC_ID_DSD_LSBF_PLANAR, + AV_CODEC_ID_DSD_MSBF_PLANAR, + AV_CODEC_ID_4GV, + AV_CODEC_ID_INTERPLAY_ACM, + AV_CODEC_ID_XMA1, + AV_CODEC_ID_XMA2, + AV_CODEC_ID_DST, + AV_CODEC_ID_ATRAC3AL, + AV_CODEC_ID_ATRAC3PAL, + AV_CODEC_ID_DOLBY_E, + AV_CODEC_ID_APTX, + AV_CODEC_ID_APTX_HD, + AV_CODEC_ID_SBC, + AV_CODEC_ID_ATRAC9, + AV_CODEC_ID_HCOM, + AV_CODEC_ID_ACELP_KELVIN, + AV_CODEC_ID_MPEGH_3D_AUDIO, + AV_CODEC_ID_SIREN, + AV_CODEC_ID_HCA, + AV_CODEC_ID_FASTAUDIO, + AV_CODEC_ID_MSNSIREN, + AV_CODEC_ID_DFPWM, + AV_CODEC_ID_BONK, + AV_CODEC_ID_MISC4, + AV_CODEC_ID_APAC, + AV_CODEC_ID_FTR, + AV_CODEC_ID_WAVARC, + AV_CODEC_ID_RKA, + AV_CODEC_ID_AC4, + AV_CODEC_ID_OSQ, + AV_CODEC_ID_QOA, + + /* subtitle codecs */ + AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. + AV_CODEC_ID_DVD_SUBTITLE = 0x17000, + AV_CODEC_ID_DVB_SUBTITLE, + AV_CODEC_ID_TEXT, ///< raw UTF-8 text + AV_CODEC_ID_XSUB, + AV_CODEC_ID_SSA, + AV_CODEC_ID_MOV_TEXT, + AV_CODEC_ID_HDMV_PGS_SUBTITLE, + AV_CODEC_ID_DVB_TELETEXT, + AV_CODEC_ID_SRT, + AV_CODEC_ID_MICRODVD, + AV_CODEC_ID_EIA_608, + AV_CODEC_ID_JACOSUB, + AV_CODEC_ID_SAMI, + AV_CODEC_ID_REALTEXT, + AV_CODEC_ID_STL, + AV_CODEC_ID_SUBVIEWER1, + AV_CODEC_ID_SUBVIEWER, + AV_CODEC_ID_SUBRIP, + AV_CODEC_ID_WEBVTT, + AV_CODEC_ID_MPL2, + AV_CODEC_ID_VPLAYER, + AV_CODEC_ID_PJS, + AV_CODEC_ID_ASS, + AV_CODEC_ID_HDMV_TEXT_SUBTITLE, + AV_CODEC_ID_TTML, + AV_CODEC_ID_ARIB_CAPTION, + + /* other specific kind of codecs (generally used for attachments) */ + AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. + AV_CODEC_ID_TTF = 0x18000, + + AV_CODEC_ID_SCTE_35, ///< Contain timestamp estimated through PCR of program stream. + AV_CODEC_ID_EPG, + AV_CODEC_ID_BINTEXT, + AV_CODEC_ID_XBIN, + AV_CODEC_ID_IDF, + AV_CODEC_ID_OTF, + AV_CODEC_ID_SMPTE_KLV, + AV_CODEC_ID_DVD_NAV, + AV_CODEC_ID_TIMED_ID3, + AV_CODEC_ID_BIN_DATA, + AV_CODEC_ID_SMPTE_2038, + + + AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it + + AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + * stream (only used by libavformat) */ + AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems + * stream (only used by libavformat) */ + AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. + AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket + /** + * Dummy null video codec, useful mainly for development and debugging. + * Null encoder/decoder discard all input and never return any output. + */ + AV_CODEC_ID_VNULL, + /** + * Dummy null audio codec, useful mainly for development and debugging. + * Null encoder/decoder discard all input and never return any output. + */ + AV_CODEC_ID_ANULL, +}; + +/** + * Get the type of the given codec. + */ +enum AVMediaType avcodec_get_type(enum AVCodecID codec_id); + +/** + * Get the name of a codec. + * @return a static string identifying the codec; never NULL + */ +const char *avcodec_get_name(enum AVCodecID id); + +/** + * Return codec bits per sample. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return codec bits per sample. + * Only return non-zero if the bits per sample is exactly correct, not an + * approximation. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_exact_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return a name for the specified profile, if available. + * + * @param codec_id the ID of the codec to which the requested profile belongs + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + * + * @note unlike av_get_profile_name(), which searches a list of profiles + * supported by a specific decoder or encoder implementation, this + * function searches the list of profiles from the AVCodecDescriptor + */ +const char *avcodec_profile_name(enum AVCodecID codec_id, int profile); + +/** + * Return the PCM codec associated with a sample format. + * @param be endianness, 0 for little, 1 for big, + * -1 (or anything else) for native + * @return AV_CODEC_ID_PCM_* or AV_CODEC_ID_NONE + */ +enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_ID_H diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec_par.h b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec_par.h new file mode 100644 index 0000000000000..f4b9bb5c06d25 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/codec_par.h @@ -0,0 +1,248 @@ +/* + * Codec parameters public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_PAR_H +#define AVCODEC_CODEC_PAR_H + +#include + +#include "libavutil/avutil.h" +#include "libavutil/channel_layout.h" +#include "libavutil/rational.h" +#include "libavutil/pixfmt.h" + +#include "codec_id.h" +#include "defs.h" +#include "packet.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * This struct describes the properties of an encoded stream. + * + * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must + * be allocated with avcodec_parameters_alloc() and freed with + * avcodec_parameters_free(). + */ +typedef struct AVCodecParameters { + /** + * General type of the encoded data. + */ + enum AVMediaType codec_type; + /** + * Specific type of the encoded data (the codec used). + */ + enum AVCodecID codec_id; + /** + * Additional information about the codec (corresponds to the AVI FOURCC). + */ + uint32_t codec_tag; + + /** + * Extra binary data needed for initializing the decoder, codec-dependent. + * + * Must be allocated with av_malloc() and will be freed by + * avcodec_parameters_free(). The allocated size of extradata must be at + * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding + * bytes zeroed. + */ + uint8_t *extradata; + /** + * Size of the extradata content in bytes. + */ + int extradata_size; + + /** + * Additional data associated with the entire stream. + * + * Should be allocated with av_packet_side_data_new() or + * av_packet_side_data_add(), and will be freed by avcodec_parameters_free(). + */ + AVPacketSideData *coded_side_data; + + /** + * Amount of entries in @ref coded_side_data. + */ + int nb_coded_side_data; + + /** + * - video: the pixel format, the value corresponds to enum AVPixelFormat. + * - audio: the sample format, the value corresponds to enum AVSampleFormat. + */ + int format; + + /** + * The average bitrate of the encoded data (in bits per second). + */ + int64_t bit_rate; + + /** + * The number of bits per sample in the codedwords. + * + * This is basically the bitrate per sample. It is mandatory for a bunch of + * formats to actually decode them. It's the number of bits for one sample in + * the actual coded bitstream. + * + * This could be for example 4 for ADPCM + * For PCM formats this matches bits_per_raw_sample + * Can be 0 + */ + int bits_per_coded_sample; + + /** + * This is the number of valid bits in each output sample. If the + * sample format has more bits, the least significant bits are additional + * padding bits, which are always 0. Use right shifts to reduce the sample + * to its actual size. For example, audio formats with 24 bit samples will + * have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32. + * To get the original sample use "(int32_t)sample >> 8"." + * + * For ADPCM this might be 12 or 16 or similar + * Can be 0 + */ + int bits_per_raw_sample; + + /** + * Codec-specific bitstream restrictions that the stream conforms to. + */ + int profile; + int level; + + /** + * Video only. The dimensions of the video frame in pixels. + */ + int width; + int height; + + /** + * Video only. The aspect ratio (width / height) which a single pixel + * should have when displayed. + * + * When the aspect ratio is unknown / undefined, the numerator should be + * set to 0 (the denominator may have any value). + */ + AVRational sample_aspect_ratio; + + /** + * Video only. Number of frames per second, for streams with constant frame + * durations. Should be set to { 0, 1 } when some frames have differing + * durations or if the value is not known. + * + * @note This field correponds to values that are stored in codec-level + * headers and is typically overridden by container/transport-layer + * timestamps, when available. It should thus be used only as a last resort, + * when no higher-level timing information is available. + */ + AVRational framerate; + + /** + * Video only. The order of the fields in interlaced video. + */ + enum AVFieldOrder field_order; + + /** + * Video only. Additional colorspace characteristics. + */ + enum AVColorRange color_range; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace color_space; + enum AVChromaLocation chroma_location; + + /** + * Video only. Number of delayed frames. + */ + int video_delay; + + /** + * Audio only. The channel layout and number of channels. + */ + AVChannelLayout ch_layout; + /** + * Audio only. The number of audio samples per second. + */ + int sample_rate; + /** + * Audio only. The number of bytes per coded audio frame, required by some + * formats. + * + * Corresponds to nBlockAlign in WAVEFORMATEX. + */ + int block_align; + /** + * Audio only. Audio frame size, if known. Required by some formats to be static. + */ + int frame_size; + + /** + * Audio only. The amount of padding (in samples) inserted by the encoder at + * the beginning of the audio. I.e. this number of leading decoded samples + * must be discarded by the caller to get the original audio without leading + * padding. + */ + int initial_padding; + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + */ + int trailing_padding; + /** + * Audio only. Number of samples to skip after a discontinuity. + */ + int seek_preroll; +} AVCodecParameters; + +/** + * Allocate a new AVCodecParameters and set its fields to default values + * (unknown/invalid/0). The returned struct must be freed with + * avcodec_parameters_free(). + */ +AVCodecParameters *avcodec_parameters_alloc(void); + +/** + * Free an AVCodecParameters instance and everything associated with it and + * write NULL to the supplied pointer. + */ +void avcodec_parameters_free(AVCodecParameters **par); + +/** + * Copy the contents of src to dst. Any allocated fields in dst are freed and + * replaced with newly allocated duplicates of the corresponding fields in src. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src); + +/** + * This function is the same as av_get_audio_frame_duration(), except it works + * with AVCodecParameters instead of an AVCodecContext. + */ +int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_PAR_H diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/defs.h b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/defs.h new file mode 100644 index 0000000000000..00d840ec19b6f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/defs.h @@ -0,0 +1,335 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DEFS_H +#define AVCODEC_DEFS_H + +/** + * @file + * @ingroup libavc + * Misc types and constants that do not belong anywhere else. + */ + +#include +#include + +/** + * @ingroup lavc_decoding + * Required number of additionally allocated bytes at the end of the input bitstream for decoding. + * This is mainly needed because some optimized bitstream readers read + * 32 or 64 bit at once and could read over the end.
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged + * MPEG bitstreams could cause overread and segfault. + */ +#define AV_INPUT_BUFFER_PADDING_SIZE 64 + +/** + * Verify checksums embedded in the bitstream (could be of either encoded or + * decoded data, depending on the format) and print an error message on mismatch. + * If AV_EF_EXPLODE is also set, a mismatching checksum will result in the + * decoder/demuxer returning an error. + */ +#define AV_EF_CRCCHECK (1<<0) +#define AV_EF_BITSTREAM (1<<1) ///< detect bitstream specification deviations +#define AV_EF_BUFFER (1<<2) ///< detect improper bitstream length +#define AV_EF_EXPLODE (1<<3) ///< abort decoding on minor error detection + +#define AV_EF_IGNORE_ERR (1<<15) ///< ignore errors and continue +#define AV_EF_CAREFUL (1<<16) ///< consider things that violate the spec, are fast to calculate and have not been seen in the wild as errors +#define AV_EF_COMPLIANT (1<<17) ///< consider all spec non compliances as errors +#define AV_EF_AGGRESSIVE (1<<18) ///< consider things that a sane encoder/muxer should not do as an error + +#define FF_COMPLIANCE_VERY_STRICT 2 ///< Strictly conform to an older more strict version of the spec or reference software. +#define FF_COMPLIANCE_STRICT 1 ///< Strictly conform to all the things in the spec no matter what consequences. +#define FF_COMPLIANCE_NORMAL 0 +#define FF_COMPLIANCE_UNOFFICIAL -1 ///< Allow unofficial extensions +#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things. + + +#define AV_PROFILE_UNKNOWN -99 +#define AV_PROFILE_RESERVED -100 + +#define AV_PROFILE_AAC_MAIN 0 +#define AV_PROFILE_AAC_LOW 1 +#define AV_PROFILE_AAC_SSR 2 +#define AV_PROFILE_AAC_LTP 3 +#define AV_PROFILE_AAC_HE 4 +#define AV_PROFILE_AAC_HE_V2 28 +#define AV_PROFILE_AAC_LD 22 +#define AV_PROFILE_AAC_ELD 38 +#define AV_PROFILE_MPEG2_AAC_LOW 128 +#define AV_PROFILE_MPEG2_AAC_HE 131 + +#define AV_PROFILE_DNXHD 0 +#define AV_PROFILE_DNXHR_LB 1 +#define AV_PROFILE_DNXHR_SQ 2 +#define AV_PROFILE_DNXHR_HQ 3 +#define AV_PROFILE_DNXHR_HQX 4 +#define AV_PROFILE_DNXHR_444 5 + +#define AV_PROFILE_DTS 20 +#define AV_PROFILE_DTS_ES 30 +#define AV_PROFILE_DTS_96_24 40 +#define AV_PROFILE_DTS_HD_HRA 50 +#define AV_PROFILE_DTS_HD_MA 60 +#define AV_PROFILE_DTS_EXPRESS 70 +#define AV_PROFILE_DTS_HD_MA_X 61 +#define AV_PROFILE_DTS_HD_MA_X_IMAX 62 + +#define AV_PROFILE_EAC3_DDP_ATMOS 30 + +#define AV_PROFILE_TRUEHD_ATMOS 30 + +#define AV_PROFILE_MPEG2_422 0 +#define AV_PROFILE_MPEG2_HIGH 1 +#define AV_PROFILE_MPEG2_SS 2 +#define AV_PROFILE_MPEG2_SNR_SCALABLE 3 +#define AV_PROFILE_MPEG2_MAIN 4 +#define AV_PROFILE_MPEG2_SIMPLE 5 + +#define AV_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag +#define AV_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag + +#define AV_PROFILE_H264_BASELINE 66 +#define AV_PROFILE_H264_CONSTRAINED_BASELINE (66|AV_PROFILE_H264_CONSTRAINED) +#define AV_PROFILE_H264_MAIN 77 +#define AV_PROFILE_H264_EXTENDED 88 +#define AV_PROFILE_H264_HIGH 100 +#define AV_PROFILE_H264_HIGH_10 110 +#define AV_PROFILE_H264_HIGH_10_INTRA (110|AV_PROFILE_H264_INTRA) +#define AV_PROFILE_H264_MULTIVIEW_HIGH 118 +#define AV_PROFILE_H264_HIGH_422 122 +#define AV_PROFILE_H264_HIGH_422_INTRA (122|AV_PROFILE_H264_INTRA) +#define AV_PROFILE_H264_STEREO_HIGH 128 +#define AV_PROFILE_H264_HIGH_444 144 +#define AV_PROFILE_H264_HIGH_444_PREDICTIVE 244 +#define AV_PROFILE_H264_HIGH_444_INTRA (244|AV_PROFILE_H264_INTRA) +#define AV_PROFILE_H264_CAVLC_444 44 + +#define AV_PROFILE_VC1_SIMPLE 0 +#define AV_PROFILE_VC1_MAIN 1 +#define AV_PROFILE_VC1_COMPLEX 2 +#define AV_PROFILE_VC1_ADVANCED 3 + +#define AV_PROFILE_MPEG4_SIMPLE 0 +#define AV_PROFILE_MPEG4_SIMPLE_SCALABLE 1 +#define AV_PROFILE_MPEG4_CORE 2 +#define AV_PROFILE_MPEG4_MAIN 3 +#define AV_PROFILE_MPEG4_N_BIT 4 +#define AV_PROFILE_MPEG4_SCALABLE_TEXTURE 5 +#define AV_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6 +#define AV_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7 +#define AV_PROFILE_MPEG4_HYBRID 8 +#define AV_PROFILE_MPEG4_ADVANCED_REAL_TIME 9 +#define AV_PROFILE_MPEG4_CORE_SCALABLE 10 +#define AV_PROFILE_MPEG4_ADVANCED_CODING 11 +#define AV_PROFILE_MPEG4_ADVANCED_CORE 12 +#define AV_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13 +#define AV_PROFILE_MPEG4_SIMPLE_STUDIO 14 +#define AV_PROFILE_MPEG4_ADVANCED_SIMPLE 15 + +#define AV_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 1 +#define AV_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 2 +#define AV_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION 32768 +#define AV_PROFILE_JPEG2000_DCINEMA_2K 3 +#define AV_PROFILE_JPEG2000_DCINEMA_4K 4 + +#define AV_PROFILE_VP9_0 0 +#define AV_PROFILE_VP9_1 1 +#define AV_PROFILE_VP9_2 2 +#define AV_PROFILE_VP9_3 3 + +#define AV_PROFILE_HEVC_MAIN 1 +#define AV_PROFILE_HEVC_MAIN_10 2 +#define AV_PROFILE_HEVC_MAIN_STILL_PICTURE 3 +#define AV_PROFILE_HEVC_REXT 4 +#define AV_PROFILE_HEVC_SCC 9 + +#define AV_PROFILE_VVC_MAIN_10 1 +#define AV_PROFILE_VVC_MAIN_10_444 33 + +#define AV_PROFILE_AV1_MAIN 0 +#define AV_PROFILE_AV1_HIGH 1 +#define AV_PROFILE_AV1_PROFESSIONAL 2 + +#define AV_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT 0xc0 +#define AV_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1 +#define AV_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT 0xc2 +#define AV_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3 +#define AV_PROFILE_MJPEG_JPEG_LS 0xf7 + +#define AV_PROFILE_SBC_MSBC 1 + +#define AV_PROFILE_PRORES_PROXY 0 +#define AV_PROFILE_PRORES_LT 1 +#define AV_PROFILE_PRORES_STANDARD 2 +#define AV_PROFILE_PRORES_HQ 3 +#define AV_PROFILE_PRORES_4444 4 +#define AV_PROFILE_PRORES_XQ 5 + +#define AV_PROFILE_ARIB_PROFILE_A 0 +#define AV_PROFILE_ARIB_PROFILE_C 1 + +#define AV_PROFILE_KLVA_SYNC 0 +#define AV_PROFILE_KLVA_ASYNC 1 + +#define AV_PROFILE_EVC_BASELINE 0 +#define AV_PROFILE_EVC_MAIN 1 + + +#define AV_LEVEL_UNKNOWN -99 + +enum AVFieldOrder { + AV_FIELD_UNKNOWN, + AV_FIELD_PROGRESSIVE, + AV_FIELD_TT, ///< Top coded_first, top displayed first + AV_FIELD_BB, ///< Bottom coded first, bottom displayed first + AV_FIELD_TB, ///< Top coded first, bottom displayed first + AV_FIELD_BT, ///< Bottom coded first, top displayed first +}; + +/** + * @ingroup lavc_decoding + */ +enum AVDiscard{ + /* We leave some space between them for extensions (drop some + * keyframes for intra-only or drop just some bidir frames). */ + AVDISCARD_NONE =-16, ///< discard nothing + AVDISCARD_DEFAULT = 0, ///< discard useless packets like 0 size packets in avi + AVDISCARD_NONREF = 8, ///< discard all non reference + AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames + AVDISCARD_NONINTRA= 24, ///< discard all non intra frames + AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes + AVDISCARD_ALL = 48, ///< discard all +}; + +enum AVAudioServiceType { + AV_AUDIO_SERVICE_TYPE_MAIN = 0, + AV_AUDIO_SERVICE_TYPE_EFFECTS = 1, + AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED = 2, + AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED = 3, + AV_AUDIO_SERVICE_TYPE_DIALOGUE = 4, + AV_AUDIO_SERVICE_TYPE_COMMENTARY = 5, + AV_AUDIO_SERVICE_TYPE_EMERGENCY = 6, + AV_AUDIO_SERVICE_TYPE_VOICE_OVER = 7, + AV_AUDIO_SERVICE_TYPE_KARAOKE = 8, + AV_AUDIO_SERVICE_TYPE_NB , ///< Not part of ABI +}; + +/** + * Pan Scan area. + * This specifies the area which should be displayed. + * Note there may be multiple such areas for one frame. + */ +typedef struct AVPanScan { + /** + * id + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int id; + + /** + * width and height in 1/16 pel + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int width; + int height; + + /** + * position of the top left corner in 1/16 pel for up to 3 fields/frames + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int16_t position[3][2]; +} AVPanScan; + +/** + * This structure describes the bitrate properties of an encoded bitstream. It + * roughly corresponds to a subset the VBV parameters for MPEG-2 or HRD + * parameters for H.264/HEVC. + */ +typedef struct AVCPBProperties { + /** + * Maximum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int64_t max_bitrate; + /** + * Minimum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int64_t min_bitrate; + /** + * Average bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int64_t avg_bitrate; + + /** + * The size of the buffer to which the ratecontrol is applied, in bits. + * Zero if unknown or unspecified. + */ + int64_t buffer_size; + + /** + * The delay between the time the packet this structure is associated with + * is received and the time when it should be decoded, in periods of a 27MHz + * clock. + * + * UINT64_MAX when unknown or unspecified. + */ + uint64_t vbv_delay; +} AVCPBProperties; + +/** + * Allocate a CPB properties structure and initialize its fields to default + * values. + * + * @param size if non-NULL, the size of the allocated struct will be written + * here. This is useful for embedding it in side data. + * + * @return the newly allocated struct or NULL on failure + */ +AVCPBProperties *av_cpb_properties_alloc(size_t *size); + +/** + * This structure supplies correlation between a packet timestamp and a wall clock + * production time. The definition follows the Producer Reference Time ('prft') + * as defined in ISO/IEC 14496-12 + */ +typedef struct AVProducerReferenceTime { + /** + * A UTC timestamp, in microseconds, since Unix epoch (e.g, av_gettime()). + */ + int64_t wallclock; + int flags; +} AVProducerReferenceTime; + +/** + * Encode extradata length to a buffer. Used by xiph codecs. + * + * @param s buffer to write to; must be at least (v/255+1) bytes long + * @param v size of extradata in bytes + * @return number of bytes written to the buffer. + */ +unsigned int av_xiphlacing(unsigned char *s, unsigned int v); + +#endif // AVCODEC_DEFS_H diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/packet.h b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/packet.h new file mode 100644 index 0000000000000..b0ba3baea2399 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/packet.h @@ -0,0 +1,870 @@ +/* + * AVPacket public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_PACKET_H +#define AVCODEC_PACKET_H + +#include +#include + +#include "libavutil/attributes.h" +#include "libavutil/buffer.h" +#include "libavutil/dict.h" +#include "libavutil/rational.h" +#include "libavutil/version.h" + +#include "libavcodec/version_major.h" + +/** + * @defgroup lavc_packet_side_data AVPacketSideData + * + * Types and functions for working with AVPacketSideData. + * @{ + */ +enum AVPacketSideDataType { + /** + * An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE + * bytes worth of palette. This side data signals that a new palette is + * present. + */ + AV_PKT_DATA_PALETTE, + + /** + * The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format + * that the extradata buffer was changed and the receiving side should + * act upon it appropriately. The new extradata is embedded in the side + * data buffer and should be immediately used for processing the current + * frame or packet. + */ + AV_PKT_DATA_NEW_EXTRADATA, + + /** + * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows: + * @code + * u32le param_flags + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) + * s32le channel_count + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) + * u64le channel_layout + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) + * s32le sample_rate + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) + * s32le width + * s32le height + * @endcode + */ + AV_PKT_DATA_PARAM_CHANGE, + + /** + * An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of + * structures with info about macroblocks relevant to splitting the + * packet into smaller packets on macroblock edges (e.g. as for RFC 2190). + * That is, it does not necessarily contain info about all macroblocks, + * as long as the distance between macroblocks in the info is smaller + * than the target payload size. + * Each MB info structure is 12 bytes, and is laid out as follows: + * @code + * u32le bit offset from the start of the packet + * u8 current quantizer at the start of the macroblock + * u8 GOB number + * u16le macroblock address within the GOB + * u8 horizontal MV predictor + * u8 vertical MV predictor + * u8 horizontal MV predictor for block number 3 + * u8 vertical MV predictor for block number 3 + * @endcode + */ + AV_PKT_DATA_H263_MB_INFO, + + /** + * This side data should be associated with an audio stream and contains + * ReplayGain information in form of the AVReplayGain struct. + */ + AV_PKT_DATA_REPLAYGAIN, + + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the decoded video frames for + * correct presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_PKT_DATA_DISPLAYMATRIX, + + /** + * This side data should be associated with a video stream and contains + * Stereoscopic 3D information in form of the AVStereo3D struct. + */ + AV_PKT_DATA_STEREO3D, + + /** + * This side data should be associated with an audio stream and corresponds + * to enum AVAudioServiceType. + */ + AV_PKT_DATA_AUDIO_SERVICE_TYPE, + + /** + * This side data contains quality related information from the encoder. + * @code + * u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad). + * u8 picture type + * u8 error count + * u16 reserved + * u64le[error count] sum of squared differences between encoder in and output + * @endcode + */ + AV_PKT_DATA_QUALITY_STATS, + + /** + * This side data contains an integer value representing the stream index + * of a "fallback" track. A fallback track indicates an alternate + * track to use when the current track can not be decoded for some reason. + * e.g. no decoder available for codec. + */ + AV_PKT_DATA_FALLBACK_TRACK, + + /** + * This side data corresponds to the AVCPBProperties struct. + */ + AV_PKT_DATA_CPB_PROPERTIES, + + /** + * Recommmends skipping the specified number of samples + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_PKT_DATA_SKIP_SAMPLES, + + /** + * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that + * the packet may contain "dual mono" audio specific to Japanese DTV + * and if it is true, recommends only the selected channel to be used. + * @code + * u8 selected channels (0=main/left, 1=sub/right, 2=both) + * @endcode + */ + AV_PKT_DATA_JP_DUALMONO, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. + */ + AV_PKT_DATA_STRINGS_METADATA, + + /** + * Subtitle event position + * @code + * u32le x1 + * u32le y1 + * u32le x2 + * u32le y2 + * @endcode + */ + AV_PKT_DATA_SUBTITLE_POSITION, + + /** + * Data found in BlockAdditional element of matroska container. There is + * no end marker for the data, so it is required to rely on the side data + * size to recognize the end. 8 byte id (as found in BlockAddId) followed + * by data. + */ + AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + + /** + * The optional first identifier line of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_IDENTIFIER, + + /** + * The optional settings (rendering instructions) that immediately + * follow the timestamp specifier of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_SETTINGS, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. This + * side data includes updated metadata which appeared in the stream. + */ + AV_PKT_DATA_METADATA_UPDATE, + + /** + * MPEGTS stream ID as uint8_t, this is required to pass the stream ID + * information from the demuxer to the corresponding muxer. + */ + AV_PKT_DATA_MPEGTS_STREAM_ID, + + /** + * Mastering display metadata (based on SMPTE-2086:2014). This metadata + * should be associated with a video stream and contains data in the form + * of the AVMasteringDisplayMetadata struct. + */ + AV_PKT_DATA_MASTERING_DISPLAY_METADATA, + + /** + * This side data should be associated with a video stream and corresponds + * to the AVSphericalMapping structure. + */ + AV_PKT_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This metadata should be + * associated with a video stream and contains data in the form of the + * AVContentLightMetadata struct. + */ + AV_PKT_DATA_CONTENT_LIGHT_LEVEL, + + /** + * ATSC A53 Part 4 Closed Captions. This metadata should be associated with + * a video stream. A53 CC bitstream is stored as uint8_t in AVPacketSideData.data. + * The number of bytes of CC data is AVPacketSideData.size. + */ + AV_PKT_DATA_A53_CC, + + /** + * This side data is encryption initialization data. + * The format is not part of ABI, use av_encryption_init_info_* methods to + * access. + */ + AV_PKT_DATA_ENCRYPTION_INIT_INFO, + + /** + * This side data contains encryption info for how to decrypt the packet. + * The format is not part of ABI, use av_encryption_info_* methods to access. + */ + AV_PKT_DATA_ENCRYPTION_INFO, + + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_PKT_DATA_AFD, + + /** + * Producer Reference Time data corresponding to the AVProducerReferenceTime struct, + * usually exported by some encoders (on demand through the prft flag set in the + * AVCodecContext export_side_data field). + */ + AV_PKT_DATA_PRFT, + + /** + * ICC profile data consisting of an opaque octet buffer following the + * format described by ISO 15076-1. + */ + AV_PKT_DATA_ICC_PROFILE, + + /** + * DOVI configuration + * ref: + * dolby-vision-bitstreams-within-the-iso-base-media-file-format-v2.1.2, section 2.2 + * dolby-vision-bitstreams-in-mpeg-2-transport-stream-multiplex-v1.2, section 3.3 + * Tags are stored in struct AVDOVIDecoderConfigurationRecord. + */ + AV_PKT_DATA_DOVI_CONF, + + /** + * Timecode which conforms to SMPTE ST 12-1:2014. The data is an array of 4 uint32_t + * where the first uint32_t describes how many (1-3) of the other timecodes are used. + * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.h. + */ + AV_PKT_DATA_S12M_TIMECODE, + + /** + * HDR10+ dynamic metadata associated with a video frame. The metadata is in + * the form of the AVDynamicHDRPlus struct and contains + * information for color volume transform - application 4 of + * SMPTE 2094-40:2016 standard. + */ + AV_PKT_DATA_DYNAMIC_HDR10_PLUS, + + /** + * IAMF Mix Gain Parameter Data associated with the audio frame. This metadata + * is in the form of the AVIAMFParamDefinition struct and contains information + * defined in sections 3.6.1 and 3.8.1 of the Immersive Audio Model and + * Formats standard. + */ + AV_PKT_DATA_IAMF_MIX_GAIN_PARAM, + + /** + * IAMF Demixing Info Parameter Data associated with the audio frame. This + * metadata is in the form of the AVIAMFParamDefinition struct and contains + * information defined in sections 3.6.1 and 3.8.2 of the Immersive Audio Model + * and Formats standard. + */ + AV_PKT_DATA_IAMF_DEMIXING_INFO_PARAM, + + /** + * IAMF Recon Gain Info Parameter Data associated with the audio frame. This + * metadata is in the form of the AVIAMFParamDefinition struct and contains + * information defined in sections 3.6.1 and 3.8.3 of the Immersive Audio Model + * and Formats standard. + */ + AV_PKT_DATA_IAMF_RECON_GAIN_INFO_PARAM, + + /** + * Ambient viewing environment metadata, as defined by H.274. This metadata + * should be associated with a video stream and contains data in the form + * of the AVAmbientViewingEnvironment struct. + */ + AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT, + + /** + * The number of side data types. + * This is not part of the public API/ABI in the sense that it may + * change when new side data types are added. + * This must stay the last enum value. + * If its value becomes huge, some code using it + * needs to be updated as it assumes it to be smaller than other limits. + */ + AV_PKT_DATA_NB +}; + +#define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED + +/** + * This structure stores auxiliary information for decoding, presenting, or + * otherwise processing the coded stream. It is typically exported by demuxers + * and encoders and can be fed to decoders and muxers either in a per packet + * basis, or as global side data (applying to the entire coded stream). + * + * Global side data is handled as follows: + * - During demuxing, it may be exported through + * @ref AVStream.codecpar.side_data "AVStream's codec parameters", which can + * then be passed as input to decoders through the + * @ref AVCodecContext.coded_side_data "decoder context's side data", for + * initialization. + * - For muxing, it can be fed through @ref AVStream.codecpar.side_data + * "AVStream's codec parameters", typically the output of encoders through + * the @ref AVCodecContext.coded_side_data "encoder context's side data", for + * initialization. + * + * Packet specific side data is handled as follows: + * - During demuxing, it may be exported through @ref AVPacket.side_data + * "AVPacket's side data", which can then be passed as input to decoders. + * - For muxing, it can be fed through @ref AVPacket.side_data "AVPacket's + * side data", typically the output of encoders. + * + * Different modules may accept or export different types of side data + * depending on media type and codec. Refer to @ref AVPacketSideDataType for a + * list of defined types and where they may be found or used. + */ +typedef struct AVPacketSideData { + uint8_t *data; + size_t size; + enum AVPacketSideDataType type; +} AVPacketSideData; + +/** + * Allocate a new packet side data. + * + * @param sd pointer to an array of side data to which the side data should + * be added. *sd may be NULL, in which case the array will be + * initialized. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. The integer value will be increased by 1 on success. + * @param type side data type + * @param size desired side data size + * @param flags currently unused. Must be zero + * + * @return pointer to freshly allocated side data on success, or NULL otherwise. + */ +AVPacketSideData *av_packet_side_data_new(AVPacketSideData **psd, int *pnb_sd, + enum AVPacketSideDataType type, + size_t size, int flags); + +/** + * Wrap existing data as packet side data. + * + * @param sd pointer to an array of side data to which the side data should + * be added. *sd may be NULL, in which case the array will be + * initialized + * @param nb_sd pointer to an integer containing the number of entries in + * the array. The integer value will be increased by 1 on success. + * @param type side data type + * @param data a data array. It must be allocated with the av_malloc() family + * of functions. The ownership of the data is transferred to the + * side data array on success + * @param size size of the data array + * @param flags currently unused. Must be zero + * + * @return pointer to freshly allocated side data on success, or NULL otherwise + * On failure, the side data array is unchanged and the data remains + * owned by the caller. + */ +AVPacketSideData *av_packet_side_data_add(AVPacketSideData **sd, int *nb_sd, + enum AVPacketSideDataType type, + void *data, size_t size, int flags); + +/** + * Get side information from a side data array. + * + * @param sd the array from which the side data should be fetched + * @param nb_sd value containing the number of entries in the array. + * @param type desired side information type + * + * @return pointer to side data if present or NULL otherwise + */ +const AVPacketSideData *av_packet_side_data_get(const AVPacketSideData *sd, + int nb_sd, + enum AVPacketSideDataType type); + +/** + * Remove side data of the given type from a side data array. + * + * @param sd the array from which the side data should be removed + * @param nb_sd pointer to an integer containing the number of entries in + * the array. Will be reduced by the amount of entries removed + * upon return + * @param type side information type + */ +void av_packet_side_data_remove(AVPacketSideData *sd, int *nb_sd, + enum AVPacketSideDataType type); + +/** + * Convenience function to free all the side data stored in an array, and + * the array itself. + * + * @param sd pointer to array of side data to free. Will be set to NULL + * upon return. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. Will be set to 0 upon return. + */ +void av_packet_side_data_free(AVPacketSideData **sd, int *nb_sd); + +const char *av_packet_side_data_name(enum AVPacketSideDataType type); + +/** + * @} + */ + +/** + * @defgroup lavc_packet AVPacket + * + * Types and functions for working with AVPacket. + * @{ + */ + +/** + * This structure stores compressed data. It is typically exported by demuxers + * and then passed as input to decoders, or received as output from encoders and + * then passed to muxers. + * + * For video, it should typically contain one compressed frame. For audio it may + * contain several compressed frames. Encoders are allowed to output empty + * packets, with no compressed data, containing only side data + * (e.g. to update some stream parameters at the end of encoding). + * + * The semantics of data ownership depends on the buf field. + * If it is set, the packet data is dynamically allocated and is + * valid indefinitely until a call to av_packet_unref() reduces the + * reference count to 0. + * + * If the buf field is not set av_packet_ref() would make a copy instead + * of increasing the reference count. + * + * The side data is always allocated with av_malloc(), copied by + * av_packet_ref() and freed by av_packet_unref(). + * + * sizeof(AVPacket) being a part of the public ABI is deprecated. once + * av_init_packet() is removed, new packets will only be able to be allocated + * with av_packet_alloc(), and new fields may be added to the end of the struct + * with a minor bump. + * + * @see av_packet_alloc + * @see av_packet_ref + * @see av_packet_unref + */ +typedef struct AVPacket { + /** + * A reference to the reference-counted buffer where the packet data is + * stored. + * May be NULL, then the packet data is not reference-counted. + */ + AVBufferRef *buf; + /** + * Presentation timestamp in AVStream->time_base units; the time at which + * the decompressed packet will be presented to the user. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + * pts MUST be larger or equal to dts as presentation cannot happen before + * decompression, unless one wants to view hex dumps. Some formats misuse + * the terms dts and pts/cts to mean something different. Such timestamps + * must be converted to true pts/dts before they are stored in AVPacket. + */ + int64_t pts; + /** + * Decompression timestamp in AVStream->time_base units; the time at which + * the packet is decompressed. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + */ + int64_t dts; + uint8_t *data; + int size; + int stream_index; + /** + * A combination of AV_PKT_FLAG values + */ + int flags; + /** + * Additional packet data that can be provided by the container. + * Packet can contain several types of side information. + */ + AVPacketSideData *side_data; + int side_data_elems; + + /** + * Duration of this packet in AVStream->time_base units, 0 if unknown. + * Equals next_pts - this_pts in presentation order. + */ + int64_t duration; + + int64_t pos; ///< byte position in stream, -1 if unknown + + /** + * for some private data of the user + */ + void *opaque; + + /** + * AVBufferRef for free use by the API user. FFmpeg will never check the + * contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when + * the packet is unreferenced. av_packet_copy_props() calls create a new + * reference with av_buffer_ref() for the target packet's opaque_ref field. + * + * This is unrelated to the opaque field, although it serves a similar + * purpose. + */ + AVBufferRef *opaque_ref; + + /** + * Time base of the packet's timestamps. + * In the future, this field may be set on packets output by encoders or + * demuxers, but its value will be by default ignored on input to decoders + * or muxers. + */ + AVRational time_base; +} AVPacket; + +#if FF_API_INIT_PACKET +attribute_deprecated +typedef struct AVPacketList { + AVPacket pkt; + struct AVPacketList *next; +} AVPacketList; +#endif + +#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe +#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted +/** + * Flag is used to discard packets which are required to maintain valid + * decoder state but are not required for output and should be dropped + * after decoding. + **/ +#define AV_PKT_FLAG_DISCARD 0x0004 +/** + * The packet comes from a trusted source. + * + * Otherwise-unsafe constructs such as arbitrary pointers to data + * outside the packet may be followed. + */ +#define AV_PKT_FLAG_TRUSTED 0x0008 +/** + * Flag is used to indicate packets that contain frames that can + * be discarded by the decoder. I.e. Non-reference frames. + */ +#define AV_PKT_FLAG_DISPOSABLE 0x0010 + +enum AVSideDataParamChangeFlags { + AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004, + AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008, +}; + +/** + * Allocate an AVPacket and set its fields to default values. The resulting + * struct must be freed using av_packet_free(). + * + * @return An AVPacket filled with default values or NULL on failure. + * + * @note this only allocates the AVPacket itself, not the data buffers. Those + * must be allocated through other means such as av_new_packet. + * + * @see av_new_packet + */ +AVPacket *av_packet_alloc(void); + +/** + * Create a new packet that references the same data as src. + * + * This is a shortcut for av_packet_alloc()+av_packet_ref(). + * + * @return newly created AVPacket on success, NULL on error. + * + * @see av_packet_alloc + * @see av_packet_ref + */ +AVPacket *av_packet_clone(const AVPacket *src); + +/** + * Free the packet, if the packet is reference counted, it will be + * unreferenced first. + * + * @param pkt packet to be freed. The pointer will be set to NULL. + * @note passing NULL is a no-op. + */ +void av_packet_free(AVPacket **pkt); + +#if FF_API_INIT_PACKET +/** + * Initialize optional fields of a packet with default values. + * + * Note, this does not touch the data and size members, which have to be + * initialized separately. + * + * @param pkt packet + * + * @see av_packet_alloc + * @see av_packet_unref + * + * @deprecated This function is deprecated. Once it's removed, + sizeof(AVPacket) will not be a part of the ABI anymore. + */ +attribute_deprecated +void av_init_packet(AVPacket *pkt); +#endif + +/** + * Allocate the payload of a packet and initialize its fields with + * default values. + * + * @param pkt packet + * @param size wanted payload size + * @return 0 if OK, AVERROR_xxx otherwise + */ +int av_new_packet(AVPacket *pkt, int size); + +/** + * Reduce packet size, correctly zeroing padding + * + * @param pkt packet + * @param size new size + */ +void av_shrink_packet(AVPacket *pkt, int size); + +/** + * Increase packet size, correctly zeroing padding + * + * @param pkt packet + * @param grow_by number of bytes by which to increase the size of the packet + */ +int av_grow_packet(AVPacket *pkt, int grow_by); + +/** + * Initialize a reference-counted packet from av_malloc()ed data. + * + * @param pkt packet to be initialized. This function will set the data, size, + * and buf fields, all others are left untouched. + * @param data Data allocated by av_malloc() to be used as packet data. If this + * function returns successfully, the data is owned by the underlying AVBuffer. + * The caller may not access the data through other means. + * @param size size of data in bytes, without the padding. I.e. the full buffer + * size is assumed to be size + AV_INPUT_BUFFER_PADDING_SIZE. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size); + +/** + * Allocate new information of a packet. + * + * @param pkt packet + * @param type side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + size_t size); + +/** + * Wrap an existing array as a packet side data. + * + * @param pkt packet + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * pkt. + * @param size side information size + * @return a non-negative number on success, a negative AVERROR code on + * failure. On failure, the packet is unchanged and the data remains + * owned by the caller. + */ +int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + +/** + * Shrink the already allocated side data buffer + * + * @param pkt packet + * @param type side information type + * @param size new side information size + * @return 0 on success, < 0 on failure + */ +int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + size_t size); + +/** + * Get side information from packet. + * + * @param pkt packet + * @param type desired side information type + * @param size If supplied, *size will be set to the size of the side data + * or to zero if the desired side data is not present. + * @return pointer to data if present or NULL otherwise + */ +uint8_t* av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, + size_t *size); + +/** + * Pack a dictionary for use in side_data. + * + * @param dict The dictionary to pack. + * @param size pointer to store the size of the returned data + * @return pointer to data if successful, NULL otherwise + */ +uint8_t *av_packet_pack_dictionary(AVDictionary *dict, size_t *size); +/** + * Unpack a dictionary from side_data. + * + * @param data data from side_data + * @param size size of the data + * @param dict the metadata storage dictionary + * @return 0 on success, < 0 on failure + */ +int av_packet_unpack_dictionary(const uint8_t *data, size_t size, + AVDictionary **dict); + +/** + * Convenience function to free all the side data stored. + * All the other fields stay untouched. + * + * @param pkt packet + */ +void av_packet_free_side_data(AVPacket *pkt); + +/** + * Setup a new reference to the data described by a given packet + * + * If src is reference-counted, setup dst as a new reference to the + * buffer in src. Otherwise allocate a new buffer in dst and copy the + * data from src into it. + * + * All the other fields are copied from src. + * + * @see av_packet_unref + * + * @param dst Destination packet. Will be completely overwritten. + * @param src Source packet + * + * @return 0 on success, a negative AVERROR on error. On error, dst + * will be blank (as if returned by av_packet_alloc()). + */ +int av_packet_ref(AVPacket *dst, const AVPacket *src); + +/** + * Wipe the packet. + * + * Unreference the buffer referenced by the packet and reset the + * remaining packet fields to their default values. + * + * @param pkt The packet to be unreferenced. + */ +void av_packet_unref(AVPacket *pkt); + +/** + * Move every field in src to dst and reset src. + * + * @see av_packet_unref + * + * @param src Source packet, will be reset + * @param dst Destination packet + */ +void av_packet_move_ref(AVPacket *dst, AVPacket *src); + +/** + * Copy only "properties" fields from src to dst. + * + * Properties for the purpose of this function are all the fields + * beside those related to the packet data (buf, data, size) + * + * @param dst Destination packet + * @param src Source packet + * + * @return 0 on success AVERROR on failure. + */ +int av_packet_copy_props(AVPacket *dst, const AVPacket *src); + +/** + * Ensure the data described by a given packet is reference counted. + * + * @note This function does not ensure that the reference will be writable. + * Use av_packet_make_writable instead for that purpose. + * + * @see av_packet_ref + * @see av_packet_make_writable + * + * @param pkt packet whose data should be made reference counted. + * + * @return 0 on success, a negative AVERROR on error. On failure, the + * packet is unchanged. + */ +int av_packet_make_refcounted(AVPacket *pkt); + +/** + * Create a writable reference for the data described by a given packet, + * avoiding data copy if possible. + * + * @param pkt Packet whose data should be made writable. + * + * @return 0 on success, a negative AVERROR on failure. On failure, the + * packet is unchanged. + */ +int av_packet_make_writable(AVPacket *pkt); + +/** + * Convert valid timing fields (timestamps / durations) in a packet from one + * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be + * ignored. + * + * @param pkt packet on which the conversion will be performed + * @param tb_src source timebase, in which the timing fields in pkt are + * expressed + * @param tb_dst destination timebase, to which the timing fields will be + * converted + */ +void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst); + +/** + * @} + */ + +#endif // AVCODEC_PACKET_H diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/version.h b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/version.h new file mode 100644 index 0000000000000..43794ea58856f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/version.h @@ -0,0 +1,45 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VERSION_H +#define AVCODEC_VERSION_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBAVCODEC_VERSION_MINOR 3 +#define LIBAVCODEC_VERSION_MICRO 100 + +#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT + +#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) + +#endif /* AVCODEC_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/version_major.h b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/version_major.h new file mode 100644 index 0000000000000..ab1f4511b4d20 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavcodec/version_major.h @@ -0,0 +1,51 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VERSION_MAJOR_H +#define AVCODEC_VERSION_MAJOR_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#define LIBAVCODEC_VERSION_MAJOR 61 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + */ + +#define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 62) +#define FF_API_SUBFRAMES (LIBAVCODEC_VERSION_MAJOR < 62) +#define FF_API_TICKS_PER_FRAME (LIBAVCODEC_VERSION_MAJOR < 62) +#define FF_API_DROPCHANGED (LIBAVCODEC_VERSION_MAJOR < 62) + +#define FF_API_AVFFT (LIBAVCODEC_VERSION_MAJOR < 62) +#define FF_API_FF_PROFILE_LEVEL (LIBAVCODEC_VERSION_MAJOR < 62) +#define FF_API_AVCODEC_CLOSE (LIBAVCODEC_VERSION_MAJOR < 62) +#define FF_API_BUFFER_MIN_SIZE (LIBAVCODEC_VERSION_MAJOR < 62) +#define FF_API_VDPAU_ALLOC_GET_SET (LIBAVCODEC_VERSION_MAJOR < 62) + +#endif /* AVCODEC_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavformat/avformat.h b/src/framework/media/thirdparty/ffmpeg/v7/libavformat/avformat.h new file mode 100644 index 0000000000000..de403976760cf --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavformat/avformat.h @@ -0,0 +1,3067 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_AVFORMAT_H +#define AVFORMAT_AVFORMAT_H + +/** + * @file + * @ingroup libavf + * Main libavformat public API header + */ + +/** + * @defgroup libavf libavformat + * I/O and Muxing/Demuxing Library + * + * Libavformat (lavf) is a library for dealing with various media container + * formats. Its main two purposes are demuxing - i.e. splitting a media file + * into component streams, and the reverse process of muxing - writing supplied + * data in a specified container format. It also has an @ref lavf_io + * "I/O module" which supports a number of protocols for accessing the data (e.g. + * file, tcp, http and others). + * Unless you are absolutely sure you won't use libavformat's network + * capabilities, you should also call avformat_network_init(). + * + * A supported input format is described by an AVInputFormat struct, conversely + * an output format is described by AVOutputFormat. You can iterate over all + * input/output formats using the av_demuxer_iterate / av_muxer_iterate() functions. + * The protocols layer is not part of the public API, so you can only get the names + * of supported protocols with the avio_enum_protocols() function. + * + * Main lavf structure used for both muxing and demuxing is AVFormatContext, + * which exports all information about the file being read or written. As with + * most Libavformat structures, its size is not part of public ABI, so it cannot be + * allocated on stack or directly with av_malloc(). To create an + * AVFormatContext, use avformat_alloc_context() (some functions, like + * avformat_open_input() might do that for you). + * + * Most importantly an AVFormatContext contains: + * @li the @ref AVFormatContext.iformat "input" or @ref AVFormatContext.oformat + * "output" format. It is either autodetected or set by user for input; + * always set by user for output. + * @li an @ref AVFormatContext.streams "array" of AVStreams, which describe all + * elementary streams stored in the file. AVStreams are typically referred to + * using their index in this array. + * @li an @ref AVFormatContext.pb "I/O context". It is either opened by lavf or + * set by user for input, always set by user for output (unless you are dealing + * with an AVFMT_NOFILE format). + * + * @section lavf_options Passing options to (de)muxers + * It is possible to configure lavf muxers and demuxers using the @ref avoptions + * mechanism. Generic (format-independent) libavformat options are provided by + * AVFormatContext, they can be examined from a user program by calling + * av_opt_next() / av_opt_find() on an allocated AVFormatContext (or its AVClass + * from avformat_get_class()). Private (format-specific) options are provided by + * AVFormatContext.priv_data if and only if AVInputFormat.priv_class / + * AVOutputFormat.priv_class of the corresponding format struct is non-NULL. + * Further options may be provided by the @ref AVFormatContext.pb "I/O context", + * if its AVClass is non-NULL, and the protocols layer. See the discussion on + * nesting in @ref avoptions documentation to learn how to access those. + * + * @section urls + * URL strings in libavformat are made of a scheme/protocol, a ':', and a + * scheme specific string. URLs without a scheme and ':' used for local files + * are supported but deprecated. "file:" should be used for local files. + * + * It is important that the scheme string is not taken from untrusted + * sources without checks. + * + * Note that some schemes/protocols are quite powerful, allowing access to + * both local and remote files, parts of them, concatenations of them, local + * audio and video devices and so on. + * + * @{ + * + * @defgroup lavf_decoding Demuxing + * @{ + * Demuxers read a media file and split it into chunks of data (@em packets). A + * @ref AVPacket "packet" contains one or more encoded frames which belongs to a + * single elementary stream. In the lavf API this process is represented by the + * avformat_open_input() function for opening a file, av_read_frame() for + * reading a single packet and finally avformat_close_input(), which does the + * cleanup. + * + * @section lavf_decoding_open Opening a media file + * The minimum information required to open a file is its URL, which + * is passed to avformat_open_input(), as in the following code: + * @code + * const char *url = "file:in.mp3"; + * AVFormatContext *s = NULL; + * int ret = avformat_open_input(&s, url, NULL, NULL); + * if (ret < 0) + * abort(); + * @endcode + * The above code attempts to allocate an AVFormatContext, open the + * specified file (autodetecting the format) and read the header, exporting the + * information stored there into s. Some formats do not have a header or do not + * store enough information there, so it is recommended that you call the + * avformat_find_stream_info() function which tries to read and decode a few + * frames to find missing information. + * + * In some cases you might want to preallocate an AVFormatContext yourself with + * avformat_alloc_context() and do some tweaking on it before passing it to + * avformat_open_input(). One such case is when you want to use custom functions + * for reading input data instead of lavf internal I/O layer. + * To do that, create your own AVIOContext with avio_alloc_context(), passing + * your reading callbacks to it. Then set the @em pb field of your + * AVFormatContext to newly created AVIOContext. + * + * Since the format of the opened file is in general not known until after + * avformat_open_input() has returned, it is not possible to set demuxer private + * options on a preallocated context. Instead, the options should be passed to + * avformat_open_input() wrapped in an AVDictionary: + * @code + * AVDictionary *options = NULL; + * av_dict_set(&options, "video_size", "640x480", 0); + * av_dict_set(&options, "pixel_format", "rgb24", 0); + * + * if (avformat_open_input(&s, url, NULL, &options) < 0) + * abort(); + * av_dict_free(&options); + * @endcode + * This code passes the private options 'video_size' and 'pixel_format' to the + * demuxer. They would be necessary for e.g. the rawvideo demuxer, since it + * cannot know how to interpret raw video data otherwise. If the format turns + * out to be something different than raw video, those options will not be + * recognized by the demuxer and therefore will not be applied. Such unrecognized + * options are then returned in the options dictionary (recognized options are + * consumed). The calling program can handle such unrecognized options as it + * wishes, e.g. + * @code + * AVDictionaryEntry *e; + * if (e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX)) { + * fprintf(stderr, "Option %s not recognized by the demuxer.\n", e->key); + * abort(); + * } + * @endcode + * + * After you have finished reading the file, you must close it with + * avformat_close_input(). It will free everything associated with the file. + * + * @section lavf_decoding_read Reading from an opened file + * Reading data from an opened AVFormatContext is done by repeatedly calling + * av_read_frame() on it. Each call, if successful, will return an AVPacket + * containing encoded data for one AVStream, identified by + * AVPacket.stream_index. This packet may be passed straight into the libavcodec + * decoding functions avcodec_send_packet() or avcodec_decode_subtitle2() if the + * caller wishes to decode the data. + * + * AVPacket.pts, AVPacket.dts and AVPacket.duration timing information will be + * set if known. They may also be unset (i.e. AV_NOPTS_VALUE for + * pts/dts, 0 for duration) if the stream does not provide them. The timing + * information will be in AVStream.time_base units, i.e. it has to be + * multiplied by the timebase to convert them to seconds. + * + * A packet returned by av_read_frame() is always reference-counted, + * i.e. AVPacket.buf is set and the user may keep it indefinitely. + * The packet must be freed with av_packet_unref() when it is no + * longer needed. + * + * @section lavf_decoding_seek Seeking + * @} + * + * @defgroup lavf_encoding Muxing + * @{ + * Muxers take encoded data in the form of @ref AVPacket "AVPackets" and write + * it into files or other output bytestreams in the specified container format. + * + * The main API functions for muxing are avformat_write_header() for writing the + * file header, av_write_frame() / av_interleaved_write_frame() for writing the + * packets and av_write_trailer() for finalizing the file. + * + * At the beginning of the muxing process, the caller must first call + * avformat_alloc_context() to create a muxing context. The caller then sets up + * the muxer by filling the various fields in this context: + * + * - The @ref AVFormatContext.oformat "oformat" field must be set to select the + * muxer that will be used. + * - Unless the format is of the AVFMT_NOFILE type, the @ref AVFormatContext.pb + * "pb" field must be set to an opened IO context, either returned from + * avio_open2() or a custom one. + * - Unless the format is of the AVFMT_NOSTREAMS type, at least one stream must + * be created with the avformat_new_stream() function. The caller should fill + * the @ref AVStream.codecpar "stream codec parameters" information, such as the + * codec @ref AVCodecParameters.codec_type "type", @ref AVCodecParameters.codec_id + * "id" and other parameters (e.g. width / height, the pixel or sample format, + * etc.) as known. The @ref AVStream.time_base "stream timebase" should + * be set to the timebase that the caller desires to use for this stream (note + * that the timebase actually used by the muxer can be different, as will be + * described later). + * - It is advised to manually initialize only the relevant fields in + * AVCodecParameters, rather than using @ref avcodec_parameters_copy() during + * remuxing: there is no guarantee that the codec context values remain valid + * for both input and output format contexts. + * - The caller may fill in additional information, such as @ref + * AVFormatContext.metadata "global" or @ref AVStream.metadata "per-stream" + * metadata, @ref AVFormatContext.chapters "chapters", @ref + * AVFormatContext.programs "programs", etc. as described in the + * AVFormatContext documentation. Whether such information will actually be + * stored in the output depends on what the container format and the muxer + * support. + * + * When the muxing context is fully set up, the caller must call + * avformat_write_header() to initialize the muxer internals and write the file + * header. Whether anything actually is written to the IO context at this step + * depends on the muxer, but this function must always be called. Any muxer + * private options must be passed in the options parameter to this function. + * + * The data is then sent to the muxer by repeatedly calling av_write_frame() or + * av_interleaved_write_frame() (consult those functions' documentation for + * discussion on the difference between them; only one of them may be used with + * a single muxing context, they should not be mixed). Do note that the timing + * information on the packets sent to the muxer must be in the corresponding + * AVStream's timebase. That timebase is set by the muxer (in the + * avformat_write_header() step) and may be different from the timebase + * requested by the caller. + * + * Once all the data has been written, the caller must call av_write_trailer() + * to flush any buffered packets and finalize the output file, then close the IO + * context (if any) and finally free the muxing context with + * avformat_free_context(). + * @} + * + * @defgroup lavf_io I/O Read/Write + * @{ + * @section lavf_io_dirlist Directory listing + * The directory listing API makes it possible to list files on remote servers. + * + * Some of possible use cases: + * - an "open file" dialog to choose files from a remote location, + * - a recursive media finder providing a player with an ability to play all + * files from a given directory. + * + * @subsection lavf_io_dirlist_open Opening a directory + * At first, a directory needs to be opened by calling avio_open_dir() + * supplied with a URL and, optionally, ::AVDictionary containing + * protocol-specific parameters. The function returns zero or positive + * integer and allocates AVIODirContext on success. + * + * @code + * AVIODirContext *ctx = NULL; + * if (avio_open_dir(&ctx, "smb://example.com/some_dir", NULL) < 0) { + * fprintf(stderr, "Cannot open directory.\n"); + * abort(); + * } + * @endcode + * + * This code tries to open a sample directory using smb protocol without + * any additional parameters. + * + * @subsection lavf_io_dirlist_read Reading entries + * Each directory's entry (i.e. file, another directory, anything else + * within ::AVIODirEntryType) is represented by AVIODirEntry. + * Reading consecutive entries from an opened AVIODirContext is done by + * repeatedly calling avio_read_dir() on it. Each call returns zero or + * positive integer if successful. Reading can be stopped right after the + * NULL entry has been read -- it means there are no entries left to be + * read. The following code reads all entries from a directory associated + * with ctx and prints their names to standard output. + * @code + * AVIODirEntry *entry = NULL; + * for (;;) { + * if (avio_read_dir(ctx, &entry) < 0) { + * fprintf(stderr, "Cannot list directory.\n"); + * abort(); + * } + * if (!entry) + * break; + * printf("%s\n", entry->name); + * avio_free_directory_entry(&entry); + * } + * @endcode + * @} + * + * @defgroup lavf_codec Demuxers + * @{ + * @defgroup lavf_codec_native Native Demuxers + * @{ + * @} + * @defgroup lavf_codec_wrappers External library wrappers + * @{ + * @} + * @} + * @defgroup lavf_protos I/O Protocols + * @{ + * @} + * @defgroup lavf_internal Internal + * @{ + * @} + * @} + */ + +#include /* FILE */ + +#include "libavcodec/codec_par.h" +#include "libavcodec/defs.h" +#include "libavcodec/packet.h" + +#include "libavutil/dict.h" +#include "libavutil/log.h" + +#include "avio.h" +#include "libavformat/version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "libavformat/version.h" + +#include "libavutil/frame.h" +#include "libavcodec/codec.h" +#endif + +struct AVFormatContext; +struct AVFrame; + +/** + * @defgroup metadata_api Public Metadata API + * @{ + * @ingroup libavf + * The metadata API allows libavformat to export metadata tags to a client + * application when demuxing. Conversely it allows a client application to + * set metadata when muxing. + * + * Metadata is exported or set as pairs of key/value strings in the 'metadata' + * fields of the AVFormatContext, AVStream, AVChapter and AVProgram structs + * using the @ref lavu_dict "AVDictionary" API. Like all strings in FFmpeg, + * metadata is assumed to be UTF-8 encoded Unicode. Note that metadata + * exported by demuxers isn't checked to be valid UTF-8 in most cases. + * + * Important concepts to keep in mind: + * - Keys are unique; there can never be 2 tags with the same key. This is + * also meant semantically, i.e., a demuxer should not knowingly produce + * several keys that are literally different but semantically identical. + * E.g., key=Author5, key=Author6. In this example, all authors must be + * placed in the same tag. + * - Metadata is flat, not hierarchical; there are no subtags. If you + * want to store, e.g., the email address of the child of producer Alice + * and actor Bob, that could have key=alice_and_bobs_childs_email_address. + * - Several modifiers can be applied to the tag name. This is done by + * appending a dash character ('-') and the modifier name in the order + * they appear in the list below -- e.g. foo-eng-sort, not foo-sort-eng. + * - language -- a tag whose value is localized for a particular language + * is appended with the ISO 639-2/B 3-letter language code. + * For example: Author-ger=Michael, Author-eng=Mike + * The original/default language is in the unqualified "Author" tag. + * A demuxer should set a default if it sets any translated tag. + * - sorting -- a modified version of a tag that should be used for + * sorting will have '-sort' appended. E.g. artist="The Beatles", + * artist-sort="Beatles, The". + * - Some protocols and demuxers support metadata updates. After a successful + * call to av_read_frame(), AVFormatContext.event_flags or AVStream.event_flags + * will be updated to indicate if metadata changed. In order to detect metadata + * changes on a stream, you need to loop through all streams in the AVFormatContext + * and check their individual event_flags. + * + * - Demuxers attempt to export metadata in a generic format, however tags + * with no generic equivalents are left as they are stored in the container. + * Follows a list of generic tag names: + * + @verbatim + album -- name of the set this work belongs to + album_artist -- main creator of the set/album, if different from artist. + e.g. "Various Artists" for compilation albums. + artist -- main creator of the work + comment -- any additional description of the file. + composer -- who composed the work, if different from artist. + copyright -- name of copyright holder. + creation_time-- date when the file was created, preferably in ISO 8601. + date -- date when the work was created, preferably in ISO 8601. + disc -- number of a subset, e.g. disc in a multi-disc collection. + encoder -- name/settings of the software/hardware that produced the file. + encoded_by -- person/group who created the file. + filename -- original name of the file. + genre -- . + language -- main language in which the work is performed, preferably + in ISO 639-2 format. Multiple languages can be specified by + separating them with commas. + performer -- artist who performed the work, if different from artist. + E.g for "Also sprach Zarathustra", artist would be "Richard + Strauss" and performer "London Philharmonic Orchestra". + publisher -- name of the label/publisher. + service_name -- name of the service in broadcasting (channel name). + service_provider -- name of the service provider in broadcasting. + title -- name of the work. + track -- number of this work in the set, can be in form current/total. + variant_bitrate -- the total bitrate of the bitrate variant that the current stream is part of + @endverbatim + * + * Look in the examples section for an application example how to use the Metadata API. + * + * @} + */ + +/* packet functions */ + + +/** + * Allocate and read the payload of a packet and initialize its + * fields with default values. + * + * @param s associated IO context + * @param pkt packet + * @param size desired payload size + * @return >0 (read size) if OK, AVERROR_xxx otherwise + */ +int av_get_packet(AVIOContext *s, AVPacket *pkt, int size); + + +/** + * Read data and append it to the current content of the AVPacket. + * If pkt->size is 0 this is identical to av_get_packet. + * Note that this uses av_grow_packet and thus involves a realloc + * which is inefficient. Thus this function should only be used + * when there is no reasonable way to know (an upper bound of) + * the final size. + * + * @param s associated IO context + * @param pkt packet + * @param size amount of data to read + * @return >0 (read size) if OK, AVERROR_xxx otherwise, previous data + * will not be lost even if an error occurs. + */ +int av_append_packet(AVIOContext *s, AVPacket *pkt, int size); + +/*************************************************/ +/* input/output formats */ + +struct AVCodecTag; + +/** + * This structure contains the data a format has to probe a file. + */ +typedef struct AVProbeData { + const char *filename; + unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */ + int buf_size; /**< Size of buf except extra allocated bytes */ + const char *mime_type; /**< mime_type, when known. */ +} AVProbeData; + +#define AVPROBE_SCORE_RETRY (AVPROBE_SCORE_MAX/4) +#define AVPROBE_SCORE_STREAM_RETRY (AVPROBE_SCORE_MAX/4-1) + +#define AVPROBE_SCORE_EXTENSION 50 ///< score for file extension +#define AVPROBE_SCORE_MIME 75 ///< score for file mime type +#define AVPROBE_SCORE_MAX 100 ///< maximum score + +#define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer + +/// Demuxer will use avio_open, no opened file should be provided by the caller. +#define AVFMT_NOFILE 0x0001 +#define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */ +/** + * The muxer/demuxer is experimental and should be used with caution. + * + * - demuxers: will not be selected automatically by probing, must be specified + * explicitly. + */ +#define AVFMT_EXPERIMENTAL 0x0004 +#define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */ +#define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */ +#define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */ +#define AVFMT_GENERIC_INDEX 0x0100 /**< Use generic index building code. */ +#define AVFMT_TS_DISCONT 0x0200 /**< Format allows timestamp discontinuities. Note, muxers always require valid (monotone) timestamps */ +#define AVFMT_VARIABLE_FPS 0x0400 /**< Format allows variable fps. */ +#define AVFMT_NODIMENSIONS 0x0800 /**< Format does not need width/height */ +#define AVFMT_NOSTREAMS 0x1000 /**< Format does not require any streams */ +#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fall back on binary search via read_timestamp */ +#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fall back on generic search */ +#define AVFMT_NO_BYTE_SEEK 0x8000 /**< Format does not allow seeking by bytes */ +#if FF_API_ALLOW_FLUSH +#define AVFMT_ALLOW_FLUSH 0x10000 /**< @deprecated: Just send a NULL packet if you want to flush a muxer. */ +#endif +#define AVFMT_TS_NONSTRICT 0x20000 /**< Format does not require strictly + increasing timestamps, but they must + still be monotonic */ +#define AVFMT_TS_NEGATIVE 0x40000 /**< Format allows muxing negative + timestamps. If not set the timestamp + will be shifted in av_write_frame and + av_interleaved_write_frame so they + start from 0. + The user or muxer can override this through + AVFormatContext.avoid_negative_ts + */ + +#define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */ + +/** + * @addtogroup lavf_encoding + * @{ + */ +typedef struct AVOutputFormat { + const char *name; + /** + * Descriptive name for the format, meant to be more human-readable + * than name. You should use the NULL_IF_CONFIG_SMALL() macro + * to define it. + */ + const char *long_name; + const char *mime_type; + const char *extensions; /**< comma-separated filename extensions */ + /* output support */ + enum AVCodecID audio_codec; /**< default audio codec */ + enum AVCodecID video_codec; /**< default video codec */ + enum AVCodecID subtitle_codec; /**< default subtitle codec */ + /** + * can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, + * AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, + * AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, + * AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE + */ + int flags; + + /** + * List of supported codec_id-codec_tag pairs, ordered by "better + * choice first". The arrays are all terminated by AV_CODEC_ID_NONE. + */ + const struct AVCodecTag * const *codec_tag; + + + const AVClass *priv_class; ///< AVClass for the private context +} AVOutputFormat; +/** + * @} + */ + +/** + * @addtogroup lavf_decoding + * @{ + */ +typedef struct AVInputFormat { + /** + * A comma separated list of short names for the format. New names + * may be appended with a minor bump. + */ + const char *name; + + /** + * Descriptive name for the format, meant to be more human-readable + * than name. You should use the NULL_IF_CONFIG_SMALL() macro + * to define it. + */ + const char *long_name; + + /** + * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS, + * AVFMT_NOTIMESTAMPS, AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH, + * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS. + */ + int flags; + + /** + * If extensions are defined, then no probe is done. You should + * usually not use extension format guessing because it is not + * reliable enough + */ + const char *extensions; + + const struct AVCodecTag * const *codec_tag; + + const AVClass *priv_class; ///< AVClass for the private context + + /** + * Comma-separated list of mime types. + * It is used check for matching mime types while probing. + * @see av_probe_input_format2 + */ + const char *mime_type; +} AVInputFormat; +/** + * @} + */ + +enum AVStreamParseType { + AVSTREAM_PARSE_NONE, + AVSTREAM_PARSE_FULL, /**< full parsing and repack */ + AVSTREAM_PARSE_HEADERS, /**< Only parse headers, do not repack. */ + AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on a packet boundary */ + AVSTREAM_PARSE_FULL_ONCE, /**< full parsing and repack of the first frame only, only implemented for H.264 currently */ + AVSTREAM_PARSE_FULL_RAW, /**< full parsing and repack with timestamp and position generation by parser for raw + this assumes that each packet in the file contains no demuxer level headers and + just codec level data, otherwise position generation would fail */ +}; + +typedef struct AVIndexEntry { + int64_t pos; + int64_t timestamp; /**< + * Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are available + * when seeking to this entry. That means preferable PTS on keyframe based formats. + * But demuxers can choose to store a different timestamp, if it is more convenient for the implementation or nothing better + * is known + */ +#define AVINDEX_KEYFRAME 0x0001 +#define AVINDEX_DISCARD_FRAME 0x0002 /** + * Flag is used to indicate which frame should be discarded after decoding. + */ + int flags:2; + int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment). + int min_distance; /**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. */ +} AVIndexEntry; + +/** + * The stream should be chosen by default among other streams of the same type, + * unless the user has explicitly specified otherwise. + */ +#define AV_DISPOSITION_DEFAULT (1 << 0) +/** + * The stream is not in original language. + * + * @note AV_DISPOSITION_ORIGINAL is the inverse of this disposition. At most + * one of them should be set in properly tagged streams. + * @note This disposition may apply to any stream type, not just audio. + */ +#define AV_DISPOSITION_DUB (1 << 1) +/** + * The stream is in original language. + * + * @see the notes for AV_DISPOSITION_DUB + */ +#define AV_DISPOSITION_ORIGINAL (1 << 2) +/** + * The stream is a commentary track. + */ +#define AV_DISPOSITION_COMMENT (1 << 3) +/** + * The stream contains song lyrics. + */ +#define AV_DISPOSITION_LYRICS (1 << 4) +/** + * The stream contains karaoke audio. + */ +#define AV_DISPOSITION_KARAOKE (1 << 5) + +/** + * Track should be used during playback by default. + * Useful for subtitle track that should be displayed + * even when user did not explicitly ask for subtitles. + */ +#define AV_DISPOSITION_FORCED (1 << 6) +/** + * The stream is intended for hearing impaired audiences. + */ +#define AV_DISPOSITION_HEARING_IMPAIRED (1 << 7) +/** + * The stream is intended for visually impaired audiences. + */ +#define AV_DISPOSITION_VISUAL_IMPAIRED (1 << 8) +/** + * The audio stream contains music and sound effects without voice. + */ +#define AV_DISPOSITION_CLEAN_EFFECTS (1 << 9) +/** + * The stream is stored in the file as an attached picture/"cover art" (e.g. + * APIC frame in ID3v2). The first (usually only) packet associated with it + * will be returned among the first few packets read from the file unless + * seeking takes place. It can also be accessed at any time in + * AVStream.attached_pic. + */ +#define AV_DISPOSITION_ATTACHED_PIC (1 << 10) +/** + * The stream is sparse, and contains thumbnail images, often corresponding + * to chapter markers. Only ever used with AV_DISPOSITION_ATTACHED_PIC. + */ +#define AV_DISPOSITION_TIMED_THUMBNAILS (1 << 11) + +/** + * The stream is intended to be mixed with a spatial audio track. For example, + * it could be used for narration or stereo music, and may remain unchanged by + * listener head rotation. + */ +#define AV_DISPOSITION_NON_DIEGETIC (1 << 12) + +/** + * The subtitle stream contains captions, providing a transcription and possibly + * a translation of audio. Typically intended for hearing-impaired audiences. + */ +#define AV_DISPOSITION_CAPTIONS (1 << 16) +/** + * The subtitle stream contains a textual description of the video content. + * Typically intended for visually-impaired audiences or for the cases where the + * video cannot be seen. + */ +#define AV_DISPOSITION_DESCRIPTIONS (1 << 17) +/** + * The subtitle stream contains time-aligned metadata that is not intended to be + * directly presented to the user. + */ +#define AV_DISPOSITION_METADATA (1 << 18) +/** + * The stream is intended to be mixed with another stream before presentation. + * Used for example to signal the stream contains an image part of a HEIF grid, + * or for mix_type=0 in mpegts. + */ +#define AV_DISPOSITION_DEPENDENT (1 << 19) +/** + * The video stream contains still images. + */ +#define AV_DISPOSITION_STILL_IMAGE (1 << 20) + +/** + * @return The AV_DISPOSITION_* flag corresponding to disp or a negative error + * code if disp does not correspond to a known stream disposition. + */ +int av_disposition_from_string(const char *disp); + +/** + * @param disposition a combination of AV_DISPOSITION_* values + * @return The string description corresponding to the lowest set bit in + * disposition. NULL when the lowest set bit does not correspond + * to a known disposition or when disposition is 0. + */ +const char *av_disposition_to_string(int disposition); + +/** + * Options for behavior on timestamp wrap detection. + */ +#define AV_PTS_WRAP_IGNORE 0 ///< ignore the wrap +#define AV_PTS_WRAP_ADD_OFFSET 1 ///< add the format specific offset on wrap detection +#define AV_PTS_WRAP_SUB_OFFSET -1 ///< subtract the format specific offset on wrap detection + +/** + * Stream structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVStream) must not be used outside libav*. + */ +typedef struct AVStream { + /** + * A class for @ref avoptions. Set on stream creation. + */ + const AVClass *av_class; + + int index; /**< stream index in AVFormatContext */ + /** + * Format-specific stream ID. + * decoding: set by libavformat + * encoding: set by the user, replaced by libavformat if left unset + */ + int id; + + /** + * Codec parameters associated with this stream. Allocated and freed by + * libavformat in avformat_new_stream() and avformat_free_context() + * respectively. + * + * - demuxing: filled by libavformat on stream creation or in + * avformat_find_stream_info() + * - muxing: filled by the caller before avformat_write_header() + */ + AVCodecParameters *codecpar; + + void *priv_data; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. + * + * decoding: set by libavformat + * encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the desired timebase. In + * avformat_write_header(), the muxer will overwrite this field + * with the timebase that will actually be used for the timestamps + * written into the file (which may or may not be related to the + * user-provided one, depending on the format). + */ + AVRational time_base; + + /** + * Decoding: pts of the first frame of the stream in presentation order, in stream time base. + * Only set this if you are absolutely 100% sure that the value you set + * it to really is the pts of the first frame. + * This may be undefined (AV_NOPTS_VALUE). + * @note The ASF header does NOT contain a correct start_time the ASF + * demuxer must NOT set this. + */ + int64_t start_time; + + /** + * Decoding: duration of the stream, in stream time base. + * If a source file does not specify a duration, but does specify + * a bitrate, this value will be estimated from bitrate and file size. + * + * Encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the estimated duration. + */ + int64_t duration; + + int64_t nb_frames; ///< number of frames in this stream if known or 0 + + /** + * Stream disposition - a combination of AV_DISPOSITION_* flags. + * - demuxing: set by libavformat when creating the stream or in + * avformat_find_stream_info(). + * - muxing: may be set by the caller before avformat_write_header(). + */ + int disposition; + + enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed. + + /** + * sample aspect ratio (0 if unknown) + * - encoding: Set by user. + * - decoding: Set by libavformat. + */ + AVRational sample_aspect_ratio; + + AVDictionary *metadata; + + /** + * Average framerate + * + * - demuxing: May be set by libavformat when creating the stream or in + * avformat_find_stream_info(). + * - muxing: May be set by the caller before avformat_write_header(). + */ + AVRational avg_frame_rate; + + /** + * For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet + * will contain the attached picture. + * + * decoding: set by libavformat, must not be modified by the caller. + * encoding: unused + */ + AVPacket attached_pic; + +#if FF_API_AVSTREAM_SIDE_DATA + /** + * An array of side data that applies to the whole stream (i.e. the + * container does not allow it to change between packets). + * + * There may be no overlap between the side data in this array and side data + * in the packets. I.e. a given side data is either exported by the muxer + * (demuxing) / set by the caller (muxing) in this array, then it never + * appears in the packets, or the side data is exported / sent through + * the packets (always in the first packet where the value becomes known or + * changes), then it does not appear in this array. + * + * - demuxing: Set by libavformat when the stream is created. + * - muxing: May be set by the caller before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + * + * @deprecated use AVStream's @ref AVCodecParameters.coded_side_data + * "codecpar side data". + */ + attribute_deprecated + AVPacketSideData *side_data; + /** + * The number of elements in the AVStream.side_data array. + * + * @deprecated use AVStream's @ref AVCodecParameters.nb_coded_side_data + * "codecpar side data". + */ + attribute_deprecated + int nb_side_data; +#endif + + /** + * Flags indicating events happening on the stream, a combination of + * AVSTREAM_EVENT_FLAG_*. + * + * - demuxing: may be set by the demuxer in avformat_open_input(), + * avformat_find_stream_info() and av_read_frame(). Flags must be cleared + * by the user once the event has been handled. + * - muxing: may be set by the user after avformat_write_header(). to + * indicate a user-triggered event. The muxer will clear the flags for + * events it has handled in av_[interleaved]_write_frame(). + */ + int event_flags; +/** + * - demuxing: the demuxer read new metadata from the file and updated + * AVStream.metadata accordingly + * - muxing: the user updated AVStream.metadata and wishes the muxer to write + * it into the file + */ +#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 +/** + * - demuxing: new packets for this stream were read from the file. This + * event is informational only and does not guarantee that new packets + * for this stream will necessarily be returned from av_read_frame(). + */ +#define AVSTREAM_EVENT_FLAG_NEW_PACKETS (1 << 1) + + /** + * Real base framerate of the stream. + * This is the lowest framerate with which all timestamps can be + * represented accurately (it is the least common multiple of all + * framerates in the stream). Note, this value is just a guess! + * For example, if the time base is 1/90000 and all frames have either + * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1. + */ + AVRational r_frame_rate; + + /** + * Number of bits in timestamps. Used for wrapping control. + * + * - demuxing: set by libavformat + * - muxing: set by libavformat + * + */ + int pts_wrap_bits; +} AVStream; + +/** + * AVStreamGroupTileGrid holds information on how to combine several + * independent images on a single canvas for presentation. + * + * The output should be a @ref AVStreamGroupTileGrid.background "background" + * colored @ref AVStreamGroupTileGrid.coded_width "coded_width" x + * @ref AVStreamGroupTileGrid.coded_height "coded_height" canvas where a + * @ref AVStreamGroupTileGrid.nb_tiles "nb_tiles" amount of tiles are placed in + * the order they appear in the @ref AVStreamGroupTileGrid.offsets "offsets" + * array, at the exact offset described for them. In particular, if two or more + * tiles overlap, the image with higher index in the + * @ref AVStreamGroupTileGrid.offsets "offsets" array takes priority. + * Note that a single image may be used multiple times, i.e. multiple entries + * in @ref AVStreamGroupTileGrid.offsets "offsets" may have the same value of + * idx. + * + * The following is an example of a simple grid with 3 rows and 4 columns: + * + * +---+---+---+---+ + * | 0 | 1 | 2 | 3 | + * +---+---+---+---+ + * | 4 | 5 | 6 | 7 | + * +---+---+---+---+ + * | 8 | 9 |10 |11 | + * +---+---+---+---+ + * + * Assuming all tiles have a dimension of 512x512, the + * @ref AVStreamGroupTileGrid.offsets "offset" of the topleft pixel of + * the first @ref AVStreamGroup.streams "stream" in the group is "0,0", the + * @ref AVStreamGroupTileGrid.offsets "offset" of the topleft pixel of + * the second @ref AVStreamGroup.streams "stream" in the group is "512,0", the + * @ref AVStreamGroupTileGrid.offsets "offset" of the topleft pixel of + * the fifth @ref AVStreamGroup.streams "stream" in the group is "0,512", the + * @ref AVStreamGroupTileGrid.offsets "offset", of the topleft pixel of + * the sixth @ref AVStreamGroup.streams "stream" in the group is "512,512", + * etc. + * + * The following is an example of a canvas with overlaping tiles: + * + * +-----------+ + * | %%%%% | + * |***%%3%%@@@| + * |**0%%%%%2@@| + * |***##1@@@@@| + * | ##### | + * +-----------+ + * + * Assuming a canvas with size 1024x1024 and all tiles with a dimension of + * 512x512, a possible @ref AVStreamGroupTileGrid.offsets "offset" for the + * topleft pixel of the first @ref AVStreamGroup.streams "stream" in the group + * would be 0x256, the @ref AVStreamGroupTileGrid.offsets "offset" for the + * topleft pixel of the second @ref AVStreamGroup.streams "stream" in the group + * would be 256x512, the @ref AVStreamGroupTileGrid.offsets "offset" for the + * topleft pixel of the third @ref AVStreamGroup.streams "stream" in the group + * would be 512x256, and the @ref AVStreamGroupTileGrid.offsets "offset" for + * the topleft pixel of the fourth @ref AVStreamGroup.streams "stream" in the + * group would be 256x0. + * + * sizeof(AVStreamGroupTileGrid) is not a part of the ABI and may only be + * allocated by avformat_stream_group_create(). + */ +typedef struct AVStreamGroupTileGrid { + const AVClass *av_class; + + /** + * Amount of tiles in the grid. + * + * Must be > 0. + */ + unsigned int nb_tiles; + + /** + * Width of the canvas. + * + * Must be > 0. + */ + int coded_width; + /** + * Width of the canvas. + * + * Must be > 0. + */ + int coded_height; + + /** + * An @ref nb_tiles sized array of offsets in pixels from the topleft edge + * of the canvas, indicating where each stream should be placed. + * It must be allocated with the av_malloc() family of functions. + * + * - demuxing: set by libavformat, must not be modified by the caller. + * - muxing: set by the caller before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + */ + struct { + /** + * Index of the stream in the group this tile references. + * + * Must be < @ref AVStreamGroup.nb_streams "nb_streams". + */ + unsigned int idx; + /** + * Offset in pixels from the left edge of the canvas where the tile + * should be placed. + */ + int horizontal; + /** + * Offset in pixels from the top edge of the canvas where the tile + * should be placed. + */ + int vertical; + } *offsets; + + /** + * The pixel value per channel in RGBA format used if no pixel of any tile + * is located at a particular pixel location. + * + * @see av_image_fill_color(). + * @see av_parse_color(). + */ + uint8_t background[4]; + + /** + * Offset in pixels from the left edge of the canvas where the actual image + * meant for presentation starts. + * + * This field must be >= 0 and < @ref coded_width. + */ + int horizontal_offset; + /** + * Offset in pixels from the top edge of the canvas where the actual image + * meant for presentation starts. + * + * This field must be >= 0 and < @ref coded_height. + */ + int vertical_offset; + + /** + * Width of the final image for presentation. + * + * Must be > 0 and <= (@ref coded_width - @ref horizontal_offset). + * When it's not equal to (@ref coded_width - @ref horizontal_offset), the + * result of (@ref coded_width - width - @ref horizontal_offset) is the + * amount amount of pixels to be cropped from the right edge of the + * final image before presentation. + */ + int width; + /** + * Height of the final image for presentation. + * + * Must be > 0 and <= (@ref coded_height - @ref vertical_offset). + * When it's not equal to (@ref coded_height - @ref vertical_offset), the + * result of (@ref coded_height - height - @ref vertical_offset) is the + * amount amount of pixels to be cropped from the bottom edge of the + * final image before presentation. + */ + int height; +} AVStreamGroupTileGrid; + +enum AVStreamGroupParamsType { + AV_STREAM_GROUP_PARAMS_NONE, + AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, + AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, + AV_STREAM_GROUP_PARAMS_TILE_GRID, +}; + +struct AVIAMFAudioElement; +struct AVIAMFMixPresentation; + +typedef struct AVStreamGroup { + /** + * A class for @ref avoptions. Set by avformat_stream_group_create(). + */ + const AVClass *av_class; + + void *priv_data; + + /** + * Group index in AVFormatContext. + */ + unsigned int index; + + /** + * Group type-specific group ID. + * + * decoding: set by libavformat + * encoding: may set by the user + */ + int64_t id; + + /** + * Group type + * + * decoding: set by libavformat on group creation + * encoding: set by avformat_stream_group_create() + */ + enum AVStreamGroupParamsType type; + + /** + * Group type-specific parameters + */ + union { + struct AVIAMFAudioElement *iamf_audio_element; + struct AVIAMFMixPresentation *iamf_mix_presentation; + struct AVStreamGroupTileGrid *tile_grid; + } params; + + /** + * Metadata that applies to the whole group. + * + * - demuxing: set by libavformat on group creation + * - muxing: may be set by the caller before avformat_write_header() + * + * Freed by libavformat in avformat_free_context(). + */ + AVDictionary *metadata; + + /** + * Number of elements in AVStreamGroup.streams. + * + * Set by avformat_stream_group_add_stream() must not be modified by any other code. + */ + unsigned int nb_streams; + + /** + * A list of streams in the group. New entries are created with + * avformat_stream_group_add_stream(). + * + * - demuxing: entries are created by libavformat on group creation. + * If AVFMTCTX_NOHEADER is set in ctx_flags, then new entries may also + * appear in av_read_frame(). + * - muxing: entries are created by the user before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + */ + AVStream **streams; + + /** + * Stream group disposition - a combination of AV_DISPOSITION_* flags. + * This field currently applies to all defined AVStreamGroupParamsType. + * + * - demuxing: set by libavformat when creating the group or in + * avformat_find_stream_info(). + * - muxing: may be set by the caller before avformat_write_header(). + */ + int disposition; +} AVStreamGroup; + +struct AVCodecParserContext *av_stream_get_parser(const AVStream *s); + +#define AV_PROGRAM_RUNNING 1 + +/** + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVProgram) must not be used outside libav*. + */ +typedef struct AVProgram { + int id; + int flags; + enum AVDiscard discard; ///< selects which program to discard and which to feed to the caller + unsigned int *stream_index; + unsigned int nb_stream_indexes; + AVDictionary *metadata; + + int program_num; + int pmt_pid; + int pcr_pid; + int pmt_version; + + /***************************************************************** + * All fields below this line are not part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + int64_t start_time; + int64_t end_time; + + int64_t pts_wrap_reference; ///< reference dts for wrap detection + int pts_wrap_behavior; ///< behavior on wrap detection +} AVProgram; + +#define AVFMTCTX_NOHEADER 0x0001 /**< signal that no header is present + (streams are added dynamically) */ +#define AVFMTCTX_UNSEEKABLE 0x0002 /**< signal that the stream is definitely + not seekable, and attempts to call the + seek function will fail. For some + network protocols (e.g. HLS), this can + change dynamically at runtime. */ + +typedef struct AVChapter { + int64_t id; ///< unique ID to identify the chapter + AVRational time_base; ///< time base in which the start/end timestamps are specified + int64_t start, end; ///< chapter start/end time in time_base units + AVDictionary *metadata; +} AVChapter; + + +/** + * Callback used by devices to communicate with application. + */ +typedef int (*av_format_control_message)(struct AVFormatContext *s, int type, + void *data, size_t data_size); + +typedef int (*AVOpenCallback)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, + const AVIOInterruptCB *int_cb, AVDictionary **options); + +/** + * The duration of a video can be estimated through various ways, and this enum can be used + * to know how the duration was estimated. + */ +enum AVDurationEstimationMethod { + AVFMT_DURATION_FROM_PTS, ///< Duration accurately estimated from PTSes + AVFMT_DURATION_FROM_STREAM, ///< Duration estimated from a stream with a known duration + AVFMT_DURATION_FROM_BITRATE ///< Duration estimated from bitrate (less accurate) +}; + +/** + * Format I/O context. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVFormatContext) must not be used outside libav*, use + * avformat_alloc_context() to create an AVFormatContext. + * + * Fields can be accessed through AVOptions (av_opt*), + * the name string used matches the associated command line parameter name and + * can be found in libavformat/options_table.h. + * The AVOption/command line parameter names differ in some cases from the C + * structure field names for historic reasons or brevity. + */ +typedef struct AVFormatContext { + /** + * A class for logging and @ref avoptions. Set by avformat_alloc_context(). + * Exports (de)muxer private options if they exist. + */ + const AVClass *av_class; + + /** + * The input container format. + * + * Demuxing only, set by avformat_open_input(). + */ + const struct AVInputFormat *iformat; + + /** + * The output container format. + * + * Muxing only, must be set by the caller before avformat_write_header(). + */ + const struct AVOutputFormat *oformat; + + /** + * Format private data. This is an AVOptions-enabled struct + * if and only if iformat/oformat.priv_class is not NULL. + * + * - muxing: set by avformat_write_header() + * - demuxing: set by avformat_open_input() + */ + void *priv_data; + + /** + * I/O context. + * + * - demuxing: either set by the user before avformat_open_input() (then + * the user must close it manually) or set by avformat_open_input(). + * - muxing: set by the user before avformat_write_header(). The caller must + * take care of closing / freeing the IO context. + * + * Do NOT set this field if AVFMT_NOFILE flag is set in + * iformat/oformat.flags. In such a case, the (de)muxer will handle + * I/O in some other way and this field will be NULL. + */ + AVIOContext *pb; + + /* stream info */ + /** + * Flags signalling stream properties. A combination of AVFMTCTX_*. + * Set by libavformat. + */ + int ctx_flags; + + /** + * Number of elements in AVFormatContext.streams. + * + * Set by avformat_new_stream(), must not be modified by any other code. + */ + unsigned int nb_streams; + /** + * A list of all streams in the file. New streams are created with + * avformat_new_stream(). + * + * - demuxing: streams are created by libavformat in avformat_open_input(). + * If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also + * appear in av_read_frame(). + * - muxing: streams are created by the user before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + */ + AVStream **streams; + + /** + * Number of elements in AVFormatContext.stream_groups. + * + * Set by avformat_stream_group_create(), must not be modified by any other code. + */ + unsigned int nb_stream_groups; + /** + * A list of all stream groups in the file. New groups are created with + * avformat_stream_group_create(), and filled with avformat_stream_group_add_stream(). + * + * - demuxing: groups may be created by libavformat in avformat_open_input(). + * If AVFMTCTX_NOHEADER is set in ctx_flags, then new groups may also + * appear in av_read_frame(). + * - muxing: groups may be created by the user before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + */ + AVStreamGroup **stream_groups; + + /** + * Number of chapters in AVChapter array. + * When muxing, chapters are normally written in the file header, + * so nb_chapters should normally be initialized before write_header + * is called. Some muxers (e.g. mov and mkv) can also write chapters + * in the trailer. To write chapters in the trailer, nb_chapters + * must be zero when write_header is called and non-zero when + * write_trailer is called. + * - muxing: set by user + * - demuxing: set by libavformat + */ + unsigned int nb_chapters; + AVChapter **chapters; + + /** + * input or output URL. Unlike the old filename field, this field has no + * length restriction. + * + * - demuxing: set by avformat_open_input(), initialized to an empty + * string if url parameter was NULL in avformat_open_input(). + * - muxing: may be set by the caller before calling avformat_write_header() + * (or avformat_init_output() if that is called first) to a string + * which is freeable by av_free(). Set to an empty string if it + * was NULL in avformat_init_output(). + * + * Freed by libavformat in avformat_free_context(). + */ + char *url; + + /** + * Position of the first frame of the component, in + * AV_TIME_BASE fractional seconds. NEVER set this value directly: + * It is deduced from the AVStream values. + * + * Demuxing only, set by libavformat. + */ + int64_t start_time; + + /** + * Duration of the stream, in AV_TIME_BASE fractional + * seconds. Only set this value if you know none of the individual stream + * durations and also do not set any of them. This is deduced from the + * AVStream values if not set. + * + * Demuxing only, set by libavformat. + */ + int64_t duration; + + /** + * Total stream bitrate in bit/s, 0 if not + * available. Never set it directly if the file_size and the + * duration are known as FFmpeg can compute it automatically. + */ + int64_t bit_rate; + + unsigned int packet_size; + int max_delay; + + /** + * Flags modifying the (de)muxer behaviour. A combination of AVFMT_FLAG_*. + * Set by the user before avformat_open_input() / avformat_write_header(). + */ + int flags; +#define AVFMT_FLAG_GENPTS 0x0001 ///< Generate missing pts even if it requires parsing future frames. +#define AVFMT_FLAG_IGNIDX 0x0002 ///< Ignore index. +#define AVFMT_FLAG_NONBLOCK 0x0004 ///< Do not block when reading packets from input. +#define AVFMT_FLAG_IGNDTS 0x0008 ///< Ignore DTS on frames that contain both DTS & PTS +#define AVFMT_FLAG_NOFILLIN 0x0010 ///< Do not infer any values from other values, just return what is stored in the container +#define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled +#define AVFMT_FLAG_NOBUFFER 0x0040 ///< Do not buffer frames when possible +#define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it. +#define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted +#define AVFMT_FLAG_FLUSH_PACKETS 0x0200 ///< Flush the AVIOContext every packet. +/** + * When muxing, try to avoid writing any random/volatile data to the output. + * This includes any random IDs, real-time timestamps/dates, muxer version, etc. + * + * This flag is mainly intended for testing. + */ +#define AVFMT_FLAG_BITEXACT 0x0400 +#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down) +#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats +#if FF_API_LAVF_SHORTEST +#define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops. +#endif +#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer + + /** + * Maximum number of bytes read from input in order to determine stream + * properties. Used when reading the global header and in + * avformat_find_stream_info(). + * + * Demuxing only, set by the caller before avformat_open_input(). + * + * @note this is \e not used for determining the \ref AVInputFormat + * "input format" + * @sa format_probesize + */ + int64_t probesize; + + /** + * Maximum duration (in AV_TIME_BASE units) of the data read + * from input in avformat_find_stream_info(). + * Demuxing only, set by the caller before avformat_find_stream_info(). + * Can be set to 0 to let avformat choose using a heuristic. + */ + int64_t max_analyze_duration; + + const uint8_t *key; + int keylen; + + unsigned int nb_programs; + AVProgram **programs; + + /** + * Forced video codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID video_codec_id; + + /** + * Forced audio codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID audio_codec_id; + + /** + * Forced subtitle codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID subtitle_codec_id; + + /** + * Forced Data codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID data_codec_id; + + /** + * Metadata that applies to the whole file. + * + * - demuxing: set by libavformat in avformat_open_input() + * - muxing: may be set by the caller before avformat_write_header() + * + * Freed by libavformat in avformat_free_context(). + */ + AVDictionary *metadata; + + /** + * Start time of the stream in real world time, in microseconds + * since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the + * stream was captured at this real world time. + * - muxing: Set by the caller before avformat_write_header(). If set to + * either 0 or AV_NOPTS_VALUE, then the current wall-time will + * be used. + * - demuxing: Set by libavformat. AV_NOPTS_VALUE if unknown. Note that + * the value may become known after some number of frames + * have been received. + */ + int64_t start_time_realtime; + + /** + * The number of frames used for determining the framerate in + * avformat_find_stream_info(). + * Demuxing only, set by the caller before avformat_find_stream_info(). + */ + int fps_probe_size; + + /** + * Error recognition; higher values will detect more errors but may + * misdetect some more or less valid parts as errors. + * Demuxing only, set by the caller before avformat_open_input(). + */ + int error_recognition; + + /** + * Custom interrupt callbacks for the I/O layer. + * + * demuxing: set by the user before avformat_open_input(). + * muxing: set by the user before avformat_write_header() + * (mainly useful for AVFMT_NOFILE formats). The callback + * should also be passed to avio_open2() if it's used to + * open the file. + */ + AVIOInterruptCB interrupt_callback; + + /** + * Flags to enable debugging. + */ + int debug; +#define FF_FDEBUG_TS 0x0001 + + /** + * The maximum number of streams. + * - encoding: unused + * - decoding: set by user + */ + int max_streams; + + /** + * Maximum amount of memory in bytes to use for the index of each stream. + * If the index exceeds this size, entries will be discarded as + * needed to maintain a smaller size. This can lead to slower or less + * accurate seeking (depends on demuxer). + * Demuxers for which a full in-memory index is mandatory will ignore + * this. + * - muxing: unused + * - demuxing: set by user + */ + unsigned int max_index_size; + + /** + * Maximum amount of memory in bytes to use for buffering frames + * obtained from realtime capture devices. + */ + unsigned int max_picture_buffer; + + /** + * Maximum buffering duration for interleaving. + * + * To ensure all the streams are interleaved correctly, + * av_interleaved_write_frame() will wait until it has at least one packet + * for each stream before actually writing any packets to the output file. + * When some streams are "sparse" (i.e. there are large gaps between + * successive packets), this can result in excessive buffering. + * + * This field specifies the maximum difference between the timestamps of the + * first and the last packet in the muxing queue, above which libavformat + * will output a packet regardless of whether it has queued a packet for all + * the streams. + * + * Muxing only, set by the caller before avformat_write_header(). + */ + int64_t max_interleave_delta; + + /** + * Maximum number of packets to read while waiting for the first timestamp. + * Decoding only. + */ + int max_ts_probe; + + /** + * Max chunk time in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int max_chunk_duration; + + /** + * Max chunk size in bytes + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int max_chunk_size; + + /** + * Maximum number of packets that can be probed + * - encoding: unused + * - decoding: set by user + */ + int max_probe_packets; + + /** + * Allow non-standard and experimental extension + * @see AVCodecContext.strict_std_compliance + */ + int strict_std_compliance; + + /** + * Flags indicating events happening on the file, a combination of + * AVFMT_EVENT_FLAG_*. + * + * - demuxing: may be set by the demuxer in avformat_open_input(), + * avformat_find_stream_info() and av_read_frame(). Flags must be cleared + * by the user once the event has been handled. + * - muxing: may be set by the user after avformat_write_header() to + * indicate a user-triggered event. The muxer will clear the flags for + * events it has handled in av_[interleaved]_write_frame(). + */ + int event_flags; +/** + * - demuxing: the demuxer read new metadata from the file and updated + * AVFormatContext.metadata accordingly + * - muxing: the user updated AVFormatContext.metadata and wishes the muxer to + * write it into the file + */ +#define AVFMT_EVENT_FLAG_METADATA_UPDATED 0x0001 + + + /** + * Avoid negative timestamps during muxing. + * Any value of the AVFMT_AVOID_NEG_TS_* constants. + * Note, this works better when using av_interleaved_write_frame(). + * - muxing: Set by user + * - demuxing: unused + */ + int avoid_negative_ts; +#define AVFMT_AVOID_NEG_TS_AUTO -1 ///< Enabled when required by target format +#define AVFMT_AVOID_NEG_TS_DISABLED 0 ///< Do not shift timestamps even when they are negative. +#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative +#define AVFMT_AVOID_NEG_TS_MAKE_ZERO 2 ///< Shift timestamps so that they start at 0 + + /** + * Audio preload in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int audio_preload; + + /** + * forces the use of wallclock timestamps as pts/dts of packets + * This has undefined results in the presence of B frames. + * - encoding: unused + * - decoding: Set by user + */ + int use_wallclock_as_timestamps; + + /** + * Skip duration calcuation in estimate_timings_from_pts. + * - encoding: unused + * - decoding: set by user + */ + int skip_estimate_duration_from_pts; + + /** + * avio flags, used to force AVIO_FLAG_DIRECT. + * - encoding: unused + * - decoding: Set by user + */ + int avio_flags; + + /** + * The duration field can be estimated through various ways, and this field can be used + * to know how the duration was estimated. + * - encoding: unused + * - decoding: Read by user + */ + enum AVDurationEstimationMethod duration_estimation_method; + + /** + * Skip initial bytes when opening stream + * - encoding: unused + * - decoding: Set by user + */ + int64_t skip_initial_bytes; + + /** + * Correct single timestamp overflows + * - encoding: unused + * - decoding: Set by user + */ + unsigned int correct_ts_overflow; + + /** + * Force seeking to any (also non key) frames. + * - encoding: unused + * - decoding: Set by user + */ + int seek2any; + + /** + * Flush the I/O context after each packet. + * - encoding: Set by user + * - decoding: unused + */ + int flush_packets; + + /** + * format probing score. + * The maximal score is AVPROBE_SCORE_MAX, its set when the demuxer probes + * the format. + * - encoding: unused + * - decoding: set by avformat, read by user + */ + int probe_score; + + /** + * Maximum number of bytes read from input in order to identify the + * \ref AVInputFormat "input format". Only used when the format is not set + * explicitly by the caller. + * + * Demuxing only, set by the caller before avformat_open_input(). + * + * @sa probesize + */ + int format_probesize; + + /** + * ',' separated list of allowed decoders. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *codec_whitelist; + + /** + * ',' separated list of allowed demuxers. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *format_whitelist; + + /** + * ',' separated list of allowed protocols. + * - encoding: unused + * - decoding: set by user + */ + char *protocol_whitelist; + + /** + * ',' separated list of disallowed protocols. + * - encoding: unused + * - decoding: set by user + */ + char *protocol_blacklist; + + /** + * IO repositioned flag. + * This is set by avformat when the underlaying IO context read pointer + * is repositioned, for example when doing byte based seeking. + * Demuxers can use the flag to detect such changes. + */ + int io_repositioned; + + /** + * Forced video codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const struct AVCodec *video_codec; + + /** + * Forced audio codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const struct AVCodec *audio_codec; + + /** + * Forced subtitle codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const struct AVCodec *subtitle_codec; + + /** + * Forced data codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const struct AVCodec *data_codec; + + /** + * Number of bytes to be written as padding in a metadata header. + * Demuxing: Unused. + * Muxing: Set by user. + */ + int metadata_header_padding; + + /** + * User data. + * This is a place for some private data of the user. + */ + void *opaque; + + /** + * Callback used by devices to communicate with application. + */ + av_format_control_message control_message_cb; + + /** + * Output timestamp offset, in microseconds. + * Muxing: set by user + */ + int64_t output_ts_offset; + + /** + * dump format separator. + * can be ", " or "\n " or anything else + * - muxing: Set by user. + * - demuxing: Set by user. + */ + uint8_t *dump_separator; + + /** + * A callback for opening new IO streams. + * + * Whenever a muxer or a demuxer needs to open an IO stream (typically from + * avformat_open_input() for demuxers, but for certain formats can happen at + * other times as well), it will call this callback to obtain an IO context. + * + * @param s the format context + * @param pb on success, the newly opened IO context should be returned here + * @param url the url to open + * @param flags a combination of AVIO_FLAG_* + * @param options a dictionary of additional options, with the same + * semantics as in avio_open2() + * @return 0 on success, a negative AVERROR code on failure + * + * @note Certain muxers and demuxers do nesting, i.e. they open one or more + * additional internal format contexts. Thus the AVFormatContext pointer + * passed to this callback may be different from the one facing the caller. + * It will, however, have the same 'opaque' field. + */ + int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, + int flags, AVDictionary **options); + + /** + * A callback for closing the streams opened with AVFormatContext.io_open(). + * + * Using this is preferred over io_close, because this can return an error. + * Therefore this callback is used instead of io_close by the generic + * libavformat code if io_close is NULL or the default. + * + * @param s the format context + * @param pb IO context to be closed and freed + * @return 0 on success, a negative AVERROR code on failure + */ + int (*io_close2)(struct AVFormatContext *s, AVIOContext *pb); +} AVFormatContext; + +/** + * This function will cause global side data to be injected in the next packet + * of each stream as well as after any subsequent seek. + * + * @note global side data is always available in every AVStream's + * @ref AVCodecParameters.coded_side_data "codecpar side data" array, and + * in a @ref AVCodecContext.coded_side_data "decoder's side data" array if + * initialized with said stream's codecpar. + * @see av_packet_side_data_get() + */ +void av_format_inject_global_side_data(AVFormatContext *s); + +#if FF_API_GET_DUR_ESTIMATE_METHOD +/** + * Returns the method used to set ctx->duration. + * + * @return AVFMT_DURATION_FROM_PTS, AVFMT_DURATION_FROM_STREAM, or AVFMT_DURATION_FROM_BITRATE. + * @deprecated duration_estimation_method is public and can be read directly. + */ +attribute_deprecated +enum AVDurationEstimationMethod av_fmt_ctx_get_duration_estimation_method(const AVFormatContext* ctx); +#endif + +/** + * @defgroup lavf_core Core functions + * @ingroup libavf + * + * Functions for querying libavformat capabilities, allocating core structures, + * etc. + * @{ + */ + +/** + * Return the LIBAVFORMAT_VERSION_INT constant. + */ +unsigned avformat_version(void); + +/** + * Return the libavformat build-time configuration. + */ +const char *avformat_configuration(void); + +/** + * Return the libavformat license. + */ +const char *avformat_license(void); + +/** + * Do global initialization of network libraries. This is optional, + * and not recommended anymore. + * + * This functions only exists to work around thread-safety issues + * with older GnuTLS or OpenSSL libraries. If libavformat is linked + * to newer versions of those libraries, or if you do not use them, + * calling this function is unnecessary. Otherwise, you need to call + * this function before any other threads using them are started. + * + * This function will be deprecated once support for older GnuTLS and + * OpenSSL libraries is removed, and this function has no purpose + * anymore. + */ +int avformat_network_init(void); + +/** + * Undo the initialization done by avformat_network_init. Call it only + * once for each time you called avformat_network_init. + */ +int avformat_network_deinit(void); + +/** + * Iterate over all registered muxers. + * + * @param opaque a pointer where libavformat will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered muxer or NULL when the iteration is + * finished + */ +const AVOutputFormat *av_muxer_iterate(void **opaque); + +/** + * Iterate over all registered demuxers. + * + * @param opaque a pointer where libavformat will store the iteration state. + * Must point to NULL to start the iteration. + * + * @return the next registered demuxer or NULL when the iteration is + * finished + */ +const AVInputFormat *av_demuxer_iterate(void **opaque); + +/** + * Allocate an AVFormatContext. + * avformat_free_context() can be used to free the context and everything + * allocated by the framework within it. + */ +AVFormatContext *avformat_alloc_context(void); + +/** + * Free an AVFormatContext and all its streams. + * @param s context to free + */ +void avformat_free_context(AVFormatContext *s); + +/** + * Get the AVClass for AVFormatContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avformat_get_class(void); + +/** + * Get the AVClass for AVStream. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *av_stream_get_class(void); + +/** + * Get the AVClass for AVStreamGroup. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *av_stream_group_get_class(void); + +/** + * @return a string identifying the stream group type, or NULL if unknown + */ +const char *avformat_stream_group_name(enum AVStreamGroupParamsType type); + +/** + * Add a new empty stream group to a media file. + * + * When demuxing, it may be called by the demuxer in read_header(). If the + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also + * be called in read_packet(). + * + * When muxing, may be called by the user before avformat_write_header(). + * + * User is required to call avformat_free_context() to clean up the allocation + * by avformat_stream_group_create(). + * + * New streams can be added to the group with avformat_stream_group_add_stream(). + * + * @param s media file handle + * + * @return newly created group or NULL on error. + * @see avformat_new_stream, avformat_stream_group_add_stream. + */ +AVStreamGroup *avformat_stream_group_create(AVFormatContext *s, + enum AVStreamGroupParamsType type, + AVDictionary **options); + +/** + * Add a new stream to a media file. + * + * When demuxing, it is called by the demuxer in read_header(). If the + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also + * be called in read_packet(). + * + * When muxing, should be called by the user before avformat_write_header(). + * + * User is required to call avformat_free_context() to clean up the allocation + * by avformat_new_stream(). + * + * @param s media file handle + * @param c unused, does nothing + * + * @return newly created stream or NULL on error. + */ +AVStream *avformat_new_stream(AVFormatContext *s, const struct AVCodec *c); + +/** + * Add an already allocated stream to a stream group. + * + * When demuxing, it may be called by the demuxer in read_header(). If the + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also + * be called in read_packet(). + * + * When muxing, may be called by the user before avformat_write_header() after + * having allocated a new group with avformat_stream_group_create() and stream with + * avformat_new_stream(). + * + * User is required to call avformat_free_context() to clean up the allocation + * by avformat_stream_group_add_stream(). + * + * @param stg stream group belonging to a media file. + * @param st stream in the media file to add to the group. + * + * @retval 0 success + * @retval AVERROR(EEXIST) the stream was already in the group + * @retval "another negative error code" legitimate errors + * + * @see avformat_new_stream, avformat_stream_group_create. + */ +int avformat_stream_group_add_stream(AVStreamGroup *stg, AVStream *st); + +#if FF_API_AVSTREAM_SIDE_DATA +/** + * Wrap an existing array as stream side data. + * + * @param st stream + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * st. + * @param size side information size + * + * @return zero on success, a negative AVERROR code on failure. On failure, + * the stream is unchanged and the data remains owned by the caller. + * @deprecated use av_packet_side_data_add() with the stream's + * @ref AVCodecParameters.coded_side_data "codecpar side data" + */ +attribute_deprecated +int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + +/** + * Allocate new information from stream. + * + * @param stream stream + * @param type desired side information type + * @param size side information size + * + * @return pointer to fresh allocated data or NULL otherwise + * @deprecated use av_packet_side_data_new() with the stream's + * @ref AVCodecParameters.coded_side_data "codecpar side data" + */ +attribute_deprecated +uint8_t *av_stream_new_side_data(AVStream *stream, + enum AVPacketSideDataType type, size_t size); +/** + * Get side information from stream. + * + * @param stream stream + * @param type desired side information type + * @param size If supplied, *size will be set to the size of the side data + * or to zero if the desired side data is not present. + * + * @return pointer to data if present or NULL otherwise + * @deprecated use av_packet_side_data_get() with the stream's + * @ref AVCodecParameters.coded_side_data "codecpar side data" + */ +attribute_deprecated +uint8_t *av_stream_get_side_data(const AVStream *stream, + enum AVPacketSideDataType type, size_t *size); +#endif + +AVProgram *av_new_program(AVFormatContext *s, int id); + +/** + * @} + */ + + +/** + * Allocate an AVFormatContext for an output format. + * avformat_free_context() can be used to free the context and + * everything allocated by the framework within it. + * + * @param ctx pointee is set to the created format context, + * or to NULL in case of failure + * @param oformat format to use for allocating the context, if NULL + * format_name and filename are used instead + * @param format_name the name of output format to use for allocating the + * context, if NULL filename is used instead + * @param filename the name of the filename to use for allocating the + * context, may be NULL + * + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int avformat_alloc_output_context2(AVFormatContext **ctx, const AVOutputFormat *oformat, + const char *format_name, const char *filename); + +/** + * @addtogroup lavf_decoding + * @{ + */ + +/** + * Find AVInputFormat based on the short name of the input format. + */ +const AVInputFormat *av_find_input_format(const char *short_name); + +/** + * Guess the file format. + * + * @param pd data to be probed + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + */ +const AVInputFormat *av_probe_input_format(const AVProbeData *pd, int is_opened); + +/** + * Guess the file format. + * + * @param pd data to be probed + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_max A probe score larger that this is required to accept a + * detection, the variable is set to the actual detection + * score afterwards. + * If the score is <= AVPROBE_SCORE_MAX / 4 it is recommended + * to retry with a larger probe buffer. + */ +const AVInputFormat *av_probe_input_format2(const AVProbeData *pd, + int is_opened, int *score_max); + +/** + * Guess the file format. + * + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_ret The score of the best detection. + */ +const AVInputFormat *av_probe_input_format3(const AVProbeData *pd, + int is_opened, int *score_ret); + +/** + * Probe a bytestream to determine the input format. Each time a probe returns + * with a score that is too low, the probe buffer size is increased and another + * attempt is made. When the maximum probe size is reached, the input format + * with the highest score is returned. + * + * @param pb the bytestream to probe + * @param fmt the input format is put here + * @param url the url of the stream + * @param logctx the log context + * @param offset the offset within the bytestream to probe from + * @param max_probe_size the maximum probe buffer size (zero for default) + * + * @return the score in case of success, a negative value corresponding to an + * the maximal score is AVPROBE_SCORE_MAX + * AVERROR code otherwise + */ +int av_probe_input_buffer2(AVIOContext *pb, const AVInputFormat **fmt, + const char *url, void *logctx, + unsigned int offset, unsigned int max_probe_size); + +/** + * Like av_probe_input_buffer2() but returns 0 on success + */ +int av_probe_input_buffer(AVIOContext *pb, const AVInputFormat **fmt, + const char *url, void *logctx, + unsigned int offset, unsigned int max_probe_size); + +/** + * Open an input stream and read the header. The codecs are not opened. + * The stream must be closed with avformat_close_input(). + * + * @param ps Pointer to user-supplied AVFormatContext (allocated by + * avformat_alloc_context). May be a pointer to NULL, in + * which case an AVFormatContext is allocated by this + * function and written into ps. + * Note that a user-supplied AVFormatContext will be freed + * on failure. + * @param url URL of the stream to open. + * @param fmt If non-NULL, this parameter forces a specific input format. + * Otherwise the format is autodetected. + * @param options A dictionary filled with AVFormatContext and demuxer-private + * options. + * On return this parameter will be destroyed and replaced with + * a dict containing options that were not found. May be NULL. + * + * @return 0 on success, a negative AVERROR on failure. + * + * @note If you want to use custom IO, preallocate the format context and set its pb field. + */ +int avformat_open_input(AVFormatContext **ps, const char *url, + const AVInputFormat *fmt, AVDictionary **options); + +/** + * Read packets of a media file to get stream information. This + * is useful for file formats with no headers such as MPEG. This + * function also computes the real framerate in case of MPEG-2 repeat + * frame mode. + * The logical file position is not changed by this function; + * examined packets may be buffered for later processing. + * + * @param ic media file handle + * @param options If non-NULL, an ic.nb_streams long array of pointers to + * dictionaries, where i-th member contains options for + * codec corresponding to i-th stream. + * On return each dictionary will be filled with options that were not found. + * @return >=0 if OK, AVERROR_xxx on error + * + * @note this function isn't guaranteed to open all the codecs, so + * options being non-empty at return is a perfectly normal behavior. + * + * @todo Let the user decide somehow what information is needed so that + * we do not waste time getting stuff the user does not need. + */ +int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); + +/** + * Find the programs which belong to a given stream. + * + * @param ic media file handle + * @param last the last found program, the search will start after this + * program, or from the beginning if it is NULL + * @param s stream index + * + * @return the next program which belongs to s, NULL if no program is found or + * the last program is not among the programs of ic. + */ +AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s); + +void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx); + +/** + * Find the "best" stream in the file. + * The best stream is determined according to various heuristics as the most + * likely to be what the user expects. + * If the decoder parameter is non-NULL, av_find_best_stream will find the + * default decoder for the stream's codec; streams for which no decoder can + * be found are ignored. + * + * @param ic media file handle + * @param type stream type: video, audio, subtitles, etc. + * @param wanted_stream_nb user-requested stream number, + * or -1 for automatic selection + * @param related_stream try to find a stream related (eg. in the same + * program) to this one, or -1 if none + * @param decoder_ret if non-NULL, returns the decoder for the + * selected stream + * @param flags flags; none are currently defined + * + * @return the non-negative stream number in case of success, + * AVERROR_STREAM_NOT_FOUND if no stream with the requested type + * could be found, + * AVERROR_DECODER_NOT_FOUND if streams were found but no decoder + * + * @note If av_find_best_stream returns successfully and decoder_ret is not + * NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec. + */ +int av_find_best_stream(AVFormatContext *ic, + enum AVMediaType type, + int wanted_stream_nb, + int related_stream, + const struct AVCodec **decoder_ret, + int flags); + +/** + * Return the next frame of a stream. + * This function returns what is stored in the file, and does not validate + * that what is there are valid frames for the decoder. It will split what is + * stored in the file into frames and return one for each call. It will not + * omit invalid data between valid frames so as to give the decoder the maximum + * information possible for decoding. + * + * On success, the returned packet is reference-counted (pkt->buf is set) and + * valid indefinitely. The packet must be freed with av_packet_unref() when + * it is no longer needed. For video, the packet contains exactly one frame. + * For audio, it contains an integer number of frames if each frame has + * a known fixed size (e.g. PCM or ADPCM data). If the audio frames have + * a variable size (e.g. MPEG audio), then it contains one frame. + * + * pkt->pts, pkt->dts and pkt->duration are always set to correct + * values in AVStream.time_base units (and guessed if the format cannot + * provide them). pkt->pts can be AV_NOPTS_VALUE if the video format + * has B-frames, so it is better to rely on pkt->dts if you do not + * decompress the payload. + * + * @return 0 if OK, < 0 on error or end of file. On error, pkt will be blank + * (as if it came from av_packet_alloc()). + * + * @note pkt will be initialized, so it may be uninitialized, but it must not + * contain data that needs to be freed. + */ +int av_read_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Seek to the keyframe at timestamp. + * 'timestamp' in 'stream_index'. + * + * @param s media file handle + * @param stream_index If stream_index is (-1), a default stream is selected, + * and timestamp is automatically converted from + * AV_TIME_BASE units to the stream specific time_base. + * @param timestamp Timestamp in AVStream.time_base units or, if no stream + * is specified, in AV_TIME_BASE units. + * @param flags flags which select direction and seeking mode + * + * @return >= 0 on success + */ +int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, + int flags); + +/** + * Seek to timestamp ts. + * Seeking will be done so that the point from which all active streams + * can be presented successfully will be closest to ts and within min/max_ts. + * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL. + * + * If flags contain AVSEEK_FLAG_BYTE, then all timestamps are in bytes and + * are the file position (this may not be supported by all demuxers). + * If flags contain AVSEEK_FLAG_FRAME, then all timestamps are in frames + * in the stream with stream_index (this may not be supported by all demuxers). + * Otherwise all timestamps are in units of the stream selected by stream_index + * or if stream_index is -1, in AV_TIME_BASE units. + * If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as + * keyframes (this may not be supported by all demuxers). + * If flags contain AVSEEK_FLAG_BACKWARD, it is ignored. + * + * @param s media file handle + * @param stream_index index of the stream which is used as time base reference + * @param min_ts smallest acceptable timestamp + * @param ts target timestamp + * @param max_ts largest acceptable timestamp + * @param flags flags + * @return >=0 on success, error code otherwise + * + * @note This is part of the new seek API which is still under construction. + */ +int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); + +/** + * Discard all internally buffered data. This can be useful when dealing with + * discontinuities in the byte stream. Generally works only with formats that + * can resync. This includes headerless formats like MPEG-TS/TS but should also + * work with NUT, Ogg and in a limited way AVI for example. + * + * The set of streams, the detected duration, stream parameters and codecs do + * not change when calling this function. If you want a complete reset, it's + * better to open a new AVFormatContext. + * + * This does not flush the AVIOContext (s->pb). If necessary, call + * avio_flush(s->pb) before calling this function. + * + * @param s media file handle + * @return >=0 on success, error code otherwise + */ +int avformat_flush(AVFormatContext *s); + +/** + * Start playing a network-based stream (e.g. RTSP stream) at the + * current position. + */ +int av_read_play(AVFormatContext *s); + +/** + * Pause a network-based stream (e.g. RTSP stream). + * + * Use av_read_play() to resume it. + */ +int av_read_pause(AVFormatContext *s); + +/** + * Close an opened input AVFormatContext. Free it and all its contents + * and set *s to NULL. + */ +void avformat_close_input(AVFormatContext **s); +/** + * @} + */ + +#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward +#define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes +#define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes +#define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number + +/** + * @addtogroup lavf_encoding + * @{ + */ + +#define AVSTREAM_INIT_IN_WRITE_HEADER 0 ///< stream parameters initialized in avformat_write_header +#define AVSTREAM_INIT_IN_INIT_OUTPUT 1 ///< stream parameters initialized in avformat_init_output + +/** + * Allocate the stream private data and write the stream header to + * an output media file. + * + * @param s Media file handle, must be allocated with + * avformat_alloc_context(). + * Its \ref AVFormatContext.oformat "oformat" field must be set + * to the desired output format; + * Its \ref AVFormatContext.pb "pb" field must be set to an + * already opened ::AVIOContext. + * @param options An ::AVDictionary filled with AVFormatContext and + * muxer-private options. + * On return this parameter will be destroyed and replaced with + * a dict containing options that were not found. May be NULL. + * + * @retval AVSTREAM_INIT_IN_WRITE_HEADER On success, if the codec had not already been + * fully initialized in avformat_init_output(). + * @retval AVSTREAM_INIT_IN_INIT_OUTPUT On success, if the codec had already been fully + * initialized in avformat_init_output(). + * @retval AVERROR A negative AVERROR on failure. + * + * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_init_output. + */ +av_warn_unused_result +int avformat_write_header(AVFormatContext *s, AVDictionary **options); + +/** + * Allocate the stream private data and initialize the codec, but do not write the header. + * May optionally be used before avformat_write_header() to initialize stream parameters + * before actually writing the header. + * If using this function, do not pass the same options to avformat_write_header(). + * + * @param s Media file handle, must be allocated with + * avformat_alloc_context(). + * Its \ref AVFormatContext.oformat "oformat" field must be set + * to the desired output format; + * Its \ref AVFormatContext.pb "pb" field must be set to an + * already opened ::AVIOContext. + * @param options An ::AVDictionary filled with AVFormatContext and + * muxer-private options. + * On return this parameter will be destroyed and replaced with + * a dict containing options that were not found. May be NULL. + * + * @retval AVSTREAM_INIT_IN_WRITE_HEADER On success, if the codec requires + * avformat_write_header to fully initialize. + * @retval AVSTREAM_INIT_IN_INIT_OUTPUT On success, if the codec has been fully + * initialized. + * @retval AVERROR Anegative AVERROR on failure. + * + * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_write_header. + */ +av_warn_unused_result +int avformat_init_output(AVFormatContext *s, AVDictionary **options); + +/** + * Write a packet to an output media file. + * + * This function passes the packet directly to the muxer, without any buffering + * or reordering. The caller is responsible for correctly interleaving the + * packets if the format requires it. Callers that want libavformat to handle + * the interleaving should call av_interleaved_write_frame() instead of this + * function. + * + * @param s media file handle + * @param pkt The packet containing the data to be written. Note that unlike + * av_interleaved_write_frame(), this function does not take + * ownership of the packet passed to it (though some muxers may make + * an internal reference to the input packet). + *
+ * This parameter can be NULL (at any time, not just at the end), in + * order to immediately flush data buffered within the muxer, for + * muxers that buffer up data internally before writing it to the + * output. + *
+ * Packet's @ref AVPacket.stream_index "stream_index" field must be + * set to the index of the corresponding stream in @ref + * AVFormatContext.streams "s->streams". + *
+ * The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts") + * must be set to correct values in the stream's timebase (unless the + * output format is flagged with the AVFMT_NOTIMESTAMPS flag, then + * they can be set to AV_NOPTS_VALUE). + * The dts for subsequent packets passed to this function must be strictly + * increasing when compared in their respective timebases (unless the + * output format is flagged with the AVFMT_TS_NONSTRICT, then they + * merely have to be nondecreasing). @ref AVPacket.duration + * "duration") should also be set if known. + * @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush + * + * @see av_interleaved_write_frame() + */ +int av_write_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Write a packet to an output media file ensuring correct interleaving. + * + * This function will buffer the packets internally as needed to make sure the + * packets in the output file are properly interleaved, usually ordered by + * increasing dts. Callers doing their own interleaving should call + * av_write_frame() instead of this function. + * + * Using this function instead of av_write_frame() can give muxers advance + * knowledge of future packets, improving e.g. the behaviour of the mp4 + * muxer for VFR content in fragmenting mode. + * + * @param s media file handle + * @param pkt The packet containing the data to be written. + *
+ * If the packet is reference-counted, this function will take + * ownership of this reference and unreference it later when it sees + * fit. If the packet is not reference-counted, libavformat will + * make a copy. + * The returned packet will be blank (as if returned from + * av_packet_alloc()), even on error. + *
+ * This parameter can be NULL (at any time, not just at the end), to + * flush the interleaving queues. + *
+ * Packet's @ref AVPacket.stream_index "stream_index" field must be + * set to the index of the corresponding stream in @ref + * AVFormatContext.streams "s->streams". + *
+ * The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts") + * must be set to correct values in the stream's timebase (unless the + * output format is flagged with the AVFMT_NOTIMESTAMPS flag, then + * they can be set to AV_NOPTS_VALUE). + * The dts for subsequent packets in one stream must be strictly + * increasing (unless the output format is flagged with the + * AVFMT_TS_NONSTRICT, then they merely have to be nondecreasing). + * @ref AVPacket.duration "duration" should also be set if known. + * + * @return 0 on success, a negative AVERROR on error. + * + * @see av_write_frame(), AVFormatContext.max_interleave_delta + */ +int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Write an uncoded frame to an output media file. + * + * The frame must be correctly interleaved according to the container + * specification; if not, av_interleaved_write_uncoded_frame() must be used. + * + * See av_interleaved_write_uncoded_frame() for details. + */ +int av_write_uncoded_frame(AVFormatContext *s, int stream_index, + struct AVFrame *frame); + +/** + * Write an uncoded frame to an output media file. + * + * If the muxer supports it, this function makes it possible to write an AVFrame + * structure directly, without encoding it into a packet. + * It is mostly useful for devices and similar special muxers that use raw + * video or PCM data and will not serialize it into a byte stream. + * + * To test whether it is possible to use it with a given muxer and stream, + * use av_write_uncoded_frame_query(). + * + * The caller gives up ownership of the frame and must not access it + * afterwards. + * + * @return >=0 for success, a negative code on error + */ +int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index, + struct AVFrame *frame); + +/** + * Test whether a muxer supports uncoded frame. + * + * @return >=0 if an uncoded frame can be written to that muxer and stream, + * <0 if not + */ +int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index); + +/** + * Write the stream trailer to an output media file and free the + * file private data. + * + * May only be called after a successful call to avformat_write_header. + * + * @param s media file handle + * @return 0 if OK, AVERROR_xxx on error + */ +int av_write_trailer(AVFormatContext *s); + +/** + * Return the output format in the list of registered output formats + * which best matches the provided parameters, or return NULL if + * there is no match. + * + * @param short_name if non-NULL checks if short_name matches with the + * names of the registered formats + * @param filename if non-NULL checks if filename terminates with the + * extensions of the registered formats + * @param mime_type if non-NULL checks if mime_type matches with the + * MIME type of the registered formats + */ +const AVOutputFormat *av_guess_format(const char *short_name, + const char *filename, + const char *mime_type); + +/** + * Guess the codec ID based upon muxer and filename. + */ +enum AVCodecID av_guess_codec(const AVOutputFormat *fmt, const char *short_name, + const char *filename, const char *mime_type, + enum AVMediaType type); + +/** + * Get timing information for the data currently output. + * The exact meaning of "currently output" depends on the format. + * It is mostly relevant for devices that have an internal buffer and/or + * work in real time. + * @param s media file handle + * @param stream stream in the media file + * @param[out] dts DTS of the last packet output for the stream, in stream + * time_base units + * @param[out] wall absolute time when that packet whas output, + * in microsecond + * @retval 0 Success + * @retval AVERROR(ENOSYS) The format does not support it + * + * @note Some formats or devices may not allow to measure dts and wall + * atomically. + */ +int av_get_output_timestamp(struct AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall); + + +/** + * @} + */ + + +/** + * @defgroup lavf_misc Utility functions + * @ingroup libavf + * @{ + * + * Miscellaneous utility functions related to both muxing and demuxing + * (or neither). + */ + +/** + * Send a nice hexadecimal dump of a buffer to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump_log, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump(FILE *f, const uint8_t *buf, int size); + +/** + * Send a nice hexadecimal dump of a buffer to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size); + +/** + * Send a nice dump of a packet to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st); + + +/** + * Send a nice dump of a packet to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload, + const AVStream *st); + +/** + * Get the AVCodecID for the given codec tag tag. + * If no codec id is found returns AV_CODEC_ID_NONE. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param tag codec tag to match to a codec ID + */ +enum AVCodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned int tag); + +/** + * Get the codec tag for the given codec id id. + * If no codec tag is found returns 0. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param id codec ID to match to a codec tag + */ +unsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum AVCodecID id); + +/** + * Get the codec tag for the given codec id. + * + * @param tags list of supported codec_id - codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param id codec id that should be searched for in the list + * @param tag A pointer to the found tag + * @return 0 if id was not found in tags, > 0 if it was found + */ +int av_codec_get_tag2(const struct AVCodecTag * const *tags, enum AVCodecID id, + unsigned int *tag); + +int av_find_default_stream_index(AVFormatContext *s); + +/** + * Get the index for a specific timestamp. + * + * @param st stream that the timestamp belongs to + * @param timestamp timestamp to retrieve the index for + * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond + * to the timestamp which is <= the requested one, if backward + * is 0, then it will be >= + * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise + * @return < 0 if no such timestamp could be found + */ +int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags); + +/** + * Get the index entry count for the given AVStream. + * + * @param st stream + * @return the number of index entries in the stream + */ +int avformat_index_get_entries_count(const AVStream *st); + +/** + * Get the AVIndexEntry corresponding to the given index. + * + * @param st Stream containing the requested AVIndexEntry. + * @param idx The desired index. + * @return A pointer to the requested AVIndexEntry if it exists, NULL otherwise. + * + * @note The pointer returned by this function is only guaranteed to be valid + * until any function that takes the stream or the parent AVFormatContext + * as input argument is called. + */ +const AVIndexEntry *avformat_index_get_entry(AVStream *st, int idx); + +/** + * Get the AVIndexEntry corresponding to the given timestamp. + * + * @param st Stream containing the requested AVIndexEntry. + * @param wanted_timestamp Timestamp to retrieve the index entry for. + * @param flags If AVSEEK_FLAG_BACKWARD then the returned entry will correspond + * to the timestamp which is <= the requested one, if backward + * is 0, then it will be >= + * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise. + * @return A pointer to the requested AVIndexEntry if it exists, NULL otherwise. + * + * @note The pointer returned by this function is only guaranteed to be valid + * until any function that takes the stream or the parent AVFormatContext + * as input argument is called. + */ +const AVIndexEntry *avformat_index_get_entry_from_timestamp(AVStream *st, + int64_t wanted_timestamp, + int flags); +/** + * Add an index entry into a sorted list. Update the entry if the list + * already contains it. + * + * @param timestamp timestamp in the time base of the given stream + */ +int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, + int size, int distance, int flags); + + +/** + * Split a URL string into components. + * + * The pointers to buffers for storing individual components may be null, + * in order to ignore that component. Buffers for components not found are + * set to empty strings. If the port is not found, it is set to a negative + * value. + * + * @param proto the buffer for the protocol + * @param proto_size the size of the proto buffer + * @param authorization the buffer for the authorization + * @param authorization_size the size of the authorization buffer + * @param hostname the buffer for the host name + * @param hostname_size the size of the hostname buffer + * @param port_ptr a pointer to store the port number in + * @param path the buffer for the path + * @param path_size the size of the path buffer + * @param url the URL to split + */ +void av_url_split(char *proto, int proto_size, + char *authorization, int authorization_size, + char *hostname, int hostname_size, + int *port_ptr, + char *path, int path_size, + const char *url); + + +/** + * Print detailed information about the input or output format, such as + * duration, bitrate, streams, container, programs, metadata, side data, + * codec and time base. + * + * @param ic the context to analyze + * @param index index of the stream to dump information about + * @param url the URL to print, such as source or destination file + * @param is_output Select whether the specified context is an input(0) or output(1) + */ +void av_dump_format(AVFormatContext *ic, + int index, + const char *url, + int is_output); + + +#define AV_FRAME_FILENAME_FLAGS_MULTIPLE 1 ///< Allow multiple %d + +/** + * Return in 'buf' the path with '%d' replaced by a number. + * + * Also handles the '%0nd' format where 'n' is the total number + * of digits and '%%'. + * + * @param buf destination buffer + * @param buf_size destination buffer size + * @param path numbered sequence string + * @param number frame number + * @param flags AV_FRAME_FILENAME_FLAGS_* + * @return 0 if OK, -1 on format error + */ +int av_get_frame_filename2(char *buf, int buf_size, + const char *path, int number, int flags); + +int av_get_frame_filename(char *buf, int buf_size, + const char *path, int number); + +/** + * Check whether filename actually is a numbered sequence generator. + * + * @param filename possible numbered sequence string + * @return 1 if a valid numbered sequence string, 0 otherwise + */ +int av_filename_number_test(const char *filename); + +/** + * Generate an SDP for an RTP session. + * + * Note, this overwrites the id values of AVStreams in the muxer contexts + * for getting unique dynamic payload types. + * + * @param ac array of AVFormatContexts describing the RTP streams. If the + * array is composed by only one context, such context can contain + * multiple AVStreams (one AVStream per RTP stream). Otherwise, + * all the contexts in the array (an AVCodecContext per RTP stream) + * must contain only one AVStream. + * @param n_files number of AVCodecContexts contained in ac + * @param buf buffer where the SDP will be stored (must be allocated by + * the caller) + * @param size the size of the buffer + * @return 0 if OK, AVERROR_xxx on error + */ +int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size); + +/** + * Return a positive value if the given filename has one of the given + * extensions, 0 otherwise. + * + * @param filename file name to check against the given extensions + * @param extensions a comma-separated list of filename extensions + */ +int av_match_ext(const char *filename, const char *extensions); + +/** + * Test if the given container can store a codec. + * + * @param ofmt container to check for compatibility + * @param codec_id codec to potentially store in container + * @param std_compliance standards compliance level, one of FF_COMPLIANCE_* + * + * @return 1 if codec with ID codec_id can be stored in ofmt, 0 if it cannot. + * A negative number if this information is not available. + */ +int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id, + int std_compliance); + +/** + * @defgroup riff_fourcc RIFF FourCCs + * @{ + * Get the tables mapping RIFF FourCCs to libavcodec AVCodecIDs. The tables are + * meant to be passed to av_codec_get_id()/av_codec_get_tag() as in the + * following code: + * @code + * uint32_t tag = MKTAG('H', '2', '6', '4'); + * const struct AVCodecTag *table[] = { avformat_get_riff_video_tags(), 0 }; + * enum AVCodecID id = av_codec_get_id(table, tag); + * @endcode + */ +/** + * @return the table mapping RIFF FourCCs for video to libavcodec AVCodecID. + */ +const struct AVCodecTag *avformat_get_riff_video_tags(void); +/** + * @return the table mapping RIFF FourCCs for audio to AVCodecID. + */ +const struct AVCodecTag *avformat_get_riff_audio_tags(void); +/** + * @return the table mapping MOV FourCCs for video to libavcodec AVCodecID. + */ +const struct AVCodecTag *avformat_get_mov_video_tags(void); +/** + * @return the table mapping MOV FourCCs for audio to AVCodecID. + */ +const struct AVCodecTag *avformat_get_mov_audio_tags(void); + +/** + * @} + */ + +/** + * Guess the sample aspect ratio of a frame, based on both the stream and the + * frame aspect ratio. + * + * Since the frame aspect ratio is set by the codec but the stream aspect ratio + * is set by the demuxer, these two may not be equal. This function tries to + * return the value that you should use if you would like to display the frame. + * + * Basic logic is to use the stream aspect ratio if it is set to something sane + * otherwise use the frame aspect ratio. This way a container setting, which is + * usually easy to modify can override the coded value in the frames. + * + * @param format the format context which the stream is part of + * @param stream the stream which the frame is part of + * @param frame the frame with the aspect ratio to be determined + * @return the guessed (valid) sample_aspect_ratio, 0/1 if no idea + */ +AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, + struct AVFrame *frame); + +/** + * Guess the frame rate, based on both the container and codec information. + * + * @param ctx the format context which the stream is part of + * @param stream the stream which the frame is part of + * @param frame the frame for which the frame rate should be determined, may be NULL + * @return the guessed (valid) frame rate, 0/1 if no idea + */ +AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, + struct AVFrame *frame); + +/** + * Check if the stream st contained in s is matched by the stream specifier + * spec. + * + * See the "stream specifiers" chapter in the documentation for the syntax + * of spec. + * + * @return >0 if st is matched by spec; + * 0 if st is not matched by spec; + * AVERROR code if spec is invalid + * + * @note A stream specifier can match several streams in the format. + */ +int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, + const char *spec); + +int avformat_queue_attached_pictures(AVFormatContext *s); + +enum AVTimebaseSource { + AVFMT_TBCF_AUTO = -1, + AVFMT_TBCF_DECODER, + AVFMT_TBCF_DEMUXER, +#if FF_API_R_FRAME_RATE + AVFMT_TBCF_R_FRAMERATE, +#endif +}; + +/** + * Transfer internal timing information from one stream to another. + * + * This function is useful when doing stream copy. + * + * @param ofmt target output format for ost + * @param ost output stream which needs timings copy and adjustments + * @param ist reference input stream to copy timings from + * @param copy_tb define from where the stream codec timebase needs to be imported + */ +int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, + AVStream *ost, const AVStream *ist, + enum AVTimebaseSource copy_tb); + +/** + * Get the internal codec timebase from a stream. + * + * @param st input stream to extract the timebase from + */ +AVRational av_stream_get_codec_timebase(const AVStream *st); + +/** + * @} + */ + +#endif /* AVFORMAT_AVFORMAT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavformat/avio.h b/src/framework/media/thirdparty/ffmpeg/v7/libavformat/avio.h new file mode 100644 index 0000000000000..ebf611187dcf4 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavformat/avio.h @@ -0,0 +1,831 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef AVFORMAT_AVIO_H +#define AVFORMAT_AVIO_H + +/** + * @file + * @ingroup lavf_io + * Buffered I/O operations + */ + +#include +#include + +#include "libavutil/attributes.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" + +#include "libavformat/version_major.h" + +/** + * Seeking works like for a local file. + */ +#define AVIO_SEEKABLE_NORMAL (1 << 0) + +/** + * Seeking by timestamp with avio_seek_time() is possible. + */ +#define AVIO_SEEKABLE_TIME (1 << 1) + +/** + * Callback for checking whether to abort blocking functions. + * AVERROR_EXIT is returned in this case by the interrupted + * function. During blocking operations, callback is called with + * opaque as parameter. If the callback returns 1, the + * blocking operation will be aborted. + * + * No members can be added to this struct without a major bump, if + * new elements have been added after this struct in AVFormatContext + * or AVIOContext. + */ +typedef struct AVIOInterruptCB { + int (*callback)(void*); + void *opaque; +} AVIOInterruptCB; + +/** + * Directory entry types. + */ +enum AVIODirEntryType { + AVIO_ENTRY_UNKNOWN, + AVIO_ENTRY_BLOCK_DEVICE, + AVIO_ENTRY_CHARACTER_DEVICE, + AVIO_ENTRY_DIRECTORY, + AVIO_ENTRY_NAMED_PIPE, + AVIO_ENTRY_SYMBOLIC_LINK, + AVIO_ENTRY_SOCKET, + AVIO_ENTRY_FILE, + AVIO_ENTRY_SERVER, + AVIO_ENTRY_SHARE, + AVIO_ENTRY_WORKGROUP, +}; + +/** + * Describes single entry of the directory. + * + * Only name and type fields are guaranteed be set. + * Rest of fields are protocol or/and platform dependent and might be unknown. + */ +typedef struct AVIODirEntry { + char *name; /**< Filename */ + int type; /**< Type of the entry */ + int utf8; /**< Set to 1 when name is encoded with UTF-8, 0 otherwise. + Name can be encoded with UTF-8 even though 0 is set. */ + int64_t size; /**< File size in bytes, -1 if unknown. */ + int64_t modification_timestamp; /**< Time of last modification in microseconds since unix + epoch, -1 if unknown. */ + int64_t access_timestamp; /**< Time of last access in microseconds since unix epoch, + -1 if unknown. */ + int64_t status_change_timestamp; /**< Time of last status change in microseconds since unix + epoch, -1 if unknown. */ + int64_t user_id; /**< User ID of owner, -1 if unknown. */ + int64_t group_id; /**< Group ID of owner, -1 if unknown. */ + int64_t filemode; /**< Unix file mode, -1 if unknown. */ +} AVIODirEntry; + +typedef struct AVIODirContext AVIODirContext; + +/** + * Different data types that can be returned via the AVIO + * write_data_type callback. + */ +enum AVIODataMarkerType { + /** + * Header data; this needs to be present for the stream to be decodeable. + */ + AVIO_DATA_MARKER_HEADER, + /** + * A point in the output bytestream where a decoder can start decoding + * (i.e. a keyframe). A demuxer/decoder given the data flagged with + * AVIO_DATA_MARKER_HEADER, followed by any AVIO_DATA_MARKER_SYNC_POINT, + * should give decodeable results. + */ + AVIO_DATA_MARKER_SYNC_POINT, + /** + * A point in the output bytestream where a demuxer can start parsing + * (for non self synchronizing bytestream formats). That is, any + * non-keyframe packet start point. + */ + AVIO_DATA_MARKER_BOUNDARY_POINT, + /** + * This is any, unlabelled data. It can either be a muxer not marking + * any positions at all, it can be an actual boundary/sync point + * that the muxer chooses not to mark, or a later part of a packet/fragment + * that is cut into multiple write callbacks due to limited IO buffer size. + */ + AVIO_DATA_MARKER_UNKNOWN, + /** + * Trailer data, which doesn't contain actual content, but only for + * finalizing the output file. + */ + AVIO_DATA_MARKER_TRAILER, + /** + * A point in the output bytestream where the underlying AVIOContext might + * flush the buffer depending on latency or buffering requirements. Typically + * means the end of a packet. + */ + AVIO_DATA_MARKER_FLUSH_POINT, +}; + +/** + * Bytestream IO Context. + * New public fields can be added with minor version bumps. + * Removal, reordering and changes to existing public fields require + * a major version bump. + * sizeof(AVIOContext) must not be used outside libav*. + * + * @note None of the function pointers in AVIOContext should be called + * directly, they should only be set by the client application + * when implementing custom I/O. Normally these are set to the + * function pointers specified in avio_alloc_context() + */ +typedef struct AVIOContext { + /** + * A class for private options. + * + * If this AVIOContext is created by avio_open2(), av_class is set and + * passes the options down to protocols. + * + * If this AVIOContext is manually allocated, then av_class may be set by + * the caller. + * + * warning -- this field can be NULL, be sure to not pass this AVIOContext + * to any av_opt_* functions in that case. + */ + const AVClass *av_class; + + /* + * The following shows the relationship between buffer, buf_ptr, + * buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing + * (since AVIOContext is used for both): + * + ********************************************************************************** + * READING + ********************************************************************************** + * + * | buffer_size | + * |---------------------------------------| + * | | + * + * buffer buf_ptr buf_end + * +---------------+-----------------------+ + * |/ / / / / / / /|/ / / / / / /| | + * read buffer: |/ / consumed / | to be read /| | + * |/ / / / / / / /|/ / / / / / /| | + * +---------------+-----------------------+ + * + * pos + * +-------------------------------------------+-----------------+ + * input file: | | | + * +-------------------------------------------+-----------------+ + * + * + ********************************************************************************** + * WRITING + ********************************************************************************** + * + * | buffer_size | + * |--------------------------------------| + * | | + * + * buf_ptr_max + * buffer (buf_ptr) buf_end + * +-----------------------+--------------+ + * |/ / / / / / / / / / / /| | + * write buffer: | / / to be flushed / / | | + * |/ / / / / / / / / / / /| | + * +-----------------------+--------------+ + * buf_ptr can be in this + * due to a backward seek + * + * pos + * +-------------+----------------------------------------------+ + * output file: | | | + * +-------------+----------------------------------------------+ + * + */ + unsigned char *buffer; /**< Start of the buffer. */ + int buffer_size; /**< Maximum buffer size */ + unsigned char *buf_ptr; /**< Current position in the buffer */ + unsigned char *buf_end; /**< End of the data, may be less than + buffer+buffer_size if the read function returned + less data than requested, e.g. for streams where + no more data has been received yet. */ + void *opaque; /**< A private pointer, passed to the read/write/seek/... + functions. */ + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size); + int (*write_packet)(void *opaque, const uint8_t *buf, int buf_size); + int64_t (*seek)(void *opaque, int64_t offset, int whence); + int64_t pos; /**< position in the file of the current buffer */ + int eof_reached; /**< true if was unable to read due to error or eof */ + int error; /**< contains the error code or 0 if no error happened */ + int write_flag; /**< true if open for writing */ + int max_packet_size; + int min_packet_size; /**< Try to buffer at least this amount of data + before flushing it. */ + unsigned long checksum; + unsigned char *checksum_ptr; + unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size); + /** + * Pause or resume playback for network streaming protocols - e.g. MMS. + */ + int (*read_pause)(void *opaque, int pause); + /** + * Seek to a given timestamp in stream with the specified stream_index. + * Needed for some network streaming protocols which don't support seeking + * to byte position. + */ + int64_t (*read_seek)(void *opaque, int stream_index, + int64_t timestamp, int flags); + /** + * A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable. + */ + int seekable; + + /** + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ + int direct; + + /** + * ',' separated list of allowed protocols. + */ + const char *protocol_whitelist; + + /** + * ',' separated list of disallowed protocols. + */ + const char *protocol_blacklist; + + /** + * A callback that is used instead of write_packet. + */ + int (*write_data_type)(void *opaque, const uint8_t *buf, int buf_size, + enum AVIODataMarkerType type, int64_t time); + /** + * If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT, + * but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly + * small chunks of data returned from the callback). + */ + int ignore_boundary_point; + + /** + * Maximum reached position before a backward seek in the write buffer, + * used keeping track of already written data for a later flush. + */ + unsigned char *buf_ptr_max; + + /** + * Read-only statistic of bytes read for this AVIOContext. + */ + int64_t bytes_read; + + /** + * Read-only statistic of bytes written for this AVIOContext. + */ + int64_t bytes_written; +} AVIOContext; + +/** + * Return the name of the protocol that will handle the passed URL. + * + * NULL is returned if no protocol could be found for the given URL. + * + * @return Name of the protocol or NULL. + */ +const char *avio_find_protocol_name(const char *url); + +/** + * Return AVIO_FLAG_* access flags corresponding to the access permissions + * of the resource in url, or a negative value corresponding to an + * AVERROR code in case of failure. The returned access flags are + * masked by the value in flags. + * + * @note This function is intrinsically unsafe, in the sense that the + * checked resource may change its existence or permission status from + * one call to another. Thus you should not trust the returned value, + * unless you are sure that no other processes are accessing the + * checked resource. + */ +int avio_check(const char *url, int flags); + +/** + * Open directory for reading. + * + * @param s directory read context. Pointer to a NULL pointer must be passed. + * @param url directory to be listed. + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dictionary + * containing options that were not found. May be NULL. + * @return >=0 on success or negative on error. + */ +int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options); + +/** + * Get next directory entry. + * + * Returned entry must be freed with avio_free_directory_entry(). In particular + * it may outlive AVIODirContext. + * + * @param s directory read context. + * @param[out] next next entry or NULL when no more entries. + * @return >=0 on success or negative on error. End of list is not considered an + * error. + */ +int avio_read_dir(AVIODirContext *s, AVIODirEntry **next); + +/** + * Close directory. + * + * @note Entries created using avio_read_dir() are not deleted and must be + * freeded with avio_free_directory_entry(). + * + * @param s directory read context. + * @return >=0 on success or negative on error. + */ +int avio_close_dir(AVIODirContext **s); + +/** + * Free entry allocated by avio_read_dir(). + * + * @param entry entry to be freed. + */ +void avio_free_directory_entry(AVIODirEntry **entry); + +/** + * Allocate and initialize an AVIOContext for buffered I/O. It must be later + * freed with avio_context_free(). + * + * @param buffer Memory block for input/output operations via AVIOContext. + * The buffer must be allocated with av_malloc() and friends. + * It may be freed and replaced with a new buffer by libavformat. + * AVIOContext.buffer holds the buffer currently in use, + * which must be later freed with av_free(). + * @param buffer_size The buffer size is very important for performance. + * For protocols with fixed blocksize it should be set to this blocksize. + * For others a typical size is a cache page, e.g. 4kb. + * @param write_flag Set to 1 if the buffer should be writable, 0 otherwise. + * @param opaque An opaque pointer to user-specific data. + * @param read_packet A function for refilling the buffer, may be NULL. + * For stream protocols, must never return 0 but rather + * a proper AVERROR code. + * @param write_packet A function for writing the buffer contents, may be NULL. + * The function may not change the input buffers content. + * @param seek A function for seeking to specified byte position, may be NULL. + * + * @return Allocated AVIOContext or NULL on failure. + */ +AVIOContext *avio_alloc_context( + unsigned char *buffer, + int buffer_size, + int write_flag, + void *opaque, + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), + int (*write_packet)(void *opaque, const uint8_t *buf, int buf_size), + int64_t (*seek)(void *opaque, int64_t offset, int whence)); + +/** + * Free the supplied IO context and everything associated with it. + * + * @param s Double pointer to the IO context. This function will write NULL + * into s. + */ +void avio_context_free(AVIOContext **s); + +void avio_w8(AVIOContext *s, int b); +void avio_write(AVIOContext *s, const unsigned char *buf, int size); +void avio_wl64(AVIOContext *s, uint64_t val); +void avio_wb64(AVIOContext *s, uint64_t val); +void avio_wl32(AVIOContext *s, unsigned int val); +void avio_wb32(AVIOContext *s, unsigned int val); +void avio_wl24(AVIOContext *s, unsigned int val); +void avio_wb24(AVIOContext *s, unsigned int val); +void avio_wl16(AVIOContext *s, unsigned int val); +void avio_wb16(AVIOContext *s, unsigned int val); + +/** + * Write a NULL-terminated string. + * @return number of bytes written. + */ +int avio_put_str(AVIOContext *s, const char *str); + +/** + * Convert an UTF-8 string to UTF-16LE and write it. + * @param s the AVIOContext + * @param str NULL-terminated UTF-8 string + * + * @return number of bytes written. + */ +int avio_put_str16le(AVIOContext *s, const char *str); + +/** + * Convert an UTF-8 string to UTF-16BE and write it. + * @param s the AVIOContext + * @param str NULL-terminated UTF-8 string + * + * @return number of bytes written. + */ +int avio_put_str16be(AVIOContext *s, const char *str); + +/** + * Mark the written bytestream as a specific type. + * + * Zero-length ranges are omitted from the output. + * + * @param s the AVIOContext + * @param time the stream time the current bytestream pos corresponds to + * (in AV_TIME_BASE units), or AV_NOPTS_VALUE if unknown or not + * applicable + * @param type the kind of data written starting at the current pos + */ +void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type); + +/** + * ORing this as the "whence" parameter to a seek function causes it to + * return the filesize without seeking anywhere. Supporting this is optional. + * If it is not supported then the seek function will return <0. + */ +#define AVSEEK_SIZE 0x10000 + +/** + * Passing this flag as the "whence" parameter to a seek function causes it to + * seek by any means (like reopening and linear reading) or other normally unreasonable + * means that can be extremely slow. + * This may be ignored by the seek code. + */ +#define AVSEEK_FORCE 0x20000 + +/** + * fseek() equivalent for AVIOContext. + * @return new position or AVERROR. + */ +int64_t avio_seek(AVIOContext *s, int64_t offset, int whence); + +/** + * Skip given number of bytes forward + * @return new position or AVERROR. + */ +int64_t avio_skip(AVIOContext *s, int64_t offset); + +/** + * ftell() equivalent for AVIOContext. + * @return position or AVERROR. + */ +static av_always_inline int64_t avio_tell(AVIOContext *s) +{ + return avio_seek(s, 0, SEEK_CUR); +} + +/** + * Get the filesize. + * @return filesize or AVERROR + */ +int64_t avio_size(AVIOContext *s); + +/** + * Similar to feof() but also returns nonzero on read errors. + * @return non zero if and only if at end of file or a read error happened when reading. + */ +int avio_feof(AVIOContext *s); + +/** + * Writes a formatted string to the context taking a va_list. + * @return number of bytes written, < 0 on error. + */ +int avio_vprintf(AVIOContext *s, const char *fmt, va_list ap); + +/** + * Writes a formatted string to the context. + * @return number of bytes written, < 0 on error. + */ +int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3); + +/** + * Write a NULL terminated array of strings to the context. + * Usually you don't need to use this function directly but its macro wrapper, + * avio_print. + */ +void avio_print_string_array(AVIOContext *s, const char * const strings[]); + +/** + * Write strings (const char *) to the context. + * This is a convenience macro around avio_print_string_array and it + * automatically creates the string array from the variable argument list. + * For simple string concatenations this function is more performant than using + * avio_printf since it does not need a temporary buffer. + */ +#define avio_print(s, ...) \ + avio_print_string_array(s, (const char*[]){__VA_ARGS__, NULL}) + +/** + * Force flushing of buffered data. + * + * For write streams, force the buffered data to be immediately written to the output, + * without to wait to fill the internal buffer. + * + * For read streams, discard all currently buffered data, and advance the + * reported file position to that of the underlying stream. This does not + * read new data, and does not perform any seeks. + */ +void avio_flush(AVIOContext *s); + +/** + * Read size bytes from AVIOContext into buf. + * @return number of bytes read or AVERROR + */ +int avio_read(AVIOContext *s, unsigned char *buf, int size); + +/** + * Read size bytes from AVIOContext into buf. Unlike avio_read(), this is allowed + * to read fewer bytes than requested. The missing bytes can be read in the next + * call. This always tries to read at least 1 byte. + * Useful to reduce latency in certain cases. + * @return number of bytes read or AVERROR + */ +int avio_read_partial(AVIOContext *s, unsigned char *buf, int size); + +/** + * @name Functions for reading from AVIOContext + * @{ + * + * @note return 0 if EOF, so you cannot use it if EOF handling is + * necessary + */ +int avio_r8 (AVIOContext *s); +unsigned int avio_rl16(AVIOContext *s); +unsigned int avio_rl24(AVIOContext *s); +unsigned int avio_rl32(AVIOContext *s); +uint64_t avio_rl64(AVIOContext *s); +unsigned int avio_rb16(AVIOContext *s); +unsigned int avio_rb24(AVIOContext *s); +unsigned int avio_rb32(AVIOContext *s); +uint64_t avio_rb64(AVIOContext *s); +/** + * @} + */ + +/** + * Read a string from pb into buf. The reading will terminate when either + * a NULL character was encountered, maxlen bytes have been read, or nothing + * more can be read from pb. The result is guaranteed to be NULL-terminated, it + * will be truncated if buf is too small. + * Note that the string is not interpreted or validated in any way, it + * might get truncated in the middle of a sequence for multi-byte encodings. + * + * @return number of bytes read (is always <= maxlen). + * If reading ends on EOF or error, the return value will be one more than + * bytes actually read. + */ +int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen); + +/** + * Read a UTF-16 string from pb and convert it to UTF-8. + * The reading will terminate when either a null or invalid character was + * encountered or maxlen bytes have been read. + * @return number of bytes read (is always <= maxlen) + */ +int avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen); +int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen); + + +/** + * @name URL open modes + * The flags argument to avio_open must be one of the following + * constants, optionally ORed with other flags. + * @{ + */ +#define AVIO_FLAG_READ 1 /**< read-only */ +#define AVIO_FLAG_WRITE 2 /**< write-only */ +#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE) /**< read-write pseudo flag */ +/** + * @} + */ + +/** + * Use non-blocking mode. + * If this flag is set, operations on the context will return + * AVERROR(EAGAIN) if they can not be performed immediately. + * If this flag is not set, operations on the context will never return + * AVERROR(EAGAIN). + * Note that this flag does not affect the opening/connecting of the + * context. Connecting a protocol will always block if necessary (e.g. on + * network protocols) but never hang (e.g. on busy devices). + * Warning: non-blocking protocols is work-in-progress; this flag may be + * silently ignored. + */ +#define AVIO_FLAG_NONBLOCK 8 + +/** + * Use direct mode. + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ +#define AVIO_FLAG_DIRECT 0x8000 + +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param url resource to access + * @param flags flags which control how the resource indicated by url + * is to be opened + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open(AVIOContext **s, const char *url, int flags); + +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param url resource to access + * @param flags flags which control how the resource indicated by url + * is to be opened + * @param int_cb an interrupt callback to be used at the protocols level + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dict containing options + * that were not found. May be NULL. + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open2(AVIOContext **s, const char *url, int flags, + const AVIOInterruptCB *int_cb, AVDictionary **options); + +/** + * Close the resource accessed by the AVIOContext s and free it. + * This function can only be used if s was opened by avio_open(). + * + * The internal buffer is automatically flushed before closing the + * resource. + * + * @return 0 on success, an AVERROR < 0 on error. + * @see avio_closep + */ +int avio_close(AVIOContext *s); + +/** + * Close the resource accessed by the AVIOContext *s, free it + * and set the pointer pointing to it to NULL. + * This function can only be used if s was opened by avio_open(). + * + * The internal buffer is automatically flushed before closing the + * resource. + * + * @return 0 on success, an AVERROR < 0 on error. + * @see avio_close + */ +int avio_closep(AVIOContext **s); + + +/** + * Open a write only memory stream. + * + * @param s new IO context + * @return zero if no error. + */ +int avio_open_dyn_buf(AVIOContext **s); + +/** + * Return the written size and a pointer to the buffer. + * The AVIOContext stream is left intact. + * The buffer must NOT be freed. + * No padding is added to the buffer. + * + * @param s IO context + * @param pbuffer pointer to a byte buffer + * @return the length of the byte buffer + */ +int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + +/** + * Return the written size and a pointer to the buffer. The buffer + * must be freed with av_free(). + * Padding of AV_INPUT_BUFFER_PADDING_SIZE is added to the buffer. + * + * @param s IO context + * @param pbuffer pointer to a byte buffer + * @return the length of the byte buffer + */ +int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + +/** + * Iterate through names of available protocols. + * + * @param opaque A private pointer representing current protocol. + * It must be a pointer to NULL on first iteration and will + * be updated by successive calls to avio_enum_protocols. + * @param output If set to 1, iterate over output protocols, + * otherwise over input protocols. + * + * @return A static string containing the name of current protocol or NULL + */ +const char *avio_enum_protocols(void **opaque, int output); + +/** + * Get AVClass by names of available protocols. + * + * @return A AVClass of input protocol name or NULL + */ +const AVClass *avio_protocol_get_class(const char *name); + +/** + * Pause and resume playing - only meaningful if using a network streaming + * protocol (e.g. MMS). + * + * @param h IO context from which to call the read_pause function pointer + * @param pause 1 for pause, 0 for resume + */ +int avio_pause(AVIOContext *h, int pause); + +/** + * Seek to a given timestamp relative to some component stream. + * Only meaningful if using a network streaming protocol (e.g. MMS.). + * + * @param h IO context from which to call the seek function pointers + * @param stream_index The stream index that the timestamp is relative to. + * If stream_index is (-1) the timestamp should be in AV_TIME_BASE + * units from the beginning of the presentation. + * If a stream_index >= 0 is used and the protocol does not support + * seeking based on component streams, the call will fail. + * @param timestamp timestamp in AVStream.time_base units + * or if there is no stream specified then in AV_TIME_BASE units. + * @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE + * and AVSEEK_FLAG_ANY. The protocol may silently ignore + * AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will + * fail if used and not supported. + * @return >= 0 on success + * @see AVInputFormat::read_seek + */ +int64_t avio_seek_time(AVIOContext *h, int stream_index, + int64_t timestamp, int flags); + +/* Avoid a warning. The header can not be included because it breaks c++. */ +struct AVBPrint; + +/** + * Read contents of h into print buffer, up to max_size bytes, or up to EOF. + * + * @return 0 for success (max_size bytes read or EOF reached), negative error + * code otherwise + */ +int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size); + +/** + * Accept and allocate a client context on a server context. + * @param s the server context + * @param c the client context, must be unallocated + * @return >= 0 on success or a negative value corresponding + * to an AVERROR on failure + */ +int avio_accept(AVIOContext *s, AVIOContext **c); + +/** + * Perform one step of the protocol handshake to accept a new client. + * This function must be called on a client returned by avio_accept() before + * using it as a read/write context. + * It is separate from avio_accept() because it may block. + * A step of the handshake is defined by places where the application may + * decide to change the proceedings. + * For example, on a protocol with a request header and a reply header, each + * one can constitute a step because the application may use the parameters + * from the request to change parameters in the reply; or each individual + * chunk of the request can constitute a step. + * If the handshake is already finished, avio_handshake() does nothing and + * returns 0 immediately. + * + * @param c the client context to perform the handshake on + * @return 0 on a complete and successful handshake + * > 0 if the handshake progressed, but is not complete + * < 0 for an AVERROR code + */ +int avio_handshake(AVIOContext *c); +#endif /* AVFORMAT_AVIO_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavformat/version.h b/src/framework/media/thirdparty/ffmpeg/v7/libavformat/version.h new file mode 100644 index 0000000000000..a7c80dc5647d8 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavformat/version.h @@ -0,0 +1,47 @@ +/* + * Version macros. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_VERSION_H +#define AVFORMAT_VERSION_H + +/** + * @file + * @ingroup libavf + * Libavformat version macros + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBAVFORMAT_VERSION_MINOR 1 +#define LIBAVFORMAT_VERSION_MICRO 100 + +#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT + +#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) + +#endif /* AVFORMAT_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavformat/version_major.h b/src/framework/media/thirdparty/ffmpeg/v7/libavformat/version_major.h new file mode 100644 index 0000000000000..44ad23c6b65a2 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavformat/version_major.h @@ -0,0 +1,53 @@ +/* + * Version macros. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_VERSION_MAJOR_H +#define AVFORMAT_VERSION_MAJOR_H + +/** + * @file + * @ingroup libavf + * Libavformat version macros + */ + +// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) +// Also please add any ticket numbers that you believe might be affected here +#define LIBAVFORMAT_VERSION_MAJOR 61 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + * + */ +#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 62) +#define FF_API_LAVF_SHORTEST (LIBAVFORMAT_VERSION_MAJOR < 62) +#define FF_API_ALLOW_FLUSH (LIBAVFORMAT_VERSION_MAJOR < 62) +#define FF_API_AVSTREAM_SIDE_DATA (LIBAVFORMAT_VERSION_MAJOR < 62) + +#define FF_API_GET_DUR_ESTIMATE_METHOD (LIBAVFORMAT_VERSION_MAJOR < 62) + +#define FF_API_R_FRAME_RATE 1 + +#endif /* AVFORMAT_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/attributes.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/attributes.h new file mode 100644 index 0000000000000..04c615c952c46 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/attributes.h @@ -0,0 +1,173 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Macro definitions for various function/variable attributes + */ + +#ifndef AVUTIL_ATTRIBUTES_H +#define AVUTIL_ATTRIBUTES_H + +#ifdef __GNUC__ +# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) +# define AV_GCC_VERSION_AT_MOST(x,y) (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y)) +#else +# define AV_GCC_VERSION_AT_LEAST(x,y) 0 +# define AV_GCC_VERSION_AT_MOST(x,y) 0 +#endif + +#ifdef __has_builtin +# define AV_HAS_BUILTIN(x) __has_builtin(x) +#else +# define AV_HAS_BUILTIN(x) 0 +#endif + +#ifndef av_always_inline +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_always_inline __attribute__((always_inline)) inline +#elif defined(_MSC_VER) +# define av_always_inline __forceinline +#else +# define av_always_inline inline +#endif +#endif + +#ifndef av_extern_inline +#if defined(__ICL) && __ICL >= 1210 || defined(__GNUC_STDC_INLINE__) +# define av_extern_inline extern inline +#else +# define av_extern_inline inline +#endif +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,4) +# define av_warn_unused_result __attribute__((warn_unused_result)) +#else +# define av_warn_unused_result +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_noinline __attribute__((noinline)) +#elif defined(_MSC_VER) +# define av_noinline __declspec(noinline) +#else +# define av_noinline +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) +# define av_pure __attribute__((pure)) +#else +# define av_pure +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,6) || defined(__clang__) +# define av_const __attribute__((const)) +#else +# define av_const +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,3) || defined(__clang__) +# define av_cold __attribute__((cold)) +#else +# define av_cold +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,1) && !defined(__llvm__) +# define av_flatten __attribute__((flatten)) +#else +# define av_flatten +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define attribute_deprecated __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define attribute_deprecated __declspec(deprecated) +#else +# define attribute_deprecated +#endif + +/** + * Disable warnings about deprecated features + * This is useful for sections of code kept for backward compatibility and + * scheduled for removal. + */ +#ifndef AV_NOWARN_DEPRECATED +#if AV_GCC_VERSION_AT_LEAST(4,6) || defined(__clang__) +# define AV_NOWARN_DEPRECATED(code) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \ + code \ + _Pragma("GCC diagnostic pop") +#elif defined(_MSC_VER) +# define AV_NOWARN_DEPRECATED(code) \ + __pragma(warning(push)) \ + __pragma(warning(disable : 4996)) \ + code; \ + __pragma(warning(pop)) +#else +# define AV_NOWARN_DEPRECATED(code) code +#endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define av_unused __attribute__((unused)) +#else +# define av_unused +#endif + +/** + * Mark a variable as used and prevent the compiler from optimizing it + * away. This is useful for variables accessed only from inline + * assembler without the compiler being aware. + */ +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) +# define av_used __attribute__((used)) +#else +# define av_used +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,3) || defined(__clang__) +# define av_alias __attribute__((may_alias)) +#else +# define av_alias +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__INTEL_COMPILER) +# define av_uninit(x) x=x +#else +# define av_uninit(x) x +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define av_builtin_constant_p __builtin_constant_p +# define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos))) +#else +# define av_builtin_constant_p(x) 0 +# define av_printf_format(fmtpos, attrpos) +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,5) || defined(__clang__) +# define av_noreturn __attribute__((noreturn)) +#else +# define av_noreturn +#endif + +#endif /* AVUTIL_ATTRIBUTES_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/avconfig.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/avconfig.h new file mode 100644 index 0000000000000..f13252f7d2c25 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/avconfig.h @@ -0,0 +1,24 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVCONFIG_H +#define AVUTIL_AVCONFIG_H + +#define AV_HAVE_BIGENDIAN 0 + +#endif /* AVUTIL_AVCONFIG_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/avstring.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/avstring.h new file mode 100644 index 0000000000000..fc095349d2652 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/avstring.h @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2007 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVSTRING_H +#define AVUTIL_AVSTRING_H + +#include +#include +#include "attributes.h" + +/** + * @addtogroup lavu_string + * @{ + */ + +/** + * Return non-zero if pfx is a prefix of str. If it is, *ptr is set to + * the address of the first character in str after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_strstart(const char *str, const char *pfx, const char **ptr); + +/** + * Return non-zero if pfx is a prefix of str independent of case. If + * it is, *ptr is set to the address of the first character in str + * after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_stristart(const char *str, const char *pfx, const char **ptr); + +/** + * Locate the first case-independent occurrence in the string haystack + * of the string needle. A zero-length string needle is considered to + * match at the start of haystack. + * + * This function is a case-insensitive version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_stristr(const char *haystack, const char *needle); + +/** + * Locate the first occurrence of the string needle in the string haystack + * where not more than hay_length characters are searched. A zero-length + * string needle is considered to match at the start of haystack. + * + * This function is a length-limited version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @param hay_length length of string to search in + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_strnstr(const char *haystack, const char *needle, size_t hay_length); + +/** + * Copy the string src to dst, but no more than size - 1 bytes, and + * null-terminate dst. + * + * This function is the same as BSD strlcpy(). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the length of src + * + * @warning since the return value is the length of src, src absolutely + * _must_ be a properly 0-terminated string, otherwise this will read beyond + * the end of the buffer and possibly crash. + */ +size_t av_strlcpy(char *dst, const char *src, size_t size); + +/** + * Append the string src to the string dst, but to a total length of + * no more than size - 1 bytes, and null-terminate dst. + * + * This function is similar to BSD strlcat(), but differs when + * size <= strlen(dst). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the total length of src and dst + * + * @warning since the return value use the length of src and dst, these + * absolutely _must_ be a properly 0-terminated strings, otherwise this + * will read beyond the end of the buffer and possibly crash. + */ +size_t av_strlcat(char *dst, const char *src, size_t size); + +/** + * Append output to a string, according to a format. Never write out of + * the destination buffer, and always put a terminating 0 within + * the buffer. + * @param dst destination buffer (string to which the output is + * appended) + * @param size total size of the destination buffer + * @param fmt printf-compatible format string, specifying how the + * following parameters are used + * @return the length of the string that would have been generated + * if enough space had been available + */ +size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Get the count of continuous non zero chars starting from the beginning. + * + * @param s the string whose length to count + * @param len maximum number of characters to check in the string, that + * is the maximum value which is returned by the function + */ +static inline size_t av_strnlen(const char *s, size_t len) +{ + size_t i; + for (i = 0; i < len && s[i]; i++) + ; + return i; +} + +/** + * Print arguments following specified format into a large enough auto + * allocated buffer. It is similar to GNU asprintf(). + * @param fmt printf-compatible format string, specifying how the + * following parameters are used. + * @return the allocated string + * @note You have to free the string yourself with av_free(). + */ +char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2); + +/** + * Unescape the given string until a non escaped terminating char, + * and return the token corresponding to the unescaped string. + * + * The normal \ and ' escaping is supported. Leading and trailing + * whitespaces are removed, unless they are escaped with '\' or are + * enclosed between ''. + * + * @param buf the buffer to parse, buf will be updated to point to the + * terminating char + * @param term a 0-terminated list of terminating chars + * @return the malloced unescaped string, which must be av_freed by + * the user, NULL in case of allocation failure + */ +char *av_get_token(const char **buf, const char *term); + +/** + * Split the string into several tokens which can be accessed by + * successive calls to av_strtok(). + * + * A token is defined as a sequence of characters not belonging to the + * set specified in delim. + * + * On the first call to av_strtok(), s should point to the string to + * parse, and the value of saveptr is ignored. In subsequent calls, s + * should be NULL, and saveptr should be unchanged since the previous + * call. + * + * This function is similar to strtok_r() defined in POSIX.1. + * + * @param s the string to parse, may be NULL + * @param delim 0-terminated list of token delimiters, must be non-NULL + * @param saveptr user-provided pointer which points to stored + * information necessary for av_strtok() to continue scanning the same + * string. saveptr is updated to point to the next character after the + * first delimiter found, or to NULL if the string was terminated + * @return the found token, or NULL when no token is found + */ +char *av_strtok(char *s, const char *delim, char **saveptr); + +/** + * Locale-independent conversion of ASCII isdigit. + */ +static inline av_const int av_isdigit(int c) +{ + return c >= '0' && c <= '9'; +} + +/** + * Locale-independent conversion of ASCII isgraph. + */ +static inline av_const int av_isgraph(int c) +{ + return c > 32 && c < 127; +} + +/** + * Locale-independent conversion of ASCII isspace. + */ +static inline av_const int av_isspace(int c) +{ + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || + c == '\v'; +} + +/** + * Locale-independent conversion of ASCII characters to uppercase. + */ +static inline av_const int av_toupper(int c) +{ + if (c >= 'a' && c <= 'z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII characters to lowercase. + */ +static inline av_const int av_tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII isxdigit. + */ +static inline av_const int av_isxdigit(int c) +{ + c = av_tolower(c); + return av_isdigit(c) || (c >= 'a' && c <= 'f'); +} + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strcasecmp(const char *a, const char *b); + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strncasecmp(const char *a, const char *b, size_t n); + +/** + * Locale-independent strings replace. + * @note This means only ASCII-range characters are replaced. + */ +char *av_strireplace(const char *str, const char *from, const char *to); + +/** + * Thread safe basename. + * @param path the string to parse, on DOS both \ and / are considered separators. + * @return pointer to the basename substring. + * If path does not contain a slash, the function returns a copy of path. + * If path is a NULL pointer or points to an empty string, a pointer + * to a string "." is returned. + */ +const char *av_basename(const char *path); + +/** + * Thread safe dirname. + * @param path the string to parse, on DOS both \ and / are considered separators. + * @return A pointer to a string that's the parent directory of path. + * If path is a NULL pointer or points to an empty string, a pointer + * to a string "." is returned. + * @note the function may modify the contents of the path, so copies should be passed. + */ +const char *av_dirname(char *path); + +/** + * Match instances of a name in a comma-separated list of names. + * List entries are checked from the start to the end of the names list, + * the first match ends further processing. If an entry prefixed with '-' + * matches, then 0 is returned. The "ALL" list entry is considered to + * match all names. + * + * @param name Name to look for. + * @param names List of names. + * @return 1 on match, 0 otherwise. + */ +int av_match_name(const char *name, const char *names); + +/** + * Append path component to the existing path. + * Path separator '/' is placed between when needed. + * Resulting string have to be freed with av_free(). + * @param path base path + * @param component component to be appended + * @return new path or NULL on error. + */ +char *av_append_path_component(const char *path, const char *component); + +enum AVEscapeMode { + AV_ESCAPE_MODE_AUTO, ///< Use auto-selected escaping mode. + AV_ESCAPE_MODE_BACKSLASH, ///< Use backslash escaping. + AV_ESCAPE_MODE_QUOTE, ///< Use single-quote escaping. + AV_ESCAPE_MODE_XML, ///< Use XML non-markup character data escaping. +}; + +/** + * Consider spaces special and escape them even in the middle of the + * string. + * + * This is equivalent to adding the whitespace characters to the special + * characters lists, except it is guaranteed to use the exact same list + * of whitespace characters as the rest of libavutil. + */ +#define AV_ESCAPE_FLAG_WHITESPACE (1 << 0) + +/** + * Escape only specified special characters. + * Without this flag, escape also any characters that may be considered + * special by av_get_token(), such as the single quote. + */ +#define AV_ESCAPE_FLAG_STRICT (1 << 1) + +/** + * Within AV_ESCAPE_MODE_XML, additionally escape single quotes for single + * quoted attributes. + */ +#define AV_ESCAPE_FLAG_XML_SINGLE_QUOTES (1 << 2) + +/** + * Within AV_ESCAPE_MODE_XML, additionally escape double quotes for double + * quoted attributes. + */ +#define AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES (1 << 3) + + +/** + * Escape string in src, and put the escaped string in an allocated + * string in *dst, which must be freed with av_free(). + * + * @param dst pointer where an allocated string is put + * @param src string to escape, must be non-NULL + * @param special_chars string containing the special characters which + * need to be escaped, can be NULL + * @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros. + * Any unknown value for mode will be considered equivalent to + * AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without + * notice. + * @param flags flags which control how to escape, see AV_ESCAPE_FLAG_ macros + * @return the length of the allocated string, or a negative error code in case of error + * @see av_bprint_escape() + */ +av_warn_unused_result +int av_escape(char **dst, const char *src, const char *special_chars, + enum AVEscapeMode mode, int flags); + +#define AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES 1 ///< accept codepoints over 0x10FFFF +#define AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS 2 ///< accept non-characters - 0xFFFE and 0xFFFF +#define AV_UTF8_FLAG_ACCEPT_SURROGATES 4 ///< accept UTF-16 surrogates codes +#define AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES 8 ///< exclude control codes not accepted by XML + +#define AV_UTF8_FLAG_ACCEPT_ALL \ + AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES|AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS|AV_UTF8_FLAG_ACCEPT_SURROGATES + +/** + * Read and decode a single UTF-8 code point (character) from the + * buffer in *buf, and update *buf to point to the next byte to + * decode. + * + * In case of an invalid byte sequence, the pointer will be updated to + * the next byte after the invalid sequence and the function will + * return an error code. + * + * Depending on the specified flags, the function will also fail in + * case the decoded code point does not belong to a valid range. + * + * @note For speed-relevant code a carefully implemented use of + * GET_UTF8() may be preferred. + * + * @param codep pointer used to return the parsed code in case of success. + * The value in *codep is set even in case the range check fails. + * @param bufp pointer to the address the first byte of the sequence + * to decode, updated by the function to point to the + * byte next after the decoded sequence + * @param buf_end pointer to the end of the buffer, points to the next + * byte past the last in the buffer. This is used to + * avoid buffer overreads (in case of an unfinished + * UTF-8 sequence towards the end of the buffer). + * @param flags a collection of AV_UTF8_FLAG_* flags + * @return >= 0 in case a sequence was successfully read, a negative + * value in case of invalid sequence + */ +av_warn_unused_result +int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end, + unsigned int flags); + +/** + * Check if a name is in a list. + * @returns 0 if not found, or the 1 based index where it has been found in the + * list. + */ +int av_match_list(const char *name, const char *list, char separator); + +/** + * See libc sscanf manual for more information. + * Locale-independent sscanf implementation. + */ +int av_sscanf(const char *string, const char *format, ...); + +/** + * @} + */ + +#endif /* AVUTIL_AVSTRING_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/avutil.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/avutil.h new file mode 100644 index 0000000000000..d2900dcb485f5 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/avutil.h @@ -0,0 +1,362 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVUTIL_H +#define AVUTIL_AVUTIL_H + +/** + * @file + * @ingroup lavu + * Convenience header that includes @ref lavu "libavutil"'s core. + */ + +/** + * @mainpage + * + * @section ffmpeg_intro Introduction + * + * This document describes the usage of the different libraries + * provided by FFmpeg. + * + * @li @ref libavc "libavcodec" encoding/decoding library + * @li @ref lavfi "libavfilter" graph-based frame editing library + * @li @ref libavf "libavformat" I/O and muxing/demuxing library + * @li @ref lavd "libavdevice" special devices muxing/demuxing library + * @li @ref lavu "libavutil" common utility library + * @li @ref lswr "libswresample" audio resampling, format conversion and mixing + * @li @ref lpp "libpostproc" post processing library + * @li @ref libsws "libswscale" color conversion and scaling library + * + * @section ffmpeg_versioning Versioning and compatibility + * + * Each of the FFmpeg libraries contains a version.h header, which defines a + * major, minor and micro version number with the + * LIBRARYNAME_VERSION_{MAJOR,MINOR,MICRO} macros. The major version + * number is incremented with backward incompatible changes - e.g. removing + * parts of the public API, reordering public struct members, etc. The minor + * version number is incremented for backward compatible API changes or major + * new features - e.g. adding a new public function or a new decoder. The micro + * version number is incremented for smaller changes that a calling program + * might still want to check for - e.g. changing behavior in a previously + * unspecified situation. + * + * FFmpeg guarantees backward API and ABI compatibility for each library as long + * as its major version number is unchanged. This means that no public symbols + * will be removed or renamed. Types and names of the public struct members and + * values of public macros and enums will remain the same (unless they were + * explicitly declared as not part of the public API). Documented behavior will + * not change. + * + * In other words, any correct program that works with a given FFmpeg snapshot + * should work just as well without any changes with any later snapshot with the + * same major versions. This applies to both rebuilding the program against new + * FFmpeg versions or to replacing the dynamic FFmpeg libraries that a program + * links against. + * + * However, new public symbols may be added and new members may be appended to + * public structs whose size is not part of public ABI (most public structs in + * FFmpeg). New macros and enum values may be added. Behavior in undocumented + * situations may change slightly (and be documented). All those are accompanied + * by an entry in doc/APIchanges and incrementing either the minor or micro + * version number. + */ + +/** + * @defgroup lavu libavutil + * Common code shared across all FFmpeg libraries. + * + * @note + * libavutil is designed to be modular. In most cases, in order to use the + * functions provided by one component of libavutil you must explicitly include + * the specific header containing that feature. If you are only using + * media-related components, you could simply include libavutil/avutil.h, which + * brings in most of the "core" components. + * + * @{ + * + * @defgroup lavu_crypto Crypto and Hashing + * + * @{ + * @} + * + * @defgroup lavu_math Mathematics + * @{ + * + * @} + * + * @defgroup lavu_string String Manipulation + * + * @{ + * + * @} + * + * @defgroup lavu_mem Memory Management + * + * @{ + * + * @} + * + * @defgroup lavu_data Data Structures + * @{ + * + * @} + * + * @defgroup lavu_video Video related + * + * @{ + * + * @} + * + * @defgroup lavu_audio Audio related + * + * @{ + * + * @} + * + * @defgroup lavu_error Error Codes + * + * @{ + * + * @} + * + * @defgroup lavu_log Logging Facility + * + * @{ + * + * @} + * + * @defgroup lavu_misc Other + * + * @{ + * + * @defgroup preproc_misc Preprocessor String Macros + * + * @{ + * + * @} + * + * @defgroup version_utils Library Version Macros + * + * @{ + * + * @} + */ + + +/** + * @addtogroup lavu_ver + * @{ + */ + +/** + * Return the LIBAVUTIL_VERSION_INT constant. + */ +unsigned avutil_version(void); + +/** + * Return an informative version string. This usually is the actual release + * version number or a git commit description. This string has no fixed format + * and can change any time. It should never be parsed by code. + */ +const char *av_version_info(void); + +/** + * Return the libavutil build-time configuration. + */ +const char *avutil_configuration(void); + +/** + * Return the libavutil license. + */ +const char *avutil_license(void); + +/** + * @} + */ + +/** + * @addtogroup lavu_media Media Type + * @brief Media Type + */ + +enum AVMediaType { + AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA + AVMEDIA_TYPE_VIDEO, + AVMEDIA_TYPE_AUDIO, + AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous + AVMEDIA_TYPE_SUBTITLE, + AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse + AVMEDIA_TYPE_NB +}; + +/** + * Return a string describing the media_type enum, NULL if media_type + * is unknown. + */ +const char *av_get_media_type_string(enum AVMediaType media_type); + +/** + * @defgroup lavu_const Constants + * @{ + * + * @defgroup lavu_enc Encoding specific + * + * @note those definition should move to avcodec + * @{ + */ + +#define FF_LAMBDA_SHIFT 7 +#define FF_LAMBDA_SCALE (1< +#include + +/** + * @defgroup lavu_buffer AVBuffer + * @ingroup lavu_data + * + * @{ + * AVBuffer is an API for reference-counted data buffers. + * + * There are two core objects in this API -- AVBuffer and AVBufferRef. AVBuffer + * represents the data buffer itself; it is opaque and not meant to be accessed + * by the caller directly, but only through AVBufferRef. However, the caller may + * e.g. compare two AVBuffer pointers to check whether two different references + * are describing the same data buffer. AVBufferRef represents a single + * reference to an AVBuffer and it is the object that may be manipulated by the + * caller directly. + * + * There are two functions provided for creating a new AVBuffer with a single + * reference -- av_buffer_alloc() to just allocate a new buffer, and + * av_buffer_create() to wrap an existing array in an AVBuffer. From an existing + * reference, additional references may be created with av_buffer_ref(). + * Use av_buffer_unref() to free a reference (this will automatically free the + * data once all the references are freed). + * + * The convention throughout this API and the rest of FFmpeg is such that the + * buffer is considered writable if there exists only one reference to it (and + * it has not been marked as read-only). The av_buffer_is_writable() function is + * provided to check whether this is true and av_buffer_make_writable() will + * automatically create a new writable buffer when necessary. + * Of course nothing prevents the calling code from violating this convention, + * however that is safe only when all the existing references are under its + * control. + * + * @note Referencing and unreferencing the buffers is thread-safe and thus + * may be done from multiple threads simultaneously without any need for + * additional locking. + * + * @note Two different references to the same buffer can point to different + * parts of the buffer (i.e. their AVBufferRef.data will not be equal). + */ + +/** + * A reference counted buffer type. It is opaque and is meant to be used through + * references (AVBufferRef). + */ +typedef struct AVBuffer AVBuffer; + +/** + * A reference to a data buffer. + * + * The size of this struct is not a part of the public ABI and it is not meant + * to be allocated directly. + */ +typedef struct AVBufferRef { + AVBuffer *buffer; + + /** + * The data buffer. It is considered writable if and only if + * this is the only reference to the buffer, in which case + * av_buffer_is_writable() returns 1. + */ + uint8_t *data; + /** + * Size of data in bytes. + */ + size_t size; +} AVBufferRef; + +/** + * Allocate an AVBuffer of the given size using av_malloc(). + * + * @return an AVBufferRef of given size or NULL when out of memory + */ +AVBufferRef *av_buffer_alloc(size_t size); + +/** + * Same as av_buffer_alloc(), except the returned buffer will be initialized + * to zero. + */ +AVBufferRef *av_buffer_allocz(size_t size); + +/** + * Always treat the buffer as read-only, even when it has only one + * reference. + */ +#define AV_BUFFER_FLAG_READONLY (1 << 0) + +/** + * Create an AVBuffer from an existing array. + * + * If this function is successful, data is owned by the AVBuffer. The caller may + * only access data through the returned AVBufferRef and references derived from + * it. + * If this function fails, data is left untouched. + * @param data data array + * @param size size of data in bytes + * @param free a callback for freeing this buffer's data + * @param opaque parameter to be got for processing or passed to free + * @param flags a combination of AV_BUFFER_FLAG_* + * + * @return an AVBufferRef referring to data on success, NULL on failure. + */ +AVBufferRef *av_buffer_create(uint8_t *data, size_t size, + void (*free)(void *opaque, uint8_t *data), + void *opaque, int flags); + +/** + * Default free callback, which calls av_free() on the buffer data. + * This function is meant to be passed to av_buffer_create(), not called + * directly. + */ +void av_buffer_default_free(void *opaque, uint8_t *data); + +/** + * Create a new reference to an AVBuffer. + * + * @return a new AVBufferRef referring to the same AVBuffer as buf or NULL on + * failure. + */ +AVBufferRef *av_buffer_ref(const AVBufferRef *buf); + +/** + * Free a given reference and automatically free the buffer if there are no more + * references to it. + * + * @param buf the reference to be freed. The pointer is set to NULL on return. + */ +void av_buffer_unref(AVBufferRef **buf); + +/** + * @return 1 if the caller may write to the data referred to by buf (which is + * true if and only if buf is the only reference to the underlying AVBuffer). + * Return 0 otherwise. + * A positive answer is valid until av_buffer_ref() is called on buf. + */ +int av_buffer_is_writable(const AVBufferRef *buf); + +/** + * @return the opaque parameter set by av_buffer_create. + */ +void *av_buffer_get_opaque(const AVBufferRef *buf); + +int av_buffer_get_ref_count(const AVBufferRef *buf); + +/** + * Create a writable reference from a given buffer reference, avoiding data copy + * if possible. + * + * @param buf buffer reference to make writable. On success, buf is either left + * untouched, or it is unreferenced and a new writable AVBufferRef is + * written in its place. On failure, buf is left untouched. + * @return 0 on success, a negative AVERROR on failure. + */ +int av_buffer_make_writable(AVBufferRef **buf); + +/** + * Reallocate a given buffer. + * + * @param buf a buffer reference to reallocate. On success, buf will be + * unreferenced and a new reference with the required size will be + * written in its place. On failure buf will be left untouched. *buf + * may be NULL, then a new buffer is allocated. + * @param size required new buffer size. + * @return 0 on success, a negative AVERROR on failure. + * + * @note the buffer is actually reallocated with av_realloc() only if it was + * initially allocated through av_buffer_realloc(NULL) and there is only one + * reference to it (i.e. the one passed to this function). In all other cases + * a new buffer is allocated and the data is copied. + */ +int av_buffer_realloc(AVBufferRef **buf, size_t size); + +/** + * Ensure dst refers to the same data as src. + * + * When *dst is already equivalent to src, do nothing. Otherwise unreference dst + * and replace it with a new reference to src. + * + * @param dst Pointer to either a valid buffer reference or NULL. On success, + * this will point to a buffer reference equivalent to src. On + * failure, dst will be left untouched. + * @param src A buffer reference to replace dst with. May be NULL, then this + * function is equivalent to av_buffer_unref(dst). + * @return 0 on success + * AVERROR(ENOMEM) on memory allocation failure. + */ +int av_buffer_replace(AVBufferRef **dst, const AVBufferRef *src); + +/** + * @} + */ + +/** + * @defgroup lavu_bufferpool AVBufferPool + * @ingroup lavu_data + * + * @{ + * AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers. + * + * Frequently allocating and freeing large buffers may be slow. AVBufferPool is + * meant to solve this in cases when the caller needs a set of buffers of the + * same size (the most obvious use case being buffers for raw video or audio + * frames). + * + * At the beginning, the user must call av_buffer_pool_init() to create the + * buffer pool. Then whenever a buffer is needed, call av_buffer_pool_get() to + * get a reference to a new buffer, similar to av_buffer_alloc(). This new + * reference works in all aspects the same way as the one created by + * av_buffer_alloc(). However, when the last reference to this buffer is + * unreferenced, it is returned to the pool instead of being freed and will be + * reused for subsequent av_buffer_pool_get() calls. + * + * When the caller is done with the pool and no longer needs to allocate any new + * buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable. + * Once all the buffers are released, it will automatically be freed. + * + * Allocating and releasing buffers with this API is thread-safe as long as + * either the default alloc callback is used, or the user-supplied one is + * thread-safe. + */ + +/** + * The buffer pool. This structure is opaque and not meant to be accessed + * directly. It is allocated with av_buffer_pool_init() and freed with + * av_buffer_pool_uninit(). + */ +typedef struct AVBufferPool AVBufferPool; + +/** + * Allocate and initialize a buffer pool. + * + * @param size size of each buffer in this pool + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be used + * (av_buffer_alloc()). + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init(size_t size, AVBufferRef* (*alloc)(size_t size)); + +/** + * Allocate and initialize a buffer pool with a more complex allocator. + * + * @param size size of each buffer in this pool + * @param opaque arbitrary user data used by the allocator + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be + * used (av_buffer_alloc()). + * @param pool_free a function that will be called immediately before the pool + * is freed. I.e. after av_buffer_pool_uninit() is called + * by the caller and all the frames are returned to the pool + * and freed. It is intended to uninitialize the user opaque + * data. May be NULL. + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init2(size_t size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, size_t size), + void (*pool_free)(void *opaque)); + +/** + * Mark the pool as being available for freeing. It will actually be freed only + * once all the allocated buffers associated with the pool are released. Thus it + * is safe to call this function while some of the allocated buffers are still + * in use. + * + * @param pool pointer to the pool to be freed. It will be set to NULL. + */ +void av_buffer_pool_uninit(AVBufferPool **pool); + +/** + * Allocate a new AVBuffer, reusing an old buffer from the pool when available. + * This function may be called simultaneously from multiple threads. + * + * @return a reference to the new buffer on success, NULL on error. + */ +AVBufferRef *av_buffer_pool_get(AVBufferPool *pool); + +/** + * Query the original opaque parameter of an allocated buffer in the pool. + * + * @param ref a buffer reference to a buffer returned by av_buffer_pool_get. + * @return the opaque parameter set by the buffer allocator function of the + * buffer pool. + * + * @note the opaque parameter of ref is used by the buffer pool implementation, + * therefore you have to use this function to access the original opaque + * parameter of an allocated buffer. + */ +void *av_buffer_pool_buffer_get_opaque(const AVBufferRef *ref); + +/** + * @} + */ + +#endif /* AVUTIL_BUFFER_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/channel_layout.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/channel_layout.h new file mode 100644 index 0000000000000..8a078d160198c --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/channel_layout.h @@ -0,0 +1,733 @@ +/* + * Copyright (c) 2006 Michael Niedermayer + * Copyright (c) 2008 Peter Ross + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_CHANNEL_LAYOUT_H +#define AVUTIL_CHANNEL_LAYOUT_H + +#include +#include + +#include "version.h" +#include "attributes.h" + +/** + * @file + * @ingroup lavu_audio_channels + * Public libavutil channel layout APIs header. + */ + + +/** + * @defgroup lavu_audio_channels Audio channels + * @ingroup lavu_audio + * + * Audio channel layout utility functions + * + * @{ + */ + +enum AVChannel { + ///< Invalid channel index + AV_CHAN_NONE = -1, + AV_CHAN_FRONT_LEFT, + AV_CHAN_FRONT_RIGHT, + AV_CHAN_FRONT_CENTER, + AV_CHAN_LOW_FREQUENCY, + AV_CHAN_BACK_LEFT, + AV_CHAN_BACK_RIGHT, + AV_CHAN_FRONT_LEFT_OF_CENTER, + AV_CHAN_FRONT_RIGHT_OF_CENTER, + AV_CHAN_BACK_CENTER, + AV_CHAN_SIDE_LEFT, + AV_CHAN_SIDE_RIGHT, + AV_CHAN_TOP_CENTER, + AV_CHAN_TOP_FRONT_LEFT, + AV_CHAN_TOP_FRONT_CENTER, + AV_CHAN_TOP_FRONT_RIGHT, + AV_CHAN_TOP_BACK_LEFT, + AV_CHAN_TOP_BACK_CENTER, + AV_CHAN_TOP_BACK_RIGHT, + /** Stereo downmix. */ + AV_CHAN_STEREO_LEFT = 29, + /** See above. */ + AV_CHAN_STEREO_RIGHT, + AV_CHAN_WIDE_LEFT, + AV_CHAN_WIDE_RIGHT, + AV_CHAN_SURROUND_DIRECT_LEFT, + AV_CHAN_SURROUND_DIRECT_RIGHT, + AV_CHAN_LOW_FREQUENCY_2, + AV_CHAN_TOP_SIDE_LEFT, + AV_CHAN_TOP_SIDE_RIGHT, + AV_CHAN_BOTTOM_FRONT_CENTER, + AV_CHAN_BOTTOM_FRONT_LEFT, + AV_CHAN_BOTTOM_FRONT_RIGHT, + + /** Channel is empty can be safely skipped. */ + AV_CHAN_UNUSED = 0x200, + + /** Channel contains data, but its position is unknown. */ + AV_CHAN_UNKNOWN = 0x300, + + /** + * Range of channels between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END represent Ambisonic components using the ACN system. + * + * Given a channel id `` between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END (inclusive), the ACN index of the channel `` is + * ` = - AV_CHAN_AMBISONIC_BASE`. + * + * @note these values are only used for AV_CHANNEL_ORDER_CUSTOM channel + * orderings, the AV_CHANNEL_ORDER_AMBISONIC ordering orders the channels + * implicitly by their position in the stream. + */ + AV_CHAN_AMBISONIC_BASE = 0x400, + // leave space for 1024 ids, which correspond to maximum order-32 harmonics, + // which should be enough for the foreseeable use cases + AV_CHAN_AMBISONIC_END = 0x7ff, +}; + +enum AVChannelOrder { + /** + * Only the channel count is specified, without any further information + * about the channel order. + */ + AV_CHANNEL_ORDER_UNSPEC, + /** + * The native channel order, i.e. the channels are in the same order in + * which they are defined in the AVChannel enum. This supports up to 63 + * different channels. + */ + AV_CHANNEL_ORDER_NATIVE, + /** + * The channel order does not correspond to any other predefined order and + * is stored as an explicit map. For example, this could be used to support + * layouts with 64 or more channels, or with empty/skipped (AV_CHAN_UNUSED) + * channels at arbitrary positions. + */ + AV_CHANNEL_ORDER_CUSTOM, + /** + * The audio is represented as the decomposition of the sound field into + * spherical harmonics. Each channel corresponds to a single expansion + * component. Channels are ordered according to ACN (Ambisonic Channel + * Number). + * + * The channel with the index n in the stream contains the spherical + * harmonic of degree l and order m given by + * @code{.unparsed} + * l = floor(sqrt(n)), + * m = n - l * (l + 1). + * @endcode + * + * Conversely given a spherical harmonic of degree l and order m, the + * corresponding channel index n is given by + * @code{.unparsed} + * n = l * (l + 1) + m. + * @endcode + * + * Normalization is assumed to be SN3D (Schmidt Semi-Normalization) + * as defined in AmbiX format $ 2.1. + */ + AV_CHANNEL_ORDER_AMBISONIC, + /** + * Number of channel orders, not part of ABI/API + */ + FF_CHANNEL_ORDER_NB +}; + + +/** + * @defgroup channel_masks Audio channel masks + * + * A channel layout is a 64-bits integer with a bit set for every channel. + * The number of bits set must be equal to the number of channels. + * The value 0 means that the channel layout is not known. + * @note this data structure is not powerful enough to handle channels + * combinations that have the same channel multiple times, such as + * dual-mono. + * + * @{ + */ +#define AV_CH_FRONT_LEFT (1ULL << AV_CHAN_FRONT_LEFT ) +#define AV_CH_FRONT_RIGHT (1ULL << AV_CHAN_FRONT_RIGHT ) +#define AV_CH_FRONT_CENTER (1ULL << AV_CHAN_FRONT_CENTER ) +#define AV_CH_LOW_FREQUENCY (1ULL << AV_CHAN_LOW_FREQUENCY ) +#define AV_CH_BACK_LEFT (1ULL << AV_CHAN_BACK_LEFT ) +#define AV_CH_BACK_RIGHT (1ULL << AV_CHAN_BACK_RIGHT ) +#define AV_CH_FRONT_LEFT_OF_CENTER (1ULL << AV_CHAN_FRONT_LEFT_OF_CENTER ) +#define AV_CH_FRONT_RIGHT_OF_CENTER (1ULL << AV_CHAN_FRONT_RIGHT_OF_CENTER) +#define AV_CH_BACK_CENTER (1ULL << AV_CHAN_BACK_CENTER ) +#define AV_CH_SIDE_LEFT (1ULL << AV_CHAN_SIDE_LEFT ) +#define AV_CH_SIDE_RIGHT (1ULL << AV_CHAN_SIDE_RIGHT ) +#define AV_CH_TOP_CENTER (1ULL << AV_CHAN_TOP_CENTER ) +#define AV_CH_TOP_FRONT_LEFT (1ULL << AV_CHAN_TOP_FRONT_LEFT ) +#define AV_CH_TOP_FRONT_CENTER (1ULL << AV_CHAN_TOP_FRONT_CENTER ) +#define AV_CH_TOP_FRONT_RIGHT (1ULL << AV_CHAN_TOP_FRONT_RIGHT ) +#define AV_CH_TOP_BACK_LEFT (1ULL << AV_CHAN_TOP_BACK_LEFT ) +#define AV_CH_TOP_BACK_CENTER (1ULL << AV_CHAN_TOP_BACK_CENTER ) +#define AV_CH_TOP_BACK_RIGHT (1ULL << AV_CHAN_TOP_BACK_RIGHT ) +#define AV_CH_STEREO_LEFT (1ULL << AV_CHAN_STEREO_LEFT ) +#define AV_CH_STEREO_RIGHT (1ULL << AV_CHAN_STEREO_RIGHT ) +#define AV_CH_WIDE_LEFT (1ULL << AV_CHAN_WIDE_LEFT ) +#define AV_CH_WIDE_RIGHT (1ULL << AV_CHAN_WIDE_RIGHT ) +#define AV_CH_SURROUND_DIRECT_LEFT (1ULL << AV_CHAN_SURROUND_DIRECT_LEFT ) +#define AV_CH_SURROUND_DIRECT_RIGHT (1ULL << AV_CHAN_SURROUND_DIRECT_RIGHT) +#define AV_CH_LOW_FREQUENCY_2 (1ULL << AV_CHAN_LOW_FREQUENCY_2 ) +#define AV_CH_TOP_SIDE_LEFT (1ULL << AV_CHAN_TOP_SIDE_LEFT ) +#define AV_CH_TOP_SIDE_RIGHT (1ULL << AV_CHAN_TOP_SIDE_RIGHT ) +#define AV_CH_BOTTOM_FRONT_CENTER (1ULL << AV_CHAN_BOTTOM_FRONT_CENTER ) +#define AV_CH_BOTTOM_FRONT_LEFT (1ULL << AV_CHAN_BOTTOM_FRONT_LEFT ) +#define AV_CH_BOTTOM_FRONT_RIGHT (1ULL << AV_CHAN_BOTTOM_FRONT_RIGHT ) + +/** + * @} + * @defgroup channel_mask_c Audio channel layouts + * @{ + * */ +#define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT) +#define AV_CH_LAYOUT_2POINT1 (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_3POINT1 (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_4POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_4POINT1 (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_2 (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_QUAD (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_5POINT0_BACK (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT1_BACK (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_6POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT0_FRONT (AV_CH_LAYOUT_2_2|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_HEXAGONAL (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_3POINT1POINT2 (AV_CH_LAYOUT_3POINT1|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_6POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_FRONT (AV_CH_LAYOUT_6POINT0_FRONT|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_7POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT0_FRONT (AV_CH_LAYOUT_5POINT0|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1_WIDE_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_5POINT1POINT2_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_CUBE (AV_CH_LAYOUT_QUAD|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT1POINT4_BACK (AV_CH_LAYOUT_5POINT1POINT2_BACK|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT1POINT2 (AV_CH_LAYOUT_7POINT1|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_7POINT1POINT4_BACK (AV_CH_LAYOUT_7POINT1POINT2|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT2POINT3 (AV_CH_LAYOUT_7POINT1POINT2|AV_CH_TOP_BACK_CENTER|AV_CH_LOW_FREQUENCY_2) +#define AV_CH_LAYOUT_9POINT1POINT4_BACK (AV_CH_LAYOUT_7POINT1POINT4_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_HEXADECAGONAL (AV_CH_LAYOUT_OCTAGONAL|AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT) +#define AV_CH_LAYOUT_22POINT2 (AV_CH_LAYOUT_7POINT1POINT4_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER|AV_CH_BACK_CENTER|AV_CH_LOW_FREQUENCY_2|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_CENTER|AV_CH_TOP_SIDE_LEFT|AV_CH_TOP_SIDE_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_BOTTOM_FRONT_CENTER|AV_CH_BOTTOM_FRONT_LEFT|AV_CH_BOTTOM_FRONT_RIGHT) + +#define AV_CH_LAYOUT_7POINT1_TOP_BACK AV_CH_LAYOUT_5POINT1POINT2_BACK + +enum AVMatrixEncoding { + AV_MATRIX_ENCODING_NONE, + AV_MATRIX_ENCODING_DOLBY, + AV_MATRIX_ENCODING_DPLII, + AV_MATRIX_ENCODING_DPLIIX, + AV_MATRIX_ENCODING_DPLIIZ, + AV_MATRIX_ENCODING_DOLBYEX, + AV_MATRIX_ENCODING_DOLBYHEADPHONE, + AV_MATRIX_ENCODING_NB +}; + +/** + * @} + */ + +/** + * An AVChannelCustom defines a single channel within a custom order layout + * + * Unlike most structures in FFmpeg, sizeof(AVChannelCustom) is a part of the + * public ABI. + * + * No new fields may be added to it without a major version bump. + */ +typedef struct AVChannelCustom { + enum AVChannel id; + char name[16]; + void *opaque; +} AVChannelCustom; + +/** + * An AVChannelLayout holds information about the channel layout of audio data. + * + * A channel layout here is defined as a set of channels ordered in a specific + * way (unless the channel order is AV_CHANNEL_ORDER_UNSPEC, in which case an + * AVChannelLayout carries only the channel count). + * All orders may be treated as if they were AV_CHANNEL_ORDER_UNSPEC by + * ignoring everything but the channel count, as long as av_channel_layout_check() + * considers they are valid. + * + * Unlike most structures in FFmpeg, sizeof(AVChannelLayout) is a part of the + * public ABI and may be used by the caller. E.g. it may be allocated on stack + * or embedded in caller-defined structs. + * + * AVChannelLayout can be initialized as follows: + * - default initialization with {0}, followed by setting all used fields + * correctly; + * - by assigning one of the predefined AV_CHANNEL_LAYOUT_* initializers; + * - with a constructor function, such as av_channel_layout_default(), + * av_channel_layout_from_mask() or av_channel_layout_from_string(). + * + * The channel layout must be unitialized with av_channel_layout_uninit() + * + * Copying an AVChannelLayout via assigning is forbidden, + * av_channel_layout_copy() must be used instead (and its return value should + * be checked) + * + * No new fields may be added to it without a major version bump, except for + * new elements of the union fitting in sizeof(uint64_t). + */ +typedef struct AVChannelLayout { + /** + * Channel order used in this layout. + * This is a mandatory field. + */ + enum AVChannelOrder order; + + /** + * Number of channels in this layout. Mandatory field. + */ + int nb_channels; + + /** + * Details about which channels are present in this layout. + * For AV_CHANNEL_ORDER_UNSPEC, this field is undefined and must not be + * used. + */ + union { + /** + * This member must be used for AV_CHANNEL_ORDER_NATIVE, and may be used + * for AV_CHANNEL_ORDER_AMBISONIC to signal non-diegetic channels. + * It is a bitmask, where the position of each set bit means that the + * AVChannel with the corresponding value is present. + * + * I.e. when (mask & (1 << AV_CHAN_FOO)) is non-zero, then AV_CHAN_FOO + * is present in the layout. Otherwise it is not present. + * + * @note when a channel layout using a bitmask is constructed or + * modified manually (i.e. not using any of the av_channel_layout_* + * functions), the code doing it must ensure that the number of set bits + * is equal to nb_channels. + */ + uint64_t mask; + /** + * This member must be used when the channel order is + * AV_CHANNEL_ORDER_CUSTOM. It is a nb_channels-sized array, with each + * element signalling the presence of the AVChannel with the + * corresponding value in map[i].id. + * + * I.e. when map[i].id is equal to AV_CHAN_FOO, then AV_CH_FOO is the + * i-th channel in the audio data. + * + * When map[i].id is in the range between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END (inclusive), the channel contains an ambisonic + * component with ACN index (as defined above) + * n = map[i].id - AV_CHAN_AMBISONIC_BASE. + * + * map[i].name may be filled with a 0-terminated string, in which case + * it will be used for the purpose of identifying the channel with the + * convenience functions below. Otherise it must be zeroed. + */ + AVChannelCustom *map; + } u; + + /** + * For some private data of the user. + */ + void *opaque; +} AVChannelLayout; + +/** + * Macro to define native channel layouts + * + * @note This doesn't use designated initializers for compatibility with C++ 17 and older. + */ +#define AV_CHANNEL_LAYOUT_MASK(nb, m) \ + { /* .order */ AV_CHANNEL_ORDER_NATIVE, \ + /* .nb_channels */ (nb), \ + /* .u.mask */ { m }, \ + /* .opaque */ NULL } + +/** + * @name Common pre-defined channel layouts + * @{ + */ +#define AV_CHANNEL_LAYOUT_MONO AV_CHANNEL_LAYOUT_MASK(1, AV_CH_LAYOUT_MONO) +#define AV_CHANNEL_LAYOUT_STEREO AV_CHANNEL_LAYOUT_MASK(2, AV_CH_LAYOUT_STEREO) +#define AV_CHANNEL_LAYOUT_2POINT1 AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_2POINT1) +#define AV_CHANNEL_LAYOUT_2_1 AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_2_1) +#define AV_CHANNEL_LAYOUT_SURROUND AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_SURROUND) +#define AV_CHANNEL_LAYOUT_3POINT1 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_3POINT1) +#define AV_CHANNEL_LAYOUT_4POINT0 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_4POINT0) +#define AV_CHANNEL_LAYOUT_4POINT1 AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_4POINT1) +#define AV_CHANNEL_LAYOUT_2_2 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_2_2) +#define AV_CHANNEL_LAYOUT_QUAD AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_QUAD) +#define AV_CHANNEL_LAYOUT_5POINT0 AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_5POINT0) +#define AV_CHANNEL_LAYOUT_5POINT1 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_5POINT1) +#define AV_CHANNEL_LAYOUT_5POINT0_BACK AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_5POINT0_BACK) +#define AV_CHANNEL_LAYOUT_5POINT1_BACK AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_5POINT1_BACK) +#define AV_CHANNEL_LAYOUT_6POINT0 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_6POINT0) +#define AV_CHANNEL_LAYOUT_6POINT0_FRONT AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_6POINT0_FRONT) +#define AV_CHANNEL_LAYOUT_3POINT1POINT2 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_3POINT1POINT2) +#define AV_CHANNEL_LAYOUT_HEXAGONAL AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_HEXAGONAL) +#define AV_CHANNEL_LAYOUT_6POINT1 AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1) +#define AV_CHANNEL_LAYOUT_6POINT1_BACK AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1_BACK) +#define AV_CHANNEL_LAYOUT_6POINT1_FRONT AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1_FRONT) +#define AV_CHANNEL_LAYOUT_7POINT0 AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_7POINT0) +#define AV_CHANNEL_LAYOUT_7POINT0_FRONT AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_7POINT0_FRONT) +#define AV_CHANNEL_LAYOUT_7POINT1 AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1) +#define AV_CHANNEL_LAYOUT_7POINT1_WIDE AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1_WIDE) +#define AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1_WIDE_BACK) +#define AV_CHANNEL_LAYOUT_5POINT1POINT2_BACK AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_5POINT1POINT2_BACK) +#define AV_CHANNEL_LAYOUT_OCTAGONAL AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_OCTAGONAL) +#define AV_CHANNEL_LAYOUT_CUBE AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_CUBE) +#define AV_CHANNEL_LAYOUT_5POINT1POINT4_BACK AV_CHANNEL_LAYOUT_MASK(10, AV_CH_LAYOUT_5POINT1POINT4_BACK) +#define AV_CHANNEL_LAYOUT_7POINT1POINT2 AV_CHANNEL_LAYOUT_MASK(10, AV_CH_LAYOUT_7POINT1POINT2) +#define AV_CHANNEL_LAYOUT_7POINT1POINT4_BACK AV_CHANNEL_LAYOUT_MASK(12, AV_CH_LAYOUT_7POINT1POINT4_BACK) +#define AV_CHANNEL_LAYOUT_7POINT2POINT3 AV_CHANNEL_LAYOUT_MASK(12, AV_CH_LAYOUT_7POINT2POINT3) +#define AV_CHANNEL_LAYOUT_9POINT1POINT4_BACK AV_CHANNEL_LAYOUT_MASK(14, AV_CH_LAYOUT_9POINT1POINT4_BACK) +#define AV_CHANNEL_LAYOUT_HEXADECAGONAL AV_CHANNEL_LAYOUT_MASK(16, AV_CH_LAYOUT_HEXADECAGONAL) +#define AV_CHANNEL_LAYOUT_STEREO_DOWNMIX AV_CHANNEL_LAYOUT_MASK(2, AV_CH_LAYOUT_STEREO_DOWNMIX) +#define AV_CHANNEL_LAYOUT_22POINT2 AV_CHANNEL_LAYOUT_MASK(24, AV_CH_LAYOUT_22POINT2) + +#define AV_CHANNEL_LAYOUT_7POINT1_TOP_BACK AV_CHANNEL_LAYOUT_5POINT1POINT2_BACK + +#define AV_CHANNEL_LAYOUT_AMBISONIC_FIRST_ORDER \ + { /* .order */ AV_CHANNEL_ORDER_AMBISONIC, \ + /* .nb_channels */ 4, \ + /* .u.mask */ { 0 }, \ + /* .opaque */ NULL } +/** @} */ + +struct AVBPrint; + +/** + * Get a human readable string in an abbreviated form describing a given channel. + * This is the inverse function of @ref av_channel_from_string(). + * + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @param channel the AVChannel whose name to get + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel); + +/** + * bprint variant of av_channel_name(). + * + * @note the string will be appended to the bprint buffer. + */ +void av_channel_name_bprint(struct AVBPrint *bp, enum AVChannel channel_id); + +/** + * Get a human readable string describing a given channel. + * + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @param channel the AVChannel whose description to get + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel); + +/** + * bprint variant of av_channel_description(). + * + * @note the string will be appended to the bprint buffer. + */ +void av_channel_description_bprint(struct AVBPrint *bp, enum AVChannel channel_id); + +/** + * This is the inverse function of @ref av_channel_name(). + * + * @return the channel with the given name + * AV_CHAN_NONE when name does not identify a known channel + */ +enum AVChannel av_channel_from_string(const char *name); + +/** + * Initialize a custom channel layout with the specified number of channels. + * The channel map will be allocated and the designation of all channels will + * be set to AV_CHAN_UNKNOWN. + * + * This is only a convenience helper function, a custom channel layout can also + * be constructed without using this. + * + * @param channel_layout the layout structure to be initialized + * @param nb_channels the number of channels + * + * @return 0 on success + * AVERROR(EINVAL) if the number of channels <= 0 + * AVERROR(ENOMEM) if the channel map could not be allocated + */ +int av_channel_layout_custom_init(AVChannelLayout *channel_layout, int nb_channels); + +/** + * Initialize a native channel layout from a bitmask indicating which channels + * are present. + * + * @param channel_layout the layout structure to be initialized + * @param mask bitmask describing the channel layout + * + * @return 0 on success + * AVERROR(EINVAL) for invalid mask values + */ +int av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask); + +/** + * Initialize a channel layout from a given string description. + * The input string can be represented by: + * - the formal channel layout name (returned by av_channel_layout_describe()) + * - single or multiple channel names (returned by av_channel_name(), eg. "FL", + * or concatenated with "+", each optionally containing a custom name after + * a "@", eg. "FL@Left+FR@Right+LFE") + * - a decimal or hexadecimal value of a native channel layout (eg. "4" or "0x4") + * - the number of channels with default layout (eg. "4c") + * - the number of unordered channels (eg. "4C" or "4 channels") + * - the ambisonic order followed by optional non-diegetic channels (eg. + * "ambisonic 2+stereo") + * On error, the channel layout will remain uninitialized, but not necessarily + * untouched. + * + * @param channel_layout uninitialized channel layout for the result + * @param str string describing the channel layout + * @return 0 on success parsing the channel layout + * AVERROR(EINVAL) if an invalid channel layout string was provided + * AVERROR(ENOMEM) if there was not enough memory + */ +int av_channel_layout_from_string(AVChannelLayout *channel_layout, + const char *str); + +/** + * Get the default channel layout for a given number of channels. + * + * @param ch_layout the layout structure to be initialized + * @param nb_channels number of channels + */ +void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels); + +/** + * Iterate over all standard channel layouts. + * + * @param opaque a pointer where libavutil will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the standard channel layout or NULL when the iteration is + * finished + */ +const AVChannelLayout *av_channel_layout_standard(void **opaque); + +/** + * Free any allocated data in the channel layout and reset the channel + * count to 0. + * + * @param channel_layout the layout structure to be uninitialized + */ +void av_channel_layout_uninit(AVChannelLayout *channel_layout); + +/** + * Make a copy of a channel layout. This differs from just assigning src to dst + * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM. + * + * @note the destination channel_layout will be always uninitialized before copy. + * + * @param dst destination channel layout + * @param src source channel layout + * @return 0 on success, a negative AVERROR on error. + */ +int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src); + +/** + * Get a human-readable string describing the channel layout properties. + * The string will be in the same format that is accepted by + * @ref av_channel_layout_from_string(), allowing to rebuild the same + * channel layout, except for opaque pointers. + * + * @param channel_layout channel layout to be described + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_layout_describe(const AVChannelLayout *channel_layout, + char *buf, size_t buf_size); + +/** + * bprint variant of av_channel_layout_describe(). + * + * @note the string will be appended to the bprint buffer. + * @return 0 on success, or a negative AVERROR value on failure. + */ +int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout, + struct AVBPrint *bp); + +/** + * Get the channel with the given index in a channel layout. + * + * @param channel_layout input channel layout + * @param idx index of the channel + * @return channel with the index idx in channel_layout on success or + * AV_CHAN_NONE on failure (if idx is not valid or the channel order is + * unspecified) + */ +enum AVChannel +av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx); + +/** + * Get the index of a given channel in a channel layout. In case multiple + * channels are found, only the first match will be returned. + * + * @param channel_layout input channel layout + * @param channel the channel whose index to obtain + * @return index of channel in channel_layout on success or a negative number if + * channel is not present in channel_layout. + */ +int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, + enum AVChannel channel); + +/** + * Get the index in a channel layout of a channel described by the given string. + * In case multiple channels are found, only the first match will be returned. + * + * This function accepts channel names in the same format as + * @ref av_channel_from_string(). + * + * @param channel_layout input channel layout + * @param name string describing the channel whose index to obtain + * @return a channel index described by the given string, or a negative AVERROR + * value. + */ +int av_channel_layout_index_from_string(const AVChannelLayout *channel_layout, + const char *name); + +/** + * Get a channel described by the given string. + * + * This function accepts channel names in the same format as + * @ref av_channel_from_string(). + * + * @param channel_layout input channel layout + * @param name string describing the channel to obtain + * @return a channel described by the given string in channel_layout on success + * or AV_CHAN_NONE on failure (if the string is not valid or the channel + * order is unspecified) + */ +enum AVChannel +av_channel_layout_channel_from_string(const AVChannelLayout *channel_layout, + const char *name); + +/** + * Find out what channels from a given set are present in a channel layout, + * without regard for their positions. + * + * @param channel_layout input channel layout + * @param mask a combination of AV_CH_* representing a set of channels + * @return a bitfield representing all the channels from mask that are present + * in channel_layout + */ +uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout, + uint64_t mask); + +/** + * Check whether a channel layout is valid, i.e. can possibly describe audio + * data. + * + * @param channel_layout input channel layout + * @return 1 if channel_layout is valid, 0 otherwise. + */ +int av_channel_layout_check(const AVChannelLayout *channel_layout); + +/** + * Check whether two channel layouts are semantically the same, i.e. the same + * channels are present on the same positions in both. + * + * If one of the channel layouts is AV_CHANNEL_ORDER_UNSPEC, while the other is + * not, they are considered to be unequal. If both are AV_CHANNEL_ORDER_UNSPEC, + * they are considered equal iff the channel counts are the same in both. + * + * @param chl input channel layout + * @param chl1 input channel layout + * @return 0 if chl and chl1 are equal, 1 if they are not equal. A negative + * AVERROR code if one or both are invalid. + */ +int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1); + +/** + * The conversion must be lossless. + */ +#define AV_CHANNEL_LAYOUT_RETYPE_FLAG_LOSSLESS (1 << 0) + +/** + * The specified retype target order is ignored and the simplest possible + * (canonical) order is used for which the input layout can be losslessy + * represented. + */ +#define AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL (1 << 1) + +/** + * Change the AVChannelOrder of a channel layout. + * + * Change of AVChannelOrder can be either lossless or lossy. In case of a + * lossless conversion all the channel designations and the associated channel + * names (if any) are kept. On a lossy conversion the channel names and channel + * designations might be lost depending on the capabilities of the desired + * AVChannelOrder. Note that some conversions are simply not possible in which + * case this function returns AVERROR(ENOSYS). + * + * The following conversions are supported: + * + * Any -> Custom : Always possible, always lossless. + * Any -> Unspecified: Always possible, lossless if channel designations + * are all unknown and channel names are not used, lossy otherwise. + * Custom -> Ambisonic : Possible if it contains ambisonic channels with + * optional non-diegetic channels in the end. Lossy if the channels have + * custom names, lossless otherwise. + * Custom -> Native : Possible if it contains native channels in native + * order. Lossy if the channels have custom names, lossless otherwise. + * + * On error this function keeps the original channel layout untouched. + * + * @param channel_layout channel layout which will be changed + * @param order the desired channel layout order + * @param flags a combination of AV_CHANNEL_LAYOUT_RETYPE_FLAG_* constants + * @return 0 if the conversion was successful and lossless or if the channel + * layout was already in the desired order + * >0 if the conversion was successful but lossy + * AVERROR(ENOSYS) if the conversion was not possible (or would be + * lossy and AV_CHANNEL_LAYOUT_RETYPE_FLAG_LOSSLESS was specified) + * AVERROR(EINVAL), AVERROR(ENOMEM) on error + */ +int av_channel_layout_retype(AVChannelLayout *channel_layout, enum AVChannelOrder order, int flags); + +/** + * @} + */ + +#endif /* AVUTIL_CHANNEL_LAYOUT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/common.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/common.h new file mode 100644 index 0000000000000..57c87f191979e --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/common.h @@ -0,0 +1,573 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * common internal and external API header + */ + +#ifndef AVUTIL_COMMON_H +#define AVUTIL_COMMON_H + +#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) && !defined(UINT64_C) +#error missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "error.h" +#include "macros.h" +#include "mem.h" + +#ifdef HAVE_AV_CONFIG_H +# include "config.h" +# include "intmath.h" +# include "internal.h" +#endif /* HAVE_AV_CONFIG_H */ + +//rounded division & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>=0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +/* Fast a/(1<=0 and b>=0 */ +#define AV_CEIL_RSHIFT(a,b) (!av_builtin_constant_p(b) ? -((-(a)) >> (b)) \ + : ((a) + (1<<(b)) - 1) >> (b)) +/* Backwards compat. */ +#define FF_CEIL_RSHIFT AV_CEIL_RSHIFT + +#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b)) +#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b)) + +/** + * Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they + * are not representable as absolute values of their type. This is the same + * as with *abs() + * @see FFNABS() + */ +#define FFABS(a) ((a) >= 0 ? (a) : (-(a))) +#define FFSIGN(a) ((a) > 0 ? 1 : -1) + +/** + * Negative Absolute value. + * this works for all integers of all types. + * As with many macros, this evaluates its argument twice, it thus must not have + * a sideeffect, that is FFNABS(x++) has undefined behavior. + */ +#define FFNABS(a) ((a) <= 0 ? (a) : (-(a))) + +/** + * Unsigned Absolute value. + * This takes the absolute value of a signed int and returns it as a unsigned. + * This also works with INT_MIN which would otherwise not be representable + * As with many macros, this evaluates its argument twice. + */ +#define FFABSU(a) ((a) <= 0 ? -(unsigned)(a) : (unsigned)(a)) +#define FFABS64U(a) ((a) <= 0 ? -(uint64_t)(a) : (uint64_t)(a)) + +/* misc math functions */ + +#ifndef av_ceil_log2 +# define av_ceil_log2 av_ceil_log2_c +#endif +#ifndef av_clip +# define av_clip av_clip_c +#endif +#ifndef av_clip64 +# define av_clip64 av_clip64_c +#endif +#ifndef av_clip_uint8 +# define av_clip_uint8 av_clip_uint8_c +#endif +#ifndef av_clip_int8 +# define av_clip_int8 av_clip_int8_c +#endif +#ifndef av_clip_uint16 +# define av_clip_uint16 av_clip_uint16_c +#endif +#ifndef av_clip_int16 +# define av_clip_int16 av_clip_int16_c +#endif +#ifndef av_clipl_int32 +# define av_clipl_int32 av_clipl_int32_c +#endif +#ifndef av_clip_intp2 +# define av_clip_intp2 av_clip_intp2_c +#endif +#ifndef av_clip_uintp2 +# define av_clip_uintp2 av_clip_uintp2_c +#endif +#ifndef av_mod_uintp2 +# define av_mod_uintp2 av_mod_uintp2_c +#endif +#ifndef av_sat_add32 +# define av_sat_add32 av_sat_add32_c +#endif +#ifndef av_sat_dadd32 +# define av_sat_dadd32 av_sat_dadd32_c +#endif +#ifndef av_sat_sub32 +# define av_sat_sub32 av_sat_sub32_c +#endif +#ifndef av_sat_dsub32 +# define av_sat_dsub32 av_sat_dsub32_c +#endif +#ifndef av_sat_add64 +# define av_sat_add64 av_sat_add64_c +#endif +#ifndef av_sat_sub64 +# define av_sat_sub64 av_sat_sub64_c +#endif +#ifndef av_clipf +# define av_clipf av_clipf_c +#endif +#ifndef av_clipd +# define av_clipd av_clipd_c +#endif +#ifndef av_popcount +# define av_popcount av_popcount_c +#endif +#ifndef av_popcount64 +# define av_popcount64 av_popcount64_c +#endif +#ifndef av_parity +# define av_parity av_parity_c +#endif + +#ifndef av_log2 +av_const int av_log2(unsigned v); +#endif + +#ifndef av_log2_16bit +av_const int av_log2_16bit(unsigned v); +#endif + +/** + * Clip a signed integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int av_clip_c(int a, int amin, int amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed 64bit integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, int64_t amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed integer value into the 0-255 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint8_t av_clip_uint8_c(int a) +{ + if (a&(~0xFF)) return (~a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -128,127 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int8_t av_clip_int8_c(int a) +{ + if ((a+0x80U) & ~0xFF) return (a>>31) ^ 0x7F; + else return a; +} + +/** + * Clip a signed integer value into the 0-65535 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint16_t av_clip_uint16_c(int a) +{ + if (a&(~0xFFFF)) return (~a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -32768,32767 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int16_t av_clip_int16_c(int a) +{ + if ((a+0x8000U) & ~0xFFFF) return (a>>31) ^ 0x7FFF; + else return a; +} + +/** + * Clip a signed 64-bit integer value into the -2147483648,2147483647 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a) +{ + if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (int32_t)((a>>63) ^ 0x7FFFFFFF); + else return (int32_t)a; +} + +/** + * Clip a signed integer into the -(2^p),(2^p-1) range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const int av_clip_intp2_c(int a, int p) +{ + if (((unsigned)a + (1 << p)) & ~((2 << p) - 1)) + return (a >> 31) ^ ((1 << p) - 1); + else + return a; +} + +/** + * Clip a signed integer to an unsigned power of two range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p) +{ + if (a & ~((1<> 31 & ((1<= 0) + return INT64_MAX ^ (b >> 63); + return s; +#endif +} + +/** + * Subtract two signed 64-bit values with saturation. + * + * @param a one value + * @param b another value + * @return difference with signed saturation + */ +static av_always_inline int64_t av_sat_sub64_c(int64_t a, int64_t b) { +#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_sub_overflow) + int64_t tmp; + return !__builtin_sub_overflow(a, b, &tmp) ? tmp : (tmp < 0 ? INT64_MAX : INT64_MIN); +#else + if (b <= 0 && a >= INT64_MAX + b) + return INT64_MAX; + if (b >= 0 && a <= INT64_MIN + b) + return INT64_MIN; + return a - b; +#endif +} + +/** + * Clip a float value into the amin-amax range. + * If a is nan or -inf amin will be returned. + * If a is +inf amax will be returned. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const float av_clipf_c(float a, float amin, float amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + return FFMIN(FFMAX(a, amin), amax); +} + +/** + * Clip a double value into the amin-amax range. + * If a is nan or -inf amin will be returned. + * If a is +inf amax will be returned. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const double av_clipd_c(double a, double amin, double amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + return FFMIN(FFMAX(a, amin), amax); +} + +/** Compute ceil(log2(x)). + * @param x value used to compute ceil(log2(x)) + * @return computed ceiling of log2(x) + */ +static av_always_inline av_const int av_ceil_log2_c(int x) +{ + return av_log2((x - 1U) << 1); +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount_c(uint32_t x) +{ + x -= (x >> 1) & 0x55555555; + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x += x >> 8; + return (x + (x >> 16)) & 0x3F; +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount64_c(uint64_t x) +{ + return av_popcount((uint32_t)x) + av_popcount((uint32_t)(x >> 32)); +} + +static av_always_inline av_const int av_parity_c(uint32_t v) +{ + return av_popcount(v) & 1; +} + +/** + * Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_BYTE Expression reading one byte from the input. + * Evaluated up to 7 times (4 for the currently + * assigned Unicode range). With a memory buffer + * input, this could be *ptr++, or if you want to make sure + * that *ptr stops at the end of a NULL terminated string then + * *ptr ? *ptr++ : 0 + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + * + * @warning ERROR should not contain a loop control statement which + * could interact with the internal while loop, and should force an + * exit from the macro code (e.g. through a goto or a return) in order + * to prevent undefined results. + */ +#define GET_UTF8(val, GET_BYTE, ERROR)\ + val= (GET_BYTE);\ + {\ + uint32_t top = (val & 128) >> 1;\ + if ((val & 0xc0) == 0x80 || val >= 0xFE)\ + {ERROR}\ + while (val & top) {\ + unsigned int tmp = (GET_BYTE) - 128;\ + if(tmp>>6)\ + {ERROR}\ + val= (val<<6) + tmp;\ + top <<= 5;\ + }\ + val &= (top << 1) - 1;\ + } + +/** + * Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_16BIT Expression returning two bytes of UTF-16 data converted + * to native byte order. Evaluated one or two times. + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + */ +#define GET_UTF16(val, GET_16BIT, ERROR)\ + val = (GET_16BIT);\ + {\ + unsigned int hi = val - 0xD800;\ + if (hi < 0x800) {\ + val = (GET_16BIT) - 0xDC00;\ + if (val > 0x3FFU || hi > 0x3FFU)\ + {ERROR}\ + val += (hi<<10) + 0x10000;\ + }\ + }\ + +/** + * @def PUT_UTF8(val, tmp, PUT_BYTE) + * Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-8. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint8_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_BYTE. + * @param PUT_BYTE writes the converted UTF-8 bytes to any proper destination. + * It could be a function or a statement, and uses tmp as the input byte. + * For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be + * executed up to 4 times for values in the valid UTF-8 range and up to + * 7 times in the general case, depending on the length of the converted + * Unicode character. + */ +#define PUT_UTF8(val, tmp, PUT_BYTE)\ + {\ + int bytes, shift;\ + uint32_t in = val;\ + if (in < 0x80) {\ + tmp = in;\ + PUT_BYTE\ + } else {\ + bytes = (av_log2(in) + 4) / 5;\ + shift = (bytes - 1) * 6;\ + tmp = (256 - (256 >> bytes)) | (in >> shift);\ + PUT_BYTE\ + while (shift >= 6) {\ + shift -= 6;\ + tmp = 0x80 | ((in >> shift) & 0x3f);\ + PUT_BYTE\ + }\ + }\ + } + +/** + * @def PUT_UTF16(val, tmp, PUT_16BIT) + * Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-16. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint16_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_16BIT. + * @param PUT_16BIT writes the converted UTF-16 data to any proper destination + * in desired endianness. It could be a function or a statement, and uses tmp + * as the input byte. For example, PUT_BYTE could be "*output++ = tmp;" + * PUT_BYTE will be executed 1 or 2 times depending on input character. + */ +#define PUT_UTF16(val, tmp, PUT_16BIT)\ + {\ + uint32_t in = val;\ + if (in < 0x10000) {\ + tmp = in;\ + PUT_16BIT\ + } else {\ + tmp = 0xD800 | ((in - 0x10000) >> 10);\ + PUT_16BIT\ + tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\ + PUT_16BIT\ + }\ + }\ + +#endif /* AVUTIL_COMMON_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/dict.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/dict.h new file mode 100644 index 0000000000000..713c9e361af83 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/dict.h @@ -0,0 +1,241 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Public dictionary API. + * @deprecated + * AVDictionary is provided for compatibility with libav. It is both in + * implementation as well as API inefficient. It does not scale and is + * extremely slow with large dictionaries. + * It is recommended that new code uses our tree container from tree.c/h + * where applicable, which uses AVL trees to achieve O(log n) performance. + */ + +#ifndef AVUTIL_DICT_H +#define AVUTIL_DICT_H + +#include + +/** + * @addtogroup lavu_dict AVDictionary + * @ingroup lavu_data + * + * @brief Simple key:value store + * + * @{ + * Dictionaries are used for storing key-value pairs. + * + * - To **create an AVDictionary**, simply pass an address of a NULL + * pointer to av_dict_set(). NULL can be used as an empty dictionary + * wherever a pointer to an AVDictionary is required. + * - To **insert an entry**, use av_dict_set(). + * - Use av_dict_get() to **retrieve an entry**. + * - To **iterate over all entries**, use av_dict_iterate(). + * - In order to **free the dictionary and all its contents**, use av_dict_free(). + * + @code + AVDictionary *d = NULL; // "create" an empty dictionary + AVDictionaryEntry *t = NULL; + + av_dict_set(&d, "foo", "bar", 0); // add an entry + + char *k = av_strdup("key"); // if your strings are already allocated, + char *v = av_strdup("value"); // you can avoid copying them like this + av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); + + while ((t = av_dict_iterate(d, t))) { + <....> // iterate over all entries in d + } + av_dict_free(&d); + @endcode + */ + +/** + * @name AVDictionary Flags + * Flags that influence behavior of the matching of keys or insertion to the dictionary. + * @{ + */ +#define AV_DICT_MATCH_CASE 1 /**< Only get an entry with exact-case key match. Only relevant in av_dict_get(). */ +#define AV_DICT_IGNORE_SUFFIX 2 /**< Return first entry in a dictionary whose first part corresponds to the search key, + ignoring the suffix of the found key string. Only relevant in av_dict_get(). */ +#define AV_DICT_DONT_STRDUP_KEY 4 /**< Take ownership of a key that's been + allocated with av_malloc() or another memory allocation function. */ +#define AV_DICT_DONT_STRDUP_VAL 8 /**< Take ownership of a value that's been + allocated with av_malloc() or another memory allocation function. */ +#define AV_DICT_DONT_OVERWRITE 16 /**< Don't overwrite existing entries. */ +#define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no + delimiter is added, the strings are simply concatenated. */ +#define AV_DICT_MULTIKEY 64 /**< Allow to store several equal keys in the dictionary */ +/** + * @} + */ + +typedef struct AVDictionaryEntry { + char *key; + char *value; +} AVDictionaryEntry; + +typedef struct AVDictionary AVDictionary; + +/** + * Get a dictionary entry with matching key. + * + * The returned entry key or value must not be changed, or it will + * cause undefined behavior. + * + * @param prev Set to the previous matching element to find the next. + * If set to NULL the first matching element is returned. + * @param key Matching key + * @param flags A collection of AV_DICT_* flags controlling how the + * entry is retrieved + * + * @return Found entry or NULL in case no matching entry was found in the dictionary + */ +AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key, + const AVDictionaryEntry *prev, int flags); + +/** + * Iterate over a dictionary + * + * Iterates through all entries in the dictionary. + * + * @warning The returned AVDictionaryEntry key/value must not be changed. + * + * @warning As av_dict_set() invalidates all previous entries returned + * by this function, it must not be called while iterating over the dict. + * + * Typical usage: + * @code + * const AVDictionaryEntry *e = NULL; + * while ((e = av_dict_iterate(m, e))) { + * // ... + * } + * @endcode + * + * @param m The dictionary to iterate over + * @param prev Pointer to the previous AVDictionaryEntry, NULL initially + * + * @retval AVDictionaryEntry* The next element in the dictionary + * @retval NULL No more elements in the dictionary + */ +const AVDictionaryEntry *av_dict_iterate(const AVDictionary *m, + const AVDictionaryEntry *prev); + +/** + * Get number of entries in dictionary. + * + * @param m dictionary + * @return number of entries in dictionary + */ +int av_dict_count(const AVDictionary *m); + +/** + * Set the given entry in *pm, overwriting an existing entry. + * + * Note: If AV_DICT_DONT_STRDUP_KEY or AV_DICT_DONT_STRDUP_VAL is set, + * these arguments will be freed on error. + * + * @warning Adding a new entry to a dictionary invalidates all existing entries + * previously returned with av_dict_get() or av_dict_iterate(). + * + * @param pm Pointer to a pointer to a dictionary struct. If *pm is NULL + * a dictionary struct is allocated and put in *pm. + * @param key Entry key to add to *pm (will either be av_strduped or added as a new key depending on flags) + * @param value Entry value to add to *pm (will be av_strduped or added as a new key depending on flags). + * Passing a NULL value will cause an existing entry to be deleted. + * + * @return >= 0 on success otherwise an error code <0 + */ +int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags); + +/** + * Convenience wrapper for av_dict_set() that converts the value to a string + * and stores it. + * + * Note: If ::AV_DICT_DONT_STRDUP_KEY is set, key will be freed on error. + */ +int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags); + +/** + * Parse the key/value pairs list and add the parsed entries to a dictionary. + * + * In case of failure, all the successfully set entries are stored in + * *pm. You may need to manually free the created dictionary. + * + * @param key_val_sep A 0-terminated list of characters used to separate + * key from value + * @param pairs_sep A 0-terminated list of characters used to separate + * two pairs from each other + * @param flags Flags to use when adding to the dictionary. + * ::AV_DICT_DONT_STRDUP_KEY and ::AV_DICT_DONT_STRDUP_VAL + * are ignored since the key/value tokens will always + * be duplicated. + * + * @return 0 on success, negative AVERROR code on failure + */ +int av_dict_parse_string(AVDictionary **pm, const char *str, + const char *key_val_sep, const char *pairs_sep, + int flags); + +/** + * Copy entries from one AVDictionary struct into another. + * + * @note Metadata is read using the ::AV_DICT_IGNORE_SUFFIX flag + * + * @param dst Pointer to a pointer to a AVDictionary struct to copy into. If *dst is NULL, + * this function will allocate a struct for you and put it in *dst + * @param src Pointer to the source AVDictionary struct to copy items from. + * @param flags Flags to use when setting entries in *dst + * + * @return 0 on success, negative AVERROR code on failure. If dst was allocated + * by this function, callers should free the associated memory. + */ +int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags); + +/** + * Free all the memory allocated for an AVDictionary struct + * and all keys and values. + */ +void av_dict_free(AVDictionary **m); + +/** + * Get dictionary entries as a string. + * + * Create a string containing dictionary's entries. + * Such string may be passed back to av_dict_parse_string(). + * @note String is escaped with backslashes ('\'). + * + * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same. + * + * @param[in] m The dictionary + * @param[out] buffer Pointer to buffer that will be allocated with string containg entries. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep Character used to separate key from value + * @param[in] pairs_sep Character used to separate two pairs from each other + * + * @return >= 0 on success, negative on error + */ +int av_dict_get_string(const AVDictionary *m, char **buffer, + const char key_val_sep, const char pairs_sep); + +/** + * @} + */ + +#endif /* AVUTIL_DICT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/error.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/error.h new file mode 100644 index 0000000000000..0d3269aa6da13 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/error.h @@ -0,0 +1,128 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * error code definitions + */ + +#ifndef AVUTIL_ERROR_H +#define AVUTIL_ERROR_H + +#include +#include + +#include "macros.h" + +/** + * @addtogroup lavu_error + * + * @{ + */ + + +/* error handling */ +#if EDOM > 0 +#define AVERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions. +#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value. +#else +/* Some platforms have E* and errno already negated. */ +#define AVERROR(e) (e) +#define AVUNERROR(e) (e) +#endif + +#define FFERRTAG(a, b, c, d) (-(int)MKTAG(a, b, c, d)) + +#define AVERROR_BSF_NOT_FOUND FFERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found +#define AVERROR_BUG FFERRTAG( 'B','U','G','!') ///< Internal bug, also see AVERROR_BUG2 +#define AVERROR_BUFFER_TOO_SMALL FFERRTAG( 'B','U','F','S') ///< Buffer too small +#define AVERROR_DECODER_NOT_FOUND FFERRTAG(0xF8,'D','E','C') ///< Decoder not found +#define AVERROR_DEMUXER_NOT_FOUND FFERRTAG(0xF8,'D','E','M') ///< Demuxer not found +#define AVERROR_ENCODER_NOT_FOUND FFERRTAG(0xF8,'E','N','C') ///< Encoder not found +#define AVERROR_EOF FFERRTAG( 'E','O','F',' ') ///< End of file +#define AVERROR_EXIT FFERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted +#define AVERROR_EXTERNAL FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library +#define AVERROR_FILTER_NOT_FOUND FFERRTAG(0xF8,'F','I','L') ///< Filter not found +#define AVERROR_INVALIDDATA FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input +#define AVERROR_MUXER_NOT_FOUND FFERRTAG(0xF8,'M','U','X') ///< Muxer not found +#define AVERROR_OPTION_NOT_FOUND FFERRTAG(0xF8,'O','P','T') ///< Option not found +#define AVERROR_PATCHWELCOME FFERRTAG( 'P','A','W','E') ///< Not yet implemented in FFmpeg, patches welcome +#define AVERROR_PROTOCOL_NOT_FOUND FFERRTAG(0xF8,'P','R','O') ///< Protocol not found + +#define AVERROR_STREAM_NOT_FOUND FFERRTAG(0xF8,'S','T','R') ///< Stream not found +/** + * This is semantically identical to AVERROR_BUG + * it has been introduced in Libav after our AVERROR_BUG and with a modified value. + */ +#define AVERROR_BUG2 FFERRTAG( 'B','U','G',' ') +#define AVERROR_UNKNOWN FFERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library +#define AVERROR_EXPERIMENTAL (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it. +#define AVERROR_INPUT_CHANGED (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED) +#define AVERROR_OUTPUT_CHANGED (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED) +/* HTTP & RTSP errors */ +#define AVERROR_HTTP_BAD_REQUEST FFERRTAG(0xF8,'4','0','0') +#define AVERROR_HTTP_UNAUTHORIZED FFERRTAG(0xF8,'4','0','1') +#define AVERROR_HTTP_FORBIDDEN FFERRTAG(0xF8,'4','0','3') +#define AVERROR_HTTP_NOT_FOUND FFERRTAG(0xF8,'4','0','4') +#define AVERROR_HTTP_OTHER_4XX FFERRTAG(0xF8,'4','X','X') +#define AVERROR_HTTP_SERVER_ERROR FFERRTAG(0xF8,'5','X','X') + +#define AV_ERROR_MAX_STRING_SIZE 64 + +/** + * Put a description of the AVERROR code errnum in errbuf. + * In case of failure the global variable errno is set to indicate the + * error. Even in case of failure av_strerror() will print a generic + * error message indicating the errnum provided to errbuf. + * + * @param errnum error code to describe + * @param errbuf buffer to which description is written + * @param errbuf_size the size in bytes of errbuf + * @return 0 on success, a negative value if a description for errnum + * cannot be found + */ +int av_strerror(int errnum, char *errbuf, size_t errbuf_size); + +/** + * Fill the provided buffer with a string containing an error string + * corresponding to the AVERROR code errnum. + * + * @param errbuf a buffer + * @param errbuf_size size in bytes of errbuf + * @param errnum error code to describe + * @return the buffer in input, filled with the error description + * @see av_strerror() + */ +static inline char *av_make_error_string(char *errbuf, size_t errbuf_size, int errnum) +{ + av_strerror(errnum, errbuf, errbuf_size); + return errbuf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_err2str(errnum) \ + av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum) + +/** + * @} + */ + +#endif /* AVUTIL_ERROR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/frame.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/frame.h new file mode 100644 index 0000000000000..8aa05ec127991 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/frame.h @@ -0,0 +1,1081 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_frame + * reference-counted frame API + */ + +#ifndef AVUTIL_FRAME_H +#define AVUTIL_FRAME_H + +#include +#include + +#include "avutil.h" +#include "buffer.h" +#include "channel_layout.h" +#include "dict.h" +#include "rational.h" +#include "samplefmt.h" +#include "pixfmt.h" +#include "version.h" + + +/** + * @defgroup lavu_frame AVFrame + * @ingroup lavu_data + * + * @{ + * AVFrame is an abstraction for reference-counted raw multimedia data. + */ + +enum AVFrameSideDataType { + /** + * The data is the AVPanScan struct defined in libavcodec. + */ + AV_FRAME_DATA_PANSCAN, + /** + * ATSC A53 Part 4 Closed Captions. + * A53 CC bitstream is stored as uint8_t in AVFrameSideData.data. + * The number of bytes of CC data is AVFrameSideData.size. + */ + AV_FRAME_DATA_A53_CC, + /** + * Stereoscopic 3d metadata. + * The data is the AVStereo3D struct defined in libavutil/stereo3d.h. + */ + AV_FRAME_DATA_STEREO3D, + /** + * The data is the AVMatrixEncoding enum defined in libavutil/channel_layout.h. + */ + AV_FRAME_DATA_MATRIXENCODING, + /** + * Metadata relevant to a downmix procedure. + * The data is the AVDownmixInfo struct defined in libavutil/downmix_info.h. + */ + AV_FRAME_DATA_DOWNMIX_INFO, + /** + * ReplayGain information in the form of the AVReplayGain struct. + */ + AV_FRAME_DATA_REPLAYGAIN, + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the frame for correct + * presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_FRAME_DATA_DISPLAYMATRIX, + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_FRAME_DATA_AFD, + /** + * Motion vectors exported by some codecs (on demand through the export_mvs + * flag set in the libavcodec AVCodecContext flags2 option). + * The data is the AVMotionVector struct defined in + * libavutil/motion_vector.h. + */ + AV_FRAME_DATA_MOTION_VECTORS, + /** + * Recommmends skipping the specified number of samples. This is exported + * only if the "skip_manual" AVOption is set in libavcodec. + * This has the same format as AV_PKT_DATA_SKIP_SAMPLES. + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_FRAME_DATA_SKIP_SAMPLES, + /** + * This side data must be associated with an audio frame and corresponds to + * enum AVAudioServiceType defined in avcodec.h. + */ + AV_FRAME_DATA_AUDIO_SERVICE_TYPE, + /** + * Mastering display metadata associated with a video frame. The payload is + * an AVMasteringDisplayMetadata type and contains information about the + * mastering display color volume. + */ + AV_FRAME_DATA_MASTERING_DISPLAY_METADATA, + /** + * The GOP timecode in 25 bit timecode format. Data format is 64-bit integer. + * This is set on the first frame of a GOP that has a temporal reference of 0. + */ + AV_FRAME_DATA_GOP_TIMECODE, + + /** + * The data represents the AVSphericalMapping structure defined in + * libavutil/spherical.h. + */ + AV_FRAME_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This payload contains data in + * the form of the AVContentLightMetadata struct. + */ + AV_FRAME_DATA_CONTENT_LIGHT_LEVEL, + + /** + * The data contains an ICC profile as an opaque octet buffer following the + * format described by ISO 15076-1 with an optional name defined in the + * metadata key entry "name". + */ + AV_FRAME_DATA_ICC_PROFILE, + + /** + * Timecode which conforms to SMPTE ST 12-1. The data is an array of 4 uint32_t + * where the first uint32_t describes how many (1-3) of the other timecodes are used. + * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.h. + */ + AV_FRAME_DATA_S12M_TIMECODE, + + /** + * HDR dynamic metadata associated with a video frame. The payload is + * an AVDynamicHDRPlus type and contains information for color + * volume transform - application 4 of SMPTE 2094-40:2016 standard. + */ + AV_FRAME_DATA_DYNAMIC_HDR_PLUS, + + /** + * Regions Of Interest, the data is an array of AVRegionOfInterest type, the number of + * array element is implied by AVFrameSideData.size / AVRegionOfInterest.self_size. + */ + AV_FRAME_DATA_REGIONS_OF_INTEREST, + + /** + * Encoding parameters for a video frame, as described by AVVideoEncParams. + */ + AV_FRAME_DATA_VIDEO_ENC_PARAMS, + + /** + * User data unregistered metadata associated with a video frame. + * This is the H.26[45] UDU SEI message, and shouldn't be used for any other purpose + * The data is stored as uint8_t in AVFrameSideData.data which is 16 bytes of + * uuid_iso_iec_11578 followed by AVFrameSideData.size - 16 bytes of user_data_payload_byte. + */ + AV_FRAME_DATA_SEI_UNREGISTERED, + + /** + * Film grain parameters for a frame, described by AVFilmGrainParams. + * Must be present for every frame which should have film grain applied. + * + * May be present multiple times, for example when there are multiple + * alternative parameter sets for different video signal characteristics. + * The user should select the most appropriate set for the application. + */ + AV_FRAME_DATA_FILM_GRAIN_PARAMS, + + /** + * Bounding boxes for object detection and classification, + * as described by AVDetectionBBoxHeader. + */ + AV_FRAME_DATA_DETECTION_BBOXES, + + /** + * Dolby Vision RPU raw data, suitable for passing to x265 + * or other libraries. Array of uint8_t, with NAL emulation + * bytes intact. + */ + AV_FRAME_DATA_DOVI_RPU_BUFFER, + + /** + * Parsed Dolby Vision metadata, suitable for passing to a software + * implementation. The payload is the AVDOVIMetadata struct defined in + * libavutil/dovi_meta.h. + */ + AV_FRAME_DATA_DOVI_METADATA, + + /** + * HDR Vivid dynamic metadata associated with a video frame. The payload is + * an AVDynamicHDRVivid type and contains information for color + * volume transform - CUVA 005.1-2021. + */ + AV_FRAME_DATA_DYNAMIC_HDR_VIVID, + + /** + * Ambient viewing environment metadata, as defined by H.274. + */ + AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT, + + /** + * Provide encoder-specific hinting information about changed/unchanged + * portions of a frame. It can be used to pass information about which + * macroblocks can be skipped because they didn't change from the + * corresponding ones in the previous frame. This could be useful for + * applications which know this information in advance to speed up + * encoding. + */ + AV_FRAME_DATA_VIDEO_HINT, +}; + +enum AVActiveFormatDescription { + AV_AFD_SAME = 8, + AV_AFD_4_3 = 9, + AV_AFD_16_9 = 10, + AV_AFD_14_9 = 11, + AV_AFD_4_3_SP_14_9 = 13, + AV_AFD_16_9_SP_14_9 = 14, + AV_AFD_SP_4_3 = 15, +}; + + +/** + * Structure to hold side data for an AVFrame. + * + * sizeof(AVFrameSideData) is not a part of the public ABI, so new fields may be added + * to the end with a minor bump. + */ +typedef struct AVFrameSideData { + enum AVFrameSideDataType type; + uint8_t *data; + size_t size; + AVDictionary *metadata; + AVBufferRef *buf; +} AVFrameSideData; + +/** + * Structure describing a single Region Of Interest. + * + * When multiple regions are defined in a single side-data block, they + * should be ordered from most to least important - some encoders are only + * capable of supporting a limited number of distinct regions, so will have + * to truncate the list. + * + * When overlapping regions are defined, the first region containing a given + * area of the frame applies. + */ +typedef struct AVRegionOfInterest { + /** + * Must be set to the size of this data structure (that is, + * sizeof(AVRegionOfInterest)). + */ + uint32_t self_size; + /** + * Distance in pixels from the top edge of the frame to the top and + * bottom edges and from the left edge of the frame to the left and + * right edges of the rectangle defining this region of interest. + * + * The constraints on a region are encoder dependent, so the region + * actually affected may be slightly larger for alignment or other + * reasons. + */ + int top; + int bottom; + int left; + int right; + /** + * Quantisation offset. + * + * Must be in the range -1 to +1. A value of zero indicates no quality + * change. A negative value asks for better quality (less quantisation), + * while a positive value asks for worse quality (greater quantisation). + * + * The range is calibrated so that the extreme values indicate the + * largest possible offset - if the rest of the frame is encoded with the + * worst possible quality, an offset of -1 indicates that this region + * should be encoded with the best possible quality anyway. Intermediate + * values are then interpolated in some codec-dependent way. + * + * For example, in 10-bit H.264 the quantisation parameter varies between + * -12 and 51. A typical qoffset value of -1/10 therefore indicates that + * this region should be encoded with a QP around one-tenth of the full + * range better than the rest of the frame. So, if most of the frame + * were to be encoded with a QP of around 30, this region would get a QP + * of around 24 (an offset of approximately -1/10 * (51 - -12) = -6.3). + * An extreme value of -1 would indicate that this region should be + * encoded with the best possible quality regardless of the treatment of + * the rest of the frame - that is, should be encoded at a QP of -12. + */ + AVRational qoffset; +} AVRegionOfInterest; + +/** + * This structure describes decoded (raw) audio or video data. + * + * AVFrame must be allocated using av_frame_alloc(). Note that this only + * allocates the AVFrame itself, the buffers for the data must be managed + * through other means (see below). + * AVFrame must be freed with av_frame_free(). + * + * AVFrame is typically allocated once and then reused multiple times to hold + * different data (e.g. a single AVFrame to hold frames received from a + * decoder). In such a case, av_frame_unref() will free any references held by + * the frame and reset it to its original clean state before it + * is reused again. + * + * The data described by an AVFrame is usually reference counted through the + * AVBuffer API. The underlying buffer references are stored in AVFrame.buf / + * AVFrame.extended_buf. An AVFrame is considered to be reference counted if at + * least one reference is set, i.e. if AVFrame.buf[0] != NULL. In such a case, + * every single data plane must be contained in one of the buffers in + * AVFrame.buf or AVFrame.extended_buf. + * There may be a single buffer for all the data, or one separate buffer for + * each plane, or anything in between. + * + * sizeof(AVFrame) is not a part of the public ABI, so new fields may be added + * to the end with a minor bump. + * + * Fields can be accessed through AVOptions, the name string used, matches the + * C structure field name for fields accessible through AVOptions. The AVClass + * for AVFrame can be obtained from avcodec_get_frame_class() + */ +typedef struct AVFrame { +#define AV_NUM_DATA_POINTERS 8 + /** + * pointer to the picture/channel planes. + * This might be different from the first allocated byte. For video, + * it could even point to the end of the image data. + * + * All pointers in data and extended_data must point into one of the + * AVBufferRef in buf or extended_buf. + * + * Some decoders access areas outside 0,0 - width,height, please + * see avcodec_align_dimensions2(). Some filters and swscale can read + * up to 16 bytes beyond the planes, if these filters are to be used, + * then 16 extra bytes must be allocated. + * + * NOTE: Pointers not needed by the format MUST be set to NULL. + * + * @attention In case of video, the data[] pointers can point to the + * end of image data in order to reverse line order, when used in + * combination with negative values in the linesize[] array. + */ + uint8_t *data[AV_NUM_DATA_POINTERS]; + + /** + * For video, a positive or negative value, which is typically indicating + * the size in bytes of each picture line, but it can also be: + * - the negative byte size of lines for vertical flipping + * (with data[n] pointing to the end of the data + * - a positive or negative multiple of the byte size as for accessing + * even and odd fields of a frame (possibly flipped) + * + * For audio, only linesize[0] may be set. For planar audio, each channel + * plane must be the same size. + * + * For video the linesizes should be multiples of the CPUs alignment + * preference, this is 16 or 32 for modern desktop CPUs. + * Some code requires such alignment other code can be slower without + * correct alignment, for yet other it makes no difference. + * + * @note The linesize may be larger than the size of usable data -- there + * may be extra padding present for performance reasons. + * + * @attention In case of video, line size values can be negative to achieve + * a vertically inverted iteration over image lines. + */ + int linesize[AV_NUM_DATA_POINTERS]; + + /** + * pointers to the data planes/channels. + * + * For video, this should simply point to data[]. + * + * For planar audio, each channel has a separate data pointer, and + * linesize[0] contains the size of each channel buffer. + * For packed audio, there is just one data pointer, and linesize[0] + * contains the total size of the buffer for all channels. + * + * Note: Both data and extended_data should always be set in a valid frame, + * but for planar audio with more channels that can fit in data, + * extended_data must be used in order to access all channels. + */ + uint8_t **extended_data; + + /** + * @name Video dimensions + * Video frames only. The coded dimensions (in pixels) of the video frame, + * i.e. the size of the rectangle that contains some well-defined values. + * + * @note The part of the frame intended for display/presentation is further + * restricted by the @ref cropping "Cropping rectangle". + * @{ + */ + int width, height; + /** + * @} + */ + + /** + * number of audio samples (per channel) described by this frame + */ + int nb_samples; + + /** + * format of the frame, -1 if unknown or unset + * Values correspond to enum AVPixelFormat for video frames, + * enum AVSampleFormat for audio) + */ + int format; + +#if FF_API_FRAME_KEY + /** + * 1 -> keyframe, 0-> not + * + * @deprecated Use AV_FRAME_FLAG_KEY instead + */ + attribute_deprecated + int key_frame; +#endif + + /** + * Picture type of the frame. + */ + enum AVPictureType pict_type; + + /** + * Sample aspect ratio for the video frame, 0/1 if unknown/unspecified. + */ + AVRational sample_aspect_ratio; + + /** + * Presentation timestamp in time_base units (time when frame should be shown to user). + */ + int64_t pts; + + /** + * DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used) + * This is also the Presentation time of this AVFrame calculated from + * only AVPacket.dts values without pts values. + */ + int64_t pkt_dts; + + /** + * Time base for the timestamps in this frame. + * In the future, this field may be set on frames output by decoders or + * filters, but its value will be by default ignored on input to encoders + * or filters. + */ + AVRational time_base; + + /** + * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) + */ + int quality; + + /** + * Frame owner's private data. + * + * This field may be set by the code that allocates/owns the frame data. + * It is then not touched by any library functions, except: + * - it is copied to other references by av_frame_copy_props() (and hence by + * av_frame_ref()); + * - it is set to NULL when the frame is cleared by av_frame_unref() + * - on the caller's explicit request. E.g. libavcodec encoders/decoders + * will copy this field to/from @ref AVPacket "AVPackets" if the caller sets + * @ref AV_CODEC_FLAG_COPY_OPAQUE. + * + * @see opaque_ref the reference-counted analogue + */ + void *opaque; + + /** + * Number of fields in this frame which should be repeated, i.e. the total + * duration of this frame should be repeat_pict + 2 normal field durations. + * + * For interlaced frames this field may be set to 1, which signals that this + * frame should be presented as 3 fields: beginning with the first field (as + * determined by AV_FRAME_FLAG_TOP_FIELD_FIRST being set or not), followed + * by the second field, and then the first field again. + * + * For progressive frames this field may be set to a multiple of 2, which + * signals that this frame's duration should be (repeat_pict + 2) / 2 + * normal frame durations. + * + * @note This field is computed from MPEG2 repeat_first_field flag and its + * associated flags, H.264 pic_struct from picture timing SEI, and + * their analogues in other codecs. Typically it should only be used when + * higher-layer timing information is not available. + */ + int repeat_pict; + +#if FF_API_INTERLACED_FRAME + /** + * The content of the picture is interlaced. + * + * @deprecated Use AV_FRAME_FLAG_INTERLACED instead + */ + attribute_deprecated + int interlaced_frame; + + /** + * If the content is interlaced, is top field displayed first. + * + * @deprecated Use AV_FRAME_FLAG_TOP_FIELD_FIRST instead + */ + attribute_deprecated + int top_field_first; +#endif + +#if FF_API_PALETTE_HAS_CHANGED + /** + * Tell user application that palette has changed from previous frame. + */ + attribute_deprecated + int palette_has_changed; +#endif + + /** + * Sample rate of the audio data. + */ + int sample_rate; + + /** + * AVBuffer references backing the data for this frame. All the pointers in + * data and extended_data must point inside one of the buffers in buf or + * extended_buf. This array must be filled contiguously -- if buf[i] is + * non-NULL then buf[j] must also be non-NULL for all j < i. + * + * There may be at most one AVBuffer per data plane, so for video this array + * always contains all the references. For planar audio with more than + * AV_NUM_DATA_POINTERS channels, there may be more buffers than can fit in + * this array. Then the extra AVBufferRef pointers are stored in the + * extended_buf array. + */ + AVBufferRef *buf[AV_NUM_DATA_POINTERS]; + + /** + * For planar audio which requires more than AV_NUM_DATA_POINTERS + * AVBufferRef pointers, this array will hold all the references which + * cannot fit into AVFrame.buf. + * + * Note that this is different from AVFrame.extended_data, which always + * contains all the pointers. This array only contains the extra pointers, + * which cannot fit into AVFrame.buf. + * + * This array is always allocated using av_malloc() by whoever constructs + * the frame. It is freed in av_frame_unref(). + */ + AVBufferRef **extended_buf; + /** + * Number of elements in extended_buf. + */ + int nb_extended_buf; + + AVFrameSideData **side_data; + int nb_side_data; + +/** + * @defgroup lavu_frame_flags AV_FRAME_FLAGS + * @ingroup lavu_frame + * Flags describing additional frame properties. + * + * @{ + */ + +/** + * The frame data may be corrupted, e.g. due to decoding errors. + */ +#define AV_FRAME_FLAG_CORRUPT (1 << 0) +/** + * A flag to mark frames that are keyframes. + */ +#define AV_FRAME_FLAG_KEY (1 << 1) +/** + * A flag to mark the frames which need to be decoded, but shouldn't be output. + */ +#define AV_FRAME_FLAG_DISCARD (1 << 2) +/** + * A flag to mark frames whose content is interlaced. + */ +#define AV_FRAME_FLAG_INTERLACED (1 << 3) +/** + * A flag to mark frames where the top field is displayed first if the content + * is interlaced. + */ +#define AV_FRAME_FLAG_TOP_FIELD_FIRST (1 << 4) +/** + * @} + */ + + /** + * Frame flags, a combination of @ref lavu_frame_flags + */ + int flags; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorRange color_range; + + enum AVColorPrimaries color_primaries; + + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + enum AVChromaLocation chroma_location; + + /** + * frame timestamp estimated using various heuristics, in stream time base + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int64_t best_effort_timestamp; + +#if FF_API_FRAME_PKT + /** + * reordered pos from the last AVPacket that has been input into the decoder + * - encoding: unused + * - decoding: Read by user. + * @deprecated use AV_CODEC_FLAG_COPY_OPAQUE to pass through arbitrary user + * data from packets to frames + */ + attribute_deprecated + int64_t pkt_pos; +#endif + + /** + * metadata. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVDictionary *metadata; + + /** + * decode error flags of the frame, set to a combination of + * FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there + * were errors during the decoding. + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int decode_error_flags; +#define FF_DECODE_ERROR_INVALID_BITSTREAM 1 +#define FF_DECODE_ERROR_MISSING_REFERENCE 2 +#define FF_DECODE_ERROR_CONCEALMENT_ACTIVE 4 +#define FF_DECODE_ERROR_DECODE_SLICES 8 + +#if FF_API_FRAME_PKT + /** + * size of the corresponding packet containing the compressed + * frame. + * It is set to a negative value if unknown. + * - encoding: unused + * - decoding: set by libavcodec, read by user. + * @deprecated use AV_CODEC_FLAG_COPY_OPAQUE to pass through arbitrary user + * data from packets to frames + */ + attribute_deprecated + int pkt_size; +#endif + + /** + * For hwaccel-format frames, this should be a reference to the + * AVHWFramesContext describing the frame. + */ + AVBufferRef *hw_frames_ctx; + + /** + * Frame owner's private data. + * + * This field may be set by the code that allocates/owns the frame data. + * It is then not touched by any library functions, except: + * - a new reference to the underlying buffer is propagated by + * av_frame_copy_props() (and hence by av_frame_ref()); + * - it is unreferenced in av_frame_unref(); + * - on the caller's explicit request. E.g. libavcodec encoders/decoders + * will propagate a new reference to/from @ref AVPacket "AVPackets" if the + * caller sets @ref AV_CODEC_FLAG_COPY_OPAQUE. + * + * @see opaque the plain pointer analogue + */ + AVBufferRef *opaque_ref; + + /** + * @anchor cropping + * @name Cropping + * Video frames only. The number of pixels to discard from the the + * top/bottom/left/right border of the frame to obtain the sub-rectangle of + * the frame intended for presentation. + * @{ + */ + size_t crop_top; + size_t crop_bottom; + size_t crop_left; + size_t crop_right; + /** + * @} + */ + + /** + * AVBufferRef for internal use by a single libav* library. + * Must not be used to transfer data between libraries. + * Has to be NULL when ownership of the frame leaves the respective library. + * + * Code outside the FFmpeg libs should never check or change the contents of the buffer ref. + * + * FFmpeg calls av_buffer_unref() on it when the frame is unreferenced. + * av_frame_copy_props() calls create a new reference with av_buffer_ref() + * for the target frame's private_ref field. + */ + AVBufferRef *private_ref; + + /** + * Channel layout of the audio data. + */ + AVChannelLayout ch_layout; + + /** + * Duration of the frame, in the same units as pts. 0 if unknown. + */ + int64_t duration; +} AVFrame; + + +/** + * Allocate an AVFrame and set its fields to default values. The resulting + * struct must be freed using av_frame_free(). + * + * @return An AVFrame filled with default values or NULL on failure. + * + * @note this only allocates the AVFrame itself, not the data buffers. Those + * must be allocated through other means, e.g. with av_frame_get_buffer() or + * manually. + */ +AVFrame *av_frame_alloc(void); + +/** + * Free the frame and any dynamically allocated objects in it, + * e.g. extended_data. If the frame is reference counted, it will be + * unreferenced first. + * + * @param frame frame to be freed. The pointer will be set to NULL. + */ +void av_frame_free(AVFrame **frame); + +/** + * Set up a new reference to the data described by the source frame. + * + * Copy frame properties from src to dst and create a new reference for each + * AVBufferRef from src. + * + * If src is not reference counted, new buffers are allocated and the data is + * copied. + * + * @warning: dst MUST have been either unreferenced with av_frame_unref(dst), + * or newly allocated with av_frame_alloc() before calling this + * function, or undefined behavior will occur. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_frame_ref(AVFrame *dst, const AVFrame *src); + +/** + * Ensure the destination frame refers to the same data described by the source + * frame, either by creating a new reference for each AVBufferRef from src if + * they differ from those in dst, by allocating new buffers and copying data if + * src is not reference counted, or by unrefencing it if src is empty. + * + * Frame properties on dst will be replaced by those from src. + * + * @return 0 on success, a negative AVERROR on error. On error, dst is + * unreferenced. + */ +int av_frame_replace(AVFrame *dst, const AVFrame *src); + +/** + * Create a new frame that references the same data as src. + * + * This is a shortcut for av_frame_alloc()+av_frame_ref(). + * + * @return newly created AVFrame on success, NULL on error. + */ +AVFrame *av_frame_clone(const AVFrame *src); + +/** + * Unreference all the buffers referenced by frame and reset the frame fields. + */ +void av_frame_unref(AVFrame *frame); + +/** + * Move everything contained in src to dst and reset src. + * + * @warning: dst is not unreferenced, but directly overwritten without reading + * or deallocating its contents. Call av_frame_unref(dst) manually + * before calling this function to ensure that no memory is leaked. + */ +void av_frame_move_ref(AVFrame *dst, AVFrame *src); + +/** + * Allocate new buffer(s) for audio or video data. + * + * The following fields must be set on frame before calling this function: + * - format (pixel format for video, sample format for audio) + * - width and height for video + * - nb_samples and ch_layout for audio + * + * This function will fill AVFrame.data and AVFrame.buf arrays and, if + * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf. + * For planar formats, one buffer will be allocated for each plane. + * + * @warning: if frame already has been allocated, calling this function will + * leak memory. In addition, undefined behavior can occur in certain + * cases. + * + * @param frame frame in which to store the new buffers. + * @param align Required buffer size alignment. If equal to 0, alignment will be + * chosen automatically for the current CPU. It is highly + * recommended to pass 0 here unless you know what you are doing. + * + * @return 0 on success, a negative AVERROR on error. + */ +int av_frame_get_buffer(AVFrame *frame, int align); + +/** + * Check if the frame data is writable. + * + * @return A positive value if the frame data is writable (which is true if and + * only if each of the underlying buffers has only one reference, namely the one + * stored in this frame). Return 0 otherwise. + * + * If 1 is returned the answer is valid until av_buffer_ref() is called on any + * of the underlying AVBufferRefs (e.g. through av_frame_ref() or directly). + * + * @see av_frame_make_writable(), av_buffer_is_writable() + */ +int av_frame_is_writable(AVFrame *frame); + +/** + * Ensure that the frame data is writable, avoiding data copy if possible. + * + * Do nothing if the frame is writable, allocate new buffers and copy the data + * if it is not. Non-refcounted frames behave as non-writable, i.e. a copy + * is always made. + * + * @return 0 on success, a negative AVERROR on error. + * + * @see av_frame_is_writable(), av_buffer_is_writable(), + * av_buffer_make_writable() + */ +int av_frame_make_writable(AVFrame *frame); + +/** + * Copy the frame data from src to dst. + * + * This function does not allocate anything, dst must be already initialized and + * allocated with the same parameters as src. + * + * This function only copies the frame data (i.e. the contents of the data / + * extended data arrays), not any other properties. + * + * @return >= 0 on success, a negative AVERROR on error. + */ +int av_frame_copy(AVFrame *dst, const AVFrame *src); + +/** + * Copy only "metadata" fields from src to dst. + * + * Metadata for the purpose of this function are those fields that do not affect + * the data layout in the buffers. E.g. pts, sample rate (for audio) or sample + * aspect ratio (for video), but not width/height or channel layout. + * Side data is also copied. + */ +int av_frame_copy_props(AVFrame *dst, const AVFrame *src); + +/** + * Get the buffer reference a given data plane is stored in. + * + * @param frame the frame to get the plane's buffer from + * @param plane index of the data plane of interest in frame->extended_data. + * + * @return the buffer reference that contains the plane or NULL if the input + * frame is not valid. + */ +AVBufferRef *av_frame_get_plane_buffer(const AVFrame *frame, int plane); + +/** + * Add a new side data to a frame. + * + * @param frame a frame to which the side data should be added + * @param type type of the added side data + * @param size size of the side data + * + * @return newly added side data on success, NULL on error + */ +AVFrameSideData *av_frame_new_side_data(AVFrame *frame, + enum AVFrameSideDataType type, + size_t size); + +/** + * Add a new side data to a frame from an existing AVBufferRef + * + * @param frame a frame to which the side data should be added + * @param type the type of the added side data + * @param buf an AVBufferRef to add as side data. The ownership of + * the reference is transferred to the frame. + * + * @return newly added side data on success, NULL on error. On failure + * the frame is unchanged and the AVBufferRef remains owned by + * the caller. + */ +AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame, + enum AVFrameSideDataType type, + AVBufferRef *buf); + +/** + * @return a pointer to the side data of a given type on success, NULL if there + * is no side data with such type in this frame. + */ +AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, + enum AVFrameSideDataType type); + +/** + * Remove and free all side data instances of the given type. + */ +void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type); + + +/** + * Flags for frame cropping. + */ +enum { + /** + * Apply the maximum possible cropping, even if it requires setting the + * AVFrame.data[] entries to unaligned pointers. Passing unaligned data + * to FFmpeg API is generally not allowed, and causes undefined behavior + * (such as crashes). You can pass unaligned data only to FFmpeg APIs that + * are explicitly documented to accept it. Use this flag only if you + * absolutely know what you are doing. + */ + AV_FRAME_CROP_UNALIGNED = 1 << 0, +}; + +/** + * Crop the given video AVFrame according to its crop_left/crop_top/crop_right/ + * crop_bottom fields. If cropping is successful, the function will adjust the + * data pointers and the width/height fields, and set the crop fields to 0. + * + * In all cases, the cropping boundaries will be rounded to the inherent + * alignment of the pixel format. In some cases, such as for opaque hwaccel + * formats, the left/top cropping is ignored. The crop fields are set to 0 even + * if the cropping was rounded or ignored. + * + * @param frame the frame which should be cropped + * @param flags Some combination of AV_FRAME_CROP_* flags, or 0. + * + * @return >= 0 on success, a negative AVERROR on error. If the cropping fields + * were invalid, AVERROR(ERANGE) is returned, and nothing is changed. + */ +int av_frame_apply_cropping(AVFrame *frame, int flags); + +/** + * @return a string identifying the side data type + */ +const char *av_frame_side_data_name(enum AVFrameSideDataType type); + +/** + * Free all side data entries and their contents, then zeroes out the + * values which the pointers are pointing to. + * + * @param sd pointer to array of side data to free. Will be set to NULL + * upon return. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. Will be set to 0 upon return. + */ +void av_frame_side_data_free(AVFrameSideData ***sd, int *nb_sd); + +#define AV_FRAME_SIDE_DATA_FLAG_UNIQUE (1 << 0) + +/** + * Add new side data entry to an array. + * + * @param sd pointer to array of side data to which to add another entry, + * or to NULL in order to start a new array. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. + * @param type type of the added side data + * @param size size of the side data + * @param flags Some combination of AV_FRAME_SIDE_DATA_FLAG_* flags, or 0. + * + * @return newly added side data on success, NULL on error. In case of + * AV_FRAME_SIDE_DATA_FLAG_UNIQUE being set, entries of matching + * AVFrameSideDataType will be removed before the addition is + * attempted. + */ +AVFrameSideData *av_frame_side_data_new(AVFrameSideData ***sd, int *nb_sd, + enum AVFrameSideDataType type, + size_t size, unsigned int flags); + +/** + * Add a new side data entry to an array based on existing side data, taking + * a reference towards the contained AVBufferRef. + * + * @param sd pointer to array of side data to which to add another entry, + * or to NULL in order to start a new array. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. + * @param src side data to be cloned, with a new reference utilized + * for the buffer. + * @param flags Some combination of AV_FRAME_SIDE_DATA_FLAG_* flags, or 0. + * + * @return negative error code on failure, >=0 on success. In case of + * AV_FRAME_SIDE_DATA_FLAG_UNIQUE being set, entries of matching + * AVFrameSideDataType will be removed before the addition is + * attempted. + */ +int av_frame_side_data_clone(AVFrameSideData ***sd, int *nb_sd, + const AVFrameSideData *src, unsigned int flags); + +/** + * Get a side data entry of a specific type from an array. + * + * @param sd array of side data. + * @param nb_sd integer containing the number of entries in the array. + * @param type type of side data to be queried + * + * @return a pointer to the side data of a given type on success, NULL if there + * is no side data with such type in this set. + */ +const AVFrameSideData *av_frame_side_data_get_c(const AVFrameSideData * const *sd, + const int nb_sd, + enum AVFrameSideDataType type); + +/** + * Wrapper around av_frame_side_data_get_c() to workaround the limitation + * that for any type T the conversion from T * const * to const T * const * + * is not performed automatically in C. + * @see av_frame_side_data_get_c() + */ +static inline +const AVFrameSideData *av_frame_side_data_get(AVFrameSideData * const *sd, + const int nb_sd, + enum AVFrameSideDataType type) +{ + return av_frame_side_data_get_c((const AVFrameSideData * const *)sd, + nb_sd, type); +} + +/** + * @} + */ + +#endif /* AVUTIL_FRAME_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/hwcontext.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/hwcontext.h new file mode 100644 index 0000000000000..bac30debaed54 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/hwcontext.h @@ -0,0 +1,598 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_H +#define AVUTIL_HWCONTEXT_H + +#include "buffer.h" +#include "frame.h" +#include "log.h" +#include "pixfmt.h" + +enum AVHWDeviceType { + AV_HWDEVICE_TYPE_NONE, + AV_HWDEVICE_TYPE_VDPAU, + AV_HWDEVICE_TYPE_CUDA, + AV_HWDEVICE_TYPE_VAAPI, + AV_HWDEVICE_TYPE_DXVA2, + AV_HWDEVICE_TYPE_QSV, + AV_HWDEVICE_TYPE_VIDEOTOOLBOX, + AV_HWDEVICE_TYPE_D3D11VA, + AV_HWDEVICE_TYPE_DRM, + AV_HWDEVICE_TYPE_OPENCL, + AV_HWDEVICE_TYPE_MEDIACODEC, + AV_HWDEVICE_TYPE_VULKAN, + AV_HWDEVICE_TYPE_D3D12VA, +}; + +/** + * This struct aggregates all the (hardware/vendor-specific) "high-level" state, + * i.e. state that is not tied to a concrete processing configuration. + * E.g., in an API that supports hardware-accelerated encoding and decoding, + * this struct will (if possible) wrap the state that is common to both encoding + * and decoding and from which specific instances of encoders or decoders can be + * derived. + * + * This struct is reference-counted with the AVBuffer mechanism. The + * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field + * points to the actual AVHWDeviceContext. Further objects derived from + * AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with + * specific properties) will hold an internal reference to it. After all the + * references are released, the AVHWDeviceContext itself will be freed, + * optionally invoking a user-specified callback for uninitializing the hardware + * state. + */ +typedef struct AVHWDeviceContext { + /** + * A class for logging. Set by av_hwdevice_ctx_alloc(). + */ + const AVClass *av_class; + + /** + * This field identifies the underlying API used for hardware access. + * + * This field is set when this struct is allocated and never changed + * afterwards. + */ + enum AVHWDeviceType type; + + /** + * The format-specific data, allocated and freed by libavutil along with + * this context. + * + * Should be cast by the user to the format-specific context defined in the + * corresponding header (hwcontext_*.h) and filled as described in the + * documentation before calling av_hwdevice_ctx_init(). + * + * After calling av_hwdevice_ctx_init() this struct should not be modified + * by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwdevice_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + * + * @note when other objects (e.g an AVHWFramesContext) are derived from this + * struct, this callback will be invoked after all such child objects + * are fully uninitialized and their respective destructors invoked. + */ + void (*free)(struct AVHWDeviceContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; +} AVHWDeviceContext; + +/** + * This struct describes a set or pool of "hardware" frames (i.e. those with + * data not located in normal system memory). All the frames in the pool are + * assumed to be allocated in the same way and interchangeable. + * + * This struct is reference-counted with the AVBuffer mechanism and tied to a + * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor + * yields a reference, whose data field points to the actual AVHWFramesContext + * struct. + */ +typedef struct AVHWFramesContext { + /** + * A class for logging. + */ + const AVClass *av_class; + + /** + * A reference to the parent AVHWDeviceContext. This reference is owned and + * managed by the enclosing AVHWFramesContext, but the caller may derive + * additional references from it. + */ + AVBufferRef *device_ref; + + /** + * The parent AVHWDeviceContext. This is simply a pointer to + * device_ref->data provided for convenience. + * + * Set by libavutil in av_hwframe_ctx_init(). + */ + AVHWDeviceContext *device_ctx; + + /** + * The format-specific data, allocated and freed automatically along with + * this context. + * + * The user shall ignore this field if the corresponding format-specific + * header (hwcontext_*.h) does not define a context to be used as + * AVHWFramesContext.hwctx. + * + * Otherwise, it should be cast by the user to said context and filled + * as described in the documentation before calling av_hwframe_ctx_init(). + * + * After any frames using this context are created, the contents of this + * struct should not be modified by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + */ + void (*free)(struct AVHWFramesContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; + + /** + * A pool from which the frames are allocated by av_hwframe_get_buffer(). + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * The buffers returned by calling av_buffer_pool_get() on this pool must + * have the properties described in the documentation in the corresponding hw + * type's header (hwcontext_*.h). The pool will be freed strictly before + * this struct's free() callback is invoked. + * + * This field may be NULL, then libavutil will attempt to allocate a pool + * internally. Note that certain device types enforce pools allocated at + * fixed size (frame count), which cannot be extended dynamically. In such a + * case, initial_pool_size must be set appropriately. + */ + AVBufferPool *pool; + + /** + * Initial size of the frame pool. If a device type does not support + * dynamically resizing the pool, then this is also the maximum pool size. + * + * May be set by the caller before calling av_hwframe_ctx_init(). Must be + * set if pool is NULL and the device type does not support dynamic pools. + */ + int initial_pool_size; + + /** + * The pixel format identifying the underlying HW surface type. + * + * Must be a hwaccel format, i.e. the corresponding descriptor must have the + * AV_PIX_FMT_FLAG_HWACCEL flag set. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + enum AVPixelFormat format; + + /** + * The pixel format identifying the actual data layout of the hardware + * frames. + * + * Must be set by the caller before calling av_hwframe_ctx_init(). + * + * @note when the underlying API does not provide the exact data layout, but + * only the colorspace/bit depth, this field should be set to the fully + * planar version of that format (e.g. for 8-bit 420 YUV it should be + * AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else). + */ + enum AVPixelFormat sw_format; + + /** + * The allocated dimensions of the frames in this pool. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + int width, height; +} AVHWFramesContext; + +/** + * Look up an AVHWDeviceType by name. + * + * @param name String name of the device type (case-insensitive). + * @return The type from enum AVHWDeviceType, or AV_HWDEVICE_TYPE_NONE if + * not found. + */ +enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name); + +/** Get the string name of an AVHWDeviceType. + * + * @param type Type from enum AVHWDeviceType. + * @return Pointer to a static string containing the name, or NULL if the type + * is not valid. + */ +const char *av_hwdevice_get_type_name(enum AVHWDeviceType type); + +/** + * Iterate over supported device types. + * + * @param prev AV_HWDEVICE_TYPE_NONE initially, then the previous type + * returned by this function in subsequent iterations. + * @return The next usable device type from enum AVHWDeviceType, or + * AV_HWDEVICE_TYPE_NONE if there are no more. + */ +enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev); + +/** + * Allocate an AVHWDeviceContext for a given hardware type. + * + * @param type the type of the hardware device to allocate. + * @return a reference to the newly created AVHWDeviceContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type); + +/** + * Finalize the device context before use. This function must be called after + * the context is filled with all the required information and before it is + * used in any way. + * + * @param ref a reference to the AVHWDeviceContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwdevice_ctx_init(AVBufferRef *ref); + +/** + * Open a device of the specified type and create an AVHWDeviceContext for it. + * + * This is a convenience function intended to cover the simple cases. Callers + * who need to fine-tune device creation/management should open the device + * manually and then wrap it in an AVHWDeviceContext using + * av_hwdevice_ctx_alloc()/av_hwdevice_ctx_init(). + * + * The returned context is already initialized and ready for use, the caller + * should not call av_hwdevice_ctx_init() on it. The user_opaque/free fields of + * the created AVHWDeviceContext are set by this function and should not be + * touched by the caller. + * + * @param device_ctx On success, a reference to the newly-created device context + * will be written here. The reference is owned by the caller + * and must be released with av_buffer_unref() when no longer + * needed. On failure, NULL will be written to this pointer. + * @param type The type of the device to create. + * @param device A type-specific string identifying the device to open. + * @param opts A dictionary of additional (type-specific) options to use in + * opening the device. The dictionary remains owned by the caller. + * @param flags currently unused + * + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type, + const char *device, AVDictionary *opts, int flags); + +/** + * Create a new device of the specified type from an existing device. + * + * If the source device is a device of the target type or was originally + * derived from such a device (possibly through one or more intermediate + * devices of other types), then this will return a reference to the + * existing device of the same type as is requested. + * + * Otherwise, it will attempt to derive a new device from the given source + * device. If direct derivation to the new type is not implemented, it will + * attempt the same derivation from each ancestor of the source device in + * turn looking for an implemented derivation method. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, int flags); + +/** + * Create a new device of the specified type from an existing device. + * + * This function performs the same action as av_hwdevice_ctx_create_derived, + * however, it is able to set options for the new device to be derived. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param options Options for the new device to create, same format as in + * av_hwdevice_ctx_create. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, + AVDictionary *options, int flags); + +/** + * Allocate an AVHWFramesContext tied to a given device context. + * + * @param device_ctx a reference to a AVHWDeviceContext. This function will make + * a new reference for internal use, the one passed to the + * function remains owned by the caller. + * @return a reference to the newly created AVHWFramesContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx); + +/** + * Finalize the context before use. This function must be called after the + * context is filled with all the required information and before it is attached + * to any frames. + * + * @param ref a reference to the AVHWFramesContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_ctx_init(AVBufferRef *ref); + +/** + * Allocate a new frame attached to the given AVHWFramesContext. + * + * @param hwframe_ctx a reference to an AVHWFramesContext + * @param frame an empty (freshly allocated or unreffed) frame to be filled with + * newly allocated buffers. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags); + +/** + * Copy data to or from a hw surface. At least one of dst/src must have an + * AVHWFramesContext attached. + * + * If src has an AVHWFramesContext attached, then the format of dst (if set) + * must use one of the formats returned by av_hwframe_transfer_get_formats(src, + * AV_HWFRAME_TRANSFER_DIRECTION_FROM). + * If dst has an AVHWFramesContext attached, then the format of src must use one + * of the formats returned by av_hwframe_transfer_get_formats(dst, + * AV_HWFRAME_TRANSFER_DIRECTION_TO) + * + * dst may be "clean" (i.e. with data/buf pointers unset), in which case the + * data buffers will be allocated by this function using av_frame_get_buffer(). + * If dst->format is set, then this format will be used, otherwise (when + * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen. + * + * The two frames must have matching allocated dimensions (i.e. equal to + * AVHWFramesContext.width/height), since not all device types support + * transferring a sub-rectangle of the whole surface. The display dimensions + * (i.e. AVFrame.width/height) may be smaller than the allocated dimensions, but + * also have to be equal for both frames. When the display dimensions are + * smaller than the allocated dimensions, the content of the padding in the + * destination frame is unspecified. + * + * @param dst the destination frame. dst is not touched on failure. + * @param src the source frame. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR error code on failure. + */ +int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags); + +enum AVHWFrameTransferDirection { + /** + * Transfer the data from the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_FROM, + + /** + * Transfer the data to the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_TO, +}; + +/** + * Get a list of possible source or target formats usable in + * av_hwframe_transfer_data(). + * + * @param hwframe_ctx the frame context to obtain the information for + * @param dir the direction of the transfer + * @param formats the pointer to the output format list will be written here. + * The list is terminated with AV_PIX_FMT_NONE and must be freed + * by the caller when no longer needed using av_free(). + * If this function returns successfully, the format list will + * have at least one item (not counting the terminator). + * On failure, the contents of this pointer are unspecified. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats, int flags); + + +/** + * This struct describes the constraints on hardware frames attached to + * a given device with a hardware-specific configuration. This is returned + * by av_hwdevice_get_hwframe_constraints() and must be freed by + * av_hwframe_constraints_free() after use. + */ +typedef struct AVHWFramesConstraints { + /** + * A list of possible values for format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. This member will always be filled. + */ + enum AVPixelFormat *valid_hw_formats; + + /** + * A list of possible values for sw_format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. Can be NULL if this information is + * not known. + */ + enum AVPixelFormat *valid_sw_formats; + + /** + * The minimum size of frames in this hw_frames_ctx. + * (Zero if not known.) + */ + int min_width; + int min_height; + + /** + * The maximum size of frames in this hw_frames_ctx. + * (INT_MAX if not known / no limit.) + */ + int max_width; + int max_height; +} AVHWFramesConstraints; + +/** + * Allocate a HW-specific configuration structure for a given HW device. + * After use, the user must free all members as required by the specific + * hardware structure being used, then free the structure itself with + * av_free(). + * + * @param device_ctx a reference to the associated AVHWDeviceContext. + * @return The newly created HW-specific configuration structure on + * success or NULL on failure. + */ +void *av_hwdevice_hwconfig_alloc(AVBufferRef *device_ctx); + +/** + * Get the constraints on HW frames given a device and the HW-specific + * configuration to be used with that device. If no HW-specific + * configuration is provided, returns the maximum possible capabilities + * of the device. + * + * @param ref a reference to the associated AVHWDeviceContext. + * @param hwconfig a filled HW-specific configuration structure, or NULL + * to return the maximum possible capabilities of the device. + * @return AVHWFramesConstraints structure describing the constraints + * on the device, or NULL if not available. + */ +AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, + const void *hwconfig); + +/** + * Free an AVHWFrameConstraints structure. + * + * @param constraints The (filled or unfilled) AVHWFrameConstraints structure. + */ +void av_hwframe_constraints_free(AVHWFramesConstraints **constraints); + + +/** + * Flags to apply to frame mappings. + */ +enum { + /** + * The mapping must be readable. + */ + AV_HWFRAME_MAP_READ = 1 << 0, + /** + * The mapping must be writeable. + */ + AV_HWFRAME_MAP_WRITE = 1 << 1, + /** + * The mapped frame will be overwritten completely in subsequent + * operations, so the current frame data need not be loaded. Any values + * which are not overwritten are unspecified. + */ + AV_HWFRAME_MAP_OVERWRITE = 1 << 2, + /** + * The mapping must be direct. That is, there must not be any copying in + * the map or unmap steps. Note that performance of direct mappings may + * be much lower than normal memory. + */ + AV_HWFRAME_MAP_DIRECT = 1 << 3, +}; + +/** + * Map a hardware frame. + * + * This has a number of different possible effects, depending on the format + * and origin of the src and dst frames. On input, src should be a usable + * frame with valid buffers and dst should be blank (typically as just created + * by av_frame_alloc()). src should have an associated hwframe context, and + * dst may optionally have a format and associated hwframe context. + * + * If src was created by mapping a frame from the hwframe context of dst, + * then this function undoes the mapping - dst is replaced by a reference to + * the frame that src was originally mapped from. + * + * If both src and dst have an associated hwframe context, then this function + * attempts to map the src frame from its hardware context to that of dst and + * then fill dst with appropriate data to be usable there. This will only be + * possible if the hwframe contexts and associated devices are compatible - + * given compatible devices, av_hwframe_ctx_create_derived() can be used to + * create a hwframe context for dst in which mapping should be possible. + * + * If src has a hwframe context but dst does not, then the src frame is + * mapped to normal memory and should thereafter be usable as a normal frame. + * If the format is set on dst, then the mapping will attempt to create dst + * with that format and fail if it is not possible. If format is unset (is + * AV_PIX_FMT_NONE) then dst will be mapped with whatever the most appropriate + * format to use is (probably the sw_format of the src hwframe context). + * + * A return value of AVERROR(ENOSYS) indicates that the mapping is not + * possible with the given arguments and hwframe setup, while other return + * values indicate that it failed somehow. + * + * On failure, the destination frame will be left blank, except for the + * hw_frames_ctx/format fields thay may have been set by the caller - those will + * be preserved as they were. + * + * @param dst Destination frame, to contain the mapping. + * @param src Source frame, to be mapped. + * @param flags Some combination of AV_HWFRAME_MAP_* flags. + * @return Zero on success, negative AVERROR code on failure. + */ +int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags); + + +/** + * Create and initialise an AVHWFramesContext as a mapping of another existing + * AVHWFramesContext on a different device. + * + * av_hwframe_ctx_init() should not be called after this. + * + * @param derived_frame_ctx On success, a reference to the newly created + * AVHWFramesContext. + * @param format The AVPixelFormat for the derived context. + * @param derived_device_ctx A reference to the device to create the new + * AVHWFramesContext on. + * @param source_frame_ctx A reference to an existing AVHWFramesContext + * which will be mapped to the derived context. + * @param flags Some combination of AV_HWFRAME_MAP_* flags, defining the + * mapping parameters to apply to frames which are allocated + * in the derived device. + * @return Zero on success, negative AVERROR code on failure. + */ +int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, + enum AVPixelFormat format, + AVBufferRef *derived_device_ctx, + AVBufferRef *source_frame_ctx, + int flags); + +#endif /* AVUTIL_HWCONTEXT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/imgutils.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/imgutils.h new file mode 100644 index 0000000000000..123a9e5c0d21a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/imgutils.h @@ -0,0 +1,377 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_IMGUTILS_H +#define AVUTIL_IMGUTILS_H + +/** + * @file + * misc image utilities + * + * @addtogroup lavu_picture + * @{ + */ + +#include +#include +#include "pixdesc.h" +#include "pixfmt.h" +#include "rational.h" + +/** + * Compute the max pixel step for each plane of an image with a + * format described by pixdesc. + * + * The pixel step is the distance in bytes between the first byte of + * the group of bytes which describe a pixel component and the first + * byte of the successive group in the same plane for the same + * component. + * + * @param max_pixsteps an array which is filled with the max pixel step + * for each plane. Since a plane may contain different pixel + * components, the computed max_pixsteps[plane] is relative to the + * component in the plane with the max pixel step. + * @param max_pixstep_comps an array which is filled with the component + * for each plane which has the max pixel step. May be NULL. + * @param pixdesc the AVPixFmtDescriptor for the image, describing its format + */ +void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], + const AVPixFmtDescriptor *pixdesc); + +/** + * Compute the size of an image line with format pix_fmt and width + * width for the plane plane. + * + * @return the computed size in bytes + */ +int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane); + +/** + * Fill plane linesizes for an image with pixel format pix_fmt and + * width width. + * + * @param linesizes array to be filled with the linesize for each plane + * @param pix_fmt the AVPixelFormat of the image + * @param width width of the image in pixels + * @return >= 0 in case of success, a negative error code otherwise + */ +int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width); + +/** + * Fill plane sizes for an image with pixel format pix_fmt and height height. + * + * @param size the array to be filled with the size of each image plane + * @param pix_fmt the AVPixelFormat of the image + * @param height height of the image in pixels + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return >= 0 in case of success, a negative error code otherwise + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_fill_linesizes(). + */ +int av_image_fill_plane_sizes(size_t size[4], enum AVPixelFormat pix_fmt, + int height, const ptrdiff_t linesizes[4]); + +/** + * Fill plane data pointers for an image with pixel format pix_fmt and + * height height. + * + * @param data pointers array to be filled with the pointer for each image plane + * @param pix_fmt the AVPixelFormat of the image + * @param height height of the image in pixels + * @param ptr the pointer to a buffer which will contain the image + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, + uint8_t *ptr, const int linesizes[4]); + +/** + * Allocate an image with size w and h and pixel format pix_fmt, and + * fill pointers and linesizes accordingly. + * The allocated image buffer has to be freed by using + * av_freep(&pointers[0]). + * + * @param pointers array to be filled with the pointer for each image plane + * @param linesizes the array filled with the linesize for each plane + * @param w width of the image in pixels + * @param h height of the image in pixels + * @param pix_fmt the AVPixelFormat of the image + * @param align the value to use for buffer size alignment + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_alloc(uint8_t *pointers[4], int linesizes[4], + int w, int h, enum AVPixelFormat pix_fmt, int align); + +/** + * Copy image plane from src to dst. + * That is, copy "height" number of lines of "bytewidth" bytes each. + * The first byte of each successive line is separated by *_linesize + * bytes. + * + * bytewidth must be contained by both absolute values of dst_linesize + * and src_linesize, otherwise the function behavior is undefined. + * + * @param dst destination plane to copy to + * @param dst_linesize linesize for the image plane in dst + * @param src source plane to copy from + * @param src_linesize linesize for the image plane in src + * @param height height (number of lines) of the plane + */ +void av_image_copy_plane(uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, + int bytewidth, int height); + +/** + * Copy image data located in uncacheable (e.g. GPU mapped) memory. Where + * available, this function will use special functionality for reading from such + * memory, which may result in greatly improved performance compared to plain + * av_image_copy_plane(). + * + * bytewidth must be contained by both absolute values of dst_linesize + * and src_linesize, otherwise the function behavior is undefined. + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_copy_plane(). + * @note On x86, the linesizes currently need to be aligned to the cacheline + * size (i.e. 64) to get improved performance. + */ +void av_image_copy_plane_uc_from(uint8_t *dst, ptrdiff_t dst_linesize, + const uint8_t *src, ptrdiff_t src_linesize, + ptrdiff_t bytewidth, int height); + +/** + * Copy image in src_data to dst_data. + * + * @param dst_data destination image data buffer to copy to + * @param dst_linesizes linesizes for the image in dst_data + * @param src_data source image data buffer to copy from + * @param src_linesizes linesizes for the image in src_data + * @param pix_fmt the AVPixelFormat of the image + * @param width width of the image in pixels + * @param height height of the image in pixels + */ +void av_image_copy(uint8_t * const dst_data[4], const int dst_linesizes[4], + const uint8_t * const src_data[4], const int src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Wrapper around av_image_copy() to workaround the limitation + * that the conversion from uint8_t * const * to const uint8_t * const * + * is not performed automatically in C. + * @see av_image_copy() + */ +static inline +void av_image_copy2(uint8_t * const dst_data[4], const int dst_linesizes[4], + uint8_t * const src_data[4], const int src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height) +{ + av_image_copy(dst_data, dst_linesizes, + (const uint8_t * const *)src_data, src_linesizes, + pix_fmt, width, height); +} + +/** + * Copy image data located in uncacheable (e.g. GPU mapped) memory. Where + * available, this function will use special functionality for reading from such + * memory, which may result in greatly improved performance compared to plain + * av_image_copy(). + * + * The data pointers and the linesizes must be aligned to the maximum required + * by the CPU architecture. + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_copy(). + * @note On x86, the linesizes currently need to be aligned to the cacheline + * size (i.e. 64) to get improved performance. + */ +void av_image_copy_uc_from(uint8_t * const dst_data[4], const ptrdiff_t dst_linesizes[4], + const uint8_t * const src_data[4], const ptrdiff_t src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Setup the data pointers and linesizes based on the specified image + * parameters and the provided array. + * + * The fields of the given image are filled in by using the src + * address which points to the image data buffer. Depending on the + * specified pixel format, one or multiple image data pointers and + * line sizes will be set. If a planar format is specified, several + * pointers will be set pointing to the different picture planes and + * the line sizes of the different planes will be stored in the + * lines_sizes array. Call with src == NULL to get the required + * size for the src buffer. + * + * To allocate the buffer and fill in the dst_data and dst_linesize in + * one call, use av_image_alloc(). + * + * @param dst_data data pointers to be filled in + * @param dst_linesize linesizes for the image in dst_data to be filled in + * @param src buffer which will contain or contains the actual image data, can be NULL + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the value used in src for linesize alignment + * @return the size in bytes required for src, a negative error code + * in case of failure + */ +int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Return the size in bytes of the amount of data required to store an + * image with the given parameters. + * + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the assumed linesize alignment + * @return the buffer size in bytes, a negative error code in case of failure + */ +int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Copy image data from an image into a buffer. + * + * av_image_get_buffer_size() can be used to compute the required size + * for the buffer to fill. + * + * @param dst a buffer into which picture data will be copied + * @param dst_size the size in bytes of dst + * @param src_data pointers containing the source image data + * @param src_linesize linesizes for the image in src_data + * @param pix_fmt the pixel format of the source image + * @param width the width of the source image in pixels + * @param height the height of the source image in pixels + * @param align the assumed linesize alignment for dst + * @return the number of bytes written to dst, or a negative value + * (error code) on error + */ +int av_image_copy_to_buffer(uint8_t *dst, int dst_size, + const uint8_t * const src_data[4], const int src_linesize[4], + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of the image can be addressed with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of a plane of an image with the specified pix_fmt can be addressed + * with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param max_pixels the maximum number of pixels the user wants to accept + * @param pix_fmt the pixel format, can be AV_PIX_FMT_NONE if unknown. + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx); + +/** + * Check if the given sample aspect ratio of an image is valid. + * + * It is considered invalid if the denominator is 0 or if applying the ratio + * to the image size would make the smaller dimension less than 1. If the + * sar numerator is 0, it is considered unknown and will return as valid. + * + * @param w width of the image + * @param h height of the image + * @param sar sample aspect ratio of the image + * @return 0 if valid, a negative AVERROR code otherwise + */ +int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar); + +/** + * Overwrite the image data with black. This is suitable for filling a + * sub-rectangle of an image, meaning the padding between the right most pixel + * and the left most pixel on the next line will not be overwritten. For some + * formats, the image size might be rounded up due to inherent alignment. + * + * If the pixel format has alpha, the alpha is cleared to opaque. + * + * This can return an error if the pixel format is not supported. Normally, all + * non-hwaccel pixel formats should be supported. + * + * Passing NULL for dst_data is allowed. Then the function returns whether the + * operation would have succeeded. (It can return an error if the pix_fmt is + * not supported.) + * + * @param dst_data data pointers to destination image + * @param dst_linesize linesizes for the destination image + * @param pix_fmt the pixel format of the image + * @param range the color range of the image (important for colorspaces such as YUV) + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @return 0 if the image data was cleared, a negative AVERROR code otherwise + */ +int av_image_fill_black(uint8_t * const dst_data[4], const ptrdiff_t dst_linesize[4], + enum AVPixelFormat pix_fmt, enum AVColorRange range, + int width, int height); + +/** + * Overwrite the image data with a color. This is suitable for filling a + * sub-rectangle of an image, meaning the padding between the right most pixel + * and the left most pixel on the next line will not be overwritten. For some + * formats, the image size might be rounded up due to inherent alignment. + * + * If the pixel format has alpha, it is also replaced. Color component values + * are interpreted as native integers (or intfloats) regardless of actual pixel + * format endianness. + * + * This can return an error if the pixel format is not supported. Normally, all + * non-hwaccel pixel formats should be supported. + * + * Passing NULL for dst_data is allowed. Then the function returns whether the + * operation would have succeeded. (It can return an error if the pix_fmt is + * not supported.) + * + * @param dst_data data pointers to destination image + * @param dst_linesize linesizes for the destination image + * @param pix_fmt the pixel format of the image + * @param color the color components to be used for the fill + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param flags currently unused + * @return 0 if the image data was filled, a negative AVERROR code otherwise + */ +int av_image_fill_color(uint8_t * const dst_data[4], const ptrdiff_t dst_linesize[4], + enum AVPixelFormat pix_fmt, const uint32_t color[4], + int width, int height, int flags); + +/** + * @} + */ + + +#endif /* AVUTIL_IMGUTILS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/intfloat.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/intfloat.h new file mode 100644 index 0000000000000..fe3d7ec4a5b6f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/intfloat.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_INTFLOAT_H +#define AVUTIL_INTFLOAT_H + +#include +#include "attributes.h" + +union av_intfloat32 { + uint32_t i; + float f; +}; + +union av_intfloat64 { + uint64_t i; + double f; +}; + +/** + * Reinterpret a 32-bit integer as a float. + */ +static av_always_inline float av_int2float(uint32_t i) +{ + union av_intfloat32 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a float as a 32-bit integer. + */ +static av_always_inline uint32_t av_float2int(float f) +{ + union av_intfloat32 v; + v.f = f; + return v.i; +} + +/** + * Reinterpret a 64-bit integer as a double. + */ +static av_always_inline double av_int2double(uint64_t i) +{ + union av_intfloat64 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a double as a 64-bit integer. + */ +static av_always_inline uint64_t av_double2int(double f) +{ + union av_intfloat64 v; + v.f = f; + return v.i; +} + +#endif /* AVUTIL_INTFLOAT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/log.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/log.h new file mode 100644 index 0000000000000..ab7ceabe2234a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/log.h @@ -0,0 +1,387 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_LOG_H +#define AVUTIL_LOG_H + +#include +#include "attributes.h" +#include "version.h" + +typedef enum { + AV_CLASS_CATEGORY_NA = 0, + AV_CLASS_CATEGORY_INPUT, + AV_CLASS_CATEGORY_OUTPUT, + AV_CLASS_CATEGORY_MUXER, + AV_CLASS_CATEGORY_DEMUXER, + AV_CLASS_CATEGORY_ENCODER, + AV_CLASS_CATEGORY_DECODER, + AV_CLASS_CATEGORY_FILTER, + AV_CLASS_CATEGORY_BITSTREAM_FILTER, + AV_CLASS_CATEGORY_SWSCALER, + AV_CLASS_CATEGORY_SWRESAMPLER, + AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT = 40, + AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT, + AV_CLASS_CATEGORY_NB ///< not part of ABI/API +}AVClassCategory; + +#define AV_IS_INPUT_DEVICE(category) \ + (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_INPUT)) + +#define AV_IS_OUTPUT_DEVICE(category) \ + (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_OUTPUT)) + +struct AVOptionRanges; + +/** + * Describe the class of an AVClass context structure. That is an + * arbitrary struct of which the first field is a pointer to an + * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.). + */ +typedef struct AVClass { + /** + * The name of the class; usually it is the same name as the + * context structure type to which the AVClass is associated. + */ + const char* class_name; + + /** + * A pointer to a function which returns the name of a context + * instance ctx associated with the class. + */ + const char* (*item_name)(void* ctx); + + /** + * a pointer to the first option specified in the class if any or NULL + * + * @see av_set_default_options() + */ + const struct AVOption *option; + + /** + * LIBAVUTIL_VERSION with which this structure was created. + * This is used to allow fields to be added without requiring major + * version bumps everywhere. + */ + + int version; + + /** + * Offset in the structure where log_level_offset is stored. + * 0 means there is no such variable + */ + int log_level_offset_offset; + + /** + * Offset in the structure where a pointer to the parent context for + * logging is stored. For example a decoder could pass its AVCodecContext + * to eval as such a parent context, which an av_log() implementation + * could then leverage to display the parent context. + * The offset can be NULL. + */ + int parent_log_context_offset; + + /** + * Category used for visualization (like color) + * This is only set if the category is equal for all objects using this class. + * available since version (51 << 16 | 56 << 8 | 100) + */ + AVClassCategory category; + + /** + * Callback to return the category. + * available since version (51 << 16 | 59 << 8 | 100) + */ + AVClassCategory (*get_category)(void* ctx); + + /** + * Callback to return the supported/allowed ranges. + * available since version (52.12) + */ + int (*query_ranges)(struct AVOptionRanges **, void *obj, const char *key, int flags); + + /** + * Return next AVOptions-enabled child or NULL + */ + void* (*child_next)(void *obj, void *prev); + + /** + * Iterate over the AVClasses corresponding to potential AVOptions-enabled + * children. + * + * @param iter pointer to opaque iteration state. The caller must initialize + * *iter to NULL before the first call. + * @return AVClass for the next AVOptions-enabled child or NULL if there are + * no more such children. + * + * @note The difference between child_next and this is that child_next + * iterates over _already existing_ objects, while child_class_iterate + * iterates over _all possible_ children. + */ + const struct AVClass* (*child_class_iterate)(void **iter); +} AVClass; + +/** + * @addtogroup lavu_log + * + * @{ + * + * @defgroup lavu_log_constants Logging Constants + * + * @{ + */ + +/** + * Print no output. + */ +#define AV_LOG_QUIET -8 + +/** + * Something went really wrong and we will crash now. + */ +#define AV_LOG_PANIC 0 + +/** + * Something went wrong and recovery is not possible. + * For example, no header was found for a format which depends + * on headers or an illegal combination of parameters is used. + */ +#define AV_LOG_FATAL 8 + +/** + * Something went wrong and cannot losslessly be recovered. + * However, not all future data is affected. + */ +#define AV_LOG_ERROR 16 + +/** + * Something somehow does not look correct. This may or may not + * lead to problems. An example would be the use of '-vstrict -2'. + */ +#define AV_LOG_WARNING 24 + +/** + * Standard information. + */ +#define AV_LOG_INFO 32 + +/** + * Detailed information. + */ +#define AV_LOG_VERBOSE 40 + +/** + * Stuff which is only useful for libav* developers. + */ +#define AV_LOG_DEBUG 48 + +/** + * Extremely verbose debugging, useful for libav* development. + */ +#define AV_LOG_TRACE 56 + +#define AV_LOG_MAX_OFFSET (AV_LOG_TRACE - AV_LOG_QUIET) + +/** + * @} + */ + +/** + * Sets additional colors for extended debugging sessions. + * @code + av_log(ctx, AV_LOG_DEBUG|AV_LOG_C(134), "Message in purple\n"); + @endcode + * Requires 256color terminal support. Uses outside debugging is not + * recommended. + */ +#define AV_LOG_C(x) ((x) << 8) + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log_set_callback + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct or NULL if general log. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + */ +void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Send the specified message to the log once with the initial_level and then with + * the subsequent_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct or NULL if general log. + * @param initial_level importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant" for the first occurance. + * @param subsequent_level importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant" after the first occurance. + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param state a variable to keep trak of if a message has already been printed + * this must be initialized to 0 before the first use. The same state + * must not be accessed by 2 Threads simultaneously. + */ +void av_log_once(void* avcl, int initial_level, int subsequent_level, int *state, const char *fmt, ...) av_printf_format(5, 6); + + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log_set_callback + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param vl The arguments referenced by the format string. + */ +void av_vlog(void *avcl, int level, const char *fmt, va_list vl); + +/** + * Get the current log level + * + * @see lavu_log_constants + * + * @return Current log level + */ +int av_log_get_level(void); + +/** + * Set the log level + * + * @see lavu_log_constants + * + * @param level Logging level + */ +void av_log_set_level(int level); + +/** + * Set the logging callback + * + * @note The callback must be thread safe, even if the application does not use + * threads itself as some codecs are multithreaded. + * + * @see av_log_default_callback + * + * @param callback A logging function with a compatible signature. + */ +void av_log_set_callback(void (*callback)(void*, int, const char*, va_list)); + +/** + * Default logging callback + * + * It prints the message to stderr, optionally colorizing it. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param vl The arguments referenced by the format string. + */ +void av_log_default_callback(void *avcl, int level, const char *fmt, + va_list vl); + +/** + * Return the context name + * + * @param ctx The AVClass context + * + * @return The AVClass class_name + */ +const char* av_default_item_name(void* ctx); +AVClassCategory av_default_get_category(void *ptr); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formatted line + * @param line_size size of the buffer + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + */ +void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formatted line; + * may be NULL if line_size is 0 + * @param line_size size of the buffer; at most line_size-1 characters will + * be written to the buffer, plus one null terminator + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + * @return Returns a negative value if an error occurred, otherwise returns + * the number of characters that would have been written for a + * sufficiently large buffer, not including the terminating null + * character. If the return value is not less than line_size, it means + * that the log message was truncated to fit the buffer. + */ +int av_log_format_line2(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * Skip repeated messages, this requires the user app to use av_log() instead of + * (f)printf as the 2 would otherwise interfere and lead to + * "Last message repeated x times" messages below (f)printf messages with some + * bad luck. + * Also to receive the last, "last repeated" line if any, the user app must + * call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end + */ +#define AV_LOG_SKIP_REPEATED 1 + +/** + * Include the log severity in messages originating from codecs. + * + * Results in messages such as: + * [rawvideo @ 0xDEADBEEF] [error] encode did not produce valid pts + */ +#define AV_LOG_PRINT_LEVEL 2 + +void av_log_set_flags(int arg); +int av_log_get_flags(void); + +/** + * @} + */ + +#endif /* AVUTIL_LOG_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/macros.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/macros.h new file mode 100644 index 0000000000000..2a7567c3ea8fb --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/macros.h @@ -0,0 +1,80 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu + * Utility Preprocessor macros + */ + +#ifndef AVUTIL_MACROS_H +#define AVUTIL_MACROS_H + +#include "libavutil/avconfig.h" + +#if AV_HAVE_BIGENDIAN +# define AV_NE(be, le) (be) +#else +# define AV_NE(be, le) (le) +#endif + +/** + * Comparator. + * For two numerical expressions x and y, gives 1 if x > y, -1 if x < y, and 0 + * if x == y. This is useful for instance in a qsort comparator callback. + * Furthermore, compilers are able to optimize this to branchless code, and + * there is no risk of overflow with signed types. + * As with many macros, this evaluates its argument multiple times, it thus + * must not have a side-effect. + */ +#define FFDIFFSIGN(x,y) (((x)>(y)) - ((x)<(y))) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) +#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c) + +#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0) +#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) + +#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24)) +#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24)) + +/** + * @addtogroup preproc_misc Preprocessor String Macros + * + * String manipulation macros + * + * @{ + */ + +#define AV_STRINGIFY(s) AV_TOSTRING(s) +#define AV_TOSTRING(s) #s + +#define AV_GLUE(a, b) a ## b +#define AV_JOIN(a, b) AV_GLUE(a, b) + +/** + * @} + */ + +#define AV_PRAGMA(s) _Pragma(#s) + +#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1)) + +#endif /* AVUTIL_MACROS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/mathematics.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/mathematics.h new file mode 100644 index 0000000000000..e213bab68c9c9 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/mathematics.h @@ -0,0 +1,300 @@ +/* + * copyright (c) 2005-2012 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @addtogroup lavu_math + * Mathematical utilities for working with timestamp and time base. + */ + +#ifndef AVUTIL_MATHEMATICS_H +#define AVUTIL_MATHEMATICS_H + +#include +#include +#include "attributes.h" +#include "rational.h" +#include "intfloat.h" + +#ifndef M_E +#define M_E 2.7182818284590452354 /* e */ +#endif +#ifndef M_Ef +#define M_Ef 2.7182818284590452354f /* e */ +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#endif +#ifndef M_LN2f +#define M_LN2f 0.69314718055994530942f /* log_e 2 */ +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#endif +#ifndef M_LN10f +#define M_LN10f 2.30258509299404568402f /* log_e 10 */ +#endif +#ifndef M_LOG2_10 +#define M_LOG2_10 3.32192809488736234787 /* log_2 10 */ +#endif +#ifndef M_LOG2_10f +#define M_LOG2_10f 3.32192809488736234787f /* log_2 10 */ +#endif +#ifndef M_PHI +#define M_PHI 1.61803398874989484820 /* phi / golden ratio */ +#endif +#ifndef M_PHIf +#define M_PHIf 1.61803398874989484820f /* phi / golden ratio */ +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif +#ifndef M_PIf +#define M_PIf 3.14159265358979323846f /* pi */ +#endif +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#endif +#ifndef M_PI_2f +#define M_PI_2f 1.57079632679489661923f /* pi/2 */ +#endif +#ifndef M_PI_4 +#define M_PI_4 0.78539816339744830962 /* pi/4 */ +#endif +#ifndef M_PI_4f +#define M_PI_4f 0.78539816339744830962f /* pi/4 */ +#endif +#ifndef M_1_PI +#define M_1_PI 0.31830988618379067154 /* 1/pi */ +#endif +#ifndef M_1_PIf +#define M_1_PIf 0.31830988618379067154f /* 1/pi */ +#endif +#ifndef M_2_PI +#define M_2_PI 0.63661977236758134308 /* 2/pi */ +#endif +#ifndef M_2_PIf +#define M_2_PIf 0.63661977236758134308f /* 2/pi */ +#endif +#ifndef M_2_SQRTPI +#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +#endif +#ifndef M_2_SQRTPIf +#define M_2_SQRTPIf 1.12837916709551257390f /* 2/sqrt(pi) */ +#endif +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif +#ifndef M_SQRT1_2f +#define M_SQRT1_2f 0.70710678118654752440f /* 1/sqrt(2) */ +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#endif +#ifndef M_SQRT2f +#define M_SQRT2f 1.41421356237309504880f /* sqrt(2) */ +#endif +#ifndef NAN +#define NAN av_int2float(0x7fc00000) +#endif +#ifndef INFINITY +#define INFINITY av_int2float(0x7f800000) +#endif + +/** + * @addtogroup lavu_math + * + * @{ + */ + +/** + * Rounding methods. + */ +enum AVRounding { + AV_ROUND_ZERO = 0, ///< Round toward zero. + AV_ROUND_INF = 1, ///< Round away from zero. + AV_ROUND_DOWN = 2, ///< Round toward -infinity. + AV_ROUND_UP = 3, ///< Round toward +infinity. + AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero. + /** + * Flag telling rescaling functions to pass `INT64_MIN`/`MAX` through + * unchanged, avoiding special cases for #AV_NOPTS_VALUE. + * + * Unlike other values of the enumeration AVRounding, this value is a + * bitmask that must be used in conjunction with another value of the + * enumeration through a bitwise OR, in order to set behavior for normal + * cases. + * + * @code{.c} + * av_rescale_rnd(3, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + * // Rescaling 3: + * // Calculating 3 * 1 / 2 + * // 3 / 2 is rounded up to 2 + * // => 2 + * + * av_rescale_rnd(AV_NOPTS_VALUE, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + * // Rescaling AV_NOPTS_VALUE: + * // AV_NOPTS_VALUE == INT64_MIN + * // AV_NOPTS_VALUE is passed through + * // => AV_NOPTS_VALUE + * @endcode + */ + AV_ROUND_PASS_MINMAX = 8192, +}; + +/** + * Compute the greatest common divisor of two integer operands. + * + * @param a Operand + * @param b Operand + * @return GCD of a and b up to sign; if a >= 0 and b >= 0, return value is >= 0; + * if a == 0 and b == 0, returns 0. + */ +int64_t av_const av_gcd(int64_t a, int64_t b); + +/** + * Rescale a 64-bit integer with rounding to nearest. + * + * The operation is mathematically equivalent to `a * b / c`, but writing that + * directly can overflow. + * + * This function is equivalent to av_rescale_rnd() with #AV_ROUND_NEAR_INF. + * + * @see av_rescale_rnd(), av_rescale_q(), av_rescale_q_rnd() + */ +int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const; + +/** + * Rescale a 64-bit integer with specified rounding. + * + * The operation is mathematically equivalent to `a * b / c`, but writing that + * directly can overflow, and does not support different rounding methods. + * If the result is not representable then INT64_MIN is returned. + * + * @see av_rescale(), av_rescale_q(), av_rescale_q_rnd() + */ +int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers. + * + * The operation is mathematically equivalent to `a * bq / cq`. + * + * This function is equivalent to av_rescale_q_rnd() with #AV_ROUND_NEAR_INF. + * + * @see av_rescale(), av_rescale_rnd(), av_rescale_q_rnd() + */ +int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers with specified rounding. + * + * The operation is mathematically equivalent to `a * bq / cq`. + * + * @see av_rescale(), av_rescale_rnd(), av_rescale_q() + */ +int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, + enum AVRounding rnd) av_const; + +/** + * Compare two timestamps each in its own time base. + * + * @return One of the following values: + * - -1 if `ts_a` is before `ts_b` + * - 1 if `ts_a` is after `ts_b` + * - 0 if they represent the same position + * + * @warning + * The result of the function is undefined if one of the timestamps is outside + * the `int64_t` range when represented in the other's timebase. + */ +int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b); + +/** + * Compare the remainders of two integer operands divided by a common divisor. + * + * In other words, compare the least significant `log2(mod)` bits of integers + * `a` and `b`. + * + * @code{.c} + * av_compare_mod(0x11, 0x02, 0x10) < 0 // since 0x11 % 0x10 (0x1) < 0x02 % 0x10 (0x2) + * av_compare_mod(0x11, 0x02, 0x20) > 0 // since 0x11 % 0x20 (0x11) > 0x02 % 0x20 (0x02) + * @endcode + * + * @param a Operand + * @param b Operand + * @param mod Divisor; must be a power of 2 + * @return + * - a negative value if `a % mod < b % mod` + * - a positive value if `a % mod > b % mod` + * - zero if `a % mod == b % mod` + */ +int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod); + +/** + * Rescale a timestamp while preserving known durations. + * + * This function is designed to be called per audio packet to scale the input + * timestamp to a different time base. Compared to a simple av_rescale_q() + * call, this function is robust against possible inconsistent frame durations. + * + * The `last` parameter is a state variable that must be preserved for all + * subsequent calls for the same stream. For the first call, `*last` should be + * initialized to #AV_NOPTS_VALUE. + * + * @param[in] in_tb Input time base + * @param[in] in_ts Input timestamp + * @param[in] fs_tb Duration time base; typically this is finer-grained + * (greater) than `in_tb` and `out_tb` + * @param[in] duration Duration till the next call to this function (i.e. + * duration of the current packet/frame) + * @param[in,out] last Pointer to a timestamp expressed in terms of + * `fs_tb`, acting as a state variable + * @param[in] out_tb Output timebase + * @return Timestamp expressed in terms of `out_tb` + * + * @note In the context of this function, "duration" is in term of samples, not + * seconds. + */ +int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb); + +/** + * Add a value to a timestamp. + * + * This function guarantees that when the same value is repeatly added that + * no accumulation of rounding errors occurs. + * + * @param[in] ts Input timestamp + * @param[in] ts_tb Input timestamp time base + * @param[in] inc Value to be added + * @param[in] inc_tb Time base of `inc` + */ +int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc); + +/** + * 0th order modified bessel function of the first kind. + */ +double av_bessel_i0(double x); + +/** + * @} + */ + +#endif /* AVUTIL_MATHEMATICS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/mem.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/mem.h new file mode 100644 index 0000000000000..ab7648ac5705f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/mem.h @@ -0,0 +1,607 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_mem + * Memory handling functions + */ + +#ifndef AVUTIL_MEM_H +#define AVUTIL_MEM_H + +#include +#include + +#include "attributes.h" + +/** + * @addtogroup lavu_mem + * Utilities for manipulating memory. + * + * FFmpeg has several applications of memory that are not required of a typical + * program. For example, the computing-heavy components like video decoding and + * encoding can be sped up significantly through the use of aligned memory. + * + * However, for each of FFmpeg's applications of memory, there might not be a + * recognized or standardized API for that specific use. Memory alignment, for + * instance, varies wildly depending on operating systems, architectures, and + * compilers. Hence, this component of @ref libavutil is created to make + * dealing with memory consistently possible on all platforms. + * + * @{ + */ + +/** + * @defgroup lavu_mem_attrs Function Attributes + * Function attributes applicable to memory handling functions. + * + * These function attributes can help compilers emit more useful warnings, or + * generate better code. + * @{ + */ + +/** + * @def av_malloc_attrib + * Function attribute denoting a malloc-like function. + * + * @see Function attribute `malloc` in GCC's documentation + */ + +#if AV_GCC_VERSION_AT_LEAST(3,1) + #define av_malloc_attrib __attribute__((__malloc__)) +#else + #define av_malloc_attrib +#endif + +/** + * @def av_alloc_size(...) + * Function attribute used on a function that allocates memory, whose size is + * given by the specified parameter(s). + * + * @code{.c} + * void *av_malloc(size_t size) av_alloc_size(1); + * void *av_calloc(size_t nmemb, size_t size) av_alloc_size(1, 2); + * @endcode + * + * @param ... One or two parameter indexes, separated by a comma + * + * @see Function attribute `alloc_size` in GCC's documentation + */ + +#if AV_GCC_VERSION_AT_LEAST(4,3) + #define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__))) +#else + #define av_alloc_size(...) +#endif + +/** + * @} + */ + +/** + * @defgroup lavu_mem_funcs Heap Management + * Functions responsible for allocating, freeing, and copying memory. + * + * All memory allocation functions have a built-in upper limit of `INT_MAX` + * bytes. This may be changed with av_max_alloc(), although exercise extreme + * caution when doing so. + * + * @{ + */ + +/** + * Allocate a memory block with alignment suitable for all memory accesses + * (including vectors if available on the CPU). + * + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * @see av_mallocz() + */ +void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a memory block with alignment suitable for all memory accesses + * (including vectors if available on the CPU) and zero all the bytes of the + * block. + * + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if it cannot be allocated + * @see av_malloc() + */ +void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a memory block for an array with av_malloc(). + * + * The allocated memory will have size `size * nmemb` bytes. + * + * @param nmemb Number of element + * @param size Size of a single element + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * @see av_malloc() + */ +av_alloc_size(1, 2) void *av_malloc_array(size_t nmemb, size_t size); + +/** + * Allocate a memory block for an array with av_mallocz(). + * + * The allocated memory will have size `size * nmemb` bytes. + * + * @param nmemb Number of elements + * @param size Size of the single element + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * + * @see av_mallocz() + * @see av_malloc_array() + */ +void *av_calloc(size_t nmemb, size_t size) av_malloc_attrib av_alloc_size(1, 2); + +/** + * Allocate, reallocate, or free a block of memory. + * + * If `ptr` is `NULL` and `size` > 0, allocate a new block. Otherwise, expand or + * shrink that block of memory according to `size`. + * + * @param ptr Pointer to a memory block already allocated with + * av_realloc() or `NULL` + * @param size Size in bytes of the memory block to be allocated or + * reallocated + * + * @return Pointer to a newly-reallocated block or `NULL` if the block + * cannot be reallocated + * + * @warning Unlike av_malloc(), the returned pointer is not guaranteed to be + * correctly aligned. The returned pointer must be freed after even + * if size is zero. + * @see av_fast_realloc() + * @see av_reallocp() + */ +void *av_realloc(void *ptr, size_t size) av_alloc_size(2); + +/** + * Allocate, reallocate, or free a block of memory through a pointer to a + * pointer. + * + * If `*ptr` is `NULL` and `size` > 0, allocate a new block. If `size` is + * zero, free the memory block pointed to by `*ptr`. Otherwise, expand or + * shrink that block of memory according to `size`. + * + * @param[in,out] ptr Pointer to a pointer to a memory block already allocated + * with av_realloc(), or a pointer to `NULL`. The pointer + * is updated on success, or freed on failure. + * @param[in] size Size in bytes for the memory block to be allocated or + * reallocated + * + * @return Zero on success, an AVERROR error code on failure + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. + */ +av_warn_unused_result +int av_reallocp(void *ptr, size_t size); + +/** + * Allocate, reallocate, or free a block of memory. + * + * This function does the same thing as av_realloc(), except: + * - It takes two size arguments and allocates `nelem * elsize` bytes, + * after checking the result of the multiplication for integer overflow. + * - It frees the input block in case of failure, thus avoiding the memory + * leak with the classic + * @code{.c} + * buf = realloc(buf); + * if (!buf) + * return -1; + * @endcode + * pattern. + */ +void *av_realloc_f(void *ptr, size_t nelem, size_t elsize); + +/** + * Allocate, reallocate, or free an array. + * + * If `ptr` is `NULL` and `nmemb` > 0, allocate a new block. + * + * @param ptr Pointer to a memory block already allocated with + * av_realloc() or `NULL` + * @param nmemb Number of elements in the array + * @param size Size of the single element of the array + * + * @return Pointer to a newly-reallocated block or NULL if the block + * cannot be reallocated + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. The returned pointer must be freed after even if + * nmemb is zero. + * @see av_reallocp_array() + */ +av_alloc_size(2, 3) void *av_realloc_array(void *ptr, size_t nmemb, size_t size); + +/** + * Allocate, reallocate an array through a pointer to a pointer. + * + * If `*ptr` is `NULL` and `nmemb` > 0, allocate a new block. + * + * @param[in,out] ptr Pointer to a pointer to a memory block already + * allocated with av_realloc(), or a pointer to `NULL`. + * The pointer is updated on success, or freed on failure. + * @param[in] nmemb Number of elements + * @param[in] size Size of the single element + * + * @return Zero on success, an AVERROR error code on failure + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. *ptr must be freed after even if nmemb is zero. + */ +int av_reallocp_array(void *ptr, size_t nmemb, size_t size); + +/** + * Reallocate the given buffer if it is not large enough, otherwise do nothing. + * + * If the given buffer is `NULL`, then a new uninitialized buffer is allocated. + * + * If the given buffer is not large enough, and reallocation fails, `NULL` is + * returned and `*size` is set to 0, but the original buffer is not changed or + * freed. + * + * A typical use pattern follows: + * + * @code{.c} + * uint8_t *buf = ...; + * uint8_t *new_buf = av_fast_realloc(buf, ¤t_size, size_needed); + * if (!new_buf) { + * // Allocation failed; clean up original buffer + * av_freep(&buf); + * return AVERROR(ENOMEM); + * } + * @endcode + * + * @param[in,out] ptr Already allocated buffer, or `NULL` + * @param[in,out] size Pointer to the size of buffer `ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `ptr` + * @return `ptr` if the buffer is large enough, a pointer to newly reallocated + * buffer if the buffer was not large enough, or `NULL` in case of + * error + * @see av_realloc() + * @see av_fast_malloc() + */ +void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate a buffer, reusing the given one if large enough. + * + * Contrary to av_fast_realloc(), the current buffer contents might not be + * preserved and on error the old buffer is freed, thus no special handling to + * avoid memleaks is necessary. + * + * `*ptr` is allowed to be `NULL`, in which case allocation always happens if + * `size_needed` is greater than 0. + * + * @code{.c} + * uint8_t *buf = ...; + * av_fast_malloc(&buf, ¤t_size, size_needed); + * if (!buf) { + * // Allocation failed; buf already freed + * return AVERROR(ENOMEM); + * } + * @endcode + * + * @param[in,out] ptr Pointer to pointer to an already allocated buffer. + * `*ptr` will be overwritten with pointer to new + * buffer on success or `NULL` on failure + * @param[in,out] size Pointer to the size of buffer `*ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `*ptr` + * @see av_realloc() + * @see av_fast_mallocz() + */ +void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate and clear a buffer, reusing the given one if large enough. + * + * Like av_fast_malloc(), but all newly allocated space is initially cleared. + * Reused buffer is not cleared. + * + * `*ptr` is allowed to be `NULL`, in which case allocation always happens if + * `size_needed` is greater than 0. + * + * @param[in,out] ptr Pointer to pointer to an already allocated buffer. + * `*ptr` will be overwritten with pointer to new + * buffer on success or `NULL` on failure + * @param[in,out] size Pointer to the size of buffer `*ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `*ptr` + * @see av_fast_malloc() + */ +void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * Free a memory block which has been allocated with a function of av_malloc() + * or av_realloc() family. + * + * @param ptr Pointer to the memory block which should be freed. + * + * @note `ptr = NULL` is explicitly allowed. + * @note It is recommended that you use av_freep() instead, to prevent leaving + * behind dangling pointers. + * @see av_freep() + */ +void av_free(void *ptr); + +/** + * Free a memory block which has been allocated with a function of av_malloc() + * or av_realloc() family, and set the pointer pointing to it to `NULL`. + * + * @code{.c} + * uint8_t *buf = av_malloc(16); + * av_free(buf); + * // buf now contains a dangling pointer to freed memory, and accidental + * // dereference of buf will result in a use-after-free, which may be a + * // security risk. + * + * uint8_t *buf = av_malloc(16); + * av_freep(&buf); + * // buf is now NULL, and accidental dereference will only result in a + * // NULL-pointer dereference. + * @endcode + * + * @param ptr Pointer to the pointer to the memory block which should be freed + * @note `*ptr = NULL` is safe and leads to no action. + * @see av_free() + */ +void av_freep(void *ptr); + +/** + * Duplicate a string. + * + * @param s String to be duplicated + * @return Pointer to a newly-allocated string containing a + * copy of `s` or `NULL` if the string cannot be allocated + * @see av_strndup() + */ +char *av_strdup(const char *s) av_malloc_attrib; + +/** + * Duplicate a substring of a string. + * + * @param s String to be duplicated + * @param len Maximum length of the resulting string (not counting the + * terminating byte) + * @return Pointer to a newly-allocated string containing a + * substring of `s` or `NULL` if the string cannot be allocated + */ +char *av_strndup(const char *s, size_t len) av_malloc_attrib; + +/** + * Duplicate a buffer with av_malloc(). + * + * @param p Buffer to be duplicated + * @param size Size in bytes of the buffer copied + * @return Pointer to a newly allocated buffer containing a + * copy of `p` or `NULL` if the buffer cannot be allocated + */ +void *av_memdup(const void *p, size_t size); + +/** + * Overlapping memcpy() implementation. + * + * @param dst Destination buffer + * @param back Number of bytes back to start copying (i.e. the initial size of + * the overlapping window); must be > 0 + * @param cnt Number of bytes to copy; must be >= 0 + * + * @note `cnt > back` is valid, this will copy the bytes we just copied, + * thus creating a repeating pattern with a period length of `back`. + */ +void av_memcpy_backptr(uint8_t *dst, int back, int cnt); + +/** + * @} + */ + +/** + * @defgroup lavu_mem_dynarray Dynamic Array + * + * Utilities to make an array grow when needed. + * + * Sometimes, the programmer would want to have an array that can grow when + * needed. The libavutil dynamic array utilities fill that need. + * + * libavutil supports two systems of appending elements onto a dynamically + * allocated array, the first one storing the pointer to the value in the + * array, and the second storing the value directly. In both systems, the + * caller is responsible for maintaining a variable containing the length of + * the array, as well as freeing of the array after use. + * + * The first system stores pointers to values in a block of dynamically + * allocated memory. Since only pointers are stored, the function does not need + * to know the size of the type. Both av_dynarray_add() and + * av_dynarray_add_nofree() implement this system. + * + * @code + * type **array = NULL; //< an array of pointers to values + * int nb = 0; //< a variable to keep track of the length of the array + * + * type to_be_added = ...; + * type to_be_added2 = ...; + * + * av_dynarray_add(&array, &nb, &to_be_added); + * if (nb == 0) + * return AVERROR(ENOMEM); + * + * av_dynarray_add(&array, &nb, &to_be_added2); + * if (nb == 0) + * return AVERROR(ENOMEM); + * + * // Now: + * // nb == 2 + * // &to_be_added == array[0] + * // &to_be_added2 == array[1] + * + * av_freep(&array); + * @endcode + * + * The second system stores the value directly in a block of memory. As a + * result, the function has to know the size of the type. av_dynarray2_add() + * implements this mechanism. + * + * @code + * type *array = NULL; //< an array of values + * int nb = 0; //< a variable to keep track of the length of the array + * + * type to_be_added = ...; + * type to_be_added2 = ...; + * + * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), NULL); + * if (!addr) + * return AVERROR(ENOMEM); + * memcpy(addr, &to_be_added, sizeof(to_be_added)); + * + * // Shortcut of the above. + * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), + * (const void *)&to_be_added2); + * if (!addr) + * return AVERROR(ENOMEM); + * + * // Now: + * // nb == 2 + * // to_be_added == array[0] + * // to_be_added2 == array[1] + * + * av_freep(&array); + * @endcode + * + * @{ + */ + +/** + * Add the pointer to an element to a dynamic array. + * + * The array to grow is supposed to be an array of pointers to + * structures, and the element to add must be a pointer to an already + * allocated structure. + * + * The array is reallocated when its size reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the number pointed to by `nb_ptr` + * is incremented. + * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and + * `*nb_ptr` is set to 0. + * + * @param[in,out] tab_ptr Pointer to the array to grow + * @param[in,out] nb_ptr Pointer to the number of elements in the array + * @param[in] elem Element to add + * @see av_dynarray_add_nofree(), av_dynarray2_add() + */ +void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element to a dynamic array. + * + * Function has the same functionality as av_dynarray_add(), + * but it doesn't free memory on fails. It returns error code + * instead and leave current buffer untouched. + * + * @return >=0 on success, negative otherwise + * @see av_dynarray_add(), av_dynarray2_add() + */ +av_warn_unused_result +int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element of size `elem_size` to a dynamic array. + * + * The array is reallocated when its number of elements reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the number pointed to by `nb_ptr` + * is incremented. + * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and + * `*nb_ptr` is set to 0. + * + * @param[in,out] tab_ptr Pointer to the array to grow + * @param[in,out] nb_ptr Pointer to the number of elements in the array + * @param[in] elem_size Size in bytes of an element in the array + * @param[in] elem_data Pointer to the data of the element to add. If + * `NULL`, the space of the newly added element is + * allocated but left uninitialized. + * + * @return Pointer to the data of the element to copy in the newly allocated + * space + * @see av_dynarray_add(), av_dynarray_add_nofree() + */ +void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, + const uint8_t *elem_data); + +/** + * @} + */ + +/** + * @defgroup lavu_mem_misc Miscellaneous Functions + * + * Other functions related to memory allocation. + * + * @{ + */ + +/** + * Multiply two `size_t` values checking for overflow. + * + * @param[in] a Operand of multiplication + * @param[in] b Operand of multiplication + * @param[out] r Pointer to the result of the operation + * @return 0 on success, AVERROR(EINVAL) on overflow + */ +int av_size_mult(size_t a, size_t b, size_t *r); + +/** + * Set the maximum size that may be allocated in one block. + * + * The value specified with this function is effective for all libavutil's @ref + * lavu_mem_funcs "heap management functions." + * + * By default, the max value is defined as `INT_MAX`. + * + * @param max Value to be set as the new maximum size + * + * @warning Exercise extreme caution when using this function. Don't touch + * this if you do not understand the full consequence of doing so. + */ +void av_max_alloc(size_t max); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_MEM_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/opt.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/opt.h new file mode 100644 index 0000000000000..e6013662f6cac --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/opt.h @@ -0,0 +1,998 @@ +/* + * AVOptions + * copyright (c) 2005 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_OPT_H +#define AVUTIL_OPT_H + +/** + * @file + * AVOptions + */ + +#include "rational.h" +#include "avutil.h" +#include "channel_layout.h" +#include "dict.h" +#include "log.h" +#include "pixfmt.h" +#include "samplefmt.h" + +/** + * @defgroup avoptions AVOptions + * @ingroup lavu_data + * @{ + * AVOptions provide a generic system to declare options on arbitrary structs + * ("objects"). An option can have a help text, a type and a range of possible + * values. Options may then be enumerated, read and written to. + * + * There are two modes of access to members of AVOption and its child structs. + * One is called 'native access', and refers to access from the code that + * declares the AVOption in question. The other is 'foreign access', and refers + * to access from other code. + * + * Certain struct members in this header are documented as 'native access only' + * or similar - it means that only the code that declared the AVOption in + * question is allowed to access the field. This allows us to extend the + * semantics of those fields without breaking API compatibility. + * + * @section avoptions_implement Implementing AVOptions + * This section describes how to add AVOptions capabilities to a struct. + * + * All AVOptions-related information is stored in an AVClass. Therefore + * the first member of the struct should be a pointer to an AVClass describing it. + * The option field of the AVClass must be set to a NULL-terminated static array + * of AVOptions. Each AVOption must have a non-empty name, a type, a default + * value and for number-type AVOptions also a range of allowed values. It must + * also declare an offset in bytes from the start of the struct, where the field + * associated with this AVOption is located. Other fields in the AVOption struct + * should also be set when applicable, but are not required. + * + * The following example illustrates an AVOptions-enabled struct: + * @code + * typedef struct test_struct { + * const AVClass *class; + * int int_opt; + * char *str_opt; + * uint8_t *bin_opt; + * int bin_len; + * } test_struct; + * + * static const AVOption test_options[] = { + * { "test_int", "This is a test option of int type.", offsetof(test_struct, int_opt), + * AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX }, + * { "test_str", "This is a test option of string type.", offsetof(test_struct, str_opt), + * AV_OPT_TYPE_STRING }, + * { "test_bin", "This is a test option of binary type.", offsetof(test_struct, bin_opt), + * AV_OPT_TYPE_BINARY }, + * { NULL }, + * }; + * + * static const AVClass test_class = { + * .class_name = "test class", + * .item_name = av_default_item_name, + * .option = test_options, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * @endcode + * + * Next, when allocating your struct, you must ensure that the AVClass pointer + * is set to the correct value. Then, av_opt_set_defaults() can be called to + * initialize defaults. After that the struct is ready to be used with the + * AVOptions API. + * + * When cleaning up, you may use the av_opt_free() function to automatically + * free all the allocated string and binary options. + * + * Continuing with the above example: + * + * @code + * test_struct *alloc_test_struct(void) + * { + * test_struct *ret = av_mallocz(sizeof(*ret)); + * ret->class = &test_class; + * av_opt_set_defaults(ret); + * return ret; + * } + * void free_test_struct(test_struct **foo) + * { + * av_opt_free(*foo); + * av_freep(foo); + * } + * @endcode + * + * @subsection avoptions_implement_nesting Nesting + * It may happen that an AVOptions-enabled struct contains another + * AVOptions-enabled struct as a member (e.g. AVCodecContext in + * libavcodec exports generic options, while its priv_data field exports + * codec-specific options). In such a case, it is possible to set up the + * parent struct to export a child's options. To do that, simply + * implement AVClass.child_next() and AVClass.child_class_iterate() in the + * parent struct's AVClass. + * Assuming that the test_struct from above now also contains a + * child_struct field: + * + * @code + * typedef struct child_struct { + * AVClass *class; + * int flags_opt; + * } child_struct; + * static const AVOption child_opts[] = { + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX }, + * { NULL }, + * }; + * static const AVClass child_class = { + * .class_name = "child class", + * .item_name = av_default_item_name, + * .option = child_opts, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * + * void *child_next(void *obj, void *prev) + * { + * test_struct *t = obj; + * if (!prev && t->child_struct) + * return t->child_struct; + * return NULL + * } + * const AVClass child_class_iterate(void **iter) + * { + * const AVClass *c = *iter ? NULL : &child_class; + * *iter = (void*)(uintptr_t)c; + * return c; + * } + * @endcode + * Putting child_next() and child_class_iterate() as defined above into + * test_class will now make child_struct's options accessible through + * test_struct (again, proper setup as described above needs to be done on + * child_struct right after it is created). + * + * From the above example it might not be clear why both child_next() + * and child_class_iterate() are needed. The distinction is that child_next() + * iterates over actually existing objects, while child_class_iterate() + * iterates over all possible child classes. E.g. if an AVCodecContext + * was initialized to use a codec which has private options, then its + * child_next() will return AVCodecContext.priv_data and finish + * iterating. OTOH child_class_iterate() on AVCodecContext.av_class will + * iterate over all available codecs with private options. + * + * @subsection avoptions_implement_named_constants Named constants + * It is possible to create named constants for options. Simply set the unit + * field of the option the constants should apply to a string and + * create the constants themselves as options of type AV_OPT_TYPE_CONST + * with their unit field set to the same string. + * Their default_val field should contain the value of the named + * constant. + * For example, to add some named constants for the test_flags option + * above, put the following into the child_opts array: + * @code + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, "test_unit" }, + * { "flag1", "This is a flag with value 16", 0, AV_OPT_TYPE_CONST, { .i64 = 16 }, 0, 0, "test_unit" }, + * @endcode + * + * @section avoptions_use Using AVOptions + * This section deals with accessing options in an AVOptions-enabled struct. + * Such structs in FFmpeg are e.g. AVCodecContext in libavcodec or + * AVFormatContext in libavformat. + * + * @subsection avoptions_use_examine Examining AVOptions + * The basic functions for examining options are av_opt_next(), which iterates + * over all options defined for one object, and av_opt_find(), which searches + * for an option with the given name. + * + * The situation is more complicated with nesting. An AVOptions-enabled struct + * may have AVOptions-enabled children. Passing the AV_OPT_SEARCH_CHILDREN flag + * to av_opt_find() will make the function search children recursively. + * + * For enumerating there are basically two cases. The first is when you want to + * get all options that may potentially exist on the struct and its children + * (e.g. when constructing documentation). In that case you should call + * av_opt_child_class_iterate() recursively on the parent struct's AVClass. The + * second case is when you have an already initialized struct with all its + * children and you want to get all options that can be actually written or read + * from it. In that case you should call av_opt_child_next() recursively (and + * av_opt_next() on each result). + * + * @subsection avoptions_use_get_set Reading and writing AVOptions + * When setting options, you often have a string read directly from the + * user. In such a case, simply passing it to av_opt_set() is enough. For + * non-string type options, av_opt_set() will parse the string according to the + * option type. + * + * Similarly av_opt_get() will read any option type and convert it to a string + * which will be returned. Do not forget that the string is allocated, so you + * have to free it with av_free(). + * + * In some cases it may be more convenient to put all options into an + * AVDictionary and call av_opt_set_dict() on it. A specific case of this + * are the format/codec open functions in lavf/lavc which take a dictionary + * filled with option as a parameter. This makes it possible to set some options + * that cannot be set otherwise, since e.g. the input file format is not known + * before the file is actually opened. + */ + +enum AVOptionType{ + AV_OPT_TYPE_FLAGS = 1, + AV_OPT_TYPE_INT, + AV_OPT_TYPE_INT64, + AV_OPT_TYPE_DOUBLE, + AV_OPT_TYPE_FLOAT, + AV_OPT_TYPE_STRING, + AV_OPT_TYPE_RATIONAL, + AV_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length + AV_OPT_TYPE_DICT, + AV_OPT_TYPE_UINT64, + AV_OPT_TYPE_CONST, + AV_OPT_TYPE_IMAGE_SIZE, ///< offset must point to two consecutive integers + AV_OPT_TYPE_PIXEL_FMT, + AV_OPT_TYPE_SAMPLE_FMT, + AV_OPT_TYPE_VIDEO_RATE, ///< offset must point to AVRational + AV_OPT_TYPE_DURATION, + AV_OPT_TYPE_COLOR, + AV_OPT_TYPE_BOOL, + AV_OPT_TYPE_CHLAYOUT, + + /** + * May be combined with another regular option type to declare an array + * option. + * + * For array options, @ref AVOption.offset should refer to a pointer + * corresponding to the option type. The pointer should be immediately + * followed by an unsigned int that will store the number of elements in the + * array. + */ + AV_OPT_TYPE_FLAG_ARRAY = (1 << 16), +}; + +/** + * A generic parameter which can be set by the user for muxing or encoding. + */ +#define AV_OPT_FLAG_ENCODING_PARAM (1 << 0) +/** + * A generic parameter which can be set by the user for demuxing or decoding. + */ +#define AV_OPT_FLAG_DECODING_PARAM (1 << 1) +#define AV_OPT_FLAG_AUDIO_PARAM (1 << 3) +#define AV_OPT_FLAG_VIDEO_PARAM (1 << 4) +#define AV_OPT_FLAG_SUBTITLE_PARAM (1 << 5) +/** + * The option is intended for exporting values to the caller. + */ +#define AV_OPT_FLAG_EXPORT (1 << 6) +/** + * The option may not be set through the AVOptions API, only read. + * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set. + */ +#define AV_OPT_FLAG_READONLY (1 << 7) +/** + * A generic parameter which can be set by the user for bit stream filtering. + */ +#define AV_OPT_FLAG_BSF_PARAM (1 << 8) + +/** + * A generic parameter which can be set by the user at runtime. + */ +#define AV_OPT_FLAG_RUNTIME_PARAM (1 << 15) +/** + * A generic parameter which can be set by the user for filtering. + */ +#define AV_OPT_FLAG_FILTERING_PARAM (1 << 16) +/** + * Set if option is deprecated, users should refer to AVOption.help text for + * more information. + */ +#define AV_OPT_FLAG_DEPRECATED (1 << 17) +/** + * Set if option constants can also reside in child objects. + */ +#define AV_OPT_FLAG_CHILD_CONSTS (1 << 18) + +/** + * May be set as default_val for AV_OPT_TYPE_FLAG_ARRAY options. + */ +typedef struct AVOptionArrayDef { + /** + * Native access only. + * + * Default value of the option, as would be serialized by av_opt_get() (i.e. + * using the value of sep as the separator). + */ + const char *def; + + /** + * Minimum number of elements in the array. When this field is non-zero, def + * must be non-NULL and contain at least this number of elements. + */ + unsigned size_min; + /** + * Maximum number of elements in the array, 0 when unlimited. + */ + unsigned size_max; + + /** + * Separator between array elements in string representations of this + * option, used by av_opt_set() and av_opt_get(). It must be a printable + * ASCII character, excluding alphanumeric and the backslash. A comma is + * used when sep=0. + * + * The separator and the backslash must be backslash-escaped in order to + * appear in string representations of the option value. + */ + char sep; +} AVOptionArrayDef; + +/** + * AVOption + */ +typedef struct AVOption { + const char *name; + + /** + * short English help text + * @todo What about other languages? + */ + const char *help; + + /** + * Native access only. + * + * The offset relative to the context structure where the option + * value is stored. It should be 0 for named constants. + */ + int offset; + enum AVOptionType type; + + /** + * Native access only, except when documented otherwise. + * the default value for scalar options + */ + union { + int64_t i64; + double dbl; + const char *str; + /* TODO those are unused now */ + AVRational q; + + /** + * Used for AV_OPT_TYPE_FLAG_ARRAY options. May be NULL. + * + * Foreign access to some members allowed, as noted in AVOptionArrayDef + * documentation. + */ + const AVOptionArrayDef *arr; + } default_val; + double min; ///< minimum valid value for the option + double max; ///< maximum valid value for the option + + /** + * A combination of AV_OPT_FLAG_*. + */ + int flags; + + /** + * The logical unit to which the option belongs. Non-constant + * options and corresponding named constants share the same + * unit. May be NULL. + */ + const char *unit; +} AVOption; + +/** + * A single allowed range of values, or a single allowed value. + */ +typedef struct AVOptionRange { + const char *str; + /** + * Value range. + * For string ranges this represents the min/max length. + * For dimensions this represents the min/max pixel count or width/height in multi-component case. + */ + double value_min, value_max; + /** + * Value's component range. + * For string this represents the unicode range for chars, 0-127 limits to ASCII. + */ + double component_min, component_max; + /** + * Range flag. + * If set to 1 the struct encodes a range, if set to 0 a single value. + */ + int is_range; +} AVOptionRange; + +/** + * List of AVOptionRange structs. + */ +typedef struct AVOptionRanges { + /** + * Array of option ranges. + * + * Most of option types use just one component. + * Following describes multi-component option types: + * + * AV_OPT_TYPE_IMAGE_SIZE: + * component index 0: range of pixel count (width * height). + * component index 1: range of width. + * component index 2: range of height. + * + * @note To obtain multi-component version of this structure, user must + * provide AV_OPT_MULTI_COMPONENT_RANGE to av_opt_query_ranges or + * av_opt_query_ranges_default function. + * + * Multi-component range can be read as in following example: + * + * @code + * int range_index, component_index; + * AVOptionRanges *ranges; + * AVOptionRange *range[3]; //may require more than 3 in the future. + * av_opt_query_ranges(&ranges, obj, key, AV_OPT_MULTI_COMPONENT_RANGE); + * for (range_index = 0; range_index < ranges->nb_ranges; range_index++) { + * for (component_index = 0; component_index < ranges->nb_components; component_index++) + * range[component_index] = ranges->range[ranges->nb_ranges * component_index + range_index]; + * //do something with range here. + * } + * av_opt_freep_ranges(&ranges); + * @endcode + */ + AVOptionRange **range; + /** + * Number of ranges per component. + */ + int nb_ranges; + /** + * Number of componentes. + */ + int nb_components; +} AVOptionRanges; + +/** + * @defgroup opt_mng AVOption (un)initialization and inspection. + * @{ + */ + +/** + * Set the values of all AVOption fields to their default values. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + */ +void av_opt_set_defaults(void *s); + +/** + * Set the values of all AVOption fields to their default values. Only these + * AVOption fields for which (opt->flags & mask) == flags will have their + * default applied to s. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + * @param mask combination of AV_OPT_FLAG_* + * @param flags combination of AV_OPT_FLAG_* + */ +void av_opt_set_defaults2(void *s, int mask, int flags); + +/** + * Free all allocated objects in obj. + */ +void av_opt_free(void *obj); + +/** + * Iterate over all AVOptions belonging to obj. + * + * @param obj an AVOptions-enabled struct or a double pointer to an + * AVClass describing it. + * @param prev result of the previous call to av_opt_next() on this object + * or NULL + * @return next AVOption or NULL + */ +const AVOption *av_opt_next(const void *obj, const AVOption *prev); + +/** + * Iterate over AVOptions-enabled children of obj. + * + * @param prev result of a previous call to this function or NULL + * @return next AVOptions-enabled child or NULL + */ +void *av_opt_child_next(void *obj, void *prev); + +/** + * Iterate over potential AVOptions-enabled children of parent. + * + * @param iter a pointer where iteration state is stored. + * @return AVClass corresponding to next potential child or NULL + */ +const AVClass *av_opt_child_class_iterate(const AVClass *parent, void **iter); + +#define AV_OPT_SEARCH_CHILDREN (1 << 0) /**< Search in possible children of the + given object first. */ +/** + * The obj passed to av_opt_find() is fake -- only a double pointer to AVClass + * instead of a required pointer to a struct containing AVClass. This is + * useful for searching for options without needing to allocate the corresponding + * object. + */ +#define AV_OPT_SEARCH_FAKE_OBJ (1 << 1) + +/** + * In av_opt_get, return NULL if the option has a pointer type and is set to NULL, + * rather than returning an empty string. + */ +#define AV_OPT_ALLOW_NULL (1 << 2) + +/** + * Allows av_opt_query_ranges and av_opt_query_ranges_default to return more than + * one component for certain option types. + * @see AVOptionRanges for details. + */ +#define AV_OPT_MULTI_COMPONENT_RANGE (1 << 12) + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return A pointer to the option found, or NULL if no option + * was found. + * + * @note Options found with AV_OPT_SEARCH_CHILDREN flag may not be settable + * directly with av_opt_set(). Use special calls which take an options + * AVDictionary (e.g. avformat_open_input()) to set options found with this + * flag. + */ +const AVOption *av_opt_find(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags); + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * @param[out] target_obj if non-NULL, an object to which the option belongs will be + * written here. It may be different from obj if AV_OPT_SEARCH_CHILDREN is present + * in search_flags. This parameter is ignored if search_flags contain + * AV_OPT_SEARCH_FAKE_OBJ. + * + * @return A pointer to the option found, or NULL if no option + * was found. + */ +const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags, void **target_obj); + +/** + * Show the obj options. + * + * @param req_flags requested flags for the options to show. Show only the + * options for which it is opt->flags & req_flags. + * @param rej_flags rejected flags for the options to show. Show only the + * options for which it is !(opt->flags & req_flags). + * @param av_log_obj log context to use for showing the options + */ +int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); + +/** + * Extract a key-value pair from the beginning of a string. + * + * @param ropts pointer to the options string, will be updated to + * point to the rest of the string (one of the pairs_sep + * or the final NUL) + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @param flags flags; see the AV_OPT_FLAG_* values below + * @param rkey parsed key; must be freed using av_free() + * @param rval parsed value; must be freed using av_free() + * + * @return >=0 for success, or a negative value corresponding to an + * AVERROR code in case of error; in particular: + * AVERROR(EINVAL) if no key is present + * + */ +int av_opt_get_key_value(const char **ropts, + const char *key_val_sep, const char *pairs_sep, + unsigned flags, + char **rkey, char **rval); + +enum { + + /** + * Accept to parse a value without a key; the key will then be returned + * as NULL. + */ + AV_OPT_FLAG_IMPLICIT_KEY = 1, +}; + +/** + * @} + */ + +/** + * @defgroup opt_write Setting and modifying option values + * @{ + */ + +/** + * Parse the key/value pairs list in opts. For each key/value pair + * found, stores the value in the field in ctx that is named like the + * key. ctx must be an AVClass context, storing is done using + * AVOptions. + * + * @param opts options string to parse, may be NULL + * @param key_val_sep a 0-terminated list of characters used to + * separate key from value + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other + * @return the number of successfully set key/value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_opt_set() if a key/value pair + * cannot be set + */ +int av_set_options_string(void *ctx, const char *opts, + const char *key_val_sep, const char *pairs_sep); + +/** + * Parse the key-value pairs list in opts. For each key=value pair found, + * set the value of the corresponding option in ctx. + * + * @param ctx the AVClass object to set options on + * @param opts the options string, key-value pairs separated by a + * delimiter + * @param shorthand a NULL-terminated array of options names for shorthand + * notation: if the first field in opts has no key part, + * the key is taken from the first element of shorthand; + * then again for the second, etc., until either opts is + * finished, shorthand is finished or a named option is + * found; after that, all options must be named + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @return the number of successfully set key=value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_set_string3() if a key/value pair + * cannot be set + * + * Options names must use only the following characters: a-z A-Z 0-9 - . / _ + * Separators must use characters distinct from option names and from each + * other. + */ +int av_opt_set_from_string(void *ctx, const char *opts, + const char *const *shorthand, + const char *key_val_sep, const char *pairs_sep); + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict(void *obj, struct AVDictionary **options); + + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags); + +/** + * Copy options from src object into dest object. + * + * The underlying AVClass of both src and dest must coincide. The guarantee + * below does not apply if this is not fulfilled. + * + * Options that require memory allocation (e.g. string or binary) are malloc'ed in dest object. + * Original memory allocated for such options is freed unless both src and dest options points to the same memory. + * + * Even on error it is guaranteed that allocated options from src and dest + * no longer alias each other afterwards; in particular calling av_opt_free() + * on both src and dest is safe afterwards if dest has been memdup'ed from src. + * + * @param dest Object to copy from + * @param src Object to copy into + * @return 0 on success, negative on error + */ +int av_opt_copy(void *dest, const void *src); + +/** + * @defgroup opt_set_funcs Option setting functions + * @{ + * Those functions set the field of obj with the given name to value. + * + * @param[in] obj A struct whose first element is a pointer to an AVClass. + * @param[in] name the name of the field to set + * @param[in] val The value to set. In case of av_opt_set() if the field is not + * of a string type, then the given string is parsed. + * SI postfixes and some named scalars are supported. + * If the field is of a numeric type, it has to be a numeric or named + * scalar. Behavior with more than one scalar and +- infix operators + * is undefined. + * If the field is of a flags type, it has to be a sequence of numeric + * scalars or named flags separated by '+' or '-'. Prefixing a flag + * with '+' causes it to be set without affecting the other flags; + * similarly, '-' unsets a flag. + * If the field is of a dictionary type, it has to be a ':' separated list of + * key=value parameters. Values containing ':' special characters must be + * escaped. + * @param search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be set on a child of obj. + * + * @return 0 if the value has been set, or an AVERROR code in case of + * error: + * AVERROR_OPTION_NOT_FOUND if no matching option exists + * AVERROR(ERANGE) if the value is out of range + * AVERROR(EINVAL) if the value is not valid + */ +int av_opt_set (void *obj, const char *name, const char *val, int search_flags); +int av_opt_set_int (void *obj, const char *name, int64_t val, int search_flags); +int av_opt_set_double (void *obj, const char *name, double val, int search_flags); +int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags); +int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, int search_flags); +int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags); +int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags); +int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags); +int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags); +int av_opt_set_chlayout(void *obj, const char *name, const AVChannelLayout *layout, int search_flags); +/** + * @note Any old dictionary present is discarded and replaced with a copy of the new one. The + * caller still owns val is and responsible for freeing it. + */ +int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags); + +/** + * Set a binary option to an integer list. + * + * @param obj AVClass object to set options on + * @param name name of the binary option + * @param val pointer to an integer list (must have the correct type with + * regard to the contents of the list) + * @param term list terminator (usually 0 or -1) + * @param flags search flags + */ +#define av_opt_set_int_list(obj, name, val, term, flags) \ + (av_int_list_length(val, term) > INT_MAX / sizeof(*(val)) ? \ + AVERROR(EINVAL) : \ + av_opt_set_bin(obj, name, (const uint8_t *)(val), \ + av_int_list_length(val, term) * sizeof(*(val)), flags)) + +/** + * @} + * @} + */ + +/** + * @defgroup opt_read Reading option values + * @{ + */ + +/** + * @defgroup opt_get_funcs Option getting functions + * @{ + * Those functions get a value of the option with the given name from an object. + * + * @param[in] obj a struct whose first element is a pointer to an AVClass. + * @param[in] name name of the option to get. + * @param[in] search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be found in a child of obj. + * @param[out] out_val value of the option will be written here + * @return >=0 on success, a negative error code otherwise + */ +/** + * @note the returned string will be av_malloc()ed and must be av_free()ed by the caller + * + * @note if AV_OPT_ALLOW_NULL is set in search_flags in av_opt_get, and the + * option is of type AV_OPT_TYPE_STRING, AV_OPT_TYPE_BINARY or AV_OPT_TYPE_DICT + * and is set to NULL, *out_val will be set to NULL instead of an allocated + * empty string. + */ +int av_opt_get (void *obj, const char *name, int search_flags, uint8_t **out_val); +int av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val); +int av_opt_get_double (void *obj, const char *name, int search_flags, double *out_val); +int av_opt_get_q (void *obj, const char *name, int search_flags, AVRational *out_val); +int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out); +int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt); +int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt); +int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val); +int av_opt_get_chlayout(void *obj, const char *name, int search_flags, AVChannelLayout *layout); +/** + * @param[out] out_val The returned dictionary is a copy of the actual value and must + * be freed with av_dict_free() by the caller + */ +int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val); +/** + * @} + */ + +/** + * @defgroup opt_eval_funcs Evaluating option strings + * @{ + * This group of functions can be used to evaluate option strings + * and get numbers out of them. They do the same thing as av_opt_set(), + * except the result is written into the caller-supplied pointer. + * + * @param obj a struct whose first element is a pointer to AVClass. + * @param o an option for which the string is to be evaluated. + * @param val string to be evaluated. + * @param *_out value of the string will be written here. + * + * @return 0 on success, a negative number on failure. + */ +int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out); +int av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out); +int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out); +int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out); +int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double *double_out); +int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out); +/** + * @} + */ + +/** + * Gets a pointer to the requested field in a struct. + * This function allows accessing a struct even when its fields are moved or + * renamed since the application making the access has been compiled, + * + * @returns a pointer to the field, it can be cast to the correct type and read + * or written to. + */ +void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name); + +/** + * Check if given option is set to its default value. + * + * Options o must belong to the obj. This function must not be called to check child's options state. + * @see av_opt_is_set_to_default_by_name(). + * + * @param obj AVClass object to check option on + * @param o option to be checked + * @return >0 when option is set to its default, + * 0 when option is not set its default, + * <0 on error + */ +int av_opt_is_set_to_default(void *obj, const AVOption *o); + +/** + * Check if given option is set to its default value. + * + * @param obj AVClass object to check option on + * @param name option name + * @param search_flags combination of AV_OPT_SEARCH_* + * @return >0 when option is set to its default, + * 0 when option is not set its default, + * <0 on error + */ +int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags); + +/** + * Check whether a particular flag is set in a flags field. + * + * @param field_name the name of the flag field option + * @param flag_name the name of the flag to check + * @return non-zero if the flag is set, zero if the flag isn't set, + * isn't of the right type, or the flags field doesn't exist. + */ +int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name); + +#define AV_OPT_SERIALIZE_SKIP_DEFAULTS 0x00000001 ///< Serialize options that are not set to default values only. +#define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT 0x00000002 ///< Serialize options that exactly match opt_flags only. + +/** + * Serialize object's options. + * + * Create a string containing object's serialized options. + * Such string may be passed back to av_opt_set_from_string() in order to restore option values. + * A key/value or pairs separator occurring in the serialized value or + * name string are escaped through the av_escape() function. + * + * @param[in] obj AVClass object to serialize + * @param[in] opt_flags serialize options with all the specified flags set (AV_OPT_FLAG) + * @param[in] flags combination of AV_OPT_SERIALIZE_* flags + * @param[out] buffer Pointer to buffer that will be allocated with string containg serialized options. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep character used to separate key from value + * @param[in] pairs_sep character used to separate two pairs from each other + * @return >= 0 on success, negative on error + * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same. + */ +int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, + const char key_val_sep, const char pairs_sep); + +/** + * @} + */ + +/** + * Free an AVOptionRanges struct and set it to NULL. + */ +void av_opt_freep_ranges(AVOptionRanges **ranges); + +/** + * Get a list of allowed ranges for the given option. + * + * The returned list may depend on other fields in obj like for example profile. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_freep_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * Get a default list of allowed ranges for the given option. + * + * This list is constructed without using the AVClass.query_ranges() callback + * and can be used as fallback from within the callback. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_free_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * @} + */ + +#endif /* AVUTIL_OPT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/pixdesc.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/pixdesc.h new file mode 100644 index 0000000000000..ba2f6328141b3 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/pixdesc.h @@ -0,0 +1,440 @@ +/* + * pixel format descriptor + * Copyright (c) 2009 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXDESC_H +#define AVUTIL_PIXDESC_H + +#include + +#include "attributes.h" +#include "pixfmt.h" + +typedef struct AVComponentDescriptor { + /** + * Which of the 4 planes contains the component. + */ + int plane; + + /** + * Number of elements between 2 horizontally consecutive pixels. + * Elements are bits for bitstream formats, bytes otherwise. + */ + int step; + + /** + * Number of elements before the component of the first pixel. + * Elements are bits for bitstream formats, bytes otherwise. + */ + int offset; + + /** + * Number of least significant bits that must be shifted away + * to get the value. + */ + int shift; + + /** + * Number of bits in the component. + */ + int depth; +} AVComponentDescriptor; + +/** + * Descriptor that unambiguously describes how the bits of a pixel are + * stored in the up to 4 data planes of an image. It also stores the + * subsampling factors and number of components. + * + * @note This is separate of the colorspace (RGB, YCbCr, YPbPr, JPEG-style YUV + * and all the YUV variants) AVPixFmtDescriptor just stores how values + * are stored not what these values represent. + */ +typedef struct AVPixFmtDescriptor { + const char *name; + uint8_t nb_components; ///< The number of components each pixel has, (1-4) + + /** + * Amount to shift the luma width right to find the chroma width. + * For YV12 this is 1 for example. + * chroma_width = AV_CEIL_RSHIFT(luma_width, log2_chroma_w) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_w; + + /** + * Amount to shift the luma height right to find the chroma height. + * For YV12 this is 1 for example. + * chroma_height= AV_CEIL_RSHIFT(luma_height, log2_chroma_h) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_h; + + /** + * Combination of AV_PIX_FMT_FLAG_... flags. + */ + uint64_t flags; + + /** + * Parameters that describe how pixels are packed. + * If the format has 1 or 2 components, then luma is 0. + * If the format has 3 or 4 components: + * if the RGB flag is set then 0 is red, 1 is green and 2 is blue; + * otherwise 0 is luma, 1 is chroma-U and 2 is chroma-V. + * + * If present, the Alpha channel is always the last component. + */ + AVComponentDescriptor comp[4]; + + /** + * Alternative comma-separated names. + */ + const char *alias; +} AVPixFmtDescriptor; + +/** + * Pixel format is big-endian. + */ +#define AV_PIX_FMT_FLAG_BE (1 << 0) +/** + * Pixel format has a palette in data[1], values are indexes in this palette. + */ +#define AV_PIX_FMT_FLAG_PAL (1 << 1) +/** + * All values of a component are bit-wise packed end to end. + */ +#define AV_PIX_FMT_FLAG_BITSTREAM (1 << 2) +/** + * Pixel format is an HW accelerated format. + */ +#define AV_PIX_FMT_FLAG_HWACCEL (1 << 3) +/** + * At least one pixel component is not in the first data plane. + */ +#define AV_PIX_FMT_FLAG_PLANAR (1 << 4) +/** + * The pixel format contains RGB-like data (as opposed to YUV/grayscale). + */ +#define AV_PIX_FMT_FLAG_RGB (1 << 5) + +/** + * The pixel format has an alpha channel. This is set on all formats that + * support alpha in some way, including AV_PIX_FMT_PAL8. The alpha is always + * straight, never pre-multiplied. + * + * If a codec or a filter does not support alpha, it should set all alpha to + * opaque, or use the equivalent pixel formats without alpha component, e.g. + * AV_PIX_FMT_RGB0 (or AV_PIX_FMT_RGB24 etc.) instead of AV_PIX_FMT_RGBA. + */ +#define AV_PIX_FMT_FLAG_ALPHA (1 << 7) + +/** + * The pixel format is following a Bayer pattern + */ +#define AV_PIX_FMT_FLAG_BAYER (1 << 8) + +/** + * The pixel format contains IEEE-754 floating point values. Precision (double, + * single, or half) should be determined by the pixel size (64, 32, or 16 bits). + */ +#define AV_PIX_FMT_FLAG_FLOAT (1 << 9) + +/** + * The pixel format contains XYZ-like data (as opposed to YUV/RGB/grayscale). + */ +#define AV_PIX_FMT_FLAG_XYZ (1 << 10) + +/** + * Return the number of bits per pixel used by the pixel format + * described by pixdesc. Note that this is not the same as the number + * of bits per sample. + * + * The returned number of bits refers to the number of bits actually + * used for storing the pixel information, that is padding bits are + * not counted. + */ +int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * Return the number of bits per pixel for the pixel format + * described by pixdesc, including any padding or unused bits. + */ +int av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * @return a pixel format descriptor for provided pixel format or NULL if + * this pixel format is unknown. + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt); + +/** + * Iterate over all pixel format descriptors known to libavutil. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_next(const AVPixFmtDescriptor *prev); + +/** + * @return an AVPixelFormat id described by desc, or AV_PIX_FMT_NONE if desc + * is not a valid pointer to a pixel format descriptor. + */ +enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); + +/** + * Utility function to access log2_chroma_w log2_chroma_h from + * the pixel format AVPixFmtDescriptor. + * + * @param[in] pix_fmt the pixel format + * @param[out] h_shift store log2_chroma_w (horizontal/width shift) + * @param[out] v_shift store log2_chroma_h (vertical/height shift) + * + * @return 0 on success, AVERROR(ENOSYS) on invalid or unknown pixel format + */ +int av_pix_fmt_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, + int *h_shift, int *v_shift); + +/** + * @return number of planes in pix_fmt, a negative AVERROR if pix_fmt is not a + * valid pixel format. + */ +int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt); + +/** + * @return the name for provided color range or NULL if unknown. + */ +const char *av_color_range_name(enum AVColorRange range); + +/** + * @return the AVColorRange value for name or an AVError if not found. + */ +int av_color_range_from_name(const char *name); + +/** + * @return the name for provided color primaries or NULL if unknown. + */ +const char *av_color_primaries_name(enum AVColorPrimaries primaries); + +/** + * @return the AVColorPrimaries value for name or an AVError if not found. + */ +int av_color_primaries_from_name(const char *name); + +/** + * @return the name for provided color transfer or NULL if unknown. + */ +const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer); + +/** + * @return the AVColorTransferCharacteristic value for name or an AVError if not found. + */ +int av_color_transfer_from_name(const char *name); + +/** + * @return the name for provided color space or NULL if unknown. + */ +const char *av_color_space_name(enum AVColorSpace space); + +/** + * @return the AVColorSpace value for name or an AVError if not found. + */ +int av_color_space_from_name(const char *name); + +/** + * @return the name for provided chroma location or NULL if unknown. + */ +const char *av_chroma_location_name(enum AVChromaLocation location); + +/** + * @return the AVChromaLocation value for name or an AVError if not found. + */ +int av_chroma_location_from_name(const char *name); + +/** + * Converts AVChromaLocation to swscale x/y chroma position. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + */ +int av_chroma_location_enum_to_pos(int *xpos, int *ypos, enum AVChromaLocation pos); + +/** + * Converts swscale x/y chroma position to AVChromaLocation. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + */ +enum AVChromaLocation av_chroma_location_pos_to_enum(int xpos, int ypos); + +/** + * Return the pixel format corresponding to name. + * + * If there is no pixel format with name name, then looks for a + * pixel format with the name corresponding to the native endian + * format of name. + * For example in a little-endian system, first looks for "gray16", + * then for "gray16le". + * + * Finally if no pixel format has been found, returns AV_PIX_FMT_NONE. + */ +enum AVPixelFormat av_get_pix_fmt(const char *name); + +/** + * Return the short name for a pixel format, NULL in case pix_fmt is + * unknown. + * + * @see av_get_pix_fmt(), av_get_pix_fmt_string() + */ +const char *av_get_pix_fmt_name(enum AVPixelFormat pix_fmt); + +/** + * Print in buf the string corresponding to the pixel format with + * number pix_fmt, or a header if pix_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param pix_fmt the number of the pixel format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + */ +char *av_get_pix_fmt_string(char *buf, int buf_size, + enum AVPixelFormat pix_fmt); + +/** + * Read a line from an image, and write the values of the + * pixel format component c to dst. + * + * @param data the array containing the pointers to the planes of the image + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to read + * @param y the vertical coordinate of the first pixel to read + * @param w the width of the line to read, that is the number of + * values to write to dst + * @param read_pal_component if not zero and the format is a paletted + * format writes the values corresponding to the palette + * component c in data[1] to dst, rather than the palette indexes in + * data[0]. The behavior is undefined if the format is not paletted. + * @param dst_element_size size of elements in dst array (2 or 4 byte) + */ +void av_read_image_line2(void *dst, const uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int read_pal_component, + int dst_element_size); + +void av_read_image_line(uint16_t *dst, const uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int read_pal_component); + +/** + * Write the values from src to the pixel format component c of an + * image line. + * + * @param src array containing the values to write + * @param data the array containing the pointers to the planes of the + * image to write into. It is supposed to be zeroed. + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to write + * @param y the vertical coordinate of the first pixel to write + * @param w the width of the line to write, that is the number of + * values to write to the image line + * @param src_element_size size of elements in src array (2 or 4 byte) + */ +void av_write_image_line2(const void *src, uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int src_element_size); + +void av_write_image_line(const uint16_t *src, uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w); + +/** + * Utility function to swap the endianness of a pixel format. + * + * @param[in] pix_fmt the pixel format + * + * @return pixel format with swapped endianness if it exists, + * otherwise AV_PIX_FMT_NONE + */ +enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt); + +#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ +#define FF_LOSS_EXCESS_RESOLUTION 0x0040 /**< loss due to unneeded extra resolution */ +#define FF_LOSS_EXCESS_DEPTH 0x0080 /**< loss due to unneeded extra color depth */ + + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + int has_alpha); + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); + +#endif /* AVUTIL_PIXDESC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/pixfmt.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/pixfmt.h new file mode 100644 index 0000000000000..4aa20e4e58537 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/pixfmt.h @@ -0,0 +1,713 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXFMT_H +#define AVUTIL_PIXFMT_H + +/** + * @file + * pixel format definitions + */ + +#include "libavutil/avconfig.h" +#include "version.h" + +#define AVPALETTE_SIZE 1024 +#define AVPALETTE_COUNT 256 + +/** + * Maximum number of planes in any pixel format. + * This should be used when a maximum is needed, but code should not + * be written to require a maximum for no good reason. + */ +#define AV_VIDEO_MAX_PLANES 4 + +/** + * Pixel format. + * + * @note + * AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA + * color is put together as: + * (A << 24) | (R << 16) | (G << 8) | B + * This is stored as BGRA on little-endian CPU architectures and ARGB on + * big-endian CPUs. + * + * @note + * If the resolution is not a multiple of the chroma subsampling factor + * then the chroma plane resolution must be rounded up. + * + * @par + * When the pixel format is palettized RGB32 (AV_PIX_FMT_PAL8), the palettized + * image data is stored in AVFrame.data[0]. The palette is transported in + * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is + * formatted the same as in AV_PIX_FMT_RGB32 described above (i.e., it is + * also endian-specific). Note also that the individual RGB32 palette + * components stored in AVFrame.data[1] should be in the range 0..255. + * This is important as many custom PAL8 video codecs that were designed + * to run on the IBM VGA graphics adapter use 6-bit palette components. + * + * @par + * For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like + * for pal8. This palette is filled in automatically by the function + * allocating the picture. + */ +enum AVPixelFormat { + AV_PIX_FMT_NONE = -1, + AV_PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) + AV_PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr + AV_PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB... + AV_PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR... + AV_PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) + AV_PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples) + AV_PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) + AV_PIX_FMT_GRAY8, ///< Y , 8bpp + AV_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_PAL8, ///< 8 bits with AV_PIX_FMT_RGB32 palette + AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range + AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range + AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range + AV_PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 + AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 + AV_PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) + AV_PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb) + AV_PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)3R 3G 2B(lsb) + AV_PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) + AV_PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV21, ///< as above, but U and V bytes are swapped + + AV_PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... + AV_PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA... + AV_PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR... + AV_PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA... + + AV_PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian + AV_PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian + AV_PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) + AV_PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range + AV_PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) + AV_PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian + + AV_PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian + AV_PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian + AV_PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined + + AV_PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian + AV_PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian + AV_PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined + + /** + * Hardware acceleration through VA-API, data[3] contains a + * VASurfaceID. + */ + AV_PIX_FMT_VAAPI, + + AV_PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer + + AV_PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_YA8, ///< 8 bits gray, 8 bits alpha + + AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + AV_PIX_FMT_GRAY8A= AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + + AV_PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian + + /** + * The following 12 formats have the disadvantage of needing 1 format for each bit depth. + * Notice that each 9/10 bits sample is stored in 16 bits with extra padding. + * If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better. + */ + AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp + AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP + AV_PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big-endian + AV_PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little-endian + AV_PIX_FMT_GBRP10BE, ///< planar GBR 4:4:4 30bpp, big-endian + AV_PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little-endian + AV_PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little-endian + AV_PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + AV_PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + AV_PIX_FMT_YUVA420P9BE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian + AV_PIX_FMT_YUVA420P9LE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian + AV_PIX_FMT_YUVA422P9BE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA422P9LE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA444P9BE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA444P9LE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA420P10BE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P10LE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P10BE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P10LE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P10BE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P10LE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA420P16BE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P16LE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P16BE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P16LE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P16BE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P16LE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + + AV_PIX_FMT_VDPAU, ///< HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface + + AV_PIX_FMT_XYZ12LE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_XYZ12BE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_NV16, ///< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_NV20LE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_NV20BE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + + AV_PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + + AV_PIX_FMT_YVYU422, ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb + + AV_PIX_FMT_YA16BE, ///< 16 bits gray, 16 bits alpha (big-endian) + AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian) + + AV_PIX_FMT_GBRAP, ///< planar GBRA 4:4:4:4 32bpp + AV_PIX_FMT_GBRAP16BE, ///< planar GBRA 4:4:4:4 64bpp, big-endian + AV_PIX_FMT_GBRAP16LE, ///< planar GBRA 4:4:4:4 64bpp, little-endian + /** + * HW acceleration through QSV, data[3] contains a pointer to the + * mfxFrameSurface1 structure. + * + * Before FFmpeg 5.0: + * mfxFrameSurface1.Data.MemId contains a pointer when importing + * the following frames as QSV frames: + * + * VAAPI: + * mfxFrameSurface1.Data.MemId contains a pointer to VASurfaceID + * + * DXVA2: + * mfxFrameSurface1.Data.MemId contains a pointer to IDirect3DSurface9 + * + * FFmpeg 5.0 and above: + * mfxFrameSurface1.Data.MemId contains a pointer to the mfxHDLPair + * structure when importing the following frames as QSV frames: + * + * VAAPI: + * mfxHDLPair.first contains a VASurfaceID pointer. + * mfxHDLPair.second is always MFX_INFINITE. + * + * DXVA2: + * mfxHDLPair.first contains IDirect3DSurface9 pointer. + * mfxHDLPair.second is always MFX_INFINITE. + * + * D3D11: + * mfxHDLPair.first contains a ID3D11Texture2D pointer. + * mfxHDLPair.second contains the texture array index of the frame if the + * ID3D11Texture2D is an array texture, or always MFX_INFINITE if it is a + * normal texture. + */ + AV_PIX_FMT_QSV, + /** + * HW acceleration though MMAL, data[3] contains a pointer to the + * MMAL_BUFFER_HEADER_T structure. + */ + AV_PIX_FMT_MMAL, + + AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer + + /** + * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers + * exactly as for system memory frames. + */ + AV_PIX_FMT_CUDA, + + AV_PIX_FMT_0RGB, ///< packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined + AV_PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined + AV_PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined + AV_PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined + + AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_GBRP12BE, ///< planar GBR 4:4:4 36bpp, big-endian + AV_PIX_FMT_GBRP12LE, ///< planar GBR 4:4:4 36bpp, little-endian + AV_PIX_FMT_GBRP14BE, ///< planar GBR 4:4:4 42bpp, big-endian + AV_PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little-endian + AV_PIX_FMT_YUVJ411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV411P and setting color_range + + AV_PIX_FMT_BAYER_BGGR8, ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples + AV_PIX_FMT_BAYER_RGGB8, ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples + AV_PIX_FMT_BAYER_GBRG8, ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples + AV_PIX_FMT_BAYER_GRBG8, ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples + AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian + + AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_YUV440P12LE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P12BE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_AYUV64LE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_AYUV64BE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + + AV_PIX_FMT_VIDEOTOOLBOX, ///< hardware decoding through Videotoolbox + + AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian + AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian + + AV_PIX_FMT_GBRAP12BE, ///< planar GBR 4:4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRAP12LE, ///< planar GBR 4:4:4:4 48bpp, little-endian + + AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian + AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian + + AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec + + AV_PIX_FMT_GRAY12BE, ///< Y , 12bpp, big-endian + AV_PIX_FMT_GRAY12LE, ///< Y , 12bpp, little-endian + AV_PIX_FMT_GRAY10BE, ///< Y , 10bpp, big-endian + AV_PIX_FMT_GRAY10LE, ///< Y , 10bpp, little-endian + + AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian + AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian + + /** + * Hardware surfaces for Direct3D11. + * + * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11 + * hwaccel API and filtering support AV_PIX_FMT_D3D11 only. + * + * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the + * texture array index of the frame as intptr_t if the ID3D11Texture2D is + * an array texture (or always 0 if it's a normal texture). + */ + AV_PIX_FMT_D3D11, + + AV_PIX_FMT_GRAY9BE, ///< Y , 9bpp, big-endian + AV_PIX_FMT_GRAY9LE, ///< Y , 9bpp, little-endian + + AV_PIX_FMT_GBRPF32BE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, big-endian + AV_PIX_FMT_GBRPF32LE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, little-endian + AV_PIX_FMT_GBRAPF32BE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian + AV_PIX_FMT_GBRAPF32LE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian + + /** + * DRM-managed buffers exposed through PRIME buffer sharing. + * + * data[0] points to an AVDRMFrameDescriptor. + */ + AV_PIX_FMT_DRM_PRIME, + /** + * Hardware surfaces for OpenCL. + * + * data[i] contain 2D image objects (typed in C as cl_mem, used + * in OpenCL as image2d_t) for each plane of the surface. + */ + AV_PIX_FMT_OPENCL, + + AV_PIX_FMT_GRAY14BE, ///< Y , 14bpp, big-endian + AV_PIX_FMT_GRAY14LE, ///< Y , 14bpp, little-endian + + AV_PIX_FMT_GRAYF32BE, ///< IEEE-754 single precision Y, 32bpp, big-endian + AV_PIX_FMT_GRAYF32LE, ///< IEEE-754 single precision Y, 32bpp, little-endian + + AV_PIX_FMT_YUVA422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, little-endian + AV_PIX_FMT_YUVA444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, little-endian + + AV_PIX_FMT_NV24, ///< planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV42, ///< as above, but U and V bytes are swapped + + /** + * Vulkan hardware images. + * + * data[0] points to an AVVkFrame + */ + AV_PIX_FMT_VULKAN, + + AV_PIX_FMT_Y210BE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_Y210LE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, little-endian + + AV_PIX_FMT_X2RGB10LE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_X2RGB10BE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_X2BGR10LE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_X2BGR10BE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), big-endian, X=unused/undefined + + AV_PIX_FMT_P210BE, ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_P210LE, ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, little-endian + + AV_PIX_FMT_P410BE, ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, big-endian + AV_PIX_FMT_P410LE, ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, little-endian + + AV_PIX_FMT_P216BE, ///< interleaved chroma YUV 4:2:2, 32bpp, big-endian + AV_PIX_FMT_P216LE, ///< interleaved chroma YUV 4:2:2, 32bpp, little-endian + + AV_PIX_FMT_P416BE, ///< interleaved chroma YUV 4:4:4, 48bpp, big-endian + AV_PIX_FMT_P416LE, ///< interleaved chroma YUV 4:4:4, 48bpp, little-endian + + AV_PIX_FMT_VUYA, ///< packed VUYA 4:4:4, 32bpp, VUYAVUYA... + + AV_PIX_FMT_RGBAF16BE, ///< IEEE-754 half precision packed RGBA 16:16:16:16, 64bpp, RGBARGBA..., big-endian + AV_PIX_FMT_RGBAF16LE, ///< IEEE-754 half precision packed RGBA 16:16:16:16, 64bpp, RGBARGBA..., little-endian + + AV_PIX_FMT_VUYX, ///< packed VUYX 4:4:4, 32bpp, Variant of VUYA where alpha channel is left undefined + + AV_PIX_FMT_P012LE, ///< like NV12, with 12bpp per component, data in the high bits, zeros in the low bits, little-endian + AV_PIX_FMT_P012BE, ///< like NV12, with 12bpp per component, data in the high bits, zeros in the low bits, big-endian + + AV_PIX_FMT_Y212BE, ///< packed YUV 4:2:2 like YUYV422, 24bpp, data in the high bits, zeros in the low bits, big-endian + AV_PIX_FMT_Y212LE, ///< packed YUV 4:2:2 like YUYV422, 24bpp, data in the high bits, zeros in the low bits, little-endian + + AV_PIX_FMT_XV30BE, ///< packed XVYU 4:4:4, 32bpp, (msb)2X 10V 10Y 10U(lsb), big-endian, variant of Y410 where alpha channel is left undefined + AV_PIX_FMT_XV30LE, ///< packed XVYU 4:4:4, 32bpp, (msb)2X 10V 10Y 10U(lsb), little-endian, variant of Y410 where alpha channel is left undefined + + AV_PIX_FMT_XV36BE, ///< packed XVYU 4:4:4, 48bpp, data in the high bits, zeros in the low bits, big-endian, variant of Y412 where alpha channel is left undefined + AV_PIX_FMT_XV36LE, ///< packed XVYU 4:4:4, 48bpp, data in the high bits, zeros in the low bits, little-endian, variant of Y412 where alpha channel is left undefined + + AV_PIX_FMT_RGBF32BE, ///< IEEE-754 single precision packed RGB 32:32:32, 96bpp, RGBRGB..., big-endian + AV_PIX_FMT_RGBF32LE, ///< IEEE-754 single precision packed RGB 32:32:32, 96bpp, RGBRGB..., little-endian + + AV_PIX_FMT_RGBAF32BE, ///< IEEE-754 single precision packed RGBA 32:32:32:32, 128bpp, RGBARGBA..., big-endian + AV_PIX_FMT_RGBAF32LE, ///< IEEE-754 single precision packed RGBA 32:32:32:32, 128bpp, RGBARGBA..., little-endian + + AV_PIX_FMT_P212BE, ///< interleaved chroma YUV 4:2:2, 24bpp, data in the high bits, big-endian + AV_PIX_FMT_P212LE, ///< interleaved chroma YUV 4:2:2, 24bpp, data in the high bits, little-endian + + AV_PIX_FMT_P412BE, ///< interleaved chroma YUV 4:4:4, 36bpp, data in the high bits, big-endian + AV_PIX_FMT_P412LE, ///< interleaved chroma YUV 4:4:4, 36bpp, data in the high bits, little-endian + + AV_PIX_FMT_GBRAP14BE, ///< planar GBR 4:4:4:4 56bpp, big-endian + AV_PIX_FMT_GBRAP14LE, ///< planar GBR 4:4:4:4 56bpp, little-endian + + /** + * Hardware surfaces for Direct3D 12. + * + * data[0] points to an AVD3D12VAFrame + */ + AV_PIX_FMT_D3D12, + + AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions +}; + +#if AV_HAVE_BIGENDIAN +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##be +#else +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##le +#endif + +#define AV_PIX_FMT_RGB32 AV_PIX_FMT_NE(ARGB, BGRA) +#define AV_PIX_FMT_RGB32_1 AV_PIX_FMT_NE(RGBA, ABGR) +#define AV_PIX_FMT_BGR32 AV_PIX_FMT_NE(ABGR, RGBA) +#define AV_PIX_FMT_BGR32_1 AV_PIX_FMT_NE(BGRA, ARGB) +#define AV_PIX_FMT_0RGB32 AV_PIX_FMT_NE(0RGB, BGR0) +#define AV_PIX_FMT_0BGR32 AV_PIX_FMT_NE(0BGR, RGB0) + +#define AV_PIX_FMT_GRAY9 AV_PIX_FMT_NE(GRAY9BE, GRAY9LE) +#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE) +#define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE) +#define AV_PIX_FMT_GRAY14 AV_PIX_FMT_NE(GRAY14BE, GRAY14LE) +#define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE) +#define AV_PIX_FMT_YA16 AV_PIX_FMT_NE(YA16BE, YA16LE) +#define AV_PIX_FMT_RGB48 AV_PIX_FMT_NE(RGB48BE, RGB48LE) +#define AV_PIX_FMT_RGB565 AV_PIX_FMT_NE(RGB565BE, RGB565LE) +#define AV_PIX_FMT_RGB555 AV_PIX_FMT_NE(RGB555BE, RGB555LE) +#define AV_PIX_FMT_RGB444 AV_PIX_FMT_NE(RGB444BE, RGB444LE) +#define AV_PIX_FMT_RGBA64 AV_PIX_FMT_NE(RGBA64BE, RGBA64LE) +#define AV_PIX_FMT_BGR48 AV_PIX_FMT_NE(BGR48BE, BGR48LE) +#define AV_PIX_FMT_BGR565 AV_PIX_FMT_NE(BGR565BE, BGR565LE) +#define AV_PIX_FMT_BGR555 AV_PIX_FMT_NE(BGR555BE, BGR555LE) +#define AV_PIX_FMT_BGR444 AV_PIX_FMT_NE(BGR444BE, BGR444LE) +#define AV_PIX_FMT_BGRA64 AV_PIX_FMT_NE(BGRA64BE, BGRA64LE) + +#define AV_PIX_FMT_YUV420P9 AV_PIX_FMT_NE(YUV420P9BE , YUV420P9LE) +#define AV_PIX_FMT_YUV422P9 AV_PIX_FMT_NE(YUV422P9BE , YUV422P9LE) +#define AV_PIX_FMT_YUV444P9 AV_PIX_FMT_NE(YUV444P9BE , YUV444P9LE) +#define AV_PIX_FMT_YUV420P10 AV_PIX_FMT_NE(YUV420P10BE, YUV420P10LE) +#define AV_PIX_FMT_YUV422P10 AV_PIX_FMT_NE(YUV422P10BE, YUV422P10LE) +#define AV_PIX_FMT_YUV440P10 AV_PIX_FMT_NE(YUV440P10BE, YUV440P10LE) +#define AV_PIX_FMT_YUV444P10 AV_PIX_FMT_NE(YUV444P10BE, YUV444P10LE) +#define AV_PIX_FMT_YUV420P12 AV_PIX_FMT_NE(YUV420P12BE, YUV420P12LE) +#define AV_PIX_FMT_YUV422P12 AV_PIX_FMT_NE(YUV422P12BE, YUV422P12LE) +#define AV_PIX_FMT_YUV440P12 AV_PIX_FMT_NE(YUV440P12BE, YUV440P12LE) +#define AV_PIX_FMT_YUV444P12 AV_PIX_FMT_NE(YUV444P12BE, YUV444P12LE) +#define AV_PIX_FMT_YUV420P14 AV_PIX_FMT_NE(YUV420P14BE, YUV420P14LE) +#define AV_PIX_FMT_YUV422P14 AV_PIX_FMT_NE(YUV422P14BE, YUV422P14LE) +#define AV_PIX_FMT_YUV444P14 AV_PIX_FMT_NE(YUV444P14BE, YUV444P14LE) +#define AV_PIX_FMT_YUV420P16 AV_PIX_FMT_NE(YUV420P16BE, YUV420P16LE) +#define AV_PIX_FMT_YUV422P16 AV_PIX_FMT_NE(YUV422P16BE, YUV422P16LE) +#define AV_PIX_FMT_YUV444P16 AV_PIX_FMT_NE(YUV444P16BE, YUV444P16LE) + +#define AV_PIX_FMT_GBRP9 AV_PIX_FMT_NE(GBRP9BE , GBRP9LE) +#define AV_PIX_FMT_GBRP10 AV_PIX_FMT_NE(GBRP10BE, GBRP10LE) +#define AV_PIX_FMT_GBRP12 AV_PIX_FMT_NE(GBRP12BE, GBRP12LE) +#define AV_PIX_FMT_GBRP14 AV_PIX_FMT_NE(GBRP14BE, GBRP14LE) +#define AV_PIX_FMT_GBRP16 AV_PIX_FMT_NE(GBRP16BE, GBRP16LE) +#define AV_PIX_FMT_GBRAP10 AV_PIX_FMT_NE(GBRAP10BE, GBRAP10LE) +#define AV_PIX_FMT_GBRAP12 AV_PIX_FMT_NE(GBRAP12BE, GBRAP12LE) +#define AV_PIX_FMT_GBRAP14 AV_PIX_FMT_NE(GBRAP14BE, GBRAP14LE) +#define AV_PIX_FMT_GBRAP16 AV_PIX_FMT_NE(GBRAP16BE, GBRAP16LE) + +#define AV_PIX_FMT_BAYER_BGGR16 AV_PIX_FMT_NE(BAYER_BGGR16BE, BAYER_BGGR16LE) +#define AV_PIX_FMT_BAYER_RGGB16 AV_PIX_FMT_NE(BAYER_RGGB16BE, BAYER_RGGB16LE) +#define AV_PIX_FMT_BAYER_GBRG16 AV_PIX_FMT_NE(BAYER_GBRG16BE, BAYER_GBRG16LE) +#define AV_PIX_FMT_BAYER_GRBG16 AV_PIX_FMT_NE(BAYER_GRBG16BE, BAYER_GRBG16LE) + +#define AV_PIX_FMT_GBRPF32 AV_PIX_FMT_NE(GBRPF32BE, GBRPF32LE) +#define AV_PIX_FMT_GBRAPF32 AV_PIX_FMT_NE(GBRAPF32BE, GBRAPF32LE) + +#define AV_PIX_FMT_GRAYF32 AV_PIX_FMT_NE(GRAYF32BE, GRAYF32LE) + +#define AV_PIX_FMT_YUVA420P9 AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE) +#define AV_PIX_FMT_YUVA422P9 AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE) +#define AV_PIX_FMT_YUVA444P9 AV_PIX_FMT_NE(YUVA444P9BE , YUVA444P9LE) +#define AV_PIX_FMT_YUVA420P10 AV_PIX_FMT_NE(YUVA420P10BE, YUVA420P10LE) +#define AV_PIX_FMT_YUVA422P10 AV_PIX_FMT_NE(YUVA422P10BE, YUVA422P10LE) +#define AV_PIX_FMT_YUVA444P10 AV_PIX_FMT_NE(YUVA444P10BE, YUVA444P10LE) +#define AV_PIX_FMT_YUVA422P12 AV_PIX_FMT_NE(YUVA422P12BE, YUVA422P12LE) +#define AV_PIX_FMT_YUVA444P12 AV_PIX_FMT_NE(YUVA444P12BE, YUVA444P12LE) +#define AV_PIX_FMT_YUVA420P16 AV_PIX_FMT_NE(YUVA420P16BE, YUVA420P16LE) +#define AV_PIX_FMT_YUVA422P16 AV_PIX_FMT_NE(YUVA422P16BE, YUVA422P16LE) +#define AV_PIX_FMT_YUVA444P16 AV_PIX_FMT_NE(YUVA444P16BE, YUVA444P16LE) + +#define AV_PIX_FMT_XYZ12 AV_PIX_FMT_NE(XYZ12BE, XYZ12LE) +#define AV_PIX_FMT_NV20 AV_PIX_FMT_NE(NV20BE, NV20LE) +#define AV_PIX_FMT_AYUV64 AV_PIX_FMT_NE(AYUV64BE, AYUV64LE) +#define AV_PIX_FMT_P010 AV_PIX_FMT_NE(P010BE, P010LE) +#define AV_PIX_FMT_P012 AV_PIX_FMT_NE(P012BE, P012LE) +#define AV_PIX_FMT_P016 AV_PIX_FMT_NE(P016BE, P016LE) + +#define AV_PIX_FMT_Y210 AV_PIX_FMT_NE(Y210BE, Y210LE) +#define AV_PIX_FMT_Y212 AV_PIX_FMT_NE(Y212BE, Y212LE) +#define AV_PIX_FMT_XV30 AV_PIX_FMT_NE(XV30BE, XV30LE) +#define AV_PIX_FMT_XV36 AV_PIX_FMT_NE(XV36BE, XV36LE) +#define AV_PIX_FMT_X2RGB10 AV_PIX_FMT_NE(X2RGB10BE, X2RGB10LE) +#define AV_PIX_FMT_X2BGR10 AV_PIX_FMT_NE(X2BGR10BE, X2BGR10LE) + +#define AV_PIX_FMT_P210 AV_PIX_FMT_NE(P210BE, P210LE) +#define AV_PIX_FMT_P410 AV_PIX_FMT_NE(P410BE, P410LE) +#define AV_PIX_FMT_P212 AV_PIX_FMT_NE(P212BE, P212LE) +#define AV_PIX_FMT_P412 AV_PIX_FMT_NE(P412BE, P412LE) +#define AV_PIX_FMT_P216 AV_PIX_FMT_NE(P216BE, P216LE) +#define AV_PIX_FMT_P416 AV_PIX_FMT_NE(P416BE, P416LE) + +#define AV_PIX_FMT_RGBAF16 AV_PIX_FMT_NE(RGBAF16BE, RGBAF16LE) + +#define AV_PIX_FMT_RGBF32 AV_PIX_FMT_NE(RGBF32BE, RGBF32LE) +#define AV_PIX_FMT_RGBAF32 AV_PIX_FMT_NE(RGBAF32BE, RGBAF32LE) + +/** + * Chromaticity coordinates of the source primaries. + * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.1 and ITU-T H.273. + */ +enum AVColorPrimaries { + AVCOL_PRI_RESERVED0 = 0, + AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP 177 Annex B + AVCOL_PRI_UNSPECIFIED = 2, + AVCOL_PRI_RESERVED = 3, + AVCOL_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + + AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + AVCOL_PRI_SMPTE240M = 7, ///< identical to above, also called "SMPTE C" even though it uses D65 + AVCOL_PRI_FILM = 8, ///< colour filters using Illuminant C + AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020 + AVCOL_PRI_SMPTE428 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ) + AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428, + AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) / DCI P3 + AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3 + AVCOL_PRI_EBU3213 = 22, ///< EBU Tech. 3213-E (nothing there) / one of JEDEC P22 group phosphors + AVCOL_PRI_JEDEC_P22 = AVCOL_PRI_EBU3213, + AVCOL_PRI_NB ///< Not part of ABI +}; + +/** + * Color Transfer Characteristic. + * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.2. + */ +enum AVColorTransferCharacteristic { + AVCOL_TRC_RESERVED0 = 0, + AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361 + AVCOL_TRC_UNSPECIFIED = 2, + AVCOL_TRC_RESERVED = 3, + AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG + AVCOL_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC + AVCOL_TRC_SMPTE240M = 7, + AVCOL_TRC_LINEAR = 8, ///< "Linear transfer characteristics" + AVCOL_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)" + AVCOL_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" + AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4 + AVCOL_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut + AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC) + AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10-bit system + AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12-bit system + AVCOL_TRC_SMPTE2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084, + AVCOL_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1 + AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428, + AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma" + AVCOL_TRC_NB ///< Not part of ABI +}; + +/** + * YUV colorspace type. + * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.3. + */ +enum AVColorSpace { + AVCOL_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1 + AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B + AVCOL_SPC_UNSPECIFIED = 2, + AVCOL_SPC_RESERVED = 3, ///< reserved for future use by ITU-T and ISO/IEC just like 15-255 are + AVCOL_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 + AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above + AVCOL_SPC_SMPTE240M = 7, ///< derived from 170M primaries and D65 white point, 170M is derived from BT470 System M's primaries + AVCOL_SPC_YCGCO = 8, ///< used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + AVCOL_SPC_YCOCG = AVCOL_SPC_YCGCO, + AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system + AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system + AVCOL_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x + AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system + AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system + AVCOL_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp + AVCOL_SPC_NB ///< Not part of ABI +}; + +/** + * Visual content value range. + * + * These values are based on definitions that can be found in multiple + * specifications, such as ITU-T BT.709 (3.4 - Quantization of RGB, luminance + * and colour-difference signals), ITU-T BT.2020 (Table 5 - Digital + * Representation) as well as ITU-T BT.2100 (Table 9 - Digital 10- and 12-bit + * integer representation). At the time of writing, the BT.2100 one is + * recommended, as it also defines the full range representation. + * + * Common definitions: + * - For RGB and luma planes such as Y in YCbCr and I in ICtCp, + * 'E' is the original value in range of 0.0 to 1.0. + * - For chroma planes such as Cb,Cr and Ct,Cp, 'E' is the original + * value in range of -0.5 to 0.5. + * - 'n' is the output bit depth. + * - For additional definitions such as rounding and clipping to valid n + * bit unsigned integer range, please refer to BT.2100 (Table 9). + */ +enum AVColorRange { + AVCOL_RANGE_UNSPECIFIED = 0, + + /** + * Narrow or limited range content. + * + * - For luma planes: + * + * (219 * E + 16) * 2^(n-8) + * + * F.ex. the range of 16-235 for 8 bits + * + * - For chroma planes: + * + * (224 * E + 128) * 2^(n-8) + * + * F.ex. the range of 16-240 for 8 bits + */ + AVCOL_RANGE_MPEG = 1, + + /** + * Full range content. + * + * - For RGB and luma planes: + * + * (2^n - 1) * E + * + * F.ex. the range of 0-255 for 8 bits + * + * - For chroma planes: + * + * (2^n - 1) * E + 2^(n - 1) + * + * F.ex. the range of 1-255 for 8 bits + */ + AVCOL_RANGE_JPEG = 2, + AVCOL_RANGE_NB ///< Not part of ABI +}; + +/** + * Location of chroma samples. + * + * Illustration showing the location of the first (top left) chroma sample of the + * image, the left shows only luma, the right + * shows the location of the chroma sample, the 2 could be imagined to overlay + * each other but are drawn separately due to limitations of ASCII + * + * 1st 2nd 1st 2nd horizontal luma sample positions + * v v v v + * ______ ______ + *1st luma line > |X X ... |3 4 X ... X are luma samples, + * | |1 2 1-6 are possible chroma positions + *2nd luma line > |X X ... |5 6 X ... 0 is undefined/unknown position + */ +enum AVChromaLocation { + AVCHROMA_LOC_UNSPECIFIED = 0, + AVCHROMA_LOC_LEFT = 1, ///< MPEG-2/4 4:2:0, H.264 default for 4:2:0 + AVCHROMA_LOC_CENTER = 2, ///< MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0 + AVCHROMA_LOC_TOPLEFT = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2 + AVCHROMA_LOC_TOP = 4, + AVCHROMA_LOC_BOTTOMLEFT = 5, + AVCHROMA_LOC_BOTTOM = 6, + AVCHROMA_LOC_NB ///< Not part of ABI +}; + +#endif /* AVUTIL_PIXFMT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/rational.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/rational.h new file mode 100644 index 0000000000000..849f47f38d569 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/rational.h @@ -0,0 +1,225 @@ +/* + * rational numbers + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_math_rational + * Utilties for rational number calculation. + * @author Michael Niedermayer + */ + +#ifndef AVUTIL_RATIONAL_H +#define AVUTIL_RATIONAL_H + +#include +#include +#include "attributes.h" + +/** + * @defgroup lavu_math_rational AVRational + * @ingroup lavu_math + * Rational number calculation. + * + * While rational numbers can be expressed as floating-point numbers, the + * conversion process is a lossy one, so are floating-point operations. On the + * other hand, the nature of FFmpeg demands highly accurate calculation of + * timestamps. This set of rational number utilities serves as a generic + * interface for manipulating rational numbers as pairs of numerators and + * denominators. + * + * Many of the functions that operate on AVRational's have the suffix `_q`, in + * reference to the mathematical symbol "ℚ" (Q) which denotes the set of all + * rational numbers. + * + * @{ + */ + +/** + * Rational number (pair of numerator and denominator). + */ +typedef struct AVRational{ + int num; ///< Numerator + int den; ///< Denominator +} AVRational; + +/** + * Create an AVRational. + * + * Useful for compilers that do not support compound literals. + * + * @note The return value is not reduced. + * @see av_reduce() + */ +static inline AVRational av_make_q(int num, int den) +{ + AVRational r = { num, den }; + return r; +} + +/** + * Compare two rationals. + * + * @param a First rational + * @param b Second rational + * + * @return One of the following values: + * - 0 if `a == b` + * - 1 if `a > b` + * - -1 if `a < b` + * - `INT_MIN` if one of the values is of the form `0 / 0` + */ +static inline int av_cmp_q(AVRational a, AVRational b){ + const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den; + + if(tmp) return (int)((tmp ^ a.den ^ b.den)>>63)|1; + else if(b.den && a.den) return 0; + else if(a.num && b.num) return (a.num>>31) - (b.num>>31); + else return INT_MIN; +} + +/** + * Convert an AVRational to a `double`. + * @param a AVRational to convert + * @return `a` in floating-point form + * @see av_d2q() + */ +static inline double av_q2d(AVRational a){ + return a.num / (double) a.den; +} + +/** + * Reduce a fraction. + * + * This is useful for framerate calculations. + * + * @param[out] dst_num Destination numerator + * @param[out] dst_den Destination denominator + * @param[in] num Source numerator + * @param[in] den Source denominator + * @param[in] max Maximum allowed values for `dst_num` & `dst_den` + * @return 1 if the operation is exact, 0 otherwise + */ +int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max); + +/** + * Multiply two rationals. + * @param b First rational + * @param c Second rational + * @return b*c + */ +AVRational av_mul_q(AVRational b, AVRational c) av_const; + +/** + * Divide one rational by another. + * @param b First rational + * @param c Second rational + * @return b/c + */ +AVRational av_div_q(AVRational b, AVRational c) av_const; + +/** + * Add two rationals. + * @param b First rational + * @param c Second rational + * @return b+c + */ +AVRational av_add_q(AVRational b, AVRational c) av_const; + +/** + * Subtract one rational from another. + * @param b First rational + * @param c Second rational + * @return b-c + */ +AVRational av_sub_q(AVRational b, AVRational c) av_const; + +/** + * Invert a rational. + * @param q value + * @return 1 / q + */ +static av_always_inline AVRational av_inv_q(AVRational q) +{ + AVRational r = { q.den, q.num }; + return r; +} + +/** + * Convert a double precision floating point number to a rational. + * + * In case of infinity, the returned value is expressed as `{1, 0}` or + * `{-1, 0}` depending on the sign. + * + * In general rational numbers with |num| <= 1<<26 && |den| <= 1<<26 + * can be recovered exactly from their double representation. + * (no exceptions were found within 1B random ones) + * + * @param d `double` to convert + * @param max Maximum allowed numerator and denominator + * @return `d` in AVRational form + * @see av_q2d() + */ +AVRational av_d2q(double d, int max) av_const; + +/** + * Find which of the two rationals is closer to another rational. + * + * @param q Rational to be compared against + * @param q1 Rational to be tested + * @param q2 Rational to be tested + * @return One of the following values: + * - 1 if `q1` is nearer to `q` than `q2` + * - -1 if `q2` is nearer to `q` than `q1` + * - 0 if they have the same distance + */ +int av_nearer_q(AVRational q, AVRational q1, AVRational q2); + +/** + * Find the value in a list of rationals nearest a given reference rational. + * + * @param q Reference rational + * @param q_list Array of rationals terminated by `{0, 0}` + * @return Index of the nearest value found in the array + */ +int av_find_nearest_q_idx(AVRational q, const AVRational* q_list); + +/** + * Convert an AVRational to a IEEE 32-bit `float` expressed in fixed-point + * format. + * + * @param q Rational to be converted + * @return Equivalent floating-point value, expressed as an unsigned 32-bit + * integer. + * @note The returned value is platform-indepedant. + */ +uint32_t av_q2intfloat(AVRational q); + +/** + * Return the best rational so that a and b are multiple of it. + * If the resulting denominator is larger than max_den, return def. + */ +AVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def); + +/** + * @} + */ + +#endif /* AVUTIL_RATIONAL_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/samplefmt.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/samplefmt.h new file mode 100644 index 0000000000000..43a57a422cdbf --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/samplefmt.h @@ -0,0 +1,269 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_SAMPLEFMT_H +#define AVUTIL_SAMPLEFMT_H + +#include + +/** + * @addtogroup lavu_audio + * @{ + * + * @defgroup lavu_sampfmts Audio sample formats + * + * Audio sample format enumeration and related convenience functions. + * @{ + */ + +/** + * Audio sample formats + * + * - The data described by the sample format is always in native-endian order. + * Sample values can be expressed by native C types, hence the lack of a signed + * 24-bit sample format even though it is a common raw audio data format. + * + * - The floating-point formats are based on full volume being in the range + * [-1.0, 1.0]. Any values outside this range are beyond full volume level. + * + * - The data layout as used in av_samples_fill_arrays() and elsewhere in FFmpeg + * (such as AVFrame in libavcodec) is as follows: + * + * @par + * For planar sample formats, each audio channel is in a separate data plane, + * and linesize is the buffer size, in bytes, for a single plane. All data + * planes must be the same size. For packed sample formats, only the first data + * plane is used, and samples for each channel are interleaved. In this case, + * linesize is the buffer size, in bytes, for the 1 plane. + * + */ +enum AVSampleFormat { + AV_SAMPLE_FMT_NONE = -1, + AV_SAMPLE_FMT_U8, ///< unsigned 8 bits + AV_SAMPLE_FMT_S16, ///< signed 16 bits + AV_SAMPLE_FMT_S32, ///< signed 32 bits + AV_SAMPLE_FMT_FLT, ///< float + AV_SAMPLE_FMT_DBL, ///< double + + AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar + AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar + AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar + AV_SAMPLE_FMT_FLTP, ///< float, planar + AV_SAMPLE_FMT_DBLP, ///< double, planar + AV_SAMPLE_FMT_S64, ///< signed 64 bits + AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar + + AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically +}; + +/** + * Return the name of sample_fmt, or NULL if sample_fmt is not + * recognized. + */ +const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt); + +/** + * Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE + * on error. + */ +enum AVSampleFormat av_get_sample_fmt(const char *name); + +/** + * Return the planar<->packed alternative form of the given sample format, or + * AV_SAMPLE_FMT_NONE on error. If the passed sample_fmt is already in the + * requested planar/packed format, the format returned is the same as the + * input. + */ +enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar); + +/** + * Get the packed alternative form of the given sample format. + * + * If the passed sample_fmt is already in packed format, the format returned is + * the same as the input. + * + * @return the packed alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Get the planar alternative form of the given sample format. + * + * If the passed sample_fmt is already in planar format, the format returned is + * the same as the input. + * + * @return the planar alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Generate a string corresponding to the sample format with + * sample_fmt, or a header if sample_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param sample_fmt the number of the sample format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + * @return the pointer to the filled buffer or NULL if sample_fmt is + * unknown or in case of other errors + */ +char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt); + +/** + * Return number of bytes per sample. + * + * @param sample_fmt the sample format + * @return number of bytes per sample or zero if unknown for the given + * sample format + */ +int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt); + +/** + * Check if the sample format is planar. + * + * @param sample_fmt the sample format to inspect + * @return 1 if the sample format is planar, 0 if it is interleaved + */ +int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt); + +/** + * Get the required buffer size for the given audio parameters. + * + * @param[out] linesize calculated linesize, may be NULL + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return required buffer size, or negative error code on failure + */ +int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * @} + * + * @defgroup lavu_sampmanip Samples manipulation + * + * Functions that manipulate audio samples + * @{ + */ + +/** + * Fill plane data pointers and linesize for samples with sample + * format sample_fmt. + * + * The audio_data array is filled with the pointers to the samples data planes: + * for planar, set the start point of each channel's data within the buffer, + * for packed, set the start point of the entire buffer only. + * + * The value pointed to by linesize is set to the aligned size of each + * channel's data buffer for planar layout, or to the aligned size of the + * buffer for all channels for packed layout. + * + * The buffer in buf must be big enough to contain all the samples + * (use av_samples_get_buffer_size() to compute its minimum size), + * otherwise the audio_data pointers will point to invalid data. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize calculated linesize, may be NULL + * @param buf the pointer to a buffer containing the samples + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return minimum size in bytes required for the buffer on success, + * or a negative error code on failure + */ +int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, + const uint8_t *buf, + int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a samples buffer for nb_samples samples, and fill data pointers and + * linesize accordingly. + * The allocated samples buffer can be freed by using av_freep(&audio_data[0]) + * Allocated data will be initialized to silence. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize aligned size for audio buffer(s), may be NULL + * @param nb_channels number of audio channels + * @param nb_samples number of samples per channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return >=0 on success or a negative error code on failure + * @todo return the size of the allocated buffer in case of success at the next bump + * @see av_samples_fill_arrays() + * @see av_samples_alloc_array_and_samples() + */ +int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a data pointers array, samples buffer for nb_samples + * samples, and fill data pointers and linesize accordingly. + * + * This is the same as av_samples_alloc(), but also allocates the data + * pointers array. + * + * @see av_samples_alloc() + */ +int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Copy samples from src to dst. + * + * @param dst destination array of pointers to data planes + * @param src source array of pointers to data planes + * @param dst_offset offset in samples at which the data will be written to dst + * @param src_offset offset in samples at which the data will be read from src + * @param nb_samples number of samples to be copied + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_copy(uint8_t * const *dst, uint8_t * const *src, int dst_offset, + int src_offset, int nb_samples, int nb_channels, + enum AVSampleFormat sample_fmt); + +/** + * Fill an audio buffer with silence. + * + * @param audio_data array of pointers to data planes + * @param offset offset in samples at which to start filling + * @param nb_samples number of samples to fill + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_set_silence(uint8_t * const *audio_data, int offset, int nb_samples, + int nb_channels, enum AVSampleFormat sample_fmt); + +/** + * @} + * @} + */ +#endif /* AVUTIL_SAMPLEFMT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libavutil/version.h b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/version.h new file mode 100644 index 0000000000000..0a3f5dd0c9216 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libavutil/version.h @@ -0,0 +1,121 @@ +/* + * copyright (c) 2003 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu + * Libavutil version macros + */ + +#ifndef AVUTIL_VERSION_H +#define AVUTIL_VERSION_H + +#include "macros.h" + +/** + * @addtogroup version_utils + * + * Useful to check and match library version in order to maintain + * backward compatibility. + * + * The FFmpeg libraries follow a versioning sheme very similar to + * Semantic Versioning (http://semver.org/) + * The difference is that the component called PATCH is called MICRO in FFmpeg + * and its value is reset to 100 instead of 0 to keep it above or equal to 100. + * Also we do not increase MICRO for every bugfix or change in git master. + * + * Prior to FFmpeg 3.2 point releases did not change any lib version number to + * avoid aliassing different git master checkouts. + * Starting with FFmpeg 3.2, the released library versions will occupy + * a separate MAJOR.MINOR that is not used on the master development branch. + * That is if we branch a release of master 55.10.123 we will bump to 55.11.100 + * for the release and master will continue at 55.12.100 after it. Each new + * point release will then bump the MICRO improving the usefulness of the lib + * versions. + * + * @{ + */ + +#define AV_VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c)) +#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c +#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c) + +/** + * Extract version components from the full ::AV_VERSION_INT int as returned + * by functions like ::avformat_version() and ::avcodec_version() + */ +#define AV_VERSION_MAJOR(a) ((a) >> 16) +#define AV_VERSION_MINOR(a) (((a) & 0x00FF00) >> 8) +#define AV_VERSION_MICRO(a) ((a) & 0xFF) + +/** + * @} + */ + +/** + * @defgroup lavu_ver Version and Build diagnostics + * + * Macros and function useful to check at compiletime and at runtime + * which version of libavutil is in use. + * + * @{ + */ + +#define LIBAVUTIL_VERSION_MAJOR 59 +#define LIBAVUTIL_VERSION_MINOR 8 +#define LIBAVUTIL_VERSION_MICRO 100 + +#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT + +#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION) + +/** + * @defgroup lavu_depr_guards Deprecation Guards + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + * + * @{ + */ + +#define FF_API_HDR_VIVID_THREE_SPLINE (LIBAVUTIL_VERSION_MAJOR < 60) +#define FF_API_FRAME_PKT (LIBAVUTIL_VERSION_MAJOR < 60) +#define FF_API_INTERLACED_FRAME (LIBAVUTIL_VERSION_MAJOR < 60) +#define FF_API_FRAME_KEY (LIBAVUTIL_VERSION_MAJOR < 60) +#define FF_API_PALETTE_HAS_CHANGED (LIBAVUTIL_VERSION_MAJOR < 60) +#define FF_API_VULKAN_CONTIGUOUS_MEMORY (LIBAVUTIL_VERSION_MAJOR < 60) +#define FF_API_H274_FILM_GRAIN_VCS (LIBAVUTIL_VERSION_MAJOR < 60) + +/** + * @} + * @} + */ + +#endif /* AVUTIL_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libswscale/swscale.h b/src/framework/media/thirdparty/ffmpeg/v7/libswscale/swscale.h new file mode 100644 index 0000000000000..9d4612aaf3a64 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libswscale/swscale.h @@ -0,0 +1,436 @@ +/* + * Copyright (C) 2001-2011 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_SWSCALE_H +#define SWSCALE_SWSCALE_H + +/** + * @file + * @ingroup libsws + * external API header + */ + +#include + +#include "libavutil/avutil.h" +#include "libavutil/frame.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "version.h" +#endif + +/** + * @defgroup libsws libswscale + * Color conversion and scaling library. + * + * @{ + * + * Return the LIBSWSCALE_VERSION_INT constant. + */ +unsigned swscale_version(void); + +/** + * Return the libswscale build-time configuration. + */ +const char *swscale_configuration(void); + +/** + * Return the libswscale license. + */ +const char *swscale_license(void); + +/* values for the flags, the stuff on the command line is different */ +#define SWS_FAST_BILINEAR 1 +#define SWS_BILINEAR 2 +#define SWS_BICUBIC 4 +#define SWS_X 8 +#define SWS_POINT 0x10 +#define SWS_AREA 0x20 +#define SWS_BICUBLIN 0x40 +#define SWS_GAUSS 0x80 +#define SWS_SINC 0x100 +#define SWS_LANCZOS 0x200 +#define SWS_SPLINE 0x400 + +#define SWS_SRC_V_CHR_DROP_MASK 0x30000 +#define SWS_SRC_V_CHR_DROP_SHIFT 16 + +#define SWS_PARAM_DEFAULT 123456 + +#define SWS_PRINT_INFO 0x1000 + +//the following 3 flags are not completely implemented +//internal chrominance subsampling info +#define SWS_FULL_CHR_H_INT 0x2000 +//input subsampling info +#define SWS_FULL_CHR_H_INP 0x4000 +#define SWS_DIRECT_BGR 0x8000 +#define SWS_ACCURATE_RND 0x40000 +#define SWS_BITEXACT 0x80000 +#define SWS_ERROR_DIFFUSION 0x800000 + +#define SWS_MAX_REDUCE_CUTOFF 0.002 + +#define SWS_CS_ITU709 1 +#define SWS_CS_FCC 4 +#define SWS_CS_ITU601 5 +#define SWS_CS_ITU624 5 +#define SWS_CS_SMPTE170M 5 +#define SWS_CS_SMPTE240M 7 +#define SWS_CS_DEFAULT 5 +#define SWS_CS_BT2020 9 + +/** + * Return a pointer to yuv<->rgb coefficients for the given colorspace + * suitable for sws_setColorspaceDetails(). + * + * @param colorspace One of the SWS_CS_* macros. If invalid, + * SWS_CS_DEFAULT is used. + */ +const int *sws_getCoefficients(int colorspace); + +// when used for filters they must have an odd number of elements +// coeffs cannot be shared between vectors +typedef struct SwsVector { + double *coeff; ///< pointer to the list of coefficients + int length; ///< number of coefficients in the vector +} SwsVector; + +// vectors can be shared +typedef struct SwsFilter { + SwsVector *lumH; + SwsVector *lumV; + SwsVector *chrH; + SwsVector *chrV; +} SwsFilter; + +struct SwsContext; + +/** + * Return a positive value if pix_fmt is a supported input format, 0 + * otherwise. + */ +int sws_isSupportedInput(enum AVPixelFormat pix_fmt); + +/** + * Return a positive value if pix_fmt is a supported output format, 0 + * otherwise. + */ +int sws_isSupportedOutput(enum AVPixelFormat pix_fmt); + +/** + * @param[in] pix_fmt the pixel format + * @return a positive value if an endianness conversion for pix_fmt is + * supported, 0 otherwise. + */ +int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt); + +/** + * Allocate an empty SwsContext. This must be filled and passed to + * sws_init_context(). For filling see AVOptions, options.c and + * sws_setColorspaceDetails(). + */ +struct SwsContext *sws_alloc_context(void); + +/** + * Initialize the swscaler context sws_context. + * + * @return zero or positive value on success, a negative value on + * error + */ +av_warn_unused_result +int sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter); + +/** + * Free the swscaler context swsContext. + * If swsContext is NULL, then does nothing. + */ +void sws_freeContext(struct SwsContext *swsContext); + +/** + * Allocate and return an SwsContext. You need it to perform + * scaling/conversion operations using sws_scale(). + * + * @param srcW the width of the source image + * @param srcH the height of the source image + * @param srcFormat the source image format + * @param dstW the width of the destination image + * @param dstH the height of the destination image + * @param dstFormat the destination image format + * @param flags specify which algorithm and options to use for rescaling + * @param param extra parameters to tune the used scaler + * For SWS_BICUBIC param[0] and [1] tune the shape of the basis + * function, param[0] tunes f(1) and param[1] f´(1) + * For SWS_GAUSS param[0] tunes the exponent and thus cutoff + * frequency + * For SWS_LANCZOS param[0] tunes the width of the window function + * @return a pointer to an allocated context, or NULL in case of error + * @note this function is to be removed after a saner alternative is + * written + */ +struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, + int dstW, int dstH, enum AVPixelFormat dstFormat, + int flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param); + +/** + * Scale the image slice in srcSlice and put the resulting scaled + * slice in the image in dst. A slice is a sequence of consecutive + * rows in an image. + * + * Slices have to be provided in sequential order, either in + * top-bottom or bottom-top order. If slices are provided in + * non-sequential order the behavior of the function is undefined. + * + * @param c the scaling context previously created with + * sws_getContext() + * @param srcSlice the array containing the pointers to the planes of + * the source slice + * @param srcStride the array containing the strides for each plane of + * the source image + * @param srcSliceY the position in the source image of the slice to + * process, that is the number (counted starting from + * zero) in the image of the first row of the slice + * @param srcSliceH the height of the source slice, that is the number + * of rows in the slice + * @param dst the array containing the pointers to the planes of + * the destination image + * @param dstStride the array containing the strides for each plane of + * the destination image + * @return the height of the output slice + */ +int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], + const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *const dst[], const int dstStride[]); + +/** + * Scale source data from src and write the output to dst. + * + * This is merely a convenience wrapper around + * - sws_frame_start() + * - sws_send_slice(0, src->height) + * - sws_receive_slice(0, dst->height) + * - sws_frame_end() + * + * @param c The scaling context + * @param dst The destination frame. See documentation for sws_frame_start() for + * more details. + * @param src The source frame. + * + * @return 0 on success, a negative AVERROR code on failure + */ +int sws_scale_frame(struct SwsContext *c, AVFrame *dst, const AVFrame *src); + +/** + * Initialize the scaling process for a given pair of source/destination frames. + * Must be called before any calls to sws_send_slice() and sws_receive_slice(). + * + * This function will retain references to src and dst, so they must both use + * refcounted buffers (if allocated by the caller, in case of dst). + * + * @param c The scaling context + * @param dst The destination frame. + * + * The data buffers may either be already allocated by the caller or + * left clear, in which case they will be allocated by the scaler. + * The latter may have performance advantages - e.g. in certain cases + * some output planes may be references to input planes, rather than + * copies. + * + * Output data will be written into this frame in successful + * sws_receive_slice() calls. + * @param src The source frame. The data buffers must be allocated, but the + * frame data does not have to be ready at this point. Data + * availability is then signalled by sws_send_slice(). + * @return 0 on success, a negative AVERROR code on failure + * + * @see sws_frame_end() + */ +int sws_frame_start(struct SwsContext *c, AVFrame *dst, const AVFrame *src); + +/** + * Finish the scaling process for a pair of source/destination frames previously + * submitted with sws_frame_start(). Must be called after all sws_send_slice() + * and sws_receive_slice() calls are done, before any new sws_frame_start() + * calls. + * + * @param c The scaling context + */ +void sws_frame_end(struct SwsContext *c); + +/** + * Indicate that a horizontal slice of input data is available in the source + * frame previously provided to sws_frame_start(). The slices may be provided in + * any order, but may not overlap. For vertically subsampled pixel formats, the + * slices must be aligned according to subsampling. + * + * @param c The scaling context + * @param slice_start first row of the slice + * @param slice_height number of rows in the slice + * + * @return a non-negative number on success, a negative AVERROR code on failure. + */ +int sws_send_slice(struct SwsContext *c, unsigned int slice_start, + unsigned int slice_height); + +/** + * Request a horizontal slice of the output data to be written into the frame + * previously provided to sws_frame_start(). + * + * @param c The scaling context + * @param slice_start first row of the slice; must be a multiple of + * sws_receive_slice_alignment() + * @param slice_height number of rows in the slice; must be a multiple of + * sws_receive_slice_alignment(), except for the last slice + * (i.e. when slice_start+slice_height is equal to output + * frame height) + * + * @return a non-negative number if the data was successfully written into the output + * AVERROR(EAGAIN) if more input data needs to be provided before the + * output can be produced + * another negative AVERROR code on other kinds of scaling failure + */ +int sws_receive_slice(struct SwsContext *c, unsigned int slice_start, + unsigned int slice_height); + +/** + * Get the alignment required for slices + * + * @param c The scaling context + * @return alignment required for output slices requested with sws_receive_slice(). + * Slice offsets and sizes passed to sws_receive_slice() must be + * multiples of the value returned from this function. + */ +unsigned int sws_receive_slice_alignment(const struct SwsContext *c); + +/** + * @param c the scaling context + * @param dstRange flag indicating the while-black range of the output (1=jpeg / 0=mpeg) + * @param srcRange flag indicating the while-black range of the input (1=jpeg / 0=mpeg) + * @param table the yuv2rgb coefficients describing the output yuv space, normally ff_yuv2rgb_coeffs[x] + * @param inv_table the yuv2rgb coefficients describing the input yuv space, normally ff_yuv2rgb_coeffs[x] + * @param brightness 16.16 fixed point brightness correction + * @param contrast 16.16 fixed point contrast correction + * @param saturation 16.16 fixed point saturation correction + * + * @return A negative error code on error, non negative otherwise. + * If `LIBSWSCALE_VERSION_MAJOR < 7`, returns -1 if not supported. + */ +int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], + int srcRange, const int table[4], int dstRange, + int brightness, int contrast, int saturation); + +/** + * @return A negative error code on error, non negative otherwise. + * If `LIBSWSCALE_VERSION_MAJOR < 7`, returns -1 if not supported. + */ +int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table, + int *srcRange, int **table, int *dstRange, + int *brightness, int *contrast, int *saturation); + +/** + * Allocate and return an uninitialized vector with length coefficients. + */ +SwsVector *sws_allocVec(int length); + +/** + * Return a normalized Gaussian curve used to filter stuff + * quality = 3 is high quality, lower is lower quality. + */ +SwsVector *sws_getGaussianVec(double variance, double quality); + +/** + * Scale all the coefficients of a by the scalar value. + */ +void sws_scaleVec(SwsVector *a, double scalar); + +/** + * Scale all the coefficients of a so that their sum equals height. + */ +void sws_normalizeVec(SwsVector *a, double height); + +void sws_freeVec(SwsVector *a); + +SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, + float lumaSharpen, float chromaSharpen, + float chromaHShift, float chromaVShift, + int verbose); +void sws_freeFilter(SwsFilter *filter); + +/** + * Check if context can be reused, otherwise reallocate a new one. + * + * If context is NULL, just calls sws_getContext() to get a new + * context. Otherwise, checks if the parameters are the ones already + * saved in context. If that is the case, returns the current + * context. Otherwise, frees context and gets a new context with + * the new parameters. + * + * Be warned that srcFilter and dstFilter are not checked, they + * are assumed to remain the same. + */ +struct SwsContext *sws_getCachedContext(struct SwsContext *context, + int srcW, int srcH, enum AVPixelFormat srcFormat, + int dstW, int dstH, enum AVPixelFormat dstFormat, + int flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 32 bits. + * + * The output frame will have the same packed format as the palette. + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 24 bits. + * + * With the palette format "ABCD", the destination frame ends up with the format "ABC". + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Get the AVClass for swsContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *sws_get_class(void); + +/** + * @} + */ + +#endif /* SWSCALE_SWSCALE_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libswscale/version.h b/src/framework/media/thirdparty/ffmpeg/v7/libswscale/version.h new file mode 100644 index 0000000000000..4e54701aba888 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libswscale/version.h @@ -0,0 +1,44 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_VERSION_H +#define SWSCALE_VERSION_H + +/** + * @file + * swscale version macros + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBSWSCALE_VERSION_MINOR 1 +#define LIBSWSCALE_VERSION_MICRO 100 + +#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_VERSION AV_VERSION(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_BUILD LIBSWSCALE_VERSION_INT + +#define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION) + +#endif /* SWSCALE_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libswscale/version_major.h b/src/framework/media/thirdparty/ffmpeg/v7/libswscale/version_major.h new file mode 100644 index 0000000000000..fd259f959d131 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libswscale/version_major.h @@ -0,0 +1,35 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_VERSION_MAJOR_H +#define SWSCALE_VERSION_MAJOR_H + +/** + * @file + * swscale version macros + */ + +#define LIBSWSCALE_VERSION_MAJOR 8 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + */ + +#endif /* SWSCALE_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/avcodec.h b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/avcodec.h new file mode 100644 index 0000000000000..108df5a24e9d6 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/avcodec.h @@ -0,0 +1,2947 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AVCODEC_H +#define AVCODEC_AVCODEC_H + +/** + * @file + * @ingroup libavc + * Libavcodec external API header + */ + +#include "libavutil/samplefmt.h" +#include "libavutil/attributes.h" +#include "libavutil/avutil.h" +#include "libavutil/buffer.h" +#include "libavutil/channel_layout.h" +#include "libavutil/dict.h" +#include "libavutil/frame.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +#include "codec.h" +#include "codec_id.h" +#include "defs.h" +#include "packet.h" +#include "version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "version.h" + +#include "codec_desc.h" +#include "codec_par.h" +#endif + +struct AVCodecParameters; + +/** + * @defgroup libavc libavcodec + * Encoding/Decoding Library + * + * @{ + * + * @defgroup lavc_decoding Decoding + * @{ + * @} + * + * @defgroup lavc_encoding Encoding + * @{ + * @} + * + * @defgroup lavc_codec Codecs + * @{ + * @defgroup lavc_codec_native Native Codecs + * @{ + * @} + * @defgroup lavc_codec_wrappers External library wrappers + * @{ + * @} + * @defgroup lavc_codec_hwaccel Hardware Accelerators bridge + * @{ + * @} + * @} + * @defgroup lavc_internal Internal + * @{ + * @} + * @} + */ + +/** + * @ingroup libavc + * @defgroup lavc_encdec send/receive encoding and decoding API overview + * @{ + * + * The avcodec_send_packet()/avcodec_receive_frame()/avcodec_send_frame()/ + * avcodec_receive_packet() functions provide an encode/decode API, which + * decouples input and output. + * + * The API is very similar for encoding/decoding and audio/video, and works as + * follows: + * - Set up and open the AVCodecContext as usual. + * - Send valid input: + * - For decoding, call avcodec_send_packet() to give the decoder raw + * compressed data in an AVPacket. + * - For encoding, call avcodec_send_frame() to give the encoder an AVFrame + * containing uncompressed audio or video. + * + * In both cases, it is recommended that AVPackets and AVFrames are + * refcounted, or libavcodec might have to copy the input data. (libavformat + * always returns refcounted AVPackets, and av_frame_get_buffer() allocates + * refcounted AVFrames.) + * - Receive output in a loop. Periodically call one of the avcodec_receive_*() + * functions and process their output: + * - For decoding, call avcodec_receive_frame(). On success, it will return + * an AVFrame containing uncompressed audio or video data. + * - For encoding, call avcodec_receive_packet(). On success, it will return + * an AVPacket with a compressed frame. + * + * Repeat this call until it returns AVERROR(EAGAIN) or an error. The + * AVERROR(EAGAIN) return value means that new input data is required to + * return new output. In this case, continue with sending input. For each + * input frame/packet, the codec will typically return 1 output frame/packet, + * but it can also be 0 or more than 1. + * + * At the beginning of decoding or encoding, the codec might accept multiple + * input frames/packets without returning a frame, until its internal buffers + * are filled. This situation is handled transparently if you follow the steps + * outlined above. + * + * In theory, sending input can result in EAGAIN - this should happen only if + * not all output was received. You can use this to structure alternative decode + * or encode loops other than the one suggested above. For example, you could + * try sending new input on each iteration, and try to receive output if that + * returns EAGAIN. + * + * End of stream situations. These require "flushing" (aka draining) the codec, + * as the codec might buffer multiple frames or packets internally for + * performance or out of necessity (consider B-frames). + * This is handled as follows: + * - Instead of valid input, send NULL to the avcodec_send_packet() (decoding) + * or avcodec_send_frame() (encoding) functions. This will enter draining + * mode. + * - Call avcodec_receive_frame() (decoding) or avcodec_receive_packet() + * (encoding) in a loop until AVERROR_EOF is returned. The functions will + * not return AVERROR(EAGAIN), unless you forgot to enter draining mode. + * - Before decoding can be resumed again, the codec has to be reset with + * avcodec_flush_buffers(). + * + * Using the API as outlined above is highly recommended. But it is also + * possible to call functions outside of this rigid schema. For example, you can + * call avcodec_send_packet() repeatedly without calling + * avcodec_receive_frame(). In this case, avcodec_send_packet() will succeed + * until the codec's internal buffer has been filled up (which is typically of + * size 1 per output frame, after initial input), and then reject input with + * AVERROR(EAGAIN). Once it starts rejecting input, you have no choice but to + * read at least some output. + * + * Not all codecs will follow a rigid and predictable dataflow; the only + * guarantee is that an AVERROR(EAGAIN) return value on a send/receive call on + * one end implies that a receive/send call on the other end will succeed, or + * at least will not fail with AVERROR(EAGAIN). In general, no codec will + * permit unlimited buffering of input or output. + * + * A codec is not allowed to return AVERROR(EAGAIN) for both sending and receiving. This + * would be an invalid state, which could put the codec user into an endless + * loop. The API has no concept of time either: it cannot happen that trying to + * do avcodec_send_packet() results in AVERROR(EAGAIN), but a repeated call 1 second + * later accepts the packet (with no other receive/flush API calls involved). + * The API is a strict state machine, and the passage of time is not supposed + * to influence it. Some timing-dependent behavior might still be deemed + * acceptable in certain cases. But it must never result in both send/receive + * returning EAGAIN at the same time at any point. It must also absolutely be + * avoided that the current state is "unstable" and can "flip-flop" between + * the send/receive APIs allowing progress. For example, it's not allowed that + * the codec randomly decides that it actually wants to consume a packet now + * instead of returning a frame, after it just returned AVERROR(EAGAIN) on an + * avcodec_send_packet() call. + * @} + */ + +/** + * @defgroup lavc_core Core functions/structures. + * @ingroup libavc + * + * Basic definitions, functions for querying libavcodec capabilities, + * allocating core structures, etc. + * @{ + */ + +/** + * @ingroup lavc_encoding + */ +typedef struct RcOverride{ + int start_frame; + int end_frame; + int qscale; // If this is 0 then quality_factor will be used instead. + float quality_factor; +} RcOverride; + +/* encoding support + These flags can be passed in AVCodecContext.flags before initialization. + Note: Not everything is supported yet. +*/ + +/** + * Allow decoders to produce frames with data planes that are not aligned + * to CPU requirements (e.g. due to cropping). + */ +#define AV_CODEC_FLAG_UNALIGNED (1 << 0) +/** + * Use fixed qscale. + */ +#define AV_CODEC_FLAG_QSCALE (1 << 1) +/** + * 4 MV per MB allowed / advanced prediction for H.263. + */ +#define AV_CODEC_FLAG_4MV (1 << 2) +/** + * Output even those frames that might be corrupted. + */ +#define AV_CODEC_FLAG_OUTPUT_CORRUPT (1 << 3) +/** + * Use qpel MC. + */ +#define AV_CODEC_FLAG_QPEL (1 << 4) +/** + * Request the encoder to output reconstructed frames, i.e.\ frames that would + * be produced by decoding the encoded bitstream. These frames may be retrieved + * by calling avcodec_receive_frame() immediately after a successful call to + * avcodec_receive_packet(). + * + * Should only be used with encoders flagged with the + * @ref AV_CODEC_CAP_ENCODER_RECON_FRAME capability. + * + * @note + * Each reconstructed frame returned by the encoder corresponds to the last + * encoded packet, i.e. the frames are returned in coded order rather than + * presentation order. + * + * @note + * Frame parameters (like pixel format or dimensions) do not have to match the + * AVCodecContext values. Make sure to use the values from the returned frame. + */ +#define AV_CODEC_FLAG_RECON_FRAME (1 << 6) +/** + * @par decoding + * Request the decoder to propagate each packet's AVPacket.opaque and + * AVPacket.opaque_ref to its corresponding output AVFrame. + * + * @par encoding: + * Request the encoder to propagate each frame's AVFrame.opaque and + * AVFrame.opaque_ref values to its corresponding output AVPacket. + * + * @par + * May only be set on encoders that have the + * @ref AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability flag. + * + * @note + * While in typical cases one input frame produces exactly one output packet + * (perhaps after a delay), in general the mapping of frames to packets is + * M-to-N, so + * - Any number of input frames may be associated with any given output packet. + * This includes zero - e.g. some encoders may output packets that carry only + * metadata about the whole stream. + * - A given input frame may be associated with any number of output packets. + * Again this includes zero - e.g. some encoders may drop frames under certain + * conditions. + * . + * This implies that when using this flag, the caller must NOT assume that + * - a given input frame's opaques will necessarily appear on some output packet; + * - every output packet will have some non-NULL opaque value. + * . + * When an output packet contains multiple frames, the opaque values will be + * taken from the first of those. + * + * @note + * The converse holds for decoders, with frames and packets switched. + */ +#define AV_CODEC_FLAG_COPY_OPAQUE (1 << 7) +/** + * Signal to the encoder that the values of AVFrame.duration are valid and + * should be used (typically for transferring them to output packets). + * + * If this flag is not set, frame durations are ignored. + */ +#define AV_CODEC_FLAG_FRAME_DURATION (1 << 8) +/** + * Use internal 2pass ratecontrol in first pass mode. + */ +#define AV_CODEC_FLAG_PASS1 (1 << 9) +/** + * Use internal 2pass ratecontrol in second pass mode. + */ +#define AV_CODEC_FLAG_PASS2 (1 << 10) +/** + * loop filter. + */ +#define AV_CODEC_FLAG_LOOP_FILTER (1 << 11) +/** + * Only decode/encode grayscale. + */ +#define AV_CODEC_FLAG_GRAY (1 << 13) +/** + * error[?] variables will be set during encoding. + */ +#define AV_CODEC_FLAG_PSNR (1 << 15) +/** + * Use interlaced DCT. + */ +#define AV_CODEC_FLAG_INTERLACED_DCT (1 << 18) +/** + * Force low delay. + */ +#define AV_CODEC_FLAG_LOW_DELAY (1 << 19) +/** + * Place global headers in extradata instead of every keyframe. + */ +#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22) +/** + * Use only bitexact stuff (except (I)DCT). + */ +#define AV_CODEC_FLAG_BITEXACT (1 << 23) +/* Fx : Flag for H.263+ extra options */ +/** + * H.263 advanced intra coding / MPEG-4 AC prediction + */ +#define AV_CODEC_FLAG_AC_PRED (1 << 24) +/** + * interlaced motion estimation + */ +#define AV_CODEC_FLAG_INTERLACED_ME (1 << 29) +#define AV_CODEC_FLAG_CLOSED_GOP (1U << 31) + +/** + * Allow non spec compliant speedup tricks. + */ +#define AV_CODEC_FLAG2_FAST (1 << 0) +/** + * Skip bitstream encoding. + */ +#define AV_CODEC_FLAG2_NO_OUTPUT (1 << 2) +/** + * Place global headers at every keyframe instead of in extradata. + */ +#define AV_CODEC_FLAG2_LOCAL_HEADER (1 << 3) + +/** + * Input bitstream might be truncated at a packet boundaries + * instead of only at frame boundaries. + */ +#define AV_CODEC_FLAG2_CHUNKS (1 << 15) +/** + * Discard cropping information from SPS. + */ +#define AV_CODEC_FLAG2_IGNORE_CROP (1 << 16) + +/** + * Show all frames before the first keyframe + */ +#define AV_CODEC_FLAG2_SHOW_ALL (1 << 22) +/** + * Export motion vectors through frame side data + */ +#define AV_CODEC_FLAG2_EXPORT_MVS (1 << 28) +/** + * Do not skip samples and export skip information as frame side data + */ +#define AV_CODEC_FLAG2_SKIP_MANUAL (1 << 29) +/** + * Do not reset ASS ReadOrder field on flush (subtitles decoding) + */ +#define AV_CODEC_FLAG2_RO_FLUSH_NOOP (1 << 30) +/** + * Generate/parse ICC profiles on encode/decode, as appropriate for the type of + * file. No effect on codecs which cannot contain embedded ICC profiles, or + * when compiled without support for lcms2. + */ +#define AV_CODEC_FLAG2_ICC_PROFILES (1U << 31) + +/* Exported side data. + These flags can be passed in AVCodecContext.export_side_data before initialization. +*/ +/** + * Export motion vectors through frame side data + */ +#define AV_CODEC_EXPORT_DATA_MVS (1 << 0) +/** + * Export encoder Producer Reference Time through packet side data + */ +#define AV_CODEC_EXPORT_DATA_PRFT (1 << 1) +/** + * Decoding only. + * Export the AVVideoEncParams structure through frame side data. + */ +#define AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS (1 << 2) +/** + * Decoding only. + * Do not apply film grain, export it instead. + */ +#define AV_CODEC_EXPORT_DATA_FILM_GRAIN (1 << 3) + +/** + * Decoding only. + * Do not apply picture enhancement layers, export them instead. + */ +#define AV_CODEC_EXPORT_DATA_ENHANCEMENTS (1 << 4) + +/** + * The decoder will keep a reference to the frame and may reuse it later. + */ +#define AV_GET_BUFFER_FLAG_REF (1 << 0) + +/** + * The encoder will keep a reference to the packet and may reuse it later. + */ +#define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0) + +/** + * main external API structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * You can use AVOptions (av_opt* / av_set/get*()) to access these fields from user + * applications. + * The name string for AVOptions options matches the associated command line + * parameter name and can be found in libavcodec/options_table.h + * The AVOption/command line parameter names differ in some cases from the C + * structure field names for historic reasons or brevity. + * sizeof(AVCodecContext) must not be used outside libav*. + */ +typedef struct AVCodecContext { + /** + * information on struct for av_log + * - set by avcodec_alloc_context3 + */ + const AVClass *av_class; + int log_level_offset; + + enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ + const struct AVCodec *codec; + enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ + + /** + * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * This is used to work around some encoder bugs. + * A demuxer should set this to what is stored in the field used to identify the codec. + * If there are multiple such fields in a container then the demuxer should choose the one + * which maximizes the information about the used codec. + * If the codec tag field in a container is larger than 32 bits then the demuxer should + * remap the longer ID to 32 bits with a table or other structure. Alternatively a new + * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated + * first. + * - encoding: Set by user, if not then the default based on codec_id will be used. + * - decoding: Set by user, will be converted to uppercase by libavcodec during init. + */ + unsigned int codec_tag; + + void *priv_data; + + /** + * Private context used for internal data. + * + * Unlike priv_data, this is not codec-specific. It is used in general + * libavcodec functions. + */ + struct AVCodecInternal *internal; + + /** + * Private data of the user, can be used to carry app specific stuff. + * - encoding: Set by user. + * - decoding: Set by user. + */ + void *opaque; + + /** + * the average bitrate + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: Set by user, may be overwritten by libavcodec + * if this info is available in the stream + */ + int64_t bit_rate; + + /** + * AV_CODEC_FLAG_*. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags; + + /** + * AV_CODEC_FLAG2_* + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags2; + + /** + * Out-of-band global headers that may be used by some codecs. + * + * - decoding: Should be set by the caller when available (typically from a + * demuxer) before opening the decoder; some decoders require this to be + * set and will fail to initialize otherwise. + * + * The array must be allocated with the av_malloc() family of functions; + * allocated size must be at least AV_INPUT_BUFFER_PADDING_SIZE bytes + * larger than extradata_size. + * + * - encoding: May be set by the encoder in avcodec_open2() (possibly + * depending on whether the AV_CODEC_FLAG_GLOBAL_HEADER flag is set). + * + * After being set, the array is owned by the codec and freed in + * avcodec_free_context(). + */ + uint8_t *extradata; + int extradata_size; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. For fixed-fps content, + * timebase should be 1/framerate and timestamp increments should be + * identically 1. + * This often, but not always is the inverse of the frame rate or field rate + * for video. 1/time_base is not the average frame rate if the frame rate is not + * constant. + * + * Like containers, elementary streams also can store timestamps, 1/time_base + * is the unit in which these timestamps are specified. + * As example of such codec time base see ISO/IEC 14496-2:2001(E) + * vop_time_increment_resolution and fixed_vop_rate + * (fixed_vop_rate == 0 implies that it is different from the framerate) + * + * - encoding: MUST be set by user. + * - decoding: unused. + */ + AVRational time_base; + + /** + * Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed. + * - encoding: unused. + * - decoding: set by user. + */ + AVRational pkt_timebase; + + /** + * - decoding: For codecs that store a framerate value in the compressed + * bitstream, the decoder may export it here. { 0, 1} when + * unknown. + * - encoding: May be used to signal the framerate of CFR content to an + * encoder. + */ + AVRational framerate; + + /** + * Codec delay. + * + * Encoding: Number of frames delay there will be from the encoder input to + * the decoder output. (we assume the decoder matches the spec) + * Decoding: Number of frames delay in addition to what a standard decoder + * as specified in the spec would produce. + * + * Video: + * Number of frames the decoded output will be delayed relative to the + * encoded input. + * + * Audio: + * For encoding, this field is unused (see initial_padding). + * + * For decoding, this is the number of samples the decoder needs to + * output before the decoder's output is valid. When seeking, you should + * start decoding this many samples prior to your desired seek point. + * + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int delay; + + + /* video only */ + /** + * picture width / height. + * + * @note Those fields may not match the values of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: MUST be set by user. + * - decoding: May be set by the user before opening the decoder if known e.g. + * from the container. Some decoders will require the dimensions + * to be set by the caller. During decoding, the decoder may + * overwrite those values as required while parsing the data. + */ + int width, height; + + /** + * Bitstream width / height, may be different from width/height e.g. when + * the decoded frame is cropped before being output or lowres is enabled. + * + * @note Those field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: unused + * - decoding: May be set by the user before opening the decoder if known + * e.g. from the container. During decoding, the decoder may + * overwrite those values as required while parsing the data. + */ + int coded_width, coded_height; + + /** + * sample aspect ratio (0 if unknown) + * That is the width of a pixel divided by the height of the pixel. + * Numerator and denominator must be relatively prime and smaller than 256 for some video standards. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVRational sample_aspect_ratio; + + /** + * Pixel format, see AV_PIX_FMT_xxx. + * May be set by the demuxer if known from headers. + * May be overridden by the decoder if it knows better. + * + * @note This field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: Set by user. + * - decoding: Set by user if known, overridden by libavcodec while + * parsing the data. + */ + enum AVPixelFormat pix_fmt; + + /** + * Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx. + * - encoding: unused. + * - decoding: Set by libavcodec before calling get_format() + */ + enum AVPixelFormat sw_pix_fmt; + + /** + * Chromaticity coordinates of the source primaries. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorPrimaries color_primaries; + + /** + * Color Transfer Characteristic. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user to override the default output color range value, + * If not specified, libavcodec sets the color range depending on the + * output format. + * - decoding: Set by libavcodec, can be set by the user to propagate the + * color range to components reading from the decoder context. + */ + enum AVColorRange color_range; + + /** + * This defines the location of chroma samples. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVChromaLocation chroma_sample_location; + + /** Field order + * - encoding: set by libavcodec + * - decoding: Set by user. + */ + enum AVFieldOrder field_order; + + /** + * number of reference frames + * - encoding: Set by user. + * - decoding: Set by lavc. + */ + int refs; + + /** + * Size of the frame reordering buffer in the decoder. + * For MPEG-2 it is 1 IPB or 0 low delay IP. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int has_b_frames; + + /** + * slice flags + * - encoding: unused + * - decoding: Set by user. + */ + int slice_flags; +#define SLICE_FLAG_CODED_ORDER 0x0001 ///< draw_horiz_band() is called in coded order instead of display +#define SLICE_FLAG_ALLOW_FIELD 0x0002 ///< allow draw_horiz_band() with field slices (MPEG-2 field pics) +#define SLICE_FLAG_ALLOW_PLANE 0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1) + + /** + * If non NULL, 'draw_horiz_band' is called by the libavcodec + * decoder to draw a horizontal band. It improves cache usage. Not + * all codecs can do that. You must check the codec capabilities + * beforehand. + * When multithreading is used, it may be called from multiple threads + * at the same time; threads might draw different parts of the same AVFrame, + * or multiple AVFrames, and there is no guarantee that slices will be drawn + * in order. + * The function is also used by hardware acceleration APIs. + * It is called at least once during frame decoding to pass + * the data needed for hardware render. + * In that mode instead of pixel data, AVFrame points to + * a structure specific to the acceleration API. The application + * reads the structure and can change some fields to indicate progress + * or mark state. + * - encoding: unused + * - decoding: Set by user. + * @param height the height of the slice + * @param y the y position of the slice + * @param type 1->top field, 2->bottom field, 3->frame + * @param offset offset into the AVFrame.data from which the slice should be read + */ + void (*draw_horiz_band)(struct AVCodecContext *s, + const AVFrame *src, int offset[AV_NUM_DATA_POINTERS], + int y, int type, int height); + + /** + * Callback to negotiate the pixel format. Decoding only, may be set by the + * caller before avcodec_open2(). + * + * Called by some decoders to select the pixel format that will be used for + * the output frames. This is mainly used to set up hardware acceleration, + * then the provided format list contains the corresponding hwaccel pixel + * formats alongside the "software" one. The software pixel format may also + * be retrieved from \ref sw_pix_fmt. + * + * This callback will be called when the coded frame properties (such as + * resolution, pixel format, etc.) change and more than one output format is + * supported for those new properties. If a hardware pixel format is chosen + * and initialization for it fails, the callback may be called again + * immediately. + * + * This callback may be called from different threads if the decoder is + * multi-threaded, but not from more than one thread simultaneously. + * + * @param fmt list of formats which may be used in the current + * configuration, terminated by AV_PIX_FMT_NONE. + * @warning Behavior is undefined if the callback returns a value other + * than one of the formats in fmt or AV_PIX_FMT_NONE. + * @return the chosen format or AV_PIX_FMT_NONE + */ + enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + + /** + * maximum number of B-frames between non-B-frames + * Note: The output will be delayed by max_b_frames+1 relative to the input. + * - encoding: Set by user. + * - decoding: unused + */ + int max_b_frames; + + /** + * qscale factor between IP and B-frames + * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_factor; + + /** + * qscale offset between IP and B-frames + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_offset; + + /** + * qscale factor between P- and I-frames + * If > 0 then the last P-frame quantizer will be used (q = lastp_q * factor + offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_factor; + + /** + * qscale offset between P and I-frames + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_offset; + + /** + * luminance masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float lumi_masking; + + /** + * temporary complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float temporal_cplx_masking; + + /** + * spatial complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float spatial_cplx_masking; + + /** + * p block masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float p_masking; + + /** + * darkness masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float dark_masking; + + /** + * noise vs. sse weight for the nsse comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int nsse_weight; + + /** + * motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_cmp; + /** + * subpixel motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_sub_cmp; + /** + * macroblock comparison function (not supported yet) + * - encoding: Set by user. + * - decoding: unused + */ + int mb_cmp; + /** + * interlaced DCT comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int ildct_cmp; +#define FF_CMP_SAD 0 +#define FF_CMP_SSE 1 +#define FF_CMP_SATD 2 +#define FF_CMP_DCT 3 +#define FF_CMP_PSNR 4 +#define FF_CMP_BIT 5 +#define FF_CMP_RD 6 +#define FF_CMP_ZERO 7 +#define FF_CMP_VSAD 8 +#define FF_CMP_VSSE 9 +#define FF_CMP_NSSE 10 +#define FF_CMP_W53 11 +#define FF_CMP_W97 12 +#define FF_CMP_DCTMAX 13 +#define FF_CMP_DCT264 14 +#define FF_CMP_MEDIAN_SAD 15 +#define FF_CMP_CHROMA 256 + + /** + * ME diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int dia_size; + + /** + * amount of previous MV predictors (2a+1 x 2a+1 square) + * - encoding: Set by user. + * - decoding: unused + */ + int last_predictor_count; + + /** + * motion estimation prepass comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_pre_cmp; + + /** + * ME prepass diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int pre_dia_size; + + /** + * subpel ME quality + * - encoding: Set by user. + * - decoding: unused + */ + int me_subpel_quality; + + /** + * maximum motion estimation search range in subpel units + * If 0 then no limit. + * + * - encoding: Set by user. + * - decoding: unused + */ + int me_range; + + /** + * macroblock decision mode + * - encoding: Set by user. + * - decoding: unused + */ + int mb_decision; +#define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp +#define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits +#define FF_MB_DECISION_RD 2 ///< rate distortion + + /** + * custom intra quantization matrix + * Must be allocated with the av_malloc() family of functions, and will be freed in + * avcodec_free_context(). + * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL. + * - decoding: Set/allocated/freed by libavcodec. + */ + uint16_t *intra_matrix; + + /** + * custom inter quantization matrix + * Must be allocated with the av_malloc() family of functions, and will be freed in + * avcodec_free_context(). + * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL. + * - decoding: Set/allocated/freed by libavcodec. + */ + uint16_t *inter_matrix; + + /** + * custom intra quantization matrix + * - encoding: Set by user, can be NULL. + * - decoding: unused. + */ + uint16_t *chroma_intra_matrix; + + /** + * precision of the intra DC coefficient - 8 + * - encoding: Set by user. + * - decoding: Set by libavcodec + */ + int intra_dc_precision; + + /** + * minimum MB Lagrange multiplier + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmin; + + /** + * maximum MB Lagrange multiplier + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmax; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int bidir_refine; + + /** + * minimum GOP size + * - encoding: Set by user. + * - decoding: unused + */ + int keyint_min; + + /** + * the number of pictures in a group of pictures, or 0 for intra_only + * - encoding: Set by user. + * - decoding: unused + */ + int gop_size; + + /** + * Note: Value depends upon the compare function used for fullpel ME. + * - encoding: Set by user. + * - decoding: unused + */ + int mv0_threshold; + + /** + * Number of slices. + * Indicates number of picture subdivisions. Used for parallelized + * decoding. + * - encoding: Set by user + * - decoding: unused + */ + int slices; + + /* audio only */ + int sample_rate; ///< samples per second + + /** + * audio sample format + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVSampleFormat sample_fmt; ///< sample format + + /** + * Audio channel layout. + * - encoding: must be set by the caller, to one of AVCodec.ch_layouts. + * - decoding: may be set by the caller if known e.g. from the container. + * The decoder can then override during decoding as needed. + */ + AVChannelLayout ch_layout; + + /* The following data should not be initialized. */ + /** + * Number of samples per channel in an audio frame. + * + * - encoding: set by libavcodec in avcodec_open2(). Each submitted frame + * except the last must contain exactly frame_size samples per channel. + * May be 0 when the codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE set, then the + * frame size is not restricted. + * - decoding: may be set by some decoders to indicate constant frame size + */ + int frame_size; + + /** + * number of bytes per packet if constant and known or 0 + * Used by some WAV based audio codecs. + */ + int block_align; + + /** + * Audio cutoff bandwidth (0 means "automatic") + * - encoding: Set by user. + * - decoding: unused + */ + int cutoff; + + /** + * Type of service that the audio stream conveys. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVAudioServiceType audio_service_type; + + /** + * desired sample format + * - encoding: Not used. + * - decoding: Set by user. + * Decoder will decode to this format if it can. + */ + enum AVSampleFormat request_sample_fmt; + + /** + * Audio only. The number of "priming" samples (padding) inserted by the + * encoder at the beginning of the audio. I.e. this number of leading + * decoded samples must be discarded by the caller to get the original audio + * without leading padding. + * + * - decoding: unused + * - encoding: Set by libavcodec. The timestamps on the output packets are + * adjusted by the encoder so that they always refer to the + * first sample of the data actually contained in the packet, + * including any added padding. E.g. if the timebase is + * 1/samplerate and the timestamp of the first input sample is + * 0, the timestamp of the first output packet will be + * -initial_padding. + */ + int initial_padding; + + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + * + * - decoding: unused + * - encoding: unused + */ + int trailing_padding; + + /** + * Number of samples to skip after a discontinuity + * - decoding: unused + * - encoding: set by libavcodec + */ + int seek_preroll; + + /** + * This callback is called at the beginning of each frame to get data + * buffer(s) for it. There may be one contiguous buffer for all the data or + * there may be a buffer per each data plane or anything in between. What + * this means is, you may set however many entries in buf[] you feel necessary. + * Each buffer must be reference-counted using the AVBuffer API (see description + * of buf[] below). + * + * The following fields will be set in the frame before this callback is + * called: + * - format + * - width, height (video only) + * - sample_rate, channel_layout, nb_samples (audio only) + * Their values may differ from the corresponding values in + * AVCodecContext. This callback must use the frame values, not the codec + * context values, to calculate the required buffer size. + * + * This callback must fill the following fields in the frame: + * - data[] + * - linesize[] + * - extended_data: + * * if the data is planar audio with more than 8 channels, then this + * callback must allocate and fill extended_data to contain all pointers + * to all data planes. data[] must hold as many pointers as it can. + * extended_data must be allocated with av_malloc() and will be freed in + * av_frame_unref(). + * * otherwise extended_data must point to data + * - buf[] must contain one or more pointers to AVBufferRef structures. Each of + * the frame's data and extended_data pointers must be contained in these. That + * is, one AVBufferRef for each allocated chunk of memory, not necessarily one + * AVBufferRef per data[] entry. See: av_buffer_create(), av_buffer_alloc(), + * and av_buffer_ref(). + * - extended_buf and nb_extended_buf must be allocated with av_malloc() by + * this callback and filled with the extra buffers if there are more + * buffers than buf[] can hold. extended_buf will be freed in + * av_frame_unref(). + * Decoders will generally initialize the whole buffer before it is output + * but it can in rare error conditions happen that uninitialized data is passed + * through. \important The buffers returned by get_buffer* should thus not contain sensitive + * data. + * + * If AV_CODEC_CAP_DR1 is not set then get_buffer2() must call + * avcodec_default_get_buffer2() instead of providing buffers allocated by + * some other means. + * + * Each data plane must be aligned to the maximum required by the target + * CPU. + * + * @see avcodec_default_get_buffer2() + * + * Video: + * + * If AV_GET_BUFFER_FLAG_REF is set in flags then the frame may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * avcodec_align_dimensions2() should be used to find the required width and + * height, as they normally need to be rounded up to the next multiple of 16. + * + * Some decoders do not support linesizes changing between frames. + * + * If frame multithreading is used, this callback may be called from a + * different thread, but not from more than one at once. Does not need to be + * reentrant. + * + * @see avcodec_align_dimensions2() + * + * Audio: + * + * Decoders request a buffer of a particular size by setting + * AVFrame.nb_samples prior to calling get_buffer2(). The decoder may, + * however, utilize only part of the buffer by setting AVFrame.nb_samples + * to a smaller value in the output frame. + * + * As a convenience, av_samples_get_buffer_size() and + * av_samples_fill_arrays() in libavutil may be used by custom get_buffer2() + * functions to find the required data size and to fill data pointers and + * linesize. In AVFrame.linesize, only linesize[0] may be set for audio + * since all planes must be the same size. + * + * @see av_samples_get_buffer_size(), av_samples_fill_arrays() + * + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + */ + int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags); + + /* - encoding parameters */ + /** + * number of bits the bitstream is allowed to diverge from the reference. + * the reference can be CBR (for CBR pass1) or VBR (for pass2) + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: unused + */ + int bit_rate_tolerance; + + /** + * Global quality for codecs which cannot change it per frame. + * This should be proportional to MPEG-1/2/4 qscale. + * - encoding: Set by user. + * - decoding: unused + */ + int global_quality; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int compression_level; +#define FF_COMPRESSION_DEFAULT -1 + + float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0) + float qblur; ///< amount of qscale smoothing over time (0.0-1.0) + + /** + * minimum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmin; + + /** + * maximum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmax; + + /** + * maximum quantizer difference between frames + * - encoding: Set by user. + * - decoding: unused + */ + int max_qdiff; + + /** + * decoder bitstream buffer size + * - encoding: Set by user. + * - decoding: May be set by libavcodec. + */ + int rc_buffer_size; + + /** + * ratecontrol override, see RcOverride + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + int rc_override_count; + RcOverride *rc_override; + + /** + * maximum bitrate + * - encoding: Set by user. + * - decoding: Set by user, may be overwritten by libavcodec. + */ + int64_t rc_max_rate; + + /** + * minimum bitrate + * - encoding: Set by user. + * - decoding: unused + */ + int64_t rc_min_rate; + + /** + * Ratecontrol attempt to use, at maximum, of what can be used without an underflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_max_available_vbv_use; + + /** + * Ratecontrol attempt to use, at least, times the amount needed to prevent a vbv overflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_min_vbv_overflow_use; + + /** + * Number of bits which should be loaded into the rc buffer before decoding starts. + * - encoding: Set by user. + * - decoding: unused + */ + int rc_initial_buffer_occupancy; + + /** + * trellis RD quantization + * - encoding: Set by user. + * - decoding: unused + */ + int trellis; + + /** + * pass1 encoding statistics output buffer + * - encoding: Set by libavcodec. + * - decoding: unused + */ + char *stats_out; + + /** + * pass2 encoding statistics input buffer + * Concatenated stuff from stats_out of pass1 should be placed here. + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + char *stats_in; + + /** + * Work around bugs in encoders which sometimes cannot be detected automatically. + * - encoding: Set by user + * - decoding: Set by user + */ + int workaround_bugs; +#define FF_BUG_AUTODETECT 1 ///< autodetection +#define FF_BUG_XVID_ILACE 4 +#define FF_BUG_UMP4 8 +#define FF_BUG_NO_PADDING 16 +#define FF_BUG_AMV 32 +#define FF_BUG_QPEL_CHROMA 64 +#define FF_BUG_STD_QPEL 128 +#define FF_BUG_QPEL_CHROMA2 256 +#define FF_BUG_DIRECT_BLOCKSIZE 512 +#define FF_BUG_EDGE 1024 +#define FF_BUG_HPEL_CHROMA 2048 +#define FF_BUG_DC_CLIP 4096 +#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders. +#define FF_BUG_TRUNCATED 16384 +#define FF_BUG_IEDGE 32768 + + /** + * strictly follow the standard (MPEG-4, ...). + * - encoding: Set by user. + * - decoding: Set by user. + * Setting this to STRICT or higher means the encoder and decoder will + * generally do stupid things, whereas setting it to unofficial or lower + * will mean the encoder might produce output that is not supported by all + * spec-compliant decoders. Decoders don't differentiate between normal, + * unofficial and experimental (that is, they always try to decode things + * when they can) unless they are explicitly asked to behave stupidly + * (=strictly conform to the specs) + * This may only be set to one of the FF_COMPLIANCE_* values in defs.h. + */ + int strict_std_compliance; + + /** + * error concealment flags + * - encoding: unused + * - decoding: Set by user. + */ + int error_concealment; +#define FF_EC_GUESS_MVS 1 +#define FF_EC_DEBLOCK 2 +#define FF_EC_FAVOR_INTER 256 + + /** + * debug + * - encoding: Set by user. + * - decoding: Set by user. + */ + int debug; +#define FF_DEBUG_PICT_INFO 1 +#define FF_DEBUG_RC 2 +#define FF_DEBUG_BITSTREAM 4 +#define FF_DEBUG_MB_TYPE 8 +#define FF_DEBUG_QP 16 +#define FF_DEBUG_DCT_COEFF 0x00000040 +#define FF_DEBUG_SKIP 0x00000080 +#define FF_DEBUG_STARTCODE 0x00000100 +#define FF_DEBUG_ER 0x00000400 +#define FF_DEBUG_MMCO 0x00000800 +#define FF_DEBUG_BUGS 0x00001000 +#define FF_DEBUG_BUFFERS 0x00008000 +#define FF_DEBUG_THREADS 0x00010000 +#define FF_DEBUG_GREEN_MD 0x00800000 +#define FF_DEBUG_NOMC 0x01000000 + + /** + * Error recognition; may misdetect some more or less valid parts as errors. + * This is a bitfield of the AV_EF_* values defined in defs.h. + * + * - encoding: Set by user. + * - decoding: Set by user. + */ + int err_recognition; + + /** + * Hardware accelerator in use + * - encoding: unused. + * - decoding: Set by libavcodec + */ + const struct AVHWAccel *hwaccel; + + /** + * Legacy hardware accelerator context. + * + * For some hardware acceleration methods, the caller may use this field to + * signal hwaccel-specific data to the codec. The struct pointed to by this + * pointer is hwaccel-dependent and defined in the respective header. Please + * refer to the FFmpeg HW accelerator documentation to know how to fill + * this. + * + * In most cases this field is optional - the necessary information may also + * be provided to libavcodec through @ref hw_frames_ctx or @ref + * hw_device_ctx (see avcodec_get_hw_config()). However, in some cases it + * may be the only method of signalling some (optional) information. + * + * The struct and its contents are owned by the caller. + * + * - encoding: May be set by the caller before avcodec_open2(). Must remain + * valid until avcodec_free_context(). + * - decoding: May be set by the caller in the get_format() callback. + * Must remain valid until the next get_format() call, + * or avcodec_free_context() (whichever comes first). + */ + void *hwaccel_context; + + /** + * A reference to the AVHWFramesContext describing the input (for encoding) + * or output (decoding) frames. The reference is set by the caller and + * afterwards owned (and freed) by libavcodec - it should never be read by + * the caller after being set. + * + * - decoding: This field should be set by the caller from the get_format() + * callback. The previous reference (if any) will always be + * unreffed by libavcodec before the get_format() call. + * + * If the default get_buffer2() is used with a hwaccel pixel + * format, then this AVHWFramesContext will be used for + * allocating the frame buffers. + * + * - encoding: For hardware encoders configured to use a hwaccel pixel + * format, this field should be set by the caller to a reference + * to the AVHWFramesContext describing input frames. + * AVHWFramesContext.format must be equal to + * AVCodecContext.pix_fmt. + * + * This field should be set before avcodec_open2() is called. + */ + AVBufferRef *hw_frames_ctx; + + /** + * A reference to the AVHWDeviceContext describing the device which will + * be used by a hardware encoder/decoder. The reference is set by the + * caller and afterwards owned (and freed) by libavcodec. + * + * This should be used if either the codec device does not require + * hardware frames or any that are used are to be allocated internally by + * libavcodec. If the user wishes to supply any of the frames used as + * encoder input or decoder output then hw_frames_ctx should be used + * instead. When hw_frames_ctx is set in get_format() for a decoder, this + * field will be ignored while decoding the associated stream segment, but + * may again be used on a following one after another get_format() call. + * + * For both encoders and decoders this field should be set before + * avcodec_open2() is called and must not be written to thereafter. + * + * Note that some decoders may require this field to be set initially in + * order to support hw_frames_ctx at all - in that case, all frames + * contexts used must be created on the same device. + */ + AVBufferRef *hw_device_ctx; + + /** + * Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated + * decoding (if active). + * - encoding: unused + * - decoding: Set by user (either before avcodec_open2(), or in the + * AVCodecContext.get_format callback) + */ + int hwaccel_flags; + + /** + * Video decoding only. Sets the number of extra hardware frames which + * the decoder will allocate for use by the caller. This must be set + * before avcodec_open2() is called. + * + * Some hardware decoders require all frames that they will use for + * output to be defined in advance before decoding starts. For such + * decoders, the hardware frame pool must therefore be of a fixed size. + * The extra frames set here are on top of any number that the decoder + * needs internally in order to operate normally (for example, frames + * used as reference pictures). + */ + int extra_hw_frames; + + /** + * error + * - encoding: Set by libavcodec if flags & AV_CODEC_FLAG_PSNR. + * - decoding: unused + */ + uint64_t error[AV_NUM_DATA_POINTERS]; + + /** + * DCT algorithm, see FF_DCT_* below + * - encoding: Set by user. + * - decoding: unused + */ + int dct_algo; +#define FF_DCT_AUTO 0 +#define FF_DCT_FASTINT 1 +#define FF_DCT_INT 2 +#define FF_DCT_MMX 3 +#define FF_DCT_ALTIVEC 5 +#define FF_DCT_FAAN 6 +#define FF_DCT_NEON 7 + + /** + * IDCT algorithm, see FF_IDCT_* below. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int idct_algo; +#define FF_IDCT_AUTO 0 +#define FF_IDCT_INT 1 +#define FF_IDCT_SIMPLE 2 +#define FF_IDCT_SIMPLEMMX 3 +#define FF_IDCT_ARM 7 +#define FF_IDCT_ALTIVEC 8 +#define FF_IDCT_SIMPLEARM 10 +#define FF_IDCT_XVID 14 +#define FF_IDCT_SIMPLEARMV5TE 16 +#define FF_IDCT_SIMPLEARMV6 17 +#define FF_IDCT_FAAN 20 +#define FF_IDCT_SIMPLENEON 22 +#define FF_IDCT_SIMPLEAUTO 128 + + /** + * bits per sample/pixel from the demuxer (needed for huffyuv). + * - encoding: Set by libavcodec. + * - decoding: Set by user. + */ + int bits_per_coded_sample; + + /** + * Bits per sample/pixel of internal libavcodec pixel/sample format. + * - encoding: set by user. + * - decoding: set by libavcodec. + */ + int bits_per_raw_sample; + + /** + * thread count + * is used to decide how many independent tasks should be passed to execute() + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_count; + + /** + * Which multithreading methods to use. + * Use of FF_THREAD_FRAME will increase decoding delay by one frame per thread, + * so clients which cannot provide future frames should not use it. + * + * - encoding: Set by user, otherwise the default is used. + * - decoding: Set by user, otherwise the default is used. + */ + int thread_type; +#define FF_THREAD_FRAME 1 ///< Decode more than one frame at once +#define FF_THREAD_SLICE 2 ///< Decode more than one part of a single frame at once + + /** + * Which multithreading methods are in use by the codec. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int active_thread_type; + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param count the number of things to execute + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size); + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param c context passed also to func + * @param count the number of things to execute + * @param arg2 argument passed unchanged to func + * @param ret return values of executed functions, must have space for "count" values. May be NULL. + * @param func function that will be called count times, with jobnr from 0 to count-1. + * threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no + * two instances of func executing at the same time will have the same threadnr. + * @return always 0 currently, but code should handle a future improvement where when any call to func + * returns < 0 no further calls to func may be done and < 0 is returned. + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count); + + /** + * profile + * - encoding: Set by user. + * - decoding: Set by libavcodec. + * See the AV_PROFILE_* defines in defs.h. + */ + int profile; + + /** + * Encoding level descriptor. + * - encoding: Set by user, corresponds to a specific level defined by the + * codec, usually corresponding to the profile level, if not specified it + * is set to AV_LEVEL_UNKNOWN. + * - decoding: Set by libavcodec. + * See AV_LEVEL_* in defs.h. + */ + int level; + +#if FF_API_CODEC_PROPS + /** + * Properties of the stream that gets decoded + * - encoding: unused + * - decoding: set by libavcodec + */ + attribute_deprecated + unsigned properties; +#define FF_CODEC_PROPERTY_LOSSLESS 0x00000001 +#define FF_CODEC_PROPERTY_CLOSED_CAPTIONS 0x00000002 +#define FF_CODEC_PROPERTY_FILM_GRAIN 0x00000004 +#endif + + /** + * Skip loop filtering for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_loop_filter; + + /** + * Skip IDCT/dequantization for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_idct; + + /** + * Skip decoding for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_frame; + + /** + * Skip processing alpha if supported by codec. + * Note that if the format uses pre-multiplied alpha (common with VP6, + * and recommended due to better video quality/compression) + * the image will look as if alpha-blended onto a black background. + * However for formats that do not use pre-multiplied alpha + * there might be serious artefacts (though e.g. libswscale currently + * assumes pre-multiplied alpha anyway). + * + * - decoding: set by user + * - encoding: unused + */ + int skip_alpha; + + /** + * Number of macroblock rows at the top which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_top; + + /** + * Number of macroblock rows at the bottom which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_bottom; + + /** + * low resolution decoding, 1-> 1/2 size, 2->1/4 size + * - encoding: unused + * - decoding: Set by user. + */ + int lowres; + + /** + * AVCodecDescriptor + * - encoding: unused. + * - decoding: set by libavcodec. + */ + const struct AVCodecDescriptor *codec_descriptor; + + /** + * Character encoding of the input subtitles file. + * - decoding: set by user + * - encoding: unused + */ + char *sub_charenc; + + /** + * Subtitles character encoding mode. Formats or codecs might be adjusting + * this setting (if they are doing the conversion themselves for instance). + * - decoding: set by libavcodec + * - encoding: unused + */ + int sub_charenc_mode; +#define FF_SUB_CHARENC_MODE_DO_NOTHING -1 ///< do nothing (demuxer outputs a stream supposed to be already in UTF-8, or the codec is bitmap for instance) +#define FF_SUB_CHARENC_MODE_AUTOMATIC 0 ///< libavcodec will select the mode itself +#define FF_SUB_CHARENC_MODE_PRE_DECODER 1 ///< the AVPacket data needs to be recoded to UTF-8 before being fed to the decoder, requires iconv +#define FF_SUB_CHARENC_MODE_IGNORE 2 ///< neither convert the subtitles, nor check them for valid UTF-8 + + /** + * Header containing style information for text subtitles. + * For SUBTITLE_ASS subtitle type, it should contain the whole ASS + * [Script Info] and [V4+ Styles] section, plus the [Events] line and + * the Format line following. It shouldn't include any Dialogue line. + * + * - encoding: May be set by the caller before avcodec_open2() to an array + * allocated with the av_malloc() family of functions. + * - decoding: May be set by libavcodec in avcodec_open2(). + * + * After being set, the array is owned by the codec and freed in + * avcodec_free_context(). + */ + int subtitle_header_size; + uint8_t *subtitle_header; + + /** + * dump format separator. + * can be ", " or "\n " or anything else + * - encoding: Set by user. + * - decoding: Set by user. + */ + uint8_t *dump_separator; + + /** + * ',' separated list of allowed decoders. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *codec_whitelist; + + /** + * Additional data associated with the entire coded stream. + * + * - decoding: may be set by user before calling avcodec_open2(). + * - encoding: may be set by libavcodec after avcodec_open2(). + */ + AVPacketSideData *coded_side_data; + int nb_coded_side_data; + + /** + * Bit set of AV_CODEC_EXPORT_DATA_* flags, which affects the kind of + * metadata exported in frame, packet, or coded stream side data by + * decoders and encoders. + * + * - decoding: set by user + * - encoding: set by user + */ + int export_side_data; + + /** + * The number of pixels per image to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_pixels; + + /** + * Video decoding only. Certain video codecs support cropping, meaning that + * only a sub-rectangle of the decoded frame is intended for display. This + * option controls how cropping is handled by libavcodec. + * + * When set to 1 (the default), libavcodec will apply cropping internally. + * I.e. it will modify the output frame width/height fields and offset the + * data pointers (only by as much as possible while preserving alignment, or + * by the full amount if the AV_CODEC_FLAG_UNALIGNED flag is set) so that + * the frames output by the decoder refer only to the cropped area. The + * crop_* fields of the output frames will be zero. + * + * When set to 0, the width/height fields of the output frames will be set + * to the coded dimensions and the crop_* fields will describe the cropping + * rectangle. Applying the cropping is left to the caller. + * + * @warning When hardware acceleration with opaque output frames is used, + * libavcodec is unable to apply cropping from the top/left border. + * + * @note when this option is set to zero, the width/height fields of the + * AVCodecContext and output AVFrames have different meanings. The codec + * context fields store display dimensions (with the coded dimensions in + * coded_width/height), while the frame fields store the coded dimensions + * (with the display dimensions being determined by the crop_* fields). + */ + int apply_cropping; + + /** + * The percentage of damaged samples to discard a frame. + * + * - decoding: set by user + * - encoding: unused + */ + int discard_damaged_percentage; + + /** + * The number of samples per frame to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_samples; + + /** + * This callback is called at the beginning of each packet to get a data + * buffer for it. + * + * The following field will be set in the packet before this callback is + * called: + * - size + * This callback must use the above value to calculate the required buffer size, + * which must padded by at least AV_INPUT_BUFFER_PADDING_SIZE bytes. + * + * In some specific cases, the encoder may not use the entire buffer allocated by this + * callback. This will be reflected in the size value in the packet once returned by + * avcodec_receive_packet(). + * + * This callback must fill the following fields in the packet: + * - data: alignment requirements for AVPacket apply, if any. Some architectures and + * encoders may benefit from having aligned data. + * - buf: must contain a pointer to an AVBufferRef structure. The packet's + * data pointer must be contained in it. See: av_buffer_create(), av_buffer_alloc(), + * and av_buffer_ref(). + * + * If AV_CODEC_CAP_DR1 is not set then get_encode_buffer() must call + * avcodec_default_get_encode_buffer() instead of providing a buffer allocated by + * some other means. + * + * The flags field may contain a combination of AV_GET_ENCODE_BUFFER_FLAG_ flags. + * They may be used for example to hint what use the buffer may get after being + * created. + * Implementations of this callback may ignore flags they don't understand. + * If AV_GET_ENCODE_BUFFER_FLAG_REF is set in flags then the packet may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * This callback must be thread-safe, as when frame threading is used, it may + * be called from multiple threads simultaneously. + * + * @see avcodec_default_get_encode_buffer() + * + * - encoding: Set by libavcodec, user can override. + * - decoding: unused + */ + int (*get_encode_buffer)(struct AVCodecContext *s, AVPacket *pkt, int flags); + + /** + * Frame counter, set by libavcodec. + * + * - decoding: total number of frames returned from the decoder so far. + * - encoding: total number of frames passed to the encoder so far. + * + * @note the counter is not incremented if encoding/decoding resulted in + * an error. + */ + int64_t frame_num; + + /** + * Decoding only. May be set by the caller before avcodec_open2() to an + * av_malloc()'ed array (or via AVOptions). Owned and freed by the decoder + * afterwards. + * + * Side data attached to decoded frames may come from several sources: + * 1. coded_side_data, which the decoder will for certain types translate + * from packet-type to frame-type and attach to frames; + * 2. side data attached to an AVPacket sent for decoding (same + * considerations as above); + * 3. extracted from the coded bytestream. + * The first two cases are supplied by the caller and typically come from a + * container. + * + * This array configures decoder behaviour in cases when side data of the + * same type is present both in the coded bytestream and in the + * user-supplied side data (items 1. and 2. above). In all cases, at most + * one instance of each side data type will be attached to output frames. By + * default it will be the bytestream side data. Adding an + * AVPacketSideDataType value to this array will flip the preference for + * this type, thus making the decoder prefer user-supplied side data over + * bytestream. In case side data of the same type is present both in + * coded_data and attacked to a packet, the packet instance always has + * priority. + * + * The array may also contain a single -1, in which case the preference is + * switched for all side data types. + */ + int *side_data_prefer_packet; + /** + * Number of entries in side_data_prefer_packet. + */ + unsigned nb_side_data_prefer_packet; + + /** + * Array containing static side data, such as HDR10 CLL / MDCV structures. + * Side data entries should be allocated by usage of helpers defined in + * libavutil/frame.h. + * + * - encoding: may be set by user before calling avcodec_open2() for + * encoder configuration. Afterwards owned and freed by the + * encoder. + * - decoding: may be set by libavcodec in avcodec_open2(). + */ + AVFrameSideData **decoded_side_data; + int nb_decoded_side_data; +} AVCodecContext; + +/** + * @defgroup lavc_hwaccel AVHWAccel + * + * @note Nothing in this structure should be accessed by the user. At some + * point in future it will not be externally visible at all. + * + * @{ + */ +typedef struct AVHWAccel { + /** + * Name of the hardware accelerated codec. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + */ + const char *name; + + /** + * Type of codec implemented by the hardware accelerator. + * + * See AVMEDIA_TYPE_xxx + */ + enum AVMediaType type; + + /** + * Codec implemented by the hardware accelerator. + * + * See AV_CODEC_ID_xxx + */ + enum AVCodecID id; + + /** + * Supported pixel format. + * + * Only hardware accelerated formats are supported here. + */ + enum AVPixelFormat pix_fmt; + + /** + * Hardware accelerated codec capabilities. + * see AV_HWACCEL_CODEC_CAP_* + */ + int capabilities; +} AVHWAccel; + +/** + * HWAccel is experimental and is thus avoided in favor of non experimental + * codecs + */ +#define AV_HWACCEL_CODEC_CAP_EXPERIMENTAL 0x0200 + +/** + * Hardware acceleration should be used for decoding even if the codec level + * used is unknown or higher than the maximum supported level reported by the + * hardware driver. + * + * It's generally a good idea to pass this flag unless you have a specific + * reason not to, as hardware tends to under-report supported levels. + */ +#define AV_HWACCEL_FLAG_IGNORE_LEVEL (1 << 0) + +/** + * Hardware acceleration can output YUV pixel formats with a different chroma + * sampling than 4:2:0 and/or other than 8 bits per component. + */ +#define AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH (1 << 1) + +/** + * Hardware acceleration should still be attempted for decoding when the + * codec profile does not match the reported capabilities of the hardware. + * + * For example, this can be used to try to decode baseline profile H.264 + * streams in hardware - it will often succeed, because many streams marked + * as baseline profile actually conform to constrained baseline profile. + * + * @warning If the stream is actually not supported then the behaviour is + * undefined, and may include returning entirely incorrect output + * while indicating success. + */ +#define AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH (1 << 2) + +/** + * Some hardware decoders (namely nvdec) can either output direct decoder + * surfaces, or make an on-device copy and return said copy. + * There is a hard limit on how many decoder surfaces there can be, and it + * cannot be accurately guessed ahead of time. + * For some processing chains, this can be okay, but others will run into the + * limit and in turn produce very confusing errors that require fine tuning of + * more or less obscure options by the user, or in extreme cases cannot be + * resolved at all without inserting an avfilter that forces a copy. + * + * Thus, the hwaccel will by default make a copy for safety and resilience. + * If a users really wants to minimize the amount of copies, they can set this + * flag and ensure their processing chain does not exhaust the surface pool. + */ +#define AV_HWACCEL_FLAG_UNSAFE_OUTPUT (1 << 3) + +/** + * @} + */ + +enum AVSubtitleType { + SUBTITLE_NONE, + + SUBTITLE_BITMAP, ///< A bitmap, pict will be set + + /** + * Plain text, the text field must be set by the decoder and is + * authoritative. ass and pict fields may contain approximations. + */ + SUBTITLE_TEXT, + + /** + * Formatted text, the ass field must be set by the decoder and is + * authoritative. pict and text fields may contain approximations. + */ + SUBTITLE_ASS, +}; + +#define AV_SUBTITLE_FLAG_FORCED 0x00000001 + +typedef struct AVSubtitleRect { + int x; ///< top left corner of pict, undefined when pict is not set + int y; ///< top left corner of pict, undefined when pict is not set + int w; ///< width of pict, undefined when pict is not set + int h; ///< height of pict, undefined when pict is not set + int nb_colors; ///< number of colors in pict, undefined when pict is not set + + /** + * data+linesize for the bitmap of this subtitle. + * Can be set for text/ass as well once they are rendered. + */ + uint8_t *data[4]; + int linesize[4]; + + int flags; + enum AVSubtitleType type; + + char *text; ///< 0 terminated plain UTF-8 text + + /** + * 0 terminated ASS/SSA compatible event line. + * The presentation of this is unaffected by the other values in this + * struct. + */ + char *ass; +} AVSubtitleRect; + +typedef struct AVSubtitle { + uint16_t format; /* 0 = graphics */ + uint32_t start_display_time; /* relative to packet pts, in ms */ + uint32_t end_display_time; /* relative to packet pts, in ms */ + unsigned num_rects; + AVSubtitleRect **rects; + int64_t pts; ///< Same as packet pts, in AV_TIME_BASE +} AVSubtitle; + +/** + * Return the LIBAVCODEC_VERSION_INT constant. + */ +unsigned avcodec_version(void); + +/** + * Return the libavcodec build-time configuration. + */ +const char *avcodec_configuration(void); + +/** + * Return the libavcodec license. + */ +const char *avcodec_license(void); + +/** + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct should be freed with avcodec_free_context(). + * + * @param codec if non-NULL, allocate private data and initialize defaults + * for the given codec. It is illegal to then call avcodec_open2() + * with a different codec. + * If NULL, then the codec-specific defaults won't be initialized, + * which may result in suboptimal default settings (this is + * important mainly for encoders, e.g. libx264). + * + * @return An AVCodecContext filled with default values or NULL on failure. + */ +AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); + +/** + * Free the codec context and everything associated with it and write NULL to + * the provided pointer. + */ +void avcodec_free_context(AVCodecContext **avctx); + +/** + * Get the AVClass for AVCodecContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_class(void); + +/** + * Get the AVClass for AVSubtitleRect. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_subtitle_rect_class(void); + +/** + * Fill the parameters struct based on the values from the supplied codec + * context. Any allocated fields in par are freed and replaced with duplicates + * of the corresponding fields in codec. + * + * @return >= 0 on success, a negative AVERROR code on failure + */ +int avcodec_parameters_from_context(struct AVCodecParameters *par, + const AVCodecContext *codec); + +/** + * Fill the codec context based on the values from the supplied codec + * parameters. Any allocated fields in codec that have a corresponding field in + * par are freed and replaced with duplicates of the corresponding field in par. + * Fields in codec that do not have a counterpart in par are not touched. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_to_context(AVCodecContext *codec, + const struct AVCodecParameters *par); + +/** + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated with avcodec_alloc_context3(). + * + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. + * + * Depending on the codec, you might need to set options in the codec context + * also for decoding (e.g. width, height, or the pixel or audio sample format in + * the case the information is not available in the bitstream, as when decoding + * raw audio or video). + * + * Options in the codec context can be set either by setting them in the options + * AVDictionary, or by setting the values in the context itself, directly or by + * using the av_opt_set() API before calling this function. + * + * Example: + * @code + * av_dict_set(&opts, "b", "2.5M", 0); + * codec = avcodec_find_decoder(AV_CODEC_ID_H264); + * if (!codec) + * exit(1); + * + * context = avcodec_alloc_context3(codec); + * + * if (avcodec_open2(context, codec, opts) < 0) + * exit(1); + * @endcode + * + * In the case AVCodecParameters are available (e.g. when demuxing a stream + * using libavformat, and accessing the AVStream contained in the demuxer), the + * codec parameters can be copied to the codec context using + * avcodec_parameters_to_context(), as in the following example: + * + * @code + * AVStream *stream = ...; + * context = avcodec_alloc_context3(codec); + * if (avcodec_parameters_to_context(context, stream->codecpar) < 0) + * exit(1); + * if (avcodec_open2(context, codec, NULL) < 0) + * exit(1); + * @endcode + * + * @note Always call this function before using decoding routines (such as + * @ref avcodec_receive_frame()). + * + * @param avctx The context to initialize. + * @param codec The codec to open this context for. If a non-NULL codec has been + * previously passed to avcodec_alloc_context3() or + * for this context, then this parameter MUST be either NULL or + * equal to the previously passed codec. + * @param options A dictionary filled with AVCodecContext and codec-private + * options, which are set on top of the options already set in + * avctx, can be NULL. On return this object will be filled with + * options that were not found in the avctx codec context. + * + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), + * av_dict_set(), av_opt_set(), av_opt_find(), avcodec_parameters_to_context() + */ +int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); + +/** + * Free all allocated data in the given subtitle struct. + * + * @param sub AVSubtitle to free. + */ +void avsubtitle_free(AVSubtitle *sub); + +/** + * @} + */ + +/** + * @addtogroup lavc_decoding + * @{ + */ + +/** + * The default callback for AVCodecContext.get_buffer2(). It is made public so + * it can be called by custom get_buffer2() implementations for decoders without + * AV_CODEC_CAP_DR1 set. + */ +int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags); + +/** + * The default callback for AVCodecContext.get_encode_buffer(). It is made public so + * it can be called by custom get_encode_buffer() implementations for encoders without + * AV_CODEC_CAP_DR1 set. + */ +int avcodec_default_get_encode_buffer(AVCodecContext *s, AVPacket *pkt, int flags); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you do not use any horizontal + * padding. + * + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. + */ +void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you also ensure that all + * line sizes are a multiple of the respective linesize_align[i]. + * + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. + */ +void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, + int linesize_align[AV_NUM_DATA_POINTERS]); + +/** + * Decode a subtitle message. + * Return a negative value on error, otherwise return the number of bytes used. + * If no subtitle could be decompressed, got_sub_ptr is zero. + * Otherwise, the subtitle is stored in *sub. + * Note that AV_CODEC_CAP_DR1 is not available for subtitle codecs. This is for + * simplicity, because the performance difference is expected to be negligible + * and reusing a get_buffer written for video codecs would probably perform badly + * due to a potentially very different allocation pattern. + * + * Some decoders (those marked with AV_CODEC_CAP_DELAY) have a delay between input + * and output. This means that for some packets they will not immediately + * produce decoded output and need to be flushed at the end of decoding to get + * all the decoded data. Flushing is done by calling this function with packets + * with avpkt->data set to NULL and avpkt->size set to 0 until it stops + * returning subtitles. It is safe to flush even those decoders that are not + * marked with AV_CODEC_CAP_DELAY, then no subtitles will be returned. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx the codec context + * @param[out] sub The preallocated AVSubtitle in which the decoded subtitle will be stored, + * must be freed with avsubtitle_free if *got_sub_ptr is set. + * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. + * @param[in] avpkt The input AVPacket containing the input buffer. + */ +int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt); + +/** + * Supply raw packet data as input to a decoder. + * + * Internally, this call will copy relevant AVCodecContext fields, which can + * influence decoding per-packet, and apply them when the packet is actually + * decoded. (For example AVCodecContext.skip_frame, which might direct the + * decoder to drop the frame contained by the packet sent with this function.) + * + * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE + * larger than the actual read bytes because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx codec context + * @param[in] avpkt The input AVPacket. Usually, this will be a single video + * frame, or several complete audio frames. + * Ownership of the packet remains with the caller, and the + * decoder will not write to the packet. The decoder may create + * a reference to the packet data (or copy it if the packet is + * not reference-counted). + * Unlike with older APIs, the packet is always fully consumed, + * and if it contains multiple frames (e.g. some audio codecs), + * will require you to call avcodec_receive_frame() multiple + * times afterwards before you can send a new packet. + * It can be NULL (or an AVPacket with data set to NULL and + * size set to 0); in this case, it is considered a flush + * packet, which signals the end of the stream. Sending the + * first flush packet will return success. Subsequent ones are + * unnecessary and will return AVERROR_EOF. If the decoder + * still has frames buffered, it will return them after sending + * a flush packet. + * + * @retval 0 success + * @retval AVERROR(EAGAIN) input is not accepted in the current state - user + * must read output with avcodec_receive_frame() (once + * all output is read, the packet should be resent, + * and the call will not fail with EAGAIN). + * @retval AVERROR_EOF the decoder has been flushed, and no new packets can be + * sent to it (also returned if more than 1 flush + * packet is sent) + * @retval AVERROR(EINVAL) codec not opened, it is an encoder, or requires flush + * @retval AVERROR(ENOMEM) failed to add packet to internal queue, or similar + * @retval "another negative error code" legitimate decoding errors + */ +int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); + +/** + * Return decoded output data from a decoder or encoder (when the + * @ref AV_CODEC_FLAG_RECON_FRAME flag is used). + * + * @param avctx codec context + * @param frame This will be set to a reference-counted video or audio + * frame (depending on the decoder type) allocated by the + * codec. Note that the function will always call + * av_frame_unref(frame) before doing anything else. + * + * @retval 0 success, a frame was returned + * @retval AVERROR(EAGAIN) output is not available in this state - user must + * try to send new input + * @retval AVERROR_EOF the codec has been fully flushed, and there will be + * no more output frames + * @retval AVERROR(EINVAL) codec not opened, or it is an encoder without the + * @ref AV_CODEC_FLAG_RECON_FRAME flag enabled + * @retval "other negative error code" legitimate decoding errors + */ +int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); + +/** + * Supply a raw video or audio frame to the encoder. Use avcodec_receive_packet() + * to retrieve buffered output packets. + * + * @param avctx codec context + * @param[in] frame AVFrame containing the raw audio or video frame to be encoded. + * Ownership of the frame remains with the caller, and the + * encoder will not write to the frame. The encoder may create + * a reference to the frame data (or copy it if the frame is + * not reference-counted). + * It can be NULL, in which case it is considered a flush + * packet. This signals the end of the stream. If the encoder + * still has packets buffered, it will return them after this + * call. Once flushing mode has been entered, additional flush + * packets are ignored, and sending frames will return + * AVERROR_EOF. + * + * For audio: + * If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * can have any number of samples. + * If it is not set, frame->nb_samples must be equal to + * avctx->frame_size for all frames except the last. + * The final frame may be smaller than avctx->frame_size. + * @retval 0 success + * @retval AVERROR(EAGAIN) input is not accepted in the current state - user must + * read output with avcodec_receive_packet() (once all + * output is read, the packet should be resent, and the + * call will not fail with EAGAIN). + * @retval AVERROR_EOF the encoder has been flushed, and no new frames can + * be sent to it + * @retval AVERROR(EINVAL) codec not opened, it is a decoder, or requires flush + * @retval AVERROR(ENOMEM) failed to add packet to internal queue, or similar + * @retval "another negative error code" legitimate encoding errors + */ +int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); + +/** + * Read encoded data from the encoder. + * + * @param avctx codec context + * @param avpkt This will be set to a reference-counted packet allocated by the + * encoder. Note that the function will always call + * av_packet_unref(avpkt) before doing anything else. + * @retval 0 success + * @retval AVERROR(EAGAIN) output is not available in the current state - user must + * try to send input + * @retval AVERROR_EOF the encoder has been fully flushed, and there will be no + * more output packets + * @retval AVERROR(EINVAL) codec not opened, or it is a decoder + * @retval "another negative error code" legitimate encoding errors + */ +int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); + +/** + * Create and return a AVHWFramesContext with values adequate for hardware + * decoding. This is meant to get called from the get_format callback, and is + * a helper for preparing a AVHWFramesContext for AVCodecContext.hw_frames_ctx. + * This API is for decoding with certain hardware acceleration modes/APIs only. + * + * The returned AVHWFramesContext is not initialized. The caller must do this + * with av_hwframe_ctx_init(). + * + * Calling this function is not a requirement, but makes it simpler to avoid + * codec or hardware API specific details when manually allocating frames. + * + * Alternatively to this, an API user can set AVCodecContext.hw_device_ctx, + * which sets up AVCodecContext.hw_frames_ctx fully automatically, and makes + * it unnecessary to call this function or having to care about + * AVHWFramesContext initialization at all. + * + * There are a number of requirements for calling this function: + * + * - It must be called from get_format with the same avctx parameter that was + * passed to get_format. Calling it outside of get_format is not allowed, and + * can trigger undefined behavior. + * - The function is not always supported (see description of return values). + * Even if this function returns successfully, hwaccel initialization could + * fail later. (The degree to which implementations check whether the stream + * is actually supported varies. Some do this check only after the user's + * get_format callback returns.) + * - The hw_pix_fmt must be one of the choices suggested by get_format. If the + * user decides to use a AVHWFramesContext prepared with this API function, + * the user must return the same hw_pix_fmt from get_format. + * - The device_ref passed to this function must support the given hw_pix_fmt. + * - After calling this API function, it is the user's responsibility to + * initialize the AVHWFramesContext (returned by the out_frames_ref parameter), + * and to set AVCodecContext.hw_frames_ctx to it. If done, this must be done + * before returning from get_format (this is implied by the normal + * AVCodecContext.hw_frames_ctx API rules). + * - The AVHWFramesContext parameters may change every time time get_format is + * called. Also, AVCodecContext.hw_frames_ctx is reset before get_format. So + * you are inherently required to go through this process again on every + * get_format call. + * - It is perfectly possible to call this function without actually using + * the resulting AVHWFramesContext. One use-case might be trying to reuse a + * previously initialized AVHWFramesContext, and calling this API function + * only to test whether the required frame parameters have changed. + * - Fields that use dynamically allocated values of any kind must not be set + * by the user unless setting them is explicitly allowed by the documentation. + * If the user sets AVHWFramesContext.free and AVHWFramesContext.user_opaque, + * the new free callback must call the potentially set previous free callback. + * This API call may set any dynamically allocated fields, including the free + * callback. + * + * The function will set at least the following fields on AVHWFramesContext + * (potentially more, depending on hwaccel API): + * + * - All fields set by av_hwframe_ctx_alloc(). + * - Set the format field to hw_pix_fmt. + * - Set the sw_format field to the most suited and most versatile format. (An + * implication is that this will prefer generic formats over opaque formats + * with arbitrary restrictions, if possible.) + * - Set the width/height fields to the coded frame size, rounded up to the + * API-specific minimum alignment. + * - Only _if_ the hwaccel requires a pre-allocated pool: set the initial_pool_size + * field to the number of maximum reference surfaces possible with the codec, + * plus 1 surface for the user to work (meaning the user can safely reference + * at most 1 decoded surface at a time), plus additional buffering introduced + * by frame threading. If the hwaccel does not require pre-allocation, the + * field is left to 0, and the decoder will allocate new surfaces on demand + * during decoding. + * - Possibly AVHWFramesContext.hwctx fields, depending on the underlying + * hardware API. + * + * Essentially, out_frames_ref returns the same as av_hwframe_ctx_alloc(), but + * with basic frame parameters set. + * + * The function is stateless, and does not change the AVCodecContext or the + * device_ref AVHWDeviceContext. + * + * @param avctx The context which is currently calling get_format, and which + * implicitly contains all state needed for filling the returned + * AVHWFramesContext properly. + * @param device_ref A reference to the AVHWDeviceContext describing the device + * which will be used by the hardware decoder. + * @param hw_pix_fmt The hwaccel format you are going to return from get_format. + * @param out_frames_ref On success, set to a reference to an _uninitialized_ + * AVHWFramesContext, created from the given device_ref. + * Fields will be set to values required for decoding. + * Not changed if an error is returned. + * @return zero on success, a negative value on error. The following error codes + * have special semantics: + * AVERROR(ENOENT): the decoder does not support this functionality. Setup + * is always manual, or it is a decoder which does not + * support setting AVCodecContext.hw_frames_ctx at all, + * or it is a software format. + * AVERROR(EINVAL): it is known that hardware decoding is not supported for + * this configuration, or the device_ref is not supported + * for the hwaccel referenced by hw_pix_fmt. + */ +int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, + AVBufferRef *device_ref, + enum AVPixelFormat hw_pix_fmt, + AVBufferRef **out_frames_ref); + +enum AVCodecConfig { + AV_CODEC_CONFIG_PIX_FORMAT, ///< AVPixelFormat, terminated by AV_PIX_FMT_NONE + AV_CODEC_CONFIG_FRAME_RATE, ///< AVRational, terminated by {0, 0} + AV_CODEC_CONFIG_SAMPLE_RATE, ///< int, terminated by 0 + AV_CODEC_CONFIG_SAMPLE_FORMAT, ///< AVSampleFormat, terminated by AV_SAMPLE_FMT_NONE + AV_CODEC_CONFIG_CHANNEL_LAYOUT, ///< AVChannelLayout, terminated by {0} + AV_CODEC_CONFIG_COLOR_RANGE, ///< AVColorRange, terminated by AVCOL_RANGE_UNSPECIFIED + AV_CODEC_CONFIG_COLOR_SPACE, ///< AVColorSpace, terminated by AVCOL_SPC_UNSPECIFIED +}; + +/** + * Retrieve a list of all supported values for a given configuration type. + * + * @param avctx An optional context to use. Values such as + * `strict_std_compliance` may affect the result. If NULL, + * default values are used. + * @param codec The codec to query, or NULL to use avctx->codec. + * @param config The configuration to query. + * @param flags Currently unused; should be set to zero. + * @param out_configs On success, set to a list of configurations, terminated + * by a config-specific terminator, or NULL if all + * possible values are supported. + * @param out_num_configs On success, set to the number of elements in + *out_configs, excluding the terminator. Optional. + */ +int avcodec_get_supported_config(const AVCodecContext *avctx, + const AVCodec *codec, enum AVCodecConfig config, + unsigned flags, const void **out_configs, + int *out_num_configs); + + + +/** + * @defgroup lavc_parsing Frame parsing + * @{ + */ + +enum AVPictureStructure { + AV_PICTURE_STRUCTURE_UNKNOWN, ///< unknown + AV_PICTURE_STRUCTURE_TOP_FIELD, ///< coded as top field + AV_PICTURE_STRUCTURE_BOTTOM_FIELD, ///< coded as bottom field + AV_PICTURE_STRUCTURE_FRAME, ///< coded as frame +}; + +typedef struct AVCodecParserContext { + void *priv_data; + const struct AVCodecParser *parser; + int64_t frame_offset; /* offset of the current frame */ + int64_t cur_offset; /* current offset + (incremented by each av_parser_parse()) */ + int64_t next_frame_offset; /* offset of the next frame */ + /* video info */ + int pict_type; /* XXX: Put it back in AVCodecContext. */ + /** + * This field is used for proper frame duration computation in lavf. + * It signals, how much longer the frame duration of the current frame + * is compared to normal frame duration. + * + * frame_duration = (1 + repeat_pict) * time_base + * + * It is used by codecs like H.264 to display telecined material. + */ + int repeat_pict; /* XXX: Put it back in AVCodecContext. */ + int64_t pts; /* pts of the current frame */ + int64_t dts; /* dts of the current frame */ + + /* private data */ + int64_t last_pts; + int64_t last_dts; + int fetch_timestamp; + +#define AV_PARSER_PTS_NB 4 + int cur_frame_start_index; + int64_t cur_frame_offset[AV_PARSER_PTS_NB]; + int64_t cur_frame_pts[AV_PARSER_PTS_NB]; + int64_t cur_frame_dts[AV_PARSER_PTS_NB]; + + int flags; +#define PARSER_FLAG_COMPLETE_FRAMES 0x0001 +#define PARSER_FLAG_ONCE 0x0002 +/// Set if the parser has a valid file offset +#define PARSER_FLAG_FETCHED_OFFSET 0x0004 +#define PARSER_FLAG_USE_CODEC_TS 0x1000 + + int64_t offset; ///< byte offset from starting packet start + int64_t cur_frame_end[AV_PARSER_PTS_NB]; + + /** + * Set by parser to 1 for key frames and 0 for non-key frames. + * It is initialized to -1, so if the parser doesn't set this flag, + * old-style fallback using AV_PICTURE_TYPE_I picture type as key frames + * will be used. + */ + int key_frame; + + // Timestamp generation support: + /** + * Synchronization point for start of timestamp generation. + * + * Set to >0 for sync point, 0 for no sync point and <0 for undefined + * (default). + * + * For example, this corresponds to presence of H.264 buffering period + * SEI message. + */ + int dts_sync_point; + + /** + * Offset of the current timestamp against last timestamp sync point in + * units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain a valid timestamp offset. + * + * Note that the timestamp of sync point has usually a nonzero + * dts_ref_dts_delta, which refers to the previous sync point. Offset of + * the next frame after timestamp sync point will be usually 1. + * + * For example, this corresponds to H.264 cpb_removal_delay. + */ + int dts_ref_dts_delta; + + /** + * Presentation delay of current frame in units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain valid non-negative timestamp delta (presentation time of a frame + * must not lie in the past). + * + * This delay represents the difference between decoding and presentation + * time of the frame. + * + * For example, this corresponds to H.264 dpb_output_delay. + */ + int pts_dts_delta; + + /** + * Position of the packet in file. + * + * Analogous to cur_frame_pts/dts + */ + int64_t cur_frame_pos[AV_PARSER_PTS_NB]; + + /** + * Byte position of currently parsed frame in stream. + */ + int64_t pos; + + /** + * Previous frame byte position. + */ + int64_t last_pos; + + /** + * Duration of the current frame. + * For audio, this is in units of 1 / AVCodecContext.sample_rate. + * For all other types, this is in units of AVCodecContext.time_base. + */ + int duration; + + enum AVFieldOrder field_order; + + /** + * Indicate whether a picture is coded as a frame, top field or bottom field. + * + * For example, H.264 field_pic_flag equal to 0 corresponds to + * AV_PICTURE_STRUCTURE_FRAME. An H.264 picture with field_pic_flag + * equal to 1 and bottom_field_flag equal to 0 corresponds to + * AV_PICTURE_STRUCTURE_TOP_FIELD. + */ + enum AVPictureStructure picture_structure; + + /** + * Picture number incremented in presentation or output order. + * This field may be reinitialized at the first picture of a new sequence. + * + * For example, this corresponds to H.264 PicOrderCnt. + */ + int output_picture_number; + + /** + * Dimensions of the decoded video intended for presentation. + */ + int width; + int height; + + /** + * Dimensions of the coded video. + */ + int coded_width; + int coded_height; + + /** + * The format of the coded data, corresponds to enum AVPixelFormat for video + * and for enum AVSampleFormat for audio. + * + * Note that a decoder can have considerable freedom in how exactly it + * decodes the data, so the format reported here might be different from the + * one returned by a decoder. + */ + int format; +} AVCodecParserContext; + +typedef struct AVCodecParser { + int codec_ids[7]; /* several codec IDs are permitted */ + int priv_data_size; + int (*parser_init)(AVCodecParserContext *s); + /* This callback never returns an error, a negative value means that + * the frame start was in a previous packet. */ + int (*parser_parse)(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size); + void (*parser_close)(AVCodecParserContext *s); + int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size); +} AVCodecParser; + +/** + * Iterate over all registered codec parsers. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec parser or NULL when the iteration is + * finished + */ +const AVCodecParser *av_parser_iterate(void **opaque); + +AVCodecParserContext *av_parser_init(int codec_id); + +/** + * Parse a packet. + * + * @param s parser context. + * @param avctx codec context. + * @param poutbuf set to pointer to parsed buffer or NULL if not yet finished. + * @param poutbuf_size set to size of parsed buffer or zero if not yet finished. + * @param buf input buffer. + * @param buf_size buffer size in bytes without the padding. I.e. the full buffer + size is assumed to be buf_size + AV_INPUT_BUFFER_PADDING_SIZE. + To signal EOF, this should be 0 (so that the last frame + can be output). + * @param pts input presentation timestamp. + * @param dts input decoding timestamp. + * @param pos input byte position in stream. + * @return the number of bytes of the input bitstream used. + * + * Example: + * @code + * while(in_len){ + * len = av_parser_parse2(myparser, AVCodecContext, &data, &size, + * in_data, in_len, + * pts, dts, pos); + * in_data += len; + * in_len -= len; + * + * if(size) + * decode_frame(data, size); + * } + * @endcode + */ +int av_parser_parse2(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int64_t pts, int64_t dts, + int64_t pos); + +void av_parser_close(AVCodecParserContext *s); + +/** + * @} + * @} + */ + +/** + * @addtogroup lavc_encoding + * @{ + */ + +int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVSubtitle *sub); + + +/** + * @} + */ + +/** + * @defgroup lavc_misc Utility functions + * @ingroup libavc + * + * Miscellaneous utility functions related to both encoding and decoding + * (or neither). + * @{ + */ + +/** + * @defgroup lavc_misc_pixfmt Pixel formats + * + * Functions for working with pixel formats. + * @{ + */ + +/** + * Return a value representing the fourCC code associated to the + * pixel format pix_fmt, or 0 if no associated fourCC code can be + * found. + */ +unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt); + +/** + * Find the best pixel format to convert to given a certain source pixel + * format. When converting from one pixel format to another, information loss + * may occur. For example, when converting from RGB24 to GRAY, the color + * information will be lost. Similarly, other losses occur when converting from + * some formats to other formats. avcodec_find_best_pix_fmt_of_2() searches which of + * the given pixel formats should be used to suffer the least amount of loss. + * The pixel formats from which it chooses one, are determined by the + * pix_fmt_list parameter. + * + * + * @param[in] pix_fmt_list AV_PIX_FMT_NONE terminated array of pixel formats to choose from + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. + * @return The best pixel format to convert to or -1 if none was found. + */ +enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *pix_fmt_list, + enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); + +enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + +/** + * @} + */ + +void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); + +int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); +int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count); +//FIXME func typedef + +/** + * Fill AVFrame audio data and linesize pointers. + * + * The buffer buf must be a preallocated buffer with a size big enough + * to contain the specified samples amount. The filled AVFrame data + * pointers will point to this buffer. + * + * AVFrame extended_data channel pointers are allocated if necessary for + * planar audio. + * + * @param frame the AVFrame + * frame->nb_samples must be set prior to calling the + * function. This function fills in frame->data, + * frame->extended_data, frame->linesize[0]. + * @param nb_channels channel count + * @param sample_fmt sample format + * @param buf buffer to use for frame data + * @param buf_size size of buffer + * @param align plane size sample alignment (0 = default) + * @return >=0 on success, negative error code on failure + * @todo return the size in bytes required to store the samples in + * case of success, at the next libavutil bump + */ +int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, + enum AVSampleFormat sample_fmt, const uint8_t *buf, + int buf_size, int align); + +/** + * Reset the internal codec state / flush internal buffers. Should be called + * e.g. when seeking or when switching to a different stream. + * + * @note for decoders, this function just releases any references the decoder + * might keep internally, but the caller's references remain valid. + * + * @note for encoders, this function will only do something if the encoder + * declares support for AV_CODEC_CAP_ENCODER_FLUSH. When called, the encoder + * will drain any remaining packets, and can then be reused for a different + * stream (as opposed to sending a null frame which will leave the encoder + * in a permanent EOF state after draining). This can be desirable if the + * cost of tearing down and replacing the encoder instance is high. + */ +void avcodec_flush_buffers(AVCodecContext *avctx); + +/** + * Return audio frame duration. + * + * @param avctx codec context + * @param frame_bytes size of the frame, or 0 if unknown + * @return frame duration, in samples, if known. 0 if not able to + * determine. + */ +int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes); + +/* memory */ + +/** + * Same behaviour av_fast_malloc but the buffer has additional + * AV_INPUT_BUFFER_PADDING_SIZE at the end which will always be 0. + * + * In addition the whole buffer will initially and after resizes + * be 0-initialized so that no uninitialized data will ever appear. + */ +void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Same behaviour av_fast_padded_malloc except that buffer will always + * be 0-initialized after call. + */ +void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * @return a positive value if s is open (i.e. avcodec_open2() was called on it), + * 0 otherwise. + */ +int avcodec_is_open(AVCodecContext *s); + +/** + * @} + */ + +#endif /* AVCODEC_AVCODEC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec.h b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec.h new file mode 100644 index 0000000000000..f509e5d94e1b6 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec.h @@ -0,0 +1,367 @@ +/* + * AVCodec public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_H +#define AVCODEC_CODEC_H + +#include + +#include "libavutil/avutil.h" +#include "libavutil/hwcontext.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" +#include "libavutil/samplefmt.h" + +#include "libavcodec/codec_id.h" +#include "libavcodec/version_major.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * Decoder can use draw_horiz_band callback. + */ +#define AV_CODEC_CAP_DRAW_HORIZ_BAND (1 << 0) +/** + * Codec uses get_buffer() or get_encode_buffer() for allocating buffers and + * supports custom allocators. + * If not set, it might not use get_buffer() or get_encode_buffer() at all, or + * use operations that assume the buffer was allocated by + * avcodec_default_get_buffer2 or avcodec_default_get_encode_buffer. + */ +#define AV_CODEC_CAP_DR1 (1 << 1) +/** + * Encoder or decoder requires flushing with NULL input at the end in order to + * give the complete and correct output. + * + * NOTE: If this flag is not set, the codec is guaranteed to never be fed with + * with NULL data. The user can still send NULL data to the public encode + * or decode function, but libavcodec will not pass it along to the codec + * unless this flag is set. + * + * Decoders: + * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to get the delayed data until the decoder no longer + * returns frames. + * + * Encoders: + * The encoder needs to be fed with NULL data at the end of encoding until the + * encoder no longer returns data. + * + * NOTE: For encoders implementing the AVCodec.encode2() function, setting this + * flag also means that the encoder must set the pts and duration for + * each output packet. If this flag is not set, the pts and duration will + * be determined by libavcodec from the input frame. + */ +#define AV_CODEC_CAP_DELAY (1 << 5) +/** + * Codec can be fed a final frame with a smaller size. + * This can be used to prevent truncation of the last audio samples. + */ +#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6) + +/** + * Codec is experimental and is thus avoided in favor of non experimental + * encoders + */ +#define AV_CODEC_CAP_EXPERIMENTAL (1 << 9) +/** + * Codec should fill in channel configuration and samplerate instead of container + */ +#define AV_CODEC_CAP_CHANNEL_CONF (1 << 10) +/** + * Codec supports frame-level multithreading. + */ +#define AV_CODEC_CAP_FRAME_THREADS (1 << 12) +/** + * Codec supports slice-based (or partition-based) multithreading. + */ +#define AV_CODEC_CAP_SLICE_THREADS (1 << 13) +/** + * Codec supports changed parameters at any point. + */ +#define AV_CODEC_CAP_PARAM_CHANGE (1 << 14) +/** + * Codec supports multithreading through a method other than slice- or + * frame-level multithreading. Typically this marks wrappers around + * multithreading-capable external libraries. + */ +#define AV_CODEC_CAP_OTHER_THREADS (1 << 15) +/** + * Audio encoder supports receiving a different number of samples in each call. + */ +#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16) +/** + * Decoder is not a preferred choice for probing. + * This indicates that the decoder is not a good choice for probing. + * It could for example be an expensive to spin up hardware decoder, + * or it could simply not provide a lot of useful information about + * the stream. + * A decoder marked with this flag should only be used as last resort + * choice for probing. + */ +#define AV_CODEC_CAP_AVOID_PROBING (1 << 17) + +/** + * Codec is backed by a hardware implementation. Typically used to + * identify a non-hwaccel hardware decoder. For information about hwaccels, use + * avcodec_get_hw_config() instead. + */ +#define AV_CODEC_CAP_HARDWARE (1 << 18) + +/** + * Codec is potentially backed by a hardware implementation, but not + * necessarily. This is used instead of AV_CODEC_CAP_HARDWARE, if the + * implementation provides some sort of internal fallback. + */ +#define AV_CODEC_CAP_HYBRID (1 << 19) + +/** + * This encoder can reorder user opaque values from input AVFrames and return + * them with corresponding output packets. + * @see AV_CODEC_FLAG_COPY_OPAQUE + */ +#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE (1 << 20) + +/** + * This encoder can be flushed using avcodec_flush_buffers(). If this flag is + * not set, the encoder must be closed and reopened to ensure that no frames + * remain pending. + */ +#define AV_CODEC_CAP_ENCODER_FLUSH (1 << 21) + +/** + * The encoder is able to output reconstructed frame data, i.e. raw frames that + * would be produced by decoding the encoded bitstream. + * + * Reconstructed frame output is enabled by the AV_CODEC_FLAG_RECON_FRAME flag. + */ +#define AV_CODEC_CAP_ENCODER_RECON_FRAME (1 << 22) + +/** + * AVProfile. + */ +typedef struct AVProfile { + int profile; + const char *name; ///< short name for the profile +} AVProfile; + +/** + * AVCodec. + */ +typedef struct AVCodec { + /** + * Name of the codec implementation. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + * This is the primary way to find a codec from the user perspective. + */ + const char *name; + /** + * Descriptive name for the codec, meant to be more human readable than name. + * You should use the NULL_IF_CONFIG_SMALL() macro to define it. + */ + const char *long_name; + enum AVMediaType type; + enum AVCodecID id; + /** + * Codec capabilities. + * see AV_CODEC_CAP_* + */ + int capabilities; + uint8_t max_lowres; ///< maximum value for lowres supported by the decoder + + /** + * Deprecated codec capabilities. + */ + attribute_deprecated + const AVRational *supported_framerates; ///< @deprecated use avcodec_get_supported_config() + attribute_deprecated + const enum AVPixelFormat *pix_fmts; ///< @deprecated use avcodec_get_supported_config() + attribute_deprecated + const int *supported_samplerates; ///< @deprecated use avcodec_get_supported_config() + attribute_deprecated + const enum AVSampleFormat *sample_fmts; ///< @deprecated use avcodec_get_supported_config() + + const AVClass *priv_class; ///< AVClass for the private context + const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {AV_PROFILE_UNKNOWN} + + /** + * Group name of the codec implementation. + * This is a short symbolic name of the wrapper backing this codec. A + * wrapper uses some kind of external implementation for the codec, such + * as an external library, or a codec implementation provided by the OS or + * the hardware. + * If this field is NULL, this is a builtin, libavcodec native codec. + * If non-NULL, this will be the suffix in AVCodec.name in most cases + * (usually AVCodec.name will be of the form "_"). + */ + const char *wrapper_name; + + /** + * Array of supported channel layouts, terminated with a zeroed layout. + * @deprecated use avcodec_get_supported_config() + */ + attribute_deprecated + const AVChannelLayout *ch_layouts; +} AVCodec; + +/** + * Iterate over all registered codecs. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec or NULL when the iteration is + * finished + */ +const AVCodec *av_codec_iterate(void **opaque); + +/** + * Find a registered decoder with a matching codec ID. + * + * @param id AVCodecID of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_decoder(enum AVCodecID id); + +/** + * Find a registered decoder with the specified name. + * + * @param name name of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_decoder_by_name(const char *name); + +/** + * Find a registered encoder with a matching codec ID. + * + * @param id AVCodecID of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_encoder(enum AVCodecID id); + +/** + * Find a registered encoder with the specified name. + * + * @param name name of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +const AVCodec *avcodec_find_encoder_by_name(const char *name); +/** + * @return a non-zero number if codec is an encoder, zero otherwise + */ +int av_codec_is_encoder(const AVCodec *codec); + +/** + * @return a non-zero number if codec is a decoder, zero otherwise + */ +int av_codec_is_decoder(const AVCodec *codec); + +/** + * Return a name for the specified profile, if available. + * + * @param codec the codec that is searched for the given profile + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + */ +const char *av_get_profile_name(const AVCodec *codec, int profile); + +enum { + /** + * The codec supports this format via the hw_device_ctx interface. + * + * When selecting this format, AVCodecContext.hw_device_ctx should + * have been set to a device of the specified type before calling + * avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01, + /** + * The codec supports this format via the hw_frames_ctx interface. + * + * When selecting this format for a decoder, + * AVCodecContext.hw_frames_ctx should be set to a suitable frames + * context inside the get_format() callback. The frames context + * must have been created on a device of the specified type. + * + * When selecting this format for an encoder, + * AVCodecContext.hw_frames_ctx should be set to the context which + * will be used for the input frames before calling avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02, + /** + * The codec supports this format by some internal method. + * + * This format can be selected without any additional configuration - + * no device or frames context is required. + */ + AV_CODEC_HW_CONFIG_METHOD_INTERNAL = 0x04, + /** + * The codec supports this format by some ad-hoc method. + * + * Additional settings and/or function calls are required. See the + * codec-specific documentation for details. (Methods requiring + * this sort of configuration are deprecated and others should be + * used in preference.) + */ + AV_CODEC_HW_CONFIG_METHOD_AD_HOC = 0x08, +}; + +typedef struct AVCodecHWConfig { + /** + * For decoders, a hardware pixel format which that decoder may be + * able to decode to if suitable hardware is available. + * + * For encoders, a pixel format which the encoder may be able to + * accept. If set to AV_PIX_FMT_NONE, this applies to all pixel + * formats supported by the codec. + */ + enum AVPixelFormat pix_fmt; + /** + * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible + * setup methods which can be used with this configuration. + */ + int methods; + /** + * The device type associated with the configuration. + * + * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and + * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused. + */ + enum AVHWDeviceType device_type; +} AVCodecHWConfig; + +/** + * Retrieve supported hardware configurations for a codec. + * + * Values of index from zero to some maximum return the indexed configuration + * descriptor; all other values return NULL. If the codec does not support + * any hardware configurations then it will always return NULL. + */ +const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index); + +/** + * @} + */ + +#endif /* AVCODEC_CODEC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec_desc.h b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec_desc.h new file mode 100644 index 0000000000000..96afd20208b3d --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec_desc.h @@ -0,0 +1,134 @@ +/* + * Codec descriptors public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_DESC_H +#define AVCODEC_CODEC_DESC_H + +#include "libavutil/avutil.h" + +#include "codec_id.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * This struct describes the properties of a single codec described by an + * AVCodecID. + * @see avcodec_descriptor_get() + */ +typedef struct AVCodecDescriptor { + enum AVCodecID id; + enum AVMediaType type; + /** + * Name of the codec described by this descriptor. It is non-empty and + * unique for each codec descriptor. It should contain alphanumeric + * characters and '_' only. + */ + const char *name; + /** + * A more descriptive name for this codec. May be NULL. + */ + const char *long_name; + /** + * Codec properties, a combination of AV_CODEC_PROP_* flags. + */ + int props; + /** + * MIME type(s) associated with the codec. + * May be NULL; if not, a NULL-terminated array of MIME types. + * The first item is always non-NULL and is the preferred MIME type. + */ + const char *const *mime_types; + /** + * If non-NULL, an array of profiles recognized for this codec. + * Terminated with AV_PROFILE_UNKNOWN. + */ + const struct AVProfile *profiles; +} AVCodecDescriptor; + +/** + * Codec uses only intra compression. + * Video and audio codecs only. + */ +#define AV_CODEC_PROP_INTRA_ONLY (1 << 0) +/** + * Codec supports lossy compression. Audio and video codecs only. + * @note a codec may support both lossy and lossless + * compression modes + */ +#define AV_CODEC_PROP_LOSSY (1 << 1) +/** + * Codec supports lossless compression. Audio and video codecs only. + */ +#define AV_CODEC_PROP_LOSSLESS (1 << 2) +/** + * Codec supports frame reordering. That is, the coded order (the order in which + * the encoded packets are output by the encoders / stored / input to the + * decoders) may be different from the presentation order of the corresponding + * frames. + * + * For codecs that do not have this property set, PTS and DTS should always be + * equal. + */ +#define AV_CODEC_PROP_REORDER (1 << 3) + +/** + * Video codec supports separate coding of fields in interlaced frames. + */ +#define AV_CODEC_PROP_FIELDS (1 << 4) + +/** + * Subtitle codec is bitmap based + * Decoded AVSubtitle data can be read from the AVSubtitleRect->pict field. + */ +#define AV_CODEC_PROP_BITMAP_SUB (1 << 16) +/** + * Subtitle codec is text based. + * Decoded AVSubtitle data can be read from the AVSubtitleRect->ass field. + */ +#define AV_CODEC_PROP_TEXT_SUB (1 << 17) + +/** + * @return descriptor for given codec ID or NULL if no descriptor exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id); + +/** + * Iterate over all codec descriptors known to libavcodec. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); + +/** + * @return codec descriptor with the given name or NULL if no such descriptor + * exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_DESC_H diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec_id.h b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec_id.h new file mode 100644 index 0000000000000..c4842e61ff031 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec_id.h @@ -0,0 +1,683 @@ +/* + * Codec IDs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_ID_H +#define AVCODEC_CODEC_ID_H + +#include "libavutil/avutil.h" +#include "libavutil/samplefmt.h" + +#include "version_major.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * Identify the syntax and semantics of the bitstream. + * The principle is roughly: + * Two decoders with the same ID can decode the same streams. + * Two encoders with the same ID can encode compatible streams. + * There may be slight deviations from the principle due to implementation + * details. + * + * If you add a codec ID to this list, add it so that + * 1. no value of an existing codec ID changes (that would break ABI), + * 2. it is as close as possible to similar codecs + * + * After adding new codec IDs, do not forget to add an entry to the codec + * descriptor list and bump libavcodec minor version. + */ +enum AVCodecID { + AV_CODEC_ID_NONE, + + /* video codecs */ + AV_CODEC_ID_MPEG1VIDEO, + AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding + AV_CODEC_ID_H261, + AV_CODEC_ID_H263, + AV_CODEC_ID_RV10, + AV_CODEC_ID_RV20, + AV_CODEC_ID_MJPEG, + AV_CODEC_ID_MJPEGB, + AV_CODEC_ID_LJPEG, + AV_CODEC_ID_SP5X, + AV_CODEC_ID_JPEGLS, + AV_CODEC_ID_MPEG4, + AV_CODEC_ID_RAWVIDEO, + AV_CODEC_ID_MSMPEG4V1, + AV_CODEC_ID_MSMPEG4V2, + AV_CODEC_ID_MSMPEG4V3, + AV_CODEC_ID_WMV1, + AV_CODEC_ID_WMV2, + AV_CODEC_ID_H263P, + AV_CODEC_ID_H263I, + AV_CODEC_ID_FLV1, + AV_CODEC_ID_SVQ1, + AV_CODEC_ID_SVQ3, + AV_CODEC_ID_DVVIDEO, + AV_CODEC_ID_HUFFYUV, + AV_CODEC_ID_CYUV, + AV_CODEC_ID_H264, + AV_CODEC_ID_INDEO3, + AV_CODEC_ID_VP3, + AV_CODEC_ID_THEORA, + AV_CODEC_ID_ASV1, + AV_CODEC_ID_ASV2, + AV_CODEC_ID_FFV1, + AV_CODEC_ID_4XM, + AV_CODEC_ID_VCR1, + AV_CODEC_ID_CLJR, + AV_CODEC_ID_MDEC, + AV_CODEC_ID_ROQ, + AV_CODEC_ID_INTERPLAY_VIDEO, + AV_CODEC_ID_XAN_WC3, + AV_CODEC_ID_XAN_WC4, + AV_CODEC_ID_RPZA, + AV_CODEC_ID_CINEPAK, + AV_CODEC_ID_WS_VQA, + AV_CODEC_ID_MSRLE, + AV_CODEC_ID_MSVIDEO1, + AV_CODEC_ID_IDCIN, + AV_CODEC_ID_8BPS, + AV_CODEC_ID_SMC, + AV_CODEC_ID_FLIC, + AV_CODEC_ID_TRUEMOTION1, + AV_CODEC_ID_VMDVIDEO, + AV_CODEC_ID_MSZH, + AV_CODEC_ID_ZLIB, + AV_CODEC_ID_QTRLE, + AV_CODEC_ID_TSCC, + AV_CODEC_ID_ULTI, + AV_CODEC_ID_QDRAW, + AV_CODEC_ID_VIXL, + AV_CODEC_ID_QPEG, + AV_CODEC_ID_PNG, + AV_CODEC_ID_PPM, + AV_CODEC_ID_PBM, + AV_CODEC_ID_PGM, + AV_CODEC_ID_PGMYUV, + AV_CODEC_ID_PAM, + AV_CODEC_ID_FFVHUFF, + AV_CODEC_ID_RV30, + AV_CODEC_ID_RV40, + AV_CODEC_ID_VC1, + AV_CODEC_ID_WMV3, + AV_CODEC_ID_LOCO, + AV_CODEC_ID_WNV1, + AV_CODEC_ID_AASC, + AV_CODEC_ID_INDEO2, + AV_CODEC_ID_FRAPS, + AV_CODEC_ID_TRUEMOTION2, + AV_CODEC_ID_BMP, + AV_CODEC_ID_CSCD, + AV_CODEC_ID_MMVIDEO, + AV_CODEC_ID_ZMBV, + AV_CODEC_ID_AVS, + AV_CODEC_ID_SMACKVIDEO, + AV_CODEC_ID_NUV, + AV_CODEC_ID_KMVC, + AV_CODEC_ID_FLASHSV, + AV_CODEC_ID_CAVS, + AV_CODEC_ID_JPEG2000, + AV_CODEC_ID_VMNC, + AV_CODEC_ID_VP5, + AV_CODEC_ID_VP6, + AV_CODEC_ID_VP6F, + AV_CODEC_ID_TARGA, + AV_CODEC_ID_DSICINVIDEO, + AV_CODEC_ID_TIERTEXSEQVIDEO, + AV_CODEC_ID_TIFF, + AV_CODEC_ID_GIF, + AV_CODEC_ID_DXA, + AV_CODEC_ID_DNXHD, + AV_CODEC_ID_THP, + AV_CODEC_ID_SGI, + AV_CODEC_ID_C93, + AV_CODEC_ID_BETHSOFTVID, + AV_CODEC_ID_PTX, + AV_CODEC_ID_TXD, + AV_CODEC_ID_VP6A, + AV_CODEC_ID_AMV, + AV_CODEC_ID_VB, + AV_CODEC_ID_PCX, + AV_CODEC_ID_SUNRAST, + AV_CODEC_ID_INDEO4, + AV_CODEC_ID_INDEO5, + AV_CODEC_ID_MIMIC, + AV_CODEC_ID_RL2, + AV_CODEC_ID_ESCAPE124, + AV_CODEC_ID_DIRAC, + AV_CODEC_ID_BFI, + AV_CODEC_ID_CMV, + AV_CODEC_ID_MOTIONPIXELS, + AV_CODEC_ID_TGV, + AV_CODEC_ID_TGQ, + AV_CODEC_ID_TQI, + AV_CODEC_ID_AURA, + AV_CODEC_ID_AURA2, + AV_CODEC_ID_V210X, + AV_CODEC_ID_TMV, + AV_CODEC_ID_V210, + AV_CODEC_ID_DPX, + AV_CODEC_ID_MAD, + AV_CODEC_ID_FRWU, + AV_CODEC_ID_FLASHSV2, + AV_CODEC_ID_CDGRAPHICS, + AV_CODEC_ID_R210, + AV_CODEC_ID_ANM, + AV_CODEC_ID_BINKVIDEO, + AV_CODEC_ID_IFF_ILBM, +#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM + AV_CODEC_ID_KGV1, + AV_CODEC_ID_YOP, + AV_CODEC_ID_VP8, + AV_CODEC_ID_PICTOR, + AV_CODEC_ID_ANSI, + AV_CODEC_ID_A64_MULTI, + AV_CODEC_ID_A64_MULTI5, + AV_CODEC_ID_R10K, + AV_CODEC_ID_MXPEG, + AV_CODEC_ID_LAGARITH, + AV_CODEC_ID_PRORES, + AV_CODEC_ID_JV, + AV_CODEC_ID_DFA, + AV_CODEC_ID_WMV3IMAGE, + AV_CODEC_ID_VC1IMAGE, + AV_CODEC_ID_UTVIDEO, + AV_CODEC_ID_BMV_VIDEO, + AV_CODEC_ID_VBLE, + AV_CODEC_ID_DXTORY, +#if FF_API_V408_CODECID + AV_CODEC_ID_V410, +#endif + AV_CODEC_ID_XWD, + AV_CODEC_ID_CDXL, + AV_CODEC_ID_XBM, + AV_CODEC_ID_ZEROCODEC, + AV_CODEC_ID_MSS1, + AV_CODEC_ID_MSA1, + AV_CODEC_ID_TSCC2, + AV_CODEC_ID_MTS2, + AV_CODEC_ID_CLLC, + AV_CODEC_ID_MSS2, + AV_CODEC_ID_VP9, + AV_CODEC_ID_AIC, + AV_CODEC_ID_ESCAPE130, + AV_CODEC_ID_G2M, + AV_CODEC_ID_WEBP, + AV_CODEC_ID_HNM4_VIDEO, + AV_CODEC_ID_HEVC, +#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC + AV_CODEC_ID_FIC, + AV_CODEC_ID_ALIAS_PIX, + AV_CODEC_ID_BRENDER_PIX, + AV_CODEC_ID_PAF_VIDEO, + AV_CODEC_ID_EXR, + AV_CODEC_ID_VP7, + AV_CODEC_ID_SANM, + AV_CODEC_ID_SGIRLE, + AV_CODEC_ID_MVC1, + AV_CODEC_ID_MVC2, + AV_CODEC_ID_HQX, + AV_CODEC_ID_TDSC, + AV_CODEC_ID_HQ_HQA, + AV_CODEC_ID_HAP, + AV_CODEC_ID_DDS, + AV_CODEC_ID_DXV, + AV_CODEC_ID_SCREENPRESSO, + AV_CODEC_ID_RSCC, + AV_CODEC_ID_AVS2, + AV_CODEC_ID_PGX, + AV_CODEC_ID_AVS3, + AV_CODEC_ID_MSP2, + AV_CODEC_ID_VVC, +#define AV_CODEC_ID_H266 AV_CODEC_ID_VVC + AV_CODEC_ID_Y41P, + AV_CODEC_ID_AVRP, + AV_CODEC_ID_012V, + AV_CODEC_ID_AVUI, + AV_CODEC_ID_TARGA_Y216, +#if FF_API_V408_CODECID + AV_CODEC_ID_V308, + AV_CODEC_ID_V408, +#endif + AV_CODEC_ID_YUV4, + AV_CODEC_ID_AVRN, + AV_CODEC_ID_CPIA, + AV_CODEC_ID_XFACE, + AV_CODEC_ID_SNOW, + AV_CODEC_ID_SMVJPEG, + AV_CODEC_ID_APNG, + AV_CODEC_ID_DAALA, + AV_CODEC_ID_CFHD, + AV_CODEC_ID_TRUEMOTION2RT, + AV_CODEC_ID_M101, + AV_CODEC_ID_MAGICYUV, + AV_CODEC_ID_SHEERVIDEO, + AV_CODEC_ID_YLC, + AV_CODEC_ID_PSD, + AV_CODEC_ID_PIXLET, + AV_CODEC_ID_SPEEDHQ, + AV_CODEC_ID_FMVC, + AV_CODEC_ID_SCPR, + AV_CODEC_ID_CLEARVIDEO, + AV_CODEC_ID_XPM, + AV_CODEC_ID_AV1, + AV_CODEC_ID_BITPACKED, + AV_CODEC_ID_MSCC, + AV_CODEC_ID_SRGC, + AV_CODEC_ID_SVG, + AV_CODEC_ID_GDV, + AV_CODEC_ID_FITS, + AV_CODEC_ID_IMM4, + AV_CODEC_ID_PROSUMER, + AV_CODEC_ID_MWSC, + AV_CODEC_ID_WCMV, + AV_CODEC_ID_RASC, + AV_CODEC_ID_HYMT, + AV_CODEC_ID_ARBC, + AV_CODEC_ID_AGM, + AV_CODEC_ID_LSCR, + AV_CODEC_ID_VP4, + AV_CODEC_ID_IMM5, + AV_CODEC_ID_MVDV, + AV_CODEC_ID_MVHA, + AV_CODEC_ID_CDTOONS, + AV_CODEC_ID_MV30, + AV_CODEC_ID_NOTCHLC, + AV_CODEC_ID_PFM, + AV_CODEC_ID_MOBICLIP, + AV_CODEC_ID_PHOTOCD, + AV_CODEC_ID_IPU, + AV_CODEC_ID_ARGO, + AV_CODEC_ID_CRI, + AV_CODEC_ID_SIMBIOSIS_IMX, + AV_CODEC_ID_SGA_VIDEO, + AV_CODEC_ID_GEM, + AV_CODEC_ID_VBN, + AV_CODEC_ID_JPEGXL, + AV_CODEC_ID_QOI, + AV_CODEC_ID_PHM, + AV_CODEC_ID_RADIANCE_HDR, + AV_CODEC_ID_WBMP, + AV_CODEC_ID_MEDIA100, + AV_CODEC_ID_VQC, + AV_CODEC_ID_PDV, + AV_CODEC_ID_EVC, + AV_CODEC_ID_RTV1, + AV_CODEC_ID_VMIX, + AV_CODEC_ID_LEAD, + AV_CODEC_ID_DNXUC, + AV_CODEC_ID_RV60, + AV_CODEC_ID_JPEGXL_ANIM, + AV_CODEC_ID_APV, + AV_CODEC_ID_PRORES_RAW, + + /* various PCM "codecs" */ + AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs + AV_CODEC_ID_PCM_S16LE = 0x10000, + AV_CODEC_ID_PCM_S16BE, + AV_CODEC_ID_PCM_U16LE, + AV_CODEC_ID_PCM_U16BE, + AV_CODEC_ID_PCM_S8, + AV_CODEC_ID_PCM_U8, + AV_CODEC_ID_PCM_MULAW, + AV_CODEC_ID_PCM_ALAW, + AV_CODEC_ID_PCM_S32LE, + AV_CODEC_ID_PCM_S32BE, + AV_CODEC_ID_PCM_U32LE, + AV_CODEC_ID_PCM_U32BE, + AV_CODEC_ID_PCM_S24LE, + AV_CODEC_ID_PCM_S24BE, + AV_CODEC_ID_PCM_U24LE, + AV_CODEC_ID_PCM_U24BE, + AV_CODEC_ID_PCM_S24DAUD, + AV_CODEC_ID_PCM_ZORK, + AV_CODEC_ID_PCM_S16LE_PLANAR, + AV_CODEC_ID_PCM_DVD, + AV_CODEC_ID_PCM_F32BE, + AV_CODEC_ID_PCM_F32LE, + AV_CODEC_ID_PCM_F64BE, + AV_CODEC_ID_PCM_F64LE, + AV_CODEC_ID_PCM_BLURAY, + AV_CODEC_ID_PCM_LXF, + AV_CODEC_ID_S302M, + AV_CODEC_ID_PCM_S8_PLANAR, + AV_CODEC_ID_PCM_S24LE_PLANAR, + AV_CODEC_ID_PCM_S32LE_PLANAR, + AV_CODEC_ID_PCM_S16BE_PLANAR, + AV_CODEC_ID_PCM_S64LE, + AV_CODEC_ID_PCM_S64BE, + AV_CODEC_ID_PCM_F16LE, + AV_CODEC_ID_PCM_F24LE, + AV_CODEC_ID_PCM_VIDC, + AV_CODEC_ID_PCM_SGA, + + /* various ADPCM codecs */ + AV_CODEC_ID_ADPCM_IMA_QT = 0x11000, + AV_CODEC_ID_ADPCM_IMA_WAV, + AV_CODEC_ID_ADPCM_IMA_DK3, + AV_CODEC_ID_ADPCM_IMA_DK4, + AV_CODEC_ID_ADPCM_IMA_WS, + AV_CODEC_ID_ADPCM_IMA_SMJPEG, + AV_CODEC_ID_ADPCM_MS, + AV_CODEC_ID_ADPCM_4XM, + AV_CODEC_ID_ADPCM_XA, + AV_CODEC_ID_ADPCM_ADX, + AV_CODEC_ID_ADPCM_EA, + AV_CODEC_ID_ADPCM_G726, + AV_CODEC_ID_ADPCM_CT, + AV_CODEC_ID_ADPCM_SWF, + AV_CODEC_ID_ADPCM_YAMAHA, + AV_CODEC_ID_ADPCM_SBPRO_4, + AV_CODEC_ID_ADPCM_SBPRO_3, + AV_CODEC_ID_ADPCM_SBPRO_2, + AV_CODEC_ID_ADPCM_THP, + AV_CODEC_ID_ADPCM_IMA_AMV, + AV_CODEC_ID_ADPCM_EA_R1, + AV_CODEC_ID_ADPCM_EA_R3, + AV_CODEC_ID_ADPCM_EA_R2, + AV_CODEC_ID_ADPCM_IMA_EA_SEAD, + AV_CODEC_ID_ADPCM_IMA_EA_EACS, + AV_CODEC_ID_ADPCM_EA_XAS, + AV_CODEC_ID_ADPCM_EA_MAXIS_XA, + AV_CODEC_ID_ADPCM_IMA_ISS, + AV_CODEC_ID_ADPCM_G722, + AV_CODEC_ID_ADPCM_IMA_APC, + AV_CODEC_ID_ADPCM_VIMA, + AV_CODEC_ID_ADPCM_AFC, + AV_CODEC_ID_ADPCM_IMA_OKI, + AV_CODEC_ID_ADPCM_DTK, + AV_CODEC_ID_ADPCM_IMA_RAD, + AV_CODEC_ID_ADPCM_G726LE, + AV_CODEC_ID_ADPCM_THP_LE, + AV_CODEC_ID_ADPCM_PSX, + AV_CODEC_ID_ADPCM_AICA, + AV_CODEC_ID_ADPCM_IMA_DAT4, + AV_CODEC_ID_ADPCM_MTAF, + AV_CODEC_ID_ADPCM_AGM, + AV_CODEC_ID_ADPCM_ARGO, + AV_CODEC_ID_ADPCM_IMA_SSI, + AV_CODEC_ID_ADPCM_ZORK, + AV_CODEC_ID_ADPCM_IMA_APM, + AV_CODEC_ID_ADPCM_IMA_ALP, + AV_CODEC_ID_ADPCM_IMA_MTF, + AV_CODEC_ID_ADPCM_IMA_CUNNING, + AV_CODEC_ID_ADPCM_IMA_MOFLEX, + AV_CODEC_ID_ADPCM_IMA_ACORN, + AV_CODEC_ID_ADPCM_XMD, + AV_CODEC_ID_ADPCM_IMA_XBOX, + AV_CODEC_ID_ADPCM_SANYO, + + /* AMR */ + AV_CODEC_ID_AMR_NB = 0x12000, + AV_CODEC_ID_AMR_WB, + + /* RealAudio codecs*/ + AV_CODEC_ID_RA_144 = 0x13000, + AV_CODEC_ID_RA_288, + + /* various DPCM codecs */ + AV_CODEC_ID_ROQ_DPCM = 0x14000, + AV_CODEC_ID_INTERPLAY_DPCM, + AV_CODEC_ID_XAN_DPCM, + AV_CODEC_ID_SOL_DPCM, + AV_CODEC_ID_SDX2_DPCM, + AV_CODEC_ID_GREMLIN_DPCM, + AV_CODEC_ID_DERF_DPCM, + AV_CODEC_ID_WADY_DPCM, + AV_CODEC_ID_CBD2_DPCM, + + /* audio codecs */ + AV_CODEC_ID_MP2 = 0x15000, + AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 + AV_CODEC_ID_AAC, + AV_CODEC_ID_AC3, + AV_CODEC_ID_DTS, + AV_CODEC_ID_VORBIS, + AV_CODEC_ID_DVAUDIO, + AV_CODEC_ID_WMAV1, + AV_CODEC_ID_WMAV2, + AV_CODEC_ID_MACE3, + AV_CODEC_ID_MACE6, + AV_CODEC_ID_VMDAUDIO, + AV_CODEC_ID_FLAC, + AV_CODEC_ID_MP3ADU, + AV_CODEC_ID_MP3ON4, + AV_CODEC_ID_SHORTEN, + AV_CODEC_ID_ALAC, + AV_CODEC_ID_WESTWOOD_SND1, + AV_CODEC_ID_GSM, ///< as in Berlin toast format + AV_CODEC_ID_QDM2, + AV_CODEC_ID_COOK, + AV_CODEC_ID_TRUESPEECH, + AV_CODEC_ID_TTA, + AV_CODEC_ID_SMACKAUDIO, + AV_CODEC_ID_QCELP, + AV_CODEC_ID_WAVPACK, + AV_CODEC_ID_DSICINAUDIO, + AV_CODEC_ID_IMC, + AV_CODEC_ID_MUSEPACK7, + AV_CODEC_ID_MLP, + AV_CODEC_ID_GSM_MS, /* as found in WAV */ + AV_CODEC_ID_ATRAC3, + AV_CODEC_ID_APE, + AV_CODEC_ID_NELLYMOSER, + AV_CODEC_ID_MUSEPACK8, + AV_CODEC_ID_SPEEX, + AV_CODEC_ID_WMAVOICE, + AV_CODEC_ID_WMAPRO, + AV_CODEC_ID_WMALOSSLESS, + AV_CODEC_ID_ATRAC3P, + AV_CODEC_ID_EAC3, + AV_CODEC_ID_SIPR, + AV_CODEC_ID_MP1, + AV_CODEC_ID_TWINVQ, + AV_CODEC_ID_TRUEHD, + AV_CODEC_ID_MP4ALS, + AV_CODEC_ID_ATRAC1, + AV_CODEC_ID_BINKAUDIO_RDFT, + AV_CODEC_ID_BINKAUDIO_DCT, + AV_CODEC_ID_AAC_LATM, + AV_CODEC_ID_QDMC, + AV_CODEC_ID_CELT, + AV_CODEC_ID_G723_1, + AV_CODEC_ID_G729, + AV_CODEC_ID_8SVX_EXP, + AV_CODEC_ID_8SVX_FIB, + AV_CODEC_ID_BMV_AUDIO, + AV_CODEC_ID_RALF, + AV_CODEC_ID_IAC, + AV_CODEC_ID_ILBC, + AV_CODEC_ID_OPUS, + AV_CODEC_ID_COMFORT_NOISE, + AV_CODEC_ID_TAK, + AV_CODEC_ID_METASOUND, + AV_CODEC_ID_PAF_AUDIO, + AV_CODEC_ID_ON2AVC, + AV_CODEC_ID_DSS_SP, + AV_CODEC_ID_CODEC2, + AV_CODEC_ID_FFWAVESYNTH, + AV_CODEC_ID_SONIC, + AV_CODEC_ID_SONIC_LS, + AV_CODEC_ID_EVRC, + AV_CODEC_ID_SMV, + AV_CODEC_ID_DSD_LSBF, + AV_CODEC_ID_DSD_MSBF, + AV_CODEC_ID_DSD_LSBF_PLANAR, + AV_CODEC_ID_DSD_MSBF_PLANAR, + AV_CODEC_ID_4GV, + AV_CODEC_ID_INTERPLAY_ACM, + AV_CODEC_ID_XMA1, + AV_CODEC_ID_XMA2, + AV_CODEC_ID_DST, + AV_CODEC_ID_ATRAC3AL, + AV_CODEC_ID_ATRAC3PAL, + AV_CODEC_ID_DOLBY_E, + AV_CODEC_ID_APTX, + AV_CODEC_ID_APTX_HD, + AV_CODEC_ID_SBC, + AV_CODEC_ID_ATRAC9, + AV_CODEC_ID_HCOM, + AV_CODEC_ID_ACELP_KELVIN, + AV_CODEC_ID_MPEGH_3D_AUDIO, + AV_CODEC_ID_SIREN, + AV_CODEC_ID_HCA, + AV_CODEC_ID_FASTAUDIO, + AV_CODEC_ID_MSNSIREN, + AV_CODEC_ID_DFPWM, + AV_CODEC_ID_BONK, + AV_CODEC_ID_MISC4, + AV_CODEC_ID_APAC, + AV_CODEC_ID_FTR, + AV_CODEC_ID_WAVARC, + AV_CODEC_ID_RKA, + AV_CODEC_ID_AC4, + AV_CODEC_ID_OSQ, + AV_CODEC_ID_QOA, + AV_CODEC_ID_LC3, + AV_CODEC_ID_G728, + + /* subtitle codecs */ + AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. + AV_CODEC_ID_DVD_SUBTITLE = 0x17000, + AV_CODEC_ID_DVB_SUBTITLE, + AV_CODEC_ID_TEXT, ///< raw UTF-8 text + AV_CODEC_ID_XSUB, + AV_CODEC_ID_SSA, + AV_CODEC_ID_MOV_TEXT, + AV_CODEC_ID_HDMV_PGS_SUBTITLE, + AV_CODEC_ID_DVB_TELETEXT, + AV_CODEC_ID_SRT, + AV_CODEC_ID_MICRODVD, + AV_CODEC_ID_EIA_608, + AV_CODEC_ID_JACOSUB, + AV_CODEC_ID_SAMI, + AV_CODEC_ID_REALTEXT, + AV_CODEC_ID_STL, + AV_CODEC_ID_SUBVIEWER1, + AV_CODEC_ID_SUBVIEWER, + AV_CODEC_ID_SUBRIP, + AV_CODEC_ID_WEBVTT, + AV_CODEC_ID_MPL2, + AV_CODEC_ID_VPLAYER, + AV_CODEC_ID_PJS, + AV_CODEC_ID_ASS, + AV_CODEC_ID_HDMV_TEXT_SUBTITLE, + AV_CODEC_ID_TTML, + AV_CODEC_ID_ARIB_CAPTION, + AV_CODEC_ID_IVTV_VBI, + + /* other specific kind of codecs (generally used for attachments) */ + AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. + AV_CODEC_ID_TTF = 0x18000, + + AV_CODEC_ID_SCTE_35, ///< Contain timestamp estimated through PCR of program stream. + AV_CODEC_ID_EPG, + AV_CODEC_ID_BINTEXT, + AV_CODEC_ID_XBIN, + AV_CODEC_ID_IDF, + AV_CODEC_ID_OTF, + AV_CODEC_ID_SMPTE_KLV, + AV_CODEC_ID_DVD_NAV, + AV_CODEC_ID_TIMED_ID3, + AV_CODEC_ID_BIN_DATA, + AV_CODEC_ID_SMPTE_2038, + AV_CODEC_ID_LCEVC, + AV_CODEC_ID_SMPTE_436M_ANC, + + + AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it + + AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + * stream (only used by libavformat) */ + AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems + * stream (only used by libavformat) */ + AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. + AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket + /** + * Dummy null video codec, useful mainly for development and debugging. + * Null encoder/decoder discard all input and never return any output. + */ + AV_CODEC_ID_VNULL, + /** + * Dummy null audio codec, useful mainly for development and debugging. + * Null encoder/decoder discard all input and never return any output. + */ + AV_CODEC_ID_ANULL, +}; + +/** + * Get the type of the given codec. + */ +enum AVMediaType avcodec_get_type(enum AVCodecID codec_id); + +/** + * Get the name of a codec. + * @return a static string identifying the codec; never NULL + */ +const char *avcodec_get_name(enum AVCodecID id); + +/** + * Return codec bits per sample. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return codec bits per sample. + * Only return non-zero if the bits per sample is exactly correct, not an + * approximation. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_exact_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return a name for the specified profile, if available. + * + * @param codec_id the ID of the codec to which the requested profile belongs + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + * + * @note unlike av_get_profile_name(), which searches a list of profiles + * supported by a specific decoder or encoder implementation, this + * function searches the list of profiles from the AVCodecDescriptor + */ +const char *avcodec_profile_name(enum AVCodecID codec_id, int profile); + +/** + * Return the PCM codec associated with a sample format. + * @param be endianness, 0 for little, 1 for big, + * -1 (or anything else) for native + * @return AV_CODEC_ID_PCM_* or AV_CODEC_ID_NONE + */ +enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_ID_H diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec_par.h b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec_par.h new file mode 100644 index 0000000000000..64b01f7e028b5 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/codec_par.h @@ -0,0 +1,248 @@ +/* + * Codec parameters public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_PAR_H +#define AVCODEC_CODEC_PAR_H + +#include + +#include "libavutil/avutil.h" +#include "libavutil/channel_layout.h" +#include "libavutil/rational.h" +#include "libavutil/pixfmt.h" + +#include "codec_id.h" +#include "defs.h" +#include "packet.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * This struct describes the properties of an encoded stream. + * + * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must + * be allocated with avcodec_parameters_alloc() and freed with + * avcodec_parameters_free(). + */ +typedef struct AVCodecParameters { + /** + * General type of the encoded data. + */ + enum AVMediaType codec_type; + /** + * Specific type of the encoded data (the codec used). + */ + enum AVCodecID codec_id; + /** + * Additional information about the codec (corresponds to the AVI FOURCC). + */ + uint32_t codec_tag; + + /** + * Extra binary data needed for initializing the decoder, codec-dependent. + * + * Must be allocated with av_malloc() and will be freed by + * avcodec_parameters_free(). The allocated size of extradata must be at + * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding + * bytes zeroed. + */ + uint8_t *extradata; + /** + * Size of the extradata content in bytes. + */ + int extradata_size; + + /** + * Additional data associated with the entire stream. + * + * Should be allocated with av_packet_side_data_new() or + * av_packet_side_data_add(), and will be freed by avcodec_parameters_free(). + */ + AVPacketSideData *coded_side_data; + + /** + * Amount of entries in @ref coded_side_data. + */ + int nb_coded_side_data; + + /** + * - video: the pixel format, the value corresponds to enum AVPixelFormat. + * - audio: the sample format, the value corresponds to enum AVSampleFormat. + */ + int format; + + /** + * The average bitrate of the encoded data (in bits per second). + */ + int64_t bit_rate; + + /** + * The number of bits per sample in the codedwords. + * + * This is basically the bitrate per sample. It is mandatory for a bunch of + * formats to actually decode them. It's the number of bits for one sample in + * the actual coded bitstream. + * + * This could be for example 4 for ADPCM + * For PCM formats this matches bits_per_raw_sample + * Can be 0 + */ + int bits_per_coded_sample; + + /** + * This is the number of valid bits in each output sample. If the + * sample format has more bits, the least significant bits are additional + * padding bits, which are always 0. Use right shifts to reduce the sample + * to its actual size. For example, audio formats with 24 bit samples will + * have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32. + * To get the original sample use "(int32_t)sample >> 8"." + * + * For ADPCM this might be 12 or 16 or similar + * Can be 0 + */ + int bits_per_raw_sample; + + /** + * Codec-specific bitstream restrictions that the stream conforms to. + */ + int profile; + int level; + + /** + * Video only. The dimensions of the video frame in pixels. + */ + int width; + int height; + + /** + * Video only. The aspect ratio (width / height) which a single pixel + * should have when displayed. + * + * When the aspect ratio is unknown / undefined, the numerator should be + * set to 0 (the denominator may have any value). + */ + AVRational sample_aspect_ratio; + + /** + * Video only. Number of frames per second, for streams with constant frame + * durations. Should be set to { 0, 1 } when some frames have differing + * durations or if the value is not known. + * + * @note This field corresponds to values that are stored in codec-level + * headers and is typically overridden by container/transport-layer + * timestamps, when available. It should thus be used only as a last resort, + * when no higher-level timing information is available. + */ + AVRational framerate; + + /** + * Video only. The order of the fields in interlaced video. + */ + enum AVFieldOrder field_order; + + /** + * Video only. Additional colorspace characteristics. + */ + enum AVColorRange color_range; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace color_space; + enum AVChromaLocation chroma_location; + + /** + * Video only. Number of delayed frames. + */ + int video_delay; + + /** + * Audio only. The channel layout and number of channels. + */ + AVChannelLayout ch_layout; + /** + * Audio only. The number of audio samples per second. + */ + int sample_rate; + /** + * Audio only. The number of bytes per coded audio frame, required by some + * formats. + * + * Corresponds to nBlockAlign in WAVEFORMATEX. + */ + int block_align; + /** + * Audio only. Audio frame size, if known. Required by some formats to be static. + */ + int frame_size; + + /** + * Audio only. The amount of padding (in samples) inserted by the encoder at + * the beginning of the audio. I.e. this number of leading decoded samples + * must be discarded by the caller to get the original audio without leading + * padding. + */ + int initial_padding; + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + */ + int trailing_padding; + /** + * Audio only. Number of samples to skip after a discontinuity. + */ + int seek_preroll; +} AVCodecParameters; + +/** + * Allocate a new AVCodecParameters and set its fields to default values + * (unknown/invalid/0). The returned struct must be freed with + * avcodec_parameters_free(). + */ +AVCodecParameters *avcodec_parameters_alloc(void); + +/** + * Free an AVCodecParameters instance and everything associated with it and + * write NULL to the supplied pointer. + */ +void avcodec_parameters_free(AVCodecParameters **par); + +/** + * Copy the contents of src to dst. Any allocated fields in dst are freed and + * replaced with newly allocated duplicates of the corresponding fields in src. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src); + +/** + * This function is the same as av_get_audio_frame_duration(), except it works + * with AVCodecParameters instead of an AVCodecContext. + */ +int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_PAR_H diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/defs.h b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/defs.h new file mode 100644 index 0000000000000..b13e983b13a93 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/defs.h @@ -0,0 +1,362 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DEFS_H +#define AVCODEC_DEFS_H + +/** + * @file + * @ingroup libavc + * Misc types and constants that do not belong anywhere else. + */ + +#include +#include + +/** + * @ingroup lavc_decoding + * Required number of additionally allocated bytes at the end of the input bitstream for decoding. + * This is mainly needed because some optimized bitstream readers read + * 32 or 64 bit at once and could read over the end.
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged + * MPEG bitstreams could cause overread and segfault. + */ +#define AV_INPUT_BUFFER_PADDING_SIZE 64 + +/** + * Verify checksums embedded in the bitstream (could be of either encoded or + * decoded data, depending on the format) and print an error message on mismatch. + * If AV_EF_EXPLODE is also set, a mismatching checksum will result in the + * decoder/demuxer returning an error. + */ +#define AV_EF_CRCCHECK (1<<0) +#define AV_EF_BITSTREAM (1<<1) ///< detect bitstream specification deviations +#define AV_EF_BUFFER (1<<2) ///< detect improper bitstream length +#define AV_EF_EXPLODE (1<<3) ///< abort decoding on minor error detection + +#define AV_EF_IGNORE_ERR (1<<15) ///< ignore errors and continue +#define AV_EF_CAREFUL (1<<16) ///< consider things that violate the spec, are fast to calculate and have not been seen in the wild as errors +#define AV_EF_COMPLIANT (1<<17) ///< consider all spec non compliances as errors +#define AV_EF_AGGRESSIVE (1<<18) ///< consider things that a sane encoder/muxer should not do as an error + +#define FF_COMPLIANCE_VERY_STRICT 2 ///< Strictly conform to an older more strict version of the spec or reference software. +#define FF_COMPLIANCE_STRICT 1 ///< Strictly conform to all the things in the spec no matter what consequences. +#define FF_COMPLIANCE_NORMAL 0 +#define FF_COMPLIANCE_UNOFFICIAL -1 ///< Allow unofficial extensions +#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things. + + +#define AV_PROFILE_UNKNOWN -99 +#define AV_PROFILE_RESERVED -100 + +#define AV_PROFILE_AAC_MAIN 0 +#define AV_PROFILE_AAC_LOW 1 +#define AV_PROFILE_AAC_SSR 2 +#define AV_PROFILE_AAC_LTP 3 +#define AV_PROFILE_AAC_HE 4 +#define AV_PROFILE_AAC_HE_V2 28 +#define AV_PROFILE_AAC_LD 22 +#define AV_PROFILE_AAC_ELD 38 +#define AV_PROFILE_AAC_USAC 41 +#define AV_PROFILE_MPEG2_AAC_LOW 128 +#define AV_PROFILE_MPEG2_AAC_HE 131 + +#define AV_PROFILE_DNXHD 0 +#define AV_PROFILE_DNXHR_LB 1 +#define AV_PROFILE_DNXHR_SQ 2 +#define AV_PROFILE_DNXHR_HQ 3 +#define AV_PROFILE_DNXHR_HQX 4 +#define AV_PROFILE_DNXHR_444 5 + +#define AV_PROFILE_DTS 20 +#define AV_PROFILE_DTS_ES 30 +#define AV_PROFILE_DTS_96_24 40 +#define AV_PROFILE_DTS_HD_HRA 50 +#define AV_PROFILE_DTS_HD_MA 60 +#define AV_PROFILE_DTS_EXPRESS 70 +#define AV_PROFILE_DTS_HD_MA_X 61 +#define AV_PROFILE_DTS_HD_MA_X_IMAX 62 + +#define AV_PROFILE_EAC3_DDP_ATMOS 30 + +#define AV_PROFILE_TRUEHD_ATMOS 30 + +#define AV_PROFILE_MPEG2_422 0 +#define AV_PROFILE_MPEG2_HIGH 1 +#define AV_PROFILE_MPEG2_SS 2 +#define AV_PROFILE_MPEG2_SNR_SCALABLE 3 +#define AV_PROFILE_MPEG2_MAIN 4 +#define AV_PROFILE_MPEG2_SIMPLE 5 + +#define AV_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag +#define AV_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag + +#define AV_PROFILE_H264_BASELINE 66 +#define AV_PROFILE_H264_CONSTRAINED_BASELINE (66|AV_PROFILE_H264_CONSTRAINED) +#define AV_PROFILE_H264_MAIN 77 +#define AV_PROFILE_H264_EXTENDED 88 +#define AV_PROFILE_H264_HIGH 100 +#define AV_PROFILE_H264_HIGH_10 110 +#define AV_PROFILE_H264_HIGH_10_INTRA (110|AV_PROFILE_H264_INTRA) +#define AV_PROFILE_H264_MULTIVIEW_HIGH 118 +#define AV_PROFILE_H264_HIGH_422 122 +#define AV_PROFILE_H264_HIGH_422_INTRA (122|AV_PROFILE_H264_INTRA) +#define AV_PROFILE_H264_STEREO_HIGH 128 +#define AV_PROFILE_H264_HIGH_444 144 +#define AV_PROFILE_H264_HIGH_444_PREDICTIVE 244 +#define AV_PROFILE_H264_HIGH_444_INTRA (244|AV_PROFILE_H264_INTRA) +#define AV_PROFILE_H264_CAVLC_444 44 + +#define AV_PROFILE_VC1_SIMPLE 0 +#define AV_PROFILE_VC1_MAIN 1 +#define AV_PROFILE_VC1_COMPLEX 2 +#define AV_PROFILE_VC1_ADVANCED 3 + +#define AV_PROFILE_MPEG4_SIMPLE 0 +#define AV_PROFILE_MPEG4_SIMPLE_SCALABLE 1 +#define AV_PROFILE_MPEG4_CORE 2 +#define AV_PROFILE_MPEG4_MAIN 3 +#define AV_PROFILE_MPEG4_N_BIT 4 +#define AV_PROFILE_MPEG4_SCALABLE_TEXTURE 5 +#define AV_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6 +#define AV_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7 +#define AV_PROFILE_MPEG4_HYBRID 8 +#define AV_PROFILE_MPEG4_ADVANCED_REAL_TIME 9 +#define AV_PROFILE_MPEG4_CORE_SCALABLE 10 +#define AV_PROFILE_MPEG4_ADVANCED_CODING 11 +#define AV_PROFILE_MPEG4_ADVANCED_CORE 12 +#define AV_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13 +#define AV_PROFILE_MPEG4_SIMPLE_STUDIO 14 +#define AV_PROFILE_MPEG4_ADVANCED_SIMPLE 15 + +#define AV_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 1 +#define AV_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 2 +#define AV_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION 32768 +#define AV_PROFILE_JPEG2000_DCINEMA_2K 3 +#define AV_PROFILE_JPEG2000_DCINEMA_4K 4 + +#define AV_PROFILE_VP9_0 0 +#define AV_PROFILE_VP9_1 1 +#define AV_PROFILE_VP9_2 2 +#define AV_PROFILE_VP9_3 3 + +#define AV_PROFILE_HEVC_MAIN 1 +#define AV_PROFILE_HEVC_MAIN_10 2 +#define AV_PROFILE_HEVC_MAIN_STILL_PICTURE 3 +#define AV_PROFILE_HEVC_REXT 4 +#define AV_PROFILE_HEVC_MULTIVIEW_MAIN 6 +#define AV_PROFILE_HEVC_SCC 9 + +#define AV_PROFILE_VVC_MAIN_10 1 +#define AV_PROFILE_VVC_MAIN_10_444 33 + +#define AV_PROFILE_AV1_MAIN 0 +#define AV_PROFILE_AV1_HIGH 1 +#define AV_PROFILE_AV1_PROFESSIONAL 2 + +#define AV_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT 0xc0 +#define AV_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1 +#define AV_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT 0xc2 +#define AV_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3 +#define AV_PROFILE_MJPEG_JPEG_LS 0xf7 + +#define AV_PROFILE_SBC_MSBC 1 + +#define AV_PROFILE_PRORES_PROXY 0 +#define AV_PROFILE_PRORES_LT 1 +#define AV_PROFILE_PRORES_STANDARD 2 +#define AV_PROFILE_PRORES_HQ 3 +#define AV_PROFILE_PRORES_4444 4 +#define AV_PROFILE_PRORES_XQ 5 + +#define AV_PROFILE_PRORES_RAW 0 +#define AV_PROFILE_PRORES_RAW_HQ 1 + +#define AV_PROFILE_ARIB_PROFILE_A 0 +#define AV_PROFILE_ARIB_PROFILE_C 1 + +#define AV_PROFILE_KLVA_SYNC 0 +#define AV_PROFILE_KLVA_ASYNC 1 + +#define AV_PROFILE_EVC_BASELINE 0 +#define AV_PROFILE_EVC_MAIN 1 + +#define AV_PROFILE_APV_422_10 33 +#define AV_PROFILE_APV_422_12 44 +#define AV_PROFILE_APV_444_10 55 +#define AV_PROFILE_APV_444_12 66 +#define AV_PROFILE_APV_4444_10 77 +#define AV_PROFILE_APV_4444_12 88 +#define AV_PROFILE_APV_400_10 99 + + +#define AV_LEVEL_UNKNOWN -99 + +enum AVFieldOrder { + AV_FIELD_UNKNOWN, + AV_FIELD_PROGRESSIVE, + AV_FIELD_TT, ///< Top coded_first, top displayed first + AV_FIELD_BB, ///< Bottom coded first, bottom displayed first + AV_FIELD_TB, ///< Top coded first, bottom displayed first + AV_FIELD_BT, ///< Bottom coded first, top displayed first +}; + +/** + * @ingroup lavc_decoding + */ +enum AVDiscard{ + /* We leave some space between them for extensions (drop some + * keyframes for intra-only or drop just some bidir frames). */ + AVDISCARD_NONE =-16, ///< discard nothing + AVDISCARD_DEFAULT = 0, ///< discard useless packets like 0 size packets in avi + AVDISCARD_NONREF = 8, ///< discard all non reference + AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames + AVDISCARD_NONINTRA= 24, ///< discard all non intra frames + AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes + AVDISCARD_ALL = 48, ///< discard all +}; + +enum AVAudioServiceType { + AV_AUDIO_SERVICE_TYPE_MAIN = 0, + AV_AUDIO_SERVICE_TYPE_EFFECTS = 1, + AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED = 2, + AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED = 3, + AV_AUDIO_SERVICE_TYPE_DIALOGUE = 4, + AV_AUDIO_SERVICE_TYPE_COMMENTARY = 5, + AV_AUDIO_SERVICE_TYPE_EMERGENCY = 6, + AV_AUDIO_SERVICE_TYPE_VOICE_OVER = 7, + AV_AUDIO_SERVICE_TYPE_KARAOKE = 8, + AV_AUDIO_SERVICE_TYPE_NB , ///< Not part of ABI +}; + +/** + * Pan Scan area. + * This specifies the area which should be displayed. + * Note there may be multiple such areas for one frame. + */ +typedef struct AVPanScan { + /** + * id + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int id; + + /** + * width and height in 1/16 pel + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int width; + int height; + + /** + * position of the top left corner in 1/16 pel for up to 3 fields/frames + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int16_t position[3][2]; +} AVPanScan; + +/** + * This structure describes the bitrate properties of an encoded bitstream. It + * roughly corresponds to a subset the VBV parameters for MPEG-2 or HRD + * parameters for H.264/HEVC. + */ +typedef struct AVCPBProperties { + /** + * Maximum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int64_t max_bitrate; + /** + * Minimum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int64_t min_bitrate; + /** + * Average bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int64_t avg_bitrate; + + /** + * The size of the buffer to which the ratecontrol is applied, in bits. + * Zero if unknown or unspecified. + */ + int64_t buffer_size; + + /** + * The delay between the time the packet this structure is associated with + * is received and the time when it should be decoded, in periods of a 27MHz + * clock. + * + * UINT64_MAX when unknown or unspecified. + */ + uint64_t vbv_delay; +} AVCPBProperties; + +/** + * Allocate a CPB properties structure and initialize its fields to default + * values. + * + * @param size if non-NULL, the size of the allocated struct will be written + * here. This is useful for embedding it in side data. + * + * @return the newly allocated struct or NULL on failure + */ +AVCPBProperties *av_cpb_properties_alloc(size_t *size); + +/** + * This structure supplies correlation between a packet timestamp and a wall clock + * production time. The definition follows the Producer Reference Time ('prft') + * as defined in ISO/IEC 14496-12 + */ +typedef struct AVProducerReferenceTime { + /** + * A UTC timestamp, in microseconds, since Unix epoch (e.g, av_gettime()). + */ + int64_t wallclock; + int flags; +} AVProducerReferenceTime; + +/** + * RTCP SR (Sender Report) information + * + * The received sender report information for an RTSP + * stream, exposed as AV_PKT_DATA_RTCP_SR side data. + */ +typedef struct AVRTCPSenderReport { + uint32_t ssrc; ///< Synchronization source identifier + uint64_t ntp_timestamp; ///< NTP time when the report was sent + uint32_t rtp_timestamp; ///< RTP time when the report was sent + uint32_t sender_nb_packets; ///< Total number of packets sent + uint32_t sender_nb_bytes; ///< Total number of bytes sent (excluding headers or padding) +} AVRTCPSenderReport; + +/** + * Encode extradata length to a buffer. Used by xiph codecs. + * + * @param s buffer to write to; must be at least (v/255+1) bytes long + * @param v size of extradata in bytes + * @return number of bytes written to the buffer. + */ +unsigned int av_xiphlacing(unsigned char *s, unsigned int v); + +#endif // AVCODEC_DEFS_H diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/packet.h b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/packet.h new file mode 100644 index 0000000000000..55389a957d808 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/packet.h @@ -0,0 +1,907 @@ +/* + * AVPacket public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_PACKET_H +#define AVCODEC_PACKET_H + +#include +#include + +#include "libavutil/attributes.h" +#include "libavutil/buffer.h" +#include "libavutil/dict.h" +#include "libavutil/rational.h" +#include "libavutil/version.h" + +#include "libavcodec/version_major.h" + +/** + * @defgroup lavc_packet_side_data AVPacketSideData + * + * Types and functions for working with AVPacketSideData. + * @{ + */ +enum AVPacketSideDataType { + /** + * An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE + * bytes worth of palette. This side data signals that a new palette is + * present. + */ + AV_PKT_DATA_PALETTE, + + /** + * The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format + * that the extradata buffer was changed and the receiving side should + * act upon it appropriately. The new extradata is embedded in the side + * data buffer and should be immediately used for processing the current + * frame or packet. + */ + AV_PKT_DATA_NEW_EXTRADATA, + + /** + * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows: + * @code + * u32le param_flags + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) + * s32le sample_rate + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) + * s32le width + * s32le height + * @endcode + */ + AV_PKT_DATA_PARAM_CHANGE, + + /** + * An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of + * structures with info about macroblocks relevant to splitting the + * packet into smaller packets on macroblock edges (e.g. as for RFC 2190). + * That is, it does not necessarily contain info about all macroblocks, + * as long as the distance between macroblocks in the info is smaller + * than the target payload size. + * Each MB info structure is 12 bytes, and is laid out as follows: + * @code + * u32le bit offset from the start of the packet + * u8 current quantizer at the start of the macroblock + * u8 GOB number + * u16le macroblock address within the GOB + * u8 horizontal MV predictor + * u8 vertical MV predictor + * u8 horizontal MV predictor for block number 3 + * u8 vertical MV predictor for block number 3 + * @endcode + */ + AV_PKT_DATA_H263_MB_INFO, + + /** + * This side data should be associated with an audio stream and contains + * ReplayGain information in form of the AVReplayGain struct. + */ + AV_PKT_DATA_REPLAYGAIN, + + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the decoded video frames for + * correct presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_PKT_DATA_DISPLAYMATRIX, + + /** + * This side data should be associated with a video stream and contains + * Stereoscopic 3D information in form of the AVStereo3D struct. + */ + AV_PKT_DATA_STEREO3D, + + /** + * This side data should be associated with an audio stream and corresponds + * to enum AVAudioServiceType. + */ + AV_PKT_DATA_AUDIO_SERVICE_TYPE, + + /** + * This side data contains quality related information from the encoder. + * @code + * u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad). + * u8 picture type + * u8 error count + * u16 reserved + * u64le[error count] sum of squared differences between encoder in and output + * @endcode + */ + AV_PKT_DATA_QUALITY_STATS, + + /** + * This side data contains an integer value representing the stream index + * of a "fallback" track. A fallback track indicates an alternate + * track to use when the current track can not be decoded for some reason. + * e.g. no decoder available for codec. + */ + AV_PKT_DATA_FALLBACK_TRACK, + + /** + * This side data corresponds to the AVCPBProperties struct. + */ + AV_PKT_DATA_CPB_PROPERTIES, + + /** + * Recommends skipping the specified number of samples + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_PKT_DATA_SKIP_SAMPLES, + + /** + * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that + * the packet may contain "dual mono" audio specific to Japanese DTV + * and if it is true, recommends only the selected channel to be used. + * @code + * u8 selected channels (0=main/left, 1=sub/right, 2=both) + * @endcode + */ + AV_PKT_DATA_JP_DUALMONO, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. + */ + AV_PKT_DATA_STRINGS_METADATA, + + /** + * Subtitle event position + * @code + * u32le x1 + * u32le y1 + * u32le x2 + * u32le y2 + * @endcode + */ + AV_PKT_DATA_SUBTITLE_POSITION, + + /** + * Data found in BlockAdditional element of matroska container. There is + * no end marker for the data, so it is required to rely on the side data + * size to recognize the end. 8 byte id (as found in BlockAddId) followed + * by data. + */ + AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + + /** + * The optional first identifier line of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_IDENTIFIER, + + /** + * The optional settings (rendering instructions) that immediately + * follow the timestamp specifier of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_SETTINGS, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. This + * side data includes updated metadata which appeared in the stream. + */ + AV_PKT_DATA_METADATA_UPDATE, + + /** + * MPEGTS stream ID as uint8_t, this is required to pass the stream ID + * information from the demuxer to the corresponding muxer. + */ + AV_PKT_DATA_MPEGTS_STREAM_ID, + + /** + * Mastering display metadata (based on SMPTE-2086:2014). This metadata + * should be associated with a video stream and contains data in the form + * of the AVMasteringDisplayMetadata struct. + */ + AV_PKT_DATA_MASTERING_DISPLAY_METADATA, + + /** + * This side data should be associated with a video stream and corresponds + * to the AVSphericalMapping structure. + */ + AV_PKT_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This metadata should be + * associated with a video stream and contains data in the form of the + * AVContentLightMetadata struct. + */ + AV_PKT_DATA_CONTENT_LIGHT_LEVEL, + + /** + * ATSC A53 Part 4 Closed Captions. This metadata should be associated with + * a video stream. A53 CC bitstream is stored as uint8_t in AVPacketSideData.data. + * The number of bytes of CC data is AVPacketSideData.size. + */ + AV_PKT_DATA_A53_CC, + + /** + * This side data is encryption initialization data. + * The format is not part of ABI, use av_encryption_init_info_* methods to + * access. + */ + AV_PKT_DATA_ENCRYPTION_INIT_INFO, + + /** + * This side data contains encryption info for how to decrypt the packet. + * The format is not part of ABI, use av_encryption_info_* methods to access. + */ + AV_PKT_DATA_ENCRYPTION_INFO, + + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_PKT_DATA_AFD, + + /** + * Producer Reference Time data corresponding to the AVProducerReferenceTime struct, + * usually exported by some encoders (on demand through the prft flag set in the + * AVCodecContext export_side_data field). + */ + AV_PKT_DATA_PRFT, + + /** + * ICC profile data consisting of an opaque octet buffer following the + * format described by ISO 15076-1. + */ + AV_PKT_DATA_ICC_PROFILE, + + /** + * DOVI configuration + * ref: + * dolby-vision-bitstreams-within-the-iso-base-media-file-format-v2.1.2, section 2.2 + * dolby-vision-bitstreams-in-mpeg-2-transport-stream-multiplex-v1.2, section 3.3 + * Tags are stored in struct AVDOVIDecoderConfigurationRecord. + */ + AV_PKT_DATA_DOVI_CONF, + + /** + * Timecode which conforms to SMPTE ST 12-1:2014. The data is an array of 4 uint32_t + * where the first uint32_t describes how many (1-3) of the other timecodes are used. + * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.h. + */ + AV_PKT_DATA_S12M_TIMECODE, + + /** + * HDR10+ dynamic metadata associated with a video frame. The metadata is in + * the form of the AVDynamicHDRPlus struct and contains + * information for color volume transform - application 4 of + * SMPTE 2094-40:2016 standard. + */ + AV_PKT_DATA_DYNAMIC_HDR10_PLUS, + + /** + * IAMF Mix Gain Parameter Data associated with the audio frame. This metadata + * is in the form of the AVIAMFParamDefinition struct and contains information + * defined in sections 3.6.1 and 3.8.1 of the Immersive Audio Model and + * Formats standard. + */ + AV_PKT_DATA_IAMF_MIX_GAIN_PARAM, + + /** + * IAMF Demixing Info Parameter Data associated with the audio frame. This + * metadata is in the form of the AVIAMFParamDefinition struct and contains + * information defined in sections 3.6.1 and 3.8.2 of the Immersive Audio Model + * and Formats standard. + */ + AV_PKT_DATA_IAMF_DEMIXING_INFO_PARAM, + + /** + * IAMF Recon Gain Info Parameter Data associated with the audio frame. This + * metadata is in the form of the AVIAMFParamDefinition struct and contains + * information defined in sections 3.6.1 and 3.8.3 of the Immersive Audio Model + * and Formats standard. + */ + AV_PKT_DATA_IAMF_RECON_GAIN_INFO_PARAM, + + /** + * Ambient viewing environment metadata, as defined by H.274. This metadata + * should be associated with a video stream and contains data in the form + * of the AVAmbientViewingEnvironment struct. + */ + AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT, + + /** + * The number of pixels to discard from the top/bottom/left/right border of the + * decoded frame to obtain the sub-rectangle intended for presentation. + * + * @code + * u32le crop_top + * u32le crop_bottom + * u32le crop_left + * u32le crop_right + * @endcode + */ + AV_PKT_DATA_FRAME_CROPPING, + + /** + * Raw LCEVC payload data, as a uint8_t array, with NAL emulation + * bytes intact. + */ + AV_PKT_DATA_LCEVC, + + /** + * This side data contains information about the reference display width(s) + * and reference viewing distance(s) as well as information about the + * corresponding reference stereo pair(s), i.e., the pair(s) of views to be + * displayed for the viewer's left and right eyes on the reference display + * at the reference viewing distance. + * The payload is the AV3DReferenceDisplaysInfo struct defined in + * libavutil/tdrdi.h. + */ + AV_PKT_DATA_3D_REFERENCE_DISPLAYS, + + /** + * Contains the last received RTCP SR (Sender Report) information + * in the form of the AVRTCPSenderReport struct. + */ + AV_PKT_DATA_RTCP_SR, + + /** + * The number of side data types. + * This is not part of the public API/ABI in the sense that it may + * change when new side data types are added. + * This must stay the last enum value. + * If its value becomes huge, some code using it + * needs to be updated as it assumes it to be smaller than other limits. + */ + AV_PKT_DATA_NB +}; + +/** + * This structure stores auxiliary information for decoding, presenting, or + * otherwise processing the coded stream. It is typically exported by demuxers + * and encoders and can be fed to decoders and muxers either in a per packet + * basis, or as global side data (applying to the entire coded stream). + * + * Global side data is handled as follows: + * - During demuxing, it may be exported through + * @ref AVCodecParameters.coded_side_data "AVStream's codec parameters", which can + * then be passed as input to decoders through the + * @ref AVCodecContext.coded_side_data "decoder context's side data", for + * initialization. + * - For muxing, it can be fed through @ref AVCodecParameters.coded_side_data + * "AVStream's codec parameters", typically the output of encoders through + * the @ref AVCodecContext.coded_side_data "encoder context's side data", for + * initialization. + * + * Packet specific side data is handled as follows: + * - During demuxing, it may be exported through @ref AVPacket.side_data + * "AVPacket's side data", which can then be passed as input to decoders. + * - For muxing, it can be fed through @ref AVPacket.side_data "AVPacket's + * side data", typically the output of encoders. + * + * Different modules may accept or export different types of side data + * depending on media type and codec. Refer to @ref AVPacketSideDataType for a + * list of defined types and where they may be found or used. + */ +typedef struct AVPacketSideData { + uint8_t *data; + size_t size; + enum AVPacketSideDataType type; +} AVPacketSideData; + +/** + * Allocate a new packet side data. + * + * @param sd pointer to an array of side data to which the side data should + * be added. *sd may be NULL, in which case the array will be + * initialized. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. The integer value will be increased by 1 on success. + * @param type side data type + * @param size desired side data size + * @param flags currently unused. Must be zero + * + * @return pointer to freshly allocated side data on success, or NULL otherwise. + */ +AVPacketSideData *av_packet_side_data_new(AVPacketSideData **psd, int *pnb_sd, + enum AVPacketSideDataType type, + size_t size, int flags); + +/** + * Wrap existing data as packet side data. + * + * @param sd pointer to an array of side data to which the side data should + * be added. *sd may be NULL, in which case the array will be + * initialized + * @param nb_sd pointer to an integer containing the number of entries in + * the array. The integer value will be increased by 1 on success. + * @param type side data type + * @param data a data array. It must be allocated with the av_malloc() family + * of functions. The ownership of the data is transferred to the + * side data array on success + * @param size size of the data array + * @param flags currently unused. Must be zero + * + * @return pointer to freshly allocated side data on success, or NULL otherwise + * On failure, the side data array is unchanged and the data remains + * owned by the caller. + */ +AVPacketSideData *av_packet_side_data_add(AVPacketSideData **sd, int *nb_sd, + enum AVPacketSideDataType type, + void *data, size_t size, int flags); + +/** + * Get side information from a side data array. + * + * @param sd the array from which the side data should be fetched + * @param nb_sd value containing the number of entries in the array. + * @param type desired side information type + * + * @return pointer to side data if present or NULL otherwise + */ +const AVPacketSideData *av_packet_side_data_get(const AVPacketSideData *sd, + int nb_sd, + enum AVPacketSideDataType type); + +/** + * Remove side data of the given type from a side data array. + * + * @param sd the array from which the side data should be removed + * @param nb_sd pointer to an integer containing the number of entries in + * the array. Will be reduced by the amount of entries removed + * upon return + * @param type side information type + */ +void av_packet_side_data_remove(AVPacketSideData *sd, int *nb_sd, + enum AVPacketSideDataType type); + +/** + * Convenience function to free all the side data stored in an array, and + * the array itself. + * + * @param sd pointer to array of side data to free. Will be set to NULL + * upon return. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. Will be set to 0 upon return. + */ +void av_packet_side_data_free(AVPacketSideData **sd, int *nb_sd); + +const char *av_packet_side_data_name(enum AVPacketSideDataType type); + +/** + * @} + */ + +/** + * @defgroup lavc_packet AVPacket + * + * Types and functions for working with AVPacket. + * @{ + */ + +/** + * This structure stores compressed data. It is typically exported by demuxers + * and then passed as input to decoders, or received as output from encoders and + * then passed to muxers. + * + * For video, it should typically contain one compressed frame. For audio it may + * contain several compressed frames. Encoders are allowed to output empty + * packets, with no compressed data, containing only side data + * (e.g. to update some stream parameters at the end of encoding). + * + * The semantics of data ownership depends on the buf field. + * If it is set, the packet data is dynamically allocated and is + * valid indefinitely until a call to av_packet_unref() reduces the + * reference count to 0. + * + * If the buf field is not set av_packet_ref() would make a copy instead + * of increasing the reference count. + * + * The side data is always allocated with av_malloc(), copied by + * av_packet_ref() and freed by av_packet_unref(). + * + * sizeof(AVPacket) being a part of the public ABI is deprecated. once + * av_init_packet() is removed, new packets will only be able to be allocated + * with av_packet_alloc(), and new fields may be added to the end of the struct + * with a minor bump. + * + * @see av_packet_alloc + * @see av_packet_ref + * @see av_packet_unref + */ +typedef struct AVPacket { + /** + * A reference to the reference-counted buffer where the packet data is + * stored. + * May be NULL, then the packet data is not reference-counted. + */ + AVBufferRef *buf; + /** + * Presentation timestamp in AVStream->time_base units; the time at which + * the decompressed packet will be presented to the user. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + * pts MUST be larger or equal to dts as presentation cannot happen before + * decompression, unless one wants to view hex dumps. Some formats misuse + * the terms dts and pts/cts to mean something different. Such timestamps + * must be converted to true pts/dts before they are stored in AVPacket. + */ + int64_t pts; + /** + * Decompression timestamp in AVStream->time_base units; the time at which + * the packet is decompressed. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + */ + int64_t dts; + uint8_t *data; + int size; + int stream_index; + /** + * A combination of AV_PKT_FLAG values + */ + int flags; + /** + * Additional packet data that can be provided by the container. + * Packet can contain several types of side information. + */ + AVPacketSideData *side_data; + int side_data_elems; + + /** + * Duration of this packet in AVStream->time_base units, 0 if unknown. + * Equals next_pts - this_pts in presentation order. + */ + int64_t duration; + + int64_t pos; ///< byte position in stream, -1 if unknown + + /** + * for some private data of the user + */ + void *opaque; + + /** + * AVBufferRef for free use by the API user. FFmpeg will never check the + * contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when + * the packet is unreferenced. av_packet_copy_props() calls create a new + * reference with av_buffer_ref() for the target packet's opaque_ref field. + * + * This is unrelated to the opaque field, although it serves a similar + * purpose. + */ + AVBufferRef *opaque_ref; + + /** + * Time base of the packet's timestamps. + * In the future, this field may be set on packets output by encoders or + * demuxers, but its value will be by default ignored on input to decoders + * or muxers. + */ + AVRational time_base; +} AVPacket; + +#if FF_API_INIT_PACKET +attribute_deprecated +typedef struct AVPacketList { + AVPacket pkt; + struct AVPacketList *next; +} AVPacketList; +#endif + +#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe +#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted +/** + * Flag is used to discard packets which are required to maintain valid + * decoder state but are not required for output and should be dropped + * after decoding. + **/ +#define AV_PKT_FLAG_DISCARD 0x0004 +/** + * The packet comes from a trusted source. + * + * Otherwise-unsafe constructs such as arbitrary pointers to data + * outside the packet may be followed. + */ +#define AV_PKT_FLAG_TRUSTED 0x0008 +/** + * Flag is used to indicate packets that contain frames that can + * be discarded by the decoder. I.e. Non-reference frames. + */ +#define AV_PKT_FLAG_DISPOSABLE 0x0010 + +enum AVSideDataParamChangeFlags { + AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004, + AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008, +}; + +/** + * Allocate an AVPacket and set its fields to default values. The resulting + * struct must be freed using av_packet_free(). + * + * @return An AVPacket filled with default values or NULL on failure. + * + * @note this only allocates the AVPacket itself, not the data buffers. Those + * must be allocated through other means such as av_new_packet. + * + * @see av_new_packet + */ +AVPacket *av_packet_alloc(void); + +/** + * Create a new packet that references the same data as src. + * + * This is a shortcut for av_packet_alloc()+av_packet_ref(). + * + * @return newly created AVPacket on success, NULL on error. + * + * @see av_packet_alloc + * @see av_packet_ref + */ +AVPacket *av_packet_clone(const AVPacket *src); + +/** + * Free the packet, if the packet is reference counted, it will be + * unreferenced first. + * + * @param pkt packet to be freed. The pointer will be set to NULL. + * @note passing NULL is a no-op. + */ +void av_packet_free(AVPacket **pkt); + +#if FF_API_INIT_PACKET +/** + * Initialize optional fields of a packet with default values. + * + * Note, this does not touch the data and size members, which have to be + * initialized separately. + * + * @param pkt packet + * + * @see av_packet_alloc + * @see av_packet_unref + * + * @deprecated This function is deprecated. Once it's removed, + sizeof(AVPacket) will not be a part of the ABI anymore. + */ +attribute_deprecated +void av_init_packet(AVPacket *pkt); +#endif + +/** + * Allocate the payload of a packet and initialize its fields with + * default values. + * + * @param pkt packet + * @param size wanted payload size + * @return 0 if OK, AVERROR_xxx otherwise + */ +int av_new_packet(AVPacket *pkt, int size); + +/** + * Reduce packet size, correctly zeroing padding + * + * @param pkt packet + * @param size new size + */ +void av_shrink_packet(AVPacket *pkt, int size); + +/** + * Increase packet size, correctly zeroing padding + * + * @param pkt packet + * @param grow_by number of bytes by which to increase the size of the packet + */ +int av_grow_packet(AVPacket *pkt, int grow_by); + +/** + * Initialize a reference-counted packet from av_malloc()ed data. + * + * @param pkt packet to be initialized. This function will set the data, size, + * and buf fields, all others are left untouched. + * @param data Data allocated by av_malloc() to be used as packet data. If this + * function returns successfully, the data is owned by the underlying AVBuffer. + * The caller may not access the data through other means. + * @param size size of data in bytes, without the padding. I.e. the full buffer + * size is assumed to be size + AV_INPUT_BUFFER_PADDING_SIZE. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size); + +/** + * Allocate new information of a packet. + * + * @param pkt packet + * @param type side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + size_t size); + +/** + * Wrap an existing array as a packet side data. + * + * @param pkt packet + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * pkt. + * @param size side information size + * @return a non-negative number on success, a negative AVERROR code on + * failure. On failure, the packet is unchanged and the data remains + * owned by the caller. + */ +int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + +/** + * Shrink the already allocated side data buffer + * + * @param pkt packet + * @param type side information type + * @param size new side information size + * @return 0 on success, < 0 on failure + */ +int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + size_t size); + +/** + * Get side information from packet. + * + * @param pkt packet + * @param type desired side information type + * @param size If supplied, *size will be set to the size of the side data + * or to zero if the desired side data is not present. + * @return pointer to data if present or NULL otherwise + */ +uint8_t* av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, + size_t *size); + +/** + * Pack a dictionary for use in side_data. + * + * @param dict The dictionary to pack. + * @param size pointer to store the size of the returned data + * @return pointer to data if successful, NULL otherwise + */ +uint8_t *av_packet_pack_dictionary(AVDictionary *dict, size_t *size); +/** + * Unpack a dictionary from side_data. + * + * @param data data from side_data + * @param size size of the data + * @param dict the metadata storage dictionary + * @return 0 on success, < 0 on failure + */ +int av_packet_unpack_dictionary(const uint8_t *data, size_t size, + AVDictionary **dict); + +/** + * Convenience function to free all the side data stored. + * All the other fields stay untouched. + * + * @param pkt packet + */ +void av_packet_free_side_data(AVPacket *pkt); + +/** + * Setup a new reference to the data described by a given packet + * + * If src is reference-counted, setup dst as a new reference to the + * buffer in src. Otherwise allocate a new buffer in dst and copy the + * data from src into it. + * + * All the other fields are copied from src. + * + * @see av_packet_unref + * + * @param dst Destination packet. Will be completely overwritten. + * @param src Source packet + * + * @return 0 on success, a negative AVERROR on error. On error, dst + * will be blank (as if returned by av_packet_alloc()). + */ +int av_packet_ref(AVPacket *dst, const AVPacket *src); + +/** + * Wipe the packet. + * + * Unreference the buffer referenced by the packet and reset the + * remaining packet fields to their default values. + * + * @param pkt The packet to be unreferenced. + */ +void av_packet_unref(AVPacket *pkt); + +/** + * Move every field in src to dst and reset src. + * + * @see av_packet_unref + * + * @param src Source packet, will be reset + * @param dst Destination packet + */ +void av_packet_move_ref(AVPacket *dst, AVPacket *src); + +/** + * Copy only "properties" fields from src to dst. + * + * Properties for the purpose of this function are all the fields + * beside those related to the packet data (buf, data, size) + * + * @param dst Destination packet + * @param src Source packet + * + * @return 0 on success AVERROR on failure. + */ +int av_packet_copy_props(AVPacket *dst, const AVPacket *src); + +/** + * Ensure the data described by a given packet is reference counted. + * + * @note This function does not ensure that the reference will be writable. + * Use av_packet_make_writable instead for that purpose. + * + * @see av_packet_ref + * @see av_packet_make_writable + * + * @param pkt packet whose data should be made reference counted. + * + * @return 0 on success, a negative AVERROR on error. On failure, the + * packet is unchanged. + */ +int av_packet_make_refcounted(AVPacket *pkt); + +/** + * Create a writable reference for the data described by a given packet, + * avoiding data copy if possible. + * + * @param pkt Packet whose data should be made writable. + * + * @return 0 on success, a negative AVERROR on failure. On failure, the + * packet is unchanged. + */ +int av_packet_make_writable(AVPacket *pkt); + +/** + * Convert valid timing fields (timestamps / durations) in a packet from one + * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be + * ignored. + * + * @param pkt packet on which the conversion will be performed + * @param tb_src source timebase, in which the timing fields in pkt are + * expressed + * @param tb_dst destination timebase, to which the timing fields will be + * converted + */ +void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst); + +/** + * Allocate an AVContainerFifo instance for AVPacket. + * + * @param flags currently unused + */ +struct AVContainerFifo *av_container_fifo_alloc_avpacket(unsigned flags); + +/** + * @} + */ + +#endif // AVCODEC_PACKET_H diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/version.h b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/version.h new file mode 100644 index 0000000000000..8b53586be1d4e --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/version.h @@ -0,0 +1,45 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VERSION_H +#define AVCODEC_VERSION_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBAVCODEC_VERSION_MINOR 11 +#define LIBAVCODEC_VERSION_MICRO 100 + +#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT + +#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) + +#endif /* AVCODEC_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/version_major.h b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/version_major.h new file mode 100644 index 0000000000000..97e4e12065c45 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavcodec/version_major.h @@ -0,0 +1,55 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VERSION_MAJOR_H +#define AVCODEC_VERSION_MAJOR_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#define LIBAVCODEC_VERSION_MAJOR 62 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + */ + +#define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 63) + +#define FF_API_V408_CODECID (LIBAVCODEC_VERSION_MAJOR < 63) +#define FF_API_CODEC_PROPS (LIBAVCODEC_VERSION_MAJOR < 63) +#define FF_API_EXR_GAMMA (LIBAVCODEC_VERSION_MAJOR < 63) + +#define FF_API_NVDEC_OLD_PIX_FMTS (LIBAVCODEC_VERSION_MAJOR < 63) + +// reminder to remove the OMX encoder on next major bump +#define FF_CODEC_OMX (LIBAVCODEC_VERSION_MAJOR < 63) +// reminder to remove Sonic Lossy/Lossless encoders on next major bump +#define FF_CODEC_SONIC_ENC (LIBAVCODEC_VERSION_MAJOR < 63) +// reminder to remove Sonic decoder on next-next major bump +#define FF_CODEC_SONIC_DEC (LIBAVCODEC_VERSION_MAJOR < 63) + +#endif /* AVCODEC_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavformat/avformat.h b/src/framework/media/thirdparty/ffmpeg/v8/libavformat/avformat.h new file mode 100644 index 0000000000000..be6e532387a43 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavformat/avformat.h @@ -0,0 +1,3004 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_AVFORMAT_H +#define AVFORMAT_AVFORMAT_H + +/** + * @file + * @ingroup libavf + * Main libavformat public API header + */ + +/** + * @defgroup libavf libavformat + * I/O and Muxing/Demuxing Library + * + * Libavformat (lavf) is a library for dealing with various media container + * formats. Its main two purposes are demuxing - i.e. splitting a media file + * into component streams, and the reverse process of muxing - writing supplied + * data in a specified container format. It also has an @ref lavf_io + * "I/O module" which supports a number of protocols for accessing the data (e.g. + * file, tcp, http and others). + * Unless you are absolutely sure you won't use libavformat's network + * capabilities, you should also call avformat_network_init(). + * + * A supported input format is described by an AVInputFormat struct, conversely + * an output format is described by AVOutputFormat. You can iterate over all + * input/output formats using the av_demuxer_iterate / av_muxer_iterate() functions. + * The protocols layer is not part of the public API, so you can only get the names + * of supported protocols with the avio_enum_protocols() function. + * + * Main lavf structure used for both muxing and demuxing is AVFormatContext, + * which exports all information about the file being read or written. As with + * most Libavformat structures, its size is not part of public ABI, so it cannot be + * allocated on stack or directly with av_malloc(). To create an + * AVFormatContext, use avformat_alloc_context() (some functions, like + * avformat_open_input() might do that for you). + * + * Most importantly an AVFormatContext contains: + * @li the @ref AVFormatContext.iformat "input" or @ref AVFormatContext.oformat + * "output" format. It is either autodetected or set by user for input; + * always set by user for output. + * @li an @ref AVFormatContext.streams "array" of AVStreams, which describe all + * elementary streams stored in the file. AVStreams are typically referred to + * using their index in this array. + * @li an @ref AVFormatContext.pb "I/O context". It is either opened by lavf or + * set by user for input, always set by user for output (unless you are dealing + * with an AVFMT_NOFILE format). + * + * @section lavf_options Passing options to (de)muxers + * It is possible to configure lavf muxers and demuxers using the @ref avoptions + * mechanism. Generic (format-independent) libavformat options are provided by + * AVFormatContext, they can be examined from a user program by calling + * av_opt_next() / av_opt_find() on an allocated AVFormatContext (or its AVClass + * from avformat_get_class()). Private (format-specific) options are provided by + * AVFormatContext.priv_data if and only if AVInputFormat.priv_class / + * AVOutputFormat.priv_class of the corresponding format struct is non-NULL. + * Further options may be provided by the @ref AVFormatContext.pb "I/O context", + * if its AVClass is non-NULL, and the protocols layer. See the discussion on + * nesting in @ref avoptions documentation to learn how to access those. + * + * @section urls + * URL strings in libavformat are made of a scheme/protocol, a ':', and a + * scheme specific string. URLs without a scheme and ':' used for local files + * are supported but deprecated. "file:" should be used for local files. + * + * It is important that the scheme string is not taken from untrusted + * sources without checks. + * + * Note that some schemes/protocols are quite powerful, allowing access to + * both local and remote files, parts of them, concatenations of them, local + * audio and video devices and so on. + * + * @{ + * + * @defgroup lavf_decoding Demuxing + * @{ + * Demuxers read a media file and split it into chunks of data (@em packets). A + * @ref AVPacket "packet" contains one or more encoded frames which belongs to a + * single elementary stream. In the lavf API this process is represented by the + * avformat_open_input() function for opening a file, av_read_frame() for + * reading a single packet and finally avformat_close_input(), which does the + * cleanup. + * + * @section lavf_decoding_open Opening a media file + * The minimum information required to open a file is its URL, which + * is passed to avformat_open_input(), as in the following code: + * @code + * const char *url = "file:in.mp3"; + * AVFormatContext *s = NULL; + * int ret = avformat_open_input(&s, url, NULL, NULL); + * if (ret < 0) + * abort(); + * @endcode + * The above code attempts to allocate an AVFormatContext, open the + * specified file (autodetecting the format) and read the header, exporting the + * information stored there into s. Some formats do not have a header or do not + * store enough information there, so it is recommended that you call the + * avformat_find_stream_info() function which tries to read and decode a few + * frames to find missing information. + * + * In some cases you might want to preallocate an AVFormatContext yourself with + * avformat_alloc_context() and do some tweaking on it before passing it to + * avformat_open_input(). One such case is when you want to use custom functions + * for reading input data instead of lavf internal I/O layer. + * To do that, create your own AVIOContext with avio_alloc_context(), passing + * your reading callbacks to it. Then set the @em pb field of your + * AVFormatContext to newly created AVIOContext. + * + * Since the format of the opened file is in general not known until after + * avformat_open_input() has returned, it is not possible to set demuxer private + * options on a preallocated context. Instead, the options should be passed to + * avformat_open_input() wrapped in an AVDictionary: + * @code + * AVDictionary *options = NULL; + * av_dict_set(&options, "video_size", "640x480", 0); + * av_dict_set(&options, "pixel_format", "rgb24", 0); + * + * if (avformat_open_input(&s, url, NULL, &options) < 0) + * abort(); + * av_dict_free(&options); + * @endcode + * This code passes the private options 'video_size' and 'pixel_format' to the + * demuxer. They would be necessary for e.g. the rawvideo demuxer, since it + * cannot know how to interpret raw video data otherwise. If the format turns + * out to be something different than raw video, those options will not be + * recognized by the demuxer and therefore will not be applied. Such unrecognized + * options are then returned in the options dictionary (recognized options are + * consumed). The calling program can handle such unrecognized options as it + * wishes, e.g. + * @code + * const AVDictionaryEntry *e; + * if ((e = av_dict_iterate(options, NULL))) { + * fprintf(stderr, "Option %s not recognized by the demuxer.\n", e->key); + * abort(); + * } + * @endcode + * + * After you have finished reading the file, you must close it with + * avformat_close_input(). It will free everything associated with the file. + * + * @section lavf_decoding_read Reading from an opened file + * Reading data from an opened AVFormatContext is done by repeatedly calling + * av_read_frame() on it. Each call, if successful, will return an AVPacket + * containing encoded data for one AVStream, identified by + * AVPacket.stream_index. This packet may be passed straight into the libavcodec + * decoding functions avcodec_send_packet() or avcodec_decode_subtitle2() if the + * caller wishes to decode the data. + * + * AVPacket.pts, AVPacket.dts and AVPacket.duration timing information will be + * set if known. They may also be unset (i.e. AV_NOPTS_VALUE for + * pts/dts, 0 for duration) if the stream does not provide them. The timing + * information will be in AVStream.time_base units, i.e. it has to be + * multiplied by the timebase to convert them to seconds. + * + * A packet returned by av_read_frame() is always reference-counted, + * i.e. AVPacket.buf is set and the user may keep it indefinitely. + * The packet must be freed with av_packet_unref() when it is no + * longer needed. + * + * @section lavf_decoding_seek Seeking + * @} + * + * @defgroup lavf_encoding Muxing + * @{ + * Muxers take encoded data in the form of @ref AVPacket "AVPackets" and write + * it into files or other output bytestreams in the specified container format. + * + * The main API functions for muxing are avformat_write_header() for writing the + * file header, av_write_frame() / av_interleaved_write_frame() for writing the + * packets and av_write_trailer() for finalizing the file. + * + * At the beginning of the muxing process, the caller must first call + * avformat_alloc_context() to create a muxing context. The caller then sets up + * the muxer by filling the various fields in this context: + * + * - The @ref AVFormatContext.oformat "oformat" field must be set to select the + * muxer that will be used. + * - Unless the format is of the AVFMT_NOFILE type, the @ref AVFormatContext.pb + * "pb" field must be set to an opened IO context, either returned from + * avio_open2() or a custom one. + * - Unless the format is of the AVFMT_NOSTREAMS type, at least one stream must + * be created with the avformat_new_stream() function. The caller should fill + * the @ref AVStream.codecpar "stream codec parameters" information, such as the + * codec @ref AVCodecParameters.codec_type "type", @ref AVCodecParameters.codec_id + * "id" and other parameters (e.g. width / height, the pixel or sample format, + * etc.) as known. The @ref AVStream.time_base "stream timebase" should + * be set to the timebase that the caller desires to use for this stream (note + * that the timebase actually used by the muxer can be different, as will be + * described later). + * - It is advised to manually initialize only the relevant fields in + * AVCodecParameters, rather than using @ref avcodec_parameters_copy() during + * remuxing: there is no guarantee that the codec context values remain valid + * for both input and output format contexts. + * - The caller may fill in additional information, such as @ref + * AVFormatContext.metadata "global" or @ref AVStream.metadata "per-stream" + * metadata, @ref AVFormatContext.chapters "chapters", @ref + * AVFormatContext.programs "programs", etc. as described in the + * AVFormatContext documentation. Whether such information will actually be + * stored in the output depends on what the container format and the muxer + * support. + * + * When the muxing context is fully set up, the caller must call + * avformat_write_header() to initialize the muxer internals and write the file + * header. Whether anything actually is written to the IO context at this step + * depends on the muxer, but this function must always be called. Any muxer + * private options must be passed in the options parameter to this function. + * + * The data is then sent to the muxer by repeatedly calling av_write_frame() or + * av_interleaved_write_frame() (consult those functions' documentation for + * discussion on the difference between them; only one of them may be used with + * a single muxing context, they should not be mixed). Do note that the timing + * information on the packets sent to the muxer must be in the corresponding + * AVStream's timebase. That timebase is set by the muxer (in the + * avformat_write_header() step) and may be different from the timebase + * requested by the caller. + * + * Once all the data has been written, the caller must call av_write_trailer() + * to flush any buffered packets and finalize the output file, then close the IO + * context (if any) and finally free the muxing context with + * avformat_free_context(). + * @} + * + * @defgroup lavf_io I/O Read/Write + * @{ + * @section lavf_io_dirlist Directory listing + * The directory listing API makes it possible to list files on remote servers. + * + * Some of possible use cases: + * - an "open file" dialog to choose files from a remote location, + * - a recursive media finder providing a player with an ability to play all + * files from a given directory. + * + * @subsection lavf_io_dirlist_open Opening a directory + * At first, a directory needs to be opened by calling avio_open_dir() + * supplied with a URL and, optionally, ::AVDictionary containing + * protocol-specific parameters. The function returns zero or positive + * integer and allocates AVIODirContext on success. + * + * @code + * AVIODirContext *ctx = NULL; + * if (avio_open_dir(&ctx, "smb://example.com/some_dir", NULL) < 0) { + * fprintf(stderr, "Cannot open directory.\n"); + * abort(); + * } + * @endcode + * + * This code tries to open a sample directory using smb protocol without + * any additional parameters. + * + * @subsection lavf_io_dirlist_read Reading entries + * Each directory's entry (i.e. file, another directory, anything else + * within ::AVIODirEntryType) is represented by AVIODirEntry. + * Reading consecutive entries from an opened AVIODirContext is done by + * repeatedly calling avio_read_dir() on it. Each call returns zero or + * positive integer if successful. Reading can be stopped right after the + * NULL entry has been read -- it means there are no entries left to be + * read. The following code reads all entries from a directory associated + * with ctx and prints their names to standard output. + * @code + * AVIODirEntry *entry = NULL; + * for (;;) { + * if (avio_read_dir(ctx, &entry) < 0) { + * fprintf(stderr, "Cannot list directory.\n"); + * abort(); + * } + * if (!entry) + * break; + * printf("%s\n", entry->name); + * avio_free_directory_entry(&entry); + * } + * @endcode + * @} + * + * @defgroup lavf_codec Demuxers + * @{ + * @defgroup lavf_codec_native Native Demuxers + * @{ + * @} + * @defgroup lavf_codec_wrappers External library wrappers + * @{ + * @} + * @} + * @defgroup lavf_protos I/O Protocols + * @{ + * @} + * @defgroup lavf_internal Internal + * @{ + * @} + * @} + */ + +#include /* FILE */ + +#include "libavcodec/codec_par.h" +#include "libavcodec/defs.h" +#include "libavcodec/packet.h" + +#include "libavutil/dict.h" +#include "libavutil/log.h" + +#include "avio.h" +#include "libavformat/version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "libavformat/version.h" + +#include "libavutil/frame.h" +#include "libavcodec/codec.h" +#endif + +struct AVFormatContext; +struct AVFrame; + +/** + * @defgroup metadata_api Public Metadata API + * @{ + * @ingroup libavf + * The metadata API allows libavformat to export metadata tags to a client + * application when demuxing. Conversely it allows a client application to + * set metadata when muxing. + * + * Metadata is exported or set as pairs of key/value strings in the 'metadata' + * fields of the AVFormatContext, AVStream, AVChapter and AVProgram structs + * using the @ref lavu_dict "AVDictionary" API. Like all strings in FFmpeg, + * metadata is assumed to be UTF-8 encoded Unicode. Note that metadata + * exported by demuxers isn't checked to be valid UTF-8 in most cases. + * + * Important concepts to keep in mind: + * - Keys are unique; there can never be 2 tags with the same key. This is + * also meant semantically, i.e., a demuxer should not knowingly produce + * several keys that are literally different but semantically identical. + * E.g., key=Author5, key=Author6. In this example, all authors must be + * placed in the same tag. + * - Metadata is flat, not hierarchical; there are no subtags. If you + * want to store, e.g., the email address of the child of producer Alice + * and actor Bob, that could have key=alice_and_bobs_childs_email_address. + * - Several modifiers can be applied to the tag name. This is done by + * appending a dash character ('-') and the modifier name in the order + * they appear in the list below -- e.g. foo-eng-sort, not foo-sort-eng. + * - language -- a tag whose value is localized for a particular language + * is appended with the ISO 639-2/B 3-letter language code. + * For example: Author-ger=Michael, Author-eng=Mike + * The original/default language is in the unqualified "Author" tag. + * A demuxer should set a default if it sets any translated tag. + * - sorting -- a modified version of a tag that should be used for + * sorting will have '-sort' appended. E.g. artist="The Beatles", + * artist-sort="Beatles, The". + * - Some protocols and demuxers support metadata updates. After a successful + * call to av_read_frame(), AVFormatContext.event_flags or AVStream.event_flags + * will be updated to indicate if metadata changed. In order to detect metadata + * changes on a stream, you need to loop through all streams in the AVFormatContext + * and check their individual event_flags. + * + * - Demuxers attempt to export metadata in a generic format, however tags + * with no generic equivalents are left as they are stored in the container. + * Follows a list of generic tag names: + * + @verbatim + album -- name of the set this work belongs to + album_artist -- main creator of the set/album, if different from artist. + e.g. "Various Artists" for compilation albums. + artist -- main creator of the work + comment -- any additional description of the file. + composer -- who composed the work, if different from artist. + copyright -- name of copyright holder. + creation_time-- date when the file was created, preferably in ISO 8601. + date -- date when the work was created, preferably in ISO 8601. + disc -- number of a subset, e.g. disc in a multi-disc collection. + encoder -- name/settings of the software/hardware that produced the file. + encoded_by -- person/group who created the file. + filename -- original name of the file. + genre -- . + language -- main language in which the work is performed, preferably + in ISO 639-2 format. Multiple languages can be specified by + separating them with commas. + performer -- artist who performed the work, if different from artist. + E.g for "Also sprach Zarathustra", artist would be "Richard + Strauss" and performer "London Philharmonic Orchestra". + publisher -- name of the label/publisher. + service_name -- name of the service in broadcasting (channel name). + service_provider -- name of the service provider in broadcasting. + title -- name of the work. + track -- number of this work in the set, can be in form current/total. + variant_bitrate -- the total bitrate of the bitrate variant that the current stream is part of + @endverbatim + * + * Look in the examples section for an application example how to use the Metadata API. + * + * @} + */ + +/* packet functions */ + + +/** + * Allocate and read the payload of a packet and initialize its + * fields with default values. + * + * @param s associated IO context + * @param pkt packet + * @param size desired payload size + * @return >0 (read size) if OK, AVERROR_xxx otherwise + */ +int av_get_packet(AVIOContext *s, AVPacket *pkt, int size); + + +/** + * Read data and append it to the current content of the AVPacket. + * If pkt->size is 0 this is identical to av_get_packet. + * Note that this uses av_grow_packet and thus involves a realloc + * which is inefficient. Thus this function should only be used + * when there is no reasonable way to know (an upper bound of) + * the final size. + * + * @param s associated IO context + * @param pkt packet + * @param size amount of data to read + * @return >0 (read size) if OK, AVERROR_xxx otherwise, previous data + * will not be lost even if an error occurs. + */ +int av_append_packet(AVIOContext *s, AVPacket *pkt, int size); + +/*************************************************/ +/* input/output formats */ + +struct AVCodecTag; + +/** + * This structure contains the data a format has to probe a file. + */ +typedef struct AVProbeData { + const char *filename; + unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */ + int buf_size; /**< Size of buf except extra allocated bytes */ + const char *mime_type; /**< mime_type, when known. */ +} AVProbeData; + +#define AVPROBE_SCORE_RETRY (AVPROBE_SCORE_MAX/4) +#define AVPROBE_SCORE_STREAM_RETRY (AVPROBE_SCORE_MAX/4-1) + +#define AVPROBE_SCORE_EXTENSION 50 ///< score for file extension +#define AVPROBE_SCORE_MIME_BONUS 30 ///< score added for matching mime type +#define AVPROBE_SCORE_MAX 100 ///< maximum score + +#define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer + +/// Demuxer will use avio_open, no opened file should be provided by the caller. +#define AVFMT_NOFILE 0x0001 +#define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */ +/** + * The muxer/demuxer is experimental and should be used with caution. + * + * It will not be selected automatically, and must be specified explicitly. + */ +#define AVFMT_EXPERIMENTAL 0x0004 +#define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */ +#define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */ +#define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */ +#define AVFMT_GENERIC_INDEX 0x0100 /**< Use generic index building code. */ +#define AVFMT_TS_DISCONT 0x0200 /**< Format allows timestamp discontinuities. Note, muxers always require valid (monotone) timestamps */ +#define AVFMT_VARIABLE_FPS 0x0400 /**< Format allows variable fps. */ +#define AVFMT_NODIMENSIONS 0x0800 /**< Format does not need width/height */ +#define AVFMT_NOSTREAMS 0x1000 /**< Format does not require any streams */ +#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fall back on binary search via read_timestamp */ +#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fall back on generic search */ +#define AVFMT_NO_BYTE_SEEK 0x8000 /**< Format does not allow seeking by bytes */ +#define AVFMT_TS_NONSTRICT 0x20000 /**< Format does not require strictly + increasing timestamps, but they must + still be monotonic */ +#define AVFMT_TS_NEGATIVE 0x40000 /**< Format allows muxing negative + timestamps. If not set the timestamp + will be shifted in av_write_frame and + av_interleaved_write_frame so they + start from 0. + The user or muxer can override this through + AVFormatContext.avoid_negative_ts + */ + +#define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */ + +/** + * @addtogroup lavf_encoding + * @{ + */ +typedef struct AVOutputFormat { + const char *name; + /** + * Descriptive name for the format, meant to be more human-readable + * than name. You should use the NULL_IF_CONFIG_SMALL() macro + * to define it. + */ + const char *long_name; + const char *mime_type; + const char *extensions; /**< comma-separated filename extensions */ + /* output support */ + enum AVCodecID audio_codec; /**< default audio codec */ + enum AVCodecID video_codec; /**< default video codec */ + enum AVCodecID subtitle_codec; /**< default subtitle codec */ + /** + * can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, + * AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, + * AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, + * AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE + */ + int flags; + + /** + * List of supported codec_id-codec_tag pairs, ordered by "better + * choice first". The arrays are all terminated by AV_CODEC_ID_NONE. + */ + const struct AVCodecTag * const *codec_tag; + + + const AVClass *priv_class; ///< AVClass for the private context +} AVOutputFormat; +/** + * @} + */ + +/** + * @addtogroup lavf_decoding + * @{ + */ +typedef struct AVInputFormat { + /** + * A comma separated list of short names for the format. New names + * may be appended with a minor bump. + */ + const char *name; + + /** + * Descriptive name for the format, meant to be more human-readable + * than name. You should use the NULL_IF_CONFIG_SMALL() macro + * to define it. + */ + const char *long_name; + + /** + * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS, + * AVFMT_NOTIMESTAMPS, AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH, + * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS. + */ + int flags; + + /** + * If extensions are defined, then no probe is done. You should + * usually not use extension format guessing because it is not + * reliable enough + */ + const char *extensions; + + const struct AVCodecTag * const *codec_tag; + + const AVClass *priv_class; ///< AVClass for the private context + + /** + * Comma-separated list of mime types. + * It is used check for matching mime types while probing. + * @see av_probe_input_format2 + */ + const char *mime_type; +} AVInputFormat; +/** + * @} + */ + +enum AVStreamParseType { + AVSTREAM_PARSE_NONE, + AVSTREAM_PARSE_FULL, /**< full parsing and repack */ + AVSTREAM_PARSE_HEADERS, /**< Only parse headers, do not repack. */ + AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on a packet boundary */ + AVSTREAM_PARSE_FULL_ONCE, /**< full parsing and repack of the first frame only, only implemented for H.264 currently */ + AVSTREAM_PARSE_FULL_RAW, /**< full parsing and repack with timestamp and position generation by parser for raw + this assumes that each packet in the file contains no demuxer level headers and + just codec level data, otherwise position generation would fail */ +}; + +typedef struct AVIndexEntry { + int64_t pos; + int64_t timestamp; /**< + * Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are available + * when seeking to this entry. That means preferable PTS on keyframe based formats. + * But demuxers can choose to store a different timestamp, if it is more convenient for the implementation or nothing better + * is known + */ +#define AVINDEX_KEYFRAME 0x0001 +#define AVINDEX_DISCARD_FRAME 0x0002 /** + * Flag is used to indicate which frame should be discarded after decoding. + */ + int flags:2; + int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment). + int min_distance; /**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. */ +} AVIndexEntry; + +/** + * The stream should be chosen by default among other streams of the same type, + * unless the user has explicitly specified otherwise. + */ +#define AV_DISPOSITION_DEFAULT (1 << 0) +/** + * The stream is not in original language. + * + * @note AV_DISPOSITION_ORIGINAL is the inverse of this disposition. At most + * one of them should be set in properly tagged streams. + * @note This disposition may apply to any stream type, not just audio. + */ +#define AV_DISPOSITION_DUB (1 << 1) +/** + * The stream is in original language. + * + * @see the notes for AV_DISPOSITION_DUB + */ +#define AV_DISPOSITION_ORIGINAL (1 << 2) +/** + * The stream is a commentary track. + */ +#define AV_DISPOSITION_COMMENT (1 << 3) +/** + * The stream contains song lyrics. + */ +#define AV_DISPOSITION_LYRICS (1 << 4) +/** + * The stream contains karaoke audio. + */ +#define AV_DISPOSITION_KARAOKE (1 << 5) + +/** + * Track should be used during playback by default. + * Useful for subtitle track that should be displayed + * even when user did not explicitly ask for subtitles. + */ +#define AV_DISPOSITION_FORCED (1 << 6) +/** + * The stream is intended for hearing impaired audiences. + */ +#define AV_DISPOSITION_HEARING_IMPAIRED (1 << 7) +/** + * The stream is intended for visually impaired audiences. + */ +#define AV_DISPOSITION_VISUAL_IMPAIRED (1 << 8) +/** + * The audio stream contains music and sound effects without voice. + */ +#define AV_DISPOSITION_CLEAN_EFFECTS (1 << 9) +/** + * The stream is stored in the file as an attached picture/"cover art" (e.g. + * APIC frame in ID3v2). The first (usually only) packet associated with it + * will be returned among the first few packets read from the file unless + * seeking takes place. It can also be accessed at any time in + * AVStream.attached_pic. + */ +#define AV_DISPOSITION_ATTACHED_PIC (1 << 10) +/** + * The stream is sparse, and contains thumbnail images, often corresponding + * to chapter markers. Only ever used with AV_DISPOSITION_ATTACHED_PIC. + */ +#define AV_DISPOSITION_TIMED_THUMBNAILS (1 << 11) + +/** + * The stream is intended to be mixed with a spatial audio track. For example, + * it could be used for narration or stereo music, and may remain unchanged by + * listener head rotation. + */ +#define AV_DISPOSITION_NON_DIEGETIC (1 << 12) + +/** + * The subtitle stream contains captions, providing a transcription and possibly + * a translation of audio. Typically intended for hearing-impaired audiences. + */ +#define AV_DISPOSITION_CAPTIONS (1 << 16) +/** + * The subtitle stream contains a textual description of the video content. + * Typically intended for visually-impaired audiences or for the cases where the + * video cannot be seen. + */ +#define AV_DISPOSITION_DESCRIPTIONS (1 << 17) +/** + * The subtitle stream contains time-aligned metadata that is not intended to be + * directly presented to the user. + */ +#define AV_DISPOSITION_METADATA (1 << 18) +/** + * The stream is intended to be mixed with another stream before presentation. + * Used for example to signal the stream contains an image part of a HEIF grid, + * or for mix_type=0 in mpegts. + */ +#define AV_DISPOSITION_DEPENDENT (1 << 19) +/** + * The video stream contains still images. + */ +#define AV_DISPOSITION_STILL_IMAGE (1 << 20) +/** + * The video stream contains multiple layers, e.g. stereoscopic views (cf. H.264 + * Annex G/H, or HEVC Annex F). + */ +#define AV_DISPOSITION_MULTILAYER (1 << 21) + +/** + * @return The AV_DISPOSITION_* flag corresponding to disp or a negative error + * code if disp does not correspond to a known stream disposition. + */ +int av_disposition_from_string(const char *disp); + +/** + * @param disposition a combination of AV_DISPOSITION_* values + * @return The string description corresponding to the lowest set bit in + * disposition. NULL when the lowest set bit does not correspond + * to a known disposition or when disposition is 0. + */ +const char *av_disposition_to_string(int disposition); + +/** + * Options for behavior on timestamp wrap detection. + */ +#define AV_PTS_WRAP_IGNORE 0 ///< ignore the wrap +#define AV_PTS_WRAP_ADD_OFFSET 1 ///< add the format specific offset on wrap detection +#define AV_PTS_WRAP_SUB_OFFSET -1 ///< subtract the format specific offset on wrap detection + +/** + * Stream structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVStream) must not be used outside libav*. + */ +typedef struct AVStream { + /** + * A class for @ref avoptions. Set on stream creation. + */ + const AVClass *av_class; + + int index; /**< stream index in AVFormatContext */ + /** + * Format-specific stream ID. + * decoding: set by libavformat + * encoding: set by the user, replaced by libavformat if left unset + */ + int id; + + /** + * Codec parameters associated with this stream. Allocated and freed by + * libavformat in avformat_new_stream() and avformat_free_context() + * respectively. + * + * - demuxing: filled by libavformat on stream creation or in + * avformat_find_stream_info() + * - muxing: filled by the caller before avformat_write_header() + */ + AVCodecParameters *codecpar; + + void *priv_data; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. + * + * decoding: set by libavformat + * encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the desired timebase. In + * avformat_write_header(), the muxer will overwrite this field + * with the timebase that will actually be used for the timestamps + * written into the file (which may or may not be related to the + * user-provided one, depending on the format). + */ + AVRational time_base; + + /** + * Decoding: pts of the first frame of the stream in presentation order, in stream time base. + * Only set this if you are absolutely 100% sure that the value you set + * it to really is the pts of the first frame. + * This may be undefined (AV_NOPTS_VALUE). + * @note The ASF header does NOT contain a correct start_time the ASF + * demuxer must NOT set this. + */ + int64_t start_time; + + /** + * Decoding: duration of the stream, in stream time base. + * If a source file does not specify a duration, but does specify + * a bitrate, this value will be estimated from bitrate and file size. + * + * Encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the estimated duration. + */ + int64_t duration; + + int64_t nb_frames; ///< number of frames in this stream if known or 0 + + /** + * Stream disposition - a combination of AV_DISPOSITION_* flags. + * - demuxing: set by libavformat when creating the stream or in + * avformat_find_stream_info(). + * - muxing: may be set by the caller before avformat_write_header(). + */ + int disposition; + + enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed. + + /** + * sample aspect ratio (0 if unknown) + * - encoding: Set by user. + * - decoding: Set by libavformat. + */ + AVRational sample_aspect_ratio; + + AVDictionary *metadata; + + /** + * Average framerate + * + * - demuxing: May be set by libavformat when creating the stream or in + * avformat_find_stream_info(). + * - muxing: May be set by the caller before avformat_write_header(). + */ + AVRational avg_frame_rate; + + /** + * For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet + * will contain the attached picture. + * + * decoding: set by libavformat, must not be modified by the caller. + * encoding: unused + */ + AVPacket attached_pic; + + /** + * Flags indicating events happening on the stream, a combination of + * AVSTREAM_EVENT_FLAG_*. + * + * - demuxing: may be set by the demuxer in avformat_open_input(), + * avformat_find_stream_info() and av_read_frame(). Flags must be cleared + * by the user once the event has been handled. + * - muxing: may be set by the user after avformat_write_header(). to + * indicate a user-triggered event. The muxer will clear the flags for + * events it has handled in av_[interleaved]_write_frame(). + */ + int event_flags; +/** + * - demuxing: the demuxer read new metadata from the file and updated + * AVStream.metadata accordingly + * - muxing: the user updated AVStream.metadata and wishes the muxer to write + * it into the file + */ +#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 +/** + * - demuxing: new packets for this stream were read from the file. This + * event is informational only and does not guarantee that new packets + * for this stream will necessarily be returned from av_read_frame(). + */ +#define AVSTREAM_EVENT_FLAG_NEW_PACKETS (1 << 1) + + /** + * Real base framerate of the stream. + * This is the lowest framerate with which all timestamps can be + * represented accurately (it is the least common multiple of all + * framerates in the stream). Note, this value is just a guess! + * For example, if the time base is 1/90000 and all frames have either + * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1. + */ + AVRational r_frame_rate; + + /** + * Number of bits in timestamps. Used for wrapping control. + * + * - demuxing: set by libavformat + * - muxing: set by libavformat + * + */ + int pts_wrap_bits; +} AVStream; + +/** + * AVStreamGroupTileGrid holds information on how to combine several + * independent images on a single canvas for presentation. + * + * The output should be a @ref AVStreamGroupTileGrid.background "background" + * colored @ref AVStreamGroupTileGrid.coded_width "coded_width" x + * @ref AVStreamGroupTileGrid.coded_height "coded_height" canvas where a + * @ref AVStreamGroupTileGrid.nb_tiles "nb_tiles" amount of tiles are placed in + * the order they appear in the @ref AVStreamGroupTileGrid.offsets "offsets" + * array, at the exact offset described for them. In particular, if two or more + * tiles overlap, the image with higher index in the + * @ref AVStreamGroupTileGrid.offsets "offsets" array takes priority. + * Note that a single image may be used multiple times, i.e. multiple entries + * in @ref AVStreamGroupTileGrid.offsets "offsets" may have the same value of + * idx. + * + * The following is an example of a simple grid with 3 rows and 4 columns: + * + * +---+---+---+---+ + * | 0 | 1 | 2 | 3 | + * +---+---+---+---+ + * | 4 | 5 | 6 | 7 | + * +---+---+---+---+ + * | 8 | 9 |10 |11 | + * +---+---+---+---+ + * + * Assuming all tiles have a dimension of 512x512, the + * @ref AVStreamGroupTileGrid.offsets "offset" of the topleft pixel of + * the first @ref AVStreamGroup.streams "stream" in the group is "0,0", the + * @ref AVStreamGroupTileGrid.offsets "offset" of the topleft pixel of + * the second @ref AVStreamGroup.streams "stream" in the group is "512,0", the + * @ref AVStreamGroupTileGrid.offsets "offset" of the topleft pixel of + * the fifth @ref AVStreamGroup.streams "stream" in the group is "0,512", the + * @ref AVStreamGroupTileGrid.offsets "offset", of the topleft pixel of + * the sixth @ref AVStreamGroup.streams "stream" in the group is "512,512", + * etc. + * + * The following is an example of a canvas with overlapping tiles: + * + * +-----------+ + * | %%%%% | + * |***%%3%%@@@| + * |**0%%%%%2@@| + * |***##1@@@@@| + * | ##### | + * +-----------+ + * + * Assuming a canvas with size 1024x1024 and all tiles with a dimension of + * 512x512, a possible @ref AVStreamGroupTileGrid.offsets "offset" for the + * topleft pixel of the first @ref AVStreamGroup.streams "stream" in the group + * would be 0x256, the @ref AVStreamGroupTileGrid.offsets "offset" for the + * topleft pixel of the second @ref AVStreamGroup.streams "stream" in the group + * would be 256x512, the @ref AVStreamGroupTileGrid.offsets "offset" for the + * topleft pixel of the third @ref AVStreamGroup.streams "stream" in the group + * would be 512x256, and the @ref AVStreamGroupTileGrid.offsets "offset" for + * the topleft pixel of the fourth @ref AVStreamGroup.streams "stream" in the + * group would be 256x0. + * + * sizeof(AVStreamGroupTileGrid) is not a part of the ABI and may only be + * allocated by avformat_stream_group_create(). + */ +typedef struct AVStreamGroupTileGrid { + const AVClass *av_class; + + /** + * Amount of tiles in the grid. + * + * Must be > 0. + */ + unsigned int nb_tiles; + + /** + * Width of the canvas. + * + * Must be > 0. + */ + int coded_width; + /** + * Width of the canvas. + * + * Must be > 0. + */ + int coded_height; + + /** + * An @ref nb_tiles sized array of offsets in pixels from the topleft edge + * of the canvas, indicating where each stream should be placed. + * It must be allocated with the av_malloc() family of functions. + * + * - demuxing: set by libavformat, must not be modified by the caller. + * - muxing: set by the caller before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + */ + struct { + /** + * Index of the stream in the group this tile references. + * + * Must be < @ref AVStreamGroup.nb_streams "nb_streams". + */ + unsigned int idx; + /** + * Offset in pixels from the left edge of the canvas where the tile + * should be placed. + */ + int horizontal; + /** + * Offset in pixels from the top edge of the canvas where the tile + * should be placed. + */ + int vertical; + } *offsets; + + /** + * The pixel value per channel in RGBA format used if no pixel of any tile + * is located at a particular pixel location. + * + * @see av_image_fill_color(). + * @see av_parse_color(). + */ + uint8_t background[4]; + + /** + * Offset in pixels from the left edge of the canvas where the actual image + * meant for presentation starts. + * + * This field must be >= 0 and < @ref coded_width. + */ + int horizontal_offset; + /** + * Offset in pixels from the top edge of the canvas where the actual image + * meant for presentation starts. + * + * This field must be >= 0 and < @ref coded_height. + */ + int vertical_offset; + + /** + * Width of the final image for presentation. + * + * Must be > 0 and <= (@ref coded_width - @ref horizontal_offset). + * When it's not equal to (@ref coded_width - @ref horizontal_offset), the + * result of (@ref coded_width - width - @ref horizontal_offset) is the + * amount amount of pixels to be cropped from the right edge of the + * final image before presentation. + */ + int width; + /** + * Height of the final image for presentation. + * + * Must be > 0 and <= (@ref coded_height - @ref vertical_offset). + * When it's not equal to (@ref coded_height - @ref vertical_offset), the + * result of (@ref coded_height - height - @ref vertical_offset) is the + * amount amount of pixels to be cropped from the bottom edge of the + * final image before presentation. + */ + int height; + + /** + * Additional data associated with the grid. + * + * Should be allocated with av_packet_side_data_new() or + * av_packet_side_data_add(), and will be freed by avformat_free_context(). + */ + AVPacketSideData *coded_side_data; + + /** + * Amount of entries in @ref coded_side_data. + */ + int nb_coded_side_data; +} AVStreamGroupTileGrid; + +/** + * AVStreamGroupLCEVC is meant to define the relation between video streams + * and a data stream containing LCEVC enhancement layer NALUs. + * + * No more than one stream of @ref AVCodecParameters.codec_type "codec_type" + * AVMEDIA_TYPE_DATA shall be present, and it must be of + * @ref AVCodecParameters.codec_id "codec_id" AV_CODEC_ID_LCEVC. + */ +typedef struct AVStreamGroupLCEVC { + const AVClass *av_class; + + /** + * Index of the LCEVC data stream in AVStreamGroup. + */ + unsigned int lcevc_index; + /** + * Width of the final stream for presentation. + */ + int width; + /** + * Height of the final image for presentation. + */ + int height; +} AVStreamGroupLCEVC; + +enum AVStreamGroupParamsType { + AV_STREAM_GROUP_PARAMS_NONE, + AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, + AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, + AV_STREAM_GROUP_PARAMS_TILE_GRID, + AV_STREAM_GROUP_PARAMS_LCEVC, +}; + +struct AVIAMFAudioElement; +struct AVIAMFMixPresentation; + +typedef struct AVStreamGroup { + /** + * A class for @ref avoptions. Set by avformat_stream_group_create(). + */ + const AVClass *av_class; + + void *priv_data; + + /** + * Group index in AVFormatContext. + */ + unsigned int index; + + /** + * Group type-specific group ID. + * + * decoding: set by libavformat + * encoding: may set by the user + */ + int64_t id; + + /** + * Group type + * + * decoding: set by libavformat on group creation + * encoding: set by avformat_stream_group_create() + */ + enum AVStreamGroupParamsType type; + + /** + * Group type-specific parameters + */ + union { + struct AVIAMFAudioElement *iamf_audio_element; + struct AVIAMFMixPresentation *iamf_mix_presentation; + struct AVStreamGroupTileGrid *tile_grid; + struct AVStreamGroupLCEVC *lcevc; + } params; + + /** + * Metadata that applies to the whole group. + * + * - demuxing: set by libavformat on group creation + * - muxing: may be set by the caller before avformat_write_header() + * + * Freed by libavformat in avformat_free_context(). + */ + AVDictionary *metadata; + + /** + * Number of elements in AVStreamGroup.streams. + * + * Set by avformat_stream_group_add_stream() must not be modified by any other code. + */ + unsigned int nb_streams; + + /** + * A list of streams in the group. New entries are created with + * avformat_stream_group_add_stream(). + * + * - demuxing: entries are created by libavformat on group creation. + * If AVFMTCTX_NOHEADER is set in ctx_flags, then new entries may also + * appear in av_read_frame(). + * - muxing: entries are created by the user before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + */ + AVStream **streams; + + /** + * Stream group disposition - a combination of AV_DISPOSITION_* flags. + * This field currently applies to all defined AVStreamGroupParamsType. + * + * - demuxing: set by libavformat when creating the group or in + * avformat_find_stream_info(). + * - muxing: may be set by the caller before avformat_write_header(). + */ + int disposition; +} AVStreamGroup; + +struct AVCodecParserContext *av_stream_get_parser(const AVStream *s); + +#define AV_PROGRAM_RUNNING 1 + +/** + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVProgram) must not be used outside libav*. + */ +typedef struct AVProgram { + int id; + int flags; + enum AVDiscard discard; ///< selects which program to discard and which to feed to the caller + unsigned int *stream_index; + unsigned int nb_stream_indexes; + AVDictionary *metadata; + + int program_num; + int pmt_pid; + int pcr_pid; + int pmt_version; + + /***************************************************************** + * All fields below this line are not part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + int64_t start_time; + int64_t end_time; + + int64_t pts_wrap_reference; ///< reference dts for wrap detection + int pts_wrap_behavior; ///< behavior on wrap detection +} AVProgram; + +#define AVFMTCTX_NOHEADER 0x0001 /**< signal that no header is present + (streams are added dynamically) */ +#define AVFMTCTX_UNSEEKABLE 0x0002 /**< signal that the stream is definitely + not seekable, and attempts to call the + seek function will fail. For some + network protocols (e.g. HLS), this can + change dynamically at runtime. */ + +typedef struct AVChapter { + int64_t id; ///< unique ID to identify the chapter + AVRational time_base; ///< time base in which the start/end timestamps are specified + int64_t start, end; ///< chapter start/end time in time_base units + AVDictionary *metadata; +} AVChapter; + + +/** + * Callback used by devices to communicate with application. + */ +typedef int (*av_format_control_message)(struct AVFormatContext *s, int type, + void *data, size_t data_size); + +typedef int (*AVOpenCallback)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, + const AVIOInterruptCB *int_cb, AVDictionary **options); + +/** + * The duration of a video can be estimated through various ways, and this enum can be used + * to know how the duration was estimated. + */ +enum AVDurationEstimationMethod { + AVFMT_DURATION_FROM_PTS, ///< Duration accurately estimated from PTSes + AVFMT_DURATION_FROM_STREAM, ///< Duration estimated from a stream with a known duration + AVFMT_DURATION_FROM_BITRATE ///< Duration estimated from bitrate (less accurate) +}; + +/** + * Format I/O context. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * sizeof(AVFormatContext) must not be used outside libav*, use + * avformat_alloc_context() to create an AVFormatContext. + * + * Fields can be accessed through AVOptions (av_opt*), + * the name string used matches the associated command line parameter name and + * can be found in libavformat/options_table.h. + * The AVOption/command line parameter names differ in some cases from the C + * structure field names for historic reasons or brevity. + */ +typedef struct AVFormatContext { + /** + * A class for logging and @ref avoptions. Set by avformat_alloc_context(). + * Exports (de)muxer private options if they exist. + */ + const AVClass *av_class; + + /** + * The input container format. + * + * Demuxing only, set by avformat_open_input(). + */ + const struct AVInputFormat *iformat; + + /** + * The output container format. + * + * Muxing only, must be set by the caller before avformat_write_header(). + */ + const struct AVOutputFormat *oformat; + + /** + * Format private data. This is an AVOptions-enabled struct + * if and only if iformat/oformat.priv_class is not NULL. + * + * - muxing: set by avformat_write_header() + * - demuxing: set by avformat_open_input() + */ + void *priv_data; + + /** + * I/O context. + * + * - demuxing: either set by the user before avformat_open_input() (then + * the user must close it manually) or set by avformat_open_input(). + * - muxing: set by the user before avformat_write_header(). The caller must + * take care of closing / freeing the IO context. + * + * Do NOT set this field if AVFMT_NOFILE flag is set in + * iformat/oformat.flags. In such a case, the (de)muxer will handle + * I/O in some other way and this field will be NULL. + */ + AVIOContext *pb; + + /* stream info */ + /** + * Flags signalling stream properties. A combination of AVFMTCTX_*. + * Set by libavformat. + */ + int ctx_flags; + + /** + * Number of elements in AVFormatContext.streams. + * + * Set by avformat_new_stream(), must not be modified by any other code. + */ + unsigned int nb_streams; + /** + * A list of all streams in the file. New streams are created with + * avformat_new_stream(). + * + * - demuxing: streams are created by libavformat in avformat_open_input(). + * If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also + * appear in av_read_frame(). + * - muxing: streams are created by the user before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + */ + AVStream **streams; + + /** + * Number of elements in AVFormatContext.stream_groups. + * + * Set by avformat_stream_group_create(), must not be modified by any other code. + */ + unsigned int nb_stream_groups; + /** + * A list of all stream groups in the file. New groups are created with + * avformat_stream_group_create(), and filled with avformat_stream_group_add_stream(). + * + * - demuxing: groups may be created by libavformat in avformat_open_input(). + * If AVFMTCTX_NOHEADER is set in ctx_flags, then new groups may also + * appear in av_read_frame(). + * - muxing: groups may be created by the user before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + */ + AVStreamGroup **stream_groups; + + /** + * Number of chapters in AVChapter array. + * When muxing, chapters are normally written in the file header, + * so nb_chapters should normally be initialized before write_header + * is called. Some muxers (e.g. mov and mkv) can also write chapters + * in the trailer. To write chapters in the trailer, nb_chapters + * must be zero when write_header is called and non-zero when + * write_trailer is called. + * - muxing: set by user + * - demuxing: set by libavformat + */ + unsigned int nb_chapters; + AVChapter **chapters; + + /** + * input or output URL. Unlike the old filename field, this field has no + * length restriction. + * + * - demuxing: set by avformat_open_input(), initialized to an empty + * string if url parameter was NULL in avformat_open_input(). + * - muxing: may be set by the caller before calling avformat_write_header() + * (or avformat_init_output() if that is called first) to a string + * which is freeable by av_free(). Set to an empty string if it + * was NULL in avformat_init_output(). + * + * Freed by libavformat in avformat_free_context(). + */ + char *url; + + /** + * Position of the first frame of the component, in + * AV_TIME_BASE fractional seconds. NEVER set this value directly: + * It is deduced from the AVStream values. + * + * Demuxing only, set by libavformat. + */ + int64_t start_time; + + /** + * Duration of the stream, in AV_TIME_BASE fractional + * seconds. Only set this value if you know none of the individual stream + * durations and also do not set any of them. This is deduced from the + * AVStream values if not set. + * + * Demuxing only, set by libavformat. + */ + int64_t duration; + + /** + * Total stream bitrate in bit/s, 0 if not + * available. Never set it directly if the file_size and the + * duration are known as FFmpeg can compute it automatically. + */ + int64_t bit_rate; + + unsigned int packet_size; + int max_delay; + + /** + * Flags modifying the (de)muxer behaviour. A combination of AVFMT_FLAG_*. + * Set by the user before avformat_open_input() / avformat_write_header(). + */ + int flags; +#define AVFMT_FLAG_GENPTS 0x0001 ///< Generate missing pts even if it requires parsing future frames. +#define AVFMT_FLAG_IGNIDX 0x0002 ///< Ignore index. +#define AVFMT_FLAG_NONBLOCK 0x0004 ///< Do not block when reading packets from input. +#define AVFMT_FLAG_IGNDTS 0x0008 ///< Ignore DTS on frames that contain both DTS & PTS +#define AVFMT_FLAG_NOFILLIN 0x0010 ///< Do not infer any values from other values, just return what is stored in the container +#define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the filling code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled +#define AVFMT_FLAG_NOBUFFER 0x0040 ///< Do not buffer frames when possible +#define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it. +#define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted +#define AVFMT_FLAG_FLUSH_PACKETS 0x0200 ///< Flush the AVIOContext every packet. +/** + * When muxing, try to avoid writing any random/volatile data to the output. + * This includes any random IDs, real-time timestamps/dates, muxer version, etc. + * + * This flag is mainly intended for testing. + */ +#define AVFMT_FLAG_BITEXACT 0x0400 +#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down) +#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats +#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer + + /** + * Maximum number of bytes read from input in order to determine stream + * properties. Used when reading the global header and in + * avformat_find_stream_info(). + * + * Demuxing only, set by the caller before avformat_open_input(). + * + * @note this is \e not used for determining the \ref AVInputFormat + * "input format" + * @see format_probesize + */ + int64_t probesize; + + /** + * Maximum duration (in AV_TIME_BASE units) of the data read + * from input in avformat_find_stream_info(). + * Demuxing only, set by the caller before avformat_find_stream_info(). + * Can be set to 0 to let avformat choose using a heuristic. + */ + int64_t max_analyze_duration; + + const uint8_t *key; + int keylen; + + unsigned int nb_programs; + AVProgram **programs; + + /** + * Forced video codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID video_codec_id; + + /** + * Forced audio codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID audio_codec_id; + + /** + * Forced subtitle codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID subtitle_codec_id; + + /** + * Forced Data codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID data_codec_id; + + /** + * Metadata that applies to the whole file. + * + * - demuxing: set by libavformat in avformat_open_input() + * - muxing: may be set by the caller before avformat_write_header() + * + * Freed by libavformat in avformat_free_context(). + */ + AVDictionary *metadata; + + /** + * Start time of the stream in real world time, in microseconds + * since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the + * stream was captured at this real world time. + * - muxing: Set by the caller before avformat_write_header(). If set to + * either 0 or AV_NOPTS_VALUE, then the current wall-time will + * be used. + * - demuxing: Set by libavformat. AV_NOPTS_VALUE if unknown. Note that + * the value may become known after some number of frames + * have been received. + */ + int64_t start_time_realtime; + + /** + * The number of frames used for determining the framerate in + * avformat_find_stream_info(). + * Demuxing only, set by the caller before avformat_find_stream_info(). + */ + int fps_probe_size; + + /** + * Error recognition; higher values will detect more errors but may + * misdetect some more or less valid parts as errors. + * Demuxing only, set by the caller before avformat_open_input(). + */ + int error_recognition; + + /** + * Custom interrupt callbacks for the I/O layer. + * + * demuxing: set by the user before avformat_open_input(). + * muxing: set by the user before avformat_write_header() + * (mainly useful for AVFMT_NOFILE formats). The callback + * should also be passed to avio_open2() if it's used to + * open the file. + */ + AVIOInterruptCB interrupt_callback; + + /** + * Flags to enable debugging. + */ + int debug; +#define FF_FDEBUG_TS 0x0001 + + /** + * The maximum number of streams. + * - encoding: unused + * - decoding: set by user + */ + int max_streams; + + /** + * Maximum amount of memory in bytes to use for the index of each stream. + * If the index exceeds this size, entries will be discarded as + * needed to maintain a smaller size. This can lead to slower or less + * accurate seeking (depends on demuxer). + * Demuxers for which a full in-memory index is mandatory will ignore + * this. + * - muxing: unused + * - demuxing: set by user + */ + unsigned int max_index_size; + + /** + * Maximum amount of memory in bytes to use for buffering frames + * obtained from realtime capture devices. + */ + unsigned int max_picture_buffer; + + /** + * Maximum buffering duration for interleaving. + * + * To ensure all the streams are interleaved correctly, + * av_interleaved_write_frame() will wait until it has at least one packet + * for each stream before actually writing any packets to the output file. + * When some streams are "sparse" (i.e. there are large gaps between + * successive packets), this can result in excessive buffering. + * + * This field specifies the maximum difference between the timestamps of the + * first and the last packet in the muxing queue, above which libavformat + * will output a packet regardless of whether it has queued a packet for all + * the streams. + * + * Muxing only, set by the caller before avformat_write_header(). + */ + int64_t max_interleave_delta; + + /** + * Maximum number of packets to read while waiting for the first timestamp. + * Decoding only. + */ + int max_ts_probe; + + /** + * Max chunk time in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int max_chunk_duration; + + /** + * Max chunk size in bytes + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int max_chunk_size; + + /** + * Maximum number of packets that can be probed + * - encoding: unused + * - decoding: set by user + */ + int max_probe_packets; + + /** + * Allow non-standard and experimental extension + * @see AVCodecContext.strict_std_compliance + */ + int strict_std_compliance; + + /** + * Flags indicating events happening on the file, a combination of + * AVFMT_EVENT_FLAG_*. + * + * - demuxing: may be set by the demuxer in avformat_open_input(), + * avformat_find_stream_info() and av_read_frame(). Flags must be cleared + * by the user once the event has been handled. + * - muxing: may be set by the user after avformat_write_header() to + * indicate a user-triggered event. The muxer will clear the flags for + * events it has handled in av_[interleaved]_write_frame(). + */ + int event_flags; +/** + * - demuxing: the demuxer read new metadata from the file and updated + * AVFormatContext.metadata accordingly + * - muxing: the user updated AVFormatContext.metadata and wishes the muxer to + * write it into the file + */ +#define AVFMT_EVENT_FLAG_METADATA_UPDATED 0x0001 + + + /** + * Avoid negative timestamps during muxing. + * Any value of the AVFMT_AVOID_NEG_TS_* constants. + * Note, this works better when using av_interleaved_write_frame(). + * - muxing: Set by user + * - demuxing: unused + */ + int avoid_negative_ts; +#define AVFMT_AVOID_NEG_TS_AUTO -1 ///< Enabled when required by target format +#define AVFMT_AVOID_NEG_TS_DISABLED 0 ///< Do not shift timestamps even when they are negative. +#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative +#define AVFMT_AVOID_NEG_TS_MAKE_ZERO 2 ///< Shift timestamps so that they start at 0 + + /** + * Audio preload in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user + * - decoding: unused + */ + int audio_preload; + + /** + * forces the use of wallclock timestamps as pts/dts of packets + * This has undefined results in the presence of B frames. + * - encoding: unused + * - decoding: Set by user + */ + int use_wallclock_as_timestamps; + + /** + * Skip duration calculation in estimate_timings_from_pts. + * - encoding: unused + * - decoding: set by user + * + * @see duration_probesize + */ + int skip_estimate_duration_from_pts; + + /** + * avio flags, used to force AVIO_FLAG_DIRECT. + * - encoding: unused + * - decoding: Set by user + */ + int avio_flags; + + /** + * The duration field can be estimated through various ways, and this field can be used + * to know how the duration was estimated. + * - encoding: unused + * - decoding: Read by user + */ + enum AVDurationEstimationMethod duration_estimation_method; + + /** + * Skip initial bytes when opening stream + * - encoding: unused + * - decoding: Set by user + */ + int64_t skip_initial_bytes; + + /** + * Correct single timestamp overflows + * - encoding: unused + * - decoding: Set by user + */ + unsigned int correct_ts_overflow; + + /** + * Force seeking to any (also non key) frames. + * - encoding: unused + * - decoding: Set by user + */ + int seek2any; + + /** + * Flush the I/O context after each packet. + * - encoding: Set by user + * - decoding: unused + */ + int flush_packets; + + /** + * format probing score. + * The maximal score is AVPROBE_SCORE_MAX, its set when the demuxer probes + * the format. + * - encoding: unused + * - decoding: set by avformat, read by user + */ + int probe_score; + + /** + * Maximum number of bytes read from input in order to identify the + * \ref AVInputFormat "input format". Only used when the format is not set + * explicitly by the caller. + * + * Demuxing only, set by the caller before avformat_open_input(). + * + * @see probesize + */ + int format_probesize; + + /** + * ',' separated list of allowed decoders. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *codec_whitelist; + + /** + * ',' separated list of allowed demuxers. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *format_whitelist; + + /** + * ',' separated list of allowed protocols. + * - encoding: unused + * - decoding: set by user + */ + char *protocol_whitelist; + + /** + * ',' separated list of disallowed protocols. + * - encoding: unused + * - decoding: set by user + */ + char *protocol_blacklist; + + /** + * IO repositioned flag. + * This is set by avformat when the underlying IO context read pointer + * is repositioned, for example when doing byte based seeking. + * Demuxers can use the flag to detect such changes. + */ + int io_repositioned; + + /** + * Forced video codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const struct AVCodec *video_codec; + + /** + * Forced audio codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const struct AVCodec *audio_codec; + + /** + * Forced subtitle codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const struct AVCodec *subtitle_codec; + + /** + * Forced data codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user + */ + const struct AVCodec *data_codec; + + /** + * Number of bytes to be written as padding in a metadata header. + * Demuxing: Unused. + * Muxing: Set by user. + */ + int metadata_header_padding; + + /** + * User data. + * This is a place for some private data of the user. + */ + void *opaque; + + /** + * Callback used by devices to communicate with application. + */ + av_format_control_message control_message_cb; + + /** + * Output timestamp offset, in microseconds. + * Muxing: set by user + */ + int64_t output_ts_offset; + + /** + * dump format separator. + * can be ", " or "\n " or anything else + * - muxing: Set by user. + * - demuxing: Set by user. + */ + uint8_t *dump_separator; + + /** + * A callback for opening new IO streams. + * + * Whenever a muxer or a demuxer needs to open an IO stream (typically from + * avformat_open_input() for demuxers, but for certain formats can happen at + * other times as well), it will call this callback to obtain an IO context. + * + * @param s the format context + * @param pb on success, the newly opened IO context should be returned here + * @param url the url to open + * @param flags a combination of AVIO_FLAG_* + * @param options a dictionary of additional options, with the same + * semantics as in avio_open2() + * @return 0 on success, a negative AVERROR code on failure + * + * @note Certain muxers and demuxers do nesting, i.e. they open one or more + * additional internal format contexts. Thus the AVFormatContext pointer + * passed to this callback may be different from the one facing the caller. + * It will, however, have the same 'opaque' field. + */ + int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, + int flags, AVDictionary **options); + + /** + * A callback for closing the streams opened with AVFormatContext.io_open(). + * + * @param s the format context + * @param pb IO context to be closed and freed + * @return 0 on success, a negative AVERROR code on failure + */ + int (*io_close2)(struct AVFormatContext *s, AVIOContext *pb); + + /** + * Maximum number of bytes read from input in order to determine stream durations + * when using estimate_timings_from_pts in avformat_find_stream_info(). + * Demuxing only, set by the caller before avformat_find_stream_info(). + * Can be set to 0 to let avformat choose using a heuristic. + * + * @see skip_estimate_duration_from_pts + */ + int64_t duration_probesize; +} AVFormatContext; + +/** + * @defgroup lavf_core Core functions + * @ingroup libavf + * + * Functions for querying libavformat capabilities, allocating core structures, + * etc. + * @{ + */ + +/** + * Return the LIBAVFORMAT_VERSION_INT constant. + */ +unsigned avformat_version(void); + +/** + * Return the libavformat build-time configuration. + */ +const char *avformat_configuration(void); + +/** + * Return the libavformat license. + */ +const char *avformat_license(void); + +/** + * Do global initialization of network libraries. This is optional, + * and not recommended anymore. + * + * This functions only exists to work around thread-safety issues + * with older GnuTLS or OpenSSL libraries. If libavformat is linked + * to newer versions of those libraries, or if you do not use them, + * calling this function is unnecessary. Otherwise, you need to call + * this function before any other threads using them are started. + * + * This function will be deprecated once support for older GnuTLS and + * OpenSSL libraries is removed, and this function has no purpose + * anymore. + */ +int avformat_network_init(void); + +/** + * Undo the initialization done by avformat_network_init. Call it only + * once for each time you called avformat_network_init. + */ +int avformat_network_deinit(void); + +/** + * Iterate over all registered muxers. + * + * @param opaque a pointer where libavformat will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered muxer or NULL when the iteration is + * finished + */ +const AVOutputFormat *av_muxer_iterate(void **opaque); + +/** + * Iterate over all registered demuxers. + * + * @param opaque a pointer where libavformat will store the iteration state. + * Must point to NULL to start the iteration. + * + * @return the next registered demuxer or NULL when the iteration is + * finished + */ +const AVInputFormat *av_demuxer_iterate(void **opaque); + +/** + * Allocate an AVFormatContext. + * avformat_free_context() can be used to free the context and everything + * allocated by the framework within it. + */ +AVFormatContext *avformat_alloc_context(void); + +/** + * Free an AVFormatContext and all its streams. + * @param s context to free + */ +void avformat_free_context(AVFormatContext *s); + +/** + * Get the AVClass for AVFormatContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avformat_get_class(void); + +/** + * Get the AVClass for AVStream. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *av_stream_get_class(void); + +/** + * Get the AVClass for AVStreamGroup. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *av_stream_group_get_class(void); + +/** + * @return a string identifying the stream group type, or NULL if unknown + */ +const char *avformat_stream_group_name(enum AVStreamGroupParamsType type); + +/** + * Add a new empty stream group to a media file. + * + * When demuxing, it may be called by the demuxer in read_header(). If the + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also + * be called in read_packet(). + * + * When muxing, may be called by the user before avformat_write_header(). + * + * User is required to call avformat_free_context() to clean up the allocation + * by avformat_stream_group_create(). + * + * New streams can be added to the group with avformat_stream_group_add_stream(). + * + * @param s media file handle + * + * @return newly created group or NULL on error. + * @see avformat_new_stream, avformat_stream_group_add_stream. + */ +AVStreamGroup *avformat_stream_group_create(AVFormatContext *s, + enum AVStreamGroupParamsType type, + AVDictionary **options); + +/** + * Add a new stream to a media file. + * + * When demuxing, it is called by the demuxer in read_header(). If the + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also + * be called in read_packet(). + * + * When muxing, should be called by the user before avformat_write_header(). + * + * User is required to call avformat_free_context() to clean up the allocation + * by avformat_new_stream(). + * + * @param s media file handle + * @param c unused, does nothing + * + * @return newly created stream or NULL on error. + */ +AVStream *avformat_new_stream(AVFormatContext *s, const struct AVCodec *c); + +/** + * Add an already allocated stream to a stream group. + * + * When demuxing, it may be called by the demuxer in read_header(). If the + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also + * be called in read_packet(). + * + * When muxing, may be called by the user before avformat_write_header() after + * having allocated a new group with avformat_stream_group_create() and stream with + * avformat_new_stream(). + * + * User is required to call avformat_free_context() to clean up the allocation + * by avformat_stream_group_add_stream(). + * + * @param stg stream group belonging to a media file. + * @param st stream in the media file to add to the group. + * + * @retval 0 success + * @retval AVERROR(EEXIST) the stream was already in the group + * @retval "another negative error code" legitimate errors + * + * @see avformat_new_stream, avformat_stream_group_create. + */ +int avformat_stream_group_add_stream(AVStreamGroup *stg, AVStream *st); + +AVProgram *av_new_program(AVFormatContext *s, int id); + +/** + * @} + */ + + +/** + * Allocate an AVFormatContext for an output format. + * avformat_free_context() can be used to free the context and + * everything allocated by the framework within it. + * + * @param ctx pointee is set to the created format context, + * or to NULL in case of failure + * @param oformat format to use for allocating the context, if NULL + * format_name and filename are used instead + * @param format_name the name of output format to use for allocating the + * context, if NULL filename is used instead + * @param filename the name of the filename to use for allocating the + * context, may be NULL + * + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int avformat_alloc_output_context2(AVFormatContext **ctx, const AVOutputFormat *oformat, + const char *format_name, const char *filename); + +/** + * @addtogroup lavf_decoding + * @{ + */ + +/** + * Find AVInputFormat based on the short name of the input format. + */ +const AVInputFormat *av_find_input_format(const char *short_name); + +/** + * Guess the file format. + * + * @param pd data to be probed + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + */ +const AVInputFormat *av_probe_input_format(const AVProbeData *pd, int is_opened); + +/** + * Guess the file format. + * + * @param pd data to be probed + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_max A probe score larger that this is required to accept a + * detection, the variable is set to the actual detection + * score afterwards. + * If the score is <= AVPROBE_SCORE_MAX / 4 it is recommended + * to retry with a larger probe buffer. + */ +const AVInputFormat *av_probe_input_format2(const AVProbeData *pd, + int is_opened, int *score_max); + +/** + * Guess the file format. + * + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_ret The score of the best detection. + */ +const AVInputFormat *av_probe_input_format3(const AVProbeData *pd, + int is_opened, int *score_ret); + +/** + * Probe a bytestream to determine the input format. Each time a probe returns + * with a score that is too low, the probe buffer size is increased and another + * attempt is made. When the maximum probe size is reached, the input format + * with the highest score is returned. + * + * @param pb the bytestream to probe + * @param fmt the input format is put here + * @param url the url of the stream + * @param logctx the log context + * @param offset the offset within the bytestream to probe from + * @param max_probe_size the maximum probe buffer size (zero for default) + * + * @return the score in case of success, a negative value corresponding to an + * the maximal score is AVPROBE_SCORE_MAX + * AVERROR code otherwise + */ +int av_probe_input_buffer2(AVIOContext *pb, const AVInputFormat **fmt, + const char *url, void *logctx, + unsigned int offset, unsigned int max_probe_size); + +/** + * Like av_probe_input_buffer2() but returns 0 on success + */ +int av_probe_input_buffer(AVIOContext *pb, const AVInputFormat **fmt, + const char *url, void *logctx, + unsigned int offset, unsigned int max_probe_size); + +/** + * Open an input stream and read the header. The codecs are not opened. + * The stream must be closed with avformat_close_input(). + * + * @param ps Pointer to user-supplied AVFormatContext (allocated by + * avformat_alloc_context). May be a pointer to NULL, in + * which case an AVFormatContext is allocated by this + * function and written into ps. + * Note that a user-supplied AVFormatContext will be freed + * on failure and its pointer set to NULL. + * @param url URL of the stream to open. + * @param fmt If non-NULL, this parameter forces a specific input format. + * Otherwise the format is autodetected. + * @param options A dictionary filled with AVFormatContext and demuxer-private + * options. + * On return this parameter will be destroyed and replaced with + * a dict containing options that were not found. May be NULL. + * + * @return 0 on success; on failure: frees ps, sets its pointer to NULL, + * and returns a negative AVERROR. + * + * @note If you want to use custom IO, preallocate the format context and set its pb field. + */ +int avformat_open_input(AVFormatContext **ps, const char *url, + const AVInputFormat *fmt, AVDictionary **options); + +/** + * Read packets of a media file to get stream information. This + * is useful for file formats with no headers such as MPEG. This + * function also computes the real framerate in case of MPEG-2 repeat + * frame mode. + * The logical file position is not changed by this function; + * examined packets may be buffered for later processing. + * + * @param ic media file handle + * @param options If non-NULL, an ic.nb_streams long array of pointers to + * dictionaries, where i-th member contains options for + * codec corresponding to i-th stream. + * On return each dictionary will be filled with options that were not found. + * @return >=0 if OK, AVERROR_xxx on error + * + * @note this function isn't guaranteed to open all the codecs, so + * options being non-empty at return is a perfectly normal behavior. + * + * @todo Let the user decide somehow what information is needed so that + * we do not waste time getting stuff the user does not need. + */ +int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); + +/** + * Find the programs which belong to a given stream. + * + * @param ic media file handle + * @param last the last found program, the search will start after this + * program, or from the beginning if it is NULL + * @param s stream index + * + * @return the next program which belongs to s, NULL if no program is found or + * the last program is not among the programs of ic. + */ +AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s); + +void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx); + +/** + * Find the "best" stream in the file. + * The best stream is determined according to various heuristics as the most + * likely to be what the user expects. + * If the decoder parameter is non-NULL, av_find_best_stream will find the + * default decoder for the stream's codec; streams for which no decoder can + * be found are ignored. + * + * @param ic media file handle + * @param type stream type: video, audio, subtitles, etc. + * @param wanted_stream_nb user-requested stream number, + * or -1 for automatic selection + * @param related_stream try to find a stream related (eg. in the same + * program) to this one, or -1 if none + * @param decoder_ret if non-NULL, returns the decoder for the + * selected stream + * @param flags flags; none are currently defined + * + * @return the non-negative stream number in case of success, + * AVERROR_STREAM_NOT_FOUND if no stream with the requested type + * could be found, + * AVERROR_DECODER_NOT_FOUND if streams were found but no decoder + * + * @note If av_find_best_stream returns successfully and decoder_ret is not + * NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec. + */ +int av_find_best_stream(AVFormatContext *ic, + enum AVMediaType type, + int wanted_stream_nb, + int related_stream, + const struct AVCodec **decoder_ret, + int flags); + +/** + * Return the next frame of a stream. + * This function returns what is stored in the file, and does not validate + * that what is there are valid frames for the decoder. It will split what is + * stored in the file into frames and return one for each call. It will not + * omit invalid data between valid frames so as to give the decoder the maximum + * information possible for decoding. + * + * On success, the returned packet is reference-counted (pkt->buf is set) and + * valid indefinitely. The packet must be freed with av_packet_unref() when + * it is no longer needed. For video, the packet contains exactly one frame. + * For audio, it contains an integer number of frames if each frame has + * a known fixed size (e.g. PCM or ADPCM data). If the audio frames have + * a variable size (e.g. MPEG audio), then it contains one frame. + * + * pkt->pts, pkt->dts and pkt->duration are always set to correct + * values in AVStream.time_base units (and guessed if the format cannot + * provide them). pkt->pts can be AV_NOPTS_VALUE if the video format + * has B-frames, so it is better to rely on pkt->dts if you do not + * decompress the payload. + * + * @return 0 if OK, < 0 on error or end of file. On error, pkt will be blank + * (as if it came from av_packet_alloc()). + * + * @note pkt will be initialized, so it may be uninitialized, but it must not + * contain data that needs to be freed. + */ +int av_read_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Seek to the keyframe at timestamp. + * 'timestamp' in 'stream_index'. + * + * @param s media file handle + * @param stream_index If stream_index is (-1), a default stream is selected, + * and timestamp is automatically converted from + * AV_TIME_BASE units to the stream specific time_base. + * @param timestamp Timestamp in AVStream.time_base units or, if no stream + * is specified, in AV_TIME_BASE units. + * @param flags flags which select direction and seeking mode + * + * @return >= 0 on success + */ +int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, + int flags); + +/** + * Seek to timestamp ts. + * Seeking will be done so that the point from which all active streams + * can be presented successfully will be closest to ts and within min/max_ts. + * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL. + * + * If flags contain AVSEEK_FLAG_BYTE, then all timestamps are in bytes and + * are the file position (this may not be supported by all demuxers). + * If flags contain AVSEEK_FLAG_FRAME, then all timestamps are in frames + * in the stream with stream_index (this may not be supported by all demuxers). + * Otherwise all timestamps are in units of the stream selected by stream_index + * or if stream_index is -1, in AV_TIME_BASE units. + * If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as + * keyframes (this may not be supported by all demuxers). + * If flags contain AVSEEK_FLAG_BACKWARD, it is ignored. + * + * @param s media file handle + * @param stream_index index of the stream which is used as time base reference + * @param min_ts smallest acceptable timestamp + * @param ts target timestamp + * @param max_ts largest acceptable timestamp + * @param flags flags + * @return >=0 on success, error code otherwise + * + * @note This is part of the new seek API which is still under construction. + */ +int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); + +/** + * Discard all internally buffered data. This can be useful when dealing with + * discontinuities in the byte stream. Generally works only with formats that + * can resync. This includes headerless formats like MPEG-TS/TS but should also + * work with NUT, Ogg and in a limited way AVI for example. + * + * The set of streams, the detected duration, stream parameters and codecs do + * not change when calling this function. If you want a complete reset, it's + * better to open a new AVFormatContext. + * + * This does not flush the AVIOContext (s->pb). If necessary, call + * avio_flush(s->pb) before calling this function. + * + * @param s media file handle + * @return >=0 on success, error code otherwise + */ +int avformat_flush(AVFormatContext *s); + +/** + * Start playing a network-based stream (e.g. RTSP stream) at the + * current position. + */ +int av_read_play(AVFormatContext *s); + +/** + * Pause a network-based stream (e.g. RTSP stream). + * + * Use av_read_play() to resume it. + */ +int av_read_pause(AVFormatContext *s); + +/** + * Close an opened input AVFormatContext. Free it and all its contents + * and set *s to NULL. + */ +void avformat_close_input(AVFormatContext **s); +/** + * @} + */ + +#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward +#define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes +#define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes +#define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number + +/** + * @addtogroup lavf_encoding + * @{ + */ + +#define AVSTREAM_INIT_IN_WRITE_HEADER 0 ///< stream parameters initialized in avformat_write_header +#define AVSTREAM_INIT_IN_INIT_OUTPUT 1 ///< stream parameters initialized in avformat_init_output + +/** + * Allocate the stream private data and write the stream header to + * an output media file. + * + * @param s Media file handle, must be allocated with + * avformat_alloc_context(). + * Its \ref AVFormatContext.oformat "oformat" field must be set + * to the desired output format; + * Its \ref AVFormatContext.pb "pb" field must be set to an + * already opened ::AVIOContext. + * @param options An ::AVDictionary filled with AVFormatContext and + * muxer-private options. + * On return this parameter will be destroyed and replaced with + * a dict containing options that were not found. May be NULL. + * + * @retval AVSTREAM_INIT_IN_WRITE_HEADER On success, if the codec had not already been + * fully initialized in avformat_init_output(). + * @retval AVSTREAM_INIT_IN_INIT_OUTPUT On success, if the codec had already been fully + * initialized in avformat_init_output(). + * @retval AVERROR A negative AVERROR on failure. + * + * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_init_output. + */ +av_warn_unused_result +int avformat_write_header(AVFormatContext *s, AVDictionary **options); + +/** + * Allocate the stream private data and initialize the codec, but do not write the header. + * May optionally be used before avformat_write_header() to initialize stream parameters + * before actually writing the header. + * If using this function, do not pass the same options to avformat_write_header(). + * + * @param s Media file handle, must be allocated with + * avformat_alloc_context(). + * Its \ref AVFormatContext.oformat "oformat" field must be set + * to the desired output format; + * Its \ref AVFormatContext.pb "pb" field must be set to an + * already opened ::AVIOContext. + * @param options An ::AVDictionary filled with AVFormatContext and + * muxer-private options. + * On return this parameter will be destroyed and replaced with + * a dict containing options that were not found. May be NULL. + * + * @retval AVSTREAM_INIT_IN_WRITE_HEADER On success, if the codec requires + * avformat_write_header to fully initialize. + * @retval AVSTREAM_INIT_IN_INIT_OUTPUT On success, if the codec has been fully + * initialized. + * @retval AVERROR Anegative AVERROR on failure. + * + * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_write_header. + */ +av_warn_unused_result +int avformat_init_output(AVFormatContext *s, AVDictionary **options); + +/** + * Write a packet to an output media file. + * + * This function passes the packet directly to the muxer, without any buffering + * or reordering. The caller is responsible for correctly interleaving the + * packets if the format requires it. Callers that want libavformat to handle + * the interleaving should call av_interleaved_write_frame() instead of this + * function. + * + * @param s media file handle + * @param pkt The packet containing the data to be written. Note that unlike + * av_interleaved_write_frame(), this function does not take + * ownership of the packet passed to it (though some muxers may make + * an internal reference to the input packet). + *
+ * This parameter can be NULL (at any time, not just at the end), in + * order to immediately flush data buffered within the muxer, for + * muxers that buffer up data internally before writing it to the + * output. + *
+ * Packet's @ref AVPacket.stream_index "stream_index" field must be + * set to the index of the corresponding stream in @ref + * AVFormatContext.streams "s->streams". + *
+ * The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts") + * must be set to correct values in the stream's timebase (unless the + * output format is flagged with the AVFMT_NOTIMESTAMPS flag, then + * they can be set to AV_NOPTS_VALUE). + * The dts for subsequent packets passed to this function must be strictly + * increasing when compared in their respective timebases (unless the + * output format is flagged with the AVFMT_TS_NONSTRICT, then they + * merely have to be nondecreasing). @ref AVPacket.duration + * "duration") should also be set if known. + * @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush + * + * @see av_interleaved_write_frame() + */ +int av_write_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Write a packet to an output media file ensuring correct interleaving. + * + * This function will buffer the packets internally as needed to make sure the + * packets in the output file are properly interleaved, usually ordered by + * increasing dts. Callers doing their own interleaving should call + * av_write_frame() instead of this function. + * + * Using this function instead of av_write_frame() can give muxers advance + * knowledge of future packets, improving e.g. the behaviour of the mp4 + * muxer for VFR content in fragmenting mode. + * + * @param s media file handle + * @param pkt The packet containing the data to be written. + *
+ * If the packet is reference-counted, this function will take + * ownership of this reference and unreference it later when it sees + * fit. If the packet is not reference-counted, libavformat will + * make a copy. + * The returned packet will be blank (as if returned from + * av_packet_alloc()), even on error. + *
+ * This parameter can be NULL (at any time, not just at the end), to + * flush the interleaving queues. + *
+ * Packet's @ref AVPacket.stream_index "stream_index" field must be + * set to the index of the corresponding stream in @ref + * AVFormatContext.streams "s->streams". + *
+ * The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts") + * must be set to correct values in the stream's timebase (unless the + * output format is flagged with the AVFMT_NOTIMESTAMPS flag, then + * they can be set to AV_NOPTS_VALUE). + * The dts for subsequent packets in one stream must be strictly + * increasing (unless the output format is flagged with the + * AVFMT_TS_NONSTRICT, then they merely have to be nondecreasing). + * @ref AVPacket.duration "duration" should also be set if known. + * + * @return 0 on success, a negative AVERROR on error. + * + * @see av_write_frame(), AVFormatContext.max_interleave_delta + */ +int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt); + +/** + * Write an uncoded frame to an output media file. + * + * The frame must be correctly interleaved according to the container + * specification; if not, av_interleaved_write_uncoded_frame() must be used. + * + * See av_interleaved_write_uncoded_frame() for details. + */ +int av_write_uncoded_frame(AVFormatContext *s, int stream_index, + struct AVFrame *frame); + +/** + * Write an uncoded frame to an output media file. + * + * If the muxer supports it, this function makes it possible to write an AVFrame + * structure directly, without encoding it into a packet. + * It is mostly useful for devices and similar special muxers that use raw + * video or PCM data and will not serialize it into a byte stream. + * + * To test whether it is possible to use it with a given muxer and stream, + * use av_write_uncoded_frame_query(). + * + * The caller gives up ownership of the frame and must not access it + * afterwards. + * + * @return >=0 for success, a negative code on error + */ +int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index, + struct AVFrame *frame); + +/** + * Test whether a muxer supports uncoded frame. + * + * @return >=0 if an uncoded frame can be written to that muxer and stream, + * <0 if not + */ +int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index); + +/** + * Write the stream trailer to an output media file and free the + * file private data. + * + * May only be called after a successful call to avformat_write_header. + * + * @param s media file handle + * @return 0 if OK, AVERROR_xxx on error + */ +int av_write_trailer(AVFormatContext *s); + +/** + * Return the output format in the list of registered output formats + * which best matches the provided parameters, or return NULL if + * there is no match. + * + * @param short_name if non-NULL checks if short_name matches with the + * names of the registered formats + * @param filename if non-NULL checks if filename terminates with the + * extensions of the registered formats + * @param mime_type if non-NULL checks if mime_type matches with the + * MIME type of the registered formats + */ +const AVOutputFormat *av_guess_format(const char *short_name, + const char *filename, + const char *mime_type); + +/** + * Guess the codec ID based upon muxer and filename. + */ +enum AVCodecID av_guess_codec(const AVOutputFormat *fmt, const char *short_name, + const char *filename, const char *mime_type, + enum AVMediaType type); + +/** + * Get timing information for the data currently output. + * The exact meaning of "currently output" depends on the format. + * It is mostly relevant for devices that have an internal buffer and/or + * work in real time. + * @param s media file handle + * @param stream stream in the media file + * @param[out] dts DTS of the last packet output for the stream, in stream + * time_base units + * @param[out] wall absolute time when that packet whas output, + * in microsecond + * @retval 0 Success + * @retval AVERROR(ENOSYS) The format does not support it + * + * @note Some formats or devices may not allow to measure dts and wall + * atomically. + */ +int av_get_output_timestamp(struct AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall); + + +/** + * @} + */ + + +/** + * @defgroup lavf_misc Utility functions + * @ingroup libavf + * @{ + * + * Miscellaneous utility functions related to both muxing and demuxing + * (or neither). + */ + +/** + * Send a nice hexadecimal dump of a buffer to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump_log, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump(FILE *f, const uint8_t *buf, int size); + +/** + * Send a nice hexadecimal dump of a buffer to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size); + +/** + * Send a nice dump of a packet to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st); + + +/** + * Send a nice dump of a packet to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload, + const AVStream *st); + +/** + * Get the AVCodecID for the given codec tag tag. + * If no codec id is found returns AV_CODEC_ID_NONE. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param tag codec tag to match to a codec ID + */ +enum AVCodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned int tag); + +/** + * Get the codec tag for the given codec id id. + * If no codec tag is found returns 0. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param id codec ID to match to a codec tag + */ +unsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum AVCodecID id); + +/** + * Get the codec tag for the given codec id. + * + * @param tags list of supported codec_id - codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + * @param id codec id that should be searched for in the list + * @param tag A pointer to the found tag + * @return 0 if id was not found in tags, > 0 if it was found + */ +int av_codec_get_tag2(const struct AVCodecTag * const *tags, enum AVCodecID id, + unsigned int *tag); + +int av_find_default_stream_index(AVFormatContext *s); + +/** + * Get the index for a specific timestamp. + * + * @param st stream that the timestamp belongs to + * @param timestamp timestamp to retrieve the index for + * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond + * to the timestamp which is <= the requested one, if backward + * is 0, then it will be >= + * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise + * @return < 0 if no such timestamp could be found + */ +int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags); + +/** + * Get the index entry count for the given AVStream. + * + * @param st stream + * @return the number of index entries in the stream + */ +int avformat_index_get_entries_count(const AVStream *st); + +/** + * Get the AVIndexEntry corresponding to the given index. + * + * @param st Stream containing the requested AVIndexEntry. + * @param idx The desired index. + * @return A pointer to the requested AVIndexEntry if it exists, NULL otherwise. + * + * @note The pointer returned by this function is only guaranteed to be valid + * until any function that takes the stream or the parent AVFormatContext + * as input argument is called. + */ +const AVIndexEntry *avformat_index_get_entry(AVStream *st, int idx); + +/** + * Get the AVIndexEntry corresponding to the given timestamp. + * + * @param st Stream containing the requested AVIndexEntry. + * @param wanted_timestamp Timestamp to retrieve the index entry for. + * @param flags If AVSEEK_FLAG_BACKWARD then the returned entry will correspond + * to the timestamp which is <= the requested one, if backward + * is 0, then it will be >= + * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise. + * @return A pointer to the requested AVIndexEntry if it exists, NULL otherwise. + * + * @note The pointer returned by this function is only guaranteed to be valid + * until any function that takes the stream or the parent AVFormatContext + * as input argument is called. + */ +const AVIndexEntry *avformat_index_get_entry_from_timestamp(AVStream *st, + int64_t wanted_timestamp, + int flags); +/** + * Add an index entry into a sorted list. Update the entry if the list + * already contains it. + * + * @param timestamp timestamp in the time base of the given stream + */ +int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, + int size, int distance, int flags); + + +/** + * Split a URL string into components. + * + * The pointers to buffers for storing individual components may be null, + * in order to ignore that component. Buffers for components not found are + * set to empty strings. If the port is not found, it is set to a negative + * value. + * + * @param proto the buffer for the protocol + * @param proto_size the size of the proto buffer + * @param authorization the buffer for the authorization + * @param authorization_size the size of the authorization buffer + * @param hostname the buffer for the host name + * @param hostname_size the size of the hostname buffer + * @param port_ptr a pointer to store the port number in + * @param path the buffer for the path + * @param path_size the size of the path buffer + * @param url the URL to split + */ +void av_url_split(char *proto, int proto_size, + char *authorization, int authorization_size, + char *hostname, int hostname_size, + int *port_ptr, + char *path, int path_size, + const char *url); + + +/** + * Print detailed information about the input or output format, such as + * duration, bitrate, streams, container, programs, metadata, side data, + * codec and time base. + * + * @param ic the context to analyze + * @param index index of the stream to dump information about + * @param url the URL to print, such as source or destination file + * @param is_output Select whether the specified context is an input(0) or output(1) + */ +void av_dump_format(AVFormatContext *ic, + int index, + const char *url, + int is_output); + + +#define AV_FRAME_FILENAME_FLAGS_MULTIPLE 1 ///< Allow multiple %d + +/** + * Return in 'buf' the path with '%d' replaced by a number. + * + * Also handles the '%0nd' format where 'n' is the total number + * of digits and '%%'. + * + * @param buf destination buffer + * @param buf_size destination buffer size + * @param path numbered sequence string + * @param number frame number + * @param flags AV_FRAME_FILENAME_FLAGS_* + * @return 0 if OK, -1 on format error + */ +int av_get_frame_filename2(char *buf, int buf_size, + const char *path, int number, int flags); + +int av_get_frame_filename(char *buf, int buf_size, + const char *path, int number); + +/** + * Check whether filename actually is a numbered sequence generator. + * + * @param filename possible numbered sequence string + * @return 1 if a valid numbered sequence string, 0 otherwise + */ +int av_filename_number_test(const char *filename); + +/** + * Generate an SDP for an RTP session. + * + * Note, this overwrites the id values of AVStreams in the muxer contexts + * for getting unique dynamic payload types. + * + * @param ac array of AVFormatContexts describing the RTP streams. If the + * array is composed by only one context, such context can contain + * multiple AVStreams (one AVStream per RTP stream). Otherwise, + * all the contexts in the array (an AVCodecContext per RTP stream) + * must contain only one AVStream. + * @param n_files number of AVCodecContexts contained in ac + * @param buf buffer where the SDP will be stored (must be allocated by + * the caller) + * @param size the size of the buffer + * @return 0 if OK, AVERROR_xxx on error + */ +int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size); + +/** + * Return a positive value if the given filename has one of the given + * extensions, 0 otherwise. + * + * @param filename file name to check against the given extensions + * @param extensions a comma-separated list of filename extensions + */ +int av_match_ext(const char *filename, const char *extensions); + +/** + * Test if the given container can store a codec. + * + * @param ofmt container to check for compatibility + * @param codec_id codec to potentially store in container + * @param std_compliance standards compliance level, one of FF_COMPLIANCE_* + * + * @return 1 if codec with ID codec_id can be stored in ofmt, 0 if it cannot. + * A negative number if this information is not available. + */ +int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id, + int std_compliance); + +/** + * @defgroup riff_fourcc RIFF FourCCs + * @{ + * Get the tables mapping RIFF FourCCs to libavcodec AVCodecIDs. The tables are + * meant to be passed to av_codec_get_id()/av_codec_get_tag() as in the + * following code: + * @code + * uint32_t tag = MKTAG('H', '2', '6', '4'); + * const struct AVCodecTag *table[] = { avformat_get_riff_video_tags(), 0 }; + * enum AVCodecID id = av_codec_get_id(table, tag); + * @endcode + */ +/** + * @return the table mapping RIFF FourCCs for video to libavcodec AVCodecID. + */ +const struct AVCodecTag *avformat_get_riff_video_tags(void); +/** + * @return the table mapping RIFF FourCCs for audio to AVCodecID. + */ +const struct AVCodecTag *avformat_get_riff_audio_tags(void); +/** + * @return the table mapping MOV FourCCs for video to libavcodec AVCodecID. + */ +const struct AVCodecTag *avformat_get_mov_video_tags(void); +/** + * @return the table mapping MOV FourCCs for audio to AVCodecID. + */ +const struct AVCodecTag *avformat_get_mov_audio_tags(void); + +/** + * @} + */ + +/** + * Guess the sample aspect ratio of a frame, based on both the stream and the + * frame aspect ratio. + * + * Since the frame aspect ratio is set by the codec but the stream aspect ratio + * is set by the demuxer, these two may not be equal. This function tries to + * return the value that you should use if you would like to display the frame. + * + * Basic logic is to use the stream aspect ratio if it is set to something sane + * otherwise use the frame aspect ratio. This way a container setting, which is + * usually easy to modify can override the coded value in the frames. + * + * @param format the format context which the stream is part of + * @param stream the stream which the frame is part of + * @param frame the frame with the aspect ratio to be determined + * @return the guessed (valid) sample_aspect_ratio, 0/1 if no idea + */ +AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, + struct AVFrame *frame); + +/** + * Guess the frame rate, based on both the container and codec information. + * + * @param ctx the format context which the stream is part of + * @param stream the stream which the frame is part of + * @param frame the frame for which the frame rate should be determined, may be NULL + * @return the guessed (valid) frame rate, 0/1 if no idea + */ +AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, + struct AVFrame *frame); + +/** + * Check if the stream st contained in s is matched by the stream specifier + * spec. + * + * See the "stream specifiers" chapter in the documentation for the syntax + * of spec. + * + * @return >0 if st is matched by spec; + * 0 if st is not matched by spec; + * AVERROR code if spec is invalid + * + * @note A stream specifier can match several streams in the format. + */ +int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, + const char *spec); + +int avformat_queue_attached_pictures(AVFormatContext *s); + +#if FF_API_INTERNAL_TIMING +enum AVTimebaseSource { + AVFMT_TBCF_AUTO = -1, + AVFMT_TBCF_DECODER, + AVFMT_TBCF_DEMUXER, +#if FF_API_R_FRAME_RATE + AVFMT_TBCF_R_FRAMERATE, +#endif +}; + +/** + * @deprecated do not call this function + */ +attribute_deprecated +int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, + AVStream *ost, const AVStream *ist, + enum AVTimebaseSource copy_tb); + +/** + * @deprecated do not call this function + */ +attribute_deprecated +AVRational av_stream_get_codec_timebase(const AVStream *st); +#endif + + +/** + * @} + */ + +#endif /* AVFORMAT_AVFORMAT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavformat/avio.h b/src/framework/media/thirdparty/ffmpeg/v8/libavformat/avio.h new file mode 100644 index 0000000000000..ebf611187dcf4 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavformat/avio.h @@ -0,0 +1,831 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef AVFORMAT_AVIO_H +#define AVFORMAT_AVIO_H + +/** + * @file + * @ingroup lavf_io + * Buffered I/O operations + */ + +#include +#include + +#include "libavutil/attributes.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" + +#include "libavformat/version_major.h" + +/** + * Seeking works like for a local file. + */ +#define AVIO_SEEKABLE_NORMAL (1 << 0) + +/** + * Seeking by timestamp with avio_seek_time() is possible. + */ +#define AVIO_SEEKABLE_TIME (1 << 1) + +/** + * Callback for checking whether to abort blocking functions. + * AVERROR_EXIT is returned in this case by the interrupted + * function. During blocking operations, callback is called with + * opaque as parameter. If the callback returns 1, the + * blocking operation will be aborted. + * + * No members can be added to this struct without a major bump, if + * new elements have been added after this struct in AVFormatContext + * or AVIOContext. + */ +typedef struct AVIOInterruptCB { + int (*callback)(void*); + void *opaque; +} AVIOInterruptCB; + +/** + * Directory entry types. + */ +enum AVIODirEntryType { + AVIO_ENTRY_UNKNOWN, + AVIO_ENTRY_BLOCK_DEVICE, + AVIO_ENTRY_CHARACTER_DEVICE, + AVIO_ENTRY_DIRECTORY, + AVIO_ENTRY_NAMED_PIPE, + AVIO_ENTRY_SYMBOLIC_LINK, + AVIO_ENTRY_SOCKET, + AVIO_ENTRY_FILE, + AVIO_ENTRY_SERVER, + AVIO_ENTRY_SHARE, + AVIO_ENTRY_WORKGROUP, +}; + +/** + * Describes single entry of the directory. + * + * Only name and type fields are guaranteed be set. + * Rest of fields are protocol or/and platform dependent and might be unknown. + */ +typedef struct AVIODirEntry { + char *name; /**< Filename */ + int type; /**< Type of the entry */ + int utf8; /**< Set to 1 when name is encoded with UTF-8, 0 otherwise. + Name can be encoded with UTF-8 even though 0 is set. */ + int64_t size; /**< File size in bytes, -1 if unknown. */ + int64_t modification_timestamp; /**< Time of last modification in microseconds since unix + epoch, -1 if unknown. */ + int64_t access_timestamp; /**< Time of last access in microseconds since unix epoch, + -1 if unknown. */ + int64_t status_change_timestamp; /**< Time of last status change in microseconds since unix + epoch, -1 if unknown. */ + int64_t user_id; /**< User ID of owner, -1 if unknown. */ + int64_t group_id; /**< Group ID of owner, -1 if unknown. */ + int64_t filemode; /**< Unix file mode, -1 if unknown. */ +} AVIODirEntry; + +typedef struct AVIODirContext AVIODirContext; + +/** + * Different data types that can be returned via the AVIO + * write_data_type callback. + */ +enum AVIODataMarkerType { + /** + * Header data; this needs to be present for the stream to be decodeable. + */ + AVIO_DATA_MARKER_HEADER, + /** + * A point in the output bytestream where a decoder can start decoding + * (i.e. a keyframe). A demuxer/decoder given the data flagged with + * AVIO_DATA_MARKER_HEADER, followed by any AVIO_DATA_MARKER_SYNC_POINT, + * should give decodeable results. + */ + AVIO_DATA_MARKER_SYNC_POINT, + /** + * A point in the output bytestream where a demuxer can start parsing + * (for non self synchronizing bytestream formats). That is, any + * non-keyframe packet start point. + */ + AVIO_DATA_MARKER_BOUNDARY_POINT, + /** + * This is any, unlabelled data. It can either be a muxer not marking + * any positions at all, it can be an actual boundary/sync point + * that the muxer chooses not to mark, or a later part of a packet/fragment + * that is cut into multiple write callbacks due to limited IO buffer size. + */ + AVIO_DATA_MARKER_UNKNOWN, + /** + * Trailer data, which doesn't contain actual content, but only for + * finalizing the output file. + */ + AVIO_DATA_MARKER_TRAILER, + /** + * A point in the output bytestream where the underlying AVIOContext might + * flush the buffer depending on latency or buffering requirements. Typically + * means the end of a packet. + */ + AVIO_DATA_MARKER_FLUSH_POINT, +}; + +/** + * Bytestream IO Context. + * New public fields can be added with minor version bumps. + * Removal, reordering and changes to existing public fields require + * a major version bump. + * sizeof(AVIOContext) must not be used outside libav*. + * + * @note None of the function pointers in AVIOContext should be called + * directly, they should only be set by the client application + * when implementing custom I/O. Normally these are set to the + * function pointers specified in avio_alloc_context() + */ +typedef struct AVIOContext { + /** + * A class for private options. + * + * If this AVIOContext is created by avio_open2(), av_class is set and + * passes the options down to protocols. + * + * If this AVIOContext is manually allocated, then av_class may be set by + * the caller. + * + * warning -- this field can be NULL, be sure to not pass this AVIOContext + * to any av_opt_* functions in that case. + */ + const AVClass *av_class; + + /* + * The following shows the relationship between buffer, buf_ptr, + * buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing + * (since AVIOContext is used for both): + * + ********************************************************************************** + * READING + ********************************************************************************** + * + * | buffer_size | + * |---------------------------------------| + * | | + * + * buffer buf_ptr buf_end + * +---------------+-----------------------+ + * |/ / / / / / / /|/ / / / / / /| | + * read buffer: |/ / consumed / | to be read /| | + * |/ / / / / / / /|/ / / / / / /| | + * +---------------+-----------------------+ + * + * pos + * +-------------------------------------------+-----------------+ + * input file: | | | + * +-------------------------------------------+-----------------+ + * + * + ********************************************************************************** + * WRITING + ********************************************************************************** + * + * | buffer_size | + * |--------------------------------------| + * | | + * + * buf_ptr_max + * buffer (buf_ptr) buf_end + * +-----------------------+--------------+ + * |/ / / / / / / / / / / /| | + * write buffer: | / / to be flushed / / | | + * |/ / / / / / / / / / / /| | + * +-----------------------+--------------+ + * buf_ptr can be in this + * due to a backward seek + * + * pos + * +-------------+----------------------------------------------+ + * output file: | | | + * +-------------+----------------------------------------------+ + * + */ + unsigned char *buffer; /**< Start of the buffer. */ + int buffer_size; /**< Maximum buffer size */ + unsigned char *buf_ptr; /**< Current position in the buffer */ + unsigned char *buf_end; /**< End of the data, may be less than + buffer+buffer_size if the read function returned + less data than requested, e.g. for streams where + no more data has been received yet. */ + void *opaque; /**< A private pointer, passed to the read/write/seek/... + functions. */ + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size); + int (*write_packet)(void *opaque, const uint8_t *buf, int buf_size); + int64_t (*seek)(void *opaque, int64_t offset, int whence); + int64_t pos; /**< position in the file of the current buffer */ + int eof_reached; /**< true if was unable to read due to error or eof */ + int error; /**< contains the error code or 0 if no error happened */ + int write_flag; /**< true if open for writing */ + int max_packet_size; + int min_packet_size; /**< Try to buffer at least this amount of data + before flushing it. */ + unsigned long checksum; + unsigned char *checksum_ptr; + unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size); + /** + * Pause or resume playback for network streaming protocols - e.g. MMS. + */ + int (*read_pause)(void *opaque, int pause); + /** + * Seek to a given timestamp in stream with the specified stream_index. + * Needed for some network streaming protocols which don't support seeking + * to byte position. + */ + int64_t (*read_seek)(void *opaque, int stream_index, + int64_t timestamp, int flags); + /** + * A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable. + */ + int seekable; + + /** + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ + int direct; + + /** + * ',' separated list of allowed protocols. + */ + const char *protocol_whitelist; + + /** + * ',' separated list of disallowed protocols. + */ + const char *protocol_blacklist; + + /** + * A callback that is used instead of write_packet. + */ + int (*write_data_type)(void *opaque, const uint8_t *buf, int buf_size, + enum AVIODataMarkerType type, int64_t time); + /** + * If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT, + * but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly + * small chunks of data returned from the callback). + */ + int ignore_boundary_point; + + /** + * Maximum reached position before a backward seek in the write buffer, + * used keeping track of already written data for a later flush. + */ + unsigned char *buf_ptr_max; + + /** + * Read-only statistic of bytes read for this AVIOContext. + */ + int64_t bytes_read; + + /** + * Read-only statistic of bytes written for this AVIOContext. + */ + int64_t bytes_written; +} AVIOContext; + +/** + * Return the name of the protocol that will handle the passed URL. + * + * NULL is returned if no protocol could be found for the given URL. + * + * @return Name of the protocol or NULL. + */ +const char *avio_find_protocol_name(const char *url); + +/** + * Return AVIO_FLAG_* access flags corresponding to the access permissions + * of the resource in url, or a negative value corresponding to an + * AVERROR code in case of failure. The returned access flags are + * masked by the value in flags. + * + * @note This function is intrinsically unsafe, in the sense that the + * checked resource may change its existence or permission status from + * one call to another. Thus you should not trust the returned value, + * unless you are sure that no other processes are accessing the + * checked resource. + */ +int avio_check(const char *url, int flags); + +/** + * Open directory for reading. + * + * @param s directory read context. Pointer to a NULL pointer must be passed. + * @param url directory to be listed. + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dictionary + * containing options that were not found. May be NULL. + * @return >=0 on success or negative on error. + */ +int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options); + +/** + * Get next directory entry. + * + * Returned entry must be freed with avio_free_directory_entry(). In particular + * it may outlive AVIODirContext. + * + * @param s directory read context. + * @param[out] next next entry or NULL when no more entries. + * @return >=0 on success or negative on error. End of list is not considered an + * error. + */ +int avio_read_dir(AVIODirContext *s, AVIODirEntry **next); + +/** + * Close directory. + * + * @note Entries created using avio_read_dir() are not deleted and must be + * freeded with avio_free_directory_entry(). + * + * @param s directory read context. + * @return >=0 on success or negative on error. + */ +int avio_close_dir(AVIODirContext **s); + +/** + * Free entry allocated by avio_read_dir(). + * + * @param entry entry to be freed. + */ +void avio_free_directory_entry(AVIODirEntry **entry); + +/** + * Allocate and initialize an AVIOContext for buffered I/O. It must be later + * freed with avio_context_free(). + * + * @param buffer Memory block for input/output operations via AVIOContext. + * The buffer must be allocated with av_malloc() and friends. + * It may be freed and replaced with a new buffer by libavformat. + * AVIOContext.buffer holds the buffer currently in use, + * which must be later freed with av_free(). + * @param buffer_size The buffer size is very important for performance. + * For protocols with fixed blocksize it should be set to this blocksize. + * For others a typical size is a cache page, e.g. 4kb. + * @param write_flag Set to 1 if the buffer should be writable, 0 otherwise. + * @param opaque An opaque pointer to user-specific data. + * @param read_packet A function for refilling the buffer, may be NULL. + * For stream protocols, must never return 0 but rather + * a proper AVERROR code. + * @param write_packet A function for writing the buffer contents, may be NULL. + * The function may not change the input buffers content. + * @param seek A function for seeking to specified byte position, may be NULL. + * + * @return Allocated AVIOContext or NULL on failure. + */ +AVIOContext *avio_alloc_context( + unsigned char *buffer, + int buffer_size, + int write_flag, + void *opaque, + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), + int (*write_packet)(void *opaque, const uint8_t *buf, int buf_size), + int64_t (*seek)(void *opaque, int64_t offset, int whence)); + +/** + * Free the supplied IO context and everything associated with it. + * + * @param s Double pointer to the IO context. This function will write NULL + * into s. + */ +void avio_context_free(AVIOContext **s); + +void avio_w8(AVIOContext *s, int b); +void avio_write(AVIOContext *s, const unsigned char *buf, int size); +void avio_wl64(AVIOContext *s, uint64_t val); +void avio_wb64(AVIOContext *s, uint64_t val); +void avio_wl32(AVIOContext *s, unsigned int val); +void avio_wb32(AVIOContext *s, unsigned int val); +void avio_wl24(AVIOContext *s, unsigned int val); +void avio_wb24(AVIOContext *s, unsigned int val); +void avio_wl16(AVIOContext *s, unsigned int val); +void avio_wb16(AVIOContext *s, unsigned int val); + +/** + * Write a NULL-terminated string. + * @return number of bytes written. + */ +int avio_put_str(AVIOContext *s, const char *str); + +/** + * Convert an UTF-8 string to UTF-16LE and write it. + * @param s the AVIOContext + * @param str NULL-terminated UTF-8 string + * + * @return number of bytes written. + */ +int avio_put_str16le(AVIOContext *s, const char *str); + +/** + * Convert an UTF-8 string to UTF-16BE and write it. + * @param s the AVIOContext + * @param str NULL-terminated UTF-8 string + * + * @return number of bytes written. + */ +int avio_put_str16be(AVIOContext *s, const char *str); + +/** + * Mark the written bytestream as a specific type. + * + * Zero-length ranges are omitted from the output. + * + * @param s the AVIOContext + * @param time the stream time the current bytestream pos corresponds to + * (in AV_TIME_BASE units), or AV_NOPTS_VALUE if unknown or not + * applicable + * @param type the kind of data written starting at the current pos + */ +void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type); + +/** + * ORing this as the "whence" parameter to a seek function causes it to + * return the filesize without seeking anywhere. Supporting this is optional. + * If it is not supported then the seek function will return <0. + */ +#define AVSEEK_SIZE 0x10000 + +/** + * Passing this flag as the "whence" parameter to a seek function causes it to + * seek by any means (like reopening and linear reading) or other normally unreasonable + * means that can be extremely slow. + * This may be ignored by the seek code. + */ +#define AVSEEK_FORCE 0x20000 + +/** + * fseek() equivalent for AVIOContext. + * @return new position or AVERROR. + */ +int64_t avio_seek(AVIOContext *s, int64_t offset, int whence); + +/** + * Skip given number of bytes forward + * @return new position or AVERROR. + */ +int64_t avio_skip(AVIOContext *s, int64_t offset); + +/** + * ftell() equivalent for AVIOContext. + * @return position or AVERROR. + */ +static av_always_inline int64_t avio_tell(AVIOContext *s) +{ + return avio_seek(s, 0, SEEK_CUR); +} + +/** + * Get the filesize. + * @return filesize or AVERROR + */ +int64_t avio_size(AVIOContext *s); + +/** + * Similar to feof() but also returns nonzero on read errors. + * @return non zero if and only if at end of file or a read error happened when reading. + */ +int avio_feof(AVIOContext *s); + +/** + * Writes a formatted string to the context taking a va_list. + * @return number of bytes written, < 0 on error. + */ +int avio_vprintf(AVIOContext *s, const char *fmt, va_list ap); + +/** + * Writes a formatted string to the context. + * @return number of bytes written, < 0 on error. + */ +int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3); + +/** + * Write a NULL terminated array of strings to the context. + * Usually you don't need to use this function directly but its macro wrapper, + * avio_print. + */ +void avio_print_string_array(AVIOContext *s, const char * const strings[]); + +/** + * Write strings (const char *) to the context. + * This is a convenience macro around avio_print_string_array and it + * automatically creates the string array from the variable argument list. + * For simple string concatenations this function is more performant than using + * avio_printf since it does not need a temporary buffer. + */ +#define avio_print(s, ...) \ + avio_print_string_array(s, (const char*[]){__VA_ARGS__, NULL}) + +/** + * Force flushing of buffered data. + * + * For write streams, force the buffered data to be immediately written to the output, + * without to wait to fill the internal buffer. + * + * For read streams, discard all currently buffered data, and advance the + * reported file position to that of the underlying stream. This does not + * read new data, and does not perform any seeks. + */ +void avio_flush(AVIOContext *s); + +/** + * Read size bytes from AVIOContext into buf. + * @return number of bytes read or AVERROR + */ +int avio_read(AVIOContext *s, unsigned char *buf, int size); + +/** + * Read size bytes from AVIOContext into buf. Unlike avio_read(), this is allowed + * to read fewer bytes than requested. The missing bytes can be read in the next + * call. This always tries to read at least 1 byte. + * Useful to reduce latency in certain cases. + * @return number of bytes read or AVERROR + */ +int avio_read_partial(AVIOContext *s, unsigned char *buf, int size); + +/** + * @name Functions for reading from AVIOContext + * @{ + * + * @note return 0 if EOF, so you cannot use it if EOF handling is + * necessary + */ +int avio_r8 (AVIOContext *s); +unsigned int avio_rl16(AVIOContext *s); +unsigned int avio_rl24(AVIOContext *s); +unsigned int avio_rl32(AVIOContext *s); +uint64_t avio_rl64(AVIOContext *s); +unsigned int avio_rb16(AVIOContext *s); +unsigned int avio_rb24(AVIOContext *s); +unsigned int avio_rb32(AVIOContext *s); +uint64_t avio_rb64(AVIOContext *s); +/** + * @} + */ + +/** + * Read a string from pb into buf. The reading will terminate when either + * a NULL character was encountered, maxlen bytes have been read, or nothing + * more can be read from pb. The result is guaranteed to be NULL-terminated, it + * will be truncated if buf is too small. + * Note that the string is not interpreted or validated in any way, it + * might get truncated in the middle of a sequence for multi-byte encodings. + * + * @return number of bytes read (is always <= maxlen). + * If reading ends on EOF or error, the return value will be one more than + * bytes actually read. + */ +int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen); + +/** + * Read a UTF-16 string from pb and convert it to UTF-8. + * The reading will terminate when either a null or invalid character was + * encountered or maxlen bytes have been read. + * @return number of bytes read (is always <= maxlen) + */ +int avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen); +int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen); + + +/** + * @name URL open modes + * The flags argument to avio_open must be one of the following + * constants, optionally ORed with other flags. + * @{ + */ +#define AVIO_FLAG_READ 1 /**< read-only */ +#define AVIO_FLAG_WRITE 2 /**< write-only */ +#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE) /**< read-write pseudo flag */ +/** + * @} + */ + +/** + * Use non-blocking mode. + * If this flag is set, operations on the context will return + * AVERROR(EAGAIN) if they can not be performed immediately. + * If this flag is not set, operations on the context will never return + * AVERROR(EAGAIN). + * Note that this flag does not affect the opening/connecting of the + * context. Connecting a protocol will always block if necessary (e.g. on + * network protocols) but never hang (e.g. on busy devices). + * Warning: non-blocking protocols is work-in-progress; this flag may be + * silently ignored. + */ +#define AVIO_FLAG_NONBLOCK 8 + +/** + * Use direct mode. + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ +#define AVIO_FLAG_DIRECT 0x8000 + +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param url resource to access + * @param flags flags which control how the resource indicated by url + * is to be opened + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open(AVIOContext **s, const char *url, int flags); + +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param url resource to access + * @param flags flags which control how the resource indicated by url + * is to be opened + * @param int_cb an interrupt callback to be used at the protocols level + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dict containing options + * that were not found. May be NULL. + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open2(AVIOContext **s, const char *url, int flags, + const AVIOInterruptCB *int_cb, AVDictionary **options); + +/** + * Close the resource accessed by the AVIOContext s and free it. + * This function can only be used if s was opened by avio_open(). + * + * The internal buffer is automatically flushed before closing the + * resource. + * + * @return 0 on success, an AVERROR < 0 on error. + * @see avio_closep + */ +int avio_close(AVIOContext *s); + +/** + * Close the resource accessed by the AVIOContext *s, free it + * and set the pointer pointing to it to NULL. + * This function can only be used if s was opened by avio_open(). + * + * The internal buffer is automatically flushed before closing the + * resource. + * + * @return 0 on success, an AVERROR < 0 on error. + * @see avio_close + */ +int avio_closep(AVIOContext **s); + + +/** + * Open a write only memory stream. + * + * @param s new IO context + * @return zero if no error. + */ +int avio_open_dyn_buf(AVIOContext **s); + +/** + * Return the written size and a pointer to the buffer. + * The AVIOContext stream is left intact. + * The buffer must NOT be freed. + * No padding is added to the buffer. + * + * @param s IO context + * @param pbuffer pointer to a byte buffer + * @return the length of the byte buffer + */ +int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + +/** + * Return the written size and a pointer to the buffer. The buffer + * must be freed with av_free(). + * Padding of AV_INPUT_BUFFER_PADDING_SIZE is added to the buffer. + * + * @param s IO context + * @param pbuffer pointer to a byte buffer + * @return the length of the byte buffer + */ +int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + +/** + * Iterate through names of available protocols. + * + * @param opaque A private pointer representing current protocol. + * It must be a pointer to NULL on first iteration and will + * be updated by successive calls to avio_enum_protocols. + * @param output If set to 1, iterate over output protocols, + * otherwise over input protocols. + * + * @return A static string containing the name of current protocol or NULL + */ +const char *avio_enum_protocols(void **opaque, int output); + +/** + * Get AVClass by names of available protocols. + * + * @return A AVClass of input protocol name or NULL + */ +const AVClass *avio_protocol_get_class(const char *name); + +/** + * Pause and resume playing - only meaningful if using a network streaming + * protocol (e.g. MMS). + * + * @param h IO context from which to call the read_pause function pointer + * @param pause 1 for pause, 0 for resume + */ +int avio_pause(AVIOContext *h, int pause); + +/** + * Seek to a given timestamp relative to some component stream. + * Only meaningful if using a network streaming protocol (e.g. MMS.). + * + * @param h IO context from which to call the seek function pointers + * @param stream_index The stream index that the timestamp is relative to. + * If stream_index is (-1) the timestamp should be in AV_TIME_BASE + * units from the beginning of the presentation. + * If a stream_index >= 0 is used and the protocol does not support + * seeking based on component streams, the call will fail. + * @param timestamp timestamp in AVStream.time_base units + * or if there is no stream specified then in AV_TIME_BASE units. + * @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE + * and AVSEEK_FLAG_ANY. The protocol may silently ignore + * AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will + * fail if used and not supported. + * @return >= 0 on success + * @see AVInputFormat::read_seek + */ +int64_t avio_seek_time(AVIOContext *h, int stream_index, + int64_t timestamp, int flags); + +/* Avoid a warning. The header can not be included because it breaks c++. */ +struct AVBPrint; + +/** + * Read contents of h into print buffer, up to max_size bytes, or up to EOF. + * + * @return 0 for success (max_size bytes read or EOF reached), negative error + * code otherwise + */ +int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size); + +/** + * Accept and allocate a client context on a server context. + * @param s the server context + * @param c the client context, must be unallocated + * @return >= 0 on success or a negative value corresponding + * to an AVERROR on failure + */ +int avio_accept(AVIOContext *s, AVIOContext **c); + +/** + * Perform one step of the protocol handshake to accept a new client. + * This function must be called on a client returned by avio_accept() before + * using it as a read/write context. + * It is separate from avio_accept() because it may block. + * A step of the handshake is defined by places where the application may + * decide to change the proceedings. + * For example, on a protocol with a request header and a reply header, each + * one can constitute a step because the application may use the parameters + * from the request to change parameters in the reply; or each individual + * chunk of the request can constitute a step. + * If the handshake is already finished, avio_handshake() does nothing and + * returns 0 immediately. + * + * @param c the client context to perform the handshake on + * @return 0 on a complete and successful handshake + * > 0 if the handshake progressed, but is not complete + * < 0 for an AVERROR code + */ +int avio_handshake(AVIOContext *c); +#endif /* AVFORMAT_AVIO_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavformat/version.h b/src/framework/media/thirdparty/ffmpeg/v8/libavformat/version.h new file mode 100644 index 0000000000000..7ff14839125f8 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavformat/version.h @@ -0,0 +1,47 @@ +/* + * Version macros. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_VERSION_H +#define AVFORMAT_VERSION_H + +/** + * @file + * @ingroup libavf + * Libavformat version macros + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBAVFORMAT_VERSION_MINOR 3 +#define LIBAVFORMAT_VERSION_MICRO 100 + +#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT + +#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) + +#endif /* AVFORMAT_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavformat/version_major.h b/src/framework/media/thirdparty/ffmpeg/v8/libavformat/version_major.h new file mode 100644 index 0000000000000..c2f6e1616b793 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavformat/version_major.h @@ -0,0 +1,52 @@ +/* + * Version macros. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_VERSION_MAJOR_H +#define AVFORMAT_VERSION_MAJOR_H + +/** + * @file + * @ingroup libavf + * Libavformat version macros + */ + +// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) +// Also please add any ticket numbers that you believe might be affected here +#define LIBAVFORMAT_VERSION_MAJOR 62 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + * + */ +#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 63) + +#define FF_API_INTERNAL_TIMING (LIBAVFORMAT_VERSION_MAJOR < 63) + +#define FF_API_NO_DEFAULT_TLS_VERIFY (LIBAVFORMAT_VERSION_MAJOR < 63) + +#define FF_API_R_FRAME_RATE 1 + +#endif /* AVFORMAT_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/attributes.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/attributes.h new file mode 100644 index 0000000000000..d15ede12862cb --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/attributes.h @@ -0,0 +1,175 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Macro definitions for various function/variable attributes + */ + +#ifndef AVUTIL_ATTRIBUTES_H +#define AVUTIL_ATTRIBUTES_H + +#ifdef __GNUC__ +# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) +# define AV_GCC_VERSION_AT_MOST(x,y) (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y)) +#else +# define AV_GCC_VERSION_AT_LEAST(x,y) 0 +# define AV_GCC_VERSION_AT_MOST(x,y) 0 +#endif + +#ifdef __has_builtin +# define AV_HAS_BUILTIN(x) __has_builtin(x) +#else +# define AV_HAS_BUILTIN(x) 0 +#endif + +#ifndef av_always_inline +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_always_inline __attribute__((always_inline)) inline +#elif defined(_MSC_VER) +# define av_always_inline __forceinline +#else +# define av_always_inline inline +#endif +#endif + +#ifndef av_extern_inline +#if defined(__ICL) && __ICL >= 1210 || defined(__GNUC_STDC_INLINE__) +# define av_extern_inline extern inline +#else +# define av_extern_inline inline +#endif +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,4) +# define av_warn_unused_result __attribute__((warn_unused_result)) +#else +# define av_warn_unused_result +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_noinline __attribute__((noinline)) +#elif defined(_MSC_VER) +# define av_noinline __declspec(noinline) +#else +# define av_noinline +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) +# define av_pure __attribute__((pure)) +#else +# define av_pure +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,6) || defined(__clang__) +# define av_const __attribute__((const)) +#else +# define av_const +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,3) || defined(__clang__) +# define av_cold __attribute__((cold)) +#else +# define av_cold +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,1) && !defined(__llvm__) +# define av_flatten __attribute__((flatten)) +#else +# define av_flatten +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define attribute_deprecated __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define attribute_deprecated __declspec(deprecated) +#else +# define attribute_deprecated +#endif + +/** + * Disable warnings about deprecated features + * This is useful for sections of code kept for backward compatibility and + * scheduled for removal. + */ +#ifndef AV_NOWARN_DEPRECATED +#if AV_GCC_VERSION_AT_LEAST(4,6) || defined(__clang__) +# define AV_NOWARN_DEPRECATED(code) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \ + code \ + _Pragma("GCC diagnostic pop") +#elif defined(_MSC_VER) +# define AV_NOWARN_DEPRECATED(code) \ + __pragma(warning(push)) \ + __pragma(warning(disable : 4996)) \ + code; \ + __pragma(warning(pop)) +#else +# define AV_NOWARN_DEPRECATED(code) code +#endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define av_unused __attribute__((unused)) +#else +# define av_unused +#endif + +/** + * Mark a variable as used and prevent the compiler from optimizing it + * away. This is useful for variables accessed only from inline + * assembler without the compiler being aware. + */ +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) +# define av_used __attribute__((used)) +#else +# define av_used +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,3) || defined(__clang__) +# define av_alias __attribute__((may_alias)) +#else +# define av_alias +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__INTEL_COMPILER) +# define av_uninit(x) x=x +#else +# define av_uninit(x) x +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define av_builtin_constant_p __builtin_constant_p +# define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos))) +# define av_scanf_format(fmtpos, attrpos) __attribute__((__format__(__scanf__, fmtpos, attrpos))) +#else +# define av_builtin_constant_p(x) 0 +# define av_printf_format(fmtpos, attrpos) +# define av_scanf_format(fmtpos, attrpos) +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,5) || defined(__clang__) +# define av_noreturn __attribute__((noreturn)) +#else +# define av_noreturn +#endif + +#endif /* AVUTIL_ATTRIBUTES_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/avconfig.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/avconfig.h new file mode 100644 index 0000000000000..f13252f7d2c25 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/avconfig.h @@ -0,0 +1,24 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVCONFIG_H +#define AVUTIL_AVCONFIG_H + +#define AV_HAVE_BIGENDIAN 0 + +#endif /* AVUTIL_AVCONFIG_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/avstring.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/avstring.h new file mode 100644 index 0000000000000..17f7b03db5282 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/avstring.h @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2007 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVSTRING_H +#define AVUTIL_AVSTRING_H + +#include +#include +#include "attributes.h" + +/** + * @addtogroup lavu_string + * @{ + */ + +/** + * Return non-zero if pfx is a prefix of str. If it is, *ptr is set to + * the address of the first character in str after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_strstart(const char *str, const char *pfx, const char **ptr); + +/** + * Return non-zero if pfx is a prefix of str independent of case. If + * it is, *ptr is set to the address of the first character in str + * after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_stristart(const char *str, const char *pfx, const char **ptr); + +/** + * Locate the first case-independent occurrence in the string haystack + * of the string needle. A zero-length string needle is considered to + * match at the start of haystack. + * + * This function is a case-insensitive version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_stristr(const char *haystack, const char *needle); + +/** + * Locate the first occurrence of the string needle in the string haystack + * where not more than hay_length characters are searched. A zero-length + * string needle is considered to match at the start of haystack. + * + * This function is a length-limited version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @param hay_length length of string to search in + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_strnstr(const char *haystack, const char *needle, size_t hay_length); + +/** + * Copy the string src to dst, but no more than size - 1 bytes, and + * null-terminate dst. + * + * This function is the same as BSD strlcpy(). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the length of src + * + * @warning since the return value is the length of src, src absolutely + * _must_ be a properly 0-terminated string, otherwise this will read beyond + * the end of the buffer and possibly crash. + */ +size_t av_strlcpy(char *dst, const char *src, size_t size); + +/** + * Append the string src to the string dst, but to a total length of + * no more than size - 1 bytes, and null-terminate dst. + * + * This function is similar to BSD strlcat(), but differs when + * size <= strlen(dst). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the total length of src and dst + * + * @warning since the return value use the length of src and dst, these + * absolutely _must_ be a properly 0-terminated strings, otherwise this + * will read beyond the end of the buffer and possibly crash. + */ +size_t av_strlcat(char *dst, const char *src, size_t size); + +/** + * Append output to a string, according to a format. Never write out of + * the destination buffer, and always put a terminating 0 within + * the buffer. + * @param dst destination buffer (string to which the output is + * appended) + * @param size total size of the destination buffer + * @param fmt printf-compatible format string, specifying how the + * following parameters are used + * @return the length of the string that would have been generated + * if enough space had been available + */ +size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Get the count of continuous non zero chars starting from the beginning. + * + * @param s the string whose length to count + * @param len maximum number of characters to check in the string, that + * is the maximum value which is returned by the function + */ +static inline size_t av_strnlen(const char *s, size_t len) +{ + size_t i; + for (i = 0; i < len && s[i]; i++) + ; + return i; +} + +/** + * Print arguments following specified format into a large enough auto + * allocated buffer. It is similar to GNU asprintf(). + * @param fmt printf-compatible format string, specifying how the + * following parameters are used. + * @return the allocated string + * @note You have to free the string yourself with av_free(). + */ +char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2); + +/** + * Unescape the given string until a non escaped terminating char, + * and return the token corresponding to the unescaped string. + * + * The normal \ and ' escaping is supported. Leading and trailing + * whitespaces are removed, unless they are escaped with '\' or are + * enclosed between ''. + * + * @param buf the buffer to parse, buf will be updated to point to the + * terminating char + * @param term a 0-terminated list of terminating chars + * @return the malloced unescaped string, which must be av_freed by + * the user, NULL in case of allocation failure + */ +char *av_get_token(const char **buf, const char *term); + +/** + * Split the string into several tokens which can be accessed by + * successive calls to av_strtok(). + * + * A token is defined as a sequence of characters not belonging to the + * set specified in delim. + * + * On the first call to av_strtok(), s should point to the string to + * parse, and the value of saveptr is ignored. In subsequent calls, s + * should be NULL, and saveptr should be unchanged since the previous + * call. + * + * This function is similar to strtok_r() defined in POSIX.1. + * + * @param s the string to parse, may be NULL + * @param delim 0-terminated list of token delimiters, must be non-NULL + * @param saveptr user-provided pointer which points to stored + * information necessary for av_strtok() to continue scanning the same + * string. saveptr is updated to point to the next character after the + * first delimiter found, or to NULL if the string was terminated + * @return the found token, or NULL when no token is found + */ +char *av_strtok(char *s, const char *delim, char **saveptr); + +/** + * Locale-independent conversion of ASCII isdigit. + */ +static inline av_const int av_isdigit(int c) +{ + return c >= '0' && c <= '9'; +} + +/** + * Locale-independent conversion of ASCII isgraph. + */ +static inline av_const int av_isgraph(int c) +{ + return c > 32 && c < 127; +} + +/** + * Locale-independent conversion of ASCII isspace. + */ +static inline av_const int av_isspace(int c) +{ + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || + c == '\v'; +} + +/** + * Locale-independent conversion of ASCII characters to uppercase. + */ +static inline av_const int av_toupper(int c) +{ + if (c >= 'a' && c <= 'z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII characters to lowercase. + */ +static inline av_const int av_tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII isxdigit. + */ +static inline av_const int av_isxdigit(int c) +{ + c = av_tolower(c); + return av_isdigit(c) || (c >= 'a' && c <= 'f'); +} + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strcasecmp(const char *a, const char *b); + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strncasecmp(const char *a, const char *b, size_t n); + +/** + * Locale-independent strings replace. + * @note This means only ASCII-range characters are replaced. + */ +char *av_strireplace(const char *str, const char *from, const char *to); + +/** + * Thread safe basename. + * @param path the string to parse, on DOS both \ and / are considered separators. + * @return pointer to the basename substring. + * If path does not contain a slash, the function returns a copy of path. + * If path is a NULL pointer or points to an empty string, a pointer + * to a string "." is returned. + */ +const char *av_basename(const char *path); + +/** + * Thread safe dirname. + * @param path the string to parse, on DOS both \ and / are considered separators. + * @return A pointer to a string that's the parent directory of path. + * If path is a NULL pointer or points to an empty string, a pointer + * to a string "." is returned. + * @note the function may modify the contents of the path, so copies should be passed. + */ +const char *av_dirname(char *path); + +/** + * Match instances of a name in a comma-separated list of names. + * List entries are checked from the start to the end of the names list, + * the first match ends further processing. If an entry prefixed with '-' + * matches, then 0 is returned. The "ALL" list entry is considered to + * match all names. + * + * @param name Name to look for. + * @param names List of names. + * @return 1 on match, 0 otherwise. + */ +int av_match_name(const char *name, const char *names); + +/** + * Append path component to the existing path. + * Path separator '/' is placed between when needed. + * Resulting string have to be freed with av_free(). + * @param path base path + * @param component component to be appended + * @return new path or NULL on error. + */ +char *av_append_path_component(const char *path, const char *component); + +enum AVEscapeMode { + AV_ESCAPE_MODE_AUTO, ///< Use auto-selected escaping mode. + AV_ESCAPE_MODE_BACKSLASH, ///< Use backslash escaping. + AV_ESCAPE_MODE_QUOTE, ///< Use single-quote escaping. + AV_ESCAPE_MODE_XML, ///< Use XML non-markup character data escaping. +}; + +/** + * Consider spaces special and escape them even in the middle of the + * string. + * + * This is equivalent to adding the whitespace characters to the special + * characters lists, except it is guaranteed to use the exact same list + * of whitespace characters as the rest of libavutil. + */ +#define AV_ESCAPE_FLAG_WHITESPACE (1 << 0) + +/** + * Escape only specified special characters. + * Without this flag, escape also any characters that may be considered + * special by av_get_token(), such as the single quote. + */ +#define AV_ESCAPE_FLAG_STRICT (1 << 1) + +/** + * Within AV_ESCAPE_MODE_XML, additionally escape single quotes for single + * quoted attributes. + */ +#define AV_ESCAPE_FLAG_XML_SINGLE_QUOTES (1 << 2) + +/** + * Within AV_ESCAPE_MODE_XML, additionally escape double quotes for double + * quoted attributes. + */ +#define AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES (1 << 3) + + +/** + * Escape string in src, and put the escaped string in an allocated + * string in *dst, which must be freed with av_free(). + * + * @param dst pointer where an allocated string is put + * @param src string to escape, must be non-NULL + * @param special_chars string containing the special characters which + * need to be escaped, can be NULL + * @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros. + * Any unknown value for mode will be considered equivalent to + * AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without + * notice. + * @param flags flags which control how to escape, see AV_ESCAPE_FLAG_ macros + * @return the length of the allocated string, or a negative error code in case of error + * @see av_bprint_escape() + */ +av_warn_unused_result +int av_escape(char **dst, const char *src, const char *special_chars, + enum AVEscapeMode mode, int flags); + +#define AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES 1 ///< accept codepoints over 0x10FFFF +#define AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS 2 ///< accept non-characters - 0xFFFE and 0xFFFF +#define AV_UTF8_FLAG_ACCEPT_SURROGATES 4 ///< accept UTF-16 surrogates codes +#define AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES 8 ///< exclude control codes not accepted by XML + +#define AV_UTF8_FLAG_ACCEPT_ALL \ + AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES|AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS|AV_UTF8_FLAG_ACCEPT_SURROGATES + +/** + * Read and decode a single UTF-8 code point (character) from the + * buffer in *buf, and update *buf to point to the next byte to + * decode. + * + * In case of an invalid byte sequence, the pointer will be updated to + * the next byte after the invalid sequence and the function will + * return an error code. + * + * Depending on the specified flags, the function will also fail in + * case the decoded code point does not belong to a valid range. + * + * @note For speed-relevant code a carefully implemented use of + * GET_UTF8() may be preferred. + * + * @param codep pointer used to return the parsed code in case of success. + * The value in *codep is set even in case the range check fails. + * @param bufp pointer to the address the first byte of the sequence + * to decode, updated by the function to point to the + * byte next after the decoded sequence + * @param buf_end pointer to the end of the buffer, points to the next + * byte past the last in the buffer. This is used to + * avoid buffer overreads (in case of an unfinished + * UTF-8 sequence towards the end of the buffer). + * @param flags a collection of AV_UTF8_FLAG_* flags + * @return >= 0 in case a sequence was successfully read, a negative + * value in case of invalid sequence + */ +av_warn_unused_result +int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end, + unsigned int flags); + +/** + * Check if a name is in a list. + * @returns 0 if not found, or the 1 based index where it has been found in the + * list. + */ +int av_match_list(const char *name, const char *list, char separator); + +/** + * See libc sscanf manual for more information. + * Locale-independent sscanf implementation. + */ +int av_sscanf(const char *string, const char *format, ...) av_scanf_format(2, 3); + +/** + * @} + */ + +#endif /* AVUTIL_AVSTRING_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/avutil.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/avutil.h new file mode 100644 index 0000000000000..c8ae114ab6f37 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/avutil.h @@ -0,0 +1,364 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVUTIL_H +#define AVUTIL_AVUTIL_H + +/** + * @file + * @ingroup lavu + * Convenience header that includes @ref lavu "libavutil"'s core. + */ + +/** + * @mainpage + * + * @section ffmpeg_intro Introduction + * + * This document describes the usage of the different libraries + * provided by FFmpeg. + * + * @li @ref libavc "libavcodec" encoding/decoding library + * @li @ref lavfi "libavfilter" graph-based frame editing library + * @li @ref libavf "libavformat" I/O and muxing/demuxing library + * @li @ref lavd "libavdevice" special devices muxing/demuxing library + * @li @ref lavu "libavutil" common utility library + * @li @ref lswr "libswresample" audio resampling, format conversion and mixing + * @li @ref libsws "libswscale" color conversion and scaling library + * + * @section ffmpeg_versioning Versioning and compatibility + * + * Each of the FFmpeg libraries contains a version.h header, which defines a + * major, minor and micro version number with the + * LIBRARYNAME_VERSION_{MAJOR,MINOR,MICRO} macros. The major version + * number is incremented with backward incompatible changes - e.g. removing + * parts of the public API, reordering public struct members, etc. The minor + * version number is incremented for backward compatible API changes or major + * new features - e.g. adding a new public function or a new decoder. The micro + * version number is incremented for smaller changes that a calling program + * might still want to check for - e.g. changing behavior in a previously + * unspecified situation. + * + * FFmpeg guarantees backward API and ABI compatibility for each library as long + * as its major version number is unchanged. This means that no public symbols + * will be removed or renamed. Types and names of the public struct members and + * values of public macros and enums will remain the same (unless they were + * explicitly declared as not part of the public API). Documented behavior will + * not change. + * + * In other words, any correct program that works with a given FFmpeg snapshot + * should work just as well without any changes with any later snapshot with the + * same major versions. This applies to both rebuilding the program against new + * FFmpeg versions or to replacing the dynamic FFmpeg libraries that a program + * links against. + * + * However, new public symbols may be added and new members may be appended to + * public structs whose size is not part of public ABI (most public structs in + * FFmpeg). New macros and enum values may be added. Behavior in undocumented + * situations may change slightly (and be documented). All those are accompanied + * by an entry in doc/APIchanges and incrementing either the minor or micro + * version number. + */ + +/** + * @defgroup lavu libavutil + * Common code shared across all FFmpeg libraries. + * + * @note + * libavutil is designed to be modular. In most cases, in order to use the + * functions provided by one component of libavutil you must explicitly include + * the specific header containing that feature. If you are only using + * media-related components, you could simply include libavutil/avutil.h, which + * brings in most of the "core" components. + * + * @{ + * + * @defgroup lavu_crypto Crypto and Hashing + * + * @{ + * @} + * + * @defgroup lavu_math Mathematics + * @{ + * + * @} + * + * @defgroup lavu_string String Manipulation + * + * @{ + * + * @} + * + * @defgroup lavu_mem Memory Management + * + * @{ + * + * @} + * + * @defgroup lavu_data Data Structures + * @{ + * + * @} + * + * @defgroup lavu_video Video related + * + * @{ + * + * @} + * + * @defgroup lavu_audio Audio related + * + * @{ + * + * @} + * + * @defgroup lavu_error Error Codes + * + * @{ + * + * @} + * + * @defgroup lavu_log Logging Facility + * + * @{ + * + * @} + * + * @defgroup lavu_misc Other + * + * @{ + * + * @defgroup preproc_misc Preprocessor String Macros + * + * @{ + * + * @} + * + * @defgroup version_utils Library Version Macros + * + * @{ + * + * @} + */ + + +/** + * @addtogroup lavu_ver + * @{ + */ + +/** + * Return the LIBAVUTIL_VERSION_INT constant. + */ +unsigned avutil_version(void); + +/** + * Return an informative version string. This usually is the actual release + * version number or a git commit description. This string has no fixed format + * and can change any time. It should never be parsed by code. + */ +const char *av_version_info(void); + +/** + * Return the libavutil build-time configuration. + */ +const char *avutil_configuration(void); + +/** + * Return the libavutil license. + */ +const char *avutil_license(void); + +/** + * @} + */ + +/** + * @addtogroup lavu_media Media Type + * @brief Media Type + */ + +enum AVMediaType { + AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA + AVMEDIA_TYPE_VIDEO, + AVMEDIA_TYPE_AUDIO, + AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous + AVMEDIA_TYPE_SUBTITLE, + AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse + AVMEDIA_TYPE_NB +}; + +/** + * Return a string describing the media_type enum, NULL if media_type + * is unknown. + */ +const char *av_get_media_type_string(enum AVMediaType media_type); + +/** + * @defgroup lavu_const Constants + * @{ + * + * @defgroup lavu_enc Encoding specific + * + * @note those definition should move to avcodec + * @{ + */ + +#define FF_LAMBDA_SHIFT 7 +#define FF_LAMBDA_SCALE (1< +#include + +/** + * @defgroup lavu_buffer AVBuffer + * @ingroup lavu_data + * + * @{ + * AVBuffer is an API for reference-counted data buffers. + * + * There are two core objects in this API -- AVBuffer and AVBufferRef. AVBuffer + * represents the data buffer itself; it is opaque and not meant to be accessed + * by the caller directly, but only through AVBufferRef. However, the caller may + * e.g. compare two AVBuffer pointers to check whether two different references + * are describing the same data buffer. AVBufferRef represents a single + * reference to an AVBuffer and it is the object that may be manipulated by the + * caller directly. + * + * There are two functions provided for creating a new AVBuffer with a single + * reference -- av_buffer_alloc() to just allocate a new buffer, and + * av_buffer_create() to wrap an existing array in an AVBuffer. From an existing + * reference, additional references may be created with av_buffer_ref(). + * Use av_buffer_unref() to free a reference (this will automatically free the + * data once all the references are freed). + * + * The convention throughout this API and the rest of FFmpeg is such that the + * buffer is considered writable if there exists only one reference to it (and + * it has not been marked as read-only). The av_buffer_is_writable() function is + * provided to check whether this is true and av_buffer_make_writable() will + * automatically create a new writable buffer when necessary. + * Of course nothing prevents the calling code from violating this convention, + * however that is safe only when all the existing references are under its + * control. + * + * @note Referencing and unreferencing the buffers is thread-safe and thus + * may be done from multiple threads simultaneously without any need for + * additional locking. + * + * @note Two different references to the same buffer can point to different + * parts of the buffer (i.e. their AVBufferRef.data will not be equal). + */ + +/** + * A reference counted buffer type. It is opaque and is meant to be used through + * references (AVBufferRef). + */ +typedef struct AVBuffer AVBuffer; + +/** + * A reference to a data buffer. + * + * The size of this struct is not a part of the public ABI and it is not meant + * to be allocated directly. + */ +typedef struct AVBufferRef { + AVBuffer *buffer; + + /** + * The data buffer. It is considered writable if and only if + * this is the only reference to the buffer, in which case + * av_buffer_is_writable() returns 1. + */ + uint8_t *data; + /** + * Size of data in bytes. + */ + size_t size; +} AVBufferRef; + +/** + * Allocate an AVBuffer of the given size using av_malloc(). + * + * @return an AVBufferRef of given size or NULL when out of memory + */ +AVBufferRef *av_buffer_alloc(size_t size); + +/** + * Same as av_buffer_alloc(), except the returned buffer will be initialized + * to zero. + */ +AVBufferRef *av_buffer_allocz(size_t size); + +/** + * Always treat the buffer as read-only, even when it has only one + * reference. + */ +#define AV_BUFFER_FLAG_READONLY (1 << 0) + +/** + * Create an AVBuffer from an existing array. + * + * If this function is successful, data is owned by the AVBuffer. The caller may + * only access data through the returned AVBufferRef and references derived from + * it. + * If this function fails, data is left untouched. + * @param data data array + * @param size size of data in bytes + * @param free a callback for freeing this buffer's data + * @param opaque parameter to be got for processing or passed to free + * @param flags a combination of AV_BUFFER_FLAG_* + * + * @return an AVBufferRef referring to data on success, NULL on failure. + */ +AVBufferRef *av_buffer_create(uint8_t *data, size_t size, + void (*free)(void *opaque, uint8_t *data), + void *opaque, int flags); + +/** + * Default free callback, which calls av_free() on the buffer data. + * This function is meant to be passed to av_buffer_create(), not called + * directly. + */ +void av_buffer_default_free(void *opaque, uint8_t *data); + +/** + * Create a new reference to an AVBuffer. + * + * @return a new AVBufferRef referring to the same AVBuffer as buf or NULL on + * failure. + */ +AVBufferRef *av_buffer_ref(const AVBufferRef *buf); + +/** + * Free a given reference and automatically free the buffer if there are no more + * references to it. + * + * @param buf the reference to be freed. The pointer is set to NULL on return. + */ +void av_buffer_unref(AVBufferRef **buf); + +/** + * @return 1 if the caller may write to the data referred to by buf (which is + * true if and only if buf is the only reference to the underlying AVBuffer). + * Return 0 otherwise. + * A positive answer is valid until av_buffer_ref() is called on buf. + */ +int av_buffer_is_writable(const AVBufferRef *buf); + +/** + * @return the opaque parameter set by av_buffer_create. + */ +void *av_buffer_get_opaque(const AVBufferRef *buf); + +int av_buffer_get_ref_count(const AVBufferRef *buf); + +/** + * Create a writable reference from a given buffer reference, avoiding data copy + * if possible. + * + * @param buf buffer reference to make writable. On success, buf is either left + * untouched, or it is unreferenced and a new writable AVBufferRef is + * written in its place. On failure, buf is left untouched. + * @return 0 on success, a negative AVERROR on failure. + */ +int av_buffer_make_writable(AVBufferRef **buf); + +/** + * Reallocate a given buffer. + * + * @param buf a buffer reference to reallocate. On success, buf will be + * unreferenced and a new reference with the required size will be + * written in its place. On failure buf will be left untouched. *buf + * may be NULL, then a new buffer is allocated. + * @param size required new buffer size. + * @return 0 on success, a negative AVERROR on failure. + * + * @note the buffer is actually reallocated with av_realloc() only if it was + * initially allocated through av_buffer_realloc(NULL) and there is only one + * reference to it (i.e. the one passed to this function). In all other cases + * a new buffer is allocated and the data is copied. + */ +int av_buffer_realloc(AVBufferRef **buf, size_t size); + +/** + * Ensure dst refers to the same data as src. + * + * When *dst is already equivalent to src, do nothing. Otherwise unreference dst + * and replace it with a new reference to src. + * + * @param dst Pointer to either a valid buffer reference or NULL. On success, + * this will point to a buffer reference equivalent to src. On + * failure, dst will be left untouched. + * @param src A buffer reference to replace dst with. May be NULL, then this + * function is equivalent to av_buffer_unref(dst). + * @return 0 on success + * AVERROR(ENOMEM) on memory allocation failure. + */ +int av_buffer_replace(AVBufferRef **dst, const AVBufferRef *src); + +/** + * @} + */ + +/** + * @defgroup lavu_bufferpool AVBufferPool + * @ingroup lavu_data + * + * @{ + * AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers. + * + * Frequently allocating and freeing large buffers may be slow. AVBufferPool is + * meant to solve this in cases when the caller needs a set of buffers of the + * same size (the most obvious use case being buffers for raw video or audio + * frames). + * + * At the beginning, the user must call av_buffer_pool_init() to create the + * buffer pool. Then whenever a buffer is needed, call av_buffer_pool_get() to + * get a reference to a new buffer, similar to av_buffer_alloc(). This new + * reference works in all aspects the same way as the one created by + * av_buffer_alloc(). However, when the last reference to this buffer is + * unreferenced, it is returned to the pool instead of being freed and will be + * reused for subsequent av_buffer_pool_get() calls. + * + * When the caller is done with the pool and no longer needs to allocate any new + * buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable. + * Once all the buffers are released, it will automatically be freed. + * + * Allocating and releasing buffers with this API is thread-safe as long as + * either the default alloc callback is used, or the user-supplied one is + * thread-safe. + */ + +/** + * The buffer pool. This structure is opaque and not meant to be accessed + * directly. It is allocated with av_buffer_pool_init() and freed with + * av_buffer_pool_uninit(). + */ +typedef struct AVBufferPool AVBufferPool; + +/** + * Allocate and initialize a buffer pool. + * + * @param size size of each buffer in this pool + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be used + * (av_buffer_alloc()). + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init(size_t size, AVBufferRef* (*alloc)(size_t size)); + +/** + * Allocate and initialize a buffer pool with a more complex allocator. + * + * @param size size of each buffer in this pool + * @param opaque arbitrary user data used by the allocator + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be + * used (av_buffer_alloc()). + * @param pool_free a function that will be called immediately before the pool + * is freed. I.e. after av_buffer_pool_uninit() is called + * by the caller and all the frames are returned to the pool + * and freed. It is intended to uninitialize the user opaque + * data. May be NULL. + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init2(size_t size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, size_t size), + void (*pool_free)(void *opaque)); + +/** + * Mark the pool as being available for freeing. It will actually be freed only + * once all the allocated buffers associated with the pool are released. Thus it + * is safe to call this function while some of the allocated buffers are still + * in use. + * + * @param pool pointer to the pool to be freed. It will be set to NULL. + */ +void av_buffer_pool_uninit(AVBufferPool **pool); + +/** + * Allocate a new AVBuffer, reusing an old buffer from the pool when available. + * This function may be called simultaneously from multiple threads. + * + * @return a reference to the new buffer on success, NULL on error. + */ +AVBufferRef *av_buffer_pool_get(AVBufferPool *pool); + +/** + * Query the original opaque parameter of an allocated buffer in the pool. + * + * @param ref a buffer reference to a buffer returned by av_buffer_pool_get. + * @return the opaque parameter set by the buffer allocator function of the + * buffer pool. + * + * @note the opaque parameter of ref is used by the buffer pool implementation, + * therefore you have to use this function to access the original opaque + * parameter of an allocated buffer. + */ +void *av_buffer_pool_buffer_get_opaque(const AVBufferRef *ref); + +/** + * @} + */ + +#endif /* AVUTIL_BUFFER_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/channel_layout.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/channel_layout.h new file mode 100644 index 0000000000000..5ad2d5ed98f2c --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/channel_layout.h @@ -0,0 +1,762 @@ +/* + * Copyright (c) 2006 Michael Niedermayer + * Copyright (c) 2008 Peter Ross + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_CHANNEL_LAYOUT_H +#define AVUTIL_CHANNEL_LAYOUT_H + +#include +#include + +#include "version.h" +#include "attributes.h" + +/** + * @file + * @ingroup lavu_audio_channels + * Public libavutil channel layout APIs header. + */ + + +/** + * @defgroup lavu_audio_channels Audio channels + * @ingroup lavu_audio + * + * Audio channel layout utility functions + * + * @{ + */ + +enum AVChannel { + /// Invalid channel index + AV_CHAN_NONE = -1, + AV_CHAN_FRONT_LEFT, + AV_CHAN_FRONT_RIGHT, + AV_CHAN_FRONT_CENTER, + AV_CHAN_LOW_FREQUENCY, + AV_CHAN_BACK_LEFT, + AV_CHAN_BACK_RIGHT, + AV_CHAN_FRONT_LEFT_OF_CENTER, + AV_CHAN_FRONT_RIGHT_OF_CENTER, + AV_CHAN_BACK_CENTER, + AV_CHAN_SIDE_LEFT, + AV_CHAN_SIDE_RIGHT, + AV_CHAN_TOP_CENTER, + AV_CHAN_TOP_FRONT_LEFT, + AV_CHAN_TOP_FRONT_CENTER, + AV_CHAN_TOP_FRONT_RIGHT, + AV_CHAN_TOP_BACK_LEFT, + AV_CHAN_TOP_BACK_CENTER, + AV_CHAN_TOP_BACK_RIGHT, + /** Stereo downmix. */ + AV_CHAN_STEREO_LEFT = 29, + /** See above. */ + AV_CHAN_STEREO_RIGHT, + AV_CHAN_WIDE_LEFT, + AV_CHAN_WIDE_RIGHT, + AV_CHAN_SURROUND_DIRECT_LEFT, + AV_CHAN_SURROUND_DIRECT_RIGHT, + AV_CHAN_LOW_FREQUENCY_2, + AV_CHAN_TOP_SIDE_LEFT, + AV_CHAN_TOP_SIDE_RIGHT, + AV_CHAN_BOTTOM_FRONT_CENTER, + AV_CHAN_BOTTOM_FRONT_LEFT, + AV_CHAN_BOTTOM_FRONT_RIGHT, + AV_CHAN_SIDE_SURROUND_LEFT, ///< +90 degrees, Lss, SiL + AV_CHAN_SIDE_SURROUND_RIGHT, ///< -90 degrees, Rss, SiR + AV_CHAN_TOP_SURROUND_LEFT, ///< +110 degrees, Lvs, TpLS + AV_CHAN_TOP_SURROUND_RIGHT, ///< -110 degrees, Rvs, TpRS + + AV_CHAN_BINAURAL_LEFT = 61, + AV_CHAN_BINAURAL_RIGHT, + + /** Channel is empty can be safely skipped. */ + AV_CHAN_UNUSED = 0x200, + + /** Channel contains data, but its position is unknown. */ + AV_CHAN_UNKNOWN = 0x300, + + /** + * Range of channels between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END represent Ambisonic components using the ACN system. + * + * Given a channel id `` between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END (inclusive), the ACN index of the channel `` is + * ` = - AV_CHAN_AMBISONIC_BASE`. + * + * @note these values are only used for AV_CHANNEL_ORDER_CUSTOM channel + * orderings, the AV_CHANNEL_ORDER_AMBISONIC ordering orders the channels + * implicitly by their position in the stream. + */ + AV_CHAN_AMBISONIC_BASE = 0x400, + // leave space for 1024 ids, which correspond to maximum order-32 harmonics, + // which should be enough for the foreseeable use cases + AV_CHAN_AMBISONIC_END = 0x7ff, +}; + +enum AVChannelOrder { + /** + * Only the channel count is specified, without any further information + * about the channel order. + */ + AV_CHANNEL_ORDER_UNSPEC, + /** + * The native channel order, i.e. the channels are in the same order in + * which they are defined in the AVChannel enum. This supports up to 63 + * different channels. + */ + AV_CHANNEL_ORDER_NATIVE, + /** + * The channel order does not correspond to any other predefined order and + * is stored as an explicit map. For example, this could be used to support + * layouts with 64 or more channels, or with empty/skipped (AV_CHAN_UNUSED) + * channels at arbitrary positions. + */ + AV_CHANNEL_ORDER_CUSTOM, + /** + * The audio is represented as the decomposition of the sound field into + * spherical harmonics. Each channel corresponds to a single expansion + * component. Channels are ordered according to ACN (Ambisonic Channel + * Number). + * + * The channel with the index n in the stream contains the spherical + * harmonic of degree l and order m given by + * @code{.unparsed} + * l = floor(sqrt(n)), + * m = n - l * (l + 1). + * @endcode + * + * Conversely given a spherical harmonic of degree l and order m, the + * corresponding channel index n is given by + * @code{.unparsed} + * n = l * (l + 1) + m. + * @endcode + * + * Normalization is assumed to be SN3D (Schmidt Semi-Normalization) + * as defined in AmbiX format $ 2.1. + */ + AV_CHANNEL_ORDER_AMBISONIC, + /** + * Number of channel orders, not part of ABI/API + */ + FF_CHANNEL_ORDER_NB +}; + + +/** + * @defgroup channel_masks Audio channel masks + * + * A channel layout is a 64-bits integer with a bit set for every channel. + * The number of bits set must be equal to the number of channels. + * The value 0 means that the channel layout is not known. + * @note this data structure is not powerful enough to handle channels + * combinations that have the same channel multiple times, such as + * dual-mono. + * + * @{ + */ +#define AV_CH_FRONT_LEFT (1ULL << AV_CHAN_FRONT_LEFT ) +#define AV_CH_FRONT_RIGHT (1ULL << AV_CHAN_FRONT_RIGHT ) +#define AV_CH_FRONT_CENTER (1ULL << AV_CHAN_FRONT_CENTER ) +#define AV_CH_LOW_FREQUENCY (1ULL << AV_CHAN_LOW_FREQUENCY ) +#define AV_CH_BACK_LEFT (1ULL << AV_CHAN_BACK_LEFT ) +#define AV_CH_BACK_RIGHT (1ULL << AV_CHAN_BACK_RIGHT ) +#define AV_CH_FRONT_LEFT_OF_CENTER (1ULL << AV_CHAN_FRONT_LEFT_OF_CENTER ) +#define AV_CH_FRONT_RIGHT_OF_CENTER (1ULL << AV_CHAN_FRONT_RIGHT_OF_CENTER) +#define AV_CH_BACK_CENTER (1ULL << AV_CHAN_BACK_CENTER ) +#define AV_CH_SIDE_LEFT (1ULL << AV_CHAN_SIDE_LEFT ) +#define AV_CH_SIDE_RIGHT (1ULL << AV_CHAN_SIDE_RIGHT ) +#define AV_CH_TOP_CENTER (1ULL << AV_CHAN_TOP_CENTER ) +#define AV_CH_TOP_FRONT_LEFT (1ULL << AV_CHAN_TOP_FRONT_LEFT ) +#define AV_CH_TOP_FRONT_CENTER (1ULL << AV_CHAN_TOP_FRONT_CENTER ) +#define AV_CH_TOP_FRONT_RIGHT (1ULL << AV_CHAN_TOP_FRONT_RIGHT ) +#define AV_CH_TOP_BACK_LEFT (1ULL << AV_CHAN_TOP_BACK_LEFT ) +#define AV_CH_TOP_BACK_CENTER (1ULL << AV_CHAN_TOP_BACK_CENTER ) +#define AV_CH_TOP_BACK_RIGHT (1ULL << AV_CHAN_TOP_BACK_RIGHT ) +#define AV_CH_STEREO_LEFT (1ULL << AV_CHAN_STEREO_LEFT ) +#define AV_CH_STEREO_RIGHT (1ULL << AV_CHAN_STEREO_RIGHT ) +#define AV_CH_WIDE_LEFT (1ULL << AV_CHAN_WIDE_LEFT ) +#define AV_CH_WIDE_RIGHT (1ULL << AV_CHAN_WIDE_RIGHT ) +#define AV_CH_SURROUND_DIRECT_LEFT (1ULL << AV_CHAN_SURROUND_DIRECT_LEFT ) +#define AV_CH_SURROUND_DIRECT_RIGHT (1ULL << AV_CHAN_SURROUND_DIRECT_RIGHT) +#define AV_CH_LOW_FREQUENCY_2 (1ULL << AV_CHAN_LOW_FREQUENCY_2 ) +#define AV_CH_TOP_SIDE_LEFT (1ULL << AV_CHAN_TOP_SIDE_LEFT ) +#define AV_CH_TOP_SIDE_RIGHT (1ULL << AV_CHAN_TOP_SIDE_RIGHT ) +#define AV_CH_BOTTOM_FRONT_CENTER (1ULL << AV_CHAN_BOTTOM_FRONT_CENTER ) +#define AV_CH_BOTTOM_FRONT_LEFT (1ULL << AV_CHAN_BOTTOM_FRONT_LEFT ) +#define AV_CH_BOTTOM_FRONT_RIGHT (1ULL << AV_CHAN_BOTTOM_FRONT_RIGHT ) +#define AV_CH_SIDE_SURROUND_LEFT (1ULL << AV_CHAN_SIDE_SURROUND_LEFT ) +#define AV_CH_SIDE_SURROUND_RIGHT (1ULL << AV_CHAN_SIDE_SURROUND_RIGHT ) +#define AV_CH_TOP_SURROUND_LEFT (1ULL << AV_CHAN_TOP_SURROUND_LEFT ) +#define AV_CH_TOP_SURROUND_RIGHT (1ULL << AV_CHAN_TOP_SURROUND_RIGHT ) +#define AV_CH_BINAURAL_LEFT (1ULL << AV_CHAN_BINAURAL_LEFT ) +#define AV_CH_BINAURAL_RIGHT (1ULL << AV_CHAN_BINAURAL_RIGHT ) + +/** + * @} + * @defgroup channel_mask_c Audio channel layouts + * @{ + * */ +#define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT) +#define AV_CH_LAYOUT_2POINT1 (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_3POINT1 (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_4POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_4POINT1 (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_2 (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_QUAD (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_5POINT0_BACK (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT1_BACK (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_6POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT0_FRONT (AV_CH_LAYOUT_2_2|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_HEXAGONAL (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_3POINT1POINT2 (AV_CH_LAYOUT_3POINT1|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_6POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_FRONT (AV_CH_LAYOUT_6POINT0_FRONT|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_7POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT0_FRONT (AV_CH_LAYOUT_5POINT0|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1_WIDE_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_5POINT1POINT2 (AV_CH_LAYOUT_5POINT1|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_5POINT1POINT2_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_CUBE (AV_CH_LAYOUT_QUAD|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT1POINT4_BACK (AV_CH_LAYOUT_5POINT1POINT2|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT1POINT2 (AV_CH_LAYOUT_7POINT1|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_7POINT1POINT4_BACK (AV_CH_LAYOUT_7POINT1POINT2|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT2POINT3 (AV_CH_LAYOUT_7POINT1POINT2|AV_CH_TOP_BACK_CENTER|AV_CH_LOW_FREQUENCY_2) +#define AV_CH_LAYOUT_9POINT1POINT4_BACK (AV_CH_LAYOUT_7POINT1POINT4_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_9POINT1POINT6 (AV_CH_LAYOUT_9POINT1POINT4_BACK|AV_CH_TOP_SIDE_LEFT|AV_CH_TOP_SIDE_RIGHT) +#define AV_CH_LAYOUT_HEXADECAGONAL (AV_CH_LAYOUT_OCTAGONAL|AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_BINAURAL (AV_CH_BINAURAL_LEFT|AV_CH_BINAURAL_RIGHT) +#define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT) +#define AV_CH_LAYOUT_22POINT2 (AV_CH_LAYOUT_9POINT1POINT6|AV_CH_BACK_CENTER|AV_CH_LOW_FREQUENCY_2|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_CENTER|AV_CH_TOP_BACK_CENTER|AV_CH_BOTTOM_FRONT_CENTER|AV_CH_BOTTOM_FRONT_LEFT|AV_CH_BOTTOM_FRONT_RIGHT) + +#define AV_CH_LAYOUT_7POINT1_TOP_BACK AV_CH_LAYOUT_5POINT1POINT2_BACK + +enum AVMatrixEncoding { + AV_MATRIX_ENCODING_NONE, + AV_MATRIX_ENCODING_DOLBY, + AV_MATRIX_ENCODING_DPLII, + AV_MATRIX_ENCODING_DPLIIX, + AV_MATRIX_ENCODING_DPLIIZ, + AV_MATRIX_ENCODING_DOLBYEX, + AV_MATRIX_ENCODING_DOLBYHEADPHONE, + AV_MATRIX_ENCODING_NB +}; + +/** + * @} + */ + +/** + * An AVChannelCustom defines a single channel within a custom order layout + * + * Unlike most structures in FFmpeg, sizeof(AVChannelCustom) is a part of the + * public ABI. + * + * No new fields may be added to it without a major version bump. + */ +typedef struct AVChannelCustom { + enum AVChannel id; + char name[16]; + void *opaque; +} AVChannelCustom; + +/** + * An AVChannelLayout holds information about the channel layout of audio data. + * + * A channel layout here is defined as a set of channels ordered in a specific + * way (unless the channel order is AV_CHANNEL_ORDER_UNSPEC, in which case an + * AVChannelLayout carries only the channel count). + * All orders may be treated as if they were AV_CHANNEL_ORDER_UNSPEC by + * ignoring everything but the channel count, as long as av_channel_layout_check() + * considers they are valid. + * + * Unlike most structures in FFmpeg, sizeof(AVChannelLayout) is a part of the + * public ABI and may be used by the caller. E.g. it may be allocated on stack + * or embedded in caller-defined structs. + * + * AVChannelLayout can be initialized as follows: + * - default initialization with {0}, followed by setting all used fields + * correctly; + * - by assigning one of the predefined AV_CHANNEL_LAYOUT_* initializers; + * - with a constructor function, such as av_channel_layout_default(), + * av_channel_layout_from_mask() or av_channel_layout_from_string(). + * + * The channel layout must be uninitialized with av_channel_layout_uninit() + * + * Copying an AVChannelLayout via assigning is forbidden, + * av_channel_layout_copy() must be used instead (and its return value should + * be checked) + * + * No new fields may be added to it without a major version bump, except for + * new elements of the union fitting in sizeof(uint64_t). + */ +typedef struct AVChannelLayout { + /** + * Channel order used in this layout. + * This is a mandatory field. + */ + enum AVChannelOrder order; + + /** + * Number of channels in this layout. Mandatory field. + */ + int nb_channels; + + /** + * Details about which channels are present in this layout. + * For AV_CHANNEL_ORDER_UNSPEC, this field is undefined and must not be + * used. + */ + union { + /** + * This member must be used for AV_CHANNEL_ORDER_NATIVE, and may be used + * for AV_CHANNEL_ORDER_AMBISONIC to signal non-diegetic channels. + * It is a bitmask, where the position of each set bit means that the + * AVChannel with the corresponding value is present. + * + * I.e. when (mask & (1 << AV_CHAN_FOO)) is non-zero, then AV_CHAN_FOO + * is present in the layout. Otherwise it is not present. + * + * @note when a channel layout using a bitmask is constructed or + * modified manually (i.e. not using any of the av_channel_layout_* + * functions), the code doing it must ensure that the number of set bits + * is equal to nb_channels. + */ + uint64_t mask; + /** + * This member must be used when the channel order is + * AV_CHANNEL_ORDER_CUSTOM. It is a nb_channels-sized array, with each + * element signalling the presence of the AVChannel with the + * corresponding value in map[i].id. + * + * I.e. when map[i].id is equal to AV_CHAN_FOO, then AV_CH_FOO is the + * i-th channel in the audio data. + * + * When map[i].id is in the range between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END (inclusive), the channel contains an ambisonic + * component with ACN index (as defined above) + * n = map[i].id - AV_CHAN_AMBISONIC_BASE. + * + * map[i].name may be filled with a 0-terminated string, in which case + * it will be used for the purpose of identifying the channel with the + * convenience functions below. Otherwise it must be zeroed. + */ + AVChannelCustom *map; + } u; + + /** + * For some private data of the user. + */ + void *opaque; +} AVChannelLayout; + +/** + * Macro to define native channel layouts + * + * @note This doesn't use designated initializers for compatibility with C++ 17 and older. + */ +#define AV_CHANNEL_LAYOUT_MASK(nb, m) \ + { /* .order */ AV_CHANNEL_ORDER_NATIVE, \ + /* .nb_channels */ (nb), \ + /* .u.mask */ { m }, \ + /* .opaque */ NULL } + +/** + * @name Common pre-defined channel layouts + * @{ + */ +#define AV_CHANNEL_LAYOUT_MONO AV_CHANNEL_LAYOUT_MASK(1, AV_CH_LAYOUT_MONO) +#define AV_CHANNEL_LAYOUT_STEREO AV_CHANNEL_LAYOUT_MASK(2, AV_CH_LAYOUT_STEREO) +#define AV_CHANNEL_LAYOUT_2POINT1 AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_2POINT1) +#define AV_CHANNEL_LAYOUT_2_1 AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_2_1) +#define AV_CHANNEL_LAYOUT_SURROUND AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_SURROUND) +#define AV_CHANNEL_LAYOUT_3POINT1 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_3POINT1) +#define AV_CHANNEL_LAYOUT_4POINT0 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_4POINT0) +#define AV_CHANNEL_LAYOUT_4POINT1 AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_4POINT1) +#define AV_CHANNEL_LAYOUT_2_2 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_2_2) +#define AV_CHANNEL_LAYOUT_QUAD AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_QUAD) +#define AV_CHANNEL_LAYOUT_5POINT0 AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_5POINT0) +#define AV_CHANNEL_LAYOUT_5POINT1 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_5POINT1) +#define AV_CHANNEL_LAYOUT_5POINT0_BACK AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_5POINT0_BACK) +#define AV_CHANNEL_LAYOUT_5POINT1_BACK AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_5POINT1_BACK) +#define AV_CHANNEL_LAYOUT_6POINT0 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_6POINT0) +#define AV_CHANNEL_LAYOUT_6POINT0_FRONT AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_6POINT0_FRONT) +#define AV_CHANNEL_LAYOUT_3POINT1POINT2 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_3POINT1POINT2) +#define AV_CHANNEL_LAYOUT_HEXAGONAL AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_HEXAGONAL) +#define AV_CHANNEL_LAYOUT_6POINT1 AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1) +#define AV_CHANNEL_LAYOUT_6POINT1_BACK AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1_BACK) +#define AV_CHANNEL_LAYOUT_6POINT1_FRONT AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1_FRONT) +#define AV_CHANNEL_LAYOUT_7POINT0 AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_7POINT0) +#define AV_CHANNEL_LAYOUT_7POINT0_FRONT AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_7POINT0_FRONT) +#define AV_CHANNEL_LAYOUT_7POINT1 AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1) +#define AV_CHANNEL_LAYOUT_7POINT1_WIDE AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1_WIDE) +#define AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1_WIDE_BACK) +#define AV_CHANNEL_LAYOUT_5POINT1POINT2 AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_5POINT1POINT2) +#define AV_CHANNEL_LAYOUT_5POINT1POINT2_BACK AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_5POINT1POINT2_BACK) +#define AV_CHANNEL_LAYOUT_OCTAGONAL AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_OCTAGONAL) +#define AV_CHANNEL_LAYOUT_CUBE AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_CUBE) +#define AV_CHANNEL_LAYOUT_5POINT1POINT4_BACK AV_CHANNEL_LAYOUT_MASK(10, AV_CH_LAYOUT_5POINT1POINT4_BACK) +#define AV_CHANNEL_LAYOUT_7POINT1POINT2 AV_CHANNEL_LAYOUT_MASK(10, AV_CH_LAYOUT_7POINT1POINT2) +#define AV_CHANNEL_LAYOUT_7POINT1POINT4_BACK AV_CHANNEL_LAYOUT_MASK(12, AV_CH_LAYOUT_7POINT1POINT4_BACK) +#define AV_CHANNEL_LAYOUT_7POINT2POINT3 AV_CHANNEL_LAYOUT_MASK(12, AV_CH_LAYOUT_7POINT2POINT3) +#define AV_CHANNEL_LAYOUT_9POINT1POINT4_BACK AV_CHANNEL_LAYOUT_MASK(14, AV_CH_LAYOUT_9POINT1POINT4_BACK) +#define AV_CHANNEL_LAYOUT_9POINT1POINT6 AV_CHANNEL_LAYOUT_MASK(16, AV_CH_LAYOUT_9POINT1POINT6) +#define AV_CHANNEL_LAYOUT_HEXADECAGONAL AV_CHANNEL_LAYOUT_MASK(16, AV_CH_LAYOUT_HEXADECAGONAL) +#define AV_CHANNEL_LAYOUT_BINAURAL AV_CHANNEL_LAYOUT_MASK(2, AV_CH_LAYOUT_BINAURAL) +#define AV_CHANNEL_LAYOUT_STEREO_DOWNMIX AV_CHANNEL_LAYOUT_MASK(2, AV_CH_LAYOUT_STEREO_DOWNMIX) +#define AV_CHANNEL_LAYOUT_22POINT2 AV_CHANNEL_LAYOUT_MASK(24, AV_CH_LAYOUT_22POINT2) + +#define AV_CHANNEL_LAYOUT_7POINT1_TOP_BACK AV_CHANNEL_LAYOUT_5POINT1POINT2_BACK + +#define AV_CHANNEL_LAYOUT_AMBISONIC_FIRST_ORDER \ + { /* .order */ AV_CHANNEL_ORDER_AMBISONIC, \ + /* .nb_channels */ 4, \ + /* .u.mask */ { 0 }, \ + /* .opaque */ NULL } +/** @} */ + +struct AVBPrint; + +/** + * Get a human readable string in an abbreviated form describing a given channel. + * This is the inverse function of @ref av_channel_from_string(). + * + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @param channel the AVChannel whose name to get + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel); + +/** + * bprint variant of av_channel_name(). + * + * @note the string will be appended to the bprint buffer. + */ +void av_channel_name_bprint(struct AVBPrint *bp, enum AVChannel channel_id); + +/** + * Get a human readable string describing a given channel. + * + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @param channel the AVChannel whose description to get + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel); + +/** + * bprint variant of av_channel_description(). + * + * @note the string will be appended to the bprint buffer. + */ +void av_channel_description_bprint(struct AVBPrint *bp, enum AVChannel channel_id); + +/** + * This is the inverse function of @ref av_channel_name(). + * + * @return the channel with the given name + * AV_CHAN_NONE when name does not identify a known channel + */ +enum AVChannel av_channel_from_string(const char *name); + +/** + * Initialize a custom channel layout with the specified number of channels. + * The channel map will be allocated and the designation of all channels will + * be set to AV_CHAN_UNKNOWN. + * + * This is only a convenience helper function, a custom channel layout can also + * be constructed without using this. + * + * @param channel_layout the layout structure to be initialized + * @param nb_channels the number of channels + * + * @return 0 on success + * AVERROR(EINVAL) if the number of channels <= 0 + * AVERROR(ENOMEM) if the channel map could not be allocated + */ +int av_channel_layout_custom_init(AVChannelLayout *channel_layout, int nb_channels); + +/** + * Initialize a native channel layout from a bitmask indicating which channels + * are present. + * + * @param channel_layout the layout structure to be initialized + * @param mask bitmask describing the channel layout + * + * @return 0 on success + * AVERROR(EINVAL) for invalid mask values + */ +int av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask); + +/** + * Initialize a channel layout from a given string description. + * The input string can be represented by: + * - the formal channel layout name (returned by av_channel_layout_describe()) + * - single or multiple channel names (returned by av_channel_name(), eg. "FL", + * or concatenated with "+", each optionally containing a custom name after + * a "@", eg. "FL@Left+FR@Right+LFE") + * - a decimal or hexadecimal value of a native channel layout (eg. "4" or "0x4") + * - the number of channels with default layout (eg. "4c") + * - the number of unordered channels (eg. "4C" or "4 channels") + * - the ambisonic order followed by optional non-diegetic channels (eg. + * "ambisonic 2+stereo") + * On error, the channel layout will remain uninitialized, but not necessarily + * untouched. + * + * @param channel_layout uninitialized channel layout for the result + * @param str string describing the channel layout + * @return 0 on success parsing the channel layout + * AVERROR(EINVAL) if an invalid channel layout string was provided + * AVERROR(ENOMEM) if there was not enough memory + */ +int av_channel_layout_from_string(AVChannelLayout *channel_layout, + const char *str); + +/** + * Get the default channel layout for a given number of channels. + * + * @param ch_layout the layout structure to be initialized + * @param nb_channels number of channels + */ +void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels); + +/** + * Iterate over all standard channel layouts. + * + * @param opaque a pointer where libavutil will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the standard channel layout or NULL when the iteration is + * finished + */ +const AVChannelLayout *av_channel_layout_standard(void **opaque); + +/** + * Free any allocated data in the channel layout and reset the channel + * count to 0. + * + * @param channel_layout the layout structure to be uninitialized + */ +void av_channel_layout_uninit(AVChannelLayout *channel_layout); + +/** + * Make a copy of a channel layout. This differs from just assigning src to dst + * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM. + * + * @note the destination channel_layout will be always uninitialized before copy. + * + * @param dst destination channel layout + * @param src source channel layout + * @return 0 on success, a negative AVERROR on error. + */ +int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src); + +/** + * Get a human-readable string describing the channel layout properties. + * The string will be in the same format that is accepted by + * @ref av_channel_layout_from_string(), allowing to rebuild the same + * channel layout, except for opaque pointers. + * + * @param channel_layout channel layout to be described + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_layout_describe(const AVChannelLayout *channel_layout, + char *buf, size_t buf_size); + +/** + * bprint variant of av_channel_layout_describe(). + * + * @note the string will be appended to the bprint buffer. + * @return 0 on success, or a negative AVERROR value on failure. + */ +int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout, + struct AVBPrint *bp); + +/** + * Get the channel with the given index in a channel layout. + * + * @param channel_layout input channel layout + * @param idx index of the channel + * @return channel with the index idx in channel_layout on success or + * AV_CHAN_NONE on failure (if idx is not valid or the channel order is + * unspecified) + */ +enum AVChannel +av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx); + +/** + * Get the index of a given channel in a channel layout. In case multiple + * channels are found, only the first match will be returned. + * + * @param channel_layout input channel layout + * @param channel the channel whose index to obtain + * @return index of channel in channel_layout on success or a negative number if + * channel is not present in channel_layout. + */ +int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, + enum AVChannel channel); + +/** + * Get the index in a channel layout of a channel described by the given string. + * In case multiple channels are found, only the first match will be returned. + * + * This function accepts channel names in the same format as + * @ref av_channel_from_string(). + * + * @param channel_layout input channel layout + * @param name string describing the channel whose index to obtain + * @return a channel index described by the given string, or a negative AVERROR + * value. + */ +int av_channel_layout_index_from_string(const AVChannelLayout *channel_layout, + const char *name); + +/** + * Get a channel described by the given string. + * + * This function accepts channel names in the same format as + * @ref av_channel_from_string(). + * + * @param channel_layout input channel layout + * @param name string describing the channel to obtain + * @return a channel described by the given string in channel_layout on success + * or AV_CHAN_NONE on failure (if the string is not valid or the channel + * order is unspecified) + */ +enum AVChannel +av_channel_layout_channel_from_string(const AVChannelLayout *channel_layout, + const char *name); + +/** + * Find out what channels from a given set are present in a channel layout, + * without regard for their positions. + * + * @param channel_layout input channel layout + * @param mask a combination of AV_CH_* representing a set of channels + * @return a bitfield representing all the channels from mask that are present + * in channel_layout + */ +uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout, + uint64_t mask); + +/** + * Check whether a channel layout is valid, i.e. can possibly describe audio + * data. + * + * @param channel_layout input channel layout + * @return 1 if channel_layout is valid, 0 otherwise. + */ +int av_channel_layout_check(const AVChannelLayout *channel_layout); + +/** + * Check whether two channel layouts are semantically the same, i.e. the same + * channels are present on the same positions in both. + * + * If one of the channel layouts is AV_CHANNEL_ORDER_UNSPEC, while the other is + * not, they are considered to be unequal. If both are AV_CHANNEL_ORDER_UNSPEC, + * they are considered equal iff the channel counts are the same in both. + * + * @param chl input channel layout + * @param chl1 input channel layout + * @return 0 if chl and chl1 are equal, 1 if they are not equal. A negative + * AVERROR code if one or both are invalid. + */ +int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1); + +/** + * Return the order if the layout is n-th order standard-order ambisonic. + * The presence of optional extra non-diegetic channels at the end is not taken + * into account. + * + * @param channel_layout input channel layout + * @return the order of the layout, a negative error code otherwise. + */ +int av_channel_layout_ambisonic_order(const AVChannelLayout *channel_layout); + +/** + * The conversion must be lossless. + */ +#define AV_CHANNEL_LAYOUT_RETYPE_FLAG_LOSSLESS (1 << 0) + +/** + * The specified retype target order is ignored and the simplest possible + * (canonical) order is used for which the input layout can be losslessy + * represented. + */ +#define AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL (1 << 1) + +/** + * Change the AVChannelOrder of a channel layout. + * + * Change of AVChannelOrder can be either lossless or lossy. In case of a + * lossless conversion all the channel designations and the associated channel + * names (if any) are kept. On a lossy conversion the channel names and channel + * designations might be lost depending on the capabilities of the desired + * AVChannelOrder. Note that some conversions are simply not possible in which + * case this function returns AVERROR(ENOSYS). + * + * The following conversions are supported: + * + * Any -> Custom : Always possible, always lossless. + * Any -> Unspecified: Always possible, lossless if channel designations + * are all unknown and channel names are not used, lossy otherwise. + * Custom -> Ambisonic : Possible if it contains ambisonic channels with + * optional non-diegetic channels in the end. Lossy if the channels have + * custom names, lossless otherwise. + * Custom -> Native : Possible if it contains native channels in native + * order. Lossy if the channels have custom names, lossless otherwise. + * + * On error this function keeps the original channel layout untouched. + * + * @param channel_layout channel layout which will be changed + * @param order the desired channel layout order + * @param flags a combination of AV_CHANNEL_LAYOUT_RETYPE_FLAG_* constants + * @return 0 if the conversion was successful and lossless or if the channel + * layout was already in the desired order + * >0 if the conversion was successful but lossy + * AVERROR(ENOSYS) if the conversion was not possible (or would be + * lossy and AV_CHANNEL_LAYOUT_RETYPE_FLAG_LOSSLESS was specified) + * AVERROR(EINVAL), AVERROR(ENOMEM) on error + */ +int av_channel_layout_retype(AVChannelLayout *channel_layout, enum AVChannelOrder order, int flags); + +/** + * @} + */ + +#endif /* AVUTIL_CHANNEL_LAYOUT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/common.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/common.h new file mode 100644 index 0000000000000..3b830daf30857 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/common.h @@ -0,0 +1,589 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * common internal and external API header + */ + +#ifndef AVUTIL_COMMON_H +#define AVUTIL_COMMON_H + +#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) && !defined(UINT64_C) +#error missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "error.h" +#include "macros.h" +#include "version.h" + +#ifdef HAVE_AV_CONFIG_H +# include "config.h" +# include "intmath.h" +# include "internal.h" +#else +# include "mem.h" +#endif /* HAVE_AV_CONFIG_H */ + +//rounded division & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>=0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +/* Fast a/(1<=0 and b>=0 */ +#define AV_CEIL_RSHIFT(a,b) (!av_builtin_constant_p(b) ? -((-(a)) >> (b)) \ + : ((a) + (1<<(b)) - 1) >> (b)) +/* Backwards compat. */ +#define FF_CEIL_RSHIFT AV_CEIL_RSHIFT + +#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b)) +#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b)) + +/** + * Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they + * are not representable as absolute values of their type. This is the same + * as with *abs() + * @see FFNABS() + */ +#define FFABS(a) ((a) >= 0 ? (a) : (-(a))) +#define FFSIGN(a) ((a) > 0 ? 1 : -1) + +/** + * Negative Absolute value. + * this works for all integers of all types. + * As with many macros, this evaluates its argument twice, it thus must not have + * a sideeffect, that is FFNABS(x++) has undefined behavior. + */ +#define FFNABS(a) ((a) <= 0 ? (a) : (-(a))) + +/** + * Unsigned Absolute value. + * This takes the absolute value of a signed int and returns it as a unsigned. + * This also works with INT_MIN which would otherwise not be representable + * As with many macros, this evaluates its argument twice. + */ +#define FFABSU(a) ((a) <= 0 ? -(unsigned)(a) : (unsigned)(a)) +#define FFABS64U(a) ((a) <= 0 ? -(uint64_t)(a) : (uint64_t)(a)) + +/* misc math functions */ + +#ifndef av_ceil_log2 +# define av_ceil_log2 av_ceil_log2_c +#endif +#ifndef av_clip +# define av_clip av_clip_c +#endif +#ifndef av_clip64 +# define av_clip64 av_clip64_c +#endif +#ifndef av_clip_uint8 +# define av_clip_uint8 av_clip_uint8_c +#endif +#ifndef av_clip_int8 +# define av_clip_int8 av_clip_int8_c +#endif +#ifndef av_clip_uint16 +# define av_clip_uint16 av_clip_uint16_c +#endif +#ifndef av_clip_int16 +# define av_clip_int16 av_clip_int16_c +#endif +#ifndef av_clipl_int32 +# define av_clipl_int32 av_clipl_int32_c +#endif +#ifndef av_clip_intp2 +# define av_clip_intp2 av_clip_intp2_c +#endif +#ifndef av_clip_uintp2 +# define av_clip_uintp2 av_clip_uintp2_c +#endif +#ifndef av_sat_add32 +# define av_sat_add32 av_sat_add32_c +#endif +#ifndef av_sat_dadd32 +# define av_sat_dadd32 av_sat_dadd32_c +#endif +#ifndef av_sat_sub32 +# define av_sat_sub32 av_sat_sub32_c +#endif +#ifndef av_sat_dsub32 +# define av_sat_dsub32 av_sat_dsub32_c +#endif +#ifndef av_sat_add64 +# define av_sat_add64 av_sat_add64_c +#endif +#ifndef av_sat_sub64 +# define av_sat_sub64 av_sat_sub64_c +#endif +#ifndef av_clipf +# define av_clipf av_clipf_c +#endif +#ifndef av_clipd +# define av_clipd av_clipd_c +#endif +#ifndef av_zero_extend +# define av_zero_extend av_zero_extend_c +#endif +#ifndef av_popcount +# define av_popcount av_popcount_c +#endif +#ifndef av_popcount64 +# define av_popcount64 av_popcount64_c +#endif +#ifndef av_parity +# define av_parity av_parity_c +#endif + +#ifndef av_log2 +av_const int av_log2(unsigned v); +#endif + +#ifndef av_log2_16bit +av_const int av_log2_16bit(unsigned v); +#endif + +/** + * Clip a signed integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int av_clip_c(int a, int amin, int amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed 64bit integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, int64_t amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed integer value into the 0-255 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint8_t av_clip_uint8_c(int a) +{ + if (a&(~0xFF)) return (~a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -128,127 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int8_t av_clip_int8_c(int a) +{ + if ((a+0x80U) & ~0xFF) return (a>>31) ^ 0x7F; + else return a; +} + +/** + * Clip a signed integer value into the 0-65535 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint16_t av_clip_uint16_c(int a) +{ + if (a&(~0xFFFF)) return (~a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -32768,32767 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int16_t av_clip_int16_c(int a) +{ + if ((a+0x8000U) & ~0xFFFF) return (a>>31) ^ 0x7FFF; + else return a; +} + +/** + * Clip a signed 64-bit integer value into the -2147483648,2147483647 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a) +{ + if ((a+UINT64_C(0x80000000)) & ~UINT64_C(0xFFFFFFFF)) return (int32_t)((a>>63) ^ 0x7FFFFFFF); + else return (int32_t)a; +} + +/** + * Clip a signed integer into the -(2^p),(2^p-1) range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const int av_clip_intp2_c(int a, int p) +{ + if (((unsigned)a + (1U << p)) & ~((2U << p) - 1)) + return (a >> 31) ^ ((1 << p) - 1); + else + return a; +} + +/** + * Clip a signed integer to an unsigned power of two range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p) +{ + if (a & ~((1U<> 31 & ((1U<= 2 + if (p > 31) abort(); +#endif + return a & ((1U << p) - 1); +} + +#if FF_API_MOD_UINTP2 +#ifndef av_mod_uintp2 +# define av_mod_uintp2 av_mod_uintp2_c +#endif +attribute_deprecated +static av_always_inline av_const unsigned av_mod_uintp2_c(unsigned a, unsigned p) +{ + return av_zero_extend_c(a, p); +} +#endif + +/** + * Add two signed 32-bit values with saturation. + * + * @param a one value + * @param b another value + * @return sum with signed saturation + */ +static av_always_inline int av_sat_add32_c(int a, int b) +{ + return av_clipl_int32((int64_t)a + b); +} + +/** + * Add a doubled value to another value with saturation at both stages. + * + * @param a first value + * @param b value doubled and added to a + * @return sum sat(a + sat(2*b)) with signed saturation + */ +static av_always_inline int av_sat_dadd32_c(int a, int b) +{ + return av_sat_add32(a, av_sat_add32(b, b)); +} + +/** + * Subtract two signed 32-bit values with saturation. + * + * @param a one value + * @param b another value + * @return difference with signed saturation + */ +static av_always_inline int av_sat_sub32_c(int a, int b) +{ + return av_clipl_int32((int64_t)a - b); +} + +/** + * Subtract a doubled value from another value with saturation at both stages. + * + * @param a first value + * @param b value doubled and subtracted from a + * @return difference sat(a - sat(2*b)) with signed saturation + */ +static av_always_inline int av_sat_dsub32_c(int a, int b) +{ + return av_sat_sub32(a, av_sat_add32(b, b)); +} + +/** + * Add two signed 64-bit values with saturation. + * + * @param a one value + * @param b another value + * @return sum with signed saturation + */ +static av_always_inline int64_t av_sat_add64_c(int64_t a, int64_t b) { +#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_add_overflow) + int64_t tmp; + return !__builtin_add_overflow(a, b, &tmp) ? tmp : (tmp < 0 ? INT64_MAX : INT64_MIN); +#else + int64_t s = a+(uint64_t)b; + if ((int64_t)(a^b | ~s^b) >= 0) + return INT64_MAX ^ (b >> 63); + return s; +#endif +} + +/** + * Subtract two signed 64-bit values with saturation. + * + * @param a one value + * @param b another value + * @return difference with signed saturation + */ +static av_always_inline int64_t av_sat_sub64_c(int64_t a, int64_t b) { +#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_sub_overflow) + int64_t tmp; + return !__builtin_sub_overflow(a, b, &tmp) ? tmp : (tmp < 0 ? INT64_MAX : INT64_MIN); +#else + if (b <= 0 && a >= INT64_MAX + b) + return INT64_MAX; + if (b >= 0 && a <= INT64_MIN + b) + return INT64_MIN; + return a - b; +#endif +} + +/** + * Clip a float value into the amin-amax range. + * If a is nan or -inf amin will be returned. + * If a is +inf amax will be returned. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const float av_clipf_c(float a, float amin, float amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + return FFMIN(FFMAX(a, amin), amax); +} + +/** + * Clip a double value into the amin-amax range. + * If a is nan or -inf amin will be returned. + * If a is +inf amax will be returned. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const double av_clipd_c(double a, double amin, double amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + return FFMIN(FFMAX(a, amin), amax); +} + +/** Compute ceil(log2(x)). + * @param x value used to compute ceil(log2(x)) + * @return computed ceiling of log2(x) + */ +static av_always_inline av_const int av_ceil_log2_c(int x) +{ + return av_log2((x - 1U) << 1); +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount_c(uint32_t x) +{ + x -= (x >> 1) & 0x55555555; + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x += x >> 8; + return (x + (x >> 16)) & 0x3F; +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount64_c(uint64_t x) +{ + return av_popcount((uint32_t)x) + av_popcount((uint32_t)(x >> 32)); +} + +static av_always_inline av_const int av_parity_c(uint32_t v) +{ + return av_popcount(v) & 1; +} + +/** + * Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_BYTE Expression reading one byte from the input. + * Evaluated up to 7 times (4 for the currently + * assigned Unicode range). With a memory buffer + * input, this could be *ptr++, or if you want to make sure + * that *ptr stops at the end of a NULL terminated string then + * *ptr ? *ptr++ : 0 + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + * + * @warning ERROR should not contain a loop control statement which + * could interact with the internal while loop, and should force an + * exit from the macro code (e.g. through a goto or a return) in order + * to prevent undefined results. + */ +#define GET_UTF8(val, GET_BYTE, ERROR)\ + val= (GET_BYTE);\ + {\ + uint32_t top = (val & 128) >> 1;\ + if ((val & 0xc0) == 0x80 || val >= 0xFE)\ + {ERROR}\ + while (val & top) {\ + unsigned int tmp = (GET_BYTE) - 128;\ + if(tmp>>6)\ + {ERROR}\ + val= (val<<6) + tmp;\ + top <<= 5;\ + }\ + val &= (top << 1) - 1;\ + } + +/** + * Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_16BIT Expression returning two bytes of UTF-16 data converted + * to native byte order. Evaluated one or two times. + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + */ +#define GET_UTF16(val, GET_16BIT, ERROR)\ + val = (GET_16BIT);\ + {\ + unsigned int hi = val - 0xD800;\ + if (hi < 0x800) {\ + val = (GET_16BIT) - 0xDC00;\ + if (val > 0x3FFU || hi > 0x3FFU)\ + {ERROR}\ + val += (hi<<10) + 0x10000;\ + }\ + }\ + +/** + * @def PUT_UTF8(val, tmp, PUT_BYTE) + * Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-8. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint8_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_BYTE. + * @param PUT_BYTE writes the converted UTF-8 bytes to any proper destination. + * It could be a function or a statement, and uses tmp as the input byte. + * For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be + * executed up to 4 times for values in the valid UTF-8 range and up to + * 7 times in the general case, depending on the length of the converted + * Unicode character. + */ +#define PUT_UTF8(val, tmp, PUT_BYTE)\ + {\ + int bytes, shift;\ + uint32_t in = val;\ + if (in < 0x80) {\ + tmp = in;\ + PUT_BYTE\ + } else {\ + bytes = (av_log2(in) + 4) / 5;\ + shift = (bytes - 1) * 6;\ + tmp = (256 - (256 >> bytes)) | (in >> shift);\ + PUT_BYTE\ + while (shift >= 6) {\ + shift -= 6;\ + tmp = 0x80 | ((in >> shift) & 0x3f);\ + PUT_BYTE\ + }\ + }\ + } + +/** + * @def PUT_UTF16(val, tmp, PUT_16BIT) + * Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-16. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint16_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_16BIT. + * @param PUT_16BIT writes the converted UTF-16 data to any proper destination + * in desired endianness. It could be a function or a statement, and uses tmp + * as the input byte. For example, PUT_BYTE could be "*output++ = tmp;" + * PUT_BYTE will be executed 1 or 2 times depending on input character. + */ +#define PUT_UTF16(val, tmp, PUT_16BIT)\ + {\ + uint32_t in = val;\ + if (in < 0x10000) {\ + tmp = in;\ + PUT_16BIT\ + } else {\ + tmp = 0xD800 | ((in - 0x10000) >> 10);\ + PUT_16BIT\ + tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\ + PUT_16BIT\ + }\ + }\ + +#endif /* AVUTIL_COMMON_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/dict.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/dict.h new file mode 100644 index 0000000000000..93c7cbf1286c3 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/dict.h @@ -0,0 +1,242 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Public dictionary API. + * @deprecated + * AVDictionary is provided for compatibility with libav. It is both in + * implementation as well as API inefficient. It does not scale and is + * extremely slow with large dictionaries. + * It is recommended that new code uses our tree container from tree.c/h + * where applicable, which uses AVL trees to achieve O(log n) performance. + */ + +#ifndef AVUTIL_DICT_H +#define AVUTIL_DICT_H + +#include + +/** + * @addtogroup lavu_dict AVDictionary + * @ingroup lavu_data + * + * @brief Simple key:value store + * + * @{ + * Dictionaries are used for storing key-value pairs. + * + * - To **create an AVDictionary**, simply pass an address of a NULL + * pointer to av_dict_set(). NULL can be used as an empty dictionary + * wherever a pointer to an AVDictionary is required. + * - To **insert an entry**, use av_dict_set(). + * - Use av_dict_get() to **retrieve an entry**. + * - To **iterate over all entries**, use av_dict_iterate(). + * - In order to **free the dictionary and all its contents**, use av_dict_free(). + * + @code + AVDictionary *d = NULL; // "create" an empty dictionary + AVDictionaryEntry *t = NULL; + + av_dict_set(&d, "foo", "bar", 0); // add an entry + + char *k = av_strdup("key"); // if your strings are already allocated, + char *v = av_strdup("value"); // you can avoid copying them like this + av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); + + while ((t = av_dict_iterate(d, t))) { + <....> // iterate over all entries in d + } + av_dict_free(&d); + @endcode + */ + +/** + * @name AVDictionary Flags + * Flags that influence behavior of the matching of keys or insertion to the dictionary. + * @{ + */ +#define AV_DICT_MATCH_CASE 1 /**< Only get an entry with exact-case key match. Only relevant in av_dict_get(). */ +#define AV_DICT_IGNORE_SUFFIX 2 /**< Return first entry in a dictionary whose first part corresponds to the search key, + ignoring the suffix of the found key string. Only relevant in av_dict_get(). */ +#define AV_DICT_DONT_STRDUP_KEY 4 /**< Take ownership of a key that's been + allocated with av_malloc() or another memory allocation function. */ +#define AV_DICT_DONT_STRDUP_VAL 8 /**< Take ownership of a value that's been + allocated with av_malloc() or another memory allocation function. */ +#define AV_DICT_DONT_OVERWRITE 16 /**< Don't overwrite existing entries. */ +#define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no + delimiter is added, the strings are simply concatenated. */ +#define AV_DICT_MULTIKEY 64 /**< Allow to store several equal keys in the dictionary */ +#define AV_DICT_DEDUP 128 /**< If inserting a value that already exists for a key, do nothing. Only relevant with AV_DICT_MULTIKEY. */ +/** + * @} + */ + +typedef struct AVDictionaryEntry { + char *key; + char *value; +} AVDictionaryEntry; + +typedef struct AVDictionary AVDictionary; + +/** + * Get a dictionary entry with matching key. + * + * The returned entry key or value must not be changed, or it will + * cause undefined behavior. + * + * @param prev Set to the previous matching element to find the next. + * If set to NULL the first matching element is returned. + * @param key Matching key + * @param flags A collection of AV_DICT_* flags controlling how the + * entry is retrieved + * + * @return Found entry or NULL in case no matching entry was found in the dictionary + */ +AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key, + const AVDictionaryEntry *prev, int flags); + +/** + * Iterate over a dictionary + * + * Iterates through all entries in the dictionary. + * + * @warning The returned AVDictionaryEntry key/value must not be changed. + * + * @warning As av_dict_set() invalidates all previous entries returned + * by this function, it must not be called while iterating over the dict. + * + * Typical usage: + * @code + * const AVDictionaryEntry *e = NULL; + * while ((e = av_dict_iterate(m, e))) { + * // ... + * } + * @endcode + * + * @param m The dictionary to iterate over + * @param prev Pointer to the previous AVDictionaryEntry, NULL initially + * + * @retval AVDictionaryEntry* The next element in the dictionary + * @retval NULL No more elements in the dictionary + */ +const AVDictionaryEntry *av_dict_iterate(const AVDictionary *m, + const AVDictionaryEntry *prev); + +/** + * Get number of entries in dictionary. + * + * @param m dictionary + * @return number of entries in dictionary + */ +int av_dict_count(const AVDictionary *m); + +/** + * Set the given entry in *pm, overwriting an existing entry. + * + * Note: If AV_DICT_DONT_STRDUP_KEY or AV_DICT_DONT_STRDUP_VAL is set, + * these arguments will be freed on error. + * + * @warning Adding a new entry to a dictionary invalidates all existing entries + * previously returned with av_dict_get() or av_dict_iterate(). + * + * @param pm Pointer to a pointer to a dictionary struct. If *pm is NULL + * a dictionary struct is allocated and put in *pm. + * @param key Entry key to add to *pm (will either be av_strduped or added as a new key depending on flags) + * @param value Entry value to add to *pm (will be av_strduped or added as a new key depending on flags). + * Passing a NULL value will cause an existing entry to be deleted. + * + * @return >= 0 on success otherwise an error code <0 + */ +int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags); + +/** + * Convenience wrapper for av_dict_set() that converts the value to a string + * and stores it. + * + * Note: If ::AV_DICT_DONT_STRDUP_KEY is set, key will be freed on error. + */ +int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags); + +/** + * Parse the key/value pairs list and add the parsed entries to a dictionary. + * + * In case of failure, all the successfully set entries are stored in + * *pm. You may need to manually free the created dictionary. + * + * @param key_val_sep A 0-terminated list of characters used to separate + * key from value + * @param pairs_sep A 0-terminated list of characters used to separate + * two pairs from each other + * @param flags Flags to use when adding to the dictionary. + * ::AV_DICT_DONT_STRDUP_KEY and ::AV_DICT_DONT_STRDUP_VAL + * are ignored since the key/value tokens will always + * be duplicated. + * + * @return 0 on success, negative AVERROR code on failure + */ +int av_dict_parse_string(AVDictionary **pm, const char *str, + const char *key_val_sep, const char *pairs_sep, + int flags); + +/** + * Copy entries from one AVDictionary struct into another. + * + * @note Metadata is read using the ::AV_DICT_IGNORE_SUFFIX flag + * + * @param dst Pointer to a pointer to a AVDictionary struct to copy into. If *dst is NULL, + * this function will allocate a struct for you and put it in *dst + * @param src Pointer to the source AVDictionary struct to copy items from. + * @param flags Flags to use when setting entries in *dst + * + * @return 0 on success, negative AVERROR code on failure. If dst was allocated + * by this function, callers should free the associated memory. + */ +int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags); + +/** + * Free all the memory allocated for an AVDictionary struct + * and all keys and values. + */ +void av_dict_free(AVDictionary **m); + +/** + * Get dictionary entries as a string. + * + * Create a string containing dictionary's entries. + * Such string may be passed back to av_dict_parse_string(). + * @note String is escaped with backslashes ('\'). + * + * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same. + * + * @param[in] m The dictionary + * @param[out] buffer Pointer to buffer that will be allocated with string containing entries. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep Character used to separate key from value + * @param[in] pairs_sep Character used to separate two pairs from each other + * + * @return >= 0 on success, negative on error + */ +int av_dict_get_string(const AVDictionary *m, char **buffer, + const char key_val_sep, const char pairs_sep); + +/** + * @} + */ + +#endif /* AVUTIL_DICT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/error.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/error.h new file mode 100644 index 0000000000000..1efa86c4c106c --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/error.h @@ -0,0 +1,129 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * error code definitions + */ + +#ifndef AVUTIL_ERROR_H +#define AVUTIL_ERROR_H + +#include +#include + +#include "macros.h" + +/** + * @addtogroup lavu_error + * + * @{ + */ + + +/* error handling */ +#if EDOM > 0 +#define AVERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions. +#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value. +#else +/* Some platforms have E* and errno already negated. */ +#define AVERROR(e) (e) +#define AVUNERROR(e) (e) +#endif + +#define FFERRTAG(a, b, c, d) (-(int)MKTAG(a, b, c, d)) + +#define AVERROR_BSF_NOT_FOUND FFERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found +#define AVERROR_BUG FFERRTAG( 'B','U','G','!') ///< Internal bug, also see AVERROR_BUG2 +#define AVERROR_BUFFER_TOO_SMALL FFERRTAG( 'B','U','F','S') ///< Buffer too small +#define AVERROR_DECODER_NOT_FOUND FFERRTAG(0xF8,'D','E','C') ///< Decoder not found +#define AVERROR_DEMUXER_NOT_FOUND FFERRTAG(0xF8,'D','E','M') ///< Demuxer not found +#define AVERROR_ENCODER_NOT_FOUND FFERRTAG(0xF8,'E','N','C') ///< Encoder not found +#define AVERROR_EOF FFERRTAG( 'E','O','F',' ') ///< End of file +#define AVERROR_EXIT FFERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted +#define AVERROR_EXTERNAL FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library +#define AVERROR_FILTER_NOT_FOUND FFERRTAG(0xF8,'F','I','L') ///< Filter not found +#define AVERROR_INVALIDDATA FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input +#define AVERROR_MUXER_NOT_FOUND FFERRTAG(0xF8,'M','U','X') ///< Muxer not found +#define AVERROR_OPTION_NOT_FOUND FFERRTAG(0xF8,'O','P','T') ///< Option not found +#define AVERROR_PATCHWELCOME FFERRTAG( 'P','A','W','E') ///< Not yet implemented in FFmpeg, patches welcome +#define AVERROR_PROTOCOL_NOT_FOUND FFERRTAG(0xF8,'P','R','O') ///< Protocol not found + +#define AVERROR_STREAM_NOT_FOUND FFERRTAG(0xF8,'S','T','R') ///< Stream not found +/** + * This is semantically identical to AVERROR_BUG + * it has been introduced in Libav after our AVERROR_BUG and with a modified value. + */ +#define AVERROR_BUG2 FFERRTAG( 'B','U','G',' ') +#define AVERROR_UNKNOWN FFERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library +#define AVERROR_EXPERIMENTAL (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it. +#define AVERROR_INPUT_CHANGED (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED) +#define AVERROR_OUTPUT_CHANGED (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED) +/* HTTP & RTSP errors */ +#define AVERROR_HTTP_BAD_REQUEST FFERRTAG(0xF8,'4','0','0') +#define AVERROR_HTTP_UNAUTHORIZED FFERRTAG(0xF8,'4','0','1') +#define AVERROR_HTTP_FORBIDDEN FFERRTAG(0xF8,'4','0','3') +#define AVERROR_HTTP_NOT_FOUND FFERRTAG(0xF8,'4','0','4') +#define AVERROR_HTTP_TOO_MANY_REQUESTS FFERRTAG(0xF8,'4','2','9') +#define AVERROR_HTTP_OTHER_4XX FFERRTAG(0xF8,'4','X','X') +#define AVERROR_HTTP_SERVER_ERROR FFERRTAG(0xF8,'5','X','X') + +#define AV_ERROR_MAX_STRING_SIZE 64 + +/** + * Put a description of the AVERROR code errnum in errbuf. + * In case of failure the global variable errno is set to indicate the + * error. Even in case of failure av_strerror() will print a generic + * error message indicating the errnum provided to errbuf. + * + * @param errnum error code to describe + * @param errbuf buffer to which description is written + * @param errbuf_size the size in bytes of errbuf + * @return 0 on success, a negative value if a description for errnum + * cannot be found + */ +int av_strerror(int errnum, char *errbuf, size_t errbuf_size); + +/** + * Fill the provided buffer with a string containing an error string + * corresponding to the AVERROR code errnum. + * + * @param errbuf a buffer + * @param errbuf_size size in bytes of errbuf + * @param errnum error code to describe + * @return the buffer in input, filled with the error description + * @see av_strerror() + */ +static inline char *av_make_error_string(char *errbuf, size_t errbuf_size, int errnum) +{ + av_strerror(errnum, errbuf, errbuf_size); + return errbuf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_err2str(errnum) \ + av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum) + +/** + * @} + */ + +#endif /* AVUTIL_ERROR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/frame.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/frame.h new file mode 100644 index 0000000000000..d440cfba2e366 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/frame.h @@ -0,0 +1,1163 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_frame + * reference-counted frame API + */ + +#ifndef AVUTIL_FRAME_H +#define AVUTIL_FRAME_H + +#include +#include + +#include "avutil.h" +#include "buffer.h" +#include "channel_layout.h" +#include "dict.h" +#include "rational.h" +#include "samplefmt.h" +#include "pixfmt.h" +#include "version.h" + + +/** + * @defgroup lavu_frame AVFrame + * @ingroup lavu_data + * + * @{ + * AVFrame is an abstraction for reference-counted raw multimedia data. + */ + +enum AVFrameSideDataType { + /** + * The data is the AVPanScan struct defined in libavcodec. + */ + AV_FRAME_DATA_PANSCAN, + /** + * ATSC A53 Part 4 Closed Captions. + * A53 CC bitstream is stored as uint8_t in AVFrameSideData.data. + * The number of bytes of CC data is AVFrameSideData.size. + */ + AV_FRAME_DATA_A53_CC, + /** + * Stereoscopic 3d metadata. + * The data is the AVStereo3D struct defined in libavutil/stereo3d.h. + */ + AV_FRAME_DATA_STEREO3D, + /** + * The data is the AVMatrixEncoding enum defined in libavutil/channel_layout.h. + */ + AV_FRAME_DATA_MATRIXENCODING, + /** + * Metadata relevant to a downmix procedure. + * The data is the AVDownmixInfo struct defined in libavutil/downmix_info.h. + */ + AV_FRAME_DATA_DOWNMIX_INFO, + /** + * ReplayGain information in the form of the AVReplayGain struct. + */ + AV_FRAME_DATA_REPLAYGAIN, + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the frame for correct + * presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_FRAME_DATA_DISPLAYMATRIX, + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_FRAME_DATA_AFD, + /** + * Motion vectors exported by some codecs (on demand through the export_mvs + * flag set in the libavcodec AVCodecContext flags2 option). + * The data is the AVMotionVector struct defined in + * libavutil/motion_vector.h. + */ + AV_FRAME_DATA_MOTION_VECTORS, + /** + * Recommends skipping the specified number of samples. This is exported + * only if the "skip_manual" AVOption is set in libavcodec. + * This has the same format as AV_PKT_DATA_SKIP_SAMPLES. + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_FRAME_DATA_SKIP_SAMPLES, + /** + * This side data must be associated with an audio frame and corresponds to + * enum AVAudioServiceType defined in avcodec.h. + */ + AV_FRAME_DATA_AUDIO_SERVICE_TYPE, + /** + * Mastering display metadata associated with a video frame. The payload is + * an AVMasteringDisplayMetadata type and contains information about the + * mastering display color volume. + */ + AV_FRAME_DATA_MASTERING_DISPLAY_METADATA, + /** + * The GOP timecode in 25 bit timecode format. Data format is 64-bit integer. + * This is set on the first frame of a GOP that has a temporal reference of 0. + */ + AV_FRAME_DATA_GOP_TIMECODE, + + /** + * The data represents the AVSphericalMapping structure defined in + * libavutil/spherical.h. + */ + AV_FRAME_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This payload contains data in + * the form of the AVContentLightMetadata struct. + */ + AV_FRAME_DATA_CONTENT_LIGHT_LEVEL, + + /** + * The data contains an ICC profile as an opaque octet buffer following the + * format described by ISO 15076-1 with an optional name defined in the + * metadata key entry "name". + */ + AV_FRAME_DATA_ICC_PROFILE, + + /** + * Timecode which conforms to SMPTE ST 12-1. The data is an array of 4 uint32_t + * where the first uint32_t describes how many (1-3) of the other timecodes are used. + * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.h. + */ + AV_FRAME_DATA_S12M_TIMECODE, + + /** + * HDR dynamic metadata associated with a video frame. The payload is + * an AVDynamicHDRPlus type and contains information for color + * volume transform - application 4 of SMPTE 2094-40:2016 standard. + */ + AV_FRAME_DATA_DYNAMIC_HDR_PLUS, + + /** + * Regions Of Interest, the data is an array of AVRegionOfInterest type, the number of + * array element is implied by AVFrameSideData.size / AVRegionOfInterest.self_size. + */ + AV_FRAME_DATA_REGIONS_OF_INTEREST, + + /** + * Encoding parameters for a video frame, as described by AVVideoEncParams. + */ + AV_FRAME_DATA_VIDEO_ENC_PARAMS, + + /** + * User data unregistered metadata associated with a video frame. + * This is the H.26[45] UDU SEI message, and shouldn't be used for any other purpose + * The data is stored as uint8_t in AVFrameSideData.data which is 16 bytes of + * uuid_iso_iec_11578 followed by AVFrameSideData.size - 16 bytes of user_data_payload_byte. + */ + AV_FRAME_DATA_SEI_UNREGISTERED, + + /** + * Film grain parameters for a frame, described by AVFilmGrainParams. + * Must be present for every frame which should have film grain applied. + * + * May be present multiple times, for example when there are multiple + * alternative parameter sets for different video signal characteristics. + * The user should select the most appropriate set for the application. + */ + AV_FRAME_DATA_FILM_GRAIN_PARAMS, + + /** + * Bounding boxes for object detection and classification, + * as described by AVDetectionBBoxHeader. + */ + AV_FRAME_DATA_DETECTION_BBOXES, + + /** + * Dolby Vision RPU raw data, suitable for passing to x265 + * or other libraries. Array of uint8_t, with NAL emulation + * bytes intact. + */ + AV_FRAME_DATA_DOVI_RPU_BUFFER, + + /** + * Parsed Dolby Vision metadata, suitable for passing to a software + * implementation. The payload is the AVDOVIMetadata struct defined in + * libavutil/dovi_meta.h. + */ + AV_FRAME_DATA_DOVI_METADATA, + + /** + * HDR Vivid dynamic metadata associated with a video frame. The payload is + * an AVDynamicHDRVivid type and contains information for color + * volume transform - CUVA 005.1-2021. + */ + AV_FRAME_DATA_DYNAMIC_HDR_VIVID, + + /** + * Ambient viewing environment metadata, as defined by H.274. + */ + AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT, + + /** + * Provide encoder-specific hinting information about changed/unchanged + * portions of a frame. It can be used to pass information about which + * macroblocks can be skipped because they didn't change from the + * corresponding ones in the previous frame. This could be useful for + * applications which know this information in advance to speed up + * encoding. + */ + AV_FRAME_DATA_VIDEO_HINT, + + /** + * Raw LCEVC payload data, as a uint8_t array, with NAL emulation + * bytes intact. + */ + AV_FRAME_DATA_LCEVC, + + /** + * This side data must be associated with a video frame. + * The presence of this side data indicates that the video stream is + * composed of multiple views (e.g. stereoscopic 3D content, + * cf. H.264 Annex H or H.265 Annex G). + * The data is an int storing the view ID. + */ + AV_FRAME_DATA_VIEW_ID, + + /** + * This side data contains information about the reference display width(s) + * and reference viewing distance(s) as well as information about the + * corresponding reference stereo pair(s), i.e., the pair(s) of views to be + * displayed for the viewer's left and right eyes on the reference display + * at the reference viewing distance. + * The payload is the AV3DReferenceDisplaysInfo struct defined in + * libavutil/tdrdi.h. + */ + AV_FRAME_DATA_3D_REFERENCE_DISPLAYS, +}; + +enum AVActiveFormatDescription { + AV_AFD_SAME = 8, + AV_AFD_4_3 = 9, + AV_AFD_16_9 = 10, + AV_AFD_14_9 = 11, + AV_AFD_4_3_SP_14_9 = 13, + AV_AFD_16_9_SP_14_9 = 14, + AV_AFD_SP_4_3 = 15, +}; + + +/** + * Structure to hold side data for an AVFrame. + * + * sizeof(AVFrameSideData) is not a part of the public ABI, so new fields may be added + * to the end with a minor bump. + */ +typedef struct AVFrameSideData { + enum AVFrameSideDataType type; + uint8_t *data; + size_t size; + AVDictionary *metadata; + AVBufferRef *buf; +} AVFrameSideData; + +enum AVSideDataProps { + /** + * The side data type can be used in stream-global structures. + * Side data types without this property are only meaningful on per-frame + * basis. + */ + AV_SIDE_DATA_PROP_GLOBAL = (1 << 0), + + /** + * Multiple instances of this side data type can be meaningfully present in + * a single side data array. + */ + AV_SIDE_DATA_PROP_MULTI = (1 << 1), + + /** + * Side data depends on the video dimensions. Side data with this property + * loses its meaning when rescaling or cropping the image, unless + * either recomputed or adjusted to the new resolution. + */ + AV_SIDE_DATA_PROP_SIZE_DEPENDENT = (1 << 2), + + /** + * Side data depends on the video color space. Side data with this property + * loses its meaning when changing the video color encoding, e.g. by + * adapting to a different set of primaries or transfer characteristics. + */ + AV_SIDE_DATA_PROP_COLOR_DEPENDENT = (1 << 3), + + /** + * Side data depends on the channel layout. Side data with this property + * loses its meaning when downmixing or upmixing, unless either recomputed + * or adjusted to the new layout. + */ + AV_SIDE_DATA_PROP_CHANNEL_DEPENDENT = (1 << 4), +}; + +/** + * This struct describes the properties of a side data type. Its instance + * corresponding to a given type can be obtained from av_frame_side_data_desc(). + */ +typedef struct AVSideDataDescriptor { + /** + * Human-readable side data description. + */ + const char *name; + + /** + * Side data property flags, a combination of AVSideDataProps values. + */ + unsigned props; +} AVSideDataDescriptor; + +/** + * Structure describing a single Region Of Interest. + * + * When multiple regions are defined in a single side-data block, they + * should be ordered from most to least important - some encoders are only + * capable of supporting a limited number of distinct regions, so will have + * to truncate the list. + * + * When overlapping regions are defined, the first region containing a given + * area of the frame applies. + */ +typedef struct AVRegionOfInterest { + /** + * Must be set to the size of this data structure (that is, + * sizeof(AVRegionOfInterest)). + */ + uint32_t self_size; + /** + * Distance in pixels from the top edge of the frame to the top and + * bottom edges and from the left edge of the frame to the left and + * right edges of the rectangle defining this region of interest. + * + * The constraints on a region are encoder dependent, so the region + * actually affected may be slightly larger for alignment or other + * reasons. + */ + int top; + int bottom; + int left; + int right; + /** + * Quantisation offset. + * + * Must be in the range -1 to +1. A value of zero indicates no quality + * change. A negative value asks for better quality (less quantisation), + * while a positive value asks for worse quality (greater quantisation). + * + * The range is calibrated so that the extreme values indicate the + * largest possible offset - if the rest of the frame is encoded with the + * worst possible quality, an offset of -1 indicates that this region + * should be encoded with the best possible quality anyway. Intermediate + * values are then interpolated in some codec-dependent way. + * + * For example, in 10-bit H.264 the quantisation parameter varies between + * -12 and 51. A typical qoffset value of -1/10 therefore indicates that + * this region should be encoded with a QP around one-tenth of the full + * range better than the rest of the frame. So, if most of the frame + * were to be encoded with a QP of around 30, this region would get a QP + * of around 24 (an offset of approximately -1/10 * (51 - -12) = -6.3). + * An extreme value of -1 would indicate that this region should be + * encoded with the best possible quality regardless of the treatment of + * the rest of the frame - that is, should be encoded at a QP of -12. + */ + AVRational qoffset; +} AVRegionOfInterest; + +/** + * This structure describes decoded (raw) audio or video data. + * + * AVFrame must be allocated using av_frame_alloc(). Note that this only + * allocates the AVFrame itself, the buffers for the data must be managed + * through other means (see below). + * AVFrame must be freed with av_frame_free(). + * + * AVFrame is typically allocated once and then reused multiple times to hold + * different data (e.g. a single AVFrame to hold frames received from a + * decoder). In such a case, av_frame_unref() will free any references held by + * the frame and reset it to its original clean state before it + * is reused again. + * + * The data described by an AVFrame is usually reference counted through the + * AVBuffer API. The underlying buffer references are stored in AVFrame.buf / + * AVFrame.extended_buf. An AVFrame is considered to be reference counted if at + * least one reference is set, i.e. if AVFrame.buf[0] != NULL. In such a case, + * every single data plane must be contained in one of the buffers in + * AVFrame.buf or AVFrame.extended_buf. + * There may be a single buffer for all the data, or one separate buffer for + * each plane, or anything in between. + * + * sizeof(AVFrame) is not a part of the public ABI, so new fields may be added + * to the end with a minor bump. + * + * Fields can be accessed through AVOptions, the name string used, matches the + * C structure field name for fields accessible through AVOptions. + */ +typedef struct AVFrame { +#define AV_NUM_DATA_POINTERS 8 + /** + * pointer to the picture/channel planes. + * This might be different from the first allocated byte. For video, + * it could even point to the end of the image data. + * + * All pointers in data and extended_data must point into one of the + * AVBufferRef in buf or extended_buf. + * + * Some decoders access areas outside 0,0 - width,height, please + * see avcodec_align_dimensions2(). Some filters and swscale can read + * up to 16 bytes beyond the planes, if these filters are to be used, + * then 16 extra bytes must be allocated. + * + * NOTE: Pointers not needed by the format MUST be set to NULL. + * + * @attention In case of video, the data[] pointers can point to the + * end of image data in order to reverse line order, when used in + * combination with negative values in the linesize[] array. + */ + uint8_t *data[AV_NUM_DATA_POINTERS]; + + /** + * For video, a positive or negative value, which is typically indicating + * the size in bytes of each picture line, but it can also be: + * - the negative byte size of lines for vertical flipping + * (with data[n] pointing to the end of the data + * - a positive or negative multiple of the byte size as for accessing + * even and odd fields of a frame (possibly flipped) + * + * For audio, only linesize[0] may be set. For planar audio, each channel + * plane must be the same size. + * + * For video the linesizes should be multiples of the CPUs alignment + * preference, this is 16 or 32 for modern desktop CPUs. + * Some code requires such alignment other code can be slower without + * correct alignment, for yet other it makes no difference. + * + * @note The linesize may be larger than the size of usable data -- there + * may be extra padding present for performance reasons. + * + * @attention In case of video, line size values can be negative to achieve + * a vertically inverted iteration over image lines. + */ + int linesize[AV_NUM_DATA_POINTERS]; + + /** + * pointers to the data planes/channels. + * + * For video, this should simply point to data[]. + * + * For planar audio, each channel has a separate data pointer, and + * linesize[0] contains the size of each channel buffer. + * For packed audio, there is just one data pointer, and linesize[0] + * contains the total size of the buffer for all channels. + * + * Note: Both data and extended_data should always be set in a valid frame, + * but for planar audio with more channels that can fit in data, + * extended_data must be used in order to access all channels. + */ + uint8_t **extended_data; + + /** + * @name Video dimensions + * Video frames only. The coded dimensions (in pixels) of the video frame, + * i.e. the size of the rectangle that contains some well-defined values. + * + * @note The part of the frame intended for display/presentation is further + * restricted by the @ref cropping "Cropping rectangle". + * @{ + */ + int width, height; + /** + * @} + */ + + /** + * number of audio samples (per channel) described by this frame + */ + int nb_samples; + + /** + * format of the frame, -1 if unknown or unset + * Values correspond to enum AVPixelFormat for video frames, + * enum AVSampleFormat for audio) + */ + int format; + + /** + * Picture type of the frame. + */ + enum AVPictureType pict_type; + + /** + * Sample aspect ratio for the video frame, 0/1 if unknown/unspecified. + */ + AVRational sample_aspect_ratio; + + /** + * Presentation timestamp in time_base units (time when frame should be shown to user). + */ + int64_t pts; + + /** + * DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used) + * This is also the Presentation time of this AVFrame calculated from + * only AVPacket.dts values without pts values. + */ + int64_t pkt_dts; + + /** + * Time base for the timestamps in this frame. + * In the future, this field may be set on frames output by decoders or + * filters, but its value will be by default ignored on input to encoders + * or filters. + */ + AVRational time_base; + + /** + * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) + */ + int quality; + + /** + * Frame owner's private data. + * + * This field may be set by the code that allocates/owns the frame data. + * It is then not touched by any library functions, except: + * - it is copied to other references by av_frame_copy_props() (and hence by + * av_frame_ref()); + * - it is set to NULL when the frame is cleared by av_frame_unref() + * - on the caller's explicit request. E.g. libavcodec encoders/decoders + * will copy this field to/from @ref AVPacket "AVPackets" if the caller sets + * @ref AV_CODEC_FLAG_COPY_OPAQUE. + * + * @see opaque_ref the reference-counted analogue + */ + void *opaque; + + /** + * Number of fields in this frame which should be repeated, i.e. the total + * duration of this frame should be repeat_pict + 2 normal field durations. + * + * For interlaced frames this field may be set to 1, which signals that this + * frame should be presented as 3 fields: beginning with the first field (as + * determined by AV_FRAME_FLAG_TOP_FIELD_FIRST being set or not), followed + * by the second field, and then the first field again. + * + * For progressive frames this field may be set to a multiple of 2, which + * signals that this frame's duration should be (repeat_pict + 2) / 2 + * normal frame durations. + * + * @note This field is computed from MPEG2 repeat_first_field flag and its + * associated flags, H.264 pic_struct from picture timing SEI, and + * their analogues in other codecs. Typically it should only be used when + * higher-layer timing information is not available. + */ + int repeat_pict; + + /** + * Sample rate of the audio data. + */ + int sample_rate; + + /** + * AVBuffer references backing the data for this frame. All the pointers in + * data and extended_data must point inside one of the buffers in buf or + * extended_buf. This array must be filled contiguously -- if buf[i] is + * non-NULL then buf[j] must also be non-NULL for all j < i. + * + * There may be at most one AVBuffer per data plane, so for video this array + * always contains all the references. For planar audio with more than + * AV_NUM_DATA_POINTERS channels, there may be more buffers than can fit in + * this array. Then the extra AVBufferRef pointers are stored in the + * extended_buf array. + */ + AVBufferRef *buf[AV_NUM_DATA_POINTERS]; + + /** + * For planar audio which requires more than AV_NUM_DATA_POINTERS + * AVBufferRef pointers, this array will hold all the references which + * cannot fit into AVFrame.buf. + * + * Note that this is different from AVFrame.extended_data, which always + * contains all the pointers. This array only contains the extra pointers, + * which cannot fit into AVFrame.buf. + * + * This array is always allocated using av_malloc() by whoever constructs + * the frame. It is freed in av_frame_unref(). + */ + AVBufferRef **extended_buf; + /** + * Number of elements in extended_buf. + */ + int nb_extended_buf; + + AVFrameSideData **side_data; + int nb_side_data; + +/** + * @defgroup lavu_frame_flags AV_FRAME_FLAGS + * @ingroup lavu_frame + * Flags describing additional frame properties. + * + * @{ + */ + +/** + * The frame data may be corrupted, e.g. due to decoding errors. + */ +#define AV_FRAME_FLAG_CORRUPT (1 << 0) +/** + * A flag to mark frames that are keyframes. + */ +#define AV_FRAME_FLAG_KEY (1 << 1) +/** + * A flag to mark the frames which need to be decoded, but shouldn't be output. + */ +#define AV_FRAME_FLAG_DISCARD (1 << 2) +/** + * A flag to mark frames whose content is interlaced. + */ +#define AV_FRAME_FLAG_INTERLACED (1 << 3) +/** + * A flag to mark frames where the top field is displayed first if the content + * is interlaced. + */ +#define AV_FRAME_FLAG_TOP_FIELD_FIRST (1 << 4) +/** + * A decoder can use this flag to mark frames which were originally encoded losslessly. + * + * For coding bitstream formats which support both lossless and lossy + * encoding, it is sometimes possible for a decoder to determine which method + * was used when the bitsream was encoded. + */ +#define AV_FRAME_FLAG_LOSSLESS (1 << 5) +/** + * @} + */ + + /** + * Frame flags, a combination of @ref lavu_frame_flags + */ + int flags; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorRange color_range; + + enum AVColorPrimaries color_primaries; + + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + enum AVChromaLocation chroma_location; + + /** + * frame timestamp estimated using various heuristics, in stream time base + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int64_t best_effort_timestamp; + + /** + * metadata. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVDictionary *metadata; + + /** + * decode error flags of the frame, set to a combination of + * FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there + * were errors during the decoding. + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int decode_error_flags; +#define FF_DECODE_ERROR_INVALID_BITSTREAM 1 +#define FF_DECODE_ERROR_MISSING_REFERENCE 2 +#define FF_DECODE_ERROR_CONCEALMENT_ACTIVE 4 +#define FF_DECODE_ERROR_DECODE_SLICES 8 + + /** + * For hwaccel-format frames, this should be a reference to the + * AVHWFramesContext describing the frame. + */ + AVBufferRef *hw_frames_ctx; + + /** + * Frame owner's private data. + * + * This field may be set by the code that allocates/owns the frame data. + * It is then not touched by any library functions, except: + * - a new reference to the underlying buffer is propagated by + * av_frame_copy_props() (and hence by av_frame_ref()); + * - it is unreferenced in av_frame_unref(); + * - on the caller's explicit request. E.g. libavcodec encoders/decoders + * will propagate a new reference to/from @ref AVPacket "AVPackets" if the + * caller sets @ref AV_CODEC_FLAG_COPY_OPAQUE. + * + * @see opaque the plain pointer analogue + */ + AVBufferRef *opaque_ref; + + /** + * @anchor cropping + * @name Cropping + * Video frames only. The number of pixels to discard from the the + * top/bottom/left/right border of the frame to obtain the sub-rectangle of + * the frame intended for presentation. + * @{ + */ + size_t crop_top; + size_t crop_bottom; + size_t crop_left; + size_t crop_right; + /** + * @} + */ + + /** + * RefStruct reference for internal use by a single libav* library. + * Must not be used to transfer data between libraries. + * Has to be NULL when ownership of the frame leaves the respective library. + * + * Code outside the FFmpeg libs must never check or change private_ref. + */ + void *private_ref; + + /** + * Channel layout of the audio data. + */ + AVChannelLayout ch_layout; + + /** + * Duration of the frame, in the same units as pts. 0 if unknown. + */ + int64_t duration; +} AVFrame; + + +/** + * Allocate an AVFrame and set its fields to default values. The resulting + * struct must be freed using av_frame_free(). + * + * @return An AVFrame filled with default values or NULL on failure. + * + * @note this only allocates the AVFrame itself, not the data buffers. Those + * must be allocated through other means, e.g. with av_frame_get_buffer() or + * manually. + */ +AVFrame *av_frame_alloc(void); + +/** + * Free the frame and any dynamically allocated objects in it, + * e.g. extended_data. If the frame is reference counted, it will be + * unreferenced first. + * + * @param frame frame to be freed. The pointer will be set to NULL. + */ +void av_frame_free(AVFrame **frame); + +/** + * Set up a new reference to the data described by the source frame. + * + * Copy frame properties from src to dst and create a new reference for each + * AVBufferRef from src. + * + * If src is not reference counted, new buffers are allocated and the data is + * copied. + * + * @warning: dst MUST have been either unreferenced with av_frame_unref(dst), + * or newly allocated with av_frame_alloc() before calling this + * function, or undefined behavior will occur. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_frame_ref(AVFrame *dst, const AVFrame *src); + +/** + * Ensure the destination frame refers to the same data described by the source + * frame, either by creating a new reference for each AVBufferRef from src if + * they differ from those in dst, by allocating new buffers and copying data if + * src is not reference counted, or by unrefencing it if src is empty. + * + * Frame properties on dst will be replaced by those from src. + * + * @return 0 on success, a negative AVERROR on error. On error, dst is + * unreferenced. + */ +int av_frame_replace(AVFrame *dst, const AVFrame *src); + +/** + * Create a new frame that references the same data as src. + * + * This is a shortcut for av_frame_alloc()+av_frame_ref(). + * + * @return newly created AVFrame on success, NULL on error. + */ +AVFrame *av_frame_clone(const AVFrame *src); + +/** + * Unreference all the buffers referenced by frame and reset the frame fields. + */ +void av_frame_unref(AVFrame *frame); + +/** + * Move everything contained in src to dst and reset src. + * + * @warning: dst is not unreferenced, but directly overwritten without reading + * or deallocating its contents. Call av_frame_unref(dst) manually + * before calling this function to ensure that no memory is leaked. + */ +void av_frame_move_ref(AVFrame *dst, AVFrame *src); + +/** + * Allocate new buffer(s) for audio or video data. + * + * The following fields must be set on frame before calling this function: + * - format (pixel format for video, sample format for audio) + * - width and height for video + * - nb_samples and ch_layout for audio + * + * This function will fill AVFrame.data and AVFrame.buf arrays and, if + * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf. + * For planar formats, one buffer will be allocated for each plane. + * + * @warning: if frame already has been allocated, calling this function will + * leak memory. In addition, undefined behavior can occur in certain + * cases. + * + * @param frame frame in which to store the new buffers. + * @param align Required buffer size and data pointer alignment. If equal to 0, + * alignment will be chosen automatically for the current CPU. + * It is highly recommended to pass 0 here unless you know what + * you are doing. + * + * @return 0 on success, a negative AVERROR on error. + */ +int av_frame_get_buffer(AVFrame *frame, int align); + +/** + * Check if the frame data is writable. + * + * @return A positive value if the frame data is writable (which is true if and + * only if each of the underlying buffers has only one reference, namely the one + * stored in this frame). Return 0 otherwise. + * + * If 1 is returned the answer is valid until av_buffer_ref() is called on any + * of the underlying AVBufferRefs (e.g. through av_frame_ref() or directly). + * + * @see av_frame_make_writable(), av_buffer_is_writable() + */ +int av_frame_is_writable(AVFrame *frame); + +/** + * Ensure that the frame data is writable, avoiding data copy if possible. + * + * Do nothing if the frame is writable, allocate new buffers and copy the data + * if it is not. Non-refcounted frames behave as non-writable, i.e. a copy + * is always made. + * + * @return 0 on success, a negative AVERROR on error. + * + * @see av_frame_is_writable(), av_buffer_is_writable(), + * av_buffer_make_writable() + */ +int av_frame_make_writable(AVFrame *frame); + +/** + * Copy the frame data from src to dst. + * + * This function does not allocate anything, dst must be already initialized and + * allocated with the same parameters as src. + * + * This function only copies the frame data (i.e. the contents of the data / + * extended data arrays), not any other properties. + * + * @return >= 0 on success, a negative AVERROR on error. + */ +int av_frame_copy(AVFrame *dst, const AVFrame *src); + +/** + * Copy only "metadata" fields from src to dst. + * + * Metadata for the purpose of this function are those fields that do not affect + * the data layout in the buffers. E.g. pts, sample rate (for audio) or sample + * aspect ratio (for video), but not width/height or channel layout. + * Side data is also copied. + */ +int av_frame_copy_props(AVFrame *dst, const AVFrame *src); + +/** + * Get the buffer reference a given data plane is stored in. + * + * @param frame the frame to get the plane's buffer from + * @param plane index of the data plane of interest in frame->extended_data. + * + * @return the buffer reference that contains the plane or NULL if the input + * frame is not valid. + */ +AVBufferRef *av_frame_get_plane_buffer(const AVFrame *frame, int plane); + +/** + * Add a new side data to a frame. + * + * @param frame a frame to which the side data should be added + * @param type type of the added side data + * @param size size of the side data + * + * @return newly added side data on success, NULL on error + */ +AVFrameSideData *av_frame_new_side_data(AVFrame *frame, + enum AVFrameSideDataType type, + size_t size); + +/** + * Add a new side data to a frame from an existing AVBufferRef + * + * @param frame a frame to which the side data should be added + * @param type the type of the added side data + * @param buf an AVBufferRef to add as side data. The ownership of + * the reference is transferred to the frame. + * + * @return newly added side data on success, NULL on error. On failure + * the frame is unchanged and the AVBufferRef remains owned by + * the caller. + */ +AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame, + enum AVFrameSideDataType type, + AVBufferRef *buf); + +/** + * @return a pointer to the side data of a given type on success, NULL if there + * is no side data with such type in this frame. + */ +AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, + enum AVFrameSideDataType type); + +/** + * Remove and free all side data instances of the given type. + */ +void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type); + + +/** + * Flags for frame cropping. + */ +enum { + /** + * Apply the maximum possible cropping, even if it requires setting the + * AVFrame.data[] entries to unaligned pointers. Passing unaligned data + * to FFmpeg API is generally not allowed, and causes undefined behavior + * (such as crashes). You can pass unaligned data only to FFmpeg APIs that + * are explicitly documented to accept it. Use this flag only if you + * absolutely know what you are doing. + */ + AV_FRAME_CROP_UNALIGNED = 1 << 0, +}; + +/** + * Crop the given video AVFrame according to its crop_left/crop_top/crop_right/ + * crop_bottom fields. If cropping is successful, the function will adjust the + * data pointers and the width/height fields, and set the crop fields to 0. + * + * In all cases, the cropping boundaries will be rounded to the inherent + * alignment of the pixel format. In some cases, such as for opaque hwaccel + * formats, the left/top cropping is ignored. The crop fields are set to 0 even + * if the cropping was rounded or ignored. + * + * @param frame the frame which should be cropped + * @param flags Some combination of AV_FRAME_CROP_* flags, or 0. + * + * @return >= 0 on success, a negative AVERROR on error. If the cropping fields + * were invalid, AVERROR(ERANGE) is returned, and nothing is changed. + */ +int av_frame_apply_cropping(AVFrame *frame, int flags); + +/** + * @return a string identifying the side data type + */ +const char *av_frame_side_data_name(enum AVFrameSideDataType type); + +/** + * @return side data descriptor corresponding to a given side data type, NULL + * when not available. + */ +const AVSideDataDescriptor *av_frame_side_data_desc(enum AVFrameSideDataType type); + +/** + * Free all side data entries and their contents, then zeroes out the + * values which the pointers are pointing to. + * + * @param sd pointer to array of side data to free. Will be set to NULL + * upon return. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. Will be set to 0 upon return. + */ +void av_frame_side_data_free(AVFrameSideData ***sd, int *nb_sd); + +/** + * Remove existing entries before adding new ones. + */ +#define AV_FRAME_SIDE_DATA_FLAG_UNIQUE (1 << 0) +/** + * Don't add a new entry if another of the same type exists. + * Applies only for side data types without the AV_SIDE_DATA_PROP_MULTI prop. + */ +#define AV_FRAME_SIDE_DATA_FLAG_REPLACE (1 << 1) +/** + * Create a new reference to the passed in buffer instead of taking ownership + * of it. + */ +#define AV_FRAME_SIDE_DATA_FLAG_NEW_REF (1 << 2) + +/** + * Add new side data entry to an array. + * + * @param sd pointer to array of side data to which to add another entry, + * or to NULL in order to start a new array. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. + * @param type type of the added side data + * @param size size of the side data + * @param flags Some combination of AV_FRAME_SIDE_DATA_FLAG_* flags, or 0. + * + * @return newly added side data on success, NULL on error. + * @note In case of AV_FRAME_SIDE_DATA_FLAG_UNIQUE being set, entries of + * matching AVFrameSideDataType will be removed before the addition + * is attempted. + * @note In case of AV_FRAME_SIDE_DATA_FLAG_REPLACE being set, if an + * entry of the same type already exists, it will be replaced instead. + */ +AVFrameSideData *av_frame_side_data_new(AVFrameSideData ***sd, int *nb_sd, + enum AVFrameSideDataType type, + size_t size, unsigned int flags); + +/** + * Add a new side data entry to an array from an existing AVBufferRef. + * + * @param sd pointer to array of side data to which to add another entry, + * or to NULL in order to start a new array. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. + * @param type type of the added side data + * @param buf Pointer to AVBufferRef to add to the array. On success, + * the function takes ownership of the AVBufferRef and *buf is + * set to NULL, unless AV_FRAME_SIDE_DATA_FLAG_NEW_REF is set + * in which case the ownership will remain with the caller. + * @param flags Some combination of AV_FRAME_SIDE_DATA_FLAG_* flags, or 0. + * + * @return newly added side data on success, NULL on error. + * @note In case of AV_FRAME_SIDE_DATA_FLAG_UNIQUE being set, entries of + * matching AVFrameSideDataType will be removed before the addition + * is attempted. + * @note In case of AV_FRAME_SIDE_DATA_FLAG_REPLACE being set, if an + * entry of the same type already exists, it will be replaced instead. + * + */ +AVFrameSideData *av_frame_side_data_add(AVFrameSideData ***sd, int *nb_sd, + enum AVFrameSideDataType type, + AVBufferRef **buf, unsigned int flags); + +/** + * Add a new side data entry to an array based on existing side data, taking + * a reference towards the contained AVBufferRef. + * + * @param sd pointer to array of side data to which to add another entry, + * or to NULL in order to start a new array. + * @param nb_sd pointer to an integer containing the number of entries in + * the array. + * @param src side data to be cloned, with a new reference utilized + * for the buffer. + * @param flags Some combination of AV_FRAME_SIDE_DATA_FLAG_* flags, or 0. + * + * @return negative error code on failure, >=0 on success. + * @note In case of AV_FRAME_SIDE_DATA_FLAG_UNIQUE being set, entries of + * matching AVFrameSideDataType will be removed before the addition + * is attempted. + * @note In case of AV_FRAME_SIDE_DATA_FLAG_REPLACE being set, if an + * entry of the same type already exists, it will be replaced instead. + */ +int av_frame_side_data_clone(AVFrameSideData ***sd, int *nb_sd, + const AVFrameSideData *src, unsigned int flags); + +/** + * Get a side data entry of a specific type from an array. + * + * @param sd array of side data. + * @param nb_sd integer containing the number of entries in the array. + * @param type type of side data to be queried + * + * @return a pointer to the side data of a given type on success, NULL if there + * is no side data with such type in this set. + */ +const AVFrameSideData *av_frame_side_data_get_c(const AVFrameSideData * const *sd, + const int nb_sd, + enum AVFrameSideDataType type); + +/** + * Wrapper around av_frame_side_data_get_c() to workaround the limitation + * that for any type T the conversion from T * const * to const T * const * + * is not performed automatically in C. + * @see av_frame_side_data_get_c() + */ +static inline +const AVFrameSideData *av_frame_side_data_get(AVFrameSideData * const *sd, + const int nb_sd, + enum AVFrameSideDataType type) +{ + return av_frame_side_data_get_c((const AVFrameSideData * const *)sd, + nb_sd, type); +} + +/** + * Remove and free all side data instances of the given type from an array. + */ +void av_frame_side_data_remove(AVFrameSideData ***sd, int *nb_sd, + enum AVFrameSideDataType type); + +/** + * Remove and free all side data instances that match any of the given + * side data properties. (See enum AVSideDataProps) + */ +void av_frame_side_data_remove_by_props(AVFrameSideData ***sd, int *nb_sd, + int props); + +/** + * @} + */ + +#endif /* AVUTIL_FRAME_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/hwcontext.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/hwcontext.h new file mode 100644 index 0000000000000..29374cf0a7e35 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/hwcontext.h @@ -0,0 +1,601 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_H +#define AVUTIL_HWCONTEXT_H + +#include "buffer.h" +#include "frame.h" +#include "log.h" +#include "pixfmt.h" + +enum AVHWDeviceType { + AV_HWDEVICE_TYPE_NONE, + AV_HWDEVICE_TYPE_VDPAU, + AV_HWDEVICE_TYPE_CUDA, + AV_HWDEVICE_TYPE_VAAPI, + AV_HWDEVICE_TYPE_DXVA2, + AV_HWDEVICE_TYPE_QSV, + AV_HWDEVICE_TYPE_VIDEOTOOLBOX, + AV_HWDEVICE_TYPE_D3D11VA, + AV_HWDEVICE_TYPE_DRM, + AV_HWDEVICE_TYPE_OPENCL, + AV_HWDEVICE_TYPE_MEDIACODEC, + AV_HWDEVICE_TYPE_VULKAN, + AV_HWDEVICE_TYPE_D3D12VA, + AV_HWDEVICE_TYPE_AMF, + /* OpenHarmony Codec device */ + AV_HWDEVICE_TYPE_OHCODEC, +}; + +/** + * This struct aggregates all the (hardware/vendor-specific) "high-level" state, + * i.e. state that is not tied to a concrete processing configuration. + * E.g., in an API that supports hardware-accelerated encoding and decoding, + * this struct will (if possible) wrap the state that is common to both encoding + * and decoding and from which specific instances of encoders or decoders can be + * derived. + * + * This struct is reference-counted with the AVBuffer mechanism. The + * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field + * points to the actual AVHWDeviceContext. Further objects derived from + * AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with + * specific properties) will hold an internal reference to it. After all the + * references are released, the AVHWDeviceContext itself will be freed, + * optionally invoking a user-specified callback for uninitializing the hardware + * state. + */ +typedef struct AVHWDeviceContext { + /** + * A class for logging. Set by av_hwdevice_ctx_alloc(). + */ + const AVClass *av_class; + + /** + * This field identifies the underlying API used for hardware access. + * + * This field is set when this struct is allocated and never changed + * afterwards. + */ + enum AVHWDeviceType type; + + /** + * The format-specific data, allocated and freed by libavutil along with + * this context. + * + * Should be cast by the user to the format-specific context defined in the + * corresponding header (hwcontext_*.h) and filled as described in the + * documentation before calling av_hwdevice_ctx_init(). + * + * After calling av_hwdevice_ctx_init() this struct should not be modified + * by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwdevice_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + * + * @note when other objects (e.g an AVHWFramesContext) are derived from this + * struct, this callback will be invoked after all such child objects + * are fully uninitialized and their respective destructors invoked. + */ + void (*free)(struct AVHWDeviceContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; +} AVHWDeviceContext; + +/** + * This struct describes a set or pool of "hardware" frames (i.e. those with + * data not located in normal system memory). All the frames in the pool are + * assumed to be allocated in the same way and interchangeable. + * + * This struct is reference-counted with the AVBuffer mechanism and tied to a + * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor + * yields a reference, whose data field points to the actual AVHWFramesContext + * struct. + */ +typedef struct AVHWFramesContext { + /** + * A class for logging. + */ + const AVClass *av_class; + + /** + * A reference to the parent AVHWDeviceContext. This reference is owned and + * managed by the enclosing AVHWFramesContext, but the caller may derive + * additional references from it. + */ + AVBufferRef *device_ref; + + /** + * The parent AVHWDeviceContext. This is simply a pointer to + * device_ref->data provided for convenience. + * + * Set by libavutil in av_hwframe_ctx_init(). + */ + AVHWDeviceContext *device_ctx; + + /** + * The format-specific data, allocated and freed automatically along with + * this context. + * + * The user shall ignore this field if the corresponding format-specific + * header (hwcontext_*.h) does not define a context to be used as + * AVHWFramesContext.hwctx. + * + * Otherwise, it should be cast by the user to said context and filled + * as described in the documentation before calling av_hwframe_ctx_init(). + * + * After any frames using this context are created, the contents of this + * struct should not be modified by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + */ + void (*free)(struct AVHWFramesContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; + + /** + * A pool from which the frames are allocated by av_hwframe_get_buffer(). + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * The buffers returned by calling av_buffer_pool_get() on this pool must + * have the properties described in the documentation in the corresponding hw + * type's header (hwcontext_*.h). The pool will be freed strictly before + * this struct's free() callback is invoked. + * + * This field may be NULL, then libavutil will attempt to allocate a pool + * internally. Note that certain device types enforce pools allocated at + * fixed size (frame count), which cannot be extended dynamically. In such a + * case, initial_pool_size must be set appropriately. + */ + AVBufferPool *pool; + + /** + * Initial size of the frame pool. If a device type does not support + * dynamically resizing the pool, then this is also the maximum pool size. + * + * May be set by the caller before calling av_hwframe_ctx_init(). Must be + * set if pool is NULL and the device type does not support dynamic pools. + */ + int initial_pool_size; + + /** + * The pixel format identifying the underlying HW surface type. + * + * Must be a hwaccel format, i.e. the corresponding descriptor must have the + * AV_PIX_FMT_FLAG_HWACCEL flag set. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + enum AVPixelFormat format; + + /** + * The pixel format identifying the actual data layout of the hardware + * frames. + * + * Must be set by the caller before calling av_hwframe_ctx_init(). + * + * @note when the underlying API does not provide the exact data layout, but + * only the colorspace/bit depth, this field should be set to the fully + * planar version of that format (e.g. for 8-bit 420 YUV it should be + * AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else). + */ + enum AVPixelFormat sw_format; + + /** + * The allocated dimensions of the frames in this pool. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + int width, height; +} AVHWFramesContext; + +/** + * Look up an AVHWDeviceType by name. + * + * @param name String name of the device type (case-insensitive). + * @return The type from enum AVHWDeviceType, or AV_HWDEVICE_TYPE_NONE if + * not found. + */ +enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name); + +/** Get the string name of an AVHWDeviceType. + * + * @param type Type from enum AVHWDeviceType. + * @return Pointer to a static string containing the name, or NULL if the type + * is not valid. + */ +const char *av_hwdevice_get_type_name(enum AVHWDeviceType type); + +/** + * Iterate over supported device types. + * + * @param prev AV_HWDEVICE_TYPE_NONE initially, then the previous type + * returned by this function in subsequent iterations. + * @return The next usable device type from enum AVHWDeviceType, or + * AV_HWDEVICE_TYPE_NONE if there are no more. + */ +enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev); + +/** + * Allocate an AVHWDeviceContext for a given hardware type. + * + * @param type the type of the hardware device to allocate. + * @return a reference to the newly created AVHWDeviceContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type); + +/** + * Finalize the device context before use. This function must be called after + * the context is filled with all the required information and before it is + * used in any way. + * + * @param ref a reference to the AVHWDeviceContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwdevice_ctx_init(AVBufferRef *ref); + +/** + * Open a device of the specified type and create an AVHWDeviceContext for it. + * + * This is a convenience function intended to cover the simple cases. Callers + * who need to fine-tune device creation/management should open the device + * manually and then wrap it in an AVHWDeviceContext using + * av_hwdevice_ctx_alloc()/av_hwdevice_ctx_init(). + * + * The returned context is already initialized and ready for use, the caller + * should not call av_hwdevice_ctx_init() on it. The user_opaque/free fields of + * the created AVHWDeviceContext are set by this function and should not be + * touched by the caller. + * + * @param device_ctx On success, a reference to the newly-created device context + * will be written here. The reference is owned by the caller + * and must be released with av_buffer_unref() when no longer + * needed. On failure, NULL will be written to this pointer. + * @param type The type of the device to create. + * @param device A type-specific string identifying the device to open. + * @param opts A dictionary of additional (type-specific) options to use in + * opening the device. The dictionary remains owned by the caller. + * @param flags currently unused + * + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type, + const char *device, AVDictionary *opts, int flags); + +/** + * Create a new device of the specified type from an existing device. + * + * If the source device is a device of the target type or was originally + * derived from such a device (possibly through one or more intermediate + * devices of other types), then this will return a reference to the + * existing device of the same type as is requested. + * + * Otherwise, it will attempt to derive a new device from the given source + * device. If direct derivation to the new type is not implemented, it will + * attempt the same derivation from each ancestor of the source device in + * turn looking for an implemented derivation method. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, int flags); + +/** + * Create a new device of the specified type from an existing device. + * + * This function performs the same action as av_hwdevice_ctx_create_derived, + * however, it is able to set options for the new device to be derived. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param options Options for the new device to create, same format as in + * av_hwdevice_ctx_create. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, + AVDictionary *options, int flags); + +/** + * Allocate an AVHWFramesContext tied to a given device context. + * + * @param device_ctx a reference to a AVHWDeviceContext. This function will make + * a new reference for internal use, the one passed to the + * function remains owned by the caller. + * @return a reference to the newly created AVHWFramesContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx); + +/** + * Finalize the context before use. This function must be called after the + * context is filled with all the required information and before it is attached + * to any frames. + * + * @param ref a reference to the AVHWFramesContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_ctx_init(AVBufferRef *ref); + +/** + * Allocate a new frame attached to the given AVHWFramesContext. + * + * @param hwframe_ctx a reference to an AVHWFramesContext + * @param frame an empty (freshly allocated or unreffed) frame to be filled with + * newly allocated buffers. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags); + +/** + * Copy data to or from a hw surface. At least one of dst/src must have an + * AVHWFramesContext attached. + * + * If src has an AVHWFramesContext attached, then the format of dst (if set) + * must use one of the formats returned by av_hwframe_transfer_get_formats(src, + * AV_HWFRAME_TRANSFER_DIRECTION_FROM). + * If dst has an AVHWFramesContext attached, then the format of src must use one + * of the formats returned by av_hwframe_transfer_get_formats(dst, + * AV_HWFRAME_TRANSFER_DIRECTION_TO) + * + * dst may be "clean" (i.e. with data/buf pointers unset), in which case the + * data buffers will be allocated by this function using av_frame_get_buffer(). + * If dst->format is set, then this format will be used, otherwise (when + * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen. + * + * The two frames must have matching allocated dimensions (i.e. equal to + * AVHWFramesContext.width/height), since not all device types support + * transferring a sub-rectangle of the whole surface. The display dimensions + * (i.e. AVFrame.width/height) may be smaller than the allocated dimensions, but + * also have to be equal for both frames. When the display dimensions are + * smaller than the allocated dimensions, the content of the padding in the + * destination frame is unspecified. + * + * @param dst the destination frame. dst is not touched on failure. + * @param src the source frame. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR error code on failure. + */ +int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags); + +enum AVHWFrameTransferDirection { + /** + * Transfer the data from the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_FROM, + + /** + * Transfer the data to the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_TO, +}; + +/** + * Get a list of possible source or target formats usable in + * av_hwframe_transfer_data(). + * + * @param hwframe_ctx the frame context to obtain the information for + * @param dir the direction of the transfer + * @param formats the pointer to the output format list will be written here. + * The list is terminated with AV_PIX_FMT_NONE and must be freed + * by the caller when no longer needed using av_free(). + * If this function returns successfully, the format list will + * have at least one item (not counting the terminator). + * On failure, the contents of this pointer are unspecified. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats, int flags); + + +/** + * This struct describes the constraints on hardware frames attached to + * a given device with a hardware-specific configuration. This is returned + * by av_hwdevice_get_hwframe_constraints() and must be freed by + * av_hwframe_constraints_free() after use. + */ +typedef struct AVHWFramesConstraints { + /** + * A list of possible values for format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. This member will always be filled. + */ + enum AVPixelFormat *valid_hw_formats; + + /** + * A list of possible values for sw_format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. Can be NULL if this information is + * not known. + */ + enum AVPixelFormat *valid_sw_formats; + + /** + * The minimum size of frames in this hw_frames_ctx. + * (Zero if not known.) + */ + int min_width; + int min_height; + + /** + * The maximum size of frames in this hw_frames_ctx. + * (INT_MAX if not known / no limit.) + */ + int max_width; + int max_height; +} AVHWFramesConstraints; + +/** + * Allocate a HW-specific configuration structure for a given HW device. + * After use, the user must free all members as required by the specific + * hardware structure being used, then free the structure itself with + * av_free(). + * + * @param device_ctx a reference to the associated AVHWDeviceContext. + * @return The newly created HW-specific configuration structure on + * success or NULL on failure. + */ +void *av_hwdevice_hwconfig_alloc(AVBufferRef *device_ctx); + +/** + * Get the constraints on HW frames given a device and the HW-specific + * configuration to be used with that device. If no HW-specific + * configuration is provided, returns the maximum possible capabilities + * of the device. + * + * @param ref a reference to the associated AVHWDeviceContext. + * @param hwconfig a filled HW-specific configuration structure, or NULL + * to return the maximum possible capabilities of the device. + * @return AVHWFramesConstraints structure describing the constraints + * on the device, or NULL if not available. + */ +AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, + const void *hwconfig); + +/** + * Free an AVHWFrameConstraints structure. + * + * @param constraints The (filled or unfilled) AVHWFrameConstraints structure. + */ +void av_hwframe_constraints_free(AVHWFramesConstraints **constraints); + + +/** + * Flags to apply to frame mappings. + */ +enum { + /** + * The mapping must be readable. + */ + AV_HWFRAME_MAP_READ = 1 << 0, + /** + * The mapping must be writeable. + */ + AV_HWFRAME_MAP_WRITE = 1 << 1, + /** + * The mapped frame will be overwritten completely in subsequent + * operations, so the current frame data need not be loaded. Any values + * which are not overwritten are unspecified. + */ + AV_HWFRAME_MAP_OVERWRITE = 1 << 2, + /** + * The mapping must be direct. That is, there must not be any copying in + * the map or unmap steps. Note that performance of direct mappings may + * be much lower than normal memory. + */ + AV_HWFRAME_MAP_DIRECT = 1 << 3, +}; + +/** + * Map a hardware frame. + * + * This has a number of different possible effects, depending on the format + * and origin of the src and dst frames. On input, src should be a usable + * frame with valid buffers and dst should be blank (typically as just created + * by av_frame_alloc()). src should have an associated hwframe context, and + * dst may optionally have a format and associated hwframe context. + * + * If src was created by mapping a frame from the hwframe context of dst, + * then this function undoes the mapping - dst is replaced by a reference to + * the frame that src was originally mapped from. + * + * If both src and dst have an associated hwframe context, then this function + * attempts to map the src frame from its hardware context to that of dst and + * then fill dst with appropriate data to be usable there. This will only be + * possible if the hwframe contexts and associated devices are compatible - + * given compatible devices, av_hwframe_ctx_create_derived() can be used to + * create a hwframe context for dst in which mapping should be possible. + * + * If src has a hwframe context but dst does not, then the src frame is + * mapped to normal memory and should thereafter be usable as a normal frame. + * If the format is set on dst, then the mapping will attempt to create dst + * with that format and fail if it is not possible. If format is unset (is + * AV_PIX_FMT_NONE) then dst will be mapped with whatever the most appropriate + * format to use is (probably the sw_format of the src hwframe context). + * + * A return value of AVERROR(ENOSYS) indicates that the mapping is not + * possible with the given arguments and hwframe setup, while other return + * values indicate that it failed somehow. + * + * On failure, the destination frame will be left blank, except for the + * hw_frames_ctx/format fields they may have been set by the caller - those will + * be preserved as they were. + * + * @param dst Destination frame, to contain the mapping. + * @param src Source frame, to be mapped. + * @param flags Some combination of AV_HWFRAME_MAP_* flags. + * @return Zero on success, negative AVERROR code on failure. + */ +int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags); + + +/** + * Create and initialise an AVHWFramesContext as a mapping of another existing + * AVHWFramesContext on a different device. + * + * av_hwframe_ctx_init() should not be called after this. + * + * @param derived_frame_ctx On success, a reference to the newly created + * AVHWFramesContext. + * @param format The AVPixelFormat for the derived context. + * @param derived_device_ctx A reference to the device to create the new + * AVHWFramesContext on. + * @param source_frame_ctx A reference to an existing AVHWFramesContext + * which will be mapped to the derived context. + * @param flags Some combination of AV_HWFRAME_MAP_* flags, defining the + * mapping parameters to apply to frames which are allocated + * in the derived device. + * @return Zero on success, negative AVERROR code on failure. + */ +int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, + enum AVPixelFormat format, + AVBufferRef *derived_device_ctx, + AVBufferRef *source_frame_ctx, + int flags); + +#endif /* AVUTIL_HWCONTEXT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/imgutils.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/imgutils.h new file mode 100644 index 0000000000000..123a9e5c0d21a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/imgutils.h @@ -0,0 +1,377 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_IMGUTILS_H +#define AVUTIL_IMGUTILS_H + +/** + * @file + * misc image utilities + * + * @addtogroup lavu_picture + * @{ + */ + +#include +#include +#include "pixdesc.h" +#include "pixfmt.h" +#include "rational.h" + +/** + * Compute the max pixel step for each plane of an image with a + * format described by pixdesc. + * + * The pixel step is the distance in bytes between the first byte of + * the group of bytes which describe a pixel component and the first + * byte of the successive group in the same plane for the same + * component. + * + * @param max_pixsteps an array which is filled with the max pixel step + * for each plane. Since a plane may contain different pixel + * components, the computed max_pixsteps[plane] is relative to the + * component in the plane with the max pixel step. + * @param max_pixstep_comps an array which is filled with the component + * for each plane which has the max pixel step. May be NULL. + * @param pixdesc the AVPixFmtDescriptor for the image, describing its format + */ +void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], + const AVPixFmtDescriptor *pixdesc); + +/** + * Compute the size of an image line with format pix_fmt and width + * width for the plane plane. + * + * @return the computed size in bytes + */ +int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane); + +/** + * Fill plane linesizes for an image with pixel format pix_fmt and + * width width. + * + * @param linesizes array to be filled with the linesize for each plane + * @param pix_fmt the AVPixelFormat of the image + * @param width width of the image in pixels + * @return >= 0 in case of success, a negative error code otherwise + */ +int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width); + +/** + * Fill plane sizes for an image with pixel format pix_fmt and height height. + * + * @param size the array to be filled with the size of each image plane + * @param pix_fmt the AVPixelFormat of the image + * @param height height of the image in pixels + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return >= 0 in case of success, a negative error code otherwise + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_fill_linesizes(). + */ +int av_image_fill_plane_sizes(size_t size[4], enum AVPixelFormat pix_fmt, + int height, const ptrdiff_t linesizes[4]); + +/** + * Fill plane data pointers for an image with pixel format pix_fmt and + * height height. + * + * @param data pointers array to be filled with the pointer for each image plane + * @param pix_fmt the AVPixelFormat of the image + * @param height height of the image in pixels + * @param ptr the pointer to a buffer which will contain the image + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, + uint8_t *ptr, const int linesizes[4]); + +/** + * Allocate an image with size w and h and pixel format pix_fmt, and + * fill pointers and linesizes accordingly. + * The allocated image buffer has to be freed by using + * av_freep(&pointers[0]). + * + * @param pointers array to be filled with the pointer for each image plane + * @param linesizes the array filled with the linesize for each plane + * @param w width of the image in pixels + * @param h height of the image in pixels + * @param pix_fmt the AVPixelFormat of the image + * @param align the value to use for buffer size alignment + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_alloc(uint8_t *pointers[4], int linesizes[4], + int w, int h, enum AVPixelFormat pix_fmt, int align); + +/** + * Copy image plane from src to dst. + * That is, copy "height" number of lines of "bytewidth" bytes each. + * The first byte of each successive line is separated by *_linesize + * bytes. + * + * bytewidth must be contained by both absolute values of dst_linesize + * and src_linesize, otherwise the function behavior is undefined. + * + * @param dst destination plane to copy to + * @param dst_linesize linesize for the image plane in dst + * @param src source plane to copy from + * @param src_linesize linesize for the image plane in src + * @param height height (number of lines) of the plane + */ +void av_image_copy_plane(uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, + int bytewidth, int height); + +/** + * Copy image data located in uncacheable (e.g. GPU mapped) memory. Where + * available, this function will use special functionality for reading from such + * memory, which may result in greatly improved performance compared to plain + * av_image_copy_plane(). + * + * bytewidth must be contained by both absolute values of dst_linesize + * and src_linesize, otherwise the function behavior is undefined. + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_copy_plane(). + * @note On x86, the linesizes currently need to be aligned to the cacheline + * size (i.e. 64) to get improved performance. + */ +void av_image_copy_plane_uc_from(uint8_t *dst, ptrdiff_t dst_linesize, + const uint8_t *src, ptrdiff_t src_linesize, + ptrdiff_t bytewidth, int height); + +/** + * Copy image in src_data to dst_data. + * + * @param dst_data destination image data buffer to copy to + * @param dst_linesizes linesizes for the image in dst_data + * @param src_data source image data buffer to copy from + * @param src_linesizes linesizes for the image in src_data + * @param pix_fmt the AVPixelFormat of the image + * @param width width of the image in pixels + * @param height height of the image in pixels + */ +void av_image_copy(uint8_t * const dst_data[4], const int dst_linesizes[4], + const uint8_t * const src_data[4], const int src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Wrapper around av_image_copy() to workaround the limitation + * that the conversion from uint8_t * const * to const uint8_t * const * + * is not performed automatically in C. + * @see av_image_copy() + */ +static inline +void av_image_copy2(uint8_t * const dst_data[4], const int dst_linesizes[4], + uint8_t * const src_data[4], const int src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height) +{ + av_image_copy(dst_data, dst_linesizes, + (const uint8_t * const *)src_data, src_linesizes, + pix_fmt, width, height); +} + +/** + * Copy image data located in uncacheable (e.g. GPU mapped) memory. Where + * available, this function will use special functionality for reading from such + * memory, which may result in greatly improved performance compared to plain + * av_image_copy(). + * + * The data pointers and the linesizes must be aligned to the maximum required + * by the CPU architecture. + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_copy(). + * @note On x86, the linesizes currently need to be aligned to the cacheline + * size (i.e. 64) to get improved performance. + */ +void av_image_copy_uc_from(uint8_t * const dst_data[4], const ptrdiff_t dst_linesizes[4], + const uint8_t * const src_data[4], const ptrdiff_t src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Setup the data pointers and linesizes based on the specified image + * parameters and the provided array. + * + * The fields of the given image are filled in by using the src + * address which points to the image data buffer. Depending on the + * specified pixel format, one or multiple image data pointers and + * line sizes will be set. If a planar format is specified, several + * pointers will be set pointing to the different picture planes and + * the line sizes of the different planes will be stored in the + * lines_sizes array. Call with src == NULL to get the required + * size for the src buffer. + * + * To allocate the buffer and fill in the dst_data and dst_linesize in + * one call, use av_image_alloc(). + * + * @param dst_data data pointers to be filled in + * @param dst_linesize linesizes for the image in dst_data to be filled in + * @param src buffer which will contain or contains the actual image data, can be NULL + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the value used in src for linesize alignment + * @return the size in bytes required for src, a negative error code + * in case of failure + */ +int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Return the size in bytes of the amount of data required to store an + * image with the given parameters. + * + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the assumed linesize alignment + * @return the buffer size in bytes, a negative error code in case of failure + */ +int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Copy image data from an image into a buffer. + * + * av_image_get_buffer_size() can be used to compute the required size + * for the buffer to fill. + * + * @param dst a buffer into which picture data will be copied + * @param dst_size the size in bytes of dst + * @param src_data pointers containing the source image data + * @param src_linesize linesizes for the image in src_data + * @param pix_fmt the pixel format of the source image + * @param width the width of the source image in pixels + * @param height the height of the source image in pixels + * @param align the assumed linesize alignment for dst + * @return the number of bytes written to dst, or a negative value + * (error code) on error + */ +int av_image_copy_to_buffer(uint8_t *dst, int dst_size, + const uint8_t * const src_data[4], const int src_linesize[4], + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of the image can be addressed with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of a plane of an image with the specified pix_fmt can be addressed + * with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param max_pixels the maximum number of pixels the user wants to accept + * @param pix_fmt the pixel format, can be AV_PIX_FMT_NONE if unknown. + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx); + +/** + * Check if the given sample aspect ratio of an image is valid. + * + * It is considered invalid if the denominator is 0 or if applying the ratio + * to the image size would make the smaller dimension less than 1. If the + * sar numerator is 0, it is considered unknown and will return as valid. + * + * @param w width of the image + * @param h height of the image + * @param sar sample aspect ratio of the image + * @return 0 if valid, a negative AVERROR code otherwise + */ +int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar); + +/** + * Overwrite the image data with black. This is suitable for filling a + * sub-rectangle of an image, meaning the padding between the right most pixel + * and the left most pixel on the next line will not be overwritten. For some + * formats, the image size might be rounded up due to inherent alignment. + * + * If the pixel format has alpha, the alpha is cleared to opaque. + * + * This can return an error if the pixel format is not supported. Normally, all + * non-hwaccel pixel formats should be supported. + * + * Passing NULL for dst_data is allowed. Then the function returns whether the + * operation would have succeeded. (It can return an error if the pix_fmt is + * not supported.) + * + * @param dst_data data pointers to destination image + * @param dst_linesize linesizes for the destination image + * @param pix_fmt the pixel format of the image + * @param range the color range of the image (important for colorspaces such as YUV) + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @return 0 if the image data was cleared, a negative AVERROR code otherwise + */ +int av_image_fill_black(uint8_t * const dst_data[4], const ptrdiff_t dst_linesize[4], + enum AVPixelFormat pix_fmt, enum AVColorRange range, + int width, int height); + +/** + * Overwrite the image data with a color. This is suitable for filling a + * sub-rectangle of an image, meaning the padding between the right most pixel + * and the left most pixel on the next line will not be overwritten. For some + * formats, the image size might be rounded up due to inherent alignment. + * + * If the pixel format has alpha, it is also replaced. Color component values + * are interpreted as native integers (or intfloats) regardless of actual pixel + * format endianness. + * + * This can return an error if the pixel format is not supported. Normally, all + * non-hwaccel pixel formats should be supported. + * + * Passing NULL for dst_data is allowed. Then the function returns whether the + * operation would have succeeded. (It can return an error if the pix_fmt is + * not supported.) + * + * @param dst_data data pointers to destination image + * @param dst_linesize linesizes for the destination image + * @param pix_fmt the pixel format of the image + * @param color the color components to be used for the fill + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param flags currently unused + * @return 0 if the image data was filled, a negative AVERROR code otherwise + */ +int av_image_fill_color(uint8_t * const dst_data[4], const ptrdiff_t dst_linesize[4], + enum AVPixelFormat pix_fmt, const uint32_t color[4], + int width, int height, int flags); + +/** + * @} + */ + + +#endif /* AVUTIL_IMGUTILS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/intfloat.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/intfloat.h new file mode 100644 index 0000000000000..fe3d7ec4a5b6f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/intfloat.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_INTFLOAT_H +#define AVUTIL_INTFLOAT_H + +#include +#include "attributes.h" + +union av_intfloat32 { + uint32_t i; + float f; +}; + +union av_intfloat64 { + uint64_t i; + double f; +}; + +/** + * Reinterpret a 32-bit integer as a float. + */ +static av_always_inline float av_int2float(uint32_t i) +{ + union av_intfloat32 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a float as a 32-bit integer. + */ +static av_always_inline uint32_t av_float2int(float f) +{ + union av_intfloat32 v; + v.f = f; + return v.i; +} + +/** + * Reinterpret a 64-bit integer as a double. + */ +static av_always_inline double av_int2double(uint64_t i) +{ + union av_intfloat64 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a double as a 64-bit integer. + */ +static av_always_inline uint64_t av_double2int(double f) +{ + union av_intfloat64 v; + v.f = f; + return v.i; +} + +#endif /* AVUTIL_INTFLOAT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/log.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/log.h new file mode 100644 index 0000000000000..4a111ca9a5b8a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/log.h @@ -0,0 +1,427 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_LOG_H +#define AVUTIL_LOG_H + +#include +#include "attributes.h" +#include "version.h" + +typedef enum { + AV_CLASS_CATEGORY_NA = 0, + AV_CLASS_CATEGORY_INPUT, + AV_CLASS_CATEGORY_OUTPUT, + AV_CLASS_CATEGORY_MUXER, + AV_CLASS_CATEGORY_DEMUXER, + AV_CLASS_CATEGORY_ENCODER, + AV_CLASS_CATEGORY_DECODER, + AV_CLASS_CATEGORY_FILTER, + AV_CLASS_CATEGORY_BITSTREAM_FILTER, + AV_CLASS_CATEGORY_SWSCALER, + AV_CLASS_CATEGORY_SWRESAMPLER, + AV_CLASS_CATEGORY_HWDEVICE, + AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT = 40, + AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT, + AV_CLASS_CATEGORY_NB ///< not part of ABI/API +}AVClassCategory; + +enum AVClassStateFlags { + /** + * Object initialization has finished and it is now in the 'runtime' stage. + * This affects e.g. what options can be set on the object (only + * AV_OPT_FLAG_RUNTIME_PARAM options can be set on initialized objects). + */ + AV_CLASS_STATE_INITIALIZED = (1 << 0), +}; + +#define AV_IS_INPUT_DEVICE(category) \ + (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_INPUT)) + +#define AV_IS_OUTPUT_DEVICE(category) \ + (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_OUTPUT)) + +struct AVOptionRanges; + +/** + * Describe the class of an AVClass context structure. That is an + * arbitrary struct of which the first field is a pointer to an + * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.). + */ +typedef struct AVClass { + /** + * The name of the class; usually it is the same name as the + * context structure type to which the AVClass is associated. + */ + const char* class_name; + + /** + * A pointer to a function which returns the name of a context + * instance ctx associated with the class. + */ + const char* (*item_name)(void* ctx); + + /** + * An array of options for the structure or NULL. + * When non-NULL, the array must be terminated by an option with a NULL + * name. + * + * @see av_set_default_options() + */ + const struct AVOption *option; + + /** + * LIBAVUTIL_VERSION with which this structure was created. + * This is used to allow fields to be added to AVClass without requiring + * major version bumps everywhere. + */ + + int version; + + /** + * Offset in the structure where the log level offset is stored. The log + * level offset is an int added to the log level for logging with this + * object as the context. + * + * 0 means there is no such variable. + */ + int log_level_offset_offset; + + /** + * Offset in the structure where a pointer to the parent context for + * logging is stored. For example a decoder could pass its AVCodecContext + * to eval as such a parent context, which an ::av_log() implementation + * could then leverage to display the parent context. + * + * When the pointer is NULL, or this offset is zero, the object is assumed + * to have no parent. + */ + int parent_log_context_offset; + + /** + * Category used for visualization (like color). + * + * Only used when ::get_category() is NULL. Use this field when all + * instances of this class have the same category, use ::get_category() + * otherwise. + */ + AVClassCategory category; + + /** + * Callback to return the instance category. Use this callback when + * different instances of this class may have different categories, + * ::category otherwise. + */ + AVClassCategory (*get_category)(void* ctx); + + /** + * Callback to return the supported/allowed ranges. + */ + int (*query_ranges)(struct AVOptionRanges **, void *obj, const char *key, int flags); + + /** + * Return next AVOptions-enabled child or NULL + */ + void* (*child_next)(void *obj, void *prev); + + /** + * Iterate over the AVClasses corresponding to potential AVOptions-enabled + * children. + * + * @param iter pointer to opaque iteration state. The caller must initialize + * *iter to NULL before the first call. + * @return AVClass for the next AVOptions-enabled child or NULL if there are + * no more such children. + * + * @note The difference between ::child_next() and ::child_class_iterate() + * is that ::child_next() iterates over _actual_ children of an + * _existing_ object instance, while ::child_class_iterate() iterates + * over the classes of all _potential_ children of any possible + * instance of this class. + */ + const struct AVClass* (*child_class_iterate)(void **iter); + + /** + * When non-zero, offset in the object to an unsigned int holding object + * state flags, a combination of AVClassStateFlags values. The flags are + * updated by the object to signal its state to the generic code. + * + * Added in version 59.41.100. + */ + int state_flags_offset; +} AVClass; + +/** + * @addtogroup lavu_log + * + * @{ + * + * @defgroup lavu_log_constants Logging Constants + * + * @{ + */ + +/** + * Print no output. + */ +#define AV_LOG_QUIET -8 + +/** + * Something went really wrong and we will crash now. + */ +#define AV_LOG_PANIC 0 + +/** + * Something went wrong and recovery is not possible. + * For example, no header was found for a format which depends + * on headers or an illegal combination of parameters is used. + */ +#define AV_LOG_FATAL 8 + +/** + * Something went wrong and cannot losslessly be recovered. + * However, not all future data is affected. + */ +#define AV_LOG_ERROR 16 + +/** + * Something somehow does not look correct. This may or may not + * lead to problems. An example would be the use of '-vstrict -2'. + */ +#define AV_LOG_WARNING 24 + +/** + * Standard information. + */ +#define AV_LOG_INFO 32 + +/** + * Detailed information. + */ +#define AV_LOG_VERBOSE 40 + +/** + * Stuff which is only useful for libav* developers. + */ +#define AV_LOG_DEBUG 48 + +/** + * Extremely verbose debugging, useful for libav* development. + */ +#define AV_LOG_TRACE 56 + +#define AV_LOG_MAX_OFFSET (AV_LOG_TRACE - AV_LOG_QUIET) + +/** + * @} + */ + +/** + * Sets additional colors for extended debugging sessions. + * @code + av_log(ctx, AV_LOG_DEBUG|AV_LOG_C(134), "Message in purple\n"); + @endcode + * Requires 256color terminal support. Uses outside debugging is not + * recommended. + */ +#define AV_LOG_C(x) ((x) << 8) + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log_set_callback + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct or NULL if general log. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + */ +void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Send the specified message to the log once with the initial_level and then with + * the subsequent_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct or NULL if general log. + * @param initial_level importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant" for the first occurrence. + * @param subsequent_level importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant" after the first occurrence. + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param state a variable to keep trak of if a message has already been printed + * this must be initialized to 0 before the first use. The same state + * must not be accessed by 2 Threads simultaneously. + */ +void av_log_once(void* avcl, int initial_level, int subsequent_level, int *state, const char *fmt, ...) av_printf_format(5, 6); + + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log_set_callback + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param vl The arguments referenced by the format string. + */ +void av_vlog(void *avcl, int level, const char *fmt, va_list vl); + +/** + * Get the current log level + * + * @see lavu_log_constants + * + * @return Current log level + */ +int av_log_get_level(void); + +/** + * Set the log level + * + * @see lavu_log_constants + * + * @param level Logging level + */ +void av_log_set_level(int level); + +/** + * Set the logging callback + * + * @note The callback must be thread safe, even if the application does not use + * threads itself as some codecs are multithreaded. + * + * @see av_log_default_callback + * + * @param callback A logging function with a compatible signature. + */ +void av_log_set_callback(void (*callback)(void*, int, const char*, va_list)); + +/** + * Default logging callback + * + * It prints the message to stderr, optionally colorizing it. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param vl The arguments referenced by the format string. + */ +void av_log_default_callback(void *avcl, int level, const char *fmt, + va_list vl); + +/** + * Return the context name + * + * @param ctx The AVClass context + * + * @return The AVClass class_name + */ +const char* av_default_item_name(void* ctx); +AVClassCategory av_default_get_category(void *ptr); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formatted line + * @param line_size size of the buffer + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + */ +void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formatted line; + * may be NULL if line_size is 0 + * @param line_size size of the buffer; at most line_size-1 characters will + * be written to the buffer, plus one null terminator + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + * @return Returns a negative value if an error occurred, otherwise returns + * the number of characters that would have been written for a + * sufficiently large buffer, not including the terminating null + * character. If the return value is not less than line_size, it means + * that the log message was truncated to fit the buffer. + */ +int av_log_format_line2(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * Skip repeated messages, this requires the user app to use av_log() instead of + * (f)printf as the 2 would otherwise interfere and lead to + * "Last message repeated x times" messages below (f)printf messages with some + * bad luck. + * Also to receive the last, "last repeated" line if any, the user app must + * call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end + */ +#define AV_LOG_SKIP_REPEATED 1 + +/** + * Include the log severity in messages originating from codecs. + * + * Results in messages such as: + * [rawvideo @ 0xDEADBEEF] [error] encode did not produce valid pts + */ +#define AV_LOG_PRINT_LEVEL 2 + +/** + * Include system time in log output. + */ +#define AV_LOG_PRINT_TIME 4 + +/** + * Include system date and time in log output. + */ +#define AV_LOG_PRINT_DATETIME 8 + +void av_log_set_flags(int arg); +int av_log_get_flags(void); + +/** + * @} + */ + +#endif /* AVUTIL_LOG_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/macros.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/macros.h new file mode 100644 index 0000000000000..2a7567c3ea8fb --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/macros.h @@ -0,0 +1,80 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu + * Utility Preprocessor macros + */ + +#ifndef AVUTIL_MACROS_H +#define AVUTIL_MACROS_H + +#include "libavutil/avconfig.h" + +#if AV_HAVE_BIGENDIAN +# define AV_NE(be, le) (be) +#else +# define AV_NE(be, le) (le) +#endif + +/** + * Comparator. + * For two numerical expressions x and y, gives 1 if x > y, -1 if x < y, and 0 + * if x == y. This is useful for instance in a qsort comparator callback. + * Furthermore, compilers are able to optimize this to branchless code, and + * there is no risk of overflow with signed types. + * As with many macros, this evaluates its argument multiple times, it thus + * must not have a side-effect. + */ +#define FFDIFFSIGN(x,y) (((x)>(y)) - ((x)<(y))) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) +#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c) + +#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0) +#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) + +#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24)) +#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24)) + +/** + * @addtogroup preproc_misc Preprocessor String Macros + * + * String manipulation macros + * + * @{ + */ + +#define AV_STRINGIFY(s) AV_TOSTRING(s) +#define AV_TOSTRING(s) #s + +#define AV_GLUE(a, b) a ## b +#define AV_JOIN(a, b) AV_GLUE(a, b) + +/** + * @} + */ + +#define AV_PRAGMA(s) _Pragma(#s) + +#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1)) + +#endif /* AVUTIL_MACROS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/mathematics.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/mathematics.h new file mode 100644 index 0000000000000..486de530f2e4f --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/mathematics.h @@ -0,0 +1,300 @@ +/* + * copyright (c) 2005-2012 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @addtogroup lavu_math + * Mathematical utilities for working with timestamp and time base. + */ + +#ifndef AVUTIL_MATHEMATICS_H +#define AVUTIL_MATHEMATICS_H + +#include +#include +#include "attributes.h" +#include "rational.h" +#include "intfloat.h" + +#ifndef M_E +#define M_E 2.7182818284590452354 /* e */ +#endif +#ifndef M_Ef +#define M_Ef 2.7182818284590452354f /* e */ +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#endif +#ifndef M_LN2f +#define M_LN2f 0.69314718055994530942f /* log_e 2 */ +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#endif +#ifndef M_LN10f +#define M_LN10f 2.30258509299404568402f /* log_e 10 */ +#endif +#ifndef M_LOG2_10 +#define M_LOG2_10 3.32192809488736234787 /* log_2 10 */ +#endif +#ifndef M_LOG2_10f +#define M_LOG2_10f 3.32192809488736234787f /* log_2 10 */ +#endif +#ifndef M_PHI +#define M_PHI 1.61803398874989484820 /* phi / golden ratio */ +#endif +#ifndef M_PHIf +#define M_PHIf 1.61803398874989484820f /* phi / golden ratio */ +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif +#ifndef M_PIf +#define M_PIf 3.14159265358979323846f /* pi */ +#endif +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#endif +#ifndef M_PI_2f +#define M_PI_2f 1.57079632679489661923f /* pi/2 */ +#endif +#ifndef M_PI_4 +#define M_PI_4 0.78539816339744830962 /* pi/4 */ +#endif +#ifndef M_PI_4f +#define M_PI_4f 0.78539816339744830962f /* pi/4 */ +#endif +#ifndef M_1_PI +#define M_1_PI 0.31830988618379067154 /* 1/pi */ +#endif +#ifndef M_1_PIf +#define M_1_PIf 0.31830988618379067154f /* 1/pi */ +#endif +#ifndef M_2_PI +#define M_2_PI 0.63661977236758134308 /* 2/pi */ +#endif +#ifndef M_2_PIf +#define M_2_PIf 0.63661977236758134308f /* 2/pi */ +#endif +#ifndef M_2_SQRTPI +#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +#endif +#ifndef M_2_SQRTPIf +#define M_2_SQRTPIf 1.12837916709551257390f /* 2/sqrt(pi) */ +#endif +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif +#ifndef M_SQRT1_2f +#define M_SQRT1_2f 0.70710678118654752440f /* 1/sqrt(2) */ +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#endif +#ifndef M_SQRT2f +#define M_SQRT2f 1.41421356237309504880f /* sqrt(2) */ +#endif +#ifndef NAN +#define NAN av_int2float(0x7fc00000) +#endif +#ifndef INFINITY +#define INFINITY av_int2float(0x7f800000) +#endif + +/** + * @addtogroup lavu_math + * + * @{ + */ + +/** + * Rounding methods. + */ +enum AVRounding { + AV_ROUND_ZERO = 0, ///< Round toward zero. + AV_ROUND_INF = 1, ///< Round away from zero. + AV_ROUND_DOWN = 2, ///< Round toward -infinity. + AV_ROUND_UP = 3, ///< Round toward +infinity. + AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero. + /** + * Flag telling rescaling functions to pass `INT64_MIN`/`MAX` through + * unchanged, avoiding special cases for #AV_NOPTS_VALUE. + * + * Unlike other values of the enumeration AVRounding, this value is a + * bitmask that must be used in conjunction with another value of the + * enumeration through a bitwise OR, in order to set behavior for normal + * cases. + * + * @code{.c} + * av_rescale_rnd(3, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + * // Rescaling 3: + * // Calculating 3 * 1 / 2 + * // 3 / 2 is rounded up to 2 + * // => 2 + * + * av_rescale_rnd(AV_NOPTS_VALUE, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + * // Rescaling AV_NOPTS_VALUE: + * // AV_NOPTS_VALUE == INT64_MIN + * // AV_NOPTS_VALUE is passed through + * // => AV_NOPTS_VALUE + * @endcode + */ + AV_ROUND_PASS_MINMAX = 8192, +}; + +/** + * Compute the greatest common divisor of two integer operands. + * + * @param a Operand + * @param b Operand + * @return GCD of a and b up to sign; if a >= 0 and b >= 0, return value is >= 0; + * if a == 0 and b == 0, returns 0. + */ +int64_t av_const av_gcd(int64_t a, int64_t b); + +/** + * Rescale a 64-bit integer with rounding to nearest. + * + * The operation is mathematically equivalent to `a * b / c`, but writing that + * directly can overflow. + * + * This function is equivalent to av_rescale_rnd() with #AV_ROUND_NEAR_INF. + * + * @see av_rescale_rnd(), av_rescale_q(), av_rescale_q_rnd() + */ +int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const; + +/** + * Rescale a 64-bit integer with specified rounding. + * + * The operation is mathematically equivalent to `a * b / c`, but writing that + * directly can overflow, and does not support different rounding methods. + * If the result is not representable then INT64_MIN is returned. + * + * @see av_rescale(), av_rescale_q(), av_rescale_q_rnd() + */ +int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers. + * + * The operation is mathematically equivalent to `a * bq / cq`. + * + * This function is equivalent to av_rescale_q_rnd() with #AV_ROUND_NEAR_INF. + * + * @see av_rescale(), av_rescale_rnd(), av_rescale_q_rnd() + */ +int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers with specified rounding. + * + * The operation is mathematically equivalent to `a * bq / cq`. + * + * @see av_rescale(), av_rescale_rnd(), av_rescale_q() + */ +int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, + enum AVRounding rnd) av_const; + +/** + * Compare two timestamps each in its own time base. + * + * @return One of the following values: + * - -1 if `ts_a` is before `ts_b` + * - 1 if `ts_a` is after `ts_b` + * - 0 if they represent the same position + * + * @warning + * The result of the function is undefined if one of the timestamps is outside + * the `int64_t` range when represented in the other's timebase. + */ +int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b); + +/** + * Compare the remainders of two integer operands divided by a common divisor. + * + * In other words, compare the least significant `log2(mod)` bits of integers + * `a` and `b`. + * + * @code{.c} + * av_compare_mod(0x11, 0x02, 0x10) < 0 // since 0x11 % 0x10 (0x1) < 0x02 % 0x10 (0x2) + * av_compare_mod(0x11, 0x02, 0x20) > 0 // since 0x11 % 0x20 (0x11) > 0x02 % 0x20 (0x02) + * @endcode + * + * @param a Operand + * @param b Operand + * @param mod Divisor; must be a power of 2 + * @return + * - a negative value if `a % mod < b % mod` + * - a positive value if `a % mod > b % mod` + * - zero if `a % mod == b % mod` + */ +int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod); + +/** + * Rescale a timestamp while preserving known durations. + * + * This function is designed to be called per audio packet to scale the input + * timestamp to a different time base. Compared to a simple av_rescale_q() + * call, this function is robust against possible inconsistent frame durations. + * + * The `last` parameter is a state variable that must be preserved for all + * subsequent calls for the same stream. For the first call, `*last` should be + * initialized to #AV_NOPTS_VALUE. + * + * @param[in] in_tb Input time base + * @param[in] in_ts Input timestamp + * @param[in] fs_tb Duration time base; typically this is finer-grained + * (greater) than `in_tb` and `out_tb` + * @param[in] duration Duration till the next call to this function (i.e. + * duration of the current packet/frame) + * @param[in,out] last Pointer to a timestamp expressed in terms of + * `fs_tb`, acting as a state variable + * @param[in] out_tb Output timebase + * @return Timestamp expressed in terms of `out_tb` + * + * @note In the context of this function, "duration" is in term of samples, not + * seconds. + */ +int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb); + +/** + * Add a value to a timestamp. + * + * This function guarantees that when the same value is repeatedly added that + * no accumulation of rounding errors occurs. + * + * @param[in] ts Input timestamp + * @param[in] ts_tb Input timestamp time base + * @param[in] inc Value to be added + * @param[in] inc_tb Time base of `inc` + */ +int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc); + +/** + * 0th order modified bessel function of the first kind. + */ +double av_bessel_i0(double x); + +/** + * @} + */ + +#endif /* AVUTIL_MATHEMATICS_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/mem.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/mem.h index 22c3c9c3b36db..ab7648ac5705f 100644 --- a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/mem.h +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/mem.h @@ -27,12 +27,10 @@ #ifndef AVUTIL_MEM_H #define AVUTIL_MEM_H -#include +#include #include #include "attributes.h" -#include "avutil.h" -#include "version.h" /** * @addtogroup lavu_mem @@ -51,44 +49,20 @@ * @{ */ -#if defined(FF_API_DECLARE_ALIGNED) && FF_API_DECLARE_ALIGNED /** + * @defgroup lavu_mem_attrs Function Attributes + * Function attributes applicable to memory handling functions. * - * @defgroup lavu_mem_macros Alignment Macros - * Helper macros for declaring aligned variables. + * These function attributes can help compilers emit more useful warnings, or + * generate better code. * @{ */ -#if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C) - #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v - #define DECLARE_ASM_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v - #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v -#elif defined(__DJGPP__) - #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v - #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v - #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v -#elif defined(__GNUC__) || defined(__clang__) - #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v - #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (n))) v - #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v -#elif defined(_MSC_VER) - #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v - #define DECLARE_ASM_ALIGNED(n,t,v) __declspec(align(n)) t v - #define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v -#else - #define DECLARE_ALIGNED(n,t,v) t v - #define DECLARE_ASM_ALIGNED(n,t,v) t v - #define DECLARE_ASM_CONST(n,t,v) static const t v -#endif - -/** - * @} - */ -#endif - /** - * @defgroup lavu_mem_attrs Function Attributes - * @{ + * @def av_malloc_attrib + * Function attribute denoting a malloc-like function. + * + * @see Function attribute `malloc` in GCC's documentation */ #if AV_GCC_VERSION_AT_LEAST(3,1) @@ -97,6 +71,21 @@ #define av_malloc_attrib #endif +/** + * @def av_alloc_size(...) + * Function attribute used on a function that allocates memory, whose size is + * given by the specified parameter(s). + * + * @code{.c} + * void *av_malloc(size_t size) av_alloc_size(1); + * void *av_calloc(size_t nmemb, size_t size) av_alloc_size(1, 2); + * @endcode + * + * @param ... One or two parameter indexes, separated by a comma + * + * @see Function attribute `alloc_size` in GCC's documentation + */ + #if AV_GCC_VERSION_AT_LEAST(4,3) #define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__))) #else @@ -109,34 +98,505 @@ /** * @defgroup lavu_mem_funcs Heap Management + * Functions responsible for allocating, freeing, and copying memory. + * + * All memory allocation functions have a built-in upper limit of `INT_MAX` + * bytes. This may be changed with av_max_alloc(), although exercise extreme + * caution when doing so. + * * @{ */ +/** + * Allocate a memory block with alignment suitable for all memory accesses + * (including vectors if available on the CPU). + * + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * @see av_mallocz() + */ void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a memory block with alignment suitable for all memory accesses + * (including vectors if available on the CPU) and zero all the bytes of the + * block. + * + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if it cannot be allocated + * @see av_malloc() + */ void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a memory block for an array with av_malloc(). + * + * The allocated memory will have size `size * nmemb` bytes. + * + * @param nmemb Number of element + * @param size Size of a single element + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * @see av_malloc() + */ av_alloc_size(1, 2) void *av_malloc_array(size_t nmemb, size_t size); + +/** + * Allocate a memory block for an array with av_mallocz(). + * + * The allocated memory will have size `size * nmemb` bytes. + * + * @param nmemb Number of elements + * @param size Size of the single element + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * + * @see av_mallocz() + * @see av_malloc_array() + */ void *av_calloc(size_t nmemb, size_t size) av_malloc_attrib av_alloc_size(1, 2); + +/** + * Allocate, reallocate, or free a block of memory. + * + * If `ptr` is `NULL` and `size` > 0, allocate a new block. Otherwise, expand or + * shrink that block of memory according to `size`. + * + * @param ptr Pointer to a memory block already allocated with + * av_realloc() or `NULL` + * @param size Size in bytes of the memory block to be allocated or + * reallocated + * + * @return Pointer to a newly-reallocated block or `NULL` if the block + * cannot be reallocated + * + * @warning Unlike av_malloc(), the returned pointer is not guaranteed to be + * correctly aligned. The returned pointer must be freed after even + * if size is zero. + * @see av_fast_realloc() + * @see av_reallocp() + */ void *av_realloc(void *ptr, size_t size) av_alloc_size(2); + +/** + * Allocate, reallocate, or free a block of memory through a pointer to a + * pointer. + * + * If `*ptr` is `NULL` and `size` > 0, allocate a new block. If `size` is + * zero, free the memory block pointed to by `*ptr`. Otherwise, expand or + * shrink that block of memory according to `size`. + * + * @param[in,out] ptr Pointer to a pointer to a memory block already allocated + * with av_realloc(), or a pointer to `NULL`. The pointer + * is updated on success, or freed on failure. + * @param[in] size Size in bytes for the memory block to be allocated or + * reallocated + * + * @return Zero on success, an AVERROR error code on failure + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. + */ av_warn_unused_result int av_reallocp(void *ptr, size_t size); + +/** + * Allocate, reallocate, or free a block of memory. + * + * This function does the same thing as av_realloc(), except: + * - It takes two size arguments and allocates `nelem * elsize` bytes, + * after checking the result of the multiplication for integer overflow. + * - It frees the input block in case of failure, thus avoiding the memory + * leak with the classic + * @code{.c} + * buf = realloc(buf); + * if (!buf) + * return -1; + * @endcode + * pattern. + */ void *av_realloc_f(void *ptr, size_t nelem, size_t elsize); + +/** + * Allocate, reallocate, or free an array. + * + * If `ptr` is `NULL` and `nmemb` > 0, allocate a new block. + * + * @param ptr Pointer to a memory block already allocated with + * av_realloc() or `NULL` + * @param nmemb Number of elements in the array + * @param size Size of the single element of the array + * + * @return Pointer to a newly-reallocated block or NULL if the block + * cannot be reallocated + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. The returned pointer must be freed after even if + * nmemb is zero. + * @see av_reallocp_array() + */ av_alloc_size(2, 3) void *av_realloc_array(void *ptr, size_t nmemb, size_t size); + +/** + * Allocate, reallocate an array through a pointer to a pointer. + * + * If `*ptr` is `NULL` and `nmemb` > 0, allocate a new block. + * + * @param[in,out] ptr Pointer to a pointer to a memory block already + * allocated with av_realloc(), or a pointer to `NULL`. + * The pointer is updated on success, or freed on failure. + * @param[in] nmemb Number of elements + * @param[in] size Size of the single element + * + * @return Zero on success, an AVERROR error code on failure + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. *ptr must be freed after even if nmemb is zero. + */ int av_reallocp_array(void *ptr, size_t nmemb, size_t size); + +/** + * Reallocate the given buffer if it is not large enough, otherwise do nothing. + * + * If the given buffer is `NULL`, then a new uninitialized buffer is allocated. + * + * If the given buffer is not large enough, and reallocation fails, `NULL` is + * returned and `*size` is set to 0, but the original buffer is not changed or + * freed. + * + * A typical use pattern follows: + * + * @code{.c} + * uint8_t *buf = ...; + * uint8_t *new_buf = av_fast_realloc(buf, ¤t_size, size_needed); + * if (!new_buf) { + * // Allocation failed; clean up original buffer + * av_freep(&buf); + * return AVERROR(ENOMEM); + * } + * @endcode + * + * @param[in,out] ptr Already allocated buffer, or `NULL` + * @param[in,out] size Pointer to the size of buffer `ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `ptr` + * @return `ptr` if the buffer is large enough, a pointer to newly reallocated + * buffer if the buffer was not large enough, or `NULL` in case of + * error + * @see av_realloc() + * @see av_fast_malloc() + */ void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate a buffer, reusing the given one if large enough. + * + * Contrary to av_fast_realloc(), the current buffer contents might not be + * preserved and on error the old buffer is freed, thus no special handling to + * avoid memleaks is necessary. + * + * `*ptr` is allowed to be `NULL`, in which case allocation always happens if + * `size_needed` is greater than 0. + * + * @code{.c} + * uint8_t *buf = ...; + * av_fast_malloc(&buf, ¤t_size, size_needed); + * if (!buf) { + * // Allocation failed; buf already freed + * return AVERROR(ENOMEM); + * } + * @endcode + * + * @param[in,out] ptr Pointer to pointer to an already allocated buffer. + * `*ptr` will be overwritten with pointer to new + * buffer on success or `NULL` on failure + * @param[in,out] size Pointer to the size of buffer `*ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `*ptr` + * @see av_realloc() + * @see av_fast_mallocz() + */ void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate and clear a buffer, reusing the given one if large enough. + * + * Like av_fast_malloc(), but all newly allocated space is initially cleared. + * Reused buffer is not cleared. + * + * `*ptr` is allowed to be `NULL`, in which case allocation always happens if + * `size_needed` is greater than 0. + * + * @param[in,out] ptr Pointer to pointer to an already allocated buffer. + * `*ptr` will be overwritten with pointer to new + * buffer on success or `NULL` on failure + * @param[in,out] size Pointer to the size of buffer `*ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `*ptr` + * @see av_fast_malloc() + */ void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * Free a memory block which has been allocated with a function of av_malloc() + * or av_realloc() family. + * + * @param ptr Pointer to the memory block which should be freed. + * + * @note `ptr = NULL` is explicitly allowed. + * @note It is recommended that you use av_freep() instead, to prevent leaving + * behind dangling pointers. + * @see av_freep() + */ void av_free(void *ptr); + +/** + * Free a memory block which has been allocated with a function of av_malloc() + * or av_realloc() family, and set the pointer pointing to it to `NULL`. + * + * @code{.c} + * uint8_t *buf = av_malloc(16); + * av_free(buf); + * // buf now contains a dangling pointer to freed memory, and accidental + * // dereference of buf will result in a use-after-free, which may be a + * // security risk. + * + * uint8_t *buf = av_malloc(16); + * av_freep(&buf); + * // buf is now NULL, and accidental dereference will only result in a + * // NULL-pointer dereference. + * @endcode + * + * @param ptr Pointer to the pointer to the memory block which should be freed + * @note `*ptr = NULL` is safe and leads to no action. + * @see av_free() + */ void av_freep(void *ptr); + +/** + * Duplicate a string. + * + * @param s String to be duplicated + * @return Pointer to a newly-allocated string containing a + * copy of `s` or `NULL` if the string cannot be allocated + * @see av_strndup() + */ char *av_strdup(const char *s) av_malloc_attrib; + +/** + * Duplicate a substring of a string. + * + * @param s String to be duplicated + * @param len Maximum length of the resulting string (not counting the + * terminating byte) + * @return Pointer to a newly-allocated string containing a + * substring of `s` or `NULL` if the string cannot be allocated + */ char *av_strndup(const char *s, size_t len) av_malloc_attrib; + +/** + * Duplicate a buffer with av_malloc(). + * + * @param p Buffer to be duplicated + * @param size Size in bytes of the buffer copied + * @return Pointer to a newly allocated buffer containing a + * copy of `p` or `NULL` if the buffer cannot be allocated + */ void *av_memdup(const void *p, size_t size); + +/** + * Overlapping memcpy() implementation. + * + * @param dst Destination buffer + * @param back Number of bytes back to start copying (i.e. the initial size of + * the overlapping window); must be > 0 + * @param cnt Number of bytes to copy; must be >= 0 + * + * @note `cnt > back` is valid, this will copy the bytes we just copied, + * thus creating a repeating pattern with a period length of `back`. + */ void av_memcpy_backptr(uint8_t *dst, int back, int cnt); + +/** + * @} + */ + +/** + * @defgroup lavu_mem_dynarray Dynamic Array + * + * Utilities to make an array grow when needed. + * + * Sometimes, the programmer would want to have an array that can grow when + * needed. The libavutil dynamic array utilities fill that need. + * + * libavutil supports two systems of appending elements onto a dynamically + * allocated array, the first one storing the pointer to the value in the + * array, and the second storing the value directly. In both systems, the + * caller is responsible for maintaining a variable containing the length of + * the array, as well as freeing of the array after use. + * + * The first system stores pointers to values in a block of dynamically + * allocated memory. Since only pointers are stored, the function does not need + * to know the size of the type. Both av_dynarray_add() and + * av_dynarray_add_nofree() implement this system. + * + * @code + * type **array = NULL; //< an array of pointers to values + * int nb = 0; //< a variable to keep track of the length of the array + * + * type to_be_added = ...; + * type to_be_added2 = ...; + * + * av_dynarray_add(&array, &nb, &to_be_added); + * if (nb == 0) + * return AVERROR(ENOMEM); + * + * av_dynarray_add(&array, &nb, &to_be_added2); + * if (nb == 0) + * return AVERROR(ENOMEM); + * + * // Now: + * // nb == 2 + * // &to_be_added == array[0] + * // &to_be_added2 == array[1] + * + * av_freep(&array); + * @endcode + * + * The second system stores the value directly in a block of memory. As a + * result, the function has to know the size of the type. av_dynarray2_add() + * implements this mechanism. + * + * @code + * type *array = NULL; //< an array of values + * int nb = 0; //< a variable to keep track of the length of the array + * + * type to_be_added = ...; + * type to_be_added2 = ...; + * + * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), NULL); + * if (!addr) + * return AVERROR(ENOMEM); + * memcpy(addr, &to_be_added, sizeof(to_be_added)); + * + * // Shortcut of the above. + * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), + * (const void *)&to_be_added2); + * if (!addr) + * return AVERROR(ENOMEM); + * + * // Now: + * // nb == 2 + * // to_be_added == array[0] + * // to_be_added2 == array[1] + * + * av_freep(&array); + * @endcode + * + * @{ + */ + +/** + * Add the pointer to an element to a dynamic array. + * + * The array to grow is supposed to be an array of pointers to + * structures, and the element to add must be a pointer to an already + * allocated structure. + * + * The array is reallocated when its size reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the number pointed to by `nb_ptr` + * is incremented. + * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and + * `*nb_ptr` is set to 0. + * + * @param[in,out] tab_ptr Pointer to the array to grow + * @param[in,out] nb_ptr Pointer to the number of elements in the array + * @param[in] elem Element to add + * @see av_dynarray_add_nofree(), av_dynarray2_add() + */ void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element to a dynamic array. + * + * Function has the same functionality as av_dynarray_add(), + * but it doesn't free memory on fails. It returns error code + * instead and leave current buffer untouched. + * + * @return >=0 on success, negative otherwise + * @see av_dynarray_add(), av_dynarray2_add() + */ av_warn_unused_result int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element of size `elem_size` to a dynamic array. + * + * The array is reallocated when its number of elements reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the number pointed to by `nb_ptr` + * is incremented. + * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and + * `*nb_ptr` is set to 0. + * + * @param[in,out] tab_ptr Pointer to the array to grow + * @param[in,out] nb_ptr Pointer to the number of elements in the array + * @param[in] elem_size Size in bytes of an element in the array + * @param[in] elem_data Pointer to the data of the element to add. If + * `NULL`, the space of the newly added element is + * allocated but left uninitialized. + * + * @return Pointer to the data of the element to copy in the newly allocated + * space + * @see av_dynarray_add(), av_dynarray_add_nofree() + */ void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, const uint8_t *elem_data); + +/** + * @} + */ + +/** + * @defgroup lavu_mem_misc Miscellaneous Functions + * + * Other functions related to memory allocation. + * + * @{ + */ + +/** + * Multiply two `size_t` values checking for overflow. + * + * @param[in] a Operand of multiplication + * @param[in] b Operand of multiplication + * @param[out] r Pointer to the result of the operation + * @return 0 on success, AVERROR(EINVAL) on overflow + */ int av_size_mult(size_t a, size_t b, size_t *r); + +/** + * Set the maximum size that may be allocated in one block. + * + * The value specified with this function is effective for all libavutil's @ref + * lavu_mem_funcs "heap management functions." + * + * By default, the max value is defined as `INT_MAX`. + * + * @param max Value to be set as the new maximum size + * + * @warning Exercise extreme caution when using this function. Don't touch + * this if you do not understand the full consequence of doing so. + */ void av_max_alloc(size_t max); /** diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/opt.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/opt.h new file mode 100644 index 0000000000000..ab24fae7779fb --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/opt.h @@ -0,0 +1,1194 @@ +/* + * AVOptions + * copyright (c) 2005 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_OPT_H +#define AVUTIL_OPT_H + +/** + * @file + * AVOptions + */ + +#include "rational.h" +#include "avutil.h" +#include "channel_layout.h" +#include "dict.h" +#include "log.h" +#include "pixfmt.h" +#include "samplefmt.h" + +/** + * @defgroup avoptions AVOptions + * @ingroup lavu_data + * @{ + * AVOptions provide a generic system to declare options on arbitrary structs + * ("objects"). An option can have a help text, a type and a range of possible + * values. Options may then be enumerated, read and written to. + * + * There are two modes of access to members of AVOption and its child structs. + * One is called 'native access', and refers to access from the code that + * declares the AVOption in question. The other is 'foreign access', and refers + * to access from other code. + * + * Certain struct members in this header are documented as 'native access only' + * or similar - it means that only the code that declared the AVOption in + * question is allowed to access the field. This allows us to extend the + * semantics of those fields without breaking API compatibility. + * + * @section avoptions_scope Scope of AVOptions + * + * AVOptions is designed to support any set of multimedia configuration options + * that can be defined at compile-time. Although it is mainly used to expose + * FFmpeg options, you are welcome to adapt it to your own use case. + * + * No single approach can ever fully solve the problem of configuration, + * but please submit a patch if you believe you have found a problem + * that is best solved by extending AVOptions. + * + * @section avoptions_implement Implementing AVOptions + * This section describes how to add AVOptions capabilities to a struct. + * + * All AVOptions-related information is stored in an AVClass. Therefore + * the first member of the struct should be a pointer to an AVClass describing it. + * The option field of the AVClass must be set to a NULL-terminated static array + * of AVOptions. Each AVOption must have a non-empty name, a type, a default + * value and for number-type AVOptions also a range of allowed values. It must + * also declare an offset in bytes from the start of the struct, where the field + * associated with this AVOption is located. Other fields in the AVOption struct + * should also be set when applicable, but are not required. + * + * The following example illustrates an AVOptions-enabled struct: + * @code + * typedef struct test_struct { + * const AVClass *class; + * int int_opt; + * char *str_opt; + * uint8_t *bin_opt; + * int bin_len; + * } test_struct; + * + * static const AVOption test_options[] = { + * { "test_int", "This is a test option of int type.", offsetof(test_struct, int_opt), + * AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX }, + * { "test_str", "This is a test option of string type.", offsetof(test_struct, str_opt), + * AV_OPT_TYPE_STRING }, + * { "test_bin", "This is a test option of binary type.", offsetof(test_struct, bin_opt), + * AV_OPT_TYPE_BINARY }, + * { NULL }, + * }; + * + * static const AVClass test_class = { + * .class_name = "test class", + * .item_name = av_default_item_name, + * .option = test_options, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * @endcode + * + * Next, when allocating your struct, you must ensure that the AVClass pointer + * is set to the correct value. Then, av_opt_set_defaults() can be called to + * initialize defaults. After that the struct is ready to be used with the + * AVOptions API. + * + * When cleaning up, you may use the av_opt_free() function to automatically + * free all the allocated string and binary options. + * + * Continuing with the above example: + * + * @code + * test_struct *alloc_test_struct(void) + * { + * test_struct *ret = av_mallocz(sizeof(*ret)); + * ret->class = &test_class; + * av_opt_set_defaults(ret); + * return ret; + * } + * void free_test_struct(test_struct **foo) + * { + * av_opt_free(*foo); + * av_freep(foo); + * } + * @endcode + * + * @subsection avoptions_implement_nesting Nesting + * It may happen that an AVOptions-enabled struct contains another + * AVOptions-enabled struct as a member (e.g. AVCodecContext in + * libavcodec exports generic options, while its priv_data field exports + * codec-specific options). In such a case, it is possible to set up the + * parent struct to export a child's options. To do that, simply + * implement AVClass.child_next() and AVClass.child_class_iterate() in the + * parent struct's AVClass. + * Assuming that the test_struct from above now also contains a + * child_struct field: + * + * @code + * typedef struct child_struct { + * AVClass *class; + * int flags_opt; + * } child_struct; + * static const AVOption child_opts[] = { + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX }, + * { NULL }, + * }; + * static const AVClass child_class = { + * .class_name = "child class", + * .item_name = av_default_item_name, + * .option = child_opts, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * + * void *child_next(void *obj, void *prev) + * { + * test_struct *t = obj; + * if (!prev && t->child_struct) + * return t->child_struct; + * return NULL + * } + * const AVClass child_class_iterate(void **iter) + * { + * const AVClass *c = *iter ? NULL : &child_class; + * *iter = (void*)(uintptr_t)c; + * return c; + * } + * @endcode + * Putting child_next() and child_class_iterate() as defined above into + * test_class will now make child_struct's options accessible through + * test_struct (again, proper setup as described above needs to be done on + * child_struct right after it is created). + * + * From the above example it might not be clear why both child_next() + * and child_class_iterate() are needed. The distinction is that child_next() + * iterates over actually existing objects, while child_class_iterate() + * iterates over all possible child classes. E.g. if an AVCodecContext + * was initialized to use a codec which has private options, then its + * child_next() will return AVCodecContext.priv_data and finish + * iterating. OTOH child_class_iterate() on AVCodecContext.av_class will + * iterate over all available codecs with private options. + * + * @subsection avoptions_implement_named_constants Named constants + * It is possible to create named constants for options. Simply set the unit + * field of the option the constants should apply to a string and + * create the constants themselves as options of type AV_OPT_TYPE_CONST + * with their unit field set to the same string. + * Their default_val field should contain the value of the named + * constant. + * For example, to add some named constants for the test_flags option + * above, put the following into the child_opts array: + * @code + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, "test_unit" }, + * { "flag1", "This is a flag with value 16", 0, AV_OPT_TYPE_CONST, { .i64 = 16 }, 0, 0, "test_unit" }, + * @endcode + * + * @section avoptions_use Using AVOptions + * This section deals with accessing options in an AVOptions-enabled struct. + * Such structs in FFmpeg are e.g. AVCodecContext in libavcodec or + * AVFormatContext in libavformat. + * + * @subsection avoptions_use_examine Examining AVOptions + * The basic functions for examining options are av_opt_next(), which iterates + * over all options defined for one object, and av_opt_find(), which searches + * for an option with the given name. + * + * The situation is more complicated with nesting. An AVOptions-enabled struct + * may have AVOptions-enabled children. Passing the AV_OPT_SEARCH_CHILDREN flag + * to av_opt_find() will make the function search children recursively. + * + * For enumerating there are basically two cases. The first is when you want to + * get all options that may potentially exist on the struct and its children + * (e.g. when constructing documentation). In that case you should call + * av_opt_child_class_iterate() recursively on the parent struct's AVClass. The + * second case is when you have an already initialized struct with all its + * children and you want to get all options that can be actually written or read + * from it. In that case you should call av_opt_child_next() recursively (and + * av_opt_next() on each result). + * + * @subsection avoptions_use_get_set Reading and writing AVOptions + * When setting options, you often have a string read directly from the + * user. In such a case, simply passing it to av_opt_set() is enough. For + * non-string type options, av_opt_set() will parse the string according to the + * option type. + * + * Similarly av_opt_get() will read any option type and convert it to a string + * which will be returned. Do not forget that the string is allocated, so you + * have to free it with av_free(). + * + * In some cases it may be more convenient to put all options into an + * AVDictionary and call av_opt_set_dict() on it. A specific case of this + * are the format/codec open functions in lavf/lavc which take a dictionary + * filled with option as a parameter. This makes it possible to set some options + * that cannot be set otherwise, since e.g. the input file format is not known + * before the file is actually opened. + */ + +/** + * An option type determines: + * - for native access, the underlying C type of the field that an AVOption + * refers to; + * - for foreign access, the semantics of accessing the option through this API, + * e.g. which av_opt_get_*() and av_opt_set_*() functions can be called, or + * what format will av_opt_get()/av_opt_set() expect/produce. + */ +enum AVOptionType{ + /** + * Underlying C type is unsigned int. + */ + AV_OPT_TYPE_FLAGS = 1, + /** + * Underlying C type is int. + */ + AV_OPT_TYPE_INT, + /** + * Underlying C type is int64_t. + */ + AV_OPT_TYPE_INT64, + /** + * Underlying C type is double. + */ + AV_OPT_TYPE_DOUBLE, + /** + * Underlying C type is float. + */ + AV_OPT_TYPE_FLOAT, + /** + * Underlying C type is a uint8_t* that is either NULL or points to a C + * string allocated with the av_malloc() family of functions. + */ + AV_OPT_TYPE_STRING, + /** + * Underlying C type is AVRational. + */ + AV_OPT_TYPE_RATIONAL, + /** + * Underlying C type is a uint8_t* that is either NULL or points to an array + * allocated with the av_malloc() family of functions. The pointer is + * immediately followed by an int containing the array length in bytes. + */ + AV_OPT_TYPE_BINARY, + /** + * Underlying C type is AVDictionary*. + */ + AV_OPT_TYPE_DICT, + /** + * Underlying C type is uint64_t. + */ + AV_OPT_TYPE_UINT64, + /** + * Special option type for declaring named constants. Does not correspond to + * an actual field in the object, offset must be 0. + */ + AV_OPT_TYPE_CONST, + /** + * Underlying C type is two consecutive integers. + */ + AV_OPT_TYPE_IMAGE_SIZE, + /** + * Underlying C type is enum AVPixelFormat. + */ + AV_OPT_TYPE_PIXEL_FMT, + /** + * Underlying C type is enum AVSampleFormat. + */ + AV_OPT_TYPE_SAMPLE_FMT, + /** + * Underlying C type is AVRational. + */ + AV_OPT_TYPE_VIDEO_RATE, + /** + * Underlying C type is int64_t. + */ + AV_OPT_TYPE_DURATION, + /** + * Underlying C type is uint8_t[4]. + */ + AV_OPT_TYPE_COLOR, + /** + * Underlying C type is int. + */ + AV_OPT_TYPE_BOOL, + /** + * Underlying C type is AVChannelLayout. + */ + AV_OPT_TYPE_CHLAYOUT, + /** + * Underlying C type is unsigned int. + */ + AV_OPT_TYPE_UINT, + + /** + * May be combined with another regular option type to declare an array + * option. + * + * For array options, @ref AVOption.offset should refer to a pointer + * corresponding to the option type. The pointer should be immediately + * followed by an unsigned int that will store the number of elements in the + * array. + */ + AV_OPT_TYPE_FLAG_ARRAY = (1 << 16), +}; + +/** + * A generic parameter which can be set by the user for muxing or encoding. + */ +#define AV_OPT_FLAG_ENCODING_PARAM (1 << 0) +/** + * A generic parameter which can be set by the user for demuxing or decoding. + */ +#define AV_OPT_FLAG_DECODING_PARAM (1 << 1) +#define AV_OPT_FLAG_AUDIO_PARAM (1 << 3) +#define AV_OPT_FLAG_VIDEO_PARAM (1 << 4) +#define AV_OPT_FLAG_SUBTITLE_PARAM (1 << 5) +/** + * The option is intended for exporting values to the caller. + */ +#define AV_OPT_FLAG_EXPORT (1 << 6) +/** + * The option may not be set through the AVOptions API, only read. + * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set. + */ +#define AV_OPT_FLAG_READONLY (1 << 7) +/** + * A generic parameter which can be set by the user for bit stream filtering. + */ +#define AV_OPT_FLAG_BSF_PARAM (1 << 8) + +/** + * A generic parameter which can be set by the user at runtime. + */ +#define AV_OPT_FLAG_RUNTIME_PARAM (1 << 15) +/** + * A generic parameter which can be set by the user for filtering. + */ +#define AV_OPT_FLAG_FILTERING_PARAM (1 << 16) +/** + * Set if option is deprecated, users should refer to AVOption.help text for + * more information. + */ +#define AV_OPT_FLAG_DEPRECATED (1 << 17) +/** + * Set if option constants can also reside in child objects. + */ +#define AV_OPT_FLAG_CHILD_CONSTS (1 << 18) + +/** + * May be set as default_val for AV_OPT_TYPE_FLAG_ARRAY options. + */ +typedef struct AVOptionArrayDef { + /** + * Native access only. + * + * Default value of the option, as would be serialized by av_opt_get() (i.e. + * using the value of sep as the separator). + */ + const char *def; + + /** + * Minimum number of elements in the array. When this field is non-zero, def + * must be non-NULL and contain at least this number of elements. + */ + unsigned size_min; + /** + * Maximum number of elements in the array, 0 when unlimited. + */ + unsigned size_max; + + /** + * Separator between array elements in string representations of this + * option, used by av_opt_set() and av_opt_get(). It must be a printable + * ASCII character, excluding alphanumeric and the backslash. A comma is + * used when sep=0. + * + * The separator and the backslash must be backslash-escaped in order to + * appear in string representations of the option value. + */ + char sep; +} AVOptionArrayDef; + +/** + * AVOption + */ +typedef struct AVOption { + const char *name; + + /** + * short English help text + * @todo What about other languages? + */ + const char *help; + + /** + * Native access only. + * + * The offset relative to the context structure where the option + * value is stored. It should be 0 for named constants. + */ + int offset; + enum AVOptionType type; + + /** + * Native access only, except when documented otherwise. + * the default value for scalar options + */ + union { + int64_t i64; + double dbl; + const char *str; + /* TODO those are unused now */ + AVRational q; + + /** + * Used for AV_OPT_TYPE_FLAG_ARRAY options. May be NULL. + * + * Foreign access to some members allowed, as noted in AVOptionArrayDef + * documentation. + */ + const AVOptionArrayDef *arr; + } default_val; + double min; ///< minimum valid value for the option + double max; ///< maximum valid value for the option + + /** + * A combination of AV_OPT_FLAG_*. + */ + int flags; + + /** + * The logical unit to which the option belongs. Non-constant + * options and corresponding named constants share the same + * unit. May be NULL. + */ + const char *unit; +} AVOption; + +/** + * A single allowed range of values, or a single allowed value. + */ +typedef struct AVOptionRange { + const char *str; + /** + * Value range. + * For string ranges this represents the min/max length. + * For dimensions this represents the min/max pixel count or width/height in multi-component case. + */ + double value_min, value_max; + /** + * Value's component range. + * For string this represents the unicode range for chars, 0-127 limits to ASCII. + */ + double component_min, component_max; + /** + * Range flag. + * If set to 1 the struct encodes a range, if set to 0 a single value. + */ + int is_range; +} AVOptionRange; + +/** + * List of AVOptionRange structs. + */ +typedef struct AVOptionRanges { + /** + * Array of option ranges. + * + * Most of option types use just one component. + * Following describes multi-component option types: + * + * AV_OPT_TYPE_IMAGE_SIZE: + * component index 0: range of pixel count (width * height). + * component index 1: range of width. + * component index 2: range of height. + * + * @note To obtain multi-component version of this structure, user must + * provide AV_OPT_MULTI_COMPONENT_RANGE to av_opt_query_ranges or + * av_opt_query_ranges_default function. + * + * Multi-component range can be read as in following example: + * + * @code + * int range_index, component_index; + * AVOptionRanges *ranges; + * AVOptionRange *range[3]; //may require more than 3 in the future. + * av_opt_query_ranges(&ranges, obj, key, AV_OPT_MULTI_COMPONENT_RANGE); + * for (range_index = 0; range_index < ranges->nb_ranges; range_index++) { + * for (component_index = 0; component_index < ranges->nb_components; component_index++) + * range[component_index] = ranges->range[ranges->nb_ranges * component_index + range_index]; + * //do something with range here. + * } + * av_opt_freep_ranges(&ranges); + * @endcode + */ + AVOptionRange **range; + /** + * Number of ranges per component. + */ + int nb_ranges; + /** + * Number of components. + */ + int nb_components; +} AVOptionRanges; + +/** + * @defgroup opt_mng AVOption (un)initialization and inspection. + * @{ + */ + +/** + * Set the values of all AVOption fields to their default values. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + */ +void av_opt_set_defaults(void *s); + +/** + * Set the values of all AVOption fields to their default values. Only these + * AVOption fields for which (opt->flags & mask) == flags will have their + * default applied to s. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + * @param mask combination of AV_OPT_FLAG_* + * @param flags combination of AV_OPT_FLAG_* + */ +void av_opt_set_defaults2(void *s, int mask, int flags); + +/** + * Free all allocated objects in obj. + */ +void av_opt_free(void *obj); + +/** + * Iterate over all AVOptions belonging to obj. + * + * @param obj an AVOptions-enabled struct or a double pointer to an + * AVClass describing it. + * @param prev result of the previous call to av_opt_next() on this object + * or NULL + * @return next AVOption or NULL + */ +const AVOption *av_opt_next(const void *obj, const AVOption *prev); + +/** + * Iterate over AVOptions-enabled children of obj. + * + * @param prev result of a previous call to this function or NULL + * @return next AVOptions-enabled child or NULL + */ +void *av_opt_child_next(void *obj, void *prev); + +/** + * Iterate over potential AVOptions-enabled children of parent. + * + * @param iter a pointer where iteration state is stored. + * @return AVClass corresponding to next potential child or NULL + */ +const AVClass *av_opt_child_class_iterate(const AVClass *parent, void **iter); + +#define AV_OPT_SEARCH_CHILDREN (1 << 0) /**< Search in possible children of the + given object first. */ +/** + * The obj passed to av_opt_find() is fake -- only a double pointer to AVClass + * instead of a required pointer to a struct containing AVClass. This is + * useful for searching for options without needing to allocate the corresponding + * object. + */ +#define AV_OPT_SEARCH_FAKE_OBJ (1 << 1) + +/** + * In av_opt_get, return NULL if the option has a pointer type and is set to NULL, + * rather than returning an empty string. + */ +#define AV_OPT_ALLOW_NULL (1 << 2) + +/** + * May be used with av_opt_set_array() to signal that new elements should + * replace the existing ones in the indicated range. + */ +#define AV_OPT_ARRAY_REPLACE (1 << 3) + +/** + * Allows av_opt_query_ranges and av_opt_query_ranges_default to return more than + * one component for certain option types. + * @see AVOptionRanges for details. + */ +#define AV_OPT_MULTI_COMPONENT_RANGE (1 << 12) + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return A pointer to the option found, or NULL if no option + * was found. + * + * @note Options found with AV_OPT_SEARCH_CHILDREN flag may not be settable + * directly with av_opt_set(). Use special calls which take an options + * AVDictionary (e.g. avformat_open_input()) to set options found with this + * flag. + */ +const AVOption *av_opt_find(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags); + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * @param[out] target_obj if non-NULL, an object to which the option belongs will be + * written here. It may be different from obj if AV_OPT_SEARCH_CHILDREN is present + * in search_flags. This parameter is ignored if search_flags contain + * AV_OPT_SEARCH_FAKE_OBJ. + * + * @return A pointer to the option found, or NULL if no option + * was found. + */ +const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags, void **target_obj); + +/** + * Show the obj options. + * + * @param req_flags requested flags for the options to show. Show only the + * options for which it is opt->flags & req_flags. + * @param rej_flags rejected flags for the options to show. Show only the + * options for which it is !(opt->flags & req_flags). + * @param av_log_obj log context to use for showing the options + */ +int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); + +/** + * Extract a key-value pair from the beginning of a string. + * + * @param ropts pointer to the options string, will be updated to + * point to the rest of the string (one of the pairs_sep + * or the final NUL) + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @param flags flags; see the AV_OPT_FLAG_* values below + * @param rkey parsed key; must be freed using av_free() + * @param rval parsed value; must be freed using av_free() + * + * @return >=0 for success, or a negative value corresponding to an + * AVERROR code in case of error; in particular: + * AVERROR(EINVAL) if no key is present + * + */ +int av_opt_get_key_value(const char **ropts, + const char *key_val_sep, const char *pairs_sep, + unsigned flags, + char **rkey, char **rval); + +enum { + + /** + * Accept to parse a value without a key; the key will then be returned + * as NULL. + */ + AV_OPT_FLAG_IMPLICIT_KEY = 1, +}; + +/** + * @} + */ + +/** + * @defgroup opt_write Setting and modifying option values + * @{ + */ + +/** + * Parse the key/value pairs list in opts. For each key/value pair + * found, stores the value in the field in ctx that is named like the + * key. ctx must be an AVClass context, storing is done using + * AVOptions. + * + * @param opts options string to parse, may be NULL + * @param key_val_sep a 0-terminated list of characters used to + * separate key from value + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other + * @return the number of successfully set key/value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_opt_set() if a key/value pair + * cannot be set + */ +int av_set_options_string(void *ctx, const char *opts, + const char *key_val_sep, const char *pairs_sep); + +/** + * Parse the key-value pairs list in opts. For each key=value pair found, + * set the value of the corresponding option in ctx. + * + * @param ctx the AVClass object to set options on + * @param opts the options string, key-value pairs separated by a + * delimiter + * @param shorthand a NULL-terminated array of options names for shorthand + * notation: if the first field in opts has no key part, + * the key is taken from the first element of shorthand; + * then again for the second, etc., until either opts is + * finished, shorthand is finished or a named option is + * found; after that, all options must be named + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @return the number of successfully set key=value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_set_string3() if a key/value pair + * cannot be set + * + * Options names must use only the following characters: a-z A-Z 0-9 - . / _ + * Separators must use characters distinct from option names and from each + * other. + */ +int av_opt_set_from_string(void *ctx, const char *opts, + const char *const *shorthand, + const char *key_val_sep, const char *pairs_sep); + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict(void *obj, struct AVDictionary **options); + + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags); + +/** + * Copy options from src object into dest object. + * + * The underlying AVClass of both src and dest must coincide. The guarantee + * below does not apply if this is not fulfilled. + * + * Options that require memory allocation (e.g. string or binary) are malloc'ed in dest object. + * Original memory allocated for such options is freed unless both src and dest options points to the same memory. + * + * Even on error it is guaranteed that allocated options from src and dest + * no longer alias each other afterwards; in particular calling av_opt_free() + * on both src and dest is safe afterwards if dest has been memdup'ed from src. + * + * @param dest Object to copy from + * @param src Object to copy into + * @return 0 on success, negative on error + */ +int av_opt_copy(void *dest, const void *src); + +/** + * @defgroup opt_set_funcs Option setting functions + * @{ + * Those functions set the field of obj with the given name to value. + * + * @param[in] obj A struct whose first element is a pointer to an AVClass. + * @param[in] name the name of the field to set + * @param[in] val The value to set. In case of av_opt_set() if the field is not + * of a string type, then the given string is parsed. + * SI postfixes and some named scalars are supported. + * If the field is of a numeric type, it has to be a numeric or named + * scalar. Behavior with more than one scalar and +- infix operators + * is undefined. + * If the field is of a flags type, it has to be a sequence of numeric + * scalars or named flags separated by '+' or '-'. Prefixing a flag + * with '+' causes it to be set without affecting the other flags; + * similarly, '-' unsets a flag. + * If the field is of a dictionary type, it has to be a ':' separated list of + * key=value parameters. Values containing ':' special characters must be + * escaped. + * @param search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be set on a child of obj. + * + * @return 0 if the value has been set, or an AVERROR code in case of + * error: + * AVERROR_OPTION_NOT_FOUND if no matching option exists + * AVERROR(ERANGE) if the value is out of range + * AVERROR(EINVAL) if the value is not valid + */ +int av_opt_set (void *obj, const char *name, const char *val, int search_flags); +int av_opt_set_int (void *obj, const char *name, int64_t val, int search_flags); +int av_opt_set_double (void *obj, const char *name, double val, int search_flags); +int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags); +int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, int search_flags); +int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags); +int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags); +int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags); +int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags); +/** + * @note Any old chlayout present is discarded and replaced with a copy of the new one. The + * caller still owns layout and is responsible for uninitializing it. + */ +int av_opt_set_chlayout(void *obj, const char *name, const AVChannelLayout *layout, int search_flags); +/** + * @note Any old dictionary present is discarded and replaced with a copy of the new one. The + * caller still owns val is and responsible for freeing it. + */ +int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags); + +#if FF_API_OPT_INT_LIST +/** + * Set a binary option to an integer list. + * + * @param obj AVClass object to set options on + * @param name name of the binary option + * @param val pointer to an integer list (must have the correct type with + * regard to the contents of the list) + * @param term list terminator (usually 0 or -1) + * @param flags search flags + */ +#define av_opt_set_int_list(obj, name, val, term, flags) \ + (av_int_list_length(val, term) > INT_MAX / sizeof(*(val)) ? \ + AVERROR(EINVAL) : \ + av_opt_set_bin(obj, name, (const uint8_t *)(val), \ + av_int_list_length(val, term) * sizeof(*(val)), flags)) +#endif + +/** + * Add, replace, or remove elements for an array option. Which of these + * operations is performed depends on the values of val and search_flags. + * + * @param start_elem Index of the first array element to modify; must not be + * larger than array size as returned by + * av_opt_get_array_size(). + * @param nb_elems number of array elements to modify; when val is NULL, + * start_elem+nb_elems must not be larger than array size as + * returned by av_opt_get_array_size() + * + * @param val_type Option type corresponding to the type of val, ignored when val is + * NULL. + * + * The effect of this function will will be as if av_opt_setX() + * was called for each element, where X is specified by type. + * E.g. AV_OPT_TYPE_STRING corresponds to av_opt_set(). + * + * Typically this should be the same as the scalarized type of + * the AVOption being set, but certain conversions are also + * possible - the same as those done by the corresponding + * av_opt_set*() function. E.g. any option type can be set from + * a string, numeric types can be set from int64, double, or + * rational, etc. + * + * @param val Array with nb_elems elements or NULL. + * + * When NULL, nb_elems array elements starting at start_elem are + * removed from the array. Any array elements remaining at the end + * are shifted by nb_elems towards the first element in order to keep + * the array contiguous. + * + * Otherwise (val is non-NULL), the type of val must match the + * underlying C type as documented for val_type. + * + * When AV_OPT_ARRAY_REPLACE is not set in search_flags, the array is + * enlarged by nb_elems, and the contents of val are inserted at + * start_elem. Previously existing array elements from start_elem + * onwards (if present) are shifted by nb_elems away from the first + * element in order to make space for the new elements. + * + * When AV_OPT_ARRAY_REPLACE is set in search_flags, the contents + * of val replace existing array elements from start_elem to + * start_elem+nb_elems (if present). New array size is + * max(start_elem + nb_elems, old array size). + */ +int av_opt_set_array(void *obj, const char *name, int search_flags, + unsigned int start_elem, unsigned int nb_elems, + enum AVOptionType val_type, const void *val); + +/** + * @} + * @} + */ + +/** + * @defgroup opt_read Reading option values + * @{ + */ + +/** + * @defgroup opt_get_funcs Option getting functions + * @{ + * Those functions get a value of the option with the given name from an object. + * + * @param[in] obj a struct whose first element is a pointer to an AVClass. + * @param[in] name name of the option to get. + * @param[in] search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be found in a child of obj. + * @param[out] out_val value of the option will be written here + * @return >=0 on success, a negative error code otherwise + */ +/** + * @note the returned string will be av_malloc()ed and must be av_free()ed by the caller + * + * @note if AV_OPT_ALLOW_NULL is set in search_flags in av_opt_get, and the + * option is of type AV_OPT_TYPE_STRING, AV_OPT_TYPE_BINARY or AV_OPT_TYPE_DICT + * and is set to NULL, *out_val will be set to NULL instead of an allocated + * empty string. + */ +int av_opt_get (void *obj, const char *name, int search_flags, uint8_t **out_val); +int av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val); +int av_opt_get_double (void *obj, const char *name, int search_flags, double *out_val); +int av_opt_get_q (void *obj, const char *name, int search_flags, AVRational *out_val); +int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out); +int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt); +int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt); +int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val); +/** + * @param[out] layout The returned layout is a copy of the actual value and must + * be freed with av_channel_layout_uninit() by the caller + */ +int av_opt_get_chlayout(void *obj, const char *name, int search_flags, AVChannelLayout *layout); +/** + * @param[out] out_val The returned dictionary is a copy of the actual value and must + * be freed with av_dict_free() by the caller + */ +int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val); + +/** + * For an array-type option, get the number of elements in the array. + */ +int av_opt_get_array_size(void *obj, const char *name, int search_flags, + unsigned int *out_val); + +/** + * For an array-type option, retrieve the values of one or more array elements. + * + * @param start_elem index of the first array element to retrieve + * @param nb_elems number of array elements to retrieve; start_elem+nb_elems + * must not be larger than array size as returned by + * av_opt_get_array_size() + * + * @param out_type Option type corresponding to the desired output. + * + * The array elements produced by this function will + * will be as if av_opt_getX() was called for each element, + * where X is specified by out_type. E.g. AV_OPT_TYPE_STRING + * corresponds to av_opt_get(). + * + * Typically this should be the same as the scalarized type of + * the AVOption being retrieved, but certain conversions are + * also possible - the same as those done by the corresponding + * av_opt_get*() function. E.g. any option type can be retrieved + * as a string, numeric types can be retrieved as int64, double, + * or rational, etc. + * + * @param out_val Array with nb_elems members into which the output will be + * written. The array type must match the underlying C type as + * documented for out_type, and be zeroed on entry to this + * function. + * + * For dynamically allocated types (strings, binary, dicts, + * etc.), the result is owned and freed by the caller. + */ +int av_opt_get_array(void *obj, const char *name, int search_flags, + unsigned int start_elem, unsigned int nb_elems, + enum AVOptionType out_type, void *out_val); +/** + * @} + */ + +/** + * @defgroup opt_eval_funcs Evaluating option strings + * @{ + * This group of functions can be used to evaluate option strings + * and get numbers out of them. They do the same thing as av_opt_set(), + * except the result is written into the caller-supplied pointer. + * + * @param obj a struct whose first element is a pointer to AVClass. + * @param o an option for which the string is to be evaluated. + * @param val string to be evaluated. + * @param *_out value of the string will be written here. + * + * @return 0 on success, a negative number on failure. + */ +int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out); +int av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out); +int av_opt_eval_uint (void *obj, const AVOption *o, const char *val, unsigned *uint_out); +int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out); +int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out); +int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double *double_out); +int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out); +/** + * @} + */ + +#if FF_API_OPT_PTR +/** + * Gets a pointer to the requested field in a struct. + * This function allows accessing a struct even when its fields are moved or + * renamed since the application making the access has been compiled, + * + * @returns a pointer to the field, it can be cast to the correct type and read + * or written to. + * + * @deprecated direct access to AVOption-exported fields is not supported + */ +attribute_deprecated +void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name); +#endif + +/** + * Check if given option is set to its default value. + * + * Options o must belong to the obj. This function must not be called to check child's options state. + * @see av_opt_is_set_to_default_by_name(). + * + * @param obj AVClass object to check option on + * @param o option to be checked + * @return >0 when option is set to its default, + * 0 when option is not set its default, + * <0 on error + */ +int av_opt_is_set_to_default(void *obj, const AVOption *o); + +/** + * Check if given option is set to its default value. + * + * @param obj AVClass object to check option on + * @param name option name + * @param search_flags combination of AV_OPT_SEARCH_* + * @return >0 when option is set to its default, + * 0 when option is not set its default, + * <0 on error + */ +int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags); + +/** + * Check whether a particular flag is set in a flags field. + * + * @param field_name the name of the flag field option + * @param flag_name the name of the flag to check + * @return non-zero if the flag is set, zero if the flag isn't set, + * isn't of the right type, or the flags field doesn't exist. + */ +int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name); + +#define AV_OPT_SERIALIZE_SKIP_DEFAULTS 0x00000001 ///< Serialize options that are not set to default values only. +#define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT 0x00000002 ///< Serialize options that exactly match opt_flags only. +#define AV_OPT_SERIALIZE_SEARCH_CHILDREN 0x00000004 ///< Serialize options in possible children of the given object. + +/** + * Serialize object's options. + * + * Create a string containing object's serialized options. + * Such string may be passed back to av_opt_set_from_string() in order to restore option values. + * A key/value or pairs separator occurring in the serialized value or + * name string are escaped through the av_escape() function. + * + * @param[in] obj AVClass object to serialize + * @param[in] opt_flags serialize options with all the specified flags set (AV_OPT_FLAG) + * @param[in] flags combination of AV_OPT_SERIALIZE_* flags + * @param[out] buffer Pointer to buffer that will be allocated with string containing serialized options. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep character used to separate key from value + * @param[in] pairs_sep character used to separate two pairs from each other + * @return >= 0 on success, negative on error + * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same. + */ +int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, + const char key_val_sep, const char pairs_sep); + +/** + * @} + */ + +/** + * Free an AVOptionRanges struct and set it to NULL. + */ +void av_opt_freep_ranges(AVOptionRanges **ranges); + +/** + * Get a list of allowed ranges for the given option. + * + * The returned list may depend on other fields in obj like for example profile. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_freep_ranges. + * + * @return number of components returned on success, a negative error code otherwise + */ +int av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * Get a default list of allowed ranges for the given option. + * + * This list is constructed without using the AVClass.query_ranges() callback + * and can be used as fallback from within the callback. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_free_ranges. + * + * @return number of components returned on success, a negative error code otherwise + */ +int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * @} + */ + +#endif /* AVUTIL_OPT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/pixdesc.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/pixdesc.h new file mode 100644 index 0000000000000..ba2f6328141b3 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/pixdesc.h @@ -0,0 +1,440 @@ +/* + * pixel format descriptor + * Copyright (c) 2009 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXDESC_H +#define AVUTIL_PIXDESC_H + +#include + +#include "attributes.h" +#include "pixfmt.h" + +typedef struct AVComponentDescriptor { + /** + * Which of the 4 planes contains the component. + */ + int plane; + + /** + * Number of elements between 2 horizontally consecutive pixels. + * Elements are bits for bitstream formats, bytes otherwise. + */ + int step; + + /** + * Number of elements before the component of the first pixel. + * Elements are bits for bitstream formats, bytes otherwise. + */ + int offset; + + /** + * Number of least significant bits that must be shifted away + * to get the value. + */ + int shift; + + /** + * Number of bits in the component. + */ + int depth; +} AVComponentDescriptor; + +/** + * Descriptor that unambiguously describes how the bits of a pixel are + * stored in the up to 4 data planes of an image. It also stores the + * subsampling factors and number of components. + * + * @note This is separate of the colorspace (RGB, YCbCr, YPbPr, JPEG-style YUV + * and all the YUV variants) AVPixFmtDescriptor just stores how values + * are stored not what these values represent. + */ +typedef struct AVPixFmtDescriptor { + const char *name; + uint8_t nb_components; ///< The number of components each pixel has, (1-4) + + /** + * Amount to shift the luma width right to find the chroma width. + * For YV12 this is 1 for example. + * chroma_width = AV_CEIL_RSHIFT(luma_width, log2_chroma_w) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_w; + + /** + * Amount to shift the luma height right to find the chroma height. + * For YV12 this is 1 for example. + * chroma_height= AV_CEIL_RSHIFT(luma_height, log2_chroma_h) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_h; + + /** + * Combination of AV_PIX_FMT_FLAG_... flags. + */ + uint64_t flags; + + /** + * Parameters that describe how pixels are packed. + * If the format has 1 or 2 components, then luma is 0. + * If the format has 3 or 4 components: + * if the RGB flag is set then 0 is red, 1 is green and 2 is blue; + * otherwise 0 is luma, 1 is chroma-U and 2 is chroma-V. + * + * If present, the Alpha channel is always the last component. + */ + AVComponentDescriptor comp[4]; + + /** + * Alternative comma-separated names. + */ + const char *alias; +} AVPixFmtDescriptor; + +/** + * Pixel format is big-endian. + */ +#define AV_PIX_FMT_FLAG_BE (1 << 0) +/** + * Pixel format has a palette in data[1], values are indexes in this palette. + */ +#define AV_PIX_FMT_FLAG_PAL (1 << 1) +/** + * All values of a component are bit-wise packed end to end. + */ +#define AV_PIX_FMT_FLAG_BITSTREAM (1 << 2) +/** + * Pixel format is an HW accelerated format. + */ +#define AV_PIX_FMT_FLAG_HWACCEL (1 << 3) +/** + * At least one pixel component is not in the first data plane. + */ +#define AV_PIX_FMT_FLAG_PLANAR (1 << 4) +/** + * The pixel format contains RGB-like data (as opposed to YUV/grayscale). + */ +#define AV_PIX_FMT_FLAG_RGB (1 << 5) + +/** + * The pixel format has an alpha channel. This is set on all formats that + * support alpha in some way, including AV_PIX_FMT_PAL8. The alpha is always + * straight, never pre-multiplied. + * + * If a codec or a filter does not support alpha, it should set all alpha to + * opaque, or use the equivalent pixel formats without alpha component, e.g. + * AV_PIX_FMT_RGB0 (or AV_PIX_FMT_RGB24 etc.) instead of AV_PIX_FMT_RGBA. + */ +#define AV_PIX_FMT_FLAG_ALPHA (1 << 7) + +/** + * The pixel format is following a Bayer pattern + */ +#define AV_PIX_FMT_FLAG_BAYER (1 << 8) + +/** + * The pixel format contains IEEE-754 floating point values. Precision (double, + * single, or half) should be determined by the pixel size (64, 32, or 16 bits). + */ +#define AV_PIX_FMT_FLAG_FLOAT (1 << 9) + +/** + * The pixel format contains XYZ-like data (as opposed to YUV/RGB/grayscale). + */ +#define AV_PIX_FMT_FLAG_XYZ (1 << 10) + +/** + * Return the number of bits per pixel used by the pixel format + * described by pixdesc. Note that this is not the same as the number + * of bits per sample. + * + * The returned number of bits refers to the number of bits actually + * used for storing the pixel information, that is padding bits are + * not counted. + */ +int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * Return the number of bits per pixel for the pixel format + * described by pixdesc, including any padding or unused bits. + */ +int av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * @return a pixel format descriptor for provided pixel format or NULL if + * this pixel format is unknown. + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt); + +/** + * Iterate over all pixel format descriptors known to libavutil. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_next(const AVPixFmtDescriptor *prev); + +/** + * @return an AVPixelFormat id described by desc, or AV_PIX_FMT_NONE if desc + * is not a valid pointer to a pixel format descriptor. + */ +enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); + +/** + * Utility function to access log2_chroma_w log2_chroma_h from + * the pixel format AVPixFmtDescriptor. + * + * @param[in] pix_fmt the pixel format + * @param[out] h_shift store log2_chroma_w (horizontal/width shift) + * @param[out] v_shift store log2_chroma_h (vertical/height shift) + * + * @return 0 on success, AVERROR(ENOSYS) on invalid or unknown pixel format + */ +int av_pix_fmt_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, + int *h_shift, int *v_shift); + +/** + * @return number of planes in pix_fmt, a negative AVERROR if pix_fmt is not a + * valid pixel format. + */ +int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt); + +/** + * @return the name for provided color range or NULL if unknown. + */ +const char *av_color_range_name(enum AVColorRange range); + +/** + * @return the AVColorRange value for name or an AVError if not found. + */ +int av_color_range_from_name(const char *name); + +/** + * @return the name for provided color primaries or NULL if unknown. + */ +const char *av_color_primaries_name(enum AVColorPrimaries primaries); + +/** + * @return the AVColorPrimaries value for name or an AVError if not found. + */ +int av_color_primaries_from_name(const char *name); + +/** + * @return the name for provided color transfer or NULL if unknown. + */ +const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer); + +/** + * @return the AVColorTransferCharacteristic value for name or an AVError if not found. + */ +int av_color_transfer_from_name(const char *name); + +/** + * @return the name for provided color space or NULL if unknown. + */ +const char *av_color_space_name(enum AVColorSpace space); + +/** + * @return the AVColorSpace value for name or an AVError if not found. + */ +int av_color_space_from_name(const char *name); + +/** + * @return the name for provided chroma location or NULL if unknown. + */ +const char *av_chroma_location_name(enum AVChromaLocation location); + +/** + * @return the AVChromaLocation value for name or an AVError if not found. + */ +int av_chroma_location_from_name(const char *name); + +/** + * Converts AVChromaLocation to swscale x/y chroma position. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + */ +int av_chroma_location_enum_to_pos(int *xpos, int *ypos, enum AVChromaLocation pos); + +/** + * Converts swscale x/y chroma position to AVChromaLocation. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + */ +enum AVChromaLocation av_chroma_location_pos_to_enum(int xpos, int ypos); + +/** + * Return the pixel format corresponding to name. + * + * If there is no pixel format with name name, then looks for a + * pixel format with the name corresponding to the native endian + * format of name. + * For example in a little-endian system, first looks for "gray16", + * then for "gray16le". + * + * Finally if no pixel format has been found, returns AV_PIX_FMT_NONE. + */ +enum AVPixelFormat av_get_pix_fmt(const char *name); + +/** + * Return the short name for a pixel format, NULL in case pix_fmt is + * unknown. + * + * @see av_get_pix_fmt(), av_get_pix_fmt_string() + */ +const char *av_get_pix_fmt_name(enum AVPixelFormat pix_fmt); + +/** + * Print in buf the string corresponding to the pixel format with + * number pix_fmt, or a header if pix_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param pix_fmt the number of the pixel format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + */ +char *av_get_pix_fmt_string(char *buf, int buf_size, + enum AVPixelFormat pix_fmt); + +/** + * Read a line from an image, and write the values of the + * pixel format component c to dst. + * + * @param data the array containing the pointers to the planes of the image + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to read + * @param y the vertical coordinate of the first pixel to read + * @param w the width of the line to read, that is the number of + * values to write to dst + * @param read_pal_component if not zero and the format is a paletted + * format writes the values corresponding to the palette + * component c in data[1] to dst, rather than the palette indexes in + * data[0]. The behavior is undefined if the format is not paletted. + * @param dst_element_size size of elements in dst array (2 or 4 byte) + */ +void av_read_image_line2(void *dst, const uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int read_pal_component, + int dst_element_size); + +void av_read_image_line(uint16_t *dst, const uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int read_pal_component); + +/** + * Write the values from src to the pixel format component c of an + * image line. + * + * @param src array containing the values to write + * @param data the array containing the pointers to the planes of the + * image to write into. It is supposed to be zeroed. + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to write + * @param y the vertical coordinate of the first pixel to write + * @param w the width of the line to write, that is the number of + * values to write to the image line + * @param src_element_size size of elements in src array (2 or 4 byte) + */ +void av_write_image_line2(const void *src, uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int src_element_size); + +void av_write_image_line(const uint16_t *src, uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w); + +/** + * Utility function to swap the endianness of a pixel format. + * + * @param[in] pix_fmt the pixel format + * + * @return pixel format with swapped endianness if it exists, + * otherwise AV_PIX_FMT_NONE + */ +enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt); + +#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ +#define FF_LOSS_EXCESS_RESOLUTION 0x0040 /**< loss due to unneeded extra resolution */ +#define FF_LOSS_EXCESS_DEPTH 0x0080 /**< loss due to unneeded extra color depth */ + + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + int has_alpha); + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); + +#endif /* AVUTIL_PIXDESC_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/pixfmt.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/pixfmt.h new file mode 100644 index 0000000000000..823ea8edabe2b --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/pixfmt.h @@ -0,0 +1,797 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXFMT_H +#define AVUTIL_PIXFMT_H + +/** + * @file + * pixel format definitions + */ + +#include "libavutil/avconfig.h" +#include "version.h" + +#define AVPALETTE_SIZE 1024 +#define AVPALETTE_COUNT 256 + +/** + * Maximum number of planes in any pixel format. + * This should be used when a maximum is needed, but code should not + * be written to require a maximum for no good reason. + */ +#define AV_VIDEO_MAX_PLANES 4 + +/** + * Pixel format. + * + * @note + * AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA + * color is put together as: + * (A << 24) | (R << 16) | (G << 8) | B + * This is stored as BGRA on little-endian CPU architectures and ARGB on + * big-endian CPUs. + * + * @note + * If the resolution is not a multiple of the chroma subsampling factor + * then the chroma plane resolution must be rounded up. + * + * @par + * When the pixel format is palettized RGB32 (AV_PIX_FMT_PAL8), the palettized + * image data is stored in AVFrame.data[0]. The palette is transported in + * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is + * formatted the same as in AV_PIX_FMT_RGB32 described above (i.e., it is + * also endian-specific). Note also that the individual RGB32 palette + * components stored in AVFrame.data[1] should be in the range 0..255. + * This is important as many custom PAL8 video codecs that were designed + * to run on the IBM VGA graphics adapter use 6-bit palette components. + * + * @par + * For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like + * for pal8. This palette is filled in automatically by the function + * allocating the picture. + */ +enum AVPixelFormat { + AV_PIX_FMT_NONE = -1, + AV_PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) + AV_PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr + AV_PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB... + AV_PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR... + AV_PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) + AV_PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples) + AV_PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) + AV_PIX_FMT_GRAY8, ///< Y , 8bpp + AV_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_PAL8, ///< 8 bits with AV_PIX_FMT_RGB32 palette + AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range + AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range + AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range + AV_PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 + AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 + AV_PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) + AV_PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb) + AV_PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)3R 3G 2B(lsb) + AV_PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) + AV_PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV21, ///< as above, but U and V bytes are swapped + + AV_PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... + AV_PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA... + AV_PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR... + AV_PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA... + + AV_PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian + AV_PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian + AV_PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) + AV_PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range + AV_PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) + AV_PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian + + AV_PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian + AV_PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian + AV_PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined + + AV_PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian + AV_PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian + AV_PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined + + /** + * Hardware acceleration through VA-API, data[3] contains a + * VASurfaceID. + */ + AV_PIX_FMT_VAAPI, + + AV_PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer + + AV_PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_YA8, ///< 8 bits gray, 8 bits alpha + + AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + AV_PIX_FMT_GRAY8A= AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + + AV_PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian + + /** + * The following 12 formats have the disadvantage of needing 1 format for each bit depth. + * Notice that each 9/10 bits sample is stored in 16 bits with extra padding. + * If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better. + */ + AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp + AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP + AV_PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big-endian + AV_PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little-endian + AV_PIX_FMT_GBRP10BE, ///< planar GBR 4:4:4 30bpp, big-endian + AV_PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little-endian + AV_PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little-endian + AV_PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + AV_PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + AV_PIX_FMT_YUVA420P9BE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian + AV_PIX_FMT_YUVA420P9LE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian + AV_PIX_FMT_YUVA422P9BE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA422P9LE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA444P9BE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA444P9LE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA420P10BE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P10LE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P10BE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P10LE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P10BE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P10LE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA420P16BE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P16LE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P16BE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P16LE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P16BE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P16LE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + + AV_PIX_FMT_VDPAU, ///< HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface + + AV_PIX_FMT_XYZ12LE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_XYZ12BE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_NV16, ///< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_NV20LE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_NV20BE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + + AV_PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + + AV_PIX_FMT_YVYU422, ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb + + AV_PIX_FMT_YA16BE, ///< 16 bits gray, 16 bits alpha (big-endian) + AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian) + + AV_PIX_FMT_GBRAP, ///< planar GBRA 4:4:4:4 32bpp + AV_PIX_FMT_GBRAP16BE, ///< planar GBRA 4:4:4:4 64bpp, big-endian + AV_PIX_FMT_GBRAP16LE, ///< planar GBRA 4:4:4:4 64bpp, little-endian + /** + * HW acceleration through QSV, data[3] contains a pointer to the + * mfxFrameSurface1 structure. + * + * Before FFmpeg 5.0: + * mfxFrameSurface1.Data.MemId contains a pointer when importing + * the following frames as QSV frames: + * + * VAAPI: + * mfxFrameSurface1.Data.MemId contains a pointer to VASurfaceID + * + * DXVA2: + * mfxFrameSurface1.Data.MemId contains a pointer to IDirect3DSurface9 + * + * FFmpeg 5.0 and above: + * mfxFrameSurface1.Data.MemId contains a pointer to the mfxHDLPair + * structure when importing the following frames as QSV frames: + * + * VAAPI: + * mfxHDLPair.first contains a VASurfaceID pointer. + * mfxHDLPair.second is always MFX_INFINITE. + * + * DXVA2: + * mfxHDLPair.first contains IDirect3DSurface9 pointer. + * mfxHDLPair.second is always MFX_INFINITE. + * + * D3D11: + * mfxHDLPair.first contains a ID3D11Texture2D pointer. + * mfxHDLPair.second contains the texture array index of the frame if the + * ID3D11Texture2D is an array texture, or always MFX_INFINITE if it is a + * normal texture. + */ + AV_PIX_FMT_QSV, + /** + * HW acceleration though MMAL, data[3] contains a pointer to the + * MMAL_BUFFER_HEADER_T structure. + */ + AV_PIX_FMT_MMAL, + + AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer + + /** + * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers + * exactly as for system memory frames. + */ + AV_PIX_FMT_CUDA, + + AV_PIX_FMT_0RGB, ///< packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined + AV_PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined + AV_PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined + AV_PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined + + AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_GBRP12BE, ///< planar GBR 4:4:4 36bpp, big-endian + AV_PIX_FMT_GBRP12LE, ///< planar GBR 4:4:4 36bpp, little-endian + AV_PIX_FMT_GBRP14BE, ///< planar GBR 4:4:4 42bpp, big-endian + AV_PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little-endian + AV_PIX_FMT_YUVJ411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV411P and setting color_range + + AV_PIX_FMT_BAYER_BGGR8, ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples + AV_PIX_FMT_BAYER_RGGB8, ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples + AV_PIX_FMT_BAYER_GBRG8, ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples + AV_PIX_FMT_BAYER_GRBG8, ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples + AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian + + AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_YUV440P12LE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P12BE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_AYUV64LE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_AYUV64BE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + + AV_PIX_FMT_VIDEOTOOLBOX, ///< hardware decoding through Videotoolbox + + AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian + AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian + + AV_PIX_FMT_GBRAP12BE, ///< planar GBR 4:4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRAP12LE, ///< planar GBR 4:4:4:4 48bpp, little-endian + + AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian + AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian + + AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec + + AV_PIX_FMT_GRAY12BE, ///< Y , 12bpp, big-endian + AV_PIX_FMT_GRAY12LE, ///< Y , 12bpp, little-endian + AV_PIX_FMT_GRAY10BE, ///< Y , 10bpp, big-endian + AV_PIX_FMT_GRAY10LE, ///< Y , 10bpp, little-endian + + AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian + AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian + + /** + * Hardware surfaces for Direct3D11. + * + * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11 + * hwaccel API and filtering support AV_PIX_FMT_D3D11 only. + * + * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the + * texture array index of the frame as intptr_t if the ID3D11Texture2D is + * an array texture (or always 0 if it's a normal texture). + */ + AV_PIX_FMT_D3D11, + + AV_PIX_FMT_GRAY9BE, ///< Y , 9bpp, big-endian + AV_PIX_FMT_GRAY9LE, ///< Y , 9bpp, little-endian + + AV_PIX_FMT_GBRPF32BE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, big-endian + AV_PIX_FMT_GBRPF32LE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, little-endian + AV_PIX_FMT_GBRAPF32BE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian + AV_PIX_FMT_GBRAPF32LE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian + + /** + * DRM-managed buffers exposed through PRIME buffer sharing. + * + * data[0] points to an AVDRMFrameDescriptor. + */ + AV_PIX_FMT_DRM_PRIME, + /** + * Hardware surfaces for OpenCL. + * + * data[i] contain 2D image objects (typed in C as cl_mem, used + * in OpenCL as image2d_t) for each plane of the surface. + */ + AV_PIX_FMT_OPENCL, + + AV_PIX_FMT_GRAY14BE, ///< Y , 14bpp, big-endian + AV_PIX_FMT_GRAY14LE, ///< Y , 14bpp, little-endian + + AV_PIX_FMT_GRAYF32BE, ///< IEEE-754 single precision Y, 32bpp, big-endian + AV_PIX_FMT_GRAYF32LE, ///< IEEE-754 single precision Y, 32bpp, little-endian + + AV_PIX_FMT_YUVA422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, little-endian + AV_PIX_FMT_YUVA444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, little-endian + + AV_PIX_FMT_NV24, ///< planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV42, ///< as above, but U and V bytes are swapped + + /** + * Vulkan hardware images. + * + * data[0] points to an AVVkFrame + */ + AV_PIX_FMT_VULKAN, + + AV_PIX_FMT_Y210BE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_Y210LE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, little-endian + + AV_PIX_FMT_X2RGB10LE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_X2RGB10BE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_X2BGR10LE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_X2BGR10BE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), big-endian, X=unused/undefined + + AV_PIX_FMT_P210BE, ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_P210LE, ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, little-endian + + AV_PIX_FMT_P410BE, ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, big-endian + AV_PIX_FMT_P410LE, ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, little-endian + + AV_PIX_FMT_P216BE, ///< interleaved chroma YUV 4:2:2, 32bpp, big-endian + AV_PIX_FMT_P216LE, ///< interleaved chroma YUV 4:2:2, 32bpp, little-endian + + AV_PIX_FMT_P416BE, ///< interleaved chroma YUV 4:4:4, 48bpp, big-endian + AV_PIX_FMT_P416LE, ///< interleaved chroma YUV 4:4:4, 48bpp, little-endian + + AV_PIX_FMT_VUYA, ///< packed VUYA 4:4:4:4, 32bpp (1 Cr & Cb sample per 1x1 Y & A samples), VUYAVUYA... + + AV_PIX_FMT_RGBAF16BE, ///< IEEE-754 half precision packed RGBA 16:16:16:16, 64bpp, RGBARGBA..., big-endian + AV_PIX_FMT_RGBAF16LE, ///< IEEE-754 half precision packed RGBA 16:16:16:16, 64bpp, RGBARGBA..., little-endian + + AV_PIX_FMT_VUYX, ///< packed VUYX 4:4:4:4, 32bpp, Variant of VUYA where alpha channel is left undefined + + AV_PIX_FMT_P012LE, ///< like NV12, with 12bpp per component, data in the high bits, zeros in the low bits, little-endian + AV_PIX_FMT_P012BE, ///< like NV12, with 12bpp per component, data in the high bits, zeros in the low bits, big-endian + + AV_PIX_FMT_Y212BE, ///< packed YUV 4:2:2 like YUYV422, 24bpp, data in the high bits, zeros in the low bits, big-endian + AV_PIX_FMT_Y212LE, ///< packed YUV 4:2:2 like YUYV422, 24bpp, data in the high bits, zeros in the low bits, little-endian + + AV_PIX_FMT_XV30BE, ///< packed XVYU 4:4:4, 32bpp, (msb)2X 10V 10Y 10U(lsb), big-endian, variant of Y410 where alpha channel is left undefined + AV_PIX_FMT_XV30LE, ///< packed XVYU 4:4:4, 32bpp, (msb)2X 10V 10Y 10U(lsb), little-endian, variant of Y410 where alpha channel is left undefined + + AV_PIX_FMT_XV36BE, ///< packed XVYU 4:4:4, 48bpp, data in the high bits, zeros in the low bits, big-endian, variant of Y412 where alpha channel is left undefined + AV_PIX_FMT_XV36LE, ///< packed XVYU 4:4:4, 48bpp, data in the high bits, zeros in the low bits, little-endian, variant of Y412 where alpha channel is left undefined + + AV_PIX_FMT_RGBF32BE, ///< IEEE-754 single precision packed RGB 32:32:32, 96bpp, RGBRGB..., big-endian + AV_PIX_FMT_RGBF32LE, ///< IEEE-754 single precision packed RGB 32:32:32, 96bpp, RGBRGB..., little-endian + + AV_PIX_FMT_RGBAF32BE, ///< IEEE-754 single precision packed RGBA 32:32:32:32, 128bpp, RGBARGBA..., big-endian + AV_PIX_FMT_RGBAF32LE, ///< IEEE-754 single precision packed RGBA 32:32:32:32, 128bpp, RGBARGBA..., little-endian + + AV_PIX_FMT_P212BE, ///< interleaved chroma YUV 4:2:2, 24bpp, data in the high bits, big-endian + AV_PIX_FMT_P212LE, ///< interleaved chroma YUV 4:2:2, 24bpp, data in the high bits, little-endian + + AV_PIX_FMT_P412BE, ///< interleaved chroma YUV 4:4:4, 36bpp, data in the high bits, big-endian + AV_PIX_FMT_P412LE, ///< interleaved chroma YUV 4:4:4, 36bpp, data in the high bits, little-endian + + AV_PIX_FMT_GBRAP14BE, ///< planar GBR 4:4:4:4 56bpp, big-endian + AV_PIX_FMT_GBRAP14LE, ///< planar GBR 4:4:4:4 56bpp, little-endian + + /** + * Hardware surfaces for Direct3D 12. + * + * data[0] points to an AVD3D12VAFrame + */ + AV_PIX_FMT_D3D12, + + AV_PIX_FMT_AYUV, ///< packed AYUV 4:4:4:4, 32bpp (1 Cr & Cb sample per 1x1 Y & A samples), AYUVAYUV... + + AV_PIX_FMT_UYVA, ///< packed UYVA 4:4:4:4, 32bpp (1 Cr & Cb sample per 1x1 Y & A samples), UYVAUYVA... + + AV_PIX_FMT_VYU444, ///< packed VYU 4:4:4, 24bpp (1 Cr & Cb sample per 1x1 Y), VYUVYU... + + AV_PIX_FMT_V30XBE, ///< packed VYUX 4:4:4 like XV30, 32bpp, (msb)10V 10Y 10U 2X(lsb), big-endian + AV_PIX_FMT_V30XLE, ///< packed VYUX 4:4:4 like XV30, 32bpp, (msb)10V 10Y 10U 2X(lsb), little-endian + + AV_PIX_FMT_RGBF16BE, ///< IEEE-754 half precision packed RGB 16:16:16, 48bpp, RGBRGB..., big-endian + AV_PIX_FMT_RGBF16LE, ///< IEEE-754 half precision packed RGB 16:16:16, 48bpp, RGBRGB..., little-endian + + AV_PIX_FMT_RGBA128BE, ///< packed RGBA 32:32:32:32, 128bpp, RGBARGBA..., big-endian + AV_PIX_FMT_RGBA128LE, ///< packed RGBA 32:32:32:32, 128bpp, RGBARGBA..., little-endian + + AV_PIX_FMT_RGB96BE, ///< packed RGBA 32:32:32, 96bpp, RGBRGB..., big-endian + AV_PIX_FMT_RGB96LE, ///< packed RGBA 32:32:32, 96bpp, RGBRGB..., little-endian + + AV_PIX_FMT_Y216BE, ///< packed YUV 4:2:2 like YUYV422, 32bpp, big-endian + AV_PIX_FMT_Y216LE, ///< packed YUV 4:2:2 like YUYV422, 32bpp, little-endian + + AV_PIX_FMT_XV48BE, ///< packed XVYU 4:4:4, 64bpp, big-endian, variant of Y416 where alpha channel is left undefined + AV_PIX_FMT_XV48LE, ///< packed XVYU 4:4:4, 64bpp, little-endian, variant of Y416 where alpha channel is left undefined + + AV_PIX_FMT_GBRPF16BE, ///< IEEE-754 half precision planer GBR 4:4:4, 48bpp, big-endian + AV_PIX_FMT_GBRPF16LE, ///< IEEE-754 half precision planer GBR 4:4:4, 48bpp, little-endian + AV_PIX_FMT_GBRAPF16BE, ///< IEEE-754 half precision planar GBRA 4:4:4:4, 64bpp, big-endian + AV_PIX_FMT_GBRAPF16LE, ///< IEEE-754 half precision planar GBRA 4:4:4:4, 64bpp, little-endian + + AV_PIX_FMT_GRAYF16BE, ///< IEEE-754 half precision Y, 16bpp, big-endian + AV_PIX_FMT_GRAYF16LE, ///< IEEE-754 half precision Y, 16bpp, little-endian + + /** + * HW acceleration through AMF. data[0] contain AMFSurface pointer + */ + AV_PIX_FMT_AMF_SURFACE, + + AV_PIX_FMT_GRAY32BE, ///< Y , 32bpp, big-endian + AV_PIX_FMT_GRAY32LE, ///< Y , 32bpp, little-endian + + AV_PIX_FMT_YAF32BE, ///< IEEE-754 single precision packed YA, 32 bits gray, 32 bits alpha, 64bpp, big-endian + AV_PIX_FMT_YAF32LE, ///< IEEE-754 single precision packed YA, 32 bits gray, 32 bits alpha, 64bpp, little-endian + + AV_PIX_FMT_YAF16BE, ///< IEEE-754 half precision packed YA, 16 bits gray, 16 bits alpha, 32bpp, big-endian + AV_PIX_FMT_YAF16LE, ///< IEEE-754 half precision packed YA, 16 bits gray, 16 bits alpha, 32bpp, little-endian + + AV_PIX_FMT_GBRAP32BE, ///< planar GBRA 4:4:4:4 128bpp, big-endian + AV_PIX_FMT_GBRAP32LE, ///< planar GBRA 4:4:4:4 128bpp, little-endian + + AV_PIX_FMT_YUV444P10MSBBE, ///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), lowest bits zero, big-endian + AV_PIX_FMT_YUV444P10MSBLE, ///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), lowest bits zero, little-endian + AV_PIX_FMT_YUV444P12MSBBE, ///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), lowest bits zero, big-endian + AV_PIX_FMT_YUV444P12MSBLE, ///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), lowest bits zero, little-endian + AV_PIX_FMT_GBRP10MSBBE, ///< planar GBR 4:4:4 30bpp, lowest bits zero, big-endian + AV_PIX_FMT_GBRP10MSBLE, ///< planar GBR 4:4:4 30bpp, lowest bits zero, little-endian + AV_PIX_FMT_GBRP12MSBBE, ///< planar GBR 4:4:4 36bpp, lowest bits zero, big-endian + AV_PIX_FMT_GBRP12MSBLE, ///< planar GBR 4:4:4 36bpp, lowest bits zero, little-endian + + AV_PIX_FMT_OHCODEC, /// hardware decoding through openharmony + + AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions +}; + +#if AV_HAVE_BIGENDIAN +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##be +#else +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##le +#endif + +#define AV_PIX_FMT_RGB32 AV_PIX_FMT_NE(ARGB, BGRA) +#define AV_PIX_FMT_RGB32_1 AV_PIX_FMT_NE(RGBA, ABGR) +#define AV_PIX_FMT_BGR32 AV_PIX_FMT_NE(ABGR, RGBA) +#define AV_PIX_FMT_BGR32_1 AV_PIX_FMT_NE(BGRA, ARGB) +#define AV_PIX_FMT_0RGB32 AV_PIX_FMT_NE(0RGB, BGR0) +#define AV_PIX_FMT_0BGR32 AV_PIX_FMT_NE(0BGR, RGB0) + +#define AV_PIX_FMT_GRAY9 AV_PIX_FMT_NE(GRAY9BE, GRAY9LE) +#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE) +#define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE) +#define AV_PIX_FMT_GRAY14 AV_PIX_FMT_NE(GRAY14BE, GRAY14LE) +#define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE) +#define AV_PIX_FMT_GRAY32 AV_PIX_FMT_NE(GRAY32BE, GRAY32LE) +#define AV_PIX_FMT_YA16 AV_PIX_FMT_NE(YA16BE, YA16LE) +#define AV_PIX_FMT_RGB48 AV_PIX_FMT_NE(RGB48BE, RGB48LE) +#define AV_PIX_FMT_RGB565 AV_PIX_FMT_NE(RGB565BE, RGB565LE) +#define AV_PIX_FMT_RGB555 AV_PIX_FMT_NE(RGB555BE, RGB555LE) +#define AV_PIX_FMT_RGB444 AV_PIX_FMT_NE(RGB444BE, RGB444LE) +#define AV_PIX_FMT_RGBA64 AV_PIX_FMT_NE(RGBA64BE, RGBA64LE) +#define AV_PIX_FMT_BGR48 AV_PIX_FMT_NE(BGR48BE, BGR48LE) +#define AV_PIX_FMT_BGR565 AV_PIX_FMT_NE(BGR565BE, BGR565LE) +#define AV_PIX_FMT_BGR555 AV_PIX_FMT_NE(BGR555BE, BGR555LE) +#define AV_PIX_FMT_BGR444 AV_PIX_FMT_NE(BGR444BE, BGR444LE) +#define AV_PIX_FMT_BGRA64 AV_PIX_FMT_NE(BGRA64BE, BGRA64LE) + +#define AV_PIX_FMT_YUV420P9 AV_PIX_FMT_NE(YUV420P9BE , YUV420P9LE) +#define AV_PIX_FMT_YUV422P9 AV_PIX_FMT_NE(YUV422P9BE , YUV422P9LE) +#define AV_PIX_FMT_YUV444P9 AV_PIX_FMT_NE(YUV444P9BE , YUV444P9LE) +#define AV_PIX_FMT_YUV420P10 AV_PIX_FMT_NE(YUV420P10BE, YUV420P10LE) +#define AV_PIX_FMT_YUV422P10 AV_PIX_FMT_NE(YUV422P10BE, YUV422P10LE) +#define AV_PIX_FMT_YUV440P10 AV_PIX_FMT_NE(YUV440P10BE, YUV440P10LE) +#define AV_PIX_FMT_YUV444P10 AV_PIX_FMT_NE(YUV444P10BE, YUV444P10LE) +#define AV_PIX_FMT_YUV420P12 AV_PIX_FMT_NE(YUV420P12BE, YUV420P12LE) +#define AV_PIX_FMT_YUV422P12 AV_PIX_FMT_NE(YUV422P12BE, YUV422P12LE) +#define AV_PIX_FMT_YUV440P12 AV_PIX_FMT_NE(YUV440P12BE, YUV440P12LE) +#define AV_PIX_FMT_YUV444P12 AV_PIX_FMT_NE(YUV444P12BE, YUV444P12LE) +#define AV_PIX_FMT_YUV420P14 AV_PIX_FMT_NE(YUV420P14BE, YUV420P14LE) +#define AV_PIX_FMT_YUV422P14 AV_PIX_FMT_NE(YUV422P14BE, YUV422P14LE) +#define AV_PIX_FMT_YUV444P14 AV_PIX_FMT_NE(YUV444P14BE, YUV444P14LE) +#define AV_PIX_FMT_YUV420P16 AV_PIX_FMT_NE(YUV420P16BE, YUV420P16LE) +#define AV_PIX_FMT_YUV422P16 AV_PIX_FMT_NE(YUV422P16BE, YUV422P16LE) +#define AV_PIX_FMT_YUV444P16 AV_PIX_FMT_NE(YUV444P16BE, YUV444P16LE) + +#define AV_PIX_FMT_YUV444P10MSB AV_PIX_FMT_NE(YUV444P10MSBBE, YUV444P10MSBLE) +#define AV_PIX_FMT_YUV444P12MSB AV_PIX_FMT_NE(YUV444P12MSBBE, YUV444P12MSBLE) + +#define AV_PIX_FMT_GBRP9 AV_PIX_FMT_NE(GBRP9BE , GBRP9LE) +#define AV_PIX_FMT_GBRP10 AV_PIX_FMT_NE(GBRP10BE, GBRP10LE) +#define AV_PIX_FMT_GBRP12 AV_PIX_FMT_NE(GBRP12BE, GBRP12LE) +#define AV_PIX_FMT_GBRP14 AV_PIX_FMT_NE(GBRP14BE, GBRP14LE) +#define AV_PIX_FMT_GBRP16 AV_PIX_FMT_NE(GBRP16BE, GBRP16LE) +#define AV_PIX_FMT_GBRAP10 AV_PIX_FMT_NE(GBRAP10BE, GBRAP10LE) +#define AV_PIX_FMT_GBRAP12 AV_PIX_FMT_NE(GBRAP12BE, GBRAP12LE) +#define AV_PIX_FMT_GBRAP14 AV_PIX_FMT_NE(GBRAP14BE, GBRAP14LE) +#define AV_PIX_FMT_GBRAP16 AV_PIX_FMT_NE(GBRAP16BE, GBRAP16LE) +#define AV_PIX_FMT_GBRAP32 AV_PIX_FMT_NE(GBRAP32BE, GBRAP32LE) + +#define AV_PIX_FMT_GBRP10MSB AV_PIX_FMT_NE(GBRP10MSBBE, GBRP10MSBLE) +#define AV_PIX_FMT_GBRP12MSB AV_PIX_FMT_NE(GBRP12MSBBE, GBRP12MSBLE) + +#define AV_PIX_FMT_BAYER_BGGR16 AV_PIX_FMT_NE(BAYER_BGGR16BE, BAYER_BGGR16LE) +#define AV_PIX_FMT_BAYER_RGGB16 AV_PIX_FMT_NE(BAYER_RGGB16BE, BAYER_RGGB16LE) +#define AV_PIX_FMT_BAYER_GBRG16 AV_PIX_FMT_NE(BAYER_GBRG16BE, BAYER_GBRG16LE) +#define AV_PIX_FMT_BAYER_GRBG16 AV_PIX_FMT_NE(BAYER_GRBG16BE, BAYER_GRBG16LE) + +#define AV_PIX_FMT_GBRPF16 AV_PIX_FMT_NE(GBRPF16BE, GBRPF16LE) +#define AV_PIX_FMT_GBRAPF16 AV_PIX_FMT_NE(GBRAPF16BE, GBRAPF16LE) +#define AV_PIX_FMT_GBRPF32 AV_PIX_FMT_NE(GBRPF32BE, GBRPF32LE) +#define AV_PIX_FMT_GBRAPF32 AV_PIX_FMT_NE(GBRAPF32BE, GBRAPF32LE) + +#define AV_PIX_FMT_GRAYF16 AV_PIX_FMT_NE(GRAYF16BE, GRAYF16LE) +#define AV_PIX_FMT_GRAYF32 AV_PIX_FMT_NE(GRAYF32BE, GRAYF32LE) + +#define AV_PIX_FMT_YAF16 AV_PIX_FMT_NE(YAF16BE, YAF16LE) +#define AV_PIX_FMT_YAF32 AV_PIX_FMT_NE(YAF32BE, YAF32LE) + +#define AV_PIX_FMT_YUVA420P9 AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE) +#define AV_PIX_FMT_YUVA422P9 AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE) +#define AV_PIX_FMT_YUVA444P9 AV_PIX_FMT_NE(YUVA444P9BE , YUVA444P9LE) +#define AV_PIX_FMT_YUVA420P10 AV_PIX_FMT_NE(YUVA420P10BE, YUVA420P10LE) +#define AV_PIX_FMT_YUVA422P10 AV_PIX_FMT_NE(YUVA422P10BE, YUVA422P10LE) +#define AV_PIX_FMT_YUVA444P10 AV_PIX_FMT_NE(YUVA444P10BE, YUVA444P10LE) +#define AV_PIX_FMT_YUVA422P12 AV_PIX_FMT_NE(YUVA422P12BE, YUVA422P12LE) +#define AV_PIX_FMT_YUVA444P12 AV_PIX_FMT_NE(YUVA444P12BE, YUVA444P12LE) +#define AV_PIX_FMT_YUVA420P16 AV_PIX_FMT_NE(YUVA420P16BE, YUVA420P16LE) +#define AV_PIX_FMT_YUVA422P16 AV_PIX_FMT_NE(YUVA422P16BE, YUVA422P16LE) +#define AV_PIX_FMT_YUVA444P16 AV_PIX_FMT_NE(YUVA444P16BE, YUVA444P16LE) + +#define AV_PIX_FMT_XYZ12 AV_PIX_FMT_NE(XYZ12BE, XYZ12LE) +#define AV_PIX_FMT_NV20 AV_PIX_FMT_NE(NV20BE, NV20LE) +#define AV_PIX_FMT_AYUV64 AV_PIX_FMT_NE(AYUV64BE, AYUV64LE) +#define AV_PIX_FMT_P010 AV_PIX_FMT_NE(P010BE, P010LE) +#define AV_PIX_FMT_P012 AV_PIX_FMT_NE(P012BE, P012LE) +#define AV_PIX_FMT_P016 AV_PIX_FMT_NE(P016BE, P016LE) + +#define AV_PIX_FMT_Y210 AV_PIX_FMT_NE(Y210BE, Y210LE) +#define AV_PIX_FMT_Y212 AV_PIX_FMT_NE(Y212BE, Y212LE) +#define AV_PIX_FMT_Y216 AV_PIX_FMT_NE(Y216BE, Y216LE) +#define AV_PIX_FMT_XV30 AV_PIX_FMT_NE(XV30BE, XV30LE) +#define AV_PIX_FMT_XV36 AV_PIX_FMT_NE(XV36BE, XV36LE) +#define AV_PIX_FMT_XV48 AV_PIX_FMT_NE(XV48BE, XV48LE) +#define AV_PIX_FMT_V30X AV_PIX_FMT_NE(V30XBE, V30XLE) +#define AV_PIX_FMT_X2RGB10 AV_PIX_FMT_NE(X2RGB10BE, X2RGB10LE) +#define AV_PIX_FMT_X2BGR10 AV_PIX_FMT_NE(X2BGR10BE, X2BGR10LE) + +#define AV_PIX_FMT_P210 AV_PIX_FMT_NE(P210BE, P210LE) +#define AV_PIX_FMT_P410 AV_PIX_FMT_NE(P410BE, P410LE) +#define AV_PIX_FMT_P212 AV_PIX_FMT_NE(P212BE, P212LE) +#define AV_PIX_FMT_P412 AV_PIX_FMT_NE(P412BE, P412LE) +#define AV_PIX_FMT_P216 AV_PIX_FMT_NE(P216BE, P216LE) +#define AV_PIX_FMT_P416 AV_PIX_FMT_NE(P416BE, P416LE) + +#define AV_PIX_FMT_RGBF16 AV_PIX_FMT_NE(RGBF16BE, RGBF16LE) +#define AV_PIX_FMT_RGBAF16 AV_PIX_FMT_NE(RGBAF16BE, RGBAF16LE) + +#define AV_PIX_FMT_RGBF32 AV_PIX_FMT_NE(RGBF32BE, RGBF32LE) +#define AV_PIX_FMT_RGBAF32 AV_PIX_FMT_NE(RGBAF32BE, RGBAF32LE) + +#define AV_PIX_FMT_RGB96 AV_PIX_FMT_NE(RGB96BE, RGB96LE) +#define AV_PIX_FMT_RGBA128 AV_PIX_FMT_NE(RGBA128BE, RGBA128LE) + +/** + * Chromaticity coordinates of the source primaries. + * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.1 and ITU-T H.273. + */ +enum AVColorPrimaries { + AVCOL_PRI_RESERVED0 = 0, + AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP 177 Annex B + AVCOL_PRI_UNSPECIFIED = 2, + AVCOL_PRI_RESERVED = 3, + AVCOL_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + + AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + AVCOL_PRI_SMPTE240M = 7, ///< identical to above, also called "SMPTE C" even though it uses D65 + AVCOL_PRI_FILM = 8, ///< colour filters using Illuminant C + AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020 + AVCOL_PRI_SMPTE428 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ) + AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428, + AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) / DCI P3 + AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3 + AVCOL_PRI_EBU3213 = 22, ///< EBU Tech. 3213-E (nothing there) / one of JEDEC P22 group phosphors + AVCOL_PRI_JEDEC_P22 = AVCOL_PRI_EBU3213, + AVCOL_PRI_NB ///< Not part of ABI +}; + +/** + * Color Transfer Characteristic. + * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.2. + */ +enum AVColorTransferCharacteristic { + AVCOL_TRC_RESERVED0 = 0, + AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361 + AVCOL_TRC_UNSPECIFIED = 2, + AVCOL_TRC_RESERVED = 3, + AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG + AVCOL_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC + AVCOL_TRC_SMPTE240M = 7, + AVCOL_TRC_LINEAR = 8, ///< "Linear transfer characteristics" + AVCOL_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)" + AVCOL_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" + AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4 + AVCOL_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut + AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC) + AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10-bit system + AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12-bit system + AVCOL_TRC_SMPTE2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084, + AVCOL_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1 + AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428, + AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma" + AVCOL_TRC_NB ///< Not part of ABI +}; + +/** + * YUV colorspace type. + * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.3. + */ +enum AVColorSpace { + AVCOL_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1 + AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B + AVCOL_SPC_UNSPECIFIED = 2, + AVCOL_SPC_RESERVED = 3, ///< reserved for future use by ITU-T and ISO/IEC just like 15-255 are + AVCOL_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 + AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above + AVCOL_SPC_SMPTE240M = 7, ///< derived from 170M primaries and D65 white point, 170M is derived from BT470 System M's primaries + AVCOL_SPC_YCGCO = 8, ///< used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + AVCOL_SPC_YCOCG = AVCOL_SPC_YCGCO, + AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system + AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system + AVCOL_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x + AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system + AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system + AVCOL_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp + AVCOL_SPC_IPT_C2 = 15, ///< SMPTE ST 2128, IPT-C2 + AVCOL_SPC_YCGCO_RE = 16, ///< YCgCo-R, even addition of bits + AVCOL_SPC_YCGCO_RO = 17, ///< YCgCo-R, odd addition of bits + AVCOL_SPC_NB ///< Not part of ABI +}; + +/** + * Visual content value range. + * + * These values are based on definitions that can be found in multiple + * specifications, such as ITU-T BT.709 (3.4 - Quantization of RGB, luminance + * and colour-difference signals), ITU-T BT.2020 (Table 5 - Digital + * Representation) as well as ITU-T BT.2100 (Table 9 - Digital 10- and 12-bit + * integer representation). At the time of writing, the BT.2100 one is + * recommended, as it also defines the full range representation. + * + * Common definitions: + * - For RGB and luma planes such as Y in YCbCr and I in ICtCp, + * 'E' is the original value in range of 0.0 to 1.0. + * - For chroma planes such as Cb,Cr and Ct,Cp, 'E' is the original + * value in range of -0.5 to 0.5. + * - 'n' is the output bit depth. + * - For additional definitions such as rounding and clipping to valid n + * bit unsigned integer range, please refer to BT.2100 (Table 9). + */ +enum AVColorRange { + AVCOL_RANGE_UNSPECIFIED = 0, + + /** + * Narrow or limited range content. + * + * - For luma planes: + * + * (219 * E + 16) * 2^(n-8) + * + * F.ex. the range of 16-235 for 8 bits + * + * - For chroma planes: + * + * (224 * E + 128) * 2^(n-8) + * + * F.ex. the range of 16-240 for 8 bits + */ + AVCOL_RANGE_MPEG = 1, + + /** + * Full range content. + * + * - For RGB and luma planes: + * + * (2^n - 1) * E + * + * F.ex. the range of 0-255 for 8 bits + * + * - For chroma planes: + * + * (2^n - 1) * E + 2^(n - 1) + * + * F.ex. the range of 1-255 for 8 bits + */ + AVCOL_RANGE_JPEG = 2, + AVCOL_RANGE_NB ///< Not part of ABI +}; + +/** + * Location of chroma samples. + * + * Illustration showing the location of the first (top left) chroma sample of the + * image, the left shows only luma, the right + * shows the location of the chroma sample, the 2 could be imagined to overlay + * each other but are drawn separately due to limitations of ASCII + * + * 1st 2nd 1st 2nd horizontal luma sample positions + * v v v v + * ______ ______ + *1st luma line > |X X ... |3 4 X ... X are luma samples, + * | |1 2 1-6 are possible chroma positions + *2nd luma line > |X X ... |5 6 X ... 0 is undefined/unknown position + */ +enum AVChromaLocation { + AVCHROMA_LOC_UNSPECIFIED = 0, + AVCHROMA_LOC_LEFT = 1, ///< MPEG-2/4 4:2:0, H.264 default for 4:2:0 + AVCHROMA_LOC_CENTER = 2, ///< MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0 + AVCHROMA_LOC_TOPLEFT = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2 + AVCHROMA_LOC_TOP = 4, + AVCHROMA_LOC_BOTTOMLEFT = 5, + AVCHROMA_LOC_BOTTOM = 6, + AVCHROMA_LOC_NB ///< Not part of ABI +}; + +#endif /* AVUTIL_PIXFMT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/rational.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/rational.h new file mode 100644 index 0000000000000..30ac2aced76ee --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/rational.h @@ -0,0 +1,225 @@ +/* + * rational numbers + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_math_rational + * Utilities for rational number calculation. + * @author Michael Niedermayer + */ + +#ifndef AVUTIL_RATIONAL_H +#define AVUTIL_RATIONAL_H + +#include +#include +#include "attributes.h" + +/** + * @defgroup lavu_math_rational AVRational + * @ingroup lavu_math + * Rational number calculation. + * + * While rational numbers can be expressed as floating-point numbers, the + * conversion process is a lossy one, so are floating-point operations. On the + * other hand, the nature of FFmpeg demands highly accurate calculation of + * timestamps. This set of rational number utilities serves as a generic + * interface for manipulating rational numbers as pairs of numerators and + * denominators. + * + * Many of the functions that operate on AVRational's have the suffix `_q`, in + * reference to the mathematical symbol "ℚ" (Q) which denotes the set of all + * rational numbers. + * + * @{ + */ + +/** + * Rational number (pair of numerator and denominator). + */ +typedef struct AVRational{ + int num; ///< Numerator + int den; ///< Denominator +} AVRational; + +/** + * Create an AVRational. + * + * Useful for compilers that do not support compound literals. + * + * @note The return value is not reduced. + * @see av_reduce() + */ +static inline AVRational av_make_q(int num, int den) +{ + AVRational r = { num, den }; + return r; +} + +/** + * Compare two rationals. + * + * @param a First rational + * @param b Second rational + * + * @return One of the following values: + * - 0 if `a == b` + * - 1 if `a > b` + * - -1 if `a < b` + * - `INT_MIN` if one of the values is of the form `0 / 0` + */ +static inline int av_cmp_q(AVRational a, AVRational b){ + const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den; + + if(tmp) return (int)((tmp ^ a.den ^ b.den)>>63)|1; + else if(b.den && a.den) return 0; + else if(a.num && b.num) return (a.num>>31) - (b.num>>31); + else return INT_MIN; +} + +/** + * Convert an AVRational to a `double`. + * @param a AVRational to convert + * @return `a` in floating-point form + * @see av_d2q() + */ +static inline double av_q2d(AVRational a){ + return a.num / (double) a.den; +} + +/** + * Reduce a fraction. + * + * This is useful for framerate calculations. + * + * @param[out] dst_num Destination numerator + * @param[out] dst_den Destination denominator + * @param[in] num Source numerator + * @param[in] den Source denominator + * @param[in] max Maximum allowed values for `dst_num` & `dst_den` + * @return 1 if the operation is exact, 0 otherwise + */ +int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max); + +/** + * Multiply two rationals. + * @param b First rational + * @param c Second rational + * @return b*c + */ +AVRational av_mul_q(AVRational b, AVRational c) av_const; + +/** + * Divide one rational by another. + * @param b First rational + * @param c Second rational + * @return b/c + */ +AVRational av_div_q(AVRational b, AVRational c) av_const; + +/** + * Add two rationals. + * @param b First rational + * @param c Second rational + * @return b+c + */ +AVRational av_add_q(AVRational b, AVRational c) av_const; + +/** + * Subtract one rational from another. + * @param b First rational + * @param c Second rational + * @return b-c + */ +AVRational av_sub_q(AVRational b, AVRational c) av_const; + +/** + * Invert a rational. + * @param q value + * @return 1 / q + */ +static av_always_inline AVRational av_inv_q(AVRational q) +{ + AVRational r = { q.den, q.num }; + return r; +} + +/** + * Convert a double precision floating point number to a rational. + * + * In case of infinity, the returned value is expressed as `{1, 0}` or + * `{-1, 0}` depending on the sign. + * + * In general rational numbers with |num| <= 1<<26 && |den| <= 1<<26 + * can be recovered exactly from their double representation. + * (no exceptions were found within 1B random ones) + * + * @param d `double` to convert + * @param max Maximum allowed numerator and denominator + * @return `d` in AVRational form + * @see av_q2d() + */ +AVRational av_d2q(double d, int max) av_const; + +/** + * Find which of the two rationals is closer to another rational. + * + * @param q Rational to be compared against + * @param q1 Rational to be tested + * @param q2 Rational to be tested + * @return One of the following values: + * - 1 if `q1` is nearer to `q` than `q2` + * - -1 if `q2` is nearer to `q` than `q1` + * - 0 if they have the same distance + */ +int av_nearer_q(AVRational q, AVRational q1, AVRational q2); + +/** + * Find the value in a list of rationals nearest a given reference rational. + * + * @param q Reference rational + * @param q_list Array of rationals terminated by `{0, 0}` + * @return Index of the nearest value found in the array + */ +int av_find_nearest_q_idx(AVRational q, const AVRational* q_list); + +/** + * Convert an AVRational to a IEEE 32-bit `float` expressed in fixed-point + * format. + * + * @param q Rational to be converted + * @return Equivalent floating-point value, expressed as an unsigned 32-bit + * integer. + * @note The returned value is platform-indepedant. + */ +uint32_t av_q2intfloat(AVRational q); + +/** + * Return the best rational so that a and b are multiple of it. + * If the resulting denominator is larger than max_den, return def. + */ +AVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def); + +/** + * @} + */ + +#endif /* AVUTIL_RATIONAL_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/samplefmt.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/samplefmt.h new file mode 100644 index 0000000000000..43a57a422cdbf --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/samplefmt.h @@ -0,0 +1,269 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_SAMPLEFMT_H +#define AVUTIL_SAMPLEFMT_H + +#include + +/** + * @addtogroup lavu_audio + * @{ + * + * @defgroup lavu_sampfmts Audio sample formats + * + * Audio sample format enumeration and related convenience functions. + * @{ + */ + +/** + * Audio sample formats + * + * - The data described by the sample format is always in native-endian order. + * Sample values can be expressed by native C types, hence the lack of a signed + * 24-bit sample format even though it is a common raw audio data format. + * + * - The floating-point formats are based on full volume being in the range + * [-1.0, 1.0]. Any values outside this range are beyond full volume level. + * + * - The data layout as used in av_samples_fill_arrays() and elsewhere in FFmpeg + * (such as AVFrame in libavcodec) is as follows: + * + * @par + * For planar sample formats, each audio channel is in a separate data plane, + * and linesize is the buffer size, in bytes, for a single plane. All data + * planes must be the same size. For packed sample formats, only the first data + * plane is used, and samples for each channel are interleaved. In this case, + * linesize is the buffer size, in bytes, for the 1 plane. + * + */ +enum AVSampleFormat { + AV_SAMPLE_FMT_NONE = -1, + AV_SAMPLE_FMT_U8, ///< unsigned 8 bits + AV_SAMPLE_FMT_S16, ///< signed 16 bits + AV_SAMPLE_FMT_S32, ///< signed 32 bits + AV_SAMPLE_FMT_FLT, ///< float + AV_SAMPLE_FMT_DBL, ///< double + + AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar + AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar + AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar + AV_SAMPLE_FMT_FLTP, ///< float, planar + AV_SAMPLE_FMT_DBLP, ///< double, planar + AV_SAMPLE_FMT_S64, ///< signed 64 bits + AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar + + AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically +}; + +/** + * Return the name of sample_fmt, or NULL if sample_fmt is not + * recognized. + */ +const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt); + +/** + * Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE + * on error. + */ +enum AVSampleFormat av_get_sample_fmt(const char *name); + +/** + * Return the planar<->packed alternative form of the given sample format, or + * AV_SAMPLE_FMT_NONE on error. If the passed sample_fmt is already in the + * requested planar/packed format, the format returned is the same as the + * input. + */ +enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar); + +/** + * Get the packed alternative form of the given sample format. + * + * If the passed sample_fmt is already in packed format, the format returned is + * the same as the input. + * + * @return the packed alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Get the planar alternative form of the given sample format. + * + * If the passed sample_fmt is already in planar format, the format returned is + * the same as the input. + * + * @return the planar alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Generate a string corresponding to the sample format with + * sample_fmt, or a header if sample_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param sample_fmt the number of the sample format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + * @return the pointer to the filled buffer or NULL if sample_fmt is + * unknown or in case of other errors + */ +char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt); + +/** + * Return number of bytes per sample. + * + * @param sample_fmt the sample format + * @return number of bytes per sample or zero if unknown for the given + * sample format + */ +int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt); + +/** + * Check if the sample format is planar. + * + * @param sample_fmt the sample format to inspect + * @return 1 if the sample format is planar, 0 if it is interleaved + */ +int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt); + +/** + * Get the required buffer size for the given audio parameters. + * + * @param[out] linesize calculated linesize, may be NULL + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return required buffer size, or negative error code on failure + */ +int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * @} + * + * @defgroup lavu_sampmanip Samples manipulation + * + * Functions that manipulate audio samples + * @{ + */ + +/** + * Fill plane data pointers and linesize for samples with sample + * format sample_fmt. + * + * The audio_data array is filled with the pointers to the samples data planes: + * for planar, set the start point of each channel's data within the buffer, + * for packed, set the start point of the entire buffer only. + * + * The value pointed to by linesize is set to the aligned size of each + * channel's data buffer for planar layout, or to the aligned size of the + * buffer for all channels for packed layout. + * + * The buffer in buf must be big enough to contain all the samples + * (use av_samples_get_buffer_size() to compute its minimum size), + * otherwise the audio_data pointers will point to invalid data. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize calculated linesize, may be NULL + * @param buf the pointer to a buffer containing the samples + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return minimum size in bytes required for the buffer on success, + * or a negative error code on failure + */ +int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, + const uint8_t *buf, + int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a samples buffer for nb_samples samples, and fill data pointers and + * linesize accordingly. + * The allocated samples buffer can be freed by using av_freep(&audio_data[0]) + * Allocated data will be initialized to silence. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize aligned size for audio buffer(s), may be NULL + * @param nb_channels number of audio channels + * @param nb_samples number of samples per channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return >=0 on success or a negative error code on failure + * @todo return the size of the allocated buffer in case of success at the next bump + * @see av_samples_fill_arrays() + * @see av_samples_alloc_array_and_samples() + */ +int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a data pointers array, samples buffer for nb_samples + * samples, and fill data pointers and linesize accordingly. + * + * This is the same as av_samples_alloc(), but also allocates the data + * pointers array. + * + * @see av_samples_alloc() + */ +int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Copy samples from src to dst. + * + * @param dst destination array of pointers to data planes + * @param src source array of pointers to data planes + * @param dst_offset offset in samples at which the data will be written to dst + * @param src_offset offset in samples at which the data will be read from src + * @param nb_samples number of samples to be copied + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_copy(uint8_t * const *dst, uint8_t * const *src, int dst_offset, + int src_offset, int nb_samples, int nb_channels, + enum AVSampleFormat sample_fmt); + +/** + * Fill an audio buffer with silence. + * + * @param audio_data array of pointers to data planes + * @param offset offset in samples at which to start filling + * @param nb_samples number of samples to fill + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_set_silence(uint8_t * const *audio_data, int offset, int nb_samples, + int nb_channels, enum AVSampleFormat sample_fmt); + +/** + * @} + * @} + */ +#endif /* AVUTIL_SAMPLEFMT_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libavutil/version.h b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/version.h new file mode 100644 index 0000000000000..6ce66075b441b --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libavutil/version.h @@ -0,0 +1,119 @@ +/* + * copyright (c) 2003 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu + * Libavutil version macros + */ + +#ifndef AVUTIL_VERSION_H +#define AVUTIL_VERSION_H + +#include "macros.h" + +/** + * @addtogroup version_utils + * + * Useful to check and match library version in order to maintain + * backward compatibility. + * + * The FFmpeg libraries follow a versioning scheme very similar to + * Semantic Versioning (http://semver.org/) + * The difference is that the component called PATCH is called MICRO in FFmpeg + * and its value is reset to 100 instead of 0 to keep it above or equal to 100. + * Also we do not increase MICRO for every bugfix or change in git master. + * + * Prior to FFmpeg 3.2 point releases did not change any lib version number to + * avoid aliassing different git master checkouts. + * Starting with FFmpeg 3.2, the released library versions will occupy + * a separate MAJOR.MINOR that is not used on the master development branch. + * That is if we branch a release of master 55.10.123 we will bump to 55.11.100 + * for the release and master will continue at 55.12.100 after it. Each new + * point release will then bump the MICRO improving the usefulness of the lib + * versions. + * + * @{ + */ + +#define AV_VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c)) +#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c +#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c) + +/** + * Extract version components from the full ::AV_VERSION_INT int as returned + * by functions like ::avformat_version() and ::avcodec_version() + */ +#define AV_VERSION_MAJOR(a) ((a) >> 16) +#define AV_VERSION_MINOR(a) (((a) & 0x00FF00) >> 8) +#define AV_VERSION_MICRO(a) ((a) & 0xFF) + +/** + * @} + */ + +/** + * @defgroup lavu_ver Version and Build diagnostics + * + * Macros and function useful to check at compile time and at runtime + * which version of libavutil is in use. + * + * @{ + */ + +#define LIBAVUTIL_VERSION_MAJOR 60 +#define LIBAVUTIL_VERSION_MINOR 8 +#define LIBAVUTIL_VERSION_MICRO 100 + +#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT + +#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION) + +/** + * @defgroup lavu_depr_guards Deprecation Guards + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + * + * @{ + */ + +#define FF_API_MOD_UINTP2 (LIBAVUTIL_VERSION_MAJOR < 61) +#define FF_API_RISCV_FD_ZBA (LIBAVUTIL_VERSION_MAJOR < 61) +#define FF_API_VULKAN_FIXED_QUEUES (LIBAVUTIL_VERSION_MAJOR < 61) +#define FF_API_OPT_INT_LIST (LIBAVUTIL_VERSION_MAJOR < 61) +#define FF_API_OPT_PTR (LIBAVUTIL_VERSION_MAJOR < 61) + +/** + * @} + * @} + */ + +#endif /* AVUTIL_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libswscale/swscale.h b/src/framework/media/thirdparty/ffmpeg/v8/libswscale/swscale.h new file mode 100644 index 0000000000000..39e23075a4d1a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libswscale/swscale.h @@ -0,0 +1,683 @@ +/* + * Copyright (C) 2024 Niklas Haas + * Copyright (C) 2001-2011 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_SWSCALE_H +#define SWSCALE_SWSCALE_H + +/** + * @file + * @ingroup libsws + * external API header + */ + +#include + +#include "libavutil/avutil.h" +#include "libavutil/frame.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "version.h" +#endif + +/** + * @defgroup libsws libswscale + * Color conversion and scaling library. + * + * @{ + * + * Return the LIBSWSCALE_VERSION_INT constant. + */ +unsigned swscale_version(void); + +/** + * Return the libswscale build-time configuration. + */ +const char *swscale_configuration(void); + +/** + * Return the libswscale license. + */ +const char *swscale_license(void); + +/** + * Get the AVClass for SwsContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *sws_get_class(void); + +/****************************** + * Flags and quality settings * + ******************************/ + +typedef enum SwsDither { + SWS_DITHER_NONE = 0, /* disable dithering */ + SWS_DITHER_AUTO, /* auto-select from preset */ + SWS_DITHER_BAYER, /* ordered dither matrix */ + SWS_DITHER_ED, /* error diffusion */ + SWS_DITHER_A_DITHER, /* arithmetic addition */ + SWS_DITHER_X_DITHER, /* arithmetic xor */ + SWS_DITHER_NB, /* not part of the ABI */ +} SwsDither; + +typedef enum SwsAlphaBlend { + SWS_ALPHA_BLEND_NONE = 0, + SWS_ALPHA_BLEND_UNIFORM, + SWS_ALPHA_BLEND_CHECKERBOARD, + SWS_ALPHA_BLEND_NB, /* not part of the ABI */ +} SwsAlphaBlend; + +typedef enum SwsFlags { + /** + * Scaler selection options. Only one may be active at a time. + */ + SWS_FAST_BILINEAR = 1 << 0, ///< fast bilinear filtering + SWS_BILINEAR = 1 << 1, ///< bilinear filtering + SWS_BICUBIC = 1 << 2, ///< 2-tap cubic B-spline + SWS_X = 1 << 3, ///< experimental + SWS_POINT = 1 << 4, ///< nearest neighbor + SWS_AREA = 1 << 5, ///< area averaging + SWS_BICUBLIN = 1 << 6, ///< bicubic luma, bilinear chroma + SWS_GAUSS = 1 << 7, ///< gaussian approximation + SWS_SINC = 1 << 8, ///< unwindowed sinc + SWS_LANCZOS = 1 << 9, ///< 3-tap sinc/sinc + SWS_SPLINE = 1 << 10, ///< cubic Keys spline + + /** + * Return an error on underspecified conversions. Without this flag, + * unspecified fields are defaulted to sensible values. + */ + SWS_STRICT = 1 << 11, + + /** + * Emit verbose log of scaling parameters. + */ + SWS_PRINT_INFO = 1 << 12, + + /** + * Perform full chroma upsampling when upscaling to RGB. + * + * For example, when converting 50x50 yuv420p to 100x100 rgba, setting this flag + * will scale the chroma plane from 25x25 to 100x100 (4:4:4), and then convert + * the 100x100 yuv444p image to rgba in the final output step. + * + * Without this flag, the chroma plane is instead scaled to 50x100 (4:2:2), + * with a single chroma sample being reused for both of the horizontally + * adjacent RGBA output pixels. + */ + SWS_FULL_CHR_H_INT = 1 << 13, + + /** + * Perform full chroma interpolation when downscaling RGB sources. + * + * For example, when converting a 100x100 rgba source to 50x50 yuv444p, setting + * this flag will generate a 100x100 (4:4:4) chroma plane, which is then + * downscaled to the required 50x50. + * + * Without this flag, the chroma plane is instead generated at 50x100 (dropping + * every other pixel), before then being downscaled to the required 50x50 + * resolution. + */ + SWS_FULL_CHR_H_INP = 1 << 14, + + /** + * Force bit-exact output. This will prevent the use of platform-specific + * optimizations that may lead to slight difference in rounding, in favor + * of always maintaining exact bit output compatibility with the reference + * C code. + * + * Note: It is recommended to set both of these flags simultaneously. + */ + SWS_ACCURATE_RND = 1 << 18, + SWS_BITEXACT = 1 << 19, + + /** + * Deprecated flags. + */ + SWS_DIRECT_BGR = 1 << 15, ///< This flag has no effect + SWS_ERROR_DIFFUSION = 1 << 23, ///< Set `SwsContext.dither` instead +} SwsFlags; + +typedef enum SwsIntent { + SWS_INTENT_PERCEPTUAL = 0, ///< Perceptual tone mapping + SWS_INTENT_RELATIVE_COLORIMETRIC = 1, ///< Relative colorimetric clipping + SWS_INTENT_SATURATION = 2, ///< Saturation mapping + SWS_INTENT_ABSOLUTE_COLORIMETRIC = 3, ///< Absolute colorimetric clipping + SWS_INTENT_NB, ///< not part of the ABI +} SwsIntent; + +/*********************************** + * Context creation and management * + ***********************************/ + +/** + * Main external API structure. New fields can be added to the end with + * minor version bumps. Removal, reordering and changes to existing fields + * require a major version bump. sizeof(SwsContext) is not part of the ABI. + */ +typedef struct SwsContext { + const AVClass *av_class; + + /** + * Private data of the user, can be used to carry app specific stuff. + */ + void *opaque; + + /** + * Bitmask of SWS_*. See `SwsFlags` for details. + */ + unsigned flags; + + /** + * Extra parameters for fine-tuning certain scalers. + */ + double scaler_params[2]; + + /** + * How many threads to use for processing, or 0 for automatic selection. + */ + int threads; + + /** + * Dither mode. + */ + SwsDither dither; + + /** + * Alpha blending mode. See `SwsAlphaBlend` for details. + */ + SwsAlphaBlend alpha_blend; + + /** + * Use gamma correct scaling. + */ + int gamma_flag; + + /** + * Deprecated frame property overrides, for the legacy API only. + * + * Ignored by sws_scale_frame() when used in dynamic mode, in which + * case all properties are instead taken from the frame directly. + */ + int src_w, src_h; ///< Width and height of the source frame + int dst_w, dst_h; ///< Width and height of the destination frame + int src_format; ///< Source pixel format + int dst_format; ///< Destination pixel format + int src_range; ///< Source is full range + int dst_range; ///< Destination is full range + int src_v_chr_pos; ///< Source vertical chroma position in luma grid / 256 + int src_h_chr_pos; ///< Source horizontal chroma position + int dst_v_chr_pos; ///< Destination vertical chroma position + int dst_h_chr_pos; ///< Destination horizontal chroma position + + /** + * Desired ICC intent for color space conversions. + */ + int intent; + + /* Remember to add new fields to graph.c:opts_equal() */ +} SwsContext; + +/** + * Allocate an empty SwsContext and set its fields to default values. + */ +SwsContext *sws_alloc_context(void); + +/** + * Free the context and everything associated with it, and write NULL + * to the provided pointer. + */ +void sws_free_context(SwsContext **ctx); + +/*************************** + * Supported frame formats * + ***************************/ + +/** + * Test if a given pixel format is supported. + * + * @param output If 0, test if compatible with the source/input frame; + * otherwise, with the destination/output frame. + * @param format The format to check. + * + * @return A positive integer if supported, 0 otherwise. + */ +int sws_test_format(enum AVPixelFormat format, int output); + +/** + * Test if a given color space is supported. + * + * @param output If 0, test if compatible with the source/input frame; + * otherwise, with the destination/output frame. + * @param colorspace The colorspace to check. + * + * @return A positive integer if supported, 0 otherwise. + */ +int sws_test_colorspace(enum AVColorSpace colorspace, int output); + +/** + * Test if a given set of color primaries is supported. + * + * @param output If 0, test if compatible with the source/input frame; + * otherwise, with the destination/output frame. + * @param primaries The color primaries to check. + * + * @return A positive integer if supported, 0 otherwise. + */ +int sws_test_primaries(enum AVColorPrimaries primaries, int output); + +/** + * Test if a given color transfer function is supported. + * + * @param output If 0, test if compatible with the source/input frame; + * otherwise, with the destination/output frame. + * @param trc The color transfer function to check. + * + * @return A positive integer if supported, 0 otherwise. + */ +int sws_test_transfer(enum AVColorTransferCharacteristic trc, int output); + +/** + * Helper function to run all sws_test_* against a frame, as well as testing + * the basic frame properties for sanity. Ignores irrelevant properties - for + * example, AVColorSpace is not checked for RGB frames. + */ +int sws_test_frame(const AVFrame *frame, int output); + +/** + * Like `sws_scale_frame`, but without actually scaling. It will instead + * merely initialize internal state that *would* be required to perform the + * operation, as well as returning the correct error code for unsupported + * frame combinations. + * + * @param ctx The scaling context. + * @param dst The destination frame to consider. + * @param src The source frame to consider. + * @return 0 on success, a negative AVERROR code on failure. + */ +int sws_frame_setup(SwsContext *ctx, const AVFrame *dst, const AVFrame *src); + +/******************** + * Main scaling API * + ********************/ + +/** + * Check if a given conversion is a noop. Returns a positive integer if + * no operation needs to be performed, 0 otherwise. + */ +int sws_is_noop(const AVFrame *dst, const AVFrame *src); + +/** + * Scale source data from `src` and write the output to `dst`. + * + * This function can be used directly on an allocated context, without setting + * up any frame properties or calling `sws_init_context()`. Such usage is fully + * dynamic and does not require reallocation if the frame properties change. + * + * Alternatively, this function can be called on a context that has been + * explicitly initialized. However, this is provided only for backwards + * compatibility. In this usage mode, all frame properties must be correctly + * set at init time, and may no longer change after initialization. + * + * @param ctx The scaling context. + * @param dst The destination frame. The data buffers may either be already + * allocated by the caller or left clear, in which case they will + * be allocated by the scaler. The latter may have performance + * advantages - e.g. in certain cases some (or all) output planes + * may be references to input planes, rather than copies. + * @param src The source frame. If the data buffers are set to NULL, then + * this function behaves identically to `sws_frame_setup`. + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int sws_scale_frame(SwsContext *c, AVFrame *dst, const AVFrame *src); + +/************************* + * Legacy (stateful) API * + *************************/ + +#define SWS_SRC_V_CHR_DROP_MASK 0x30000 +#define SWS_SRC_V_CHR_DROP_SHIFT 16 + +#define SWS_PARAM_DEFAULT 123456 + +#define SWS_MAX_REDUCE_CUTOFF 0.002 + +#define SWS_CS_ITU709 1 +#define SWS_CS_FCC 4 +#define SWS_CS_ITU601 5 +#define SWS_CS_ITU624 5 +#define SWS_CS_SMPTE170M 5 +#define SWS_CS_SMPTE240M 7 +#define SWS_CS_DEFAULT 5 +#define SWS_CS_BT2020 9 + +/** + * Return a pointer to yuv<->rgb coefficients for the given colorspace + * suitable for sws_setColorspaceDetails(). + * + * @param colorspace One of the SWS_CS_* macros. If invalid, + * SWS_CS_DEFAULT is used. + */ +const int *sws_getCoefficients(int colorspace); + +// when used for filters they must have an odd number of elements +// coeffs cannot be shared between vectors +typedef struct SwsVector { + double *coeff; ///< pointer to the list of coefficients + int length; ///< number of coefficients in the vector +} SwsVector; + +// vectors can be shared +typedef struct SwsFilter { + SwsVector *lumH; + SwsVector *lumV; + SwsVector *chrH; + SwsVector *chrV; +} SwsFilter; + +/** + * Return a positive value if pix_fmt is a supported input format, 0 + * otherwise. + */ +int sws_isSupportedInput(enum AVPixelFormat pix_fmt); + +/** + * Return a positive value if pix_fmt is a supported output format, 0 + * otherwise. + */ +int sws_isSupportedOutput(enum AVPixelFormat pix_fmt); + +/** + * @param[in] pix_fmt the pixel format + * @return a positive value if an endianness conversion for pix_fmt is + * supported, 0 otherwise. + */ +int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt); + +/** + * Initialize the swscaler context sws_context. + * + * This function is considered deprecated, and provided only for backwards + * compatibility with sws_scale() and sws_start_frame(). The preferred way to + * use libswscale is to set all frame properties correctly and call + * sws_scale_frame() directly, without explicitly initializing the context. + * + * @return zero or positive value on success, a negative value on + * error + */ +av_warn_unused_result +int sws_init_context(SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter); + +/** + * Free the swscaler context swsContext. + * If swsContext is NULL, then does nothing. + */ +void sws_freeContext(SwsContext *swsContext); + +/** + * Allocate and return an SwsContext. You need it to perform + * scaling/conversion operations using sws_scale(). + * + * @param srcW the width of the source image + * @param srcH the height of the source image + * @param srcFormat the source image format + * @param dstW the width of the destination image + * @param dstH the height of the destination image + * @param dstFormat the destination image format + * @param flags specify which algorithm and options to use for rescaling + * @param param extra parameters to tune the used scaler + * For SWS_BICUBIC param[0] and [1] tune the shape of the basis + * function, param[0] tunes f(1) and param[1] f´(1) + * For SWS_GAUSS param[0] tunes the exponent and thus cutoff + * frequency + * For SWS_LANCZOS param[0] tunes the width of the window function + * @return a pointer to an allocated context, or NULL in case of error + * @note this function is to be removed after a saner alternative is + * written + */ +SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, + int dstW, int dstH, enum AVPixelFormat dstFormat, + int flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param); + +/** + * Scale the image slice in srcSlice and put the resulting scaled + * slice in the image in dst. A slice is a sequence of consecutive + * rows in an image. Requires a context that has been previously + * been initialized with sws_init_context(). + * + * Slices have to be provided in sequential order, either in + * top-bottom or bottom-top order. If slices are provided in + * non-sequential order the behavior of the function is undefined. + * + * @param c the scaling context previously created with + * sws_getContext() + * @param srcSlice the array containing the pointers to the planes of + * the source slice + * @param srcStride the array containing the strides for each plane of + * the source image + * @param srcSliceY the position in the source image of the slice to + * process, that is the number (counted starting from + * zero) in the image of the first row of the slice + * @param srcSliceH the height of the source slice, that is the number + * of rows in the slice + * @param dst the array containing the pointers to the planes of + * the destination image + * @param dstStride the array containing the strides for each plane of + * the destination image + * @return the height of the output slice + */ +int sws_scale(SwsContext *c, const uint8_t *const srcSlice[], + const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *const dst[], const int dstStride[]); + +/** + * Initialize the scaling process for a given pair of source/destination frames. + * Must be called before any calls to sws_send_slice() and sws_receive_slice(). + * Requires a context that has been previously been initialized with + * sws_init_context(). + * + * This function will retain references to src and dst, so they must both use + * refcounted buffers (if allocated by the caller, in case of dst). + * + * @param c The scaling context + * @param dst The destination frame. + * + * The data buffers may either be already allocated by the caller or + * left clear, in which case they will be allocated by the scaler. + * The latter may have performance advantages - e.g. in certain cases + * some output planes may be references to input planes, rather than + * copies. + * + * Output data will be written into this frame in successful + * sws_receive_slice() calls. + * @param src The source frame. The data buffers must be allocated, but the + * frame data does not have to be ready at this point. Data + * availability is then signalled by sws_send_slice(). + * @return 0 on success, a negative AVERROR code on failure + * + * @see sws_frame_end() + */ +int sws_frame_start(SwsContext *c, AVFrame *dst, const AVFrame *src); + +/** + * Finish the scaling process for a pair of source/destination frames previously + * submitted with sws_frame_start(). Must be called after all sws_send_slice() + * and sws_receive_slice() calls are done, before any new sws_frame_start() + * calls. + * + * @param c The scaling context + */ +void sws_frame_end(SwsContext *c); + +/** + * Indicate that a horizontal slice of input data is available in the source + * frame previously provided to sws_frame_start(). The slices may be provided in + * any order, but may not overlap. For vertically subsampled pixel formats, the + * slices must be aligned according to subsampling. + * + * @param c The scaling context + * @param slice_start first row of the slice + * @param slice_height number of rows in the slice + * + * @return a non-negative number on success, a negative AVERROR code on failure. + */ +int sws_send_slice(SwsContext *c, unsigned int slice_start, + unsigned int slice_height); + +/** + * Request a horizontal slice of the output data to be written into the frame + * previously provided to sws_frame_start(). + * + * @param c The scaling context + * @param slice_start first row of the slice; must be a multiple of + * sws_receive_slice_alignment() + * @param slice_height number of rows in the slice; must be a multiple of + * sws_receive_slice_alignment(), except for the last slice + * (i.e. when slice_start+slice_height is equal to output + * frame height) + * + * @return a non-negative number if the data was successfully written into the output + * AVERROR(EAGAIN) if more input data needs to be provided before the + * output can be produced + * another negative AVERROR code on other kinds of scaling failure + */ +int sws_receive_slice(SwsContext *c, unsigned int slice_start, + unsigned int slice_height); + +/** + * Get the alignment required for slices. Requires a context that has been + * previously been initialized with sws_init_context(). + * + * @param c The scaling context + * @return alignment required for output slices requested with sws_receive_slice(). + * Slice offsets and sizes passed to sws_receive_slice() must be + * multiples of the value returned from this function. + */ +unsigned int sws_receive_slice_alignment(const SwsContext *c); + +/** + * @param c the scaling context + * @param dstRange flag indicating the while-black range of the output (1=jpeg / 0=mpeg) + * @param srcRange flag indicating the while-black range of the input (1=jpeg / 0=mpeg) + * @param table the yuv2rgb coefficients describing the output yuv space, normally ff_yuv2rgb_coeffs[x] + * @param inv_table the yuv2rgb coefficients describing the input yuv space, normally ff_yuv2rgb_coeffs[x] + * @param brightness 16.16 fixed point brightness correction + * @param contrast 16.16 fixed point contrast correction + * @param saturation 16.16 fixed point saturation correction + * + * @return A negative error code on error, non negative otherwise. + * If `LIBSWSCALE_VERSION_MAJOR < 7`, returns -1 if not supported. + */ +int sws_setColorspaceDetails(SwsContext *c, const int inv_table[4], + int srcRange, const int table[4], int dstRange, + int brightness, int contrast, int saturation); + +/** + * @return A negative error code on error, non negative otherwise. + * If `LIBSWSCALE_VERSION_MAJOR < 7`, returns -1 if not supported. + */ +int sws_getColorspaceDetails(SwsContext *c, int **inv_table, + int *srcRange, int **table, int *dstRange, + int *brightness, int *contrast, int *saturation); + +/** + * Allocate and return an uninitialized vector with length coefficients. + */ +SwsVector *sws_allocVec(int length); + +/** + * Return a normalized Gaussian curve used to filter stuff + * quality = 3 is high quality, lower is lower quality. + */ +SwsVector *sws_getGaussianVec(double variance, double quality); + +/** + * Scale all the coefficients of a by the scalar value. + */ +void sws_scaleVec(SwsVector *a, double scalar); + +/** + * Scale all the coefficients of a so that their sum equals height. + */ +void sws_normalizeVec(SwsVector *a, double height); + +void sws_freeVec(SwsVector *a); + +SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, + float lumaSharpen, float chromaSharpen, + float chromaHShift, float chromaVShift, + int verbose); +void sws_freeFilter(SwsFilter *filter); + +/** + * Check if context can be reused, otherwise reallocate a new one. + * + * If context is NULL, just calls sws_getContext() to get a new + * context. Otherwise, checks if the parameters are the ones already + * saved in context. If that is the case, returns the current + * context. Otherwise, frees context and gets a new context with + * the new parameters. + * + * Be warned that srcFilter and dstFilter are not checked, they + * are assumed to remain the same. + */ +SwsContext *sws_getCachedContext(SwsContext *context, int srcW, int srcH, + enum AVPixelFormat srcFormat, int dstW, int dstH, + enum AVPixelFormat dstFormat, int flags, + SwsFilter *srcFilter, SwsFilter *dstFilter, + const double *param); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 32 bits. + * + * The output frame will have the same packed format as the palette. + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 24 bits. + * + * With the palette format "ABCD", the destination frame ends up with the format "ABC". + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * @} + */ + +#endif /* SWSCALE_SWSCALE_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libswscale/version.h b/src/framework/media/thirdparty/ffmpeg/v8/libswscale/version.h new file mode 100644 index 0000000000000..4e54701aba888 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libswscale/version.h @@ -0,0 +1,44 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_VERSION_H +#define SWSCALE_VERSION_H + +/** + * @file + * swscale version macros + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBSWSCALE_VERSION_MINOR 1 +#define LIBSWSCALE_VERSION_MICRO 100 + +#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_VERSION AV_VERSION(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_BUILD LIBSWSCALE_VERSION_INT + +#define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION) + +#endif /* SWSCALE_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libswscale/version_major.h b/src/framework/media/thirdparty/ffmpeg/v8/libswscale/version_major.h new file mode 100644 index 0000000000000..0dc507921ed4c --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libswscale/version_major.h @@ -0,0 +1,35 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_VERSION_MAJOR_H +#define SWSCALE_VERSION_MAJOR_H + +/** + * @file + * swscale version macros + */ + +#define LIBSWSCALE_VERSION_MAJOR 9 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + */ + +#endif /* SWSCALE_VERSION_MAJOR_H */ From e62223cd52bb375d47443bedde11cd1ef989247f Mon Sep 17 00:00:00 2001 From: Eism Date: Wed, 4 Mar 2026 17:52:29 +0200 Subject: [PATCH 12/52] added dynamic loading of ffmpeg library --- src/framework/media/CMakeLists.txt | 26 +- src/framework/media/imediaconfiguration.h | 42 ++++ .../media/internal/ffmpegfunctions.cpp | 46 ++++ .../media/internal/ffmpegfunctions.h | 101 ++++++++ .../media/internal/ffmpeglibhandler.cpp | 209 +++++++++++++++++ .../media/internal/ffmpeglibhandler.h | 57 +++++ src/framework/media/internal/ffmpegloader.cpp | 154 ++++++++++++ src/framework/media/internal/ffmpegloader.h | 34 +++ src/framework/media/internal/ffmpegutils.h | 45 ++++ .../media/internal/mediaconfiguration.cpp | 52 ++++ .../media/internal/mediaconfiguration.h | 46 ++++ src/framework/media/internal/videoencoder.cpp | 222 ++++++++++-------- src/framework/media/internal/videoencoder.h | 8 +- .../media/internal/videoencoderresolver.cpp | 54 +++++ .../media/internal/videoencoderresolver.h | 46 ++++ src/framework/media/ivideoencoder.h | 3 +- .../ffmpeg.h => ivideoencoderresolver.h} | 26 +- src/framework/media/mediamodule.cpp | 17 +- src/framework/media/mediamodule.h | 8 + src/framework/stubs/media/CMakeLists.txt | 1 + src/framework/stubs/media/mediastubmodule.cpp | 9 +- .../videoexport/internal/videowriter.cpp | 11 +- .../videoexport/internal/videowriter.h | 4 +- 23 files changed, 1087 insertions(+), 134 deletions(-) create mode 100644 src/framework/media/imediaconfiguration.h create mode 100644 src/framework/media/internal/ffmpegfunctions.cpp create mode 100644 src/framework/media/internal/ffmpegfunctions.h create mode 100644 src/framework/media/internal/ffmpeglibhandler.cpp create mode 100644 src/framework/media/internal/ffmpeglibhandler.h create mode 100644 src/framework/media/internal/ffmpegloader.cpp create mode 100644 src/framework/media/internal/ffmpegloader.h create mode 100644 src/framework/media/internal/ffmpegutils.h create mode 100644 src/framework/media/internal/mediaconfiguration.cpp create mode 100644 src/framework/media/internal/mediaconfiguration.h create mode 100644 src/framework/media/internal/videoencoderresolver.cpp create mode 100644 src/framework/media/internal/videoencoderresolver.h rename src/framework/media/{internal/ffmpeg.h => ivideoencoderresolver.h} (67%) diff --git a/src/framework/media/CMakeLists.txt b/src/framework/media/CMakeLists.txt index ab40348b64249..787f374cb17b6 100644 --- a/src/framework/media/CMakeLists.txt +++ b/src/framework/media/CMakeLists.txt @@ -18,20 +18,34 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -muse_create_module(muse_media ALIAS muse::media) +muse_create_module(muse_media ALIAS muse::media NO_UNITY) target_sources(muse_media PRIVATE mediamodule.cpp mediamodule.h + imediaconfiguration.h + ivideoencoder.h + ivideoencoderresolver.h + + internal/mediaconfiguration.cpp + internal/videoencoderresolver.cpp + internal/mediaconfiguration.h + internal/videoencoderresolver.h + + internal/ffmpegloader.cpp + internal/ffmpegloader.h + internal/ffmpegutils.h + + internal/ffmpegfunctions.cpp + internal/ffmpeglibhandler.cpp + internal/ffmpeglibhandler.h internal/videoencoder.cpp internal/videoencoder.h - internal/ffmpeg.h ) -# FFmpeg -find_package(FFmpeg REQUIRED) +target_include_directories(muse_media PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v8) -target_include_directories(muse_media PRIVATE ${FFMPEG_INCLUDE_DIRS}) -target_link_libraries(muse_media PRIVATE ${FFMPEG_LIBRARIES}) +set(MODULE_USE_PCH OFF) +set(MODULE_USE_UNITY OFF) diff --git a/src/framework/media/imediaconfiguration.h b/src/framework/media/imediaconfiguration.h new file mode 100644 index 0000000000000..5ce6ca3c85281 --- /dev/null +++ b/src/framework/media/imediaconfiguration.h @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +#include "modularity/imoduleinterface.h" + +#include "io/path.h" +#include "async/channel.h" + +namespace muse::media { +class IMediaConfiguration : MODULE_GLOBAL_INTERFACE +{ + INTERFACE_ID(IMediaConfiguration) + +public: + virtual ~IMediaConfiguration() = default; + + virtual io::path_t ffmpegLibsDir() const = 0; + virtual void setFFmpegLibsDir(const io::path_t& path) = 0; + virtual async::Channel ffmpegLibsDirChanged() const = 0; +}; +} diff --git a/src/framework/media/internal/ffmpegfunctions.cpp b/src/framework/media/internal/ffmpegfunctions.cpp new file mode 100644 index 0000000000000..af2b2316bbde1 --- /dev/null +++ b/src/framework/media/internal/ffmpegfunctions.cpp @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "ffmpegfunctions.h" + +namespace muse::media { + +bool FFmpegFunctions::isValid() const +{ + return av_free && av_freep && av_rescale_q + && av_image_fill_arrays && av_image_get_buffer_size + && av_opt_set_int + && av_guess_format && avformat_alloc_context && avformat_new_stream + && avformat_write_header && av_write_trailer + && avio_open && avio_close && av_interleaved_write_frame + && avformat_open_input && avformat_find_stream_info + && avformat_close_input && avformat_free_context + && avformat_alloc_output_context2 && av_read_frame + && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context + && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_copy + && avcodec_send_frame && avcodec_receive_packet + && av_frame_alloc + && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts + && sws_getCachedContext && sws_scale; +} + +} diff --git a/src/framework/media/internal/ffmpegfunctions.h b/src/framework/media/internal/ffmpegfunctions.h new file mode 100644 index 0000000000000..9d92f64b0508e --- /dev/null +++ b/src/framework/media/internal/ffmpegfunctions.h @@ -0,0 +1,101 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +extern "C" { +#include "thirdparty/ffmpeg/v8/libavcodec/avcodec.h" +#include "thirdparty/ffmpeg/v8/libavformat/avformat.h" +#include "thirdparty/ffmpeg/v8/libswscale/swscale.h" +} + +namespace muse::media { + +struct FFmpegFunctions +{ + // libavutil + void (*av_free)(void* ptr) = nullptr; + void (*av_freep)(void* ptr) = nullptr; + int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; + + // libavutil (imgutils) + int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], + const uint8_t* src, AVPixelFormat pix_fmt, + int width, int height, int align) = nullptr; + int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; + + // libavutil (opt) + int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; + + // libavformat + const AVOutputFormat* (*av_guess_format)(const char* short_name, const char* filename, + const char* mime_type) = nullptr; + AVFormatContext* (*avformat_alloc_context)(void) = nullptr; + AVStream* (*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; + int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; + int (*av_write_trailer)(AVFormatContext* s) = nullptr; + int (*avio_open)(AVIOContext** s, const char* url, int flags) = nullptr; + int (*avio_close)(AVIOContext* s) = nullptr; + int (*av_interleaved_write_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + + int (*avformat_open_input)(AVFormatContext** ctx, const char* url, + const AVInputFormat* fmt, AVDictionary** options) = nullptr; + int (*avformat_find_stream_info)(AVFormatContext* ic, AVDictionary** options) = nullptr; + void (*avformat_close_input)(AVFormatContext** s) = nullptr; + void (*avformat_free_context)(AVFormatContext* s) = nullptr; + int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, + const char* format_name, const char* filename) = nullptr; + int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + + // libavcodec + AVCodecContext* (*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; + const AVCodec* (*avcodec_find_encoder)(AVCodecID id) = nullptr; + void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; + int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; + int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; + int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; + int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; + int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; + + // libavutil (frame) + AVFrame* (*av_frame_alloc)(void) = nullptr; + + // libavcodec (packet) + AVPacket* (*av_packet_alloc)(void) = nullptr; + void (*av_packet_free)(AVPacket** pkt) = nullptr; + void (*av_packet_unref)(AVPacket* pkt) = nullptr; + void (*av_packet_rescale_ts)(AVPacket* pkt, AVRational tb_src, AVRational tb_dst) = nullptr; + + // libswscale + SwsContext* (*sws_getCachedContext)(SwsContext* context, int srcW, int srcH, + AVPixelFormat srcFormat, int dstW, int dstH, + AVPixelFormat dstFormat, int flags, + SwsFilter* srcFilter, SwsFilter* dstFilter, + const double* param) = nullptr; + int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], + const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t* const dst[], const int dstStride[]) = nullptr; + + bool isValid() const; +}; + +} diff --git a/src/framework/media/internal/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeglibhandler.cpp new file mode 100644 index 0000000000000..d047fe1bdd1e6 --- /dev/null +++ b/src/framework/media/internal/ffmpeglibhandler.cpp @@ -0,0 +1,209 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "ffmpeglibhandler.h" + +#if !defined(Q_OS_WIN) +#include +#endif + +#include "io/fileinfo.h" +#include "global/dlib.h" + +#include "internal/ffmpegutils.h" + +#include "log.h" + +using namespace muse::media; + +static int versionFromAVFormatPath(const muse::io::path_t& path) +{ + std::string name = muse::io::filename(path, true).toStdString(); + int avVer = -1; +#if defined(Q_OS_MAC) + // libavformat.60.dylib + size_t dot = name.rfind('.'); + if (dot != std::string::npos && dot > 0) { + size_t verStart = name.rfind('.', dot - 1); + if (verStart != std::string::npos && verStart + 1 < dot) { + try { + avVer = std::stoi(name.substr(verStart + 1, dot - verStart - 1)); + } catch (...) {} + } + } +#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) + // libavformat.so.60 + size_t so = name.rfind(".so."); + if (so != std::string::npos && so + 4 < name.size()) { + try { + avVer = std::stoi(name.substr(so + 4)); + } catch (...) {} + } +#elif defined(Q_OS_WIN) + // avformat-60.dll + size_t dash = name.find('-'); + if (dash != std::string::npos && dash + 1 < name.size()) { + size_t dot = name.find('.', dash); + if (dot != std::string::npos) { + try { + avVer = std::stoi(name.substr(dash + 1, dot - dash - 1)); + } catch (...) {} + } + } +#endif + + for (const auto& [ver, componentsVersions]: FFMPEG_COMPONENTS_VERSIONS) { + if (componentsVersions.avFormatVersion == avVer) { + return ver; + } + } + + return 0; +} + +#define RESOLVE_FROM(lib, name) do { \ + m_functions.name = reinterpret_cast(getSymbol(lib, #name)); \ + if (!m_functions.name) { LOGW() << "FFmpeg: missing symbol " #name; return false; } \ +} while (0) + +void* FFmpegLibHandler::getSymbol(void* lib, const char* name) const +{ + if (!lib) { + return nullptr; + } + void* sym = muse::getLibFunc(lib, name); + if (!sym) { +#if !defined(Q_OS_WIN) + sym = dlsym(RTLD_DEFAULT, name); +#endif + } + return sym; +} + +bool FFmpegLibHandler::loadApi() +{ + if (!m_avUtilLibrary || !m_avCodecLibrary || !m_avFormatLibrary || !m_swsScaleLibrary) { + return false; + } + + m_functions = FFmpegFunctions(); + + // libavutil + RESOLVE_FROM(m_avUtilLibrary, av_free); + RESOLVE_FROM(m_avUtilLibrary, av_freep); + RESOLVE_FROM(m_avUtilLibrary, av_rescale_q); + RESOLVE_FROM(m_avUtilLibrary, av_image_fill_arrays); + RESOLVE_FROM(m_avUtilLibrary, av_image_get_buffer_size); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); + RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); + + // libavformat + RESOLVE_FROM(m_avFormatLibrary, av_guess_format); + RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); + RESOLVE_FROM(m_avFormatLibrary, av_interleaved_write_frame); + RESOLVE_FROM(m_avFormatLibrary, av_read_frame); + RESOLVE_FROM(m_avFormatLibrary, avio_open); + RESOLVE_FROM(m_avFormatLibrary, avio_close); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avformat_new_stream); + RESOLVE_FROM(m_avFormatLibrary, avformat_write_header); + RESOLVE_FROM(m_avFormatLibrary, avformat_open_input); + RESOLVE_FROM(m_avFormatLibrary, avformat_find_stream_info); + RESOLVE_FROM(m_avFormatLibrary, avformat_close_input); + RESOLVE_FROM(m_avFormatLibrary, avformat_free_context); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_output_context2); + + // libavcodec + RESOLVE_FROM(m_avCodecLibrary, av_packet_alloc); + RESOLVE_FROM(m_avCodecLibrary, av_packet_free); + RESOLVE_FROM(m_avCodecLibrary, av_packet_unref); + RESOLVE_FROM(m_avCodecLibrary, av_packet_rescale_ts); + RESOLVE_FROM(m_avCodecLibrary, avcodec_alloc_context3); + RESOLVE_FROM(m_avCodecLibrary, avcodec_find_encoder); + RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_open2); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy); + RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame); + RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet); + + // libswscale + RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); + RESOLVE_FROM(m_swsScaleLibrary, sws_scale); + + return m_functions.isValid(); +} + +bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, + const io::path_t& swScalePath) +{ + unload(); + + // Load avutil first, then avcodec, swscale, avformat (dependency order) + if (!tryLoadPath(m_avUtilLibrary, avUtilPath) + || !tryLoadPath(m_avCodecLibrary, avCodecPath) + || !tryLoadPath(m_swsScaleLibrary, swScalePath) + || !tryLoadPath(m_avFormatLibrary, avFormatPath)) { + return false; + } + + m_version = versionFromAVFormatPath(avFormatPath); + + LOGI() << "FFmpeg loaded: avutil=" << avUtilPath << ", avcodec=" << avCodecPath << ", avformat=" << avFormatPath + << ", swscale=" << swScalePath; + + return true; +} + +void FFmpegLibHandler::unload() +{ + closeLib(m_avFormatLibrary); + closeLib(m_swsScaleLibrary); + closeLib(m_avCodecLibrary); + closeLib(m_avUtilLibrary); + + m_functions = FFmpegFunctions(); + m_version = 0; +} + +void FFmpegLibHandler::closeLib(void*& lib) +{ + if (lib) { + muse::closeLib(lib); + lib = nullptr; + } +} + +bool FFmpegLibHandler::tryLoadPath(void*& lib, const io::path_t& fullPath) +{ + if (!io::FileInfo::exists(fullPath)) { + return false; + } + + void* loaded = muse::loadLib(fullPath); + if (loaded) { + lib = loaded; + return true; + } + + return false; +} diff --git a/src/framework/media/internal/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeglibhandler.h new file mode 100644 index 0000000000000..b592f1d2524df --- /dev/null +++ b/src/framework/media/internal/ffmpeglibhandler.h @@ -0,0 +1,57 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +#include "io/path.h" +#include "ffmpegfunctions.h" + +namespace muse::media { +class FFmpegLibHandler +{ +public: + FFmpegLibHandler() = default; + + bool loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, + const io::path_t& swScalePath); + bool loadApi(); + void unload(); + + const FFmpegFunctions* functions() const { return &m_functions; } + + int version() const { return m_version; } + +private: + void* getSymbol(void* lib, const char* name) const; + bool tryLoadPath(void*& lib, const io::path_t& fullPath); + void closeLib(void*& lib); + + void* m_avUtilLibrary = nullptr; + void* m_avCodecLibrary = nullptr; + void* m_avFormatLibrary = nullptr; + void* m_swsScaleLibrary = nullptr; + + FFmpegFunctions m_functions; + + int m_version = 0; +}; +} diff --git a/src/framework/media/internal/ffmpegloader.cpp b/src/framework/media/internal/ffmpegloader.cpp new file mode 100644 index 0000000000000..d214ac241e353 --- /dev/null +++ b/src/framework/media/internal/ffmpegloader.cpp @@ -0,0 +1,154 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "ffmpegloader.h" + +#include "io/fileinfo.h" +#include "io/path.h" + +#include "ffmpegutils.h" +#include "internal/ffmpeglibhandler.h" + +#include "log.h" + +using namespace muse::media; +using namespace muse; + +namespace { +io::paths_t defaultSearchPaths() +{ + io::paths_t paths; +#if defined(Q_OS_MAC) + paths.push_back("/opt/homebrew/lib"); + paths.push_back("/usr/local/lib"); +#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) + paths.push_back("/usr/lib/x86_64-linux-gnu"); + paths.push_back("/usr/lib64"); + paths.push_back("/usr/lib"); +#elif defined(Q_OS_WIN) + // Windows: rely on PATH or user-specified path +#endif + return paths; +} + +struct FFmpegLibPaths { + io::path_t avUtilPath; + io::path_t avCodecPath; + io::path_t avFormatPath; + io::path_t swScalePath; +}; + +FFmpegLibPaths libraryPathsForVersion(int ffmpegVer, const io::paths_t& searchPaths) +{ + const std::string verStr = std::to_string(ffmpegVer); + + FFmpegVersionInfo ffmpegVersionInfo; + for (const auto& [ffmpegVersion, componentsVersions] : FFMPEG_COMPONENTS_VERSIONS) { + if (ffmpegVersion == ffmpegVer) { + ffmpegVersionInfo = componentsVersions; + break; + } + } + + if (!ffmpegVersionInfo.isValid()) { + return {}; + } + + io::path_t avutilName, avcodecName, avformatName, swscaleName; +#if defined(Q_OS_MAC) + avutilName = io::path_t("libavutil." + std::to_string(ffmpegVersionInfo.avUtilVersion) + ".dylib"); + avcodecName = io::path_t("libavcodec." + std::to_string(ffmpegVersionInfo.avCodecVersion) + ".dylib"); + avformatName = io::path_t("libavformat." + std::to_string(ffmpegVersionInfo.avFormatVersion) + ".dylib"); + swscaleName = io::path_t("libswscale." + std::to_string(ffmpegVersionInfo.swScaleVersion) + ".dylib"); +#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) + avutilName = io::path_t("libavutil.so." + std::to_string(ffmpegVersionInfo.avUtilVersion)); + avcodecName = io::path_t("libavcodec.so." + std::to_string(ffmpegVersionInfo.avCodecVersion)); + avformatName = io::path_t("libavformat.so." + verStr); + swscaleName = io::path_t("libswscale.so." + std::to_string(ffmpegVersionInfo.swScaleVersion)); +#elif defined(Q_OS_WIN) + avutilName = io::path_t("avutil-" + std::to_string(ffmpegVersionInfo.avUtilVersion) + ".dll"); + avcodecName = io::path_t("avcodec-" + std::to_string(ffmpegVersionInfo.avCodecVersion) + ".dll"); + avformatName = io::path_t("avformat-" + std::to_string(ffmpegVersionInfo.avFormatVersion) + ".dll"); + swscaleName = io::path_t("swscale-" + std::to_string(ffmpegVersionInfo.swScaleVersion) + ".dll"); +#endif + + FFmpegLibPaths result; + for (const io::path_t& dir : searchPaths) { + io::path_t avutilPath = dir.appendingComponent(avutilName); + io::path_t avcodecPath = dir.appendingComponent(avcodecName); + io::path_t avformatPath = dir.appendingComponent(avformatName); + io::path_t swscalePath = dir.appendingComponent(swscaleName); + if (io::FileInfo::exists(avutilPath) && io::FileInfo::exists(avcodecPath) + && io::FileInfo::exists(avformatPath) && io::FileInfo::exists(swscalePath)) { + result.avUtilPath = avutilPath; + result.avCodecPath = avcodecPath; + result.avFormatPath = avformatPath; + result.swScalePath = swscalePath; + return result; + } + } + + return result; +} + +FFmpegLibPaths findLibraryPaths(const io::path_t& configPath) +{ + FFmpegLibPaths result; + + io::paths_t searchPaths; + if (!configPath.empty() && io::FileInfo::exists(configPath)) { + searchPaths.push_back(io::FileInfo(configPath).entryType() == io::EntryType::Dir + ? configPath : io::dirpath(configPath)); + } + + for (const io::path_t& p : defaultSearchPaths()) { + searchPaths.push_back(p); + } + + for (const auto& [ffmpegVer, _] : FFMPEG_COMPONENTS_VERSIONS) { + result = libraryPathsForVersion(ffmpegVer, searchPaths); + if (!result.avFormatPath.empty()) { + return result; + } + } + + return result; +} +} + +std::shared_ptr FFmpegLoader::load(const io::path_t& ffmpegLibsDir) +{ + const FFmpegLibPaths paths = findLibraryPaths(ffmpegLibsDir); + if (paths.avFormatPath.empty()) { + return nullptr; + } + + std::shared_ptr libHandlerPtr = std::make_shared(); + if (libHandlerPtr->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, paths.swScalePath) + && libHandlerPtr->loadApi()) { + LOGD() << "FFmpeg loaded, version: " << libHandlerPtr->version(); + return libHandlerPtr; + } + + LOGW() << "FFmpeg libraries not found"; + return nullptr; +} diff --git a/src/framework/media/internal/ffmpegloader.h b/src/framework/media/internal/ffmpegloader.h new file mode 100644 index 0000000000000..cd0c8237d30f7 --- /dev/null +++ b/src/framework/media/internal/ffmpegloader.h @@ -0,0 +1,34 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +#include "io/path.h" + +namespace muse::media { +class FFmpegLibHandler; +class FFmpegLoader +{ +public: + static std::shared_ptr load(const muse::io::path_t& ffmpegLibsDir); +}; +} diff --git a/src/framework/media/internal/ffmpegutils.h b/src/framework/media/internal/ffmpegutils.h new file mode 100644 index 0000000000000..e2c4b4bb3adae --- /dev/null +++ b/src/framework/media/internal/ffmpegutils.h @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +namespace muse::media { +struct FFmpegVersionInfo { + int avFormatVersion = -1; + int avUtilVersion = -1; + int avCodecVersion = -1; + int swScaleVersion = -1; + + bool isValid() const + { + return avFormatVersion != -1 && avUtilVersion != -1 && avCodecVersion != -1 && swScaleVersion != -1; + } +}; + +static const std::vector> FFMPEG_COMPONENTS_VERSIONS = { + { 8, { 62, 60, 62, 9 } }, + { 7, { 61, 59, 61, 8 } }, + { 6, { 60, 58, 60, 7 } }, + { 5, { 59, 57, 59, 6 } }, + { 4, { 58, 56, 58, 5 } }, +}; +} diff --git a/src/framework/media/internal/mediaconfiguration.cpp b/src/framework/media/internal/mediaconfiguration.cpp new file mode 100644 index 0000000000000..3dc3c08e1701f --- /dev/null +++ b/src/framework/media/internal/mediaconfiguration.cpp @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "mediaconfiguration.h" + +#include "settings.h" + +using namespace muse::media; + +static const muse::Settings::Key FFMPEG_LIBS_DIR("media", "application/ffmpegLibsDir"); + +void MediaConfiguration::init() +{ + settings()->setDefaultValue(FFMPEG_LIBS_DIR, Val("")); + settings()->valueChanged(FFMPEG_LIBS_DIR).onReceive(this, [this](const Val& val) { + m_ffmpegLibsDirChanged.send(val.toPath()); + }); +} + +muse::io::path_t MediaConfiguration::ffmpegLibsDir() const +{ + return settings()->value(FFMPEG_LIBS_DIR).toPath(); +} + +void MediaConfiguration::setFFmpegLibsDir(const io::path_t& path) +{ + settings()->setSharedValue(FFMPEG_LIBS_DIR, Val(path)); +} + +muse::async::Channel MediaConfiguration::ffmpegLibsDirChanged() const +{ + return m_ffmpegLibsDirChanged; +} diff --git a/src/framework/media/internal/mediaconfiguration.h b/src/framework/media/internal/mediaconfiguration.h new file mode 100644 index 0000000000000..ed67cb85c47c3 --- /dev/null +++ b/src/framework/media/internal/mediaconfiguration.h @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +#include "modularity/ioc.h" + +#include "imediaconfiguration.h" +#include "async/asyncable.h" + +namespace muse::media { +class MediaConfiguration : public IMediaConfiguration, public Contextable, public async::Asyncable +{ +public: + MediaConfiguration(const modularity::ContextPtr& iocCtx) + : Contextable(iocCtx) {} + + void init(); + + io::path_t ffmpegLibsDir() const override; + void setFFmpegLibsDir(const io::path_t& path) override; + async::Channel ffmpegLibsDirChanged() const override; + +private: + async::Channel m_ffmpegLibsDirChanged; +}; +} diff --git a/src/framework/media/internal/videoencoder.cpp b/src/framework/media/internal/videoencoder.cpp index a604ff33c8f0f..b133b740f7d9a 100644 --- a/src/framework/media/internal/videoencoder.cpp +++ b/src/framework/media/internal/videoencoder.cpp @@ -21,8 +21,6 @@ */ #include "videoencoder.h" -#include "ffmpeg.h" - #include "log.h" using namespace muse::media; @@ -61,7 +59,8 @@ struct muse::media::FFmpeg { bool opened = false; }; -VideoEncoder::VideoEncoder() +VideoEncoder::VideoEncoder(const std::shared_ptr& handler) + : m_ffmpegHandler(handler) { m_ffmpeg = new FFmpeg(); @@ -78,17 +77,16 @@ VideoEncoder::~VideoEncoder() delete m_ffmpeg; } -bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, - unsigned fps) +bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) { m_ffmpeg->ptsCounter = 0; m_ffmpeg->width = width; m_ffmpeg->height = height; - m_ffmpeg->outputFormat = av_guess_format("mp4", NULL, NULL); + m_ffmpeg->outputFormat = ffmpegFunctions()->av_guess_format("mp4", NULL, NULL); - m_ffmpeg->formatCtx = avformat_alloc_context(); + m_ffmpeg->formatCtx = ffmpegFunctions()->avformat_alloc_context(); if (!m_ffmpeg->formatCtx) { LOGE() << "failed allocate format context"; return false; @@ -101,7 +99,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign #endif // Add the video stream - m_ffmpeg->videoStream = avformat_new_stream(m_ffmpeg->formatCtx, 0); + m_ffmpeg->videoStream = ffmpegFunctions()->avformat_new_stream(m_ffmpeg->formatCtx, 0); if (!m_ffmpeg->videoStream) { LOGE() << "failed allocate stream"; return false; @@ -116,12 +114,12 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->codecCtx->codec_type = AVMEDIA_TYPE_VIDEO; #else // find the video encoder - m_ffmpeg->codec = avcodec_find_encoder(AV_CODEC_ID_H264); + m_ffmpeg->codec = ffmpegFunctions()->avcodec_find_encoder(AV_CODEC_ID_H264); if (!m_ffmpeg->codec) { LOGE() << "not found codec"; return false; } - m_ffmpeg->codecCtx = avcodec_alloc_context3(m_ffmpeg->codec); + m_ffmpeg->codecCtx = ffmpegFunctions()->avcodec_alloc_context3(m_ffmpeg->codec); if (m_ffmpeg->codecCtx == nullptr) { LOGE() << "failed to allocate AV context"; return false; @@ -148,7 +146,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 25, 100) m_ffmpeg->codecCtx->b_frame_strategy = 1; #else - av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); + ffmpegFunctions()->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); #endif m_ffmpeg->codecCtx->me_cmp = 1; @@ -157,7 +155,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 49, 100) m_ffmpeg->codecCtx->me_method = ME_HEX; #else - av_opt_set_int(m_ffmpeg->codecCtx, "hex", 1, 0); + ffmpegFunctions()->av_opt_set_int(m_ffmpeg->codecCtx, "hex", 1, 0); #endif m_ffmpeg->codecCtx->qmin = 10; @@ -165,7 +163,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 25, 100) m_ffmpeg->codecCtx->scenechange_threshold = 40; #else - av_opt_set_int(m_ffmpeg->codecCtx, "sc_threshold", 40, 0); + ffmpegFunctions()->av_opt_set_int(m_ffmpeg->codecCtx, "sc_threshold", 40, 0); #endif #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 56, 100) m_ffmpeg->codecCtx->flags |= CODEC_FLAG_LOOP_FILTER; @@ -186,29 +184,31 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign #endif } + //av_dump_format(m_ffmpeg->formatCtx, 0, fileName.c_str(), 1); + // open_video #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) // find the video encoder - m_ffmpeg->codec = avcodec_find_encoder(m_ffmpeg->codecCtx->codec_id); + m_ffmpeg->codec = ffmpegFunctions()->avcodec_find_encoder(m_ffmpeg->codecCtx->codec_id); if (!m_ffmpeg->codec) { LOGE() << "not found codec"; return false; } #else - if (avcodec_parameters_from_context(m_ffmpeg->videoStream->codecpar, m_ffmpeg->codecCtx) < 0) { - avcodec_free_context(&m_ffmpeg->codecCtx); + if (ffmpegFunctions()->avcodec_parameters_from_context(m_ffmpeg->videoStream->codecpar, m_ffmpeg->codecCtx) < 0) { + ffmpegFunctions()->avcodec_free_context(&m_ffmpeg->codecCtx); LOGE() << "failed to set AV parameters from context"; return false; } #endif // open the codec - if (avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, 0) < 0) { + if (ffmpegFunctions()->avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, 0) < 0) { LOGE() << "failed open codec"; return false; } // Allocate the YUV frame - m_ffmpeg->ppicture = av_frame_alloc(); + m_ffmpeg->ppicture = ffmpegFunctions()->av_frame_alloc(); if (!m_ffmpeg->ppicture) { LOGE() << "failed allocate frame"; return false; @@ -219,32 +219,35 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(55, 4, 100) - int size = avpicture_get_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height); + int size = ffmpegFunctions()->avpicture_get_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height); #else - int size = av_image_get_buffer_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height, 1); + int size = ffmpegFunctions()->av_image_get_buffer_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, + m_ffmpeg->codecCtx->height, 1); #endif m_ffmpeg->picture_buf = new uint8_t[size]; if (!m_ffmpeg->picture_buf) { LOGE() << "failed allocate frame buf"; - av_free(m_ffmpeg->ppicture); + ffmpegFunctions()->av_free(m_ffmpeg->ppicture); return false; } // Setup the planes #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(55, 4, 100) - avpicture_fill((AVPicture*)m_ffmpeg->ppicture, m_ffmpeg->picture_buf, m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, - m_ffmpeg->codecCtx->height); + ffmpegFunctions()->avpicture_fill((AVPicture*)m_ffmpeg->ppicture, m_ffmpeg->picture_buf, m_ffmpeg->codecCtx->pix_fmt, + m_ffmpeg->codecCtx->width, + m_ffmpeg->codecCtx->height); #else - av_image_fill_arrays(m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize, m_ffmpeg->picture_buf, m_ffmpeg->codecCtx->pix_fmt, - m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height, 1); + ffmpegFunctions()->av_image_fill_arrays(m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize, m_ffmpeg->picture_buf, + m_ffmpeg->codecCtx->pix_fmt, + m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height, 1); #endif - if (avio_open(&m_ffmpeg->formatCtx->pb, fileName.c_str(), AVIO_FLAG_WRITE) < 0) { + if (ffmpegFunctions()->avio_open(&m_ffmpeg->formatCtx->pb, fileName.c_str(), AVIO_FLAG_WRITE) < 0) { LOGE() << "failed open file: " << fileName; return false; } - int ret = avformat_write_header(m_ffmpeg->formatCtx, NULL); + int ret = ffmpegFunctions()->avformat_write_header(m_ffmpeg->formatCtx, NULL); if (ret < 0) { LOGE() << "failed write AV header"; return false; @@ -261,7 +264,7 @@ void VideoEncoder::close() return; } - int ret = avcodec_send_frame(m_ffmpeg->codecCtx, NULL); + int ret = ffmpegFunctions()->avcodec_send_frame(m_ffmpeg->codecCtx, NULL); if (ret < 0) { LOGE() << "failed to flush encoder buffer"; return; @@ -269,8 +272,8 @@ void VideoEncoder::close() while (true) { #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100) - av_init_packet(&m_ffmpeg->pkt); - int ret = avcodec_receive_packet(m_ffmpeg->codecCtx, &m_ffmpeg->pkt); + ffmpegFunctions()->av_init_packet(&m_ffmpeg->pkt); + int ret = ffmpegFunctions()->avcodec_receive_packet(m_ffmpeg->codecCtx, &m_ffmpeg->pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { @@ -278,19 +281,21 @@ void VideoEncoder::close() return; } - m_ffmpeg->pkt.pts = av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); - m_ffmpeg->pkt.dts = av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt.pts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt.dts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); m_ffmpeg->ptsCounter++; - ret = av_interleaved_write_frame(m_ffmpeg->formatCtx, &m_ffmpeg->pkt); + ret = ffmpegFunctions()->av_interleaved_write_frame(m_ffmpeg->formatCtx, &m_ffmpeg->pkt); if (ret < 0) { return; } - av_packet_unref(&m_ffmpeg->pkt); + ffmpegFunctions()->av_packet_unref(&m_ffmpeg->pkt); #else - m_ffmpeg->pkt = av_packet_alloc(); - int ret = avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); + m_ffmpeg->pkt = ffmpegFunctions()->av_packet_alloc(); + int ret = ffmpegFunctions()->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { @@ -298,27 +303,29 @@ void VideoEncoder::close() return; } - m_ffmpeg->pkt->pts = av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); - m_ffmpeg->pkt->dts = av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt->pts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt->dts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); m_ffmpeg->ptsCounter++; - ret = av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); + ret = ffmpegFunctions()->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); if (ret < 0) { return; } - av_packet_unref(m_ffmpeg->pkt); + ffmpegFunctions()->av_packet_unref(m_ffmpeg->pkt); #endif } - av_write_trailer(m_ffmpeg->formatCtx); + ffmpegFunctions()->av_write_trailer(m_ffmpeg->formatCtx); // close_video #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) - avcodec_close(m_ffmpeg->videoStream->codec); + ffmpegFunctions()->avcodec_close(m_ffmpeg->videoStream->codec); #else - avcodec_free_context(&m_ffmpeg->codecCtx); + ffmpegFunctions()->avcodec_free_context(&m_ffmpeg->codecCtx); #endif if (m_ffmpeg->picture_buf) { @@ -327,7 +334,7 @@ void VideoEncoder::close() } if (m_ffmpeg->ppicture) { - av_free(m_ffmpeg->ppicture); + ffmpegFunctions()->av_free(m_ffmpeg->ppicture); m_ffmpeg->ppicture = 0; } @@ -335,16 +342,16 @@ void VideoEncoder::close() for (unsigned int i = 0; i < m_ffmpeg->formatCtx->nb_streams; i++) { #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) - av_freep(&m_ffmpeg->formatCtx->streams[i]->codec); + ffmpegFunctions()->av_freep(&m_ffmpeg->formatCtx->streams[i]->codec); #endif - av_freep(&m_ffmpeg->formatCtx->streams[i]); + ffmpegFunctions()->av_freep(&m_ffmpeg->formatCtx->streams[i]); } // Close file - avio_close(m_ffmpeg->formatCtx->pb); + ffmpegFunctions()->avio_close(m_ffmpeg->formatCtx->pb); // Free the stream - av_free(m_ffmpeg->formatCtx); + ffmpegFunctions()->av_free(m_ffmpeg->formatCtx); } bool VideoEncoder::encodeImage(const QImage& img) @@ -356,22 +363,22 @@ bool VideoEncoder::encodeImage(const QImage& img) convertImage_sws(img); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 3, 100) - m_ffmpeg->ppicture->pts = av_rescale_q(m_ffmpeg->codecCtx->frame_num, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); + m_ffmpeg->ppicture->pts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->codecCtx->frame_num, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); #else - m_ffmpeg->ppicture->pts = av_rescale_q(m_ffmpeg->codecCtx->frame_number, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); + m_ffmpeg->ppicture->pts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->codecCtx->frame_number, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); #endif - int ret = avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); + int ret = ffmpegFunctions()->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); if (ret < 0) { return false; } while (ret >= 0) { #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100) - av_init_packet(&m_ffmpeg->pkt); - ret = avcodec_receive_packet(m_ffmpeg->codecCtx, &m_ffmpeg->pkt); + ffmpegFunctions()->av_init_packet(&m_ffmpeg->pkt); + ret = ffmpegFunctions()->avcodec_receive_packet(m_ffmpeg->codecCtx, &m_ffmpeg->pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { return 0; } else if (ret < 0) { @@ -379,19 +386,21 @@ bool VideoEncoder::encodeImage(const QImage& img) return false; } - m_ffmpeg->pkt.pts = av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); - m_ffmpeg->pkt.dts = av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt.pts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt.dts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); m_ffmpeg->ptsCounter++; - ret = av_interleaved_write_frame(m_ffmpeg->formatCtx, &m_ffmpeg->pkt); + ret = ffmpegFunctions()->av_interleaved_write_frame(m_ffmpeg->formatCtx, &m_ffmpeg->pkt); if (ret < 0) { return false; } - av_packet_unref(&m_ffmpeg->pkt); + ffmpegFunctions()->av_packet_unref(&m_ffmpeg->pkt); #else - m_ffmpeg->pkt = av_packet_alloc(); - ret = avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); + m_ffmpeg->pkt = ffmpegFunctions()->av_packet_alloc(); + ret = ffmpegFunctions()->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { return 0; } else if (ret < 0) { @@ -399,25 +408,25 @@ bool VideoEncoder::encodeImage(const QImage& img) return false; } - m_ffmpeg->pkt->pts = av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); - m_ffmpeg->pkt->dts = av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt->pts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt->dts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); m_ffmpeg->ptsCounter++; - ret = av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); + ret = ffmpegFunctions()->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); if (ret < 0) { return false; } - av_packet_unref(m_ffmpeg->pkt); + ffmpegFunctions()->av_packet_unref(m_ffmpeg->pkt); #endif } return true; } -bool VideoEncoder::muxAudioVideo(const muse::io::path_t& videoPath, - const muse::io::path_t& audioPath, - const muse::io::path_t& outputPath, +bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& audioPath, const io::path_t& outputPath, double audioOffsetSec) { AVFormatContext* videoFmtCtx = nullptr; @@ -427,43 +436,42 @@ bool VideoEncoder::muxAudioVideo(const muse::io::path_t& videoPath, auto cleanup = [&]() { if (videoFmtCtx) { - avformat_close_input(&videoFmtCtx); + ffmpegFunctions()->avformat_close_input(&videoFmtCtx); } if (audioFmtCtx) { - avformat_close_input(&audioFmtCtx); + ffmpegFunctions()->avformat_close_input(&audioFmtCtx); } if (outputFmtCtx) { if (outputFmtCtx->pb) { - avio_close(outputFmtCtx->pb); + ffmpegFunctions()->avio_close(outputFmtCtx->pb); } - avformat_free_context(outputFmtCtx); + ffmpegFunctions()->avformat_free_context(outputFmtCtx); } }; - if (avformat_open_input(&videoFmtCtx, videoPath.c_str(), nullptr, nullptr) < 0) { + if (ffmpegFunctions()->avformat_open_input(&videoFmtCtx, videoPath.c_str(), nullptr, nullptr) < 0) { LOGE() << "mux: failed to open video input: " << videoPath; cleanup(); return false; } - if (avformat_find_stream_info(videoFmtCtx, nullptr) < 0) { + if (ffmpegFunctions()->avformat_find_stream_info(videoFmtCtx, nullptr) < 0) { LOGE() << "mux: failed to find video stream info"; cleanup(); return false; } - if (avformat_open_input(&audioFmtCtx, audioPath.c_str(), nullptr, nullptr) < 0) { + if (ffmpegFunctions()->avformat_open_input(&audioFmtCtx, audioPath.c_str(), nullptr, nullptr) < 0) { LOGE() << "mux: failed to open audio input: " << audioPath; cleanup(); return false; } - if (avformat_find_stream_info(audioFmtCtx, nullptr) < 0) { + if (ffmpegFunctions()->avformat_find_stream_info(audioFmtCtx, nullptr) < 0) { LOGE() << "mux: failed to find audio stream info"; cleanup(); return false; } - avformat_alloc_output_context2(&outputFmtCtx, nullptr, "mp4", outputPath.c_str()); - if (!outputFmtCtx) { + if (ffmpegFunctions()->avformat_alloc_output_context2(&outputFmtCtx, nullptr, "mp4", outputPath.c_str()) < 0 || !outputFmtCtx) { LOGE() << "mux: failed to allocate output context"; cleanup(); return false; @@ -477,13 +485,13 @@ bool VideoEncoder::muxAudioVideo(const muse::io::path_t& videoPath, for (unsigned i = 0; i < videoFmtCtx->nb_streams; i++) { if (videoFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { videoInIdx = static_cast(i); - AVStream* outStream = avformat_new_stream(outputFmtCtx, nullptr); + AVStream* outStream = ffmpegFunctions()->avformat_new_stream(outputFmtCtx, nullptr); if (!outStream) { LOGE() << "mux: failed to create output video stream"; cleanup(); return false; } - avcodec_parameters_copy(outStream->codecpar, videoFmtCtx->streams[i]->codecpar); + ffmpegFunctions()->avcodec_parameters_copy(outStream->codecpar, videoFmtCtx->streams[i]->codecpar); outStream->codecpar->codec_tag = 0; outStream->time_base = videoFmtCtx->streams[i]->time_base; outVideoIdx = outStream->index; @@ -494,13 +502,13 @@ bool VideoEncoder::muxAudioVideo(const muse::io::path_t& videoPath, for (unsigned i = 0; i < audioFmtCtx->nb_streams; i++) { if (audioFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { audioInIdx = static_cast(i); - AVStream* outStream = avformat_new_stream(outputFmtCtx, nullptr); + AVStream* outStream = ffmpegFunctions()->avformat_new_stream(outputFmtCtx, nullptr); if (!outStream) { LOGE() << "mux: failed to create output audio stream"; cleanup(); return false; } - avcodec_parameters_copy(outStream->codecpar, audioFmtCtx->streams[i]->codecpar); + ffmpegFunctions()->avcodec_parameters_copy(outStream->codecpar, audioFmtCtx->streams[i]->codecpar); outStream->codecpar->codec_tag = 0; outStream->time_base = audioFmtCtx->streams[i]->time_base; outAudioIdx = outStream->index; @@ -514,13 +522,13 @@ bool VideoEncoder::muxAudioVideo(const muse::io::path_t& videoPath, return false; } - if (avio_open(&outputFmtCtx->pb, outputPath.c_str(), AVIO_FLAG_WRITE) < 0) { + if (ffmpegFunctions()->avio_open(&outputFmtCtx->pb, outputPath.c_str(), AVIO_FLAG_WRITE) < 0) { LOGE() << "mux: failed to open output file: " << outputPath; cleanup(); return false; } - if (avformat_write_header(outputFmtCtx, nullptr) < 0) { + if (ffmpegFunctions()->avformat_write_header(outputFmtCtx, nullptr) < 0) { LOGE() << "mux: failed to write header"; cleanup(); return false; @@ -529,40 +537,38 @@ bool VideoEncoder::muxAudioVideo(const muse::io::path_t& videoPath, int64_t audioOffsetPts = 0; { AVStream* audioOutStream = outputFmtCtx->streams[outAudioIdx]; - audioOffsetPts = static_cast(audioOffsetSec * audioOutStream->time_base.den / audioOutStream->time_base.num); + audioOffsetPts = static_cast(audioOffsetSec * audioOutStream->time_base.den + / audioOutStream->time_base.num); } - AVPacket* pkt = av_packet_alloc(); + AVPacket* pkt = ffmpegFunctions()->av_packet_alloc(); - // Copy video packets - while (av_read_frame(videoFmtCtx, pkt) >= 0) { + while (ffmpegFunctions()->av_read_frame(videoFmtCtx, pkt) >= 0) { if (pkt->stream_index == videoInIdx) { pkt->stream_index = outVideoIdx; - av_packet_rescale_ts(pkt, videoFmtCtx->streams[videoInIdx]->time_base, - outputFmtCtx->streams[outVideoIdx]->time_base); + ffmpegFunctions()->av_packet_rescale_ts(pkt, videoFmtCtx->streams[videoInIdx]->time_base, + outputFmtCtx->streams[outVideoIdx]->time_base); pkt->pos = -1; - av_interleaved_write_frame(outputFmtCtx, pkt); + ffmpegFunctions()->av_interleaved_write_frame(outputFmtCtx, pkt); } - av_packet_unref(pkt); + ffmpegFunctions()->av_packet_unref(pkt); } - // Copy audio packets with offset - while (av_read_frame(audioFmtCtx, pkt) >= 0) { + while (ffmpegFunctions()->av_read_frame(audioFmtCtx, pkt) >= 0) { if (pkt->stream_index == audioInIdx) { pkt->stream_index = outAudioIdx; - av_packet_rescale_ts(pkt, audioFmtCtx->streams[audioInIdx]->time_base, - outputFmtCtx->streams[outAudioIdx]->time_base); + ffmpegFunctions()->av_packet_rescale_ts(pkt, audioFmtCtx->streams[audioInIdx]->time_base, + outputFmtCtx->streams[outAudioIdx]->time_base); pkt->pts += audioOffsetPts; pkt->dts += audioOffsetPts; pkt->pos = -1; - av_interleaved_write_frame(outputFmtCtx, pkt); + ffmpegFunctions()->av_interleaved_write_frame(outputFmtCtx, pkt); } - av_packet_unref(pkt); + ffmpegFunctions()->av_packet_unref(pkt); } - av_packet_free(&pkt); - - av_write_trailer(outputFmtCtx); + ffmpegFunctions()->av_packet_free(&pkt); + ffmpegFunctions()->av_write_trailer(outputFmtCtx); ok = true; cleanup(); @@ -582,8 +588,10 @@ bool VideoEncoder::convertImage_sws(const QImage& img) return false; } - m_ffmpeg->img_convert_ctx = sws_getCachedContext(m_ffmpeg->img_convert_ctx, m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_BGRA, - m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); + m_ffmpeg->img_convert_ctx = ffmpegFunctions()->sws_getCachedContext(m_ffmpeg->img_convert_ctx, m_ffmpeg->width, m_ffmpeg->height, + AV_PIX_FMT_BGRA, + m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, + NULL, NULL, NULL); if (!m_ffmpeg->img_convert_ctx) { LOGE() << "failed initialize the conversion context"; @@ -600,7 +608,13 @@ bool VideoEncoder::convertImage_sws(const QImage& img) srcstride[1] = 0; srcstride[2 ]= 0; - sws_scale(m_ffmpeg->img_convert_ctx, srcplanes, srcstride, 0, m_ffmpeg->height, m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize); + ffmpegFunctions()->sws_scale(m_ffmpeg->img_convert_ctx, srcplanes, srcstride, 0, m_ffmpeg->height, m_ffmpeg->ppicture->data, + m_ffmpeg->ppicture->linesize); return true; } + +const FFmpegFunctions* VideoEncoder::ffmpegFunctions() const +{ + return m_ffmpegHandler->functions(); +} diff --git a/src/framework/media/internal/videoencoder.h b/src/framework/media/internal/videoencoder.h index 089047152120c..77a4be8e7238c 100644 --- a/src/framework/media/internal/videoencoder.h +++ b/src/framework/media/internal/videoencoder.h @@ -24,12 +24,16 @@ #include "../ivideoencoder.h" +#include "ffmpegfunctions.h" + +#include "ffmpeglibhandler.h" + namespace muse::media { struct FFmpeg; class VideoEncoder : public IVideoEncoder { public: - VideoEncoder(); + explicit VideoEncoder(const std::shared_ptr& handler); ~VideoEncoder() override; bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; @@ -41,7 +45,9 @@ class VideoEncoder : public IVideoEncoder private: bool convertImage_sws(const QImage& img); + const FFmpegFunctions* ffmpegFunctions() const; + std::shared_ptr m_ffmpegHandler = nullptr; FFmpeg* m_ffmpeg = nullptr; }; } diff --git a/src/framework/media/internal/videoencoderresolver.cpp b/src/framework/media/internal/videoencoderresolver.cpp new file mode 100644 index 0000000000000..2ae6cdda7edc7 --- /dev/null +++ b/src/framework/media/internal/videoencoderresolver.cpp @@ -0,0 +1,54 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "videoencoderresolver.h" + +#include "ffmpegloader.h" +#include "videoencoder.h" + +using namespace muse::media; + +void VideoEncoderResolver::init() +{ + loadFFmpeg(configuration()->ffmpegLibsDir()); +} + +void VideoEncoderResolver::loadFFmpeg(const io::path_t& ffmpegLibsDir) +{ + auto ffmpegLibHandler = FFmpegLoader::load(ffmpegLibsDir); + if (!ffmpegLibHandler) { + return; + } + + std::shared_ptr encoder = std::make_shared(ffmpegLibHandler); + setCurrentVideoEncoder(encoder); +} + +IVideoEncoderPtr VideoEncoderResolver::currentVideoEncoder() const +{ + return m_encoder; +} + +void VideoEncoderResolver::setCurrentVideoEncoder(IVideoEncoderPtr encoder) +{ + m_encoder = std::move(encoder); +} diff --git a/src/framework/media/internal/videoencoderresolver.h b/src/framework/media/internal/videoencoderresolver.h new file mode 100644 index 0000000000000..5a5a656c25632 --- /dev/null +++ b/src/framework/media/internal/videoencoderresolver.h @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "modularity/ioc.h" +#include "imediaconfiguration.h" + +#include "../ivideoencoderresolver.h" + +namespace muse::media { +class VideoEncoderResolver : public IVideoEncoderResolver +{ + GlobalInject configuration; + +public: + void init(); + + void loadFFmpeg(const muse::io::path_t& ffmpegLibsDir) override; + + IVideoEncoderPtr currentVideoEncoder() const override; + void setCurrentVideoEncoder(IVideoEncoderPtr encoder) override; + +private: + IVideoEncoderPtr m_encoder; +}; +} diff --git a/src/framework/media/ivideoencoder.h b/src/framework/media/ivideoencoder.h index 0a37b9c8c63af..788dc84577321 100644 --- a/src/framework/media/ivideoencoder.h +++ b/src/framework/media/ivideoencoder.h @@ -29,7 +29,7 @@ #include "modularity/imoduleinterface.h" namespace muse::media { -class IVideoEncoder : MODULE_GLOBAL_INTERFACE +class IVideoEncoder : MODULE_CONTEXT_INTERFACE { INTERFACE_ID(IVideoEncoder) @@ -42,4 +42,5 @@ class IVideoEncoder : MODULE_GLOBAL_INTERFACE virtual bool muxAudioVideo(const muse::io::path_t& videoPath, const muse::io::path_t& audioPath, const muse::io::path_t& outputPath, double audioOffsetSec) = 0; }; +using IVideoEncoderPtr = std::shared_ptr; } diff --git a/src/framework/media/internal/ffmpeg.h b/src/framework/media/ivideoencoderresolver.h similarity index 67% rename from src/framework/media/internal/ffmpeg.h rename to src/framework/media/ivideoencoderresolver.h index feb99c3552850..46eb9cc780c9c 100644 --- a/src/framework/media/internal/ffmpeg.h +++ b/src/framework/media/ivideoencoderresolver.h @@ -22,17 +22,19 @@ #pragma once -#include +#include "modularity/imoduleinterface.h" -extern "C" { -#include "libavcodec/avcodec.h" -#include "libavformat/avformat.h" -#include "libavutil/mathematics.h" -#include "libavutil/rational.h" -#include "libavutil/avstring.h" -#include "libavutil/opt.h" -#include "libswscale/swscale.h" -#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(54, 6, 100) -#include "libavutil/imgutils.h" -#endif +#include "ivideoencoder.h" + +namespace muse::media { +class IVideoEncoderResolver : MODULE_CONTEXT_INTERFACE +{ + INTERFACE_ID(IVideoEncoderResolver) + +public: + virtual ~IVideoEncoderResolver() = default; + + virtual IVideoEncoderPtr currentVideoEncoder() const = 0; + virtual void setCurrentVideoEncoder(IVideoEncoderPtr encoder) = 0; +}; } diff --git a/src/framework/media/mediamodule.cpp b/src/framework/media/mediamodule.cpp index 1242c37ea7561..5a6b9f84d3843 100644 --- a/src/framework/media/mediamodule.cpp +++ b/src/framework/media/mediamodule.cpp @@ -23,7 +23,10 @@ #include "modularity/ioc.h" -#include "internal/videoencoder.h" +#include "imediaconfiguration.h" +#include "ivideoencoderresolver.h" +#include "internal/mediaconfiguration.h" +#include "internal/videoencoderresolver.h" using namespace muse::media; using namespace muse::modularity; @@ -35,5 +38,15 @@ std::string MediaModule::moduleName() const void MediaModule::registerExports() { - ioc()->registerExport(moduleName(), std::make_shared()); + m_configuration = std::make_shared(iocContext()); + m_videoEncoderResolver = std::make_shared(); + + ioc()->registerExport(moduleName(), m_configuration); + ioc()->registerExport(moduleName(), m_videoEncoderResolver); +} + +void MediaModule::onInit(const IApplication::RunMode&) +{ + m_configuration->init(); + m_videoEncoderResolver->init(); } diff --git a/src/framework/media/mediamodule.h b/src/framework/media/mediamodule.h index 2fc6af2c3b39d..dd3cf10912fc1 100644 --- a/src/framework/media/mediamodule.h +++ b/src/framework/media/mediamodule.h @@ -25,11 +25,19 @@ #include "modularity/imodulesetup.h" namespace muse::media { +class MediaConfiguration; +class VideoEncoderResolver; + class MediaModule : public modularity::IModuleSetup { public: std::string moduleName() const override; void registerExports() override; + void onInit(const IApplication::RunMode& mode) override; + +private: + std::shared_ptr m_configuration; + std::shared_ptr m_videoEncoderResolver; }; } diff --git a/src/framework/stubs/media/CMakeLists.txt b/src/framework/stubs/media/CMakeLists.txt index fd3eb94641a1a..2fc33b5c0a6cf 100644 --- a/src/framework/stubs/media/CMakeLists.txt +++ b/src/framework/stubs/media/CMakeLists.txt @@ -25,4 +25,5 @@ target_sources(muse_media PRIVATE mediastubmodule.h videoencoderstub.cpp videoencoderstub.h + ../../media/internal/videoencoderresolver.cpp ) diff --git a/src/framework/stubs/media/mediastubmodule.cpp b/src/framework/stubs/media/mediastubmodule.cpp index 9827af972e3df..ba8e2bbdff6ef 100644 --- a/src/framework/stubs/media/mediastubmodule.cpp +++ b/src/framework/stubs/media/mediastubmodule.cpp @@ -22,6 +22,8 @@ #include "mediastubmodule.h" #include "framework/media/ivideoencoder.h" +#include "framework/media/ivideoencoderresolver.h" +#include "framework/media/internal/videoencoderresolver.h" #include "modularity/ioc.h" #include "videoencoderstub.h" @@ -36,5 +38,10 @@ std::string MediaModule::moduleName() const void MediaModule::registerExports() { - ioc()->registerExport(moduleName(), std::make_shared()); + auto videoEncoderStub = std::make_shared(); + auto videoEncodeResolver = std::make_shared(); + videoEncodeResolver->setCurrentVideoEncoder(videoEncoderStub); + + ioc()->registerExport(moduleName(), videoEncoderStub); + ioc()->registerExport(moduleName(), videoEncodeResolver); } diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index ce299b385a8d3..3ed9f36f72f8a 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -103,7 +103,7 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, if (withAudio) { if (result && m_audioRet) { - if (!videoEncoder()->muxAudioVideo(tempVideoPath, tempAudioPath, finalPath, cfg.leadingSec)) { + if (!videoEncodeResolver()->currentVideoEncoder()->muxAudioVideo(tempVideoPath, tempAudioPath, finalPath, cfg.leadingSec)) { result = make_ret(muse::Ret::Code::UnknownError); } } else if (!result) { @@ -315,7 +315,8 @@ void VideoWriter::restoreScore(INotationPtr notation, const ScoreRestoreData& da void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& filePath, const Config& config) { - if (!videoEncoder()->open(filePath, config.width, config.height, config.bitrate, config.fps / 2, config.fps)) { + if (!videoEncodeResolver()->currentVideoEncoder()->open(filePath, config.width, config.height, config.bitrate, config.fps / 2, + config.fps)) { LOGE() << "failed open encoder"; m_writeRet = make_ret(muse::Ret::Code::UnknownError); m_isCompleted = true; @@ -378,7 +379,7 @@ void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& file for (int f = 0; f < frameCount; f++) { if (m_abort) { - videoEncoder()->close(); + videoEncodeResolver()->currentVideoEncoder()->close(); m_writeRet = make_ret(muse::Ret::Code::Cancel); m_progress.finish(make_ret(muse::Ret::Code::Cancel)); return; @@ -419,10 +420,10 @@ void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& file painter.fillRect(cursorAbsRect, CURSOR_COLOR); - videoEncoder()->encodeImage(frame); + videoEncodeResolver()->currentVideoEncoder()->encodeImage(frame); } - videoEncoder()->close(); + videoEncodeResolver()->currentVideoEncoder()->close(); m_writeRet = muse::make_ok(); m_progress.finish(muse::make_ok()); diff --git a/src/importexport/videoexport/internal/videowriter.h b/src/importexport/videoexport/internal/videowriter.h index c8c8526f0881a..eec5f82a98f57 100644 --- a/src/importexport/videoexport/internal/videowriter.h +++ b/src/importexport/videoexport/internal/videowriter.h @@ -28,7 +28,7 @@ #include "modularity/ioc.h" #include "global/iapplication.h" -#include "media/ivideoencoder.h" +#include "media/ivideoencoderresolver.h" #include "../ivideoexportconfiguration.h" #include "project/inotationwriter.h" @@ -41,7 +41,7 @@ class VideoWriter : public project::INotationWriter, public muse::Contextable, p { muse::GlobalInject configuration; muse::ContextInject application = { this }; - muse::ContextInject videoEncoder = { this }; + muse::ContextInject videoEncodeResolver = { this }; muse::ContextInject writers = { this }; public: From 29cdcd6fbd4d504a1192ca8d57c96feae79eff1c Mon Sep 17 00:00:00 2001 From: Eism Date: Thu, 5 Mar 2026 18:02:42 +0200 Subject: [PATCH 13/52] added ffmpeg library setting --- .../media/internal/ffmpegfunctions.cpp | 2 - .../media/internal/ffmpegfunctions.h | 40 ++++---- .../media/internal/ffmpeglibhandler.cpp | 2 + .../media/internal/ffmpeglibhandler.h | 2 + src/framework/media/internal/ffmpegutils.h | 2 +- .../media/internal/videoencoderresolver.cpp | 25 +++++ .../media/internal/videoencoderresolver.h | 9 +- src/framework/media/ivideoencoderresolver.h | 8 ++ .../stubs/media/videoencoderstub.cpp | 2 +- src/framework/stubs/media/videoencoderstub.h | 3 +- .../qml/MuseScore/Preferences/CMakeLists.txt | 1 + .../Preferences/FoldersPreferencesPage.qml | 12 +++ .../Preferences/folderspreferencesmodel.cpp | 25 +++++ .../Preferences/folderspreferencesmodel.h | 17 +++- .../Preferences/internal/FFmpegSection.qml | 91 +++++++++++++++++++ 15 files changed, 209 insertions(+), 32 deletions(-) create mode 100644 src/preferences/qml/MuseScore/Preferences/internal/FFmpegSection.qml diff --git a/src/framework/media/internal/ffmpegfunctions.cpp b/src/framework/media/internal/ffmpegfunctions.cpp index af2b2316bbde1..0319b94802788 100644 --- a/src/framework/media/internal/ffmpegfunctions.cpp +++ b/src/framework/media/internal/ffmpegfunctions.cpp @@ -23,7 +23,6 @@ #include "ffmpegfunctions.h" namespace muse::media { - bool FFmpegFunctions::isValid() const { return av_free && av_freep && av_rescale_q @@ -42,5 +41,4 @@ bool FFmpegFunctions::isValid() const && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts && sws_getCachedContext && sws_scale; } - } diff --git a/src/framework/media/internal/ffmpegfunctions.h b/src/framework/media/internal/ffmpegfunctions.h index 9d92f64b0508e..3296bb01cad0d 100644 --- a/src/framework/media/internal/ffmpegfunctions.h +++ b/src/framework/media/internal/ffmpegfunctions.h @@ -29,7 +29,6 @@ extern "C" { } namespace muse::media { - struct FFmpegFunctions { // libavutil @@ -38,37 +37,34 @@ struct FFmpegFunctions int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; // libavutil (imgutils) - int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], - const uint8_t* src, AVPixelFormat pix_fmt, - int width, int height, int align) = nullptr; + int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, + int align) = nullptr; int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; // libavutil (opt) int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; // libavformat - const AVOutputFormat* (*av_guess_format)(const char* short_name, const char* filename, - const char* mime_type) = nullptr; - AVFormatContext* (*avformat_alloc_context)(void) = nullptr; - AVStream* (*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; + const AVOutputFormat*(*av_guess_format)(const char* short_name, const char* filename, const char* mime_type) = nullptr; + AVFormatContext*(*avformat_alloc_context)(void) = nullptr; + AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; int (*av_write_trailer)(AVFormatContext* s) = nullptr; int (*avio_open)(AVIOContext** s, const char* url, int flags) = nullptr; int (*avio_close)(AVIOContext* s) = nullptr; int (*av_interleaved_write_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; - int (*avformat_open_input)(AVFormatContext** ctx, const char* url, - const AVInputFormat* fmt, AVDictionary** options) = nullptr; + int (*avformat_open_input)(AVFormatContext** ctx, const char* url, const AVInputFormat* fmt, AVDictionary** options) = nullptr; int (*avformat_find_stream_info)(AVFormatContext* ic, AVDictionary** options) = nullptr; void (*avformat_close_input)(AVFormatContext** s) = nullptr; void (*avformat_free_context)(AVFormatContext* s) = nullptr; - int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, - const char* format_name, const char* filename) = nullptr; + int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, const char* format_name, + const char* filename) = nullptr; int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; // libavcodec - AVCodecContext* (*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; - const AVCodec* (*avcodec_find_encoder)(AVCodecID id) = nullptr; + AVCodecContext*(*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; + const AVCodec*(*avcodec_find_encoder)(AVCodecID id) = nullptr; void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; @@ -77,25 +73,21 @@ struct FFmpegFunctions int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; // libavutil (frame) - AVFrame* (*av_frame_alloc)(void) = nullptr; + AVFrame*(*av_frame_alloc)(void) = nullptr; // libavcodec (packet) - AVPacket* (*av_packet_alloc)(void) = nullptr; + AVPacket*(*av_packet_alloc)(void) = nullptr; void (*av_packet_free)(AVPacket** pkt) = nullptr; void (*av_packet_unref)(AVPacket* pkt) = nullptr; void (*av_packet_rescale_ts)(AVPacket* pkt, AVRational tb_src, AVRational tb_dst) = nullptr; // libswscale - SwsContext* (*sws_getCachedContext)(SwsContext* context, int srcW, int srcH, - AVPixelFormat srcFormat, int dstW, int dstH, - AVPixelFormat dstFormat, int flags, - SwsFilter* srcFilter, SwsFilter* dstFilter, - const double* param) = nullptr; - int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], - const int srcStride[], int srcSliceY, int srcSliceH, + SwsContext*(*sws_getCachedContext)(SwsContext* context, int srcW, int srcH, AVPixelFormat srcFormat, int dstW, int dstH, + AVPixelFormat dstFormat, int flags, SwsFilter* srcFilter, SwsFilter* dstFilter, + const double* param) = nullptr; + int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]) = nullptr; bool isValid() const; }; - } diff --git a/src/framework/media/internal/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeglibhandler.cpp index d047fe1bdd1e6..5688181166cc1 100644 --- a/src/framework/media/internal/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeglibhandler.cpp @@ -167,6 +167,7 @@ bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& a } m_version = versionFromAVFormatPath(avFormatPath); + m_dir = io::dirpath(avFormatPath); LOGI() << "FFmpeg loaded: avutil=" << avUtilPath << ", avcodec=" << avCodecPath << ", avformat=" << avFormatPath << ", swscale=" << swScalePath; @@ -183,6 +184,7 @@ void FFmpegLibHandler::unload() m_functions = FFmpegFunctions(); m_version = 0; + m_dir = io::path_t(); } void FFmpegLibHandler::closeLib(void*& lib) diff --git a/src/framework/media/internal/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeglibhandler.h index b592f1d2524df..78eee6b6c62b8 100644 --- a/src/framework/media/internal/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeglibhandler.h @@ -39,6 +39,7 @@ class FFmpegLibHandler const FFmpegFunctions* functions() const { return &m_functions; } int version() const { return m_version; } + io::path_t dir() const { return m_dir; } private: void* getSymbol(void* lib, const char* name) const; @@ -53,5 +54,6 @@ class FFmpegLibHandler FFmpegFunctions m_functions; int m_version = 0; + io::path_t m_dir; }; } diff --git a/src/framework/media/internal/ffmpegutils.h b/src/framework/media/internal/ffmpegutils.h index e2c4b4bb3adae..ab8e0954aa4ae 100644 --- a/src/framework/media/internal/ffmpegutils.h +++ b/src/framework/media/internal/ffmpegutils.h @@ -35,7 +35,7 @@ struct FFmpegVersionInfo { } }; -static const std::vector> FFMPEG_COMPONENTS_VERSIONS = { +static const std::vector > FFMPEG_COMPONENTS_VERSIONS = { { 8, { 62, 60, 62, 9 } }, { 7, { 61, 59, 61, 8 } }, { 6, { 60, 58, 60, 7 } }, diff --git a/src/framework/media/internal/videoencoderresolver.cpp b/src/framework/media/internal/videoencoderresolver.cpp index 2ae6cdda7edc7..df672e261f330 100644 --- a/src/framework/media/internal/videoencoderresolver.cpp +++ b/src/framework/media/internal/videoencoderresolver.cpp @@ -34,6 +34,11 @@ void VideoEncoderResolver::init() void VideoEncoderResolver::loadFFmpeg(const io::path_t& ffmpegLibsDir) { + if (m_encoder) { + m_currentEncoderFFmpegVersion = -1; + configuration()->setFFmpegLibsDir({}); + } + auto ffmpegLibHandler = FFmpegLoader::load(ffmpegLibsDir); if (!ffmpegLibHandler) { return; @@ -41,6 +46,26 @@ void VideoEncoderResolver::loadFFmpeg(const io::path_t& ffmpegLibsDir) std::shared_ptr encoder = std::make_shared(ffmpegLibHandler); setCurrentVideoEncoder(encoder); + + configuration()->setFFmpegLibsDir(ffmpegLibHandler->dir()); + + m_currentEncoderFFmpegVersion = ffmpegLibHandler->version(); + m_loadedFFmpegChanged.notify(); +} + +muse::io::path_t VideoEncoderResolver::loadedFFmpegDir() const +{ + return configuration()->ffmpegLibsDir(); +} + +int VideoEncoderResolver::loadedFFmpegVersion() const +{ + return m_currentEncoderFFmpegVersion; +} + +muse::async::Notification VideoEncoderResolver::loadedFFmpegChanged() const +{ + return m_loadedFFmpegChanged; } IVideoEncoderPtr VideoEncoderResolver::currentVideoEncoder() const diff --git a/src/framework/media/internal/videoencoderresolver.h b/src/framework/media/internal/videoencoderresolver.h index 5a5a656c25632..d96aa0bc99ec1 100644 --- a/src/framework/media/internal/videoencoderresolver.h +++ b/src/framework/media/internal/videoencoderresolver.h @@ -23,12 +23,13 @@ #pragma once #include "modularity/ioc.h" +#include "async/asyncable.h" #include "imediaconfiguration.h" #include "../ivideoencoderresolver.h" namespace muse::media { -class VideoEncoderResolver : public IVideoEncoderResolver +class VideoEncoderResolver : public IVideoEncoderResolver, public muse::async::Asyncable { GlobalInject configuration; @@ -36,11 +37,17 @@ class VideoEncoderResolver : public IVideoEncoderResolver void init(); void loadFFmpeg(const muse::io::path_t& ffmpegLibsDir) override; + io::path_t loadedFFmpegDir() const override; + int loadedFFmpegVersion() const override; + async::Notification loadedFFmpegChanged() const override; IVideoEncoderPtr currentVideoEncoder() const override; void setCurrentVideoEncoder(IVideoEncoderPtr encoder) override; private: IVideoEncoderPtr m_encoder; + int m_currentEncoderFFmpegVersion = -1; + + async::Notification m_loadedFFmpegChanged; }; } diff --git a/src/framework/media/ivideoencoderresolver.h b/src/framework/media/ivideoencoderresolver.h index 46eb9cc780c9c..f2a96cffa7112 100644 --- a/src/framework/media/ivideoencoderresolver.h +++ b/src/framework/media/ivideoencoderresolver.h @@ -22,6 +22,9 @@ #pragma once +#include "io/path.h" +#include "async/notification.h" + #include "modularity/imoduleinterface.h" #include "ivideoencoder.h" @@ -34,6 +37,11 @@ class IVideoEncoderResolver : MODULE_CONTEXT_INTERFACE public: virtual ~IVideoEncoderResolver() = default; + virtual void loadFFmpeg(const muse::io::path_t& ffmpegLibsDir) = 0; + virtual io::path_t loadedFFmpegDir() const = 0; + virtual int loadedFFmpegVersion() const = 0; + virtual async::Notification loadedFFmpegChanged() const = 0; + virtual IVideoEncoderPtr currentVideoEncoder() const = 0; virtual void setCurrentVideoEncoder(IVideoEncoderPtr encoder) = 0; }; diff --git a/src/framework/stubs/media/videoencoderstub.cpp b/src/framework/stubs/media/videoencoderstub.cpp index 3aaf1f3874c77..e756100b3057a 100644 --- a/src/framework/stubs/media/videoencoderstub.cpp +++ b/src/framework/stubs/media/videoencoderstub.cpp @@ -38,7 +38,7 @@ bool VideoEncoderStub::encodeImage(const QImage&) } bool VideoEncoderStub::muxAudioVideo(const muse::io::path_t&, const muse::io::path_t&, - const muse::io::path_t&, double) + const muse::io::path_t&, double) { return false; } diff --git a/src/framework/stubs/media/videoencoderstub.h b/src/framework/stubs/media/videoencoderstub.h index 343ea918671cd..a02668190a04a 100644 --- a/src/framework/stubs/media/videoencoderstub.h +++ b/src/framework/stubs/media/videoencoderstub.h @@ -33,7 +33,6 @@ class VideoEncoderStub : public IVideoEncoder bool open(const muse::io::path_t&, unsigned, unsigned, unsigned, unsigned, unsigned) override; void close() override; bool encodeImage(const QImage&) override; - bool muxAudioVideo(const muse::io::path_t&, const muse::io::path_t&, const muse::io::path_t&, - double) override; + bool muxAudioVideo(const muse::io::path_t&, const muse::io::path_t&, const muse::io::path_t&, double) override; }; } diff --git a/src/preferences/qml/MuseScore/Preferences/CMakeLists.txt b/src/preferences/qml/MuseScore/Preferences/CMakeLists.txt index f7aa442d57d19..6d8d9d3be2b8f 100644 --- a/src/preferences/qml/MuseScore/Preferences/CMakeLists.txt +++ b/src/preferences/qml/MuseScore/Preferences/CMakeLists.txt @@ -94,6 +94,7 @@ qt_add_qml_module(preferences_qml internal/CommonAudioApiConfiguration.qml internal/DefaultStyleSection.qml internal/FoldersSection.qml + internal/FFmpegSection.qml internal/ImportStyleSection.qml internal/IncrementalPropertyControlWithTitle.qml internal/KeyboardLayoutsSection.qml diff --git a/src/preferences/qml/MuseScore/Preferences/FoldersPreferencesPage.qml b/src/preferences/qml/MuseScore/Preferences/FoldersPreferencesPage.qml index 037fd3fe46e67..71c8743979a9f 100644 --- a/src/preferences/qml/MuseScore/Preferences/FoldersPreferencesPage.qml +++ b/src/preferences/qml/MuseScore/Preferences/FoldersPreferencesPage.qml @@ -20,6 +20,7 @@ * along with this program. If not, see . */ import QtQuick +import QtQuick.Layouts import Muse.UiComponents import MuseScore.Preferences @@ -42,10 +43,21 @@ PreferencesPage { spacing: root.sectionsSpacing FoldersSection { + id: generalFoldersSection + model: foldersPreferencesModel navigation.section: root.navigationSection navigation.order: root.navigationOrderStart + 1 } + + FFmpegSection { + id: ffmpegSection + + model: foldersPreferencesModel + + navigation.section: root.navigationSection + navigation.order: generalFoldersSection.navigation.order + 1 + } } } diff --git a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp index 3fbff42327949..866dda0043fef 100644 --- a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp +++ b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp @@ -165,6 +165,12 @@ void FoldersPreferencesModel::setupConnections() vstConfiguration()->userVstDirectoriesChanged().onReceive(this, [this](const io::paths_t& paths) { setFolderPaths(FolderType::VST3, pathsToString(paths)); }); + + videoEncoderResolver()->loadedFFmpegChanged().onNotify(this, [this]() { + emit ffmpegDirChanged(); + }); + + emit ffmpegDirChanged(); } void FoldersPreferencesModel::saveFolderPaths(FoldersPreferencesModel::FolderType folderType, const QString& paths) @@ -244,3 +250,22 @@ io::paths_t FoldersPreferencesModel::pathsFromString(const QString& pathsStr) co { return io::pathsFromString(pathsStr.toStdString()); } + +int FoldersPreferencesModel::ffmpegVersion() const +{ + return videoEncoderResolver()->loadedFFmpegVersion(); +} + +QString FoldersPreferencesModel::ffmpegDir() const +{ + return videoEncoderResolver()->loadedFFmpegDir().toQString(); +} + +void FoldersPreferencesModel::setFFmpegDir(const QString& dir) +{ + if (mediaConfiguration()->ffmpegLibsDir() == dir) { + return; + } + + videoEncoderResolver()->loadFFmpeg(dir); +} diff --git a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h index dd2c09728ef05..7194d032fe347 100644 --- a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h +++ b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h @@ -33,7 +33,8 @@ #include "extensions/iextensionsconfiguration.h" #include "audio/main/iaudioconfiguration.h" #include "vst/ivstconfiguration.h" -#include "appshell/iappshellconfiguration.h" +#include "media/imediaconfiguration.h" +#include "media/ivideoencoderresolver.h" namespace mu::preferences { class FoldersPreferencesModel : public QAbstractListModel, public muse::Contextable, public muse::async::Asyncable @@ -47,6 +48,11 @@ class FoldersPreferencesModel : public QAbstractListModel, public muse::Contexta muse::GlobalInject extensionsConfiguration; muse::GlobalInject audioConfiguration; muse::GlobalInject vstConfiguration; + muse::GlobalInject mediaConfiguration; + muse::ContextInject videoEncoderResolver = { this }; + + Q_PROPERTY(int ffmpegVersion READ ffmpegVersion NOTIFY ffmpegVersionChanged FINAL) + Q_PROPERTY(QString ffmpegDir READ ffmpegDir WRITE setFFmpegDir NOTIFY ffmpegDirChanged FINAL) public: explicit FoldersPreferencesModel(QObject* parent = nullptr); @@ -58,6 +64,15 @@ class FoldersPreferencesModel : public QAbstractListModel, public muse::Contexta Q_INVOKABLE void load(); + int ffmpegVersion() const; + + QString ffmpegDir() const; + void setFFmpegDir(const QString& dir); + +signals: + void ffmpegVersionChanged(); + void ffmpegDirChanged(); + private: void setupConnections(); diff --git a/src/preferences/qml/MuseScore/Preferences/internal/FFmpegSection.qml b/src/preferences/qml/MuseScore/Preferences/internal/FFmpegSection.qml new file mode 100644 index 0000000000000..6957930211e5a --- /dev/null +++ b/src/preferences/qml/MuseScore/Preferences/internal/FFmpegSection.qml @@ -0,0 +1,91 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import QtQuick +import QtQuick.Layouts + +import Muse.UiComponents + +BaseSection { + id: root + + title: qsTrc("preferences", "FFmpeg") + + property var model: null + + visible: model ? model.showFFmpegSection : false + + ColumnLayout { + width: parent.width + height: 30 + + spacing: 20 + + StyledTextLabel { + id: titleLabel + Layout.fillWidth: true + text: qsTrc("preferences", "Version:") + " " + (model && model.ffmpegVersion !== -1 + ? model.ffmpegVersion + : qsTrc("preferences", "FFmpeg library not found")) + horizontalAlignment: Text.AlignLeft + } + + RowLayout { + Layout.fillWidth: true + height: 30 + + spacing: root.columnSpacing + + FilePicker { + id: ffmpegDirPicker + Layout.fillWidth: true + + pickerType: FilePicker.PickerType.Directory + dialogTitle: qsTrc("preferences", "Choose %1 folder").arg(root.title) + + dir: model ? model.ffmpegDir : "" + path: model ? model.ffmpegDir : "" + + navigation: root.navigation + pathFieldTitle: titleLabel.text + + onPathEdited: function(newPath) { + if (model) { + model.ffmpegDir = newPath + } + } + } + + FlatButton { + text: qsTrc("preferences", "Download FFmpeg") + isNarrow: true + + navigation.panel: root.navigation + navigation.row: ffmpegDirPicker.navigationRowOrderStart + navigation.column: 100 + + onClicked: { + api.launcher.openUrl("https://support.audacityteam.org/basics/installing-ffmpeg") // todo + } + } + } + } +} From e889935c357f9733c2c3b1beeb7e41a865c2fc1e Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 11:11:29 +0200 Subject: [PATCH 14/52] enabled video export module by default --- CMakeLists.txt | 2 +- ninja_build.sh | 3 --- .../media/internal/videoencoderresolver.cpp | 12 +++++---- .../media/internal/videoencoderresolver.h | 2 ++ .../Preferences/folderspreferencesmodel.cpp | 5 ++++ .../Preferences/folderspreferencesmodel.h | 8 +++++- .../internal/Export/exportdialogmodel.cpp | 25 +++++++------------ .../internal/Export/exportdialogmodel.h | 6 ++--- 8 files changed, 33 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e127b89f710d..04702dcbc0a85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ option(MUE_BUILD_IMPEXP_AUDIOEXPORT_MODULE "Build importexport audioexport modul option(MUE_BUILD_IMPEXP_IMAGESEXPORT_MODULE "Build importexport imagesexport module" ON) option(MUE_BUILD_IMPEXP_GUITARPRO_MODULE "Build importexport guitarpro module" ON) option(MUE_BUILD_IMPEXP_MEI_MODULE "Build importexport mei module" ON) -option(MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE "Build importexport videoexport module" OFF) +option(MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE "Build importexport videoexport module" ON) option(MUE_BUILD_IMPEXP_TABLEDIT_MODULE "Build importexport tabledit module" ON) option(MUE_BUILD_IMPEXP_LYRICS_MODULE "Build importexport lyrics module" ON) diff --git a/ninja_build.sh b/ninja_build.sh index 1bdbd67b29269..f0e361744d634 100755 --- a/ninja_build.sh +++ b/ninja_build.sh @@ -46,7 +46,6 @@ MUSESCORE_ENABLE_CODE_COVERAGE=${MUSESCORE_UNIT_TESTS_ENABLE_CODE_COVERAGE:-"OFF MUSESCORE_NO_RPATH=${MUSESCORE_NO_RPATH:-"OFF"} MUSESCORE_MODULE_UPDATE=${MUSESCORE_MODULE_UPDATE:-"ON"} MUSESCORE_BUILD_VST_MODULE=${MUSESCORE_BUILD_VST_MODULE:-"OFF"} -MUSESCORE_BUILD_IMPEXP_VIDEOEXPORT_MODULE=${MUSESCORE_BUILD_IMPEXP_VIDEOEXPORT_MODULE:-"OFF"} MUSESCORE_BUILD_WEBSOCKET=${MUSESCORE_BUILD_WEBSOCKET:-"OFF"} MUSESCORE_BUILD_PIPEWIRE_AUDIO_DRIVER=${MUSESCORE_BUILD_PIPEWIRE_AUDIO_DRIVER:-"OFF"} MUSESCORE_COMPILE_USE_UNITY=${MUSESCORE_COMPILE_USE_UNITY:-"ON"} @@ -92,7 +91,6 @@ function do_build() { -DCMAKE_BUILD_NUMBER="${MUSESCORE_BUILD_NUMBER}" \ -DMUSESCORE_REVISION="${MUSESCORE_REVISION}" \ -DMUE_RUN_LRELEASE="${MUSESCORE_RUN_LRELEASE}" \ - -DMUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE="${MUSESCORE_BUILD_IMPEXP_VIDEOEXPORT_MODULE}" \ -DMUSE_MODULE_UPDATE="${MUSESCORE_MODULE_UPDATE}" \ -DMUE_DOWNLOAD_SOUNDFONT="${MUSESCORE_DOWNLOAD_SOUNDFONT}" \ -DMUSE_ENABLE_UNIT_TESTS="${MUSESCORE_BUILD_UNIT_TESTS}" \ @@ -170,7 +168,6 @@ case $TARGET in -DCMAKE_BUILD_NUMBER="${MUSESCORE_BUILD_NUMBER}" \ -DMUSESCORE_REVISION="${MUSESCORE_REVISION}" \ -DMUE_RUN_LRELEASE="${MUSESCORE_RUN_LRELEASE}" \ - -DMUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE="${MUSESCORE_BUILD_IMPEXP_VIDEOEXPORT_MODULE}" \ -DMUSE_MODULE_UPDATE="${MUSESCORE_MODULE_UPDATE}" \ -DMUE_DOWNLOAD_SOUNDFONT="${MUSESCORE_DOWNLOAD_SOUNDFONT}" \ -DMUSE_ENABLE_UNIT_TESTS="${MUSESCORE_BUILD_UNIT_TESTS}" \ diff --git a/src/framework/media/internal/videoencoderresolver.cpp b/src/framework/media/internal/videoencoderresolver.cpp index df672e261f330..fe82e66e1c574 100644 --- a/src/framework/media/internal/videoencoderresolver.cpp +++ b/src/framework/media/internal/videoencoderresolver.cpp @@ -34,13 +34,9 @@ void VideoEncoderResolver::init() void VideoEncoderResolver::loadFFmpeg(const io::path_t& ffmpegLibsDir) { - if (m_encoder) { - m_currentEncoderFFmpegVersion = -1; - configuration()->setFFmpegLibsDir({}); - } - auto ffmpegLibHandler = FFmpegLoader::load(ffmpegLibsDir); if (!ffmpegLibHandler) { + resetFFmpegSettings(); return; } @@ -77,3 +73,9 @@ void VideoEncoderResolver::setCurrentVideoEncoder(IVideoEncoderPtr encoder) { m_encoder = std::move(encoder); } + +void VideoEncoderResolver::resetFFmpegSettings() +{ + m_currentEncoderFFmpegVersion = -1; + configuration()->setFFmpegLibsDir({}); +} diff --git a/src/framework/media/internal/videoencoderresolver.h b/src/framework/media/internal/videoencoderresolver.h index d96aa0bc99ec1..094c737421c71 100644 --- a/src/framework/media/internal/videoencoderresolver.h +++ b/src/framework/media/internal/videoencoderresolver.h @@ -45,6 +45,8 @@ class VideoEncoderResolver : public IVideoEncoderResolver, public muse::async::A void setCurrentVideoEncoder(IVideoEncoderPtr encoder) override; private: + void resetFFmpegSettings(); + IVideoEncoderPtr m_encoder; int m_currentEncoderFFmpegVersion = -1; diff --git a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp index 866dda0043fef..90f15caad33a0 100644 --- a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp +++ b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp @@ -269,3 +269,8 @@ void FoldersPreferencesModel::setFFmpegDir(const QString& dir) videoEncoderResolver()->loadFFmpeg(dir); } + +bool FoldersPreferencesModel::showFFmpegSection() const +{ + return appliaction()->unstable(); +} diff --git a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h index 7194d032fe347..ab97357bed5dd 100644 --- a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h +++ b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h @@ -25,8 +25,10 @@ #include -#include "modularity/ioc.h" #include "async/asyncable.h" + +#include "modularity/ioc.h" +#include "iapplication.h" #include "iglobalconfiguration.h" #include "project/iprojectconfiguration.h" #include "notation/inotationconfiguration.h" @@ -49,8 +51,10 @@ class FoldersPreferencesModel : public QAbstractListModel, public muse::Contexta muse::GlobalInject audioConfiguration; muse::GlobalInject vstConfiguration; muse::GlobalInject mediaConfiguration; + muse::ContextInject appliaction = { this }; muse::ContextInject videoEncoderResolver = { this }; + Q_PROPERTY(bool showFFmpegSection READ showFFmpegSection CONSTANT FINAL) Q_PROPERTY(int ffmpegVersion READ ffmpegVersion NOTIFY ffmpegVersionChanged FINAL) Q_PROPERTY(QString ffmpegDir READ ffmpegDir WRITE setFFmpegDir NOTIFY ffmpegDirChanged FINAL) @@ -69,6 +73,8 @@ class FoldersPreferencesModel : public QAbstractListModel, public muse::Contexta QString ffmpegDir() const; void setFFmpegDir(const QString& dir); + bool showFFmpegSection() const; + signals: void ffmpegVersionChanged(); void ffmpegDirChanged(); diff --git a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp index 22a9b15ba6be5..231f7ef4f0abe 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp +++ b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp @@ -79,12 +79,6 @@ ExportDialogModel::ExportDialogModel(QObject* parent) muse::qtrc("project/export", "MP3 audio"), muse::qtrc("project/export", "MP3 audio files"), "Mp3SettingsPage.qml"), -#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE - ExportType::makeWithSuffixes({ "mp4" }, - muse::qtrc("project/export", "Video mp4"), - muse::qtrc("project/export", "Video mp4 files"), - "Mp4SettingsPage.qml"), -#endif ExportType::makeWithSuffixes({ "wav" }, muse::qtrc("project/export", "WAV audio"), muse::qtrc("project/export", "WAV audio files"), @@ -122,6 +116,15 @@ ExportDialogModel::ExportDialogModel(QObject* parent) muse::qtrc("project/export", "LRC files"), "LrcSettingsPage.qml") }; + + if (application()->unstable()) { + m_exportTypeList.push_back( + ExportType::makeWithSuffixes({ "mp4" }, + muse::qtrc("project/export", "Video mp4"), + muse::qtrc("project/export", "Video mp4 files"), + "Mp4SettingsPage.qml") + ); + } } ExportDialogModel::~ExportDialogModel() @@ -562,25 +565,17 @@ void ExportDialogModel::setSvgIllustratorCompat(bool compat) QStringList ExportDialogModel::availableVideoResolutions() const { -#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE const std::vector& resolutions = videoExportConfiguration()->availableResolutions(); QStringList result; for (const std::string& res : resolutions) { result << QString::fromStdString(res); } return result; -#else - return { }; -#endif } QString ExportDialogModel::videoResolution() const { -#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE return QString::fromStdString(videoExportConfiguration()->resolution()); -#else - return ""; -#endif } void ExportDialogModel::setVideoResolution(const QString& resolution) @@ -589,9 +584,7 @@ void ExportDialogModel::setVideoResolution(const QString& resolution) return; } -#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE videoExportConfiguration()->setResolution(resolution.toStdString()); -#endif emit videoResolutionChanged(resolution); } diff --git a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h index ac5fab60246cf..c976f308e6df7 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h +++ b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h @@ -33,14 +33,13 @@ #include "async/asyncable.h" #include "interactive/iinteractive.h" +#include "iapplication.h" #include "context/iglobalcontext.h" #include "importexport/imagesexport/iimagesexportconfiguration.h" #include "importexport/musicxml/imusicxmlconfiguration.h" #include "importexport/midi/imidiconfiguration.h" #include "importexport/audioexport/iaudioexportconfiguration.h" -#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE #include "importexport/videoexport/ivideoexportconfiguration.h" -#endif #include "importexport/mei/imeiconfiguration.h" #include "importexport/lyricsexport/ilyricsexportconfiguration.h" #include "importexport/mnx/imnxconfiguration.h" @@ -113,12 +112,11 @@ class ExportDialogModel : public QAbstractListModel, public QQmlParserStatus, pu muse::GlobalInject lrcConfiguration; muse::GlobalInject mnxConfiguration; muse::GlobalInject configuration; -#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE muse::GlobalInject videoExportConfiguration; -#endif muse::GlobalInject imageExportConfiguration; muse::GlobalInject writers; muse::ContextInject interactive = { this }; + muse::ContextInject application = { this }; muse::ContextInject context = { this }; muse::ContextInject exportProjectScenario = { this }; From 4af4044596c97150186ab232ed8eb4f91e6dfcd8 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 11:16:31 +0200 Subject: [PATCH 15/52] fixed build after cherry-pick --- src/framework/media/mediamodule.cpp | 10 ++++++---- .../MuseScore/Preferences/folderspreferencesmodel.h | 2 +- .../Project/internal/Export/exportdialogmodel.h | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/framework/media/mediamodule.cpp b/src/framework/media/mediamodule.cpp index 5a6b9f84d3843..79ea92375dd1a 100644 --- a/src/framework/media/mediamodule.cpp +++ b/src/framework/media/mediamodule.cpp @@ -31,18 +31,20 @@ using namespace muse::media; using namespace muse::modularity; +static const std::string mname("media"); + std::string MediaModule::moduleName() const { - return "media"; + return mname; } void MediaModule::registerExports() { - m_configuration = std::make_shared(iocContext()); + m_configuration = std::make_shared(globalCtx()); m_videoEncoderResolver = std::make_shared(); - ioc()->registerExport(moduleName(), m_configuration); - ioc()->registerExport(moduleName(), m_videoEncoderResolver); + globalIoc()->registerExport(mname, m_configuration); + globalIoc()->registerExport(mname, m_videoEncoderResolver); } void MediaModule::onInit(const IApplication::RunMode&) diff --git a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h index ab97357bed5dd..6cf9e36ceb4bb 100644 --- a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h +++ b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h @@ -51,7 +51,7 @@ class FoldersPreferencesModel : public QAbstractListModel, public muse::Contexta muse::GlobalInject audioConfiguration; muse::GlobalInject vstConfiguration; muse::GlobalInject mediaConfiguration; - muse::ContextInject appliaction = { this }; + muse::GlobalInject appliaction; muse::ContextInject videoEncoderResolver = { this }; Q_PROPERTY(bool showFFmpegSection READ showFFmpegSection CONSTANT FINAL) diff --git a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h index c976f308e6df7..e6c62409be579 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h +++ b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h @@ -115,8 +115,8 @@ class ExportDialogModel : public QAbstractListModel, public QQmlParserStatus, pu muse::GlobalInject videoExportConfiguration; muse::GlobalInject imageExportConfiguration; muse::GlobalInject writers; + muse::GlobalInject application; muse::ContextInject interactive = { this }; - muse::ContextInject application = { this }; muse::ContextInject context = { this }; muse::ContextInject exportProjectScenario = { this }; From 4d987adada7c9055d9d0090c787c19d198f2b750 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 11:17:43 +0200 Subject: [PATCH 16/52] removed FFmpegFunctions --- src/framework/media/CMakeLists.txt | 1 - .../media/internal/ffmpegfunctions.cpp | 44 ----- .../media/internal/ffmpegfunctions.h | 93 ---------- .../media/internal/ffmpeglibhandler.cpp | 118 ++++++------ .../media/internal/ffmpeglibhandler.h | 64 ++++++- src/framework/media/internal/ffmpegloader.cpp | 55 ++++++ src/framework/media/internal/videoencoder.cpp | 173 +++++++++--------- src/framework/media/internal/videoencoder.h | 3 - 8 files changed, 261 insertions(+), 290 deletions(-) delete mode 100644 src/framework/media/internal/ffmpegfunctions.cpp delete mode 100644 src/framework/media/internal/ffmpegfunctions.h diff --git a/src/framework/media/CMakeLists.txt b/src/framework/media/CMakeLists.txt index 787f374cb17b6..404d31a77008a 100644 --- a/src/framework/media/CMakeLists.txt +++ b/src/framework/media/CMakeLists.txt @@ -37,7 +37,6 @@ target_sources(muse_media PRIVATE internal/ffmpegloader.h internal/ffmpegutils.h - internal/ffmpegfunctions.cpp internal/ffmpeglibhandler.cpp internal/ffmpeglibhandler.h diff --git a/src/framework/media/internal/ffmpegfunctions.cpp b/src/framework/media/internal/ffmpegfunctions.cpp deleted file mode 100644 index 0319b94802788..0000000000000 --- a/src/framework/media/internal/ffmpegfunctions.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0-only - * MuseScore-Studio-CLA-applies - * - * MuseScore Studio - * Music Composition & Notation - * - * Copyright (C) 2025 MuseScore Limited - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include "ffmpegfunctions.h" - -namespace muse::media { -bool FFmpegFunctions::isValid() const -{ - return av_free && av_freep && av_rescale_q - && av_image_fill_arrays && av_image_get_buffer_size - && av_opt_set_int - && av_guess_format && avformat_alloc_context && avformat_new_stream - && avformat_write_header && av_write_trailer - && avio_open && avio_close && av_interleaved_write_frame - && avformat_open_input && avformat_find_stream_info - && avformat_close_input && avformat_free_context - && avformat_alloc_output_context2 && av_read_frame - && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context - && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_copy - && avcodec_send_frame && avcodec_receive_packet - && av_frame_alloc - && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts - && sws_getCachedContext && sws_scale; -} -} diff --git a/src/framework/media/internal/ffmpegfunctions.h b/src/framework/media/internal/ffmpegfunctions.h deleted file mode 100644 index 3296bb01cad0d..0000000000000 --- a/src/framework/media/internal/ffmpegfunctions.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0-only - * MuseScore-Studio-CLA-applies - * - * MuseScore Studio - * Music Composition & Notation - * - * Copyright (C) 2025 MuseScore Limited - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#pragma once - -extern "C" { -#include "thirdparty/ffmpeg/v8/libavcodec/avcodec.h" -#include "thirdparty/ffmpeg/v8/libavformat/avformat.h" -#include "thirdparty/ffmpeg/v8/libswscale/swscale.h" -} - -namespace muse::media { -struct FFmpegFunctions -{ - // libavutil - void (*av_free)(void* ptr) = nullptr; - void (*av_freep)(void* ptr) = nullptr; - int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; - - // libavutil (imgutils) - int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, - int align) = nullptr; - int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; - - // libavutil (opt) - int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; - - // libavformat - const AVOutputFormat*(*av_guess_format)(const char* short_name, const char* filename, const char* mime_type) = nullptr; - AVFormatContext*(*avformat_alloc_context)(void) = nullptr; - AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; - int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; - int (*av_write_trailer)(AVFormatContext* s) = nullptr; - int (*avio_open)(AVIOContext** s, const char* url, int flags) = nullptr; - int (*avio_close)(AVIOContext* s) = nullptr; - int (*av_interleaved_write_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; - - int (*avformat_open_input)(AVFormatContext** ctx, const char* url, const AVInputFormat* fmt, AVDictionary** options) = nullptr; - int (*avformat_find_stream_info)(AVFormatContext* ic, AVDictionary** options) = nullptr; - void (*avformat_close_input)(AVFormatContext** s) = nullptr; - void (*avformat_free_context)(AVFormatContext* s) = nullptr; - int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, const char* format_name, - const char* filename) = nullptr; - int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; - - // libavcodec - AVCodecContext*(*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; - const AVCodec*(*avcodec_find_encoder)(AVCodecID id) = nullptr; - void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; - int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; - int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; - int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; - int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; - int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; - - // libavutil (frame) - AVFrame*(*av_frame_alloc)(void) = nullptr; - - // libavcodec (packet) - AVPacket*(*av_packet_alloc)(void) = nullptr; - void (*av_packet_free)(AVPacket** pkt) = nullptr; - void (*av_packet_unref)(AVPacket* pkt) = nullptr; - void (*av_packet_rescale_ts)(AVPacket* pkt, AVRational tb_src, AVRational tb_dst) = nullptr; - - // libswscale - SwsContext*(*sws_getCachedContext)(SwsContext* context, int srcW, int srcH, AVPixelFormat srcFormat, int dstW, int dstH, - AVPixelFormat dstFormat, int flags, SwsFilter* srcFilter, SwsFilter* dstFilter, - const double* param) = nullptr; - int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, - uint8_t* const dst[], const int dstStride[]) = nullptr; - - bool isValid() const; -}; -} diff --git a/src/framework/media/internal/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeglibhandler.cpp index 5688181166cc1..d1d971e808a51 100644 --- a/src/framework/media/internal/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeglibhandler.cpp @@ -29,60 +29,13 @@ #include "io/fileinfo.h" #include "global/dlib.h" -#include "internal/ffmpegutils.h" - #include "log.h" using namespace muse::media; -static int versionFromAVFormatPath(const muse::io::path_t& path) -{ - std::string name = muse::io::filename(path, true).toStdString(); - int avVer = -1; -#if defined(Q_OS_MAC) - // libavformat.60.dylib - size_t dot = name.rfind('.'); - if (dot != std::string::npos && dot > 0) { - size_t verStart = name.rfind('.', dot - 1); - if (verStart != std::string::npos && verStart + 1 < dot) { - try { - avVer = std::stoi(name.substr(verStart + 1, dot - verStart - 1)); - } catch (...) {} - } - } -#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) - // libavformat.so.60 - size_t so = name.rfind(".so."); - if (so != std::string::npos && so + 4 < name.size()) { - try { - avVer = std::stoi(name.substr(so + 4)); - } catch (...) {} - } -#elif defined(Q_OS_WIN) - // avformat-60.dll - size_t dash = name.find('-'); - if (dash != std::string::npos && dash + 1 < name.size()) { - size_t dot = name.find('.', dash); - if (dot != std::string::npos) { - try { - avVer = std::stoi(name.substr(dash + 1, dot - dash - 1)); - } catch (...) {} - } - } -#endif - - for (const auto& [ver, componentsVersions]: FFMPEG_COMPONENTS_VERSIONS) { - if (componentsVersions.avFormatVersion == avVer) { - return ver; - } - } - - return 0; -} - #define RESOLVE_FROM(lib, name) do { \ - m_functions.name = reinterpret_cast(getSymbol(lib, #name)); \ - if (!m_functions.name) { LOGW() << "FFmpeg: missing symbol " #name; return false; } \ + name = reinterpret_cast(getSymbol(lib, #name)); \ + if (!name) { LOGW() << "FFmpeg: missing symbol " #name; return false; } \ } while (0) void* FFmpegLibHandler::getSymbol(void* lib, const char* name) const @@ -105,7 +58,7 @@ bool FFmpegLibHandler::loadApi() return false; } - m_functions = FFmpegFunctions(); + clearFunctions(); // libavutil RESOLVE_FROM(m_avUtilLibrary, av_free); @@ -150,7 +103,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); RESOLVE_FROM(m_swsScaleLibrary, sws_scale); - return m_functions.isValid(); + return functionsValid(); } bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, @@ -166,9 +119,6 @@ bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& a return false; } - m_version = versionFromAVFormatPath(avFormatPath); - m_dir = io::dirpath(avFormatPath); - LOGI() << "FFmpeg loaded: avutil=" << avUtilPath << ", avcodec=" << avCodecPath << ", avformat=" << avFormatPath << ", swscale=" << swScalePath; @@ -182,7 +132,7 @@ void FFmpegLibHandler::unload() closeLib(m_avCodecLibrary); closeLib(m_avUtilLibrary); - m_functions = FFmpegFunctions(); + clearFunctions(); m_version = 0; m_dir = io::path_t(); } @@ -209,3 +159,61 @@ bool FFmpegLibHandler::tryLoadPath(void*& lib, const io::path_t& fullPath) return false; } + +bool FFmpegLibHandler::functionsValid() const +{ + return av_free && av_freep && av_rescale_q + && av_image_fill_arrays && av_image_get_buffer_size + && av_opt_set_int + && av_guess_format && avformat_alloc_context && avformat_new_stream + && avformat_write_header && av_write_trailer + && avio_open && avio_close && av_interleaved_write_frame + && avformat_open_input && avformat_find_stream_info + && avformat_close_input && avformat_free_context + && avformat_alloc_output_context2 && av_read_frame + && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context + && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_copy + && avcodec_send_frame && avcodec_receive_packet + && av_frame_alloc + && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts + && sws_getCachedContext && sws_scale; +} + +void FFmpegLibHandler::clearFunctions() +{ + av_free = nullptr; + av_freep = nullptr; + av_rescale_q = nullptr; + av_image_fill_arrays = nullptr; + av_image_get_buffer_size = nullptr; + av_opt_set_int = nullptr; + av_guess_format = nullptr; + avformat_alloc_context = nullptr; + avformat_new_stream = nullptr; + avformat_write_header = nullptr; + av_write_trailer = nullptr; + avio_open = nullptr; + avio_close = nullptr; + av_interleaved_write_frame = nullptr; + avformat_open_input = nullptr; + avformat_find_stream_info = nullptr; + avformat_close_input = nullptr; + avformat_free_context = nullptr; + avformat_alloc_output_context2 = nullptr; + av_read_frame = nullptr; + avcodec_alloc_context3 = nullptr; + avcodec_find_encoder = nullptr; + avcodec_free_context = nullptr; + avcodec_open2 = nullptr; + avcodec_parameters_from_context = nullptr; + avcodec_parameters_copy = nullptr; + avcodec_send_frame = nullptr; + avcodec_receive_packet = nullptr; + av_frame_alloc = nullptr; + av_packet_alloc = nullptr; + av_packet_free = nullptr; + av_packet_unref = nullptr; + av_packet_rescale_ts = nullptr; + sws_getCachedContext = nullptr; + sws_scale = nullptr; +} diff --git a/src/framework/media/internal/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeglibhandler.h index 78eee6b6c62b8..429c3661843e4 100644 --- a/src/framework/media/internal/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeglibhandler.h @@ -22,8 +22,13 @@ #pragma once +extern "C" { +#include "thirdparty/ffmpeg/v8/libavcodec/avcodec.h" +#include "thirdparty/ffmpeg/v8/libavformat/avformat.h" +#include "thirdparty/ffmpeg/v8/libswscale/swscale.h" +} + #include "io/path.h" -#include "ffmpegfunctions.h" namespace muse::media { class FFmpegLibHandler @@ -36,23 +41,72 @@ class FFmpegLibHandler bool loadApi(); void unload(); - const FFmpegFunctions* functions() const { return &m_functions; } - int version() const { return m_version; } + void setVersion(int version) { m_version = version; } + io::path_t dir() const { return m_dir; } + void setDir(const io::path_t& dir) { m_dir = dir; } + + // libavutil + void (*av_free)(void* ptr) = nullptr; + void (*av_freep)(void* ptr) = nullptr; + int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; + int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, + int align) = nullptr; + int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; + int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; + + // libavformat + const AVOutputFormat*(*av_guess_format)(const char* short_name, const char* filename, const char* mime_type) = nullptr; + AVFormatContext*(*avformat_alloc_context)(void) = nullptr; + AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; + int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; + int (*av_write_trailer)(AVFormatContext* s) = nullptr; + int (*avio_open)(AVIOContext** s, const char* url, int flags) = nullptr; + int (*avio_close)(AVIOContext* s) = nullptr; + int (*av_interleaved_write_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + int (*avformat_open_input)(AVFormatContext** ctx, const char* url, const AVInputFormat* fmt, AVDictionary** options) = nullptr; + int (*avformat_find_stream_info)(AVFormatContext* ic, AVDictionary** options) = nullptr; + void (*avformat_close_input)(AVFormatContext** s) = nullptr; + void (*avformat_free_context)(AVFormatContext* s) = nullptr; + int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, const char* format_name, + const char* filename) = nullptr; + int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + + // libavcodec + AVCodecContext*(*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; + const AVCodec*(*avcodec_find_encoder)(AVCodecID id) = nullptr; + void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; + int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; + int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; + int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; + int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; + int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; + AVFrame*(*av_frame_alloc)(void) = nullptr; + AVPacket*(*av_packet_alloc)(void) = nullptr; + void (*av_packet_free)(AVPacket** pkt) = nullptr; + void (*av_packet_unref)(AVPacket* pkt) = nullptr; + void (*av_packet_rescale_ts)(AVPacket* pkt, AVRational tb_src, AVRational tb_dst) = nullptr; + + // libswscale + SwsContext*(*sws_getCachedContext)(SwsContext* context, int srcW, int srcH, AVPixelFormat srcFormat, int dstW, int dstH, + AVPixelFormat dstFormat, int flags, SwsFilter* srcFilter, SwsFilter* dstFilter, + const double* param) = nullptr; + int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t* const dst[], const int dstStride[]) = nullptr; private: void* getSymbol(void* lib, const char* name) const; bool tryLoadPath(void*& lib, const io::path_t& fullPath); void closeLib(void*& lib); + void clearFunctions(); + bool functionsValid() const; void* m_avUtilLibrary = nullptr; void* m_avCodecLibrary = nullptr; void* m_avFormatLibrary = nullptr; void* m_swsScaleLibrary = nullptr; - FFmpegFunctions m_functions; - int m_version = 0; io::path_t m_dir; }; diff --git a/src/framework/media/internal/ffmpegloader.cpp b/src/framework/media/internal/ffmpegloader.cpp index d214ac241e353..4432ec0f67f05 100644 --- a/src/framework/media/internal/ffmpegloader.cpp +++ b/src/framework/media/internal/ffmpegloader.cpp @@ -34,6 +34,56 @@ using namespace muse::media; using namespace muse; namespace { +static int versionFromAVFormatPath(const io::path_t& path) +{ + std::string name = io::filename(path, true).toStdString(); + int avVer = -1; +#if defined(Q_OS_MAC) + // libavformat.60.dylib + size_t dot = name.rfind('.'); + if (dot != std::string::npos && dot > 0) { + size_t verStart = name.rfind('.', dot - 1); + if (verStart != std::string::npos && verStart + 1 < dot) { + try { + avVer = std::stoi(name.substr(verStart + 1, dot - verStart - 1)); + } catch (...) {} + } + } +#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) + // libavformat.so.60 + size_t so = name.rfind(".so."); + if (so != std::string::npos && so + 4 < name.size()) { + try { + avVer = std::stoi(name.substr(so + 4)); + } catch (...) {} + } +#elif defined(Q_OS_WIN) + // avformat-60.dll + size_t dash = name.find('-'); + if (dash != std::string::npos && dash + 1 < name.size()) { + size_t dot = name.find('.', dash); + if (dot != std::string::npos) { + try { + avVer = std::stoi(name.substr(dash + 1, dot - dash - 1)); + } catch (...) {} + } + } +#endif + + for (const auto& [ver, componentsVersions] : FFMPEG_COMPONENTS_VERSIONS) { + if (componentsVersions.avFormatVersion == avVer) { + return ver; + } + } + + return 0; +} + +static io::path_t dirFromAVFormatPath(const io::path_t& path) +{ + return io::dirpath(path); +} + io::paths_t defaultSearchPaths() { io::paths_t paths; @@ -139,13 +189,18 @@ std::shared_ptr FFmpegLoader::load(const io::path_t& ffmpegLib { const FFmpegLibPaths paths = findLibraryPaths(ffmpegLibsDir); if (paths.avFormatPath.empty()) { + LOGW() << "FFmpeg libraries not found"; return nullptr; } std::shared_ptr libHandlerPtr = std::make_shared(); if (libHandlerPtr->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, paths.swScalePath) && libHandlerPtr->loadApi()) { + libHandlerPtr->setVersion(versionFromAVFormatPath(paths.avFormatPath)); + libHandlerPtr->setDir(dirFromAVFormatPath(paths.avFormatPath)); + LOGD() << "FFmpeg loaded, version: " << libHandlerPtr->version(); + return libHandlerPtr; } diff --git a/src/framework/media/internal/videoencoder.cpp b/src/framework/media/internal/videoencoder.cpp index b133b740f7d9a..43d7bb9c06471 100644 --- a/src/framework/media/internal/videoencoder.cpp +++ b/src/framework/media/internal/videoencoder.cpp @@ -84,9 +84,9 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->width = width; m_ffmpeg->height = height; - m_ffmpeg->outputFormat = ffmpegFunctions()->av_guess_format("mp4", NULL, NULL); + m_ffmpeg->outputFormat = m_ffmpegHandler->av_guess_format("mp4", NULL, NULL); - m_ffmpeg->formatCtx = ffmpegFunctions()->avformat_alloc_context(); + m_ffmpeg->formatCtx = m_ffmpegHandler->avformat_alloc_context(); if (!m_ffmpeg->formatCtx) { LOGE() << "failed allocate format context"; return false; @@ -99,7 +99,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign #endif // Add the video stream - m_ffmpeg->videoStream = ffmpegFunctions()->avformat_new_stream(m_ffmpeg->formatCtx, 0); + m_ffmpeg->videoStream = m_ffmpegHandler->avformat_new_stream(m_ffmpeg->formatCtx, 0); if (!m_ffmpeg->videoStream) { LOGE() << "failed allocate stream"; return false; @@ -114,12 +114,12 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->codecCtx->codec_type = AVMEDIA_TYPE_VIDEO; #else // find the video encoder - m_ffmpeg->codec = ffmpegFunctions()->avcodec_find_encoder(AV_CODEC_ID_H264); + m_ffmpeg->codec = m_ffmpegHandler->avcodec_find_encoder(AV_CODEC_ID_H264); if (!m_ffmpeg->codec) { LOGE() << "not found codec"; return false; } - m_ffmpeg->codecCtx = ffmpegFunctions()->avcodec_alloc_context3(m_ffmpeg->codec); + m_ffmpeg->codecCtx = m_ffmpegHandler->avcodec_alloc_context3(m_ffmpeg->codec); if (m_ffmpeg->codecCtx == nullptr) { LOGE() << "failed to allocate AV context"; return false; @@ -146,7 +146,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 25, 100) m_ffmpeg->codecCtx->b_frame_strategy = 1; #else - ffmpegFunctions()->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); #endif m_ffmpeg->codecCtx->me_cmp = 1; @@ -155,7 +155,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 49, 100) m_ffmpeg->codecCtx->me_method = ME_HEX; #else - ffmpegFunctions()->av_opt_set_int(m_ffmpeg->codecCtx, "hex", 1, 0); + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "hex", 1, 0); #endif m_ffmpeg->codecCtx->qmin = 10; @@ -163,7 +163,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 25, 100) m_ffmpeg->codecCtx->scenechange_threshold = 40; #else - ffmpegFunctions()->av_opt_set_int(m_ffmpeg->codecCtx, "sc_threshold", 40, 0); + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "sc_threshold", 40, 0); #endif #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 56, 100) m_ffmpeg->codecCtx->flags |= CODEC_FLAG_LOOP_FILTER; @@ -189,26 +189,26 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign // open_video #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) // find the video encoder - m_ffmpeg->codec = ffmpegFunctions()->avcodec_find_encoder(m_ffmpeg->codecCtx->codec_id); + m_ffmpeg->codec = m_ffmpegHandler->avcodec_find_encoder(m_ffmpeg->codecCtx->codec_id); if (!m_ffmpeg->codec) { LOGE() << "not found codec"; return false; } #else - if (ffmpegFunctions()->avcodec_parameters_from_context(m_ffmpeg->videoStream->codecpar, m_ffmpeg->codecCtx) < 0) { - ffmpegFunctions()->avcodec_free_context(&m_ffmpeg->codecCtx); + if (m_ffmpegHandler->avcodec_parameters_from_context(m_ffmpeg->videoStream->codecpar, m_ffmpeg->codecCtx) < 0) { + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); LOGE() << "failed to set AV parameters from context"; return false; } #endif // open the codec - if (ffmpegFunctions()->avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, 0) < 0) { + if (m_ffmpegHandler->avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, 0) < 0) { LOGE() << "failed open codec"; return false; } // Allocate the YUV frame - m_ffmpeg->ppicture = ffmpegFunctions()->av_frame_alloc(); + m_ffmpeg->ppicture = m_ffmpegHandler->av_frame_alloc(); if (!m_ffmpeg->ppicture) { LOGE() << "failed allocate frame"; return false; @@ -219,35 +219,35 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(55, 4, 100) - int size = ffmpegFunctions()->avpicture_get_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height); + int size = m_ffmpegHandler->avpicture_get_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height); #else - int size = ffmpegFunctions()->av_image_get_buffer_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, + int size = m_ffmpegHandler->av_image_get_buffer_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height, 1); #endif m_ffmpeg->picture_buf = new uint8_t[size]; if (!m_ffmpeg->picture_buf) { LOGE() << "failed allocate frame buf"; - ffmpegFunctions()->av_free(m_ffmpeg->ppicture); + m_ffmpegHandler->av_free(m_ffmpeg->ppicture); return false; } // Setup the planes #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(55, 4, 100) - ffmpegFunctions()->avpicture_fill((AVPicture*)m_ffmpeg->ppicture, m_ffmpeg->picture_buf, m_ffmpeg->codecCtx->pix_fmt, + m_ffmpegHandler->avpicture_fill((AVPicture*)m_ffmpeg->ppicture, m_ffmpeg->picture_buf, m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height); #else - ffmpegFunctions()->av_image_fill_arrays(m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize, m_ffmpeg->picture_buf, + m_ffmpegHandler->av_image_fill_arrays(m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize, m_ffmpeg->picture_buf, m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height, 1); #endif - if (ffmpegFunctions()->avio_open(&m_ffmpeg->formatCtx->pb, fileName.c_str(), AVIO_FLAG_WRITE) < 0) { + if (m_ffmpegHandler->avio_open(&m_ffmpeg->formatCtx->pb, fileName.c_str(), AVIO_FLAG_WRITE) < 0) { LOGE() << "failed open file: " << fileName; return false; } - int ret = ffmpegFunctions()->avformat_write_header(m_ffmpeg->formatCtx, NULL); + int ret = m_ffmpegHandler->avformat_write_header(m_ffmpeg->formatCtx, NULL); if (ret < 0) { LOGE() << "failed write AV header"; return false; @@ -264,7 +264,7 @@ void VideoEncoder::close() return; } - int ret = ffmpegFunctions()->avcodec_send_frame(m_ffmpeg->codecCtx, NULL); + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, NULL); if (ret < 0) { LOGE() << "failed to flush encoder buffer"; return; @@ -272,8 +272,8 @@ void VideoEncoder::close() while (true) { #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100) - ffmpegFunctions()->av_init_packet(&m_ffmpeg->pkt); - int ret = ffmpegFunctions()->avcodec_receive_packet(m_ffmpeg->codecCtx, &m_ffmpeg->pkt); + m_ffmpegHandler->av_init_packet(&m_ffmpeg->pkt); + int ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, &m_ffmpeg->pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { @@ -281,21 +281,21 @@ void VideoEncoder::close() return; } - m_ffmpeg->pkt.pts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->pkt.pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); - m_ffmpeg->pkt.dts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->pkt.dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); m_ffmpeg->ptsCounter++; - ret = ffmpegFunctions()->av_interleaved_write_frame(m_ffmpeg->formatCtx, &m_ffmpeg->pkt); + ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, &m_ffmpeg->pkt); if (ret < 0) { return; } - ffmpegFunctions()->av_packet_unref(&m_ffmpeg->pkt); + m_ffmpegHandler->av_packet_unref(&m_ffmpeg->pkt); #else - m_ffmpeg->pkt = ffmpegFunctions()->av_packet_alloc(); - int ret = ffmpegFunctions()->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); + m_ffmpeg->pkt = m_ffmpegHandler->av_packet_alloc(); + int ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { @@ -303,29 +303,29 @@ void VideoEncoder::close() return; } - m_ffmpeg->pkt->pts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->pkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); - m_ffmpeg->pkt->dts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->pkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); m_ffmpeg->ptsCounter++; - ret = ffmpegFunctions()->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); + ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); if (ret < 0) { return; } - ffmpegFunctions()->av_packet_unref(m_ffmpeg->pkt); + m_ffmpegHandler->av_packet_unref(m_ffmpeg->pkt); #endif } - ffmpegFunctions()->av_write_trailer(m_ffmpeg->formatCtx); + m_ffmpegHandler->av_write_trailer(m_ffmpeg->formatCtx); // close_video #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) - ffmpegFunctions()->avcodec_close(m_ffmpeg->videoStream->codec); + m_ffmpegHandler->avcodec_close(m_ffmpeg->videoStream->codec); #else - ffmpegFunctions()->avcodec_free_context(&m_ffmpeg->codecCtx); + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); #endif if (m_ffmpeg->picture_buf) { @@ -334,7 +334,7 @@ void VideoEncoder::close() } if (m_ffmpeg->ppicture) { - ffmpegFunctions()->av_free(m_ffmpeg->ppicture); + m_ffmpegHandler->av_free(m_ffmpeg->ppicture); m_ffmpeg->ppicture = 0; } @@ -342,16 +342,16 @@ void VideoEncoder::close() for (unsigned int i = 0; i < m_ffmpeg->formatCtx->nb_streams; i++) { #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) - ffmpegFunctions()->av_freep(&m_ffmpeg->formatCtx->streams[i]->codec); + m_ffmpegHandler->av_freep(&m_ffmpeg->formatCtx->streams[i]->codec); #endif - ffmpegFunctions()->av_freep(&m_ffmpeg->formatCtx->streams[i]); + m_ffmpegHandler->av_freep(&m_ffmpeg->formatCtx->streams[i]); } // Close file - ffmpegFunctions()->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); // Free the stream - ffmpegFunctions()->av_free(m_ffmpeg->formatCtx); + m_ffmpegHandler->av_free(m_ffmpeg->formatCtx); } bool VideoEncoder::encodeImage(const QImage& img) @@ -363,22 +363,22 @@ bool VideoEncoder::encodeImage(const QImage& img) convertImage_sws(img); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 3, 100) - m_ffmpeg->ppicture->pts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->codecCtx->frame_num, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->codecCtx->frame_num, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); #else - m_ffmpeg->ppicture->pts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->codecCtx->frame_number, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->codecCtx->frame_number, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); #endif - int ret = ffmpegFunctions()->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); if (ret < 0) { return false; } while (ret >= 0) { #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100) - ffmpegFunctions()->av_init_packet(&m_ffmpeg->pkt); - ret = ffmpegFunctions()->avcodec_receive_packet(m_ffmpeg->codecCtx, &m_ffmpeg->pkt); + m_ffmpegHandler->av_init_packet(&m_ffmpeg->pkt); + ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, &m_ffmpeg->pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { return 0; } else if (ret < 0) { @@ -386,21 +386,21 @@ bool VideoEncoder::encodeImage(const QImage& img) return false; } - m_ffmpeg->pkt.pts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->pkt.pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); - m_ffmpeg->pkt.dts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->pkt.dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); m_ffmpeg->ptsCounter++; - ret = ffmpegFunctions()->av_interleaved_write_frame(m_ffmpeg->formatCtx, &m_ffmpeg->pkt); + ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, &m_ffmpeg->pkt); if (ret < 0) { return false; } - ffmpegFunctions()->av_packet_unref(&m_ffmpeg->pkt); + m_ffmpegHandler->av_packet_unref(&m_ffmpeg->pkt); #else - m_ffmpeg->pkt = ffmpegFunctions()->av_packet_alloc(); - ret = ffmpegFunctions()->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); + m_ffmpeg->pkt = m_ffmpegHandler->av_packet_alloc(); + ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { return 0; } else if (ret < 0) { @@ -408,18 +408,18 @@ bool VideoEncoder::encodeImage(const QImage& img) return false; } - m_ffmpeg->pkt->pts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->pkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); - m_ffmpeg->pkt->dts = ffmpegFunctions()->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->pkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); m_ffmpeg->ptsCounter++; - ret = ffmpegFunctions()->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); + ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); if (ret < 0) { return false; } - ffmpegFunctions()->av_packet_unref(m_ffmpeg->pkt); + m_ffmpegHandler->av_packet_unref(m_ffmpeg->pkt); #endif } @@ -436,42 +436,42 @@ bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& auto cleanup = [&]() { if (videoFmtCtx) { - ffmpegFunctions()->avformat_close_input(&videoFmtCtx); + m_ffmpegHandler->avformat_close_input(&videoFmtCtx); } if (audioFmtCtx) { - ffmpegFunctions()->avformat_close_input(&audioFmtCtx); + m_ffmpegHandler->avformat_close_input(&audioFmtCtx); } if (outputFmtCtx) { if (outputFmtCtx->pb) { - ffmpegFunctions()->avio_close(outputFmtCtx->pb); + m_ffmpegHandler->avio_close(outputFmtCtx->pb); } - ffmpegFunctions()->avformat_free_context(outputFmtCtx); + m_ffmpegHandler->avformat_free_context(outputFmtCtx); } }; - if (ffmpegFunctions()->avformat_open_input(&videoFmtCtx, videoPath.c_str(), nullptr, nullptr) < 0) { + if (m_ffmpegHandler->avformat_open_input(&videoFmtCtx, videoPath.c_str(), nullptr, nullptr) < 0) { LOGE() << "mux: failed to open video input: " << videoPath; cleanup(); return false; } - if (ffmpegFunctions()->avformat_find_stream_info(videoFmtCtx, nullptr) < 0) { + if (m_ffmpegHandler->avformat_find_stream_info(videoFmtCtx, nullptr) < 0) { LOGE() << "mux: failed to find video stream info"; cleanup(); return false; } - if (ffmpegFunctions()->avformat_open_input(&audioFmtCtx, audioPath.c_str(), nullptr, nullptr) < 0) { + if (m_ffmpegHandler->avformat_open_input(&audioFmtCtx, audioPath.c_str(), nullptr, nullptr) < 0) { LOGE() << "mux: failed to open audio input: " << audioPath; cleanup(); return false; } - if (ffmpegFunctions()->avformat_find_stream_info(audioFmtCtx, nullptr) < 0) { + if (m_ffmpegHandler->avformat_find_stream_info(audioFmtCtx, nullptr) < 0) { LOGE() << "mux: failed to find audio stream info"; cleanup(); return false; } - if (ffmpegFunctions()->avformat_alloc_output_context2(&outputFmtCtx, nullptr, "mp4", outputPath.c_str()) < 0 || !outputFmtCtx) { + if (m_ffmpegHandler->avformat_alloc_output_context2(&outputFmtCtx, nullptr, "mp4", outputPath.c_str()) < 0 || !outputFmtCtx) { LOGE() << "mux: failed to allocate output context"; cleanup(); return false; @@ -485,13 +485,13 @@ bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& for (unsigned i = 0; i < videoFmtCtx->nb_streams; i++) { if (videoFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { videoInIdx = static_cast(i); - AVStream* outStream = ffmpegFunctions()->avformat_new_stream(outputFmtCtx, nullptr); + AVStream* outStream = m_ffmpegHandler->avformat_new_stream(outputFmtCtx, nullptr); if (!outStream) { LOGE() << "mux: failed to create output video stream"; cleanup(); return false; } - ffmpegFunctions()->avcodec_parameters_copy(outStream->codecpar, videoFmtCtx->streams[i]->codecpar); + m_ffmpegHandler->avcodec_parameters_copy(outStream->codecpar, videoFmtCtx->streams[i]->codecpar); outStream->codecpar->codec_tag = 0; outStream->time_base = videoFmtCtx->streams[i]->time_base; outVideoIdx = outStream->index; @@ -502,13 +502,13 @@ bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& for (unsigned i = 0; i < audioFmtCtx->nb_streams; i++) { if (audioFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { audioInIdx = static_cast(i); - AVStream* outStream = ffmpegFunctions()->avformat_new_stream(outputFmtCtx, nullptr); + AVStream* outStream = m_ffmpegHandler->avformat_new_stream(outputFmtCtx, nullptr); if (!outStream) { LOGE() << "mux: failed to create output audio stream"; cleanup(); return false; } - ffmpegFunctions()->avcodec_parameters_copy(outStream->codecpar, audioFmtCtx->streams[i]->codecpar); + m_ffmpegHandler->avcodec_parameters_copy(outStream->codecpar, audioFmtCtx->streams[i]->codecpar); outStream->codecpar->codec_tag = 0; outStream->time_base = audioFmtCtx->streams[i]->time_base; outAudioIdx = outStream->index; @@ -522,13 +522,13 @@ bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& return false; } - if (ffmpegFunctions()->avio_open(&outputFmtCtx->pb, outputPath.c_str(), AVIO_FLAG_WRITE) < 0) { + if (m_ffmpegHandler->avio_open(&outputFmtCtx->pb, outputPath.c_str(), AVIO_FLAG_WRITE) < 0) { LOGE() << "mux: failed to open output file: " << outputPath; cleanup(); return false; } - if (ffmpegFunctions()->avformat_write_header(outputFmtCtx, nullptr) < 0) { + if (m_ffmpegHandler->avformat_write_header(outputFmtCtx, nullptr) < 0) { LOGE() << "mux: failed to write header"; cleanup(); return false; @@ -541,34 +541,34 @@ bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& / audioOutStream->time_base.num); } - AVPacket* pkt = ffmpegFunctions()->av_packet_alloc(); + AVPacket* pkt = m_ffmpegHandler->av_packet_alloc(); - while (ffmpegFunctions()->av_read_frame(videoFmtCtx, pkt) >= 0) { + while (m_ffmpegHandler->av_read_frame(videoFmtCtx, pkt) >= 0) { if (pkt->stream_index == videoInIdx) { pkt->stream_index = outVideoIdx; - ffmpegFunctions()->av_packet_rescale_ts(pkt, videoFmtCtx->streams[videoInIdx]->time_base, + m_ffmpegHandler->av_packet_rescale_ts(pkt, videoFmtCtx->streams[videoInIdx]->time_base, outputFmtCtx->streams[outVideoIdx]->time_base); pkt->pos = -1; - ffmpegFunctions()->av_interleaved_write_frame(outputFmtCtx, pkt); + m_ffmpegHandler->av_interleaved_write_frame(outputFmtCtx, pkt); } - ffmpegFunctions()->av_packet_unref(pkt); + m_ffmpegHandler->av_packet_unref(pkt); } - while (ffmpegFunctions()->av_read_frame(audioFmtCtx, pkt) >= 0) { + while (m_ffmpegHandler->av_read_frame(audioFmtCtx, pkt) >= 0) { if (pkt->stream_index == audioInIdx) { pkt->stream_index = outAudioIdx; - ffmpegFunctions()->av_packet_rescale_ts(pkt, audioFmtCtx->streams[audioInIdx]->time_base, + m_ffmpegHandler->av_packet_rescale_ts(pkt, audioFmtCtx->streams[audioInIdx]->time_base, outputFmtCtx->streams[outAudioIdx]->time_base); pkt->pts += audioOffsetPts; pkt->dts += audioOffsetPts; pkt->pos = -1; - ffmpegFunctions()->av_interleaved_write_frame(outputFmtCtx, pkt); + m_ffmpegHandler->av_interleaved_write_frame(outputFmtCtx, pkt); } - ffmpegFunctions()->av_packet_unref(pkt); + m_ffmpegHandler->av_packet_unref(pkt); } - ffmpegFunctions()->av_packet_free(&pkt); - ffmpegFunctions()->av_write_trailer(outputFmtCtx); + m_ffmpegHandler->av_packet_free(&pkt); + m_ffmpegHandler->av_write_trailer(outputFmtCtx); ok = true; cleanup(); @@ -588,7 +588,7 @@ bool VideoEncoder::convertImage_sws(const QImage& img) return false; } - m_ffmpeg->img_convert_ctx = ffmpegFunctions()->sws_getCachedContext(m_ffmpeg->img_convert_ctx, m_ffmpeg->width, m_ffmpeg->height, + m_ffmpeg->img_convert_ctx = m_ffmpegHandler->sws_getCachedContext(m_ffmpeg->img_convert_ctx, m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_BGRA, m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); @@ -608,13 +608,8 @@ bool VideoEncoder::convertImage_sws(const QImage& img) srcstride[1] = 0; srcstride[2 ]= 0; - ffmpegFunctions()->sws_scale(m_ffmpeg->img_convert_ctx, srcplanes, srcstride, 0, m_ffmpeg->height, m_ffmpeg->ppicture->data, + m_ffmpegHandler->sws_scale(m_ffmpeg->img_convert_ctx, srcplanes, srcstride, 0, m_ffmpeg->height, m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize); return true; } - -const FFmpegFunctions* VideoEncoder::ffmpegFunctions() const -{ - return m_ffmpegHandler->functions(); -} diff --git a/src/framework/media/internal/videoencoder.h b/src/framework/media/internal/videoencoder.h index 77a4be8e7238c..a869b8c0f85c7 100644 --- a/src/framework/media/internal/videoencoder.h +++ b/src/framework/media/internal/videoencoder.h @@ -24,8 +24,6 @@ #include "../ivideoencoder.h" -#include "ffmpegfunctions.h" - #include "ffmpeglibhandler.h" namespace muse::media { @@ -45,7 +43,6 @@ class VideoEncoder : public IVideoEncoder private: bool convertImage_sws(const QImage& img); - const FFmpegFunctions* ffmpegFunctions() const; std::shared_ptr m_ffmpegHandler = nullptr; FFmpeg* m_ffmpeg = nullptr; From 62b230b43c2add8e02979fcca25507e4246fd651 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 11:18:12 +0200 Subject: [PATCH 17/52] removed support of ffmpeg < v4 --- src/framework/media/internal/videoencoder.cpp | 132 ++---------------- 1 file changed, 9 insertions(+), 123 deletions(-) diff --git a/src/framework/media/internal/videoencoder.cpp b/src/framework/media/internal/videoencoder.cpp index 43d7bb9c06471..8b2304fe0baff 100644 --- a/src/framework/media/internal/videoencoder.cpp +++ b/src/framework/media/internal/videoencoder.cpp @@ -39,22 +39,14 @@ struct muse::media::FFmpeg { AVFormatContext* formatCtx = nullptr; AVStream* videoStream = nullptr; AVCodecContext* codecCtx = nullptr; -#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) - AVCodec* codec = nullptr; -#else const AVCodec* codec = nullptr; -#endif // Frame data AVFrame* ppicture = nullptr; uint8_t* picture_buf = nullptr; // Conversion SwsContext* img_convert_ctx = nullptr; // Packet -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100) - AVPacket pkt; -#else AVPacket* pkt; -#endif bool opened = false; }; @@ -63,13 +55,6 @@ VideoEncoder::VideoEncoder(const std::shared_ptr& handler) : m_ffmpegHandler(handler) { m_ffmpeg = new FFmpeg(); - -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100) - avcodec_register_all(); -#endif -#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100) - av_register_all(); -#endif } VideoEncoder::~VideoEncoder() @@ -92,11 +77,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } m_ffmpeg->formatCtx->oformat = m_ffmpeg->outputFormat; -#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 7, 100) - snprintf(m_ffmpeg->formatCtx->filename, sizeof(m_ffmpeg->formatCtx->filename), "%s", fileName.c_str()); -#else m_ffmpeg->formatCtx->url = strdup(fileName.c_str()); -#endif // Add the video stream m_ffmpeg->videoStream = m_ffmpegHandler->avformat_new_stream(m_ffmpeg->formatCtx, 0); @@ -108,11 +89,6 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->videoStream->time_base.den = fps; m_ffmpeg->videoStream->time_base.num = 1; -#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) - m_ffmpeg->codecCtx = m_ffmpeg->videoStream->codec; - m_ffmpeg->codecCtx->codec_id = AV_CODEC_ID_H264; - m_ffmpeg->codecCtx->codec_type = AVMEDIA_TYPE_VIDEO; -#else // find the video encoder m_ffmpeg->codec = m_ffmpegHandler->avcodec_find_encoder(AV_CODEC_ID_H264); if (!m_ffmpeg->codec) { @@ -124,7 +100,6 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign LOGE() << "failed to allocate AV context"; return false; } -#endif #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(60, 31, 102) m_ffmpeg->codecCtx->profile = FF_PROFILE_H264_HIGH; #else @@ -143,33 +118,17 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->codecCtx->time_base.den = fps; m_ffmpeg->codecCtx->time_base.num = 1; m_ffmpeg->codecCtx->max_b_frames = 3; -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 25, 100) - m_ffmpeg->codecCtx->b_frame_strategy = 1; -#else m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); -#endif m_ffmpeg->codecCtx->me_cmp = 1; m_ffmpeg->codecCtx->me_range = 16; -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 49, 100) - m_ffmpeg->codecCtx->me_method = ME_HEX; -#else m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "hex", 1, 0); -#endif m_ffmpeg->codecCtx->qmin = 10; m_ffmpeg->codecCtx->qmax = 51; -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 25, 100) - m_ffmpeg->codecCtx->scenechange_threshold = 40; -#else m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "sc_threshold", 40, 0); -#endif -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 56, 100) - m_ffmpeg->codecCtx->flags |= CODEC_FLAG_LOOP_FILTER; -#else m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_LOOP_FILTER; -#endif m_ffmpeg->codecCtx->me_subpel_quality = 5; m_ffmpeg->codecCtx->i_quant_factor = 0.71; m_ffmpeg->codecCtx->qcompress = 0.6; @@ -177,30 +136,17 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign // some formats want stream headers to be separate if (m_ffmpeg->formatCtx->oformat->flags & AVFMT_GLOBALHEADER) { -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 56, 100) - m_ffmpeg->codecCtx->flags |= CODEC_FLAG_LOOP_FILTER; -#else m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_LOOP_FILTER; -#endif } //av_dump_format(m_ffmpeg->formatCtx, 0, fileName.c_str(), 1); // open_video -#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) - // find the video encoder - m_ffmpeg->codec = m_ffmpegHandler->avcodec_find_encoder(m_ffmpeg->codecCtx->codec_id); - if (!m_ffmpeg->codec) { - LOGE() << "not found codec"; - return false; - } -#else if (m_ffmpegHandler->avcodec_parameters_from_context(m_ffmpeg->videoStream->codecpar, m_ffmpeg->codecCtx) < 0) { m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); LOGE() << "failed to set AV parameters from context"; return false; } -#endif // open the codec if (m_ffmpegHandler->avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, 0) < 0) { LOGE() << "failed open codec"; @@ -218,12 +164,8 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->ppicture->height = height; m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; -#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(55, 4, 100) - int size = m_ffmpegHandler->avpicture_get_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height); -#else int size = m_ffmpegHandler->av_image_get_buffer_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height, 1); -#endif m_ffmpeg->picture_buf = new uint8_t[size]; if (!m_ffmpeg->picture_buf) { LOGE() << "failed allocate frame buf"; @@ -232,15 +174,9 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign } // Setup the planes -#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(55, 4, 100) - m_ffmpegHandler->avpicture_fill((AVPicture*)m_ffmpeg->ppicture, m_ffmpeg->picture_buf, m_ffmpeg->codecCtx->pix_fmt, - m_ffmpeg->codecCtx->width, - m_ffmpeg->codecCtx->height); -#else m_ffmpegHandler->av_image_fill_arrays(m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize, m_ffmpeg->picture_buf, m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height, 1); -#endif if (m_ffmpegHandler->avio_open(&m_ffmpeg->formatCtx->pb, fileName.c_str(), AVIO_FLAG_WRITE) < 0) { LOGE() << "failed open file: " << fileName; @@ -271,34 +207,13 @@ void VideoEncoder::close() } while (true) { -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100) - m_ffmpegHandler->av_init_packet(&m_ffmpeg->pkt); - int ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, &m_ffmpeg->pkt); - if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { - break; - } else if (ret < 0) { - LOGE() << "error during encoding"; - return; - } - - m_ffmpeg->pkt.pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); - m_ffmpeg->pkt.dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); - - m_ffmpeg->ptsCounter++; - - ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, &m_ffmpeg->pkt); - if (ret < 0) { - return; - } - m_ffmpegHandler->av_packet_unref(&m_ffmpeg->pkt); -#else m_ffmpeg->pkt = m_ffmpegHandler->av_packet_alloc(); int ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); break; } else if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); LOGE() << "error during encoding"; return; } @@ -312,21 +227,16 @@ void VideoEncoder::close() ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); return; } - m_ffmpegHandler->av_packet_unref(m_ffmpeg->pkt); -#endif + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); } m_ffmpegHandler->av_write_trailer(m_ffmpeg->formatCtx); // close_video - -#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) - m_ffmpegHandler->avcodec_close(m_ffmpeg->videoStream->codec); -#else m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); -#endif if (m_ffmpeg->picture_buf) { delete[] m_ffmpeg->picture_buf; @@ -341,9 +251,6 @@ void VideoEncoder::close() /* free the streams */ for (unsigned int i = 0; i < m_ffmpeg->formatCtx->nb_streams; i++) { -#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) - m_ffmpegHandler->av_freep(&m_ffmpeg->formatCtx->streams[i]->codec); -#endif m_ffmpegHandler->av_freep(&m_ffmpeg->formatCtx->streams[i]); } @@ -376,34 +283,13 @@ bool VideoEncoder::encodeImage(const QImage& img) } while (ret >= 0) { -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100) - m_ffmpegHandler->av_init_packet(&m_ffmpeg->pkt); - ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, &m_ffmpeg->pkt); - if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { - return 0; - } else if (ret < 0) { - LOGE() << "error during encoding"; - return false; - } - - m_ffmpeg->pkt.pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); - m_ffmpeg->pkt.dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); - - m_ffmpeg->ptsCounter++; - - ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, &m_ffmpeg->pkt); - if (ret < 0) { - return false; - } - m_ffmpegHandler->av_packet_unref(&m_ffmpeg->pkt); -#else m_ffmpeg->pkt = m_ffmpegHandler->av_packet_alloc(); ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { - return 0; + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return true; } else if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); LOGE() << "error during encoding"; return false; } @@ -417,10 +303,10 @@ bool VideoEncoder::encodeImage(const QImage& img) ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); return false; } - m_ffmpegHandler->av_packet_unref(m_ffmpeg->pkt); -#endif + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); } return true; From eda31535b6d6ff2b04518f4a33c6d6eaf3429ffe Mon Sep 17 00:00:00 2001 From: Eism Date: Tue, 10 Mar 2026 11:56:12 +0200 Subject: [PATCH 18/52] some code clean --- src/framework/media/internal/ffmpegutils.h | 11 +++--- src/framework/media/internal/videoencoder.cpp | 36 +++++++++---------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/framework/media/internal/ffmpegutils.h b/src/framework/media/internal/ffmpegutils.h index ab8e0954aa4ae..d78e07cea3093 100644 --- a/src/framework/media/internal/ffmpegutils.h +++ b/src/framework/media/internal/ffmpegutils.h @@ -36,10 +36,11 @@ struct FFmpegVersionInfo { }; static const std::vector > FFMPEG_COMPONENTS_VERSIONS = { - { 8, { 62, 60, 62, 9 } }, - { 7, { 61, 59, 61, 8 } }, - { 6, { 60, 58, 60, 7 } }, - { 5, { 59, 57, 59, 6 } }, - { 4, { 58, 56, 58, 5 } }, + // ffmpeg avFormat avUtil avCodec swScale + { 8, { 62, 60, 62, 9 } }, + { 7, { 61, 59, 61, 8 } }, + { 6, { 60, 58, 60, 7 } }, + { 5, { 59, 57, 59, 6 } }, + { 4, { 58, 56, 58, 5 } }, }; } diff --git a/src/framework/media/internal/videoencoder.cpp b/src/framework/media/internal/videoencoder.cpp index 8b2304fe0baff..94bd55e019d47 100644 --- a/src/framework/media/internal/videoencoder.cpp +++ b/src/framework/media/internal/videoencoder.cpp @@ -165,7 +165,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; int size = m_ffmpegHandler->av_image_get_buffer_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, - m_ffmpeg->codecCtx->height, 1); + m_ffmpeg->codecCtx->height, 1); m_ffmpeg->picture_buf = new uint8_t[size]; if (!m_ffmpeg->picture_buf) { LOGE() << "failed allocate frame buf"; @@ -175,8 +175,8 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign // Setup the planes m_ffmpegHandler->av_image_fill_arrays(m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize, m_ffmpeg->picture_buf, - m_ffmpeg->codecCtx->pix_fmt, - m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height, 1); + m_ffmpeg->codecCtx->pix_fmt, + m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height, 1); if (m_ffmpegHandler->avio_open(&m_ffmpeg->formatCtx->pb, fileName.c_str(), AVIO_FLAG_WRITE) < 0) { LOGE() << "failed open file: " << fileName; @@ -219,9 +219,9 @@ void VideoEncoder::close() } m_ffmpeg->pkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); + m_ffmpeg->videoStream->time_base); m_ffmpeg->pkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); + m_ffmpeg->videoStream->time_base); m_ffmpeg->ptsCounter++; @@ -269,12 +269,12 @@ bool VideoEncoder::encodeImage(const QImage& img) convertImage_sws(img); -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 3, 100) - m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->codecCtx->frame_num, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); -#else +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(60, 3, 100) m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->codecCtx->frame_number, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); + m_ffmpeg->videoStream->time_base); +#else + m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->codecCtx->frame_num, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); #endif int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); @@ -295,9 +295,9 @@ bool VideoEncoder::encodeImage(const QImage& img) } m_ffmpeg->pkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); + m_ffmpeg->videoStream->time_base); m_ffmpeg->pkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); + m_ffmpeg->videoStream->time_base); m_ffmpeg->ptsCounter++; @@ -433,7 +433,7 @@ bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& if (pkt->stream_index == videoInIdx) { pkt->stream_index = outVideoIdx; m_ffmpegHandler->av_packet_rescale_ts(pkt, videoFmtCtx->streams[videoInIdx]->time_base, - outputFmtCtx->streams[outVideoIdx]->time_base); + outputFmtCtx->streams[outVideoIdx]->time_base); pkt->pos = -1; m_ffmpegHandler->av_interleaved_write_frame(outputFmtCtx, pkt); } @@ -444,7 +444,7 @@ bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& if (pkt->stream_index == audioInIdx) { pkt->stream_index = outAudioIdx; m_ffmpegHandler->av_packet_rescale_ts(pkt, audioFmtCtx->streams[audioInIdx]->time_base, - outputFmtCtx->streams[outAudioIdx]->time_base); + outputFmtCtx->streams[outAudioIdx]->time_base); pkt->pts += audioOffsetPts; pkt->dts += audioOffsetPts; pkt->pos = -1; @@ -475,9 +475,9 @@ bool VideoEncoder::convertImage_sws(const QImage& img) } m_ffmpeg->img_convert_ctx = m_ffmpegHandler->sws_getCachedContext(m_ffmpeg->img_convert_ctx, m_ffmpeg->width, m_ffmpeg->height, - AV_PIX_FMT_BGRA, - m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, - NULL, NULL, NULL); + AV_PIX_FMT_BGRA, + m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, + NULL, NULL, NULL); if (!m_ffmpeg->img_convert_ctx) { LOGE() << "failed initialize the conversion context"; @@ -495,7 +495,7 @@ bool VideoEncoder::convertImage_sws(const QImage& img) srcstride[2 ]= 0; m_ffmpegHandler->sws_scale(m_ffmpeg->img_convert_ctx, srcplanes, srcstride, 0, m_ffmpeg->height, m_ffmpeg->ppicture->data, - m_ffmpeg->ppicture->linesize); + m_ffmpeg->ppicture->linesize); return true; } From 06bc78ae92644d02028c18226978906e3df77884 Mon Sep 17 00:00:00 2001 From: Eism Date: Tue, 10 Mar 2026 15:50:14 +0200 Subject: [PATCH 19/52] fixed add audio interface in VideoEncoder --- src/framework/media/internal/videoencoder.cpp | 80 ++++++++++++------- src/framework/media/internal/videoencoder.h | 6 +- src/framework/media/ivideoencoder.h | 6 +- .../stubs/media/videoencoderstub.cpp | 7 +- src/framework/stubs/media/videoencoderstub.h | 5 +- .../videoexport/internal/videowriter.cpp | 37 ++++----- .../videoexport/internal/videowriter.h | 4 +- 7 files changed, 87 insertions(+), 58 deletions(-) diff --git a/src/framework/media/internal/videoencoder.cpp b/src/framework/media/internal/videoencoder.cpp index 94bd55e019d47..ff71d6948cda0 100644 --- a/src/framework/media/internal/videoencoder.cpp +++ b/src/framework/media/internal/videoencoder.cpp @@ -21,6 +21,8 @@ */ #include "videoencoder.h" +#include "io/file.h" +#include "defer.h" #include "log.h" using namespace muse::media; @@ -190,11 +192,12 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign } m_ffmpeg->opened = true; + m_outputPath = fileName; return true; } -void VideoEncoder::close() +void VideoEncoder::finishEncode() { if (!m_ffmpeg->opened) { return; @@ -234,6 +237,15 @@ void VideoEncoder::close() } m_ffmpegHandler->av_write_trailer(m_ffmpeg->formatCtx); + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; +} + +void VideoEncoder::close() +{ + if (!m_ffmpeg->opened) { + return; + } // close_video m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); @@ -256,9 +268,14 @@ void VideoEncoder::close() // Close file m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; // Free the stream m_ffmpegHandler->av_free(m_ffmpeg->formatCtx); + m_ffmpeg->formatCtx = nullptr; + m_ffmpeg->opened = false; + + m_outputPath = io::path_t(); } bool VideoEncoder::encodeImage(const QImage& img) @@ -312,13 +329,19 @@ bool VideoEncoder::encodeImage(const QImage& img) return true; } -bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& audioPath, const io::path_t& outputPath, - double audioOffsetSec) +bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) { + if (m_outputPath.empty()) { + LOGE() << "addAudio: encoder was not opened or path not set"; + return false; + } + + const io::path_t videoPath = m_outputPath; + const io::path_t tmpPath = m_outputPath + ".tmp"; + AVFormatContext* videoFmtCtx = nullptr; AVFormatContext* audioFmtCtx = nullptr; AVFormatContext* outputFmtCtx = nullptr; - bool ok = false; auto cleanup = [&]() { if (videoFmtCtx) { @@ -335,31 +358,30 @@ bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& } }; - if (m_ffmpegHandler->avformat_open_input(&videoFmtCtx, videoPath.c_str(), nullptr, nullptr) < 0) { - LOGE() << "mux: failed to open video input: " << videoPath; + DEFER { cleanup(); + }; + + if (m_ffmpegHandler->avformat_open_input(&videoFmtCtx, videoPath.c_str(), nullptr, nullptr) < 0) { + LOGE() << "addAudio: failed to open video input: " << videoPath; return false; } if (m_ffmpegHandler->avformat_find_stream_info(videoFmtCtx, nullptr) < 0) { - LOGE() << "mux: failed to find video stream info"; - cleanup(); + LOGE() << "addAudio: failed to find video stream info"; return false; } if (m_ffmpegHandler->avformat_open_input(&audioFmtCtx, audioPath.c_str(), nullptr, nullptr) < 0) { - LOGE() << "mux: failed to open audio input: " << audioPath; - cleanup(); + LOGE() << "addAudio: failed to open audio input: " << audioPath; return false; } if (m_ffmpegHandler->avformat_find_stream_info(audioFmtCtx, nullptr) < 0) { - LOGE() << "mux: failed to find audio stream info"; - cleanup(); + LOGE() << "addAudio: failed to find audio stream info"; return false; } - if (m_ffmpegHandler->avformat_alloc_output_context2(&outputFmtCtx, nullptr, "mp4", outputPath.c_str()) < 0 || !outputFmtCtx) { - LOGE() << "mux: failed to allocate output context"; - cleanup(); + if (m_ffmpegHandler->avformat_alloc_output_context2(&outputFmtCtx, nullptr, "mp4", tmpPath.c_str()) < 0 || !outputFmtCtx) { + LOGE() << "addAudio: failed to allocate output context"; return false; } @@ -373,8 +395,7 @@ bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& videoInIdx = static_cast(i); AVStream* outStream = m_ffmpegHandler->avformat_new_stream(outputFmtCtx, nullptr); if (!outStream) { - LOGE() << "mux: failed to create output video stream"; - cleanup(); + LOGE() << "addAudio: failed to create output video stream"; return false; } m_ffmpegHandler->avcodec_parameters_copy(outStream->codecpar, videoFmtCtx->streams[i]->codecpar); @@ -390,8 +411,7 @@ bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& audioInIdx = static_cast(i); AVStream* outStream = m_ffmpegHandler->avformat_new_stream(outputFmtCtx, nullptr); if (!outStream) { - LOGE() << "mux: failed to create output audio stream"; - cleanup(); + LOGE() << "addAudio: failed to create output audio stream"; return false; } m_ffmpegHandler->avcodec_parameters_copy(outStream->codecpar, audioFmtCtx->streams[i]->codecpar); @@ -403,20 +423,17 @@ bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& } if (videoInIdx < 0 || audioInIdx < 0) { - LOGE() << "mux: could not find video or audio stream"; - cleanup(); + LOGE() << "addAudio: could not find video or audio stream"; return false; } - if (m_ffmpegHandler->avio_open(&outputFmtCtx->pb, outputPath.c_str(), AVIO_FLAG_WRITE) < 0) { - LOGE() << "mux: failed to open output file: " << outputPath; - cleanup(); + if (m_ffmpegHandler->avio_open(&outputFmtCtx->pb, tmpPath.c_str(), AVIO_FLAG_WRITE) < 0) { + LOGE() << "addAudio: failed to open output file: " << tmpPath; return false; } if (m_ffmpegHandler->avformat_write_header(outputFmtCtx, nullptr) < 0) { - LOGE() << "mux: failed to write header"; - cleanup(); + LOGE() << "addAudio: failed to write header"; return false; } @@ -456,9 +473,14 @@ bool VideoEncoder::muxAudioVideo(const io::path_t& videoPath, const io::path_t& m_ffmpegHandler->av_packet_free(&pkt); m_ffmpegHandler->av_write_trailer(outputFmtCtx); - ok = true; - cleanup(); - return ok; + if (!io::File::copy(tmpPath, videoPath, true)) { + LOGE() << "addAudio: failed to replace with muxed file"; + return false; + } + + io::File::remove(tmpPath); + + return true; } bool VideoEncoder::convertImage_sws(const QImage& img) diff --git a/src/framework/media/internal/videoencoder.h b/src/framework/media/internal/videoencoder.h index a869b8c0f85c7..6ff42b21acd53 100644 --- a/src/framework/media/internal/videoencoder.h +++ b/src/framework/media/internal/videoencoder.h @@ -38,13 +38,15 @@ class VideoEncoder : public IVideoEncoder void close() override; bool encodeImage(const QImage& img) override; - bool muxAudioVideo(const muse::io::path_t& videoPath, const muse::io::path_t& audioPath, const muse::io::path_t& outputPath, - double audioOffsetSec) override; + void finishEncode() override; + + bool addAudio(const muse::io::path_t& audioPath, double audioOffsetSec) override; private: bool convertImage_sws(const QImage& img); std::shared_ptr m_ffmpegHandler = nullptr; FFmpeg* m_ffmpeg = nullptr; + muse::io::path_t m_outputPath; }; } diff --git a/src/framework/media/ivideoencoder.h b/src/framework/media/ivideoencoder.h index 788dc84577321..d4ae609a727d6 100644 --- a/src/framework/media/ivideoencoder.h +++ b/src/framework/media/ivideoencoder.h @@ -38,9 +38,11 @@ class IVideoEncoder : MODULE_CONTEXT_INTERFACE virtual bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) = 0; virtual void close() = 0; + virtual bool encodeImage(const QImage& img) = 0; - virtual bool muxAudioVideo(const muse::io::path_t& videoPath, const muse::io::path_t& audioPath, const muse::io::path_t& outputPath, - double audioOffsetSec) = 0; + virtual void finishEncode() = 0; + + virtual bool addAudio(const muse::io::path_t& audioPath, double audioOffsetSec) = 0; }; using IVideoEncoderPtr = std::shared_ptr; } diff --git a/src/framework/stubs/media/videoencoderstub.cpp b/src/framework/stubs/media/videoencoderstub.cpp index e756100b3057a..f9abd48fe9d6a 100644 --- a/src/framework/stubs/media/videoencoderstub.cpp +++ b/src/framework/stubs/media/videoencoderstub.cpp @@ -37,8 +37,11 @@ bool VideoEncoderStub::encodeImage(const QImage&) return false; } -bool VideoEncoderStub::muxAudioVideo(const muse::io::path_t&, const muse::io::path_t&, - const muse::io::path_t&, double) +void VideoEncoderStub::finishEncode() +{ +} + +bool VideoEncoderStub::addAudio(const muse::io::path_t&, double) { return false; } diff --git a/src/framework/stubs/media/videoencoderstub.h b/src/framework/stubs/media/videoencoderstub.h index a02668190a04a..47421b092d275 100644 --- a/src/framework/stubs/media/videoencoderstub.h +++ b/src/framework/stubs/media/videoencoderstub.h @@ -32,7 +32,10 @@ class VideoEncoderStub : public IVideoEncoder bool open(const muse::io::path_t&, unsigned, unsigned, unsigned, unsigned, unsigned) override; void close() override; + bool encodeImage(const QImage&) override; - bool muxAudioVideo(const muse::io::path_t&, const muse::io::path_t&, const muse::io::path_t&, double) override; + void finishEncode() override; + + bool addAudio(const muse::io::path_t&, double) override; }; } diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index 3ed9f36f72f8a..ebd2238da331a 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -71,16 +71,21 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, Config cfg = makeConfig(); muse::io::path_t finalPath(filePath); - muse::io::path_t tempVideoPath = withAudio ? finalPath + ".tmp_video.mp4" : finalPath; muse::io::path_t tempAudioPath = finalPath + ".tmp_audio.mp3"; + auto encoder = videoEncodeResolver()->currentVideoEncoder(); + if (!encoder->open(finalPath, cfg.width, cfg.height, cfg.bitrate, cfg.fps / 2, cfg.fps)) { + LOGE() << "failed to open video encoder"; + return make_ret(muse::Ret::Code::UnknownError); + } + m_isCompleted = false; m_audioCompleted = false; m_abort = false; m_writeRet = muse::Ret(); m_audioRet = muse::Ret(); - startVideoExport(notation, tempVideoPath, cfg); + startVideoExport(encoder, notation, cfg); if (withAudio) { startAudioExport(notation, tempAudioPath); @@ -101,9 +106,11 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, muse::Ret result = m_writeRet; + encoder->finishEncode(); + if (withAudio) { if (result && m_audioRet) { - if (!videoEncodeResolver()->currentVideoEncoder()->muxAudioVideo(tempVideoPath, tempAudioPath, finalPath, cfg.leadingSec)) { + if (!encoder->addAudio(tempAudioPath, cfg.leadingSec)) { result = make_ret(muse::Ret::Code::UnknownError); } } else if (!result) { @@ -112,10 +119,11 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, result = m_audioRet; } - muse::io::File::remove(tempVideoPath); muse::io::File::remove(tempAudioPath); } + encoder->close(); + return result; } @@ -173,10 +181,10 @@ VideoWriter::Config VideoWriter::makeConfig() const return cfg; } -void VideoWriter::startVideoExport(INotationPtr notation, const muse::io::path_t& videoPath, const Config& cfg) +void VideoWriter::startVideoExport(muse::media::IVideoEncoderPtr encoder, INotationPtr notation, const Config& cfg) { - muse::Concurrent::run([this, notation, videoPath, cfg]() { - doGenerate(notation, videoPath, cfg); + muse::Concurrent::run([this, encoder, notation, cfg]() { + doGenerate(encoder, notation, cfg); }); } @@ -313,16 +321,8 @@ void VideoWriter::restoreScore(INotationPtr notation, const ScoreRestoreData& da score->update(); } -void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& filePath, const Config& config) +void VideoWriter::doGenerate(muse::media::IVideoEncoderPtr encoder, INotationPtr notation, const Config& config) { - if (!videoEncodeResolver()->currentVideoEncoder()->open(filePath, config.width, config.height, config.bitrate, config.fps / 2, - config.fps)) { - LOGE() << "failed open encoder"; - m_writeRet = make_ret(muse::Ret::Code::UnknownError); - m_isCompleted = true; - return; - } - auto restoreData = prepareScore(notation, config); if (!restoreData) { m_writeRet = make_ret(muse::Ret::Code::UnknownError); @@ -379,7 +379,6 @@ void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& file for (int f = 0; f < frameCount; f++) { if (m_abort) { - videoEncodeResolver()->currentVideoEncoder()->close(); m_writeRet = make_ret(muse::Ret::Code::Cancel); m_progress.finish(make_ret(muse::Ret::Code::Cancel)); return; @@ -420,11 +419,9 @@ void VideoWriter::doGenerate(INotationPtr notation, const muse::io::path_t& file painter.fillRect(cursorAbsRect, CURSOR_COLOR); - videoEncodeResolver()->currentVideoEncoder()->encodeImage(frame); + encoder->encodeImage(frame); } - videoEncodeResolver()->currentVideoEncoder()->close(); - m_writeRet = muse::make_ok(); m_progress.finish(muse::make_ok()); } diff --git a/src/importexport/videoexport/internal/videowriter.h b/src/importexport/videoexport/internal/videowriter.h index eec5f82a98f57..f1c7a2b722c0c 100644 --- a/src/importexport/videoexport/internal/videowriter.h +++ b/src/importexport/videoexport/internal/videowriter.h @@ -69,10 +69,10 @@ class VideoWriter : public project::INotationWriter, public muse::Contextable, p Config makeConfig() const; - void startVideoExport(notation::INotationPtr notation, const muse::io::path_t& videoPath, const Config& cfg); + void startVideoExport(muse::media::IVideoEncoderPtr encoder, notation::INotationPtr notation, const Config& cfg); void startAudioExport(notation::INotationPtr notation, const muse::io::path_t& audioPath); - void doGenerate(notation::INotationPtr notation, const muse::io::path_t& filePath, const Config& config); + void doGenerate(muse::media::IVideoEncoderPtr encoder, notation::INotationPtr notation, const Config& config); struct ScoreRestoreData { From ce9c4ad5c152f90194fcd0602f7ca867bf14650c Mon Sep 17 00:00:00 2001 From: Eism Date: Tue, 10 Mar 2026 16:54:20 +0200 Subject: [PATCH 20/52] moved current videoencoder to ffmpeg/v8 --- src/framework/media/CMakeLists.txt | 16 +- .../{ => ffmpeg/v8}/ffmpeglibhandler.cpp | 4 +- .../{ => ffmpeg/v8}/ffmpeglibhandler.h | 7 +- .../internal/{ => ffmpeg/v8}/videoencoder.cpp | 20 +-- .../internal/{ => ffmpeg/v8}/videoencoder.h | 4 +- src/framework/media/internal/ffmpegloader.h | 34 ----- .../{ffmpegloader.cpp => ffmpegutils.cpp} | 140 +++++++----------- src/framework/media/internal/ffmpegutils.h | 34 ++++- .../media/internal/videoencoderresolver.cpp | 55 ++++++- .../media/internal/videoencoderresolver.h | 10 ++ 10 files changed, 153 insertions(+), 171 deletions(-) rename src/framework/media/internal/{ => ffmpeg/v8}/ffmpeglibhandler.cpp (99%) rename src/framework/media/internal/{ => ffmpeg/v8}/ffmpeglibhandler.h (97%) rename src/framework/media/internal/{ => ffmpeg/v8}/videoencoder.cpp (96%) rename src/framework/media/internal/{ => ffmpeg/v8}/videoencoder.h (95%) delete mode 100644 src/framework/media/internal/ffmpegloader.h rename src/framework/media/internal/{ffmpegloader.cpp => ffmpegutils.cpp} (79%) diff --git a/src/framework/media/CMakeLists.txt b/src/framework/media/CMakeLists.txt index 404d31a77008a..16e87c804a379 100644 --- a/src/framework/media/CMakeLists.txt +++ b/src/framework/media/CMakeLists.txt @@ -18,7 +18,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -muse_create_module(muse_media ALIAS muse::media NO_UNITY) +muse_create_module(muse_media ALIAS muse::media) target_sources(muse_media PRIVATE mediamodule.cpp @@ -33,18 +33,16 @@ target_sources(muse_media PRIVATE internal/mediaconfiguration.h internal/videoencoderresolver.h - internal/ffmpegloader.cpp - internal/ffmpegloader.h + internal/ffmpegutils.cpp internal/ffmpegutils.h - internal/ffmpeglibhandler.cpp - internal/ffmpeglibhandler.h - - internal/videoencoder.cpp - internal/videoencoder.h + internal/ffmpeg/v8/ffmpeglibhandler.cpp + internal/ffmpeg/v8/ffmpeglibhandler.h + internal/ffmpeg/v8/videoencoder.cpp + internal/ffmpeg/v8/videoencoder.h ) -target_include_directories(muse_media PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v8) +target_include_directories(muse_media PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg) set(MODULE_USE_PCH OFF) set(MODULE_USE_UNITY OFF) diff --git a/src/framework/media/internal/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp similarity index 99% rename from src/framework/media/internal/ffmpeglibhandler.cpp rename to src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp index d1d971e808a51..5824917ce98b2 100644 --- a/src/framework/media/internal/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp @@ -31,8 +31,7 @@ #include "log.h" -using namespace muse::media; - +namespace muse::media::ffmpeg::v8 { #define RESOLVE_FROM(lib, name) do { \ name = reinterpret_cast(getSymbol(lib, #name)); \ if (!name) { LOGW() << "FFmpeg: missing symbol " #name; return false; } \ @@ -217,3 +216,4 @@ void FFmpegLibHandler::clearFunctions() sws_getCachedContext = nullptr; sws_scale = nullptr; } +} diff --git a/src/framework/media/internal/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h similarity index 97% rename from src/framework/media/internal/ffmpeglibhandler.h rename to src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h index 429c3661843e4..0ace5ccfc38e8 100644 --- a/src/framework/media/internal/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h @@ -30,7 +30,7 @@ extern "C" { #include "io/path.h" -namespace muse::media { +namespace muse::media::ffmpeg::v8 { class FFmpegLibHandler { public: @@ -52,7 +52,7 @@ class FFmpegLibHandler void (*av_freep)(void* ptr) = nullptr; int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, - int align) = nullptr; + int align) = nullptr; int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; @@ -95,8 +95,7 @@ class FFmpegLibHandler int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]) = nullptr; -private: - void* getSymbol(void* lib, const char* name) const; +private : void* getSymbol(void* lib, const char* name) const; bool tryLoadPath(void*& lib, const io::path_t& fullPath); void closeLib(void*& lib); void clearFunctions(); diff --git a/src/framework/media/internal/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp similarity index 96% rename from src/framework/media/internal/videoencoder.cpp rename to src/framework/media/internal/ffmpeg/v8/videoencoder.cpp index ff71d6948cda0..108daaf30c214 100644 --- a/src/framework/media/internal/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp @@ -25,19 +25,14 @@ #include "defer.h" #include "log.h" -using namespace muse::media; - -struct muse::media::FFmpeg { +namespace muse::media::ffmpeg::v8 { +struct FFmpeg { int width = 0; int height = 0; unsigned int ptsCounter = 0; // FFmpeg stuff -#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(59, 16, 100) - AVOutputFormat* outputFormat = nullptr; -#else const AVOutputFormat* outputFormat = nullptr; -#endif AVFormatContext* formatCtx = nullptr; AVStream* videoStream = nullptr; AVCodecContext* codecCtx = nullptr; @@ -102,11 +97,8 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign LOGE() << "failed to allocate AV context"; return false; } -#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(60, 31, 102) - m_ffmpeg->codecCtx->profile = FF_PROFILE_H264_HIGH; -#else + m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; -#endif m_ffmpeg->codecCtx->bit_rate = bitrate; m_ffmpeg->codecCtx->width = width; @@ -286,13 +278,8 @@ bool VideoEncoder::encodeImage(const QImage& img) convertImage_sws(img); -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(60, 3, 100) - m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->codecCtx->frame_number, m_ffmpeg->codecCtx->time_base, - m_ffmpeg->videoStream->time_base); -#else m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->codecCtx->frame_num, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); -#endif int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); if (ret < 0) { @@ -521,3 +508,4 @@ bool VideoEncoder::convertImage_sws(const QImage& img) return true; } +} diff --git a/src/framework/media/internal/videoencoder.h b/src/framework/media/internal/ffmpeg/v8/videoencoder.h similarity index 95% rename from src/framework/media/internal/videoencoder.h rename to src/framework/media/internal/ffmpeg/v8/videoencoder.h index 6ff42b21acd53..5b3306de15a7e 100644 --- a/src/framework/media/internal/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.h @@ -22,11 +22,11 @@ #pragma once -#include "../ivideoencoder.h" +#include "media/ivideoencoder.h" #include "ffmpeglibhandler.h" -namespace muse::media { +namespace muse::media::ffmpeg::v8 { struct FFmpeg; class VideoEncoder : public IVideoEncoder { diff --git a/src/framework/media/internal/ffmpegloader.h b/src/framework/media/internal/ffmpegloader.h deleted file mode 100644 index cd0c8237d30f7..0000000000000 --- a/src/framework/media/internal/ffmpegloader.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0-only - * MuseScore-Studio-CLA-applies - * - * MuseScore Studio - * Music Composition & Notation - * - * Copyright (C) 2025 MuseScore Limited - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#pragma once - -#include "io/path.h" - -namespace muse::media { -class FFmpegLibHandler; -class FFmpegLoader -{ -public: - static std::shared_ptr load(const muse::io::path_t& ffmpegLibsDir); -}; -} diff --git a/src/framework/media/internal/ffmpegloader.cpp b/src/framework/media/internal/ffmpegutils.cpp similarity index 79% rename from src/framework/media/internal/ffmpegloader.cpp rename to src/framework/media/internal/ffmpegutils.cpp index 4432ec0f67f05..5b5fc8b8124e7 100644 --- a/src/framework/media/internal/ffmpegloader.cpp +++ b/src/framework/media/internal/ffmpegutils.cpp @@ -17,74 +17,19 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, see . + * along with this program. If not, see . */ -#include "ffmpegloader.h" +#include "ffmpegutils.h" #include "io/fileinfo.h" #include "io/path.h" -#include "ffmpegutils.h" -#include "internal/ffmpeglibhandler.h" - -#include "log.h" - using namespace muse::media; using namespace muse; -namespace { -static int versionFromAVFormatPath(const io::path_t& path) -{ - std::string name = io::filename(path, true).toStdString(); - int avVer = -1; -#if defined(Q_OS_MAC) - // libavformat.60.dylib - size_t dot = name.rfind('.'); - if (dot != std::string::npos && dot > 0) { - size_t verStart = name.rfind('.', dot - 1); - if (verStart != std::string::npos && verStart + 1 < dot) { - try { - avVer = std::stoi(name.substr(verStart + 1, dot - verStart - 1)); - } catch (...) {} - } - } -#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) - // libavformat.so.60 - size_t so = name.rfind(".so."); - if (so != std::string::npos && so + 4 < name.size()) { - try { - avVer = std::stoi(name.substr(so + 4)); - } catch (...) {} - } -#elif defined(Q_OS_WIN) - // avformat-60.dll - size_t dash = name.find('-'); - if (dash != std::string::npos && dash + 1 < name.size()) { - size_t dot = name.find('.', dash); - if (dot != std::string::npos) { - try { - avVer = std::stoi(name.substr(dash + 1, dot - dash - 1)); - } catch (...) {} - } - } -#endif - - for (const auto& [ver, componentsVersions] : FFMPEG_COMPONENTS_VERSIONS) { - if (componentsVersions.avFormatVersion == avVer) { - return ver; - } - } - - return 0; -} - -static io::path_t dirFromAVFormatPath(const io::path_t& path) -{ - return io::dirpath(path); -} - -io::paths_t defaultSearchPaths() +namespace muse::media { +static io::paths_t defaultSearchPaths() { io::paths_t paths; #if defined(Q_OS_MAC) @@ -100,14 +45,7 @@ io::paths_t defaultSearchPaths() return paths; } -struct FFmpegLibPaths { - io::path_t avUtilPath; - io::path_t avCodecPath; - io::path_t avFormatPath; - io::path_t swScalePath; -}; - -FFmpegLibPaths libraryPathsForVersion(int ffmpegVer, const io::paths_t& searchPaths) +static FFmpegLibPaths libraryPathsForVersion(int ffmpegVer, const io::paths_t& searchPaths) { const std::string verStr = std::to_string(ffmpegVer); @@ -160,6 +98,51 @@ FFmpegLibPaths libraryPathsForVersion(int ffmpegVer, const io::paths_t& searchPa return result; } +FFmpegVersion versionFromAVFormatPath(const io::path_t& path) +{ + std::string name = io::filename(path, true).toStdString(); + int avVer = -1; +#if defined(Q_OS_MAC) + // libavformat.60.dylib + size_t dot = name.rfind('.'); + if (dot != std::string::npos && dot > 0) { + size_t verStart = name.rfind('.', dot - 1); + if (verStart != std::string::npos && verStart + 1 < dot) { + try { + avVer = std::stoi(name.substr(verStart + 1, dot - verStart - 1)); + } catch (...) {} + } + } +#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) + // libavformat.so.60 + size_t so = name.rfind(".so."); + if (so != std::string::npos && so + 4 < name.size()) { + try { + avVer = std::stoi(name.substr(so + 4)); + } catch (...) {} + } +#elif defined(Q_OS_WIN) + // avformat-60.dll + size_t dash = name.find('-'); + if (dash != std::string::npos && dash + 1 < name.size()) { + size_t dot = name.find('.', dash); + if (dot != std::string::npos) { + try { + avVer = std::stoi(name.substr(dash + 1, dot - dash - 1)); + } catch (...) {} + } + } +#endif + + for (const auto& [ver, componentsVersions] : FFMPEG_COMPONENTS_VERSIONS) { + if (componentsVersions.avFormatVersion == avVer) { + return ver; + } + } + + return FFMPEG_INVALID_VERION; +} + FFmpegLibPaths findLibraryPaths(const io::path_t& configPath) { FFmpegLibPaths result; @@ -184,26 +167,3 @@ FFmpegLibPaths findLibraryPaths(const io::path_t& configPath) return result; } } - -std::shared_ptr FFmpegLoader::load(const io::path_t& ffmpegLibsDir) -{ - const FFmpegLibPaths paths = findLibraryPaths(ffmpegLibsDir); - if (paths.avFormatPath.empty()) { - LOGW() << "FFmpeg libraries not found"; - return nullptr; - } - - std::shared_ptr libHandlerPtr = std::make_shared(); - if (libHandlerPtr->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, paths.swScalePath) - && libHandlerPtr->loadApi()) { - libHandlerPtr->setVersion(versionFromAVFormatPath(paths.avFormatPath)); - libHandlerPtr->setDir(dirFromAVFormatPath(paths.avFormatPath)); - - LOGD() << "FFmpeg loaded, version: " << libHandlerPtr->version(); - - return libHandlerPtr; - } - - LOGW() << "FFmpeg libraries not found"; - return nullptr; -} diff --git a/src/framework/media/internal/ffmpegutils.h b/src/framework/media/internal/ffmpegutils.h index d78e07cea3093..a8baeaa3b2fe9 100644 --- a/src/framework/media/internal/ffmpegutils.h +++ b/src/framework/media/internal/ffmpegutils.h @@ -22,7 +22,19 @@ #pragma once +#include + +#include "io/path.h" + namespace muse::media { +using FFmpegVersion = int; +static const int FFMPEG_V8 = 8; +static const int FFMPEG_V7 = 7; +static const int FFMPEG_V6 = 6; +static const int FFMPEG_V5 = 5; +static const int FFMPEG_V4 = 4; +static const int FFMPEG_INVALID_VERION = -1; + struct FFmpegVersionInfo { int avFormatVersion = -1; int avUtilVersion = -1; @@ -36,11 +48,21 @@ struct FFmpegVersionInfo { }; static const std::vector > FFMPEG_COMPONENTS_VERSIONS = { - // ffmpeg avFormat avUtil avCodec swScale - { 8, { 62, 60, 62, 9 } }, - { 7, { 61, 59, 61, 8 } }, - { 6, { 60, 58, 60, 7 } }, - { 5, { 59, 57, 59, 6 } }, - { 4, { 58, 56, 58, 5 } }, + // ffmpeg avFormat avUtil avCodec swScale + { FFMPEG_V8, { 62, 60, 62, 9 } }, + { FFMPEG_V7, { 61, 59, 61, 8 } }, + { FFMPEG_V6, { 60, 58, 60, 7 } }, + { FFMPEG_V5, { 59, 57, 59, 6 } }, + { FFMPEG_V4, { 58, 56, 58, 5 } }, }; + +struct FFmpegLibPaths { + io::path_t avUtilPath; + io::path_t avCodecPath; + io::path_t avFormatPath; + io::path_t swScalePath; +}; + +FFmpegLibPaths findLibraryPaths(const io::path_t& ffmpegLibsDir); +FFmpegVersion versionFromAVFormatPath(const io::path_t& path); } diff --git a/src/framework/media/internal/videoencoderresolver.cpp b/src/framework/media/internal/videoencoderresolver.cpp index fe82e66e1c574..99267bc13b588 100644 --- a/src/framework/media/internal/videoencoderresolver.cpp +++ b/src/framework/media/internal/videoencoderresolver.cpp @@ -22,8 +22,11 @@ #include "videoencoderresolver.h" -#include "ffmpegloader.h" -#include "videoencoder.h" +#include "internal/ffmpeg/v8/ffmpeglibhandler.h" +#include "internal/ffmpeg/v8/videoencoder.h" + +#include "io/path.h" +#include "log.h" using namespace muse::media; @@ -34,18 +37,23 @@ void VideoEncoderResolver::init() void VideoEncoderResolver::loadFFmpeg(const io::path_t& ffmpegLibsDir) { - auto ffmpegLibHandler = FFmpegLoader::load(ffmpegLibsDir); - if (!ffmpegLibHandler) { + const FFmpegLibPaths paths = findLibraryPaths(ffmpegLibsDir); + if (paths.avFormatPath.empty()) { resetFFmpegSettings(); return; } - std::shared_ptr encoder = std::make_shared(ffmpegLibHandler); - setCurrentVideoEncoder(encoder); + EncoderInfo encoderInfo = makeEncoder(paths); + if (!encoderInfo.encoder) { + resetFFmpegSettings(); + return; + } - configuration()->setFFmpegLibsDir(ffmpegLibHandler->dir()); + setCurrentVideoEncoder(encoderInfo.encoder); - m_currentEncoderFFmpegVersion = ffmpegLibHandler->version(); + configuration()->setFFmpegLibsDir(encoderInfo.ffmpegLibsDir); + + m_currentEncoderFFmpegVersion = encoderInfo.ffmpegVersion; m_loadedFFmpegChanged.notify(); } @@ -79,3 +87,34 @@ void VideoEncoderResolver::resetFFmpegSettings() m_currentEncoderFFmpegVersion = -1; configuration()->setFFmpegLibsDir({}); } + +VideoEncoderResolver::EncoderInfo VideoEncoderResolver::makeEncoder(const FFmpegLibPaths& ffmpegLibsPaths) const +{ + EncoderInfo result; + + const FFmpegVersion version = versionFromAVFormatPath(ffmpegLibsPaths.avFormatPath); + switch (version) { + case FFMPEG_V8: { + auto ffmpegLibHandler = std::make_shared(); + if (ffmpegLibHandler->loadLib(ffmpegLibsPaths.avUtilPath, ffmpegLibsPaths.avCodecPath, ffmpegLibsPaths.avFormatPath, + ffmpegLibsPaths.swScalePath) + && ffmpegLibHandler->loadApi()) { + ffmpegLibHandler->setVersion(version); + ffmpegLibHandler->setDir(io::dirpath(ffmpegLibsPaths.avFormatPath)); + + LOGD() << "FFmpeg loaded, version: " << ffmpegLibHandler->version(); + + result.encoder = std::make_shared(ffmpegLibHandler); + result.ffmpegLibsDir = ffmpegLibHandler->dir(); + result.ffmpegVersion = ffmpegLibHandler->version(); + } else { + LOGW() << "FFmpeg libraries not found"; + } + } + break; + default: + break; + } + + return result; +} diff --git a/src/framework/media/internal/videoencoderresolver.h b/src/framework/media/internal/videoencoderresolver.h index 094c737421c71..89a7fb0a83556 100644 --- a/src/framework/media/internal/videoencoderresolver.h +++ b/src/framework/media/internal/videoencoderresolver.h @@ -26,6 +26,8 @@ #include "async/asyncable.h" #include "imediaconfiguration.h" +#include "ffmpegutils.h" + #include "../ivideoencoderresolver.h" namespace muse::media { @@ -47,6 +49,14 @@ class VideoEncoderResolver : public IVideoEncoderResolver, public muse::async::A private: void resetFFmpegSettings(); + struct EncoderInfo { + IVideoEncoderPtr encoder; + FFmpegVersion ffmpegVersion = FFMPEG_INVALID_VERION; + io::path_t ffmpegLibsDir; + }; + + EncoderInfo makeEncoder(const FFmpegLibPaths& ffmpegLibsPaths) const; + IVideoEncoderPtr m_encoder; int m_currentEncoderFFmpegVersion = -1; From 88dde7c9704213b68c85e4537378dcf3a0aa5b31 Mon Sep 17 00:00:00 2001 From: Eism Date: Wed, 11 Mar 2026 11:08:15 +0200 Subject: [PATCH 21/52] added ffmpeg v7 --- src/framework/media/CMakeLists.txt | 5 + .../internal/ffmpeg/v7/ffmpeglibhandler.cpp | 223 ++++++++ .../internal/ffmpeg/v7/ffmpeglibhandler.h | 114 ++++ .../media/internal/ffmpeg/v7/videoencoder.cpp | 511 ++++++++++++++++++ .../media/internal/ffmpeg/v7/videoencoder.h | 52 ++ .../media/internal/videoencoderresolver.cpp | 23 +- 6 files changed, 926 insertions(+), 2 deletions(-) create mode 100644 src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp create mode 100644 src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h create mode 100644 src/framework/media/internal/ffmpeg/v7/videoencoder.cpp create mode 100644 src/framework/media/internal/ffmpeg/v7/videoencoder.h diff --git a/src/framework/media/CMakeLists.txt b/src/framework/media/CMakeLists.txt index 16e87c804a379..938c350e3d986 100644 --- a/src/framework/media/CMakeLists.txt +++ b/src/framework/media/CMakeLists.txt @@ -40,6 +40,11 @@ target_sources(muse_media PRIVATE internal/ffmpeg/v8/ffmpeglibhandler.h internal/ffmpeg/v8/videoencoder.cpp internal/ffmpeg/v8/videoencoder.h + + internal/ffmpeg/v7/ffmpeglibhandler.cpp + internal/ffmpeg/v7/ffmpeglibhandler.h + internal/ffmpeg/v7/videoencoder.cpp + internal/ffmpeg/v7/videoencoder.h ) target_include_directories(muse_media PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg) diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp new file mode 100644 index 0000000000000..ae44cecd8a17e --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp @@ -0,0 +1,223 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "ffmpeglibhandler.h" + +#if !defined(Q_OS_WIN) +#include +#endif + +#include "io/fileinfo.h" +#include "global/dlib.h" + +#include "log.h" + +namespace muse::media::ffmpeg::v7 { +#define RESOLVE_FROM(lib, name) do { \ + name = reinterpret_cast(getSymbol(lib, #name)); \ + if (!name) { LOGW() << "FFmpeg: missing symbol " #name; return false; } \ +} while (0) + +void* FFmpegLibHandler::getSymbol(void* lib, const char* name) const +{ + if (!lib) { + return nullptr; + } + void* sym = muse::getLibFunc(lib, name); + if (!sym) { +#if !defined(Q_OS_WIN) + sym = dlsym(RTLD_DEFAULT, name); +#endif + } + return sym; +} + +bool FFmpegLibHandler::loadApi() +{ + if (!m_avUtilLibrary || !m_avCodecLibrary || !m_avFormatLibrary || !m_swsScaleLibrary) { + return false; + } + + clearFunctions(); + + // libavutil + RESOLVE_FROM(m_avUtilLibrary, av_free); + RESOLVE_FROM(m_avUtilLibrary, av_freep); + RESOLVE_FROM(m_avUtilLibrary, av_rescale_q); + RESOLVE_FROM(m_avUtilLibrary, av_image_fill_arrays); + RESOLVE_FROM(m_avUtilLibrary, av_image_get_buffer_size); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set_pixel_fmt); + RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); + + // libavformat + RESOLVE_FROM(m_avFormatLibrary, av_guess_format); + RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); + RESOLVE_FROM(m_avFormatLibrary, av_interleaved_write_frame); + RESOLVE_FROM(m_avFormatLibrary, av_read_frame); + RESOLVE_FROM(m_avFormatLibrary, avio_open); + RESOLVE_FROM(m_avFormatLibrary, avio_close); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avformat_new_stream); + RESOLVE_FROM(m_avFormatLibrary, avformat_write_header); + RESOLVE_FROM(m_avFormatLibrary, avformat_open_input); + RESOLVE_FROM(m_avFormatLibrary, avformat_find_stream_info); + RESOLVE_FROM(m_avFormatLibrary, avformat_close_input); + RESOLVE_FROM(m_avFormatLibrary, avformat_free_context); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_output_context2); + + // libavcodec + RESOLVE_FROM(m_avCodecLibrary, av_packet_alloc); + RESOLVE_FROM(m_avCodecLibrary, av_packet_free); + RESOLVE_FROM(m_avCodecLibrary, av_packet_unref); + RESOLVE_FROM(m_avCodecLibrary, av_packet_rescale_ts); + RESOLVE_FROM(m_avCodecLibrary, avcodec_alloc_context3); + RESOLVE_FROM(m_avCodecLibrary, avcodec_find_encoder); + RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_open2); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy); + RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame); + RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet); + + // libswscale + RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); + RESOLVE_FROM(m_swsScaleLibrary, sws_scale); + + return functionsValid(); +} + +bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, + const io::path_t& swScalePath) +{ + unload(); + + // Load avutil first, then avcodec, swscale, avformat (dependency order) + if (!tryLoadPath(m_avUtilLibrary, avUtilPath) + || !tryLoadPath(m_avCodecLibrary, avCodecPath) + || !tryLoadPath(m_swsScaleLibrary, swScalePath) + || !tryLoadPath(m_avFormatLibrary, avFormatPath)) { + return false; + } + + LOGI() << "FFmpeg loaded: avutil=" << avUtilPath << ", avcodec=" << avCodecPath << ", avformat=" << avFormatPath + << ", swscale=" << swScalePath; + + return true; +} + +void FFmpegLibHandler::unload() +{ + closeLib(m_avFormatLibrary); + closeLib(m_swsScaleLibrary); + closeLib(m_avCodecLibrary); + closeLib(m_avUtilLibrary); + + clearFunctions(); + m_version = 0; + m_dir = io::path_t(); +} + +void FFmpegLibHandler::closeLib(void*& lib) +{ + if (lib) { + muse::closeLib(lib); + lib = nullptr; + } +} + +bool FFmpegLibHandler::tryLoadPath(void*& lib, const io::path_t& fullPath) +{ + if (!io::FileInfo::exists(fullPath)) { + return false; + } + + void* loaded = muse::loadLib(fullPath); + if (loaded) { + lib = loaded; + return true; + } + + return false; +} + +bool FFmpegLibHandler::functionsValid() const +{ + return av_free && av_freep && av_rescale_q + && av_image_fill_arrays && av_image_get_buffer_size + && av_opt_set && av_opt_set_int && av_opt_set_pixel_fmt + && av_guess_format && avformat_alloc_context && avformat_new_stream + && avformat_write_header && av_write_trailer + && avio_open && avio_close && av_interleaved_write_frame + && avformat_open_input && avformat_find_stream_info + && avformat_close_input && avformat_free_context + && avformat_alloc_output_context2 && av_read_frame + && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context + && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_copy + && avcodec_send_frame && avcodec_receive_packet + && av_frame_alloc + && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts + && sws_getCachedContext && sws_scale; +} + +void FFmpegLibHandler::clearFunctions() +{ + av_free = nullptr; + av_freep = nullptr; + av_rescale_q = nullptr; + av_image_fill_arrays = nullptr; + av_image_get_buffer_size = nullptr; + av_opt_set = nullptr; + av_opt_set_int = nullptr; + av_opt_set_pixel_fmt = nullptr; + av_guess_format = nullptr; + avformat_alloc_context = nullptr; + avformat_new_stream = nullptr; + avformat_write_header = nullptr; + av_write_trailer = nullptr; + avio_open = nullptr; + avio_close = nullptr; + av_interleaved_write_frame = nullptr; + avformat_open_input = nullptr; + avformat_find_stream_info = nullptr; + avformat_close_input = nullptr; + avformat_free_context = nullptr; + avformat_alloc_output_context2 = nullptr; + av_read_frame = nullptr; + avcodec_alloc_context3 = nullptr; + avcodec_find_encoder = nullptr; + avcodec_free_context = nullptr; + avcodec_open2 = nullptr; + avcodec_parameters_from_context = nullptr; + avcodec_parameters_copy = nullptr; + avcodec_send_frame = nullptr; + avcodec_receive_packet = nullptr; + av_frame_alloc = nullptr; + av_packet_alloc = nullptr; + av_packet_free = nullptr; + av_packet_unref = nullptr; + av_packet_rescale_ts = nullptr; + sws_getCachedContext = nullptr; + sws_scale = nullptr; +} +} diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h new file mode 100644 index 0000000000000..64287c1631111 --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h @@ -0,0 +1,114 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +extern "C" { +#include "thirdparty/ffmpeg/v7/libavcodec/avcodec.h" +#include "thirdparty/ffmpeg/v7/libavformat/avformat.h" +#include "thirdparty/ffmpeg/v7/libswscale/swscale.h" +} + +#include "io/path.h" + +namespace muse::media::ffmpeg::v7 { +class FFmpegLibHandler +{ +public: + FFmpegLibHandler() = default; + + bool loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, + const io::path_t& swScalePath); + bool loadApi(); + void unload(); + + int version() const { return m_version; } + void setVersion(int version) { m_version = version; } + + io::path_t dir() const { return m_dir; } + void setDir(const io::path_t& dir) { m_dir = dir; } + + // libavutil + void (*av_free)(void* ptr) = nullptr; + void (*av_freep)(void* ptr) = nullptr; + int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; + int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, + int align) = nullptr; + int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; + int (*av_opt_set)(void* obj, const char* name, const char* val, int search_flags) = nullptr; + int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; + int (*av_opt_set_pixel_fmt)(void* obj, const char* name, AVPixelFormat fmt, int search_flags) = nullptr; + + // libavformat + const AVOutputFormat*(*av_guess_format)(const char* short_name, const char* filename, const char* mime_type) = nullptr; + AVFormatContext*(*avformat_alloc_context)(void) = nullptr; + AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; + int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; + int (*av_write_trailer)(AVFormatContext* s) = nullptr; + int (*avio_open)(AVIOContext** s, const char* url, int flags) = nullptr; + int (*avio_close)(AVIOContext* s) = nullptr; + int (*av_interleaved_write_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + int (*avformat_open_input)(AVFormatContext** ctx, const char* url, const AVInputFormat* fmt, AVDictionary** options) = nullptr; + int (*avformat_find_stream_info)(AVFormatContext* ic, AVDictionary** options) = nullptr; + void (*avformat_close_input)(AVFormatContext** s) = nullptr; + void (*avformat_free_context)(AVFormatContext* s) = nullptr; + int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, const char* format_name, + const char* filename) = nullptr; + int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + + // libavcodec + AVCodecContext*(*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; + const AVCodec*(*avcodec_find_encoder)(AVCodecID id) = nullptr; + void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; + int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; + int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; + int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; + int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; + int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; + AVFrame*(*av_frame_alloc)(void) = nullptr; + AVPacket*(*av_packet_alloc)(void) = nullptr; + void (*av_packet_free)(AVPacket** pkt) = nullptr; + void (*av_packet_unref)(AVPacket* pkt) = nullptr; + void (*av_packet_rescale_ts)(AVPacket* pkt, AVRational tb_src, AVRational tb_dst) = nullptr; + + // libswscale + SwsContext*(*sws_getCachedContext)(SwsContext* context, int srcW, int srcH, AVPixelFormat srcFormat, int dstW, int dstH, + AVPixelFormat dstFormat, int flags, SwsFilter* srcFilter, SwsFilter* dstFilter, + const double* param) = nullptr; + int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t* const dst[], const int dstStride[]) = nullptr; + +private : void* getSymbol(void* lib, const char* name) const; + bool tryLoadPath(void*& lib, const io::path_t& fullPath); + void closeLib(void*& lib); + void clearFunctions(); + bool functionsValid() const; + + void* m_avUtilLibrary = nullptr; + void* m_avCodecLibrary = nullptr; + void* m_avFormatLibrary = nullptr; + void* m_swsScaleLibrary = nullptr; + + int m_version = 0; + io::path_t m_dir; +}; +} diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp new file mode 100644 index 0000000000000..0560a236d1107 --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp @@ -0,0 +1,511 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "videoencoder.h" + +#include "io/file.h" +#include "defer.h" +#include "log.h" + +namespace muse::media::ffmpeg::v7 { +struct FFmpeg { + int width = 0; + int height = 0; + unsigned int ptsCounter = 0; + + // FFmpeg stuff + const AVOutputFormat* outputFormat = nullptr; + AVFormatContext* formatCtx = nullptr; + AVStream* videoStream = nullptr; + AVCodecContext* codecCtx = nullptr; + const AVCodec* codec = nullptr; + // Frame data + AVFrame* ppicture = nullptr; + uint8_t* picture_buf = nullptr; + // Conversion + SwsContext* img_convert_ctx = nullptr; + // Packet + AVPacket* pkt; + + bool opened = false; +}; + +VideoEncoder::VideoEncoder(const std::shared_ptr& handler) + : m_ffmpegHandler(handler) +{ + m_ffmpeg = new FFmpeg(); +} + +VideoEncoder::~VideoEncoder() +{ + delete m_ffmpeg; +} + +bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) +{ + m_ffmpeg->ptsCounter = 0; + + m_ffmpeg->width = width; + m_ffmpeg->height = height; + + m_ffmpeg->outputFormat = m_ffmpegHandler->av_guess_format("mp4", NULL, NULL); + + m_ffmpeg->formatCtx = m_ffmpegHandler->avformat_alloc_context(); + if (!m_ffmpeg->formatCtx) { + LOGE() << "failed allocate format context"; + return false; + } + m_ffmpeg->formatCtx->oformat = m_ffmpeg->outputFormat; + m_ffmpeg->formatCtx->url = strdup(fileName.c_str()); + + // Add the video stream + m_ffmpeg->videoStream = m_ffmpegHandler->avformat_new_stream(m_ffmpeg->formatCtx, 0); + if (!m_ffmpeg->videoStream) { + LOGE() << "failed allocate stream"; + return false; + } + + m_ffmpeg->videoStream->time_base.den = fps; + m_ffmpeg->videoStream->time_base.num = 1; + + // find the video encoder + m_ffmpeg->codec = m_ffmpegHandler->avcodec_find_encoder(AV_CODEC_ID_H264); + if (!m_ffmpeg->codec) { + LOGE() << "not found codec"; + return false; + } + m_ffmpeg->codecCtx = m_ffmpegHandler->avcodec_alloc_context3(m_ffmpeg->codec); + if (m_ffmpeg->codecCtx == nullptr) { + LOGE() << "failed to allocate AV context"; + return false; + } + + m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; + + m_ffmpeg->codecCtx->bit_rate = bitrate; + m_ffmpeg->codecCtx->width = width; + m_ffmpeg->codecCtx->height = height; + + // Avoid bug with missing frames + m_ffmpeg->codecCtx->gop_size = gop; + m_ffmpeg->codecCtx->pix_fmt = AV_PIX_FMT_YUV420P; + m_ffmpeg->codecCtx->thread_count = 10; + + m_ffmpeg->codecCtx->time_base.den = fps; + m_ffmpeg->codecCtx->time_base.num = 1; + m_ffmpeg->codecCtx->max_b_frames = 3; + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); + + m_ffmpeg->codecCtx->me_cmp = 1; + m_ffmpeg->codecCtx->me_range = 16; + + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "hex", 1, 0); + + m_ffmpeg->codecCtx->qmin = 10; + m_ffmpeg->codecCtx->qmax = 51; + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "sc_threshold", 40, 0); + m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_LOOP_FILTER; + m_ffmpeg->codecCtx->me_subpel_quality = 5; + m_ffmpeg->codecCtx->i_quant_factor = 0.71; + m_ffmpeg->codecCtx->qcompress = 0.6; + m_ffmpeg->codecCtx->max_qdiff = 4; + + // some formats want stream headers to be separate + if (m_ffmpeg->formatCtx->oformat->flags & AVFMT_GLOBALHEADER) { + m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_LOOP_FILTER; + } + + //av_dump_format(m_ffmpeg->formatCtx, 0, fileName.c_str(), 1); + + // open_video + if (m_ffmpegHandler->avcodec_parameters_from_context(m_ffmpeg->videoStream->codecpar, m_ffmpeg->codecCtx) < 0) { + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + LOGE() << "failed to set AV parameters from context"; + return false; + } + // open the codec + if (m_ffmpegHandler->avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, 0) < 0) { + LOGE() << "failed open codec"; + return false; + } + + // Allocate the YUV frame + m_ffmpeg->ppicture = m_ffmpegHandler->av_frame_alloc(); + if (!m_ffmpeg->ppicture) { + LOGE() << "failed allocate frame"; + return false; + } + + m_ffmpeg->ppicture->width = width; + m_ffmpeg->ppicture->height = height; + m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; + + int size = m_ffmpegHandler->av_image_get_buffer_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, + m_ffmpeg->codecCtx->height, 1); + m_ffmpeg->picture_buf = new uint8_t[size]; + if (!m_ffmpeg->picture_buf) { + LOGE() << "failed allocate frame buf"; + m_ffmpegHandler->av_free(m_ffmpeg->ppicture); + return false; + } + + // Setup the planes + m_ffmpegHandler->av_image_fill_arrays(m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize, m_ffmpeg->picture_buf, + m_ffmpeg->codecCtx->pix_fmt, + m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height, 1); + + if (m_ffmpegHandler->avio_open(&m_ffmpeg->formatCtx->pb, fileName.c_str(), AVIO_FLAG_WRITE) < 0) { + LOGE() << "failed open file: " << fileName; + return false; + } + + int ret = m_ffmpegHandler->avformat_write_header(m_ffmpeg->formatCtx, NULL); + if (ret < 0) { + LOGE() << "failed write AV header"; + return false; + } + + m_ffmpeg->opened = true; + m_outputPath = fileName; + + return true; +} + +void VideoEncoder::finishEncode() +{ + if (!m_ffmpeg->opened) { + return; + } + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, NULL); + if (ret < 0) { + LOGE() << "failed to flush encoder buffer"; + return; + } + + while (true) { + m_ffmpeg->pkt = m_ffmpegHandler->av_packet_alloc(); + int ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + break; + } else if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + LOGE() << "error during encoding"; + return; + } + + m_ffmpeg->pkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + + m_ffmpeg->ptsCounter++; + + ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return; + } + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + } + + m_ffmpegHandler->av_write_trailer(m_ffmpeg->formatCtx); + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; +} + +void VideoEncoder::close() +{ + if (!m_ffmpeg->opened) { + return; + } + + // close_video + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + + if (m_ffmpeg->picture_buf) { + delete[] m_ffmpeg->picture_buf; + m_ffmpeg->picture_buf = 0; + } + + if (m_ffmpeg->ppicture) { + m_ffmpegHandler->av_free(m_ffmpeg->ppicture); + m_ffmpeg->ppicture = 0; + } + + /* free the streams */ + + for (unsigned int i = 0; i < m_ffmpeg->formatCtx->nb_streams; i++) { + m_ffmpegHandler->av_freep(&m_ffmpeg->formatCtx->streams[i]); + } + + // Close file + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; + + // Free the stream + m_ffmpegHandler->av_free(m_ffmpeg->formatCtx); + m_ffmpeg->formatCtx = nullptr; + m_ffmpeg->opened = false; + + m_outputPath = io::path_t(); +} + +bool VideoEncoder::encodeImage(const QImage& img) +{ + if (!m_ffmpeg->opened) { + return false; + } + + convertImage_sws(img); + + m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->codecCtx->frame_num, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); + if (ret < 0) { + return false; + } + + while (ret >= 0) { + m_ffmpeg->pkt = m_ffmpegHandler->av_packet_alloc(); + ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return true; + } else if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + LOGE() << "error during encoding"; + return false; + } + + m_ffmpeg->pkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + + m_ffmpeg->ptsCounter++; + + ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return false; + } + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + } + + return true; +} + +bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) +{ + if (m_outputPath.empty()) { + LOGE() << "addAudio: encoder was not opened or path not set"; + return false; + } + + const io::path_t videoPath = m_outputPath; + const io::path_t tmpPath = m_outputPath + ".tmp"; + + AVFormatContext* videoFmtCtx = nullptr; + AVFormatContext* audioFmtCtx = nullptr; + AVFormatContext* outputFmtCtx = nullptr; + + auto cleanup = [&]() { + if (videoFmtCtx) { + m_ffmpegHandler->avformat_close_input(&videoFmtCtx); + } + if (audioFmtCtx) { + m_ffmpegHandler->avformat_close_input(&audioFmtCtx); + } + if (outputFmtCtx) { + if (outputFmtCtx->pb) { + m_ffmpegHandler->avio_close(outputFmtCtx->pb); + } + m_ffmpegHandler->avformat_free_context(outputFmtCtx); + } + }; + + DEFER { + cleanup(); + }; + + if (m_ffmpegHandler->avformat_open_input(&videoFmtCtx, videoPath.c_str(), nullptr, nullptr) < 0) { + LOGE() << "addAudio: failed to open video input: " << videoPath; + return false; + } + if (m_ffmpegHandler->avformat_find_stream_info(videoFmtCtx, nullptr) < 0) { + LOGE() << "addAudio: failed to find video stream info"; + return false; + } + + if (m_ffmpegHandler->avformat_open_input(&audioFmtCtx, audioPath.c_str(), nullptr, nullptr) < 0) { + LOGE() << "addAudio: failed to open audio input: " << audioPath; + return false; + } + if (m_ffmpegHandler->avformat_find_stream_info(audioFmtCtx, nullptr) < 0) { + LOGE() << "addAudio: failed to find audio stream info"; + return false; + } + + if (m_ffmpegHandler->avformat_alloc_output_context2(&outputFmtCtx, nullptr, "mp4", tmpPath.c_str()) < 0 || !outputFmtCtx) { + LOGE() << "addAudio: failed to allocate output context"; + return false; + } + + int videoInIdx = -1; + int audioInIdx = -1; + int outVideoIdx = -1; + int outAudioIdx = -1; + + for (unsigned i = 0; i < videoFmtCtx->nb_streams; i++) { + if (videoFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + videoInIdx = static_cast(i); + AVStream* outStream = m_ffmpegHandler->avformat_new_stream(outputFmtCtx, nullptr); + if (!outStream) { + LOGE() << "addAudio: failed to create output video stream"; + return false; + } + m_ffmpegHandler->avcodec_parameters_copy(outStream->codecpar, videoFmtCtx->streams[i]->codecpar); + outStream->codecpar->codec_tag = 0; + outStream->time_base = videoFmtCtx->streams[i]->time_base; + outVideoIdx = outStream->index; + break; + } + } + + for (unsigned i = 0; i < audioFmtCtx->nb_streams; i++) { + if (audioFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + audioInIdx = static_cast(i); + AVStream* outStream = m_ffmpegHandler->avformat_new_stream(outputFmtCtx, nullptr); + if (!outStream) { + LOGE() << "addAudio: failed to create output audio stream"; + return false; + } + m_ffmpegHandler->avcodec_parameters_copy(outStream->codecpar, audioFmtCtx->streams[i]->codecpar); + outStream->codecpar->codec_tag = 0; + outStream->time_base = audioFmtCtx->streams[i]->time_base; + outAudioIdx = outStream->index; + break; + } + } + + if (videoInIdx < 0 || audioInIdx < 0) { + LOGE() << "addAudio: could not find video or audio stream"; + return false; + } + + if (m_ffmpegHandler->avio_open(&outputFmtCtx->pb, tmpPath.c_str(), AVIO_FLAG_WRITE) < 0) { + LOGE() << "addAudio: failed to open output file: " << tmpPath; + return false; + } + + if (m_ffmpegHandler->avformat_write_header(outputFmtCtx, nullptr) < 0) { + LOGE() << "addAudio: failed to write header"; + return false; + } + + int64_t audioOffsetPts = 0; + { + AVStream* audioOutStream = outputFmtCtx->streams[outAudioIdx]; + audioOffsetPts = static_cast(audioOffsetSec * audioOutStream->time_base.den + / audioOutStream->time_base.num); + } + + AVPacket* pkt = m_ffmpegHandler->av_packet_alloc(); + + while (m_ffmpegHandler->av_read_frame(videoFmtCtx, pkt) >= 0) { + if (pkt->stream_index == videoInIdx) { + pkt->stream_index = outVideoIdx; + m_ffmpegHandler->av_packet_rescale_ts(pkt, videoFmtCtx->streams[videoInIdx]->time_base, + outputFmtCtx->streams[outVideoIdx]->time_base); + pkt->pos = -1; + m_ffmpegHandler->av_interleaved_write_frame(outputFmtCtx, pkt); + } + m_ffmpegHandler->av_packet_unref(pkt); + } + + while (m_ffmpegHandler->av_read_frame(audioFmtCtx, pkt) >= 0) { + if (pkt->stream_index == audioInIdx) { + pkt->stream_index = outAudioIdx; + m_ffmpegHandler->av_packet_rescale_ts(pkt, audioFmtCtx->streams[audioInIdx]->time_base, + outputFmtCtx->streams[outAudioIdx]->time_base); + pkt->pts += audioOffsetPts; + pkt->dts += audioOffsetPts; + pkt->pos = -1; + m_ffmpegHandler->av_interleaved_write_frame(outputFmtCtx, pkt); + } + m_ffmpegHandler->av_packet_unref(pkt); + } + + m_ffmpegHandler->av_packet_free(&pkt); + m_ffmpegHandler->av_write_trailer(outputFmtCtx); + + if (!io::File::copy(tmpPath, videoPath, true)) { + LOGE() << "addAudio: failed to replace with muxed file"; + return false; + } + + io::File::remove(tmpPath); + + return true; +} + +bool VideoEncoder::convertImage_sws(const QImage& img) +{ + // Check if the image matches the size + if (img.width() != m_ffmpeg->width || img.height() != m_ffmpeg->height) { + LOGE() << "wrong image size!"; + return false; + } + + if (img.format() != QImage::Format_RGB32 && img.format() != QImage::Format_ARGB32) { + LOGE() << "wrong image format"; + return false; + } + + m_ffmpeg->img_convert_ctx = m_ffmpegHandler->sws_getCachedContext(m_ffmpeg->img_convert_ctx, m_ffmpeg->width, m_ffmpeg->height, + AV_PIX_FMT_BGRA, + m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, + NULL, NULL, NULL); + + if (!m_ffmpeg->img_convert_ctx) { + LOGE() << "failed initialize the conversion context"; + return false; + } + + uint8_t* srcplanes[3]; + srcplanes[0] = (uint8_t*)img.bits(); + srcplanes[1] = 0; + srcplanes[2] = 0; + + int srcstride[3]; + srcstride[0] = img.bytesPerLine(); + srcstride[1] = 0; + srcstride[2 ]= 0; + + m_ffmpegHandler->sws_scale(m_ffmpeg->img_convert_ctx, srcplanes, srcstride, 0, m_ffmpeg->height, m_ffmpeg->ppicture->data, + m_ffmpeg->ppicture->linesize); + + return true; +} +} diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.h b/src/framework/media/internal/ffmpeg/v7/videoencoder.h new file mode 100644 index 0000000000000..f83f4b76d3bab --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.h @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "media/ivideoencoder.h" + +#include "ffmpeglibhandler.h" + +namespace muse::media::ffmpeg::v7 { +struct FFmpeg; +class VideoEncoder : public IVideoEncoder +{ +public: + explicit VideoEncoder(const std::shared_ptr& handler); + ~VideoEncoder() override; + + bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; + void close() override; + + bool encodeImage(const QImage& img) override; + void finishEncode() override; + + bool addAudio(const muse::io::path_t& audioPath, double audioOffsetSec) override; + +private: + bool convertImage_sws(const QImage& img); + + std::shared_ptr m_ffmpegHandler = nullptr; + FFmpeg* m_ffmpeg = nullptr; + muse::io::path_t m_outputPath; +}; +} diff --git a/src/framework/media/internal/videoencoderresolver.cpp b/src/framework/media/internal/videoencoderresolver.cpp index 99267bc13b588..d43a48b1c1ba2 100644 --- a/src/framework/media/internal/videoencoderresolver.cpp +++ b/src/framework/media/internal/videoencoderresolver.cpp @@ -25,6 +25,9 @@ #include "internal/ffmpeg/v8/ffmpeglibhandler.h" #include "internal/ffmpeg/v8/videoencoder.h" +#include "internal/ffmpeg/v7/ffmpeglibhandler.h" +#include "internal/ffmpeg/v7/videoencoder.h" + #include "io/path.h" #include "log.h" @@ -110,8 +113,24 @@ VideoEncoderResolver::EncoderInfo VideoEncoderResolver::makeEncoder(const FFmpeg } else { LOGW() << "FFmpeg libraries not found"; } - } - break; + } break; + case FFMPEG_V7: { + auto ffmpegLibHandler = std::make_shared(); + if (ffmpegLibHandler->loadLib(ffmpegLibsPaths.avUtilPath, ffmpegLibsPaths.avCodecPath, ffmpegLibsPaths.avFormatPath, + ffmpegLibsPaths.swScalePath) + && ffmpegLibHandler->loadApi()) { + ffmpegLibHandler->setVersion(version); + ffmpegLibHandler->setDir(io::dirpath(ffmpegLibsPaths.avFormatPath)); + + LOGD() << "FFmpeg loaded, version: " << ffmpegLibHandler->version(); + + result.encoder = std::make_shared(ffmpegLibHandler); + result.ffmpegLibsDir = ffmpegLibHandler->dir(); + result.ffmpegVersion = ffmpegLibHandler->version(); + } else { + LOGW() << "FFmpeg libraries not found"; + } + } break; default: break; } From 4024a495fd3f8d5b4d64ec8c9db35024fbf4a34c Mon Sep 17 00:00:00 2001 From: Eism Date: Thu, 12 Mar 2026 11:50:06 +0200 Subject: [PATCH 22/52] added libswresample --- .../thirdparty/ffmpeg/copy_ffmpeg_headers.sh | 3 +- .../ffmpeg/download_ffmpeg_headers.sh | 4 +- .../ffmpeg/v4/libswresample/swresample.h | 579 ++++++++++++++++ .../ffmpeg/v4/libswresample/version.h | 45 ++ .../ffmpeg/v5/libswresample/swresample.h | 650 ++++++++++++++++++ .../ffmpeg/v5/libswresample/version.h | 46 ++ .../ffmpeg/v5/libswresample/version_major.h | 31 + .../ffmpeg/v6/libswresample/swresample.h | 650 ++++++++++++++++++ .../ffmpeg/v6/libswresample/version.h | 46 ++ .../ffmpeg/v6/libswresample/version_major.h | 31 + .../ffmpeg/v7/libswresample/swresample.h | 587 ++++++++++++++++ .../ffmpeg/v7/libswresample/version.h | 46 ++ .../ffmpeg/v7/libswresample/version_major.h | 31 + .../ffmpeg/v8/libswresample/swresample.h | 587 ++++++++++++++++ .../ffmpeg/v8/libswresample/version.h | 46 ++ .../ffmpeg/v8/libswresample/version_major.h | 31 + 16 files changed, 3410 insertions(+), 3 deletions(-) create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libswresample/swresample.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libswresample/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libswresample/swresample.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libswresample/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v5/libswresample/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libswresample/swresample.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libswresample/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v6/libswresample/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libswresample/swresample.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libswresample/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v7/libswresample/version_major.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libswresample/swresample.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libswresample/version.h create mode 100644 src/framework/media/thirdparty/ffmpeg/v8/libswresample/version_major.h diff --git a/src/framework/media/thirdparty/ffmpeg/copy_ffmpeg_headers.sh b/src/framework/media/thirdparty/ffmpeg/copy_ffmpeg_headers.sh index 945d5fd36bcab..6a7a729be9795 100755 --- a/src/framework/media/thirdparty/ffmpeg/copy_ffmpeg_headers.sh +++ b/src/framework/media/thirdparty/ffmpeg/copy_ffmpeg_headers.sh @@ -12,7 +12,8 @@ libavutil/avstring.h libavutil/opt.h libavutil/mem.h libswscale/swscale.h -libavutil/imgutils.h" +libavutil/imgutils.h +libswresample/swresample.h" NL=' ' diff --git a/src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh b/src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh index 8d9d1a6a52cbe..1b1e92aa84af8 100644 --- a/src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh +++ b/src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh @@ -53,7 +53,7 @@ if [ ! -d "$FFMPEG_DIR" ]; then echo "Cloning FFmpeg (sparse checkout)..." git clone --depth 1 --filter=blob:none --sparse https://github.com/FFmpeg/FFmpeg.git "$FFMPEG_DIR" cd "$FFMPEG_DIR" - git sparse-checkout set libavcodec libavformat libavutil libswscale + git sparse-checkout set libavcodec libavformat libavutil libswscale libswresample cd - > /dev/null else echo "Using existing FFmpeg clone: $FFMPEG_DIR" @@ -71,7 +71,7 @@ for ver_spec in "${VERSIONS[@]}"; do git fetch --depth 1 origin tag "$tag" 2>/dev/null || true git checkout "$tag" - git sparse-checkout set libavcodec libavformat libavutil libswscale + git sparse-checkout set libavcodec libavformat libavutil libswscale libswresample mkdir -p "$target" diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libswresample/swresample.h b/src/framework/media/thirdparty/ffmpeg/v4/libswresample/swresample.h new file mode 100644 index 0000000000000..c7b84fbcac526 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libswresample/swresample.h @@ -0,0 +1,579 @@ +/* + * Copyright (C) 2011-2013 Michael Niedermayer (michaelni@gmx.at) + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_SWRESAMPLE_H +#define SWRESAMPLE_SWRESAMPLE_H + +/** + * @file + * @ingroup lswr + * libswresample public header + */ + +/** + * @defgroup lswr libswresample + * @{ + * + * Audio resampling, sample format conversion and mixing library. + * + * Interaction with lswr is done through SwrContext, which is + * allocated with swr_alloc() or swr_alloc_set_opts(). It is opaque, so all parameters + * must be set with the @ref avoptions API. + * + * The first thing you will need to do in order to use lswr is to allocate + * SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts(). If you + * are using the former, you must set options through the @ref avoptions API. + * The latter function provides the same feature, but it allows you to set some + * common options in the same statement. + * + * For example the following code will setup conversion from planar float sample + * format to interleaved signed 16-bit integer, downsampling from 48kHz to + * 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing + * matrix). This is using the swr_alloc() function. + * @code + * SwrContext *swr = swr_alloc(); + * av_opt_set_channel_layout(swr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0); + * av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); + * av_opt_set_int(swr, "in_sample_rate", 48000, 0); + * av_opt_set_int(swr, "out_sample_rate", 44100, 0); + * av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); + * av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + * @endcode + * + * The same job can be done using swr_alloc_set_opts() as well: + * @code + * SwrContext *swr = swr_alloc_set_opts(NULL, // we're allocating a new context + * AV_CH_LAYOUT_STEREO, // out_ch_layout + * AV_SAMPLE_FMT_S16, // out_sample_fmt + * 44100, // out_sample_rate + * AV_CH_LAYOUT_5POINT1, // in_ch_layout + * AV_SAMPLE_FMT_FLTP, // in_sample_fmt + * 48000, // in_sample_rate + * 0, // log_offset + * NULL); // log_ctx + * @endcode + * + * Once all values have been set, it must be initialized with swr_init(). If + * you need to change the conversion parameters, you can change the parameters + * using @ref AVOptions, as described above in the first example; or by using + * swr_alloc_set_opts(), but with the first argument the allocated context. + * You must then call swr_init() again. + * + * The conversion itself is done by repeatedly calling swr_convert(). + * Note that the samples may get buffered in swr if you provide insufficient + * output space or if sample rate conversion is done, which requires "future" + * samples. Samples that do not require future input can be retrieved at any + * time by using swr_convert() (in_count can be set to 0). + * At the end of conversion the resampling buffer can be flushed by calling + * swr_convert() with NULL in and 0 in_count. + * + * The samples used in the conversion process can be managed with the libavutil + * @ref lavu_sampmanip "samples manipulation" API, including av_samples_alloc() + * function used in the following example. + * + * The delay between input and output, can at any time be found by using + * swr_get_delay(). + * + * The following code demonstrates the conversion loop assuming the parameters + * from above and caller-defined functions get_input() and handle_output(): + * @code + * uint8_t **input; + * int in_samples; + * + * while (get_input(&input, &in_samples)) { + * uint8_t *output; + * int out_samples = av_rescale_rnd(swr_get_delay(swr, 48000) + + * in_samples, 44100, 48000, AV_ROUND_UP); + * av_samples_alloc(&output, NULL, 2, out_samples, + * AV_SAMPLE_FMT_S16, 0); + * out_samples = swr_convert(swr, &output, out_samples, + * input, in_samples); + * handle_output(output, out_samples); + * av_freep(&output); + * } + * @endcode + * + * When the conversion is finished, the conversion + * context and everything associated with it must be freed with swr_free(). + * A swr_close() function is also available, but it exists mainly for + * compatibility with libavresample, and is not required to be called. + * + * There will be no memory leak if the data is not completely flushed before + * swr_free(). + */ + +#include +#include "libavutil/channel_layout.h" +#include "libavutil/frame.h" +#include "libavutil/samplefmt.h" + +#include "libswresample/version.h" + +/** + * @name Option constants + * These constants are used for the @ref avoptions interface for lswr. + * @{ + * + */ + +#define SWR_FLAG_RESAMPLE 1 ///< Force resampling even if equal sample rate +//TODO use int resample ? +//long term TODO can we enable this dynamically? + +/** Dithering algorithms */ +enum SwrDitherType { + SWR_DITHER_NONE = 0, + SWR_DITHER_RECTANGULAR, + SWR_DITHER_TRIANGULAR, + SWR_DITHER_TRIANGULAR_HIGHPASS, + + SWR_DITHER_NS = 64, ///< not part of API/ABI + SWR_DITHER_NS_LIPSHITZ, + SWR_DITHER_NS_F_WEIGHTED, + SWR_DITHER_NS_MODIFIED_E_WEIGHTED, + SWR_DITHER_NS_IMPROVED_E_WEIGHTED, + SWR_DITHER_NS_SHIBATA, + SWR_DITHER_NS_LOW_SHIBATA, + SWR_DITHER_NS_HIGH_SHIBATA, + SWR_DITHER_NB, ///< not part of API/ABI +}; + +/** Resampling Engines */ +enum SwrEngine { + SWR_ENGINE_SWR, /**< SW Resampler */ + SWR_ENGINE_SOXR, /**< SoX Resampler */ + SWR_ENGINE_NB, ///< not part of API/ABI +}; + +/** Resampling Filter Types */ +enum SwrFilterType { + SWR_FILTER_TYPE_CUBIC, /**< Cubic */ + SWR_FILTER_TYPE_BLACKMAN_NUTTALL, /**< Blackman Nuttall windowed sinc */ + SWR_FILTER_TYPE_KAISER, /**< Kaiser windowed sinc */ +}; + +/** + * @} + */ + +/** + * The libswresample context. Unlike libavcodec and libavformat, this structure + * is opaque. This means that if you would like to set options, you must use + * the @ref avoptions API and cannot directly set values to members of the + * structure. + */ +typedef struct SwrContext SwrContext; + +/** + * Get the AVClass for SwrContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + * @return the AVClass of SwrContext + */ +const AVClass *swr_get_class(void); + +/** + * @name SwrContext constructor functions + * @{ + */ + +/** + * Allocate SwrContext. + * + * If you use this function you will need to set the parameters (manually or + * with swr_alloc_set_opts()) before calling swr_init(). + * + * @see swr_alloc_set_opts(), swr_init(), swr_free() + * @return NULL on error, allocated context otherwise + */ +struct SwrContext *swr_alloc(void); + +/** + * Initialize context after user parameters have been set. + * @note The context must be configured using the AVOption API. + * + * @see av_opt_set_int() + * @see av_opt_set_dict() + * + * @param[in,out] s Swr context to initialize + * @return AVERROR error code in case of failure. + */ +int swr_init(struct SwrContext *s); + +/** + * Check whether an swr context has been initialized or not. + * + * @param[in] s Swr context to check + * @see swr_init() + * @return positive if it has been initialized, 0 if not initialized + */ +int swr_is_initialized(struct SwrContext *s); + +/** + * Allocate SwrContext if needed and set/reset common parameters. + * + * This function does not require s to be allocated with swr_alloc(). On the + * other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters + * on the allocated context. + * + * @param s existing Swr context if available, or NULL if not + * @param out_ch_layout output channel layout (AV_CH_LAYOUT_*) + * @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*). + * @param out_sample_rate output sample rate (frequency in Hz) + * @param in_ch_layout input channel layout (AV_CH_LAYOUT_*) + * @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*). + * @param in_sample_rate input sample rate (frequency in Hz) + * @param log_offset logging level offset + * @param log_ctx parent logging context, can be NULL + * + * @see swr_init(), swr_free() + * @return NULL on error, allocated context otherwise + */ +struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, + int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx); + +/** + * @} + * + * @name SwrContext destructor functions + * @{ + */ + +/** + * Free the given SwrContext and set the pointer to NULL. + * + * @param[in] s a pointer to a pointer to Swr context + */ +void swr_free(struct SwrContext **s); + +/** + * Closes the context so that swr_is_initialized() returns 0. + * + * The context can be brought back to life by running swr_init(), + * swr_init() can also be used without swr_close(). + * This function is mainly provided for simplifying the usecase + * where one tries to support libavresample and libswresample. + * + * @param[in,out] s Swr context to be closed + */ +void swr_close(struct SwrContext *s); + +/** + * @} + * + * @name Core conversion functions + * @{ + */ + +/** Convert audio. + * + * in and in_count can be set to 0 to flush the last few samples out at the + * end. + * + * If more input is provided than output space, then the input will be buffered. + * You can avoid this buffering by using swr_get_out_samples() to retrieve an + * upper bound on the required number of output samples for the given number of + * input samples. Conversion will run directly without copying whenever possible. + * + * @param s allocated Swr context, with parameters set + * @param out output buffers, only the first one need be set in case of packed audio + * @param out_count amount of space available for output in samples per channel + * @param in input buffers, only the first one need to be set in case of packed audio + * @param in_count number of input samples available in one channel + * + * @return number of samples output per channel, negative value on error + */ +int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, + const uint8_t **in , int in_count); + +/** + * Convert the next timestamp from input to output + * timestamps are in 1/(in_sample_rate * out_sample_rate) units. + * + * @note There are 2 slightly differently behaving modes. + * @li When automatic timestamp compensation is not used, (min_compensation >= FLT_MAX) + * in this case timestamps will be passed through with delays compensated + * @li When automatic timestamp compensation is used, (min_compensation < FLT_MAX) + * in this case the output timestamps will match output sample numbers. + * See ffmpeg-resampler(1) for the two modes of compensation. + * + * @param s[in] initialized Swr context + * @param pts[in] timestamp for the next input sample, INT64_MIN if unknown + * @see swr_set_compensation(), swr_drop_output(), and swr_inject_silence() are + * function used internally for timestamp compensation. + * @return the output timestamp for the next output sample + */ +int64_t swr_next_pts(struct SwrContext *s, int64_t pts); + +/** + * @} + * + * @name Low-level option setting functions + * These functons provide a means to set low-level options that is not possible + * with the AVOption API. + * @{ + */ + +/** + * Activate resampling compensation ("soft" compensation). This function is + * internally called when needed in swr_next_pts(). + * + * @param[in,out] s allocated Swr context. If it is not initialized, + * or SWR_FLAG_RESAMPLE is not set, swr_init() is + * called with the flag set. + * @param[in] sample_delta delta in PTS per sample + * @param[in] compensation_distance number of samples to compensate for + * @return >= 0 on success, AVERROR error codes if: + * @li @c s is NULL, + * @li @c compensation_distance is less than 0, + * @li @c compensation_distance is 0 but sample_delta is not, + * @li compensation unsupported by resampler, or + * @li swr_init() fails when called. + */ +int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance); + +/** + * Set a customized input channel mapping. + * + * @param[in,out] s allocated Swr context, not yet initialized + * @param[in] channel_map customized input channel mapping (array of channel + * indexes, -1 for a muted channel) + * @return >= 0 on success, or AVERROR error code in case of failure. + */ +int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); + +/** + * Generate a channel mixing matrix. + * + * This function is the one used internally by libswresample for building the + * default mixing matrix. It is made public just as a utility function for + * building custom matrices. + * + * @param in_layout input channel layout + * @param out_layout output channel layout + * @param center_mix_level mix level for the center channel + * @param surround_mix_level mix level for the surround channel(s) + * @param lfe_mix_level mix level for the low-frequency effects channel + * @param rematrix_maxval if 1.0, coefficients will be normalized to prevent + * overflow. if INT_MAX, coefficients will not be + * normalized. + * @param[out] matrix mixing coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o. + * @param stride distance between adjacent input channels in the + * matrix array + * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii) + * @param log_ctx parent logging context, can be NULL + * @return 0 on success, negative AVERROR code on failure + */ +int swr_build_matrix(uint64_t in_layout, uint64_t out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double rematrix_maxval, + double rematrix_volume, double *matrix, + int stride, enum AVMatrixEncoding matrix_encoding, + void *log_ctx); + +/** + * Set a customized remix matrix. + * + * @param s allocated Swr context, not yet initialized + * @param matrix remix coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o + * @param stride offset between lines of the matrix + * @return >= 0 on success, or AVERROR error code in case of failure. + */ +int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride); + +/** + * @} + * + * @name Sample handling functions + * @{ + */ + +/** + * Drops the specified number of output samples. + * + * This function, along with swr_inject_silence(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure + */ +int swr_drop_output(struct SwrContext *s, int count); + +/** + * Injects the specified number of silence samples. + * + * This function, along with swr_drop_output(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure + */ +int swr_inject_silence(struct SwrContext *s, int count); + +/** + * Gets the delay the next input sample will experience relative to the next output sample. + * + * Swresample can buffer data if more input has been provided than available + * output space, also converting between sample rates needs a delay. + * This function returns the sum of all such delays. + * The exact delay is not necessarily an integer value in either input or + * output sample rate. Especially when downsampling by a large value, the + * output sample rate may be a poor choice to represent the delay, similarly + * for upsampling and the input sample rate. + * + * @param s swr context + * @param base timebase in which the returned delay will be: + * @li if it's set to 1 the returned delay is in seconds + * @li if it's set to 1000 the returned delay is in milliseconds + * @li if it's set to the input sample rate then the returned + * delay is in input samples + * @li if it's set to the output sample rate then the returned + * delay is in output samples + * @li if it's the least common multiple of in_sample_rate and + * out_sample_rate then an exact rounding-free delay will be + * returned + * @returns the delay in 1 / @c base units. + */ +int64_t swr_get_delay(struct SwrContext *s, int64_t base); + +/** + * Find an upper bound on the number of samples that the next swr_convert + * call will output, if called with in_samples of input samples. This + * depends on the internal state, and anything changing the internal state + * (like further swr_convert() calls) will may change the number of samples + * swr_get_out_samples() returns for the same number of input samples. + * + * @param in_samples number of input samples. + * @note any call to swr_inject_silence(), swr_convert(), swr_next_pts() + * or swr_set_compensation() invalidates this limit + * @note it is recommended to pass the correct available buffer size + * to all functions like swr_convert() even if swr_get_out_samples() + * indicates that less would be used. + * @returns an upper bound on the number of samples that the next swr_convert + * will output or a negative value to indicate an error + */ +int swr_get_out_samples(struct SwrContext *s, int in_samples); + +/** + * @} + * + * @name Configuration accessors + * @{ + */ + +/** + * Return the @ref LIBSWRESAMPLE_VERSION_INT constant. + * + * This is useful to check if the build-time libswresample has the same version + * as the run-time one. + * + * @returns the unsigned int-typed version + */ +unsigned swresample_version(void); + +/** + * Return the swr build-time configuration. + * + * @returns the build-time @c ./configure flags + */ +const char *swresample_configuration(void); + +/** + * Return the swr license. + * + * @returns the license of libswresample, determined at build-time + */ +const char *swresample_license(void); + +/** + * @} + * + * @name AVFrame based API + * @{ + */ + +/** + * Convert the samples in the input AVFrame and write them to the output AVFrame. + * + * Input and output AVFrames must have channel_layout, sample_rate and format set. + * + * If the output AVFrame does not have the data pointers allocated the nb_samples + * field will be set using av_frame_get_buffer() + * is called to allocate the frame. + * + * The output AVFrame can be NULL or have fewer allocated samples than required. + * In this case, any remaining samples not written to the output will be added + * to an internal FIFO buffer, to be returned at the next call to this function + * or to swr_convert(). + * + * If converting sample rate, there may be data remaining in the internal + * resampling delay buffer. swr_get_delay() tells the number of + * remaining samples. To get this data as output, call this function or + * swr_convert() with NULL input. + * + * If the SwrContext configuration does not match the output and + * input AVFrame settings the conversion does not take place and depending on + * which AVFrame is not matching AVERROR_OUTPUT_CHANGED, AVERROR_INPUT_CHANGED + * or the result of a bitwise-OR of them is returned. + * + * @see swr_delay() + * @see swr_convert() + * @see swr_get_delay() + * + * @param swr audio resample context + * @param output output AVFrame + * @param input input AVFrame + * @return 0 on success, AVERROR on failure or nonmatching + * configuration. + */ +int swr_convert_frame(SwrContext *swr, + AVFrame *output, const AVFrame *input); + +/** + * Configure or reconfigure the SwrContext using the information + * provided by the AVFrames. + * + * The original resampling context is reset even on failure. + * The function calls swr_close() internally if the context is open. + * + * @see swr_close(); + * + * @param swr audio resample context + * @param output output AVFrame + * @param input input AVFrame + * @return 0 on success, AVERROR on failure. + */ +int swr_config_frame(SwrContext *swr, const AVFrame *out, const AVFrame *in); + +/** + * @} + * @} + */ + +#endif /* SWRESAMPLE_SWRESAMPLE_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libswresample/version.h b/src/framework/media/thirdparty/ffmpeg/v4/libswresample/version.h new file mode 100644 index 0000000000000..0a99e0f135049 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libswresample/version.h @@ -0,0 +1,45 @@ +/* + * Version macros. + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_VERSION_H +#define SWRESAMPLE_VERSION_H + +/** + * @file + * Libswresample version macros + */ + +#include "libavutil/avutil.h" + +#define LIBSWRESAMPLE_VERSION_MAJOR 3 +#define LIBSWRESAMPLE_VERSION_MINOR 9 +#define LIBSWRESAMPLE_VERSION_MICRO 100 + +#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) +#define LIBSWRESAMPLE_VERSION AV_VERSION(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) +#define LIBSWRESAMPLE_BUILD LIBSWRESAMPLE_VERSION_INT + +#define LIBSWRESAMPLE_IDENT "SwR" AV_STRINGIFY(LIBSWRESAMPLE_VERSION) + +#endif /* SWRESAMPLE_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libswresample/swresample.h b/src/framework/media/thirdparty/ffmpeg/v5/libswresample/swresample.h new file mode 100644 index 0000000000000..26d42fab8d7b2 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libswresample/swresample.h @@ -0,0 +1,650 @@ +/* + * Copyright (C) 2011-2013 Michael Niedermayer (michaelni@gmx.at) + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_SWRESAMPLE_H +#define SWRESAMPLE_SWRESAMPLE_H + +/** + * @file + * @ingroup lswr + * libswresample public header + */ + +/** + * @defgroup lswr libswresample + * @{ + * + * Audio resampling, sample format conversion and mixing library. + * + * Interaction with lswr is done through SwrContext, which is + * allocated with swr_alloc() or swr_alloc_set_opts2(). It is opaque, so all parameters + * must be set with the @ref avoptions API. + * + * The first thing you will need to do in order to use lswr is to allocate + * SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts2(). If you + * are using the former, you must set options through the @ref avoptions API. + * The latter function provides the same feature, but it allows you to set some + * common options in the same statement. + * + * For example the following code will setup conversion from planar float sample + * format to interleaved signed 16-bit integer, downsampling from 48kHz to + * 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing + * matrix). This is using the swr_alloc() function. + * @code + * SwrContext *swr = swr_alloc(); + * av_opt_set_channel_layout(swr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0); + * av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); + * av_opt_set_int(swr, "in_sample_rate", 48000, 0); + * av_opt_set_int(swr, "out_sample_rate", 44100, 0); + * av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); + * av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + * @endcode + * + * The same job can be done using swr_alloc_set_opts2() as well: + * @code + * SwrContext *swr = NULL; + * int ret = swr_alloc_set_opts2(&swr, // we're allocating a new context + * &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO, // out_ch_layout + * AV_SAMPLE_FMT_S16, // out_sample_fmt + * 44100, // out_sample_rate + * &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1, // in_ch_layout + * AV_SAMPLE_FMT_FLTP, // in_sample_fmt + * 48000, // in_sample_rate + * 0, // log_offset + * NULL); // log_ctx + * @endcode + * + * Once all values have been set, it must be initialized with swr_init(). If + * you need to change the conversion parameters, you can change the parameters + * using @ref AVOptions, as described above in the first example; or by using + * swr_alloc_set_opts2(), but with the first argument the allocated context. + * You must then call swr_init() again. + * + * The conversion itself is done by repeatedly calling swr_convert(). + * Note that the samples may get buffered in swr if you provide insufficient + * output space or if sample rate conversion is done, which requires "future" + * samples. Samples that do not require future input can be retrieved at any + * time by using swr_convert() (in_count can be set to 0). + * At the end of conversion the resampling buffer can be flushed by calling + * swr_convert() with NULL in and 0 in_count. + * + * The samples used in the conversion process can be managed with the libavutil + * @ref lavu_sampmanip "samples manipulation" API, including av_samples_alloc() + * function used in the following example. + * + * The delay between input and output, can at any time be found by using + * swr_get_delay(). + * + * The following code demonstrates the conversion loop assuming the parameters + * from above and caller-defined functions get_input() and handle_output(): + * @code + * uint8_t **input; + * int in_samples; + * + * while (get_input(&input, &in_samples)) { + * uint8_t *output; + * int out_samples = av_rescale_rnd(swr_get_delay(swr, 48000) + + * in_samples, 44100, 48000, AV_ROUND_UP); + * av_samples_alloc(&output, NULL, 2, out_samples, + * AV_SAMPLE_FMT_S16, 0); + * out_samples = swr_convert(swr, &output, out_samples, + * input, in_samples); + * handle_output(output, out_samples); + * av_freep(&output); + * } + * @endcode + * + * When the conversion is finished, the conversion + * context and everything associated with it must be freed with swr_free(). + * A swr_close() function is also available, but it exists mainly for + * compatibility with libavresample, and is not required to be called. + * + * There will be no memory leak if the data is not completely flushed before + * swr_free(). + */ + +#include +#include "libavutil/channel_layout.h" +#include "libavutil/frame.h" +#include "libavutil/samplefmt.h" + +#include "libswresample/version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "libswresample/version.h" +#endif + +/** + * @name Option constants + * These constants are used for the @ref avoptions interface for lswr. + * @{ + * + */ + +#define SWR_FLAG_RESAMPLE 1 ///< Force resampling even if equal sample rate +//TODO use int resample ? +//long term TODO can we enable this dynamically? + +/** Dithering algorithms */ +enum SwrDitherType { + SWR_DITHER_NONE = 0, + SWR_DITHER_RECTANGULAR, + SWR_DITHER_TRIANGULAR, + SWR_DITHER_TRIANGULAR_HIGHPASS, + + SWR_DITHER_NS = 64, ///< not part of API/ABI + SWR_DITHER_NS_LIPSHITZ, + SWR_DITHER_NS_F_WEIGHTED, + SWR_DITHER_NS_MODIFIED_E_WEIGHTED, + SWR_DITHER_NS_IMPROVED_E_WEIGHTED, + SWR_DITHER_NS_SHIBATA, + SWR_DITHER_NS_LOW_SHIBATA, + SWR_DITHER_NS_HIGH_SHIBATA, + SWR_DITHER_NB, ///< not part of API/ABI +}; + +/** Resampling Engines */ +enum SwrEngine { + SWR_ENGINE_SWR, /**< SW Resampler */ + SWR_ENGINE_SOXR, /**< SoX Resampler */ + SWR_ENGINE_NB, ///< not part of API/ABI +}; + +/** Resampling Filter Types */ +enum SwrFilterType { + SWR_FILTER_TYPE_CUBIC, /**< Cubic */ + SWR_FILTER_TYPE_BLACKMAN_NUTTALL, /**< Blackman Nuttall windowed sinc */ + SWR_FILTER_TYPE_KAISER, /**< Kaiser windowed sinc */ +}; + +/** + * @} + */ + +/** + * The libswresample context. Unlike libavcodec and libavformat, this structure + * is opaque. This means that if you would like to set options, you must use + * the @ref avoptions API and cannot directly set values to members of the + * structure. + */ +typedef struct SwrContext SwrContext; + +/** + * Get the AVClass for SwrContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + * @return the AVClass of SwrContext + */ +const AVClass *swr_get_class(void); + +/** + * @name SwrContext constructor functions + * @{ + */ + +/** + * Allocate SwrContext. + * + * If you use this function you will need to set the parameters (manually or + * with swr_alloc_set_opts2()) before calling swr_init(). + * + * @see swr_alloc_set_opts2(), swr_init(), swr_free() + * @return NULL on error, allocated context otherwise + */ +struct SwrContext *swr_alloc(void); + +/** + * Initialize context after user parameters have been set. + * @note The context must be configured using the AVOption API. + * + * @see av_opt_set_int() + * @see av_opt_set_dict() + * + * @param[in,out] s Swr context to initialize + * @return AVERROR error code in case of failure. + */ +int swr_init(struct SwrContext *s); + +/** + * Check whether an swr context has been initialized or not. + * + * @param[in] s Swr context to check + * @see swr_init() + * @return positive if it has been initialized, 0 if not initialized + */ +int swr_is_initialized(struct SwrContext *s); + +#if FF_API_OLD_CHANNEL_LAYOUT +/** + * Allocate SwrContext if needed and set/reset common parameters. + * + * This function does not require s to be allocated with swr_alloc(). On the + * other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters + * on the allocated context. + * + * @param s existing Swr context if available, or NULL if not + * @param out_ch_layout output channel layout (AV_CH_LAYOUT_*) + * @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*). + * @param out_sample_rate output sample rate (frequency in Hz) + * @param in_ch_layout input channel layout (AV_CH_LAYOUT_*) + * @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*). + * @param in_sample_rate input sample rate (frequency in Hz) + * @param log_offset logging level offset + * @param log_ctx parent logging context, can be NULL + * + * @see swr_init(), swr_free() + * @return NULL on error, allocated context otherwise + * @deprecated use @ref swr_alloc_set_opts2() + */ +attribute_deprecated +struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, + int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx); +#endif + +/** + * Allocate SwrContext if needed and set/reset common parameters. + * + * This function does not require *ps to be allocated with swr_alloc(). On the + * other hand, swr_alloc() can use swr_alloc_set_opts2() to set the parameters + * on the allocated context. + * + * @param ps Pointer to an existing Swr context if available, or to NULL if not. + * On success, *ps will be set to the allocated context. + * @param out_ch_layout output channel layout (e.g. AV_CHANNEL_LAYOUT_*) + * @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*). + * @param out_sample_rate output sample rate (frequency in Hz) + * @param in_ch_layout input channel layout (e.g. AV_CHANNEL_LAYOUT_*) + * @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*). + * @param in_sample_rate input sample rate (frequency in Hz) + * @param log_offset logging level offset + * @param log_ctx parent logging context, can be NULL + * + * @see swr_init(), swr_free() + * @return 0 on success, a negative AVERROR code on error. + * On error, the Swr context is freed and *ps set to NULL. + */ +int swr_alloc_set_opts2(struct SwrContext **ps, + AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + AVChannelLayout *in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx); +/** + * @} + * + * @name SwrContext destructor functions + * @{ + */ + +/** + * Free the given SwrContext and set the pointer to NULL. + * + * @param[in] s a pointer to a pointer to Swr context + */ +void swr_free(struct SwrContext **s); + +/** + * Closes the context so that swr_is_initialized() returns 0. + * + * The context can be brought back to life by running swr_init(), + * swr_init() can also be used without swr_close(). + * This function is mainly provided for simplifying the usecase + * where one tries to support libavresample and libswresample. + * + * @param[in,out] s Swr context to be closed + */ +void swr_close(struct SwrContext *s); + +/** + * @} + * + * @name Core conversion functions + * @{ + */ + +/** Convert audio. + * + * in and in_count can be set to 0 to flush the last few samples out at the + * end. + * + * If more input is provided than output space, then the input will be buffered. + * You can avoid this buffering by using swr_get_out_samples() to retrieve an + * upper bound on the required number of output samples for the given number of + * input samples. Conversion will run directly without copying whenever possible. + * + * @param s allocated Swr context, with parameters set + * @param out output buffers, only the first one need be set in case of packed audio + * @param out_count amount of space available for output in samples per channel + * @param in input buffers, only the first one need to be set in case of packed audio + * @param in_count number of input samples available in one channel + * + * @return number of samples output per channel, negative value on error + */ +int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, + const uint8_t **in , int in_count); + +/** + * Convert the next timestamp from input to output + * timestamps are in 1/(in_sample_rate * out_sample_rate) units. + * + * @note There are 2 slightly differently behaving modes. + * @li When automatic timestamp compensation is not used, (min_compensation >= FLT_MAX) + * in this case timestamps will be passed through with delays compensated + * @li When automatic timestamp compensation is used, (min_compensation < FLT_MAX) + * in this case the output timestamps will match output sample numbers. + * See ffmpeg-resampler(1) for the two modes of compensation. + * + * @param s[in] initialized Swr context + * @param pts[in] timestamp for the next input sample, INT64_MIN if unknown + * @see swr_set_compensation(), swr_drop_output(), and swr_inject_silence() are + * function used internally for timestamp compensation. + * @return the output timestamp for the next output sample + */ +int64_t swr_next_pts(struct SwrContext *s, int64_t pts); + +/** + * @} + * + * @name Low-level option setting functions + * These functons provide a means to set low-level options that is not possible + * with the AVOption API. + * @{ + */ + +/** + * Activate resampling compensation ("soft" compensation). This function is + * internally called when needed in swr_next_pts(). + * + * @param[in,out] s allocated Swr context. If it is not initialized, + * or SWR_FLAG_RESAMPLE is not set, swr_init() is + * called with the flag set. + * @param[in] sample_delta delta in PTS per sample + * @param[in] compensation_distance number of samples to compensate for + * @return >= 0 on success, AVERROR error codes if: + * @li @c s is NULL, + * @li @c compensation_distance is less than 0, + * @li @c compensation_distance is 0 but sample_delta is not, + * @li compensation unsupported by resampler, or + * @li swr_init() fails when called. + */ +int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance); + +/** + * Set a customized input channel mapping. + * + * @param[in,out] s allocated Swr context, not yet initialized + * @param[in] channel_map customized input channel mapping (array of channel + * indexes, -1 for a muted channel) + * @return >= 0 on success, or AVERROR error code in case of failure. + */ +int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); + +#if FF_API_OLD_CHANNEL_LAYOUT +/** + * Generate a channel mixing matrix. + * + * This function is the one used internally by libswresample for building the + * default mixing matrix. It is made public just as a utility function for + * building custom matrices. + * + * @param in_layout input channel layout + * @param out_layout output channel layout + * @param center_mix_level mix level for the center channel + * @param surround_mix_level mix level for the surround channel(s) + * @param lfe_mix_level mix level for the low-frequency effects channel + * @param rematrix_maxval if 1.0, coefficients will be normalized to prevent + * overflow. if INT_MAX, coefficients will not be + * normalized. + * @param[out] matrix mixing coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o. + * @param stride distance between adjacent input channels in the + * matrix array + * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii) + * @param log_ctx parent logging context, can be NULL + * @return 0 on success, negative AVERROR code on failure + * @deprecated use @ref swr_build_matrix2() + */ +attribute_deprecated +int swr_build_matrix(uint64_t in_layout, uint64_t out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double rematrix_maxval, + double rematrix_volume, double *matrix, + int stride, enum AVMatrixEncoding matrix_encoding, + void *log_ctx); +#endif + +/** + * Generate a channel mixing matrix. + * + * This function is the one used internally by libswresample for building the + * default mixing matrix. It is made public just as a utility function for + * building custom matrices. + * + * @param in_layout input channel layout + * @param out_layout output channel layout + * @param center_mix_level mix level for the center channel + * @param surround_mix_level mix level for the surround channel(s) + * @param lfe_mix_level mix level for the low-frequency effects channel + * @param rematrix_maxval if 1.0, coefficients will be normalized to prevent + * overflow. if INT_MAX, coefficients will not be + * normalized. + * @param[out] matrix mixing coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o. + * @param stride distance between adjacent input channels in the + * matrix array + * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii) + * @param log_ctx parent logging context, can be NULL + * @return 0 on success, negative AVERROR code on failure + */ +int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double maxval, + double rematrix_volume, double *matrix, + ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, + void *log_context); + +/** + * Set a customized remix matrix. + * + * @param s allocated Swr context, not yet initialized + * @param matrix remix coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o + * @param stride offset between lines of the matrix + * @return >= 0 on success, or AVERROR error code in case of failure. + */ +int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride); + +/** + * @} + * + * @name Sample handling functions + * @{ + */ + +/** + * Drops the specified number of output samples. + * + * This function, along with swr_inject_silence(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure + */ +int swr_drop_output(struct SwrContext *s, int count); + +/** + * Injects the specified number of silence samples. + * + * This function, along with swr_drop_output(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure + */ +int swr_inject_silence(struct SwrContext *s, int count); + +/** + * Gets the delay the next input sample will experience relative to the next output sample. + * + * Swresample can buffer data if more input has been provided than available + * output space, also converting between sample rates needs a delay. + * This function returns the sum of all such delays. + * The exact delay is not necessarily an integer value in either input or + * output sample rate. Especially when downsampling by a large value, the + * output sample rate may be a poor choice to represent the delay, similarly + * for upsampling and the input sample rate. + * + * @param s swr context + * @param base timebase in which the returned delay will be: + * @li if it's set to 1 the returned delay is in seconds + * @li if it's set to 1000 the returned delay is in milliseconds + * @li if it's set to the input sample rate then the returned + * delay is in input samples + * @li if it's set to the output sample rate then the returned + * delay is in output samples + * @li if it's the least common multiple of in_sample_rate and + * out_sample_rate then an exact rounding-free delay will be + * returned + * @returns the delay in 1 / @c base units. + */ +int64_t swr_get_delay(struct SwrContext *s, int64_t base); + +/** + * Find an upper bound on the number of samples that the next swr_convert + * call will output, if called with in_samples of input samples. This + * depends on the internal state, and anything changing the internal state + * (like further swr_convert() calls) will may change the number of samples + * swr_get_out_samples() returns for the same number of input samples. + * + * @param in_samples number of input samples. + * @note any call to swr_inject_silence(), swr_convert(), swr_next_pts() + * or swr_set_compensation() invalidates this limit + * @note it is recommended to pass the correct available buffer size + * to all functions like swr_convert() even if swr_get_out_samples() + * indicates that less would be used. + * @returns an upper bound on the number of samples that the next swr_convert + * will output or a negative value to indicate an error + */ +int swr_get_out_samples(struct SwrContext *s, int in_samples); + +/** + * @} + * + * @name Configuration accessors + * @{ + */ + +/** + * Return the @ref LIBSWRESAMPLE_VERSION_INT constant. + * + * This is useful to check if the build-time libswresample has the same version + * as the run-time one. + * + * @returns the unsigned int-typed version + */ +unsigned swresample_version(void); + +/** + * Return the swr build-time configuration. + * + * @returns the build-time @c ./configure flags + */ +const char *swresample_configuration(void); + +/** + * Return the swr license. + * + * @returns the license of libswresample, determined at build-time + */ +const char *swresample_license(void); + +/** + * @} + * + * @name AVFrame based API + * @{ + */ + +/** + * Convert the samples in the input AVFrame and write them to the output AVFrame. + * + * Input and output AVFrames must have channel_layout, sample_rate and format set. + * + * If the output AVFrame does not have the data pointers allocated the nb_samples + * field will be set using av_frame_get_buffer() + * is called to allocate the frame. + * + * The output AVFrame can be NULL or have fewer allocated samples than required. + * In this case, any remaining samples not written to the output will be added + * to an internal FIFO buffer, to be returned at the next call to this function + * or to swr_convert(). + * + * If converting sample rate, there may be data remaining in the internal + * resampling delay buffer. swr_get_delay() tells the number of + * remaining samples. To get this data as output, call this function or + * swr_convert() with NULL input. + * + * If the SwrContext configuration does not match the output and + * input AVFrame settings the conversion does not take place and depending on + * which AVFrame is not matching AVERROR_OUTPUT_CHANGED, AVERROR_INPUT_CHANGED + * or the result of a bitwise-OR of them is returned. + * + * @see swr_delay() + * @see swr_convert() + * @see swr_get_delay() + * + * @param swr audio resample context + * @param output output AVFrame + * @param input input AVFrame + * @return 0 on success, AVERROR on failure or nonmatching + * configuration. + */ +int swr_convert_frame(SwrContext *swr, + AVFrame *output, const AVFrame *input); + +/** + * Configure or reconfigure the SwrContext using the information + * provided by the AVFrames. + * + * The original resampling context is reset even on failure. + * The function calls swr_close() internally if the context is open. + * + * @see swr_close(); + * + * @param swr audio resample context + * @param output output AVFrame + * @param input input AVFrame + * @return 0 on success, AVERROR on failure. + */ +int swr_config_frame(SwrContext *swr, const AVFrame *out, const AVFrame *in); + +/** + * @} + * @} + */ + +#endif /* SWRESAMPLE_SWRESAMPLE_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libswresample/version.h b/src/framework/media/thirdparty/ffmpeg/v5/libswresample/version.h new file mode 100644 index 0000000000000..7e5c58ec876da --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libswresample/version.h @@ -0,0 +1,46 @@ +/* + * Version macros. + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_VERSION_H +#define SWRESAMPLE_VERSION_H + +/** + * @file + * Libswresample version macros + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBSWRESAMPLE_VERSION_MINOR 7 +#define LIBSWRESAMPLE_VERSION_MICRO 100 + +#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) +#define LIBSWRESAMPLE_VERSION AV_VERSION(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) +#define LIBSWRESAMPLE_BUILD LIBSWRESAMPLE_VERSION_INT + +#define LIBSWRESAMPLE_IDENT "SwR" AV_STRINGIFY(LIBSWRESAMPLE_VERSION) + +#endif /* SWRESAMPLE_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v5/libswresample/version_major.h b/src/framework/media/thirdparty/ffmpeg/v5/libswresample/version_major.h new file mode 100644 index 0000000000000..7f265c2073d10 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v5/libswresample/version_major.h @@ -0,0 +1,31 @@ +/* + * Version macros. + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_VERSION_MAJOR_H +#define SWRESAMPLE_VERSION_MAJOR_H + +/** + * @file + * Libswresample version macros + */ + +#define LIBSWRESAMPLE_VERSION_MAJOR 4 + +#endif /* SWRESAMPLE_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libswresample/swresample.h b/src/framework/media/thirdparty/ffmpeg/v6/libswresample/swresample.h new file mode 100644 index 0000000000000..d4dcaebdcf37e --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libswresample/swresample.h @@ -0,0 +1,650 @@ +/* + * Copyright (C) 2011-2013 Michael Niedermayer (michaelni@gmx.at) + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_SWRESAMPLE_H +#define SWRESAMPLE_SWRESAMPLE_H + +/** + * @file + * @ingroup lswr + * libswresample public header + */ + +/** + * @defgroup lswr libswresample + * @{ + * + * Audio resampling, sample format conversion and mixing library. + * + * Interaction with lswr is done through SwrContext, which is + * allocated with swr_alloc() or swr_alloc_set_opts2(). It is opaque, so all parameters + * must be set with the @ref avoptions API. + * + * The first thing you will need to do in order to use lswr is to allocate + * SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts2(). If you + * are using the former, you must set options through the @ref avoptions API. + * The latter function provides the same feature, but it allows you to set some + * common options in the same statement. + * + * For example the following code will setup conversion from planar float sample + * format to interleaved signed 16-bit integer, downsampling from 48kHz to + * 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing + * matrix). This is using the swr_alloc() function. + * @code + * SwrContext *swr = swr_alloc(); + * av_opt_set_channel_layout(swr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0); + * av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); + * av_opt_set_int(swr, "in_sample_rate", 48000, 0); + * av_opt_set_int(swr, "out_sample_rate", 44100, 0); + * av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); + * av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + * @endcode + * + * The same job can be done using swr_alloc_set_opts2() as well: + * @code + * SwrContext *swr = NULL; + * int ret = swr_alloc_set_opts2(&swr, // we're allocating a new context + * &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO, // out_ch_layout + * AV_SAMPLE_FMT_S16, // out_sample_fmt + * 44100, // out_sample_rate + * &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1, // in_ch_layout + * AV_SAMPLE_FMT_FLTP, // in_sample_fmt + * 48000, // in_sample_rate + * 0, // log_offset + * NULL); // log_ctx + * @endcode + * + * Once all values have been set, it must be initialized with swr_init(). If + * you need to change the conversion parameters, you can change the parameters + * using @ref avoptions, as described above in the first example; or by using + * swr_alloc_set_opts2(), but with the first argument the allocated context. + * You must then call swr_init() again. + * + * The conversion itself is done by repeatedly calling swr_convert(). + * Note that the samples may get buffered in swr if you provide insufficient + * output space or if sample rate conversion is done, which requires "future" + * samples. Samples that do not require future input can be retrieved at any + * time by using swr_convert() (in_count can be set to 0). + * At the end of conversion the resampling buffer can be flushed by calling + * swr_convert() with NULL in and 0 in_count. + * + * The samples used in the conversion process can be managed with the libavutil + * @ref lavu_sampmanip "samples manipulation" API, including av_samples_alloc() + * function used in the following example. + * + * The delay between input and output, can at any time be found by using + * swr_get_delay(). + * + * The following code demonstrates the conversion loop assuming the parameters + * from above and caller-defined functions get_input() and handle_output(): + * @code + * uint8_t **input; + * int in_samples; + * + * while (get_input(&input, &in_samples)) { + * uint8_t *output; + * int out_samples = av_rescale_rnd(swr_get_delay(swr, 48000) + + * in_samples, 44100, 48000, AV_ROUND_UP); + * av_samples_alloc(&output, NULL, 2, out_samples, + * AV_SAMPLE_FMT_S16, 0); + * out_samples = swr_convert(swr, &output, out_samples, + * input, in_samples); + * handle_output(output, out_samples); + * av_freep(&output); + * } + * @endcode + * + * When the conversion is finished, the conversion + * context and everything associated with it must be freed with swr_free(). + * A swr_close() function is also available, but it exists mainly for + * compatibility with libavresample, and is not required to be called. + * + * There will be no memory leak if the data is not completely flushed before + * swr_free(). + */ + +#include +#include "libavutil/channel_layout.h" +#include "libavutil/frame.h" +#include "libavutil/samplefmt.h" + +#include "libswresample/version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "libswresample/version.h" +#endif + +/** + * @name Option constants + * These constants are used for the @ref avoptions interface for lswr. + * @{ + * + */ + +#define SWR_FLAG_RESAMPLE 1 ///< Force resampling even if equal sample rate +//TODO use int resample ? +//long term TODO can we enable this dynamically? + +/** Dithering algorithms */ +enum SwrDitherType { + SWR_DITHER_NONE = 0, + SWR_DITHER_RECTANGULAR, + SWR_DITHER_TRIANGULAR, + SWR_DITHER_TRIANGULAR_HIGHPASS, + + SWR_DITHER_NS = 64, ///< not part of API/ABI + SWR_DITHER_NS_LIPSHITZ, + SWR_DITHER_NS_F_WEIGHTED, + SWR_DITHER_NS_MODIFIED_E_WEIGHTED, + SWR_DITHER_NS_IMPROVED_E_WEIGHTED, + SWR_DITHER_NS_SHIBATA, + SWR_DITHER_NS_LOW_SHIBATA, + SWR_DITHER_NS_HIGH_SHIBATA, + SWR_DITHER_NB, ///< not part of API/ABI +}; + +/** Resampling Engines */ +enum SwrEngine { + SWR_ENGINE_SWR, /**< SW Resampler */ + SWR_ENGINE_SOXR, /**< SoX Resampler */ + SWR_ENGINE_NB, ///< not part of API/ABI +}; + +/** Resampling Filter Types */ +enum SwrFilterType { + SWR_FILTER_TYPE_CUBIC, /**< Cubic */ + SWR_FILTER_TYPE_BLACKMAN_NUTTALL, /**< Blackman Nuttall windowed sinc */ + SWR_FILTER_TYPE_KAISER, /**< Kaiser windowed sinc */ +}; + +/** + * @} + */ + +/** + * The libswresample context. Unlike libavcodec and libavformat, this structure + * is opaque. This means that if you would like to set options, you must use + * the @ref avoptions API and cannot directly set values to members of the + * structure. + */ +typedef struct SwrContext SwrContext; + +/** + * Get the AVClass for SwrContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + * @return the AVClass of SwrContext + */ +const AVClass *swr_get_class(void); + +/** + * @name SwrContext constructor functions + * @{ + */ + +/** + * Allocate SwrContext. + * + * If you use this function you will need to set the parameters (manually or + * with swr_alloc_set_opts2()) before calling swr_init(). + * + * @see swr_alloc_set_opts2(), swr_init(), swr_free() + * @return NULL on error, allocated context otherwise + */ +struct SwrContext *swr_alloc(void); + +/** + * Initialize context after user parameters have been set. + * @note The context must be configured using the AVOption API. + * + * @see av_opt_set_int() + * @see av_opt_set_dict() + * + * @param[in,out] s Swr context to initialize + * @return AVERROR error code in case of failure. + */ +int swr_init(struct SwrContext *s); + +/** + * Check whether an swr context has been initialized or not. + * + * @param[in] s Swr context to check + * @see swr_init() + * @return positive if it has been initialized, 0 if not initialized + */ +int swr_is_initialized(struct SwrContext *s); + +#if FF_API_OLD_CHANNEL_LAYOUT +/** + * Allocate SwrContext if needed and set/reset common parameters. + * + * This function does not require s to be allocated with swr_alloc(). On the + * other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters + * on the allocated context. + * + * @param s existing Swr context if available, or NULL if not + * @param out_ch_layout output channel layout (AV_CH_LAYOUT_*) + * @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*). + * @param out_sample_rate output sample rate (frequency in Hz) + * @param in_ch_layout input channel layout (AV_CH_LAYOUT_*) + * @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*). + * @param in_sample_rate input sample rate (frequency in Hz) + * @param log_offset logging level offset + * @param log_ctx parent logging context, can be NULL + * + * @see swr_init(), swr_free() + * @return NULL on error, allocated context otherwise + * @deprecated use @ref swr_alloc_set_opts2() + */ +attribute_deprecated +struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, + int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx); +#endif + +/** + * Allocate SwrContext if needed and set/reset common parameters. + * + * This function does not require *ps to be allocated with swr_alloc(). On the + * other hand, swr_alloc() can use swr_alloc_set_opts2() to set the parameters + * on the allocated context. + * + * @param ps Pointer to an existing Swr context if available, or to NULL if not. + * On success, *ps will be set to the allocated context. + * @param out_ch_layout output channel layout (e.g. AV_CHANNEL_LAYOUT_*) + * @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*). + * @param out_sample_rate output sample rate (frequency in Hz) + * @param in_ch_layout input channel layout (e.g. AV_CHANNEL_LAYOUT_*) + * @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*). + * @param in_sample_rate input sample rate (frequency in Hz) + * @param log_offset logging level offset + * @param log_ctx parent logging context, can be NULL + * + * @see swr_init(), swr_free() + * @return 0 on success, a negative AVERROR code on error. + * On error, the Swr context is freed and *ps set to NULL. + */ +int swr_alloc_set_opts2(struct SwrContext **ps, + const AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + const AVChannelLayout *in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx); +/** + * @} + * + * @name SwrContext destructor functions + * @{ + */ + +/** + * Free the given SwrContext and set the pointer to NULL. + * + * @param[in] s a pointer to a pointer to Swr context + */ +void swr_free(struct SwrContext **s); + +/** + * Closes the context so that swr_is_initialized() returns 0. + * + * The context can be brought back to life by running swr_init(), + * swr_init() can also be used without swr_close(). + * This function is mainly provided for simplifying the usecase + * where one tries to support libavresample and libswresample. + * + * @param[in,out] s Swr context to be closed + */ +void swr_close(struct SwrContext *s); + +/** + * @} + * + * @name Core conversion functions + * @{ + */ + +/** Convert audio. + * + * in and in_count can be set to 0 to flush the last few samples out at the + * end. + * + * If more input is provided than output space, then the input will be buffered. + * You can avoid this buffering by using swr_get_out_samples() to retrieve an + * upper bound on the required number of output samples for the given number of + * input samples. Conversion will run directly without copying whenever possible. + * + * @param s allocated Swr context, with parameters set + * @param out output buffers, only the first one need be set in case of packed audio + * @param out_count amount of space available for output in samples per channel + * @param in input buffers, only the first one need to be set in case of packed audio + * @param in_count number of input samples available in one channel + * + * @return number of samples output per channel, negative value on error + */ +int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, + const uint8_t **in , int in_count); + +/** + * Convert the next timestamp from input to output + * timestamps are in 1/(in_sample_rate * out_sample_rate) units. + * + * @note There are 2 slightly differently behaving modes. + * @li When automatic timestamp compensation is not used, (min_compensation >= FLT_MAX) + * in this case timestamps will be passed through with delays compensated + * @li When automatic timestamp compensation is used, (min_compensation < FLT_MAX) + * in this case the output timestamps will match output sample numbers. + * See ffmpeg-resampler(1) for the two modes of compensation. + * + * @param[in] s initialized Swr context + * @param[in] pts timestamp for the next input sample, INT64_MIN if unknown + * @see swr_set_compensation(), swr_drop_output(), and swr_inject_silence() are + * function used internally for timestamp compensation. + * @return the output timestamp for the next output sample + */ +int64_t swr_next_pts(struct SwrContext *s, int64_t pts); + +/** + * @} + * + * @name Low-level option setting functions + * These functons provide a means to set low-level options that is not possible + * with the AVOption API. + * @{ + */ + +/** + * Activate resampling compensation ("soft" compensation). This function is + * internally called when needed in swr_next_pts(). + * + * @param[in,out] s allocated Swr context. If it is not initialized, + * or SWR_FLAG_RESAMPLE is not set, swr_init() is + * called with the flag set. + * @param[in] sample_delta delta in PTS per sample + * @param[in] compensation_distance number of samples to compensate for + * @return >= 0 on success, AVERROR error codes if: + * @li @c s is NULL, + * @li @c compensation_distance is less than 0, + * @li @c compensation_distance is 0 but sample_delta is not, + * @li compensation unsupported by resampler, or + * @li swr_init() fails when called. + */ +int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance); + +/** + * Set a customized input channel mapping. + * + * @param[in,out] s allocated Swr context, not yet initialized + * @param[in] channel_map customized input channel mapping (array of channel + * indexes, -1 for a muted channel) + * @return >= 0 on success, or AVERROR error code in case of failure. + */ +int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); + +#if FF_API_OLD_CHANNEL_LAYOUT +/** + * Generate a channel mixing matrix. + * + * This function is the one used internally by libswresample for building the + * default mixing matrix. It is made public just as a utility function for + * building custom matrices. + * + * @param in_layout input channel layout + * @param out_layout output channel layout + * @param center_mix_level mix level for the center channel + * @param surround_mix_level mix level for the surround channel(s) + * @param lfe_mix_level mix level for the low-frequency effects channel + * @param rematrix_maxval if 1.0, coefficients will be normalized to prevent + * overflow. if INT_MAX, coefficients will not be + * normalized. + * @param[out] matrix mixing coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o. + * @param stride distance between adjacent input channels in the + * matrix array + * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii) + * @param log_ctx parent logging context, can be NULL + * @return 0 on success, negative AVERROR code on failure + * @deprecated use @ref swr_build_matrix2() + */ +attribute_deprecated +int swr_build_matrix(uint64_t in_layout, uint64_t out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double rematrix_maxval, + double rematrix_volume, double *matrix, + int stride, enum AVMatrixEncoding matrix_encoding, + void *log_ctx); +#endif + +/** + * Generate a channel mixing matrix. + * + * This function is the one used internally by libswresample for building the + * default mixing matrix. It is made public just as a utility function for + * building custom matrices. + * + * @param in_layout input channel layout + * @param out_layout output channel layout + * @param center_mix_level mix level for the center channel + * @param surround_mix_level mix level for the surround channel(s) + * @param lfe_mix_level mix level for the low-frequency effects channel + * @param rematrix_maxval if 1.0, coefficients will be normalized to prevent + * overflow. if INT_MAX, coefficients will not be + * normalized. + * @param[out] matrix mixing coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o. + * @param stride distance between adjacent input channels in the + * matrix array + * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii) + * @param log_ctx parent logging context, can be NULL + * @return 0 on success, negative AVERROR code on failure + */ +int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double maxval, + double rematrix_volume, double *matrix, + ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, + void *log_context); + +/** + * Set a customized remix matrix. + * + * @param s allocated Swr context, not yet initialized + * @param matrix remix coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o + * @param stride offset between lines of the matrix + * @return >= 0 on success, or AVERROR error code in case of failure. + */ +int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride); + +/** + * @} + * + * @name Sample handling functions + * @{ + */ + +/** + * Drops the specified number of output samples. + * + * This function, along with swr_inject_silence(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure + */ +int swr_drop_output(struct SwrContext *s, int count); + +/** + * Injects the specified number of silence samples. + * + * This function, along with swr_drop_output(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure + */ +int swr_inject_silence(struct SwrContext *s, int count); + +/** + * Gets the delay the next input sample will experience relative to the next output sample. + * + * Swresample can buffer data if more input has been provided than available + * output space, also converting between sample rates needs a delay. + * This function returns the sum of all such delays. + * The exact delay is not necessarily an integer value in either input or + * output sample rate. Especially when downsampling by a large value, the + * output sample rate may be a poor choice to represent the delay, similarly + * for upsampling and the input sample rate. + * + * @param s swr context + * @param base timebase in which the returned delay will be: + * @li if it's set to 1 the returned delay is in seconds + * @li if it's set to 1000 the returned delay is in milliseconds + * @li if it's set to the input sample rate then the returned + * delay is in input samples + * @li if it's set to the output sample rate then the returned + * delay is in output samples + * @li if it's the least common multiple of in_sample_rate and + * out_sample_rate then an exact rounding-free delay will be + * returned + * @returns the delay in 1 / @c base units. + */ +int64_t swr_get_delay(struct SwrContext *s, int64_t base); + +/** + * Find an upper bound on the number of samples that the next swr_convert + * call will output, if called with in_samples of input samples. This + * depends on the internal state, and anything changing the internal state + * (like further swr_convert() calls) will may change the number of samples + * swr_get_out_samples() returns for the same number of input samples. + * + * @param in_samples number of input samples. + * @note any call to swr_inject_silence(), swr_convert(), swr_next_pts() + * or swr_set_compensation() invalidates this limit + * @note it is recommended to pass the correct available buffer size + * to all functions like swr_convert() even if swr_get_out_samples() + * indicates that less would be used. + * @returns an upper bound on the number of samples that the next swr_convert + * will output or a negative value to indicate an error + */ +int swr_get_out_samples(struct SwrContext *s, int in_samples); + +/** + * @} + * + * @name Configuration accessors + * @{ + */ + +/** + * Return the @ref LIBSWRESAMPLE_VERSION_INT constant. + * + * This is useful to check if the build-time libswresample has the same version + * as the run-time one. + * + * @returns the unsigned int-typed version + */ +unsigned swresample_version(void); + +/** + * Return the swr build-time configuration. + * + * @returns the build-time @c ./configure flags + */ +const char *swresample_configuration(void); + +/** + * Return the swr license. + * + * @returns the license of libswresample, determined at build-time + */ +const char *swresample_license(void); + +/** + * @} + * + * @name AVFrame based API + * @{ + */ + +/** + * Convert the samples in the input AVFrame and write them to the output AVFrame. + * + * Input and output AVFrames must have channel_layout, sample_rate and format set. + * + * If the output AVFrame does not have the data pointers allocated the nb_samples + * field will be set using av_frame_get_buffer() + * is called to allocate the frame. + * + * The output AVFrame can be NULL or have fewer allocated samples than required. + * In this case, any remaining samples not written to the output will be added + * to an internal FIFO buffer, to be returned at the next call to this function + * or to swr_convert(). + * + * If converting sample rate, there may be data remaining in the internal + * resampling delay buffer. swr_get_delay() tells the number of + * remaining samples. To get this data as output, call this function or + * swr_convert() with NULL input. + * + * If the SwrContext configuration does not match the output and + * input AVFrame settings the conversion does not take place and depending on + * which AVFrame is not matching AVERROR_OUTPUT_CHANGED, AVERROR_INPUT_CHANGED + * or the result of a bitwise-OR of them is returned. + * + * @see swr_delay() + * @see swr_convert() + * @see swr_get_delay() + * + * @param swr audio resample context + * @param output output AVFrame + * @param input input AVFrame + * @return 0 on success, AVERROR on failure or nonmatching + * configuration. + */ +int swr_convert_frame(SwrContext *swr, + AVFrame *output, const AVFrame *input); + +/** + * Configure or reconfigure the SwrContext using the information + * provided by the AVFrames. + * + * The original resampling context is reset even on failure. + * The function calls swr_close() internally if the context is open. + * + * @see swr_close(); + * + * @param swr audio resample context + * @param out output AVFrame + * @param in input AVFrame + * @return 0 on success, AVERROR on failure. + */ +int swr_config_frame(SwrContext *swr, const AVFrame *out, const AVFrame *in); + +/** + * @} + * @} + */ + +#endif /* SWRESAMPLE_SWRESAMPLE_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libswresample/version.h b/src/framework/media/thirdparty/ffmpeg/v6/libswresample/version.h new file mode 100644 index 0000000000000..a2668b5e59e36 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libswresample/version.h @@ -0,0 +1,46 @@ +/* + * Version macros. + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_VERSION_H +#define SWRESAMPLE_VERSION_H + +/** + * @file + * Libswresample version macros + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBSWRESAMPLE_VERSION_MINOR 12 +#define LIBSWRESAMPLE_VERSION_MICRO 100 + +#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) +#define LIBSWRESAMPLE_VERSION AV_VERSION(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) +#define LIBSWRESAMPLE_BUILD LIBSWRESAMPLE_VERSION_INT + +#define LIBSWRESAMPLE_IDENT "SwR" AV_STRINGIFY(LIBSWRESAMPLE_VERSION) + +#endif /* SWRESAMPLE_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v6/libswresample/version_major.h b/src/framework/media/thirdparty/ffmpeg/v6/libswresample/version_major.h new file mode 100644 index 0000000000000..7f265c2073d10 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v6/libswresample/version_major.h @@ -0,0 +1,31 @@ +/* + * Version macros. + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_VERSION_MAJOR_H +#define SWRESAMPLE_VERSION_MAJOR_H + +/** + * @file + * Libswresample version macros + */ + +#define LIBSWRESAMPLE_VERSION_MAJOR 4 + +#endif /* SWRESAMPLE_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libswresample/swresample.h b/src/framework/media/thirdparty/ffmpeg/v7/libswresample/swresample.h new file mode 100644 index 0000000000000..217e5461bf95a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libswresample/swresample.h @@ -0,0 +1,587 @@ +/* + * Copyright (C) 2011-2013 Michael Niedermayer (michaelni@gmx.at) + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_SWRESAMPLE_H +#define SWRESAMPLE_SWRESAMPLE_H + +/** + * @file + * @ingroup lswr + * libswresample public header + */ + +/** + * @defgroup lswr libswresample + * @{ + * + * Audio resampling, sample format conversion and mixing library. + * + * Interaction with lswr is done through SwrContext, which is + * allocated with swr_alloc() or swr_alloc_set_opts2(). It is opaque, so all parameters + * must be set with the @ref avoptions API. + * + * The first thing you will need to do in order to use lswr is to allocate + * SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts2(). If you + * are using the former, you must set options through the @ref avoptions API. + * The latter function provides the same feature, but it allows you to set some + * common options in the same statement. + * + * For example the following code will setup conversion from planar float sample + * format to interleaved signed 16-bit integer, downsampling from 48kHz to + * 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing + * matrix). This is using the swr_alloc() function. + * @code + * SwrContext *swr = swr_alloc(); + * av_opt_set_channel_layout(swr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0); + * av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); + * av_opt_set_int(swr, "in_sample_rate", 48000, 0); + * av_opt_set_int(swr, "out_sample_rate", 44100, 0); + * av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); + * av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + * @endcode + * + * The same job can be done using swr_alloc_set_opts2() as well: + * @code + * SwrContext *swr = NULL; + * int ret = swr_alloc_set_opts2(&swr, // we're allocating a new context + * &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO, // out_ch_layout + * AV_SAMPLE_FMT_S16, // out_sample_fmt + * 44100, // out_sample_rate + * &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1, // in_ch_layout + * AV_SAMPLE_FMT_FLTP, // in_sample_fmt + * 48000, // in_sample_rate + * 0, // log_offset + * NULL); // log_ctx + * @endcode + * + * Once all values have been set, it must be initialized with swr_init(). If + * you need to change the conversion parameters, you can change the parameters + * using @ref avoptions, as described above in the first example; or by using + * swr_alloc_set_opts2(), but with the first argument the allocated context. + * You must then call swr_init() again. + * + * The conversion itself is done by repeatedly calling swr_convert(). + * Note that the samples may get buffered in swr if you provide insufficient + * output space or if sample rate conversion is done, which requires "future" + * samples. Samples that do not require future input can be retrieved at any + * time by using swr_convert() (in_count can be set to 0). + * At the end of conversion the resampling buffer can be flushed by calling + * swr_convert() with NULL in and 0 in_count. + * + * The samples used in the conversion process can be managed with the libavutil + * @ref lavu_sampmanip "samples manipulation" API, including av_samples_alloc() + * function used in the following example. + * + * The delay between input and output, can at any time be found by using + * swr_get_delay(). + * + * The following code demonstrates the conversion loop assuming the parameters + * from above and caller-defined functions get_input() and handle_output(): + * @code + * uint8_t **input; + * int in_samples; + * + * while (get_input(&input, &in_samples)) { + * uint8_t *output; + * int out_samples = av_rescale_rnd(swr_get_delay(swr, 48000) + + * in_samples, 44100, 48000, AV_ROUND_UP); + * av_samples_alloc(&output, NULL, 2, out_samples, + * AV_SAMPLE_FMT_S16, 0); + * out_samples = swr_convert(swr, &output, out_samples, + * input, in_samples); + * handle_output(output, out_samples); + * av_freep(&output); + * } + * @endcode + * + * When the conversion is finished, the conversion + * context and everything associated with it must be freed with swr_free(). + * A swr_close() function is also available, but it exists mainly for + * compatibility with libavresample, and is not required to be called. + * + * There will be no memory leak if the data is not completely flushed before + * swr_free(). + */ + +#include +#include "libavutil/channel_layout.h" +#include "libavutil/frame.h" +#include "libavutil/samplefmt.h" + +#include "libswresample/version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "libswresample/version.h" +#endif + +/** + * @name Option constants + * These constants are used for the @ref avoptions interface for lswr. + * @{ + * + */ + +#define SWR_FLAG_RESAMPLE 1 ///< Force resampling even if equal sample rate +//TODO use int resample ? +//long term TODO can we enable this dynamically? + +/** Dithering algorithms */ +enum SwrDitherType { + SWR_DITHER_NONE = 0, + SWR_DITHER_RECTANGULAR, + SWR_DITHER_TRIANGULAR, + SWR_DITHER_TRIANGULAR_HIGHPASS, + + SWR_DITHER_NS = 64, ///< not part of API/ABI + SWR_DITHER_NS_LIPSHITZ, + SWR_DITHER_NS_F_WEIGHTED, + SWR_DITHER_NS_MODIFIED_E_WEIGHTED, + SWR_DITHER_NS_IMPROVED_E_WEIGHTED, + SWR_DITHER_NS_SHIBATA, + SWR_DITHER_NS_LOW_SHIBATA, + SWR_DITHER_NS_HIGH_SHIBATA, + SWR_DITHER_NB, ///< not part of API/ABI +}; + +/** Resampling Engines */ +enum SwrEngine { + SWR_ENGINE_SWR, /**< SW Resampler */ + SWR_ENGINE_SOXR, /**< SoX Resampler */ + SWR_ENGINE_NB, ///< not part of API/ABI +}; + +/** Resampling Filter Types */ +enum SwrFilterType { + SWR_FILTER_TYPE_CUBIC, /**< Cubic */ + SWR_FILTER_TYPE_BLACKMAN_NUTTALL, /**< Blackman Nuttall windowed sinc */ + SWR_FILTER_TYPE_KAISER, /**< Kaiser windowed sinc */ +}; + +/** + * @} + */ + +/** + * The libswresample context. Unlike libavcodec and libavformat, this structure + * is opaque. This means that if you would like to set options, you must use + * the @ref avoptions API and cannot directly set values to members of the + * structure. + */ +typedef struct SwrContext SwrContext; + +/** + * Get the AVClass for SwrContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + * @return the AVClass of SwrContext + */ +const AVClass *swr_get_class(void); + +/** + * @name SwrContext constructor functions + * @{ + */ + +/** + * Allocate SwrContext. + * + * If you use this function you will need to set the parameters (manually or + * with swr_alloc_set_opts2()) before calling swr_init(). + * + * @see swr_alloc_set_opts2(), swr_init(), swr_free() + * @return NULL on error, allocated context otherwise + */ +struct SwrContext *swr_alloc(void); + +/** + * Initialize context after user parameters have been set. + * @note The context must be configured using the AVOption API. + * + * @see av_opt_set_int() + * @see av_opt_set_dict() + * + * @param[in,out] s Swr context to initialize + * @return AVERROR error code in case of failure. + */ +int swr_init(struct SwrContext *s); + +/** + * Check whether an swr context has been initialized or not. + * + * @param[in] s Swr context to check + * @see swr_init() + * @return positive if it has been initialized, 0 if not initialized + */ +int swr_is_initialized(struct SwrContext *s); + +/** + * Allocate SwrContext if needed and set/reset common parameters. + * + * This function does not require *ps to be allocated with swr_alloc(). On the + * other hand, swr_alloc() can use swr_alloc_set_opts2() to set the parameters + * on the allocated context. + * + * @param ps Pointer to an existing Swr context if available, or to NULL if not. + * On success, *ps will be set to the allocated context. + * @param out_ch_layout output channel layout (e.g. AV_CHANNEL_LAYOUT_*) + * @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*). + * @param out_sample_rate output sample rate (frequency in Hz) + * @param in_ch_layout input channel layout (e.g. AV_CHANNEL_LAYOUT_*) + * @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*). + * @param in_sample_rate input sample rate (frequency in Hz) + * @param log_offset logging level offset + * @param log_ctx parent logging context, can be NULL + * + * @see swr_init(), swr_free() + * @return 0 on success, a negative AVERROR code on error. + * On error, the Swr context is freed and *ps set to NULL. + */ +int swr_alloc_set_opts2(struct SwrContext **ps, + const AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + const AVChannelLayout *in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx); +/** + * @} + * + * @name SwrContext destructor functions + * @{ + */ + +/** + * Free the given SwrContext and set the pointer to NULL. + * + * @param[in] s a pointer to a pointer to Swr context + */ +void swr_free(struct SwrContext **s); + +/** + * Closes the context so that swr_is_initialized() returns 0. + * + * The context can be brought back to life by running swr_init(), + * swr_init() can also be used without swr_close(). + * This function is mainly provided for simplifying the usecase + * where one tries to support libavresample and libswresample. + * + * @param[in,out] s Swr context to be closed + */ +void swr_close(struct SwrContext *s); + +/** + * @} + * + * @name Core conversion functions + * @{ + */ + +/** Convert audio. + * + * in and in_count can be set to 0 to flush the last few samples out at the + * end. + * + * If more input is provided than output space, then the input will be buffered. + * You can avoid this buffering by using swr_get_out_samples() to retrieve an + * upper bound on the required number of output samples for the given number of + * input samples. Conversion will run directly without copying whenever possible. + * + * @param s allocated Swr context, with parameters set + * @param out output buffers, only the first one need be set in case of packed audio + * @param out_count amount of space available for output in samples per channel + * @param in input buffers, only the first one need to be set in case of packed audio + * @param in_count number of input samples available in one channel + * + * @return number of samples output per channel, negative value on error + */ +int swr_convert(struct SwrContext *s, uint8_t * const *out, int out_count, + const uint8_t * const *in , int in_count); + +/** + * Convert the next timestamp from input to output + * timestamps are in 1/(in_sample_rate * out_sample_rate) units. + * + * @note There are 2 slightly differently behaving modes. + * @li When automatic timestamp compensation is not used, (min_compensation >= FLT_MAX) + * in this case timestamps will be passed through with delays compensated + * @li When automatic timestamp compensation is used, (min_compensation < FLT_MAX) + * in this case the output timestamps will match output sample numbers. + * See ffmpeg-resampler(1) for the two modes of compensation. + * + * @param[in] s initialized Swr context + * @param[in] pts timestamp for the next input sample, INT64_MIN if unknown + * @see swr_set_compensation(), swr_drop_output(), and swr_inject_silence() are + * function used internally for timestamp compensation. + * @return the output timestamp for the next output sample + */ +int64_t swr_next_pts(struct SwrContext *s, int64_t pts); + +/** + * @} + * + * @name Low-level option setting functions + * These functons provide a means to set low-level options that is not possible + * with the AVOption API. + * @{ + */ + +/** + * Activate resampling compensation ("soft" compensation). This function is + * internally called when needed in swr_next_pts(). + * + * @param[in,out] s allocated Swr context. If it is not initialized, + * or SWR_FLAG_RESAMPLE is not set, swr_init() is + * called with the flag set. + * @param[in] sample_delta delta in PTS per sample + * @param[in] compensation_distance number of samples to compensate for + * @return >= 0 on success, AVERROR error codes if: + * @li @c s is NULL, + * @li @c compensation_distance is less than 0, + * @li @c compensation_distance is 0 but sample_delta is not, + * @li compensation unsupported by resampler, or + * @li swr_init() fails when called. + */ +int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance); + +/** + * Set a customized input channel mapping. + * + * @param[in,out] s allocated Swr context, not yet initialized + * @param[in] channel_map customized input channel mapping (array of channel + * indexes, -1 for a muted channel) + * @return >= 0 on success, or AVERROR error code in case of failure. + */ +int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); + +/** + * Generate a channel mixing matrix. + * + * This function is the one used internally by libswresample for building the + * default mixing matrix. It is made public just as a utility function for + * building custom matrices. + * + * @param in_layout input channel layout + * @param out_layout output channel layout + * @param center_mix_level mix level for the center channel + * @param surround_mix_level mix level for the surround channel(s) + * @param lfe_mix_level mix level for the low-frequency effects channel + * @param rematrix_maxval if 1.0, coefficients will be normalized to prevent + * overflow. if INT_MAX, coefficients will not be + * normalized. + * @param[out] matrix mixing coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o. + * @param stride distance between adjacent input channels in the + * matrix array + * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii) + * @param log_ctx parent logging context, can be NULL + * @return 0 on success, negative AVERROR code on failure + */ +int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double maxval, + double rematrix_volume, double *matrix, + ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, + void *log_context); + +/** + * Set a customized remix matrix. + * + * @param s allocated Swr context, not yet initialized + * @param matrix remix coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o + * @param stride offset between lines of the matrix + * @return >= 0 on success, or AVERROR error code in case of failure. + */ +int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride); + +/** + * @} + * + * @name Sample handling functions + * @{ + */ + +/** + * Drops the specified number of output samples. + * + * This function, along with swr_inject_silence(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure + */ +int swr_drop_output(struct SwrContext *s, int count); + +/** + * Injects the specified number of silence samples. + * + * This function, along with swr_drop_output(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure + */ +int swr_inject_silence(struct SwrContext *s, int count); + +/** + * Gets the delay the next input sample will experience relative to the next output sample. + * + * Swresample can buffer data if more input has been provided than available + * output space, also converting between sample rates needs a delay. + * This function returns the sum of all such delays. + * The exact delay is not necessarily an integer value in either input or + * output sample rate. Especially when downsampling by a large value, the + * output sample rate may be a poor choice to represent the delay, similarly + * for upsampling and the input sample rate. + * + * @param s swr context + * @param base timebase in which the returned delay will be: + * @li if it's set to 1 the returned delay is in seconds + * @li if it's set to 1000 the returned delay is in milliseconds + * @li if it's set to the input sample rate then the returned + * delay is in input samples + * @li if it's set to the output sample rate then the returned + * delay is in output samples + * @li if it's the least common multiple of in_sample_rate and + * out_sample_rate then an exact rounding-free delay will be + * returned + * @returns the delay in 1 / @c base units. + */ +int64_t swr_get_delay(struct SwrContext *s, int64_t base); + +/** + * Find an upper bound on the number of samples that the next swr_convert + * call will output, if called with in_samples of input samples. This + * depends on the internal state, and anything changing the internal state + * (like further swr_convert() calls) will may change the number of samples + * swr_get_out_samples() returns for the same number of input samples. + * + * @param in_samples number of input samples. + * @note any call to swr_inject_silence(), swr_convert(), swr_next_pts() + * or swr_set_compensation() invalidates this limit + * @note it is recommended to pass the correct available buffer size + * to all functions like swr_convert() even if swr_get_out_samples() + * indicates that less would be used. + * @returns an upper bound on the number of samples that the next swr_convert + * will output or a negative value to indicate an error + */ +int swr_get_out_samples(struct SwrContext *s, int in_samples); + +/** + * @} + * + * @name Configuration accessors + * @{ + */ + +/** + * Return the @ref LIBSWRESAMPLE_VERSION_INT constant. + * + * This is useful to check if the build-time libswresample has the same version + * as the run-time one. + * + * @returns the unsigned int-typed version + */ +unsigned swresample_version(void); + +/** + * Return the swr build-time configuration. + * + * @returns the build-time @c ./configure flags + */ +const char *swresample_configuration(void); + +/** + * Return the swr license. + * + * @returns the license of libswresample, determined at build-time + */ +const char *swresample_license(void); + +/** + * @} + * + * @name AVFrame based API + * @{ + */ + +/** + * Convert the samples in the input AVFrame and write them to the output AVFrame. + * + * Input and output AVFrames must have channel_layout, sample_rate and format set. + * + * If the output AVFrame does not have the data pointers allocated the nb_samples + * field will be set using av_frame_get_buffer() + * is called to allocate the frame. + * + * The output AVFrame can be NULL or have fewer allocated samples than required. + * In this case, any remaining samples not written to the output will be added + * to an internal FIFO buffer, to be returned at the next call to this function + * or to swr_convert(). + * + * If converting sample rate, there may be data remaining in the internal + * resampling delay buffer. swr_get_delay() tells the number of + * remaining samples. To get this data as output, call this function or + * swr_convert() with NULL input. + * + * If the SwrContext configuration does not match the output and + * input AVFrame settings the conversion does not take place and depending on + * which AVFrame is not matching AVERROR_OUTPUT_CHANGED, AVERROR_INPUT_CHANGED + * or the result of a bitwise-OR of them is returned. + * + * @see swr_delay() + * @see swr_convert() + * @see swr_get_delay() + * + * @param swr audio resample context + * @param output output AVFrame + * @param input input AVFrame + * @return 0 on success, AVERROR on failure or nonmatching + * configuration. + */ +int swr_convert_frame(SwrContext *swr, + AVFrame *output, const AVFrame *input); + +/** + * Configure or reconfigure the SwrContext using the information + * provided by the AVFrames. + * + * The original resampling context is reset even on failure. + * The function calls swr_close() internally if the context is open. + * + * @see swr_close(); + * + * @param swr audio resample context + * @param out output AVFrame + * @param in input AVFrame + * @return 0 on success, AVERROR on failure. + */ +int swr_config_frame(SwrContext *swr, const AVFrame *out, const AVFrame *in); + +/** + * @} + * @} + */ + +#endif /* SWRESAMPLE_SWRESAMPLE_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libswresample/version.h b/src/framework/media/thirdparty/ffmpeg/v7/libswresample/version.h new file mode 100644 index 0000000000000..9c223e1426f9a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libswresample/version.h @@ -0,0 +1,46 @@ +/* + * Version macros. + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_VERSION_H +#define SWRESAMPLE_VERSION_H + +/** + * @file + * Libswresample version macros + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBSWRESAMPLE_VERSION_MINOR 1 +#define LIBSWRESAMPLE_VERSION_MICRO 100 + +#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) +#define LIBSWRESAMPLE_VERSION AV_VERSION(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) +#define LIBSWRESAMPLE_BUILD LIBSWRESAMPLE_VERSION_INT + +#define LIBSWRESAMPLE_IDENT "SwR" AV_STRINGIFY(LIBSWRESAMPLE_VERSION) + +#endif /* SWRESAMPLE_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v7/libswresample/version_major.h b/src/framework/media/thirdparty/ffmpeg/v7/libswresample/version_major.h new file mode 100644 index 0000000000000..dd13f2bbe3274 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v7/libswresample/version_major.h @@ -0,0 +1,31 @@ +/* + * Version macros. + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_VERSION_MAJOR_H +#define SWRESAMPLE_VERSION_MAJOR_H + +/** + * @file + * Libswresample version macros + */ + +#define LIBSWRESAMPLE_VERSION_MAJOR 5 + +#endif /* SWRESAMPLE_VERSION_MAJOR_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libswresample/swresample.h b/src/framework/media/thirdparty/ffmpeg/v8/libswresample/swresample.h new file mode 100644 index 0000000000000..052089acca54c --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libswresample/swresample.h @@ -0,0 +1,587 @@ +/* + * Copyright (C) 2011-2013 Michael Niedermayer (michaelni@gmx.at) + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_SWRESAMPLE_H +#define SWRESAMPLE_SWRESAMPLE_H + +/** + * @file + * @ingroup lswr + * libswresample public header + */ + +/** + * @defgroup lswr libswresample + * @{ + * + * Audio resampling, sample format conversion and mixing library. + * + * Interaction with lswr is done through SwrContext, which is + * allocated with swr_alloc() or swr_alloc_set_opts2(). It is opaque, so all parameters + * must be set with the @ref avoptions API. + * + * The first thing you will need to do in order to use lswr is to allocate + * SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts2(). If you + * are using the former, you must set options through the @ref avoptions API. + * The latter function provides the same feature, but it allows you to set some + * common options in the same statement. + * + * For example the following code will setup conversion from planar float sample + * format to interleaved signed 16-bit integer, downsampling from 48kHz to + * 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing + * matrix). This is using the swr_alloc() function. + * @code + * SwrContext *swr = swr_alloc(); + * av_opt_set_chlayout(swr, "in_chlayout", &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1, 0); + * av_opt_set_chlayout(swr, "out_chlayout", &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO, 0); + * av_opt_set_int(swr, "in_sample_rate", 48000, 0); + * av_opt_set_int(swr, "out_sample_rate", 44100, 0); + * av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); + * av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + * @endcode + * + * The same job can be done using swr_alloc_set_opts2() as well: + * @code + * SwrContext *swr = NULL; + * int ret = swr_alloc_set_opts2(&swr, // we're allocating a new context + * &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO, // out_ch_layout + * AV_SAMPLE_FMT_S16, // out_sample_fmt + * 44100, // out_sample_rate + * &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1, // in_ch_layout + * AV_SAMPLE_FMT_FLTP, // in_sample_fmt + * 48000, // in_sample_rate + * 0, // log_offset + * NULL); // log_ctx + * @endcode + * + * Once all values have been set, it must be initialized with swr_init(). If + * you need to change the conversion parameters, you can change the parameters + * using @ref avoptions, as described above in the first example; or by using + * swr_alloc_set_opts2(), but with the first argument the allocated context. + * You must then call swr_init() again. + * + * The conversion itself is done by repeatedly calling swr_convert(). + * Note that the samples may get buffered in swr if you provide insufficient + * output space or if sample rate conversion is done, which requires "future" + * samples. Samples that do not require future input can be retrieved at any + * time by using swr_convert() (in_count can be set to 0). + * At the end of conversion the resampling buffer can be flushed by calling + * swr_convert() with NULL in and 0 in_count. + * + * The samples used in the conversion process can be managed with the libavutil + * @ref lavu_sampmanip "samples manipulation" API, including av_samples_alloc() + * function used in the following example. + * + * The delay between input and output, can at any time be found by using + * swr_get_delay(). + * + * The following code demonstrates the conversion loop assuming the parameters + * from above and caller-defined functions get_input() and handle_output(): + * @code + * uint8_t **input; + * int in_samples; + * + * while (get_input(&input, &in_samples)) { + * uint8_t *output; + * int out_samples = av_rescale_rnd(swr_get_delay(swr, 48000) + + * in_samples, 44100, 48000, AV_ROUND_UP); + * av_samples_alloc(&output, NULL, 2, out_samples, + * AV_SAMPLE_FMT_S16, 0); + * out_samples = swr_convert(swr, &output, out_samples, + * input, in_samples); + * handle_output(output, out_samples); + * av_freep(&output); + * } + * @endcode + * + * When the conversion is finished, the conversion + * context and everything associated with it must be freed with swr_free(). + * A swr_close() function is also available, but it exists mainly for + * compatibility with libavresample, and is not required to be called. + * + * There will be no memory leak if the data is not completely flushed before + * swr_free(). + */ + +#include +#include "libavutil/channel_layout.h" +#include "libavutil/frame.h" +#include "libavutil/samplefmt.h" + +#include "libswresample/version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ +#include "libswresample/version.h" +#endif + +/** + * @name Option constants + * These constants are used for the @ref avoptions interface for lswr. + * @{ + * + */ + +#define SWR_FLAG_RESAMPLE 1 ///< Force resampling even if equal sample rate +//TODO use int resample ? +//long term TODO can we enable this dynamically? + +/** Dithering algorithms */ +enum SwrDitherType { + SWR_DITHER_NONE = 0, + SWR_DITHER_RECTANGULAR, + SWR_DITHER_TRIANGULAR, + SWR_DITHER_TRIANGULAR_HIGHPASS, + + SWR_DITHER_NS = 64, ///< not part of API/ABI + SWR_DITHER_NS_LIPSHITZ, + SWR_DITHER_NS_F_WEIGHTED, + SWR_DITHER_NS_MODIFIED_E_WEIGHTED, + SWR_DITHER_NS_IMPROVED_E_WEIGHTED, + SWR_DITHER_NS_SHIBATA, + SWR_DITHER_NS_LOW_SHIBATA, + SWR_DITHER_NS_HIGH_SHIBATA, + SWR_DITHER_NB, ///< not part of API/ABI +}; + +/** Resampling Engines */ +enum SwrEngine { + SWR_ENGINE_SWR, /**< SW Resampler */ + SWR_ENGINE_SOXR, /**< SoX Resampler */ + SWR_ENGINE_NB, ///< not part of API/ABI +}; + +/** Resampling Filter Types */ +enum SwrFilterType { + SWR_FILTER_TYPE_CUBIC, /**< Cubic */ + SWR_FILTER_TYPE_BLACKMAN_NUTTALL, /**< Blackman Nuttall windowed sinc */ + SWR_FILTER_TYPE_KAISER, /**< Kaiser windowed sinc */ +}; + +/** + * @} + */ + +/** + * The libswresample context. Unlike libavcodec and libavformat, this structure + * is opaque. This means that if you would like to set options, you must use + * the @ref avoptions API and cannot directly set values to members of the + * structure. + */ +typedef struct SwrContext SwrContext; + +/** + * Get the AVClass for SwrContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + * @return the AVClass of SwrContext + */ +const AVClass *swr_get_class(void); + +/** + * @name SwrContext constructor functions + * @{ + */ + +/** + * Allocate SwrContext. + * + * If you use this function you will need to set the parameters (manually or + * with swr_alloc_set_opts2()) before calling swr_init(). + * + * @see swr_alloc_set_opts2(), swr_init(), swr_free() + * @return NULL on error, allocated context otherwise + */ +struct SwrContext *swr_alloc(void); + +/** + * Initialize context after user parameters have been set. + * @note The context must be configured using the AVOption API. + * + * @see av_opt_set_int() + * @see av_opt_set_dict() + * + * @param[in,out] s Swr context to initialize + * @return AVERROR error code in case of failure. + */ +int swr_init(struct SwrContext *s); + +/** + * Check whether an swr context has been initialized or not. + * + * @param[in] s Swr context to check + * @see swr_init() + * @return positive if it has been initialized, 0 if not initialized + */ +int swr_is_initialized(struct SwrContext *s); + +/** + * Allocate SwrContext if needed and set/reset common parameters. + * + * This function does not require *ps to be allocated with swr_alloc(). On the + * other hand, swr_alloc() can use swr_alloc_set_opts2() to set the parameters + * on the allocated context. + * + * @param ps Pointer to an existing Swr context if available, or to NULL if not. + * On success, *ps will be set to the allocated context. + * @param out_ch_layout output channel layout (e.g. AV_CHANNEL_LAYOUT_*) + * @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*). + * @param out_sample_rate output sample rate (frequency in Hz) + * @param in_ch_layout input channel layout (e.g. AV_CHANNEL_LAYOUT_*) + * @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*). + * @param in_sample_rate input sample rate (frequency in Hz) + * @param log_offset logging level offset + * @param log_ctx parent logging context, can be NULL + * + * @see swr_init(), swr_free() + * @return 0 on success, a negative AVERROR code on error. + * On error, the Swr context is freed and *ps set to NULL. + */ +int swr_alloc_set_opts2(struct SwrContext **ps, + const AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + const AVChannelLayout *in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx); +/** + * @} + * + * @name SwrContext destructor functions + * @{ + */ + +/** + * Free the given SwrContext and set the pointer to NULL. + * + * @param[in] s a pointer to a pointer to Swr context + */ +void swr_free(struct SwrContext **s); + +/** + * Closes the context so that swr_is_initialized() returns 0. + * + * The context can be brought back to life by running swr_init(), + * swr_init() can also be used without swr_close(). + * This function is mainly provided for simplifying the usecase + * where one tries to support libavresample and libswresample. + * + * @param[in,out] s Swr context to be closed + */ +void swr_close(struct SwrContext *s); + +/** + * @} + * + * @name Core conversion functions + * @{ + */ + +/** Convert audio. + * + * in and in_count can be set to 0 to flush the last few samples out at the + * end. + * + * If more input is provided than output space, then the input will be buffered. + * You can avoid this buffering by using swr_get_out_samples() to retrieve an + * upper bound on the required number of output samples for the given number of + * input samples. Conversion will run directly without copying whenever possible. + * + * @param s allocated Swr context, with parameters set + * @param out output buffers, only the first one need be set in case of packed audio + * @param out_count amount of space available for output in samples per channel + * @param in input buffers, only the first one need to be set in case of packed audio + * @param in_count number of input samples available in one channel + * + * @return number of samples output per channel, negative value on error + */ +int swr_convert(struct SwrContext *s, uint8_t * const *out, int out_count, + const uint8_t * const *in , int in_count); + +/** + * Convert the next timestamp from input to output + * timestamps are in 1/(in_sample_rate * out_sample_rate) units. + * + * @note There are 2 slightly differently behaving modes. + * @li When automatic timestamp compensation is not used, (min_compensation >= FLT_MAX) + * in this case timestamps will be passed through with delays compensated + * @li When automatic timestamp compensation is used, (min_compensation < FLT_MAX) + * in this case the output timestamps will match output sample numbers. + * See ffmpeg-resampler(1) for the two modes of compensation. + * + * @param[in] s initialized Swr context + * @param[in] pts timestamp for the next input sample, INT64_MIN if unknown + * @see swr_set_compensation(), swr_drop_output(), and swr_inject_silence() are + * function used internally for timestamp compensation. + * @return the output timestamp for the next output sample + */ +int64_t swr_next_pts(struct SwrContext *s, int64_t pts); + +/** + * @} + * + * @name Low-level option setting functions + * These functions provide a means to set low-level options that is not possible + * with the AVOption API. + * @{ + */ + +/** + * Activate resampling compensation ("soft" compensation). This function is + * internally called when needed in swr_next_pts(). + * + * @param[in,out] s allocated Swr context. If it is not initialized, + * or SWR_FLAG_RESAMPLE is not set, swr_init() is + * called with the flag set. + * @param[in] sample_delta delta in PTS per sample + * @param[in] compensation_distance number of samples to compensate for + * @return >= 0 on success, AVERROR error codes if: + * @li @c s is NULL, + * @li @c compensation_distance is less than 0, + * @li @c compensation_distance is 0 but sample_delta is not, + * @li compensation unsupported by resampler, or + * @li swr_init() fails when called. + */ +int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance); + +/** + * Set a customized input channel mapping. + * + * @param[in,out] s allocated Swr context, not yet initialized + * @param[in] channel_map customized input channel mapping (array of channel + * indexes, -1 for a muted channel) + * @return >= 0 on success, or AVERROR error code in case of failure. + */ +int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); + +/** + * Generate a channel mixing matrix. + * + * This function is the one used internally by libswresample for building the + * default mixing matrix. It is made public just as a utility function for + * building custom matrices. + * + * @param in_layout input channel layout + * @param out_layout output channel layout + * @param center_mix_level mix level for the center channel + * @param surround_mix_level mix level for the surround channel(s) + * @param lfe_mix_level mix level for the low-frequency effects channel + * @param rematrix_maxval if 1.0, coefficients will be normalized to prevent + * overflow. if INT_MAX, coefficients will not be + * normalized. + * @param[out] matrix mixing coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o. + * @param stride distance between adjacent input channels in the + * matrix array + * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii) + * @param log_ctx parent logging context, can be NULL + * @return 0 on success, negative AVERROR code on failure + */ +int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double maxval, + double rematrix_volume, double *matrix, + ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, + void *log_context); + +/** + * Set a customized remix matrix. + * + * @param s allocated Swr context, not yet initialized + * @param matrix remix coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o + * @param stride offset between lines of the matrix + * @return >= 0 on success, or AVERROR error code in case of failure. + */ +int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride); + +/** + * @} + * + * @name Sample handling functions + * @{ + */ + +/** + * Drops the specified number of output samples. + * + * This function, along with swr_inject_silence(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure + */ +int swr_drop_output(struct SwrContext *s, int count); + +/** + * Injects the specified number of silence samples. + * + * This function, along with swr_drop_output(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure + */ +int swr_inject_silence(struct SwrContext *s, int count); + +/** + * Gets the delay the next input sample will experience relative to the next output sample. + * + * Swresample can buffer data if more input has been provided than available + * output space, also converting between sample rates needs a delay. + * This function returns the sum of all such delays. + * The exact delay is not necessarily an integer value in either input or + * output sample rate. Especially when downsampling by a large value, the + * output sample rate may be a poor choice to represent the delay, similarly + * for upsampling and the input sample rate. + * + * @param s swr context + * @param base timebase in which the returned delay will be: + * @li if it's set to 1 the returned delay is in seconds + * @li if it's set to 1000 the returned delay is in milliseconds + * @li if it's set to the input sample rate then the returned + * delay is in input samples + * @li if it's set to the output sample rate then the returned + * delay is in output samples + * @li if it's the least common multiple of in_sample_rate and + * out_sample_rate then an exact rounding-free delay will be + * returned + * @returns the delay in 1 / @c base units. + */ +int64_t swr_get_delay(struct SwrContext *s, int64_t base); + +/** + * Find an upper bound on the number of samples that the next swr_convert + * call will output, if called with in_samples of input samples. This + * depends on the internal state, and anything changing the internal state + * (like further swr_convert() calls) will may change the number of samples + * swr_get_out_samples() returns for the same number of input samples. + * + * @param in_samples number of input samples. + * @note any call to swr_inject_silence(), swr_convert(), swr_next_pts() + * or swr_set_compensation() invalidates this limit + * @note it is recommended to pass the correct available buffer size + * to all functions like swr_convert() even if swr_get_out_samples() + * indicates that less would be used. + * @returns an upper bound on the number of samples that the next swr_convert + * will output or a negative value to indicate an error + */ +int swr_get_out_samples(struct SwrContext *s, int in_samples); + +/** + * @} + * + * @name Configuration accessors + * @{ + */ + +/** + * Return the @ref LIBSWRESAMPLE_VERSION_INT constant. + * + * This is useful to check if the build-time libswresample has the same version + * as the run-time one. + * + * @returns the unsigned int-typed version + */ +unsigned swresample_version(void); + +/** + * Return the swr build-time configuration. + * + * @returns the build-time @c ./configure flags + */ +const char *swresample_configuration(void); + +/** + * Return the swr license. + * + * @returns the license of libswresample, determined at build-time + */ +const char *swresample_license(void); + +/** + * @} + * + * @name AVFrame based API + * @{ + */ + +/** + * Convert the samples in the input AVFrame and write them to the output AVFrame. + * + * Input and output AVFrames must have channel_layout, sample_rate and format set. + * + * If the output AVFrame does not have the data pointers allocated the nb_samples + * field will be set using av_frame_get_buffer() + * is called to allocate the frame. + * + * The output AVFrame can be NULL or have fewer allocated samples than required. + * In this case, any remaining samples not written to the output will be added + * to an internal FIFO buffer, to be returned at the next call to this function + * or to swr_convert(). + * + * If converting sample rate, there may be data remaining in the internal + * resampling delay buffer. swr_get_delay() tells the number of + * remaining samples. To get this data as output, call this function or + * swr_convert() with NULL input. + * + * If the SwrContext configuration does not match the output and + * input AVFrame settings the conversion does not take place and depending on + * which AVFrame is not matching AVERROR_OUTPUT_CHANGED, AVERROR_INPUT_CHANGED + * or the result of a bitwise-OR of them is returned. + * + * @see swr_delay() + * @see swr_convert() + * @see swr_get_delay() + * + * @param swr audio resample context + * @param output output AVFrame + * @param input input AVFrame + * @return 0 on success, AVERROR on failure or nonmatching + * configuration. + */ +int swr_convert_frame(SwrContext *swr, + AVFrame *output, const AVFrame *input); + +/** + * Configure or reconfigure the SwrContext using the information + * provided by the AVFrames. + * + * The original resampling context is reset even on failure. + * The function calls swr_close() internally if the context is open. + * + * @see swr_close(); + * + * @param swr audio resample context + * @param out output AVFrame + * @param in input AVFrame + * @return 0 on success, AVERROR on failure. + */ +int swr_config_frame(SwrContext *swr, const AVFrame *out, const AVFrame *in); + +/** + * @} + * @} + */ + +#endif /* SWRESAMPLE_SWRESAMPLE_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libswresample/version.h b/src/framework/media/thirdparty/ffmpeg/v8/libswresample/version.h new file mode 100644 index 0000000000000..9c223e1426f9a --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libswresample/version.h @@ -0,0 +1,46 @@ +/* + * Version macros. + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_VERSION_H +#define SWRESAMPLE_VERSION_H + +/** + * @file + * Libswresample version macros + */ + +#include "libavutil/version.h" + +#include "version_major.h" + +#define LIBSWRESAMPLE_VERSION_MINOR 1 +#define LIBSWRESAMPLE_VERSION_MICRO 100 + +#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) +#define LIBSWRESAMPLE_VERSION AV_VERSION(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) +#define LIBSWRESAMPLE_BUILD LIBSWRESAMPLE_VERSION_INT + +#define LIBSWRESAMPLE_IDENT "SwR" AV_STRINGIFY(LIBSWRESAMPLE_VERSION) + +#endif /* SWRESAMPLE_VERSION_H */ diff --git a/src/framework/media/thirdparty/ffmpeg/v8/libswresample/version_major.h b/src/framework/media/thirdparty/ffmpeg/v8/libswresample/version_major.h new file mode 100644 index 0000000000000..4e0bc0ab19970 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v8/libswresample/version_major.h @@ -0,0 +1,31 @@ +/* + * Version macros. + * + * This file is part of libswresample + * + * libswresample is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libswresample is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_VERSION_MAJOR_H +#define SWRESAMPLE_VERSION_MAJOR_H + +/** + * @file + * Libswresample version macros + */ + +#define LIBSWRESAMPLE_VERSION_MAJOR 6 + +#endif /* SWRESAMPLE_VERSION_MAJOR_H */ From 088d25230c7a2356828ad3434130934e3558912b Mon Sep 17 00:00:00 2001 From: Eism Date: Thu, 12 Mar 2026 12:07:56 +0200 Subject: [PATCH 23/52] added loading libswresample --- .../internal/ffmpeg/v7/ffmpeglibhandler.cpp | 10 ++++++---- .../media/internal/ffmpeg/v7/ffmpeglibhandler.h | 3 ++- .../internal/ffmpeg/v8/ffmpeglibhandler.cpp | 10 ++++++---- .../media/internal/ffmpeg/v8/ffmpeglibhandler.h | 3 ++- src/framework/media/internal/ffmpegutils.cpp | 10 ++++++++-- src/framework/media/internal/ffmpegutils.h | 16 +++++++++------- .../media/internal/videoencoderresolver.cpp | 4 ++-- 7 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp index ae44cecd8a17e..91b5f492de878 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp @@ -53,7 +53,7 @@ void* FFmpegLibHandler::getSymbol(void* lib, const char* name) const bool FFmpegLibHandler::loadApi() { - if (!m_avUtilLibrary || !m_avCodecLibrary || !m_avFormatLibrary || !m_swsScaleLibrary) { + if (!m_avUtilLibrary || !m_avCodecLibrary || !m_avFormatLibrary || !m_swsScaleLibrary || !m_swResampleLibrary) { return false; } @@ -108,20 +108,21 @@ bool FFmpegLibHandler::loadApi() } bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, - const io::path_t& swScalePath) + const io::path_t& swScalePath, const io::path_t& swResamplePath) { unload(); - // Load avutil first, then avcodec, swscale, avformat (dependency order) + // Load avutil first, then avcodec, swscale, swresample, avformat (dependency order) if (!tryLoadPath(m_avUtilLibrary, avUtilPath) || !tryLoadPath(m_avCodecLibrary, avCodecPath) || !tryLoadPath(m_swsScaleLibrary, swScalePath) + || !tryLoadPath(m_swResampleLibrary, swResamplePath) || !tryLoadPath(m_avFormatLibrary, avFormatPath)) { return false; } LOGI() << "FFmpeg loaded: avutil=" << avUtilPath << ", avcodec=" << avCodecPath << ", avformat=" << avFormatPath - << ", swscale=" << swScalePath; + << ", swscale=" << swScalePath << ", swresample=" << swResamplePath; return true; } @@ -129,6 +130,7 @@ bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& a void FFmpegLibHandler::unload() { closeLib(m_avFormatLibrary); + closeLib(m_swResampleLibrary); closeLib(m_swsScaleLibrary); closeLib(m_avCodecLibrary); closeLib(m_avUtilLibrary); diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h index 64287c1631111..4d586e042e4d9 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h @@ -37,7 +37,7 @@ class FFmpegLibHandler FFmpegLibHandler() = default; bool loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, - const io::path_t& swScalePath); + const io::path_t& swScalePath, const io::path_t& swResamplePath); bool loadApi(); void unload(); @@ -107,6 +107,7 @@ private : void* getSymbol(void* lib, const char* name) const; void* m_avCodecLibrary = nullptr; void* m_avFormatLibrary = nullptr; void* m_swsScaleLibrary = nullptr; + void* m_swResampleLibrary = nullptr; int m_version = 0; io::path_t m_dir; diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp index 5824917ce98b2..d0017f81531ce 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp @@ -53,7 +53,7 @@ void* FFmpegLibHandler::getSymbol(void* lib, const char* name) const bool FFmpegLibHandler::loadApi() { - if (!m_avUtilLibrary || !m_avCodecLibrary || !m_avFormatLibrary || !m_swsScaleLibrary) { + if (!m_avUtilLibrary || !m_avCodecLibrary || !m_avFormatLibrary || !m_swsScaleLibrary || !m_swResampleLibrary) { return false; } @@ -106,20 +106,21 @@ bool FFmpegLibHandler::loadApi() } bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, - const io::path_t& swScalePath) + const io::path_t& swScalePath, const io::path_t& swResamplePath) { unload(); - // Load avutil first, then avcodec, swscale, avformat (dependency order) + // Load avutil first, then avcodec, swscale, swresample, avformat (dependency order) if (!tryLoadPath(m_avUtilLibrary, avUtilPath) || !tryLoadPath(m_avCodecLibrary, avCodecPath) || !tryLoadPath(m_swsScaleLibrary, swScalePath) + || !tryLoadPath(m_swResampleLibrary, swResamplePath) || !tryLoadPath(m_avFormatLibrary, avFormatPath)) { return false; } LOGI() << "FFmpeg loaded: avutil=" << avUtilPath << ", avcodec=" << avCodecPath << ", avformat=" << avFormatPath - << ", swscale=" << swScalePath; + << ", swscale=" << swScalePath << ", swresample=" << swResamplePath; return true; } @@ -127,6 +128,7 @@ bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& a void FFmpegLibHandler::unload() { closeLib(m_avFormatLibrary); + closeLib(m_swResampleLibrary); closeLib(m_swsScaleLibrary); closeLib(m_avCodecLibrary); closeLib(m_avUtilLibrary); diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h index 0ace5ccfc38e8..302467fedbc8d 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h @@ -37,7 +37,7 @@ class FFmpegLibHandler FFmpegLibHandler() = default; bool loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, - const io::path_t& swScalePath); + const io::path_t& swScalePath, const io::path_t& swResamplePath); bool loadApi(); void unload(); @@ -105,6 +105,7 @@ private : void* getSymbol(void* lib, const char* name) const; void* m_avCodecLibrary = nullptr; void* m_avFormatLibrary = nullptr; void* m_swsScaleLibrary = nullptr; + void* m_swResampleLibrary = nullptr; int m_version = 0; io::path_t m_dir; diff --git a/src/framework/media/internal/ffmpegutils.cpp b/src/framework/media/internal/ffmpegutils.cpp index 5b5fc8b8124e7..6f40e69dec5e3 100644 --- a/src/framework/media/internal/ffmpegutils.cpp +++ b/src/framework/media/internal/ffmpegutils.cpp @@ -61,22 +61,25 @@ static FFmpegLibPaths libraryPathsForVersion(int ffmpegVer, const io::paths_t& s return {}; } - io::path_t avutilName, avcodecName, avformatName, swscaleName; + io::path_t avutilName, avcodecName, avformatName, swscaleName, swresampleName; #if defined(Q_OS_MAC) avutilName = io::path_t("libavutil." + std::to_string(ffmpegVersionInfo.avUtilVersion) + ".dylib"); avcodecName = io::path_t("libavcodec." + std::to_string(ffmpegVersionInfo.avCodecVersion) + ".dylib"); avformatName = io::path_t("libavformat." + std::to_string(ffmpegVersionInfo.avFormatVersion) + ".dylib"); swscaleName = io::path_t("libswscale." + std::to_string(ffmpegVersionInfo.swScaleVersion) + ".dylib"); + swresampleName = io::path_t("libswresample." + std::to_string(ffmpegVersionInfo.swResampleVersion) + ".dylib"); #elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) avutilName = io::path_t("libavutil.so." + std::to_string(ffmpegVersionInfo.avUtilVersion)); avcodecName = io::path_t("libavcodec.so." + std::to_string(ffmpegVersionInfo.avCodecVersion)); avformatName = io::path_t("libavformat.so." + verStr); swscaleName = io::path_t("libswscale.so." + std::to_string(ffmpegVersionInfo.swScaleVersion)); + swresampleName = io::path_t("libswresample.so." + std::to_string(ffmpegVersionInfo.swResampleVersion)); #elif defined(Q_OS_WIN) avutilName = io::path_t("avutil-" + std::to_string(ffmpegVersionInfo.avUtilVersion) + ".dll"); avcodecName = io::path_t("avcodec-" + std::to_string(ffmpegVersionInfo.avCodecVersion) + ".dll"); avformatName = io::path_t("avformat-" + std::to_string(ffmpegVersionInfo.avFormatVersion) + ".dll"); swscaleName = io::path_t("swscale-" + std::to_string(ffmpegVersionInfo.swScaleVersion) + ".dll"); + swresampleName = io::path_t("swresample-" + std::to_string(ffmpegVersionInfo.swResampleVersion) + ".dll"); #endif FFmpegLibPaths result; @@ -85,12 +88,15 @@ static FFmpegLibPaths libraryPathsForVersion(int ffmpegVer, const io::paths_t& s io::path_t avcodecPath = dir.appendingComponent(avcodecName); io::path_t avformatPath = dir.appendingComponent(avformatName); io::path_t swscalePath = dir.appendingComponent(swscaleName); + io::path_t swresamplePath = dir.appendingComponent(swresampleName); if (io::FileInfo::exists(avutilPath) && io::FileInfo::exists(avcodecPath) - && io::FileInfo::exists(avformatPath) && io::FileInfo::exists(swscalePath)) { + && io::FileInfo::exists(avformatPath) && io::FileInfo::exists(swscalePath) + && io::FileInfo::exists(swresamplePath)) { result.avUtilPath = avutilPath; result.avCodecPath = avcodecPath; result.avFormatPath = avformatPath; result.swScalePath = swscalePath; + result.swResamplePath = swresamplePath; return result; } } diff --git a/src/framework/media/internal/ffmpegutils.h b/src/framework/media/internal/ffmpegutils.h index a8baeaa3b2fe9..a168fcdaac46f 100644 --- a/src/framework/media/internal/ffmpegutils.h +++ b/src/framework/media/internal/ffmpegutils.h @@ -40,20 +40,21 @@ struct FFmpegVersionInfo { int avUtilVersion = -1; int avCodecVersion = -1; int swScaleVersion = -1; + int swResampleVersion = -1; bool isValid() const { - return avFormatVersion != -1 && avUtilVersion != -1 && avCodecVersion != -1 && swScaleVersion != -1; + return avFormatVersion != -1 && avUtilVersion != -1 && avCodecVersion != -1 && swScaleVersion != -1 && swResampleVersion != -1; } }; static const std::vector > FFMPEG_COMPONENTS_VERSIONS = { - // ffmpeg avFormat avUtil avCodec swScale - { FFMPEG_V8, { 62, 60, 62, 9 } }, - { FFMPEG_V7, { 61, 59, 61, 8 } }, - { FFMPEG_V6, { 60, 58, 60, 7 } }, - { FFMPEG_V5, { 59, 57, 59, 6 } }, - { FFMPEG_V4, { 58, 56, 58, 5 } }, + // ffmpeg avFormat avUtil avCodec swScale swResample + { FFMPEG_V8, { 62, 60, 62, 9, 6 } }, + { FFMPEG_V7, { 61, 59, 61, 8, 5 } }, + { FFMPEG_V6, { 60, 58, 60, 7, 4 } }, + { FFMPEG_V5, { 59, 57, 59, 6, 4 } }, + { FFMPEG_V4, { 58, 56, 58, 5, 3 } }, }; struct FFmpegLibPaths { @@ -61,6 +62,7 @@ struct FFmpegLibPaths { io::path_t avCodecPath; io::path_t avFormatPath; io::path_t swScalePath; + io::path_t swResamplePath; }; FFmpegLibPaths findLibraryPaths(const io::path_t& ffmpegLibsDir); diff --git a/src/framework/media/internal/videoencoderresolver.cpp b/src/framework/media/internal/videoencoderresolver.cpp index d43a48b1c1ba2..f324cbd0fbfff 100644 --- a/src/framework/media/internal/videoencoderresolver.cpp +++ b/src/framework/media/internal/videoencoderresolver.cpp @@ -100,7 +100,7 @@ VideoEncoderResolver::EncoderInfo VideoEncoderResolver::makeEncoder(const FFmpeg case FFMPEG_V8: { auto ffmpegLibHandler = std::make_shared(); if (ffmpegLibHandler->loadLib(ffmpegLibsPaths.avUtilPath, ffmpegLibsPaths.avCodecPath, ffmpegLibsPaths.avFormatPath, - ffmpegLibsPaths.swScalePath) + ffmpegLibsPaths.swScalePath, ffmpegLibsPaths.swResamplePath) && ffmpegLibHandler->loadApi()) { ffmpegLibHandler->setVersion(version); ffmpegLibHandler->setDir(io::dirpath(ffmpegLibsPaths.avFormatPath)); @@ -117,7 +117,7 @@ VideoEncoderResolver::EncoderInfo VideoEncoderResolver::makeEncoder(const FFmpeg case FFMPEG_V7: { auto ffmpegLibHandler = std::make_shared(); if (ffmpegLibHandler->loadLib(ffmpegLibsPaths.avUtilPath, ffmpegLibsPaths.avCodecPath, ffmpegLibsPaths.avFormatPath, - ffmpegLibsPaths.swScalePath) + ffmpegLibsPaths.swScalePath, ffmpegLibsPaths.swResamplePath) && ffmpegLibHandler->loadApi()) { ffmpegLibHandler->setVersion(version); ffmpegLibHandler->setDir(io::dirpath(ffmpegLibsPaths.avFormatPath)); From 00fc4c6073ac8ae6f02761e2eda5d2c3bd07daaf Mon Sep 17 00:00:00 2001 From: Eism Date: Thu, 12 Mar 2026 13:32:23 +0200 Subject: [PATCH 24/52] fixed build on Windows --- src/framework/media/CMakeLists.txt | 2 +- .../media/internal/ffmpeg/v7/ffmpeglibhandler.cpp | 6 +++--- .../media/internal/ffmpeg/v8/ffmpeglibhandler.cpp | 6 +++--- src/framework/media/internal/ffmpeg/v8/videoencoder.cpp | 9 +++++++++ 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/framework/media/CMakeLists.txt b/src/framework/media/CMakeLists.txt index 938c350e3d986..f1d37ac6886e1 100644 --- a/src/framework/media/CMakeLists.txt +++ b/src/framework/media/CMakeLists.txt @@ -47,7 +47,7 @@ target_sources(muse_media PRIVATE internal/ffmpeg/v7/videoencoder.h ) -target_include_directories(muse_media PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg) +target_include_directories(muse_media PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v8) set(MODULE_USE_PCH OFF) set(MODULE_USE_UNITY OFF) diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp index 91b5f492de878..3121ef97e00a2 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp @@ -112,11 +112,11 @@ bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& a { unload(); - // Load avutil first, then avcodec, swscale, swresample, avformat (dependency order) + // Load avutil first, then swresample, swscale, avcodec, avformat (dependency order) if (!tryLoadPath(m_avUtilLibrary, avUtilPath) - || !tryLoadPath(m_avCodecLibrary, avCodecPath) - || !tryLoadPath(m_swsScaleLibrary, swScalePath) || !tryLoadPath(m_swResampleLibrary, swResamplePath) + || !tryLoadPath(m_swsScaleLibrary, swScalePath) + || !tryLoadPath(m_avCodecLibrary, avCodecPath) || !tryLoadPath(m_avFormatLibrary, avFormatPath)) { return false; } diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp index d0017f81531ce..5d555e81b0c91 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp @@ -110,11 +110,11 @@ bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& a { unload(); - // Load avutil first, then avcodec, swscale, swresample, avformat (dependency order) + // Load avutil first, then swresample, swscale, avcodec, avformat (dependency order) if (!tryLoadPath(m_avUtilLibrary, avUtilPath) - || !tryLoadPath(m_avCodecLibrary, avCodecPath) - || !tryLoadPath(m_swsScaleLibrary, swScalePath) || !tryLoadPath(m_swResampleLibrary, swResamplePath) + || !tryLoadPath(m_swsScaleLibrary, swScalePath) + || !tryLoadPath(m_avCodecLibrary, avCodecPath) || !tryLoadPath(m_avFormatLibrary, avFormatPath)) { return false; } diff --git a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp index 108daaf30c214..d5a02203cd082 100644 --- a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp @@ -330,7 +330,12 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) AVFormatContext* audioFmtCtx = nullptr; AVFormatContext* outputFmtCtx = nullptr; + bool cleaned = false; auto cleanup = [&]() { + if (cleaned) { + return; + } + if (videoFmtCtx) { m_ffmpegHandler->avformat_close_input(&videoFmtCtx); } @@ -343,6 +348,8 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) } m_ffmpegHandler->avformat_free_context(outputFmtCtx); } + + cleaned = true; }; DEFER { @@ -460,6 +467,8 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) m_ffmpegHandler->av_packet_free(&pkt); m_ffmpegHandler->av_write_trailer(outputFmtCtx); + cleanup(); + if (!io::File::copy(tmpPath, videoPath, true)) { LOGE() << "addAudio: failed to replace with muxed file"; return false; From 5b38dabec3f4b6853656ec7c2d69d1d57328097b Mon Sep 17 00:00:00 2001 From: Eism Date: Fri, 13 Mar 2026 12:05:18 +0200 Subject: [PATCH 25/52] fixed ffmpeg 7 and applied to ffmpeg 8 --- src/framework/media/CMakeLists.txt | 6 +- .../internal/ffmpeg/v7/ffmpeglibhandler.cpp | 8 +- .../internal/ffmpeg/v7/ffmpeglibhandler.h | 6 +- .../media/internal/ffmpeg/v7/videoencoder.cpp | 103 +++++++++--------- .../internal/ffmpeg/v8/ffmpeglibhandler.cpp | 8 +- .../internal/ffmpeg/v8/ffmpeglibhandler.h | 6 +- .../media/internal/ffmpeg/v8/videoencoder.cpp | 103 +++++++++--------- 7 files changed, 129 insertions(+), 111 deletions(-) diff --git a/src/framework/media/CMakeLists.txt b/src/framework/media/CMakeLists.txt index f1d37ac6886e1..d23b44f9b5f74 100644 --- a/src/framework/media/CMakeLists.txt +++ b/src/framework/media/CMakeLists.txt @@ -47,7 +47,11 @@ target_sources(muse_media PRIVATE internal/ffmpeg/v7/videoencoder.h ) -target_include_directories(muse_media PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v8) +target_include_directories(muse_media + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v8 + ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v7 +) set(MODULE_USE_PCH OFF) set(MODULE_USE_UNITY OFF) diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp index 3121ef97e00a2..9da02a0ecc32d 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp @@ -69,6 +69,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); RESOLVE_FROM(m_avUtilLibrary, av_opt_set_pixel_fmt); RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); + RESOLVE_FROM(m_avUtilLibrary, av_frame_free); // libavformat RESOLVE_FROM(m_avFormatLibrary, av_guess_format); @@ -96,6 +97,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context); RESOLVE_FROM(m_avCodecLibrary, avcodec_open2); RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_to_context); RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy); RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame); RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet); @@ -175,9 +177,9 @@ bool FFmpegLibHandler::functionsValid() const && avformat_close_input && avformat_free_context && avformat_alloc_output_context2 && av_read_frame && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context - && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_copy + && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_to_context && avcodec_parameters_copy && avcodec_send_frame && avcodec_receive_packet - && av_frame_alloc + && av_frame_alloc && av_frame_free && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts && sws_getCachedContext && sws_scale; } @@ -211,10 +213,12 @@ void FFmpegLibHandler::clearFunctions() avcodec_free_context = nullptr; avcodec_open2 = nullptr; avcodec_parameters_from_context = nullptr; + avcodec_parameters_to_context = nullptr; avcodec_parameters_copy = nullptr; avcodec_send_frame = nullptr; avcodec_receive_packet = nullptr; av_frame_alloc = nullptr; + av_frame_free = nullptr; av_packet_alloc = nullptr; av_packet_free = nullptr; av_packet_unref = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h index 4d586e042e4d9..06f98c6bbb8c1 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h @@ -36,8 +36,8 @@ class FFmpegLibHandler public: FFmpegLibHandler() = default; - bool loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, - const io::path_t& swScalePath, const io::path_t& swResamplePath); + bool loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, const io::path_t& swScalePath, + const io::path_t& swResamplePath); bool loadApi(); void unload(); @@ -81,10 +81,12 @@ class FFmpegLibHandler void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; + int (*avcodec_parameters_to_context)(AVCodecContext* codec, const AVCodecParameters* par) = nullptr; int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; AVFrame*(*av_frame_alloc)(void) = nullptr; + void (*av_frame_free)(AVFrame** frame) = nullptr; AVPacket*(*av_packet_alloc)(void) = nullptr; void (*av_packet_free)(AVPacket** pkt) = nullptr; void (*av_packet_unref)(AVPacket* pkt) = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp index 0560a236d1107..61c87864b9391 100644 --- a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp @@ -32,7 +32,6 @@ struct FFmpeg { unsigned int ptsCounter = 0; // FFmpeg stuff - const AVOutputFormat* outputFormat = nullptr; AVFormatContext* formatCtx = nullptr; AVStream* videoStream = nullptr; AVCodecContext* codecCtx = nullptr; @@ -46,6 +45,7 @@ struct FFmpeg { AVPacket* pkt; bool opened = false; + bool finished = false; }; VideoEncoder::VideoEncoder(const std::shared_ptr& handler) @@ -66,18 +66,14 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->width = width; m_ffmpeg->height = height; - m_ffmpeg->outputFormat = m_ffmpegHandler->av_guess_format("mp4", NULL, NULL); - - m_ffmpeg->formatCtx = m_ffmpegHandler->avformat_alloc_context(); - if (!m_ffmpeg->formatCtx) { - LOGE() << "failed allocate format context"; + if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, "mp4", fileName.c_str()) < 0 + || !m_ffmpeg->formatCtx) { + LOGE() << "failed to allocate output context"; return false; } - m_ffmpeg->formatCtx->oformat = m_ffmpeg->outputFormat; - m_ffmpeg->formatCtx->url = strdup(fileName.c_str()); // Add the video stream - m_ffmpeg->videoStream = m_ffmpegHandler->avformat_new_stream(m_ffmpeg->formatCtx, 0); + m_ffmpeg->videoStream = m_ffmpegHandler->avformat_new_stream(m_ffmpeg->formatCtx, nullptr); if (!m_ffmpeg->videoStream) { LOGE() << "failed allocate stream"; return false; @@ -98,25 +94,29 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } - m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; - - m_ffmpeg->codecCtx->bit_rate = bitrate; - m_ffmpeg->codecCtx->width = width; - m_ffmpeg->codecCtx->height = height; + m_ffmpeg->videoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + m_ffmpeg->videoStream->codecpar->codec_id = AV_CODEC_ID_H264; + m_ffmpeg->videoStream->codecpar->width = width; + m_ffmpeg->videoStream->codecpar->height = height; + m_ffmpeg->videoStream->codecpar->format = AV_PIX_FMT_YUV420P; + m_ffmpeg->videoStream->codecpar->bit_rate = bitrate; - // Avoid bug with missing frames - m_ffmpeg->codecCtx->gop_size = gop; - m_ffmpeg->codecCtx->pix_fmt = AV_PIX_FMT_YUV420P; - m_ffmpeg->codecCtx->thread_count = 10; + if (m_ffmpegHandler->avcodec_parameters_to_context(m_ffmpeg->codecCtx, m_ffmpeg->videoStream->codecpar) < 0) { + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + LOGE() << "failed to set codec parameters from stream"; + return false; + } + m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; m_ffmpeg->codecCtx->time_base.den = fps; m_ffmpeg->codecCtx->time_base.num = 1; + m_ffmpeg->codecCtx->gop_size = gop; + m_ffmpeg->codecCtx->thread_count = 10; m_ffmpeg->codecCtx->max_b_frames = 3; m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); m_ffmpeg->codecCtx->me_cmp = 1; m_ffmpeg->codecCtx->me_range = 16; - m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "hex", 1, 0); m_ffmpeg->codecCtx->qmin = 10; @@ -128,22 +128,19 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->codecCtx->qcompress = 0.6; m_ffmpeg->codecCtx->max_qdiff = 4; - // some formats want stream headers to be separate if (m_ffmpeg->formatCtx->oformat->flags & AVFMT_GLOBALHEADER) { - m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_LOOP_FILTER; + m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } - //av_dump_format(m_ffmpeg->formatCtx, 0, fileName.c_str(), 1); + if (m_ffmpegHandler->avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, nullptr) < 0) { + LOGE() << "failed open codec"; + return false; + } - // open_video + // Copy codec params to stream AFTER open - codec adds extradata (SPS/PPS) during open if (m_ffmpegHandler->avcodec_parameters_from_context(m_ffmpeg->videoStream->codecpar, m_ffmpeg->codecCtx) < 0) { m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); - LOGE() << "failed to set AV parameters from context"; - return false; - } - // open the codec - if (m_ffmpegHandler->avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, 0) < 0) { - LOGE() << "failed open codec"; + LOGE() << "failed to copy codec parameters to stream"; return false; } @@ -158,19 +155,17 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->ppicture->height = height; m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; - int size = m_ffmpegHandler->av_image_get_buffer_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, - m_ffmpeg->codecCtx->height, 1); + int size = m_ffmpegHandler->av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); m_ffmpeg->picture_buf = new uint8_t[size]; if (!m_ffmpeg->picture_buf) { LOGE() << "failed allocate frame buf"; - m_ffmpegHandler->av_free(m_ffmpeg->ppicture); + m_ffmpegHandler->av_frame_free(&m_ffmpeg->ppicture); return false; } // Setup the planes m_ffmpegHandler->av_image_fill_arrays(m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize, m_ffmpeg->picture_buf, - m_ffmpeg->codecCtx->pix_fmt, - m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height, 1); + AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); if (m_ffmpegHandler->avio_open(&m_ffmpeg->formatCtx->pb, fileName.c_str(), AVIO_FLAG_WRITE) < 0) { LOGE() << "failed open file: " << fileName; @@ -183,6 +178,8 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } + //av_dump_format(m_ffmpeg->formatCtx, 0, fileName.c_str(), 1); + m_ffmpeg->opened = true; m_outputPath = fileName; @@ -191,7 +188,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign void VideoEncoder::finishEncode() { - if (!m_ffmpeg->opened) { + if (!m_ffmpeg->opened || m_ffmpeg->finished) { return; } @@ -229,8 +226,13 @@ void VideoEncoder::finishEncode() } m_ffmpegHandler->av_write_trailer(m_ffmpeg->formatCtx); - m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); - m_ffmpeg->formatCtx->pb = nullptr; + + if (m_ffmpeg->formatCtx->pb) { + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; + } + + m_ffmpeg->finished = true; } void VideoEncoder::close() @@ -239,7 +241,10 @@ void VideoEncoder::close() return; } - // close_video + if (!m_ffmpeg->finished) { + finishEncode(); + } + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); if (m_ffmpeg->picture_buf) { @@ -248,24 +253,20 @@ void VideoEncoder::close() } if (m_ffmpeg->ppicture) { - m_ffmpegHandler->av_free(m_ffmpeg->ppicture); + m_ffmpegHandler->av_frame_free(&m_ffmpeg->ppicture); m_ffmpeg->ppicture = 0; } - /* free the streams */ - - for (unsigned int i = 0; i < m_ffmpeg->formatCtx->nb_streams; i++) { - m_ffmpegHandler->av_freep(&m_ffmpeg->formatCtx->streams[i]); + if (m_ffmpeg->formatCtx) { + if (m_ffmpeg->formatCtx->pb) { + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; + } + m_ffmpegHandler->avformat_free_context(m_ffmpeg->formatCtx); + m_ffmpeg->formatCtx = nullptr; } - - // Close file - m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); - m_ffmpeg->formatCtx->pb = nullptr; - - // Free the stream - m_ffmpegHandler->av_free(m_ffmpeg->formatCtx); - m_ffmpeg->formatCtx = nullptr; m_ffmpeg->opened = false; + m_ffmpeg->finished = false; m_outputPath = io::path_t(); } diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp index 5d555e81b0c91..52be48ba1b25b 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp @@ -67,6 +67,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avUtilLibrary, av_image_get_buffer_size); RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); + RESOLVE_FROM(m_avUtilLibrary, av_frame_free); // libavformat RESOLVE_FROM(m_avFormatLibrary, av_guess_format); @@ -94,6 +95,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context); RESOLVE_FROM(m_avCodecLibrary, avcodec_open2); RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_to_context); RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy); RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame); RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet); @@ -173,9 +175,9 @@ bool FFmpegLibHandler::functionsValid() const && avformat_close_input && avformat_free_context && avformat_alloc_output_context2 && av_read_frame && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context - && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_copy + && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_to_context && avcodec_parameters_copy && avcodec_send_frame && avcodec_receive_packet - && av_frame_alloc + && av_frame_alloc && av_frame_free && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts && sws_getCachedContext && sws_scale; } @@ -207,10 +209,12 @@ void FFmpegLibHandler::clearFunctions() avcodec_free_context = nullptr; avcodec_open2 = nullptr; avcodec_parameters_from_context = nullptr; + avcodec_parameters_to_context = nullptr; avcodec_parameters_copy = nullptr; avcodec_send_frame = nullptr; avcodec_receive_packet = nullptr; av_frame_alloc = nullptr; + av_frame_free = nullptr; av_packet_alloc = nullptr; av_packet_free = nullptr; av_packet_unref = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h index 302467fedbc8d..1151b44161f0f 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h @@ -36,8 +36,8 @@ class FFmpegLibHandler public: FFmpegLibHandler() = default; - bool loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, - const io::path_t& swScalePath, const io::path_t& swResamplePath); + bool loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, const io::path_t& swScalePath, + const io::path_t& swResamplePath); bool loadApi(); void unload(); @@ -79,10 +79,12 @@ class FFmpegLibHandler void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; + int (*avcodec_parameters_to_context)(AVCodecContext* codec, const AVCodecParameters* par) = nullptr; int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; AVFrame*(*av_frame_alloc)(void) = nullptr; + void (*av_frame_free)(AVFrame** frame) = nullptr; AVPacket*(*av_packet_alloc)(void) = nullptr; void (*av_packet_free)(AVPacket** pkt) = nullptr; void (*av_packet_unref)(AVPacket* pkt) = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp index d5a02203cd082..0528f016f59df 100644 --- a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp @@ -32,7 +32,6 @@ struct FFmpeg { unsigned int ptsCounter = 0; // FFmpeg stuff - const AVOutputFormat* outputFormat = nullptr; AVFormatContext* formatCtx = nullptr; AVStream* videoStream = nullptr; AVCodecContext* codecCtx = nullptr; @@ -46,6 +45,7 @@ struct FFmpeg { AVPacket* pkt; bool opened = false; + bool finished = false; }; VideoEncoder::VideoEncoder(const std::shared_ptr& handler) @@ -66,18 +66,14 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->width = width; m_ffmpeg->height = height; - m_ffmpeg->outputFormat = m_ffmpegHandler->av_guess_format("mp4", NULL, NULL); - - m_ffmpeg->formatCtx = m_ffmpegHandler->avformat_alloc_context(); - if (!m_ffmpeg->formatCtx) { - LOGE() << "failed allocate format context"; + if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, "mp4", fileName.c_str()) < 0 + || !m_ffmpeg->formatCtx) { + LOGE() << "failed to allocate output context"; return false; } - m_ffmpeg->formatCtx->oformat = m_ffmpeg->outputFormat; - m_ffmpeg->formatCtx->url = strdup(fileName.c_str()); // Add the video stream - m_ffmpeg->videoStream = m_ffmpegHandler->avformat_new_stream(m_ffmpeg->formatCtx, 0); + m_ffmpeg->videoStream = m_ffmpegHandler->avformat_new_stream(m_ffmpeg->formatCtx, nullptr); if (!m_ffmpeg->videoStream) { LOGE() << "failed allocate stream"; return false; @@ -98,25 +94,29 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } - m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; - - m_ffmpeg->codecCtx->bit_rate = bitrate; - m_ffmpeg->codecCtx->width = width; - m_ffmpeg->codecCtx->height = height; + m_ffmpeg->videoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + m_ffmpeg->videoStream->codecpar->codec_id = AV_CODEC_ID_H264; + m_ffmpeg->videoStream->codecpar->width = width; + m_ffmpeg->videoStream->codecpar->height = height; + m_ffmpeg->videoStream->codecpar->format = AV_PIX_FMT_YUV420P; + m_ffmpeg->videoStream->codecpar->bit_rate = bitrate; - // Avoid bug with missing frames - m_ffmpeg->codecCtx->gop_size = gop; - m_ffmpeg->codecCtx->pix_fmt = AV_PIX_FMT_YUV420P; - m_ffmpeg->codecCtx->thread_count = 10; + if (m_ffmpegHandler->avcodec_parameters_to_context(m_ffmpeg->codecCtx, m_ffmpeg->videoStream->codecpar) < 0) { + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + LOGE() << "failed to set codec parameters from stream"; + return false; + } + m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; m_ffmpeg->codecCtx->time_base.den = fps; m_ffmpeg->codecCtx->time_base.num = 1; + m_ffmpeg->codecCtx->gop_size = gop; + m_ffmpeg->codecCtx->thread_count = 10; m_ffmpeg->codecCtx->max_b_frames = 3; m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); m_ffmpeg->codecCtx->me_cmp = 1; m_ffmpeg->codecCtx->me_range = 16; - m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "hex", 1, 0); m_ffmpeg->codecCtx->qmin = 10; @@ -128,22 +128,19 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->codecCtx->qcompress = 0.6; m_ffmpeg->codecCtx->max_qdiff = 4; - // some formats want stream headers to be separate if (m_ffmpeg->formatCtx->oformat->flags & AVFMT_GLOBALHEADER) { - m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_LOOP_FILTER; + m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } - //av_dump_format(m_ffmpeg->formatCtx, 0, fileName.c_str(), 1); + if (m_ffmpegHandler->avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, nullptr) < 0) { + LOGE() << "failed open codec"; + return false; + } - // open_video + // Copy codec params to stream AFTER open - codec adds extradata (SPS/PPS) during open if (m_ffmpegHandler->avcodec_parameters_from_context(m_ffmpeg->videoStream->codecpar, m_ffmpeg->codecCtx) < 0) { m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); - LOGE() << "failed to set AV parameters from context"; - return false; - } - // open the codec - if (m_ffmpegHandler->avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, 0) < 0) { - LOGE() << "failed open codec"; + LOGE() << "failed to copy codec parameters to stream"; return false; } @@ -158,19 +155,17 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->ppicture->height = height; m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; - int size = m_ffmpegHandler->av_image_get_buffer_size(m_ffmpeg->codecCtx->pix_fmt, m_ffmpeg->codecCtx->width, - m_ffmpeg->codecCtx->height, 1); + int size = m_ffmpegHandler->av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); m_ffmpeg->picture_buf = new uint8_t[size]; if (!m_ffmpeg->picture_buf) { LOGE() << "failed allocate frame buf"; - m_ffmpegHandler->av_free(m_ffmpeg->ppicture); + m_ffmpegHandler->av_frame_free(&m_ffmpeg->ppicture); return false; } // Setup the planes m_ffmpegHandler->av_image_fill_arrays(m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize, m_ffmpeg->picture_buf, - m_ffmpeg->codecCtx->pix_fmt, - m_ffmpeg->codecCtx->width, m_ffmpeg->codecCtx->height, 1); + AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); if (m_ffmpegHandler->avio_open(&m_ffmpeg->formatCtx->pb, fileName.c_str(), AVIO_FLAG_WRITE) < 0) { LOGE() << "failed open file: " << fileName; @@ -183,6 +178,8 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } + //av_dump_format(m_ffmpeg->formatCtx, 0, fileName.c_str(), 1); + m_ffmpeg->opened = true; m_outputPath = fileName; @@ -191,7 +188,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign void VideoEncoder::finishEncode() { - if (!m_ffmpeg->opened) { + if (!m_ffmpeg->opened || m_ffmpeg->finished) { return; } @@ -229,8 +226,13 @@ void VideoEncoder::finishEncode() } m_ffmpegHandler->av_write_trailer(m_ffmpeg->formatCtx); - m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); - m_ffmpeg->formatCtx->pb = nullptr; + + if (m_ffmpeg->formatCtx->pb) { + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; + } + + m_ffmpeg->finished = true; } void VideoEncoder::close() @@ -239,7 +241,10 @@ void VideoEncoder::close() return; } - // close_video + if (!m_ffmpeg->finished) { + finishEncode(); + } + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); if (m_ffmpeg->picture_buf) { @@ -248,24 +253,20 @@ void VideoEncoder::close() } if (m_ffmpeg->ppicture) { - m_ffmpegHandler->av_free(m_ffmpeg->ppicture); + m_ffmpegHandler->av_frame_free(&m_ffmpeg->ppicture); m_ffmpeg->ppicture = 0; } - /* free the streams */ - - for (unsigned int i = 0; i < m_ffmpeg->formatCtx->nb_streams; i++) { - m_ffmpegHandler->av_freep(&m_ffmpeg->formatCtx->streams[i]); + if (m_ffmpeg->formatCtx) { + if (m_ffmpeg->formatCtx->pb) { + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; + } + m_ffmpegHandler->avformat_free_context(m_ffmpeg->formatCtx); + m_ffmpeg->formatCtx = nullptr; } - - // Close file - m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); - m_ffmpeg->formatCtx->pb = nullptr; - - // Free the stream - m_ffmpegHandler->av_free(m_ffmpeg->formatCtx); - m_ffmpeg->formatCtx = nullptr; m_ffmpeg->opened = false; + m_ffmpeg->finished = false; m_outputPath = io::path_t(); } From b3b0ebeb95e77d22123219c9112ffa749be8d519 Mon Sep 17 00:00:00 2001 From: Eism Date: Fri, 13 Mar 2026 12:17:34 +0200 Subject: [PATCH 26/52] fixed the sequence of directories for searching --- src/framework/media/internal/ffmpegutils.cpp | 42 +++++++++---------- .../Preferences/folderspreferencesmodel.cpp | 2 + 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/framework/media/internal/ffmpegutils.cpp b/src/framework/media/internal/ffmpegutils.cpp index 6f40e69dec5e3..de9b2d98924ac 100644 --- a/src/framework/media/internal/ffmpegutils.cpp +++ b/src/framework/media/internal/ffmpegutils.cpp @@ -45,7 +45,7 @@ static io::paths_t defaultSearchPaths() return paths; } -static FFmpegLibPaths libraryPathsForVersion(int ffmpegVer, const io::paths_t& searchPaths) +static FFmpegLibPaths libraryPathsForVersion(int ffmpegVer, const io::path_t& searchDir) { const std::string verStr = std::to_string(ffmpegVer); @@ -83,22 +83,20 @@ static FFmpegLibPaths libraryPathsForVersion(int ffmpegVer, const io::paths_t& s #endif FFmpegLibPaths result; - for (const io::path_t& dir : searchPaths) { - io::path_t avutilPath = dir.appendingComponent(avutilName); - io::path_t avcodecPath = dir.appendingComponent(avcodecName); - io::path_t avformatPath = dir.appendingComponent(avformatName); - io::path_t swscalePath = dir.appendingComponent(swscaleName); - io::path_t swresamplePath = dir.appendingComponent(swresampleName); - if (io::FileInfo::exists(avutilPath) && io::FileInfo::exists(avcodecPath) - && io::FileInfo::exists(avformatPath) && io::FileInfo::exists(swscalePath) - && io::FileInfo::exists(swresamplePath)) { - result.avUtilPath = avutilPath; - result.avCodecPath = avcodecPath; - result.avFormatPath = avformatPath; - result.swScalePath = swscalePath; - result.swResamplePath = swresamplePath; - return result; - } + io::path_t avutilPath = searchDir.appendingComponent(avutilName); + io::path_t avcodecPath = searchDir.appendingComponent(avcodecName); + io::path_t avformatPath = searchDir.appendingComponent(avformatName); + io::path_t swscalePath = searchDir.appendingComponent(swscaleName); + io::path_t swresamplePath = searchDir.appendingComponent(swresampleName); + if (io::FileInfo::exists(avutilPath) && io::FileInfo::exists(avcodecPath) + && io::FileInfo::exists(avformatPath) && io::FileInfo::exists(swscalePath) + && io::FileInfo::exists(swresamplePath)) { + result.avUtilPath = avutilPath; + result.avCodecPath = avcodecPath; + result.avFormatPath = avformatPath; + result.swScalePath = swscalePath; + result.swResamplePath = swresamplePath; + return result; } return result; @@ -163,10 +161,12 @@ FFmpegLibPaths findLibraryPaths(const io::path_t& configPath) searchPaths.push_back(p); } - for (const auto& [ffmpegVer, _] : FFMPEG_COMPONENTS_VERSIONS) { - result = libraryPathsForVersion(ffmpegVer, searchPaths); - if (!result.avFormatPath.empty()) { - return result; + for (const io::path_t& path : searchPaths) { + for (const auto& [ffmpegVer, _] : FFMPEG_COMPONENTS_VERSIONS) { + result = libraryPathsForVersion(ffmpegVer, path); + if (!result.avFormatPath.empty()) { + return result; + } } } diff --git a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp index 90f15caad33a0..591749e117e84 100644 --- a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp +++ b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp @@ -167,9 +167,11 @@ void FoldersPreferencesModel::setupConnections() }); videoEncoderResolver()->loadedFFmpegChanged().onNotify(this, [this]() { + emit ffmpegVersionChanged(); emit ffmpegDirChanged(); }); + emit ffmpegVersionChanged(); emit ffmpegDirChanged(); } From 6c3aca5705ee0977a5f06efbf18fa758ce39b726 Mon Sep 17 00:00:00 2001 From: Eism Date: Fri, 13 Mar 2026 12:38:18 +0200 Subject: [PATCH 27/52] added ffmpeg 6 --- src/framework/media/CMakeLists.txt | 6 + .../internal/ffmpeg/v6/ffmpeglibhandler.cpp | 229 ++++++++ .../internal/ffmpeg/v6/ffmpeglibhandler.h | 117 ++++ .../media/internal/ffmpeg/v6/videoencoder.cpp | 512 ++++++++++++++++++ .../media/internal/ffmpeg/v6/videoencoder.h | 52 ++ .../media/internal/videoencoderresolver.cpp | 20 + 6 files changed, 936 insertions(+) create mode 100644 src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp create mode 100644 src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h create mode 100644 src/framework/media/internal/ffmpeg/v6/videoencoder.cpp create mode 100644 src/framework/media/internal/ffmpeg/v6/videoencoder.h diff --git a/src/framework/media/CMakeLists.txt b/src/framework/media/CMakeLists.txt index d23b44f9b5f74..a790e2371d143 100644 --- a/src/framework/media/CMakeLists.txt +++ b/src/framework/media/CMakeLists.txt @@ -45,12 +45,18 @@ target_sources(muse_media PRIVATE internal/ffmpeg/v7/ffmpeglibhandler.h internal/ffmpeg/v7/videoencoder.cpp internal/ffmpeg/v7/videoencoder.h + + internal/ffmpeg/v6/ffmpeglibhandler.cpp + internal/ffmpeg/v6/ffmpeglibhandler.h + internal/ffmpeg/v6/videoencoder.cpp + internal/ffmpeg/v6/videoencoder.h ) target_include_directories(muse_media PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v8 ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v7 + ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v6 ) set(MODULE_USE_PCH OFF) diff --git a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp new file mode 100644 index 0000000000000..5d8f83095b75e --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp @@ -0,0 +1,229 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "ffmpeglibhandler.h" + +#if !defined(Q_OS_WIN) +#include +#endif + +#include "io/fileinfo.h" +#include "global/dlib.h" + +#include "log.h" + +namespace muse::media::ffmpeg::v6 { +#define RESOLVE_FROM(lib, name) do { \ + name = reinterpret_cast(getSymbol(lib, #name)); \ + if (!name) { LOGW() << "FFmpeg: missing symbol " #name; return false; } \ +} while (0) + +void* FFmpegLibHandler::getSymbol(void* lib, const char* name) const +{ + if (!lib) { + return nullptr; + } + void* sym = muse::getLibFunc(lib, name); + if (!sym) { +#if !defined(Q_OS_WIN) + sym = dlsym(RTLD_DEFAULT, name); +#endif + } + return sym; +} + +bool FFmpegLibHandler::loadApi() +{ + if (!m_avUtilLibrary || !m_avCodecLibrary || !m_avFormatLibrary || !m_swsScaleLibrary || !m_swResampleLibrary) { + return false; + } + + clearFunctions(); + + // libavutil + RESOLVE_FROM(m_avUtilLibrary, av_free); + RESOLVE_FROM(m_avUtilLibrary, av_freep); + RESOLVE_FROM(m_avUtilLibrary, av_rescale_q); + RESOLVE_FROM(m_avUtilLibrary, av_image_fill_arrays); + RESOLVE_FROM(m_avUtilLibrary, av_image_get_buffer_size); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set_pixel_fmt); + RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); + RESOLVE_FROM(m_avUtilLibrary, av_frame_free); + + // libavformat + RESOLVE_FROM(m_avFormatLibrary, av_guess_format); + RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); + RESOLVE_FROM(m_avFormatLibrary, av_interleaved_write_frame); + RESOLVE_FROM(m_avFormatLibrary, av_read_frame); + RESOLVE_FROM(m_avFormatLibrary, avio_open); + RESOLVE_FROM(m_avFormatLibrary, avio_close); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avformat_new_stream); + RESOLVE_FROM(m_avFormatLibrary, avformat_write_header); + RESOLVE_FROM(m_avFormatLibrary, avformat_open_input); + RESOLVE_FROM(m_avFormatLibrary, avformat_find_stream_info); + RESOLVE_FROM(m_avFormatLibrary, avformat_close_input); + RESOLVE_FROM(m_avFormatLibrary, avformat_free_context); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_output_context2); + + // libavcodec + RESOLVE_FROM(m_avCodecLibrary, av_packet_alloc); + RESOLVE_FROM(m_avCodecLibrary, av_packet_free); + RESOLVE_FROM(m_avCodecLibrary, av_packet_unref); + RESOLVE_FROM(m_avCodecLibrary, av_packet_rescale_ts); + RESOLVE_FROM(m_avCodecLibrary, avcodec_alloc_context3); + RESOLVE_FROM(m_avCodecLibrary, avcodec_find_encoder); + RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_open2); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_to_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy); + RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame); + RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet); + + // libswscale + RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); + RESOLVE_FROM(m_swsScaleLibrary, sws_scale); + + return functionsValid(); +} + +bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, + const io::path_t& swScalePath, const io::path_t& swResamplePath) +{ + unload(); + + // Load avutil first, then swresample, swscale, avcodec, avformat (dependency order) + if (!tryLoadPath(m_avUtilLibrary, avUtilPath) + || !tryLoadPath(m_swResampleLibrary, swResamplePath) + || !tryLoadPath(m_swsScaleLibrary, swScalePath) + || !tryLoadPath(m_avCodecLibrary, avCodecPath) + || !tryLoadPath(m_avFormatLibrary, avFormatPath)) { + return false; + } + + LOGI() << "FFmpeg loaded: avutil=" << avUtilPath << ", avcodec=" << avCodecPath << ", avformat=" << avFormatPath + << ", swscale=" << swScalePath << ", swresample=" << swResamplePath; + + return true; +} + +void FFmpegLibHandler::unload() +{ + closeLib(m_avFormatLibrary); + closeLib(m_swResampleLibrary); + closeLib(m_swsScaleLibrary); + closeLib(m_avCodecLibrary); + closeLib(m_avUtilLibrary); + + clearFunctions(); + m_version = 0; + m_dir = io::path_t(); +} + +void FFmpegLibHandler::closeLib(void*& lib) +{ + if (lib) { + muse::closeLib(lib); + lib = nullptr; + } +} + +bool FFmpegLibHandler::tryLoadPath(void*& lib, const io::path_t& fullPath) +{ + if (!io::FileInfo::exists(fullPath)) { + return false; + } + + void* loaded = muse::loadLib(fullPath); + if (loaded) { + lib = loaded; + return true; + } + + return false; +} + +bool FFmpegLibHandler::functionsValid() const +{ + return av_free && av_freep && av_rescale_q + && av_image_fill_arrays && av_image_get_buffer_size + && av_opt_set && av_opt_set_int && av_opt_set_pixel_fmt + && av_guess_format && avformat_alloc_context && avformat_new_stream + && avformat_write_header && av_write_trailer + && avio_open && avio_close && av_interleaved_write_frame + && avformat_open_input && avformat_find_stream_info + && avformat_close_input && avformat_free_context + && avformat_alloc_output_context2 && av_read_frame + && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context + && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_to_context && avcodec_parameters_copy + && avcodec_send_frame && avcodec_receive_packet + && av_frame_alloc && av_frame_free + && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts + && sws_getCachedContext && sws_scale; +} + +void FFmpegLibHandler::clearFunctions() +{ + av_free = nullptr; + av_freep = nullptr; + av_rescale_q = nullptr; + av_image_fill_arrays = nullptr; + av_image_get_buffer_size = nullptr; + av_opt_set = nullptr; + av_opt_set_int = nullptr; + av_opt_set_pixel_fmt = nullptr; + av_guess_format = nullptr; + avformat_alloc_context = nullptr; + avformat_new_stream = nullptr; + avformat_write_header = nullptr; + av_write_trailer = nullptr; + avio_open = nullptr; + avio_close = nullptr; + av_interleaved_write_frame = nullptr; + avformat_open_input = nullptr; + avformat_find_stream_info = nullptr; + avformat_close_input = nullptr; + avformat_free_context = nullptr; + avformat_alloc_output_context2 = nullptr; + av_read_frame = nullptr; + avcodec_alloc_context3 = nullptr; + avcodec_find_encoder = nullptr; + avcodec_free_context = nullptr; + avcodec_open2 = nullptr; + avcodec_parameters_from_context = nullptr; + avcodec_parameters_to_context = nullptr; + avcodec_parameters_copy = nullptr; + avcodec_send_frame = nullptr; + avcodec_receive_packet = nullptr; + av_frame_alloc = nullptr; + av_frame_free = nullptr; + av_packet_alloc = nullptr; + av_packet_free = nullptr; + av_packet_unref = nullptr; + av_packet_rescale_ts = nullptr; + sws_getCachedContext = nullptr; + sws_scale = nullptr; +} +} diff --git a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h new file mode 100644 index 0000000000000..b48495820135f --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h @@ -0,0 +1,117 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +extern "C" { +#include "thirdparty/ffmpeg/v6/libavcodec/avcodec.h" +#include "thirdparty/ffmpeg/v6/libavformat/avformat.h" +#include "thirdparty/ffmpeg/v6/libswscale/swscale.h" +} + +#include "io/path.h" + +namespace muse::media::ffmpeg::v6 { +class FFmpegLibHandler +{ +public: + FFmpegLibHandler() = default; + + bool loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, const io::path_t& swScalePath, + const io::path_t& swResamplePath); + bool loadApi(); + void unload(); + + int version() const { return m_version; } + void setVersion(int version) { m_version = version; } + + io::path_t dir() const { return m_dir; } + void setDir(const io::path_t& dir) { m_dir = dir; } + + // libavutil + void (*av_free)(void* ptr) = nullptr; + void (*av_freep)(void* ptr) = nullptr; + int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; + int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, + int align) = nullptr; + int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; + int (*av_opt_set)(void* obj, const char* name, const char* val, int search_flags) = nullptr; + int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; + int (*av_opt_set_pixel_fmt)(void* obj, const char* name, AVPixelFormat fmt, int search_flags) = nullptr; + + // libavformat + const AVOutputFormat*(*av_guess_format)(const char* short_name, const char* filename, const char* mime_type) = nullptr; + AVFormatContext*(*avformat_alloc_context)(void) = nullptr; + AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; + int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; + int (*av_write_trailer)(AVFormatContext* s) = nullptr; + int (*avio_open)(AVIOContext** s, const char* url, int flags) = nullptr; + int (*avio_close)(AVIOContext* s) = nullptr; + int (*av_interleaved_write_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + int (*avformat_open_input)(AVFormatContext** ctx, const char* url, const AVInputFormat* fmt, AVDictionary** options) = nullptr; + int (*avformat_find_stream_info)(AVFormatContext* ic, AVDictionary** options) = nullptr; + void (*avformat_close_input)(AVFormatContext** s) = nullptr; + void (*avformat_free_context)(AVFormatContext* s) = nullptr; + int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, const char* format_name, + const char* filename) = nullptr; + int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + + // libavcodec + AVCodecContext*(*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; + const AVCodec*(*avcodec_find_encoder)(AVCodecID id) = nullptr; + void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; + int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; + int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; + int (*avcodec_parameters_to_context)(AVCodecContext* codec, const AVCodecParameters* par) = nullptr; + int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; + int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; + int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; + AVFrame*(*av_frame_alloc)(void) = nullptr; + void (*av_frame_free)(AVFrame** frame) = nullptr; + AVPacket*(*av_packet_alloc)(void) = nullptr; + void (*av_packet_free)(AVPacket** pkt) = nullptr; + void (*av_packet_unref)(AVPacket* pkt) = nullptr; + void (*av_packet_rescale_ts)(AVPacket* pkt, AVRational tb_src, AVRational tb_dst) = nullptr; + + // libswscale + SwsContext*(*sws_getCachedContext)(SwsContext* context, int srcW, int srcH, AVPixelFormat srcFormat, int dstW, int dstH, + AVPixelFormat dstFormat, int flags, SwsFilter* srcFilter, SwsFilter* dstFilter, + const double* param) = nullptr; + int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t* const dst[], const int dstStride[]) = nullptr; + +private : void* getSymbol(void* lib, const char* name) const; + bool tryLoadPath(void*& lib, const io::path_t& fullPath); + void closeLib(void*& lib); + void clearFunctions(); + bool functionsValid() const; + + void* m_avUtilLibrary = nullptr; + void* m_avCodecLibrary = nullptr; + void* m_avFormatLibrary = nullptr; + void* m_swsScaleLibrary = nullptr; + void* m_swResampleLibrary = nullptr; + + int m_version = 0; + io::path_t m_dir; +}; +} diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp new file mode 100644 index 0000000000000..d471359a13b57 --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp @@ -0,0 +1,512 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "videoencoder.h" + +#include "io/file.h" +#include "defer.h" +#include "log.h" + +namespace muse::media::ffmpeg::v6 { +struct FFmpeg { + int width = 0; + int height = 0; + unsigned int ptsCounter = 0; + + // FFmpeg stuff + AVFormatContext* formatCtx = nullptr; + AVStream* videoStream = nullptr; + AVCodecContext* codecCtx = nullptr; + const AVCodec* codec = nullptr; + // Frame data + AVFrame* ppicture = nullptr; + uint8_t* picture_buf = nullptr; + // Conversion + SwsContext* img_convert_ctx = nullptr; + // Packet + AVPacket* pkt; + + bool opened = false; + bool finished = false; +}; + +VideoEncoder::VideoEncoder(const std::shared_ptr& handler) + : m_ffmpegHandler(handler) +{ + m_ffmpeg = new FFmpeg(); +} + +VideoEncoder::~VideoEncoder() +{ + delete m_ffmpeg; +} + +bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) +{ + m_ffmpeg->ptsCounter = 0; + + m_ffmpeg->width = width; + m_ffmpeg->height = height; + + if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, "mp4", fileName.c_str()) < 0 + || !m_ffmpeg->formatCtx) { + LOGE() << "failed to allocate output context"; + return false; + } + + // Add the video stream + m_ffmpeg->videoStream = m_ffmpegHandler->avformat_new_stream(m_ffmpeg->formatCtx, nullptr); + if (!m_ffmpeg->videoStream) { + LOGE() << "failed allocate stream"; + return false; + } + + m_ffmpeg->videoStream->time_base.den = fps; + m_ffmpeg->videoStream->time_base.num = 1; + + // find the video encoder + m_ffmpeg->codec = m_ffmpegHandler->avcodec_find_encoder(AV_CODEC_ID_H264); + if (!m_ffmpeg->codec) { + LOGE() << "not found codec"; + return false; + } + m_ffmpeg->codecCtx = m_ffmpegHandler->avcodec_alloc_context3(m_ffmpeg->codec); + if (m_ffmpeg->codecCtx == nullptr) { + LOGE() << "failed to allocate AV context"; + return false; + } + + m_ffmpeg->videoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + m_ffmpeg->videoStream->codecpar->codec_id = AV_CODEC_ID_H264; + m_ffmpeg->videoStream->codecpar->width = width; + m_ffmpeg->videoStream->codecpar->height = height; + m_ffmpeg->videoStream->codecpar->format = AV_PIX_FMT_YUV420P; + m_ffmpeg->videoStream->codecpar->bit_rate = bitrate; + + if (m_ffmpegHandler->avcodec_parameters_to_context(m_ffmpeg->codecCtx, m_ffmpeg->videoStream->codecpar) < 0) { + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + LOGE() << "failed to set codec parameters from stream"; + return false; + } + + m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; + m_ffmpeg->codecCtx->time_base.den = fps; + m_ffmpeg->codecCtx->time_base.num = 1; + m_ffmpeg->codecCtx->gop_size = gop; + m_ffmpeg->codecCtx->thread_count = 10; + m_ffmpeg->codecCtx->max_b_frames = 3; + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); + + m_ffmpeg->codecCtx->me_cmp = 1; + m_ffmpeg->codecCtx->me_range = 16; + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "hex", 1, 0); + + m_ffmpeg->codecCtx->qmin = 10; + m_ffmpeg->codecCtx->qmax = 51; + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "sc_threshold", 40, 0); + m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_LOOP_FILTER; + m_ffmpeg->codecCtx->me_subpel_quality = 5; + m_ffmpeg->codecCtx->i_quant_factor = 0.71; + m_ffmpeg->codecCtx->qcompress = 0.6; + m_ffmpeg->codecCtx->max_qdiff = 4; + + if (m_ffmpeg->formatCtx->oformat->flags & AVFMT_GLOBALHEADER) { + m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + } + + if (m_ffmpegHandler->avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, nullptr) < 0) { + LOGE() << "failed open codec"; + return false; + } + + // Copy codec params to stream AFTER open - codec adds extradata (SPS/PPS) during open + if (m_ffmpegHandler->avcodec_parameters_from_context(m_ffmpeg->videoStream->codecpar, m_ffmpeg->codecCtx) < 0) { + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + LOGE() << "failed to copy codec parameters to stream"; + return false; + } + + // Allocate the YUV frame + m_ffmpeg->ppicture = m_ffmpegHandler->av_frame_alloc(); + if (!m_ffmpeg->ppicture) { + LOGE() << "failed allocate frame"; + return false; + } + + m_ffmpeg->ppicture->width = width; + m_ffmpeg->ppicture->height = height; + m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; + + int size = m_ffmpegHandler->av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); + m_ffmpeg->picture_buf = new uint8_t[size]; + if (!m_ffmpeg->picture_buf) { + LOGE() << "failed allocate frame buf"; + m_ffmpegHandler->av_frame_free(&m_ffmpeg->ppicture); + return false; + } + + // Setup the planes + m_ffmpegHandler->av_image_fill_arrays(m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize, m_ffmpeg->picture_buf, + AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); + + if (m_ffmpegHandler->avio_open(&m_ffmpeg->formatCtx->pb, fileName.c_str(), AVIO_FLAG_WRITE) < 0) { + LOGE() << "failed open file: " << fileName; + return false; + } + + int ret = m_ffmpegHandler->avformat_write_header(m_ffmpeg->formatCtx, NULL); + if (ret < 0) { + LOGE() << "failed write AV header"; + return false; + } + + //av_dump_format(m_ffmpeg->formatCtx, 0, fileName.c_str(), 1); + + m_ffmpeg->opened = true; + m_outputPath = fileName; + + return true; +} + +void VideoEncoder::finishEncode() +{ + if (!m_ffmpeg->opened || m_ffmpeg->finished) { + return; + } + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, NULL); + if (ret < 0) { + LOGE() << "failed to flush encoder buffer"; + return; + } + + while (true) { + m_ffmpeg->pkt = m_ffmpegHandler->av_packet_alloc(); + int ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + break; + } else if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + LOGE() << "error during encoding"; + return; + } + + m_ffmpeg->pkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + + m_ffmpeg->ptsCounter++; + + ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return; + } + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + } + + m_ffmpegHandler->av_write_trailer(m_ffmpeg->formatCtx); + + if (m_ffmpeg->formatCtx->pb) { + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; + } + + m_ffmpeg->finished = true; +} + +void VideoEncoder::close() +{ + if (!m_ffmpeg->opened) { + return; + } + + if (!m_ffmpeg->finished) { + finishEncode(); + } + + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + + if (m_ffmpeg->picture_buf) { + delete[] m_ffmpeg->picture_buf; + m_ffmpeg->picture_buf = 0; + } + + if (m_ffmpeg->ppicture) { + m_ffmpegHandler->av_frame_free(&m_ffmpeg->ppicture); + m_ffmpeg->ppicture = 0; + } + + if (m_ffmpeg->formatCtx) { + if (m_ffmpeg->formatCtx->pb) { + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; + } + m_ffmpegHandler->avformat_free_context(m_ffmpeg->formatCtx); + m_ffmpeg->formatCtx = nullptr; + } + m_ffmpeg->opened = false; + m_ffmpeg->finished = false; + + m_outputPath = io::path_t(); +} + +bool VideoEncoder::encodeImage(const QImage& img) +{ + if (!m_ffmpeg->opened) { + return false; + } + + convertImage_sws(img); + + m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->codecCtx->frame_num, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); + if (ret < 0) { + return false; + } + + while (ret >= 0) { + m_ffmpeg->pkt = m_ffmpegHandler->av_packet_alloc(); + ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return true; + } else if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + LOGE() << "error during encoding"; + return false; + } + + m_ffmpeg->pkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + + m_ffmpeg->ptsCounter++; + + ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return false; + } + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + } + + return true; +} + +bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) +{ + if (m_outputPath.empty()) { + LOGE() << "addAudio: encoder was not opened or path not set"; + return false; + } + + const io::path_t videoPath = m_outputPath; + const io::path_t tmpPath = m_outputPath + ".tmp"; + + AVFormatContext* videoFmtCtx = nullptr; + AVFormatContext* audioFmtCtx = nullptr; + AVFormatContext* outputFmtCtx = nullptr; + + auto cleanup = [&]() { + if (videoFmtCtx) { + m_ffmpegHandler->avformat_close_input(&videoFmtCtx); + } + if (audioFmtCtx) { + m_ffmpegHandler->avformat_close_input(&audioFmtCtx); + } + if (outputFmtCtx) { + if (outputFmtCtx->pb) { + m_ffmpegHandler->avio_close(outputFmtCtx->pb); + } + m_ffmpegHandler->avformat_free_context(outputFmtCtx); + } + }; + + DEFER { + cleanup(); + }; + + if (m_ffmpegHandler->avformat_open_input(&videoFmtCtx, videoPath.c_str(), nullptr, nullptr) < 0) { + LOGE() << "addAudio: failed to open video input: " << videoPath; + return false; + } + if (m_ffmpegHandler->avformat_find_stream_info(videoFmtCtx, nullptr) < 0) { + LOGE() << "addAudio: failed to find video stream info"; + return false; + } + + if (m_ffmpegHandler->avformat_open_input(&audioFmtCtx, audioPath.c_str(), nullptr, nullptr) < 0) { + LOGE() << "addAudio: failed to open audio input: " << audioPath; + return false; + } + if (m_ffmpegHandler->avformat_find_stream_info(audioFmtCtx, nullptr) < 0) { + LOGE() << "addAudio: failed to find audio stream info"; + return false; + } + + if (m_ffmpegHandler->avformat_alloc_output_context2(&outputFmtCtx, nullptr, "mp4", tmpPath.c_str()) < 0 || !outputFmtCtx) { + LOGE() << "addAudio: failed to allocate output context"; + return false; + } + + int videoInIdx = -1; + int audioInIdx = -1; + int outVideoIdx = -1; + int outAudioIdx = -1; + + for (unsigned i = 0; i < videoFmtCtx->nb_streams; i++) { + if (videoFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + videoInIdx = static_cast(i); + AVStream* outStream = m_ffmpegHandler->avformat_new_stream(outputFmtCtx, nullptr); + if (!outStream) { + LOGE() << "addAudio: failed to create output video stream"; + return false; + } + m_ffmpegHandler->avcodec_parameters_copy(outStream->codecpar, videoFmtCtx->streams[i]->codecpar); + outStream->codecpar->codec_tag = 0; + outStream->time_base = videoFmtCtx->streams[i]->time_base; + outVideoIdx = outStream->index; + break; + } + } + + for (unsigned i = 0; i < audioFmtCtx->nb_streams; i++) { + if (audioFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + audioInIdx = static_cast(i); + AVStream* outStream = m_ffmpegHandler->avformat_new_stream(outputFmtCtx, nullptr); + if (!outStream) { + LOGE() << "addAudio: failed to create output audio stream"; + return false; + } + m_ffmpegHandler->avcodec_parameters_copy(outStream->codecpar, audioFmtCtx->streams[i]->codecpar); + outStream->codecpar->codec_tag = 0; + outStream->time_base = audioFmtCtx->streams[i]->time_base; + outAudioIdx = outStream->index; + break; + } + } + + if (videoInIdx < 0 || audioInIdx < 0) { + LOGE() << "addAudio: could not find video or audio stream"; + return false; + } + + if (m_ffmpegHandler->avio_open(&outputFmtCtx->pb, tmpPath.c_str(), AVIO_FLAG_WRITE) < 0) { + LOGE() << "addAudio: failed to open output file: " << tmpPath; + return false; + } + + if (m_ffmpegHandler->avformat_write_header(outputFmtCtx, nullptr) < 0) { + LOGE() << "addAudio: failed to write header"; + return false; + } + + int64_t audioOffsetPts = 0; + { + AVStream* audioOutStream = outputFmtCtx->streams[outAudioIdx]; + audioOffsetPts = static_cast(audioOffsetSec * audioOutStream->time_base.den + / audioOutStream->time_base.num); + } + + AVPacket* pkt = m_ffmpegHandler->av_packet_alloc(); + + while (m_ffmpegHandler->av_read_frame(videoFmtCtx, pkt) >= 0) { + if (pkt->stream_index == videoInIdx) { + pkt->stream_index = outVideoIdx; + m_ffmpegHandler->av_packet_rescale_ts(pkt, videoFmtCtx->streams[videoInIdx]->time_base, + outputFmtCtx->streams[outVideoIdx]->time_base); + pkt->pos = -1; + m_ffmpegHandler->av_interleaved_write_frame(outputFmtCtx, pkt); + } + m_ffmpegHandler->av_packet_unref(pkt); + } + + while (m_ffmpegHandler->av_read_frame(audioFmtCtx, pkt) >= 0) { + if (pkt->stream_index == audioInIdx) { + pkt->stream_index = outAudioIdx; + m_ffmpegHandler->av_packet_rescale_ts(pkt, audioFmtCtx->streams[audioInIdx]->time_base, + outputFmtCtx->streams[outAudioIdx]->time_base); + pkt->pts += audioOffsetPts; + pkt->dts += audioOffsetPts; + pkt->pos = -1; + m_ffmpegHandler->av_interleaved_write_frame(outputFmtCtx, pkt); + } + m_ffmpegHandler->av_packet_unref(pkt); + } + + m_ffmpegHandler->av_packet_free(&pkt); + m_ffmpegHandler->av_write_trailer(outputFmtCtx); + + if (!io::File::copy(tmpPath, videoPath, true)) { + LOGE() << "addAudio: failed to replace with muxed file"; + return false; + } + + io::File::remove(tmpPath); + + return true; +} + +bool VideoEncoder::convertImage_sws(const QImage& img) +{ + // Check if the image matches the size + if (img.width() != m_ffmpeg->width || img.height() != m_ffmpeg->height) { + LOGE() << "wrong image size!"; + return false; + } + + if (img.format() != QImage::Format_RGB32 && img.format() != QImage::Format_ARGB32) { + LOGE() << "wrong image format"; + return false; + } + + m_ffmpeg->img_convert_ctx = m_ffmpegHandler->sws_getCachedContext(m_ffmpeg->img_convert_ctx, m_ffmpeg->width, m_ffmpeg->height, + AV_PIX_FMT_BGRA, + m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, + NULL, NULL, NULL); + + if (!m_ffmpeg->img_convert_ctx) { + LOGE() << "failed initialize the conversion context"; + return false; + } + + uint8_t* srcplanes[3]; + srcplanes[0] = (uint8_t*)img.bits(); + srcplanes[1] = 0; + srcplanes[2] = 0; + + int srcstride[3]; + srcstride[0] = img.bytesPerLine(); + srcstride[1] = 0; + srcstride[2 ]= 0; + + m_ffmpegHandler->sws_scale(m_ffmpeg->img_convert_ctx, srcplanes, srcstride, 0, m_ffmpeg->height, m_ffmpeg->ppicture->data, + m_ffmpeg->ppicture->linesize); + + return true; +} +} diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.h b/src/framework/media/internal/ffmpeg/v6/videoencoder.h new file mode 100644 index 0000000000000..ed6bdf6d69aa1 --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.h @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "media/ivideoencoder.h" + +#include "ffmpeglibhandler.h" + +namespace muse::media::ffmpeg::v6 { +struct FFmpeg; +class VideoEncoder : public IVideoEncoder +{ +public: + explicit VideoEncoder(const std::shared_ptr& handler); + ~VideoEncoder() override; + + bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; + void close() override; + + bool encodeImage(const QImage& img) override; + void finishEncode() override; + + bool addAudio(const muse::io::path_t& audioPath, double audioOffsetSec) override; + +private: + bool convertImage_sws(const QImage& img); + + std::shared_ptr m_ffmpegHandler = nullptr; + FFmpeg* m_ffmpeg = nullptr; + muse::io::path_t m_outputPath; +}; +} diff --git a/src/framework/media/internal/videoencoderresolver.cpp b/src/framework/media/internal/videoencoderresolver.cpp index f324cbd0fbfff..2467ebecf3bd5 100644 --- a/src/framework/media/internal/videoencoderresolver.cpp +++ b/src/framework/media/internal/videoencoderresolver.cpp @@ -28,6 +28,9 @@ #include "internal/ffmpeg/v7/ffmpeglibhandler.h" #include "internal/ffmpeg/v7/videoencoder.h" +#include "internal/ffmpeg/v6/ffmpeglibhandler.h" +#include "internal/ffmpeg/v6/videoencoder.h" + #include "io/path.h" #include "log.h" @@ -131,6 +134,23 @@ VideoEncoderResolver::EncoderInfo VideoEncoderResolver::makeEncoder(const FFmpeg LOGW() << "FFmpeg libraries not found"; } } break; + case FFMPEG_V6: { + auto ffmpegLibHandler = std::make_shared(); + if (ffmpegLibHandler->loadLib(ffmpegLibsPaths.avUtilPath, ffmpegLibsPaths.avCodecPath, ffmpegLibsPaths.avFormatPath, + ffmpegLibsPaths.swScalePath, ffmpegLibsPaths.swResamplePath) + && ffmpegLibHandler->loadApi()) { + ffmpegLibHandler->setVersion(version); + ffmpegLibHandler->setDir(io::dirpath(ffmpegLibsPaths.avFormatPath)); + + LOGD() << "FFmpeg loaded, version: " << ffmpegLibHandler->version(); + + result.encoder = std::make_shared(ffmpegLibHandler); + result.ffmpegLibsDir = ffmpegLibHandler->dir(); + result.ffmpegVersion = ffmpegLibHandler->version(); + } else { + LOGW() << "FFmpeg libraries not found"; + } + } break; default: break; } From e2276acd8268d641733a4d546bb72ccc108974e7 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 16 Mar 2026 11:31:36 +0200 Subject: [PATCH 28/52] isolated ffmpeg include directories for different versions Moved FFmpeg include paths from target-wide to specific source files to prevent header version conflicts. --- src/framework/media/CMakeLists.txt | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/framework/media/CMakeLists.txt b/src/framework/media/CMakeLists.txt index a790e2371d143..91c8a2ecb6077 100644 --- a/src/framework/media/CMakeLists.txt +++ b/src/framework/media/CMakeLists.txt @@ -52,11 +52,22 @@ target_sources(muse_media PRIVATE internal/ffmpeg/v6/videoencoder.h ) -target_include_directories(muse_media - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v8 - ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v7 - ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v6 +set_source_files_properties( + internal/ffmpeg/v8/ffmpeglibhandler.cpp + internal/ffmpeg/v8/videoencoder.cpp + PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v8" +) + +set_source_files_properties( + internal/ffmpeg/v7/ffmpeglibhandler.cpp + internal/ffmpeg/v7/videoencoder.cpp + PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v7" +) + +set_source_files_properties( + internal/ffmpeg/v6/ffmpeglibhandler.cpp + internal/ffmpeg/v6/videoencoder.cpp + PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v6" ) set(MODULE_USE_PCH OFF) From 82f7d190e14be46219448a342d4aa9596ebb64e6 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 16 Mar 2026 11:39:04 +0200 Subject: [PATCH 29/52] added ffmpeg 5 copy of ffmpeg 6 --- src/framework/media/CMakeLists.txt | 11 + .../internal/ffmpeg/v5/ffmpeglibhandler.cpp | 229 ++++++++ .../internal/ffmpeg/v5/ffmpeglibhandler.h | 117 ++++ .../media/internal/ffmpeg/v5/videoencoder.cpp | 512 ++++++++++++++++++ .../media/internal/ffmpeg/v5/videoencoder.h | 52 ++ .../media/internal/videoencoderresolver.cpp | 20 + 6 files changed, 941 insertions(+) create mode 100644 src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp create mode 100644 src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h create mode 100644 src/framework/media/internal/ffmpeg/v5/videoencoder.cpp create mode 100644 src/framework/media/internal/ffmpeg/v5/videoencoder.h diff --git a/src/framework/media/CMakeLists.txt b/src/framework/media/CMakeLists.txt index 91c8a2ecb6077..7fc4a6b3350ec 100644 --- a/src/framework/media/CMakeLists.txt +++ b/src/framework/media/CMakeLists.txt @@ -50,6 +50,11 @@ target_sources(muse_media PRIVATE internal/ffmpeg/v6/ffmpeglibhandler.h internal/ffmpeg/v6/videoencoder.cpp internal/ffmpeg/v6/videoencoder.h + + internal/ffmpeg/v5/ffmpeglibhandler.cpp + internal/ffmpeg/v5/ffmpeglibhandler.h + internal/ffmpeg/v5/videoencoder.cpp + internal/ffmpeg/v5/videoencoder.h ) set_source_files_properties( @@ -70,5 +75,11 @@ set_source_files_properties( PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v6" ) +set_source_files_properties( + internal/ffmpeg/v5/ffmpeglibhandler.cpp + internal/ffmpeg/v5/videoencoder.cpp + PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v5" +) + set(MODULE_USE_PCH OFF) set(MODULE_USE_UNITY OFF) diff --git a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp new file mode 100644 index 0000000000000..5c07ac29b0210 --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp @@ -0,0 +1,229 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "ffmpeglibhandler.h" + +#if !defined(Q_OS_WIN) +#include +#endif + +#include "io/fileinfo.h" +#include "global/dlib.h" + +#include "log.h" + +namespace muse::media::ffmpeg::v5 { +#define RESOLVE_FROM(lib, name) do { \ + name = reinterpret_cast(getSymbol(lib, #name)); \ + if (!name) { LOGW() << "FFmpeg: missing symbol " #name; return false; } \ +} while (0) + +void* FFmpegLibHandler::getSymbol(void* lib, const char* name) const +{ + if (!lib) { + return nullptr; + } + void* sym = muse::getLibFunc(lib, name); + if (!sym) { +#if !defined(Q_OS_WIN) + sym = dlsym(RTLD_DEFAULT, name); +#endif + } + return sym; +} + +bool FFmpegLibHandler::loadApi() +{ + if (!m_avUtilLibrary || !m_avCodecLibrary || !m_avFormatLibrary || !m_swsScaleLibrary || !m_swResampleLibrary) { + return false; + } + + clearFunctions(); + + // libavutil + RESOLVE_FROM(m_avUtilLibrary, av_free); + RESOLVE_FROM(m_avUtilLibrary, av_freep); + RESOLVE_FROM(m_avUtilLibrary, av_rescale_q); + RESOLVE_FROM(m_avUtilLibrary, av_image_fill_arrays); + RESOLVE_FROM(m_avUtilLibrary, av_image_get_buffer_size); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set_pixel_fmt); + RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); + RESOLVE_FROM(m_avUtilLibrary, av_frame_free); + + // libavformat + RESOLVE_FROM(m_avFormatLibrary, av_guess_format); + RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); + RESOLVE_FROM(m_avFormatLibrary, av_interleaved_write_frame); + RESOLVE_FROM(m_avFormatLibrary, av_read_frame); + RESOLVE_FROM(m_avFormatLibrary, avio_open); + RESOLVE_FROM(m_avFormatLibrary, avio_close); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avformat_new_stream); + RESOLVE_FROM(m_avFormatLibrary, avformat_write_header); + RESOLVE_FROM(m_avFormatLibrary, avformat_open_input); + RESOLVE_FROM(m_avFormatLibrary, avformat_find_stream_info); + RESOLVE_FROM(m_avFormatLibrary, avformat_close_input); + RESOLVE_FROM(m_avFormatLibrary, avformat_free_context); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_output_context2); + + // libavcodec + RESOLVE_FROM(m_avCodecLibrary, av_packet_alloc); + RESOLVE_FROM(m_avCodecLibrary, av_packet_free); + RESOLVE_FROM(m_avCodecLibrary, av_packet_unref); + RESOLVE_FROM(m_avCodecLibrary, av_packet_rescale_ts); + RESOLVE_FROM(m_avCodecLibrary, avcodec_alloc_context3); + RESOLVE_FROM(m_avCodecLibrary, avcodec_find_encoder); + RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_open2); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_to_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy); + RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame); + RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet); + + // libswscale + RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); + RESOLVE_FROM(m_swsScaleLibrary, sws_scale); + + return functionsValid(); +} + +bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, + const io::path_t& swScalePath, const io::path_t& swResamplePath) +{ + unload(); + + // Load avutil first, then swresample, swscale, avcodec, avformat (dependency order) + if (!tryLoadPath(m_avUtilLibrary, avUtilPath) + || !tryLoadPath(m_swResampleLibrary, swResamplePath) + || !tryLoadPath(m_swsScaleLibrary, swScalePath) + || !tryLoadPath(m_avCodecLibrary, avCodecPath) + || !tryLoadPath(m_avFormatLibrary, avFormatPath)) { + return false; + } + + LOGI() << "FFmpeg loaded: avutil=" << avUtilPath << ", avcodec=" << avCodecPath << ", avformat=" << avFormatPath + << ", swscale=" << swScalePath << ", swresample=" << swResamplePath; + + return true; +} + +void FFmpegLibHandler::unload() +{ + closeLib(m_avFormatLibrary); + closeLib(m_swResampleLibrary); + closeLib(m_swsScaleLibrary); + closeLib(m_avCodecLibrary); + closeLib(m_avUtilLibrary); + + clearFunctions(); + m_version = 0; + m_dir = io::path_t(); +} + +void FFmpegLibHandler::closeLib(void*& lib) +{ + if (lib) { + muse::closeLib(lib); + lib = nullptr; + } +} + +bool FFmpegLibHandler::tryLoadPath(void*& lib, const io::path_t& fullPath) +{ + if (!io::FileInfo::exists(fullPath)) { + return false; + } + + void* loaded = muse::loadLib(fullPath); + if (loaded) { + lib = loaded; + return true; + } + + return false; +} + +bool FFmpegLibHandler::functionsValid() const +{ + return av_free && av_freep && av_rescale_q + && av_image_fill_arrays && av_image_get_buffer_size + && av_opt_set && av_opt_set_int && av_opt_set_pixel_fmt + && av_guess_format && avformat_alloc_context && avformat_new_stream + && avformat_write_header && av_write_trailer + && avio_open && avio_close && av_interleaved_write_frame + && avformat_open_input && avformat_find_stream_info + && avformat_close_input && avformat_free_context + && avformat_alloc_output_context2 && av_read_frame + && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context + && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_to_context && avcodec_parameters_copy + && avcodec_send_frame && avcodec_receive_packet + && av_frame_alloc && av_frame_free + && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts + && sws_getCachedContext && sws_scale; +} + +void FFmpegLibHandler::clearFunctions() +{ + av_free = nullptr; + av_freep = nullptr; + av_rescale_q = nullptr; + av_image_fill_arrays = nullptr; + av_image_get_buffer_size = nullptr; + av_opt_set = nullptr; + av_opt_set_int = nullptr; + av_opt_set_pixel_fmt = nullptr; + av_guess_format = nullptr; + avformat_alloc_context = nullptr; + avformat_new_stream = nullptr; + avformat_write_header = nullptr; + av_write_trailer = nullptr; + avio_open = nullptr; + avio_close = nullptr; + av_interleaved_write_frame = nullptr; + avformat_open_input = nullptr; + avformat_find_stream_info = nullptr; + avformat_close_input = nullptr; + avformat_free_context = nullptr; + avformat_alloc_output_context2 = nullptr; + av_read_frame = nullptr; + avcodec_alloc_context3 = nullptr; + avcodec_find_encoder = nullptr; + avcodec_free_context = nullptr; + avcodec_open2 = nullptr; + avcodec_parameters_from_context = nullptr; + avcodec_parameters_to_context = nullptr; + avcodec_parameters_copy = nullptr; + avcodec_send_frame = nullptr; + avcodec_receive_packet = nullptr; + av_frame_alloc = nullptr; + av_frame_free = nullptr; + av_packet_alloc = nullptr; + av_packet_free = nullptr; + av_packet_unref = nullptr; + av_packet_rescale_ts = nullptr; + sws_getCachedContext = nullptr; + sws_scale = nullptr; +} +} diff --git a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h new file mode 100644 index 0000000000000..7549992323f00 --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h @@ -0,0 +1,117 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +extern "C" { +#include "thirdparty/ffmpeg/v5/libavcodec/avcodec.h" +#include "thirdparty/ffmpeg/v5/libavformat/avformat.h" +#include "thirdparty/ffmpeg/v5/libswscale/swscale.h" +} + +#include "io/path.h" + +namespace muse::media::ffmpeg::v5 { +class FFmpegLibHandler +{ +public: + FFmpegLibHandler() = default; + + bool loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, const io::path_t& swScalePath, + const io::path_t& swResamplePath); + bool loadApi(); + void unload(); + + int version() const { return m_version; } + void setVersion(int version) { m_version = version; } + + io::path_t dir() const { return m_dir; } + void setDir(const io::path_t& dir) { m_dir = dir; } + + // libavutil + void (*av_free)(void* ptr) = nullptr; + void (*av_freep)(void* ptr) = nullptr; + int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; + int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, + int align) = nullptr; + int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; + int (*av_opt_set)(void* obj, const char* name, const char* val, int search_flags) = nullptr; + int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; + int (*av_opt_set_pixel_fmt)(void* obj, const char* name, AVPixelFormat fmt, int search_flags) = nullptr; + + // libavformat + const AVOutputFormat*(*av_guess_format)(const char* short_name, const char* filename, const char* mime_type) = nullptr; + AVFormatContext*(*avformat_alloc_context)(void) = nullptr; + AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; + int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; + int (*av_write_trailer)(AVFormatContext* s) = nullptr; + int (*avio_open)(AVIOContext** s, const char* url, int flags) = nullptr; + int (*avio_close)(AVIOContext* s) = nullptr; + int (*av_interleaved_write_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + int (*avformat_open_input)(AVFormatContext** ctx, const char* url, const AVInputFormat* fmt, AVDictionary** options) = nullptr; + int (*avformat_find_stream_info)(AVFormatContext* ic, AVDictionary** options) = nullptr; + void (*avformat_close_input)(AVFormatContext** s) = nullptr; + void (*avformat_free_context)(AVFormatContext* s) = nullptr; + int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, const char* format_name, + const char* filename) = nullptr; + int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + + // libavcodec + AVCodecContext*(*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; + const AVCodec*(*avcodec_find_encoder)(AVCodecID id) = nullptr; + void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; + int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; + int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; + int (*avcodec_parameters_to_context)(AVCodecContext* codec, const AVCodecParameters* par) = nullptr; + int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; + int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; + int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; + AVFrame*(*av_frame_alloc)(void) = nullptr; + void (*av_frame_free)(AVFrame** frame) = nullptr; + AVPacket*(*av_packet_alloc)(void) = nullptr; + void (*av_packet_free)(AVPacket** pkt) = nullptr; + void (*av_packet_unref)(AVPacket* pkt) = nullptr; + void (*av_packet_rescale_ts)(AVPacket* pkt, AVRational tb_src, AVRational tb_dst) = nullptr; + + // libswscale + SwsContext*(*sws_getCachedContext)(SwsContext* context, int srcW, int srcH, AVPixelFormat srcFormat, int dstW, int dstH, + AVPixelFormat dstFormat, int flags, SwsFilter* srcFilter, SwsFilter* dstFilter, + const double* param) = nullptr; + int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t* const dst[], const int dstStride[]) = nullptr; + +private : void* getSymbol(void* lib, const char* name) const; + bool tryLoadPath(void*& lib, const io::path_t& fullPath); + void closeLib(void*& lib); + void clearFunctions(); + bool functionsValid() const; + + void* m_avUtilLibrary = nullptr; + void* m_avCodecLibrary = nullptr; + void* m_avFormatLibrary = nullptr; + void* m_swsScaleLibrary = nullptr; + void* m_swResampleLibrary = nullptr; + + int m_version = 0; + io::path_t m_dir; +}; +} diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp new file mode 100644 index 0000000000000..f7c00b0f28124 --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp @@ -0,0 +1,512 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "videoencoder.h" + +#include "io/file.h" +#include "defer.h" +#include "log.h" + +namespace muse::media::ffmpeg::v5 { +struct FFmpeg { + int width = 0; + int height = 0; + unsigned int ptsCounter = 0; + + // FFmpeg stuff + AVFormatContext* formatCtx = nullptr; + AVStream* videoStream = nullptr; + AVCodecContext* codecCtx = nullptr; + const AVCodec* codec = nullptr; + // Frame data + AVFrame* ppicture = nullptr; + uint8_t* picture_buf = nullptr; + // Conversion + SwsContext* img_convert_ctx = nullptr; + // Packet + AVPacket* pkt; + + bool opened = false; + bool finished = false; +}; + +VideoEncoder::VideoEncoder(const std::shared_ptr& handler) + : m_ffmpegHandler(handler) +{ + m_ffmpeg = new FFmpeg(); +} + +VideoEncoder::~VideoEncoder() +{ + delete m_ffmpeg; +} + +bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) +{ + m_ffmpeg->ptsCounter = 0; + + m_ffmpeg->width = width; + m_ffmpeg->height = height; + + if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, "mp4", fileName.c_str()) < 0 + || !m_ffmpeg->formatCtx) { + LOGE() << "failed to allocate output context"; + return false; + } + + // Add the video stream + m_ffmpeg->videoStream = m_ffmpegHandler->avformat_new_stream(m_ffmpeg->formatCtx, nullptr); + if (!m_ffmpeg->videoStream) { + LOGE() << "failed allocate stream"; + return false; + } + + m_ffmpeg->videoStream->time_base.den = fps; + m_ffmpeg->videoStream->time_base.num = 1; + + // find the video encoder + m_ffmpeg->codec = m_ffmpegHandler->avcodec_find_encoder(AV_CODEC_ID_H264); + if (!m_ffmpeg->codec) { + LOGE() << "not found codec"; + return false; + } + m_ffmpeg->codecCtx = m_ffmpegHandler->avcodec_alloc_context3(m_ffmpeg->codec); + if (m_ffmpeg->codecCtx == nullptr) { + LOGE() << "failed to allocate AV context"; + return false; + } + + m_ffmpeg->videoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + m_ffmpeg->videoStream->codecpar->codec_id = AV_CODEC_ID_H264; + m_ffmpeg->videoStream->codecpar->width = width; + m_ffmpeg->videoStream->codecpar->height = height; + m_ffmpeg->videoStream->codecpar->format = AV_PIX_FMT_YUV420P; + m_ffmpeg->videoStream->codecpar->bit_rate = bitrate; + + if (m_ffmpegHandler->avcodec_parameters_to_context(m_ffmpeg->codecCtx, m_ffmpeg->videoStream->codecpar) < 0) { + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + LOGE() << "failed to set codec parameters from stream"; + return false; + } + + m_ffmpeg->codecCtx->profile = FF_PROFILE_H264_HIGH; + m_ffmpeg->codecCtx->time_base.den = fps; + m_ffmpeg->codecCtx->time_base.num = 1; + m_ffmpeg->codecCtx->gop_size = gop; + m_ffmpeg->codecCtx->thread_count = 10; + m_ffmpeg->codecCtx->max_b_frames = 3; + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); + + m_ffmpeg->codecCtx->me_cmp = 1; + m_ffmpeg->codecCtx->me_range = 16; + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "hex", 1, 0); + + m_ffmpeg->codecCtx->qmin = 10; + m_ffmpeg->codecCtx->qmax = 51; + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "sc_threshold", 40, 0); + m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_LOOP_FILTER; + m_ffmpeg->codecCtx->me_subpel_quality = 5; + m_ffmpeg->codecCtx->i_quant_factor = 0.71; + m_ffmpeg->codecCtx->qcompress = 0.6; + m_ffmpeg->codecCtx->max_qdiff = 4; + + if (m_ffmpeg->formatCtx->oformat->flags & AVFMT_GLOBALHEADER) { + m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + } + + if (m_ffmpegHandler->avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, nullptr) < 0) { + LOGE() << "failed open codec"; + return false; + } + + // Copy codec params to stream AFTER open - codec adds extradata (SPS/PPS) during open + if (m_ffmpegHandler->avcodec_parameters_from_context(m_ffmpeg->videoStream->codecpar, m_ffmpeg->codecCtx) < 0) { + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + LOGE() << "failed to copy codec parameters to stream"; + return false; + } + + // Allocate the YUV frame + m_ffmpeg->ppicture = m_ffmpegHandler->av_frame_alloc(); + if (!m_ffmpeg->ppicture) { + LOGE() << "failed allocate frame"; + return false; + } + + m_ffmpeg->ppicture->width = width; + m_ffmpeg->ppicture->height = height; + m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; + + int size = m_ffmpegHandler->av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); + m_ffmpeg->picture_buf = new uint8_t[size]; + if (!m_ffmpeg->picture_buf) { + LOGE() << "failed allocate frame buf"; + m_ffmpegHandler->av_frame_free(&m_ffmpeg->ppicture); + return false; + } + + // Setup the planes + m_ffmpegHandler->av_image_fill_arrays(m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize, m_ffmpeg->picture_buf, + AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); + + if (m_ffmpegHandler->avio_open(&m_ffmpeg->formatCtx->pb, fileName.c_str(), AVIO_FLAG_WRITE) < 0) { + LOGE() << "failed open file: " << fileName; + return false; + } + + int ret = m_ffmpegHandler->avformat_write_header(m_ffmpeg->formatCtx, NULL); + if (ret < 0) { + LOGE() << "failed write AV header"; + return false; + } + + //av_dump_format(m_ffmpeg->formatCtx, 0, fileName.c_str(), 1); + + m_ffmpeg->opened = true; + m_outputPath = fileName; + + return true; +} + +void VideoEncoder::finishEncode() +{ + if (!m_ffmpeg->opened || m_ffmpeg->finished) { + return; + } + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, NULL); + if (ret < 0) { + LOGE() << "failed to flush encoder buffer"; + return; + } + + while (true) { + m_ffmpeg->pkt = m_ffmpegHandler->av_packet_alloc(); + int ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + break; + } else if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + LOGE() << "error during encoding"; + return; + } + + m_ffmpeg->pkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + + m_ffmpeg->ptsCounter++; + + ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return; + } + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + } + + m_ffmpegHandler->av_write_trailer(m_ffmpeg->formatCtx); + + if (m_ffmpeg->formatCtx->pb) { + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; + } + + m_ffmpeg->finished = true; +} + +void VideoEncoder::close() +{ + if (!m_ffmpeg->opened) { + return; + } + + if (!m_ffmpeg->finished) { + finishEncode(); + } + + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + + if (m_ffmpeg->picture_buf) { + delete[] m_ffmpeg->picture_buf; + m_ffmpeg->picture_buf = 0; + } + + if (m_ffmpeg->ppicture) { + m_ffmpegHandler->av_frame_free(&m_ffmpeg->ppicture); + m_ffmpeg->ppicture = 0; + } + + if (m_ffmpeg->formatCtx) { + if (m_ffmpeg->formatCtx->pb) { + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; + } + m_ffmpegHandler->avformat_free_context(m_ffmpeg->formatCtx); + m_ffmpeg->formatCtx = nullptr; + } + m_ffmpeg->opened = false; + m_ffmpeg->finished = false; + + m_outputPath = io::path_t(); +} + +bool VideoEncoder::encodeImage(const QImage& img) +{ + if (!m_ffmpeg->opened) { + return false; + } + + convertImage_sws(img); + + m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->codecCtx->frame_number, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); + if (ret < 0) { + return false; + } + + while (ret >= 0) { + m_ffmpeg->pkt = m_ffmpegHandler->av_packet_alloc(); + ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return true; + } else if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + LOGE() << "error during encoding"; + return false; + } + + m_ffmpeg->pkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + + m_ffmpeg->ptsCounter++; + + ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return false; + } + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + } + + return true; +} + +bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) +{ + if (m_outputPath.empty()) { + LOGE() << "addAudio: encoder was not opened or path not set"; + return false; + } + + const io::path_t videoPath = m_outputPath; + const io::path_t tmpPath = m_outputPath + ".tmp"; + + AVFormatContext* videoFmtCtx = nullptr; + AVFormatContext* audioFmtCtx = nullptr; + AVFormatContext* outputFmtCtx = nullptr; + + auto cleanup = [&]() { + if (videoFmtCtx) { + m_ffmpegHandler->avformat_close_input(&videoFmtCtx); + } + if (audioFmtCtx) { + m_ffmpegHandler->avformat_close_input(&audioFmtCtx); + } + if (outputFmtCtx) { + if (outputFmtCtx->pb) { + m_ffmpegHandler->avio_close(outputFmtCtx->pb); + } + m_ffmpegHandler->avformat_free_context(outputFmtCtx); + } + }; + + DEFER { + cleanup(); + }; + + if (m_ffmpegHandler->avformat_open_input(&videoFmtCtx, videoPath.c_str(), nullptr, nullptr) < 0) { + LOGE() << "addAudio: failed to open video input: " << videoPath; + return false; + } + if (m_ffmpegHandler->avformat_find_stream_info(videoFmtCtx, nullptr) < 0) { + LOGE() << "addAudio: failed to find video stream info"; + return false; + } + + if (m_ffmpegHandler->avformat_open_input(&audioFmtCtx, audioPath.c_str(), nullptr, nullptr) < 0) { + LOGE() << "addAudio: failed to open audio input: " << audioPath; + return false; + } + if (m_ffmpegHandler->avformat_find_stream_info(audioFmtCtx, nullptr) < 0) { + LOGE() << "addAudio: failed to find audio stream info"; + return false; + } + + if (m_ffmpegHandler->avformat_alloc_output_context2(&outputFmtCtx, nullptr, "mp4", tmpPath.c_str()) < 0 || !outputFmtCtx) { + LOGE() << "addAudio: failed to allocate output context"; + return false; + } + + int videoInIdx = -1; + int audioInIdx = -1; + int outVideoIdx = -1; + int outAudioIdx = -1; + + for (unsigned i = 0; i < videoFmtCtx->nb_streams; i++) { + if (videoFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + videoInIdx = static_cast(i); + AVStream* outStream = m_ffmpegHandler->avformat_new_stream(outputFmtCtx, nullptr); + if (!outStream) { + LOGE() << "addAudio: failed to create output video stream"; + return false; + } + m_ffmpegHandler->avcodec_parameters_copy(outStream->codecpar, videoFmtCtx->streams[i]->codecpar); + outStream->codecpar->codec_tag = 0; + outStream->time_base = videoFmtCtx->streams[i]->time_base; + outVideoIdx = outStream->index; + break; + } + } + + for (unsigned i = 0; i < audioFmtCtx->nb_streams; i++) { + if (audioFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + audioInIdx = static_cast(i); + AVStream* outStream = m_ffmpegHandler->avformat_new_stream(outputFmtCtx, nullptr); + if (!outStream) { + LOGE() << "addAudio: failed to create output audio stream"; + return false; + } + m_ffmpegHandler->avcodec_parameters_copy(outStream->codecpar, audioFmtCtx->streams[i]->codecpar); + outStream->codecpar->codec_tag = 0; + outStream->time_base = audioFmtCtx->streams[i]->time_base; + outAudioIdx = outStream->index; + break; + } + } + + if (videoInIdx < 0 || audioInIdx < 0) { + LOGE() << "addAudio: could not find video or audio stream"; + return false; + } + + if (m_ffmpegHandler->avio_open(&outputFmtCtx->pb, tmpPath.c_str(), AVIO_FLAG_WRITE) < 0) { + LOGE() << "addAudio: failed to open output file: " << tmpPath; + return false; + } + + if (m_ffmpegHandler->avformat_write_header(outputFmtCtx, nullptr) < 0) { + LOGE() << "addAudio: failed to write header"; + return false; + } + + int64_t audioOffsetPts = 0; + { + AVStream* audioOutStream = outputFmtCtx->streams[outAudioIdx]; + audioOffsetPts = static_cast(audioOffsetSec * audioOutStream->time_base.den + / audioOutStream->time_base.num); + } + + AVPacket* pkt = m_ffmpegHandler->av_packet_alloc(); + + while (m_ffmpegHandler->av_read_frame(videoFmtCtx, pkt) >= 0) { + if (pkt->stream_index == videoInIdx) { + pkt->stream_index = outVideoIdx; + m_ffmpegHandler->av_packet_rescale_ts(pkt, videoFmtCtx->streams[videoInIdx]->time_base, + outputFmtCtx->streams[outVideoIdx]->time_base); + pkt->pos = -1; + m_ffmpegHandler->av_interleaved_write_frame(outputFmtCtx, pkt); + } + m_ffmpegHandler->av_packet_unref(pkt); + } + + while (m_ffmpegHandler->av_read_frame(audioFmtCtx, pkt) >= 0) { + if (pkt->stream_index == audioInIdx) { + pkt->stream_index = outAudioIdx; + m_ffmpegHandler->av_packet_rescale_ts(pkt, audioFmtCtx->streams[audioInIdx]->time_base, + outputFmtCtx->streams[outAudioIdx]->time_base); + pkt->pts += audioOffsetPts; + pkt->dts += audioOffsetPts; + pkt->pos = -1; + m_ffmpegHandler->av_interleaved_write_frame(outputFmtCtx, pkt); + } + m_ffmpegHandler->av_packet_unref(pkt); + } + + m_ffmpegHandler->av_packet_free(&pkt); + m_ffmpegHandler->av_write_trailer(outputFmtCtx); + + if (!io::File::copy(tmpPath, videoPath, true)) { + LOGE() << "addAudio: failed to replace with muxed file"; + return false; + } + + io::File::remove(tmpPath); + + return true; +} + +bool VideoEncoder::convertImage_sws(const QImage& img) +{ + // Check if the image matches the size + if (img.width() != m_ffmpeg->width || img.height() != m_ffmpeg->height) { + LOGE() << "wrong image size!"; + return false; + } + + if (img.format() != QImage::Format_RGB32 && img.format() != QImage::Format_ARGB32) { + LOGE() << "wrong image format"; + return false; + } + + m_ffmpeg->img_convert_ctx = m_ffmpegHandler->sws_getCachedContext(m_ffmpeg->img_convert_ctx, m_ffmpeg->width, m_ffmpeg->height, + AV_PIX_FMT_BGRA, + m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, + NULL, NULL, NULL); + + if (!m_ffmpeg->img_convert_ctx) { + LOGE() << "failed initialize the conversion context"; + return false; + } + + uint8_t* srcplanes[3]; + srcplanes[0] = (uint8_t*)img.bits(); + srcplanes[1] = 0; + srcplanes[2] = 0; + + int srcstride[3]; + srcstride[0] = img.bytesPerLine(); + srcstride[1] = 0; + srcstride[2 ]= 0; + + m_ffmpegHandler->sws_scale(m_ffmpeg->img_convert_ctx, srcplanes, srcstride, 0, m_ffmpeg->height, m_ffmpeg->ppicture->data, + m_ffmpeg->ppicture->linesize); + + return true; +} +} diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.h b/src/framework/media/internal/ffmpeg/v5/videoencoder.h new file mode 100644 index 0000000000000..1aedc4681daa2 --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.h @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "media/ivideoencoder.h" + +#include "ffmpeglibhandler.h" + +namespace muse::media::ffmpeg::v5 { +struct FFmpeg; +class VideoEncoder : public IVideoEncoder +{ +public: + explicit VideoEncoder(const std::shared_ptr& handler); + ~VideoEncoder() override; + + bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; + void close() override; + + bool encodeImage(const QImage& img) override; + void finishEncode() override; + + bool addAudio(const muse::io::path_t& audioPath, double audioOffsetSec) override; + +private: + bool convertImage_sws(const QImage& img); + + std::shared_ptr m_ffmpegHandler = nullptr; + FFmpeg* m_ffmpeg = nullptr; + muse::io::path_t m_outputPath; +}; +} diff --git a/src/framework/media/internal/videoencoderresolver.cpp b/src/framework/media/internal/videoencoderresolver.cpp index 2467ebecf3bd5..43f7e7b93919c 100644 --- a/src/framework/media/internal/videoencoderresolver.cpp +++ b/src/framework/media/internal/videoencoderresolver.cpp @@ -31,6 +31,9 @@ #include "internal/ffmpeg/v6/ffmpeglibhandler.h" #include "internal/ffmpeg/v6/videoencoder.h" +#include "internal/ffmpeg/v5/ffmpeglibhandler.h" +#include "internal/ffmpeg/v5/videoencoder.h" + #include "io/path.h" #include "log.h" @@ -151,6 +154,23 @@ VideoEncoderResolver::EncoderInfo VideoEncoderResolver::makeEncoder(const FFmpeg LOGW() << "FFmpeg libraries not found"; } } break; + case FFMPEG_V5: { + auto ffmpegLibHandler = std::make_shared(); + if (ffmpegLibHandler->loadLib(ffmpegLibsPaths.avUtilPath, ffmpegLibsPaths.avCodecPath, ffmpegLibsPaths.avFormatPath, + ffmpegLibsPaths.swScalePath, ffmpegLibsPaths.swResamplePath) + && ffmpegLibHandler->loadApi()) { + ffmpegLibHandler->setVersion(version); + ffmpegLibHandler->setDir(io::dirpath(ffmpegLibsPaths.avFormatPath)); + + LOGD() << "FFmpeg loaded, version: " << ffmpegLibHandler->version(); + + result.encoder = std::make_shared(ffmpegLibHandler); + result.ffmpegLibsDir = ffmpegLibHandler->dir(); + result.ffmpegVersion = ffmpegLibHandler->version(); + } else { + LOGW() << "FFmpeg libraries not found"; + } + } break; default: break; } From 9159ab152f552b65c024e666f11436d3127eeb81 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 16 Mar 2026 11:45:36 +0200 Subject: [PATCH 30/52] added ffmpeg 4 copy of ffmpeg 5 --- src/framework/media/CMakeLists.txt | 11 + .../internal/ffmpeg/v4/ffmpeglibhandler.cpp | 229 ++++++++ .../internal/ffmpeg/v4/ffmpeglibhandler.h | 117 ++++ .../media/internal/ffmpeg/v4/videoencoder.cpp | 512 ++++++++++++++++++ .../media/internal/ffmpeg/v4/videoencoder.h | 52 ++ .../media/internal/videoencoderresolver.cpp | 20 + 6 files changed, 941 insertions(+) create mode 100644 src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp create mode 100644 src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h create mode 100644 src/framework/media/internal/ffmpeg/v4/videoencoder.cpp create mode 100644 src/framework/media/internal/ffmpeg/v4/videoencoder.h diff --git a/src/framework/media/CMakeLists.txt b/src/framework/media/CMakeLists.txt index 7fc4a6b3350ec..ba23f8ff1728e 100644 --- a/src/framework/media/CMakeLists.txt +++ b/src/framework/media/CMakeLists.txt @@ -55,6 +55,11 @@ target_sources(muse_media PRIVATE internal/ffmpeg/v5/ffmpeglibhandler.h internal/ffmpeg/v5/videoencoder.cpp internal/ffmpeg/v5/videoencoder.h + + internal/ffmpeg/v4/ffmpeglibhandler.cpp + internal/ffmpeg/v4/ffmpeglibhandler.h + internal/ffmpeg/v4/videoencoder.cpp + internal/ffmpeg/v4/videoencoder.h ) set_source_files_properties( @@ -81,5 +86,11 @@ set_source_files_properties( PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v5" ) +set_source_files_properties( + internal/ffmpeg/v4/ffmpeglibhandler.cpp + internal/ffmpeg/v4/videoencoder.cpp + PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v4" +) + set(MODULE_USE_PCH OFF) set(MODULE_USE_UNITY OFF) diff --git a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp new file mode 100644 index 0000000000000..9cdd3dec9d3cb --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp @@ -0,0 +1,229 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "ffmpeglibhandler.h" + +#if !defined(Q_OS_WIN) +#include +#endif + +#include "io/fileinfo.h" +#include "global/dlib.h" + +#include "log.h" + +namespace muse::media::ffmpeg::v4 { +#define RESOLVE_FROM(lib, name) do { \ + name = reinterpret_cast(getSymbol(lib, #name)); \ + if (!name) { LOGW() << "FFmpeg: missing symbol " #name; return false; } \ +} while (0) + +void* FFmpegLibHandler::getSymbol(void* lib, const char* name) const +{ + if (!lib) { + return nullptr; + } + void* sym = muse::getLibFunc(lib, name); + if (!sym) { +#if !defined(Q_OS_WIN) + sym = dlsym(RTLD_DEFAULT, name); +#endif + } + return sym; +} + +bool FFmpegLibHandler::loadApi() +{ + if (!m_avUtilLibrary || !m_avCodecLibrary || !m_avFormatLibrary || !m_swsScaleLibrary || !m_swResampleLibrary) { + return false; + } + + clearFunctions(); + + // libavutil + RESOLVE_FROM(m_avUtilLibrary, av_free); + RESOLVE_FROM(m_avUtilLibrary, av_freep); + RESOLVE_FROM(m_avUtilLibrary, av_rescale_q); + RESOLVE_FROM(m_avUtilLibrary, av_image_fill_arrays); + RESOLVE_FROM(m_avUtilLibrary, av_image_get_buffer_size); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); + RESOLVE_FROM(m_avUtilLibrary, av_opt_set_pixel_fmt); + RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); + RESOLVE_FROM(m_avUtilLibrary, av_frame_free); + + // libavformat + RESOLVE_FROM(m_avFormatLibrary, av_guess_format); + RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); + RESOLVE_FROM(m_avFormatLibrary, av_interleaved_write_frame); + RESOLVE_FROM(m_avFormatLibrary, av_read_frame); + RESOLVE_FROM(m_avFormatLibrary, avio_open); + RESOLVE_FROM(m_avFormatLibrary, avio_close); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avformat_new_stream); + RESOLVE_FROM(m_avFormatLibrary, avformat_write_header); + RESOLVE_FROM(m_avFormatLibrary, avformat_open_input); + RESOLVE_FROM(m_avFormatLibrary, avformat_find_stream_info); + RESOLVE_FROM(m_avFormatLibrary, avformat_close_input); + RESOLVE_FROM(m_avFormatLibrary, avformat_free_context); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_output_context2); + + // libavcodec + RESOLVE_FROM(m_avCodecLibrary, av_packet_alloc); + RESOLVE_FROM(m_avCodecLibrary, av_packet_free); + RESOLVE_FROM(m_avCodecLibrary, av_packet_unref); + RESOLVE_FROM(m_avCodecLibrary, av_packet_rescale_ts); + RESOLVE_FROM(m_avCodecLibrary, avcodec_alloc_context3); + RESOLVE_FROM(m_avCodecLibrary, avcodec_find_encoder); + RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_open2); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_to_context); + RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy); + RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame); + RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet); + + // libswscale + RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); + RESOLVE_FROM(m_swsScaleLibrary, sws_scale); + + return functionsValid(); +} + +bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, + const io::path_t& swScalePath, const io::path_t& swResamplePath) +{ + unload(); + + // Load avutil first, then swresample, swscale, avcodec, avformat (dependency order) + if (!tryLoadPath(m_avUtilLibrary, avUtilPath) + || !tryLoadPath(m_swResampleLibrary, swResamplePath) + || !tryLoadPath(m_swsScaleLibrary, swScalePath) + || !tryLoadPath(m_avCodecLibrary, avCodecPath) + || !tryLoadPath(m_avFormatLibrary, avFormatPath)) { + return false; + } + + LOGI() << "FFmpeg loaded: avutil=" << avUtilPath << ", avcodec=" << avCodecPath << ", avformat=" << avFormatPath + << ", swscale=" << swScalePath << ", swresample=" << swResamplePath; + + return true; +} + +void FFmpegLibHandler::unload() +{ + closeLib(m_avFormatLibrary); + closeLib(m_swResampleLibrary); + closeLib(m_swsScaleLibrary); + closeLib(m_avCodecLibrary); + closeLib(m_avUtilLibrary); + + clearFunctions(); + m_version = 0; + m_dir = io::path_t(); +} + +void FFmpegLibHandler::closeLib(void*& lib) +{ + if (lib) { + muse::closeLib(lib); + lib = nullptr; + } +} + +bool FFmpegLibHandler::tryLoadPath(void*& lib, const io::path_t& fullPath) +{ + if (!io::FileInfo::exists(fullPath)) { + return false; + } + + void* loaded = muse::loadLib(fullPath); + if (loaded) { + lib = loaded; + return true; + } + + return false; +} + +bool FFmpegLibHandler::functionsValid() const +{ + return av_free && av_freep && av_rescale_q + && av_image_fill_arrays && av_image_get_buffer_size + && av_opt_set && av_opt_set_int && av_opt_set_pixel_fmt + && av_guess_format && avformat_alloc_context && avformat_new_stream + && avformat_write_header && av_write_trailer + && avio_open && avio_close && av_interleaved_write_frame + && avformat_open_input && avformat_find_stream_info + && avformat_close_input && avformat_free_context + && avformat_alloc_output_context2 && av_read_frame + && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context + && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_to_context && avcodec_parameters_copy + && avcodec_send_frame && avcodec_receive_packet + && av_frame_alloc && av_frame_free + && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts + && sws_getCachedContext && sws_scale; +} + +void FFmpegLibHandler::clearFunctions() +{ + av_free = nullptr; + av_freep = nullptr; + av_rescale_q = nullptr; + av_image_fill_arrays = nullptr; + av_image_get_buffer_size = nullptr; + av_opt_set = nullptr; + av_opt_set_int = nullptr; + av_opt_set_pixel_fmt = nullptr; + av_guess_format = nullptr; + avformat_alloc_context = nullptr; + avformat_new_stream = nullptr; + avformat_write_header = nullptr; + av_write_trailer = nullptr; + avio_open = nullptr; + avio_close = nullptr; + av_interleaved_write_frame = nullptr; + avformat_open_input = nullptr; + avformat_find_stream_info = nullptr; + avformat_close_input = nullptr; + avformat_free_context = nullptr; + avformat_alloc_output_context2 = nullptr; + av_read_frame = nullptr; + avcodec_alloc_context3 = nullptr; + avcodec_find_encoder = nullptr; + avcodec_free_context = nullptr; + avcodec_open2 = nullptr; + avcodec_parameters_from_context = nullptr; + avcodec_parameters_to_context = nullptr; + avcodec_parameters_copy = nullptr; + avcodec_send_frame = nullptr; + avcodec_receive_packet = nullptr; + av_frame_alloc = nullptr; + av_frame_free = nullptr; + av_packet_alloc = nullptr; + av_packet_free = nullptr; + av_packet_unref = nullptr; + av_packet_rescale_ts = nullptr; + sws_getCachedContext = nullptr; + sws_scale = nullptr; +} +} diff --git a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h new file mode 100644 index 0000000000000..69b62ce15adf6 --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h @@ -0,0 +1,117 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +extern "C" { +#include "thirdparty/ffmpeg/v4/libavcodec/avcodec.h" +#include "thirdparty/ffmpeg/v4/libavformat/avformat.h" +#include "thirdparty/ffmpeg/v4/libswscale/swscale.h" +} + +#include "io/path.h" + +namespace muse::media::ffmpeg::v4 { +class FFmpegLibHandler +{ +public: + FFmpegLibHandler() = default; + + bool loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath, const io::path_t& swScalePath, + const io::path_t& swResamplePath); + bool loadApi(); + void unload(); + + int version() const { return m_version; } + void setVersion(int version) { m_version = version; } + + io::path_t dir() const { return m_dir; } + void setDir(const io::path_t& dir) { m_dir = dir; } + + // libavutil + void (*av_free)(void* ptr) = nullptr; + void (*av_freep)(void* ptr) = nullptr; + int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; + int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, + int align) = nullptr; + int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; + int (*av_opt_set)(void* obj, const char* name, const char* val, int search_flags) = nullptr; + int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; + int (*av_opt_set_pixel_fmt)(void* obj, const char* name, AVPixelFormat fmt, int search_flags) = nullptr; + + // libavformat + const AVOutputFormat*(*av_guess_format)(const char* short_name, const char* filename, const char* mime_type) = nullptr; + AVFormatContext*(*avformat_alloc_context)(void) = nullptr; + AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; + int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; + int (*av_write_trailer)(AVFormatContext* s) = nullptr; + int (*avio_open)(AVIOContext** s, const char* url, int flags) = nullptr; + int (*avio_close)(AVIOContext* s) = nullptr; + int (*av_interleaved_write_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + int (*avformat_open_input)(AVFormatContext** ctx, const char* url, const AVInputFormat* fmt, AVDictionary** options) = nullptr; + int (*avformat_find_stream_info)(AVFormatContext* ic, AVDictionary** options) = nullptr; + void (*avformat_close_input)(AVFormatContext** s) = nullptr; + void (*avformat_free_context)(AVFormatContext* s) = nullptr; + int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, const char* format_name, + const char* filename) = nullptr; + int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + + // libavcodec + AVCodecContext*(*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; + const AVCodec*(*avcodec_find_encoder)(AVCodecID id) = nullptr; + void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; + int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; + int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; + int (*avcodec_parameters_to_context)(AVCodecContext* codec, const AVCodecParameters* par) = nullptr; + int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; + int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; + int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; + AVFrame*(*av_frame_alloc)(void) = nullptr; + void (*av_frame_free)(AVFrame** frame) = nullptr; + AVPacket*(*av_packet_alloc)(void) = nullptr; + void (*av_packet_free)(AVPacket** pkt) = nullptr; + void (*av_packet_unref)(AVPacket* pkt) = nullptr; + void (*av_packet_rescale_ts)(AVPacket* pkt, AVRational tb_src, AVRational tb_dst) = nullptr; + + // libswscale + SwsContext*(*sws_getCachedContext)(SwsContext* context, int srcW, int srcH, AVPixelFormat srcFormat, int dstW, int dstH, + AVPixelFormat dstFormat, int flags, SwsFilter* srcFilter, SwsFilter* dstFilter, + const double* param) = nullptr; + int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t* const dst[], const int dstStride[]) = nullptr; + +private : void* getSymbol(void* lib, const char* name) const; + bool tryLoadPath(void*& lib, const io::path_t& fullPath); + void closeLib(void*& lib); + void clearFunctions(); + bool functionsValid() const; + + void* m_avUtilLibrary = nullptr; + void* m_avCodecLibrary = nullptr; + void* m_avFormatLibrary = nullptr; + void* m_swsScaleLibrary = nullptr; + void* m_swResampleLibrary = nullptr; + + int m_version = 0; + io::path_t m_dir; +}; +} diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp new file mode 100644 index 0000000000000..d93d87f6b3933 --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp @@ -0,0 +1,512 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "videoencoder.h" + +#include "io/file.h" +#include "defer.h" +#include "log.h" + +namespace muse::media::ffmpeg::v4 { +struct FFmpeg { + int width = 0; + int height = 0; + unsigned int ptsCounter = 0; + + // FFmpeg stuff + AVFormatContext* formatCtx = nullptr; + AVStream* videoStream = nullptr; + AVCodecContext* codecCtx = nullptr; + const AVCodec* codec = nullptr; + // Frame data + AVFrame* ppicture = nullptr; + uint8_t* picture_buf = nullptr; + // Conversion + SwsContext* img_convert_ctx = nullptr; + // Packet + AVPacket* pkt; + + bool opened = false; + bool finished = false; +}; + +VideoEncoder::VideoEncoder(const std::shared_ptr& handler) + : m_ffmpegHandler(handler) +{ + m_ffmpeg = new FFmpeg(); +} + +VideoEncoder::~VideoEncoder() +{ + delete m_ffmpeg; +} + +bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) +{ + m_ffmpeg->ptsCounter = 0; + + m_ffmpeg->width = width; + m_ffmpeg->height = height; + + if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, "mp4", fileName.c_str()) < 0 + || !m_ffmpeg->formatCtx) { + LOGE() << "failed to allocate output context"; + return false; + } + + // Add the video stream + m_ffmpeg->videoStream = m_ffmpegHandler->avformat_new_stream(m_ffmpeg->formatCtx, nullptr); + if (!m_ffmpeg->videoStream) { + LOGE() << "failed allocate stream"; + return false; + } + + m_ffmpeg->videoStream->time_base.den = fps; + m_ffmpeg->videoStream->time_base.num = 1; + + // find the video encoder + m_ffmpeg->codec = m_ffmpegHandler->avcodec_find_encoder(AV_CODEC_ID_H264); + if (!m_ffmpeg->codec) { + LOGE() << "not found codec"; + return false; + } + m_ffmpeg->codecCtx = m_ffmpegHandler->avcodec_alloc_context3(m_ffmpeg->codec); + if (m_ffmpeg->codecCtx == nullptr) { + LOGE() << "failed to allocate AV context"; + return false; + } + + m_ffmpeg->videoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + m_ffmpeg->videoStream->codecpar->codec_id = AV_CODEC_ID_H264; + m_ffmpeg->videoStream->codecpar->width = width; + m_ffmpeg->videoStream->codecpar->height = height; + m_ffmpeg->videoStream->codecpar->format = AV_PIX_FMT_YUV420P; + m_ffmpeg->videoStream->codecpar->bit_rate = bitrate; + + if (m_ffmpegHandler->avcodec_parameters_to_context(m_ffmpeg->codecCtx, m_ffmpeg->videoStream->codecpar) < 0) { + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + LOGE() << "failed to set codec parameters from stream"; + return false; + } + + m_ffmpeg->codecCtx->profile = FF_PROFILE_H264_HIGH; + m_ffmpeg->codecCtx->time_base.den = fps; + m_ffmpeg->codecCtx->time_base.num = 1; + m_ffmpeg->codecCtx->gop_size = gop; + m_ffmpeg->codecCtx->thread_count = 10; + m_ffmpeg->codecCtx->max_b_frames = 3; + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); + + m_ffmpeg->codecCtx->me_cmp = 1; + m_ffmpeg->codecCtx->me_range = 16; + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "hex", 1, 0); + + m_ffmpeg->codecCtx->qmin = 10; + m_ffmpeg->codecCtx->qmax = 51; + m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "sc_threshold", 40, 0); + m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_LOOP_FILTER; + m_ffmpeg->codecCtx->me_subpel_quality = 5; + m_ffmpeg->codecCtx->i_quant_factor = 0.71; + m_ffmpeg->codecCtx->qcompress = 0.6; + m_ffmpeg->codecCtx->max_qdiff = 4; + + if (m_ffmpeg->formatCtx->oformat->flags & AVFMT_GLOBALHEADER) { + m_ffmpeg->codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + } + + if (m_ffmpegHandler->avcodec_open2(m_ffmpeg->codecCtx, m_ffmpeg->codec, nullptr) < 0) { + LOGE() << "failed open codec"; + return false; + } + + // Copy codec params to stream AFTER open - codec adds extradata (SPS/PPS) during open + if (m_ffmpegHandler->avcodec_parameters_from_context(m_ffmpeg->videoStream->codecpar, m_ffmpeg->codecCtx) < 0) { + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + LOGE() << "failed to copy codec parameters to stream"; + return false; + } + + // Allocate the YUV frame + m_ffmpeg->ppicture = m_ffmpegHandler->av_frame_alloc(); + if (!m_ffmpeg->ppicture) { + LOGE() << "failed allocate frame"; + return false; + } + + m_ffmpeg->ppicture->width = width; + m_ffmpeg->ppicture->height = height; + m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; + + int size = m_ffmpegHandler->av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); + m_ffmpeg->picture_buf = new uint8_t[size]; + if (!m_ffmpeg->picture_buf) { + LOGE() << "failed allocate frame buf"; + m_ffmpegHandler->av_frame_free(&m_ffmpeg->ppicture); + return false; + } + + // Setup the planes + m_ffmpegHandler->av_image_fill_arrays(m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize, m_ffmpeg->picture_buf, + AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); + + if (m_ffmpegHandler->avio_open(&m_ffmpeg->formatCtx->pb, fileName.c_str(), AVIO_FLAG_WRITE) < 0) { + LOGE() << "failed open file: " << fileName; + return false; + } + + int ret = m_ffmpegHandler->avformat_write_header(m_ffmpeg->formatCtx, NULL); + if (ret < 0) { + LOGE() << "failed write AV header"; + return false; + } + + //av_dump_format(m_ffmpeg->formatCtx, 0, fileName.c_str(), 1); + + m_ffmpeg->opened = true; + m_outputPath = fileName; + + return true; +} + +void VideoEncoder::finishEncode() +{ + if (!m_ffmpeg->opened || m_ffmpeg->finished) { + return; + } + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, NULL); + if (ret < 0) { + LOGE() << "failed to flush encoder buffer"; + return; + } + + while (true) { + m_ffmpeg->pkt = m_ffmpegHandler->av_packet_alloc(); + int ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + break; + } else if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + LOGE() << "error during encoding"; + return; + } + + m_ffmpeg->pkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + + m_ffmpeg->ptsCounter++; + + ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return; + } + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + } + + m_ffmpegHandler->av_write_trailer(m_ffmpeg->formatCtx); + + if (m_ffmpeg->formatCtx->pb) { + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; + } + + m_ffmpeg->finished = true; +} + +void VideoEncoder::close() +{ + if (!m_ffmpeg->opened) { + return; + } + + if (!m_ffmpeg->finished) { + finishEncode(); + } + + m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); + + if (m_ffmpeg->picture_buf) { + delete[] m_ffmpeg->picture_buf; + m_ffmpeg->picture_buf = 0; + } + + if (m_ffmpeg->ppicture) { + m_ffmpegHandler->av_frame_free(&m_ffmpeg->ppicture); + m_ffmpeg->ppicture = 0; + } + + if (m_ffmpeg->formatCtx) { + if (m_ffmpeg->formatCtx->pb) { + m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); + m_ffmpeg->formatCtx->pb = nullptr; + } + m_ffmpegHandler->avformat_free_context(m_ffmpeg->formatCtx); + m_ffmpeg->formatCtx = nullptr; + } + m_ffmpeg->opened = false; + m_ffmpeg->finished = false; + + m_outputPath = io::path_t(); +} + +bool VideoEncoder::encodeImage(const QImage& img) +{ + if (!m_ffmpeg->opened) { + return false; + } + + convertImage_sws(img); + + m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->codecCtx->frame_number, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); + if (ret < 0) { + return false; + } + + while (ret >= 0) { + m_ffmpeg->pkt = m_ffmpegHandler->av_packet_alloc(); + ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, m_ffmpeg->pkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return true; + } else if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + LOGE() << "error during encoding"; + return false; + } + + m_ffmpeg->pkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->pkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + + m_ffmpeg->ptsCounter++; + + ret = m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, m_ffmpeg->pkt); + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + return false; + } + m_ffmpegHandler->av_packet_free(&m_ffmpeg->pkt); + } + + return true; +} + +bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) +{ + if (m_outputPath.empty()) { + LOGE() << "addAudio: encoder was not opened or path not set"; + return false; + } + + const io::path_t videoPath = m_outputPath; + const io::path_t tmpPath = m_outputPath + ".tmp"; + + AVFormatContext* videoFmtCtx = nullptr; + AVFormatContext* audioFmtCtx = nullptr; + AVFormatContext* outputFmtCtx = nullptr; + + auto cleanup = [&]() { + if (videoFmtCtx) { + m_ffmpegHandler->avformat_close_input(&videoFmtCtx); + } + if (audioFmtCtx) { + m_ffmpegHandler->avformat_close_input(&audioFmtCtx); + } + if (outputFmtCtx) { + if (outputFmtCtx->pb) { + m_ffmpegHandler->avio_close(outputFmtCtx->pb); + } + m_ffmpegHandler->avformat_free_context(outputFmtCtx); + } + }; + + DEFER { + cleanup(); + }; + + if (m_ffmpegHandler->avformat_open_input(&videoFmtCtx, videoPath.c_str(), nullptr, nullptr) < 0) { + LOGE() << "addAudio: failed to open video input: " << videoPath; + return false; + } + if (m_ffmpegHandler->avformat_find_stream_info(videoFmtCtx, nullptr) < 0) { + LOGE() << "addAudio: failed to find video stream info"; + return false; + } + + if (m_ffmpegHandler->avformat_open_input(&audioFmtCtx, audioPath.c_str(), nullptr, nullptr) < 0) { + LOGE() << "addAudio: failed to open audio input: " << audioPath; + return false; + } + if (m_ffmpegHandler->avformat_find_stream_info(audioFmtCtx, nullptr) < 0) { + LOGE() << "addAudio: failed to find audio stream info"; + return false; + } + + if (m_ffmpegHandler->avformat_alloc_output_context2(&outputFmtCtx, nullptr, "mp4", tmpPath.c_str()) < 0 || !outputFmtCtx) { + LOGE() << "addAudio: failed to allocate output context"; + return false; + } + + int videoInIdx = -1; + int audioInIdx = -1; + int outVideoIdx = -1; + int outAudioIdx = -1; + + for (unsigned i = 0; i < videoFmtCtx->nb_streams; i++) { + if (videoFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + videoInIdx = static_cast(i); + AVStream* outStream = m_ffmpegHandler->avformat_new_stream(outputFmtCtx, nullptr); + if (!outStream) { + LOGE() << "addAudio: failed to create output video stream"; + return false; + } + m_ffmpegHandler->avcodec_parameters_copy(outStream->codecpar, videoFmtCtx->streams[i]->codecpar); + outStream->codecpar->codec_tag = 0; + outStream->time_base = videoFmtCtx->streams[i]->time_base; + outVideoIdx = outStream->index; + break; + } + } + + for (unsigned i = 0; i < audioFmtCtx->nb_streams; i++) { + if (audioFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + audioInIdx = static_cast(i); + AVStream* outStream = m_ffmpegHandler->avformat_new_stream(outputFmtCtx, nullptr); + if (!outStream) { + LOGE() << "addAudio: failed to create output audio stream"; + return false; + } + m_ffmpegHandler->avcodec_parameters_copy(outStream->codecpar, audioFmtCtx->streams[i]->codecpar); + outStream->codecpar->codec_tag = 0; + outStream->time_base = audioFmtCtx->streams[i]->time_base; + outAudioIdx = outStream->index; + break; + } + } + + if (videoInIdx < 0 || audioInIdx < 0) { + LOGE() << "addAudio: could not find video or audio stream"; + return false; + } + + if (m_ffmpegHandler->avio_open(&outputFmtCtx->pb, tmpPath.c_str(), AVIO_FLAG_WRITE) < 0) { + LOGE() << "addAudio: failed to open output file: " << tmpPath; + return false; + } + + if (m_ffmpegHandler->avformat_write_header(outputFmtCtx, nullptr) < 0) { + LOGE() << "addAudio: failed to write header"; + return false; + } + + int64_t audioOffsetPts = 0; + { + AVStream* audioOutStream = outputFmtCtx->streams[outAudioIdx]; + audioOffsetPts = static_cast(audioOffsetSec * audioOutStream->time_base.den + / audioOutStream->time_base.num); + } + + AVPacket* pkt = m_ffmpegHandler->av_packet_alloc(); + + while (m_ffmpegHandler->av_read_frame(videoFmtCtx, pkt) >= 0) { + if (pkt->stream_index == videoInIdx) { + pkt->stream_index = outVideoIdx; + m_ffmpegHandler->av_packet_rescale_ts(pkt, videoFmtCtx->streams[videoInIdx]->time_base, + outputFmtCtx->streams[outVideoIdx]->time_base); + pkt->pos = -1; + m_ffmpegHandler->av_interleaved_write_frame(outputFmtCtx, pkt); + } + m_ffmpegHandler->av_packet_unref(pkt); + } + + while (m_ffmpegHandler->av_read_frame(audioFmtCtx, pkt) >= 0) { + if (pkt->stream_index == audioInIdx) { + pkt->stream_index = outAudioIdx; + m_ffmpegHandler->av_packet_rescale_ts(pkt, audioFmtCtx->streams[audioInIdx]->time_base, + outputFmtCtx->streams[outAudioIdx]->time_base); + pkt->pts += audioOffsetPts; + pkt->dts += audioOffsetPts; + pkt->pos = -1; + m_ffmpegHandler->av_interleaved_write_frame(outputFmtCtx, pkt); + } + m_ffmpegHandler->av_packet_unref(pkt); + } + + m_ffmpegHandler->av_packet_free(&pkt); + m_ffmpegHandler->av_write_trailer(outputFmtCtx); + + if (!io::File::copy(tmpPath, videoPath, true)) { + LOGE() << "addAudio: failed to replace with muxed file"; + return false; + } + + io::File::remove(tmpPath); + + return true; +} + +bool VideoEncoder::convertImage_sws(const QImage& img) +{ + // Check if the image matches the size + if (img.width() != m_ffmpeg->width || img.height() != m_ffmpeg->height) { + LOGE() << "wrong image size!"; + return false; + } + + if (img.format() != QImage::Format_RGB32 && img.format() != QImage::Format_ARGB32) { + LOGE() << "wrong image format"; + return false; + } + + m_ffmpeg->img_convert_ctx = m_ffmpegHandler->sws_getCachedContext(m_ffmpeg->img_convert_ctx, m_ffmpeg->width, m_ffmpeg->height, + AV_PIX_FMT_BGRA, + m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, + NULL, NULL, NULL); + + if (!m_ffmpeg->img_convert_ctx) { + LOGE() << "failed initialize the conversion context"; + return false; + } + + uint8_t* srcplanes[3]; + srcplanes[0] = (uint8_t*)img.bits(); + srcplanes[1] = 0; + srcplanes[2] = 0; + + int srcstride[3]; + srcstride[0] = img.bytesPerLine(); + srcstride[1] = 0; + srcstride[2 ]= 0; + + m_ffmpegHandler->sws_scale(m_ffmpeg->img_convert_ctx, srcplanes, srcstride, 0, m_ffmpeg->height, m_ffmpeg->ppicture->data, + m_ffmpeg->ppicture->linesize); + + return true; +} +} diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.h b/src/framework/media/internal/ffmpeg/v4/videoencoder.h new file mode 100644 index 0000000000000..2e879e0258d80 --- /dev/null +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.h @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "media/ivideoencoder.h" + +#include "ffmpeglibhandler.h" + +namespace muse::media::ffmpeg::v4 { +struct FFmpeg; +class VideoEncoder : public IVideoEncoder +{ +public: + explicit VideoEncoder(const std::shared_ptr& handler); + ~VideoEncoder() override; + + bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; + void close() override; + + bool encodeImage(const QImage& img) override; + void finishEncode() override; + + bool addAudio(const muse::io::path_t& audioPath, double audioOffsetSec) override; + +private: + bool convertImage_sws(const QImage& img); + + std::shared_ptr m_ffmpegHandler = nullptr; + FFmpeg* m_ffmpeg = nullptr; + muse::io::path_t m_outputPath; +}; +} diff --git a/src/framework/media/internal/videoencoderresolver.cpp b/src/framework/media/internal/videoencoderresolver.cpp index 43f7e7b93919c..9bd1eadb46d61 100644 --- a/src/framework/media/internal/videoencoderresolver.cpp +++ b/src/framework/media/internal/videoencoderresolver.cpp @@ -34,6 +34,9 @@ #include "internal/ffmpeg/v5/ffmpeglibhandler.h" #include "internal/ffmpeg/v5/videoencoder.h" +#include "internal/ffmpeg/v4/ffmpeglibhandler.h" +#include "internal/ffmpeg/v4/videoencoder.h" + #include "io/path.h" #include "log.h" @@ -171,6 +174,23 @@ VideoEncoderResolver::EncoderInfo VideoEncoderResolver::makeEncoder(const FFmpeg LOGW() << "FFmpeg libraries not found"; } } break; + case FFMPEG_V4: { + auto ffmpegLibHandler = std::make_shared(); + if (ffmpegLibHandler->loadLib(ffmpegLibsPaths.avUtilPath, ffmpegLibsPaths.avCodecPath, ffmpegLibsPaths.avFormatPath, + ffmpegLibsPaths.swScalePath, ffmpegLibsPaths.swResamplePath) + && ffmpegLibHandler->loadApi()) { + ffmpegLibHandler->setVersion(version); + ffmpegLibHandler->setDir(io::dirpath(ffmpegLibsPaths.avFormatPath)); + + LOGD() << "FFmpeg loaded, version: " << ffmpegLibHandler->version(); + + result.encoder = std::make_shared(ffmpegLibHandler); + result.ffmpegLibsDir = ffmpegLibHandler->dir(); + result.ffmpegVersion = ffmpegLibHandler->version(); + } else { + LOGW() << "FFmpeg libraries not found"; + } + } break; default: break; } From c1c0ce2264b51e62539deb3f286a8894c7e86439 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 16 Mar 2026 13:06:36 +0200 Subject: [PATCH 31/52] refactored ffmpeg video encoder initialization and encapsulated library loading --- src/framework/media/CMakeLists.txt | 5 +- .../media/internal/ffmpeg/v4/videoencoder.cpp | 21 ++- .../media/internal/ffmpeg/v4/videoencoder.h | 9 +- .../media/internal/ffmpeg/v5/videoencoder.cpp | 21 ++- .../media/internal/ffmpeg/v5/videoencoder.h | 9 +- .../media/internal/ffmpeg/v6/videoencoder.cpp | 21 ++- .../media/internal/ffmpeg/v6/videoencoder.h | 9 +- .../media/internal/ffmpeg/v7/videoencoder.cpp | 21 ++- .../media/internal/ffmpeg/v7/videoencoder.h | 9 +- .../media/internal/ffmpeg/v8/videoencoder.cpp | 21 ++- .../media/internal/ffmpeg/v8/videoencoder.h | 7 +- .../media/internal/videoencoderresolver.cpp | 124 +++++------------- 12 files changed, 155 insertions(+), 122 deletions(-) diff --git a/src/framework/media/CMakeLists.txt b/src/framework/media/CMakeLists.txt index ba23f8ff1728e..f0cfe3ba1fd7d 100644 --- a/src/framework/media/CMakeLists.txt +++ b/src/framework/media/CMakeLists.txt @@ -18,7 +18,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -muse_create_module(muse_media ALIAS muse::media) +muse_create_module(muse_media ALIAS muse::media NO_PCH NO_UNITY) target_sources(muse_media PRIVATE mediamodule.cpp @@ -91,6 +91,3 @@ set_source_files_properties( internal/ffmpeg/v4/videoencoder.cpp PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/ffmpeg/v4" ) - -set(MODULE_USE_PCH OFF) -set(MODULE_USE_UNITY OFF) diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp index d93d87f6b3933..8f234977eb0fe 100644 --- a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp @@ -20,8 +20,10 @@ * along with this program. If not, see . */ #include "videoencoder.h" +#include "ffmpeglibhandler.h" #include "io/file.h" +#include "io/path.h" #include "defer.h" #include "log.h" @@ -48,8 +50,7 @@ struct FFmpeg { bool finished = false; }; -VideoEncoder::VideoEncoder(const std::shared_ptr& handler) - : m_ffmpegHandler(handler) +VideoEncoder::VideoEncoder() { m_ffmpeg = new FFmpeg(); } @@ -59,6 +60,22 @@ VideoEncoder::~VideoEncoder() delete m_ffmpeg; } +bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) +{ + auto handler = std::make_shared(); + if (!handler->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, + paths.swScalePath, paths.swResamplePath) + || !handler->loadApi()) { + LOGW() << "FFmpeg libraries not found"; + return false; + } + handler->setVersion(version); + handler->setDir(io::dirpath(paths.avFormatPath)); + m_ffmpegHandler = std::move(handler); + LOGD() << "FFmpeg loaded, version: " << m_ffmpegHandler->version(); + return true; +} + bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) { m_ffmpeg->ptsCounter = 0; diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.h b/src/framework/media/internal/ffmpeg/v4/videoencoder.h index 2e879e0258d80..265af07a35409 100644 --- a/src/framework/media/internal/ffmpeg/v4/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.h @@ -22,18 +22,21 @@ #pragma once -#include "media/ivideoencoder.h" +#include "internal/ffmpegutils.h" -#include "ffmpeglibhandler.h" +#include "media/ivideoencoder.h" namespace muse::media::ffmpeg::v4 { +class FFmpegLibHandler; struct FFmpeg; class VideoEncoder : public IVideoEncoder { public: - explicit VideoEncoder(const std::shared_ptr& handler); + VideoEncoder(); ~VideoEncoder() override; + bool load(const FFmpegLibPaths& paths, int version); + bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; void close() override; diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp index f7c00b0f28124..bf0ff1e00f7c3 100644 --- a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp @@ -20,8 +20,10 @@ * along with this program. If not, see . */ #include "videoencoder.h" +#include "ffmpeglibhandler.h" #include "io/file.h" +#include "io/path.h" #include "defer.h" #include "log.h" @@ -48,8 +50,7 @@ struct FFmpeg { bool finished = false; }; -VideoEncoder::VideoEncoder(const std::shared_ptr& handler) - : m_ffmpegHandler(handler) +VideoEncoder::VideoEncoder() { m_ffmpeg = new FFmpeg(); } @@ -59,6 +60,22 @@ VideoEncoder::~VideoEncoder() delete m_ffmpeg; } +bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) +{ + auto handler = std::make_shared(); + if (!handler->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, + paths.swScalePath, paths.swResamplePath) + || !handler->loadApi()) { + LOGW() << "FFmpeg libraries not found"; + return false; + } + handler->setVersion(version); + handler->setDir(io::dirpath(paths.avFormatPath)); + m_ffmpegHandler = std::move(handler); + LOGD() << "FFmpeg loaded, version: " << m_ffmpegHandler->version(); + return true; +} + bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) { m_ffmpeg->ptsCounter = 0; diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.h b/src/framework/media/internal/ffmpeg/v5/videoencoder.h index 1aedc4681daa2..e1e328f478b9b 100644 --- a/src/framework/media/internal/ffmpeg/v5/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.h @@ -22,18 +22,21 @@ #pragma once -#include "media/ivideoencoder.h" +#include "internal/ffmpegutils.h" -#include "ffmpeglibhandler.h" +#include "media/ivideoencoder.h" namespace muse::media::ffmpeg::v5 { +class FFmpegLibHandler; struct FFmpeg; class VideoEncoder : public IVideoEncoder { public: - explicit VideoEncoder(const std::shared_ptr& handler); + VideoEncoder(); ~VideoEncoder() override; + bool load(const FFmpegLibPaths& paths, int version); + bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; void close() override; diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp index d471359a13b57..ef5ddaeeffa13 100644 --- a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp @@ -20,8 +20,10 @@ * along with this program. If not, see . */ #include "videoencoder.h" +#include "ffmpeglibhandler.h" #include "io/file.h" +#include "io/path.h" #include "defer.h" #include "log.h" @@ -48,8 +50,7 @@ struct FFmpeg { bool finished = false; }; -VideoEncoder::VideoEncoder(const std::shared_ptr& handler) - : m_ffmpegHandler(handler) +VideoEncoder::VideoEncoder() { m_ffmpeg = new FFmpeg(); } @@ -59,6 +60,22 @@ VideoEncoder::~VideoEncoder() delete m_ffmpeg; } +bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) +{ + auto handler = std::make_shared(); + if (!handler->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, + paths.swScalePath, paths.swResamplePath) + || !handler->loadApi()) { + LOGW() << "FFmpeg libraries not found"; + return false; + } + handler->setVersion(version); + handler->setDir(io::dirpath(paths.avFormatPath)); + m_ffmpegHandler = std::move(handler); + LOGD() << "FFmpeg loaded, version: " << m_ffmpegHandler->version(); + return true; +} + bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) { m_ffmpeg->ptsCounter = 0; diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.h b/src/framework/media/internal/ffmpeg/v6/videoencoder.h index ed6bdf6d69aa1..379c3023b4b20 100644 --- a/src/framework/media/internal/ffmpeg/v6/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.h @@ -22,18 +22,21 @@ #pragma once -#include "media/ivideoencoder.h" +#include "internal/ffmpegutils.h" -#include "ffmpeglibhandler.h" +#include "media/ivideoencoder.h" namespace muse::media::ffmpeg::v6 { +class FFmpegLibHandler; struct FFmpeg; class VideoEncoder : public IVideoEncoder { public: - explicit VideoEncoder(const std::shared_ptr& handler); + VideoEncoder(); ~VideoEncoder() override; + bool load(const FFmpegLibPaths& paths, int version); + bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; void close() override; diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp index 61c87864b9391..6c5f728abd64b 100644 --- a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp @@ -20,8 +20,10 @@ * along with this program. If not, see . */ #include "videoencoder.h" +#include "ffmpeglibhandler.h" #include "io/file.h" +#include "io/path.h" #include "defer.h" #include "log.h" @@ -48,8 +50,7 @@ struct FFmpeg { bool finished = false; }; -VideoEncoder::VideoEncoder(const std::shared_ptr& handler) - : m_ffmpegHandler(handler) +VideoEncoder::VideoEncoder() { m_ffmpeg = new FFmpeg(); } @@ -59,6 +60,22 @@ VideoEncoder::~VideoEncoder() delete m_ffmpeg; } +bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) +{ + auto handler = std::make_shared(); + if (!handler->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, + paths.swScalePath, paths.swResamplePath) + || !handler->loadApi()) { + LOGW() << "FFmpeg libraries not found"; + return false; + } + handler->setVersion(version); + handler->setDir(io::dirpath(paths.avFormatPath)); + m_ffmpegHandler = std::move(handler); + LOGD() << "FFmpeg loaded, version: " << m_ffmpegHandler->version(); + return true; +} + bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) { m_ffmpeg->ptsCounter = 0; diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.h b/src/framework/media/internal/ffmpeg/v7/videoencoder.h index f83f4b76d3bab..b1b1a33ce05f6 100644 --- a/src/framework/media/internal/ffmpeg/v7/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.h @@ -22,18 +22,21 @@ #pragma once -#include "media/ivideoencoder.h" +#include "internal/ffmpegutils.h" -#include "ffmpeglibhandler.h" +#include "media/ivideoencoder.h" namespace muse::media::ffmpeg::v7 { +class FFmpegLibHandler; struct FFmpeg; class VideoEncoder : public IVideoEncoder { public: - explicit VideoEncoder(const std::shared_ptr& handler); + VideoEncoder(); ~VideoEncoder() override; + bool load(const FFmpegLibPaths& paths, int version); + bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; void close() override; diff --git a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp index 0528f016f59df..632ececed0401 100644 --- a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp @@ -20,8 +20,10 @@ * along with this program. If not, see . */ #include "videoencoder.h" +#include "ffmpeglibhandler.h" #include "io/file.h" +#include "io/path.h" #include "defer.h" #include "log.h" @@ -48,8 +50,7 @@ struct FFmpeg { bool finished = false; }; -VideoEncoder::VideoEncoder(const std::shared_ptr& handler) - : m_ffmpegHandler(handler) +VideoEncoder::VideoEncoder() { m_ffmpeg = new FFmpeg(); } @@ -59,6 +60,22 @@ VideoEncoder::~VideoEncoder() delete m_ffmpeg; } +bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) +{ + auto handler = std::make_shared(); + if (!handler->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, + paths.swScalePath, paths.swResamplePath) + || !handler->loadApi()) { + LOGW() << "FFmpeg libraries not found"; + return false; + } + handler->setVersion(version); + handler->setDir(io::dirpath(paths.avFormatPath)); + m_ffmpegHandler = std::move(handler); + LOGD() << "FFmpeg loaded, version: " << m_ffmpegHandler->version(); + return true; +} + bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) { m_ffmpeg->ptsCounter = 0; diff --git a/src/framework/media/internal/ffmpeg/v8/videoencoder.h b/src/framework/media/internal/ffmpeg/v8/videoencoder.h index 5b3306de15a7e..3955290cb2216 100644 --- a/src/framework/media/internal/ffmpeg/v8/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.h @@ -24,16 +24,19 @@ #include "media/ivideoencoder.h" -#include "ffmpeglibhandler.h" +#include "internal/ffmpegutils.h" namespace muse::media::ffmpeg::v8 { +class FFmpegLibHandler; struct FFmpeg; class VideoEncoder : public IVideoEncoder { public: - explicit VideoEncoder(const std::shared_ptr& handler); + VideoEncoder(); ~VideoEncoder() override; + bool load(const FFmpegLibPaths& paths, int version); + bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; void close() override; diff --git a/src/framework/media/internal/videoencoderresolver.cpp b/src/framework/media/internal/videoencoderresolver.cpp index 9bd1eadb46d61..a8f2c64095e5d 100644 --- a/src/framework/media/internal/videoencoderresolver.cpp +++ b/src/framework/media/internal/videoencoderresolver.cpp @@ -22,19 +22,10 @@ #include "videoencoderresolver.h" -#include "internal/ffmpeg/v8/ffmpeglibhandler.h" #include "internal/ffmpeg/v8/videoencoder.h" - -#include "internal/ffmpeg/v7/ffmpeglibhandler.h" #include "internal/ffmpeg/v7/videoencoder.h" - -#include "internal/ffmpeg/v6/ffmpeglibhandler.h" #include "internal/ffmpeg/v6/videoencoder.h" - -#include "internal/ffmpeg/v5/ffmpeglibhandler.h" #include "internal/ffmpeg/v5/videoencoder.h" - -#include "internal/ffmpeg/v4/ffmpeglibhandler.h" #include "internal/ffmpeg/v4/videoencoder.h" #include "io/path.h" @@ -100,100 +91,45 @@ void VideoEncoderResolver::resetFFmpegSettings() configuration()->setFFmpegLibsDir({}); } +template +static IVideoEncoderPtr tryCreateEncoder(const FFmpegLibPaths& paths, int version) +{ + auto encoder = std::make_shared(); + if (encoder->load(paths, version)) { + return encoder; + } + return nullptr; +} + VideoEncoderResolver::EncoderInfo VideoEncoderResolver::makeEncoder(const FFmpegLibPaths& ffmpegLibsPaths) const { EncoderInfo result; const FFmpegVersion version = versionFromAVFormatPath(ffmpegLibsPaths.avFormatPath); switch (version) { - case FFMPEG_V8: { - auto ffmpegLibHandler = std::make_shared(); - if (ffmpegLibHandler->loadLib(ffmpegLibsPaths.avUtilPath, ffmpegLibsPaths.avCodecPath, ffmpegLibsPaths.avFormatPath, - ffmpegLibsPaths.swScalePath, ffmpegLibsPaths.swResamplePath) - && ffmpegLibHandler->loadApi()) { - ffmpegLibHandler->setVersion(version); - ffmpegLibHandler->setDir(io::dirpath(ffmpegLibsPaths.avFormatPath)); - - LOGD() << "FFmpeg loaded, version: " << ffmpegLibHandler->version(); - - result.encoder = std::make_shared(ffmpegLibHandler); - result.ffmpegLibsDir = ffmpegLibHandler->dir(); - result.ffmpegVersion = ffmpegLibHandler->version(); - } else { - LOGW() << "FFmpeg libraries not found"; - } - } break; - case FFMPEG_V7: { - auto ffmpegLibHandler = std::make_shared(); - if (ffmpegLibHandler->loadLib(ffmpegLibsPaths.avUtilPath, ffmpegLibsPaths.avCodecPath, ffmpegLibsPaths.avFormatPath, - ffmpegLibsPaths.swScalePath, ffmpegLibsPaths.swResamplePath) - && ffmpegLibHandler->loadApi()) { - ffmpegLibHandler->setVersion(version); - ffmpegLibHandler->setDir(io::dirpath(ffmpegLibsPaths.avFormatPath)); - - LOGD() << "FFmpeg loaded, version: " << ffmpegLibHandler->version(); - - result.encoder = std::make_shared(ffmpegLibHandler); - result.ffmpegLibsDir = ffmpegLibHandler->dir(); - result.ffmpegVersion = ffmpegLibHandler->version(); - } else { - LOGW() << "FFmpeg libraries not found"; - } - } break; - case FFMPEG_V6: { - auto ffmpegLibHandler = std::make_shared(); - if (ffmpegLibHandler->loadLib(ffmpegLibsPaths.avUtilPath, ffmpegLibsPaths.avCodecPath, ffmpegLibsPaths.avFormatPath, - ffmpegLibsPaths.swScalePath, ffmpegLibsPaths.swResamplePath) - && ffmpegLibHandler->loadApi()) { - ffmpegLibHandler->setVersion(version); - ffmpegLibHandler->setDir(io::dirpath(ffmpegLibsPaths.avFormatPath)); - - LOGD() << "FFmpeg loaded, version: " << ffmpegLibHandler->version(); - - result.encoder = std::make_shared(ffmpegLibHandler); - result.ffmpegLibsDir = ffmpegLibHandler->dir(); - result.ffmpegVersion = ffmpegLibHandler->version(); - } else { - LOGW() << "FFmpeg libraries not found"; - } - } break; - case FFMPEG_V5: { - auto ffmpegLibHandler = std::make_shared(); - if (ffmpegLibHandler->loadLib(ffmpegLibsPaths.avUtilPath, ffmpegLibsPaths.avCodecPath, ffmpegLibsPaths.avFormatPath, - ffmpegLibsPaths.swScalePath, ffmpegLibsPaths.swResamplePath) - && ffmpegLibHandler->loadApi()) { - ffmpegLibHandler->setVersion(version); - ffmpegLibHandler->setDir(io::dirpath(ffmpegLibsPaths.avFormatPath)); - - LOGD() << "FFmpeg loaded, version: " << ffmpegLibHandler->version(); - - result.encoder = std::make_shared(ffmpegLibHandler); - result.ffmpegLibsDir = ffmpegLibHandler->dir(); - result.ffmpegVersion = ffmpegLibHandler->version(); - } else { - LOGW() << "FFmpeg libraries not found"; - } - } break; - case FFMPEG_V4: { - auto ffmpegLibHandler = std::make_shared(); - if (ffmpegLibHandler->loadLib(ffmpegLibsPaths.avUtilPath, ffmpegLibsPaths.avCodecPath, ffmpegLibsPaths.avFormatPath, - ffmpegLibsPaths.swScalePath, ffmpegLibsPaths.swResamplePath) - && ffmpegLibHandler->loadApi()) { - ffmpegLibHandler->setVersion(version); - ffmpegLibHandler->setDir(io::dirpath(ffmpegLibsPaths.avFormatPath)); - - LOGD() << "FFmpeg loaded, version: " << ffmpegLibHandler->version(); - - result.encoder = std::make_shared(ffmpegLibHandler); - result.ffmpegLibsDir = ffmpegLibHandler->dir(); - result.ffmpegVersion = ffmpegLibHandler->version(); - } else { - LOGW() << "FFmpeg libraries not found"; - } - } break; + case FFMPEG_V8: + result.encoder = tryCreateEncoder(ffmpegLibsPaths, version); + break; + case FFMPEG_V7: + result.encoder = tryCreateEncoder(ffmpegLibsPaths, version); + break; + case FFMPEG_V6: + result.encoder = tryCreateEncoder(ffmpegLibsPaths, version); + break; + case FFMPEG_V5: + result.encoder = tryCreateEncoder(ffmpegLibsPaths, version); + break; + case FFMPEG_V4: + result.encoder = tryCreateEncoder(ffmpegLibsPaths, version); + break; default: break; } + if (result.encoder) { + result.ffmpegLibsDir = io::dirpath(ffmpegLibsPaths.avFormatPath); + result.ffmpegVersion = version; + } + return result; } From a244a46dc474de19eba73cbc2538ccce4dbc5842 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 16 Mar 2026 13:26:13 +0200 Subject: [PATCH 32/52] added missing include for ffmpeg 4 --- .../ffmpeg/download_ffmpeg_headers.sh | 2 +- .../thirdparty/ffmpeg/v4/libavutil/avconfig.h | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/framework/media/thirdparty/ffmpeg/v4/libavutil/avconfig.h diff --git a/src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh b/src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh index 1b1e92aa84af8..e8834112f2786 100644 --- a/src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh +++ b/src/framework/media/thirdparty/ffmpeg/download_ffmpeg_headers.sh @@ -84,7 +84,7 @@ for ver_spec in "${VERSIONS[@]}"; do done # avconfig.h is generated by FFmpeg configure, not in source; add minimal version - if [ -f "$target/libavutil/macros.h" ] && grep -q avconfig.h "$target/libavutil/macros.h" 2>/dev/null; then + if grep -rq avconfig.h "$target/libavutil/" 2>/dev/null; then mkdir -p "$target/libavutil" write_avconfig "$target/libavutil/avconfig.h" echo " added libavutil/avconfig.h" diff --git a/src/framework/media/thirdparty/ffmpeg/v4/libavutil/avconfig.h b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/avconfig.h new file mode 100644 index 0000000000000..f13252f7d2c25 --- /dev/null +++ b/src/framework/media/thirdparty/ffmpeg/v4/libavutil/avconfig.h @@ -0,0 +1,24 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVCONFIG_H +#define AVUTIL_AVCONFIG_H + +#define AV_HAVE_BIGENDIAN 0 + +#endif /* AVUTIL_AVCONFIG_H */ From 9d55f7c1666c631164c6d345e8b4ba044f684918 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 16 Mar 2026 13:48:16 +0200 Subject: [PATCH 33/52] fixed the clean issue in add audio --- src/framework/media/internal/ffmpeg/v4/videoencoder.cpp | 9 +++++++++ src/framework/media/internal/ffmpeg/v5/videoencoder.cpp | 9 +++++++++ src/framework/media/internal/ffmpeg/v6/videoencoder.cpp | 9 +++++++++ src/framework/media/internal/ffmpeg/v7/videoencoder.cpp | 9 +++++++++ 4 files changed, 36 insertions(+) diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp index 8f234977eb0fe..4710f1b185baa 100644 --- a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp @@ -348,7 +348,12 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) AVFormatContext* audioFmtCtx = nullptr; AVFormatContext* outputFmtCtx = nullptr; + bool cleaned = false; auto cleanup = [&]() { + if (cleaned) { + return; + } + if (videoFmtCtx) { m_ffmpegHandler->avformat_close_input(&videoFmtCtx); } @@ -361,6 +366,8 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) } m_ffmpegHandler->avformat_free_context(outputFmtCtx); } + + cleaned = true; }; DEFER { @@ -478,6 +485,8 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) m_ffmpegHandler->av_packet_free(&pkt); m_ffmpegHandler->av_write_trailer(outputFmtCtx); + cleanup(); + if (!io::File::copy(tmpPath, videoPath, true)) { LOGE() << "addAudio: failed to replace with muxed file"; return false; diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp index bf0ff1e00f7c3..9892f7a5f650f 100644 --- a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp @@ -348,7 +348,12 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) AVFormatContext* audioFmtCtx = nullptr; AVFormatContext* outputFmtCtx = nullptr; + bool cleaned = false; auto cleanup = [&]() { + if (cleaned) { + return; + } + if (videoFmtCtx) { m_ffmpegHandler->avformat_close_input(&videoFmtCtx); } @@ -361,6 +366,8 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) } m_ffmpegHandler->avformat_free_context(outputFmtCtx); } + + cleaned = true; }; DEFER { @@ -478,6 +485,8 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) m_ffmpegHandler->av_packet_free(&pkt); m_ffmpegHandler->av_write_trailer(outputFmtCtx); + cleanup(); + if (!io::File::copy(tmpPath, videoPath, true)) { LOGE() << "addAudio: failed to replace with muxed file"; return false; diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp index ef5ddaeeffa13..925bb5870bd5f 100644 --- a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp @@ -348,7 +348,12 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) AVFormatContext* audioFmtCtx = nullptr; AVFormatContext* outputFmtCtx = nullptr; + bool cleaned = false; auto cleanup = [&]() { + if (cleaned) { + return; + } + if (videoFmtCtx) { m_ffmpegHandler->avformat_close_input(&videoFmtCtx); } @@ -361,6 +366,8 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) } m_ffmpegHandler->avformat_free_context(outputFmtCtx); } + + cleaned = true; }; DEFER { @@ -478,6 +485,8 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) m_ffmpegHandler->av_packet_free(&pkt); m_ffmpegHandler->av_write_trailer(outputFmtCtx); + cleanup(); + if (!io::File::copy(tmpPath, videoPath, true)) { LOGE() << "addAudio: failed to replace with muxed file"; return false; diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp index 6c5f728abd64b..b1ebc64e100e2 100644 --- a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp @@ -348,7 +348,12 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) AVFormatContext* audioFmtCtx = nullptr; AVFormatContext* outputFmtCtx = nullptr; + bool cleaned = false; auto cleanup = [&]() { + if (cleaned) { + return; + } + if (videoFmtCtx) { m_ffmpegHandler->avformat_close_input(&videoFmtCtx); } @@ -361,6 +366,8 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) } m_ffmpegHandler->avformat_free_context(outputFmtCtx); } + + cleaned = true; }; DEFER { @@ -478,6 +485,8 @@ bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) m_ffmpegHandler->av_packet_free(&pkt); m_ffmpegHandler->av_write_trailer(outputFmtCtx); + cleanup(); + if (!io::File::copy(tmpPath, videoPath, true)) { LOGE() << "addAudio: failed to replace with muxed file"; return false; From 0ff87018189f4428d07b537b93c4eeb5c0f25835 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 16 Mar 2026 13:51:07 +0200 Subject: [PATCH 34/52] added check MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE --- .../qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp index 231f7ef4f0abe..5a036031773ad 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp +++ b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp @@ -117,6 +117,7 @@ ExportDialogModel::ExportDialogModel(QObject* parent) "LrcSettingsPage.qml") }; +#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE if (application()->unstable()) { m_exportTypeList.push_back( ExportType::makeWithSuffixes({ "mp4" }, @@ -125,6 +126,7 @@ ExportDialogModel::ExportDialogModel(QObject* parent) "Mp4SettingsPage.qml") ); } +#endif } ExportDialogModel::~ExportDialogModel() From af2eb31d2c8382f15076d0663c6bb693d6246300 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 11:22:43 +0200 Subject: [PATCH 35/52] moved ffmpeg settings to Video page --- src/framework/ui/data/MusescoreIcon.ttf | Bin 177136 -> 177336 bytes src/framework/ui/view/iconcodes.h | 2 + .../qml/Muse/UiComponents/FilePicker.qml | 9 +-- .../qml/MuseScore/Preferences/CMakeLists.txt | 3 + .../Preferences/FoldersPreferencesPage.qml | 11 ---- .../Preferences/VideoPreferencesPage.qml | 51 +++++++++++++++ .../Preferences/folderspreferencesmodel.cpp | 32 ---------- .../Preferences/folderspreferencesmodel.h | 21 ------ .../Preferences/internal/FFmpegSection.qml | 13 ++-- .../Preferences/preferencesmodel.cpp | 3 + .../Preferences/videopreferencesmodel.cpp | 60 ++++++++++++++++++ .../Preferences/videopreferencesmodel.h | 58 +++++++++++++++++ 12 files changed, 189 insertions(+), 74 deletions(-) create mode 100644 src/preferences/qml/MuseScore/Preferences/VideoPreferencesPage.qml create mode 100644 src/preferences/qml/MuseScore/Preferences/videopreferencesmodel.cpp create mode 100644 src/preferences/qml/MuseScore/Preferences/videopreferencesmodel.h diff --git a/src/framework/ui/data/MusescoreIcon.ttf b/src/framework/ui/data/MusescoreIcon.ttf index 85d5e3031dd5d3f7a6a7b50edf7ab05e06149897..76aa0cff08bb29938059b15314dd5915c0434b30 100644 GIT binary patch delta 1362 zcmZWpTWlLe6umS1^4dV_zN3hgPh^*v8- zHoGFvd;vh-L3?0-W;nZiVSNQa{0M+s+J9t96*`N{0QG(7S4XpBnN#o0>;rK1130o{ z!;@K@mvFxc9BpG0$8)3Z+XvVt**)AK`o}R|Jvf{h88bV2fi4^apv&1q zlT&~GGxQMXS&a7*v5~o;7 zWBDhmd6M7lIxk0ufF9}x`Z^2r@D*&o0-cnxZN-MZ>AgUYTrKJHrmVd!Yos7+^gt%p z3Zu+*W*+>o0Z>=Md)=~6d7OB|sic{WtU+?w#NSk5E6N#}k(g z#V%?R6U?Z^Pa3K?r(rlbmrD9HDWcV>Ycn*v_JOadMIB5(8&7oD9d3_b6hy9G@&%Jd z=it!Ji0<^-wZ339AxEQmAVq+OJYhsQi>daRUb*nxEFBbbrHgrz1?D8UAOvwppgW8S zMpcqwvwRB-Os*R<9mZ6Mj7}xMHV=ZH_e<}1HZ2OnR1`%?M$>{zN=sk6k@Aj9{i-K zg6%Ls1}fMAI=Maf{sNtGB~hGGGf^TFthv+~YS@zTWZX=cR$=rEeS*wgTBIszEZkhA x{VZjo1^og&;ns!egRgcscbcd)0kXc1N|&l-sWd70_9$8mjm=%n(>Q~L;a}k+5x@Wd delta 1138 zcmY*YTTB~A6umRM-d%fxvEx^;7yQ`8HW*`j?X@8WQyL&N1!Acv4Sj^VghvGqt3Xlm zQ>$u}(tK1@d{_dLG<~TbsA_9cw^da&%}+j}NPQ(zE1`ZQedH&VN>qu0+cC1Lbfi0T z&Ye4Vbgu6G^mpAKzv^;;0Kh;t8lbOlcyRT6vJG(Yd*T%i_w@Eb6HXJpPPq5z6Ct@* zeDVqaS|t3~ST>{nwZ8oYfc6~#&HC8Fyo)_l-U4v+lY7^MI+?xj#?lBtZ5n`ACo^*@ z@f%1!5)a(u%-P(8D^)iLAejL#yg4xZ0PNQ@vtt>&@LLP{aEjzx&t}f3^pNH$a!)w8PGz#=yK?&tz$+U7cw3#Fn>T*k z5e2;VA%JB|JuQ!`ce?{bf&DA;;QU@SNHMb8=SD|sJ01W}%0kwy-p}5yoOfR+#h1gV z6E!cNLeHYB#T)1vi#nH=v_9v1KRt2jCaOm4dt?NUsVKDhU#v&gME{g1SbnfE}DL zKr}KIquFLnB8yvz%89sQjC%t}NufkkgG3ai;)!@7g_M|A^e`3@X)!aR$E(ERQMrOy zJz}GBybDEHw}Oy{V&s!jGnYbo))|V9p;2c#{snVHG^j z_4kh+JnoSi3vL6;`Sj%vsFiM|{EJ7!`Td;6gNy?2MGmWG=Nl@tbFVpIPPg=Vn_7K# zmgk-3x@J%Nz)&*s_#+1zq#BpEU?&Bm{@H=+G)=XE04^XMW2y+W{--ck5koZk#669T zlxRY3TUJX^wIRR-*M6(3Vc4`vvOLAsz1_Qe&1cg@ID{U=v`8j#kKBoh2k#Tu|8eHAlc zM{*VG;23(Qih1x>#wq{u8g9v-E8yo%5om)TL_j9H3}IqQ{y_ozbdk1TL=MVfS*b*u t^EV54f9c2?7EylsBKDx>((4!TFkQOy7JkW?pV`0;)RbS`z(I-(&cE>@^r`>= diff --git a/src/framework/ui/view/iconcodes.h b/src/framework/ui/view/iconcodes.h index 79f4d58318226..9740ddee6f1f1 100644 --- a/src/framework/ui/view/iconcodes.h +++ b/src/framework/ui/view/iconcodes.h @@ -536,6 +536,8 @@ enum class Code : char16_t { FILLED_ARROW_LEFT = 0xF4BE, FILLED_ARROW_RIGHT = 0xF4BF, + VIDEO = 0xF4C2, + NONE = 0xFFFF }; diff --git a/src/framework/uicomponents/qml/Muse/UiComponents/FilePicker.qml b/src/framework/uicomponents/qml/Muse/UiComponents/FilePicker.qml index f7b9b2562d5d5..fe683c95eeddb 100644 --- a/src/framework/uicomponents/qml/Muse/UiComponents/FilePicker.qml +++ b/src/framework/uicomponents/qml/Muse/UiComponents/FilePicker.qml @@ -43,7 +43,9 @@ Item { property alias dir: filePickerModel.dir property int buttonType: FlatButton.IconOnly - property int orientation: Qt.Vertical + property string buttonText: qsTrc("ui", "Browse") + property int buttonOrientation: Qt.Vertical + property alias buttonWidth: button.implicitWidth property NavigationPanel navigation: null property int navigationRowOrderStart: 0 @@ -52,7 +54,6 @@ Item { property string pathFieldTitle: qsTrc("ui", "Current path:") property alias pathFieldWidth: pathField.implicitWidth - property alias buttonWidth: button.implicitWidth property alias spacing: row.spacing @@ -120,9 +121,9 @@ Item { Layout.alignment: Qt.AlignVCenter icon: IconCode.OPEN_FILE - text: qsTrc("ui", "Browse") + text: root.buttonText buttonType: root.buttonType - orientation: root.orientation + orientation: root.buttonOrientation navigation.name: "FilePickerButton" navigation.panel: root.navigation diff --git a/src/preferences/qml/MuseScore/Preferences/CMakeLists.txt b/src/preferences/qml/MuseScore/Preferences/CMakeLists.txt index 6d8d9d3be2b8f..e60376384f2eb 100644 --- a/src/preferences/qml/MuseScore/Preferences/CMakeLists.txt +++ b/src/preferences/qml/MuseScore/Preferences/CMakeLists.txt @@ -58,6 +58,8 @@ qt_add_qml_module(preferences_qml scorepreferencesmodel.h updatepreferencesmodel.cpp updatepreferencesmodel.h + videopreferencesmodel.cpp + videopreferencesmodel.h QML_FILES AccentColorsList.qml AdvancedPreferencesPage.qml @@ -78,6 +80,7 @@ qt_add_qml_module(preferences_qml ShortcutsPreferencesPage.qml ThemeSamplesList.qml UpdatePreferencesPage.qml + VideoPreferencesPage.qml internal/AccentColorsSection.qml internal/AdvancedTopSection.qml diff --git a/src/preferences/qml/MuseScore/Preferences/FoldersPreferencesPage.qml b/src/preferences/qml/MuseScore/Preferences/FoldersPreferencesPage.qml index 71c8743979a9f..4a0c6154c811c 100644 --- a/src/preferences/qml/MuseScore/Preferences/FoldersPreferencesPage.qml +++ b/src/preferences/qml/MuseScore/Preferences/FoldersPreferencesPage.qml @@ -43,21 +43,10 @@ PreferencesPage { spacing: root.sectionsSpacing FoldersSection { - id: generalFoldersSection - model: foldersPreferencesModel navigation.section: root.navigationSection navigation.order: root.navigationOrderStart + 1 } - - FFmpegSection { - id: ffmpegSection - - model: foldersPreferencesModel - - navigation.section: root.navigationSection - navigation.order: generalFoldersSection.navigation.order + 1 - } } } diff --git a/src/preferences/qml/MuseScore/Preferences/VideoPreferencesPage.qml b/src/preferences/qml/MuseScore/Preferences/VideoPreferencesPage.qml new file mode 100644 index 0000000000000..e3218ae8ce534 --- /dev/null +++ b/src/preferences/qml/MuseScore/Preferences/VideoPreferencesPage.qml @@ -0,0 +1,51 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import QtQuick + +import Muse.UiComponents +import MuseScore.Preferences + +import "internal" + +PreferencesPage { + id: root + + VideoPreferencesModel { + id: videoPreferencesModel + } + + Component.onCompleted: { + videoPreferencesModel.load() + } + + Column { + width: parent.width + spacing: root.sectionsSpacing + + FFmpegSection { + model: videoPreferencesModel + + navigation.section: root.navigationSection + navigation.order: root.navigationOrderStart + 1 + } + } +} diff --git a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp index 591749e117e84..3fbff42327949 100644 --- a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp +++ b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.cpp @@ -165,14 +165,6 @@ void FoldersPreferencesModel::setupConnections() vstConfiguration()->userVstDirectoriesChanged().onReceive(this, [this](const io::paths_t& paths) { setFolderPaths(FolderType::VST3, pathsToString(paths)); }); - - videoEncoderResolver()->loadedFFmpegChanged().onNotify(this, [this]() { - emit ffmpegVersionChanged(); - emit ffmpegDirChanged(); - }); - - emit ffmpegVersionChanged(); - emit ffmpegDirChanged(); } void FoldersPreferencesModel::saveFolderPaths(FoldersPreferencesModel::FolderType folderType, const QString& paths) @@ -252,27 +244,3 @@ io::paths_t FoldersPreferencesModel::pathsFromString(const QString& pathsStr) co { return io::pathsFromString(pathsStr.toStdString()); } - -int FoldersPreferencesModel::ffmpegVersion() const -{ - return videoEncoderResolver()->loadedFFmpegVersion(); -} - -QString FoldersPreferencesModel::ffmpegDir() const -{ - return videoEncoderResolver()->loadedFFmpegDir().toQString(); -} - -void FoldersPreferencesModel::setFFmpegDir(const QString& dir) -{ - if (mediaConfiguration()->ffmpegLibsDir() == dir) { - return; - } - - videoEncoderResolver()->loadFFmpeg(dir); -} - -bool FoldersPreferencesModel::showFFmpegSection() const -{ - return appliaction()->unstable(); -} diff --git a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h index 6cf9e36ceb4bb..9248d7f7d8337 100644 --- a/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h +++ b/src/preferences/qml/MuseScore/Preferences/folderspreferencesmodel.h @@ -28,15 +28,12 @@ #include "async/asyncable.h" #include "modularity/ioc.h" -#include "iapplication.h" #include "iglobalconfiguration.h" #include "project/iprojectconfiguration.h" #include "notation/inotationconfiguration.h" #include "extensions/iextensionsconfiguration.h" #include "audio/main/iaudioconfiguration.h" #include "vst/ivstconfiguration.h" -#include "media/imediaconfiguration.h" -#include "media/ivideoencoderresolver.h" namespace mu::preferences { class FoldersPreferencesModel : public QAbstractListModel, public muse::Contextable, public muse::async::Asyncable @@ -50,13 +47,6 @@ class FoldersPreferencesModel : public QAbstractListModel, public muse::Contexta muse::GlobalInject extensionsConfiguration; muse::GlobalInject audioConfiguration; muse::GlobalInject vstConfiguration; - muse::GlobalInject mediaConfiguration; - muse::GlobalInject appliaction; - muse::ContextInject videoEncoderResolver = { this }; - - Q_PROPERTY(bool showFFmpegSection READ showFFmpegSection CONSTANT FINAL) - Q_PROPERTY(int ffmpegVersion READ ffmpegVersion NOTIFY ffmpegVersionChanged FINAL) - Q_PROPERTY(QString ffmpegDir READ ffmpegDir WRITE setFFmpegDir NOTIFY ffmpegDirChanged FINAL) public: explicit FoldersPreferencesModel(QObject* parent = nullptr); @@ -68,17 +58,6 @@ class FoldersPreferencesModel : public QAbstractListModel, public muse::Contexta Q_INVOKABLE void load(); - int ffmpegVersion() const; - - QString ffmpegDir() const; - void setFFmpegDir(const QString& dir); - - bool showFFmpegSection() const; - -signals: - void ffmpegVersionChanged(); - void ffmpegDirChanged(); - private: void setupConnections(); diff --git a/src/preferences/qml/MuseScore/Preferences/internal/FFmpegSection.qml b/src/preferences/qml/MuseScore/Preferences/internal/FFmpegSection.qml index 6957930211e5a..a52e0f1a178d2 100644 --- a/src/preferences/qml/MuseScore/Preferences/internal/FFmpegSection.qml +++ b/src/preferences/qml/MuseScore/Preferences/internal/FFmpegSection.qml @@ -27,12 +27,10 @@ import Muse.UiComponents BaseSection { id: root - title: qsTrc("preferences", "FFmpeg") + title: qsTrc("preferences", "Video converter") property var model: null - visible: model ? model.showFFmpegSection : false - ColumnLayout { width: parent.width height: 30 @@ -42,9 +40,9 @@ BaseSection { StyledTextLabel { id: titleLabel Layout.fillWidth: true - text: qsTrc("preferences", "Version:") + " " + (model && model.ffmpegVersion !== -1 - ? model.ffmpegVersion - : qsTrc("preferences", "FFmpeg library not found")) + text: qsTrc("preferences", "FFmpeg library version:") + " " + (model && model.ffmpegVersion !== -1 + ? model.ffmpegVersion + : qsTrc("preferences", "FFmpeg library not found")) horizontalAlignment: Text.AlignLeft } @@ -61,6 +59,9 @@ BaseSection { pickerType: FilePicker.PickerType.Directory dialogTitle: qsTrc("preferences", "Choose %1 folder").arg(root.title) + buttonType: FlatButton.TextOnly + buttonText: qsTrc("preferences", "Locate existing installation") + dir: model ? model.ffmpegDir : "" path: model ? model.ffmpegDir : "" diff --git a/src/preferences/qml/MuseScore/Preferences/preferencesmodel.cpp b/src/preferences/qml/MuseScore/Preferences/preferencesmodel.cpp index 6cf8e8004ffe6..508868e3d4255 100644 --- a/src/preferences/qml/MuseScore/Preferences/preferencesmodel.cpp +++ b/src/preferences/qml/MuseScore/Preferences/preferencesmodel.cpp @@ -176,6 +176,9 @@ void PreferencesModel::load(const QString& currentPageId) makeItem("midi-device-mapping", QT_TRANSLATE_NOOP("preferences", "MIDI mappings"), IconCode::Code::MIDI_INPUT, "Preferences/MidiDeviceMappingPreferencesPage.qml"), + makeItem("video", QT_TRANSLATE_NOOP("preferences", "Video"), IconCode::Code::VIDEO, + "Preferences/VideoPreferencesPage.qml"), + makeItem("percussion", QT_TRANSLATE_NOOP("preferences", "Percussion"), IconCode::Code::PERCUSSION, "Preferences/PercussionPreferencesPage.qml"), diff --git a/src/preferences/qml/MuseScore/Preferences/videopreferencesmodel.cpp b/src/preferences/qml/MuseScore/Preferences/videopreferencesmodel.cpp new file mode 100644 index 0000000000000..cb15467e81e3e --- /dev/null +++ b/src/preferences/qml/MuseScore/Preferences/videopreferencesmodel.cpp @@ -0,0 +1,60 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "videopreferencesmodel.h" + +using namespace mu::preferences; + +VideoPreferencesModel::VideoPreferencesModel(QObject* parent) + : QObject(parent), muse::Contextable(muse::iocCtxForQmlObject(this)) +{ +} + +void VideoPreferencesModel::load() +{ + videoEncoderResolver()->loadedFFmpegChanged().onNotify(this, [this]() { + emit ffmpegVersionChanged(); + emit ffmpegDirChanged(); + }); + + emit ffmpegVersionChanged(); + emit ffmpegDirChanged(); +} + +int VideoPreferencesModel::ffmpegVersion() const +{ + return videoEncoderResolver()->loadedFFmpegVersion(); +} + +QString VideoPreferencesModel::ffmpegDir() const +{ + return videoEncoderResolver()->loadedFFmpegDir().toQString(); +} + +void VideoPreferencesModel::setFFmpegDir(const QString& dir) +{ + if (ffmpegDir() == dir) { + return; + } + + videoEncoderResolver()->loadFFmpeg(dir); +} diff --git a/src/preferences/qml/MuseScore/Preferences/videopreferencesmodel.h b/src/preferences/qml/MuseScore/Preferences/videopreferencesmodel.h new file mode 100644 index 0000000000000..3c8955daadf19 --- /dev/null +++ b/src/preferences/qml/MuseScore/Preferences/videopreferencesmodel.h @@ -0,0 +1,58 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include + +#include + +#include "async/asyncable.h" + +#include "modularity/ioc.h" +#include "media/ivideoencoderresolver.h" + +namespace mu::preferences { +class VideoPreferencesModel : public QObject, public muse::Contextable, public muse::async::Asyncable +{ + Q_OBJECT + QML_ELEMENT; + + muse::ContextInject videoEncoderResolver = { this }; + + Q_PROPERTY(int ffmpegVersion READ ffmpegVersion NOTIFY ffmpegVersionChanged FINAL) + Q_PROPERTY(QString ffmpegDir READ ffmpegDir WRITE setFFmpegDir NOTIFY ffmpegDirChanged FINAL) + +public: + explicit VideoPreferencesModel(QObject* parent = nullptr); + + Q_INVOKABLE void load(); + + int ffmpegVersion() const; + + QString ffmpegDir() const; + void setFFmpegDir(const QString& dir); + +signals: + void ffmpegVersionChanged(); + void ffmpegDirChanged(); +}; +} From 35b11826e8db9af176cfce2d4039fdafd0c9241d Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 16 Mar 2026 16:35:31 +0200 Subject: [PATCH 36/52] moved AutomaticUpdateSection to General page --- .../qml/MuseScore/Preferences/CMakeLists.txt | 3 - .../Preferences/GeneralPreferencesPage.qml | 15 +++++ .../Preferences/UpdatePreferencesPage.qml | 58 ----------------- .../Preferences/generalpreferencesmodel.cpp | 29 +++++++++ .../Preferences/generalpreferencesmodel.h | 12 ++++ .../Preferences/preferencesmodel.cpp | 3 - .../Preferences/updatepreferencesmodel.cpp | 62 ------------------- .../Preferences/updatepreferencesmodel.h | 59 ------------------ 8 files changed, 56 insertions(+), 185 deletions(-) delete mode 100644 src/preferences/qml/MuseScore/Preferences/UpdatePreferencesPage.qml delete mode 100644 src/preferences/qml/MuseScore/Preferences/updatepreferencesmodel.cpp delete mode 100644 src/preferences/qml/MuseScore/Preferences/updatepreferencesmodel.h diff --git a/src/preferences/qml/MuseScore/Preferences/CMakeLists.txt b/src/preferences/qml/MuseScore/Preferences/CMakeLists.txt index e60376384f2eb..6d89b3cdc32fc 100644 --- a/src/preferences/qml/MuseScore/Preferences/CMakeLists.txt +++ b/src/preferences/qml/MuseScore/Preferences/CMakeLists.txt @@ -56,8 +56,6 @@ qt_add_qml_module(preferences_qml saveandpublishpreferencesmodel.h scorepreferencesmodel.cpp scorepreferencesmodel.h - updatepreferencesmodel.cpp - updatepreferencesmodel.h videopreferencesmodel.cpp videopreferencesmodel.h QML_FILES @@ -79,7 +77,6 @@ qt_add_qml_module(preferences_qml ScorePreferencesPage.qml ShortcutsPreferencesPage.qml ThemeSamplesList.qml - UpdatePreferencesPage.qml VideoPreferencesPage.qml internal/AccentColorsSection.qml diff --git a/src/preferences/qml/MuseScore/Preferences/GeneralPreferencesPage.qml b/src/preferences/qml/MuseScore/Preferences/GeneralPreferencesPage.qml index cd31c362297c7..cdbdca0c75da3 100644 --- a/src/preferences/qml/MuseScore/Preferences/GeneralPreferencesPage.qml +++ b/src/preferences/qml/MuseScore/Preferences/GeneralPreferencesPage.qml @@ -119,5 +119,20 @@ PreferencesPage { preferencesModel.oscPort = port } }*/ + + SeparatorLine { } + + AutomaticUpdateSection { + isAppUpdatable: preferencesModel.isAppUpdatable() + needCheckForNewAppVersion: preferencesModel.needCheckForNewAppVersion + museScorePrivacyPolicyUrl: preferencesModel.museScorePrivacyPolicyUrl() + + navigation.section: root.navigationSection + navigation.order: root.navigationOrderStart + 4 + + onNeedCheckForNewAppVersionChangeRequested: function(check) { + preferencesModel.needCheckForNewAppVersion = check + } + } } } diff --git a/src/preferences/qml/MuseScore/Preferences/UpdatePreferencesPage.qml b/src/preferences/qml/MuseScore/Preferences/UpdatePreferencesPage.qml deleted file mode 100644 index 85dd4ec647707..0000000000000 --- a/src/preferences/qml/MuseScore/Preferences/UpdatePreferencesPage.qml +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0-only - * MuseScore-Studio-CLA-applies - * - * MuseScore Studio - * Music Composition & Notation - * - * Copyright (C) 2021 MuseScore Limited - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -import QtQuick - -import Muse.Ui -import Muse.UiComponents -import MuseScore.Preferences - -import "internal" - -PreferencesPage { - id: root - - UpdatePreferencesModel { - id: updateModel - } - - Component.onCompleted: { - updateModel.load() - } - - Column { - width: parent.width - spacing: root.sectionsSpacing - - AutomaticUpdateSection { - isAppUpdatable: updateModel.isAppUpdatable() - needCheckForNewAppVersion: updateModel.needCheckForNewAppVersion - museScorePrivacyPolicyUrl: updateModel.museScorePrivacyPolicyUrl() - - navigation.section: root.navigationSection - navigation.order: root.navigationOrderStart + 1 - - onNeedCheckForNewAppVersionChangeRequested: function(check) { - updateModel.needCheckForNewAppVersion = check - } - } - } -} diff --git a/src/preferences/qml/MuseScore/Preferences/generalpreferencesmodel.cpp b/src/preferences/qml/MuseScore/Preferences/generalpreferencesmodel.cpp index 5484d22e2007f..fe9050d69dacd 100644 --- a/src/preferences/qml/MuseScore/Preferences/generalpreferencesmodel.cpp +++ b/src/preferences/qml/MuseScore/Preferences/generalpreferencesmodel.cpp @@ -57,6 +57,10 @@ void GeneralPreferencesModel::load() configuration()->welcomeDialogShowOnStartupChanged().onNotify(this, [this]() { emit showWelcomeDialogChanged(); }); + + updateConfiguration()->needCheckForUpdateChanged().onNotify(this, [this]() { + emit needCheckForNewAppVersionChanged(needCheckForNewAppVersion()); + }); } void GeneralPreferencesModel::checkUpdateForCurrentLanguage() @@ -258,3 +262,28 @@ void GeneralPreferencesModel::setShowWelcomeDialog(bool show) configuration()->setWelcomeDialogShowOnStartup(show); } + +bool GeneralPreferencesModel::isAppUpdatable() const +{ + return updateConfiguration()->isAppUpdatable(); +} + +bool GeneralPreferencesModel::needCheckForNewAppVersion() const +{ + return updateConfiguration()->needCheckForUpdate(); +} + +void GeneralPreferencesModel::setNeedCheckForNewAppVersion(bool value) +{ + if (value == needCheckForNewAppVersion()) { + return; + } + + updateConfiguration()->setNeedCheckForUpdate(value); + emit needCheckForNewAppVersionChanged(value); +} + +QString GeneralPreferencesModel::museScorePrivacyPolicyUrl() const +{ + return QString::fromStdString(updateConfiguration()->museScorePrivacyPolicyUrl()); +} diff --git a/src/preferences/qml/MuseScore/Preferences/generalpreferencesmodel.h b/src/preferences/qml/MuseScore/Preferences/generalpreferencesmodel.h index 817e660097a3f..e4a6463a10188 100644 --- a/src/preferences/qml/MuseScore/Preferences/generalpreferencesmodel.h +++ b/src/preferences/qml/MuseScore/Preferences/generalpreferencesmodel.h @@ -35,6 +35,7 @@ #include "languages/ilanguagesconfiguration.h" #include "languages/ilanguagesservice.h" #include "shortcuts/ishortcutsconfiguration.h" +#include "update/iupdateconfiguration.h" namespace mu::preferences { class GeneralPreferencesModel : public QObject, public muse::Contextable, public muse::async::Asyncable @@ -60,10 +61,14 @@ class GeneralPreferencesModel : public QObject, public muse::Contextable, public Q_PROPERTY(bool showWelcomeDialog READ showWelcomeDialog WRITE setShowWelcomeDialog NOTIFY showWelcomeDialogChanged) + Q_PROPERTY( + bool needCheckForNewAppVersion READ needCheckForNewAppVersion WRITE setNeedCheckForNewAppVersion NOTIFY needCheckForNewAppVersionChanged) + muse::GlobalInject configuration; muse::GlobalInject languagesConfiguration; muse::GlobalInject shortcutsConfiguration; muse::GlobalInject languagesService; + muse::GlobalInject updateConfiguration; muse::ContextInject interactive = { this }; public: @@ -90,6 +95,10 @@ class GeneralPreferencesModel : public QObject, public muse::Contextable, public bool showWelcomeDialog() const; void setShowWelcomeDialog(bool show); + bool needCheckForNewAppVersion() const; + Q_INVOKABLE bool isAppUpdatable() const; + Q_INVOKABLE QString museScorePrivacyPolicyUrl() const; + public slots: void setCurrentLanguageCode(const QString& currentLanguageCode); void setCurrentKeyboardLayout(const QString& keyboardLayout); @@ -98,6 +107,7 @@ public slots: void setRestartRequired(bool restartRequired); void setCurrentStartupMode(int mode); void setStartupScorePath(const QString& scorePath); + void setNeedCheckForNewAppVersion(bool value); signals: void languagesChanged(QVariantList languages); @@ -114,6 +124,8 @@ public slots: void showWelcomeDialogChanged(); + void needCheckForNewAppVersionChanged(bool value); + private: muse::Progress m_languageUpdateProgress; diff --git a/src/preferences/qml/MuseScore/Preferences/preferencesmodel.cpp b/src/preferences/qml/MuseScore/Preferences/preferencesmodel.cpp index 508868e3d4255..743672cf0d842 100644 --- a/src/preferences/qml/MuseScore/Preferences/preferencesmodel.cpp +++ b/src/preferences/qml/MuseScore/Preferences/preferencesmodel.cpp @@ -188,9 +188,6 @@ void PreferencesModel::load(const QString& currentPageId) makeItem("shortcuts", QT_TRANSLATE_NOOP("preferences", "Shortcuts"), IconCode::Code::SHORTCUTS, "Preferences/ShortcutsPreferencesPage.qml"), - makeItem("update", QT_TRANSLATE_NOOP("preferences", "Update"), IconCode::Code::UPDATE, - "Preferences/UpdatePreferencesPage.qml"), - makeItem("general-folders", QT_TRANSLATE_NOOP("preferences", "Folders"), IconCode::Code::OPEN_FILE, "Preferences/FoldersPreferencesPage.qml"), diff --git a/src/preferences/qml/MuseScore/Preferences/updatepreferencesmodel.cpp b/src/preferences/qml/MuseScore/Preferences/updatepreferencesmodel.cpp deleted file mode 100644 index 7fdf0ff21b695..0000000000000 --- a/src/preferences/qml/MuseScore/Preferences/updatepreferencesmodel.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0-only - * MuseScore-Studio-CLA-applies - * - * MuseScore Studio - * Music Composition & Notation - * - * Copyright (C) 2021 MuseScore Limited - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "updatepreferencesmodel.h" - -using namespace mu::preferences; - -UpdatePreferencesModel::UpdatePreferencesModel(QObject* parent) - : QObject(parent), muse::Contextable(muse::iocCtxForQmlObject(this)) -{ -} - -void UpdatePreferencesModel::load() -{ - updateConfiguration()->needCheckForUpdateChanged().onNotify(this, [this]() { - emit needCheckForNewAppVersionChanged(needCheckForNewAppVersion()); - }); -} - -bool UpdatePreferencesModel::isAppUpdatable() const -{ - return updateConfiguration()->isAppUpdatable(); -} - -bool UpdatePreferencesModel::needCheckForNewAppVersion() const -{ - return updateConfiguration()->needCheckForUpdate(); -} - -void UpdatePreferencesModel::setNeedCheckForNewAppVersion(bool value) -{ - if (value == needCheckForNewAppVersion()) { - return; - } - - updateConfiguration()->setNeedCheckForUpdate(value); - emit needCheckForNewAppVersionChanged(value); -} - -QString UpdatePreferencesModel::museScorePrivacyPolicyUrl() const -{ - return QString::fromStdString(updateConfiguration()->museScorePrivacyPolicyUrl()); -} diff --git a/src/preferences/qml/MuseScore/Preferences/updatepreferencesmodel.h b/src/preferences/qml/MuseScore/Preferences/updatepreferencesmodel.h deleted file mode 100644 index 3959e9f7c8d8f..0000000000000 --- a/src/preferences/qml/MuseScore/Preferences/updatepreferencesmodel.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0-only - * MuseScore-Studio-CLA-applies - * - * MuseScore Studio - * Music Composition & Notation - * - * Copyright (C) 2021 MuseScore Limited - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include - -#include - -#include "async/asyncable.h" -#include "modularity/ioc.h" -#include "update/iupdateconfiguration.h" - -namespace mu::preferences { -class UpdatePreferencesModel : public QObject, public muse::Contextable, public muse::async::Asyncable -{ - Q_OBJECT - QML_ELEMENT; - - Q_PROPERTY( - bool needCheckForNewAppVersion READ needCheckForNewAppVersion WRITE setNeedCheckForNewAppVersion NOTIFY needCheckForNewAppVersionChanged) - - muse::GlobalInject updateConfiguration; - -public: - explicit UpdatePreferencesModel(QObject* parent = nullptr); - - Q_INVOKABLE void load(); - - bool needCheckForNewAppVersion() const; - - Q_INVOKABLE bool isAppUpdatable() const; - Q_INVOKABLE QString museScorePrivacyPolicyUrl() const; - -public slots: - void setNeedCheckForNewAppVersion(bool value); - -signals: - void needCheckForNewAppVersionChanged(bool value); -}; -} From eabf85ec908603ff7619509acdde53b0625e5f40 Mon Sep 17 00:00:00 2001 From: Elnur Ismailzada Date: Tue, 17 Mar 2026 11:27:39 +0200 Subject: [PATCH 37/52] fixed find libraries for linux --- src/framework/media/internal/ffmpegutils.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/framework/media/internal/ffmpegutils.cpp b/src/framework/media/internal/ffmpegutils.cpp index de9b2d98924ac..869921f5f2d97 100644 --- a/src/framework/media/internal/ffmpegutils.cpp +++ b/src/framework/media/internal/ffmpegutils.cpp @@ -47,8 +47,6 @@ static io::paths_t defaultSearchPaths() static FFmpegLibPaths libraryPathsForVersion(int ffmpegVer, const io::path_t& searchDir) { - const std::string verStr = std::to_string(ffmpegVer); - FFmpegVersionInfo ffmpegVersionInfo; for (const auto& [ffmpegVersion, componentsVersions] : FFMPEG_COMPONENTS_VERSIONS) { if (ffmpegVersion == ffmpegVer) { @@ -71,7 +69,7 @@ static FFmpegLibPaths libraryPathsForVersion(int ffmpegVer, const io::path_t& se #elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) avutilName = io::path_t("libavutil.so." + std::to_string(ffmpegVersionInfo.avUtilVersion)); avcodecName = io::path_t("libavcodec.so." + std::to_string(ffmpegVersionInfo.avCodecVersion)); - avformatName = io::path_t("libavformat.so." + verStr); + avformatName = io::path_t("libavformat.so." + std::to_string(ffmpegVersionInfo.avFormatVersion)); swscaleName = io::path_t("libswscale.so." + std::to_string(ffmpegVersionInfo.swScaleVersion)); swresampleName = io::path_t("libswresample.so." + std::to_string(ffmpegVersionInfo.swResampleVersion)); #elif defined(Q_OS_WIN) From 502815b6cf7b66a91b16363188bd20ba2852e096 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 11:23:56 +0200 Subject: [PATCH 38/52] fixed mp4 option in export dialog --- .../internal/Export/exportdialogmodel.cpp | 17 ++++++----------- .../Project/internal/Export/exportdialogmodel.h | 1 - 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp index 5a036031773ad..84eb28eb1e034 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp +++ b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp @@ -91,6 +91,12 @@ ExportDialogModel::ExportDialogModel(QObject* parent) muse::qtrc("project/export", "FLAC audio"), muse::qtrc("project/export", "FLAC audio files"), "FlacSettingsPage.qml"), +#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE + ExportType::makeWithSuffixes({ "mp4" }, + muse::qtrc("project/export", "MP4 video"), + muse::qtrc("project/export", "MP4 video"), + "Mp4SettingsPage.qml"), +#endif ExportType::makeWithSuffixes({ "mid", "midi", "kar" }, muse::qtrc("project/export", "MIDI file"), muse::qtrc("project/export", "MIDI files"), @@ -116,17 +122,6 @@ ExportDialogModel::ExportDialogModel(QObject* parent) muse::qtrc("project/export", "LRC files"), "LrcSettingsPage.qml") }; - -#ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE - if (application()->unstable()) { - m_exportTypeList.push_back( - ExportType::makeWithSuffixes({ "mp4" }, - muse::qtrc("project/export", "Video mp4"), - muse::qtrc("project/export", "Video mp4 files"), - "Mp4SettingsPage.qml") - ); - } -#endif } ExportDialogModel::~ExportDialogModel() diff --git a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h index e6c62409be579..aaa090131b217 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h +++ b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.h @@ -33,7 +33,6 @@ #include "async/asyncable.h" #include "interactive/iinteractive.h" -#include "iapplication.h" #include "context/iglobalcontext.h" #include "importexport/imagesexport/iimagesexportconfiguration.h" #include "importexport/musicxml/imusicxmlconfiguration.h" From 475c321794486fcb33dedaf846f1b104785ece90 Mon Sep 17 00:00:00 2001 From: Eism Date: Tue, 17 Mar 2026 13:55:29 +0200 Subject: [PATCH 39/52] removed redundant version and directory tracking from ffmpeg handlers --- .../internal/ffmpeg/v4/ffmpeglibhandler.cpp | 2 -- .../media/internal/ffmpeg/v4/ffmpeglibhandler.h | 8 -------- .../media/internal/ffmpeg/v4/videoencoder.cpp | 5 +---- .../media/internal/ffmpeg/v4/videoencoder.h | 2 +- .../internal/ffmpeg/v5/ffmpeglibhandler.cpp | 2 -- .../media/internal/ffmpeg/v5/ffmpeglibhandler.h | 8 -------- .../media/internal/ffmpeg/v5/videoencoder.cpp | 5 +---- .../media/internal/ffmpeg/v5/videoencoder.h | 2 +- .../internal/ffmpeg/v6/ffmpeglibhandler.cpp | 2 -- .../media/internal/ffmpeg/v6/ffmpeglibhandler.h | 8 -------- .../media/internal/ffmpeg/v6/videoencoder.cpp | 5 +---- .../media/internal/ffmpeg/v6/videoencoder.h | 2 +- .../internal/ffmpeg/v7/ffmpeglibhandler.cpp | 2 -- .../media/internal/ffmpeg/v7/ffmpeglibhandler.h | 8 -------- .../media/internal/ffmpeg/v7/videoencoder.cpp | 5 +---- .../media/internal/ffmpeg/v7/videoencoder.h | 2 +- .../internal/ffmpeg/v8/ffmpeglibhandler.cpp | 2 -- .../media/internal/ffmpeg/v8/ffmpeglibhandler.h | 8 -------- .../media/internal/ffmpeg/v8/videoencoder.cpp | 5 +---- .../media/internal/ffmpeg/v8/videoencoder.h | 2 +- .../media/internal/videoencoderresolver.cpp | 16 +++++++++------- 21 files changed, 19 insertions(+), 82 deletions(-) diff --git a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp index 9cdd3dec9d3cb..a280114fc8ea1 100644 --- a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp @@ -138,8 +138,6 @@ void FFmpegLibHandler::unload() closeLib(m_avUtilLibrary); clearFunctions(); - m_version = 0; - m_dir = io::path_t(); } void FFmpegLibHandler::closeLib(void*& lib) diff --git a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h index 69b62ce15adf6..fd8a9e09ac22d 100644 --- a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h @@ -41,12 +41,6 @@ class FFmpegLibHandler bool loadApi(); void unload(); - int version() const { return m_version; } - void setVersion(int version) { m_version = version; } - - io::path_t dir() const { return m_dir; } - void setDir(const io::path_t& dir) { m_dir = dir; } - // libavutil void (*av_free)(void* ptr) = nullptr; void (*av_freep)(void* ptr) = nullptr; @@ -111,7 +105,5 @@ private : void* getSymbol(void* lib, const char* name) const; void* m_swsScaleLibrary = nullptr; void* m_swResampleLibrary = nullptr; - int m_version = 0; - io::path_t m_dir; }; } diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp index 4710f1b185baa..d609fe9f7e521 100644 --- a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp @@ -60,7 +60,7 @@ VideoEncoder::~VideoEncoder() delete m_ffmpeg; } -bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) +bool VideoEncoder::load(const FFmpegLibPaths& paths) { auto handler = std::make_shared(); if (!handler->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, @@ -69,10 +69,7 @@ bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) LOGW() << "FFmpeg libraries not found"; return false; } - handler->setVersion(version); - handler->setDir(io::dirpath(paths.avFormatPath)); m_ffmpegHandler = std::move(handler); - LOGD() << "FFmpeg loaded, version: " << m_ffmpegHandler->version(); return true; } diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.h b/src/framework/media/internal/ffmpeg/v4/videoencoder.h index 265af07a35409..1df26f330c7d5 100644 --- a/src/framework/media/internal/ffmpeg/v4/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.h @@ -35,7 +35,7 @@ class VideoEncoder : public IVideoEncoder VideoEncoder(); ~VideoEncoder() override; - bool load(const FFmpegLibPaths& paths, int version); + bool load(const FFmpegLibPaths& paths); bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; void close() override; diff --git a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp index 5c07ac29b0210..ff26a5dbe125d 100644 --- a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp @@ -138,8 +138,6 @@ void FFmpegLibHandler::unload() closeLib(m_avUtilLibrary); clearFunctions(); - m_version = 0; - m_dir = io::path_t(); } void FFmpegLibHandler::closeLib(void*& lib) diff --git a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h index 7549992323f00..6a3066af520a2 100644 --- a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h @@ -41,12 +41,6 @@ class FFmpegLibHandler bool loadApi(); void unload(); - int version() const { return m_version; } - void setVersion(int version) { m_version = version; } - - io::path_t dir() const { return m_dir; } - void setDir(const io::path_t& dir) { m_dir = dir; } - // libavutil void (*av_free)(void* ptr) = nullptr; void (*av_freep)(void* ptr) = nullptr; @@ -111,7 +105,5 @@ private : void* getSymbol(void* lib, const char* name) const; void* m_swsScaleLibrary = nullptr; void* m_swResampleLibrary = nullptr; - int m_version = 0; - io::path_t m_dir; }; } diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp index 9892f7a5f650f..eff5a7e1c6a5d 100644 --- a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp @@ -60,7 +60,7 @@ VideoEncoder::~VideoEncoder() delete m_ffmpeg; } -bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) +bool VideoEncoder::load(const FFmpegLibPaths& paths) { auto handler = std::make_shared(); if (!handler->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, @@ -69,10 +69,7 @@ bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) LOGW() << "FFmpeg libraries not found"; return false; } - handler->setVersion(version); - handler->setDir(io::dirpath(paths.avFormatPath)); m_ffmpegHandler = std::move(handler); - LOGD() << "FFmpeg loaded, version: " << m_ffmpegHandler->version(); return true; } diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.h b/src/framework/media/internal/ffmpeg/v5/videoencoder.h index e1e328f478b9b..e9312e847d832 100644 --- a/src/framework/media/internal/ffmpeg/v5/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.h @@ -35,7 +35,7 @@ class VideoEncoder : public IVideoEncoder VideoEncoder(); ~VideoEncoder() override; - bool load(const FFmpegLibPaths& paths, int version); + bool load(const FFmpegLibPaths& paths); bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; void close() override; diff --git a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp index 5d8f83095b75e..e5b06837010cd 100644 --- a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp @@ -138,8 +138,6 @@ void FFmpegLibHandler::unload() closeLib(m_avUtilLibrary); clearFunctions(); - m_version = 0; - m_dir = io::path_t(); } void FFmpegLibHandler::closeLib(void*& lib) diff --git a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h index b48495820135f..c6702dbc4abbe 100644 --- a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h @@ -41,12 +41,6 @@ class FFmpegLibHandler bool loadApi(); void unload(); - int version() const { return m_version; } - void setVersion(int version) { m_version = version; } - - io::path_t dir() const { return m_dir; } - void setDir(const io::path_t& dir) { m_dir = dir; } - // libavutil void (*av_free)(void* ptr) = nullptr; void (*av_freep)(void* ptr) = nullptr; @@ -111,7 +105,5 @@ private : void* getSymbol(void* lib, const char* name) const; void* m_swsScaleLibrary = nullptr; void* m_swResampleLibrary = nullptr; - int m_version = 0; - io::path_t m_dir; }; } diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp index 925bb5870bd5f..5a47fac5c59e5 100644 --- a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp @@ -60,7 +60,7 @@ VideoEncoder::~VideoEncoder() delete m_ffmpeg; } -bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) +bool VideoEncoder::load(const FFmpegLibPaths& paths) { auto handler = std::make_shared(); if (!handler->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, @@ -69,10 +69,7 @@ bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) LOGW() << "FFmpeg libraries not found"; return false; } - handler->setVersion(version); - handler->setDir(io::dirpath(paths.avFormatPath)); m_ffmpegHandler = std::move(handler); - LOGD() << "FFmpeg loaded, version: " << m_ffmpegHandler->version(); return true; } diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.h b/src/framework/media/internal/ffmpeg/v6/videoencoder.h index 379c3023b4b20..b06517dd66af0 100644 --- a/src/framework/media/internal/ffmpeg/v6/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.h @@ -35,7 +35,7 @@ class VideoEncoder : public IVideoEncoder VideoEncoder(); ~VideoEncoder() override; - bool load(const FFmpegLibPaths& paths, int version); + bool load(const FFmpegLibPaths& paths); bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; void close() override; diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp index 9da02a0ecc32d..5514cad4eb75a 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp @@ -138,8 +138,6 @@ void FFmpegLibHandler::unload() closeLib(m_avUtilLibrary); clearFunctions(); - m_version = 0; - m_dir = io::path_t(); } void FFmpegLibHandler::closeLib(void*& lib) diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h index 06f98c6bbb8c1..5de5675050528 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h @@ -41,12 +41,6 @@ class FFmpegLibHandler bool loadApi(); void unload(); - int version() const { return m_version; } - void setVersion(int version) { m_version = version; } - - io::path_t dir() const { return m_dir; } - void setDir(const io::path_t& dir) { m_dir = dir; } - // libavutil void (*av_free)(void* ptr) = nullptr; void (*av_freep)(void* ptr) = nullptr; @@ -111,7 +105,5 @@ private : void* getSymbol(void* lib, const char* name) const; void* m_swsScaleLibrary = nullptr; void* m_swResampleLibrary = nullptr; - int m_version = 0; - io::path_t m_dir; }; } diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp index b1ebc64e100e2..cad636e452636 100644 --- a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp @@ -60,7 +60,7 @@ VideoEncoder::~VideoEncoder() delete m_ffmpeg; } -bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) +bool VideoEncoder::load(const FFmpegLibPaths& paths) { auto handler = std::make_shared(); if (!handler->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, @@ -69,10 +69,7 @@ bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) LOGW() << "FFmpeg libraries not found"; return false; } - handler->setVersion(version); - handler->setDir(io::dirpath(paths.avFormatPath)); m_ffmpegHandler = std::move(handler); - LOGD() << "FFmpeg loaded, version: " << m_ffmpegHandler->version(); return true; } diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.h b/src/framework/media/internal/ffmpeg/v7/videoencoder.h index b1b1a33ce05f6..5e36720a58a5e 100644 --- a/src/framework/media/internal/ffmpeg/v7/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.h @@ -35,7 +35,7 @@ class VideoEncoder : public IVideoEncoder VideoEncoder(); ~VideoEncoder() override; - bool load(const FFmpegLibPaths& paths, int version); + bool load(const FFmpegLibPaths& paths); bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; void close() override; diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp index 52be48ba1b25b..518faaa975d17 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp @@ -136,8 +136,6 @@ void FFmpegLibHandler::unload() closeLib(m_avUtilLibrary); clearFunctions(); - m_version = 0; - m_dir = io::path_t(); } void FFmpegLibHandler::closeLib(void*& lib) diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h index 1151b44161f0f..1db618550fd48 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h @@ -41,12 +41,6 @@ class FFmpegLibHandler bool loadApi(); void unload(); - int version() const { return m_version; } - void setVersion(int version) { m_version = version; } - - io::path_t dir() const { return m_dir; } - void setDir(const io::path_t& dir) { m_dir = dir; } - // libavutil void (*av_free)(void* ptr) = nullptr; void (*av_freep)(void* ptr) = nullptr; @@ -109,7 +103,5 @@ private : void* getSymbol(void* lib, const char* name) const; void* m_swsScaleLibrary = nullptr; void* m_swResampleLibrary = nullptr; - int m_version = 0; - io::path_t m_dir; }; } diff --git a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp index 632ececed0401..3f2b22c3e35bc 100644 --- a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp @@ -60,7 +60,7 @@ VideoEncoder::~VideoEncoder() delete m_ffmpeg; } -bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) +bool VideoEncoder::load(const FFmpegLibPaths& paths) { auto handler = std::make_shared(); if (!handler->loadLib(paths.avUtilPath, paths.avCodecPath, paths.avFormatPath, @@ -69,10 +69,7 @@ bool VideoEncoder::load(const FFmpegLibPaths& paths, int version) LOGW() << "FFmpeg libraries not found"; return false; } - handler->setVersion(version); - handler->setDir(io::dirpath(paths.avFormatPath)); m_ffmpegHandler = std::move(handler); - LOGD() << "FFmpeg loaded, version: " << m_ffmpegHandler->version(); return true; } diff --git a/src/framework/media/internal/ffmpeg/v8/videoencoder.h b/src/framework/media/internal/ffmpeg/v8/videoencoder.h index 3955290cb2216..8e5b38ee63e51 100644 --- a/src/framework/media/internal/ffmpeg/v8/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.h @@ -35,7 +35,7 @@ class VideoEncoder : public IVideoEncoder VideoEncoder(); ~VideoEncoder() override; - bool load(const FFmpegLibPaths& paths, int version); + bool load(const FFmpegLibPaths& paths); bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; void close() override; diff --git a/src/framework/media/internal/videoencoderresolver.cpp b/src/framework/media/internal/videoencoderresolver.cpp index a8f2c64095e5d..e89e17e739f8a 100644 --- a/src/framework/media/internal/videoencoderresolver.cpp +++ b/src/framework/media/internal/videoencoderresolver.cpp @@ -92,10 +92,10 @@ void VideoEncoderResolver::resetFFmpegSettings() } template -static IVideoEncoderPtr tryCreateEncoder(const FFmpegLibPaths& paths, int version) +static IVideoEncoderPtr tryCreateEncoder(const FFmpegLibPaths& paths) { auto encoder = std::make_shared(); - if (encoder->load(paths, version)) { + if (encoder->load(paths)) { return encoder; } return nullptr; @@ -108,19 +108,19 @@ VideoEncoderResolver::EncoderInfo VideoEncoderResolver::makeEncoder(const FFmpeg const FFmpegVersion version = versionFromAVFormatPath(ffmpegLibsPaths.avFormatPath); switch (version) { case FFMPEG_V8: - result.encoder = tryCreateEncoder(ffmpegLibsPaths, version); + result.encoder = tryCreateEncoder(ffmpegLibsPaths); break; case FFMPEG_V7: - result.encoder = tryCreateEncoder(ffmpegLibsPaths, version); + result.encoder = tryCreateEncoder(ffmpegLibsPaths); break; case FFMPEG_V6: - result.encoder = tryCreateEncoder(ffmpegLibsPaths, version); + result.encoder = tryCreateEncoder(ffmpegLibsPaths); break; case FFMPEG_V5: - result.encoder = tryCreateEncoder(ffmpegLibsPaths, version); + result.encoder = tryCreateEncoder(ffmpegLibsPaths); break; case FFMPEG_V4: - result.encoder = tryCreateEncoder(ffmpegLibsPaths, version); + result.encoder = tryCreateEncoder(ffmpegLibsPaths); break; default: break; @@ -129,6 +129,8 @@ VideoEncoderResolver::EncoderInfo VideoEncoderResolver::makeEncoder(const FFmpeg if (result.encoder) { result.ffmpegLibsDir = io::dirpath(ffmpegLibsPaths.avFormatPath); result.ffmpegVersion = version; + + LOGD() << "FFmpeg loaded, version: " << version; } return result; From 4db1c337e75f4d76006b7e78e3b64b8ff9dd71d8 Mon Sep 17 00:00:00 2001 From: Eism Date: Tue, 17 Mar 2026 15:03:26 +0200 Subject: [PATCH 40/52] refactored video encoder to use an options struct --- .../media/internal/ffmpeg/v4/videoencoder.cpp | 24 +++++++++---------- .../media/internal/ffmpeg/v4/videoencoder.h | 2 +- .../media/internal/ffmpeg/v5/videoencoder.cpp | 24 +++++++++---------- .../media/internal/ffmpeg/v5/videoencoder.h | 2 +- .../media/internal/ffmpeg/v6/videoencoder.cpp | 24 +++++++++---------- .../media/internal/ffmpeg/v6/videoencoder.h | 2 +- .../media/internal/ffmpeg/v7/videoencoder.cpp | 24 +++++++++---------- .../media/internal/ffmpeg/v7/videoencoder.h | 2 +- .../media/internal/ffmpeg/v8/videoencoder.cpp | 24 +++++++++---------- .../media/internal/ffmpeg/v8/videoencoder.h | 2 +- src/framework/media/ivideoencoder.h | 13 +++++++++- .../stubs/media/videoencoderstub.cpp | 2 +- src/framework/stubs/media/videoencoderstub.h | 2 +- .../videoexport/internal/videowriter.cpp | 11 ++++++++- 14 files changed, 89 insertions(+), 69 deletions(-) diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp index d609fe9f7e521..06af363958895 100644 --- a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp @@ -73,14 +73,14 @@ bool VideoEncoder::load(const FFmpegLibPaths& paths) return true; } -bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) +bool VideoEncoder::open(const muse::io::path_t& fileName, const Options& options) { m_ffmpeg->ptsCounter = 0; - m_ffmpeg->width = width; - m_ffmpeg->height = height; + m_ffmpeg->width = options.width; + m_ffmpeg->height = options.height; - if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, "mp4", fileName.c_str()) < 0 + if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, options.format.c_str(), fileName.c_str()) < 0 || !m_ffmpeg->formatCtx) { LOGE() << "failed to allocate output context"; return false; @@ -93,7 +93,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } - m_ffmpeg->videoStream->time_base.den = fps; + m_ffmpeg->videoStream->time_base.den = options.fps; m_ffmpeg->videoStream->time_base.num = 1; // find the video encoder @@ -110,10 +110,10 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->videoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; m_ffmpeg->videoStream->codecpar->codec_id = AV_CODEC_ID_H264; - m_ffmpeg->videoStream->codecpar->width = width; - m_ffmpeg->videoStream->codecpar->height = height; + m_ffmpeg->videoStream->codecpar->width = options.width; + m_ffmpeg->videoStream->codecpar->height = options.height; m_ffmpeg->videoStream->codecpar->format = AV_PIX_FMT_YUV420P; - m_ffmpeg->videoStream->codecpar->bit_rate = bitrate; + m_ffmpeg->videoStream->codecpar->bit_rate = options.bitrate; if (m_ffmpegHandler->avcodec_parameters_to_context(m_ffmpeg->codecCtx, m_ffmpeg->videoStream->codecpar) < 0) { m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); @@ -122,9 +122,9 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign } m_ffmpeg->codecCtx->profile = FF_PROFILE_H264_HIGH; - m_ffmpeg->codecCtx->time_base.den = fps; + m_ffmpeg->codecCtx->time_base.den = options.fps; m_ffmpeg->codecCtx->time_base.num = 1; - m_ffmpeg->codecCtx->gop_size = gop; + m_ffmpeg->codecCtx->gop_size = options.gop; m_ffmpeg->codecCtx->thread_count = 10; m_ffmpeg->codecCtx->max_b_frames = 3; m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); @@ -165,8 +165,8 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } - m_ffmpeg->ppicture->width = width; - m_ffmpeg->ppicture->height = height; + m_ffmpeg->ppicture->width = options.width; + m_ffmpeg->ppicture->height = options.height; m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; int size = m_ffmpegHandler->av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.h b/src/framework/media/internal/ffmpeg/v4/videoencoder.h index 1df26f330c7d5..73c6964d2f1ab 100644 --- a/src/framework/media/internal/ffmpeg/v4/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.h @@ -37,7 +37,7 @@ class VideoEncoder : public IVideoEncoder bool load(const FFmpegLibPaths& paths); - bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; + bool open(const muse::io::path_t& fileName, const Options& options) override; void close() override; bool encodeImage(const QImage& img) override; diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp index eff5a7e1c6a5d..c6823bba62dac 100644 --- a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp @@ -73,14 +73,14 @@ bool VideoEncoder::load(const FFmpegLibPaths& paths) return true; } -bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) +bool VideoEncoder::open(const muse::io::path_t& fileName, const Options& options) { m_ffmpeg->ptsCounter = 0; - m_ffmpeg->width = width; - m_ffmpeg->height = height; + m_ffmpeg->width = options.width; + m_ffmpeg->height = options.height; - if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, "mp4", fileName.c_str()) < 0 + if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, options.format.c_str(), fileName.c_str()) < 0 || !m_ffmpeg->formatCtx) { LOGE() << "failed to allocate output context"; return false; @@ -93,7 +93,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } - m_ffmpeg->videoStream->time_base.den = fps; + m_ffmpeg->videoStream->time_base.den = options.fps; m_ffmpeg->videoStream->time_base.num = 1; // find the video encoder @@ -110,10 +110,10 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->videoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; m_ffmpeg->videoStream->codecpar->codec_id = AV_CODEC_ID_H264; - m_ffmpeg->videoStream->codecpar->width = width; - m_ffmpeg->videoStream->codecpar->height = height; + m_ffmpeg->videoStream->codecpar->width = options.width; + m_ffmpeg->videoStream->codecpar->height = options.height; m_ffmpeg->videoStream->codecpar->format = AV_PIX_FMT_YUV420P; - m_ffmpeg->videoStream->codecpar->bit_rate = bitrate; + m_ffmpeg->videoStream->codecpar->bit_rate = options.bitrate; if (m_ffmpegHandler->avcodec_parameters_to_context(m_ffmpeg->codecCtx, m_ffmpeg->videoStream->codecpar) < 0) { m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); @@ -122,9 +122,9 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign } m_ffmpeg->codecCtx->profile = FF_PROFILE_H264_HIGH; - m_ffmpeg->codecCtx->time_base.den = fps; + m_ffmpeg->codecCtx->time_base.den = options.fps; m_ffmpeg->codecCtx->time_base.num = 1; - m_ffmpeg->codecCtx->gop_size = gop; + m_ffmpeg->codecCtx->gop_size = options.gop; m_ffmpeg->codecCtx->thread_count = 10; m_ffmpeg->codecCtx->max_b_frames = 3; m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); @@ -165,8 +165,8 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } - m_ffmpeg->ppicture->width = width; - m_ffmpeg->ppicture->height = height; + m_ffmpeg->ppicture->width = options.width; + m_ffmpeg->ppicture->height = options.height; m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; int size = m_ffmpegHandler->av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.h b/src/framework/media/internal/ffmpeg/v5/videoencoder.h index e9312e847d832..a3d19cbcad2ff 100644 --- a/src/framework/media/internal/ffmpeg/v5/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.h @@ -37,7 +37,7 @@ class VideoEncoder : public IVideoEncoder bool load(const FFmpegLibPaths& paths); - bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; + bool open(const muse::io::path_t& fileName, const Options& options) override; void close() override; bool encodeImage(const QImage& img) override; diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp index 5a47fac5c59e5..fa9f2c662c398 100644 --- a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp @@ -73,14 +73,14 @@ bool VideoEncoder::load(const FFmpegLibPaths& paths) return true; } -bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) +bool VideoEncoder::open(const muse::io::path_t& fileName, const Options& options) { m_ffmpeg->ptsCounter = 0; - m_ffmpeg->width = width; - m_ffmpeg->height = height; + m_ffmpeg->width = options.width; + m_ffmpeg->height = options.height; - if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, "mp4", fileName.c_str()) < 0 + if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, options.format.c_str(), fileName.c_str()) < 0 || !m_ffmpeg->formatCtx) { LOGE() << "failed to allocate output context"; return false; @@ -93,7 +93,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } - m_ffmpeg->videoStream->time_base.den = fps; + m_ffmpeg->videoStream->time_base.den = options.fps; m_ffmpeg->videoStream->time_base.num = 1; // find the video encoder @@ -110,10 +110,10 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->videoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; m_ffmpeg->videoStream->codecpar->codec_id = AV_CODEC_ID_H264; - m_ffmpeg->videoStream->codecpar->width = width; - m_ffmpeg->videoStream->codecpar->height = height; + m_ffmpeg->videoStream->codecpar->width = options.width; + m_ffmpeg->videoStream->codecpar->height = options.height; m_ffmpeg->videoStream->codecpar->format = AV_PIX_FMT_YUV420P; - m_ffmpeg->videoStream->codecpar->bit_rate = bitrate; + m_ffmpeg->videoStream->codecpar->bit_rate = options.bitrate; if (m_ffmpegHandler->avcodec_parameters_to_context(m_ffmpeg->codecCtx, m_ffmpeg->videoStream->codecpar) < 0) { m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); @@ -122,9 +122,9 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign } m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; - m_ffmpeg->codecCtx->time_base.den = fps; + m_ffmpeg->codecCtx->time_base.den = options.fps; m_ffmpeg->codecCtx->time_base.num = 1; - m_ffmpeg->codecCtx->gop_size = gop; + m_ffmpeg->codecCtx->gop_size = options.gop; m_ffmpeg->codecCtx->thread_count = 10; m_ffmpeg->codecCtx->max_b_frames = 3; m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); @@ -165,8 +165,8 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } - m_ffmpeg->ppicture->width = width; - m_ffmpeg->ppicture->height = height; + m_ffmpeg->ppicture->width = options.width; + m_ffmpeg->ppicture->height = options.height; m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; int size = m_ffmpegHandler->av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.h b/src/framework/media/internal/ffmpeg/v6/videoencoder.h index b06517dd66af0..ebea7c493c7b9 100644 --- a/src/framework/media/internal/ffmpeg/v6/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.h @@ -37,7 +37,7 @@ class VideoEncoder : public IVideoEncoder bool load(const FFmpegLibPaths& paths); - bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; + bool open(const muse::io::path_t& fileName, const Options& options) override; void close() override; bool encodeImage(const QImage& img) override; diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp index cad636e452636..3fe042e6d7db4 100644 --- a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp @@ -73,14 +73,14 @@ bool VideoEncoder::load(const FFmpegLibPaths& paths) return true; } -bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) +bool VideoEncoder::open(const muse::io::path_t& fileName, const Options& options) { m_ffmpeg->ptsCounter = 0; - m_ffmpeg->width = width; - m_ffmpeg->height = height; + m_ffmpeg->width = options.width; + m_ffmpeg->height = options.height; - if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, "mp4", fileName.c_str()) < 0 + if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, options.format.c_str(), fileName.c_str()) < 0 || !m_ffmpeg->formatCtx) { LOGE() << "failed to allocate output context"; return false; @@ -93,7 +93,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } - m_ffmpeg->videoStream->time_base.den = fps; + m_ffmpeg->videoStream->time_base.den = options.fps; m_ffmpeg->videoStream->time_base.num = 1; // find the video encoder @@ -110,10 +110,10 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->videoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; m_ffmpeg->videoStream->codecpar->codec_id = AV_CODEC_ID_H264; - m_ffmpeg->videoStream->codecpar->width = width; - m_ffmpeg->videoStream->codecpar->height = height; + m_ffmpeg->videoStream->codecpar->width = options.width; + m_ffmpeg->videoStream->codecpar->height = options.height; m_ffmpeg->videoStream->codecpar->format = AV_PIX_FMT_YUV420P; - m_ffmpeg->videoStream->codecpar->bit_rate = bitrate; + m_ffmpeg->videoStream->codecpar->bit_rate = options.bitrate; if (m_ffmpegHandler->avcodec_parameters_to_context(m_ffmpeg->codecCtx, m_ffmpeg->videoStream->codecpar) < 0) { m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); @@ -122,9 +122,9 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign } m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; - m_ffmpeg->codecCtx->time_base.den = fps; + m_ffmpeg->codecCtx->time_base.den = options.fps; m_ffmpeg->codecCtx->time_base.num = 1; - m_ffmpeg->codecCtx->gop_size = gop; + m_ffmpeg->codecCtx->gop_size = options.gop; m_ffmpeg->codecCtx->thread_count = 10; m_ffmpeg->codecCtx->max_b_frames = 3; m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); @@ -165,8 +165,8 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } - m_ffmpeg->ppicture->width = width; - m_ffmpeg->ppicture->height = height; + m_ffmpeg->ppicture->width = options.width; + m_ffmpeg->ppicture->height = options.height; m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; int size = m_ffmpegHandler->av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.h b/src/framework/media/internal/ffmpeg/v7/videoencoder.h index 5e36720a58a5e..d81455d55cec2 100644 --- a/src/framework/media/internal/ffmpeg/v7/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.h @@ -37,7 +37,7 @@ class VideoEncoder : public IVideoEncoder bool load(const FFmpegLibPaths& paths); - bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; + bool open(const muse::io::path_t& fileName, const Options& options) override; void close() override; bool encodeImage(const QImage& img) override; diff --git a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp index 3f2b22c3e35bc..b1e4ec72c77e6 100644 --- a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp @@ -73,14 +73,14 @@ bool VideoEncoder::load(const FFmpegLibPaths& paths) return true; } -bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) +bool VideoEncoder::open(const muse::io::path_t& fileName, const Options& options) { m_ffmpeg->ptsCounter = 0; - m_ffmpeg->width = width; - m_ffmpeg->height = height; + m_ffmpeg->width = options.width; + m_ffmpeg->height = options.height; - if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, "mp4", fileName.c_str()) < 0 + if (m_ffmpegHandler->avformat_alloc_output_context2(&m_ffmpeg->formatCtx, nullptr, options.format.c_str(), fileName.c_str()) < 0 || !m_ffmpeg->formatCtx) { LOGE() << "failed to allocate output context"; return false; @@ -93,7 +93,7 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } - m_ffmpeg->videoStream->time_base.den = fps; + m_ffmpeg->videoStream->time_base.den = options.fps; m_ffmpeg->videoStream->time_base.num = 1; // find the video encoder @@ -110,10 +110,10 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign m_ffmpeg->videoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; m_ffmpeg->videoStream->codecpar->codec_id = AV_CODEC_ID_H264; - m_ffmpeg->videoStream->codecpar->width = width; - m_ffmpeg->videoStream->codecpar->height = height; + m_ffmpeg->videoStream->codecpar->width = options.width; + m_ffmpeg->videoStream->codecpar->height = options.height; m_ffmpeg->videoStream->codecpar->format = AV_PIX_FMT_YUV420P; - m_ffmpeg->videoStream->codecpar->bit_rate = bitrate; + m_ffmpeg->videoStream->codecpar->bit_rate = options.bitrate; if (m_ffmpegHandler->avcodec_parameters_to_context(m_ffmpeg->codecCtx, m_ffmpeg->videoStream->codecpar) < 0) { m_ffmpegHandler->avcodec_free_context(&m_ffmpeg->codecCtx); @@ -122,9 +122,9 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign } m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; - m_ffmpeg->codecCtx->time_base.den = fps; + m_ffmpeg->codecCtx->time_base.den = options.fps; m_ffmpeg->codecCtx->time_base.num = 1; - m_ffmpeg->codecCtx->gop_size = gop; + m_ffmpeg->codecCtx->gop_size = options.gop; m_ffmpeg->codecCtx->thread_count = 10; m_ffmpeg->codecCtx->max_b_frames = 3; m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); @@ -165,8 +165,8 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, unsigned width, unsign return false; } - m_ffmpeg->ppicture->width = width; - m_ffmpeg->ppicture->height = height; + m_ffmpeg->ppicture->width = options.width; + m_ffmpeg->ppicture->height = options.height; m_ffmpeg->ppicture->format = AV_PIX_FMT_YUV420P; int size = m_ffmpegHandler->av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_ffmpeg->width, m_ffmpeg->height, 1); diff --git a/src/framework/media/internal/ffmpeg/v8/videoencoder.h b/src/framework/media/internal/ffmpeg/v8/videoencoder.h index 8e5b38ee63e51..d91141900a1c6 100644 --- a/src/framework/media/internal/ffmpeg/v8/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.h @@ -37,7 +37,7 @@ class VideoEncoder : public IVideoEncoder bool load(const FFmpegLibPaths& paths); - bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) override; + bool open(const muse::io::path_t& fileName, const Options& options) override; void close() override; bool encodeImage(const QImage& img) override; diff --git a/src/framework/media/ivideoencoder.h b/src/framework/media/ivideoencoder.h index d4ae609a727d6..348f8a2d937e8 100644 --- a/src/framework/media/ivideoencoder.h +++ b/src/framework/media/ivideoencoder.h @@ -22,6 +22,8 @@ #pragma once +#include + #include #include "io/path.h" @@ -36,7 +38,16 @@ class IVideoEncoder : MODULE_CONTEXT_INTERFACE public: virtual ~IVideoEncoder() = default; - virtual bool open(const muse::io::path_t& fileName, unsigned width, unsigned height, unsigned bitrate, unsigned gop, unsigned fps) = 0; + struct Options { + std::string format = ""; + unsigned width = -1; + unsigned height = -1; + unsigned bitrate = -1; + unsigned gop = -1; + unsigned fps = -1; + }; + + virtual bool open(const muse::io::path_t& fileName, const Options& options) = 0; virtual void close() = 0; virtual bool encodeImage(const QImage& img) = 0; diff --git a/src/framework/stubs/media/videoencoderstub.cpp b/src/framework/stubs/media/videoencoderstub.cpp index f9abd48fe9d6a..af790da0651fa 100644 --- a/src/framework/stubs/media/videoencoderstub.cpp +++ b/src/framework/stubs/media/videoencoderstub.cpp @@ -23,7 +23,7 @@ using namespace muse::media; -bool VideoEncoderStub::open(const muse::io::path_t&, unsigned, unsigned, unsigned, unsigned, unsigned) +bool VideoEncoderStub::open(const muse::io::path_t&, const IVideoEncoder::Options&) { return false; } diff --git a/src/framework/stubs/media/videoencoderstub.h b/src/framework/stubs/media/videoencoderstub.h index 47421b092d275..e9dc2a7f7cfa4 100644 --- a/src/framework/stubs/media/videoencoderstub.h +++ b/src/framework/stubs/media/videoencoderstub.h @@ -30,7 +30,7 @@ class VideoEncoderStub : public IVideoEncoder public: VideoEncoderStub() = default; - bool open(const muse::io::path_t&, unsigned, unsigned, unsigned, unsigned, unsigned) override; + bool open(const muse::io::path_t&, const Options&) override; void close() override; bool encodeImage(const QImage&) override; diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index ebd2238da331a..aa593038b32e0 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -74,7 +74,16 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, muse::io::path_t tempAudioPath = finalPath + ".tmp_audio.mp3"; auto encoder = videoEncodeResolver()->currentVideoEncoder(); - if (!encoder->open(finalPath, cfg.width, cfg.height, cfg.bitrate, cfg.fps / 2, cfg.fps)) { + + muse::media::IVideoEncoder::Options encoderOptions; + encoderOptions.format = "mp4"; + encoderOptions.width = cfg.width; + encoderOptions.height = cfg.height; + encoderOptions.bitrate = cfg.bitrate; + encoderOptions.gop = cfg.fps / 2; + encoderOptions.fps = cfg.fps; + + if (!encoder->open(finalPath, encoderOptions)) { LOGE() << "failed to open video encoder"; return make_ret(muse::Ret::Code::UnknownError); } From 8bbfb9f8b32db7890c45f3b69f5226ee35aedec6 Mon Sep 17 00:00:00 2001 From: Eism Date: Tue, 17 Mar 2026 15:10:47 +0200 Subject: [PATCH 41/52] removed unused ffmpeg functions from lib handler --- .../internal/ffmpeg/v4/ffmpeglibhandler.cpp | 18 +++--------------- .../internal/ffmpeg/v4/ffmpeglibhandler.h | 7 ------- .../internal/ffmpeg/v5/ffmpeglibhandler.cpp | 18 +++--------------- .../internal/ffmpeg/v5/ffmpeglibhandler.h | 7 ------- .../internal/ffmpeg/v6/ffmpeglibhandler.cpp | 18 +++--------------- .../internal/ffmpeg/v6/ffmpeglibhandler.h | 7 ------- .../internal/ffmpeg/v7/ffmpeglibhandler.cpp | 18 +++--------------- .../internal/ffmpeg/v7/ffmpeglibhandler.h | 7 ------- .../internal/ffmpeg/v8/ffmpeglibhandler.cpp | 12 ++---------- .../internal/ffmpeg/v8/ffmpeglibhandler.h | 5 ----- 10 files changed, 14 insertions(+), 103 deletions(-) diff --git a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp index a280114fc8ea1..d2af9e3f7bff8 100644 --- a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp @@ -60,25 +60,19 @@ bool FFmpegLibHandler::loadApi() clearFunctions(); // libavutil - RESOLVE_FROM(m_avUtilLibrary, av_free); - RESOLVE_FROM(m_avUtilLibrary, av_freep); RESOLVE_FROM(m_avUtilLibrary, av_rescale_q); RESOLVE_FROM(m_avUtilLibrary, av_image_fill_arrays); RESOLVE_FROM(m_avUtilLibrary, av_image_get_buffer_size); - RESOLVE_FROM(m_avUtilLibrary, av_opt_set); RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); - RESOLVE_FROM(m_avUtilLibrary, av_opt_set_pixel_fmt); RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); RESOLVE_FROM(m_avUtilLibrary, av_frame_free); // libavformat - RESOLVE_FROM(m_avFormatLibrary, av_guess_format); RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); RESOLVE_FROM(m_avFormatLibrary, av_interleaved_write_frame); RESOLVE_FROM(m_avFormatLibrary, av_read_frame); RESOLVE_FROM(m_avFormatLibrary, avio_open); RESOLVE_FROM(m_avFormatLibrary, avio_close); - RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); RESOLVE_FROM(m_avFormatLibrary, avformat_new_stream); RESOLVE_FROM(m_avFormatLibrary, avformat_write_header); RESOLVE_FROM(m_avFormatLibrary, avformat_open_input); @@ -165,10 +159,10 @@ bool FFmpegLibHandler::tryLoadPath(void*& lib, const io::path_t& fullPath) bool FFmpegLibHandler::functionsValid() const { - return av_free && av_freep && av_rescale_q + return av_rescale_q && av_image_fill_arrays && av_image_get_buffer_size - && av_opt_set && av_opt_set_int && av_opt_set_pixel_fmt - && av_guess_format && avformat_alloc_context && avformat_new_stream + && av_opt_set_int + && avformat_new_stream && avformat_write_header && av_write_trailer && avio_open && avio_close && av_interleaved_write_frame && avformat_open_input && avformat_find_stream_info @@ -184,16 +178,10 @@ bool FFmpegLibHandler::functionsValid() const void FFmpegLibHandler::clearFunctions() { - av_free = nullptr; - av_freep = nullptr; av_rescale_q = nullptr; av_image_fill_arrays = nullptr; av_image_get_buffer_size = nullptr; - av_opt_set = nullptr; av_opt_set_int = nullptr; - av_opt_set_pixel_fmt = nullptr; - av_guess_format = nullptr; - avformat_alloc_context = nullptr; avformat_new_stream = nullptr; avformat_write_header = nullptr; av_write_trailer = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h index fd8a9e09ac22d..bc5ac1add118b 100644 --- a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h @@ -42,19 +42,13 @@ class FFmpegLibHandler void unload(); // libavutil - void (*av_free)(void* ptr) = nullptr; - void (*av_freep)(void* ptr) = nullptr; int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; - int (*av_opt_set)(void* obj, const char* name, const char* val, int search_flags) = nullptr; int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; - int (*av_opt_set_pixel_fmt)(void* obj, const char* name, AVPixelFormat fmt, int search_flags) = nullptr; // libavformat - const AVOutputFormat*(*av_guess_format)(const char* short_name, const char* filename, const char* mime_type) = nullptr; - AVFormatContext*(*avformat_alloc_context)(void) = nullptr; AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; int (*av_write_trailer)(AVFormatContext* s) = nullptr; @@ -104,6 +98,5 @@ private : void* getSymbol(void* lib, const char* name) const; void* m_avFormatLibrary = nullptr; void* m_swsScaleLibrary = nullptr; void* m_swResampleLibrary = nullptr; - }; } diff --git a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp index ff26a5dbe125d..8aa3c1508e76e 100644 --- a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp @@ -60,25 +60,19 @@ bool FFmpegLibHandler::loadApi() clearFunctions(); // libavutil - RESOLVE_FROM(m_avUtilLibrary, av_free); - RESOLVE_FROM(m_avUtilLibrary, av_freep); RESOLVE_FROM(m_avUtilLibrary, av_rescale_q); RESOLVE_FROM(m_avUtilLibrary, av_image_fill_arrays); RESOLVE_FROM(m_avUtilLibrary, av_image_get_buffer_size); - RESOLVE_FROM(m_avUtilLibrary, av_opt_set); RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); - RESOLVE_FROM(m_avUtilLibrary, av_opt_set_pixel_fmt); RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); RESOLVE_FROM(m_avUtilLibrary, av_frame_free); // libavformat - RESOLVE_FROM(m_avFormatLibrary, av_guess_format); RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); RESOLVE_FROM(m_avFormatLibrary, av_interleaved_write_frame); RESOLVE_FROM(m_avFormatLibrary, av_read_frame); RESOLVE_FROM(m_avFormatLibrary, avio_open); RESOLVE_FROM(m_avFormatLibrary, avio_close); - RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); RESOLVE_FROM(m_avFormatLibrary, avformat_new_stream); RESOLVE_FROM(m_avFormatLibrary, avformat_write_header); RESOLVE_FROM(m_avFormatLibrary, avformat_open_input); @@ -165,10 +159,10 @@ bool FFmpegLibHandler::tryLoadPath(void*& lib, const io::path_t& fullPath) bool FFmpegLibHandler::functionsValid() const { - return av_free && av_freep && av_rescale_q + return av_rescale_q && av_image_fill_arrays && av_image_get_buffer_size - && av_opt_set && av_opt_set_int && av_opt_set_pixel_fmt - && av_guess_format && avformat_alloc_context && avformat_new_stream + && av_opt_set_int + && avformat_new_stream && avformat_write_header && av_write_trailer && avio_open && avio_close && av_interleaved_write_frame && avformat_open_input && avformat_find_stream_info @@ -184,16 +178,10 @@ bool FFmpegLibHandler::functionsValid() const void FFmpegLibHandler::clearFunctions() { - av_free = nullptr; - av_freep = nullptr; av_rescale_q = nullptr; av_image_fill_arrays = nullptr; av_image_get_buffer_size = nullptr; - av_opt_set = nullptr; av_opt_set_int = nullptr; - av_opt_set_pixel_fmt = nullptr; - av_guess_format = nullptr; - avformat_alloc_context = nullptr; avformat_new_stream = nullptr; avformat_write_header = nullptr; av_write_trailer = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h index 6a3066af520a2..18a844231ae69 100644 --- a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h @@ -42,19 +42,13 @@ class FFmpegLibHandler void unload(); // libavutil - void (*av_free)(void* ptr) = nullptr; - void (*av_freep)(void* ptr) = nullptr; int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; - int (*av_opt_set)(void* obj, const char* name, const char* val, int search_flags) = nullptr; int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; - int (*av_opt_set_pixel_fmt)(void* obj, const char* name, AVPixelFormat fmt, int search_flags) = nullptr; // libavformat - const AVOutputFormat*(*av_guess_format)(const char* short_name, const char* filename, const char* mime_type) = nullptr; - AVFormatContext*(*avformat_alloc_context)(void) = nullptr; AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; int (*av_write_trailer)(AVFormatContext* s) = nullptr; @@ -104,6 +98,5 @@ private : void* getSymbol(void* lib, const char* name) const; void* m_avFormatLibrary = nullptr; void* m_swsScaleLibrary = nullptr; void* m_swResampleLibrary = nullptr; - }; } diff --git a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp index e5b06837010cd..d0d8c821b7f74 100644 --- a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp @@ -60,25 +60,19 @@ bool FFmpegLibHandler::loadApi() clearFunctions(); // libavutil - RESOLVE_FROM(m_avUtilLibrary, av_free); - RESOLVE_FROM(m_avUtilLibrary, av_freep); RESOLVE_FROM(m_avUtilLibrary, av_rescale_q); RESOLVE_FROM(m_avUtilLibrary, av_image_fill_arrays); RESOLVE_FROM(m_avUtilLibrary, av_image_get_buffer_size); - RESOLVE_FROM(m_avUtilLibrary, av_opt_set); RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); - RESOLVE_FROM(m_avUtilLibrary, av_opt_set_pixel_fmt); RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); RESOLVE_FROM(m_avUtilLibrary, av_frame_free); // libavformat - RESOLVE_FROM(m_avFormatLibrary, av_guess_format); RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); RESOLVE_FROM(m_avFormatLibrary, av_interleaved_write_frame); RESOLVE_FROM(m_avFormatLibrary, av_read_frame); RESOLVE_FROM(m_avFormatLibrary, avio_open); RESOLVE_FROM(m_avFormatLibrary, avio_close); - RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); RESOLVE_FROM(m_avFormatLibrary, avformat_new_stream); RESOLVE_FROM(m_avFormatLibrary, avformat_write_header); RESOLVE_FROM(m_avFormatLibrary, avformat_open_input); @@ -165,10 +159,10 @@ bool FFmpegLibHandler::tryLoadPath(void*& lib, const io::path_t& fullPath) bool FFmpegLibHandler::functionsValid() const { - return av_free && av_freep && av_rescale_q + return av_rescale_q && av_image_fill_arrays && av_image_get_buffer_size - && av_opt_set && av_opt_set_int && av_opt_set_pixel_fmt - && av_guess_format && avformat_alloc_context && avformat_new_stream + && av_opt_set_int + && avformat_new_stream && avformat_write_header && av_write_trailer && avio_open && avio_close && av_interleaved_write_frame && avformat_open_input && avformat_find_stream_info @@ -184,16 +178,10 @@ bool FFmpegLibHandler::functionsValid() const void FFmpegLibHandler::clearFunctions() { - av_free = nullptr; - av_freep = nullptr; av_rescale_q = nullptr; av_image_fill_arrays = nullptr; av_image_get_buffer_size = nullptr; - av_opt_set = nullptr; av_opt_set_int = nullptr; - av_opt_set_pixel_fmt = nullptr; - av_guess_format = nullptr; - avformat_alloc_context = nullptr; avformat_new_stream = nullptr; avformat_write_header = nullptr; av_write_trailer = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h index c6702dbc4abbe..10722a8763e30 100644 --- a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h @@ -42,19 +42,13 @@ class FFmpegLibHandler void unload(); // libavutil - void (*av_free)(void* ptr) = nullptr; - void (*av_freep)(void* ptr) = nullptr; int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; - int (*av_opt_set)(void* obj, const char* name, const char* val, int search_flags) = nullptr; int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; - int (*av_opt_set_pixel_fmt)(void* obj, const char* name, AVPixelFormat fmt, int search_flags) = nullptr; // libavformat - const AVOutputFormat*(*av_guess_format)(const char* short_name, const char* filename, const char* mime_type) = nullptr; - AVFormatContext*(*avformat_alloc_context)(void) = nullptr; AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; int (*av_write_trailer)(AVFormatContext* s) = nullptr; @@ -104,6 +98,5 @@ private : void* getSymbol(void* lib, const char* name) const; void* m_avFormatLibrary = nullptr; void* m_swsScaleLibrary = nullptr; void* m_swResampleLibrary = nullptr; - }; } diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp index 5514cad4eb75a..f4b0ef89dacd6 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp @@ -60,25 +60,19 @@ bool FFmpegLibHandler::loadApi() clearFunctions(); // libavutil - RESOLVE_FROM(m_avUtilLibrary, av_free); - RESOLVE_FROM(m_avUtilLibrary, av_freep); RESOLVE_FROM(m_avUtilLibrary, av_rescale_q); RESOLVE_FROM(m_avUtilLibrary, av_image_fill_arrays); RESOLVE_FROM(m_avUtilLibrary, av_image_get_buffer_size); - RESOLVE_FROM(m_avUtilLibrary, av_opt_set); RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); - RESOLVE_FROM(m_avUtilLibrary, av_opt_set_pixel_fmt); RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); RESOLVE_FROM(m_avUtilLibrary, av_frame_free); // libavformat - RESOLVE_FROM(m_avFormatLibrary, av_guess_format); RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); RESOLVE_FROM(m_avFormatLibrary, av_interleaved_write_frame); RESOLVE_FROM(m_avFormatLibrary, av_read_frame); RESOLVE_FROM(m_avFormatLibrary, avio_open); RESOLVE_FROM(m_avFormatLibrary, avio_close); - RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); RESOLVE_FROM(m_avFormatLibrary, avformat_new_stream); RESOLVE_FROM(m_avFormatLibrary, avformat_write_header); RESOLVE_FROM(m_avFormatLibrary, avformat_open_input); @@ -165,10 +159,10 @@ bool FFmpegLibHandler::tryLoadPath(void*& lib, const io::path_t& fullPath) bool FFmpegLibHandler::functionsValid() const { - return av_free && av_freep && av_rescale_q + return av_rescale_q && av_image_fill_arrays && av_image_get_buffer_size - && av_opt_set && av_opt_set_int && av_opt_set_pixel_fmt - && av_guess_format && avformat_alloc_context && avformat_new_stream + && av_opt_set_int + && avformat_new_stream && avformat_write_header && av_write_trailer && avio_open && avio_close && av_interleaved_write_frame && avformat_open_input && avformat_find_stream_info @@ -184,16 +178,10 @@ bool FFmpegLibHandler::functionsValid() const void FFmpegLibHandler::clearFunctions() { - av_free = nullptr; - av_freep = nullptr; av_rescale_q = nullptr; av_image_fill_arrays = nullptr; av_image_get_buffer_size = nullptr; - av_opt_set = nullptr; av_opt_set_int = nullptr; - av_opt_set_pixel_fmt = nullptr; - av_guess_format = nullptr; - avformat_alloc_context = nullptr; avformat_new_stream = nullptr; avformat_write_header = nullptr; av_write_trailer = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h index 5de5675050528..7e36da824ba7b 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h @@ -42,19 +42,13 @@ class FFmpegLibHandler void unload(); // libavutil - void (*av_free)(void* ptr) = nullptr; - void (*av_freep)(void* ptr) = nullptr; int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; - int (*av_opt_set)(void* obj, const char* name, const char* val, int search_flags) = nullptr; int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; - int (*av_opt_set_pixel_fmt)(void* obj, const char* name, AVPixelFormat fmt, int search_flags) = nullptr; // libavformat - const AVOutputFormat*(*av_guess_format)(const char* short_name, const char* filename, const char* mime_type) = nullptr; - AVFormatContext*(*avformat_alloc_context)(void) = nullptr; AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; int (*av_write_trailer)(AVFormatContext* s) = nullptr; @@ -104,6 +98,5 @@ private : void* getSymbol(void* lib, const char* name) const; void* m_avFormatLibrary = nullptr; void* m_swsScaleLibrary = nullptr; void* m_swResampleLibrary = nullptr; - }; } diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp index 518faaa975d17..380293388e2cd 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp @@ -60,8 +60,6 @@ bool FFmpegLibHandler::loadApi() clearFunctions(); // libavutil - RESOLVE_FROM(m_avUtilLibrary, av_free); - RESOLVE_FROM(m_avUtilLibrary, av_freep); RESOLVE_FROM(m_avUtilLibrary, av_rescale_q); RESOLVE_FROM(m_avUtilLibrary, av_image_fill_arrays); RESOLVE_FROM(m_avUtilLibrary, av_image_get_buffer_size); @@ -70,13 +68,11 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avUtilLibrary, av_frame_free); // libavformat - RESOLVE_FROM(m_avFormatLibrary, av_guess_format); RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); RESOLVE_FROM(m_avFormatLibrary, av_interleaved_write_frame); RESOLVE_FROM(m_avFormatLibrary, av_read_frame); RESOLVE_FROM(m_avFormatLibrary, avio_open); RESOLVE_FROM(m_avFormatLibrary, avio_close); - RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); RESOLVE_FROM(m_avFormatLibrary, avformat_new_stream); RESOLVE_FROM(m_avFormatLibrary, avformat_write_header); RESOLVE_FROM(m_avFormatLibrary, avformat_open_input); @@ -163,10 +159,10 @@ bool FFmpegLibHandler::tryLoadPath(void*& lib, const io::path_t& fullPath) bool FFmpegLibHandler::functionsValid() const { - return av_free && av_freep && av_rescale_q + return av_rescale_q && av_image_fill_arrays && av_image_get_buffer_size && av_opt_set_int - && av_guess_format && avformat_alloc_context && avformat_new_stream + && avformat_new_stream && avformat_write_header && av_write_trailer && avio_open && avio_close && av_interleaved_write_frame && avformat_open_input && avformat_find_stream_info @@ -182,14 +178,10 @@ bool FFmpegLibHandler::functionsValid() const void FFmpegLibHandler::clearFunctions() { - av_free = nullptr; - av_freep = nullptr; av_rescale_q = nullptr; av_image_fill_arrays = nullptr; av_image_get_buffer_size = nullptr; av_opt_set_int = nullptr; - av_guess_format = nullptr; - avformat_alloc_context = nullptr; avformat_new_stream = nullptr; avformat_write_header = nullptr; av_write_trailer = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h index 1db618550fd48..d684867d953f5 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h @@ -42,8 +42,6 @@ class FFmpegLibHandler void unload(); // libavutil - void (*av_free)(void* ptr) = nullptr; - void (*av_freep)(void* ptr) = nullptr; int64_t (*av_rescale_q)(int64_t a, AVRational bq, AVRational cq) = nullptr; int (*av_image_fill_arrays)(uint8_t* dst_data[4], int dst_linesize[4], const uint8_t* src, AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; @@ -51,8 +49,6 @@ class FFmpegLibHandler int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; // libavformat - const AVOutputFormat*(*av_guess_format)(const char* short_name, const char* filename, const char* mime_type) = nullptr; - AVFormatContext*(*avformat_alloc_context)(void) = nullptr; AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; int (*avformat_write_header)(AVFormatContext* s, AVDictionary** options) = nullptr; int (*av_write_trailer)(AVFormatContext* s) = nullptr; @@ -102,6 +98,5 @@ private : void* getSymbol(void* lib, const char* name) const; void* m_avFormatLibrary = nullptr; void* m_swsScaleLibrary = nullptr; void* m_swResampleLibrary = nullptr; - }; } From 965eb5fc138da5ba9451d4dfa997c47dc28fb704 Mon Sep 17 00:00:00 2001 From: Eism Date: Tue, 17 Mar 2026 16:54:52 +0200 Subject: [PATCH 42/52] added title frame for video export --- .../videoexport/internal/videowriter.cpp | 101 ++++++++++++++---- .../videoexport/internal/videowriter.h | 12 +++ 2 files changed, 91 insertions(+), 22 deletions(-) diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index aa593038b32e0..d13950409294c 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -344,8 +344,6 @@ void VideoWriter::doGenerate(muse::media::IVideoEncoderPtr encoder, INotationPtr m_isCompleted = true; }; - PageList pages = notation->elements()->pages(); - // Setup painting QImage frame(config.width, config.height, QImage::Format_RGB32); frame.setDotsPerMeterX(std::lrint((CANVAS_DPI * 1000) / engraving::INCH)); @@ -354,21 +352,87 @@ void VideoWriter::doGenerate(muse::media::IVideoEncoderPtr encoder, INotationPtr QPainter qp(&frame); qp.setRenderHint(QPainter::Antialiasing, true); qp.setRenderHint(QPainter::TextAntialiasing, true); - muse::RectF frameRect = muse::RectF::fromQRectF(QRectF(frame.rect())); Painter painter(&qp, "video_writer"); - auto painting = notation->painting(); - // Setup duration INotationPlaybackPtr playback = notation->masterNotation()->playback(); float totalPlayTimeSec = playback->totalPlayTime(); - int frameCount = (totalPlayTimeSec + config.leadingSec + config.trailingSec) * config.fps; - LOGI() << "totalPlayTime: " << totalPlayTimeSec << " sec" << " frame count " << frameCount; + int leadingFrameCount = static_cast(config.leadingSec * config.fps); + int scoreFrameCount = static_cast((totalPlayTimeSec + config.trailingSec) * config.fps); + int totalFrameCount = leadingFrameCount + scoreFrameCount; + LOGI() << "totalPlayTime: " << totalPlayTimeSec << " sec" << " frame count " << totalFrameCount; + + m_progress.start(); + + bool ok = generateLeadingFrames(encoder, notation, painter, frame, config, totalFrameCount); + if (!ok) { + return; + } + + ok = generateScoreFrames(encoder, notation, painter, frame, config, totalPlayTimeSec, leadingFrameCount, totalFrameCount); + if (!ok) { + return; + } - //! NOTE: After setting the score above, the number of pages may change - get them again - pages = notation->elements()->pages(); + m_writeRet = muse::make_ok(); + m_progress.finish(muse::make_ok()); +} + +bool VideoWriter::generateLeadingFrames(muse::media::IVideoEncoderPtr encoder, INotationPtr notation, + Painter& painter, QImage& frame, + const Config& config, int totalFrameCount) +{ + int leadingFrameCount = static_cast(config.leadingSec * config.fps); + if (leadingFrameCount <= 0) { + return true; + } + + engraving::Score* score = notation->elements()->msScore(); + muse::String title = score->metaTag(u"workTitle"); + + Font font(Font::FontFamily(u"Edwin"), Font::Type::Text); + + double desiredPixelSize = 128.0 * config.height / 1080.0; + font.setPointSizeF(desiredPixelSize * 72.0 / engraving::DPI); + + muse::RectF frameRect = muse::RectF::fromQRectF(QRectF(frame.rect())); + + for (int f = 0; f < leadingFrameCount; f++) { + if (m_abort) { + m_writeRet = make_ret(muse::Ret::Code::Cancel); + m_progress.finish(m_writeRet); + return false; + } + + m_progress.progress(f, totalFrameCount); + + painter.fillRect(frameRect, Color::BLACK); + painter.setPen(Color::WHITE); + painter.setFont(font); + painter.drawText(frameRect, AlignCenter, title); + + encoder->encodeImage(frame); + } + + return true; +} + +bool VideoWriter::generateScoreFrames(muse::media::IVideoEncoderPtr encoder, INotationPtr notation, + Painter& painter, QImage& frame, + const Config& config, float totalPlayTimeSec, + int leadingFrameCount, int totalFrameCount) +{ + int scoreFrameCount = static_cast((totalPlayTimeSec + config.trailingSec) * config.fps); + if (scoreFrameCount <= 0) { + return true; + } + + PageList pages = notation->elements()->pages(); + auto painting = notation->painting(); + INotationPlaybackPtr playback = notation->masterNotation()->playback(); + muse::RectF frameRect = muse::RectF::fromQRectF(QRectF(frame.rect())); auto pageByTick = [](const PageList& pages, tick_t tick) -> const Page* { for (const Page* p : pages) { @@ -384,22 +448,16 @@ void VideoWriter::doGenerate(muse::media::IVideoEncoderPtr encoder, INotationPtr PlaybackCursor cursor(iocContext()); cursor.setNotation(notation); - m_progress.start(); - - for (int f = 0; f < frameCount; f++) { + for (int f = 0; f < scoreFrameCount; f++) { if (m_abort) { m_writeRet = make_ret(muse::Ret::Code::Cancel); - m_progress.finish(make_ret(muse::Ret::Code::Cancel)); - return; + m_progress.finish(m_writeRet); + return false; } - m_progress.progress(f, frameCount); + m_progress.progress(leadingFrameCount + f, totalFrameCount); - float currentTimeSec = (qreal)f / config.fps; - currentTimeSec -= config.leadingSec; - if (currentTimeSec <= 0) { - currentTimeSec = 0; - } + float currentTimeSec = static_cast(f) / config.fps; if (currentTimeSec > totalPlayTimeSec) { currentTimeSec = totalPlayTimeSec; } @@ -431,6 +489,5 @@ void VideoWriter::doGenerate(muse::media::IVideoEncoderPtr encoder, INotationPtr encoder->encodeImage(frame); } - m_writeRet = muse::make_ok(); - m_progress.finish(muse::make_ok()); + return true; } diff --git a/src/importexport/videoexport/internal/videowriter.h b/src/importexport/videoexport/internal/videowriter.h index f1c7a2b722c0c..863366f43083d 100644 --- a/src/importexport/videoexport/internal/videowriter.h +++ b/src/importexport/videoexport/internal/videowriter.h @@ -36,6 +36,12 @@ #include "notation/notationtypes.h" +class QImage; + +namespace muse::draw { +class Painter; +} + namespace mu::iex::videoexport { class VideoWriter : public project::INotationWriter, public muse::Contextable, public muse::async::Asyncable { @@ -74,6 +80,12 @@ class VideoWriter : public project::INotationWriter, public muse::Contextable, p void doGenerate(muse::media::IVideoEncoderPtr encoder, notation::INotationPtr notation, const Config& config); + bool generateLeadingFrames(muse::media::IVideoEncoderPtr encoder, notation::INotationPtr notation, muse::draw::Painter& painter, + QImage& frame, const Config& config, int totalFrameCount); + + bool generateScoreFrames(muse::media::IVideoEncoderPtr encoder, notation::INotationPtr notation, muse::draw::Painter& painter, + QImage& frame, const Config& config, float totalPlayTimeSec, int leadingFrameCount, int totalFrameCount); + struct ScoreRestoreData { engraving::MStyle style; From 156980a2f8011dacb41d1fcf02465a250f453a50 Mon Sep 17 00:00:00 2001 From: Eism Date: Wed, 18 Mar 2026 10:08:04 +0200 Subject: [PATCH 43/52] added made with for video export only difference is: v4, v5: m_ffmpeg->codecCtx->frame_number v6, v7, v8: m_ffmpeg->codecCtx->frame_num --- .../internal/ffmpeg/v4/ffmpeglibhandler.cpp | 20 +- .../internal/ffmpeg/v4/ffmpeglibhandler.h | 12 +- .../media/internal/ffmpeg/v4/videoencoder.cpp | 247 ++++++++++++++++++ .../media/internal/ffmpeg/v4/videoencoder.h | 2 + .../internal/ffmpeg/v5/ffmpeglibhandler.cpp | 20 +- .../internal/ffmpeg/v5/ffmpeglibhandler.h | 12 +- .../media/internal/ffmpeg/v5/videoencoder.cpp | 247 ++++++++++++++++++ .../media/internal/ffmpeg/v5/videoencoder.h | 2 + .../internal/ffmpeg/v6/ffmpeglibhandler.cpp | 20 +- .../internal/ffmpeg/v6/ffmpeglibhandler.h | 12 +- .../media/internal/ffmpeg/v6/videoencoder.cpp | 247 ++++++++++++++++++ .../media/internal/ffmpeg/v6/videoencoder.h | 2 + .../internal/ffmpeg/v7/ffmpeglibhandler.cpp | 20 +- .../internal/ffmpeg/v7/ffmpeglibhandler.h | 12 +- .../media/internal/ffmpeg/v7/videoencoder.cpp | 247 ++++++++++++++++++ .../media/internal/ffmpeg/v7/videoencoder.h | 2 + .../internal/ffmpeg/v8/ffmpeglibhandler.cpp | 20 +- .../internal/ffmpeg/v8/ffmpeglibhandler.h | 12 +- .../media/internal/ffmpeg/v8/videoencoder.cpp | 247 ++++++++++++++++++ .../media/internal/ffmpeg/v8/videoencoder.h | 2 + src/framework/media/ivideoencoder.h | 3 + src/importexport/videoexport/CMakeLists.txt | 7 + .../internal/resources/video_made_with.mp4 | Bin 0 -> 2026467 bytes .../videoexport/internal/videowriter.cpp | 42 ++- .../videoexport/internal/videowriter.h | 2 + 25 files changed, 1437 insertions(+), 22 deletions(-) create mode 100644 src/importexport/videoexport/internal/resources/video_made_with.mp4 diff --git a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp index d2af9e3f7bff8..da68fe592b0fb 100644 --- a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp @@ -66,6 +66,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); RESOLVE_FROM(m_avUtilLibrary, av_frame_free); + RESOLVE_FROM(m_avUtilLibrary, av_malloc); // libavformat RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); @@ -80,6 +81,9 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avFormatLibrary, avformat_close_input); RESOLVE_FROM(m_avFormatLibrary, avformat_free_context); RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_output_context2); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avio_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avio_context_free); // libavcodec RESOLVE_FROM(m_avCodecLibrary, av_packet_alloc); @@ -88,6 +92,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avCodecLibrary, av_packet_rescale_ts); RESOLVE_FROM(m_avCodecLibrary, avcodec_alloc_context3); RESOLVE_FROM(m_avCodecLibrary, avcodec_find_encoder); + RESOLVE_FROM(m_avCodecLibrary, avcodec_find_decoder); RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context); RESOLVE_FROM(m_avCodecLibrary, avcodec_open2); RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context); @@ -95,6 +100,8 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy); RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame); RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet); + RESOLVE_FROM(m_avCodecLibrary, avcodec_send_packet); + RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_frame); // libswscale RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); @@ -168,11 +175,13 @@ bool FFmpegLibHandler::functionsValid() const && avformat_open_input && avformat_find_stream_info && avformat_close_input && avformat_free_context && avformat_alloc_output_context2 && av_read_frame - && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context + && avformat_alloc_context && avio_alloc_context && avio_context_free + && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_find_decoder && avcodec_free_context && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_to_context && avcodec_parameters_copy - && avcodec_send_frame && avcodec_receive_packet + && avcodec_send_frame && avcodec_receive_packet && avcodec_send_packet && avcodec_receive_frame && av_frame_alloc && av_frame_free && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts + && av_malloc && sws_getCachedContext && sws_scale; } @@ -182,6 +191,7 @@ void FFmpegLibHandler::clearFunctions() av_image_fill_arrays = nullptr; av_image_get_buffer_size = nullptr; av_opt_set_int = nullptr; + av_malloc = nullptr; avformat_new_stream = nullptr; avformat_write_header = nullptr; av_write_trailer = nullptr; @@ -194,8 +204,12 @@ void FFmpegLibHandler::clearFunctions() avformat_free_context = nullptr; avformat_alloc_output_context2 = nullptr; av_read_frame = nullptr; + avformat_alloc_context = nullptr; + avio_alloc_context = nullptr; + avio_context_free = nullptr; avcodec_alloc_context3 = nullptr; avcodec_find_encoder = nullptr; + avcodec_find_decoder = nullptr; avcodec_free_context = nullptr; avcodec_open2 = nullptr; avcodec_parameters_from_context = nullptr; @@ -203,6 +217,8 @@ void FFmpegLibHandler::clearFunctions() avcodec_parameters_copy = nullptr; avcodec_send_frame = nullptr; avcodec_receive_packet = nullptr; + avcodec_send_packet = nullptr; + avcodec_receive_frame = nullptr; av_frame_alloc = nullptr; av_frame_free = nullptr; av_packet_alloc = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h index bc5ac1add118b..95ad9b4588b5d 100644 --- a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h @@ -47,6 +47,7 @@ class FFmpegLibHandler int align) = nullptr; int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; + void*(*av_malloc)(size_t size) = nullptr; // libavformat AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; @@ -62,10 +63,17 @@ class FFmpegLibHandler int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, const char* format_name, const char* filename) = nullptr; int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + AVFormatContext*(*avformat_alloc_context)(void) = nullptr; + AVIOContext*(*avio_alloc_context)(unsigned char* buffer, int buffer_size, int write_flag, void* opaque, + int (*read_packet)(void* opaque, uint8_t* buf, int buf_size), + int (*write_packet)(void* opaque, const uint8_t* buf, int buf_size), + int64_t (*seek)(void* opaque, int64_t offset, int whence)) = nullptr; + void (*avio_context_free)(AVIOContext** s) = nullptr; // libavcodec AVCodecContext*(*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; const AVCodec*(*avcodec_find_encoder)(AVCodecID id) = nullptr; + const AVCodec*(*avcodec_find_decoder)(AVCodecID id) = nullptr; void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; @@ -73,6 +81,8 @@ class FFmpegLibHandler int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; + int (*avcodec_send_packet)(AVCodecContext* avctx, const AVPacket* avpkt) = nullptr; + int (*avcodec_receive_frame)(AVCodecContext* avctx, AVFrame* frame) = nullptr; AVFrame*(*av_frame_alloc)(void) = nullptr; void (*av_frame_free)(AVFrame** frame) = nullptr; AVPacket*(*av_packet_alloc)(void) = nullptr; @@ -87,7 +97,7 @@ class FFmpegLibHandler int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]) = nullptr; -private : void* getSymbol(void* lib, const char* name) const; +private: void* getSymbol(void* lib, const char* name) const; bool tryLoadPath(void*& lib, const io::path_t& fullPath); void closeLib(void*& lib); void clearFunctions(); diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp index 06af363958895..2cca66581d663 100644 --- a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp @@ -22,12 +22,55 @@ #include "videoencoder.h" #include "ffmpeglibhandler.h" +#include + #include "io/file.h" #include "io/path.h" #include "defer.h" #include "log.h" namespace muse::media::ffmpeg::v4 { +struct MemoryReadContext { + const uint8_t* data = nullptr; + int64_t size = 0; + int64_t pos = 0; +}; + +static int memReadPacket(void* opaque, uint8_t* buf, int buf_size) +{ + auto* ctx = static_cast(opaque); + int64_t remaining = ctx->size - ctx->pos; + int toRead = static_cast(std::min(static_cast(buf_size), remaining)); + if (toRead <= 0) { + return AVERROR_EOF; + } + memcpy(buf, ctx->data + ctx->pos, toRead); + ctx->pos += toRead; + return toRead; +} + +static int64_t memSeek(void* opaque, int64_t offset, int whence) +{ + auto* ctx = static_cast(opaque); + switch (whence) { + case SEEK_SET: ctx->pos = offset; + break; + case SEEK_CUR: ctx->pos += offset; + break; + case SEEK_END: ctx->pos = ctx->size + offset; + break; + case AVSEEK_SIZE: return ctx->size; + default: return -1; + } + if (ctx->pos < 0) { + ctx->pos = 0; + } + if (ctx->pos > ctx->size) { + ctx->pos = ctx->size; + } + return ctx->pos; +} + struct FFmpeg { int width = 0; int height = 0; @@ -331,6 +374,210 @@ bool VideoEncoder::encodeImage(const QImage& img) return true; } +bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) +{ + if (!m_ffmpeg->opened) { + LOGE() << "encodeVideo: encoder not opened"; + return false; + } + + MemoryReadContext memCtx; + memCtx.data = videoData.constData(); + memCtx.size = static_cast(videoData.size()); + memCtx.pos = 0; + + static constexpr int AVIO_BUF_SIZE = 4096; + unsigned char* avioBuf = static_cast(m_ffmpegHandler->av_malloc(AVIO_BUF_SIZE)); + if (!avioBuf) { + LOGE() << "encodeVideo: failed to allocate avio buffer"; + return false; + } + + AVIOContext* avioCtx = m_ffmpegHandler->avio_alloc_context( + avioBuf, AVIO_BUF_SIZE, 0, &memCtx, memReadPacket, nullptr, memSeek); + if (!avioCtx) { + LOGE() << "encodeVideo: failed to allocate AVIOContext"; + return false; + } + + AVFormatContext* inputFmtCtx = m_ffmpegHandler->avformat_alloc_context(); + if (!inputFmtCtx) { + m_ffmpegHandler->avio_context_free(&avioCtx); + LOGE() << "encodeVideo: failed to allocate format context"; + return false; + } + inputFmtCtx->pb = avioCtx; + + AVCodecContext* decodeCtx = nullptr; + AVFrame* decodedFrame = nullptr; + AVPacket* packet = nullptr; + + DEFER { + if (inputFmtCtx) { + m_ffmpegHandler->avformat_close_input(&inputFmtCtx); + } + if (avioCtx) { + m_ffmpegHandler->avio_context_free(&avioCtx); + } + if (decodeCtx) { + m_ffmpegHandler->avcodec_free_context(&decodeCtx); + } + if (decodedFrame) { + m_ffmpegHandler->av_frame_free(&decodedFrame); + } + if (packet) { + m_ffmpegHandler->av_packet_free(&packet); + } + }; + + if (m_ffmpegHandler->avformat_open_input(&inputFmtCtx, nullptr, nullptr, nullptr) < 0) { + LOGE() << "encodeVideo: failed to open input from memory"; + return false; + } + + if (m_ffmpegHandler->avformat_find_stream_info(inputFmtCtx, nullptr) < 0) { + LOGE() << "encodeVideo: failed to find stream info"; + return false; + } + + int videoStreamIdx = -1; + for (unsigned i = 0; i < inputFmtCtx->nb_streams; i++) { + if (inputFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + videoStreamIdx = static_cast(i); + break; + } + } + + if (videoStreamIdx < 0) { + LOGE() << "encodeVideo: no video stream found"; + return false; + } + + AVCodecParameters* codecPar = inputFmtCtx->streams[videoStreamIdx]->codecpar; + + const AVCodec* decoder = m_ffmpegHandler->avcodec_find_decoder(codecPar->codec_id); + if (!decoder) { + LOGE() << "encodeVideo: decoder not found for codec_id " << codecPar->codec_id; + return false; + } + + decodeCtx = m_ffmpegHandler->avcodec_alloc_context3(decoder); + if (!decodeCtx) { + LOGE() << "encodeVideo: failed to allocate decoder context"; + return false; + } + + m_ffmpegHandler->avcodec_parameters_to_context(decodeCtx, codecPar); + + if (m_ffmpegHandler->avcodec_open2(decodeCtx, decoder, nullptr) < 0) { + LOGE() << "encodeVideo: failed to open decoder"; + return false; + } + + SwsContext* decSwsCtx = m_ffmpegHandler->sws_getCachedContext( + nullptr, + decodeCtx->width, decodeCtx->height, decodeCtx->pix_fmt, + m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, + SWS_BICUBIC, nullptr, nullptr, nullptr); + + if (!decSwsCtx) { + LOGE() << "encodeVideo: failed to create sws context"; + return false; + } + + decodedFrame = m_ffmpegHandler->av_frame_alloc(); + packet = m_ffmpegHandler->av_packet_alloc(); + + int framesEncoded = 0; + bool done = false; + + auto encodeDecodedFrame = [&]() -> bool { + m_ffmpegHandler->sws_scale(decSwsCtx, + decodedFrame->data, decodedFrame->linesize, + 0, decodedFrame->height, + m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize); + + m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q( + m_ffmpeg->codecCtx->frame_number, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); + if (ret < 0) { + return false; + } + + while (ret >= 0) { + AVPacket* outPkt = m_ffmpegHandler->av_packet_alloc(); + ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, outPkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&outPkt); + break; + } + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&outPkt); + return false; + } + + outPkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + outPkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->ptsCounter++; + + m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, outPkt); + m_ffmpegHandler->av_packet_free(&outPkt); + } + + framesEncoded++; + if (maxFrames > 0 && framesEncoded >= maxFrames) { + done = true; + } + + return true; + }; + + while (!done && m_ffmpegHandler->av_read_frame(inputFmtCtx, packet) >= 0) { + if (packet->stream_index != videoStreamIdx) { + m_ffmpegHandler->av_packet_unref(packet); + continue; + } + + int ret = m_ffmpegHandler->avcodec_send_packet(decodeCtx, packet); + m_ffmpegHandler->av_packet_unref(packet); + + while (!done && ret >= 0) { + ret = m_ffmpegHandler->avcodec_receive_frame(decodeCtx, decodedFrame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0) { + LOGE() << "encodeVideo: error receiving decoded frame"; + return false; + } + + if (!encodeDecodedFrame()) { + LOGE() << "encodeVideo: error encoding frame"; + return false; + } + } + } + + if (!done) { + m_ffmpegHandler->avcodec_send_packet(decodeCtx, nullptr); + while (true) { + int ret = m_ffmpegHandler->avcodec_receive_frame(decodeCtx, decodedFrame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0 || !encodeDecodedFrame() || done) { + break; + } + } + } + + LOGI() << "encodeVideo: encoded " << framesEncoded << " frames from memory buffer"; + return true; +} + bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) { if (m_outputPath.empty()) { diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.h b/src/framework/media/internal/ffmpeg/v4/videoencoder.h index 73c6964d2f1ab..0204179bbd4c1 100644 --- a/src/framework/media/internal/ffmpeg/v4/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.h @@ -43,6 +43,8 @@ class VideoEncoder : public IVideoEncoder bool encodeImage(const QImage& img) override; void finishEncode() override; + bool encodeVideo(const muse::ByteArray& videoData, int maxFrames = -1) override; + bool addAudio(const muse::io::path_t& audioPath, double audioOffsetSec) override; private: diff --git a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp index 8aa3c1508e76e..854f9bbd431df 100644 --- a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp @@ -66,6 +66,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); RESOLVE_FROM(m_avUtilLibrary, av_frame_free); + RESOLVE_FROM(m_avUtilLibrary, av_malloc); // libavformat RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); @@ -80,6 +81,9 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avFormatLibrary, avformat_close_input); RESOLVE_FROM(m_avFormatLibrary, avformat_free_context); RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_output_context2); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avio_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avio_context_free); // libavcodec RESOLVE_FROM(m_avCodecLibrary, av_packet_alloc); @@ -88,6 +92,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avCodecLibrary, av_packet_rescale_ts); RESOLVE_FROM(m_avCodecLibrary, avcodec_alloc_context3); RESOLVE_FROM(m_avCodecLibrary, avcodec_find_encoder); + RESOLVE_FROM(m_avCodecLibrary, avcodec_find_decoder); RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context); RESOLVE_FROM(m_avCodecLibrary, avcodec_open2); RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context); @@ -95,6 +100,8 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy); RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame); RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet); + RESOLVE_FROM(m_avCodecLibrary, avcodec_send_packet); + RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_frame); // libswscale RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); @@ -168,11 +175,13 @@ bool FFmpegLibHandler::functionsValid() const && avformat_open_input && avformat_find_stream_info && avformat_close_input && avformat_free_context && avformat_alloc_output_context2 && av_read_frame - && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context + && avformat_alloc_context && avio_alloc_context && avio_context_free + && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_find_decoder && avcodec_free_context && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_to_context && avcodec_parameters_copy - && avcodec_send_frame && avcodec_receive_packet + && avcodec_send_frame && avcodec_receive_packet && avcodec_send_packet && avcodec_receive_frame && av_frame_alloc && av_frame_free && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts + && av_malloc && sws_getCachedContext && sws_scale; } @@ -182,6 +191,7 @@ void FFmpegLibHandler::clearFunctions() av_image_fill_arrays = nullptr; av_image_get_buffer_size = nullptr; av_opt_set_int = nullptr; + av_malloc = nullptr; avformat_new_stream = nullptr; avformat_write_header = nullptr; av_write_trailer = nullptr; @@ -194,8 +204,12 @@ void FFmpegLibHandler::clearFunctions() avformat_free_context = nullptr; avformat_alloc_output_context2 = nullptr; av_read_frame = nullptr; + avformat_alloc_context = nullptr; + avio_alloc_context = nullptr; + avio_context_free = nullptr; avcodec_alloc_context3 = nullptr; avcodec_find_encoder = nullptr; + avcodec_find_decoder = nullptr; avcodec_free_context = nullptr; avcodec_open2 = nullptr; avcodec_parameters_from_context = nullptr; @@ -203,6 +217,8 @@ void FFmpegLibHandler::clearFunctions() avcodec_parameters_copy = nullptr; avcodec_send_frame = nullptr; avcodec_receive_packet = nullptr; + avcodec_send_packet = nullptr; + avcodec_receive_frame = nullptr; av_frame_alloc = nullptr; av_frame_free = nullptr; av_packet_alloc = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h index 18a844231ae69..b32abd991a3a5 100644 --- a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h @@ -47,6 +47,7 @@ class FFmpegLibHandler int align) = nullptr; int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; + void*(*av_malloc)(size_t size) = nullptr; // libavformat AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; @@ -62,10 +63,17 @@ class FFmpegLibHandler int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, const char* format_name, const char* filename) = nullptr; int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + AVFormatContext*(*avformat_alloc_context)(void) = nullptr; + AVIOContext*(*avio_alloc_context)(unsigned char* buffer, int buffer_size, int write_flag, void* opaque, + int (*read_packet)(void* opaque, uint8_t* buf, int buf_size), + int (*write_packet)(void* opaque, const uint8_t* buf, int buf_size), + int64_t (*seek)(void* opaque, int64_t offset, int whence)) = nullptr; + void (*avio_context_free)(AVIOContext** s) = nullptr; // libavcodec AVCodecContext*(*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; const AVCodec*(*avcodec_find_encoder)(AVCodecID id) = nullptr; + const AVCodec*(*avcodec_find_decoder)(AVCodecID id) = nullptr; void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; @@ -73,6 +81,8 @@ class FFmpegLibHandler int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; + int (*avcodec_send_packet)(AVCodecContext* avctx, const AVPacket* avpkt) = nullptr; + int (*avcodec_receive_frame)(AVCodecContext* avctx, AVFrame* frame) = nullptr; AVFrame*(*av_frame_alloc)(void) = nullptr; void (*av_frame_free)(AVFrame** frame) = nullptr; AVPacket*(*av_packet_alloc)(void) = nullptr; @@ -87,7 +97,7 @@ class FFmpegLibHandler int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]) = nullptr; -private : void* getSymbol(void* lib, const char* name) const; +private: void* getSymbol(void* lib, const char* name) const; bool tryLoadPath(void*& lib, const io::path_t& fullPath); void closeLib(void*& lib); void clearFunctions(); diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp index c6823bba62dac..6e77bf4be43e0 100644 --- a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp @@ -22,12 +22,55 @@ #include "videoencoder.h" #include "ffmpeglibhandler.h" +#include + #include "io/file.h" #include "io/path.h" #include "defer.h" #include "log.h" namespace muse::media::ffmpeg::v5 { +struct MemoryReadContext { + const uint8_t* data = nullptr; + int64_t size = 0; + int64_t pos = 0; +}; + +static int memReadPacket(void* opaque, uint8_t* buf, int buf_size) +{ + auto* ctx = static_cast(opaque); + int64_t remaining = ctx->size - ctx->pos; + int toRead = static_cast(std::min(static_cast(buf_size), remaining)); + if (toRead <= 0) { + return AVERROR_EOF; + } + memcpy(buf, ctx->data + ctx->pos, toRead); + ctx->pos += toRead; + return toRead; +} + +static int64_t memSeek(void* opaque, int64_t offset, int whence) +{ + auto* ctx = static_cast(opaque); + switch (whence) { + case SEEK_SET: ctx->pos = offset; + break; + case SEEK_CUR: ctx->pos += offset; + break; + case SEEK_END: ctx->pos = ctx->size + offset; + break; + case AVSEEK_SIZE: return ctx->size; + default: return -1; + } + if (ctx->pos < 0) { + ctx->pos = 0; + } + if (ctx->pos > ctx->size) { + ctx->pos = ctx->size; + } + return ctx->pos; +} + struct FFmpeg { int width = 0; int height = 0; @@ -331,6 +374,210 @@ bool VideoEncoder::encodeImage(const QImage& img) return true; } +bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) +{ + if (!m_ffmpeg->opened) { + LOGE() << "encodeVideo: encoder not opened"; + return false; + } + + MemoryReadContext memCtx; + memCtx.data = videoData.constData(); + memCtx.size = static_cast(videoData.size()); + memCtx.pos = 0; + + static constexpr int AVIO_BUF_SIZE = 4096; + unsigned char* avioBuf = static_cast(m_ffmpegHandler->av_malloc(AVIO_BUF_SIZE)); + if (!avioBuf) { + LOGE() << "encodeVideo: failed to allocate avio buffer"; + return false; + } + + AVIOContext* avioCtx = m_ffmpegHandler->avio_alloc_context( + avioBuf, AVIO_BUF_SIZE, 0, &memCtx, memReadPacket, nullptr, memSeek); + if (!avioCtx) { + LOGE() << "encodeVideo: failed to allocate AVIOContext"; + return false; + } + + AVFormatContext* inputFmtCtx = m_ffmpegHandler->avformat_alloc_context(); + if (!inputFmtCtx) { + m_ffmpegHandler->avio_context_free(&avioCtx); + LOGE() << "encodeVideo: failed to allocate format context"; + return false; + } + inputFmtCtx->pb = avioCtx; + + AVCodecContext* decodeCtx = nullptr; + AVFrame* decodedFrame = nullptr; + AVPacket* packet = nullptr; + + DEFER { + if (inputFmtCtx) { + m_ffmpegHandler->avformat_close_input(&inputFmtCtx); + } + if (avioCtx) { + m_ffmpegHandler->avio_context_free(&avioCtx); + } + if (decodeCtx) { + m_ffmpegHandler->avcodec_free_context(&decodeCtx); + } + if (decodedFrame) { + m_ffmpegHandler->av_frame_free(&decodedFrame); + } + if (packet) { + m_ffmpegHandler->av_packet_free(&packet); + } + }; + + if (m_ffmpegHandler->avformat_open_input(&inputFmtCtx, nullptr, nullptr, nullptr) < 0) { + LOGE() << "encodeVideo: failed to open input from memory"; + return false; + } + + if (m_ffmpegHandler->avformat_find_stream_info(inputFmtCtx, nullptr) < 0) { + LOGE() << "encodeVideo: failed to find stream info"; + return false; + } + + int videoStreamIdx = -1; + for (unsigned i = 0; i < inputFmtCtx->nb_streams; i++) { + if (inputFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + videoStreamIdx = static_cast(i); + break; + } + } + + if (videoStreamIdx < 0) { + LOGE() << "encodeVideo: no video stream found"; + return false; + } + + AVCodecParameters* codecPar = inputFmtCtx->streams[videoStreamIdx]->codecpar; + + const AVCodec* decoder = m_ffmpegHandler->avcodec_find_decoder(codecPar->codec_id); + if (!decoder) { + LOGE() << "encodeVideo: decoder not found for codec_id " << codecPar->codec_id; + return false; + } + + decodeCtx = m_ffmpegHandler->avcodec_alloc_context3(decoder); + if (!decodeCtx) { + LOGE() << "encodeVideo: failed to allocate decoder context"; + return false; + } + + m_ffmpegHandler->avcodec_parameters_to_context(decodeCtx, codecPar); + + if (m_ffmpegHandler->avcodec_open2(decodeCtx, decoder, nullptr) < 0) { + LOGE() << "encodeVideo: failed to open decoder"; + return false; + } + + SwsContext* decSwsCtx = m_ffmpegHandler->sws_getCachedContext( + nullptr, + decodeCtx->width, decodeCtx->height, decodeCtx->pix_fmt, + m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, + SWS_BICUBIC, nullptr, nullptr, nullptr); + + if (!decSwsCtx) { + LOGE() << "encodeVideo: failed to create sws context"; + return false; + } + + decodedFrame = m_ffmpegHandler->av_frame_alloc(); + packet = m_ffmpegHandler->av_packet_alloc(); + + int framesEncoded = 0; + bool done = false; + + auto encodeDecodedFrame = [&]() -> bool { + m_ffmpegHandler->sws_scale(decSwsCtx, + decodedFrame->data, decodedFrame->linesize, + 0, decodedFrame->height, + m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize); + + m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q( + m_ffmpeg->codecCtx->frame_number, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); + if (ret < 0) { + return false; + } + + while (ret >= 0) { + AVPacket* outPkt = m_ffmpegHandler->av_packet_alloc(); + ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, outPkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&outPkt); + break; + } + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&outPkt); + return false; + } + + outPkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + outPkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->ptsCounter++; + + m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, outPkt); + m_ffmpegHandler->av_packet_free(&outPkt); + } + + framesEncoded++; + if (maxFrames > 0 && framesEncoded >= maxFrames) { + done = true; + } + + return true; + }; + + while (!done && m_ffmpegHandler->av_read_frame(inputFmtCtx, packet) >= 0) { + if (packet->stream_index != videoStreamIdx) { + m_ffmpegHandler->av_packet_unref(packet); + continue; + } + + int ret = m_ffmpegHandler->avcodec_send_packet(decodeCtx, packet); + m_ffmpegHandler->av_packet_unref(packet); + + while (!done && ret >= 0) { + ret = m_ffmpegHandler->avcodec_receive_frame(decodeCtx, decodedFrame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0) { + LOGE() << "encodeVideo: error receiving decoded frame"; + return false; + } + + if (!encodeDecodedFrame()) { + LOGE() << "encodeVideo: error encoding frame"; + return false; + } + } + } + + if (!done) { + m_ffmpegHandler->avcodec_send_packet(decodeCtx, nullptr); + while (true) { + int ret = m_ffmpegHandler->avcodec_receive_frame(decodeCtx, decodedFrame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0 || !encodeDecodedFrame() || done) { + break; + } + } + } + + LOGI() << "encodeVideo: encoded " << framesEncoded << " frames from memory buffer"; + return true; +} + bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) { if (m_outputPath.empty()) { diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.h b/src/framework/media/internal/ffmpeg/v5/videoencoder.h index a3d19cbcad2ff..beff415cca53d 100644 --- a/src/framework/media/internal/ffmpeg/v5/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.h @@ -43,6 +43,8 @@ class VideoEncoder : public IVideoEncoder bool encodeImage(const QImage& img) override; void finishEncode() override; + bool encodeVideo(const muse::ByteArray& videoData, int maxFrames = -1) override; + bool addAudio(const muse::io::path_t& audioPath, double audioOffsetSec) override; private: diff --git a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp index d0d8c821b7f74..11879699f6a5b 100644 --- a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp @@ -66,6 +66,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); RESOLVE_FROM(m_avUtilLibrary, av_frame_free); + RESOLVE_FROM(m_avUtilLibrary, av_malloc); // libavformat RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); @@ -80,6 +81,9 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avFormatLibrary, avformat_close_input); RESOLVE_FROM(m_avFormatLibrary, avformat_free_context); RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_output_context2); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avio_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avio_context_free); // libavcodec RESOLVE_FROM(m_avCodecLibrary, av_packet_alloc); @@ -88,6 +92,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avCodecLibrary, av_packet_rescale_ts); RESOLVE_FROM(m_avCodecLibrary, avcodec_alloc_context3); RESOLVE_FROM(m_avCodecLibrary, avcodec_find_encoder); + RESOLVE_FROM(m_avCodecLibrary, avcodec_find_decoder); RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context); RESOLVE_FROM(m_avCodecLibrary, avcodec_open2); RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context); @@ -95,6 +100,8 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy); RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame); RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet); + RESOLVE_FROM(m_avCodecLibrary, avcodec_send_packet); + RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_frame); // libswscale RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); @@ -168,11 +175,13 @@ bool FFmpegLibHandler::functionsValid() const && avformat_open_input && avformat_find_stream_info && avformat_close_input && avformat_free_context && avformat_alloc_output_context2 && av_read_frame - && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context + && avformat_alloc_context && avio_alloc_context && avio_context_free + && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_find_decoder && avcodec_free_context && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_to_context && avcodec_parameters_copy - && avcodec_send_frame && avcodec_receive_packet + && avcodec_send_frame && avcodec_receive_packet && avcodec_send_packet && avcodec_receive_frame && av_frame_alloc && av_frame_free && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts + && av_malloc && sws_getCachedContext && sws_scale; } @@ -182,6 +191,7 @@ void FFmpegLibHandler::clearFunctions() av_image_fill_arrays = nullptr; av_image_get_buffer_size = nullptr; av_opt_set_int = nullptr; + av_malloc = nullptr; avformat_new_stream = nullptr; avformat_write_header = nullptr; av_write_trailer = nullptr; @@ -194,8 +204,12 @@ void FFmpegLibHandler::clearFunctions() avformat_free_context = nullptr; avformat_alloc_output_context2 = nullptr; av_read_frame = nullptr; + avformat_alloc_context = nullptr; + avio_alloc_context = nullptr; + avio_context_free = nullptr; avcodec_alloc_context3 = nullptr; avcodec_find_encoder = nullptr; + avcodec_find_decoder = nullptr; avcodec_free_context = nullptr; avcodec_open2 = nullptr; avcodec_parameters_from_context = nullptr; @@ -203,6 +217,8 @@ void FFmpegLibHandler::clearFunctions() avcodec_parameters_copy = nullptr; avcodec_send_frame = nullptr; avcodec_receive_packet = nullptr; + avcodec_send_packet = nullptr; + avcodec_receive_frame = nullptr; av_frame_alloc = nullptr; av_frame_free = nullptr; av_packet_alloc = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h index 10722a8763e30..807202a1fd4c5 100644 --- a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h @@ -47,6 +47,7 @@ class FFmpegLibHandler int align) = nullptr; int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; + void*(*av_malloc)(size_t size) = nullptr; // libavformat AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; @@ -62,10 +63,17 @@ class FFmpegLibHandler int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, const char* format_name, const char* filename) = nullptr; int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + AVFormatContext*(*avformat_alloc_context)(void) = nullptr; + AVIOContext*(*avio_alloc_context)(unsigned char* buffer, int buffer_size, int write_flag, void* opaque, + int (*read_packet)(void* opaque, uint8_t* buf, int buf_size), + int (*write_packet)(void* opaque, const uint8_t* buf, int buf_size), + int64_t (*seek)(void* opaque, int64_t offset, int whence)) = nullptr; + void (*avio_context_free)(AVIOContext** s) = nullptr; // libavcodec AVCodecContext*(*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; const AVCodec*(*avcodec_find_encoder)(AVCodecID id) = nullptr; + const AVCodec*(*avcodec_find_decoder)(AVCodecID id) = nullptr; void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; @@ -73,6 +81,8 @@ class FFmpegLibHandler int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; + int (*avcodec_send_packet)(AVCodecContext* avctx, const AVPacket* avpkt) = nullptr; + int (*avcodec_receive_frame)(AVCodecContext* avctx, AVFrame* frame) = nullptr; AVFrame*(*av_frame_alloc)(void) = nullptr; void (*av_frame_free)(AVFrame** frame) = nullptr; AVPacket*(*av_packet_alloc)(void) = nullptr; @@ -87,7 +97,7 @@ class FFmpegLibHandler int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]) = nullptr; -private : void* getSymbol(void* lib, const char* name) const; +private: void* getSymbol(void* lib, const char* name) const; bool tryLoadPath(void*& lib, const io::path_t& fullPath); void closeLib(void*& lib); void clearFunctions(); diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp index fa9f2c662c398..1aa98f33a2778 100644 --- a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp @@ -22,12 +22,55 @@ #include "videoencoder.h" #include "ffmpeglibhandler.h" +#include + #include "io/file.h" #include "io/path.h" #include "defer.h" #include "log.h" namespace muse::media::ffmpeg::v6 { +struct MemoryReadContext { + const uint8_t* data = nullptr; + int64_t size = 0; + int64_t pos = 0; +}; + +static int memReadPacket(void* opaque, uint8_t* buf, int buf_size) +{ + auto* ctx = static_cast(opaque); + int64_t remaining = ctx->size - ctx->pos; + int toRead = static_cast(std::min(static_cast(buf_size), remaining)); + if (toRead <= 0) { + return AVERROR_EOF; + } + memcpy(buf, ctx->data + ctx->pos, toRead); + ctx->pos += toRead; + return toRead; +} + +static int64_t memSeek(void* opaque, int64_t offset, int whence) +{ + auto* ctx = static_cast(opaque); + switch (whence) { + case SEEK_SET: ctx->pos = offset; + break; + case SEEK_CUR: ctx->pos += offset; + break; + case SEEK_END: ctx->pos = ctx->size + offset; + break; + case AVSEEK_SIZE: return ctx->size; + default: return -1; + } + if (ctx->pos < 0) { + ctx->pos = 0; + } + if (ctx->pos > ctx->size) { + ctx->pos = ctx->size; + } + return ctx->pos; +} + struct FFmpeg { int width = 0; int height = 0; @@ -331,6 +374,210 @@ bool VideoEncoder::encodeImage(const QImage& img) return true; } +bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) +{ + if (!m_ffmpeg->opened) { + LOGE() << "encodeVideo: encoder not opened"; + return false; + } + + MemoryReadContext memCtx; + memCtx.data = videoData.constData(); + memCtx.size = static_cast(videoData.size()); + memCtx.pos = 0; + + static constexpr int AVIO_BUF_SIZE = 4096; + unsigned char* avioBuf = static_cast(m_ffmpegHandler->av_malloc(AVIO_BUF_SIZE)); + if (!avioBuf) { + LOGE() << "encodeVideo: failed to allocate avio buffer"; + return false; + } + + AVIOContext* avioCtx = m_ffmpegHandler->avio_alloc_context( + avioBuf, AVIO_BUF_SIZE, 0, &memCtx, memReadPacket, nullptr, memSeek); + if (!avioCtx) { + LOGE() << "encodeVideo: failed to allocate AVIOContext"; + return false; + } + + AVFormatContext* inputFmtCtx = m_ffmpegHandler->avformat_alloc_context(); + if (!inputFmtCtx) { + m_ffmpegHandler->avio_context_free(&avioCtx); + LOGE() << "encodeVideo: failed to allocate format context"; + return false; + } + inputFmtCtx->pb = avioCtx; + + AVCodecContext* decodeCtx = nullptr; + AVFrame* decodedFrame = nullptr; + AVPacket* packet = nullptr; + + DEFER { + if (inputFmtCtx) { + m_ffmpegHandler->avformat_close_input(&inputFmtCtx); + } + if (avioCtx) { + m_ffmpegHandler->avio_context_free(&avioCtx); + } + if (decodeCtx) { + m_ffmpegHandler->avcodec_free_context(&decodeCtx); + } + if (decodedFrame) { + m_ffmpegHandler->av_frame_free(&decodedFrame); + } + if (packet) { + m_ffmpegHandler->av_packet_free(&packet); + } + }; + + if (m_ffmpegHandler->avformat_open_input(&inputFmtCtx, nullptr, nullptr, nullptr) < 0) { + LOGE() << "encodeVideo: failed to open input from memory"; + return false; + } + + if (m_ffmpegHandler->avformat_find_stream_info(inputFmtCtx, nullptr) < 0) { + LOGE() << "encodeVideo: failed to find stream info"; + return false; + } + + int videoStreamIdx = -1; + for (unsigned i = 0; i < inputFmtCtx->nb_streams; i++) { + if (inputFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + videoStreamIdx = static_cast(i); + break; + } + } + + if (videoStreamIdx < 0) { + LOGE() << "encodeVideo: no video stream found"; + return false; + } + + AVCodecParameters* codecPar = inputFmtCtx->streams[videoStreamIdx]->codecpar; + + const AVCodec* decoder = m_ffmpegHandler->avcodec_find_decoder(codecPar->codec_id); + if (!decoder) { + LOGE() << "encodeVideo: decoder not found for codec_id " << codecPar->codec_id; + return false; + } + + decodeCtx = m_ffmpegHandler->avcodec_alloc_context3(decoder); + if (!decodeCtx) { + LOGE() << "encodeVideo: failed to allocate decoder context"; + return false; + } + + m_ffmpegHandler->avcodec_parameters_to_context(decodeCtx, codecPar); + + if (m_ffmpegHandler->avcodec_open2(decodeCtx, decoder, nullptr) < 0) { + LOGE() << "encodeVideo: failed to open decoder"; + return false; + } + + SwsContext* decSwsCtx = m_ffmpegHandler->sws_getCachedContext( + nullptr, + decodeCtx->width, decodeCtx->height, decodeCtx->pix_fmt, + m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, + SWS_BICUBIC, nullptr, nullptr, nullptr); + + if (!decSwsCtx) { + LOGE() << "encodeVideo: failed to create sws context"; + return false; + } + + decodedFrame = m_ffmpegHandler->av_frame_alloc(); + packet = m_ffmpegHandler->av_packet_alloc(); + + int framesEncoded = 0; + bool done = false; + + auto encodeDecodedFrame = [&]() -> bool { + m_ffmpegHandler->sws_scale(decSwsCtx, + decodedFrame->data, decodedFrame->linesize, + 0, decodedFrame->height, + m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize); + + m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q( + m_ffmpeg->codecCtx->frame_num, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); + if (ret < 0) { + return false; + } + + while (ret >= 0) { + AVPacket* outPkt = m_ffmpegHandler->av_packet_alloc(); + ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, outPkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&outPkt); + break; + } + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&outPkt); + return false; + } + + outPkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + outPkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->ptsCounter++; + + m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, outPkt); + m_ffmpegHandler->av_packet_free(&outPkt); + } + + framesEncoded++; + if (maxFrames > 0 && framesEncoded >= maxFrames) { + done = true; + } + + return true; + }; + + while (!done && m_ffmpegHandler->av_read_frame(inputFmtCtx, packet) >= 0) { + if (packet->stream_index != videoStreamIdx) { + m_ffmpegHandler->av_packet_unref(packet); + continue; + } + + int ret = m_ffmpegHandler->avcodec_send_packet(decodeCtx, packet); + m_ffmpegHandler->av_packet_unref(packet); + + while (!done && ret >= 0) { + ret = m_ffmpegHandler->avcodec_receive_frame(decodeCtx, decodedFrame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0) { + LOGE() << "encodeVideo: error receiving decoded frame"; + return false; + } + + if (!encodeDecodedFrame()) { + LOGE() << "encodeVideo: error encoding frame"; + return false; + } + } + } + + if (!done) { + m_ffmpegHandler->avcodec_send_packet(decodeCtx, nullptr); + while (true) { + int ret = m_ffmpegHandler->avcodec_receive_frame(decodeCtx, decodedFrame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0 || !encodeDecodedFrame() || done) { + break; + } + } + } + + LOGI() << "encodeVideo: encoded " << framesEncoded << " frames from memory buffer"; + return true; +} + bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) { if (m_outputPath.empty()) { diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.h b/src/framework/media/internal/ffmpeg/v6/videoencoder.h index ebea7c493c7b9..f6a382bac549a 100644 --- a/src/framework/media/internal/ffmpeg/v6/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.h @@ -43,6 +43,8 @@ class VideoEncoder : public IVideoEncoder bool encodeImage(const QImage& img) override; void finishEncode() override; + bool encodeVideo(const muse::ByteArray& videoData, int maxFrames = -1) override; + bool addAudio(const muse::io::path_t& audioPath, double audioOffsetSec) override; private: diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp index f4b0ef89dacd6..648a1d8fb1da5 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp @@ -66,6 +66,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); RESOLVE_FROM(m_avUtilLibrary, av_frame_free); + RESOLVE_FROM(m_avUtilLibrary, av_malloc); // libavformat RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); @@ -80,6 +81,9 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avFormatLibrary, avformat_close_input); RESOLVE_FROM(m_avFormatLibrary, avformat_free_context); RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_output_context2); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avio_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avio_context_free); // libavcodec RESOLVE_FROM(m_avCodecLibrary, av_packet_alloc); @@ -88,6 +92,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avCodecLibrary, av_packet_rescale_ts); RESOLVE_FROM(m_avCodecLibrary, avcodec_alloc_context3); RESOLVE_FROM(m_avCodecLibrary, avcodec_find_encoder); + RESOLVE_FROM(m_avCodecLibrary, avcodec_find_decoder); RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context); RESOLVE_FROM(m_avCodecLibrary, avcodec_open2); RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context); @@ -95,6 +100,8 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy); RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame); RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet); + RESOLVE_FROM(m_avCodecLibrary, avcodec_send_packet); + RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_frame); // libswscale RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); @@ -168,11 +175,13 @@ bool FFmpegLibHandler::functionsValid() const && avformat_open_input && avformat_find_stream_info && avformat_close_input && avformat_free_context && avformat_alloc_output_context2 && av_read_frame - && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context + && avformat_alloc_context && avio_alloc_context && avio_context_free + && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_find_decoder && avcodec_free_context && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_to_context && avcodec_parameters_copy - && avcodec_send_frame && avcodec_receive_packet + && avcodec_send_frame && avcodec_receive_packet && avcodec_send_packet && avcodec_receive_frame && av_frame_alloc && av_frame_free && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts + && av_malloc && sws_getCachedContext && sws_scale; } @@ -182,6 +191,7 @@ void FFmpegLibHandler::clearFunctions() av_image_fill_arrays = nullptr; av_image_get_buffer_size = nullptr; av_opt_set_int = nullptr; + av_malloc = nullptr; avformat_new_stream = nullptr; avformat_write_header = nullptr; av_write_trailer = nullptr; @@ -194,8 +204,12 @@ void FFmpegLibHandler::clearFunctions() avformat_free_context = nullptr; avformat_alloc_output_context2 = nullptr; av_read_frame = nullptr; + avformat_alloc_context = nullptr; + avio_alloc_context = nullptr; + avio_context_free = nullptr; avcodec_alloc_context3 = nullptr; avcodec_find_encoder = nullptr; + avcodec_find_decoder = nullptr; avcodec_free_context = nullptr; avcodec_open2 = nullptr; avcodec_parameters_from_context = nullptr; @@ -203,6 +217,8 @@ void FFmpegLibHandler::clearFunctions() avcodec_parameters_copy = nullptr; avcodec_send_frame = nullptr; avcodec_receive_packet = nullptr; + avcodec_send_packet = nullptr; + avcodec_receive_frame = nullptr; av_frame_alloc = nullptr; av_frame_free = nullptr; av_packet_alloc = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h index 7e36da824ba7b..84a5f9b999bb9 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h @@ -47,6 +47,7 @@ class FFmpegLibHandler int align) = nullptr; int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; + void*(*av_malloc)(size_t size) = nullptr; // libavformat AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; @@ -62,10 +63,17 @@ class FFmpegLibHandler int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, const char* format_name, const char* filename) = nullptr; int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + AVFormatContext*(*avformat_alloc_context)(void) = nullptr; + AVIOContext*(*avio_alloc_context)(unsigned char* buffer, int buffer_size, int write_flag, void* opaque, + int (*read_packet)(void* opaque, uint8_t* buf, int buf_size), + int (*write_packet)(void* opaque, const uint8_t* buf, int buf_size), + int64_t (*seek)(void* opaque, int64_t offset, int whence)) = nullptr; + void (*avio_context_free)(AVIOContext** s) = nullptr; // libavcodec AVCodecContext*(*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; const AVCodec*(*avcodec_find_encoder)(AVCodecID id) = nullptr; + const AVCodec*(*avcodec_find_decoder)(AVCodecID id) = nullptr; void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; @@ -73,6 +81,8 @@ class FFmpegLibHandler int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; + int (*avcodec_send_packet)(AVCodecContext* avctx, const AVPacket* avpkt) = nullptr; + int (*avcodec_receive_frame)(AVCodecContext* avctx, AVFrame* frame) = nullptr; AVFrame*(*av_frame_alloc)(void) = nullptr; void (*av_frame_free)(AVFrame** frame) = nullptr; AVPacket*(*av_packet_alloc)(void) = nullptr; @@ -87,7 +97,7 @@ class FFmpegLibHandler int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]) = nullptr; -private : void* getSymbol(void* lib, const char* name) const; +private: void* getSymbol(void* lib, const char* name) const; bool tryLoadPath(void*& lib, const io::path_t& fullPath); void closeLib(void*& lib); void clearFunctions(); diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp index 3fe042e6d7db4..874944dd2c124 100644 --- a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp @@ -22,12 +22,55 @@ #include "videoencoder.h" #include "ffmpeglibhandler.h" +#include + #include "io/file.h" #include "io/path.h" #include "defer.h" #include "log.h" namespace muse::media::ffmpeg::v7 { +struct MemoryReadContext { + const uint8_t* data = nullptr; + int64_t size = 0; + int64_t pos = 0; +}; + +static int memReadPacket(void* opaque, uint8_t* buf, int buf_size) +{ + auto* ctx = static_cast(opaque); + int64_t remaining = ctx->size - ctx->pos; + int toRead = static_cast(std::min(static_cast(buf_size), remaining)); + if (toRead <= 0) { + return AVERROR_EOF; + } + memcpy(buf, ctx->data + ctx->pos, toRead); + ctx->pos += toRead; + return toRead; +} + +static int64_t memSeek(void* opaque, int64_t offset, int whence) +{ + auto* ctx = static_cast(opaque); + switch (whence) { + case SEEK_SET: ctx->pos = offset; + break; + case SEEK_CUR: ctx->pos += offset; + break; + case SEEK_END: ctx->pos = ctx->size + offset; + break; + case AVSEEK_SIZE: return ctx->size; + default: return -1; + } + if (ctx->pos < 0) { + ctx->pos = 0; + } + if (ctx->pos > ctx->size) { + ctx->pos = ctx->size; + } + return ctx->pos; +} + struct FFmpeg { int width = 0; int height = 0; @@ -331,6 +374,210 @@ bool VideoEncoder::encodeImage(const QImage& img) return true; } +bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) +{ + if (!m_ffmpeg->opened) { + LOGE() << "encodeVideo: encoder not opened"; + return false; + } + + MemoryReadContext memCtx; + memCtx.data = videoData.constData(); + memCtx.size = static_cast(videoData.size()); + memCtx.pos = 0; + + static constexpr int AVIO_BUF_SIZE = 4096; + unsigned char* avioBuf = static_cast(m_ffmpegHandler->av_malloc(AVIO_BUF_SIZE)); + if (!avioBuf) { + LOGE() << "encodeVideo: failed to allocate avio buffer"; + return false; + } + + AVIOContext* avioCtx = m_ffmpegHandler->avio_alloc_context( + avioBuf, AVIO_BUF_SIZE, 0, &memCtx, memReadPacket, nullptr, memSeek); + if (!avioCtx) { + LOGE() << "encodeVideo: failed to allocate AVIOContext"; + return false; + } + + AVFormatContext* inputFmtCtx = m_ffmpegHandler->avformat_alloc_context(); + if (!inputFmtCtx) { + m_ffmpegHandler->avio_context_free(&avioCtx); + LOGE() << "encodeVideo: failed to allocate format context"; + return false; + } + inputFmtCtx->pb = avioCtx; + + AVCodecContext* decodeCtx = nullptr; + AVFrame* decodedFrame = nullptr; + AVPacket* packet = nullptr; + + DEFER { + if (inputFmtCtx) { + m_ffmpegHandler->avformat_close_input(&inputFmtCtx); + } + if (avioCtx) { + m_ffmpegHandler->avio_context_free(&avioCtx); + } + if (decodeCtx) { + m_ffmpegHandler->avcodec_free_context(&decodeCtx); + } + if (decodedFrame) { + m_ffmpegHandler->av_frame_free(&decodedFrame); + } + if (packet) { + m_ffmpegHandler->av_packet_free(&packet); + } + }; + + if (m_ffmpegHandler->avformat_open_input(&inputFmtCtx, nullptr, nullptr, nullptr) < 0) { + LOGE() << "encodeVideo: failed to open input from memory"; + return false; + } + + if (m_ffmpegHandler->avformat_find_stream_info(inputFmtCtx, nullptr) < 0) { + LOGE() << "encodeVideo: failed to find stream info"; + return false; + } + + int videoStreamIdx = -1; + for (unsigned i = 0; i < inputFmtCtx->nb_streams; i++) { + if (inputFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + videoStreamIdx = static_cast(i); + break; + } + } + + if (videoStreamIdx < 0) { + LOGE() << "encodeVideo: no video stream found"; + return false; + } + + AVCodecParameters* codecPar = inputFmtCtx->streams[videoStreamIdx]->codecpar; + + const AVCodec* decoder = m_ffmpegHandler->avcodec_find_decoder(codecPar->codec_id); + if (!decoder) { + LOGE() << "encodeVideo: decoder not found for codec_id " << codecPar->codec_id; + return false; + } + + decodeCtx = m_ffmpegHandler->avcodec_alloc_context3(decoder); + if (!decodeCtx) { + LOGE() << "encodeVideo: failed to allocate decoder context"; + return false; + } + + m_ffmpegHandler->avcodec_parameters_to_context(decodeCtx, codecPar); + + if (m_ffmpegHandler->avcodec_open2(decodeCtx, decoder, nullptr) < 0) { + LOGE() << "encodeVideo: failed to open decoder"; + return false; + } + + SwsContext* decSwsCtx = m_ffmpegHandler->sws_getCachedContext( + nullptr, + decodeCtx->width, decodeCtx->height, decodeCtx->pix_fmt, + m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, + SWS_BICUBIC, nullptr, nullptr, nullptr); + + if (!decSwsCtx) { + LOGE() << "encodeVideo: failed to create sws context"; + return false; + } + + decodedFrame = m_ffmpegHandler->av_frame_alloc(); + packet = m_ffmpegHandler->av_packet_alloc(); + + int framesEncoded = 0; + bool done = false; + + auto encodeDecodedFrame = [&]() -> bool { + m_ffmpegHandler->sws_scale(decSwsCtx, + decodedFrame->data, decodedFrame->linesize, + 0, decodedFrame->height, + m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize); + + m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q( + m_ffmpeg->codecCtx->frame_num, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); + if (ret < 0) { + return false; + } + + while (ret >= 0) { + AVPacket* outPkt = m_ffmpegHandler->av_packet_alloc(); + ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, outPkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&outPkt); + break; + } + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&outPkt); + return false; + } + + outPkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + outPkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->ptsCounter++; + + m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, outPkt); + m_ffmpegHandler->av_packet_free(&outPkt); + } + + framesEncoded++; + if (maxFrames > 0 && framesEncoded >= maxFrames) { + done = true; + } + + return true; + }; + + while (!done && m_ffmpegHandler->av_read_frame(inputFmtCtx, packet) >= 0) { + if (packet->stream_index != videoStreamIdx) { + m_ffmpegHandler->av_packet_unref(packet); + continue; + } + + int ret = m_ffmpegHandler->avcodec_send_packet(decodeCtx, packet); + m_ffmpegHandler->av_packet_unref(packet); + + while (!done && ret >= 0) { + ret = m_ffmpegHandler->avcodec_receive_frame(decodeCtx, decodedFrame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0) { + LOGE() << "encodeVideo: error receiving decoded frame"; + return false; + } + + if (!encodeDecodedFrame()) { + LOGE() << "encodeVideo: error encoding frame"; + return false; + } + } + } + + if (!done) { + m_ffmpegHandler->avcodec_send_packet(decodeCtx, nullptr); + while (true) { + int ret = m_ffmpegHandler->avcodec_receive_frame(decodeCtx, decodedFrame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0 || !encodeDecodedFrame() || done) { + break; + } + } + } + + LOGI() << "encodeVideo: encoded " << framesEncoded << " frames from memory buffer"; + return true; +} + bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) { if (m_outputPath.empty()) { diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.h b/src/framework/media/internal/ffmpeg/v7/videoencoder.h index d81455d55cec2..21de8370dab05 100644 --- a/src/framework/media/internal/ffmpeg/v7/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.h @@ -43,6 +43,8 @@ class VideoEncoder : public IVideoEncoder bool encodeImage(const QImage& img) override; void finishEncode() override; + bool encodeVideo(const muse::ByteArray& videoData, int maxFrames = -1) override; + bool addAudio(const muse::io::path_t& audioPath, double audioOffsetSec) override; private: diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp index 380293388e2cd..484dfa896f4af 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp @@ -66,6 +66,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int); RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc); RESOLVE_FROM(m_avUtilLibrary, av_frame_free); + RESOLVE_FROM(m_avUtilLibrary, av_malloc); // libavformat RESOLVE_FROM(m_avFormatLibrary, av_write_trailer); @@ -80,6 +81,9 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avFormatLibrary, avformat_close_input); RESOLVE_FROM(m_avFormatLibrary, avformat_free_context); RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_output_context2); + RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avio_alloc_context); + RESOLVE_FROM(m_avFormatLibrary, avio_context_free); // libavcodec RESOLVE_FROM(m_avCodecLibrary, av_packet_alloc); @@ -88,6 +92,7 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avCodecLibrary, av_packet_rescale_ts); RESOLVE_FROM(m_avCodecLibrary, avcodec_alloc_context3); RESOLVE_FROM(m_avCodecLibrary, avcodec_find_encoder); + RESOLVE_FROM(m_avCodecLibrary, avcodec_find_decoder); RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context); RESOLVE_FROM(m_avCodecLibrary, avcodec_open2); RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context); @@ -95,6 +100,8 @@ bool FFmpegLibHandler::loadApi() RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy); RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame); RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet); + RESOLVE_FROM(m_avCodecLibrary, avcodec_send_packet); + RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_frame); // libswscale RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); @@ -168,11 +175,13 @@ bool FFmpegLibHandler::functionsValid() const && avformat_open_input && avformat_find_stream_info && avformat_close_input && avformat_free_context && avformat_alloc_output_context2 && av_read_frame - && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_free_context + && avformat_alloc_context && avio_alloc_context && avio_context_free + && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_find_decoder && avcodec_free_context && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_to_context && avcodec_parameters_copy - && avcodec_send_frame && avcodec_receive_packet + && avcodec_send_frame && avcodec_receive_packet && avcodec_send_packet && avcodec_receive_frame && av_frame_alloc && av_frame_free && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts + && av_malloc && sws_getCachedContext && sws_scale; } @@ -182,6 +191,7 @@ void FFmpegLibHandler::clearFunctions() av_image_fill_arrays = nullptr; av_image_get_buffer_size = nullptr; av_opt_set_int = nullptr; + av_malloc = nullptr; avformat_new_stream = nullptr; avformat_write_header = nullptr; av_write_trailer = nullptr; @@ -194,8 +204,12 @@ void FFmpegLibHandler::clearFunctions() avformat_free_context = nullptr; avformat_alloc_output_context2 = nullptr; av_read_frame = nullptr; + avformat_alloc_context = nullptr; + avio_alloc_context = nullptr; + avio_context_free = nullptr; avcodec_alloc_context3 = nullptr; avcodec_find_encoder = nullptr; + avcodec_find_decoder = nullptr; avcodec_free_context = nullptr; avcodec_open2 = nullptr; avcodec_parameters_from_context = nullptr; @@ -203,6 +217,8 @@ void FFmpegLibHandler::clearFunctions() avcodec_parameters_copy = nullptr; avcodec_send_frame = nullptr; avcodec_receive_packet = nullptr; + avcodec_send_packet = nullptr; + avcodec_receive_frame = nullptr; av_frame_alloc = nullptr; av_frame_free = nullptr; av_packet_alloc = nullptr; diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h index d684867d953f5..61333168b2972 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h @@ -47,6 +47,7 @@ class FFmpegLibHandler int align) = nullptr; int (*av_image_get_buffer_size)(AVPixelFormat pix_fmt, int width, int height, int align) = nullptr; int (*av_opt_set_int)(void* obj, const char* name, int64_t val, int search_flags) = nullptr; + void*(*av_malloc)(size_t size) = nullptr; // libavformat AVStream*(*avformat_new_stream)(AVFormatContext* s, const AVCodec* c) = nullptr; @@ -62,10 +63,17 @@ class FFmpegLibHandler int (*avformat_alloc_output_context2)(AVFormatContext** ctx, const AVOutputFormat* oformat, const char* format_name, const char* filename) = nullptr; int (*av_read_frame)(AVFormatContext* s, AVPacket* pkt) = nullptr; + AVFormatContext*(*avformat_alloc_context)(void) = nullptr; + AVIOContext*(*avio_alloc_context)(unsigned char* buffer, int buffer_size, int write_flag, void* opaque, + int (*read_packet)(void* opaque, uint8_t* buf, int buf_size), + int (*write_packet)(void* opaque, const uint8_t* buf, int buf_size), + int64_t (*seek)(void* opaque, int64_t offset, int whence)) = nullptr; + void (*avio_context_free)(AVIOContext** s) = nullptr; // libavcodec AVCodecContext*(*avcodec_alloc_context3)(const AVCodec* codec) = nullptr; const AVCodec*(*avcodec_find_encoder)(AVCodecID id) = nullptr; + const AVCodec*(*avcodec_find_decoder)(AVCodecID id) = nullptr; void (*avcodec_free_context)(AVCodecContext** avctx) = nullptr; int (*avcodec_open2)(AVCodecContext* avctx, const AVCodec* codec, AVDictionary** options) = nullptr; int (*avcodec_parameters_from_context)(AVCodecParameters* par, const AVCodecContext* codec) = nullptr; @@ -73,6 +81,8 @@ class FFmpegLibHandler int (*avcodec_parameters_copy)(AVCodecParameters* dst, const AVCodecParameters* src) = nullptr; int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr; int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr; + int (*avcodec_send_packet)(AVCodecContext* avctx, const AVPacket* avpkt) = nullptr; + int (*avcodec_receive_frame)(AVCodecContext* avctx, AVFrame* frame) = nullptr; AVFrame*(*av_frame_alloc)(void) = nullptr; void (*av_frame_free)(AVFrame** frame) = nullptr; AVPacket*(*av_packet_alloc)(void) = nullptr; @@ -87,7 +97,7 @@ class FFmpegLibHandler int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]) = nullptr; -private : void* getSymbol(void* lib, const char* name) const; +private: void* getSymbol(void* lib, const char* name) const; bool tryLoadPath(void*& lib, const io::path_t& fullPath); void closeLib(void*& lib); void clearFunctions(); diff --git a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp index b1e4ec72c77e6..973074cd73ff2 100644 --- a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp @@ -22,12 +22,55 @@ #include "videoencoder.h" #include "ffmpeglibhandler.h" +#include + #include "io/file.h" #include "io/path.h" #include "defer.h" #include "log.h" namespace muse::media::ffmpeg::v8 { +struct MemoryReadContext { + const uint8_t* data = nullptr; + int64_t size = 0; + int64_t pos = 0; +}; + +static int memReadPacket(void* opaque, uint8_t* buf, int buf_size) +{ + auto* ctx = static_cast(opaque); + int64_t remaining = ctx->size - ctx->pos; + int toRead = static_cast(std::min(static_cast(buf_size), remaining)); + if (toRead <= 0) { + return AVERROR_EOF; + } + memcpy(buf, ctx->data + ctx->pos, toRead); + ctx->pos += toRead; + return toRead; +} + +static int64_t memSeek(void* opaque, int64_t offset, int whence) +{ + auto* ctx = static_cast(opaque); + switch (whence) { + case SEEK_SET: ctx->pos = offset; + break; + case SEEK_CUR: ctx->pos += offset; + break; + case SEEK_END: ctx->pos = ctx->size + offset; + break; + case AVSEEK_SIZE: return ctx->size; + default: return -1; + } + if (ctx->pos < 0) { + ctx->pos = 0; + } + if (ctx->pos > ctx->size) { + ctx->pos = ctx->size; + } + return ctx->pos; +} + struct FFmpeg { int width = 0; int height = 0; @@ -331,6 +374,210 @@ bool VideoEncoder::encodeImage(const QImage& img) return true; } +bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) +{ + if (!m_ffmpeg->opened) { + LOGE() << "encodeVideo: encoder not opened"; + return false; + } + + MemoryReadContext memCtx; + memCtx.data = videoData.constData(); + memCtx.size = static_cast(videoData.size()); + memCtx.pos = 0; + + static constexpr int AVIO_BUF_SIZE = 4096; + unsigned char* avioBuf = static_cast(m_ffmpegHandler->av_malloc(AVIO_BUF_SIZE)); + if (!avioBuf) { + LOGE() << "encodeVideo: failed to allocate avio buffer"; + return false; + } + + AVIOContext* avioCtx = m_ffmpegHandler->avio_alloc_context( + avioBuf, AVIO_BUF_SIZE, 0, &memCtx, memReadPacket, nullptr, memSeek); + if (!avioCtx) { + LOGE() << "encodeVideo: failed to allocate AVIOContext"; + return false; + } + + AVFormatContext* inputFmtCtx = m_ffmpegHandler->avformat_alloc_context(); + if (!inputFmtCtx) { + m_ffmpegHandler->avio_context_free(&avioCtx); + LOGE() << "encodeVideo: failed to allocate format context"; + return false; + } + inputFmtCtx->pb = avioCtx; + + AVCodecContext* decodeCtx = nullptr; + AVFrame* decodedFrame = nullptr; + AVPacket* packet = nullptr; + + DEFER { + if (inputFmtCtx) { + m_ffmpegHandler->avformat_close_input(&inputFmtCtx); + } + if (avioCtx) { + m_ffmpegHandler->avio_context_free(&avioCtx); + } + if (decodeCtx) { + m_ffmpegHandler->avcodec_free_context(&decodeCtx); + } + if (decodedFrame) { + m_ffmpegHandler->av_frame_free(&decodedFrame); + } + if (packet) { + m_ffmpegHandler->av_packet_free(&packet); + } + }; + + if (m_ffmpegHandler->avformat_open_input(&inputFmtCtx, nullptr, nullptr, nullptr) < 0) { + LOGE() << "encodeVideo: failed to open input from memory"; + return false; + } + + if (m_ffmpegHandler->avformat_find_stream_info(inputFmtCtx, nullptr) < 0) { + LOGE() << "encodeVideo: failed to find stream info"; + return false; + } + + int videoStreamIdx = -1; + for (unsigned i = 0; i < inputFmtCtx->nb_streams; i++) { + if (inputFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + videoStreamIdx = static_cast(i); + break; + } + } + + if (videoStreamIdx < 0) { + LOGE() << "encodeVideo: no video stream found"; + return false; + } + + AVCodecParameters* codecPar = inputFmtCtx->streams[videoStreamIdx]->codecpar; + + const AVCodec* decoder = m_ffmpegHandler->avcodec_find_decoder(codecPar->codec_id); + if (!decoder) { + LOGE() << "encodeVideo: decoder not found for codec_id " << codecPar->codec_id; + return false; + } + + decodeCtx = m_ffmpegHandler->avcodec_alloc_context3(decoder); + if (!decodeCtx) { + LOGE() << "encodeVideo: failed to allocate decoder context"; + return false; + } + + m_ffmpegHandler->avcodec_parameters_to_context(decodeCtx, codecPar); + + if (m_ffmpegHandler->avcodec_open2(decodeCtx, decoder, nullptr) < 0) { + LOGE() << "encodeVideo: failed to open decoder"; + return false; + } + + SwsContext* decSwsCtx = m_ffmpegHandler->sws_getCachedContext( + nullptr, + decodeCtx->width, decodeCtx->height, decodeCtx->pix_fmt, + m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, + SWS_BICUBIC, nullptr, nullptr, nullptr); + + if (!decSwsCtx) { + LOGE() << "encodeVideo: failed to create sws context"; + return false; + } + + decodedFrame = m_ffmpegHandler->av_frame_alloc(); + packet = m_ffmpegHandler->av_packet_alloc(); + + int framesEncoded = 0; + bool done = false; + + auto encodeDecodedFrame = [&]() -> bool { + m_ffmpegHandler->sws_scale(decSwsCtx, + decodedFrame->data, decodedFrame->linesize, + 0, decodedFrame->height, + m_ffmpeg->ppicture->data, m_ffmpeg->ppicture->linesize); + + m_ffmpeg->ppicture->pts = m_ffmpegHandler->av_rescale_q( + m_ffmpeg->codecCtx->frame_num, m_ffmpeg->codecCtx->time_base, m_ffmpeg->videoStream->time_base); + + int ret = m_ffmpegHandler->avcodec_send_frame(m_ffmpeg->codecCtx, m_ffmpeg->ppicture); + if (ret < 0) { + return false; + } + + while (ret >= 0) { + AVPacket* outPkt = m_ffmpegHandler->av_packet_alloc(); + ret = m_ffmpegHandler->avcodec_receive_packet(m_ffmpeg->codecCtx, outPkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + m_ffmpegHandler->av_packet_free(&outPkt); + break; + } + if (ret < 0) { + m_ffmpegHandler->av_packet_free(&outPkt); + return false; + } + + outPkt->pts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + outPkt->dts = m_ffmpegHandler->av_rescale_q(m_ffmpeg->ptsCounter, m_ffmpeg->codecCtx->time_base, + m_ffmpeg->videoStream->time_base); + m_ffmpeg->ptsCounter++; + + m_ffmpegHandler->av_interleaved_write_frame(m_ffmpeg->formatCtx, outPkt); + m_ffmpegHandler->av_packet_free(&outPkt); + } + + framesEncoded++; + if (maxFrames > 0 && framesEncoded >= maxFrames) { + done = true; + } + + return true; + }; + + while (!done && m_ffmpegHandler->av_read_frame(inputFmtCtx, packet) >= 0) { + if (packet->stream_index != videoStreamIdx) { + m_ffmpegHandler->av_packet_unref(packet); + continue; + } + + int ret = m_ffmpegHandler->avcodec_send_packet(decodeCtx, packet); + m_ffmpegHandler->av_packet_unref(packet); + + while (!done && ret >= 0) { + ret = m_ffmpegHandler->avcodec_receive_frame(decodeCtx, decodedFrame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0) { + LOGE() << "encodeVideo: error receiving decoded frame"; + return false; + } + + if (!encodeDecodedFrame()) { + LOGE() << "encodeVideo: error encoding frame"; + return false; + } + } + } + + if (!done) { + m_ffmpegHandler->avcodec_send_packet(decodeCtx, nullptr); + while (true) { + int ret = m_ffmpegHandler->avcodec_receive_frame(decodeCtx, decodedFrame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0 || !encodeDecodedFrame() || done) { + break; + } + } + } + + LOGI() << "encodeVideo: encoded " << framesEncoded << " frames from memory buffer"; + return true; +} + bool VideoEncoder::addAudio(const io::path_t& audioPath, double audioOffsetSec) { if (m_outputPath.empty()) { diff --git a/src/framework/media/internal/ffmpeg/v8/videoencoder.h b/src/framework/media/internal/ffmpeg/v8/videoencoder.h index d91141900a1c6..be4f48b04f348 100644 --- a/src/framework/media/internal/ffmpeg/v8/videoencoder.h +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.h @@ -43,6 +43,8 @@ class VideoEncoder : public IVideoEncoder bool encodeImage(const QImage& img) override; void finishEncode() override; + bool encodeVideo(const muse::ByteArray& videoData, int maxFrames = -1) override; + bool addAudio(const muse::io::path_t& audioPath, double audioOffsetSec) override; private: diff --git a/src/framework/media/ivideoencoder.h b/src/framework/media/ivideoencoder.h index 348f8a2d937e8..ac9af44ce4c79 100644 --- a/src/framework/media/ivideoencoder.h +++ b/src/framework/media/ivideoencoder.h @@ -26,6 +26,7 @@ #include +#include "global/types/bytearray.h" #include "io/path.h" #include "modularity/imoduleinterface.h" @@ -53,6 +54,8 @@ class IVideoEncoder : MODULE_CONTEXT_INTERFACE virtual bool encodeImage(const QImage& img) = 0; virtual void finishEncode() = 0; + virtual bool encodeVideo(const muse::ByteArray& videoData, int maxFrames = -1) = 0; + virtual bool addAudio(const muse::io::path_t& audioPath, double audioOffsetSec) = 0; }; using IVideoEncoderPtr = std::shared_ptr; diff --git a/src/importexport/videoexport/CMakeLists.txt b/src/importexport/videoexport/CMakeLists.txt index 5c3ef1adf9047..66e27e3e356d1 100644 --- a/src/importexport/videoexport/CMakeLists.txt +++ b/src/importexport/videoexport/CMakeLists.txt @@ -33,3 +33,10 @@ target_sources(iex_videoexport PRIVATE ) target_link_libraries(iex_videoexport PRIVATE Qt::Concurrent muse::media engraving) + +qt_add_resources(iex_videoexport iex_videoexport_resources + PREFIX + /videoexport + FILES + internal/resources/video_made_with.mp4 +) diff --git a/src/importexport/videoexport/internal/resources/video_made_with.mp4 b/src/importexport/videoexport/internal/resources/video_made_with.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..8f8f316eeef9f3c630775d8b347fcdc92019318c GIT binary patch literal 2026467 zcmeFa1z23$vM$=V6I>E35G=U6yA#}@fySN2J;B{2xCcTYIKcx15;O#NcXtQ@UX!e> zz1G@$opbhmcfa@U_cFeoJ%`k&s_|FNs*yP-9RL78U}%t3VcKJf|26zmMC5rJ%+!N0MB`o10j%;t}| z@Cml2mO#iDnXTzx)(&uC20)Fr_z&eqb-3_^ zAovg50Dvc^KiCnOI)U!l-j{ops4h-6WIyU~4bEU=8%RCX8SMPstUvkzp+Hv?h}plF zKdSM)9YV1QITJzjHM#GEl>7eQ z#_rEhr;stv?;}6HAamfw0Dwmj4WNSmaTwJB0CblCK=6A2KuQq+*f<0Le9-}bkR$*U z6B_{VIR^l!-~|BI+W}Cq0sugD9snv2f}<=%OABfM6oxtgpwb0^l176-x&nYQNdN$Z zLI6;BivU0d1px3o9sskH1OUkR0|40N5O<`EF zAL{r07yot}=5XtOY2Kgp_&-JNH^^FXoWUmckn??k_yAKIS zu_Ztkas)b?g1-lWCpiCA`Ol340MOhf|L|{!f86W%-M=B{2RV>74CJ^kkT$~SALqYo zqclK9AYt?8_w?VhRRAERA2HCZhmA z0RWhpd4GN&-RLE1s$%!fz{U(|p+QDX(vE_(9}jwW@#!wuF0Xmtl%I9vapo)bONb*Dyo@yTAT2gk_!nU z^Skr9+d9~SAZf?l*2d16*Ij@dXlic^;)T@jyP3$zzLS8h1;|D22gtM(lp%S-2}H)j z$iiU4%*;l{#ly(M$-@lf=AtKKWoG4IVrFAv=44>u;bmdvg^d4J$OVzf_?=A6cvZwD zf0G7j36NWW!4AAkOm1#&jBad<_D<$ZEId3sOw6oItgH+W3I=BnJ223l!OofDp2ZIy z;vi=eCrbygrM(^5Jx`#qy$e`?oE$Pv_H!w=4!<+Eb7uU$EJhQ1TPAm)0}~4)Gt*y) z#TEXB-1Y~#xQ89k*3#sA%Ky_`XRx@X?cdD(O_Z~mhXaTSLI$#PhNui#$sZI2Tblg? zhCgX~Kk~0sRrotqe-meG`xgZzTp{562K1jK{KVpif+`?qdlx4Ykc2D94*Vw_O`JeL zu)UKA*#2);`Uir4(%97Gci|3@oy&I{o0>3zY(Nk^z|IhQmLK{;e34h|UJ?kh69Ng4 zL%fNTftihgg;R}%gO{0;mz7)RJ977g3Xsi;naBTt@H8_fE@6Mxy{Uv9tr*J6q8HLj>dsFoo>N{(B+f3cUB*MSDpnpe;z{yYg(zjLhH5 zPjT)71Tr)5u!GDPm?2eTW@dJFV;0~~*$@`u z_9ia(hW*LH6vBd)n~R&njM;>NgBt|l!_LgZzzsBJW8h{tWdnjh%%;Zd?0;YZQ4bQt zfHwcPSecsen%O(q0wJz1&B)5h{yln-@k3Sxv4p9M)A!Z?b{*b#xdLrm?s4S2x7v4Q zAd%#L!1)KjEKEG#N0{!T&`&=9u=+j5-?@E{2fS_&PTcIj@%hnZ0r6-S&Oddz*jYl< zbGSD(`JedyZe0_5(;sYq=mLfqT=KV7u`%D9|DNEF+TK%W{8-A*d;&=SbS9_E1m#d@= z(A-&ooB=}ho74S~&K79$F9iS{9BeFqFo66M_dXJ`a5J;;uyJ$n{8z$6Ak%*2!uuI) zEF2s>kWBHf1Oq{kKyC$z)bf^g*8j9V$fm==-r4fr&F^C(C+9y4bpqKz^1(9~kPAo# z46?l^`wg{f^2^T z$lV~fq#!qf_syI@e|qrp{eI}LuU`oKLf{tyzYzF^z%K-TA@B=eF5cq|_ zF9d!e@C$)o2>e3e7XtsMApm6ydBfaZT!u2nq@iC z=Le3j@iyNhr<2<$)}VaD&z2*i=FMfV8vLSzI1eKxVNYt-dSt3NBH;O9l zv0O)P>f!X3PkJ*lz}@`nt%VHFYnwoNJ{~OgBa*)H_vM}YH4cjB0_P6{>rzt}7eCDdcLExLJP~)bDhI1pp+%4 zt{UYw?uNyRh%G7ZHdA)+5I=L}x#Xz%txoVU1H6N?ZQD1km80~24Zc?0ZS}Y?onTDD zObra-JN89_-O?fm{b}9X3;kvZO;*qvfqoFLWY8U)#*Q+^$jjBwD>vJNnZ;A2|}m7L{u(FBqH;`-bIVf&!kZ30DW! z56y)w;TZ%5%(%Tw>D~PlQmG0xuMxBHj@;eqV%pN>W_Wew#fejvVLY@Q%+QSH#MH#Y zF=Q66WF8YaW9??9<`j43e7O@Z?XZf4gV(W3`ClIk)knN~8CjXPi-&|72PEQR#H6It zsc^T28$DY?5915*HdA{q9O$@P3!h;^jJ}-!120gAUve-MDm0*GFJm_sXiy8a6`dlv z@~|3O0q<2RJ0cPejj!1}x-3@cb*+VK&%j1)I@C19i5HJfiTpV#{N;?_XYn5OI&TEN z7lO>fu21&0WBjJnH)>i-?p7XJ=zm~jxx2e_Bg5mLc`g!lb&TEaJ zJj03wQ{u?yR}gQ9u8AmZRmAbhGmJnY6~_K449eROV`&)*3dSz$nP;K4vs8>t3ardX zkpe5)@0)6$;!1 zdo$xbubuMIxNNH~{p7vWV>QEK(3-eUbAuMPWg6;2vKURT5%MM4v=-qZ`Y8eofvqgP z3}cH=fB`~0rJ6rpArwuq(c}8p^d!WQ{n!*A5e&-giwGXsw%1;Ezl&WrFb9b)KmXPl zE#$=L9_2_+MPHWd_449^?{%L^SK3FgFdon{{?(Oe9)WMq+oye$gF5IQ`~>C!)hxr` zoG2dGAuZ`cU3U_S-v~o#(OZ|L&ad^qxNYEjc(ffuUzp^KMrwwd0YgdHg{KasG!nBY zgrtX>&_*CeaSbl0VmUFh?}Jq+n?2Mqdb8c_KNQE&ap8Y=sUWU`SI-j=%$}Ga4kJJf z446SGknkp)LSVG&5ofe~8`^bRvU1?c9<&l2Wt5G#&_kkUxxMx-8V|vceC@eNJ)Z+C z=fnO9H}9ZLD``a-ll8#1^;Ith`Lttl)@i>@e?trO&Aoc^dbk~iI&}QfwRg4{%h|zJ zen!vxyU6{8$pl}gQNkPunEGRuVm_(uaf_cKgpFfA_s&A0Va`A*DuyG7o*+}X+28D` z2}c;5*?!3||nc{|oIda7Qp>VgOHhRO0-HG;|vSq-$zpsm~lC`f&U=8rfURU=r?85P0BgMZ?3pg5}hj`)+%_XF+tINYLHk9%aA1~2sHL>wwsl{3_;5*(RyhRANT(C z10s14P=VdUag-MezwqhYD^7-^P(u-cz|cEUTp6*OWA1CrH<%xu*d+=GBHx7;e5n!Z z$ucOw3Oy~oB|twC?(C~&f_Bza(LVgpi451O@l-6R_TuDxn8^1o^-7+thUztxx#z2mu1LxmMM8H+H0?NJ zV|vcF11YwAsrt1swtYPqU!^Up#&c}R6gkW4G~8i(aEZ{$lYM7J zWnzG9Y}6s$VT>O0rVT`k?1>l867DW~s0ipcb_Hilh9jlFt99SZj%v1Ryf z=mz{bosY{1@oE<#%mB9+F zG3K>FAdw(9bs0vIbzQ8$yW~y5^US-MIy=wSj3pq;fhwFc63Cxh;1*oDIkfjt=7mO3 zhGSs0$%Dc~;0r4)Lq->D;zgJ-ojmE!i^A)^(c}LGMO>0r)qDAwV7q3T8h=_Qq z)U;Gq`t$nCG)gW~6-mRsSUt7yo=)ZX@cAx1a>s8AgRMjT<5140JC}&Q7pi;adx-Xv zxleOAfz z*g#kNRH?ovUyLeaM$V-d>$X!Ftirc2)kG(zGpM0Fe);jrd2nh&9CpsuR?yhp-vK2W%kx%P)|A+i}* z%Lh>kF)rTt8TwBxSQN5jrjaTmRH3LiXwJ~l$X1%A?dWbF?T67(^Cr8^8*K3MgRtZG z;!3Xq3y-TD4^^~>&m}9@Pb9mN=blj1#7m`gYQ>oOUS4`QY$0Gm+s~JB1RrHDbH+F| zsnNPJ7sN`ex$1Nz+n*KL4S9lF*#y!b1Z1j#<|S8$P2@+Y-j3b&m`N$TKaRZO}Y<0Smkh32J!gSXaXqDcNWETnvJ1pXLE0yEsrxb zL*W%G8TU~WR8RykOxKR}N|KvWlR-5$a66e6Jd5yc&01G&Q|vayTZbL|l8h@r6ZC>;R2> znS;BxVl_g&i_wH{b3Y}6cw$PIZ;1{wZnDYaFK=s)lI~3yuP47 z3PSlhmkVB&%ui#uiqj;vUV0@XY^8P6w@Xu={B@Tm&@^lu=VaU`3qyF}3)RaYSXMTm zz+B|}5xG5~>iFEjOPfv&c$qvBm@W)?mu}4*U-Y!Mapn zMY&V9lMDu6H(9)Qy4mxkw+Y-X*TTwq(C{;uo_ULkMBnzQro_(a8Bab=zceXvnqFZw zW#go)Gs8_T6?G{-5yYCIc_H4kMyzUIyS;3q?r*ch*m=<b;Ww!@iDs!;` z03(5u-Y#pXIbh(6XuK;~=YT+fR|{5gtHeaOzp9(|B#6R=P7=>P>;p|EFA-Y|$lRf! z487(qFPZ7Uas5Lxu9HW97IIC$@c}}$sC~2YvslDIbIX=HZzL~o@X2e0FqPYoid5Sq zIV0CxvKO;0gGQ_PP+t7Oljv7weQoVs)d3-OcEaa(y! zO5phRM7`!i?7nG>v&EApD5bNryQ@92U8WtmRk@I&8Pvl8QqRCqu)d(#LzM_RY=rZW-5Zv1B0}&_}RkKPj>;nj;=SkyolKXh#lrxg&)Z zk2pK%@7j;uZCH}!s!+|V5H@K5W3`7>Q7cHq=&I%`ldLYn&%?FTU3pjC|0of-%Amqu zSG;eBa|o6^eKTTXbJ!s{;QX1JsRCVuNshW)JOFzJfFnWFPfR;_l?&aWwAHTs^bNi5 zu2=U!PVKg(|7TE|yY7Bbp-SceJgytY3tFtK;5^Rw=Q?=Q)CZ2=q6k+u>S&OuMjxTQ4Rlq_Yr3`5M7;vBPH)ZkPQ_3h*iMm_uc@bxN_)B?xxBW*)& z46SrGZjZERg|C-zMF)pRrE-iLH%Mm-$IGq)=#MrNSfaY2L@NtqsoWLZ@m}X11T$3euLu=+gEI@3a0YDv>$|d;OPrO?soQGL zcTiwHP$)jV;&@e<^Tbc+kqwi92lIo<8@Ed>LkeR%<<_@u-odGxC@_QQN+mgOBOhZj z^YAna(O57vkcijVrR=aHG$rAM+a-1_#~xkbbfT|lc+z8q)e#;s5d4VuBIahMqJ!^w8;$bkM|=@wueYvlkLwmk@7^`!*fsEqoTne8Yq;iP}P~Wpb)W>M<>P0j;(+aIQDx)HtWCji7$95KF>*tCeC7S`stFWONaeRxdp9<0P z<+SB+K?k(Xr5vF*X$E;vs|@>!E$Lsn5p{5RSFAs;BKe1k1U-f$NKC&H-aT?8Tb{%^ zgNxAFym)i7Sc4SB8sx`o*w;V*g&-16BnBbTjB+_ef(y5%mC6S=~wZvP(02IH7Fd@n^KDlFb@9jPhHLBc?LD z5-H;EuaWV$b$<{V35x$n>6~eyL;aUKNB$@7me2*i6rGcl%cobnxztis$dqN)f-DG2<g*t@Qz;K%moY$?(`J5od zu_s8ekD`U8-l`CVIHYZWy$(Y6Qe5}&vb`>RkW;{^^>r!!p_p-Tvxj2lszdm9S~p}$ zY=vFg{m8EJST9OpZI}b1zJ41r3RQBf;ctgR*knD3w8J{veVNKkcTwGfDn7E8EOcHq z<;beY(v*Ds49zK)<~HM9QC zt&Zz@APBaP8lR7OGSKD4Br=^M%SWD&G^RGr)ln-rf7sUV(&%Mo?t1KELc$< z3#%JEPlMJBfE8pjbu*Y&Dvl!6s;9R<#-LE%%Tnn37&h;tgoSN9+U2N4TqD69fR!KX z$SkSe^x|mK?Jf3GJ2oeN5lJxW%Oh{1iUvakd?qxFW5;ZwOCQ=uk`lRgM=+YMPDDGA zf2S&vg031T>|B3Z?J4mk;|5&Qo1&DgHvRbWbmrTT>+AH#K`ruJzMN|cMo`~~`Td`g zdUB(`1P)ZvFu$5q_2W(36OFu{l3e3MoPSHn&(>vbufEMWvb{U?YJ5N67W(A}k0xl2 z7tCZC(Q|KLpR!IjMnsp3%xo-7bbhA}Sy+H~m%&}~{*ZV^ZUteyj$#jO$!Qd4e zKgW>DQFcq8#~NW$wQg!pKNd(hkA>$69r)4e9tRga&(l-wtd}Amj8kI-2;DV$Tw2jj z`(MI%8sD*N%s%2?PJgd=DOh?aK!3sEh6VlbnEgTmI_z4XiVf#{Li!sWzf1@xms09o z_=ScV@60X=i*8UnR-J8`kYZqa0E$yG7T!5SWkggU;nW)obweVsOKvu$TJCjzkIKmM0omk^=ist7dz&vU~mJwtM>JtJq)_+Qtilv;`8; z6ZxPf39Q4V%P&0-u}t&bH;vph9>n4kQKk60=Ng2uzb4zVj9xXcYbHEBkTV&PZW=GD zpDtU;oO~BugefY|Pm<`RsQs;=h%ds_=9N803r9ORB}4k6HfdXh(Sp@f2N{=)Zvm<< zW_F$HP;KGB0yW55~{9PEhr9>>`Q$OuC6cjHZtR20p z_ifs13fN2^M^CigI^ws6(7q&rdzH`M>toq>_^FNLlORn_a|M_~w!?e)D|i69zYmNLja#K>g% z48Ij(G(Z!f!#LH|)m@O`@@7|Mblw_8D|A?5bwk^xj#*ZtfZ5GIcVp{2i3y95;q@h#n8 zevn4wdQ*fRLyr_h5~)9E8dj(x#M0E{$#R>#LHgOL^1^jwh5#xLx3`2%R;Uo+vut3Y zXrIE29W{&0x8<`>!)*e2qiHYBDGx)nu&eEZ?KjcookJK0<}vrDbu=Cc0qcSRZgYMk zM^!f=MwUxAp^`)JSjX|)`@&m|Xq1R_XUDqGC1N&65=gg^wN@+}O9%CVe8+BKuw16H zf^@wKVWOqV20UpSmlraW;`;(mJ&j5oD?GKnOa*rtj7CJF-Mxv-8|FJsL_?krEh-cx+|Y+{e3|R)j!62H(y@nOs#8sAXI)`~ zJsE6NwZ?Zs4vXGDQ;uF9tu9Rl+mWrtZgAW8(ja>e%2*urMgN!j0jXEJYQZcq9mc?k zdKn*+b6hs)i5_wt+AYGhL-%0#*jHswpXK~VL4k(+E+OP0>`yBo{j$RU2dseh%L@N5 zS^@Gxf>D{sOISiNBViF(*SnP1rEd>M8s@(o)P=nL`=AI5`Q^_)zjOd^_2(Yg-aohD z+W*|Xe-+}-9DX%_A@B=<|3?sjdAxP;;O<7T;SJ6MZ;=N#T9}`UIA6Rwha&lA(*_I}Fkk&3KwTDDo3r0f zQunPjjN`F=q+;gABO@Pwl&QAVVQj5=L#<+{eDwN;r&`?O`(*@ieKL+v<=gP~wWax^ z*yp)w8HLvT96n|uABOcOsksT6Q*-2xd~Rd{#~xB`TcZeJds(YI3FiH(d0sWTX91H? zEp^Rrmo_u6in8xP!X!PiBR#JZ$wG1SE#Q%AXqG~9bR_@u4DjwGU5K%P+Vx`$|6oqM zr7b_`!Wh0I^d!m~Kea)?@0IG3(d4lvU(EjF>n+kN85Znr*TX#--P}Z0uMoSc;nPQ` zxe{L)-_#8(YHKqDa>bRkniB*bOgoA^_Q<YGR+9zhSVOqyKY|#5CY?q)RV+_}cRJ{n={b zIW8Bhw@T~gYOjYe2G)DV-4B)MtQ~Hi7Nk9u5~;m{d{(G2Cz6p#`zBn6wqH$k5FWm` zVF;RcpCZ>mvS2LL5p$$8x7&UY1f$g0npEe1a8guo9TsS`6KNA@OSrR!XOk4!pnsxf z^s=p%iy)IHwa5Q~RchDVYNETO$*2mamr`!N=I%ty#ozH*+G<^?|`&m)uxSZQ*&c04ft35BXFJTCOq) zCcZxq)mGP3P%i4M@JM5{tEbY;N@oBIIZfgVG7eQRdaE!(bb?Qr>JE4Rgb9sV7D6|{ zvpv{O#e6vr5!{}K>oc&e*;m~9$=Xmm9Qqy$P1)=?WONS@Z*$wz>#A+d5Pm&b20JXO zIm4~mhz%2l?ny<&{?Icio?-Ni&V@evJ>}uF7;-2*y+frzm(fU^iz$_K`j|oPXHxrw zO4;zlE||`Pp3g`JN8O(Gd}5RM)N_-A19<2-J(fO%UP_z3E|L3aY7g`a&t>EqGeLTL zO?9ima)bfF)T35eEq+(E5}yk%h(QeKH^i79EC%fiO-82YLPDQ^3U!%Qr)v{v;EBQh znj+U(9XT`%UzLk|TANF*iDg?4V&&X9Kg3Dv&AL$7LVmcqH0ogWP`8kn=G8+Nda!TN zyLmPXSr_2|cUq{mgU1Z7I1IEz=p0ZoL7c+lo$qFZTerjtiggWN3e&u!524!3vb3ox z^&d6l|BPhrvbmeeMm}U7hA5mI=ZyA_oX!6Uv)Qd*w+Owd(cp9BqrO+&c>$H5vlj_1 zYBke@x2H)W)aO~B50W#n8jdnvlYYt{vnnaypP%c-n{XmEA0bE{q(Q=!6QXBY)az4@ z+nLHchWv>6@0%7x#`^|LaA9JewP6eGm}Q1ZR?M!MLN3e%nZjC31J>7uY6+(o*5jEj zr@fc+k5yDv3W~iV%RMqhf=-I%UW;RD|k1=md$+&o^sH=`}PZ*lK(Un>O{vTt)` z(P-B>hUY<#rD95bse1MPpeHh`vuCG(XTp*7WNF2LkOpZnMa}DD*SdI=r&chEhZf|a z-yC!UE??ehQ5O@Qsc~(sfFtW`Stpy&CK?czk%&WL^36#WQGQG(bngSouZiIi6E|l? z-lM12i(1Y$l;d}8ejgUVUxxd}%lkbSQQjvKlW(R@IwC#@z?w`y+B-{R6*jA`d&2zt3*?lbnUbOjwGA))XD#X#wWyL>MJaH&+dfA|HOr9dXeD#4RD zzbK_U`J3GUT>3E8g^EtRDy!lAMUj!u80R`reo>ti(`|FZ=Ew>5^-{}kPoR}t$LL;U zU)^;2N|6@Hgl$+3$J3q9f)d(S0y!|4laWbifSx}4i29m+c*fb!A2xJM`QcI#-7O@W zuoxCK)wk6T!}aYh7Q zC_XZ8je{VFLWpcxV{gte_q`b7{uP(9vwnqYa@(|5iK!g%F|vdv`&QCr*vgEqd(Y$d zt-ifye1*3e23JQ;B=#lHf{##e@U%_7Qp}xY)9|;OJfLp_g$cxG(4^N=4#8Jtq_#_v z4}^}PDF^L9XLd`CEnO&~M8u}mB)(YCDnI<_nUg1lBpgQE4N6LV`g#t2DLpOrR-L!> zdI~;$wST^s8g!)g-tGAuve$mT7v;c0R)16GhD|HVegYh>)VfpuBf^NrqfrX1nB8oxB_7+xmcPqK= z4XRbi?)@6pkAf*dDHF9kogz_7ubY6m$TYdPsl@MjL+W`w+u5)K4$3_07)fYev))GP ziUek;6y=_LeVBlef|^u4znZ0NLFXu&mtlj=H8OPkMKspdNg+CFJg5MVvc@BqeI5lz zi5XE&lx6_7NYj2$b@Ezrh3K(&^sLF9DQUG)T8yQ|qrN=n4tyGsIH4~n#iex}Wiht~ z9%LWqS^K!c93Dr1@`wp#HAcX6xJnbbu8lJ)AXJaY%n+K@`i8-~FKHOAVrGJ<1zZ+yOC&>Ra~ z<}?4rr$@166wE_cA(sZUem&-vVJF^lB;vP13B+bM_|G|{E6CuGKY23s9pcw7*RU_! zKin!Z;N;*|#z`7$qLE<>5-(lqplM*AiR6Ul_r_D+?B|=21`zfnPFut%1*AMH=Bamc zOwUfpWLbYkAz11EhrkE}fEoahOcDodd`U95S|4IUK4F82+b@Xv?C!^}GBSMbjZE)i zzV4mCPFd4Xcsyi5No+SZ`LZwglWcZ=faq~b5oTCqA}>x5Hk|g@`Lt^?6x|ovqZKYF zffEPAG3cNjfee`pXR|R=6&G5X$$EC^wWjA!w0w!=@6Z>V&m~`Xabd2jJb7@wb=F41 z%GO5)eySEjh${&G^vWLR+H0B%v(C~>$dP{qPaJ-{xat!l@j&1tVkeIiRYCR_rj?rJ zeatt>tx^2)8ezIxc5(AUGSo?5mXWU>70jE2h48+wbIFe*j-4mIMS9gyl^ZlM{-D@g zHV%I)ah%b|WS8IRDTGfS39Oj4cJq^iYn zjHEOKflEv&0YG(?d8VY;H!b6?g4|>$6!D3TDukDW85t!g&qD-eDoOQpUz&*VCc-N+yOJ3Xf zaX)Q;JMvZg2ZTw#3_`|=&pIPJbnqLmUqnV|CEgr$l~iF~5y_0DU~=NWDDbXQ5r~vN z6t_9BsIzrAn%oNI)?*(!O*qrFWIwX!;@uX_v_)=DJ&UF*+N6G17~@|tf%M5Vh~@}u zaPDUQk=dwt<8I!EXw$B6JMD#?QuI?6*1mUgS($m}*v(l^DYC{+B&XGk%ylTI-06(u z#f`FC7z1M+I7P`jQQkS(E3J3ON+|(%iypu%xL(< z<16$O-4AoUT~DMUW)2-rdn@P3Ep|Kla0b`dX3^5@rKV-VI-3MZQTQZau6yd-2cqG4 zjZXPE@8b-4}0h!E40xET+g(xw-lV-LFim`-8uZh5V=neCB(q z1*213qtYI!@r0NB@1b9&o68F(=8KrYNvwBTOmK)`OiRef(Ce8T?0@8MV(Wzb&qBZN zSRfU6c*&0#)(0vYpPFrEv{IUEmb`^rJ&YuvjXd>25JkT!wKR2y6-M!dBJ%CQ?+Yi_ z5y7ur|7#xJ#d96J98;Wb+zOJEk{#)4~FCRm(R!2(=sqnHwkhn$#g)JNI6h^>wUAyh9(0AO5FI+y-*D0vI|7FFWy}fm zrB4KG`xJOsbj-DzW|x`wARaLYemh-N*o>!=jWTi@GQbXOo`^(`s^fK@b48~>xQ>ET zBA3riHbI7LFP_G{Ip;FV0hTO_w8I#w2eRoZhaC03%Nj8vr*oa^_M}xt{%BNsN4Mlb-3MoS`Kt)++;Qmn2Qv5*%VX0vD2<|!E{kM* zl~m`5CjgTkobM>S5qk*$8<#gCi616H4UP`#4)_f9q>6xLM7IGB=Kn4QyIL_g2j7^06hUnk;!l7;+`2R>x~h&!O% z*m%ziR2J=&tm6&$w0Y#)TSS?KFZ3ehEmm%skK2WZP6B{bZ$K zhTJEY{rNAqS7nSrR*duBZdX%W^)EEH^Xk7^5xi1?f^lQ0>WYC*X9qoNwVl7UGe|+1 z`p}f7-{LlO3#We2k@+d+YvWZ3mYN{M6&< z)ye!O@{-Y!*xhE=61#XDd4~j~z`CW~Ai*ak^lXDeEY!-fUFi-M!rKZ!%QLbEw9yvQ$e*wOTrM2l0^#;ZE0wIIDFvN_am zJ_HG=JMMn$(Z3iEe5W6M*>Blum}rHx0B=vNpn93FtLrZGR4r<#!8M7Ehk}b!ClA@? zw1r+iv+(8UKyr${-xt;f!Rm2_0__=kTgf8zx|Uoz+H*e8TtJ!(i@D`<>ASPsGboiF zxS0Wz1<|=;pX=RrpI5o=x@`&G`8KS`FJFamj$>9afw_uR3@90;RPq(<4YNG$l!E2>zVjU;uDwRuTX7aN;6zplfz z&HFbkFzv6Oe9ORPePQb8z}Mfi27mrZoZsq8O4>KNEcyf|pZ*KG&jvzQ?GIxMwiby* zbJY%HI*y1DIVt+uK6|?hl)2q>G_lS|s@G!{$Uv6|Hd+-je&G@6Y=aUQ{Z@Nyry=0% zA*O9-_Js3rz}vk?6{>C6WuYGVT#R-cNLjr~$U#bcM!soT<6F%ZZc31-j9Rm0%Z5Y7 zJ)ZQKV(5A@_2n1gZemdz`of)u(roUXpXkT(LKo6R@319dP#sA=`U1u@@F9OK_dr{j z^h@=LqatHK-Q)_7*Ko0jN2tG_5y63pfiwof!tX%%Ei?U(jZ z4iNVDoM~{u`c?TTj|c#wE$(C1rixb-gjLg7#c7881>HYtOh|P{qtXowqq@5*B=Nth~XVA_@1^U8i{95pHu}5Pb)t zSWfNxsk-9{iVjg?PWpFAh6xPu8ec^<#A8?GH*^zlWp876kgXpR~4bUM%S+KHz~Sw1LW z`I(rrEcfLVJq$7hM#+Xj$2h2;8Q}se$$0duM?aLyTUVYzs~5Cy-x;H6l8pK6O)uMg z@tViTeYAKE{d}Ze>(VGjhiYO>|L9WADWX<4h#IRMhL`IB^owj77oRU*-?bsA1-Y^k z#~2HddU(QU1m-D%KYh%_sgiPkV^VMi=d<)^R<5xR=R_@6r$LI&BI96fUj(o<=i9lq z9j6_I(do-w>x*85Uaak=F@gEY4fVaoQsr>)Rd}JB>(=_l6Y-FNyj@zGlZWemc4vcZ z)Zt@Dsl$GXlkXqSW8%BgyiaP*db&c9y?Fc#=u*=GUZNlJ&&kIS8YtjoXCo?^FxUb< zaL}1euEuIx4h^?`NQ&@pfn*)ix2f)-mH2w%)6Kd*ez0Op8GP)0ELFUaF7? z5Krc{XPg2WVd*$N9-o-t*Q)wbDz})}>`*fj_k{HnMyLxaeWX@GtlWU&J!d>q!WH}{ z7yj5LJ$8$>hpIlEiRx~r&$!1NX3UZ;9?7^#!4^CtL<%F|Q>h6w@r^Y8O4z?gjrPuf zmefMzk*UYm*y>|Nht_5RhB>(n8^!^(7I!0+*`+#K559obY-4lautW0eo^tFDtmA8u z+2QOv+uqWoBgMfF3S$?oz3dF;^@CQP37~F&e&Pf5oSY!uZi74y-{Nkm>b=^2m%#h8 zGt$@*DT)KeBkXkRM_CAy7|6mpw6;kfU6M>?y6Bm)I?x;BX;&)(4GRK~IOy2IeR(`G z;{*%E*N{*h-^^OVm;*{DQE791$4b z_Z-DaI6mSkf9+L)>&ENX5jJ_$hJx$ng!ln>yE4J6Co@3VWXt*~4Qn*^QJKPBZHeHf zWg8N`YG%2V#72mL1P!}nn==%KtqhucE5eobWY7jRlzBv5#WTbU=`}Xqu^&l7a0+@ z;Rq=@FKX9McOhOr!#U?%Eg69+KwC4s;%lisyE28 zA2>5isqW`3G#2uQY7n=e)6**Wo~qT8paP|disWbq%{lreGw33t z59OY@rF~TjH(@o8R>m5m$fTsZXoN1N$kZ32<-goP36Auyqp`z!b;3$V$KPVoVAl9$ zfI!F}!+4si5K~b*l$0|&Z=W>~$}ki*`U#(6E`tG5Ov_v~QM^Ov-LRVb9YYApDo))% zqhzQsyGteacw~JBL+7iM>FSXflYT+gxzBVo{Xh-JhD0?Sa8EX%SGsU(la-&JWQ~F3< zW0tmWV*NBc&a`5eldwjFUJBhvqplZx3ZQ&zJYxRgy7X9L)fMp_aroNH$eyo__D`r? z+^@?Sc%J8+C0DH;ZPT+L*QyzGz!_H`IG}TvBhGJ8zP6>n=h^I8l3kjr;kV_L7=U8t z4m<{9OlRE?W%wjMe8b=pY&xJVml2>7XlL|INbU;{p(_q)TmFcVrp9)~RMl4Pj>eXu zg=^~91Peqqrfw~riS^;CwIdu--NKubwcF5Dof=uLss-m$DLc1BUd}O zpg_}zfFsxOm_&TTql6+kXsO*}YJ{hA{TL+g20SEW-iym5)}U31WuN2zU+le8lV(x3 zt(&%Oo0Yb0Rie_iZQHgpD{b4hZQItn>wE`mogc6x_QkpzGsazyF(Z1k{`A(=cEYHT z%SPf0TTNPwclNR_RigEI0`>l7!)5IXWnbdp2c9fSguTT9mDO}lUMPy~t+sG$$b4i4E!`c7JyX^Nf(=R;JB-ImvJ^~u zaQI=d2CJ-3tK}P2w>ROzQ>AN6K=+@%aU#gU9U4Scx$i&r^O(h63}!dX3?c>4CuN0X zdp}`2(}<1BQY!h_SVG?fykLGMin6_P&7%KC^v&#;-@k_W^_ch<*kL=5541wXy$1Ic zIPFb9i7sknw2mpRO4jg`(HGRPVrPR~m$ueIf%B%xYsjW#J5L6OM&Hiut8$G}xB|HZ z7^5ZFt@@x)TBoa`el&1{P&}nTjPO%KH8x;9Td*>iVZ@*0oBMAyy#Jyq5lTqg%cr9V zqT&P$>FGYYPOu&9E!5td2p(pHhay3nvQ45+u7e_jhFQpi?zs-+SKw zOo%n8WY~ z1SsvA=mC{63n$iwrdLjMQm4nopt}dp&&F=p#`-c3bssdx%oEQf+aWR z|A(A%4mVvK72kX}dZpZQ(qfs^_~;4uS`f^*21Hzd?siGz>a-lpA%nZbasrg)I7gn1 z)TtS@)a@x^P-u^cfb;Fgg)8nX35b1g>hr5e+U|@}gh|i{Bij04@$HXrTn^0q-waRPH*CvTh6`&2o&-xR1huwe#@sJIS;8&tH zvF)A~=H($A$H4X&F+LGif~ylFgnx2Sd>V%21}y`Ht-^tB2MCqkkfZM+W~$Dw*t3tI zH>~=d%EyZb{+8dEto8zG549lQId8zc6yUu%fn=bXN@Gyzi_=$(kETx`2rO<=ppf5G z+c$!XKX2sX!q9b>=j5;2=Zm^Bbgw82cRKPVzW>u2m&`kfcp&Hw}h zrBcBI#hPnSR1qf4-HWkh8`XzmYB+Uq*zu6d@>^S*pij^yG&NFgAVDjZ(#`U`$SLq`;>a}U_*eBLCu#f z%wZuD;o&45Hwm*okj?8`F&n!aHJ_m4$SEei^G4*aH*_6zOYMpa@0Eip#?EU>3%6UM-2tVGg5a`D6H)3Rr>FwwW3`*mKJ?EG?3 z6A>l(q@QwN$%+dYFEJI#Je3&RarPno-cjQ3vdKq)*r46_(T5`*eSd&dG zHZLgTDhQC_)OFT@vb)3``HU;#=+jGj9pSWzba%xpkD%Nik~X7McytsjmbTB*-GN;b zd#5kP?-hq_QB*!b&huPg?A)$HDk|6QqZNVR#l4i!VftpyIq0^zt_1$WRAVgKvQuh!wYOpBaLI@u%Cmrc+3qv>fG(q0ohzR-XKPYN%@{idy z8`S52L+x5>2EBf?7<`@xd{3wZXV!E7CjYR(9T4Th#41x0{Z<^Rojynp?U1P7X<^go z$BGPG$Bqg9!>_SjS>6~lvd^nU-XMndM9t7N5Tl@TQ+SGYp0LHoeE`yijypUBjjG>_FPt3WOAL~Ct`JWl?f90-9u9Np*q~X zIGPQI+9!I040;yLuh`1cm>85NIr?LX)79`mUi4Og3y*TIVbnhF^#h0aPL|`Jq^9!^ z&{}~0>rP;j_E?Mx8P4^d-47voIcP#XIckG{G?~PKm;RoG*h~}it_f7zFqP3<_Lj01 zi&kHe^))C@sUXTo$pD@(!SZTUXNRks&cjqSYV+S3;n2}WE#ao%5uTk<${+rBcpNVn za}xXtSTV?5N(`L$8)3d|wZj?cR`f$>h}EfP(AKujv__pKlbP$|Byd&u@M-?7=v}6HYLaF@$|ep97%&>9b#wqc+5N#YE{b_adkDBy|IoVh)tdwlJr{{ zxv}BeHs+kG-)7V%)pkldY-|?=SgLCI<`+za_?Neos7=3uGIcr3h0;?9E}BdvgS04^71ktS@M4o@4!_i7cx1Xy*2EMFr~ z)vf*EYZk9)-J##Y8++aU(G;u(8T!$u$;qcj??Vl6&@x+M8V=)f4zZ9-R~7p^amw1l zV4)8*08&n45{la~VgI?HpOP|-tufxSx{eRXIz9B~<$~-lrvhcY^6;3&Sfm+Zw?$=< zBSzj4q!@AX)|zs-v345)RzkYzWql%2vebHq^nEvAx}H^bw>-O7ILz7AW~7+#dm-aD zW#zqVB7+{4RgsSU>2)(1g*IcX!)j~n$zP7PsMVS!_Y&>`%f@(RYx!C1{o;xW07o6l zdq^0#p=rFzp=y)*N?7TMfg{WOEpBLQslN*I_8VbZr5z{(l~kjg)Eu}egu_&mep_y^ z6&wdjA-Ot2li`C8v%iy)#B!Wz$C{>u5U_2?B2gw3QBOD#9uHY<^fxY92hUkc@7gaQ z@l;(95$K)j%~g^5hujt;R)9%ePe#QcBer$dZVRIlR`s$bU>y7C&&n5%kxdlvMm%z&>#L}66>g$NPLC*{*JREJX)}d?mAStx8N?o9 zB?`!3AB_meDouCblwK#_c!Qi}UW?-!XvFAGrkJCH({9koXeQ+Azblif*m5|)+I3!` zX!7sQ^eCtzl#b=DPKnls!ymTAx%VOvzCp;O^+aRIzFD|JTYVsl9z(V3lKAGHj4@9& zy%b+ol&-6HIYZ~>$ctz{lAq*sT%fE6l>NH(uS&7?5q+E?Qyq8_d9PPnRHfZyXVhso zuy8Te)9Z&+d9qAM;f$Y15|J%ZZ_4S?o%=Kz(13+h8zuCZKO@wEujG z?NR|n(2MwXMJrl#f+5`QijUo6p3NX!gZWG*}Brn*!V z%_Vn;qD*zwt7P^l#B99rt`{P4_nH2oH`cWA2-`V0p~~_UmB4wHTBvr$`(Bezmyc{9 zA^hTvP!TJa33c~fJm3pXiB-ZNH~nj#*YT@OIr?j@sgb_OB@}C>Fp($BsEbnvis9(O zn>pC>yR(AZ^2X}#;~Mwjxr~}Zq!lO;6MkBkiF!h&pyu4+aDBF&A5RWT+x`x<^2aGw zjJ3=hv>4yhdQCu2-5H@|J6@M4h3zn!TW#Tj!jqo9dI*iMto7MkZB7M0z`n5Duh~BJ zqzG0EP#uz+a2X221Y?J*@PVU2lxQW`xim3cr7xBdzRft^fA9Q7+mgs{HM?AMNZ-f6e31~bpdn3 z;yh|b9Z8rjl|&!mm0MRjFZm^UU;%jVI(|s7fFasx#~l}Q8oQ5ebMqRWsGUq5t@DJ)_GvQ6q1|6 zEC7Q#J1+swFJb1wdgQO*as<|~PH4rLeOwkJO{0`sHQ)0N6FZeMeb3-$RA46q860K0 z;hl^q5iAb;RE41ef~ii)`x&x>A6|zA6OqZOszNEoI=9SnxvL{xnFB*($7u9nNs?#j zC_~tZa1LrxPR*){HRdaOBkr3MLdYF&zObK!^1;U@S z-%titSoQZ$tBkCKcqy*ip|NKyFzY`3yY8DIl$%YO394SJ~IW_Df70E^TY z^TvNJy5WFux+U5M^^fDM*YlKO8_DlT$v1Le)&6SY>(GWN9x~>wu6|e#OoxJ()<|Rz z_wOD380|h^ED>9fhN)H_^@#XbAoA+w;1JW`kW^hw@<#!(xf>MF4O%(uCq28cu3zGM z@DZhIjo=}90S5{PSa|Nd950{8-UvV-Kl?g%yY1DDi6_%2-)vX2M9C$FA$YJ7AJi%i z`96aoHS>tP8ij&TQ!o~fC1=aOQy21SCV~x8bU37TH}nVuJE)QKYi7!%;`bmYymd=`i?E0|($Uf6;gKCaTy6J9j8=v`JZ-HvyZ$T^*wVr*cS6kmiba$Vtw3;pz+` z6B5tDTM>40r>qnrupwY{8-BxGGX+-F^c88%-hES3-Ow-OG;mg)O)sZZ1AM(xYYR2= zUVmQLWRD46x|Su@%UI)Mv(VQ20I@_bDKq)?D)#T`o0Wgzm18|<(|$BJejg_@3D$0@ zBqG`iNikp$GghEn=bpj|I_hESZfU!HlC456L%{4P4reu0>}a@P)s=uTdVg;duF>u9 zRa(MxL$-E$NNa>okPDH_fOORu9$U@k;LC(qy>N67Q|Z41t&j6He zuLW6+PD(?U%6!I0R=%%E!_Ru_eMI3C#qZ@zd;g|k*5FcfiS1YVW`c*>sK)W90i@ds zFVz_{Qxmi+hVmdLmSauVM>+>U`%K4OT6y%#OrV>1tYl=UR}~^Z3P<5F4DQHRj`B*- zui`|tH3XHzG?5j!IB7Wc!{7SUKTaW3<*98KHw(H+1e?~U@v{Vt=LlxA$%cJ~tAPla zETUQFNat$lof46TdD|btChF z{By1>^tLgEC80suxhcsNA~{`?s!hrPA5r@0NcXW-{;HA%) zMe@i%p*C&fSahN%jy=?LfwLasRk`a$%uNVE!hTqmE=a{aERxRN4d;?@`6!SB@;(+9 zhhW-=`b>BI0i2pNptM;vAhOffvCy=Eop)BnSg!U}^c7+s(-$I$h*|_l<$Wu^5zeOo zenjZI=J&wG;^IDKt$Z1ckCBu+rdd%7IBH72B7@C1>Ujg*Yclew_To=o*X=qWqUPC( z#NVy}rE3oRvt)s*tf9IF-cut1FHPrh(JEmd^J5}_Ua|>XDj!a1>dSh1IOoYu2N22B zMux3w0G3D7xXbCIOwG6v>KdWT{9Mvuzg+W#MqL6@C+cWm)<5*Ad@s`PGulQ-0S(Su)boVvN)$2QW8N8{()e z+)0toDD9rNC4uXkhOhN5A2{c8ktc~SD=1CkJ?(Ehto+MCaT4e|5-B}YtvJ`{8&x;I z&MZ5o2$Xc<+e}%-dVkS37TSDdRHtm60eF9RA$Y#+FTzt(9f{2s!*Xv`So9PdL8kpd>AZmz^ z3$!FBBb?1eI`daaf2Gu#r+Z9Tg0(JTL)^z*A~ufvAF-`#hCfr2x@31RKr`3Iv5A?R zc-I_b5^P{4zbm>1bCm)j0VA6dxJK(5nz?o-jsjFwMuSqki*+y#py}(3?rncOF8yB& z>lO7O=>x2JNdf&1EP*0jg2S`3voVC9#H<8eP_}zPfNRZ&%}tYyZ4!RzT+?R$I29g4 zS#02kZkM3NM3TJx1z~Uke5CI}l6X($hEtmpaBs=W#TO%jrdcpTbe!RBG#~m~gK!|- zfoowPownZ-;wf&Sv|)Iw{>9L;>!;gVuCGYXlaP?V{&XHlF%ik33NyXYA^fxMX^vh% z5wqi0)R;|2#o(=k_u6r;|6D@&I9_G7Q5^Gh5d8i9Hs@d*>^Kal_l>$`KK^|FP>TWH zh^|*81`p(D!|f7-Fi9&|qlGiVe4t+Jl{1hmx*&#(>&_(j#9!`F*z@FhV`y?z`g{0v z_LNB4w$yRx=#N|!)C{!3wHdgLu_58G+leE$7K}@t3l4%=BwtW?fd({^R~I3vdpJBj zP(p0t#IvtUwf%~*96xUmPv4vL(t8ayPP7cJy-2e%uH{RL2DOeaR}Eul$2!@@#0z>! zD!)4i7a>+l1;?w0opoeZa^yoQk;ReiAqmB#0@7bEk96OE*Ru^qtFJk%sR6==iB4?f zCGvuZDN`8cJf7UDTTy1V3vIcw|MM%K#e0N2jB*-~B9e$+DONG&5$p$S6AGjvR98ss zXe$MFi;J!6!IGi=QW`Y5FMXytYL`J73bD$T$KN@jM{%r=*;KZNjUaloh+xoa(0yTW z(jTOzCp{@F!ac-fzOVCgE(j6GiLKXMETKmiUQJTwZ|+z47U6jjWZ~-TziUURR9h=1 zn@QN5ExW+VH+=&giN0S%FU|W6^~<4xSFtcbSd@N3M>$cQyB5czWP#YeyT9)XUHGPo zpt**Jr>bq_eDA-3vbFZOKEHZ=<4ZX>BoFib((b-&KJ-})vh$1GPAnsgCX%dP39zQUgGj4igx3M&n}C~)a#CvT!fW( zCi))Z-qzOFE#iaKkqT{PYk{Bj%BjwMb4T_3)N2>bH?2o@C#Clmnk|OrM=%b&dJ=Pe zvlPa;Q0i8_u7cy@_XX`2!~n_O#|2SsMBmH|^s0dRROiyD^}_Z`F%91`5NjV$qaZdm zTYwxlb<)Hw?Z*EhmXzyJM&uSTn$9ALz#xIjfn^vK0BUw`;#+?M$!*Yg=+%>*q`Q*q z6R5Yt_M0)W)E}b@h|;x|+XvM7U}B+{bAXV0MnsSe&2tcLZG+Tg z2Eu3B&olAGnCflq#t;)hy?SVC&0$ZTVNirJfeiV_=sn^jT=>&qb?fvIJldqref;EpA_LQ<0Gz)Qr)Zle?3d5;$ z==)^DGz630#H@K$Noha%PP?OY?MrBMuj|10GS)VQlwDj{M0T!*i!nl6PqMU;DZBWb+{4XQ}AF{fYq6}tE7De&1 z7`~(ESIcm}`Xl#O>TW$-IBMfLGFEpJ#LdO42kqoCa!X7}<4!3&eqWD2HjWn*m3}P? zH)f*0K&P2mlQu6w*@5K?`$4e=bB@LhIn9e9w#xy@kn7BZG=;=LX#202@Q)GrC?|Vx zts*8}Ka*`;RgmA!>zGOa8tqxxef!x{XogO(I$MRsQGWY;gvD33-?2^__~A8TuQaJI$}4vDzQv#$HpXg39AvX5o{IQ$FhfA&@0sR>0RsC;0ZET*YPbT zO`5jEPP?1~_2}~Tp+LIcwTHQ>@+Cqr1=Q zD%iT;RUxx@=to!AABWHSa^~SlCx%=?3ehzyMghgPSn@~6XgbaT7d3Zp5N)?qbi-Fw zBu0$!&D9vbM<=Ua0cgjf>!0V9E`gy6Z@%#kS)&1T2=gvd+aP|={F82f*)T~I=+i=N zDae<3R^5GMdv{zR8Fnk^Ue)B-#_*%<4x#_Zt*QrzHD`@M)nYcdn2v-#gssmpSO;T_ zrKDC6J*KuBv@CsjhbHg;D7W>Wdd5S#a$12=Qi?wU2bXCbs_7KQEDHFTN{xcmsBAPc zqqAoD%3~%?NYCA1K8B9$0;rZs4hJAK-Y6(Z3`Q05C^FjgMvO|6dS(P*>E7eNEB&vO zIXqgWD7-hy{_6#U_H!ECdL0Huy7bZn+$oVi`ATgBKNHkY=4>2=Ud*9)>WNU z`6udD=Bulcn~f|F36DfS%Qt-)Bql4sf|&-A?23@23Z+BfWpx6j9qD4?VxVq$xF;;c zP%yjJpB(fY@cHwVG{43lu7$w9QJLGM=;`??C6gbRIh(giVEsnHX$H2~9AB|GxP?}6L|`;zAys;}!PH3`s3w2r(K6)< z9_~f$es%klE=SLme);FvDj5E**&%@P8fT1!=&Gy2Mf8rC>94v=h!2<=%~qPAG)glV zNE$}|bw$4L`$YGS)FZj`3`1QrvF^ZZvX{r(O&{`iFCjPsL}e{gKTu{~06)@(kLF0& zjQ`k|H7bt>5Va3eRS86Nd+cy9YOQ~fw4I`VLr8Sf2KN!H{!-M1Za3|fE5oXSK9U)6 zX=5Elj2%;Nj4oh#c=qhtUiBNELe3n56x;Zwr%|dM^1Uc@o-V4dD|^6*{yjb9r-jXz zY(=)T3H}ncL~Ep5A%e>ENGtb3%|dmZ&0S9hIuDNusW5?x1m9C{i`a=na<%6ylScA` zy4fR+RuWsm;+4jtQ%@`-(Jq3~x_gC8_i9r|znMI`J(Aqyn&Vi(j9MV8LKEIY0Kp*| zwZ(w;FE!8Q(Y5%Tb3f(zfr*kbFTG2U2BaFp0&ue|1kjnl%{3;ecL?{ zUVM^6BJHSA@X9uK0prXo4f1@)YxD*0t!e8i?|riL6u|Fn2e&*elvo^g|7#c+PGw>_ z@Tv5wq^U;v)|lp=df?rbr?tnY$$qk)B=4p@FH}>*ePo;Sa5%e*cr2a`rm6gC@(nBC z)%G9p_s}#_%hZt|i8xxxcxfv3J?`s)eIUY8r(OmQl|`W4Q@6$^=O9?vF-C!8&D{p*}_+aGLPlM8)BBMgl2_M-NX=5WnGI29U+-FkoD zfaEdT6!GaVLLb@Z!21Hc+z}^AQ!F0vSvL%3icDPy&4RCdyo5rt@5f06rdIs13<}ea z&$$J(X?h@On7EddoSfw6aYIOZxx$Ayyu(Igh?YAz zVclZ$jFbW6tt{iUH_6%3F}O!7;8?MNvn^vqqF2?RywjntZ$Pv8Y@DbPgI({xT%oS; zJN2prQ@ofot922uHF-QGt49!*we&W3X+#-D-GpVl==m%^?-ApoEU($y&O^w7PD){a zAwpqRFPS^!{VYp~vV0N-z=f_qD(+MMlscT2Es6h8OGitJ)Jad#i-15}maS3X8ZM@8 zJ-wSCIj>l!(h(Y;>A!_Pu>uQ(SY3>ru13H?-<4n;jfd731AGAv+9!RxTzU-EEPy}Z zu~egIJzrt^QaN8XgWvNEaADg>GtM6aXE1MJ33s6Mk_Lw`{aVc{T*+b;A`&$cdtry# z&rtR;xk4t&fhw9G?&OL#)#z+@2sDNCA($wqS_1;Z=4Jzw*_0I!F8M70(J{J<2APLS zgX{Tfi0AUmt>Lg_a;YH}IFt!&LZLPhqwb?K{0{~ZSP=8YG$apuZ*NJCIN63;**3i+ z0P{$J;JCnj5jD z`>>&Lm`C>#>Q_vTkolczaM`B7rxosDg}$l_-y&7XyFkFYCUxv6i7PnB{Qh6695LMxD8y_xfO%XN6I z_Z_8|cvQ7|c|q{gc>#sHjv>2#e5}Y<{&Yx$gKQ)N59|B@u1B>%WShW6oalblAKbv! zuI%pplQ5X=0e+JbvrN=L<#HGCQo z_C7Rtd)M3j_Oh#3v~lgfT`L&RE)Kc87%zMLImD;f6(y&pmQ9q0*Evbidr3 zB+tc6038W~6I$f5-J!hsTnV5%yoK%Hr;qe}gyDU4kS$2<-u2o@|J6+ZNwB-2es(SB zG(koYg(M@duqSBSP=|3e;FH?v^2%U}Nxe`~k55xb8}oMm@vp5VseIzMl3F3(H8nlR z<%KRG4(g$y8TAD}gPI+5@I)pZn~!?HdA$<_T1nDe7Y$v3o{Q!Wzn+_t6*L zXJcnNAjk4owvivnXvlSGbsF}C(KetHkH7IC7Gx$iYPxTW(j#Lp_`^`fOVl9dwbMMc z5FqT~RPXJu4c}lXP3%T5R5xBR2Ph4MkgDpNWTBs;2w(tJ|4On~iybtD-!b_%#sF-Q z?%I&_nc0Jx`5N&bgtWO`XU%HFk#-*sZVS)AfcG=579?c9jn%4SYu)R%8l>|mh!qdI z@&DB2IQ7Z_WdL+L zgb~d&xTG*;P*TYgELkrz1GilE!5>s3-Kjli`?uQ3rYbKwj#EF(+h(7Q-IM$Iz0cyQ zNsKE?2|p5R<$9`7b37314lqWF5ml6|uHdN#Oo!ue#=EUZ50x@LFtAd13g(vq+$-$& zr!3<-V;pg~EI&6W3y>ZDqLqu`XeDW_ofNRw&lxLUtZA6jC|t%m%J8=UYLVlDh~9Ti z@g$cdD&?Fs3#;1Vu3!yA1!AKwVd%_F*T={iC~!+8@D#HUrTX*8?D}se8S?L;IzCgj z6!oJY97KE6sC95O)CSvr=FJy={rh%U5Vtt%o$hL*I5|%(cF%EgA z3hUCE<+gWxq`;;$d0(wt?hIjn#S>xF>Q95Jf1_5`>Fp z82;qI>s1~9-qpBw5!u0Bz=d3VEH*L2wRN0v;Uj!mrj23><@aG<9bJ6!VBVg znxZ+o4h?b-#5?$<+v}{E;Vm$U=w(Z-&7>We4SY-}#qdHu2{2xaprn;m3rj1c8{U_T zqlEu!R!;zB9m1mt6y^^7Uk!}L$A-KHq^6d^%Oi7ww;wQF3H+< z|AiqSvJe6LJ9e~-Jr=VbW!53Cf-#E*`;X5V--z?IvkIH`Ra<5@%Dmjs%iu;xCV+0uatDgacR#!+dg z8K!i$y^Vt#ma~Dgt627v7?Fvq*dOT(>Nb=)4BA`NQ&Y zi-xR~o6M~fkuQxKmEgDh{)O;& z>Sf0^uq3GLxKphj6b{GUOv~#;5isuUjd9SJSZvL%{h26wAR8Wu5+?P9<;eHUPY6zt z(@x;?P+qtBW@mQm3Lwss?J#IzD@$;Kq-t3$X)(sX8^xjiILbsT?b(7MYeMGnD4$0q zLq_db>+rN{PrFc$(@y|#=BP6pr#-Tolfstl2f6Q(6w@q|@@=8)w)qrR1;i@A)O;-J zj20hq;^Q4g&m66N8!T5^Ox3S9wn|Ksy>jw=wEI*NO@MnSpC%u;IJM`qrDR?%l%Hhs zjKJkJAho_wLFlz~uTs|DeYszRWJq${0YF)E$DBHu)eG7Zn1ag}NKKI#hjR1NG zrRW@!jbO_zLN@>q8@1FacC<4uDPxt9BJ~1dyt3PJ)RL$}UEaz|B>A$6L30kRmw;*NHX(qtIWTat+_PSfg${L~0s9zOTji3hBTJ;;TX04M-RlBYK zf@!+MWwhY+|!1GyOVe zBL04kA3ok2bB`+O`0B5GpZk-CFT!194zFA{*YhLV+f^n+HtF!ROq#~2PxPV(W;=3*mUbw0cB|+^d&OS ze1s3TWD0EG^VMT{wrXv2-ftWSpG)@k#f*DVscbd>X^{Rey&M>Ew*R#=~#{XiQ~Rd$>EI;rWO_$Sy8LiXO)&hj~V63{22j~?;H)5oCHzvJ@D81 z1q#iv${1cClCMqKvuD#z8%)xZ_GM{OZre3*wsF?*v||wFV8j*mTP)1ZL?>enAV0-| zMb7EUb%|#8D#ct1cOi5=fmiCD)Jg?LA1;Rapx(J5ng1ufyE3FQR)^zARulI2XZ^t9 zEsQt^veb%2@gQ8YrX6M)f>x(Xa z`)e%#7RTBmA~>^QZftg- zu6lemjuI4hhQ-6H%z<8lKsQUj?zdmQD9|}~_1WUH!$Y7cB!Gjkxm>&kN{9m5-)!-h zJTvXJW@h;^f(1{x>(%>m^_rvy{@kS_m~-J{q6mH9CUps>?XNZekzb4ONLgQh3$2^_ zIy9Fi1L5a|#L`kd(~MTefRds*+vhq1pE{Ra&?praojTH9{Rns)JSGzN@WZ9B$=VOD zwyE->yc^#i9u`IXxP!|OoErb>@$+7Py=(&~ySbjL1&~e5v&;JH4WP+O8NX8#(R2Ky z_oZD+s7x*PrD+~4x~xtBT%gH@S!;vHl|Cu95TDhd741<=l9;Wdnlhb>1s}a|`tB-^ z1oR82bjUtpg4x4VZ|oY3`5IE9XjKNPSI?Icbn!;=^$|C}%sxMiI?d!MyMat?ujoqj z9z3-4;PF<8c9&1(%6|805Y;*p8|!FjvgT*AO)4VXd+vhb8+mT+KHoNU%9t}12)DYT zrx``w6cY!#g|MBW8tp!aXI~4CEd>3TUhfHTdP2ZKZD%hOQxYcNFYR^DG04@#>Y)qM zPF=+oTbY$&VlP&WSoDbxy#h(LqC|C!cTt4cm+@x8ZjkArc(Bo8;t!+;_>|#q;OWmW zTLl$8sJKU-on3SRwJ8SPCJ$NO9b2&-oc{#JdLil$V$*em7z&R^4;xNQ1kcQ}xGI82 zyS;^y7cCZH4HUL2nJ)^OQy4&n?zGBA$f0Xs5%$|@FMi7XO0g?wj;c(OBwyIiTOW6D zlWDu57i|I9o!Zx|pJ#5c3SREEt)Jm1WUO%(3vF^|X2!r^1wSon>w}C^eddl1%jX3F zuBe#N%V`%;41TYx%J4e?8``0QsN(z)6cAsrn!(9-oeLV0t0Q9TB!Ei#MzLN|nzKKH zA7hk6$jN>tBz*<9{GC8m$~|S)z|X^U7^vS4t5{Ta#q#`gLc-&Cx|aWRx1CXcid zWD4dy&v7B0LJ3y6;y?iHJ`R7_c5x24kc)o^$qP#k3KJ{DOKw%Iy|X5`xyMx^SEYP` z(JSzSmdvFhFs4I6D*0qo&WVG6<(^oE{#r9bU6WN&$PO?~yi@gc&6^AS9=!=?$0}7p z^LIIgbF6w(q4uhymI>?gP>c=NI~Hp8{(z{Q9{Nin#Cu8mD&`nY`<0-ngC0Pw*1|t7 z-)Aod6I9|AY!vvSu9)Rw-?1YR32Z#7uK`?LH^c~0)?uYr57376RN|UYV^za;%fTKv zwr5%SZKD98)4tHJml}0&kLrPDtqsnD=UZR?i)OFH=GFu<7scW07os?qLb=^ymol$2 z8yfmyu3T<`(Jw!o$v#XV-bETl)UtA4(Is@&`WOHB&miY($wLotFY@l%WF#mIso^r% z`)19&H?EavrylOcI6qxxzaOeyk?}AhhXkC66&$ssBfu5%K;535=B>h7_0KuYLCfcS zevs?(DQU~K%syt$ib`JHYE(IUd?g)Q#m0{5+3O;9bYVdcHL5R_ijH-*LzrXX%{sT= z;$zPsa4bPjCjMn%s{8I&LBOUMK4Wx%Fu7<(yXY_zqC;9C z=;zhckjCob?9|tRpypm(>8Jz%I6DCazPw)0=CfvIc9~eOVw?wtu%3lUl~O+yQ<4(6#GOTNU%kiVO?)2Q zlLPoS%lG?Qt>A6p0ZSk z&MM=bl?9tp_HA-Cq$&Y@vJ~&CwWtrE10v#7n9jYOfs?Qq(T1T88IYtHB$@&!i8PoF|<4sN`=(`?@kK4)7c1@v#i{?wC;hE>o` zkcP5&v!i^97CaD{-k0Dsa~{JrB5@6Wu!T;{pVrBG_~Xp?5Ttj%M#@Kp01C(A+Y+Y+ zdW0%95yF^}-bvCui~Ws9$2)W3Vg6wSXH?{poml$7YB*s^tm9;r^uVEYR6rBhQ(-!z z3B*Z)u%Iitlg0e}%^f%0tNc7wzHr|B<$*TU{hANw63v>iJ2+#xv{vwkQHblJ6{5NwkH1wauFjUFRRVFpX*)9Or@#~VaK|emEa@Rw zFIA`^U73qS%+U@=se@#Yn`py16FCd-Y(RravKn#^@x@v7kn7agJa~fb))E*l!R1K8 zUXWe*8Axc4OcYX^cwK@B-fF^n8br9}B zLVWN|yhO=#-Q<|%MF-)>R`a8L^mBh3Xsu`T>Kl@CzP86SQTd~9&hP2m4VN9BJd}49 zEMUc2Lv5OfxU~ji`F7stjU6zAa+Nd-kFjTPuyPI=Ko3Rb$%KG@1;G_iq6z)U%J{^kD|ZjE z1{1E^mY95)<{`-RNh-k6I0jK$VvNJO`ijnk5;PQT30qd*Hu(K>HS&(50c0}b7f$Tk zf02a#n0IWDy+oJ(Y-n>W(s3$fALmY$Ywf~E{7z9_L>aR^xb#WTRGq$cv9H_<3OGia zG2#}W``OoCRlndv*WizxO{zRhoOI8{?4jY#K}%N}g4@VtFQ3wbogIXopP%l&3q%+FSCy_68Hj+x1?=FNvhN%tCO*e14IEvsup`A#FvBe$HOWF9U zR@Me-A$uRNm871D_0@9^m(I!Xm$_un9Oy8q#-cFD`O?e{EBcpV<(%n;<8t4Gb7q^@ zj?jL&m@{tHC*ni)cgkmIJU2Q%)Ciy7%?3T;KVS_JClC<4wY1cmsE7D}(^o-3!~Xjh z5D?`5jqLru9uYvW_W%F;|L@{|4*yeu|Ea+LF%`g`1NwgwJZNu#b0N@6gy4Js_x`yE zKJ;g#D;O{6rSU&t&40F~DB3tnzYs^pOH6(<(&9Ta3?9zwI+))I#*en^`lh8hgrDd1 zmDXE7>jYD}gXl!OggCO*ZUy60zk)C(CV`s_SXq+Iorh*6^nK>U3y#EmQPck@M-YLp z-?OeepHoNxA&8}$`w2HW@y00|(TRtA8|Ng{RE09O9IAj)_SMswWQ<)_J8J@=`3w{~ zH7>VUV-b)%+t}_j${RS#H99SHBT1^vwqyN*EakXGl{Dx2|8O( zU$RPFlQ}reun)LF-m;m(8+`P<N`iA2=#wZF1{N8~%C8F+G-kd`cdX@x!Dd-bAjDmJBnMZ<&ZWKc38tCEz({ zvXb5zyn%J;Ix(fcXW}gRK_|@hbLiR-y4!f;s#^I3A5*3sqYHOEYm5`VpW`ia!9hQRmxxw(8jC zQ&obH^E3=>$2o1Nnmg9r1af1u8zXa{|GPZ)4fp2!{!rKZF!4v3#aeU|>5)dsd@mmI&aZ?;2!n^CM4~so;h86VHz0{W6sb~(Wze~(Oyf}(LQQ#7J z+5YB+I^$Qjz}`!Flv3&*O|Mj0Gi zOm;c+zBICh-FG4(EaInVLoK*U9rMgdWgDm%X#H67Ay80Er?^@&f7CI8x*fj+pb zbYSKFshj$!Wv*xXah%wWxB+>tFM4P=5e!EEMO3VhSm`*I zgVOjdirQn0gmLa?Vmi3q+obD67X``d{q0YAU2vtjomag}s)LDhh!#?(38DmUKwzFP zR)g){LaFsmgeP81ea%$hTd)*sr3XP1-N!zc9aG0;RxpEZxTOi70Cu2#7?QAr$FU~7 zBwHZ`N>Y8J(IuW%1Bfgx@AGIj{e;}V{~{X)E02J(6*of$_Qaa1P50Tx!M&2v{S%b- zJD}HTsLV=`v+GZ!L|AzkTJBQi+f8rxFB*Y&up!1;C)#!}Ao)W{;`&%RWKs3lMoZm? zZH~K;(CTUs65A#b{=%i0_F8Xd( zGLuRnqeg1H^}KpLU>YRVv~tOga$r0x*3&Xz`7zwyK5R1y0-*kJr@&0jAO`nNZ8604 z%ZYOS;{0DX+Q@Ew!>)cOkzv>BiQU9ubhHr3>I_$&G(5mm)iEMIOz^wHhZXSeubjle z0nm?d?1gn*_%~@zM1^7Lb^Fjao;5u;qX2 z&)zHKo+ievd#(+Kf~|23nMi~p zs1XpUFw`Y}5g-j#vamKRpd?Ji2AO|!(1)Bx$6DT_Qt*=E_i^u)zaQ&}T)qxD&wzGD z6q99jjmX~GVh?%5M{nyCL>kBtyEe%P0wNnDxTZPGPo#X zw;E2+I=;NR4GFvF$f1nIm({Sg#HX^b{~{W5ath@7Tpw};+mXcra~za^aU zm4&XoGMB$d6v#nHl#*p3v1_R>oo)e3Rji`d;Sdfjj`9LG0q>)Q8DMeqhGJ*@j` z@4)Ld!Vhr_u??~csc#1`yj9C1%YhREoX1&e~S^mK>hD;=%6Dc73?{pP@rg zXD?k&?!P?MsV`fPj%J}%p;&S>S5K~Z_1v()q7_hwf^F_%)Hp=kaD(gLX*ONH8%IPM z@KIi2iQwCVY6Pve$emocHwG)`P7-t-TJ;UXF&<;CB zy%a9*hP;cex_k;$K%nn`l0qDOI;$ps2Mi0LvH&6XV z0R0{S#E->srvVoW(v@RTz!M4$xp3F6)qS=I(;-)Xi}r1G9I`Ezn(OQjJ<9RsUqPw9 z2!K2DDiC612zYieU_K!@`YN=A>3HZho6v9|LLjn(JG|2ViT}k+hJ!{sf4YdHHVY*o z67-f(EGv@Ih(`^GRB}Z{V0=C;c&jB%B(6Csl!VxL`_D5vw4ZV_D(~wc`6eljaibfi(;NuDLK&6185??eo zltaeoFJl)0TW^BhxX;^1Y}Vse%-t&tD_zwlgeExlbywwW!)7_Wzb(!Un^mq zV-SI}bCE!UaqGeUsClR(%lt6UEo)2b0khgstjM+T{!=)%J%s~5eTsbOF@i2aN8V@+Vy$Gn%znk^L_AZHsL>u%R{YHtk zN9EV3`u_^D<_!_1keeG*)_OVIHD=aB&?|s7%fE7m>zRYIGc{r%=&uO1$^?EGl#Jc3 zf;~A07X_OBwt*}uP;wMS6A!vzOuEEz|{Y;*LPZhVZLyNL#c2(c&x&E^QiFi(I-O*b+3n>UFd z!?;Aw_D;b_D9J`px!Eln7^nA)6ls(OaaW2@6BLJ4Yr&6F3&y7eFg)d-4sq!CwfqNF zG&4cYY7)dnZT5$v(MWFB&%sS{=J4V=yE&Q${(J^w!8Tnu&Z=|}J}0o^p?ce^_lfWCsM9fQg$9L-=#nOsYcV)Pwz6%=?p?UK0iz95Y(^X7?Qzva zItz7+SHIfxEV7oa_{Eqj|O_7dt(3v$DT!~6M#y|;cDD4E-o9p@yGJ8_1`tJu) zw#%C{qOx+vBvCj>5(CE1$tG&nQ$EJ9VXLJfiYn8h%$Me0)zj?@TPqRp(QhTNw>^lJ zCUUL{gGM_=b>>W)O3vH_SBkWvGVFS$*1BfH9A=K_Q1)w_I=?r!0zN#_*w2wsgH8e4@E z>bjIJ#M-xr;xhRLM9he~WUHyjsyIbeIZWlMZ)SB!D;jewxa&I^bNkjzKZ>aubAqlz zRyRiJY+N$fWQTR;iuOVx!Rx6i$Pylr9aYZ6U}6?u zxzF&r6}*<|}Ionmf ztp3xte&G_>`9NyN_C)}g$h`%BMRaB>A(kIE-QXx-S6jwtD@|wug{RTVB`vE~7SOc( z4SAWAfH4EBIz`!ob0cNw%WP28;yc{C(0;nnrD*1_PAz3lJWjL)Y3W6VFIv#xE;l8_ z(u)X>nFU=={RpLMMaqVs)gUY{!pXs-^o2_pR=qL<#<(u+?@3-lnIwV4D+IbnWy~*D53Y$G~dh-REG7iEzgyGO0-nFY)e zXmjd|b^ZZc4!f3@Q7M3hvH(k^YDB6xX7(+hoKyvWUct`c+5?&0eFB7l@~geNWi}+x z4fggTI-Pe_PRbLhdTOl4?R%e7hx?u8?^vOH^VJPBSFIz%t)2PLW`Peethz{@MC$l; zACb*a{^G@mwB@O%VJH!jy%uR+^qbT^4Ts1*`PpUM^$1m5mSDW?1G=@Ob}}7%3G`gR z8--mZ9gLXh9Q~Ra3+K?l3%)(51I5_{QTBiU3{6uGJ=QwWLuSn(@<)}#oP2rug5mRM zSr``H$(DU<$s((97w9|H|8gY}B4|P6MAWA%_Bx#jjrlGcdJ{yrQ@54eJ;$f2U+zQM zo1T=`*p60)3)f}qKS&$BnIsPW$bibmlPrn68KOW~LQS;6xYV+MAb(sQqk7CZY_$cr zh0G{-9tH$Xy+2dCJMyURO}PJTSVxuBte;VKodNYzzl2D_a=GF;u!WQ=rW02 zl`Gu0n?)^1)pGuLuQDcU47w)kBZ*PRX=_Cp+o2>41Zw!r{NvCGlAft(8@=<>Kx@oEKK-9c&7knp$R1oPH?2n=FERCystaQkC?;-0GehA96bDG8i))4&3imvtSb=u!_&7**F2}FSZGiPE z4Iv=^X_%^Cbgpq&FkUrHd^GDl(sf*akv&M*g`W1HQ{V-k&}CwGr@?>O3w z_k@`Y$!$7%$g}Hp9{th>ua7)Dy&uvja{61dw}d!x?VTVWr&oaCKFhcs6IJvyr!P5 zF(-MDcB0d@>gh`otjo8)0=tY2%;$4&V!_*eashiB_Ux)GEkGi`9q`yq{A7yqa zn8?5iP*NhdijiaAek+6&)k#lOxDoUdC7Qsh0_oarKO9#<%mUL#XdU&ddc{t-Q(0CO zvRTm~YZ5*6RFpv>>o;Oko6^=f<%izbX)?(V$Aett5Soja4=DDW7h_7t3{eGsSvF_WHNe75am(LSHcn^6Ht(MGAJ{a zJ(I~kqzKm1<2RUmyWlV5M`qB52M(KojNY^Q?2iM>&Rf2px#6YM9C@ZxG@}q!v;vp_ zwn~b_Jp&-wxlCW6&ztfcBaOv@Hl9aO2jMmPz{Q^p>j)wjsg>qJu!9z;*U$(3pypqm z9WdM^)bSN~vK~wPEzTdD99j(!U^b6{N(;G}k%OD~!)<~3HpA*b8L!UMMm|+IEa56& z$eUEI;5m#N%)6MxIwi=nYbRMI6!q!H{CTH_?e=W4piHy*ov?VGBTDQeXs)%)7+Mq) zx9|zhbe|n{JveeWZyNSK(7;~23!-fvZt34)yj5JO>qeeVE5dIWxqs#%!8DFAh%*7T zFDtM0U#w7}6%tG5&dx@&LIlu%0Mp2e4Qhqk_^OtOSWw;90fh$7CVE>0GOZ$F@9@o5a{e^e3Q=EaLOSz zg1}9W%zex|i5zn#Ing26^@VogK+vxl@v_6LOT3)5*~9R=3P&tdkb(22;>Vy+TG04B z&C-2XNsap2rQ+PMDU|g0gp$ei;<6)gFR;&~S33C(4#Y$jFZv5Kt8GeRNvirxoWmIj zr8d_eWto59zdT~dpTU)AC1)k(IKVo>31>g8KiX#K|9QZ zl=Xs=dqJ+*C+rYOY}w5n66&RXW_}l+&k6Aq`&9c08184jR#!*J`h&+3B!)qtV@Zs)7YCESRam0`LI^w9w~rx zK_b*RW!*^(D81t2KUw75?h4pP(8nc}Re`ICszl>O<)OR%_a(;dspUz!{~=^QYhq?<^Ik#-1stoV-c4BeahTb8-s79>wIA?~Z`b z#h5_Au#R(-nqU_ecM>+j&&C+_)Bh(Y{ad+JGY!f^U zS9V&udq%ko)}%3r5Rd0tYt&m9T|0uLP}~8M`Zt1iQma(JL4rV*l{-qSww@GlABz9Micf|Gl?N>Q(T2Eq zNQ<(592LXm62`V;zBl7D2C7=`=Od&Ngqte<6|*i4C!bt}>jXpJpXjomg+qgZcyT&& zPeUZW0BUsF0a(~EkmN%l6p^ctekyb441CwSu}@FTmF%71n`I^UYd6DeVaM^b1}l;B z1LTn}s(QKqasn&_UG(sBn9CYEt)#P9&NRKMEvhSkus(StVwh{8fR8>6VEDn@C(^RX z%ojade)>)qqDr?*&&OiJ|G9HK{h4R5%CfNjzQn*9>QBzJPK_RE^{5m9xPRLf&RzCm zd`#x6VYC*zrD{}yCOC=0k)w%M=U$|} zm^ivTUU#nJDo+j4QT#KCo1d`O&lF|kX1g129V5-^PKM|6db%JydndL*J=jCg?RGw~ zNK?vyhk4mQQ%r(e$LUcWLHBG5<=r(x3W%(kB)yrT#!XKZX$zp5V>JR@LV&pCx@{f4 zg1y|h!`o@y+HXOxP(z-D`fJepLGg}T4lRTER~C7Wuug_tDrRGQrPX@lP64yzQ9s`VDNF8XN3+vh!Vg?~NX*HE`u7XO+oi|QPO8ex zyLLeMcA!9%)9=|otJM3rS?;8X(+4pVVZR?qmGlu5PjhRL7|%*4;YdoX8*RY(rv&(g7_e-xCUCnFmsz*uiLj0~O zmmNCvjH1lypQG~T;D?_?Eo2K*f+co28r%98{m4 z;hnplq)ezLcA|*^%xaj`R7q{4cqQLmk3U5-?M-9?K|3>uEw%@E=MQHQ@X zF=wIZM+EmPb*=27EM%Q5yxUNW`lE9yU$r`wb?(($#fL_z@_Y&gB=?B3nXV=Q8qsq@ z?jSR~eE{g3jA^bqB+|k8M(=z*U`gh6ZyYNm^9<`>LzOUECv``|e?P(_=>lVcQA`)W zUPKJXo#_~FxxGJVUT!YB85o#-;hK~^V|D1YB${bxpk#8kV6ZWq3msLPD4ZzVk6{O6}xv0 zbNt`sqPwP2QA$OFU8|^sBB_J{+MJk7BO2(*~XL zs}Rp-JJ*6Ye(I1jgqNWDuv{KHl}#fKq@FzO9gd$B2xa%E)D4~y((v-iNV#;p&o*%hd_lGn$jlJcdx;EzNj4#pOK~- zc6rQJWI9YttSBW)_i7!w&?@a;yrQR8_2?41eVwIH-xPvE45zzD;ple2b~30J z#l#l~U6Koin7##i<@M^pqGkokKR=3sWig$nAFFCEjLJn)yvs2auxdk>+#b|o=)do~ zV7HS=^YN}D$8cE$o!++LgZkZMFIb*N9Y zOSa61`dAsXV33saq3WO;K<$8bjP7Kb$MEEervr!EkBBNPYL2H`HG#d}%<$x|)i%a+ z0N=r@@LQP1V~h!2VI}#@>0TY`rV7 zCCm|~p+V(NGKTK0Y5*EJu~f_a%glA(8|-=TTqKu6X6gP}_3oV+bYuIzdzexZM8L?q z-XoNKn5i~TPNh_xxJ#q!WWt5&&Ut6ZWVrw*J%9k+2T;bBlS$_^Qm#B9z%^|tCwKfq zaqIfJ>;Kyk@%y^I<3a9h8tPXYS}00z2?~08r7W+v!|YAb*tj)^tHvB`PN2xRwl}of zl5rCh*kbKe(@*2?G60v2r+`JY`NHvMA@x=)ZK7(rQ!EZ1Bwk=gNAp163V8BC`($QXX zT_2%rpMkomsikrq#kHR~J0Hm@q%>09ek^KyXSV5VI0IjZQtt&UD$fGhxPKNm-Ify0 zPb%sq>ZxS|=>9xq-3&Ba`yl_fSdq+Szmuw~x{Aw8JDUf#Q^hFTQy{Ln&>Ry|vN>+_ zfJ6S#)N~H1Jfw6zo#$^j3$lj{s7&g7kGK1fRIoMmp!)3Kch%^CeE>-?EAnbrQ*Y!mZ>-PcOP167N*DZWau#QhI+&E_O_rN+RY{jUSIoTe= z0H)qncO-zMqY-&iNmRq*QOklH2Q@2Iv(X}*D{e`JxK8omXJgJX`rLf#?mY*TM^E-) zqbjg2GxYV{UVk+I5l6hkjcHnd_aG$n{gPd$+R!_o zmulC(O5n7wDs?)znbrKs79Qmkp=V)?lGZdHByQ=PvP1f6#>ZYq>>shtAMdx(Yuqj> z956`Lnj2BZ@U>PUFK}DoZMv2OLcg@za*jc7QvH@BQh--8yVTsM4^i=Y@-&eu0P)Mc zpg>-ycNoc%9LQ!VM>yF5SzjeSa`PzuLnfYijbkP{hee%Q{AE$5! zI~n}nOIH(DlRfS>tXgA_J;7&9Gm6Sz{GxpLQs^u6OA=)y`q2>RSE61{y_^~3vXxFO zMvylHu9XMQHd1R-pR~hOJQxnpUWlE}$&<3-6MV@o9p~#ZqodC6 zIwPI9kMO(j{V_GA0ro$hnz)O&#Z8lz5us+&m~Xofs%#kbNOW9iLt#@R*EWqHT3|L_ z7tCj&k3YW_WQddh;Ln3yu^9?>3&7Yq^5-r-XAa2ydoVmv_lfz<0P$p9Z#ZNoXI`C)i?bP_vr$*BR@4lMfy*zmaa={i z3oORz#kNv(h@KEgW%iO%KC+MmXjc!Ir9{5=DMIOZeXNQO}uMr90^3f_@NjTnweBzVSzCSJl7mQ{x z^_F?Rv)B!f?(;yB)#@BI6%bI?LjXXy=gDeop7PQKhR7H&bXAu$2|n^0Y<2j&Ql9-w zd6CGPB?9*aP?S%ZaW}oM%GpZba*SLxWxL9vxm1{k24WvqJP;;jqb6G`g7Uj-4&ag$ zUxX0UnZBMv88>XSGu&Q5Fckqbp2*Y%Oo5CW|I-y~jt@XD~lorrjI{Fp6d7C(KO2+^0yBLC0 z7-}@S3Jet`xHzT*d_vOrl$mTz-9%}v8F6by3=lU_JdXeBD4bSAtiqfDcW!}@hNZ5M zH?3@Qf8f;83mhjLpNY2OXc&O@ueu3z^PX>`H4V@!6w?S@C{V2kV`yJ~zgv@#;EeDD zU?gHflFM0o6wXQ)%G)fo(ip=HP!`G2s|WX6D^th=EEQ#FP)M@A5ZvK52zrRsALDPL zGQ3OxPa~fl9oFr7Kb)!^axOvFE56i_#1&QOQU~SeekEh=b?2HQ2(lm z>%0lSblKu!FrR_C6m2?(#6$QqVi>vi1JyQ!KCZKO>1kJDOK0apsH5+ZkAb z?vY=7h>D|%QV^d$u>CEwcT-azj0%9`Bv0!W{(>8g(Hh&@P$HhC@Bu%L$1421gRmd* z-FI;_z@1P1Uz7{i1rwYR`GNPx{BMj~C!TRBp;$=OaKroC!F(rOsFTzqKFl5t3Hp+oERchcg-*3z z%|jsE!j1*`2g)bs_37CNI274Vxq~*>7s)mSYzwBXOhHt(xeCKcE=6OM3+y;x?&dPd z4Epdseg%rVQ2AQTUC^PCfxx;9+EEXUV#KJAQkm~8=(e1x(@Gt1Y(B*WZz$Fo3eR?~ z-%7PZ2_AA5*Tecmf{4p>#{f&t{u*uav8kFrg&w#f8{(DrPfJ=CU;ZcT%br@UfAnCi zF=OK=`+i<#9u0>gi#g@SI(LEZHCQe*v37i<{KnrV@p0kEGq4A=~?@waSjjdi2Buszpwt9Gze?Mbj!=U>0VO(7(dovhk|P+xN=Kc zmWK8_(iMDkc);)lA)UE_=w4gxT-o#$#Lahjs38JHU9}}u43gz;#nYHzHe7%DahEAq zovI=R*qdN`*CS~e5#7_|KnaCdl0a}mFKX$X1N=vR|36F@|8IW)KK@7d%K!in+9sF@ zMrdq602q!SZI?-GD=t4E^;rs%62Mb-NbtYW0>k{zu$BLanGx#$>#xuz|FsQ!^03_RbRHx)oBCauKYuMdVMurUkbr==7hzQ2~m0wi{^L69+zhwl7e= z$^Zi)3S+_{FHOCb%Q#|_X{q&o6%Dy(AmiIQU`A4@q8y{GXuE6m`HGoU*)_0ZNU_{m1YnC={&+xp_peBiFAU zxwaocHWQyPIrr9wue?Qnp0Q{9dA#ERbNXIP#RD}`dbc>q1$2&&YuIi+6l;wO+Z$2t znJq67A1ymhGJV!EF-L;|}bM}ngv^wKem9>1SfTzCx z(P?#mt7h=H3LaE8AiBe@7kgeG4hDkoTss-s6f|8HE`kfu#%_fb6hORu+6pwM^~kJm z7EgI*{iEJ>fgblayjlh}YN8)=A>ENc06r@E*k_i`H`^w2eNehjbpk*Jzv*cd5l6pz z5b>moLdn(Uxwdas*+*Tl40h^GZX2yIaD->fTVV}U8zt1eVyv*ZBOZ>D%|}Q}wem-xIRnPO z{1gXj_gAG-jE#|X7W?Q1w7&0^Kg~_vIOxEUrMn{9@deSRE^u4m-0G`9Y(*$)T)B_R zk3}ciogGHaUw~ZqZ3ey^znR8UAyi{-TbhO;&m0IA1i9U(LxO@L?!(wFkGptEpI3ZF zSlW1%Pa}V~?c#T-LjZ}0bwqN~gifQ!RL_Fjat?tg^ejeLiGe2Z;X33R77bG==Fyj2 zl&#g%pauB#?Z#As8VBlIj{}>!AxY(33(EZj6KRo|+o@f=-k_2F~t@bTR;k`r+%rN#Mpe2j^%`1R@e!WFnm)%tzC;OyLn zsWoJgTLtmuqhZl4e+B556=Nw#F5PtT%EcaEUo!bqoZ)O^zYkIko3|AjGV9Uq9?PcM z{a`L}mWh_92MEbSEvTKD!<>B_01}FR7nb+F^uBYo?~|sY3wg~vfddB&v)vsIxc^XU zwWYZS)=8}BdQ+}=zWj+n^bp%eYMV{#3|3;=i)|P^Q^RHGpySWJetn6R2>@S=^y~`z z5xS`(Nblmb^)`;#Qif%j!j%iI{X3)J#HbrgT27f9tC(KSl0K~neB^^r-fI8qTgW54 zpDU9b0fT$`Q;L4RA!qr#1q%9YSADQjsGdOf=XVaJ9%Q9q5qlDk*!x#~P=)CPW2bkM z*lt;$7c57IKl8CsDeCjfGRN{w#shlep@Eme_@vXqIs%n)_5hwJ^Iw@zh4|@7)+9(?@f?4%~YIT8q*CrQ)TBB?S-{hMtm%h1wW>C0OZOMV{~;Ez>SF z4}~HT7X@ib2g>A8oVvB$WwaP&+&=OJFF;=^AJMYm1H&I%Ko#LxUB7WXZD1T*K{iv;efvDG>GCRVx@sC<0&n_HA_qMqF<%LO) zcFUb8{8-k>!3iizf7>Ys$<-L(xmJ%wO-x;zPD;-=XtMJ!X~jCyx8CL}gBS3S^%ZY- zo;8cBBC-FA0SkDLJ9@&R|HK|5&%OMoB1=|WND3$w#@8(t84h{HF)c<88+{HkRfi_Q z(KbnAu*%j((J@OD)L15`^$}kgk{Qz#PV8ne_Wtn>7^=(4pB<}KZbnf>f#i1}$n`&z z>~wL0aI9RP_pGLHk3hxotz`RKQGp4`6smRLp3L8uH8|otv$XKIfR(8=yE-UV=iO!z zsf^hA$cz&54rWv*`NB0v#%#woShJti_lY$Bp>MZpN?be%k?-1SiAu8$+T~_ zeZ$ODW8!8Q;RB)O28hUAlYuG+k7A0e+SGootSI4*QvIr|bvN#^Z6h+u?evDZh9Qt- zvqZ6>Qhr53?PW!8V)OVf@{n@`*?0TUp9l{~bt1E(#~0XEIU#27e+t+a&nsLa!q@H& zv8qFSHeJ{<3iI^osV%J{8oVYf4v-GKM{r3UA#~;TCJRW}#6+;ZNA;Mgl}qkR@`K~3CsJ&X}Hr5@W0^$c+d}FFv{?tGATicThs8E{#k{Z6f(Htu_2b?p}eqYD_ z&yf-^>py9BQUJ#DzT_$9pC5#t>gowy^`r}6+kKQ<5%FK;G}&rRciMAunMMUCjF&wE zIq%gMd$31A2E~@WWM0viho?Xq!9m+ScjhMpz}Z!!Uu5!bF743ay`^hT)$ejbx~US|#5K zzNSNE?-ulhu0I076c0;WsG2WVa^9W_ZUeG`2FU!?__Ba*0Z-7^yg4Ax@lBW>AfRoDHc|fz8zNUGeUb}Ji zsGrA`?FXM2x|nX%Ra>wAgzc!c?95mIOsNLEX_^Dx=0o1^iI|cBFGmEG(cHvq2^z!U zA-P~(Fk*2|v<9P@i@vbt(^{Mj>$YkeQ2v{XNen&G#Aw>Y5D1N-1Mtdc6jj9fb$Ms1-BYlQB{<; z-6N<?vldEl_d6Y!6`JXZNCmayF1oxJzdBf=!Tn&BcnE=njZR^JpZmHV`?ju1k8Da!_n06{7f|R4`qbqkdY5?m zmOt3yZM!qP(!*)WVSNL$E-iQ??hIDpy3!sHTfv>&Ols{;^>GirlU-#jSId@RX zBdBm-K#|g9SnK8K0Ve-qA%VpQWa)C(^@2=(`}H+!DC(~c;%cu>Sxnu)^NwI#*@MVR ziCovD@_|ky^7qv&P+^YHPs0?ye-+n|PJyC4fXQ-0`nkRlZ*s|KK#WLV=b7bca>a?n zmEz8L$M@SKYCOM8Tm4!8TQ(eDchZ$f^-oELZvlsv?@SRCB8DnA5JN`g;z#RIJBv~l z1@pPUYgM*5>0thXu{U+=(lJ;_w2m@rd#rtsgC8+qo8&nOG2QBDwkKCfL^&?HVn|5F zRdz8VN5eYtjQPL>9!wiQ-W2F(Xsv(6Y^T8?e;4T3DXkuATV49OpZWbrOtKNTKDwn^8B#QQtit0)}n09s z#-pS2Aj2I&x*yvuM!t-APvzFBf@PouPw8WtW+{lY` zHXaqfB$HH|TYj;AQ4ra7h>~soDv&5#!%EXsSqTp(MNUb=%f4`FlTizjn==qzX|`n% zO#&*X;F5o4-wPIv(-^TEk_Is7{Kw+S z`$qb8!k_Me1!N>9@0g9Gai@8w30SMXsB!GYbh5}c3+?6VrFNeQp~HKyA`MSm$8I3! zeYf0{$xQv&3SW^9f}9%00#XghYGs4ufvKqh+ery_i)n#qBKKe?oqhB&Q&guB?8v7O zgKD$q(;%@gi&y<)@%bU==}VW;UCiqU8r{8G&|c7;+xI3Zs6Z$Y2ChIa#6`W)i6@`B z)VVh4XjiFOA=@BGBXdoJQfV~hxBx1A(1K%+Abwim_6if_+FQ*1F~=QPmXPwg?NKmc53xtNi^LO=UX zC%XKiqUi+RO9n)?MJ=jvg^t@5QjnDy7EBycIJ1`s=awFx&%_gWnDCGD7cfQeE(^k@ zx~#N~`tkegK8zwH{t+(6 zM&5R=QASt&xgoaZ))^DDuic0%{U#aJ43>{~cFhN!3+;xLk^}^BWvz!8r>+=0qi8&w zR;}LKH<3lbj_b^>asw_dXi-o3UW|_M%<*GFPkCJ^%am&`Tn`qoNqE#IO8+$BuZ9-= zSyz>$!8dUFJ&6CGcg#}rNfm3kfMt?DKTYR^etwWOqRu-Q-$k%STHvx_ChmX&sJPZ-)wvJodQ99%Z<>QwAW-qFH7UTx{HXVA3g!hxg1wr*_Tj5E0g6_+5M`ZAu zV%ubXn5xOo^s!)`D7_~3(1p*^?f?J?8J*;pmO!X_PW;La+ezE%YKeA3H9S1dCvTU> z;ge$us1#^de`@}Vq0TL}s8ia$4}CEu^>@iixC! zwNe@gL<(Lz71hldSWGhS;b(h-Vjk&v{?3MEe%T8^dSqA_Fu#NIM$bQv)rVQJlI$Yztf+@miAIRxfa@7KGX@5K17NjWc4CkddSr3c;Vq%ko#>VC{8{|vg3=PW zbPe#KB`xy#xgneJ0GTwBwjp&;xh%1b0R#dO_k~^+h|y4v=Bl6J;`w!|<)=gk$Yb0} zdLXFf-ifs>rvYhJeI-3mq(7B>Z+bN#ZkLE-HaDqNq8{YP8)YMJvRptiovRJoZ7m4t zG;e#GVKfeo71v?caK}2IHxM-PW4Cu-c$;ABH}_qffsgj>tm`=)1LS73M`+fiE2Z1v zQ2Xa7+H~*BcI+dfyW0091er&3DfQ==sZJuU)x-rQnLC>T;dl})n9_-+4F24Zl?DjN zcp{T!J(k6%Ka&hOIx;{)*bqb`4_V6f%4oHOYU%jV(i1oAa%wMHNcVZxi^ZJv(nrd_ zl{-l-Gyeo+p=Y``SUW>8aD(7THS`<@N_Kg%6*t=wYCxd$EceqP#=Ai=K6{T!s2@$y zNBr=GRKb*hN0t#1^nKUi`URidQPOvUi@G#rq8>yBqy?8ULgMgN=Q ze$B&l)Ls(fqHz2mf=^H9iW3XlcaeH9P_Nh@3)SOv(IY+kwD2u_fU#8j9-cCCr#4`DL^MHo@^ zXt8=-at>`if-xJzCR!JlL7GfpyuPh8&yYAm2KVcM!q=j+`oO{N1UqcK1h=m^d%9%0 z8kxK6in^wseA~RMX%z&pcNqWR{9o2mer&t`$LQBUsYE1#%inUH zD@?7kK`5IqLfg6h1TM8!HNi_t?y}ofFqaiGZSW0l!D(nuH2(!BL3fQ+f)?LUJ2+ef zSv=iH%{3`Fe-R@%`>>Z?n}r5z7D|naIH)x>b$!fWzn3=GFAw786%T1iJvWlq_yGa! zeWtdW*gqCKySf1$2a@yutW;>p$n7#pQbUNORxOmyP5wtLMgC6?h~n&in?nUu8JI%$ z5&vYrND2cmg5lUn;x*>*Q^5mkSMI1zjepGm4|oU@l2*e68-*}xxF9FR&!5maeZFCN<+oe0oE9+e@Z` z&%SQ-E2X9bx0t5@f6|TVH5R{Ts(9ekCIEtgyy`7eR=NYzf8*?&qB8-T1RdM9opfy5 zwr$(CI<{@wR>$nvwv#X3-kCG|&-LEb?OW%(<*J7Uv`iMkK-D%Pf`_kU}gFbx+71 zPx#POHA|-@V~z}9$8PUkRIxY%>WH(w(Em&Q?E^ZYvtb=Uuys3Zq=>gRHqC&hhD)VQ zgdVebd`dj5{PaC#k)4B&pk!N8zc`^2E|Nm>OZbz8T=ednq#GHBB~PRDCc3 zn^tHNCsdq&fQjqL6BI?Nn zTJLvVUNzLiIX@1~Yvu5jW@)i5m6~VKody0FLHbGhgk`nnjm|K`7t_Tpj%_ zRdv;Qs`I5eHA_4dhn6Kk4kpo>C*X%*K4M8X2Mst1y>{58= zeCShK?b4n$-yOm}O65QjVsTfPv6BBJa=@g*W{9CQSTR|@aO#~Aiu7@=2m~aQMltYe zu6Y(D-WV{^uzBAC1cDm)NM`YK@F`KxMBn{z%sf$Kp{ZA{8nRA5-Rt-`c%M(JR~YTnW(7f$vC&n^S0=3tX^B1t51G1_BPRu z*s*eI?&s=_#ltKs5Zt^kHU5R;URMpoc=Pa{*2yc0bP%*)Ye>#X|Zz z?qPt#dAlV;OMxBgfFbMvN8-#$*xOrH!`!~rJfTnvmBD^)4TzxIKUrX`;nFcjy%x9z zgJ?rm+>-l8qAE;x-Y2E*Cnd-$l#?<|dn z2%r2b1p>BG(d^?9@z3>3x>wtNGScWny7v|4*p*JX8??|Ob1M(x7{D()}9ex4nB&>SmX;nyv#T7!Xe zTDR80FNxEP!FNgpskW-6(yeVAJ=5qQr8+5nxSXjYC)jnTy@24!O+*fCvw>Xu}x{0M+iRkjg z-tPrAXo(b6C0q7)D)oIH5BVAnUIG&(+@<|wNA z6s*Dpu_uo92q8!~6JN&53^d#vf)Bx{zjojB3305XQbsI^7&VOj^4;qn;oRM{Cy89e z3^65P$QMy1F&6XP+Zscx(0_|wcc<-AScj#bquH+T{<6EFkfrGVAWts`3!=eOM|X3-%p&SP#=V3hw)hVXbNco)tH=TS%S0T~Z`Z~c5(`#bi2#1CkQXpg*4Lw(e zJ2yr{KWTzG37b*rQc6NaHk)4CsHt}`!zzv)CgBAPWI#6yl9!O!#FI}^=d9MGe!{dz zQo}tJi%Pij=+ry_Lqzv$_9-OgNvfkY?&)yHz(eHEEp!DLj;&gim$|-6ekTkCukK)W zztM2rRjJ@F%<`I>?D!FvirAe(_K8Dk0fd?KTvjVQ`Kcv#Z;Lx<__NF)npV*AhXWq4WF$_3u04J7fs$ZhvYb>DR?b*V*P zY?%x!vdGAru}-<5lAkBh$dEy5J#|en$yoCc3tO_sKu*EIt~>)hiZ?KaS2+4NrN2OJL;#`U_C z5Wzn!MN5~T>6Pd!4uzBCaW9l_1W~xJ;y`5=Nkb{lZ}Pj}@oITUPb=*HH5ecyD_El- z-+nLM+ICl)p)78PAB*Cu5f=m3m9x`cu=LK0JoB0a?I$XPXDl!lx$-cb>&OzKVFo^D z(t;T2q|-}0H7Ok4C#`Wh(TtOw^p=n?j5wxJ8DqO^xyElxalo|^1==rj8!{r6~EUm zJ&|3qH`6>5m#aUI+Gn)kcZrL=Dw*v10kmKmX~;s^&^Up$FJ3nytCiGty^3)18eCoL zE>Dlg&zJe`9N%QI6q?xm$yfqBqVls;i2wL0Mo4Lh6dgVKRtOdf$-s)v%&!`Id3ZAw zD9Qm$gAYoV`W-74{Z*Q`?J;REM$VO-0-!G*cV*pcq4I|!o`&&Lb3*#MsBk`9N@eQ> zr#%wJ$qo$lplBx?i>n09V6$Jd21=+D7s@9+z6f3dumGf#V1C-`$ghz(I>H=7WSs0W z9aHK7`pZ^}UqfYDH7rhJpd(6USG+f4*{^oKC#16{q_6)>z3{Xf(eTIH($b}RWIY|wyT!QZc>znaip!c z=>BIHDXL!rp{kRgA2kjm|AF7o`n2yfiH2eX2Zm3?0wY% zP04@@tqL~d(?Df4f*(a~Z@Ss~GMTH6?>SmIwtx3Uw)fk)pd*k@JmhoXqB9!PBE#m& zU}ewzF!rhuG^{_ntNN~4{)&e7Ao+Ztud8}O(#}y9UKUK_*6Rahv%CKJbJ@|q4(0m)p)3v_f(v}{r9K2v4(y?_SCra2@^!4)32b4b4daoQED+3NpFG+|z zx}o)TNsPyaKRRKZ{>U%#I-)(6Zmed~6;yVsX<9aBP;CA?adZo!yuMo}kmNa)T-7_= z3BEh3=!b$oei511Y>*Mp_+?(&{(&HroW*zHGCu)|UEF*$a{#mz}1`8ztGA=|W$V6p_R0ymT-Xw8oq z3~x;yE%WjWE?o$MD=Nz{b(mS?-in-u{c%R{vX}%tzHX(-Z^3CP!}fx%xn_T)kxIt* zebS@Mc8L_t|HP;NHxq)o00IJ+?#I>-*7*^vmCUYvRbQ5&ruJQYj?<*k1u9xrcsXmF zU^z_qWM$_mvowx?>oGjZlee*>h^x_MNLL|f$F*?^`aL5#uHZY+b39Nc9!dE`ujnKT zrG-yk2+Ad+=frlZ5fXm?V9?!)fzoh}$M+Pr@VSRxF8WpXQ8j&;f@5{-}5|8Cf4Yw8ocn zyTTfEY(C#0YM7t`a!pQWre z&0+i}$Bm+oB9Bb5F-2M};Pb{~4f1mw#v5rD#x%I+wQdtaHAmvc7BM>GD1W zF2N6SqSMox(@SK$;}nLWlQRMnHQN_3xmb}3=)G=6J#mm6F61LKD^3&khGmLdxla@h zWUwV=k>iPjVpYFt?f|Z*g72M;=Qh-&hp6`l%UF=C{JA+n7Rfu?JKe4wO*Zql_6C7Y%8bx2XuHFTJ0DGCZro@|B zrlc5rp<+KysDO17@@g9h;XFT84dEnVyZkYIRWMC?}5H(+b$jyeq8^0xz@t$ z8eT<#&Lua%b$b)x;V!`%ZOxkJ)oh0x;TRONnm_;5Ut|FJ45hXS7pM4eUEI$ir$J9- zn%XCOxFU1&k0(fJ=)Z=tme zDwW@M$|M{+@D=*Xf_kAyi~+a&kmfkDqC&HQ1Xw;)v|sij+2zaaqNJ|PnpQerY1;cz zE&k`-Q0%^jmc@OPQgCT$=bcx-^Q4~gAYSA7T|WE)_(*H6Y{sy}>5vHCLSym9R43$5UKJ=;mH6<)%F-lFcvS1Z0> zmv7V&G}<)?XFxp=%De^G-k%L(wTkTypV$}U&Z&R zj)l(JN%NG-0WO#UlAo0Z<1}8f+)&2&K!|bhA|}0|z;r^~FS~x3#4%=9-@)u+p~U1C<5^Xw7NdXln9X8qRd<5Dc*w*sKb(@86|$h>V7YXn~{vo-yRCs zw3)s@)ltwr-cfY!3t7y8&WgK|u{$lj1yYN5^O@c!(l={eH)eQAlB5tPq+6>)LY8*@ zjl9o|b2-RbX~55?qd!h19y!j*Fdv?;=Ho%|k!&OKFGJ^d1|?lm7M&bIPzO#lOqp!W zFfz)Vkh$Jp1K05T5_V1Zx{=$pxlV0uCVXNo6;_Zkp8KAtHHf@ms&JJf$6^i`Z126! zo8b5EC6e0vopSZhh+WnJevP1QjM+8;eFPks2Z5eG7I)C7@)D0ZtDR z7c57vE8727o4E*^ulS3j}SDT&qlsD?6kL-+O= zw~?*2$-0@C*7M|r2t^mkx(wp$nDF6#8w7ue`WXbZ*qT@PxCI7U7ZwNu;7SYlo*2Pm zu3z|&HiBzSMmLRN_=MeFapZ+Jvp;-V{+@>61Tqir~!`eYmwar0L@fu@i zK$;1Zmm#&vz3WtqR&zdc#NoDcP1tb{Xw?blRqF4*h!t6<#ni}Pez~p1k~_)alFm=K z8+HZzcoH`px~Ad?m^WN)*-@oP+*CE2Z2WS5bOQFzC=G9dOu3Zm&&;lXyB(U1V#m0A zF*E+gYsa;N_yO8rXgyltx~FYM5#50ylb2&^CO#32_PwOQTx8Akd=x^b_cJ{N=7!;u z`BZbnVSyv{9O7x6@Wte38sU|R$L4H*2vW@vAy6;CtgG>VOh7cEvY2D5vz>+6i1hYN z=s>ejtRf^f&l9I70$l3=su<^Mfh4?#8nGAIk`<@-dC4NamH$8i zcJ%AZp}QS{f!?$Ln6X)Aj6`o}o^vy&ph);fMP;j&mq27QLZr~Fg=W6$YI#dnx&M|x zl$ZLcn2sRqOs&LM%A*_gry%xf1Bs4;8kSj*{Y(=6wPP%wp4V<7yL+R@wy_Y51l+Ny zS4#1>oqM{Z>uC8B%rftm92TI=tUptdiZH9w*r|K6>D!H{^S!w0DfRD|%Hse9V_OE< z2O1*UnZNTVreqk*v^$CaWd>-rGX8t7Dq}*fWeYRPzcv_bP-oNIu&&iIMP)nt)g9YJ zwQ8>+yp9q&&EDA`7!b^@7OmGGN91^-!*p&bkZnSh`xf0P6Q!~>##)!+ zz7nDk4_#4zX`tw7+!A4CRE-HBKus+P6SkiFM;f6V5oen0R2MdZB4p0}sk(Q#>DMV} z`NeIx!wBbS!{i(_Fv>P5AetBGH~S|Ea9#!&rlEE#{zXTXI${_ZgA2cfKk-9XOTJYV zm>flh%=%g}5ani1LICjYpc4kNxJ>5sC4npqV3$ren2Y0}W|!r_ZS~Wkn7qRLU8;sQ zEaP;K1l{MldRC-;rRY9LGAsU_F8aLZ@c}0-M*4uhauXJrGhSD(J!D>hR&weoWg;9> zST@e(4Ow^6R{=+4#W-=(0Mk0>il1X)!{1Za`Re$QhP**#^|qS}nv)d;Qn9ibS7QqX z7f6A0f3&$_SmkHzdZO>_c%>7Ew?1~8v!GJiD4*udA0UuCy?Bld2a~8*yoB@zwlGy;Yt4AW zhL0Fbns@f9E*M*BhZ`xg+V$B`Z9P^lYF9i6NwZ z*=)!c@J>jH_dJ*#&s3sQ7e9t;s8*`%0D_e3*U_0>Y3&Q2JU_Q}w)z!I<6rSf@`^w| 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%0Df{OkD5t-cG*$KEL#MV3I(7&=ySP{=mi&-)i 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

yR*wO@H;Tme$$%~g#wE{4n_<~H;g?^u zcEvbZX4l6^ctD+j4L`Z0R3%Q@-)qr!L`D5(EplEDwDwB&5VPPC>wL9&PYy%!I zBxET+@q1X5Jj*;>nt!+yOOGt-+uA(kwJcpu+tdJ6U7xftH%2YBN-+tv`lg&>+nJe^ z?(8|z1`|r@y3?C-wzT=6j(yZg8P214)DI?oU)CBVhkos^ts-CsC{$`kQM81h8N^D3 z389*J+Kb{EkaDvbxly=bk*lA!0S0h_3%-Uc3hIl35ajpp4nP+3pYjQGHmsJJIon*@PW}`*@6zRYA2pPMjqpWk9i2S#824!0MJliX^7>v7=#%afa z|8$o>REXWwwy_+ z7K{%Gi-NiGKkns&9?2iHsjhhbN&c4NX_40ChubW%RwpW<(J`) z06^eq({7S|Aj=dqd>PQ!nKZ`Vl;5M40nHDVNZT+jT+%8J2qg z9h?8n(fzL_`TtKL(dU-y-#>O)EMzZl7L2lqfa}Zilha%sN2=3=6dU1qGvM!9?Z@vU zDnNIvFE%kggsNNR4G}MH7*lz^jvjpNX$n-#ipw3X&%Maot*IjK8}{<{{w?R?CCtA_ zV2kII3;k!bSSFu+Q+D&cm{}lDoe)5L*L+NCkj&4i$IJ3vz7byYZ7F4)=Q*2IXWM2G z!1|z{N%a?66!lM8>Wyxv39km5KQ9~i(fm?hw$9N*A^a^vnBF6lzdQiY+~jt!0b=ip zVJ=nVunV#snp)ZqUCN3E)xM2&HDb-(kS%6*Rhr@Ni2vF}RiOt8`R!t@VvH|Z$nFoz zyJ$Kv(_1`tL1F|bXmiKf%v_O!K;Jh60OA_7a%vn;(kB^hO;k%D6+QCJ$?H&&PD<6L z`zG|$=vK6`4eH2AOj0FyYVCrO;4_`Rr0tX!=z-gj?booZjuTb{j*-BwY*8PFh2JyS zY!YFeAdht(F%$Ke8@S)em4LD37(K44xF@$a&{w`6i7_(G;qF3{1m!TZ<_bdm0olzj zAc|}#f*~leGG90>_jV&w#4@gGUXUSH2x+oU`My}Yvqv2O4LpSvGnLQ9vo>jh2QZbP zWgA!dAE{meWM2G}IxZ*!o>+s!X19K-fq>iZB}Ee-jyoV{Nn24Wv2j-n-o@EvzvZuh zQ;l+w+apDPA4E9J09fO7%3X?IUnIA>QVT(yT*~86Kc33hF-{(00pRo>} zOLnV(W*+3$Tfey1XP9P!r#u<{y5tWrQK@+4X6P^sv_tY$R3VA1Cl6R-@PFxvq_qGk z0PTNIK*cO7&eLN~l)aPw5fklTms;`V9a%ClQ-8hYGei!O+WIs*?vXV9bLRS|iuP+Q zE?-0Q=Lx)^$sZmFZRu7~I!UlxdU#vFF5ymj8tFLRcH9O`<=q&1lueyw_3x|lu#lQv zNw2Ee&~)KIZ;OmHAnY%`@Db4_dtR0gQVdN)7Nk1b$NNSCaN0FpEfkTD>{soD(ep@u zI_Hv$A4Y^CY_g;M4xRA#b3MP~()HDXb#LM0 zgm)q|B+o*`ytcjZ?P6SMdQMC*)EsY@`+_d0;Rz-}*of#9o4XvZP3$eZ5bU`WoB(@1 zj8ZWn1DU2ssNQA^r>`cP5*#dIH2*iP_cP3?(ahb-Gn&Yct zvAj!^P-Ppm<_lD0rg!05U69VJ4@{lw*nuN60;BQ75ZE`>gy%5LC_sifGz2>_FM>hk zSxw|iWQ#69#OfG$(1+wqVQ;>l0{xixE_^W;885;TYdP_3YM6_;0^%8AN6SuGP+`tR z_Ul~#Vrk1fxkFpdc3rOSVo5heoXxA&^g`m<l(>To{I|U*^3ZG!O7- z0=~wdCHxBX;>nzRj*XQa zirMoj$C5VJ;w}!Zeu|LpfMYy5>!6#!1mpLfy=00P#%E6At-9bWhZ1%Xq5TO0!u4F@ z(nGc3@5ar}r6LT*s`B(hyruYyD-o4vNAN6cw~V4})B1wl7*S}kXZGU6;6XI}chMW< zrg2P*4ZE_WD-8cX*snQ35pPu+E%yv zDdmMsmiu>vARL@d|8U8+wEN)g%9a9gwM(tY>tY?W*$e%;pJP~%29+xQ4z#MvLNlF! zL$$a;kEO*#&&~z~oqX0Yp4XscMNZFwV8e+%)feY|GU8X$rSe6^kb80#-&$W`Pon~y zH*2lmsy);*aYF2bm#ilH$B?CCB@6VDV7~oPMF<{T$MvR77DYS33ng$H{--YpOZp^FMOE-keR6INfHwkKogi7h*!MFmYl%RcfC9 zssoRc=|N&>;{}&`zq%Q+O7e3KIK;MLmAOF}mc0i_lRsgoB^|8=ywjSl`zyS5kCgTh zn`(Q97C+`ele6h_pvXmpqyQ-ikHxL-UBU!JlJ0!_bGh%9=9TW#sq51FdZzz3ft zmMp7BTRp8Ec)NmEpHQ4;>nuKa60u=ZMajTj;kRnPaMhp1JLI?(B*+N)tbrXG(=vrg zHh%$`z27)N;T|Yb zk5lK=2saPAk#=Tf64T(m-1pa^R10@_tZo$``0q=LPmFeJ=@j66?$NthZooCfA&waKl<4K^^-!zLvV(8A zOabkWj^-{THpLbDE16iW$nQfBK)Z$9q&VZtTb7c`DMymXx`wEo2|uQ2*p!CAYpO$0 z`>2?yLL^9jJi%mFtHJ?QBS8xMfur)(lcyNww4+U20HM%$m8<vnf&|`+VV5RLc+5%(Vp}%7J)uS`j&0<`j`U#)2TxU z-19DqRu|V^*Gp+p(y1dhsDYUn&f{zz$~I^o0YW;m@He(x{>l~B=P-06t}7)@JZSVU zt=@RTC>@=)qW&&nOP>!WG2Dc?~ zhRSWgXJ9#dc*mT6KiM;@qk32dI`#5k0ZP9~GPrT|dv$$QC29zC>v`P_N1<1YezMeZ z5a;=l?Fc=lOMHekFc1n{tNL{LoT^A@sR_Iip2*#dCmcbB#D6}^~~ z(Ox4cp$pV4yJOc4?Ij^!eFT5YA%SuOj+7Y?Gsuloz|Zc9D}93!#z25U?ywoCj2J3< z{Q*BR0>};Zgh%KJ!k&uVpW#cWRDcHPT~-hte0~g-A|!Xp-O5kD#fG#4@IM;duV$^gCc|$zaM1-kX|0srZDwuz!eh=k4(kd=5^&0((fu z(*hG!V$Jn9)#q}SB!lZ!AJ!8lP?$%jJs>!8=LV0hpY-rT?ZnhwbKYM^W=~@sTFS7C zr_Gf=9s-u!Ig&X3QUpr=inrc7_2f{a!a(4I$bY9uV6$T5*vJ7}mHZ5Us$SPv6=E6M z&v}mi6&;p(IGephh9)9G5hf|{s}d9WtBlTz1;e&nemYHKMKR0j@f4L;x}aYkLBm;D ze;V~2p*^rQd@`>7J@+M!-&NRpmaYa#j-C&~3JxENw%#u{n`!hiKDt^ST18?cbNN`s zSB_8w*@bG^L}X;(TDg~4ZJfa@YC-ah1tVXBT(ATW?b1cTVrl_yvunxebXOd;(y3XH z_y~yrIOn+o?3pO<4jelw=4vpVQKGE&9)8=~!IWt$Rz6))LNN^Sv{_ROu#>`RyL-`k z?Y=yeULHgKdHM-kJnhM>FXe@uZBw0x=M`dprp8M>OlX_K>gz>(6i8FNJ<pu zH<<`{(JZa7tR@~|I#)P<#r_EGJh`A*WzKJz?zrVWs5SK2r85u2N34ud1cWs)eC%Ht znliJsh@WN|-SuIpulLjUrV~dX`fk=LXV__MC0;3PG;EAzAu|hN?5mP0_iPgeJnQBsb#>n)SOxZ8#gA8dD= z5{25{xpuIYySkcr%R|wBDw^O_rV)Gv`vfCcRhVU8-W$O%w8wk#1pdt1^KxV7R4sFf z{e>tMSC0+L67-W|DdL*i(_SP*b32NqU2nGfcbqF9#{+e}# z#csWYdm;_NJ=hCwb}zvAfB@@>>RSx0ho_IrKSIZD8*>Vm-T}P;X;Uv0o^)?VXMJvB zJA}60IrkL6TuPVC)+X{v5bm+TwqAnDSeS>BnytG$0e@>?Lgcd&ewVsyQ7(*G z4rPdTv0I3uzATmTbOChB+y>jC83wsFb(-Ic1_N$3#Ystgm9Ko`^0n~hA-oqOhZwkh z^)*Z}9)=m%UJ_%LE%b*kj@t3Ew5L}SLJPTy?{`=(R+%MZq|yY&|j?A#OIcnpnL z2zP@%KQZzteq4z^db4WEPp_!BzRi zSp?(o|$>Tg2xt+GQxdKoNQW ze_b`~RJ+hxLbfV43Dr(=93qt>_g1IKfUb{46Jw-o`?C~&g$cBA?B1A1O{tEDiBqn2 zLD=ggktsl560EcJ!4VBT^Y+lqQ36T~>~ zd!s}<3RN+Cr`<#@ixx^32cZd%)Y~eIXz2L^TI`9#g9s1b8BIeUJ}C#^d6fHwgWe!D zszywNRr+TM^Foa=rdkucc9+YZ{&D;FPW9Z5Pr0N!R4|X(xM0t-4iO#F?_(}LwIzWl z_PMs3$}N0OdgsnJSpq3~yB=PLnCwGLMu-{uO9jVjJ zHM1jz$<;KJkK%WT!&Q=oS%lfPYbDV0QHjry%n|vff(*t*N9Ka3uPn@hM1iBt)0&$x z3p#Zc&UG1_txE051CP3`@AfoXdmUC_tN2;G;Y+(4iZ+D#@wLqpCfe;>w9jBOtVxYqQkay7ShqaX#SYtn3 zN8}dz3DsN0TZ2?-J*0m|R?rRU9Xu5cvxyvcG zY+UCk=GUwBkmvx{R;DMBlOLdphJ=DIIWfh`wEm#pb}i=bSA?kHnmPIa!KlC;ARGMQ ziAdq&ABdsxQj6Yo<7KY#B{D6qx2{~y7Oc~Y_)?qaT%~+q)sw%~4gj>d zLV(9^RyXWdOrJ*EU$WQ8eh0_hVb#DZer$_J)m-|2>8LTCUA9Oie~~Ss4OaxN!D&!c zwRQWyvHi`ew(42*X;gbfM7T7y3|h=4ukFH|=VX%H$Q zDTOz4D%+H#0S9Ig+=*k+B0-yL_kFKE{zdh!na zXsB54ZMQL@hmeeFbNi|pL(bG(%sd23bzo~z!f6}rx3bs9g@As4R0wB|?2TohU=u~Q zt2BT*hDWGk!|j$sVd6eg8ZFc7@>E3z6<=R3bzH%8qJ9U-r{Lb1z_o~Oj`f~EstYB9 zK7oO)qZh|&ur+cEzg4v%`1=Z8kIk@9UG&&YRtt9HG#q81E7a*~X`C!IaSF78!j|n~ zc_{8;RL2Am({`(u!9O$X$n3lfSxGnIU&W(AO_E23BGaB^*tiSUQpEJ3{=&SjcBFQc zKY1r8_pfnV3px0~6rge~%fpy$* zdC#H(8^&h_8z_({0Q__to;qPwn}HoO-B8=Mr=W8rV+^4`MyE|{V_VZCR9j`KqkUQ{ z7yxa`=yT2=-Q@<*94Kz@;KJLlkGl-%X?W*;o#ssma*w|9vI}#tJ}vU9 z&%T~~vgnSdZn>xCqT27HX;<8wr8evG^oA^ck!VB=b@l^B!2^Z&Y;CivlYefcy#-*j zRD)$FVQ5iWW0jahtQP-HXJt@`ouxDmE_DPJbu4PPkQ5Nk+1TQpM*#ZA}!wU3+n4BT_T zmFzl+I?&iQG1BU1h4|Owz13wSMT5s;0J81+dU6Hd!l!W)F%+)#8_ZVb_pHqO$=UuMc={n5wguY?q8b@gj;mS2_&Sj zcIM05g<4+ZCuyk`pT&W3#WQ|Cpo!#yfzQ}!EN<}! zB-6{OK_SDdUi|d=jQ$n`Nzo@|qdXgBv_+)+Y-@tkpNP7-wPFtN{i)TLYKMbeUYHp8 z(-Uq1m=P8Tp0%^hc=;n5)WCajyZjUmGtKqePSG-5dGh`M0@FD~<)x&n}r-RRuTO6qC`a)CSqS?oj_-@3f$W2YXfVV~}Uz`*QSK}h-> zxTw^iq%)Uj0b9Jt9j0lmN2se`k6c|3!W86((hMaqeBzC=3Do}dT})lZBzhWuhg!7= zCO`xCcQm43VZ&dX4lUr~bA0}x;nI9bdvsMd_q~=+2hucy+S;AP<$f$FYL-$ouYCH* z%cnoEbo|Nq>Foi3t>B!eI-{A?fjXCp7wA1wj!>maTYti=e-`~x6-i-SNlss_x*{Ow zW7`_DSAv)`w?XvDr}sct%) z9>yz9OoDgfj}}#!6qg(#SDa;yLGGD{wXirK5K()eY9Xmgg+9B#xTLw4R_fIzz|cm%k~0R%Cigm<&c@ z|9u)MCx)X?`uH~8AR*`Nm&#ZL+zvJ5}sWrHLUVEGa1Xl^>g)4GPJGjx-F*0 zPO|in{DP_XC9xtuFEG`c=&DW&=$%D8_Yb{Pbj5y$6Y+o_nk&4X$5l{3#eu)7^)lk; z8*;J>93!{sDxjVEg&{hBGkmm0x2G+CWDn{Mu&{zl0y@qfhYLY>3@u>-vx2!Jp`e%W z5BoKcgV2hzV6oy(@WVE$;wUW?tu_Zp)**!O`E3(sTr+%uYf0ILY?3Z?U@M1s6eWB2 z9Sx6LwF5BG2YfS${5EMvyDMa)4^iZ1sMZl9fPgpxl|b)adTlk7WZ%D!adN+ug}DG4SD zrzkL5%*!R{GfvB~>jmr4EJRE1@Ujcx9yS=6(676p{6xZk+-wi#2TkCs3Lc0I6j;5J z*+vOVCkV#(YgLjis8@J88S9#}J)-39ssi9A(ns8utf zj`>8VkumvsV2?lnLv(duM1=Xr1a=jj)WY}TQ?2(r13h}oC01sAgi&5{^Gczmo1-q^ zccA-I#F)<^dk=8_6Sh*g6uDyWKei-fvwh zEvY=-?Q1K*PWotbhP2&kOBkE;R74sdYao#-1(U&3b?C4(GVzcemm^yM$7PnASmunnPlmcF5?Uz3Q5;~t!DIuza{$RgHO{fbrX`9oX6Cz#niL3@Q8 zmbd?IV=-Usf;*~4+;$k^VRS7(ml&S;`J7irPpSbfSOov~T@>VGN7UTm$+2 zl?{HO=Fo?hio(aVDyc$7;SxwjYc*JR<6k})_#=kZx$N@Res}fh_l#t>pK-;~L)PX~ zw*)sM+{7l*yv;-9r{sLOi*hNq`=bQKmma-A9Ejz$rZK6d@AO0al(5E`h3 zgBh9o#wtl*bjHKg9+5*r;MRFAnLs;a9<3-HukS8ZsLD`QE+{-Vco#5df5jNnyR#I; zfI&K9&9%;#lzMY1q<{@@sO(Fr%*hQmKr~je1`;FI?19*`mvE*werUX9cpX#to)W9A zNKG=o0c2jaM;gzc_pC}9o^jk<;K`_?FsRUL6074IB=9$5Lu^KP*E(IaCAD~zwY+MG zmVcU=bHN|P-P69DYXVRRpV18|+wI^PK4HkXw$%lnKxr6!ZUoq5VepZWvFKhA1yS-~#`KWv&8kAV_Ugo4s%&O3sSEQo~hybC@#Wy=JVnG^I z11N@Wva{B~$>j$KW>2B#d-uiqKe*5zTzvGxXn_4V0y36OloCc5#x zoc1N$aN?+WA-h~8j!pkZ*#b)TpVR_a7BLsKZJ*CURs$-Gs=H}she75LO-;5ByDM^m z;WVw)jcTc&fptq{vX*;`?U{*X=izu}(W?sN{Kj|Y(x2`8)2ttF=RCIrI$iXiZ z9k5j568)Cp+<>#!8)w4Iqq#vrU~PO*&NM}G#(tc;8&dSRH2D6NevzBf;sJ92Vz_xN z`7V`n!{j8Ix7o!7J%_ynJaib8EGNm~yU($-PK|KZMaqfU6JUoc(RIU>U)*#=l~l;fB?3u$P~W81lq2Ic)4U+!vJCqq^i4o-uoSBv$& z!;N?$_jAL$K=5Naj~^I}whk~zhgzo2qS`tY<+|4aa$ebH<&Pmkqep4Xzi!y|Z!ocT zEF+Jiv>A)vJ{5qsbBymQZ~K5Ei4(s={SbMF$axRmfPNo<4daiO!m5a$hBbrBF`1IH z*}U*%qq+U`?K{Xwuct4Uv}}35V+khkVS(bAP0s4N2{|NT9}5D0jQeHuOy~0updkS! z_%f*HjwcHYhi-)0A)>Y0s|;xj{J^Ed&*TSA_<52jnpIT17^k@TMQ&}zqJI~5-0dJy z@7R0pMOnk_Ip?oX5Z`A`r%<*fOGL-1(mIReCHc`u^#dKPZ0BX~zub%7E3`I%*J|4+ zewi>%TUl1IsE>^cyqQ)vNP4nEWDEqk{x_H#z5B4#Bbkc6py@;}HUVFI$a~wz1Baju zCU|8ttiI(z(KbvG>2jU2lL+n-6GZVM6@$n6=I6<0G@kCcf?A*i97==Z52d)Ttnh=Q zth4RvXZa%fFvVX2!cx$)PYwJ5*GjdSKVVJCNWSeDA@8Y#Ka#vCGC#7&&yBFA>?kXh0`9nad-xkTbL`t;! za^Qm;H5VljH^aAyE@hH`=j4C*Js$m9umdS>sb+7BY@65J-mrXZv1`u11Ca^q${{03 z-<}_{1_KSVHVS5Hy6PVC(E`Abs0{nQ#{Ko;r5{55jUtGUPfEo}7bGfsJMB%uk+Rf! z1hGPz3lNA*f%Q8$P%AoxSIpN6Zc9$#LAj2vvANPNT~*$W)?X`9@nvc_iIw^rsH zvndT?CL9aMB;MXzrk1Dt z45J`3gZwM2RrfNR6RsZD?czyoV7Jaz{+d*H#QhQKh!CVNbMP5fiIh^>7UGFS%0mVK zJWAI5s0&jrAJM|fM8^WdxuLyOEcgRsg9QH0r2JtX?K2?i(sYi_LYzqvfSR_zwRW2b zFlC%If*=)vHl98q*5Qk>@z7v}d77$oQcXm<+_kOhE+&CK|HFKhF1w|gERwQ|fANTpB$(H1h{AUC z+rSWo1W1K1bE0Leo%|HhYtq)%+II2T1GmK^sw$RT-44|Ox6#rUrtOYQPYgc7pnH>+ z{~@+$&bEQoEWbo;C;%2?GONc~FzBNWrEsrCuf8Fx`$5yHhGEOY?ezTW8<{b}Gy5#Q zUkRQM=yh!;&>?1(k0$yWi}_)IvPAhM&5!{&TQ~eIZ&!uWuyry_aKDqVJ0RIW^y70< zpv`b)$ZDI6&a9gA&n># z1Y$loW(oa!I*Z=_Op`1bn%mS&&{nuB9@S?b-J}~N42=4o+=9@Q>!8iq{{gD7lmCsG zgPslWP?cAR01ji-P)EVn_?^F$4{~7xQ(l3>&Fy{1SB__^_G>-}uxeDyYJ9*$N-g;h z`ebnsJ`A-<2dKw0Pfn52--sI{%MzXK-<)UQ!xygpG zc9#4#ceG&tixUu@vge>K$6$;=8m5z+AR_t;>kzGFI6$;?&w#Q$RVvWT{Y726^XzLk z>2AF%*6i}WYUsHnnggnYxpic63YME#`8?6)?6?UnH#D^9w2e>t5?9<6Ri~M2C#4RY ze;zc>l;d6I0b%7ao27wUHfrdfaeCJF`}O&&hg-_AYl>M#fKakcsp;&qIbtsb{V!Mj zX}T|rN{xi9kKP}LlWwth;sCc zx{dONHX0V$$m3Ev5U@8|Dic40#g+Ww6_Ahgt6RzdBmRQLw8Vn}${6VNXR>4-5Yh$# zha7^;@d60fD8)>Zr_pl?Q_yusnintus;#;7b6rp^e2=*68h2l3;v3;d1rvlP2_M+wBoSQJsjYf`FjIdJRGEJGsu zQG!qcz&a&{jRSyYWCDby9n%TC*qJecpM|D|Y=A=?lG~g>H|zg*Rr>!bfT0dLROx@( zKXzvd4y&<(v03u%$Mq0#UCW6NL0>bI3#bdMn5i{$U|5BKroAKL9jlb56`qg2^7RQ7{g@K&zo-J4Ll2cX~Pu93_b7< zCchDAHc*hTwB1j^4w{UmREci?rkt51w%VH?MWrvj@E=#1`I@Ej zuo@yFRp8bibX0cXEC%>~#xXPE!t@@`)}4jT5Alcch`A0Fi|yB*XpKLIRDUWrOo$Q)UIvAwqZ4r5Y7=viNs zbjopnh*!%mrl+kmIErreRd8af+f0E`T_C-yM_5Ws-&ScLEPKS_9}qp&3yl*6t>%fl zXa}%?M#b%KbFx}!x;y-q{3|DtSdJ6*L#Gq#+XVVB)~L|zAnMg5He~{raK^&j5QI=2 zP2TqT<&nw9FK>u*2_7D}7Rt7ThPz>vyr4h%W?KlW(S4kw6c-OPcujEb1rPk8i6xl2 zyyH3M>nSk%+&Ak5j+Z+{m8uy&ek|Wz_?%U^ z_}m|%yAhxw(7H!1@vMM7^geQcLQ7{eaU1j_S?r%aLh3l?D6VK8lV$KD{c6eN1KI9* zie1J2) zmHw@bROtVW!K2scKdyj5vxxDp2qLC`D8g7n^!v|<{f9r`bQq@r4FqoagYxO_(i;qh zoW!9Z$v}a5B;j6czo0wTRh6Jw<)tI8>(2hg?e{IGahunUe=2e)O)iwPKoKEMMQx&u zq`J&zjId6du{o2yDn^_uZ=Eh8Utw58RyFnXwT&@0swAUlImD?T!jm5dwyxHGCMsZ& zxBk4*nephhK~&zw^QelY(sY|^K8mGW*_ntI3r>60HNg{I?eN2|jHR+aaqhh+W;w{t z*xYC!!Hbf)r)(eWQE}$Ui!YLHBc*+Xi_mCni*Rr%lZ)2V3i>{S<>mo_`VSh;?YszNVdIql~d$e%%hio@3pyt*2a4fsi{>N@3 zj}5@-`k;7|?1V_qDxn~It8AnIa&13gi0_{MB!8Klk>ohJ7=nUa~ktQ29`RZ*RixsKLpBR#72#mf_+btuRG z`wlQ>%{Vs43xD{(-a{a0y&N~(aMCptg!U=og}bghekWNhyfAk z+ubbVzT)tf_P8YP0_UP;4!S?Jg1LQ*6n%X#7~mE4IHU9_cq-*|dM2v1?9-G1Qf>pI zDCrPdN`NjB)TIF2AOT*%?}bf{hg?Hm8$BVE8$~d_djAAJTYt4FxFDxVsS}JDj zu!-F_<%5ykyq41h?@(k=tEOqXbKI$2Xac*UiJKN=tCqWsCE*{mR!<6v-SM<~`UKYx zU~aBh7=`0dL99lM7Jxz(go5*y$IY=DWeSl4LwRS&Ve4Wc{d*U;7QK*n2LQDpLL`M| z)%*qV;&9PC#-y`q%AzA;=s`FBUzEK=tT0T}W_x_zW81cE+qP}nwr$(CZQHi({%&s4 z-T7xdt3eGbsqD3%Jd1CwD(36lh!?|omHVT9=oZPpvf2cfiFUkl(W^CDK1((7C#T4V zPb!97#e0|EY5fIKCLyK~LL`v9?1GcoV+X)Cn=$7obFKVtVab8#(Ael6PoPJSMT$Yh zNFCJMm}ihtF|s-lnfwg;2deHTQBi$mt1mdj7`XsO!N%@q5Hxt18M$oj4I=wM_acSZlgA-eNU=N0c9DWwA7hMkQ5Hjf_5=C+&<}r zUTT2oUb&vYP$cMC1^HZ9u;&Tld-yRdhMgP1p)6!$> z`n=`48u}XFWF5^d-@T@4Z(q-;aLPi1w(c>TDqZcP)tfTt&0yWX8KH7Wez0$!z1$># zKg-H)QtMA7Ob~i?K)n9K0|3kP%C@`#Tn)Yz^wTI9ZO1$8n~uKNGIZC#02MbnlPM^3 zjMmG}viNy8E=z1c{$?X~l&>bd*=jd7^GOfQ88SEj%|39oPI`dce0qLNcm}#nJk|!4 zPyZW^(W;qpW1Ur8Fccilt$CJDZPQvERpWt6?(VlA9_{;TZbs`yX^P3zME!TXc?0o0 zV(UfXthioM&UvzG>^q?mUJwg#X%uT4%;V2(a{NBlriGVUX7bx>+ENQ%M})8<0qJ@A zbeSV#_dF_>ZAH{!9i&<%A0nBi<)71^8WOa4QtKD@%eXejy%ymHg;Qs+529|M^lwSX zO~GXzgqQ}Gi&&U0^$PC&58yggO5-WlM9pnmMLnfhduL<|#P1 z$1@RF1AUy8zF%P42lSA@OhEmq;+Icn64w;vULoLV5G|`p{mHuN-pEbcJl<5 zkX%!3NJ@x#w7Qhg6iAp5=_Gy5_RFG9jKdA+l7ZM{1rboH-)VOslh9CkML9${;evR7 zcD$)|7J<7#CZ(~+wQudPka0ISmw~t<982m#X{*wI0AHUju!Ic)5-!8?S<}T(mvR*F6vHF3vHuLP%xtq!Ssiop)+E{M=TI>HWzv7Uip_ndZQl^k zS|;gKZI>o!w9p?Km>mLL^OSv8t063=CLrkL<@I8+w*qZCZu|0AZpGAF$L7uaCy`YZ z_U(PJ64|9i4ORsgM+W%&Offf2CB0UStTND_@wC1ZBF$U8trML1=>rd2NDz-0D)^3VuM~OV)VDbk@=rw2YX3c&2m>$IfG0YyM!hb zyrl}45sL30H;y#{2#6|7UGBbw5!^+fq&Jp%Lk^syHc9Vo#s_<liu!1^b_F)h924vQ=ge#PB}Uk=qCar5g;ZO$;W7@xC-Z| z4&t2TFWzzlvgIy|+*?nHgc=weuozT`qgIs@!{^3ely5Oog@Qg8c5PF{2kGO!uWXU3 zDz1ecd31+@xhgyQr7KY>HZ`NiW%gj-9r;$WC=2c9D9vmXJT#J{QK=Ic&^ZY1H!sd*#{->X+GklQGmJ{2l$acQ1U>3{+|+vG#; z<2E(NQ)5)hNf4(=@C&w)`}el?7d*2_-D$n6?ucBcoXF7PXoOWeZ^akR);|}2iV?|m zQM&jIoIno6MUevxKMsN=l(5BFty)x1WWAS&b$vY3z<^W8?B0OORKsdg?8 zP@Z**(o9RjjYYm4OPGjSCZbk#h1tom0Gg znzs}aBQ%O3lzvwZnE0)nX0!!=m3UB)<8fd+HGdzQ!R;j_l5H8N3zDStk52CZK7XY^ zVm$qHe+x6LKsm^&PnwjYtJTz-)els$hWsdS`sk|gP}&X{r%JH|#RY(0-EhTjcK@N5 z;H)=)$Xq7F=R}4eiD)}!zV^9@yry`x|I*~&{JceIOEi5}@)K`Jh`0`3nb^JTI>|al z5V@}PX-2TgOb9?YIM#(#m9faFefHEDrNe&HRdZ^{-7yoE6k7xgQwrU*hylVu3hKGk zEXXf)EoZ+C8~IDbh7|m#cv3!&i@I}!TGdWyULwEkwXqc7>BkICrzgm$r)g_R`#y;kBKEAWq{_7 zFI1m#{04?I*cLTuGMQr(E0@rpDqj;5lk+|9_L zvwADv3>yCyxXQ$Gc0NbgvFysYD)9aNS^S3WF=qHp7SG32fq5QD>ESmv@p5_6MZo zg0)C40yPVMsN3&h{iik9n<4(;!AnMUko0clYL&*EV*sn&y9Y z8$+rEj=RrlKmX`E(P&Krrv-AIlv;L=@yWl1{Pibo4~!xb-1t>r746S*u0Z(_Brj6& zt>NqP6r!`)O?8Dsk(+cBQ2dwD6{MN<&#^H#k8UZ;>E{EVr)f_XN*nF#3`HS&ZEPvmUZP)5E$k;rD}>}jRZ_Oh+ z;V!SUch#{`8VB=d_2+W8F+i>6&1HeveKfPj*PT?1>jX~=bU(SrR!#N1uSOG@JZnM- zImpfK9z9N$)9f~W=>7Xb-WgDB?L_SB_i`ZvQ@LCeOpyApJA%w1&ZoW_WG~2yF#Dui zWgSH>j}0=}7=G-H``%j^xqwpViBTC=5j;JePg!=(nWtSz-(Ue^!C zt(Z*M(I33F952nT>stLg?kH(o$@pC***ZN!6320x z&VBp;^WOi4UH?x9nI%%-m|q)rj~PK0d5JfEBVND1Vtw_bm#?gGU1LU*gBm6CqX;&h z{14}ZblD~zKJdQk4rA;Lqa!HU1FC$1#SMdI7}il)i8K(23U#SuVY#Q%7L}mI+b&WL zL4v!Qn5tppt^^k(2n}uK?w;CjORP5Sr;LUJceqLUs`6Z!T`pgWO`E;ya9s#comWJR z{MYT-TMxq!7p`#ul`OI(rMdor<`|5bf59N7*EE1TwooHaiP%R@bTl4=l~F~?J}>ST znp}IxwBQ2m%(&iyUb%a1ywYx&P}J6e>E8Q_K3*;mDEIdEzjRp$s&SGSQRWj%T!7>_ z9l%fi*^Fm6j8Us2;jN8)+f5>qHmKqw1?!`fohjWf%-zpU_QQTuEf%ho@CO>2G;&5k zxg{IrK*L#`PX_fXqX2$IZD*iaCk>Zo)k9oxsZa2f9<*c-Qy|_WAz5CIQvCpaseGRG z>${AC zZRYGIa)yKj8IHk~b=pmR{I$K^f(jk+Z^EI%J_t0K9KNhUQ+f!ha|~Id)~YHV#*GDU z|L1F<;+}1rQ^WsT?=XgD^tzn@9QxPDShaAk_!VSmKteOzZb@A07^YAADvBFC8nJ&K z6R5Erkg2{2?5ncmr=V6pa6%>{K8#!C7N|w{pl_!D?neB3zlQidSgc5Jt|@J;ZU`3a zYCL)fo^IRc<6`h%MeVhe0EC%1EqjdHB5D?Q_DH;@v2#mI+FRS=ObRj1{YWVn*CE!L z)XS2-qha=zrTWNu-=yk8LM5?PR!UF#v^{*&u2DTD%c4C0ecvQ-xCx}Jl5ggXQ)O8| z(rnY3MK0O?pF>mQ?olyqOSs;Gv#JX*7iD=Iq)H+8XI;!|BRqOQ!bGkkZ_PHn@s`O8 zQgv^Y`AVNh>E=-LxSa~U35m1mh+e;IJ|eBP_w%()fJ!&gAgfrbn08AK~(!f#S{H(qlAgXnVe#S>>}@3JlQ3I)+cgEP<{> zpzVeZy@wN^-UB`##Nz;>E^7Q0G+3(14?y!cEdw?oAE})0SV|1jV_xlSOl-oN1@Jv^ z5K1Qtm89vebNn)TZGe;W5@J(66b&x6HZG%fe4XM;M4ESs%F6tBW|0OMe$&EF7TK{Ua-x4cA z?+^21`-Q}b;%}Rn|9bR^`}$fY$jMhwqx^C!1}T>L_5{#8zeW2Fcz9KJCOGORzeM1M zg6l;T&Q1`{@<0Jw0F%tRY2E<;1PtL#zdS{Y!zNP5rtLf&{5e+l7TF~RD=vS)V$DOs zKm4UN^yR|}f2oa2wpk)DnUrcZYIc%Ry3-B=Fs6;BAB zO7P!Qo>O~T-6=9N7`A?WDGhvCKb{SSQmvQmhG9owgXYiMUmlzu3cfWw`!GW;;mZh= zwjX%bzoIfIU_|58spi14Nm7%(5eODiJQJv>}S@dYH z#~HTRN!6`53o{rhpRJ=k3&x3PAc>O;PN|g|v~A57moxlr>zz{oq&Sw5p>;^P?S5~a z|Gln^>6~&=SdxD_{mMpf%Zv;_dl{Ao&UPlVUvedqPaP-fd}Jy}@n+~Olc@$tj?%9R zurJvS!TaSFz!UWQ$45tNU;0hY!L)xUZ6f6R`sw6^y6ZCIudc>&$f;8G9C7$&A8^kwA4qJ z-Mzd2Oe2j!5==Ch6m(YQ4!i>{WMOMwD`D3Y-<fN0l)U@-MiD&t9V~!_ui1p%a zKljugp6dIRM{ME$a|V_zClhsXbOPS1Go<4*4|)1fkrn*XrXafd-!`3h;3+@C7z3ei zeW7Z$0NRFd%!rfAL$@y9szxJZJxRT8nh)X#a~~HFe;%>?=B4xGb;7wrc}g1@ zke6urs%9<*Wqdy|rmH@B4tnlH9;&_W8K(jvPA9Y>SC~D^9y%lG$7*Nkc}=}P!j=V@a6A3%@gZvQL|kgT&QU;#2X>Zy3Qx1rkD zQp_7I&lRp;IBn;fE5Z`L;X)lqZ4mYA?fR_lZ<>FVK0nuPXCrtGUQUVOG?%rma+B;5 z?9CaqfZAfn&)lYmVS?O;efaYf48lIvmANI84gvkrf4weOc~rRgzPi`}!L?wpAp!y7 zUcfCKRylQfKkY=VO#nFtI&ORD0svmSb8rxV%DB8&a}IeGRc2~0LPZm$4CNdDu2y4| z7}xoZHLw$PrU_qM0eaMvNS?!tFpH-D9{dSZ<%T@c`V%uOvgp1ntQV4f{U#BQM?D_& zud^c#6s}~8FLlR!I21tP=4z^HKfBMPrD#X-2ue*gW+dNb~fwi>WtbG6$)ol6_ zv3+=jv-2=Q0?;BU3%2K6_y<+!Yp+7ZEz2V3tbchc^buJak`l^O9UR{$3fdAp5&P5l zN*OoR{MkTv7G>H13spFXD5d*S!732LYK1T9eqPW1Ww$*KBu(#TegFN@x>k4s_gTS!#(h!mclmw zXZT4SwiTq|w&;x|^@>I{lZQ;7RT`d)AlG-6C>eu{?KI#I+M4Ey0rD({Nj>~svvJxu z8seQq-r}&)^3Z%4so%gv%`53Q>{>h&ql6t}-a$9viclQ9Lg5mNqgk|x>pBaLV4y{e zry=fsh<#h?ZyXf-G;67)Gmmlej2c`rJ%5a%Ub(B?E99HH^&eI4xqV_BTv9$)Ns-Eg z6$L(XZa5H}Q6YM_RQYus#tRzXJNh?6honM4sG_SuUFIO+Q#mn$#zo1~h?|%8%C2#O znUuID`ir592>FD0eClaPVOh%C1q(_XnNiS!4ZB*cO#xDcFBhwGMBt2JF*t}#{d zY8+7Z+E`v5m#}jdAzlXp^At;Bm6LcrnldkV%rJhiZ-*Z`gkV5E?A1RiEBz}XIDm+AMcst)hQumQ zYcaFp_6RUwe$tJ}J{=^j!{Ue56wrHd7H!$}0Vg-H8p%C+Om%F>D-_=4Xmi`L0KKe= z?2TgLAd)6ZvQHHdFTQpXELJSXJ%y=yz)v7pj+F}!Zmj| z$|6k~4Z_UbDz~_>^LV@ZC=08#8|Bb9MFhqh@Z8Q+oEWi1>y12|Z6vXW2>%Wj%3 zA-`^hBe=I46UE&U=^439<;$UHQ9l1Ed2420tGZyei+6E(oC2{5FVBXE$^S6)W9tDB zM$Nm!A7=z%a)1)U4z5e4NBv^%iTy?l0I|5_Ue#@;*g>*S*k*t7b!Yl=j&KaLfq$2> z6{=yIrdT;-^-t8Eg$z887wj^uE^ue{66v zF<%M_Y?|V!?D?_wERr>9tLB{btPR^kZ@44;<2+jhaqMFJzEs3teS}Dn8vn zLvpoM`jTlMhzK*=S=*~eKxYXS5=Y4F(jJrJm%XB0;Aa-@wPi-EP1{Db_9$8Q7%G~i z{B@f+qvYds3y&Y{qVR_kJwiQF0^a1tgP8v7Rdf;w{Vz_mm~x=qKo*S~dG~8?>!bug z)TUrtf?r~{t6Ls6&@9w(=Qqgx7$MJQW zm88XPtd8oS^c)ECWF4Lk ztxOJ(o3WWmbCXs(gY@5U#OXPj{Bv+2bWWWTWao!MZOg3QQc>lx#E#C zMVL|}pkliMRBpH?AF^=8YQrU~|564#CY?Rrha29ur0!h)E|i#WnPNZL@TBrn%x((% zU*aoR!1r1QomI6;S-sKnRuWfQT99t>nrV^ZitaoyW5h3{ga7dpSq^C6`ATpRcj+E9 z52HGC|Hj8N`!K$WA{X;i7`_!TZRQzVNO?YtXlLO^scC8!gQecP`)j52JABXv{6-Ji zH0D}1eG#JE6(oFy6B=VIy<14T*>g7$R(XJIPifq;9bcaN6b0kxgW2IGqQgUS!vv~e zakA(TPh5j~W=rz(9)Oi$xg<(kEe~(=0B?j__|5T{DwM_PH4x80jSC;z`b31m16f|? zi9#J+XLcNR`nxO(0pKZ+Fv|W)$r~Fg2&u@wTES=%iCT?sVcQk26e^o`g_t4s80<<9 z&jtxb4-^W;(j7*S^i@{(#J1V;FA0>2Yf@>4**9&tCvzv79x$T3?6&B^RFSbyE|Oa` z4{!RLnHFQb3>Z_N+3L}@y+LS=_oBXk(nkSef?Fv&-+HDv96qUW>IM~+;k-@(54@5g z;IvyOQv>_Lt_lH|mu42!^~P!pqDp@Vz~eg3V`}vu28RIuNOp}eMagpd!=qDFL7cn0 z;bbZa3sqYcaY|74XDV@vb&vJit5ETqE&wzKPG;81kpVqJgq!gEZk=a~6J#+Lh-rVQ z(hlPqF8d=(`co;gZMSk??^&%XHbA41TcCkkRxdQs4M8vEceNNSObiZzWItF5N=2Sj zOePW?Sy>-e!8z_)Y*GCf#EMXUUD&8`IOi z2kaO~ljbcB+SJc{TZZsX@fbEeNzNtke_L)%*A$;l)}4;G2-du)sgc~~>cz^|vMXbN zZgkhQsS0P=6_nm1BX~46AzSg&S zlUiZ?iB}68uKc`-k&Ibm-d@s5gg4>*zocP6wf`R!vin@5hD%^z!(A&LmKY_6Sfn~A z%rB(qtsab5KDpH0M&O5^V_xQ-G3WU0fPbgizTLSCqoD-AiX(04B;N0?;MUj@RSb;a zhy1RNsn)Imu==^St5)n(FIHqz4k2n+Qe5)h9fjoFIhUDYNahP<61~iuGhY`nTLE>y zcY(+77++yGoT?dfcL8%8-%qQ8YAXr1Nv?F-5w*}=Cj2A;Vl?M`s}Zfr+7up#^xI0d z@Uhs13h5(9P-L3K@Q0OKj)7YW_YV}OPuE*Dt;<&U_m9G?QG?+lLp@+B+C92OYZX(i%-V9 zIR+pEa1ude;r*CNIphhx0_DN)Ape>8pR#%pr_qbWErW=i1|Sdsle*O_4}yYr{%(XP zR=;HGK0jI@d7gN+d2l1>r2r@j?dg0eHE7Vsr)G$+3v~RNY&&Zr&hXq7zU=V%F-w&1 zibp~8`1ZD9;sExYxzr^gxZH+2brBb#9(f)r&&9`)Jyud1i zWLH>U0uC-T1TYBTUQLDMW^bZPc$}Oh=ueX?3j-n)-*M0UC@PVbECDx^D-H#(K@PiI zNIyoPzDrk;w!VUXBGW}CWMfOxx(p{HgIs0H!5BvU{bHZs`gVGy^q_G1B-0_}!}0Yb zL!x)t_&nOi+JN_rORQ+GKp@?GS zJ+IEzrMzod|BV(nR(ldw>;6~?s3l<|UVf19>PxqQ&v;QK!Fg6%DQkiEkt8epLS^*+ zM;q8EdKpg*368cdwO#Kyf2xE^#uKoqGnf^rIubQeG_aqk1cYq}o^yOtSJ5BSQvJ0% zfn_>>qd4DQ_^-3}H`Pki7I400n3O%)9D~V6G)JK>4+YnWy)Seh;9c4_E92~Atc`v4 zvm5P=dkQI%PGt>|ogR=c8^C4&ZouBB7rv#0yT6B&KEa4PVD0+g$?k3Wq*8mCXp~?s5Of|MF%)X0w5_gYo z8~sLc69ybwGGdua*}I@$R+tx&-!ikGV_+>|MVF-Ep7wc1$y{VsYF@%_rPsal%+w($4bFve_5+o5Dz9;mvMe5Ob1AE>xyl;z(Rz+PBBK?+F$w?0~_X zcW0wm;M0m$E*|hI-{VT}I;iMNPkB(&jGVB-+P2q3P-R)WP{EA|d{Mz7yMG7#6vH|G*Opz;rdO<{ux_#!7Y&!e;DBUZmRjYZ!1p45EZy!n=Oh^QOwM4oL92 zJfrkv*(?Ob`eae)!PW8P_=}*ihhOJ^o4Z!=oYcabx}#iIvN;f%;>wiRFH+9_WD?Ye z2r_T()CreP8?)I$zz~~z4CY5(dw}uVULHB|{+=F#WpJnB$^4OARcIi>XkLihH@=08 z#VsI6=iMWHQqz6ils^4I9b~)u?DaPJ?l(Kqip&@ORhi&WNIS_~3j$mMC_%3I*nZiF zrZWxmd+oBa{GPZ$eb5J0cYB zc+y)wf^FrMCA1@kcVhI09rci(;Wm{6CVg1*-1^IvWv+7hQ})e-JJ}8EeT#t1P_*-V z3oD#@p^CvC=ddDoU<7)wvXSzV-(|bOlO0Br=WS$TLhXZEqlEU&1st zr4;N`VBc9XfSa=&x+Rw-T_0}po06ZMBQhR5GKoHBGwXOxSNs&d2mh%;UhhO?|NUKi z9DV$^rZYdvfXkf?2|}3uVB~o`z0=yKGo#MlB47#-g#`UiK}mP6?(GRqOJ3Ya3!y?8 z+77GP`Q(!SjjqEbAjzU{rx$Z5C6qOvovY0X#zPWF_*O(7U$u-O>cBgNiy#)*E9VX` zcV|KN^`ACVa39V|E#@23WfD+39`W2StUgD1N(vZ(J+b-marSH&NQz`q<1PS+qqF5G zCvr?%v^DYw1W`oY&{?blX=N_pPi=UH>u!L`n8W_t+g|yQF`)TD=6GhQdgnpF$@Ay1 zS^K8s!*SBq!%X|Q=RSptVE3-~W4x=FqL=*9W9A31ssiWzasM_UvQG&toZVT7NFN3o z+B4e@4kO9et0QqtIw&?d!YlVl$St~aeRc6(IF6$gVf+ameSnj;GJZANN;?rj%I~_B z<1i%1MI8>~MQCS|e9rkeo6lnZEoWG(IJxwKqkK(Y@a)Y(G$V%Rw@Kxa=^B3aL}y1@ zsszPeoLOCWUzSeg&oHQUl>;^UK6_EW*e~D*BNsepIs6sE193jwU&;CQPI%KL@eCfi zO`4gAV`a)-Ea_)WAWHn~oZl9>uvw2sBiBSbYrQ(fCqXhm!p`f!_fjzS!^NciY!s4_ z@fSJ9_Eh^anQ!P?(z-5r2^~>q#p&vyNay<|6A;f|4w9NKkc+)r`rBNDgbvyts1Wm; zOVWCXP9L#7DPx1gsya{oW2orKnOj8@MLU6`%+bYJHaTo>7!TpS1Ki!XqN>)iJ#<;5 zX}gr>DKSyBrmmX1jiL;U>E~t^;cL*8b7?ARVETnXN)r>_BnERt{*QzMc zI+C^nD!VkFlWDaRxx~e-C&$eA+e*`FobR8p@{Zzt?b$k;0>aytT7$*El9uzDC9C~y zyuT$4@S1}4Yo&tYz#pwpF^&wX*<;-tT=WQ-bQbczLxep_x{OM@I(8CG;{>WHn)aT@ zBI%{3KVK1hegy|KV=<2O?h&k1S^J!QjWe+tZiK-;y;r-COG^^#;OlnrVmOsEd_z7; zneW>l?)80mygx(T6eXKM#a8n!pwwM3#^YV=((!%#9@l)`v94XD(ox44pO(87*L`3A zvjNjjbQ$u5HJdf68R)C{BY{Q@gMXLlI^91b2LO13f7sebA|#;%)q zH9r84I%@n*2|^H$xRd7D=f^+Ky3MbsPn9F}b2VC4rJbX;&3rdSzQ9q0$=bQTLT`T{ ze19_;?zc{+)5XZC+C^$9be6RMfe3R1>D=?;*KzMT%-aY}u<~=%qej^=Gcu!W=7!`vIpb4fzH0aj zKt--E3ipj4H-LHYw6$|Y_~%w(>Q~Yd?KBXA^>TbMoadWA$dvkD=M>jQm+ZNZVUlZp zixfVf17!+PQXd$r=Rokw8a(bI=F%Y2(c6#ki=Ex7rsld5+KCQv$ToVKg(*?_*_Mvv zlIJfs=f+g0zci&*MRD)`Bo^q8%OM7b>1 zt}cuPEIzLl+4)(zMO=P>WZTRfpjK8*@WOur7_PL+eBw}WB%Fu*V|@jcCa(N+rfw~l ztARGByBgXxE)$)RfxhPN=yD46bKlPv$|1#_kvDiF<=2W<=(HpE*-rl`v5WEg3D38i zKe^ZWu3=$Ug;+N7MnQu=V_ua6`ffel!ADyvrJpU1u$s!&xKwowW=^6b=WYuCWj};% zT~JZXeJx8Qv!(bGF8sxhFbP-??X&>Y?CsR@JQ21TiP93-*1XAm|RK(>)d8B3;NFyRXtc8cwBqSt^GvK1D4 z#XrJ|RVy^R0i9s7{QW?jN1f@Q2jXHS?u^HmVIk@^`rG43JE~8aPY@CjFJP_{ zg}oS26Cr;azNb2mcEXoL1hf>tDW_j@W6Q@79I2xy6g&2HC9yBkH>mIm1X$*Xb)+Yl zZFuDkX~NPg>x;I$*CG-6c&@ruvM?g(;Lu>FWVRZZb5qnSduY^J&w$gHDi0YA^BWwS zXGAqtvWA!1%J(HcQM660Y0cfj&Wiph676c=dorQOeL;vu5AkHA(ca)t}V@VO{(hFf~W9XDT$nCQ|D&jI6wYUzU zl#!7_bE$zGu8j8^GXOh8Zc8_Pt-x&xKF8Y>D zzk3Ou9{eET$X1an%;lR6o%NqaCE_Q8SeZ(zZeO>_^PICQb?81(b1v=XQh;u3JzY%O z3fF7@he!)SvCNLJph(U}6%^h#RQVxualLR0*YYXF-YXjJNOoNvh3y%@edTJ<1pVCS zM+d|uL8$1znTP!{pe%fA{p^U-sCplbqKFHyc}y#{^!XePn(e#p&n{9{@|I*r9GcbT-OzY^BKoy2+~^(RrmJe}XKDeO5@rW&xa*@7el z@;&1y*k$dpz>88l&%*#gG?CLOHO|`ke0~FM-&s;I*vM#Y?UWeV1(KJJsRD3-p}tT! z8_}A!(3@RC6_yMzyv@@5qu&tV(R<_Y=N34wAl04wf+iNU!)G$k+_0hJ-N5RdB8`66 ztD_c7^Rvgq5``w1qL-L_lWPVe1IShgR2$uh%@uW{=-Fp?=&Cg~nr9ZWmztuMQ#^#Y zg6ApASu}^;mbv$P`>@MZU!~Eogv%8PeseV3Aq;3Jk&4ner%Y#m>3up3)h#gMzC-BA z6gNwl&RSrbJWJf^qX}j1LS$Wovyl>xl`aPy@aErjlv`ITn?E1`a>lR@ALUr|nM0QX z-v+>9EHCj_2f6{V!=!EAGuVxp2 z_Y3y3{K%vqTqf#NYSKYe5bdFI9||=V z;I043I!^NiQ&~bq&f|$f_uuiVK51{JalBZCDb047Hu2qaF5eQ<~^Xwov^fv|2hzkpeCOwYN9` zn2!Tf(Qt+_DZDva!?LVx=2Dd9*=#{H-%TbsJwnXNY5$-x%IjdwHS!>9J!N}av5r^` z5ULY<5UtVKzBFM4`q}?bK`5RySBN7t6_=j}1wWb0aXu&*lWgIgk)ba7Ni?}$E847sK7eh)c*i)C zKjuOmZbU3sY*2l8#PEtyHf$Wh3q)SDPvGG|_S0-8)f1EWrjs(d(1|<29-Fnws&X#T z&+5O8eGI+bReCY-9oNd1dho5ZdNutWe%nWEUq2?lk-ci-kzPjY+8%mcEfnr^$T0t( z;2H6Myb%oc+q-~4i34$1oh{rbk&Qq2R=*#b7|i25VN=acEYafNd=Tt;z%2(sVfca& z<-Fh0woyw8y&Ku=9Tt{&quQPr3GhxC<4nFK1a}>A7mgqg^NTAg&E=8KK;l%C5**D3 z1`O;%5N~R^2m(VZwX_K(Sgn3*P}E{TOyY8z_IKO?vj!N@uDesk@<&=K@b5YD*SZeL z85w$I^yvW%T8JyjEWXEni47^uW*qGT-=Br9o5nBi!1IV1gA`{FMX6=jsG?0)VM8+< zj96MuoYmW3I0j0fLZ=gZ6V@IZoSc=1XNGi@ z-WZ|!b)M`r7_z!Np_kOawwS}L34XTBRTG?q&Tqb zYdQkQJX#k*THI`VKfbk~YX#p)4vU8DSct44O2c+)H)YDm3Z#>A)^Gxu__gIWqEJN` zk%FghEti)cv@?Xv=H`GYc)-c8=_7whkAAjDdjZE;?sSA%HVS}3_85-Q!vSiNd^Xi2 zV^>-XP#bI`Kw1@GhOO}NVYqYw@3$q-Xj3*+9Af=Lo--CN;9UDLTl0oxpn#ty!lmm= z5RCt;2Xo|brr-VI^~pKEvhR~}VDiw>j4i8vHTa1tvY-PJ4Oz(NT|-Dr{XsK-Sa^`l z)x|`rBLwb}4)a?Z$1Oh6a*ZLhsntW`O)#uS@)6^3_#j=7Me4Ze3LizFo4Y5XVgLXu?$J*9aRFDt#~5O4RRf=dBo%c#z_rP9QxD=2yM= zYn#bByomCr#t}q~%-Q75)InFNf>xw_krdl}UhQdzNFYf7eFZ)9_nbPt7=rbfxOfnh z*$_HM;utD`{nh+4rBxUl9Z+Hor^zUBLlSVcT6oYq&jnox*9~)FCYa_5q&y$)YSo$1 zTk^E$!koh0Wc0x`eblUtTD0Z_tY}9??GRab*=8szI!+@k%rGyVgY`yNiepMcogz}> z^hRCvk4*UB35pRFfK-uv8D56=CYmmeSJTSZoC3ODOQZX@=Po(zrkh6Zz#6{_J<-M z<^9TO#R#^{!|7<6lys6tPUAdHx?`56ry^O^e>&^%k+v@kE#w&>D<*xR7yVPbdpZwe zM1w!{TT-=rhd?vC&rg)via*Z(iC@^@uO}Pr@Qv?fz_jHNQLyz5q~2Fpv!TGzS`;`b zp|M}r@Mi$h=(eB6T_VSDA)OHe105EHQhS39O7b}o`gLKz_iI2QvY~@cxRk+&?OzG4?S)F{LH0Q^c{q!t z>8MUTuxEKytK#uuPo@9Cs*ew0BO1SchDsLPv3OJPxwkDk?`+WEO8^)TwbA}vmDNLY zLaO}K^3gvW;L2Cpy`uGJh?dGi0i%MmqmvPT+YtIoTU$f=rEGUomC7!yh{K?#`|CF+ zhM+_7qMxp1FT1OhmrB*Bm)HDemh0fV6)1{~fGezbVkQJ8HC%y}Q)v|kIpJtMZFO2c zLE37)UHOAmm^_)RmX{B6c4Y}l$F6PxG9(+q1o$9c*dM((SmP|AssbH+ahI+8QqNVYc!cA7j zIfH>lVF*r9X#Xo&ff2xSrs!5>K?$@$2XaiR%j({`{}+ZUaB0vvL2vdu;nL z$&-#!h-Em`eTQnZc1|f9?WmMWN#i-SndmT}lcLPghny0|!mM?SYJ+qBIF4%f&bow! zbQ4=|>BqPIj9lL=I@)iuSBUVWjbIr*xu!u z2x&}Ksu)h~Bv;1cMbCP5VhI#MoTOQEFT%Bf#14kPt;1vO6OdpefSe~pq}s4P(LPNA z1N5x)h4+1+locOB-Wd>j13M|M>ibTHwJg4Tce!!nNqcaXY`zg^n=otD_8+W zCMM8&p#|(NUPU~8unyB=L|iJq*f;`psnU?*2Ig@44uDE*LwKgl>5LTZMe)|HSX=SC zywY8~lPH<8wbHj%hB$du)m5+JR-rqbl6%7%py$zstvv%$`nNHDxDcl6}eg4JWTqeWO(e(k!{J!3WPi|yav=xMyqS5#T_YaL^ zHrTh{B+%ZasT7TtkMMBsD{Yrl^uh956$()UXz8Vp?~6mS=GhpsFZ`C;bB!a&D<*wfuS<;oK< zasWeOv%Y`EF6^rDR{!9jA>0xzAGSXPTv6tH_X1ipRdRQvv(D`4X0Ry0uiqJxW+o$u zAh$wl)#Xm#(Z8beULqm*B29-NV6f&!A(J!C z_=Bf zUDu4q$>zc5MziL2c6^0wUXQpT{JA=7jJ_M-FYV|$G`Se{c$n*y-a!vw^!1w1N$M!+ zvhk>Vflekh(X%yX$w>(2`gONU!QEp=x4(+)%Hk5Ba4C|27_%i8q%0cHN)hF8FoQ+v z20hkHsubr>-kf--#OL%mkT)V0i;TxV3wz+~84?uHI^kbX!AR(iUo|yB#_@L;^o%T zV>`eh0h~q?)2!La*Y#c@`lFC*V(>ACc3#xVm%o}7jTr@q$!a#z3hq>F8h$>RDq%d8IYOSD1+C~n_ zosZgChJFf~YxoKv(C1@8uL9LDo0$|`X|fIHe#D<4T|E-NJt2s_LLJr* zd?JP?Ho~*#7I?W+YbiE?oD!#27!IkrwxImQB6R>Krk>_n&GQ0<=&23mdSx1BU2YVO z%-RST7bLXG%CP&T6nIU?-M2~|JA&oJe48)-zxdfq_>VwXoka)Gw^{FLCoIO&o0cOo z;=YBS^Rnrp{)z(^MY*+U;jS`#hY2dCw6hqdKgkt`LT+Gu6svS6-aRgD?)C9?0bkb4NBw22Op7$hUVJkEaE;cdE+TSgH(Sfif!o~85<6E3hjxuD-w-3%mOXBVw zN}-7XTb|B!KQNBGxS>KXr+sesF-(Xt@Qb=zRCS`1ItVGqa);;GJ zJZm#`-Zrmn2)#j<1{DauySxG!FmgI$ze){waW@a_uKkP)m19yW^z z@iiIBU7|x{Z*EU`tuHgj%k@ehFGbp0HSQI?ar1uqLJ-|8^L329&q-&G8tEpGxRN__ zo-@;p$%ew}*GlrgloQH_O|eaa#q8)(uM z*`iY!R(mhnA(u_Yvxb(QPK4jpPh4yruIbxmwf%50Pg?u9c5)5Z8FeI(7vdAeO%@#k zGySzADx};?o=AEt5{mR`sq|Vk^%nS}A@nj7O^W_ji_T8VJuwA?HER9Z2A)RK^ zB+EA`d4)Y*uE!go-ENT8u_bE=2N3RV|A4v06 zwwte*EK)wsYnYCQ+;Y~;`jq}l zb-Y0_)_b-m3jKqK`iwaldQzPXZ|y#{mG<`Im3L*bF*Q6@4H+u+tI*8w{(m{mRf~f> zI^C&piulKE>zZ;l`kbI_jEM^O-NPUiRs=1o;hF38^wnlI&DayonD2BX#XF;Lb>HYiU=8UL;2 z-A|P%!qm1++1A!DwY~LV!i@F%{4@j^91T{nnt@j)1Zf+;C^fCSYV~R_#uEDhx}Of& zo&)A*oEi9yD9XOftuf3mvCH~xFn=qA9XRx|I#;00KxJw@oye(e5=55?Aq11&Q##(0 zEn?kYubc#h7J6d>{P(Y=gu^U*DZFHF0x}4H2@^XOi2}Dkti_OdB!_1EZgFk}9l*fT zIuVzpuD+MXb~vD_}keTtkP1895dkup;{vbRtksw)S!3%$|*ZqCp6890_y;{7Q^3BA<{ zj$Vf>Mh-ZGIPhUAP(Xs@u33nXu|s#bDWn{7le4=?(WPuk)JIs_%@zS>QAp=(hji%; zu^ky2&!+0!x)OjX*m;lR5h_O|c!- zgg~L~%lNLL(i5=nq-u{1|3H^8zQcZuJQ?nuDP$nVd1r-9)xIk)_u9o*v{X2)sQM}D zqFKRJZ<2bZqy6|zS)9>kOj|=xCm-Zt(s`af-#k;1@ZRWvhAv0P!V4|v9x>(;rEDTG zxr6233f{SL@yJlhrTDE=SXG8MeDBV->cI`WjpA44kHHZet0U z3=mot!`;{>Q+bKt$D+xI!H-Vcsfi@%&jnG=sYd0aDhG^-d4{VIC(*IJABsOsayWlo z;(Q~8i-|(4Bqmh}|G(f&h%RPksJM0{$X^DCL-xoVNPN#5&Eop5K!692nZX^77564M zla`D!`UurCklZVXy)^w&lkfHIO@l;5ilAmjrAJ z$Yt_{^UB(G4OU`TjAP71CGjC^sNAft<3j3z3Nj<70h3mZg(DB`J-WU@JJWV{XI-|I zdfENDv05IXA7Bz)6d%f55;NJTaYf3yj}0rhM=yPY6;<*~$k=<&dNGQ)mDpx&!ZnlN z?fiOQk9Nhfpsc}#>fiMewA7_*QW?8;h^%@qt((B%4b#58&f-rH?W*z&(=-#Qx&Y)|7i02AZ z+rU4ruwU1K=@Ka8^TNV7)tCR!RZhTVeFcSmiZ0e=>pNz$0sk~(#l z&ZaB$6WWI7)fF4&FmV!n3!ThM?fQK?mJoHV{*TKW56)`P|#IU1OxWx=IFFvsNj082RBj22vP*G7ES~?x?d#1A*(RV#= zVK|*os@sOxdd_pIt|CYu|FVgQrCFa-Q0~tTg^1_aXS}V@Um>BVw~+ChKY_%BIqu~5 z@d5!*arxI3kjpt0?V&~|in2ld28n~RjbZ)1z^iS}1^-8QpfTr^gkl@g(gb z5%Ia2syaABUS1!QW6D=NYqduclzIK039UI}!ZXUiecazAvfc>Bjq`o-f>T{>LQ55VrP2DeYlt=R!wE;69ls^UJbY_=0ud@})X#ki?&IGrTcbOR)Mt$~oKvP3UP7gT{l_ zAMr#W0009300RI30{{s-00093K&pcCzu-20e>RUz3YQCQ#|&d>(-qRb!3sYhAK^+S zxv;D*uL{`pq#cOG8dOHJeig&-&i?lm2M)Dyybf9V0paR;M*6` z7aVh_S8+H>M85M}+FX`azWHLr8-p|3#0L`PyB1m4j4y9l2{ff^KMNnWGMM z13AR(TMDw@v)!SG`5ZXVQt8>j2n8*yz=5Qe>xbj4NCABL%gba{t$pBAIjwSrA9N6P zeOb7vc^817;W;QfVXJd~eI?p%Is7q}@4||jTrxsD$x{$`wd#WSD65-&=Qc@Y3SJs7 z)1xPDNZ54LPWkhD=zJxhPavS;z^=)ZdqjuDC1*xrr2yrI(;aJ?!bDfk<-+5A)ZD|x zPYHmn+|Y-rH>Z8gX0Jj0=~nO*xp=LwBEub15AQ~g;mH?P29KQO`+vFAf7Go+kmgL? z)0%drANRTFw0OV5WR!ly$?{+`rPds9uh>{hbnPL_k5II#<=awu!b|^ut=cFLvcJ$7 z5n{xW_ozeFxUP3cBnNg>$kgfDh{ym{{j-uNH6mUn(qsiR{n659FyY!Rb-qCJUYmsn zkpHE-kQ3!k4~v?DyoRXOcYFklDjO8PF?&W0?A!-MM5o5AX245mm6OY`G&WByQg#=E z&eG5B-KOD1i4tW+Mxm&43_$nE)KHoJHSxw(WR<~K%=cbU@} z2bJU4^Jb6a@I?dJ%T2lq8WvjAgdq9dzQHeEu~x~_Vh04+!Y+|2ZSQeCL30SeyVA@|8Pa(F+2L@zD}eAD~7R5DL`kZw=eZ?_2btdDd!?!f%YK)da2<`v4) zYup2e_?%Ozq1fDR?3-%VfH~JP<-A4C3SI{cuZLtwW5d!e?K#_@Y~U?3DK*pTL)ad$S$Dzm6h}Da$O{220a(BU2KPVAu`5RtwTG0MKUostK`PY7A zZ=6$d&7f*4S~G|~{{6|cWyA3{zw#S3uwNrpSE@HJ?zv6c*)+q~J-=`+L<7xlSd%eI zLd7+9Rd7s%X*Z&v@#L|8%(ovCzpCDDB@iB24Ua zHeyTPZ9wcLd<^eNXyo=SZ1?(rX3lJXmpis^BV-`YpzoWF|MsTa54R4qRn$&#bNvb zxV79r`vhvK{?hxBWc^O!DbtFSvj2i2IWT4CaZ6Di9p{$qzCQTjRmTG?nR^bo3Hg|r zbAkDq_OvPlGHBE)X$nf`z}^~on3U>HMpKn{x5#h9KEKpIW@`o>4>a8k7ehJzAyhPkS}-sQUU_+U~-;4`~iIPRnhB5RA2F$dIqX zh3y#K(Z+e-_rz|C^y~@Sf;;p+7o|>_iw&Pqc;|V}QD6l2RDBCzH0IUqSO*R;p_~zc zaV++dfv$q*e7Vud#J@y)+kM~UE`&-IL1a@iM-m!TGZ zZ$DgiB1a9`XEV?JmIuGacg7(c;C;O#%R!=2b%j}<$?TEhvxxWc=nAw(LU5UI4Fq(> zCAy^iI!(Vz0cTq7+SI}@*+I~)JG7gaoPD6TS8h>%2fuikRD3UpsytfX(Xgn(k_=tp zoBr0<>o4N7zFN!Z!&2<+&$ex`n?eZuKCPKg+?m46?A6yLW_pjDYJt__w>-ZH>k%ER z{J1Nwz$iF@2{#Q~=1A;cTkkAg0dm#lH)nml?rW4t3d4=c*`LgOrD}Psl$x>8U3G|@ zi9EGW#rh_jjNi6^K8r23W7ozznK8mmnZ^^;DqXASz~bQGv=}16Z_W^IU0R+$>Xla! zCq@sjzZ+7G5hmK0O=-=KjoNSxiPe~NKlkJkeS49yls;y3PFt}O>MG7+%O;&mZ83cE zP7iXjF&B36@I~~$+*(s5?MZmzHUe*lJXjk;5qgiC53-2b{Dm;7OuJ|2^iA0@@!rNi z*V;=VG1yMH^oM7!$hEd(xWB{Sz8q)aL&agCQ%v6Y;OYg3TBuHrP?#S0MKoHnIv~jO zr{uXkGEKd86JqeHDoCvGjD`Ahf8!&9!P|ies+Qi|mx|yy>QGFS+F3q_2##}taTg}G z!*3Czw74i)*xG@S`uT*WRuViZHa@KIPDJ}Lj`_))^^=c$gx=HCi46<)D?exHvS%>* z`tvBHtw9$i|9RFe&RMz#;CJkyI_6A7xM4q`uQ8tu#su<;LACl@WN31h`>OdumWA>t7QkN1xxWcxj8> z2fo8GPgmKM0#8*fN=3dhL`8u+dkao3QJ){NU!r9F$xHc*=!Epi03;H4>v_d13Rt@x}`$oWX znvQsfvfL*&+r_;58ic^LDuWd$k_pD2HA_T!AE`U^X4a;Y#7>g-x?(BQd>-DKeG!q` znHW;AqEw`vCv*G~w=mhv38+qb{*O{`{c zh}d*!Hd%obR~^M&zL(T1?J5wH0K%zpcbc8aB^*an+=0FbOQgDeVP=UuQ0Xp3z%Fwq3YCNS7|pF(ss=S@cbS<)Od2wi;gD3{D4)i2fU0m{n((Bk zdmj;dvBNnRg^}zBn{Ot(hsb_zvyW||$VDHS-N<~n&Q{bGUUnhP8~-_xrBPk z4S;ZGWUhWHUy>@ow?g^4wBE&2`skg=I2Uyd+PLvlo@oMGV@Q{ZA|RHbah7%E$V}eo z<*^5)6>mhEJLG2dV_{* zLPj&oHJRXEak|IC=5E+R+B2r*vh>PDs}c68WPzU%fa@EOW+V_BkhiK-`tB&U%bWJlK}(VE#fHubn$+AZg~-&*kGCU|h9AT-~HiKy`BFhSPrCb!qwBbds*NCDY;WhW2eEZj@+Lb zc3b0dbyPfN6#(^il_5Wo3QDW(omK1diSKNI?_n)UvOk5PmvPsW3kdA4`hHjZEG?kj z%o#^0Zw7z(XodzS+4U|4KfWVOkg4&%a)14R3I!RfA7rZm&6J~54cB*U%kX1?c_BNQ zARgD%q)rZ3=gkW%L@vQ!g1@fjQ^FkzXHws3p8KW8;q1&+&b!+< zXMi2$L!2Jq{+e6I_wzG^8)f4iu#~Cj`Ip)xug+Svod#(;F?LmnFX<(V&?(R+ zU%`KB236A`vS$dN&Dz9kVExO?s|LKED~FoR{i zfI3t6JnIs$9=8{YZrNFOeZ?How?L+hjTSAmBO;GZra4o2<7#=FAmkZbz&kyiN)eN7 z#yGVj478(4#&J8Qw5_;xPd)%=&?}F+{CW2aBN0g{Dd90`QmPq&h zbM@5ycr(sgTMPTK*EB3Vq1aSTMkZoUQpTH{*v|^Pw|B#7+Ugqhx2k(ilMPPiv$1(n z;$7|tDkG(9blkhqKG^?~2wOIk5iK+Dn$m;MtK>ca?HZZC?Qm$*(S8P4wiWjDRqR`< z-_h(+xn|lE)+%W6=j~rv{^HHCBE8IJV*rl?)*UkSY{CWit@O0S+Xc{amio(lq*Jm= z*^}W07kNMu6ApA?J^y277prz}66k;23R+|G7l=snh8q~fdqcDiQ_!%q5OK3Y83mt- zpj0J%79iNI{XhKIsGt9{avy&M?Eb|556E$THIF0YI z^Pql6ofJL&$lQds;04K4OE~1b`dimw88L(uez^D-cW9x7u#JQ~Y>)G4=C-mQCBPWy zG|@=77@ST#;7S#KxB7k&y8`^DUUfHq7auHn&R3f9X@m`K-&@AqImB4;v!2WhWkwE2 zc)1fz?&d|@L#tP7_R1d>8^Os)NPbU&m!aH%ij1Tn#*0bFZa)bKqM{6@Ox zR{+@Ju@MJ#O@|rLJNGdcOZFH&z-87QN&c%YdofYt&SSfqi)?hcHm4(%(dz075a{hNiiu%Yj1_Nlq`+)Uv zsM2CkbZ2=9N`e}pf_G(oQtp+2h%=o!QlJZk?EKn;A_aH_fqh=C1j~im^WN?YwlXyN z+l6D=p%#=b{SM1C3jz=7fUJ;n(k5)nh?bw!8kzQH!LZ{aZIln{C>nsIBqDqVk&=-h z8-(s+^!`n?tB~O+6B^zLRBPN-N@bEeo^#D@Nh>h3LLI8W7gF5 z3SO0fl0^eGk7j7lOUNx%*FHeZ@Mc#M4kWu0{{R60009300RI30|Q9CxfE=JvZP`R&H<)^i$ys@uO3i) z_EsJN*zGf+?@7A*ZFVb~PP&KRSJX9n(@^=Ls90*&o+pD~VGPyXS}&dAZhw)bGLtEb>Mtav4+R3YS=^+(|9RCr8_-*Gx96YU++mx z2iTvC#>>3%21WNR#D;|K>Fq>>7#}bg9Obs?)2fJ;Q9<<;qGG8B7}G76QNkdCt?6O= zLL3Q}%TZQli|_7{BFjBW+sOl-OqONgI{?TqNYa4UBywjKdR2A!M1m!pS#fBbya+iw*)a;2(r8O@`_b!1|3{t5ZDr`i9}8P$I#Zkb2T&D?Y+)yi`mSGWW*3}j z4)qF&?ofo5ij4G2RUf(-9GZ!k4KlAculPmvKI!Yx^|^jM-t03|ER9H<<#{I*M7Yp? z%jY(^MBnQ?%$*R?9feNhqbpo+y7M5oO`B_2M!4fOcy2 zJC1ctw7XKXBC7M?6*RDTOEk6x28ya$fkibU;5bOS@hIPXUMl<(RUq%?+Z%E`rmEu{ z$EVa2&E$)e4|`?G2Kk$K%5SnmfS;)ps&)7@c{!N_*~&2!&L$_h#jStP#V{zFKrra< zCbqM8ECfGh^@{Jbf)}}qJOTT78paxE(~yUbI30)`NuzoWFx15S3LI;g<*?!c3(QNI z>l*HK`++}MA#cV3MK*oWz=huI`3toC{C^!ZYh?G*kEr+w;O@Pvmd1&iQIZh) zt2IG=5p@U=ykd0IuIb&sVCA$}gI^JI&M%K)KF3A9xKB>jft{M87}mQL&&_iQTbldl zQM+nq8--9xvZ~$dVWh9&Gb}*Rlq$VmjWJyVE~J=q!?_q^a=hR5kMLB zYj|HT2(9n&s5mlivP_Ge=n)acIs@eSRejXKU74=+WsRpfiJR>Uu>|{HyZ_tDgH+OL zw)MC-p13TBpzD~UNZ;lOeNzkze}3Dhz%5nLgCt+wfcDKoO<{Qw&R8E>ZjcK&qabj{ zQzimu#fFF*JiO@IbDdEvpSt@czESj{nT7*;D{#Y_-%1RxJs<OnP*B z&Tz@_>!hiEeb>}lhk>|icPD@_7l&q%g_B;$wSguF9=puTeOgC-$Z~3l4+oyQ>>J2n zqlV@7`219F6srFXq$rf{QunHqN7Z^*r5sy9P8oq+9bG!7uS={T>HKuvD&Q^ODEa!h zaU*G2;~ovsGsD4|5=Y&s^@{OP+J7*7Ng98+o^kAOE}4et9;CE%p_LgzNg+&XqXXLC zFh^S<|D1VLNv;Qdg*=sZV2h4W> z(sqH>A`7QX?o;*cR=yA-r~jUb#%zWm9$pFFP|nika?R*KMmfpGnrcY$OakR=H6^xy z#pk@rSX5?uph$-!z;{k7&51udr`~CBj=WZ_O!e^%^lcnAj~MjmnUUmqp}LRI-Nmh# z0RP|=%WM51t@w5T{Iu{i`>eI>D35BkhaH>$AxsWJP*ZnAFdPPJ+vr4x{QgWk;gQbx zyVyBFtODctF>;-Lj~pzgR0i=es+37^x4)L#2NGJLbk~&5;nEpO$=yl~4KHAsv10v0 z)%q|~tM^>bHZf=Ctlpr31~0!UVS3GU+-=Vg^NxbW;|hz>ORn1hBn2xD0{SE547 z&AT`#horo-)804qb-zG0EcITP{PK(Xjt1TcDW|INcAg(h{b*#xD47ob_n_EKqls-r z26A+n2|40FxtPN@)iN;q3yT%n5tPo$a?DXyxv?DNi!A!K;a8@-{=A?>vr^Qo3n zuN$D@{13+|3YE4&=%%ma@$b4Co^iQnUwQ{tYneG*2p${3RnCkTnN}yyOvT3X^D{~r zu5Y_j^MizytcdSk#Z+F|U8(n@_%FB-{=&KXDS7(ay1liK*P#|Vy%1g_jboWOJG{<_ zCFPsi?a{Ox6Mk37D z?ZlC!uzbx-YhD{v*HwQR4y5%yyaQU;=j`VN=9z#|tuEm!?(#FDig?B-{@M6Q{R_;IW&H9Lp@$riIjvG_Sz05WwRkA(KRdvq-ie;3uw_7kDQ{G?HE zga{Unvk^~kPL^Bd*yikMapZP5wbZ@)91RhUEcQVL0lbd;YB)&%d; z3X*O5moD0{sVf1_=IfCmLrUAh}AVf0B4a49=|oyj90P;vX*%&-EF{xyv#7DOTbsUCFnI0zbY&S?^P zzPIPZGBd+}(j^(A9#&nTfRrjAW=mKBU-Kjw;Bm+Ce?s&n**L-Vr4#Edu;yXyw~)FU z@kt-TIln#iFK~^1Dr}%eF3t34zd&vhfg!0>Zur7J1V|2U55qRJ2Z$K6o#8H4kEt?H zzn^6P4eh8L{7=#9M-J%%w=yt@b?b4=sSof1IqAT)F1>nDyJpe|LWOJvCA8;tRmU=T zM#wOM{ucQUVq?Jv5zCKrx|;O`*5(g+W-O=+tJBE!=C|14rfYXE8Y#2HZSMG zqpjjz2K~hnjp;5(uB>-k?(@~VK)4DMtPV9;F{uS>x9c&yzSd}Coe^&OJv@}t=vwZR<_%EmMA>ynQ-~uHAL>k@$fdq%^effr zZL_c{cofEt)iffkP>HEPbo&SXFbTT}{ItsVk7FbW>?kS65Ddu!6g*|p{J%J!B_Jf3`){liTV>SBpq3?0bArINaqFxTRBnnzsdH0-jSh4{cw{f>;c=lrFtr@AhN0t#w4$I$n0LEXdc5B1K&9e6f6bacD(|`UJ1fP5U%5>m-N9cEhb8i34*mcMo zX@GsTW3L$))T30HQkxkWTivkfFaiJlc%hGs4Qus5yHgct>aTyudkDgZ!W$qJbSG>6 zfN7AKwaO@lI)Yq5vPz~$H>q=HME~WotP%J0(hv`2*EEs=pL1tJ+}Hg)C+3>zqFPhk z(&wXbA-hY_QAv^z5S8e$lq5o4<~kPue{9*A@kRlG6U)go-zPyxiLAmC|lap*6q`4!oN_gsw{hxgC_A0FwDq9}|jFTjXcQH-1SWlk;# z85_9z3EY`UR_k!pvX;mwa2~L)(%N_U4cOC#AWf!%;HpUyC1q)TJuc+YQ!;X^vkqnPWvfSBVAZm%8n0O=nKURMSWIT<+BpC;OT71*POC|aLaJ#Ny z<~>4VhC0E1yQIJrb>Z1k*AE=m#-R=WiFO34I1R?(DQLO3a|LV{dSS3vvK;o>I_cJh zEB!4~Hka604DXT&rYQ?$z4rec{0J1))+Mg=e))$;@J`YPt!!%c?XFn9Ht@`^9YDNZ z!j}i?{&u03A-LPD3g!H$(&>l;$bt$XBgDUdS8N2EjA1Q9EGu^td1>dG|Ck8g*u0|J zaHa2!4%FyS+un@S^TuBwdOdC=&D|$%!`5cAdt4u=#C}?fXryqlx-7nqG;o(%NpPYO zv=gYOU@Pss-j?`r1KmdO!q)5ZX*GRh ze&%!#MpgCw8@$3g+JBF5A=^s7kpfnsaMZ z`KeyNJqgafqc871eB>$>2qiJz{DiK;Nw--4ot*G`d(|qY8wG98>36g(uo@s)aI+f* zmNRn>#d6|99cET&q}sXKt?=Z1PTW^N_1n9512AUqU#+g|QF{a=8T3PH{6cL*Qco8< z15&y`3(Jl8#h{b;3fkO2?XmTETt?5y^rF$j0*)|L`%@u!Qfttvx%-S4sE&FNl7wjE z3_S0AxGZWJz8vcU9=k~BKHat{r#Lpj(;_1rt&G!4^5DbaW#}55Ve}38bk}M|S~3>gSb4S`;Qoz*;dO68HTELCv(V;L z8q&$h4e0;Odl)ImpzC}042K`0A$^~X@Jh7a;5t~B-tQ)MM%qc-#JN@Yid z6Lr9hEQ)Ov*x|?Ea7^>{l`EQyA{S_M-q(0=Tg~j+BVWhBPJuawiI`nX_gp~$bEl}* zyVAh~>5Rg0LgW_1yc0NTY7MLlve<$T|IsSl!Eh#HuqMqK)J=^Ol|g_g08{qhXjh!T>IERm3>rV~^d)T7uSHlj76hIl znQ6w_BE6N$XGGL7OCktINR%j%{&?Ak7^P1O1E)+Tzo2XXeTYI`eqiNp<02`xin;&M zzB<$a_>}Y(Dd*BZTM~A9WH2ydH?H6YH+tN?4AZ>sN|n&c%jKs8vxmZQx7bgzBxl10!V3 z1%H`-b3PtXWa5;Z;SNQBoeB75);{AL1)TvwB#^)c39J&9_Ljn>tqM^kb}o0CHxFBL z(!qjQQFV>62OY?oE<>k=zw1cB34xLFfJwIm5+efDmnau(tSI05AbquGrt0O*w3<>> z?PHz1QfMx++|qTM-tr0zQ^FN2 zka)KLEX4Q(YZ{xLQ!)5E2+OHUe12twxibUv?Xu(C?h);GdAX6sKW3_6+BL`}ac&|P!!_;5wpEAU*CdGmk(00RI30{{R6 z000JRpNC|WCamc74k>9xc8HwCooyT;|M=_1e4vf}Il=Q`crb#%+gi+MkTlfpwc4Y+XPs>jP#4PjN55Q+7 z0?8TeeGNmAOMKR-0#x6H(=UVp@{sH%17gw#hg1houz%wKo3NkDOs{zMGC-cff}C*x z%#bld%}Q(udLff%-xi;e=%`4f=H8z&C*Cc>2%?kSGY${$d)pe34%j%fp}(B#B~xvp zEKE+C;3=^v9+V@_m5+Wn1;B`jPO2o#?3adIEi2!;DR1J$I{6$aMns{&#EG!bM^B<{LY zGEU#Ifie9k2b9dU?enN}Vu^_4%OvhYQ?9VkG=n^g47(mf1fJ@7;>S=qZJH8}6O`qq z3wpw?d)guE|4kBQF2Qx&kaJ*nX1(*rB3by4VN-%6i4$ov{j(rB80gXMpJ)HuZU3H< zb%5p!ht5_|uR_Hu<)z3SY?UfI2f61kYAx5Io|4i6(ySksjv8824;?m~m9iD;n@G zP=qVVi&-umD5LFvdf@Mq$XeQKF#BJ`J+0*yLX~) ztQ6m@s?vRyx0SKgU&L-F zjvcPC#fqV0GQP3xmW`1JuLX`@z4$|9gUdsM6gf2h^y!U6*SuMMyPGe;-OFZawK>Hh zFzhmr>W=m-2mJYG_kmExt{RXi5g%m`O(zFJVWW)?T}p(`7m+|(35gx@&-W8Q65b7} z+2GT6`{rV}NelE?{=kDGNP3{2zsi^fJai=X594aMy#*Hpeap5T(szF+3;BQszkj(9 z&K-cx8}WsA0}SsTL_^ZLK~?j1{ps*vinU5&uN>rW6?d`#@o06vVhLCNpm3134ZA}x zyAR@*tkeFknr#`#P8Sh4gVBSQIz=GXU+xri)kSAQ6LW+Q{qT}Z%w0qb;J zv;&Z0clu+t!V;R$tx}AM0Gbw_VFQJel=2#W{hIc~mXZ6FovI!AZ+L!mCfjTg4M^m@ z^(^tdtwQ|!Gc=n7mGyg9N~xjrd|5jxa)OBH2Qq4+I4~@+_$GF;IKGiDP zZs@Pnue`N%N+d zu8CeB;iXgMg*ZJGYO+BTF8bhNeK=B=W%?Rq90r%fSq>lfd}T`LxK$DZHVr8Bm;kc% zzNr-}{HyN)?AF5)SOzO1o8r_Tz^L8;IGY?#N|+cs+)6^e09hM6t@5v)+YiH{Yb~hr zwT3k&eNn~L-VuU@X8+g?oke3rWsKr0&8|ZLW!>qaONw?b-oP?Q=HcX6M%9ZT$`2n& z;RRM$^v%)CiypA^c~kBPu8v}{V5l`dG{tJ)lzAtH3;O4YH{dT%bI1UKE_GECxm=o(ZT`!b7I*^1pz%x{ zlH8vUyOg#Elsn70s^$gs`)IsKdm%S5in(jJO&-;df0%9ip z=bW@OMv@%JaeseqqLJpyeq714GJsZUai)gwi>dqFzI=u8{qedk!UqA*bdkThD;j)VUt`8O) zmCOn0zqZ;wr$&@l8;=f!VF;Mnkm<9tds@pnH|XZxXO^jT0f$?46#;HyqVPi8R_19* z`7n0`n52$V)OR(<!EdvRl!1xcY z-Jn<0I3z$?GugRp{#GEo_E;I!e9Mes)hqDw@S1(f+qo$DN6*)mJg%xOIY`G( zYz^_YHah`|XjW`p`NW&*tWzWDhZZ?lULW_6gLM^1BmAUPF9U3Z4C7q-6l$?Est42N`Bi>8G-Np#}n?2jvh|)fk{$VSa zZ1Y_{JaAR#p#S!Pe5LUZSu~Ff++KOAP1da)V457YHftAIZ~v$E#LZm40A z2~$Qg`ZT1=k8^S2Kq6rjpHH zLYN=srwqU|@Q>#YQ@S<9NX}Y-MdIh|^j|R?EgsZ_0x)g-)UB`(xLYzo#^rBiHf0AW zd<1@oeThZvd9p6C>2E~8{pc=Rkk|cB2q0ufcwLi~bP8!B6hU}~)=E796G82sbx?J5 zIX|f>g;0b();4pc`E7<$&G7m~1}wWGI@w`f#by?ActrEuh^YFAI5~0ve&lMf%_dH30qM)* z0vqVqZbO&V1u`X!z%}ho2WI3;bu$&Q4qKBd=q7`~0)Af?+nvoppcEk0s1Z{qm^i1X zvfcE}_wQ+>K($NWcqaQclp?+S_-T#2Q^4Q2qEW}RsTMVk?0X)1*PdhIeN(KpLxz9T z;R?coXKFJ;9O#R8*B?r6^y2@_mWydApE+H5+Q|ychrA=fj^_>VQw)>WrH)Ym00RI3 z0{{R60009309NzHr8H)qjbHR6Oxhi-Ph?hu3+f;|nV3KjJa6gc51iLf2hJAc%nIi9 z4f@bmOMgfARLo3E($BfZ?Zb6#5psr1^tX zI?*;=QWW9{#E1HmC~_%pn&}K{8OD60`G7&=N}shx$$)x9u8?ok|1ld`*gat@-aU+v zC$ONW96&Q93{dk@n*v^mWc}X=sAx8EH4Eq|h1qDBK~|aK^5O8P>nk-)o{(Gm3|2UEDF-xtY#^rtwOqTxg(2ArC-*@B85j z#U0-T@ZQz8+T;S*n(fMSyFHG9{mAeTh`dv|?E=i!fqynn*YD@}=l;NyJCkVFrJO-> zzYZ_dQ7OIl%e4Hqg=J!!Xw9)8CSTZS6~0tSI@p;J+BdhI@jftw0*jD!at%F*D*pgs zK%T!LCnYQIDl9{G>W}!u*T3W9F826 z-OBM0zk@D!xiLVA9b|dqBOF}6fJV#+?91CHBu#kKd+&6%%T>QI4e%_Jc9yDh@&XjVY;{+w zo38UT_6sp?Cx1iA4(!4IL!L>p?T$YHTHgs^!qo>m@gc;y2s7&AWP~g2efTQRbm^f8 z&MXUE9dT}`?bU~tioGU#6;S`X6$Zv&vKmU=<1A0hPpIQZcrtP2b@rK8r|NZ`*Yk+3 z!ljuO)gB5Kz%7-x$sf;LM2Zen&i?zbwGbE3F8Cdk6gjm!qL4B{srnN4G;J14C9y78 z(vCvdd?O5Sq?v)E9YUm9xOMHN6m5;=m!`7kwZ17XhQ@?wX{ryVYWD)@wAI+r4}iJN z6VIE{)!_E;0rv9aW{08g_trL2amlfo$E=G}j!|AmDeWC&?vULM7$-Ibl$x0Y%;}B? z6KN>J@h4E`Lh&D<2$_ z`X;;zV<2o!A27R)<*aWy0Tj{04`3I=f&ynAbI0qJ^e3pgo+JjpQF=Bsaj=0LE;nMd zk`I>zpCR#w!E5{0uvt}ZhSx?MVS?DdVCRJky)!Hn5;yF+0{o7xlu$W9vUd~jqWV;$ z#o7WFJ_4k;BakP@s?=EZnje*UatGF=KOYie@SiMRkc>&0rT}3bgn#DA+F?9(snsDMLv0UvZy)psFvQLffzR)VV zpO9=;6P}`)?3oR2Hg4i;Plyi3T+bvDn0PGrhNV|$2N3vR0U)x~OM6$B!knga>n4+8 z@Ykx|H`bKT$9N5zr%I<9_0ee6EOGvWI{tCxim#}s)9%^J1lnn$jy?o10H!C?qKNNS zy6&E&7Wn7D8g8UB((kx8=MNLqaUzqNloNTM?`se@EzeNCgB1$?6mIHnSO-|z=fYPP zNlz*C(cQ0HiL`jHPC?9&FbRXi)SH*Fp9T7Y6guCk`Wa__B3RtK1qCQLovIdBx7Vu> zsSr)!@G^J*He)|QBf&82fm)~D0PI~UG!b0K!ywj3HzFU1hTPzw&io%ohkQ@ z@-Mg-EUexmkk=J-^2M9otcid+gmf^5SmVImYU@axT7ot(^~&SYtoN_bx!dPN^u)stz9!M<|H_^`t6lrp zp9&F6f9tifp2QhlXe%rEvzh34Pq54CeP^^3iz8V_^|))c<=)CuF1HLrmMQ!W0z`b{ z_+30FA)oB%qE1drI(qssH&FJ4jB_)oU>bQQzuJk0u|4CrSsU;jVN-0V3hwr3XawH% zFol+^cH%vB^?D~V#?$}c=K+rTY;qp|cIW7q7k@Ru$>Q|Qd7*g?iqO&9M?(Q`scJR} z7cl!)cop{$KCfD#>#?hqG`pby4bSoheB8g%kR^NQfKBx_Vr~{tXX+cP&qMsUh9G_m z1mjM*V2HHXGc9Y6>EnaGTsjj+?1Ji6C}}!;=^TCuV}ztZ))rz?fY(Xwn4tCAhisAqm6? zL}GV5c1KD!mdH~)WReu*@Hqx)U9^0(-`CJ^Yz#`;A<$kGckWP2f!jUQQ%W(_7V%=> z456XMO}=9+x7&E*AeeCHSg06e$%)Rq)l2LC6q@fFK;S+jM_-24FFx0v%7 zGP4!Z0&@)v#=>z^J+`ui~??!!A&V6s)6Qw`Dv-#WsLG6EhtZfTTWMYjU@egA(1{>o}{1f zfb+gPR}*6r(O<{gt_*|icqyv1;gO0m2^I%BHmvD0;XB^_C&Gz>9lo6l*b|bwUgrRk zvB)@8v|4*v_SE$9^Mlitu1xw#ojP2W{KfJz$)^Kkl>tr^e#)t8ff5@;}tI)W~OeQsTWnupF@SoMI>YqI`eA(VAO~x=J77 z!$=B4Mi2SB>LlBC2xkyA2S&onFFROJ{0C0+>fii1>CHtRwRde`9TD?~bLT|ESB}@~5GuTQ7mA>;$D84Y#S8j=UI-4d8Ha`pO3n&K|yKfdEfJpjH~UF-tPP(<`}&68-t(; z%mguPqbNgLx;iF+sIP>8>F-z@M7Pdwn$T2p%D=?d%BfIG7z=X0todXuF${ zZQYLQaZR*(7kb67O6l*b03${nNt-_z=UXdJ{~o>DnooJ=^Z(zVkAIe|3Bxwe;s(an zP|X)~8vjh-6HR|Xot9BvetCtyXSrnbk<0p?m521VTBZ@V^BG>+T0W5us_@mAI7 zSkLY4F7FR)WP|w78O<4|?kj8mw6%}^%FlYlM6z@-^H1^a{PfqB(G;pj>kC*BuT@{0 z2b2T$fK~u(f%m|rzjWv_`HK~YUfm^G2X!e>uOJKdLX_1((-&}A&*&l?)SuF+Wa=+? zB#AHS7{U)0I+p546AaXqr+G8tVgPD-_eicUFf(*3#wcRqsu0I}%B;$F( z_><)jw=n!Ntf)KjSIZyKwYzaZZQ?ruC8u1RF)M!@*@Bnq9b)>UK%-ZFTDM)(g{_(6rUhGs_cpR?nC$ z$D?>ZAO6ZVwKs>9le`S5=BGjnR4*no3vwZEar0M-7rMSQv&HiL*&m>>;Lg&%SUj7I zzr(?`i1Sp<&wP1789RAmfPFa$>Q_yAchE8eARMbm3u%B1H-vMErHR>Se)RX=U;jL? zwxFnQC}}X%Si-P$IretXb011c2&lfh=HKfIyLtPfO5k%&?0T75Kgqh0wJAb?iLS4r zv^UAlb#PBb4d(O1dm^m+%_5UHbTovq&qbCd6(9|+OLOw*fxZKORCK>Z4sG)S}^dF$L4u51R z^_1!6z)haR9DJ$Yb>nYkwU-Yt*D1>Nj@ZO0G@L|Mm*x2e-vVueHe}!5_3+-m8;gi{ zMRxdo@wh^mp8uvLLt8(}(g~L`>Qcf$t^TFU)o$;sHlPAjW$PJ8rB7O;`1oGmj)FOb z2LbyTwW7P&7s2;7k(Fgyx!LEyVbrV`)mp(9M|s)K_h7O){HvCVkWCJsge? zg7GUu7WvpGUQt@&e@YVhiY|-si9GSfWMD_+Vw-$VBtyt3!|azNi)px*1O^dX8`S^A z4kT~~by?9&UAgA^N#F1vX62aV9qjo`y`s-A>cSqbNbpnce?`w@JyR44NniB?ug0io zsDs~ALZ_TZ+M>4jJjFCEF6@1bc9YFfJLbRu00RI30{{R60009300RQ2t^y&UNElVu zEw}@%E?0tDpiItts$I0b)+_$HO8$CO;wJ>YN8lQ_g%R_)ZSs^sLnUN`$ zItf=9li$)*9C1Gk{^0_wDGu~3+WM62_am`og+DYa)^?07Gbl!RTJReO*^{_U;*vGP zd|B>+k}>nilVmER7V?kC4gR!LAT4R!-70YTgvy7x|GAZ`v$dP}bmgLwVli;5Z+Z2% zIP-xiV_aWB^tLFFi?ICajp2jXiNBUEk@sx_^<W5 zg%W^6D(8~;F~J{ru}5o`(S}%|ZmEb(!2vp3?2?2Ow_ZD(psQ#*N9s(iVR5^O4|~OM zS>P^g)wYcLA!CA#YIJ}rcId0h+ykB`m*a|m5k2Vn!nP2@4=XHj;jd!9{SO%@5zZ$4 zJ!;$A%z>}vt`7Rw=^4+2tUdEgEikRQSgIdaWuH%_zH-}=8!b_;80!LrPNO)wPKep+ zCON5CIopKyT)vZM-cOmuu6Q!z1yFmE(Tmo3-t7Mlektyienqk$cVPG8e3N z6E8@)N;%#X$~K0m)9O@uEtjlr>2t^yM*~4FwtIkVvwkxs%Q2^I4`zb_iR~L^R_ey* zA$g{=91O_O@e1~9qt>W`$e^a?p*}}}q+i_I#9ROQQOr^e*L2lfRYaPoBmW0N4o38} zP6w#*8HlFY0@yZ310VyNOUN)~6aIsOX6622GJWyZD?aXxIl8s@uZGusV6XO)@HYVW zfe%(W>@pHrn4znDrZ164dc>s=V}Y_>aGi5CWS~6=MsT=3jl-=QuXky$SwrH1EGB;` z#hM*9LKrJ^8X4I6<^1P}hKgwpG{j+?K*PxxFCXuGf=`_#fykVmgsD2tJ4rCf+O4A! zy|j1CkWp8XRqOuHTLwtc{h(2nw`x=H%HV4|=zrMwHOi~WgaehyRTZS1Vw|-hFQtou z%|G>M0ph&qVu_GE?N)W;kg~Rj4Er>ioY^^Y;Ge|kr0uS*)bh@yuT#^MQ2625R^EIF z?oPM9i^;hMDq%C$o+!efk<_nAV!*W(W>l~CP_XxIY?03eEu6<{X;eM423+bDr~!O= zcM?5ufx&HSur)1S5PU9CEg#@{W+1RhuEdgOkr8i^t{@)$5T$g%)X+?MX{}5Ds8#Hi zBG>6$x5=e^tc*J&J2T!fLg1on1X=Kd1Vnq&;f>7ZCQ(6wOkS{DdC5q06>P`sYiNA5 z$!rE90?4xEI(+n1b@1ef4t)23-{-m#|2qM#Ni5?v&A9|(M747=IfP3bnk@hQljk2k z!l5c&%U%ZH2r8FdAEg6@0Txt3+|CBB>OVX_{_j)gcafVq*ZC2~A6$Qj+95(4N7^?9 z-0=CQ?|wlMnmGv|0oZ%b#>6(0>u!(FooL)Z z$hu@x`|h;fSkBs3VB12|b;_=mqkG>=*cLv2(Qw)6Iu?wwVl5qi0IeS05zC=Mh*TMA z?Xv1Iq$DvDxtq3WiqLlPhBJSiM(Ql?YUjP~%26JlvJrG-VfdbU$mB<(3=t4}F{X(qLVueY^X|d^&oet{9UH7Txs3!8>t^fOV9Z{ zwlbeRR@1+6(uAhs!Tqrke0S{GnBwj>BylX8daY42Gsx4X*rIO}RFPYM^KZM|truA_ zL8$Zuq{~D8-k)dqi1s3VhHJWZfw}zfqe6XNu!pgbQGw`_=06HND`8Ya@^P#Tf-`Y& z41A^RAN73eCODaOuEp_cv-sq=E@t8HMe_WVfb(ccE{Ulan-EP*C{1eqh=P8Lu!g`A zL@Y(Z!YO^QurFr|rQdif-QuXVd{|8^vjF=Sq2BhRmoygZ35sH){?#|XGIs3bTtI6) z*zqqB7~*sfoH%_8KF%l*svS~2;j|!CMo=n{z!(t3D;!_H22c!CmRSU;w-IN7Kmg;d zgUJN`#Om%fe%ThF#Hzc);vsp2aXH@r69(0Pm3u++SNZ?{>(z1p|M$vc%bl*0p)C># zxUFTH%Q*yLJky(R5Ygx{g$|S5eLe@r@rtYVh}9Z6IPt-vdVAwt8jU!JkO$Jy#HHEcQ%62ipz zDQ-@`G;iZ%Bq{$0=5$~7pV=sTP$9b_*V;d5tvOg(DZ_37yLZxY>a3I4qfdN*?<|$% z3X34Z9^QHQrg{XBVFU&18t{hcsx(z+7$0!;!=rX=#*J^BZ64yq*vH-Jyh=+zym;~$ zC>pUkQX^u^pmdwz`$WDdjpAR8j3_bQHQ% zq(7}sh)xQ1g1wEzZkL~1%AE4~uPZ-3gleGFY6vXiF`CAj${UDvHVlJ*A!0TO!U&KU zvFsj*3QaZm&G21(w&1;KG`b2|=nJ`k$Fk%gIq@g$@B%#g>_@rpYX@x#siqut4!2p~ zK*BLpUx!wt%Wh*N3bBUxCz~)>-@HL+X-MRce23*Tor*~W>A>Fo%e!d+3var$bx!ka zLZmhtE$dHz1b017EC+J7`6J7Co1fD8@J6w{I77sZFXby$qB%1svmuNd{IvVekE{U1 z1yDn-r-GZGIqW|E>P41;mv)RT8{%HK(5TNmKhxl!fZ&n;FPre`vUEh=31flTt~u9W ztcL%I66Ee0W@~f0n1t9(9aAoH2>zzpCvV5Pp{kjX2b=o$BuH!=IgTv+-+lIXIOAA^ zv4WxBe=~XHxj+X}SR>M*FZpTd{lkg9+ygktQa_+-dY( zp@s$HB(n{~<;9r_*oN?!n;U<}KuIN{;~Vrk~ShKB=BTjXPPs);o0ryCbpwhdeQY zQYn0Xa^cXwDdbfX0k3`%12F?_5nErU#M@8pa=akWwpk%q$jUSBE?=?3k4BX<J7 z$Wr}VG5Awy>j@~M<G1UQ9{R1xnYoTdJ5G? z%O`6>t14Qa=6v-b*I~EjAF*mVqSrUJ9u6)3wGmAYrb_CO?%?!)g!G2iOGg-(=KkQd z?w>>(z-gL0A_B}10GxR0Iwu4$Qu){Buvr-EVJ5=+H@eZmnK+B;#Y8d-$i zqW_kRK(lGD{T77(dj4;V{*_{&O#A32^QXeegkW}dYwMj@rYfgyd0`-a zbzGE~^3Sy@K8FDxVk_$@F!lXg+l;wPg9glQQ4cz1tjFseSc&jj?qD((C5f6JftY)_ z{%{KjeVESV%iUp0se!iBo4KUXeDl^nDQUnx7)eeTRaKQN$F2cC{kE?6%~eu)lo}kl zTS%%{k=dNN!=Z>6%L!GTqA~QHeHzmruQ1yC(RUyN_TrEOdvv2A2WZSQCl0AZRYk9U z4S46tUkQ;CA(i@Uzy`5?=}cBYwN7_p18&IlsXb3sh&jD5*Fk7}F6B$v0vFF!a(Lb~ zWymH^@uqzYEc8O1`;++w?jU-MasE-P9FHX$~nNSNQm`|{}nIq>mr z%CK(>bXF267HI3`K=5;RQP=&qS+{O85~H2+AMIl^+7ojN*4gzgK{{S0{P8<0vPC&I zQ!gPJ(Nn^hYhH(YsdhNZN|gunwrVt>Y{N^WitIatrEV`C1*^j!S%%t)|6JFv zxy0%D)dH5z+99bFaCxgUAn=3^v$=LYY5|4m zZpw}^)w0Rddtg9$ofiKpeLEkL{N$!}$T^f%0`IqbW!+g`CuFoC{ zEBDBdIhPtbXqOd%6_GuoP;R%Jmex9iPKBg%!KRF^mfmVL@C6mkh{UG*>{J>IGGj{d z)}AL%xay`GGtZ7_Y?u^ITDqD?pBATGB7Je9r(T2x!;v}brre*n9Wg=_ z5uQj;2yPb93jCw`{tM%^Y3rC9H_@RZT0M4*o4=Dk4mvb%LmaUEeAC+T9ysq!2KjR! zTNG3&>x^bcAy&&T5MTyA)Wc=iCJ`@JR!4Q;WDEF8z)dL35`-F5s~5b?x*IP+o5Dq0 zyjm`6h01z%wD)J3eOv#OOS6)+-M}@)@z6Ude&CdW?%$0H-#Bh^aH>7^IX4j;seatH z-5o2(%Zz+yr`L3sFk|G_Mw$ER-IxX<4n2JYDM42KtHpz0=1|}RM{Lw!l!0>wNFS|} zfOL!5Sq>iYSAyJR zdIITw*R-mONWGhCCAuSQzp@YSUA`r}55pfVKi>~$oNs&d;d^A6&Nj|-wUmY(rd?|T zUl^}^f#3*CzmZqMP%p`L%I-x-YA49|MlKVEwhW5!M>tg4QUvHA5Y!mUwF=L1niK5A z4TKrWV4d&suP3S2qpR*q?p+2r=~A`4MmYeha~Z{1J^R5zUa)##R3bz`2BqZa2FYRI z!vjS?UWXaQ!6j@99cM(iwWvKvge?o6?X%D|3LP%ryn{@+FoExV2BcWbVf~-VF+Bg1 zt?G<5&H$oLuuJ;?b73Lq#jCEyS3ai>L%=e%H2F|e>k-ip%Gz{MR{I+yx;k)^W|S^% z*0Z1duXQ~K#IU^;10{_7BQiS6D`QT!JM<}26!24hLgr|MS?-RDeq_gch4AQS%Pr{k z@=-=~P9JVUFiw(vkgLF0QQIGUt5=dOmOgPnS8Z#j;fh+zYNH*=*`nAyN%!O1&Z@J* ztP~Z)N&D3^AP7QkK@$kP^y1uY@-b|IvjidhU!g>Mt(!Q2pzm@XGtsX*c`# zMG0bpXga&L*o71A90$7Crz%})?90+6$!|xhz-I^6cc=ZVsuA!?xmpvyUM}?=2_K-y z66sVz`;aRs7ttJ$v%!$vz&3;cwf$3$lF}Is=u*|*BE3OYq~giJVU6hIOU&;XQ>6JY z#)44;of&@uh@V&TUMh0x6c%0V)zDW(gVJuG1|BG+0nJbJc=WsR|G~KnTr3j5ASN4( z9T#G@oOdOqZz-MOc8lA9FSJA%R|%o!D^o6fhGVHyNc`H0$M+QAamV?r-_O1u zikK(K%67Z%IQ(X?PIF_;b_D(dD!I2r!NXM}{p9x~shjHzG}dnb&(~@&odM#S|Ifnd zXVsxlx4e9xSnVr?vQjlsZ-D3r+5a9M^(WMDFf^84pqE6iVgXhE@R%-`ovx0jD60zb z4@e4(+YyxJU3`c0X~hshRM`2KAxz1og{eC4aWy6-)gm%7?W7&PqQF`sdoUwM#MgObxgfZF7(yBsLpwu6U0Lh(` zIH(6~R;Z(bv_m;?JI|J|%j7-SNm?ab=CKZ6J8ObfF@8fz$L#J@v82&)`+ri!L+>}C z!vJ{)3M{b^Fu5`)wH%WFJ+n z>?beclP{gdDJFBDC(^KD_bYfPGCmrd0`MatKXZwfgj@A?Ij(e7oM9&D0d%IHqhT$8+@ZVP%$&uZUbi8H=jIuo=P*Q7{E~8BU(8i;M3^ zhVkBigsSI8{J-EURCSqcjAJ0<;xEe{)>S7dxuy;(-2&CDqCg2O1)Z{fm^iDY_+nkg ztAbL=)LrE)ZzNE%p$)7R->bd|h|VqJbz$Av2&uzR7-reJ011MRJGwdYdQ^|uve4q> zqG4_9RhB(nr?DZ7iojC#;)b~x8L)VdDJHmsZ8!^%)h@Vx$EtwgNvH2ZzIlOUtT33h zfB&_X>MrnQv|Z6vzx}Bn183b+j>JFw;2WnuE3JoJ3c&ww>V9WG-~Ru{jBC<#VGPxb z=Tr){Id5iqY90^GK~w`qp4I!I4ee{f3Be`Z+Wu1?fS7>&NG?%zSHKz-Fk7^>;vE7} z3rA4NjTWYzG450K;KlRt|IUxHn%s;w))*o}r{xPY52V)SFYi`5thPt;jz&*Z?w7gC zn-p6!iHoXBQ=l!!n3g(6KY7Fa%6=SL%??x0ByIW8sw^p}_d=IO?~1*@ELZ%;TslPQ zX0CDe9>TCjoar=LuXvQEKU5w`OJ#iH&Fdz=Ox~euAhI+IB#Q_XX(RXbBrU=QeV@e~455BV+ z4tV=c!25`Y{(HXR*5sf~G83g#oqI}Ia(e30pu-MXvYo;p>%fQPZ-~JkFARrSdMZeC zTq{w)7WU$sc{K(J|2MvdPbh$bM!EW*aSBkhK+tW7TFe=VKe9;L)_1igA%pjEq^FHPv-zHl+fuUp(IC8y$ z=~4my*^;P~K43-R^xvQ(Se$_jV|V?q-6Ilv5mCq^#p++}V&#M=w~XZ%FgtH=&FD{H zv?CK(=MaU_zX<4yY(2QFd*%GN+y7q6~2rz$*l@G{Ip$Z03h}o#w>`2p1 z71f?bB?}oA(Dzz_Y2yaRAFu$sQ3}xEQDSK&^t$i1ANTbF2p^dmdKBv0)B9>=lvx`= zS^;Z4nKSW$rT0v+(7_$zC#HPkE~@(1LzB&?z{WXGzl`V=BQ`af&4pp0sm{`cL`4^h zxBvh9FfMcKnM;o^RlVdV`s`evaE*~TPU@GRExF{c%lJ4=}Wi>mea2KtMRCYWb+7g3+Qscy7Vr?6Jw6;-xCu-sek|g z0{{R601$ux00`w=y2M0O>t*M|K`*L$up|;`D`8l)8%=IE%r%Zwv0>ke5@03Svb&OK zot*xMnd)F_OEwR4y_zO?z@B<6pwu;+h@H^`ssOMmQd1qE$ zstVZW9(^S(YGmBur`>6)5_Zd*14T#0J1SDo_o^5o#G2^!2`%x2zpg#0 zv)VH7ceu6H1Regt=yY1b#}XC3%N>1*+ZNL5yopcfnnG4vmXnetG5FOf6D{~&VGRzOmnFU~+$SODCp0&HPl zC+&m4ncD<&{|@4b_w+54TvF`a@2fC){2|*aXlmw+0#yu*Op2@m$~gw_P8yija?jfE zS)drMf=om=(mMT%jt8{1Uo5Mclldg>3s8GnWM z1OEQ7{oG+Bf7eA1Ad`=Hk@zF~?ItY0=_g7?Y9|9D4Pvzd;&y^EM~|UFnGtTlt_ol_ z)%Or<0>8mrlLbz?qne^LgO+b=josM95(+$~yv0vS3iS%{9PuFP@VIEnq@q+w=zwI3 z$ah-k=~HywOEj%GUoh#yE5Uz?&4*E&xR_b6!q0@E2<#LG?!h;2cAa)~Di}mm_!#t5 zDigXC*#;a$dz>#wl86KgfG`i_yp8~G2ruOQS1T|Bbvl@pyy=Os%J9{W{U9R%HD?5e za#FLJDB|QKxp^~-eW||&E38q>6(_x!)zyr)0=>l+0MRrD3t^#+_dqk$$N@_?U6_|_ zhSq8IG3GhBiA-)YADapL91cs#aLukib1~g=ljiS-ssysxGyB%eb-A)WE}arLLVZP- zwX~76KhrY?!6pf-d>hNLcd|{`=D<|38uDC`Oxd+k7zS+f0ERFUFj(Fa7~J|xnnL~A zTy_8cK!1o%w!!(X8QC(DeYyyiCn&T)ZvcvNF3GdR1w_L2si~xp93pPmI)l*RwJIj) z!;Cah{XXj`+{JsB|0ZUM$`}2_U8_|5#m>sR=56@XT8@fe`|}TYoaV>ZI(PRdV~kU& zz9cjuC0)y}g0!cNrmAZx;ZtBozWp!p)}qAh@dWcU>GO&DfrrpqqFTx5HyO;#-_Avf zxrfve&5#8^?_>~=1bC`jl~iufdFOupxR5W&U?~02g#o}Y^>L&I8va3y)x1+9dnEWC zVtko*eodbA1x-@~dpS zsV}`gzql4g^meQiH4-8+v2-FX=mVy?#9raQ{5#Os$1>HuWj;&UbKmCyFTKZeRy$H# zZ~plYQCX`L$Xomlr*>U&_%oCVxF!5X(bbc7-Pm#S`tdzA=0ksefB%924Oabho1^!k zs7${=K{W>${CwR_Y{1Gmi0hiAMQ7hw!*Ko7@-&;HR?quR8t>fg1BUF%XT$>u;lvYt z8hc;-vF-bcM60}fTwL1y4*_*~*u#%8#g4AgI-GNhFe#c-jEJFhLO{KS#{tg#5ycKE zS5QV7OBZQ$H)s$Zt%;6Kp{kc?avTJ-|Jx?yXP;<*9{E`7RP}$p_woqVt?BlFBf5oH z%dL61;-Co-!D}7v<#Fz7hxv*ev$YSnlB9+pCt(Ds&cGVXa~B#q?g$ustP*3PWHe!f zyon%FhLaBfVC+<|@!p?|z~E&dm?BmpmL}|z7^BenZk3y1wD8&m|Hf2Y6AK5q5_OzA zVwq_V4@tb0b-2u>V;2}SxUcwoN)NX2-b#8f__8_votuImG=dE1zyA5mHfql}dJKvP zN0Sleth(>iXA==nNY4f1oDzBNZ;ePJv3K2=rlz)4 zVP*Nvsh;3j?kY~lUTlKp2UO?drJY~`!;4Jh4r7_2=(X3@3G{Rt66(MwwET}e7%jk73JDCAb=JHosd5i zll=29eDO1|r`vhqd{7BaVn7^6pOFS)!$O&r+^=j(*f%^=J0QTv-|gKo zQA32kR=_6chd=H+Ukb^yw4Raz)gPg75T_(Vnd?^o^C64<8VxeYhtq4M6|}!! zG4DF{VwO6)vzs9lZZPG|gTld~wc+tTYC&e3{>11uCP1UKj9UfiJ-l7Jw3ayBzYO*X z64dCM?@;{FNhSKSuf;b2FSRAn;;$nV{E9NyMKHPXu*=L@-N#xWdKpD>|50oe6TDU~ z=+3wMzu)NAFQ|M{;s}y%?A(h#MgOF%FB2Lne<;mv;qpCA=4fx{o;k9BPT^Fm z$J22MhzwHd(PZ)y0d&FPFa8P@mTg}y8Y4hQProJE-_$3Ws)~owA*mx&fo1kb*M8sV zIYqoIRZ>$l=9S5Jchd5Y6BwWzBI1ge@9@yCO3-`U5ru0teUig037gOH0*q^L1oO|* zY{%l=nGLAhL`DJAYGmLO0T0$hGjj`Hpi!?{A|sAmbUVcX8v^9X@Wp;nA<$_;c7D!Q zL#A5EUUwr3BhTv=lOMjD+iZXMfxvU;LTC!~n%>GyUG}vzucexiuyPmZ{>N64uBTQ@ z9#bK94L4cCxabPLBkJ3Tnwtq$t$WgfB&Y6tCO&{H+;}KmR^GBZn-sFBQXH*}SMiW%J)TIs4!ARrO5B zf~t$%|3ff1Bz}81u=6{l!PE)?BTwE--~cJG{jE3E3^i*~b0x75_jWM9R0ttbo<2jX zKR0-$X*TtMSz08u4CakSZcYmWu3ib#M)&}Z*c0=BoUApyd|f4`i1lgXJVxh7GZ9g6 z(@r~s(T!5LM0mulO9J)J6M zb{o3?)2j5vVFbbZg3ooeC;}@s(lN8Gh)4p|X&@JKP3nFG$@-dWO(C%>ZVTM3v%Kq+ z&b2K9uNM(`|7BdnZbEO~TUKl;ZGB&*EAW@Oy|qyV&!mXp!3LlqPX5h8hM^1Q%D)LM zk-xvfkWB(g;v)Yy6v9oDFdL&l35vJRG%?#q-Z0z3RD30elu?OEdJROrS!G2yXhmCh&$;acRiEm%(BKWsRjf zI0A_z(|IhOx9Y2O8^@Rj&TUwxM?mOiVEUsDUAgy!4;aIcQyEH|T-!T=D#Z_fml8ZcV0rWCbCc%VW1&F`V(1&y`^-?r6i1AZMIC4_40rTY0GRj4lXH!5t!yqRD z3yOpS{U*Zo!HZpQ^MoTo2<0?&XxAm2vbdPwuGHwxt6bvxQGqV+*7ZT>TTZK^OAFd~ zCHWg)?cQH=1LVG2_Wuj#R(&go@TVR~eLCdm?v{Mn0y=wSJqusd^N@4=kXxP3E%W%L zEUcfYS-Bn%)!|!FRSSvUY~f8uWu4U+u#%SeE(`n!Co6b`Fv1OlXNd0e7i%1jrsB@)@=gn68WsECJ|Ns9-$AWN} zI_|Dk|0^7!uHTZVP#Zr1`|rHE(6b`SJ-;bTxc zvXmg?J0c!BUOuJ&3}qFMxlD&fb8$CYQC74KWz)NH1b-0Z>3m|u9F4WQj3WKdcp5{F zxaPqIz$e-}E5|ZuV5R!pT8`PtJdr=$9vK&a_dNoF91W-8|NsAaz^ZJ5n+~~&EVwJ* z!YK-So)LLuqB*1Cyp;$FV>tI{B4%0zSKXOJp)&Lv3%yUc`H&Sm^6%+TnY~gHwgB;K zsDS|de}hH~$y^fv0gYbo5sh8?z9^||?Zv;;#;7Zc0_EaRQ`rt%tnT*@C-4NXAR;TS zkYDI0%mN!op1)dE4z7DRG?In;6@+k+^wz5F%K{8V+3lr-ve7AKrS^cPFy^1wK6u=X zqX=JeIbA!v#za)^_F++L?3Y(Xy&H30(4d2v}uP4M)UyBu0g!HbJL@uk`VVlbAnRC)_VBfM<}dLR zwtpOFX}a2=_U?xh|6r6%yG@Zzvl^RO-=$GIxQ_zhP|g%$2y%Lb=o&=~>|{WTd-u|- zZ85NvZF$T>_^8ec3sYX^?oA|~s%I}N*uek)>bOTzgiEbjmOO|<_l|-ihgcXqpK`Lh zq)+p%(F==6-hcn0oK0)^8xtlceGNzo2ntZQlXfbtkj2-O$j`J8@`{4K{Yi8b7m{g4a@oq8{x9gUzu^HmHf<#8{P%`DKl1644d4$E0v{fT2k9foHu>crkZUJXCX3INusLo}5AwV# ztyqO1yiq9IEx&EImD{IDH$H8S=)598{%OIo;3W!d-Hj=V%ILcYj4I;G z?*?ZHK{XkyqWWViZ`ml9>FPN-$F?-5N=*wymCUlQWN*gJqyq_Ub2}e!^nejFg3+Ic zOeFa3w`vQ*{ht{nDoUR%-jf(7-mrQcN(pTq)t%-qIMWD{7+xPIOt~#)%~yw(2s)S% z(gJwG^Agej=hz*)DYV@WdswLpjM!T0{&~n5g!t@jCkzP3Fu3+6x$oeqE&cq}y)l!N zQPEwvz)7`%2Z$KBbja(Mf0Tb}JO|L8k2et`az*ZZ1$`qiOz{1^xjllu<*u~;NXbKY z0z@!=kVUCS3-vy!RR6V^>TDHYn^E1P!P`_Fyf+ob(wu&2{3awwpD`d5bwEq_xesgk-P@^Vep}pG=;7J0e0t_a#)z7U7 zRq2ply3~w2S_jT-b^{3xuR@>hFag(G4{XIG17IY+j%;}D7)rg&Pu(}DX(%VXhl6Ws$-f8^t@ca0X*5w$Y97ki;4YTyZMSk(_^={De zzXq^R!>M>9z)MP9!vY;~Rug~`h=S|)i|ME0_nDM@RiRlU-ae<9YS3`GQQRrW=>5?0 zz}&>T`JBjbQvubq$p`9!+WxB~g<8zsl;{lpaZjWds^7+UxvQl$pfzGad~XIcONX1e zmMHlAGpv;=M`Up+p}{iR5@Og|qB-=#X>y52=*H*Ig4l~QLfzBiJ^w}HAY#<`%2%(^ z+vQi`HubD96z(>1v3mdgo7Qpd4cMiDOLzPag0>8%hny^TgvjS6{<}b+VIaU!;9Dj=(knDO=3fR zrk%!v_Xg6uL=ntKvqERu8vDR}oMD~7xNAHZ*^qPf^oE(wM#P4jsu)o`f&#X>S9dn? zvvx!NL(j`Qm84PM-M!NhrZ$m5B6MU5qyvEQ5D+fL_di6kUE?dIjMzjQZQP{-`CKH? zNcsY?at%|ZzsYk*zBo&Q(9R!+6yJjtosjtFngD+ss7cbvOWz=UcuZJ(mtNKBU=rGn z)28WIu_}ua%wFM4x;0O+)BUh$UtfWt7uR(=Yd|-}w+L8k4V(hVEK1B6o(3+r7+AFE zXRsJk-8e1s-u;n1NLZY08`Ibc>jkn}7PqRHR5p^wAN$CMUrG2HUA;y@T7gEF?>JSJg?8j7hK^4Q zK?|>TXF@1V6zhg(ZV0x2iHosuNj`x*W#4J|Q=V#T^^1as8 z)RtBWJi~3tgFh(my7UJVl+y{|A2D7SkzE7vJJL#K1HW%m-pZ*6bU6 zSzllP7Q3OpIeRQ5a^(*fUvd)`2vGUTrj=62lo3bJAj;#EGjDgH8Fj)NX*L-5c-Dvl zgJnj9v!#GVv4>ErvdsV4XL3?V^u@^cjIrN_PWisHLp5IF_9Wu?(>JHe7tQz!`iw1K zti5B9?_BWjJGO1xw)fb!ZO`mIwr$(mqdm55+qONwGv`*_^S{q|eXH^!E2*R^m0q2d z?*4unQi3K*4urBTXjTt~l8WdTCsMyn@9H>0l=_fLbf6@ScA) z!ERnbS}4^Hf+fDheO8*I)XOphTK%+#XDq4yL<)%&c5|!D&bhIKQC3LdlR^J-5vS;8 zH{fReWhHYU>KVN{R}h#``8KeIgb8e16Ibm|=%|>H9KE&ce4G3xn(o1T-&xyk;`vA0 zFoti+{IHf7>DRKxGW4!HY6If~Asr|18^2=mxNbOYN8?}$w8hNSp8N>*TExl4cTR$t zzaljGJT#u>v%PeM+9BE_kni$7FwS~_0-bugHlY~Ah-#|sox;qyMg4=1E60Ue1;N402 z%9BpOtzAe?K5l4l=W%||NH6HvKvxLNB^yv@S^{gmOO$8;ro}&9_tsdUcWifR_}o zmwbF?v~$4Vt%YB~bz;%3v5V4@yoNb3ELS&Yzyn7^+rCz&mBWdcPUiAKbKgvl&+H8T5nm-DWT7!x6aS9!OGLI4Y1U zG3P#VBk3UnCektjmVMJInTAG*d{LWCg&bpG9R+|Yj2gP3&dlxYX$g@Im=A{KxZbxb zQ5_*oV~dW_oUE=HkerkFrkpGu6+3(HON?RBp0${+t#^q8BE1$V$X4+BigzuDmf{f$ zpJT&TUx8t&6REnVWSfGgwayJ7=&+!H&MBAc3}%!8K1gv#RPJ4Uv@%X>#?gysK_rO6 zXZZ#z)Qhm!6#FjkPbCqsREIEHr9XJ@`BLRoJ4}Rc{^eEbyuAyC2niLo?xIbIkdj%n z9nB^qS@4<6p4yOU5XjHFK)w$u!t$rv^Dv!a7=fn|xl51)2?6-Ozq}A;+5LD@auj#z z1g~%zw2u+q3b##qfQjb+{%b5vLNXd}iSVJb6qHHt?eb5{aGO;!HH!BK@$cAQE+L(| zQ~Kf^zwBxtrf?kFBk48HiGbm?o$D@;^g_A$3jVjyr5E-`qh(b~I%;L2RRI&CoV2V{ z=1kCXxL5x|4r$@he}7BL#0XuM?{xRqJ?;ns^b61FSj=&>(9&RY%Qrv+N@7Rjcf8}o zGuhI|#T|f;5tS$_fBw|+kyG)5W;Pucxd%xa{<27n$g8SQgy9O5L4Y4D(-Jz&#`hGN zM{|IwKI&diTSWpFOC6czLEh=7<+FG2+L}wW-JRgSiI#Z^;L-i!K-e+uEF#!`>hc#cwUyL}?#D$|+ge-;3VM_ewwTsXS5wR$95Y>yc$;}5&V{KfRc2ZdX;ZSQ zl0JytYfBgDi^h&eVy-tsKXSqP4}gE0yFn0R!TV=f%|kppV?~12)L|zv15b_NSZZz0 zv8wdd5F%FxTw?p_QXRk%$bSkxq=hn06P2B@*{C3}iEFlrSTjl`q#=24cCA{BYjE>V z#1cq+gzY1e_#<-3bl5Il&zUpWC`fKufEh?6QR3-^)cUI&n!oeX#1V)(&Wmc`lk(X2 zu+GaBDUaNJ&jD8qoj5Ms+`Ot{>~DED8WIe3$*Ovv)xh|nr#6{6E5NU%m5R+m*F;hE z$C;C4GbZe1zz}b$({hOoNfEr+O{D_nbR*Wz0=oGs@ok>h0$`}Oe-^5^VZ{7c!nZ1O zc@^5lGV`o|JW<4-4h<*H^me8s;!$RBKS;A*QG~wFVjL1ilw8)G{*8M%z1=62;Nhg6 zjP9zyblz%C2m!UcD#xJ|&y9lsQWyH&x=6ez9fM9w2S zYL(B8P(Xs^#>K3>Tb%WcLaHW?0EuBHNvGNGciz6vwL;Ii0)fp4hyC{T>&pZ3VBZSO z+`E!`yla#cx7oqr-3yV}Qm9z@P|k05bTD2IE6@c+wVW*8);oDhR+TF04zQVJj+NRl zogDr%N>vL9R5_%NKd0^tPlSIogXW2pot8>p1LP-)!9cwZSPdlzYN zKUT`aiBktgz?XaHV{+6d(e5iR7(_A^<+v!ni zz%H-Awq-`mF~CKY4L9w2fgB=0_Hpf-L5y8i9CKeN5!NH!nye|Vsv{}us;Hs~7znTxk((6HW@q;BfcZPde^ zdTj0^k%A7f*Gm$qnJw>1N66P}NPqIsHCkW!2oA^}AaN8vW`{3bzJ|etVq-%f+$zyy z>tF5yRmPbxT{9MDop+((Ay^@r1bKOu5Q1@1m3uEqf2i{|o4Yo1{~OdBBQh#gV{S2L zHe3s|CHm%D#2Le1I<`zFC8@3D1gh5>b>870LAw z`e#?WsJfvi19z&{{DF#5Bi(&>%M+3jQpkww^ye9Gd!$oK&sGmN%8>o!7q8ol+uKa7Aj5q$bgYF?A)D zB3~{A2c)Dca-UFvw91I~!5fO`SKs24PZ+E55#@*kO^OVRx(E;F5m-%)*P#nm<+;NQ zp~5;BmCtE@z9^FabJdIDTU=HuZhj9;h=iX-ncgp@)uSX)+LCc@psh5f?GLxRWCZ@d zu*=R&c273RbKa=DS$9Z}l$Bf4tt;l^87D&CtamzSKtw$1EE!}`oUs{CpJR< z!D{-|fuJhS%-#r#e4Uno_JS5A(P8Y!$0}_N^j9aZp!4|Jc!wKrc1>5t%cS9pLxC(T zIn}&s1oUfp)_a>k2vX_i;h`Ne={LpcT%0hE$)9pyRAJFJ&Cl1IT9!| zBWRVzIPixc9UZc|94e9#L{%dB*UY(^P=|f7vg;T!Ks0=A2SIdaw`EQ~*47&`!7n_$ z_oCOaXiCcxa_YOWU&4js-X2f{lItaYc{>X3dz;14?&k5Z1@5a*hL?Y1TLnU9>QL-h zPQ|uZmGNEZFr6l10b1)hiN%(`V^F{%`Y8-`VO&$g_l}gJ>SikGYK!Wwb9H2-QQGo% zj!XSl>M-o=a8=oaDCOr17wNPF`-g#;^ZnQk7JZ%De`~5Yp4VX2-$!K&h4J_~SN1NG zyj-n*TOoG!dO?R7&h5&^NGA%3A#soG7l{W~SD&gHK>`4~?wJ-UN#_nz1JBrWRa#&< zDlc5I-?hra@z^mDVlwd6%P^S)*!qIhcNL;!Im}>@rH=5(9iQhsdM?Vq8_0joStDQc zYu>QL&NO9Rl|HT?&C`(rA)gya(0iG-*#oK&UKTW{+7nGd(5|y=Qci<`NNPJ=877rP z(~~k>Tf}aH+YXI{%hQ~S&@c@Ox2l%#RH2RX=i+ws*nQ@k^?A6b^bHze(&2ChUu`h( zs9@k)IKmq~)<)Bggati4L|-8V9uP1Kl*QGOSd+Wuv<9=6fMK)0@UDr#%zAaLSu*!> zLxtjPAOUHq#b{f?ddStc%$UEr?N3+)2Vtcp+Dg3|s zbSfkuAh6X2>K?q~h9K7eUDE`je)#{KWdDiG{m}RR&xQ*3{~7!oMY#R%7~S%};~!r8 z|6Kfk?(+Z34(-dr!KuXhhKBW`H}|KGgk35UOx9_t)dQql_O6>OJ=NOO%d9}xyWHo% zFJX(N2D7v8i z+I~*j$P4bc-(0a`x~8lAsmSPFU_!b|!msZ+Q3{X0#7-Z-CowVN^qbG=mEm;E2)rrL z6k!Vh-}t+Vy^ljV1lH&O4wsL@peqbEW^RT;?gXT~eT1w1ADVT#0fl(J$n$L~k;C?#bILy7W*z zPwwP|Jc#4|D|JlaH}s@-wUKBca- zD>04jZRu}9qbRmu3=X6(6(zU&JPHKoYq^;2BZUbNMp{#U9#(GKdRq}@q`ds(D9o-N zU3OLsaw0uW3Y7z4#3stNX5Q|#>d^d%=CO;P-4 zmdS`b6^hYn6oiK8Uwy!^Uo4{T-Tr|#l;IblYC@LwGDbg4AqQ-PbQlLVi3b(0Dh+~sc`lP(s6~1wuI`r;%tEjxTNv_dEp>Fd+7$-tKA(2_4hun zoXh6(e4XH=GMd(A4IYFtKq6))b)tZpj~SlT()WyTx(~L2y8eOkuIv!^T#*TC0z1pr%DU}ME1XEtTeHchCVGgQ(po?hkAV_>otmfb zV{F&TIM<15xt`uqeO1)WHPtWFl`)P+e}wK~+xhsq(=qgHcL@&LH?(_zXfK3$Qa#%g zUi|)qkFUTUC=eWayl1o;kWi$}KTei0kP%xChu#9Z6PGlm^I!%W+f&{BT?XB;GFWi{ z4{PQ!ZzTk+dL9w7ZV?D|T5q}iIzAjZxk3y6I{;%zT>24abFGebF9(ai$)p1lnhxhY z2Ac|4T| zTMDG@U5kgva(1kQ@mH|WKy6w|^h z7ovVK$HD6eR!P(SLA&70maK4qBbNI5kv6Pe=1}WjII%OlE6hIN=4o%sb%THp6a3@z ztRXO-QvfrnV<0<6KY*~g>_U+be)o)6`sa5Rs^=)A$M&kN05gWG?NJ4nwXE+*C@z)K z#tBWStpB0Iy-ykkP3qaF*ERM$mXKa}CB$A@HY9>e*Vn$f z*Mc$kdT2!%bKn5=wXEvi&++qQUK=YL$K+Kk?w}zVmibgBVgQjHDD+F2M;Z3tb=d3l ze`YXfNOK+HW;QwCd*kTE5H;q~iH`h674W2SVuoTPHxgR>t$GAZET^48^k5ub(SY># z+1Ggopk!#VLS~Le14=wd4HJ`0u)-CR{Vl%w)jn%im0U{d%3k73SJu)kZA?}q;Mt>y z2OE!JYQ#+Xx@-R@ag2mQ@KjT>c-$ik)&mT^EmZh%zRe85 zP(k$1FiA|m9ZM(+{YzIcQMZ1&zab6-%iqnQ7`_b8l4^xq!aJ)5+$`;_?rfCp@!?W? zx+t+QX4=>Zf#k8nOzga={zajIu8<>{wXxI=|8rXtGrCO~Es%pJc(z!9wJ#;AdK4j5 zhg1Ch_KK@Gl`7D`u4rYkSuArFe&>_DuO=$X$&f`3+cs>o`SH34G;;A*aLt=DTC7!x zjcaXCB(B%EDxKnvm7S#V9^eKzji@~^YsD)gD#A|W)`jGa5n!5~B@^^|@B_w*P+^H4 z#1oYT9v4qx6YT~Ub(guO@;nP*Iq7V+V}K&!$5c6pdq$jE7Yc!l(=(&}3@6K)R*y+? zu63OyMrRiV>Nv%`#72ojY2G3e?C|#5}4ojpl-^p&CywkN-===Z8RQV;1&>A@kcZnh7{Q}OBn3sC5qb9W4^)q5ptnXAR7!z zZu%cYpy!8c!s4R2eeXy>z2cER5!d71?epb&=c?(M(>{3ysk{qe1x@Er%C+OP{XYgv z_7769*_NjL9$4++-a1H2W6hgDq9dBtbf}wZ4MdepB>yPlRvi4TvH{I70N})?MQbYL zrzN@D5086ljiv>ct#s{1E8aQqy@Ao><)Gfat-~j&Ivbx)6U8CK7DC)bO2!-72SqR4 zMc+j?$l_$|Jb#Yw3+~INL*8EYE2=5YW|?$WBC_a$trImxqcmy|q-YKi4b!H{>?y9n zJh@3bS_#_%KO)t*cIp#c&Uu~Ln}=LcMdelpjK%U+a*&v3f*lT$+0+ z->-+11y0>dFWL+7PcQ@&PSL|`VKAaGoFUxqa0qTJAA0a^#0lhH^>u+3>(kmzr|f0m|s5UDc!rV8H_EuR0&yn$UmPr zwP(EC>BO3p`ZwfdMFWmJc2@9(D1MUlPyTDQs<98B+_1*!nY`d0gzH8HxU%#|ZgOp% z9yYR&&_ue6h4&=z{5t^N%HZw_(-m6+5_slZ%n})+p^M}?7-1~nX_!4P)L{JWR!iIm zUCc99wr!lN;5Am>iyZSr+?fv#v7FN#B4agwBVu`!rG4B+Z@>U1rD!kd)f{pu^y*_Lwm!$%?% zi_>9%$}Av`Kb-hjlAEk}Z~tS_=CPv%e#_21v|rL=&0~p<-1NZUb0g>~HQYqF>DS!^ z!3S`a-SM`uwFq~Vc~4dQ=O3V1l6sohPLDi3XV7*($I9hh`M4$>6KGu~2z?-M3yuV( z)mwY7n!Xyumfo8^kH67EGo2< zDYA+Xjx_sxXC~C#WpKRv;K8GN5fzB*pxM2Rj{%Drqi3E4%e6}_S1T-( zV=R|+_He=tl7gl~kj%e{daJa8VU?WashxNTQ72H&0U;-;+oRM@&jG3f`JmZRlf!OM z0Od#eS3A*zS=7bS9FTdM*IVjC5S>xKXN6@RcPIq zOfkF>LnqL8tJ4qf)EN^_Q~?=B`axP}BsDoHj^}KZs=~)DvdhS!pgE4iPE}Fxxq13v zOrtD6$)g<7kx$txYkX5;mNZqX-9?X4XP^@GSk?uK`BxAy{>O9$A(Gj^6T-O^8$K|F zRhw2>-+~`76rM(PfJvD(Ov98mA#TI>)&00!*4(!BA~cGt#il#5xl^{ulYjDzKG45d zOjRjc&{1C$!ivJbc7})Dx_?Ydnbm-hOkm<541!v+Vm+48pkx#3cOnaPUXJ8c%>|2=-t#^vFXC#n%d|JW-B_os6P z>HHdC_4(;uy3pzJ!%znRV(qG+VH-f;t53U|ao0nPo}341hRs~z47_ervl}*K!P=p3 zURt+yw7ZuXri#!zG(!^_$2CH^Wy=uHY?A8W&$+}XG}~Y_l>MCb;VClG(nLQyOjSI9 z;v~FUt!DhsMQ77fNP`>2mVM1u>C3Fr^=y+M>7c8Dc5{z?UVl2C+~Z@ft`bM3i+cZ4 ziBiD`LX%b(?a^lq#|hVy@lSKRT9;7Vs-U|{S@B?P%bilirdu~dIk)ergE;+l$S=zA zJ#=!++n|Zgf{@rE(l={|nGm|+a75^W{N!s|Ehhr`Fs(H}gA-E5h2fRyAY2Vh0mzFV z?Vv~fGZ*^VTlJ*PHjfPS9%+L}equQBuP`Xs#b?GZp)A(ME|;zwe#2%u>bbl*b`O;Y z9U1dgb}SA{2dD^8^uDkm!d<|*Cei{1m1p3>Q$3h`PH|!u)hI{8gBxPQZAlkWZ}Rf{ zeY&4#%+V!EDV{bWypEXmr{I`v!-arF^U=iVGNJO1ztmvh``rXDw#z1bit2oQ9~aqM z4~(KQgzIO+nMQOLYK~>D4nn(W#{I(k5+ALQU9+mNhc!Yp{z*jAI6i>RwogfMOHb{M zEV5!Jlix^O07!<2L|A0X-9J@3WoHt8tq1bY+1g2~{}PKztM*n-?VKLx^2|u^!p+9$ zlH+fQU1Ao49r0^oPhx`LeF4Qz90NRqP_S;X@5Xbx7@i&A{~ZVXpN;cL{&EHqnRKBy zv|L~3X^*u7OdaizchT{vqYuD?Vr~EaQ=aLLmjc~yc`%az4NCJa`{li zEaMeUjahyV<@?#fU~3=mUucKq#fe7FUBp;qApDPXh#;^j*VCtV_5}fo-tQ@7MsTg% z2!B51NiTTD*B`J6*h+MaLlh-3`~n8H++>(IA;EVEw1 zZ*D$F44`h_1CBx_40UP{o^GVO2NqU*3zbUBa|gI$(8lWF95OT)4~y-#!=ru{0bho> z=I5H?9QBZWb0$F}y7)kW073gz%In3*jNqiU@P>cB#L*jPOpf;VNI~thZ&ZN%0SnAh zl=n?YGc9I&yI@kJAV;QH`mFbjOH_99w&!N8-UW$>R|0kWFb?UwRbJCWSwyk zw1{VSltMYq&^QwA2u)tm(#z=C472|IlZDl``v+oDmDpi7`)&T>z2h#!T-fIXuGrS`La3LuIYQcq;oQ`!vtHq+!@u-1}p@9WPyrl zdeohxD*Dv1inVw5u&rr-idt&O?scTwByO@(5EwWkz}m;0>;vLgooXBx7s=$7gt3;y zH-+pE`KjzihQziiS7&G>D#Tj&^k!E%bfaanV`2TR0r%IUZ0oxkw?xiCv49yv*3M>o z`uzrVljRQIA83X9&&@}Yd%j4rWe7i{ z^HlLU1P|fRc}4ADA<9Npz}dKYH&^uZwQ?|2sI z(-SizJH7FeADuJ`rlS%VhU34mp^m~%pIDEYDO}Zi6mv+gAy8(h^tExGs!i$=AG+6{ zFfGaDOj**8jjE#6PN+DOv|SMP%TPUwG%%rf8&MStsF3a^G91$Q2~P~>Ei)d&>a9ww z6bsZ21ise@HTgbgXO~AH5q~<(n#xRItbl);4uRHk^)R{#Nuqi`5#G@dLo~$zP`>OVG?ZxPqrIBh z%5FQh!}C>eiCFq>!9%DtuNKJ1-JX2}L~AD00u@UoG&7TOh%}RQQ{0)>^@E9cqkixL zUfeQ_ODi9&W*=s!qd^v6*mQTdvmW8uo6C2HAZ_&wL-(zckZPPgJMLlH=_h7 zixNc5X-cwGBH^;hs%Bo)+B&Hx-}wYY&ZHr#6*~JNjnf42;Y0`av|p8w;W&b&>6uS+ zu%VPMVd%;XywpaX0ZLmgA&A@^j|BigEx>2=9w1vOc;{b&mr7nhbB6}Wwc#3l6nL$m zYAZwoZ1`)(-VhmP3DYYKPoR@9%T_P#zz`YY!1R&hs#ksUPsffK#wHE5yn)A}=X zIR713CM#%PJk!zK-&z(KD0A{}uW{sWPeX3y9)II((J(-u$ycU_KTKUQacz zU;8z^B&CYk<9C|U7&3JXf`JPUpEpZK$1xh7GX#hs zT5J2CN=v_OY~n04>m@bxf%ZDMJFp5wVr~b$rj;ZnBKZ#cFb!Ic{Z^DIIBVM~2t!Ov zX_5#Eg{>KH4K#Ze032R; zg3VNJWH^p;4nSDnX?EE&L2m3kK{i_Q;@qjhG;*8noa}J9kkLEdilp8PwOGDmDOaQM z2Z;OQo}GZ@jv)-jJDCp4AYZH*7_cXK9tyi)x0+E_WOr((Y=!cm7`Q(t6(_p|yhOM_ z?;q4gBkXg59lCb{_|s?*U$l5q|1>Imu#C5Sz-+K{!M5G$xrUrfSD4!a!_&p)*S`&VbCz^D&qX0qbmXAf?$vC&x?0 zriQGQ?NIz>hL+vjFe>01K@?V3er|Z0x4_BW5jpa&AOtr6kY1$iX)D2v5#Qiu7t62s zGgeoKseg`7DC)*#sP`GD%G6b1O3Ub2gXu(Jyv;H|K^Rkkk@$sz5H`DSCk98Mt3?t8 z|0zOOXhyC^u*I&WT8m_hl=EryFXc2}9~nz@d0M}t%>>!R0~;`J*l>`oxCXurB@?8~ zxWgr_RQT-3ui=nxZoLmMc5Q%w$Rqvxh*p( z8GX2km?ZoQS-qzUF$A5*&~6V$qJKtCDZ_0SX5-&8=1|fiNx<(HRS!`3 z#rj}Y`HM4Iig54p@`99g!k0P8aH?5WF37*sI@-BxkI!SBsg00k_8BA45c9_T=5Zo2 z>Fd^S8LgcqecS@^1h%ABCArDyPx%sX5!bE9i~ONdG|85j!lntNQDxVff9Tk>^Q5C^ za%&gz#W2lIrc~*1YKo61u0r=>4eY-O5bdWZe%tO9rE+s(`Y7|!0zg7lj3jf*{r(aW zH+*Y>-&ozlkt>O;Sb^WqC%FR_ieBi8zGP2tK5{8utze`1L7PwHttbEZn?n-o1(GwK z*WldxDhye#6snLaoz23fcVzx8e5}o0)>^~!huNC! zA$|^qVryJCpdfOms-FY-?1yHk`vpUD2FC!hj6MnLaNq%g8a}U1K4UFsfhkZ33HE#h zGysS}qqdC_2#m*%zOc*2j-D&Iu1g{fwuM|8%8mWKc5m*UyY9}Hl0fqgq#CU=Tw?Zq zFh4Q&Y;JrcU9-@bmi&hF3-r(On>UZH#@Qm_j|l6dYB+tF+`>v(?ZLV@fV6CNB?3VW zGlY>`d*P-oNh&uXo`axu+~Uu^$pZcyr;*!4VFTh1)nO9#jsnP#}n_#M)}wYm3wkb(yO}N$E=0 zaCGtU%*;5M(E_Snd7{WdL;eyD2N=p3@8Y9J32<(dBts?$_@Y{6|H+`;GyEvunvw8m!QmMjA%ZHF)R3o9c%Cq3UF$le(!-57XMjQ0Aa^ch=7ZI z)9+$PMBU&U>&=S+Qa#wgz5|p27OBZpL0KR7w+(QWt_^J%60E2JT~!Qz`QF0)cqlm! zcOk$2&Tk>Ah-5xVjp!cidZN}SjZmUa_IitL%5nB85$%(9hDjuocRSeb z$Y!r*R@SkumFTeAY1LV!16!PUoKYwiJU+B;1Vw7W#|!HUQb-B7kh<(qd8koHOG6DM z;!2^)5C|u`fyA%hbb)WX=Yk`opw3)&TvT;IMn|b!D;S#{*QW(3(ch>&Cv$1h zROTAerY8VtJZNM~poe-L@9xz6YK86K@TzU9stqAE%k9w(oTESgu)=opE+5euB%UD^ z0nBmPosFk4Y4G=qWyY6Ufg>A!6TE%mG*f76ly7jSRrcBu$< zVDA)^n1vYreIJlp)$}idIW0dc#E%$WB2b)6Mic>cC}9-a!O(&9WD=Es63LDfmELI@ zc``)&4XM%3NSqb-MyQ^mIL7gkQ8U}ZOp&LGU$0t@l$5|+bP{s!(ZTJ&lVh&@ciFnP zD2x$gMRy#?OKyQhx|RzX(Tun8PEGR zCiJj+9x&QV{dbUN^NZH?vImwK4MocV2vSa*8GSvAG-{4$@8e8T=GwPCzQo@L5`T^7 zw!H1)^c=omB+`Es{a%n}gJw0A27tRLaz46Q24(p#jZTTrkOFUgn(bm&s-#8H`wsi+ z)>2WjOHMev-M9XtA~dFi{Qnp-IJSfgRLjdt+I#6uqM1s8*O(D4o_Ec3MpoMrS9}p5 zIc6IW&DF(Q$gw*)qYD)L1}!`{Hhga3_Mtoq__hjrJ}e9Z^oosTY@~aO4~R*+06*mQ zYJ^XZ==*3e%t2j&!$o4@XB23O+C8}patS~I*UY}S<(J`B9v#6nLO?VWRtxd$wu||! zOycr4UtzHKsRVN~^^CK7+ZOMLy)SN%y}g*~c`Z;PYC}x^Hp9aUKtfla_fI2oL+I$%eT&-C;+e=qAxti#BJ-MVoDUz5dI}?P%=$5YB|OpWF%DP_fCDKqLO62H#8%Y6LUHJU)}#FBG_!sh=O*4I z`)15zV<;;(2v>I|83A8(UMXBm5IK-6rj{miO*+xT`uYTLd%3@** zCQQxeZVT{6d1lXmoloITw}|PonX_)H-YgYoRYIDBl9gBfgQ+7xIrTXN9!Z<4{Q{dJ zKbrg$*}BfDBwO;~B&X~gbyC?}d+MKIeOhq}kEYh@-0dUuFdzzdyk#7TxjJ`rb{!4m zECnkyN5}i%cO7HMdXPu3z$mB=NvJ+1^dCzHg3W@Wq~Y)w-?9B+eY z#%Kn+s#h6C-rCx*CbGmwNI|A!|27a<%$8c}GT9cWE!DE$HL4hLA=1*#h~X60ac1s= z4x;-)pG~VYadigLm&(VvX?|S}<8s2zaGf4l?T|-J7_u;77^VTYnn8@y{Z%u=$%VE< zMEIxiVs+83c;9Mo&6}_?l=kJc$A?vc8)RXhQnO}v52}7|K+1xlR|la`QEdl|jYCYI zavrT#vspww3l7emBv8Ej@W~3^7KrfeeA1`3Q-rbV(f*=J3^(S1JgLb!FDI3CcBAy4 z*&d-??D^3MKmW#)GGED4V)+C% z%UK7>ivxc=)}$1^r70tum60UiW24fpg!@_R$q{V!`@y;B;^&&1PpeBC|4Ck@e+82p z2CV5RWc?v;kRMMI)uD`U(^0JD>YKma)W3%tfZhMaph!ygWV=myz0^}mM-R*i406B2|0uRPpLL(lk5V%*R!{QajGZ2$ zR2ofedN=SP!T~q1bRj59*e88roe$4QJcB*-@_GH7nlX~& z+8WIzZFW(+9xiq4vzL}UHd(Q6o&@+Q@eSid*a3c@zb~iE2yIu`&5UV-gTSUp0DR-HRaRBTc zr~fOZAv^{Dp!V_>S%jIHI*jtJzjul_EQp|4-fiYvAePM9TD+4C9vIwO(9w&etdiNn zVW+{A$@`GzXQruF{1J9+9e=LKCgf_7QIK*;cu$=A%QP8Oyv+&!x?3mlWru1RY3HVg z~d6Q;EBzUyQ-a3@R9(h{9N zp|8gA`pgQ!%rP*A*rH4$jUn$Q^4W0-F(x@9@4N}$!Z$EJ%NmzN>I* zDM_l2x(D7cRT;V`-kp?Y@Ce5ltr@6}2>mQSIC!*X(~n_S-F>VuF0? z245}1wXE$0+3q*i5NwhLaycO$Jh*BWE70Q044Al_3PX53&)P^A;W0j@s5eR8_F9!O zk z=#h1vAq%;xYhyNn-48NF&yK2CN~!;d;LgPiG4~_+{cbwO-KJ1%tJpZ@JsXh|HvOaH zSWrQ55XhHu&HBm}YAc#r5!o7vv$tg1N8%n9{!VTwyLWw|E|!2aWjf7AW)~>m9>=Mx zX7rYqVEE67;(XJYNvo{AD*PKscA!IbZ^@M@u;gr9dj%*xBSH^-Fd+CPfttdsZlvAUQ7sXfaN(H{ zCe%Pga7vQbgeNIF#pz?}Z#~KCw+GU5Fu-&nbi3Q7Uxm>xK?%BCMiS&0sG!*T!a=Q; zqY}Nc{q=Y_(Z+z@{FO9O`fg!6zG@te3D@5jE|6LG}<)8w$k|>Ulj& zQ7rBw{+H+GPy^xV=?0U9+OB4jO>!kN#@T4!61%Jo0n+(HST<-TN?Rbj>^_8NzIla{ zAnjK&iM^QmMlAO(!0kz}JaPLM2lT8n5 zdt;_tyxu>&41%<0ZgV$-@rSSUF8!mCAm>>0DiW(Cjyc8V;V^f1&0UzV{F}=0 zfwDszM4_&69a!|J?phnI#}yyzv%&+T$PV-||3`UYqm0dXh!&m*191a6IMlIO8jlGm zRR0|ZEEDZ?!F!D}uJiP`5Mue8czYQ+49qHE+m=1yehB_Ylj}SJEl$qpT6(+QFUqC~ zhnUkcO?~KkgTQJMVd-JHwtZlQx!b6cCZ? zumFDvwN4F4%oI>*dW%ADdpQm1>2)Keh4g6=V=6#cp_lC{s z2wa~xbttHJh4&a4rMyWMG&OOuU)HNIGTlN-99Hdq!gt;FCpo*ZIMKB(6%ns4($yzS z%yar*Ql1XdV0>Boguue*IPW(wU4RjKtcMmEhzO}%(>P$6Wb#LZbgo?J=sL{;b>gUW zzn`szk@=Xghb3I~`D~&*or60oJ6M6N7d#1>sUmn&(@fB6<Qw^km$*;vpcx#+Xrsb_u~VHQhhNbDQ4YEgBPEx&oRGo*Jbmcz>awiD|E<>m1^Sd6g4j`Wf6XS_umTm2i&hGXC#Ls_p#&YbP)lOA zLe>$*wHb!f^W}{jsoif8*QXA~5-@l@r0I@!j;f1~ZukCf^fg%-3XSq^>E@xL%j>Vx z%0HXmb?O=d1ta_pdKF`zc6~QkZ*OFOfusk2ez-srU9Rju9Y>FTg*!7o*O;UPxQshB zw{_lR{#r422D1jH8p;0aPL@NL^@vzZAzgpIg>G6D_<<2P%T_wk*Rs|{AqeSa>Vwme zZ^Vv)kVWJzl3Phl^3R3$O~$5@8px^CHKLi+IU6P*M|`#4sO&Yw@n4cLlr9MHN7@Xx z&6CpV)2NhffJUSWar)@z4|glQBCu6d355ZeB8d&FWrYr6{8)aZ^Y z9`0u8hfpo+hGDVL#*aY(d} z+^>;kv6&{8?2<#>@V|c%XTKZHUZ!I<32rVV3Y;FFe7vzc(3{h=oZ3yU)CSjWz#{IuCNn3L2q z#Z`6v6HcS1TneO`?Qp6MUWIkWWkPF(@Kn}i*&_qF_;yZ_rJ{fgfUH{kq;5>ZvY zf(l3)b-v-?MbAdianD=8)6b96N5`kr@w)@hV9GY)M|ck{n7TM&^(uF0q z({`t&Y#S+YGUGmFLnO!jHQqARVv?%<)mju#ihT~<`KUT|f3w6T^3OdfRYzGYCP0)| zK&NtV7U@$@o2j{HWPoIS#D>7!jxv|dA)oVitN2&QZ40}gF6HIBZa-j$Q`|AgHM8T0 z5z9Sg!cXEzy$Ts>&q!~%65Sym)YpFp5%qrbQ&@{;!(2}L2|f33<6MM;oneQ0{8e~X zH}#pIU}e&FLDN|pCM&ndPFIs5i6Q#aNv{L#}f#ce_ESPd6^&smQS4TQ>dzf7rB zu~Ga1Ws$0Fkc!$i)w(wj0~SUiNgvkbr@J{4u8A|Q#O6WHv`hBhW3c1Yb=wiS98)Wz z@{GLBcb&k$J+!4fWXfM&j^l0`klK~hX#R>#07Ac#W;q2q$E4%pZY6r}uRX0_`Jjxg zEUN=&JohM6m@=wHh%TnkGyt5Lnl?k^j^1WDX}}pwlrZ|ooU`NOo=5L+@qls)YN3|s zf{RW;lUf+y=c>1bc?@9J-WM~}79N|{y5WxgEEMP7dS%C3rY;A`? z*DfTpglUoOjsvj9lx1bF5dpm521*6AaGBY?nnnCm6eI9VS-$W(IMa;oihYnK#n0)6 zc#nLJyQN2zNF++)HO!#XXb~#+NtW9=4Jd?WGuzDC!f4Xb+e9>YfP-{nwW)$qy`$yC zS4Hz2ok8qdh5@V<4D&iuW@k(9wyI z!2HRmiywq)Y2iX6m?+wCJ&>>;)q`I!MIm73HhCZXT`#(cs#K1}F71|<1a zGESFgpIqY59EOUZ1@Xt%3({@o!kkUCskQOY8vz@<_~3|4^e9#w8o%wlWCBG+5bkKM z0wm#-?dyNb5fC&l0sS9R-0l?^@{wD)9c?%pWDt?>p;1-~8kPO8Z8;iE#@9LLia1Jz zc%w*!xdamimUoxP^#*fO|0`F&zE~P?!UgQF*oMv}C%u0tA2AOQm zbNMg)GwJ`j(FuTD_+?QwE{d34dmn&qWRJdxsl%Z=NxdF#=DBr|^`c`Zsw&rsu63Xs zXbr>rUYeh-m$<_^A$OK%H15ZAIO;`8b;am%h*!InKAEnj04n`5i$(=g_J9jQ&noJ55fMLwB^R0Kc-G>l5t%c#q;63{05L*CPFVkNU3tKS#e`OkSW4k?aO`1auae?# zByjxtDlG{Aj6#(e{&Ean?9Cqi!cb88=eKEnN}#dGg;RrN0-GZf;N;ky6yY}$tO=?x zSwaBl6DZ!z`$1mt#w4s%ixgz%cyJ)snbYHaVlGE3HE=!KJUcjWn;2o@U>E-`)k>v) z;hI83QxU4-rayn~O%iMR>$R1W0dUb)Xh;jmpI8{IvU9nho0Z|&GNTh0L;cZo8l|J0 zqIE-P$Ns$O-`?NK;oksZroxWX8C?zvsKFK*xSQU=-N5CpKeVLY(`B74i)GlrR+yGH zuWq05DO-4pv+>##!q51+EXqzO^7=)4T=DZ`;?0svPvE0L7s*HQhX7*bsBX1^J6w@z4j@6hn4R`xJk!u1K3DXhP+4_A zuTS|adMZo^uM$IxaRWPTrKq=F6jroCl4RoCi15ioMkvv{lTq1daiNhpJXy;@6b`BR z-&ZO_204xUO(*t@S}FipHSaoYO~^k$Qy*HPf5q`5^#TS&>kK&z)fje zfUKmdF8m@+0FHnzH5l@GQem`Ki>PL7xR!P-BsbJ1rz>k{n>pYkTj}9>DxooiqQ;&B z>OcQfvBfi*m9fHZ`p2H8p42#R2FpQ_>qr>r{*m`W+p)?6h0Vr^;jh3R9bnw%2VwcT zr&a|v{@jqbL2M$hH!<8$@{!}?X{Z3kjqT4;NJ=u_b0rXr%Z*5Z1JP{{9j`Lv_xVx9 zIXibI1#-Zx-?_4&cojFL@+_(*OVR_P?oBLW%FP@QY(`V%i|GM7O3?<#G#mT)4K~zh z?kw1U-=TphiS=A>l$fVjQh>=>`F(LBQsG1QYs|ZPMVQ9hsaLm;vJ{a?eF&*!qqYy< zf~5MJGwl1iJKk_(m>-2Qy_*r(^Xr_cDgu930m0$7#n@f*wDJ{K9rU~H{h&(Djj0)r zt2&3EZLOCF1ecZWetM>m=V~ZJn3xHnrJbW%#+iifjHu$4yT;&OlD2hY+L90>>W+B? z5Zj2yc>HHfL4i0{kQz7FJNE-L!kFNFu0v&vAra%W^)u;yp|#u<})_wY3ALCsJPxxRDl*vq=OKENIUFi_Db{sNogxI>943>6BM66iM7fXwF;hIXkgDynhYdb^YBn zVjZr(Ur;q;)jFWX*mzfF@pNqe{vTUE3&`=FJ`J!7w}_GKjIjz<1A(y1C6HWt`N$(3 zo+<6J3;(%KP`3O*9$5?nf%)VT7Hv%%3#lrUY|2RD8zpkJF?uy6tVozin_?)OP;;jQ)ZN3{3YmoRzZ*_QxB%#RU_iommEKWGn4J9%F{k8op zM+H8EGmMG6RrIZ9L{B5WopSKo%Fb70)ICEI>(0ad*iLG#9D%-WFo|Rg=NTtXl>2W+ z)In;E6`d}Zi+yqJenZ-(fFo(djxagcv!rokwhM1%M|w1x-K6+EEV;XQRSPjcW1^3* z)r+5PfaKk?dFdxvc_va$_04nzCNlX$XppoPBZF3GpgV-20cx`AuP5fwkO>v0focco z>n}l5v3fA$>RO;0tQ@ta!py|D8;Q^NusH?Ec_(Cb94X|Tp0}Igr@2`ga16g|;h1Q@ zY*9W=;z`qO>kg87a=JZEfbO#$uD?%6BkB$OVK{&w<(9mmDe>!&bD9bRNDu-UC=`*& zJmhDjwi*PkW218UQ3n4CiBBN!FS;8wU&B+6yPd!E{y6z-5{lVf!rgJzMXJZDc`3@{ zgFP#>NXHY`*w5`LRZqoZQL6Bshfek9@fahTzKbImJ+`rmD`18`wJ&|1jxILd9>EhJ zF!%k4;dplsom=QhdmCBrIx;tlTLmLX;|D&kd{X`)4UO@RnSlIf)pFD5*td`j^hI?3 zZ?R#c#U}mOrsbX6jS}!^CB3SXHw1{O)^)P0@a)uB#w8v{fUMv>76j1%icAEaj04F zJIfB*pa^=rn&3WebL?(2e9<{BRjU|fX8kmSr(VN<4tkdDdP&^n#ce5xcE9a9)0#l| zQf7?YT_VuSGDLfCwrrcE*G_I#@zkZ`ai+>RS&XOUr0a3$&@simt`KhdYwMQx0E&+t?Rn#7lI<*yf8FhPl%eG2&Qf7qMTEcNYebT~47VAhR zB%$IK5yfIfhiP!{A3F@UwNhp72jdRMP*KQ+e5_fta+HL%ik!|DZJiD za47Kn)aC95CMO+kw91_k>={$_GEf}HOZhSFZT?V1&BJT4Aj3-1xs=0}0dAj-1PczE z<7jpvSVyS~<+ouHEmZ!Myl95E0r-81D+2<_*%DMl!7l=iWf9ChWSiz!Ykk@Uz zN5NHYu-0i?iX0tSY~yQ5O~~*jAx2?uA7K)MR6qj_`;Q1P?5?3UY(CS+3zV;j-3z{j zpnKrtzN1`~*Ytpk6Aof;<_B0tFZrAng)|yg03XjC8j^yCG#m!*ziL&cQP{DC4Rna) zwdomr6ZYHG(8Vr{wr=PaJ3}9GvN{j#4L#~VGs31EnB#q*M!M<9XNyS=Q-`+V-zk@f z$~^wu9M%y1_#simes^F;J%3auW$8S1%x(o!Tt^pmtM&qI$=byGIoYE!1g8JyG6wN;b;U6lhwITXEpC-}}hYx4V z6|C0|I{{EG+u@yiro@8{yonTX;RLX?it4pU7%h!!ivdO-+tY&zVG}g$<_x!lX)Anr zs77MHtfWHJm|XOC>7mGRFMhNu6(;ZD=3_V76o)CX>2FDd|L0KwiQD#5rDqAf5dhsa zm-;~o_<8?MGwK(jnM;ow?VY;XlB94sgPE$6T0*D$*UXiGHhhuPVB`zbJrE%1{42~z zZ`ykHFRP$X7FHl?9h6-Ef$>ciUg=z4nhQ z{?u;uahBw7!^0ahKRjOM1g43;9`X~BWx~+fqhwlJ{dGnp;(i1Rp4O)A>-BP?hFH@| zT+h1FlMrDxCM5rz(OIfoDJuxrADaB2{;FfV6qrB(zad2p__c-u_yJC}rjoP}ChHv{ zOGs57W{PgQ=I4hHhVBJc5<6hBsK-k7MhRGJw~)Jq4S7(Zs$nZSZ)=s1a^n`!6EX-R zD%#oh0O(&hhBV&i?x>tTOs^lyiyL=JQ@yMHF&3V+EJ7N81kCx)=NpnPNZ$>In{EoP z5z78tsiqESx}742@tLUNAUGPVgrPyP8r3kH{&TyH(8bAJaer0FVju@!{jo?tICD;T z0RHEWe$qQ}heHsNN)R+O*&idod#4Pb&ULg8Ypw@EtlI|0!#oUs##1NLy1q}Lw3kUm zl{dfGn+8w7jcVNGkJV_8cn_(aZ2e#|QtVLOia0RUyu-ZDddjLw6L#3{!XQdvw7v>7 z-!oW-oyDFe$EWqBX5So#rXEq(H(2iR*-egw+lkEqH+|%5I4e0V)?!9ewq!8+=Kc3( z1jthkF)Z=zF9#}&{Y+XTX!F3Kr|Q^*_wQBCbU~GDsSOnjeg7#DEM`kBYDyQomR7}YtRX@x45(pxSyUHWbF}Mua8=o+ zuT{#0@6qu2E7z@=ghtc_e?ch@3OsVbgkz?D*l;M4p&`)l<69YZJ+XG82pk*JG?+MK11YUo$IT$< zQ8x9_Y3=Tp7g63Gk0;7^ufI;rF(l(JNQ+>%&GgzCJc)6-q#}rYM^P*r?OPog3c}g7}!wXcUw>~`PZyppj7wTa)2A#a^?Rvb;5Q-;HNih_&u@>Qb|Y=dV}_1c7?{T6x8X@Aip zbKj1N-ro-SBxPLoOrAyjtV&$No(wK^jI7z}lyJOb%Ou#ogT-V`SG`yDwy%%GX%C5Z zi!p_9j_z}m$x;Qjq4JRJ+iFGy+zbDQl#GciL4u$Frf|gvz zl9QGCr+B|?VUeIkDdES3$!{usO9R)76O;siB;r<=7anc@DB>aU+9Kkgr!ZGu5o-0T zfi-|-0rO^#eHC*b;v9L{WwouNTlu&fFJ*RDe#0x{IE(H=i(m-%xZrZ!82z6&<{Q=%bzulm%F(XaNoW7ttmRjbNb*8za~3m zt<9zO*g&2p?}1~uW>7=Bo2l}pG1LW==KZ1|L@!yx{c&c@8`T>;mYU<~b}>ee@5cly zNf4jgX?t$Zx;(`x(s(r18kvo;o&p#5&+m=8&7wY{`_%Cs@h^5kk2{nn9yS$NL%BQM zMM~3T@(+)}9aWgd>5t>`dCZ_!Aamc!26zWcNWOnf*%__NyW<$fFF!EgL=<<)%N%k} zh$U&Emj?93@UMw#b{ZAUf%PSo&kSO4LH{#OG|W8)#5Gsbq*mmrREk(wvRumpYLsDw@W0{*T1>|Hu$R3H?CDd6tNlK+wssRcZ$ME`1SoPKC@ zXv6VBRA|z^&^_Tb+y^5m`OXL@HZQ^3tVfv_hECJ-#lHMi>~>B z3`v+%P4Oqv7GXE zoHasZq)cm^g?xe_BF3Fl;P$Znd({08eI}zT1aZhjUuemAomk6YEDtV>?mkn|TPm5Y z?lb(Zis2t|1aL@dn&_f%`yOlkgktgAkvxFxL?e`MJ(dUsQ?|{Q&64 zDhPd=t_Q&t%vJx{9as(|R!;4D2+zz%%!{KhOSo`nV0>V0Uwl9AIP=9E?rgt;uaJ9f z@yXww(nrd_oM;pbOP?CI^!Pg#J{ZtVMG}21+VsTtU?$TnlEmJI>3VXtDeJlCKj}@Z zBTT{nx|=JNmA$-f1VxrT2uK9q$LM;bG%(nJh1&M04gY$yXM$P+4)OQS+$4ks z)q6DZc@126quD?#DZPSjl6^!!D*IOAgW$S^L@{xo5QyXWz!z9y21!se&tVvU08d+! zhLhN}ysuqqoql2U$*TPe8y|OIJE1~NrG`gaghhvpOp$Tjq^0rK$%*wuPK}V3W}K2@ zJ9UcKW3I5Sl9*==4(-fapu1f0poK=*!a<>kTorA)3IFEV>35%?IE*Z6&~7)@9ox%Ps*Fct7t?m?ybH&eBZ zQ4u}}nCFB&LKVa%*Y__GV=44mssNTDR6%b$0=`Sg6eg6)Yxe-90LMENj4csV9MVm2 z9m%N9;m;$6U4DJc>{%<1*AFfYxxu=SgtF|$c9m2T5qP3V|E|Wwj~?*BImji|BP@vq z#v3B*)Q{J%*IFVt=;COD9So1oa&`Rr-#RQ{rdw#At>}bzvGD+48H{+^W>{1JMkyKL=tFuV0H>q5T`a2Xs%sr^1|k`Mo%s~C=du-1_%QMCu)m!B;6 zBp8~2wf?%o;T2IO|8KcH8OePbq;vpiZ&QWp(0-s%IJdP^n>jTa&l~nxDffxOOYfW= zV?ZSLUg(0%^6zNt+qZL#ytJ2d)rXH%*Ut|`J)ks&dv#ofof;orQLd2|Yji$WbD{Rm z-AY(1<1qskbYOB5`N{H~VGz6%>rP9Hq{f}}315FASSt^D^d2PUhC)}^Iu236j(6_m z`XNl;q{)(C5c491kss0zXo`1tGN@4y{cOCSowF|;`S>K#u{dc{hEX@rO9M{Z(z!Q- zSXYbaS-oLnhPN45M6Ysw!W~_XKOrD7rQycOT8h+sfz2m{yHpULQ#l!u2o(e-Wb}C4 zy-zMr2@ce35dse+;2t?^&&X=CFiJwhNz~J20o%A6!}`R^&63k)J&W0 zY{d66)y5Y2DbI0)=McjVctjZbzJQY&{|-f0o*z>ClW)9E&V<9)#`b%fxu2M3so~?g zpQ2utNe@&~I~yevq|G2(UM!I`3>l~s3{h!cI=YJ>w>1yA4|6miQFV!!-8?eWw4mav zKcLXs>A~Hje#lu`A>wfbB|sQ7f#H`?+0;-!z2RsrC7Ae5i0wk;XdPlMtgvDO5cKk& zNcZ}xNR$JXZ+q#ZBVw^#T!t{3`8dC~7j;-}kzeg{q8=%|5Y`f0Ubgl{rX0{$A3g?< zV54&;#p_gowh!DHX`YN!foRO9%abA~IQ60b6n%~4{-k{7uNFkqqN~!{?aQfHSt&wm zenSKp9vWHgVnsaK2jDR#j7_|O%sEJ7J&(PPp$QTedHbdg=d+nMJ zKeAeDczXAIRvI0z*tvV9XirW=e3&Z@-pcuI%V`Pa9+|+03Ti1ZwF9K?k`-0|B()YI z$*;~|0VJRjEFlPxUkC}Q_D(%S+T#mKp{Kv~a;F!j)C< zxxO^~@j>J(AI`98#Dge58I7#5<;63*L>MY-p|lrqW2;@7crV|T-X8C6 z2?-KBZaRdU!X;)5y_bWc8}Y51QewK04GGE}Ur+39yQN`COZ^ooN7ZUIchs!Y+V|tQqML4bF@;f5in$0&*O_ zB(60EbYu8?!ZdGB_q-@ls(ZFoh~j(5*6H8Ic)`RJv$ea zecu;s%pc}0Xh`69*vsvUL%TrQ$!l5`6EHm0*#d+6UHNsI$JjXM@GP}2rz9}H;TAb( zNvDeh+@6c!gqG#E(3bXQu@<4x8T^CP-z7QMRAgU4!zxf~L0HdQ(>{tYf;>X2{D+Iz z^oz;k+*PC~+o>leX6&;q)xp>KJ3!!w7DA3yJ+}$;BoYoS@G~xz5XwW92ujTFVGPER z6SWK=C&aRyU0DqJ;dMQ?B_6&YkUCn7e^N6LE(Zg-fQIDWk?ZhTvEci+L}T=vH`3CB zKz8lm!En8(u_OBsMCggBb1hL6G8?x@L|-<8&-@8B#rIDF=*}U^!|+YoJ3%g&VyrrO~-$5;X{gk~0f({F`7+q2yK zBjmz7#fEEwqQQdM3Rbvqy&{=sK=E?8rWy^|yFiEr0bT1rM$8JBhs{?&tB}1&Wb18e z8|riO`fg>6J!7^H9&zpfF)S;T(LBOVa+QBD&!FE8un#o})wot+Q zGT+MB`(<6~-_AFgI{ER9TkZ|%D@%blNJe16?HsZ)d<^G*5ObJ@VnZUlON6yPM?N{9 zwy8~At{#7UR4Q4z%O&bVit-t00!!}d<+SaK^HgSg9&*|gpX>|a(Af-9P6~?{`FI58 zvq4qedh$ybR^P*ycW#5x6gycZ{>67;K6l=ac3U9!UQ&WrKu)m;!s)hNh zc&CmC}NTX6K{i*cf+);R>y zr3!+GZS(FpxOvWfRQ`p{CTr;w%XN^m4#*0AfqY3i2Bd3m=C+)|7M#=h_}dkMJIPoA z(N9Q=lmkrkH+QyYoZRHfL2^n?iZ1xikUXbBq5t4DKRm6QmyB#&WMu%EBpegb)kUB% znzTRx&R`BD7|SH1HX&xb#sozM{0b2Q#OYa8wL8#a2*h9X&pQuHVSaGSjaD`v}tl1-}iQ8S&=A>6y) zm+AE9Cz6DiP~wg>hm!9ZwP&Hy8igO5Bg&=Ns4>KbL7hK~rgf!aoW6V+6vz2M8JuCf z*N8ujL%rjaRAKqmN1V8L8_PXW?(^0%+6B0{Iq11&)cVzFcq5Aie-VF5`n3~qiSU@2 z0@a#p^{Ep8QDM=I< zU}PbWzckL9@|SY*_(owS)y3VY_$9H7l|t42N`#lg7IZmtDzr{i>jYGR5)+JV_UF8s z;-HxF25O7X@0(MB; zh0gA(=WpU(xU}s#cq0VG^O4-GS0B5T`Cm=aey<|)OuzT{U(tlnpHU}bYx}Z~ulMbP z63M!tPwOM!2$xStXpP^@CAcOnz$8DSq5hhPpcXBoMIxbPd14zXm7?WgN%O&9Sqret zpPD4at7zp-hDj4(b!TyEA%Nb_<5>*xtg4z~JdwiqRf)ZClt#v<%@~*1)KIWA+3?+K zob&Zy(3-;?-ucO(9vQRYgkJqUDXNIy%+mC!4m@2A32^10>I~62c1wRtvbRqA(S=Ax zEupq~*~*aj{A&m{!Pw>i8X6q^J13d{faC;&vSV!|VGw6_0pW}VuP0~~r3{L_{0kxs zAlUC6YshmF{xt}bBzgzeUu$Gwu=*PU%IwS)@-dm~ZV*B;bT(UJW^0F&_Gs9$pXk9% z9F+biIe;~B>b{@`lvYQ-$O7!kATzl#%i&z+Ce5-b&{&@_>|Pq+{UQ!h0fz$^tC5I# zYG&>6PE~`~%nMZEhCkNt3U{uW&QvDl4X7op0#-s!!7H-rx?SRAN~~2|i?#WTuW(tiK8`Kjs#o!$lXjNf=%h&!`uKbwjDf1hmITj`>uM6&I15 z-@Y{jc?rp`YKk!$>$f)n{aCGo*t_iQ3zTwzV_X{4fd6_?buCab?=1 zC)*8HK8;^w>SUy-T8S;eOvH18WDvct7#OS&OT^+WSp9RGb_&)2qFySTS=bU9@Y4qp z6;1N{?oc)G0f7r(V7Dc8V#z^gRW}H8IQZ3DV@`2`XWp+YfwjWSyH z=u<)cbX%$aP9VUAGzSKzXt@IoHYPbMky8=7wO;3&_N}vB#(?a_EY6DcQ82G&cEsM5 z+GP~^Gk~n*XvUMWj{zYm2Qtw{Ud8*(Fo-B9RkXH84qn(z@9cu_D=S#*WT19knXlaw zBsT>O^MTeU-H2|^kjy?WPO;G~<$8WAii+4mbhu8O5}ae4groavwYYH9dB=TZMEsB% zzUbaZLYn;7x^Yn(ZE5Ux5ZZ4z_?;x+&3k=I`>CHwCHL>?1@Qcpkk`4a)%I9YdW^2U zw6-n60cUnKE^{NTe6Yi&*HmD8yk3Z`9%X za?N)|g_-o|-{EQeBaM>Br|X-rBF0S=@%Rh7ulS8xLa35dvkP7;d7Uax3f~6^#Y;y4 zJcl$?4{@&zKjmqq)gO!G+^50($p&6J%j#<^EbvoQ=Tuj}+0yu;@ca2U9q)H0F$)0= z6#|wA>ZNylbAOy7F!)c)HYF|74Y=GD3i%P~1h)ljz~`~ZjUONvD+&t_b4+H#k+ZT3 zer2Y;y2(VBYE?JD8rKSD8gVVaI&=17d(dw|?}(5?Ry@%d2*WuiV}9hg$NFIQ5F+X6Gb*;3%{lAqMIb@6 zS4(d3{RPE9j4e=sK;GqTrY;)-s)->9Xle)NaaE-Z5*kDHE!{M%cR6-sq68(H^fKmI zn&PrdGW~Z^hUq4)tcv`&N=rq;BPvp;< zgSU3~f}Wm@++v0YLhqj|f)L(P%CQf1=8B9~6MH{qfl~^XkwpC-kls{0QwGdN?xz6=T6c}8j+VKXN*htT zAke!eLPUME1Nw5J=U59IDLw0fPlMudtw0q{fI!L&QCWhoKnIL&^5`L%j(>5^&z9m` z8_bE=09#KyFFFL&BI(}d!-IOcxxuMDFUTrSdH(Du>_zOy6oVR@ygRl~T&C*Pd8djc zXo0Gr^~<%7D4z!GAJa@Qb=F5!@<`?!OWA5C|HYeiF!boGcYsJfO?ZHwwCKg*jzC>sb3y2rz9g|R1BK% zC9xw%x3K+-e)6>Q2KmG8&l_89JfgEp-h)&?o6)!zLU??R4^%>%hlwKU9ei{RyRki; za7%q7DAWmwd^RY)YlP=KW}s${VomvnvCS->&Cj8zCeINPN3zldWAuyE#No_a=K*R$ z__EH4eV!wDG`aSa@!XP3H~4~|d)OKzu6cpNBYTcTwz>;;;qGUi{k-Hg2G+>U3bcmC zl-)z#%Azf)D&3rtn&3)B&+z*|-9pOAbpe^Ycr*5fg<>T5R@4OZ%{1&FNVN%NH{-kcfV$|}}B zW9iSZFh;Yo({RMf%QQm2rOv1>4|5z_0WTnS*ijRp)q*rjT7wRwPlUew(c-Vs{k%sy+6^m#8_io{EBv zRS0MroT`>u^Ydc9@P9;Ob*hxlDyQ}660nj*<`u=y_t$e^vZzxw=J5Q&8-IR)0^6#! z5dM5%NyvbHu?h6~d$Kaj+Lt-N^eVv}Pn>Hp#pYL44mEOK%!LHs8!<*0cL|Hi$1zB> z)E(2xAqir`Q3+o_9(~)Qu}q@$hJPTsYlAZ{J84Q`C0?mZ-+vrd0s{^}_5gxTUWeZ< zqbjI$`*es-hWCtpFMAg=*kp)VgY?^25>0rgD%ci(L|v6hMw%e<=g)i*=X@Ls>1Lvc zrJP<G}_c+bR7y+!XvBU4SIUq!~aK7cxpSj$>uy9?>jM=sAcmHp}TEfnk2X?>BWKJ0kC2a;?!YaQ?ik(y5Up^)5YE*AC z648?hE~F{jWP*>{LRk1=JFVLGT?h^mgmEjcVRak=g-B)}6|#~mBK*SE%6a<;6SJ1m z4lt__Ihiz^!kSL3s0xVR8hs>vNI=LvGhZ=-WZsWaJyRVKke*ca)ZzY|;8J_6<09^6 zS*ZrHl2Fy7`)#^TIO@%kuTvky{M%V78qpnnm8cA-GZfbq&FD9~P(O=jW)E5cFFiJ` z=7b6=O7#qDXiq}Am^j^wZNg@v(6W?IPSddm&pk)SsMLQZHO%w#R!czA=dr}sPN#Q( z6#AxIu2?9`%6_-ZYXNbQ7AVt}fF5ITNk{!76~3bOIWbQ1_752OUwv2^=#CYU>?}gQ zetG#rSievHfu}Vn20@BBgm&aCL0IBx1B`RD`N!PP&c=ySXEIrYk9ern&;h|PNqOUj z9x#_>Y1J+F!g=GCPZ-l`>2K*P9KxyY<0(Gn7y^*e(~>XLM~0dnLw&9+#c98Y9b0BX z+_`zvsv)+uhnZiGJ;o>MwL1C=q%>*I<_YHMRG#4`xevZf_3s-vC^v;a_k!qc0Y4J* zLc6PUw>m#Fz42qSxk=`7?Y-1{Zj~lxo-@NSN&jf-^OY{aEiPx1%Q^NJ4lcOvN7f*~ z_A5}Q+Bv7Is9+GjxLhoTS7&to>ESol5ADvdPoOPRxmmJ@69b99%@PCqd^ZpFkVae} z|J~e4b{OW)+r}SI(PO&cex*ZefOwEf&hQQc*(X)_?z#Pp*bgTdHyZND~!INZQTSGjnsUd zlC*%Z&<|;wFAT*HVO|6EL=2{MjF45n^RJBcFQsHGJGQt`M-Ilv$=8`hH(@r+7Np4e zQz$-mxc~@Uhf8jjU8E7C;*XG6nTYv$$B5Li6(9#Bvi5aSap(x8Hp4Uf##v4u(-l*2 zZl7smVfg~ZAj5r1%AjA3nVtAWWbh(=X2lM$UubBAB_N2kg!d>RNi+Dw71xo{fab}e z_ysiTMRB&+SCC+*Xv=)#Fmd}y9>d>Gpy;wENLzRrcpHr||4UCxl6{E6qMb?P*P(=5F45n%0|3v>{u(+($a8e;ob}firo5 zed%&8-LY1Ag*yuprL5&FhSoSAgI!jNbN8$an$$AHI8Sro7GKpC3-{3aroM^{n9voK z`2{6K_6?9>hf!eL9XGf6q8h)6vlprDbju&Ce&zO(!p6|iCr$qDqjdcl;2d8-UjK!* zW4AQd(L9Zgd@M<|sl} zoH$F?S-I96vI(_njTO-@{<2d`9@v&Q>N7hJXpSV>3_vbSpGf&$E9*WmQ6NgXg}188 zT~xH;_CGxUeCR?KuYJQcmNN)Udj3< zcNGB}R!$wi&sR0f&3&GYDUfRdVm*5L7{X8#RZe}R z(wP8YA@cCPFg~CWnQ<@E>tob{-SiqUC-xC4$Vr7|pTYluYi%J4mcbQU$)|d+LPQ(T+PX&F%(iNDFT`9 z)ke&@uxU()51xIl3)JIL#MrAG0nW-;FESK+lSA;eb!cl25fO$ZXD98QL5^_%W|pi> zoZS1(jLu^XJEF7dyW5~d5wFI0B06Sv_@_yxRD9U&8htsEVhIiBpFP7;{RC!@+VZFA z{-|!G1dT_It?qq1)f{jiqGPd6+UyPAO$#%-lp0s^`wC$mIgjvu1G3pCMY!2KASBIJ z>vUE5mR`tOA9+Zf+Lel2pdUdyVrXkXleEh%P-zG`ok$wUNpo!Gnf#C5%-@|*aq%@Jz7~3)6mrZhZ099Pt*cj0CS^SLN{42#v~xFf}7Fo%>5^>C;WL@mTWf2ZOHH zAK(RX9d4*9IRT~8$W|jLfGW&IXc+I}Nr)BHUu~fLhvZ2PzJj$8HQUy6UI&Nj+e98) zMV)SJAu~5+>c@c;w%pL`2Lhbxb?IlsVM?bi^$Qr*WB#}%x&YbG#oLY9zO#uSjuU)- zh)lNC58saV{Ch-q(F6;P6-KU=O9z1Ye4s~UA|Zk@)4T(GrqY7XC?Z4HR>e&59Gu)uTXMWpOEYdXO*orfhF#N< zNkyQ*o1Hw{GIejO-Ym9E5$T-vH9o5N{CqPZ2|!ctXfbV)>zw|Mi9O?j_>w6JPrS#f zZHNjhJp9mfXk!Ek4y6aH4RLJr2BsL@OoYGqo`HibA39hD)kqej07UZ+8kvFn4RU+V zne;yME3>w1U9LQjv-3wmP6X97Ps50}Ve)ZFo<0OekFI3Z7``U0!lwJQ7jF%w=8XKI zGD`1O9>)G$($LcwEGce?VG)u{GH4i~vntSfrg#tENYRy(IA#ydY2mSmToT{FDatmZ z?55k04<0i9nw!LdbOnyXUpD;3-RdWFVLJNSZ{*^#~Spe zP6l0?;NyPI8x%-uv9F!?KhN{@KTWKkxeqY;0gn?c%>H})<@!B-?L%R^^hVDh9s>c@hgbn3XDPeVXlY+1$w{LjKcTJjvetq z=zvKd)q*@M!Hoe^iq9#jms;cP(dSq-)(-8ybR4A^`O?B>QAxdrj~5w4F$G+FO?#iA zdBmckU_E`p7vj!vpj@Ft!I9OM@sF_ry>!G8rsBheKLrrrKytOj+)q_@_Un0+PNOJO zqkZ0u3|2hxBdiI9b%)*};er@Khwlxq>}2do9;o9D}lRJEPX8EKFUbt?aEqT0J1 z=Gz11x20xOIId3Cb3|p8d*;q$m<(?K2)x1|ay+?x891tZsFQHo>I~(R*v-y*Lt@?$ z#$DWR;rn8*1*D9W<}|BZ*U0^LUAke)$1_!4cNZ%o3A$}-&2adgI%#^!!J2>EGO`#g z%unOkz)0PC^x=f_h8y61ZKr~Kk&LV&Sy z7P%{hg~@A~(JVd0s~puF@dSqfG)w=m%)J`XEgi(Un&uZGV0<;1w;TTbh*Y~h0mYMm zHMG{#%UivI?|j}KAau*42Z|MgS|3k4sTVtlpfIWzWXi8Z>d2MOlEfjA%#baAZP^zu zb1sEtSyW43^*!dzQvWHi%Bp+8%=sA~O9e7!23UQ>=erTn(%#G}K)} z8WU^BI`4GHwG6D2f=ps_0k(&S8C{% z|Ee0FzSkrx$~l;T8+%u8jkZ?*XWe5i7yhiBdK z(RV$u5B}|ZHN_}hiNt@s?mjq4H4t$6N37o9*32}_DW5xNhmy?=#*N$?{%M4^^j{36 zhp{Vv)v8HD*I_o)u5ByVuE}}b?H2s(%n_o1dbJQXAe1`aGgDn=Ij#JwGu6_5>_%7X z-Y@Vb_$fr1dm@-M+Hc5iAc47Yv5mLf41r@}pk^Ln0{85c{`w8)DC=zHY0qb;ty8Oq zV-PXm_rNRDRD>`8k{WqKzx0({ALJHpCwagxcbig9xSbKMROCyYG;wghm%wfTuC5Uv0 z7s~*%yTTZt0uH*zsmyIlD@D&$ny)o5&yFN zaib^8@GI-GnlsPF>=~+2(4$NC{Nnnzj+M|9RjgaMp_KaE_Dh!wMij6BF%k>|vcIR| zn`6=F*z(9oJ%-2tzCus>f^!XajZLYDV}=xl`feQFF7|tqYRvS5m&J2Ar9}Pz>-cK$ z05KUm8vIXyR`$1|P$s-zox_z`BYd|yhWUMSS^w!{zq?+sPz1Z*xU(Dc$njsPn)*b~GkPU6CKZ7_F|% zi$fGr>zi4D>BdgjVmIWM;a7QdmPN=M>khdmN5aeket-i@1T(!VqgKt*fK9t~$U21U zMVi}tOpe{2jhbVjTW*T@fj&a{c7a)$cIWN5I4wr@#-E&}>^fki`jZoKoI)rq`?;)S z-~h;F)`bqRlt|g;QNJ{p8@ASYNMEP^pETovqKDYCwfxt9bePL5mq^3hv@}Q02~+>e z(m1pksr!AW84p4%iy9w2tWiE7CBT*F29glq{JI7ELJx!wCp_?n*vRJpx2R$N^uaPx zAS;UM>3rDvKd(7rINm84?LnjUBn`)p82Oq!X2<^nt4Hk?*v5IfF?WqcEji!p;#blX z#+Y40r4~R8LfsTSGFCoO(v#Fpc3lIqO@Zqg`CP8Q~ z2Kjtx@@aXQNE_axc}pM{794I4&MPVnz5n&Gf%119CA^}GoDF8Cn?A&mano$O6dsEF zZ)TfOse8XjJWI0}E1&sx~veLXq z+K~i=K_PM%v4yYdei22Cmj27!ipZKk#m60-Z}=6mKEA-Ldnwz9wh&G0Ebw~RyrOCJ zy=2fpC_e+o`Q9sC4Zy=@&z5BV^`yszy%fqQX;Xyd<+dbnoLI%{>{g~tQk{yPnP~^d zB0MZCTI)5J8D#I1e3qhA=BYh;u{o)oz?AQKk7um|Kv(+}yk7gHE??_K8?2V$>gCGL zZtx91oS#P>`RwbI;2|<0i8tRoWgRWR1FP8>w9%68mP6Qs4YOFGuBc;HNAdrJ)@%{` zX>7%n{XT`C2(ojy!_6x}QHtVK8#^ukfjrP8N5t?5no`DYE6Ls1ul|C-skUc}$d=Wq zab*1xHlsV&tZrU^pFCgqTsiwXZ2nl>^jIuFpawCrnPjY9#O%eo!|%O1ZW{4ImeWI5 z%dn^8q;aPTV3z5>r_VF^oGXww|Nqeumk`7Srr2(x6=SUsPc$+PC6%Yi1Ay#cVP?i> zyCZEXv_7XC4@{8r1R^1)d@y(~o$2(j2LfwID>kao-4}4eqeo|rvRV(*;`Dk4&R%d+ z48_R=TddShym~$-w!oAW(jmAMhzD)6 zT^e`Zl9Zr?G1OpsqXN2-AsjYy?+gFvmQM~m?ztAGGEeX2*Q{94Nk85cMUzCm__`vn zQ-|;Q^Urgh*6E{MY?vcN1v4TFnFHH zg;mN0&g6q~=Sls2H7_;)%*Euy#|}t;BU_jk6mufq=Zz^Uia-sFjyLT+KyHSkT+z^{ zdapP#$<;3YxT5x=a0$I6IFjH)fCK`gWct#OR?Diu%a#0E>uaE!4IkTxIsfWMrY1VD*8nzb`o2c0=c`4AcK5r_ zMX!_!A+JB#_yEsWe*qhANWK)~S|;R|=n>qzIs1(?34ti8?i$`i5x)zj(d+H{BCPRB z=@8gZ3u%>Jhg9(8n2b^ND{G z_a$UTh8A1y*=@$Bwnei=j2mm});R+Ucpyg+fL~RSib%ehPv64@TpGPljyE!mEV&=lRgDG%6dHVb=54G1(X2n3@Kl znjw;*HPfj05~U0#OjA<1Dn2LL|5WTbrYfir$knV4??4rRg3j{zUThP-<$Vqd`n=pK zTC$5^GPLI<2bok1U#Sn3lzH(q6?!(_Fs*3=a9RmX!P)Ah%cjVEtoXG=BU&Z7L1 z|Nk~`5&y9LbCPZ`1B!I$zK>EK(yj%l{eYlo5k`e(0i$xdKW2JrtyCJbXbq#=uUS&Z zol~1<#X`iy@>6h}7U>pt@`i3^cOPhrhgV|G;HYMn;L&<`6;ss8Kc{l;Dm{9;cT)71 zvao$5sG#RSV5#F+7f1RX()I4eg`Qg*9OKn}p>5w2wKXvk#2vL71(w0Dbvz>q#maR7TU0!G9UW(~xyTEs`Bkef*(4{IF zYGush$A+=wq{z{2nl{X;k3Dyq9s@7*iNKNsRR-NMHvQ8xAm#M=R_~6-HWWK`f7Y3j zuv(>-UwwnqO6}cDRPLo=S?Vipv`@ht`ko~ZeySTcDO<&lO{UU~ENwLJSl2-2Lxm|y z$OUWU_-WaST{Jo3V)M)w;F_q8ZLo$Q7lu_EGx#mv@Iq&kExEmCRi0*7azvA>`Um=I za<2NrvOk>4k|g+;usIlm zVD2-GUj3JAyjDv;oyxOY2l;kEl>h8c9u(#=jJHK$z>FQH9nDWjbUuMlU+z^_NfYT< zwbpN@byrCB%mTv@5S7w$L8I3{;^#A@tr#wGIhsVlqnScME5MM^nH~HXAC2KHb2vwB zyvfk)`?@XuQY)Gp8Nf~m7x`THtJy`yFrd*9`ItY6XI5B>F%FIjxfD6p1; zX5p7_KN~9E_4HkF;6J@#86*}q)y4Ib!dBh5jdTx{q`I#denRBd@eEn1$h`|=|Mqrm z_hJAUY&7<{-3st9IQ;-G;mA15flQBKz$)!eW$8w|m{j>xo!F4mipPE?adG6T)qCcZ zOY^Xrd%=b=Zp(blB8;`ialsD{<5RADgA+1Lq89SaS_r3Xg1i zCQ!rvaIB=5QvX80m(C-9##(HeQi^|BEsP|?C>Rb|mJT17m*R#kl%lUpnp^W$zw}I1ONTI!ukVsfdOlf>AOy*DYju5>DISf1 zg!aAOGYl&zDGo%wsJ{!kSere{qrK&tqrV7N+)JW)4oxMaWyyS&aPpr76fB?9a9W=y zb;!oX1Pt9LjPkQZlxx7{W0$$!>@jZ)6AVR~{^(jSm=4M(MRhr|nzAqL?@7-iI#%D1 z&k-8ONLS~cDBVS^ETzfNdHKN_B4>qn98|!!Zg=) z5yx__s-`XmcRnHGjfcPgA(kJ;5{VO%2l#W+cU>M1FSwYCWMacRBNmVUHVj8k(OH3_ z@u}vLI-n(RMr8Zl_C>t#9Rd`zaERt;p;_!IAS}m0t$M(8iWpK0mo(_)8t@*96oo-iFo<1j|q z++kz3E(6%l^q(fu^E^*s^zGHNss*b8wHTvUpNDZl9GEcXdk?_94C&oO@8MHZH2+}; z3;7f|7TK)u!eX0e{itv%j7ewcV?u~IfycA8T^s&J#OBCRxM6`?aTdC4CywalKLs|Z z6>07_pyTMTIokA(oS%xx{MqURlG86IZMTWPbP`+6Q_aq?l5U(d)dE@PlC?wN#nsy{^3I@0GS{k znmFKBTM`XYKl74@Hr|DmUxKy-Yyhe7jbErd<4NqmdlTTI7HIrQM9yiktD9@%Ytdx|6=P5(x4QgcRD31I{_tusK~C zTQyjF@|+fBQtUk*ezAS3ew#v|1aTrCyZE9V%a|abr-Q0v{ix5-1(9QNHorC-hKw!; zh#QnXRGFnj%)7p+zrye=)T?O@oXWdVr%KfiIeL+i0F7)-I)l^EMrE?f5!fjnBDrfY z;ay2*!!J5AZuw+$yqrP+jtPV_etW}`&;XfaXj96!rz!`+`dH^E;_y|WI-AB|%>{C% zQ_Gzn6-jMWQ!H&enGvcI^}_M1H=DJ7c-7z$76}znW)Q!B(*jSQ5%vm_;(WLf&Ad8x zNr^_@RV=YyFXdfiQ&303WQ^%_B6aiTjlbFWW`piTSla6fw0DI@M~XIqHGjwzAjuaZ zou~;a_2Bof&yEQUqVi8qx>G(wEdh`)x@wxCbJbl8QX+GDJKfg9TN6{IAQy)$N0XX; zs#}0xbhO?frRg`sp#{H=1)KR^Vea?*^eqMp&DD z4#TN#4oD-v2@?rr4LAAXjc)#AYlkhUt(}P2dWk0*z|9J8>b3IELn#ZRHWj6%P4P#f z2mJI)PyUt^vsEE7 zNOeKA`3165 z(}G_d2UOhoP9{7nO1HIWfMjFdHOqm`MJv zUT^H{arL`@;waVhncvu__!v4L@Lk;uk*iH0p0h8}k8q0fym$xWH+J;JOn+xUj^dp^n>wbxM8GMdmIaTgI zT4@LkIP5n;C`8zj4n_opac7_F{kk6!qYaGC?1d=xu3i#$@jF%3fZzpNXh4*&vvJyz5FS z37Q|QLl>spEt69sn%b;i?1yvWLkeU3a2~OO+w*t-|5VV$Pq3Mek6$Sg3&`X_P;8uM zSD~S~P|$n9X}56fIiTxS9OB&BgdRB!*V){98x;k-fjh=JRl4k9v)4*Jp6q5&-f1vK z=MerVx)ien8JLWz=ZQXBuIDXldqfE-F=J#JDu6=>L;C*)I zNH78*yU;LNO1;<{@0KNnMW^5Y!`bMMTHi% zRU~^5F($tS_(PHpwnDy~DdjDJ)b9!;*+9;(U-X*e>2B_qeVyuft>+-|3#`dt6l2ft zbk}HaTT5B9dP_N2a_}!pLe?b6gBsw%L>O+dM`2TZWM2CNBO8Mm|*;g*Va7w z^2DamxX?5tWV&0_e&1=$bR#P_evDG$CYKyw`Q^55#OpUtISb` zhDHSO6=$QDOSrCR=JYtBIzG$8uwF{fuT?%zh?1&)PdPT4-Z6;&)JjD}@B`s+FDX^j zPKQO0KxKk24n&Y9)Yu9s=(z4ExI|@j{@~99FPUN#g$mrt&gUdaX(^zuZ1wxn3Kyb& z7yF|N06Tp{bi%fcNckfMl%IoP7k9@e+#Bs@_hZp(`qdulj{>Eu=eFBeX~O_+wS^xH zp=GCM`DjP0K4D+{l-L1nn#^e{i-{dH25pVl$<-fz-*e}t+m5i7;Qr>v?}@@%j||1C zzk^TSYvl}GuUP<;{+F4~%dSE}TK!<<;G&CpmFhx%5n89hU;wgueu}4Ut_&?Z-!%71 z_Dgm2NwSlGwb6N9>sg|>ZGL4R05WD++>eQEsFOZKv!E9C| zhS`}>=fs&oT7IJtZN1c3^1>fsi)Q%noRPN%5!^$7KiJ0axWWdFnQr>+8r0^2!X!kd zkZFd~)N<LM0@?{_yG6up z2rvnWIdt)MrAl%x-G{%_*T|nEkIJ8Q*y!I_?bLYj94|45zx8R|4GXkO3KFyZUKH-OPRX*ahqLCC`@53O-iK0gQTr>+% z?y&fv3u{>EK;t<&R8LlctYTZxLPBJ&m^1aC^QtTuxsxyo4Ie&hbD%4Ue7wPK|No)@ z$yQJ;<+GiF?sjTsaU^RDOzcICT*&L^F=uxBl}F32%MBoIp%$wHo$oic(kp@9fzkXL zYB;k&KE9#t_^Xgj9zlRk#t*6j@ee&x0?x1$4KY0*?6+crpORBSzd&21mz9PvH%P_| zXnBdd8Gwq6SP%hp3lEiG+|qsg3YbUog_LY#!ow<>)l2G@qX}64DP|YWoT__f$zAd-5nEAx&99e6s4)%&=tUiH`=M%!`w#tv%ZU8OFD=>&~HK_Elsa z`Dq`XA3aYqTKcZ4IdeV9Q~OY!ha$FwtBOC>P%rt+bm0_{A$Y@D9)odnK|<|7r@d~C z?UR~3^?^U_p<<~NRn_cv*cVEd){laA0+Lk>;O(NQeTuxeNs0awpIU!&tYpGV#vAkW zz29HkF+%NCf$tY_uNYZ4LaEBno;z=n7s~kxUC$yqwPccOHXF&DSa<}W-@|!%Pl`Ct z)ebQ;W8x|4Iu)iJiY82~YG}$MRnW4KMYAk|#6d7L-e`hLcQbmadzuGAi$u<*Q7gmw z(r}bH&)sw8CUR`1UkO|unW7gljmr?pE;Ps)!^uKUKyT4U!a!r@(K~a(jLr?s#GEOX zQ?|cMvp#U5iNGKrTRJr@h8EC4o_grnx5UG)0L>r-I$Kjc89U(Wk zp)KG5$vxx446+F}nE$Rf9Y+(>Wnpv=t;acy|9S7GtCag{z9`-#*rP3>kZFhR61bc7 zH`YpS-Yc07N(>iN-S51Kt{1anu!&d`Mv%~hLhWf{FO?#?p(E1kAJMPl-Oe98pqjC~+xuXPxgk0<9qUJGSz}CdE{n%y5>h*# z&*!7xz*zqr%82Hj62aq`e`aPvB|+}m^9rf&R8D;6fBj8jb-sRDO1Ig!uZ5oukZl{Z zOFeoQ#i_I_S?(h}MMy~9p_}2)dp8pEI}xRTQq2PC`e+Q~iojd04`!Y6kEff+nMN?x z-ZzDL)FKshhXzz*b<)2D$d5hw;Fx#`>miSA&)20uXdZ0Npb(|#hJ!1Izgn|H+eXms z2{3R+ZKCwd=Bo`o$U}j#v;05R6I19W2hHX+UfNvEEk1EdsXV{3lZR@F`!{D-Xy?0d z=iIB9;$%m=X>)ZCq!C1v2Af$BKGJDA{BK1ASm5YY$C-I3 zswI$PCaZE8_|=3W^`4v-QDO1yPep{MfQH91i+DG`#mza&RvFeOLM@)wf=FdY#JwmD zDpE$9UJqBAG9|gTim%(OduoTd=_*}w6$CYBqfo9(yhBT_GQbbi1dWV#Aw$D|i`$nS;MkY%L*fz%bA~_xjg&u`lGPz7y zEr}&a-6=##WA5xKTT3n}&uy}Wuy1^4tMN`P<}BDxt|u&2IGe0VmpzNPBpwQ*hBTodzQU!p8nDSE6Ip_w# zW;5w3=g00&d?e0STg%$b0Yb?XoSJXuDNcj^p#)~)b>IsoTTlz8w?MT17&=?kh*RRld_J7Is835h=4 z&W;TCmA(TV&2Ey1!gf{X=p3$!4UM8048lz#gU{q?EvB2NbHQffptd+mF7>D$xX#dM&GpT~g8CCFARs8Tl zK=k3#(Yh;xlhWqDw>y=}BKBAJ>KL6S{4mH{{I}XF3$6}GM=spq22G&g37MtX= zdWsX$Kve`EP-R)LuRn)-wls!p$GALnIDq)#ThnlD$>M{cNKp_I9~&h6!;df(XQ5n5 zM&S-`)+e_^MdC=yHe8!!xiJN}mk-76H8Fmq%E`(amo z)0zwo(Wsi6hK=i^z$cdoJ~8&Ki(nGy%rFzmhL&0P_lq+lawCdqzE7!INha7 zH!=e}N1Xr`?agC=+zx-Z_+y9jh=%iJY+Q<^^mXzlx8M>==qM-PyVaPjDCy(JDy-rG z5H%oMnK82_IP?gtyw6Cn^sAtJULnK`ZTr7TU1b zo^cT3R}WeRKsmE!3icSrF4ReT#~y?elM+gL@4{E<`%91P<9ESOwMst*GN7rL}|4nL%rS) z%e!5sRfrv?qh094!Nz}f0<+dNjs+l1-diw6RryC_6{!0g5REh$M?lAVPHi;P4FDf% z#U_zU+X;f~CbT1~<~HK!Gw5{OhiobVAP>8(gpj5&Pbze2PARA6#^BLE`_j zokCSBxf1=<3{*f1bm^vO4kvkFq_y(7z^OP3lpcp^fKjU%B_&X=u!4GI^!ZGNM?_e- zLF_#_kIb~IJS+Y4?H@<ld`$<3@Q}3(rJZ*%3lAfCsrJERRbN;4 z)f=!7IJPFZCYZ0nr)u14;b}6hz9E2J^WF7?6fggIR28t=4@fU_hWf@f%|Na}va z7cP#->j1WNAea@sb~#*qQWLi}Wh>wP|K?mcrF+cOc%`(q7X`;#f_)9}rFAWdYfc@% z68^>!=|K>E^j)oj;f|wEtk0CkGHon}!r5nt*AfQCC_sU^XG=<+gGWBa+JQyjy0iT$b2$k+m1EE!BJRixs!Q5}~W=Ds?=LB{q@}OpC8N93|B9x>6z~ z*Zk)?To-x?UMZ>pn^uz2l&iix5RLHsq(XT^ko?UG*oR1fHGU-Mb-V+Hi1#2$j(VZ{ z&)Z&7Z4EUpI{hY#bMss!Vou51b_kCgV6GDgF zfv0`Xc*7(mCy>7XSm%*{odps#$=Q-JRU_cQa`A3%0>ng>%atDgrfh=`xI$pvX=R7+ zoi;<&FkhLe24SS5N`OWq+Zphvs8Kir?b4=k zdzaEn-rhC}wUbNgT=mU%dEUuh`ihjhR5r5X_Q71h+2RA&*)%PclY#7kljiN8A!b{3 zU_(Tvt+HvJ<0{XVaSj4qh)4txQO*1xG}VSzzUK!ee4=q}YYOl16S=vX?(L!a>pyw~ z^6V+iYn3>x9XBm#7#NBqoGqnS>$y+@rx~^6b69)!;gy@=!szj{oNLLDC$>{zh@dHu?C>Arq~ARKHzMtw&{ed zHC6ke;H3_17Q$YFG_Mr`>{7nuJb+$yWIOx1Ok$@q$MkMoRRqcvX0C#Y^u zQ&yX-40+jP#;|H(z{J{-zl(LW{HHlPAu?mkL%i4gXAj%K^kL2h=HDlMYfoxi3*}cC z1Nz=&aFj2FksG0@$3?N7ftKKqJ?#&H=DM!2jlH>ti z(2W3o9cRUxcC(vRO7Ze{O$0!d1sqKJZD}|%-GJ1iZc&Gz_Gr+BqCN~9bRkG&ANR~l zZ(@5T9Gbd5Ld@q_qnKmO(mZ(4LYIgspQ-2&PjgS*vF@kUr0_h=T<&B#F#Y8sjugt?$EeyZ}g-#AE5=>~UPicy4 z1wXwfboD6*!vGQwjd7FAim4tIo*#Sz_V@=$Gq?#KVmj({5S0gqAP7;xo`sg*pWw7Q zpAxT%2ByS8a#nQ}heUneUCeY9Gd-jsr}bT@^c8EXp0JaJT)fGl?>?GticxLUFXQoC z0K^KR4zae7MjnB&X}caupqAQb`=JX-OR=^zGd;{qb#Ay&MxiG9Tqgmbx6a&RCyvt8 z0pYQ3j#y4qF7y46oE$WF{qP@-?!|wf{aR#)_gkCevajxQ(iz2DA;KqP2Sy0?GH2C| z!>DEcLYxJ-$fZ{s8tt!d0=8G-rqlywBv^HCz8mO5f#jJs^|L#21^a?PiuBh{_Av?k z9DWFRFAJ3IQ9f@TCNJmXlZly_Vg z_^Ebj{|9O$VwO%35VjXr4@q0hlinEK(Rn^_ZwrMl@4c z|GPaaZW*rrzHnbqxW~?YN>B1O?3C<< zDc?S$AgE$)8JHh~aDd;g3|# zJ9<~-26l4^yR#6?F$crM<08}766b>GzL!pkJmJbiQJQ~KHy8%xN#|#P=jNq1zuQHA zE}fyLPlb6a)Pp^Aj6OqESOP=%$Q7u$<1OJodFa(-{8M%#lY(OgM2uPsS>pzdCg-T^ z26IQ%{Q#8`MaBVNq(R)K86P4@%HYz2O4QbR&e(J0s}P|(I7ZVm{@!$MyuDdD)gZ!u zOim+yswb&oHrv5}HQV=wbr+_C;-Y5%Ec^T@CW5JLG|=gOVu)Wbr-Ju8Wlk#dNp0p=~$F?+_JeDQ|z$)y^6;EmQ&6)YibT+ z(gOQhJ~@@Yd$4nTx1ksR>clU8>l!W|7yDt8xC(;5>NyGSNkQ!%ex805kFS0;U0$3e z|ApkloO9TN3S&qhW(p3LhyFwIkZn>ulYxBfEFB^GD0pqBbe)JwymQH7WW6(gGXDMEf`TC-8}2C=(R)$NbE|e2%!m_Snk<|OFlSV(gaeCh zO*1H@YXPV3icW)<<#r>tp(;>qvZND8oVmzQFm&1;aiM5dmTUpYX>KPIVR6ZpMtfA~ zb50cQdX|C)uLKkYI}CBpuVzR&Nh+Agg+Op_bEbX|;hSd8M9I(S46PBn2;I}Iks5|b z+g@r)6cR}@Op65kRBAYO2F%crzPgl9F2!PVY zxR1-(&RVXHZW+hpks|9Qts>xr7$%>cxgxF}+F=p%xX3t-&j4}wFg=(KRrF267Gg(?jY`Z-THVM;^u)nI% zqqMn62P7qSrGx48PfzM`Y*O*i4M*>(r$zml2Lb66N zR0#8DkaHF!``^{8x7x#HXhQJ=N(lkZRoM+LsNpp*=dbuNqP4! zINit|ItN_A{werNmEFOj9M|V1*y&){@Lo7?V`QQhWZ>}b%)FykHK>X;!m{Z-l)txo zVMu4(Rt#6W(Kl~P2ezC%R)nTH=54wljLY@i5eS!Xacf3iW%Ze-NQVKe_txg#k(3yx zkfxXy)#ci$JKSq?R7#QtFG||B?gvc+S!f0d#Od>Zezo&{TjZnqJT|chaS% zB5vvv=PeAzj^w0VxKx_F7?a>vfaM}jmm?T%?u<|=rxk+X=W(N7yVV`pNeirl>A3`V zV!aq(pr2uK-5M?TV>e3x0R)#(xZ*A$5LA=IW_z8KAtyLrdn8qWLIvn-z0hbFE>G-z)2X~ zcDHk5g4rVGc@XgM41yaa!Ka)Igk1?PFzgxPZeWN+SU9|PR0}VhJE=G|694C=|4%-A zPZqQQMCLvDd1sm-*}6{ug{RjVQ4IQcMhR>y{5&&~l>EE+?LE zG3Us|<>T$hwQ@m-IF?`Pfk`|WFA0O%QHd0Shidd09N!`-hz3rwz73J2+p91?S66q9vO=V;{Tr5mx1riEic(_=F|5>zm#H*Q5hK z&HQ#3wj!vQ8q9X|c(?4NzwD)U&II27wLp3E0B{OWAN9?jX+JRY0&6lNFPm)6zuvPX zglghI!XP>rS3PQ^xFcV4C9~;PI57XTYb#h$KAIe?#$f0!Zc-QKHp?QgRVoDDr zjEmBK4_Ntkn=`tTl6ko88&aa1I#0e7qMv;Pj@Sm_pN2E!?&`T}x^95$;g(g3^tvHX zGpq@OjeKso0-i>Nuvk@vbzKn%kjZkk{|IADb)#1N$<%2O@i%v1!NL_+^AX9n+<_YI z47s5)2l~wZ(Z8HYlDPKq5>y_@=9OoKPG+e3(uK(L#A;XeI~=A+7s0L+b_KdBdlNH} zX%C=2cseb*L1doc`|U=5)om$HyEV={}yna7BJ}F)xV>Ek$3Xgn?Vj z_|{8h{l&VFt1vDP)wPeej zrk8-*5O}7t1c(3i1YM{^4>2$2*4z7lL>z&>_7$4ci6L<&5TlPGKasMoE#4{t);XK; z((&7sylB?k>7(vKz?T1){&QUiyGGnZQ;i@unO>asSh!ZX=uVafW=iz#laEOT*9yw8 zLIcgIxvHJ}ojepblcEEYhKW$#(xPbDu$zc%JX!q!t|v45Ratgow{&^UU9b{(y0=f` zvM|heIod*8{@I+myVM#Dsczt+DbwhRe<{lZsWgZ`!{4b;zk{qSzd^J zWCV`qP3l0oVCgW_vPHY*k$1ici`Yta(|8|i=Kp`Y2F68u| ztE=|kbD(^TtyA~f6ReWpvA_O8z+-X~37;^v5(7gg?@bHAqtLl_N0*zqdVW0x`6$LN znzPcj-iExVKrtsF^g;5IU^w|aL8xKNzgXx~Xt`)XOI%+uCVXC+Hyf$MlK85uw>Fsc zZ6d0>--8}B95DjhD23Y}DjP)x50%T7 z^JSId2n}fa#RvQg!t;p?d!RHSzyoth>l|D?8v6A%W0!2oi{c9il*`0Z=82h9EM6ej zTTekeMude|s&!y8RGs^1l_75tVQ2xkC)BLN_doWL_GAycSFMNWw-_`;{BL}bP*(5m z+%c;nC%Kj$@OT*I5AU&OUNY8N9RzqF<@c#CaJvcsay_&j29S_AQ1=EB@n`Hg2ks8o zlaG29jUf??ewTcCk|E8Qk}_~NON zMB!@&6R!>E1!D!dQ#HXnB-TW;Q)vQn-(0X_`|!>BR>1!(VnoD}Svwn8+=1zywx?&gpm&7nZ&R3kZ>WlyQg?*&SkXh>g7adn_C{iQn+G0OLv_pH9xU5uNX7xtI2uoflYo_C~4sQEsid zm*w73^w!? z*ZF)hfBe(Kvl4rI(G9U5vf8#DhW~qKF7qv+FZR*e{apY3U-Npu$aLP3jP6O^9CZJJ z_2>}F&{4y-I2^==Uu+cp$U3B^9jz?3r!n;<5LSKY?b^b*jJ!*N8BoM*p#Z|mm^||0 zbu!Nic7T^Jbgv=sFKbm`DE5&gyWeyrhclCRY@q=QEoxrzP;hTxzlkCk7ZCE3>y015 z>(u{^r|ru;ogS^33OYL$4gKPtO}?0i7xA<2Fi8SfR3-NKC9>&Oe4B$WD;e`J6r0Z zG98@?Kes>pbNE}Eh0~BDr-;nIyfel8%qiZ*O?c9sj>I(h_$ce}#4-I1(OoEH6L_9f z2#pWz3dJ#+NdKfI=M|qT6g;0bmbIXy1j%@?n{?V-xG+tl!YC)7Z0&YNev}l|d(;Q$ zmz>kg|JZs#au-+zs^#!4Z2y}N70LehcC}${KSCw_vL{m|29qdz1S1KL?$-PNL^l@L0gGoC65J$HYNQ_ zEnu0*$Ul+Z&wWG@elW;t^e?f26>PNK$oV(qCI}veb(F{QV(c*b2H3tz?CM zJ{LR`dDT}Ry@dxVY#kC|wylhy$^U7@jseEuu1L@m;D^9UgRpBH;ygwGplLCp7>`ej zfM%P3afs3in4=RmuBZ}W=pB$TAjDJh?{&JucK_DI=4`AxN`C12kB_Q6LXnsR(;(_w zde11>?zRvJ)#`}LxmD!C1`^G&Yyk|l$H`*{*bR&ZfhOSCFQ;g)%jvj=Zp@?s1X_^> zz$;&Z;lDk0V>Ly{wPO4E4yL2B%4&&GvDgpAH>CShg{lTqzFz@0{$wQd!p`?@Hh6k};SQD>yh!@oQ zH?1e16soesuKWb1x2$VQwCXeVZ?lsB>Mu*w_d}1Ee2UUpnUmWC8_nCl_`HwgFI;^N z3dEMtySNC|3=X^JcxDm}7xMf8RIwtiqby!0?7snJq7?%u~sVXy0q)P zz?$uZ%|6hHX{EIVC`B4f!VmS9ai#A%5jhT{p~XJ>*U_lsAXOHuCer$j+c*m*ecdT5Q%K<=-J%(j;R?jX|ij@&h0gJ0V4M1LN2Ea!1EeRDtzwie4jz*9c5JT#cPgUNNS8l%p%zDHg6+ug zx=+7k1*0VT@HN2NB_{$oI@hdG-I!}p>5RLOM{afP@Icx27anSqvM_^mtSp#FO}fJk$pG);c)iVV z$}G+L#%I!<{$@P#55TKKC#>O`vnj^}T79I_Vj*`Qe11Y8ry1N9zQm&HA=80_CeQe- zmj{MRHe+X+lI}_BDCUBu%#vh`eQT%p`8h7GYaqu@-=g~qw+tl>Il*^;#Y$_U#}6g< zEnuyM^GUCRiPtgJ`P~UiR>Mrk11MdYQz6ahy%`7M`|*3pJfRChVnmRI1$8~}hh5KQ z9&6kN9Dq+Uv4Dku{BPIqNlRuew9uHOxFC&2{tSD;g z0$RTy|4-yo=${i_top7je4RsdE?Ts#W81cE+sTe?+jjEDwr$(Cv3G3Sw)0Nob?$B4 zF;-_bR<{~+R@FzJkWP1e=!AL@Zy>V$_>N0R>wUY2{_osKV13ny>$WL3t@0_hrM6SB zn&B&A%O=}}{CzpI+^;Q5{RSt0*fK2VE*K&16WtJpsr2;=TT+VPjJtfSGzYZ|`=TXD zbPK8W+)X>%(+RmuXD{CV`1rfZX%;qdtaxLlQklL~4s7PxF!ncU1PJ;o)@d%yIfzJ5 zc4Al~exU<_Ih_)6!RtwD#F3=tv}#InE(cTO;hO47g~54X76~rHxVcFa3wpbcr%L zWQ$$K1H#WX^Y6zm3Cuq!MlTHE9~|i?9?k;*b!&|w5?r+X?YM1aKihK0s6>)BAbbVJ zHc9c$n*;_<{OhI@ldyv!FCtrGm=~;yXOEisy{*p}K@x#rWOVzT;TH>gy1BSBWjXvj&MEYz%Qd1Q1GjU(YM_4;P|M zfr=-0l8aBUiI$W&omAquGZn69%16PY_{a64W8kl8y;t5>{LaBGZKVAmez^LRtp;pY zr_|TI&f#BIN!*%`jQ4&uLyv@{Pj(=s4`yZ)S~rq7F+FcEdL{+M?!~lEXy|kQrs<}? z%^8F=D`+#Srdt!brvE;qv-#r{9nKSCktz!3*VpUR@5VIwR%FWY{z3duX6%q{oEbo6O8S zv<6xZvqe!aewfn0*^aW_=|K}+0-zMiZ3nyr$0xb|0^)RPQMUGz%-T@cER!Po{=%!= z>Q!Oj7B_u=Bx=}|#E2f*;rP7A+`UvL_8(v)QWm3A;*P`8N|t-^*g{V_-VR#cb4XHZ zOBdsvb441RlEFg+z#t2aXfB=c{qfxXOBd~wfTSWM4=iQ*uV}znC?cR8?Z5SJ8~MXOZ@X{``r$k9*}hB> zEIP8ueUAd?tR%-c41RaFVc7~jGg9pMQnxTeM?AKzok~0m_KIz}2PF24V#6~GtO^hm zClLht-z$%M1e*D+l{cPU`m;SGJF5cz=*W1)rKnm%iX-^x^!k}ysNN5|8$YIO>g@^G ztA6FpGlw6A>LJ%f#ukB5Kgi!I%)fH~rb^WZ3lgc_>dg|QoXN`@C{ZXrq5H_2ilEe> z%pBgbVA2fwj6#7gpd*jINe|!2HjJL5a_0N?L9v`=fTIB0r^aogxw+QvMf%mR#ynCZ zV;&RtNFJI~686ZF-5nAym;PYLD71J;78ueZ==Re57<5kr1M|-bu!K$HY281Kv19+* ztcLM*H9lI6vB;4t2;65wwr@#E(`mHL{)qM32jG~PimPk25RwyGca;9^iez+S;Vvb4 zfK(7Z3N$3j{IQybp)?)v-0*h#+Nmz|#ag2P);AACQ7bo5NID2g+TMQ#!vi+JKWENr zz@iMJ!-T1fS4#LA9Xd?i3mG`efcbWPNzT%yqte{rJn55$kE^vy50PTyYZ)}riWbXo zBA3zx*asH!b4duh(MMtUkuqlAiVxNhSR<rs{lepgV!RUcD0^e}6= z+xum2|KU*IOB>Uu0cqYra8e~mv=oQpZhRC-j;E*#SVwvw{?VI1sJciZt$WWZh1QjX zwf6o~&$i}F{yUF?*Oafb*GhGLd!3(n)=!obj%X5rXe!`blvgEKk1ks(19yWmG|q(z3Jnzs&Btw3B=ve8HM>l!fpkiC%_5txl1cUgDb5^&mz1ena+HdDygC`3z@|tvE|$Ns9{n$p!u- zl1@P;FXAEd{;gjDcLE}Srzr^=(=B3p_>fg}-H6r=t6 zJ#PQ;dJ=r?D%yQWZO#33M6O@qnP?runw1yx4>e=laCe475!@>mtO_?`A65g zAG7HRFTK2~rNWs2F$myh|E3SDcP^w|3;g~mpPqs2|Hef0w`Y)eK@OZ!es`*UU5XRI zy8TRQnDzO>yROxxi+uI!txqmC=({03w?!$2WYHWcWqQ)=H}UO2mNn*me7ED(ecR%) znOm_&uZmvlS(Qx)|MxEJjn>=IGS z4FSD~B;=#!YX$AgU+gu6nhd;QQA@S?A(?ry2Bt~lc-I~BB%|5H6v)jTxi@kD9rc+@ zOMA&+x#Z%_A8%r^Kf{F0#-Mkt>W1dp1J4hi;hGd2(__GzLU()K1gO6xpM!1`VMGm)OiQ^_csFuSB2g@L_+Ftls=a+y3{Nfv-A?g z9~_6<4K1%XbdZ(Sn)F#8fy_hlD)3tJlb+{kA>iuppLV_Q2Zo~U#64=?V_M8DHsFAXpXMvis~u0{O`NA)M5bBC51C zBUIDGrmBOfO$2u6PJ8rB`Na@&VpRF%MtH8FJI8t$^$l=H<%FMS_!2bNeVu?YV4T6B z(yP1#(TW)l%ed2XgsI~6DnL`x+*Bu=5^jiA!3{EI{gQ;203r`s#(J}n(+QIVS%Vjx z>{utBX~M-lUq07vEtP#2n4}(ip^nZ|igZ-Gkfx>rW(?9W=`?_|usRSEkrvsukOa^! zM1JC-0B8w>D6wIuaabk7hl5OIJ$0o!FNgMtjQC69X`RzcP zKaqbWz_mQlZ_JM9(Hehy;@{Y~*#dM=hW#pa=`j&y@US*;i#Vf$a|A47K1K_R7&!m1 z^|KR%P2k#qqxh`CO5GY%;F7`O8xZj%}_NTcMOm1b3deovDY zc;&|h2Ih|fSse)f<(%xj=z#aWzP@MBx%guCko z`_8i^1v;?tY4smyMt1vybSW0kObvGLJ(-VV`zmB!H{I;q)Ir39YWah4XsU62~)*S52Y5y~-pY24<-#|wUu`Ebblhxzj+%3LTEKEq+7 zT|?`ycTlx~Sa6Fphj7LO3oH!8fdUDzx_PweWvN879eYTTuB1C3386WhP*}C65f?3YiiOQFtTx#Uj<@sx^MXnSrJhB!jH~O~O@{Jl-ydQDF7pH$P7z>q z#14I03w%RP~!(ZXiQ(Saej-vv7(o(c)$86ToP$=m4Iy&UV2H{d)3)p)Lb>)(ezB2P0cvNS;awnVltMQvpaf75VzgDl#ciU()5K-N5@540XV#oeIT^Cw?(fSFoM57K7-rf11 z;2I4t#7>uAIl}>W$Z&8Qhkda4jMkRoIv?N`Db7i5$Yzx|z_bkd!^M3_c(!dB(Aj&r4WMLq1A`%D z$87o5KKl=B%S@ungXn0S)7ev<;%reMrjmY8utcyFbsA71Q~$PSjp2=i*8$ITmvYwa zP$QN*1th(n`;DPaB&?5w#xP%Jwi+?YcSe4Xh%^Wy-=2WrZ8LLuO$$<9*njO{{a4*Z z`*N8l-CjCNJqf-e3^)FkSpc{N#oD4Umu&L1H>fD+@X8l6V70JC(4hf|#n zQMuCW$>qMgH_z&QjGLSqPH;MLW1LHF4VtZ9F?EF$pSOgt|8JVPI?AsAz~$}|I4mUydg#HqyfF~Bnlt#z2V^QFO5EmFI$oI{MTNE#tz?(} zL&TjRjo~ijxlo(SZ&GPw1B_g*f(?xWBvyCT?+Xx`ddbibNn)IZ3J^+-M5Y0c0sZ4@ zJZ~EZ_5HPGkU(2eSd0I4A6j9#c!hshU3n7(*qN1B*d(|2?MqYwgQ(M;CP3?Z*E)@q z4@KtUh_ZLM8~q3<(aO5qpAV2&A}A%JxCIVkSoL&kUz<}bqU-coJoVoUcwG%z7!_bS98v#HeE2!{HX&$GyHYRe{tcV;oj?gp=R znZ2ac)URmWNa^c+s17*ux2D2@LK^iZ^=l@rr<<)X57@O8ko_dThdbpig|wF0--g=d zPl=p;Rkye8$nj+OT0-S7{3x%EOio!@`j*6eQILS~e)&cheWQu^xQ13XQ4NQ8C?5qB zz7Z7K)k-9qKMt7EHc!y9{}H@NA1}(dP>hJj|J%emQ`md0gP!plpT|-$_K{tf;FxUOrPG)@8)-%BbIxn`lk(U&=yJHx~Z}3j-onFkYB~A3-dWr^>;$BQ{ zO!>uo?e5z;sYf_lFJ<4lbM~jZrZG|no%azmyZ>6iQ1TsB=0eJIz7#8KlKRl!d3X^R zpH%SO_Lr!7dW#@2Sa@ME&{%T`p`zWnMwQ)J1R}5#z{m4Et`H}QoCDIIT-l8FqahUX z)^fY3|6;PGy(OOnC$RJR*|0mZ)BSrXnw8squ!DzaGdNsslB>-?DD)xhN^bsf-C=5H zOK1M(N;BbCv9|7iEohOx=nQa!GSk5rqm7=4E<^QB<%F0AFb3|XL+z3}XMhbJK2lU# zS?2y_D5XExpWDWjt!D~dEx5FN;#}j{*IVYhN6{hvhNk*}m^AR4IJ__tAU>XUd9kGx zdXt2r#K0&ysB{WSbat6xv%Pxdqh4=cAy+Q}^hCc;^DR}Vvy2-SLAC5i57`TkI8JEc zZC8MYy(@o1sWTa$^t?QR7fjcM+uQ?7X4}Nu=d1ONE(-8Lm;oHE1+y%Z6!^U)?5@CU znqqwIJV;~W{gIx_3i)0j0^*gC0v;Buk=R14o#)G(JXlaT4xgM))B?u|zIisxEM+}^ zBxZ_9hl^8q*h2bqhD8O16VbS(E930PRVAPioM;6X&o;lyQPR#IdL{#K#KNC%H-QTW zkNHc{ZndoIH0g{E-{QCL5TZn?2qU2ddhuE+wl7FIOm=E4D~a7djzqZbFNK+CtQO5g zFOwwtM}RAux&Y)n6d29!S$iJ>2h~~`3A^mp*qI9nv&xHW@cnmRKuh2VxUktkZ6SE` zjBJ8;@#Vu{59=JSie{)mRz038+`bf(f2N@J#m0g_BUSxv6da@tx0)>sX`EViQhvyw zc`Y~t*9tf!*899q1Cw0gL~jU3u@lhC8TBz4!3<|<8rt-xpN<_g8b&3Rk}$O{_69@d6A-FZESuRkvut zQ4u?mBWb)rp|IRWPVy}J-qHirMBUz?7^`;PehPRYeNdsz4HXR5Q`}v+32&38Rg=sv zGvxBt2b9+{3tW=NCki!!qQUfPzD7Q1H1DE`zcwkGyOqd3YSuWLLP-fGABT39z_ee- zcG9peoeki6UBZjIb&(&aZaJk-B_?N-_|CL%=!M4*o0NLEgfBopt z7)`T61l)wb%!EpvH3&Vz?7SxNl!h|*nK+hN(p)I#S8(;10a${`10Z3k>7I@g?V9KH zXfm$zLLA{e)uW!+hXXK^kiK}}v)RQm0gT+J6ha@BR6 zVnVN7K?PpVRhrf?m9x=9G82LqQ(C9=h3NEY2=wBiW@MHkBIX`T4)l+c2{v5;Tmtm{WEgv8+ zX^tb}rDn6v+SONgg#|eE{}yN9XtcZC6pjaUOK{$w0Z{EHoO(e^BqC#|!6sO@2s{VR_z`YMTq26@z%cfES6Ip^=Z zYI&!B3QGiYP_si{U+WDgexYGcKnc3ixZ|->$hbOXjjCyy@H?-}%Gjbc;b{`Xfi#;D z$jve}c=$|c1FYg#W?;61mXJq3Fl4vkwVfCn)XsExxIZb&Ew)j>-**6t5B?Bo1VH6l z7a9|vh`!pydQL9|zCXl}T8>+kkZAMoYgx#_WhABid+lsF;~d4qwvv`8;J;sy93vQ; zS~m0;e6fYHlN{9faSNpANEv8)PTq9k?L_du{FGU^;Jl8`fggC4%2VlHj_J?#H$0qt zfabPL{!J~ozP*{O{vUTKbXviqugE*!CZ=D&nJHv?fJh)gtKR(qs&)hb6P5bl$Fy*Z z@H4k53mU|0)d%5B6A9yj_1;yIj|KP?0S(BwClW5GB(?W|&vB+tKRy9WJKp=wfBcl^ zNVx7L#ZN#Az<5W+0(^Bc%|z|rGf#~NnKep_D#BY%e@u?s7Da2=a63vGtd78Y!GxYo z(q!ID{1gi~FjCC+)1cXlu)A4al#X|kxzLWItT0RJ=^dSSjau33-b91%FaH(X0b4Zw zmmX)y)Dya@AHI(DAF=p+QdI4x6^YHCDn_-?+okQb{CZ)IXe(z=T8(C62WP~;!tccG zs-36n=p z{6hvLDEqjWk8^s%?KMejmwXdwT8&ne`WFl%}>dAGJtR~SN`0e(^l15O=&x|cfX{% zBOj>2hs%pg&ACwe3~hYWrH~h2(X^yLz9Db&<>xle#BP^JwK(>sHW;}cT zWo@CztkdQ?M=3eW0T460u{yYhuGmoO;gYvqu>ylkFF6lJ;LNH5%j;KXfPW0u{dBoD zOorsb=-G`F&ECg@jzlilIr@qE3IX$Y4M$|M<3KQmMa`hb)T}p1D+8Xd`MMc@tGnMS zpX)4Duf;70|Le_Ok%F&YQt9GQT}xWQG_EZcAN(&UO~Fi#lUoC$XS8xmZa;H`jEg^| zuWXL13uhy~YR3^1onN<5?r*KnpD036Mn@!Js$8`NBDl~pWX&AtJ~=g8_zcM$IOoFO zpu^+d(0HiaxME@0CZ&^j$UoD&Ecy0&aAT9lVAz7SXB5xyGV;#HaiCnE%gYU}-W|6> zxLv*1pTEGZ<3Un&SD5gkt6iNh#LI{rk}&ePsmyhdSxJ|97{^`U$I$xvgb$+d$J69A zF-QqnO(y5F;(5S6h(7mi6A}M;B-F6+QM~mrE!iPl+H@B#Ihk2IDPUYbTdxdXI%n+@ zt|gC+z8w3GTEilCJStnIUSVhBj~=&X0jTFdxWu{F}4f8Hy0%#iu*6l*c1ifP`) zg}h7d5{9(JmZE=?q`}@4OA9!|_g4FEP40(Eau1UQzy1J|g^QsY?Ge^^jbPY`m-;H9 z>n$N+pKpU}hmvFhJELeD)UMMAigd<+(Gu%X+Q)s&5O{h_M~!cY&LKD_MpE5({#Rbp zqHP-VlXkx)TLGfr3nXagSaINkay93$y&9PA559g*&x2c^f2s51$h4O{G~pJ&f3An$ zk2}!J5&7L2rp1k64diL~l$mC>?kG?kKo7*k*;P#b)SA0W4h$r~=l1It5g;sENtFR} z2cZ<05deVn|5?c%N{<7CNik*iab8uTu=29yM;DBrZ1{Y2l>?I*sxVIFO!Jnma4WHk zF-s|uxK+K#Z7XzOF&w!OGbti0p0@+9Za3%%l}^9lv__L(Ug>kJG2m>&GKQv-^h;(T zNk+K){@rmBL&}c0)?Fnm9{v43>w{!d^#}ibO**n5TVwT8ch7;(lNpC}ID^zL3Gi>5 zU1%#BBv6t9=tav%|8)p^;Ych`&5|O_fYngv+@~4W94AM^8bmdGlUZ7VxIof2A94}> zl;d?kju;2rprw9yTXmn7dt3x0speZ9mtO4?z_w=<)Xy7qJ~k+5?pzLA6(o}xJb8F| zm0pF}BnYzU0xv`u?nCyus;rvNNKp<8bsLdVBkVw^K$W0Z2>$*~z3fP)cUz`tK95qW zyfRG0y_`_(8+b{6>;WIFU-5tXV6!j(`76*)8%;Vq7v1vg+E@V|Ny7d+4-Z_DZ0&&( zsNvG6^rGs$ZqUo>If(n=|3|Ss298ES$MiA z+TshwExBSBFgosE-(EH_uy35Uxye@2i}vCxi+o)RlEnCfbX<3eVRr!GIm{x$Wl~m2 zIMJr4mj@`2#8ty3E#zv-41J90RZYPdnJ>E&&4W1$=bj=^F3HBXo2hG}J=ZqSEkx7* zO)h>6o&Uu3o__7ox@xEYskSgS`UeWdkh(%Y5rX?W^!-H`OZ2d4!Ovl??n3FWDZIgl zA<+_ydZ1_3#S=)OS^Pa6nJkL~w(eydu$$RpM7EIFix5ivmb@?5H`?b7)d9sq!%RMok;psJ|NTO&POv5UD~J3W zlzjSrHw#^lo=XPw_k!kksEC)2Y}fYif;rOUL6QB6-rX-z^kP6naW5zQvuBDl?ZzTi z8-f>~ZT*sq>M&V_H0FTt^ z!GgZbj|K-P%YkG+PuUNdh^MG$@`1j@JADe-l0i|EjY^}$f~pPI{Y6sDr4Uwb!_*_w zqOvtj0iT+e65S}4+~|SjH~{T*$=ff*G1B}pCp7bVVZky3u$K9gNO`EZn6Ebc8V=_r zE?ziE1gn}@Oqq?a;m@o()>wqc?$%`+Qnxc`kXZ>`MM0-(JP~ADh8TTVNNkN&9?XKj z({>?t-%2TMU(DAT)2aq?O6b8Hbz(0gza4xJem*?dlG>EHFCPeOIS_=o!`R90>e=RX zKO5GBn3aH<8fmN}I4d2RB)H=cVf`zpLP(-c@BA^T`WPlyubt47>O?z@7REwFXeg1$ zU#_dhYjCYXIAo%~NNrNGN8E0Q>8)R9T>rZUGtn*Mt=`)lY;+F?A`RQ@GJ8|-sqiz_ z0)*|Jq;_MaH1N_@&E1E#?{D)$J*M{i$~9VOFt&J>lE^3inKkowP@@TPTD2f|#00;BlX z^FN0-7LYu3RYVsCS9$R$6BPm;!t)JE15S8!%A>AT`KtX!`#@3S%cI5NtQ>_FLc`|- zN?MjkX!Z2Q^I8>?o}f&7H_hJ}kzM_0!)3^Sjv3raQ1x66xH7?!pA>IE9DYTp`0;(n zIO&y+U-Cb>mp87`$Sv}}oj<3dzvyh}!dq$LrqeRbiN}(V3OR^d8|^>xOi4y+^*&zbvI33?nED!@@fjpHlX2@Kg4_rtKt`s1 zToNX~ifu4-j0&8H{s8^+?c`eKtzd22zRo24Ufj6=G(N&)&!zkug_Fnp16dKbnU=A}HJLTjyLmYLR+?r)*u+wtdy z9y}$6SxTwg+vbCF9TFgeb2{r8Hy0mm&nWRPGtgGK9J$;!PL2)D#WAs+e(<-H4SiTR2@FDrH{alWJEOwEU)1AmYNI5jE%CAEM_)#;Hb4L0l ztSlPfJ(G&`Zd% z_gG}uwdQUmd94R+`zudGVXJmG(Z=;5?a7^ULwgb(O4$Dk@YMjghz^D?7ALyDUe3b42$|~i)17D& z-c-bMeEYGq=tgWZ;j`1J_6~ML05*pSirk6gS`NvojmN%dU8$Ln5UaG-{L-bi6-PDqu*C;VUz-O z+(OTl#(X=1<$l!f>uNHEIpX8fIV(s&=ffrzWAGIp?}TG9n|>3&Cd!Km!6PlBG4W>K zkQE8P_~g|*e$q?D$BUTxf~0q1HD2``4c{W0?X2w=#fUIPvb0CJ*1))qKndl}9C`ib zXy2fOjem%lK8mas!sZ{ph6WwBQiH`8yhLu^Gyv%X6lPdujunLjvtW|!h8!MWb3XwE zfMrPT2dEXj-!@h$=^uf0AHj_koC1*Zi+Ay*Ex__b<_cM=?q%@RQrFH{C9+om=NJ_2~HF+W(?#W7r7WrsMYY#O7Q0+<6b3kp@Z-E)&I1I9nF9} zrU$M3YwiMNZlOcra^F*9%u9B91_L!CxSHz-AHxopm2P4= zsv2H{?}UWBNoTcZIF{?I_kYNIKUFRZPY49@fj9UVN;y^HMNMI;2~?+09^W!8(nWkv z_ycbygN4~PA!cb9o>0-zCG|+`n4ej`+N%y=ogN%b)ObvlZok9u$nb%_l`j(3OMi%` zeXODEv$Xqo1&x?}n~tkVdMNnY!M@1z1XK!F?6q1>pT7NF!5ppx0>C*$fGU*!=J78Z zeIVR-LBL;N7J`O3NKB6Pv1}Wh3vWKsenQLhF;ODj&ym||X0#=OrJFtZ1y*EZk=#1Z z>9&3t5$5mtaoWCdq>D-3G{)~!gjv6RkY{QH6vZkjULU+@H9H5JjCSlZ1 zP&@9<-c51w^>m4;BUj$PcX)@iVH*CYAmAs#qJg0mA#O961>P|*9CVZ)eR93ldY*__ zf%_II>!!imSMxB^xC+F0fBk2LZm@=K5MU`kPkDlcS5ui@jgz{?)InfT;IYQjrxw2+ zM4E$ocHB90-C1t6(gdrPHC^ORxJtxWlO=oDqLkx~(@gQ6nR`FrmfraJ$Nvy8X%9lF zo>aIu_CU-WaH$hpa)I-F;97L71H6<~dgb{aHZXSM`r`RQDIG?(&9KP!I6_%OE}t0{ z57o^5q{K-%fqA7$sO$InpTSV~A5z|_HD9xkS_J91Ot&cXHrq|~%l0G_>}x(xyu03h z9h|WQSlyI2#G#IyjGgOkJ&g6P6cI=a8|)W?6%4TO}A@Mm-Ki zZvw&cL7{W5aSj5mCZ)Up+pfwV2!aS7Fc>Aex(>t;8VePFeq2^1al~{B2JHSYIK}v_A_Zf!a@*-aH>MSCX|@}!kl6j1#s0GWzu|TNFdfGW`b>^t@*Ly#*GA%yAOG{+ zZ3z?pldpUl@>)3P#kHD%t;fQ#+;Z9_NPNI1YOb{26sDHnYb1jg|L|2)6DwJ z$3h51QPv@y%LhW5Q_?{Kv8Gfss9h|`iTCOJqz?mg=Ejmk)eJum%Zz#icKW`?C33_O z+)hnqY`1tsNo?izMo&{QDH;x#m|zp}MrAkYXlRR0{-;OuysN)EV9jL&(rzcQwhA&V zyFmM|IYos+KN)$NYx01aP{EZb%AIo>Tq@kkK5W7n~~ECmKGIH;Opjs%sV~M^k%q{fAX=9wjZKufyQ7Xpm(Tmck#`8 z79sOiy`c&lkzcab2!geFE%d6{b6PK&h?~Mv=ye`!7*$)WC|{LBieG~wF|F3FHA}8@ z{WEbyjcCaKywXD_fs{Zc&?AT`8A^n1bdYSuv%;_?&Q`Y~-H#H)Nobdq$19<66ytu~ z?z!%R(pQ2=P!;t1B^aN3;)i81n7{-A!Qw4N3qk=*4`T97f$nf6YMMO~aqAxXno%)a z^K;mj?IF-ji^m{^0*0m4X;j9%>bpplX>BIVGwe zx63v~+)aX#TFLf~6-IqD+3YrM^SN}Sek?Tx_O4!`XVg-F5Q2+u==VNRdDdONL(oY0 z&)}KwW5ZaslxlVo{cgDHZ8ki^{`lPuNHrnoHaA!Z&U{3s5jUCK=XuWO>zhR+%AE`^ z%irMr7}fbBam;KwWMxq!iMo9(nm0fp?Il?Y+0az>W;U@J(^p(0diYnaZOr0;%5xIc zjzl#!Z3Rw}gOqZk3G=^fEKSUo7-+b`hRt&dLr1c5aS+gyltN-T_vG*3R3#G~DZ~Wd z@TyB7QNzs;O_`WPpII;iPxeC%OP-(jaTj|pXkIX-Mjr%B9#Rw33H7~m~xmVpGs7%*k5>#w*2PjiGf87s}DIFc;d1$ zHYrOY4f>x2L?a!Uv*R+oH+tJ}Vw9(3X0PX|DPaueeVY8^uietS8I7{q9wv7~Lb0d{ zd)^!2N-&2~Sx%lfHyjb`(sycYKq*F!;NXK@`if0hLf{MekJ7C~9<@Uw4o&%XC?G7{uJ(1)OYe~DrwDKTrs#sv3-*I!iuEAQJ z)|1=^F5mIRF)No^VxfmeGUG-zh62y>kbP?3f6!#P6HG6GUpO|j5VSEChn5_H@wgoD za!XV1n?opmE-qo>>CVj0^=Xj3D|0}Zz)1JmEfQdn&FO{v3eUvrE<4BZkHjr7f{cDk zEaDYO{Rcl>KGosh@Og8^?4Oe7I|xI(h?XC#E`M_#_+Qp5(<@tEFdhd3D=)~7&_!dI zlKarb6}BNT87Q>`ZD^PL&?}SSuSa$-J#;26Y9Juc|M5Una)!`nt!YU(0Z)8Pv8JlEi&#u%+A5u_$mA*3Tnoo^jwQ7^6n?Y)mHR*vb)i zef=l4|M8oMP-W~bAoC)-S0_Ih1}8Brpr4LeNyR&Bv+3tbxtM??x^4U?uSecfx*li# ziHxOOU)0sL^lu>hH{I#!u)?-o$l&e#Hv_gCrGL5p%JaOR# zF_q-XQ-%ilN^2h@smEimJ^7J&lmfnRKN>Qu5ajUwO!V|*IyD>jSil*sZd4|X z8N9z{z#>}7pCkRgpc=Pa>flCb96BO2JfR}3j2b-Q<`aqc9T8g+=_emHZHXN6o~0wgxow`CLyalL z7)A@uNVv>Eh)~S6eHx#$HYOE<7Y6h;#e>q72}PWiz!tHsu!7^m2QH5Do`e5zFr!a$ z>>`frS#XyLgQVo(BXK@=JW!XzQfHK6Fgt3cfJb9 zfwPPSP~w8FVA@H23g(AYNe;|DH;>(*$CbAaIp|gO{&~);<^wobAn)V5g8hG8oAAsS zR@A$0%jF5molZF7g+S~{;HV5Ht%eHq@rQM~G~Wk^aai8GCCgmQld)*P`yMN+n&!W* z7f|7gPe$iposGbPXltq#h)K64Z0#9BQyaW98kJRe<$-QcTi;W@7E-Wi81*)rl zb<=G{AbrQLmq~>=5-0Jxq0?^)tTBFDIsIsB~|pY7^={k2Q>lD7PKxy-pN_OWkbtj zN(K)OJ}vO57WH}bSd?5iXQfQSdo`a>+_#==J~n&^;#0Xl$87&KF?P$O89h1U#&cc6 z{{107f*SN1xeqir6PRafsg8WGN!onigw=+yD=2Rd$#E11XXK$YjDKXST5*6v-M_0eOhH1gYpNab^Mux=7t&vFoi;LTlJLJ z=#d9FNP!C?40gt7LEsq!oCk@KYv$s)NI@2lG?q~TD-dxI7P}^`PbN_3^-g(wGi8xA z*)w|Ddy$&;EjjYK6s49nJ;7}VvzF{qM~1=xo5Grr4{Q(WGRli1o*=}*ZZAA&KJDpr zgoR_24_h_CN*(mDfW1vuYM)@KbMQx!hf;}5Isc+6D$ zQxL0@)4F-8A8*+DDT)qtBj{E)GL>de-#q%jHcJCV(soh`XA!y;i0Mb~~^*@?(v+`vAR2hFV;Q(Q(7T zA$eg*^6N2SxO;)Pr9WS>8}40 z;X(L~q-BIf!5>U1MX2&T{cxC4g!oR=h>qR=&g%?`MVSDG2l^I$GYu%aRq5N$t}v82 zUMojO_zW%6P($mCDwWbDW zl5$W-+7l9})P|&yTSoQT=+hleXeGS5BwuTiW9brBL=HD^e}zv>hTVJs;{d_uSK`(> zc#*n=D|hr^8O}oLXII>(hW;7(yv~`Mzq*XxJY}W>JQJUWoTv;G4UB5CAGHVF1gyZb zT=Bq8{kR;ZZMV-WONdNQW{UC{Yfhjup`1f?ym4t0wttvp{2RK;K)%VE6ng3PZfNON_D;!B|IpRK5)c`ueVdJdu#U8O7GG=Q zd53>#djAhT!$tm<)P-EkALmP>q5>4;M-!pHmljJ09kx_b_DsTgq|n+wiP%?|^%9{B z+`QQ;{%vSxu(Xqirn5>h)`N&L^ZEP}#BSkL^p_MQsRJ$07$#f}F6v9ihZ1`~j}^n@FZNSH4C%D*x#}=<`azd+Gn~DN z$a)x;=%uvSb=w;kY_5?E9A#mJKdy(@JT`GN?dunW;061P@s*baa^J|T*o8qn?aj~A z;Tu#VGFtm@FtJS6&}B;*zb)%~j91@8^o|R9srC9||KskpCXzdZC#dBA15QA(ztX~B zA3hcf)!7l9L>d>fm%p$MSoQmw!a>2;iW8m$!aVFKTc2d)pee5s9(oy!Jb%0ac>S(h z2H1_Ui4aOozD2A+Fy<_u>U`TQC=O^C=k^p=T2 z8(7Tmg)I`y#vzT#y=A0M{@FdR^D)nfstb))2XO+WaUWt`#tu=K>gn-Fa@Dk#`|V7K zYil`>hObro4z}RWN7B3h2}pNot`&IFajXmh#(U1L_)OLJ^DA~Sj@v$qCZX&JLlYkI z>WYhLE;_Pmoqt+Q)3W1?a! z2C7(F-$;Y!SJ!G;M%F3K{Z2q1)Qcr8-(RY8m9L6jKjj5WFC2kFi!d~yujMei_mqu1 z4=xU!50-zTP;V;pNwz=gsnJ5T;79$L6M>&mL(Hs2qu4fD`Y&vF8?S|Bvo+ZY;|-0N zleG_%OI)zwo<#dtNy=OwI_na9Y@~7`6Ji3N!u2$0!CK15o#38O!JqR@F}flBwNkK~ z2c?Ys?j*FBneB=o+)_{(CXArNN6Aons=Nc8wc=*X27Ni$%TPX=@&cKOc15o<&>5Hi zd@RwES(?sugZ2NR|B;rv(fJpibbigwv*L|6;cijt_V4DFw6tB|IiNrAWO zl`4B5RnK9B8ix-lXmnOWUDxf3wf}J}scH(g?nq>}nd`X^Zs_6+j3^|)2hZn}`{bW$ ztuZoWCLAGzTB9~&Qj`4l@d8Yej4vSnEPMnzSa%xQBUol;+4*AL1B9{ZZg{J^LkEoG z6tU_=*XJ3VJ`of%*}9<~Lqn9&j+O@KOT|&l*=`-1>eb2K!_p@^I}6v`tYS_ik`5Z^ z+!1I!DBQ+w4D-MWBnT7QQ=8cyKR8bb;;mrXhJbJs0Qfe_5gB;fQwh=R3YtD6FB)iN zOKB-6@pf_wRxfowFWDm6K(?Ad_rAE**Ls{7_mJ3^R zny2)QhyxMwcRVIFbJh4>EB7?+lP2`WfN#PXdUplVc9|D}q@aH}MW^2g&b^F}Up9_F zzX45rwN5VCj`Y>`tviGp>jWLK&h*^yuRK8zhI+X-!Xf|SlPaJ624j}Ulw@!nJrgDf z)neJo0ROZ+sqXHPFM3nX6n|R9hhr*XK*|NnZlTilO*Jmz-w!`Li_$lLa zR9`-k%5R=Uddu7EGOFWyn^~-H93uTRik>TVW`(hk5>S|%4gAa}p>9_Q+DHH^bY)kE z4^Yn_Z5Ne3>ZwIpD}0B`%OLc6*W3($6V&Vie5RG?K`*`sc?sc<=%B<^4i(zJE)QQs zaF_?Z(&)dx$9w9hEw08nif=OLs6eRzqwB~R>A{1>vH)aB?uA3Q6@mHV-9AiT8S{z% zfungMNQ2*zXt%^2mSjo>Y}6&*3cy!Q(t)TVpvOxguFsO>qtqVOW#MxL^?d-4n*A#X zdbmbJdqmg5Iknh_aJ=Bkh=OIb151-~<;o}Z9nqQNFA;|3XTju#`bm^TH@SX`Uwd*0 z{fDuq5JE2%L<*dq)s=-acjcLxAFo@X7JaRxtQX%qzkns9VHFGIX6}*xFBz_ z>am(@*KfKe<{`grUP7?eZobl%hddx_^gY^SVQ-(zWeVIX1uK5S&Ie0>?-q6cbu@|^ zjq_c>g>A-@d?5r?l?uhy5%-9@Yu?Yg7q}o^0j~lO+4L$oWoyqdli%cSGL%1TRZX(} z)8FR#Z^Z}dsCn0a`%e`q9H1~gR`8DhB3_I4@5NIBI3Okx`!6En`Hjr8BcL;|jCvyuRg61@ zK((`)s&b;c?uh`>$`LIV*tY!U9m+zQO14JoWE9|*Gxg;!MP4+QG*f^ucPOQgRpG4n zTItlHrjA_}rlv-hEB+y}=;*&PsB#`J`Mw3@kaFL)M|0VB@i`#!YI8GC6k4W9Wc6Yyfu!5808w-)E$aJ9^AzQpg5K0YFts6u*cYlE24 zdtfZF-t6smbZsPA{f-0Qz&7sn@bSpOE>ab$uwQKi+aTL}agmwEMP4s#IJaa@ri?)P z4#2$}gp+<8T-?{Xl}@^`ni2=Vh^A&H-3&1O8!&$W;y9cLwh7(xn)G6!%|15(&d$xY z>`_jLp(#9%A(>SDcso5zTrn&%t1x>;fX;0McFOSVK! zS7z#U8l9pAq9 zZuJ++X$M%{1blwOj%OeD;0GiH>u1WV8xV8~85mxf8j0Y`M&H+pmd#o`iKgn>k*KBs zuesP$sq{T;pMwv<+I}XcpF?ejOw_!_cWLFmx2C|k_e-Pw7R~}0$8L5+A!+sM{?Roi z&$TozJbu*y75B}zmL!g;YF7b9@)3;MT=#U>{Hc>a3L{A!lx{Bzs1SlVr@aE#(0eaGJv-A%JGY_fe9= zNOR(-{=(zAzb0D(YL9_&U~neFv-Xn=MSFYR*omX|N0?#)!Qa(2s^)0 zL%=!yu#W(35cuq6Z(Qf0Si=pNiZ^6!0BE3fuW^(q1hlvl=fel&#ga*p8U{f}CT>0= zIkbwAYvP=9ODrRPmm`xW6hY{(CGbL9QvK?+Y7mavDo^AJMJFRaK^;>&a~=gX4JM0W z7l>)F=aB7g z&Swc*w%QgiUZ$ycJB(S8r|FC`noaD|`Mi^%!!m@4v>B>R^?6>Mp9_c4Kqc^2^)6Y| zYMIK+4MT&cjPj>A_+6%kY*0OTkaB%#UfKLbO1&fizbT`op_3d#ZjBPM3OtGO_kRoI zt~s`ot0vfI%TXr75R~GjZ@Kw|_bFfbxSwoKBhGNyp!L42c~yf)@nieVLyt%$CKZ`y^1ZBlK~3|()TGz6bk8{_I^Td z)$$|azPfoK80B%x;?n-^963r89edoOJAr%bAlC0Ja*$y1TSdK6qdTi4U=h|q9e>t} zXD(CehkG4rh`3WI9@#HAI#Z^R3N#hGpLSj_R!uoWio_4iN%>%qyfHs!;uU)uJ0)8GCtGO`nu`(R((W3y3EHE%d;6DU8*aP1>YE9x;rqFkCL zWtnYD+~1b0FB8~05BQwcY*>B@b4dzRuY6oC0(Ll$ZpSYxqUXFgq(XQqh zx>4-3VaQ4CMaEH9H3PEw#>1)i^FoA%#Y|y&59kNA8G5Yqz8)QHi^O+f%Zh)Keqh z#^-A(%Oo0w1^PMbA3X04b*!Q-J=Ujdkwg0qC4%n-kW@yDpVV^p2-#1$ZIceYDGm74 z)`kyv?@ZxpsW)8sC6DIHXblL?-m`;qpVd+o$Y(-zAu_XrjNi&yJkRSzB$vi-XMOUt zD>O!|t9X&BI>>;VGxVG}!!qyI?)MOLxYSy0!;W^!4_?;vg)Jmo1?%01LK8}O?Pp_k zS5EWk;(E-p#Ho%+#AKiU^5>YW;q2q3rLi0tKYMA!hav!yqh=rE4! zS`~7-ro4v5{L>YhF83ll{0`QZUTrb53MUWQT5gaF1jhj_j<|W$Y4l;;`4nMo(F6m- z1OCi%mf}dXmFD2KJ@cv$tnuLo)9#pKk=PFG<1yN2EqB^Rr&)GA) zKPrx6woqSk1K+l&#GVf1%f1OZ{L%Lk_iO7A#p$hVtA+wl;QGPsPDf(xl5}6(Z49KO zE&KXjj+JC4%LWwvw0hg|K0sh~{Iw7tM-G(!a79rXe`Qb&)LmZ*y&oPF5w+C^aWLi}PBz9~6_*f`n+@Rq9d@rG#U=<#C*jacCHj zIn%gNxEAY-!^mNVwHFb(SjxUf154yk4-P>R-H(l)J(6ACU0Q>=CH0FkW%Q66r(z&5|RXn z-%Zl>b-u4%eu&NCds$667^Er52t5v%DGmhq%D+-mR`whT-*wAMXrvqrAfYpG9VmH5 zI)u?q_cq^o=%g3wX8L>@Wm>Fs32JzIW;@Pc-AUoC7cSo{69kN?`jARqjBhos44jg_ zrzd;e^Meu6GruHbK_H|Zz7?l8)d|GxP;jz<;|NbWI&XLrpv+^wyw-D)2`EvRmfkfGI|Hjv2=5P8H8x2Yk1xbBd^wLp7F3*RxtKr$Cme`a8( zUK2YlIbR~@B_tXC`HJ(C12Mw6a}@lg)T&pScjCH;rvY8vQ`xYrG^C=ZNR12`2nJ^3 z7yEcUmok3KLtmkK2XpbxW?nGRfy3xVkvF+FI_-GH1-25`XEZ%+PZjowK`$4vC`X>W zFPktQ?iHRf=5&_G=!bJiscL4qzp4}&QW#Z<|G$Z)qa07q^SfU&MEO| ziV7toGuBCgPOYB0nf8#U&u3qp)U*Dx#L<~z=a&9|dsO#dx>3I8dDm!8NMW zTlj+W@a4oYkpYYnvv+R@n1|6#3$OE$ghRG9M9X@|V!zv|8A21P8eQzI@sYs6k<&WG zGdHDHm+Kd_hmPg`E)pjmY`x%^^YLwzb2j5gvXfvW*A-v>eH8IOL*ASyr-$8Ojx17C zSJilt7wLDI{BPFHMY~>(Kc<}?Dv6_qXIM+aaer8prUArMbFCA5)X8E7;VvI#UlCo& zsTe(~dQ^SU(b?QV){(22;kC1t@{iz&JanKjlz3ZbrTyA=m!xx(dauGmJ z_o=*bQPY)L0c4r+0*_z=F80uwbA73B9NS*s^xrOCPI{yVvlA|e!|gl6u_M+odNcoVtBrRE{e(F{&VyQ_*8dpHqniCBzs44O> zWwbiodp8uyfyQn!LkGYl795LHZMJEeAh#1PC}+AR@wD<1yg;oYcGEOyOhX1WzX=Hx zNG32!9@xzkOG|mxrP_eBs%juHt%^hzdgMw82kU~46T~7qEJ4l>Os{V+DPV~QA7Goa zMD7WKw80Sllk=DdzDo!0(z0$Q$s^|So8pHHeflO}-{eJTq96|7A`svR*ZzV3)LJvk zPkUwF2WcXqc$fmi=$Attqb$m?fO5*%MoXEDWQo5Qm>jz9roV1wPB(41%Xm(cO7q(3pVLiYAUR^jCD-R3?qr!GD{$ z!3g{@n{uAaW97F76J)yr%}*`UH{I9C&2<>~EUA9=O2`2A(+v4*zQ!ny}$HTC-!st2$A_OgWT?F_FB%>`=*73 zk8-77X$NVR}JzxRI2*3~a~s){=<#dob!2`D~CE1jAfXuXF^7*O#B#V`sP zuECj$Wq4x#S4C-hH{@uxbvpQ0B#Ba^$-znubhA}OxBEW@OF`pNY*m!+MFAS$BFaeiRfD?t z7wOkITbssCrqQJk@FayCl3XRfJ3O{2U`tfuKr2-u?%oqIA+NtcoNa_3uv$cN{_DhUijRTtFB2#^nMMu*3#as*TZN z%kwI3+nN8OSnIwG94mI1T=9le_{t3#R9=Lx#a&Gp6jvJ3i4XRa?h~b!c;; znupYS>1P)9qu#^$`xQe92OFb=`$Y_N8_|GCQG{i&m5F)911Y5UZUEJs#KZsbZ=J(- zd+bxrt#6)IE-)LL$%zd;WF``57uCQsvZN!A)5NzZ`bC(D+8tMV=L}^AKb@Vsl|fhS zX&iS?84G^|xNB?;e}S)0$MH7bddygGIlQ@bFS_AL#27iTKw4S7!KKo3gd_(^jqnZ* z2IEHSa?nE9+EJM~)#ejT8drImlEj&GfNFSmp8|81G}u=^UMY7 z-!awP<^2X_n)wo;5fk||=%>7)65~Yn!A~e*>2D<#EdKzO)TZ|Q)hnW@E>#u7s3&?d z5rqOcsr4skypxNx&@aZQYD0D*LK$aIZz_|kF`=O;{PU*UuC!x#CDuQguzHY?-yD!C z4nJ1nuXQo}9j@_@dKcFSIl|R2l_GD*FYm*#W6$GQR10b$*6h!*7>!aj7lBXttiDu5 zLE05Ns9E$vWOc}3>T3v6z247mGQ_@AL>=RR7hL3w24bm8J1)qfe;Eo99R9*8Xna_P zSWu9gjS8g%-L#UcA9tV+(UQjk_*?@Lrn12!x=>LVs~6}KIwqiC($OT z|KwhjCmDrYuj8C8o{KeVI;N7Ed1t^6=noZNLG|zbP1K2gJUL2h0c5Fnw zC$kPiA7_=zp5v(QRHxB88)fSE#5=?Xf(V?jk?}@2WqZ5Q;MX zOEHPsJ9YO01+u`&EySI7yR&#D34G4-{kz3RdxumEg(Z0jhPh}0pHbPPpLJ+ft?w4{ z4|sXfB`h#l?&3)nVHfX?H7HqZ#U$MIFP7BS;hNe0;LA!S%pLuwwb%!4r6L_m`lf%S zD5_rG$5>9X5DfNObZ-^bj{?aV#=0i@ZNBx8IIZ?Ml;{ zFAN9-1%tl@6END*R+!ED7%Wcb@AB0h6BR-T`R=XY=UUncbKE;<%T+KoEcul^6Q`V`pdWpthC zc#3Z?Es_{k%w;2viN&!LHyj%lEwYM?#Glyidl(8ys}kQbpLtGYxxH=)AA@>wHq(3wK}6 zQ=pgL>!|U6Gi0s(u_@(84G*OoD-hFPJ*4N?<`)R?E^jLs(_#dT2;CCITEFG?tC@!= zV?~mt>wAXmjd1L#l;uXa*}9*0nK`Y85uT3hFU8@5d6hg?g#p_Hj*3U_Ws6|0#Y_-I zMJp;*$K=eZc8d=FOIoEo_>_QXquDxMPz*y)2Ojn^yX>3|ET2I18r66?C18E^cVxO8 zpV|AjxF$ORoIT>!mp3Zh3d+PwKNKMnTQ?Rv8aA44MLIrv5aTjJw(-IlHdoJ83NlW3 zRzUfab5LGHgDIpGuqaOu*}`g{l}_fCCTGV+2X`JU*Qx6kQ{Qq>c^J|fd*^b4*YaY* z^y$L!*;>4u5DX|;*T+4`eg>OM1YZAg2xZnUggMro&UF6Fx zZg`5M_h!+xs+$*8W#vc|PB&9vYB$|QE~rFQVJ<_V@{x`f%i{kO-HAS_hSuKjdhH9g zr1PspjINF7mz`?oj2`5_k^b_+k2Ijn4(=aMBNyp%ZKs9H*DI=pd}^S7fuc1~P9y!B z2*pX|6w|=J;t^e5>Paj(3|X2f?m~it-dO`+SP(v5Gz!tqu0`h!kB5{viVo zOaK1cua7xWUhiD%#GHEUNd!FOEDk5|0w<`+Lk7K!(q+iGvt^iCr2N6NYjtNaFt@u} zh+od7IG^r(9CgIlI35bT>VJqkUoX|O-?}$sjsSCcaT!yktyDD^DqdP7K>Bb)+Xij2 z02V|5^*f{>%~NVZ7NliPEr(T~tn~-NO0+qBu*$|`vi(DGSCFgF4wGqN)M$s}`wY%L zsBebbDM@DOKWxz6nwnMPNN34jT<0O(@QmzRryd!j`^!YK!e39(3s?TiO7v#FPpCAd zn&0uApc<%|jwy>04o3I~!?-o^>|7*(1VztYicR~n)^mS5*-uefF-?Ms{vqc4@f|Q6m1}6PwFI&oi3AH zUmu&+l*(N{s&Tt}Uxx%1?yVwe>tQ{75U2|iDV6TFXhx+)ON`ujyXMAi**6|*iJx}L zJvjDOBuzA`Ok*_Mx5JHHE;U1HZD|ZWaQa`!Ej#uZm!vja`8IQX9IvmuM{<(w9Zw7` zjN)5NB;ZcIO#b6Jhcy}R%afy#?24dWlo0jnxRa$5;ixnz{oAiF6uU1r0Q=b*M!}S% zrsq}^?y$fMNaN1eU$#~_m!#ZNH~WM)5LS0hGo7iJkBS6b66hlT5&m}X3jU?2=`XfC z6+|u^u>(#_>{YHPcPLPv5Pd(`HIFmL70*e1R_N|-;|YKD6#8+JnQ($hE1hXARP1jWMaq6eN0|7 zoLTPu)gE3^6_uQ6h%7Rl-tI1nFUF`U>Mbd9Kk9FE*zmnjoBp2b?=CKO(`(%2-bEXn zJMqquhd5jMX7G<8W^E&$hi3nvYvDp!OK}q5WR~AW>`WtxEiOm+Qw)z|+9DLG*}()- zinSZx)oyuQx&L2AE2j-80)iDlC7-FYC6z|jb=O-!)--3QG$6s+D9O*yFE6}1ZlAi) zYvzTb)TX8FmANgRN^Ce(wp>ciV?jabdgrq4AA4Uze^n<>6sS4|2a2_RZiiGy>E=Op zZFYOnc3!6?f8@*}C-Ye^@6OMk6icuj0DZD{+t!#D;q1K>B|uFNVt(9wm&qQ0ClNd0-bV0$dY*BpOu0Lm8-OnN?(x^3>?7{7i^(_@VgEX3K7 zNrXiBIXI*t#jgaaC83 zd8Yi?NUUqU(Eo?dq@A0$LHUp4F>CbX(wXLKxg100F|XIQ!5VB@?QV_3@f(GYcidf$ zUoH~VbnqA-kLi5_5uMr!Ol7i*NoLndrd*6|<`2nj+sy>K&jT}@liQS4Cs;<+uryV^ z^xDgD_$*_Dc@(2NmE^*U8)0`+)}SLNnNuOB)6jqt%0;Y}DOC;I=ZA1Fm>p{hKdpcO zqa7onx=^GU3SQX=0$pCYYD$Bm3G)-UXNEDccQ+PLJ{>^%LNkM0foFXZaz5f&{?gJ7 z^Zcm?5by#F3=>{zl}e1dP}c-tZEYC{(JLb>r5noNW^vE3*n#5bFqp+Os+~BraFcCz%#3*hSazzO<{JyI= zGEg;84*-Z1vj4xSM!39Bo8b9s2H)0bC&_iT0bLLoM~COKxyHtp^`lW&s;yZFH*MtN zM=}I~SFK;)#@JvmU+2kCh37bLU!P%>vo}fpYdA)UgZsC=4Yo|hdSCyjMA5l@aB>w1XSYwRXlejc zaQX{f2l7U>bX(@kM+@`ZY;hN<7{~#4-~Xw-qDzdPf_cx=i^X;mEz-QqmvK$iA!f5= zUtOFPJ&k`{ZrNBXTG3#`2JC$x&)F7=&GBSM+IE@Z1FR{205X{~t*^USiBq$P1Q26f ziZB@bowrwUIz0Gky$0&{z9hW^XS)v5wd%ZVNfJx{%7-WRy{LbS1&s2mMat%BrQo}b z{;FXWK;a54=&8VWn@GZPYoUEZ&=^rxu4ddR^&q^jmc?v8PXp<7Xk3aD#|G^ICag{#lEG&)Z5(<1zzE)8S##5C3)N{4{;lOtwt=*pC z=od3y2yc8p;U%ITUPkt&t_^D!pw&=1Ot2T|a_W*+7@=%TQ=S&WDkH_AsRts#Vi(z# z7|rRr0AfBnF{PVWEJfl3Y>e78?zB!IJbe!6@t5iJmGypB?klLyDPRRQ`Gm}>%IfTw zlPjf*GDAd6@xjx;{rQ> zgkca5RbhUFe!!pcdrqTt6W2>O5}gOnCNI*HW2>PvRCN?wA_4iq^j8rdw>KN{p12eq zaLfFflyH+}G*+_jX@E+OH&q1#6VAz4%9e}f$Jg5mCiq&o(8oBZZ;lu%n3ey`pagj& zNrh2Pt`EjZ@@_#V*&E7Dq@EttYT7p+>=S=?|IguDCRG2xMvsb;KrVu}gcaT)ALX`A zG>cwIgs=X!a~P|T6499u^Zs|g%`cmYtZ)u#$VsEkr%7)oo{bHOa)i?`@>JHhn3X3MBh1|D>~V#;6b+VxhXGFw>82ho9?>ALokTM zsK0apz4L&hV7BFdrP4dtTliIN8Eyr_#3;x0&DFOPx3W^L3pQpTT^l~_rc}AFYHuTE zhr=6x_<#29heiD{;6`M%38@b z1JSu|WqyB_(aIof^wl>E&V??k(n?dFB4nLY4|jRoial57rpaK1@YoTxmKzYOOqgA{J%)Y+2-PcDZBGxg ze^>oAi|kVI0-5gX>uqSzJOzzd7tR>~{OzXK{iEdx7{T-gZxf20#@R^c?&JQkX+!Lg z^VUnYR_WAL9Cg(d0a6Daaj<}f30A`R=p@LPX4EZpJZOb2ekwR&96sFLoVb&e?%Ldc z$4Kbspx~DEqdp3wlqn850y^&+I=<3-cJei46`Y3 zEwX1#$_!aLM=?sHUOV2fq~sJ2$xQZ`#7@oAjfM^`q9~As&CLK0chfe*aT+z8?^sM0 zE+~i4udbAt(wD}=>^GgO7)8)M4<%3ON*YTV+7EFNo#(7}kfqoIe9ltr@_6a{;u&^~ zGk<)rYC(zsBQWW`;Cu>&8|EqN@nX_DTxQ;-(~Q*sdc69Vq(Rw~03#f|DDtrMw6+|M zfId*Yn;-nkaiK!Jei_UoX%oXJ1 zL)+Kfd$myBIg3nr57(Xq{EbcP$2qX|g*Rp}+nDGB_!*Ez7RKLg|AzgJCmR2+&l8uD zFVN=MJD9mb4XTBr>iBqutvDgz1cnSd44o*VdR>P&2BUQx`_}FB(h7v6-M6>XRxkkb!VN63i2W#l zOS~3i@w0lqJE{Za5Hm7=+ZAx?K1+upY;W=uhkog+schyl$ z3^mhVGO1Iv>rbb5xw@;hg~{c78+)RIi`I0SE)Lnu@7IRkV6vHD@;sZkfx!ReNo%oYFLW_A*3RZd~-D(c-U=@C3z76Dy93a*L38M-+A1R9~t(zD({ex zf9lhU%gF*GN?1E`v7Z-O3s#$^Y)XKJU@;4zf1+`9%^U|WXB#Y zKe)|k*Z=tm_q4z|1Ah61QBypsg7;Lnv4emNHW%u1AkjcZx1no)4Om8Hv;Glj$B|de z7#el4YE|z|7Tnl;C_QNjqZN1 z!??nh)A5u%#Q&qPTvjo&dzVEiJ#|?rU7W~szJ2=%hdHFoJzG9BWZr+LoHuNjFhyv? zjAX)G_jY(@#DLL62l#6>aMak3UxkgAlsgAo!n1?|Oy3)R?q2MuG>1Tr3RwePo0h*4 zQ`+VWQ5}qAY2ekPK1z?(USTD%vu~GW@-6AKfBHCEazWPb{2-yS5G4QCY?SlZG$>}W z_b~Z6;=QFisW^r1nSrXZR2Q~#hyl~splC0rp7cNQ+;q8_;Em_>5=S&t zXHfQo9&^|e!M2Ph_GWdTdbqYV@2>*?;aqT24xrd=tu@tGZ1lJ(x%4%`#Kw@;5I6*b z=I#drWq*9n$FSNnNVVcV^Bgl}tLU;e(A|JPPn66!!Omdf-lZ#S%`#96l5TynT-T*fjR zN~g7B*#Fy0LlFdk=wmv(EwrSch0;hf*KM7MlRO=E=TzWl--y6*XiB5~=EL*o-pX+rwRG5g#xvYssc! zPW06gcs(_SjzKvvMC*lYYzRp$UKIG0P>tj23x)J~c&sD2my8Wjdu`>IeCZHw=Haxq zxiKf#VlX>AiUcR1fOZRj9_FHaN+?G0@{2ILYH*S09sj*xd^S79fKIb6Vn5sX6mLU| zLZB0Fgo9Cn-RgL`SJ~{i`Y%7d&3k#eTLR$kkNJ?~c7+*evIv_apY~&@7Z-#gnuv}* z{r3Ts=++EOvv?=Beq7CFRJwRu62B9dPrXP|`;hy42#S?_|y#i=5bD5U^0h+t- zB>m=y==>Fj11Amv7*y}ceaFFZSsLEuddj8)9q2qL5eNc{XU0B-f%NZmpVxx|i5P^l zzE>*+3ZO%}m>W)V(xLozu0B?M%22xZW1>dNWxIC{8S6vegUi<^G;F7YQp^X|OOu2K zc*c?K-_f@kSa|H#jSLTZ={z=Hf(xe}Ft5$Ffv!%hHiPxn!VI&kz|>y2t?`&2Y55YdY#PhK%HC{6OlciZ=J`sUfkg4~?=Y}OR;`H-*kB{e-BDTQZfg?t33h$U*=e0cJV0%RVkCx3nYo2Fu0%t5 z&*5HIUOl@kC7Bj+zaO5RS3tibz>zTz=!Lx*_0|B2&T=B0_9w~hQk4a}$SlnakU9)c zbkXVU4XcYreVgo@-?A)|9|uns-Ne%8GKQebkpR=Aa#)I{`;R|g+H^y>rLwTE`*Oj& z;%C{xcBwf96JY-`&qh@a+}=-e_m*Qa#G;Tl@0cHZYwmshlLh8H!>W{-0r17ZRr4@2U;| z;0@~pOk3j1`p9@avy$T5+=nMS&*UTb4-VA3y)+mMU)xPdSWs`*0j`Sg4n|T#E`AXm zk(MjDfEk9<%eE>(_9R7!tYNgXOLliH=S9IGUNsK?gAV|vqPy3wPbSIdpY+x?Y9w1B z?(M?JZugRq=%jXwd-~%5RpO!KrlF=x8)6OZK7f%G3~55kJjm=LH;y{af&-zkreIE! ztmvCsFSQYQ>}Z$1=A3q$662t^B+vyMANLdPQV~M^oXC^Mb)_69YXraS*=M+U++_X*Sa-&}k=S64zs{vjv#OPk{-Ko! zl+A#&<1^a)0LM;W0#8rn0Z$Du;v$srQ@dyZN>Lc#fc~vpJ9m5{A=1+l$Gwe13zec& zr5uN8SA<+;cnYQ9m`|IA!T*+Z0R1{JxnG&*d))+NT_>6eZLuw0Q+L&o?|f*IVceIU ztQ>5EdH)`IelU#LAZL_DPE=GUrE8OKmHPG_m>MTKr0{##`PP247F8R?MXeD>?sF)U zim_rH8Yuet=U^st`h$;?0DJBOEGLT+q#&V{~ixh?$P{Cf0`Uu&AIyXtuot6wKe0l2i9J&?jMle6G7piCPX6Hpc&;%Qk< zrwLuQm>|1o_cA&Ps4^}43FB|#D^RF*B3KUJmx)_`Yn(!2Em`iq4eSF(XoFY6 zmy7B%pWx13G(tT(#?lmEw3?6x5_zgxD`uUX;n0NH(FMww9Gx3|w57%P(fJRbN9FL2 z`IsvAWkDl)$SkXK^R~wAs8k2YaHcoCjm&i{LmHEY?;$(tiVL!$Y2C*Wf<{A|k51C} z>1R_!l|+FvnezNZtc(>pxrNP=P#M*VG{iJHYH{$;&-jSkRD7!;ax5?oknvj51xkj* zqw(0>1HlCilDnsk^VKMP=|fM&9ke$;_f>MobK++1=QV1jnYmjopETRW`78gh%vgFXa##3d}5b3$XuG2X0 z5vd3SMdu-5f>p)SIsp2cuEE|gTwBP2efTKQB~K@GqsL_SZPe7!5U4xyy{vy2+_7-~ zeF&64fI9QntbJbbbkE3aKWM8mNqNBk#5!e-1P29u`4wHJv*2Ab4UBC({BEP~Us_w- zivx$kHA@SwRBEsQ1x=994~lo zlE-OfuTBo32XXVCuk$zxJk)&FfQ|N)yw=I zRKKk(C0xZy2K*z{<=yezi8BSX7vYfq^jJ*A(KmGy6Py!1m*`6_AF)cJ)2QKa;NQ0+ zP@`YQGW=7rF#T@SVD#MiHzDki@V(g%mwxLHWNbdT$U-eBUp6G>oP=`pq!WlXCwqwbNkxTHlS4eX#sFU@PXc12 zwHvC``}F7y&6$Z=70{`_0Fw7%nCv!0vp*>06U?4KLY0BXjyrJq1!qhN{p3&N0D|%7 z3Dz_S9pY{01?sssvaiqj#_M@m;Z^?IhC(nFyjs_r`e46Q(!V!c5^>l=^RYv4Z_kk>W1-Y}AnIFTio1@LzvxL(Jdv zEVI|y&WM*s))@}ZioEs@_mBTjRImIJA+u!zhwa>{-%G0K+QAgG=4@=G-vH?8;1xa@ z2aI=2OigB6OuKkpW^G%nRN&m%O-V0-HBuruFn}R8 zn#$PT(ZOZV)e#~kDhv)hQdSW4h>V^wiBd}yt)>>#EM{s?V1c0KpK8bqd>ff)M!Y&< z;^rQW&MK#_5_5p;d9Ej|ZbuEfJ3Nq{oR81fAlD`H6%|pcI4$hbHRUY`46vMI>f;xm z$w2V`!_F_QR{NUT*UVjt3pjULLIxd=x44In`?bMgI?QzHK7sr@y|L2!_>R&JU=3?1a!Y3@LBfFmjqc5OOBH_*3v;pDU&bE0*PS*#V9tyTetCC!H*}EBxi{WOAjT{p zqjrl_-;xm%3(~2M;OO^8dq4Mi49Og%s^)42l5$<#a2vQ0q85{7(Lr-))#j#je5jS; zV}FNqSX4tXH2A9VS33CkO_Rducr)z(h2l8b+3q!SuC|mej>UgDHazOOIHup#{g<*s zIy1OX=6Hd}ytnAaHdYHiZZx$Hu2Y5)iG>(3mM`^x=1MKV3}!^>at`pssJWKtBOi|) z(Cl4~2A&#@4Cs=}?ZCDqt0ufAAO067{2X{8#{Gfkg5hZlT&X^)1zjUU^ty@d1*&Ll zn)%4Ob%~iw4ioIn9aLW%Ns41sW&Hx??b*RBQq5*2zj?e2UrFp~!z5#xfXXh83roC~ zTJ9p*e}Kf&<=RY4i7^Y5N557YI8XU5dw3g`QeU&-U8QkQ9%48FNk?vFBY|-ZdWCQ5 z-gbJ(?)d^cw9G$)0p2Vk&AUM1SDJLIajAjzYiB{+BHR=8rOix+PhhIu2mFKx@Rx*H zZmFTzF7u)s4aXcm*MpX+vqm<@LN2xz;(eX~PC&80ci4Ef&P57qN4ue(B5Q|zc#U#m&`|_Xh^1g}- zbF~=z6w#0O=;riJR4OYB`1vGUQNF5IUyLAVGiQ<{fM?+K^@f;>EFyy|LW=5*`v@G& zG@2q~UV5wOMH})(Zm;M5i?NS12F2=~vodc3po2cP*tZnke@cs8K!jC}B*Y$lcmZ3&urUK&@U^CV zH*j2&xPTi3eJl)w(GS3*)q?eev3JC=jd}7=yRVXuuR@dz=smUzh8FMriWrM_!0>aP zylsxTpytwKQrbhsBAYB zu|ED?JVc{@ss*l&}jsbp!2xD!WiSl3IxM#$B~0sI$!QJH7;{Mg!R;NHUa2 zx%yHo4ZxIb(;4lrajkp{JQJ^KeYu_1=*9|KGs5fv8>w%NNE3xdNh!+D!tEx|bmI7K z+pe1x1y))@G|qEAu5H>STFLI8h&}E+W%0tB%d#{n$xCwjn-}JB5fpQ&6%vA+&68jZ zFY2s)ohVt&%{l3k2aO)*@pz-VD=oS7Z8PdM+lf?`l^;QZkmanS=rePJ<1M`Jg3##d zk9t~>9Oe@C1TuTsFj}Gj!$^|cH`N5+GlnMxll8+KhjWcURea*jxwx5EA_};`1SP^J8uX&QSz!9|p4)PrGU&<7F zTdcmjT*y^S*{TQ5)ogyILOok|+`!GRc)p-fpn~tMzM9X;T)T~jC&ni|jMtxPY*D;r z0%?;DIm1c%H9bnw7vb1J!L^V9l2+szDQcx4VRQ=fhwzEdVp0E|yY57a5?8N8mucSd z2-1B_A$k-l{3qUQ=qS(nvwTgwhBQMoO}mSMH`Q$p{y#Y8Ooh;HR)XK3M&@FrIBF@O zKSqe&$+s{M$$pNTFD?pq)i>%be9QuUn zy|_f`j9?Vs5NmIX*Ef3>gtB>XAo60*YivEL{5on|O@~oRuN`ht0@kr&OwYPC-*@cqJWOfO279IIJ6=oGqnKG4w&Ds2Th+?euG8Bp zhECx`VMAYrrw8HIvN*P)`RrEZ^1At^soX((U^{GgnidDVLe!8 z9^oou@Pd|jFI9z#ce;p?UJo$PNke{3=r$I+GS{j&d#ztZ=G(&!z0z~P@gV-hI1iUz zCAF6J%)3*{zl;CBz>M`gq#ZVsChVsp&s%e*z6zl$FO8t4`cwi0k)6(hCF%{Y315 zp7z}i4dV+bP~zD~w(*tj+L^xDAra3O_lX`6=*KfRN4|atl$b^7eXa*5*6!#tJ!3W$ zsA25MQNZehox5vr8e%1^r%8}T+VwU|S}gn#H9f)kQxVDnO8(LJ3kz)f(l@>jmX9zK zeuIiktYD4~H$?kW=+HGU!4`xPPny3{eyd$kNChwZp5Le=ZNz&?-7@^~zk3on{iHQy_(G2zHDhXQ}T$^X@_R2FoY%`MLj$AxN^IB;)c zr`I9;Ha&Ze9d)f~?<5QlofoC2L-?4xOizn&T$0Sd_@RXK2KTLa*e7<_>wPDXix04` z6q5E8u@s$+%lH}_#Di_#r^MH8d|J>;%h`vtx(eo$@HKmmS6?d-m`-ZZWd^DHV4Tt+ z7;WU(Sk=u2umr(VQ#paE1Yl$~{VfZUie z43+P3DPfqs(w{e*KqRZ^VtT#HOHiE135gu7It!cX7qZGQeV;I$7m)DjPO zc*Hk2`vx?VA~pC=k|3-7syT8lTrF}DA8Z-9-sex*Tl!Ef$|iL1 zvBYOZOqV15P#yz>RMG#GZnW6v>}*RQ%Xg~BmCSw%`G!i?oz}mk5ThaZf-{r}e>)hLG2s^QLP7x|w?_r$bFkfEXmA|D! zBp^eDE7p$jaOi*HK$)fIDTNCz~w0= zd3K^lZhsi$$`Sk%mLNXxl0*Y?`7r?3h-y zJG^Ru7_sq?*)ORnehU`#ks2NUOc+`*YhscWkJZK*{~v3^KBj$?R%7Mb4}^Q%YjWWf zy%t8aBC}ssG>I(7JSN$FzK)l()&K5U)&lr_CW(Uoz)vBB&`hxnqkL%`yRXC^P zIj-{?1!tPKyx7!Bs#;*&lP$kJs0hf-HsVvO8tjk{6udq?krG7m(J)J{Sz9If8`q|p zE)zO$IkX4WdqyD=#klsQq#GN=e`y>uUyfDhDNCHI=Nj!jJ6G7hB5m&9T$U^T<${x1 z>}&trE~LVT9}hM4&IW1NM>f#DLXNH;L^DH9Rf(oV#927)=`f(V|GHKxKMbmJKKLTW zwX4284FsJadgXzle^rLMr$4grE5?`#I48g=g}1V$%6$=pHqdWm)33xl`BDijnfG<7 z6gdce_|_ekWDP9i5;O>3JXh{GyFI4U0=`Q~8tv-aNyqX_>DF(}JVEgt^DM*m{b&ay z7v&%~w|=YN*;YZyKIB+PzaA&DnZFeYN>H`)qA|g;CC#wV*QRG}=3-I_Q~#r(e5o$wh^HO$GjO*D zF1*46)yaQ(`SqkkJ_jrswL37ROef$O@W|3+$!Z)sM5}2nGiN9I(5!deyz5sDTN+>q zouXZlQ8bBMT<~t04(F!)K6{fSY|7K_K)aOoSU@cq$*JpJ7q^7O2Ug9eY`CkGG#Jk)ye_RdKWv_qT@$uia&D z*8@cS)Lam~wG!Cc7?XzhI2%iJ-xF9sqQ`HhjAO8ie4aM3^F+ajO#9i0=)RSDbfx#i%e%$qn9XG&yZcGmd zx&!)SQmLeF#n$8utHd%i3N;BHJkxw{Vd_8No>o1@3358Pzz~hNkzELZ(PUta4A3xP z1KCO(DrOLjoA6ovEasi+r}uR@W#l6DeXRrk_KHU4|@tm{NN<8RJ#Cv3dN=$m;1XD>u<2UrYHN#1?~X|v5Ji05H=l1I7U4a z^g4_c2s4hU&?0^R^~Mi(R~lVF3#T#fw7q z?>fmH+~_tJeVR$?lU2lR{F#nvP~fp zqsqw?{V~Gbhg<`l#$O1Re(N*9HXXMvAFz_1qOcX$TROesnv71_%Qc^ppVI%Yjxj5I zY~$eQ30N^@aOnpxsd!<)3d+>*0ZxNH-P|V*GOO1-ku6xQa)CspN`Z1w*qeM>2$|Go zvU^6({Wb~CyAzCSk{#Niw(H9N)NjVK-t$ubpr74@++~!Mvq?uta@1Ie2Fq!h-flEq zan3K?R2+x#Hmjn7&Um1X43v8o*m@<*bkNkh6(Zk~Z%9 zowjjm)f@}%Eg#mMs;8!3(qf`1{s>?BEU5^Ri<>+9!pcH2QXfS4Sy*^jb+sja3DygL z0SOqlRlPiEig89pexUU zsmIc{IT3LGC)IvlJuZ`+CRly<3b_`c5M;-gcMDM~XYx4-Yo6|2YBv^cMZq)F z&?_6|49P(4u#mn%UN1*mIF|b8Rdct{CR6CAQqTDm2az8-dwpl*#=*Cucc3;g0!SJt zDZ%t*rfa0G05sH)<^})an(3@4iJp1hi)FrDc@iblbgT4!Dk1lJ#7E#+xHcX4^S9; z9pDw38Fx4PsqBHEMtG|h8ZAQ8ti2ygde#*lVs%4RL?tzQnK)sOEwb|>^r7N8enLw| za&B7VJ>ZbimCpKFnxf^873x+TFdW13Kx#@mTn^>!Z<6? z=MG6YJCq2X9#T2DT8G;RX%r_;y5Lu@!bGv$^9aEm1%~nw;t$AXr0pHQ<{)zo!}CLn z@1G^nw!A5KbyZ+yDUdTMRb5L#%Y@HhTL}eOkjfWb!k|+f`hQ?X)&JC4J(~CRLg`=R zaLHA)IOHr0-&k$v?x8wV?V=0Obf9I!TH3if*#6=J0ma4)xq=b=_)UbZ!7V$bm4!*q z_M%wN?cIUDgFC@31Ga6b`dYC>C*#dSy6O7$pN*uZ%VEtRLqmCP>HoJtc3A6+<4cx< zbRVsCV%!{!-ONW*mkjK6Z>C}wgwWAMXf8Hmrxc2>ckWXsZhMR)Li}U({+#EG(PHtG z!{vg2O|U+2n}gLlpUNq(5||$S>AOfb11@ds?eK)k)Ksb-_*@DC8FPUxbM&K*M_K1F z2@2eG>w)+MeSE11x;tYKi;i8ZGS_X7+22%(tpCbhKYBChg!;RQ6CWI6R`}V+!O#-0 zV#?veW}c*!{8>eHiK!9Cctu9@x0int2jJsi`>L|9_7r)fFWw0&ug4UXzBY02bOfvz zvbcw?GO8_5Bx7*}GQ6CWity|BG+^?x&1AR)uhDn5yvoq8Ni=d0U{K)xj_|@i*W+oh zsrmadk4;oTqx9{a`fL-Ob}#?`@jLQzrAet<7|I3*V`HRPkRAz#YERR^RCXZe!9iJm zeY^L%Sc z!GDKkyR;q!RSZwU$Vz}*v?^i|n>YGYv_W=okbs-bY}n_#8e3x2Wb6aCac?XD`0p-a zPk|XX2DFQ-A`6U;I(tTE>R|;fj3Fs;=NnZ9rbniL!RgfzX2cc>PThFH@%Y{G#{uwk zKw|Vs@jw*D`QfzsR~Ah%Wh>$RS>5xT|5XS{%>}!%?6jI1qIAwV^&(nI5{KDWxuKSwHiPJ4lbsY!@?!ERL6zV&pIM-)qwuS|z=dyE6C^hjW;fsI zuD2NQIkp@-i5nC8@NL=#6Qx(NukfrzIz6cBt5%CJ_JeESZMgQt*Pu7v0hZur0_>1D zLIY>*xOyjK1?^%pjcS|7^E?ef{1=ZmWvsU08FwTH=PY}e>(+BXHIRDrdr@%pZMqdc zH};QnAa!X4C$u>7pbPp%R=h45VKHoo(%C zj3FK6`DUh>5~>$Z+$+Z>kTCE4at(hM#Pdbypdv%$y4HbS$QSZu=3#rtnEvZp@0Rht zlUQl+Y?%gZv>ywtC4T&PSe|vK&|bTd7yEKIfQCd~o(fJad({_E?0K*oezkHN>@<5|^ zJv0!Dk!`jQ|NrjKAOHXUKlw)ax_JmiKe+f8e#DRrz;dYYr5Obu%zE}1f)R$;3MICE z`SYSlu={M1xF3r3C(~;&R}pjLupGl@@xaOf#QQEA8{Q?RJT#E72}!(Cf#Z&Sm$R8^ zFG0k~)l>hSx(blCrU^rRVrTm*{pODslYR0)Mm}{UC;jcXaug#FJ?p>ZxuX@~Js5%p zP_XItWcZQ_mEHv!R}32FGy%S`ef?`el7d4Q8jdx%FbeeLF9zbRrDp5lf=Ty`Q#a-_ z=%&aqAY}?dAO9Z;x%B{^S3$V8onT{{zGlXmdCkbqa~#rEw>8vaKlmr7B@A32k9Sh} z0=@#1<7Bev|Kx@8|5A-TX07PM`yqOHl?n~N8%{Qdng9Q>Mqo{ggNA^ENbYc!gNV4A zzn%YVv6R`izaHD=DqMOrQ66EFJsD9k34X+wb?T(9zBQe2*_kfGce^OC!zHIIcM%4A zPm$9ck79z)=Tu(y01sT=9R0Bs7(T92s|4R`;|a42Aq3OF=(%3Aqm|KK&J>Zjq*503 zZGTMM=+B=xfm7$S2#cI%yHbsdW;?{}PvWO0s)`X3utf*R0L%h#N@BUlwE_%+A^Vv; zxS&OedMKa9QRRZLxy?IxE6GPYt#-BRISLk12C!X9`cU(J21rua`hc~{T2Lc(W^3=Y=w;Kjf+{!5MtgJE&2zzEn>siyulxEfcRe=1=B?em!US{cQbM?}q0 zSd+e>^}6R58>If7gs=cgxRYw(vJxtdV5dje-6nB33Wr0i;4jP#oJtN$6 z(_wm!4RH!G5D+8WvKhKZMF9l$nlX5zHIiBn*iYQ6awL3sZhmiT#|(V^M2KqB_-=E~ zSL{N$%eu8zRRxM?NG10%B6k`hJk0>tACp!d>J5q=K^{q}2g}ieYm6p`=H^_GeZ$q% znEmF?jYs8!Uhz`S;F`cg{4VSuGwpji89Sgpon&Duu!UP7RGTs?8x`hxjOVvsoVyeG zbzk*J(SIxG9DT_Q=zxLObh$za`b;Fa{E6u8@am;z-y}I8rR=SUhL3iE^aB<@pANoj z@ms<7Ik)l3sFr`h;yR_MMJ<{ix^@?1wJJ49Yz!;E8!Mj5z8wM<^0w z_Jk9asxrd|_GXtE{yuR(vEoyCxmT43K-E`ME35_XgJaVLEml4kw8Wc)8c(VwRym49 zSFuHiAs1=orsjBk{dC};y2V9WWZN#)G&5);F1-anq@>3$;Bz%l^v0OPVwfoUD%lOx zsC+Vu?qb$0HEi=*>qPEPse5K)o$&kCe?IZJ@RHETya;-f;ybTd+=%`f-7B`wlAxKv zlB)~(Rtl;NFxP)q1evLhRIDf7x?FPv(biRYb89?&d3+FQ>!rZEqHqR9(c9CJsXn<` zxPLp9m#hr*M^(M_?l%66!9C#aMd00QHeV5e$-38Mzf5Z+(O&tI@!K6y5~jJH6%Df! z?@X;db_hLdl|a#*|HH30!8}WKjBqy!=Th^bJyCr&A}8xwh?2}t-w#Fc$40T$z=41N z_&W+2oe_Z`{;I3^==J;PdI8TP{mq1FIrv-<<|dG|QqPi1q zUJ2UXU_r}mq6`5kQ7i&U!FYjKbLOfGaxUna>1HA<5f61!m z3dvxo#|#p#%Depg%hBTMk!0c~7f*uLfWNA&VK{?Mh+eT4$3pkGsy1Qr;D+~P0H@pIu%fX@ch~NTVK2jYYvvJn~TK4IK()U zA(~Si&-gk7#}2&MvH$#?PA|8!akd@O7RW-pQz8nF%hc1p(%w z6e*I|J@^ej%igNzhKHxZckwWrobR;04d>GJ-5R$X`+nZ$`cI)XyF&=9l*saXXcKSC z)PiG9NqFr_$Mt3o5bUlsK%p0-#!%-doA*x$tqQf~GG%2Da|Wgwb|%3RiYxP+w_7|@*$IzP6!?7UX0+>dMqB$Ud(!^C z=JsGJ{F=5NRL`RWnwkjMjdw*d*Uu5|G7H?QEb3q|4|3n~7|R+74%p5`Z3i9SIQEFh zIdQwTi7g}kS$N^TGO%1{AV(ANbYCPw%X!r^y5A~);#3!a^}&xjhKyL91}`A3 z0zcFP*H0U<0DLI-cUNm0;gEb2IS>%Pp6cw$5qY&qPRr|NaCxyell%EQYB@A>jj!pF?A6fL3%ZsA4x?X6 zR@d0|dKg^^zC()8ePsB(!R>1`{E9L<&y_#V(4K6S$|w&I`zDE(m5}DrIU-Yb(<0v@ zgdL7^?yD$Lcv8g=?9?E2p0NNOW#cU`4(T6vr1vr%TX{xlKET6q9u*4( zBJsreJjt=!Heg*$Aj|Ol4)}`t(AJV#;TRbs57kW^(qrqBR`)5D8F+i+-I;0U_v?TU zp++Rn0I<42h?2Z0uMdblrAu}4(aEF?kw~l-rp&(>N`6*7IH61l18lrV2g3?+g(Tg{ zRG&2YKfvWbVi8dmHz)i;{3p;fz|^Mrc2#<>_~oJ%3;Dj(@}{p0hfqh~AYp1386mGP zm`xskhL#;1iRd#8C_>c^e3OcGOsyPjT1>pcpEkY{+ijOR(&YiiDKq|*pQo{?nxhL7 z(zC`~OXkzu_=1zNdr$cS8sVcwe@y3}15`Q6Vq(>F*TM_Xz~$4khm237y4@yXpzGoB z?cmBE6Eo@*^jRdw`=@C+Qs-26GLHwSOTYtWJ^)AuWgh8e(l=H3^fbCa(%YWi@0v6p zuvrBO>tM-H;3n_5f8-Ftsrem;iS9oU5IRSrlh1w-0TXB_nwVCOfv5`!CNF6~Q`6UC6kk-6UQe5cR>vXV?PR&2;BO1%CLO(UPDG%vHIL8 z>j{AUi3IByneopU*l)`25o3z=c7Ol>|NsBx|NeZSzRfj{|NdpKi2t2_(#b6$a9wkk zh+n2I@aje0-0!(DL#1a|do4Hh?kkc(%vjXfNuIHW1TQ9WJ}Ya6W&k>anIZ7bH3J2) zbSfKAf69(|u$pFpo}K9-z-kDla%T8a>Ui=1ouN@Pjmi?)(ts;KR@u&-^NEXn0U%AO z<7yw(8?{o#zRDPkdTr#OJpq;XzCla}1Fe^23jlF#+)`}HU_l8y_y(c=&y(}q8zICC z!4l>1z0(NX*FG|+S0R&Hfq~ng92^LqiI?~JZfmR=KwsYcWrn6qGMNEQX~<|fnd@zN zcv4C$jBTrIdV^0qSIa#N;68^z7q4ueh}q>$uSL=u3y6RJ|Nrhy9!OaRXRQ0ESY6`8 zcLWqHOR25L(SsS2Ll2m!??8mj4r(B*j|&=o5l*HwE(b{c5GacMjfmP{DH6}}@cwIW z_V*P2Uo|E6L)1ou9sl@}A0n{jejfI%q3&bh|LzvYVWwry?SZsvSG}d$#+&q*U5eA= zlYtCGuBIOs6XsgEM04>9^088#^py_$jjRbR(N8!2PvHdev&G}ckJXYdML%5H&6kab z3b8`}C_bE8fGpooztm8mt#+1Y%B^2?kf)BeeWa!j)?NTg6;QcW>gK5$QBUM1n3_^7qdKicQEDi9t|DpMw@|>x<0$v4SQkp_P zjlc+DSAUz@Wu+!k<3^pHaBlNt0nhp5bC0Po^rQPbJdzAeciDT{NYm91sIngg2yh^U z$ZAi^FZ_`8qvU?B19a%ow@WB0&I(hL_bKO^4WD0j0hxn~pSU$_&bD zZ~=8efuzhaGZ8c_cBQKz2J$`VPqk~b`l2k2PJZ{yN1D%zKEDp5d~8veEA$M&%0I`M zLd6YV*&5HJxjdRrJF)v3lrT)+MzMJ2^gV(`Wz9tg@D%bo16}^{1`UcRD=?sYCQu<_ zztlgTr0|g+qE4OC*PGD2n>cuWjC6k)oTU{d?GJI$P$12x!IUM4TFo%xCm{}&fM`>| z1r-%^;c9{JK^n#8rjBB1^=HM{}-<$Gi?q#-i!edNg>X00~d(+s2b`7o0Bl{ zge;)uDyTz!jrj*bS5j~)WuDmCDC6E#G6M`4dsURmSiW(1J1SwEl#6K=R&m(D0>a<0 z{=<^pg24p9jWEzZN#61(#W6)9-g= zR$PCdgI?_r(R6x^4-CkegC+zyEM-&|;;dnpWxD=NLU?H9$laye%93+@=QqVMgLBRf znk&Wmc_TaHr5T0k^4=l*OjIS(&qI)B$1J!{wP|)dR)F>Qx$Pr|FH-Er=*(+1cVPu0 zUDba3?-tMg!pZ8KL;vY%)jwLsA_ys6^4$OX-K3D&*ZfA1W@3|m+Okgt0lk6S^LvWSrp2lHIpkfnr5nZs z`Q#4=O5zOgAUx#bv6LPhSJWd%O4GBYZX>Y3yMn{ed+1qlj3TQgy2lLo+>94va!j0W|l%h zQLtS4D4JX*;`&71kNN2iDJRqMxBb-z$5RF_yjXH}(?BquFBla^d)=zkERSU$GZSlD z76s0P&mokQy7jg!v9wp`Nv~(NNmeGNYo7{=x8Cz4^X3N-$EOa&^0%Dd1}rbt*mmiP z7OFdy)L950vhMaYc3TSh;>;mfOH-&G^fB+WafJY400_o7oy)dq<=Wo)TbdI-p}#_H zqZrLjAWVuH-h24fF@+fF&mfJRXV|;W^%W$&O39dd6^CW~N+Ux)j_nl`2EPP}f;4fP zWb)5bi94WoEc1OKvz5Gj8`zC(3q?=_=IPH{kmunC$@G9gX0beh(2VJkTLGb+_t3?b z{=wi1+B-h!0&5su=?`>3r#Bo6T`_LQsUg3So*%iw)Yvg`N8&r!CY?;@C(owzY5Q=K ze`t%l#uyroG;M2BN6mM7oF=btqVJBxG=DOwE{-5zR#lIJ6qg;+3l~6I+Gz#w>wm|M zMdHbJtof93&%5ApDRYva^P$2V5<69?V8Fr zq4VOVSRu7SBD-cBaix%eCvqpV-Fk*WCqZ1(rq=bfoNo^%jz8n!MteT#$XfM#fv*)G zCx#IDKih(uzhjtep1UB?Zx$o8cQ zY70kuO62JOt?zRDUVrp3LWDDe8V1(W{0hC)Cy!bNLqDb-q41hsw04x#(mToKk zW%yP?XXo~TOhTa8^D$Kv^IWze2GTrwa7gIv>u7Mrq;R-Qm8shKnl~>C&z>r8Cewjr z37mP{UO$RmfkKqhjiUZ%UbANkI0N0sqOl0uR#%>oB35%Ufl9_`P*N-%TSZDyHs6N= ziC*ia&|m)~{HU1Y*Vxr)$4_f?f3QLiDwUjAOfP8+Lb(Qk|L6R&F!bU4@H>BqoBtHs zMTYv~51oGCk~+mo$d}>JO|>GAe}_%gDUb)YlsZAdXtFmr`IrUBfDviSFYoR#k%V`~QtJlimVkv#<}5xMLkp`O$Hy8}O<-&8Xty}w;W zQ_H2Z)Q8;JG($vua4EgUdglcG;^0A~Tlu7nY$;As@5bIkZjOuJ6Hi3+KkA7&Z_wqp z^3YVh5=0}SxFW0ZtTbbQ0X?o)=w6b9WuPN*S~dJ>VJYaw=YMEGO|2K ztwFTT6L1|sz$kM9b}Nqv&Ht)5hD3|C=yqvmALsd?$QnHWbHRuvb=%8Bu^JQA%N23V zuaPnLDMtO>+sG-}TxKwU!Q5a=pfqrop@4sEnf)@~gg%b;=>I*l&xog8DiOc46(7ZS z|Nq^_EBA=z`Zx#uAOH4N*T)v7(R93aL(1IfRpU=C+?e{#p&F0~1vVGjL2uaiZ`1?%=y5_=4Dq$98j z>_DO-V@U}|b!Jw~c)ECIj!iP-qjpj0px7x&Do0@f`I(5AXgZ%cQiK zf9WZDhIS*P6E~OJJ`|bNr_(fr&68wDQ$4g=WpJdN_ssl#75vK+mW|vX%23XW&IM>aXwjkapUwFjU(<~JNfEeV2fBfQl|AzwI4S$$MZADD6aj z066M!^EYzm>w}N89xpQ=Aw7C8bcT|r-1aN50-5k%|98ZzBNr2;Qq5ighH-l82<7We zKK+ZxN$5NZj$8lhIc54EE&aUdre>;*l~;j%>}|EI3+~ry+fxvdb8Uf;5K)OuXC@5JUMzTQU4Lf2Fur zpQnZZc@@jrzw}D5$8g%Pxbb|Cs;*>^CixW!;umbhhxr7H)(SCam}bf5$$u`9%#!I; zfpGCSM(sNX>gFHg_A0G_ETLwHr3Xmqy)ekHIE7y1P#)3ZVq9d88>&-%o5kLa$YSQ4Rg1@f@K$Y})U zu7ssvz=^YCo{=dRI0 z{`;zc^*P$LOyw^3qC(oV(aTBlF(F@I7X1$A)sTwNlDb010tW@E#|6}~m%>)SaoReT7bwsP5waTY48#x#c&xvJt@zAWeY7L0a<`0_;1lbYjYwUTHTJ8v^t3a9KpQjqDW zR(vP1TlY6FnPG_zo@YrC5A=-v6=icdCkzF7DROL!KKsJ|{j2`q?Y*RtPIyaj#3E0R z>YTq;Pz%Qb^|grxW1|#hMxU^DVp^#`OP*G@(rNq;T3?>1L76k;1k9YoWVjs7Y3b*- zayucmc8%63;X*kep@JK*eydEy8(^yhD{4LE{nGZ zr4g=1B)#p%4Tgt>a)ttVXcHfX`|AR|(0c)h>!=bh6p zpDk!R^j%G$MNndeuyisS?y+$T23B)EEAG~;%x-GiB!7OAj@+#0+93+!WFEkUslu}O zaZ%du|Lle0ujri`yYC`={)jZpRO-X*^T6;4OR~!U{@YFe>9v!xnub|ZQ_KKHPhv0n z1gUZ{TQ!svDx?2!5!2HPzsMdA_}_$s&QsGVNqB4{t*8gSI+wa(J@Ph(YmXmgGUFT* zoj!(M9nRiHk(XV=qphz%U>@A+os%MtoU`g&2Ms~=s2094{ zYYd(-+@p{lugMwD?;ymE1s^WQg^{==2~-t8tM|kU0UkEqx~KrLQl6Lpj;$S8nsQ{v?VF_*oFPhAd@f%8bFq z8Mo#p8QrUyr$}0pr+*u7x|~Y{gFHC&lV4k+a!2jI7in;r%&9+SN_iVnwjvR+p*7SdI zmWbg1My!@f=~cCxnQpSLYPU;42>3^jh+stq-2!IbAyo(yNeLpWDPP>L_=vq{qrY+U zJ6d3l)+fS`FMcYrqCl@s_jO<=9vWL;9Q({04batCiyZ;Smcn8y`4DLs9u~X+Yvx&h ztR|&)wMOB#Uxn*`us(@6IgA8Xaq%cQvN`2YK@Q1m`Ugo2~d+#W|pPg zp|^tv@we_n56vkeHP=1N14rLjNX`T;`axS>vEOdJUXa$S1vL+r_*|F zjNFH$G+g$!E!IUJ{{Y_`?9jVOB5CUX#FNq!ak4Edb8jShhj5a*LBT4gpw27+P^(`T z#I`3nq72#XAwi=hp`@f6^U()r3OxOwGP?HAqJ_eS;_E!T+k{RGotPMPTN*A=K73c= znnM2KAx%<$Bb{tQm0WJyO&I_u%()o*Dr%>FI|O5)f>b->1(-$5%`euc-wZ#v)t_I!4|AiYg1D6TwmFgXD`fcT4Sb;d^#WK6dj z!oIWELiVmlSw68b>Oq|5i z-<6uT<3@B7ZHR2%fhhL7zf0V;Ny6{=lNBT~H zhiPZ?b&j)n!5y^!7iFE{yzm5WrM;d!p4l{jyL7;Y_1=Ft(5jgTpv%)OIjCOoiochT z_l#X3bdtbJncw(Qg~v=W`yeNpR%}og&AEbxPSWF1n&n>x6rB!I6%uC>`f_HAD;#2H z)5Rhm?Bw*TVBuHbZ|cN?Z%rt=P>i1y#i~>pna#=YoXYw)$p=rW5z~~dlov{ngjA)E zyiM4(QJ2<3rX7ZM=KxGu%|XySx=rCBxq9oOq(+S2G`4mc6oEr7`Jx+lvM|}CPqv?C znp_BxcY}%_Gey-)rM7pV_VtIS`E+gz#5FrW%6rDgz>RC#SAddus6XONbGqnK_VO-Pp}4N_ThzX9$1*9WX>GmOK4#Fe>EY>x>DqwZW8{Md z+XUty50g<0QQ2OwGhr8tmLCOSxG8x;e%Gm)PA!Mc)MEXHi41o`jBCfzg72EXr*uY` zCJRIKG`uwGu^%;E+kTP<7Q&T&v%Q(ACie{>J-m=f4O)0+b z=|dK$xW1?9-~sB6j~$`Q+=GFnvn!-uxV6{uyzU9lVOna)7%obvCAwayT09tz2CqMI zf~QxDu(YBtp<5Km5Tk$*TaJSvZpoppVQ%8A4^jZkUXz`uBJ-t* zbP9WJ+k0pPP+}?{5{9eomF7ZxEdp?$m(=$MX0q1|_EzXcG`wPxLVSD)p5x zv%8Q*HMq)<@hZVa5Nd9LyCV4|XBzzSj5Z}PJM-zu7%e6nI^l>hWBq zj|GOvt{e+)BfMRY-6hHACFF|%A(ke3TbAEm=)#N=LvGb3?&P=k4A#x#B>Uc9ZQ&&P zjC)9_*alh$kGZpz7z*0dolR$kuf+(@vTs2<=4V^p%{~|MCVp~i`%VtWxT0*A4*^1T zeWZ(Sp0(Md?18)shcTwrHPd+Sx^u&xZ?>oa4tQ={D}$5?+i#%@{+ud2EBo z$pWudM@mI}Z7o)t^N>m-80lv?4f6=M+{|4f^V1}%TQ?5VaNd1y0=XgmjHBEb!>bjJOH)&2^xD=} zqw&046ECF@F+XMQoZM}xDC0|yrp0==umzArB#ib&>m&xLRsZ5Y zSNhR>6AoJ02-?GC8a?^Uylu;7x0x4~$v&9u24+|U6BwvQrBlBTr?5<))Dp}B?#Fcf zdfmjW@(_wwCLzrhdc4CPqi_r}TJN#?5a~a>E%JR}D*tm3XK9)~rk8epf3<(e5qAfA z#B^|8^xN3M6GWxQ+Xi5wtg1jHQ-Vr|7WjD9wZTjlqq99ES3z0Pwd$e3p_-3nPDjb0 zQG(DnAjz=TXHo#k$>x~aC2<`BxiYO^tzoy@{mcRtP7NX_suLQO7Tp^I;*8*+m6xtRGA7a%(GH7(Bv&1cMQBi|QZoP_Za65(m zGVy-_+;| zP(ePCF$FOatIdu_IO-7krRgy(v=qL~Z=O%S-RfNL-td<3gAKc5hf)zGK)?gXeW1*@ zED2A&@!c2?qqk;YPRkzB?~lS9#a$lsxJNBdET>#CO&6R>4q>RAs@YJokG_50aph2|{{+Mqq<3-2X8A6s*>OqNwH!C!8DAL?aDa%<`K0OD&E;zNO4Aosh0KYwd-Q zZn3o38)%=mgE=_~`_tZoSAy_MA%ujW>pyc3@zAA$mO@2JBl8J8OG9808@)?u2$!8C z(SWZ~%@ra;$ab}pa*%|XOyy`e&V%*Wy`5!&#jQ@jCdI+PJPhLp8>H2H6P{tU9o z{veN!_XrSY57YoPK+3-npr}r5x6{wV*qa5?+4OK+duHAkhHz!mvS(^QOGV}MB}c^P zA7*lPnd+uTVWFS@{@{B5|J7%#PyhecH`eq1Y;1g0B0hV4>zh*<&~7P51|6(XC`|>FZrTkkc|#& zBaZi#jGV%tWBxA)&o4KxGI>1n%pcJ4LqIr}ku%7iOmg&@8SALT!>Ay5GY{oYXTf>O zPO55=3+<8>R5j6?^u&c>0_@x#V4Y|SSg1QMyH^-hw?{ZFV1%KSpkym=c7hu5pz=2- zZ1cOXeZ#EMYK&p%IG;KI6Vt@lD?|Qbo)m))Tgg>rU=3j2@Y_}9#~C`&ED{^a-Z^~e zMiD~nz;+fT)ynj}>)p`!Ca8(#OO>CRoQSM9zOlFk$Mu7a7b&hA3E2a*I)%P!Ju`$S zZXekg5igrXdZUh>rVhXDsdjjK_7yAk5M?Wz=nwz@_UgdNgKclRmw<04LG83NO|rdF z{b+44yY=8xMYj~_=?RdB*_?2)?HY}K?e|v)8zwC?S!{B0c`eJ;5VGb*W z&8?FYriz#7o=zW+v8z1e4*7x$q=sJuyuK2X$bT#fhI!R#o_7phL%c}^Gu!vf9Y7{Fs3`ca^2EWhKz zh)w_k%1PXnRdFFo;1i z@iH~3v3}F81InjV!>f`v1RcHH%2AkpjyHXAJ_pkh=ZoS8n{=yXZl*G2xVP2?3(nH4 z70UD$zj~cnD@BmScjRA-enO|Pe^e#jVL~?d#cwWOzV^#RlS~6L0aAqf4O0TB zd6OxGV&)-}BYFB;66f%UsKJoL1L2X>N$7r0*jQ&SJqy8-`JBiSD%m3RBdC)tYZabRx4V^Y4$|R?3lgo&B^apR|NatXKYasj z=rzrlAgllXeX(F4|Mcp@U;q3#*h^F2-CzIz`{9iT4Y2kzI!k}1*Km%;J+Su{nsKjb zn2tWTeod>LOYx8+s&UoBa19+oEdp#hw3936w1r6*WKG?=2#WgdXwJ11UjLc(g3x$D z?N{4q-)THji-ca-tRfxbYWia5jE8B!rUi{CYVYJpRn6On_@ccLJ<>*GX~198yHg1t za~zgXx~S7i)W+&mywS%Mqu0!r_-+!Pm7dyni!24dBq%n4$nJjyUDTNn$}DhnA}L0d ze9w8GUSK|$jRZuq!1$-uF~{Q0He$mzIU2 zsOjd zMgbm_mI!WxF=qL25GN2Oe+chzk|o1#$Vn|^4{<~4O*)l_?2K8lm;eM3}R`j31n; ze4y6Iiq~W8gp2F*s^%}HoZqq%#b-x(Z3NE;ULkZK!-C^x&&3zNmSXH>AlP)mNG_HqZPgSQ#WXB4|0?9#Zsag)E9C zpd!qrEYt>4m?`EaF%T3Bhu20h2pI$Uhs8sEdR6ioUCGJf(4=@?qcg}&bgam;TolVX zrB=|B>TT$h;LvF7VxKa@&++gB?~ccg8^<>EPE1(7^a)r*nP}XswF0W!9oUkUV>8>E z|Fx`Fx$Y32s`zTd@?yvPoI_9v`doiD%itC2SbVQW&W!8wdr&<7NGoh9b+(j_a1&=N z6uo`x$n~*=){l3c5H(fYPP-O*hTkBXk(UP@*G2I#^S{4ywg12LWP^Z`#!Y7{E=yob zX!_Q_oWQ)O|D>UR+CK)@B%l9J^@}1qD=|oTaCD+uVXa@JH-|@D6AbKBMYyTRy z33!rFO^q|v3cD0bgiu9_Cz^0fb=@dhToRZ`;vdACT)%3Lj4In_jP@Fb{uUx_1~zj~ zd|7T%;#Fnv62NT!Dn?d!U@Na;XL&keUBeq!a|WizF@pIXqvE-diHVIlQ{`M;`!X~C zqcaxjR<{Id_nw+7ue%g$*PBIWLQ16@dxMZkVh@5VAm}VL8}f_ya`hfO6h1cqI}rr9 zsg<2hCuOp2xmQX1;!xFwqqP(nu$4Heg!h%qjHca$D!C1r8~!x(`%7RpLv*g_ioNO& zZ-2?NbWW*OH4|?V9c@2OTlV8gc_025ei-V}9k}VN3(pu-D%JKwT}}Qp8l_M+lz6vn zaHPB;zJ$7{)%axB*hm2+I}CU70@?_C<$0&ed??`-s0JxxO4Ecc-*<+`=&2{epp${g z@{AnS52KlcV;Q9U+rpTd7_7C@-;zKkGi zthLIhNhp46F&_tqAB{Y%=Fr-E4u=ZeA2}*CHZ>wLQ$AZ4n58Z2*@{q7#4xO|=v+Je zvjadr9%GO-urZ7?Rlk}|7S(j*F*na4n78hJPrWQE=?KEP<#s}2z%&jC`E_r2n}^L% zt1s1!zRV-q7Xh<)FnKtdP@cqN(cOo1h*xU;skKA|FSplc?2mvJ`h|P>3ZM&>~1SflM*_E0}#d_f6Ea0+gdVs*goQBWT zM^-&H-Dxyvi9WJmme73@ih*S|>3IeO%MEzElK^(_wBbIdH2AUI_Gm~d7R%T>Ib zbh*U?Li)$&LR&_)`MplxPAQN|GuclD8aknM7ZZ+ifFt2;ngWLP4q#{(hf5Kmy*1k9 zdV2bumk66tf<;XZ6H^4-n<@=v$IA67-y0y0>e4l^Kdl|8=D!Xf?d3-)YGlUu!1)`% z)K%*))8tfcm`DAN+JG^{>RoneI1xX`@%RyC{}US?|kjKiXisnzy+{O%&b&ftqQ6n#0<(_e4ZQF_JGbt{p@a1YC6SAuWp zC{=eI0hGXWwi9KT`o>-fQ&w~YY7^4GPzmPDm43&vi)^{N++_HqNMGs3442qUVOeJW zQRWb?M?!^KKEa3f8Sp)3)W(wgdzD|#?u?sv-Aa8gufRQ$OKWJ#W1Zmw!JNOMYxAjD z1Ct2M>-WuP{HoS#ebiak#vmb>iIGjmpnVad4+Q32cJVh4W%nnnWpUm92a@yT^shR% z!jYl1ID83>cvg=ePge zF4YlnrstI&P|GPsquuh%uEt572X|pCCC#p|6zX= zstzXBj767BI#@*$gb9PQWa4x7th5lGG-XV*=ku_6Q4lZt>UMG_lALaSwt!YnS$c{L zX}1i^lN^>8?^4)ys*8wsx?zp6aX+6y{%YGw5vRaNR(xJ>aIl!0VQF6C3@hf<=f7U= zG$+<7xLp~|re25|LGmZ@o&P5yr7rB4%95Ef|2I&}`T$pMMI@V_iSXal7&uvt;ho>e zs>M)2$FJvEJm3RNf0PYuEbb;2ct6sfK1rCdaFfyt-ZMr(XOk$llC#m=@ zz?k;Nns)kkm<|6u_uREA=UY)h3B-YEWijbr!&;ht@wP`7e8~(t6C-sv-t9z8a(_pt zszu{i5gIV_&ynh!C6jQJ70WzE_D(U}WB+k@WlYPtziV{OrwoA3u8sw&D>wwUC-8WU zSe1mN4hG)NsLmyfU$YG?m68=C^)yuXj*`#$$7K&4`T5!1zjQ2Sb7iz;-sbHCB=xf4 zIBi*v+?%@>c)(ojC_k5$tn`(C_i@p`g5`&vL6XQA+MnpY; zLJ?T5PW)FSiIWSyZ}9o8MgK+cj@{YRiOnWY`}}#S04i*z1+dS_g|*-}Z}P9zp}8O+4GH%xq%2=Gh2oK5!Um{~H8c)&saA1nV8D6I!MDazeNdy1msK)Kq1*AjK*K=na_&8A0I z%XBj6jZ%RGewQ?9?Ksqc*LPv?+usbXXS3~lCNfTyrm=Nb^J>xdgS}hWHL1pFch4UD zy`x`?5IRipJ?N^#TviZG)qhiJqvxQ6drheV;v9t8<5BcWDf=Y8gCq49`~lO+=$x2| zA*?)sA+Z9RFcpq!!!dK0tAL*0g7x-L?YFUay zDmuSP7l{sE8(<0YUtnpj^-B^VCJ)Xa-*P2b_fPCBA#U<)EjeBY>77_};xXO>D+Z~M0i_5f zOR_Vlz~6uSN?ab=&DTqd@q(vFCRaqKFAbZkba5u0tK~Z$=`oGygepI>l$bpoyVwGF zaiCnjh)|F(09b)085s-e-YxXHrspC=Ti>!=PhN4w#z0p~G|Mg2Y?2ImJ2v6Sy{ewl z7e!_X#V56(-zoNPug`x;0iHi^gUbMO$USYuabG%ezlkQe(#yP9$i7|U-MNH5M#T43 zU}tk!p((;ElbR5}Do*yC`Y#AL9+Uip4iqfSvDjXpd5a{n z7P98 zFBGlIB|X%a6hkue`Lcvys9I<>b3ryU)3JEhm3OJ`-|Ku~z(WrnX*khNLY?hfqmM;I z7$$ftr9H1=e2ML<^?ViA7LD?nzJ^F#6X3Ta!AZVfRsOpl-@gpO@WPL%aIeBtxW4bp zEqDbB+TIyTBfXy>){V&PW%39u>&5uv)ea#Dq?4lmJZGRL z=bxhWzENWyxX@aGNIAI9;S8?T-!z|}Nlpj4C89jwuqHb}-^$gnFAuqBx~%_1P;%+1 z<$SI%7*F${CCOjfBryUkhaVHxsi2Kn`R*>*=?fV5HG=2__(YS6!qw#DaUw$3Z6-Ph zIT1GT6oIXjRxl2Vz(z-3@s$aVIA*MC>Nb;^%wE0L!jS}>sO#?D(_E}$br*CXT2(mu z({)Lqn-DwZL|&M>JxwnX(zT)Q>Mr*UBbOen`>TlhAlY&Ci7otImZE;zmJYcqT!Zx) zXy;&38k2+;R0B?l0}v*6pY5^twVnMRkCNP=Q)CQizjCWcr_+?#yJvV*h+$~5nlhfB zg}}5_yL`UCcpR;IR)$-b8}68e( zT-~%EamAFGVyk*-1U(DK5q<;-m_tmzz@e6uIhC;A+8~@e^D+tUk^UAdShO4W-6T)A zE9o{cZpL1(ZOJ<=_pIg2jAE~)s*clb|NZx%D3_}IQn<~talwr6Hh^;jUPiWm64rl5 z@x58nE2u=^)j#F3$W6`bfR6voX%~Sv5v2Khe3Z&!Iw_I4oPaJkz&-eVKD_b{2t*X6 zlMg~pY(Jk92K6T%OJlGCHH!(>#0by|3H~(by!9K}nsS>rmm7F*th1insm$LZDUofg z2!?m@{ut@f@()x@Omm~<_5P{L#ixX6sRgob&&g~nX=FN3->)5N{J46Ern12551K(dJGVV;J+e8FVx0tXkqlLICSZepl|jeoT(?3 zkN0fv!G~%aR|C!?tdIg1Vkq9pmQKd65cx#pSCOrFJ|GF2UpTij0Jv9Za){LjI~y?| zTquA<=@R_v=L#)HRO>Zt$B8K*Ea1jDZ@obnjM-QbQq(`lVtBSw9g{cBR3>&R#dtj_ z!Inyv8oq6WzKdD)t3SdjrxW^xe0q0Wu~81ktjKt%dNr+2e+z3r)wMZHIb z3V+YE9KsW52sKvXL!thG`$Ng_N!<%$kI=Ve{YLSJU)E==f(d7*Q&4tR0(r7`e@V6u zMkRU%C%FEjYcw%pHgwcdo|e!BAwjnLGIu;P!l;t|Je;v{l~}>WzKy79=Sj$sF$X0z z0#QQF9mMN8Fgfk%9zKt}J+GD)#~#^y_}F@=sD;lTtIjmDFsBZ;r!~%XKBD^_@jX3B z4EA!)@9RX^;$5LaGC1NZZHoRp-dwWAP8qz&kHvlqL>-%N=u1I|bt(ZQ$owcA12l1E z4b40zmIcYlLOVqUaU>&g&?9aaCQvR5uwh(yz+!631;UYymkIw<>Z3c|fE^&iY_tV+D{ZxKEGC zgnjo41x?OdDmuwocyZox1Bjgs#AzPu>Cy%;7;chET0>%xz6FQK_RkiWUu z>h)Z-D-wQ&d$^`9nL`n=~-4^xkqVj_IL4I zxNGl#1`*_h)6f-xdq|Z66MzdKkt@;zx-53 z#e%S#OT zBHMSZbBdW^4}HLE+Nj;xO5~Y-P8VvkvvoEXwIc~WbQdODf0KjzK1K-{b@ShNRX0GU;ZQ? zC$uBU*XN87j{T-HKQF3ar03y5>;}lu5@@=t&BV9<+D4!nP=Ugcj5Vx>DXgbLaX-2} zMwug!?>W%D=rKgtsd2liN1(9rs#VB;HN*K-FgH~ASuGd-X|P?2ZZ@Y#Hk3vDoA?7$ z*;b#f+uF5Tf%5pZ2cbHmmp)Vtki92t`|pZ4Kc|hzrhmx$K|w5|HMy69U((NA4=K(3bJ$ zk~_COOu)+H^I74{CMJ%zIFYxSD^8Rns9h&DJh)rYx@8k&IS-IAf9n^S$ooJSoWKrm zMSLQV_TKLd0kDzgi<1i(iPQsEFf}%Gz zfTS3

#s@4v^KPMIrPyjQCKE5_YTvX*zzRSNIfm70ko;vy1Z->4F1QQ?R)jDW zaLI^|k_W%C-!K1CGv$_gdpCa8zYW@DrhZHv2Hz$EEnTs3BD|i|SLvhQ|LDw5(%LaM z9+((0peS~c{KVfqL(|>;uv)s|eG3wmTV0CvHtULO_;{-!&B&QW8qQZgB#|w&iBv^P zG|P$d?zr~{$=wmpys|e9kee%@>!AG#VkdxiQ7sBzjtl@r@mW$3^g&U1e=u1{eD?6R zxwE~v0JE7iYiVkf=F04r|4I$rpV2`Ou#o!))3p^jk{SSr)MoNXX1s_pX0nZkm+kks z(ykl=FN!hB(@WKbE#RxPfV*b0@_y4^)|WmXk|#gXECZ`89b!R&O4(Dfy)tAvPxb9& z!OGf~n@Vo2aa0LN18|{Lpya9{_>Cj&KkW=lshfkqY723O6+r@aIxyJ~nFgj>LQmG^ zoX2`sy`s^@w$Zl)Yy3W zNi~dKSX4BmDK*1Dy(MUaz0MLTM|yy$rM*AHIS}(2vKhdev4E+<3Ngzatg=s{?NA`UH!A8=Vw|ZFewTfe~)*P(MJqBthJF6>IHkQ zdQ~%(fD1LKvtXSH_)i4lWWBFwF@b@gaVrcDTl>3&%Ntc~{1W1a>$vFHw;J#*75|(h zP+pgKkNS&>gOEnAtXDUHcUaXHdY*@nsUQta~WtbD)kHdV-EXNq#PR0$m( zUz%u3whBa@t-aw_PApT{Nw?@R zK0gYITOaOmun1Nm_NEV2f|oo1ML~i&O^YtK+E3`L4!}TdxV``$xswu|IB%3Vr7Q}t zdXW2Fi0Mn;)T_7O>Wr9+4u^WiOtQ)X20Y_Q>Mxk5Z3^?$3Sx=DV=R)%%Ft;gLeHDp zhXR-KeLirLmH`bmwV=qy^4g>(5qdYm8;@it#!}{bJly`GGp!T?4RoZ z`&*tNg2n`l0L?-ht;ZL?z?J$O!5A%&mRzcqN)PY3Zo(EJ;Q+?mKH_0$+=?|&ikQ2J z+!t5vDWPOjUl+3DKzqP$nU>J2VGh<8m%qe98-V3)6=(PlrEGx6hyF!FLlZD~N0>6m zTg=sUbXvYTO&Z%{{CIz^{dEb4_YA=TF5vQawmQwny*c;E^Ey zTR;FJZ##WL3lDk9r5VRK>tLcdR6Q4_gR8UrO?AZDdCa*GV#st(#TopzL$u@~%kN2M zNb`{MC2Es>(v8`OoM$p?{8u{!B9KwPp&Ce9(GhhJYVqQf&S?_b&qwbpYwGc>mMD(C z#d|$ed{c7Ph*!0Ix?CBe!n4d?FxAgNkYvg9*>6)}0Bsm`8CUxUxZQj#8jf%^I}a`j zo1=W~XL;b!kDLkKy1Wth_--WD=TK416pY4yQ8Up8T-7?X{}hY#%2KVOJ~MKf0V-wJ zvHSk&N0*=;FOdNUfKZKipz0-UYTH$+Fs)g_lvFUw6=TJ)b$oum{y7M9@NtPIm}C^< zEqCySJaBLwY|xn5@HVw-8}+!(QL3Q`s?sG7DmU*2+(8Vs;yWMI*;Q5tg#m(laUZas z2F?}oi6E_H^8oiZ0Mzx+-Iek>kqCB`Y;f5?3Rq+i0MwZcD!$>Bqq{UbL7t1rSBfiK z?&^3&Bb`>%gy%?a(h|2Ba8Dkhz8#A%J#`j$8geGHH5ySs{dina(BOW47r%4Zf=aQ? zHRrSCf1ez6Oq)BKzp=}F3C{RKiy?C0?&BqaYwXhgpkugkIV63%(%Ee>ZFrHsG>3Mi z=9ycb_mVGs83Ne*!TA-sCBp6(Zf`ZWl(k|3TlHZ&n&R$4VrnDWXZvorOghP8wMmM) zg3aaAtJ%Tfe=_=>tN`~)ptF38g)1A~?GVYtvfIc{R?le1H zKScg-^)vCCz^}SbbU(L&)(s>nga+n$Yy|m}P0YixV6J=CwKcy1(2Bchbh^Nz4g7q0 zW@G-r8A`^hV8frGm+GRw$<>v+`Q}2P)cTXp|4Rg!Km7c1`g8=Kz>H9)*wym;-R^&k z4f2s3jrjKT%>t0akn&{zPI*n!cpxz%?k;^N$yEPkT4S2Wo?}v$EJxO4M783D@YIYN zjVB&R-$)brp*QYKYW-;H8pipR?5j>*t=n)t7Iea02{%kGq4A#F@jYWj9(UpI92x`$ z9CfbbFmm5j?LeCNg>L@S{--F2C~q9)OU1acKkzC+p#eqE9>x!nd7y5y1vlvhED^@#&qX3M@cYS z>IvIdoT>L1ZE=VbC=mX5;Yp^%ccBxPf!sY6G-)7W_M&4W+!XdY8!QxTP@V}=EaiUv?>Xe^jXf821HOrww6m29`Qd?=TCnKJt z?8d4yy1KSlEfzJfjGH)Bn;HlL{X`eRUI*m!MydDbNC;7jR-wH8elg%I)M%kAH?iI9 zIo(~af1?m56nm734EgU21SD|D@QOlKP%W|ImHGHAg=l98#+DY^(USCpTU$u?I?31Vax(QQ4ubIhxupA+HURSlf5b5JqtqV z-matMCs%#BGN^hh#R(h&k@q<;K^}WFJ}KSbNS(6oza`-tT;&=p-Pr%{#`vDQo-jY! zl}!hqFD#mD#_015Bg=WbLl*qR4|pFw5}Km{1+4AJAH}YsyFnTxT>HIiH)@ciFEq>Y zB|TFi7efq?hFy5;CXgBqF$cD?JEL0YNS(}0VaiuAP2HQ^*M~a&8wy(0ap5`f9#RTl zn)#@ajv%2r#dIXBT#Yn!v8ODC&h2b~V@$R!$i`Bu#Q!b#=lK~7tfz-^8XI8vl(jk< zSN(tJV5JDudRE>6KYlJ%bb-cLOO>SSttwnpqokD@UKM>7Znw?tc1bG!GAEK(F%F{f z%}i zyS}J0)Jt$pZ;E#6#^rz_ch9EBTd{?}Idqq>?Jyy8nDJ+|Pk<*2^Km3ru!g=Z`zNtk_X}46PTJHd%+l7+ZZ%_&9@W(y!9<);_bM zcr3-rwb54P4BBF5>D%0*C3PP;7XVp>dqw3e1>+;!K5OXV8yvVbTLENrRy+}6gB^z3 z@mf&TbNu49j;Tx=z4p|?@*vRzRIwF-;C}#I^ zi5s;K70KsL+45oYgON6f_Hu^{Q-mlzRdtD6KwQ(Zk&jkQ?rhJAx1P#9%~MZD7z4kY z@Cjpec45JF@6+P7y=^Kw?*;UlVOG`Y2mGSHn+U7EI z*Jpr1{^0D{+Ln%@Jx4@wb6=)CEZfxbyBOS#jx1SxW5dSYwr^je$LNFRHB*7M2aoA` zdZkNuFaQ7p00094eH#8y$-R_LBqO@W1aiRRm&9oQvv;G()E^$4Dqx>kbAU{%V+Z`l z5XfSAB9Sat1V1NYq;yL+pk9G#d{6Pv;z1UorMaq4G-%1i;*|BXY!Km`H9GXBg|e7C zw`)2A)c0b!FpmX26@wg>Wg6t%2hLS)@E{-~CUC|Xll?QdB>QlhKCJGCh1-kunbZ{s z*+K}5TqGkK2vV2$wzT9=(MfSBkej9&#f*tJE&Y=CDaAIwj-Yle`mrcIpmOez1Qqp| z^NCKnfUbve-S0BQ_}971C6D*z=%6h`(IAb!vn_zP2e=es@+@yrb+uHGqD|YyqYb#U zCwb}*>Bg@uQ~#8DX}E+s)>@2EZwqm_-o@>aqko8cl?=p7cT zY%_}!VnhP-_s$wllJo%Gic3Z2xh)9kwn}H&3bSDKy17xZ65Y@(^iW(^^c~VNFkm-z z_L71u`k%+F|D@qL@+q|ekhCJY7ZwqIzVp#J*2^!_V^~kABCVvO;8qnU98B z4Js5j!}>69m+(pMJ_#_eKq@8uwo)@6dseEnM8%0=4&nJ8|4PChUu+p8W-Q=D$gZsa zbxXmNvuEDsB&uF5BDXIZ;rJZvTwT|<>cAyCmYi9^VRX%1Ck`)3jaR_6h_6$Hcj%E? zqxdIhIqae0X+8t@l+4Sv!IMf(0-KKzU>!l@BLWuX>}}=xZ=iI18Pn7KxWX(<=n~5k zP&K>khvx!Hz%LVwCCAaY1OR=|-itSK?xMMpPsHfL!5Ki1Ufg$2>V3?1%;qX6HqF#d z5HyMv;eilFfMv=$&<6%Q**yPIo#XJ3r0=i|+!pWX7TW z$KY~AyG+*ob^SGpe6lE}Q1B#iZ8*Xpw)K5t((e5ON<@}M^C*9USEx~>pI3 zZWb{1A!X*S-`B{K&9+$)cbPla^wDVz(y5F@(uUgEhAeLsjBHiF=pJCxHK4Is5t8~W z&`gkGmePWSWTKW9sdyr2c{bd$*y0(UyNI9+-boQX%JG2Sn!g6eqJvG)4&|QGK151-{Vl8&y(ACt|zhUHNLyY@&4JSH7qg2$PhaF zhCK$sLEKAozi9{5ly2b)gqTK>!phsXz_7?>hG!I52oh zy^tCBtLhVN?EURvpW>SMe+u=Z@glY8J)b19!Q8PIQtM%Jd+34otc-!7MMVzaa%rqrpD<#Gmpf`%j9|UnJjljUx-ebzj-g2R0bcRB=A*Z zEHvyeb;pWIcO-X>LY5GxQvpbH$-xwabrmNdOS?8!`&f63yPvkZ4bu(BgLNeZuc| z3)-t>xz#i&kCuS>rSm@vf*v4-sqv2#gw|*IVv6pi5}q|@7K1;B?;s)i%`)gIeA-m0 zt5C9((HCKW1ui*?I4p>@l*R-1U`A5E-0)}&afvER`Op2p4OT@!`8OxEre=H&H~slM^^SU`>} z9m!BmlAc%P$e~(pN1DqA2_GkA6nQHHuf2Qb#EyIfvpF2up)G#h=!AOCDE-U%d;%QK z!^LH1Q?UaPf6hM>)&cr&z!7&*QD1aYo9DIsk za^+<(B?>#N18e9I4+bJt-hPj$#_?g0&>u`lDe=bI2h!i@p+IQ!YG<^Eb0TbSW(MR~ z>1evLR(Tp3J3RN3oby1q4Y+zHPI(ig9p5+2#uv>>ebV7hTrE}<^IlMuW3bMoKPsrU z3JKpazLOX<|KdKu54tpRKSvCG;AzybrCyu%m8{}=x@wJNlkV&Jz^UY>Exeo~PMfKG zWt!QOgN*8w^@26PzZ9_BgTwlGXpeL?6In$#L*s%lr%}9X<>>hwKyjankTKHX;E43m z`T&u__A+H|0I2;}dvxi~bE5hj2JedO9=z`_LZ!6@3bxRxFwRq*-5OtwSI6v8{8Mya#(8#E^e=2Gw7kY4fx^sg|0}Q%CFX)c~=o&t*W%T|g~s z*xs=_?^mPseb)dG(@radX!5U=;!ORC>q~bujqPgvfi6+cl_m#0oD~ip0O266s_=U# z0|yedfIv=M!B6^{qu1g<6-e^cK0@iPH|0NYi@TEhEOt6weo{A1$=3AIKUg%X;J*Jy zJNi0$_?0y_NNJ=NKK7cb@sE5#Xy?p+!#7-wW_n2bvbElL$NQW1{mdQiKEW%5V!DaZ zyJsv=jd>n-Dfl~?MVf&qpIQD+s<4AsGbJ|f-9v$)4YH&N!6v#`Ogb-^HREkVXHO{ndX(ed1wZ8`EkF?#Af|krcLQ__u|0WVNnNiT8MXE*5s=-Jh4-z#DBSn$rk=hb8U! zOsdm2>EY94u1=1AE%y<-Mf4<%6l^5Y)ZRk)kfwATZcmaz#pDId53E?4q#d_rVplNy z(OjU7q+)-D#d|wWHT}Fr-*O zML?7EILYV3kK)JzDot=Sw7d2q!4TP6(FW{Pn7p@KN!}>*%kuBK$X^SeIbC2v{eFi` znv2WCcQ^b`EK4p?)x$iD&?&b4XLdJg$np|&>DxlA0{I1nU56HRV|&mWvA7(!u}Ai*uX8xmSV9~1{&M^8B>T+vyPE&$; z9VXNBFUM6?qWJxr_u+E2-UR={_kmf=(Cv<#53-S0D52T6M?q9FqOs>^0R=jbqE`9l z4L@F4I0fm32HETb6U8s^Uw8P6q=2DZ70nk%<+Q$=rsJiTi{*OQVW)lby(hXED^q{Y z(9`V|v9q-;aPxnk))(j*(a8l}+jw6#A+d(@KK4o8E@5aN)ity)56hhfsHa>_64 zIj{3LgED;-^f&t)b*iW>l!?yKr1wcQ;olFdhEb#{>kA?He+eyXRkjP+$tAwiDf_Wp z%3MV%Yz+1oi<#3O`Y58Cl59UOt!C4tkm|6G8hS%droI^a%wcHeHV0BZkwusxyOEI5 zSlq(BP}FRAct)wTQ<})?Zqtg;Ft!95+YJU`G}+DUuP+=8Yk<|1-1NTUu4F^BW2#u; znXH6pm|goLlq3V(`R?rBkO5T7JM*#gF8X80%v$WlRKN(8Dhy}kz7VH!|HK(87vOQA z>86?d{6vPMBq%>IEF6YkBjR){?>||q#o8mtfOlyc4JDZ47nE#trCzNom+zm{r`e*C zgKY(x^nJh#D#7IOfUwNvMoGL0pF|BKnsK*r0PX(Vd)TeRJQR5seCyBWI9udV5;;!% zh0O=O3vK%9XdJA!f>Q#tIQ}}*1^YjRT%hYW9Cy#M;x;@0m*#kUyQ%nX745CgKS-z_ z8)P4#7OJbnhbKScT0O4<%q4rb^Vnz>6pVR@zij3!u86wp9nwm2_S`$m212B zlbM5Lj9jvwM9L5Gu;Bs&)IFkcAtioo` z_|jqdxh{7`EkIwKhHa7@=pXw_JrAi*f&4!*rVo>@&MZH`7-= z*_+wQ2V=dAGUmyebp2s)UW9YYZPAA(l{xI^DRK8v2CN(lqgE?aDUn-`r2+g~;>k+< z(Q)Yjqb3We@=u5gOV0Epmz?bH8(oZ9%Y6YIFCodo4o+bp@ce8!K*7!lRpY*AoGw4) zx4riN|MrXr@z=`|Q{(QI!cK+tE{ijkGVYw<2o|URHokL7@vF5idDzhRM{c#ecy;ps z6N0H)ur(g@9hdxBsj}fzlEzgf3xpAVe3+-kG%81m9qmlbOXzr@UqIOL$V(|PiLWp0 z%q?&-dpm$y$6nl}X*AdNURBaRjM&iCR$%2_T#M}C!=5~TVNmu@)Nsik3jt!V zNzhN(F?3+_E$tf~rM6!>VG@`6i&p&-(0emgdE(Nl0T?!_3kKQ2cZ9!WCC#n@U!^7d zV&1vTC&LNaRMVc0mJ3*M9*Kvkp6)Ac+NoRJ*zGE}mIr_1`1|!jEWxivpgrvW@+c+= z&2DY{M&S}u(d>VMKP+cbp_%M|f>029gBd5xufH40txqar>tu3Oh>NEk+Eu9y6BD%)UYQT706jp$zq>cq;qwL`f`mik=8{XI-QJ4saE7G~D9FC$ zPot@cs##Ei3v5NcVP-KzXfT!dATy)&H&uSmqpDwfoberx*% zb++(U9o@kRITA3M!W|F)XZ*5D{!bwihJE#X4(Z0i_|3R$ zOf>!ZqYCQ$eG73Eq3lzhR9&kkxl1bsCp7Vwb#VCL;UwE_(25;eKtsc-$CC#gIAf0K zTm_&GpD0fO3uaG%tOP02Fq-^tView97sqGR#2DPQb!NO;9+TKJG_k^5#Pt?95Ljs{ zgLHLygYU9<@{qU-J{RpnAz)ND^LXi*FdMTYOvXJbT1=hgU#8dRmt)FJl+)$?z!y7G z%Uu+lBmd7$rb12uOg=XHBE-%&wSl*SkU-G1EgXeUHz@5DMJ|j2Z)8fh`1e+%i1Hhv z7gdllX_w?!cVc95w*H*zSgFYRz=wECL3wT$W3#z?HWTMsUDw$MI|bI_b^HqS2v-aD zX}everDIf4{?{KQTcZIgu*Vb7fNd_txIvUE_sg{UaDUWRPJx${3 z`jcrGf6Ss0_N+GUho`^ZJn@5B6b`_p0J{j-_Km5~de8-5Ff3gX>Lt_TD*E`0U@Ap7 zfkB&Un8ju9F%BtdSOCwuEC3^zZL_@5dKeg8cWzEoeU0u5!Xiv2iu6odC|O9p(6N8x zEN3X5rZ6TDv((J3unx4-S$F)dJ(Pu-VL3AgmcOKsTqXnSgS}t;lojy|=>LNWB2+B1 zT>m*`?iL3!CzdEXRUsLkO-|E&QVvsf=aq$#AV+ z;Zr&L1~?CpP<%z5^c>3LT2sW_`=vie6A&~5qEaf>%*i{}f{+(#`Kt(}P4-9HcOsDP z49I&@CmP5lN~=qfu4}E_T`z?I`jm9DSsEXeB)QJ`YCRn%Bnxx14qJt4XD;C2jeJ9u z#H-WJLqDC+;6!zBPri-ZB|nuHLHvaur(a_wQC*9(u|Jd5B0W!|5v2=Rh=~Nh{5Lyv zhe0@=mpQZqet4D0!lt3QY?ibs z=c(1;Rc*f&g8iS{o6o`-gZ+R_^n1DGa&+$L-8YUm77aBvsDLtxN5#lUp7w7a<$p*K z|GUut{NV&U^cX#~`>B-Q7K261W#?)=#xZjBNMUVE+NdW_lS&K<(xx8U4DK`&H?HA{ zhg~;~7g875ytC*It~3HbC&EEm6b=AK@G7ubC!fcS-fU&=x`(;2#Yy{&veTOGV-DT$ z5Ur_$ugOh*?_C*`4#f>AXsxbXMmKoCxDI{fX$9`oQu94Tt7}RsLw=cG&E74`nVU#a zcX@ropenWgi4_`Wr2-5(GyaDVAyLg;zRSqIEileRBM`-&7cZ)vw1@+x%kaTO-<1M# zZX8T}9>Z_Y0q|H}Bs0k=FC>bWDKd=SC2crPLWzJ!y|^Y~5Igy#ygmPEw`?b%scyw( z-H61*L)qSKBbOtLcx4YnW2rv%Wc=s5KiRB1{Z)C9wY9VkAnVmDlHC(m0joM=^ReNk z@<%!8+09~hjhycv;GHQm=a%o&zh%#xMG>ssPQk(5l6e_$_(*Te-^un>)s{swga!`I zD@cV|^H&SJ8m~raJ}7Q^&g#r>lOZ?@@b~>$?)+DKOA5mNA*}Heus=wtUW4uu zE|YB#$qt=Mf00gFtFpnQP9n7ISKE{lwO_P{X9Fc!treBfn%?&iy*nos{XK-PR|Azd zAvQhXt$)`=~MvP`;R(@yfb{T==xz@33(1dXVQ{b-Jgu!mhe%h%<_ zk(&wnrrp-UIRnAz>096*`kv7ww!eHlI*T?%&I;>}56KLG>q6yVc=pEQSN3)RXdQCS z4YXWyT!Hw&c|V}Xp7ZEs^WHqCgQ@cCR~qRSjZ*M*M5Sf(?tvZ7eB5bT1CN zN;+B6gY>}5d0n(S|HqgIaQU`K`V3Trl>Vc;$QMwzm<-XSfK=m)%cASns@91qoAJSZ zzDt+&z9x9qzG*xEAG{X*4zsO(b`&NO+Abo~}vIMphI&O}Zg~EoP^srNX zRhRZ2?1B7_LP->{!fCjf2mT^UzBZ}$^ENX|7q{D*gZWs}yh4R7bleFXtS&QS%HFoJ zDK23>^c~l3a~bQH`BlZu4SW;0TUQ$je-<+ht;7`sNodGC!a@oRssYAH)1}Bq<%( z07VM}zmEQhDBRnS42etOwN~K1Bz2MoyJ-D^*1*(t0<@Np5ix`;5|R8>Xh9JTREgB6 z{+ zyg7OC@t36*m-%%)(;h*s0F?`W(Ch@=TFTjxJ(dR$Y`XI~l1Yo!?0r4j_A+6!9#;X}_W@LJT zbzGx$SkdC9`HeiUf+(nzZQbPxnTl;VboZ-2i}5(ozi~1#Xsja3{I4tYIsU)@`>QZW zF=6D;)u#Cz`cnx}SfGq}@6hXR-!QMoMA6P@u?>?~)h|u_ks$vy#26WuzCvMH4f6mx zVDB9emfLR#`(%efX8BGDh+fk(JDqWHb6|=l49xJH6$3f zr~;fvpyzFdH#qmL=1D&7#Me!&8J;vNA<_#+V*V^_kvR+bw72*4S9`-{Je&y0Nuj>y zh<~C=9(w4?FR&stUy_FcTdmM-f*_yXOfqt={_QWyCu3;dWt+&8l3ZF^ELjV+epjGWEm8eUw5_m%-YLBTFk8bVg z5gT4uZ19DC2I9faOoIiZ798pf1#$}Eg4L8b1~D->bQl6beI<1P`w6d z>AFwOFTv}z<9;fi5MTTmsN+q1qwk{{<~8Q6a;u z&`3}E^E-{YYgTO&ntmxRCO$BS<;KNbgo$z4$bb_N4Q0054DyZeN`*`80;4BE?pRzB zvi$NBigkwEiJU`=Os^wC^Uwe0|Jk~PzjKt>0@-awK;xF-rI2tedM4j&lS!hMF_9Y< z7bpC@VElS{m}<7YHR`6^m7y8%m|&~r9aZIan2l@ZnbP!}au(Xl4om%$U+iw;Fp4LCdor^Bdp$a3d*!zTzt7 zxZRa?|F`5@Z&elzmy+eT6*> zF54Mvceeq`+Ti5?tM-#Z$5>8+v)PesfE}^D~|OZKBZ+=)2rc`(n5ji`Of zw%?^j`~&y;^vPUlqv<_@yPopl&+XH(`4`pTr!QAUU$OE8_x?JvzhpC;K&CI*CnM zl6M>2*`HfTv_l7CrG}?%c|-4E-aHPK)YT9DH260i4MHOTnvOS*!cP=haJMR{8WGDk z{P$rV%|bnxctr|@g~B)>t1gLO2xIx+(75O~tOCN^%yIBZZ^`(0@FzgTLl+1Go6?3l z4Xa!!J#dOtf&kDL@ceoQ?R?}IwcO4WB_Q}fkLMURS*7$S|z88&+(*+9=?yp=r9DlqnKSnG16P?^$2z{iqfg;!WxxpRw z*%y)*HtAbF$kAlN!!!)f1cF+Xw2j58D`?Cy3vTsCi4(Gqz^Bvnet*#zqiPmpn;PN8;Oz!38G#L4|sGdodPNIOK2^s4P189U10{$_`pA`U(4Ryvtd--pF4_*Qpb|h3eT~f6yL;G zD~@#lsUgEF4aB3OA|BL;H+cqmGra&Wcv_w`L5_&_z<}Wty9f*|ye~7jVbA;+FHVV;h%BEUEBZ%Zr=e6(44>C9` zV%g~mdOjoosAG*wUNFH#xHGCEe>m72YA`GvlMz&zL$M~@6N5yVY!Qq=jig6+A2eVm zhfm7nA4W@)+eqF^i5dc#6?Q~V+wAuy6-PMh;|-u|s{aBm+0|8>!wca!3Nu>>5Nc2$ z+`z8PR%`NvliU(adOJMRiBo;Ywgi_ZKy;{=KcQU&rOH9Q4-8~mN^%N=e~C$l{n`ex zpZd;2xkg`!GKdv(+LvHEM_84v{TnjW4sq-*2|`->zu+@cGXYW>LK4#Ti|Z9oS|UM` zzkyp7>d%ADT&-*Sw77d$U7>-R9t-}6)?5~45?6J62%XQ=!e-xMtxIWa$rkZBas$32!@QUumC^r& zNgAkc72jgO&l&kL{#*P~J+QPaD67-6xQRKNFEyTrzbsdq?g_eL6dKrTF;O32-<d+XpV9`cVqEpg0lkYpGX<-&*IL8tMCcf6l z=}Q@eYktUf$Mb8^Gl^KEz78W#>$d`^+j5J_gbC`5y`Bj?Wq*ttQK82(g7t3 z9ilDXfk}%00z5PhR`2vvdNVZ7)tz=Z;+ElMJcB`e;6;Kq%d?r!rCmeP=$ZZQZ;u$>O||2A=l3X6to;>!4c*DsR*qWNj|0Cd~vdcq-K} z)IUTze?F;6K36}@P^VNwk2feEBx zzo-U~$y@GYDryJX@EWgUO6|EaUNKNOc5}^=9M9@c5SGaxKp&B^L?|o~;N;(i5zH2o zA|b!L6CfA2x{BNp-wz{kTNDmsc&y!^M2`uC;w@(AK{Zv8KwRdNf5bH(P?qG$8~PFC zA^`VC)-Qyf-(~pasbjI*5l`cVHE%oSo#VELE6TGxeHwz$SPTv^5P`Q>_j6b=Z=6LBLw<|}?E!Lt zdbpLtN128l*l_&jrIJayk8F>XzI{$9j;Eb@A6nR*0_z#N%LNRN%+CzdH<{oA>rfDt zYos2)a46zN5R-IrNvEE_I|vu*H0yrFDIt_9e#WICQhqHdhzxJBkZBlluyV=e?;onK z$Li&x)&Q_;;_qt$+Gni9MuX%83^^=bWW4rFrT!~P;>Bz6W0Y63gCxfn4oZ0$ZDt?i zL2A3$LI3s*Y`r{fy+f_ag!5lt31rt^x#<)Yz}?S z3@aOrV*|fdY(XP@$olF+MjL^PaEf`I-(IYGzD2clqjq?n4V)5N^QP8{e{#3@H+7m% zuFR+x?)`bPM@tRrVHXi4ID&HA$TgeP#_+=60ST8NTP(s}XUYEzJ(7N&^&IUF!@nio z$=u_dl_BpP(VOyvRJyvLAAO-4ja$5mT)lUjJ9mz@CtpaGC~L5{>%O1s1f^rk$24ps zX1QNyt5S(WaT#}S19<*1RSU+&TFTq+W! z><=qE6M`IZ5fw0tSwVuwKJ-o1dFhEUI^neWyL{g+^blrT{kks49b>x8Emv$<#+rt~ zhB39&(TqpM5NS!u+x9<8!h~u6yKn?-cVqQJ?17(Numu~twjT4 znd*+0QezDn{z396X|!a&MmoVx)|m11K614bddcrOem!=^fhSw5s&T+<0;QRDEp$aDN=p|+UAjfAxyYPPs3i_k zyx(4OV%tjw&S9??u{WjdzA#{3n)g<4p+>lbxWRy zhK90tcr)bhA-hxsbP`nyJ?=z72!0@N;fI#2aT4lKH=ns~{6_^S^JJ@mfR30Z+!(0w z?5QMwp40ac{+t1xb9_{;lqZckBqXvd1Js?Ib|*>9;-iQ1P*vQRV{FVW)e($oDD?zM zTqk^y&&ZRH`4Q>ISayi-+W){5!UX^0el1s`A@IN*rWQ~gK-!0Y2NE8+N?jHZRxBuh z%q}Z-u(Td-x2?NK7!N`Kj18l+c=f7r7A_}9S?unRoIrG$WT0j_$UD=Ba`@b7Cy#Wh zsv}P(#fLV3w7N47X&zjxr~1J4Tu96w3yG^}p?4Ig;01Sph)=xmFY$}33_)%_`cv_% z1XS-OWrNHtlxIrm$C)&rlNUM7pl)$18zZ^Fq%8gP|DE%nB`8ef*a2j z&kjJSs)#yu{y+quEj>3)vfOV5Lo(SN=o72^ zUu>KReb76Vp-B>`u;$a!feBw%4fd}fD%kXV!TtGa*GK;B+rPSeDh#fIFn7|`TTKg* zfPD-!oq*uO;KvH_)`bG-aoxMZ#7o>iEgz8Hy8H1nG+XOH7DW-4<5pNC|AO|^@<<;M zs^oL6gm9L2FRyxCyX1y%lv9y*0G8Va9ZCDrfm-Y$<(M`}?;=5Z#Scuy5&tVixx5Fs zMhp~?0Ed9~#ynEnZlTib6W6NyIdo?8f@lR00klTCn7dMr9b$u-(A%31{BCdmfr$hMC%ITq~o#6ny zR+{`8`V4&RQJ-(cVgQ}m+thtUbWD&LMXmOQ(y2$4$iFSl&2|8Tb-XAHps*_y^Fa=P zfQgoi`}X@Pa~ceVI!3GeZ+XYuJ$X1Gc*8r8>@P4UB}23>2aNs27B?}j`)Iy~e1+u` zk6FkSzZloQyM%KNLkzpwsL$n|u;fFQ&T15ECqK29EB?~e5+bD}fFKlbILr%}ZAdc}4? zDZ4;_^9f*9ka02FzfQM^;N8;56wc6*w&r|Zl#Lx?tUrU%gVe|TZY)W(Y)V1Z#)$u3 zD#nNeSp;9I$(>Lp08@4NmyN4b5%{%}EE6(ACvZ=lA^Z_moes)IJB6%hVg6nuTb$+! z3B3^KF7I{*A!=U<8Bd9?(oEtb&I{&~_id<$eoqt{VRcYOeXNit2jyb&EFqcY+3i~`X?-*1)qU8j zE~v|da|e{uwWcAp6z}HbN>@XZ3u~cEft@O^AY>2S=`qLqolT5&irl1NT}-gVLiOJ% zlM?L&3gZSFH~;QE05s?z$y7A7&7YB6O0Y5S{AjH zaj^N-ZR0E&+GY}V=o-J{xQ0BlHec^v*4@HZ(2ffo6Y4Kf50<{Fm4Zsp6q8_9W28$- zX#7w3oSqa6v_U*XYy)BLH7$?j9psk4zlyh^XYhUY5+9429b#jk<5F!%0Nylkrh-6Y zX~G!D7(|_JT&cfJKMAfDFH+`G1vSJ)L8ndB>oPDz0fjU^y?ZP}tr$zQ_$*QqJl4I+ZpbGqorW!WZi_WPdA2}+qdJO*+x_* z;VVwUakT4xHK#P!dIiP@5lhl9`alc<&AKl~44#z_PPHcV2Ov1H85Q(sv@0{2P&FSD z$fz;iB07|SK?7wECxHdj4G0B;t8xCOZwO;6(4)i~d7vzJe~=%HmI|?eHHifla11p4 z{LVObfdMvDe;*ySxLXP3glVfyXCbiGBIbxLUC-^ch|!xo?IVZ!lWf6s;eNeM)NARG zUH~NaJmB$bKcnaEvTK#lAe7_9mSPDo`KgwYJ;lo952u$i*?M(3{F?RAA2nzQ+%YEP zEBV}!*%;~JWu%~tBF~&U&J<6wWRBVq3!n+!jBiwkQq)K%)WRr(Bi@n{c6d9_NjYZz z%oXz&w+hHcl4bfHEROO+TZwbWY^&`+)2HA(K2iaF5g>W2dpuEJn1o17ICt9UP2n(A zpGa!oz#R*9He`$d{+|GRrPdGYrk&CEGfcdM!DAx7X*y7sKqR}s zK*bMR1jJcqCCSyd97gqFhKnlx{^R}fak-A#Ip2aYVp)HF`)Yi=gMzWCdT>wkxRHa- zwjU-ekvBaZm-?irxKP1Y7tWhJ$Jp}`A2daI(hnDD4!=g9uJ!Kp!&__G=XoQp#cubm zlVc=kC!n3bbl{xi1pazFkDeN4=TzE{jY0i(EX{ZV#S8kepmdh(uM99`68m^f7$Kz?}m+^ z8q-+tclw)6z%v$^nrV@R1n{fc7a~m?BLxQU>Z8+%TLZSKBb;9+#!d{JEDH>wMZGmpr%noq^~$^tOv=luNKh<(*0&<@PujbHeMNR!*!h$Ee0Hl6DM!7{CGGw zNpGz#M2>L3EL__TW(?X~ ze7$cL1821L$Fa>}J@XFiuw(DGo(Jc$PXxH%=x+oMHJgYBl@P4`vyt3aQ{P}WCl9(+ z;&Nm~a^qxtwbb=dw+!vpp93-vul;qykGXJH_VF~NaqAZE6gb$lXx9;KQX!258$ly<-MFsVWDXnDKgGlvXpH2z-B_xpz&-itFM&M; z4W0~1(zB{u4yJxt%rDlYE&mLeeg0w+LTR@!b&9Ver`1#+jQ zRnxNQeM&3@CZfQeD!t~Cq9t8sI@h*66#^>ng){wqq8xp}LKz5VZ4#AP1|t#HJql_} z1wFayiE%ru-}n^QYpYB~^$Zo+xbJ~eI^nWi!P|Bp8`Rp%WMB3DNn4;CsK9DbCA0$H z-X%dn{2>%)fa$p1GMCck2yN3_&<1&8V(BlYl^H=w;W}-}s&}?sSe}_I%ut^oW8ln6 zU{#OB_BM_wPTp<^gJ9PkGeQKbZueaN<%CL@&R+ou3-Ky0#ZLk9Jf&e1a=^SK)Fi$1zVTT3{5%gz#N_x&kQV9f=59UUWfOHRsNA$SK$~!%Y zQee*_DJ$59k%|D$%lTS!;fqQxE^3%(DKECFchMe4b?0Xr|o?*etYC zDd+)sv-RSp?0)eY0uOv~BVD3O8Etdh#aF;12%m|jbZ%U606A}&!5DA=PRbBhpzc*x ztM?J8T3Y==fu-WfUiG!ouc|X^NY6vcOktU&iPa~|B=%dd&05vTP*~W1MV>Rwr*thg zkHWH`#t;1&XH00>##9S!6eG$c15FTO_>($!OlkA_wHI;QZD=7n!#R&iHyT2;-si@q zkxr+;i3Us<_|lxJmCoJKs`DfDlG1&%37VH-B@({dJVD;`&bi~V{;;iq0Ewx+dRl|V z|4ieiN1@+H%ZgO|?89o2l(176H$2s$`JwO5uzt(}AN*KyKX}%cS=3I>Hrpi7m!&wm zyz-+!SBomO2wK|%pkxSm7(lMB#&l1IV`g=*TfK#?)mr@nn)6t)P0g?7>MbQpmq@#tXIbM3r~wwZ}1TEy~7eF|j_jMC%K_?E22Zafy?OPZW$&_MYZ zV{^xKoST2|RgB-axdplhR3Qb$3N+;~g%;zn>wXQ#BL3>$#kiski=oHLb-3Z3dYKya zefX{2$Q{jgOJ7CQ7IhLOZ1KA+C$-KNMl85^<#FuRE z+hZlvwv%EHH)aa1P{0NNyDPU4f~<;!n^TD2vV1{(O-55hVmG^I0ZKk*xCda)&jh`a zZ$6~q=Jha?cYAfz%j>*D0Hx+7dN1rnl?(dxFJN=q@c0E>&ch^z2;Z^l4cWKq#sF`8 zb{uUlfO*OVJfNF;baXUDG1JsI08%9aVY_kEtutlgFUxjfyIs#SOYHAGCnu39o%ixK zcbQEk+!i!a`6fAz&h%1&)^#I@MQ_#ns+rkC?#F)^0QzH&OrUmXtIS0uo-YFg^9zI)Zj7V%_tlW@!uG;*I7drqyrI4R6 zt>}MshoL9t_8ikUa&D;KQ~910tlM`clMjk(FY#$9I?{_{#r5Q%+3eHWBFn{TtV0Yc z0cAP?y5uJPJcH%1VZB#aB*ISzmAdDQlJ0MIKchK1oEq%zyx-6uX12~quSDRbwfUPd z{2|7L@%)SaQC?;? zsSU)rTYpmRddqPGv^m;YX!L%H?y_&6-Xl{0`QN?&mLM25F)bo|%WZi9e6LR;IG_z) z!uq;;7LaG@ej^i1w=-;4QhgpPGrV5N7Jm@&AOulGJ)3UJro9bor9?v1%Ajn#se$5? zyb=*S6jgkqmJu8~Pq9{0Y(y73i~rl_4Xm^hJG3uYvI;i|9GOF3*&-eSFiCT%6EWg) zumG&|AK&!alE-+9NGT!EK6o8iNj3ZE{2}XVijTLm?Eos1*Sl2W5^u*gwu<^&=%q%v)4A2Q-&OXu_x~qsPdM9YLMB+} zvSU_=PixCAaw?x9E<@~wk3Izl;xXR61?;|IeG@rt-X~(fjKSYnlbw z{E=>brdD^qT;H7n4lI5Db@bhx+zjj}4V zQ6OK**<2isnfn#d{Nxc-{x4`;xU*1g3EYP&AR*P9q)TD+N@w^r$hXgyK9U85i#Kc+ z&mOPhtz_jezK@HDNe7=iaMSsQ5BTKm3eIvi={+uLzlR!T!}dgXgWmFjzme4ZqiR|A z%5`cWNI{<-0W_YEi{HEKq7-A6Xu>=$J19}U%^dH&6B6UVom#(K;cxIk66!H_OuQyX_J zP$n>f^>J^yBX&PGd89gX5g=dWRew4S)xN$?|C!9!Nshv)|NjI|lP%EFlDLTB1Y&`o zt5wKbhAK%bGP<>bB%aWW1CeJHvI_r<<_6pmIvI&z+(5ye{|Fvt^Jl??IPap2Ag#IRh}Eu*nZr-;18h_3SzR9~ zcSZkQS&?r&-UDy_t$FJhWLAiVQCw^8e7t#uCITMMkX#0~arzWvV}`wGK`a^zPyQ4m z|0o8azSp{&wTyV>wGxkZE3-mDL_3QA#0R>wsah>T$RYFP=CA~M+_0AzBoOQCsI@XE@iV|T<#&$;La|2G~qSgjBK?F1K-|2{l(-m9d?)C7Jzn}u^m7t_LdLx4# zF`D0`@NBP)irGx`kX&h5y@Ld4<5Pjo0VHx-zh}aiQ$8&Tbe&u)@O6qQhL;AKd|DFZ z@6AmURQ-#p!V(k0vz;I#r7OQ2v`xwS;jaO397Ye4uBTeTI%aO&thI_uLPeeW1dMFB zscw#Aec2u70#~EOscXtAJHD)ap!vm(vCoIE+SHiLtpO;6U{_Achfq{DfPeChI_sWg38z1W zp7yfWLuCnq`G2)jU>qoM)z3yfEj$YKjqU0FN&GQLC6`%(wx%sBjO)x1vX zsyr!UXS;PFu=)te1BT>6(y9jGaX97Ck)cX+alBn&y=6t}lpD9l?Eli{GJ90v*RRF4 zwu*R{N|Cf^u=3ELAcMHXadL2*mmu%Bxf(Eox;D zALn--{RM)t!nyXEpg#nkWgJ8bspj6?IPD5JeUHGdAjpvWPQ3f>f==&#(An17u3 zYjO&miag04iDlnvOYNKhb}Nbew1x=0_AAUjA}$2JxL zv|tbjzb>8QPA5+1RV#g0*o)unZ_un(T(XIkWYeE34&8{19sEWTp0 zpB>uY%!E1{7jr&*FU>(y>cw&hKEzagq`B~)Ml}%kj1u86(#PH z7L06jI79<9xf$41`)(*Er_Cbzwv=8m+KP`>i-`Ygka>VG-$HV-!zVl>UuRq$+6#RY zE!NxaN318aw66GttwKhF-E?XE*|zbGwk+q9NM#|34cW0W_i2Y!%K{CtKlwU1$T@`W za7;S&ycJ-1;9Y_TKc<54?RMI0px16E@SQ2AQ=TQ3Q@%Y5r~y};Px-*Kb3sh>#Y}~9 z17uD;e8LKqA$w!12W=uNno|9E*HEfK7lOI{n zV>_m0A%9Dfw6Ri&bBcbv!gI=12Iy6eAi}wqaEi@1jGy{_HPZ(Eq7we))uRy?4`J zLK+1x%VCv!KRvCh0tRYzpV`dy6~QjotsL2=ybwF3z(K#>*Z?n&z{P|3DeH!s&T|%n zk5Tbz_SrO~o_62NaSgUAO`AL!*Q_oCZFpKH2TlL}Sv<>Okuj-l?m@+6Hhv)dAR<*v zzJKBJQ?}XV7$8nSlsK!}3YF+V@*zqN5YSHWar(!(=5EsdPxW{>Wyq$QP>E%MQ1rG4 zNh4Maj*heh>jfE(t07=hY`e94oftkh6-67sVS;W;F&DH3o<=@Zw~uOxhEw~g4s4jM z{Q$Uk!$fAp6cbPWnkR=cknHWtjipgi!?tY+1mgq%wKw9i0)M(r$o%5U4%<=4;7S;@ z-$N1r^)iNCx}qmJ;Tieb;w29DWbX#k@5ATh8;~lFWcG;A4y-yac&R@2v`KjzG%k(j z)x>V=VZC`LH$Y{0&+OxQPPXR|KHgAY-L-~_RQKnAVq+PYhH@$z;nUL{Exs{&-LiDa zzbP8|`bu$Y-jy0^0YM%+zV9P{V*%o_75s~18F6U5cOX155SejTtJ&w5?_yz$xQ=3l zX1Q=Prr;7#wK5?2(*>T4J)Vz`p#E`*9wptQDeZrJ=>|v5fd+MmW1PnJ(ef!Q@lpzg zH{3wwzUfL84|Xi;x>sktlui0lRiM)t#)`4~8sl^7+!qWpl@8F_$!iymiBQ!I(2J9U zjW9ARO_sY6kSpR$PnJJ-$dzE^vzKPAllHen|B-X6J*wZN z&Xm%sP?71?<5(*aLA)2Fij_julChT+J_n1f6VVvr>VgV}*G;u|5l@SIWQi+3UxJ2y z+-}2K+`qNXzqFfUt3L}Fy4+}Z^&!Wy0c76RweauCI?M@X2Q045kWqMR2~~<-2NW@F zph=Pw`$eT9s!}XfU6*H)YZsl{3%~!#AQr7fv5>H##hj0vj%Lo-{O2RO}t&Q8z6c2+*;> zxk;74E^CIUnPQUB2P|4yIz0FA)#o{p*~z1eoO(ljD0n3neQaY_s= z^`i(;m7sJFM3OGuzRGj0fa;1jXf7yiJXU~=H=aqt5R!W7=kyVczk24S%ZJ?Gcw1@) z2#m|%!DO@5P3OZ{gyXXb?XAJWlK=EsSWe}jj+L_7-;oc_Kazmw9H6%)e7G-WB_7~Wh>2X!ztbWIIW zf+#NXSlA&Ad$rqziOkOU6irf+}v+v5s9}nM&xAk5r@Gy&q@+ z9F=(BGh=Lrc|qIETkNi@gdZtVaAgxPIY4`ZeTj7lhLA``u!cnx5|L}}Ul3e` zSJ=-FFy__E*wPGt!K~wZ-qL>y<2*7cv1djQI@ST&E`q4KJm}r1_q(XO{$= zEnG)76njzW&>D|Tz=n=SbfN_z;XONzW;@cc|B`?I|7cj`vEJWf=3kFKGl!dV_sixG z_{H++TlPP&PIqyP)f4TAY-Gp%St5@i^Sa$Earm3?y1@lewMBpAHlso8T*Ncqk(cur z=Yp1P1|@yBI5uHr3x9IyiJV7IKy;x0DwKDtCGrTVemMQ%8Vyed>_#sM7%D81RS)w3 zEsQsQD?bEaA++g2n8?g2y2+rjphC-~(}QU{-I=@G6|OsnDL15%tx$45b@234vv3 zxGVqnui0?n@<`pVNN7l*Ur=igg){R8+w=Ets^OpY5}H|WQn;WQ=<1HkQ%a?Oz%g7# zor`$h+UUcawHssdYgKGGI@XgLC&G%`{JSM>b|JvE@XL3*zJW~Nv4OA9_-iDb*4&AH*#S$Gxc1>!IpzZ_wJz!^cjGd@vYlh@Zf$llS#7<(S~^=-p`tl3NdIscAHzE!q# zW;0nL!e@PfW5Cwtdv4xXz59E5KY5cqFlpzj$QIFT;VfoFl7VE3VF@>S7SChM=}%k& z+lIcR(l?W+z#}JpAE8lg?^VOAm;B4e2dVWifnuD_`-Y3OMgPa?cTpk`0!OS~V+blA zBDV5=S-u`B#Oe#QajwV}B%+)c2x12ATGtf8RMy+w>zAj)1_TL1kG7u8QfT0shKwKH%!7XK5a-oIWUA{UZe5 z^`!=V4HY(V`Acg!We~LVbIRZ_KcwTAN1McSfKAYeTKNPv?%m_~O%Ki$(44s|hOq~} z>=G~Wf-%S&y@xoa;d3&fbwT2rW449PJQdV>ZP!jR{~t%%hYprcr>h6 zeI=?H6#P+lwMM=JzLQPT=pqdWUuDAxe-73VG*xXCDzy2O0D5?CN494M!Q$FDl>UT8 z+y+4#1}<9Tv`e==LR2773T&>xrVH~US?uSynTlzk+!p1FrP}mlqFdnV`voa5Xbc7<2e5c#(@3tuu9hMgiQBvVukR|@;o?Nz=)IemXJlvRCQx?tSn z(B6w=hx`?~--%p;vgfVo+gtP)j&cO=!m+Ct+AeGY>cCOYJaDRkU})BSempd@p1?>bU)CMgQxM~)fB_KIKhp{JL6%J6pyqelGFY1#L^eFsTt zw-U{zh7?~#zNnTOh~DR!Gx110J6xN-9bCbH2`Al>G|J-wFJZ+NwyLbr3Y5Pd>M}dS z_BX?V-+BCNK24xDoB)ZOehWQzORYTqF3On5RP22(BxyBt+>5_hL>U_ryX|{XwV0^& z4pLoqT{1EYf=kfNa%Y-fDE6{LEo4%faBm4GnxU!Ho3`EM4BNRLg8MpYPbSKBi}NO! zukhK%hL>wRnPsEm5{A>Oyn(?%y}Vz$uqg~l7dO4t2Ijx{Bx6hqUJSoa!s=W?*aijj zmQQk*Y&%Z#)VTSS399$CPV}l7d41DG#_pkORD6YzunV{Qnx9+#p2q_uX$!qDgs;25l{XYGVebX@DkmfEcC9T8_q9oaVw!MM z5y(y&>E~Q0$2rwP8gLEAk~ukY;-I*8OI61Z11zOixAa5Q%%= znc#|x#KlcciI0^TttH?uBggzY2%-PTc0wACT7cu`A9U`>=if28*r-+1f{ zT@@ZkJy>x67)3x^yf!1y=u#k1@|ejC`<-{#!ohPZh{W!JxzYelK(fCwR8=v{??1^e z^5tsduvCLVj+Ohn-$nHG)v@;5r(4E)?H^l>{OLEn>iJ)hp{2lhmPByHcvg18RMH;_WFjsgana|N z%`#0Tq8nz&)WVr-uQ!}uBUmiNvir4C;U*5?J?Lacqh9`H)^84ddg<|(vwrC0^%$p+ zv|+Qnu%WoxXYiR0H)Whp4}4{RTUdW&|BNHOBE_RjNAu*}3BV+HO>mkzKUcHImq1gV z(YmJFf6Q=U75Kl(Gs3C{+77vH(yqT{H7A$H*le(Wuy=730e3jh=B+?6W+!ta4J;EM zxa}1RTNT0^RZ)9<$=+5gI~=Lf<~ zVDr!j*;Cj_Nuuz6?TGE+0ZTe1ng-v*Qj;u?B&Mxd0TRuzq_ElKF&%LX!X#j#-D>&B z>fp?TGf@1oK|SfT%cX}px&!`hBo|AFgx{N3)D(CgS#xG@IdU#EJ`8cmgzUUfV_eyh zd>fKoQF1KjFn{D}xPc*}QgLq|>*8u45UdwNtxnsZG8YUyC#@~XF5%P(d56_94u_do zY_<`P0dL5SqPok=E33NH3LCMa?CU#tM-IC3{685NI0z_Tcw3#fv@%)GM5=D%6z*B? z_MFQIhq$4{>^kwfy~Y&Zl7j=)RTc86RAI4O;9fcZ-zj8(>HH@aSfaGApaTy18quOU z!;yAzMWh+mT)%)P9XQ#@twZavefsronLFo>zrtteq^3JhoM{3nk1%1vbI ztUOY=*`3Jxih%;8z3>uvxDI*PhVNoU4=qZqJsibLShfpQzoL)_-xe3S>~a14q1>Qh zo|Rl4Kq2$~79N@ILB4v9T258&uh;)D$F!+4HukGDG7|)vOg{+yJQ1&w$%O0)NeQ>Q zvhFAREOa~f6|Eq!-|~~-*BK3}x-`&cfcQnaKYS?C(!@DRW3ow(D1(RSiKIwL^4{J& zS9@$yGIW2yvn|~lUNT11yGzbb{GY5gn+SKfAl|EW3`aD&^n&2^pxrlF0bk-EfRqd| zgLa~YXQ`nCb_g{~-P5i9;59qbQPziiXxCzwo`6N3{i@8Qo$X)qB`@cVshFL8^2kF} z+7CytEp|RT1vfmvLQ2M@pT7kgsd!EbM~3MK33Lhgu4Df-$T@3@Hh|1P*`VaKE+|j} zXZkzn5oi5Bt=_ecH;s3PCM3h7n%^aS!^MjYB`TPMT>ldh^e)VDBQ7BSLmtt=TY=e; zc3vBnp^$H-+0gGX!~u7I=R|+X!I9fbvF_hGGrQ^il%Wo+I^L;ou$K?B*>Xiig+KCW zJ}CdlEY6~o9*K08vaYFcyZ`MW&HOo98 z_%qhsC^$Qimch)u8+zaG8{DQCYgE0pir$L+EasXdIS!4IpVCg&sqc~!Of|;^oA6?py4tp&NwD{8kshHMV*M|>@uNMc z>~-ZXHrf96__>$MPHVnO_CNIw;goFu{EsXS>9X;7eFlU$hmGPi z3wy1ve*HH z<+GSr7z>1b(7d;9gIB^9Jy1!n!*~=X#Sy58li=xO zK!Ev(w2-38h%}^b(&oJ9NNXx5`il(USug6>SfDRn!4twFwB`TM1VcP@{MM=1U=|#{-&%i8o4ezr)e)+jPLBux{mV_IHDXo=IIbbIH^wkJ%mcje9XbYZI*F*EzqO>^;?W&}Q>rXxtN9*l&7$bv(lNoqA=W+(|KJNxZ@~a|KRp_* z^vqFN0$>0C#6*wbk}~EpZ(ypQCNZ;ibJaosuWo=8{9P_jE;!QtY`EL}?kf-;ji6z` z%`~HG2zm2rDm3b1S8VEeRa!OV&KpK9w~nI@y7sFtGtU_!(b1++ljs+}Lp!G^rCr`TBVd;etxGe`Y5p49XHWi(W)9?5>M(6T?TCd+hY_8f4(()v>J6v^)>XlY}%P8iHbAoWksXWivjG6B(>LgOcsi6m*J)#uXM~OoT^m$m)7;uosxCsAS z6z`$pQ2=lqq(;|fnRI8`fS6Uwz;0=uEp{dd_a-X1?qQ%2PrKM5e7``1Q3dF-Of;(A zs`|6MqBq2JB#5(OpE2r{ir(Wl_E@mFmkB~Gd^ZY=snB;s7-*q<2s_92rWvEQHKJZo zf1Tv{S(nV0L^p#^)a`JZ)2YxZ@BG7J+8BUoP2Vr4N?LLbRDcw9>#7%{kdYGJ_Yj$+ zTwn<#lhvKQ(hDD?n)|850rpsI#a>*rIE3eu(tGrBInTN3M)1y>9A~?Su!)m%uZUi5 zcWX<^(Mi|kDt7l~VxFCzJbfYu^Zz~^1409t2TBeCYnu5>XPY` z@~rWd#Q)#$$J4)|MDc~13EI|K{i-eJ^IVtrE8)7)#?oRESLo9ow+`gMMf!t?R3q^E&ZhAzX*Ir}(VOX^-v64cMMV4r-} zNNTG3yKy%RDMN>oH$xJJ453dycfmcT0)OPVIqbuk4MQ;;G*76cIMYJBW6XKqc29M4Gn7TdZ9DHQCPZ@%v z56g&_LQuc|w{jJ}Q0qNw?f7VmKdt3cl(ULMX5q^Eo*C}Nv1cL4r96H=-MbdzphSrw z?gDi$?*vrf#o|QticGds52G&SNE+Iz@(ib|Z|i87(`{rRTYDDsYODgIgRl<;v}kA6PPF$^+?L z>8k{q4uAde^O5qWs?pE9R+Puw6T2U|lmZ>Dt$>srB>hO{B$xh!1ZJt(PBYcYz2)ux zBiA~M3|_)lJ01_O-Av#mP3c7m)=2J}v{wQ^`s(>X55+lZ@F7y9&Te%JxO#XvSLP-E zhW_C<&Y~7jV0thqUe=}#=(?MB#K$@tv7>B3#jGlc>%V-hz1&J!R=i@TDN{*pv_5wZ zJa;qICz&ctfH#*(icH1>nQAEndyE*=&y|i7j(q|;sMB6Egx)Mi?ymU~b6L(n2peSx zonX$o%+$HT3Z>gd+tII5aK)IY&j`P-?Io-zIM2&%z}}>!3AI!Ecs4Llzc&33{I66m ztOv)C9s7o*9642TXyz)$y2oTVL`NOL?;V@}LK)29QpjDiHwn_@-s$a-;Xh#2t>!Z`;GQ-EiFHE%-9ae`$Jw zxz}!`P6xnP5>3cvAR4};mn!rL4)$LoRN zxqe4{DT^co#~rymrQ4^JIS@0ttk~`}I6r!2Hf9#6sOAuWT?CoZtu?zp(ieV>EHAWT zic&6X8u4nL?RL+ZpNtfSJI}q2fC#?7k!TsSb%RXZA}6ta5eX&26}qgNK|8b3Ofu+j z{0RM>@Ao$C3-}Ke5E!wqDEM#N7R_XvzC$gAbE`IF=BstCSBp5{4R$f+4?>UxKHMu~ z=C4Ggyex>NNc5Z)f^+Fw4XhxW7#O5Zvvq(KV+?r#;BU&Bpo%PQxU6D z+E!>(1`ZfH0ah3KKt9c2p+eNq-m7bOztgx2S+!`@2Z`T_TH{vEUDz~*7w7aUjqO3s z+aZa7QS3pP@*5sRpy%y23s&3lXKB%-Qv;0lKVxoa-Mc&%lnB<@Saxe%u>uICX9t{( zUYXt4dCTF3iYb@hBL6Bre6QLFr%a(_JwbJ_w(r9rouq&wK6rVAXwT(806HE1xAr|F zswmF~R+MXImwLw&g;^*dgfG>at4ebo^5%(<2Gr)UtF7fCbfl=vk->oYVE?m;2lv)>&s&G|`?fVZu~m*tyGJ7)8pPh)jB9Ny2v^0Zr*bzPOUXv|z;(T*$R zh4|=PGgtXdg(Mw-)1rIS+!ypfn$oT=}KY7rTR~9CZ5g>RVv?9y$ z>;9Nni!6;QO29!%YzkYxxT8g0PeO*jy0%q(pKmH$I{$x2=u{pQMcgB0JsfxQpRl&d z>+#6ikzk?0ocBo3I&~l<$gMn;(@8=~a<3uqD^V3OQ;(q zyRFb%5}=gL!mc04y(a(5qO@S_d5jv0bc}4ESqvW`tKvt(`3x1w(=7Ggw!&OwKq<#G z*fz9!@0>!9H6X8&!`4H2HfZnEdPLBRUc__H zo4*9ahd<(5K_IE{Y%*X!roFl0ZDgM?M%+_8MKuc6?N81B*O*wB&;HlG)SXi?s}xXkD*jLgWaMLqPF2EWiXa;af+&>dgxj!YB7Z5LT@YX674)M50=nX{~A5@w@&E* zirBH>CEO7cDz60rsM8H`SB$V!_t{35rgpdg4bKr%WJ5$@im+Y_^vxmletC`uC{I9s zAP9K>kiySEJX4@8eO+g0|0l&Qxn5s4%6LOLLk0UkqUsufb^@Pa(A%JyjpjVn2B1&2 zf*BWEGh`rem9gfJO?QNbOKgwTkvpYKljg_@ZUozG`s18kQ>Rjn^7>I~#+uIqm%{@+xiQjBu9AiH3-K z_q{8R{~Yr0B`{(fM!?UQDg{Vj=GMn2nS9~_eh&repGVN1NmtcXB5%HleP||NOF5+j zVYkc(^9C>n3)`s-(SD&Qki<{95)no9q0+_$cwaf!n%|W!;pd0c;S?^U-d zZNGpQ9@)_O*$`f?x&^?wVr%IlGHDr-DG02Mnh)T~Rj9MCfH21Bb#HJJejY-nSghFk zpxz(iC}-gu(dP}@9kL6>SAl|s1Xj$SO-+}NZPPTV7y;!S=8dTf_vMHi=F`fHSzWQw zrf`@JHA5-=4ZRdtUc$lWev>pY9pj_K-JVm&cU>P$@tnkEQBRoz4?YS1^z=gbDzMat zpc191P5yn$hgzZIk@6jkzeQ}tlyM;c4&$;|2JY-; zfOMWf&U(G~$=YFbUe8Z2jhgVir1y;&SU!oQj3cIJ^$QyLz=qyRHv!~Ua>QtU zjB{3-EUx<0|8UEn$g=eUp3GNnkk}HkW+J;ku86eXZi(G=LQ=RjU|xi-Et5}vAmp5Q zx}>FZXmLs~(jqorpC$(h*Bg`n_CyLSlg#&lR0|1ZMnqY~U{@yah&c<-3Q8e#2pb%` zyjHHh3kPPTuLQTL1!8jtIr_!3b5AZtH>f+;>$;LkBD}^+!Cw39o}Z|E5(j>}KM zz{6%K@ri`-&(9>ZV9=6WSDr1L3H`Vd)I6`ss%|Ic6Q&Kex82tti_5Q2(J%}nk%;Ig zxW*-P`8%=*Vt{ZDRIPh13{hsI3()TzN9>4U&~)^afS2 zc3^9y-*Q+ZP-Xrj^CFJi#ZtFA%QsH95pK`ozb*;&U|?oRLo^sWXw6VrfuxvJQS(u?c8N8Y{@jb3d6S>~bu8neR< z7jOUXzO?jGXdIZ5l8au42aHA{*jk#3H^*H;eyXgl|3j3L*Qx4Jl@SArhln0Sv4L9q z)qmhg#Jam6yJU!;$o*Trm`fx8`pe(x2gj+zj$3pA4NvGYf~7NMPWn2Kt>94>H_I$t z?52K;hCC{0q_EP%1dsn}3DsN`r1PPflFa?0%VGcTPwva&<*;w|sT$-}_-6|}ZrI8} z#9eOJq(#*@F-lREi;UMDu_)766O_m(Tb<=h$`Gz*N!8p>`Lf_)wVoA&=VgH@x(lL} zrl493t$bueJN{X4wBCiFrGt+aaUCliZg_Yswx(;b^|d;j_Nbe@luxF1M(N(nAv&0N z2ljsexn3-|qsQMg^ms`TgubQL zLr~p;x&*BS0gE7c*T}!Xf&8llu#@4gM8tAA%GWp6Z;L zFE!`Qh~NSTDXO0M<|A4xc~=@}WcLNiGWYidGypq)zC#|8Wxy&I)}<>>5KadCER4yw z{r@12o?y@xR%c}nYVyPyEmVjmDc@FXV0A5;udQL`8EFe(dJtfDP47oX*>7EJ7hEhO zwNC7kF}0=}$3i7>7r-dOk$+n#Eay3BF=LZ;Z)U$h!+$rwU09&8>*fMV!0Ky5h$#l?1 z(_zLWPt>yn*ZVKmY`S`DA_zalrx|q4#$O6?e5i4J@_r;sWT`1MH8VQ!uW=G)M2|Co z(C9vZR*tUQBTIjh=3!tn)GVKQG)xe)9kSnjGcSNW>-7(Li_&3 z0B?yjx@dQQLChFT{oXS>JZnQ^e#-z3M<+Hjt|b0uO6YNTAfQfmfv%3A;-|@NB>Z;9 zUEQq=SxC-#{c3*YGD^o2M|cL)xYEt!akN~|%U8vf|NsC0{}*4Cd0NwSFxvgR*#cI! zfvnH7GY%RYgK>sm`iNMIR1N{t<84{h>yY2CKQ^%bpN~7&Ie|#HI0Qw?U$6l1^Yuaw z*Sl8^JR=TmRC%*5oVo;MneEsA#J+Nd!jAFhnoyr?rY1pL)yS~nM6*d*?9Z)Zj3gzH ze-`c4@rP>pzMrOXkB%e>I9l3W;>Jg^(BoLQN@K~g*|m_Ix_Kb~2`8Xs4Js@?HxEWP zyQvh^=xHXaxQfh!&*N1g^4Eep{;L!SLDeV7{a|{ey$$yW0F`L8$#B67{G6?; z%oodZ-VK-{*_@aTSuv66V%czl5(`M%{yk)X>t@DXKuWQa=^=^2_pPc3ka21BY~_9_ z;GnG9`WTCQXn%jJrF0}(|OD1{3jvEm*~>gU;EVf06Xqo4BQ>TDXD z8KNM=2IkFQ>A;)1sD9ag(SmNP7i2kR5WkVnvE`7}@@G?!$#Ds*R?f5ASeJ#xptZHi z<+U+FwtpkeJ_0gVIR3Q8?_Kr$(+DR4y@=Kv@4seopCX6^Yn(;xi5=!fhU!|TDuU<& zrN&mS6V3;-+YVNUIB5+$+KlozjIK-y6-f441GG2`M4LQEiz3kV!TU6udtflpXqx;XzV3X>4v-cdL{FpaJ1Fv!}i@2#T$d;=y_R?#Br%oq;5nyHYrgDkZK8d7;?4qU#i zxB2X{;_vvh+SqwkU6_>~l?CgU;jS&RqDr3*EcZi)ho7M^?iPr&PF_~nAk-7b8&oI57O26gH&-AC8wxe|bbW{;cM()fP zdVOj>5;1cCrN#cdVBR#m4znPvNH~)GUYQzU?T@o^*<>zV1g) z;p*1p=0UhZa0r8<=WaUla*=1<;HrO)n`VdPjhl(2D00EEVEwYVre6F8Ct|USn{_uW z#BbgK1&3_ZCb5VsUq5tM;s|KhgMF~b4A zpu%uuo}e3;$f(iOO5b9!`yC_NCJu|)FB@*o za=Ux2L=Wc6*Btzp-dT6QMBjsN_GU+1&Q6*?G}A@l(sXY1$Aof&^s9~KYs&$eF9xF( zVfZ{k)fwM?5ZM`-k96A+V_PX_os~FME`^0X#bI7qedS1J~MRWVWJxF$ptWFftX zX@a9s(dn#{*kdQ(-Bm5Es{Vj?_iyfvxAe-JMMc7b{IfF(V>l)KoTJ0=5b$`-_XL1p z8$l;)6qCM|dp|qucmfSr(bLne;9&%l_e;q!exDqD>lD!(JI=lRGmbCQd$E1O+3Q%4b$-G15|U>Qd=m@Oq<+fZ5Sc zZOG$Ok4^|k*=y8cVR!qSZ#!}OwiH2aO7Zm0a+(xNNU!Ya^%DE6BABYxPE~+Cf0!!+XRR z`XAjhkoM({8;vao0J!Y%b}HrwxgQy0tXKGxFCre2-xAgs7bbKO=rBkGN(l`;?yEt1*k*>0be?5wURn-tE3c zRU6o$V8=qF+R`pO-6_|qd;k3t0MN8M=3P?ZRMtAaQx$+Q!`ka~$%1DVmTq~r$^RJq z*Oujk115ryP+i2+{@B;%Chne*riHXeihm?lnfpgpWA9nU&eBB&RFbaDv1I(}Bz$~z ztwi<@&iTHKdo1!+IVC3tK2jYkGb!h@j>ntnk_(<_xqH+O|;31aa9Lez;%(bK6PE-xML=N$tx zKwlxowIEnZ=-$VmZ!TdNZ}IaO8*Z?3JHK@D&Ga6z?ktZPZg?p}diGz`$4z>BWq z-#s@FCbYUZ!KJsvgp_AJYXx#@Wumg`r0JINABt0TR)u;PQ&b1QHLiM(P?p#1 zH9%r;@YeruQ3d}xz@k0}UxqY$bvO{^2X$HcLB*0^hMRQ|C~xh9U}0D%Q&=+9q^pz8 zKL?wa;ymBfw0G-)qaR4*Fucv4xhfF7833{oA+vI1d+v>IaG1fW6Nhv#?1k9~xB1Vg$F(_R`h`mr^7E^yFEpav?c2#Yce4+< zNk$HI4$tO(c|CZ3ZP){MZxo(W{V(RaW?``73;n+#3KPN7!UDeV0}*^J*0uiI@_(Si zF0S#O+Hgp~!YZUcx!wEKYI78k ze6i9#wcodi!>78Mpj>gp`Bkah<+J$=8_{$9sm?}~6a&fa$xNd|Kr|jxh9NQenRY&x zsU%|(cHm?Iu+-WOLXig8SN3BJ@gp8z`)S{76I17CaQmy4AoXCf{`2Cr1pp;$x(FkRsCc z3vVi0(&kE;Ep3!hR6DzauNr~0Kr5lIJfh_Gz#=k*0lDwD2JB3_ifBOZ;2!Lh3qJ9h z2+C@x({-QY|LiYZ*G?3CD^Ukg@OlNO);iu^TY2I7W{FzYe`2Nk9WhW)Us*2CxSJ`b z?YwYF2Q<96;C3?ag2S;!JO19F;Pq?WxIp3UL`+rE#?JS)jPX8Iv}urAzHny;n{r=$ zaG~%M;i6L?{m0aV>;t^Ac{}|uPP@M>ibwaox!AONJ(3;DJ0F2If^vRMXki?sx~9{g z_HGQ{lW^dy-%u@yW56}(Y91&S7k8pVB?l(tmIuU{RxGasS7-XJK5{;j=f#?`(sKtz zZ9SzD(t3PlodDf~erMNeb-2PI@Mh`ITk_2b9g%}X^GVVH6;Ho_fC;a#(14rNvTgdr zdE!KDF>)_9ks3#Xm-NC~1KgW2o#u9Gma35&j}F#XpZ)jGUn+qH_QwQ2wuUxHn%x#o zbN_)xo1d_J>zUt*MDK=vok=L!Z|nePwABdDPT=>PV2;`8VdMqpf=YdQe<4saiR7DH z;xbL>bY-}N3uSsnjx;iyOYFbN#@ozl$89RuLRb5p<)Dkm8n<_ciQ6mr{7AmGfX-eN zxc!PNDk$n)0009300RI30{{R6039Dkwlj%GDktZK4;$il<~v{>STRxYAg~au1Uyy_08a6u2*F)|{yC(ce?B$Q;Bl-d= z^Uqv==c&Y~3g-1nBIC-Sj*jqi&O}51GSkvePFT0iWw+L9vkR4aky(e=k{gg<7}b59 zN)gdGK&@SUSCTLexVyW*D%B0vkI**t4&QX0u;F;6)Z zkVM^P| z5q%0X;kXsEtmcse;89{btJwv5w~cLpL#km9lcJZYsrzW;q12CQ}{{&<%WlKAt6 zIwkTbJa0>!?SLhb(46GuAgL&S(xp~gSWI3P5giucW5yi)m$G(#dkK;S_CR$W2oZ~F z^@1jAU52St*fJFDq=A+5Eq(^UWHND$g45AE`2;saN`K5j2($xv#Hk*qDBxJRl9fRt zhPREZd9-1b+>Q0eJE^fq&UgEy(d+}p=97HS}={UX$Y~9 z?oqf%LIJG8N&l9{yufyRxe4xZvjK2A{tgAXGxW%7J8N?CZLfI?3}2kwPz|U}02M|5 zDRq<{;QjlX)su_jwU>pAN0v*nd0W!m2y(UrZI49AudiT<&P!b%8OrcV~hq zzR06@eQA?f>*9(cW;yKwHl3PP=r|a`2?3hCxFgPy_;nn`?igfJ!lmhu9Z1vkC4lc3 zI8UG40}sZih~Jpe-|DSU6h~SqU>T6Z1_9N-geW~?!?ZsKpc}xMb5IWUJa%L2+1ZdjmC3=7JD%3r!xzD3Bw6}@+7d!b-Iq!pet4dV|r4U)sXY{N8p$j zleXMc`a@89*%VP$18s4|d4Z?JJ{vIB`#194Gcfo6@c;j<|MC3z!0i0mW`F+@#@WaI zg;WfCv-|#aXYmt>$(xzcg)fDlmI175GTP1(=9L1-1fvBUwWsZ|VdO2W^P%U6aUj7V z+&p{O=r^rydvHxsz?$)60*%Tb2VBq@Gn;kqjHH+0M+(`2PeLC5$u3ze9huZ|K+8j^ zD2y3a%wj2^tu9=NmC`~KIzRmiNRKdI3qx=1>vl2m!0W3SU`$3q=Je?9YUdv91PruB zvnsjaN(k-j>E_GI7sx_ZhP*nCE#R_4N44VVBl!zDfj+eI6q83|?pQL%d_s}Op3=R6 z=}5itfoJTQCaP4t*UpnUUTD}NgzpxvM92V~m;;h@8sKjMiuw5I?L|G~+gVEL7}28v z0wBe92qSl%%LhcvTg2%8b(Fw~SHKS{gAFrq;_rQFKbD5`5`2U0SNz6Io2tmbSe7#j zKnkN9=(j8es5hz=j!nN-V()65e-r}_N}F-UiB7EJ*Sf`%=ywFMTAY5fb*hm%*%y_~ z+>#!|f}I{kC@U^zPr-o@DIP3$&>Tx;)NMyzd*_p<0MheeLAxz(`hQ$Ow>~RJ!%d%* z+o?bTbfOWbW<()PpgDqZqg!naeXW(1St7enXO!4ut5G^l-pIJJRG2yRwbBDM1{y`sNn20K$~(f z=dp4Rf+Fx0Xs(6{K16YJAGAh6>}iLNtZL)Gn*U3OQl7M+z}gbVSdXntObHYJo3oss zctQZDXa#F)3my9thVT4dk$oe#eV2N33ptqhGnmszdknCvARe5r=jsq|a9CCjAnPm| zJVd##2L-5PN`)o`$(r7_Cc zVLGi4V11aG)JuWh?R3Bi{oy&!Qun%c??kRPtd{VsM59pT9fR)%@&tc#T~N^51nbJ1!7rBfv3HukT{vnI`K2169T~QHk+M%HByE zxbU^7EWT>*N%YnnnaobRZ75Sy9KB|#R3hTKx^7X3@k9NNL>`G)BDGAEFurFE_M*l2 z1z@#b6S4zk{j8qZ!_LqZ1w|-!1V?J0>axmZgGGA= zDDp}NyMHcLTq3SqQb34sG)SEY{o|zP=3es8;py-;F8}|p>-UFipFaeW1ozByAM$z_ ziP;f{SL-GBumAtu;=lHPr(z5VOL6JCZQ_tNcMwy^d{N5d>8B=PJk4B5gybYq$t~Uw zK@m|~9L*JeP%dz1s+nJ;y(dO{A-YIFE^dfd7Qt+Xx~67S-fCz+R297UOeJ2g(i(NA zes$LAVyqO>=Vm-PLG7a-mb?X;9CV`f!|mwi!dC%ab&b*I&f4!OX(~(k{(aR_3+6o+ z>SxvW2zJFxCFZHi1UN1i>?HnDr8$}Jw*GU4eF)=#vynhc9;medN<>L^>hvS#8LKN3 z%DnwTs`Jy(H8j&2wT*c-!mHOIne4jL`D%>HiD%b|Pn8{;2BB!1^#-)mIBKQz+56Og z(9}}g+O?H80_pwlCc;%+s14#eBW%RaSMcAemDfKzZr6KJ+llF)@gggAYT#?O(kbmH z*v-`tzXn$c8W(;x(itcffe_J!401^N*in+i8EX+z+pt)wvi%Kk8S(hjes)FSr-YUI zgW8yW=h;LD|G_AJ()A{Scl|#b#Wh(_Tsres?kA+`7ytkN{zGziw1T?;OP1sM^>%p= zEF=<#Da#zkH@k94S3{%eey<;j7)T-P}>A7mx)6kh!2LEZ5?7tl{{WXprBkjeB5 z+9Eqd5RPQTzLKdceEUae#A$%lLMxYL;a1+dKqmm^h4=r5JOu8**Yo8$68yGnYrDY-V!V#qL(OzUrT>NdO=`#s5V$>ssbyQ+>@k~hBanh?oV z%a+rS#mZ*27sk|(l=bk?4ng5@;*2APGc8*FVFX(B;H2_i{Pj5~IzbpMGmQYJ3mf^u z1+NdK59K^w!(*eHI*&bNdpjZA{fD5scXRUU)VS9nSk9R(MuC4O@y9_3OcQ)=bo_6m z{I(eIC@?sxxeBtf%QT{~AtQwAFfV$#58#;3L%dbWetK6F%5VSw@?LKo3*Y&X)3;}R zG9$R$cG8YY5r3SGL&$nqJ^~8&8T}+_-%maUDf>L~x*YpEjR6_pY7H=C7~E`X_m~Sp zDTC#qh{?}ib{BWuAIdpTZ^&DMV_NHkCk?V__qSbMI#~iMYTG^f^_wjH`hSGjr9*zC z28%tpvR<5(sd+T1bT=heIUHCi6n?TA|K#+0(Xq&!zp=-B_wNFvTKS1j>4=n$GvTlP zLLE%swN#?iax7s;dG230ec6GHokluE`BZEkzbvtn-A{fgGP%Wq~C z+Wg_x;Tp^w_2S|a6ND;x^+lh5Y#%E(M|nQx{pn<>KSD3hD)OQqa+q1~=kOybusVuJPDnm50dV)L}qv^C=EI;ei4w!h`WeQMd?Q5`T9b3EU9RVHNmG#-Gak?$fpKfB*G6=Vi@xwp;$e z4m)9g%Dznqcm6PN|M^^DRgZtp6iN{hv$em2ppV{jJ+k)py}TM>>Rq?AUf#O!T-mty zRW`^uujHT%hKP!d8vyDt*$yYkz{Vt;zUwK0R|O4uz=?*RZ%ytKi=FDPf3ord_`?L1 zsC8xGG0|+tLa38>dZAflmZ(I1Ob8BFRt|$vdpQy)sn<&&W1ZGLZl@}|pF^U)C!>Hy^oFukb_lX(9oKLoG!_tUtr-@CkoUG0 z%Q~nPB6Wy-w{9govnwVC?;@mUTf^5?`)Zvg? zk-^qzE`jWg@Wt(&{KYWsxK;t88Q&?ZyhCn)_Kn{{~0yAWCB zCzD> zes5|0h&w#eJ2kGlqb>WK$0kzUr|&OW{+O2_(li&qVG>|9%Sx|$0ymSrCnGW4k|z*$ zVX@XtWHS+Q4?B&BJO61*${S%`X~#&x?RV>GrW0YGwoU&0HSpOFxq31_rysj(KKn?4vfH(>q7dq| zw9sI@L@ZGohsYU$HZ3Zcj?LDaS;zp%5!bWe$kr-`@jo+%eO}Ji0n0^BmGtP^fm`NqgEveUupf0(G^b_x~E(T zfXb01?3R1&cQwoOOqki;Sx1Me0AoO$zqn7BYj>iE`Y!kEeTz|m4ytl+unElr|2kH? z^bMgW{KQNt-_FzW#F;oUQ3ac zfnFXJi>utT;GcwQQ)KJjXh zPc6YmZ1oIRnyx6A*Yv_qk0iwm$)@4%y1ie#Q&4c}6SaTTU{DI0Q_0pI6;pVq(1i@$ z0%6}GT(?G^4lS5Ipv>l^B*Q9H08UX-)n#mXRPlnAvOE`W=N7#5&=Q9rJQvGSCjJFt zUlmU4Je$b8#!0MN3&+8Jd;9Q>>98b14V0~PXwY zMp11oG{p@-;fI(_W6dfdYR)TuF@bEovn~2)v+`_S?e_UF@Tk`dyCbMFZY6AOhEUI7 zSbN{VDPIu3>)b39>K}9Sz-7D0@3A$oo}XSb*8wPm+$zKd4z{oLsOJ$$swm{rz*`vj z749_&htUXn51IWZ4hlHa2@`q;eiozua=pAe^-$o0;X*6?osxX-lJjl0PNE=3fQR_= zuxbx9KC!o1>NJ6sa6Mu?U6n5A!kNuC?wk4=l>D=^tlwEJ;0`Ynj)=(gn%73BiU!FtjfLpS*Rxxt?X)Pb)5ZMS}14y zAc13YDj4Im#{LQi5O0i`|3~?yXYPh65e;UPQpR+}z+$c07=S^bx^q9p=4B>Wf98O7 z{0IG!{ql{>={@b2NIxd8Ov-Mg+h_(LIK?ycrKly|w83Sx=*2{N@@)K5I+uEpRaeExy+&9OUhPw=8G;Ds|+4J)bO6F-eiR4$LmyfjSuAgQwK8Ra$I8jh0N0bx{qkPwy zbVIlj8p$X1durlf6fVnFBWXJMI)*GEC`4lKRYzvpXGuE4sVn37&g}m9!wmWZ{?l)O zT+bOznn*ZLSO?r~6dV`KBXL9`>i^E-Bgtc2?Xc*RYx|5>6<>;YVv+;pGm(?a!OxHh z6u{COb+Xv!&FVXKf1F66k?DSS|};1f4lr@+y@9Xfj= zW$thlJU^CeJQ}w@(f)QP4{i=bqR71E=bc}RX)O&cx?Wm9jktN0K`i?AOXn<}KLf{F zel&@M`hWOm=$Vs@ZVWjU50O10x5r8Q3l`=;;EhnIZyzlpY~>Yc0YppwURv9xn{@6# z85_%C#~VL{aC_2c543BRS67_m`TrdENaNESw7D&1IDWuFfg-CC$gW>-9dWDtHrl7T z{snO7{*Bj)-#nS`O|;l~i(PE^ef&uLg*P!MMTNVWMe={uY&A(Y@0Ec_^jhiV)&l`b z0h8y=L(^Xog zLG&~9GfP$4E@|O-*Iryt80#myw#EpF)8Ro{ZkKRKY}fceU?<^1-yrDHIa6iW#~|ji zS${&SI9yMD8;hSAP2;Fo8=><;QA-9cs9ZBx@dWX^tp!b!S1N!B+vO|P;OZAWNm-IW zlHrEofzeYhaekoYq9dr<<7Tiqmvgh29wfBh0jeVu0)VxnkM*ZXEy9QW4b7$q&<3IX zdZgUR_n1mWEs|nwEV2pN;!&`5ZWaGp#-iX5Tbg-}=0}SP#Tp-i~63Z~45iwZ)F7HSik6OtO4XN@M9)TgTo$ z-ZZ^i-g?j>`X4B-W%gV6YsCHM5TSt7#b2hIu$5N5+e^z?uHc>iZO1+asApBtC8{cJ zAsK88=~e$mNna`$D?EHX+Xb5T$mDHS`FDvLzNtb^q!ooDEP!DE`z^>lXSNva+!>+M z@)?Z!=$oU;%8%j0k+Bb@Y$3$u%Z8G1$MCX~%FpR0Z@!KB0vk))Rjwzq@{H0wjB*S` zR)Nsl0@OZ~$D65qa$4K?u#^pgGsygMFXmf#A0qpRVCVN_yIhEe;1}n*<=<9mqF<7~ zwioWm=8)`rjHQwgdGGA6R`He2!W4CNIygbhpk*e2LOxw7>O(#u+zBee3%F$D2?yBz z{;#Xbk(o+Jm?RM_O=|lW@{$d{y*4eb)QY4>v|;TDw5hC(iZ?8l^=Rxh_ydIGjFVD@ z4g7BZkvQ+h@1{&f@>`IJgtk)4W+2SKB%Cx4t2Tm0;)fDxhSu~l2)ivMFa$A$5KSWl zP7_M}uB=+Uj0>(X&ZB+d%i zF2PlKIhoGtsqVF`a}B`(U-mwwee7KHet*YeAOf7(FQa!1%qg9C%>3GJ19d-yr!pYE zGEVO;Xk}ZSy8?6(CVB4h*st+Wm*^aWOW3ocV}Vj;W$Q|FM=h_grwvcOiCWVtpfiD) zA8zxNGC6@h>R35(Jf~_6Vja7QlMLuBfd}gr;0{KM-0+BPS~)7RGZFvy>7$)w%D?~q zE|>rR|M46ZPp{10n4b=`_+Gbmjk5p#7F-)4|NsC0uV!CA|HtF{AOGjUW+G?*F=ydg z4JY>og^HbP2=*%4(5IbPQbW#jQWTH9!@VSt{`rHwU{2@BYu`0a%r94FpYuaTUq8@h zRsTG?Ho0h9XL6x21n?6zEU5_h7%K@BM!8uhBFxKB)Pbj@8a4ZqP%qoxAxeChqG;3n zE(BeBNqJ0Ni@95ejk)n7ch#0@=O3QG1ST9ZpMcq>hTK^ zMmt8BRDBRg^n!xHfr&2Cpu-R2%RDmYEst`z)4mnl6R^B zNa;9pW2FD@WRBqSY*a}6wuh$LH>g_>rEr|ijwiQ+iU#W}poR*pl~@y{cK5hPc)CE~ z@3>Ab__-U0c1`&veA4Wd*cE@E;Ni@$HxK{+|Bq@KV@SmT3AOy#VJi9C;NC2QeNjSV zB}zBWQ{=m&_%pKS5>cGvoA3EC!;TPE%8jn|L|6Yh*n%W%gy&IUj{EZjB<^fiqV>>? z3aBMS^N-M<1D`d7j-Sz_A?q5q2OjlGby=_H9wHgIX190w0ATKQU^YMnjwqOjXcYw^F&e`8dbJ1O> z_B-*Sg{D;f11RHyH-A(TMpA@J^qVH*Y8l}20QY;txNFP}Kq#ndd9HHTHuZzpa)6$< z7N!z|NMQP)3i04dLa3CtI-Z{o<$4_YcWl^A+xRILATAy;jR#sxDJYPGar|GGuwIih ztPH~YES9#bd3|+nv_P^ZhQxnc$Cv^8_LRrT{Ri@qOABJ#m{L4qrDoER+M!HpeYxrI zWIund`kyAXBOr8Fo!~66ytr|C-6sddD9;9xyH_f|h0K2-x(Dlf z5LHCx#sIiHvsqf?!6%J{BbsohKHFL;P1N>brT=ISX{*JaTCbMK``)+44P2n`fP6X_9;45{rMjso6v1 zMFn-75PHr~8^+?S z7>3!|+Ix7x(w+t|7p>6d%aAph1g|ze;d!=P;pfrX)Y1MkRr=xW?<67rqfB!$2mjNU zbCO<@5Iaf}A=B{t%>7l6Hs=axFY&Y-m11K*abW|rV%`^c<_4T4YNfFi#tEO1Q?-mM z;FFY)lFE5~4A9KGOYRf~#_<%W~E--aZhb$#S!K;>z3g1;rkZ4VaK9WEL%_TbW;&yBn_y zMA~8Z6p^%=!4wvO_!FsOxrm1S7pLs@=jG@q|NsBB7ym$#le-N@KEL?S%GdF|a%Zca zYl$!azIHKR*~fxiYF+<~go2}Dh|b3CzKpxi%m20REA6FSf|b4T{O|GT8c9Hf_v~)0 z)?ro#!4io1EM5xT-3$`-ehh#CGKY<>K7FjLO?<6HBi%E1A)E` z75D}ku}iX6COBj49Y~QhZa#?Pfjb z->YB4JuS+NT+FeUeeuw0Kfm%O?(5S?mL6}Ueq=im4v;mUnP|yNBe#RvHOjvsads*I zdLg?z2ksN&GlVw;K|#B6l!Jj>k9$FGZdL?>wM7F-ua}pO#R#9+ypX`z`Jz0uM%swD zc_GT9@F;TO(>UJ(bJCqH+bmf%5T{)&JDSo1cFPIGsZU8!VeQpkuPgdH?9QRaY%^)y z=))Fxxb^#dMjJ~RX9CmW3Od)=a@w-ot8`sGcLw{aRha`z*8?_#5D{0B56#+0wsq>l7v;Th@(2d)5C*oktrW`3UDLl36SjV8du^Az9~RvQ8LE#Dz} z>15q*GUT(>54X=kAEbLX`w#Y$`nT*A)8JQ)3Q%!yd*1mDaV|Yq+~>Es_Um8Q6pZ2) zxnCSn2~g8g=yrF_^%>qG(_+qW0-SQ#-mG-e>`VRE4B|Y=iME^t7ovVrQ&GcM4@nBs zIqbLzu$9X%KV??9*(N&`pnjYJ|4&sH}+Bc&;xJf&3 z@9FHU!afeNt)?x(C3cR)6*>o44+8hra80g~|ZQ{h`YX7ML$5?T4Zvwk?@wk#WZA1sUpuHd!WHt~G zi&X(9OP|XmZ3A@+cG1zghR2Rv-%jI9@_pmI#(4efKxekNZ{UCGw34(;|2>mVJQEyJ zaBD+bt50pWe%XwUMr9!}wJ@K%8p{6=(M5TrNcqcA)(KwxHznvkG~}>SdaYHZk+!?1 znfK@rYR1(ZJo)@DFNgOxIx~QTBY;uCOqVYVx*P)Kn;-xG_rL$!$;dY*Jw05nPGJeY1-tB#>LB~g+e zw>t!Bb7Z$v6MAV_?TB4*A8d>ZKsg9Ij$nanX#IhA;Rqq^@QsFVcB(OHYzn@fgGX-& zEc~TItK3C-lFZ5=WtgfbB2NzKLFGA%M3JQu zoR1t0d@F~8ZejNEs?Bid;WGov>|NM;xc6yfjSp2nZjNe}@|JPre6?u0`N(c-($ zC?Ac=*|9!OUUA%(+`|-v2a-|-bdu+N+MzxTE=Xyc9K`DLAVoN@xZk8GAPu&6C@>};N zx09~ok4j+guF~SWFUea=t`{okHZ}4jqPviFauI0?a{aYU9~-+79z95ale#u+rXa4W z{eVWd*iho|F zESH)7TSB)^9W8tZzm<}+7g)+%SdzCqg1cm|6V+HHIh_)K0xkTk^5$NCCWv0b{yVxt@Hj3n5{MF5CNj2JK>FzVOfD(0#Elac>?!cvD=RQNAh7toF4yNR ztvvLf`}iMDa1PzbQAM7LM=_t~`Mq>DK@h@oE^rrnx+Ref!pQsJiQ&8XJ3wiMq&|At zFHv|t?AR`y4WFX!{oQy~Yu$KgdSh4+&x}+-qN=0O>bDv;79G;wQVgUf$r_I1w;ER7 zid0YYo(jkKT&0+O0aMMqG7bJw-*H3ysT3nDO0a_wZ??7FW!Eup&+;`;BdEBL+VSbC zhja~Z-_+Hx<0Flu+bu%0v!x!nboP0|>SV_VfDnb9VO>7{+1fAxpP(;0rP3ilAW4czjtCidaOVnL(Ep>w54ph=OG4 z?SQQ3E6p7NBVCV&70h>|X4-_15J_0P2g=RB7OR<^GJLC^1Fq+lr+8_SjkkDk{R`sE za-l->s>-rM{;BRfUPEk?H4U==qSegayMTknTv%RAAN& ztmP*XA_x+DDL0zFr)DeVS)uug!5!Rv8_VJuYu?vCDj~oS>X?2XaTV zt7^W+rA6wNx4SB7EKrWFCpMCTPRjJKK&Z;VI_}*Cqpo;Z4vSw;^9IU5k?zR5JZjqt znLX1KH<44Be%Z^CWxq4xHy_N3w#2s@s5i~gX5LQ|(%YspY+7t5(Eg%!ga{PH$Pr}b?Og$+Eh1!wm8>5?lXul=#cTMk()Xx)eRpj;8{F9$e>Knu%*!u9 zl>WtEnE20Joe62{{Uip%?OQ7k9+-?wz8erGAFUt8Vh=4Z_Z4v(#iO!)$TJ!IInm@? zmg8v?)GJu8=CI2K8w^8W#U(h_da2^lvyk*7}h8I#Uz?-fIct)ce++JT2@RqhwT{-@DKXT63^jqZDen%{e3g zj7(yHX(RF7N!9&}q8->4u`}n$4jb(0&$8}{sUM{PbOPR|XWvmJJ=<8isQ{^%u^pzj zpm2;S@-lNm$A-~iymlwwS+5_^Ha{)FF^5hHQF@OP{G;X`!p zXrL!+B$(YG+$xthPOJV($oO#wKZkqrWmlIF+*u5P7LgC33Q_SjWIellFGB#)SK7E!dO)N?CZ;aBB(A{&EO_S71j z$K$l(s~j4=by7(V-OoP>a)g-oLGr-fVe;Sjhst&y@H$crYYkmX_=CyG^e=dDV|Sip zRK=V}n?yA=5zYVXOaX&$(;cApb?!&Kt_ec{2Qa%DLw4oW%dX@tYYzIN0O9wLzk zb!2I;9A2{Xix{*l#%A=Yxm0bNuI-^o53^K1(E~O)LZ@8}12*3pkgrN*!mlCM8X$|g!D%=SZWwPr~d2AQ970Y%0cr%rN zI#thRVgx6>(}W=?RMht4%P!cp9|_X8OZKF*^;w_1={r39xg|7XQFHmIzajsBt0NJ; zWVAx#UHh)$42sZwC270Dk289;_wK@V*f#~gsl#@dZY4s&J56-f-l?e=>eb_{cz?%Q zB8dm8KK!=iejp}=O1Ii*OWf6c z`;eeaD08s4Y!fv(B_4I*VObqAw=##Kyhlsy?kI9?TdV*|a0Zdd*}(}nHn+8%JQl3I zH_yhJI}e7vd)hJ{@KbH0k=8_S@zrbGGAuwn(un=50k+#sV#Le!Bz#;c=-dK7(Nkw3 zIJkkpsi)9MjRUEh0IX6q9XMd95PooPIdFrAa$3hBMsyde+F~9`eZ)JGz57H#XTY7#z!X8u zWg*`i<03awfj6^&_1&h8Mv`gz)%)fW5ojRd8&^5CS&x7_M1FU*n&?nhMS{~I0a+#g z(;b&03FlAqKmRTW2qxdjX;u%053Q^}^rnx@Rf^5K@dagUsr15E)7P80E#hFzQR*kG zXk1R@!GVpu>oAyQMgj@;df&bg_Ts2LFpD zqKUM0IMZQg3;0^&MhOwH1zNa1W99hDU(g1?(dSX{-VB_)E?LUba7^YNYnm_~$)grH;P^m*Wo0G40oYT7ECittpGQvD)|FsU(LR{aIUHs@) z^^a3A88&EFb{WUyQ~RsrMWFr1mioNL*&c0dTl>CNc*=E)9p6p*rJH+SAHqGL@KM4F zZ6VwMhKY6SO)nWG3r-7a36n&v|B4BlLW~@U0b`e9y<_P(3~f(Z)UbjUrbr${A8kfyIb;^?59BC|F?{2(EG&eBXFuG+RfT zdvZsb*Gc3YPB>)wynraE=ZrnG9f?D83nYlzO*TMx-)y4sqqE}+53}==l5@}-8T8~; z5`voote!T;-Zwnz4adbigS-?QoX-h0!phqr5kW$y=i;dnHBkfa99dRB@8ba4zmo?%EARf?xlA>WR-YIhzVf2bj3)S_`NLoA^_Y zA*N0ov&<2@rUK^T0AN}@#77VU6f-3RhPTSS+?55<^=;)VrbR0`qyhNe@e1=A4|Aq7 zD$RQ?Ecg@mXR^1Vu@nSj3?FtK=L|lp`dJ2zwtw55t0l>iyHS^-)#xn)fc2n#<$;$W z7z791KqNcK6Q5T}!Zq3&4SwAa_=M#kadFr@7&kd&^HNLlcy15ng-fD1kjK75&j6z! zK)Fd5Q#lI}QV&r}X}NZZETmgHo(N_t2yC&B3a92~{A%sv@x0JaM7!~w8_k>I@N_WI zI>zYlC?cs`Fb9nbPJzgvznZiyO?;h$Hj2ycH~Y$szeG_JPuWX5PBF? zdy_I}AkOU5(-Dd=O0~UFJ0{J^J4s9?6FvRV7s|N3gpnr`ou6~W$Q|?ytNdndGmHeU zANjldGhP3S=#{@%sM~-RjO-K`R}VI=A7JQtxhD$MGi^OV0tT;bC1TX z!z6a?SUIgNEzTC_z@&_FP^fm3m7C(I*h{k|iJP|!BWLd9V#BR<8qHnIL9BMTVC5o) z&};YY&(ZQPQuYP4I-g#Ae^U$Dsck>LH>QK~?-3KSy={#HG4Q{ABL`P)5XuPhmBlPs zOa1;)6`}W;hb@f{8dV8ht2UCSyaII6oAJbd5NPWofYCpna7tVq{HN)ZcAwm@6M^v7 zs?Ps3crzCD#N6aEFv-PJ28dqb6)6Weh38 zK1I{-ySXCcf^YE;x@PD85`vF(e7ko^Q&Q0mp`O18iyE0i2Wy%)?uW%n+sl*tX29Z?n!;_% z!Kj(|VscaX_+_t{BJ@oFOJGh(EeEcgh+6;COzUm^Co@+`fL5L{6wghikAsCdl9ie#h#uFT*69te@(%IzX4*Gt#(U4jwmK zN*`PudWC)|px2g=Klxa>Kgt;)u)&r*05V)jB1I2uW4OHrG%|39I&hOkSgQW#EU=IP ztFuXVZ5XZVgxj*huVkN9lad8Hte5|jze>(=rjAovCCWb=0bwW% z60%wa$)GR9Ac>H%Pm*Uqo4!k5?s19)aOi%%x>jHerzfzN3IE@pTak1JB4eyWr8^lX zcp71AHyVVYe^dv*_Dmx3{kU};(*(@0XE|QO0gVWYmzaeC4yCS8(w#;;YKPgd*>k?(NL&`G=D{Z zY|Xt4qc8xr`Doc!ukI441A-gS=E7b?TctXY8kV0eP^#^^2kT8jx}?-;?sqp@8N)>u zNENii5$Kzm3M|hYyLec!?Ir!R!M@)?(#v?WukJ=R3S&7f4D5<0fxi{T!%@{^WX&fm z85f2UB3YPppnUKSqkt>JjcjByTrx9$Ej%_?e^R`);yKG73r=A>6yCI0pe){QuK z84nBoxc?`~782rrDnski(D-a^r+J{OKKL2DFU_du=gBP}@ewuWQjv9)QQ5)@IwaL3 zz+3ErTcc0n$9{C)O_)kHM)a@)PEWx%k4kjBxiG{v9lgk6vOB>NxVawIP8tG38Ys^;XHyuH|>Qcq8l%$uT4}p{gPb5VPafht8J%i=@*pp11tLJ^};}0cVB& zk|F{kCos)*#zTj46t)zd#XjsZ6w}_LckJ?S`{I`kjvqV?goDhA^_`m)H(e67lz~7xo181-o6eaG%J3kw0Y&|NsC0|NL!Q9C`!>oWAqGejz|{bf5WwB0Kw=Iu-}w&j@q*G3T{12N_D}`yJ?4)E)zpUo1B|A^;Cqb zP=~ls8#K9&LU`mq|EguSM;xFf4^dcJIenKdZh-;jzzGR_s|MT^sAWaJ6>Z~vZ7Rn3 z0an2ucpAq4C}P@tCSj8j*%0-XB>^!hl-iQTwkEcWqm`rM^AIMK2_Q z0m(&SYRVUgKU0PTYE<8#bL|D!gsX|S*lq)oo>|b2UqAO7s*2)qYLP994^u~h_m)t9 z1-q6hg`JVuHD>y%7t=K?!cF?n94MG}yDW^CE|;hOx~Foo6AHRKh3&bQ)1i-~4ck!j z*(GpG45@j`OLRyqAY#D{fhug|zy*M@sjO2K#R^xf=Zqa4P>@oC3c?7;k=JELngut9 zii_t_n^k7gFp8bPyF)L78OUAPXhwkF{qYSM%g~h0ad9js5wdKfmtOw-21n#u2Xh%?Xth zo}Kw&>utrO#L^|apb0!(PNAVPLubP)DAJ5TTudXANshJtF8P@#9hKqaA|Mx@^`}U9 zW<6^k;S$TNPKC;g1ThyA2kEBYbhcV2K{HBSN4@Ebdw_H~WwaVnruH&>g z*`2JZz+VBV!T5UN%{lk&^pH)g6U!!n+z@%pig$NR-v`1sm8pQtqbh2&;*%yu zPVkENz-*{JuT}zD6u3j8M#Eltu)@y>67sEUcf~;7oMu}LHX`U}Mgltck?w91p3n8~ zhppJivxfs-oS;Iniz1^_)%$9EI-RnX1Q?pSx#~{sJA%?I#Fg}%qp*oqF>x@rRWf%t zc-+`)A_yx9*WMip5tmA@ifAQMhjeg&XT}i3DpdSeb78cvNQNg%|1_=X5`-$xYo6`c ziCC^G#?J*r1z2Gdlw?FU>K)ntJTVCrEWdaIya~$(${G)OeF(tqL303RGcdq~a~~~# z+ye%VEPAc$vv>W6I%8|vGKCj<1^$u`*Fk5E0g>T$p#T&V6Y>JPwp>P^i9l9A0o!PY zy-ibvHw`A$rjbEG3&zg7Qfkd(*As)57?I_Ts=5D1Hyan^wt$G% zT=r*PLodYx%ky&1g`btOM*F?%f{#y{IR0-j8o8 zus^`nUauyZn~4DFrbNVn-XI-c#Dk|_>i;r5Yq>uSJkq*Oovr)8=qs5K{zn1mx(BcC zjaz-zAszETZiAu_`@jHZoT>4^a!wvEzJSSmsNm%xOktVSe-3UU%E`J|s|6dnwMT8h zF;dpn0&843E1O{M%59nf9=o+Kc6&~u7Qa4SwRr?E0t3w@pYOT5!U~ir2!E3v@;aO_ zT@?jO5~}%8YBM#rv0e7$zQInE4}WK9he6x8;PwXJMDdN5>twUH_JKiav##`#xla%A zpro=2T2@_bY{RE?3U13>8_9CiD=!UkCXx-a??e?!=333K*H62)n9L^1^+DzIq*dOv z>>J1}iXGAl?HPyTu#E}(*SZ4J@39VN!e~0Jm>rRgKXpDdLp>qX43Ot4Z)UX%Q2Tg2**D+AaZte z@`r%_J>UQT{IM$`4+744-FQdAM;`BvFcDlE7_xr?^!p-OT&G|LAY}AGZIC}BBh)SY z5vcRZ0Y`-uhAviFlNby3^9&n$_kt=B2p&=7&4Vgl%6{ zb~&P!upbA(GF8KU6gv8H=yu;#J#(Mai8^`%p)507_jNbkQi!GB?PxDCG7;KpHO`Wq zIDPNDphUB?hnJSaU`xXy&(RaePT>BeF^-j)quV?JFFOUaq@%1~I7naoe~%(c_Djgb z+(aEyO!FYJ+P;}6nu&|X`PmQfo;q;)4ar0>;T@*v71NrxO{}$qFSMCfsD`~MVDxtgw{GcXapiiP$GurA^Ugs2|1yHHH=IdENM6tx4I|Qcnq@D! zf=)&98bPp%@PwmW~Z%iIFoo&gUKF@C{9ma+$iU@mGs*UJjcNbaI?5(qw zYFSX(33G{lpJIJ^YT5xO3sy0XSOvkinkXN}E#$?A+|x5yZQKiv4DNm`xN3JDv1)2L zjAH;!p226V998UJihx#Zr+kVlY-y$`7Xwl1>%ldfTd&u;8F`L$<*f@w3*c`7Vu3!8 zp`1R53-^og8bW%ol_*ZhBt+7Qr2WB#d907-mWs{Aa^`#Tzdc5ULIw|vSGQh_z6js& zKXaG9&n=KJd~EJf2NAJOMLgWag>j9LWTwZ?=>!Wx$tk(323@xJSCiHt;1P6GBwx-2 zzkNaf<7&}#snVgvMR#uEVdeIs0&83HsTK;@

dI*Fh0+ahPl}q|Du$z<`|C0 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 rDxnHiPMhAlgXIC);L^Gp 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

!MnjG-qyKP|;wGPT{ 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%0DGMlC=PNkQ{5*75G_q!L5ROS4K0(1 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

h;Wu$+Zqjz42%HrC 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

22h76hEp~rhF$>7zlQ=i*6vti!X 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℞^>7?f{zKP^U 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℞^>7?f{zKP^UyV`@H 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�!}IE+|7t)R(cd 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 int leadingFrameCount = static_cast(config.leadingSec * config.fps); - int scoreFrameCount = static_cast((totalPlayTimeSec + config.trailingSec) * config.fps); - int totalFrameCount = leadingFrameCount + scoreFrameCount; + int scoreFrameCount = static_cast(totalPlayTimeSec * config.fps); + int trailingFrameCount = static_cast(config.trailingSec * config.fps); + int totalFrameCount = leadingFrameCount + scoreFrameCount + trailingFrameCount; LOGI() << "totalPlayTime: " << totalPlayTimeSec << " sec" << " frame count " << totalFrameCount; m_progress.start(); - bool ok = generateLeadingFrames(encoder, notation, painter, frame, config, totalFrameCount); - if (!ok) { + // Add score title + if (!generateLeadingFrames(encoder, notation, painter, frame, config, totalFrameCount)) { return; } - ok = generateScoreFrames(encoder, notation, painter, frame, config, totalPlayTimeSec, leadingFrameCount, totalFrameCount); - if (!ok) { + // Add score frames + if (!generateScoreFrames(encoder, notation, painter, frame, config, totalPlayTimeSec, leadingFrameCount, totalFrameCount)) { + return; + } + + // Add "Made with MuseScore" + if (!generateTrailingFrames(encoder, config)) { return; } @@ -419,12 +425,34 @@ bool VideoWriter::generateLeadingFrames(muse::media::IVideoEncoderPtr encoder, I return true; } +bool VideoWriter::generateTrailingFrames(muse::media::IVideoEncoderPtr encoder, const Config& config) +{ + int trailingFrameCount = static_cast(config.trailingSec * config.fps); + if (trailingFrameCount <= 0) { + return true; + } + + static const muse::io::path_t RESOURCE_PATH = ":/videoexport/internal/resources/video_made_with.mp4"; + + muse::io::File resource(RESOURCE_PATH); + if (!resource.open(muse::io::File::ReadOnly)) { + return true; + } + + muse::ByteArray videoData = resource.readAll(); + resource.close(); + + encoder->encodeVideo(videoData, trailingFrameCount); + + return true; +} + bool VideoWriter::generateScoreFrames(muse::media::IVideoEncoderPtr encoder, INotationPtr notation, Painter& painter, QImage& frame, const Config& config, float totalPlayTimeSec, int leadingFrameCount, int totalFrameCount) { - int scoreFrameCount = static_cast((totalPlayTimeSec + config.trailingSec) * config.fps); + int scoreFrameCount = static_cast(totalPlayTimeSec * config.fps); if (scoreFrameCount <= 0) { return true; } diff --git a/src/importexport/videoexport/internal/videowriter.h b/src/importexport/videoexport/internal/videowriter.h index 863366f43083d..73c569ed701de 100644 --- a/src/importexport/videoexport/internal/videowriter.h +++ b/src/importexport/videoexport/internal/videowriter.h @@ -86,6 +86,8 @@ class VideoWriter : public project::INotationWriter, public muse::Contextable, p bool generateScoreFrames(muse::media::IVideoEncoderPtr encoder, notation::INotationPtr notation, muse::draw::Painter& painter, QImage& frame, const Config& config, float totalPlayTimeSec, int leadingFrameCount, int totalFrameCount); + bool generateTrailingFrames(muse::media::IVideoEncoderPtr encoder, const Config& config); + struct ScoreRestoreData { engraving::MStyle style; From 3c5a8cc689c8d9e3b707e37e7bad588aca311730 Mon Sep 17 00:00:00 2001 From: Eism Date: Wed, 18 Mar 2026 12:13:12 +0200 Subject: [PATCH 44/52] freed sws contexts in video encoders --- .../media/internal/ffmpeg/v4/ffmpeglibhandler.cpp | 4 +++- .../media/internal/ffmpeg/v4/ffmpeglibhandler.h | 1 + .../media/internal/ffmpeg/v4/videoencoder.cpp | 12 +++++++++++- .../media/internal/ffmpeg/v5/ffmpeglibhandler.cpp | 4 +++- .../media/internal/ffmpeg/v5/ffmpeglibhandler.h | 1 + .../media/internal/ffmpeg/v5/videoencoder.cpp | 12 +++++++++++- .../media/internal/ffmpeg/v6/ffmpeglibhandler.cpp | 4 +++- .../media/internal/ffmpeg/v6/ffmpeglibhandler.h | 1 + .../media/internal/ffmpeg/v6/videoencoder.cpp | 12 +++++++++++- .../media/internal/ffmpeg/v7/ffmpeglibhandler.cpp | 4 +++- .../media/internal/ffmpeg/v7/ffmpeglibhandler.h | 1 + .../media/internal/ffmpeg/v7/videoencoder.cpp | 12 +++++++++++- .../media/internal/ffmpeg/v8/ffmpeglibhandler.cpp | 4 +++- .../media/internal/ffmpeg/v8/ffmpeglibhandler.h | 1 + .../media/internal/ffmpeg/v8/videoencoder.cpp | 12 +++++++++++- 15 files changed, 75 insertions(+), 10 deletions(-) diff --git a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp index da68fe592b0fb..9ed061587ecc3 100644 --- a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.cpp @@ -106,6 +106,7 @@ bool FFmpegLibHandler::loadApi() // libswscale RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); RESOLVE_FROM(m_swsScaleLibrary, sws_scale); + RESOLVE_FROM(m_swsScaleLibrary, sws_freeContext); return functionsValid(); } @@ -182,7 +183,7 @@ bool FFmpegLibHandler::functionsValid() const && av_frame_alloc && av_frame_free && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts && av_malloc - && sws_getCachedContext && sws_scale; + && sws_getCachedContext && sws_scale && sws_freeContext; } void FFmpegLibHandler::clearFunctions() @@ -227,5 +228,6 @@ void FFmpegLibHandler::clearFunctions() av_packet_rescale_ts = nullptr; sws_getCachedContext = nullptr; sws_scale = nullptr; + sws_freeContext = nullptr; } } diff --git a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h index 95ad9b4588b5d..da7dff48a5fac 100644 --- a/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v4/ffmpeglibhandler.h @@ -96,6 +96,7 @@ class FFmpegLibHandler const double* param) = nullptr; int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]) = nullptr; + void (*sws_freeContext)(SwsContext* swsContext) = nullptr; private: void* getSymbol(void* lib, const char* name) const; bool tryLoadPath(void*& lib, const io::path_t& fullPath); diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp index 2cca66581d663..d22869a9cd199 100644 --- a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp @@ -314,6 +314,11 @@ void VideoEncoder::close() m_ffmpeg->ppicture = 0; } + if (m_ffmpeg->img_convert_ctx) { + m_ffmpegHandler->sws_freeContext(m_ffmpeg->img_convert_ctx); + m_ffmpeg->img_convert_ctx = nullptr; + } + if (m_ffmpeg->formatCtx) { if (m_ffmpeg->formatCtx->pb) { m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); @@ -412,7 +417,12 @@ bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) AVFrame* decodedFrame = nullptr; AVPacket* packet = nullptr; + SwsContext* decSwsCtx = nullptr; + DEFER { + if (decSwsCtx) { + m_ffmpegHandler->sws_freeContext(decSwsCtx); + } if (inputFmtCtx) { m_ffmpegHandler->avformat_close_input(&inputFmtCtx); } @@ -474,7 +484,7 @@ bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) return false; } - SwsContext* decSwsCtx = m_ffmpegHandler->sws_getCachedContext( + decSwsCtx = m_ffmpegHandler->sws_getCachedContext( nullptr, decodeCtx->width, decodeCtx->height, decodeCtx->pix_fmt, m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, diff --git a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp index 854f9bbd431df..c0acbf12d8e14 100644 --- a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.cpp @@ -106,6 +106,7 @@ bool FFmpegLibHandler::loadApi() // libswscale RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); RESOLVE_FROM(m_swsScaleLibrary, sws_scale); + RESOLVE_FROM(m_swsScaleLibrary, sws_freeContext); return functionsValid(); } @@ -182,7 +183,7 @@ bool FFmpegLibHandler::functionsValid() const && av_frame_alloc && av_frame_free && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts && av_malloc - && sws_getCachedContext && sws_scale; + && sws_getCachedContext && sws_scale && sws_freeContext; } void FFmpegLibHandler::clearFunctions() @@ -227,5 +228,6 @@ void FFmpegLibHandler::clearFunctions() av_packet_rescale_ts = nullptr; sws_getCachedContext = nullptr; sws_scale = nullptr; + sws_freeContext = nullptr; } } diff --git a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h index b32abd991a3a5..0031c7a2b3488 100644 --- a/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v5/ffmpeglibhandler.h @@ -96,6 +96,7 @@ class FFmpegLibHandler const double* param) = nullptr; int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]) = nullptr; + void (*sws_freeContext)(SwsContext* swsContext) = nullptr; private: void* getSymbol(void* lib, const char* name) const; bool tryLoadPath(void*& lib, const io::path_t& fullPath); diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp index 6e77bf4be43e0..52f0e6c78972a 100644 --- a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp @@ -314,6 +314,11 @@ void VideoEncoder::close() m_ffmpeg->ppicture = 0; } + if (m_ffmpeg->img_convert_ctx) { + m_ffmpegHandler->sws_freeContext(m_ffmpeg->img_convert_ctx); + m_ffmpeg->img_convert_ctx = nullptr; + } + if (m_ffmpeg->formatCtx) { if (m_ffmpeg->formatCtx->pb) { m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); @@ -412,7 +417,12 @@ bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) AVFrame* decodedFrame = nullptr; AVPacket* packet = nullptr; + SwsContext* decSwsCtx = nullptr; + DEFER { + if (decSwsCtx) { + m_ffmpegHandler->sws_freeContext(decSwsCtx); + } if (inputFmtCtx) { m_ffmpegHandler->avformat_close_input(&inputFmtCtx); } @@ -474,7 +484,7 @@ bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) return false; } - SwsContext* decSwsCtx = m_ffmpegHandler->sws_getCachedContext( + decSwsCtx = m_ffmpegHandler->sws_getCachedContext( nullptr, decodeCtx->width, decodeCtx->height, decodeCtx->pix_fmt, m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, diff --git a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp index 11879699f6a5b..6ce33af14f6d6 100644 --- a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.cpp @@ -106,6 +106,7 @@ bool FFmpegLibHandler::loadApi() // libswscale RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); RESOLVE_FROM(m_swsScaleLibrary, sws_scale); + RESOLVE_FROM(m_swsScaleLibrary, sws_freeContext); return functionsValid(); } @@ -182,7 +183,7 @@ bool FFmpegLibHandler::functionsValid() const && av_frame_alloc && av_frame_free && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts && av_malloc - && sws_getCachedContext && sws_scale; + && sws_getCachedContext && sws_scale && sws_freeContext; } void FFmpegLibHandler::clearFunctions() @@ -227,5 +228,6 @@ void FFmpegLibHandler::clearFunctions() av_packet_rescale_ts = nullptr; sws_getCachedContext = nullptr; sws_scale = nullptr; + sws_freeContext = nullptr; } } diff --git a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h index 807202a1fd4c5..0cddef762d416 100644 --- a/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v6/ffmpeglibhandler.h @@ -96,6 +96,7 @@ class FFmpegLibHandler const double* param) = nullptr; int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]) = nullptr; + void (*sws_freeContext)(SwsContext* swsContext) = nullptr; private: void* getSymbol(void* lib, const char* name) const; bool tryLoadPath(void*& lib, const io::path_t& fullPath); diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp index 1aa98f33a2778..2dd011588c65f 100644 --- a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp @@ -314,6 +314,11 @@ void VideoEncoder::close() m_ffmpeg->ppicture = 0; } + if (m_ffmpeg->img_convert_ctx) { + m_ffmpegHandler->sws_freeContext(m_ffmpeg->img_convert_ctx); + m_ffmpeg->img_convert_ctx = nullptr; + } + if (m_ffmpeg->formatCtx) { if (m_ffmpeg->formatCtx->pb) { m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); @@ -412,7 +417,12 @@ bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) AVFrame* decodedFrame = nullptr; AVPacket* packet = nullptr; + SwsContext* decSwsCtx = nullptr; + DEFER { + if (decSwsCtx) { + m_ffmpegHandler->sws_freeContext(decSwsCtx); + } if (inputFmtCtx) { m_ffmpegHandler->avformat_close_input(&inputFmtCtx); } @@ -474,7 +484,7 @@ bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) return false; } - SwsContext* decSwsCtx = m_ffmpegHandler->sws_getCachedContext( + decSwsCtx = m_ffmpegHandler->sws_getCachedContext( nullptr, decodeCtx->width, decodeCtx->height, decodeCtx->pix_fmt, m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp index 648a1d8fb1da5..42ca9582fc99d 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.cpp @@ -106,6 +106,7 @@ bool FFmpegLibHandler::loadApi() // libswscale RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); RESOLVE_FROM(m_swsScaleLibrary, sws_scale); + RESOLVE_FROM(m_swsScaleLibrary, sws_freeContext); return functionsValid(); } @@ -182,7 +183,7 @@ bool FFmpegLibHandler::functionsValid() const && av_frame_alloc && av_frame_free && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts && av_malloc - && sws_getCachedContext && sws_scale; + && sws_getCachedContext && sws_scale && sws_freeContext; } void FFmpegLibHandler::clearFunctions() @@ -227,5 +228,6 @@ void FFmpegLibHandler::clearFunctions() av_packet_rescale_ts = nullptr; sws_getCachedContext = nullptr; sws_scale = nullptr; + sws_freeContext = nullptr; } } diff --git a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h index 84a5f9b999bb9..e54c13e6bdf31 100644 --- a/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v7/ffmpeglibhandler.h @@ -96,6 +96,7 @@ class FFmpegLibHandler const double* param) = nullptr; int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]) = nullptr; + void (*sws_freeContext)(SwsContext* swsContext) = nullptr; private: void* getSymbol(void* lib, const char* name) const; bool tryLoadPath(void*& lib, const io::path_t& fullPath); diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp index 874944dd2c124..972b267f9cbcb 100644 --- a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp @@ -314,6 +314,11 @@ void VideoEncoder::close() m_ffmpeg->ppicture = 0; } + if (m_ffmpeg->img_convert_ctx) { + m_ffmpegHandler->sws_freeContext(m_ffmpeg->img_convert_ctx); + m_ffmpeg->img_convert_ctx = nullptr; + } + if (m_ffmpeg->formatCtx) { if (m_ffmpeg->formatCtx->pb) { m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); @@ -412,7 +417,12 @@ bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) AVFrame* decodedFrame = nullptr; AVPacket* packet = nullptr; + SwsContext* decSwsCtx = nullptr; + DEFER { + if (decSwsCtx) { + m_ffmpegHandler->sws_freeContext(decSwsCtx); + } if (inputFmtCtx) { m_ffmpegHandler->avformat_close_input(&inputFmtCtx); } @@ -474,7 +484,7 @@ bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) return false; } - SwsContext* decSwsCtx = m_ffmpegHandler->sws_getCachedContext( + decSwsCtx = m_ffmpegHandler->sws_getCachedContext( nullptr, decodeCtx->width, decodeCtx->height, decodeCtx->pix_fmt, m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp index 484dfa896f4af..e48108e317b06 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.cpp @@ -106,6 +106,7 @@ bool FFmpegLibHandler::loadApi() // libswscale RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext); RESOLVE_FROM(m_swsScaleLibrary, sws_scale); + RESOLVE_FROM(m_swsScaleLibrary, sws_freeContext); return functionsValid(); } @@ -182,7 +183,7 @@ bool FFmpegLibHandler::functionsValid() const && av_frame_alloc && av_frame_free && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts && av_malloc - && sws_getCachedContext && sws_scale; + && sws_getCachedContext && sws_scale && sws_freeContext; } void FFmpegLibHandler::clearFunctions() @@ -227,5 +228,6 @@ void FFmpegLibHandler::clearFunctions() av_packet_rescale_ts = nullptr; sws_getCachedContext = nullptr; sws_scale = nullptr; + sws_freeContext = nullptr; } } diff --git a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h index 61333168b2972..5987a48f726d8 100644 --- a/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h +++ b/src/framework/media/internal/ffmpeg/v8/ffmpeglibhandler.h @@ -96,6 +96,7 @@ class FFmpegLibHandler const double* param) = nullptr; int (*sws_scale)(struct SwsContext* c, const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]) = nullptr; + void (*sws_freeContext)(SwsContext* swsContext) = nullptr; private: void* getSymbol(void* lib, const char* name) const; bool tryLoadPath(void*& lib, const io::path_t& fullPath); diff --git a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp index 973074cd73ff2..0f06cf555d9b2 100644 --- a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp @@ -314,6 +314,11 @@ void VideoEncoder::close() m_ffmpeg->ppicture = 0; } + if (m_ffmpeg->img_convert_ctx) { + m_ffmpegHandler->sws_freeContext(m_ffmpeg->img_convert_ctx); + m_ffmpeg->img_convert_ctx = nullptr; + } + if (m_ffmpeg->formatCtx) { if (m_ffmpeg->formatCtx->pb) { m_ffmpegHandler->avio_close(m_ffmpeg->formatCtx->pb); @@ -412,7 +417,12 @@ bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) AVFrame* decodedFrame = nullptr; AVPacket* packet = nullptr; + SwsContext* decSwsCtx = nullptr; + DEFER { + if (decSwsCtx) { + m_ffmpegHandler->sws_freeContext(decSwsCtx); + } if (inputFmtCtx) { m_ffmpegHandler->avformat_close_input(&inputFmtCtx); } @@ -474,7 +484,7 @@ bool VideoEncoder::encodeVideo(const ByteArray& videoData, int maxFrames) return false; } - SwsContext* decSwsCtx = m_ffmpegHandler->sws_getCachedContext( + decSwsCtx = m_ffmpegHandler->sws_getCachedContext( nullptr, decodeCtx->width, decodeCtx->height, decodeCtx->pix_fmt, m_ffmpeg->width, m_ffmpeg->height, AV_PIX_FMT_YUV420P, From 2bbf43ac1e0ffee3676a9d8429e03e7f18eadafb Mon Sep 17 00:00:00 2001 From: Eism Date: Wed, 18 Mar 2026 12:23:51 +0200 Subject: [PATCH 45/52] fixed notation update after export --- src/importexport/videoexport/internal/videowriter.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index b3f6351b790ff..67e25228101e1 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -108,6 +108,9 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, QThread::yieldCurrentThread(); } + //! NOTE: we have to do it in main thread + notation->notationChanged().notify(); + if (m_audioWriter) { m_audioWriter->progress()->finished().disconnect(this); m_audioWriter = nullptr; From a9a8ec5e979ef7e505534dee1eba8c4310633db2 Mon Sep 17 00:00:00 2001 From: Eism Date: Wed, 18 Mar 2026 12:32:14 +0200 Subject: [PATCH 46/52] added no-audio option for video export --- src/app/cmdoptions.h | 1 + src/app/internal/commandlineparser.cpp | 5 +++++ src/app/internal/consoleapp.cpp | 3 ++- src/converter/iconvertercontroller.h | 3 ++- src/converter/internal/convertercontroller.cpp | 11 +++++++++-- src/converter/internal/convertercontroller.h | 3 ++- 6 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/app/cmdoptions.h b/src/app/cmdoptions.h index 7d4c10d4381f8..87ed9bdd007cd 100644 --- a/src/app/cmdoptions.h +++ b/src/app/cmdoptions.h @@ -45,6 +45,7 @@ struct CmdOptions { ExtensionUri, PageNumber, ScoreRegion, + NoAudio, }; muse::IApplication::RunMode runMode = muse::IApplication::RunMode::GuiApp; diff --git a/src/app/internal/commandlineparser.cpp b/src/app/internal/commandlineparser.cpp index a612185cd159f..a9ba9f8a04aa2 100644 --- a/src/app/internal/commandlineparser.cpp +++ b/src/app/internal/commandlineparser.cpp @@ -156,6 +156,7 @@ void CommandLineParser::init() m_parser.addOption(QCommandLineOption("fps", "Frame per second [60, 30, 24]", "24")); m_parser.addOption(QCommandLineOption("ls", "Pause before playback in seconds (3.0)", "3.0")); m_parser.addOption(QCommandLineOption("ts", "Pause before end of video in seconds (3.0)", "3.0")); + m_parser.addOption(QCommandLineOption("no-audio", "Export video without audio")); #endif m_parser.addOption(QCommandLineOption("gp-linked", "create tabulature linked staves for guitar pro")); @@ -445,6 +446,10 @@ void CommandLineParser::parse(int argc, char** argv) if (m_parser.isSet("ts")) { m_options.exportVideo.trailingSec = doubleValue("ts"); } + + if (m_parser.isSet("no-audio")) { + m_options.converterTask.params[CmdOptions::ParamKey::NoAudio] = true; + } } #endif diff --git a/src/app/internal/consoleapp.cpp b/src/app/internal/consoleapp.cpp index 424ae0486e4d7..5db1c8e60ce8d 100644 --- a/src/app/internal/consoleapp.cpp +++ b/src/app/internal/consoleapp.cpp @@ -456,7 +456,8 @@ int ConsoleApp::processConverter(const CmdOptions::ConverterTask& task, const mu ret = converter()->exportScoreElements(task.inputFile, task.outputFile, openParams); } break; case ConvertType::ExportScoreVideo: { - ret = converter()->exportScoreVideo(task.inputFile, task.outputFile, openParams); + bool withAudio = !task.params[CmdOptions::ParamKey::NoAudio].toBool(); + ret = converter()->exportScoreVideo(task.inputFile, task.outputFile, openParams, withAudio); } break; case ConvertType::SourceUpdate: { std::string scoreSource = task.params[CmdOptions::ParamKey::ScoreSource].toString().toStdString(); diff --git a/src/converter/iconvertercontroller.h b/src/converter/iconvertercontroller.h index 110e43e413924..c8770da62213d 100644 --- a/src/converter/iconvertercontroller.h +++ b/src/converter/iconvertercontroller.h @@ -58,7 +58,8 @@ class IConverterController : MODULE_CONTEXT_INTERFACE virtual muse::Ret exportScoreElements(const muse::io::path_t& in, const muse::io::path_t& out, const OpenParams& openParams = {}) = 0; - virtual muse::Ret exportScoreVideo(const muse::io::path_t& in, const muse::io::path_t& out, const OpenParams& openParams = {}) = 0; + virtual muse::Ret exportScoreVideo(const muse::io::path_t& in, const muse::io::path_t& out, const OpenParams& openParams = {}, + bool withAudio = true) = 0; virtual muse::Ret updateSource(const muse::io::path_t& in, const std::string& newSource, bool forceMode = false) = 0; }; diff --git a/src/converter/internal/convertercontroller.cpp b/src/converter/internal/convertercontroller.cpp index 315b40b4feb68..d88a1ed6ee16d 100644 --- a/src/converter/internal/convertercontroller.cpp +++ b/src/converter/internal/convertercontroller.cpp @@ -704,7 +704,8 @@ Ret ConverterController::exportScoreElements(const muse::io::path_t& in, const m return BackendApi::exportScoreElements(in, out, openParams); } -Ret ConverterController::exportScoreVideo(const muse::io::path_t& in, const muse::io::path_t& out, const OpenParams& openParams) +Ret ConverterController::exportScoreVideo(const muse::io::path_t& in, const muse::io::path_t& out, const OpenParams& openParams, + bool withAudio) { TRACEFUNC; @@ -725,8 +726,14 @@ Ret ConverterController::exportScoreVideo(const muse::io::path_t& in, const muse return make_ret(Err::InFileFailedLoad); } + globalContext()->setCurrentProject(notationProject); + + DEFER { + globalContext()->setCurrentProject(nullptr); + }; + const INotationWriter::Options options { - { INotationWriter::OptionKey::WITH_AUDIO, Val(false) }, + { INotationWriter::OptionKey::WITH_AUDIO, Val(withAudio) }, }; return convertFullNotation(writer, notationProject->masterNotation()->notation(), out, options); diff --git a/src/converter/internal/convertercontroller.h b/src/converter/internal/convertercontroller.h index 16fb228c6c892..a758471118f3b 100644 --- a/src/converter/internal/convertercontroller.h +++ b/src/converter/internal/convertercontroller.h @@ -67,7 +67,8 @@ class ConverterController : public IConverterController, public muse::Contextabl muse::Ret exportScoreElements(const muse::io::path_t& in, const muse::io::path_t& out, const OpenParams& openParams = {}) override; - muse::Ret exportScoreVideo(const muse::io::path_t& in, const muse::io::path_t& out, const OpenParams& openParams = {}) override; + muse::Ret exportScoreVideo(const muse::io::path_t& in, const muse::io::path_t& out, const OpenParams& openParams = {}, + bool withAudio = true) override; muse::Ret updateSource(const muse::io::path_t& in, const std::string& newSource, bool forceMode = false) override; From 5857bf2970952a56bfdfebce771488b4f00f6cc1 Mon Sep 17 00:00:00 2001 From: Eism Date: Wed, 18 Mar 2026 18:05:52 +0200 Subject: [PATCH 47/52] fixed frames flickering on macOS --- src/framework/media/internal/ffmpeg/v4/videoencoder.cpp | 4 ++-- src/framework/media/internal/ffmpeg/v5/videoencoder.cpp | 4 ++-- src/framework/media/internal/ffmpeg/v6/videoencoder.cpp | 4 ++-- src/framework/media/internal/ffmpeg/v7/videoencoder.cpp | 4 ++-- src/framework/media/internal/ffmpeg/v8/videoencoder.cpp | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp index d22869a9cd199..1349d81f538c5 100644 --- a/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v4/videoencoder.cpp @@ -164,12 +164,12 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, const Options& options return false; } - m_ffmpeg->codecCtx->profile = FF_PROFILE_H264_HIGH; + m_ffmpeg->codecCtx->profile = FF_PROFILE_H264_MAIN; m_ffmpeg->codecCtx->time_base.den = options.fps; m_ffmpeg->codecCtx->time_base.num = 1; m_ffmpeg->codecCtx->gop_size = options.gop; m_ffmpeg->codecCtx->thread_count = 10; - m_ffmpeg->codecCtx->max_b_frames = 3; + m_ffmpeg->codecCtx->max_b_frames = 0; m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); m_ffmpeg->codecCtx->me_cmp = 1; diff --git a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp index 52f0e6c78972a..a9678c4700c62 100644 --- a/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v5/videoencoder.cpp @@ -164,12 +164,12 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, const Options& options return false; } - m_ffmpeg->codecCtx->profile = FF_PROFILE_H264_HIGH; + m_ffmpeg->codecCtx->profile = FF_PROFILE_H264_MAIN; m_ffmpeg->codecCtx->time_base.den = options.fps; m_ffmpeg->codecCtx->time_base.num = 1; m_ffmpeg->codecCtx->gop_size = options.gop; m_ffmpeg->codecCtx->thread_count = 10; - m_ffmpeg->codecCtx->max_b_frames = 3; + m_ffmpeg->codecCtx->max_b_frames = 0; m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); m_ffmpeg->codecCtx->me_cmp = 1; diff --git a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp index 2dd011588c65f..7f081a7898c7c 100644 --- a/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v6/videoencoder.cpp @@ -164,12 +164,12 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, const Options& options return false; } - m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; + m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_MAIN; m_ffmpeg->codecCtx->time_base.den = options.fps; m_ffmpeg->codecCtx->time_base.num = 1; m_ffmpeg->codecCtx->gop_size = options.gop; m_ffmpeg->codecCtx->thread_count = 10; - m_ffmpeg->codecCtx->max_b_frames = 3; + m_ffmpeg->codecCtx->max_b_frames = 0; m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); m_ffmpeg->codecCtx->me_cmp = 1; diff --git a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp index 972b267f9cbcb..72b0c95cd5d35 100644 --- a/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v7/videoencoder.cpp @@ -164,12 +164,12 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, const Options& options return false; } - m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; + m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_MAIN; m_ffmpeg->codecCtx->time_base.den = options.fps; m_ffmpeg->codecCtx->time_base.num = 1; m_ffmpeg->codecCtx->gop_size = options.gop; m_ffmpeg->codecCtx->thread_count = 10; - m_ffmpeg->codecCtx->max_b_frames = 3; + m_ffmpeg->codecCtx->max_b_frames = 0; m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); m_ffmpeg->codecCtx->me_cmp = 1; diff --git a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp index 0f06cf555d9b2..21a053de4b47e 100644 --- a/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp +++ b/src/framework/media/internal/ffmpeg/v8/videoencoder.cpp @@ -164,12 +164,12 @@ bool VideoEncoder::open(const muse::io::path_t& fileName, const Options& options return false; } - m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_HIGH; + m_ffmpeg->codecCtx->profile = AV_PROFILE_H264_MAIN; m_ffmpeg->codecCtx->time_base.den = options.fps; m_ffmpeg->codecCtx->time_base.num = 1; m_ffmpeg->codecCtx->gop_size = options.gop; m_ffmpeg->codecCtx->thread_count = 10; - m_ffmpeg->codecCtx->max_b_frames = 3; + m_ffmpeg->codecCtx->max_b_frames = 0; m_ffmpegHandler->av_opt_set_int(m_ffmpeg->codecCtx, "b_strategy", 1, 0); m_ffmpeg->codecCtx->me_cmp = 1; From bc27bb2ff5321669eb34e7a722e9208dddd2ad9e Mon Sep 17 00:00:00 2001 From: Eism Date: Thu, 19 Mar 2026 12:26:01 +0200 Subject: [PATCH 48/52] added fdk-aac-2.0.3 --- .../fdk-aac/fdk-aac-2.0.3/.clang-format | 4 + .../fdk-aac-2.0.3/.github/workflows/ci.yml | 215 + .../fdk-aac/fdk-aac-2.0.3/.gitignore | 46 + .../fdk-aac/fdk-aac-2.0.3/Android.bp | 101 + .../fdk-aac/fdk-aac-2.0.3/CMakeLists.txt | 600 ++ .../fdk-aac/fdk-aac-2.0.3/ChangeLog | 62 + .../thirdparty/fdk-aac/fdk-aac-2.0.3/METADATA | 7 + .../fdk-aac-2.0.3/MODULE_LICENSE_FRAUNHOFER | 0 .../fdk-aac/fdk-aac-2.0.3/Makefile.am | 305 + .../thirdparty/fdk-aac/fdk-aac-2.0.3/NOTICE | 92 + .../thirdparty/fdk-aac/fdk-aac-2.0.3/OWNERS | 2 + .../fdk-aac/fdk-aac-2.0.3/PREUPLOAD.cfg | 2 + .../fdk-aac/fdk-aac-2.0.3/aac-enc.c | 237 + .../fdk-aac/fdk-aac-2.0.3/autogen.sh | 2 + .../fdk-aac/fdk-aac-2.0.3/configure.ac | 38 + .../documentation/aacDecoder.pdf | Bin 0 -> 492288 bytes .../documentation/aacEncoder.pdf | Bin 0 -> 443831 bytes .../fdk-aac-2.0.3/fdk-aac-config.cmake.in | 5 + .../fdk-aac/fdk-aac-2.0.3/fdk-aac.def | 19 + .../fdk-aac/fdk-aac-2.0.3/fdk-aac.pc.in | 11 + .../fdk-aac/fdk-aac-2.0.3/fdk-aac.sym | 18 + .../fdk-aac/fdk-aac-2.0.3/fuzzer/Android.bp | 90 + .../fdk-aac/fdk-aac-2.0.3/fuzzer/README.md | 150 + .../fdk-aac-2.0.3/fuzzer/aac_dec_fuzzer.cpp | 141 + .../fdk-aac-2.0.3/fuzzer/aac_enc_fuzzer.cpp | 479 ++ .../libAACdec/include/aacdecoder_lib.h | 1082 +++ .../fdk-aac-2.0.3/libAACdec/src/FDK_delay.cpp | 173 + .../fdk-aac-2.0.3/libAACdec/src/FDK_delay.h | 152 + .../fdk-aac-2.0.3/libAACdec/src/aac_ram.cpp | 177 + .../fdk-aac-2.0.3/libAACdec/src/aac_ram.h | 142 + .../fdk-aac-2.0.3/libAACdec/src/aac_rom.cpp | 3428 ++++++++ .../fdk-aac-2.0.3/libAACdec/src/aac_rom.h | 238 + .../libAACdec/src/aacdec_drc.cpp | 1509 ++++ .../fdk-aac-2.0.3/libAACdec/src/aacdec_drc.h | 240 + .../libAACdec/src/aacdec_drc_types.h | 221 + .../libAACdec/src/aacdec_hcr.cpp | 1508 ++++ .../fdk-aac-2.0.3/libAACdec/src/aacdec_hcr.h | 128 + .../libAACdec/src/aacdec_hcr_bit.cpp | 164 + .../libAACdec/src/aacdec_hcr_bit.h | 114 + .../libAACdec/src/aacdec_hcr_types.h | 432 + .../libAACdec/src/aacdec_hcrs.cpp | 1557 ++++ .../fdk-aac-2.0.3/libAACdec/src/aacdec_hcrs.h | 176 + .../libAACdec/src/aacdec_pns.cpp | 361 + .../fdk-aac-2.0.3/libAACdec/src/aacdec_pns.h | 129 + .../libAACdec/src/aacdec_tns.cpp | 361 + .../fdk-aac-2.0.3/libAACdec/src/aacdec_tns.h | 149 + .../libAACdec/src/aacdecoder.cpp | 3590 ++++++++ .../fdk-aac-2.0.3/libAACdec/src/aacdecoder.h | 474 ++ .../libAACdec/src/aacdecoder_lib.cpp | 2124 +++++ .../libAACdec/src/arm/block_arm.cpp | 142 + .../fdk-aac-2.0.3/libAACdec/src/block.cpp | 1262 +++ .../fdk-aac-2.0.3/libAACdec/src/block.h | 345 + .../fdk-aac-2.0.3/libAACdec/src/channel.cpp | 926 +++ .../fdk-aac-2.0.3/libAACdec/src/channel.h | 160 + .../libAACdec/src/channelinfo.cpp | 297 + .../fdk-aac-2.0.3/libAACdec/src/channelinfo.h | 564 ++ .../fdk-aac-2.0.3/libAACdec/src/conceal.cpp | 2096 +++++ .../fdk-aac-2.0.3/libAACdec/src/conceal.h | 152 + .../libAACdec/src/conceal_types.h | 203 + .../libAACdec/src/ldfiltbank.cpp | 283 + .../fdk-aac-2.0.3/libAACdec/src/ldfiltbank.h | 113 + .../fdk-aac-2.0.3/libAACdec/src/overlapadd.h | 120 + .../fdk-aac-2.0.3/libAACdec/src/pulsedata.cpp | 164 + .../fdk-aac-2.0.3/libAACdec/src/pulsedata.h | 150 + .../fdk-aac-2.0.3/libAACdec/src/rvlc.cpp | 1218 +++ .../fdk-aac-2.0.3/libAACdec/src/rvlc.h | 153 + .../fdk-aac-2.0.3/libAACdec/src/rvlc_info.h | 204 + .../fdk-aac-2.0.3/libAACdec/src/rvlcbit.cpp | 148 + .../fdk-aac-2.0.3/libAACdec/src/rvlcbit.h | 111 + .../libAACdec/src/rvlcconceal.cpp | 787 ++ .../fdk-aac-2.0.3/libAACdec/src/rvlcconceal.h | 127 + .../fdk-aac-2.0.3/libAACdec/src/stereo.cpp | 1238 +++ .../fdk-aac-2.0.3/libAACdec/src/stereo.h | 211 + .../libAACdec/src/usacdec_ace_d4t64.cpp | 439 + .../libAACdec/src/usacdec_ace_d4t64.h | 117 + .../libAACdec/src/usacdec_ace_ltp.cpp | 229 + .../libAACdec/src/usacdec_ace_ltp.h | 128 + .../libAACdec/src/usacdec_acelp.cpp | 1299 +++ .../libAACdec/src/usacdec_acelp.h | 281 + .../libAACdec/src/usacdec_const.h | 203 + .../libAACdec/src/usacdec_fac.cpp | 743 ++ .../fdk-aac-2.0.3/libAACdec/src/usacdec_fac.h | 191 + .../libAACdec/src/usacdec_lpc.cpp | 1196 +++ .../fdk-aac-2.0.3/libAACdec/src/usacdec_lpc.h | 190 + .../libAACdec/src/usacdec_lpd.cpp | 2041 +++++ .../fdk-aac-2.0.3/libAACdec/src/usacdec_lpd.h | 201 + .../libAACdec/src/usacdec_rom.cpp | 1504 ++++ .../fdk-aac-2.0.3/libAACdec/src/usacdec_rom.h | 154 + .../libAACenc/include/aacenc_lib.h | 1709 ++++ .../libAACenc/src/aacEnc_ram.cpp | 208 + .../fdk-aac-2.0.3/libAACenc/src/aacEnc_ram.h | 249 + .../libAACenc/src/aacEnc_rom.cpp | 2486 ++++++ .../fdk-aac-2.0.3/libAACenc/src/aacEnc_rom.h | 217 + .../fdk-aac-2.0.3/libAACenc/src/aacenc.cpp | 1066 +++ .../fdk-aac-2.0.3/libAACenc/src/aacenc.h | 407 + .../libAACenc/src/aacenc_lib.cpp | 2550 ++++++ .../libAACenc/src/aacenc_pns.cpp | 541 ++ .../fdk-aac-2.0.3/libAACenc/src/aacenc_pns.h | 124 + .../libAACenc/src/aacenc_tns.cpp | 1191 +++ .../fdk-aac-2.0.3/libAACenc/src/aacenc_tns.h | 213 + .../fdk-aac-2.0.3/libAACenc/src/adj_thr.cpp | 2914 +++++++ .../fdk-aac-2.0.3/libAACenc/src/adj_thr.h | 166 + .../libAACenc/src/adj_thr_data.h | 175 + .../fdk-aac-2.0.3/libAACenc/src/band_nrg.cpp | 361 + .../fdk-aac-2.0.3/libAACenc/src/band_nrg.h | 142 + .../fdk-aac-2.0.3/libAACenc/src/bandwidth.cpp | 360 + .../fdk-aac-2.0.3/libAACenc/src/bandwidth.h | 114 + .../fdk-aac-2.0.3/libAACenc/src/bit_cnt.cpp | 950 +++ .../fdk-aac-2.0.3/libAACenc/src/bit_cnt.h | 200 + .../fdk-aac-2.0.3/libAACenc/src/bitenc.cpp | 1322 +++ .../fdk-aac-2.0.3/libAACenc/src/bitenc.h | 184 + .../libAACenc/src/block_switch.cpp | 582 ++ .../libAACenc/src/block_switch.h | 162 + .../libAACenc/src/channel_map.cpp | 664 ++ .../fdk-aac-2.0.3/libAACenc/src/channel_map.h | 136 + .../libAACenc/src/chaosmeasure.cpp | 191 + .../libAACenc/src/chaosmeasure.h | 112 + .../fdk-aac-2.0.3/libAACenc/src/dyn_bits.cpp | 663 ++ .../fdk-aac-2.0.3/libAACenc/src/dyn_bits.h | 160 + .../fdk-aac-2.0.3/libAACenc/src/grp_data.cpp | 264 + .../fdk-aac-2.0.3/libAACenc/src/grp_data.h | 123 + .../fdk-aac-2.0.3/libAACenc/src/intensity.cpp | 817 ++ .../fdk-aac-2.0.3/libAACenc/src/intensity.h | 121 + .../fdk-aac-2.0.3/libAACenc/src/interface.h | 168 + .../fdk-aac-2.0.3/libAACenc/src/line_pe.cpp | 234 + .../fdk-aac-2.0.3/libAACenc/src/line_pe.h | 148 + .../libAACenc/src/metadata_compressor.cpp | 1579 ++++ .../libAACenc/src/metadata_compressor.h | 255 + .../libAACenc/src/metadata_main.cpp | 1191 +++ .../libAACenc/src/metadata_main.h | 226 + .../fdk-aac-2.0.3/libAACenc/src/mps_main.cpp | 529 ++ .../fdk-aac-2.0.3/libAACenc/src/mps_main.h | 270 + .../fdk-aac-2.0.3/libAACenc/src/ms_stereo.cpp | 295 + .../fdk-aac-2.0.3/libAACenc/src/ms_stereo.h | 117 + .../fdk-aac-2.0.3/libAACenc/src/noisedet.cpp | 235 + .../fdk-aac-2.0.3/libAACenc/src/noisedet.h | 116 + .../fdk-aac-2.0.3/libAACenc/src/pns_func.h | 138 + .../fdk-aac-2.0.3/libAACenc/src/pnsparam.cpp | 574 ++ .../fdk-aac-2.0.3/libAACenc/src/pnsparam.h | 149 + .../libAACenc/src/pre_echo_control.cpp | 176 + .../libAACenc/src/pre_echo_control.h | 118 + .../libAACenc/src/psy_configuration.cpp | 627 ++ .../libAACenc/src/psy_configuration.h | 171 + .../fdk-aac-2.0.3/libAACenc/src/psy_const.h | 168 + .../fdk-aac-2.0.3/libAACenc/src/psy_data.h | 169 + .../fdk-aac-2.0.3/libAACenc/src/psy_main.cpp | 1348 +++ .../fdk-aac-2.0.3/libAACenc/src/psy_main.h | 161 + .../fdk-aac-2.0.3/libAACenc/src/qc_data.h | 299 + .../fdk-aac-2.0.3/libAACenc/src/qc_main.cpp | 1536 ++++ .../fdk-aac-2.0.3/libAACenc/src/qc_main.h | 158 + .../fdk-aac-2.0.3/libAACenc/src/quantize.cpp | 401 + .../fdk-aac-2.0.3/libAACenc/src/quantize.h | 127 + .../fdk-aac-2.0.3/libAACenc/src/sf_estim.cpp | 1292 +++ .../fdk-aac-2.0.3/libAACenc/src/sf_estim.h | 124 + .../fdk-aac-2.0.3/libAACenc/src/spreading.cpp | 125 + .../fdk-aac-2.0.3/libAACenc/src/spreading.h | 113 + .../fdk-aac-2.0.3/libAACenc/src/tns_func.h | 129 + .../fdk-aac-2.0.3/libAACenc/src/tonality.cpp | 219 + .../fdk-aac-2.0.3/libAACenc/src/tonality.h | 115 + .../fdk-aac-2.0.3/libAACenc/src/transform.cpp | 294 + .../fdk-aac-2.0.3/libAACenc/src/transform.h | 163 + .../libArithCoding/include/ac_arith_coder.h | 142 + .../libArithCoding/src/ac_arith_coder.cpp | 785 ++ .../libDRCdec/include/FDK_drcDecLib.h | 321 + .../libDRCdec/src/FDK_drcDecLib.cpp | 927 +++ .../libDRCdec/src/drcDec_gainDecoder.cpp | 465 ++ .../libDRCdec/src/drcDec_gainDecoder.h | 270 + .../libDRCdec/src/drcDec_reader.cpp | 2043 +++++ .../libDRCdec/src/drcDec_reader.h | 130 + .../libDRCdec/src/drcDec_rom.cpp | 323 + .../fdk-aac-2.0.3/libDRCdec/src/drcDec_rom.h | 120 + .../libDRCdec/src/drcDec_selectionProcess.cpp | 3165 +++++++ .../libDRCdec/src/drcDec_selectionProcess.h | 220 + .../libDRCdec/src/drcDec_tools.cpp | 371 + .../libDRCdec/src/drcDec_tools.h | 146 + .../libDRCdec/src/drcDec_types.h | 431 + .../fdk-aac-2.0.3/libDRCdec/src/drcDecoder.h | 142 + .../libDRCdec/src/drcGainDec_init.cpp | 333 + .../libDRCdec/src/drcGainDec_init.h | 119 + .../libDRCdec/src/drcGainDec_preprocess.cpp | 718 ++ .../libDRCdec/src/drcGainDec_preprocess.h | 111 + .../libDRCdec/src/drcGainDec_process.cpp | 532 ++ .../libDRCdec/src/drcGainDec_process.h | 119 + .../libFDK/include/FDK_archdef.h | 280 + .../libFDK/include/FDK_bitbuffer.h | 177 + .../libFDK/include/FDK_bitstream.h | 642 ++ .../fdk-aac-2.0.3/libFDK/include/FDK_core.h | 122 + .../fdk-aac-2.0.3/libFDK/include/FDK_crc.h | 225 + .../libFDK/include/FDK_decorrelate.h | 314 + .../fdk-aac-2.0.3/libFDK/include/FDK_hybrid.h | 255 + .../fdk-aac-2.0.3/libFDK/include/FDK_lpc.h | 218 + .../libFDK/include/FDK_matrixCalloc.h | 230 + .../libFDK/include/FDK_qmf_domain.h | 410 + .../libFDK/include/FDK_tools_rom.h | 398 + .../libFDK/include/FDK_trigFcts.h | 258 + .../fdk-aac-2.0.3/libFDK/include/abs.h | 136 + .../libFDK/include/arm/clz_arm.h | 164 + .../libFDK/include/arm/cplx_mul_arm.h | 201 + .../libFDK/include/arm/fixmadd_arm.h | 220 + .../libFDK/include/arm/fixmul_arm.h | 198 + .../libFDK/include/arm/scale_arm.h | 163 + .../libFDK/include/arm/scramble_arm.h | 174 + .../libFDK/include/autocorr2nd.h | 137 + .../fdk-aac-2.0.3/libFDK/include/clz.h | 205 + .../fdk-aac-2.0.3/libFDK/include/common_fix.h | 449 + .../fdk-aac-2.0.3/libFDK/include/cplx_mul.h | 266 + .../fdk-aac-2.0.3/libFDK/include/dct.h | 171 + .../fdk-aac-2.0.3/libFDK/include/fft.h | 263 + .../fdk-aac-2.0.3/libFDK/include/fft_rad2.h | 121 + .../fdk-aac-2.0.3/libFDK/include/fixmadd.h | 333 + .../fdk-aac-2.0.3/libFDK/include/fixminmax.h | 131 + .../fdk-aac-2.0.3/libFDK/include/fixmul.h | 298 + .../libFDK/include/fixpoint_math.h | 952 +++ .../fdk-aac-2.0.3/libFDK/include/huff_nodes.h | 258 + .../fdk-aac-2.0.3/libFDK/include/mdct.h | 251 + .../libFDK/include/mips/abs_mips.h | 125 + .../libFDK/include/mips/clz_mips.h | 134 + .../libFDK/include/mips/cplx_mul_mips.h | 133 + .../libFDK/include/mips/fixmul_mips.h | 130 + .../libFDK/include/mips/scale_mips.h | 122 + .../libFDK/include/mips/scramble_mips.h | 133 + .../fdk-aac-2.0.3/libFDK/include/nlc_dec.h | 184 + .../libFDK/include/ppc/clz_ppc.h | 102 + .../libFDK/include/ppc/fixmul_ppc.h | 115 + .../fdk-aac-2.0.3/libFDK/include/qmf.h | 334 + .../fdk-aac-2.0.3/libFDK/include/qmf_pcm.h | 621 ++ .../fdk-aac-2.0.3/libFDK/include/scale.h | 296 + .../fdk-aac-2.0.3/libFDK/include/scramble.h | 153 + .../libFDK/include/x86/abs_x86.h | 123 + .../libFDK/include/x86/clz_x86.h | 165 + .../libFDK/include/x86/fixmul_x86.h | 187 + .../libFDK/include/x86/fixpoint_math_x86.h | 208 + .../libFDK/src/FDK_bitbuffer.cpp | 492 ++ .../fdk-aac-2.0.3/libFDK/src/FDK_core.cpp | 145 + .../fdk-aac-2.0.3/libFDK/src/FDK_crc.cpp | 479 ++ .../libFDK/src/FDK_decorrelate.cpp | 1714 ++++ .../fdk-aac-2.0.3/libFDK/src/FDK_hybrid.cpp | 815 ++ .../fdk-aac-2.0.3/libFDK/src/FDK_lpc.cpp | 487 ++ .../libFDK/src/FDK_matrixCalloc.cpp | 315 + .../libFDK/src/FDK_qmf_domain.cpp | 1013 +++ .../libFDK/src/FDK_tools_rom.cpp | 7271 +++++++++++++++++ .../fdk-aac-2.0.3/libFDK/src/FDK_trigFcts.cpp | 340 + .../libFDK/src/arm/fft_rad2_arm.cpp | 321 + .../libFDK/src/arm/scale_arm.cpp | 174 + .../fdk-aac-2.0.3/libFDK/src/autocorr2nd.cpp | 292 + .../fdk-aac/fdk-aac-2.0.3/libFDK/src/dct.cpp | 566 ++ .../fdk-aac/fdk-aac-2.0.3/libFDK/src/fft.cpp | 1922 +++++ .../fdk-aac-2.0.3/libFDK/src/fft_rad2.cpp | 324 + .../libFDK/src/fixpoint_math.cpp | 906 ++ .../fdk-aac-2.0.3/libFDK/src/huff_nodes.cpp | 1084 +++ .../fdk-aac/fdk-aac-2.0.3/libFDK/src/mdct.cpp | 727 ++ .../libFDK/src/mips/fft_rad2_mips.cpp | 165 + .../libFDK/src/mips/mips_fft_twiddles.cpp | 931 +++ .../libFDK/src/mips/scale_mips.cpp | 133 + .../fdk-aac-2.0.3/libFDK/src/nlc_dec.cpp | 1069 +++ .../fdk-aac/fdk-aac-2.0.3/libFDK/src/qmf.cpp | 833 ++ .../fdk-aac-2.0.3/libFDK/src/scale.cpp | 720 ++ .../libMpegTPDec/include/tp_data.h | 466 ++ .../libMpegTPDec/include/tpdec_lib.h | 664 ++ .../libMpegTPDec/src/tp_version.h | 118 + .../libMpegTPDec/src/tpdec_adif.cpp | 158 + .../libMpegTPDec/src/tpdec_adif.h | 134 + .../libMpegTPDec/src/tpdec_adts.cpp | 432 + .../libMpegTPDec/src/tpdec_adts.h | 234 + .../libMpegTPDec/src/tpdec_asc.cpp | 2817 +++++++ .../libMpegTPDec/src/tpdec_drm.cpp | 148 + .../libMpegTPDec/src/tpdec_drm.h | 202 + .../libMpegTPDec/src/tpdec_latm.cpp | 677 ++ .../libMpegTPDec/src/tpdec_latm.h | 189 + .../libMpegTPDec/src/tpdec_lib.cpp | 1845 +++++ .../libMpegTPEnc/include/tp_data.h | 466 ++ .../libMpegTPEnc/include/tpenc_lib.h | 339 + .../libMpegTPEnc/src/tp_version.h | 118 + .../libMpegTPEnc/src/tpenc_adif.cpp | 186 + .../libMpegTPEnc/src/tpenc_adif.h | 146 + .../libMpegTPEnc/src/tpenc_adts.cpp | 319 + .../libMpegTPEnc/src/tpenc_adts.h | 208 + .../libMpegTPEnc/src/tpenc_asc.cpp | 996 +++ .../libMpegTPEnc/src/tpenc_asc.h | 147 + .../libMpegTPEnc/src/tpenc_latm.cpp | 850 ++ .../libMpegTPEnc/src/tpenc_latm.h | 274 + .../libMpegTPEnc/src/tpenc_lib.cpp | 664 ++ .../libPCMutils/include/limiter.h | 265 + .../libPCMutils/include/pcm_utils.h | 131 + .../libPCMutils/include/pcmdmx_lib.h | 460 ++ .../fdk-aac-2.0.3/libPCMutils/src/limiter.cpp | 555 ++ .../libPCMutils/src/pcm_utils.cpp | 195 + .../libPCMutils/src/pcmdmx_lib.cpp | 2690 ++++++ .../fdk-aac-2.0.3/libPCMutils/src/version.h | 119 + .../libSACdec/include/sac_dec_errorcodes.h | 157 + .../libSACdec/include/sac_dec_lib.h | 482 ++ .../libSACdec/src/sac_bitdec.cpp | 2175 +++++ .../fdk-aac-2.0.3/libSACdec/src/sac_bitdec.h | 161 + .../libSACdec/src/sac_calcM1andM2.cpp | 774 ++ .../libSACdec/src/sac_calcM1andM2.h | 132 + .../fdk-aac-2.0.3/libSACdec/src/sac_dec.cpp | 1548 ++++ .../fdk-aac-2.0.3/libSACdec/src/sac_dec.h | 542 ++ .../libSACdec/src/sac_dec_conceal.cpp | 392 + .../libSACdec/src/sac_dec_conceal.h | 187 + .../libSACdec/src/sac_dec_interface.h | 335 + .../libSACdec/src/sac_dec_lib.cpp | 2014 +++++ .../libSACdec/src/sac_dec_ssc_struct.h | 283 + .../libSACdec/src/sac_process.cpp | 1085 +++ .../fdk-aac-2.0.3/libSACdec/src/sac_process.h | 297 + .../fdk-aac-2.0.3/libSACdec/src/sac_qmf.cpp | 156 + .../fdk-aac-2.0.3/libSACdec/src/sac_qmf.h | 143 + .../libSACdec/src/sac_reshapeBBEnv.cpp | 678 ++ .../libSACdec/src/sac_reshapeBBEnv.h | 114 + .../fdk-aac-2.0.3/libSACdec/src/sac_rom.cpp | 4461 ++++++++++ .../fdk-aac-2.0.3/libSACdec/src/sac_rom.h | 216 + .../libSACdec/src/sac_smoothing.cpp | 295 + .../libSACdec/src/sac_smoothing.h | 114 + .../fdk-aac-2.0.3/libSACdec/src/sac_stp.cpp | 567 ++ .../fdk-aac-2.0.3/libSACdec/src/sac_stp.h | 115 + .../fdk-aac-2.0.3/libSACdec/src/sac_tsd.cpp | 359 + .../fdk-aac-2.0.3/libSACdec/src/sac_tsd.h | 167 + .../libSACenc/include/sacenc_lib.h | 405 + .../libSACenc/src/sacenc_bitstream.cpp | 826 ++ .../libSACenc/src/sacenc_bitstream.h | 296 + .../libSACenc/src/sacenc_const.h | 126 + .../libSACenc/src/sacenc_delay.cpp | 472 ++ .../libSACenc/src/sacenc_delay.h | 175 + .../libSACenc/src/sacenc_dmx_tdom_enh.cpp | 639 ++ .../libSACenc/src/sacenc_dmx_tdom_enh.h | 134 + .../libSACenc/src/sacenc_filter.cpp | 207 + .../libSACenc/src/sacenc_filter.h | 133 + .../libSACenc/src/sacenc_framewindowing.cpp | 568 ++ .../libSACenc/src/sacenc_framewindowing.h | 181 + .../libSACenc/src/sacenc_huff_tab.cpp | 997 +++ .../libSACenc/src/sacenc_huff_tab.h | 222 + .../libSACenc/src/sacenc_lib.cpp | 2042 +++++ .../libSACenc/src/sacenc_nlc_enc.cpp | 1442 ++++ .../libSACenc/src/sacenc_nlc_enc.h | 141 + .../libSACenc/src/sacenc_onsetdetect.cpp | 381 + .../libSACenc/src/sacenc_onsetdetect.h | 154 + .../libSACenc/src/sacenc_paramextract.cpp | 725 ++ .../libSACenc/src/sacenc_paramextract.h | 214 + .../libSACenc/src/sacenc_staticgain.cpp | 446 + .../libSACenc/src/sacenc_staticgain.h | 177 + .../libSACenc/src/sacenc_tree.cpp | 488 ++ .../fdk-aac-2.0.3/libSACenc/src/sacenc_tree.h | 168 + .../libSACenc/src/sacenc_vectorfunctions.cpp | 450 + .../libSACenc/src/sacenc_vectorfunctions.h | 488 ++ .../libSBRdec/include/sbrdecoder.h | 406 + .../libSBRdec/src/HFgen_preFlat.cpp | 994 +++ .../libSBRdec/src/HFgen_preFlat.h | 132 + .../fdk-aac-2.0.3/libSBRdec/src/env_calc.cpp | 3202 ++++++++ .../fdk-aac-2.0.3/libSBRdec/src/env_calc.h | 182 + .../fdk-aac-2.0.3/libSBRdec/src/env_dec.cpp | 873 ++ .../fdk-aac-2.0.3/libSBRdec/src/env_dec.h | 119 + .../fdk-aac-2.0.3/libSBRdec/src/env_extr.cpp | 1732 ++++ .../fdk-aac-2.0.3/libSBRdec/src/env_extr.h | 415 + .../fdk-aac-2.0.3/libSBRdec/src/hbe.cpp | 2187 +++++ .../fdk-aac/fdk-aac-2.0.3/libSBRdec/src/hbe.h | 200 + .../fdk-aac-2.0.3/libSBRdec/src/huff_dec.cpp | 137 + .../fdk-aac-2.0.3/libSBRdec/src/huff_dec.h | 117 + .../fdk-aac-2.0.3/libSBRdec/src/lpp_tran.cpp | 1488 ++++ .../fdk-aac-2.0.3/libSBRdec/src/lpp_tran.h | 275 + .../fdk-aac-2.0.3/libSBRdec/src/psbitdec.cpp | 594 ++ .../fdk-aac-2.0.3/libSBRdec/src/psbitdec.h | 116 + .../fdk-aac-2.0.3/libSBRdec/src/psdec.cpp | 714 ++ .../fdk-aac-2.0.3/libSBRdec/src/psdec.h | 333 + .../fdk-aac-2.0.3/libSBRdec/src/psdec_drm.cpp | 108 + .../fdk-aac-2.0.3/libSBRdec/src/psdec_drm.h | 113 + .../libSBRdec/src/psdecrom_drm.cpp | 108 + .../fdk-aac-2.0.3/libSBRdec/src/pvc_dec.cpp | 684 ++ .../fdk-aac-2.0.3/libSBRdec/src/pvc_dec.h | 238 + .../fdk-aac-2.0.3/libSBRdec/src/sbr_deb.cpp | 108 + .../fdk-aac-2.0.3/libSBRdec/src/sbr_deb.h | 113 + .../fdk-aac-2.0.3/libSBRdec/src/sbr_dec.cpp | 1482 ++++ .../fdk-aac-2.0.3/libSBRdec/src/sbr_dec.h | 205 + .../fdk-aac-2.0.3/libSBRdec/src/sbr_ram.cpp | 188 + .../fdk-aac-2.0.3/libSBRdec/src/sbr_ram.h | 189 + .../fdk-aac-2.0.3/libSBRdec/src/sbr_rom.cpp | 1193 +++ .../fdk-aac-2.0.3/libSBRdec/src/sbr_rom.h | 216 + .../libSBRdec/src/sbrdec_drc.cpp | 543 ++ .../fdk-aac-2.0.3/libSBRdec/src/sbrdec_drc.h | 149 + .../libSBRdec/src/sbrdec_freq_sca.cpp | 838 ++ .../libSBRdec/src/sbrdec_freq_sca.h | 127 + .../libSBRdec/src/sbrdecoder.cpp | 2015 +++++ .../libSBRdec/src/transcendent.h | 372 + .../libSBRenc/include/sbr_encoder.h | 483 ++ .../fdk-aac-2.0.3/libSBRenc/src/bit_sbr.cpp | 1049 +++ .../fdk-aac-2.0.3/libSBRenc/src/bit_sbr.h | 267 + .../fdk-aac-2.0.3/libSBRenc/src/cmondata.h | 127 + .../fdk-aac-2.0.3/libSBRenc/src/code_env.cpp | 602 ++ .../fdk-aac-2.0.3/libSBRenc/src/code_env.h | 161 + .../fdk-aac-2.0.3/libSBRenc/src/env_bit.cpp | 257 + .../fdk-aac-2.0.3/libSBRenc/src/env_bit.h | 135 + .../fdk-aac-2.0.3/libSBRenc/src/env_est.cpp | 1993 +++++ .../fdk-aac-2.0.3/libSBRenc/src/env_est.h | 223 + .../fdk-aac-2.0.3/libSBRenc/src/fram_gen.cpp | 1965 +++++ .../fdk-aac-2.0.3/libSBRenc/src/fram_gen.h | 343 + .../fdk-aac-2.0.3/libSBRenc/src/invf_est.cpp | 610 ++ .../fdk-aac-2.0.3/libSBRenc/src/invf_est.h | 181 + .../fdk-aac-2.0.3/libSBRenc/src/mh_det.cpp | 1396 ++++ .../fdk-aac-2.0.3/libSBRenc/src/mh_det.h | 204 + .../fdk-aac-2.0.3/libSBRenc/src/nf_est.cpp | 612 ++ .../fdk-aac-2.0.3/libSBRenc/src/nf_est.h | 185 + .../fdk-aac-2.0.3/libSBRenc/src/ps_bitenc.cpp | 624 ++ .../fdk-aac-2.0.3/libSBRenc/src/ps_bitenc.h | 173 + .../fdk-aac-2.0.3/libSBRenc/src/ps_const.h | 150 + .../fdk-aac-2.0.3/libSBRenc/src/ps_encode.cpp | 1031 +++ .../fdk-aac-2.0.3/libSBRenc/src/ps_encode.h | 185 + .../fdk-aac-2.0.3/libSBRenc/src/ps_main.cpp | 606 ++ .../fdk-aac-2.0.3/libSBRenc/src/ps_main.h | 270 + .../fdk-aac-2.0.3/libSBRenc/src/resampler.cpp | 444 + .../fdk-aac-2.0.3/libSBRenc/src/resampler.h | 159 + .../fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr.h | 194 + .../fdk-aac-2.0.3/libSBRenc/src/sbr_def.h | 276 + .../libSBRenc/src/sbr_encoder.cpp | 2576 ++++++ .../fdk-aac-2.0.3/libSBRenc/src/sbr_misc.cpp | 265 + .../fdk-aac-2.0.3/libSBRenc/src/sbr_misc.h | 127 + .../libSBRenc/src/sbrenc_freq_sca.cpp | 674 ++ .../libSBRenc/src/sbrenc_freq_sca.h | 132 + .../libSBRenc/src/sbrenc_ram.cpp | 249 + .../fdk-aac-2.0.3/libSBRenc/src/sbrenc_ram.h | 199 + .../libSBRenc/src/sbrenc_rom.cpp | 910 +++ .../fdk-aac-2.0.3/libSBRenc/src/sbrenc_rom.h | 145 + .../fdk-aac-2.0.3/libSBRenc/src/ton_corr.cpp | 891 ++ .../fdk-aac-2.0.3/libSBRenc/src/ton_corr.h | 258 + .../fdk-aac-2.0.3/libSBRenc/src/tran_det.cpp | 1092 +++ .../fdk-aac-2.0.3/libSBRenc/src/tran_det.h | 191 + .../fdk-aac-2.0.3/libSYS/include/FDK_audio.h | 813 ++ .../libSYS/include/genericStds.h | 584 ++ .../libSYS/include/machine_type.h | 411 + .../libSYS/include/syslib_channelMapDescr.h | 202 + .../fdk-aac-2.0.3/libSYS/src/genericStds.cpp | 419 + .../libSYS/src/syslib_channelMapDescr.cpp | 315 + .../fdk-aac/fdk-aac-2.0.3/m4/.gitkeep | 0 .../thirdparty/fdk-aac/fdk-aac-2.0.3/sha1.c | 399 + .../thirdparty/fdk-aac/fdk-aac-2.0.3/sha1.h | 85 + .../fdk-aac-2.0.3/test-encode-decode.c | 383 + .../fdk-aac/fdk-aac-2.0.3/test/ref-mono.txt | 2 + .../fdk-aac/fdk-aac-2.0.3/test/ref-stereo.txt | 2 + .../fdk-aac/fdk-aac-2.0.3/test/run-test.sh | 28 + .../fdk-aac/fdk-aac-2.0.3/wavreader.c | 193 + .../fdk-aac/fdk-aac-2.0.3/wavreader.h | 37 + .../fdk-aac/fdk-aac-2.0.3/win32/getopt.h | 904 ++ 439 files changed, 222956 insertions(+) create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/.clang-format create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/.github/workflows/ci.yml create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/.gitignore create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/Android.bp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/CMakeLists.txt create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/ChangeLog create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/METADATA create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/MODULE_LICENSE_FRAUNHOFER create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/Makefile.am create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/NOTICE create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/OWNERS create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/PREUPLOAD.cfg create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/aac-enc.c create mode 100755 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/autogen.sh create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/configure.ac create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/documentation/aacDecoder.pdf create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/documentation/aacEncoder.pdf create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/fdk-aac-config.cmake.in create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/fdk-aac.def create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/fdk-aac.pc.in create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/fdk-aac.sym create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/fuzzer/Android.bp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/fuzzer/README.md create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/fuzzer/aac_dec_fuzzer.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/fuzzer/aac_enc_fuzzer.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/include/aacdecoder_lib.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/FDK_delay.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/FDK_delay.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_ram.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_ram.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_rom.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_rom.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_drc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_drc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_drc_types.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr_bit.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr_bit.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr_types.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcrs.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcrs.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_pns.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_pns.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_tns.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_tns.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdecoder.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdecoder.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdecoder_lib.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/arm/block_arm.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/block.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/block.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channel.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channel.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channelinfo.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channelinfo.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/conceal.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/conceal.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/conceal_types.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/ldfiltbank.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/ldfiltbank.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/overlapadd.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/pulsedata.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/pulsedata.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlc_info.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcbit.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcbit.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcconceal.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcconceal.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/stereo.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/stereo.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_d4t64.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_d4t64.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_ltp.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_ltp.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_acelp.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_acelp.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_const.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_fac.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_fac.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpd.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpd.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_rom.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_rom.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/include/aacenc_lib.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_ram.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_ram.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_rom.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_rom.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_lib.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_pns.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_pns.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_tns.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_tns.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/adj_thr.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/adj_thr.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/adj_thr_data.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/band_nrg.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/band_nrg.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bandwidth.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bandwidth.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bit_cnt.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bit_cnt.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bitenc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bitenc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/block_switch.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/block_switch.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/channel_map.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/channel_map.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/chaosmeasure.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/chaosmeasure.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/dyn_bits.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/dyn_bits.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/grp_data.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/grp_data.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/intensity.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/intensity.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/interface.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/line_pe.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/line_pe.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_compressor.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_compressor.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_main.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_main.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/mps_main.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/mps_main.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/ms_stereo.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/ms_stereo.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/noisedet.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/noisedet.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pns_func.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pnsparam.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pnsparam.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pre_echo_control.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pre_echo_control.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_configuration.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_configuration.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_const.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_data.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_main.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_main.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/qc_data.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/qc_main.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/qc_main.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/quantize.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/quantize.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/sf_estim.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/sf_estim.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/spreading.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/spreading.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/tns_func.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/tonality.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/tonality.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/transform.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/transform.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libArithCoding/include/ac_arith_coder.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libArithCoding/src/ac_arith_coder.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/include/FDK_drcDecLib.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/FDK_drcDecLib.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_gainDecoder.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_gainDecoder.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_reader.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_reader.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_rom.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_rom.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_selectionProcess.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_selectionProcess.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_tools.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_tools.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_types.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDecoder.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_init.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_init.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_preprocess.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_preprocess.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_process.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_process.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_archdef.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_bitbuffer.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_bitstream.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_core.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_crc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_decorrelate.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_hybrid.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_lpc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_matrixCalloc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_qmf_domain.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_tools_rom.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_trigFcts.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/abs.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/clz_arm.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/cplx_mul_arm.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/fixmadd_arm.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/fixmul_arm.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/scale_arm.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/scramble_arm.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/autocorr2nd.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/clz.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/common_fix.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/cplx_mul.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/dct.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fft.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fft_rad2.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixmadd.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixminmax.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixmul.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixpoint_math.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/huff_nodes.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mdct.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/abs_mips.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/clz_mips.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/cplx_mul_mips.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/fixmul_mips.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/scale_mips.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/scramble_mips.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/nlc_dec.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/ppc/clz_ppc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/ppc/fixmul_ppc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/qmf.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/qmf_pcm.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/scale.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/scramble.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/abs_x86.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/clz_x86.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/fixmul_x86.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/fixpoint_math_x86.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_bitbuffer.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_core.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_crc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_decorrelate.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_hybrid.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_lpc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_matrixCalloc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_qmf_domain.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_tools_rom.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_trigFcts.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/arm/fft_rad2_arm.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/arm/scale_arm.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/autocorr2nd.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/dct.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/fft.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/fft_rad2.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/fixpoint_math.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/huff_nodes.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mdct.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mips/fft_rad2_mips.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mips/mips_fft_twiddles.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mips/scale_mips.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/nlc_dec.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/qmf.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/scale.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/include/tp_data.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/include/tpdec_lib.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tp_version.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adif.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adif.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adts.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adts.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_asc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_drm.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_drm.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_latm.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_latm.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_lib.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/include/tp_data.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/include/tpenc_lib.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tp_version.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adif.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adif.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adts.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adts.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_asc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_asc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_latm.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_latm.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_lib.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/include/limiter.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/include/pcm_utils.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/include/pcmdmx_lib.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/limiter.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/pcm_utils.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/pcmdmx_lib.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/version.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/include/sac_dec_errorcodes.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/include/sac_dec_lib.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_bitdec.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_bitdec.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_calcM1andM2.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_calcM1andM2.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_conceal.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_conceal.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_interface.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_lib.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_ssc_struct.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_process.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_process.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_qmf.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_qmf.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_reshapeBBEnv.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_reshapeBBEnv.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_rom.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_rom.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_smoothing.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_smoothing.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_stp.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_stp.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_tsd.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_tsd.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/include/sacenc_lib.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_bitstream.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_bitstream.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_const.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_delay.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_delay.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_dmx_tdom_enh.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_dmx_tdom_enh.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_filter.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_filter.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_framewindowing.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_framewindowing.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_huff_tab.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_huff_tab.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_lib.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_nlc_enc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_nlc_enc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_onsetdetect.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_onsetdetect.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_paramextract.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_paramextract.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_staticgain.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_staticgain.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_tree.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_tree.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_vectorfunctions.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_vectorfunctions.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/include/sbrdecoder.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/HFgen_preFlat.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/HFgen_preFlat.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_calc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_calc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_dec.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_dec.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_extr.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_extr.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/hbe.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/hbe.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/huff_dec.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/huff_dec.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/lpp_tran.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/lpp_tran.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psbitdec.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psbitdec.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec_drm.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec_drm.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdecrom_drm.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/pvc_dec.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/pvc_dec.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_deb.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_deb.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_dec.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_dec.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_ram.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_ram.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_rom.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_rom.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_drc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_drc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_freq_sca.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_freq_sca.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdecoder.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/transcendent.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/include/sbr_encoder.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/bit_sbr.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/bit_sbr.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/cmondata.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/code_env.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/code_env.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_bit.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_bit.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_est.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_est.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/fram_gen.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/fram_gen.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/invf_est.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/invf_est.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/mh_det.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/mh_det.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/nf_est.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/nf_est.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_bitenc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_bitenc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_const.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_encode.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_encode.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_main.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_main.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/resampler.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/resampler.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_def.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_encoder.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_misc.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_misc.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_freq_sca.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_freq_sca.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_ram.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_ram.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_rom.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_rom.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ton_corr.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ton_corr.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/tran_det.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/tran_det.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/FDK_audio.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/genericStds.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/machine_type.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/syslib_channelMapDescr.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/src/genericStds.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/src/syslib_channelMapDescr.cpp create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/m4/.gitkeep create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/sha1.c create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/sha1.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test-encode-decode.c create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test/ref-mono.txt create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test/ref-stereo.txt create mode 100755 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test/run-test.sh create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/wavreader.c create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/wavreader.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/win32/getopt.h diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/.clang-format b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/.clang-format new file mode 100644 index 0000000000000..caeb77385930b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/.clang-format @@ -0,0 +1,4 @@ +BasedOnStyle: Google +SortIncludes: false +# Do not reformat the Doxygen-style comments in the code +CommentPragmas : "^ * \\\\" diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/.github/workflows/ci.yml b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/.github/workflows/ci.yml new file mode 100644 index 0000000000000..c6ba3eacc7664 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/.github/workflows/ci.yml @@ -0,0 +1,215 @@ +name: CI +on: [push, pull_request] + +jobs: + linux-autotools: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build + run: | + ./autogen.sh + ./configure --enable-example + make -j$(nproc) CFLAGS="-g -O2 -Werror" CXXFLAGS="-g -O2 -Werror" + - name: Run tests + run: | + sudo apt-get update && sudo apt-get install --no-install-recommends ffmpeg + ./test/run-test.sh + + linux-cmake: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build + run: | + cmake . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_PROGRAMS=YES -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror -Wno-stringop-overflow" + cmake --build build + - name: Run tests + run: | + sudo apt-get update && sudo apt-get install --no-install-recommends ffmpeg + cd build + ../test/run-test.sh + + linux-sanitizers-gcc-autotools: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build + run: | + ./autogen.sh + FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize=shift-base -DDEBUG -fno-sanitize-recover=all" + CC="gcc $FLAGS" CXX="g++ $FLAGS" ./configure --enable-example + make -j$(nproc) + - name: Run tests + run: | + sudo apt-get update && sudo apt-get install --no-install-recommends ffmpeg + ./test/run-test.sh + + linux-sanitizers-clang-cmake: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build + run: | + FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize=shift-base -DDEBUG -fno-sanitize-recover=all -fno-sanitize=vptr -fno-sanitize=function" + cmake . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_PROGRAMS=YES -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS="$FLAGS" -DCMAKE_CXX_FLAGS="$FLAGS" + cmake --build build + - name: Run tests + run: | + sudo apt-get update && sudo apt-get install --no-install-recommends ffmpeg + cd build + ../test/run-test.sh + + macos-autotools: + runs-on: macos-latest + steps: + - name: Install autotools + run: | + brew install automake + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build + run: | + ./autogen.sh + ./configure --enable-example + make -j$(sysctl -n hw.ncpu) CFLAGS="-g -O2 -Werror" CXXFLAGS="-g -O2 -Werror -Wno-deprecated-declarations" + + macos-cmake: + runs-on: macos-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build + run: | + cmake . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_PROGRAMS=YES -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror -Wno-deprecated-declarations" + cmake --build build + + mingw-cross-autotools: + runs-on: ubuntu-latest + steps: + - name: Install cross compiler + run: | + sudo apt-get update && sudo apt-get install g++-mingw-w64-x86-64 + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build + run: | + ./autogen.sh + ./configure --enable-example --host=x86_64-w64-mingw32 + make -j$(nproc) CFLAGS="-g -O2 -Werror" CXXFLAGS="-g -O2 -Werror" + + mingw-cross-cmake: + runs-on: ubuntu-latest + steps: + - name: Install cross compiler + run: | + sudo apt-get update && sudo apt-get install g++-mingw-w64-x86-64 + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build + run: | + cmake . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_PROGRAMS=YES -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ -DCMAKE_CROSSCOMPILING=TRUE -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror -Wno-stringop-overflow" + cmake --build build + + msys-cmake: + runs-on: windows-latest + defaults: + run: + shell: msys2 {0} + steps: + - uses: msys2/setup-msys2@v2 + with: + msystem: mingw64 + update: true + install: >- + git + mingw-w64-x86_64-toolchain + mingw-w64-x86_64-cmake + mingw-w64-x86_64-ninja + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build + run: | + cmake . -G Ninja -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_PROGRAMS=YES + cmake --build build + + msvc-cmake: + runs-on: windows-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build + run: | + cmake . -B build -DBUILD_PROGRAMS=YES + cmake --build build --config Release + + msvc-cmake-ninja-arm: + runs-on: windows-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Set up the environment + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: amd64_arm + - name: Build + run: | + cmake . -G Ninja -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_PROGRAMS=YES + cmake --build build + + msvc-cmake-arm64: + runs-on: windows-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build + run: | + cmake . -B build -DBUILD_PROGRAMS=YES -A ARM64 + cmake --build build --config Release + + llvm-mingw: + runs-on: ubuntu-latest + steps: + - name: Install llvm-mingw + run: | + wget https://github.com/mstorsjo/llvm-mingw/releases/download/20231003/llvm-mingw-20231003-ucrt-ubuntu-20.04-x86_64.tar.xz + tar -Jxvf llvm-mingw-*-ucrt-ubuntu-*-x86_64.tar.xz + rm llvm-mingw-*.tar.xz + sudo mv llvm-mingw-* /opt/llvm-mingw + echo /opt/llvm-mingw/bin >> $GITHUB_PATH + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build fdk-aac + run: | + ./autogen.sh + ./configure --host=aarch64-w64-mingw32 --enable-example + make -j$(nproc) CFLAGS="-g -O2 -Werror" CXXFLAGS="-g -O2 -Werror" + + linux-ffmpeg: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Build fdk-aac + run: | + ./autogen.sh + mkdir build + cd build + ../configure --enable-example --prefix=$(pwd)/../prefix + make -j$(nproc) + make -j$(nproc) install + - name: Checkout FFmpeg + uses: actions/checkout@v4 + with: + repository: ffmpeg/ffmpeg + path: ffmpeg + - name: Build FFmpeg + run: | + sudo apt-get update && sudo apt-get install -y nasm + cd ffmpeg + PKG_CONFIG_PATH=$(pwd)/../prefix/lib/pkgconfig ./configure --enable-libfdk-aac --enable-nonfree + make -j$(nproc) diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/.gitignore b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/.gitignore new file mode 100644 index 0000000000000..d193505fe284f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/.gitignore @@ -0,0 +1,46 @@ +*.o +*.lo +*.la +*~ +.deps +.libs +.dirstamp +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +configure +fdk-aac.pc +config.guess +config.log +config.status +config.sub +depcomp +install-sh +libtool +ltmain.sh +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 +missing +stamp-h1 +aac-enc +test-encode-decode +compile + +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +CMakeSettings.json + +*[Bb]uild*/ + +.vs/ +.vscode/ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/Android.bp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/Android.bp new file mode 100644 index 0000000000000..6060256ff5b98 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/Android.bp @@ -0,0 +1,101 @@ +// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE +// CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE +// DEPENDING ON IT IN YOUR PROJECT. *** +package { + default_applicable_licenses: ["external_aac_license"], +} + +// Added automatically by a large-scale-change that took the approach of +// 'apply every license found to every target'. While this makes sure we respect +// every license restriction, it may not be entirely correct. +// +// e.g. GPL in an MIT project might only apply to the contrib/ directory. +// +// Please consider splitting the single license below into multiple licenses, +// taking care not to lose any license_kind information, and overriding the +// default license using the 'licenses: [...]' property on targets as needed. +// +// For unused files, consider creating a 'fileGroup' with "//visibility:private" +// to attach the license to, and including a comment whether the files may be +// used in the current project. +// See: http://go/android-license-faq +license { + name: "external_aac_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + "legacy_by_exception_only", // by exception only + ], + license_text: [ + "NOTICE", + ], +} + +cc_library_static { + name: "libFraunhoferAAC", + vendor_available: true, + host_supported: true, + srcs: [ + "libAACdec/src/*.cpp", + "libAACenc/src/*.cpp", + "libPCMutils/src/*.cpp", + "libFDK/src/*.cpp", + "libSYS/src/*.cpp", + "libMpegTPDec/src/*.cpp", + "libMpegTPEnc/src/*.cpp", + "libSBRdec/src/*.cpp", + "libSBRenc/src/*.cpp", + "libArithCoding/src/*.cpp", + "libDRCdec/src/*.cpp", + "libSACdec/src/*.cpp", + "libSACenc/src/*.cpp", + ], + cflags: [ + "-Werror", + "-Wno-unused-parameter", + "-Wno-#warnings", + "-Wuninitialized", + "-Wno-self-assign", + "-Wno-implicit-fallthrough", + "-DSUPPRESS_BUILD_DATE_INFO", + ], + sanitize: { + misc_undefined: [ + "unsigned-integer-overflow", + "signed-integer-overflow", + "bounds", + ], + cfi: true, + }, + shared_libs: [ + "liblog", + ], + export_include_dirs: [ + "libAACdec/include", + "libAACenc/include", + "libPCMutils/include", + "libFDK/include", + "libSYS/include", + "libMpegTPDec/include", + "libMpegTPEnc/include", + "libSBRdec/include", + "libSBRenc/include", + "libArithCoding/include", + "libDRCdec/include", + "libSACdec/include", + "libSACenc/include", + ], + + target: { + darwin: { + enabled: false, + }, + }, + + apex_available: [ + "//apex_available:platform", + "com.android.btservices", + "com.android.media.swcodec", + ], + min_sdk_version: "29", +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/CMakeLists.txt b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/CMakeLists.txt new file mode 100644 index 0000000000000..03f46ccca5d9e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/CMakeLists.txt @@ -0,0 +1,600 @@ +# # CMake project for fdk-aac +# +# ## Basic usage +# +# 1. Download and install CMake >= 3.10 (CMake >= 3.15 is recommended) +# 2. Clone fdk-aac repository +# 3. In fdk-aac directory create and go to `build` subdirectory: +# +# mkdir build +# cd build +# +# 4. Run cmake to configure project with desired build type (Release|Debug): +# +# cmake .. -DCMAKE_BUILD_TYPE=Release +# +# Note CMake configuration without CMAKE_BUILD_TYPE option will not set build +# type to some default and it is most likely is not what you want. +# +# If you want to build static (default is shared library), add BUILD_SHARED_LIBS=OFF option: +# +# # cmake .. -DBUILD_SHARED_LIBS=OFF +# +# You can combine options as well: +# +# cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF +# +# 5. Run cmake to build project: +# +# cmake --build . -c Release + +cmake_minimum_required(VERSION 3.5.1) + +# Policies + +## Enables CMAKE_MSVC_RUNTIME_LIBRARY option support for CMake >= 3.15 +## if you want to use a MSVC multi-threaded statically-linked runtime library +## If you enable it, CMake will build fdk-acc.dll without external dependencies. +## +## Example usage: +## +## cmake .. -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$:Debug> +if(POLICY CMP0091) + cmake_policy(SET CMP0091 NEW) +endif() + +project(fdk-aac VERSION 2.0.3) + +# Includes + +include(CheckFunctionExists) +include(CheckLibraryExists) +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +if(CMAKE_VERSION VERSION_LESS 3.11) + set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) + set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) + set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) +endif() +include(CPack) + +# Options + +option(BUILD_SHARED_LIBS "Build shared library" ON) +option(BUILD_PROGRAMS "Build extra utilities" OFF) +option(FDK_AAC_INSTALL_CMAKE_CONFIG_MODULE "Install CMake package configuration file" ON) +option(FDK_AAC_INSTALL_PKGCONFIG_MODULE "Install pkg-config .pc file" ON) + +# Checks + +## Check if math functions are in separate library (Most of Linux distros, maybe some other OSes) +check_function_exists(sin HAVE_DEFAULT_MATH) +if(NOT HAVE_DEFAULT_MATH) + check_library_exists(m sin "" HAVE_LIBM) +endif() + +# Library + +## Sources + +set(AACDEC_SRC + libAACdec/src/FDK_delay.cpp + libAACdec/src/aac_ram.cpp + libAACdec/src/aac_rom.cpp + libAACdec/src/aacdec_drc.cpp + libAACdec/src/aacdec_hcr.cpp + libAACdec/src/aacdec_hcr_bit.cpp + libAACdec/src/aacdec_hcrs.cpp + libAACdec/src/aacdec_pns.cpp + libAACdec/src/aacdec_tns.cpp + libAACdec/src/aacdecoder.cpp + libAACdec/src/aacdecoder_lib.cpp + libAACdec/src/block.cpp + libAACdec/src/channel.cpp + libAACdec/src/channelinfo.cpp + libAACdec/src/conceal.cpp + libAACdec/src/ldfiltbank.cpp + libAACdec/src/pulsedata.cpp + libAACdec/src/rvlc.cpp + libAACdec/src/rvlcbit.cpp + libAACdec/src/rvlcconceal.cpp + libAACdec/src/stereo.cpp + libAACdec/src/usacdec_ace_d4t64.cpp + libAACdec/src/usacdec_ace_ltp.cpp + libAACdec/src/usacdec_acelp.cpp + libAACdec/src/usacdec_fac.cpp + libAACdec/src/usacdec_lpc.cpp + libAACdec/src/usacdec_lpd.cpp + libAACdec/src/usacdec_rom.cpp + libAACdec/src/aac_ram.h + libAACdec/src/aac_rom.h + libAACdec/src/aacdec_drc.h + libAACdec/src/aacdec_drc_types.h + libAACdec/src/aacdec_hcr.h + libAACdec/src/aacdec_hcr_bit.h + libAACdec/src/aacdec_hcr_types.h + libAACdec/src/aacdec_hcrs.h + libAACdec/src/aacdec_pns.h + libAACdec/src/aacdec_tns.h + libAACdec/src/aacdecoder.h + libAACdec/src/block.h + libAACdec/src/channel.h + libAACdec/src/channelinfo.h + libAACdec/src/conceal.h + libAACdec/src/conceal_types.h + libAACdec/src/FDK_delay.h + libAACdec/src/ldfiltbank.h + libAACdec/src/overlapadd.h + libAACdec/src/pulsedata.h + libAACdec/src/rvlc.h + libAACdec/src/rvlc_info.h + libAACdec/src/rvlcbit.h + libAACdec/src/rvlcconceal.h + libAACdec/src/stereo.h + libAACdec/src/usacdec_ace_d4t64.h + libAACdec/src/usacdec_ace_ltp.h + libAACdec/src/usacdec_acelp.h + libAACdec/src/usacdec_const.h + libAACdec/src/usacdec_fac.h + libAACdec/src/usacdec_lpc.h + libAACdec/src/usacdec_lpd.h + libAACdec/src/usacdec_rom.h) + +set(AACENC_SRC + libAACenc/src/aacEnc_ram.cpp + libAACenc/src/aacEnc_rom.cpp + libAACenc/src/aacenc.cpp + libAACenc/src/aacenc_lib.cpp + libAACenc/src/aacenc_pns.cpp + libAACenc/src/aacenc_tns.cpp + libAACenc/src/adj_thr.cpp + libAACenc/src/band_nrg.cpp + libAACenc/src/bandwidth.cpp + libAACenc/src/bit_cnt.cpp + libAACenc/src/bitenc.cpp + libAACenc/src/block_switch.cpp + libAACenc/src/channel_map.cpp + libAACenc/src/chaosmeasure.cpp + libAACenc/src/dyn_bits.cpp + libAACenc/src/grp_data.cpp + libAACenc/src/intensity.cpp + libAACenc/src/line_pe.cpp + libAACenc/src/metadata_compressor.cpp + libAACenc/src/metadata_main.cpp + libAACenc/src/mps_main.cpp + libAACenc/src/ms_stereo.cpp + libAACenc/src/noisedet.cpp + libAACenc/src/pnsparam.cpp + libAACenc/src/pre_echo_control.cpp + libAACenc/src/psy_configuration.cpp + libAACenc/src/psy_main.cpp + libAACenc/src/qc_main.cpp + libAACenc/src/quantize.cpp + libAACenc/src/sf_estim.cpp + libAACenc/src/spreading.cpp + libAACenc/src/tonality.cpp + libAACenc/src/transform.cpp + libAACenc/src/aacenc.h + libAACenc/src/aacenc_pns.h + libAACenc/src/aacEnc_ram.h + libAACenc/src/aacEnc_rom.h + libAACenc/src/aacenc_tns.h + libAACenc/src/adj_thr.h + libAACenc/src/adj_thr_data.h + libAACenc/src/band_nrg.h + libAACenc/src/bandwidth.h + libAACenc/src/bit_cnt.h + libAACenc/src/bitenc.h + libAACenc/src/block_switch.h + libAACenc/src/channel_map.h + libAACenc/src/chaosmeasure.h + libAACenc/src/dyn_bits.h + libAACenc/src/grp_data.h + libAACenc/src/intensity.h + libAACenc/src/interface.h + libAACenc/src/line_pe.h + libAACenc/src/metadata_compressor.h + libAACenc/src/metadata_main.h + libAACenc/src/mps_main.h + libAACenc/src/ms_stereo.h + libAACenc/src/noisedet.h + libAACenc/src/pns_func.h + libAACenc/src/pnsparam.h + libAACenc/src/pre_echo_control.h + libAACenc/src/psy_configuration.h + libAACenc/src/psy_const.h + libAACenc/src/psy_data.h + libAACenc/src/psy_main.h + libAACenc/src/qc_data.h + libAACenc/src/qc_main.h + libAACenc/src/quantize.h + libAACenc/src/sf_estim.h + libAACenc/src/spreading.h + libAACenc/src/tns_func.h + libAACenc/src/tonality.h + libAACenc/src/transform.h) + +set(ARITHCODING_SRC + libArithCoding/src/ac_arith_coder.cpp) + +set(DRCDEC_SRC + libDRCdec/src/FDK_drcDecLib.cpp + libDRCdec/src/drcDec_gainDecoder.cpp + libDRCdec/src/drcDec_reader.cpp + libDRCdec/src/drcDec_rom.cpp + libDRCdec/src/drcDec_selectionProcess.cpp + libDRCdec/src/drcDec_tools.cpp + libDRCdec/src/drcGainDec_init.cpp + libDRCdec/src/drcGainDec_preprocess.cpp + libDRCdec/src/drcGainDec_process.cpp + libDRCdec/src/drcDec_gainDecoder.h + libDRCdec/src/drcDec_reader.h + libDRCdec/src/drcDec_rom.h + libDRCdec/src/drcDec_selectionProcess.h + libDRCdec/src/drcDec_tools.h + libDRCdec/src/drcDec_types.h + libDRCdec/src/drcDecoder.h + libDRCdec/src/drcGainDec_init.h + libDRCdec/src/drcGainDec_preprocess.h + libDRCdec/src/drcGainDec_process.h) + +set(FDK_SRC + libFDK/src/FDK_bitbuffer.cpp + libFDK/src/FDK_core.cpp + libFDK/src/FDK_crc.cpp + libFDK/src/FDK_decorrelate.cpp + libFDK/src/FDK_hybrid.cpp + libFDK/src/FDK_lpc.cpp + libFDK/src/FDK_matrixCalloc.cpp + libFDK/src/FDK_qmf_domain.cpp + libFDK/src/FDK_tools_rom.cpp + libFDK/src/FDK_trigFcts.cpp + libFDK/src/autocorr2nd.cpp + libFDK/src/dct.cpp + libFDK/src/fft.cpp + libFDK/src/fft_rad2.cpp + libFDK/src/fixpoint_math.cpp + libFDK/src/huff_nodes.cpp + libFDK/src/mdct.cpp + libFDK/src/nlc_dec.cpp + libFDK/src/qmf.cpp + libFDK/src/scale.cpp) + +set(MPEGTPDEC_SRC + libMpegTPDec/src/tpdec_adif.cpp + libMpegTPDec/src/tpdec_adts.cpp + libMpegTPDec/src/tpdec_asc.cpp + libMpegTPDec/src/tpdec_drm.cpp + libMpegTPDec/src/tpdec_latm.cpp + libMpegTPDec/src/tpdec_lib.cpp + libMpegTPDec/src/tp_version.h + libMpegTPDec/src/tpdec_adif.h + libMpegTPDec/src/tpdec_adts.h + libMpegTPDec/src/tpdec_drm.h + libMpegTPDec/src/tpdec_latm.h) + +set(MPEGTPENC_SRC + libMpegTPEnc/src/tpenc_adif.cpp + libMpegTPEnc/src/tpenc_adts.cpp + libMpegTPEnc/src/tpenc_asc.cpp + libMpegTPEnc/src/tpenc_latm.cpp + libMpegTPEnc/src/tpenc_lib.cpp + libMpegTPEnc/src/tp_version.h + libMpegTPEnc/src/tpenc_adif.h + libMpegTPEnc/src/tpenc_adts.h + libMpegTPEnc/src/tpenc_asc.h + libMpegTPEnc/src/tpenc_latm.h) + +set(PCMUTILS_SRC + libPCMutils/src/limiter.cpp + libPCMutils/src/pcm_utils.cpp + libPCMutils/src/pcmdmx_lib.cpp + libPCMutils/src/version.h) + +set(SACDEC_SRC + libSACdec/src/sac_bitdec.cpp + libSACdec/src/sac_calcM1andM2.cpp + libSACdec/src/sac_dec.cpp + libSACdec/src/sac_dec_conceal.cpp + libSACdec/src/sac_dec_lib.cpp + libSACdec/src/sac_process.cpp + libSACdec/src/sac_qmf.cpp + libSACdec/src/sac_reshapeBBEnv.cpp + libSACdec/src/sac_rom.cpp + libSACdec/src/sac_smoothing.cpp + libSACdec/src/sac_stp.cpp + libSACdec/src/sac_tsd.cpp + libSACdec/src/sac_bitdec.h + libSACdec/src/sac_calcM1andM2.h + libSACdec/src/sac_dec.h + libSACdec/src/sac_dec_conceal.h + libSACdec/src/sac_dec_interface.h + libSACdec/src/sac_dec_ssc_struct.h + libSACdec/src/sac_process.h + libSACdec/src/sac_qmf.h + libSACdec/src/sac_reshapeBBEnv.h + libSACdec/src/sac_rom.h + libSACdec/src/sac_smoothing.h + libSACdec/src/sac_stp.h + libSACdec/src/sac_tsd.h) + +set(SACENC_SRC + libSACenc/src/sacenc_bitstream.cpp + libSACenc/src/sacenc_delay.cpp + libSACenc/src/sacenc_dmx_tdom_enh.cpp + libSACenc/src/sacenc_filter.cpp + libSACenc/src/sacenc_framewindowing.cpp + libSACenc/src/sacenc_huff_tab.cpp + libSACenc/src/sacenc_lib.cpp + libSACenc/src/sacenc_nlc_enc.cpp + libSACenc/src/sacenc_onsetdetect.cpp + libSACenc/src/sacenc_paramextract.cpp + libSACenc/src/sacenc_staticgain.cpp + libSACenc/src/sacenc_tree.cpp + libSACenc/src/sacenc_vectorfunctions.cpp + libSACenc/src/sacenc_bitstream.h + libSACenc/src/sacenc_const.h + libSACenc/src/sacenc_delay.h + libSACenc/src/sacenc_dmx_tdom_enh.h + libSACenc/src/sacenc_filter.h + libSACenc/src/sacenc_framewindowing.h + libSACenc/src/sacenc_huff_tab.h + libSACenc/src/sacenc_nlc_enc.h + libSACenc/src/sacenc_onsetdetect.h + libSACenc/src/sacenc_paramextract.h + libSACenc/src/sacenc_staticgain.h + libSACenc/src/sacenc_tree.h + libSACenc/src/sacenc_vectorfunctions.h) + +set(SBRDEC_SRC + libSBRdec/src/HFgen_preFlat.cpp + libSBRdec/src/env_calc.cpp + libSBRdec/src/env_dec.cpp + libSBRdec/src/env_extr.cpp + libSBRdec/src/hbe.cpp + libSBRdec/src/huff_dec.cpp + libSBRdec/src/lpp_tran.cpp + libSBRdec/src/psbitdec.cpp + libSBRdec/src/psdec.cpp + libSBRdec/src/psdec_drm.cpp + libSBRdec/src/psdecrom_drm.cpp + libSBRdec/src/pvc_dec.cpp + libSBRdec/src/sbr_deb.cpp + libSBRdec/src/sbr_dec.cpp + libSBRdec/src/sbr_ram.cpp + libSBRdec/src/sbr_rom.cpp + libSBRdec/src/sbrdec_drc.cpp + libSBRdec/src/sbrdec_freq_sca.cpp + libSBRdec/src/sbrdecoder.cpp + libSBRdec/src/env_calc.h + libSBRdec/src/env_dec.h + libSBRdec/src/env_extr.h + libSBRdec/src/hbe.h + libSBRdec/src/HFgen_preFlat.h + libSBRdec/src/huff_dec.h + libSBRdec/src/lpp_tran.h + libSBRdec/src/psbitdec.h + libSBRdec/src/psdec.h + libSBRdec/src/psdec_drm.h + libSBRdec/src/pvc_dec.h + libSBRdec/src/sbr_deb.h + libSBRdec/src/sbr_dec.h + libSBRdec/src/sbr_ram.h + libSBRdec/src/sbr_rom.h + libSBRdec/src/sbrdec_drc.h + libSBRdec/src/sbrdec_freq_sca.h + libSBRdec/src/transcendent.h) + +set(SBRENC_SRC + libSBRenc/src/bit_sbr.cpp + libSBRenc/src/code_env.cpp + libSBRenc/src/env_bit.cpp + libSBRenc/src/env_est.cpp + libSBRenc/src/fram_gen.cpp + libSBRenc/src/invf_est.cpp + libSBRenc/src/mh_det.cpp + libSBRenc/src/nf_est.cpp + libSBRenc/src/ps_bitenc.cpp + libSBRenc/src/ps_encode.cpp + libSBRenc/src/ps_main.cpp + libSBRenc/src/resampler.cpp + libSBRenc/src/sbr_encoder.cpp + libSBRenc/src/sbr_misc.cpp + libSBRenc/src/sbrenc_freq_sca.cpp + libSBRenc/src/sbrenc_ram.cpp + libSBRenc/src/sbrenc_rom.cpp + libSBRenc/src/ton_corr.cpp + libSBRenc/src/tran_det.cpp + libSBRenc/src/bit_sbr.h + libSBRenc/src/cmondata.h + libSBRenc/src/code_env.h + libSBRenc/src/env_bit.h + libSBRenc/src/env_est.h + libSBRenc/src/fram_gen.h + libSBRenc/src/invf_est.h + libSBRenc/src/mh_det.h + libSBRenc/src/nf_est.h + libSBRenc/src/ps_bitenc.h + libSBRenc/src/ps_const.h + libSBRenc/src/ps_encode.h + libSBRenc/src/ps_main.h + libSBRenc/src/resampler.h + libSBRenc/src/sbr.h + libSBRenc/src/sbr_def.h + libSBRenc/src/sbr_misc.h + libSBRenc/src/sbrenc_freq_sca.h + libSBRenc/src/sbrenc_ram.h + libSBRenc/src/sbrenc_rom.h + libSBRenc/src/ton_corr.h + libSBRenc/src/tran_det.h) + +set(SYS_SRC + libSYS/src/genericStds.cpp + libSYS/src/syslib_channelMapDescr.cpp) + +set(fdk_aacinclude_HEADERS + libSYS/include/machine_type.h + libSYS/include/genericStds.h + libSYS/include/FDK_audio.h + libSYS/include/syslib_channelMapDescr.h + libAACenc/include/aacenc_lib.h + libAACdec/include/aacdecoder_lib.h) + +set(libfdk_aac_SOURCES + ${AACDEC_SRC} ${AACENC_SRC} + ${ARITHCODING_SRC} + ${DRCDEC_SRC} + ${MPEGTPDEC_SRC} ${MPEGTPENC_SRC} + ${SACDEC_SRC} ${SACENC_SRC} + ${SBRDEC_SRC} ${SBRENC_SRC} + ${PCMUTILS_SRC} ${FDK_SRC} ${SYS_SRC}) + +if(WIN32 AND BUILD_SHARED_LIBS) + set(libfdk_aac_SOURCES ${libfdk_aac_SOURCES} fdk-aac.def) +endif() + +## Create Library target. Actually fdk-aac is enough, but we also create +## FDK-AAC::fdk-aac for consistence with config-file package. + +add_library(fdk-aac ${libfdk_aac_SOURCES}) +add_library(FDK-AAC::fdk-aac ALIAS fdk-aac) + +## Library target configuration + +### Library target includes +target_include_directories(fdk-aac + PUBLIC + $ + $ + $ + $ + PRIVATE + libArithCoding/include + libDRCdec/include + libSACdec/include + libSACenc/include + libSBRdec/include + libSBRenc/include + libMpegTPDec/include + libMpegTPEnc/include + libFDK/include + libPCMutils/include) + +### Link math library if required +target_link_libraries(fdk-aac PRIVATE $<$:m>) + +### Set public headers and shared library version. Version info is critical for Unix-like OSes. +set_target_properties(fdk-aac PROPERTIES + PUBLIC_HEADER "${fdk_aacinclude_HEADERS}" + VERSION 2.0.3 + SOVERSION 2 + MACHO_COMPATIBILITY_VERSION 3.0.0 + MACHO_CURRENT_VERSION 3.3.0 + LINKER_LANGUAGE C) + +### Some compiler options from Makefile.am +if(MSVC) + target_compile_options(fdk-aac PRIVATE /EHsc) +else() + target_compile_options(fdk-aac PRIVATE -fno-exceptions -fno-rtti) +endif() + +### Set proper name for MinGW or Cygwin DLL + +if((MINGW OR CYGWIN) AND BUILD_SHARED_LIBS) + set_property(TARGET fdk-aac PROPERTY RUNTIME_OUTPUT_NAME fdk-aac-2) +endif() + +## Library installation + +### Note we export `fdk-aac-targets` to use with config-file package. +install(TARGETS fdk-aac EXPORT fdk-aac-targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT BIN + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT DEV + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT DEV + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/fdk-aac COMPONENT DEV) + +### Configure and install pkg-config module. +if(FDK_AAC_INSTALL_PKGCONFIG_MODULE) + set(prefix ${CMAKE_INSTALL_PREFIX}) + set(exec_prefix "\$\{prefix\}") + set(libdir "\$\{exec_prefix\}/${CMAKE_INSTALL_LIBDIR}") + set(includedir "\$\{prefix\}/${CMAKE_INSTALL_INCLUDEDIR}") + set(PACKAGE_VERSION ${PROJECT_VERSION}) + if(HAVE_LIBM) + if(BUILD_SHARED_LIBS) + set(LIBS_PRIVATE "-lm") + else() + set(LIBS_PUBLIC "-lm") + endif() + endif() + configure_file(fdk-aac.pc.in fdk-aac.pc @ONLY) + install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/fdk-aac.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +endif() + +### Configure and install config-file package. Something like pkg-config module, but for Windows. +if(FDK_AAC_INSTALL_CMAKE_CONFIG_MODULE) + + set(CMAKE_INSTALL_PACKAGEDIR ${CMAKE_INSTALL_LIBDIR}/cmake/fdk-aac) + + configure_package_config_file(fdk-aac-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/fdk-aac-config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}) + + if(CMAKE_VERSION VERSION_LESS 3.11) + write_basic_package_version_file(fdk-aac-config-version.cmake COMPATIBILITY SameMajorVersion) + else() + write_basic_package_version_file(fdk-aac-config-version.cmake COMPATIBILITY SameMinorVersion) + endif() + + install(EXPORT fdk-aac-targets + NAMESPACE FDK-AAC:: + DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}) + install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/fdk-aac-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/fdk-aac-config-version.cmake + DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}) + +endif() + +# Programs + +if(BUILD_PROGRAMS) + + ## Program sources + + set(aac_enc_SOURCES + aac-enc.c + wavreader.c + wavreader.h) + + ## Program target + add_executable(aac-enc ${aac_enc_SOURCES}) + + ## Program target configuration + target_link_libraries(aac-enc PRIVATE fdk-aac) + target_compile_definitions(aac-enc PRIVATE $<$:_CRT_SECURE_NO_WARNINGS>) + if(WIN32) + target_sources(aac-enc PRIVATE win32/getopt.h) + target_include_directories(aac-enc PRIVATE win32) + endif() + + ## Program target installation + install(TARGETS aac-enc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + + ## Tool for testing the library + set(test_encode_decode_SOURCES + test-encode-decode.c + wavreader.c + wavreader.h + sha1.c + sha1.h) + + add_executable(test-encode-decode ${test_encode_decode_SOURCES}) + target_link_libraries(test-encode-decode PRIVATE fdk-aac) +endif() diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/ChangeLog b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/ChangeLog new file mode 100644 index 0000000000000..3c542e9cc1c9d --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/ChangeLog @@ -0,0 +1,62 @@ +2.0.3 + - Minor upstream updates + - Fixed one case of a failed assert in SBR encoding + - Added build support for s390x + +2.0.2 + - Minor upstream updates + - Lots of upstream and local fuzzing fixes + - Added CMake project files + - Removed the MSVC specific makefile + +2.0.1 + - Minor release with a number of crash/fuzz fixes, primarily for the decoder + +2.0.0 + - Major update in the upstream source base, with support for new + profiles and features, and numerous crash/fuzz fixes. The new + upstream version is referred to as FDKv2, thus skipping the + major version 1 and syncing the fdk-aac major version number to 2. + +0.1.6 + - Lots of minor assorted crash/fuzz fixes, mostly for the decoder but + also some for the encoder + +0.1.5 + - Updated upstream sources + - Fixed building with GCC 3.3 and 3.4 + - Fixed building with GCC 6 + - AArch64 optimizations + - Makefiles for building with MSVC + - Support building the code in C++11 mode + +0.1.4 + - Updated upstream sources, with minor changes to the decoder API + breaking the ABI. (Calling code using AUDIO_CHANNEL_TYPE may need to + be updated. A new option AAC_PCM_LIMITER_ENABLE has been added, enabled + by default, which incurs extra decoding delay.) + - PowerPC optimizations, fixes for building on AIX + - Support for reading streamed wav files in the encoder example + - Fix VBR encoding of sample rates over 64 kHz + +0.1.3 + - Updated upstream sources, with a number of crash fixes and new features + (including support for encoding 7.1) + +0.1.2 + - Fix a few more crashes + - Include dependency libs (such as -lm) in the pkg-config file + +0.1.1 + - Updated to a new upstream version from Android 4.2, fixing a lot of crashes + - Cleanup of autotools usage + - Make sure the shared library links to libm if necessary + - Performance improvements on x86 + - Added support for WG4/DVD audio channel mappings + - Minimized the differences to upstream + - Added an example encoder tool + +0.1.0 + - Initial release of fdk-aac + - autotools based build system + - Enable setting VBR bitrate modes diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/METADATA b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/METADATA new file mode 100644 index 0000000000000..4dab5e40e7c0c --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/METADATA @@ -0,0 +1,7 @@ +# *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE +# CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE +# DEPENDING ON IT IN YOUR PROJECT. *** +third_party { + license_note: "Software License for The Fraunhofer FDK AAC Codec Library for Android" + license_type: BY_EXCEPTION_ONLY +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/MODULE_LICENSE_FRAUNHOFER b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/MODULE_LICENSE_FRAUNHOFER new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/Makefile.am b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/Makefile.am new file mode 100644 index 0000000000000..06b9b6015c4cb --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/Makefile.am @@ -0,0 +1,305 @@ +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = subdir-objects + +AM_CPPFLAGS = \ + -I$(top_srcdir)/libAACdec/include \ + -I$(top_srcdir)/libAACenc/include \ + -I$(top_srcdir)/libArithCoding/include \ + -I$(top_srcdir)/libDRCdec/include \ + -I$(top_srcdir)/libSACdec/include \ + -I$(top_srcdir)/libSACenc/include \ + -I$(top_srcdir)/libSBRdec/include \ + -I$(top_srcdir)/libSBRenc/include \ + -I$(top_srcdir)/libMpegTPDec/include \ + -I$(top_srcdir)/libMpegTPEnc/include \ + -I$(top_srcdir)/libSYS/include \ + -I$(top_srcdir)/libFDK/include \ + -I$(top_srcdir)/libPCMutils/include + +AM_CXXFLAGS = -fno-exceptions -fno-rtti +libfdk_aac_la_LINK = $(LINK) $(libfdk_aac_la_LDFLAGS) +# Mention a dummy pure C file to trigger generation of the $(LINK) variable +nodist_EXTRA_libfdk_aac_la_SOURCES = dummy.c + +fdk_aacincludedir = $(includedir)/fdk-aac +fdk_aacinclude_HEADERS = \ + $(top_srcdir)/libSYS/include/machine_type.h \ + $(top_srcdir)/libSYS/include/genericStds.h \ + $(top_srcdir)/libSYS/include/FDK_audio.h \ + $(top_srcdir)/libSYS/include/syslib_channelMapDescr.h \ + $(top_srcdir)/libAACenc/include/aacenc_lib.h \ + $(top_srcdir)/libAACdec/include/aacdecoder_lib.h + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = fdk-aac.pc + +lib_LTLIBRARIES = libfdk-aac.la + +libfdk_aac_la_LDFLAGS = -version-info @FDK_AAC_VERSION@ -no-undefined \ + -export-symbols $(top_srcdir)/fdk-aac.sym + +if EXAMPLE +bin_PROGRAMS = aac-enc$(EXEEXT) +noinst_PROGRAMS = test-encode-decode$(EXEEXT) + +aac_enc_LDADD = libfdk-aac.la +aac_enc_SOURCES = aac-enc.c wavreader.c + +test_encode_decode_LDADD = libfdk-aac.la +test_encode_decode_SOURCES = test-encode-decode.c wavreader.c sha1.c + +noinst_HEADERS = wavreader.h +endif + +AACDEC_SRC = \ + libAACdec/src/FDK_delay.cpp \ + libAACdec/src/aac_ram.cpp \ + libAACdec/src/aac_rom.cpp \ + libAACdec/src/aacdec_drc.cpp \ + libAACdec/src/aacdec_hcr.cpp \ + libAACdec/src/aacdec_hcr_bit.cpp \ + libAACdec/src/aacdec_hcrs.cpp \ + libAACdec/src/aacdec_pns.cpp \ + libAACdec/src/aacdec_tns.cpp \ + libAACdec/src/aacdecoder.cpp \ + libAACdec/src/aacdecoder_lib.cpp \ + libAACdec/src/block.cpp \ + libAACdec/src/channel.cpp \ + libAACdec/src/channelinfo.cpp \ + libAACdec/src/conceal.cpp \ + libAACdec/src/ldfiltbank.cpp \ + libAACdec/src/pulsedata.cpp \ + libAACdec/src/rvlc.cpp \ + libAACdec/src/rvlcbit.cpp \ + libAACdec/src/rvlcconceal.cpp \ + libAACdec/src/stereo.cpp \ + libAACdec/src/usacdec_ace_d4t64.cpp \ + libAACdec/src/usacdec_ace_ltp.cpp \ + libAACdec/src/usacdec_acelp.cpp \ + libAACdec/src/usacdec_fac.cpp \ + libAACdec/src/usacdec_lpc.cpp \ + libAACdec/src/usacdec_lpd.cpp \ + libAACdec/src/usacdec_rom.cpp + +AACENC_SRC = \ + libAACenc/src/aacEnc_ram.cpp \ + libAACenc/src/aacEnc_rom.cpp \ + libAACenc/src/aacenc.cpp \ + libAACenc/src/aacenc_lib.cpp \ + libAACenc/src/aacenc_pns.cpp \ + libAACenc/src/aacenc_tns.cpp \ + libAACenc/src/adj_thr.cpp \ + libAACenc/src/band_nrg.cpp \ + libAACenc/src/bandwidth.cpp \ + libAACenc/src/bit_cnt.cpp \ + libAACenc/src/bitenc.cpp \ + libAACenc/src/block_switch.cpp \ + libAACenc/src/channel_map.cpp \ + libAACenc/src/chaosmeasure.cpp \ + libAACenc/src/dyn_bits.cpp \ + libAACenc/src/grp_data.cpp \ + libAACenc/src/intensity.cpp \ + libAACenc/src/line_pe.cpp \ + libAACenc/src/metadata_compressor.cpp \ + libAACenc/src/metadata_main.cpp \ + libAACenc/src/mps_main.cpp \ + libAACenc/src/ms_stereo.cpp \ + libAACenc/src/noisedet.cpp \ + libAACenc/src/pnsparam.cpp \ + libAACenc/src/pre_echo_control.cpp \ + libAACenc/src/psy_configuration.cpp \ + libAACenc/src/psy_main.cpp \ + libAACenc/src/qc_main.cpp \ + libAACenc/src/quantize.cpp \ + libAACenc/src/sf_estim.cpp \ + libAACenc/src/spreading.cpp \ + libAACenc/src/tonality.cpp \ + libAACenc/src/transform.cpp + +ARITHCODING_SRC = \ + libArithCoding/src/ac_arith_coder.cpp + +DRCDEC_SRC = \ + libDRCdec/src/FDK_drcDecLib.cpp \ + libDRCdec/src/drcDec_gainDecoder.cpp \ + libDRCdec/src/drcDec_reader.cpp \ + libDRCdec/src/drcDec_rom.cpp \ + libDRCdec/src/drcDec_selectionProcess.cpp \ + libDRCdec/src/drcDec_tools.cpp \ + libDRCdec/src/drcGainDec_init.cpp \ + libDRCdec/src/drcGainDec_preprocess.cpp \ + libDRCdec/src/drcGainDec_process.cpp + +FDK_SRC = \ + libFDK/src/FDK_bitbuffer.cpp \ + libFDK/src/FDK_core.cpp \ + libFDK/src/FDK_crc.cpp \ + libFDK/src/FDK_decorrelate.cpp \ + libFDK/src/FDK_hybrid.cpp \ + libFDK/src/FDK_lpc.cpp \ + libFDK/src/FDK_matrixCalloc.cpp \ + libFDK/src/FDK_qmf_domain.cpp \ + libFDK/src/FDK_tools_rom.cpp \ + libFDK/src/FDK_trigFcts.cpp \ + libFDK/src/autocorr2nd.cpp \ + libFDK/src/dct.cpp \ + libFDK/src/fft.cpp \ + libFDK/src/fft_rad2.cpp \ + libFDK/src/fixpoint_math.cpp \ + libFDK/src/huff_nodes.cpp \ + libFDK/src/mdct.cpp \ + libFDK/src/nlc_dec.cpp \ + libFDK/src/qmf.cpp \ + libFDK/src/scale.cpp + +MPEGTPDEC_SRC = \ + libMpegTPDec/src/tpdec_adif.cpp \ + libMpegTPDec/src/tpdec_adts.cpp \ + libMpegTPDec/src/tpdec_asc.cpp \ + libMpegTPDec/src/tpdec_drm.cpp \ + libMpegTPDec/src/tpdec_latm.cpp \ + libMpegTPDec/src/tpdec_lib.cpp + +MPEGTPENC_SRC = \ + libMpegTPEnc/src/tpenc_adif.cpp \ + libMpegTPEnc/src/tpenc_adts.cpp \ + libMpegTPEnc/src/tpenc_asc.cpp \ + libMpegTPEnc/src/tpenc_latm.cpp \ + libMpegTPEnc/src/tpenc_lib.cpp + +PCMUTILS_SRC = \ + libPCMutils/src/limiter.cpp \ + libPCMutils/src/pcm_utils.cpp \ + libPCMutils/src/pcmdmx_lib.cpp + +SACDEC_SRC = \ + libSACdec/src/sac_bitdec.cpp \ + libSACdec/src/sac_calcM1andM2.cpp \ + libSACdec/src/sac_dec.cpp \ + libSACdec/src/sac_dec_conceal.cpp \ + libSACdec/src/sac_dec_lib.cpp \ + libSACdec/src/sac_process.cpp \ + libSACdec/src/sac_qmf.cpp \ + libSACdec/src/sac_reshapeBBEnv.cpp \ + libSACdec/src/sac_rom.cpp \ + libSACdec/src/sac_smoothing.cpp \ + libSACdec/src/sac_stp.cpp \ + libSACdec/src/sac_tsd.cpp + +SACENC_SRC = \ + libSACenc/src/sacenc_bitstream.cpp \ + libSACenc/src/sacenc_delay.cpp \ + libSACenc/src/sacenc_dmx_tdom_enh.cpp \ + libSACenc/src/sacenc_filter.cpp \ + libSACenc/src/sacenc_framewindowing.cpp \ + libSACenc/src/sacenc_huff_tab.cpp \ + libSACenc/src/sacenc_lib.cpp \ + libSACenc/src/sacenc_nlc_enc.cpp \ + libSACenc/src/sacenc_onsetdetect.cpp \ + libSACenc/src/sacenc_paramextract.cpp \ + libSACenc/src/sacenc_staticgain.cpp \ + libSACenc/src/sacenc_tree.cpp \ + libSACenc/src/sacenc_vectorfunctions.cpp + +SBRDEC_SRC = \ + libSBRdec/src/HFgen_preFlat.cpp \ + libSBRdec/src/env_calc.cpp \ + libSBRdec/src/env_dec.cpp \ + libSBRdec/src/env_extr.cpp \ + libSBRdec/src/hbe.cpp \ + libSBRdec/src/huff_dec.cpp \ + libSBRdec/src/lpp_tran.cpp \ + libSBRdec/src/psbitdec.cpp \ + libSBRdec/src/psdec.cpp \ + libSBRdec/src/psdec_drm.cpp \ + libSBRdec/src/psdecrom_drm.cpp \ + libSBRdec/src/pvc_dec.cpp \ + libSBRdec/src/sbr_deb.cpp \ + libSBRdec/src/sbr_dec.cpp \ + libSBRdec/src/sbr_ram.cpp \ + libSBRdec/src/sbr_rom.cpp \ + libSBRdec/src/sbrdec_drc.cpp \ + libSBRdec/src/sbrdec_freq_sca.cpp \ + libSBRdec/src/sbrdecoder.cpp + +SBRENC_SRC = \ + libSBRenc/src/bit_sbr.cpp \ + libSBRenc/src/code_env.cpp \ + libSBRenc/src/env_bit.cpp \ + libSBRenc/src/env_est.cpp \ + libSBRenc/src/fram_gen.cpp \ + libSBRenc/src/invf_est.cpp \ + libSBRenc/src/mh_det.cpp \ + libSBRenc/src/nf_est.cpp \ + libSBRenc/src/ps_bitenc.cpp \ + libSBRenc/src/ps_encode.cpp \ + libSBRenc/src/ps_main.cpp \ + libSBRenc/src/resampler.cpp \ + libSBRenc/src/sbr_encoder.cpp \ + libSBRenc/src/sbr_misc.cpp \ + libSBRenc/src/sbrenc_freq_sca.cpp \ + libSBRenc/src/sbrenc_ram.cpp \ + libSBRenc/src/sbrenc_rom.cpp \ + libSBRenc/src/ton_corr.cpp \ + libSBRenc/src/tran_det.cpp + +SYS_SRC = \ + libSYS/src/genericStds.cpp \ + libSYS/src/syslib_channelMapDescr.cpp + +libfdk_aac_la_SOURCES = \ + $(AACDEC_SRC) $(AACENC_SRC) \ + $(ARITHCODING_SRC) \ + $(DRCDEC_SRC) \ + $(MPEGTPDEC_SRC) $(MPEGTPENC_SRC) \ + $(SACDEC_SRC) $(SACENC_SRC) \ + $(SBRDEC_SRC) $(SBRENC_SRC) \ + $(PCMUTILS_SRC) $(FDK_SRC) $(SYS_SRC) + +EXTRA_DIST = \ + $(top_srcdir)/CMakeLists.txt \ + $(top_srcdir)/.clang-format \ + $(top_srcdir)/autogen.sh \ + $(top_srcdir)/MODULE_LICENSE_FRAUNHOFER \ + $(top_srcdir)/NOTICE \ + $(top_srcdir)/OWNERS \ + $(top_srcdir)/Android.bp \ + $(top_srcdir)/fdk-aac.def \ + $(top_srcdir)/fdk-aac.sym \ + $(top_srcdir)/fdk-aac-config.cmake.in \ + $(top_srcdir)/documentation/*.pdf \ + $(top_srcdir)/fuzzer/* \ + $(top_srcdir)/libAACdec/src/*.h \ + $(top_srcdir)/libAACdec/src/arm/*.cpp \ + $(top_srcdir)/libAACenc/src/*.h \ + $(top_srcdir)/libArithCoding/include/*.h \ + $(top_srcdir)/libDRCdec/include/*.h \ + $(top_srcdir)/libDRCdec/src/*.h \ + $(top_srcdir)/libSACdec/include/*.h \ + $(top_srcdir)/libSACdec/src/*.h \ + $(top_srcdir)/libSACenc/include/*.h \ + $(top_srcdir)/libSACenc/src/*.h \ + $(top_srcdir)/libSBRenc/src/*.h \ + $(top_srcdir)/libSBRenc/include/*.h \ + $(top_srcdir)/libSBRdec/src/*.h \ + $(top_srcdir)/libSBRdec/include/*.h \ + $(top_srcdir)/libSYS/include/*.h \ + $(top_srcdir)/libPCMutils/include/*.h \ + $(top_srcdir)/libPCMutils/src/*.h \ + $(top_srcdir)/libMpegTPEnc/include/*.h \ + $(top_srcdir)/libMpegTPEnc/src/*.h \ + $(top_srcdir)/libMpegTPDec/include/*.h \ + $(top_srcdir)/libMpegTPDec/src/*.h \ + $(top_srcdir)/libFDK/include/*.h \ + $(top_srcdir)/libFDK/include/arm/*.h \ + $(top_srcdir)/libFDK/include/mips/*.h \ + $(top_srcdir)/libFDK/include/ppc/*.h \ + $(top_srcdir)/libFDK/include/x86/*.h \ + $(top_srcdir)/libFDK/src/arm/*.cpp \ + $(top_srcdir)/libFDK/src/mips/*.cpp \ + $(top_srcdir)/METADATA \ + $(top_srcdir)/PREUPLOAD.cfg \ + $(top_srcdir)/sha1.h \ + $(top_srcdir)/test/* \ + $(top_srcdir)/win32/*.h + diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/NOTICE b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/NOTICE new file mode 100644 index 0000000000000..05b32bdeaf0f0 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/NOTICE @@ -0,0 +1,92 @@ +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de + diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/OWNERS b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/OWNERS new file mode 100644 index 0000000000000..ffd753efe6681 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/OWNERS @@ -0,0 +1,2 @@ +jmtrivi@google.com +gkasten@android.com diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/PREUPLOAD.cfg b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/PREUPLOAD.cfg new file mode 100644 index 0000000000000..ecf8b8ef314dc --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/PREUPLOAD.cfg @@ -0,0 +1,2 @@ +[Hook Scripts] +mainline_hook = ${REPO_ROOT}/frameworks/av/tools/mainline_hook_project.sh diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/aac-enc.c b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/aac-enc.c new file mode 100644 index 0000000000000..7f443f20014c9 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/aac-enc.c @@ -0,0 +1,237 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 2011 Martin Storsjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#include +#include + +#if defined(_MSC_VER) +#include +#else +#include +#endif + +#include +#include "libAACenc/include/aacenc_lib.h" +#include "wavreader.h" + +void usage(const char* name) { + fprintf(stderr, "%s [-r bitrate] [-t aot] [-a afterburner] [-s sbr] [-v vbr] in.wav out.aac\n", name); + fprintf(stderr, "Supported AOTs:\n"); + fprintf(stderr, "\t2\tAAC-LC\n"); + fprintf(stderr, "\t5\tHE-AAC\n"); + fprintf(stderr, "\t29\tHE-AAC v2\n"); + fprintf(stderr, "\t23\tAAC-LD\n"); + fprintf(stderr, "\t39\tAAC-ELD\n"); +} + +int main(int argc, char *argv[]) { + int bitrate = 64000; + int ch; + const char *infile, *outfile; + FILE *out; + void *wav; + int format, sample_rate, channels, bits_per_sample; + int input_size; + uint8_t* input_buf; + int16_t* convert_buf; + int aot = 2; + int afterburner = 1; + int eld_sbr = 0; + int vbr = 0; + HANDLE_AACENCODER handle; + CHANNEL_MODE mode; + AACENC_InfoStruct info = { 0 }; + while ((ch = getopt(argc, argv, "r:t:a:s:v:")) != -1) { + switch (ch) { + case 'r': + bitrate = atoi(optarg); + break; + case 't': + aot = atoi(optarg); + break; + case 'a': + afterburner = atoi(optarg); + break; + case 's': + eld_sbr = atoi(optarg); + break; + case 'v': + vbr = atoi(optarg); + break; + case '?': + default: + usage(argv[0]); + return 1; + } + } + if (argc - optind < 2) { + usage(argv[0]); + return 1; + } + infile = argv[optind]; + outfile = argv[optind + 1]; + + wav = wav_read_open(infile); + if (!wav) { + fprintf(stderr, "Unable to open wav file %s\n", infile); + return 1; + } + if (!wav_get_header(wav, &format, &channels, &sample_rate, &bits_per_sample, NULL)) { + fprintf(stderr, "Bad wav file %s\n", infile); + return 1; + } + if (format != 1) { + fprintf(stderr, "Unsupported WAV format %d\n", format); + return 1; + } + if (bits_per_sample != 16) { + fprintf(stderr, "Unsupported WAV sample depth %d\n", bits_per_sample); + return 1; + } + switch (channels) { + case 1: mode = MODE_1; break; + case 2: mode = MODE_2; break; + case 3: mode = MODE_1_2; break; + case 4: mode = MODE_1_2_1; break; + case 5: mode = MODE_1_2_2; break; + case 6: mode = MODE_1_2_2_1; break; + default: + fprintf(stderr, "Unsupported WAV channels %d\n", channels); + return 1; + } + if (aacEncOpen(&handle, 0, channels) != AACENC_OK) { + fprintf(stderr, "Unable to open encoder\n"); + return 1; + } + if (aacEncoder_SetParam(handle, AACENC_AOT, aot) != AACENC_OK) { + fprintf(stderr, "Unable to set the AOT\n"); + return 1; + } + if (aot == 39 && eld_sbr) { + if (aacEncoder_SetParam(handle, AACENC_SBR_MODE, 1) != AACENC_OK) { + fprintf(stderr, "Unable to set SBR mode for ELD\n"); + return 1; + } + } + if (aacEncoder_SetParam(handle, AACENC_SAMPLERATE, sample_rate) != AACENC_OK) { + fprintf(stderr, "Unable to set the sample rate\n"); + return 1; + } + if (aacEncoder_SetParam(handle, AACENC_CHANNELMODE, mode) != AACENC_OK) { + fprintf(stderr, "Unable to set the channel mode\n"); + return 1; + } + if (aacEncoder_SetParam(handle, AACENC_CHANNELORDER, 1) != AACENC_OK) { + fprintf(stderr, "Unable to set the wav channel order\n"); + return 1; + } + if (vbr) { + if (aacEncoder_SetParam(handle, AACENC_BITRATEMODE, vbr) != AACENC_OK) { + fprintf(stderr, "Unable to set the VBR bitrate mode\n"); + return 1; + } + } else { + if (aacEncoder_SetParam(handle, AACENC_BITRATE, bitrate) != AACENC_OK) { + fprintf(stderr, "Unable to set the bitrate\n"); + return 1; + } + } + if (aacEncoder_SetParam(handle, AACENC_TRANSMUX, TT_MP4_ADTS) != AACENC_OK) { + fprintf(stderr, "Unable to set the ADTS transmux\n"); + return 1; + } + if (aacEncoder_SetParam(handle, AACENC_AFTERBURNER, afterburner) != AACENC_OK) { + fprintf(stderr, "Unable to set the afterburner mode\n"); + return 1; + } + if (aacEncEncode(handle, NULL, NULL, NULL, NULL) != AACENC_OK) { + fprintf(stderr, "Unable to initialize the encoder\n"); + return 1; + } + if (aacEncInfo(handle, &info) != AACENC_OK) { + fprintf(stderr, "Unable to get the encoder info\n"); + return 1; + } + + out = fopen(outfile, "wb"); + if (!out) { + perror(outfile); + return 1; + } + + input_size = channels*2*info.frameLength; + input_buf = (uint8_t*) malloc(input_size); + convert_buf = (int16_t*) malloc(input_size); + + while (1) { + AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 }; + AACENC_InArgs in_args = { 0 }; + AACENC_OutArgs out_args = { 0 }; + int in_identifier = IN_AUDIO_DATA; + int in_size, in_elem_size; + int out_identifier = OUT_BITSTREAM_DATA; + int out_size, out_elem_size; + int read, i; + void *in_ptr, *out_ptr; + uint8_t outbuf[20480]; + AACENC_ERROR err; + + read = wav_read_data(wav, input_buf, input_size); + for (i = 0; i < read/2; i++) { + const uint8_t* in = &input_buf[2*i]; + convert_buf[i] = in[0] | (in[1] << 8); + } + in_ptr = convert_buf; + in_size = read; + in_elem_size = 2; + + in_args.numInSamples = read <= 0 ? -1 : read/2; + in_buf.numBufs = 1; + in_buf.bufs = &in_ptr; + in_buf.bufferIdentifiers = &in_identifier; + in_buf.bufSizes = &in_size; + in_buf.bufElSizes = &in_elem_size; + + out_ptr = outbuf; + out_size = sizeof(outbuf); + out_elem_size = 1; + out_buf.numBufs = 1; + out_buf.bufs = &out_ptr; + out_buf.bufferIdentifiers = &out_identifier; + out_buf.bufSizes = &out_size; + out_buf.bufElSizes = &out_elem_size; + + if ((err = aacEncEncode(handle, &in_buf, &out_buf, &in_args, &out_args)) != AACENC_OK) { + if (err == AACENC_ENCODE_EOF) + break; + fprintf(stderr, "Encoding failed\n"); + return 1; + } + if (out_args.numOutBytes == 0) + continue; + fwrite(outbuf, 1, out_args.numOutBytes, out); + } + free(input_buf); + free(convert_buf); + fclose(out); + wav_read_close(wav); + aacEncClose(&handle); + + return 0; +} + diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/autogen.sh b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/autogen.sh new file mode 100755 index 0000000000000..210ccb81cb479 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/autogen.sh @@ -0,0 +1,2 @@ +#!/bin/sh +autoreconf -fiv diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/configure.ac b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/configure.ac new file mode 100644 index 0000000000000..3b0957d46367f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/configure.ac @@ -0,0 +1,38 @@ +dnl -*- Autoconf -*- +dnl Process this file with autoconf to produce a configure script. + +AC_INIT([fdk-aac], [2.0.3], [http://sourceforge.net/projects/opencore-amr/]) +AC_CONFIG_AUX_DIR(.) +AC_CONFIG_MACRO_DIR([m4]) +AM_INIT_AUTOMAKE([tar-ustar foreign]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +dnl Various options for configure +AC_ARG_ENABLE([example], + [AS_HELP_STRING([--enable-example], + [enable example encoding program (default is no)])], + [example=$enableval], [example=no]) + +dnl Automake conditionals to set +AM_CONDITIONAL(EXAMPLE, test x$example = xyes) + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CXX +LT_INIT + +AC_SEARCH_LIBS([sin], [m]) + +dnl soname version to use +dnl goes by ‘current[:revision[:age]]’ with the soname ending up as +dnl current.age.revision +FDK_AAC_VERSION=2:3:0 + +AS_IF([test x$enable_shared = xyes], [LIBS_PRIVATE=$LIBS], [LIBS_PUBLIC=$LIBS]) +AC_SUBST(FDK_AAC_VERSION) +AC_SUBST(LIBS_PUBLIC) +AC_SUBST(LIBS_PRIVATE) + +AC_CONFIG_FILES([Makefile + fdk-aac.pc]) +AC_OUTPUT diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/documentation/aacDecoder.pdf b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/documentation/aacDecoder.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3d4699e62c19282a31696c58f067bb129a502f23 GIT binary patch literal 492288 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®KZ5S-?HeSJK7q!d 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

7#-^FG)0vtBkVS4^PI?jvy^T3;qi|Foq>L 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. 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 U1BIKPpO=>pg^o@}RTkxc03R|@TmS$7 literal 0 HcmV?d00001 diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/documentation/aacEncoder.pdf b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/documentation/aacEncoder.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a47708a940e5b2218c0a2eebcb2ea2f4334943e3 GIT binary patch literal 443831 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�iPw9Ogpcc3q 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[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

cO@gwuL$F5_@TMvkI?`rE^wu7_;fh_nz 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%0D1h*&FDn} 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�{q@{hNc_FR-$Ty==*0C#ttn$%NbM1R!erk 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�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 +#include +#include +#include "aacdecoder_lib.h" + +constexpr uint8_t kNumberOfLayers = 1; +constexpr uint8_t kMaxChannelCount = 8; +constexpr uint32_t kMaxConfigurationSize = 1024; +constexpr uint32_t kMaxOutBufferSize = 2048 * kMaxChannelCount; + +// Value indicating the start of AAC Header Segment +constexpr const char *kAacSegStartSeq = "AAC_STRT"; +constexpr uint8_t kAacSegStartSeqLen = sizeof(kAacSegStartSeq); +// Value indicating the end of AAC Header Segment +constexpr const char *kAacSegEndSeq = "AAC_ENDS"; +constexpr uint8_t kAacSegEndSeqLen = sizeof(kAacSegEndSeq); + +// Number of bytes used to signal the length of the header +constexpr uint8_t kHeaderLengthBytes = 2; +// Minimum size of an AAC header is 2 +// Minimum data required is +// strlen(AAC_STRT) + strlen(AAC_ENDS) + kHeaderLengthBytes + 2; +constexpr UINT kMinDataSize = kAacSegStartSeqLen + kAacSegEndSeqLen + kHeaderLengthBytes + 2; + +UINT getHeaderSize(UCHAR *data, UINT size) { + if (size < kMinDataSize) { + return 0; + } + + int32_t result = memcmp(data, kAacSegStartSeq, kAacSegStartSeqLen); + if (result) { + return 0; + } + data += kAacSegStartSeqLen; + size -= kAacSegStartSeqLen; + + uint32_t headerLengthInBytes = (data[0] << 8 | data[1]) & 0xFFFF; + data += kHeaderLengthBytes; + size -= kHeaderLengthBytes; + + if (headerLengthInBytes + kAacSegEndSeqLen > size) { + return 0; + } + + data += headerLengthInBytes; + size -= headerLengthInBytes; + result = memcmp(data, kAacSegEndSeq, kAacSegEndSeqLen); + if (result) { + return 0; + } + + return std::min(headerLengthInBytes, kMaxConfigurationSize); +} + +class Codec { + public: + Codec() = default; + ~Codec() { deInitDecoder(); } + bool initDecoder(); + void decodeFrames(UCHAR *data, UINT size); + void deInitDecoder(); + + private: + HANDLE_AACDECODER mAacDecoderHandle = nullptr; + AAC_DECODER_ERROR mErrorCode = AAC_DEC_OK; +}; + +bool Codec::initDecoder() { + mAacDecoderHandle = aacDecoder_Open(TT_MP4_ADIF, kNumberOfLayers); + if (!mAacDecoderHandle) { + return false; + } + return true; +} + +void Codec::deInitDecoder() { + aacDecoder_Close(mAacDecoderHandle); + mAacDecoderHandle = nullptr; +} + +void Codec::decodeFrames(UCHAR *data, UINT size) { + UINT headerSize = getHeaderSize(data, size); + if (headerSize != 0) { + data += kAacSegStartSeqLen + kHeaderLengthBytes; + size -= kAacSegStartSeqLen + kHeaderLengthBytes; + aacDecoder_ConfigRaw(mAacDecoderHandle, &data, &headerSize); + data += headerSize + kAacSegEndSeqLen; + size -= headerSize + kAacSegEndSeqLen; + } + while (size > 0) { + UINT inputSize = size; + UINT valid = size; + mErrorCode = aacDecoder_Fill(mAacDecoderHandle, &data, &inputSize, &valid); + if (mErrorCode != AAC_DEC_OK) { + ++data; + --size; + } else { + INT_PCM outputBuf[kMaxOutBufferSize]; + do { + mErrorCode = + aacDecoder_DecodeFrame(mAacDecoderHandle, outputBuf, + kMaxOutBufferSize /*size in number of INT_PCM, not bytes*/, 0); + } while (mErrorCode == AAC_DEC_OK); + UINT offset = inputSize - valid; + data += offset; + size = valid; + } + } +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + Codec *codec = new Codec(); + if (!codec) { + return 0; + } + if (codec->initDecoder()) { + codec->decodeFrames((UCHAR *)(data), static_cast(size)); + } + delete codec; + return 0; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/fuzzer/aac_enc_fuzzer.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/fuzzer/aac_enc_fuzzer.cpp new file mode 100644 index 0000000000000..5a35d7049c03a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/fuzzer/aac_enc_fuzzer.cpp @@ -0,0 +1,479 @@ +/****************************************************************************** + * + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +#include +#include "aacenc_lib.h" +#include "src/aacenc.h" + +using namespace std; + +// IN_AUDIO_DATA, IN_ANCILLRY_DATA and IN_METADATA_SETUP +constexpr size_t kMaxBuffers = 3; + +constexpr size_t kMaxOutputBufferSize = 8192; + +constexpr uint32_t kMinBitRate = 8000; +constexpr uint32_t kMaxBitRate = 960000; + +constexpr int32_t kSampleRates[] = {8000, 11025, 12000, 16000, 22050, 24000, + 32000, 44100, 48000, 64000, 88200, 96000}; +constexpr size_t kSampleRatesSize = size(kSampleRates); + +constexpr CHANNEL_MODE kChannelModes[] = {MODE_1, + MODE_2, + MODE_1_2, + MODE_1_2_1, + MODE_1_2_2, + MODE_1_2_2_1, + MODE_1_2_2_2_1, + MODE_6_1, + MODE_7_1_BACK, + MODE_7_1_TOP_FRONT, + MODE_7_1_REAR_SURROUND, + MODE_7_1_FRONT_CENTER, + MODE_212}; +constexpr size_t kChannelModesSize = size(kChannelModes); + +constexpr TRANSPORT_TYPE kIdentifiers[] = { + TT_MP4_RAW, TT_MP4_ADIF, TT_MP4_ADTS, TT_MP4_LATM_MCP1, TT_MP4_LATM_MCP0, TT_MP4_LOAS, TT_DRM}; +constexpr size_t kIdentifiersSize = size(kIdentifiers); + +constexpr AUDIO_OBJECT_TYPE kAudioObjectTypes[] = {AOT_NONE, AOT_NULL_OBJECT, + AOT_AAC_MAIN, AOT_AAC_LC, + AOT_AAC_SSR, AOT_AAC_LTP, + AOT_SBR, AOT_AAC_SCAL, + AOT_TWIN_VQ, AOT_CELP, + AOT_HVXC, AOT_RSVD_10, + AOT_RSVD_11, AOT_TTSI, + AOT_MAIN_SYNTH, AOT_WAV_TAB_SYNTH, + AOT_GEN_MIDI, AOT_ALG_SYNTH_AUD_FX, + AOT_ER_AAC_LC, AOT_RSVD_18, + AOT_ER_AAC_LTP, AOT_ER_AAC_SCAL, + AOT_ER_TWIN_VQ, AOT_ER_BSAC, + AOT_ER_AAC_LD, AOT_ER_CELP, + AOT_ER_HVXC, AOT_ER_HILN, + AOT_ER_PARA, AOT_RSVD_28, + AOT_PS, AOT_MPEGS, + AOT_ESCAPE, AOT_MP3ONMP4_L1, + AOT_MP3ONMP4_L2, AOT_MP3ONMP4_L3, + AOT_RSVD_35, AOT_RSVD_36, + AOT_AAC_SLS, AOT_SLS, + AOT_ER_AAC_ELD, AOT_USAC, + AOT_SAOC, AOT_LD_MPEGS, + AOT_MP2_AAC_LC, AOT_MP2_SBR, + AOT_DRM_AAC, AOT_DRM_SBR, + AOT_DRM_MPEG_PS, AOT_DRM_SURROUND, + AOT_DRM_USAC}; + +constexpr size_t kAudioObjectTypesSize = size(kAudioObjectTypes); + +constexpr int32_t kSbrRatios[] = {-1, 0, 1, 2}; +constexpr size_t kSbrRatiosSize = size(kSbrRatios); + +constexpr int32_t kBitRateModes[] = { + AACENC_BR_MODE_INVALID, AACENC_BR_MODE_CBR, AACENC_BR_MODE_VBR_1, + AACENC_BR_MODE_VBR_2, AACENC_BR_MODE_VBR_3, AACENC_BR_MODE_VBR_4, + AACENC_BR_MODE_VBR_5, AACENC_BR_MODE_FF, AACENC_BR_MODE_SFR}; +constexpr size_t kBitRateModesSize = size(kBitRateModes); + +constexpr int32_t kGranuleLengths[] = {120, 128, 240, 256, 480, 512, 1024}; +constexpr size_t kGranuleLengthsSize = size(kGranuleLengths); + +constexpr int32_t kChannelOrder[] = {CH_ORDER_MPEG, CH_ORDER_WAV}; +constexpr size_t kChannelOrderSize = size(kChannelOrder); + +constexpr int32_t kSignalingModes[] = {-1, 0, 1, 2, 3}; +constexpr size_t kSignalingModesSize = size(kSignalingModes); + +constexpr int32_t kAudioMuxVer[] = {-1, 0, 1, 2}; +constexpr size_t kAudioMuxVerSize = size(kAudioMuxVer); + +constexpr int32_t kSbrModes[] = {-1, 0, 1, 2}; +constexpr size_t kSbrModesSize = size(kSbrModes); + +constexpr AACENC_METADATA_DRC_PROFILE kMetaDataDrcProfiles[] = { + AACENC_METADATA_DRC_NONE, AACENC_METADATA_DRC_FILMSTANDARD, + AACENC_METADATA_DRC_FILMLIGHT, AACENC_METADATA_DRC_MUSICSTANDARD, + AACENC_METADATA_DRC_MUSICLIGHT, AACENC_METADATA_DRC_SPEECH, + AACENC_METADATA_DRC_NOT_PRESENT}; +constexpr size_t kMetaDataDrcProfilesSize = size(kMetaDataDrcProfiles); + +enum { + IDX_SBR_MODE = 0, + IDX_AAC_AOT, + IDX_SAMPLE_RATE, + IDX_BIT_RATE_1, + IDX_BIT_RATE_2, + IDX_BIT_RATE_3, + IDX_CHANNEL, + IDX_IDENTIFIER, + IDX_SBR_RATIO, + IDX_METADATA_DRC_PROFILE, + IDX_METADATA_COMP_PROFILE, + IDX_METADATA_DRC_TARGET_REF_LEVEL, + IDX_METADATA_COMP_TARGET_REF_LEVEL, + IDX_METADATA_PROG_LEVEL_PRESENT, + IDX_METADATA_PROG_LEVEL, + IDX_METADATA_PCE_MIXDOWN_IDX_PRESENT, + IDX_METADATA_ETSI_DMXLVL_PRESENT, + IDX_METADATA_CENTER_MIX_LEVEL, + IDX_METADATA_SURROUND_MIX_LEVEL, + IDX_METADATA_DOLBY_SURROUND_MODE, + IDX_METADATA_DRC_PRESENTATION_MODE, + IDX_METADATA_EXT_ANC_DATA_ENABLE, + IDX_METADATA_EXT_DOWNMIX_LEVEL_ENABLE, + IDX_METADATA_EXT_DOWNMIX_LEVEL_A, + IDX_METADATA_EXT_DOWNMIX_LEVEL_B, + IDX_METADATA_DMX_GAIN_ENABLE, + IDX_METADATA_DMX_GAIN_5, + IDX_METADATA_DMX_GAIN_2, + IDX_METADATA_LFE_DMX_ENABLE, + IDX_METADATA_LFE_DMX_LEVEL, + IDX_IN_BUFFER_INDEX_1, + IDX_IN_BUFFER_INDEX_2, + IDX_IN_BUFFER_INDEX_3, + IDX_BIT_RATE_MODE, + IDX_GRANULE_LENGTH, + IDX_CHANNELORDER, + IDX_AFTERBURNER, + IDX_BANDWIDTH, + IDX_PEAK_BITRATE, + IDX_HEADER_PERIOD, + IDX_SIGNALING_MODE, + IDX_TPSUBFRAMES, + IDX_AUDIOMUXVER, + IDX_PROTECTION, + IDX_ANCILLARY_BITRATE, + IDX_METADATA_MODE, + IDX_LAST +}; + +template +auto generateNumberInRangeFromData(type1 data, type2 min, type3 max) -> decltype(max) { + return (data % (1 + max - min)) + min; +} + +class Codec { + public: + ~Codec() { deInitEncoder(); } + bool initEncoder(uint8_t **dataPtr, size_t *sizePtr); + void encodeFrames(const uint8_t *data, size_t size); + void deInitEncoder(); + + private: + template + void setAACParam(type1 data, const AACENC_PARAM aacParam, type2 min, type2 max, + const type3 *array = nullptr); + void setupMetaData(uint8_t *data); + + HANDLE_AACENCODER mEncoder = nullptr; + AACENC_MetaData mMetaData = {}; + uint32_t mInBufferIdx_1 = 0; + uint32_t mInBufferIdx_2 = 0; + uint32_t mInBufferIdx_3 = 0; +}; + +void Codec::setupMetaData(uint8_t *data) { + uint32_t drcProfileIndex = generateNumberInRangeFromData(data[IDX_METADATA_DRC_PROFILE], 0, + kMetaDataDrcProfilesSize - 1); + AACENC_METADATA_DRC_PROFILE drcProfile = kMetaDataDrcProfiles[drcProfileIndex]; + mMetaData.drc_profile = drcProfile; + + uint32_t compProfileIndex = generateNumberInRangeFromData(data[IDX_METADATA_COMP_PROFILE], 0, + kMetaDataDrcProfilesSize - 1); + AACENC_METADATA_DRC_PROFILE compProfile = kMetaDataDrcProfiles[compProfileIndex]; + mMetaData.comp_profile = compProfile; + + INT drcTargetRefLevel = + generateNumberInRangeFromData(data[IDX_METADATA_DRC_TARGET_REF_LEVEL], 0, UINT8_MAX); + mMetaData.drc_TargetRefLevel = drcTargetRefLevel; + + INT compTargetRefLevel = + generateNumberInRangeFromData(data[IDX_METADATA_COMP_TARGET_REF_LEVEL], 0, UINT8_MAX); + mMetaData.comp_TargetRefLevel = compTargetRefLevel; + + INT isProgRefLevelPresent = + generateNumberInRangeFromData(data[IDX_METADATA_PROG_LEVEL_PRESENT], 0, 1); + mMetaData.prog_ref_level_present = isProgRefLevelPresent; + + INT progRefLevel = generateNumberInRangeFromData(data[IDX_METADATA_PROG_LEVEL], 0, UINT8_MAX); + mMetaData.prog_ref_level = progRefLevel; + + UCHAR isPCEMixdownIdxPresent = + generateNumberInRangeFromData(data[IDX_METADATA_PCE_MIXDOWN_IDX_PRESENT], 0, 1); + mMetaData.PCE_mixdown_idx_present = isPCEMixdownIdxPresent; + + UCHAR isETSIDmxLvlPresent = + generateNumberInRangeFromData(data[IDX_METADATA_ETSI_DMXLVL_PRESENT], 0, 1); + mMetaData.ETSI_DmxLvl_present = isETSIDmxLvlPresent; + + SCHAR centerMixLevel = generateNumberInRangeFromData(data[IDX_METADATA_CENTER_MIX_LEVEL], 0, 7); + mMetaData.centerMixLevel = centerMixLevel; + + SCHAR surroundMixLevel = + generateNumberInRangeFromData(data[IDX_METADATA_SURROUND_MIX_LEVEL], 0, 7); + mMetaData.surroundMixLevel = surroundMixLevel; + + UCHAR dolbySurroundMode = + generateNumberInRangeFromData(data[IDX_METADATA_DOLBY_SURROUND_MODE], 0, 2); + mMetaData.dolbySurroundMode = dolbySurroundMode; + + UCHAR drcPresentationMode = + generateNumberInRangeFromData(data[IDX_METADATA_DRC_PRESENTATION_MODE], 0, 2); + mMetaData.drcPresentationMode = drcPresentationMode; + + UCHAR extAncDataEnable = + generateNumberInRangeFromData(data[IDX_METADATA_EXT_ANC_DATA_ENABLE], 0, 1); + mMetaData.ExtMetaData.extAncDataEnable = extAncDataEnable; + + UCHAR extDownmixLevelEnable = + generateNumberInRangeFromData(data[IDX_METADATA_EXT_DOWNMIX_LEVEL_ENABLE], 0, 1); + mMetaData.ExtMetaData.extDownmixLevelEnable = extDownmixLevelEnable; + + UCHAR extDownmixLevel_A = + generateNumberInRangeFromData(data[IDX_METADATA_EXT_DOWNMIX_LEVEL_A], 0, 7); + mMetaData.ExtMetaData.extDownmixLevel_A = extDownmixLevel_A; + + UCHAR extDownmixLevel_B = + generateNumberInRangeFromData(data[IDX_METADATA_EXT_DOWNMIX_LEVEL_B], 0, 7); + mMetaData.ExtMetaData.extDownmixLevel_B = extDownmixLevel_B; + + UCHAR dmxGainEnable = generateNumberInRangeFromData(data[IDX_METADATA_DMX_GAIN_ENABLE], 0, 1); + mMetaData.ExtMetaData.dmxGainEnable = dmxGainEnable; + + INT dmxGain5 = generateNumberInRangeFromData(data[IDX_METADATA_DMX_GAIN_5], 0, UINT8_MAX); + mMetaData.ExtMetaData.dmxGain5 = dmxGain5; + + INT dmxGain2 = generateNumberInRangeFromData(data[IDX_METADATA_DMX_GAIN_2], 0, UINT8_MAX); + mMetaData.ExtMetaData.dmxGain2 = dmxGain2; + + UCHAR lfeDmxEnable = generateNumberInRangeFromData(data[IDX_METADATA_LFE_DMX_ENABLE], 0, 1); + mMetaData.ExtMetaData.lfeDmxEnable = lfeDmxEnable; + + UCHAR lfeDmxLevel = generateNumberInRangeFromData(data[IDX_METADATA_LFE_DMX_LEVEL], 0, 15); + mMetaData.ExtMetaData.lfeDmxLevel = lfeDmxLevel; +} + +template +void Codec::setAACParam(type1 data, const AACENC_PARAM aacParam, type2 min, type2 max, + const type3 *array) { + auto value = 0; + if (array) { + uint32_t index = generateNumberInRangeFromData(data, min, max); + value = array[index]; + } else { + value = generateNumberInRangeFromData(data, min, max); + } + aacEncoder_SetParam(mEncoder, aacParam, value); + (void)aacEncoder_GetParam(mEncoder, aacParam); +} + +bool Codec::initEncoder(uint8_t **dataPtr, size_t *sizePtr) { + uint8_t *data = *dataPtr; + + if (AACENC_OK != aacEncOpen(&mEncoder, 0, 0)) { + return false; + } + + setAACParam(data[IDX_SBR_MODE], AACENC_SBR_MODE, 0, kSbrModesSize - 1, + kSbrModes); + + setAACParam(data[IDX_SBR_RATIO], AACENC_SBR_RATIO, 0, + kSbrRatiosSize - 1, kSbrRatios); + + setAACParam(data[IDX_AAC_AOT], AACENC_AOT, 0, + kAudioObjectTypesSize - 1, kAudioObjectTypes); + + setAACParam(data[IDX_SAMPLE_RATE], AACENC_SAMPLERATE, 0, + kSampleRatesSize - 1, kSampleRates); + + uint32_t tempValue = + (data[IDX_BIT_RATE_1] << 16) | (data[IDX_BIT_RATE_2] << 8) | data[IDX_BIT_RATE_3]; + setAACParam(tempValue, AACENC_BITRATE, kMinBitRate, kMaxBitRate); + + setAACParam(data[IDX_CHANNEL], AACENC_CHANNELMODE, 0, + kChannelModesSize - 1, kChannelModes); + + setAACParam(data[IDX_IDENTIFIER], AACENC_TRANSMUX, 0, + kIdentifiersSize - 1, kIdentifiers); + + setAACParam(data[IDX_BIT_RATE_MODE], AACENC_BITRATEMODE, 0, + kBitRateModesSize - 1, kBitRateModes); + + setAACParam(data[IDX_GRANULE_LENGTH], AACENC_GRANULE_LENGTH, 0, + kGranuleLengthsSize - 1, kGranuleLengths); + + setAACParam(data[IDX_CHANNELORDER], AACENC_CHANNELORDER, 0, + kChannelOrderSize - 1, kChannelOrder); + + setAACParam(data[IDX_AFTERBURNER], AACENC_AFTERBURNER, 0, 1); + + setAACParam(data[IDX_BANDWIDTH], AACENC_BANDWIDTH, 0, 1); + + setAACParam(data[IDX_PEAK_BITRATE], AACENC_PEAK_BITRATE, + kMinBitRate, kMinBitRate); + + setAACParam(data[IDX_HEADER_PERIOD], AACENC_HEADER_PERIOD, 0, + UINT8_MAX); + + setAACParam(data[IDX_SIGNALING_MODE], AACENC_SIGNALING_MODE, 0, + kSignalingModesSize - 1, kSignalingModes); + + setAACParam(data[IDX_TPSUBFRAMES], AACENC_TPSUBFRAMES, 0, + UINT8_MAX); + + setAACParam(data[IDX_AUDIOMUXVER], AACENC_AUDIOMUXVER, 0, + kAudioMuxVerSize - 1, kAudioMuxVer); + + setAACParam(data[IDX_PROTECTION], AACENC_PROTECTION, 0, 1); + + setAACParam(data[IDX_ANCILLARY_BITRATE], AACENC_ANCILLARY_BITRATE, + 0, kMaxBitRate); + + setAACParam(data[IDX_METADATA_MODE], AACENC_METADATA_MODE, 0, 3); + + AACENC_InfoStruct encInfo; + aacEncInfo(mEncoder, &encInfo); + + mInBufferIdx_1 = generateNumberInRangeFromData(data[IDX_IN_BUFFER_INDEX_1], 0, kMaxBuffers - 1); + mInBufferIdx_2 = generateNumberInRangeFromData(data[IDX_IN_BUFFER_INDEX_2], 0, kMaxBuffers - 1); + mInBufferIdx_3 = generateNumberInRangeFromData(data[IDX_IN_BUFFER_INDEX_3], 0, kMaxBuffers - 1); + + setupMetaData(data); + + // Not re-using the data which was used for configuration for encoding + *dataPtr += IDX_LAST; + *sizePtr -= IDX_LAST; + + return true; +} + +static void deleteBuffers(uint8_t **buffers, size_t size) { + for (size_t n = 0; n < size; ++n) { + delete[] buffers[n]; + } + delete[] buffers; +} + +void Codec::encodeFrames(const uint8_t *data, size_t size) { + uint8_t *audioData = (uint8_t *)data; + uint8_t *ancData = (uint8_t *)data; + size_t audioSize = size; + size_t ancSize = size; + + while ((audioSize > 0) && (ancSize > 0)) { + AACENC_InArgs inargs; + memset(&inargs, 0, sizeof(inargs)); + inargs.numInSamples = audioSize / sizeof(int16_t); + inargs.numAncBytes = ancSize; + + void *buffers[] = {(void *)audioData, (void *)ancData, &mMetaData}; + INT bufferIds[] = {IN_AUDIO_DATA, IN_ANCILLRY_DATA, IN_METADATA_SETUP}; + INT bufferSizes[] = {static_cast(audioSize), static_cast(ancSize), + static_cast(sizeof(mMetaData))}; + INT bufferElSizes[] = {sizeof(int16_t), sizeof(UCHAR), sizeof(AACENC_MetaData)}; + + void *inBuffer[kMaxBuffers] = {}; + INT inBufferIds[kMaxBuffers] = {}; + INT inBufferSize[kMaxBuffers] = {}; + INT inBufferElSize[kMaxBuffers] = {}; + for (int32_t buffer = 0; buffer < kMaxBuffers; ++buffer) { + uint32_t Idxs[] = {mInBufferIdx_1, mInBufferIdx_2, mInBufferIdx_3}; + inBuffer[buffer] = buffers[Idxs[buffer]]; + inBufferIds[buffer] = bufferIds[Idxs[buffer]]; + inBufferSize[buffer] = bufferSizes[Idxs[buffer]]; + inBufferElSize[buffer] = bufferElSizes[Idxs[buffer]]; + } + + AACENC_BufDesc inBufDesc; + inBufDesc.numBufs = kMaxBuffers; + inBufDesc.bufs = (void **)&inBuffer; + inBufDesc.bufferIdentifiers = inBufferIds; + inBufDesc.bufSizes = inBufferSize; + inBufDesc.bufElSizes = inBufferElSize; + + uint8_t **outPtrRef = new uint8_t *[kMaxBuffers]; + for (int32_t buffer = 0; buffer < kMaxBuffers; ++buffer) { + outPtrRef[buffer] = new uint8_t[kMaxOutputBufferSize]; + } + + void *outBuffer[kMaxBuffers]; + INT outBufferIds[kMaxBuffers]; + INT outBufferSize[kMaxBuffers]; + INT outBufferElSize[kMaxBuffers]; + + for (int32_t buffer = 0; buffer < kMaxBuffers; ++buffer) { + outBuffer[buffer] = outPtrRef[buffer]; + outBufferIds[buffer] = OUT_BITSTREAM_DATA; + outBufferSize[buffer] = (INT)kMaxOutputBufferSize; + outBufferElSize[buffer] = sizeof(UCHAR); + } + + AACENC_BufDesc outBufDesc; + outBufDesc.numBufs = kMaxBuffers; + outBufDesc.bufs = (void **)&outBuffer; + outBufDesc.bufferIdentifiers = outBufferIds; + outBufDesc.bufSizes = outBufferSize; + outBufDesc.bufElSizes = outBufferElSize; + + AACENC_OutArgs outargs = {}; + aacEncEncode(mEncoder, &inBufDesc, &outBufDesc, &inargs, &outargs); + + if (outargs.numOutBytes == 0) { + if (audioSize > 0) { + ++audioData; + --audioSize; + } + if (ancSize > 0) { + ++ancData; + --ancSize; + } + } else { + size_t audioConsumed = outargs.numInSamples * sizeof(int16_t); + audioData += audioConsumed; + audioSize -= audioConsumed; + + size_t ancConsumed = outargs.numAncBytes; + ancData += ancConsumed; + ancSize -= ancConsumed; + } + deleteBuffers(outPtrRef, kMaxBuffers); + + // break out of loop if only metadata was sent in all the input buffers + // as sending it multiple times in a loop is redundant. + if ((mInBufferIdx_1 == kMaxBuffers - 1) && (mInBufferIdx_2 == kMaxBuffers - 1) && + (mInBufferIdx_3 == kMaxBuffers - 1)) { + break; + } + } +} + +void Codec::deInitEncoder() { aacEncClose(&mEncoder); } + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size < IDX_LAST) { + return 0; + } + Codec encoder; + if (encoder.initEncoder(const_cast(&data), &size)) { + encoder.encodeFrames(data, size); + } + return 0; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/include/aacdecoder_lib.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/include/aacdecoder_lib.h new file mode 100644 index 0000000000000..02596b21a28de --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/include/aacdecoder_lib.h @@ -0,0 +1,1082 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: + +*******************************************************************************/ + +#ifndef AACDECODER_LIB_H +#define AACDECODER_LIB_H + +/** + * \file aacdecoder_lib.h + * \brief FDK AAC decoder library interface header file. + * + +\page INTRO Introduction + + +\section SCOPE Scope + +This document describes the high-level application interface and usage of the +ISO/MPEG-2/4 AAC Decoder library developed by the Fraunhofer Institute for +Integrated Circuits (IIS). Depending on the library configuration, decoding of +AAC-LC (Low-Complexity), HE-AAC (High-Efficiency AAC v1 and v2), AAC-LD +(Low-Delay) and AAC-ELD (Enhanced Low-Delay) is implemented. + +All references to SBR (Spectral Band Replication) are only applicable to HE-AAC +and AAC-ELD configurations of the FDK library. All references to PS (Parametric +Stereo) are only applicable to HE-AAC v2 decoder configuration of the library. + +\section DecoderBasics Decoder Basics + +This document can only give a rough overview about the ISO/MPEG-2, ISO/MPEG-4 +AAC audio and MPEG-D USAC coding standards. To understand all details referenced +in this document, you are encouraged to read the following documents. + +- ISO/IEC 13818-7 (MPEG-2 AAC) Standard, defines the syntax of MPEG-2 AAC audio +bitstreams. +- ISO/IEC 14496-3 (MPEG-4 AAC, subpart 1 and 4) Standard, defines the syntax of +MPEG-4 AAC audio bitstreams. +- ISO/IEC 23003-3 (MPEG-D USAC), defines MPEG-D USAC unified speech and audio +codec. +- Lutzky, Schuller, Gayer, Krämer, Wabnik, "A guideline to audio codec +delay", 116th AES Convention, May 8, 2004 + +In short, MPEG Advanced Audio Coding is based on a time-to-frequency mapping of +the signal. The signal is partitioned into overlapping time portions and +transformed into frequency domain. The spectral components are then quantized +and coded using a highly efficient coding scheme.\n Encoded MPEG-2 and MPEG-4 +AAC audio bitstreams are composed of frames. Contrary to MPEG-1/2 Layer-3 (mp3), +the length of individual frames is not restricted to a fixed number of bytes, +but can take any length between 1 and 768 bytes. + +In addition to the above mentioned frequency domain coding mode, MPEG-D USAC +also employs a time domain Algebraic Code-Excited Linear Prediction (ACELP) +speech coder core. This operating mode is selected by the encoder in order to +achieve the optimum audio quality for different content type. Several +enhancements allow achieving higher quality at lower bit rates compared to +MPEG-4 HE-AAC. + + +\page LIBUSE Library Usage + + +\section InterfaceDescritpion API Description + +All API header files are located in the folder /include of the release package. +The contents of each file is described in detail in this document. All header +files are provided for usage in specific C/C++ programs. The main AAC decoder +library API functions are located in aacdecoder_lib.h header file. + + +\section Calling_Sequence Calling Sequence + +The following sequence is necessary for proper decoding of ISO/MPEG-2/4 AAC, +HE-AAC v2, or MPEG-D USAC bitstreams. In the following description, input stream +read and output write function details are left out, since they may be +implemented in a variety of configurations depending on the user's specific +requirements. + + +-# Call aacDecoder_Open() to open and retrieve a handle to a new AAC decoder +instance. \code aacDecoderInfo = aacDecoder_Open(transportType, nrOfLayers); +\endcode +-# If out-of-band config data (Audio Specific Config (ASC) or Stream Mux Config +(SMC)) is available, call aacDecoder_ConfigRaw() to pass this data to the +decoder before beginning the decoding process. If this data is not available in +advance, the decoder will configure itself while decoding, during the +aacDecoder_DecodeFrame() function call. +-# Begin decoding loop. +\code +do { +\endcode +-# Read data from bitstream file or stream buffer in to the driver program +working memory (a client-supplied input buffer "inBuffer" in framework). This +buffer will be used to load AAC bitstream data to the decoder. Only when all +data in this buffer has been processed will the decoder signal an empty buffer. +-# Call aacDecoder_Fill() to fill the decoder's internal bitstream input buffer +with the client-supplied bitstream input buffer. Note, if the data loaded in to +the internal buffer is not sufficient to decode a frame, +aacDecoder_DecodeFrame() will return ::AAC_DEC_NOT_ENOUGH_BITS until a +sufficient amount of data is loaded in to the internal buffer. For streaming +formats (ADTS, LOAS), it is acceptable to load more than one frame to the +decoder. However, for packed based formats, only one frame may be loaded to the +decoder per aacDecoder_DecodeFrame() call. For least amount of communication +delay, fill and decode should be performed on a frame by frame basis. \code + ErrorStatus = aacDecoder_Fill(aacDecoderInfo, inBuffer, bytesRead, +bytesValid); \endcode +-# Call aacDecoder_DecodeFrame(). This function decodes one frame and writes +decoded PCM audio data to a client-supplied buffer. It is the client's +responsibility to allocate a buffer which is large enough to hold the decoded +output data. \code ErrorStatus = aacDecoder_DecodeFrame(aacDecoderInfo, +TimeData, OUT_BUF_SIZE, flags); \endcode If the bitstream configuration (number +of channels, sample rate, frame size) is not known a priori, you may call +aacDecoder_GetStreamInfo() to retrieve a structure that contains this +information. You may use this data to initialize an audio output device. \code + p_si = aacDecoder_GetStreamInfo(aacDecoderInfo); +\endcode +-# Repeat steps 5 to 7 until no data is available to decode any more, or in case +of error. \code } while (bytesRead[0] > 0 || doFlush || doBsFlush || +forceContinue); \endcode +-# Call aacDecoder_Close() to de-allocate all AAC decoder and transport layer +structures. \code aacDecoder_Close(aacDecoderInfo); \endcode + +\image latex decode.png "Decode calling sequence" width=11cm + +\image latex change_source.png "Change data source sequence" width=5cm + +\image latex conceal.png "Error concealment sequence" width=14cm + +\subsection Error_Concealment_Sequence Error Concealment Sequence + +There are different strategies to handle bit stream errors. Depending on the +system properties the product designer might choose to take different actions in +case a bit error occurs. In many cases the decoder might be able to do +reasonable error concealment without the need of any additional actions from the +system. But in some cases its not even possible to know how many decoded PCM +output samples are required to fill the gap due to the data error, then the +software surrounding the decoder must deal with the situation. The most simple +way would be to just stop audio playback and resume once enough bit stream data +and/or buffered output samples are available. More sophisticated designs might +also be able to deal with sender/receiver clock drifts or data drop outs by +using a closed loop control of FIFO fulness levels. The chosen strategy depends +on the final product requirements. + +The error concealment sequence diagram illustrates the general execution paths +for error handling. + +The macro IS_OUTPUT_VALID(err) can be used to identify if the audio output +buffer contains valid audio either from error free bit stream data or successful +error concealment. In case the result is false, the decoder output buffer does +not contain meaningful audio samples and should not be passed to any output as +it is. Most likely in case that a continuous audio output PCM stream is +required, the output buffer must be filled with audio data from the calling +framework. This might be e.g. an appropriate number of samples all zero. + +If error code ::AAC_DEC_TRANSPORT_SYNC_ERROR is returned by the decoder, under +some particular conditions it is possible to estimate lost frames due to the bit +stream error. In that case the bit stream is required to have a constant +bitrate, and compatible transport type. Audio samples for the lost frames can be +obtained by calling aacDecoder_DecodeFrame() with flag ::AACDEC_CONCEAL set +n-times where n is the count of lost frames. Please note that the decoder has to +have encountered valid configuration data at least once to be able to generate +concealed data, because at the minimum the sampling rate, frame size and amount +of audio channels needs to be known. + +If it is not possible to get an estimation of lost frames then a constant +fullness of the audio output buffer can be achieved by implementing different +FIFO control techniques e.g. just stop taking of samples from the buffer to +avoid underflow or stop filling new data to the buffer to avoid overflow. But +this techniques are out of scope of this document. + +For a detailed description of a specific error code please refer also to +::AAC_DECODER_ERROR. + +\section BufferSystem Buffer System + +There are three main buffers in an AAC decoder application. One external input +buffer to hold bitstream data from file I/O or elsewhere, one decoder-internal +input buffer, and one to hold the decoded output PCM sample data. In resource +limited applications, the output buffer may be reused as an external input +buffer prior to the subsequence aacDecoder_Fill() function call. + +To feed the data to the decoder-internal input buffer, use the +function aacDecoder_Fill(). This function returns important information +regarding the number of bytes in the external input buffer that have not yet +been copied into the internal input buffer (variable bytesValid). Once the +external buffer has been fully copied, it can be completely re-filled again. In +case you wish to refill the buffer while there are unprocessed bytes (bytesValid +is unequal 0), you should preserve the unconsumed data. However, we recommend to +refill the buffer only when bytesValid returns 0. + +The bytesValid parameter is an input and output parameter to the FDK decoder. As +an input, it signals how many valid bytes are available in the external buffer. +After consumption of the external buffer using aacDecoder_Fill() function, the +bytesValid parameter indicates if any of the bytes in the external buffer were +not consumed. + +\image latex dec_buffer.png "Life cycle of the external input buffer" width=9cm + +\page OutputFormat Decoder audio output + +\section OutputFormatObtaining Obtaining channel mapping information + +The decoded audio output format is indicated by a set of variables of the +CStreamInfo structure. While the struct members sampleRate, frameSize and +numChannels might be self explanatory, pChannelType and pChannelIndices require +some further explanation. + +These two arrays indicate the configuration of channel data within the output +buffer. Both arrays have CStreamInfo::numChannels number of cells. Each cell of +pChannelType indicates the channel type, which is described in the enum +::AUDIO_CHANNEL_TYPE (defined in FDK_audio.h). The cells of pChannelIndices +indicate the sub index among the channels starting with 0 among channels of the +same audio channel type. + +The indexing scheme is structured as defined in MPEG-2/4 Standards. Indices +start from the front direction (a center channel if available, will always be +index 0) and increment, starting with the left side, pairwise (e.g. L, R) and +from front to back (Front L, Front R, Surround L, Surround R). For detailed +explanation, please refer to ISO/IEC 13818-7:2005(E), chapter 8.5.3.2. + +In case a Program Config is included in the audio configuration, the channel +mapping described within it will be adopted. + +The examples below explain these aspects in detail. + +\section OutputFormatChange Changing the audio output format + +For MPEG-4 audio the channel order can be changed at runtime through the +parameter +::AAC_PCM_OUTPUT_CHANNEL_MAPPING. See the description of those +parameters and the decoder library function aacDecoder_SetParam() for more +detail. + +\section OutputFormatExample Channel mapping examples + +The following examples illustrate the location of individual audio samples in +the audio buffer that is passed to aacDecoder_DecodeFrame() and the expected +data in the CStreamInfo structure which can be obtained by calling +aacDecoder_GetStreamInfo(). + +\subsection ExamplesStereo Stereo + +In case of ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1, +a AAC-LC bit stream which has channelConfiguration = 2 in its audio specific +config would lead to the following values in CStreamInfo: + +CStreamInfo::numChannels = 2 + +CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT } + +CStreamInfo::pChannelIndices = { 0, 1 } + +The output buffer will be formatted as follows: + +\verbatim + ... + ... +\endverbatim + +Where N equals to CStreamInfo::frameSize . + +\subsection ExamplesSurround Surround 5.1 + +In case of ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1, +a AAC-LC bit stream which has channelConfiguration = 6 in its audio specific +config, would lead to the following values in CStreamInfo: + +CStreamInfo::numChannels = 6 + +CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT, ::ACT_FRONT, ::ACT_LFE, +::ACT_BACK, ::ACT_BACK } + +CStreamInfo::pChannelIndices = { 1, 2, 0, 0, 0, 1 } + +Since ::AAC_PCM_OUTPUT_CHANNEL_MAPPING is 1, WAV file channel ordering will be +used. For a 5.1 channel scheme, thus the channels would be: front left, front +right, center, LFE, surround left, surround right. Thus the third channel is the +center channel, receiving the index 0. The other front channels are front left, +front right being placed as first and second channels with indices 1 and 2 +correspondingly. There is only one LFE, placed as the fourth channel and index +0. Finally both surround channels get the type definition ACT_BACK, and the +indices 0 and 1. + +The output buffer will be formatted as follows: + +\verbatim + +

+ + + +
+ + +... + + +
+ +\endverbatim + +Where N equals to CStreamInfo::frameSize . + +\subsection ExamplesArib ARIB coding mode 2/1 + +In case of ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1, +in case of a ARIB bit stream using coding mode 2/1 as described in ARIB STD-B32 +Part 2 Version 2.1-E1, page 61, would lead to the following values in +CStreamInfo: + +CStreamInfo::numChannels = 3 + +CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT, ::ACT_BACK } + +CStreamInfo::pChannelIndices = { 0, 1, 0 } + +The audio channels will be placed as follows in the audio output buffer: + +\verbatim + + + + +... + + + +Where N equals to CStreamInfo::frameSize . + +\endverbatim + +*/ + +#include "machine_type.h" +#include "FDK_audio.h" + +#define AACDECODER_LIB_VL0 3 +#define AACDECODER_LIB_VL1 2 +#define AACDECODER_LIB_VL2 0 + +#include "genericStds.h" +/** + * \brief AAC decoder error codes. + */ +typedef enum { + AAC_DEC_OK = + 0x0000, /*!< No error occurred. Output buffer is valid and error free. */ + AAC_DEC_OUT_OF_MEMORY = + 0x0002, /*!< Heap returned NULL pointer. Output buffer is invalid. */ + AAC_DEC_UNKNOWN = + 0x0005, /*!< Error condition is of unknown reason, or from a another + module. Output buffer is invalid. */ + + /* Synchronization errors. Output buffer is invalid. */ + aac_dec_sync_error_start = 0x1000, + AAC_DEC_TRANSPORT_SYNC_ERROR = 0x1001, /*!< The transport decoder had + synchronization problems. Do not + exit decoding. Just feed new + bitstream data. */ + AAC_DEC_NOT_ENOUGH_BITS = 0x1002, /*!< The input buffer ran out of bits. */ + aac_dec_sync_error_end = 0x1FFF, + + /* Initialization errors. Output buffer is invalid. */ + aac_dec_init_error_start = 0x2000, + AAC_DEC_INVALID_HANDLE = + 0x2001, /*!< The handle passed to the function call was invalid (NULL). */ + AAC_DEC_UNSUPPORTED_AOT = + 0x2002, /*!< The AOT found in the configuration is not supported. */ + AAC_DEC_UNSUPPORTED_FORMAT = + 0x2003, /*!< The bitstream format is not supported. */ + AAC_DEC_UNSUPPORTED_ER_FORMAT = + 0x2004, /*!< The error resilience tool format is not supported. */ + AAC_DEC_UNSUPPORTED_EPCONFIG = + 0x2005, /*!< The error protection format is not supported. */ + AAC_DEC_UNSUPPORTED_MULTILAYER = + 0x2006, /*!< More than one layer for AAC scalable is not supported. */ + AAC_DEC_UNSUPPORTED_CHANNELCONFIG = + 0x2007, /*!< The channel configuration (either number or arrangement) is + not supported. */ + AAC_DEC_UNSUPPORTED_SAMPLINGRATE = 0x2008, /*!< The sample rate specified in + the configuration is not + supported. */ + AAC_DEC_INVALID_SBR_CONFIG = + 0x2009, /*!< The SBR configuration is not supported. */ + AAC_DEC_SET_PARAM_FAIL = 0x200A, /*!< The parameter could not be set. Either + the value was out of range or the + parameter does not exist. */ + AAC_DEC_NEED_TO_RESTART = 0x200B, /*!< The decoder needs to be restarted, + since the required configuration change + cannot be performed. */ + AAC_DEC_OUTPUT_BUFFER_TOO_SMALL = + 0x200C, /*!< The provided output buffer is too small. */ + aac_dec_init_error_end = 0x2FFF, + + /* Decode errors. Output buffer is valid but concealed. */ + aac_dec_decode_error_start = 0x4000, + AAC_DEC_TRANSPORT_ERROR = + 0x4001, /*!< The transport decoder encountered an unexpected error. */ + AAC_DEC_PARSE_ERROR = 0x4002, /*!< Error while parsing the bitstream. Most + probably it is corrupted, or the system + crashed. */ + AAC_DEC_UNSUPPORTED_EXTENSION_PAYLOAD = + 0x4003, /*!< Error while parsing the extension payload of the bitstream. + The extension payload type found is not supported. */ + AAC_DEC_DECODE_FRAME_ERROR = 0x4004, /*!< The parsed bitstream value is out of + range. Most probably the bitstream is + corrupt, or the system crashed. */ + AAC_DEC_CRC_ERROR = 0x4005, /*!< The embedded CRC did not match. */ + AAC_DEC_INVALID_CODE_BOOK = 0x4006, /*!< An invalid codebook was signaled. + Most probably the bitstream is corrupt, + or the system crashed. */ + AAC_DEC_UNSUPPORTED_PREDICTION = + 0x4007, /*!< Predictor found, but not supported in the AAC Low Complexity + profile. Most probably the bitstream is corrupt, or has a wrong + format. */ + AAC_DEC_UNSUPPORTED_CCE = 0x4008, /*!< A CCE element was found which is not + supported. Most probably the bitstream is + corrupt, or has a wrong format. */ + AAC_DEC_UNSUPPORTED_LFE = 0x4009, /*!< A LFE element was found which is not + supported. Most probably the bitstream is + corrupt, or has a wrong format. */ + AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA = + 0x400A, /*!< Gain control data found but not supported. Most probably the + bitstream is corrupt, or has a wrong format. */ + AAC_DEC_UNSUPPORTED_SBA = + 0x400B, /*!< SBA found, but currently not supported in the BSAC profile. + */ + AAC_DEC_TNS_READ_ERROR = 0x400C, /*!< Error while reading TNS data. Most + probably the bitstream is corrupt or the + system crashed. */ + AAC_DEC_RVLC_ERROR = + 0x400D, /*!< Error while decoding error resilient data. */ + aac_dec_decode_error_end = 0x4FFF, + /* Ancillary data errors. Output buffer is valid. */ + aac_dec_anc_data_error_start = 0x8000, + AAC_DEC_ANC_DATA_ERROR = + 0x8001, /*!< Non severe error concerning the ancillary data handling. */ + AAC_DEC_TOO_SMALL_ANC_BUFFER = 0x8002, /*!< The registered ancillary data + buffer is too small to receive the + parsed data. */ + AAC_DEC_TOO_MANY_ANC_ELEMENTS = 0x8003, /*!< More than the allowed number of + ancillary data elements should be + written to buffer. */ + aac_dec_anc_data_error_end = 0x8FFF + +} AAC_DECODER_ERROR; + +/** Macro to identify initialization errors. Output buffer is invalid. */ +#define IS_INIT_ERROR(err) \ + ((((err) >= aac_dec_init_error_start) && ((err) <= aac_dec_init_error_end)) \ + ? 1 \ + : 0) +/** Macro to identify decode errors. Output buffer is valid but concealed. */ +#define IS_DECODE_ERROR(err) \ + ((((err) >= aac_dec_decode_error_start) && \ + ((err) <= aac_dec_decode_error_end)) \ + ? 1 \ + : 0) +/** + * Macro to identify if the audio output buffer contains valid samples after + * calling aacDecoder_DecodeFrame(). Output buffer is valid but can be + * concealed. + */ +#define IS_OUTPUT_VALID(err) (((err) == AAC_DEC_OK) || IS_DECODE_ERROR(err)) + +/*! \enum AAC_MD_PROFILE + * \brief The available metadata profiles which are mostly related to downmixing. The values define the arguments + * for the use with parameter ::AAC_METADATA_PROFILE. + */ +typedef enum { + AAC_MD_PROFILE_MPEG_STANDARD = + 0, /*!< The standard profile creates a mixdown signal based on the + advanced downmix metadata (from a DSE). The equations and default + values are defined in ISO/IEC 14496:3 Ammendment 4. Any other + (legacy) downmix metadata will be ignored. No other parameter will + be modified. */ + AAC_MD_PROFILE_MPEG_LEGACY = + 1, /*!< This profile behaves identical to the standard profile if advanced + downmix metadata (from a DSE) is available. If not, the + matrix_mixdown information embedded in the program configuration + element (PCE) will be applied. If neither is the case, the module + creates a mixdown using the default coefficients as defined in + ISO/IEC 14496:3 AMD 4. The profile can be used to support legacy + digital TV (e.g. DVB) streams. */ + AAC_MD_PROFILE_MPEG_LEGACY_PRIO = + 2, /*!< Similar to the ::AAC_MD_PROFILE_MPEG_LEGACY profile but if both + the advanced (ISO/IEC 14496:3 AMD 4) and the legacy (PCE) MPEG + downmix metadata are available the latter will be applied. + */ + AAC_MD_PROFILE_ARIB_JAPAN = + 3 /*!< Downmix creation as described in ABNT NBR 15602-2. But if advanced + downmix metadata (ISO/IEC 14496:3 AMD 4) is available it will be + preferred because of the higher resolutions. In addition the + metadata expiry time will be set to the value defined in the ARIB + standard (see ::AAC_METADATA_EXPIRY_TIME). + */ +} AAC_MD_PROFILE; + +/*! \enum AAC_DRC_DEFAULT_PRESENTATION_MODE_OPTIONS + * \brief Options for handling of DRC parameters, if presentation mode is not indicated in bitstream + */ +typedef enum { + AAC_DRC_PARAMETER_HANDLING_DISABLED = -1, /*!< DRC parameter handling + disabled, all parameters are + applied as requested. */ + AAC_DRC_PARAMETER_HANDLING_ENABLED = + 0, /*!< Apply changes to requested DRC parameters to prevent clipping. */ + AAC_DRC_PRESENTATION_MODE_1_DEFAULT = + 1, /*!< Use DRC presentation mode 1 as default (e.g. for Nordig) */ + AAC_DRC_PRESENTATION_MODE_2_DEFAULT = + 2 /*!< Use DRC presentation mode 2 as default (e.g. for DTG DBook) */ +} AAC_DRC_DEFAULT_PRESENTATION_MODE_OPTIONS; + +/** + * \brief AAC decoder setting parameters + */ +typedef enum { + AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE = + 0x0002, /*!< Defines how the decoder processes two channel signals: \n + 0: Leave both signals as they are (default). \n + 1: Create a dual mono output signal from channel 1. \n + 2: Create a dual mono output signal from channel 2. \n + 3: Create a dual mono output signal by mixing both channels + (L' = R' = 0.5*Ch1 + 0.5*Ch2). */ + AAC_PCM_OUTPUT_CHANNEL_MAPPING = + 0x0003, /*!< Output buffer channel ordering. 0: MPEG PCE style order, 1: + WAV file channel order (default). */ + AAC_PCM_LIMITER_ENABLE = + 0x0004, /*!< Enable signal level limiting. \n + -1: Auto-config. Enable limiter for all + non-lowdelay configurations by default. \n + 0: Disable limiter in general. \n + 1: Enable limiter always. + It is recommended to call the decoder + with a AACDEC_CLRHIST flag to reset all + states when the limiter switch is changed + explicitly. */ + AAC_PCM_LIMITER_ATTACK_TIME = 0x0005, /*!< Signal level limiting attack time + in ms. Default configuration is 15 + ms. Adjustable range from 1 ms to 15 + ms. */ + AAC_PCM_LIMITER_RELEAS_TIME = 0x0006, /*!< Signal level limiting release time + in ms. Default configuration is 50 + ms. Adjustable time must be larger + than 0 ms. */ + AAC_PCM_MIN_OUTPUT_CHANNELS = + 0x0011, /*!< Minimum number of PCM output channels. If higher than the + number of encoded audio channels, a simple channel extension is + applied (see note 4 for exceptions). \n -1, 0: Disable channel + extension feature. The decoder output contains the same number + of channels as the encoded bitstream. \n 1: This value is + currently needed only together with the mix-down feature. See + ::AAC_PCM_MAX_OUTPUT_CHANNELS and note 2 below. \n + 2: Encoded mono signals will be duplicated to achieve a + 2/0/0.0 channel output configuration. \n 6: The decoder + tries to reorder encoded signals with less than six channels to + achieve a 3/0/2.1 channel output signal. Missing channels will + be filled with a zero signal. If reordering is not possible the + empty channels will simply be appended. Only available if + instance is configured to support multichannel output. \n 8: + The decoder tries to reorder encoded signals with less than + eight channels to achieve a 3/0/4.1 channel output signal. + Missing channels will be filled with a zero signal. If + reordering is not possible the empty channels will simply be + appended. Only available if instance is configured to + support multichannel output.\n NOTE: \n + 1. The channel signaling (CStreamInfo::pChannelType and + CStreamInfo::pChannelIndices) will not be modified. Added empty + channels will be signaled with channel type + AUDIO_CHANNEL_TYPE::ACT_NONE. \n + 2. If the parameter value is greater than that of + ::AAC_PCM_MAX_OUTPUT_CHANNELS both will be set to the same + value. \n + 3. This parameter will be ignored if the number of encoded + audio channels is greater than 8. */ + AAC_PCM_MAX_OUTPUT_CHANNELS = + 0x0012, /*!< Maximum number of PCM output channels. If lower than the + number of encoded audio channels, downmixing is applied + accordingly (see note 5 for exceptions). If dedicated metadata + is available in the stream it will be used to achieve better + mixing results. \n -1, 0: Disable downmixing feature. The + decoder output contains the same number of channels as the + encoded bitstream. \n 1: All encoded audio configurations + with more than one channel will be mixed down to one mono + output signal. \n 2: The decoder performs a stereo mix-down + if the number encoded audio channels is greater than two. \n 6: + If the number of encoded audio channels is greater than six the + decoder performs a mix-down to meet the target output + configuration of 3/0/2.1 channels. Only available if instance + is configured to support multichannel output. \n 8: This + value is currently needed only together with the channel + extension feature. See ::AAC_PCM_MIN_OUTPUT_CHANNELS and note 2 + below. Only available if instance is configured to support + multichannel output. \n NOTE: \n + 1. Down-mixing of any seven or eight channel configuration + not defined in ISO/IEC 14496-3 PDAM 4 is not supported by this + software version. \n + 2. If the parameter value is greater than zero but smaller + than ::AAC_PCM_MIN_OUTPUT_CHANNELS both will be set to same + value. \n + 3. This parameter will be ignored if the number of encoded + audio channels is greater than 8. */ + AAC_METADATA_PROFILE = + 0x0020, /*!< See ::AAC_MD_PROFILE for all available values. */ + AAC_METADATA_EXPIRY_TIME = 0x0021, /*!< Defines the time in ms after which all + the bitstream associated meta-data (DRC, + downmix coefficients, ...) will be reset + to default if no update has been + received. Negative values disable the + feature. */ + + AAC_CONCEAL_METHOD = 0x0100, /*!< Error concealment: Processing method. \n + 0: Spectral muting. \n + 1: Noise substitution (see ::CONCEAL_NOISE). + \n 2: Energy interpolation (adds additional + signal delay of one frame, see + ::CONCEAL_INTER. only some AOTs are + supported). \n */ + AAC_DRC_BOOST_FACTOR = + 0x0200, /*!< MPEG-4 / MPEG-D Dynamic Range Control (DRC): Scaling factor + for boosting gain values. Defines how the boosting DRC factors + (conveyed in the bitstream) will be applied to the decoded + signal. The valid values range from 0 (don't apply boost + factors) to 127 (fully apply boost factors). Default value is 0 + for MPEG-4 DRC and 127 for MPEG-D DRC. */ + AAC_DRC_ATTENUATION_FACTOR = 0x0201, /*!< MPEG-4 / MPEG-D DRC: Scaling factor + for attenuating gain values. Same as + ::AAC_DRC_BOOST_FACTOR but for + attenuating DRC factors. */ + AAC_DRC_REFERENCE_LEVEL = + 0x0202, /*!< MPEG-4 / MPEG-D DRC: Target reference level / decoder target + loudness.\n Defines the level below full-scale (quantized in + steps of 0.25dB) to which the output audio signal will be + normalized to by the DRC module.\n The parameter controls + loudness normalization for both MPEG-4 DRC and MPEG-D DRC. The + valid values range from 40 (-10 dBFS) to 127 (-31.75 dBFS).\n + Example values:\n + 124 (-31 dBFS) for audio/video receivers (AVR) or other + devices allowing audio playback with high dynamic range,\n 96 + (-24 dBFS) for TV sets or equivalent devices (default),\n 64 + (-16 dBFS) for mobile devices where the dynamic range of audio + playback is restricted.\n Any value smaller than 0 switches off + loudness normalization and MPEG-4 DRC. */ + AAC_DRC_HEAVY_COMPRESSION = + 0x0203, /*!< MPEG-4 DRC: En-/Disable DVB specific heavy compression (aka + RF mode). If set to 1, the decoder will apply the compression + values from the DVB specific ancillary data field. At the same + time the MPEG-4 Dynamic Range Control tool will be disabled. By + default, heavy compression is disabled. */ + AAC_DRC_DEFAULT_PRESENTATION_MODE = + 0x0204, /*!< MPEG-4 DRC: Default presentation mode (DRC parameter + handling). \n Defines the handling of the DRC parameters boost + factor, attenuation factor and heavy compression, if no + presentation mode is indicated in the bitstream.\n For options, + see ::AAC_DRC_DEFAULT_PRESENTATION_MODE_OPTIONS.\n Default: + ::AAC_DRC_PARAMETER_HANDLING_DISABLED */ + AAC_DRC_ENC_TARGET_LEVEL = + 0x0205, /*!< MPEG-4 DRC: Encoder target level for light (i.e. not heavy) + compression.\n If known, this declares the target reference + level that was assumed at the encoder for calculation of + limiting gains. The valid values range from 0 (full-scale) to + 127 (31.75 dB below full-scale). This parameter is used only + with ::AAC_DRC_PARAMETER_HANDLING_ENABLED and ignored + otherwise.\n Default: 127 (worst-case assumption).\n */ + AAC_UNIDRC_SET_EFFECT = 0x0206, /*!< MPEG-D DRC: Request a DRC effect type for + selection of a DRC set.\n Supported indices + are:\n -1: DRC off. Completely disables + MPEG-D DRC.\n 0: None (default). Disables + MPEG-D DRC, but automatically enables DRC + if necessary to prevent clipping.\n 1: Late + night\n 2: Noisy environment\n 3: Limited + playback range\n 4: Low playback level\n 5: + Dialog enhancement\n 6: General + compression. Used for generally enabling + MPEG-D DRC without particular request.\n */ + AAC_UNIDRC_ALBUM_MODE = + 0x0207, /*!< MPEG-D DRC: Enable album mode. 0: Disabled (default), 1: + Enabled.\n Disabled album mode leads to application of gain + sequences for fading in and out, if provided in the + bitstream.\n Enabled album mode makes use of dedicated album + loudness information, if provided in the bitstream.\n */ + AAC_QMF_LOWPOWER = + 0x0300, /*!< Quadrature Mirror Filter (QMF) Bank processing mode. \n + -1: Use internal default. \n + 0: Use complex QMF data mode. \n + 1: Use real (low power) QMF data mode. \n */ + AAC_TPDEC_CLEAR_BUFFER = + 0x0603 /*!< Clear internal bit stream buffer of transport layers. The + decoder will start decoding at new data passed after this event + and any previous data is discarded. */ + +} AACDEC_PARAM; + +/** + * \brief This structure gives information about the currently decoded audio + * data. All fields are read-only. + */ +typedef struct { + /* These five members are the only really relevant ones for the user. */ + INT sampleRate; /*!< The sample rate in Hz of the decoded PCM audio signal. */ + INT frameSize; /*!< The frame size of the decoded PCM audio signal. \n + Typically this is: \n + 1024 or 960 for AAC-LC \n + 2048 or 1920 for HE-AAC (v2) \n + 512 or 480 for AAC-LD and AAC-ELD \n + 768, 1024, 2048 or 4096 for USAC */ + INT numChannels; /*!< The number of output audio channels before the rendering + module, i.e. the original channel configuration. */ + AUDIO_CHANNEL_TYPE + *pChannelType; /*!< Audio channel type of each output audio channel. */ + UCHAR *pChannelIndices; /*!< Audio channel index for each output audio + channel. See ISO/IEC 13818-7:2005(E), 8.5.3.2 + Explicit channel mapping using a + program_config_element() */ + /* Decoder internal members. */ + INT aacSampleRate; /*!< Sampling rate in Hz without SBR (from configuration + info) divided by a (ELD) downscale factor if present. */ + INT profile; /*!< MPEG-2 profile (from file header) (-1: not applicable (e. g. + MPEG-4)). */ + AUDIO_OBJECT_TYPE + aot; /*!< Audio Object Type (from ASC): is set to the appropriate value + for MPEG-2 bitstreams (e. g. 2 for AAC-LC). */ + INT channelConfig; /*!< Channel configuration (0: PCE defined, 1: mono, 2: + stereo, ... */ + INT bitRate; /*!< Instantaneous bit rate. */ + INT aacSamplesPerFrame; /*!< Samples per frame for the AAC core (from ASC) + divided by a (ELD) downscale factor if present. \n + Typically this is (with a downscale factor of 1): + \n 1024 or 960 for AAC-LC \n 512 or 480 for + AAC-LD and AAC-ELD */ + INT aacNumChannels; /*!< The number of audio channels after AAC core + processing (before PS or MPS processing). CAUTION: This + are not the final number of output channels! */ + AUDIO_OBJECT_TYPE extAot; /*!< Extension Audio Object Type (from ASC) */ + INT extSamplingRate; /*!< Extension sampling rate in Hz (from ASC) divided by + a (ELD) downscale factor if present. */ + + UINT outputDelay; /*!< The number of samples the output is additionally + delayed by.the decoder. */ + UINT flags; /*!< Copy of internal flags. Only to be written by the decoder, + and only to be read externally. */ + + SCHAR epConfig; /*!< epConfig level (from ASC): only level 0 supported, -1 + means no ER (e. g. AOT=2, MPEG-2 AAC, etc.) */ + /* Statistics */ + INT numLostAccessUnits; /*!< This integer will reflect the estimated amount of + lost access units in case aacDecoder_DecodeFrame() + returns AAC_DEC_TRANSPORT_SYNC_ERROR. It will be + < 0 if the estimation failed. */ + + INT64 numTotalBytes; /*!< This is the number of total bytes that have passed + through the decoder. */ + INT64 + numBadBytes; /*!< This is the number of total bytes that were considered + with errors from numTotalBytes. */ + INT64 + numTotalAccessUnits; /*!< This is the number of total access units that + have passed through the decoder. */ + INT64 numBadAccessUnits; /*!< This is the number of total access units that + were considered with errors from numTotalBytes. */ + + /* Metadata */ + SCHAR drcProgRefLev; /*!< DRC program reference level. Defines the reference + level below full-scale. It is quantized in steps of + 0.25dB. The valid values range from 0 (0 dBFS) to 127 + (-31.75 dBFS). It is used to reflect the average + loudness of the audio in LKFS according to ITU-R BS + 1770. If no level has been found in the bitstream the + value is -1. */ + SCHAR + drcPresMode; /*!< DRC presentation mode. According to ETSI TS 101 154, + this field indicates whether light (MPEG-4 Dynamic Range + Control tool) or heavy compression (DVB heavy + compression) dynamic range control shall take priority + on the outputs. For details, see ETSI TS 101 154, table + C.33. Possible values are: \n -1: No corresponding + metadata found in the bitstream \n 0: DRC presentation + mode not indicated \n 1: DRC presentation mode 1 \n 2: + DRC presentation mode 2 \n 3: Reserved */ + INT outputLoudness; /*!< Audio output loudness in steps of -0.25 dB. Range: 0 + (0 dBFS) to 231 (-57.75 dBFS).\n A value of -1 + indicates that no loudness metadata is present.\n If + loudness normalization is active, the value corresponds + to the target loudness value set with + ::AAC_DRC_REFERENCE_LEVEL.\n If loudness normalization + is not active, the output loudness value corresponds to + the loudness metadata given in the bitstream.\n + Loudness metadata can originate from MPEG-4 DRC or + MPEG-D DRC. */ + +} CStreamInfo; + +typedef struct AAC_DECODER_INSTANCE + *HANDLE_AACDECODER; /*!< Pointer to a AAC decoder instance. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize ancillary data buffer. + * + * \param self AAC decoder handle. + * \param buffer Pointer to (external) ancillary data buffer. + * \param size Size of the buffer pointed to by buffer. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_AncDataInit(HANDLE_AACDECODER self, + UCHAR *buffer, int size); + +/** + * \brief Get one ancillary data element. + * + * \param self AAC decoder handle. + * \param index Index of the ancillary data element to get. + * \param ptr Pointer to a buffer receiving a pointer to the requested + * ancillary data element. + * \param size Pointer to a buffer receiving the length of the requested + * ancillary data element. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_AncDataGet(HANDLE_AACDECODER self, + int index, UCHAR **ptr, + int *size); + +/** + * \brief Set one single decoder parameter. + * + * \param self AAC decoder handle. + * \param param Parameter to be set. + * \param value Parameter value. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_SetParam(const HANDLE_AACDECODER self, + const AACDEC_PARAM param, + const INT value); + +/** + * \brief Get free bytes inside decoder internal buffer. + * \param self Handle of AAC decoder instance. + * \param pFreeBytes Pointer to variable receiving amount of free bytes inside + * decoder internal buffer. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR +aacDecoder_GetFreeBytes(const HANDLE_AACDECODER self, UINT *pFreeBytes); + +/** + * \brief Open an AAC decoder instance. + * \param transportFmt The transport type to be used. + * \param nrOfLayers Number of transport layers. + * \return AAC decoder handle. + */ +LINKSPEC_H HANDLE_AACDECODER aacDecoder_Open(TRANSPORT_TYPE transportFmt, + UINT nrOfLayers); + +/** + * \brief Explicitly configure the decoder by passing a raw AudioSpecificConfig + * (ASC) or a StreamMuxConfig (SMC), contained in a binary buffer. This is + * required for MPEG-4 and Raw Packets file format bitstreams as well as for + * LATM bitstreams with no in-band SMC. If the transport format is LATM with or + * without LOAS, configuration is assumed to be an SMC, for all other file + * formats an ASC. + * + * \param self AAC decoder handle. + * \param conf Pointer to an unsigned char buffer containing the binary + * configuration buffer (either ASC or SMC). + * \param length Length of the configuration buffer in bytes. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_ConfigRaw(HANDLE_AACDECODER self, + UCHAR *conf[], + const UINT length[]); + +/** + * \brief Submit raw ISO base media file format boxes to decoder for parsing + * (only some box types are recognized). + * + * \param self AAC decoder handle. + * \param buffer Pointer to an unsigned char buffer containing the binary box + * data (including size and type, can be a sequence of multiple boxes). + * \param length Length of the data in bytes. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_RawISOBMFFData(HANDLE_AACDECODER self, + UCHAR *buffer, + UINT length); + +/** + * \brief Fill AAC decoder's internal input buffer with bitstream data from the + * external input buffer. The function only copies such data as long as the + * decoder-internal input buffer is not full. So it grabs whatever it can from + * pBuffer and returns information (bytesValid) so that at a subsequent call of + * %aacDecoder_Fill(), the right position in pBuffer can be determined to grab + * the next data. + * + * \param self AAC decoder handle. + * \param pBuffer Pointer to external input buffer. + * \param bufferSize Size of external input buffer. This argument is required + * because decoder-internally we need the information to calculate the offset to + * pBuffer, where the next available data is, which is then + * fed into the decoder-internal buffer (as much as + * possible). Our example framework implementation fills the + * buffer at pBuffer again, once it contains no available valid bytes anymore + * (meaning bytesValid equal 0). + * \param bytesValid Number of bitstream bytes in the external bitstream buffer + * that have not yet been copied into the decoder's internal bitstream buffer by + * calling this function. The value is updated according to + * the amount of newly copied bytes. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_Fill(HANDLE_AACDECODER self, + UCHAR *pBuffer[], + const UINT bufferSize[], + UINT *bytesValid); + +/** Flag for aacDecoder_DecodeFrame(): Trigger the built-in error concealment + * module to generate a substitute signal for one lost frame. New input data + * will not be considered. + */ +#define AACDEC_CONCEAL 1 +/** Flag for aacDecoder_DecodeFrame(): Flush all filterbanks to get all delayed + * audio without having new input data. Thus new input data will not be + * considered. + */ +#define AACDEC_FLUSH 2 +/** Flag for aacDecoder_DecodeFrame(): Signal an input bit stream data + * discontinuity. Resync any internals as necessary. + */ +#define AACDEC_INTR 4 +/** Flag for aacDecoder_DecodeFrame(): Clear all signal delay lines and history + * buffers. CAUTION: This can cause discontinuities in the output signal. + */ +#define AACDEC_CLRHIST 8 + +/** + * \brief Decode one audio frame + * + * \param self AAC decoder handle. + * \param pTimeData Pointer to external output buffer where the decoded PCM + * samples will be stored into. + * \param timeDataSize Size of external output buffer in PCM samples. + * \param flags Bit field with flags for the decoder: \n + * (flags & AACDEC_CONCEAL) == 1: Do concealment. \n + * (flags & AACDEC_FLUSH) == 2: Discard input data. Flush + * filter banks (output delayed audio). \n (flags & AACDEC_INTR) == 4: Input + * data is discontinuous. Resynchronize any internals as + * necessary. \n (flags & AACDEC_CLRHIST) == 8: Clear all signal delay lines and + * history buffers. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self, + INT_PCM *pTimeData, + const INT timeDataSize, + const UINT flags); + +/** + * \brief De-allocate all resources of an AAC decoder instance. + * + * \param self AAC decoder handle. + * \return void. + */ +LINKSPEC_H void aacDecoder_Close(HANDLE_AACDECODER self); + +/** + * \brief Get CStreamInfo handle from decoder. + * + * \param self AAC decoder handle. + * \return Reference to requested CStreamInfo. + */ +LINKSPEC_H CStreamInfo *aacDecoder_GetStreamInfo(HANDLE_AACDECODER self); + +/** + * \brief Get decoder library info. + * + * \param info Pointer to an allocated LIB_INFO structure. + * \return 0 on success. + */ +LINKSPEC_H INT aacDecoder_GetLibInfo(LIB_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif /* AACDECODER_LIB_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/FDK_delay.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/FDK_delay.cpp new file mode 100644 index 0000000000000..0cc869cd291b9 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/FDK_delay.cpp @@ -0,0 +1,173 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: + +*******************************************************************************/ + +#include "FDK_delay.h" + +#include "genericStds.h" + +#define MAX_FRAME_LENGTH (1024) + +INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay, + const UCHAR num_channels) { + FDK_ASSERT(data != NULL); + FDK_ASSERT(num_channels > 0); + + if (delay > 0) { + data->delay_line = + (PCM_DEC*)FDKcalloc(num_channels * delay, sizeof(PCM_DEC)); + if (data->delay_line == NULL) { + return -1; + } + } else { + data->delay_line = NULL; + } + data->num_channels = num_channels; + data->delay = delay; + + return 0; +} + +void FDK_Delay_Apply(FDK_SignalDelay* data, PCM_DEC* time_buffer, + const UINT frame_length, const UCHAR channel) { + FDK_ASSERT(data != NULL); + + if (data->delay > 0) { + C_ALLOC_SCRATCH_START(tmp, PCM_DEC, MAX_FRAME_LENGTH) + FDK_ASSERT(frame_length <= MAX_FRAME_LENGTH); + FDK_ASSERT(channel < data->num_channels); + FDK_ASSERT(time_buffer != NULL); + if (frame_length >= data->delay) { + FDKmemcpy(tmp, &time_buffer[frame_length - data->delay], + data->delay * sizeof(PCM_DEC)); + FDKmemmove(&time_buffer[data->delay], &time_buffer[0], + (frame_length - data->delay) * sizeof(PCM_DEC)); + FDKmemcpy(&time_buffer[0], &data->delay_line[channel * data->delay], + data->delay * sizeof(PCM_DEC)); + FDKmemcpy(&data->delay_line[channel * data->delay], tmp, + data->delay * sizeof(PCM_DEC)); + } else { + FDKmemcpy(tmp, &time_buffer[0], frame_length * sizeof(PCM_DEC)); + FDKmemcpy(&time_buffer[0], &data->delay_line[channel * data->delay], + frame_length * sizeof(PCM_DEC)); + FDKmemcpy(&data->delay_line[channel * data->delay], + &data->delay_line[channel * data->delay + frame_length], + (data->delay - frame_length) * sizeof(PCM_DEC)); + FDKmemcpy(&data->delay_line[channel * data->delay + + (data->delay - frame_length)], + tmp, frame_length * sizeof(PCM_DEC)); + } + C_ALLOC_SCRATCH_END(tmp, PCM_DEC, MAX_FRAME_LENGTH) + } + + return; +} + +void FDK_Delay_Destroy(FDK_SignalDelay* data) { + if (data->delay_line != NULL) { + FDKfree(data->delay_line); + } + data->delay_line = NULL; + data->delay = 0; + data->num_channels = 0; + + return; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/FDK_delay.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/FDK_delay.h new file mode 100644 index 0000000000000..6317d9dd5340b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/FDK_delay.h @@ -0,0 +1,152 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: + +*******************************************************************************/ + +#ifndef FDK_DELAY_H +#define FDK_DELAY_H + +#include "aac_rom.h" + +/** + * Structure representing one delay element for multiple channels. + */ +typedef struct { + PCM_DEC* delay_line; /*!< Pointer which stores allocated delay line. */ + USHORT delay; /*!< Delay required in samples (per channel). */ + UCHAR num_channels; /*!< Number of channels to delay. */ +} FDK_SignalDelay; + +/** + * \brief Create delay element for multiple channels with fixed delay value. + * + * \param data Pointer delay element structure. + * \param delay Required delay value in samples per channel. + * \param num_channels Required number of channels. + * + * \return -1 on out of memory, else 0 + */ +INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay, + const UCHAR num_channels); + +/** + * \brief Apply delay to one channel (non-interleaved storage assumed). + * + * \param data Pointer delay element structure. + * \param time_buffer Pointer to signal to delay. + * \param frame_length Frame length of input/output signal (needs to be >= + * delay). + * \param channel Index of current channel (0 <= channel < num_channels). + * + * \return void + */ +void FDK_Delay_Apply(FDK_SignalDelay* data, PCM_DEC* time_buffer, + const UINT frame_length, const UCHAR channel); + +/** + * \brief Destroy delay element. + * + * \param data Pointer delay element structure. + * + * \return void + */ +void FDK_Delay_Destroy(FDK_SignalDelay* data); + +#endif /* #ifndef FDK_DELAY_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_ram.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_ram.cpp new file mode 100644 index 0000000000000..fac154059ef11 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_ram.cpp @@ -0,0 +1,177 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +#include "aac_ram.h" +#include "aac_rom.h" + +#define WORKBUFFER1_TAG 0 +#define WORKBUFFER2_TAG 1 +#define WORKBUFFER5_TAG 6 +#define WORKBUFFER6_TAG 7 + +/*! The structure AAC_DECODER_INSTANCE is the top level structure holding all + decoder configurations, handles and structs. + */ +C_ALLOC_MEM(AacDecoder, struct AAC_DECODER_INSTANCE, 1) + +/*! + \name StaticAacData + + Static memory areas, must not be overwritten in other sections of the decoder +*/ +/* @{ */ + +/*! The structure CAacDecoderStaticChannelInfo contains the static sideinfo + which is needed for the decoding of one aac channel.
Dimension: + #AacDecoderChannels */ +C_ALLOC_MEM2(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo, 1, (8)) + +/*! The structure CAacDecoderChannelInfo contains the dynamic sideinfo which is + needed for the decoding of one aac channel.
Dimension: + #AacDecoderChannels */ +C_AALLOC_MEM2(AacDecoderChannelInfo, CAacDecoderChannelInfo, 1, (8)) + +/*! Overlap buffer */ +C_AALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (8)) + +C_ALLOC_MEM(DrcInfo, CDrcInfo, 1) + +/*! The structure CpePersistentData holds the persistent data shared by both + channels of a CPE.
It needs to be allocated for each CPE.
+ Dimension: 1 */ +C_ALLOC_MEM(CpePersistentData, CpePersistentData, 1) + +/*! The structure CCplxPredictionData holds data for complex stereo prediction. +
Dimension: 1 + */ +C_ALLOC_MEM(CplxPredictionData, CCplxPredictionData, 1) + +/*! The buffer holds time samples for the crossfade in case of an USAC DASH IPF + config change Dimension: (8) + */ +C_ALLOC_MEM2(TimeDataFlush, PCM_DEC, TIME_DATA_FLUSH_SIZE, (8)) + +/* @} */ + +/*! + \name DynamicAacData + + Dynamic memory areas, might be reused in other algorithm sections, + e.g. the sbr decoder +*/ + +/* Take into consideration to make use of the WorkBufferCore[3/4] for decoder + * configurations with more than 2 channels */ +C_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL, ((8) * 1024), SECT_DATA_L2, + WORKBUFFER2_TAG) + +C_ALLOC_MEM_OVERLAY(WorkBufferCore6, SCHAR, + fMax((INT)(sizeof(FIXP_DBL) * WB_SECTION_SIZE), + (INT)sizeof(CAacDecoderCommonData)), + SECT_DATA_L2, WORKBUFFER6_TAG) + +C_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1, 1, SECT_DATA_L1, + WORKBUFFER1_TAG) + +/* double buffer size needed for de-/interleaving */ +C_ALLOC_MEM_OVERLAY(WorkBufferCore5, PCM_DEC, (8) * (1024 * 4) * 2, + SECT_DATA_EXTERN, WORKBUFFER5_TAG) diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_ram.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_ram.h new file mode 100644 index 0000000000000..395b2b24a7dcb --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_ram.h @@ -0,0 +1,142 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +#ifndef AAC_RAM_H +#define AAC_RAM_H + +#include "common_fix.h" + +#include "aacdecoder.h" + +#include "channel.h" + +#include "ac_arith_coder.h" + +#include "aacdec_hcr_types.h" +#include "aacdec_hcr.h" + +/* End of formal fix.h */ + +#define MAX_SYNCHS 10 +#define SAMPL_FREQS 12 + +H_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE) + +H_ALLOC_MEM(DrcInfo, CDrcInfo) + +H_ALLOC_MEM(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo) +H_ALLOC_MEM(AacDecoderChannelInfo, CAacDecoderChannelInfo) +H_ALLOC_MEM(OverlapBuffer, FIXP_DBL) + +H_ALLOC_MEM(CpePersistentData, CpePersistentData) +H_ALLOC_MEM(CplxPredictionData, CCplxPredictionData) +H_ALLOC_MEM(SpectralCoeffs, FIXP_DBL) +H_ALLOC_MEM(SpecScale, SHORT) + +H_ALLOC_MEM(TimeDataFlush, PCM_DEC) + +H_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1) +H_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL) +H_ALLOC_MEM_OVERLAY(WorkBufferCore5, PCM_DEC) +H_ALLOC_MEM_OVERLAY(WorkBufferCore6, SCHAR) + +#endif /* #ifndef AAC_RAM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_rom.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_rom.cpp new file mode 100644 index 0000000000000..cbdffc4ebe268 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_rom.cpp @@ -0,0 +1,3428 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl, Tobias Chalupka + + Description: Definition of constant tables + +*******************************************************************************/ + +#include "aac_rom.h" + +/* Prescale InverseQuantTable by 4 to save + redundant shifts in invers quantization + */ +#define SCL_TAB(a) (a >> 4) +const FIXP_DBL InverseQuantTable[INV_QUANT_TABLESIZE + 1] = { + SCL_TAB(0x32CBFD40), SCL_TAB(0x330FC340), SCL_TAB(0x33539FC0), + SCL_TAB(0x33979280), SCL_TAB(0x33DB9BC0), SCL_TAB(0x341FBB80), + SCL_TAB(0x3463F180), SCL_TAB(0x34A83DC0), SCL_TAB(0x34ECA000), + SCL_TAB(0x35311880), SCL_TAB(0x3575A700), SCL_TAB(0x35BA4B80), + SCL_TAB(0x35FF0600), SCL_TAB(0x3643D680), SCL_TAB(0x3688BCC0), + SCL_TAB(0x36CDB880), SCL_TAB(0x3712CA40), SCL_TAB(0x3757F1C0), + SCL_TAB(0x379D2F00), SCL_TAB(0x37E28180), SCL_TAB(0x3827E9C0), + SCL_TAB(0x386D6740), SCL_TAB(0x38B2FA40), SCL_TAB(0x38F8A2C0), + SCL_TAB(0x393E6080), SCL_TAB(0x39843380), SCL_TAB(0x39CA1BC0), + SCL_TAB(0x3A101940), SCL_TAB(0x3A562BC0), SCL_TAB(0x3A9C5340), + SCL_TAB(0x3AE28FC0), SCL_TAB(0x3B28E180), SCL_TAB(0x3B6F4800), + SCL_TAB(0x3BB5C340), SCL_TAB(0x3BFC5380), SCL_TAB(0x3C42F880), + SCL_TAB(0x3C89B200), SCL_TAB(0x3CD08080), SCL_TAB(0x3D176340), + SCL_TAB(0x3D5E5B00), SCL_TAB(0x3DA56700), SCL_TAB(0x3DEC87C0), + SCL_TAB(0x3E33BCC0), SCL_TAB(0x3E7B0640), SCL_TAB(0x3EC26400), + SCL_TAB(0x3F09D640), SCL_TAB(0x3F515C80), SCL_TAB(0x3F98F740), + SCL_TAB(0x3FE0A600), SCL_TAB(0x40286900), SCL_TAB(0x40704000), + SCL_TAB(0x40B82B00), SCL_TAB(0x41002A00), SCL_TAB(0x41483D00), + SCL_TAB(0x41906400), SCL_TAB(0x41D89F00), SCL_TAB(0x4220ED80), + SCL_TAB(0x42695000), SCL_TAB(0x42B1C600), SCL_TAB(0x42FA5000), + SCL_TAB(0x4342ED80), SCL_TAB(0x438B9E80), SCL_TAB(0x43D46380), + SCL_TAB(0x441D3B80), SCL_TAB(0x44662780), SCL_TAB(0x44AF2680), + SCL_TAB(0x44F83900), SCL_TAB(0x45415F00), SCL_TAB(0x458A9880), + SCL_TAB(0x45D3E500), SCL_TAB(0x461D4500), SCL_TAB(0x4666B800), + SCL_TAB(0x46B03E80), SCL_TAB(0x46F9D800), SCL_TAB(0x47438480), + SCL_TAB(0x478D4400), SCL_TAB(0x47D71680), SCL_TAB(0x4820FC00), + SCL_TAB(0x486AF500), SCL_TAB(0x48B50000), SCL_TAB(0x48FF1E80), + SCL_TAB(0x49494F80), SCL_TAB(0x49939380), SCL_TAB(0x49DDEA80), + SCL_TAB(0x4A285400), SCL_TAB(0x4A72D000), SCL_TAB(0x4ABD5E80), + SCL_TAB(0x4B080000), SCL_TAB(0x4B52B400), SCL_TAB(0x4B9D7A80), + SCL_TAB(0x4BE85380), SCL_TAB(0x4C333F00), SCL_TAB(0x4C7E3D00), + SCL_TAB(0x4CC94D00), SCL_TAB(0x4D146F80), SCL_TAB(0x4D5FA500), + SCL_TAB(0x4DAAEC00), SCL_TAB(0x4DF64580), SCL_TAB(0x4E41B180), + SCL_TAB(0x4E8D2F00), SCL_TAB(0x4ED8BF80), SCL_TAB(0x4F246180), + SCL_TAB(0x4F701600), SCL_TAB(0x4FBBDC00), SCL_TAB(0x5007B480), + SCL_TAB(0x50539F00), SCL_TAB(0x509F9B80), SCL_TAB(0x50EBA980), + SCL_TAB(0x5137C980), SCL_TAB(0x5183FB80), SCL_TAB(0x51D03F80), + SCL_TAB(0x521C9500), SCL_TAB(0x5268FC80), SCL_TAB(0x52B57580), + SCL_TAB(0x53020000), SCL_TAB(0x534E9C80), SCL_TAB(0x539B4A80), + SCL_TAB(0x53E80A80), SCL_TAB(0x5434DB80), SCL_TAB(0x5481BE80), + SCL_TAB(0x54CEB280), SCL_TAB(0x551BB880), SCL_TAB(0x5568CF80), + SCL_TAB(0x55B5F800), SCL_TAB(0x56033200), SCL_TAB(0x56507D80), + SCL_TAB(0x569DDA00), SCL_TAB(0x56EB4800), SCL_TAB(0x5738C700), + SCL_TAB(0x57865780), SCL_TAB(0x57D3F900), SCL_TAB(0x5821AC00), + SCL_TAB(0x586F7000), SCL_TAB(0x58BD4500), SCL_TAB(0x590B2B00), + SCL_TAB(0x59592200), SCL_TAB(0x59A72A80), SCL_TAB(0x59F54380), + SCL_TAB(0x5A436D80), SCL_TAB(0x5A91A900), SCL_TAB(0x5ADFF500), + SCL_TAB(0x5B2E5180), SCL_TAB(0x5B7CBF80), SCL_TAB(0x5BCB3E00), + SCL_TAB(0x5C19CD00), SCL_TAB(0x5C686D80), SCL_TAB(0x5CB71E00), + SCL_TAB(0x5D05DF80), SCL_TAB(0x5D54B200), SCL_TAB(0x5DA39500), + SCL_TAB(0x5DF28880), SCL_TAB(0x5E418C80), SCL_TAB(0x5E90A100), + SCL_TAB(0x5EDFC680), SCL_TAB(0x5F2EFC00), SCL_TAB(0x5F7E4280), + SCL_TAB(0x5FCD9900), SCL_TAB(0x601D0080), SCL_TAB(0x606C7800), + SCL_TAB(0x60BC0000), SCL_TAB(0x610B9800), SCL_TAB(0x615B4100), + SCL_TAB(0x61AAF980), SCL_TAB(0x61FAC300), SCL_TAB(0x624A9C80), + SCL_TAB(0x629A8600), SCL_TAB(0x62EA8000), SCL_TAB(0x633A8A00), + SCL_TAB(0x638AA480), SCL_TAB(0x63DACF00), SCL_TAB(0x642B0980), + SCL_TAB(0x647B5400), SCL_TAB(0x64CBAE80), SCL_TAB(0x651C1900), + SCL_TAB(0x656C9400), SCL_TAB(0x65BD1E80), SCL_TAB(0x660DB900), + SCL_TAB(0x665E6380), SCL_TAB(0x66AF1E00), SCL_TAB(0x66FFE880), + SCL_TAB(0x6750C280), SCL_TAB(0x67A1AC80), SCL_TAB(0x67F2A600), + SCL_TAB(0x6843B000), SCL_TAB(0x6894C900), SCL_TAB(0x68E5F200), + SCL_TAB(0x69372B00), SCL_TAB(0x69887380), SCL_TAB(0x69D9CB80), + SCL_TAB(0x6A2B3300), SCL_TAB(0x6A7CAA80), SCL_TAB(0x6ACE3180), + SCL_TAB(0x6B1FC800), SCL_TAB(0x6B716E00), SCL_TAB(0x6BC32400), + SCL_TAB(0x6C14E900), SCL_TAB(0x6C66BD80), SCL_TAB(0x6CB8A180), + SCL_TAB(0x6D0A9500), SCL_TAB(0x6D5C9800), SCL_TAB(0x6DAEAA00), + SCL_TAB(0x6E00CB80), SCL_TAB(0x6E52FC80), SCL_TAB(0x6EA53D00), + SCL_TAB(0x6EF78C80), SCL_TAB(0x6F49EB80), SCL_TAB(0x6F9C5980), + SCL_TAB(0x6FEED700), SCL_TAB(0x70416380), SCL_TAB(0x7093FF00), + SCL_TAB(0x70E6AA00), SCL_TAB(0x71396400), SCL_TAB(0x718C2D00), + SCL_TAB(0x71DF0580), SCL_TAB(0x7231ED00), SCL_TAB(0x7284E300), + SCL_TAB(0x72D7E880), SCL_TAB(0x732AFD00), SCL_TAB(0x737E2080), + SCL_TAB(0x73D15300), SCL_TAB(0x74249480), SCL_TAB(0x7477E480), + SCL_TAB(0x74CB4400), SCL_TAB(0x751EB200), SCL_TAB(0x75722F00), + SCL_TAB(0x75C5BB00), SCL_TAB(0x76195580), SCL_TAB(0x766CFF00), + SCL_TAB(0x76C0B700), SCL_TAB(0x77147E00), SCL_TAB(0x77685400), + SCL_TAB(0x77BC3880), SCL_TAB(0x78102B80), SCL_TAB(0x78642D80), + SCL_TAB(0x78B83E00), SCL_TAB(0x790C5D00), SCL_TAB(0x79608B00), + SCL_TAB(0x79B4C780), SCL_TAB(0x7A091280), SCL_TAB(0x7A5D6C00), + SCL_TAB(0x7AB1D400), SCL_TAB(0x7B064A80), SCL_TAB(0x7B5ACF80), + SCL_TAB(0x7BAF6380), SCL_TAB(0x7C040580), SCL_TAB(0x7C58B600), + SCL_TAB(0x7CAD7500), SCL_TAB(0x7D024200), SCL_TAB(0x7D571E00), + SCL_TAB(0x7DAC0800), SCL_TAB(0x7E010080), SCL_TAB(0x7E560780), + SCL_TAB(0x7EAB1C80), SCL_TAB(0x7F004000), SCL_TAB(0x7F557200), + SCL_TAB(0x7FAAB200), SCL_TAB(0x7FFFFFFF)}; + +/** + * \brief Table representing scale factor gains. Given a scale factor sf, and a + * value pSpec[i] the gain is given by: MantissaTable[sf % 4][msb] = 2^(sf % 4) + * / (1<> 2)) The corresponding + * exponents for the values in this tables are stored in ExponentTable[sf % + * 4][msb] below. + */ +const FIXP_DBL MantissaTable[4][14] = { + {0x40000000, 0x50A28C00, 0x6597FA80, 0x40000000, 0x50A28C00, 0x6597FA80, + 0x40000000, 0x50A28C00, 0x6597FA80, 0x40000000, 0x50A28C00, 0x6597FA80, + 0x40000000, 0x50A28C00}, + {0x4C1BF800, 0x5FE44380, 0x78D0DF80, 0x4C1BF800, 0x5FE44380, 0x78D0DF80, + 0x4C1BF800, 0x5FE44380, 0x78D0DF80, 0x4C1BF800, 0x5FE44380, 0x78D0DF80, + 0x4C1BF800, 0x5FE44380}, + {0x5A827980, 0x7208F800, 0x47D66B00, 0x5A827980, 0x7208F800, 0x47D66B00, + 0x5A827980, 0x7208F800, 0x47D66B00, 0x5A827980, 0x7208F800, 0x47D66B00, + 0x5A827980, 0x7208F800}, + {0x6BA27E80, 0x43CE3E80, 0x556E0400, 0x6BA27E80, 0x43CE3E80, 0x556E0400, + 0x6BA27E80, 0x43CE3E80, 0x556E0400, 0x6BA27E80, 0x43CE3E80, 0x556E0400, + 0x6BA27E80, 0x43CE3E80}}; + +const SCHAR ExponentTable[4][14] = { + {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18}, + {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18}, + {1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18}, + {1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19}}; + +/* 41 scfbands */ +static const SHORT sfb_96_1024[42] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, + 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 156, 172, 188, 212, + 240, 276, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024}; +/* 12 scfbands */ +static const SHORT sfb_96_128[13] = {0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 128}; + +/* 47 scfbands*/ +static const SHORT sfb_64_1024[48] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 48, 52, 56, 64, 72, 80, 88, 100, 112, 124, 140, 156, + 172, 192, 216, 240, 268, 304, 344, 384, 424, 464, 504, 544, + 584, 624, 664, 704, 744, 784, 824, 864, 904, 944, 984, 1024}; + +/* 12 scfbands */ +static const SHORT sfb_64_128[13] = {0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 128}; + +/* 49 scfbands */ +static const SHORT sfb_48_1024[50] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, + 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, + 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, + 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 1024}; +/* 14 scfbands */ +static const SHORT sfb_48_128[15] = {0, 4, 8, 12, 16, 20, 28, 36, + 44, 56, 68, 80, 96, 112, 128}; + +/* 51 scfbands */ +static const SHORT sfb_32_1024[52] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, + 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, + 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, + 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960, 992, 1024}; + +/* 47 scfbands */ +static const SHORT sfb_24_1024[48] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 136, 148, + 160, 172, 188, 204, 220, 240, 260, 284, 308, 336, 364, 396, + 432, 468, 508, 552, 600, 652, 704, 768, 832, 896, 960, 1024}; + +/* 15 scfbands */ +static const SHORT sfb_24_128[16] = {0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 64, 76, 92, 108, 128}; + +/* 43 scfbands */ +static const SHORT sfb_16_1024[44] = { + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 100, 112, 124, + 136, 148, 160, 172, 184, 196, 212, 228, 244, 260, 280, 300, 320, 344, 368, + 396, 424, 456, 492, 532, 572, 616, 664, 716, 772, 832, 896, 960, 1024}; + +/* 15 scfbands */ +static const SHORT sfb_16_128[16] = {0, 4, 8, 12, 16, 20, 24, 28, + 32, 40, 48, 60, 72, 88, 108, 128}; + +/* 40 scfbands */ +static const SHORT sfb_8_1024[41] = { + 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, + 172, 188, 204, 220, 236, 252, 268, 288, 308, 328, 348, 372, 396, 420, + 448, 476, 508, 544, 580, 620, 664, 712, 764, 820, 880, 944, 1024}; + +/* 15 scfbands */ +static const SHORT sfb_8_128[16] = {0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 60, 72, 88, 108, 128}; + +static const SHORT + sfb_96_960[42] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, + 44, 48, 52, 56, 64, 72, 80, 88, 96, 108, 120, + 132, 144, 156, 172, 188, 212, 240, 276, 320, 384, 448, + 512, 576, 640, 704, 768, 832, 896, 960}; /* 40 scfbands */ + +static const SHORT sfb_96_120[13] = {0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 120}; /* 12 scfbands */ + +static const SHORT sfb_64_960[47] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 48, 52, 56, 64, 72, 80, 88, 100, 112, 124, 140, 156, + 172, 192, 216, 240, 268, 304, 344, 384, 424, 464, 504, 544, + 584, 624, 664, 704, 744, 784, 824, 864, 904, 944, 960}; /* 46 scfbands */ + +static const SHORT sfb_64_120[13] = {0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 120}; /* 12 scfbands */ + +static const SHORT sfb_48_960[50] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, + 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, + 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, + 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960}; /* 49 scfbands */ +static const SHORT sfb_48_120[15] = { + 0, 4, 8, 12, 16, 20, 28, 36, + 44, 56, 68, 80, 96, 112, 120}; /* 14 scfbands */ + +static const SHORT sfb_32_960[50] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, + 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, + 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, + 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960}; /* 49 scfbands */ + +static const SHORT sfb_24_960[47] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 136, 148, + 160, 172, 188, 204, 220, 240, 260, 284, 308, 336, 364, 396, + 432, 468, 508, 552, 600, 652, 704, 768, 832, 896, 960}; /* 46 scfbands */ + +static const SHORT sfb_24_120[16] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 64, 76, 92, 108, 120}; /* 15 scfbands */ + +static const SHORT sfb_16_960[43] = {0, 8, 16, 24, 32, 40, 48, 56, + 64, 72, 80, 88, 100, 112, 124, 136, + 148, 160, 172, 184, 196, 212, 228, 244, + 260, 280, 300, 320, 344, 368, 396, 424, + 456, 492, 532, 572, 616, 664, 716, 772, + 832, 896, 960}; /* 42 scfbands */ + +static const SHORT sfb_16_120[16] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 40, 48, 60, 72, 88, 108, 120}; /* 15 scfbands */ + +static const SHORT sfb_8_960[41] = {0, 12, 24, 36, 48, 60, 72, 84, 96, + 108, 120, 132, 144, 156, 172, 188, 204, 220, + 236, 252, 268, 288, 308, 328, 348, 372, 396, + 420, 448, 476, 508, 544, 580, 620, 664, 712, + 764, 820, 880, 944, 960}; /* 40 scfbands */ + +static const SHORT sfb_8_120[16] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 60, 72, 88, 108, 120}; /* 15 scfbands */ + +static const SHORT + sfb_96_768[] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, + 108, 120, 132, 144, 156, 172, 188, 212, 240, 276, + 320, 384, 448, 512, 576, 640, 704, 768}; /* 37 scfbands */ +static const SHORT sfb_96_96[] = {0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 96}; /* 12 scfbands */ + +static const SHORT sfb_64_768[] = + { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, + 44, 48, 52, 56, 64, 72, 80, 88, 100, 112, 124, + 140, 156, 172, 192, 216, 240, 268, 304, 344, 384, 424, + 464, 504, 544, 584, 624, 664, 704, 744, 768}; /* 41 scfbands */ + +static const SHORT sfb_64_96[] = {0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 96}; /* 12 scfbands */ + +static const SHORT + sfb_48_768[] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, + 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, + 196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, + 544, 576, 608, 640, 672, 704, 736, 768}; /* 43 scfbands */ + +static const SHORT sfb_48_96[] = {0, 4, 8, 12, 16, 20, 28, + 36, 44, 56, 68, 80, 96}; /* 12 scfbands */ + +static const SHORT + sfb_32_768[] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, + 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, + 196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, + 544, 576, 608, 640, 672, 704, 736, 768}; /* 43 scfbands */ + +static const SHORT + sfb_24_768[] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 136, 148, + 160, 172, 188, 204, 220, 240, 260, 284, 308, 336, 364, 396, + 432, 468, 508, 552, 600, 652, 704, 768}; /* 43 scfbands */ + +static const SHORT sfb_24_96[] = {0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 64, 76, 92, 96}; /* 14 scfbands */ + +static const SHORT sfb_16_768[] = {0, 8, 16, 24, 32, 40, 48, 56, 64, + 72, 80, 88, 100, 112, 124, 136, 148, 160, + 172, 184, 196, 212, 228, 244, 260, 280, 300, + 320, 344, 368, 396, 424, 456, 492, 532, 572, + 616, 664, 716, 768}; /* 39 scfbands */ + +static const SHORT sfb_16_96[] = {0, 4, 8, 12, 16, 20, 24, 28, + 32, 40, 48, 60, 72, 88, 96}; /* 14 scfbands */ + +static const SHORT + sfb_8_768[] = {0, 12, 24, 36, 48, 60, 72, 84, 96, 108, + 120, 132, 144, 156, 172, 188, 204, 220, 236, 252, + 268, 288, 308, 328, 348, 372, 396, 420, 448, 476, + 508, 544, 580, 620, 664, 712, 764, 768}; /* 37 scfbands */ + +static const SHORT sfb_8_96[] = {0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 60, 72, 88, 96}; /* 14 scfbands */ + +static const SHORT sfb_48_512[37] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, + 52, 56, 60, 68, 76, 84, 92, 100, 112, 124, 136, 148, 164, + 184, 208, 236, 268, 300, 332, 364, 396, 428, 460, 512}; /* 36 scfbands */ +static const SHORT + sfb_32_512[38] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, + 108, 120, 132, 144, 160, 176, 192, 212, 236, 260, + 288, 320, 352, 384, 416, 448, 480, 512}; /* 37 scfbands */ +static const SHORT sfb_24_512[32] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, + 44, 52, 60, 68, 80, 92, 104, 120, 140, 164, 192, + 224, 256, 288, 320, 352, 384, 416, 448, 480, 512}; /* 31 scfbands */ + +static const SHORT sfb_48_480[36] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, + 52, 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 156, 172, + 188, 212, 240, 272, 304, 336, 368, 400, 432, 480}; /* 35 scfbands */ +static const SHORT + sfb_32_480[38] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 60, 64, 72, 80, 88, + 96, 104, 112, 124, 136, 148, 164, 180, 200, 224, + 256, 288, 320, 352, 384, 416, 448, 480}; /* 37 scfbands */ +static const SHORT sfb_24_480[31] = + {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, + 44, 52, 60, 68, 80, 92, 104, 120, 140, 164, 192, + 224, 256, 288, 320, 352, 384, 416, 448, 480}; /* 30 scfbands */ + +const SFB_INFO sfbOffsetTables[5][16] = {{ + {sfb_96_1024, sfb_96_128, 41, 12}, + {sfb_96_1024, sfb_96_128, 41, 12}, + {sfb_64_1024, sfb_64_128, 47, 12}, + {sfb_48_1024, sfb_48_128, 49, 14}, + {sfb_48_1024, sfb_48_128, 49, 14}, + {sfb_32_1024, sfb_48_128, 51, 14}, + {sfb_24_1024, sfb_24_128, 47, 15}, + {sfb_24_1024, sfb_24_128, 47, 15}, + {sfb_16_1024, sfb_16_128, 43, 15}, + {sfb_16_1024, sfb_16_128, 43, 15}, + {sfb_16_1024, sfb_16_128, 43, 15}, + {sfb_8_1024, sfb_8_128, 40, 15}, + {sfb_8_1024, sfb_8_128, 40, 15}, + }, + { + {sfb_96_960, sfb_96_120, 40, 12}, + {sfb_96_960, sfb_96_120, 40, 12}, + {sfb_64_960, sfb_64_120, 46, 12}, + {sfb_48_960, sfb_48_120, 49, 14}, + {sfb_48_960, sfb_48_120, 49, 14}, + {sfb_32_960, sfb_48_120, 49, 14}, + {sfb_24_960, sfb_24_120, 46, 15}, + {sfb_24_960, sfb_24_120, 46, 15}, + {sfb_16_960, sfb_16_120, 42, 15}, + {sfb_16_960, sfb_16_120, 42, 15}, + {sfb_16_960, sfb_16_120, 42, 15}, + {sfb_8_960, sfb_8_120, 40, 15}, + {sfb_8_960, sfb_8_120, 40, 15}, + }, + { + {sfb_96_768, sfb_96_96, 37, 12}, + {sfb_96_768, sfb_96_96, 37, 12}, + {sfb_64_768, sfb_64_96, 41, 12}, + {sfb_48_768, sfb_48_96, 43, 12}, + {sfb_48_768, sfb_48_96, 43, 12}, + {sfb_32_768, sfb_48_96, 43, 12}, + {sfb_24_768, sfb_24_96, 43, 14}, + {sfb_24_768, sfb_24_96, 43, 14}, + {sfb_16_768, sfb_16_96, 39, 14}, + {sfb_16_768, sfb_16_96, 39, 14}, + {sfb_16_768, sfb_16_96, 39, 14}, + {sfb_8_768, sfb_8_96, 37, 14}, + {sfb_8_768, sfb_8_96, 37, 14}, + }, + { + {sfb_48_512, NULL, 36, 0}, + {sfb_48_512, NULL, 36, 0}, + {sfb_48_512, NULL, 36, 0}, + {sfb_48_512, NULL, 36, 0}, + {sfb_48_512, NULL, 36, 0}, + {sfb_32_512, NULL, 37, 0}, + {sfb_24_512, NULL, 31, 0}, + {sfb_24_512, NULL, 31, 0}, + {sfb_24_512, NULL, 31, 0}, + {sfb_24_512, NULL, 31, 0}, + {sfb_24_512, NULL, 31, 0}, + {sfb_24_512, NULL, 31, 0}, + {sfb_24_512, NULL, 31, 0}, + }, + { + {sfb_48_480, NULL, 35, 0}, + {sfb_48_480, NULL, 35, 0}, + {sfb_48_480, NULL, 35, 0}, + {sfb_48_480, NULL, 35, 0}, + {sfb_48_480, NULL, 35, 0}, + {sfb_32_480, NULL, 37, 0}, + {sfb_24_480, NULL, 30, 0}, + {sfb_24_480, NULL, 30, 0}, + {sfb_24_480, NULL, 30, 0}, + {sfb_24_480, NULL, 30, 0}, + {sfb_24_480, NULL, 30, 0}, + {sfb_24_480, NULL, 30, 0}, + {sfb_24_480, NULL, 30, 0}, + }}; + +/*# don't use 1 bit hufman tables */ +/* + MPEG-2 AAC 2 BITS parallel Hufman Tables + + Bit 0: = 1=ENDNODE, 0=INDEX + Bit 1: = CODEWORD LEN MOD 2 + Bit 2..9: = VALUE/REF Tables 1..10,SCL + Bit 2..11: = VALUE/REF Table 11 +*/ +const USHORT HuffmanCodeBook_1[51][4] = { + {0x0157, 0x0157, 0x0004, 0x0018}, {0x0008, 0x000c, 0x0010, 0x0014}, + {0x015b, 0x015b, 0x0153, 0x0153}, {0x0057, 0x0057, 0x0167, 0x0167}, + {0x0257, 0x0257, 0x0117, 0x0117}, {0x0197, 0x0197, 0x0147, 0x0147}, + {0x001c, 0x0030, 0x0044, 0x0058}, {0x0020, 0x0024, 0x0028, 0x002c}, + {0x014b, 0x014b, 0x0163, 0x0163}, {0x0217, 0x0217, 0x0127, 0x0127}, + {0x0187, 0x0187, 0x0097, 0x0097}, {0x016b, 0x016b, 0x0017, 0x0017}, + {0x0034, 0x0038, 0x003c, 0x0040}, {0x0143, 0x0143, 0x0107, 0x0107}, + {0x011b, 0x011b, 0x0067, 0x0067}, {0x0193, 0x0193, 0x0297, 0x0297}, + {0x019b, 0x019b, 0x0247, 0x0247}, {0x0048, 0x004c, 0x0050, 0x0054}, + {0x01a7, 0x01a7, 0x0267, 0x0267}, {0x0113, 0x0113, 0x025b, 0x025b}, + {0x0053, 0x0053, 0x005b, 0x005b}, {0x0253, 0x0253, 0x0047, 0x0047}, + {0x005c, 0x0070, 0x0084, 0x0098}, {0x0060, 0x0064, 0x0068, 0x006c}, + {0x012b, 0x012b, 0x0123, 0x0123}, {0x018b, 0x018b, 0x00a7, 0x00a7}, + {0x0227, 0x0227, 0x0287, 0x0287}, {0x0087, 0x0087, 0x010b, 0x010b}, + {0x0074, 0x0078, 0x007c, 0x0080}, {0x021b, 0x021b, 0x0027, 0x0027}, + {0x01a3, 0x01a3, 0x0093, 0x0093}, {0x0183, 0x0183, 0x0207, 0x0207}, + {0x024b, 0x024b, 0x004b, 0x004b}, {0x0088, 0x008c, 0x0090, 0x0094}, + {0x0063, 0x0063, 0x0103, 0x0103}, {0x0007, 0x0007, 0x02a7, 0x02a7}, + {0x009b, 0x009b, 0x026b, 0x026b}, {0x0263, 0x0263, 0x01ab, 0x01ab}, + {0x009c, 0x00a0, 0x00a4, 0x00b8}, {0x0241, 0x0011, 0x0069, 0x0019}, + {0x0211, 0x0041, 0x0291, 0x0299}, {0x00a8, 0x00ac, 0x00b0, 0x00b4}, + {0x008b, 0x008b, 0x0223, 0x0223}, {0x00a3, 0x00a3, 0x020b, 0x020b}, + {0x02ab, 0x02ab, 0x0283, 0x0283}, {0x002b, 0x002b, 0x0083, 0x0083}, + {0x00bc, 0x00c0, 0x00c4, 0x00c8}, {0x0003, 0x0003, 0x022b, 0x022b}, + {0x028b, 0x028b, 0x02a3, 0x02a3}, {0x0023, 0x0023, 0x0203, 0x0203}, + {0x000b, 0x000b, 0x00ab, 0x00ab}}; + +const USHORT HuffmanCodeBook_2[39][4] = { + {0x0004, 0x000c, 0x0020, 0x0034}, {0x0157, 0x0157, 0x0159, 0x0008}, + {0x0153, 0x0153, 0x0257, 0x0257}, {0x0010, 0x0014, 0x0018, 0x001c}, + {0x0117, 0x0117, 0x0057, 0x0057}, {0x0147, 0x0147, 0x0197, 0x0197}, + {0x0167, 0x0167, 0x0185, 0x0161}, {0x0125, 0x0095, 0x0065, 0x0215}, + {0x0024, 0x0028, 0x002c, 0x0030}, {0x0051, 0x0149, 0x0119, 0x0141}, + {0x0015, 0x0199, 0x0259, 0x0245}, {0x0191, 0x0265, 0x0105, 0x0251}, + {0x0045, 0x0111, 0x0169, 0x01a5}, {0x0038, 0x0044, 0x0058, 0x006c}, + {0x0295, 0x0059, 0x003c, 0x0040}, {0x0227, 0x0227, 0x021b, 0x021b}, + {0x0123, 0x0123, 0x0087, 0x0087}, {0x0048, 0x004c, 0x0050, 0x0054}, + {0x018b, 0x018b, 0x006b, 0x006b}, {0x029b, 0x029b, 0x01a3, 0x01a3}, + {0x0207, 0x0207, 0x01ab, 0x01ab}, {0x0093, 0x0093, 0x0103, 0x0103}, + {0x005c, 0x0060, 0x0064, 0x0068}, {0x0213, 0x0213, 0x010b, 0x010b}, + {0x012b, 0x012b, 0x0249, 0x0061}, {0x0181, 0x0291, 0x0241, 0x0041}, + {0x0005, 0x0099, 0x0019, 0x0025}, {0x0070, 0x0074, 0x0078, 0x0088}, + {0x02a5, 0x0261, 0x0011, 0x00a5}, {0x0049, 0x0285, 0x0269, 0x0089}, + {0x0221, 0x007c, 0x0080, 0x0084}, {0x020b, 0x020b, 0x0003, 0x0003}, + {0x00a3, 0x00a3, 0x02a3, 0x02a3}, {0x02ab, 0x02ab, 0x0083, 0x0083}, + {0x008c, 0x0090, 0x0094, 0x0098}, {0x028b, 0x028b, 0x0023, 0x0023}, + {0x0283, 0x0283, 0x002b, 0x002b}, {0x000b, 0x000b, 0x0203, 0x0203}, + {0x022b, 0x022b, 0x00ab, 0x00ab}}; + +const USHORT HuffmanCodeBook_3[39][4] = { + {0x0003, 0x0003, 0x0004, 0x0008}, {0x0005, 0x0101, 0x0011, 0x0041}, + {0x000c, 0x0010, 0x0014, 0x0020}, {0x0017, 0x0017, 0x0143, 0x0143}, + {0x0051, 0x0111, 0x0045, 0x0151}, {0x0105, 0x0055, 0x0018, 0x001c}, + {0x0157, 0x0157, 0x0147, 0x0147}, {0x0117, 0x0117, 0x0009, 0x0201}, + {0x0024, 0x002c, 0x0040, 0x0054}, {0x0241, 0x0019, 0x0065, 0x0028}, + {0x0183, 0x0183, 0x0193, 0x0193}, {0x0030, 0x0034, 0x0038, 0x003c}, + {0x0027, 0x0027, 0x0253, 0x0253}, {0x005b, 0x005b, 0x0083, 0x0083}, + {0x0063, 0x0063, 0x0093, 0x0093}, {0x0023, 0x0023, 0x0213, 0x0213}, + {0x0044, 0x0048, 0x004c, 0x0050}, {0x004b, 0x004b, 0x0167, 0x0167}, + {0x0163, 0x0163, 0x0097, 0x0097}, {0x0197, 0x0197, 0x0125, 0x0085}, + {0x0185, 0x0121, 0x0159, 0x0255}, {0x0058, 0x005c, 0x0060, 0x0070}, + {0x0119, 0x0245, 0x0281, 0x0291}, {0x0069, 0x00a5, 0x0205, 0x0109}, + {0x01a1, 0x0064, 0x0068, 0x006c}, {0x002b, 0x002b, 0x01a7, 0x01a7}, + {0x0217, 0x0217, 0x014b, 0x014b}, {0x0297, 0x0297, 0x016b, 0x016b}, + {0x0074, 0x0078, 0x007c, 0x0080}, {0x00a3, 0x00a3, 0x0263, 0x0263}, + {0x0285, 0x0129, 0x0099, 0x00a9}, {0x02a1, 0x01a9, 0x0199, 0x0265}, + {0x02a5, 0x0084, 0x0088, 0x008c}, {0x0223, 0x0223, 0x008b, 0x008b}, + {0x0227, 0x0227, 0x0189, 0x0259}, {0x0219, 0x0090, 0x0094, 0x0098}, + {0x02ab, 0x02ab, 0x026b, 0x026b}, {0x029b, 0x029b, 0x024b, 0x024b}, + {0x020b, 0x020b, 0x0229, 0x0289}}; + +const USHORT HuffmanCodeBook_4[38][4] = { + {0x0004, 0x0008, 0x000c, 0x0018}, {0x0155, 0x0151, 0x0115, 0x0055}, + {0x0145, 0x0005, 0x0015, 0x0001}, {0x0141, 0x0045, 0x0010, 0x0014}, + {0x0107, 0x0107, 0x0053, 0x0053}, {0x0103, 0x0103, 0x0113, 0x0113}, + {0x001c, 0x0020, 0x0034, 0x0048}, {0x0043, 0x0043, 0x0013, 0x0013}, + {0x0024, 0x0028, 0x002c, 0x0030}, {0x015b, 0x015b, 0x0197, 0x0197}, + {0x0167, 0x0167, 0x0257, 0x0257}, {0x005b, 0x005b, 0x011b, 0x011b}, + {0x0067, 0x0067, 0x014b, 0x014b}, {0x0038, 0x003c, 0x0040, 0x0044}, + {0x0193, 0x0193, 0x0251, 0x0095}, {0x0161, 0x0245, 0x0125, 0x0215}, + {0x0185, 0x0019, 0x0049, 0x0025}, {0x0109, 0x0211, 0x0061, 0x0241}, + {0x004c, 0x0050, 0x0058, 0x006c}, {0x0091, 0x0121, 0x0205, 0x0181}, + {0x0085, 0x0009, 0x0201, 0x0054}, {0x0023, 0x0023, 0x0083, 0x0083}, + {0x005c, 0x0060, 0x0064, 0x0068}, {0x01a7, 0x01a7, 0x016b, 0x016b}, + {0x019b, 0x019b, 0x0297, 0x0297}, {0x0267, 0x0267, 0x025b, 0x025b}, + {0x00a5, 0x0069, 0x0099, 0x01a1}, {0x0070, 0x0074, 0x0078, 0x0084}, + {0x0291, 0x0129, 0x0261, 0x0189}, {0x0285, 0x01a9, 0x0225, 0x0249}, + {0x0219, 0x02a5, 0x007c, 0x0080}, {0x029b, 0x029b, 0x026b, 0x026b}, + {0x00a3, 0x00a3, 0x002b, 0x002b}, {0x0088, 0x008c, 0x0090, 0x0094}, + {0x0283, 0x0283, 0x008b, 0x008b}, {0x0223, 0x0223, 0x020b, 0x020b}, + {0x02ab, 0x02ab, 0x02a3, 0x02a3}, {0x00ab, 0x00ab, 0x0229, 0x0289}}; + +const USHORT HuffmanCodeBook_5[41][4] = { + {0x0113, 0x0113, 0x0004, 0x0008}, {0x010d, 0x0115, 0x0151, 0x00d1}, + {0x000c, 0x0010, 0x0014, 0x0028}, {0x00d7, 0x00d7, 0x014f, 0x014f}, + {0x00cf, 0x00cf, 0x0157, 0x0157}, {0x0018, 0x001c, 0x0020, 0x0024}, + {0x010b, 0x010b, 0x0193, 0x0193}, {0x011b, 0x011b, 0x0093, 0x0093}, + {0x00c9, 0x0159, 0x008d, 0x0195}, {0x0149, 0x00d9, 0x018d, 0x0095}, + {0x002c, 0x0030, 0x0044, 0x0058}, {0x0105, 0x011d, 0x0051, 0x01d1}, + {0x0034, 0x0038, 0x003c, 0x0040}, {0x00c7, 0x00c7, 0x01d7, 0x01d7}, + {0x015f, 0x015f, 0x004f, 0x004f}, {0x0147, 0x0147, 0x00df, 0x00df}, + {0x0057, 0x0057, 0x01cf, 0x01cf}, {0x0048, 0x004c, 0x0050, 0x0054}, + {0x018b, 0x018b, 0x019b, 0x019b}, {0x008b, 0x008b, 0x009b, 0x009b}, + {0x0085, 0x009d, 0x01c9, 0x0059}, {0x019d, 0x01d9, 0x0185, 0x0049}, + {0x005c, 0x0060, 0x0074, 0x0088}, {0x0011, 0x0101, 0x0161, 0x0121}, + {0x0064, 0x0068, 0x006c, 0x0070}, {0x00c3, 0x00c3, 0x0213, 0x0213}, + {0x00e3, 0x00e3, 0x000f, 0x000f}, {0x0217, 0x0217, 0x020f, 0x020f}, + {0x0143, 0x0143, 0x0017, 0x0017}, {0x0078, 0x007c, 0x0080, 0x0084}, + {0x005f, 0x005f, 0x0047, 0x0047}, {0x01c7, 0x01c7, 0x020b, 0x020b}, + {0x0083, 0x0083, 0x01a3, 0x01a3}, {0x001b, 0x001b, 0x021b, 0x021b}, + {0x008c, 0x0090, 0x0094, 0x0098}, {0x01df, 0x01df, 0x0183, 0x0183}, + {0x0009, 0x00a1, 0x001d, 0x0041}, {0x01c1, 0x021d, 0x0205, 0x01e1}, + {0x0061, 0x0005, 0x009c, 0x00a0}, {0x0023, 0x0023, 0x0203, 0x0203}, + {0x0223, 0x0223, 0x0003, 0x0003}}; + +const USHORT HuffmanCodeBook_6[40][4] = { + {0x0004, 0x0008, 0x000c, 0x001c}, {0x0111, 0x0115, 0x00d1, 0x0151}, + {0x010d, 0x0155, 0x014d, 0x00d5}, {0x00cd, 0x0010, 0x0014, 0x0018}, + {0x00d9, 0x0159, 0x0149, 0x00c9}, {0x0109, 0x018d, 0x0119, 0x0095}, + {0x0195, 0x0091, 0x008d, 0x0191}, {0x0020, 0x0024, 0x0038, 0x004c}, + {0x0099, 0x0189, 0x0089, 0x0199}, {0x0028, 0x002c, 0x0030, 0x0034}, + {0x0147, 0x0147, 0x015f, 0x015f}, {0x00df, 0x00df, 0x01cf, 0x01cf}, + {0x00c7, 0x00c7, 0x01d7, 0x01d7}, {0x0057, 0x0057, 0x004f, 0x004f}, + {0x003c, 0x0040, 0x0044, 0x0048}, {0x011f, 0x011f, 0x0107, 0x0107}, + {0x0053, 0x0053, 0x01d3, 0x01d3}, {0x019f, 0x019f, 0x0085, 0x01c9}, + {0x01d9, 0x009d, 0x0059, 0x0049}, {0x0050, 0x005c, 0x0070, 0x0084}, + {0x0185, 0x01dd, 0x0054, 0x0058}, {0x005f, 0x005f, 0x0047, 0x0047}, + {0x01c7, 0x01c7, 0x0017, 0x0017}, {0x0060, 0x0064, 0x0068, 0x006c}, + {0x000f, 0x000f, 0x0163, 0x0163}, {0x0143, 0x0143, 0x00c3, 0x00c3}, + {0x0217, 0x0217, 0x00e3, 0x00e3}, {0x020f, 0x020f, 0x0013, 0x0013}, + {0x0074, 0x0078, 0x007c, 0x0080}, {0x0183, 0x0183, 0x0083, 0x0083}, + {0x021b, 0x021b, 0x000b, 0x000b}, {0x0103, 0x0103, 0x01a3, 0x01a3}, + {0x00a3, 0x00a3, 0x020b, 0x020b}, {0x0088, 0x008c, 0x0090, 0x0094}, + {0x0123, 0x0123, 0x001b, 0x001b}, {0x0213, 0x0213, 0x0005, 0x0205}, + {0x001d, 0x0061, 0x021d, 0x01e1}, {0x01c1, 0x0041, 0x0098, 0x009c}, + {0x0223, 0x0223, 0x0203, 0x0203}, {0x0003, 0x0003, 0x0023, 0x0023}}; + +const USHORT HuffmanCodeBook_7[31][4] = { + {0x0003, 0x0003, 0x0004, 0x0008}, {0x0007, 0x0007, 0x0043, 0x0043}, + {0x0045, 0x000c, 0x0010, 0x0024}, {0x0049, 0x0085, 0x0009, 0x0081}, + {0x0014, 0x0018, 0x001c, 0x0020}, {0x004f, 0x004f, 0x00c7, 0x00c7}, + {0x008b, 0x008b, 0x000f, 0x000f}, {0x00c3, 0x00c3, 0x00c9, 0x008d}, + {0x0105, 0x0051, 0x0145, 0x0055}, {0x0028, 0x002c, 0x0040, 0x0054}, + {0x00cd, 0x0109, 0x0101, 0x0011}, {0x0030, 0x0034, 0x0038, 0x003c}, + {0x0093, 0x0093, 0x014b, 0x014b}, {0x0097, 0x0097, 0x0143, 0x0143}, + {0x005b, 0x005b, 0x0017, 0x0017}, {0x0187, 0x0187, 0x00d3, 0x00d3}, + {0x0044, 0x0048, 0x004c, 0x0050}, {0x014f, 0x014f, 0x010f, 0x010f}, + {0x00d7, 0x00d7, 0x018b, 0x018b}, {0x009b, 0x009b, 0x01c7, 0x01c7}, + {0x018d, 0x0181, 0x0019, 0x0111}, {0x0058, 0x005c, 0x0060, 0x0068}, + {0x005d, 0x0151, 0x009d, 0x0115}, {0x00d9, 0x01c9, 0x00dd, 0x0119}, + {0x0155, 0x0191, 0x01cd, 0x0064}, {0x001f, 0x001f, 0x01c3, 0x01c3}, + {0x006c, 0x0070, 0x0074, 0x0078}, {0x015b, 0x015b, 0x0197, 0x0197}, + {0x011f, 0x011f, 0x01d3, 0x01d3}, {0x01d7, 0x01d7, 0x015f, 0x015f}, + {0x019d, 0x0199, 0x01d9, 0x01dd}}; + +const USHORT HuffmanCodeBook_8[31][4] = { + {0x0004, 0x0008, 0x0010, 0x0024}, {0x0047, 0x0047, 0x0049, 0x0005}, + {0x0085, 0x0041, 0x0089, 0x000c}, {0x0003, 0x0003, 0x000b, 0x000b}, + {0x0014, 0x0018, 0x001c, 0x0020}, {0x0083, 0x0083, 0x004f, 0x004f}, + {0x00c7, 0x00c7, 0x008f, 0x008f}, {0x00cb, 0x00cb, 0x00cd, 0x0051}, + {0x0105, 0x0091, 0x0109, 0x000d}, {0x0028, 0x002c, 0x0040, 0x0054}, + {0x00c1, 0x00d1, 0x010d, 0x0095}, {0x0030, 0x0034, 0x0038, 0x003c}, + {0x0057, 0x0057, 0x014b, 0x014b}, {0x0147, 0x0147, 0x00d7, 0x00d7}, + {0x014f, 0x014f, 0x0113, 0x0113}, {0x0117, 0x0117, 0x0103, 0x0103}, + {0x0044, 0x0048, 0x004c, 0x0050}, {0x0153, 0x0153, 0x0013, 0x0013}, + {0x018b, 0x018b, 0x009b, 0x009b}, {0x005b, 0x005b, 0x0187, 0x0187}, + {0x018d, 0x00d9, 0x0155, 0x0015}, {0x0058, 0x005c, 0x0060, 0x0068}, + {0x0119, 0x0141, 0x0191, 0x005d}, {0x009d, 0x01c9, 0x0159, 0x00dd}, + {0x01c5, 0x0195, 0x01cd, 0x0064}, {0x019b, 0x019b, 0x011f, 0x011f}, + {0x006c, 0x0070, 0x0074, 0x0078}, {0x001b, 0x001b, 0x01d3, 0x01d3}, + {0x0183, 0x0183, 0x015f, 0x015f}, {0x019f, 0x019f, 0x01db, 0x01db}, + {0x01d5, 0x001d, 0x01c1, 0x01dd}}; + +const USHORT HuffmanCodeBook_9[84][4] = { + {0x0003, 0x0003, 0x0004, 0x0008}, {0x0007, 0x0007, 0x0043, 0x0043}, + {0x0045, 0x000c, 0x0010, 0x002c}, {0x0049, 0x0085, 0x0009, 0x0081}, + {0x0014, 0x0018, 0x001c, 0x0020}, {0x004f, 0x004f, 0x008b, 0x008b}, + {0x00c7, 0x00c7, 0x000d, 0x00c1}, {0x00c9, 0x008d, 0x0105, 0x0051}, + {0x0109, 0x0145, 0x0024, 0x0028}, {0x0093, 0x0093, 0x00cf, 0x00cf}, + {0x0103, 0x0103, 0x0013, 0x0013}, {0x0030, 0x0044, 0x0058, 0x00a4}, + {0x0034, 0x0038, 0x003c, 0x0040}, {0x0057, 0x0057, 0x014b, 0x014b}, + {0x0187, 0x0187, 0x010f, 0x010f}, {0x0097, 0x0097, 0x005b, 0x005b}, + {0x00d3, 0x00d3, 0x0141, 0x0189}, {0x0048, 0x004c, 0x0050, 0x0054}, + {0x0015, 0x01c5, 0x014d, 0x0205}, {0x0061, 0x0111, 0x00d5, 0x0099}, + {0x005d, 0x0181, 0x00a1, 0x0209}, {0x018d, 0x01c9, 0x0151, 0x0065}, + {0x005c, 0x0068, 0x007c, 0x0090}, {0x0245, 0x009d, 0x0060, 0x0064}, + {0x001b, 0x001b, 0x0117, 0x0117}, {0x00db, 0x00db, 0x00e3, 0x00e3}, + {0x006c, 0x0070, 0x0074, 0x0078}, {0x01c3, 0x01c3, 0x00a7, 0x00a7}, + {0x020f, 0x020f, 0x0193, 0x0193}, {0x01cf, 0x01cf, 0x0203, 0x0203}, + {0x006b, 0x006b, 0x011b, 0x011b}, {0x0080, 0x0084, 0x0088, 0x008c}, + {0x024b, 0x024b, 0x0157, 0x0157}, {0x0023, 0x0023, 0x001f, 0x001f}, + {0x00df, 0x00df, 0x00ab, 0x00ab}, {0x00e7, 0x00e7, 0x0123, 0x0123}, + {0x0094, 0x0098, 0x009c, 0x00a0}, {0x0287, 0x0287, 0x011f, 0x011f}, + {0x015b, 0x015b, 0x0197, 0x0197}, {0x0213, 0x0213, 0x01d3, 0x01d3}, + {0x024f, 0x024f, 0x006f, 0x006f}, {0x00a8, 0x00bc, 0x00d0, 0x00f4}, + {0x00ac, 0x00b0, 0x00b4, 0x00b8}, {0x0217, 0x0217, 0x0027, 0x0027}, + {0x0163, 0x0163, 0x00e9, 0x0289}, {0x0241, 0x00ad, 0x0125, 0x0199}, + {0x0071, 0x0251, 0x01a1, 0x02c5}, {0x00c0, 0x00c4, 0x00c8, 0x00cc}, + {0x0165, 0x0129, 0x01d5, 0x015d}, {0x02c9, 0x0305, 0x00b1, 0x00ed}, + {0x028d, 0x0255, 0x01d9, 0x01e1}, {0x012d, 0x0281, 0x019d, 0x00f1}, + {0x00d4, 0x00d8, 0x00dc, 0x00e0}, {0x0029, 0x0169, 0x0291, 0x0219}, + {0x0309, 0x01a5, 0x01e5, 0x02d1}, {0x002d, 0x0259, 0x02cd, 0x0295}, + {0x00e4, 0x00e8, 0x00ec, 0x00f0}, {0x0223, 0x0223, 0x021f, 0x021f}, + {0x0173, 0x0173, 0x030f, 0x030f}, {0x016f, 0x016f, 0x01df, 0x01df}, + {0x0133, 0x0133, 0x01af, 0x01af}, {0x00f8, 0x010c, 0x0120, 0x0134}, + {0x00fc, 0x0100, 0x0104, 0x0108}, {0x01ab, 0x01ab, 0x0313, 0x0313}, + {0x025f, 0x025f, 0x02d7, 0x02d7}, {0x02c3, 0x02c3, 0x01b3, 0x01b3}, + {0x029b, 0x029b, 0x0033, 0x0033}, {0x0110, 0x0114, 0x0118, 0x011c}, + {0x01eb, 0x01eb, 0x0317, 0x0317}, {0x029f, 0x029f, 0x0227, 0x0227}, + {0x0303, 0x0303, 0x01ef, 0x01ef}, {0x0263, 0x0263, 0x0267, 0x0267}, + {0x0124, 0x0128, 0x012c, 0x0130}, {0x022b, 0x022b, 0x02df, 0x02df}, + {0x01f3, 0x01f3, 0x02db, 0x02db}, {0x02e3, 0x02e3, 0x022f, 0x022f}, + {0x031f, 0x031f, 0x031b, 0x031b}, {0x0138, 0x013c, 0x0140, 0x0144}, + {0x02a1, 0x0269, 0x0321, 0x02a5}, {0x02e5, 0x0325, 0x02e9, 0x0271}, + {0x02a9, 0x026d, 0x0231, 0x02ad}, {0x02b1, 0x02f1, 0x0148, 0x014c}, + {0x032b, 0x032b, 0x02ef, 0x02ef}, {0x032f, 0x032f, 0x0333, 0x0333}}; + +const USHORT HuffmanCodeBook_10[82][4] = { + {0x0004, 0x000c, 0x0020, 0x004c}, {0x0045, 0x0085, 0x0049, 0x0008}, + {0x008b, 0x008b, 0x0007, 0x0007}, {0x0010, 0x0014, 0x0018, 0x001c}, + {0x0043, 0x0043, 0x00c7, 0x00c7}, {0x008f, 0x008f, 0x004f, 0x004f}, + {0x00cb, 0x00cb, 0x00cf, 0x00cf}, {0x0009, 0x0081, 0x0109, 0x0091}, + {0x0024, 0x0028, 0x002c, 0x0038}, {0x0105, 0x0051, 0x0001, 0x00d1}, + {0x010d, 0x000d, 0x00c1, 0x0111}, {0x0149, 0x0095, 0x0030, 0x0034}, + {0x0147, 0x0147, 0x0057, 0x0057}, {0x00d7, 0x00d7, 0x014f, 0x014f}, + {0x003c, 0x0040, 0x0044, 0x0048}, {0x0117, 0x0117, 0x0153, 0x0153}, + {0x009b, 0x009b, 0x018b, 0x018b}, {0x00db, 0x00db, 0x0013, 0x0013}, + {0x005b, 0x005b, 0x0103, 0x0103}, {0x0050, 0x0064, 0x0078, 0x00c0}, + {0x0054, 0x0058, 0x005c, 0x0060}, {0x0187, 0x0187, 0x018f, 0x018f}, + {0x0157, 0x0157, 0x011b, 0x011b}, {0x0193, 0x0193, 0x0159, 0x009d}, + {0x01cd, 0x01c9, 0x0195, 0x00a1}, {0x0068, 0x006c, 0x0070, 0x0074}, + {0x00dd, 0x0015, 0x005d, 0x0141}, {0x0061, 0x01c5, 0x00e1, 0x011d}, + {0x01d1, 0x0209, 0x0199, 0x015d}, {0x0205, 0x020d, 0x0121, 0x0211}, + {0x007c, 0x0084, 0x0098, 0x00ac}, {0x01d5, 0x0161, 0x0215, 0x0080}, + {0x019f, 0x019f, 0x01db, 0x01db}, {0x0088, 0x008c, 0x0090, 0x0094}, + {0x00a7, 0x00a7, 0x001b, 0x001b}, {0x021b, 0x021b, 0x00e7, 0x00e7}, + {0x024f, 0x024f, 0x0067, 0x0067}, {0x024b, 0x024b, 0x0183, 0x0183}, + {0x009c, 0x00a0, 0x00a4, 0x00a8}, {0x01a3, 0x01a3, 0x0127, 0x0127}, + {0x0253, 0x0253, 0x00ab, 0x00ab}, {0x0247, 0x0247, 0x01df, 0x01df}, + {0x01e3, 0x01e3, 0x0167, 0x0167}, {0x00b0, 0x00b4, 0x00b8, 0x00bc}, + {0x021f, 0x021f, 0x00eb, 0x00eb}, {0x0257, 0x0257, 0x012b, 0x012b}, + {0x028b, 0x028b, 0x006b, 0x006b}, {0x028f, 0x028f, 0x01a7, 0x01a7}, + {0x00c4, 0x00d8, 0x00ec, 0x0100}, {0x00c8, 0x00cc, 0x00d0, 0x00d4}, + {0x025b, 0x025b, 0x0023, 0x0023}, {0x0293, 0x0293, 0x001f, 0x001f}, + {0x00af, 0x00af, 0x025d, 0x00ed}, {0x01a9, 0x0285, 0x006d, 0x01e5}, + {0x00dc, 0x00e0, 0x00e4, 0x00e8}, {0x01c1, 0x0221, 0x0169, 0x02cd}, + {0x0295, 0x0261, 0x016d, 0x0201}, {0x012d, 0x02c9, 0x029d, 0x0299}, + {0x01e9, 0x02d1, 0x02c5, 0x00b1}, {0x00f0, 0x00f4, 0x00f8, 0x00fc}, + {0x0225, 0x00f1, 0x01ad, 0x02d5}, {0x0131, 0x01ed, 0x0171, 0x030d}, + {0x02d9, 0x0025, 0x0229, 0x0029}, {0x0071, 0x0241, 0x0311, 0x0265}, + {0x0104, 0x010c, 0x0120, 0x0134}, {0x01b1, 0x0309, 0x02a1, 0x0108}, + {0x02a7, 0x02a7, 0x0307, 0x0307}, {0x0110, 0x0114, 0x0118, 0x011c}, + {0x022f, 0x022f, 0x01f3, 0x01f3}, {0x02df, 0x02df, 0x0317, 0x0317}, + {0x031b, 0x031b, 0x026b, 0x026b}, {0x02e3, 0x02e3, 0x0233, 0x0233}, + {0x0124, 0x0128, 0x012c, 0x0130}, {0x0283, 0x0283, 0x031f, 0x031f}, + {0x002f, 0x002f, 0x02ab, 0x02ab}, {0x026f, 0x026f, 0x02af, 0x02af}, + {0x02c3, 0x02c3, 0x02ef, 0x02ef}, {0x0138, 0x013c, 0x0140, 0x0144}, + {0x02e7, 0x02e7, 0x02eb, 0x02eb}, {0x0033, 0x0033, 0x0323, 0x0323}, + {0x0271, 0x0329, 0x0325, 0x032d}, {0x02f1, 0x0301, 0x02b1, 0x0331}}; + +const USHORT HuffmanCodeBook_11[152][4] = { + {0x0004, 0x0010, 0x0038, 0x008c}, {0x0001, 0x0085, 0x0008, 0x000c}, + {0x0843, 0x0843, 0x0007, 0x0007}, {0x0083, 0x0083, 0x008b, 0x008b}, + {0x0014, 0x0018, 0x001c, 0x0024}, {0x0107, 0x0107, 0x010b, 0x010b}, + {0x0185, 0x008d, 0x010d, 0x0009}, {0x0189, 0x0101, 0x018d, 0x0020}, + {0x0093, 0x0093, 0x0207, 0x0207}, {0x0028, 0x002c, 0x0030, 0x0034}, + {0x0113, 0x0113, 0x020b, 0x020b}, {0x0193, 0x0193, 0x020f, 0x020f}, + {0x000f, 0x000f, 0x0183, 0x0183}, {0x0097, 0x0097, 0x0117, 0x0117}, + {0x003c, 0x0050, 0x0064, 0x0078}, {0x0040, 0x0044, 0x0048, 0x004c}, + {0x028b, 0x028b, 0x0213, 0x0213}, {0x0287, 0x0287, 0x0197, 0x0197}, + {0x028f, 0x028f, 0x0217, 0x0217}, {0x0291, 0x0119, 0x0309, 0x0099}, + {0x0054, 0x0058, 0x005c, 0x0060}, {0x0199, 0x030d, 0x0305, 0x0811}, + {0x080d, 0x02c1, 0x01c1, 0x0241}, {0x0219, 0x0341, 0x0011, 0x0311}, + {0x0201, 0x0809, 0x0295, 0x0815}, {0x0068, 0x006c, 0x0070, 0x0074}, + {0x03c1, 0x0141, 0x0441, 0x0389}, {0x011d, 0x038d, 0x0299, 0x0315}, + {0x0819, 0x0541, 0x019d, 0x009d}, {0x04c1, 0x081d, 0x0805, 0x0385}, + {0x007c, 0x0080, 0x0084, 0x0088}, {0x0391, 0x05c1, 0x021d, 0x0641}, + {0x0821, 0x00c1, 0x0319, 0x0825}, {0x0409, 0x0395, 0x0829, 0x06c1}, + {0x01a1, 0x0121, 0x040d, 0x0015}, {0x0090, 0x00c8, 0x011c, 0x0170}, + {0x0094, 0x0098, 0x00a0, 0x00b4}, {0x0741, 0x082d, 0x029d, 0x0411}, + {0x0399, 0x031d, 0x0281, 0x009c}, {0x0223, 0x0223, 0x07c3, 0x07c3}, + {0x00a4, 0x00a8, 0x00ac, 0x00b0}, {0x0833, 0x0833, 0x0407, 0x0407}, + {0x00a3, 0x00a3, 0x083b, 0x083b}, {0x0417, 0x0417, 0x0837, 0x0837}, + {0x048f, 0x048f, 0x02a3, 0x02a3}, {0x00b8, 0x00bc, 0x00c0, 0x00c4}, + {0x039f, 0x039f, 0x048b, 0x048b}, {0x0323, 0x0323, 0x0127, 0x0127}, + {0x01a7, 0x01a7, 0x083f, 0x083f}, {0x0493, 0x0493, 0x041b, 0x041b}, + {0x00cc, 0x00e0, 0x00f4, 0x0108}, {0x00d0, 0x00d4, 0x00d8, 0x00dc}, + {0x001b, 0x001b, 0x0227, 0x0227}, {0x0497, 0x0497, 0x03a3, 0x03a3}, + {0x041f, 0x041f, 0x0487, 0x0487}, {0x01ab, 0x01ab, 0x0303, 0x0303}, + {0x00e4, 0x00e8, 0x00ec, 0x00f0}, {0x012b, 0x012b, 0x00a7, 0x00a7}, + {0x02a7, 0x02a7, 0x0513, 0x0513}, {0x050b, 0x050b, 0x0327, 0x0327}, + {0x050f, 0x050f, 0x049b, 0x049b}, {0x00f8, 0x00fc, 0x0100, 0x0104}, + {0x022b, 0x022b, 0x0423, 0x0423}, {0x02ab, 0x02ab, 0x03a7, 0x03a7}, + {0x01af, 0x01af, 0x0507, 0x0507}, {0x001f, 0x001f, 0x032b, 0x032b}, + {0x010c, 0x0110, 0x0114, 0x0118}, {0x049f, 0x049f, 0x058f, 0x058f}, + {0x0517, 0x0517, 0x00ab, 0x00ab}, {0x0593, 0x0593, 0x012f, 0x012f}, + {0x0137, 0x0137, 0x051b, 0x051b}, {0x0120, 0x0134, 0x0148, 0x015c}, + {0x0124, 0x0128, 0x012c, 0x0130}, {0x01b7, 0x01b7, 0x058b, 0x058b}, + {0x0043, 0x0043, 0x0597, 0x0597}, {0x02af, 0x02af, 0x022d, 0x0425}, + {0x051d, 0x04a1, 0x0801, 0x0691}, {0x0138, 0x013c, 0x0140, 0x0144}, + {0x0381, 0x068d, 0x032d, 0x00b5}, {0x0235, 0x01b1, 0x0689, 0x02b5}, + {0x0521, 0x0599, 0x0429, 0x03a9}, {0x0139, 0x0231, 0x0585, 0x0611}, + {0x014c, 0x0150, 0x0154, 0x0158}, {0x00ad, 0x060d, 0x0685, 0x0131}, + {0x059d, 0x070d, 0x0615, 0x0695}, {0x0239, 0x0711, 0x03ad, 0x01b9}, + {0x02b1, 0x0335, 0x0331, 0x0021}, {0x0160, 0x0164, 0x0168, 0x016c}, + {0x042d, 0x0609, 0x04a5, 0x02b9}, {0x0699, 0x0529, 0x013d, 0x05a1}, + {0x0525, 0x0339, 0x04a9, 0x0715}, {0x04ad, 0x00b9, 0x0709, 0x0619}, + {0x0174, 0x0188, 0x019c, 0x01cc}, {0x0178, 0x017c, 0x0180, 0x0184}, + {0x0605, 0x0435, 0x0401, 0x03b5}, {0x061d, 0x03b1, 0x069d, 0x01bd}, + {0x00b1, 0x0719, 0x0789, 0x02bd}, {0x023d, 0x0705, 0x05a5, 0x0791}, + {0x018c, 0x0190, 0x0194, 0x0198}, {0x03b9, 0x06a1, 0x04b5, 0x0621}, + {0x0795, 0x078d, 0x05a9, 0x052d}, {0x0431, 0x033d, 0x03bd, 0x0721}, + {0x00bd, 0x071d, 0x0025, 0x0481}, {0x01a0, 0x01a4, 0x01a8, 0x01b8}, + {0x06a5, 0x0625, 0x04b1, 0x0439}, {0x06a9, 0x04b9, 0x0531, 0x0799}, + {0x079d, 0x01ac, 0x01b0, 0x01b4}, {0x0727, 0x0727, 0x043f, 0x043f}, + {0x05af, 0x05af, 0x072f, 0x072f}, {0x0787, 0x0787, 0x062b, 0x062b}, + {0x01bc, 0x01c0, 0x01c4, 0x01c8}, {0x072b, 0x072b, 0x05b7, 0x05b7}, + {0x0537, 0x0537, 0x06af, 0x06af}, {0x062f, 0x062f, 0x07a3, 0x07a3}, + {0x05bb, 0x05bb, 0x0637, 0x0637}, {0x01d0, 0x01e4, 0x01f8, 0x020c}, + {0x01d4, 0x01d8, 0x01dc, 0x01e0}, {0x06b3, 0x06b3, 0x04bf, 0x04bf}, + {0x053b, 0x053b, 0x002b, 0x002b}, {0x05b3, 0x05b3, 0x07a7, 0x07a7}, + {0x0503, 0x0503, 0x0633, 0x0633}, {0x01e8, 0x01ec, 0x01f0, 0x01f4}, + {0x002f, 0x002f, 0x0733, 0x0733}, {0x07ab, 0x07ab, 0x06b7, 0x06b7}, + {0x0683, 0x0683, 0x063b, 0x063b}, {0x053f, 0x053f, 0x05bf, 0x05bf}, + {0x01fc, 0x0200, 0x0204, 0x0208}, {0x07af, 0x07af, 0x06bb, 0x06bb}, + {0x0037, 0x0037, 0x0583, 0x0583}, {0x0737, 0x0737, 0x063f, 0x063f}, + {0x06bf, 0x06bf, 0x07b3, 0x07b3}, {0x0210, 0x0214, 0x0218, 0x021c}, + {0x003b, 0x003b, 0x073b, 0x073b}, {0x07b7, 0x07b7, 0x0033, 0x0033}, + {0x07bb, 0x07bb, 0x0701, 0x0601}, {0x073d, 0x003d, 0x0781, 0x07bd}, + {0x0118, 0x0117, 0x0100, 0x0109}, {0x05a5, 0x05a1, 0x05b7, 0x0513}, + {0x08f9, 0x08ff, 0x0821, 0x08ff}, {0x084f, 0x08ff, 0x08bc, 0x08ff}, + {0x0815, 0x08ff, 0x0837, 0x08ff}, {0x080d, 0x08ff, 0x085f, 0x08ff}, + {0x084a, 0x08ff, 0x087d, 0x08ff}, {0x08ff, 0x08ff, 0x08a8, 0x08ff}, + {0x0815, 0x08ff, 0x083f, 0x08ff}, {0x0830, 0x08ff, 0x0894, 0x08ff}, + {0x08d4, 0x08ff, 0x0825, 0x08ff}, {0x08ef, 0x08ff, 0x083f, 0x08ff}, + {0x0809, 0x08ff, 0x08fc, 0x08ff}, {0x0842, 0x08ff, 0x08b3, 0x08ff}, + {0x070d, 0x07a9, 0x060e, 0x06e2}, {0x06c7, 0x06d0, 0x04b2, 0x0407}}; + +const USHORT HuffmanCodeBook_SCL[65][4] = { + {0x00f3, 0x00f3, 0x0004, 0x0008}, {0x00ef, 0x00ef, 0x00f5, 0x00e9}, + {0x00f9, 0x000c, 0x0010, 0x0014}, {0x00e7, 0x00e7, 0x00ff, 0x00ff}, + {0x00e1, 0x0101, 0x00dd, 0x0105}, {0x0018, 0x001c, 0x0020, 0x0028}, + {0x010b, 0x010b, 0x00db, 0x00db}, {0x010f, 0x010f, 0x00d5, 0x0111}, + {0x00d1, 0x0115, 0x00cd, 0x0024}, {0x011b, 0x011b, 0x00cb, 0x00cb}, + {0x002c, 0x0030, 0x0034, 0x0040}, {0x00c7, 0x00c7, 0x011f, 0x011f}, + {0x0121, 0x00c1, 0x0125, 0x00bd}, {0x0129, 0x00b9, 0x0038, 0x003c}, + {0x0133, 0x0133, 0x012f, 0x012f}, {0x0137, 0x0137, 0x013b, 0x013b}, + {0x0044, 0x0048, 0x004c, 0x0058}, {0x00b7, 0x00b7, 0x00af, 0x00af}, + {0x00b1, 0x013d, 0x00a9, 0x00a5}, {0x0141, 0x00a1, 0x0050, 0x0054}, + {0x0147, 0x0147, 0x009f, 0x009f}, {0x014b, 0x014b, 0x009b, 0x009b}, + {0x005c, 0x0060, 0x0064, 0x0070}, {0x014f, 0x014f, 0x0095, 0x008d}, + {0x0155, 0x0085, 0x0091, 0x0089}, {0x0151, 0x0081, 0x0068, 0x006c}, + {0x015f, 0x015f, 0x0167, 0x0167}, {0x007b, 0x007b, 0x007f, 0x007f}, + {0x0074, 0x0078, 0x0080, 0x00b0}, {0x0159, 0x0075, 0x0069, 0x006d}, + {0x0071, 0x0061, 0x0161, 0x007c}, {0x0067, 0x0067, 0x005b, 0x005b}, + {0x0084, 0x0088, 0x008c, 0x009c}, {0x005f, 0x005f, 0x0169, 0x0055}, + {0x004d, 0x000d, 0x0005, 0x0009}, {0x0001, 0x0090, 0x0094, 0x0098}, + {0x018b, 0x018b, 0x018f, 0x018f}, {0x0193, 0x0193, 0x0197, 0x0197}, + {0x019b, 0x019b, 0x01d7, 0x01d7}, {0x00a0, 0x00a4, 0x00a8, 0x00ac}, + {0x0187, 0x0187, 0x016f, 0x016f}, {0x0173, 0x0173, 0x0177, 0x0177}, + {0x017b, 0x017b, 0x017f, 0x017f}, {0x0183, 0x0183, 0x01a3, 0x01a3}, + {0x00b4, 0x00c8, 0x00dc, 0x00f0}, {0x00b8, 0x00bc, 0x00c0, 0x00c4}, + {0x01bf, 0x01bf, 0x01c3, 0x01c3}, {0x01c7, 0x01c7, 0x01cb, 0x01cb}, + {0x01cf, 0x01cf, 0x01d3, 0x01d3}, {0x01bb, 0x01bb, 0x01a7, 0x01a7}, + {0x00cc, 0x00d0, 0x00d4, 0x00d8}, {0x01ab, 0x01ab, 0x01af, 0x01af}, + {0x01b3, 0x01b3, 0x01b7, 0x01b7}, {0x01db, 0x01db, 0x001b, 0x001b}, + {0x0023, 0x0023, 0x0027, 0x0027}, {0x00e0, 0x00e4, 0x00e8, 0x00ec}, + {0x002b, 0x002b, 0x0017, 0x0017}, {0x019f, 0x019f, 0x01e3, 0x01e3}, + {0x01df, 0x01df, 0x0013, 0x0013}, {0x001f, 0x001f, 0x003f, 0x003f}, + {0x00f4, 0x00f8, 0x00fc, 0x0100}, {0x0043, 0x0043, 0x004b, 0x004b}, + {0x0053, 0x0053, 0x0047, 0x0047}, {0x002f, 0x002f, 0x0033, 0x0033}, + {0x003b, 0x003b, 0x0037, 0x0037}}; + +/* .CodeBook = HuffmanCodeBook_x, .Dimension = 4, .numBits = 2, .Offset = 0 */ +const CodeBookDescription AACcodeBookDescriptionTable[13] = { + {NULL, 0, 0, 0}, + {HuffmanCodeBook_1, 4, 2, 1}, + {HuffmanCodeBook_2, 4, 2, 1}, + {HuffmanCodeBook_3, 4, 2, 0}, + {HuffmanCodeBook_4, 4, 2, 0}, + {HuffmanCodeBook_5, 2, 4, 4}, + {HuffmanCodeBook_6, 2, 4, 4}, + {HuffmanCodeBook_7, 2, 4, 0}, + {HuffmanCodeBook_8, 2, 4, 0}, + {HuffmanCodeBook_9, 2, 4, 0}, + {HuffmanCodeBook_10, 2, 4, 0}, + {HuffmanCodeBook_11, 2, 5, 0}, + {HuffmanCodeBook_SCL, 1, 8, 60}}; + +const CodeBookDescription AACcodeBookDescriptionSCL = {HuffmanCodeBook_SCL, 1, + 8, 60}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree41 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 1). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 4) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 4 */ +/* --------------------------------------------------------------------------------------------- + */ +/* HuffTree */ +const UINT aHuffTree41[80] = { + 0x4a0001, 0x026002, 0x013003, 0x021004, 0x01c005, 0x00b006, 0x010007, + 0x019008, 0x00900e, 0x00a03a, 0x400528, 0x00c037, 0x00d03b, 0x454404, + 0x00f04c, 0x448408, 0x017011, 0x01202e, 0x42c40c, 0x034014, 0x01502c, + 0x016049, 0x410470, 0x01804e, 0x414424, 0x03201a, 0x02001b, 0x520418, + 0x02f01d, 0x02a01e, 0x01f04d, 0x41c474, 0x540420, 0x022024, 0x04a023, + 0x428510, 0x025029, 0x430508, 0x02703c, 0x028047, 0x50c434, 0x438478, + 0x04802b, 0x46443c, 0x02d03e, 0x4404b0, 0x44451c, 0x03003f, 0x03104b, + 0x52444c, 0x033039, 0x4f0450, 0x035041, 0x036046, 0x4e8458, 0x04f038, + 0x45c53c, 0x4604e0, 0x4f8468, 0x46c4d4, 0x04503d, 0x4ac47c, 0x518480, + 0x043040, 0x4844dc, 0x042044, 0x4884a8, 0x4bc48c, 0x530490, 0x4a4494, + 0x4984b8, 0x49c4c4, 0x5044b4, 0x5004c0, 0x4d04c8, 0x4f44cc, 0x4d8538, + 0x4ec4e4, 0x52c4fc, 0x514534}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree42 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 2). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 4) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 4 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree42[80] = { + 0x026001, 0x014002, 0x009003, 0x010004, 0x01d005, 0x00600d, 0x007018, + 0x450008, 0x4e0400, 0x02e00a, 0x03900b, 0x03d00c, 0x43c404, 0x01b00e, + 0x00f04f, 0x4d8408, 0x023011, 0x01203b, 0x01a013, 0x41440c, 0x015020, + 0x016040, 0x025017, 0x500410, 0x038019, 0x540418, 0x41c444, 0x02d01c, + 0x420520, 0x01e042, 0x03701f, 0x4244cc, 0x02a021, 0x02204c, 0x478428, + 0x024031, 0x42c4dc, 0x4304e8, 0x027033, 0x4a0028, 0x50c029, 0x4344a4, + 0x02c02b, 0x470438, 0x4404c8, 0x4f8448, 0x04902f, 0x04b030, 0x44c484, + 0x524032, 0x4ec454, 0x03e034, 0x035046, 0x4c4036, 0x488458, 0x4d445c, + 0x460468, 0x04e03a, 0x51c464, 0x03c04a, 0x46c514, 0x47453c, 0x04503f, + 0x47c4ac, 0x044041, 0x510480, 0x04304d, 0x4e448c, 0x490518, 0x49449c, + 0x048047, 0x4c0498, 0x4b84a8, 0x4b0508, 0x4fc4b4, 0x4bc504, 0x5304d0, + 0x5344f0, 0x4f452c, 0x528538}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree43 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 3). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 4) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 4 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree43[80] = { + 0x400001, 0x002004, 0x00300a, 0x46c404, 0x00b005, 0x00600d, 0x034007, + 0x037008, 0x494009, 0x4d8408, 0x42440c, 0x00c01b, 0x490410, 0x00e016, + 0x00f011, 0x010014, 0x4144fc, 0x01201d, 0x020013, 0x508418, 0x4c0015, + 0x41c440, 0x022017, 0x018026, 0x019035, 0x03801a, 0x420444, 0x01c01f, + 0x430428, 0x02101e, 0x44842c, 0x478434, 0x4b4438, 0x45443c, 0x02c023, + 0x039024, 0x02503f, 0x48844c, 0x030027, 0x02e028, 0x032029, 0x02a041, + 0x4d402b, 0x4504f0, 0x04302d, 0x4584a8, 0x02f03b, 0x46045c, 0x03103d, + 0x464046, 0x033044, 0x46853c, 0x47049c, 0x045036, 0x4744dc, 0x4a047c, + 0x500480, 0x4ac03a, 0x4b8484, 0x03c04e, 0x48c524, 0x03e040, 0x4984e8, + 0x50c4a4, 0x4b0530, 0x042047, 0x4bc04b, 0x4e44c4, 0x5184c8, 0x52c4cc, + 0x5204d0, 0x04d048, 0x04a049, 0x4e004c, 0x51c4ec, 0x4f4510, 0x5284f8, + 0x50404f, 0x514538, 0x540534}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree44 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 4). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 4) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 4 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree44[80] = { + 0x001004, 0x020002, 0x036003, 0x490400, 0x005008, 0x010006, 0x01f007, + 0x404428, 0x00e009, 0x01100a, 0x00b018, 0x01600c, 0x03700d, 0x408015, + 0x00f03e, 0x40c424, 0x410478, 0x022012, 0x038013, 0x01e014, 0x454414, + 0x448418, 0x025017, 0x47441c, 0x030019, 0x02601a, 0x02d01b, 0x01c034, + 0x01d029, 0x4204f0, 0x4dc42c, 0x470430, 0x02103c, 0x4a0434, 0x02302a, + 0x440024, 0x4384a8, 0x43c44c, 0x02703a, 0x02802c, 0x444524, 0x4504e0, + 0x02b03d, 0x458480, 0x45c4f4, 0x04b02e, 0x04f02f, 0x460520, 0x042031, + 0x048032, 0x049033, 0x514464, 0x03504c, 0x540468, 0x47c46c, 0x4844d8, + 0x039044, 0x4884fc, 0x03b045, 0x48c53c, 0x49449c, 0x4b8498, 0x03f046, + 0x041040, 0x4c44a4, 0x50c4ac, 0x04a043, 0x5184b0, 0x4e44b4, 0x4bc4ec, + 0x04e047, 0x4c04e8, 0x4c8510, 0x4cc52c, 0x4d0530, 0x5044d4, 0x53804d, + 0x5284f8, 0x508500, 0x51c534}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree21 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 5). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree21[80] = { + 0x450001, 0x044002, 0x042003, 0x035004, 0x026005, 0x022006, 0x013007, + 0x010008, 0x00d009, 0x01c00a, 0x01f00b, 0x01e00c, 0x4a0400, 0x01b00e, + 0x03200f, 0x47e402, 0x020011, 0x01204d, 0x40449c, 0x017014, 0x015019, + 0x01603f, 0x406458, 0x01804f, 0x448408, 0x04901a, 0x40a45a, 0x48c40c, + 0x01d031, 0x40e48e, 0x490410, 0x492412, 0x021030, 0x480414, 0x033023, + 0x02402e, 0x02503e, 0x416482, 0x02a027, 0x02802c, 0x029040, 0x418468, + 0x02b04a, 0x41a486, 0x02d048, 0x41c484, 0x04e02f, 0x41e426, 0x420434, + 0x42249e, 0x424494, 0x03d034, 0x428470, 0x039036, 0x03703b, 0x038041, + 0x42a476, 0x03a04b, 0x42c454, 0x03c047, 0x42e472, 0x430478, 0x43246e, + 0x496436, 0x488438, 0x43a466, 0x046043, 0x43c464, 0x04504c, 0x43e462, + 0x460440, 0x44245e, 0x45c444, 0x46a446, 0x44a456, 0x47444c, 0x45244e, + 0x46c47c, 0x48a47a, 0x49a498}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree22 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 6). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree22[80] = { + 0x03c001, 0x02f002, 0x020003, 0x01c004, 0x00f005, 0x00c006, 0x016007, + 0x04d008, 0x00b009, 0x01500a, 0x400490, 0x40e402, 0x00d013, 0x00e02a, + 0x40c404, 0x019010, 0x011041, 0x038012, 0x40a406, 0x014037, 0x40849c, + 0x4a0410, 0x04a017, 0x458018, 0x412422, 0x02801a, 0x01b029, 0x480414, + 0x02401d, 0x01e02b, 0x48a01f, 0x416432, 0x02d021, 0x026022, 0x023039, + 0x418468, 0x025043, 0x48641a, 0x027040, 0x41c488, 0x41e48c, 0x42045a, + 0x47c424, 0x04c02c, 0x46e426, 0x03602e, 0x428478, 0x030033, 0x43c031, + 0x04b032, 0x42e42a, 0x03403a, 0x035048, 0x42c442, 0x470430, 0x494434, + 0x43649a, 0x45c438, 0x04403b, 0x43a454, 0x04503d, 0x03e03f, 0x43e464, + 0x440460, 0x484444, 0x049042, 0x446448, 0x44a456, 0x46644c, 0x047046, + 0x44e452, 0x450462, 0x47445e, 0x46a496, 0x49846c, 0x472476, 0x47a482, + 0x04e04f, 0x47e492, 0x48e49e}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree23 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 7). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree23[63] = { + 0x400001, 0x002003, 0x410402, 0x004007, 0x412005, 0x01c006, 0x420404, + 0x00800b, 0x01d009, 0x00a01f, 0x406026, 0x00c012, 0x00d00f, 0x02700e, + 0x408440, 0x010022, 0x028011, 0x45440a, 0x013017, 0x029014, 0x024015, + 0x01602f, 0x43c40c, 0x02b018, 0x019033, 0x03201a, 0x43e01b, 0x47040e, + 0x422414, 0x01e025, 0x432416, 0x020021, 0x418442, 0x41a452, 0x036023, + 0x41c446, 0x46441e, 0x424430, 0x426434, 0x436428, 0x44442a, 0x02e02a, + 0x45642c, 0x03002c, 0x02d03b, 0x46642e, 0x43a438, 0x460448, 0x031037, + 0x47244a, 0x45a44c, 0x034039, 0x038035, 0x47844e, 0x462450, 0x474458, + 0x46a45c, 0x03a03c, 0x45e47a, 0x476468, 0x03d03e, 0x47c46c, 0x46e47e}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree24 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 8). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree24[63] = { + 0x001006, 0x01d002, 0x005003, 0x424004, 0x400420, 0x414402, 0x00700a, + 0x008020, 0x00901f, 0x404432, 0x00b011, 0x00c00e, 0x00d032, 0x406446, + 0x02300f, 0x033010, 0x458408, 0x025012, 0x013016, 0x01402f, 0x015038, + 0x46840a, 0x028017, 0x01801a, 0x039019, 0x40c47a, 0x03e01b, 0x03b01c, + 0x40e47e, 0x41201e, 0x422410, 0x416434, 0x02a021, 0x02202b, 0x418444, + 0x02c024, 0x41a456, 0x02d026, 0x027034, 0x46241c, 0x029036, 0x41e45c, + 0x426031, 0x428430, 0x45242a, 0x03702e, 0x42c464, 0x03003c, 0x47442e, + 0x436442, 0x438454, 0x43a448, 0x03503a, 0x43c466, 0x43e03d, 0x44a440, + 0x44c472, 0x46044e, 0x45a450, 0x45e470, 0x46a476, 0x46c478, 0x47c46e}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree25 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 9). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree25[168] = { + 0x400001, 0x002003, 0x41a402, 0x004007, 0x41c005, 0x035006, 0x434404, + 0x008010, 0x00900c, 0x04a00a, 0x42000b, 0x44e406, 0x03600d, 0x03800e, + 0x05a00f, 0x408468, 0x01101a, 0x012016, 0x039013, 0x070014, 0x46e015, + 0x40a440, 0x03b017, 0x01804d, 0x01904f, 0x4b840c, 0x01b022, 0x01c041, + 0x03f01d, 0x01e020, 0x01f05b, 0x40e4ee, 0x02107c, 0x45c410, 0x02302c, + 0x024028, 0x053025, 0x026045, 0x02707d, 0x412522, 0x047029, 0x05e02a, + 0x02b08a, 0x526414, 0x05602d, 0x02e081, 0x02f032, 0x06e030, 0x031080, + 0x416544, 0x079033, 0x034091, 0x41852c, 0x43641e, 0x04b037, 0x42246a, + 0x43c424, 0x04c03a, 0x426456, 0x03c066, 0x03d03e, 0x482428, 0x45842a, + 0x040072, 0x42c4ba, 0x050042, 0x04305c, 0x044074, 0x42e4be, 0x06a046, + 0x4dc430, 0x075048, 0x0490a3, 0x44a432, 0x450438, 0x43a452, 0x48443e, + 0x04e068, 0x45a442, 0x4d4444, 0x051088, 0x052087, 0x44648c, 0x077054, + 0x4da055, 0x50a448, 0x057060, 0x06b058, 0x05906d, 0x44c4f6, 0x46c454, + 0x45e474, 0x06905d, 0x460520, 0x05f07e, 0x462494, 0x061063, 0x07f062, + 0x464496, 0x06408b, 0x08d065, 0x542466, 0x067071, 0x4d2470, 0x4724ec, + 0x478476, 0x53a47a, 0x09b06c, 0x47c4ac, 0x4f847e, 0x06f078, 0x510480, + 0x48649e, 0x4884a0, 0x07307b, 0x49c48a, 0x4a648e, 0x098076, 0x4904c0, + 0x4924ea, 0x4c8498, 0x07a08e, 0x51249a, 0x4a24d6, 0x5064a4, 0x4f24a8, + 0x4aa4de, 0x51e4ae, 0x4b0538, 0x082092, 0x083085, 0x08f084, 0x5464b2, + 0x096086, 0x4ce4b4, 0x4d04b6, 0x089090, 0x4bc508, 0x4c253e, 0x08c0a4, + 0x5284c4, 0x4e04c6, 0x4ca4fa, 0x5144cc, 0x4f04d8, 0x4e24fc, 0x09309c, + 0x094099, 0x095097, 0x4e4516, 0x4e652e, 0x4e84fe, 0x4f450c, 0x09a09f, + 0x500502, 0x50450e, 0x09d0a0, 0x09e0a5, 0x518530, 0x51a54a, 0x0a70a1, + 0x0a20a6, 0x51c534, 0x53c524, 0x54052a, 0x548532, 0x536550, 0x54c54e}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree26 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 10). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree26[168] = { + 0x006001, 0x002013, 0x00300f, 0x00400d, 0x03b005, 0x40046e, 0x037007, + 0x00800a, 0x009067, 0x402420, 0x05600b, 0x00c057, 0x434404, 0x06600e, + 0x406470, 0x03c010, 0x059011, 0x06f012, 0x49e408, 0x014019, 0x03f015, + 0x016044, 0x017042, 0x079018, 0x4b840a, 0x01a01f, 0x01b047, 0x07c01c, + 0x08701d, 0x06901e, 0x44640c, 0x020027, 0x04b021, 0x02204f, 0x023025, + 0x02406b, 0x40e4e0, 0x081026, 0x528410, 0x02802c, 0x06c029, 0x08f02a, + 0x02b078, 0x53a412, 0x05202d, 0x02e033, 0x02f031, 0x0300a2, 0x4144ce, + 0x0a6032, 0x416534, 0x09a034, 0x09f035, 0x0360a7, 0x54e418, 0x03a038, + 0x436039, 0x43841a, 0x41c41e, 0x42246a, 0x05803d, 0x03e068, 0x424484, + 0x04005b, 0x04107a, 0x42645a, 0x043093, 0x4d2428, 0x05e045, 0x046072, + 0x42a45e, 0x048060, 0x073049, 0x04a098, 0x42c4c4, 0x07504c, 0x09504d, + 0x04e09c, 0x51042e, 0x063050, 0x077051, 0x43053c, 0x053084, 0x065054, + 0x4e4055, 0x4fe432, 0x43a454, 0x43c46c, 0x43e486, 0x07005a, 0x4a0440, + 0x07105c, 0x05d07b, 0x45c442, 0x05f08a, 0x476444, 0x07f061, 0x06206a, + 0x448506, 0x06408e, 0x52644a, 0x54444c, 0x45644e, 0x452450, 0x488458, + 0x4604ec, 0x4624f6, 0x50e464, 0x08206d, 0x0a406e, 0x542466, 0x4a2468, + 0x48a472, 0x474089, 0x4d8478, 0x097074, 0x47a508, 0x08d076, 0x47c4b6, + 0x51247e, 0x4804fc, 0x4bc482, 0x48c4a4, 0x48e4d4, 0x07d07e, 0x4904da, + 0x49208b, 0x094080, 0x49450c, 0x4964e2, 0x09d083, 0x52a498, 0x085091, + 0x0a5086, 0x4cc49a, 0x08808c, 0x4ee49c, 0x4a64ba, 0x4a84c0, 0x4c24aa, + 0x4ac4f0, 0x4ae4d0, 0x4ca4b0, 0x0900a1, 0x4b24ea, 0x092099, 0x4b4516, + 0x4d64be, 0x4c650a, 0x522096, 0x4c8524, 0x4dc4f2, 0x4de4f4, 0x4e6548, + 0x09e09b, 0x5384e8, 0x5204f8, 0x4fa53e, 0x50051a, 0x0a30a0, 0x502536, + 0x514504, 0x51e518, 0x54a51c, 0x54052c, 0x52e546, 0x530532, 0x54c550}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree27 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 11). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree27[288] = { + 0x00100d, 0x002006, 0x003004, 0x400424, 0x047005, 0x402446, 0x048007, + 0x00800a, 0x00904c, 0x44a404, 0x07400b, 0x00c0bb, 0x466406, 0x00e014, + 0x00f054, 0x04e010, 0x051011, 0x0a9012, 0x0130bc, 0x408464, 0x01501f, + 0x01601a, 0x017059, 0x0af018, 0x0ca019, 0x40a0e4, 0x01b05e, 0x01c084, + 0x0bf01d, 0x05d01e, 0x55a40c, 0x020026, 0x021066, 0x043022, 0x023062, + 0x02408d, 0x025108, 0x40e480, 0x027030, 0x02802c, 0x02906b, 0x02a0da, + 0x06502b, 0x4105c8, 0x0a402d, 0x0ec02e, 0x0dd02f, 0x532412, 0x06e031, + 0x032036, 0x03303e, 0x0fd034, 0x0fc035, 0x4145b0, 0x03703a, 0x038117, + 0x10d039, 0x5ba416, 0x10f03b, 0x03c041, 0x5fa03d, 0x41c418, 0x10403f, + 0x04011d, 0x41a5f4, 0x11c042, 0x41e61c, 0x087044, 0x0f5045, 0x0d9046, + 0x4204a2, 0x640422, 0x04904a, 0x426448, 0x04b073, 0x428468, 0x46c04d, + 0x48a42a, 0x04f077, 0x076050, 0x42c4b0, 0x0520a7, 0x096053, 0x42e4a8, + 0x05507d, 0x07a056, 0x0d4057, 0x0df058, 0x442430, 0x05a081, 0x05b09b, + 0x05c0e2, 0x5b8432, 0x4fe434, 0x05f09e, 0x0e6060, 0x0610d6, 0x57c436, + 0x0cc063, 0x112064, 0x4384a0, 0x43a5ca, 0x067089, 0x0680b7, 0x0690a2, + 0x0a106a, 0x43c59c, 0x09206c, 0x06d0ba, 0x60643e, 0x0d106f, 0x0700ee, + 0x0de071, 0x10b072, 0x44056c, 0x46a444, 0x075094, 0x48c44c, 0x44e490, + 0x095078, 0x0ab079, 0x4504ce, 0x07b097, 0x11e07c, 0x630452, 0x0ac07e, + 0x07f099, 0x080106, 0x4544b8, 0x0820b1, 0x0830e5, 0x4fc456, 0x0b3085, + 0x08609d, 0x45853e, 0x0880c2, 0x5c045a, 0x08a08f, 0x08b0ce, 0x08c0f7, + 0x58645c, 0x11108e, 0x45e5c4, 0x0c4090, 0x10a091, 0x4604e4, 0x0d0093, + 0x462608, 0x48e46e, 0x4704b2, 0x4d2472, 0x0980bd, 0x4f2474, 0x0e309a, + 0x4764aa, 0x0be09c, 0x47851a, 0x47a4de, 0x09f0b5, 0x0a00c1, 0x50047c, + 0x57847e, 0x0a30c3, 0x504482, 0x0e90a5, 0x0a6100, 0x4c8484, 0x0a811f, + 0x48662a, 0x0c70aa, 0x488494, 0x4924d0, 0x0ad0c8, 0x0ae0d8, 0x496636, + 0x10e0b0, 0x4f8498, 0x0f30b2, 0x49a4dc, 0x0f20b4, 0x53c49c, 0x0b60cb, + 0x49e57a, 0x0b80e0, 0x0b9109, 0x5e44a4, 0x5484a6, 0x4ac4ae, 0x4b44ca, + 0x4d64b6, 0x4ba5da, 0x0c60c0, 0x4bc51e, 0x4be556, 0x6204c0, 0x4c24c4, + 0x0f80c5, 0x5664c6, 0x4cc53a, 0x4d462c, 0x0f10c9, 0x4d8552, 0x4da4fa, + 0x5be4e0, 0x0cd0ff, 0x5244e2, 0x0cf0e8, 0x4e6568, 0x59a4e8, 0x0f90d2, + 0x1010d3, 0x5ac4ea, 0x0d50d7, 0x4ec634, 0x4ee560, 0x4f44f0, 0x4f6638, + 0x502522, 0x0db0dc, 0x5065a6, 0x508604, 0x60050a, 0x50c0fb, 0x63250e, + 0x1130e1, 0x5a4510, 0x5125fc, 0x516514, 0x51863e, 0x51c536, 0x0e70f4, + 0x55c520, 0x602526, 0x0eb0ea, 0x5cc528, 0x5ea52a, 0x1140ed, 0x60c52c, + 0x1020ef, 0x0f0119, 0x58e52e, 0x530622, 0x558534, 0x53861e, 0x55e540, + 0x5800f6, 0x57e542, 0x5445e6, 0x5465e8, 0x0fa115, 0x54c54a, 0x54e60e, + 0x5ae550, 0x1160fe, 0x5f0554, 0x564562, 0x56a58a, 0x56e5ee, 0x10310c, + 0x5705d0, 0x107105, 0x5725d4, 0x57463a, 0x5765b4, 0x5825bc, 0x5845e2, + 0x5885de, 0x58c592, 0x5ce590, 0x5945f6, 0x63c596, 0x11b110, 0x5d8598, + 0x5c259e, 0x5e05a0, 0x5a25c6, 0x5a860a, 0x5aa5ec, 0x5b2610, 0x11a118, + 0x6185b6, 0x5f25d2, 0x5d6616, 0x5dc5f8, 0x61a5fe, 0x612614, 0x62e624, + 0x626628}; + +/* get starting addresses of huffman tables into an array [convert codebook into + * starting address] */ +/* cb tree */ +const UINT *aHuffTable[MAX_CB] = { + aHuffTree41, + /* 0 - */ /* use tree 1 as dummy here */ + aHuffTree41, /* 1 1 */ + aHuffTree42, /* 2 2 */ + aHuffTree43, /* 3 3 */ + aHuffTree44, /* 4 4 */ + aHuffTree21, /* 5 5 */ + aHuffTree22, /* 6 6 */ + aHuffTree23, /* 7 7 */ + aHuffTree24, /* 8 8 */ + aHuffTree25, /* 9 9 */ + aHuffTree26, /* 10 10 */ + aHuffTree27, /* 11 11 */ + aHuffTree41, + /* 12 - */ /* use tree 1 as dummy here */ + aHuffTree41, + /* 13 - */ /* use tree 1 as dummy here */ + aHuffTree41, + /* 14 - */ /* use tree 1 as dummy here */ + aHuffTree41, + /* 15 - */ /* use tree 1 as dummy here */ + aHuffTree27, /* 16 11 */ + aHuffTree27, /* 17 11 */ + aHuffTree27, /* 18 11 */ + aHuffTree27, /* 19 11 */ + aHuffTree27, /* 20 11 */ + aHuffTree27, /* 21 11 */ + aHuffTree27, /* 22 11 */ + aHuffTree27, /* 23 11 */ + aHuffTree27, /* 24 11 */ + aHuffTree27, /* 25 11 */ + aHuffTree27, /* 26 11 */ + aHuffTree27, /* 27 11 */ + aHuffTree27, /* 28 11 */ + aHuffTree27, /* 29 11 */ + aHuffTree27, /* 30 11 */ + aHuffTree27}; /* 31 11 */ + +/*--------------------------------------------------------------------------------------------- + data-description: + The following tables contain the quantized values. Two or four of the + quantized values are indexed by the result of the decoding in the decoding tree + (see tables above). + -------------------------------------------------------------------------------------------- + */ + +/* ********************************************************************************************* + */ +/* Table: ValTab41 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the quantized values for codebooks + * 1-2. */ +/* --------------------------------------------------------------------------------------------- + */ +const SCHAR aValTab41[324] = { + -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, 1, -1, -1, 0, -1, -1, -1, + 0, 0, -1, -1, 0, 1, -1, -1, 1, -1, -1, -1, 1, 0, -1, -1, 1, 1, + -1, 0, -1, -1, -1, 0, -1, 0, -1, 0, -1, 1, -1, 0, 0, -1, -1, 0, + 0, 0, -1, 0, 0, 1, -1, 0, 1, -1, -1, 0, 1, 0, -1, 0, 1, 1, + -1, 1, -1, -1, -1, 1, -1, 0, -1, 1, -1, 1, -1, 1, 0, -1, -1, 1, + 0, 0, -1, 1, 0, 1, -1, 1, 1, -1, -1, 1, 1, 0, -1, 1, 1, 1, + 0, -1, -1, -1, 0, -1, -1, 0, 0, -1, -1, 1, 0, -1, 0, -1, 0, -1, + 0, 0, 0, -1, 0, 1, 0, -1, 1, -1, 0, -1, 1, 0, 0, -1, 1, 1, + 0, 0, -1, -1, 0, 0, -1, 0, 0, 0, -1, 1, 0, 0, 0, -1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 1, 0, 0, 0, 1, 1, + 0, 1, -1, -1, 0, 1, -1, 0, 0, 1, -1, 1, 0, 1, 0, -1, 0, 1, + 0, 0, 0, 1, 0, 1, 0, 1, 1, -1, 0, 1, 1, 0, 0, 1, 1, 1, + 1, -1, -1, -1, 1, -1, -1, 0, 1, -1, -1, 1, 1, -1, 0, -1, 1, -1, + 0, 0, 1, -1, 0, 1, 1, -1, 1, -1, 1, -1, 1, 0, 1, -1, 1, 1, + 1, 0, -1, -1, 1, 0, -1, 0, 1, 0, -1, 1, 1, 0, 0, -1, 1, 0, + 0, 0, 1, 0, 0, 1, 1, 0, 1, -1, 1, 0, 1, 0, 1, 0, 1, 1, + 1, 1, -1, -1, 1, 1, -1, 0, 1, 1, -1, 1, 1, 1, 0, -1, 1, 1, + 0, 0, 1, 1, 0, 1, 1, 1, 1, -1, 1, 1, 1, 0, 1, 1, 1, 1}; + +/* ********************************************************************************************* + */ +/* Table: ValTab42 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the quantized values for codebooks + * 3-4. */ +/* --------------------------------------------------------------------------------------------- + */ +const SCHAR aValTab42[324] = { + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 2, 0, + 0, 2, 0, 0, 0, 2, 1, 0, 0, 2, 2, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 2, 0, 1, + 1, 0, 0, 1, 1, 1, 0, 1, 1, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 2, 0, + 0, 0, 2, 0, 1, 0, 2, 0, 2, 0, 2, 1, 0, 0, 2, 1, 1, 0, 2, 1, 2, 0, 2, 2, 0, + 0, 2, 2, 1, 0, 2, 2, 2, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 2, 1, 0, 1, 0, 1, + 0, 1, 1, 1, 0, 1, 2, 1, 0, 2, 0, 1, 0, 2, 1, 1, 0, 2, 2, 1, 1, 0, 0, 1, 1, + 0, 1, 1, 1, 0, 2, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 0, 1, 1, 2, + 1, 1, 1, 2, 2, 1, 2, 0, 0, 1, 2, 0, 1, 1, 2, 0, 2, 1, 2, 1, 0, 1, 2, 1, 1, + 1, 2, 1, 2, 1, 2, 2, 0, 1, 2, 2, 1, 1, 2, 2, 2, 2, 0, 0, 0, 2, 0, 0, 1, 2, + 0, 0, 2, 2, 0, 1, 0, 2, 0, 1, 1, 2, 0, 1, 2, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, + 2, 2, 2, 1, 0, 0, 2, 1, 0, 1, 2, 1, 0, 2, 2, 1, 1, 0, 2, 1, 1, 1, 2, 1, 1, + 2, 2, 1, 2, 0, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 0, 0, 2, 2, 0, 1, 2, 2, 0, 2, + 2, 2, 1, 0, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2, 2}; + +/* ********************************************************************************************* + */ +/* Table: ValTab21 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the quantized values for codebooks + * 5-6. */ +/* --------------------------------------------------------------------------------------------- + */ +const SCHAR aValTab21[162] = { + -4, -4, -4, -3, -4, -2, -4, -1, -4, 0, -4, 1, -4, 2, -4, 3, -4, 4, + -3, -4, -3, -3, -3, -2, -3, -1, -3, 0, -3, 1, -3, 2, -3, 3, -3, 4, + -2, -4, -2, -3, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, 3, -2, 4, + -1, -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3, -1, 4, + 0, -4, 0, -3, 0, -2, 0, -1, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, + 1, -4, 1, -3, 1, -2, 1, -1, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, + 2, -4, 2, -3, 2, -2, 2, -1, 2, 0, 2, 1, 2, 2, 2, 3, 2, 4, + 3, -4, 3, -3, 3, -2, 3, -1, 3, 0, 3, 1, 3, 2, 3, 3, 3, 4, + 4, -4, 4, -3, 4, -2, 4, -1, 4, 0, 4, 1, 4, 2, 4, 3, 4, 4}; + +/* ********************************************************************************************* + */ +/* Table: ValTab22 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the quantized values for codebooks + * 7-8. */ +/* --------------------------------------------------------------------------------------------- + */ +const SCHAR aValTab22[128] = { + 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 1, 0, 1, 1, 1, 2, + 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5, + 2, 6, 2, 7, 3, 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, 5, 3, 6, 3, 7, 4, 0, + 4, 1, 4, 2, 4, 3, 4, 4, 4, 5, 4, 6, 4, 7, 5, 0, 5, 1, 5, 2, 5, 3, + 5, 4, 5, 5, 5, 6, 5, 7, 6, 0, 6, 1, 6, 2, 6, 3, 6, 4, 6, 5, 6, 6, + 6, 7, 7, 0, 7, 1, 7, 2, 7, 3, 7, 4, 7, 5, 7, 6, 7, 7}; + +/* ********************************************************************************************* + */ +/* Table: ValTab23 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the quantized values for codebooks + * 9-10. */ +/* --------------------------------------------------------------------------------------------- + */ +const SCHAR aValTab23[338] = { + 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, + 9, 0, 10, 0, 11, 0, 12, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, 5, + 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1, 11, 1, 12, 2, 0, 2, 1, 2, + 2, 2, 3, 2, 4, 2, 5, 2, 6, 2, 7, 2, 8, 2, 9, 2, 10, 2, 11, + 2, 12, 3, 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, 5, 3, 6, 3, 7, 3, + 8, 3, 9, 3, 10, 3, 11, 3, 12, 4, 0, 4, 1, 4, 2, 4, 3, 4, 4, + 4, 5, 4, 6, 4, 7, 4, 8, 4, 9, 4, 10, 4, 11, 4, 12, 5, 0, 5, + 1, 5, 2, 5, 3, 5, 4, 5, 5, 5, 6, 5, 7, 5, 8, 5, 9, 5, 10, + 5, 11, 5, 12, 6, 0, 6, 1, 6, 2, 6, 3, 6, 4, 6, 5, 6, 6, 6, + 7, 6, 8, 6, 9, 6, 10, 6, 11, 6, 12, 7, 0, 7, 1, 7, 2, 7, 3, + 7, 4, 7, 5, 7, 6, 7, 7, 7, 8, 7, 9, 7, 10, 7, 11, 7, 12, 8, + 0, 8, 1, 8, 2, 8, 3, 8, 4, 8, 5, 8, 6, 8, 7, 8, 8, 8, 9, + 8, 10, 8, 11, 8, 12, 9, 0, 9, 1, 9, 2, 9, 3, 9, 4, 9, 5, 9, + 6, 9, 7, 9, 8, 9, 9, 9, 10, 9, 11, 9, 12, 10, 0, 10, 1, 10, 2, + 10, 3, 10, 4, 10, 5, 10, 6, 10, 7, 10, 8, 10, 9, 10, 10, 10, 11, 10, + 12, 11, 0, 11, 1, 11, 2, 11, 3, 11, 4, 11, 5, 11, 6, 11, 7, 11, 8, + 11, 9, 11, 10, 11, 11, 11, 12, 12, 0, 12, 1, 12, 2, 12, 3, 12, 4, 12, + 5, 12, 6, 12, 7, 12, 8, 12, 9, 12, 10, 12, 11, 12, 12}; + +/* ********************************************************************************************* + */ +/* Table: ValTab24 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the quantized values for codebooks 11. + */ +/* --------------------------------------------------------------------------------------------- + */ +const SCHAR aValTab24[578] = { + 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, + 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 1, 0, 1, 1, + 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1, + 11, 1, 12, 1, 13, 1, 14, 1, 15, 1, 16, 2, 0, 2, 1, 2, 2, 2, 3, + 2, 4, 2, 5, 2, 6, 2, 7, 2, 8, 2, 9, 2, 10, 2, 11, 2, 12, 2, + 13, 2, 14, 2, 15, 2, 16, 3, 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, 5, + 3, 6, 3, 7, 3, 8, 3, 9, 3, 10, 3, 11, 3, 12, 3, 13, 3, 14, 3, + 15, 3, 16, 4, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4, 5, 4, 6, 4, 7, + 4, 8, 4, 9, 4, 10, 4, 11, 4, 12, 4, 13, 4, 14, 4, 15, 4, 16, 5, + 0, 5, 1, 5, 2, 5, 3, 5, 4, 5, 5, 5, 6, 5, 7, 5, 8, 5, 9, + 5, 10, 5, 11, 5, 12, 5, 13, 5, 14, 5, 15, 5, 16, 6, 0, 6, 1, 6, + 2, 6, 3, 6, 4, 6, 5, 6, 6, 6, 7, 6, 8, 6, 9, 6, 10, 6, 11, + 6, 12, 6, 13, 6, 14, 6, 15, 6, 16, 7, 0, 7, 1, 7, 2, 7, 3, 7, + 4, 7, 5, 7, 6, 7, 7, 7, 8, 7, 9, 7, 10, 7, 11, 7, 12, 7, 13, + 7, 14, 7, 15, 7, 16, 8, 0, 8, 1, 8, 2, 8, 3, 8, 4, 8, 5, 8, + 6, 8, 7, 8, 8, 8, 9, 8, 10, 8, 11, 8, 12, 8, 13, 8, 14, 8, 15, + 8, 16, 9, 0, 9, 1, 9, 2, 9, 3, 9, 4, 9, 5, 9, 6, 9, 7, 9, + 8, 9, 9, 9, 10, 9, 11, 9, 12, 9, 13, 9, 14, 9, 15, 9, 16, 10, 0, + 10, 1, 10, 2, 10, 3, 10, 4, 10, 5, 10, 6, 10, 7, 10, 8, 10, 9, 10, + 10, 10, 11, 10, 12, 10, 13, 10, 14, 10, 15, 10, 16, 11, 0, 11, 1, 11, 2, + 11, 3, 11, 4, 11, 5, 11, 6, 11, 7, 11, 8, 11, 9, 11, 10, 11, 11, 11, + 12, 11, 13, 11, 14, 11, 15, 11, 16, 12, 0, 12, 1, 12, 2, 12, 3, 12, 4, + 12, 5, 12, 6, 12, 7, 12, 8, 12, 9, 12, 10, 12, 11, 12, 12, 12, 13, 12, + 14, 12, 15, 12, 16, 13, 0, 13, 1, 13, 2, 13, 3, 13, 4, 13, 5, 13, 6, + 13, 7, 13, 8, 13, 9, 13, 10, 13, 11, 13, 12, 13, 13, 13, 14, 13, 15, 13, + 16, 14, 0, 14, 1, 14, 2, 14, 3, 14, 4, 14, 5, 14, 6, 14, 7, 14, 8, + 14, 9, 14, 10, 14, 11, 14, 12, 14, 13, 14, 14, 14, 15, 14, 16, 15, 0, 15, + 1, 15, 2, 15, 3, 15, 4, 15, 5, 15, 6, 15, 7, 15, 8, 15, 9, 15, 10, + 15, 11, 15, 12, 15, 13, 15, 14, 15, 15, 15, 16, 16, 0, 16, 1, 16, 2, 16, + 3, 16, 4, 16, 5, 16, 6, 16, 7, 16, 8, 16, 9, 16, 10, 16, 11, 16, 12, + 16, 13, 16, 14, 16, 15, 16, 16}; + +/* cb quant. val table */ +const SCHAR *aQuantTable[] = { + aValTab41, + /* 0 - */ /* use quant. val talble 1 as dummy here */ + aValTab41, /* 1 1 */ + aValTab41, /* 2 1 */ + aValTab42, /* 3 2 */ + aValTab42, /* 4 2 */ + aValTab21, /* 5 3 */ + aValTab21, /* 6 3 */ + aValTab22, /* 7 4 */ + aValTab22, /* 8 4 */ + aValTab23, /* 9 5 */ + aValTab23, /* 10 5 */ + aValTab24, /* 11 6 */ + aValTab41, + /* 12 - */ /* use quant. val talble 1 as dummy here */ + aValTab41, + /* 13 - */ /* use quant. val talble 1 as dummy here */ + aValTab41, + /* 14 - */ /* use quant. val talble 1 as dummy here */ + aValTab41, + /* 15 - */ /* use quant. val talble 1 as dummy here */ + aValTab24, /* 16 6 */ + aValTab24, /* 17 6 */ + aValTab24, /* 18 6 */ + aValTab24, /* 19 6 */ + aValTab24, /* 20 6 */ + aValTab24, /* 21 6 */ + aValTab24, /* 22 6 */ + aValTab24, /* 23 6 */ + aValTab24, /* 24 6 */ + aValTab24, /* 25 6 */ + aValTab24, /* 26 6 */ + aValTab24, /* 27 6 */ + aValTab24, /* 28 6 */ + aValTab24, /* 29 6 */ + aValTab24, /* 30 6 */ + aValTab24}; /* 31 6 */ + +/* arrays for HCR_TABLE_INFO structures */ +/* maximum length of codeword in each codebook */ +/* codebook: 0,1, 2,3, 4, 5, 6, 7, 8, 9, + * 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 */ +const UCHAR aMaxCwLen[MAX_CB] = {0, 11, 9, 20, 16, 13, 11, 14, 12, 17, 14, + 49, 0, 0, 0, 0, 14, 17, 21, 21, 25, 25, + 29, 29, 29, 29, 33, 33, 33, 37, 37, 41}; + +/* 11 13 15 17 19 + * 21 23 25 27 39 31 */ +/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 + * 22 24 26 28 30 */ +const UCHAR aDimCb[MAX_CB] = { + 2, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; /* codebook dimension - + zero cb got a + dimension of 2 */ + +/* 11 13 15 17 19 + * 21 23 25 27 39 31 */ +/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 + * 22 24 26 28 30 */ +const UCHAR aDimCbShift[MAX_CB] = { + 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; /* codebook dimension */ + +/* 1 -> decode sign bits */ +/* 0 -> decode no sign bits 11 13 15 17 19 21 + * 23 25 27 39 31 */ +/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 + * 24 26 28 30 */ +const UCHAR aSignCb[MAX_CB] = {0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + +/* arrays for HCR_CB_PAIRS structures */ +const UCHAR aMinOfCbPair[MAX_CB_PAIRS] = {0, 1, 3, 5, 7, 9, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 11}; +const UCHAR aMaxOfCbPair[MAX_CB_PAIRS] = {0, 2, 4, 6, 8, 10, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 11}; + +/* priorities of codebooks */ +const UCHAR aCbPriority[MAX_CB] = {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, + 22, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}; + +const SCHAR aCodebook2StartInt[] = {STOP_THIS_STATE, /* cb 0 */ + BODY_ONLY, /* cb 1 */ + BODY_ONLY, /* cb 2 */ + BODY_SIGN__BODY, /* cb 3 */ + BODY_SIGN__BODY, /* cb 4 */ + BODY_ONLY, /* cb 5 */ + BODY_ONLY, /* cb 6 */ + BODY_SIGN__BODY, /* cb 7 */ + BODY_SIGN__BODY, /* cb 8 */ + BODY_SIGN__BODY, /* cb 9 */ + BODY_SIGN__BODY, /* cb 10 */ + BODY_SIGN_ESC__BODY, /* cb 11 */ + STOP_THIS_STATE, /* cb 12 */ + STOP_THIS_STATE, /* cb 13 */ + STOP_THIS_STATE, /* cb 14 */ + STOP_THIS_STATE, /* cb 15 */ + BODY_SIGN_ESC__BODY, /* cb 16 */ + BODY_SIGN_ESC__BODY, /* cb 17 */ + BODY_SIGN_ESC__BODY, /* cb 18 */ + BODY_SIGN_ESC__BODY, /* cb 19 */ + BODY_SIGN_ESC__BODY, /* cb 20 */ + BODY_SIGN_ESC__BODY, /* cb 21 */ + BODY_SIGN_ESC__BODY, /* cb 22 */ + BODY_SIGN_ESC__BODY, /* cb 23 */ + BODY_SIGN_ESC__BODY, /* cb 24 */ + BODY_SIGN_ESC__BODY, /* cb 25 */ + BODY_SIGN_ESC__BODY, /* cb 26 */ + BODY_SIGN_ESC__BODY, /* cb 27 */ + BODY_SIGN_ESC__BODY, /* cb 28 */ + BODY_SIGN_ESC__BODY, /* cb 29 */ + BODY_SIGN_ESC__BODY, /* cb 30 */ + BODY_SIGN_ESC__BODY}; /* cb 31 */ + +const STATEFUNC aStateConstant2State[] = { + NULL, /* 0 = STOP_THIS_STATE */ + Hcr_State_BODY_ONLY, /* 1 = BODY_ONLY */ + Hcr_State_BODY_SIGN__BODY, /* 2 = BODY_SIGN__BODY */ + Hcr_State_BODY_SIGN__SIGN, /* 3 = BODY_SIGN__SIGN */ + Hcr_State_BODY_SIGN_ESC__BODY, /* 4 = BODY_SIGN_ESC__BODY */ + Hcr_State_BODY_SIGN_ESC__SIGN, /* 5 = BODY_SIGN_ESC__SIGN */ + Hcr_State_BODY_SIGN_ESC__ESC_PREFIX, /* 6 = BODY_SIGN_ESC__ESC_PREFIX */ + Hcr_State_BODY_SIGN_ESC__ESC_WORD}; /* 7 = BODY_SIGN_ESC__ESC_WORD */ + +/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 + * 14 16 18 20 22 24 26 28 30 */ +const USHORT aLargestAbsoluteValue[MAX_CB] = { + 0, 1, 1, 2, 2, 4, 4, 7, 7, 12, 12, + 8191, 0, 0, 0, 0, 15, 31, 47, 63, 95, 127, + 159, 191, 223, 255, 319, 383, 511, 767, 1023, 2047}; /* lav */ +/* CB: 11 13 + * 15 17 19 21 23 25 27 39 31 */ + +/* ------------------------------------------------------------------------------------------ + description: The table 'HuffTreeRvlcEscape' contains the decode tree for +the rvlc escape sequences. bit 23 and 11 not used bit 22 and 10 determine end +value --> if set codeword is decoded bit 21-12 and 9-0 (offset to next node) +or (index value) The escape sequence is the index value. + + input: codeword + output: index +------------------------------------------------------------------------------------------ +*/ +const UINT aHuffTreeRvlcEscape[53] = { + 0x002001, 0x400003, 0x401004, 0x402005, 0x403007, 0x404006, 0x00a405, + 0x009008, 0x00b406, 0x00c407, 0x00d408, 0x00e409, 0x40b40a, 0x40c00f, + 0x40d010, 0x40e011, 0x40f012, 0x410013, 0x411014, 0x412015, 0x016413, + 0x414415, 0x017416, 0x417018, 0x419019, 0x01a418, 0x01b41a, 0x01c023, + 0x03201d, 0x01e020, 0x43501f, 0x41b41c, 0x021022, 0x41d41e, 0x41f420, + 0x02402b, 0x025028, 0x026027, 0x421422, 0x423424, 0x02902a, 0x425426, + 0x427428, 0x02c02f, 0x02d02e, 0x42942a, 0x42b42c, 0x030031, 0x42d42e, + 0x42f430, 0x033034, 0x431432, 0x433434}; + +/* ------------------------------------------------------------------------------------------ + description: The table 'HuffTreeRvlc' contains the huffman decoding tree +for the RVLC scale factors. The table contains 15 allowed, symmetric codewords +and 8 forbidden codewords, which are used for error detection. + + usage of bits: bit 23 and 11 not used + bit 22 and 10 determine end value --> if set codeword is +decoded bit 21-12 and 9-0 (offset to next node within the table) or (index+7). + The decoded (index+7) is in the range from 0,1,..,22. If the +(index+7) is in the range 15,16,..,22, then a forbidden codeword is decoded. + + input: A single bit from a RVLC scalefactor codeword + output: [if codeword is not completely decoded:] offset to next node +within table or [if codeword is decoded:] A dpcm value i.e. (index+7) in range +from 0,1,..,22. The differential scalefactor (DPCM value) named 'index' is +calculated by subtracting 7 from the decoded value (index+7). +------------------------------------------------------------------------------------------ +*/ +const UINT aHuffTreeRvlCodewds[22] = { + 0x407001, 0x002009, 0x003406, 0x004405, 0x005404, 0x006403, + 0x007400, 0x008402, 0x411401, 0x00a408, 0x00c00b, 0x00e409, + 0x01000d, 0x40f40a, 0x41400f, 0x01340b, 0x011015, 0x410012, + 0x41240c, 0x416014, 0x41540d, 0x41340e}; + +const FIXP_WTB LowDelaySynthesis256[768] = { + WTC(0xdaecb88a), WTC(0xdb7a5230), WTC(0xdc093961), WTC(0xdc9977b5), + WTC(0xdd2b11b4), WTC(0xddbe06c1), WTC(0xde525277), WTC(0xdee7f167), + WTC(0xdf7ee2f9), WTC(0xe0173207), WTC(0xe0b0e70e), WTC(0xe14beb4d), + WTC(0xe1e82002), WTC(0xe285693d), WTC(0xe323ba3c), WTC(0xe3c33cdb), + WTC(0xe4640c93), WTC(0xe5060b3f), WTC(0xe5a915ce), WTC(0xe64cffc2), + WTC(0xe6f19868), WTC(0xe796b4d7), WTC(0xe83c2ebf), WTC(0xe8e1eea1), + WTC(0xe987f784), WTC(0xea2e8014), WTC(0xead5a2b6), WTC(0xeb7d3476), + WTC(0xec24ebfb), WTC(0xeccc4e9a), WTC(0xed72f723), WTC(0xee18b585), + WTC(0xeebd6902), WTC(0xef610661), WTC(0xf0037f41), WTC(0xf0a4c139), + WTC(0xf144c5bc), WTC(0xf1e395c4), WTC(0xf2812c5d), WTC(0xf31d6db4), + WTC(0xf3b83ed0), WTC(0xf4517963), WTC(0xf4e8d672), WTC(0xf57de495), + WTC(0xf610395e), WTC(0xf69f7e84), WTC(0xf72b9152), WTC(0xf7b495b5), + WTC(0xf83af453), WTC(0xf8bf7118), WTC(0xf9429a33), WTC(0xf9c4c183), + WTC(0xfa466592), WTC(0xfac80867), WTC(0xfb49d2bd), WTC(0xfbcb7294), + WTC(0xfc4d0e35), WTC(0xfccf7e7b), WTC(0xfd53af97), WTC(0xfddab5ca), + WTC(0xfe629a56), WTC(0xfee5c7c9), WTC(0xff5b6311), WTC(0xffb6bd45), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbff6c845), WTC(0xbfe461ee), WTC(0xbfd1f586), WTC(0xbfbf85b2), + WTC(0xbfad1518), WTC(0xbf9aa640), WTC(0xbf883911), WTC(0xbf75caf0), + WTC(0xbf635c4b), WTC(0xbf50f09b), WTC(0xbf3e886d), WTC(0xbf2c2167), + WTC(0xbf19bc2c), WTC(0xbf075c64), WTC(0xbef502db), WTC(0xbee2ad83), + WTC(0xbed05d67), WTC(0xbebe16a7), WTC(0xbeabda46), WTC(0xbe99a62e), + WTC(0xbe877b90), WTC(0xbe755ee8), WTC(0xbe63517d), WTC(0xbe51515b), + WTC(0xbe3f5fc9), WTC(0xbe2d8141), WTC(0xbe1bb721), WTC(0xbe09ffa3), + WTC(0xbdf85c17), WTC(0xbde6d0e3), WTC(0xbdd55f47), WTC(0xbdc4055d), + WTC(0xbdb2c438), WTC(0xbda19fe0), WTC(0xbd909942), WTC(0xbd7fae2f), + WTC(0xbd6edf8d), WTC(0xbd5e3153), WTC(0xbd4da45b), WTC(0xbd3d365a), + WTC(0xbd2ce7eb), WTC(0xbd1cbc87), WTC(0xbd0cb466), WTC(0xbcfccc80), + WTC(0xbced04c5), WTC(0xbcdd6022), WTC(0xbccdde49), WTC(0xbcbe7bb4), + WTC(0xbcaf37ec), WTC(0xbca01594), WTC(0xbc91149b), WTC(0xbc823234), + WTC(0xbc736d81), WTC(0xbc64c7a4), WTC(0xbc564085), WTC(0xbc47d6a9), + WTC(0xbc398617), WTC(0xbc2b4915), WTC(0xbc1d2a92), WTC(0xbc0f4370), + WTC(0xbc016785), WTC(0xbbf32f6c), WTC(0xbbe53648), WTC(0xbbd91eb5), + WTC(0xbbd02f7c), WTC(0xbbcb58db), WTC(0xbbca5ac2), WTC(0xbbcbdea2), + WTC(0xbbcee192), WTC(0xbbd2c7c2), WTC(0xbbd7a648), WTC(0xbbde3c5a), + WTC(0xbbe7079f), WTC(0xbbf238bf), WTC(0xbbff8eec), WTC(0xbc0e5d22), + WTC(0xbc1e2c8b), WTC(0xbc2ec3a4), WTC(0xbc402f19), WTC(0xbc52c1ac), + WTC(0xbc6709aa), WTC(0xbc7dcbce), WTC(0xbc979383), WTC(0xbcb4ae30), + WTC(0xbcd52aeb), WTC(0xbcf8db63), WTC(0xbd1f6993), WTC(0xbd485b46), + WTC(0xbd735007), WTC(0xbda003fc), WTC(0xbdce556c), WTC(0xbdfe453b), + WTC(0xbe2ffd4e), WTC(0xbe63ceb7), WTC(0xbe9a006f), WTC(0xbed2ce2b), + WTC(0xbf0e7d8e), WTC(0xbf4d5cfc), WTC(0xbf8f92bd), WTC(0xbfd5160c), + WTC(0xc01d3b27), WTC(0xc066b8f5), WTC(0xc0b0a3b8), WTC(0xc0fa7cdd), + WTC(0xc144b0e8), WTC(0xc1908d71), WTC(0xc1ded403), WTC(0xc22fae49), + WTC(0xc2830092), WTC(0xc2d86ca8), WTC(0xc32f4341), WTC(0xc38687e5), + WTC(0xc3dd5c55), WTC(0xc43310e4), WTC(0xc4883eca), WTC(0xc4deba3d), + WTC(0xc5372c82), WTC(0xc59102fb), WTC(0xc5eb416a), WTC(0xc644986f), + WTC(0xc69cabb2), WTC(0xc6f41290), WTC(0xc74b22bf), WTC(0xc7a1e4b9), + WTC(0xc7f83500), WTC(0xc84dc737), WTC(0xc8a24e07), WTC(0xc8f5776f), + WTC(0xb4db4a8b), WTC(0xb3c58a32), WTC(0xb2b2acb4), WTC(0xb1a2afc0), + WTC(0xb0959107), WTC(0xaf8b4e0a), WTC(0xae83dfef), WTC(0xad7f3ba6), + WTC(0xac7d5a57), WTC(0xab7e397d), WTC(0xaa81d5a7), WTC(0xa9882a64), + WTC(0xa89135bc), WTC(0xa79cf84e), WTC(0xa6ab74fc), WTC(0xa5bcb0d0), + WTC(0xa4d0b1b8), WTC(0xa3e77e6d), WTC(0xa3011e16), WTC(0xa21d986c), + WTC(0xa13cf921), WTC(0xa05f4fb9), WTC(0x9f84a850), WTC(0x9ead0baf), + WTC(0x9dd8888c), WTC(0x9d073385), WTC(0x9c391db5), WTC(0x9b6e5484), + WTC(0x9aa6e656), WTC(0x99e2e2c5), WTC(0x99225ac4), WTC(0x9865608a), + WTC(0x97ac0564), WTC(0x96f65984), WTC(0x96446a25), WTC(0x95964196), + WTC(0x94ebe9ec), WTC(0x94456d19), WTC(0x93a2d46a), WTC(0x93042864), + WTC(0x92696dea), WTC(0x91d2a637), WTC(0x913fd120), WTC(0x90b0ecfe), + WTC(0x9025f239), WTC(0x8f9ed33e), WTC(0x8f1b804b), WTC(0x8e9be72b), + WTC(0x8e1fe984), WTC(0x8da75ce4), WTC(0x8d321511), WTC(0x8cbfe381), + WTC(0x8c508090), WTC(0x8be38b7b), WTC(0x8b78a10a), WTC(0x8b0f5bb4), + WTC(0x8aa740f3), WTC(0x8a3fc439), WTC(0x89d8a093), WTC(0x8971e7bf), + WTC(0x890d0fa8), WTC(0x88acfc32), WTC(0x8855e07a), WTC(0x880d5010), + WTC(0x87cc444c), WTC(0x87b6e84e), WTC(0x879e3713), WTC(0x87850a87), + WTC(0x876c76ee), WTC(0x8753c55a), WTC(0x873aa70d), WTC(0x872147e7), + WTC(0x8707bb23), WTC(0x86edf64f), WTC(0x86d3f20d), WTC(0x86b9ab68), + WTC(0x869f21e7), WTC(0x86845744), WTC(0x8669499e), WTC(0x864df395), + WTC(0x863254b2), WTC(0x8616715e), WTC(0x85fa4870), WTC(0x85ddd324), + WTC(0x85c1108b), WTC(0x85a40597), WTC(0x8586b1d1), WTC(0x85690f48), + WTC(0x854b1dfb), WTC(0x852ce3e7), WTC(0x850e61c8), WTC(0x84ef9303), + WTC(0x84d078c2), WTC(0x84b119fa), WTC(0x849177fa), WTC(0x84718e56), + WTC(0x84515e65), WTC(0x8430ef53), WTC(0x841042cb), WTC(0x83ef54e8), + WTC(0x83ce27ab), WTC(0x83acc30a), WTC(0x838b2934), WTC(0x83695686), + WTC(0x83474d47), WTC(0x832515b6), WTC(0x8302b202), WTC(0x82e01e3b), + WTC(0x82bd5c8e), WTC(0x829a755a), WTC(0x82776abf), WTC(0x8254388a), + WTC(0x8230e07e), WTC(0x820d6a69), WTC(0x81e9d82d), WTC(0x81c625ae), + WTC(0x81a25455), WTC(0x817e6b1f), WTC(0x815a6b39), WTC(0x81364fec), + WTC(0x81121a34), WTC(0x80edd0c9), WTC(0x80c97479), WTC(0x80a5000a), + WTC(0x80807332), WTC(0x805bd2e6), WTC(0x80372460), WTC(0x80126cc4), + WTC(0x0a8a8431), WTC(0x0ae3c329), WTC(0x0b3fdab2), WTC(0x0b9e6e44), + WTC(0x0bff2161), WTC(0x0c619a72), WTC(0x0cc5c66d), WTC(0x0d2bd6df), + WTC(0x0d93cf64), WTC(0x0dfd8545), WTC(0x0e69093a), WTC(0x0ed6a636), + WTC(0x0f465aea), WTC(0x0fb7d810), WTC(0x102ade99), WTC(0x109f4245), + WTC(0x1114c9e8), WTC(0x118b31bc), WTC(0x120282b8), WTC(0x127b0be1), + WTC(0x12f46b9a), WTC(0x136d8dde), WTC(0x13e57912), WTC(0x145b55cb), + WTC(0x14ce5b18), WTC(0x153dccd0), WTC(0x15a8e724), WTC(0x160edefe), + WTC(0x166f004f), WTC(0x16c8aff4), WTC(0x171b7afc), WTC(0x17673db3), + WTC(0x17afb798), WTC(0x17fc62a2), WTC(0x185114c1), WTC(0x18add722), + WTC(0x1912798d), WTC(0x197eb9a2), WTC(0x19f25657), WTC(0x1a6d113e), + WTC(0x1aeeb824), WTC(0x1b7723ab), WTC(0x1c060b77), WTC(0x1c9b09a1), + WTC(0x1d361822), WTC(0x1dd7933f), WTC(0x1e7ff592), WTC(0x1f2fd0b5), + WTC(0x1fe762a9), WTC(0x20a68700), WTC(0x216bbf5e), WTC(0x22344798), + WTC(0x22feebdb), WTC(0x23cc22a6), WTC(0x249da10b), WTC(0x25762e41), + WTC(0x2655ebc8), WTC(0x273a4e66), WTC(0x28212eaa), WTC(0x2908ff30), + WTC(0x29f2ca00), WTC(0x2ae221c4), WTC(0x2bd9c6fc), WTC(0x2cdb967e), + WTC(0x2de64c86), WTC(0x2ef61340), WTC(0x3006852b), WTC(0x31131a1b), + WTC(0x321aec79), WTC(0x3320d4ed), WTC(0x342a2cb3), WTC(0x353e77f7), + WTC(0x3660aaba), WTC(0x378ef057), WTC(0x38c42495), WTC(0x39f81cec), + WTC(0x3b250148), WTC(0x3c47960e), WTC(0x3d60c625), WTC(0x3e75864a), + WTC(0x3f8a9ef7), WTC(0x40a46d36), WTC(0x41c537d7), WTC(0x42ed2889), + WTC(0x441b52d1), WTC(0x454dc37f), WTC(0x4681e9fa), WTC(0x47b4a9fe), + WTC(0x48e39960), WTC(0x4a0d10fd), WTC(0x4b30824b), WTC(0x4c4e759e), + WTC(0x4d680b1c), WTC(0x4e7eecaa), WTC(0x4f947d1e), WTC(0x50a9d1f4), + WTC(0x51bfee19), WTC(0x52d7be4d), WTC(0x53f187eb), WTC(0x550cd3c8), + WTC(0x56270706), WTC(0x573b7c75), WTC(0x58474819), WTC(0x59496ae2), + WTC(0x5a43dfa0), WTC(0x5b3b721f), WTC(0x5c32e266), WTC(0x5d2abea1), + WTC(0x5e22b479), WTC(0x5f199f8b), WTC(0x600d9194), WTC(0x60fbe188), + WTC(0x61e289de), WTC(0x62c0520c), WTC(0x63974d1e), WTC(0x646cb022), + WTC(0x6542745a), WTC(0x66172e2f), WTC(0x66e897d0), WTC(0x67b3cc52), + WTC(0x68783ebd), WTC(0x6937b9ed), WTC(0x69f365dd), WTC(0x6aabab1a), + WTC(0x6b60849c), WTC(0x6c11876e), WTC(0x6cbe46f0), WTC(0x6d6645bc), + WTC(0xae238366), WTC(0xb047d99a), WTC(0xb26207ba), WTC(0xb4733ab5), + WTC(0xb67c9f5f), WTC(0xb87f5bce), WTC(0xba7bf18d), WTC(0xbc723dd6), + WTC(0xbe621be8), WTC(0xc04b6b3d), WTC(0xc22e00ff), WTC(0xc409a8ad), + WTC(0xc5de425b), WTC(0xc7abc2a7), WTC(0xc9721421), WTC(0xcb31173c), + WTC(0xcce8c08d), WTC(0xce991894), WTC(0xd04218cd), WTC(0xd1e3aba9), + WTC(0xd37dcf0c), WTC(0xd510942f), WTC(0xd69bfa86), WTC(0xd81fefcc), + WTC(0xd99c766d), WTC(0xdb11a570), WTC(0xdc7f806e), WTC(0xdde5f79d), + WTC(0xdf451092), WTC(0xe09ce645), WTC(0xe1ed7fff), WTC(0xe336d16a), + WTC(0xe478e4f4), WTC(0xe5b3dbbb), WTC(0xe6e7c1ac), WTC(0xe8148d53), + WTC(0xe93a4835), WTC(0xea590eb0), WTC(0xeb70e4f8), WTC(0xec81b75d), + WTC(0xed8b8b6c), WTC(0xee8e8068), WTC(0xef8aa970), WTC(0xf0800dfd), + WTC(0xf16edc4d), WTC(0xf2576853), WTC(0xf339e058), WTC(0xf4164a51), + WTC(0xf4ec8fb8), WTC(0xf5bc7cef), WTC(0xf685a697), WTC(0xf74771c9), + WTC(0xf801f31b), WTC(0xf8b5eeb1), WTC(0xf963fadb), WTC(0xfa0c7427), + WTC(0xfaaf3e0f), WTC(0xfb4bcb6d), WTC(0xfbe2276f), WTC(0xfc72f578), + WTC(0xfcfe65d9), WTC(0xfd842e5b), WTC(0xfe03e14e), WTC(0xfe7ce07d), + WTC(0xfeef932b), WTC(0xff5d0236), WTC(0xffc68fee), WTC(0x002dbccc), + WTC(0x00927c78), WTC(0x00f32cbd), WTC(0x014d7209), WTC(0x019e5f51), + WTC(0x01e550aa), WTC(0x0223fc07), WTC(0x025d2618), WTC(0x02947b12), + WTC(0x02cc33db), WTC(0x0304fa92), WTC(0x033db713), WTC(0x0373a431), + WTC(0x03a47d96), WTC(0x03ce9b0f), WTC(0x03f14dc9), WTC(0x040ce0bc), + WTC(0x042245a9), WTC(0x043309a5), WTC(0x0440981a), WTC(0x044c30f1), + WTC(0x0456bb74), WTC(0x0460c1b4), WTC(0x046a2fdd), WTC(0x0472573f), + WTC(0x047877b6), WTC(0x047bc673), WTC(0x047b8615), WTC(0x04770be2), + WTC(0x046e23fc), WTC(0x04611460), WTC(0x04507fbd), WTC(0x043d6170), + WTC(0x0428ca31), WTC(0x0413d39a), WTC(0x03feb9c3), WTC(0x03e8d946), + WTC(0x03d16667), WTC(0x03b77aba), WTC(0x039aa384), WTC(0x037ae75c), + WTC(0x0358be80), WTC(0x03350af6), WTC(0x031064fa), WTC(0x02eb13f6), + WTC(0x02c51a7b), WTC(0x029e38b0), WTC(0x027619ef), WTC(0x024c5c09), + WTC(0x02210ea3), WTC(0x01f4b19e), WTC(0x01c78f79), WTC(0x0199b8ad), + WTC(0x016b3aef), WTC(0x013c2366), WTC(0x010c7be8), WTC(0x00dc4bb5), + WTC(0x00abab29), WTC(0x007ac3e1), WTC(0x0049c02f), WTC(0x0018ca71), + WTC(0xd6208221), WTC(0xd54e9f5b), WTC(0xd47fa35f), WTC(0xd3b35bdb), + WTC(0xd2e99693), WTC(0xd2222685), WTC(0xd15d5e4c), WTC(0xd09c06ff), + WTC(0xcfde0c24), WTC(0xcf2281d2), WTC(0xce698b2a), WTC(0xcdb455e0), + WTC(0xcd02c9b7), WTC(0xcc5381e5), WTC(0xcba580c3), WTC(0xcaf839ea), + WTC(0xca4ad0b7), WTC(0xc99c2153), WTC(0xc8ec5a61), WTC(0xc83ce258), + WTC(0xc78c42cd), WTC(0xc6d6213b), WTC(0xc616a6e0), WTC(0xc54a9f27), + WTC(0xc46ee44d), WTC(0xc38058a2), WTC(0xc27bd88d), WTC(0xc15e3d07), + WTC(0xc024a4d9), WTC(0xbecc7ca2), WTC(0xbd53f2b9), WTC(0xbbba98b4), + WTC(0xba0ffbc3), WTC(0xb872fb24), WTC(0xb6f36547), WTC(0xb5915345), + WTC(0xb44c3975), WTC(0xb3238942), WTC(0xb216b3fb), WTC(0xb1252b0b), + WTC(0xb04e5fc8), WTC(0xaf91c370), WTC(0xaeeec760), WTC(0xae64dd0b), + WTC(0xadf375ce), WTC(0xad9a02f0), WTC(0xad57f5bc), WTC(0xad2cbf87), + WTC(0xad17d19d), WTC(0xad189d42), WTC(0xad2e93d6), WTC(0xad5926d3), + WTC(0xad97c78a), WTC(0xade9e726), WTC(0xae4ef6fc), WTC(0xaec6688c), + WTC(0xaf4fad2c), WTC(0xafea3605), WTC(0xb0957469), WTC(0xb150d9d2), + WTC(0xb21bd793), WTC(0xb2f5de5d), WTC(0xb3de573d), WTC(0xb4d4de47), + WTC(0xb5d89c80), WTC(0xb6e937c2), WTC(0xb8061354), WTC(0xb92ea07c), + WTC(0xba62508e), WTC(0xbba094e4), WTC(0xbce8dee0), WTC(0xbe3a9fe3), + WTC(0xbf954939), WTC(0xc0f84c11), WTC(0xc26319c2), WTC(0xc3d523c5), + WTC(0xc54ddb77), WTC(0xc6ccb217), WTC(0xc85118f8), WTC(0xc9da8182), + WTC(0xcb685d07), WTC(0xccfa1cc7), WTC(0xce8f3211), WTC(0xd0270e48), + WTC(0xd1c122c7), WTC(0xd35ce0de), WTC(0xd4f9b9e1), WTC(0xd6971f23), + WTC(0xd83481f8), WTC(0xd9d153bb), WTC(0xdb6d05c0), WTC(0xdd070956), + WTC(0xde9ecfd2), WTC(0xe033ca91), WTC(0xe1c56ae7), WTC(0xe3532223), + WTC(0xe4dc6199), WTC(0xe6609aa5), WTC(0xe7df3e9a), WTC(0xe957bec9), + WTC(0xeac98c84), WTC(0xec341927), WTC(0xed96d607), WTC(0xeef13474), + WTC(0xf042a5c5), WTC(0xf18a9b4e), WTC(0xf2c88667), WTC(0xf3fbd863), + WTC(0xf5240296), WTC(0xf6407658), WTC(0xf750a4fe), WTC(0xf853ffda), + WTC(0xf949f840), WTC(0xfa31ff83), WTC(0xfb0b86fb), WTC(0xfbd5fffe), + WTC(0xfc90dbe1), WTC(0xfd3b8bf8), WTC(0xfdd58197), WTC(0xfe5e2e14), + WTC(0xfed502c4), WTC(0xff3970fc), WTC(0xff8aea0f), WTC(0xffc8df55), + WTC(0xfff2c233), WTC(0x000804e6), WTC(0x0008256a), WTC(0xfff25358), +}; + +const FIXP_WTB LowDelaySynthesis240[720] = { + WTC(0xdaf16ba1), WTC(0xdb888d4d), WTC(0xdc212bc1), WTC(0xdcbb51d0), + WTC(0xdd5703be), WTC(0xddf43f3b), WTC(0xde92fee5), WTC(0xdf333f92), + WTC(0xdfd505d1), WTC(0xe078624a), WTC(0xe11d48ff), WTC(0xe1c39358), + WTC(0xe26b2066), WTC(0xe313d8a9), WTC(0xe3bde63c), WTC(0xe4696e45), + WTC(0xe5164d95), WTC(0xe5c4597d), WTC(0xe673596f), WTC(0xe723153c), + WTC(0xe7d35813), WTC(0xe883fa49), WTC(0xe934e7a3), WTC(0xe9e64205), + WTC(0xea984aa8), WTC(0xeb4ae6ef), WTC(0xebfdcbf6), WTC(0xecb0744b), + WTC(0xed625671), WTC(0xee133361), WTC(0xeec2e1b4), WTC(0xef715334), + WTC(0xf01e7588), WTC(0xf0ca33ec), WTC(0xf1748a4e), WTC(0xf21d83ed), + WTC(0xf2c50dbe), WTC(0xf36b0639), WTC(0xf40f4892), WTC(0xf4b1944d), + WTC(0xf5517289), WTC(0xf5ee573d), WTC(0xf687d70d), WTC(0xf71db368), + WTC(0xf7b01057), WTC(0xf83f6570), WTC(0xf8cc9d0a), WTC(0xf9585a73), + WTC(0xf9e307f8), WTC(0xfa6d44d2), WTC(0xfaf79d75), WTC(0xfb8208e8), + WTC(0xfc0c33c8), WTC(0xfc96d00c), WTC(0xfd22f257), WTC(0xfdb1e623), + WTC(0xfe4318a3), WTC(0xfed08c1d), WTC(0xff5091f1), WTC(0xffb4390a), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbff62b62), WTC(0xbfe28a84), WTC(0xbfcee30d), WTC(0xbfbb3832), + WTC(0xbfa78d29), WTC(0xbf93e490), WTC(0xbf803cc6), WTC(0xbf6c9376), + WTC(0xbf58eb89), WTC(0xbf4547f8), WTC(0xbf31a6aa), WTC(0xbf1e06a3), + WTC(0xbf0a6bdf), WTC(0xbef6d863), WTC(0xbee349e5), WTC(0xbecfc145), + WTC(0xbebc4362), WTC(0xbea8d111), WTC(0xbe956806), WTC(0xbe820aeb), + WTC(0xbe6ebeb9), WTC(0xbe5b8313), WTC(0xbe485678), WTC(0xbe353cfb), + WTC(0xbe223ab8), WTC(0xbe0f4e5f), WTC(0xbdfc77b4), WTC(0xbde9bb99), + WTC(0xbdd71cbe), WTC(0xbdc4990d), WTC(0xbdb23175), WTC(0xbd9feab6), + WTC(0xbd8dc58d), WTC(0xbd7bbf8c), WTC(0xbd69daec), WTC(0xbd581c07), + WTC(0xbd46820c), WTC(0xbd350af8), WTC(0xbd23b9cc), WTC(0xbd129158), + WTC(0xbd018ece), WTC(0xbcf0b057), WTC(0xbcdff912), WTC(0xbccf69cf), + WTC(0xbcbefe81), WTC(0xbcaeb63a), WTC(0xbc9e9406), WTC(0xbc8e977c), + WTC(0xbc7ebd58), WTC(0xbc6f0544), WTC(0xbc5f7077), WTC(0xbc4ffe1d), + WTC(0xbc40ab99), WTC(0xbc317239), WTC(0xbc2252ad), WTC(0xbc136963), + WTC(0xbc04a822), WTC(0xbbf5941e), WTC(0xbbe68dab), WTC(0xbbd97a36), + WTC(0xbbcff44f), WTC(0xbbcb1891), WTC(0xbbca7818), WTC(0xbbcc765f), + WTC(0xbbcffaa5), WTC(0xbbd46a0f), WTC(0xbbda4060), WTC(0xbbe257f1), + WTC(0xbbed131c), WTC(0xbbfa7628), WTC(0xbc09cdd6), WTC(0xbc1a685b), + WTC(0xbc2bf2fd), WTC(0xbc3e6557), WTC(0xbc521d37), WTC(0xbc67c093), + WTC(0xbc803b98), WTC(0xbc9c3060), WTC(0xbcbbf6da), WTC(0xbcdf8c51), + WTC(0xbd06afb5), WTC(0xbd30e36d), WTC(0xbd5d99a0), WTC(0xbd8c71a6), + WTC(0xbdbd29c3), WTC(0xbdefb72a), WTC(0xbe243660), WTC(0xbe5b0335), + WTC(0xbe9477fd), WTC(0xbed0de00), WTC(0xbf108881), WTC(0xbf53d585), + WTC(0xbf9aeeba), WTC(0xbfe5bb38), WTC(0xc033318c), WTC(0xc081cdf2), + WTC(0xc0d0a9ee), WTC(0xc11f76d5), WTC(0xc16f66c3), WTC(0xc1c1d5c1), + WTC(0xc21726d4), WTC(0xc26f5bba), WTC(0xc2ca1036), WTC(0xc3268b0f), + WTC(0xc3839ff3), WTC(0xc3e03d22), WTC(0xc43b93ef), WTC(0xc4968594), + WTC(0xc4f3353c), WTC(0xc55202ab), WTC(0xc5b21fcf), WTC(0xc61224e6), + WTC(0xc670c168), WTC(0xc6ce3f1e), WTC(0xc72b3fbb), WTC(0xc787e688), + WTC(0xc7e41f56), WTC(0xc83f94a9), WTC(0xc899e833), WTC(0xc8f2b832), + WTC(0xb4d1fc78), WTC(0xb3a9ec70), WTC(0xb28524ca), WTC(0xb163a2ba), + WTC(0xb0456373), WTC(0xaf2a6327), WTC(0xae129708), WTC(0xacfdf2ca), + WTC(0xabec7168), WTC(0xaade0f8c), WTC(0xa9d2c80a), WTC(0xa8ca9711), + WTC(0xa7c57cdc), WTC(0xa6c37c29), WTC(0xa5c49ae6), WTC(0xa4c8e02c), + WTC(0xa3d05422), WTC(0xa2daff83), WTC(0xa1e8ec04), WTC(0xa0fa293f), + WTC(0xa00ec98a), WTC(0x9f26d990), WTC(0x9e4265a5), WTC(0x9d618437), + WTC(0x9c844ce0), WTC(0x9baad0fa), WTC(0x9ad52154), WTC(0x9a03509b), + WTC(0x993572ed), WTC(0x986b9e4d), WTC(0x97a5e7d8), WTC(0x96e46329), + WTC(0x96271ff8), WTC(0x956e2ab8), WTC(0x94b98f9c), WTC(0x94095a97), + WTC(0x935d969b), WTC(0x92b64cdf), WTC(0x9213809b), WTC(0x9175328a), + WTC(0x90db6153), WTC(0x90460712), WTC(0x8fb5146f), WTC(0x8f2876f4), + WTC(0x8ea018e5), WTC(0x8e1bd6df), WTC(0x8d9b7d9b), WTC(0x8d1ed745), + WTC(0x8ca5a942), WTC(0x8c2f93ce), WTC(0x8bbc204c), WTC(0x8b4ad58d), + WTC(0x8adb31e4), WTC(0x8a6c909b), WTC(0x89fe673d), WTC(0x8990a478), + WTC(0x89244670), WTC(0x88bc84cb), WTC(0x885e0963), WTC(0x880f73f5), + WTC(0x87cba2c0), WTC(0x87b48a6f), WTC(0x8799fb25), WTC(0x877f46f2), + WTC(0x876519cd), WTC(0x874a9a11), WTC(0x872fae01), WTC(0x871487d2), + WTC(0x86f9287b), WTC(0x86dd83b5), WTC(0x86c1947c), WTC(0x86a558f1), + WTC(0x8688d2e3), WTC(0x866c015b), WTC(0x864ede0c), WTC(0x863167cc), + WTC(0x8613a3b8), WTC(0x85f58fb2), WTC(0x85d723f0), WTC(0x85b86176), + WTC(0x85994d82), WTC(0x8579e443), WTC(0x855a201b), WTC(0x853a05b7), + WTC(0x85199a26), WTC(0x84f8d93f), WTC(0x84d7c100), WTC(0x84b65901), + WTC(0x8494a4ee), WTC(0x84729fd4), WTC(0x84504a9b), WTC(0x842dadb3), + WTC(0x840aca71), WTC(0x83e79c87), WTC(0x83c42892), WTC(0x83a07767), + WTC(0x837c883a), WTC(0x83585835), WTC(0x8333eeca), WTC(0x830f5368), + WTC(0x82ea82ec), WTC(0x82c57c57), WTC(0x82a048ea), WTC(0x827aed86), + WTC(0x82556588), WTC(0x822fb255), WTC(0x8209dd1e), WTC(0x81e3e76f), + WTC(0x81bdccac), WTC(0x81979098), WTC(0x81713ad7), WTC(0x814ac95d), + WTC(0x812437f2), WTC(0x80fd8c4b), WTC(0x80d6cc0a), WTC(0x80aff283), + WTC(0x8088fc64), WTC(0x8061eebe), WTC(0x803acfe9), WTC(0x8013a62d), + WTC(0x0a8d710a), WTC(0x0aecd974), WTC(0x0b4f7449), WTC(0x0bb4d13b), + WTC(0x0c1c7fee), WTC(0x0c86202a), WTC(0x0cf1c2e7), WTC(0x0d5f98d1), + WTC(0x0dcf816a), WTC(0x0e4162ae), WTC(0x0eb588ad), WTC(0x0f2c1e88), + WTC(0x0fa4d14f), WTC(0x101f4d80), WTC(0x109b5bfd), WTC(0x1118b908), + WTC(0x11971466), WTC(0x12168249), WTC(0x129754ab), WTC(0x1318d5c0), + WTC(0x1399b5d7), WTC(0x1418d8ec), WTC(0x14953f24), WTC(0x150dfe8a), + WTC(0x15822faa), WTC(0x15f0dd70), WTC(0x16592014), WTC(0x16ba35b2), + WTC(0x171384e7), WTC(0x1764cf1f), WTC(0x17b22a28), WTC(0x18047d40), + WTC(0x185ffc05), WTC(0x18c4a075), WTC(0x19322980), WTC(0x19a84643), + WTC(0x1a26a8f4), WTC(0x1aad099d), WTC(0x1b3b3493), WTC(0x1bd0eb32), + WTC(0x1c6db754), WTC(0x1d115a8c), WTC(0x1dbc329b), WTC(0x1e6ecb33), + WTC(0x1f29d42a), WTC(0x1feda2e4), WTC(0x20ba056e), WTC(0x218d02a2), + WTC(0x22635c75), WTC(0x233c2e7f), WTC(0x24184da1), WTC(0x24fa799d), + WTC(0x25e54e95), WTC(0x26d6edd8), WTC(0x27cc57a5), WTC(0x28c36349), + WTC(0x29bbdfdf), WTC(0x2ab9b7c2), WTC(0x2bc09790), WTC(0x2cd2d465), + WTC(0x2def4cb9), WTC(0x2f115dcc), WTC(0x3033a99c), WTC(0x3150fd8d), + WTC(0x32698a94), WTC(0x338152e6), WTC(0x34a02dcd), WTC(0x35cdedd1), + WTC(0x370aa9fa), WTC(0x38527a79), WTC(0x399c4a4f), WTC(0x3adf9c27), + WTC(0x3c17edc7), WTC(0x3d44f05d), WTC(0x3e6c519e), WTC(0x3f93ea5b), + WTC(0x40c0fc6d), WTC(0x41f60bdd), WTC(0x43332d15), WTC(0x4476e6ea), + WTC(0x45beb7e1), WTC(0x47072f2b), WTC(0x484cb71a), WTC(0x498ceafd), + WTC(0x4ac650c3), WTC(0x4bf93458), WTC(0x4d26a4c7), WTC(0x4e5090eb), + WTC(0x4f78c2ac), WTC(0x50a0918a), WTC(0x51c93995), WTC(0x52f3d6c7), + WTC(0x5420a9a2), WTC(0x554ef122), WTC(0x567ac4a9), WTC(0x579ebeb9), + WTC(0x58b8569c), WTC(0x59c74ea4), WTC(0x5ad03f31), WTC(0x5bd821c8), + WTC(0x5ce05502), WTC(0x5de8e582), WTC(0x5ef09b49), WTC(0x5ff56247), + WTC(0x60f40d81), WTC(0x61ea1450), WTC(0x62d60a2d), WTC(0x63bad7f1), + WTC(0x649e942e), WTC(0x65827556), WTC(0x66648178), WTC(0x67418c31), + WTC(0x6816c1ee), WTC(0x68e5411d), WTC(0x69aeffdb), WTC(0x6a74bb0e), + WTC(0x6b36a5ae), WTC(0x6bf44fd1), WTC(0x6cad341f), WTC(0x6d60c0ca), + WTC(0xae35f79b), WTC(0xb07e1b0d), WTC(0xb2bad26d), WTC(0xb4ed8af7), + WTC(0xb717b207), WTC(0xb93a8f5b), WTC(0xbb56631e), WTC(0xbd6afcab), + WTC(0xbf7832db), WTC(0xc17dd996), WTC(0xc37bb355), WTC(0xc5718d72), + WTC(0xc75f56cc), WTC(0xc944f93d), WTC(0xcb224f17), WTC(0xccf74805), + WTC(0xcec3ed8c), WTC(0xd08835d9), WTC(0xd2440837), WTC(0xd3f7692d), + WTC(0xd5a26b17), WTC(0xd74502b6), WTC(0xd8df1f82), WTC(0xda70d495), + WTC(0xdbfa35a1), WTC(0xdd7b3498), WTC(0xdef3cba3), WTC(0xe064184e), + WTC(0xe1cc2ab9), WTC(0xe32bf548), WTC(0xe48381cd), WTC(0xe5d2f779), + WTC(0xe71a6218), WTC(0xe859b789), WTC(0xe9910a60), WTC(0xeac07956), + WTC(0xebe7fb55), WTC(0xed077f41), WTC(0xee1f1f9d), WTC(0xef2efd99), + WTC(0xf0372472), WTC(0xf137b605), WTC(0xf23112b3), WTC(0xf323808a), + WTC(0xf40f0a86), WTC(0xf4f39883), WTC(0xf5d0eb3c), WTC(0xf6a679c6), + WTC(0xf7739640), WTC(0xf8389849), WTC(0xf8f66b2a), WTC(0xf9ada7d6), + WTC(0xfa5e97ed), WTC(0xfb08becd), WTC(0xfbabb380), WTC(0xfc48125f), + WTC(0xfcde5b40), WTC(0xfd6e4aac), WTC(0xfdf76560), WTC(0xfe78f3ab), + WTC(0xfef34cf0), WTC(0xff67b689), WTC(0xffd7e342), WTC(0x004584ef), + WTC(0x00b00074), WTC(0x01152d47), WTC(0x0171ccea), WTC(0x01c2fdbe), + WTC(0x0209b563), WTC(0x02489832), WTC(0x0283e2cd), WTC(0x02bf2050), + WTC(0x02fb72fb), WTC(0x03381f29), WTC(0x0371ea7c), WTC(0x03a602f3), + WTC(0x03d267e0), WTC(0x03f6621b), WTC(0x04125dc8), WTC(0x0427b7a5), + WTC(0x04385062), WTC(0x0445caca), WTC(0x04518ee3), WTC(0x045c745e), + WTC(0x0466d714), WTC(0x0470125c), WTC(0x047742d7), WTC(0x047b73cf), + WTC(0x047bba82), WTC(0x047744aa), WTC(0x046dc536), WTC(0x045f9068), + WTC(0x044d7632), WTC(0x0438aa92), WTC(0x04227f39), WTC(0x040c2331), + WTC(0x03f561d8), WTC(0x03dd60b4), WTC(0x03c31064), WTC(0x03a58d7d), + WTC(0x0384b74f), WTC(0x0360e29a), WTC(0x033b1151), WTC(0x031417f0), + WTC(0x02ec54ca), WTC(0x02c3d2ce), WTC(0x029a458d), WTC(0x026f4411), + WTC(0x02426093), WTC(0x0213d67f), WTC(0x01e43b01), WTC(0x01b3c7c1), + WTC(0x01828dd8), WTC(0x01509d92), WTC(0x011e0556), WTC(0x00eace1d), + WTC(0x00b70bb3), WTC(0x0082ed8b), WTC(0x004ea707), WTC(0x001a6b8f), + WTC(0xd619769b), WTC(0xd539cbf6), WTC(0xd45d68b9), WTC(0xd3840fce), + WTC(0xd2ad840b), WTC(0xd1d9a580), WTC(0xd1092160), WTC(0xd03cacdc), + WTC(0xcf7383ba), WTC(0xceacfd46), WTC(0xcdea429a), WTC(0xcd2bf5ec), + WTC(0xcc709dc1), WTC(0xcbb6dc91), WTC(0xcafdff71), WTC(0xca4504cd), + WTC(0xc98a93f4), WTC(0xc8cf0eb0), WTC(0xc813ee7f), WTC(0xc75665f3), + WTC(0xc6912d63), WTC(0xc5bff74a), WTC(0xc4dee9fa), WTC(0xc3ea39ef), + WTC(0xc2de1c94), WTC(0xc1b6bd08), WTC(0xc07074da), WTC(0xbf081038), + WTC(0xbd7b166b), WTC(0xbbc8afd7), WTC(0xba01d47c), WTC(0xb84b481f), + WTC(0xb6b65953), WTC(0xb542e5d2), WTC(0xb3f04291), WTC(0xb2bdc25a), + WTC(0xb1aab810), WTC(0xb0b676a0), WTC(0xafe050d5), WTC(0xaf27997d), + WTC(0xae8ba390), WTC(0xae0bc202), WTC(0xada7479d), WTC(0xad5d872f), + WTC(0xad2dd392), WTC(0xad177f97), WTC(0xad19de04), WTC(0xad3441c5), + WTC(0xad65fddc), WTC(0xadae6514), WTC(0xae0cca18), WTC(0xae807fde), + WTC(0xaf08d967), WTC(0xafa5296f), WTC(0xb054c2ac), WTC(0xb116f81b), + WTC(0xb1eb1cb1), WTC(0xb2d082fe), WTC(0xb3c677e5), WTC(0xb4cc6e9c), + WTC(0xb5e17eb4), WTC(0xb7052956), WTC(0xb836b427), WTC(0xb97571f3), + WTC(0xbac0b594), WTC(0xbc17d1ee), WTC(0xbd7a19eb), WTC(0xbee6e071), + WTC(0xc05d7837), WTC(0xc1dd33fe), WTC(0xc36566c2), WTC(0xc4f56377), + WTC(0xc68c7ce5), WTC(0xc82a05db), WTC(0xc9cd5148), WTC(0xcb75b207), + WTC(0xcd227ad9), WTC(0xced2fe95), WTC(0xd0869026), WTC(0xd23c8268), + WTC(0xd3f42834), WTC(0xd5acd460), WTC(0xd765d9c5), WTC(0xd91e8b42), + WTC(0xdad63bb5), WTC(0xdc8c3df2), WTC(0xde3fe4d1), WTC(0xdff08333), + WTC(0xe19d6bf6), WTC(0xe345f1ee), WTC(0xe4e967f3), WTC(0xe68720e7), + WTC(0xe81e6fa3), WTC(0xe9aea6fb), WTC(0xeb3719cb), WTC(0xecb71af3), + WTC(0xee2dfd4b), WTC(0xef9b13ab), WTC(0xf0fdb0ee), WTC(0xf25527f1), + WTC(0xf3a0cb8e), WTC(0xf4dfee9f), WTC(0xf611e3ff), WTC(0xf735fe8b), + WTC(0xf84b911a), WTC(0xf951ee85), WTC(0xfa4869a5), WTC(0xfb2e5557), + WTC(0xfc030477), WTC(0xfcc5c9e0), WTC(0xfd75f86b), WTC(0xfe12e2f2), + WTC(0xfe9bdc51), WTC(0xff103761), WTC(0xff6f46fc), WTC(0xffb85dfe), + WTC(0xffeacf42), WTC(0x0005ee03), WTC(0x0009162b), WTC(0xfff368d1), +}; + +const FIXP_WTB LowDelaySynthesis160[480] = { + WTC(0xdb171130), WTC(0xdbfadfbd), WTC(0xdce2192a), WTC(0xddcccbc8), + WTC(0xdebaeb0c), WTC(0xdfac6ebd), WTC(0xe0a17875), WTC(0xe199e10c), + WTC(0xe29531fd), WTC(0xe3933ef6), WTC(0xe49487be), WTC(0xe598bcf5), + WTC(0xe69f38b0), WTC(0xe7a73d45), WTC(0xe8b02e94), WTC(0xe9b9dc97), + WTC(0xeac4e62c), WTC(0xebd111fc), WTC(0xecdd0242), WTC(0xede7178d), + WTC(0xeeee9c24), WTC(0xeff34dba), WTC(0xf0f4eaf5), WTC(0xf1f36695), + WTC(0xf2eeb2b2), WTC(0xf3e663cb), WTC(0xf4d9cbfe), WTC(0xf5c76b3c), + WTC(0xf6ada4cb), WTC(0xf78bc92d), WTC(0xf862dc57), WTC(0xf93589ca), + WTC(0xfa059b44), WTC(0xfad501fc), WTC(0xfba49819), WTC(0xfc740f58), + WTC(0xfd465b6d), WTC(0xfe1ee06f), WTC(0xfef2581b), WTC(0xff9ec7d9), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbff143f6), WTC(0xbfd3cd5c), WTC(0xbfb64d54), WTC(0xbf98ce80), + WTC(0xbf7b5291), WTC(0xbf5dd523), WTC(0xbf405f8e), WTC(0xbf22ee55), + WTC(0xbf058664), WTC(0xbee82d22), WTC(0xbecae0a1), WTC(0xbeadacb5), + WTC(0xbe908f68), WTC(0xbe73901d), WTC(0xbe56b673), WTC(0xbe3a013e), + WTC(0xbe1d7dad), WTC(0xbe012b19), WTC(0xbde51134), WTC(0xbdc93781), + WTC(0xbdad9c88), WTC(0xbd924bd8), WTC(0xbd774311), WTC(0xbd5c882b), + WTC(0xbd4220fa), WTC(0xbd280a49), WTC(0xbd0e4d50), WTC(0xbcf4e46e), + WTC(0xbcdbd1a4), WTC(0xbcc31624), WTC(0xbcaaaa02), WTC(0xbc929348), + WTC(0xbc7acc12), WTC(0xbc63525e), WTC(0xbc4c26b1), WTC(0xbc353ea9), + WTC(0xbc1e91e2), WTC(0xbc085aea), WTC(0xbbf1c04a), WTC(0xbbdc7521), + WTC(0xbbce4740), WTC(0xbbca5187), WTC(0xbbcd3a7c), WTC(0xbbd33634), + WTC(0xbbdc0a34), WTC(0xbbea218a), WTC(0xbbfe25b7), WTC(0xbc162887), + WTC(0xbc3076c5), WTC(0xbc4d09f6), WTC(0xbc6d925c), WTC(0xbc94da6e), + WTC(0xbcc48300), WTC(0xbcfc9763), WTC(0xbd3bd94f), WTC(0xbd808d05), + WTC(0xbdc9a11b), WTC(0xbe16e339), WTC(0xbe691db9), WTC(0xbec179c1), + WTC(0xbf210140), WTC(0xbf88cd62), WTC(0xbff8e8d3), WTC(0xc06e1aaa), + WTC(0xc0e45951), WTC(0xc15b3820), WTC(0xc1d6e2ff), WTC(0xc2590e0a), + WTC(0xc2e10f83), WTC(0xc36c5c9a), WTC(0xc3f735f3), WTC(0xc47fb2d1), + WTC(0xc50abce5), WTC(0xc59a0a25), WTC(0xc629f21c), WTC(0xc6b6ef89), + WTC(0xc7427180), WTC(0xc7cd1fc4), WTC(0xc856485f), WTC(0xc8dcae93), + WTC(0xb487a986), WTC(0xb2ce0812), WTC(0xb11bc4c2), WTC(0xaf70d5cb), + WTC(0xadcd228e), WTC(0xac3086a2), WTC(0xaa9af36b), WTC(0xa90c5935), + WTC(0xa784b214), WTC(0xa60407e9), WTC(0xa48a7076), WTC(0xa31806f9), + WTC(0xa1aceb03), WTC(0xa0494f63), WTC(0x9eed6840), WTC(0x9d996570), + WTC(0x9c4d93b4), WTC(0x9b0a3114), WTC(0x99cf798d), WTC(0x989db16a), + WTC(0x97752146), WTC(0x965609f1), WTC(0x95409b05), WTC(0x9434fda9), + WTC(0x9333587b), WTC(0x923bc7d6), WTC(0x914e5299), WTC(0x906af345), + WTC(0x8f9185e6), WTC(0x8ec1cbe9), WTC(0x8dfb64c9), WTC(0x8d3dab18), + WTC(0x8c87de34), WTC(0x8bd8c494), WTC(0x8b2ecacc), WTC(0x8a882a5f), + WTC(0x89e2ecd1), WTC(0x893f12b2), WTC(0x88a3c878), WTC(0x882141c7), + WTC(0x87c65dcd), WTC(0x87a0c07b), WTC(0x8778b859), WTC(0x87514698), + WTC(0x8728e900), WTC(0x87000679), WTC(0x86d68f05), WTC(0x86ac6ee7), + WTC(0x8681a5ce), WTC(0x86562ed0), WTC(0x8629fdeb), WTC(0x85fd1ca8), + WTC(0x85cf7b32), WTC(0x85a11a2f), WTC(0x8571fbbe), WTC(0x854213f5), + WTC(0x8511722b), WTC(0x84e00ee3), WTC(0x84adf346), WTC(0x847b28e5), + WTC(0x8447a9d0), WTC(0x84138a20), WTC(0x83dec5b6), WTC(0x83a9694f), + WTC(0x83738231), WTC(0x833d0def), WTC(0x8306247b), WTC(0x82cec29b), + WTC(0x8296f5f3), WTC(0x825ecbe4), WTC(0x82263fe8), WTC(0x81ed682f), + WTC(0x81b4406d), WTC(0x817ad2a1), WTC(0x814127f4), WTC(0x8107392d), + WTC(0x80cd184d), WTC(0x8092bc5f), WTC(0x80582866), WTC(0x801d714f), + WTC(0x0aa4f846), WTC(0x0b3686fe), WTC(0x0bce899e), WTC(0x0c6b8a7e), + WTC(0x0d0d036f), WTC(0x0db358b8), WTC(0x0e5e31dd), WTC(0x0f0e4270), + WTC(0x0fc347c1), WTC(0x107c35cc), WTC(0x11383a63), WTC(0x11f68759), + WTC(0x12b7b1e3), WTC(0x13799d61), WTC(0x14383db4), WTC(0x14f032c0), + WTC(0x159e6920), WTC(0x163fb449), WTC(0x16d14820), WTC(0x17512c3f), + WTC(0x17c5f622), WTC(0x18483f2a), WTC(0x18df3074), WTC(0x1989f589), + WTC(0x1a4783af), WTC(0x1b16f152), WTC(0x1bf7795a), WTC(0x1ce7c950), + WTC(0x1de817ec), WTC(0x1efa3f4a), WTC(0x201ff37a), WTC(0x2157d4e1), + WTC(0x22995036), WTC(0x23e0d882), WTC(0x25345db2), WTC(0x269a10c3), + WTC(0x280a0798), WTC(0x297d6cf9), WTC(0x2afa7e1b), WTC(0x2c8d210a), + WTC(0x2e377db2), WTC(0x2feb60cc), WTC(0x31977111), WTC(0x333b1637), + WTC(0x34ea14df), WTC(0x36ba32d4), WTC(0x38a524c8), WTC(0x3a8fa891), + WTC(0x3c640cb3), WTC(0x3e22ab11), WTC(0x3fde7cc9), WTC(0x41a80486), + WTC(0x438394e4), WTC(0x456c8d8f), WTC(0x4758f4da), WTC(0x493d7a7b), + WTC(0x4b139f32), WTC(0x4cdbb199), WTC(0x4e9ab8d1), WTC(0x50569530), + WTC(0x5213a89e), WTC(0x53d5462c), WTC(0x559a5aa7), WTC(0x5756acf5), + WTC(0x58fcfb38), WTC(0x5a8e3e07), WTC(0x5c1a20e8), WTC(0x5da6c7da), + WTC(0x5f3231f3), WTC(0x60b51fb6), WTC(0x62260848), WTC(0x6381f5a9), + WTC(0x64d79ac7), WTC(0x662c51c0), WTC(0x67779c07), WTC(0x68b22184), + WTC(0x69e0ca28), WTC(0x6b068bcf), WTC(0x6c23008e), WTC(0x6d346856), + WTC(0xaec92693), WTC(0xb22ca2bd), WTC(0xb578d421), WTC(0xb8b27edb), + WTC(0xbbdc38b5), WTC(0xbef598bb), WTC(0xc1fe0dcd), WTC(0xc4f4d7ff), + WTC(0xc7d98479), WTC(0xcaabc289), WTC(0xcd6b38f6), WTC(0xd017edff), + WTC(0xd2b1aa37), WTC(0xd538739f), WTC(0xd7ac554d), WTC(0xda0d2f5e), + WTC(0xdc5b3f69), WTC(0xde966e30), WTC(0xe0bee2c8), WTC(0xe2d4c9cd), + WTC(0xe4d82000), WTC(0xe6c94926), WTC(0xe8a84b14), WTC(0xea755ac3), + WTC(0xec309bdc), WTC(0xedd9f2a8), WTC(0xef71c040), WTC(0xf0f842ad), + WTC(0xf26e53cb), WTC(0xf3d4cd9f), WTC(0xf52b9ddf), WTC(0xf671db4d), + WTC(0xf7a58faa), WTC(0xf8c79907), WTC(0xf9da7c73), WTC(0xfadee240), + WTC(0xfbd360e6), WTC(0xfcb95db4), WTC(0xfd913bb1), WTC(0xfe594e2e), + WTC(0xff10e67c), WTC(0xffbc2326), WTC(0x00608350), WTC(0x00fc8a2d), + WTC(0x01873313), WTC(0x01f8e4fe), WTC(0x02579318), WTC(0x02b03ec3), + WTC(0x030ab2da), WTC(0x0363ea2a), WTC(0x03b1e60d), WTC(0x03ee2920), + WTC(0x0418405c), WTC(0x04348449), WTC(0x0448d9f7), WTC(0x0459c65f), + WTC(0x04694a29), WTC(0x0475b506), WTC(0x047bebeb), WTC(0x0478dcd2), + WTC(0x046aa475), WTC(0x045249a9), WTC(0x043332f0), WTC(0x0411bb77), + WTC(0x03ef893b), WTC(0x03c9ebb8), WTC(0x039da778), WTC(0x036a1273), + WTC(0x03316a60), WTC(0x02f6553a), WTC(0x02b98be9), WTC(0x027a2e2c), + WTC(0x0236df64), WTC(0x01f036bf), WTC(0x01a78b41), WTC(0x015d29da), + WTC(0x01114624), WTC(0x00c406e9), WTC(0x0075ddb1), WTC(0x00277692), + WTC(0xd5e139e9), WTC(0xd494362e), WTC(0xd34e2bff), WTC(0xd20e56f8), + WTC(0xd0d5a3dc), WTC(0xcfa5904f), WTC(0xce7be3cb), WTC(0xcd5b3086), + WTC(0xcc420f0f), WTC(0xcb2c2bf6), WTC(0xca1695c3), WTC(0xc8fdf020), + WTC(0xc7e4fc07), WTC(0xc6c374c6), WTC(0xc5895653), WTC(0xc4297218), + WTC(0xc296f958), WTC(0xc0c51a3c), WTC(0xbea84ee5), WTC(0xbc38842f), + WTC(0xb9915966), WTC(0xb7186ae5), WTC(0xb4eb3040), WTC(0xb3076897), + WTC(0xb16acba3), WTC(0xb013112a), WTC(0xaefdf0a2), WTC(0xae2921f5), + WTC(0xad925cd6), WTC(0xad3758be), WTC(0xad15cd3d), WTC(0xad2b71ca), + WTC(0xad75fe65), WTC(0xadf32a84), WTC(0xaea0ada9), WTC(0xaf7c3fcd), + WTC(0xb0839825), WTC(0xb1b46e9c), WTC(0xb30c7a20), WTC(0xb48970be), + WTC(0xb62912e0), WTC(0xb7e90de7), WTC(0xb9c71d12), WTC(0xbbc0f7fd), + WTC(0xbdd45674), WTC(0xbffef022), WTC(0xc23e7c49), WTC(0xc490b2d4), + WTC(0xc6f34b70), WTC(0xc963fda9), WTC(0xcbe0813e), WTC(0xce668d98), + WTC(0xd0f3da69), WTC(0xd3861f64), WTC(0xd61b141f), WTC(0xd8b07038), + WTC(0xdb43eb5d), WTC(0xddd33d22), WTC(0xe05c1d2e), WTC(0xe2dc432c), + WTC(0xe55166ad), WTC(0xe7b93f62), WTC(0xea1184df), WTC(0xec57eec9), + WTC(0xee8a34c6), WTC(0xf0a60e70), WTC(0xf2a9336e), WTC(0xf4915b60), + WTC(0xf65c3dea), WTC(0xf80792ae), WTC(0xf9911147), WTC(0xfaf67154), + WTC(0xfc356a7e), WTC(0xfd4bb465), WTC(0xfe3706a9), WTC(0xfef518ec), + WTC(0xff83a2cf), WTC(0xffe05bed), WTC(0x0008fd26), WTC(0xfffb4037), +}; + +const FIXP_WTB LowDelaySynthesis128[384] = { + WTC(0xdb335c78), WTC(0xdc512d40), WTC(0xdd746116), WTC(0xde9cf7ae), + WTC(0xdfcadda8), WTC(0xe0fe4196), WTC(0xe236a409), WTC(0xe373518f), + WTC(0xe4b4e870), WTC(0xe5faf25e), WTC(0xe744190a), WTC(0xe88f06f4), + WTC(0xe9db2796), WTC(0xeb29613f), WTC(0xec78b08e), WTC(0xedc5f65d), + WTC(0xef0f5af4), WTC(0xf05447dd), WTC(0xf1945392), WTC(0xf2cf795a), + WTC(0xf405123d), WTC(0xf533af3d), WTC(0xf65842dd), WTC(0xf77071ae), + WTC(0xf87d623f), WTC(0xf983c711), WTC(0xfa8730ce), WTC(0xfb8aad4b), + WTC(0xfc8e1dc6), WTC(0xfd96d19a), WTC(0xfea5325a), WTC(0xff8d21da), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbfed9606), WTC(0xbfc8bddf), WTC(0xbfa3dd57), WTC(0xbf7f023c), + WTC(0xbf5a25e8), WTC(0xbf3554df), WTC(0xbf108b6b), WTC(0xbeebd7bd), + WTC(0xbec738a6), WTC(0xbea2bf45), WTC(0xbe7e6b42), WTC(0xbe5a4fd5), + WTC(0xbe366de8), WTC(0xbe12d91e), WTC(0xbdef9338), WTC(0xbdccaf6e), + WTC(0xbdaa2e3f), WTC(0xbd88205e), WTC(0xbd668430), WTC(0xbd456994), + WTC(0xbd24cdad), WTC(0xbd04bc91), WTC(0xbce52def), WTC(0xbcc62942), + WTC(0xbca7a273), WTC(0xbc899fba), WTC(0xbc6c16ab), WTC(0xbc4f0812), + WTC(0xbc326537), WTC(0xbc162fb3), WTC(0xbbfa5915), WTC(0xbbded462), + WTC(0xbbcd3956), WTC(0xbbcae0f5), WTC(0xbbd0beb7), WTC(0xbbdaaf42), + WTC(0xbbec5289), WTC(0xbc06d115), WTC(0xbc266162), WTC(0xbc494d27), + WTC(0xbc721013), WTC(0xbca5b2d9), WTC(0xbce6a063), WTC(0xbd339d3d), + WTC(0xbd8975b2), WTC(0xbde618b1), WTC(0xbe499de1), WTC(0xbeb60feb), + WTC(0xbf2d830e), WTC(0xbfb1ee2e), WTC(0xc041e22f), WTC(0xc0d59618), + WTC(0xc16a574d), WTC(0xc206ed94), WTC(0xc2ad7ad1), WTC(0xc35ae733), + WTC(0xc4085fbf), WTC(0xc4b33a35), WTC(0xc563f6ce), WTC(0xc6181ab7), + WTC(0xc6c86beb), WTC(0xc7768de4), WTC(0xc8231ab3), WTC(0xc8cc145a), + WTC(0xb4500dde), WTC(0xb22a524e), WTC(0xb010144c), WTC(0xae013530), + WTC(0xabfd7206), WTC(0xaa04a92f), WTC(0xa816c008), WTC(0xa633baab), + WTC(0xa45bbe2b), WTC(0xa28eff5e), WTC(0xa0cdc4c6), WTC(0x9f187801), + WTC(0x9d6f7708), WTC(0x9bd34eb0), WTC(0x9a44763a), WTC(0x98c36ace), + WTC(0x9750b896), WTC(0x95ecdc61), WTC(0x94982f8c), WTC(0x9353005a), + WTC(0x921d8bac), WTC(0x90f7e126), WTC(0x8fe1e828), WTC(0x8edb3ddc), + WTC(0x8de337c8), WTC(0x8cf89cdb), WTC(0x8c19be6d), WTC(0x8b43d072), + WTC(0x8a737663), WTC(0x89a52f4d), WTC(0x88dc38e8), WTC(0x882f6f3f), + WTC(0x87c22c55), WTC(0x87918a21), WTC(0x87602c61), WTC(0x872dfd0a), + WTC(0x86fae063), WTC(0x86c6d729), WTC(0x8691c4ad), WTC(0x865ba7e8), + WTC(0x86246b66), WTC(0x85ec17ab), WTC(0x85b293e2), WTC(0x8577eaac), + WTC(0x853c09be), WTC(0x84ff042d), WTC(0x84c0d195), WTC(0x84818c4c), + WTC(0x84412e63), WTC(0x83ffd42c), WTC(0x83bd7bdf), WTC(0x837a471b), + WTC(0x833636dc), WTC(0x82f16e48), WTC(0x82abed37), WTC(0x8265d6c4), + WTC(0x821f28cf), WTC(0x81d80322), WTC(0x8190625c), WTC(0x81486134), + WTC(0x80fff7a0), WTC(0x80b73d86), WTC(0x806e2527), WTC(0x8024c969), + WTC(0x0ab6c2d2), WTC(0x0b6edac2), WTC(0x0c302988), WTC(0x0cf88fab), + WTC(0x0dc87461), WTC(0x0e9f9122), WTC(0x0f7ee53f), WTC(0x1064e7bf), + WTC(0x114fe4b7), WTC(0x123e9e4c), WTC(0x13311589), WTC(0x1420b664), + WTC(0x15069245), WTC(0x15dc93ad), WTC(0x169caf41), WTC(0x17422e16), + WTC(0x17d51de4), WTC(0x187e7622), WTC(0x1947aa0b), WTC(0x1a2ed3b4), + WTC(0x1b321858), WTC(0x1c4fcc7f), WTC(0x1d8601a3), WTC(0x1ed6ec5e), + WTC(0x20460b07), WTC(0x21cfbf59), WTC(0x23652732), WTC(0x2508e4b1), + WTC(0x26c7b0a6), WTC(0x289505da), WTC(0x2a698dd8), WTC(0x2c5954d2), + WTC(0x2e6dd135), WTC(0x308d838f), WTC(0x329de377), WTC(0x34b28f13), + WTC(0x36f67988), WTC(0x395ec1e5), WTC(0x3bb7b587), WTC(0x3deb63cc), + WTC(0x4016b320), WTC(0x42584eb2), WTC(0x44b424ca), WTC(0x471ba5b2), + WTC(0x49791954), WTC(0x4bc02004), WTC(0x4df3b8c0), WTC(0x501f1e1e), + WTC(0x524b93e2), WTC(0x547f0eef), WTC(0x56b23d03), WTC(0x58c99052), + WTC(0x5abfc042), WTC(0x5caebf1a), WTC(0x5e9e618b), WTC(0x608595d7), + WTC(0x62528e67), WTC(0x6401eb53), WTC(0x65ad0eb1), WTC(0x674f1cd2), + WTC(0x68d8804e), WTC(0x6a4ff10e), WTC(0x6bb987a5), WTC(0x6d12e937), + WTC(0xaf370652), WTC(0xb36badcf), WTC(0xb77ec321), WTC(0xbb77e364), + WTC(0xbf57979e), WTC(0xc31cb589), WTC(0xc6c5e686), WTC(0xca52811d), + WTC(0xcdc1d66b), WTC(0xd113d0f0), WTC(0xd4481c98), WTC(0xd75ee41b), + WTC(0xda57f7bf), WTC(0xdd33a926), WTC(0xdff1e272), WTC(0xe2931227), + WTC(0xe5174232), WTC(0xe77f0b15), WTC(0xe9ca889d), WTC(0xebfa2f7c), + WTC(0xee0de002), WTC(0xf0063326), WTC(0xf1e3e5f1), WTC(0xf3a8d749), + WTC(0xf5555599), WTC(0xf6e77eb2), WTC(0xf85cb5d6), WTC(0xf9b8e64d), + WTC(0xfafe52ad), WTC(0xfc2b37b8), WTC(0xfd420467), WTC(0xfe41412c), + WTC(0xff26ded5), WTC(0xfffa6150), WTC(0x00c374a4), WTC(0x01773884), + WTC(0x02058de3), WTC(0x0278d689), WTC(0x02e87372), WTC(0x03593268), + WTC(0x03ba79ab), WTC(0x03fff32b), WTC(0x042b2341), WTC(0x044690de), + WTC(0x045bc96a), WTC(0x046e77e9), WTC(0x047a85c1), WTC(0x0479d8c4), + WTC(0x04681aec), WTC(0x0447318f), WTC(0x041e4d13), WTC(0x03f3edad), + WTC(0x03c4cc17), WTC(0x038b1f6f), WTC(0x03470909), WTC(0x02fdcebd), + WTC(0x02b1cb18), WTC(0x0261730d), WTC(0x020afad0), WTC(0x01b0b9c8), + WTC(0x0153c1a0), WTC(0x00f47426), WTC(0x00933db7), WTC(0x003140e9), + WTC(0xd5b730bf), WTC(0xd4192c32), WTC(0xd2859479), WTC(0xd0fc3b9d), + WTC(0xcf800352), WTC(0xce0e6ab3), WTC(0xccaaf25f), WTC(0xcb4ed003), + WTC(0xc9f3ae44), WTC(0xc8948a56), WTC(0xc73226fd), WTC(0xc5b2676a), + WTC(0xc3fa2a82), WTC(0xc1f05f70), WTC(0xbf7c884b), WTC(0xbc8b1e86), + WTC(0xb93e1633), WTC(0xb63eb483), WTC(0xb3b45d14), WTC(0xb19a8ee2), + WTC(0xafecd4aa), WTC(0xaea6b8e7), WTC(0xadc3c6bf), WTC(0xad3f88ac), + WTC(0xad158929), WTC(0xad4152b1), WTC(0xadbe7068), WTC(0xae886c76), + WTC(0xaf9ad1fe), WTC(0xb0f12b26), WTC(0xb2870347), WTC(0xb457d633), + WTC(0xb65f592c), WTC(0xb898eca0), WTC(0xbb00291b), WTC(0xbd90996b), + WTC(0xc045c861), WTC(0xc31b4022), WTC(0xc60c8bd5), WTC(0xc91535f2), + WTC(0xcc30c94c), WTC(0xcf5ad039), WTC(0xd28ed58a), WTC(0xd5c863e5), + WTC(0xd90305e6), WTC(0xdc3a4644), WTC(0xdf69af93), WTC(0xe28ccc93), + WTC(0xe59f27d7), WTC(0xe89c4c15), WTC(0xeb7fc3e3), WTC(0xee4519f7), + WTC(0xf0e7d8ed), WTC(0xf3638b73), WTC(0xf5b3bc30), WTC(0xf7d3f5d0), + WTC(0xf9bfc2f0), WTC(0xfb72ae35), WTC(0xfce84251), WTC(0xfe1c09e5), + WTC(0xff098f9a), WTC(0xffac5e15), WTC(0xffffffb2), WTC(0x0000159b), +}; + +const FIXP_WTB LowDelaySynthesis120[360] = { + WTC(0xdb3ccdcd), WTC(0xdc6e0d69), WTC(0xdda570a7), WTC(0xdee2ef33), + WTC(0xe02680f4), WTC(0xe1704397), WTC(0xe2bf5626), WTC(0xe4137c80), + WTC(0xe56d30cd), WTC(0xe6cb22fe), WTC(0xe82b9f14), WTC(0xe98d8220), + WTC(0xeaf18a17), WTC(0xec57328f), WTC(0xedbae901), WTC(0xef1a42b9), + WTC(0xf07481f7), WTC(0xf1c932d4), WTC(0xf3183e19), WTC(0xf460b35f), + WTC(0xf5a04ac7), WTC(0xf6d33845), WTC(0xf7f80ec0), WTC(0xf912a5cd), + WTC(0xfa282a2e), WTC(0xfb3cd81c), WTC(0xfc51629b), WTC(0xfd69f81f), + WTC(0xfe8abdeb), WTC(0xff86f173), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbfec5bfa), WTC(0xbfc50dd8), WTC(0xbf9db88b), WTC(0xbf76683c), + WTC(0xbf4f1944), WTC(0xbf27d649), WTC(0xbf00a158), WTC(0xbed9848c), + WTC(0xbeb288f1), WTC(0xbe8bb79f), WTC(0xbe651f00), WTC(0xbe3ec6f8), + WTC(0xbe18c1f6), WTC(0xbdf315fe), WTC(0xbdcdd79d), WTC(0xbda909c1), + WTC(0xbd84beae), WTC(0xbd60f6ab), WTC(0xbd3dc210), WTC(0xbd1b2093), + WTC(0xbcf91ae9), WTC(0xbcd7acab), WTC(0xbcb6d5cc), WTC(0xbc969143), + WTC(0xbc76dcf4), WTC(0xbc57b317), WTC(0xbc390c4d), WTC(0xbc1ad514), + WTC(0xbbfd2fdb), WTC(0xbbdfa548), WTC(0xbbcce946), WTC(0xbbcb39d9), + WTC(0xbbd214cf), WTC(0xbbddfb60), WTC(0xbbf3783e), WTC(0xbc11f8d2), + WTC(0xbc3509f8), WTC(0xbc5ca2b0), WTC(0xbc8dc0b0), WTC(0xbccd4b2f), + WTC(0xbd1b7107), WTC(0xbd74c6a4), WTC(0xbdd635c0), WTC(0xbe3f4cd7), + WTC(0xbeb24836), WTC(0xbf31b5df), WTC(0xbfbfe6e2), WTC(0xc05a6dbf), + WTC(0xc0f80700), WTC(0xc198449c), WTC(0xc242ea15), WTC(0xc2f8270d), + WTC(0xc3b20bd2), WTC(0xc468f554), WTC(0xc522637e), WTC(0xc5e2403b), + WTC(0xc69f9771), WTC(0xc7599dd5), WTC(0xc811f85a), WTC(0xc8c687db), + WTC(0xb43d8b3b), WTC(0xb1f3fb3c), WTC(0xafb77be9), WTC(0xad87e063), + WTC(0xab64dcd5), WTC(0xa94e4cc2), WTC(0xa74418f8), WTC(0xa5465837), + WTC(0xa3554252), WTC(0xa1711f59), WTC(0x9f9a62f5), WTC(0x9dd18104), + WTC(0x9c17167e), WTC(0x9a6bbbe9), WTC(0x98d0061c), WTC(0x97449e23), + WTC(0x95ca1ad6), WTC(0x9460e7a1), WTC(0x93096222), WTC(0x91c3c9da), + WTC(0x90902633), WTC(0x8f6e3c5f), WTC(0x8e5d7788), WTC(0x8d5cb789), + WTC(0x8c6a42d5), WTC(0x8b833d6f), WTC(0x8aa3cc10), WTC(0x89c7789a), + WTC(0x88ef9802), WTC(0x883452c3), WTC(0x87c0bb9a), WTC(0x878c8326), + WTC(0x8757eb4c), WTC(0x87222119), WTC(0x86eb5f31), WTC(0x86b3802c), + WTC(0x867a73ee), WTC(0x86402cf8), WTC(0x8604a439), WTC(0x85c7cd22), + WTC(0x8589a40b), WTC(0x854a1d2f), WTC(0x850944c1), WTC(0x84c71670), + WTC(0x8483acc8), WTC(0x843f04b6), WTC(0x83f93cd9), WTC(0x83b2576c), + WTC(0x836a7812), WTC(0x8321a764), WTC(0x82d805e8), WTC(0x828da076), + WTC(0x824290c3), WTC(0x81f6e6a8), WTC(0x81aab23c), WTC(0x815e05f8), + WTC(0x8110e4d6), WTC(0x80c362df), WTC(0x8075781d), WTC(0x80273c0c), + WTC(0x0abcb7ed), WTC(0x0b81d183), WTC(0x0c5113e3), WTC(0x0d2867d5), + WTC(0x0e082fa5), WTC(0x0ef089ad), WTC(0x0fe1d9cd), WTC(0x10d9e5f4), + WTC(0x11d6a2a0), WTC(0x12d814b1), WTC(0x13d98f52), WTC(0x14d221e1), + WTC(0x15ba467a), WTC(0x168a9c18), WTC(0x173d1fef), WTC(0x17da3bff), + WTC(0x18912cac), WTC(0x196c2a5e), WTC(0x1a68dd2e), WTC(0x1b85250c), + WTC(0x1cbea9a1), WTC(0x1e147be7), WTC(0x1f8aa446), WTC(0x2122e73a), + WTC(0x22cf6de3), WTC(0x248867f3), WTC(0x265d7937), WTC(0x2847c91b), + WTC(0x2a39d98e), WTC(0x2c482abf), WTC(0x2e7ff439), WTC(0x30c31f46), + WTC(0x32f5245d), WTC(0x3535070e), WTC(0x37adae38), WTC(0x3a3f151a), + WTC(0x3caf861b), WTC(0x3effc08b), WTC(0x415a803b), WTC(0x43d45ca9), + WTC(0x46631c69), WTC(0x48ed9c7e), WTC(0x4b608807), WTC(0x4dbbead3), + WTC(0x500ca1df), WTC(0x525e3c5d), WTC(0x54b7c199), WTC(0x570df9a2), + WTC(0x5940f661), WTC(0x5b542f13), WTC(0x5d64a202), WTC(0x5f738e39), + WTC(0x61704027), WTC(0x6348ef5e), WTC(0x65109c5f), WTC(0x66d3e29d), + WTC(0x687eb29a), WTC(0x6a125643), WTC(0x6b960b3a), WTC(0x6d07b283), + WTC(0xaf5b8daa), WTC(0xb3d557ba), WTC(0xb829feb2), WTC(0xbc6199e7), + WTC(0xc07bfbc1), WTC(0xc477a1b6), WTC(0xc8532f30), WTC(0xcc0dd698), + WTC(0xcfa71f06), WTC(0xd31ec578), WTC(0xd674c5b9), WTC(0xd9a90516), + WTC(0xdcbbc2b6), WTC(0xdfacf934), WTC(0xe27d19ab), WTC(0xe52c3d89), + WTC(0xe7bb0f52), WTC(0xea29bdd0), WTC(0xec78bc4a), WTC(0xeea805e6), + WTC(0xf0b85a68), WTC(0xf2ab266e), WTC(0xf48234a7), WTC(0xf63cb733), + WTC(0xf7d70b3f), WTC(0xf952d4d3), WTC(0xfab4906d), WTC(0xfbfaa858), + WTC(0xfd272437), WTC(0xfe392bea), WTC(0xff2e26f1), WTC(0x000efac0), + WTC(0x00e36d26), WTC(0x019bd803), WTC(0x0229e357), WTC(0x02a16b25), + WTC(0x0319ee5e), WTC(0x038ccea0), WTC(0x03e56d3d), WTC(0x041dc072), + WTC(0x043f58cc), WTC(0x04571273), WTC(0x046ba761), WTC(0x0479caa5), + WTC(0x047a2279), WTC(0x04673950), WTC(0x04435263), WTC(0x041750da), + WTC(0x03e99926), WTC(0x03b4ba1f), WTC(0x03731e2b), WTC(0x0327b303), + WTC(0x02d8301b), WTC(0x0284fb11), WTC(0x022b464a), WTC(0x01cc1b40), + WTC(0x0169ab7d), WTC(0x01047d1e), WTC(0x009d04e0), WTC(0x003484b0), + WTC(0xd5a9348a), WTC(0xd3f05eca), WTC(0xd24339e7), WTC(0xd0a269b7), + WTC(0xcf0fe026), WTC(0xcd8aa14b), WTC(0xcc13963e), WTC(0xcaa19c5a), + WTC(0xc92cd701), WTC(0xc7b5cd7b), WTC(0xc62a4fe3), WTC(0xc46742be), + WTC(0xc24e128c), WTC(0xbfc0b758), WTC(0xbca661e3), WTC(0xb922924b), + WTC(0xb5f87ac2), WTC(0xb35308e7), WTC(0xb12cc90f), WTC(0xaf80522c), + WTC(0xae483b10), WTC(0xad7f1af9), WTC(0xad1f8874), WTC(0xad241a09), + WTC(0xad8766ea), WTC(0xae4405b1), WTC(0xaf548d72), WTC(0xb0b394ad), + WTC(0xb25bb297), WTC(0xb4476fa1), WTC(0xb6718d2c), WTC(0xb8d47781), + WTC(0xbb6ad37b), WTC(0xbe2f3831), WTC(0xc11c3c6c), WTC(0xc42c76b1), + WTC(0xc75a7e40), WTC(0xcaa0e9d1), WTC(0xcdfa502b), WTC(0xd1614803), + WTC(0xd4d06850), WTC(0xd84247d3), WTC(0xdbb17d6d), WTC(0xdf189fe3), + WTC(0xe272461e), WTC(0xe5b906e1), WTC(0xe8e7790e), WTC(0xebf83366), + WTC(0xeee5cccc), WTC(0xf1aadc0a), WTC(0xf441f7fa), WTC(0xf6a5b772), + WTC(0xf8d0b146), WTC(0xfabd7c3e), WTC(0xfc66af35), WTC(0xfdc6e101), + WTC(0xfed8a875), WTC(0xff969c63), WTC(0xfffb5390), WTC(0x00017ad8), +}; + +const FIXP_WTB LowDelaySynthesis512[1536] = { + /* part 0 */ + WTC(0xdac984c0), WTC(0xdb100080), WTC(0xdb56cd00), WTC(0xdb9dec40), + WTC(0xdbe55fc0), WTC(0xdc2d2880), WTC(0xdc754780), WTC(0xdcbdbd80), + WTC(0xdd068a80), WTC(0xdd4fae80), WTC(0xdd992940), WTC(0xdde2f9c0), + WTC(0xde2d1fc0), WTC(0xde779a80), WTC(0xdec26a00), WTC(0xdf0d8e00), + WTC(0xdf590680), WTC(0xdfa4d540), WTC(0xdff0fc80), WTC(0xe03d7e20), + WTC(0xe08a5900), WTC(0xe0d78a20), WTC(0xe1250cc0), WTC(0xe172dcc0), + WTC(0xe1c0f7a0), WTC(0xe20f59a0), WTC(0xe25dfea0), WTC(0xe2ace400), + WTC(0xe2fc0be0), WTC(0xe34b7bc0), WTC(0xe39b3c80), WTC(0xe3eb5260), + WTC(0xe43bbac0), WTC(0xe48c7160), WTC(0xe4dd7140), WTC(0xe52eb600), + WTC(0xe5803c00), WTC(0xe5d1fda0), WTC(0xe623f360), WTC(0xe6761700), + WTC(0xe6c86400), WTC(0xe71ad500), WTC(0xe76d63e0), WTC(0xe7c00ba0), + WTC(0xe812c8e0), WTC(0xe86598e0), WTC(0xe8b878e0), WTC(0xe90b68a0), + WTC(0xe95e6c40), WTC(0xe9b18ae0), WTC(0xea04ce80), WTC(0xea583ba0), + WTC(0xeaabcda0), WTC(0xeaff7ee0), WTC(0xeb5348e0), WTC(0xeba722c0), + WTC(0xebfb0060), WTC(0xec4ed240), WTC(0xeca28540), WTC(0xecf60c20), + WTC(0xed496120), WTC(0xed9c7e80), WTC(0xedef5e40), WTC(0xee41fc00), + WTC(0xee945600), WTC(0xeee66ac0), WTC(0xef3839a0), WTC(0xef89c0e0), + WTC(0xefdafda0), WTC(0xf02bed60), WTC(0xf07c8e80), WTC(0xf0cce000), + WTC(0xf11ce220), WTC(0xf16c9620), WTC(0xf1bbfe30), WTC(0xf20b19e0), + WTC(0xf259e5a0), WTC(0xf2a85dc0), WTC(0xf2f67ed0), WTC(0xf34445b0), + WTC(0xf391aed0), WTC(0xf3deb590), WTC(0xf42b53e0), WTC(0xf4778140), + WTC(0xf4c33190), WTC(0xf50e5660), WTC(0xf558df30), WTC(0xf5a2be50), + WTC(0xf5ebea10), WTC(0xf6345780), WTC(0xf67bfab0), WTC(0xf6c2cee0), + WTC(0xf708d7b0), WTC(0xf74e19c0), WTC(0xf7929a70), WTC(0xf7d66630), + WTC(0xf8199268), WTC(0xf85c3860), WTC(0xf89e7480), WTC(0xf8e058c0), + WTC(0xf921ec08), WTC(0xf9633800), WTC(0xf9a44980), WTC(0xf9e53158), + WTC(0xfa260158), WTC(0xfa66ca18), WTC(0xfaa79ac0), WTC(0xfae87920), + WTC(0xfb295fa0), WTC(0xfb6a42b8), WTC(0xfbab1240), WTC(0xfbebd1c0), + WTC(0xfc2c9c24), WTC(0xfc6d8d90), WTC(0xfcaec240), WTC(0xfcf05684), + WTC(0xfd326a98), WTC(0xfd75254c), WTC(0xfdb8afd4), WTC(0xfdfccdfc), + WTC(0xfe40d694), WTC(0xfe84161c), WTC(0xfec5cf5a), WTC(0xff04e7fc), + WTC(0xff3fdfe3), WTC(0xff751ddf), WTC(0xffa2fb0f), WTC(0xffc87c42), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbffb6081), WTC(0xbff22f81), WTC(0xbfe8fc01), WTC(0xbfdfc781), + WTC(0xbfd69101), WTC(0xbfcd5a01), WTC(0xbfc42201), WTC(0xbfbae981), + WTC(0xbfb1b101), WTC(0xbfa87901), WTC(0xbf9f4181), WTC(0xbf960b01), + WTC(0xbf8cd481), WTC(0xbf839d81), WTC(0xbf7a6681), WTC(0xbf712f01), + WTC(0xbf67f801), WTC(0xbf5ec101), WTC(0xbf558b01), WTC(0xbf4c5681), + WTC(0xbf432281), WTC(0xbf39ee81), WTC(0xbf30bb01), WTC(0xbf278801), + WTC(0xbf1e5501), WTC(0xbf152381), WTC(0xbf0bf381), WTC(0xbf02c581), + WTC(0xbef99901), WTC(0xbef06d01), WTC(0xbee74281), WTC(0xbede1901), + WTC(0xbed4f081), WTC(0xbecbca81), WTC(0xbec2a781), WTC(0xbeb98681), + WTC(0xbeb06881), WTC(0xbea74c81), WTC(0xbe9e3281), WTC(0xbe951a81), + WTC(0xbe8c0501), WTC(0xbe82f301), WTC(0xbe79e481), WTC(0xbe70da01), + WTC(0xbe67d381), WTC(0xbe5ed081), WTC(0xbe55d001), WTC(0xbe4cd381), + WTC(0xbe43da81), WTC(0xbe3ae601), WTC(0xbe31f701), WTC(0xbe290d01), + WTC(0xbe202801), WTC(0xbe174781), WTC(0xbe0e6c01), WTC(0xbe059481), + WTC(0xbdfcc301), WTC(0xbdf3f701), WTC(0xbdeb3101), WTC(0xbde27201), + WTC(0xbdd9b981), WTC(0xbdd10681), WTC(0xbdc85981), WTC(0xbdbfb281), + WTC(0xbdb71201), WTC(0xbdae7881), WTC(0xbda5e601), WTC(0xbd9d5b81), + WTC(0xbd94d801), WTC(0xbd8c5c01), WTC(0xbd83e681), WTC(0xbd7b7781), + WTC(0xbd731081), WTC(0xbd6ab101), WTC(0xbd625981), WTC(0xbd5a0b01), + WTC(0xbd51c481), WTC(0xbd498601), WTC(0xbd414f01), WTC(0xbd391f81), + WTC(0xbd30f881), WTC(0xbd28d981), WTC(0xbd20c401), WTC(0xbd18b781), + WTC(0xbd10b381), WTC(0xbd08b781), WTC(0xbd00c381), WTC(0xbcf8d781), + WTC(0xbcf0f381), WTC(0xbce91801), WTC(0xbce14601), WTC(0xbcd97c81), + WTC(0xbcd1bb81), WTC(0xbcca0301), WTC(0xbcc25181), WTC(0xbcbaa801), + WTC(0xbcb30601), WTC(0xbcab6c01), WTC(0xbca3db01), WTC(0xbc9c5281), + WTC(0xbc94d201), WTC(0xbc8d5901), WTC(0xbc85e801), WTC(0xbc7e7e01), + WTC(0xbc771c01), WTC(0xbc6fc101), WTC(0xbc686e01), WTC(0xbc612301), + WTC(0xbc59df81), WTC(0xbc52a381), WTC(0xbc4b6e81), WTC(0xbc444081), + WTC(0xbc3d1801), WTC(0xbc35f501), WTC(0xbc2ed681), WTC(0xbc27bd81), + WTC(0xbc20ae01), WTC(0xbc19ab01), WTC(0xbc12b801), WTC(0xbc0bcf81), + WTC(0xbc04e381), WTC(0xbbfde481), WTC(0xbbf6c601), WTC(0xbbef9b81), + WTC(0xbbe89901), WTC(0xbbe1f401), WTC(0xbbdbe201), WTC(0xbbd68c81), + WTC(0xbbd21281), WTC(0xbbce9181), WTC(0xbbcc2681), WTC(0xbbcaca01), + WTC(0xbbca5081), WTC(0xbbca8d01), WTC(0xbbcb5301), WTC(0xbbcc8201), + WTC(0xbbce0601), WTC(0xbbcfca81), WTC(0xbbd1bd81), WTC(0xbbd3e101), + WTC(0xbbd64d01), WTC(0xbbd91b81), WTC(0xbbdc6481), WTC(0xbbe03801), + WTC(0xbbe49d01), WTC(0xbbe99981), WTC(0xbbef3301), WTC(0xbbf56181), + WTC(0xbbfc0f81), WTC(0xbc032601), WTC(0xbc0a8f01), WTC(0xbc123b81), + WTC(0xbc1a2401), WTC(0xbc224181), WTC(0xbc2a8c81), WTC(0xbc330781), + WTC(0xbc3bbc01), WTC(0xbc44b481), WTC(0xbc4dfb81), WTC(0xbc57a301), + WTC(0xbc61c401), WTC(0xbc6c7781), WTC(0xbc77d601), WTC(0xbc83f201), + WTC(0xbc90d481), WTC(0xbc9e8801), WTC(0xbcad1501), WTC(0xbcbc7e01), + WTC(0xbcccbd01), WTC(0xbcddcc81), WTC(0xbcefa601), WTC(0xbd023f01), + WTC(0xbd158801), WTC(0xbd297181), WTC(0xbd3deb81), WTC(0xbd52eb01), + WTC(0xbd686681), WTC(0xbd7e5581), WTC(0xbd94b001), WTC(0xbdab7181), + WTC(0xbdc29a81), WTC(0xbdda2a01), WTC(0xbdf22181), WTC(0xbe0a8581), + WTC(0xbe236001), WTC(0xbe3cbc01), WTC(0xbe56a381), WTC(0xbe712001), + WTC(0xbe8c3781), WTC(0xbea7f301), WTC(0xbec45881), WTC(0xbee17201), + WTC(0xbeff4801), WTC(0xbf1de601), WTC(0xbf3d5501), WTC(0xbf5d9a81), + WTC(0xbf7eb581), WTC(0xbfa0a581), WTC(0xbfc36a01), WTC(0xbfe6ed01), + WTC(0xc00b04c0), WTC(0xc02f86c0), WTC(0xc0544940), WTC(0xc0792ec0), + WTC(0xc09e2640), WTC(0xc0c31f00), WTC(0xc0e80a00), WTC(0xc10cf480), + WTC(0xc1320940), WTC(0xc15773c0), WTC(0xc17d5f00), WTC(0xc1a3e340), + WTC(0xc1cb05c0), WTC(0xc1f2cbc0), WTC(0xc21b3940), WTC(0xc2444b00), + WTC(0xc26df5c0), WTC(0xc2982d80), WTC(0xc2c2e640), WTC(0xc2ee0a00), + WTC(0xc3197940), WTC(0xc34513c0), WTC(0xc370b9c0), WTC(0xc39c4f00), + WTC(0xc3c7bc00), WTC(0xc3f2e940), WTC(0xc41dc140), WTC(0xc44856c0), + WTC(0xc472e640), WTC(0xc49dad80), WTC(0xc4c8e880), WTC(0xc4f4acc0), + WTC(0xc520e840), WTC(0xc54d8780), WTC(0xc57a76c0), WTC(0xc5a79640), + WTC(0xc5d4bac0), WTC(0xc601b880), WTC(0xc62e6580), WTC(0xc65ab600), + WTC(0xc686bd40), WTC(0xc6b28fc0), WTC(0xc6de41c0), WTC(0xc709de40), + WTC(0xc7356640), WTC(0xc760da80), WTC(0xc78c3c40), WTC(0xc7b78640), + WTC(0xc7e2afc0), WTC(0xc80dae80), WTC(0xc83878c0), WTC(0xc86304c0), + WTC(0xc88d4900), WTC(0xc8b73b80), WTC(0xc8e0d280), WTC(0xc90a0440), + /* part 1 */ + WTC(0xb5212e81), WTC(0xb4959501), WTC(0xb40ab501), WTC(0xb3808d81), + WTC(0xb2f71f01), WTC(0xb26e6881), WTC(0xb1e66a01), WTC(0xb15f2381), + WTC(0xb0d89401), WTC(0xb052bc01), WTC(0xafcd9a81), WTC(0xaf492f01), + WTC(0xaec57801), WTC(0xae427481), WTC(0xadc02281), WTC(0xad3e8101), + WTC(0xacbd9081), WTC(0xac3d5001), WTC(0xabbdc001), WTC(0xab3edf01), + WTC(0xaac0ad01), WTC(0xaa432981), WTC(0xa9c65401), WTC(0xa94a2c01), + WTC(0xa8ceb201), WTC(0xa853e501), WTC(0xa7d9c681), WTC(0xa7605601), + WTC(0xa6e79401), WTC(0xa66f8201), WTC(0xa5f81f81), WTC(0xa5816e81), + WTC(0xa50b6e81), WTC(0xa4962181), WTC(0xa4218801), WTC(0xa3ada281), + WTC(0xa33a7201), WTC(0xa2c7f801), WTC(0xa2563501), WTC(0xa1e52a81), + WTC(0xa174da81), WTC(0xa1054701), WTC(0xa0967201), WTC(0xa0285d81), + WTC(0x9fbb0981), WTC(0x9f4e7801), WTC(0x9ee2a901), WTC(0x9e779f81), + WTC(0x9e0d5e01), WTC(0x9da3e601), WTC(0x9d3b3b81), WTC(0x9cd35f81), + WTC(0x9c6c5481), WTC(0x9c061b81), WTC(0x9ba0b701), WTC(0x9b3c2801), + WTC(0x9ad87081), WTC(0x9a759301), WTC(0x9a139101), WTC(0x99b26c81), + WTC(0x99522801), WTC(0x98f2c601), WTC(0x98944901), WTC(0x9836b201), + WTC(0x97da0481), WTC(0x977e4181), WTC(0x97236b01), WTC(0x96c98381), + WTC(0x96708b81), WTC(0x96188501), WTC(0x95c17081), WTC(0x956b4f81), + WTC(0x95162381), WTC(0x94c1ee01), WTC(0x946eaf81), WTC(0x941c6901), + WTC(0x93cb1c81), WTC(0x937acb01), WTC(0x932b7501), WTC(0x92dd1b01), + WTC(0x928fbe01), WTC(0x92435d01), WTC(0x91f7f981), WTC(0x91ad9281), + WTC(0x91642781), WTC(0x911bb981), WTC(0x90d44781), WTC(0x908dd101), + WTC(0x90485401), WTC(0x9003ce81), WTC(0x8fc03f01), WTC(0x8f7da401), + WTC(0x8f3bfb01), WTC(0x8efb4181), WTC(0x8ebb7581), WTC(0x8e7c9301), + WTC(0x8e3e9481), WTC(0x8e017581), WTC(0x8dc53001), WTC(0x8d89be81), + WTC(0x8d4f1b01), WTC(0x8d154081), WTC(0x8cdc2901), WTC(0x8ca3cb01), + WTC(0x8c6c1b01), WTC(0x8c350d01), WTC(0x8bfe9401), WTC(0x8bc8a401), + WTC(0x8b933001), WTC(0x8b5e2c81), WTC(0x8b298b81), WTC(0x8af53e81), + WTC(0x8ac13381), WTC(0x8a8d5801), WTC(0x8a599a81), WTC(0x8a25f301), + WTC(0x89f26101), WTC(0x89bee581), WTC(0x898b8301), WTC(0x89586901), + WTC(0x8925f101), WTC(0x88f47901), WTC(0x88c45e81), WTC(0x88962981), + WTC(0x886a8a81), WTC(0x88423301), WTC(0x881dd301), WTC(0x87fdd781), + WTC(0x87d0ca81), WTC(0x87c76201), WTC(0x87bcab81), WTC(0x87b0ef01), + WTC(0x87a48b01), WTC(0x8797dd81), WTC(0x878b4301), WTC(0x877ede01), + WTC(0x87729701), WTC(0x87665481), WTC(0x8759fd01), WTC(0x874d8681), + WTC(0x8740f681), WTC(0x87345381), WTC(0x8727a381), WTC(0x871ae981), + WTC(0x870e2301), WTC(0x87014f81), WTC(0x86f46d81), WTC(0x86e77b81), + WTC(0x86da7901), WTC(0x86cd6681), WTC(0x86c04381), WTC(0x86b30f01), + WTC(0x86a5ca81), WTC(0x86987581), WTC(0x868b1001), WTC(0x867d9a81), + WTC(0x86701381), WTC(0x86627b01), WTC(0x8654d001), WTC(0x86471281), + WTC(0x86394301), WTC(0x862b6201), WTC(0x861d7081), WTC(0x860f6e01), + WTC(0x86015981), WTC(0x85f33281), WTC(0x85e4f801), WTC(0x85d6a981), + WTC(0x85c84801), WTC(0x85b9d481), WTC(0x85ab4f01), WTC(0x859cb781), + WTC(0x858e0e01), WTC(0x857f5101), WTC(0x85707f81), WTC(0x85619a01), + WTC(0x8552a181), WTC(0x85439601), WTC(0x85347901), WTC(0x85254a81), + WTC(0x85160981), WTC(0x8506b581), WTC(0x84f74e01), WTC(0x84e7d381), + WTC(0x84d84601), WTC(0x84c8a701), WTC(0x84b8f801), WTC(0x84a93801), + WTC(0x84996701), WTC(0x84898481), WTC(0x84798f81), WTC(0x84698881), + WTC(0x84597081), WTC(0x84494881), WTC(0x84391081), WTC(0x8428ca01), + WTC(0x84187401), WTC(0x84080d81), WTC(0x83f79681), WTC(0x83e70f01), + WTC(0x83d67881), WTC(0x83c5d381), WTC(0x83b52101), WTC(0x83a46181), + WTC(0x83939501), WTC(0x8382ba01), WTC(0x8371d081), WTC(0x8360d901), + WTC(0x834fd481), WTC(0x833ec381), WTC(0x832da781), WTC(0x831c8101), + WTC(0x830b4f81), WTC(0x82fa1181), WTC(0x82e8c801), WTC(0x82d77201), + WTC(0x82c61101), WTC(0x82b4a601), WTC(0x82a33281), WTC(0x8291b601), + WTC(0x82803101), WTC(0x826ea201), WTC(0x825d0901), WTC(0x824b6601), + WTC(0x8239b981), WTC(0x82280581), WTC(0x82164a81), WTC(0x82048881), + WTC(0x81f2bf81), WTC(0x81e0ee81), WTC(0x81cf1581), WTC(0x81bd3401), + WTC(0x81ab4b01), WTC(0x81995c01), WTC(0x81876781), WTC(0x81756d81), + WTC(0x81636d81), WTC(0x81516701), WTC(0x813f5981), WTC(0x812d4481), + WTC(0x811b2981), WTC(0x81090981), WTC(0x80f6e481), WTC(0x80e4bb81), + WTC(0x80d28d81), WTC(0x80c05a01), WTC(0x80ae1f81), WTC(0x809bdf01), + WTC(0x80899881), WTC(0x80774c81), WTC(0x8064fc81), WTC(0x8052a881), + WTC(0x80405101), WTC(0x802df701), WTC(0x801b9b01), WTC(0x80093e01), + WTC(0x0a74b120), WTC(0x0aa08a90), WTC(0x0acd2b80), WTC(0x0afa8860), + WTC(0x0b289590), WTC(0x0b574790), WTC(0x0b8692d0), WTC(0x0bb66bb0), + WTC(0x0be6c6b0), WTC(0x0c179830), WTC(0x0c48d500), WTC(0x0c7a7ad0), + WTC(0x0cac9000), WTC(0x0cdf1b60), WTC(0x0d122390), WTC(0x0d45a8f0), + WTC(0x0d79a5e0), WTC(0x0dae1480), WTC(0x0de2ef30), WTC(0x0e183800), + WTC(0x0e4df8c0), WTC(0x0e843b90), WTC(0x0ebb0a20), WTC(0x0ef26430), + WTC(0x0f2a3fc0), WTC(0x0f629280), WTC(0x0f9b5210), WTC(0x0fd47690), + WTC(0x100dfa80), WTC(0x1047d8a0), WTC(0x10820b40), WTC(0x10bc8b80), + WTC(0x10f75080), WTC(0x11325100), WTC(0x116d84e0), WTC(0x11a8ece0), + WTC(0x11e49420), WTC(0x122085a0), WTC(0x125ccbc0), WTC(0x12995a40), + WTC(0x12d60e80), WTC(0x1312c4c0), WTC(0x134f59e0), WTC(0x138bae60), + WTC(0x13c7a740), WTC(0x140329e0), WTC(0x143e1b60), WTC(0x147862a0), + WTC(0x14b1e840), WTC(0x14ea94c0), WTC(0x152250a0), WTC(0x15590380), + WTC(0x158e93e0), WTC(0x15c2e820), WTC(0x15f5e6e0), WTC(0x162779a0), + WTC(0x16578ca0), WTC(0x16860ca0), WTC(0x16b2e640), WTC(0x16de0b00), + WTC(0x17077140), WTC(0x172f0fa0), WTC(0x1754e200), WTC(0x17796080), + WTC(0x179d7f20), WTC(0x17c23760), WTC(0x17e87da0), WTC(0x1810cc80), + WTC(0x183b25a0), WTC(0x18678520), WTC(0x1895e700), WTC(0x18c64540), + WTC(0x18f89780), WTC(0x192cd560), WTC(0x1962f680), WTC(0x199af2a0), + WTC(0x19d4c1e0), WTC(0x1a105ca0), WTC(0x1a4dbae0), WTC(0x1a8cd660), + WTC(0x1acdaa60), WTC(0x1b103260), WTC(0x1b546940), WTC(0x1b9a4600), + WTC(0x1be1bb80), WTC(0x1c2abc60), WTC(0x1c753b80), WTC(0x1cc13860), + WTC(0x1d0ebe20), WTC(0x1d5dd8c0), WTC(0x1dae9480), WTC(0x1e010060), + WTC(0x1e552f40), WTC(0x1eab33e0), WTC(0x1f032060), WTC(0x1f5cfce0), + WTC(0x1fb8c660), WTC(0x201679c0), WTC(0x207611c0), WTC(0x20d75f00), + WTC(0x213a0640), WTC(0x219dab80), WTC(0x2201f480), WTC(0x2266ba80), + WTC(0x22cc0ac0), WTC(0x2331f4c0), WTC(0x23988940), WTC(0x23ffff40), + WTC(0x2468b340), WTC(0x24d30300), WTC(0x253f4900), WTC(0x25ad8980), + WTC(0x261d72c0), WTC(0x268eaec0), WTC(0x2700e880), WTC(0x2773db40), + WTC(0x27e751c0), WTC(0x285b1780), WTC(0x28cefbc0), WTC(0x29431f80), + WTC(0x29b7f680), WTC(0x2a2df780), WTC(0x2aa59880), WTC(0x2b1f3280), + WTC(0x2b9b0140), WTC(0x2c194000), WTC(0x2c9a2540), WTC(0x2d1d8dc0), + WTC(0x2da2fc40), WTC(0x2e29ee80), WTC(0x2eb1e340), WTC(0x2f3a4e40), + WTC(0x2fc29980), WTC(0x304a2ec0), WTC(0x30d07cc0), WTC(0x315566c0), + WTC(0x31d94480), WTC(0x325c72c0), WTC(0x32df51c0), WTC(0x33628c80), + WTC(0x33e71a00), WTC(0x346df400), WTC(0x34f80dc0), WTC(0x3585c640), + WTC(0x3616e700), WTC(0x36ab3380), WTC(0x37426ac0), WTC(0x37dbe840), + WTC(0x3876a340), WTC(0x39118f40), WTC(0x39aba2c0), WTC(0x3a4422c0), + WTC(0x3adaa200), WTC(0x3b6eb6c0), WTC(0x3bfffd80), WTC(0x3c8e9380), + WTC(0x3d1b1780), WTC(0x3da62e00), WTC(0x3e307b00), WTC(0x3eba97c0), + WTC(0x3f451280), WTC(0x3fd07940), WTC(0x405d577f), WTC(0x40ebf57f), + WTC(0x417c59ff), WTC(0x420e897f), WTC(0x42a2857f), WTC(0x4338307f), + WTC(0x43cf4d7f), WTC(0x44679cff), WTC(0x4500dfff), WTC(0x459ac2ff), + WTC(0x4634e2ff), WTC(0x46ced9ff), WTC(0x4768437f), WTC(0x4800d27f), + WTC(0x489850ff), WTC(0x492e88ff), WTC(0x49c346ff), WTC(0x4a5678ff), + WTC(0x4ae82f7f), WTC(0x4b787c7f), WTC(0x4c07717f), WTC(0x4c95337f), + WTC(0x4d21f77f), WTC(0x4dadf3ff), WTC(0x4e395eff), WTC(0x4ec4657f), + WTC(0x4f4f297f), WTC(0x4fd9cd7f), WTC(0x5064737f), WTC(0x50ef3cff), + WTC(0x517a46ff), WTC(0x5205b0ff), WTC(0x529197ff), WTC(0x531e04ff), + WTC(0x53aaeb7f), WTC(0x54383eff), WTC(0x54c5ef7f), WTC(0x5553a8ff), + WTC(0x55e0d57f), WTC(0x566cda7f), WTC(0x56f720ff), WTC(0x577f4aff), + WTC(0x580534ff), WTC(0x5888bd7f), WTC(0x5909c6ff), WTC(0x598890ff), + WTC(0x5a05b7ff), WTC(0x5a81db7f), WTC(0x5afd99ff), WTC(0x5b794a7f), + WTC(0x5bf5007f), WTC(0x5c70cbff), WTC(0x5cecbb7f), WTC(0x5d68c47f), + WTC(0x5de4c3ff), WTC(0x5e6094ff), WTC(0x5edc127f), WTC(0x5f56fdff), + WTC(0x5fd1017f), WTC(0x6049c67f), WTC(0x60c0f67f), WTC(0x613650ff), + WTC(0x61a9a9ff), WTC(0x621ad77f), WTC(0x6289b37f), WTC(0x62f67fff), + WTC(0x6361e87f), WTC(0x63cc9bff), WTC(0x6437457f), WTC(0x64a2247f), + WTC(0x650d0c7f), WTC(0x6577cc7f), WTC(0x65e2327f), WTC(0x664bf57f), + WTC(0x66b4b5ff), WTC(0x671c137f), WTC(0x6781afff), WTC(0x67e579ff), + WTC(0x6847abff), WTC(0x68a882ff), WTC(0x69083bff), WTC(0x6966fbff), + WTC(0x69c4cfff), WTC(0x6a21c57f), WTC(0x6a7de87f), WTC(0x6ad9377f), + WTC(0x6b33a5ff), WTC(0x6b8d257f), WTC(0x6be5a8ff), WTC(0x6c3d20ff), + WTC(0x6c9380ff), WTC(0x6ce8ba7f), WTC(0x6d3cbfff), WTC(0x6d8f827f), + /* part 2 */ + WTC(0xad98b481), WTC(0xaead9d01), WTC(0xafbfc381), WTC(0xb0cf4d01), + WTC(0xb1dc5f81), WTC(0xb2e72081), WTC(0xb3efb501), WTC(0xb4f64381), + WTC(0xb5faf101), WTC(0xb6fde401), WTC(0xb7ff4001), WTC(0xb8ff1601), + WTC(0xb9fd6181), WTC(0xbafa1d01), WTC(0xbbf54401), WTC(0xbceed101), + WTC(0xbde6c081), WTC(0xbedd0e81), WTC(0xbfd1b701), WTC(0xc0c4b440), + WTC(0xc1b5ffc0), WTC(0xc2a59340), WTC(0xc3936780), WTC(0xc47f78c0), + WTC(0xc569c600), WTC(0xc6524d40), WTC(0xc7390dc0), WTC(0xc81e04c0), + WTC(0xc9012e00), WTC(0xc9e28540), WTC(0xcac20700), WTC(0xcb9fb1c0), + WTC(0xcc7b8640), WTC(0xcd558600), WTC(0xce2db200), WTC(0xcf0409c0), + WTC(0xcfd88a40), WTC(0xd0ab3080), WTC(0xd17bfa00), WTC(0xd24ae640), + WTC(0xd317f7c0), WTC(0xd3e33080), WTC(0xd4ac9340), WTC(0xd5741f40), + WTC(0xd639d2c0), WTC(0xd6fdab00), WTC(0xd7bfa5c0), WTC(0xd87fc300), + WTC(0xd93e0600), WTC(0xd9fa7180), WTC(0xdab50900), WTC(0xdb6dccc0), + WTC(0xdc24ba80), WTC(0xdcd9d000), WTC(0xdd8d0b80), WTC(0xde3e6dc0), + WTC(0xdeedf9c0), WTC(0xdf9bb340), WTC(0xe0479e20), WTC(0xe0f1bac0), + WTC(0xe19a07e0), WTC(0xe2408380), WTC(0xe2e52c00), WTC(0xe38802e0), + WTC(0xe4290c00), WTC(0xe4c84c20), WTC(0xe565c760), WTC(0xe6017f20), + WTC(0xe69b7240), WTC(0xe7339f60), WTC(0xe7ca0500), WTC(0xe85ea480), + WTC(0xe8f18180), WTC(0xe9829fc0), WTC(0xea1202e0), WTC(0xea9fab80), + WTC(0xeb2b9700), WTC(0xebb5c2a0), WTC(0xec3e2bc0), WTC(0xecc4d300), + WTC(0xed49bc80), WTC(0xedccec60), WTC(0xee4e66a0), WTC(0xeece2d80), + WTC(0xef4c41e0), WTC(0xefc8a480), WTC(0xf0435610), WTC(0xf0bc5c60), + WTC(0xf133c230), WTC(0xf1a99270), WTC(0xf21dd7b0), WTC(0xf29097e0), + WTC(0xf301d3d0), WTC(0xf3718c20), WTC(0xf3dfc180), WTC(0xf44c7100), + WTC(0xf4b79480), WTC(0xf52125b0), WTC(0xf5891df0), WTC(0xf5ef6fe0), + WTC(0xf6540730), WTC(0xf6b6cf50), WTC(0xf717b490), WTC(0xf776b9a0), + WTC(0xf7d3f720), WTC(0xf82f86e8), WTC(0xf8898260), WTC(0xf8e1fc50), + WTC(0xf93900f0), WTC(0xf98e9c28), WTC(0xf9e2d940), WTC(0xfa35b4a0), + WTC(0xfa871bd8), WTC(0xfad6fbd0), WTC(0xfb254250), WTC(0xfb71f0c0), + WTC(0xfbbd1c28), WTC(0xfc06da60), WTC(0xfc4f40a4), WTC(0xfc965500), + WTC(0xfcdc0e5c), WTC(0xfd2062f4), WTC(0xfd6348d0), WTC(0xfda4b1b8), + WTC(0xfde48b2c), WTC(0xfe22c280), WTC(0xfe5f462a), WTC(0xfe9a1f2e), + WTC(0xfed3711c), WTC(0xff0b60ac), WTC(0xff4212dd), WTC(0xff77b344), + WTC(0xffac7407), WTC(0xffe08796), WTC(0x00141e37), WTC(0x00473665), + WTC(0x00799cd0), WTC(0x00ab1bff), WTC(0x00db7d8b), WTC(0x010a75ea), + WTC(0x0137a46e), WTC(0x0162a77a), WTC(0x018b20ac), WTC(0x01b0fb7a), + WTC(0x01d46d3c), WTC(0x01f5ae7c), WTC(0x0214f91c), WTC(0x0232a5cc), + WTC(0x024f2c04), WTC(0x026b048c), WTC(0x0286a628), WTC(0x02a25808), + WTC(0x02be31c0), WTC(0x02da48e0), WTC(0x02f6b09c), WTC(0x031345dc), + WTC(0x032faf50), WTC(0x034b9148), WTC(0x036690e8), WTC(0x0380658c), + WTC(0x0398d8e4), WTC(0x03afb568), WTC(0x03c4c6e0), WTC(0x03d7f770), + WTC(0x03e94f9c), WTC(0x03f8d938), WTC(0x04069ee8), WTC(0x0412bef8), + WTC(0x041d6b30), WTC(0x0426d638), WTC(0x042f3288), WTC(0x0436ad98), + WTC(0x043d6fd0), WTC(0x0443a170), WTC(0x04496a40), WTC(0x044ee728), + WTC(0x04542a40), WTC(0x04594520), WTC(0x045e4890), WTC(0x04633210), + WTC(0x0467ebe8), WTC(0x046c5f80), WTC(0x04707630), WTC(0x047417f0), + WTC(0x04772b58), WTC(0x047996e8), WTC(0x047b4140), WTC(0x047c12a0), + WTC(0x047bf520), WTC(0x047ad2e0), WTC(0x04789690), WTC(0x047539c8), + WTC(0x0470c4b8), WTC(0x046b4058), WTC(0x0464b600), WTC(0x045d3a08), + WTC(0x0454ebc8), WTC(0x044beb00), WTC(0x04425798), WTC(0x043853b0), + WTC(0x042e0398), WTC(0x04238bd8), WTC(0x04190f98), WTC(0x040e9670), + WTC(0x04040c18), WTC(0x03f95b30), WTC(0x03ee6e20), WTC(0x03e32b64), + WTC(0x03d77598), WTC(0x03cb2f24), WTC(0x03be3b18), WTC(0x03b08b18), + WTC(0x03a21f64), WTC(0x0392f8d4), WTC(0x038318e0), WTC(0x03728e94), + WTC(0x03617694), WTC(0x034fee18), WTC(0x033e11f4), WTC(0x032bf530), + WTC(0x0319a114), WTC(0x03071e80), WTC(0x02f475f4), WTC(0x02e1a7c0), + WTC(0x02ceac04), WTC(0x02bb7a84), WTC(0x02a80af0), WTC(0x029452b0), + WTC(0x028044e0), WTC(0x026bd488), WTC(0x0256f558), WTC(0x0241a940), + WTC(0x022c0084), WTC(0x02160c08), WTC(0x01ffdc5a), WTC(0x01e97ad2), + WTC(0x01d2e982), WTC(0x01bc2a2a), WTC(0x01a53e8c), WTC(0x018e2860), + WTC(0x0176e94c), WTC(0x015f82fa), WTC(0x0147f70e), WTC(0x013046c2), + WTC(0x011872e8), WTC(0x01007c4a), WTC(0x00e863cf), WTC(0x00d02c81), + WTC(0x00b7db94), WTC(0x009f7651), WTC(0x00870204), WTC(0x006e83f8), + WTC(0x00560176), WTC(0x003d7fcb), WTC(0x0025043f), WTC(0x000c941f), + WTC(0xd65574c0), WTC(0xd5ebc100), WTC(0xd582d080), WTC(0xd51a9cc0), + WTC(0xd4b31f80), WTC(0xd44c5280), WTC(0xd3e62f80), WTC(0xd380b040), + WTC(0xd31bce40), WTC(0xd2b78380), WTC(0xd253ca40), WTC(0xd1f0acc0), + WTC(0xd18e4580), WTC(0xd12caf40), WTC(0xd0cc0400), WTC(0xd06c40c0), + WTC(0xd00d4740), WTC(0xcfaef6c0), WTC(0xcf513140), WTC(0xcef3fa80), + WTC(0xce977a40), WTC(0xce3bd980), WTC(0xcde13f40), WTC(0xcd87a880), + WTC(0xcd2ee800), WTC(0xccd6cf00), WTC(0xcc7f2f40), WTC(0xcc27e880), + WTC(0xcbd0ea00), WTC(0xcb7a2380), WTC(0xcb238380), WTC(0xcaccee80), + WTC(0xca763ec0), WTC(0xca1f4d00), WTC(0xc9c7f480), WTC(0xc9703b40), + WTC(0xc9185200), WTC(0xc8c06b00), WTC(0xc868b4c0), WTC(0xc81100c0), + WTC(0xc7b8c280), WTC(0xc75f6a40), WTC(0xc7046900), WTC(0xc6a74340), + WTC(0xc6479300), WTC(0xc5e4f200), WTC(0xc57efac0), WTC(0xc5154880), + WTC(0xc4a77780), WTC(0xc4352440), WTC(0xc3bdeac0), WTC(0xc3416740), + WTC(0xc2bf33c0), WTC(0xc236eb40), WTC(0xc1a82900), WTC(0xc11290c0), + WTC(0xc075cf00), WTC(0xbfd19081), WTC(0xbf258401), WTC(0xbe716d81), + WTC(0xbdb52b81), WTC(0xbcf09a81), WTC(0xbc23af81), WTC(0xbb505c01), + WTC(0xba7a9081), WTC(0xb9a65281), WTC(0xb8d79301), WTC(0xb8104c01), + WTC(0xb7508181), WTC(0xb6982201), WTC(0xb5e71b01), WTC(0xb53d5b01), + WTC(0xb49ad081), WTC(0xb3ff6901), WTC(0xb36b1301), WTC(0xb2ddbd01), + WTC(0xb2575481), WTC(0xb1d7c801), WTC(0xb15f0601), WTC(0xb0ecfc01), + WTC(0xb0819881), WTC(0xb01cca01), WTC(0xafbe7e01), WTC(0xaf66a301), + WTC(0xaf152701), WTC(0xaec9f881), WTC(0xae850601), WTC(0xae463c81), + WTC(0xae0d8b01), WTC(0xaddae001), WTC(0xadae2881), WTC(0xad875381), + WTC(0xad664f81), WTC(0xad4b0981), WTC(0xad357081), WTC(0xad257301), + WTC(0xad1afe01), WTC(0xad160081), WTC(0xad166901), WTC(0xad1c2481), + WTC(0xad272201), WTC(0xad374f81), WTC(0xad4c9b01), WTC(0xad66f381), + WTC(0xad864601), WTC(0xadaa8101), WTC(0xadd39301), WTC(0xae016a01), + WTC(0xae33f481), WTC(0xae6b2001), WTC(0xaea6db01), WTC(0xaee71381), + WTC(0xaf2bb801), WTC(0xaf74b681), WTC(0xafc1fd01), WTC(0xb0137a01), + WTC(0xb0691b81), WTC(0xb0c2cf81), WTC(0xb1208481), WTC(0xb1822881), + WTC(0xb1e7a981), WTC(0xb250f601), WTC(0xb2bdfc01), WTC(0xb32eaa01), + WTC(0xb3a2ed01), WTC(0xb41ab481), WTC(0xb495ee01), WTC(0xb5148801), + WTC(0xb5967081), WTC(0xb61b9581), WTC(0xb6a3e581), WTC(0xb72f4e01), + WTC(0xb7bdbe01), WTC(0xb84f2381), WTC(0xb8e36c81), WTC(0xb97a8701), + WTC(0xba146101), WTC(0xbab0e981), WTC(0xbb500d81), WTC(0xbbf1bc81), + WTC(0xbc95e381), WTC(0xbd3c7181), WTC(0xbde55481), WTC(0xbe907a01), + WTC(0xbf3dd101), WTC(0xbfed4701), WTC(0xc09ecac0), WTC(0xc1524a00), + WTC(0xc207b300), WTC(0xc2bef440), WTC(0xc377fb80), WTC(0xc432b700), + WTC(0xc4ef1500), WTC(0xc5ad03c0), WTC(0xc66c7140), WTC(0xc72d4bc0), + WTC(0xc7ef8180), WTC(0xc8b30080), WTC(0xc977b700), WTC(0xca3d9340), + WTC(0xcb048340), WTC(0xcbcc7540), WTC(0xcc955740), WTC(0xcd5f17c0), + WTC(0xce29a480), WTC(0xcef4ec00), WTC(0xcfc0dc80), WTC(0xd08d63c0), + WTC(0xd15a7040), WTC(0xd227f000), WTC(0xd2f5d140), WTC(0xd3c40240), + WTC(0xd4927100), WTC(0xd5610b80), WTC(0xd62fc080), WTC(0xd6fe7dc0), + WTC(0xd7cd3140), WTC(0xd89bc980), WTC(0xd96a34c0), WTC(0xda3860c0), + WTC(0xdb063c00), WTC(0xdbd3b480), WTC(0xdca0b880), WTC(0xdd6d3640), + WTC(0xde391bc0), WTC(0xdf045740), WTC(0xdfced6c0), WTC(0xe09888c0), + WTC(0xe1615b20), WTC(0xe2293c20), WTC(0xe2f01a00), WTC(0xe3b5e2c0), + WTC(0xe47a84c0), WTC(0xe53dee00), WTC(0xe6000cc0), WTC(0xe6c0cf20), + WTC(0xe7802360), WTC(0xe83df7a0), WTC(0xe8fa39e0), WTC(0xe9b4d880), + WTC(0xea6dc1a0), WTC(0xeb24e360), WTC(0xebda2be0), WTC(0xec8d8960), + WTC(0xed3eea20), WTC(0xedee3c00), WTC(0xee9b6d80), WTC(0xef466ca0), + WTC(0xefef2780), WTC(0xf0958c50), WTC(0xf1398950), WTC(0xf1db0ca0), + WTC(0xf27a0470), WTC(0xf3165ed0), WTC(0xf3b00a10), WTC(0xf446f440), + WTC(0xf4db0b90), WTC(0xf56c3e30), WTC(0xf5fa7a50), WTC(0xf685ae10), + WTC(0xf70dc7a0), WTC(0xf792b520), WTC(0xf81464c8), WTC(0xf892c4c0), + WTC(0xf90dc330), WTC(0xf9854e40), WTC(0xf9f95418), WTC(0xfa69c2f0), + WTC(0xfad688e8), WTC(0xfb3f9428), WTC(0xfba4d2e8), WTC(0xfc063344), + WTC(0xfc63a370), WTC(0xfcbd1194), WTC(0xfd126bdc), WTC(0xfd63a06c), + WTC(0xfdb09d78), WTC(0xfdf95124), WTC(0xfe3da99e), WTC(0xfe7d950e), + WTC(0xfeb901a2), WTC(0xfeefdd80), WTC(0xff2216d7), WTC(0xff4f9bcf), + WTC(0xff785a93), WTC(0xff9c414e), WTC(0xffbb3e2b), WTC(0xffd53f54), + WTC(0xffea32f4), WTC(0xfffa0735), WTC(0x0004aa43), WTC(0x000a0a47), + WTC(0x000a156c), WTC(0x0004b9de), WTC(0xfff9e5c5), WTC(0xffe9874e)}; + +const FIXP_WTB LowDelaySynthesis480[1440] = { + WTC(0xdad2e6c0), WTC(0xdb1da900), WTC(0xdb68ce40), WTC(0xdbb45840), + WTC(0xdc004940), WTC(0xdc4ca280), WTC(0xdc996500), WTC(0xdce69140), + WTC(0xdd342780), WTC(0xdd822700), WTC(0xddd08a80), WTC(0xde1f4d00), + WTC(0xde6e6ec0), WTC(0xdebdec40), WTC(0xdf0dba80), WTC(0xdf5dd540), + WTC(0xdfae3cc0), WTC(0xdfff0500), WTC(0xe0505140), WTC(0xe0a22980), + WTC(0xe0f488e0), WTC(0xe1476180), WTC(0xe19aa480), WTC(0xe1ee4d80), + WTC(0xe2425400), WTC(0xe29689a0), WTC(0xe2eacd60), WTC(0xe33f2420), + WTC(0xe393a300), WTC(0xe3e87f20), WTC(0xe43dcee0), WTC(0xe4938a80), + WTC(0xe4e9b0a0), WTC(0xe5404300), WTC(0xe5973e60), WTC(0xe5ee9b80), + WTC(0xe64649e0), WTC(0xe69e37e0), WTC(0xe6f65ec0), WTC(0xe74eb6c0), + WTC(0xe7a73000), WTC(0xe7ffbe40), WTC(0xe8585ee0), WTC(0xe8b10740), + WTC(0xe9099c40), WTC(0xe96214e0), WTC(0xe9ba79a0), WTC(0xea12e7c0), + WTC(0xea6b89c0), WTC(0xeac46580), WTC(0xeb1d7260), WTC(0xeb76b620), + WTC(0xebd036c0), WTC(0xec29e520), WTC(0xec83aa60), WTC(0xecdd5a00), + WTC(0xed36d500), WTC(0xed901540), WTC(0xede91160), WTC(0xee41bc20), + WTC(0xee9a0ee0), WTC(0xeef20860), WTC(0xef49a7e0), WTC(0xefa0ec00), + WTC(0xeff7d1c0), WTC(0xf04e56b0), WTC(0xf0a476e0), WTC(0xf0fa2f60), + WTC(0xf14f80e0), WTC(0xf1a46e10), WTC(0xf1f8fe80), WTC(0xf24d34a0), + WTC(0xf2a10bb0), WTC(0xf2f48210), WTC(0xf3479cc0), WTC(0xf39a5be0), + WTC(0xf3ecb8f0), WTC(0xf43eafa0), WTC(0xf4903b50), WTC(0xf4e14e80), + WTC(0xf531d6a0), WTC(0xf581bc10), WTC(0xf5d0e9c0), WTC(0xf61f5250), + WTC(0xf66ce6e0), WTC(0xf6b99330), WTC(0xf7054eb0), WTC(0xf7501f20), + WTC(0xf79a0750), WTC(0xf7e30700), WTC(0xf82b2fc0), WTC(0xf872a138), + WTC(0xf8b97f18), WTC(0xf8ffe668), WTC(0xf945e538), WTC(0xf98b8860), + WTC(0xf9d0f380), WTC(0xfa165148), WTC(0xfa5bb8a8), WTC(0xfaa13df8), + WTC(0xfae6fb00), WTC(0xfb2cf8c8), WTC(0xfb732a80), WTC(0xfbb97910), + WTC(0xfbffcd10), WTC(0xfc463478), WTC(0xfc8cd3fc), WTC(0xfcd3be5c), + WTC(0xfd1afa90), WTC(0xfd62aa84), WTC(0xfdab0288), WTC(0xfdf404b4), + WTC(0xfe3d3006), WTC(0xfe85b20e), WTC(0xfecca4cc), WTC(0xff10d559), + WTC(0xff50579b), WTC(0xff8a40d2), WTC(0xffb7d86e), WTC(0xffef6bbb), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbff67a01), WTC(0xbfecaa81), WTC(0xbfe2d901), WTC(0xbfd90601), + WTC(0xbfcf3181), WTC(0xbfc55c81), WTC(0xbfbb8701), WTC(0xbfb1b101), + WTC(0xbfa7dc01), WTC(0xbf9e0701), WTC(0xbf943301), WTC(0xbf8a5f81), + WTC(0xbf808b81), WTC(0xbf76b701), WTC(0xbf6ce201), WTC(0xbf630d81), + WTC(0xbf593a01), WTC(0xbf4f6801), WTC(0xbf459681), WTC(0xbf3bc601), + WTC(0xbf31f501), WTC(0xbf282501), WTC(0xbf1e5501), WTC(0xbf148681), + WTC(0xbf0aba01), WTC(0xbf00ef81), WTC(0xbef72681), WTC(0xbeed5f01), + WTC(0xbee39801), WTC(0xbed9d281), WTC(0xbed00f81), WTC(0xbec64e81), + WTC(0xbebc9181), WTC(0xbeb2d681), WTC(0xbea91f01), WTC(0xbe9f6901), + WTC(0xbe95b581), WTC(0xbe8c0501), WTC(0xbe825801), WTC(0xbe78b001), + WTC(0xbe6f0c01), WTC(0xbe656c01), WTC(0xbe5bd001), WTC(0xbe523781), + WTC(0xbe48a301), WTC(0xbe3f1381), WTC(0xbe358901), WTC(0xbe2c0501), + WTC(0xbe228681), WTC(0xbe190d81), WTC(0xbe0f9a01), WTC(0xbe062b81), + WTC(0xbdfcc301), WTC(0xbdf36101), WTC(0xbdea0681), WTC(0xbde0b301), + WTC(0xbdd76701), WTC(0xbdce2181), WTC(0xbdc4e301), WTC(0xbdbbab01), + WTC(0xbdb27b01), WTC(0xbda95301), WTC(0xbda03381), WTC(0xbd971c81), + WTC(0xbd8e0e01), WTC(0xbd850701), WTC(0xbd7c0781), WTC(0xbd731081), + WTC(0xbd6a2201), WTC(0xbd613d81), WTC(0xbd586281), WTC(0xbd4f9101), + WTC(0xbd46c801), WTC(0xbd3e0801), WTC(0xbd355081), WTC(0xbd2ca281), + WTC(0xbd23ff01), WTC(0xbd1b6501), WTC(0xbd12d581), WTC(0xbd0a4f81), + WTC(0xbd01d281), WTC(0xbcf95e81), WTC(0xbcf0f381), WTC(0xbce89281), + WTC(0xbce03b81), WTC(0xbcd7ef01), WTC(0xbccfac01), WTC(0xbcc77181), + WTC(0xbcbf4001), WTC(0xbcb71701), WTC(0xbcaef701), WTC(0xbca6e101), + WTC(0xbc9ed481), WTC(0xbc96d101), WTC(0xbc8ed701), WTC(0xbc86e581), + WTC(0xbc7efc81), WTC(0xbc771c01), WTC(0xbc6f4401), WTC(0xbc677501), + WTC(0xbc5fae81), WTC(0xbc57f101), WTC(0xbc503b81), WTC(0xbc488e81), + WTC(0xbc40e881), WTC(0xbc394901), WTC(0xbc31af01), WTC(0xbc2a1a81), + WTC(0xbc228f01), WTC(0xbc1b1081), WTC(0xbc13a481), WTC(0xbc0c4581), + WTC(0xbc04e381), WTC(0xbbfd6c01), WTC(0xbbf5d181), WTC(0xbbee2f81), + WTC(0xbbe6c801), WTC(0xbbdfdb81), WTC(0xbbd9a781), WTC(0xbbd45881), + WTC(0xbbd01301), WTC(0xbbccfc81), WTC(0xbbcb2281), WTC(0xbbca5d01), + WTC(0xbbca7481), WTC(0xbbcb3201), WTC(0xbbcc6b01), WTC(0xbbce0601), + WTC(0xbbcfea81), WTC(0xbbd20301), WTC(0xbbd45601), WTC(0xbbd70201), + WTC(0xbbda2501), WTC(0xbbdddb01), WTC(0xbbe23281), WTC(0xbbe73201), + WTC(0xbbece281), WTC(0xbbf34281), WTC(0xbbfa3c01), WTC(0xbc01b381), + WTC(0xbc098d81), WTC(0xbc11b681), WTC(0xbc1a2401), WTC(0xbc22cd81), + WTC(0xbc2bab01), WTC(0xbc34c081), WTC(0xbc3e1981), WTC(0xbc47c281), + WTC(0xbc51cb01), WTC(0xbc5c4c81), WTC(0xbc676501), WTC(0xbc733401), + WTC(0xbc7fd301), WTC(0xbc8d5101), WTC(0xbc9bb901), WTC(0xbcab1781), + WTC(0xbcbb7001), WTC(0xbcccbd01), WTC(0xbcdef701), WTC(0xbcf21601), + WTC(0xbd060c81), WTC(0xbd1ac801), WTC(0xbd303581), WTC(0xbd464281), + WTC(0xbd5ce281), WTC(0xbd740b81), WTC(0xbd8bb281), WTC(0xbda3d081), + WTC(0xbdbc6381), WTC(0xbdd56b81), WTC(0xbdeee981), WTC(0xbe08e181), + WTC(0xbe236001), WTC(0xbe3e7201), WTC(0xbe5a2301), WTC(0xbe767e81), + WTC(0xbe938c81), WTC(0xbeb15701), WTC(0xbecfe601), WTC(0xbeef4601), + WTC(0xbf0f8301), WTC(0xbf30a901), WTC(0xbf52c101), WTC(0xbf75cc81), + WTC(0xbf99cb01), WTC(0xbfbebb81), WTC(0xbfe48981), WTC(0xc00b04c0), + WTC(0xc031f880), WTC(0xc0593340), WTC(0xc0809280), WTC(0xc0a802c0), + WTC(0xc0cf6ec0), WTC(0xc0f6cc00), WTC(0xc11e3a80), WTC(0xc145f040), + WTC(0xc16e22c0), WTC(0xc196fb00), WTC(0xc1c08680), WTC(0xc1eaca00), + WTC(0xc215cbc0), WTC(0xc2418940), WTC(0xc26df5c0), WTC(0xc29b02c0), + WTC(0xc2c8a140), WTC(0xc2f6b500), WTC(0xc3251740), WTC(0xc353a0c0), + WTC(0xc3822c00), WTC(0xc3b09940), WTC(0xc3deccc0), WTC(0xc40ca800), + WTC(0xc43a28c0), WTC(0xc4678a00), WTC(0xc4951780), WTC(0xc4c31d00), + WTC(0xc4f1bdc0), WTC(0xc520e840), WTC(0xc5508440), WTC(0xc5807900), + WTC(0xc5b09e80), WTC(0xc5e0bfc0), WTC(0xc610a740), WTC(0xc64029c0), + WTC(0xc66f49c0), WTC(0xc69e2180), WTC(0xc6ccca40), WTC(0xc6fb5700), + WTC(0xc729cc80), WTC(0xc7582b40), WTC(0xc7867480), WTC(0xc7b4a480), + WTC(0xc7e2afc0), WTC(0xc8108a80), WTC(0xc83e28c0), WTC(0xc86b7f00), + WTC(0xc8988100), WTC(0xc8c52340), WTC(0xc8f15980), WTC(0xc91d1840), + WTC(0xb4d6a381), WTC(0xb4422b81), WTC(0xb3ae8601), WTC(0xb31bb301), + WTC(0xb289b181), WTC(0xb1f88181), WTC(0xb1682281), WTC(0xb0d89401), + WTC(0xb049d601), WTC(0xafbbe801), WTC(0xaf2ec901), WTC(0xaea27681), + WTC(0xae16f001), WTC(0xad8c3301), WTC(0xad023f01), WTC(0xac791401), + WTC(0xabf0b181), WTC(0xab691681), WTC(0xaae24301), WTC(0xaa5c3601), + WTC(0xa9d6ef01), WTC(0xa9526d81), WTC(0xa8ceb201), WTC(0xa84bbb81), + WTC(0xa7c98b01), WTC(0xa7482101), WTC(0xa6c77e01), WTC(0xa647a301), + WTC(0xa5c89001), WTC(0xa54a4701), WTC(0xa4ccc901), WTC(0xa4501601), + WTC(0xa3d43001), WTC(0xa3591801), WTC(0xa2dece81), WTC(0xa2655581), + WTC(0xa1ecae01), WTC(0xa174da81), WTC(0xa0fddd81), WTC(0xa087b981), + WTC(0xa0127081), WTC(0x9f9e0301), WTC(0x9f2a7281), WTC(0x9eb7c101), + WTC(0x9e45f081), WTC(0x9dd50481), WTC(0x9d650081), WTC(0x9cf5e701), + WTC(0x9c87ba81), WTC(0x9c1a7c81), WTC(0x9bae2f81), WTC(0x9b42d581), + WTC(0x9ad87081), WTC(0x9a6f0381), WTC(0x9a069001), WTC(0x999f1981), + WTC(0x9938a281), WTC(0x98d32d81), WTC(0x986ebd81), WTC(0x980b5501), + WTC(0x97a8f681), WTC(0x9747a481), WTC(0x96e76101), WTC(0x96882e01), + WTC(0x962a0c81), WTC(0x95ccff01), WTC(0x95710601), WTC(0x95162381), + WTC(0x94bc5981), WTC(0x9463a881), WTC(0x940c1281), WTC(0x93b59901), + WTC(0x93603d01), WTC(0x930bff81), WTC(0x92b8e101), WTC(0x9266e281), + WTC(0x92160301), WTC(0x91c64301), WTC(0x9177a301), WTC(0x912a2201), + WTC(0x90ddc001), WTC(0x90927b81), WTC(0x90485401), WTC(0x8fff4601), + WTC(0x8fb74f81), WTC(0x8f706f01), WTC(0x8f2aa101), WTC(0x8ee5e301), + WTC(0x8ea23201), WTC(0x8e5f8881), WTC(0x8e1de001), WTC(0x8ddd3201), + WTC(0x8d9d7781), WTC(0x8d5eaa01), WTC(0x8d20c301), WTC(0x8ce3ba81), + WTC(0x8ca78781), WTC(0x8c6c1b01), WTC(0x8c316681), WTC(0x8bf75b01), + WTC(0x8bbde981), WTC(0x8b850281), WTC(0x8b4c9701), WTC(0x8b149701), + WTC(0x8adcee01), WTC(0x8aa58681), WTC(0x8a6e4a01), WTC(0x8a372881), + WTC(0x8a001f01), WTC(0x89c92f81), WTC(0x89925a81), WTC(0x895bcd01), + WTC(0x8925f101), WTC(0x88f13801), WTC(0x88be1681), WTC(0x888d3181), + WTC(0x885f8481), WTC(0x88353501), WTC(0x88124281), WTC(0x87e73d81), + WTC(0x87d4ac81), WTC(0x87cb5101), WTC(0x87c05e81), WTC(0x87b42481), + WTC(0x87a70e81), WTC(0x87998f01), WTC(0x878c1881), WTC(0x877ede01), + WTC(0x8771c601), WTC(0x8764b101), WTC(0x87578181), WTC(0x874a2f01), + WTC(0x873cc201), WTC(0x872f4201), WTC(0x8721b481), WTC(0x87141b01), + WTC(0x87067281), WTC(0x86f8ba81), WTC(0x86eaf081), WTC(0x86dd1481), + WTC(0x86cf2601), WTC(0x86c12401), WTC(0x86b30f01), WTC(0x86a4e781), + WTC(0x8696ad01), WTC(0x86886001), WTC(0x867a0081), WTC(0x866b8d81), + WTC(0x865d0581), WTC(0x864e6901), WTC(0x863fb701), WTC(0x8630f181), + WTC(0x86221801), WTC(0x86132c01), WTC(0x86042c01), WTC(0x85f51681), + WTC(0x85e5eb81), WTC(0x85d6a981), WTC(0x85c75201), WTC(0x85b7e601), + WTC(0x85a86581), WTC(0x8598d081), WTC(0x85892681), WTC(0x85796601), + WTC(0x85698e81), WTC(0x8559a081), WTC(0x85499d01), WTC(0x85398481), + WTC(0x85295881), WTC(0x85191801), WTC(0x8508c181), WTC(0x84f85581), + WTC(0x84e7d381), WTC(0x84d73c01), WTC(0x84c69101), WTC(0x84b5d301), + WTC(0x84a50201), WTC(0x84941d81), WTC(0x84832481), WTC(0x84721701), + WTC(0x8460f581), WTC(0x844fc081), WTC(0x843e7a81), WTC(0x842d2281), + WTC(0x841bb981), WTC(0x840a3e81), WTC(0x83f8b001), WTC(0x83e70f01), + WTC(0x83d55d01), WTC(0x83c39a81), WTC(0x83b1c881), WTC(0x839fe801), + WTC(0x838df801), WTC(0x837bf801), WTC(0x8369e781), WTC(0x8357c701), + WTC(0x83459881), WTC(0x83335c81), WTC(0x83211501), WTC(0x830ec081), + WTC(0x82fc5f01), WTC(0x82e9ef01), WTC(0x82d77201), WTC(0x82c4e801), + WTC(0x82b25301), WTC(0x829fb401), WTC(0x828d0b01), WTC(0x827a5801), + WTC(0x82679901), WTC(0x8254cf01), WTC(0x8241fa01), WTC(0x822f1b01), + WTC(0x821c3401), WTC(0x82094581), WTC(0x81f64f01), WTC(0x81e34f81), + WTC(0x81d04681), WTC(0x81bd3401), WTC(0x81aa1981), WTC(0x8196f781), + WTC(0x8183cf81), WTC(0x8170a181), WTC(0x815d6c01), WTC(0x814a2f81), + WTC(0x8136ea01), WTC(0x81239d81), WTC(0x81104a01), WTC(0x80fcf181), + WTC(0x80e99401), WTC(0x80d63101), WTC(0x80c2c781), WTC(0x80af5701), + WTC(0x809bdf01), WTC(0x80886081), WTC(0x8074dc01), WTC(0x80615281), + WTC(0x804dc481), WTC(0x803a3381), WTC(0x80269f81), WTC(0x80130981), + WTC(0x0a608220), WTC(0x0a8ee7d0), WTC(0x0abe35c0), WTC(0x0aee5de0), + WTC(0x0b1f5230), WTC(0x0b5104a0), WTC(0x0b836720), WTC(0x0bb66bb0), + WTC(0x0bea0440), WTC(0x0c1e22c0), WTC(0x0c52ba70), WTC(0x0c87ca90), + WTC(0x0cbd5ba0), WTC(0x0cf375e0), WTC(0x0d2a1f50), WTC(0x0d615480), + WTC(0x0d990e40), WTC(0x0dd14500), WTC(0x0e09f730), WTC(0x0e432e90), + WTC(0x0e7cf790), WTC(0x0eb75e50), WTC(0x0ef26430), WTC(0x0f2dfd70), + WTC(0x0f6a1d70), WTC(0x0fa6b7e0), WTC(0x0fe3c3d0), WTC(0x10213ac0), + WTC(0x105f1640), WTC(0x109d4f20), WTC(0x10dbdb80), WTC(0x111ab0c0), + WTC(0x1159c360), WTC(0x11990fc0), WTC(0x11d8a060), WTC(0x121882c0), + WTC(0x1258c480), WTC(0x12995a40), WTC(0x12da1b00), WTC(0x131adb60), + WTC(0x135b70c0), WTC(0x139bb680), WTC(0x13db8c00), WTC(0x141ad080), + WTC(0x14596460), WTC(0x149729e0), WTC(0x14d404e0), WTC(0x150fd8e0), + WTC(0x154a88c0), WTC(0x1583f5e0), WTC(0x15bc0120), WTC(0x15f28ba0), + WTC(0x162779a0), WTC(0x165ab300), WTC(0x168c2040), WTC(0x16bbaa80), + WTC(0x16e94120), WTC(0x1714d9e0), WTC(0x173e6440), WTC(0x17660680), + WTC(0x178ca020), WTC(0x17b36400), WTC(0x17db84e0), WTC(0x1805d920), + WTC(0x18328400), WTC(0x18617cc0), WTC(0x1892bfa0), WTC(0x18c64540), + WTC(0x18fc0400), WTC(0x1933f140), WTC(0x196e0320), WTC(0x19aa2fc0), + WTC(0x19e86d80), WTC(0x1a28b2e0), WTC(0x1a6af700), WTC(0x1aaf3320), + WTC(0x1af56180), WTC(0x1b3d7ce0), WTC(0x1b877c40), WTC(0x1bd350c0), + WTC(0x1c20ea40), WTC(0x1c703840), WTC(0x1cc13860), WTC(0x1d13f760), + WTC(0x1d688420), WTC(0x1dbeed40), WTC(0x1e174660), WTC(0x1e71a640), + WTC(0x1ece2400), WTC(0x1f2cd220), WTC(0x1f8db3c0), WTC(0x1ff0c3e0), + WTC(0x20560080), WTC(0x20bd46c0), WTC(0x21263400), WTC(0x21905740), + WTC(0x21fb4100), WTC(0x2266ba80), WTC(0x22d2d140), WTC(0x233f9780), + WTC(0x23ad25c0), WTC(0x241bc800), WTC(0x248bf040), WTC(0x24fe1380), + WTC(0x25728180), WTC(0x25e90a00), WTC(0x26614080), WTC(0x26dabdc0), + WTC(0x27552540), WTC(0x27d03200), WTC(0x284ba580), WTC(0x28c740c0), + WTC(0x29431f80), WTC(0x29bfc9c0), WTC(0x2a3dd080), WTC(0x2abdc000), + WTC(0x2b3ffd00), WTC(0x2bc4cd80), WTC(0x2c4c7d40), WTC(0x2cd72ec0), + WTC(0x2d647f80), WTC(0x2df3cd80), WTC(0x2e847d80), WTC(0x2f15ea40), + WTC(0x2fa760c0), WTC(0x30382b80), WTC(0x30c79440), WTC(0x315566c0), + WTC(0x31e20800), WTC(0x326de7c0), WTC(0x32f98200), WTC(0x3385ba00), + WTC(0x3413bec0), WTC(0x34a4c480), WTC(0x3539bf00), WTC(0x35d2c4c0), + WTC(0x366f8340), WTC(0x370fb800), WTC(0x37b2cf80), WTC(0x3857a480), + WTC(0x38fcee80), WTC(0x39a16840), WTC(0x3a4422c0), WTC(0x3ae495c0), + WTC(0x3b824000), WTC(0x3c1cb500), WTC(0x3cb438c0), WTC(0x3d4994c0), + WTC(0x3ddd8f40), WTC(0x3e70ec00), WTC(0x3f045e40), WTC(0x3f989080), + WTC(0x402e32ff), WTC(0x40c5c07f), WTC(0x415f547f), WTC(0x41faf07f), + WTC(0x4298997f), WTC(0x4338307f), WTC(0x43d96bff), WTC(0x447bffff), + WTC(0x451f9cff), WTC(0x45c3daff), WTC(0x46683eff), WTC(0x470c4cff), + WTC(0x47af93ff), WTC(0x4851c3ff), WTC(0x48f29d7f), WTC(0x4991de7f), + WTC(0x4a2f5e7f), WTC(0x4acb287f), WTC(0x4b65537f), WTC(0x4bfdf37f), + WTC(0x4c95337f), WTC(0x4d2b51ff), WTC(0x4dc091ff), WTC(0x4e5533ff), + WTC(0x4ee96b7f), WTC(0x4f7d61ff), WTC(0x501140ff), WTC(0x50a5317f), + WTC(0x51395a7f), WTC(0x51cddf7f), WTC(0x5262e6ff), WTC(0x52f885ff), + WTC(0x538eb47f), WTC(0x542560ff), WTC(0x54bc7b7f), WTC(0x5553a8ff), + WTC(0x55ea35ff), WTC(0x567f66ff), WTC(0x5712897f), WTC(0x57a33a7f), + WTC(0x583152ff), WTC(0x58bca5ff), WTC(0x594530ff), WTC(0x59cb79ff), + WTC(0x5a5047ff), WTC(0x5ad45eff), WTC(0x5b584e7f), WTC(0x5bdc417f), + WTC(0x5c60487f), WTC(0x5ce476ff), WTC(0x5d68c47f), WTC(0x5ded06ff), + WTC(0x5e7111ff), WTC(0x5ef4b5ff), WTC(0x5f77a17f), WTC(0x5ff96aff), + WTC(0x6079a7ff), WTC(0x60f7f7ff), WTC(0x617417ff), WTC(0x61edd87f), + WTC(0x6264ffff), WTC(0x62d9a6ff), WTC(0x634c817f), WTC(0x63be657f), + WTC(0x6430277f), WTC(0x64a2247f), WTC(0x65142bff), WTC(0x6586027f), + WTC(0x65f7697f), WTC(0x666801ff), WTC(0x66d756ff), WTC(0x6744f0ff), + WTC(0x67b0787f), WTC(0x681a077f), WTC(0x6881ebff), WTC(0x68e8707f), + WTC(0x694dceff), WTC(0x69b21e7f), WTC(0x6a156cff), WTC(0x6a77ca7f), + WTC(0x6ad9377f), WTC(0x6b39a4ff), WTC(0x6b9901ff), WTC(0x6bf73cff), + WTC(0x6c54457f), WTC(0x6cb00aff), WTC(0x6d0a7bff), WTC(0x6d6387ff), + WTC(0xae2cbe01), WTC(0xaf526d01), WTC(0xb0751201), WTC(0xb194da81), + WTC(0xb2b1f401), WTC(0xb3cc8d01), WTC(0xb4e4d201), WTC(0xb5faf101), + WTC(0xb70f1881), WTC(0xb8217301), WTC(0xb9321181), WTC(0xba40ee01), + WTC(0xbb4e0201), WTC(0xbc594781), WTC(0xbd62b881), WTC(0xbe6a5181), + WTC(0xbf700d01), WTC(0xc073e4c0), WTC(0xc175d240), WTC(0xc275cc80), + WTC(0xc373cb80), WTC(0xc46fca00), WTC(0xc569c600), WTC(0xc661bdc0), + WTC(0xc757af80), WTC(0xc84b9840), WTC(0xc93d7300), WTC(0xca2d3a40), + WTC(0xcb1aea40), WTC(0xcc068280), WTC(0xccf00480), WTC(0xcdd77200), + WTC(0xcebccb40), WTC(0xcfa00d80), WTC(0xd0813540), WTC(0xd1603f00), + WTC(0xd23d2980), WTC(0xd317f7c0), WTC(0xd3f0ac40), WTC(0xd4c74980), + WTC(0xd59bcf80), WTC(0xd66e3b00), WTC(0xd73e8900), WTC(0xd80cb740), + WTC(0xd8d8c7c0), WTC(0xd9a2be00), WTC(0xda6a9e40), WTC(0xdb306a40), + WTC(0xdbf42080), WTC(0xdcb5be80), WTC(0xdd754140), WTC(0xde32a900), + WTC(0xdeedf9c0), WTC(0xdfa737c0), WTC(0xe05e6740), WTC(0xe1138900), + WTC(0xe1c69ac0), WTC(0xe2779a40), WTC(0xe3268680), WTC(0xe3d36260), + WTC(0xe47e33a0), WTC(0xe526ff80), WTC(0xe5cdc960), WTC(0xe6729100), + WTC(0xe7155460), WTC(0xe7b611c0), WTC(0xe854ca20), WTC(0xe8f18180), + WTC(0xe98c3ca0), WTC(0xea24ffe0), WTC(0xeabbcb20), WTC(0xeb509b60), + WTC(0xebe36d00), WTC(0xec743e00), WTC(0xed0310e0), WTC(0xed8feaa0), + WTC(0xee1ad060), WTC(0xeea3c640), WTC(0xef2acd60), WTC(0xefafe6a0), + WTC(0xf03312f0), WTC(0xf0b45800), WTC(0xf133c230), WTC(0xf1b15ef0), + WTC(0xf22d3af0), WTC(0xf2a75c80), WTC(0xf31fc460), WTC(0xf39673b0), + WTC(0xf40b6a00), WTC(0xf47ea230), WTC(0xf4f01450), WTC(0xf55fb930), + WTC(0xf5cd84c0), WTC(0xf6396090), WTC(0xf6a333e0), WTC(0xf70ae540), + WTC(0xf7707260), WTC(0xf7d3f720), WTC(0xf83592f0), WTC(0xf8956450), + WTC(0xf8f38120), WTC(0xf94ff7c8), WTC(0xf9aad740), WTC(0xfa042920), + WTC(0xfa5be110), WTC(0xfab1e778), WTC(0xfb062478), WTC(0xfb588d78), + WTC(0xfba93530), WTC(0xfbf836c8), WTC(0xfc45ace0), WTC(0xfc91a294), + WTC(0xfcdc0e5c), WTC(0xfd24e438), WTC(0xfd6c17dc), WTC(0xfdb19758), + WTC(0xfdf54c3c), WTC(0xfe371ef8), WTC(0xfe7701aa), WTC(0xfeb50d62), + WTC(0xfef1700a), WTC(0xff2c5574), WTC(0xff65ee7b), WTC(0xff9e75de), + WTC(0xffd62863), WTC(0x000d4401), WTC(0x0043d345), WTC(0x00799cd0), + WTC(0x00ae5f49), WTC(0x00e1d7a4), WTC(0x0113a6f2), WTC(0x0143575c), + WTC(0x01707024), WTC(0x019a9346), WTC(0x01c1cf08), WTC(0x01e66c12), + WTC(0x0208ac48), WTC(0x0228e868), WTC(0x0247a6c8), WTC(0x02657aa0), + WTC(0x0282f710), WTC(0x02a07e50), WTC(0x02be31c0), WTC(0x02dc2b30), + WTC(0x02fa7f34), WTC(0x0318fb10), WTC(0x03372fdc), WTC(0x0354ae54), + WTC(0x03710d18), WTC(0x038bfdb4), WTC(0x03a54084), WTC(0x03bc92b8), + WTC(0x03d1c710), WTC(0x03e4dd20), WTC(0x03f5e25c), WTC(0x0404e218), + WTC(0x0411fc30), WTC(0x041d6b30), WTC(0x04276cd0), WTC(0x04303e00), + WTC(0x04381528), WTC(0x043f2310), WTC(0x04459908), WTC(0x044ba430), + WTC(0x045161f8), WTC(0x0456e6f8), WTC(0x045c49a8), WTC(0x046192f8), + WTC(0x0466af40), WTC(0x046b8240), WTC(0x046ff0d8), WTC(0x0473de18), + WTC(0x04772b58), WTC(0x0479b9a0), WTC(0x047b6a30), WTC(0x047c2088), + WTC(0x047bc230), WTC(0x047a3418), WTC(0x04776098), WTC(0x04734790), + WTC(0x046df4c0), WTC(0x04677220), WTC(0x045fd1b0), WTC(0x04573588), + WTC(0x044dc4b8), WTC(0x0443a5b8), WTC(0x04390160), WTC(0x042e0398), + WTC(0x0422d8c0), WTC(0x0417aa30), WTC(0x040c7ce0), WTC(0x040136e0), + WTC(0x03f5beb0), WTC(0x03e9f8ec), WTC(0x03ddc484), WTC(0x03d0fd9c), + WTC(0x03c37fa0), WTC(0x03b53014), WTC(0x03a60a18), WTC(0x03960f88), + WTC(0x03854110), WTC(0x0373ad9c), WTC(0x03617694), WTC(0x034ebf9c), + WTC(0x033bab30), WTC(0x03284ef0), WTC(0x0314b598), WTC(0x0300ea54), + WTC(0x02ecf524), WTC(0x02d8d210), WTC(0x02c476ac), WTC(0x02afd940), + WTC(0x029aee4c), WTC(0x0285a6f4), WTC(0x026ff398), WTC(0x0259c448), + WTC(0x024317cc), WTC(0x022c0084), WTC(0x02149310), WTC(0x01fce334), + WTC(0x01e4fb24), WTC(0x01ccdd0a), WTC(0x01b48b20), WTC(0x019c077e), + WTC(0x01835432), WTC(0x016a733c), WTC(0x015166a6), WTC(0x0138302e), + WTC(0x011ed0f6), WTC(0x010549f8), WTC(0x00eb9c25), WTC(0x00d1caa6), + WTC(0x00b7db94), WTC(0x009dd560), WTC(0x0083be75), WTC(0x00699d41), + WTC(0x004f782f), WTC(0x003555ab), WTC(0x001b3c21), WTC(0x000131fe), + WTC(0xd61cfc40), WTC(0xd5acb340), WTC(0xd53d4400), WTC(0xd4cea6c0), + WTC(0xd460d440), WTC(0xd3f3c440), WTC(0xd3876f80), WTC(0xd31bce40), + WTC(0xd2b0d900), WTC(0xd2468980), WTC(0xd1dcef00), WTC(0xd17429c0), + WTC(0xd10c5b80), WTC(0xd0a59b80), WTC(0xd03fd780), WTC(0xcfdae780), + WTC(0xcf76a380), WTC(0xcf12fac0), WTC(0xceb01100), WTC(0xce4e18c0), + WTC(0xcded4440), WTC(0xcd8d9a40), WTC(0xcd2ee800), WTC(0xccd0f440), + WTC(0xcc738780), WTC(0xcc167d40), WTC(0xcbb9c180), WTC(0xcb5d4040), + WTC(0xcb00e240), WTC(0xcaa48000), WTC(0xca47eac0), WTC(0xc9eaf1c0), + WTC(0xc98d8100), WTC(0xc92fc580), WTC(0xc8d1fc80), WTC(0xc8746480), + WTC(0xc816dc40), WTC(0xc7b8c280), WTC(0xc7596800), WTC(0xc6f81f80), + WTC(0xc6945740), WTC(0xc62d93c0), WTC(0xc5c358c0), WTC(0xc5552b80), + WTC(0xc4e29240), WTC(0xc46b1440), WTC(0xc3ee3840), WTC(0xc36b8500), + WTC(0xc2e28040), WTC(0xc252ae80), WTC(0xc1bb9540), WTC(0xc11cc200), + WTC(0xc075cf00), WTC(0xbfc65781), WTC(0xbf0df881), WTC(0xbe4c6f01), + WTC(0xbd819401), WTC(0xbcad2d01), WTC(0xbbcfb981), WTC(0xbaeca681), + WTC(0xba08e781), WTC(0xb9297081), WTC(0xb851e081), WTC(0xb782ed01), + WTC(0xb6bc6a81), WTC(0xb5fe4981), WTC(0xb5487281), WTC(0xb49ad081), + WTC(0xb3f54d81), WTC(0xb357d401), WTC(0xb2c24e01), WTC(0xb234a681), + WTC(0xb1aec701), WTC(0xb1309b01), WTC(0xb0ba0c01), WTC(0xb04b0481), + WTC(0xafe36f01), WTC(0xaf833601), WTC(0xaf2a4381), WTC(0xaed88201), + WTC(0xae8ddb81), WTC(0xae4a3b81), WTC(0xae0d8b01), WTC(0xadd7b581), + WTC(0xada8a481), WTC(0xad804281), WTC(0xad5e7a81), WTC(0xad433601), + WTC(0xad2e6001), WTC(0xad1fe281), WTC(0xad17a801), WTC(0xad159a81), + WTC(0xad19a501), WTC(0xad23b101), WTC(0xad33aa01), WTC(0xad497981), + WTC(0xad650a01), WTC(0xad864601), WTC(0xadad1781), WTC(0xadd96981), + WTC(0xae0b2601), WTC(0xae423781), WTC(0xae7e8801), WTC(0xaec00201), + WTC(0xaf069081), WTC(0xaf521c81), WTC(0xafa29201), WTC(0xaff7da01), + WTC(0xb051df01), WTC(0xb0b08c81), WTC(0xb113cb81), WTC(0xb17b8701), + WTC(0xb1e7a981), WTC(0xb2581d81), WTC(0xb2cccc81), WTC(0xb345a181), + WTC(0xb3c28701), WTC(0xb4436681), WTC(0xb4c82b81), WTC(0xb550bf81), + WTC(0xb5dd0d01), WTC(0xb66cff01), WTC(0xb7007f01), WTC(0xb7977781), + WTC(0xb831d381), WTC(0xb8cf7d01), WTC(0xb9705e01), WTC(0xba146101), + WTC(0xbabb7081), WTC(0xbb657781), WTC(0xbc125f01), WTC(0xbcc21281), + WTC(0xbd747b81), WTC(0xbe298581), WTC(0xbee11981), WTC(0xbf9b2301), + WTC(0xc0578b80), WTC(0xc1163dc0), WTC(0xc1d72400), WTC(0xc29a28c0), + WTC(0xc35f3640), WTC(0xc42636c0), WTC(0xc4ef1500), WTC(0xc5b9bb00), + WTC(0xc6861340), WTC(0xc7540840), WTC(0xc8238400), WTC(0xc8f47100), + WTC(0xc9c6b9c0), WTC(0xca9a4840), WTC(0xcb6f0780), WTC(0xcc44e140), + WTC(0xcd1bc000), WTC(0xcdf38e00), WTC(0xcecc3600), WTC(0xcfa5a240), + WTC(0xd07fbcc0), WTC(0xd15a7040), WTC(0xd235a6c0), WTC(0xd3114b00), + WTC(0xd3ed4740), WTC(0xd4c98580), WTC(0xd5a5f080), WTC(0xd6827280), + WTC(0xd75ef600), WTC(0xd83b6500), WTC(0xd917aa00), WTC(0xd9f3af80), + WTC(0xdacf5fc0), WTC(0xdbaaa540), WTC(0xdc856a00), WTC(0xdd5f98c0), + WTC(0xde391bc0), WTC(0xdf11dd40), WTC(0xdfe9c780), WTC(0xe0c0c540), + WTC(0xe196c080), WTC(0xe26ba3c0), WTC(0xe33f5960), WTC(0xe411cba0), + WTC(0xe4e2e500), WTC(0xe5b28fc0), WTC(0xe680b640), WTC(0xe74d42e0), + WTC(0xe8181fe0), WTC(0xe8e137e0), WTC(0xe9a87500), WTC(0xea6dc1a0), + WTC(0xeb310820), WTC(0xebf23300), WTC(0xecb12c60), WTC(0xed6ddee0), + WTC(0xee2834a0), WTC(0xeee01800), WTC(0xef957380), WTC(0xf0483160), + WTC(0xf0f83c00), WTC(0xf1a57db0), WTC(0xf24fe0f0), WTC(0xf2f74ff0), + WTC(0xf39bb530), WTC(0xf43cfaf0), WTC(0xf4db0b90), WTC(0xf575d180), + WTC(0xf60d3700), WTC(0xf6a12680), WTC(0xf7318a50), WTC(0xf7be4cc0), + WTC(0xf8475850), WTC(0xf8cc9738), WTC(0xf94df3e0), WTC(0xf9cb58a8), + WTC(0xfa44afe0), WTC(0xfab9e3e8), WTC(0xfb2adf20), WTC(0xfb978be8), + WTC(0xfbffd488), WTC(0xfc63a370), WTC(0xfcc2e2f0), WTC(0xfd1d7d64), + WTC(0xfd735d2c), WTC(0xfdc46c9c), WTC(0xfe109618), WTC(0xfe57c3f4), + WTC(0xfe99e090), WTC(0xfed6d644), WTC(0xff0e8f6e), WTC(0xff40f667), + WTC(0xff6df58c), WTC(0xff957738), WTC(0xffb765c5), WTC(0xffd3ab90), + WTC(0xffea32f4), WTC(0xfffae64c), WTC(0x0005aff3), WTC(0x000a7a44), + WTC(0x00092f9c), WTC(0x0001ba54), WTC(0xfff404ca), WTC(0xffdff957)}; + +/* + * TNS_MAX_BANDS + * entry for each sampling rate + * 1 long window + * 2 SHORT window + */ +const UCHAR tns_max_bands_tbl[13][2] = { + {31, 9}, /* 96000 */ + {31, 9}, /* 88200 */ + {34, 10}, /* 64000 */ + {40, 14}, /* 48000 */ + {42, 14}, /* 44100 */ + {51, 14}, /* 32000 */ + {46, 14}, /* 24000 */ + {46, 14}, /* 22050 */ + {42, 14}, /* 16000 */ + {42, 14}, /* 12000 */ + {42, 14}, /* 11025 */ + {39, 14}, /* 8000 */ + {39, 14}, /* 7350 */ +}; + +/* TNS_MAX_BANDS for low delay. The array index is the sampleRateIndex */ +const UCHAR tns_max_bands_tbl_480[13] = { + 31, /* 96000 */ + 31, /* 88200 */ + 31, /* 64000 */ + 31, /* 48000 */ + 32, /* 44100 */ + 37, /* 32000 */ + 30, /* 24000 */ + 30, /* 22050 */ + 30, /* 16000 */ + 30, /* 12000 */ + 30, /* 11025 */ + 30, /* 8000 */ + 30 /* 7350 */ +}; +const UCHAR tns_max_bands_tbl_512[13] = { + 31, /* 96000 */ + 31, /* 88200 */ + 31, /* 64000 */ + 31, /* 48000 */ + 32, /* 44100 */ + 37, /* 32000 */ + 31, /* 24000 */ + 31, /* 22050 */ + 31, /* 16000 */ + 31, /* 12000 */ + 31, /* 11025 */ + 31, /* 8000 */ + 31 /* 7350 */ +}; + +#define TCC(x) (FIXP_DBL(x)) + +const FIXP_TCC FDKaacDec_tnsCoeff3[8] = { + TCC(0x81f1d1d4), TCC(0x9126146c), TCC(0xadb922c4), TCC(0xd438af1f), + TCC(0x00000000), TCC(0x3789809b), TCC(0x64130dd4), TCC(0x7cca7016)}; +const FIXP_TCC FDKaacDec_tnsCoeff4[16] = { + TCC(0x808bc842), TCC(0x84e2e58c), TCC(0x8d6b49d1), TCC(0x99da920a), + TCC(0xa9c45713), TCC(0xbc9ddeb9), TCC(0xd1c2d51b), TCC(0xe87ae53d), + TCC(0x00000000), TCC(0x1a9cd9b6), TCC(0x340ff254), TCC(0x4b3c8c29), + TCC(0x5f1f5ebb), TCC(0x6ed9ebba), TCC(0x79bc385f), TCC(0x7f4c7e5b)}; + +const UCHAR FDKaacDec_tnsCoeff3_gain_ld[] = { + 3, 1, 1, 1, 0, 1, 1, 3, +}; +const UCHAR FDKaacDec_tnsCoeff4_gain_ld[] = { + 4, 2, 2, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 4, +}; + +/* Lookup tables for elements in ER bitstream */ +const MP4_ELEMENT_ID + elementsTab[AACDEC_MAX_CH_CONF][AACDEC_CH_ELEMENTS_TAB_SIZE] = { + /* 1 */ {ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE, + ID_NONE}, /* 1 channel */ + /* 2 */ + {ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE, + ID_NONE} /* 2 channels */ +#if (AACDEC_MAX_CH_CONF > 2) + /* 3 */, + {ID_SCE, ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE, + ID_NONE}, /* 3 channels */ + /* 4 */ + {ID_SCE, ID_CPE, ID_SCE, ID_EXT, ID_END, ID_NONE, + ID_NONE}, /* 4 channels */ + /* 5 */ + {ID_SCE, ID_CPE, ID_CPE, ID_EXT, ID_END, ID_NONE, + ID_NONE}, /* 5 channels */ + /* 6 */ + {ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END, + ID_NONE} /* 6 channels */ +#endif +#if (AACDEC_MAX_CH_CONF > 6) + /* 7 */, + {ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, + ID_END}, /* 8 channels */ + /* 8 */ + {ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, + ID_NONE}, /* reserved */ + /* 9 */ + {ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, + ID_NONE}, /* reserved */ + /* 10 */ + {ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, + ID_NONE}, /* reserved */ + /* 11 */ + {ID_SCE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_EXT, + ID_END}, /* 7 channels */ + /* 12 */ + {ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, + ID_END}, /* 8 channels */ + /* 13 */ + {ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, + ID_NONE}, /* see elementsChCfg13 */ + /* 14 */ + {ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_CPE, ID_EXT, + ID_END} /* 8 channels */ +#endif +}; + +/*! Random sign bit used for concealment + */ +const USHORT AacDec_randomSign[AAC_NF_NO_RANDOM_VAL / 16] = { + /* + sign bits of FDK_sbrDecoder_sbr_randomPhase[] entries: + LSB ........... MSB -> MSB ... LSB + */ + /* 1001 0111 0011 1100 -> */ 0x3ce9, + /* 0100 0111 0111 1011 -> */ 0xdee2, + /* 0001 1100 1110 1011 -> */ 0xd738, + /* 0001 0011 0110 1001 -> */ 0x96c8, + /* 0101 0011 1101 0000 -> */ 0x0bca, + /* 0001 0001 1111 0100 -> */ 0x2f88, + /* 1110 1100 1110 1101 -> */ 0xb737, + /* 0010 1010 1011 1001 -> */ 0x9d54, + /* 0111 1100 0110 1010 -> */ 0x563e, + /* 1101 0111 0010 0101 -> */ 0xa4eb, + /* 0001 0101 1011 1100 -> */ 0x3da8, + /* 0101 0111 1001 1011 -> */ 0xd9ea, + /* 1101 0100 0101 0101 -> */ 0xaa2b, + /* 1000 1001 0100 0011 -> */ 0xc291, + /* 1100 1111 1010 1100 -> */ 0x35f3, + /* 1100 1010 1110 0010 -> */ 0x4753, + /* 0110 0001 1010 1000 -> */ 0x1586, + /* 0011 0101 1111 1100 -> */ 0x3fac, + /* 0001 0110 1010 0001 -> */ 0x8568, + /* 0010 1101 0111 0010 -> */ 0x4eb4, + /* 1101 1010 0100 1001 -> */ 0x925b, + /* 1100 1001 0000 1110 -> */ 0x7093, + /* 1000 1100 0110 1010 -> */ 0x5631, + /* 0000 1000 0110 1101 -> */ 0xb610, + /* 1000 0001 1111 1011 -> */ 0xdf81, + /* 1111 0011 0100 0111 -> */ 0xe2cf, + /* 1000 0001 0010 1010 -> */ 0x5481, + /* 1101 0101 1100 1111 -> */ 0xf3ab, + /* 0110 0001 0110 1000 -> */ 0x1686, + /* 0011 0011 1100 0110 -> */ 0x63cc, + /* 0011 0111 0101 0110 -> */ 0x6aec, + /* 1011 0001 1010 0010 -> */ 0x458d}; + +/* MDST filter coefficients for current window + * max: 0.635722 => 20 bits (unsigned) necessary for representation + * min: = -max */ +const FIXP_FILT mdst_filt_coef_curr[20][3] = { + {FILT(0.000000f), FILT(0.000000f), FILT(0.500000f)}, + /*, FILT( 0.000000f), FILT(-0.500000f), FILT( 0.000000f), FILT( 0.000000f) }, */ /* only long / eight short l:sine r:sine */ + {FILT(0.091497f), FILT(0.000000f), FILT(0.581427f)}, + /*, FILT( 0.000000f), FILT(-0.581427f), FILT( 0.000000f), FILT(-0.091497f) }, */ /* l:kbd r:kbd */ + {FILT(0.045748f), FILT(0.057238f), FILT(0.540714f)}, + /*, FILT( 0.000000f), FILT(-0.540714f), FILT(-0.057238f), FILT(-0.045748f) }, */ /* l:sine r:kbd */ + {FILT(0.045748f), FILT(-0.057238f), FILT(0.540714f)}, + /*, FILT( 0.000000f), FILT(-0.540714f), FILT( 0.057238f), FILT(-0.045748f) }, */ /* l:kbd r:sine */ + + {FILT(0.102658f), FILT(0.103791f), FILT(0.567149f)}, + /*, FILT( 0.000000f), FILT(-0.567149f), FILT(-0.103791f), FILT(-0.102658f) }, */ /* long start */ + {FILT(0.150512f), FILT(0.047969f), + FILT(0.608574f)}, /*, FILT( 0.000000f), FILT(-0.608574f), + FILT(-0.047969f), FILT(-0.150512f) }, */ + {FILT(0.104763f), FILT(0.105207f), + FILT(0.567861f)}, /*, FILT( 0.000000f), FILT(-0.567861f), + FILT(-0.105207f), FILT(-0.104763f) }, */ + {FILT(0.148406f), FILT(0.046553f), + FILT(0.607863f)}, /*, FILT( 0.000000f), FILT(-0.607863f), + FILT(-0.046553f), FILT(-0.148406f) }, */ + + {FILT(0.102658f), FILT(-0.103791f), FILT(0.567149f)}, + /*, FILT( 0.000000f), FILT(-0.567149f), FILT( 0.103791f), FILT(-0.102658f) }, */ /* long stop */ + {FILT(0.150512f), FILT(-0.047969f), + FILT(0.608574f)}, /*, FILT( 0.000000f), FILT(-0.608574f), FILT( + 0.047969f), FILT(-0.150512f) }, */ + {FILT(0.148406f), FILT(-0.046553f), + FILT(0.607863f)}, /*, FILT( 0.000000f), FILT(-0.607863f), FILT( + 0.046553f), FILT(-0.148406f) }, */ + {FILT(0.104763f), FILT(-0.105207f), + FILT(0.567861f)}, /*, FILT( 0.000000f), FILT(-0.567861f), FILT( + 0.105207f), FILT(-0.104763f) }, */ + + {FILT(0.205316f), FILT(0.000000f), FILT(0.634298f)}, + /*, FILT( 0.000000f), FILT(-0.634298f), FILT( 0.000000f), FILT(-0.205316f) }, */ /* stop start */ + {FILT(0.209526f), FILT(0.000000f), + FILT(0.635722f)}, /*, FILT( 0.000000f), FILT(-0.635722f), FILT( + 0.000000f), FILT(-0.209526f) }, */ + {FILT(0.207421f), FILT(0.001416f), + FILT(0.635010f)}, /*, FILT( 0.000000f), FILT(-0.635010f), + FILT(-0.001416f), FILT(-0.207421f) }, */ + {FILT(0.207421f), FILT(-0.001416f), + FILT(0.635010f)}, /*, FILT( 0.000000f), FILT(-0.635010f), FILT( + 0.001416f), FILT(-0.207421f) } */ + + {FILT(0.185618f), FILT(0.000000f), FILT(0.627371f)}, + /*, FILT( 0.000000f), FILT(-0.634298f), FILT( 0.000000f), FILT(-0.205316f) }, */ /* stop start Transform Splitting */ + {FILT(0.204932f), FILT(0.000000f), + FILT(0.634159f)}, /*, FILT( 0.000000f), FILT(-0.635722f), FILT( + 0.000000f), FILT(-0.209526f) }, */ + {FILT(0.194609f), FILT(0.006202f), + FILT(0.630536f)}, /*, FILT( 0.000000f), FILT(-0.635010f), + FILT(-0.001416f), FILT(-0.207421f) }, */ + {FILT(0.194609f), FILT(-0.006202f), + FILT(0.630536f)}, /*, FILT( 0.000000f), FILT(-0.635010f), FILT( + 0.001416f), FILT(-0.207421f) } */ +}; + +/* MDST filter coefficients for previous window + * max: 0.31831 => 15 bits (unsigned) necessary for representation + * min: 0.0 */ +const FIXP_FILT mdst_filt_coef_prev[6][4] = { + {FILT(0.000000f), FILT(0.106103f), FILT(0.250000f), FILT(0.318310f)}, + /*, FILT( 0.250000f), FILT( 0.106103f), FILT( 0.000000f) }, */ /* only long + / long + start / + eight + short + l:sine */ + {FILT(0.059509f), FILT(0.123714f), FILT(0.186579f), FILT(0.213077f)}, + /*, FILT( 0.186579f), FILT( 0.123714f), FILT( 0.059509f) }, */ /* l:kbd + */ + + {FILT(0.038498f), FILT(0.039212f), FILT(0.039645f), FILT(0.039790f)}, + /*, FILT( 0.039645f), FILT( 0.039212f), FILT( 0.038498f) }, */ /* long stop + / stop + start + l:sine */ + {FILT(0.026142f), FILT(0.026413f), FILT(0.026577f), FILT(0.026631f)}, + /*, FILT( 0.026577f), FILT( 0.026413f), FILT( 0.026142f) } */ /* l:kbd + */ + + {FILT(0.069608f), FILT(0.075028f), FILT(0.078423f), FILT(0.079580f)}, + /*, FILT( 0.039645f), FILT( 0.039212f), FILT( 0.038498f) }, */ /* Transform + splitting + l:sine */ + {FILT(0.042172f), FILT(0.043458f), FILT(0.044248f), FILT(0.044514f)}, + /*, FILT( 0.026577f), FILT( 0.026413f), FILT( 0.026142f) } */ /* l:kbd + */ +}; diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_rom.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_rom.h new file mode 100644 index 0000000000000..7a1597c27daf2 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aac_rom.h @@ -0,0 +1,238 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: Definition of constant tables + +*******************************************************************************/ + +#ifndef AAC_ROM_H +#define AAC_ROM_H + +#include "common_fix.h" +#include "FDK_audio.h" +#include "aacdec_hcr_types.h" +#include "aacdec_hcrs.h" + +#define PCM_AAC LONG +#define PCM_DEC FIXP_DBL +#define MAXVAL_PCM_DEC MAXVAL_DBL +#define MINVAL_PCM_DEC MINVAL_DBL +#define FIXP_DBL2PCM_DEC(x) (x) +#define PCM_DEC2FIXP_DBL(x) (x) +#define PCM_DEC_BITS DFRACT_BITS +#define PCM_DEC2FX_PCM(x) FX_DBL2FX_PCM(x) +#define FX_PCM2PCM_DEC(x) FX_PCM2FX_DBL(x) + +#define AACDEC_MAX_CH_CONF 14 +#define AACDEC_CH_ELEMENTS_TAB_SIZE 7 /*!< Size of element tables */ + +#define AAC_NF_NO_RANDOM_VAL \ + 512 /*!< Size of random number array for noise floor */ + +#define INV_QUANT_TABLESIZE 256 + +extern const FIXP_DBL InverseQuantTable[INV_QUANT_TABLESIZE + 1]; +extern const FIXP_DBL MantissaTable[4][14]; +extern const SCHAR ExponentTable[4][14]; + +#define NUM_LD_COEF_512 1536 +#define NUM_LD_COEF_480 1440 +/* Window table partition exponents. */ +#define WTS0 (1) +#define WTS1 (0) +#define WTS2 (-2) +extern const FIXP_WTB LowDelaySynthesis512[1536]; +extern const FIXP_WTB LowDelaySynthesis480[1440]; +extern const FIXP_WTB LowDelaySynthesis256[768]; +extern const FIXP_WTB LowDelaySynthesis240[720]; +extern const FIXP_WTB LowDelaySynthesis160[480]; +extern const FIXP_WTB LowDelaySynthesis128[384]; +extern const FIXP_WTB LowDelaySynthesis120[360]; + +typedef struct { + const SHORT *sfbOffsetLong; + const SHORT *sfbOffsetShort; + UCHAR numberOfSfbLong; + UCHAR numberOfSfbShort; +} SFB_INFO; + +extern const SFB_INFO sfbOffsetTables[5][16]; + +/* Huffman tables */ +enum { HuffmanBits = 2, HuffmanEntries = (1 << HuffmanBits) }; + +typedef struct { + const USHORT (*CodeBook)[HuffmanEntries]; + UCHAR Dimension; + UCHAR numBits; + UCHAR Offset; +} CodeBookDescription; + +extern const CodeBookDescription AACcodeBookDescriptionTable[13]; +extern const CodeBookDescription AACcodeBookDescriptionSCL; + +extern const STATEFUNC aStateConstant2State[]; + +extern const SCHAR aCodebook2StartInt[]; + +extern const UCHAR aMinOfCbPair[]; +extern const UCHAR aMaxOfCbPair[]; + +extern const UCHAR aMaxCwLen[]; +extern const UCHAR aDimCb[]; +extern const UCHAR aDimCbShift[]; +extern const UCHAR aSignCb[]; +extern const UCHAR aCbPriority[]; + +extern const UINT *aHuffTable[]; +extern const SCHAR *aQuantTable[]; + +extern const USHORT aLargestAbsoluteValue[]; + +extern const UINT aHuffTreeRvlcEscape[]; +extern const UINT aHuffTreeRvlCodewds[]; + +extern const UCHAR tns_max_bands_tbl[13][2]; + +extern const UCHAR tns_max_bands_tbl_480[13]; +extern const UCHAR tns_max_bands_tbl_512[13]; + +#define FIXP_TCC FIXP_DBL + +extern const FIXP_TCC FDKaacDec_tnsCoeff3[8]; +extern const FIXP_TCC FDKaacDec_tnsCoeff4[16]; + +extern const UCHAR FDKaacDec_tnsCoeff3_gain_ld[]; +extern const UCHAR FDKaacDec_tnsCoeff4_gain_ld[]; + +extern const USHORT AacDec_randomSign[AAC_NF_NO_RANDOM_VAL / 16]; + +extern const FIXP_DBL pow2_div24minus1[47]; +extern const int offsetTab[2][16]; + +/* Channel mapping indices for time domain I/O. + The first dimension is the channel configuration index. */ +extern const UCHAR channelMappingTablePassthrough[15][8]; +extern const UCHAR channelMappingTableWAV[15][8]; + +/* Lookup tables for elements in ER bitstream */ +extern const MP4_ELEMENT_ID elementsTab[AACDEC_MAX_CH_CONF] + [AACDEC_CH_ELEMENTS_TAB_SIZE]; + +#define SF_FNA_COEFFS \ + 1 /* Compile-time prescaler for MDST-filter coefficients. */ +/* SF_FNA_COEFFS > 0 should only be considered for FIXP_DBL-coefficients */ +/* (i.e. if CPLX_PRED_FILTER_16BIT is not defined). */ +/* With FIXP_DBL loss of precision is possible for SF_FNA_COEFFS > 11. */ + +#ifdef CPLX_PRED_FILTER_16BIT +#define FIXP_FILT FIXP_SGL +#define FILT(a) ((FL2FXCONST_SGL(a)) >> SF_FNA_COEFFS) +#else +#define FIXP_FILT FIXP_DBL +#define FILT(a) ((FL2FXCONST_DBL(a)) >> SF_FNA_COEFFS) +#endif + +extern const FIXP_FILT mdst_filt_coef_curr[20][3]; /* MDST-filter coefficient + tables used for current + window */ +extern const FIXP_FILT mdst_filt_coef_prev[6][4]; /* MDST-filter coefficient + tables used for previous + window */ + +#endif /* #ifndef AAC_ROM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_drc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_drc.cpp new file mode 100644 index 0000000000000..abb9af72ae1b5 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_drc.cpp @@ -0,0 +1,1509 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Christian Griebel + + Description: Dynamic range control (DRC) decoder tool for AAC + +*******************************************************************************/ + +#include "aacdec_drc.h" + +#include "channelinfo.h" +#include "aac_rom.h" + +#include "sbrdecoder.h" + +/* + * Dynamic Range Control + */ + +/* For parameter conversion */ +#define DRC_PARAMETER_BITS (7) +#define DRC_MAX_QUANT_STEPS (1 << DRC_PARAMETER_BITS) +#define DRC_MAX_QUANT_FACTOR (DRC_MAX_QUANT_STEPS - 1) +#define DRC_PARAM_QUANT_STEP \ + (FL2FXCONST_DBL(1.0f / (float)DRC_MAX_QUANT_FACTOR)) +#define DRC_PARAM_SCALE (1) +#define DRC_SCALING_MAX \ + ((FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP >> DRC_PARAM_SCALE) * (INT)127)) + +#define DRC_BLOCK_LEN (1024) +#define DRC_BAND_MULT (4) +#define DRC_BLOCK_LEN_DIV_BAND_MULT (DRC_BLOCK_LEN / DRC_BAND_MULT) + +#define MAX_REFERENCE_LEVEL (127) + +#define DRC_HEAVY_THRESHOLD_DB (10) + +#define DVB_ANC_DATA_SYNC_BYTE (0xBC) /* DVB ancillary data sync byte. */ + +#define OFF 0 +#define ON 1 + +static INT convert_drcParam(FIXP_DBL param_dbl) { + /* converts an internal DRC boost/cut scaling factor in FIXP_DBL + (which is downscaled by DRC_PARAM_SCALE) + back to an integer value between 0 and 127. */ + LONG param_long; + + param_long = (LONG)param_dbl >> 7; + param_long = param_long * (INT)DRC_MAX_QUANT_FACTOR; + param_long >>= 31 - 7 - DRC_PARAM_SCALE - 1; + param_long += 1; /* for rounding */ + param_long >>= 1; + + return (INT)param_long; +} + +/*! +\brief Disable DRC + +\self Handle of DRC info + +\return none +*/ +void aacDecoder_drcDisable(HANDLE_AAC_DRC self) { + self->enable = 0; + self->applyExtGain = 0; + self->progRefLevelPresent = 0; +} + +/*! +\brief Reset DRC information + +\self Handle of DRC info + +\return none +*/ +void aacDecoder_drcReset(HANDLE_AAC_DRC self) { + self->applyExtGain = 0; + self->additionalGainPrev = AACDEC_DRC_GAIN_INIT_VALUE; + self->additionalGainFilterState = AACDEC_DRC_GAIN_INIT_VALUE; + self->additionalGainFilterState1 = AACDEC_DRC_GAIN_INIT_VALUE; +} + +/*! + \brief Initialize DRC information + + \self Handle of DRC info + + \return none +*/ +void aacDecoder_drcInit(HANDLE_AAC_DRC self) { + CDrcParams *pParams; + + if (self == NULL) { + return; + } + + /* init control fields */ + self->enable = OFF; + self->numThreads = 0; + + /* init params */ + pParams = &self->params; + pParams->bsDelayEnable = 0; + pParams->cut = FL2FXCONST_DBL(0.0f); + pParams->usrCut = FL2FXCONST_DBL(0.0f); + pParams->boost = FL2FXCONST_DBL(0.0f); + pParams->usrBoost = FL2FXCONST_DBL(0.0f); + pParams->targetRefLevel = 96; + pParams->expiryFrame = AACDEC_DRC_DFLT_EXPIRY_FRAMES; + pParams->applyHeavyCompression = OFF; + pParams->usrApplyHeavyCompression = OFF; + + pParams->defaultPresentationMode = DISABLED_PARAMETER_HANDLING; + pParams->encoderTargetLevel = MAX_REFERENCE_LEVEL; /* worst case assumption */ + + self->update = 1; + self->numOutChannels = 0; + self->prevAacNumChannels = 0; + + /* initial program ref level = target ref level */ + self->progRefLevel = pParams->targetRefLevel; + self->progRefLevelPresent = 0; + self->presMode = -1; + + aacDecoder_drcReset(self); +} + +/*! + \brief Initialize DRC control data for one channel + + \self Handle of DRC info + + \return none +*/ +void aacDecoder_drcInitChannelData(CDrcChannelData *pDrcChData) { + if (pDrcChData != NULL) { + pDrcChData->expiryCount = 0; + pDrcChData->numBands = 1; + pDrcChData->bandTop[0] = DRC_BLOCK_LEN_DIV_BAND_MULT - 1; + pDrcChData->drcValue[0] = 0; + pDrcChData->drcInterpolationScheme = 0; + pDrcChData->drcDataType = UNKNOWN_PAYLOAD; + } +} + +/*! + \brief Set one single DRC parameter + + \self Handle of DRC info. + \param Parameter to be set. + \value Value to be set. + + \return an error code. +*/ +AAC_DECODER_ERROR aacDecoder_drcSetParam(HANDLE_AAC_DRC self, + AACDEC_DRC_PARAM param, INT value) { + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + switch (param) { + case DRC_CUT_SCALE: + /* set attenuation scale factor */ + if ((value < 0) || (value > DRC_MAX_QUANT_FACTOR)) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.usrCut = (FIXP_DBL)( + (INT)(DRC_PARAM_QUANT_STEP >> DRC_PARAM_SCALE) * (INT)value); + self->update = 1; + break; + case DRC_BOOST_SCALE: + /* set boost factor */ + if ((value < 0) || (value > DRC_MAX_QUANT_FACTOR)) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.usrBoost = (FIXP_DBL)( + (INT)(DRC_PARAM_QUANT_STEP >> DRC_PARAM_SCALE) * (INT)value); + self->update = 1; + break; + case TARGET_REF_LEVEL: + if (value > MAX_REFERENCE_LEVEL || value < -MAX_REFERENCE_LEVEL) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + if (value < 0) { + self->params.targetRefLevel = -1; + } else { + if (self->params.targetRefLevel != (SCHAR)value) { + self->params.targetRefLevel = (SCHAR)value; + self->progRefLevel = (SCHAR)value; /* Always set the program reference + level equal to the target level + according to 4.5.2.7.3 of + ISO/IEC 14496-3. */ + } + self->update = 1; + } + break; + case APPLY_HEAVY_COMPRESSION: + if ((value != OFF) && (value != ON)) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + /* Store new parameter value */ + self->params.usrApplyHeavyCompression = (UCHAR)value; + self->update = 1; + break; + case DEFAULT_PRESENTATION_MODE: + if (value < AAC_DRC_PARAMETER_HANDLING_DISABLED || + value > AAC_DRC_PRESENTATION_MODE_2_DEFAULT) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.defaultPresentationMode = + (AACDEC_DRC_PARAMETER_HANDLING)value; + self->update = 1; + break; + case ENCODER_TARGET_LEVEL: + if (value > MAX_REFERENCE_LEVEL || value < 0) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.encoderTargetLevel = (UCHAR)value; + self->update = 1; + break; + case DRC_BS_DELAY: + if (value < 0 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.bsDelayEnable = value; + break; + case DRC_DATA_EXPIRY_FRAME: + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.expiryFrame = (value > 0) ? (UINT)value : 0; + break; + case MAX_OUTPUT_CHANNELS: + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->numOutChannels = (INT)value; + self->update = 1; + break; + default: + return AAC_DEC_SET_PARAM_FAIL; + } /* switch(param) */ + + return ErrorStatus; +} + +static int parseExcludedChannels(UINT *excludedChnsMask, + HANDLE_FDK_BITSTREAM bs) { + UINT excludeMask = 0; + UINT i, j; + int bitCnt = 9; + + for (i = 0, j = 1; i < 7; i++, j <<= 1) { + if (FDKreadBits(bs, 1)) { + excludeMask |= j; + } + } + + /* additional_excluded_chns */ + while (FDKreadBits(bs, 1)) { + for (i = 0; i < 7; i++, j <<= 1) { + if (FDKreadBits(bs, 1)) { + excludeMask |= j; + } + } + bitCnt += 9; + FDK_ASSERT(j < (UINT)-1); + } + + *excludedChnsMask = excludeMask; + + return (bitCnt); +} + +/*! + \brief Save DRC payload bitstream position + + \self Handle of DRC info + \bs Handle of FDK bitstream + + \return The number of DRC payload bits +*/ +int aacDecoder_drcMarkPayload(HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM bs, + AACDEC_DRC_PAYLOAD_TYPE type) { + UINT bsStartPos; + int i, numBands = 1, bitCnt = 0; + + if (self == NULL) { + return 0; + } + + bsStartPos = FDKgetValidBits(bs); + + switch (type) { + case MPEG_DRC_EXT_DATA: { + bitCnt = 4; + + if (FDKreadBits(bs, 1)) { /* pce_tag_present */ + FDKreadBits(bs, 8); /* pce_instance_tag + drc_tag_reserved_bits */ + bitCnt += 8; + } + + if (FDKreadBits(bs, 1)) { /* excluded_chns_present */ + FDKreadBits(bs, 7); /* exclude mask [0..7] */ + bitCnt += 8; + while (FDKreadBits(bs, 1)) { /* additional_excluded_chns */ + FDKreadBits(bs, 7); /* exclude mask [x..y] */ + bitCnt += 8; + } + } + + if (FDKreadBits(bs, 1)) { /* drc_bands_present */ + numBands += FDKreadBits(bs, 4); /* drc_band_incr */ + FDKreadBits(bs, 4); /* reserved */ + bitCnt += 8; + for (i = 0; i < numBands; i++) { + FDKreadBits(bs, 8); /* drc_band_top[i] */ + bitCnt += 8; + } + } + + if (FDKreadBits(bs, 1)) { /* prog_ref_level_present */ + FDKreadBits(bs, 8); /* prog_ref_level + prog_ref_level_reserved_bits */ + bitCnt += 8; + } + + for (i = 0; i < numBands; i++) { + FDKreadBits(bs, 8); /* dyn_rng_sgn[i] + dyn_rng_ctl[i] */ + bitCnt += 8; + } + + if ((self->numPayloads < MAX_DRC_THREADS) && + ((INT)FDKgetValidBits(bs) >= 0)) { + self->drcPayloadPosition[self->numPayloads++] = bsStartPos; + } + } break; + + case DVB_DRC_ANC_DATA: + bitCnt += 8; + /* check sync word */ + if (FDKreadBits(bs, 8) == DVB_ANC_DATA_SYNC_BYTE) { + int dmxLevelsPresent, compressionPresent; + int coarseGrainTcPresent, fineGrainTcPresent; + + /* bs_info field */ + FDKreadBits( + bs, + 8); /* mpeg_audio_type, dolby_surround_mode, presentation_mode */ + bitCnt += 8; + + /* Evaluate ancillary_data_status */ + FDKreadBits(bs, 3); /* reserved, set to 0 */ + dmxLevelsPresent = + FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */ + FDKreadBits(bs, 1); /* reserved, set to 0 */ + compressionPresent = + FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */ + coarseGrainTcPresent = + FDKreadBits(bs, 1); /* coarse_grain_timecode_status */ + fineGrainTcPresent = + FDKreadBits(bs, 1); /* fine_grain_timecode_status */ + bitCnt += 8; + + /* MPEG4 downmixing levels */ + if (dmxLevelsPresent) { + FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */ + bitCnt += 8; + } + /* audio coding mode and compression status */ + if (compressionPresent) { + FDKreadBits(bs, 16); /* audio_coding_mode, Compression_value */ + bitCnt += 16; + } + /* coarse grain timecode */ + if (coarseGrainTcPresent) { + FDKreadBits(bs, 16); /* coarse_grain_timecode */ + bitCnt += 16; + } + /* fine grain timecode */ + if (fineGrainTcPresent) { + FDKreadBits(bs, 16); /* fine_grain_timecode */ + bitCnt += 16; + } + if (!self->dvbAncDataAvailable && ((INT)FDKgetValidBits(bs) >= 0)) { + self->dvbAncDataPosition = bsStartPos; + self->dvbAncDataAvailable = 1; + } + } + break; + + default: + break; + } + + return (bitCnt); +} + +/*! + \brief Parse DRC parameters from bitstream + + \bs Handle of FDK bitstream (in) + \pDrcBs Pointer to DRC payload data container (out) + \payloadPosition Bitstream position of MPEG DRC data chunk (in) + + \return Flag telling whether new DRC data has been found or not. +*/ +static int aacDecoder_drcParse(HANDLE_FDK_BITSTREAM bs, CDrcPayload *pDrcBs, + UINT payloadPosition) { + int i, numBands; + + /* Move to the beginning of the DRC payload field */ + FDKpushBiDirectional(bs, (INT)FDKgetValidBits(bs) - (INT)payloadPosition); + + /* pce_tag_present */ + if (FDKreadBits(bs, 1)) { + pDrcBs->pceInstanceTag = FDKreadBits(bs, 4); /* pce_instance_tag */ + /* only one program supported */ + FDKreadBits(bs, 4); /* drc_tag_reserved_bits */ + } else { + pDrcBs->pceInstanceTag = -1; /* not present */ + } + + if (FDKreadBits(bs, 1)) { /* excluded_chns_present */ + /* get excluded_chn_mask */ + parseExcludedChannels(&pDrcBs->excludedChnsMask, bs); + } else { + pDrcBs->excludedChnsMask = 0; + } + + numBands = 1; + if (FDKreadBits(bs, 1)) /* drc_bands_present */ + { + /* get band_incr */ + numBands += FDKreadBits(bs, 4); /* drc_band_incr */ + pDrcBs->channelData.drcInterpolationScheme = + FDKreadBits(bs, 4); /* drc_interpolation_scheme */ + /* band_top */ + for (i = 0; i < numBands; i++) { + pDrcBs->channelData.bandTop[i] = FDKreadBits(bs, 8); /* drc_band_top[i] */ + } + } else { + pDrcBs->channelData.bandTop[0] = DRC_BLOCK_LEN_DIV_BAND_MULT - + 1; /* ... comprising the whole spectrum. */ + ; + } + + pDrcBs->channelData.numBands = numBands; + + if (FDKreadBits(bs, 1)) /* prog_ref_level_present */ + { + pDrcBs->progRefLevel = FDKreadBits(bs, 7); /* prog_ref_level */ + FDKreadBits(bs, 1); /* prog_ref_level_reserved_bits */ + } else { + pDrcBs->progRefLevel = -1; + } + + for (i = 0; i < numBands; i++) { + pDrcBs->channelData.drcValue[i] = FDKreadBits(bs, 1) + << 7; /* dyn_rng_sgn[i] */ + pDrcBs->channelData.drcValue[i] |= + FDKreadBits(bs, 7) & 0x7F; /* dyn_rng_ctl[i] */ + } + + /* Set DRC payload type */ + pDrcBs->channelData.drcDataType = MPEG_DRC_EXT_DATA; + + return (1); +} + +/*! + \brief Parse heavy compression value transported in DSEs of DVB streams with + MPEG-4 content. + + \bs Handle of FDK bitstream (in) + \pDrcBs Pointer to DRC payload data container (out) + \payloadPosition Bitstream position of DVB ancillary data chunk + + \return Flag telling whether new DRC data has been found or not. +*/ +#define DVB_COMPRESSION_SCALE (8) /* 48,164 dB */ + +static int aacDecoder_drcReadCompression(HANDLE_FDK_BITSTREAM bs, + CDrcPayload *pDrcBs, + UINT payloadPosition) { + int foundDrcData = 0; + int dmxLevelsPresent, compressionPresent; + + /* Move to the beginning of the DRC payload field */ + FDKpushBiDirectional(bs, (INT)FDKgetValidBits(bs) - (INT)payloadPosition); + + /* Sanity checks */ + if (FDKgetValidBits(bs) < 24) { + return 0; + } + + /* Check sync word */ + if (FDKreadBits(bs, 8) != DVB_ANC_DATA_SYNC_BYTE) { + return 0; + } + + /* Evaluate bs_info field */ + if (FDKreadBits(bs, 2) != 3) { /* mpeg_audio_type */ + /* No MPEG-4 audio data */ + return 0; + } + FDKreadBits(bs, 2); /* dolby_surround_mode */ + pDrcBs->presMode = FDKreadBits(bs, 2); /* presentation_mode */ + FDKreadBits(bs, 1); /* stereo_downmix_mode */ + if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */ + return 0; + } + + /* Evaluate ancillary_data_status */ + if (FDKreadBits(bs, 3) != 0) { /* reserved, set to 0 */ + return 0; + } + dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */ + /*extensionPresent =*/FDKreadBits(bs, + 1); /* ancillary_data_extension_status; */ + compressionPresent = + FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */ + /*coarseGrainTcPresent =*/FDKreadBits(bs, + 1); /* coarse_grain_timecode_status */ + /*fineGrainTcPresent =*/FDKreadBits(bs, 1); /* fine_grain_timecode_status */ + + if (dmxLevelsPresent) { + FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */ + } + + /* audio_coding_mode_and_compression_status */ + if (compressionPresent) { + UCHAR compressionOn, compressionValue; + + /* audio_coding_mode */ + if (FDKreadBits(bs, 7) != 0) { /* The reserved bits shall be set to "0". */ + return 0; + } + compressionOn = (UCHAR)FDKreadBits(bs, 1); /* compression_on */ + compressionValue = (UCHAR)FDKreadBits(bs, 8); /* Compression_value */ + + if (compressionOn) { + /* A compression value is available so store the data just like MPEG DRC + * data */ + pDrcBs->channelData.numBands = 1; /* One band ... */ + pDrcBs->channelData.drcValue[0] = + compressionValue; /* ... with one value ... */ + pDrcBs->channelData.bandTop[0] = + DRC_BLOCK_LEN_DIV_BAND_MULT - + 1; /* ... comprising the whole spectrum. */ + ; + pDrcBs->pceInstanceTag = -1; /* Not present */ + pDrcBs->progRefLevel = -1; /* Not present */ + pDrcBs->channelData.drcDataType = + DVB_DRC_ANC_DATA; /* Set DRC payload type to DVB. */ + foundDrcData = 1; + } + } + + return (foundDrcData); +} + +/* + * Extract DRC payload from bitstream and map it to channels. + * Valid return values are: + * -1 : An unexpected error occured. + * 0 : No error and no valid DRC data available. + * 1 : No error and valid DRC data has been mapped. + */ +static int aacDecoder_drcExtractAndMap( + HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, + UCHAR channelMapping[], /* Channel mapping translating drcChannel index to + canonical channel index */ + int validChannels) { + CDrcPayload threadBs[MAX_DRC_THREADS]; + CDrcPayload *validThreadBs[MAX_DRC_THREADS]; + CDrcParams *pParams; + UINT backupBsPosition; + int result = 0; + int i, thread, validThreads = 0; + + FDK_ASSERT(self != NULL); + FDK_ASSERT(hBs != NULL); + FDK_ASSERT(pAacDecoderStaticChannelInfo != NULL); + + pParams = &self->params; + + self->numThreads = 0; + backupBsPosition = FDKgetValidBits(hBs); + + for (i = 0; i < self->numPayloads && self->numThreads < MAX_DRC_THREADS; + i++) { + /* Init payload data chunk. The memclear is very important because it + initializes the most values. Without it the module wouldn't work properly + or crash. */ + FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload)); + threadBs[self->numThreads].channelData.bandTop[0] = + DRC_BLOCK_LEN_DIV_BAND_MULT - 1; + + /* Extract payload */ + self->numThreads += aacDecoder_drcParse(hBs, &threadBs[self->numThreads], + self->drcPayloadPosition[i]); + } + self->numPayloads = 0; + + if (self->dvbAncDataAvailable && + self->numThreads < MAX_DRC_THREADS) { /* Append a DVB heavy compression + payload thread if available. */ + + /* Init payload data chunk. The memclear is very important because it + initializes the most values. Without it the module wouldn't work properly + or crash. */ + FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload)); + threadBs[self->numThreads].channelData.bandTop[0] = + DRC_BLOCK_LEN_DIV_BAND_MULT - 1; + + /* Extract payload */ + self->numThreads += aacDecoder_drcReadCompression( + hBs, &threadBs[self->numThreads], self->dvbAncDataPosition); + } + self->dvbAncDataAvailable = 0; + + /* Reset the bitbufffer */ + FDKpushBiDirectional(hBs, (INT)FDKgetValidBits(hBs) - (INT)backupBsPosition); + + /* calculate number of valid bits in excl_chn_mask */ + + /* coupling channels not supported */ + + /* check for valid threads */ + for (thread = 0; thread < self->numThreads; thread++) { + CDrcPayload *pThreadBs = &threadBs[thread]; + int numExclChns = 0; + + switch ((AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType) { + default: + continue; + case MPEG_DRC_EXT_DATA: + case DVB_DRC_ANC_DATA: + break; + } + + if (pThreadBs->pceInstanceTag >= 0) { /* if PCE tag present */ + if (pThreadBs->pceInstanceTag != pceInstanceTag) { + continue; /* don't accept */ + } + } + + /* calculate number of excluded channels */ + if (pThreadBs->excludedChnsMask > 0) { + INT exclMask = pThreadBs->excludedChnsMask; + int ch; + for (ch = 0; ch < validChannels; ch++) { + numExclChns += exclMask & 0x1; + exclMask >>= 1; + } + } + if (numExclChns < validChannels) { + validThreadBs[validThreads] = pThreadBs; + validThreads++; + } + } + + /* map DRC bitstream information onto DRC channel information */ + for (thread = 0; thread < validThreads; thread++) { + CDrcPayload *pThreadBs = validThreadBs[thread]; + INT exclMask = pThreadBs->excludedChnsMask; + AACDEC_DRC_PAYLOAD_TYPE drcPayloadType = + (AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType; + int ch; + + /* last progRefLevel transmitted is the one that is used + * (but it should really only be transmitted once per block!) + */ + if (pThreadBs->progRefLevel >= 0) { + self->progRefLevel = pThreadBs->progRefLevel; + self->progRefLevelPresent = 1; + self->prlExpiryCount = 0; /* Got a new value -> Reset counter */ + } + + if (drcPayloadType == DVB_DRC_ANC_DATA) { + /* Announce the presentation mode of this valid thread. */ + self->presMode = pThreadBs->presMode; + } + + /* SCE, CPE and LFE */ + for (ch = 0; ch < validChannels; ch++) { + AACDEC_DRC_PAYLOAD_TYPE prvPayloadType = UNKNOWN_PAYLOAD; + int mapedChannel = channelMapping[ch]; + + if ((mapedChannel >= validChannels) || + ((exclMask & (1 << mapedChannel)) != 0)) + continue; + + if ((pParams->expiryFrame <= 0) || + (pAacDecoderStaticChannelInfo[ch]->drcData.expiryCount < + pParams->expiryFrame)) { + prvPayloadType = + (AACDEC_DRC_PAYLOAD_TYPE)pAacDecoderStaticChannelInfo[ch] + ->drcData.drcDataType; + } + if (((drcPayloadType == MPEG_DRC_EXT_DATA) && + (prvPayloadType != DVB_DRC_ANC_DATA)) || + ((drcPayloadType == DVB_DRC_ANC_DATA) && + (pParams->applyHeavyCompression == + ON))) { /* copy thread to channel */ + pAacDecoderStaticChannelInfo[ch]->drcData = pThreadBs->channelData; + result = 1; + } + } + /* CCEs not supported by now */ + } + + /* Increment and check expiry counter for the program reference level: */ + if ((pParams->expiryFrame > 0) && + (self->prlExpiryCount++ > + pParams->expiryFrame)) { /* The program reference level is too old, so + set it back to the target level. */ + self->progRefLevelPresent = 0; + self->progRefLevel = pParams->targetRefLevel; + self->prlExpiryCount = 0; + } + + return result; +} + +void aacDecoder_drcApply(HANDLE_AAC_DRC self, void *pSbrDec, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CDrcChannelData *pDrcChData, FIXP_DBL *extGain, + int ch, /* needed only for SBR */ + int aacFrameSize, int bSbrPresent) { + int band, bin, numBands; + int bottom = 0; + int modifyBins = 0; + + FIXP_DBL max_mantissa; + INT max_exponent; + + FIXP_DBL norm_mantissa = FL2FXCONST_DBL(0.5f); + INT norm_exponent = 1; + + FIXP_DBL fact_mantissa[MAX_DRC_BANDS]; + INT fact_exponent[MAX_DRC_BANDS]; + + CDrcParams *pParams = &self->params; + + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + + int winSeq = pIcsInfo->WindowSequence; + + /* Increment and check expiry counter */ + if ((pParams->expiryFrame > 0) && + (++pDrcChData->expiryCount > + pParams->expiryFrame)) { /* The DRC data is too old, so delete it. */ + aacDecoder_drcInitChannelData(pDrcChData); + } + + if (self->enable != ON) { + sbrDecoder_drcDisable((HANDLE_SBRDECODER)pSbrDec, ch); + if (extGain != NULL) { + INT gainScale = (INT)*extGain; + /* The gain scaling must be passed to the function in the buffer pointed + * on by extGain. */ + if (gainScale >= 0 && gainScale <= DFRACT_BITS) { + *extGain = scaleValue(norm_mantissa, norm_exponent - gainScale); + } else { + FDK_ASSERT(0); + } + } + return; + } + + numBands = pDrcChData->numBands; + + /* If program reference normalization is done in the digital domain, + modify factor to perform normalization. prog_ref_level can + alternatively be passed to the system for modification of the level in + the analog domain. Analog level modification avoids problems with + reduced DAC SNR (if signal is attenuated) or clipping (if signal is + boosted) */ + + if (pParams->targetRefLevel >= 0) { + /* 0.5^((targetRefLevel - progRefLevel)/24) */ + norm_mantissa = + fLdPow(FL2FXCONST_DBL(-1.0), /* log2(0.5) */ + 0, + (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0f / 24.0) >> 3) * + (INT)(pParams->targetRefLevel - self->progRefLevel)), + 3, &norm_exponent); + } + /* Always export the normalization gain (if possible). */ + if (extGain != NULL) { + INT gainScale = (INT)*extGain; + /* The gain scaling must be passed to the function in the buffer pointed on + * by extGain. */ + if (gainScale >= 0 && gainScale <= DFRACT_BITS) { + *extGain = scaleValue(norm_mantissa, norm_exponent - gainScale); + } else { + FDK_ASSERT(0); + } + } + /* Reset normalization gain since this module must not apply it */ + norm_mantissa = FL2FXCONST_DBL(0.5f); + norm_exponent = 1; + + /* calc scale factors */ + for (band = 0; band < numBands; band++) { + UCHAR drcVal = pDrcChData->drcValue[band]; + + fact_mantissa[band] = FL2FXCONST_DBL(0.5f); + fact_exponent[band] = 1; + + if ((pParams->applyHeavyCompression == ON) && + ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType == + DVB_DRC_ANC_DATA)) { + INT compressionFactorVal_e; + int valX, valY; + + valX = drcVal >> 4; + valY = drcVal & 0x0F; + + /* calculate the unscaled heavy compression factor. + compressionFactor = 48.164 - 6.0206*valX - 0.4014*valY dB + range: -48.166 dB to 48.164 dB */ + if (drcVal != 0x7F) { + fact_mantissa[band] = fPowInt( + FL2FXCONST_DBL(0.95483867181), /* -0.4014dB = 0.95483867181 */ + 0, valY, &compressionFactorVal_e); + + /* -0.0008dB (48.164 - 6.0206*8 = -0.0008) */ + fact_mantissa[band] = + fMult(FL2FXCONST_DBL(0.99990790084), fact_mantissa[band]); + + fact_exponent[band] = + DVB_COMPRESSION_SCALE - valX + compressionFactorVal_e; + } + } else if ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType == + MPEG_DRC_EXT_DATA) { + /* apply the scaled dynamic range control words to factor. + * if scaling drc_cut (or drc_boost), or control word drc_mantissa is 0 + * then there is no dynamic range compression + * + * if pDrcChData->drcSgn[band] is + * 1 then gain is < 1 : factor = 2^(-self->cut * + * pDrcChData->drcMag[band] / 24) 0 then gain is > 1 : factor = 2^( + * self->boost * pDrcChData->drcMag[band] / 24) + */ + + if ((drcVal & 0x7F) > 0) { + FIXP_DBL tParamVal = (drcVal & 0x80) ? -pParams->cut : pParams->boost; + + fact_mantissa[band] = f2Pow( + (FIXP_DBL)((INT)fMult(FL2FXCONST_DBL(1.0f / 192.0f), tParamVal) * + (drcVal & 0x7F)), + 3 + DRC_PARAM_SCALE, &fact_exponent[band]); + } + } + + fact_mantissa[band] = fMult(fact_mantissa[band], norm_mantissa); + fact_exponent[band] += norm_exponent; + + } /* end loop over bands */ + + /* normalizations */ + { + int res; + + max_mantissa = FL2FXCONST_DBL(0.0f); + max_exponent = 0; + for (band = 0; band < numBands; band++) { + max_mantissa = fixMax(max_mantissa, fact_mantissa[band]); + max_exponent = fixMax(max_exponent, fact_exponent[band]); + } + + /* left shift factors to gain accurancy */ + res = CntLeadingZeros(max_mantissa) - 1; + + /* above topmost DRC band gain factor is 1 */ + if (((pDrcChData->bandTop[fMax(0, numBands - 1)] + 1) << 2) < aacFrameSize) + res = 0; + + if (res > 0) { + res = fixMin(res, max_exponent); + max_exponent -= res; + + for (band = 0; band < numBands; band++) { + fact_mantissa[band] <<= res; + fact_exponent[band] -= res; + } + } + + /* normalize magnitudes to one scale factor */ + for (band = 0; band < numBands; band++) { + if (fact_exponent[band] < max_exponent) { + fact_mantissa[band] >>= max_exponent - fact_exponent[band]; + } + if (fact_mantissa[band] != FL2FXCONST_DBL(0.5f)) { + modifyBins = 1; + } + } + if (max_exponent != 1) { + modifyBins = 1; + } + } + + /* apply factor to spectral lines + * short blocks must take care that bands fall on + * block boundaries! + */ + if (!bSbrPresent) { + bottom = 0; + + if (!modifyBins) { + /* We don't have to modify the spectral bins because the fractional part + of all factors is 0.5. In order to keep accurancy we don't apply the + factor but decrease the exponent instead. */ + max_exponent -= 1; + } else { + for (band = 0; band < numBands; band++) { + int top = fixMin((int)((pDrcChData->bandTop[band] + 1) << 2), + aacFrameSize); /* ... * DRC_BAND_MULT; */ + + for (bin = bottom; bin < top; bin++) { + pSpectralCoefficient[bin] = + fMult(pSpectralCoefficient[bin], fact_mantissa[band]); + } + + bottom = top; + } + } + + /* above topmost DRC band gain factor is 1 */ + if (max_exponent > 0) { + for (bin = bottom; bin < aacFrameSize; bin += 1) { + pSpectralCoefficient[bin] >>= max_exponent; + } + } + + /* adjust scaling */ + pSpecScale[0] += max_exponent; + + if (winSeq == BLOCK_SHORT) { + int win; + for (win = 1; win < 8; win++) { + pSpecScale[win] += max_exponent; + } + } + } else { + HANDLE_SBRDECODER hSbrDecoder = (HANDLE_SBRDECODER)pSbrDec; + numBands = pDrcChData->numBands; + + /* feed factors into SBR decoder for application in QMF domain. */ + sbrDecoder_drcFeedChannel(hSbrDecoder, ch, numBands, fact_mantissa, + max_exponent, pDrcChData->drcInterpolationScheme, + winSeq, pDrcChData->bandTop); + } + + return; +} + +/* + * DRC parameter and presentation mode handling + */ +static void aacDecoder_drcParameterHandling(HANDLE_AAC_DRC self, + INT aacNumChannels, + SCHAR prevDrcProgRefLevel, + SCHAR prevDrcPresMode) { + int isDownmix, isMonoDownmix, isStereoDownmix; + int dDmx, dHr; + AACDEC_DRC_PARAMETER_HANDLING drcParameterHandling; + CDrcParams *p; + + FDK_ASSERT(self != NULL); + + p = &self->params; + + if (self->progRefLevel != prevDrcProgRefLevel) self->update = 1; + + if (self->presMode != prevDrcPresMode) self->update = 1; + + if (self->prevAacNumChannels != aacNumChannels) self->update = 1; + + /* return if no relevant parameter has changed */ + if (!self->update) { + return; + } + + /* derive downmix property. aacNumChannels: number of channels in aac stream, + * numOutChannels: number of output channels */ + isDownmix = (aacNumChannels > self->numOutChannels); + isDownmix = (isDownmix && (self->numOutChannels > 0)); + isMonoDownmix = (isDownmix && (self->numOutChannels == 1)); + isStereoDownmix = (isDownmix && (self->numOutChannels == 2)); + + if ((self->presMode == 1) || (self->presMode == 2)) { + drcParameterHandling = (AACDEC_DRC_PARAMETER_HANDLING)self->presMode; + } else { /* no presentation mode -> use parameter handling specified by + AAC_DRC_DEFAULT_PRESENTATION_MODE */ + drcParameterHandling = p->defaultPresentationMode; + } + + /* by default, do as desired */ + p->cut = p->usrCut; + p->boost = p->usrBoost; + p->applyHeavyCompression = p->usrApplyHeavyCompression; + + switch (drcParameterHandling) { + case DISABLED_PARAMETER_HANDLING: + default: + /* use drc parameters as requested */ + break; + + case ENABLED_PARAMETER_HANDLING: + /* dDmx: estimated headroom reduction due to downmix, format: -1/4*dB + dDmx = floor(-4*20*log10(aacNumChannels/numOutChannels)) */ + if (isDownmix) { + FIXP_DBL dmxTmp; + int e_log, e_mult; + dmxTmp = fDivNorm(self->numOutChannels, + aacNumChannels); /* inverse division -> + negative sign after + logarithm */ + dmxTmp = fLog2(dmxTmp, 0, &e_log); + dmxTmp = fMultNorm( + dmxTmp, FL2FXCONST_DBL(4.0f * 20.0f * 0.30103f / (float)(1 << 5)), + &e_mult); /* e = e_log + e_mult + 5 */ + dDmx = (int)scaleValue(dmxTmp, e_log + e_mult + 5 - (DFRACT_BITS - 1)); + } else { + dDmx = 0; + } + + /* dHr: Full estimated (decoder) headroom reduction due to loudness + * normalisation (DTL - PRL) and downmix. Format: -1/4*dB */ + if (p->targetRefLevel >= 0) { /* if target level is provided */ + dHr = p->targetRefLevel + dDmx - self->progRefLevel; + } else { + dHr = dDmx; + } + + if (dHr < 0) { /* if headroom is reduced */ + /* Use compression, but as little as possible. */ + /* eHr: Headroom provided by encoder, format: -1/4 dB */ + int eHr = fixMin(p->encoderTargetLevel - self->progRefLevel, 0); + if (eHr < + dHr) { /* if encoder provides more headroom than decoder needs */ + /* derive scaling of light DRC */ + FIXP_DBL calcFactor_norm; + INT calcFactor; /* fraction of DRC gains that is minimally needed for + clipping prevention */ + calcFactor_norm = + fDivNorm(-dHr, -eHr); /* 0.0 < calcFactor_norm < 1.0 */ + calcFactor_norm = calcFactor_norm >> DRC_PARAM_SCALE; + /* quantize to 128 steps */ + calcFactor = convert_drcParam( + calcFactor_norm); /* convert to integer value between 0 and 127 */ + calcFactor_norm = (FIXP_DBL)( + (INT)(DRC_PARAM_QUANT_STEP >> DRC_PARAM_SCALE) * calcFactor); + p->cut = (calcFactor_norm > p->cut) + ? calcFactor_norm + : p->cut; /* use calcFactor_norm as lower limit */ + } else { + /* encoder provides equal or less headroom than decoder needs */ + /* the time domain limiter must always be active in this case. It is + * assumed that the framework activates it by default */ + p->cut = DRC_SCALING_MAX; + if ((dHr - eHr) <= + -4 * DRC_HEAVY_THRESHOLD_DB) { /* use heavy compression if + headroom deficit is equal or + higher than + DRC_HEAVY_THRESHOLD_DB */ + p->applyHeavyCompression = ON; + } + } + } else { /* dHr >= 0 */ + /* no restrictions required, as headroom is not reduced. */ + /* p->cut = p->usrCut; */ + } + break; + + /* presentation mode 1 and 2 according to ETSI TS 101 154: + Digital Video Broadcasting (DVB); Specification for the use of Video + and Audio Coding in Broadcasting Applications based on the MPEG-2 + Transport Stream, section C.5.4., "Decoding", and Table C.33. Also + according to amendment 4 to ISO/IEC 14496-3, section 4.5.2.14.2.4, and + Table AMD4.11. ISO DRC -> applyHeavyCompression = OFF (Use + light compression, MPEG-style) Compression_value -> + applyHeavyCompression = ON (Use heavy compression, DVB-style) scaling + restricted -> p->cut = DRC_SCALING_MAX */ + + case DRC_PRESENTATION_MODE_1: /* presentation mode 1, Light:-31/Heavy:-23 */ + if ((p->targetRefLevel >= 0) && + (p->targetRefLevel < + 124)) { /* if target level is provided and > -31 dB */ + /* playback up to -23 dB */ + p->applyHeavyCompression = ON; + } else { /* target level <= -31 dB or not provided */ + /* playback -31 dB */ + if (isMonoDownmix || isStereoDownmix) { /* stereo or mono downmixing */ + p->cut = DRC_SCALING_MAX; + } + } + break; + + case DRC_PRESENTATION_MODE_2: /* presentation mode 2, Light:-23/Heavy:-23 */ + if ((p->targetRefLevel >= 0) && + (p->targetRefLevel < + 124)) { /* if target level is provided and > -31 dB */ + /* playback up to -23 dB */ + if (isMonoDownmix) { /* if mono downmix */ + p->applyHeavyCompression = ON; + } else { + p->applyHeavyCompression = OFF; + p->cut = DRC_SCALING_MAX; + } + } else { /* target level <= -31 dB or not provided */ + /* playback -31 dB */ + p->applyHeavyCompression = OFF; + if (isMonoDownmix || isStereoDownmix) { /* stereo or mono downmixing */ + p->cut = DRC_SCALING_MAX; + } + } + break; + } /* switch (drcParameterHandling) */ + + /* With heavy compression, there is no scaling. + Scaling factors are set for notification only. */ + if (p->applyHeavyCompression == ON) { + p->boost = DRC_SCALING_MAX; + p->cut = DRC_SCALING_MAX; + } + + /* switch on/off processing */ + self->enable = ((p->boost > (FIXP_DBL)0) || (p->cut > (FIXP_DBL)0) || + (p->applyHeavyCompression == ON) || (p->targetRefLevel >= 0)); + + self->prevAacNumChannels = aacNumChannels; + self->update = 0; +} + +/* + * Prepare DRC processing + * Valid return values are: + * -1 : An unexpected error occured. + * 0 : No error and no valid DRC data available. + * 1 : No error and valid DRC data has been mapped. + */ +int aacDecoder_drcProlog( + HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, + UCHAR channelMapping[], /* Channel mapping translating drcChannel index to + canonical channel index */ + int validChannels) { + int result = 0; + + if (self == NULL) { + return -1; + } + + if (!self->params.bsDelayEnable) { + /* keep previous progRefLevel and presMode for update flag in + * drcParameterHandling */ + INT prevPRL, prevPM = 0; + prevPRL = self->progRefLevel; + prevPM = self->presMode; + + result = aacDecoder_drcExtractAndMap( + self, hBs, pAacDecoderStaticChannelInfo, pceInstanceTag, channelMapping, + validChannels); + + if (result < 0) { + return result; + } + + /* Drc parameter handling */ + aacDecoder_drcParameterHandling(self, validChannels, prevPRL, prevPM); + } + + return result; +} + +/* + * Finalize DRC processing + * Valid return values are: + * -1 : An unexpected error occured. + * 0 : No error and no valid DRC data available. + * 1 : No error and valid DRC data has been mapped. + */ +int aacDecoder_drcEpilog( + HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, + UCHAR channelMapping[], /* Channel mapping translating drcChannel index to + canonical channel index */ + int validChannels) { + int result = 0; + + if (self == NULL) { + return -1; + } + + if (self->params.bsDelayEnable) { + /* keep previous progRefLevel and presMode for update flag in + * drcParameterHandling */ + INT prevPRL, prevPM = 0; + prevPRL = self->progRefLevel; + prevPM = self->presMode; + + result = aacDecoder_drcExtractAndMap( + self, hBs, pAacDecoderStaticChannelInfo, pceInstanceTag, channelMapping, + validChannels); + + if (result < 0) { + return result; + } + + /* Drc parameter handling */ + aacDecoder_drcParameterHandling(self, validChannels, prevPRL, prevPM); + } + + return result; +} + +/* + * Export relevant metadata info from bitstream payload. + */ +void aacDecoder_drcGetInfo(HANDLE_AAC_DRC self, SCHAR *pPresMode, + SCHAR *pProgRefLevel) { + if (self != NULL) { + if (pPresMode != NULL) { + *pPresMode = self->presMode; + } + if (pProgRefLevel != NULL) { + if (self->progRefLevelPresent) { + *pProgRefLevel = self->progRefLevel; + } else { + *pProgRefLevel = -1; + } + } + } +} + +/** + * \brief Apply DRC Level Normalization. + * + * This function prepares/applies the gain values for the DRC Level + * Normalization and returns the exponent of the time data. The following two + * cases are handled: + * + * - Limiter enabled: + * The input data must be interleaved. + * One gain per sample is written to the buffer pGainPerSample. + * If necessary the time data is rescaled. + * + * - Limiter disabled: + * The input data can be interleaved or deinterleaved. + * The gain values are applied to the time data. + * If necessary the time data is rescaled. + * + * \param hDrcInfo [i/o] handle to drc data structure. + * \param samplesIn [i/o] pointer to time data. + * \param pGain [i ] pointer to gain to be applied to + * the time data. + * \param pGainPerSample [o ] pointer to the gain per sample to + * be applied to the time data in the limiter. + * \param gain_scale [i ] exponent to be applied to the time + * data. + * \param gain_delay [i ] delay[samples] with which the gains + * in pGain shall be applied (gain_delay <= nSamples). + * \param nSamples [i ] number of samples per frame. + * \param channels [i ] number of channels. + * \param stride [i ] channel stride of time data. + * \param limiterEnabled [i ] 1 if limiter is enabled, otherwise + * 0. + * + * \return exponent of time data + */ +INT applyDrcLevelNormalization(HANDLE_AAC_DRC hDrcInfo, PCM_DEC *samplesIn, + FIXP_DBL *pGain, FIXP_DBL *pGainPerSample, + const INT gain_scale, const UINT gain_delay, + const UINT nSamples, const UINT channels, + const UINT stride, const UINT limiterEnabled) { + UINT i; + INT additionalGain_scaling; + FIXP_DBL additionalGain; + + FDK_ASSERT(gain_delay <= nSamples); + + FIXP_DBL additionalGainSmoothState = hDrcInfo->additionalGainFilterState; + FIXP_DBL additionalGainSmoothState1 = hDrcInfo->additionalGainFilterState1; + + if (!gain_delay) { + additionalGain = pGain[0]; + + /* Apply the additional scaling gain_scale[0] that has no delay and no + * smoothing */ + additionalGain_scaling = + fMin(gain_scale, CntLeadingZeros(additionalGain) - 1); + additionalGain = scaleValue(additionalGain, additionalGain_scaling); + + /* if it's not possible to fully apply gain_scale to additionalGain, apply + * it to the input signal */ + additionalGain_scaling -= gain_scale; + + if (additionalGain_scaling) { + scaleValuesSaturate(samplesIn, channels * nSamples, + -additionalGain_scaling); + } + + if (limiterEnabled) { + FDK_ASSERT(pGainPerSample != NULL); + + for (i = 0; i < nSamples; i++) { + pGainPerSample[i] = additionalGain; + } + } else { + for (i = 0; i < channels * nSamples; i++) { + samplesIn[i] = FIXP_DBL2PCM_DEC(fMult(samplesIn[i], additionalGain)); + } + } + } else { + UINT inc; + FIXP_DBL additionalGainUnfiltered; + + inc = (stride == 1) ? channels : 1; + + for (i = 0; i < nSamples; i++) { + if (i < gain_delay) { + additionalGainUnfiltered = hDrcInfo->additionalGainPrev; + } else { + additionalGainUnfiltered = pGain[0]; + } + + /* Smooth additionalGain */ + + /* [b,a] = butter(1, 0.01) */ + static const FIXP_SGL b[] = {FL2FXCONST_SGL(0.015466 * 2.0), + FL2FXCONST_SGL(0.015466 * 2.0)}; + static const FIXP_SGL a[] = {(FIXP_SGL)MAXVAL_SGL, + FL2FXCONST_SGL(-0.96907)}; + + additionalGain = -fMult(additionalGainSmoothState, a[1]) + + fMultDiv2(additionalGainUnfiltered, b[0]) + + fMultDiv2(additionalGainSmoothState1, b[1]); + additionalGainSmoothState1 = additionalGainUnfiltered; + additionalGainSmoothState = additionalGain; + + /* Apply the additional scaling gain_scale[0] that has no delay and no + * smoothing */ + additionalGain_scaling = + fMin(gain_scale, CntLeadingZeros(additionalGain) - 1); + additionalGain = scaleValue(additionalGain, additionalGain_scaling); + + /* if it's not possible to fully apply gain_scale[0] to additionalGain, + * apply it to the input signal */ + additionalGain_scaling -= gain_scale; + + if (limiterEnabled) { + FDK_ASSERT(stride == 1); + FDK_ASSERT(pGainPerSample != NULL); + + if (additionalGain_scaling) { + scaleValuesSaturate(samplesIn, channels, -additionalGain_scaling); + } + + pGainPerSample[i] = additionalGain; + } else { + if (additionalGain_scaling) { + for (UINT k = 0; k < channels; k++) { + scaleValuesSaturate(&samplesIn[k * stride], 1, + -additionalGain_scaling); + } + } + + for (UINT k = 0; k < channels; k++) { + samplesIn[k * stride] = + FIXP_DBL2PCM_DEC(fMult(samplesIn[k * stride], additionalGain)); + } + } + + samplesIn += inc; + } + } + + hDrcInfo->additionalGainPrev = pGain[0]; + hDrcInfo->additionalGainFilterState = additionalGainSmoothState; + hDrcInfo->additionalGainFilterState1 = additionalGainSmoothState1; + + return (AACDEC_DRC_GAIN_SCALING); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_drc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_drc.h new file mode 100644 index 0000000000000..f2c1390289243 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_drc.h @@ -0,0 +1,240 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Christian Griebel + + Description: Dynamic range control (DRC) decoder tool for AAC + +*******************************************************************************/ + +#ifndef AACDEC_DRC_H +#define AACDEC_DRC_H + +#include "tp_data.h" /* for program config element support */ + +#include "aacdec_drc_types.h" +#include "channel.h" +#include "FDK_bitstream.h" + +#define AACDEC_DRC_GAIN_SCALING (11) /* Scaling of DRC gains */ +#define AACDEC_DRC_GAIN_INIT_VALUE \ + (FL2FXCONST_DBL( \ + 1.0f / (1 << AACDEC_DRC_GAIN_SCALING))) /* Init value for DRC gains */ + +#define AACDEC_DRC_DFLT_EXPIRY_FRAMES \ + (0) /* Default DRC data expiry time in AAC frames */ + +/* #define AACDEC_DRC_IGNORE_FRAMES_WITH_MULTIPLE_CH_THREADS */ /* The name says + it all. */ +/* #define AACDEC_DRC_DEBUG */ + +/** + * \brief DRC module setting parameters + */ +typedef enum { + DRC_CUT_SCALE = 0, + DRC_BOOST_SCALE, + TARGET_REF_LEVEL, + DRC_BS_DELAY, + DRC_DATA_EXPIRY_FRAME, + APPLY_HEAVY_COMPRESSION, + DEFAULT_PRESENTATION_MODE, + ENCODER_TARGET_LEVEL, + MAX_OUTPUT_CHANNELS +} AACDEC_DRC_PARAM; + +/** + * \brief DRC module interface functions + */ +void aacDecoder_drcDisable(HANDLE_AAC_DRC self); + +void aacDecoder_drcReset(HANDLE_AAC_DRC self); + +void aacDecoder_drcInit(HANDLE_AAC_DRC self); + +void aacDecoder_drcInitChannelData(CDrcChannelData *pDrcChannel); + +AAC_DECODER_ERROR aacDecoder_drcSetParam(HANDLE_AAC_DRC self, + AACDEC_DRC_PARAM param, INT value); + +int aacDecoder_drcMarkPayload(HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs, + AACDEC_DRC_PAYLOAD_TYPE type); + +int aacDecoder_drcProlog( + HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, UCHAR channelMapping[], int validChannels); + +/** + * \brief Apply DRC. If SBR is present, DRC data is handed over to the SBR + * decoder. + * \param self AAC decoder instance + * \param pSbrDec pointer to SBR decoder instance + * \param pAacDecoderChannelInfo AAC decoder channel instance to be processed + * \param pDrcDat DRC channel data + * \param extGain Pointer to a FIXP_DBL where a externally applyable gain will + * be stored into (independently on whether it will be apply internally or not). + * At function call the buffer must hold the scale (0 >= scale < + * DFRACT_BITS) to be applied on the gain value. + * \param ch channel index + * \param aacFrameSize AAC frame size + * \param bSbrPresent flag indicating that SBR is present, in which case DRC is + * handed over to the SBR instance pSbrDec + */ +void aacDecoder_drcApply(HANDLE_AAC_DRC self, void *pSbrDec, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CDrcChannelData *pDrcDat, FIXP_DBL *extGain, int ch, + int aacFrameSize, int bSbrPresent); + +int aacDecoder_drcEpilog( + HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, UCHAR channelMapping[], int validChannels); + +/** + * \brief Get metadata information found in bitstream. + * \param self DRC module instance handle. + * \param pPresMode Pointer to field where the presentation mode will be written + * to. + * \param pProgRefLevel Pointer to field where the program reference level will + * be written to. + * \return Nothing. + */ +void aacDecoder_drcGetInfo(HANDLE_AAC_DRC self, SCHAR *pPresMode, + SCHAR *pProgRefLevel); + +/** + * \brief Apply DRC Level Normalization. + * + * This function prepares/applies the gain values for the DRC Level + * Normalization and returns the exponent of the time data. The following two + * cases are handled: + * + * - Limiter enabled: + * The input data must be interleaved. + * One gain per sample is written to the buffer pGainPerSample. + * If necessary the time data is rescaled. + * + * - Limiter disabled: + * The input data can be interleaved or deinterleaved. + * The gain values are applied to the time data. + * If necessary the time data is rescaled. + * + * \param hDrcInfo [i/o] handle to drc data structure. + * \param samplesIn [i/o] pointer to time data. + * \param pGain [i ] pointer to gain to be applied to + * the time data. + * \param pGainPerSample [o ] pointer to the gain per sample to + * be applied to the time data in the limiter. + * \param gain_scale [i ] exponent to be applied to the time + * data. + * \param gain_delay [i ] delay[samples] with which the gains + * in pGain shall be applied (gain_delay <= nSamples). + * \param nSamples [i ] number of samples per frame. + * \param channels [i ] number of channels. + * \param stride [i ] channel stride of time data. + * \param limiterEnabled [i ] 1 if limiter is enabled, otherwise + * 0. + * + * \return exponent of time data + */ +INT applyDrcLevelNormalization(HANDLE_AAC_DRC hDrcInfo, PCM_DEC *samplesIn, + FIXP_DBL *pGain, FIXP_DBL *pGainPerSample, + const INT gain_scale, const UINT gain_delay, + const UINT nSamples, const UINT channels, + const UINT stride, const UINT limiterEnabled); + +#endif /* AACDEC_DRC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_drc_types.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_drc_types.h new file mode 100644 index 0000000000000..c4c07949502a2 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_drc_types.h @@ -0,0 +1,221 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Christian Griebel + + Description: Dynamic range control (DRC) global data types + +*******************************************************************************/ + +#ifndef AACDEC_DRC_TYPES_H +#define AACDEC_DRC_TYPES_H + +#include "common_fix.h" + +#define MAX_DRC_THREADS \ + ((8) + 1) /* Heavy compression value is handled just like MPEG DRC data */ +#define MAX_DRC_BANDS (16) /* 2^LEN_DRC_BAND_INCR (LEN_DRC_BAND_INCR = 4) */ + +/** + * \brief DRC module global data types + */ +typedef enum { + UNKNOWN_PAYLOAD = 0, + MPEG_DRC_EXT_DATA = 1, + DVB_DRC_ANC_DATA = 2 + +} AACDEC_DRC_PAYLOAD_TYPE; + +/** + * \brief Options for parameter handling / presentation mode + */ +typedef enum { + DISABLED_PARAMETER_HANDLING = -1, /*!< DRC parameter handling disabled, all + parameters are applied as requested. */ + ENABLED_PARAMETER_HANDLING = + 0, /*!< Apply changes to requested DRC parameters to prevent clipping */ + DRC_PRESENTATION_MODE_1 = 1, /*!< DRC Presentation mode 1*/ + DRC_PRESENTATION_MODE_2 = 2 /*!< DRC Presentation mode 2*/ + +} AACDEC_DRC_PARAMETER_HANDLING; + +typedef struct { + UINT expiryCount; + UINT numBands; + USHORT bandTop[MAX_DRC_BANDS]; + SHORT drcInterpolationScheme; + UCHAR drcValue[MAX_DRC_BANDS]; + SCHAR drcDataType; + +} CDrcChannelData; + +typedef struct { + UINT excludedChnsMask; + SCHAR progRefLevel; + SCHAR presMode; /* Presentation mode: 0 (not indicated), 1, 2, and 3 + (reserved). */ + SCHAR pceInstanceTag; + + CDrcChannelData channelData; + +} CDrcPayload; + +typedef struct { + /* DRC parameters: Latest user requests */ + FIXP_DBL usrCut; + FIXP_DBL usrBoost; + UCHAR usrApplyHeavyCompression; + + /* DRC parameters: Currently used, possibly changed by + * aacDecoder_drcParameterHandling */ + FIXP_DBL cut; /* attenuation scale factor */ + FIXP_DBL boost; /* boost scale factor */ + SCHAR targetRefLevel; /* target reference level for loudness normalization */ + UCHAR applyHeavyCompression; /* heavy compression (DVB) flag */ + + UINT expiryFrame; + UCHAR bsDelayEnable; + + AACDEC_DRC_PARAMETER_HANDLING defaultPresentationMode; + UCHAR encoderTargetLevel; + +} CDrcParams; + +typedef struct { + CDrcParams + params; /* Module parameters that can be set by user (via SetParam API + function) */ + + UCHAR enable; /* Switch that controls dynamic range processing */ + UCHAR digitalNorm; /* Switch to en-/disable reference level normalization in + digital domain */ + + UCHAR update; /* Flag indicating the change of a user or bitstream parameter + which affects aacDecoder_drcParameterHandling */ + INT numOutChannels; /* Number of output channels */ + INT prevAacNumChannels; /* Previous number of channels of aac bitstream, used + for update flag */ + + USHORT numPayloads; /* The number of DRC data payload elements found within + frame */ + USHORT + numThreads; /* The number of DRC data threads extracted from the found + payload elements */ + SCHAR progRefLevel; /* Program reference level for all channels */ + UCHAR progRefLevelPresent; /* Program reference level found in bitstream */ + + UINT prlExpiryCount; /* Counter that can be used to monitor the life time of + the program reference level. */ + + SCHAR presMode; /* Presentation mode as defined in ETSI TS 101 154 */ + UCHAR dvbAncDataAvailable; /* Flag that indicates whether DVB ancillary data + is present or not */ + UINT dvbAncDataPosition; /* Used to store the DVB ancillary data payload + position in the bitstream (only one per frame) */ + UINT drcPayloadPosition[MAX_DRC_THREADS]; /* Used to store the DRC payload + positions in the bitstream */ + UCHAR applyExtGain; /* Flag is 1 if extGain has to be applied, otherwise 0. */ + + FIXP_DBL additionalGainPrev; /* Gain of previous frame to be applied to the + time data */ + FIXP_DBL additionalGainFilterState; /* Filter state for the gain smoothing */ + FIXP_DBL additionalGainFilterState1; /* Filter state for the gain smoothing */ + +} CDrcInfo; + +typedef CDrcInfo *HANDLE_AAC_DRC; + +#endif /* AACDEC_DRC_TYPES_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr.cpp new file mode 100644 index 0000000000000..a7e9cce439627 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr.cpp @@ -0,0 +1,1508 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: HCR initialization, preprocess HCR sideinfo, + decode priority codewords (PCWs) + +*******************************************************************************/ + +#include "aacdec_hcr.h" + +#include "aacdec_hcr_types.h" +#include "aacdec_hcr_bit.h" +#include "aacdec_hcrs.h" +#include "aac_ram.h" +#include "aac_rom.h" +#include "channel.h" +#include "block.h" + +#include "aacdecoder.h" /* for ID_CPE, ID_SCE ... */ +#include "FDK_bitstream.h" + +extern int mlFileChCurr; + +static void errDetectorInHcrSideinfoShrt(SCHAR cb, SHORT numLine, + UINT *errorWord); + +static void errDetectorInHcrLengths(SCHAR lengthOfLongestCodeword, + SHORT lengthOfReorderedSpectralData, + UINT *errorWord); + +static void HcrCalcNumCodeword(H_HCR_INFO pHcr); +static void HcrSortCodebookAndNumCodewordInSection(H_HCR_INFO pHcr); +static void HcrPrepareSegmentationGrid(H_HCR_INFO pHcr); +static void HcrExtendedSectionInfo(H_HCR_INFO pHcr); + +static void DeriveNumberOfExtendedSortedSectionsInSets( + UINT numSegment, USHORT *pNumExtendedSortedCodewordInSection, + int numExtendedSortedCodewordInSectionIdx, + USHORT *pNumExtendedSortedSectionsInSets, + int numExtendedSortedSectionsInSetsIdx); + +static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + INT quantSpecCoef, INT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits, UINT *errorWord); + +static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + UINT codebookDim, const SCHAR *pQuantVal, + FIXP_DBL *pQuantSpecCoef, int *quantSpecCoefIdx, + INT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, int *pNumDecodedBits); + +static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + const UINT *pCurrentTree, + const SCHAR *pQuantValBase, + INT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits); + +static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr); + +static void HcrReorderQuantizedSpectralCoefficients( + H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo); + +static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment, + H_HCR_INFO pHcr, PCW_TYPE kind, + FIXP_DBL *qsc_base_of_cw, + UCHAR dimension); + +static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr); + +/*--------------------------------------------------------------------------------------------- + description: Check if codebook and numSect are within allowed range +(short only) +-------------------------------------------------------------------------------------------- +*/ +static void errDetectorInHcrSideinfoShrt(SCHAR cb, SHORT numLine, + UINT *errorWord) { + if (cb < ZERO_HCB || cb >= MAX_CB_CHECK || cb == BOOKSCL) { + *errorWord |= CB_OUT_OF_RANGE_SHORT_BLOCK; + } + if (numLine < 0 || numLine > 1024) { + *errorWord |= LINE_IN_SECT_OUT_OF_RANGE_SHORT_BLOCK; + } +} + +/*--------------------------------------------------------------------------------------------- + description: Check both HCR lengths +-------------------------------------------------------------------------------------------- +*/ +static void errDetectorInHcrLengths(SCHAR lengthOfLongestCodeword, + SHORT lengthOfReorderedSpectralData, + UINT *errorWord) { + if (lengthOfReorderedSpectralData < lengthOfLongestCodeword) { + *errorWord |= HCR_SI_LENGTHS_FAILURE; + } +} + +/*--------------------------------------------------------------------------------------------- + description: Decode (and adapt if necessary) the two HCR sideinfo +components: 'reordered_spectral_data_length' and 'longest_codeword_length' +-------------------------------------------------------------------------------------------- +*/ + +void CHcr_Read(HANDLE_FDK_BITSTREAM bs, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const MP4_ELEMENT_ID globalHcrType) { + SHORT lengOfReorderedSpectralData; + SCHAR lengOfLongestCodeword; + + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = + 0; + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = 0; + + /* ------- SI-Value No 1 ------- */ + lengOfReorderedSpectralData = FDKreadBits(bs, 14) + ERROR_LORSD; + if (globalHcrType == ID_CPE) { + if ((lengOfReorderedSpectralData >= 0) && + (lengOfReorderedSpectralData <= CPE_TOP_LENGTH)) { + pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData = + lengOfReorderedSpectralData; /* the decoded value is within range */ + } else { + if (lengOfReorderedSpectralData > CPE_TOP_LENGTH) { + pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData = + CPE_TOP_LENGTH; /* use valid maximum */ + } + } + } else if (globalHcrType == ID_SCE || globalHcrType == ID_LFE || + globalHcrType == ID_CCE) { + if ((lengOfReorderedSpectralData >= 0) && + (lengOfReorderedSpectralData <= SCE_TOP_LENGTH)) { + pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData = + lengOfReorderedSpectralData; /* the decoded value is within range */ + } else { + if (lengOfReorderedSpectralData > SCE_TOP_LENGTH) { + pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData = + SCE_TOP_LENGTH; /* use valid maximum */ + } + } + } + + /* ------- SI-Value No 2 ------- */ + lengOfLongestCodeword = FDKreadBits(bs, 6) + ERROR_LOLC; + if ((lengOfLongestCodeword >= 0) && + (lengOfLongestCodeword <= LEN_OF_LONGEST_CW_TOP_LENGTH)) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = + lengOfLongestCodeword; /* the decoded value is within range */ + } else { + if (lengOfLongestCodeword > LEN_OF_LONGEST_CW_TOP_LENGTH) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = + LEN_OF_LONGEST_CW_TOP_LENGTH; /* use valid maximum */ + } + } +} + +/*--------------------------------------------------------------------------------------------- + description: Set up HCR - must be called before every call to +HcrDecoder(). For short block a sorting algorithm is applied to get the SI in +the order that HCR could assemble the qsc's as if it is a long block. +----------------------------------------------------------------------------------------------- + return: error log +-------------------------------------------------------------------------------------------- +*/ + +UINT HcrInit(H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs) { + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + SHORT *pNumLinesInSec; + UCHAR *pCodeBk; + SHORT numSection; + SCHAR cb; + int numLine; + int i; + + pHcr->decInOut.lengthOfReorderedSpectralData = + pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData; + pHcr->decInOut.lengthOfLongestCodeword = + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword; + pHcr->decInOut.pQuantizedSpectralCoefficientsBase = + pAacDecoderChannelInfo->pSpectralCoefficient; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = 0; + pHcr->decInOut.pCodebook = + pAacDecoderChannelInfo->pDynData->specificTo.aac.aCodeBooks4Hcr; + pHcr->decInOut.pNumLineInSect = + pAacDecoderChannelInfo->pDynData->specificTo.aac.aNumLineInSec4Hcr; + pHcr->decInOut.numSection = + pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection; + pHcr->decInOut.errorLog = 0; + pHcr->nonPcwSideinfo.pResultBase = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + + FDKsyncCache(bs); + pHcr->decInOut.bitstreamAnchor = (INT)FDKgetValidBits(bs); + + if (!IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) /* short block */ + { + SHORT band; + SHORT maxBand; + SCHAR group; + SCHAR winGroupLen; + SCHAR window; + SCHAR numUnitInBand; + SCHAR cntUnitInBand; + SCHAR groupWin; + SCHAR cb_prev; + + UCHAR *pCodeBook; + const SHORT *BandOffsets; + SCHAR numOfGroups; + + pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; /* in */ + pNumLinesInSec = pHcr->decInOut.pNumLineInSect; /* out */ + pCodeBk = pHcr->decInOut.pCodebook; /* out */ + BandOffsets = + GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo); /* aux */ + numOfGroups = GetWindowGroups(pIcsInfo); + + numLine = 0; + numSection = 0; + cb = pCodeBook[0]; + cb_prev = pCodeBook[0]; + + /* convert HCR-sideinfo into a unitwise manner: When the cb changes, a new + * section starts */ + + *pCodeBk++ = cb_prev; + + maxBand = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + for (band = 0; band < maxBand; + band++) { /* from low to high sfbs i.e. from low to high frequencies */ + numUnitInBand = + ((BandOffsets[band + 1] - BandOffsets[band]) >> + FOUR_LOG_DIV_TWO_LOG); /* get the number of units in current sfb */ + for (cntUnitInBand = numUnitInBand; cntUnitInBand != 0; + cntUnitInBand--) { /* for every unit in the band */ + for (window = 0, group = 0; group < numOfGroups; group++) { + winGroupLen = (SCHAR)GetWindowGroupLength( + &pAacDecoderChannelInfo->icsInfo, group); + for (groupWin = winGroupLen; groupWin != 0; groupWin--, window++) { + cb = pCodeBook[group * 16 + band]; + if (cb != cb_prev) { + errDetectorInHcrSideinfoShrt(cb, numLine, + &pHcr->decInOut.errorLog); + if (pHcr->decInOut.errorLog != 0) { + return (pHcr->decInOut.errorLog); + } + *pCodeBk++ = cb; + *pNumLinesInSec++ = numLine; + numSection++; + + cb_prev = cb; + numLine = LINES_PER_UNIT; + } else { + numLine += LINES_PER_UNIT; + } + } + } + } + } + + numSection++; + + errDetectorInHcrSideinfoShrt(cb, numLine, &pHcr->decInOut.errorLog); + if (numSection <= 0 || numSection > 1024 / 2) { + pHcr->decInOut.errorLog |= NUM_SECT_OUT_OF_RANGE_SHORT_BLOCK; + } + errDetectorInHcrLengths(pHcr->decInOut.lengthOfLongestCodeword, + pHcr->decInOut.lengthOfReorderedSpectralData, + &pHcr->decInOut.errorLog); + if (pHcr->decInOut.errorLog != 0) { + return (pHcr->decInOut.errorLog); + } + + *pCodeBk = cb; + *pNumLinesInSec = numLine; + pHcr->decInOut.numSection = numSection; + + } else /* end short block prepare SI */ + { /* long block */ + errDetectorInHcrLengths(pHcr->decInOut.lengthOfLongestCodeword, + pHcr->decInOut.lengthOfReorderedSpectralData, + &pHcr->decInOut.errorLog); + numSection = pHcr->decInOut.numSection; + pNumLinesInSec = pHcr->decInOut.pNumLineInSect; + pCodeBk = pHcr->decInOut.pCodebook; + if (numSection <= 0 || numSection > 64) { + pHcr->decInOut.errorLog |= NUM_SECT_OUT_OF_RANGE_LONG_BLOCK; + numSection = 0; + } + + for (i = numSection; i != 0; i--) { + cb = *pCodeBk++; + + if (cb < ZERO_HCB || cb >= MAX_CB_CHECK || cb == BOOKSCL) { + pHcr->decInOut.errorLog |= CB_OUT_OF_RANGE_LONG_BLOCK; + } + + numLine = *pNumLinesInSec++; + /* FDK_ASSERT(numLine > 0); */ + + if ((numLine <= 0) || (numLine > 1024)) { + pHcr->decInOut.errorLog |= LINE_IN_SECT_OUT_OF_RANGE_LONG_BLOCK; + } + } + if (pHcr->decInOut.errorLog != 0) { + return (pHcr->decInOut.errorLog); + } + } + + pCodeBk = pHcr->decInOut.pCodebook; + for (i = 0; i < numSection; i++) { + if ((*pCodeBk == NOISE_HCB) || (*pCodeBk == INTENSITY_HCB2) || + (*pCodeBk == INTENSITY_HCB)) { + *pCodeBk = 0; + } + pCodeBk++; + } + + /* HCR-sideinfo-input is complete and seems to be valid */ + + return (pHcr->decInOut.errorLog); +} + +/*--------------------------------------------------------------------------------------------- + description: This function decodes the codewords of the spectral +coefficients from the bitstream according to the HCR algorithm and stores the +quantized spectral coefficients in correct order in the output buffer. +-------------------------------------------------------------------------------------------- +*/ + +UINT HcrDecoder(H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs) { + int pTmp1, pTmp2, pTmp3, pTmp4; + int pTmp5; + + INT bitCntOffst; + INT saveBitCnt = (INT)FDKgetValidBits(bs); /* save bitstream position */ + + HcrCalcNumCodeword(pHcr); + + HcrSortCodebookAndNumCodewordInSection(pHcr); + + HcrPrepareSegmentationGrid(pHcr); + + HcrExtendedSectionInfo(pHcr); + + if ((pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK) != 0) { + return (pHcr->decInOut.errorLog); /* sideinfo is massively corrupt, return + from HCR without having decoded + anything */ + } + + DeriveNumberOfExtendedSortedSectionsInSets( + pHcr->segmentInfo.numSegment, + pHcr->sectionInfo.pNumExtendedSortedCodewordInSection, + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx, + pHcr->sectionInfo.pNumExtendedSortedSectionsInSets, + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx); + + /* store */ + pTmp1 = pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx; + pTmp2 = pHcr->sectionInfo.extendedSortedCodebookIdx; + pTmp3 = pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx; + pTmp4 = pHcr->decInOut.quantizedSpectralCoefficientsIdx; + pTmp5 = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx; + + /* ------- decode meaningful PCWs ------ */ + DecodePCWs(bs, pHcr); + + if ((pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK) == 0) { + /* ------ decode the non-PCWs -------- */ + DecodeNonPCWs(bs, pHcr); + } + + errDetectWithinSegmentationFinal(pHcr); + + /* restore */ + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = pTmp1; + pHcr->sectionInfo.extendedSortedCodebookIdx = pTmp2; + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = pTmp3; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = pTmp4; + pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = pTmp5; + + HcrReorderQuantizedSpectralCoefficients(pHcr, pAacDecoderChannelInfo, + pSamplingRateInfo); + + /* restore bitstream position */ + bitCntOffst = (INT)FDKgetValidBits(bs) - saveBitCnt; + if (bitCntOffst) { + FDKpushBiDirectional(bs, bitCntOffst); + } + + return (pHcr->decInOut.errorLog); +} + +/*--------------------------------------------------------------------------------------------- + description: This function reorders the quantized spectral coefficients +sectionwise for long- and short-blocks and compares to the LAV (Largest Absolute +Value of the current codebook) -- a counter is incremented if there is an error + detected. + Additional for short-blocks a unit-based-deinterleaving is +applied. Moreover (for short blocks) the scaling is derived (compare plain +huffman decoder). +-------------------------------------------------------------------------------------------- +*/ + +static void HcrReorderQuantizedSpectralCoefficients( + H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo) { + INT qsc; + UINT abs_qsc; + UINT i, j; + USHORT numSpectralValuesInSection; + FIXP_DBL *pTeVa; + USHORT lavErrorCnt = 0; + + UINT numSection = pHcr->decInOut.numSection; + SPECTRAL_PTR pQuantizedSpectralCoefficientsBase = + pHcr->decInOut.pQuantizedSpectralCoefficientsBase; + FIXP_DBL *pQuantizedSpectralCoefficients = + SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase); + const UCHAR *pCbDimShift = aDimCbShift; + const USHORT *pLargestAbsVal = aLargestAbsoluteValue; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumSortedCodewordInSection = + pHcr->sectionInfo.pNumSortedCodewordInSection; + USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset; + FIXP_DBL pTempValues[1024]; + FIXP_DBL *pBak = pTempValues; + + FDKmemclear(pTempValues, 1024 * sizeof(FIXP_DBL)); + + /* long and short: check if decoded huffman-values (quantized spectral + * coefficients) are within range */ + for (i = numSection; i != 0; i--) { + numSpectralValuesInSection = *pNumSortedCodewordInSection++ + << pCbDimShift[*pSortedCodebook]; + pTeVa = &pTempValues[*pReorderOffset++]; + for (j = numSpectralValuesInSection; j != 0; j--) { + qsc = *pQuantizedSpectralCoefficients++; + abs_qsc = fAbs(qsc); + if (abs_qsc <= pLargestAbsVal[*pSortedCodebook]) { + *pTeVa++ = (FIXP_DBL)qsc; /* the qsc value is within range */ + } else { /* line is too high .. */ + if (abs_qsc == + Q_VALUE_INVALID) { /* .. because of previous marking --> dont set + LAV flag (would be confusing), just copy out + the already marked value */ + *pTeVa++ = (FIXP_DBL)qsc; + } else { /* .. because a too high value was decoded for this cb --> set + LAV flag */ + *pTeVa++ = (FIXP_DBL)Q_VALUE_INVALID; + lavErrorCnt += 1; + } + } + } + pSortedCodebook++; + } + + if (!IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) { + FIXP_DBL *pOut; + FIXP_DBL locMax; + FIXP_DBL tmp; + SCHAR groupoffset; + SCHAR group; + SCHAR band; + SCHAR groupwin; + SCHAR window; + SCHAR numWinGroup; + SHORT interm; + SCHAR numSfbTransm; + SCHAR winGroupLen; + SHORT index; + INT msb; + INT lsb; + + SHORT *pScaleFacHcr = pAacDecoderChannelInfo->pDynData->aScaleFactor; + SHORT *pSfbSclHcr = pAacDecoderChannelInfo->pDynData->aSfbScale; + const SHORT *BandOffsets = GetScaleFactorBandOffsets( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + + pBak = pTempValues; + /* deinterleave unitwise for short blocks */ + for (window = 0; window < (8); window++) { + pOut = SPEC(pQuantizedSpectralCoefficientsBase, window, + pAacDecoderChannelInfo->granuleLength); + for (i = 0; i < (LINES_PER_UNIT_GROUP); i++) { + pTeVa = pBak + (window << FOUR_LOG_DIV_TWO_LOG) + + i * 32; /* distance of lines between unit groups has to be + constant for every framelength (32)! */ + for (j = (LINES_PER_UNIT); j != 0; j--) { + *pOut++ = *pTeVa++; + } + } + } + + /* short blocks only */ + /* derive global scaling-value for every sfb and every window (as it is done + * in plain-huffman-decoder at short blocks) */ + groupoffset = 0; + + numWinGroup = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + numSfbTransm = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + + for (group = 0; group < numWinGroup; group++) { + winGroupLen = + GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo, group); + for (band = 0; band < numSfbTransm; band++) { + interm = group * 16 + band; + msb = pScaleFacHcr[interm] >> 2; + lsb = pScaleFacHcr[interm] & 3; + for (groupwin = 0; groupwin < winGroupLen; groupwin++) { + window = groupoffset + groupwin; + pBak = SPEC(pQuantizedSpectralCoefficientsBase, window, + pAacDecoderChannelInfo->granuleLength); + locMax = FL2FXCONST_DBL(0.0f); + for (index = BandOffsets[band]; index < BandOffsets[band + 1]; + index += LINES_PER_UNIT) { + pTeVa = &pBak[index]; + for (i = LINES_PER_UNIT; i != 0; i--) { + tmp = (*pTeVa < FL2FXCONST_DBL(0.0f)) ? -*pTeVa++ : *pTeVa++; + locMax = fixMax(tmp, locMax); + } + } + if (fixp_abs(locMax) > (FIXP_DBL)MAX_QUANTIZED_VALUE) { + locMax = (FIXP_DBL)MAX_QUANTIZED_VALUE; + } + pSfbSclHcr[window * 16 + band] = + msb - GetScaleFromValue( + locMax, lsb); /* save global scale maxima in this sfb */ + } + } + groupoffset += + GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo, group); + } + } else { + /* copy straight for long-blocks */ + pQuantizedSpectralCoefficients = + SPEC_LONG(pQuantizedSpectralCoefficientsBase); + for (i = 1024; i != 0; i--) { + *pQuantizedSpectralCoefficients++ = *pBak++; + } + } + + if (lavErrorCnt != 0) { + pHcr->decInOut.errorLog |= LAV_VIOLATION; + } +} + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the number of codewords + for each section (numCodewordInSection) and the number of +codewords for all sections (numCodeword). For zero and intensity codebooks a +entry is also done in the variable numCodewordInSection. It is assumed that the +codebook is a two tuples codebook. This is needed later for the calculation of +the base addresses for the reordering of the quantize spectral coefficients at +the end of the hcr tool. The variable numCodeword contain the number of +codewords which are really in the bitstream. Zero or intensity codebooks does +not increase the variable numCodewords. +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void HcrCalcNumCodeword(H_HCR_INFO pHcr) { + int hcrSection; + UINT numCodeword; + + UINT numSection = pHcr->decInOut.numSection; + UCHAR *pCodebook = pHcr->decInOut.pCodebook; + SHORT *pNumLineInSection = pHcr->decInOut.pNumLineInSect; + const UCHAR *pCbDimShift = aDimCbShift; + + USHORT *pNumCodewordInSection = pHcr->sectionInfo.pNumCodewordInSection; + + numCodeword = 0; + for (hcrSection = numSection; hcrSection != 0; hcrSection--) { + *pNumCodewordInSection = *pNumLineInSection++ >> pCbDimShift[*pCodebook]; + if (*pCodebook != 0) { + numCodeword += *pNumCodewordInSection; + } + pNumCodewordInSection++; + pCodebook++; + } + pHcr->sectionInfo.numCodeword = numCodeword; +} + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the number + of sorted codebooks and sorts the codebooks and the +numCodewordInSection according to the priority. +-------------------------------------------------------------------------------------------- +*/ + +static void HcrSortCodebookAndNumCodewordInSection(H_HCR_INFO pHcr) { + UINT i, j, k; + UCHAR temp; + UINT counter; + UINT startOffset; + UINT numZeroSection; + UCHAR *pDest; + UINT numSectionDec; + + UINT numSection = pHcr->decInOut.numSection; + UCHAR *pCodebook = pHcr->decInOut.pCodebook; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumCodewordInSection = pHcr->sectionInfo.pNumCodewordInSection; + USHORT *pNumSortedCodewordInSection = + pHcr->sectionInfo.pNumSortedCodewordInSection; + UCHAR *pCodebookSwitch = pHcr->sectionInfo.pCodebookSwitch; + USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset; + const UCHAR *pCbPriority = aCbPriority; + const UCHAR *pMinOfCbPair = aMinOfCbPair; + const UCHAR *pMaxOfCbPair = aMaxOfCbPair; + const UCHAR *pCbDimShift = aDimCbShift; + + UINT searchStart = 0; + + /* calculate *pNumSortedSection and store the priorities in array + * pSortedCdebook */ + pDest = pSortedCodebook; + numZeroSection = 0; + for (i = numSection; i != 0; i--) { + if (pCbPriority[*pCodebook] == 0) { + numZeroSection += 1; + } + *pDest++ = pCbPriority[*pCodebook++]; + } + pHcr->sectionInfo.numSortedSection = + numSection - numZeroSection; /* numSortedSection contains no zero or + intensity section */ + pCodebook = pHcr->decInOut.pCodebook; + + /* sort priorities of the codebooks in array pSortedCdebook[] */ + numSectionDec = numSection - 1; + if (numSectionDec > 0) { + counter = numSectionDec; + for (j = numSectionDec; j != 0; j--) { + for (i = 0; i < counter; i++) { + /* swap priorities */ + if (pSortedCodebook[i + 1] > pSortedCodebook[i]) { + temp = pSortedCodebook[i]; + pSortedCodebook[i] = pSortedCodebook[i + 1]; + pSortedCodebook[i + 1] = temp; + } + } + counter -= 1; + } + } + + /* clear codebookSwitch array */ + for (i = numSection; i != 0; i--) { + *pCodebookSwitch++ = 0; + } + pCodebookSwitch = pHcr->sectionInfo.pCodebookSwitch; + + /* sort sectionCodebooks and numCodwordsInSection and calculate + * pReorderOffst[j] */ + for (j = 0; j < numSection; j++) { + for (i = searchStart; i < numSection; i++) { + if (pCodebookSwitch[i] == 0 && + (pMinOfCbPair[pSortedCodebook[j]] == pCodebook[i] || + pMaxOfCbPair[pSortedCodebook[j]] == pCodebook[i])) { + pCodebookSwitch[i] = 1; + pSortedCodebook[j] = pCodebook[i]; /* sort codebook */ + pNumSortedCodewordInSection[j] = + pNumCodewordInSection[i]; /* sort NumCodewordInSection */ + + startOffset = 0; + for (k = 0; k < i; k++) { /* make entry in pReorderOffst */ + startOffset += pNumCodewordInSection[k] << pCbDimShift[pCodebook[k]]; + } + pReorderOffset[j] = + startOffset; /* offset for reordering the codewords */ + + if (i == searchStart) { + k = i; + while (pCodebookSwitch[k++] == 1) searchStart++; + } + break; + } + } + } +} + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the segmentation, which includes +numSegment, leftStartOfSegment, rightStartOfSegment and remainingBitsInSegment. + The segmentation could be visualized a as kind of +'overlay-grid' for the bitstream-block holding the HCR-encoded +quantized-spectral-coefficients. +-------------------------------------------------------------------------------------------- +*/ + +static void HcrPrepareSegmentationGrid(H_HCR_INFO pHcr) { + USHORT i, j; + USHORT numSegment = 0; + INT segmentStart = 0; + UCHAR segmentWidth; + UCHAR lastSegmentWidth; + UCHAR sortedCodebook; + UCHAR endFlag = 0; + INT intermediateResult; + + SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword; + SHORT lengthOfReorderedSpectralData = + pHcr->decInOut.lengthOfReorderedSpectralData; + UINT numSortedSection = pHcr->sectionInfo.numSortedSection; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumSortedCodewordInSection = + pHcr->sectionInfo.pNumSortedCodewordInSection; + INT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + INT *pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + const UCHAR *pMaxCwLength = aMaxCwLen; + + for (i = numSortedSection; i != 0; i--) { + sortedCodebook = *pSortedCodebook++; + segmentWidth = + fMin((INT)pMaxCwLength[sortedCodebook], (INT)lengthOfLongestCodeword); + + for (j = *pNumSortedCodewordInSection; j != 0; j--) { + /* width allows a new segment */ + intermediateResult = segmentStart; + if ((segmentStart + segmentWidth) <= lengthOfReorderedSpectralData) { + /* store segment start, segment length and increment the number of + * segments */ + *pLeftStartOfSegment++ = intermediateResult; + *pRightStartOfSegment++ = intermediateResult + segmentWidth - 1; + *pRemainingBitsInSegment++ = segmentWidth; + segmentStart += segmentWidth; + numSegment += 1; + } + /* width does not allow a new segment */ + else { + /* correct the last segment length */ + pLeftStartOfSegment--; + pRightStartOfSegment--; + pRemainingBitsInSegment--; + segmentStart = *pLeftStartOfSegment; + + lastSegmentWidth = lengthOfReorderedSpectralData - segmentStart; + *pRemainingBitsInSegment = lastSegmentWidth; + *pRightStartOfSegment = segmentStart + lastSegmentWidth - 1; + endFlag = 1; + break; + } + } + pNumSortedCodewordInSection++; + if (endFlag != 0) { + break; + } + } + pHcr->segmentInfo.numSegment = numSegment; +} + +/*--------------------------------------------------------------------------------------------- + description: This function adapts the sorted section boundaries to the +boundaries of segmentation. If the section lengths does not fit completely into +the current segment, the section is spitted into two so called 'extended + sections'. The extended-section-info +(pNumExtendedSortedCodewordInSectin and pExtendedSortedCodebook) is updated in +this case. + +-------------------------------------------------------------------------------------------- +*/ + +static void HcrExtendedSectionInfo(H_HCR_INFO pHcr) { + UINT srtSecCnt = 0; /* counter for sorted sections */ + UINT xSrtScCnt = 0; /* counter for extended sorted sections */ + UINT remainNumCwInSortSec; + UINT inSegmentRemainNumCW; + + UINT numSortedSection = pHcr->sectionInfo.numSortedSection; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumSortedCodewordInSection = + pHcr->sectionInfo.pNumSortedCodewordInSection; + UCHAR *pExtendedSortedCoBo = pHcr->sectionInfo.pExtendedSortedCodebook; + USHORT *pNumExtSortCwInSect = + pHcr->sectionInfo.pNumExtendedSortedCodewordInSection; + UINT numSegment = pHcr->segmentInfo.numSegment; + UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec; + SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword; + const UCHAR *pMaxCwLength = aMaxCwLen; + + remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt]; + inSegmentRemainNumCW = numSegment; + + while (srtSecCnt < numSortedSection) { + if (inSegmentRemainNumCW < remainNumCwInSortSec) { + pNumExtSortCwInSect[xSrtScCnt] = inSegmentRemainNumCW; + pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt]; + + remainNumCwInSortSec -= inSegmentRemainNumCW; + inSegmentRemainNumCW = numSegment; + /* data of a sorted section was not integrated in extended sorted section + */ + } else if (inSegmentRemainNumCW == remainNumCwInSortSec) { + pNumExtSortCwInSect[xSrtScCnt] = inSegmentRemainNumCW; + pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt]; + + srtSecCnt++; + remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt]; + inSegmentRemainNumCW = numSegment; + /* data of a sorted section was integrated in extended sorted section */ + } else { /* inSegmentRemainNumCW > remainNumCwInSortSec */ + pNumExtSortCwInSect[xSrtScCnt] = remainNumCwInSortSec; + pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt]; + + inSegmentRemainNumCW -= remainNumCwInSortSec; + srtSecCnt++; + remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt]; + /* data of a sorted section was integrated in extended sorted section */ + } + pMaxLenOfCbInExtSrtSec[xSrtScCnt] = + fMin((INT)pMaxCwLength[pExtendedSortedCoBo[xSrtScCnt]], + (INT)lengthOfLongestCodeword); + + xSrtScCnt += 1; + + if (xSrtScCnt >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + pHcr->decInOut.errorLog |= EXTENDED_SORTED_COUNTER_OVERFLOW; + return; + } + } + pNumExtSortCwInSect[xSrtScCnt] = 0; +} + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the number of extended sorted +sections which belong to the sets. Each set from set 0 (one and only set for the +PCWs) till to the last set gets a entry in the array to which + 'pNumExtendedSortedSectinsInSets' points to. + + Calculation: The entrys in +pNumExtendedSortedCodewordInSectin are added untill the value numSegment is +reached. Then the sum_variable is cleared and the calculation starts from the +beginning. As much extended sorted Sections are summed up to reach the value +numSegment, as much is the current entry in *pNumExtendedSortedCodewordInSectin. +-------------------------------------------------------------------------------------------- +*/ +static void DeriveNumberOfExtendedSortedSectionsInSets( + UINT numSegment, USHORT *pNumExtendedSortedCodewordInSection, + int numExtendedSortedCodewordInSectionIdx, + USHORT *pNumExtendedSortedSectionsInSets, + int numExtendedSortedSectionsInSetsIdx) { + USHORT counter = 0; + UINT cwSum = 0; + USHORT *pNumExSortCwInSec = pNumExtendedSortedCodewordInSection; + USHORT *pNumExSortSecInSets = pNumExtendedSortedSectionsInSets; + + while (pNumExSortCwInSec[numExtendedSortedCodewordInSectionIdx] != 0) { + cwSum += pNumExSortCwInSec[numExtendedSortedCodewordInSectionIdx]; + numExtendedSortedCodewordInSectionIdx++; + if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + return; + } + if (cwSum > numSegment) { + return; + } + counter++; + if (counter > 1024 / 4) { + return; + } + if (cwSum == numSegment) { + pNumExSortSecInSets[numExtendedSortedSectionsInSetsIdx] = counter; + numExtendedSortedSectionsInSetsIdx++; + if (numExtendedSortedSectionsInSetsIdx >= MAX_HCR_SETS) { + return; + } + counter = 0; + cwSum = 0; + } + } + pNumExSortSecInSets[numExtendedSortedSectionsInSetsIdx] = + counter; /* save last entry for the last - probably shorter - set */ +} + +/*--------------------------------------------------------------------------------------------- + description: This function decodes all priority codewords (PCWs) in a +spectrum (within set 0). The calculation of the PCWs is managed in two loops. +The loopcounter of the outer loop is set to the first value pointer + pNumExtendedSortedSectionsInSets points to. This value +represents the number of extended sorted sections within set 0. The loopcounter +of the inner loop is set to the first value pointer + pNumExtendedSortedCodewordInSectin points to. The value +represents the number of extended sorted codewords in sections (the original +sections have been splitted to go along with the borders of the sets). Each time +the number of the extended sorted codewords in sections are de- coded, the +pointer 'pNumExtendedSortedCodewordInSectin' is incremented by one. +-------------------------------------------------------------------------------------------- +*/ +static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) { + UINT i; + USHORT extSortSec; + USHORT curExtSortCwInSec; + UCHAR codebook; + UCHAR dimension; + const UINT *pCurrentTree; + const SCHAR *pQuantValBase; + const SCHAR *pQuantVal; + + USHORT *pNumExtendedSortedCodewordInSection = + pHcr->sectionInfo.pNumExtendedSortedCodewordInSection; + int numExtendedSortedCodewordInSectionIdx = + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx; + UCHAR *pExtendedSortedCodebook = pHcr->sectionInfo.pExtendedSortedCodebook; + int extendedSortedCodebookIdx = pHcr->sectionInfo.extendedSortedCodebookIdx; + USHORT *pNumExtendedSortedSectionsInSets = + pHcr->sectionInfo.pNumExtendedSortedSectionsInSets; + int numExtendedSortedSectionsInSetsIdx = + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx; + FIXP_DBL *pQuantizedSpectralCoefficients = + SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase); + int quantizedSpectralCoefficientsIdx = + pHcr->decInOut.quantizedSpectralCoefficientsIdx; + INT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec; + int maxLenOfCbInExtSrtSecIdx = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx; + UCHAR maxAllowedCwLen; + int numDecodedBits; + const UCHAR *pCbDimension = aDimCb; + const UCHAR *pCbSign = aSignCb; + + /* clear result array */ + FDKmemclear(pQuantizedSpectralCoefficients + quantizedSpectralCoefficientsIdx, + 1024 * sizeof(FIXP_DBL)); + + /* decode all PCWs in the extended sorted section(s) belonging to set 0 */ + for (extSortSec = + pNumExtendedSortedSectionsInSets[numExtendedSortedSectionsInSetsIdx]; + extSortSec != 0; extSortSec--) { + codebook = + pExtendedSortedCodebook[extendedSortedCodebookIdx]; /* get codebook for + this extended + sorted section + and increment ptr + to cb of next + ext. sort sec */ + extendedSortedCodebookIdx++; + if (extendedSortedCodebookIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + return; + } + dimension = pCbDimension[codebook]; /* get dimension of codebook of this + extended sort. sec. */ + pCurrentTree = + aHuffTable[codebook]; /* convert codebook to pointer to QSCs */ + pQuantValBase = + aQuantTable[codebook]; /* convert codebook to index to table of QSCs */ + maxAllowedCwLen = pMaxLenOfCbInExtSrtSec[maxLenOfCbInExtSrtSecIdx]; + maxLenOfCbInExtSrtSecIdx++; + if (maxLenOfCbInExtSrtSecIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + return; + } + + /* switch for decoding with different codebooks: */ + if (pCbSign[codebook] == + 0) { /* no sign bits follow after the codeword-body */ + /* PCW_BodyONLY */ + /*==============*/ + + for (curExtSortCwInSec = pNumExtendedSortedCodewordInSection + [numExtendedSortedCodewordInSectionIdx]; + curExtSortCwInSec != 0; curExtSortCwInSec--) { + numDecodedBits = 0; + + /* decode PCW_BODY */ + pQuantVal = DecodePCW_Body( + bs, pHcr->decInOut.bitstreamAnchor, pCurrentTree, pQuantValBase, + pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits); + + /* result is written out here because NO sign bits follow the body */ + for (i = dimension; i != 0; i--) { + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = + (FIXP_DBL)*pQuantVal++; /* write quant. spec. coef. into + spectrum; sign is already valid */ + quantizedSpectralCoefficientsIdx++; + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + } + + /* one more PCW should be decoded */ + + if (maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_ONLY_TOO_LONG)) { + pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_BITS_DECODED; + } + + if (1 == errDetectPcwSegmentation( + *pRemainingBitsInSegment - ERROR_PCW_BODY, pHcr, PCW_BODY, + pQuantizedSpectralCoefficients + + quantizedSpectralCoefficientsIdx - dimension, + dimension)) { + return; + } + pLeftStartOfSegment++; /* update pointer for decoding the next PCW */ + pRemainingBitsInSegment++; /* update pointer for decoding the next PCW + */ + } + } else if ((codebook < 11) && (pCbSign[codebook] == + 1)) { /* possibly there follow 1,2,3 or 4 + sign bits after the codeword-body */ + /* PCW_Body and PCW_Sign */ + /*=======================*/ + + for (curExtSortCwInSec = pNumExtendedSortedCodewordInSection + [numExtendedSortedCodewordInSectionIdx]; + curExtSortCwInSec != 0; curExtSortCwInSec--) { + int err; + numDecodedBits = 0; + + pQuantVal = DecodePCW_Body( + bs, pHcr->decInOut.bitstreamAnchor, pCurrentTree, pQuantValBase, + pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits); + + err = DecodePCW_Sign( + bs, pHcr->decInOut.bitstreamAnchor, dimension, pQuantVal, + pQuantizedSpectralCoefficients, &quantizedSpectralCoefficientsIdx, + pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits); + if (err != 0) { + return; + } + /* one more PCW should be decoded */ + + if (maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_SIGN_TOO_LONG)) { + pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_BITS_DECODED; + } + + if (1 == errDetectPcwSegmentation( + *pRemainingBitsInSegment - ERROR_PCW_BODY_SIGN, pHcr, + PCW_BODY_SIGN, + pQuantizedSpectralCoefficients + + quantizedSpectralCoefficientsIdx - dimension, + dimension)) { + return; + } + pLeftStartOfSegment++; + pRemainingBitsInSegment++; + } + } else if ((pCbSign[codebook] == 1) && + (codebook >= 11)) { /* possibly there follow some sign bits and + maybe one or two escape sequences after + the cw-body */ + /* PCW_Body, PCW_Sign and maybe PCW_Escape */ + /*=========================================*/ + + for (curExtSortCwInSec = pNumExtendedSortedCodewordInSection + [numExtendedSortedCodewordInSectionIdx]; + curExtSortCwInSec != 0; curExtSortCwInSec--) { + int err; + numDecodedBits = 0; + + /* decode PCW_BODY */ + pQuantVal = DecodePCW_Body( + bs, pHcr->decInOut.bitstreamAnchor, pCurrentTree, pQuantValBase, + pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits); + + err = DecodePCW_Sign( + bs, pHcr->decInOut.bitstreamAnchor, dimension, pQuantVal, + pQuantizedSpectralCoefficients, &quantizedSpectralCoefficientsIdx, + pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits); + if (err != 0) { + return; + } + + /* decode PCW_ESCAPE if present */ + quantizedSpectralCoefficientsIdx -= DIMENSION_OF_ESCAPE_CODEBOOK; + + if (fixp_abs(pQuantizedSpectralCoefficients + [quantizedSpectralCoefficientsIdx]) == + (FIXP_DBL)ESCAPE_VALUE) { + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = + (FIXP_DBL)DecodeEscapeSequence( + bs, pHcr->decInOut.bitstreamAnchor, + pQuantizedSpectralCoefficients + [quantizedSpectralCoefficientsIdx], + pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits, + &pHcr->decInOut.errorLog); + } + quantizedSpectralCoefficientsIdx++; + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + + if (fixp_abs(pQuantizedSpectralCoefficients + [quantizedSpectralCoefficientsIdx]) == + (FIXP_DBL)ESCAPE_VALUE) { + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = + (FIXP_DBL)DecodeEscapeSequence( + bs, pHcr->decInOut.bitstreamAnchor, + pQuantizedSpectralCoefficients + [quantizedSpectralCoefficientsIdx], + pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits, + &pHcr->decInOut.errorLog); + } + quantizedSpectralCoefficientsIdx++; + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + + /* one more PCW should be decoded */ + + if (maxAllowedCwLen < + (numDecodedBits + ERROR_PCW_BODY_SIGN_ESC_TOO_LONG)) { + pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED; + } + + if (1 == errDetectPcwSegmentation( + *pRemainingBitsInSegment - ERROR_PCW_BODY_SIGN_ESC, pHcr, + PCW_BODY_SIGN_ESC, + pQuantizedSpectralCoefficients + + quantizedSpectralCoefficientsIdx - + DIMENSION_OF_ESCAPE_CODEBOOK, + DIMENSION_OF_ESCAPE_CODEBOOK)) { + return; + } + pLeftStartOfSegment++; + pRemainingBitsInSegment++; + } + } + + /* all PCWs belonging to this extended section should be decoded */ + numExtendedSortedCodewordInSectionIdx++; + if (numExtendedSortedCodewordInSectionIdx >= MAX_SFB_HCR + MAX_HCR_SETS) { + return; + } + } + /* all PCWs should be decoded */ + + numExtendedSortedSectionsInSetsIdx++; + if (numExtendedSortedSectionsInSetsIdx >= MAX_HCR_SETS) { + return; + } + + /* Write back indexes into structure */ + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = + numExtendedSortedCodewordInSectionIdx; + pHcr->sectionInfo.extendedSortedCodebookIdx = extendedSortedCodebookIdx; + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = + numExtendedSortedSectionsInSetsIdx; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = + quantizedSpectralCoefficientsIdx; + pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = maxLenOfCbInExtSrtSecIdx; +} + +/*--------------------------------------------------------------------------------------------- + description: This function checks immediately after every decoded PCW, +whether out of the current segment too many bits have been read or not. If an +error occurrs, probably the sideinfo or the HCR-bitstream block holding the +huffman encoded quantized spectral coefficients is distorted. In this case the +two or four quantized spectral coefficients belonging to the current codeword + are marked (for being detected by concealment later). +-------------------------------------------------------------------------------------------- +*/ +static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment, + H_HCR_INFO pHcr, PCW_TYPE kind, + FIXP_DBL *qsc_base_of_cw, + UCHAR dimension) { + SCHAR i; + if (remainingBitsInSegment < 0) { + /* log the error */ + switch (kind) { + case PCW_BODY: + pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY; + break; + case PCW_BODY_SIGN: + pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN; + break; + case PCW_BODY_SIGN_ESC: + pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN_ESC; + break; + } + /* mark the erred lines */ + for (i = dimension; i != 0; i--) { + *qsc_base_of_cw++ = (FIXP_DBL)Q_VALUE_INVALID; + } + return 1; + } + return 0; +} + +/*--------------------------------------------------------------------------------------------- + description: This function checks if all segments are empty after +decoding. There are _no lines markded_ as invalid because it could not be traced +back where from the remaining bits are. +-------------------------------------------------------------------------------------------- +*/ +static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr) { + UCHAR segmentationErrorFlag = 0; + USHORT i; + SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + UINT numSegment = pHcr->segmentInfo.numSegment; + + for (i = numSegment; i != 0; i--) { + if (*pRemainingBitsInSegment++ != 0) { + segmentationErrorFlag = 1; + } + } + if (segmentationErrorFlag == 1) { + pHcr->decInOut.errorLog |= BIT_IN_SEGMENTATION_ERROR; + } +} + +/*--------------------------------------------------------------------------------------------- + description: This function walks one step within the decoding tree. Which +branch is taken depends on the decoded carryBit input parameter. +-------------------------------------------------------------------------------------------- +*/ +void CarryBitToBranchValue(UCHAR carryBit, UINT treeNode, UINT *branchValue, + UINT *branchNode) { + if (carryBit == 0) { + *branchNode = + (treeNode & MASK_LEFT) >> LEFT_OFFSET; /* MASK_LEFT: 00FFF000 */ + } else { + *branchNode = treeNode & MASK_RIGHT; /* MASK_RIGHT: 00000FFF */ + } + + *branchValue = *branchNode & CLR_BIT_10; /* clear bit 10 (if set) */ +} + +/*--------------------------------------------------------------------------------------------- + description: Decodes the body of a priority codeword (PCW) +----------------------------------------------------------------------------------------------- + return: - return value is pointer to first of two or four quantized +spectral coefficients +-------------------------------------------------------------------------------------------- +*/ +static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + const UINT *pCurrentTree, + const SCHAR *pQuantValBase, + INT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits) { + UCHAR carryBit; + UINT branchNode; + UINT treeNode; + UINT branchValue; + const SCHAR *pQuantVal; + + /* decode PCW_BODY */ + treeNode = *pCurrentTree; /* get first node of current tree belonging to + current codebook */ + + /* decode whole PCW-codeword-body */ + while (1) { + carryBit = HcrGetABitFromBitstream(bs, bsAnchor, pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + + CarryBitToBranchValue(carryBit, treeNode, &branchValue, &branchNode); + + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set --> codeword-body is complete */ + break; /* end of branch in tree reached i.e. a whole PCW-Body is decoded + */ + } else { + treeNode = *( + pCurrentTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + + pQuantVal = + pQuantValBase + branchValue; /* update pointer to valid first of 2 or 4 + quantized values */ + + return pQuantVal; +} + +/*--------------------------------------------------------------------------------------------- + description: This function decodes one escape sequence. In case of a +escape codebook and in case of the absolute value of the quantized spectral +value == 16, a escapeSequence is decoded in two steps: + 1. escape prefix + 2. escape word +-------------------------------------------------------------------------------------------- +*/ + +static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + INT quantSpecCoef, INT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits, UINT *errorWord) { + UINT i; + INT sign; + UINT escapeOnesCounter = 0; + UINT carryBit; + INT escape_word = 0; + + /* decode escape prefix */ + while (1) { + carryBit = HcrGetABitFromBitstream(bs, bsAnchor, pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + if (*pRemainingBitsInSegment < 0) { + return Q_VALUE_INVALID; + } + + if (carryBit != 0) { + escapeOnesCounter += 1; + } else { + escapeOnesCounter += 4; + break; + } + } + + /* decode escape word */ + for (i = escapeOnesCounter; i != 0; i--) { + carryBit = HcrGetABitFromBitstream(bs, bsAnchor, pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + if (*pRemainingBitsInSegment < 0) { + return Q_VALUE_INVALID; + } + + escape_word <<= 1; + escape_word = escape_word | carryBit; + } + + sign = (quantSpecCoef >= 0) ? 1 : -1; + + if (escapeOnesCounter < 13) { + quantSpecCoef = sign * (((INT)1 << escapeOnesCounter) + escape_word); + } else { + *errorWord |= TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED; + quantSpecCoef = Q_VALUE_INVALID; + } + return quantSpecCoef; +} + +/*--------------------------------------------------------------------------------------------- + description: Decodes the Signbits of a priority codeword (PCW) and writes +out the resulting quantized spectral values into unsorted sections +----------------------------------------------------------------------------------------------- + output: - two or four lines at position in corresponding section +(which are not located at the desired position, i.e. they must be reordered in +the last of eight function of HCR) +----------------------------------------------------------------------------------------------- + return: - updated pQuantSpecCoef pointer (to next empty storage for a +line) +-------------------------------------------------------------------------------------------- +*/ +static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + UINT codebookDim, const SCHAR *pQuantVal, + FIXP_DBL *pQuantSpecCoef, int *quantSpecCoefIdx, + INT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits) { + UINT i; + UINT carryBit; + INT quantSpecCoef; + + for (i = codebookDim; i != 0; i--) { + quantSpecCoef = *pQuantVal++; + if (quantSpecCoef != 0) { + carryBit = HcrGetABitFromBitstream(bs, bsAnchor, pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + if (*pRemainingBitsInSegment < 0 || *pNumDecodedBits >= (1024 >> 1)) { + return -1; + } + + /* adapt sign of values according to the decoded sign bit */ + if (carryBit != 0) { + pQuantSpecCoef[*quantSpecCoefIdx] = -(FIXP_DBL)quantSpecCoef; + } else { + pQuantSpecCoef[*quantSpecCoefIdx] = (FIXP_DBL)quantSpecCoef; + } + } else { + pQuantSpecCoef[*quantSpecCoefIdx] = FL2FXCONST_DBL(0.0f); + } + *quantSpecCoefIdx += 1; + if (*quantSpecCoefIdx >= 1024) { + return -1; + } + } + return 0; +} + +/*--------------------------------------------------------------------------------------------- + description: Mutes spectral lines which have been marked as erroneous +(Q_VALUE_INVALID) +-------------------------------------------------------------------------------------------- +*/ +void HcrMuteErroneousLines(H_HCR_INFO hHcr) { + int c; + FIXP_DBL *RESTRICT pLong = + SPEC_LONG(hHcr->decInOut.pQuantizedSpectralCoefficientsBase); + + /* if there is a line with value Q_VALUE_INVALID mute it */ + for (c = 0; c < 1024; c++) { + if (pLong[c] == (FIXP_DBL)Q_VALUE_INVALID) { + pLong[c] = FL2FXCONST_DBL(0.0f); /* muting */ + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr.h new file mode 100644 index 0000000000000..be21144686d71 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr.h @@ -0,0 +1,128 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Interface function declaration; common defines + and structures; defines for switching error-generator, + -detector, and -concealment + +*******************************************************************************/ + +#ifndef AACDEC_HCR_H +#define AACDEC_HCR_H + +#include "channelinfo.h" +#include "FDK_bitstream.h" + +UINT HcrInit(H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs); +UINT HcrDecoder(H_HCR_INFO hHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs); +void CarryBitToBranchValue(UCHAR carryBit, UINT treeNode, UINT *branchValue, + UINT *branchNode); + +void CHcr_Read(HANDLE_FDK_BITSTREAM bs, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const MP4_ELEMENT_ID globalHcrType); +void HcrMuteErroneousLines(H_HCR_INFO hHcr); + +void setHcrType(H_HCR_INFO hHcr, MP4_ELEMENT_ID type); +INT getHcrType(H_HCR_INFO hHcr); + +#endif /* AACDEC_HCR_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr_bit.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr_bit.cpp new file mode 100644 index 0000000000000..0198659147b27 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr_bit.cpp @@ -0,0 +1,164 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Bitstream reading + +*******************************************************************************/ + +#include "aacdec_hcr_bit.h" + +/*--------------------------------------------------------------------------------------------- + description: This function toggles the read direction. +----------------------------------------------------------------------------------------------- + input: current read direction +----------------------------------------------------------------------------------------------- + return: new read direction +-------------------------------------------------------------------------------------------- +*/ +UCHAR ToggleReadDirection(UCHAR readDirection) { + if (readDirection == FROM_LEFT_TO_RIGHT) { + return FROM_RIGHT_TO_LEFT; + } else { + return FROM_LEFT_TO_RIGHT; + } +} + +/*--------------------------------------------------------------------------------------------- + description: This function returns a bit from the bitstream according to +read direction. It is called very often, therefore it makes sense to inline it +(runtime). +----------------------------------------------------------------------------------------------- + input: - handle to FDK bitstream + - reference value marking start of bitfield + - pLeftStartOfSegment + - pRightStartOfSegment + - readDirection +----------------------------------------------------------------------------------------------- + return: - bit from bitstream +-------------------------------------------------------------------------------------------- +*/ +UINT HcrGetABitFromBitstream(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + INT *pLeftStartOfSegment, + INT *pRightStartOfSegment, UCHAR readDirection) { + UINT bit; + INT readBitOffset; + + if (readDirection == FROM_LEFT_TO_RIGHT) { + readBitOffset = (INT)FDKgetValidBits(bs) - bsAnchor + *pLeftStartOfSegment; + if (readBitOffset) { + FDKpushBiDirectional(bs, readBitOffset); + } + + bit = FDKreadBits(bs, 1); + + *pLeftStartOfSegment += 1; + } else { + readBitOffset = (INT)FDKgetValidBits(bs) - bsAnchor + *pRightStartOfSegment; + if (readBitOffset) { + FDKpushBiDirectional(bs, readBitOffset); + } + + /* to be replaced with a brother function of FDKreadBits() */ + bit = FDKreadBits(bs, 1); + FDKpushBack(bs, 2); + + *pRightStartOfSegment -= 1; + } + + return (bit); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr_bit.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr_bit.h new file mode 100644 index 0000000000000..77242acb82818 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr_bit.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Bitstream reading prototypes + +*******************************************************************************/ + +#ifndef AACDEC_HCR_BIT_H +#define AACDEC_HCR_BIT_H + +#include "aacdec_hcr.h" + +UCHAR ToggleReadDirection(UCHAR readDirection); + +UINT HcrGetABitFromBitstream(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + INT *pLeftStartOfSegment, + INT *pRightStartOfSegment, UCHAR readDirection); + +#endif /* AACDEC_HCR_BIT_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr_types.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr_types.h new file mode 100644 index 0000000000000..1cc3cb0d7c688 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcr_types.h @@ -0,0 +1,432 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Common defines and structures; defines for + switching error-generator, -detector, and -concealment; + +*******************************************************************************/ + +#ifndef AACDEC_HCR_TYPES_H +#define AACDEC_HCR_TYPES_H + +#include "FDK_bitstream.h" +#include "overlapadd.h" + +/* ------------------------------------------------ */ +/* ------------------------------------------------ */ + +#define LINES_PER_UNIT 4 + +/* ------------------------------------------------ */ +/* ------------------------------------------------ */ +/* ----------- basic HCR configuration ------------ */ + +#define MAX_SFB_HCR \ + (((1024 / 8) / LINES_PER_UNIT) * 8) /* (8 * 16) is not enough because sfbs \ + are split in units for blocktype \ + short */ +#define NUMBER_OF_UNIT_GROUPS (LINES_PER_UNIT * 8) +#define LINES_PER_UNIT_GROUP (1024 / NUMBER_OF_UNIT_GROUPS) /* 15 16 30 32 */ + +/* ------------------------------------------------ */ +/* ------------------------------------------------ */ +/* ------------------------------------------------ */ + +#define FROM_LEFT_TO_RIGHT 0 +#define FROM_RIGHT_TO_LEFT 1 + +#define MAX_CB_PAIRS 23 +#define MAX_HCR_SETS 14 + +#define ESCAPE_VALUE 16 +#define POSITION_OF_FLAG_A 21 +#define POSITION_OF_FLAG_B 20 + +#define MAX_CB 32 /* last used CB is cb #31 when VCB11 is used */ + +#define MAX_CB_CHECK \ + 32 /* support for VCB11 available -- is more general, could therefore used \ + in both cases */ + +#define NUMBER_OF_BIT_IN_WORD 32 + +/* log */ +#define THIRTYTWO_LOG_DIV_TWO_LOG 5 +#define EIGHT_LOG_DIV_TWO_LOG 3 +#define FOUR_LOG_DIV_TWO_LOG 2 + +/* borders */ +#define CPE_TOP_LENGTH 12288 +#define SCE_TOP_LENGTH 6144 +#define LEN_OF_LONGEST_CW_TOP_LENGTH 49 + +/* qsc's of high level */ +#define Q_VALUE_INVALID \ + 8192 /* mark a invalid line with this value (to be concealed later on) */ +#define HCR_DIRAC 500 /* a line of high level */ + +/* masks */ +#define MASK_LEFT 0xFFF000 +#define MASK_RIGHT 0xFFF +#define CLR_BIT_10 0x3FF +#define TEST_BIT_10 0x400 + +#define LEFT_OFFSET 12 + +/* when set HCR is replaced by a dummy-module which just fills the outputbuffer + * with a dirac sequence */ +/* use this if HCR is suspected to write in other modules -- if error is stell + * there, HCR is innocent */ + +/* ------------------------------ */ +/* - insert HCR errors - */ +/* ------------------------------ */ + +/* modify input lengths -- high protected */ +#define ERROR_LORSD 0 /* offset: error if different from zero */ +#define ERROR_LOLC 0 /* offset: error if different from zero */ + +/* segments are earlier empty as expected when decoding PCWs */ +#define ERROR_PCW_BODY \ + 0 /* set a positive values to trigger the error (make segments earlyer \ + appear to be empty) */ +#define ERROR_PCW_BODY_SIGN \ + 0 /* set a positive values to trigger the error (make segments earlyer \ + appear to be empty) */ +#define ERROR_PCW_BODY_SIGN_ESC \ + 0 /* set a positive values to trigger the error (make segments earlyer \ + appear to be empty) */ + +/* pretend there are too many bits decoded (enlarge length of codeword) at PCWs + * -- use a positive value */ +#define ERROR_PCW_BODY_ONLY_TOO_LONG \ + 0 /* set a positive values to trigger the error */ +#define ERROR_PCW_BODY_SIGN_TOO_LONG \ + 0 /* set a positive values to trigger the error */ +#define ERROR_PCW_BODY_SIGN_ESC_TOO_LONG \ + 0 /* set a positive values to trigger the error */ + +/* modify HCR bitstream block */ + +#define MODULO_DIVISOR_HCR 30 + +/* ------------------------------ */ +/* - detect HCR errors - */ +/* ------------------------------ */ +/* check input data */ + +/* during decoding */ + +/* all the segments are checked -- therefore -- if this check passes, its a kind + of evidence that the decoded PCWs and non-PCWs are fine */ + +/* if a codeword is decoded there exists a border for the number of bits, which + are allowed to read for this codeword. This border is the minimum of the + length of the longest codeword (for the currently used codebook) and the + separately transmitted 'lengthOfLongestCodeword' in this frame and channel. + The number of decoded bits is counted (for PCWs only -- there it makes really + sense in my opinion). If this number exceeds the border (derived as minimum + -- see above), a error is detected. */ + +/* ----------------------------------------------------------------------------------------------------- + This error check could be set to zero because due to a test within + RVLC-Escape-huffman-Decoder a too long codeword could not be detected -- it + seems that for RVLC-Escape-Codeword the coderoom is used to 100%. Therefore I + assume that the coderoom is used to 100% also for the codebooks 1..11 used at + HCR Therefore this test is deactivated pending further notice + ----------------------------------------------------------------------------------------------------- + */ + +/* test if the number of remaining bits in a segment is _below_ zero. If there + are no errors the lowest allowed value for remainingBitsInSegment is zero. + This check also could be set to zero (save runtime) */ + +/* other */ +/* when set to '1', avoid setting the LAV-Flag in errorLog due to a + previous-line-marking (at PCW decoder). A little more runtime is needed then + when writing values out into output-buffer. */ + +/* ------------------------------ */ +/* - conceal HCR errors - */ +/* ------------------------------ */ + +#define HCR_ERROR_CONCEALMENT \ + 1 /* if set to '1', HCR _mutes_ the erred quantized spectral coefficients */ + +// ------------------------------------------------------------------------------------------------------------------ +// errorLog: A word of 32 bits used for +// logging possible errors within HCR +// in case of distorted +// bitstreams. Table of all +// known errors: +// ------------------------------------------------------------------------------------------------------------------------ +// bit fatal location meaning +// ----+-----+-----------+-------------------------------------- +#define SEGMENT_OVERRIDE_ERR_PCW_BODY \ + 0x80000000 // 31 no PCW-Dec During PCW decoding it is checked after + // every PCW if there are too many bits decoded (immediate + // check). +#define SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN \ + 0x40000000 // 30 no PCW-Dec During PCW decoding it is checked after + // every PCW if there are too many bits decoded (immediate + // check). +#define SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN_ESC \ + 0x20000000 // 29 no PCW-Dec During PCW decoding it is checked after + // every PCW if there are too many bits decoded (immediate + // check). +#define EXTENDED_SORTED_COUNTER_OVERFLOW \ + 0x10000000 // 28 yes Init-Dec Error during extending sideinfo + // (neither a PCW nor a nonPCW was decoded so far) + // 0x08000000 // 27 reserved + // 0x04000000 // 26 reserved + // 0x02000000 // 25 reserved + // 0x01000000 // 24 reserved + // 0x00800000 // 23 reserved + // 0x00400000 // 22 reserved + // 0x00200000 // 21 reserved + // 0x00100000 // 20 reserved + +/* special errors */ +#define TOO_MANY_PCW_BODY_BITS_DECODED \ + 0x00080000 // 19 yes PCW-Dec During PCW-body-decoding too many bits + // have been read from bitstream -- advice: skip non-PCW decoding +#define TOO_MANY_PCW_BODY_SIGN_BITS_DECODED \ + 0x00040000 // 18 yes PCW-Dec During PCW-body-sign-decoding too many + // bits have been read from bitstream -- advice: skip non-PCW + // decoding +#define TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED \ + 0x00020000 // 17 yes PCW-Dec During PCW-body-sign-esc-decoding too + // many bits have been read from bitstream -- advice: skip + // non-PCW decoding + +// 0x00010000 // 16 reserved +#define STATE_ERROR_BODY_ONLY \ + 0x00008000 // 15 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN__BODY \ + 0x00004000 // 14 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN__SIGN \ + 0x00002000 // 13 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN_ESC__BODY \ + 0x00001000 // 12 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN_ESC__SIGN \ + 0x00000800 // 11 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX \ + 0x00000400 // 10 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN_ESC__ESC_WORD \ + 0x00000200 // 9 no NonPCW-Dec State machine returned with error +#define HCR_SI_LENGTHS_FAILURE \ + 0x00000100 // 8 yes Init-Dec LengthOfLongestCodeword must not be + // less than lenghtOfReorderedSpectralData +#define NUM_SECT_OUT_OF_RANGE_SHORT_BLOCK \ + 0x00000080 // 7 yes Init-Dec The number of sections is not within + // the allowed range (short block) +#define NUM_SECT_OUT_OF_RANGE_LONG_BLOCK \ + 0x00000040 // 6 yes Init-Dec The number of sections is not within + // the allowed range (long block) +#define LINE_IN_SECT_OUT_OF_RANGE_SHORT_BLOCK \ + 0x00000020 // 5 yes Init-Dec The number of lines per section is not + // within the allowed range (short block) +#define CB_OUT_OF_RANGE_SHORT_BLOCK \ + 0x00000010 // 4 yes Init-Dec The codebook is not within the allowed + // range (short block) +#define LINE_IN_SECT_OUT_OF_RANGE_LONG_BLOCK \ + 0x00000008 // 3 yes Init-Dec The number of lines per section is not + // within the allowed range (long block) +#define CB_OUT_OF_RANGE_LONG_BLOCK \ + 0x00000004 // 2 yes Init-Dec The codebook is not within the allowed + // range (long block) +#define LAV_VIOLATION \ + 0x00000002 // 1 no Final The absolute value of at least one + // decoded line was too high for the according codebook. +#define BIT_IN_SEGMENTATION_ERROR \ + 0x00000001 // 0 no Final After PCW and non-PWC-decoding at least + // one segment is not zero (global check). + +/*----------*/ +#define HCR_FATAL_PCW_ERROR_MASK 0x100E01FC + +typedef enum { PCW_BODY, PCW_BODY_SIGN, PCW_BODY_SIGN_ESC } PCW_TYPE; + +/* interface Decoder <---> HCR */ +typedef struct { + UINT errorLog; + SPECTRAL_PTR pQuantizedSpectralCoefficientsBase; + int quantizedSpectralCoefficientsIdx; + SHORT lengthOfReorderedSpectralData; + SHORT numSection; + SHORT *pNumLineInSect; + INT bitstreamAnchor; + SCHAR lengthOfLongestCodeword; + UCHAR *pCodebook; +} HCR_INPUT_OUTPUT; + +typedef struct { + const UCHAR *pMinOfCbPair; + const UCHAR *pMaxOfCbPair; +} HCR_CB_PAIRS; + +typedef struct { + const USHORT *pLargestAbsVal; + const UCHAR *pMaxCwLength; + const UCHAR *pCbDimension; + const UCHAR *pCbDimShift; + const UCHAR *pCbSign; + const UCHAR *pCbPriority; +} HCR_TABLE_INFO; + +typedef struct { + UINT numSegment; + UINT pSegmentBitfield[((1024 >> 1) / NUMBER_OF_BIT_IN_WORD + 1)]; + UINT pCodewordBitfield[((1024 >> 1) / NUMBER_OF_BIT_IN_WORD + 1)]; + UINT segmentOffset; + INT pLeftStartOfSegment[1024 >> 1]; + INT pRightStartOfSegment[1024 >> 1]; + SCHAR pRemainingBitsInSegment[1024 >> 1]; + UCHAR readDirection; + UCHAR numWordForBitfield; + USHORT pNumBitValidInLastWord; +} HCR_SEGMENT_INFO; + +typedef struct { + UINT numCodeword; + UINT numSortedSection; + USHORT pNumCodewordInSection[MAX_SFB_HCR]; + USHORT pNumSortedCodewordInSection[MAX_SFB_HCR]; + USHORT pNumExtendedSortedCodewordInSection[MAX_SFB_HCR + MAX_HCR_SETS]; + int numExtendedSortedCodewordInSectionIdx; + USHORT pNumExtendedSortedSectionsInSets[MAX_HCR_SETS]; + int numExtendedSortedSectionsInSetsIdx; + USHORT pReorderOffset[MAX_SFB_HCR]; + UCHAR pSortedCodebook[MAX_SFB_HCR]; + + UCHAR pExtendedSortedCodebook[MAX_SFB_HCR + MAX_HCR_SETS]; + int extendedSortedCodebookIdx; + UCHAR pMaxLenOfCbInExtSrtSec[MAX_SFB_HCR + MAX_HCR_SETS]; + int maxLenOfCbInExtSrtSecIdx; + UCHAR pCodebookSwitch[MAX_SFB_HCR]; +} HCR_SECTION_INFO; + +typedef UINT (*STATEFUNC)(HANDLE_FDK_BITSTREAM, void *); + +typedef struct { + /* worst-case and 1024/4 non-PCWs exist in worst-case */ + FIXP_DBL + *pResultBase; /* Base address for spectral data output target buffer */ + UINT iNode[1024 >> 2]; /* Helper indices for code books */ + USHORT + iResultPointer[1024 >> 2]; /* Helper indices for accessing pResultBase */ + UINT pEscapeSequenceInfo[1024 >> 2]; + UINT codewordOffset; + STATEFUNC pState; + UCHAR pCodebook[1024 >> 2]; + UCHAR pCntSign[1024 >> 2]; + /* this array holds the states coded as integer values within the range + * [0,1,..,7] */ + SCHAR pSta[1024 >> 2]; +} HCR_NON_PCW_SIDEINFO; + +typedef struct { + HCR_INPUT_OUTPUT decInOut; + HCR_SEGMENT_INFO segmentInfo; + HCR_SECTION_INFO sectionInfo; + HCR_NON_PCW_SIDEINFO nonPcwSideinfo; +} CErHcrInfo; + +typedef CErHcrInfo *H_HCR_INFO; + +#endif /* AACDEC_HCR_TYPES_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcrs.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcrs.cpp new file mode 100644 index 0000000000000..5e3f9ac4dcb9f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcrs.cpp @@ -0,0 +1,1557 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Prepare decoding of non-PCWs, segmentation- and + bitfield-handling, HCR-Statemachine + +*******************************************************************************/ + +#include "aacdec_hcrs.h" + +#include "aacdec_hcr.h" + +#include "aacdec_hcr_bit.h" +#include "aac_rom.h" +#include "aac_ram.h" + +static UINT InitSegmentBitfield(UINT *pNumSegment, + SCHAR *pRemainingBitsInSegment, + UINT *pSegmentBitfield, + UCHAR *pNumWordForBitfield, + USHORT *pNumBitValidInLastWord); + +static void InitNonPCWSideInformationForCurrentSet(H_HCR_INFO pHcr); + +static INT ModuloValue(INT input, INT bufferlength); + +static void ClearBitFromBitfield(STATEFUNC *ptrState, UINT offset, + UINT *pBitfield); + +/*--------------------------------------------------------------------------------------------- + description: This function decodes all non-priority codewords (non-PCWs) by +using a state-machine. +-------------------------------------------------------------------------------------------- +*/ +void DecodeNonPCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) { + UINT numValidSegment; + INT segmentOffset; + INT codewordOffsetBase; + INT codewordOffset; + UINT trial; + + UINT *pNumSegment; + SCHAR *pRemainingBitsInSegment; + UINT *pSegmentBitfield; + UCHAR *pNumWordForBitfield; + USHORT *pNumBitValidInLastWord; + UINT *pCodewordBitfield; + INT bitfieldWord; + INT bitInWord; + UINT tempWord; + UINT interMediateWord; + INT tempBit; + INT carry; + + UINT numCodeword; + UCHAR numSet; + UCHAR currentSet; + UINT codewordInSet; + UINT remainingCodewordsInSet; + SCHAR *pSta; + UINT ret; + + pNumSegment = &(pHcr->segmentInfo.numSegment); + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pNumWordForBitfield = &(pHcr->segmentInfo.numWordForBitfield); + pNumBitValidInLastWord = &(pHcr->segmentInfo.pNumBitValidInLastWord); + pSta = pHcr->nonPcwSideinfo.pSta; + + numValidSegment = InitSegmentBitfield(pNumSegment, pRemainingBitsInSegment, + pSegmentBitfield, pNumWordForBitfield, + pNumBitValidInLastWord); + + if (numValidSegment != 0) { + numCodeword = pHcr->sectionInfo.numCodeword; + numSet = ((numCodeword - 1) / *pNumSegment) + 1; + + pHcr->segmentInfo.readDirection = FROM_RIGHT_TO_LEFT; + + /* Process sets subsequently */ + numSet = fMin(numSet, (UCHAR)MAX_HCR_SETS); + for (currentSet = 1; currentSet < numSet; currentSet++) { + + /* step 1 */ + numCodeword -= + *pNumSegment; /* number of remaining non PCWs [for all sets] */ + if (numCodeword < *pNumSegment) { + codewordInSet = numCodeword; /* for last set */ + } else { + codewordInSet = *pNumSegment; /* for all sets except last set */ + } + + /* step 2 */ + /* prepare array 'CodewordBitfield'; as much ones are written from left in + * all words, as much decodedCodewordInSetCounter nonPCWs exist in this + * set */ + tempWord = 0xFFFFFFFF; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + + for (bitfieldWord = *pNumWordForBitfield; bitfieldWord != 0; + bitfieldWord--) { /* loop over all used words */ + if (codewordInSet > NUMBER_OF_BIT_IN_WORD) { /* more codewords than + number of bits => fill + ones */ + /* fill a whole word with ones */ + *pCodewordBitfield++ = tempWord; + codewordInSet -= NUMBER_OF_BIT_IN_WORD; /* subtract number of bits */ + } else { + /* prepare last tempWord */ + for (remainingCodewordsInSet = codewordInSet; + remainingCodewordsInSet < NUMBER_OF_BIT_IN_WORD; + remainingCodewordsInSet++) { + tempWord = + tempWord & + ~(1 + << (NUMBER_OF_BIT_IN_WORD - 1 - + remainingCodewordsInSet)); /* set a zero at bit number + (NUMBER_OF_BIT_IN_WORD-1-i) + in tempWord */ + } + *pCodewordBitfield++ = tempWord; + tempWord = 0x00000000; + } + } + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + + /* step 3 */ + /* build non-PCW sideinfo for each non-PCW of the current set */ + InitNonPCWSideInformationForCurrentSet(pHcr); + + /* step 4 */ + /* decode all non-PCWs belonging to this set */ + + /* loop over trials */ + codewordOffsetBase = 0; + for (trial = *pNumSegment; trial > 0; trial--) { + /* loop over number of words in bitfields */ + segmentOffset = 0; /* start at zero in every segment */ + pHcr->segmentInfo.segmentOffset = + segmentOffset; /* store in structure for states */ + codewordOffset = codewordOffsetBase; + pHcr->nonPcwSideinfo.codewordOffset = + codewordOffset; /* store in structure for states */ + + for (bitfieldWord = 0; bitfieldWord < *pNumWordForBitfield; + bitfieldWord++) { + /* derive tempWord with bitwise and */ + tempWord = + pSegmentBitfield[bitfieldWord] & pCodewordBitfield[bitfieldWord]; + + /* if tempWord is not zero, decode something */ + if (tempWord != 0) { + /* loop over all bits in tempWord; start state machine if & is true + */ + for (bitInWord = NUMBER_OF_BIT_IN_WORD; bitInWord > 0; + bitInWord--) { + interMediateWord = ((UINT)1 << (bitInWord - 1)); + if ((tempWord & interMediateWord) == interMediateWord) { + /* get state and start state machine */ + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; + + while (pHcr->nonPcwSideinfo.pState) { + ret = ((STATEFUNC)pHcr->nonPcwSideinfo.pState)(bs, pHcr); + if (ret != 0) { + return; + } + } + } + + /* update both offsets */ + segmentOffset += 1; /* add NUMBER_OF_BIT_IN_WORD times one */ + pHcr->segmentInfo.segmentOffset = segmentOffset; + codewordOffset += 1; /* add NUMBER_OF_BIT_IN_WORD times one */ + codewordOffset = + ModuloValue(codewordOffset, + *pNumSegment); /* index of the current codeword + lies within modulo range */ + pHcr->nonPcwSideinfo.codewordOffset = codewordOffset; + } + } else { + segmentOffset += + NUMBER_OF_BIT_IN_WORD; /* add NUMBER_OF_BIT_IN_WORD at once */ + pHcr->segmentInfo.segmentOffset = segmentOffset; + codewordOffset += + NUMBER_OF_BIT_IN_WORD; /* add NUMBER_OF_BIT_IN_WORD at once */ + codewordOffset = ModuloValue( + codewordOffset, + *pNumSegment); /* index of the current codeword lies within + modulo range */ + pHcr->nonPcwSideinfo.codewordOffset = codewordOffset; + } + } /* end of bitfield word loop */ + + /* decrement codeword - pointer */ + codewordOffsetBase -= 1; + codewordOffsetBase = + ModuloValue(codewordOffsetBase, *pNumSegment); /* index of the + current codeword + base lies within + modulo range */ + + /* rotate numSegment bits in codewordBitfield */ + /* rotation of *numSegment bits in bitfield of codewords + * (circle-rotation) */ + /* get last valid bit */ + tempBit = pCodewordBitfield[*pNumWordForBitfield - 1] & + (1 << (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord)); + tempBit = tempBit >> (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord); + + /* write zero into place where tempBit was fetched from */ + pCodewordBitfield[*pNumWordForBitfield - 1] = + pCodewordBitfield[*pNumWordForBitfield - 1] & + ~(1 << (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord)); + + /* rotate last valid word */ + pCodewordBitfield[*pNumWordForBitfield - 1] = + pCodewordBitfield[*pNumWordForBitfield - 1] >> 1; + + /* transfare carry bit 0 from current word into bitposition 31 from next + * word and rotate current word */ + for (bitfieldWord = *pNumWordForBitfield - 2; bitfieldWord > -1; + bitfieldWord--) { + /* get carry (=bit at position 0) from current word */ + carry = pCodewordBitfield[bitfieldWord] & 1; + + /* put the carry bit at position 31 into word right from current word + */ + pCodewordBitfield[bitfieldWord + 1] = + pCodewordBitfield[bitfieldWord + 1] | + (carry << (NUMBER_OF_BIT_IN_WORD - 1)); + + /* shift current word */ + pCodewordBitfield[bitfieldWord] = + pCodewordBitfield[bitfieldWord] >> 1; + } + + /* put tempBit into free bit-position 31 from first word */ + pCodewordBitfield[0] = + pCodewordBitfield[0] | (tempBit << (NUMBER_OF_BIT_IN_WORD - 1)); + + } /* end of trial loop */ + + /* toggle read direction */ + pHcr->segmentInfo.readDirection = + ToggleReadDirection(pHcr->segmentInfo.readDirection); + } + /* end of set loop */ + + /* all non-PCWs of this spectrum are decoded */ + } + + /* all PCWs and all non PCWs are decoded. They are unbacksorted in output + * buffer. Here is the Interface with comparing QSCs to asm decoding */ +} + +/*--------------------------------------------------------------------------------------------- + description: This function prepares the bitfield used for the + segments. The list is set up once to be used in all +following sets. If a segment is decoded empty, the according bit from the +Bitfield is removed. +----------------------------------------------------------------------------------------------- + return: numValidSegment = the number of valid segments +-------------------------------------------------------------------------------------------- +*/ +static UINT InitSegmentBitfield(UINT *pNumSegment, + SCHAR *pRemainingBitsInSegment, + UINT *pSegmentBitfield, + UCHAR *pNumWordForBitfield, + USHORT *pNumBitValidInLastWord) { + SHORT i; + USHORT r; + UCHAR bitfieldWord; + UINT tempWord; + USHORT numValidSegment; + + *pNumWordForBitfield = + (*pNumSegment == 0) + ? 0 + : ((*pNumSegment - 1) >> THIRTYTWO_LOG_DIV_TWO_LOG) + 1; + + /* loop over all words, which are completely used or only partial */ + /* bit in pSegmentBitfield is zero if segment is empty; bit in + * pSegmentBitfield is one if segment is not empty */ + numValidSegment = 0; + *pNumBitValidInLastWord = *pNumSegment; + + /* loop over words */ + for (bitfieldWord = 0; bitfieldWord < *pNumWordForBitfield - 1; + bitfieldWord++) { + tempWord = 0xFFFFFFFF; /* set ones */ + r = bitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG; + for (i = 0; i < NUMBER_OF_BIT_IN_WORD; i++) { + if (pRemainingBitsInSegment[r + i] == 0) { + tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD - 1 - + i)); /* set a zero at bit number + (NUMBER_OF_BIT_IN_WORD-1-i) in + tempWord */ + } else { + numValidSegment += 1; /* count segments which are not empty */ + } + } + pSegmentBitfield[bitfieldWord] = tempWord; /* store result */ + *pNumBitValidInLastWord -= NUMBER_OF_BIT_IN_WORD; /* calculate number of + zeros on LSB side in + the last word */ + } + + /* calculate last word: prepare special tempWord */ + tempWord = 0xFFFFFFFF; + for (i = 0; i < (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord); i++) { + tempWord = tempWord & ~(1 << i); /* clear bit i in tempWord */ + } + + /* calculate last word */ + r = bitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG; + for (i = 0; i < *pNumBitValidInLastWord; i++) { + if (pRemainingBitsInSegment[r + i] == 0) { + tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD - 1 - + i)); /* set a zero at bit number + (NUMBER_OF_BIT_IN_WORD-1-i) in + tempWord */ + } else { + numValidSegment += 1; /* count segments which are not empty */ + } + } + pSegmentBitfield[bitfieldWord] = tempWord; /* store result */ + + return numValidSegment; +} + +/*--------------------------------------------------------------------------------------------- + description: This function sets up sideinfo for the non-PCW decoder (for the +current set). +---------------------------------------------------------------------------------------------*/ +static void InitNonPCWSideInformationForCurrentSet(H_HCR_INFO pHcr) { + USHORT i, k; + UCHAR codebookDim; + UINT startNode; + + UCHAR *pCodebook = pHcr->nonPcwSideinfo.pCodebook; + UINT *iNode = pHcr->nonPcwSideinfo.iNode; + UCHAR *pCntSign = pHcr->nonPcwSideinfo.pCntSign; + USHORT *iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + UINT *pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + SCHAR *pSta = pHcr->nonPcwSideinfo.pSta; + USHORT *pNumExtendedSortedCodewordInSection = + pHcr->sectionInfo.pNumExtendedSortedCodewordInSection; + int numExtendedSortedCodewordInSectionIdx = + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx; + UCHAR *pExtendedSortedCodebook = pHcr->sectionInfo.pExtendedSortedCodebook; + int extendedSortedCodebookIdx = pHcr->sectionInfo.extendedSortedCodebookIdx; + USHORT *pNumExtendedSortedSectionsInSets = + pHcr->sectionInfo.pNumExtendedSortedSectionsInSets; + int numExtendedSortedSectionsInSetsIdx = + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx; + int quantizedSpectralCoefficientsIdx = + pHcr->decInOut.quantizedSpectralCoefficientsIdx; + const UCHAR *pCbDimension = aDimCb; + int iterationCounter = 0; + + /* loop over number of extended sorted sections in the current set so all + * codewords sideinfo variables within this set can be prepared for decoding + */ + for (i = pNumExtendedSortedSectionsInSets[numExtendedSortedSectionsInSetsIdx]; + i != 0; i--) { + codebookDim = + pCbDimension[pExtendedSortedCodebook[extendedSortedCodebookIdx]]; + startNode = *aHuffTable[pExtendedSortedCodebook[extendedSortedCodebookIdx]]; + + for (k = pNumExtendedSortedCodewordInSection + [numExtendedSortedCodewordInSectionIdx]; + k != 0; k--) { + iterationCounter++; + if (iterationCounter > (1024 >> 2)) { + return; + } + *pSta++ = aCodebook2StartInt + [pExtendedSortedCodebook[extendedSortedCodebookIdx]]; + *pCodebook++ = pExtendedSortedCodebook[extendedSortedCodebookIdx]; + *iNode++ = startNode; + *pCntSign++ = 0; + *iResultPointer++ = quantizedSpectralCoefficientsIdx; + *pEscapeSequenceInfo++ = 0; + quantizedSpectralCoefficientsIdx += + codebookDim; /* update pointer by codebookDim --> point to next + starting value for writing out */ + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + } + numExtendedSortedCodewordInSectionIdx++; /* inc ptr for next ext sort sec in + current set */ + extendedSortedCodebookIdx++; /* inc ptr for next ext sort sec in current set + */ + if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR + MAX_HCR_SETS) || + extendedSortedCodebookIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + return; + } + } + numExtendedSortedSectionsInSetsIdx++; /* inc ptr for next set of non-PCWs */ + if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + return; + } + + /* Write back indexes */ + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = + numExtendedSortedCodewordInSectionIdx; + pHcr->sectionInfo.extendedSortedCodebookIdx = extendedSortedCodebookIdx; + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = + numExtendedSortedSectionsInSetsIdx; + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = + numExtendedSortedCodewordInSectionIdx; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = + quantizedSpectralCoefficientsIdx; +} + +/*--------------------------------------------------------------------------------------------- + description: This function returns the input value if the value is in the + range of bufferlength. If is smaller, one bufferlength +is added, if is bigger one bufferlength is subtracted. +----------------------------------------------------------------------------------------------- + return: modulo result +-------------------------------------------------------------------------------------------- +*/ +static INT ModuloValue(INT input, INT bufferlength) { + if (input > (bufferlength - 1)) { + return (input - bufferlength); + } + if (input < 0) { + return (input + bufferlength); + } + return input; +} + +/*--------------------------------------------------------------------------------------------- + description: This function clears a bit from current bitfield and + switches off the statemachine. + + A bit is cleared in two cases: + a) a codeword is decoded, then a bit is cleared in codeword +bitfield b) a segment is decoded empty, then a bit is cleared in segment +bitfield +-------------------------------------------------------------------------------------------- +*/ +static void ClearBitFromBitfield(STATEFUNC *ptrState, UINT offset, + UINT *pBitfield) { + UINT numBitfieldWord; + UINT numBitfieldBit; + + /* get both values needed for clearing the bit */ + numBitfieldWord = offset >> THIRTYTWO_LOG_DIV_TWO_LOG; /* int = wordNr */ + numBitfieldBit = offset - (numBitfieldWord + << THIRTYTWO_LOG_DIV_TWO_LOG); /* fract = bitNr */ + + /* clear a bit in bitfield */ + pBitfield[numBitfieldWord] = + pBitfield[numBitfieldWord] & + ~(1 << (NUMBER_OF_BIT_IN_WORD - 1 - numBitfieldBit)); + + /* switch off state machine because codeword is decoded and/or because segment + * is empty */ + *ptrState = NULL; +} + +/* ========================================================================================= + the states of the statemachine + ========================================================================================= + */ + +/*--------------------------------------------------------------------------------------------- + description: Decodes the body of a codeword. This State is used for +codebooks 1,2,5 and 6. No sign bits are decoded, because the table of the +quantized spectral values has got a valid sign at the quantized spectral lines. +----------------------------------------------------------------------------------------------- + output: Two or four quantizes spectral values written at position +where pResultPointr points to +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_ONLY(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + FIXP_DBL *pResultBase; + UINT *iNode; + USHORT *iResultPointer; + UINT codewordOffset; + UINT branchNode; + UINT branchValue; + UINT iQSC; + UINT treeNode; + UCHAR carryBit; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + SCHAR *pRemainingBitsInSegment; + UCHAR readDirection; + UCHAR *pCodebook; + UCHAR dimCntr; + const UINT *pCurrentTree; + const UCHAR *pCbDimension; + const SCHAR *pQuantVal; + const SCHAR *pQuantValBase; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pCodebook = pHcr->nonPcwSideinfo.pCodebook; + iNode = pHcr->nonPcwSideinfo.iNode; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + + pCbDimension = aDimCb; + + treeNode = iNode[codewordOffset]; + pCurrentTree = aHuffTable[pCodebook[codewordOffset]]; + + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + CarryBitToBranchValue(carryBit, /* make a step in decoding tree */ + treeNode, &branchValue, &branchNode); + + /* if end of branch reached write out lines and count bits needed for sign, + * otherwise store node in codeword sideinfo */ + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; ==> body is complete */ + pQuantValBase = aQuantTable[pCodebook[codewordOffset]]; /* get base + address of + quantized + values + belonging to + current + codebook */ + pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid + line [of 2 or 4 quantized + values] */ + + iQSC = iResultPointer[codewordOffset]; /* get position of first line for + writing out result */ + + for (dimCntr = pCbDimension[pCodebook[codewordOffset]]; dimCntr != 0; + dimCntr--) { + pResultBase[iQSC++] = + (FIXP_DBL)*pQuantVal++; /* write out 2 or 4 lines into + spectrum; no Sign bits + available in this state */ + } + + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and + switch off statemachine */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + break; /* end of branch in tree reached i.e. a whole nonPCW-Body is + decoded */ + } else { /* body is not decoded completely: */ + treeNode = *( + pCurrentTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + iNode[codewordOffset] = treeNode; /* store updated treeNode because maybe + decoding of codeword body not finished + yet */ + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_ONLY; + return BODY_ONLY; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: Decodes the codeword body, writes out result and counts the +number of quantized spectral values, which are different form zero. For those +values sign bits are needed. + + If sign bit counter cntSign is different from zero, switch to +next state to decode sign Bits there. If sign bit counter cntSign is zero, no +sign bits are needed and codeword is decoded. +----------------------------------------------------------------------------------------------- + output: Two or four written quantizes spectral values written at +position where pResultPointr points to. The signs of those lines may be wrong. +If the signs [on just one signle sign] is wrong, the next state will correct it. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN__BODY(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UCHAR *pCodebook; + UINT *iNode; + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT codewordOffset; + + UINT iQSC; + UINT cntSign; + UCHAR dimCntr; + UCHAR carryBit; + SCHAR *pSta; + UINT treeNode; + UINT branchValue; + UINT branchNode; + const UCHAR *pCbDimension; + const UINT *pCurrentTree; + const SCHAR *pQuantValBase; + const SCHAR *pQuantVal; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pCodebook = pHcr->nonPcwSideinfo.pCodebook; + iNode = pHcr->nonPcwSideinfo.iNode; + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + pCbDimension = aDimCb; + + treeNode = iNode[codewordOffset]; + pCurrentTree = aHuffTable[pCodebook[codewordOffset]]; + + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + CarryBitToBranchValue(carryBit, /* make a step in decoding tree */ + treeNode, &branchValue, &branchNode); + + /* if end of branch reached write out lines and count bits needed for sign, + * otherwise store node in codeword sideinfo */ + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set body complete */ + /* body completely decoded; branchValue is valid, set pQuantVal to first + * (of two or four) quantized spectral coefficients */ + pQuantValBase = aQuantTable[pCodebook[codewordOffset]]; /* get base + address of + quantized + values + belonging to + current + codebook */ + pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid + line [of 2 or 4 quantized + values] */ + + iQSC = iResultPointer[codewordOffset]; /* get position of first line for + writing result */ + + /* codeword decoding result is written out here: Write out 2 or 4 + * quantized spectral values with probably */ + /* wrong sign and count number of values which are different from zero for + * sign bit decoding [which happens in next state] */ + cntSign = 0; + for (dimCntr = pCbDimension[pCodebook[codewordOffset]]; dimCntr != 0; + dimCntr--) { + pResultBase[iQSC++] = + (FIXP_DBL)*pQuantVal; /* write quant. spec. coef. into spectrum */ + if (*pQuantVal++ != 0) { + cntSign += 1; + } + } + + if (cntSign == 0) { + ClearBitFromBitfield( + &(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off + statemachine */ + } else { + pCntSign[codewordOffset] = cntSign; /* write sign count result into + codewordsideinfo of current + codeword */ + pSta[codewordOffset] = BODY_SIGN__SIGN; /* change state */ + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from + separate array of + cw-sideinfo */ + } + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + break; /* end of branch in tree reached i.e. a whole nonPCW-Body is + decoded */ + } else { /* body is not decoded completely: */ + treeNode = *( + pCurrentTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + iNode[codewordOffset] = treeNode; /* store updated treeNode because maybe + decoding of codeword body not finished + yet */ + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN__BODY; + return BODY_SIGN__BODY; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: This state decodes the sign bits belonging to a codeword. The +state is called as often in different "trials" until pCntSgn[codewordOffset] is +zero. +----------------------------------------------------------------------------------------------- + output: The two or four quantizes spectral values (written in previous +state) have now the correct sign. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT codewordOffset; + + UCHAR carryBit; + UINT iQSC; + UCHAR cntSign; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + /*pCodebook = */ + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + + iQSC = iResultPointer[codewordOffset]; + cntSign = pCntSign[codewordOffset]; + + /* loop for sign bit decoding */ + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + cntSign -= + 1; /* decrement sign counter because one sign bit has been read */ + + /* search for a line (which was decoded in previous state) which is not + * zero. [This value will get a sign] */ + while (pResultBase[iQSC] == (FIXP_DBL)0) { + if (++iQSC >= 1024) { /* points to current value different from zero */ + return BODY_SIGN__SIGN; + } + } + + /* put sign together with line; if carryBit is zero, the sign is ok already; + * no write operation necessary in this case */ + if (carryBit != 0) { + pResultBase[iQSC] = -pResultBase[iQSC]; /* carryBit = 1 --> minus */ + } + + iQSC++; /* update pointer to next (maybe valid) value */ + + if (cntSign == 0) { /* if (cntSign==0) ==> set state CODEWORD_DECODED */ + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and + switch off statemachine */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + break; /* whole nonPCW-Body and according sign bits are decoded */ + } + } + pCntSign[codewordOffset] = cntSign; + iResultPointer[codewordOffset] = iQSC; /* store updated pResultPointer */ + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN__SIGN; + return BODY_SIGN__SIGN; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: Decodes the codeword body in case of codebook is 11. Writes +out resulting two or four lines [with probably wrong sign] and counts the number +of lines, which are different form zero. This information is needed in next + state where sign bits will be decoded, if necessary. + If sign bit counter cntSign is zero, no sign bits are needed +and codeword is decoded completely. +----------------------------------------------------------------------------------------------- + output: Two lines (quantizes spectral coefficients) which are probably +wrong. The sign may be wrong and if one or two values is/are 16, the following +states will decode the escape sequence to correct the values which are wirtten +here. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN_ESC__BODY(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UINT *iNode; + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT codewordOffset; + + UCHAR carryBit; + UINT iQSC; + UINT cntSign; + UINT dimCntr; + UINT treeNode; + SCHAR *pSta; + UINT branchNode; + UINT branchValue; + const UINT *pCurrentTree; + const SCHAR *pQuantValBase; + const SCHAR *pQuantVal; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + iNode = pHcr->nonPcwSideinfo.iNode; + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + treeNode = iNode[codewordOffset]; + pCurrentTree = aHuffTable[ESCAPE_CODEBOOK]; + + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + /* make a step in tree */ + CarryBitToBranchValue(carryBit, treeNode, &branchValue, &branchNode); + + /* if end of branch reached write out lines and count bits needed for sign, + * otherwise store node in codeword sideinfo */ + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set body complete */ + + /* body completely decoded; branchValue is valid */ + /* set pQuantVol to first (of two or four) quantized spectral coefficients + */ + pQuantValBase = aQuantTable[ESCAPE_CODEBOOK]; /* get base address of + quantized values + belonging to current + codebook */ + pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid + line [of 2 or 4 quantized + values] */ + + /* make backup from original resultPointer in node storage for state + * BODY_SIGN_ESC__SIGN */ + iNode[codewordOffset] = iResultPointer[codewordOffset]; + + /* get position of first line for writing result */ + iQSC = iResultPointer[codewordOffset]; + + /* codeword decoding result is written out here: Write out 2 or 4 + * quantized spectral values with probably */ + /* wrong sign and count number of values which are different from zero for + * sign bit decoding [which happens in next state] */ + cntSign = 0; + + for (dimCntr = DIMENSION_OF_ESCAPE_CODEBOOK; dimCntr != 0; dimCntr--) { + pResultBase[iQSC++] = + (FIXP_DBL)*pQuantVal; /* write quant. spec. coef. into spectrum */ + if (*pQuantVal++ != 0) { + cntSign += 1; + } + } + + if (cntSign == 0) { + ClearBitFromBitfield( + &(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off + statemachine */ + /* codeword decoded */ + } else { + /* write sign count result into codewordsideinfo of current codeword */ + pCntSign[codewordOffset] = cntSign; + pSta[codewordOffset] = BODY_SIGN_ESC__SIGN; /* change state */ + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from + separate array of + cw-sideinfo */ + } + pRemainingBitsInSegment[segmentOffset] -= 1; /* the last reinitialzation + of for loop counter (see + above) is done here */ + break; /* end of branch in tree reached i.e. a whole nonPCW-Body is + decoded */ + } else { /* body is not decoded completely: */ + /* update treeNode for further step in decoding tree and store updated + * treeNode because maybe no more bits left in segment */ + treeNode = *(pCurrentTree + branchValue); + iNode[codewordOffset] = treeNode; + } + } + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__BODY; + return BODY_SIGN_ESC__BODY; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: This state decodes the sign bits, if a codeword of codebook 11 +needs some. A flag named 'flagB' in codeword sideinfo is set, if the second line +of quantized spectral values is 16. The 'flagB' is used in case of decoding of a +escape sequence is necessary as far as the second line is concerned. + + If only the first line needs an escape sequence, the flagB is +cleared. If only the second line needs an escape sequence, the flagB is not +used. + + For storing sideinfo in case of escape sequence decoding one +single word can be used for both escape sequences because they are decoded not +at the same time: + + + bit 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 +4 3 2 1 0 + ===== == == =========== =========== +=================================== ^ ^ ^ ^ ^ +^ | | | | | | res. flagA flagB +escapePrefixUp escapePrefixDown escapeWord + +----------------------------------------------------------------------------------------------- + output: Two lines with correct sign. If one or two values is/are 16, +the lines are not valid, otherwise they are. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN_ESC__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UINT *iNode; + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT *pEscapeSequenceInfo; + UINT codewordOffset; + + UINT iQSC; + UCHAR cntSign; + UINT flagA; + UINT flagB; + UINT flags; + UCHAR carryBit; + SCHAR *pSta; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + iNode = pHcr->nonPcwSideinfo.iNode; + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + iQSC = iResultPointer[codewordOffset]; + cntSign = pCntSign[codewordOffset]; + + /* loop for sign bit decoding */ + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + /* decrement sign counter because one sign bit has been read */ + cntSign -= 1; + pCntSign[codewordOffset] = cntSign; + + /* get a quantized spectral value (which was decoded in previous state) + * which is not zero. [This value will get a sign] */ + while (pResultBase[iQSC] == (FIXP_DBL)0) { + if (++iQSC >= 1024) { + return BODY_SIGN_ESC__SIGN; + } + } + iResultPointer[codewordOffset] = iQSC; + + /* put negative sign together with quantized spectral value; if carryBit is + * zero, the sign is ok already; no write operation necessary in this case + */ + if (carryBit != 0) { + pResultBase[iQSC] = -pResultBase[iQSC]; /* carryBit = 1 --> minus */ + } + iQSC++; /* update index to next (maybe valid) value */ + iResultPointer[codewordOffset] = iQSC; + + if (cntSign == 0) { + /* all sign bits are decoded now */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + + /* check decoded values if codeword is decoded: Check if one or two escape + * sequences 16 follow */ + + /* step 0 */ + /* restore pointer to first decoded quantized value [ = original + * pResultPointr] from index iNode prepared in State_BODY_SIGN_ESC__BODY + */ + iQSC = iNode[codewordOffset]; + + /* step 1 */ + /* test first value if escape sequence follows */ + flagA = 0; /* for first possible escape sequence */ + if (fixp_abs(pResultBase[iQSC++]) == (FIXP_DBL)ESCAPE_VALUE) { + flagA = 1; + } + + /* step 2 */ + /* test second value if escape sequence follows */ + flagB = 0; /* for second possible escape sequence */ + if (fixp_abs(pResultBase[iQSC]) == (FIXP_DBL)ESCAPE_VALUE) { + flagB = 1; + } + + /* step 3 */ + /* evaluate flag result and go on if necessary */ + if (!flagA && !flagB) { + ClearBitFromBitfield( + &(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off + statemachine */ + } else { + /* at least one of two lines is 16 */ + /* store both flags at correct positions in non PCW codeword sideinfo + * pEscapeSequenceInfo[codewordOffset] */ + flags = flagA << POSITION_OF_FLAG_A; + flags |= (flagB << POSITION_OF_FLAG_B); + pEscapeSequenceInfo[codewordOffset] = flags; + + /* set next state */ + pSta[codewordOffset] = BODY_SIGN_ESC__ESC_PREFIX; + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from + separate array of + cw-sideinfo */ + + /* set result pointer to the first line of the two decoded lines */ + iResultPointer[codewordOffset] = iNode[codewordOffset]; + + if (!flagA && flagB) { + /* update pResultPointr ==> state Stat_BODY_SIGN_ESC__ESC_WORD writes + * to correct position. Second value is the one and only escape value + */ + iQSC = iResultPointer[codewordOffset]; + iQSC++; + iResultPointer[codewordOffset] = iQSC; + } + + } /* at least one of two lines is 16 */ + break; /* nonPCW-Body at cb 11 and according sign bits are decoded */ + + } /* if ( cntSign == 0 ) */ + } /* loop over remaining Bits in segment */ + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__SIGN; + return BODY_SIGN_ESC__SIGN; + } + } + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: Decode escape prefix of first or second escape sequence. The +escape prefix consists of ones. The following zero is also decoded here. +----------------------------------------------------------------------------------------------- + output: If the single separator-zero which follows the +escape-prefix-ones is not yet decoded: The value 'escapePrefixUp' in word +pEscapeSequenceInfo[codewordOffset] is updated. + + If the single separator-zero which follows the +escape-prefix-ones is decoded: Two updated values 'escapePrefixUp' and +'escapePrefixDown' in word pEscapeSequenceInfo[codewordOffset]. This State is +finished. Switch to next state. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT segmentOffset; + UINT *pEscapeSequenceInfo; + UINT codewordOffset; + UCHAR carryBit; + UINT escapePrefixUp; + SCHAR *pSta; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + escapePrefixUp = + (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_UP) >> + LSB_ESCAPE_PREFIX_UP; + + /* decode escape prefix */ + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + /* count ones and store sum in escapePrefixUp */ + if (carryBit == 1) { + escapePrefixUp += 1; /* update conter for ones */ + if (escapePrefixUp > 8) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX; + return BODY_SIGN_ESC__ESC_PREFIX; + } + + /* store updated counter in sideinfo of current codeword */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_PREFIX_UP; /* delete old escapePrefixUp */ + escapePrefixUp <<= LSB_ESCAPE_PREFIX_UP; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= + escapePrefixUp; /* insert new escapePrefixUp */ + escapePrefixUp >>= LSB_ESCAPE_PREFIX_UP; /* shift back down */ + } else { /* separator [zero] reached */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + escapePrefixUp += + 4; /* if escape_separator '0' appears, add 4 and ==> break */ + + /* store escapePrefixUp in pEscapeSequenceInfo[codewordOffset] at bit + * position escapePrefixUp */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_PREFIX_UP; /* delete old escapePrefixUp */ + escapePrefixUp <<= LSB_ESCAPE_PREFIX_UP; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= + escapePrefixUp; /* insert new escapePrefixUp */ + escapePrefixUp >>= LSB_ESCAPE_PREFIX_UP; /* shift back down */ + + /* store escapePrefixUp in pEscapeSequenceInfo[codewordOffset] at bit + * position escapePrefixDown */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_PREFIX_DOWN; /* delete old escapePrefixDown */ + escapePrefixUp <<= LSB_ESCAPE_PREFIX_DOWN; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= + escapePrefixUp; /* insert new escapePrefixDown */ + + pSta[codewordOffset] = BODY_SIGN_ESC__ESC_WORD; /* set next state */ + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from separate + array of cw-sideinfo */ + break; + } + } + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX; + return BODY_SIGN_ESC__ESC_PREFIX; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: Decode escapeWord of escape sequence. If the escape sequence +is decoded completely, assemble quantized-spectral-escape-coefficient and +replace the previous decoded 16 by the new value. Test flagB. If flagB is set, +the second escape sequence must be decoded. If flagB is not set, the codeword is +decoded and the state machine is switched off. +----------------------------------------------------------------------------------------------- + output: Two lines with valid sign. At least one of both lines has got +the correct value. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN_ESC__ESC_WORD(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT *pEscapeSequenceInfo; + UINT codewordOffset; + + UINT escapeWord; + UINT escapePrefixDown; + UINT escapePrefixUp; + UCHAR carryBit; + UINT iQSC; + INT sign; + UINT flagA; + UINT flagB; + SCHAR *pSta; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + escapeWord = pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_WORD; + escapePrefixDown = + (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_DOWN) >> + LSB_ESCAPE_PREFIX_DOWN; + + /* decode escape word */ + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + /* build escape word */ + escapeWord <<= + 1; /* left shift previous decoded part of escapeWord by on bit */ + escapeWord = escapeWord | carryBit; /* assemble escape word by bitwise or */ + + /* decrement counter for length of escape word because one more bit was + * decoded */ + escapePrefixDown -= 1; + + /* store updated escapePrefixDown */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_PREFIX_DOWN; /* delete old escapePrefixDown */ + escapePrefixDown <<= LSB_ESCAPE_PREFIX_DOWN; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= + escapePrefixDown; /* insert new escapePrefixDown */ + escapePrefixDown >>= LSB_ESCAPE_PREFIX_DOWN; /* shift back */ + + /* store updated escapeWord */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_WORD; /* delete old escapeWord */ + pEscapeSequenceInfo[codewordOffset] |= + escapeWord; /* insert new escapeWord */ + + if (escapePrefixDown == 0) { + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + + /* escape sequence decoded. Assemble escape-line and replace original line + */ + + /* step 0 */ + /* derive sign */ + iQSC = iResultPointer[codewordOffset]; + sign = (pResultBase[iQSC] >= (FIXP_DBL)0) + ? 1 + : -1; /* get sign of escape value 16 */ + + /* step 1 */ + /* get escapePrefixUp */ + escapePrefixUp = + (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_UP) >> + LSB_ESCAPE_PREFIX_UP; + + /* step 2 */ + /* calculate escape value */ + pResultBase[iQSC] = + (FIXP_DBL)(sign * (((INT)1 << escapePrefixUp) + (INT)escapeWord)); + + /* get both flags from sideinfo (flags are not shifted to the + * lsb-position) */ + flagA = pEscapeSequenceInfo[codewordOffset] & MASK_FLAG_A; + flagB = pEscapeSequenceInfo[codewordOffset] & MASK_FLAG_B; + + /* step 3 */ + /* clear the whole escape sideinfo word */ + pEscapeSequenceInfo[codewordOffset] = 0; + + /* change state in dependence of flag flagB */ + if (flagA != 0) { + /* first escape sequence decoded; previous decoded 16 has been replaced + * by valid line */ + + /* clear flagA in sideinfo word because this escape sequence has already + * beed decoded */ + pEscapeSequenceInfo[codewordOffset] &= ~MASK_FLAG_A; + + if (flagB == 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield + and switch off + statemachine */ + } else { + /* updated pointer to next and last 16 */ + iQSC++; + iResultPointer[codewordOffset] = iQSC; + + /* change state */ + pSta[codewordOffset] = BODY_SIGN_ESC__ESC_PREFIX; + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from + separate array of + cw-sideinfo */ + } + } else { + ClearBitFromBitfield( + &(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off + statemachine */ + } + break; + } + } + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_WORD; + return BODY_SIGN_ESC__ESC_WORD; + } + } + + return STOP_THIS_STATE; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcrs.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcrs.h new file mode 100644 index 0000000000000..acb2f40c9f444 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_hcrs.h @@ -0,0 +1,176 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Defines of state-constants, masks and + state-prototypes + +*******************************************************************************/ + +#ifndef AACDEC_HCRS_H +#define AACDEC_HCRS_H + +#include "FDK_bitstream.h" +#include "aacdec_hcr_types.h" +/* The four different kinds of types of states are: */ +/* different states are defined as constants */ /* start middle=self next + stop */ +#define STOP_THIS_STATE \ + 0 /* */ +#define BODY_ONLY \ + 1 /* X X X */ +#define BODY_SIGN__BODY \ + 2 /* X X X X [stop if no sign] */ +#define BODY_SIGN__SIGN \ + 3 /* X X [stop if sign bits decoded] */ +#define BODY_SIGN_ESC__BODY \ + 4 /* X X X X [stop if no sign] */ +#define BODY_SIGN_ESC__SIGN \ + 5 /* X X X [stop if no escape sequence] */ +#define BODY_SIGN_ESC__ESC_PREFIX \ + 6 /* X X */ +#define BODY_SIGN_ESC__ESC_WORD \ + 7 /* X X X [stop if abs(second qsc) != 16] */ + +/* examples: */ + +/* BODY_ONLY means only the codeword body will be decoded; no + * sign bits will follow and no escapesequence will follow */ + +/* BODY_SIGN__BODY means that the codeword consists of two parts; + * body and sign part. The part '__BODY' after the two underscores shows */ +/* that the bits which are currently decoded belong + * to the '__BODY' of the codeword and not to the sign part. */ + +/* BODY_SIGN_ESC__ESC_PB means that the codeword consists of three parts; + * body, sign and (here: two) escape sequences; */ +/* P = Prefix = ones */ +/* W = Escape Word */ +/* A = first possible (of two) Escape sequeces */ +/* B = second possible (of two) Escape sequeces */ +/* The part after the two underscores shows that + * the current bits which are decoded belong to the '__ESC_PB' - part of the */ +/* codeword. That means the body and the sign bits + * are decoded completely and the bits which are decoded now belong to */ +/* the escape sequence [P = prefix; B=second + * possible escape sequence] */ + +#define MSB_31_MASK 0x80000000 /* masks MSB (= Bit 31) in a 32 bit word */ +#define DIMENSION_OF_ESCAPE_CODEBOOK 2 /* for cb >= 11 is dimension 2 */ +#define ESCAPE_CODEBOOK 11 + +#define MASK_ESCAPE_PREFIX_UP 0x000F0000 +#define LSB_ESCAPE_PREFIX_UP 16 + +#define MASK_ESCAPE_PREFIX_DOWN 0x0000F000 +#define LSB_ESCAPE_PREFIX_DOWN 12 + +#define MASK_ESCAPE_WORD 0x00000FFF +#define MASK_FLAG_A 0x00200000 +#define MASK_FLAG_B 0x00100000 + +extern void DecodeNonPCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO hHcr); + +UINT Hcr_State_BODY_ONLY(HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN__BODY(HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN__SIGN(HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN_ESC__BODY(HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN_ESC__SIGN(HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX(HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN_ESC__ESC_WORD(HANDLE_FDK_BITSTREAM, void*); + +#endif /* AACDEC_HCRS_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_pns.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_pns.cpp new file mode 100644 index 0000000000000..432cd4e45705c --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_pns.cpp @@ -0,0 +1,361 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: perceptual noise substitution tool + +*******************************************************************************/ + +#include "aacdec_pns.h" + +#include "aac_ram.h" +#include "aac_rom.h" +#include "channelinfo.h" +#include "block.h" +#include "FDK_bitstream.h" + +#include "genericStds.h" + +#define NOISE_OFFSET 90 /* cf. ISO 14496-3 p. 175 */ + +/*! + \brief Reset InterChannel and PNS data + + The function resets the InterChannel and PNS data +*/ +void CPns_ResetData(CPnsData *pPnsData, + CPnsInterChannelData *pPnsInterChannelData) { + FDK_ASSERT(pPnsData != NULL); + FDK_ASSERT(pPnsInterChannelData != NULL); + /* Assign pointer always, since pPnsData is not persistent data */ + pPnsData->pPnsInterChannelData = pPnsInterChannelData; + pPnsData->PnsActive = 0; + pPnsData->CurrentEnergy = 0; + + FDKmemclear(pPnsData->pnsUsed, (8 * 16) * sizeof(UCHAR)); + FDKmemclear(pPnsInterChannelData->correlated, (8 * 16) * sizeof(UCHAR)); +} + +/*! + \brief Update PNS noise generator state. + + The function sets the seed for PNS noise generation. + It can be used to link two or more channels in terms of PNS. +*/ +void CPns_UpdateNoiseState(CPnsData *pPnsData, INT *currentSeed, + INT *randomSeed) { + /* use pointer because seed has to be + same, left and right channel ! */ + pPnsData->currentSeed = currentSeed; + pPnsData->randomSeed = randomSeed; +} + +/*! + \brief Indicates if PNS is used + + The function returns a value indicating whether PNS is used or not + acordding to the noise energy + + \return PNS used +*/ +int CPns_IsPnsUsed(const CPnsData *pPnsData, const int group, const int band) { + unsigned pns_band = group * 16 + band; + + return pPnsData->pnsUsed[pns_band] & (UCHAR)1; +} + +/*! + \brief Set correlation + + The function activates the noise correlation between the channel pair +*/ +void CPns_SetCorrelation(CPnsData *pPnsData, const int group, const int band, + const int outofphase) { + CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData; + unsigned pns_band = group * 16 + band; + + pInterChannelData->correlated[pns_band] = (outofphase) ? 3 : 1; +} + +/*! + \brief Indicates if correlation is used + + The function indicates if the noise correlation between the channel pair + is activated + + \return PNS is correlated +*/ +static int CPns_IsCorrelated(const CPnsData *pPnsData, const int group, + const int band) { + CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData; + unsigned pns_band = group * 16 + band; + + return (pInterChannelData->correlated[pns_band] & 0x01) ? 1 : 0; +} + +/*! + \brief Indicates if correlated out of phase mode is used. + + The function indicates if the noise correlation between the channel pair + is activated in out-of-phase mode. + + \return PNS is out-of-phase +*/ +static int CPns_IsOutOfPhase(const CPnsData *pPnsData, const int group, + const int band) { + CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData; + unsigned pns_band = group * 16 + band; + + return (pInterChannelData->correlated[pns_band] & 0x02) ? 1 : 0; +} + +/*! + \brief Read PNS information + + The function reads the PNS information from the bitstream +*/ +void CPns_Read(CPnsData *pPnsData, HANDLE_FDK_BITSTREAM bs, + const CodeBookDescription *hcb, SHORT *pScaleFactor, + UCHAR global_gain, int band, int group /* = 0 */) { + int delta; + UINT pns_band = group * 16 + band; + + if (pPnsData->PnsActive) { + /* Next PNS band case */ + delta = CBlock_DecodeHuffmanWord(bs, hcb) - 60; + } else { + /* First PNS band case */ + int noiseStartValue = FDKreadBits(bs, 9); + + delta = noiseStartValue - 256; + pPnsData->PnsActive = 1; + pPnsData->CurrentEnergy = global_gain - NOISE_OFFSET; + } + + pPnsData->CurrentEnergy += delta; + pScaleFactor[pns_band] = pPnsData->CurrentEnergy; + + pPnsData->pnsUsed[pns_band] = 1; +} + +/** + * \brief Generate a vector of noise of given length. The noise values are + * scaled in order to yield a noise energy of 1.0 + * \param spec pointer to were the noise values will be written to. + * \param size amount of noise values to be generated. + * \param pRandomState pointer to the state of the random generator being used. + * \return exponent of generated noise vector. + */ +static int GenerateRandomVector(FIXP_DBL *RESTRICT spec, int size, + int *pRandomState) { + int i, invNrg_e = 0, nrg_e = 0; + FIXP_DBL invNrg_m, nrg_m = FL2FXCONST_DBL(0.0f); + FIXP_DBL *RESTRICT ptr = spec; + int randomState = *pRandomState; + +#define GEN_NOISE_NRG_SCALE 7 + + /* Generate noise and calculate energy. */ + for (i = 0; i < size; i++) { + randomState = + (((INT64)1664525 * randomState) + (INT64)1013904223) & 0xFFFFFFFF; + nrg_m = fPow2AddDiv2(nrg_m, (FIXP_DBL)randomState >> GEN_NOISE_NRG_SCALE); + *ptr++ = (FIXP_DBL)randomState; + } + nrg_e = GEN_NOISE_NRG_SCALE * 2 + 1; + + /* weight noise with = 1 / sqrt_nrg; */ + invNrg_m = invSqrtNorm2(nrg_m << 1, &invNrg_e); + invNrg_e += -((nrg_e - 1) >> 1); + + for (i = size; i--;) { + spec[i] = fMult(spec[i], invNrg_m); + } + + /* Store random state */ + *pRandomState = randomState; + + return invNrg_e; +} + +static void ScaleBand(FIXP_DBL *RESTRICT spec, int size, int scaleFactor, + int specScale, int noise_e, int out_of_phase) { + int i, shift, sfExponent; + FIXP_DBL sfMatissa; + + /* Get gain from scale factor value = 2^(scaleFactor * 0.25) */ + sfMatissa = MantissaTable[scaleFactor & 0x03][0]; + /* sfExponent = (scaleFactor >> 2) + ExponentTable[scaleFactor & 0x03][0]; */ + /* Note: ExponentTable[scaleFactor & 0x03][0] is always 1. */ + sfExponent = (scaleFactor >> 2) + 1; + + if (out_of_phase != 0) { + sfMatissa = -sfMatissa; + } + + /* +1 because of fMultDiv2 below. */ + shift = sfExponent - specScale + 1 + noise_e; + + /* Apply gain to noise values */ + if (shift >= 0) { + shift = fixMin(shift, DFRACT_BITS - 1); + for (i = size; i-- != 0;) { + spec[i] = fMultDiv2(spec[i], sfMatissa) << shift; + } + } else { + shift = fixMin(-shift, DFRACT_BITS - 1); + for (i = size; i-- != 0;) { + spec[i] = fMultDiv2(spec[i], sfMatissa) >> shift; + } + } +} + +/*! + \brief Apply PNS + + The function applies PNS (i.e. it generates noise) on the bands + flagged as noisy bands + +*/ +void CPns_Apply(const CPnsData *pPnsData, const CIcsInfo *pIcsInfo, + SPECTRAL_PTR pSpectrum, const SHORT *pSpecScale, + const SHORT *pScaleFactor, + const SamplingRateInfo *pSamplingRateInfo, + const INT granuleLength, const int channel) { + if (pPnsData->PnsActive) { + const short *BandOffsets = + GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo); + + int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(pIcsInfo); + + for (int window = 0, group = 0; group < GetWindowGroups(pIcsInfo); + group++) { + for (int groupwin = 0; groupwin < GetWindowGroupLength(pIcsInfo, group); + groupwin++, window++) { + FIXP_DBL *spectrum = SPEC(pSpectrum, window, granuleLength); + + for (int band = 0; band < ScaleFactorBandsTransmitted; band++) { + if (CPns_IsPnsUsed(pPnsData, group, band)) { + UINT pns_band = window * 16 + band; + + int bandWidth = BandOffsets[band + 1] - BandOffsets[band]; + int noise_e; + + FDK_ASSERT(bandWidth >= 0); + + if (channel > 0 && CPns_IsCorrelated(pPnsData, group, band)) { + noise_e = + GenerateRandomVector(spectrum + BandOffsets[band], bandWidth, + &pPnsData->randomSeed[pns_band]); + } else { + pPnsData->randomSeed[pns_band] = *pPnsData->currentSeed; + + noise_e = GenerateRandomVector(spectrum + BandOffsets[band], + bandWidth, pPnsData->currentSeed); + } + + int outOfPhase = CPns_IsOutOfPhase(pPnsData, group, band); + + ScaleBand(spectrum + BandOffsets[band], bandWidth, + pScaleFactor[group * 16 + band], pSpecScale[window], + noise_e, outOfPhase); + } + } + } + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_pns.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_pns.h new file mode 100644 index 0000000000000..45cd989309341 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_pns.h @@ -0,0 +1,129 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: perceptual noise substitution tool + +*******************************************************************************/ + +#ifndef AACDEC_PNS_H +#define AACDEC_PNS_H + +#include "common_fix.h" + +#define NO_OFBANDS ((8 * 16)) + +typedef struct { + UCHAR correlated[NO_OFBANDS]; +} CPnsInterChannelData; + +typedef struct { + CPnsInterChannelData *pPnsInterChannelData; + UCHAR pnsUsed[NO_OFBANDS]; + int CurrentEnergy; + UCHAR PnsActive; + INT *currentSeed; + INT *randomSeed; +} CPnsData; + +void CPns_UpdateNoiseState(CPnsData *pPnsData, INT *currentSeed, + INT *randomSeed); + +void CPns_ResetData(CPnsData *pPnsData, + CPnsInterChannelData *pPnsInterChannelData); + +#endif /* #ifndef AACDEC_PNS_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_tns.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_tns.cpp new file mode 100644 index 0000000000000..fb3fe33893812 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_tns.cpp @@ -0,0 +1,361 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: temporal noise shaping tool + +*******************************************************************************/ + +#include "aacdec_tns.h" +#include "aac_rom.h" +#include "FDK_bitstream.h" +#include "channelinfo.h" + +#include "FDK_lpc.h" + +#define TNS_MAXIMUM_ORDER_AAC 12 + +/*! + \brief Reset tns data + + The function resets the tns data + + \return none +*/ +void CTns_Reset(CTnsData *pTnsData) { + /* Note: the following FDKmemclear should not be required. */ + FDKmemclear(pTnsData->Filter, + TNS_MAX_WINDOWS * TNS_MAXIMUM_FILTERS * sizeof(CFilter)); + FDKmemclear(pTnsData->NumberOfFilters, TNS_MAX_WINDOWS * sizeof(UCHAR)); + pTnsData->DataPresent = 0; + pTnsData->Active = 0; +} + +void CTns_ReadDataPresentFlag( + HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */ + CTnsData *pTnsData) /*!< pointer to aac decoder channel info */ +{ + pTnsData->DataPresent = (UCHAR)FDKreadBits(bs, 1); +} + +/*! + \brief Read tns data from bitstream + + The function reads the elements for tns from + the bitstream. + + \return none +*/ +AAC_DECODER_ERROR CTns_Read(HANDLE_FDK_BITSTREAM bs, CTnsData *pTnsData, + const CIcsInfo *pIcsInfo, const UINT flags) { + UCHAR n_filt, order; + UCHAR length, coef_res, coef_compress; + UCHAR window; + UCHAR wins_per_frame; + UCHAR isLongFlag; + UCHAR start_window; + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + if (!pTnsData->DataPresent) { + return ErrorStatus; + } + + { + start_window = 0; + wins_per_frame = GetWindowsPerFrame(pIcsInfo); + isLongFlag = IsLongBlock(pIcsInfo); + } + + pTnsData->GainLd = 0; + + for (window = start_window; window < wins_per_frame; window++) { + pTnsData->NumberOfFilters[window] = n_filt = + (UCHAR)FDKreadBits(bs, isLongFlag ? 2 : 1); + + if (n_filt) { + int index; + UCHAR nextstopband; + + coef_res = (UCHAR)FDKreadBits(bs, 1); + + nextstopband = GetScaleFactorBandsTotal(pIcsInfo); + + for (index = 0; index < n_filt; index++) { + CFilter *filter = &pTnsData->Filter[window][index]; + + length = (UCHAR)FDKreadBits(bs, isLongFlag ? 6 : 4); + + if (length > nextstopband) { + length = nextstopband; + } + + filter->StartBand = nextstopband - length; + filter->StopBand = nextstopband; + nextstopband = filter->StartBand; + + if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) { + /* max(Order) = 15 (long), 7 (short) */ + filter->Order = order = (UCHAR)FDKreadBits(bs, isLongFlag ? 4 : 3); + } else { + filter->Order = order = (UCHAR)FDKreadBits(bs, isLongFlag ? 5 : 3); + + if (filter->Order > TNS_MAXIMUM_ORDER) { + ErrorStatus = AAC_DEC_TNS_READ_ERROR; + return ErrorStatus; + } + } + + FDK_ASSERT(order <= + TNS_MAXIMUM_ORDER); /* avoid illegal memory access */ + if (order) { + UCHAR coef, s_mask; + UCHAR i; + SCHAR n_mask; + + static const UCHAR sgn_mask[] = {0x2, 0x4, 0x8}; + static const SCHAR neg_mask[] = {~0x3, ~0x7, ~0xF}; + + filter->Direction = FDKreadBits(bs, 1) ? -1 : 1; + + coef_compress = (UCHAR)FDKreadBits(bs, 1); + + filter->Resolution = coef_res + 3; + + s_mask = sgn_mask[coef_res + 1 - coef_compress]; + n_mask = neg_mask[coef_res + 1 - coef_compress]; + + for (i = 0; i < order; i++) { + coef = (UCHAR)FDKreadBits(bs, filter->Resolution - coef_compress); + filter->Coeff[i] = (coef & s_mask) ? (coef | n_mask) : coef; + } + pTnsData->GainLd = 4; + } + } + } + } + + pTnsData->Active = 1; + + return ErrorStatus; +} + +void CTns_ReadDataPresentUsac(HANDLE_FDK_BITSTREAM hBs, CTnsData *pTnsData0, + CTnsData *pTnsData1, UCHAR *ptns_on_lr, + const CIcsInfo *pIcsInfo, const UINT flags, + const UINT elFlags, const int fCommonWindow) { + int common_tns = 0; + + if (fCommonWindow) { + common_tns = FDKreadBit(hBs); + } + { *ptns_on_lr = FDKreadBit(hBs); } + if (common_tns) { + pTnsData0->DataPresent = 1; + CTns_Read(hBs, pTnsData0, pIcsInfo, flags); + + pTnsData0->DataPresent = 0; + pTnsData0->Active = 1; + *pTnsData1 = *pTnsData0; + } else { + int tns_present_both; + + tns_present_both = FDKreadBit(hBs); + if (tns_present_both) { + pTnsData0->DataPresent = 1; + pTnsData1->DataPresent = 1; + } else { + pTnsData1->DataPresent = FDKreadBit(hBs); + pTnsData0->DataPresent = !pTnsData1->DataPresent; + } + } +} + +/*! + \brief Apply tns to spectral lines + + The function applies the tns to the spectrum, + + \return none +*/ +void CTns_Apply(CTnsData *RESTRICT pTnsData, /*!< pointer to aac decoder info */ + const CIcsInfo *pIcsInfo, SPECTRAL_PTR pSpectralCoefficient, + const SamplingRateInfo *pSamplingRateInfo, + const INT granuleLength, const UCHAR nbands, + const UCHAR igf_active, const UINT flags) { + int window, index, start, stop, size, start_window, wins_per_frame; + + if (pTnsData->Active) { + C_AALLOC_SCRATCH_START(coeff, FIXP_TCC, TNS_MAXIMUM_ORDER) + + { + start_window = 0; + wins_per_frame = GetWindowsPerFrame(pIcsInfo); + } + + for (window = start_window; window < wins_per_frame; window++) { + FIXP_DBL *pSpectrum; + + { pSpectrum = SPEC(pSpectralCoefficient, window, granuleLength); } + + for (index = 0; index < pTnsData->NumberOfFilters[window]; index++) { + CFilter *filter = &pTnsData->Filter[window][index]; + + if (filter->Order > 0) { + FIXP_TCC *pCoeff; + UCHAR tns_max_bands; + + pCoeff = coeff; + if (filter->Resolution == 3) { + int i; + for (i = 0; i < filter->Order; i++) + *pCoeff++ = FDKaacDec_tnsCoeff3[filter->Coeff[i] + 4]; + } else { + int i; + for (i = 0; i < filter->Order; i++) + *pCoeff++ = FDKaacDec_tnsCoeff4[filter->Coeff[i] + 8]; + } + + switch (granuleLength) { + case 480: + tns_max_bands = + tns_max_bands_tbl_480[pSamplingRateInfo->samplingRateIndex]; + break; + case 512: + tns_max_bands = + tns_max_bands_tbl_512[pSamplingRateInfo->samplingRateIndex]; + break; + default: + tns_max_bands = GetMaximumTnsBands( + pIcsInfo, pSamplingRateInfo->samplingRateIndex); + /* See redefinition of TNS_MAX_BANDS table */ + if ((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && + (pSamplingRateInfo->samplingRateIndex > 5)) { + tns_max_bands += 1; + } + break; + } + + start = fixMin(fixMin(filter->StartBand, tns_max_bands), nbands); + + start = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo)[start]; + + if (igf_active) { + stop = fixMin(filter->StopBand, nbands); + } else { + stop = fixMin(fixMin(filter->StopBand, tns_max_bands), nbands); + } + + stop = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo)[stop]; + + size = stop - start; + + if (size) { + C_ALLOC_SCRATCH_START(state, FIXP_DBL, TNS_MAXIMUM_ORDER) + + FDKmemclear(state, TNS_MAXIMUM_ORDER * sizeof(FIXP_DBL)); + CLpc_SynthesisLattice(pSpectrum + start, size, 0, 0, + filter->Direction, coeff, filter->Order, + state); + + C_ALLOC_SCRATCH_END(state, FIXP_DBL, TNS_MAXIMUM_ORDER) + } + } + } + } + C_AALLOC_SCRATCH_END(coeff, FIXP_TCC, TNS_MAXIMUM_ORDER) + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_tns.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_tns.h new file mode 100644 index 0000000000000..1a63bed5bd7c8 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdec_tns.h @@ -0,0 +1,149 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: temporal noise shaping tool + +*******************************************************************************/ + +#ifndef AACDEC_TNS_H +#define AACDEC_TNS_H + +#include "common_fix.h" + +enum { + TNS_MAX_WINDOWS = 8, /* 8 */ + TNS_MAXIMUM_FILTERS = 3 +}; + +/* TNS_MAXIMUM_ORDER (for memory allocation) + 12 for AAC-LC and AAC-SSR. Set to 20 for AAC-Main (AOT 1). Some broken + encoders also do order 20 for AAC-LC :( 15 for USAC (AOT 42) +*/ +#define TNS_MAXIMUM_ORDER (20) + +#if (TNS_MAXIMUM_ORDER < 15) +#error USAC: TNS filter order up 15 can be signaled! +#endif + +typedef struct { + SCHAR Coeff[TNS_MAXIMUM_ORDER]; + + UCHAR StartBand; + UCHAR StopBand; + + SCHAR Direction; + SCHAR Resolution; + + UCHAR Order; +} CFilter; + +typedef struct { + CFilter Filter[TNS_MAX_WINDOWS][TNS_MAXIMUM_FILTERS]; + UCHAR NumberOfFilters[TNS_MAX_WINDOWS]; + UCHAR DataPresent; + UCHAR Active; + + /* log2 of the maximum total filter gains. The value is required to + keep necessary mantissa headroom so that while applying the TNS predictor + the mantissas do not overflow. */ + UCHAR GainLd; +} CTnsData; + +void CTns_Reset(CTnsData *pTnsData); + +#endif /* #ifndef AACDEC_TNS_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdecoder.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdecoder.cpp new file mode 100644 index 0000000000000..ad8ce0d962cbe --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdecoder.cpp @@ -0,0 +1,3590 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +/*! + \page default General Overview of the AAC Decoder Implementation + + The main entry point to decode a AAC frame is CAacDecoder_DecodeFrame(). It + handles the different transport multiplexes and bitstream formats supported by + this implementation. It extracts the AAC_raw_data_blocks from these bitstreams + to further process then in the actual decoding stages. + + Note: Click on a function of file in the above image to see details about the + function. Also note, that this is just an overview of the most important + functions and not a complete call graph. + +

1 Bitstream deformatter

+ The basic bit stream parser function CChannelElement_Read() is called. It uses + other subcalls in order to parse and unpack the bitstreams. Note, that this + includes huffmann decoding of the coded spectral data. This operation can be + computational significant specifically at higher bitrates. Optimization is + likely in CBlock_ReadSpectralData(). + + The bitstream deformatter also includes many bitfield operations. Profiling on + the target will determine required optimizations. + +

2 Actual decoding to retain the time domain output

+ The basic bitstream deformatter function CChannelElement_Decode() for CPE + elements and SCE elements are called. Except for the stereo processing (2.1) + which is only used for CPE elements, the function calls for CPE or SCE are + similar, except that CPE always processes to independent channels while SCE + only processes one channel. + + Often there is the distinction between long blocks and short blocks. However, + computational expensive functions that ususally require optimization are being + shared by these two groups, + +

2.1 Stereo processing for CPE elements

+ CChannelPairElement_Decode() first calles the joint stereo tools in + stereo.cpp when required. + +

2.2 Scaling of spectral data

+ CBlock_ScaleSpectralData(). + +

2.3 Apply additional coding tools

+ ApplyTools() calles the PNS tools in case of MPEG-4 bitstreams, and TNS + filtering CTns_Apply() for MPEG-2 and MPEG-4 bitstreams. The function + TnsFilterIIR() which is called by CTns_Apply() (2.3.1) might require some + optimization. + +

3 Frequency-To-Time conversion

+ The filterbank is called using CBlock_FrequencyToTime() using the MDCT module + from the FDK Tools + +*/ + +#include "aacdecoder.h" + +#include "aac_rom.h" +#include "aac_ram.h" +#include "channel.h" +#include "FDK_audio.h" + +#include "aacdec_pns.h" + +#include "sbrdecoder.h" + +#include "sac_dec_lib.h" + +#include "aacdec_hcr.h" +#include "rvlc.h" + +#include "usacdec_lpd.h" + +#include "ac_arith_coder.h" + +#include "tpdec_lib.h" + +#include "conceal.h" + +#include "FDK_crc.h" +#define PS_IS_EXPLICITLY_DISABLED(aot, flags) \ + (((aot) == AOT_DRM_AAC) && !(flags & AC_PS_PRESENT)) + +#define IS_STEREO_SBR(el_id, stereoConfigIndex) \ + (((el_id) == ID_USAC_CPE && (stereoConfigIndex) == 0) || \ + ((el_id) == ID_USAC_CPE && (stereoConfigIndex) == 3)) + +void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self) { + FDK_ASSERT( + !((self->flags[0] & AC_MPS_PRESENT) && (self->flags[0] & AC_PS_PRESENT))); + + /* Assign user requested mode */ + self->qmfModeCurr = self->qmfModeUser; + + if (IS_USAC(self->streamInfo.aot)) { + self->qmfModeCurr = MODE_HQ; + } + + if (self->qmfModeCurr == NOT_DEFINED) { + if ((IS_LOWDELAY(self->streamInfo.aot) && + (self->flags[0] & AC_MPS_PRESENT)) || + ((self->streamInfo.aacNumChannels == 1) && + ((CAN_DO_PS(self->streamInfo.aot) && + !(self->flags[0] & AC_MPS_PRESENT)) || + (IS_USAC(self->streamInfo.aot))))) { + self->qmfModeCurr = MODE_HQ; + } else { + self->qmfModeCurr = MODE_LP; + } + } + + if (self->mpsEnableCurr) { + if (IS_LOWDELAY(self->streamInfo.aot) && + (self->qmfModeCurr == MODE_LP)) { /* Overrule user requested QMF mode */ + self->qmfModeCurr = MODE_HQ; + } + /* Set and check if MPS decoder allows the current mode */ + switch (mpegSurroundDecoder_SetParam( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, + SACDEC_PARTIALLY_COMPLEX, self->qmfModeCurr == MODE_LP)) { + case MPS_OK: + break; + case MPS_INVALID_PARAMETER: { /* Only one mode supported. Find out which + one: */ + LIB_INFO libInfo[FDK_MODULE_LAST]; + UINT mpsCaps; + + FDKinitLibInfo(libInfo); + mpegSurroundDecoder_GetLibInfo(libInfo); + mpsCaps = FDKlibInfo_getCapabilities(libInfo, FDK_MPSDEC); + + if (((mpsCaps & CAPF_MPS_LP) && (self->qmfModeCurr == MODE_LP)) || + ((mpsCaps & CAPF_MPS_HQ) && + (self->qmfModeCurr == + MODE_HQ))) { /* MPS decoder does support the requested mode. */ + break; + } + } + FDK_FALLTHROUGH; + default: + if (self->qmfModeUser == NOT_DEFINED) { + /* Revert in case mpegSurroundDecoder_SetParam() fails. */ + self->qmfModeCurr = + (self->qmfModeCurr == MODE_LP) ? MODE_HQ : MODE_LP; + } else { + /* in case specific mode was requested we disable MPS and playout the + * downmix */ + self->mpsEnableCurr = 0; + } + } + } + + /* Set SBR to current QMF mode. Error does not matter. */ + sbrDecoder_SetParam(self->hSbrDecoder, SBR_QMF_MODE, + (self->qmfModeCurr == MODE_LP)); + self->psPossible = + ((CAN_DO_PS(self->streamInfo.aot) && + !PS_IS_EXPLICITLY_DISABLED(self->streamInfo.aot, self->flags[0]) && + self->streamInfo.aacNumChannels == 1 && + !(self->flags[0] & AC_MPS_PRESENT))) && + self->qmfModeCurr == MODE_HQ; + FDK_ASSERT(!((self->flags[0] & AC_MPS_PRESENT) && self->psPossible)); +} + +void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self) { + if (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) { + int i; + + for (i = 0; i < fMin(self->aacChannels, (8)); i++) { + if (self->pAacDecoderStaticChannelInfo + [i]) { /* number of active channels can be smaller */ + self->pAacDecoderStaticChannelInfo[i]->hArCo->m_numberLinesPrev = 0; + } + } + } +} + +/*! + \brief Calculates the number of element channels + + \type channel type + \usacStereoConfigIndex usac stereo config index + + \return element channels +*/ +static int CAacDecoder_GetELChannels(MP4_ELEMENT_ID type, + UCHAR usacStereoConfigIndex) { + int el_channels = 0; + + switch (type) { + case ID_USAC_CPE: + if (usacStereoConfigIndex == 1) { + el_channels = 1; + } else { + el_channels = 2; + } + break; + case ID_CPE: + el_channels = 2; + break; + case ID_USAC_SCE: + case ID_USAC_LFE: + case ID_SCE: + case ID_LFE: + el_channels = 1; + break; + default: + el_channels = 0; + break; + } + + return el_channels; +} + +/*! + \brief Reset ancillary data struct. Call before parsing a new frame. + + \ancData Pointer to ancillary data structure + + \return Error code +*/ +static AAC_DECODER_ERROR CAacDecoder_AncDataReset(CAncData *ancData) { + int i; + for (i = 0; i < 8; i++) { + ancData->offset[i] = 0; + } + ancData->nrElements = 0; + + return AAC_DEC_OK; +} + +/*! + \brief Initialize ancillary buffer + + \ancData Pointer to ancillary data structure + \buffer Pointer to (external) anc data buffer + \size Size of the buffer pointed on by buffer in bytes + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData, + unsigned char *buffer, int size) { + if (size >= 0) { + ancData->buffer = buffer; + ancData->bufferSize = size; + + CAacDecoder_AncDataReset(ancData); + + return AAC_DEC_OK; + } + + return AAC_DEC_ANC_DATA_ERROR; +} + +/*! + \brief Get one ancillary data element + + \ancData Pointer to ancillary data structure + \index Index of the anc data element to get + \ptr Pointer to a buffer receiving a pointer to the requested anc data element + \size Pointer to a buffer receiving the length of the requested anc data + element in bytes + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index, + unsigned char **ptr, int *size) { + AAC_DECODER_ERROR error = AAC_DEC_OK; + + *ptr = NULL; + *size = 0; + + if (index >= 0 && index < 8 - 1 && index < ancData->nrElements) { + *ptr = &ancData->buffer[ancData->offset[index]]; + *size = ancData->offset[index + 1] - ancData->offset[index]; + } + + return error; +} + +/*! + \brief Parse ancillary data + + \ancData Pointer to ancillary data structure + \hBs Handle to FDK bitstream + \ancBytes Length of ancillary data to read from the bitstream + + \return Error code +*/ +static AAC_DECODER_ERROR CAacDecoder_AncDataParse(CAncData *ancData, + HANDLE_FDK_BITSTREAM hBs, + const int ancBytes) { + AAC_DECODER_ERROR error = AAC_DEC_OK; + int readBytes = 0; + + if (ancData->buffer != NULL) { + if (ancBytes > 0) { + /* write ancillary data to external buffer */ + int offset = ancData->offset[ancData->nrElements]; + + if ((offset + ancBytes) > ancData->bufferSize) { + error = AAC_DEC_TOO_SMALL_ANC_BUFFER; + } else if (ancData->nrElements >= 8 - 1) { + error = AAC_DEC_TOO_MANY_ANC_ELEMENTS; + } else { + int i; + + for (i = 0; i < ancBytes; i++) { + ancData->buffer[i + offset] = FDKreadBits(hBs, 8); + readBytes++; + } + + ancData->nrElements++; + ancData->offset[ancData->nrElements] = + ancBytes + ancData->offset[ancData->nrElements - 1]; + } + } + } + + readBytes = ancBytes - readBytes; + + if (readBytes > 0) { + /* skip data */ + FDKpushFor(hBs, readBytes << 3); + } + + return error; +} + +/*! + \brief Read Stream Data Element + + \bs Bitstream Handle + + \return Error code +*/ +static AAC_DECODER_ERROR CDataStreamElement_Read(HANDLE_AACDECODER self, + HANDLE_FDK_BITSTREAM bs, + UCHAR *elementInstanceTag, + UINT alignmentAnchor) { + AAC_DECODER_ERROR error = AAC_DEC_OK; + UINT dseBits; + INT dataStart; + int dataByteAlignFlag, count; + + FDK_ASSERT(self != NULL); + + int crcReg = transportDec_CrcStartReg(self->hInput, 0); + + /* Element Instance Tag */ + *elementInstanceTag = FDKreadBits(bs, 4); + /* Data Byte Align Flag */ + dataByteAlignFlag = FDKreadBits(bs, 1); + + count = FDKreadBits(bs, 8); + + if (count == 255) { + count += FDKreadBits(bs, 8); /* EscCount */ + } + dseBits = count * 8; + + if (dataByteAlignFlag) { + FDKbyteAlign(bs, alignmentAnchor); + } + + dataStart = (INT)FDKgetValidBits(bs); + + error = CAacDecoder_AncDataParse(&self->ancData, bs, count); + transportDec_CrcEndReg(self->hInput, crcReg); + + { + /* Move to the beginning of the data chunk */ + FDKpushBack(bs, dataStart - (INT)FDKgetValidBits(bs)); + + /* Read Anc data if available */ + aacDecoder_drcMarkPayload(self->hDrcInfo, bs, DVB_DRC_ANC_DATA); + } + + { + PCMDMX_ERROR dmxErr = PCMDMX_OK; + + /* Move to the beginning of the data chunk */ + FDKpushBack(bs, dataStart - (INT)FDKgetValidBits(bs)); + + /* Read DMX meta-data */ + dmxErr = pcmDmx_Parse(self->hPcmUtils, bs, dseBits, 0 /* not mpeg2 */); + if (error == AAC_DEC_OK && dmxErr != PCMDMX_OK) { + error = AAC_DEC_UNKNOWN; + } + } + + /* Move to the very end of the element. */ + FDKpushBiDirectional(bs, (INT)FDKgetValidBits(bs) - dataStart + (INT)dseBits); + + return error; +} + +static INT findElementInstanceTag( + INT elementTag, MP4_ELEMENT_ID elementId, + CAacDecoderChannelInfo **pAacDecoderChannelInfo, INT nChannels, + MP4_ELEMENT_ID *pElementIdTab, INT nElements) { + int el, chCnt = 0; + + for (el = 0; el < nElements; el++) { + switch (pElementIdTab[el]) { + case ID_CPE: + case ID_SCE: + case ID_LFE: + if ((elementTag == pAacDecoderChannelInfo[chCnt]->ElementInstanceTag) && + (elementId == pElementIdTab[el])) { + return 1; /* element instance tag found */ + } + chCnt += (pElementIdTab[el] == ID_CPE) ? 2 : 1; + break; + default: + break; + } + if (chCnt >= nChannels) break; + if (pElementIdTab[el] == ID_END) break; + } + + return 0; /* element instance tag not found */ +} + +static INT validateElementInstanceTags( + CProgramConfig *pce, CAacDecoderChannelInfo **pAacDecoderChannelInfo, + INT nChannels, MP4_ELEMENT_ID *pElementIdTab, INT nElements) { + if (nChannels >= pce->NumChannels) { + for (int el = 0; el < pce->NumFrontChannelElements; el++) { + if (!findElementInstanceTag(pce->FrontElementTagSelect[el], + pce->FrontElementIsCpe[el] ? ID_CPE : ID_SCE, + pAacDecoderChannelInfo, nChannels, + pElementIdTab, nElements)) { + return 0; /* element instance tag not in raw_data_block() */ + } + } + for (int el = 0; el < pce->NumSideChannelElements; el++) { + if (!findElementInstanceTag(pce->SideElementTagSelect[el], + pce->SideElementIsCpe[el] ? ID_CPE : ID_SCE, + pAacDecoderChannelInfo, nChannels, + pElementIdTab, nElements)) { + return 0; /* element instance tag not in raw_data_block() */ + } + } + for (int el = 0; el < pce->NumBackChannelElements; el++) { + if (!findElementInstanceTag(pce->BackElementTagSelect[el], + pce->BackElementIsCpe[el] ? ID_CPE : ID_SCE, + pAacDecoderChannelInfo, nChannels, + pElementIdTab, nElements)) { + return 0; /* element instance tag not in raw_data_block() */ + } + } + for (int el = 0; el < pce->NumLfeChannelElements; el++) { + if (!findElementInstanceTag(pce->LfeElementTagSelect[el], ID_LFE, + pAacDecoderChannelInfo, nChannels, + pElementIdTab, nElements)) { + return 0; /* element instance tag not in raw_data_block() */ + } + } + } else { + return 0; /* too less decoded audio channels */ + } + + return 1; /* all element instance tags found in raw_data_block() */ +} + +/*! + \brief Read Program Config Element + + \bs Bitstream Handle + \pTp Transport decoder handle for CRC handling + \pce Pointer to PCE buffer + \channelConfig Current channel configuration + \alignAnchor Anchor for byte alignment + + \return PCE status (-1: fail, 0: no new PCE, 1: PCE updated, 2: PCE updated + need re-config). +*/ +static int CProgramConfigElement_Read(HANDLE_FDK_BITSTREAM bs, + HANDLE_TRANSPORTDEC pTp, + CProgramConfig *pce, + const UINT channelConfig, + const UINT alignAnchor) { + int pceStatus = 0; + int crcReg; + + /* read PCE to temporal buffer first */ + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + + CProgramConfig_Init(tmpPce); + + crcReg = transportDec_CrcStartReg(pTp, 0); + + CProgramConfig_Read(tmpPce, bs, alignAnchor); + + transportDec_CrcEndReg(pTp, crcReg); + + if (CProgramConfig_IsValid(tmpPce) && (tmpPce->Profile == 1)) { + if (!CProgramConfig_IsValid(pce) && (channelConfig > 0)) { + /* Create a standard channel config PCE to compare with */ + CProgramConfig_GetDefault(pce, channelConfig); + } + + if (CProgramConfig_IsValid(pce)) { + /* Compare the new and the old PCE (tags ignored) */ + switch (CProgramConfig_Compare(pce, tmpPce)) { + case 1: /* Channel configuration not changed. Just new metadata. */ + FDKmemcpy(pce, tmpPce, + sizeof(CProgramConfig)); /* Store the complete PCE */ + pceStatus = 1; /* New PCE but no change of config */ + break; + case 2: /* The number of channels are identical but not the config */ + case -1: /* The channel configuration is completely different */ + pceStatus = -1; /* Not supported! */ + break; + case 0: /* Nothing to do because PCE matches the old one exactly. */ + default: + /* pceStatus = 0; */ + break; + } + } + } + + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + + return pceStatus; +} + +/*! + \brief Prepares crossfade for USAC DASH IPF config change + + \pTimeData Pointer to time data + \pTimeDataFlush Pointer to flushed time data + \numChannels Number of channels + \frameSize Size of frame + \interleaved Indicates if time data is interleaved + + \return Error code +*/ +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade( + const PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels, + const INT frameSize, const INT interleaved) { + int i, ch, s1, s2; + AAC_DECODER_ERROR ErrorStatus; + + ErrorStatus = AAC_DEC_OK; + + if (interleaved) { + s1 = 1; + s2 = numChannels; + } else { + s1 = frameSize; + s2 = 1; + } + + for (ch = 0; ch < numChannels; ch++) { + const PCM_DEC *pIn = &pTimeData[ch * s1]; + for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) { + pTimeDataFlush[ch][i] = *pIn; + pIn += s2; + } + } + + return ErrorStatus; +} + +/*! + \brief Applies crossfade for USAC DASH IPF config change + + \pTimeData Pointer to time data + \pTimeDataFlush Pointer to flushed time data + \numChannels Number of channels + \frameSize Size of frame + \interleaved Indicates if time data is interleaved + + \return Error code +*/ +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade( + PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels, + const INT frameSize, const INT interleaved) { + int i, ch, s1, s2; + AAC_DECODER_ERROR ErrorStatus; + + ErrorStatus = AAC_DEC_OK; + + if (interleaved) { + s1 = 1; + s2 = numChannels; + } else { + s1 = frameSize; + s2 = 1; + } + + for (ch = 0; ch < numChannels; ch++) { + PCM_DEC *pIn = &pTimeData[ch * s1]; + for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) { + FIXP_SGL alpha = (FIXP_SGL)i + << (FRACT_BITS - 1 - TIME_DATA_FLUSH_SIZE_SF); + FIXP_DBL time = PCM_DEC2FIXP_DBL(*pIn); + FIXP_DBL timeFlush = PCM_DEC2FIXP_DBL(pTimeDataFlush[ch][i]); + + *pIn = FIXP_DBL2PCM_DEC(timeFlush - fMult(timeFlush, alpha) + + fMult(time, alpha)); + pIn += s2; + } + } + + return ErrorStatus; +} + +/*! + \brief Parse PreRoll Extension Payload + + \self Handle of AAC decoder + \numPrerollAU Number of preRoll AUs + \prerollAUOffset Offset to each preRoll AU + \prerollAULength Length of each preRoll AU + + \return Error code +*/ +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PreRollExtensionPayloadParse( + HANDLE_AACDECODER self, UINT *numPrerollAU, UINT *prerollAUOffset, + UINT *prerollAULength) { + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs; + AAC_DECODER_ERROR ErrorStatus; + + INT auStartAnchor; + UINT independencyFlag; + UINT extPayloadPresentFlag; + UINT useDefaultLengthFlag; + UINT configLength = 0; + UINT preRollPossible = 1; + UINT i; + UCHAR configChanged = 0; + UCHAR config[TP_USAC_MAX_CONFIG_LEN] = {0}; + UCHAR + implicitExplicitCfgDiff = 0; /* in case implicit and explicit config is + equal preroll AU's should be processed + after decoder reset */ + + ErrorStatus = AAC_DEC_OK; + + hBs = transportDec_GetBitstream(self->hInput, 0); + bs = *hBs; + + auStartAnchor = (INT)FDKgetValidBits(hBs); + if (auStartAnchor <= 0) { + ErrorStatus = AAC_DEC_NOT_ENOUGH_BITS; + goto bail; + } + + /* Independency flag */ + FDKreadBit(hBs); + + /* Payload present flag of extension ID_EXT_ELE_AUDIOPREROLL must be one */ + extPayloadPresentFlag = FDKreadBits(hBs, 1); + if (!extPayloadPresentFlag) { + preRollPossible = 0; + } + + /* Default length flag of extension ID_EXT_ELE_AUDIOPREROLL must be zero */ + useDefaultLengthFlag = FDKreadBits(hBs, 1); + if (useDefaultLengthFlag) { + preRollPossible = 0; + } + + if (preRollPossible) { /* extPayloadPresentFlag && !useDefaultLengthFlag */ + /* Read overall ext payload length, useDefaultLengthFlag must be zero. */ + escapedValue(hBs, 8, 16, 0); + + /* Read RSVD60 Config size */ + configLength = escapedValue(hBs, 4, 4, 8); + + /* Avoid decoding pre roll frames if there was no config change and no + * config is included in the pre roll ext payload. */ + } + + /* If pre roll not possible then exit. */ + if (preRollPossible == 0) { + /* Sanity check: if flushing is switched on, preRollPossible must be 1 */ + if (self->flushStatus != AACDEC_FLUSH_OFF) { + /* Mismatch of current payload and flushing status */ + self->flushStatus = AACDEC_FLUSH_OFF; + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + goto bail; + } + + if (self->flags[0] & AC_USAC) { + if (configLength > 0) { + /* DASH IPF USAC Config Change: Read new config and compare with current + * config. Apply reconfiguration if config's are different. */ + for (i = 0; i < configLength; i++) { + config[i] = FDKreadBits(hBs, 8); + } + TRANSPORTDEC_ERROR terr; + terr = transportDec_InBandConfig(self->hInput, config, configLength, + self->buildUpStatus, &configChanged, 0, + &implicitExplicitCfgDiff); + if (terr != TRANSPORTDEC_OK) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + } + + /* For the first frame buildUpStatus is not set and no flushing is performed + * but preroll AU's should processed. */ + /* For USAC there is no idle state. */ + if ((self->streamInfo.numChannels == 0) && !implicitExplicitCfgDiff && + (self->flags[0] & AC_USAC)) { + self->buildUpStatus = AACDEC_USAC_BUILD_UP_ON; + /* sanity check: if buildUp status on -> flushing must be off */ + if (self->flushStatus != AACDEC_FLUSH_OFF) { + self->flushStatus = AACDEC_FLUSH_OFF; + ErrorStatus = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + + if (self->flags[0] & AC_USAC) { + /* We are interested in preroll AUs if an explicit or an implicit config + * change is signalized in other words if the build up status is set. */ + if (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON) { + UCHAR applyCrossfade = FDKreadBit(hBs); + if (applyCrossfade) { + self->applyCrossfade |= AACDEC_CROSSFADE_BITMASK_PREROLL; + } else { + self->applyCrossfade &= ~AACDEC_CROSSFADE_BITMASK_PREROLL; + } + FDKreadBit(hBs); /* reserved */ + /* Read num preroll AU's */ + *numPrerollAU = escapedValue(hBs, 2, 4, 0); + /* check limits for USAC */ + if (*numPrerollAU > AACDEC_MAX_NUM_PREROLL_AU_USAC) { + *numPrerollAU = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + } + + for (i = 0; i < *numPrerollAU; i++) { + /* For every AU get length and offset in the bitstream */ + prerollAULength[i] = escapedValue(hBs, 16, 16, 0); + if (prerollAULength[i] > 0) { + prerollAUOffset[i] = auStartAnchor - (INT)FDKgetValidBits(hBs); + independencyFlag = FDKreadBit(hBs); + if (i == 0 && !independencyFlag) { + *numPrerollAU = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + goto bail; + } + FDKpushFor(hBs, prerollAULength[i] * 8 - 1); + self->prerollAULength[i] = (prerollAULength[i] * 8) + prerollAUOffset[i]; + } else { + *numPrerollAU = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; /* Something is wrong */ + goto bail; + } + } + +bail: + + *hBs = bs; + + return ErrorStatus; +} + +/*! + \brief Parse Extension Payload + + \self Handle of AAC decoder + \count Pointer to bit counter. + \previous_element ID of previous element (required by some extension payloads) + + \return Error code +*/ +static AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse( + HANDLE_AACDECODER self, HANDLE_FDK_BITSTREAM hBs, int *count, + MP4_ELEMENT_ID previous_element, int elIndex, int fIsFillElement) { + AAC_DECODER_ERROR error = AAC_DEC_OK; + EXT_PAYLOAD_TYPE extension_type; + int bytes = (*count) >> 3; + int crcFlag = 0; + + if (*count < 4) { + return AAC_DEC_PARSE_ERROR; + } else if ((INT)FDKgetValidBits(hBs) < *count) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + extension_type = + (EXT_PAYLOAD_TYPE)FDKreadBits(hBs, 4); /* bs_extension_type */ + *count -= 4; + + /* For ELD, the SBR signaling is explicit and parsed in + aacDecoder_ParseExplicitMpsAndSbr(), therefore skip SBR if implicit + present. */ + if ((self->flags[0] & AC_ELD) && ((extension_type == EXT_SBR_DATA_CRC) || + (extension_type == EXT_SBR_DATA))) { + extension_type = EXT_FIL; /* skip sbr data */ + } + + switch (extension_type) { + case EXT_DYNAMIC_RANGE: { + INT readBits = + aacDecoder_drcMarkPayload(self->hDrcInfo, hBs, MPEG_DRC_EXT_DATA); + + if (readBits > *count) { /* Read too much. Something went wrong! */ + error = AAC_DEC_PARSE_ERROR; + } + *count -= readBits; + } break; + case EXT_LDSAC_DATA: + case EXT_SAC_DATA: + /* Read MPEG Surround Extension payload */ + { + int err, mpsSampleRate, mpsFrameSize; + + if (self->flags[0] & AC_PS_PRESENT) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + + /* Handle SBR dual rate case */ + if (self->streamInfo.extSamplingRate != 0) { + mpsSampleRate = self->streamInfo.extSamplingRate; + mpsFrameSize = self->streamInfo.aacSamplesPerFrame * + (self->streamInfo.extSamplingRate / + self->streamInfo.aacSampleRate); + } else { + mpsSampleRate = self->streamInfo.aacSampleRate; + mpsFrameSize = self->streamInfo.aacSamplesPerFrame; + } + /* Setting of internal MPS state; may be reset in + CAacDecoder_SyncQmfMode if decoder is unable to decode with user + defined qmfMode */ + if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_ELD))) { + self->mpsEnableCurr = self->mpsEnableUser; + } + if (self->mpsEnableCurr) { + if (!self->qmfDomain.globalConf.qmfDomainExplicitConfig) { + /* if not done yet, allocate full MPEG Surround decoder instance */ + if (mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder) == + SAC_INSTANCE_NOT_FULL_AVAILABLE) { + if (mpegSurroundDecoder_Open( + (CMpegSurroundDecoder **)&self->pMpegSurroundDecoder, -1, + &self->qmfDomain)) { + return AAC_DEC_OUT_OF_MEMORY; + } + } + } + err = mpegSurroundDecoder_Parse( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, hBs, count, + self->streamInfo.aot, mpsSampleRate, mpsFrameSize, + self->flags[0] & AC_INDEP); + if (err == MPS_OK) { + self->flags[0] |= AC_MPS_PRESENT; + } else { + error = AAC_DEC_PARSE_ERROR; + } + } + /* Skip any trailing bytes */ + FDKpushFor(hBs, *count); + *count = 0; + } + break; + + case EXT_SBR_DATA_CRC: + crcFlag = 1; + FDK_FALLTHROUGH; + case EXT_SBR_DATA: + if (IS_CHANNEL_ELEMENT(previous_element)) { + SBR_ERROR sbrError; + UCHAR configMode = 0; + UCHAR configChanged = 0; + + CAacDecoder_SyncQmfMode(self); + + configMode |= AC_CM_ALLOC_MEM; + + sbrError = sbrDecoder_InitElement( + self->hSbrDecoder, self->streamInfo.aacSampleRate, + self->streamInfo.extSamplingRate, + self->streamInfo.aacSamplesPerFrame, self->streamInfo.aot, + previous_element, elIndex, + 2, /* Signalize that harmonicSBR shall be ignored in the config + change detection */ + 0, configMode, &configChanged, self->downscaleFactor); + + if (sbrError == SBRDEC_OK) { + sbrError = sbrDecoder_Parse(self->hSbrDecoder, hBs, + self->pDrmBsBuffer, self->drmBsBufferSize, + count, *count, crcFlag, previous_element, + elIndex, self->flags[0], self->elFlags); + /* Enable SBR for implicit SBR signalling but only if no severe error + * happend. */ + if ((sbrError == SBRDEC_OK) || (sbrError == SBRDEC_PARSE_ERROR)) { + self->sbrEnabled = 1; + } + } else { + /* Do not try to apply SBR because initializing the element failed. */ + self->sbrEnabled = 0; + } + /* Citation from ISO/IEC 14496-3 chapter 4.5.2.1.5.2 + Fill elements containing an extension_payload() with an extension_type + of EXT_SBR_DATA or EXT_SBR_DATA_CRC shall not contain any other + extension_payload of any other extension_type. + */ + if (fIsFillElement) { + FDKpushBiDirectional(hBs, *count); + *count = 0; + } else { + /* If this is not a fill element with a known length, we are screwed + * and further parsing makes no sense. */ + if (sbrError != SBRDEC_OK) { + self->frameOK = 0; + } + } + } else { + error = AAC_DEC_PARSE_ERROR; + } + break; + + case EXT_FILL_DATA: { + int temp; + + temp = FDKreadBits(hBs, 4); + bytes--; + if (temp != 0) { + error = AAC_DEC_PARSE_ERROR; + break; + } + while (bytes > 0) { + temp = FDKreadBits(hBs, 8); + bytes--; + if (temp != 0xa5) { + error = AAC_DEC_PARSE_ERROR; + break; + } + } + *count = bytes << 3; + } break; + + case EXT_DATA_ELEMENT: { + int dataElementVersion; + + dataElementVersion = FDKreadBits(hBs, 4); + *count -= 4; + if (dataElementVersion == 0) /* ANC_DATA */ + { + int temp, dataElementLength = 0; + do { + temp = FDKreadBits(hBs, 8); + *count -= 8; + dataElementLength += temp; + } while (temp == 255); + + CAacDecoder_AncDataParse(&self->ancData, hBs, dataElementLength); + *count -= (dataElementLength << 3); + } else { + /* align = 0 */ + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } break; + + case EXT_DATA_LENGTH: + if (!fIsFillElement /* Makes no sens to have an additional length in a + fill ... */ + && + (self->flags[0] & + AC_ER)) /* ... element because this extension payload type was ... */ + { /* ... created to circumvent the missing length in ER-Syntax. */ + int bitCnt, len = FDKreadBits(hBs, 4); + *count -= 4; + + if (len == 15) { + int add_len = FDKreadBits(hBs, 8); + *count -= 8; + len += add_len; + + if (add_len == 255) { + len += FDKreadBits(hBs, 16); + *count -= 16; + } + } + len <<= 3; + bitCnt = len; + + if ((EXT_PAYLOAD_TYPE)FDKreadBits(hBs, 4) == EXT_DATA_LENGTH) { + /* Check NOTE 2: The extension_payload() included here must + not have extension_type == EXT_DATA_LENGTH. */ + error = AAC_DEC_PARSE_ERROR; + goto bail; + } else { + /* rewind and call myself again. */ + FDKpushBack(hBs, 4); + + error = CAacDecoder_ExtPayloadParse( + self, hBs, &bitCnt, previous_element, elIndex, + 1); /* Treat same as fill element */ + + *count -= len - bitCnt; + } + /* Note: the fall through in case the if statement above is not taken is + * intentional. */ + break; + } + FDK_FALLTHROUGH; + + case EXT_FIL: + + default: + /* align = 4 */ + FDKpushFor(hBs, *count); + *count = 0; + break; + } + +bail: + if ((error != AAC_DEC_OK) && + fIsFillElement) { /* Skip the remaining extension bytes */ + FDKpushBiDirectional(hBs, *count); + *count = 0; + /* Patch error code because decoding can go on. */ + error = AAC_DEC_OK; + /* Be sure that parsing errors have been stored. */ + } + return error; +} + +static AAC_DECODER_ERROR aacDecoder_ParseExplicitMpsAndSbr( + HANDLE_AACDECODER self, HANDLE_FDK_BITSTREAM bs, + const MP4_ELEMENT_ID previous_element, const int previous_element_index, + const int element_index, const int el_cnt[]) { + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + INT bitCnt = 0; + + /* get the remaining bits of this frame */ + bitCnt = transportDec_GetAuBitsRemaining(self->hInput, 0); + + if ((self->flags[0] & AC_SBR_PRESENT) && + (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_ELD | AC_DRM))) { + SBR_ERROR err = SBRDEC_OK; + int chElIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE] + + el_cnt[ID_LFE] + el_cnt[ID_USAC_SCE] + + el_cnt[ID_USAC_CPE] + el_cnt[ID_USAC_LFE]; + INT bitCntTmp = bitCnt; + + if (self->flags[0] & AC_USAC) { + chElIdx = numChElements - 1; + } else { + chElIdx = 0; /* ELD case */ + } + + for (; chElIdx < numChElements; chElIdx += 1) { + MP4_ELEMENT_ID sbrType; + SBR_ERROR errTmp; + if (self->flags[0] & (AC_USAC)) { + FDK_ASSERT((self->elements[element_index] == ID_USAC_SCE) || + (self->elements[element_index] == ID_USAC_CPE)); + sbrType = IS_STEREO_SBR(self->elements[element_index], + self->usacStereoConfigIndex[element_index]) + ? ID_CPE + : ID_SCE; + } else + sbrType = self->elements[chElIdx]; + errTmp = sbrDecoder_Parse(self->hSbrDecoder, bs, self->pDrmBsBuffer, + self->drmBsBufferSize, &bitCnt, -1, + self->flags[0] & AC_SBRCRC, sbrType, chElIdx, + self->flags[0], self->elFlags); + if (errTmp != SBRDEC_OK) { + err = errTmp; + bitCntTmp = bitCnt; + bitCnt = 0; + } + } + switch (err) { + case SBRDEC_PARSE_ERROR: + /* Can not go on parsing because we do not + know the length of the SBR extension data. */ + FDKpushFor(bs, bitCntTmp); + bitCnt = 0; + break; + case SBRDEC_OK: + self->sbrEnabled = 1; + break; + default: + self->frameOK = 0; + break; + } + } + + if ((bitCnt > 0) && (self->flags[0] & (AC_USAC | AC_RSVD50))) { + if ((self->flags[0] & AC_MPS_PRESENT) || + (self->elFlags[element_index] & AC_EL_USAC_MPS212)) { + int err; + + err = mpegSurroundDecoder_ParseNoHeader( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, bs, &bitCnt, + self->flags[0] & AC_INDEP); + if (err != MPS_OK) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + } + } + + if (self->flags[0] & AC_DRM) { + if ((bitCnt = (INT)FDKgetValidBits(bs)) != 0) { + FDKpushBiDirectional(bs, bitCnt); + } + } + + if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_DRM))) { + while (bitCnt > 7) { + ErrorStatus = CAacDecoder_ExtPayloadParse( + self, bs, &bitCnt, previous_element, previous_element_index, 0); + if (ErrorStatus != AAC_DEC_OK) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + break; + } + } + } + return ErrorStatus; +} + +/* Stream Configuration and Information. + + This class holds configuration and information data for a stream to be + decoded. It provides the calling application as well as the decoder with + substantial information, e.g. profile, sampling rate, number of channels + found in the bitstream etc. +*/ +static void CStreamInfoInit(CStreamInfo *pStreamInfo) { + pStreamInfo->aacSampleRate = 0; + pStreamInfo->profile = -1; + pStreamInfo->aot = AOT_NONE; + + pStreamInfo->channelConfig = -1; + pStreamInfo->bitRate = 0; + pStreamInfo->aacSamplesPerFrame = 0; + + pStreamInfo->extAot = AOT_NONE; + pStreamInfo->extSamplingRate = 0; + + pStreamInfo->flags = 0; + + pStreamInfo->epConfig = -1; /* default: no ER */ + + pStreamInfo->numChannels = 0; + pStreamInfo->sampleRate = 0; + pStreamInfo->frameSize = 0; + + pStreamInfo->outputDelay = 0; + + /* DRC */ + pStreamInfo->drcProgRefLev = + -1; /* set program reference level to not indicated */ + pStreamInfo->drcPresMode = -1; /* default: presentation mode not indicated */ + + pStreamInfo->outputLoudness = -1; /* default: no loudness metadata present */ +} + +/*! + \brief Initialization of AacDecoderChannelInfo + + The function initializes the pointers to AacDecoderChannelInfo for each + channel, set the start values for window shape and window sequence of + overlap&add to zero, set the overlap buffer to zero and initializes the + pointers to the window coefficients. \param bsFormat is the format of the AAC + bitstream + + \return AACDECODER instance +*/ +LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open( + TRANSPORT_TYPE bsFormat) /*!< bitstream format (adif,adts,loas,...). */ +{ + HANDLE_AACDECODER self; + + self = GetAacDecoder(); + if (self == NULL) { + goto bail; + } + + FDK_QmfDomain_ClearRequested(&self->qmfDomain.globalConf); + + /* Assign channel mapping info arrays (doing so removes dependency of settings + * header in API header). */ + self->streamInfo.pChannelIndices = self->channelIndices; + self->streamInfo.pChannelType = self->channelType; + self->downscaleFactor = 1; + self->downscaleFactorInBS = 1; + + /* initialize anc data */ + CAacDecoder_AncDataInit(&self->ancData, NULL, 0); + + /* initialize stream info */ + CStreamInfoInit(&self->streamInfo); + + /* initialize progam config */ + CProgramConfig_Init(&self->pce); + + /* initialize error concealment common data */ + CConcealment_InitCommonData(&self->concealCommonData); + self->concealMethodUser = ConcealMethodNone; /* undefined -> auto mode */ + + self->hDrcInfo = GetDrcInfo(); + if (self->hDrcInfo == NULL) { + goto bail; + } + /* Init common DRC structure */ + aacDecoder_drcInit(self->hDrcInfo); + /* Set default frame delay */ + aacDecoder_drcSetParam(self->hDrcInfo, DRC_BS_DELAY, + CConcealment_GetDelay(&self->concealCommonData)); + self->workBufferCore1 = (FIXP_DBL *)GetWorkBufferCore1(); + + self->workBufferCore2 = GetWorkBufferCore2(); + if (self->workBufferCore2 == NULL) goto bail; + + /* When RSVD60 is active use dedicated memory for core decoding */ + self->pTimeData2 = GetWorkBufferCore5(); + self->timeData2Size = GetRequiredMemWorkBufferCore5(); + if (self->pTimeData2 == NULL) { + goto bail; + } + + return self; + +bail: + CAacDecoder_Close(self); + + return NULL; +} + +/* Revert CAacDecoder_Init() */ +static void CAacDecoder_DeInit(HANDLE_AACDECODER self, + const int subStreamIndex) { + int ch; + int aacChannelOffset = 0, aacChannels = (8); + int numElements = (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1), + elementOffset = 0; + + if (self == NULL) return; + + { + self->ascChannels[0] = 0; + self->elements[0] = ID_END; + } + + for (ch = aacChannelOffset; ch < aacChannelOffset + aacChannels; ch++) { + if (self->pAacDecoderChannelInfo[ch] != NULL) { + if (self->pAacDecoderChannelInfo[ch]->pComStaticData != NULL) { + if (self->pAacDecoderChannelInfo[ch] + ->pComStaticData->pWorkBufferCore1 != NULL) { + if (ch == aacChannelOffset) { + FreeWorkBufferCore1(&self->pAacDecoderChannelInfo[ch] + ->pComStaticData->pWorkBufferCore1); + } + } + if (self->pAacDecoderChannelInfo[ch] + ->pComStaticData->cplxPredictionData != NULL) { + FreeCplxPredictionData(&self->pAacDecoderChannelInfo[ch] + ->pComStaticData->cplxPredictionData); + } + /* Avoid double free of linked pComStaticData in case of CPE by settings + * pointer to NULL. */ + if (ch < (8) - 1) { + if ((self->pAacDecoderChannelInfo[ch + 1] != NULL) && + (self->pAacDecoderChannelInfo[ch + 1]->pComStaticData == + self->pAacDecoderChannelInfo[ch]->pComStaticData)) { + self->pAacDecoderChannelInfo[ch + 1]->pComStaticData = NULL; + } + } + FDKfree(self->pAacDecoderChannelInfo[ch]->pComStaticData); + self->pAacDecoderChannelInfo[ch]->pComStaticData = NULL; + } + if (self->pAacDecoderChannelInfo[ch]->pComData != NULL) { + /* Avoid double free of linked pComData in case of CPE by settings + * pointer to NULL. */ + if (ch < (8) - 1) { + if ((self->pAacDecoderChannelInfo[ch + 1] != NULL) && + (self->pAacDecoderChannelInfo[ch + 1]->pComData == + self->pAacDecoderChannelInfo[ch]->pComData)) { + self->pAacDecoderChannelInfo[ch + 1]->pComData = NULL; + } + } + if (ch == aacChannelOffset) { + FreeWorkBufferCore6( + (SCHAR **)&self->pAacDecoderChannelInfo[ch]->pComData); + } else { + FDKafree(self->pAacDecoderChannelInfo[ch]->pComData); + } + self->pAacDecoderChannelInfo[ch]->pComData = NULL; + } + } + if (self->pAacDecoderStaticChannelInfo[ch] != NULL) { + if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer != NULL) { + FreeOverlapBuffer( + &self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer); + } + if (self->pAacDecoderStaticChannelInfo[ch]->hArCo != NULL) { + CArco_Destroy(self->pAacDecoderStaticChannelInfo[ch]->hArCo); + } + FreeAacDecoderStaticChannelInfo(&self->pAacDecoderStaticChannelInfo[ch]); + } + if (self->pAacDecoderChannelInfo[ch] != NULL) { + FreeAacDecoderChannelInfo(&self->pAacDecoderChannelInfo[ch]); + } + } + + { + int el; + for (el = elementOffset; el < elementOffset + numElements; el++) { + if (self->cpeStaticData[el] != NULL) { + FreeCpePersistentData(&self->cpeStaticData[el]); + } + } + } + + FDK_Delay_Destroy(&self->usacResidualDelay); + + self->aacChannels = 0; + self->streamInfo.aacSampleRate = 0; + self->streamInfo.sampleRate = 0; + /* This samplerate value is checked for configuration change, not the others + * above. */ + self->samplingRateInfo[subStreamIndex].samplingRate = 0; +} + +/*! + * \brief CAacDecoder_AcceptFlags Accept flags and element flags + * + * \param self [o] handle to AACDECODER structure + * \param asc [i] handle to ASC structure + * \param flags [i] flags + * \param elFlags [i] pointer to element flags + * \param streamIndex [i] stream index + * \param elementOffset [i] element offset + * + * \return void + */ +static void CAacDecoder_AcceptFlags(HANDLE_AACDECODER self, + const CSAudioSpecificConfig *asc, + UINT flags, UINT *elFlags, int streamIndex, + int elementOffset) { + FDKmemcpy(self->elFlags, elFlags, sizeof(self->elFlags)); + + self->flags[streamIndex] = flags; +} + +/*! + * \brief CAacDecoder_CtrlCFGChange Set config change parameters. + * + * \param self [i] handle to AACDECODER structure + * \param flushStatus [i] flush status: on|off + * \param flushCnt [i] flush frame counter + * \param buildUpStatus [i] build up status: on|off + * \param buildUpCnt [i] build up frame counter + * + * \return error + */ +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_CtrlCFGChange(HANDLE_AACDECODER self, + UCHAR flushStatus, + SCHAR flushCnt, + UCHAR buildUpStatus, + SCHAR buildUpCnt) { + AAC_DECODER_ERROR err = AAC_DEC_OK; + + self->flushStatus = flushStatus; + self->flushCnt = flushCnt; + self->buildUpStatus = buildUpStatus; + self->buildUpCnt = buildUpCnt; + + return (err); +} + +/*! + * \brief CAacDecoder_FreeMem Free config dependent AAC memory. + * + * \param self [i] handle to AACDECODER structure + * + * \return error + */ +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_FreeMem(HANDLE_AACDECODER self, + const int subStreamIndex) { + AAC_DECODER_ERROR err = AAC_DEC_OK; + + CAacDecoder_DeInit(self, subStreamIndex); + + return (err); +} + +/* Destroy aac decoder */ +LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self) { + if (self == NULL) return; + + CAacDecoder_DeInit(self, 0); + + { + int ch; + for (ch = 0; ch < (8); ch++) { + if (self->pTimeDataFlush[ch] != NULL) { + FreeTimeDataFlush(&self->pTimeDataFlush[ch]); + } + } + } + + if (self->hDrcInfo) { + FreeDrcInfo(&self->hDrcInfo); + } + + if (self->workBufferCore1 != NULL) { + FreeWorkBufferCore1((CWorkBufferCore1 **)&self->workBufferCore1); + } + + /* Free WorkBufferCore2 */ + if (self->workBufferCore2 != NULL) { + FreeWorkBufferCore2(&self->workBufferCore2); + } + if (self->pTimeData2 != NULL) { + FreeWorkBufferCore5(&self->pTimeData2); + } + + FDK_QmfDomain_Close(&self->qmfDomain); + + FreeAacDecoder(&self); +} + +/*! + \brief Initialization of decoder instance + + The function initializes the decoder. + + \return error status: 0 for success, <>0 for unsupported configurations +*/ +LINKSPEC_CPP AAC_DECODER_ERROR +CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc, + UCHAR configMode, UCHAR *configChanged) { + AAC_DECODER_ERROR err = AAC_DEC_OK; + INT ascChannels, ascChanged = 0; + AACDEC_RENDER_MODE initRenderMode = AACDEC_RENDER_INVALID; + SCHAR usacStereoConfigIndex = -1; + int usacResidualDelayCompSamples = 0; + int elementOffset, aacChannelsOffset, aacChannelsOffsetIdx; + const int streamIndex = 0; + INT flushChannels = 0; + + UINT flags; + /* elFlags[(3*MAX_CHANNELS + (MAX_CHANNELS)/2 + 4 * (MAX_TRACKS) + 1] + where MAX_CHANNELS is (8*2) and MAX_TRACKS is 1 */ + UINT elFlags[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)]; + + UCHAR sbrEnabled = self->sbrEnabled; + UCHAR sbrEnabledPrev = self->sbrEnabledPrev; + UCHAR mpsEnableCurr = self->mpsEnableCurr; + + if (!self) return AAC_DEC_INVALID_HANDLE; + + UCHAR downscaleFactor = self->downscaleFactor; + UCHAR downscaleFactorInBS = self->downscaleFactorInBS; + + self->aacOutDataHeadroom = (3); + + // set profile and check for supported aot + // leave profile on default (=-1) for all other supported MPEG-4 aot's except + // aot=2 (=AAC-LC) + switch (asc->m_aot) { + case AOT_AAC_LC: + self->streamInfo.profile = 1; + FDK_FALLTHROUGH; + case AOT_ER_AAC_SCAL: + if (asc->m_sc.m_gaSpecificConfig.m_layer > 0) { + /* aac_scalable_extension_element() currently not supported. */ + return AAC_DEC_UNSUPPORTED_FORMAT; + } + FDK_FALLTHROUGH; + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + initRenderMode = AACDEC_RENDER_IMDCT; + break; + case AOT_ER_AAC_ELD: + initRenderMode = AACDEC_RENDER_ELDFB; + break; + case AOT_USAC: + initRenderMode = AACDEC_RENDER_IMDCT; + break; + default: + return AAC_DEC_UNSUPPORTED_AOT; + } + + if (CProgramConfig_IsValid(&self->pce) && (asc->m_channelConfiguration > 0)) { + /* Compare the stored (old) PCE with a default PCE created from the (new) + channel_config (on a temporal buffer) to find out wheter we can keep it + (and its metadata) or not. */ + int pceCmpResult; + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + + CProgramConfig_GetDefault(tmpPce, asc->m_channelConfiguration); + pceCmpResult = CProgramConfig_Compare(&self->pce, tmpPce); + if ((pceCmpResult < 0) /* Reset if PCEs are completely different ... */ + || + (pceCmpResult > 1)) { /* ... or have a different layout. */ + CProgramConfig_Init(&self->pce); + } /* Otherwise keep the PCE (and its metadata). */ + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + } else { + CProgramConfig_Init(&self->pce); + } + + /* set channels */ + switch (asc->m_channelConfiguration) { + case 0: + switch (asc->m_aot) { + case AOT_USAC: + self->chMapIndex = 0; + ascChannels = asc->m_sc.m_usacConfig.m_nUsacChannels; + break; + default: + /* get channels from program config (ASC) */ + if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) { + ascChannels = asc->m_progrConfigElement.NumChannels; + if (ascChannels > 0) { + int el_tmp; + /* valid number of channels -> copy program config element (PCE) + * from ASC */ + FDKmemcpy(&self->pce, &asc->m_progrConfigElement, + sizeof(CProgramConfig)); + /* Built element table */ + el_tmp = CProgramConfig_GetElementTable( + &asc->m_progrConfigElement, self->elements, (((8)) + (8)), + &self->chMapIndex); + for (; el_tmp < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1); + el_tmp++) { + self->elements[el_tmp] = ID_NONE; + } + } else { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + } else { + self->chMapIndex = 0; + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + break; + } + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + ascChannels = asc->m_channelConfiguration; + break; + case 11: + ascChannels = 7; + break; + case 7: + case 12: + case 14: + ascChannels = 8; + break; + default: + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + + if (asc->m_aot == AOT_USAC) { + flushChannels = fMin(ascChannels, (8)); + INT numChannel; + pcmDmx_GetParam(self->hPcmUtils, MIN_NUMBER_OF_OUTPUT_CHANNELS, + &numChannel); + flushChannels = fMin(fMax(numChannel, flushChannels), (8)); + } + + if (IS_USAC(asc->m_aot)) { + for (int el = 0; el < (INT)asc->m_sc.m_usacConfig.m_usacNumElements; el++) { + /* fix number of core channels aka ascChannels for stereoConfigIndex = 1 + * cases */ + if (asc->m_sc.m_usacConfig.element[el].m_stereoConfigIndex == 1) { + ascChannels--; /* stereoConfigIndex == 1 stereo cases do actually + contain only a mono core channel. */ + } else if (asc->m_sc.m_usacConfig.element[el].m_stereoConfigIndex == 2) { + /* In this case it is necessary to follow up the DMX signal delay caused + by HBE also with the residual signal (2nd core channel). The SBR + overlap delay is not regarded here, this is handled by the MPS212 + implementation. + */ + if (asc->m_sc.m_usacConfig.element[el].m_harmonicSBR) { + usacResidualDelayCompSamples += asc->m_samplesPerFrame; + } + if (asc->m_sc.m_usacConfig.m_coreSbrFrameLengthIndex == 4) { + usacResidualDelayCompSamples += + 6 * 16; /* difference between 12 SBR + overlap slots from SBR and 6 + slots delayed in MPS212 */ + } + } + } + } + + aacChannelsOffset = 0; + aacChannelsOffsetIdx = 0; + elementOffset = 0; + if ((ascChannels <= 0) || (ascChannels > (8)) || + (asc->m_channelConfiguration > AACDEC_MAX_CH_CONF)) { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + + /* Set syntax flags */ + flags = 0; + { FDKmemclear(elFlags, sizeof(elFlags)); } + + if ((asc->m_channelConfiguration > 0) || IS_USAC(asc->m_aot)) { + if (IS_USAC(asc->m_aot)) { + /* copy pointer to usac config + (this is preliminary since there's an ongoing discussion about storing + the config-part of the bitstream rather than the complete decoded + configuration) */ + self->pUsacConfig[streamIndex] = &asc->m_sc.m_usacConfig; + + /* copy list of elements */ + if (self->pUsacConfig[streamIndex]->m_usacNumElements > + (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) { + goto bail; + } + + if (self->numUsacElements[streamIndex] != + asc->m_sc.m_usacConfig.m_usacNumElements) { + ascChanged = 1; + } + + if (configMode & AC_CM_ALLOC_MEM) { + self->numUsacElements[streamIndex] = + asc->m_sc.m_usacConfig.m_usacNumElements; + } + + mpsEnableCurr = 0; + for (int _el = 0; + _el < (int)self->pUsacConfig[streamIndex]->m_usacNumElements; + _el++) { + int el = _el + elementOffset; + if (self->elements[el] != + self->pUsacConfig[streamIndex]->element[_el].usacElementType) { + ascChanged = 1; + } + if (self->usacStereoConfigIndex[el] != + asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex) { + ascChanged = 1; + } + if (configMode & AC_CM_ALLOC_MEM) { + self->elements[el] = + self->pUsacConfig[streamIndex]->element[_el].usacElementType; + /* for Unified Stereo Coding */ + self->usacStereoConfigIndex[el] = + asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex; + if (self->elements[el] == ID_USAC_CPE) { + mpsEnableCurr |= self->usacStereoConfigIndex[el] ? 1 : 0; + } + } + + elFlags[el] |= (asc->m_sc.m_usacConfig.element[_el].m_noiseFilling) + ? AC_EL_USAC_NOISE + : 0; + elFlags[el] |= + (asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex > 0) + ? AC_EL_USAC_MPS212 + : 0; + elFlags[el] |= (asc->m_sc.m_usacConfig.element[_el].m_interTes) + ? AC_EL_USAC_ITES + : 0; + elFlags[el] |= + (asc->m_sc.m_usacConfig.element[_el].m_pvc) ? AC_EL_USAC_PVC : 0; + elFlags[el] |= + (asc->m_sc.m_usacConfig.element[_el].usacElementType == ID_USAC_LFE) + ? AC_EL_USAC_LFE + : 0; + elFlags[el] |= + (asc->m_sc.m_usacConfig.element[_el].usacElementType == ID_USAC_LFE) + ? AC_EL_LFE + : 0; + if ((asc->m_sc.m_usacConfig.element[_el].usacElementType == + ID_USAC_CPE) && + ((self->usacStereoConfigIndex[el] == 0))) { + elFlags[el] |= AC_EL_USAC_CP_POSSIBLE; + } + } + + self->hasAudioPreRoll = 0; + if (self->pUsacConfig[streamIndex]->m_usacNumElements) { + self->hasAudioPreRoll = asc->m_sc.m_usacConfig.element[0] + .extElement.usacExtElementHasAudioPreRoll; + } + if (configMode & AC_CM_ALLOC_MEM) { + self->elements[elementOffset + + self->pUsacConfig[streamIndex]->m_usacNumElements] = + ID_END; + } + } else { + /* Initialize constant mappings for channel config 1-7 */ + int i; + for (i = 0; i < AACDEC_CH_ELEMENTS_TAB_SIZE; i++) { + self->elements[i] = elementsTab[asc->m_channelConfiguration - 1][i]; + } + for (; i < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1); i++) { + self->elements[i] = ID_NONE; + } + } + + { + int ch; + + for (ch = 0; ch < ascChannels; ch++) { + self->chMapping[ch] = ch; + } + for (; ch < (8); ch++) { + self->chMapping[ch] = 255; + } + } + + self->chMapIndex = asc->m_channelConfiguration; + } else { + if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) { + /* Set matrix mixdown infos if available from PCE. */ + pcmDmx_SetMatrixMixdownFromPce( + self->hPcmUtils, asc->m_progrConfigElement.MatrixMixdownIndexPresent, + asc->m_progrConfigElement.MatrixMixdownIndex, + asc->m_progrConfigElement.PseudoSurroundEnable); + } + } + + self->streamInfo.channelConfig = asc->m_channelConfiguration; + + if (self->streamInfo.aot != asc->m_aot) { + if (configMode & AC_CM_ALLOC_MEM) { + self->streamInfo.aot = asc->m_aot; + } + ascChanged = 1; + } + + if (asc->m_aot == AOT_ER_AAC_ELD && + asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency != 0) { + if (self->samplingRateInfo[0].samplingRate != + asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency || + self->samplingRateInfo[0].samplingRate * self->downscaleFactor != + asc->m_samplingFrequency) { + /* get downscaledSamplingFrequency from ESC and compute the downscale + * factor */ + downscaleFactorInBS = + asc->m_samplingFrequency / + asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency; + if ((downscaleFactorInBS == 1 || downscaleFactorInBS == 2 || + (downscaleFactorInBS == 3 && + asc->m_sc.m_eldSpecificConfig.m_frameLengthFlag) || + downscaleFactorInBS == 4) && + ((asc->m_samplingFrequency % + asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency) == + 0)) { + downscaleFactor = downscaleFactorInBS; + } else { + downscaleFactorInBS = 1; + downscaleFactor = 1; + } + } + } else { + downscaleFactorInBS = 1; + downscaleFactor = 1; + } + + if (self->downscaleFactorInBS != downscaleFactorInBS) { + if (configMode & AC_CM_ALLOC_MEM) { + self->downscaleFactorInBS = downscaleFactorInBS; + self->downscaleFactor = downscaleFactor; + } + ascChanged = 1; + } + + if ((INT)asc->m_samplesPerFrame % downscaleFactor != 0) { + return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* frameSize/dsf must be an integer + number */ + } + + self->streamInfo.bitRate = 0; + + if (asc->m_aot == AOT_ER_AAC_ELD) { + if (self->useLdQmfTimeAlign != + asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) { + ascChanged = 1; + } + if (configMode & AC_CM_ALLOC_MEM) { + self->useLdQmfTimeAlign = + asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign; + } + if (sbrEnabled != asc->m_sbrPresentFlag) { + ascChanged = 1; + } + } + + self->streamInfo.extAot = asc->m_extensionAudioObjectType; + if (self->streamInfo.extSamplingRate != + (INT)asc->m_extensionSamplingFrequency) { + ascChanged = 1; + } + if (configMode & AC_CM_ALLOC_MEM) { + self->streamInfo.extSamplingRate = asc->m_extensionSamplingFrequency; + } + flags |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0; + flags |= (asc->m_psPresentFlag) ? AC_PS_PRESENT : 0; + if (asc->m_sbrPresentFlag) { + sbrEnabled = 1; + sbrEnabledPrev = 1; + } else { + sbrEnabled = 0; + sbrEnabledPrev = 0; + } + if (sbrEnabled && asc->m_extensionSamplingFrequency) { + if (downscaleFactor != 1 && (downscaleFactor)&1) { + return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* SBR needs an even downscale + factor */ + } + if (configMode & AC_CM_ALLOC_MEM) { + self->streamInfo.extSamplingRate = + self->streamInfo.extSamplingRate / self->downscaleFactor; + } + } + if ((asc->m_aot == AOT_AAC_LC) && (asc->m_sbrPresentFlag == 1) && + (asc->m_extensionSamplingFrequency > (2 * asc->m_samplingFrequency))) { + return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* Core decoder supports at most a + 1:2 upsampling for HE-AAC and + HE-AACv2 */ + } + + /* --------- vcb11 ------------ */ + flags |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0; + + /* ---------- rvlc ------------ */ + flags |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0; + + /* ----------- hcr ------------ */ + flags |= (asc->m_hcrFlag) ? AC_ER_HCR : 0; + + if (asc->m_aot == AOT_ER_AAC_ELD) { + mpsEnableCurr = 0; + flags |= AC_ELD; + flags |= (asc->m_sbrPresentFlag) + ? AC_SBR_PRESENT + : 0; /* Need to set the SBR flag for backward-compatibility + reasons. Even if SBR is not supported. */ + flags |= (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0; + flags |= (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) + ? AC_MPS_PRESENT + : 0; + if (self->mpsApplicable) { + mpsEnableCurr = asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign; + } + } + flags |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0; + flags |= (asc->m_epConfig >= 0) ? AC_ER : 0; + + if (asc->m_aot == AOT_USAC) { + flags |= AC_USAC; + flags |= (asc->m_sc.m_usacConfig.element[0].m_stereoConfigIndex > 0) + ? AC_MPS_PRESENT + : 0; + } + if (asc->m_aot == AOT_DRM_AAC) { + flags |= AC_DRM | AC_SBRCRC | AC_SCALABLE; + } + if (asc->m_aot == AOT_DRM_SURROUND) { + flags |= AC_DRM | AC_SBRCRC | AC_SCALABLE | AC_MPS_PRESENT; + FDK_ASSERT(!asc->m_psPresentFlag); + } + if ((asc->m_aot == AOT_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_SCAL)) { + flags |= AC_SCALABLE; + } + + if ((asc->m_epConfig >= 0) && (asc->m_channelConfiguration <= 0)) { + /* we have to know the number of channels otherwise no decoding is possible + */ + return AAC_DEC_UNSUPPORTED_ER_FORMAT; + } + + self->streamInfo.epConfig = asc->m_epConfig; + /* self->hInput->asc.m_epConfig = asc->m_epConfig; */ + + if (asc->m_epConfig > 1) return AAC_DEC_UNSUPPORTED_ER_FORMAT; + + /* Check if samplerate changed. */ + if ((self->samplingRateInfo[streamIndex].samplingRate != + asc->m_samplingFrequency) || + (self->streamInfo.aacSamplesPerFrame != + (INT)asc->m_samplesPerFrame / downscaleFactor)) { + AAC_DECODER_ERROR error; + + ascChanged = 1; + + if (configMode & AC_CM_ALLOC_MEM) { + /* Update samplerate info. */ + error = getSamplingRateInfo( + &self->samplingRateInfo[streamIndex], asc->m_samplesPerFrame, + asc->m_samplingFrequencyIndex, asc->m_samplingFrequency); + if (error != AAC_DEC_OK) { + return error; + } + self->streamInfo.aacSampleRate = + self->samplingRateInfo[0].samplingRate / self->downscaleFactor; + self->streamInfo.aacSamplesPerFrame = + asc->m_samplesPerFrame / self->downscaleFactor; + if (self->streamInfo.aacSampleRate <= 0) { + return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; + } + } + } + + /* Check if amount of channels has changed. */ + if (self->ascChannels[streamIndex] != ascChannels) { + ascChanged = 1; + } + + /* detect config change */ + if (configMode & AC_CM_DET_CFG_CHANGE) { + if (ascChanged != 0) { + *configChanged = 1; + } + + CAacDecoder_AcceptFlags(self, asc, flags, elFlags, streamIndex, + elementOffset); + + return err; + } + + /* set AC_USAC_SCFGI3 globally if any usac element uses */ + switch (asc->m_aot) { + case AOT_USAC: + if (sbrEnabled) { + for (int _el = 0; + _el < (int)self->pUsacConfig[streamIndex]->m_usacNumElements; + _el++) { + int el = elementOffset + _el; + if (IS_USAC_CHANNEL_ELEMENT(self->elements[el])) { + if (usacStereoConfigIndex < 0) { + usacStereoConfigIndex = self->usacStereoConfigIndex[el]; + } else { + if ((usacStereoConfigIndex != self->usacStereoConfigIndex[el]) || + (self->usacStereoConfigIndex[el] > 0)) { + goto bail; + } + } + } + } + + if (usacStereoConfigIndex < 0) { + goto bail; + } + + if (usacStereoConfigIndex == 3) { + flags |= AC_USAC_SCFGI3; + } + } + break; + default: + break; + } + + if (*configChanged) { + /* Set up QMF domain for AOTs with explicit signalling of SBR and or MPS. + This is to be able to play out the first frame alway with the correct + frame size and sampling rate even in case of concealment. + */ + switch (asc->m_aot) { + case AOT_USAC: + if (sbrEnabled) { + const UCHAR map_sbrRatio_2_nAnaBands[] = {16, 24, 32}; + + FDK_ASSERT(asc->m_sc.m_usacConfig.m_sbrRatioIndex > 0); + FDK_ASSERT(streamIndex == 0); + + self->qmfDomain.globalConf.nInputChannels_requested = ascChannels; + self->qmfDomain.globalConf.nOutputChannels_requested = + (usacStereoConfigIndex == 1) ? 2 : ascChannels; + self->qmfDomain.globalConf.flags_requested = 0; + self->qmfDomain.globalConf.nBandsAnalysis_requested = + map_sbrRatio_2_nAnaBands[asc->m_sc.m_usacConfig.m_sbrRatioIndex - + 1]; + self->qmfDomain.globalConf.nBandsSynthesis_requested = 64; + self->qmfDomain.globalConf.nQmfTimeSlots_requested = + (asc->m_sc.m_usacConfig.m_sbrRatioIndex == 1) ? 64 : 32; + self->qmfDomain.globalConf.nQmfOvTimeSlots_requested = + (asc->m_sc.m_usacConfig.m_sbrRatioIndex == 1) ? 12 : 6; + self->qmfDomain.globalConf.nQmfProcBands_requested = 64; + self->qmfDomain.globalConf.nQmfProcChannels_requested = 1; + self->qmfDomain.globalConf.parkChannel = + (usacStereoConfigIndex == 3) ? 1 : 0; + self->qmfDomain.globalConf.parkChannel_requested = + (usacStereoConfigIndex == 3) ? 1 : 0; + self->qmfDomain.globalConf.qmfDomainExplicitConfig = 1; + } + break; + case AOT_ER_AAC_ELD: + if (mpsEnableCurr && + asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) { + SAC_INPUT_CONFIG sac_interface = (sbrEnabled && self->hSbrDecoder) + ? SAC_INTERFACE_QMF + : SAC_INTERFACE_TIME; + mpegSurroundDecoder_ConfigureQmfDomain( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, sac_interface, + (UINT)self->streamInfo.aacSampleRate, asc->m_aot); + self->qmfDomain.globalConf.qmfDomainExplicitConfig = 1; + } + break; + default: + self->qmfDomain.globalConf.qmfDomainExplicitConfig = + 0; /* qmfDomain is initialized by SBR and MPS init functions if + required */ + break; + } + + /* Allocate all memory structures for each channel */ + { + int ch = aacChannelsOffset; + for (int _ch = 0; _ch < ascChannels; _ch++) { + if (ch >= (8)) { + goto bail; + } + self->pAacDecoderChannelInfo[ch] = GetAacDecoderChannelInfo(ch); + /* This is temporary until the DynamicData is split into two or more + regions! The memory could be reused after completed core decoding. */ + if (self->pAacDecoderChannelInfo[ch] == NULL) { + goto bail; + } + ch++; + } + + int chIdx = aacChannelsOffsetIdx; + ch = aacChannelsOffset; + int _numElements; + _numElements = (((8)) + (8)); + if (flags & (AC_RSV603DA | AC_USAC)) { + _numElements = (int)asc->m_sc.m_usacConfig.m_usacNumElements; + } + for (int _el = 0; _el < _numElements; _el++) { + int el_channels = 0; + int el = elementOffset + _el; + + if (flags & + (AC_ER | AC_LD | AC_ELD | AC_RSV603DA | AC_USAC | AC_RSVD50)) { + if (ch >= ascChannels) { + break; + } + } + + switch (self->elements[el]) { + case ID_SCE: + case ID_CPE: + case ID_LFE: + case ID_USAC_SCE: + case ID_USAC_CPE: + case ID_USAC_LFE: + + el_channels = CAacDecoder_GetELChannels( + self->elements[el], self->usacStereoConfigIndex[el]); + + { + self->pAacDecoderChannelInfo[ch]->pComStaticData = + (CAacDecoderCommonStaticData *)FDKcalloc( + 1, sizeof(CAacDecoderCommonStaticData)); + if (self->pAacDecoderChannelInfo[ch]->pComStaticData == NULL) { + goto bail; + } + if (ch == aacChannelsOffset) { + self->pAacDecoderChannelInfo[ch]->pComData = + (CAacDecoderCommonData *)GetWorkBufferCore6(); + self->pAacDecoderChannelInfo[ch] + ->pComStaticData->pWorkBufferCore1 = GetWorkBufferCore1(); + } else { + self->pAacDecoderChannelInfo[ch]->pComData = + (CAacDecoderCommonData *)FDKaalloc( + sizeof(CAacDecoderCommonData), ALIGNMENT_DEFAULT); + self->pAacDecoderChannelInfo[ch] + ->pComStaticData->pWorkBufferCore1 = + self->pAacDecoderChannelInfo[aacChannelsOffset] + ->pComStaticData->pWorkBufferCore1; + } + if ((self->pAacDecoderChannelInfo[ch]->pComData == NULL) || + (self->pAacDecoderChannelInfo[ch] + ->pComStaticData->pWorkBufferCore1 == NULL)) { + goto bail; + } + self->pAacDecoderChannelInfo[ch]->pDynData = + &(self->pAacDecoderChannelInfo[ch] + ->pComData->pAacDecoderDynamicData[0]); + self->pAacDecoderChannelInfo[ch]->pSpectralCoefficient = + (SPECTRAL_PTR)&self->workBufferCore2[ch * 1024]; + + if (el_channels == 2) { + if (ch >= (8) - 1) { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + self->pAacDecoderChannelInfo[ch + 1]->pComData = + self->pAacDecoderChannelInfo[ch]->pComData; + self->pAacDecoderChannelInfo[ch + 1]->pComStaticData = + self->pAacDecoderChannelInfo[ch]->pComStaticData; + self->pAacDecoderChannelInfo[ch + 1] + ->pComStaticData->pWorkBufferCore1 = + self->pAacDecoderChannelInfo[ch] + ->pComStaticData->pWorkBufferCore1; + self->pAacDecoderChannelInfo[ch + 1]->pDynData = + &(self->pAacDecoderChannelInfo[ch] + ->pComData->pAacDecoderDynamicData[1]); + self->pAacDecoderChannelInfo[ch + 1]->pSpectralCoefficient = + (SPECTRAL_PTR)&self->workBufferCore2[(ch + 1) * 1024]; + } + + ch += el_channels; + } + chIdx += el_channels; + break; + + default: + break; + } + + if (self->elements[el] == ID_END) { + break; + } + + el++; + } + + chIdx = aacChannelsOffsetIdx; + ch = aacChannelsOffset; + for (int _ch = 0; _ch < ascChannels; _ch++) { + /* Allocate persistent channel memory */ + { + self->pAacDecoderStaticChannelInfo[ch] = + GetAacDecoderStaticChannelInfo(ch); + if (self->pAacDecoderStaticChannelInfo[ch] == NULL) { + goto bail; + } + self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer = + GetOverlapBuffer(ch); /* This area size depends on the AOT */ + if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer == NULL) { + goto bail; + } + if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA /*|AC_BSAC*/)) { + self->pAacDecoderStaticChannelInfo[ch]->hArCo = CArco_Create(); + if (self->pAacDecoderStaticChannelInfo[ch]->hArCo == NULL) { + goto bail; + } + } + + if (!(flags & (AC_USAC | AC_RSV603DA))) { + CPns_UpdateNoiseState( + &self->pAacDecoderChannelInfo[ch]->data.aac.PnsData, + &self->pAacDecoderStaticChannelInfo[ch]->pnsCurrentSeed, + self->pAacDecoderChannelInfo[ch]->pComData->pnsRandomSeed); + } + ch++; + } + chIdx++; + } + + if (flags & AC_USAC) { + for (int _ch = 0; _ch < flushChannels; _ch++) { + ch = aacChannelsOffset + _ch; + if (self->pTimeDataFlush[ch] == NULL) { + self->pTimeDataFlush[ch] = GetTimeDataFlush(ch); + if (self->pTimeDataFlush[ch] == NULL) { + goto bail; + } + } + } + } + + if (flags & (AC_USAC | AC_RSV603DA)) { + int complexStereoPredPossible = 0; + ch = aacChannelsOffset; + chIdx = aacChannelsOffsetIdx; + for (int _el2 = 0; _el2 < (int)asc->m_sc.m_usacConfig.m_usacNumElements; + _el2++) { + int el2 = elementOffset + _el2; + int elCh = 0, ch2; + + if ((self->elements[el2] == ID_USAC_CPE) && + !(self->usacStereoConfigIndex[el2] == 1)) { + elCh = 2; + } else if (IS_CHANNEL_ELEMENT(self->elements[el2])) { + elCh = 1; + } + + if (elFlags[el2] & AC_EL_USAC_CP_POSSIBLE) { + complexStereoPredPossible = 1; + if (self->cpeStaticData[el2] == NULL) { + self->cpeStaticData[el2] = GetCpePersistentData(); + if (self->cpeStaticData[el2] == NULL) { + goto bail; + } + } + } + + for (ch2 = 0; ch2 < elCh; ch2++) { + /* Hook element specific cpeStaticData into channel specific + * aacDecoderStaticChannelInfo */ + self->pAacDecoderStaticChannelInfo[ch]->pCpeStaticData = + self->cpeStaticData[el2]; + if (self->pAacDecoderStaticChannelInfo[ch]->pCpeStaticData != + NULL) { + self->pAacDecoderStaticChannelInfo[ch] + ->pCpeStaticData->jointStereoPersistentData + .spectralCoeffs[ch2] = + self->pAacDecoderStaticChannelInfo[ch] + ->concealmentInfo.spectralCoefficient; + self->pAacDecoderStaticChannelInfo[ch] + ->pCpeStaticData->jointStereoPersistentData.specScale[ch2] = + self->pAacDecoderStaticChannelInfo[ch] + ->concealmentInfo.specScale; + self->pAacDecoderStaticChannelInfo[ch] + ->pCpeStaticData->jointStereoPersistentData.scratchBuffer = + (FIXP_DBL *)self->pTimeData2; + } + chIdx++; + ch++; + } /* for each channel in current element */ + if (complexStereoPredPossible && (elCh == 2)) { + /* needed once for all channels */ + if (self->pAacDecoderChannelInfo[ch - 1] + ->pComStaticData->cplxPredictionData == NULL) { + self->pAacDecoderChannelInfo[ch - 1] + ->pComStaticData->cplxPredictionData = + GetCplxPredictionData(); + } + if (self->pAacDecoderChannelInfo[ch - 1] + ->pComStaticData->cplxPredictionData == NULL) { + goto bail; + } + } + if (elCh > 0) { + self->pAacDecoderStaticChannelInfo[ch - elCh]->nfRandomSeed = + (ULONG)0x3039; + if (self->elements[el2] == ID_USAC_CPE) { + if (asc->m_sc.m_usacConfig.element[el2].m_stereoConfigIndex != + 1) { + self->pAacDecoderStaticChannelInfo[ch - elCh + 1] + ->nfRandomSeed = (ULONG)0x10932; + } + } + } + } /* for each element */ + } + + if (ascChannels != self->aacChannels) { + /* Make allocated channel count persistent in decoder context. */ + self->aacChannels = aacChannelsOffset + ch; + } + } + + if (usacResidualDelayCompSamples) { + INT delayErr = FDK_Delay_Create(&self->usacResidualDelay, + (USHORT)usacResidualDelayCompSamples, 1); + if (delayErr) { + goto bail; + } + } + + /* Make amount of signalled channels persistent in decoder context. */ + self->ascChannels[streamIndex] = ascChannels; + /* Init the previous channel count values. This is required to avoid a + mismatch of memory accesses in the error concealment module and the + allocated channel structures in this function. */ + self->aacChannelsPrev = 0; + } + + if (self->pAacDecoderChannelInfo[0] != NULL) { + self->pDrmBsBuffer = self->pAacDecoderChannelInfo[0] + ->pComStaticData->pWorkBufferCore1->DrmBsBuffer; + self->drmBsBufferSize = DRM_BS_BUFFER_SIZE; + } + + /* Update structures */ + if (*configChanged) { + /* Things to be done for each channel, which do not involve allocating + memory. Doing these things only on the channels needed for the current + configuration (ascChannels) could lead to memory access violation later + (error concealment). */ + int ch = 0; + int chIdx = 0; + for (int _ch = 0; _ch < self->ascChannels[streamIndex]; _ch++) { + switch (self->streamInfo.aot) { + case AOT_ER_AAC_ELD: + case AOT_ER_AAC_LD: + self->pAacDecoderChannelInfo[ch]->granuleLength = + self->streamInfo.aacSamplesPerFrame; + break; + default: + self->pAacDecoderChannelInfo[ch]->granuleLength = + self->streamInfo.aacSamplesPerFrame / 8; + break; + } + self->pAacDecoderChannelInfo[ch]->renderMode = initRenderMode; + + mdct_init(&self->pAacDecoderStaticChannelInfo[ch]->IMdct, + self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer, + OverlapBufferSize); + + self->pAacDecoderStaticChannelInfo[ch]->last_core_mode = FD_LONG; + self->pAacDecoderStaticChannelInfo[ch]->last_lpd_mode = 255; + + self->pAacDecoderStaticChannelInfo[ch]->last_tcx_pitch = L_DIV; + + /* Reset DRC control data for this channel */ + aacDecoder_drcInitChannelData( + &self->pAacDecoderStaticChannelInfo[ch]->drcData); + + /* Delete mixdown metadata from the past */ + pcmDmx_Reset(self->hPcmUtils, PCMDMX_RESET_BS_DATA); + + /* Reset concealment only if ASC changed. Otherwise it will be done with + any config callback. E.g. every time the LATM SMC is present. */ + CConcealment_InitChannelData( + &self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo, + &self->concealCommonData, initRenderMode, + self->streamInfo.aacSamplesPerFrame); + ch++; + chIdx++; + } + } + + if (*configChanged) { + int drcDecSampleRate, drcDecFrameSize; + + if (self->streamInfo.extSamplingRate != 0) { + drcDecSampleRate = self->streamInfo.extSamplingRate; + drcDecFrameSize = (self->streamInfo.aacSamplesPerFrame * + self->streamInfo.extSamplingRate) / + self->streamInfo.aacSampleRate; + } else { + drcDecSampleRate = self->streamInfo.aacSampleRate; + drcDecFrameSize = self->streamInfo.aacSamplesPerFrame; + } + + if (FDK_drcDec_Init(self->hUniDrcDecoder, drcDecFrameSize, drcDecSampleRate, + self->aacChannels) != 0) + goto bail; + } + + if (*configChanged) { + if (asc->m_aot == AOT_USAC) { + aacDecoder_drcDisable(self->hDrcInfo); + } + } + + if (asc->m_aot == AOT_USAC) { + pcmLimiter_SetAttack(self->hLimiter, (5)); + pcmLimiter_SetThreshold(self->hLimiter, FL2FXCONST_DBL(0.89125094f)); + } + + CAacDecoder_AcceptFlags(self, asc, flags, elFlags, streamIndex, + elementOffset); + self->sbrEnabled = sbrEnabled; + self->sbrEnabledPrev = sbrEnabledPrev; + self->mpsEnableCurr = mpsEnableCurr; + + /* Update externally visible copy of flags */ + self->streamInfo.flags = self->flags[0]; + + return err; + +bail: + CAacDecoder_DeInit(self, 0); + return AAC_DEC_OUT_OF_MEMORY; +} + +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( + HANDLE_AACDECODER self, const UINT flags, PCM_DEC *pTimeData, + const INT timeDataSize, const int timeDataChannelOffset) { + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + CProgramConfig *pce; + HANDLE_FDK_BITSTREAM bs = transportDec_GetBitstream(self->hInput, 0); + + MP4_ELEMENT_ID type = ID_NONE; /* Current element type */ + INT aacChannels = 0; /* Channel counter for channels found in the bitstream */ + const int streamIndex = 0; /* index of the current substream */ + + INT auStartAnchor = (INT)FDKgetValidBits( + bs); /* AU start bit buffer position for AU byte alignment */ + + INT checkSampleRate = self->streamInfo.aacSampleRate; + + INT CConceal_TDFading_Applied[(8)] = { + 0}; /* Initialize status of Time Domain fading */ + + if (self->aacChannels <= 0) { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + + /* Any supported base layer valid AU will require more than 16 bits. */ + if ((transportDec_GetAuBitsRemaining(self->hInput, 0) < 15) && + (flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) == 0) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + + /* Reset Program Config structure */ + pce = &self->pce; + CProgramConfig_Reset(pce); + + CAacDecoder_AncDataReset(&self->ancData); + if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) && + !(self->flags[0] & (AC_USAC | AC_RSV603DA))) { + int ch; + if (self->streamInfo.channelConfig == 0) { + /* Init Channel/Element mapping table */ + for (ch = 0; ch < (8); ch++) { + self->chMapping[ch] = 255; + } + if (!CProgramConfig_IsValid(pce)) { + int el; + for (el = 0; el < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1); + el++) { + self->elements[el] = ID_NONE; + } + } + } + } + + if (self->downscaleFactor > 1 && (self->flags[0] & AC_ELD)) { + self->flags[0] |= AC_ELD_DOWNSCALE; + } else { + self->flags[0] &= ~AC_ELD_DOWNSCALE; + } + /* unsupported dsf (aacSampleRate has not yet been divided by dsf) -> divide + */ + if (self->downscaleFactorInBS > 1 && + (self->flags[0] & AC_ELD_DOWNSCALE) == 0) { + checkSampleRate = + self->streamInfo.aacSampleRate / self->downscaleFactorInBS; + } + + /* Check sampling frequency */ + if (self->streamInfo.aacSampleRate <= 0) { + /* Instance maybe uninitialized! */ + return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; + } + switch (checkSampleRate) { + case 96000: + case 88200: + case 64000: + case 16000: + case 12000: + case 11025: + case 8000: + case 7350: + case 48000: + case 44100: + case 32000: + case 24000: + case 22050: + break; + default: + if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) { + return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; + } + break; + } + + if (flags & AACDEC_CLRHIST) { + if (!(self->flags[0] & AC_USAC)) { + int ch; + /* Clear history */ + for (ch = 0; ch < self->aacChannels; ch++) { + /* Reset concealment */ + CConcealment_InitChannelData( + &self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo, + &self->concealCommonData, + self->pAacDecoderChannelInfo[0]->renderMode, + self->streamInfo.aacSamplesPerFrame); + /* Clear overlap-add buffers to avoid clicks. */ + FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer, + OverlapBufferSize * sizeof(FIXP_DBL)); + } + if (self->streamInfo.channelConfig > 0) { + /* Declare the possibly adopted old PCE (with outdated metadata) + * invalid. */ + CProgramConfig_Init(pce); + } + } + } + + int pceRead = 0; /* Flag indicating a PCE in the current raw_data_block() */ + + INT hdaacDecoded = 0; + MP4_ELEMENT_ID previous_element = + ID_END; /* Last element ID (required for extension payload mapping */ + UCHAR previous_element_index = 0; /* Canonical index of last element */ + int element_count = + 0; /* Element counter for elements found in the bitstream */ + int channel_element_count = 0; /* Channel element counter */ + MP4_ELEMENT_ID + channel_elements[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + + 1)]; /* Channel elements in bit stream order. */ + int el_cnt[ID_LAST] = {0}; /* element counter ( robustness ) */ + int element_count_prev_streams = + 0; /* Element count of all previous sub streams. */ + + while ((type != ID_END) && (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) && + self->frameOK) { + int el_channels; + + if (!(self->flags[0] & + (AC_USAC | AC_RSVD50 | AC_RSV603DA | AC_ELD | AC_SCALABLE | AC_ER))) + type = (MP4_ELEMENT_ID)FDKreadBits(bs, 3); + else { + if (element_count >= (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + break; + } + type = self->elements[element_count]; + } + + if ((self->flags[streamIndex] & (AC_USAC | AC_RSVD50) && + element_count == 0) || + (self->flags[streamIndex] & AC_RSV603DA)) { + self->flags[streamIndex] &= ~AC_INDEP; + + if (FDKreadBit(bs)) { + self->flags[streamIndex] |= AC_INDEP; + } + + int ch = aacChannels; + for (int chIdx = aacChannels; chIdx < self->ascChannels[streamIndex]; + chIdx++) { + { + /* Robustness check */ + if (ch >= self->aacChannels) { + return AAC_DEC_UNKNOWN; + } + + /* if last frame was broken and this frame is no independent frame, + * correct decoding is impossible we need to trigger concealment */ + if ((CConcealment_GetLastFrameOk( + &self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo, + 1) == 0) && + !(self->flags[streamIndex] & AC_INDEP)) { + self->frameOK = 0; + } + ch++; + } + } + } + + if ((INT)FDKgetValidBits(bs) < 0) { + self->frameOK = 0; + } + + switch (type) { + case ID_SCE: + case ID_CPE: + case ID_LFE: + case ID_USAC_SCE: + case ID_USAC_CPE: + case ID_USAC_LFE: + if (element_count >= (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + break; + } + + el_channels = CAacDecoder_GetELChannels( + type, self->usacStereoConfigIndex[element_count]); + + /* + Consistency check + */ + { + int totalAscChannels = 0; + + for (int i = 0; i < (1 * 1); i++) { + totalAscChannels += self->ascChannels[i]; + } + if ((el_cnt[type] >= (totalAscChannels >> (el_channels - 1))) || + (aacChannels > (totalAscChannels - el_channels))) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + break; + } + } + + if (!(self->flags[streamIndex] & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) { + int ch; + for (ch = 0; ch < el_channels; ch += 1) { + CPns_ResetData(&self->pAacDecoderChannelInfo[aacChannels + ch] + ->data.aac.PnsData, + &self->pAacDecoderChannelInfo[aacChannels + ch] + ->pComData->pnsInterChannelData); + } + } + + if (self->frameOK) { + ErrorStatus = CChannelElement_Read( + bs, &self->pAacDecoderChannelInfo[aacChannels], + &self->pAacDecoderStaticChannelInfo[aacChannels], + self->streamInfo.aot, &self->samplingRateInfo[streamIndex], + self->flags[streamIndex], self->elFlags[element_count], + self->streamInfo.aacSamplesPerFrame, el_channels, + self->streamInfo.epConfig, self->hInput); + if (ErrorStatus != AAC_DEC_OK) { + self->frameOK = 0; + } + } + + if (self->frameOK) { + /* Lookup the element and decode it only if it belongs to the current + * program */ + if (CProgramConfig_LookupElement( + pce, self->streamInfo.channelConfig, + self->pAacDecoderChannelInfo[aacChannels]->ElementInstanceTag, + aacChannels, self->chMapping, self->channelType, + self->channelIndices, (8), &previous_element_index, + self->elements, type)) { + channel_elements[channel_element_count++] = type; + aacChannels += el_channels; + } else { + self->frameOK = 0; + } + /* Create SBR element for SBR for upsampling for LFE elements, + and if SBR was implicitly signaled, because the first frame(s) + may not contain SBR payload (broken encoder, bit errors). */ + if (self->frameOK && + ((self->flags[streamIndex] & AC_SBR_PRESENT) || + (self->sbrEnabled == 1)) && + !(self->flags[streamIndex] & + AC_USAC) /* Is done during explicit config set up */ + ) { + SBR_ERROR sbrError; + UCHAR configMode = 0; + UCHAR configChanged = 0; + configMode |= AC_CM_ALLOC_MEM; + + sbrError = sbrDecoder_InitElement( + self->hSbrDecoder, self->streamInfo.aacSampleRate, + self->streamInfo.extSamplingRate, + self->streamInfo.aacSamplesPerFrame, self->streamInfo.aot, type, + previous_element_index, 2, /* Signalize that harmonicSBR shall + be ignored in the config change + detection */ + 0, configMode, &configChanged, self->downscaleFactor); + if (sbrError != SBRDEC_OK) { + /* Do not try to apply SBR because initializing the element + * failed. */ + self->sbrEnabled = 0; + } + } + } + + el_cnt[type]++; + if (self->frameOK && (self->flags[streamIndex] & AC_USAC) && + (type == ID_USAC_CPE || type == ID_USAC_SCE)) { + ErrorStatus = aacDecoder_ParseExplicitMpsAndSbr( + self, bs, previous_element, previous_element_index, element_count, + el_cnt); + if (ErrorStatus != AAC_DEC_OK) { + self->frameOK = 0; + } + } + break; + + case ID_CCE: + /* + Consistency check + */ + if (el_cnt[type] > self->ascChannels[streamIndex]) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + break; + } + + if (self->frameOK) { + CAacDecoderCommonData commonData; + CAacDecoderCommonStaticData commonStaticData; + CWorkBufferCore1 workBufferCore1; + commonStaticData.pWorkBufferCore1 = &workBufferCore1; + /* memory for spectral lines temporal on scratch */ + C_AALLOC_SCRATCH_START(mdctSpec, FIXP_DBL, 1024); + + /* create dummy channel for CCE parsing on stack */ + CAacDecoderChannelInfo tmpAacDecoderChannelInfo, + *pTmpAacDecoderChannelInfo; + + FDKmemclear(mdctSpec, 1024 * sizeof(FIXP_DBL)); + + tmpAacDecoderChannelInfo.pDynData = commonData.pAacDecoderDynamicData; + tmpAacDecoderChannelInfo.pComData = &commonData; + tmpAacDecoderChannelInfo.pComStaticData = &commonStaticData; + tmpAacDecoderChannelInfo.pSpectralCoefficient = + (SPECTRAL_PTR)mdctSpec; + /* Assume AAC-LC */ + tmpAacDecoderChannelInfo.granuleLength = + self->streamInfo.aacSamplesPerFrame / 8; + /* Reset PNS data. */ + CPns_ResetData( + &tmpAacDecoderChannelInfo.data.aac.PnsData, + &tmpAacDecoderChannelInfo.pComData->pnsInterChannelData); + pTmpAacDecoderChannelInfo = &tmpAacDecoderChannelInfo; + /* do CCE parsing */ + ErrorStatus = CChannelElement_Read( + bs, &pTmpAacDecoderChannelInfo, NULL, self->streamInfo.aot, + &self->samplingRateInfo[streamIndex], self->flags[streamIndex], + AC_EL_GA_CCE, self->streamInfo.aacSamplesPerFrame, 1, + self->streamInfo.epConfig, self->hInput); + + C_AALLOC_SCRATCH_END(mdctSpec, FIXP_DBL, 1024); + + if (ErrorStatus) { + self->frameOK = 0; + } + + if (self->frameOK) { + /* Lookup the element and decode it only if it belongs to the + * current program */ + if (CProgramConfig_LookupElement( + pce, self->streamInfo.channelConfig, + pTmpAacDecoderChannelInfo->ElementInstanceTag, 0, + self->chMapping, self->channelType, self->channelIndices, + (8), &previous_element_index, self->elements, type)) { + /* decoding of CCE not supported */ + } else { + self->frameOK = 0; + } + } + } + el_cnt[type]++; + break; + + case ID_DSE: { + UCHAR element_instance_tag; + + CDataStreamElement_Read(self, bs, &element_instance_tag, auStartAnchor); + + if (!CProgramConfig_LookupElement( + pce, self->streamInfo.channelConfig, element_instance_tag, 0, + self->chMapping, self->channelType, self->channelIndices, (8), + &previous_element_index, self->elements, type)) { + /* most likely an error in bitstream occured */ + // self->frameOK = 0; + } + } break; + + case ID_PCE: { + int result = CProgramConfigElement_Read(bs, self->hInput, pce, + self->streamInfo.channelConfig, + auStartAnchor); + if (result < 0) { + /* Something went wrong */ + ErrorStatus = AAC_DEC_PARSE_ERROR; + self->frameOK = 0; + } else if (result > 1) { + /* Built element table */ + int elIdx = CProgramConfig_GetElementTable( + pce, self->elements, (((8)) + (8)), &self->chMapIndex); + /* Reset the remaining tabs */ + for (; elIdx < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1); + elIdx++) { + self->elements[elIdx] = ID_NONE; + } + /* Make new number of channel persistent */ + self->ascChannels[streamIndex] = pce->NumChannels; + /* If PCE is not first element conceal this frame to avoid + * inconsistencies */ + if (element_count != 0) { + self->frameOK = 0; + } + } + pceRead = (result >= 0) ? 1 : 0; + } break; + + case ID_FIL: { + int bitCnt = FDKreadBits(bs, 4); /* bs_count */ + + if (bitCnt == 15) { + int esc_count = FDKreadBits(bs, 8); /* bs_esc_count */ + bitCnt = esc_count + 14; + } + + /* Convert to bits */ + bitCnt <<= 3; + + while (bitCnt > 0) { + ErrorStatus = CAacDecoder_ExtPayloadParse( + self, bs, &bitCnt, previous_element, previous_element_index, 1); + if (ErrorStatus != AAC_DEC_OK) { + self->frameOK = 0; + break; + } + } + } break; + + case ID_EXT: + if (element_count >= (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + break; + } + + ErrorStatus = aacDecoder_ParseExplicitMpsAndSbr( + self, bs, previous_element, previous_element_index, element_count, + el_cnt); + break; + + case ID_USAC_EXT: { + if ((element_count - element_count_prev_streams) >= + TP_USAC_MAX_ELEMENTS) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + break; + } + /* parse extension element payload + q.v. rsv603daExtElement() ISO/IEC DIS 23008-3 Table 30 + or UsacExElement() ISO/IEC FDIS 23003-3:2011(E) Table 21 + */ + int usacExtElementPayloadLength; + /* int usacExtElementStart, usacExtElementStop; */ + + if (FDKreadBit(bs)) { /* usacExtElementPresent */ + if (FDKreadBit(bs)) { /* usacExtElementUseDefaultLength */ + usacExtElementPayloadLength = + self->pUsacConfig[streamIndex] + ->element[element_count - element_count_prev_streams] + .extElement.usacExtElementDefaultLength; + } else { + usacExtElementPayloadLength = FDKreadBits(bs, 8); + if (usacExtElementPayloadLength == (UINT)(1 << 8) - 1) { + UINT valueAdd = FDKreadBits(bs, 16); + usacExtElementPayloadLength += (INT)valueAdd - 2; + } + } + if (usacExtElementPayloadLength > 0) { + int usacExtBitPos; + + if (self->pUsacConfig[streamIndex] + ->element[element_count - element_count_prev_streams] + .extElement.usacExtElementPayloadFrag) { + /* usacExtElementStart = */ FDKreadBit(bs); + /* usacExtElementStop = */ FDKreadBit(bs); + } else { + /* usacExtElementStart = 1; */ + /* usacExtElementStop = 1; */ + } + + usacExtBitPos = (INT)FDKgetValidBits(bs); + + USAC_EXT_ELEMENT_TYPE usacExtElementType = + self->pUsacConfig[streamIndex] + ->element[element_count - element_count_prev_streams] + .extElement.usacExtElementType; + + switch (usacExtElementType) { + case ID_EXT_ELE_UNI_DRC: /* uniDrcGain() */ + if (streamIndex == 0) { + int drcErr; + + drcErr = FDK_drcDec_ReadUniDrcGain(self->hUniDrcDecoder, bs); + if (drcErr != 0) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + } + break; + + default: + break; + } + + /* Skip any remaining bits of extension payload */ + usacExtBitPos = (usacExtElementPayloadLength * 8) - + (usacExtBitPos - (INT)FDKgetValidBits(bs)); + if (usacExtBitPos < 0) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + FDKpushBiDirectional(bs, usacExtBitPos); + } + } + } break; + case ID_END: + case ID_USAC_END: + break; + + default: + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + break; + } + + previous_element = type; + element_count++; + + } /* while ( (type != ID_END) ... ) */ + + if (!(self->flags[streamIndex] & + (AC_USAC | AC_RSVD50 | AC_RSV603DA | AC_BSAC | AC_LD | AC_ELD | AC_ER | + AC_SCALABLE)) && + (self->streamInfo.channelConfig == 0) && pce->isValid && + (ErrorStatus == AAC_DEC_OK) && self->frameOK && + !(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) { + /* Check whether all PCE listed element instance tags are present in + * raw_data_block() */ + if (!validateElementInstanceTags( + &self->pce, self->pAacDecoderChannelInfo, aacChannels, + channel_elements, + fMin(channel_element_count, (int)(sizeof(channel_elements) / + sizeof(*channel_elements))))) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + } + } + + if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) { + /* float decoder checks if bitsLeft is in range 0-7; only prerollAUs are + * byteAligned with respect to the first bit */ + /* Byte alignment with respect to the first bit of the raw_data_block(). */ + if (!(self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) || + (self->prerollAULength[self->accessUnit]) /* indicates preroll */ + ) { + FDKbyteAlign(bs, auStartAnchor); + } + + /* Check if all bits of the raw_data_block() have been read. */ + if (transportDec_GetAuBitsTotal(self->hInput, 0) > 0) { + INT unreadBits = transportDec_GetAuBitsRemaining(self->hInput, 0); + /* for pre-roll frames pre-roll length has to be used instead of total AU + * lenght */ + /* unreadBits regarding preroll bounds */ + if (self->prerollAULength[self->accessUnit]) { + unreadBits = unreadBits - transportDec_GetAuBitsTotal(self->hInput, 0) + + (INT)self->prerollAULength[self->accessUnit]; + } + if (((self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) && + ((unreadBits < 0) || (unreadBits > 7)) && + !(self->prerollAULength[self->accessUnit])) || + ((!(self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) || + (self->prerollAULength[self->accessUnit])) && + (unreadBits != 0))) { + if ((((unreadBits < 0) || (unreadBits > 7)) && self->frameOK) && + ((transportDec_GetFormat(self->hInput) == TT_DRM) && + (self->flags[streamIndex] & AC_USAC))) { + /* Set frame OK because of fill bits. */ + self->frameOK = 1; + } else { + self->frameOK = 0; + } + + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK && self->frameOK == 0) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + /* Always put the bitbuffer at the right position after the current + * Access Unit. */ + FDKpushBiDirectional(bs, unreadBits); + } + } + + /* Check the last element. The terminator (ID_END) has to be the last one + * (even if ER syntax is used). */ + if (self->frameOK && type != ID_END) { + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + self->frameOK = 0; + } + } + + if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) && self->frameOK) { + channel_elements[channel_element_count++] = ID_END; + } + element_count = 0; + aacChannels = 0; + type = ID_NONE; + previous_element_index = 0; + + while (type != ID_END && + element_count < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) { + int el_channels; + + if ((flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) || !self->frameOK) { + channel_elements[element_count] = self->elements[element_count]; + if (channel_elements[element_count] == ID_NONE) { + channel_elements[element_count] = ID_END; + } + } + + if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA | AC_BSAC)) { + type = self->elements[element_count]; + } else { + type = channel_elements[element_count]; + } + + if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) && self->frameOK) { + switch (type) { + case ID_SCE: + case ID_CPE: + case ID_LFE: + case ID_USAC_SCE: + case ID_USAC_CPE: + case ID_USAC_LFE: + + el_channels = CAacDecoder_GetELChannels( + type, self->usacStereoConfigIndex[element_count]); + + if (!hdaacDecoded) { + if (self->pAacDecoderStaticChannelInfo[aacChannels] + ->pCpeStaticData != NULL) { + self->pAacDecoderStaticChannelInfo[aacChannels] + ->pCpeStaticData->jointStereoPersistentData.scratchBuffer = + (FIXP_DBL *)pTimeData; + } + CChannelElement_Decode( + &self->pAacDecoderChannelInfo[aacChannels], + &self->pAacDecoderStaticChannelInfo[aacChannels], + &self->samplingRateInfo[streamIndex], self->flags[streamIndex], + self->elFlags[element_count], el_channels); + } + aacChannels += el_channels; + break; + case ID_NONE: + type = ID_END; + break; + default: + break; + } + } + element_count++; + } + + /* More AAC channels than specified by the ASC not allowed. */ + if ((aacChannels == 0 || aacChannels > self->aacChannels) && + !(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) { + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + self->frameOK = 0; + aacChannels = 0; + } + + if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) { + if (TRANSPORTDEC_OK != transportDec_CrcCheck(self->hInput)) { + ErrorStatus = AAC_DEC_CRC_ERROR; + self->frameOK = 0; + } + } + + /* Ensure that in case of concealment a proper error status is set. */ + if ((self->frameOK == 0) && (ErrorStatus == AAC_DEC_OK)) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + + if (self->frameOK && (flags & AACDEC_FLUSH)) { + aacChannels = self->aacChannelsPrev; + /* Because the downmix could be active, its necessary to restore the channel + * type and indices. */ + FDKmemcpy(self->channelType, self->channelTypePrev, + (8) * sizeof(AUDIO_CHANNEL_TYPE)); /* restore */ + FDKmemcpy(self->channelIndices, self->channelIndicesPrev, + (8) * sizeof(UCHAR)); /* restore */ + self->sbrEnabled = self->sbrEnabledPrev; + } else { + /* store or restore the number of channels and the corresponding info */ + if (self->frameOK && !(flags & AACDEC_CONCEAL)) { + self->aacChannelsPrev = aacChannels; /* store */ + FDKmemcpy(self->channelTypePrev, self->channelType, + (8) * sizeof(AUDIO_CHANNEL_TYPE)); /* store */ + FDKmemcpy(self->channelIndicesPrev, self->channelIndices, + (8) * sizeof(UCHAR)); /* store */ + self->sbrEnabledPrev = self->sbrEnabled; + } else { + if (self->aacChannels > 0) { + if ((self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON) || + (self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON_IN_BAND) || + (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON)) { + aacChannels = self->aacChannels; + self->aacChannelsPrev = aacChannels; /* store */ + } else { + aacChannels = self->aacChannelsPrev; /* restore */ + } + FDKmemcpy(self->channelType, self->channelTypePrev, + (8) * sizeof(AUDIO_CHANNEL_TYPE)); /* restore */ + FDKmemcpy(self->channelIndices, self->channelIndicesPrev, + (8) * sizeof(UCHAR)); /* restore */ + self->sbrEnabled = self->sbrEnabledPrev; + } + } + } + + /* Update number of output channels */ + self->streamInfo.aacNumChannels = aacChannels; + + /* Ensure consistency of IS_OUTPUT_VALID() macro. */ + if (aacChannels == 0) { + ErrorStatus = AAC_DEC_UNKNOWN; + } + + if (pceRead == 1 && CProgramConfig_IsValid(pce)) { + /* Set matrix mixdown infos if available from PCE. */ + pcmDmx_SetMatrixMixdownFromPce( + self->hPcmUtils, pce->MatrixMixdownIndexPresent, + pce->MatrixMixdownIndex, pce->PseudoSurroundEnable); + ; + } + + /* If there is no valid data to transfrom into time domain, return. */ + if (!IS_OUTPUT_VALID(ErrorStatus)) { + return ErrorStatus; + } + + /* Setup the output channel mapping. The table below shows the three + * possibilities: # | chCfg | PCE | chMapIndex + * ---+-------+-----+------------------ + * 1 | > 0 | no | chCfg + * 2 | 0 | yes | cChCfg + * 3 | 0 | no | aacChannels || 0 + * ---+-------+-----+--------+------------------ + * Where chCfg is the channel configuration index from ASC and cChCfg is a + * corresponding chCfg derived from a given PCE. The variable aacChannels + * represents the number of channel found during bitstream decoding. Due to + * the structure of the mapping table it can only be used for mapping if its + * value is smaller than 7. Otherwise we use the fallback (0) which is a + * simple pass-through. The possibility #3 should appear only with MPEG-2 + * (ADTS) streams. This is mode is called "implicit channel mapping". + */ + if ((self->streamInfo.channelConfig == 0) && !pce->isValid) { + self->chMapIndex = (aacChannels < 7) ? aacChannels : 0; + } + + /* + Inverse transform + */ + { + int c, cIdx; + int mapped, fCopyChMap = 1; + UCHAR drcChMap[(8)]; + + if ((self->streamInfo.channelConfig == 0) && CProgramConfig_IsValid(pce)) { + /* ISO/IEC 14496-3 says: + If a PCE is present, the exclude_mask bits correspond to the audio + channels in the SCE, CPE, CCE and LFE syntax elements in the order of + their appearance in the PCE. In the case of a CPE, the first + transmitted mask bit corresponds to the first channel in the CPE, the + second transmitted mask bit to the second channel. In the case of a + CCE, a mask bit is transmitted only if the coupling channel is + specified to be an independently switched coupling channel. Thus we + have to convert the internal channel mapping from "canonical" MPEG to + PCE order: */ + UCHAR tmpChMap[(8)]; + if (CProgramConfig_GetPceChMap(pce, tmpChMap, (8)) == 0) { + for (c = 0; c < aacChannels; c += 1) { + drcChMap[c] = + (self->chMapping[c] == 255) ? 255 : tmpChMap[self->chMapping[c]]; + } + fCopyChMap = 0; + } + } + if (fCopyChMap != 0) { + FDKmemcpy(drcChMap, self->chMapping, (8) * sizeof(UCHAR)); + } + + /* Extract DRC control data and map it to channels (without bitstream delay) + */ + mapped = aacDecoder_drcProlog( + self->hDrcInfo, bs, self->pAacDecoderStaticChannelInfo, + pce->ElementInstanceTag, drcChMap, aacChannels); + if (mapped > 0) { + if (!(self->flags[streamIndex] & (AC_USAC | AC_RSV603DA))) { + /* If at least one DRC thread has been mapped to a channel there was DRC + * data in the bitstream. */ + self->flags[streamIndex] |= AC_DRC_PRESENT; + } else { + ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT; + } + } + if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA)) { + aacDecoder_drcDisable(self->hDrcInfo); + } + + /* Create a reverse mapping table */ + UCHAR Reverse_chMapping[((8) * 2)]; + for (c = 0; c < aacChannels; c++) { + int d; + for (d = 0; d < aacChannels - 1; d++) { + if (self->chMapping[d] == c) { + break; + } + } + Reverse_chMapping[c] = d; + } + + int el; + int el_channels; + c = 0; + cIdx = 0; + el_channels = 0; + for (el = 0; el < element_count; el++) { + int frameOk_butConceal = + 0; /* Force frame concealment during mute release active state. */ + int concealApplyReturnCode; + + if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA | AC_BSAC)) { + type = self->elements[el]; + } else { + type = channel_elements[el]; + } + + { + int nElementChannels; + + nElementChannels = + CAacDecoder_GetELChannels(type, self->usacStereoConfigIndex[el]); + + el_channels += nElementChannels; + + if (nElementChannels == 0) { + continue; + } + } + + int offset; + int elCh = 0; + /* "c" iterates in canonical MPEG channel order */ + for (; cIdx < el_channels; c++, cIdx++, elCh++) { + /* Robustness check */ + if (c >= aacChannels) { + return AAC_DEC_UNKNOWN; + } + + CAacDecoderChannelInfo *pAacDecoderChannelInfo = + self->pAacDecoderChannelInfo[c]; + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo = + self->pAacDecoderStaticChannelInfo[c]; + + /* Setup offset for time buffer traversal. */ + { + pAacDecoderStaticChannelInfo = + self->pAacDecoderStaticChannelInfo[Reverse_chMapping[c]]; + offset = + FDK_chMapDescr_getMapValue( + &self->mapDescr, Reverse_chMapping[cIdx], self->chMapIndex) * + timeDataChannelOffset; + } + + if (flags & AACDEC_FLUSH) { + /* Clear pAacDecoderChannelInfo->pSpectralCoefficient because with + * AACDEC_FLUSH set it contains undefined data. */ + FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, + sizeof(FIXP_DBL) * self->streamInfo.aacSamplesPerFrame); + } + + /* if The ics info is not valid and it will be stored and used in the + * following concealment method, mark the frame as erroneous */ + { + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + CConcealmentInfo *hConcealmentInfo = + &pAacDecoderStaticChannelInfo->concealmentInfo; + const int mute_release_active = + (self->frameOK && !(flags & AACDEC_CONCEAL)) && + ((hConcealmentInfo->concealState >= ConcealState_Mute) && + (hConcealmentInfo->cntValidFrames + 1 <= + hConcealmentInfo->pConcealParams->numMuteReleaseFrames)); + const int icsIsInvalid = (GetScaleFactorBandsTransmitted(pIcsInfo) > + GetScaleFactorBandsTotal(pIcsInfo)); + const int icsInfoUsedinFadeOut = + !(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD && + pAacDecoderStaticChannelInfo->last_lpd_mode == 0); + if (icsInfoUsedinFadeOut && icsIsInvalid && !mute_release_active) { + self->frameOK = 0; + } + } + + /* + Conceal defective spectral data + */ + { + CAacDecoderChannelInfo **ppAacDecoderChannelInfo = + &pAacDecoderChannelInfo; + CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo = + &pAacDecoderStaticChannelInfo; + { + concealApplyReturnCode = CConcealment_Apply( + &(*ppAacDecoderStaticChannelInfo)->concealmentInfo, + *ppAacDecoderChannelInfo, *ppAacDecoderStaticChannelInfo, + &self->samplingRateInfo[streamIndex], + self->streamInfo.aacSamplesPerFrame, + pAacDecoderStaticChannelInfo->last_lpd_mode, + (self->frameOK && !(flags & AACDEC_CONCEAL)), + self->flags[streamIndex]); + } + } + if (concealApplyReturnCode == -1) { + frameOk_butConceal = 1; + } + + if (flags & (AACDEC_INTR)) { + /* Reset DRC control data for this channel */ + aacDecoder_drcInitChannelData(&pAacDecoderStaticChannelInfo->drcData); + } + if (flags & (AACDEC_CLRHIST)) { + if (!(self->flags[0] & AC_USAC)) { + /* Reset DRC control data for this channel */ + aacDecoder_drcInitChannelData( + &pAacDecoderStaticChannelInfo->drcData); + } + } + + /* The DRC module demands to be called with the gain field holding the + * gain scale. */ + self->extGain[0] = (FIXP_DBL)AACDEC_DRC_GAIN_SCALING; + + /* DRC processing */ + aacDecoder_drcApply( + self->hDrcInfo, self->hSbrDecoder, pAacDecoderChannelInfo, + &pAacDecoderStaticChannelInfo->drcData, self->extGain, c, + self->streamInfo.aacSamplesPerFrame, self->sbrEnabled + + ); + + if (timeDataSize < timeDataChannelOffset * self->aacChannels) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + break; + } + if (self->flushStatus && (self->flushCnt > 0) && + !(flags & AACDEC_CONCEAL)) { + FDKmemclear(pTimeData + offset, + sizeof(PCM_DEC) * self->streamInfo.aacSamplesPerFrame); + } else + switch (pAacDecoderChannelInfo->renderMode) { + case AACDEC_RENDER_IMDCT: + + CBlock_FrequencyToTime( + pAacDecoderStaticChannelInfo, pAacDecoderChannelInfo, + pTimeData + offset, self->streamInfo.aacSamplesPerFrame, + (self->frameOK && !(flags & AACDEC_CONCEAL) && + !frameOk_butConceal), + pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1 + ->mdctOutTemp, + self->aacOutDataHeadroom, self->elFlags[el], elCh); + + self->extGainDelay = self->streamInfo.aacSamplesPerFrame; + break; + case AACDEC_RENDER_ELDFB: { + CBlock_FrequencyToTimeLowDelay( + pAacDecoderStaticChannelInfo, pAacDecoderChannelInfo, + pTimeData + offset, self->streamInfo.aacSamplesPerFrame); + self->extGainDelay = + (self->streamInfo.aacSamplesPerFrame * 2 - + self->streamInfo.aacSamplesPerFrame / 2 - 1) / + 2; + } break; + case AACDEC_RENDER_LPD: + + CLpd_RenderTimeSignal( + pAacDecoderStaticChannelInfo, pAacDecoderChannelInfo, + pTimeData + offset, self->streamInfo.aacSamplesPerFrame, + &self->samplingRateInfo[streamIndex], + (self->frameOK && !(flags & AACDEC_CONCEAL) && + !frameOk_butConceal), + self->aacOutDataHeadroom, flags, self->flags[streamIndex]); + + self->extGainDelay = self->streamInfo.aacSamplesPerFrame; + break; + default: + ErrorStatus = AAC_DEC_UNKNOWN; + break; + } + /* TimeDomainFading */ + if (!CConceal_TDFading_Applied[c]) { + CConceal_TDFading_Applied[c] = CConcealment_TDFading( + self->streamInfo.aacSamplesPerFrame, + &self->pAacDecoderStaticChannelInfo[c], self->aacOutDataHeadroom, + pTimeData + offset, 0); + if (c + 1 < (8) && c < aacChannels - 1) { + /* update next TDNoise Seed to avoid muting in case of Parametric + * Stereo */ + self->pAacDecoderStaticChannelInfo[c + 1] + ->concealmentInfo.TDNoiseSeed = + self->pAacDecoderStaticChannelInfo[c] + ->concealmentInfo.TDNoiseSeed; + } + } + } + } + + if (self->flags[streamIndex] & AC_USAC) { + int bsPseudoLr = 0; + mpegSurroundDecoder_IsPseudoLR( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, &bsPseudoLr); + /* ISO/IEC 23003-3, 7.11.2.6 Modification of core decoder output (pseudo + * LR) */ + if ((aacChannels == 2) && bsPseudoLr) { + int i, offset2; + const FIXP_SGL invSqrt2 = FL2FXCONST_SGL(0.707106781186547f); + PCM_DEC *pTD = pTimeData; + + offset2 = timeDataChannelOffset; + + for (i = 0; i < self->streamInfo.aacSamplesPerFrame; i++) { + FIXP_DBL L = PCM_DEC2FIXP_DBL(pTD[0]); + FIXP_DBL R = PCM_DEC2FIXP_DBL(pTD[offset2]); + L = fMult(L, invSqrt2); + R = fMult(R, invSqrt2); + pTD[0] = L + R; + pTD[offset2] = L - R; + pTD++; + } + } + } + + /* Extract DRC control data and map it to channels (with bitstream delay) */ + mapped = aacDecoder_drcEpilog( + self->hDrcInfo, bs, self->pAacDecoderStaticChannelInfo, + pce->ElementInstanceTag, drcChMap, aacChannels); + if (mapped > 0) { + if (!(self->flags[streamIndex] & (AC_USAC | AC_RSV603DA))) { + /* If at least one DRC thread has been mapped to a channel there was DRC + * data in the bitstream. */ + self->flags[streamIndex] |= AC_DRC_PRESENT; + } else { + ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT; + } + } + if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA)) { + aacDecoder_drcDisable(self->hDrcInfo); + } + } + + /* Add additional concealment delay */ + self->streamInfo.outputDelay += + CConcealment_GetDelay(&self->concealCommonData) * + self->streamInfo.aacSamplesPerFrame; + + /* Map DRC data to StreamInfo structure */ + aacDecoder_drcGetInfo(self->hDrcInfo, &self->streamInfo.drcPresMode, + &self->streamInfo.drcProgRefLev); + + /* Reorder channel type information tables. */ + if (!(self->flags[0] & AC_RSV603DA)) { + AUDIO_CHANNEL_TYPE types[(8)]; + UCHAR idx[(8)]; + int c; + int mapValue; + + FDK_ASSERT(sizeof(self->channelType) == sizeof(types)); + FDK_ASSERT(sizeof(self->channelIndices) == sizeof(idx)); + + FDKmemcpy(types, self->channelType, sizeof(types)); + FDKmemcpy(idx, self->channelIndices, sizeof(idx)); + + for (c = 0; c < aacChannels; c++) { + mapValue = + FDK_chMapDescr_getMapValue(&self->mapDescr, c, self->chMapIndex); + self->channelType[mapValue] = types[c]; + self->channelIndices[mapValue] = idx[c]; + } + } + + self->blockNumber++; + + return ErrorStatus; +} + +/*! + \brief returns the streaminfo pointer + + The function hands back a pointer to the streaminfo structure + + \return pointer to the struct +*/ +LINKSPEC_CPP CStreamInfo *CAacDecoder_GetStreamInfo(HANDLE_AACDECODER self) { + if (!self) { + return NULL; + } + return &self->streamInfo; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdecoder.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdecoder.h new file mode 100644 index 0000000000000..002807f8c0089 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdecoder.h @@ -0,0 +1,474 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +#ifndef AACDECODER_H +#define AACDECODER_H + +#include "common_fix.h" + +#include "FDK_bitstream.h" + +#include "channel.h" + +#include "tpdec_lib.h" +#include "FDK_audio.h" + +#include "block.h" + +#include "genericStds.h" + +#include "FDK_qmf_domain.h" + +#include "sbrdecoder.h" + +#include "aacdec_drc.h" + +#include "pcmdmx_lib.h" + +#include "FDK_drcDecLib.h" + +#include "limiter.h" + +#include "FDK_delay.h" + +#define TIME_DATA_FLUSH_SIZE (128) +#define TIME_DATA_FLUSH_SIZE_SF (7) + +#define AACDEC_MAX_NUM_PREROLL_AU_USAC (3) +#if (AACDEC_MAX_NUM_PREROLL_AU < 3) +#undef AACDEC_MAX_NUM_PREROLL_AU +#define AACDEC_MAX_NUM_PREROLL_AU AACDEC_MAX_NUM_PREROLL_AU_USAC +#endif + +typedef struct AAC_DECODER_INSTANCE *HANDLE_AACDECODER; + +enum { L = 0, R = 1 }; + +typedef struct { + unsigned char *buffer; + int bufferSize; + int offset[8]; + int nrElements; +} CAncData; + +typedef enum { NOT_DEFINED = -1, MODE_HQ = 0, MODE_LP = 1 } QMF_MODE; + +typedef struct { + int bsDelay; +} SBR_PARAMS; + +enum { + AACDEC_FLUSH_OFF = 0, + AACDEC_RSV60_CFG_CHANGE_ATSC_FLUSH_ON = 1, + AACDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON = 2, + AACDEC_USAC_DASH_IPF_FLUSH_ON = 3 +}; + +enum { + AACDEC_BUILD_UP_OFF = 0, + AACDEC_RSV60_BUILD_UP_ON = 1, + AACDEC_RSV60_BUILD_UP_ON_IN_BAND = 2, + AACDEC_USAC_BUILD_UP_ON = 3, + AACDEC_RSV60_BUILD_UP_IDLE = 4, + AACDEC_RSV60_BUILD_UP_IDLE_IN_BAND = 5 +}; + +#define AACDEC_CROSSFADE_BITMASK_OFF \ + ((UCHAR)0) /*!< No cross-fade between frames shall be applied at next \ + config change. */ +#define AACDEC_CROSSFADE_BITMASK_PREROLL \ + ((UCHAR)1 << 1) /*!< applyCrossfade is signaled in AudioPreRoll */ + +typedef struct { + /* Usac Extension Elements */ + USAC_EXT_ELEMENT_TYPE usacExtElementType[(3)]; + UINT usacExtElementDefaultLength[(3)]; + UCHAR usacExtElementPayloadFrag[(3)]; +} CUsacCoreExtensions; + +/* AAC decoder (opaque toward userland) struct declaration */ +struct AAC_DECODER_INSTANCE { + INT aacChannels; /*!< Amount of AAC decoder channels allocated. */ + INT ascChannels[(1 * + 1)]; /*!< Amount of AAC decoder channels signalled in ASC. */ + INT blockNumber; /*!< frame counter */ + + INT nrOfLayers; + + INT outputInterleaved; /*!< PCM output format (interleaved/none interleaved). + */ + + INT aacOutDataHeadroom; /*!< Headroom of the output time signal to prevent + clipping */ + + HANDLE_TRANSPORTDEC hInput; /*!< Transport layer handle. */ + + SamplingRateInfo + samplingRateInfo[(1 * 1)]; /*!< Sampling Rate information table */ + + UCHAR + frameOK; /*!< Will be unset if a consistency check, e.g. CRC etc. fails */ + + UINT flags[(1 * 1)]; /*!< Flags for internal decoder use. DO NOT USE + self::streaminfo::flags ! */ + UINT elFlags[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + + 1)]; /*!< Flags for internal decoder use (element specific). DO + NOT USE self::streaminfo::flags ! */ + + MP4_ELEMENT_ID elements[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + + 1)]; /*!< Table where the element Id's are listed */ + UCHAR elTags[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + + 1)]; /*!< Table where the elements id Tags are listed */ + UCHAR chMapping[((8) * 2)]; /*!< Table of MPEG canonical order to bitstream + channel order mapping. */ + + AUDIO_CHANNEL_TYPE channelType[(8)]; /*!< Audio channel type of each output + audio channel (from 0 upto + numChannels). */ + UCHAR channelIndices[(8)]; /*!< Audio channel index for each output audio + channel (from 0 upto numChannels). */ + /* See ISO/IEC 13818-7:2005(E), 8.5.3.2 Explicit channel mapping using a + * program_config_element() */ + + FDK_channelMapDescr mapDescr; /*!< Describes the output channel mapping. */ + UCHAR chMapIndex; /*!< Index to access one line of the channelOutputMapping + table. This is required because not all 8 channel + configurations have the same output mapping. */ + INT sbrDataLen; /*!< Expected length of the SBR remaining in bitbuffer after + the AAC payload has been pared. */ + + CProgramConfig pce; + CStreamInfo + streamInfo; /*!< Pointer to StreamInfo data (read from the bitstream) */ + CAacDecoderChannelInfo + *pAacDecoderChannelInfo[(8)]; /*!< Temporal channel memory */ + CAacDecoderStaticChannelInfo + *pAacDecoderStaticChannelInfo[(8)]; /*!< Persistent channel memory */ + + FIXP_DBL *workBufferCore1; + FIXP_DBL *workBufferCore2; + PCM_DEC *pTimeData2; + INT timeData2Size; + + CpePersistentData *cpeStaticData[( + 3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + + 1)]; /*!< Pointer to persistent data shared by both channels of a CPE. +This structure is allocated once for each CPE. */ + + CConcealParams concealCommonData; + CConcealmentMethod concealMethodUser; + + CUsacCoreExtensions usacCoreExt; /*!< Data and handles to extend USAC FD/LPD + core decoder (SBR, MPS, ...) */ + UINT numUsacElements[(1 * 1)]; + UCHAR usacStereoConfigIndex[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)]; + const CSUsacConfig *pUsacConfig[(1 * 1)]; + INT nbDiv; /*!< number of frame divisions in LPD-domain */ + + UCHAR useLdQmfTimeAlign; + + INT aacChannelsPrev; /*!< The amount of AAC core channels of the last + successful decode call. */ + AUDIO_CHANNEL_TYPE channelTypePrev[(8)]; /*!< Array holding the channelType + values of the last successful + decode call. */ + UCHAR + channelIndicesPrev[(8)]; /*!< Array holding the channelIndices values of + the last successful decode call. */ + + UCHAR + downscaleFactor; /*!< Variable to store a supported ELD downscale factor + of 1, 2, 3 or 4 */ + UCHAR downscaleFactorInBS; /*!< Variable to store the (not necessarily + supported) ELD downscale factor discovered in + the bitstream */ + + HANDLE_SBRDECODER hSbrDecoder; /*!< SBR decoder handle. */ + UCHAR sbrEnabled; /*!< flag to store if SBR has been detected */ + UCHAR sbrEnabledPrev; /*!< flag to store if SBR has been detected from + previous frame */ + UCHAR psPossible; /*!< flag to store if PS is possible */ + SBR_PARAMS sbrParams; /*!< struct to store all sbr parameters */ + + UCHAR *pDrmBsBuffer; /*!< Pointer to dynamic buffer which is used to reverse + the bits of the DRM SBR payload */ + USHORT drmBsBufferSize; /*!< Size of the dynamic buffer which is used to + reverse the bits of the DRM SBR payload */ + FDK_QMF_DOMAIN + qmfDomain; /*!< Instance of module for QMF domain data handling */ + + QMF_MODE qmfModeCurr; /*!< The current QMF mode */ + QMF_MODE qmfModeUser; /*!< The QMF mode requested by the library user */ + + HANDLE_AAC_DRC hDrcInfo; /*!< handle to DRC data structure */ + INT metadataExpiry; /*!< Metadata expiry time in milli-seconds. */ + + void *pMpegSurroundDecoder; /*!< pointer to mpeg surround decoder structure */ + UCHAR mpsEnableUser; /*!< MPS enable user flag */ + UCHAR mpsEnableCurr; /*!< MPS enable decoder state */ + UCHAR mpsApplicable; /*!< MPS applicable */ + SCHAR mpsOutputMode; /*!< setting: normal = 0, binaural = 1, stereo = 2, 5.1ch + = 3 */ + INT mpsOutChannelsLast; /*!< The amount of channels returned by the last + successful MPS decoder call. */ + INT mpsFrameSizeLast; /*!< The frame length returned by the last successful + MPS decoder call. */ + + CAncData ancData; /*!< structure to handle ancillary data */ + + HANDLE_PCM_DOWNMIX hPcmUtils; /*!< privat data for the PCM utils. */ + + TDLimiterPtr hLimiter; /*!< Handle of time domain limiter. */ + UCHAR limiterEnableUser; /*!< The limiter configuration requested by the + library user */ + UCHAR limiterEnableCurr; /*!< The current limiter configuration. */ + + FIXP_DBL extGain[1]; /*!< Gain that must be applied to the output signal. */ + UINT extGainDelay; /*!< Delay that must be accounted for extGain. */ + + HANDLE_DRC_DECODER hUniDrcDecoder; + UCHAR multibandDrcPresent; + UCHAR numTimeSlots; + UINT loudnessInfoSetPosition[3]; + SCHAR defaultTargetLoudness; + + PCM_DEC + *pTimeDataFlush[((8) * 2)]; /*!< Pointer to the flushed time data which + will be used for the crossfade in case of + an USAC DASH IPF config change */ + + UCHAR flushStatus; /*!< Indicates flush status: on|off */ + SCHAR flushCnt; /*!< Flush frame counter */ + UCHAR buildUpStatus; /*!< Indicates build up status: on|off */ + SCHAR buildUpCnt; /*!< Build up frame counter */ + UCHAR hasAudioPreRoll; /*!< Indicates preRoll status: on|off */ + UINT prerollAULength[AACDEC_MAX_NUM_PREROLL_AU + 1]; /*!< Relative offset of + the prerollAU end + position to the AU + start position in the + bitstream */ + INT accessUnit; /*!< Number of the actual processed preroll accessUnit */ + UCHAR applyCrossfade; /*!< If any bit is set, cross-fade for seamless stream + switching is applied */ + + FDK_SignalDelay usacResidualDelay; /*!< Delay residual signal to compensate + for eSBR delay of DMX signal in case of + stereoConfigIndex==2. */ +}; + +#define AAC_DEBUG_EXTHLP \ + "\ +--- AAC-Core ---\n\ + 0x00010000 Header data\n\ + 0x00020000 CRC data\n\ + 0x00040000 Channel info\n\ + 0x00080000 Section data\n\ + 0x00100000 Scalefactor data\n\ + 0x00200000 Pulse data\n\ + 0x00400000 Tns data\n\ + 0x00800000 Quantized spectrum\n\ + 0x01000000 Requantized spectrum\n\ + 0x02000000 Time output\n\ + 0x04000000 Fatal errors\n\ + 0x08000000 Buffer fullness\n\ + 0x10000000 Average bitrate\n\ + 0x20000000 Synchronization\n\ + 0x40000000 Concealment\n\ + 0x7FFF0000 all AAC-Core-Info\n\ +" + +/** + * \brief Synchronise QMF mode for all modules using QMF data. + * \param self decoder handle + */ +void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self); + +/** + * \brief Signal a bit stream interruption to the decoder + * \param self decoder handle + */ +void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self); + +/*! + \brief Initialize ancillary buffer + + \ancData Pointer to ancillary data structure + \buffer Pointer to (external) anc data buffer + \size Size of the buffer pointed on by buffer + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData, + unsigned char *buffer, int size); + +/*! + \brief Get one ancillary data element + + \ancData Pointer to ancillary data structure + \index Index of the anc data element to get + \ptr Pointer to a buffer receiving a pointer to the requested anc data element + \size Pointer to a buffer receiving the length of the requested anc data + element + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index, + unsigned char **ptr, int *size); + +/* initialization of aac decoder */ +LINKSPEC_H HANDLE_AACDECODER CAacDecoder_Open(TRANSPORT_TYPE bsFormat); + +/* Initialization of channel elements */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, + const CSAudioSpecificConfig *asc, + UCHAR configMode, + UCHAR *configChanged); +/*! + \brief Decodes one aac frame + + The function decodes one aac frame. The decoding of coupling channel + elements are not supported. The transport layer might signal, that the + data of the current frame is invalid, e.g. as a result of a packet + loss in streaming mode. + The bitstream position of transportDec_GetBitstream(self->hInput) must + be exactly the end of the access unit, including all byte alignment bits. + For this purpose, the variable auStartAnchor is used. + + \return error status +*/ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_DecodeFrame( + HANDLE_AACDECODER self, const UINT flags, PCM_DEC *pTimeData, + const INT timeDataSize, const int timeDataChannelOffset); + +/* Free config dependent AAC memory */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_FreeMem(HANDLE_AACDECODER self, + const int subStreamIndex); + +/* Prepare crossfade for USAC DASH IPF config change */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade( + const PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels, + const INT frameSize, const INT interleaved); + +/* Apply crossfade for USAC DASH IPF config change */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade( + PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels, + const INT frameSize, const INT interleaved); + +/* Set flush and build up mode */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_CtrlCFGChange(HANDLE_AACDECODER self, + UCHAR flushStatus, + SCHAR flushCnt, + UCHAR buildUpStatus, + SCHAR buildUpCnt); + +/* Parse preRoll Extension Payload */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_PreRollExtensionPayloadParse( + HANDLE_AACDECODER self, UINT *numPrerollAU, UINT *prerollAUOffset, + UINT *prerollAULength); + +/* Destroy aac decoder */ +LINKSPEC_H void CAacDecoder_Close(HANDLE_AACDECODER self); + +/* get streaminfo handle from decoder */ +LINKSPEC_H CStreamInfo *CAacDecoder_GetStreamInfo(HANDLE_AACDECODER self); + +#endif /* #ifndef AACDECODER_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdecoder_lib.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdecoder_lib.cpp new file mode 100644 index 0000000000000..5319b7c5837ba --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/aacdecoder_lib.cpp @@ -0,0 +1,2124 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: + +*******************************************************************************/ + +#include "aacdecoder_lib.h" + +#include "aac_ram.h" +#include "aacdecoder.h" +#include "tpdec_lib.h" +#include "FDK_core.h" /* FDK_tools version info */ + +#include "sbrdecoder.h" + +#include "conceal.h" + +#include "aacdec_drc.h" + +#include "sac_dec_lib.h" + +#include "pcm_utils.h" + +/* Decoder library info */ +#define AACDECODER_LIB_VL0 3 +#define AACDECODER_LIB_VL1 2 +#define AACDECODER_LIB_VL2 0 +#define AACDECODER_LIB_TITLE "AAC Decoder Lib" +#ifdef SUPPRESS_BUILD_DATE_INFO +#define AACDECODER_LIB_BUILD_DATE "" +#define AACDECODER_LIB_BUILD_TIME "" +#else +#define AACDECODER_LIB_BUILD_DATE __DATE__ +#define AACDECODER_LIB_BUILD_TIME __TIME__ +#endif + +static AAC_DECODER_ERROR setConcealMethod(const HANDLE_AACDECODER self, + const INT method); + +static void aacDecoder_setMetadataExpiry(const HANDLE_AACDECODER self, + const INT value) { + /* check decoder handle */ + if (self != NULL) { + INT mdExpFrame = 0; /* default: disable */ + + if ((value > 0) && + (self->streamInfo.aacSamplesPerFrame > + 0)) { /* Determine the corresponding number of frames: */ + FIXP_DBL frameTime = fDivNorm(self->streamInfo.aacSampleRate, + self->streamInfo.aacSamplesPerFrame * 1000); + mdExpFrame = fMultIceil(frameTime, value); + } + + /* Configure DRC module */ + aacDecoder_drcSetParam(self->hDrcInfo, DRC_DATA_EXPIRY_FRAME, mdExpFrame); + + /* Configure PCM downmix module */ + pcmDmx_SetParam(self->hPcmUtils, DMX_BS_DATA_EXPIRY_FRAME, mdExpFrame); + } +} + +LINKSPEC_CPP AAC_DECODER_ERROR +aacDecoder_GetFreeBytes(const HANDLE_AACDECODER self, UINT *pFreeBytes) { + /* reset free bytes */ + *pFreeBytes = 0; + + /* check handle */ + if (!self) return AAC_DEC_INVALID_HANDLE; + + /* return nr of free bytes */ + HANDLE_FDK_BITSTREAM hBs = transportDec_GetBitstream(self->hInput, 0); + *pFreeBytes = FDKgetFreeBits(hBs) >> 3; + + /* success */ + return AAC_DEC_OK; +} + +/** + * Config Decoder using a CSAudioSpecificConfig struct. + */ +static LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_Config( + HANDLE_AACDECODER self, const CSAudioSpecificConfig *pAscStruct, + UCHAR configMode, UCHAR *configChanged) { + AAC_DECODER_ERROR err; + + /* Initialize AAC core decoder, and update self->streaminfo */ + err = CAacDecoder_Init(self, pAscStruct, configMode, configChanged); + + if (!FDK_chMapDescr_isValid(&self->mapDescr)) { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + + return err; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_ConfigRaw(HANDLE_AACDECODER self, + UCHAR *conf[], + const UINT length[]) { + AAC_DECODER_ERROR err = AAC_DEC_OK; + TRANSPORTDEC_ERROR errTp; + UINT layer, nrOfLayers = self->nrOfLayers; + + for (layer = 0; layer < nrOfLayers; layer++) { + if (length[layer] > 0) { + errTp = transportDec_OutOfBandConfig(self->hInput, conf[layer], + length[layer], layer); + if (errTp != TRANSPORTDEC_OK) { + switch (errTp) { + case TRANSPORTDEC_NEED_TO_RESTART: + err = AAC_DEC_NEED_TO_RESTART; + break; + case TRANSPORTDEC_UNSUPPORTED_FORMAT: + err = AAC_DEC_UNSUPPORTED_FORMAT; + break; + default: + err = AAC_DEC_UNKNOWN; + break; + } + /* if baselayer is OK we continue decoding */ + if (layer >= 1) { + self->nrOfLayers = layer; + err = AAC_DEC_OK; + } + break; + } + } + } + + return err; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_RawISOBMFFData(HANDLE_AACDECODER self, + UCHAR *buffer, + UINT length) { + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + AAC_DECODER_ERROR err = AAC_DEC_OK; + + if (length < 8) return AAC_DEC_UNKNOWN; + + while (length >= 8) { + UINT size = + (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; + DRC_DEC_ERROR uniDrcErr = DRC_DEC_OK; + + if (length < size) return AAC_DEC_UNKNOWN; + if (size <= 8) return AAC_DEC_UNKNOWN; + + FDKinitBitStream(hBs, buffer + 8, 0x10000000, (size - 8) * 8); + + if ((buffer[4] == 'l') && (buffer[5] == 'u') && (buffer[6] == 'd') && + (buffer[7] == 't')) { + uniDrcErr = FDK_drcDec_ReadLoudnessBox(self->hUniDrcDecoder, hBs); + } else if ((buffer[4] == 'd') && (buffer[5] == 'm') && (buffer[6] == 'i') && + (buffer[7] == 'x')) { + uniDrcErr = + FDK_drcDec_ReadDownmixInstructions_Box(self->hUniDrcDecoder, hBs); + } else if ((buffer[4] == 'u') && (buffer[5] == 'd') && (buffer[6] == 'i') && + (buffer[7] == '2')) { + uniDrcErr = + FDK_drcDec_ReadUniDrcInstructions_Box(self->hUniDrcDecoder, hBs); + } else if ((buffer[4] == 'u') && (buffer[5] == 'd') && (buffer[6] == 'c') && + (buffer[7] == '2')) { + uniDrcErr = + FDK_drcDec_ReadUniDrcCoefficients_Box(self->hUniDrcDecoder, hBs); + } + + if (uniDrcErr != DRC_DEC_OK) err = AAC_DEC_UNKNOWN; + + buffer += size; + length -= size; + } + + return err; +} + +static INT aacDecoder_ConfigCallback(void *handle, + const CSAudioSpecificConfig *pAscStruct, + UCHAR configMode, UCHAR *configChanged) { + HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle; + AAC_DECODER_ERROR err = AAC_DEC_OK; + TRANSPORTDEC_ERROR errTp; + + FDK_ASSERT(self != NULL); + { + { err = aacDecoder_Config(self, pAscStruct, configMode, configChanged); } + } + if (err == AAC_DEC_OK) { + /* + revert concealment method if either + - Interpolation concealment might not be meaningful + - Interpolation concealment is not implemented + */ + if ((self->flags[0] & (AC_LD | AC_ELD) && + (self->concealMethodUser == ConcealMethodNone) && + CConcealment_GetDelay(&self->concealCommonData) > + 0) /* might not be meaningful but allow if user has set it + expicitly */ + || (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA) && + CConcealment_GetDelay(&self->concealCommonData) > + 0) /* not implemented */ + ) { + /* Revert to error concealment method Noise Substitution. + Because interpolation is not implemented for USAC or + the additional delay is unwanted for low delay codecs. */ + setConcealMethod(self, 1); + } + aacDecoder_setMetadataExpiry(self, self->metadataExpiry); + errTp = TRANSPORTDEC_OK; + } else { + if (err == AAC_DEC_NEED_TO_RESTART) { + errTp = TRANSPORTDEC_NEED_TO_RESTART; + } else if (IS_INIT_ERROR(err)) { + errTp = TRANSPORTDEC_UNSUPPORTED_FORMAT; + } /* Fatal errors */ + else { + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + } + + return errTp; +} + +static INT aacDecoder_FreeMemCallback(void *handle, + const CSAudioSpecificConfig *pAscStruct) { + TRANSPORTDEC_ERROR errTp = TRANSPORTDEC_OK; + HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle; + + const int subStreamIndex = 0; + + FDK_ASSERT(self != NULL); + + if (CAacDecoder_FreeMem(self, subStreamIndex) != AAC_DEC_OK) { + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + + /* free Ram_SbrDecoder and Ram_SbrDecChannel */ + if (self->hSbrDecoder != NULL) { + if (sbrDecoder_FreeMem(&self->hSbrDecoder) != SBRDEC_OK) { + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + } + + /* free pSpatialDec and mpsData */ + if (self->pMpegSurroundDecoder != NULL) { + if (mpegSurroundDecoder_FreeMem( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder) != MPS_OK) { + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + } + + /* free persistent qmf domain buffer, QmfWorkBufferCore3, QmfWorkBufferCore4, + * QmfWorkBufferCore5 and configuration variables */ + FDK_QmfDomain_FreeMem(&self->qmfDomain); + + return errTp; +} + +static INT aacDecoder_CtrlCFGChangeCallback( + void *handle, const CCtrlCFGChange *pCtrlCFGChangeStruct) { + TRANSPORTDEC_ERROR errTp = TRANSPORTDEC_OK; + HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle; + + if (self != NULL) { + CAacDecoder_CtrlCFGChange( + self, pCtrlCFGChangeStruct->flushStatus, pCtrlCFGChangeStruct->flushCnt, + pCtrlCFGChangeStruct->buildUpStatus, pCtrlCFGChangeStruct->buildUpCnt); + } else { + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + + return errTp; +} + +static INT aacDecoder_SbrCallback( + void *handle, HANDLE_FDK_BITSTREAM hBs, const INT sampleRateIn, + const INT sampleRateOut, const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, const MP4_ELEMENT_ID elementID, + const INT elementIndex, const UCHAR harmonicSBR, + const UCHAR stereoConfigIndex, const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor) { + HANDLE_SBRDECODER self = (HANDLE_SBRDECODER)handle; + + INT errTp = sbrDecoder_Header(self, hBs, sampleRateIn, sampleRateOut, + samplesPerFrame, coreCodec, elementID, + elementIndex, harmonicSBR, stereoConfigIndex, + configMode, configChanged, downscaleFactor); + + return errTp; +} + +static INT aacDecoder_SscCallback( + void *handle, HANDLE_FDK_BITSTREAM hBs, const AUDIO_OBJECT_TYPE coreCodec, + const INT samplingRate, const INT frameSize, const INT numChannels, + const INT stereoConfigIndex, const INT coreSbrFrameLengthIndex, + const INT configBytes, const UCHAR configMode, UCHAR *configChanged) { + SACDEC_ERROR err; + TRANSPORTDEC_ERROR errTp; + HANDLE_AACDECODER hAacDecoder = (HANDLE_AACDECODER)handle; + + err = mpegSurroundDecoder_Config( + (CMpegSurroundDecoder *)hAacDecoder->pMpegSurroundDecoder, hBs, coreCodec, + samplingRate, frameSize, numChannels, stereoConfigIndex, + coreSbrFrameLengthIndex, configBytes, configMode, configChanged); + + switch (err) { + case MPS_UNSUPPORTED_CONFIG: + /* MPS found but invalid or not decodable by this instance */ + /* We switch off MPS and keep going */ + hAacDecoder->mpsEnableCurr = 0; + hAacDecoder->mpsApplicable = 0; + errTp = TRANSPORTDEC_OK; + break; + case MPS_PARSE_ERROR: + /* MPS found but invalid or not decodable by this instance */ + hAacDecoder->mpsEnableCurr = 0; + hAacDecoder->mpsApplicable = 0; + if ((coreCodec == AOT_USAC) || (coreCodec == AOT_DRM_USAC) || + IS_LOWDELAY(coreCodec)) { + errTp = TRANSPORTDEC_PARSE_ERROR; + } else { + errTp = TRANSPORTDEC_OK; + } + break; + case MPS_OK: + hAacDecoder->mpsApplicable = 1; + errTp = TRANSPORTDEC_OK; + break; + default: + /* especially Parsing error is critical for transport layer */ + hAacDecoder->mpsApplicable = 0; + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + + return (INT)errTp; +} + +static INT aacDecoder_UniDrcCallback(void *handle, HANDLE_FDK_BITSTREAM hBs, + const INT fullPayloadLength, + const INT payloadType, + const INT subStreamIndex, + const INT payloadStart, + const AUDIO_OBJECT_TYPE aot) { + DRC_DEC_ERROR err = DRC_DEC_OK; + TRANSPORTDEC_ERROR errTp; + HANDLE_AACDECODER hAacDecoder = (HANDLE_AACDECODER)handle; + DRC_DEC_CODEC_MODE drcDecCodecMode = DRC_DEC_CODEC_MODE_UNDEFINED; + UCHAR dummyBuffer[4] = {0}; + FDK_BITSTREAM dummyBs; + HANDLE_FDK_BITSTREAM hReadBs; + + if (subStreamIndex != 0) { + return TRANSPORTDEC_OK; + } + + if (hBs == NULL) { + /* use dummy zero payload to clear memory */ + hReadBs = &dummyBs; + FDKinitBitStream(hReadBs, dummyBuffer, 4, 24); + } else { + hReadBs = hBs; + } + + if (aot == AOT_USAC) { + drcDecCodecMode = DRC_DEC_MPEG_D_USAC; + } + + err = FDK_drcDec_SetCodecMode(hAacDecoder->hUniDrcDecoder, drcDecCodecMode); + if (err) return (INT)TRANSPORTDEC_UNKOWN_ERROR; + + if (payloadType == 0) /* uniDrcConfig */ + { + err = FDK_drcDec_ReadUniDrcConfig(hAacDecoder->hUniDrcDecoder, hReadBs); + } else /* loudnessInfoSet */ + { + err = FDK_drcDec_ReadLoudnessInfoSet(hAacDecoder->hUniDrcDecoder, hReadBs); + hAacDecoder->loudnessInfoSetPosition[1] = payloadStart; + hAacDecoder->loudnessInfoSetPosition[2] = fullPayloadLength; + } + + if (err == DRC_DEC_OK) + errTp = TRANSPORTDEC_OK; + else + errTp = TRANSPORTDEC_UNKOWN_ERROR; + + return (INT)errTp; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_AncDataInit(HANDLE_AACDECODER self, + UCHAR *buffer, int size) { + CAncData *ancData = &self->ancData; + + return CAacDecoder_AncDataInit(ancData, buffer, size); +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_AncDataGet(HANDLE_AACDECODER self, + int index, UCHAR **ptr, + int *size) { + CAncData *ancData = &self->ancData; + + return CAacDecoder_AncDataGet(ancData, index, ptr, size); +} + +/* If MPS is present in stream, but not supported by this instance, we'll + have to switch off MPS and use QMF synthesis in the SBR module if required */ +static int isSupportedMpsConfig(AUDIO_OBJECT_TYPE aot, + unsigned int numInChannels, + unsigned int fMpsPresent) { + LIB_INFO libInfo[FDK_MODULE_LAST]; + UINT mpsCaps; + int isSupportedCfg = 1; + + FDKinitLibInfo(libInfo); + + mpegSurroundDecoder_GetLibInfo(libInfo); + + mpsCaps = FDKlibInfo_getCapabilities(libInfo, FDK_MPSDEC); + + if (!(mpsCaps & CAPF_MPS_LD) && IS_LOWDELAY(aot)) { + /* We got an LD AOT but MPS decoder does not support LD. */ + isSupportedCfg = 0; + } + if ((mpsCaps & CAPF_MPS_LD) && IS_LOWDELAY(aot) && !fMpsPresent) { + /* We got an LD AOT and the MPS decoder supports it. + * But LD-MPS is not explicitly signaled. */ + isSupportedCfg = 0; + } + if (!(mpsCaps & CAPF_MPS_USAC) && IS_USAC(aot)) { + /* We got an USAC AOT but MPS decoder does not support USAC. */ + isSupportedCfg = 0; + } + if (!(mpsCaps & CAPF_MPS_STD) && !IS_LOWDELAY(aot) && !IS_USAC(aot)) { + /* We got an GA AOT but MPS decoder does not support it. */ + isSupportedCfg = 0; + } + /* Check whether the MPS modul supports the given number of input channels: */ + switch (numInChannels) { + case 1: + if (!(mpsCaps & CAPF_MPS_1CH_IN)) { + /* We got a one channel input to MPS decoder but it does not support it. + */ + isSupportedCfg = 0; + } + break; + case 2: + if (!(mpsCaps & CAPF_MPS_2CH_IN)) { + /* We got a two channel input to MPS decoder but it does not support it. + */ + isSupportedCfg = 0; + } + break; + case 5: + case 6: + if (!(mpsCaps & CAPF_MPS_6CH_IN)) { + /* We got a six channel input to MPS decoder but it does not support it. + */ + isSupportedCfg = 0; + } + break; + default: + isSupportedCfg = 0; + } + + return (isSupportedCfg); +} + +static AAC_DECODER_ERROR setConcealMethod( + const HANDLE_AACDECODER self, /*!< Handle of the decoder instance */ + const INT method) { + AAC_DECODER_ERROR errorStatus = AAC_DEC_OK; + CConcealParams *pConcealData = NULL; + int method_revert = 0; + HANDLE_SBRDECODER hSbrDec = NULL; + HANDLE_AAC_DRC hDrcInfo = NULL; + HANDLE_PCM_DOWNMIX hPcmDmx = NULL; + CConcealmentMethod backupMethod = ConcealMethodNone; + int backupDelay = 0; + int bsDelay = 0; + + /* check decoder handle */ + if (self != NULL) { + pConcealData = &self->concealCommonData; + hSbrDec = self->hSbrDecoder; + hDrcInfo = self->hDrcInfo; + hPcmDmx = self->hPcmUtils; + if (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA) && method >= 2) { + /* Interpolation concealment is not implemented for USAC/RSVD50 */ + /* errorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; */ + method_revert = 1; + } + if (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA) && method >= 2) { + /* Interpolation concealment is not implemented for USAC/RSVD50 */ + errorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; + } + } + + /* Get current method/delay */ + backupMethod = CConcealment_GetMethod(pConcealData); + backupDelay = CConcealment_GetDelay(pConcealData); + + /* Be sure to set AAC and SBR concealment method simultaneously! */ + errorStatus = CConcealment_SetParams( + pConcealData, + (method_revert == 0) ? (int)method : (int)1, // concealMethod + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealFadeOutSlope + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealFadeInSlope + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealMuteRelease + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED // concealComfNoiseLevel + ); + if ((errorStatus != AAC_DEC_OK) && (errorStatus != AAC_DEC_INVALID_HANDLE)) { + goto bail; + } + + /* Get new delay */ + bsDelay = CConcealment_GetDelay(pConcealData); + + { + SBR_ERROR sbrErr = SBRDEC_OK; + + /* set SBR bitstream delay */ + sbrErr = sbrDecoder_SetParam(hSbrDec, SBR_SYSTEM_BITSTREAM_DELAY, bsDelay); + + switch (sbrErr) { + case SBRDEC_OK: + case SBRDEC_NOT_INITIALIZED: + if (self != NULL) { + /* save the param value and set later + (when SBR has been initialized) */ + self->sbrParams.bsDelay = bsDelay; + } + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; + } + } + + errorStatus = aacDecoder_drcSetParam(hDrcInfo, DRC_BS_DELAY, bsDelay); + if ((errorStatus != AAC_DEC_OK) && (errorStatus != AAC_DEC_INVALID_HANDLE)) { + goto bail; + } + + if (errorStatus == AAC_DEC_OK) { + PCMDMX_ERROR err = pcmDmx_SetParam(hPcmDmx, DMX_BS_DATA_DELAY, bsDelay); + switch (err) { + case PCMDMX_INVALID_HANDLE: + errorStatus = AAC_DEC_INVALID_HANDLE; + break; + case PCMDMX_OK: + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; + } + } + +bail: + if ((errorStatus != AAC_DEC_OK) && (errorStatus != AAC_DEC_INVALID_HANDLE)) { + /* Revert to the initial state */ + CConcealment_SetParams( + pConcealData, (int)backupMethod, AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED); + /* Revert SBR bitstream delay */ + sbrDecoder_SetParam(hSbrDec, SBR_SYSTEM_BITSTREAM_DELAY, backupDelay); + /* Revert DRC bitstream delay */ + aacDecoder_drcSetParam(hDrcInfo, DRC_BS_DELAY, backupDelay); + /* Revert PCM mixdown bitstream delay */ + pcmDmx_SetParam(hPcmDmx, DMX_BS_DATA_DELAY, backupDelay); + } + + return errorStatus; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_SetParam( + const HANDLE_AACDECODER self, /*!< Handle of the decoder instance */ + const AACDEC_PARAM param, /*!< Parameter to set */ + const INT value) /*!< Parameter valued */ +{ + AAC_DECODER_ERROR errorStatus = AAC_DEC_OK; + HANDLE_TRANSPORTDEC hTpDec = NULL; + TRANSPORTDEC_ERROR errTp = TRANSPORTDEC_OK; + HANDLE_AAC_DRC hDrcInfo = NULL; + HANDLE_PCM_DOWNMIX hPcmDmx = NULL; + PCMDMX_ERROR dmxErr = PCMDMX_OK; + TDLimiterPtr hPcmTdl = NULL; + DRC_DEC_ERROR uniDrcErr = DRC_DEC_OK; + + /* check decoder handle */ + if (self != NULL) { + hTpDec = self->hInput; + hDrcInfo = self->hDrcInfo; + hPcmDmx = self->hPcmUtils; + hPcmTdl = self->hLimiter; + } else { + errorStatus = AAC_DEC_INVALID_HANDLE; + goto bail; + } + + /* configure the subsystems */ + switch (param) { + case AAC_PCM_MIN_OUTPUT_CHANNELS: + if (value < -1 || value > (8)) { + return AAC_DEC_SET_PARAM_FAIL; + } + dmxErr = pcmDmx_SetParam(hPcmDmx, MIN_NUMBER_OF_OUTPUT_CHANNELS, value); + break; + + case AAC_PCM_MAX_OUTPUT_CHANNELS: + if (value < -1 || value > (8)) { + return AAC_DEC_SET_PARAM_FAIL; + } + dmxErr = pcmDmx_SetParam(hPcmDmx, MAX_NUMBER_OF_OUTPUT_CHANNELS, value); + + if (dmxErr != PCMDMX_OK) { + goto bail; + } + errorStatus = + aacDecoder_drcSetParam(hDrcInfo, MAX_OUTPUT_CHANNELS, value); + if (value > 0) { + uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, + DRC_DEC_TARGET_CHANNEL_COUNT_REQUESTED, + (FIXP_DBL)value); + } + break; + + case AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE: + dmxErr = pcmDmx_SetParam(hPcmDmx, DMX_DUAL_CHANNEL_MODE, value); + break; + + case AAC_PCM_LIMITER_ENABLE: + if (value < -2 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + self->limiterEnableUser = value; + break; + + case AAC_PCM_LIMITER_ATTACK_TIME: + if (value <= 0) { /* module function converts value to unsigned */ + return AAC_DEC_SET_PARAM_FAIL; + } + switch (pcmLimiter_SetAttack(hPcmTdl, value)) { + case TDLIMIT_OK: + break; + case TDLIMIT_INVALID_HANDLE: + return AAC_DEC_INVALID_HANDLE; + case TDLIMIT_INVALID_PARAMETER: + default: + return AAC_DEC_SET_PARAM_FAIL; + } + break; + + case AAC_PCM_LIMITER_RELEAS_TIME: + if (value <= 0) { /* module function converts value to unsigned */ + return AAC_DEC_SET_PARAM_FAIL; + } + switch (pcmLimiter_SetRelease(hPcmTdl, value)) { + case TDLIMIT_OK: + break; + case TDLIMIT_INVALID_HANDLE: + return AAC_DEC_INVALID_HANDLE; + case TDLIMIT_INVALID_PARAMETER: + default: + return AAC_DEC_SET_PARAM_FAIL; + } + break; + + case AAC_METADATA_PROFILE: { + DMX_PROFILE_TYPE dmxProfile; + INT mdExpiry = -1; /* in ms (-1: don't change) */ + + switch ((AAC_MD_PROFILE)value) { + case AAC_MD_PROFILE_MPEG_STANDARD: + dmxProfile = DMX_PRFL_STANDARD; + break; + case AAC_MD_PROFILE_MPEG_LEGACY: + dmxProfile = DMX_PRFL_MATRIX_MIX; + break; + case AAC_MD_PROFILE_MPEG_LEGACY_PRIO: + dmxProfile = DMX_PRFL_FORCE_MATRIX_MIX; + break; + case AAC_MD_PROFILE_ARIB_JAPAN: + dmxProfile = DMX_PRFL_ARIB_JAPAN; + mdExpiry = 550; /* ms */ + break; + default: + return AAC_DEC_SET_PARAM_FAIL; + } + dmxErr = pcmDmx_SetParam(hPcmDmx, DMX_PROFILE_SETTING, (INT)dmxProfile); + if (dmxErr != PCMDMX_OK) { + goto bail; + } + if ((self != NULL) && (mdExpiry >= 0)) { + self->metadataExpiry = mdExpiry; + /* Determine the corresponding number of frames and configure all + * related modules. */ + aacDecoder_setMetadataExpiry(self, mdExpiry); + } + } break; + + case AAC_METADATA_EXPIRY_TIME: + if (value < 0) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self != NULL) { + self->metadataExpiry = value; + /* Determine the corresponding number of frames and configure all + * related modules. */ + aacDecoder_setMetadataExpiry(self, value); + } + break; + + case AAC_PCM_OUTPUT_CHANNEL_MAPPING: + if (value < 0 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + /* CAUTION: The given value must be inverted to match the logic! */ + FDK_chMapDescr_setPassThrough(&self->mapDescr, !value); + break; + + case AAC_QMF_LOWPOWER: + if (value < -1 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + + /** + * Set QMF mode (might be overriden) + * 0:HQ (complex) + * 1:LP (partially complex) + */ + self->qmfModeUser = (QMF_MODE)value; + break; + + case AAC_DRC_ATTENUATION_FACTOR: + /* DRC compression factor (where 0 is no and 127 is max compression) */ + if ((value < 0) || (value > 127)) { + return AAC_DEC_SET_PARAM_FAIL; + } + errorStatus = aacDecoder_drcSetParam(hDrcInfo, DRC_CUT_SCALE, value); + uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_COMPRESS, + value * (FL2FXCONST_DBL(0.5f / 127.0f))); + break; + + case AAC_DRC_BOOST_FACTOR: + /* DRC boost factor (where 0 is no and 127 is max boost) */ + if ((value < 0) || (value > 127)) { + return AAC_DEC_SET_PARAM_FAIL; + } + errorStatus = aacDecoder_drcSetParam(hDrcInfo, DRC_BOOST_SCALE, value); + uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_BOOST, + value * (FL2FXCONST_DBL(0.5f / 127.0f))); + break; + + case AAC_DRC_REFERENCE_LEVEL: + if ((value >= 0) && + ((value < 40) || (value > 127))) /* allowed range: -10 to -31.75 dB */ + return AAC_DEC_SET_PARAM_FAIL; + /* DRC target reference level quantized in 0.25dB steps using values + [40..127]. Negative values switch off loudness normalisation. Negative + values also switch off MPEG-4 DRC, while MPEG-D DRC can be separately + switched on/off with AAC_UNIDRC_SET_EFFECT */ + errorStatus = aacDecoder_drcSetParam(hDrcInfo, TARGET_REF_LEVEL, value); + uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, + DRC_DEC_LOUDNESS_NORMALIZATION_ON, + (FIXP_DBL)(value >= 0)); + /* set target loudness also for MPEG-D DRC */ + self->defaultTargetLoudness = (SCHAR)value; + break; + + case AAC_DRC_HEAVY_COMPRESSION: + /* Don't need to overwrite cut/boost values */ + errorStatus = + aacDecoder_drcSetParam(hDrcInfo, APPLY_HEAVY_COMPRESSION, value); + break; + + case AAC_DRC_DEFAULT_PRESENTATION_MODE: + /* DRC default presentation mode */ + errorStatus = + aacDecoder_drcSetParam(hDrcInfo, DEFAULT_PRESENTATION_MODE, value); + break; + + case AAC_DRC_ENC_TARGET_LEVEL: + /* Encoder target level for light (i.e. not heavy) compression: + Target reference level assumed at encoder for deriving limiting gains + */ + errorStatus = + aacDecoder_drcSetParam(hDrcInfo, ENCODER_TARGET_LEVEL, value); + break; + + case AAC_UNIDRC_SET_EFFECT: + if ((value < -1) || (value > 6)) return AAC_DEC_SET_PARAM_FAIL; + uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_EFFECT_TYPE, + (FIXP_DBL)value); + break; + case AAC_UNIDRC_ALBUM_MODE: + uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_ALBUM_MODE, + (FIXP_DBL)value); + break; + + case AAC_TPDEC_CLEAR_BUFFER: + errTp = transportDec_SetParam(hTpDec, TPDEC_PARAM_RESET, 1); + self->streamInfo.numLostAccessUnits = 0; + self->streamInfo.numBadBytes = 0; + self->streamInfo.numTotalBytes = 0; + /* aacDecoder_SignalInterruption(self); */ + break; + case AAC_CONCEAL_METHOD: + /* Changing the concealment method can introduce additional bitstream + delay. And that in turn affects sub libraries and modules which makes + the whole thing quite complex. So the complete changing routine is + packed into a helper function which keeps all modules and libs in a + consistent state even in the case an error occures. */ + errorStatus = setConcealMethod(self, value); + if (errorStatus == AAC_DEC_OK) { + self->concealMethodUser = (CConcealmentMethod)value; + } + break; + + default: + return AAC_DEC_SET_PARAM_FAIL; + } /* switch(param) */ + +bail: + + if (errorStatus == AAC_DEC_OK) { + /* Check error code returned by DMX module library: */ + switch (dmxErr) { + case PCMDMX_OK: + break; + case PCMDMX_INVALID_HANDLE: + errorStatus = AAC_DEC_INVALID_HANDLE; + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + } + } + + if (errTp != TRANSPORTDEC_OK && errorStatus == AAC_DEC_OK) { + errorStatus = AAC_DEC_SET_PARAM_FAIL; + } + + if (errorStatus == AAC_DEC_OK) { + /* Check error code returned by MPEG-D DRC decoder library: */ + switch (uniDrcErr) { + case 0: + break; + case -9998: + errorStatus = AAC_DEC_INVALID_HANDLE; + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + break; + } + } + + return (errorStatus); +} +LINKSPEC_CPP HANDLE_AACDECODER aacDecoder_Open(TRANSPORT_TYPE transportFmt, + UINT nrOfLayers) { + AAC_DECODER_INSTANCE *aacDec = NULL; + HANDLE_TRANSPORTDEC pIn; + int err = 0; + int stereoConfigIndex = -1; + + UINT nrOfLayers_min = fMin(nrOfLayers, (UINT)1); + + /* Allocate transport layer struct. */ + pIn = transportDec_Open(transportFmt, TP_FLAG_MPEG4, nrOfLayers_min); + if (pIn == NULL) { + return NULL; + } + + transportDec_SetParam(pIn, TPDEC_PARAM_IGNORE_BUFFERFULLNESS, 1); + + /* Allocate AAC decoder core struct. */ + aacDec = CAacDecoder_Open(transportFmt); + + if (aacDec == NULL) { + transportDec_Close(&pIn); + goto bail; + } + aacDec->hInput = pIn; + + aacDec->nrOfLayers = nrOfLayers_min; + + /* Setup channel mapping descriptor. */ + FDK_chMapDescr_init(&aacDec->mapDescr, NULL, 0, 0); + + /* Register Config Update callback. */ + transportDec_RegisterAscCallback(pIn, aacDecoder_ConfigCallback, + (void *)aacDec); + + /* Register Free Memory callback. */ + transportDec_RegisterFreeMemCallback(pIn, aacDecoder_FreeMemCallback, + (void *)aacDec); + + /* Register config switch control callback. */ + transportDec_RegisterCtrlCFGChangeCallback( + pIn, aacDecoder_CtrlCFGChangeCallback, (void *)aacDec); + + FDKmemclear(&aacDec->qmfDomain, sizeof(FDK_QMF_DOMAIN)); + /* open SBR decoder */ + if (SBRDEC_OK != sbrDecoder_Open(&aacDec->hSbrDecoder, &aacDec->qmfDomain)) { + err = -1; + goto bail; + } + aacDec->qmfModeUser = NOT_DEFINED; + transportDec_RegisterSbrCallback(aacDec->hInput, aacDecoder_SbrCallback, + (void *)aacDec->hSbrDecoder); + + if (mpegSurroundDecoder_Open( + (CMpegSurroundDecoder **)&aacDec->pMpegSurroundDecoder, + stereoConfigIndex, &aacDec->qmfDomain)) { + err = -1; + goto bail; + } + /* Set MPEG Surround defaults */ + aacDec->mpsEnableUser = 0; + aacDec->mpsEnableCurr = 0; + aacDec->mpsApplicable = 0; + aacDec->mpsOutputMode = (SCHAR)SACDEC_OUT_MODE_NORMAL; + transportDec_RegisterSscCallback(pIn, aacDecoder_SscCallback, (void *)aacDec); + + { + if (FDK_drcDec_Open(&(aacDec->hUniDrcDecoder), DRC_DEC_ALL) != 0) { + err = -1; + goto bail; + } + } + + transportDec_RegisterUniDrcConfigCallback(pIn, aacDecoder_UniDrcCallback, + (void *)aacDec, + aacDec->loudnessInfoSetPosition); + aacDec->defaultTargetLoudness = (SCHAR)96; + + pcmDmx_Open(&aacDec->hPcmUtils); + if (aacDec->hPcmUtils == NULL) { + err = -1; + goto bail; + } + + aacDec->hLimiter = + pcmLimiter_Create(TDL_ATTACK_DEFAULT_MS, TDL_RELEASE_DEFAULT_MS, + (FIXP_DBL)MAXVAL_DBL, (8), 96000); + if (NULL == aacDec->hLimiter) { + err = -1; + goto bail; + } + aacDec->limiterEnableUser = (UCHAR)-1; + aacDec->limiterEnableCurr = 0; + + /* Assure that all modules have same delay */ + if (setConcealMethod(aacDec, + CConcealment_GetMethod(&aacDec->concealCommonData))) { + err = -1; + goto bail; + } + +bail: + if (err == -1) { + aacDecoder_Close(aacDec); + aacDec = NULL; + } + return aacDec; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_Fill(HANDLE_AACDECODER self, + UCHAR *pBuffer[], + const UINT bufferSize[], + UINT *pBytesValid) { + TRANSPORTDEC_ERROR tpErr; + /* loop counter for layers; if not TT_MP4_RAWPACKETS used as index for only + available layer */ + INT layer = 0; + INT nrOfLayers = self->nrOfLayers; + + { + for (layer = 0; layer < nrOfLayers; layer++) { + { + tpErr = transportDec_FillData(self->hInput, pBuffer[layer], + bufferSize[layer], &pBytesValid[layer], + layer); + if (tpErr != TRANSPORTDEC_OK) { + return AAC_DEC_UNKNOWN; /* Must be an internal error */ + } + } + } + } + + return AAC_DEC_OK; +} + +static void aacDecoder_SignalInterruption(HANDLE_AACDECODER self) { + CAacDecoder_SignalInterruption(self); + + if (self->hSbrDecoder != NULL) { + sbrDecoder_SetParam(self->hSbrDecoder, SBR_BS_INTERRUPTION, 1); + } + if (self->mpsEnableUser) { + mpegSurroundDecoder_SetParam( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, + SACDEC_BS_INTERRUPTION, 1); + } +} + +static void aacDecoder_UpdateBitStreamCounters(CStreamInfo *pSi, + HANDLE_FDK_BITSTREAM hBs, + INT nBits, + AAC_DECODER_ERROR ErrorStatus) { + /* calculate bit difference (amount of bits moved forward) */ + nBits = nBits - (INT)FDKgetValidBits(hBs); + + /* Note: The amount of bits consumed might become negative when parsing a + bit stream with several sub frames, and we find out at the last sub frame + that the total frame length does not match the sum of sub frame length. + If this happens, the transport decoder might want to rewind to the supposed + ending of the transport frame, and this position might be before the last + access unit beginning. */ + + /* Calc bitrate. */ + if (pSi->frameSize > 0) { + /* bitRate = nBits * sampleRate / frameSize */ + int ratio_e = 0; + FIXP_DBL ratio_m = fDivNorm(pSi->sampleRate, pSi->frameSize, &ratio_e); + pSi->bitRate = (INT)fMultNorm(nBits, DFRACT_BITS - 1, ratio_m, ratio_e, + DFRACT_BITS - 1); + } + + /* bit/byte counters */ + { + INT nBytes; + + nBytes = nBits >> 3; + pSi->numTotalBytes += nBytes; + if (IS_OUTPUT_VALID(ErrorStatus)) { + pSi->numTotalAccessUnits++; + } + if (IS_DECODE_ERROR(ErrorStatus)) { + pSi->numBadBytes += nBytes; + pSi->numBadAccessUnits++; + } + } +} + +static INT aacDecoder_EstimateNumberOfLostFrames(HANDLE_AACDECODER self) { + INT n; + + transportDec_GetMissingAccessUnitCount(&n, self->hInput); + + return n; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self, + INT_PCM *pTimeData, + const INT timeDataSize, + const UINT flags) { + AAC_DECODER_ERROR ErrorStatus; + INT layer; + INT nBits; + INT timeData2Size; + INT timeData3Size; + INT timeDataHeadroom; + HANDLE_FDK_BITSTREAM hBs; + int fTpInterruption = 0; /* Transport originated interruption detection. */ + int fTpConceal = 0; /* Transport originated concealment. */ + UINT accessUnit = 0; + UINT numAccessUnits = 1; + UINT numPrerollAU = 0; + int fEndAuNotAdjusted = 0; /* The end of the access unit was not adjusted */ + int applyCrossfade = 1; /* flag indicates if flushing was possible */ + PCM_DEC *pTimeData2; + PCM_AAC *pTimeData3; + INT pcmLimiterScale = 0; + INT interleaved = 0; + + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + + if (flags & AACDEC_INTR) { + self->streamInfo.numLostAccessUnits = 0; + } + hBs = transportDec_GetBitstream(self->hInput, 0); + + /* Get current bits position for bitrate calculation. */ + nBits = FDKgetValidBits(hBs); + + if (flags & AACDEC_CLRHIST) { + if (self->flags[0] & AC_USAC) { + /* 1) store AudioSpecificConfig always in AudioSpecificConfig_Parse() */ + /* 2) free memory of dynamic allocated data */ + CSAudioSpecificConfig asc; + transportDec_GetAsc(self->hInput, 0, &asc); + aacDecoder_FreeMemCallback(self, &asc); + self->streamInfo.numChannels = 0; + /* 3) restore AudioSpecificConfig */ + if (asc.configBits <= (TP_USAC_MAX_CONFIG_LEN << 3)) { + transportDec_OutOfBandConfig(self->hInput, asc.config, + (asc.configBits + 7) >> 3, 0); + } + } + } + + if (!((flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) || + (self->flushStatus == AACDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON) || + (self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON) || + (self->buildUpStatus == AACDEC_RSV60_BUILD_UP_IDLE_IN_BAND))) { + TRANSPORTDEC_ERROR err; + + for (layer = 0; layer < self->nrOfLayers; layer++) { + err = transportDec_ReadAccessUnit(self->hInput, layer); + if (err != TRANSPORTDEC_OK) { + switch (err) { + case TRANSPORTDEC_NOT_ENOUGH_BITS: + ErrorStatus = AAC_DEC_NOT_ENOUGH_BITS; + goto bail; + case TRANSPORTDEC_SYNC_ERROR: + self->streamInfo.numLostAccessUnits = + aacDecoder_EstimateNumberOfLostFrames(self); + fTpInterruption = 1; + break; + case TRANSPORTDEC_NEED_TO_RESTART: + ErrorStatus = AAC_DEC_NEED_TO_RESTART; + goto bail; + case TRANSPORTDEC_CRC_ERROR: + fTpConceal = 1; + break; + case TRANSPORTDEC_UNSUPPORTED_FORMAT: + ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT; + goto bail; + default: + ErrorStatus = AAC_DEC_UNKNOWN; + goto bail; + } + } + } + } else { + if (self->streamInfo.numLostAccessUnits > 0) { + self->streamInfo.numLostAccessUnits--; + } + } + + self->frameOK = 1; + + UINT prerollAUOffset[AACDEC_MAX_NUM_PREROLL_AU]; + UINT prerollAULength[AACDEC_MAX_NUM_PREROLL_AU]; + for (int i = 0; i < AACDEC_MAX_NUM_PREROLL_AU + 1; i++) + self->prerollAULength[i] = 0; + + INT auStartAnchor; + HANDLE_FDK_BITSTREAM hBsAu; + + /* Process preroll frames and current frame */ + do { + if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) && + (self->flushStatus != AACDEC_RSV60_CFG_CHANGE_ATSC_FLUSH_ON) && + (accessUnit == 0) && + (self->hasAudioPreRoll || + (self->buildUpStatus == AACDEC_RSV60_BUILD_UP_IDLE_IN_BAND)) && + !fTpInterruption && + !fTpConceal /* Bit stream pointer needs to be at the beginning of a + (valid) AU. */ + ) { + ErrorStatus = CAacDecoder_PreRollExtensionPayloadParse( + self, &numPrerollAU, prerollAUOffset, prerollAULength); + + if (ErrorStatus != AAC_DEC_OK) { + switch (ErrorStatus) { + case AAC_DEC_NOT_ENOUGH_BITS: + goto bail; + case AAC_DEC_PARSE_ERROR: + self->frameOK = 0; + break; + default: + break; + } + } + + numAccessUnits += numPrerollAU; + } + + hBsAu = transportDec_GetBitstream(self->hInput, 0); + auStartAnchor = (INT)FDKgetValidBits(hBsAu); + + self->accessUnit = accessUnit; + if (accessUnit < numPrerollAU) { + FDKpushFor(hBsAu, prerollAUOffset[accessUnit]); + } + + /* Signal bit stream interruption to other modules if required. */ + if (fTpInterruption || ((flags & AACDEC_INTR) && (accessUnit == 0))) { + aacDecoder_SignalInterruption(self); + if (!((flags & AACDEC_INTR) && (accessUnit == 0))) { + ErrorStatus = AAC_DEC_TRANSPORT_SYNC_ERROR; + goto bail; + } + } + + /* Clearing core data will be done in CAacDecoder_DecodeFrame() below. + Tell other modules to clear states if required. */ + if (flags & AACDEC_CLRHIST) { + if (!(self->flags[0] & AC_USAC)) { + sbrDecoder_SetParam(self->hSbrDecoder, SBR_CLEAR_HISTORY, 1); + mpegSurroundDecoder_SetParam( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, + SACDEC_CLEAR_HISTORY, 1); + if (FDK_QmfDomain_ClearPersistentMemory(&self->qmfDomain) != 0) { + ErrorStatus = AAC_DEC_UNKNOWN; + goto bail; + } + } + } + + /* Empty bit buffer in case of flush request. */ + if (flags & AACDEC_FLUSH && !(flags & AACDEC_CONCEAL)) { + if (!self->flushStatus) { + transportDec_SetParam(self->hInput, TPDEC_PARAM_RESET, 1); + self->streamInfo.numLostAccessUnits = 0; + self->streamInfo.numBadBytes = 0; + self->streamInfo.numTotalBytes = 0; + } + } + /* Reset the output delay field. The modules will add their figures one + * after another. */ + self->streamInfo.outputDelay = 0; + + if (self->limiterEnableUser == (UCHAR)-2) { + /* Enable limiter only for RSVD60. */ + self->limiterEnableCurr = (self->flags[0] & AC_RSV603DA) ? 1 : 0; + } else if (self->limiterEnableUser == (UCHAR)-1) { + /* Enable limiter for all non-lowdelay AOT's. */ + self->limiterEnableCurr = (self->flags[0] & (AC_LD | AC_ELD)) ? 0 : 1; + } else { + /* Use limiter configuration as requested. */ + self->limiterEnableCurr = self->limiterEnableUser; + } + + /* reset DRC level normalization gain on a per frame basis */ + self->extGain[0] = AACDEC_DRC_GAIN_INIT_VALUE; + + pTimeData2 = self->pTimeData2; + timeData2Size = self->timeData2Size / sizeof(PCM_DEC); + pTimeData3 = (PCM_AAC *)self->pTimeData2; + timeData3Size = self->timeData2Size / sizeof(PCM_AAC); + + ErrorStatus = CAacDecoder_DecodeFrame( + self, + flags | (fTpConceal ? AACDEC_CONCEAL : 0) | + ((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH + : 0), + pTimeData2 + 0, timeData2Size, self->streamInfo.aacSamplesPerFrame + 0); + + timeDataHeadroom = self->aacOutDataHeadroom; + + /* if flushing for USAC DASH IPF was not possible go on with decoding + * preroll */ + if ((self->flags[0] & AC_USAC) && + (self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON) && + !(flags & AACDEC_CONCEAL) && (ErrorStatus != AAC_DEC_OK)) { + applyCrossfade = 0; + } else /* USAC DASH IPF flushing possible begin */ + { + if (!((flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) || fTpConceal || + self->flushStatus) && + (!(IS_OUTPUT_VALID(ErrorStatus)) || !(accessUnit < numPrerollAU))) { + TRANSPORTDEC_ERROR tpErr; + tpErr = transportDec_EndAccessUnit(self->hInput); + if (tpErr != TRANSPORTDEC_OK) { + self->frameOK = 0; + } + } else { /* while preroll processing later possibly an error in the + renderer part occurrs */ + if (IS_OUTPUT_VALID(ErrorStatus)) { + fEndAuNotAdjusted = 1; + } + } + + /* If the current pTimeData2 does not contain a valid signal, there + * nothing else we can do, so bail. */ + if (!IS_OUTPUT_VALID(ErrorStatus)) { + goto bail; + } + + { + self->streamInfo.sampleRate = self->streamInfo.aacSampleRate; + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame; + } + + self->streamInfo.numChannels = self->streamInfo.aacNumChannels; + + { + FDK_Delay_Apply( + &self->usacResidualDelay, + pTimeData2 + 1 * (self->streamInfo.aacSamplesPerFrame + 0) + 0, + self->streamInfo.frameSize, 0); + } + + /* Setting of internal MPS state; may be reset in CAacDecoder_SyncQmfMode + if decoder is unable to decode with user defined qmfMode */ + if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA | AC_ELD))) { + self->mpsEnableCurr = + (self->mpsEnableUser && + isSupportedMpsConfig(self->streamInfo.aot, + self->streamInfo.numChannels, + (self->flags[0] & AC_MPS_PRESENT) ? 1 : 0)); + } + + if (!self->qmfDomain.globalConf.qmfDomainExplicitConfig && + self->mpsEnableCurr) { + /* if not done yet, allocate full MPEG Surround decoder instance */ + if (mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder) == + SAC_INSTANCE_NOT_FULL_AVAILABLE) { + if (mpegSurroundDecoder_Open( + (CMpegSurroundDecoder **)&self->pMpegSurroundDecoder, -1, + &self->qmfDomain)) { + return AAC_DEC_OUT_OF_MEMORY; + } + } + } + + CAacDecoder_SyncQmfMode(self); + + if (!self->qmfDomain.globalConf.qmfDomainExplicitConfig && + self->mpsEnableCurr) { + SAC_INPUT_CONFIG sac_interface = (self->sbrEnabled && self->hSbrDecoder) + ? SAC_INTERFACE_QMF + : SAC_INTERFACE_TIME; + /* needs to be done before first SBR apply. */ + mpegSurroundDecoder_ConfigureQmfDomain( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, sac_interface, + (UINT)self->streamInfo.aacSampleRate, self->streamInfo.aot); + if (self->qmfDomain.globalConf.nBandsAnalysis_requested > 0) { + self->qmfDomain.globalConf.nQmfTimeSlots_requested = + self->streamInfo.aacSamplesPerFrame / + self->qmfDomain.globalConf.nBandsAnalysis_requested; + } else { + self->qmfDomain.globalConf.nQmfTimeSlots_requested = 0; + } + } + + switch (FDK_QmfDomain_Configure(&self->qmfDomain)) { + default: + case QMF_DOMAIN_INIT_ERROR: + ErrorStatus = AAC_DEC_UNKNOWN; + goto bail; + case QMF_DOMAIN_OUT_OF_MEMORY: + ErrorStatus = AAC_DEC_OUT_OF_MEMORY; + goto bail; + case QMF_DOMAIN_OK: + break; + } + + /* sbr decoder */ + + if ((ErrorStatus != AAC_DEC_OK) || (flags & AACDEC_CONCEAL) || + self->pAacDecoderStaticChannelInfo[0]->concealmentInfo.concealState > + ConcealState_FadeIn) { + self->frameOK = 0; /* if an error has occured do concealment in the SBR + decoder too */ + } + + if (self->sbrEnabled && (!(self->flags[0] & AC_USAC_SCFGI3))) { + SBR_ERROR sbrError = SBRDEC_OK; + int chIdx, numCoreChannel = self->streamInfo.numChannels; + + /* set params */ + sbrDecoder_SetParam(self->hSbrDecoder, SBR_SYSTEM_BITSTREAM_DELAY, + self->sbrParams.bsDelay); + sbrDecoder_SetParam( + self->hSbrDecoder, SBR_FLUSH_DATA, + (flags & AACDEC_FLUSH) | + ((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH + : 0)); + + if (self->streamInfo.aot == AOT_ER_AAC_ELD) { + /* Configure QMF */ + sbrDecoder_SetParam(self->hSbrDecoder, SBR_LD_QMF_TIME_ALIGN, + (self->flags[0] & AC_MPS_PRESENT) ? 1 : 0); + } + + { + PCMDMX_ERROR dmxErr; + INT maxOutCh = 0; + + dmxErr = pcmDmx_GetParam(self->hPcmUtils, + MAX_NUMBER_OF_OUTPUT_CHANNELS, &maxOutCh); + if ((dmxErr == PCMDMX_OK) && (maxOutCh == 1)) { + /* Disable PS processing if we have to create a mono output signal. + */ + self->psPossible = 0; + } + } + + sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF, + (self->mpsEnableCurr) ? 2 : 0); + + PCM_AAC *input; + input = (PCM_AAC *)self->workBufferCore2; + FDKmemcpy(input, pTimeData3, + sizeof(PCM_AAC) * (self->streamInfo.numChannels) * + (self->streamInfo.frameSize)); + + /* apply SBR processing */ + sbrError = sbrDecoder_Apply( + self->hSbrDecoder, input, pTimeData3, timeData3Size, + &self->streamInfo.numChannels, &self->streamInfo.sampleRate, + &self->mapDescr, self->chMapIndex, self->frameOK, &self->psPossible, + self->aacOutDataHeadroom, &timeDataHeadroom); + + if (sbrError == SBRDEC_OK) { + /* Update data in streaminfo structure. Assume that the SBR upsampling + factor is either 1, 2, 8/3 or 4. Maximum upsampling factor is 4 + (CELP+SBR or USAC 4:1 SBR) */ + self->flags[0] |= AC_SBR_PRESENT; + if (self->streamInfo.aacSampleRate != self->streamInfo.sampleRate) { + if (self->streamInfo.aacSampleRate >> 2 == + self->streamInfo.sampleRate) { + self->streamInfo.frameSize = + self->streamInfo.aacSamplesPerFrame >> 2; + self->streamInfo.outputDelay = self->streamInfo.outputDelay >> 2; + } else if (self->streamInfo.aacSampleRate >> 1 == + self->streamInfo.sampleRate) { + self->streamInfo.frameSize = + self->streamInfo.aacSamplesPerFrame >> 1; + self->streamInfo.outputDelay = self->streamInfo.outputDelay >> 1; + } else if (self->streamInfo.aacSampleRate << 1 == + self->streamInfo.sampleRate) { + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame + << 1; + self->streamInfo.outputDelay = self->streamInfo.outputDelay << 1; + } else if (self->streamInfo.aacSampleRate << 2 == + self->streamInfo.sampleRate) { + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame + << 2; + self->streamInfo.outputDelay = self->streamInfo.outputDelay << 2; + } else if (self->streamInfo.frameSize == 768) { + self->streamInfo.frameSize = + (self->streamInfo.aacSamplesPerFrame << 3) / 3; + self->streamInfo.outputDelay = + (self->streamInfo.outputDelay << 3) / 3; + } else { + ErrorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; + } + } else { + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame; + } + self->streamInfo.outputDelay += + sbrDecoder_GetDelay(self->hSbrDecoder); + + if (self->psPossible) { + self->flags[0] |= AC_PS_PRESENT; + } + for (chIdx = numCoreChannel; chIdx < self->streamInfo.numChannels; + chIdx += 1) { + self->channelType[chIdx] = ACT_FRONT; + self->channelIndices[chIdx] = chIdx; + } + } + if (sbrError == SBRDEC_OUTPUT_BUFFER_TOO_SMALL) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + goto bail; + } + } + + if (self->mpsEnableCurr) { + int err, sac_interface, nChannels, frameSize; + + nChannels = self->streamInfo.numChannels; + frameSize = self->streamInfo.frameSize; + sac_interface = SAC_INTERFACE_TIME; + + if (self->sbrEnabled && self->hSbrDecoder) + sac_interface = SAC_INTERFACE_QMF; + if (self->streamInfo.aot == AOT_USAC) { + if (self->flags[0] & AC_USAC_SCFGI3) { + sac_interface = SAC_INTERFACE_TIME; + } + } + err = mpegSurroundDecoder_SetParam( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, + SACDEC_INTERFACE, sac_interface); + + if (err == 0) { + err = mpegSurroundDecoder_Apply( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, + (PCM_AAC *)self->workBufferCore2, pTimeData3, timeData3Size, + self->streamInfo.aacSamplesPerFrame, &nChannels, &frameSize, + self->streamInfo.sampleRate, self->streamInfo.aot, + self->channelType, self->channelIndices, &self->mapDescr, + self->aacOutDataHeadroom, &timeDataHeadroom); + } + + if (err == MPS_OUTPUT_BUFFER_TOO_SMALL) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + goto bail; + } + if (err == 0) { + /* Update output parameter */ + self->streamInfo.numChannels = nChannels; + self->streamInfo.frameSize = frameSize; + self->streamInfo.outputDelay += mpegSurroundDecoder_GetDelay( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder); + /* Save current parameter for possible concealment of next frame */ + self->mpsOutChannelsLast = nChannels; + self->mpsFrameSizeLast = frameSize; + } else if ((self->mpsOutChannelsLast > 0) && + (self->mpsFrameSizeLast > 0)) { + /* Restore parameters of last frame ... */ + self->streamInfo.numChannels = self->mpsOutChannelsLast; + self->streamInfo.frameSize = self->mpsFrameSizeLast; + /* ... and clear output buffer so that potentially corrupted data does + * not reach the framework. */ + FDKmemclear(pTimeData3, self->mpsOutChannelsLast * + self->mpsFrameSizeLast * sizeof(PCM_AAC)); + /* Additionally proclaim that this frame had errors during decoding. + */ + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } else { + ErrorStatus = AAC_DEC_UNKNOWN; /* no output */ + } + } + + /* SBR decoder for Unified Stereo Config (stereoConfigIndex == 3) */ + + if (self->sbrEnabled && (self->flags[0] & AC_USAC_SCFGI3)) { + SBR_ERROR sbrError = SBRDEC_OK; + + /* set params */ + sbrDecoder_SetParam(self->hSbrDecoder, SBR_SYSTEM_BITSTREAM_DELAY, + self->sbrParams.bsDelay); + sbrDecoder_SetParam( + self->hSbrDecoder, SBR_FLUSH_DATA, + (flags & AACDEC_FLUSH) | + ((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH + : 0)); + + sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF, 1); + + /* apply SBR processing */ + sbrError = sbrDecoder_Apply( + self->hSbrDecoder, pTimeData3, pTimeData3, timeData3Size, + &self->streamInfo.numChannels, &self->streamInfo.sampleRate, + &self->mapDescr, self->chMapIndex, self->frameOK, &self->psPossible, + self->aacOutDataHeadroom, &timeDataHeadroom); + + if (sbrError == SBRDEC_OK) { + /* Update data in streaminfo structure. Assume that the SBR upsampling + * factor is either 1,2 or 4 */ + self->flags[0] |= AC_SBR_PRESENT; + if (self->streamInfo.aacSampleRate != self->streamInfo.sampleRate) { + if (self->streamInfo.frameSize == 768) { + self->streamInfo.frameSize = + (self->streamInfo.aacSamplesPerFrame * 8) / 3; + } else if (self->streamInfo.aacSampleRate << 2 == + self->streamInfo.sampleRate) { + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame + << 2; + } else { + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame + << 1; + } + } + + self->flags[0] &= ~AC_PS_PRESENT; + } + if (sbrError == SBRDEC_OUTPUT_BUFFER_TOO_SMALL) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + goto bail; + } + } + + { + if ((INT)PCM_OUT_HEADROOM != timeDataHeadroom) { + for (int i = ((self->streamInfo.frameSize * + self->streamInfo.numChannels) - + 1); + i >= 0; i--) { + pTimeData2[i] = + (PCM_DEC)pTimeData3[i] >> (PCM_OUT_HEADROOM - timeDataHeadroom); + } + } + } + + { + if ((FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_IS_ACTIVE)) && + (self->flags[0] & AC_USAC)) { + /* Apply DRC gains*/ + int ch, drcDelay = 0; + int needsDeinterleaving = 0; + FIXP_DBL *drcWorkBuffer = NULL; + FIXP_DBL channelGain[(8)]; + int reverseInChannelMap[(8)]; + int reverseOutChannelMap[(8)]; + FDKmemclear(channelGain, sizeof(channelGain)); + for (ch = 0; ch < (8); ch++) { + reverseInChannelMap[ch] = ch; + reverseOutChannelMap[ch] = ch; + } + + /* Update sampleRate and frameSize. This may be necessary in case of + * implicit SBR signaling */ + FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_SAMPLE_RATE, + self->streamInfo.sampleRate); + FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_FRAME_SIZE, + self->streamInfo.frameSize); + + /* If SBR and/or MPS is active, the DRC gains are aligned to the QMF + domain signal before the QMF synthesis. Therefore the DRC gains + need to be delayed by the QMF synthesis delay. */ + if (self->sbrEnabled) drcDelay = 257; + if (self->mpsEnableCurr) drcDelay = 257; + /* Take into account concealment delay */ + drcDelay += CConcealment_GetDelay(&self->concealCommonData) * + self->streamInfo.frameSize; + + /* The output of SBR and MPS is interleaved. Deinterleaving may be + * necessary for FDK_drcDec_ProcessTime, which accepts deinterleaved + * audio only. */ + if ((self->streamInfo.numChannels > 1) && + (0 || (self->sbrEnabled) || (self->mpsEnableCurr))) { + /* interleaving/deinterleaving is performed on upper part of + * pTimeData2. Check if this buffer is large enough. */ + if (timeData2Size < (INT)(2 * self->streamInfo.numChannels * + self->streamInfo.frameSize)) { + ErrorStatus = AAC_DEC_UNKNOWN; + goto bail; + } + needsDeinterleaving = 1; + drcWorkBuffer = + (FIXP_DBL *)pTimeData2 + + self->streamInfo.numChannels * self->streamInfo.frameSize; + FDK_deinterleave( + pTimeData2, drcWorkBuffer, self->streamInfo.numChannels, + self->streamInfo.frameSize, self->streamInfo.frameSize); + } else { + drcWorkBuffer = pTimeData2; + } + + /* prepare Loudness Normalisation gain */ + FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_TARGET_LOUDNESS, + (INT)-self->defaultTargetLoudness * + FL2FXCONST_DBL(1.0f / (float)(1 << 9))); + FDK_drcDec_SetChannelGains(self->hUniDrcDecoder, + self->streamInfo.numChannels, + self->streamInfo.frameSize, channelGain, + drcWorkBuffer, self->streamInfo.frameSize); + FDK_drcDec_Preprocess(self->hUniDrcDecoder); + + /* apply DRC1 gain sequence */ + FDK_drcDec_ProcessTime(self->hUniDrcDecoder, drcDelay, DRC_DEC_DRC1, + 0, 0, self->streamInfo.numChannels, + drcWorkBuffer, self->streamInfo.frameSize); + /* apply downmix */ + FDK_drcDec_ApplyDownmix( + self->hUniDrcDecoder, reverseInChannelMap, reverseOutChannelMap, + drcWorkBuffer, + &self->streamInfo.numChannels); /* self->streamInfo.numChannels + may change here */ + /* apply DRC2/3 gain sequence */ + FDK_drcDec_ProcessTime(self->hUniDrcDecoder, drcDelay, + DRC_DEC_DRC2_DRC3, 0, 0, + self->streamInfo.numChannels, drcWorkBuffer, + self->streamInfo.frameSize); + + if (needsDeinterleaving) { + FDK_interleave( + drcWorkBuffer, pTimeData2, self->streamInfo.numChannels, + self->streamInfo.frameSize, self->streamInfo.frameSize); + } + } + } + if (FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_IS_ACTIVE)) { + /* return output loudness information for MPEG-D DRC */ + LONG outputLoudness = + FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_OUTPUT_LOUDNESS); + if (outputLoudness == DRC_DEC_LOUDNESS_NOT_PRESENT) { + /* no valid MPEG-D DRC loudness value contained */ + self->streamInfo.outputLoudness = -1; + } else { + if (outputLoudness > 0) { + /* positive output loudness values (very unusual) are limited to 0 + * dB */ + self->streamInfo.outputLoudness = 0; + } else { + self->streamInfo.outputLoudness = + -(INT)outputLoudness >> + 22; /* negate and scale from e = 7 to e = (31-2) */ + } + } + } else { + /* return output loudness information for MPEG-4 DRC */ + if (self->streamInfo.drcProgRefLev < + 0) { /* no MPEG-4 DRC loudness metadata contained */ + self->streamInfo.outputLoudness = -1; + } else { + if (self->defaultTargetLoudness < + 0) { /* loudness normalization is off */ + self->streamInfo.outputLoudness = self->streamInfo.drcProgRefLev; + } else { + self->streamInfo.outputLoudness = self->defaultTargetLoudness; + } + } + } + + if (self->streamInfo.extAot != AOT_AAC_SLS) { + interleaved = 0; + interleaved |= (self->sbrEnabled) ? 1 : 0; + interleaved |= (self->mpsEnableCurr) ? 1 : 0; + PCMDMX_ERROR dmxErr = PCMDMX_OK; + if ((flags & AACDEC_INTR) && (accessUnit == 0)) { + /* delete data from the past (e.g. mixdown coeficients) */ + pcmDmx_Reset(self->hPcmUtils, PCMDMX_RESET_BS_DATA); + } + if (flags & (AACDEC_CLRHIST)) { + if (!(self->flags[0] & AC_USAC)) { + /* delete data from the past (e.g. mixdown coeficients) */ + pcmDmx_Reset(self->hPcmUtils, PCMDMX_RESET_BS_DATA); + } + } + + /* do PCM post processing */ + dmxErr = pcmDmx_ApplyFrame(self->hPcmUtils, pTimeData2, timeData2Size, + self->streamInfo.frameSize, + &self->streamInfo.numChannels, interleaved, + self->channelType, self->channelIndices, + &self->mapDescr, &pcmLimiterScale); + if (dmxErr == PCMDMX_OUTPUT_BUFFER_TOO_SMALL) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + goto bail; + } + if ((ErrorStatus == AAC_DEC_OK) && (dmxErr == PCMDMX_INVALID_MODE)) { + /* Announce the framework that the current combination of channel + * configuration and downmix settings are not know to produce a + * predictable behavior and thus maybe produce strange output. */ + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + } + + if (self->flags[0] & AC_USAC) { + if (self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON && + !(flags & AACDEC_CONCEAL)) { + CAacDecoder_PrepareCrossFade(pTimeData2, self->pTimeDataFlush, + self->streamInfo.numChannels, + self->streamInfo.frameSize, interleaved); + } + + /* prepare crossfade buffer for fade in */ + if (!applyCrossfade && + (self->applyCrossfade != AACDEC_CROSSFADE_BITMASK_OFF) && + !(flags & AACDEC_CONCEAL)) { + for (int ch = 0; ch < self->streamInfo.numChannels; ch++) { + for (int i = 0; i < TIME_DATA_FLUSH_SIZE; i++) { + self->pTimeDataFlush[ch][i] = (PCM_DEC)0; + } + } + applyCrossfade = 1; + } + + if (applyCrossfade && + (self->applyCrossfade != AACDEC_CROSSFADE_BITMASK_OFF) && + !(accessUnit < numPrerollAU) && + (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON)) { + CAacDecoder_ApplyCrossFade(pTimeData2, self->pTimeDataFlush, + self->streamInfo.numChannels, + self->streamInfo.frameSize, interleaved); + self->applyCrossfade = + AACDEC_CROSSFADE_BITMASK_OFF; /* disable cross-fade between frames + at nect config change */ + } + } + + /* Signal interruption to take effect in next frame. */ + if ((flags & AACDEC_FLUSH || self->flushStatus) && + !(flags & AACDEC_CONCEAL)) { + aacDecoder_SignalInterruption(self); + } + + /* Update externally visible copy of flags */ + self->streamInfo.flags = self->flags[0]; + + } /* USAC DASH IPF flushing possible end */ + if (accessUnit < numPrerollAU) { + FDKpushBack(hBsAu, auStartAnchor - (INT)FDKgetValidBits(hBsAu)); + } else { + if ((self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON) || + (self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON_IN_BAND) || + (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON)) { + self->buildUpCnt--; + + if (self->buildUpCnt < 0) { + self->buildUpStatus = 0; + } + } + + if (self->flags[0] & AC_USAC) { + if (self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON && + !(flags & AACDEC_CONCEAL)) { + self->streamInfo.frameSize = 0; + } + } + } + + if (self->flushStatus != AACDEC_USAC_DASH_IPF_FLUSH_ON) { + accessUnit++; + } + } while ((accessUnit < numAccessUnits) || + ((self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON) && + !(flags & AACDEC_CONCEAL))); + + if (self->streamInfo.extAot != AOT_AAC_SLS) { + pcmLimiterScale += PCM_OUT_HEADROOM; + + if (flags & AACDEC_CLRHIST) { + if (!(self->flags[0] & AC_USAC)) { + /* Reset DRC data */ + aacDecoder_drcReset(self->hDrcInfo); + /* Delete the delayed signal. */ + pcmLimiter_Reset(self->hLimiter); + } + } + + /* Set applyExtGain if DRC processing is enabled and if progRefLevelPresent + is present for the first time. Consequences: The headroom of the output + signal can be set to AACDEC_DRC_GAIN_SCALING only for audio formats which + support legacy DRC Level Normalization. For all other audio formats the + headroom of the output signal is set to PCM_OUT_HEADROOM. */ + if (self->hDrcInfo->enable && (self->hDrcInfo->progRefLevelPresent == 1)) { + self->hDrcInfo->applyExtGain |= 1; + } + + /* Check whether time data buffer is large enough. */ + if (timeDataSize < + (self->streamInfo.numChannels * self->streamInfo.frameSize)) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + goto bail; + } + + if (self->limiterEnableCurr) { + /* use workBufferCore2 buffer for interleaving */ + PCM_LIM *pInterleaveBuffer; + int blockLength = self->streamInfo.frameSize; + + /* Set actual signal parameters */ + pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels); + pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate); + + if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) || + (self->mpsEnableCurr)) { + pInterleaveBuffer = (PCM_LIM *)pTimeData2; + } else { + pInterleaveBuffer = (PCM_LIM *)self->workBufferCore2; + + /* applyLimiter requests for interleaved data */ + /* Interleave ouput buffer */ + FDK_interleave(pTimeData2, pInterleaveBuffer, + self->streamInfo.numChannels, blockLength, + self->streamInfo.frameSize); + } + + FIXP_DBL *pGainPerSample = NULL; + + if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) { + pGainPerSample = self->workBufferCore1; + + if ((INT)GetRequiredMemWorkBufferCore1() < + (INT)(self->streamInfo.frameSize * sizeof(FIXP_DBL))) { + ErrorStatus = AAC_DEC_UNKNOWN; + goto bail; + } + + pcmLimiterScale = applyDrcLevelNormalization( + self->hDrcInfo, (PCM_DEC *)pInterleaveBuffer, self->extGain, + pGainPerSample, pcmLimiterScale, self->extGainDelay, + self->streamInfo.frameSize, self->streamInfo.numChannels, 1, 1); + } + + pcmLimiter_Apply(self->hLimiter, pInterleaveBuffer, pTimeData, + pGainPerSample, pcmLimiterScale, + self->streamInfo.frameSize); + + { + /* Announce the additional limiter output delay */ + self->streamInfo.outputDelay += pcmLimiter_GetDelay(self->hLimiter); + } + } else { + if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) { + pcmLimiterScale = applyDrcLevelNormalization( + self->hDrcInfo, pTimeData2, self->extGain, NULL, pcmLimiterScale, + self->extGainDelay, self->streamInfo.frameSize, + self->streamInfo.numChannels, + (interleaved || (self->streamInfo.numChannels == 1)) + ? 1 + : self->streamInfo.frameSize, + 0); + } + + /* If numChannels = 1 we do not need interleaving. The same applies if SBR + or MPS are used, since their output is interleaved already (resampled or + not) */ + if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) || + (self->mpsEnableCurr)) { + scaleValuesSaturate( + pTimeData, pTimeData2, + self->streamInfo.frameSize * self->streamInfo.numChannels, + pcmLimiterScale); + + } else { + scaleValuesSaturate( + (INT_PCM *)self->workBufferCore2, pTimeData2, + self->streamInfo.frameSize * self->streamInfo.numChannels, + pcmLimiterScale); + /* Interleave ouput buffer */ + FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData, + self->streamInfo.numChannels, self->streamInfo.frameSize, + self->streamInfo.frameSize); + } + } + } /* if (self->streamInfo.extAot != AOT_AAC_SLS)*/ + +bail: + + /* error in renderer part occurred, ErrorStatus was set to invalid output */ + if (fEndAuNotAdjusted && !IS_OUTPUT_VALID(ErrorStatus) && + (accessUnit < numPrerollAU)) { + transportDec_EndAccessUnit(self->hInput); + } + + /* Update Statistics */ + aacDecoder_UpdateBitStreamCounters(&self->streamInfo, hBs, nBits, + ErrorStatus); + if (((self->streamInfo.numChannels <= 0) || + (self->streamInfo.frameSize <= 0) || + (self->streamInfo.sampleRate <= 0)) && + IS_OUTPUT_VALID(ErrorStatus)) { + /* Ensure consistency of IS_OUTPUT_VALID() macro. */ + ErrorStatus = AAC_DEC_UNKNOWN; + } + + if (!IS_OUTPUT_VALID(ErrorStatus)) { + FDKmemclear(pTimeData, timeDataSize * sizeof(*pTimeData)); + } + + return ErrorStatus; +} + +LINKSPEC_CPP void aacDecoder_Close(HANDLE_AACDECODER self) { + if (self == NULL) return; + + if (self->hLimiter != NULL) { + pcmLimiter_Destroy(self->hLimiter); + } + + if (self->hPcmUtils != NULL) { + pcmDmx_Close(&self->hPcmUtils); + } + + FDK_drcDec_Close(&self->hUniDrcDecoder); + + if (self->pMpegSurroundDecoder != NULL) { + mpegSurroundDecoder_Close( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder); + } + + if (self->hSbrDecoder != NULL) { + sbrDecoder_Close(&self->hSbrDecoder); + } + + if (self->hInput != NULL) { + transportDec_Close(&self->hInput); + } + + CAacDecoder_Close(self); +} + +LINKSPEC_CPP CStreamInfo *aacDecoder_GetStreamInfo(HANDLE_AACDECODER self) { + return CAacDecoder_GetStreamInfo(self); +} + +LINKSPEC_CPP INT aacDecoder_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return -1; + } + + sbrDecoder_GetLibInfo(info); + mpegSurroundDecoder_GetLibInfo(info); + transportDec_GetLibInfo(info); + FDK_toolsGetLibInfo(info); + pcmDmx_GetLibInfo(info); + pcmLimiter_GetLibInfo(info); + FDK_drcDec_GetLibInfo(info); + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return -1; + } + info += i; + + info->module_id = FDK_AACDEC; + /* build own library info */ + info->version = + LIB_VERSION(AACDECODER_LIB_VL0, AACDECODER_LIB_VL1, AACDECODER_LIB_VL2); + LIB_VERSION_STRING(info); + info->build_date = AACDECODER_LIB_BUILD_DATE; + info->build_time = AACDECODER_LIB_BUILD_TIME; + info->title = AACDECODER_LIB_TITLE; + + /* Set flags */ + info->flags = 0 | CAPF_AAC_LC | CAPF_ER_AAC_LC | CAPF_ER_AAC_SCAL | + CAPF_AAC_VCB11 | CAPF_AAC_HCR | CAPF_AAC_RVLC | CAPF_ER_AAC_LD | + CAPF_ER_AAC_ELD | CAPF_AAC_CONCEALMENT | CAPF_AAC_DRC | + CAPF_AAC_MPEG4 | CAPF_AAC_DRM_BSFORMAT | CAPF_AAC_1024 | + CAPF_AAC_960 | CAPF_AAC_512 | CAPF_AAC_480 | + CAPF_AAC_ELD_DOWNSCALE + + | CAPF_AAC_USAC | CAPF_ER_AAC_ELDV2 | CAPF_AAC_UNIDRC; + /* End of flags */ + + return 0; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/arm/block_arm.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/arm/block_arm.cpp new file mode 100644 index 0000000000000..3c1b4bae012aa --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/arm/block_arm.cpp @@ -0,0 +1,142 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Arthur Tritthart + + Description: (ARM optimised) Scaling of spectral data + +*******************************************************************************/ + +#define FUNCTION_CBlock_ScaleSpectralData_func1 + +/* Note: This loop is only separated for ARM in order to save cycles + by loop unrolling. The ARM core provides by default a 5-cycle + loop overhead per sample, that goes down to 1-cycle per sample + with an optimal 4x-loop construct (do - 4x - while). +*/ +static inline void CBlock_ScaleSpectralData_func1( + FIXP_DBL *pSpectrum, int maxSfbs, const SHORT *RESTRICT BandOffsets, + int SpecScale_window, const SHORT *RESTRICT pSfbScale, int window) { + int band_offset = 0; + for (int band = 0; band < maxSfbs; band++) { + int runs = band_offset; + band_offset = BandOffsets[band + 1]; + runs = band_offset - runs; /* is always a multiple of 4 */ + FDK_ASSERT((runs & 3) == 0); + int scale = + fMin(DFRACT_BITS - 1, SpecScale_window - pSfbScale[window * 16 + band]); + + if (scale) { + do { + FIXP_DBL tmp0, tmp1, tmp2, tmp3; + tmp0 = pSpectrum[0]; + tmp1 = pSpectrum[1]; + tmp2 = pSpectrum[2]; + tmp3 = pSpectrum[3]; + tmp0 >>= scale; + tmp1 >>= scale; + tmp2 >>= scale; + tmp3 >>= scale; + *pSpectrum++ = tmp0; + *pSpectrum++ = tmp1; + *pSpectrum++ = tmp2; + *pSpectrum++ = tmp3; + } while ((runs = runs - 4) != 0); + } else { + pSpectrum += runs; + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/block.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/block.cpp new file mode 100644 index 0000000000000..0bca57798c067 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/block.cpp @@ -0,0 +1,1262 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: long/short-block decoding + +*******************************************************************************/ + +#include "block.h" + +#include "aac_rom.h" +#include "FDK_bitstream.h" +#include "scale.h" +#include "FDK_tools_rom.h" + +#include "usacdec_fac.h" +#include "usacdec_lpd.h" +#include "usacdec_lpc.h" +#include "FDK_trigFcts.h" + +#include "ac_arith_coder.h" + +#include "aacdec_hcr.h" +#include "rvlc.h" + +#if defined(__arm__) +#include "arm/block_arm.cpp" +#endif + +/*! + \brief Read escape sequence of codeword + + The function reads the escape sequence from the bitstream, + if the absolute value of the quantized coefficient has the + value 16. + A limitation is implemented to maximal 21 bits according to + ISO/IEC 14496-3:2009(E) 4.6.3.3. + This limits the escape prefix to a maximum of eight 1's. + If more than eight 1's are read, MAX_QUANTIZED_VALUE + 1 is + returned, independent of the sign of parameter q. + + \return quantized coefficient +*/ +LONG CBlock_GetEscape(HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */ + const LONG q) /*!< quantized coefficient */ +{ + if (fAbs(q) != 16) return (q); + + LONG i, off; + for (i = 4; i < 13; i++) { + if (FDKreadBit(bs) == 0) break; + } + + if (i == 13) return (MAX_QUANTIZED_VALUE + 1); + + off = FDKreadBits(bs, i); + i = off + (1 << i); + + if (q < 0) i = -i; + + return i; +} + +AAC_DECODER_ERROR CBlock_ReadScaleFactorData( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, HANDLE_FDK_BITSTREAM bs, + UINT flags) { + int temp; + int band; + int group; + int position = 0; /* accu for intensity delta coding */ + int factor = pAacDecoderChannelInfo->pDynData->RawDataInfo + .GlobalGain; /* accu for scale factor delta coding */ + UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor; + const CodeBookDescription *hcb = &AACcodeBookDescriptionTable[BOOKSCL]; + + const USHORT(*CodeBook)[HuffmanEntries] = hcb->CodeBook; + + int ScaleFactorBandsTransmitted = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + for (group = 0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + group++) { + for (band = 0; band < ScaleFactorBandsTransmitted; band++) { + switch (pCodeBook[band]) { + case ZERO_HCB: /* zero book */ + pScaleFactor[band] = 0; + break; + + default: /* decode scale factor */ + if (!((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && band == 0 && + group == 0)) { + temp = CBlock_DecodeHuffmanWordCB(bs, CodeBook); + factor += temp - 60; /* MIDFAC 1.5 dB */ + } + pScaleFactor[band] = factor - 100; + break; + + case INTENSITY_HCB: /* intensity steering */ + case INTENSITY_HCB2: + temp = CBlock_DecodeHuffmanWordCB(bs, CodeBook); + position += temp - 60; + pScaleFactor[band] = position - 100; + break; + + case NOISE_HCB: /* PNS */ + if (flags & (AC_MPEGD_RES | AC_USAC | AC_RSVD50 | AC_RSV603DA)) { + return AAC_DEC_PARSE_ERROR; + } + CPns_Read(&pAacDecoderChannelInfo->data.aac.PnsData, bs, hcb, + pAacDecoderChannelInfo->pDynData->aScaleFactor, + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain, + band, group); + break; + } + } + pCodeBook += 16; + pScaleFactor += 16; + } + + return AAC_DEC_OK; +} + +void CBlock_ScaleSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + UCHAR maxSfbs, + SamplingRateInfo *pSamplingRateInfo) { + int band; + int window; + const SHORT *RESTRICT pSfbScale = pAacDecoderChannelInfo->pDynData->aSfbScale; + SHORT *RESTRICT pSpecScale = pAacDecoderChannelInfo->specScale; + int groupwin, group; + const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + SPECTRAL_PTR RESTRICT pSpectralCoefficient = + pAacDecoderChannelInfo->pSpectralCoefficient; + + FDKmemclear(pSpecScale, 8 * sizeof(SHORT)); + + for (window = 0, group = 0; + group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++) { + for (groupwin = 0; groupwin < GetWindowGroupLength( + &pAacDecoderChannelInfo->icsInfo, group); + groupwin++, window++) { + int SpecScale_window = pSpecScale[window]; + FIXP_DBL *pSpectrum = SPEC(pSpectralCoefficient, window, + pAacDecoderChannelInfo->granuleLength); + + /* find scaling for current window */ + for (band = 0; band < maxSfbs; band++) { + SpecScale_window = + fMax(SpecScale_window, (int)pSfbScale[window * 16 + band]); + } + + if (pAacDecoderChannelInfo->pDynData->TnsData.Active && + pAacDecoderChannelInfo->pDynData->TnsData.NumberOfFilters[window] > + 0) { + int filter_index, SpecScale_window_tns; + int tns_start, tns_stop; + + /* Find max scale of TNS bands */ + SpecScale_window_tns = 0; + tns_start = GetMaximumTnsBands(&pAacDecoderChannelInfo->icsInfo, + pSamplingRateInfo->samplingRateIndex); + tns_stop = 0; + for (filter_index = 0; + filter_index < (int)pAacDecoderChannelInfo->pDynData->TnsData + .NumberOfFilters[window]; + filter_index++) { + for (band = pAacDecoderChannelInfo->pDynData->TnsData + .Filter[window][filter_index] + .StartBand; + band < pAacDecoderChannelInfo->pDynData->TnsData + .Filter[window][filter_index] + .StopBand; + band++) { + SpecScale_window_tns = + fMax(SpecScale_window_tns, (int)pSfbScale[window * 16 + band]); + } + /* Find TNS line boundaries for all TNS filters */ + tns_start = + fMin(tns_start, (int)pAacDecoderChannelInfo->pDynData->TnsData + .Filter[window][filter_index] + .StartBand); + tns_stop = + fMax(tns_stop, (int)pAacDecoderChannelInfo->pDynData->TnsData + .Filter[window][filter_index] + .StopBand); + } + SpecScale_window_tns = SpecScale_window_tns + + pAacDecoderChannelInfo->pDynData->TnsData.GainLd; + FDK_ASSERT(tns_stop >= tns_start); + /* Consider existing headroom of all MDCT lines inside the TNS bands. */ + SpecScale_window_tns -= + getScalefactor(pSpectrum + BandOffsets[tns_start], + BandOffsets[tns_stop] - BandOffsets[tns_start]); + if (SpecScale_window <= 17) { + SpecScale_window_tns++; + } + /* Add enough mantissa head room such that the spectrum is still + representable after applying TNS. */ + SpecScale_window = fMax(SpecScale_window, SpecScale_window_tns); + } + + /* store scaling of current window */ + pSpecScale[window] = SpecScale_window; + +#ifdef FUNCTION_CBlock_ScaleSpectralData_func1 + + CBlock_ScaleSpectralData_func1(pSpectrum, maxSfbs, BandOffsets, + SpecScale_window, pSfbScale, window); + +#else /* FUNCTION_CBlock_ScaleSpectralData_func1 */ + for (band = 0; band < maxSfbs; band++) { + int scale = fMin(DFRACT_BITS - 1, + SpecScale_window - pSfbScale[window * 16 + band]); + if (scale) { + FDK_ASSERT(scale > 0); + + /* following relation can be used for optimizations: + * (BandOffsets[i]%4) == 0 for all i */ + int max_index = BandOffsets[band + 1]; + DWORD_ALIGNED(pSpectrum); + for (int index = BandOffsets[band]; index < max_index; index++) { + pSpectrum[index] >>= scale; + } + } + } +#endif /* FUNCTION_CBlock_ScaleSpectralData_func1 */ + } + } +} + +AAC_DECODER_ERROR CBlock_ReadSectionData( + HANDLE_FDK_BITSTREAM bs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const UINT flags) { + int top, band; + int sect_len, sect_len_incr; + int group; + UCHAR sect_cb; + UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + /* HCR input (long) */ + SHORT *pNumLinesInSec = + pAacDecoderChannelInfo->pDynData->specificTo.aac.aNumLineInSec4Hcr; + int numLinesInSecIdx = 0; + UCHAR *pHcrCodeBook = + pAacDecoderChannelInfo->pDynData->specificTo.aac.aCodeBooks4Hcr; + const SHORT *BandOffsets = GetScaleFactorBandOffsets( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection = 0; + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + FDKmemclear(pCodeBook, sizeof(UCHAR) * (8 * 16)); + + const int nbits = + (IsLongBlock(&pAacDecoderChannelInfo->icsInfo) == 1) ? 5 : 3; + + int sect_esc_val = (1 << nbits) - 1; + + UCHAR ScaleFactorBandsTransmitted = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + for (group = 0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + group++) { + for (band = 0; band < ScaleFactorBandsTransmitted;) { + sect_len = 0; + if (flags & AC_ER_VCB11) { + sect_cb = (UCHAR)FDKreadBits(bs, 5); + } else + sect_cb = (UCHAR)FDKreadBits(bs, 4); + + if (((flags & AC_ER_VCB11) == 0) || (sect_cb < 11) || + ((sect_cb > 11) && (sect_cb < 16))) { + sect_len_incr = FDKreadBits(bs, nbits); + while (sect_len_incr == sect_esc_val) { + sect_len += sect_esc_val; + sect_len_incr = FDKreadBits(bs, nbits); + } + } else { + sect_len_incr = 1; + } + + sect_len += sect_len_incr; + + top = band + sect_len; + + if (flags & AC_ER_HCR) { + /* HCR input (long) -- collecting sideinfo (for HCR-_long_ only) */ + if (numLinesInSecIdx >= MAX_SFB_HCR) { + return AAC_DEC_PARSE_ERROR; + } + if (top > (int)GetNumberOfScaleFactorBands( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo)) { + return AAC_DEC_PARSE_ERROR; + } + pNumLinesInSec[numLinesInSecIdx] = BandOffsets[top] - BandOffsets[band]; + numLinesInSecIdx++; + if (sect_cb == BOOKSCL) { + return AAC_DEC_INVALID_CODE_BOOK; + } else { + *pHcrCodeBook++ = sect_cb; + } + pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection++; + } + + /* Check spectral line limits */ + if (IsLongBlock(&(pAacDecoderChannelInfo->icsInfo))) { + if (top > 64) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + } else { /* short block */ + if (top + group * 16 > (8 * 16)) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + } + + /* Check if decoded codebook index is feasible */ + if ((sect_cb == BOOKSCL) || + ((sect_cb == INTENSITY_HCB || sect_cb == INTENSITY_HCB2) && + pAacDecoderChannelInfo->pDynData->RawDataInfo.CommonWindow == 0)) { + return AAC_DEC_INVALID_CODE_BOOK; + } + + /* Store codebook index */ + for (; band < top; band++) { + pCodeBook[group * 16 + band] = sect_cb; + } + } + } + + return ErrorStatus; +} + +/* mso: provides a faster way to i-quantize a whole band in one go */ + +/** + * \brief inverse quantize one sfb. Each value of the sfb is processed according + * to the formula: spectrum[i] = Sign(spectrum[i]) * Matissa(spectrum[i])^(4/3) + * * 2^(lsb/4). + * \param spectrum pointer to first line of the sfb to be inverse quantized. + * \param noLines number of lines belonging to the sfb. + * \param lsb last 2 bits of the scale factor of the sfb. + * \param scale max allowed shift scale for the sfb. + */ +static inline void InverseQuantizeBand( + FIXP_DBL *RESTRICT spectrum, const FIXP_DBL *RESTRICT InverseQuantTabler, + const FIXP_DBL *RESTRICT MantissaTabler, + const SCHAR *RESTRICT ExponentTabler, INT noLines, INT scale) { + scale = scale + 1; /* +1 to compensate fMultDiv2 shift-right in loop */ + + FIXP_DBL *RESTRICT ptr = spectrum; + FIXP_DBL signedValue; + + for (INT i = noLines; i--;) { + if ((signedValue = *ptr++) != FL2FXCONST_DBL(0)) { + FIXP_DBL value = fAbs(signedValue); + UINT freeBits = CntLeadingZeros(value); + UINT exponent = 32 - freeBits; + + UINT x = (UINT)(LONG)value << (INT)freeBits; + x <<= 1; /* shift out sign bit to avoid masking later on */ + UINT tableIndex = x >> 24; + x = (x >> 20) & 0x0F; + + UINT r0 = (UINT)(LONG)InverseQuantTabler[tableIndex + 0]; + UINT r1 = (UINT)(LONG)InverseQuantTabler[tableIndex + 1]; + UINT temp = (r1 - r0) * x + (r0 << 4); + + value = fMultDiv2((FIXP_DBL)temp, MantissaTabler[exponent]); + + /* + 1 compensates fMultDiv2() */ + scaleValueInPlace(&value, scale + ExponentTabler[exponent]); + + signedValue = (signedValue < (FIXP_DBL)0) ? -value : value; + ptr[-1] = signedValue; + } + } +} + +static inline FIXP_DBL maxabs_D(const FIXP_DBL *pSpectralCoefficient, + const int noLines) { + /* Find max spectral line value of the current sfb */ + FIXP_DBL locMax = (FIXP_DBL)0; + int i; + + DWORD_ALIGNED(pSpectralCoefficient); + + for (i = noLines; i-- > 0;) { + /* Expensive memory access */ + locMax = fMax(fixp_abs(pSpectralCoefficient[i]), locMax); + } + + return locMax; +} + +AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + SamplingRateInfo *pSamplingRateInfo, UCHAR *band_is_noise, + UCHAR active_band_search) { + int window, group, groupwin, band; + int ScaleFactorBandsTransmitted = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + UCHAR *RESTRICT pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + SHORT *RESTRICT pSfbScale = pAacDecoderChannelInfo->pDynData->aSfbScale; + SHORT *RESTRICT pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor; + const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + const SHORT total_bands = + GetScaleFactorBandsTotal(&pAacDecoderChannelInfo->icsInfo); + + FDKmemclear(pAacDecoderChannelInfo->pDynData->aSfbScale, + (8 * 16) * sizeof(SHORT)); + + for (window = 0, group = 0; + group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++) { + for (groupwin = 0; groupwin < GetWindowGroupLength( + &pAacDecoderChannelInfo->icsInfo, group); + groupwin++, window++) { + /* inverse quantization */ + for (band = 0; band < ScaleFactorBandsTransmitted; band++) { + FIXP_DBL *pSpectralCoefficient = + SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, window, + pAacDecoderChannelInfo->granuleLength) + + BandOffsets[band]; + FIXP_DBL locMax; + + const int noLines = BandOffsets[band + 1] - BandOffsets[band]; + const int bnds = group * 16 + band; + + if ((pCodeBook[bnds] == ZERO_HCB) || + (pCodeBook[bnds] == INTENSITY_HCB) || + (pCodeBook[bnds] == INTENSITY_HCB2)) + continue; + + if (pCodeBook[bnds] == NOISE_HCB) { + /* Leave headroom for PNS values. + 1 because ceil(log2(2^(0.25*3))) = + 1, worst case of additional headroom required because of the + scalefactor. */ + pSfbScale[window * 16 + band] = (pScaleFactor[bnds] >> 2) + 1; + continue; + } + + locMax = maxabs_D(pSpectralCoefficient, noLines); + + if (active_band_search) { + if (locMax != FIXP_DBL(0)) { + band_is_noise[group * 16 + band] = 0; + } + } + + /* Cheap robustness improvement - Do not remove!!! */ + if (fixp_abs(locMax) > (FIXP_DBL)MAX_QUANTIZED_VALUE) { + return AAC_DEC_PARSE_ERROR; + } + + /* Added by Youliy Ninov: + The inverse quantization operation is given by (ISO/IEC 14496-3:2009(E)) + by: + + x_invquant=Sign(x_quant). abs(x_quant)^(4/3) + + We apply a gain, derived from the scale factor for the particular sfb, + according to the following function: + + gain=2^(0.25*ScaleFactor) + + So, after scaling we have: + + x_rescale=gain*x_invquant=Sign(x_quant)*2^(0.25*ScaleFactor)*abs(s_quant)^(4/3) + + We could represent the ScaleFactor as: + + ScaleFactor= (ScaleFactor >> 2)*4 + ScaleFactor %4 + + When we substitute it we get: + + x_rescale=Sign(x_quant)*2^(ScaleFactor>>2)* ( + 2^(0.25*(ScaleFactor%4))*abs(s_quant)^(4/3)) + + When we set: msb=(ScaleFactor>>2) and lsb=(ScaleFactor%4), we obtain: + + x_rescale=Sign(x_quant)*(2^msb)* ( 2^(lsb/4)*abs(s_quant)^(4/3)) + + The rescaled output can be represented by: + mantissa : Sign(x_quant)*( 2^(lsb/4)*abs(s_quant)^(4/3)) + exponent :(2^msb) + + */ + + int msb = pScaleFactor[bnds] >> 2; + + /* Inverse quantize band only if it is not empty */ + if (locMax != FIXP_DBL(0)) { + int lsb = pScaleFactor[bnds] & 0x03; + + int scale = EvaluatePower43(&locMax, lsb); + + scale = CntLeadingZeros(locMax) - scale - 2; + + pSfbScale[window * 16 + band] = msb - scale; + InverseQuantizeBand(pSpectralCoefficient, InverseQuantTable, + MantissaTable[lsb], ExponentTable[lsb], noLines, + scale); + } else { + pSfbScale[window * 16 + band] = msb; + } + + } /* for (band=0; band < ScaleFactorBandsTransmitted; band++) */ + + /* Make sure the array is cleared to the end */ + SHORT start_clear = BandOffsets[ScaleFactorBandsTransmitted]; + SHORT end_clear = BandOffsets[total_bands]; + int diff_clear = (int)(end_clear - start_clear); + FIXP_DBL *pSpectralCoefficient = + SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, window, + pAacDecoderChannelInfo->granuleLength) + + start_clear; + FDKmemclear(pSpectralCoefficient, diff_clear * sizeof(FIXP_DBL)); + + } /* for (groupwin=0; groupwin < + GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); + groupwin++, window++) */ + } /* for (window=0, group=0; group < + GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)*/ + + return AAC_DEC_OK; +} + +AAC_DECODER_ERROR CBlock_ReadSpectralData( + HANDLE_FDK_BITSTREAM bs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const UINT flags) { + int index, i; + const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + + SPECTRAL_PTR pSpectralCoefficient = + pAacDecoderChannelInfo->pSpectralCoefficient; + + FDK_ASSERT(BandOffsets != NULL); + + FDKmemclear(pSpectralCoefficient, sizeof(SPECTRUM)); + + if ((flags & AC_ER_HCR) == 0) { + int group; + int groupoffset; + UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + int ScaleFactorBandsTransmitted = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + int granuleLength = pAacDecoderChannelInfo->granuleLength; + + groupoffset = 0; + + /* plain huffman decoder short */ + int max_group = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + + for (group = 0; group < max_group; group++) { + int max_groupwin = + GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo, group); + int band; + + int bnds = group * 16; + + int bandOffset1 = BandOffsets[0]; + for (band = 0; band < ScaleFactorBandsTransmitted; band++, bnds++) { + UCHAR currentCB = pCodeBook[bnds]; + int bandOffset0 = bandOffset1; + bandOffset1 = BandOffsets[band + 1]; + + /* patch to run plain-huffman-decoder with vcb11 input codebooks + * (LAV-checking might be possible below using the virtual cb and a + * LAV-table) */ + if ((currentCB >= 16) && (currentCB <= 31)) { + pCodeBook[bnds] = currentCB = 11; + } + if (((currentCB != ZERO_HCB) && (currentCB != NOISE_HCB) && + (currentCB != INTENSITY_HCB) && (currentCB != INTENSITY_HCB2))) { + const CodeBookDescription *hcb = + &AACcodeBookDescriptionTable[currentCB]; + int step = hcb->Dimension; + int offset = hcb->Offset; + int bits = hcb->numBits; + int mask = (1 << bits) - 1; + const USHORT(*CodeBook)[HuffmanEntries] = hcb->CodeBook; + int groupwin; + + FIXP_DBL *mdctSpectrum = + &pSpectralCoefficient[groupoffset * granuleLength]; + + if (offset == 0) { + for (groupwin = 0; groupwin < max_groupwin; groupwin++) { + for (index = bandOffset0; index < bandOffset1; index += step) { + int idx = CBlock_DecodeHuffmanWordCB(bs, CodeBook); + for (i = 0; i < step; i++, idx >>= bits) { + FIXP_DBL tmp = (FIXP_DBL)((idx & mask) - offset); + if (tmp != FIXP_DBL(0)) tmp = (FDKreadBit(bs)) ? -tmp : tmp; + mdctSpectrum[index + i] = tmp; + } + + if (currentCB == ESCBOOK) { + for (int j = 0; j < 2; j++) + mdctSpectrum[index + j] = (FIXP_DBL)CBlock_GetEscape( + bs, (LONG)mdctSpectrum[index + j]); + } + } + mdctSpectrum += granuleLength; + } + } else { + for (groupwin = 0; groupwin < max_groupwin; groupwin++) { + for (index = bandOffset0; index < bandOffset1; index += step) { + int idx = CBlock_DecodeHuffmanWordCB(bs, CodeBook); + for (i = 0; i < step; i++, idx >>= bits) { + mdctSpectrum[index + i] = (FIXP_DBL)((idx & mask) - offset); + } + if (currentCB == ESCBOOK) { + for (int j = 0; j < 2; j++) + mdctSpectrum[index + j] = (FIXP_DBL)CBlock_GetEscape( + bs, (LONG)mdctSpectrum[index + j]); + } + } + mdctSpectrum += granuleLength; + } + } + } + } + groupoffset += max_groupwin; + } + /* plain huffman decoding (short) finished */ + } + + /* HCR - Huffman Codeword Reordering short */ + else /* if ( flags & AC_ER_HCR ) */ + + { + H_HCR_INFO hHcr = &pAacDecoderChannelInfo->pComData->overlay.aac.erHcrInfo; + + int hcrStatus = 0; + + /* advanced Huffman decoding starts here (HCR decoding :) */ + if (pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData != 0) { + /* HCR initialization short */ + hcrStatus = HcrInit(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs); + + if (hcrStatus != 0) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + /* HCR decoding short */ + hcrStatus = + HcrDecoder(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs); + + if (hcrStatus != 0) { +#if HCR_ERROR_CONCEALMENT + HcrMuteErroneousLines(hHcr); +#else + return AAC_DEC_DECODE_FRAME_ERROR; +#endif /* HCR_ERROR_CONCEALMENT */ + } + + FDKpushFor(bs, pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData); + } + } + /* HCR - Huffman Codeword Reordering short finished */ + + if (IsLongBlock(&pAacDecoderChannelInfo->icsInfo) && + !(flags & (AC_ELD | AC_SCALABLE))) { + /* apply pulse data */ + CPulseData_Apply( + &pAacDecoderChannelInfo->pDynData->specificTo.aac.PulseData, + GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, + pSamplingRateInfo), + SPEC_LONG(pSpectralCoefficient)); + } + + return AAC_DEC_OK; +} + +static const FIXP_SGL noise_level_tab[8] = { + /* FDKpow(2, (float)(noise_level-14)/3.0f) * 2; (*2 to compensate for + fMultDiv2) noise_level_tab(noise_level==0) == 0 by definition + */ + FX_DBL2FXCONST_SGL(0x00000000 /*0x0a145173*/), + FX_DBL2FXCONST_SGL(0x0cb2ff5e), + FX_DBL2FXCONST_SGL(0x10000000), + FX_DBL2FXCONST_SGL(0x1428a2e7), + FX_DBL2FXCONST_SGL(0x1965febd), + FX_DBL2FXCONST_SGL(0x20000000), + FX_DBL2FXCONST_SGL(0x28514606), + FX_DBL2FXCONST_SGL(0x32cbfd33)}; + +void CBlock_ApplyNoise(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + SamplingRateInfo *pSamplingRateInfo, ULONG *nfRandomSeed, + UCHAR *band_is_noise) { + const SHORT *swb_offset = GetScaleFactorBandOffsets( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + int g, win, gwin, sfb, noiseFillingStartOffset, nfStartOffset_sfb; + + /* Obtain noise level and scale factor offset. */ + int noise_level = pAacDecoderChannelInfo->pDynData->specificTo.usac + .fd_noise_level_and_offset >> + 5; + const FIXP_SGL noiseVal_pos = noise_level_tab[noise_level]; + + /* noise_offset can change even when noise_level=0. Neccesary for IGF stereo + * filling */ + const int noise_offset = (pAacDecoderChannelInfo->pDynData->specificTo.usac + .fd_noise_level_and_offset & + 0x1f) - + 16; + + int max_sfb = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + + noiseFillingStartOffset = + (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) + ? 20 + : 160; + if (pAacDecoderChannelInfo->granuleLength == 96) { + noiseFillingStartOffset = + (3 * noiseFillingStartOffset) / + 4; /* scale offset with 3/4 for coreCoderFrameLength == 768 */ + } + + /* determine sfb from where on noise filling is applied */ + for (sfb = 0; swb_offset[sfb] < noiseFillingStartOffset; sfb++) + ; + nfStartOffset_sfb = sfb; + + /* if (noise_level!=0) */ + { + for (g = 0, win = 0; g < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + g++) { + int windowGroupLength = + GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo, g); + for (sfb = nfStartOffset_sfb; sfb < max_sfb; sfb++) { + int bin_start = swb_offset[sfb]; + int bin_stop = swb_offset[sfb + 1]; + + int flagN = band_is_noise[g * 16 + sfb]; + + /* if all bins of one sfb in one window group are zero modify the scale + * factor by noise_offset */ + if (flagN) { + /* Change scaling factors for empty signal bands */ + pAacDecoderChannelInfo->pDynData->aScaleFactor[g * 16 + sfb] += + noise_offset; + /* scale factor "sf" implied gain "g" is g = 2^(sf/4) */ + for (gwin = 0; gwin < windowGroupLength; gwin++) { + pAacDecoderChannelInfo->pDynData + ->aSfbScale[(win + gwin) * 16 + sfb] += (noise_offset >> 2); + } + } + + ULONG seed = *nfRandomSeed; + /* + 1 because exponent of MantissaTable[lsb][0] is always 1. */ + int scale = + (pAacDecoderChannelInfo->pDynData->aScaleFactor[g * 16 + sfb] >> + 2) + + 1; + int lsb = + pAacDecoderChannelInfo->pDynData->aScaleFactor[g * 16 + sfb] & 3; + FIXP_DBL mantissa = MantissaTable[lsb][0]; + + for (gwin = 0; gwin < windowGroupLength; gwin++) { + FIXP_DBL *pSpec = + SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, win + gwin, + pAacDecoderChannelInfo->granuleLength); + + int scale1 = scale - pAacDecoderChannelInfo->pDynData + ->aSfbScale[(win + gwin) * 16 + sfb]; + FIXP_DBL scaled_noiseVal_pos = + scaleValue(fMultDiv2(noiseVal_pos, mantissa), scale1); + FIXP_DBL scaled_noiseVal_neg = -scaled_noiseVal_pos; + + /* If the whole band is zero, just fill without checking */ + if (flagN) { + for (int bin = bin_start; bin < bin_stop; bin++) { + seed = (ULONG)( + (UINT64)seed * 69069 + + 5); /* Inlined: UsacRandomSign - origin in usacdec_lpd.h */ + pSpec[bin] = + (seed & 0x10000) ? scaled_noiseVal_neg : scaled_noiseVal_pos; + } /* for (bin...) */ + } + /*If band is sparsely filled, check for 0 and fill */ + else { + for (int bin = bin_start; bin < bin_stop; bin++) { + if (pSpec[bin] == (FIXP_DBL)0) { + seed = (ULONG)( + (UINT64)seed * 69069 + + 5); /* Inlined: UsacRandomSign - origin in usacdec_lpd.h */ + pSpec[bin] = (seed & 0x10000) ? scaled_noiseVal_neg + : scaled_noiseVal_pos; + } + } /* for (bin...) */ + } + + } /* for (gwin...) */ + *nfRandomSeed = seed; + } /* for (sfb...) */ + win += windowGroupLength; + } /* for (g...) */ + + } /* ... */ +} + +AAC_DECODER_ERROR CBlock_ReadAcSpectralData( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const UINT frame_length, + const UINT flags) { + AAC_DECODER_ERROR errorAAC = AAC_DEC_OK; + ARITH_CODING_ERROR error = ARITH_CODER_OK; + int arith_reset_flag, lg, numWin, win, winLen; + const SHORT *RESTRICT BandOffsets; + + /* number of transmitted spectral coefficients */ + BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, + pSamplingRateInfo); + lg = BandOffsets[GetScaleFactorBandsTransmitted( + &pAacDecoderChannelInfo->icsInfo)]; + + numWin = GetWindowsPerFrame(&pAacDecoderChannelInfo->icsInfo); + winLen = (IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) + ? (int)frame_length + : (int)frame_length / numWin; + + if (flags & AC_INDEP) { + arith_reset_flag = 1; + } else { + arith_reset_flag = (USHORT)FDKreadBits(hBs, 1); + } + + for (win = 0; win < numWin; win++) { + error = + CArco_DecodeArithData(pAacDecoderStaticChannelInfo->hArCo, hBs, + SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, + win, pAacDecoderChannelInfo->granuleLength), + lg, winLen, arith_reset_flag && (win == 0)); + if (error != ARITH_CODER_OK) { + goto bail; + } + } + +bail: + if (error == ARITH_CODER_ERROR) { + errorAAC = AAC_DEC_PARSE_ERROR; + } + + return errorAAC; +} + +void ApplyTools(CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + const SamplingRateInfo *pSamplingRateInfo, const UINT flags, + const UINT elFlags, const int channel, + const int common_window) { + if (!(flags & (AC_USAC | AC_RSVD50 | AC_MPEGD_RES | AC_RSV603DA))) { + CPns_Apply(&pAacDecoderChannelInfo[channel]->data.aac.PnsData, + &pAacDecoderChannelInfo[channel]->icsInfo, + pAacDecoderChannelInfo[channel]->pSpectralCoefficient, + pAacDecoderChannelInfo[channel]->specScale, + pAacDecoderChannelInfo[channel]->pDynData->aScaleFactor, + pSamplingRateInfo, + pAacDecoderChannelInfo[channel]->granuleLength, channel); + } + + UCHAR nbands = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[channel]->icsInfo); + + CTns_Apply(&pAacDecoderChannelInfo[channel]->pDynData->TnsData, + &pAacDecoderChannelInfo[channel]->icsInfo, + pAacDecoderChannelInfo[channel]->pSpectralCoefficient, + pSamplingRateInfo, pAacDecoderChannelInfo[channel]->granuleLength, + nbands, (elFlags & AC_EL_ENHANCED_NOISE) ? 1 : 0, flags); +} + +static int getWindow2Nr(int length, int shape) { + int nr = 0; + + if (shape == 2) { + /* Low Overlap, 3/4 zeroed */ + nr = (length * 3) >> 2; + } + + return nr; +} + +FIXP_DBL get_gain(const FIXP_DBL *x, const FIXP_DBL *y, int n) { + FIXP_DBL corr = (FIXP_DBL)0; + FIXP_DBL ener = (FIXP_DBL)1; + + int headroom_x = getScalefactor(x, n); + int headroom_y = getScalefactor(y, n); + + /*Calculate the normalization necessary due to addition*/ + /* Check for power of two /special case */ + INT width_shift = (INT)(fNormz((FIXP_DBL)n)); + /* Get the number of bits necessary minus one, because we need one sign bit + * only */ + width_shift = 31 - width_shift; + + for (int i = 0; i < n; i++) { + corr += + fMultDiv2((x[i] << headroom_x), (y[i] << headroom_y)) >> width_shift; + ener += fPow2Div2((y[i] << headroom_y)) >> width_shift; + } + + int exp_corr = (17 - headroom_x) + (17 - headroom_y) + width_shift + 1; + int exp_ener = ((17 - headroom_y) << 1) + width_shift + 1; + + int temp_exp = 0; + FIXP_DBL output = fDivNormSigned(corr, ener, &temp_exp); + + int output_exp = (exp_corr - exp_ener) + temp_exp; + + INT output_shift = 17 - output_exp; + output_shift = fMin(output_shift, 31); + + output = scaleValue(output, -output_shift); + + return output; +} + +void CBlock_FrequencyToTime( + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[], + const SHORT frameLen, const int frameOk, FIXP_DBL *pWorkBuffer1, + const INT aacOutDataHeadroom, UINT elFlags, INT elCh) { + int fr, fl, tl, nSpec; + +#if defined(FDK_ASSERT_ENABLE) + LONG nSamples; +#endif + + /* Determine left slope length (fl), right slope length (fr) and transform + length (tl). USAC: The slope length may mismatch with the previous frame in + case of LPD / FD transitions. The adjustment is handled by the imdct + implementation. + */ + tl = frameLen; + nSpec = 1; + + switch (pAacDecoderChannelInfo->icsInfo.WindowSequence) { + default: + case BLOCK_LONG: + fl = frameLen; + fr = frameLen - + getWindow2Nr(frameLen, + GetWindowShape(&pAacDecoderChannelInfo->icsInfo)); + /* New startup needs differentiation between sine shape and low overlap + shape. This is a special case for the LD-AAC transformation windows, + because the slope length can be different while using the same window + sequence. */ + if (pAacDecoderStaticChannelInfo->IMdct.prev_tl == 0) { + fl = fr; + } + break; + case BLOCK_STOP: + fl = frameLen >> 3; + fr = frameLen; + break; + case BLOCK_START: /* or StopStartSequence */ + fl = frameLen; + fr = frameLen >> 3; + break; + case BLOCK_SHORT: + fl = fr = frameLen >> 3; + tl >>= 3; + nSpec = 8; + break; + } + + { + int last_frame_lost = pAacDecoderStaticChannelInfo->last_lpc_lost; + + if (pAacDecoderStaticChannelInfo->last_core_mode == LPD) { + INT fac_FB = 1; + if (elFlags & AC_EL_FULLBANDLPD) { + fac_FB = 2; + } + + FIXP_DBL *synth; + + /* Keep some free space at the beginning of the buffer. To be used for + * past data */ + if (!(elFlags & AC_EL_LPDSTEREOIDX)) { + synth = pWorkBuffer1 + ((PIT_MAX_MAX - (1 * L_SUBFR)) * fac_FB); + } else { + synth = pWorkBuffer1 + PIT_MAX_MAX * fac_FB; + } + + int fac_length = + (pAacDecoderChannelInfo->icsInfo.WindowSequence == BLOCK_SHORT) + ? (frameLen >> 4) + : (frameLen >> 3); + + INT pitch[NB_SUBFR_SUPERFR + SYN_SFD]; + FIXP_DBL pit_gain[NB_SUBFR_SUPERFR + SYN_SFD]; + + int nbDiv = (elFlags & AC_EL_FULLBANDLPD) ? 2 : 4; + int lFrame = (elFlags & AC_EL_FULLBANDLPD) ? frameLen / 2 : frameLen; + int nbSubfr = + lFrame / (nbDiv * L_SUBFR); /* number of subframes per division */ + int LpdSfd = (nbDiv * nbSubfr) >> 1; + int SynSfd = LpdSfd - BPF_SFD; + + FDKmemclear( + pitch, + sizeof( + pitch)); // added to prevent ferret errors in bass_pf_1sf_delay + FDKmemclear(pit_gain, sizeof(pit_gain)); + + /* FAC case */ + if (pAacDecoderStaticChannelInfo->last_lpd_mode == 0 || + pAacDecoderStaticChannelInfo->last_lpd_mode == 4) { + FIXP_DBL fac_buf[LFAC]; + FIXP_LPC *A = pAacDecoderChannelInfo->data.usac.lp_coeff[0]; + + if (!frameOk || last_frame_lost || + (pAacDecoderChannelInfo->data.usac.fac_data[0] == NULL)) { + FDKmemclear(fac_buf, + pAacDecoderChannelInfo->granuleLength * sizeof(FIXP_DBL)); + pAacDecoderChannelInfo->data.usac.fac_data[0] = fac_buf; + pAacDecoderChannelInfo->data.usac.fac_data_e[0] = 0; + } + + INT A_exp; /* linear prediction coefficients exponent */ + { + for (int i = 0; i < M_LP_FILTER_ORDER; i++) { + A[i] = FX_DBL2FX_LPC(fixp_cos( + fMult(pAacDecoderStaticChannelInfo->lpc4_lsf[i], + FL2FXCONST_SGL((1 << LSPARG_SCALE) * M_PI / 6400.0)), + LSF_SCALE - LSPARG_SCALE)); + } + + E_LPC_f_lsp_a_conversion(A, A, &A_exp); + } + +#if defined(FDK_ASSERT_ENABLE) + nSamples = +#endif + CLpd_FAC_Acelp2Mdct( + &pAacDecoderStaticChannelInfo->IMdct, synth, + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient), + pAacDecoderChannelInfo->specScale, nSpec, + pAacDecoderChannelInfo->data.usac.fac_data[0], + pAacDecoderChannelInfo->data.usac.fac_data_e[0], fac_length, + frameLen, tl, + FDKgetWindowSlope( + fr, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fr, A, A_exp, &pAacDecoderStaticChannelInfo->acelp, + (FIXP_DBL)0, /* FAC gain has already been applied. */ + (last_frame_lost || !frameOk), 1, + pAacDecoderStaticChannelInfo->last_lpd_mode, 0, + pAacDecoderChannelInfo->currAliasingSymmetry); + + } else { +#if defined(FDK_ASSERT_ENABLE) + nSamples = +#endif + imlt_block( + &pAacDecoderStaticChannelInfo->IMdct, synth, + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient), + pAacDecoderChannelInfo->specScale, nSpec, frameLen, tl, + FDKgetWindowSlope( + fl, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fl, + FDKgetWindowSlope( + fr, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fr, (FIXP_DBL)0, + pAacDecoderChannelInfo->currAliasingSymmetry + ? MLT_FLAG_CURR_ALIAS_SYMMETRY + : 0); + } + FDK_ASSERT(nSamples == frameLen); + + /* The "if" clause is entered both for fullbandLpd mono and + * non-fullbandLpd*. The "else"-> just for fullbandLpd stereo*/ + if (!(elFlags & AC_EL_LPDSTEREOIDX)) { + FDKmemcpy(pitch, pAacDecoderStaticChannelInfo->old_T_pf, + SynSfd * sizeof(INT)); + FDKmemcpy(pit_gain, pAacDecoderStaticChannelInfo->old_gain_pf, + SynSfd * sizeof(FIXP_DBL)); + + for (int i = SynSfd; i < LpdSfd + 3; i++) { + pitch[i] = L_SUBFR; + pit_gain[i] = (FIXP_DBL)0; + } + + if (pAacDecoderStaticChannelInfo->last_lpd_mode == 0) { + pitch[SynSfd] = pitch[SynSfd - 1]; + pit_gain[SynSfd] = pit_gain[SynSfd - 1]; + if (IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) { + pitch[SynSfd + 1] = pitch[SynSfd]; + pit_gain[SynSfd + 1] = pit_gain[SynSfd]; + } + } + + /* Copy old data to the beginning of the buffer */ + { + FDKmemcpy( + pWorkBuffer1, pAacDecoderStaticChannelInfo->old_synth, + ((PIT_MAX_MAX - (1 * L_SUBFR)) * fac_FB) * sizeof(FIXP_DBL)); + } + + FIXP_DBL *p2_synth = pWorkBuffer1 + (PIT_MAX_MAX * fac_FB); + + /* recalculate pitch gain to allow postfilering on FAC area */ + for (int i = 0; i < SynSfd + 2; i++) { + int T = pitch[i]; + FIXP_DBL gain = pit_gain[i]; + + if (gain > (FIXP_DBL)0) { + gain = get_gain(&p2_synth[i * L_SUBFR * fac_FB], + &p2_synth[(i * L_SUBFR * fac_FB) - fac_FB * T], + L_SUBFR * fac_FB); + pit_gain[i] = gain; + } + } + + bass_pf_1sf_delay(p2_synth, pitch, pit_gain, frameLen, + (LpdSfd + 2) * L_SUBFR + BPF_SFD * L_SUBFR, + frameLen - (LpdSfd + 4) * L_SUBFR, outSamples, + aacOutDataHeadroom, + pAacDecoderStaticChannelInfo->mem_bpf); + } + + } else /* last_core_mode was not LPD */ + { + FIXP_DBL *tmp = + pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1->mdctOutTemp; +#if defined(FDK_ASSERT_ENABLE) + nSamples = +#endif + imlt_block(&pAacDecoderStaticChannelInfo->IMdct, tmp, + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient), + pAacDecoderChannelInfo->specScale, nSpec, frameLen, tl, + FDKgetWindowSlope( + fl, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fl, + FDKgetWindowSlope( + fr, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fr, (FIXP_DBL)0, + pAacDecoderChannelInfo->currAliasingSymmetry + ? MLT_FLAG_CURR_ALIAS_SYMMETRY + : 0); + + scaleValuesSaturate(outSamples, tmp, frameLen, + MDCT_OUT_HEADROOM - aacOutDataHeadroom); + } + } + + FDK_ASSERT(nSamples == frameLen); + + pAacDecoderStaticChannelInfo->last_core_mode = + (pAacDecoderChannelInfo->icsInfo.WindowSequence == BLOCK_SHORT) ? FD_SHORT + : FD_LONG; + pAacDecoderStaticChannelInfo->last_lpd_mode = 255; +} + +#include "ldfiltbank.h" +void CBlock_FrequencyToTimeLowDelay( + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[], + const short frameLen) { + InvMdctTransformLowDelay_fdk( + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient), + pAacDecoderChannelInfo->specScale[0], outSamples, + pAacDecoderStaticChannelInfo->pOverlapBuffer, frameLen); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/block.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/block.h new file mode 100644 index 0000000000000..f5118a2dcf88a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/block.h @@ -0,0 +1,345 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: long/short-block decoding + +*******************************************************************************/ + +#ifndef BLOCK_H +#define BLOCK_H + +#include "common_fix.h" + +#include "channelinfo.h" +#include "FDK_bitstream.h" + +/* PNS (of block) */ +void CPns_Read(CPnsData *pPnsData, HANDLE_FDK_BITSTREAM bs, + const CodeBookDescription *hcb, SHORT *pScaleFactor, + UCHAR global_gain, int band, int group); + +void CPns_Apply(const CPnsData *pPnsData, const CIcsInfo *pIcsInfo, + SPECTRAL_PTR pSpectrum, const SHORT *pSpecScale, + const SHORT *pScaleFactor, + const SamplingRateInfo *pSamplingRateInfo, + const INT granuleLength, const int channel); + +void CBlock_ApplyNoise(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + SamplingRateInfo *pSamplingRateInfo, ULONG *nfRandomSeed, + UCHAR *band_is_noise); + +/* TNS (of block) */ +/*! + \brief Read tns data-present flag from bitstream + + The function reads the data-present flag for tns from + the bitstream. + + \return none +*/ +void CTns_ReadDataPresentFlag(HANDLE_FDK_BITSTREAM bs, CTnsData *pTnsData); + +void CTns_ReadDataPresentUsac(HANDLE_FDK_BITSTREAM hBs, CTnsData *pTnsData0, + CTnsData *pTnsData1, UCHAR *ptns_on_lr, + const CIcsInfo *pIcsInfo, const UINT flags, + const UINT elFlags, const int fCommonWindow); + +AAC_DECODER_ERROR CTns_Read(HANDLE_FDK_BITSTREAM bs, CTnsData *pTnsData, + const CIcsInfo *pIcsInfo, const UINT flags); + +void CTns_Apply(CTnsData *RESTRICT pTnsData, /*!< pointer to aac decoder info */ + const CIcsInfo *pIcsInfo, SPECTRAL_PTR pSpectralCoefficient, + const SamplingRateInfo *pSamplingRateInfo, + const INT granuleLength, const UCHAR nbands, + const UCHAR igf_active, const UINT flags); + +/* Block */ + +LONG CBlock_GetEscape(HANDLE_FDK_BITSTREAM bs, const LONG q); + +/** + * \brief Read scale factor data. See chapter 4.6.2.3.2 of ISO/IEC 14496-3. + * The SF_OFFSET = 100 value referenced in chapter 4.6.2.3.3 is already + * substracted from the scale factor values. Also includes PNS data reading. + * \param bs bit stream handle data source + * \param pAacDecoderChannelInfo channel context info were decoded data is + * stored into. + * \param flags the decoder flags. + */ +AAC_DECODER_ERROR CBlock_ReadScaleFactorData( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, HANDLE_FDK_BITSTREAM bs, + const UINT flags); + +/** + * \brief Read Huffman encoded spectral data. + * \param pAacDecoderChannelInfo channel context info. + * \param pSamplingRateInfo sampling rate info (sfb offsets). + * \param flags syntax flags. + */ +AAC_DECODER_ERROR CBlock_ReadSpectralData( + HANDLE_FDK_BITSTREAM bs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const UINT flags); + +/** + * \brief Read Arithmetic encoded spectral data. + * \param pAacDecoderChannelInfo channel context info. + * \param pAacDecoderStaticChannelInfo static channel context info. + * \param pSamplingRateInfo sampling rate info (sfb offsets). + * \param frame_length spectral window length. + * \param flags syntax flags. + * \return error code. + */ +AAC_DECODER_ERROR CBlock_ReadAcSpectralData( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const UINT frame_length, + const UINT flags); + +AAC_DECODER_ERROR CBlock_ReadSectionData( + HANDLE_FDK_BITSTREAM bs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const UINT flags); + +/** + * \brief find a common exponent (shift factor) for all sfb in each Spectral + * window, and store them into CAacDecoderChannelInfo::specScale. + * \param pAacDecoderChannelInfo channel context info. + * \param UCHAR maxSfbs maximum number of SFBs to be processed (might differ + * from pAacDecoderChannelInfo->icsInfo.MaxSfBands) + * \param pSamplingRateInfo sampling rate info (sfb offsets). + */ +void CBlock_ScaleSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + UCHAR maxSfbs, + SamplingRateInfo *pSamplingRateInfo); + +/** + * \brief Apply TNS and PNS tools. + */ +void ApplyTools(CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + const SamplingRateInfo *pSamplingRateInfo, const UINT flags, + const UINT elFlags, const int channel, const int maybe_jstereo); + +/** + * \brief Transform MDCT spectral data into time domain + */ +void CBlock_FrequencyToTime( + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[], + const SHORT frameLen, const int frameOk, FIXP_DBL *pWorkBuffer1, + const INT aacOutDataHeadroom, UINT elFlags, INT elCh); + +/** + * \brief Transform double lapped MDCT (AAC-ELD) spectral data into time domain. + */ +void CBlock_FrequencyToTimeLowDelay( + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[], + const short frameLen); + +AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + SamplingRateInfo *pSamplingRateInfo, UCHAR *band_is_noise, + UCHAR active_band_search); + +/** + * \brief Calculate 2^(lsb/4) * value^(4/3) + * \param pValue pointer to quantized value. The inverse quantized result is + * stored back here. + * \param lsb 2 LSBs of the scale factor (scaleFactor % 4) applied as power 2 + * factor to the resulting inverse quantized value. + * \return the exponent of the result (mantissa) stored into *pValue. + */ +FDK_INLINE +int EvaluatePower43(FIXP_DBL *pValue, UINT lsb) { + FIXP_DBL value; + UINT freeBits; + UINT exponent; + + value = *pValue; + freeBits = fNormz(value); + exponent = DFRACT_BITS - freeBits; + FDK_ASSERT(exponent < 14); + + UINT x = (((int)value << freeBits) >> 19); + UINT tableIndex = (x & 0x0FFF) >> 4; + FIXP_DBL invQVal; + + x = x & 0x0F; + + UINT r0 = (LONG)InverseQuantTable[tableIndex + 0]; + UINT r1 = (LONG)InverseQuantTable[tableIndex + 1]; + USHORT nx = 16 - x; + UINT temp = (r0)*nx + (r1)*x; + invQVal = (FIXP_DBL)temp; + + FDK_ASSERT(lsb < 4); + *pValue = fMultDiv2(invQVal, MantissaTable[lsb][exponent]); + + /* + 1 compensates fMultDiv2(). */ + return ExponentTable[lsb][exponent] + 1; +} + +/* Recalculate gain */ +FIXP_DBL get_gain(const FIXP_DBL *x, const FIXP_DBL *y, int n); + +/** + * \brief determine the required shift scale for the given quantized value and + * scale (factor % 4) value. + */ +FDK_INLINE int GetScaleFromValue(FIXP_DBL value, unsigned int lsb) { + if (value != (FIXP_DBL)0) { + int scale = EvaluatePower43(&value, lsb); + return CntLeadingZeros(value) - scale - 2; + } else + return 0; /* Return zero, because its useless to scale a zero value, saves + workload and avoids scaling overshifts. */ +} + +/*! + \brief Read huffman codeword + + The function reads the huffman codeword from the bitstream and + returns the index value. + + \return index value +*/ +inline int CBlock_DecodeHuffmanWord( + HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */ + const CodeBookDescription *hcb) /*!< pointer to codebook description */ +{ + UINT val; + UINT index = 0; + const USHORT(*CodeBook)[HuffmanEntries] = hcb->CodeBook; + + while (1) { + val = CodeBook[index] + [FDKreadBits(bs, HuffmanBits)]; /* Expensive memory access */ + + if ((val & 1) == 0) { + index = val >> 2; + continue; + } else { + if (val & 2) { + FDKpushBackCache(bs, 1); + } + + val >>= 2; + break; + } + } + + return val; +} +inline int CBlock_DecodeHuffmanWordCB( + HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */ + const USHORT ( + *CodeBook)[HuffmanEntries]) /*!< pointer to codebook description */ +{ + UINT index = 0; + + while (1) { + index = CodeBook[index][FDKread2Bits(bs)]; /* Expensive memory access */ + if (index & 1) break; + index >>= 2; + } + if (index & 2) { + FDKpushBackCache(bs, 1); + } + return index >> 2; +} + +#endif /* #ifndef BLOCK_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channel.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channel.cpp new file mode 100644 index 0000000000000..7e62bfb577d3a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channel.cpp @@ -0,0 +1,926 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +#include "channel.h" +#include "aacdecoder.h" +#include "block.h" +#include "aacdec_tns.h" +#include "FDK_bitstream.h" + +#include "conceal.h" + +#include "rvlc.h" + +#include "aacdec_hcr.h" + +#include "usacdec_lpd.h" +#include "usacdec_fac.h" + +static void MapMidSideMaskToPnsCorrelation( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[2]) { + int group; + + for (group = 0; group < pAacDecoderChannelInfo[L]->icsInfo.WindowGroups; + group++) { + UCHAR groupMask = 1 << group; + + for (UCHAR band = 0; band < pAacDecoderChannelInfo[L]->icsInfo.MaxSfBands; + band++) { + if (pAacDecoderChannelInfo[L]->pComData->jointStereoData.MsUsed[band] & + groupMask) { /* channels are correlated */ + CPns_SetCorrelation(&pAacDecoderChannelInfo[L]->data.aac.PnsData, group, + band, 0); + + if (CPns_IsPnsUsed(&pAacDecoderChannelInfo[L]->data.aac.PnsData, group, + band) && + CPns_IsPnsUsed(&pAacDecoderChannelInfo[R]->data.aac.PnsData, group, + band)) + pAacDecoderChannelInfo[L]->pComData->jointStereoData.MsUsed[band] ^= + groupMask; /* clear the groupMask-bit */ + } + } + } +} + +static void Clean_Complex_Prediction_coefficients( + CJointStereoPersistentData *pJointStereoPersistentData, int windowGroups, + const int low_limit, const int high_limit) { + for (int group = 0; group < windowGroups; group++) { + for (int sfb = low_limit; sfb < high_limit; sfb++) { + pJointStereoPersistentData->alpha_q_re_prev[group][sfb] = 0; + pJointStereoPersistentData->alpha_q_im_prev[group][sfb] = 0; + } + } +} + +/*! + \brief Decode channel pair element + + The function decodes a channel pair element. + + \return none +*/ +void CChannelElement_Decode( + CAacDecoderChannelInfo + *pAacDecoderChannelInfo[2], /*!< pointer to aac decoder channel info */ + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2], + SamplingRateInfo *pSamplingRateInfo, UINT flags, UINT elFlags, + int el_channels) { + int ch = 0; + + int maxSfBandsL = 0, maxSfBandsR = 0; + int maybe_jstereo = (el_channels > 1); + + if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA) && el_channels == 2) { + if (pAacDecoderChannelInfo[L]->data.usac.core_mode || + pAacDecoderChannelInfo[R]->data.usac.core_mode) { + maybe_jstereo = 0; + } + } + + if (maybe_jstereo) { + maxSfBandsL = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[L]->icsInfo); + maxSfBandsR = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[R]->icsInfo); + + /* apply ms */ + if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow) { + if (!(flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) { + if (pAacDecoderChannelInfo[L]->data.aac.PnsData.PnsActive || + pAacDecoderChannelInfo[R]->data.aac.PnsData.PnsActive) { + MapMidSideMaskToPnsCorrelation(pAacDecoderChannelInfo); + } + } + /* if tns_on_lr == 1 run MS */ /* && + (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_active + == 1) */ + if (((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && + (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_on_lr == + 1)) || + ((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) == 0)) { + int max_sfb_ste = (INT)(pAacDecoderChannelInfo[L]->icsInfo.max_sfb_ste); + + CJointStereo_ApplyMS( + pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, + pAacDecoderChannelInfo[L]->pSpectralCoefficient, + pAacDecoderChannelInfo[R]->pSpectralCoefficient, + pAacDecoderChannelInfo[L]->pDynData->aSfbScale, + pAacDecoderChannelInfo[R]->pDynData->aSfbScale, + pAacDecoderChannelInfo[L]->specScale, + pAacDecoderChannelInfo[R]->specScale, + GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, + pSamplingRateInfo), + GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo), + GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo), max_sfb_ste, + maxSfBandsL, maxSfBandsR, + pAacDecoderChannelInfo[L] + ->pComData->jointStereoData.store_dmx_re_prev, + &(pAacDecoderChannelInfo[L] + ->pComData->jointStereoData.store_dmx_re_prev_e), + 1); + + } /* if ( ((elFlags & AC_EL_USAC_CP_POSSIBLE).... */ + } /* if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow)*/ + + /* apply intensity stereo */ /* modifies pAacDecoderChannelInfo[]->aSpecSfb + */ + if (!(flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) { + if ((pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow == + 1) && + (el_channels == 2)) { + CJointStereo_ApplyIS( + pAacDecoderChannelInfo, + GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, + pSamplingRateInfo), + GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo), + GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo), + GetScaleFactorBandsTransmitted( + &pAacDecoderChannelInfo[L]->icsInfo)); + } + } + } /* maybe_stereo */ + + for (ch = 0; ch < el_channels; ch++) { + if (pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_LPD) { + /* Decode LPD data */ + CLpdChannelStream_Decode(pAacDecoderChannelInfo[ch], + pAacDecoderStaticChannelInfo[ch], flags); + } else { + UCHAR noSfbs = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[ch]->icsInfo); + /* For USAC common window: max_sfb of both channels may differ + * (common_max_sfb == 0). */ + if ((maybe_jstereo == 1) && + (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow == + 1)) { + noSfbs = fMax(maxSfBandsL, maxSfBandsR); + } + int CP_active = 0; + if (elFlags & AC_EL_USAC_CP_POSSIBLE) { + CP_active = pAacDecoderChannelInfo[ch] + ->pComData->jointStereoData.cplx_pred_flag; + } + + /* Omit writing of pAacDecoderChannelInfo[ch]->specScale for complex + stereo prediction since scaling has already been carried out. */ + int max_sfb_ste = (INT)(pAacDecoderChannelInfo[L]->icsInfo.max_sfb_ste); + + if (!(CP_active && (max_sfb_ste == noSfbs)) || + !(CP_active && + !(pAacDecoderChannelInfo[ch]->pDynData->TnsData.Active)) || + ((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && + (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_on_lr == + 0))) { + CBlock_ScaleSpectralData(pAacDecoderChannelInfo[ch], noSfbs, + pSamplingRateInfo); + + /*Active for the case of TNS applied before MS/CP*/ + if ((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && + (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_on_lr == + 0)) { + if (IsLongBlock(&pAacDecoderChannelInfo[ch]->icsInfo)) { + for (int i = 0; i < noSfbs; i++) { + pAacDecoderChannelInfo[ch]->pDynData->aSfbScale[i] = + pAacDecoderChannelInfo[ch]->specScale[0]; + } + } else { + for (int i = 0; i < 8; i++) { + for (int j = 0; j < noSfbs; j++) { + pAacDecoderChannelInfo[ch]->pDynData->aSfbScale[i * 16 + j] = + pAacDecoderChannelInfo[ch]->specScale[i]; + } + } + } + } + } + } + } /* End "for (ch = 0; ch < el_channels; ch++)" */ + + if (maybe_jstereo) { + /* apply ms */ + if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow) { + } /* CommonWindow */ + else { + if (elFlags & AC_EL_USAC_CP_POSSIBLE) { + FDKmemclear( + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.alpha_q_re_prev, + JointStereoMaximumGroups * JointStereoMaximumBands * sizeof(SHORT)); + FDKmemclear( + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.alpha_q_im_prev, + JointStereoMaximumGroups * JointStereoMaximumBands * sizeof(SHORT)); + } + } + + } /* if (maybe_jstereo) */ + + for (ch = 0; ch < el_channels; ch++) { + if (pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_LPD) { + } else { + if (!(flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) { + /* Use same seed for coupled channels (CPE) */ + int pnsCh = (ch > 0) ? L : ch; + CPns_UpdateNoiseState( + &pAacDecoderChannelInfo[ch]->data.aac.PnsData, + pAacDecoderChannelInfo[pnsCh]->data.aac.PnsData.currentSeed, + pAacDecoderChannelInfo[ch]->pComData->pnsRandomSeed); + } + + if ((!(flags & (AC_USAC))) || + ((flags & (AC_USAC)) && + (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_active == + 1)) || + (maybe_jstereo == 0)) { + ApplyTools( + pAacDecoderChannelInfo, pSamplingRateInfo, flags, elFlags, ch, + pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow); + } + } /* End "} else" */ + } /* End "for (ch = 0; ch < el_channels; ch++)" */ + + if (maybe_jstereo) { + /* apply ms */ + if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow) { + /* if tns_on_lr == 0 run MS */ + if ((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && + (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_on_lr == + 0)) { + int max_sfb_ste = (INT)(pAacDecoderChannelInfo[L]->icsInfo.max_sfb_ste); + + CJointStereo_ApplyMS( + pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, + pAacDecoderChannelInfo[L]->pSpectralCoefficient, + pAacDecoderChannelInfo[R]->pSpectralCoefficient, + pAacDecoderChannelInfo[L]->pDynData->aSfbScale, + pAacDecoderChannelInfo[R]->pDynData->aSfbScale, + pAacDecoderChannelInfo[L]->specScale, + pAacDecoderChannelInfo[R]->specScale, + GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, + pSamplingRateInfo), + GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo), + GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo), max_sfb_ste, + maxSfBandsL, maxSfBandsR, + pAacDecoderChannelInfo[L] + ->pComData->jointStereoData.store_dmx_re_prev, + &(pAacDecoderChannelInfo[L] + ->pComData->jointStereoData.store_dmx_re_prev_e), + 1); + } + + } /* if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow) */ + + } /* if (maybe_jstereo) */ + + for (ch = 0; ch < el_channels; ch++) { + if (elFlags & AC_EL_USAC_CP_POSSIBLE) { + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.clearSpectralCoeffs = 0; + } + } + + CRvlc_ElementCheck(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, + flags, el_channels); +} + +void CChannel_CodebookTableInit( + CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + int b, w, maxBands, maxWindows; + int maxSfb = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + + if (IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) { + maxBands = 64; + maxWindows = 1; + } else { + maxBands = 16; + maxWindows = 8; + } + + for (w = 0; w < maxWindows; w++) { + for (b = 0; b < maxSfb; b++) { + pCodeBook[b] = ESCBOOK; + } + for (; b < maxBands; b++) { + pCodeBook[b] = ZERO_HCB; + } + pCodeBook += maxBands; + } +} + +/* + * Arbitrary order bitstream parser + */ +AAC_DECODER_ERROR CChannelElement_Read( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + const AUDIO_OBJECT_TYPE aot, SamplingRateInfo *pSamplingRateInfo, + const UINT flags, const UINT elFlags, const UINT frame_length, + const UCHAR numberOfChannels, const SCHAR epConfig, + HANDLE_TRANSPORTDEC pTpDec) { + AAC_DECODER_ERROR error = AAC_DEC_OK; + const element_list_t *list; + int i, ch, decision_bit; + int crcReg1 = -1, crcReg2 = -1; + int cplxPred; + int ind_sw_cce_flag = 0, num_gain_element_lists = 0; + + FDK_ASSERT((numberOfChannels == 1) || (numberOfChannels == 2)); + + /* Get channel element sequence table */ + list = getBitstreamElementList(aot, epConfig, numberOfChannels, 0, elFlags); + if (list == NULL) { + error = AAC_DEC_UNSUPPORTED_FORMAT; + goto bail; + } + + CTns_Reset(&pAacDecoderChannelInfo[0]->pDynData->TnsData); + /* Set common window to 0 by default. If signalized in the bit stream it will + * be overwritten later explicitely */ + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow = 0; + if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) { + pAacDecoderChannelInfo[0]->pDynData->specificTo.usac.tns_active = 0; + pAacDecoderChannelInfo[0]->pDynData->specificTo.usac.tns_on_lr = 0; + } + if (numberOfChannels == 2) { + CTns_Reset(&pAacDecoderChannelInfo[1]->pDynData->TnsData); + pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = 0; + } + + cplxPred = 0; + if (pAacDecoderStaticChannelInfo != NULL) { + if (elFlags & AC_EL_USAC_CP_POSSIBLE) { + pAacDecoderChannelInfo[0]->pComData->jointStereoData.cplx_pred_flag = 0; + cplxPred = 1; + } + } + + if (0 || (flags & (AC_ELD | AC_SCALABLE))) { + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow = 1; + if (numberOfChannels == 2) { + pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow; + } + } + + /* Iterate through sequence table */ + i = 0; + ch = 0; + decision_bit = 0; + do { + switch (list->id[i]) { + case element_instance_tag: + pAacDecoderChannelInfo[0]->ElementInstanceTag = FDKreadBits(hBs, 4); + if (numberOfChannels == 2) { + pAacDecoderChannelInfo[1]->ElementInstanceTag = + pAacDecoderChannelInfo[0]->ElementInstanceTag; + } + break; + case common_window: + decision_bit = + pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.CommonWindow = + FDKreadBits(hBs, 1); + if (numberOfChannels == 2) { + pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow; + } + break; + case ics_info: + /* store last window sequence (utilized in complex stereo prediction) + * before reading new channel-info */ + if (cplxPred) { + if (pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow) { + pAacDecoderStaticChannelInfo[0] + ->pCpeStaticData->jointStereoPersistentData.winSeqPrev = + pAacDecoderChannelInfo[0]->icsInfo.WindowSequence; + pAacDecoderStaticChannelInfo[0] + ->pCpeStaticData->jointStereoPersistentData.winShapePrev = + pAacDecoderChannelInfo[0]->icsInfo.WindowShape; + } + } + /* Read individual channel info */ + error = IcsRead(hBs, &pAacDecoderChannelInfo[ch]->icsInfo, + pSamplingRateInfo, flags); + + if (elFlags & AC_EL_LFE && + GetWindowSequence(&pAacDecoderChannelInfo[ch]->icsInfo) != + BLOCK_LONG) { + error = AAC_DEC_PARSE_ERROR; + break; + } + + if (numberOfChannels == 2 && + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow) { + pAacDecoderChannelInfo[1]->icsInfo = + pAacDecoderChannelInfo[0]->icsInfo; + } + break; + + case common_max_sfb: + if (FDKreadBit(hBs) == 0) { + error = IcsReadMaxSfb(hBs, &pAacDecoderChannelInfo[1]->icsInfo, + pSamplingRateInfo); + } + break; + + case ltp_data_present: + if (FDKreadBits(hBs, 1) != 0) { + error = AAC_DEC_UNSUPPORTED_PREDICTION; + } + break; + + case ms: + + INT max_sfb_ste; + INT max_sfb_ste_clear; + + max_sfb_ste = GetScaleMaxFactorBandsTransmitted( + &pAacDecoderChannelInfo[0]->icsInfo, + &pAacDecoderChannelInfo[1]->icsInfo); + + max_sfb_ste_clear = 64; + + pAacDecoderChannelInfo[0]->icsInfo.max_sfb_ste = (UCHAR)max_sfb_ste; + pAacDecoderChannelInfo[1]->icsInfo.max_sfb_ste = (UCHAR)max_sfb_ste; + + if (flags & (AC_USAC | AC_RSV603DA) && + pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.CommonWindow == + 0) { + Clean_Complex_Prediction_coefficients( + &pAacDecoderStaticChannelInfo[0] + ->pCpeStaticData->jointStereoPersistentData, + GetWindowGroups(&pAacDecoderChannelInfo[0]->icsInfo), 0, 64); + } + + if (CJointStereo_Read( + hBs, &pAacDecoderChannelInfo[0]->pComData->jointStereoData, + GetWindowGroups(&pAacDecoderChannelInfo[0]->icsInfo), + max_sfb_ste, max_sfb_ste_clear, + /* jointStereoPersistentData and cplxPredictionData are only + available/allocated if cplxPred is active. */ + ((cplxPred == 0) || (pAacDecoderStaticChannelInfo == NULL)) + ? NULL + : &pAacDecoderStaticChannelInfo[0] + ->pCpeStaticData->jointStereoPersistentData, + ((cplxPred == 0) || (pAacDecoderChannelInfo[0] == NULL)) + ? NULL + : pAacDecoderChannelInfo[0] + ->pComStaticData->cplxPredictionData, + cplxPred, + GetScaleFactorBandsTotal(&pAacDecoderChannelInfo[0]->icsInfo), + GetWindowSequence(&pAacDecoderChannelInfo[0]->icsInfo), + flags)) { + error = AAC_DEC_PARSE_ERROR; + } + + break; + + case global_gain: + pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.GlobalGain = + (UCHAR)FDKreadBits(hBs, 8); + break; + + case section_data: + error = CBlock_ReadSectionData(hBs, pAacDecoderChannelInfo[ch], + pSamplingRateInfo, flags); + break; + + case scale_factor_data_usac: + pAacDecoderChannelInfo[ch]->currAliasingSymmetry = 0; + /* Set active sfb codebook indexes to HCB_ESC to make them "active" */ + CChannel_CodebookTableInit( + pAacDecoderChannelInfo[ch]); /* equals ReadSectionData(self, + bs) in float soft. block.c + line: ~599 */ + /* Note: The missing "break" is intentional here, since we need to call + * CBlock_ReadScaleFactorData(). */ + FDK_FALLTHROUGH; + + case scale_factor_data: + if (flags & AC_ER_RVLC) { + /* read RVLC data from bitstream (error sens. cat. 1) */ + CRvlc_Read(pAacDecoderChannelInfo[ch], hBs); + } else { + error = CBlock_ReadScaleFactorData(pAacDecoderChannelInfo[ch], hBs, + flags); + } + break; + + case pulse: + if (CPulseData_Read( + hBs, + &pAacDecoderChannelInfo[ch]->pDynData->specificTo.aac.PulseData, + pSamplingRateInfo->ScaleFactorBands_Long, /* pulse data is only + allowed to be + present in long + blocks! */ + (void *)&pAacDecoderChannelInfo[ch]->icsInfo, + frame_length) != 0) { + error = AAC_DEC_DECODE_FRAME_ERROR; + } + break; + case tns_data_present: + CTns_ReadDataPresentFlag( + hBs, &pAacDecoderChannelInfo[ch]->pDynData->TnsData); + if (elFlags & AC_EL_LFE && + pAacDecoderChannelInfo[ch]->pDynData->TnsData.DataPresent) { + error = AAC_DEC_PARSE_ERROR; + } + break; + case tns_data: + /* tns_data_present is checked inside CTns_Read(). */ + error = CTns_Read(hBs, &pAacDecoderChannelInfo[ch]->pDynData->TnsData, + &pAacDecoderChannelInfo[ch]->icsInfo, flags); + + break; + + case gain_control_data: + break; + + case gain_control_data_present: + if (FDKreadBits(hBs, 1)) { + error = AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA; + } + break; + + case tw_data: + break; + case common_tw: + break; + case tns_data_present_usac: + if (pAacDecoderChannelInfo[0]->pDynData->specificTo.usac.tns_active) { + CTns_ReadDataPresentUsac( + hBs, &pAacDecoderChannelInfo[0]->pDynData->TnsData, + &pAacDecoderChannelInfo[1]->pDynData->TnsData, + &pAacDecoderChannelInfo[0]->pDynData->specificTo.usac.tns_on_lr, + &pAacDecoderChannelInfo[0]->icsInfo, flags, elFlags, + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow); + } else { + pAacDecoderChannelInfo[0]->pDynData->specificTo.usac.tns_on_lr = + (UCHAR)1; + } + break; + case core_mode: + decision_bit = FDKreadBits(hBs, 1); + pAacDecoderChannelInfo[ch]->data.usac.core_mode = decision_bit; + if ((ch == 1) && (pAacDecoderChannelInfo[0]->data.usac.core_mode != + pAacDecoderChannelInfo[1]->data.usac.core_mode)) { + /* StereoCoreToolInfo(core_mode[ch] ) */ + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow = 0; + pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = 0; + } + break; + case tns_active: + pAacDecoderChannelInfo[0]->pDynData->specificTo.usac.tns_active = + FDKreadBit(hBs); + break; + case noise: + if (elFlags & AC_EL_USAC_NOISE) { + pAacDecoderChannelInfo[ch] + ->pDynData->specificTo.usac.fd_noise_level_and_offset = + FDKreadBits(hBs, 3 + 5); /* Noise level */ + } + break; + case lpd_channel_stream: + + { + error = CLpdChannelStream_Read(/* = lpd_channel_stream() */ + hBs, pAacDecoderChannelInfo[ch], + pAacDecoderStaticChannelInfo[ch], + pSamplingRateInfo, flags); + } + + pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_LPD; + break; + case fac_data: { + int fFacDatPresent = FDKreadBit(hBs); + + /* Wee need a valid fac_data[0] even if no FAC data is present (as + * temporal buffer) */ + pAacDecoderChannelInfo[ch]->data.usac.fac_data[0] = + pAacDecoderChannelInfo[ch]->data.usac.fac_data0; + + if (fFacDatPresent) { + if (elFlags & AC_EL_LFE) { + error = AAC_DEC_PARSE_ERROR; + break; + } + /* FAC data present, this frame is FD, so the last mode had to be + * ACELP. */ + if (pAacDecoderStaticChannelInfo[ch]->last_core_mode != LPD || + pAacDecoderStaticChannelInfo[ch]->last_lpd_mode != 0) { + pAacDecoderChannelInfo[ch]->data.usac.core_mode_last = LPD; + pAacDecoderChannelInfo[ch]->data.usac.lpd_mode_last = 0; + /* We can't change the past! So look to the future and go ahead! */ + } + CLpd_FAC_Read(hBs, pAacDecoderChannelInfo[ch]->data.usac.fac_data[0], + pAacDecoderChannelInfo[ch]->data.usac.fac_data_e, + CLpd_FAC_getLength( + IsLongBlock(&pAacDecoderChannelInfo[ch]->icsInfo), + pAacDecoderChannelInfo[ch]->granuleLength), + 1, 0); + } else { + if (pAacDecoderStaticChannelInfo[ch]->last_core_mode == LPD && + pAacDecoderStaticChannelInfo[ch]->last_lpd_mode == 0) { + /* ACELP to FD transitons without FAC are possible. That is why we + zero it out (i.e FAC will not be considered in the subsequent + calculations */ + FDKmemclear(pAacDecoderChannelInfo[ch]->data.usac.fac_data0, + LFAC * sizeof(FIXP_DBL)); + } + } + } break; + case esc2_rvlc: + if (flags & AC_ER_RVLC) { + CRvlc_Decode(pAacDecoderChannelInfo[ch], + pAacDecoderStaticChannelInfo[ch], hBs); + } + break; + + case esc1_hcr: + if (flags & AC_ER_HCR) { + CHcr_Read(hBs, pAacDecoderChannelInfo[ch], + numberOfChannels == 2 ? ID_CPE : ID_SCE); + } + break; + + case spectral_data: + error = CBlock_ReadSpectralData(hBs, pAacDecoderChannelInfo[ch], + pSamplingRateInfo, flags); + if (flags & AC_ELD) { + pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_ELDFB; + } else { + if (flags & AC_HDAAC) { + pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_INTIMDCT; + } else { + pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_IMDCT; + } + } + break; + + case ac_spectral_data: + error = CBlock_ReadAcSpectralData( + hBs, pAacDecoderChannelInfo[ch], pAacDecoderStaticChannelInfo[ch], + pSamplingRateInfo, frame_length, flags); + pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_IMDCT; + break; + + case coupled_elements: { + int num_coupled_elements, c; + + ind_sw_cce_flag = FDKreadBit(hBs); + num_coupled_elements = FDKreadBits(hBs, 3); + + for (c = 0; c < (num_coupled_elements + 1); c++) { + int cc_target_is_cpe; + + num_gain_element_lists++; + cc_target_is_cpe = FDKreadBit(hBs); /* cc_target_is_cpe[c] */ + FDKreadBits(hBs, 4); /* cc_target_tag_select[c] */ + + if (cc_target_is_cpe) { + int cc_l, cc_r; + + cc_l = FDKreadBit(hBs); /* cc_l[c] */ + cc_r = FDKreadBit(hBs); /* cc_r[c] */ + + if (cc_l && cc_r) { + num_gain_element_lists++; + } + } + } + FDKreadBit(hBs); /* cc_domain */ + FDKreadBit(hBs); /* gain_element_sign */ + FDKreadBits(hBs, 2); /* gain_element_scale */ + } break; + + case gain_element_lists: { + const CodeBookDescription *hcb; + UCHAR *pCodeBook; + int c; + + hcb = &AACcodeBookDescriptionTable[BOOKSCL]; + pCodeBook = pAacDecoderChannelInfo[ch]->pDynData->aCodeBook; + + for (c = 1; c < num_gain_element_lists; c++) { + int cge; + if (ind_sw_cce_flag) { + cge = 1; + } else { + cge = FDKreadBits(hBs, 1); /* common_gain_element_present[c] */ + } + if (cge) { + /* Huffman */ + CBlock_DecodeHuffmanWord( + hBs, hcb); /* hcod_sf[common_gain_element[c]] 1..19 */ + } else { + int g, sfb; + for (g = 0; + g < GetWindowGroups(&pAacDecoderChannelInfo[ch]->icsInfo); + g++) { + for (sfb = 0; sfb < GetScaleFactorBandsTransmitted( + &pAacDecoderChannelInfo[ch]->icsInfo); + sfb++) { + if (pCodeBook[sfb] != ZERO_HCB) { + /* Huffman */ + CBlock_DecodeHuffmanWord( + hBs, + hcb); /* hcod_sf[dpcm_gain_element[c][g][sfb]] 1..19 */ + } + } + } + } + } + } break; + + /* CRC handling */ + case adtscrc_start_reg1: + if (pTpDec != NULL) { + crcReg1 = transportDec_CrcStartReg(pTpDec, 192); + } + break; + case adtscrc_start_reg2: + if (pTpDec != NULL) { + crcReg2 = transportDec_CrcStartReg(pTpDec, 128); + } + break; + case adtscrc_end_reg1: + case drmcrc_end_reg: + if (pTpDec != NULL) { + transportDec_CrcEndReg(pTpDec, crcReg1); + crcReg1 = -1; + } + break; + case adtscrc_end_reg2: + if (crcReg1 != -1) { + error = AAC_DEC_DECODE_FRAME_ERROR; + } else if (pTpDec != NULL) { + transportDec_CrcEndReg(pTpDec, crcReg2); + crcReg2 = -1; + } + break; + case drmcrc_start_reg: + if (pTpDec != NULL) { + crcReg1 = transportDec_CrcStartReg(pTpDec, 0); + } + break; + + /* Non data cases */ + case next_channel: + ch = (ch + 1) % numberOfChannels; + break; + case link_sequence: + list = list->next[decision_bit]; + i = -1; + break; + + default: + error = AAC_DEC_UNSUPPORTED_FORMAT; + break; + } + + if (error != AAC_DEC_OK) { + goto bail; + } + + i++; + + } while (list->id[i] != end_of_sequence); + + for (ch = 0; ch < numberOfChannels; ch++) { + if (pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_IMDCT || + pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_ELDFB) { + /* Shows which bands are empty. */ + UCHAR *band_is_noise = + pAacDecoderChannelInfo[ch]->pDynData->band_is_noise; + FDKmemset(band_is_noise, (UCHAR)1, sizeof(UCHAR) * (8 * 16)); + + error = CBlock_InverseQuantizeSpectralData( + pAacDecoderChannelInfo[ch], pSamplingRateInfo, band_is_noise, 1); + if (error != AAC_DEC_OK) { + return error; + } + + if (elFlags & AC_EL_USAC_NOISE) { + CBlock_ApplyNoise(pAacDecoderChannelInfo[ch], pSamplingRateInfo, + &pAacDecoderStaticChannelInfo[ch]->nfRandomSeed, + band_is_noise); + + } /* if (elFlags & AC_EL_USAC_NOISE) */ + } + } + +bail: + if (crcReg1 != -1 || crcReg2 != -1) { + if (error == AAC_DEC_OK) { + error = AAC_DEC_DECODE_FRAME_ERROR; + } + if (crcReg1 != -1) { + transportDec_CrcEndReg(pTpDec, crcReg1); + } + if (crcReg2 != -1) { + transportDec_CrcEndReg(pTpDec, crcReg2); + } + } + return error; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channel.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channel.h new file mode 100644 index 0000000000000..ed4666678e1ee --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channel.h @@ -0,0 +1,160 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +#ifndef CHANNEL_H +#define CHANNEL_H + +#include "common_fix.h" + +#include "FDK_tools_rom.h" +#include "channelinfo.h" +#include "tpdec_lib.h" + +/** + * \brief Init codeBook SFB indices (section data) with HCB_ESC. Useful for + * bitstreams which do not have any section data, but still SFB's (scale factor + * bands). This has the effect that upto the amount of transmitted SFB are + * treated as non-zero. + * \param pAacDecoderChannelInfo channel info structure containing a valid + * icsInfo struct. + */ +void CChannel_CodebookTableInit(CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +/** + * \brief decode a channel element. To be called after CChannelElement_Read() + * \param pAacDecoderChannelInfo pointer to channel data struct. Depending on + * el_channels either one or two. + * \param pSamplingRateInfo pointer to sample rate information structure + * \param el_channels amount of channels of the element to be decoded. + * \param output pointer to time domain output buffer (ACELP) + */ +void CChannelElement_Decode( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2], + SamplingRateInfo *pSamplingRateInfo, UINT flags, UINT elFlags, + int el_channels); + +/** + * \brief Read channel element of given type from bitstream. + * \param hBs bitstream handle to access bitstream data. + * \param pAacDecoderChannelInfo pointer array to store channel information. + * \param aot Audio Object Type + * \param pSamplingRateInfo sampling rate info table. + * \param flags common parser guidance flags + * \param elFlags element specific parser guidance flags + * \param numberOfChannels amoun of channels contained in the object to be + * parsed. + * \param epConfig the current epConfig value obtained from the Audio Specific + * Config. + * \param pTp transport decoder handle required for ADTS CRC checking. + * ... + * \return an AAC_DECODER_ERROR error code. + */ +AAC_DECODER_ERROR CChannelElement_Read( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + const AUDIO_OBJECT_TYPE aot, SamplingRateInfo *pSamplingRateInfo, + const UINT flags, const UINT elFlags, const UINT frame_length, + const UCHAR numberOfChannels, const SCHAR epConfig, + HANDLE_TRANSPORTDEC pTpDec); + +#endif /* #ifndef CHANNEL_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channelinfo.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channelinfo.cpp new file mode 100644 index 0000000000000..79add5bf126bf --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channelinfo.cpp @@ -0,0 +1,297 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: individual channel stream info + +*******************************************************************************/ + +#include "channelinfo.h" +#include "aac_rom.h" +#include "aac_ram.h" +#include "FDK_bitstream.h" + +AAC_DECODER_ERROR IcsReadMaxSfb(HANDLE_FDK_BITSTREAM bs, CIcsInfo *pIcsInfo, + const SamplingRateInfo *pSamplingRateInfo) { + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + int nbits; + + if (IsLongBlock(pIcsInfo)) { + nbits = 6; + pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Long; + } else { + nbits = 4; + pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Short; + } + pIcsInfo->MaxSfBands = (UCHAR)FDKreadBits(bs, nbits); + + if (pIcsInfo->MaxSfBands > pIcsInfo->TotalSfBands) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + + return ErrorStatus; +} + +AAC_DECODER_ERROR IcsRead(HANDLE_FDK_BITSTREAM bs, CIcsInfo *pIcsInfo, + const SamplingRateInfo *pSamplingRateInfo, + const UINT flags) { + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + pIcsInfo->Valid = 0; + + if (flags & AC_ELD) { + pIcsInfo->WindowSequence = BLOCK_LONG; + pIcsInfo->WindowShape = 0; + } else { + if (!(flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) { + FDKreadBits(bs, 1); + } + pIcsInfo->WindowSequence = (BLOCK_TYPE)FDKreadBits(bs, 2); + pIcsInfo->WindowShape = (UCHAR)FDKreadBits(bs, 1); + if (flags & AC_LD) { + if (pIcsInfo->WindowShape) { + pIcsInfo->WindowShape = 2; /* select low overlap instead of KBD */ + } + } + } + + /* Sanity check */ + if ((flags & (AC_ELD | AC_LD)) && pIcsInfo->WindowSequence != BLOCK_LONG) { + pIcsInfo->WindowSequence = BLOCK_LONG; + ErrorStatus = AAC_DEC_PARSE_ERROR; + goto bail; + } + + ErrorStatus = IcsReadMaxSfb(bs, pIcsInfo, pSamplingRateInfo); + if (ErrorStatus != AAC_DEC_OK) { + goto bail; + } + + if (IsLongBlock(pIcsInfo)) { + if (!(flags & (AC_ELD | AC_SCALABLE | AC_BSAC | AC_USAC | AC_RSVD50 | + AC_RSV603DA))) /* If not ELD nor Scalable nor BSAC nor USAC + syntax then ... */ + { + if ((UCHAR)FDKreadBits(bs, 1) != 0) /* UCHAR PredictorDataPresent */ + { + ErrorStatus = AAC_DEC_UNSUPPORTED_PREDICTION; + goto bail; + } + } + + pIcsInfo->WindowGroups = 1; + pIcsInfo->WindowGroupLength[0] = 1; + } else { + INT i; + UINT mask; + + pIcsInfo->ScaleFactorGrouping = (UCHAR)FDKreadBits(bs, 7); + + pIcsInfo->WindowGroups = 0; + + for (i = 0; i < (8 - 1); i++) { + mask = 1 << (6 - i); + pIcsInfo->WindowGroupLength[i] = 1; + + if (pIcsInfo->ScaleFactorGrouping & mask) { + pIcsInfo->WindowGroupLength[pIcsInfo->WindowGroups]++; + } else { + pIcsInfo->WindowGroups++; + } + } + + /* loop runs to i < 7 only */ + pIcsInfo->WindowGroupLength[8 - 1] = 1; + pIcsInfo->WindowGroups++; + } + +bail: + if (ErrorStatus == AAC_DEC_OK) pIcsInfo->Valid = 1; + + return ErrorStatus; +} + +/* + interleave codebooks the following way + + 9 (84w) | 1 (51w) + 10 (82w) | 2 (39w) + SCL (65w) | 4 (38w) + 3 (39w) | 5 (41w) + | 6 (40w) + | 7 (31w) + | 8 (31w) + (270w) (271w) +*/ + +/* + Table entries are sorted as following: + | num_swb_long_window | sfbands_long | num_swb_short_window | sfbands_short | +*/ +AAC_DECODER_ERROR getSamplingRateInfo(SamplingRateInfo *t, UINT samplesPerFrame, + UINT samplingRateIndex, + UINT samplingRate) { + int index = 0; + + /* Search closest samplerate according to ISO/IEC 13818-7:2005(E) 8.2.4 (Table + * 38): */ + if ((samplingRateIndex >= 15) || (samplesPerFrame == 768)) { + const UINT borders[] = {(UINT)-1, 92017, 75132, 55426, 46009, 37566, + 27713, 23004, 18783, 13856, 11502, 9391}; + UINT i, samplingRateSearch = samplingRate; + + if (samplesPerFrame == 768) { + samplingRateSearch = (samplingRate * 4) / 3; + } + + for (i = 0; i < 11; i++) { + if (borders[i] > samplingRateSearch && + samplingRateSearch >= borders[i + 1]) { + break; + } + } + samplingRateIndex = i; + } + + t->samplingRateIndex = samplingRateIndex; + t->samplingRate = samplingRate; + + switch (samplesPerFrame) { + case 1024: + index = 0; + break; + case 960: + index = 1; + break; + case 768: + index = 2; + break; + case 512: + index = 3; + break; + case 480: + index = 4; + break; + + default: + return AAC_DEC_UNSUPPORTED_FORMAT; + } + + t->ScaleFactorBands_Long = + sfbOffsetTables[index][samplingRateIndex].sfbOffsetLong; + t->ScaleFactorBands_Short = + sfbOffsetTables[index][samplingRateIndex].sfbOffsetShort; + t->NumberOfScaleFactorBands_Long = + sfbOffsetTables[index][samplingRateIndex].numberOfSfbLong; + t->NumberOfScaleFactorBands_Short = + sfbOffsetTables[index][samplingRateIndex].numberOfSfbShort; + + if (t->ScaleFactorBands_Long == NULL || + t->NumberOfScaleFactorBands_Long == 0) { + t->samplingRate = 0; + return AAC_DEC_UNSUPPORTED_FORMAT; + } + + FDK_ASSERT((UINT)t->ScaleFactorBands_Long[t->NumberOfScaleFactorBands_Long] == + samplesPerFrame); + FDK_ASSERT( + t->ScaleFactorBands_Short == NULL || + (UINT)t->ScaleFactorBands_Short[t->NumberOfScaleFactorBands_Short] * 8 == + samplesPerFrame); + + return AAC_DEC_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channelinfo.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channelinfo.h new file mode 100644 index 0000000000000..4523400d45f96 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/channelinfo.h @@ -0,0 +1,564 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: individual channel stream info + +*******************************************************************************/ + +#ifndef CHANNELINFO_H +#define CHANNELINFO_H + +#include "common_fix.h" + +#include "aac_rom.h" +#include "aacdecoder_lib.h" +#include "FDK_bitstream.h" +#include "overlapadd.h" + +#include "mdct.h" +#include "stereo.h" +#include "pulsedata.h" +#include "aacdec_tns.h" + +#include "aacdec_pns.h" + +#include "aacdec_hcr_types.h" +#include "rvlc_info.h" + +#include "usacdec_acelp.h" +#include "usacdec_const.h" +#include "usacdec_rom.h" + +#include "ac_arith_coder.h" + +#include "conceal_types.h" + +#include "aacdec_drc_types.h" + +#define WB_SECTION_SIZE (1024 * 2) + +#define DRM_BS_BUFFER_SIZE \ + (512) /* size of the dynamic buffer which is used to reverse the bits of \ + the DRM SBR payload */ + +/* Output rendering mode */ +typedef enum { + AACDEC_RENDER_INVALID = 0, + AACDEC_RENDER_IMDCT, + AACDEC_RENDER_ELDFB, + AACDEC_RENDER_LPD, + AACDEC_RENDER_INTIMDCT +} AACDEC_RENDER_MODE; + +enum { MAX_QUANTIZED_VALUE = 8191 }; + +typedef enum { FD_LONG, FD_SHORT, LPD } USAC_COREMODE; + +typedef struct { + const SHORT *ScaleFactorBands_Long; + const SHORT *ScaleFactorBands_Short; + UCHAR NumberOfScaleFactorBands_Long; + UCHAR NumberOfScaleFactorBands_Short; + UINT samplingRateIndex; + UINT samplingRate; +} SamplingRateInfo; + +typedef struct { + UCHAR CommonWindow; + UCHAR GlobalGain; + +} CRawDataInfo; + +typedef struct { + UCHAR WindowGroupLength[8]; + UCHAR WindowGroups; + UCHAR Valid; + + UCHAR WindowShape; /* 0: sine window, 1: KBD, 2: low overlap */ + BLOCK_TYPE WindowSequence; /* mdct.h; 0: long, 1: start, 2: short, 3: stop */ + UCHAR MaxSfBands; + UCHAR max_sfb_ste; + UCHAR ScaleFactorGrouping; + + UCHAR TotalSfBands; + +} CIcsInfo; + +enum { + ZERO_HCB = 0, + ESCBOOK = 11, + NSPECBOOKS = ESCBOOK + 1, + BOOKSCL = NSPECBOOKS, + NOISE_HCB = 13, + INTENSITY_HCB2 = 14, + INTENSITY_HCB = 15, + LAST_HCB +}; + +/* This struct holds the persistent data shared by both channels of a CPE. + It needs to be allocated for each CPE. */ +typedef struct { + CJointStereoPersistentData jointStereoPersistentData; +} CpePersistentData; + +/* + * This struct must be allocated one for every channel and must be persistent. + */ +typedef struct { + FIXP_DBL *pOverlapBuffer; + mdct_t IMdct; + + CArcoData *hArCo; + + INT pnsCurrentSeed; + + /* LPD memory */ + FIXP_DBL old_synth[PIT_MAX_MAX - L_SUBFR]; + INT old_T_pf[SYN_SFD]; + FIXP_DBL old_gain_pf[SYN_SFD]; + FIXP_DBL mem_bpf[L_FILT + L_SUBFR]; + UCHAR + old_bpf_control_info; /* (1: enable, 0: disable) bpf for past superframe + */ + + USAC_COREMODE last_core_mode; /* core mode used by the decoder in previous + frame. (not signalled by the bitstream, see + CAacDecoderChannelInfo::core_mode_last !! ) + */ + UCHAR last_lpd_mode; /* LPD mode used by the decoder in last LPD subframe + (not signalled by the bitstream, see + CAacDecoderChannelInfo::lpd_mode_last !! ) */ + UCHAR last_last_lpd_mode; /* LPD mode used in second last LPD subframe + (not signalled by the bitstream) */ + UCHAR last_lpc_lost; /* Flag indicating that the previous LPC is lost */ + + FIXP_LPC + lpc4_lsf[M_LP_FILTER_ORDER]; /* Last LPC4 coefficients in LSF domain. */ + FIXP_LPC lsf_adaptive_mean[M_LP_FILTER_ORDER]; /* Adaptive mean of LPC + coefficients in LSF domain + for concealment. */ + FIXP_LPC lp_coeff_old[2][M_LP_FILTER_ORDER]; /* Last LPC coefficients in LP + domain. lp_coeff_old[0] is lpc4 (coeffs for + right folding point of last tcx frame), + lp_coeff_old[1] are coeffs for left folding + point of last tcx frame */ + INT lp_coeff_old_exp[2]; + + FIXP_SGL + oldStability; /* LPC coeff stability value from last frame (required for + TCX concealment). */ + UINT numLostLpdFrames; /* Number of consecutive lost subframes. */ + + /* TCX memory */ + FIXP_DBL last_tcx_gain; + INT last_tcx_gain_e; + FIXP_DBL last_alfd_gains[32]; /* Scaled by one bit. */ + SHORT last_tcx_pitch; + UCHAR last_tcx_noise_factor; + + /* ACELP memory */ + CAcelpStaticMem acelp; + + ULONG nfRandomSeed; /* seed value for USAC noise filling random generator */ + + CDrcChannelData drcData; + CConcealmentInfo concealmentInfo; + + CpePersistentData *pCpeStaticData; + +} CAacDecoderStaticChannelInfo; + +/* + * This union must be allocated for every element (up to 2 channels). + */ +typedef struct { + /* Common bit stream data */ + SHORT aScaleFactor[( + 8 * 16)]; /* Spectral scale factors for each sfb in each window. */ + SHORT aSfbScale[(8 * 16)]; /* could be free after ApplyTools() */ + UCHAR + aCodeBook[(8 * 16)]; /* section data: codebook for each window and sfb. */ + UCHAR band_is_noise[(8 * 16)]; + CTnsData TnsData; + CRawDataInfo RawDataInfo; + + shouldBeUnion { + struct { + CPulseData PulseData; + SHORT aNumLineInSec4Hcr[MAX_SFB_HCR]; /* needed once for all channels + except for Drm syntax */ + UCHAR + aCodeBooks4Hcr[MAX_SFB_HCR]; /* needed once for all channels except for + Drm syntax. Same as "aCodeBook" ? */ + SHORT lenOfReorderedSpectralData; + SCHAR lenOfLongestCodeword; + SCHAR numberSection; + SCHAR rvlcCurrentScaleFactorOK; + SCHAR rvlcIntensityUsed; + } aac; + struct { + UCHAR fd_noise_level_and_offset; + UCHAR tns_active; + UCHAR tns_on_lr; + UCHAR tcx_noise_factor[4]; + UCHAR tcx_global_gain[4]; + } usac; + } + specificTo; + +} CAacDecoderDynamicData; + +typedef shouldBeUnion { + UCHAR DrmBsBuffer[DRM_BS_BUFFER_SIZE]; + + /* Common signal data, can be used once the bit stream data from above is not + * used anymore. */ + FIXP_DBL mdctOutTemp[1024]; + + FIXP_DBL synth_buf[(PIT_MAX_MAX + SYN_DELAY + L_FRAME_PLUS)]; + + FIXP_DBL workBuffer[WB_SECTION_SIZE]; +} +CWorkBufferCore1; + +/* Common data referenced by all channels */ +typedef struct { + CAacDecoderDynamicData pAacDecoderDynamicData[2]; + + CPnsInterChannelData pnsInterChannelData; + INT pnsRandomSeed[(8 * 16)]; + + CJointStereoData jointStereoData; /* One for one element */ + + shouldBeUnion { + struct { + CErHcrInfo erHcrInfo; + CErRvlcInfo erRvlcInfo; + SHORT aRvlcScfEsc[RVLC_MAX_SFB]; /* needed once for all channels */ + SHORT aRvlcScfFwd[RVLC_MAX_SFB]; /* needed once for all channels */ + SHORT aRvlcScfBwd[RVLC_MAX_SFB]; /* needed once for all channels */ + } aac; + } + overlay; + +} CAacDecoderCommonData; + +typedef struct { + CWorkBufferCore1 *pWorkBufferCore1; + CCplxPredictionData *cplxPredictionData; +} CAacDecoderCommonStaticData; + +/* + * This struct must be allocated one for every channel of every element and must + * be persistent. Among its members, the following memory areas can be + * overwritten under the given conditions: + * - pSpectralCoefficient The memory pointed to can be overwritten after time + * signal rendering. + * - data can be overwritten after time signal rendering. + * - pDynData memory pointed to can be overwritten after each + * CChannelElement_Decode() call. + * - pComData->overlay memory pointed to can be overwritten after each + * CChannelElement_Decode() call.. + */ +typedef struct { + shouldBeUnion { + struct { + FIXP_DBL fac_data0[LFAC]; + SCHAR fac_data_e[4]; + FIXP_DBL + *fac_data[4]; /* Pointers to unused parts of pSpectralCoefficient */ + + UCHAR core_mode; /* current core mode */ + USAC_COREMODE + core_mode_last; /* previous core mode, signalled in the bitstream + (not done by the decoder, see + CAacDecoderStaticChannelInfo::last_core_mode !!)*/ + UCHAR lpd_mode_last; /* previous LPD mode, signalled in the bitstream + (not done by the decoder, see + CAacDecoderStaticChannelInfo::last_core_mode !!)*/ + UCHAR mod[4]; + UCHAR bpf_control_info; /* (1: enable, 0: disable) bpf for current + superframe */ + + FIXP_LPC lsp_coeff[5][M_LP_FILTER_ORDER]; /* linear prediction + coefficients in LSP domain */ + FIXP_LPC + lp_coeff[5][M_LP_FILTER_ORDER]; /* linear prediction coefficients in + LP domain */ + INT lp_coeff_exp[5]; + FIXP_LPC lsf_adaptive_mean_cand + [M_LP_FILTER_ORDER]; /* concealment: is copied to + CAacDecoderStaticChannelInfo->lsf_adaptive_mean once frame is + assumed to be correct*/ + FIXP_SGL aStability[4]; /* LPC coeff stability values required for ACELP + and TCX (concealment) */ + + CAcelpChannelData acelp[4]; + + FIXP_DBL tcx_gain[4]; + SCHAR tcx_gain_e[4]; + } usac; + + struct { + CPnsData PnsData; /* Not required for USAC */ + } aac; + } + data; + + SPECTRAL_PTR pSpectralCoefficient; /* Spectral coefficients of each window */ + SHORT specScale[8]; /* Scale shift values of each spectrum window */ + CIcsInfo icsInfo; + INT granuleLength; /* Size of smallest spectrum piece */ + UCHAR ElementInstanceTag; + + AACDEC_RENDER_MODE renderMode; /* Output signal rendering mode */ + + CAacDecoderDynamicData * + pDynData; /* Data required for one element and discarded after decoding */ + CAacDecoderCommonData + *pComData; /* Data required for one channel at a time during decode */ + CAacDecoderCommonStaticData *pComStaticData; /* Persistent data required for + one channel at a time during + decode */ + + int currAliasingSymmetry; /* required for RSVD60 MCT */ + +} CAacDecoderChannelInfo; + +/* channelinfo.cpp */ + +AAC_DECODER_ERROR getSamplingRateInfo(SamplingRateInfo *t, UINT samplesPerFrame, + UINT samplingRateIndex, + UINT samplingRate); + +/** + * \brief Read max SFB from bit stream and assign TotalSfBands according + * to the window sequence and sample rate. + * \param hBs bit stream handle as data source + * \param pIcsInfo IcsInfo structure to read the window sequence and store + * MaxSfBands and TotalSfBands + * \param pSamplingRateInfo read only + */ +AAC_DECODER_ERROR IcsReadMaxSfb(HANDLE_FDK_BITSTREAM hBs, CIcsInfo *pIcsInfo, + const SamplingRateInfo *pSamplingRateInfo); + +AAC_DECODER_ERROR IcsRead(HANDLE_FDK_BITSTREAM bs, CIcsInfo *pIcsInfo, + const SamplingRateInfo *SamplingRateInfoTable, + const UINT flags); + +/* stereo.cpp, only called from this file */ + +/*! + \brief Applies MS stereo. + + The function applies MS stereo. + + \param pAacDecoderChannelInfo aac channel info. + \param pScaleFactorBandOffsets pointer to scalefactor band offsets. + \param pWindowGroupLength pointer to window group length array. + \param windowGroups number of window groups. + \param scaleFactorBandsTransmittedL number of transmitted scalefactor bands in + left channel. \param scaleFactorBandsTransmittedR number of transmitted + scalefactor bands in right channel. May differ from + scaleFactorBandsTransmittedL only for USAC. \return none +*/ +void CJointStereo_ApplyMS( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2], + FIXP_DBL *spectrumL, FIXP_DBL *spectrumR, SHORT *SFBleftScale, + SHORT *SFBrightScale, SHORT *specScaleL, SHORT *specScaleR, + const SHORT *pScaleFactorBandOffsets, const UCHAR *pWindowGroupLength, + const int windowGroups, const int max_sfb_ste_outside, + const int scaleFactorBandsTransmittedL, + const int scaleFactorBandsTransmittedR, FIXP_DBL *store_dmx_re_prev, + SHORT *store_dmx_re_prev_e, const int mainband_flag); + +/*! + \brief Applies intensity stereo + + The function applies intensity stereo. + + \param pAacDecoderChannelInfo aac channel info. + \param pScaleFactorBandOffsets pointer to scalefactor band offsets. + \param pWindowGroupLength pointer to window group length array. + \param windowGroups number of window groups. + \param scaleFactorBandsTransmitted number of transmitted scalefactor bands. + \return none +*/ +void CJointStereo_ApplyIS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + const short *pScaleFactorBandOffsets, + const UCHAR *pWindowGroupLength, + const int windowGroups, + const int scaleFactorBandsTransmitted); + +/* aacdec_pns.cpp */ +int CPns_IsPnsUsed(const CPnsData *pPnsData, const int group, const int band); + +void CPns_SetCorrelation(CPnsData *pPnsData, const int group, const int band, + const int outofphase); + +/****************** inline functions ******************/ + +inline UCHAR IsValid(const CIcsInfo *pIcsInfo) { return pIcsInfo->Valid; } + +inline UCHAR IsLongBlock(const CIcsInfo *pIcsInfo) { + return (pIcsInfo->WindowSequence != BLOCK_SHORT); +} + +inline UCHAR GetWindowShape(const CIcsInfo *pIcsInfo) { + return pIcsInfo->WindowShape; +} + +inline BLOCK_TYPE GetWindowSequence(const CIcsInfo *pIcsInfo) { + return pIcsInfo->WindowSequence; +} + +inline const SHORT *GetScaleFactorBandOffsets( + const CIcsInfo *pIcsInfo, const SamplingRateInfo *samplingRateInfo) { + if (IsLongBlock(pIcsInfo)) { + return samplingRateInfo->ScaleFactorBands_Long; + } else { + return samplingRateInfo->ScaleFactorBands_Short; + } +} + +inline UCHAR GetNumberOfScaleFactorBands( + const CIcsInfo *pIcsInfo, const SamplingRateInfo *samplingRateInfo) { + if (IsLongBlock(pIcsInfo)) { + return samplingRateInfo->NumberOfScaleFactorBands_Long; + } else { + return samplingRateInfo->NumberOfScaleFactorBands_Short; + } +} + +inline int GetWindowsPerFrame(const CIcsInfo *pIcsInfo) { + return (pIcsInfo->WindowSequence == BLOCK_SHORT) ? 8 : 1; +} + +inline UCHAR GetWindowGroups(const CIcsInfo *pIcsInfo) { + return pIcsInfo->WindowGroups; +} + +inline UCHAR GetWindowGroupLength(const CIcsInfo *pIcsInfo, const INT index) { + return pIcsInfo->WindowGroupLength[index]; +} + +inline const UCHAR *GetWindowGroupLengthTable(const CIcsInfo *pIcsInfo) { + return pIcsInfo->WindowGroupLength; +} + +inline UCHAR GetScaleFactorBandsTransmitted(const CIcsInfo *pIcsInfo) { + return pIcsInfo->MaxSfBands; +} + +inline UCHAR GetScaleMaxFactorBandsTransmitted(const CIcsInfo *pIcsInfo0, + const CIcsInfo *pIcsInfo1) { + return fMax(pIcsInfo0->MaxSfBands, pIcsInfo1->MaxSfBands); +} + +inline UCHAR GetScaleFactorBandsTotal(const CIcsInfo *pIcsInfo) { + return pIcsInfo->TotalSfBands; +} + +/* Note: This function applies to AAC-LC only ! */ +inline UCHAR GetMaximumTnsBands(const CIcsInfo *pIcsInfo, + const int samplingRateIndex) { + return tns_max_bands_tbl[samplingRateIndex][!IsLongBlock(pIcsInfo)]; +} + +#endif /* #ifndef CHANNELINFO_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/conceal.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/conceal.cpp new file mode 100644 index 0000000000000..0939bb5dcd3ff --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/conceal.cpp @@ -0,0 +1,2096 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: independent channel concealment + +*******************************************************************************/ + +/*! + \page concealment AAC core concealment + + This AAC core implementation includes a concealment function, which can be + enabled using the several defines during compilation. + + There are various tests inside the core, starting with simple CRC tests and + ending in a variety of plausibility checks. If such a check indicates an + invalid bitstream, then concealment is applied. + + Concealment is also applied when the calling main program indicates a + distorted or missing data frame using the frameOK flag. This is used for error + detection on the transport layer. (See below) + + There are three concealment-modes: + + 1) Muting: The spectral data is simply set to zero in case of an detected + error. + + 2) Noise substitution: In case of an detected error, concealment copies the + last frame and adds attenuates the spectral data. For this mode you have to + set the #CONCEAL_NOISE define. Noise substitution adds no additional delay. + + 3) Interpolation: The interpolation routine swaps the spectral data from the + previous and the current frame just before the final frequency to time + conversion. In case a single frame is corrupted, concealmant interpolates + between the last good and the first good frame to create the spectral data for + the missing frame. If multiple frames are corrupted, concealment implements + first a fade out based on slightly modified spectral values from the last good + frame. As soon as good frames are available, concealmant fades in the new + spectral data. For this mode you have to set the #CONCEAL_INTER define. Note + that in this case, you also need to set #SBR_BS_DELAY_ENABLE, which basically + adds approriate delay in the SBR decoder. Note that the + Interpolating-Concealment increases the delay of your decoder by one frame and + that it does require additional resources such as memory and computational + complexity. + +

How concealment can be used with errors on the transport layer

+ + Many errors can or have to be detected on the transport layer. For example in + IP based systems packet loss can occur. The transport protocol used should + indicate such packet loss by inserting an empty frame with frameOK=0. +*/ + +#include "conceal.h" + +#include "aac_rom.h" +#include "genericStds.h" + +/* PNS (of block) */ +#include "aacdec_pns.h" +#include "block.h" + +#define CONCEAL_DFLT_COMF_NOISE_LEVEL (0x100000) + +#define CONCEAL_NOT_DEFINED ((UCHAR)-1) + +/* default settings */ +#define CONCEAL_DFLT_FADEOUT_FRAMES (6) +#define CONCEAL_DFLT_FADEIN_FRAMES (5) +#define CONCEAL_DFLT_MUTE_RELEASE_FRAMES (0) + +#define CONCEAL_DFLT_FADE_FACTOR (0.707106781186548f) /* 1/sqrt(2) */ + +/* some often used constants: */ +#define FIXP_ZERO FL2FXCONST_DBL(0.0f) +#define FIXP_ONE FL2FXCONST_DBL(1.0f) +#define FIXP_FL_CORRECTION FL2FXCONST_DBL(0.53333333333333333f) + +/* For parameter conversion */ +#define CONCEAL_PARAMETER_BITS (8) +#define CONCEAL_MAX_QUANT_FACTOR ((1 << CONCEAL_PARAMETER_BITS) - 1) +/*#define CONCEAL_MIN_ATTENUATION_FACTOR_025 ( FL2FXCONST_DBL(0.971627951577106174) )*/ /* -0.25 dB */ +#define CONCEAL_MIN_ATTENUATION_FACTOR_025_LD \ + FL2FXCONST_DBL(-0.041524101186092029596853445212299) +/*#define CONCEAL_MIN_ATTENUATION_FACTOR_050 ( FL2FXCONST_DBL(0.944060876285923380) )*/ /* -0.50 dB */ +#define CONCEAL_MIN_ATTENUATION_FACTOR_050_LD \ + FL2FXCONST_DBL(-0.083048202372184059253597008145293) + +typedef enum { + CConcealment_NoExpand, + CConcealment_Expand, + CConcealment_Compress +} CConcealmentExpandType; + +static const FIXP_SGL facMod4Table[4] = { + FL2FXCONST_SGL(0.500000000f), /* FIXP_SGL(0x4000), 2^-(1-0,00) */ + FL2FXCONST_SGL(0.594603558f), /* FIXP_SGL(0x4c1b), 2^-(1-0,25) */ + FL2FXCONST_SGL(0.707106781f), /* FIXP_SGL(0x5a82), 2^-(1-0,50) */ + FL2FXCONST_SGL(0.840896415f) /* FIXP_SGL(0x6ba2) 2^-(1-0,75) */ +}; + +static void CConcealment_CalcBandEnergy( + FIXP_DBL *spectrum, const SamplingRateInfo *pSamplingRateInfo, + const int blockType, CConcealmentExpandType ex, int *sfbEnergy); + +static void CConcealment_InterpolateBuffer(FIXP_DBL *spectrum, + SHORT *pSpecScalePrev, + SHORT *pSpecScaleAct, + SHORT *pSpecScaleOut, int *enPrv, + int *enAct, int sfbCnt, + const SHORT *pSfbOffset); + +static int CConcealment_ApplyInter( + CConcealmentInfo *pConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const int improveTonal, const int frameOk, const int mute_release_active); + +static int CConcealment_ApplyNoise( + CConcealmentInfo *pConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const UINT flags); + +static void CConcealment_UpdateState( + CConcealmentInfo *pConcealmentInfo, int frameOk, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +static void CConcealment_ApplyRandomSign(int iRandomPhase, FIXP_DBL *spec, + int samplesPerFrame); + +/* TimeDomainFading */ +static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart, + FIXP_DBL fadeStop, PCM_DEC *pcmdata); +static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations, + int *fadingSteps, + FIXP_DBL fadeStop, + FIXP_DBL fadeStart, + TDfadingType fadingType); +static void CConcealment_TDFading_doLinearFadingSteps(int *fadingSteps); + +/* Streamline the state machine */ +static int CConcealment_ApplyFadeOut( + int mode, CConcealmentInfo *pConcealmentInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +static int CConcealment_TDNoise_Random(ULONG *seed); +static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo, + const int len, + const INT aacOutDataHeadroom, + PCM_DEC *const pcmdata); + +static BLOCK_TYPE CConcealment_GetWinSeq(int prevWinSeq) { + BLOCK_TYPE newWinSeq = BLOCK_LONG; + + /* Try to have only long blocks */ + if (prevWinSeq == BLOCK_START || prevWinSeq == BLOCK_SHORT) { + newWinSeq = BLOCK_STOP; + } + + return (newWinSeq); +} + +/*! + \brief Init common concealment information data + + \param pConcealCommonData Pointer to the concealment common data structure. +*/ +void CConcealment_InitCommonData(CConcealParams *pConcealCommonData) { + if (pConcealCommonData != NULL) { + int i; + + /* Set default error concealment technique */ + pConcealCommonData->method = ConcealMethodInter; + + pConcealCommonData->numFadeOutFrames = CONCEAL_DFLT_FADEOUT_FRAMES; + pConcealCommonData->numFadeInFrames = CONCEAL_DFLT_FADEIN_FRAMES; + pConcealCommonData->numMuteReleaseFrames = CONCEAL_DFLT_MUTE_RELEASE_FRAMES; + + pConcealCommonData->comfortNoiseLevel = + (FIXP_DBL)CONCEAL_DFLT_COMF_NOISE_LEVEL; + + /* Init fade factors (symetric) */ + pConcealCommonData->fadeOutFactor[0] = + FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR); + pConcealCommonData->fadeInFactor[0] = pConcealCommonData->fadeOutFactor[0]; + + for (i = 1; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + pConcealCommonData->fadeOutFactor[i] = + FX_DBL2FX_SGL(fMult(pConcealCommonData->fadeOutFactor[i - 1], + FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR))); + pConcealCommonData->fadeInFactor[i] = + pConcealCommonData->fadeOutFactor[i]; + } + } +} + +/*! + \brief Get current concealment method. + + \param pConcealCommonData Pointer to common concealment data (for all + channels) +*/ +CConcealmentMethod CConcealment_GetMethod(CConcealParams *pConcealCommonData) { + CConcealmentMethod method = ConcealMethodNone; + + if (pConcealCommonData != NULL) { + method = pConcealCommonData->method; + } + + return (method); +} + +/*! + \brief Init concealment information for each channel + + \param pConcealChannelInfo Pointer to the channel related concealment info + structure to be initialized. \param pConcealCommonData Pointer to common + concealment data (for all channels) \param initRenderMode Initial render + mode to be set for the current channel. \param samplesPerFrame The number + of samples per frame. +*/ +void CConcealment_InitChannelData(CConcealmentInfo *pConcealChannelInfo, + CConcealParams *pConcealCommonData, + AACDEC_RENDER_MODE initRenderMode, + int samplesPerFrame) { + int i; + pConcealChannelInfo->TDNoiseSeed = 0; + FDKmemclear(pConcealChannelInfo->TDNoiseStates, + sizeof(pConcealChannelInfo->TDNoiseStates)); + pConcealChannelInfo->TDNoiseCoef[0] = FL2FXCONST_SGL(0.05f); + pConcealChannelInfo->TDNoiseCoef[1] = FL2FXCONST_SGL(0.5f); + pConcealChannelInfo->TDNoiseCoef[2] = FL2FXCONST_SGL(0.45f); + + pConcealChannelInfo->pConcealParams = pConcealCommonData; + + pConcealChannelInfo->lastRenderMode = initRenderMode; + + pConcealChannelInfo->windowShape = CONCEAL_NOT_DEFINED; + pConcealChannelInfo->windowSequence = BLOCK_LONG; /* default type */ + pConcealChannelInfo->lastWinGrpLen = 1; + + pConcealChannelInfo->concealState = ConcealState_Ok; + + FDKmemclear(pConcealChannelInfo->spectralCoefficient, + 1024 * sizeof(FIXP_CNCL)); + + for (i = 0; i < 8; i++) { + pConcealChannelInfo->specScale[i] = 0; + } + + pConcealChannelInfo->iRandomPhase = 0; + + pConcealChannelInfo->prevFrameOk[0] = 1; + pConcealChannelInfo->prevFrameOk[1] = 1; + + pConcealChannelInfo->cntFadeFrames = 0; + pConcealChannelInfo->cntValidFrames = 0; + pConcealChannelInfo->fade_old = (FIXP_DBL)MAXVAL_DBL; + pConcealChannelInfo->winGrpOffset[0] = 0; + pConcealChannelInfo->winGrpOffset[1] = 0; + pConcealChannelInfo->attGrpOffset[0] = 0; + pConcealChannelInfo->attGrpOffset[1] = 0; +} + +/*! + \brief Set error concealment parameters + + \param concealParams + \param method + \param fadeOutSlope + \param fadeInSlope + \param muteRelease + \param comfNoiseLevel +*/ +AAC_DECODER_ERROR +CConcealment_SetParams(CConcealParams *concealParams, int method, + int fadeOutSlope, int fadeInSlope, int muteRelease, + FIXP_DBL comfNoiseLevel) { + /* set concealment technique */ + if (method != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + switch ((CConcealmentMethod)method) { + case ConcealMethodMute: + case ConcealMethodNoise: + case ConcealMethodInter: + /* Be sure to enable delay adjustment of SBR decoder! */ + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->method = (CConcealmentMethod)method; + } + break; + + default: + return AAC_DEC_SET_PARAM_FAIL; + } + } + + /* set number of frames for fade-out slope */ + if (fadeOutSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ((fadeOutSlope < CONCEAL_MAX_NUM_FADE_FACTORS) && (fadeOutSlope >= 0)) { + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->numFadeOutFrames = fadeOutSlope; + } + } else { + return AAC_DEC_SET_PARAM_FAIL; + } + } + + /* set number of frames for fade-in slope */ + if (fadeInSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ((fadeInSlope < CONCEAL_MAX_NUM_FADE_FACTORS) && (fadeInSlope >= 0)) { + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->numFadeInFrames = fadeInSlope; + } + } else { + return AAC_DEC_SET_PARAM_FAIL; + } + } + + /* set number of error-free frames after which the muting will be released */ + if (muteRelease != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ((muteRelease < (CONCEAL_MAX_NUM_FADE_FACTORS << 1)) && + (muteRelease >= 0)) { + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->numMuteReleaseFrames = muteRelease; + } + } else { + return AAC_DEC_SET_PARAM_FAIL; + } + } + + /* set confort noise level which will be inserted while in state 'muting' */ + if (comfNoiseLevel != (FIXP_DBL)AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ((comfNoiseLevel < (FIXP_DBL)0) || + (comfNoiseLevel > (FIXP_DBL)MAXVAL_DBL)) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + concealParams->comfortNoiseLevel = (FIXP_DBL)comfNoiseLevel; + } + } + + return (AAC_DEC_OK); +} + +/*! + \brief Set fade-out/in attenuation factor vectors + + \param concealParams + \param fadeOutAttenuationVector + \param fadeInAttenuationVector + + \return 0 if OK all other values indicate errors +*/ +AAC_DECODER_ERROR +CConcealment_SetAttenuation(CConcealParams *concealParams, + const SHORT *fadeOutAttenuationVector, + const SHORT *fadeInAttenuationVector) { + if ((fadeOutAttenuationVector == NULL) && (fadeInAttenuationVector == NULL)) { + return AAC_DEC_SET_PARAM_FAIL; + } + + /* Fade-out factors */ + if (fadeOutAttenuationVector != NULL) { + int i; + + /* check quantized factors first */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + if ((fadeOutAttenuationVector[i] < 0) || + (fadeOutAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) { + return AAC_DEC_SET_PARAM_FAIL; + } + } + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + + /* now dequantize factors */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + concealParams->fadeOutFactor[i] = + FX_DBL2FX_SGL(fLdPow(CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, 0, + (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0 / 2.0) >> + (CONCEAL_PARAMETER_BITS - 1)) * + (INT)fadeOutAttenuationVector[i]), + CONCEAL_PARAMETER_BITS)); + } + } + + /* Fade-in factors */ + if (fadeInAttenuationVector != NULL) { + int i; + + /* check quantized factors first */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + if ((fadeInAttenuationVector[i] < 0) || + (fadeInAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) { + return AAC_DEC_SET_PARAM_FAIL; + } + } + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + + /* now dequantize factors */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + concealParams->fadeInFactor[i] = FX_DBL2FX_SGL( + fLdPow(CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, 0, + (FIXP_DBL)((INT)(FIXP_ONE >> CONCEAL_PARAMETER_BITS) * + (INT)fadeInAttenuationVector[i]), + CONCEAL_PARAMETER_BITS)); + } + } + + return (AAC_DEC_OK); +} + +/*! + \brief Get state of concealment module. + + \param pConcealChannelInfo + + \return Concealment state. +*/ +CConcealmentState CConcealment_GetState(CConcealmentInfo *pConcealChannelInfo) { + CConcealmentState state = ConcealState_Ok; + + if (pConcealChannelInfo != NULL) { + state = pConcealChannelInfo->concealState; + } + + return (state); +} + +/*! + \brief Store data for concealment techniques applied later + + Interface function to store data for different concealment strategies + */ +void CConcealment_Store( + CConcealmentInfo *hConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) { + UCHAR nbDiv = NB_DIV; + + if (!(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD && + pAacDecoderChannelInfo->data.usac.mod[nbDiv - 1] == 0)) + + { + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + + SHORT tSpecScale[8]; + UCHAR tWindowShape; + BLOCK_TYPE tWindowSequence; + + /* store old window infos for swapping */ + tWindowSequence = hConcealmentInfo->windowSequence; + tWindowShape = hConcealmentInfo->windowShape; + + /* store old scale factors for swapping */ + FDKmemcpy(tSpecScale, hConcealmentInfo->specScale, 8 * sizeof(SHORT)); + + /* store new window infos */ + hConcealmentInfo->windowSequence = GetWindowSequence(pIcsInfo); + hConcealmentInfo->windowShape = GetWindowShape(pIcsInfo); + hConcealmentInfo->lastWinGrpLen = + *(GetWindowGroupLengthTable(pIcsInfo) + GetWindowGroups(pIcsInfo) - 1); + + /* store new scale factors */ + FDKmemcpy(hConcealmentInfo->specScale, pSpecScale, 8 * sizeof(SHORT)); + + if (hConcealmentInfo->pConcealParams->method < ConcealMethodInter) { + /* store new spectral bins */ +#if (CNCL_FRACT_BITS == DFRACT_BITS) + FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpectralCoefficient, + 1024 * sizeof(FIXP_CNCL)); +#else + FIXP_CNCL *RESTRICT pCncl = + &hConcealmentInfo->spectralCoefficient[1024 - 1]; + FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1]; + int i; + for (i = 1024; i != 0; i--) { + *pCncl-- = FX_DBL2FX_CNCL(*pSpec--); + } +#endif + } else { + /* swap spectral data */ +#if (FIXP_CNCL == FIXP_DBL) + C_ALLOC_SCRATCH_START(pSpecTmp, FIXP_DBL, 1024); + FDKmemcpy(pSpecTmp, pSpectralCoefficient, 1024 * sizeof(FIXP_DBL)); + FDKmemcpy(pSpectralCoefficient, hConcealmentInfo->spectralCoefficient, + 1024 * sizeof(FIXP_DBL)); + FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpecTmp, + 1024 * sizeof(FIXP_DBL)); + C_ALLOC_SCRATCH_END(pSpecTmp, FIXP_DBL, 1024); +#else + FIXP_CNCL *RESTRICT pCncl = + &hConcealmentInfo->spectralCoefficient[1024 - 1]; + FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1]; + FIXP_DBL tSpec; + + for (int i = 1024; i != 0; i--) { + tSpec = *pSpec; + *pSpec-- = FX_CNCL2FX_DBL(*pCncl); + *pCncl-- = FX_DBL2FX_CNCL(tSpec); + } +#endif + + /* complete swapping of window infos */ + pIcsInfo->WindowSequence = tWindowSequence; + pIcsInfo->WindowShape = tWindowShape; + + /* complete swapping of scale factors */ + FDKmemcpy(pSpecScale, tSpecScale, 8 * sizeof(SHORT)); + } + } + + if (pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD) { + /* Store LSF4 */ + FDKmemcpy(hConcealmentInfo->lsf4, pAacDecoderStaticChannelInfo->lpc4_lsf, + sizeof(hConcealmentInfo->lsf4)); + /* Store TCX gain */ + hConcealmentInfo->last_tcx_gain = + pAacDecoderStaticChannelInfo->last_tcx_gain; + hConcealmentInfo->last_tcx_gain_e = + pAacDecoderStaticChannelInfo->last_tcx_gain_e; + } +} + +/*! + \brief Apply concealment + + Interface function to different concealment strategies + */ +int CConcealment_Apply( + CConcealmentInfo *hConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const UCHAR lastLpdMode, const int frameOk, const UINT flags) { + int appliedProcessing = 0; + const int mute_release_active = + frameOk && (hConcealmentInfo->concealState >= ConcealState_Mute) && + (hConcealmentInfo->cntValidFrames + 1 <= + hConcealmentInfo->pConcealParams->numMuteReleaseFrames); + + if (hConcealmentInfo->windowShape == CONCEAL_NOT_DEFINED) { + /* Initialize window_shape with same value as in the current (parsed) frame. + Because section 4.6.11.3.2 (Windowing and block switching) of ISO/IEC + 14496-3:2009 says: For the first raw_data_block() to be decoded the + window_shape of the left and right half of the window are identical. */ + hConcealmentInfo->windowShape = pAacDecoderChannelInfo->icsInfo.WindowShape; + } + + if (frameOk && !mute_release_active) { + /* Update render mode if frameOk except for ongoing mute release state. */ + hConcealmentInfo->lastRenderMode = + (SCHAR)pAacDecoderChannelInfo->renderMode; + + /* Rescue current data for concealment in future frames */ + CConcealment_Store(hConcealmentInfo, pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo); + /* Reset index to random sign vector to make sign calculation frame agnostic + (only depends on number of subsequently concealed spectral blocks) */ + hConcealmentInfo->iRandomPhase = 0; + } else { + if (hConcealmentInfo->lastRenderMode == AACDEC_RENDER_INVALID) { + hConcealmentInfo->lastRenderMode = AACDEC_RENDER_IMDCT; + } + pAacDecoderChannelInfo->renderMode = + (AACDEC_RENDER_MODE)hConcealmentInfo->lastRenderMode; + } + + /* hand current frame status to the state machine */ + CConcealment_UpdateState(hConcealmentInfo, frameOk, + pAacDecoderStaticChannelInfo, samplesPerFrame, + pAacDecoderChannelInfo); + + { + if (!frameOk && pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_IMDCT) { + /* LPC extrapolation */ + CLpc_Conceal(pAacDecoderChannelInfo->data.usac.lsp_coeff, + pAacDecoderStaticChannelInfo->lpc4_lsf, + pAacDecoderStaticChannelInfo->lsf_adaptive_mean, + hConcealmentInfo->lastRenderMode == AACDEC_RENDER_IMDCT); + FDKmemcpy(hConcealmentInfo->lsf4, pAacDecoderStaticChannelInfo->lpc4_lsf, + sizeof(pAacDecoderStaticChannelInfo->lpc4_lsf)); + } + + /* Create data for signal rendering according to the selected concealment + * method and decoder operating mode. */ + + if ((!frameOk || mute_release_active) && + (pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD)) { + /* Restore old LSF4 */ + FDKmemcpy(pAacDecoderStaticChannelInfo->lpc4_lsf, hConcealmentInfo->lsf4, + sizeof(pAacDecoderStaticChannelInfo->lpc4_lsf)); + /* Restore old TCX gain */ + pAacDecoderStaticChannelInfo->last_tcx_gain = + hConcealmentInfo->last_tcx_gain; + pAacDecoderStaticChannelInfo->last_tcx_gain_e = + hConcealmentInfo->last_tcx_gain_e; + } + + if (!(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD && + pAacDecoderStaticChannelInfo->last_lpd_mode == 0)) { + switch (hConcealmentInfo->pConcealParams->method) { + default: + case ConcealMethodMute: + if (!frameOk) { + /* Mute spectral data in case of errors */ + FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, + samplesPerFrame * sizeof(FIXP_DBL)); + /* Set last window shape */ + pAacDecoderChannelInfo->icsInfo.WindowShape = + hConcealmentInfo->windowShape; + appliedProcessing = 1; + } + break; + + case ConcealMethodNoise: + /* Noise substitution error concealment technique */ + appliedProcessing = CConcealment_ApplyNoise( + hConcealmentInfo, pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo, pSamplingRateInfo, samplesPerFrame, + flags); + break; + + case ConcealMethodInter: + /* Energy interpolation concealment based on 3GPP */ + appliedProcessing = CConcealment_ApplyInter( + hConcealmentInfo, pAacDecoderChannelInfo, pSamplingRateInfo, + samplesPerFrame, 0, /* don't use tonal improvement */ + frameOk, mute_release_active); + break; + } + } else if (!frameOk || mute_release_active) { + /* simply restore the buffer */ + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; +#if (CNCL_FRACT_BITS != DFRACT_BITS) + FIXP_CNCL *RESTRICT pCncl = + &hConcealmentInfo->spectralCoefficient[1024 - 1]; + FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1]; + int i; +#endif + + /* restore window infos (gri) do we need that? */ + pIcsInfo->WindowSequence = hConcealmentInfo->windowSequence; + pIcsInfo->WindowShape = hConcealmentInfo->windowShape; + + if (hConcealmentInfo->concealState != ConcealState_Mute) { + /* restore scale factors */ + FDKmemcpy(pSpecScale, hConcealmentInfo->specScale, 8 * sizeof(SHORT)); + + /* restore spectral bins */ +#if (CNCL_FRACT_BITS == DFRACT_BITS) + FDKmemcpy(pSpectralCoefficient, hConcealmentInfo->spectralCoefficient, + 1024 * sizeof(FIXP_DBL)); +#else + for (i = 1024; i != 0; i--) { + *pSpec-- = FX_CNCL2FX_DBL(*pCncl--); + } +#endif + } else { + /* clear scale factors */ + FDKmemclear(pSpecScale, 8 * sizeof(SHORT)); + + /* clear buffer */ + FDKmemclear(pSpectralCoefficient, 1024 * sizeof(FIXP_CNCL)); + } + } + } + /* update history */ + hConcealmentInfo->prevFrameOk[0] = hConcealmentInfo->prevFrameOk[1]; + hConcealmentInfo->prevFrameOk[1] = frameOk; + + return mute_release_active ? -1 : appliedProcessing; +} + +/*! +\brief Apply concealment noise substitution + + In case of frame lost this function produces a noisy frame with respect to the + energies values of past frame. + */ +static int CConcealment_ApplyNoise( + CConcealmentInfo *pConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const UINT flags) { + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + + int appliedProcessing = 0; + + FDK_ASSERT(pConcealmentInfo != NULL); + FDK_ASSERT((samplesPerFrame >= 120) && (samplesPerFrame <= 1024)); + + switch (pConcealmentInfo->concealState) { + case ConcealState_Ok: + /* Nothing to do here! */ + break; + + case ConcealState_Single: + case ConcealState_FadeOut: + appliedProcessing = CConcealment_ApplyFadeOut( + /*mode =*/1, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + break; + + case ConcealState_Mute: { + /* set dummy window parameters */ + pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */ + pIcsInfo->WindowShape = + pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape + (required for F/T transform) */ + pIcsInfo->WindowSequence = + CConcealment_GetWinSeq(pConcealmentInfo->windowSequence); + pConcealmentInfo->windowSequence = + pIcsInfo->WindowSequence; /* Store for next frame + (spectrum in concealment + buffer can't be used at + all) */ + + /* mute spectral data */ + FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL)); + FDKmemclear(pConcealmentInfo->spectralCoefficient, + samplesPerFrame * sizeof(FIXP_DBL)); + + appliedProcessing = 1; + } break; + + case ConcealState_FadeIn: { + /* TimeDomainFading: */ + /* Attenuation of signal is done in CConcealment_TDFading() */ + + appliedProcessing = 1; + } break; + + default: + /* we shouldn't come here anyway */ + FDK_ASSERT(0); + break; + } + + return appliedProcessing; +} + +/*! + \brief Apply concealment interpolation + + The function swaps the data from the current and the previous frame. If an + error has occured, frame interpolation is performed to restore the missing + frame. In case of multiple faulty frames, fade-in and fade-out is applied. +*/ +static int CConcealment_ApplyInter( + CConcealmentInfo *pConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const int improveTonal, const int frameOk, const int mute_release_active) { +#if defined(FDK_ASSERT_ENABLE) + CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams; +#endif + + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + + int sfbEnergyPrev[64]; + int sfbEnergyAct[64]; + + int i, appliedProcessing = 0; + + /* clear/init */ + FDKmemclear(sfbEnergyPrev, 64 * sizeof(int)); + FDKmemclear(sfbEnergyAct, 64 * sizeof(int)); + + if (!frameOk || mute_release_active) { + /* Restore last frame from concealment buffer */ + pIcsInfo->WindowShape = pConcealmentInfo->windowShape; + pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence; + + /* Restore spectral data */ + for (i = 0; i < samplesPerFrame; i++) { + pSpectralCoefficient[i] = + FX_CNCL2FX_DBL(pConcealmentInfo->spectralCoefficient[i]); + } + + /* Restore scale factors */ + FDKmemcpy(pSpecScale, pConcealmentInfo->specScale, 8 * sizeof(SHORT)); + } + + /* if previous frame was not ok */ + if (!pConcealmentInfo->prevFrameOk[1] || mute_release_active) { + /* if current frame (f_n) is ok and the last but one frame (f_(n-2)) + was ok, too, then interpolate both frames in order to generate + the current output frame (f_(n-1)). Otherwise, use the last stored + frame (f_(n-2) or f_(n-3) or ...). */ + if (frameOk && pConcealmentInfo->prevFrameOk[0] && !mute_release_active) { + appliedProcessing = 1; + + /* Interpolate both frames in order to generate the current output frame + * (f_(n-1)). */ + if (pIcsInfo->WindowSequence == BLOCK_SHORT) { + /* f_(n-2) == BLOCK_SHORT */ + /* short--??????--short, short--??????--long interpolation */ + /* short--short---short, short---long---long interpolation */ + + int wnd; + + if (pConcealmentInfo->windowSequence == + BLOCK_SHORT) { /* f_n == BLOCK_SHORT */ + /* short--short---short interpolation */ + + int scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Short; + const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + pIcsInfo->WindowShape = (samplesPerFrame <= 512) ? 2 : 1; + pIcsInfo->WindowSequence = BLOCK_SHORT; + + for (wnd = 0; wnd < 8; wnd++) { + CConcealment_CalcBandEnergy( + &pSpectralCoefficient[wnd * + (samplesPerFrame / 8)], /* spec_(n-2) */ + pSamplingRateInfo, BLOCK_SHORT, CConcealment_NoExpand, + sfbEnergyPrev); + + CConcealment_CalcBandEnergy( + &pConcealmentInfo->spectralCoefficient[wnd * (samplesPerFrame / + 8)], /* spec_n */ + pSamplingRateInfo, BLOCK_SHORT, CConcealment_NoExpand, + sfbEnergyAct); + + CConcealment_InterpolateBuffer( + &pSpectralCoefficient[wnd * + (samplesPerFrame / 8)], /* spec_(n-1) */ + &pSpecScale[wnd], &pConcealmentInfo->specScale[wnd], + &pSpecScale[wnd], sfbEnergyPrev, sfbEnergyAct, + scaleFactorBandsTotal, pSfbOffset); + } + } else { /* f_n != BLOCK_SHORT */ + /* short---long---long interpolation */ + + int scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Long; + const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + SHORT specScaleOut; + + CConcealment_CalcBandEnergy( + &pSpectralCoefficient[samplesPerFrame - + (samplesPerFrame / + 8)], /* [wnd] spec_(n-2) */ + pSamplingRateInfo, BLOCK_SHORT, CConcealment_Expand, + sfbEnergyAct); + + CConcealment_CalcBandEnergy( + pConcealmentInfo->spectralCoefficient, /* spec_n */ + pSamplingRateInfo, BLOCK_LONG, CConcealment_NoExpand, + sfbEnergyPrev); + + pIcsInfo->WindowShape = 0; + pIcsInfo->WindowSequence = BLOCK_STOP; + + for (i = 0; i < samplesPerFrame; i++) { + pSpectralCoefficient[i] = + pConcealmentInfo->spectralCoefficient[i]; /* spec_n */ + } + + for (i = 0; i < 8; i++) { /* search for max(specScale) */ + if (pSpecScale[i] > pSpecScale[0]) { + pSpecScale[0] = pSpecScale[i]; + } + } + + CConcealment_InterpolateBuffer( + pSpectralCoefficient, /* spec_(n-1) */ + &pConcealmentInfo->specScale[0], &pSpecScale[0], &specScaleOut, + sfbEnergyPrev, sfbEnergyAct, scaleFactorBandsTotal, pSfbOffset); + + pSpecScale[0] = specScaleOut; + } + } else { + /* long--??????--short, long--??????--long interpolation */ + /* long---long---short, long---long---long interpolation */ + + int scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Long; + const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + SHORT specScaleAct = pConcealmentInfo->specScale[0]; + + CConcealment_CalcBandEnergy(pSpectralCoefficient, /* spec_(n-2) */ + pSamplingRateInfo, BLOCK_LONG, + CConcealment_NoExpand, sfbEnergyPrev); + + if (pConcealmentInfo->windowSequence == + BLOCK_SHORT) { /* f_n == BLOCK_SHORT */ + /* long---long---short interpolation */ + + pIcsInfo->WindowShape = (samplesPerFrame <= 512) ? 2 : 1; + pIcsInfo->WindowSequence = BLOCK_START; + + for (i = 1; i < 8; i++) { /* search for max(specScale) */ + if (pConcealmentInfo->specScale[i] > specScaleAct) { + specScaleAct = pConcealmentInfo->specScale[i]; + } + } + + /* Expand first short spectrum */ + CConcealment_CalcBandEnergy( + pConcealmentInfo->spectralCoefficient, /* spec_n */ + pSamplingRateInfo, BLOCK_SHORT, CConcealment_Expand, /* !!! */ + sfbEnergyAct); + } else { + /* long---long---long interpolation */ + + pIcsInfo->WindowShape = 0; + pIcsInfo->WindowSequence = BLOCK_LONG; + + CConcealment_CalcBandEnergy( + pConcealmentInfo->spectralCoefficient, /* spec_n */ + pSamplingRateInfo, BLOCK_LONG, CConcealment_NoExpand, + sfbEnergyAct); + } + + CConcealment_InterpolateBuffer( + pSpectralCoefficient, /* spec_(n-1) */ + &pSpecScale[0], &specScaleAct, &pSpecScale[0], sfbEnergyPrev, + sfbEnergyAct, scaleFactorBandsTotal, pSfbOffset); + } + } + + /* Noise substitution of sign of the output spectral coefficients */ + CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase, + pSpectralCoefficient, samplesPerFrame); + /* Increment random phase index to avoid repetition artifacts. */ + pConcealmentInfo->iRandomPhase = + (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); + } + + /* scale spectrum according to concealment state */ + switch (pConcealmentInfo->concealState) { + case ConcealState_Single: + appliedProcessing = 1; + break; + + case ConcealState_FadeOut: { + FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < + CONCEAL_MAX_NUM_FADE_FACTORS); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < + pConcealCommonData->numFadeOutFrames); + + /* TimeDomainFading: */ + /* Attenuation of signal is done in CConcealment_TDFading() */ + + appliedProcessing = 1; + } break; + + case ConcealState_FadeIn: { + FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < + CONCEAL_MAX_NUM_FADE_FACTORS); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < + pConcealCommonData->numFadeInFrames); + + /* TimeDomainFading: */ + /* Attenuation of signal is done in CConcealment_TDFading() */ + + appliedProcessing = 1; + } break; + + case ConcealState_Mute: { + /* set dummy window parameters */ + pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */ + pIcsInfo->WindowShape = + pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape + (required for F/T transform) */ + pIcsInfo->WindowSequence = + CConcealment_GetWinSeq(pConcealmentInfo->windowSequence); + pConcealmentInfo->windowSequence = + pIcsInfo->WindowSequence; /* Store for next frame + (spectrum in concealment + buffer can't be used at + all) */ + + /* mute spectral data */ + FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL)); + + appliedProcessing = 1; + } break; + + default: + /* nothing to do here */ + break; + } + + return appliedProcessing; +} + +/*! + \brief Calculate the spectral energy + + The function calculates band-wise the spectral energy. This is used for + frame interpolation. +*/ +static void CConcealment_CalcBandEnergy( + FIXP_DBL *spectrum, const SamplingRateInfo *pSamplingRateInfo, + const int blockType, CConcealmentExpandType expandType, int *sfbEnergy) { + const SHORT *pSfbOffset; + int line, sfb, scaleFactorBandsTotal = 0; + + /* In the following calculations, enAccu is initialized with LSB-value in + * order to avoid zero energy-level */ + + line = 0; + + switch (blockType) { + case BLOCK_LONG: + case BLOCK_START: + case BLOCK_STOP: + + if (expandType == CConcealment_NoExpand) { + /* standard long calculation */ + scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Long; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = + (sizeof(LONG) << 3) - + CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb + 1]; line++) { + enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; + } + } else { + /* compress long to short */ + scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Short; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = + (sizeof(LONG) << 3) - + CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb + 1] << 3; line++) { + enAccu += + (enAccu + (fPow2Div2(*(spectrum + line)) >> sfbScale)) >> 3; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; + } + } + break; + + case BLOCK_SHORT: + + if (expandType == CConcealment_NoExpand) { + /* standard short calculation */ + scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Short; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = + (sizeof(LONG) << 3) - + CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb + 1]; line++) { + enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; + } + } else { + /* expand short to long spectrum */ + scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Long; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = + (sizeof(LONG) << 3) - + CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb + 1]; line++) { + enAccu += fPow2Div2(*(spectrum + (line >> 3))) >> sfbScale; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; + } + } + break; + } +} + +/*! + \brief Interpolate buffer + + The function creates the interpolated spectral data according to the + energy of the last good frame and the current (good) frame. +*/ +static void CConcealment_InterpolateBuffer(FIXP_DBL *spectrum, + SHORT *pSpecScalePrv, + SHORT *pSpecScaleAct, + SHORT *pSpecScaleOut, int *enPrv, + int *enAct, int sfbCnt, + const SHORT *pSfbOffset) { + int sfb, line = 0; + int fac_shift; + int fac_mod; + + for (sfb = 0; sfb < sfbCnt; sfb++) { + fac_shift = + enPrv[sfb] - enAct[sfb] + ((*pSpecScaleAct - *pSpecScalePrv) << 1); + fac_mod = fac_shift & 3; + fac_shift = (fac_shift >> 2) + 1; + fac_shift += *pSpecScalePrv - fixMax(*pSpecScalePrv, *pSpecScaleAct); + fac_shift = fMax(fMin(fac_shift, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + + for (; line < pSfbOffset[sfb + 1]; line++) { + FIXP_DBL accu = fMult(*(spectrum + line), facMod4Table[fac_mod]); + *(spectrum + line) = scaleValue(accu, fac_shift); + } + } + *pSpecScaleOut = fixMax(*pSpecScalePrv, *pSpecScaleAct); +} + +/*! + \brief Find next fading frame in case of changing fading direction + + \param pConcealCommonData Pointer to the concealment common data structure. + \param actFadeIndex Last index used for fading + \param direction Direction of change: 0 : change from FADE-OUT to FADE-IN, 1 + : change from FADE-IN to FADE-OUT + + This function determines the next fading index to be used for the fading + direction to be changed to. +*/ + +static INT findEquiFadeFrame(CConcealParams *pConcealCommonData, + INT actFadeIndex, int direction) { + FIXP_SGL *pFactor; + FIXP_SGL referenceVal; + FIXP_SGL minDiff = (FIXP_SGL)MAXVAL_SGL; + + INT nextFadeIndex = 0; + + int i; + + /* init depending on direction */ + if (direction == 0) { /* FADE-OUT => FADE-IN */ + if (actFadeIndex < 0) { + referenceVal = (FIXP_SGL)MAXVAL_SGL; + } else { + referenceVal = pConcealCommonData->fadeOutFactor[actFadeIndex] >> 1; + } + pFactor = pConcealCommonData->fadeInFactor; + } else { /* FADE-IN => FADE-OUT */ + if (actFadeIndex < 0) { + referenceVal = (FIXP_SGL)MAXVAL_SGL; + } else { + referenceVal = pConcealCommonData->fadeInFactor[actFadeIndex] >> 1; + } + pFactor = pConcealCommonData->fadeOutFactor; + } + + /* search for minimum difference */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + FIXP_SGL diff = fixp_abs((pFactor[i] >> 1) - referenceVal); + if (diff < minDiff) { + minDiff = diff; + nextFadeIndex = i; + } + } + + /* check and adjust depending on direction */ + if (direction == 0) { /* FADE-OUT => FADE-IN */ + if (nextFadeIndex > pConcealCommonData->numFadeInFrames) { + nextFadeIndex = fMax(pConcealCommonData->numFadeInFrames - 1, 0); + } + if (((pFactor[nextFadeIndex] >> 1) <= referenceVal) && + (nextFadeIndex > 0)) { + nextFadeIndex -= 1; + } + } else { /* FADE-IN => FADE-OUT */ + if (((pFactor[nextFadeIndex] >> 1) >= referenceVal) && + (nextFadeIndex < CONCEAL_MAX_NUM_FADE_FACTORS - 1)) { + nextFadeIndex += 1; + } + } + + return (nextFadeIndex); +} + +/*! + \brief Update the concealment state + + The function updates the state of the concealment state-machine. The + states are: mute, fade-in, fade-out, interpolate and frame-ok. +*/ +static void CConcealment_UpdateState( + CConcealmentInfo *pConcealmentInfo, int frameOk, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams; + + switch (pConcealCommonData->method) { + case ConcealMethodNoise: { + if (pConcealmentInfo->concealState != ConcealState_Ok) { + /* count the valid frames during concealment process */ + if (frameOk) { + pConcealmentInfo->cntValidFrames += 1; + } else { + pConcealmentInfo->cntValidFrames = 0; + } + } + + /* -- STATE MACHINE for Noise Substitution -- */ + switch (pConcealmentInfo->concealState) { + case ConcealState_Ok: + if (!frameOk) { + pConcealmentInfo->cntFadeFrames = 0; + pConcealmentInfo->cntValidFrames = 0; + pConcealmentInfo->attGrpOffset[0] = 0; + pConcealmentInfo->attGrpOffset[1] = 0; + pConcealmentInfo->winGrpOffset[0] = 0; + pConcealmentInfo->winGrpOffset[1] = 0; + if (pConcealCommonData->numFadeOutFrames > 0) { + /* change to state SINGLE-FRAME-LOSS */ + pConcealmentInfo->concealState = ConcealState_Single; + /* mode 0 just updates the Fading counter */ + CConcealment_ApplyFadeOut( + /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + } + break; + + case ConcealState_Single: /* Just a pre-stage before fade-out begins. + Stay here only one frame! */ + if (frameOk) { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } else { + if (pConcealmentInfo->cntFadeFrames >= + pConcealCommonData->numFadeOutFrames) { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } else { + /* change to state FADE-OUT */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + /* mode 0 just updates the Fading counter */ + CConcealment_ApplyFadeOut( + /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + } + } + break; + + case ConcealState_FadeOut: + if (pConcealmentInfo->cntValidFrames > + pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( + pConcealCommonData, pConcealmentInfo->cntFadeFrames, + 0 /* FadeOut -> FadeIn */); + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (frameOk) { + /* we have good frame information but stay fully in concealment - + * reset winGrpOffset/attGrpOffset */ + pConcealmentInfo->winGrpOffset[0] = 0; + pConcealmentInfo->winGrpOffset[1] = 0; + pConcealmentInfo->attGrpOffset[0] = 0; + pConcealmentInfo->attGrpOffset[1] = 0; + } + if (pConcealmentInfo->cntFadeFrames >= + pConcealCommonData->numFadeOutFrames) { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } else /* Stay in FADE-OUT */ + { + /* mode 0 just updates the Fading counter */ + CConcealment_ApplyFadeOut( + /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + } + } + break; + + case ConcealState_Mute: + if (pConcealmentInfo->cntValidFrames > + pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = + pConcealCommonData->numFadeInFrames - 1; + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (frameOk) { + /* we have good frame information but stay fully in concealment - + * reset winGrpOffset/attGrpOffset */ + pConcealmentInfo->winGrpOffset[0] = 0; + pConcealmentInfo->winGrpOffset[1] = 0; + pConcealmentInfo->attGrpOffset[0] = 0; + pConcealmentInfo->attGrpOffset[1] = 0; + } + } + break; + + case ConcealState_FadeIn: + pConcealmentInfo->cntFadeFrames -= 1; + if (frameOk) { + if (pConcealmentInfo->cntFadeFrames < 0) { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (pConcealCommonData->numFadeOutFrames > 0) { + /* change to state FADE-OUT */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( + pConcealCommonData, pConcealmentInfo->cntFadeFrames + 1, + 1 /* FadeIn -> FadeOut */); + pConcealmentInfo->winGrpOffset[0] = 0; + pConcealmentInfo->winGrpOffset[1] = 0; + pConcealmentInfo->attGrpOffset[0] = 0; + pConcealmentInfo->attGrpOffset[1] = 0; + + pConcealmentInfo + ->cntFadeFrames--; /* decrease because + CConcealment_ApplyFadeOut() will + increase, accordingly */ + /* mode 0 just updates the Fading counter */ + CConcealment_ApplyFadeOut( + /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + } + break; + + default: + FDK_ASSERT(0); + break; + } + } break; + + case ConcealMethodInter: + case ConcealMethodTonal: { + if (pConcealmentInfo->concealState != ConcealState_Ok) { + /* count the valid frames during concealment process */ + if (pConcealmentInfo->prevFrameOk[1] || + (pConcealmentInfo->prevFrameOk[0] && + !pConcealmentInfo->prevFrameOk[1] && frameOk)) { + /* The frame is OK even if it can be estimated by the energy + * interpolation algorithm */ + pConcealmentInfo->cntValidFrames += 1; + } else { + pConcealmentInfo->cntValidFrames = 0; + } + } + + /* -- STATE MACHINE for energy interpolation -- */ + switch (pConcealmentInfo->concealState) { + case ConcealState_Ok: + if (!(pConcealmentInfo->prevFrameOk[1] || + (pConcealmentInfo->prevFrameOk[0] && + !pConcealmentInfo->prevFrameOk[1] && frameOk))) { + if (pConcealCommonData->numFadeOutFrames > 0) { + /* Fade out only if the energy interpolation algorithm can not be + * applied! */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + pConcealmentInfo->cntFadeFrames = 0; + pConcealmentInfo->cntValidFrames = 0; + } + break; + + case ConcealState_Single: + pConcealmentInfo->concealState = ConcealState_Ok; + break; + + case ConcealState_FadeOut: + pConcealmentInfo->cntFadeFrames += 1; + + if (pConcealmentInfo->cntValidFrames > + pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( + pConcealCommonData, pConcealmentInfo->cntFadeFrames - 1, + 0 /* FadeOut -> FadeIn */); + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (pConcealmentInfo->cntFadeFrames >= + pConcealCommonData->numFadeOutFrames) { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + } + break; + + case ConcealState_Mute: + if (pConcealmentInfo->cntValidFrames > + pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = + pConcealCommonData->numFadeInFrames - 1; + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } + break; + + case ConcealState_FadeIn: + pConcealmentInfo->cntFadeFrames -= + 1; /* used to address the fade-in factors */ + + if (frameOk || pConcealmentInfo->prevFrameOk[1]) { + if (pConcealmentInfo->cntFadeFrames < 0) { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (pConcealCommonData->numFadeOutFrames > 0) { + /* change to state FADE-OUT */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( + pConcealCommonData, pConcealmentInfo->cntFadeFrames + 1, + 1 /* FadeIn -> FadeOut */); + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + } + break; + } /* End switch(pConcealmentInfo->concealState) */ + } break; + + default: + /* Don't need a state machine for other concealment methods. */ + break; + } +} + +/*! +\brief Randomizes the sign of the spectral data + + The function toggles the sign of the spectral data randomly. This is + useful to ensure the quality of the concealed frames. + */ +static void CConcealment_ApplyRandomSign(int randomPhase, FIXP_DBL *spec, + int samplesPerFrame) { + int i; + USHORT packedSign = 0; + + /* random table 512x16bit has been reduced to 512 packed sign bits = 32x16 bit + */ + + /* read current packed sign word */ + packedSign = AacDec_randomSign[randomPhase >> 4]; + packedSign >>= (randomPhase & 0xf); + + for (i = 0; i < samplesPerFrame; i++) { + if ((randomPhase & 0xf) == 0) { + packedSign = AacDec_randomSign[randomPhase >> 4]; + } + + if (packedSign & 0x1) { + spec[i] = -fMax(spec[i], (FIXP_DBL)(MINVAL_DBL + 1)); + } + packedSign >>= 1; + + randomPhase = (randomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); + } +} + +/*! + \brief Get fadeing factor for current concealment state. + + The function returns the state (ok or not) of the previous frame. + If called before the function CConcealment_Apply() set the fBeforeApply + flag to get the correct value. + + \return Frame OK flag of previous frame. + */ +int CConcealment_GetLastFrameOk(CConcealmentInfo *hConcealmentInfo, + const int fBeforeApply) { + int prevFrameOk = 1; + + if (hConcealmentInfo != NULL) { + prevFrameOk = hConcealmentInfo->prevFrameOk[fBeforeApply & 0x1]; + } + + return prevFrameOk; +} + +/*! + \brief Get the number of delay frames introduced by concealment technique. + + \return Number of delay frames. + */ +UINT CConcealment_GetDelay(CConcealParams *pConcealCommonData) { + UINT frameDelay = 0; + + if (pConcealCommonData != NULL) { + switch (pConcealCommonData->method) { + case ConcealMethodTonal: + case ConcealMethodInter: + frameDelay = 1; + break; + default: + break; + } + } + + return frameDelay; +} + +static int CConcealment_ApplyFadeOut( + int mode, CConcealmentInfo *pConcealmentInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + /* mode 1 = apply RandomSign and mute spectral coefficients if necessary, * + * mode 0 = Update cntFadeFrames */ + + /* restore frequency coefficients from buffer with a specific muting */ + int srcWin, dstWin, numWindows = 1; + int windowLen = samplesPerFrame; + int srcGrpStart = 0; + int winIdxStride = 1; + int numWinGrpPerFac, attIdx, attIdxStride; + int i; + int appliedProcessing = 0; + + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + + /* set old window parameters */ + if (pConcealmentInfo->lastRenderMode == AACDEC_RENDER_LPD) { + switch (pAacDecoderStaticChannelInfo->last_lpd_mode) { + case 1: + numWindows = 4; + srcGrpStart = 3; + windowLen = samplesPerFrame >> 2; + break; + case 2: + numWindows = 2; + srcGrpStart = 1; + windowLen = samplesPerFrame >> 1; + winIdxStride = 2; + break; + case 3: + numWindows = 1; + srcGrpStart = 0; + windowLen = samplesPerFrame; + winIdxStride = 4; + break; + } + pConcealmentInfo->lastWinGrpLen = 1; + } else { + pIcsInfo->WindowShape = pConcealmentInfo->windowShape; + pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence; + + if (pConcealmentInfo->windowSequence == BLOCK_SHORT) { + /* short block handling */ + numWindows = 8; + windowLen = samplesPerFrame >> 3; + srcGrpStart = numWindows - pConcealmentInfo->lastWinGrpLen; + } + } + + attIdxStride = + fMax(1, (int)(numWindows / (pConcealmentInfo->lastWinGrpLen + 1))); + + /* load last state */ + attIdx = pConcealmentInfo->cntFadeFrames; + numWinGrpPerFac = pConcealmentInfo->attGrpOffset[mode]; + srcWin = srcGrpStart + pConcealmentInfo->winGrpOffset[mode]; + + FDK_ASSERT((srcGrpStart * windowLen + windowLen) <= samplesPerFrame); + FDK_ASSERT((srcWin * windowLen + windowLen) <= 1024); + + for (dstWin = 0; dstWin < numWindows; dstWin += 1) { + FIXP_CNCL *pCncl = + pConcealmentInfo->spectralCoefficient + (srcWin * windowLen); + FIXP_DBL *pOut = pSpectralCoefficient + (dstWin * windowLen); + + if (mode == 1) { + /* mute if attIdx gets large enaugh */ + if (attIdx > pConcealmentInfo->pConcealParams->numFadeOutFrames) { + FDKmemclear(pCncl, sizeof(FIXP_DBL) * windowLen); + } + + /* restore frequency coefficients from buffer - attenuation is done later + */ + for (i = 0; i < windowLen; i++) { + pOut[i] = pCncl[i]; + } + + /* apply random change of sign for spectral coefficients */ + CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase, pOut, + windowLen); + + /* Increment random phase index to avoid repetition artifacts. */ + pConcealmentInfo->iRandomPhase = + (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); + + /* set old scale factors */ + pSpecScale[dstWin * winIdxStride] = + pConcealmentInfo->specScale[srcWin * winIdxStride]; + } + + srcWin += 1; + + if (srcWin >= numWindows) { + /* end of sequence -> rewind to first window of group */ + srcWin = srcGrpStart; + numWinGrpPerFac += 1; + if (numWinGrpPerFac >= attIdxStride) { + numWinGrpPerFac = 0; + attIdx += 1; + } + } + } + + /* store current state */ + + pConcealmentInfo->winGrpOffset[mode] = srcWin - srcGrpStart; + FDK_ASSERT((pConcealmentInfo->winGrpOffset[mode] >= 0) && + (pConcealmentInfo->winGrpOffset[mode] < 8)); + pConcealmentInfo->attGrpOffset[mode] = numWinGrpPerFac; + FDK_ASSERT((pConcealmentInfo->attGrpOffset[mode] >= 0) && + (pConcealmentInfo->attGrpOffset[mode] < attIdxStride)); + + if (mode == 0) { + pConcealmentInfo->cntFadeFrames = attIdx; + } + + appliedProcessing = 1; + + return appliedProcessing; +} + +/*! + \brief Do Time domain fading (TDFading) in concealment case + + In case of concealment, this function takes care of the fading, after time +domain signal has been rendered by the respective signal rendering functions. + The fading out in case of ACELP decoding is not done by this function but by +the ACELP decoder for the first concealed frame if CONCEAL_CORE_IGNORANT_FADE is +not set. + + TimeDomain fading never creates jumps in energy / discontinuities, it always +does a continuous fading. To achieve this, fading is always done from a starting +point to a target point, while the starting point is always determined to be the +last target point. By varying the target point of a fading, the fading slope can +be controlled. + + This principle is applied to the fading within a frame and the fading from +frame to frame. + + One frame is divided into 8 subframes to obtain 8 parts of fading slopes +within a frame, each maybe with its own gradient. + + Workflow: + 1.) Determine Fading behavior and end-of-frame target fading level, based on +concealmentState (determined by CConcealment_UpdateState()) and the core mode. + - By _DEFAULT_, + The target fading level is determined by fadeOutFactor[cntFadeFrames] +in case of fadeOut, or fadeInFactor[cntFadeFrames] in case of fadeIn. + --> fading type is FADE_TIMEDOMAIN in this case. Target fading level +is determined by fading index cntFadeFrames. + + - If concealmentState is signalling a _MUTED SIGNAL_, + TDFading decays to 0 within 1/8th of a frame if numFadeOutFrames == 0. + --> fading type is FADE_TIMEDOMAIN_TOSPECTRALMUTE in this case. + + - If concealmentState is signalling the _END OF MUTING_, + TDFading fades to target fading level within 1/8th of a frame if +numFadeInFrames == 0. + --> fading type is FADE_TIMEDOMAIN_FROMSPECTRALMUTE in this case. +Target fading level is determined by fading index cntFadeFrames. + +#ifndef CONCEAL_CORE_IGNORANT_FADE + - In case of an _ACELP FADEOUT_, + TDFading leaves fading control to ACELP decoder for 1/2 frame. + --> fading type is FADE_ACELPDOMAIN in this case. +#endif + + 2.) Render fading levels within current frame and do the final fading: + Map Fading slopes to fading levels and apply to time domain signal. + + +*/ + +INT CConcealment_TDFading( + int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo, + const INT aacOutDataHeadroom, PCM_DEC *pcmdata, PCM_DEC *pcmdata_1) { + /* + Do the fading in Time domain based on concealment states and core mode + */ + FIXP_DBL fadeStop, attMute = (FIXP_DBL)0; + int idx = 0, ii; + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo = + *ppAacDecoderStaticChannelInfo; + CConcealmentInfo *pConcealmentInfo = + &pAacDecoderStaticChannelInfo->concealmentInfo; + CConcealParams *pConcealParams = pConcealmentInfo->pConcealParams; + const CConcealmentState concealState = pConcealmentInfo->concealState; + TDfadingType fadingType; + FIXP_DBL fadingStations[9] = {0}; + int fadingSteps[8] = {0}; + const FIXP_DBL fadeStart = + pConcealmentInfo + ->fade_old; /* start fading at last end-of-frame attenuation */ + FIXP_SGL *fadeFactor = pConcealParams->fadeOutFactor; + const INT cntFadeFrames = pConcealmentInfo->cntFadeFrames; + int TDFadeOutStopBeforeMute = 1; + int TDFadeInStopBeforeFullLevel = 1; + + /* + determine Fading behaviour (end-of-frame attenuation and fading type) (1.) + */ + + switch (concealState) { + case ConcealState_Single: + case ConcealState_Mute: + case ConcealState_FadeOut: + idx = (pConcealParams->method == ConcealMethodNoise) ? cntFadeFrames - 1 + : cntFadeFrames; + fadingType = FADE_TIMEDOMAIN; + + if (concealState == ConcealState_Mute || + (cntFadeFrames + TDFadeOutStopBeforeMute) > + pConcealmentInfo->pConcealParams->numFadeOutFrames) { + fadingType = FADE_TIMEDOMAIN_TOSPECTRALMUTE; + } + + break; + case ConcealState_FadeIn: + idx = cntFadeFrames; + idx -= TDFadeInStopBeforeFullLevel; + FDK_FALLTHROUGH; + case ConcealState_Ok: + fadeFactor = pConcealParams->fadeInFactor; + idx = (concealState == ConcealState_Ok) ? -1 : idx; + fadingType = (pConcealmentInfo->concealState_old == ConcealState_Mute) + ? FADE_TIMEDOMAIN_FROMSPECTRALMUTE + : FADE_TIMEDOMAIN; + break; + default: + FDK_ASSERT(0); + fadingType = FADE_TIMEDOMAIN_TOSPECTRALMUTE; + break; + } + + /* determine Target end-of-frame fading level and fading slope */ + switch (fadingType) { + case FADE_TIMEDOMAIN_FROMSPECTRALMUTE: + fadeStop = + (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(fadeFactor[idx]); + if (pConcealmentInfo->pConcealParams->numFadeInFrames == 0) { + /* do step as fast as possible */ + fadingSteps[0] = 1; + break; + } + CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]); + break; + case FADE_TIMEDOMAIN: + fadeStop = + (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(fadeFactor[idx]); + CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]); + break; + case FADE_TIMEDOMAIN_TOSPECTRALMUTE: + fadeStop = attMute; + if (pConcealmentInfo->pConcealParams->numFadeOutFrames == 0) { + /* do step as fast as possible */ + fadingSteps[0] = 1; + break; + } + CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]); + break; + } + + /* + Render fading levels within current frame and do the final fading (2.) + */ + + len >>= 3; + CConcealment_TDFadeFillFadingStations(fadingStations, fadingSteps, fadeStop, + fadeStart, fadingType); + + if ((fadingStations[8] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[7] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[6] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[5] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[4] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[3] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[2] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[1] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[0] != + (FIXP_DBL)MAXVAL_DBL)) /* if there's something to fade */ + { + int start = 0; + for (ii = 0; ii < 8; ii++) { + CConcealment_TDFadePcmAtt(start, len, fadingStations[ii], + fadingStations[ii + 1], pcmdata); + start += len; + } + } + CConcealment_TDNoise_Apply(pConcealmentInfo, len, aacOutDataHeadroom, + pcmdata); + + /* Save end-of-frame attenuation and fading type */ + pConcealmentInfo->lastFadingType = fadingType; + pConcealmentInfo->fade_old = fadeStop; + pConcealmentInfo->concealState_old = concealState; + + return 1; +} + +/* attenuate pcmdata in Time Domain Fading process */ +static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart, + FIXP_DBL fadeStop, PCM_DEC *pcmdata) { + int i; + FIXP_DBL dStep; + FIXP_DBL dGain; + FIXP_DBL dGain_apply; + + /* set start energy */ + dGain = fadeStart; + /* determine energy steps from sample to sample */ + dStep = (FIXP_DBL)((int)((fadeStart >> 1) - (fadeStop >> 1)) / len) << 1; + + for (i = start; i < (start + len); i++) { + dGain -= dStep; + /* prevent gain from getting negative due to possible fixpoint inaccuracies + */ + dGain_apply = fMax((FIXP_DBL)0, dGain); + /* finally, attenuate samples */ + pcmdata[i] = FIXP_DBL2PCM_DEC(fMult(pcmdata[i], dGain_apply)); + } +} + +/* +\brief Fill FadingStations + +The fadingstations are the attenuation factors, being applied to its dedicated +portions of pcm data. They are calculated using the fadingsteps. One fadingstep +is the weighted contribution to the fading slope within its dedicated portion of +pcm data. + +*Fadingsteps : 0 0 0 1 0 1 2 0 + + |<- 1 Frame pcm data ->| + fadeStart-->|__________ | + ^ ^ ^ ^ \____ | + Attenuation : | | | | ^ ^\__ | + | | | | | | ^\ | + | | | | | | | \___|<-- fadeStop + | | | | | | | ^ ^ + | | | | | | | | | +Fadingstations: [0][1][2][3][4][5][6][7][8] + +(Fadingstations "[0]" is "[8] from previous frame", therefore its not meaningful +to be edited) + +*/ +static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations, + int *fadingSteps, + FIXP_DBL fadeStop, + FIXP_DBL fadeStart, + TDfadingType fadingType) { + int i; + INT fadingSteps_sum = 0; + INT fadeDiff; + + fadingSteps_sum = fadingSteps[0] + fadingSteps[1] + fadingSteps[2] + + fadingSteps[3] + fadingSteps[4] + fadingSteps[5] + + fadingSteps[6] + fadingSteps[7]; + fadeDiff = ((INT)(fadeStop - fadeStart) / fMax(fadingSteps_sum, (INT)1)); + fadingStations[0] = fadeStart; + for (i = 1; i < 8; i++) { + fadingStations[i] = + fadingStations[i - 1] + (FIXP_DBL)(fadeDiff * fadingSteps[i - 1]); + } + fadingStations[8] = fadeStop; +} + +static void CConcealment_TDFading_doLinearFadingSteps(int *fadingSteps) { + fadingSteps[0] = fadingSteps[1] = fadingSteps[2] = fadingSteps[3] = + fadingSteps[4] = fadingSteps[5] = fadingSteps[6] = fadingSteps[7] = 1; +} + +/* end of TimeDomainFading functions */ + +/* derived from int UsacRandomSign() */ +static int CConcealment_TDNoise_Random(ULONG *seed) { + *seed = (ULONG)(((UINT64)(*seed) * 69069) + 5); + return (int)(*seed); +} + +static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo, + const int len, + const INT aacOutDataHeadroom, + PCM_DEC *const pcmdata) { + PCM_DEC *states = pConcealmentInfo->TDNoiseStates; + PCM_DEC noiseVal; + FIXP_DBL noiseValLong; + FIXP_SGL *coef = pConcealmentInfo->TDNoiseCoef; + FIXP_DBL TDNoiseAtt; + ULONG seed = pConcealmentInfo->TDNoiseSeed = + (ULONG)CConcealment_TDNoise_Random(&pConcealmentInfo->TDNoiseSeed) + 1; + + TDNoiseAtt = pConcealmentInfo->pConcealParams->comfortNoiseLevel; + + int ii; + + if ((pConcealmentInfo->concealState != ConcealState_Ok || + pConcealmentInfo->concealState_old != ConcealState_Ok) && + TDNoiseAtt != (FIXP_DBL)0) { + for (ii = 0; ii < (len << 3); ii++) { + /* create filtered noise */ + states[2] = states[1]; + states[1] = states[0]; + states[0] = + FIXP_DBL2PCM_DEC((FIXP_DBL)CConcealment_TDNoise_Random(&seed)); + noiseValLong = fMult(states[0], coef[0]) + fMult(states[1], coef[1]) + + fMult(states[2], coef[2]); + noiseVal = FIXP_DBL2PCM_DEC(fMult(noiseValLong, TDNoiseAtt) >> + aacOutDataHeadroom); + + /* add filtered noise - check for clipping, before */ + if (noiseVal > (PCM_DEC)0 && + pcmdata[ii] > (PCM_DEC)MAXVAL_PCM_DEC - noiseVal) { + noiseVal = noiseVal * (PCM_DEC)-1; + } else if (noiseVal < (PCM_DEC)0 && + pcmdata[ii] < (PCM_DEC)MINVAL_PCM_DEC - noiseVal) { + noiseVal = noiseVal * (PCM_DEC)-1; + } + + pcmdata[ii] += noiseVal; + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/conceal.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/conceal.h new file mode 100644 index 0000000000000..0c002a5920224 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/conceal.h @@ -0,0 +1,152 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: independent channel concealment + +*******************************************************************************/ + +#ifndef CONCEAL_H +#define CONCEAL_H + +#include "channelinfo.h" + +#define AACDEC_CONCEAL_PARAM_NOT_SPECIFIED (0xFFFE) + +void CConcealment_InitCommonData(CConcealParams *pConcealCommonData); + +void CConcealment_InitChannelData(CConcealmentInfo *hConcealmentInfo, + CConcealParams *pConcealCommonData, + AACDEC_RENDER_MODE initRenderMode, + int samplesPerFrame); + +CConcealmentMethod CConcealment_GetMethod(CConcealParams *pConcealCommonData); + +UINT CConcealment_GetDelay(CConcealParams *pConcealCommonData); + +AAC_DECODER_ERROR +CConcealment_SetParams(CConcealParams *concealParams, int method, + int fadeOutSlope, int fadeInSlope, int muteRelease, + FIXP_DBL comfNoiseLevel); + +CConcealmentState CConcealment_GetState(CConcealmentInfo *hConcealmentInfo); + +AAC_DECODER_ERROR +CConcealment_SetAttenuation(CConcealParams *concealParams, + const SHORT *fadeOutAttenuationVector, + const SHORT *fadeInAttenuationVector); + +void CConcealment_Store( + CConcealmentInfo *hConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo); + +int CConcealment_Apply( + CConcealmentInfo *hConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const UCHAR lastLpdMode, const int FrameOk, const UINT flags); + +int CConcealment_GetLastFrameOk(CConcealmentInfo *hConcealmentInfo, + const int fBeforeApply); + +INT CConcealment_TDFading( + int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo, + const INT aacOutDataHeadroom, PCM_DEC *pcmdata, PCM_DEC *pcmdata_1); + +#endif /* #ifndef CONCEAL_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/conceal_types.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/conceal_types.h new file mode 100644 index 0000000000000..36e7dec64f57e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/conceal_types.h @@ -0,0 +1,203 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Christian Griebel + + Description: Error concealment structs and types + +*******************************************************************************/ + +#ifndef CONCEAL_TYPES_H +#define CONCEAL_TYPES_H + +#include "machine_type.h" +#include "common_fix.h" + +#include "rvlc_info.h" + +#include "usacdec_lpc.h" + +#define CONCEAL_MAX_NUM_FADE_FACTORS (32) + +#define FIXP_CNCL FIXP_DBL +#define FL2FXCONST_CNCL FL2FXCONST_DBL +#define FX_DBL2FX_CNCL +#define FX_CNCL2FX_DBL +#define CNCL_FRACT_BITS DFRACT_BITS + +/* Warning: Do not ever change these values. */ +typedef enum { + ConcealMethodNone = -1, + ConcealMethodMute = 0, + ConcealMethodNoise = 1, + ConcealMethodInter = 2, + ConcealMethodTonal = 3 + +} CConcealmentMethod; + +typedef enum { + ConcealState_Ok, + ConcealState_Single, + ConcealState_FadeIn, + ConcealState_Mute, + ConcealState_FadeOut + +} CConcealmentState; + +typedef struct { + FIXP_SGL fadeOutFactor[CONCEAL_MAX_NUM_FADE_FACTORS]; + FIXP_SGL fadeInFactor[CONCEAL_MAX_NUM_FADE_FACTORS]; + + CConcealmentMethod method; + + int numFadeOutFrames; + int numFadeInFrames; + int numMuteReleaseFrames; + FIXP_DBL comfortNoiseLevel; + +} CConcealParams; + +typedef enum { + FADE_TIMEDOMAIN_TOSPECTRALMUTE = 1, + FADE_TIMEDOMAIN_FROMSPECTRALMUTE, + FADE_TIMEDOMAIN +} TDfadingType; + +typedef struct { + CConcealParams *pConcealParams; + + FIXP_CNCL spectralCoefficient[1024]; + SHORT specScale[8]; + + INT iRandomPhase; + INT prevFrameOk[2]; + INT cntValidFrames; + INT cntFadeFrames; /* State for signal fade-in/out */ + /* States for signal fade-out of frames with more than one window/subframe - + [0] used by Update CntFadeFrames mode of CConcealment_ApplyFadeOut, [1] used + by FadeOut mode */ + int winGrpOffset[2]; /* State for signal fade-out of frames with more than one + window/subframe */ + int attGrpOffset[2]; /* State for faster signal fade-out of frames with + transient signal parts */ + + SCHAR lastRenderMode; + + UCHAR windowShape; + BLOCK_TYPE windowSequence; + UCHAR lastWinGrpLen; + + CConcealmentState concealState; + CConcealmentState concealState_old; + FIXP_DBL fade_old; /* last fading factor */ + TDfadingType lastFadingType; /* last fading type */ + + SHORT aRvlcPreviousScaleFactor[RVLC_MAX_SFB]; /* needed once per channel */ + UCHAR aRvlcPreviousCodebook[RVLC_MAX_SFB]; /* needed once per channel */ + SCHAR rvlcPreviousScaleFactorOK; + SCHAR rvlcPreviousBlockType; + + FIXP_LPC lsf4[M_LP_FILTER_ORDER]; + FIXP_DBL last_tcx_gain; + INT last_tcx_gain_e; + ULONG TDNoiseSeed; + PCM_DEC TDNoiseStates[3]; + FIXP_SGL TDNoiseCoef[3]; + FIXP_SGL TDNoiseAtt; + +} CConcealmentInfo; + +#endif /* #ifndef CONCEAL_TYPES_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/ldfiltbank.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/ldfiltbank.cpp new file mode 100644 index 0000000000000..13e61a510a7b1 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/ldfiltbank.cpp @@ -0,0 +1,283 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: low delay filterbank + +*******************************************************************************/ + +#include "ldfiltbank.h" + +#include "aac_rom.h" +#include "dct.h" +#include "FDK_tools_rom.h" +#include "mdct.h" + +#define LDFB_HEADROOM 2 + +#if defined(__arm__) +#endif + +static void multE2_DinvF_fdk(PCM_DEC *output, FIXP_DBL *x, const FIXP_WTB *fb, + FIXP_DBL *z, const int N) { + int i; + + /* scale for FIXP_DBL -> PCM_DEC conversion: */ + const int scale = (DFRACT_BITS - PCM_OUT_BITS) - LDFB_HEADROOM + (3); + +#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0) + FIXP_DBL rnd_val_wts0 = (FIXP_DBL)0; + FIXP_DBL rnd_val_wts1 = (FIXP_DBL)0; +#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - WTS0 - 1) > 0) + if (-WTS0 - 1 + scale) + rnd_val_wts0 = (FIXP_DBL)(1 << (-WTS0 - 1 + scale - 1)); +#endif + if (-WTS1 - 1 + scale) + rnd_val_wts1 = (FIXP_DBL)(1 << (-WTS1 - 1 + scale - 1)); +#endif + + for (i = 0; i < N / 4; i++) { + FIXP_DBL z0, z2, tmp; + + z2 = x[N / 2 + i]; + z0 = fAddSaturate(z2, + (fMultDiv2(z[N / 2 + i], fb[2 * N + i]) >> (-WTS2 - 1))); + + z[N / 2 + i] = fAddSaturate( + x[N / 2 - 1 - i], + (fMultDiv2(z[N + i], fb[2 * N + N / 2 + i]) >> (-WTS2 - 1))); + + tmp = (fMultDiv2(z[N / 2 + i], fb[N + N / 2 - 1 - i]) + + fMultDiv2(z[i], fb[N + N / 2 + i])); + +#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0) + FDK_ASSERT((-WTS1 - 1 + scale) >= 0); + FDK_ASSERT(tmp <= ((FIXP_DBL)0x7FFFFFFF - + rnd_val_wts1)); /* rounding must not cause overflow */ + output[(N * 3 / 4 - 1 - i)] = (PCM_DEC)SATURATE_RIGHT_SHIFT( + tmp + rnd_val_wts1, -WTS1 - 1 + scale, PCM_OUT_BITS); +#else + FDK_ASSERT((WTS1 + 1 - scale) >= 0); + output[(N * 3 / 4 - 1 - i)] = + (PCM_DEC)SATURATE_LEFT_SHIFT(tmp, WTS1 + 1 - scale, PCM_OUT_BITS); +#endif + + z[i] = z0; + z[N + i] = z2; + } + + for (i = N / 4; i < N / 2; i++) { + FIXP_DBL z0, z2, tmp0, tmp1; + + z2 = x[N / 2 + i]; + z0 = fAddSaturate(z2, + (fMultDiv2(z[N / 2 + i], fb[2 * N + i]) >> (-WTS2 - 1))); + + z[N / 2 + i] = fAddSaturate( + x[N / 2 - 1 - i], + (fMultDiv2(z[N + i], fb[2 * N + N / 2 + i]) >> (-WTS2 - 1))); + + tmp0 = (fMultDiv2(z[N / 2 + i], fb[N / 2 - 1 - i]) + + fMultDiv2(z[i], fb[N / 2 + i])); + tmp1 = (fMultDiv2(z[N / 2 + i], fb[N + N / 2 - 1 - i]) + + fMultDiv2(z[i], fb[N + N / 2 + i])); + +#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0) + FDK_ASSERT((-WTS0 - 1 + scale) >= 0); + FDK_ASSERT(tmp0 <= ((FIXP_DBL)0x7FFFFFFF - + rnd_val_wts0)); /* rounding must not cause overflow */ + FDK_ASSERT(tmp1 <= ((FIXP_DBL)0x7FFFFFFF - + rnd_val_wts1)); /* rounding must not cause overflow */ + output[(i - N / 4)] = (PCM_DEC)SATURATE_RIGHT_SHIFT( + tmp0 + rnd_val_wts0, -WTS0 - 1 + scale, PCM_OUT_BITS); + output[(N * 3 / 4 - 1 - i)] = (PCM_DEC)SATURATE_RIGHT_SHIFT( + tmp1 + rnd_val_wts1, -WTS1 - 1 + scale, PCM_OUT_BITS); +#else + FDK_ASSERT((WTS0 + 1 - scale) >= 0); + output[(i - N / 4)] = + (PCM_DEC)SATURATE_LEFT_SHIFT(tmp0, WTS0 + 1 - scale, PCM_OUT_BITS); + output[(N * 3 / 4 - 1 - i)] = + (PCM_DEC)SATURATE_LEFT_SHIFT(tmp1, WTS1 + 1 - scale, PCM_OUT_BITS); +#endif + z[i] = z0; + z[N + i] = z2; + } + + /* Exchange quarter parts of x to bring them in the "right" order */ + for (i = 0; i < N / 4; i++) { + FIXP_DBL tmp0 = fMultDiv2(z[i], fb[N / 2 + i]); + +#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0) + FDK_ASSERT((-WTS0 - 1 + scale) >= 0); + FDK_ASSERT(tmp0 <= ((FIXP_DBL)0x7FFFFFFF - + rnd_val_wts0)); /* rounding must not cause overflow */ + output[(N * 3 / 4 + i)] = (PCM_DEC)SATURATE_RIGHT_SHIFT( + tmp0 + rnd_val_wts0, -WTS0 - 1 + scale, PCM_OUT_BITS); +#else + FDK_ASSERT((WTS0 + 1 - scale) >= 0); + output[(N * 3 / 4 + i)] = + (PCM_DEC)SATURATE_LEFT_SHIFT(tmp0, WTS0 + 1 - scale, PCM_OUT_BITS); +#endif + } +} + +int InvMdctTransformLowDelay_fdk(FIXP_DBL *mdctData, const int mdctData_e, + PCM_DEC *output, FIXP_DBL *fs_buffer, + const int N) { + const FIXP_WTB *coef; + FIXP_DBL gain = (FIXP_DBL)0; + int scale = mdctData_e + MDCT_OUT_HEADROOM - + LDFB_HEADROOM; /* The LDFB_HEADROOM is compensated inside + multE2_DinvF_fdk() below */ + int i; + + /* Select LD window slope */ + switch (N) { + case 256: + coef = LowDelaySynthesis256; + break; + case 240: + coef = LowDelaySynthesis240; + break; + case 160: + coef = LowDelaySynthesis160; + break; + case 128: + coef = LowDelaySynthesis128; + break; + case 120: + coef = LowDelaySynthesis120; + break; + case 512: + coef = LowDelaySynthesis512; + break; + case 480: + default: + coef = LowDelaySynthesis480; + break; + } + + /* + Apply exponent and 1/N factor. + Note: "scale" is off by one because for LD_MDCT the window length is twice + the window length of a regular MDCT. This is corrected inside + multE2_DinvF_fdk(). Refer to ISO/IEC 14496-3:2009 page 277, + chapter 4.6.20.2 "Low Delay Window". + */ + imdct_gain(&gain, &scale, N); + + dct_IV(mdctData, N, &scale); + + if (N == 256 || N == 240 || N == 160) { + scale -= 1; + } else if (N == 128 || N == 120) { + scale -= 2; + } + + if (gain != (FIXP_DBL)0) { + for (i = 0; i < N; i++) { + mdctData[i] = fMult(mdctData[i], gain); + } + } + scaleValuesSaturate(mdctData, N, scale); + + /* Since all exponent and factors have been applied, current exponent is zero. + */ + multE2_DinvF_fdk(output, mdctData, coef, fs_buffer, N); + + return (1); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/ldfiltbank.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/ldfiltbank.h new file mode 100644 index 0000000000000..02971d08db6ea --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/ldfiltbank.h @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: low delay filterbank interface + +*******************************************************************************/ + +#ifndef LDFILTBANK_H +#define LDFILTBANK_H + +#include "common_fix.h" +#include "aac_rom.h" + +int InvMdctTransformLowDelay_fdk(FIXP_DBL *mdctdata_m, const int mdctdata_e, + PCM_DEC *mdctOut, FIXP_DBL *fs_buffer, + const int frameLength); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/overlapadd.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/overlapadd.h new file mode 100644 index 0000000000000..49eecd8cd81d8 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/overlapadd.h @@ -0,0 +1,120 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +#ifndef OVERLAPADD_H +#define OVERLAPADD_H + +#include "common_fix.h" + +/* ELD uses different overlap which is twice the frame size: */ +#define OverlapBufferSize (768) + +typedef FIXP_DBL SPECTRUM[1024]; +typedef FIXP_DBL* SPECTRAL_PTR; + +#define SPEC_LONG(ptr) (ptr) +#define SPEC(ptr, w, gl) ((ptr) + ((w) * (gl))) + +#define SPEC_TCX(ptr, f, gl, fb) \ + ((ptr) + ((f) * (gl * 2) * (((fb) == 0) ? 1 : 2))) + +#endif /* #ifndef OVERLAPADD_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/pulsedata.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/pulsedata.cpp new file mode 100644 index 0000000000000..eb6d5bce46a8e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/pulsedata.cpp @@ -0,0 +1,164 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: pulse data tool + +*******************************************************************************/ + +#include "pulsedata.h" + +#include "channelinfo.h" + +INT CPulseData_Read(HANDLE_FDK_BITSTREAM bs, CPulseData *const PulseData, + const SHORT *sfb_startlines, const void *pIcsInfo, + const SHORT frame_length) { + int i, k = 0; + const UINT MaxSfBands = + GetScaleFactorBandsTransmitted((const CIcsInfo *)pIcsInfo); + + /* reset pulse data flag */ + PulseData->PulseDataPresent = 0; + + if ((PulseData->PulseDataPresent = (UCHAR)FDKreadBit(bs)) != 0) { + if (!IsLongBlock((const CIcsInfo *)pIcsInfo)) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + PulseData->NumberPulse = (UCHAR)FDKreadBits(bs, 2); + PulseData->PulseStartBand = (UCHAR)FDKreadBits(bs, 6); + + if (PulseData->PulseStartBand >= MaxSfBands) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + k = sfb_startlines[PulseData->PulseStartBand]; + + for (i = 0; i <= PulseData->NumberPulse; i++) { + PulseData->PulseOffset[i] = (UCHAR)FDKreadBits(bs, 5); + PulseData->PulseAmp[i] = (UCHAR)FDKreadBits(bs, 4); + k += PulseData->PulseOffset[i]; + } + + if (k >= frame_length) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + } + + return 0; +} + +void CPulseData_Apply( + CPulseData *PulseData, /*!< pointer to pulse data side info */ + const short + *pScaleFactorBandOffsets, /*!< pointer to scalefactor band offsets */ + FIXP_DBL *coef) /*!< pointer to spectrum */ +{ + int i, k; + + if (PulseData->PulseDataPresent) { + k = pScaleFactorBandOffsets[PulseData->PulseStartBand]; + + for (i = 0; i <= PulseData->NumberPulse; i++) { + k += PulseData->PulseOffset[i]; + if (coef[k] > (FIXP_DBL)0) + coef[k] += (FIXP_DBL)(int)PulseData->PulseAmp[i]; + else + coef[k] -= (FIXP_DBL)(int)PulseData->PulseAmp[i]; + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/pulsedata.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/pulsedata.h new file mode 100644 index 0000000000000..15ae11c487c30 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/pulsedata.h @@ -0,0 +1,150 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: pulse data tool + +*******************************************************************************/ + +#ifndef PULSEDATA_H +#define PULSEDATA_H + +#include "common_fix.h" +#include "FDK_bitstream.h" + +#define N_MAX_LINES 4 + +typedef struct { + UCHAR PulseDataPresent; + UCHAR NumberPulse; + UCHAR PulseStartBand; + UCHAR PulseOffset[N_MAX_LINES]; + UCHAR PulseAmp[N_MAX_LINES]; +} CPulseData; + +/** + * \brief Read pulse data from bitstream + * + * The function reads the elements for pulse data from + * the bitstream. + * + * \param bs bit stream handle data source. + * \param PulseData pointer to a CPulseData were the decoded data is stored + * into. + * \param MaxSfBands max number of scale factor bands. + * \return 0 on success, != 0 on parse error. + */ +INT CPulseData_Read(const HANDLE_FDK_BITSTREAM bs, CPulseData *const PulseData, + const SHORT *sfb_startlines, const void *pIcsInfo, + const SHORT frame_length); + +/** + * \brief Apply pulse data to spectral lines + * + * The function applies the pulse data to the + * specified spectral lines. + * + * \param PulseData pointer to the previously decoded pulse data. + * \param pScaleFactorBandOffsets scale factor band line offset table. + * \param coef pointer to the spectral data were pulse data should be applied + * to. + * \return none + */ +void CPulseData_Apply(CPulseData *PulseData, + const short *pScaleFactorBandOffsets, FIXP_DBL *coef); + +#endif /* #ifndef PULSEDATA_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlc.cpp new file mode 100644 index 0000000000000..0b80364129bdb --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlc.cpp @@ -0,0 +1,1218 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief RVLC Decoder + \author Robert Weidner +*/ + +#include "rvlc.h" + +#include "block.h" + +#include "aac_rom.h" +#include "rvlcbit.h" +#include "rvlcconceal.h" +#include "aacdec_hcr.h" + +/*--------------------------------------------------------------------------------------------- + function: rvlcInit + + description: init RVLC by data from channelinfo, which was decoded +previously and set up pointers +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - pointer bitstream structure +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcInit(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + /* RVLC common initialization part 2 of 2 */ + SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc; + SHORT *pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd; + SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd; + SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor; + int bnds; + + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = 0; + + pRvlc->numDecodedEscapeWordsEsc = 0; + pRvlc->numDecodedEscapeWordsFwd = 0; + pRvlc->numDecodedEscapeWordsBwd = 0; + + pRvlc->intensity_used = 0; + pRvlc->errorLogRvlc = 0; + + pRvlc->conceal_max = CONCEAL_MAX_INIT; + pRvlc->conceal_min = CONCEAL_MIN_INIT; + + pRvlc->conceal_max_esc = CONCEAL_MAX_INIT; + pRvlc->conceal_min_esc = CONCEAL_MIN_INIT; + + pRvlc->pHuffTreeRvlcEscape = aHuffTreeRvlcEscape; + pRvlc->pHuffTreeRvlCodewds = aHuffTreeRvlCodewds; + + /* init scf arrays (for savety (in case of there are only zero codebooks)) */ + for (bnds = 0; bnds < RVLC_MAX_SFB; bnds++) { + pScfFwd[bnds] = 0; + pScfBwd[bnds] = 0; + pScfEsc[bnds] = 0; + pScaleFactor[bnds] = 0; + } + + /* set base bitstream ptr to the RVL-coded part (start of RVLC data (ESC 2)) + */ + FDKsyncCache(bs); + pRvlc->bsAnchor = (INT)FDKgetValidBits(bs); + + pRvlc->bitstreamIndexRvlFwd = + 0; /* first bit within RVL coded block as start address for forward + decoding */ + pRvlc->bitstreamIndexRvlBwd = + pRvlc->length_of_rvlc_sf - 1; /* last bit within RVL coded block as start + address for backward decoding */ + + /* skip RVLC-bitstream-part -- pointing now to escapes (if present) or to TNS + * data (if present) */ + FDKpushFor(bs, pRvlc->length_of_rvlc_sf); + + if (pRvlc->sf_escapes_present != 0) { + /* locate internal bitstream ptr at escapes (which is the second part) */ + FDKsyncCache(bs); + pRvlc->bitstreamIndexEsc = pRvlc->bsAnchor - (INT)FDKgetValidBits(bs); + + /* skip escapeRVLC-bitstream-part -- pointing to TNS data (if present) to + * make decoder continue */ + /* decoding of RVLC should work despite this second pushFor during + * initialization because */ + /* bitstream initialization is valid for both ESC2 data parts (RVL-coded + * values and ESC-coded values) */ + FDKpushFor(bs, pRvlc->length_of_rvlc_escapes); + } +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcCheckIntensityCb + + description: Check if a intensity codebook is used in the current channel. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure +----------------------------------------------------------------------------------------------- + output: - intensity_used: 0 no intensity codebook is used + 1 intensity codebook is used +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcCheckIntensityCb( + CErRvlcInfo *pRvlc, CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + int group, band, bnds; + + pRvlc->intensity_used = 0; + + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + if ((pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] == + INTENSITY_HCB) || + (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] == + INTENSITY_HCB2)) { + pRvlc->intensity_used = 1; + break; + } + } + } +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeEscapeWord + + description: Decode a huffman coded RVLC Escape-word. This value is part +of a DPCM coded scalefactor. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure +----------------------------------------------------------------------------------------------- + return: - a single RVLC-Escape value which had to be applied to a +DPCM value (which has a absolute value of 7) +-------------------------------------------------------------------------------------------- +*/ + +static SCHAR rvlcDecodeEscapeWord(CErRvlcInfo *pRvlc, HANDLE_FDK_BITSTREAM bs) { + int i; + SCHAR value; + UCHAR carryBit; + UINT treeNode; + UINT branchValue; + UINT branchNode; + + INT *pBitstreamIndexEsc; + const UINT *pEscTree; + + pEscTree = pRvlc->pHuffTreeRvlcEscape; + pBitstreamIndexEsc = &(pRvlc->bitstreamIndexEsc); + treeNode = *pEscTree; /* init at starting node */ + + for (i = MAX_LEN_RVLC_ESCAPE_WORD - 1; i >= 0; i--) { + carryBit = + rvlcReadBitFromBitstream(bs, /* get next bit */ + pRvlc->bsAnchor, pBitstreamIndexEsc, FWD); + + CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in + huffman decoding tree */ + treeNode, &branchValue, &branchNode); + + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set --> a RVLC-escape-word is + completely decoded */ + value = (SCHAR)branchNode & CLR_BIT_10; + pRvlc->length_of_rvlc_escapes -= (MAX_LEN_RVLC_ESCAPE_WORD - i); + + if (pRvlc->length_of_rvlc_escapes < 0) { + pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID; + value = -1; + } + + return value; + } else { + treeNode = *( + pEscTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + + pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID; + + return -1; /* should not be reached */ +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeEscapes + + description: Decodes all huffman coded RVLC Escape Words. + Here a difference to the pseudo-code-implementation from +standard can be found. A while loop (and not two nested for loops) is used for +two reasons: + + 1. The plain huffman encoded escapes are decoded before the +RVL-coded scalefactors. Therefore the escapes are present in the second step + when decoding the RVL-coded-scalefactor values in forward +and backward direction. + + When the RVL-coded scalefactors are decoded and there a +escape is needed, then it is just taken out of the array in ascending order. + + 2. It's faster. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - handle to FDK bitstream +----------------------------------------------------------------------------------------------- + return: - 0 ok the decoded escapes seem to be valid + - 1 error there was a error detected during decoding escapes + --> all escapes are invalid +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcDecodeEscapes(CErRvlcInfo *pRvlc, SHORT *pEsc, + HANDLE_FDK_BITSTREAM bs) { + SCHAR escWord; + SCHAR escCnt = 0; + SHORT *pEscBitCntSum; + + pEscBitCntSum = &(pRvlc->length_of_rvlc_escapes); + + /* Decode all RVLC-Escape words with a plain Huffman-Decoder */ + while (*pEscBitCntSum > 0) { + escWord = rvlcDecodeEscapeWord(pRvlc, bs); + + if (escWord >= 0) { + pEsc[escCnt] = escWord; + escCnt++; + } else { + pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID; + pRvlc->numDecodedEscapeWordsEsc = escCnt; + + return; + } + } /* all RVLC escapes decoded */ + + pRvlc->numDecodedEscapeWordsEsc = escCnt; +} + +/*--------------------------------------------------------------------------------------------- + function: decodeRVLCodeword + + description: Decodes a RVL-coded dpcm-word (-part). +----------------------------------------------------------------------------------------------- + input: - FDK bitstream handle + - pointer rvlc structure +----------------------------------------------------------------------------------------------- + return: - a dpcm value which is within range [0,1,..,14] in case of +no errors. The offset of 7 must be subtracted to get a valid dpcm scalefactor +value. In case of errors a forbidden codeword is detected --> returning -1 +-------------------------------------------------------------------------------------------- +*/ + +SCHAR decodeRVLCodeword(HANDLE_FDK_BITSTREAM bs, CErRvlcInfo *pRvlc) { + int i; + SCHAR value; + UCHAR carryBit; + UINT branchValue; + UINT branchNode; + + const UINT *pRvlCodeTree = pRvlc->pHuffTreeRvlCodewds; + UCHAR direction = pRvlc->direction; + INT *pBitstrIndxRvl = pRvlc->pBitstrIndxRvl_RVL; + UINT treeNode = *pRvlCodeTree; + + for (i = MAX_LEN_RVLC_CODE_WORD - 1; i >= 0; i--) { + carryBit = + rvlcReadBitFromBitstream(bs, /* get next bit */ + pRvlc->bsAnchor, pBitstrIndxRvl, direction); + + CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in + huffman decoding tree */ + treeNode, &branchValue, &branchNode); + + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set --> a + RVLC-codeword is completely decoded + */ + value = (SCHAR)(branchNode & CLR_BIT_10); + *pRvlc->pRvlBitCnt_RVL -= (MAX_LEN_RVLC_CODE_WORD - i); + + /* check available bits for decoding */ + if (*pRvlc->pRvlBitCnt_RVL < 0) { + if (direction == FWD) { + pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_FWD; + } else { + pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_BWD; + } + value = -1; /* signalize an error in return value, because too many bits + was decoded */ + } + + /* check max value of dpcm value */ + if (value > MAX_ALLOWED_DPCM_INDEX) { + if (direction == FWD) { + pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD; + } else { + pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD; + } + value = -1; /* signalize an error in return value, because a forbidden + cw was detected*/ + } + + return value; /* return a dpcm value with offset +7 or an error status */ + } else { + treeNode = *( + pRvlCodeTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + + return -1; +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeForward + + description: Decode RVL-coded codewords in forward direction. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - handle to FDK bitstream +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcDecodeForward(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + int band = 0; + int group = 0; + int bnds = 0; + + SHORT dpcm; + + SHORT factor = + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET; + SHORT position = -SF_OFFSET; + SHORT noisenrg = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - + SF_OFFSET - 90 - 256; + + SHORT *pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd; + SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc; + UCHAR *pEscFwdCnt = &(pRvlc->numDecodedEscapeWordsFwd); + + pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_fwd); + pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlFwd); + + *pEscFwdCnt = 0; + pRvlc->direction = FWD; + pRvlc->noise_used = 0; + pRvlc->sf_used = 0; + pRvlc->lastScf = 0; + pRvlc->lastNrg = 0; + pRvlc->lastIs = 0; + + rvlcCheckIntensityCb(pRvlc, pAacDecoderChannelInfo); + + /* main loop fwd long */ + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pScfFwd[bnds] = 0; + break; + + case INTENSITY_HCB2: + case INTENSITY_HCB: + /* store dpcm_is_position */ + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + position += dpcm; + pScfFwd[bnds] = position; + pRvlc->lastIs = position; + break; + + case NOISE_HCB: + if (pRvlc->noise_used == 0) { + pRvlc->noise_used = 1; + pRvlc->first_noise_band = bnds; + noisenrg += pRvlc->dpcm_noise_nrg; + pScfFwd[bnds] = 100 + noisenrg; + pRvlc->lastNrg = noisenrg; + } else { + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + noisenrg += dpcm; + pScfFwd[bnds] = 100 + noisenrg; + pRvlc->lastNrg = noisenrg; + } + pAacDecoderChannelInfo->data.aac.PnsData.pnsUsed[bnds] = 1; + break; + + default: + pRvlc->sf_used = 1; + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + factor += dpcm; + pScfFwd[bnds] = factor; + pRvlc->lastScf = factor; + break; + } + } + } + + /* postfetch fwd long */ + if (pRvlc->intensity_used) { + dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */ + if (dpcm < 0) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + pRvlc->dpcm_is_last_position = dpcm; + } +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeBackward + + description: Decode RVL-coded codewords in backward direction. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - handle FDK bitstream +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcDecodeBackward(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + SHORT band, group, dpcm, offset; + SHORT bnds = pRvlc->maxSfbTransmitted - 1; + + SHORT factor = pRvlc->rev_global_gain - SF_OFFSET; + SHORT position = pRvlc->dpcm_is_last_position - SF_OFFSET; + SHORT noisenrg = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - + SF_OFFSET - 90 - 256; + + SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd; + SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc; + UCHAR escEscCnt = pRvlc->numDecodedEscapeWordsEsc; + UCHAR *pEscBwdCnt = &(pRvlc->numDecodedEscapeWordsBwd); + + pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_bwd); + pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlBwd); + + *pEscBwdCnt = 0; + pRvlc->direction = BWD; + pScfEsc += escEscCnt - 1; /* set pScfEsc to last entry */ + pRvlc->firstScf = 0; + pRvlc->firstNrg = 0; + pRvlc->firstIs = 0; + + /* prefetch long BWD */ + if (pRvlc->intensity_used) { + dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */ + if (dpcm < 0) { + pRvlc->dpcm_is_last_position = 0; + pRvlc->conceal_min = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if ((pRvlc->length_of_rvlc_escapes) || (*pEscBwdCnt >= escEscCnt)) { + pRvlc->conceal_min = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = bnds; + } + } + } + pRvlc->dpcm_is_last_position = dpcm; + } + + /* main loop long BWD */ + for (group = pRvlc->numWindowGroups - 1; group >= 0; group--) { + for (band = pRvlc->maxSfbTransmitted - 1; band >= 0; band--) { + bnds = 16 * group + band; + if ((band == 0) && (pRvlc->numWindowGroups != 1)) + offset = 16 - pRvlc->maxSfbTransmitted + 1; + else + offset = 1; + + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pScfBwd[bnds] = 0; + break; + + case INTENSITY_HCB2: + case INTENSITY_HCB: + /* store dpcm_is_position */ + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pScfBwd[bnds] = position; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if ((pRvlc->length_of_rvlc_escapes) || (*pEscBwdCnt >= escEscCnt)) { + pScfBwd[bnds] = position; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = fMax(0, bnds - offset); + } + } + } + pScfBwd[bnds] = position; + position -= dpcm; + pRvlc->firstIs = position; + break; + + case NOISE_HCB: + if (bnds == pRvlc->first_noise_band) { + pScfBwd[bnds] = + pRvlc->dpcm_noise_nrg + + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - + SF_OFFSET - 90 - 256; + pRvlc->firstNrg = pScfBwd[bnds]; + } else { + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pScfBwd[bnds] = noisenrg; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if ((pRvlc->length_of_rvlc_escapes) || + (*pEscBwdCnt >= escEscCnt)) { + pScfBwd[bnds] = noisenrg; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = fMax(0, bnds - offset); + } + } + } + pScfBwd[bnds] = noisenrg; + noisenrg -= dpcm; + pRvlc->firstNrg = noisenrg; + } + break; + + default: + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pScfBwd[bnds] = factor; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if ((pRvlc->length_of_rvlc_escapes) || (*pEscBwdCnt >= escEscCnt)) { + pScfBwd[bnds] = factor; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = fMax(0, bnds - offset); + } + } + } + pScfBwd[bnds] = factor; + factor -= dpcm; + pRvlc->firstScf = factor; + break; + } + } + } +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcFinalErrorDetection + + description: Call RVLC concealment if error was detected in decoding +process +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcFinalErrorDetection( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + UCHAR ErrorStatusComplete = 0; + UCHAR ErrorStatusLengthFwd = 0; + UCHAR ErrorStatusLengthBwd = 0; + UCHAR ErrorStatusLengthEscapes = 0; + UCHAR ErrorStatusFirstScf = 0; + UCHAR ErrorStatusLastScf = 0; + UCHAR ErrorStatusFirstNrg = 0; + UCHAR ErrorStatusLastNrg = 0; + UCHAR ErrorStatusFirstIs = 0; + UCHAR ErrorStatusLastIs = 0; + UCHAR ErrorStatusForbiddenCwFwd = 0; + UCHAR ErrorStatusForbiddenCwBwd = 0; + UCHAR ErrorStatusNumEscapesFwd = 0; + UCHAR ErrorStatusNumEscapesBwd = 0; + UCHAR ConcealStatus = 1; + UCHAR currentBlockType; /* short: 0, not short: 1*/ + + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 1; + + /* invalid escape words, bit counter unequal zero, forbidden codeword detected + */ + if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD) + ErrorStatusForbiddenCwFwd = 1; + + if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD) + ErrorStatusForbiddenCwBwd = 1; + + /* bit counter forward unequal zero */ + if (pRvlc->length_of_rvlc_sf_fwd) ErrorStatusLengthFwd = 1; + + /* bit counter backward unequal zero */ + if (pRvlc->length_of_rvlc_sf_bwd) ErrorStatusLengthBwd = 1; + + /* bit counter escape sequences unequal zero */ + if (pRvlc->sf_escapes_present) + if (pRvlc->length_of_rvlc_escapes) ErrorStatusLengthEscapes = 1; + + if (pRvlc->sf_used) { + /* first decoded scf does not match to global gain in backward direction */ + if (pRvlc->firstScf != + (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET)) + ErrorStatusFirstScf = 1; + + /* last decoded scf does not match to rev global gain in forward direction + */ + if (pRvlc->lastScf != (pRvlc->rev_global_gain - SF_OFFSET)) + ErrorStatusLastScf = 1; + } + + if (pRvlc->noise_used) { + /* first decoded nrg does not match to dpcm_noise_nrg in backward direction + */ + if (pRvlc->firstNrg != + (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain + + pRvlc->dpcm_noise_nrg - SF_OFFSET - 90 - 256)) + ErrorStatusFirstNrg = 1; + + /* last decoded nrg does not match to dpcm_noise_last_position in forward + * direction */ + if (pRvlc->lastNrg != + (pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - + 90 - 256)) + ErrorStatusLastNrg = 1; + } + + if (pRvlc->intensity_used) { + /* first decoded is position does not match in backward direction */ + if (pRvlc->firstIs != (-SF_OFFSET)) ErrorStatusFirstIs = 1; + + /* last decoded is position does not match in forward direction */ + if (pRvlc->lastIs != (pRvlc->dpcm_is_last_position - SF_OFFSET)) + ErrorStatusLastIs = 1; + } + + /* decoded escapes and used escapes in forward direction do not fit */ + if ((pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc) && + (pRvlc->conceal_max == CONCEAL_MAX_INIT)) { + ErrorStatusNumEscapesFwd = 1; + } + + /* decoded escapes and used escapes in backward direction do not fit */ + if ((pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc) && + (pRvlc->conceal_min == CONCEAL_MIN_INIT)) { + ErrorStatusNumEscapesBwd = 1; + } + + if (ErrorStatusLengthEscapes || + (((pRvlc->conceal_max == CONCEAL_MAX_INIT) && + (pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc) && + (ErrorStatusLastScf || ErrorStatusLastNrg || ErrorStatusLastIs)) + + && + + ((pRvlc->conceal_min == CONCEAL_MIN_INIT) && + (pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc) && + (ErrorStatusFirstScf || ErrorStatusFirstNrg || ErrorStatusFirstIs))) || + ((pRvlc->conceal_max == CONCEAL_MAX_INIT) && + ((pRvlc->rev_global_gain - SF_OFFSET - pRvlc->lastScf) < -15)) || + ((pRvlc->conceal_min == CONCEAL_MIN_INIT) && + ((pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - + pRvlc->firstScf) < -15))) { + if ((pRvlc->conceal_max == CONCEAL_MAX_INIT) || + (pRvlc->conceal_min == CONCEAL_MIN_INIT)) { + pRvlc->conceal_max = 0; + pRvlc->conceal_min = fMax( + 0, (pRvlc->numWindowGroups - 1) * 16 + pRvlc->maxSfbTransmitted - 1); + } else { + pRvlc->conceal_max = fMin(pRvlc->conceal_max, pRvlc->conceal_max_esc); + pRvlc->conceal_min = fMax(pRvlc->conceal_min, pRvlc->conceal_min_esc); + } + } + + ErrorStatusComplete = ErrorStatusLastScf || ErrorStatusFirstScf || + ErrorStatusLastNrg || ErrorStatusFirstNrg || + ErrorStatusLastIs || ErrorStatusFirstIs || + ErrorStatusForbiddenCwFwd || + ErrorStatusForbiddenCwBwd || ErrorStatusLengthFwd || + ErrorStatusLengthBwd || ErrorStatusLengthEscapes || + ErrorStatusNumEscapesFwd || ErrorStatusNumEscapesBwd; + + currentBlockType = + (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) ? 0 + : 1; + + if (!ErrorStatusComplete) { + int band; + int group; + int bnds; + int lastSfbIndex; + + lastSfbIndex = (pRvlc->numWindowGroups > 1) ? 16 : 64; + + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + } + } + + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] = + pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]; + } + for (; band < lastSfbIndex; band++) { + bnds = 16 * group + band; + FDK_ASSERT(bnds >= 0 && bnds < RVLC_MAX_SFB); + pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] = ZERO_HCB; + } + } + } else { + int band; + int group; + + /* A single bit error was detected in decoding of dpcm values. It also could + be an error with more bits in decoding of escapes and dpcm values whereby + an illegal codeword followed not directly after the corrupted bits but + just after decoding some more (wrong) scalefactors. Use the smaller + scalefactor from forward decoding, backward decoding and previous frame. + */ + if (((pRvlc->conceal_min != CONCEAL_MIN_INIT) || + (pRvlc->conceal_max != CONCEAL_MAX_INIT)) && + (pRvlc->conceal_min <= pRvlc->conceal_max) && + (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == + currentBlockType) && + pAacDecoderStaticChannelInfo->concealmentInfo + .rvlcPreviousScaleFactorOK && + pRvlc->sf_concealment && ConcealStatus) { + BidirectionalEstimation_UseScfOfPrevFrameAsReference( + pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo); + ConcealStatus = 0; + } + + /* A single bit error was detected in decoding of dpcm values. It also could + be an error with more bits in decoding of escapes and dpcm values whereby + an illegal codeword followed not directly after the corrupted bits but + just after decoding some more (wrong) scalefactors. Use the smaller + scalefactor from forward and backward decoding. */ + if ((pRvlc->conceal_min <= pRvlc->conceal_max) && + ((pRvlc->conceal_min != CONCEAL_MIN_INIT) || + (pRvlc->conceal_max != CONCEAL_MAX_INIT)) && + !(pAacDecoderStaticChannelInfo->concealmentInfo + .rvlcPreviousScaleFactorOK && + pRvlc->sf_concealment && + (pAacDecoderStaticChannelInfo->concealmentInfo + .rvlcPreviousBlockType == currentBlockType)) && + ConcealStatus) { + BidirectionalEstimation_UseLowerScfOfCurrentFrame(pAacDecoderChannelInfo); + ConcealStatus = 0; + } + + /* No errors were detected in decoding of escapes and dpcm values however + the first and last value of a group (is,nrg,sf) is incorrect */ + if ((pRvlc->conceal_min <= pRvlc->conceal_max) && + ((ErrorStatusLastScf && ErrorStatusFirstScf) || + (ErrorStatusLastNrg && ErrorStatusFirstNrg) || + (ErrorStatusLastIs && ErrorStatusFirstIs)) && + !(ErrorStatusForbiddenCwFwd || ErrorStatusForbiddenCwBwd || + ErrorStatusLengthEscapes) && + ConcealStatus) { + StatisticalEstimation(pAacDecoderChannelInfo); + ConcealStatus = 0; + } + + /* A error with more bits in decoding of escapes and dpcm values was + detected. Use the smaller scalefactor from forward decoding, backward + decoding and previous frame. */ + if ((pRvlc->conceal_min <= pRvlc->conceal_max) && + pAacDecoderStaticChannelInfo->concealmentInfo + .rvlcPreviousScaleFactorOK && + pRvlc->sf_concealment && + (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == + currentBlockType) && + ConcealStatus) { + PredictiveInterpolation(pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo); + ConcealStatus = 0; + } + + /* Call frame concealment, because no better strategy was found. Setting the + scalefactors to zero is done for debugging purposes */ + if (ConcealStatus) { + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + pAacDecoderChannelInfo->pDynData->aScaleFactor[16 * group + band] = 0; + } + } + pAacDecoderChannelInfo->pDynData->specificTo.aac + .rvlcCurrentScaleFactorOK = 0; + } + } +} + +/*--------------------------------------------------------------------------------------------- + function: CRvlc_Read + + description: Read RVLC ESC1 data (side info) from bitstream. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - pointer bitstream structure +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +void CRvlc_Read(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + + int group, band; + + /* RVLC long specific initialization Init part 1 of 2 */ + pRvlc->numWindowGroups = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + pRvlc->maxSfbTransmitted = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + pRvlc->noise_used = 0; /* noise detection */ + pRvlc->dpcm_noise_nrg = 0; /* only for debugging */ + pRvlc->dpcm_noise_last_position = 0; /* only for debugging */ + pRvlc->length_of_rvlc_escapes = + -1; /* default value is used for error detection and concealment */ + + /* read only error sensitivity class 1 data (ESC 1 - data) */ + pRvlc->sf_concealment = FDKreadBits(bs, 1); /* #1 */ + pRvlc->rev_global_gain = FDKreadBits(bs, 8); /* #2 */ + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) { + pRvlc->length_of_rvlc_sf = FDKreadBits(bs, 11); /* #3 */ + } else { + pRvlc->length_of_rvlc_sf = FDKreadBits(bs, 9); /* #3 */ + } + + /* check if noise codebook is used */ + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + if (pAacDecoderChannelInfo->pDynData->aCodeBook[16 * group + band] == + NOISE_HCB) { + pRvlc->noise_used = 1; + break; + } + } + } + + if (pRvlc->noise_used) + pRvlc->dpcm_noise_nrg = FDKreadBits(bs, 9); /* #4 PNS */ + + pRvlc->sf_escapes_present = FDKreadBits(bs, 1); /* #5 */ + + if (pRvlc->sf_escapes_present) { + pRvlc->length_of_rvlc_escapes = FDKreadBits(bs, 8); /* #6 */ + } + + if (pRvlc->noise_used) { + pRvlc->dpcm_noise_last_position = FDKreadBits(bs, 9); /* #7 PNS */ + pRvlc->length_of_rvlc_sf -= 9; + } + + pRvlc->length_of_rvlc_sf_fwd = pRvlc->length_of_rvlc_sf; + pRvlc->length_of_rvlc_sf_bwd = pRvlc->length_of_rvlc_sf; +} + +/*--------------------------------------------------------------------------------------------- + function: CRvlc_Decode + + description: Decode rvlc data + The function reads both the escape sequences and the +scalefactors in forward and backward direction. If an error occured during +decoding process which can not be concealed with the rvlc concealment frame +concealment will be initiated. Then the element "rvlcCurrentScaleFactorOK" in +the decoder channel info is set to 0 otherwise it is set to 1. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - pointer to persistent channel info structure + - pointer bitstream structure +----------------------------------------------------------------------------------------------- + return: ErrorStatus = AAC_DEC_OK +-------------------------------------------------------------------------------------------- +*/ + +void CRvlc_Decode(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + INT bitCntOffst; + INT saveBitCnt; + + rvlcInit(pRvlc, pAacDecoderChannelInfo, bs); + + /* save bitstream position */ + saveBitCnt = (INT)FDKgetValidBits(bs); + + if (pRvlc->sf_escapes_present) + rvlcDecodeEscapes( + pRvlc, pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc, bs); + + rvlcDecodeForward(pRvlc, pAacDecoderChannelInfo, bs); + rvlcDecodeBackward(pRvlc, pAacDecoderChannelInfo, bs); + rvlcFinalErrorDetection(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo); + + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = + pRvlc->intensity_used; + pAacDecoderChannelInfo->data.aac.PnsData.PnsActive = pRvlc->noise_used; + + /* restore bitstream position */ + bitCntOffst = (INT)FDKgetValidBits(bs) - saveBitCnt; + if (bitCntOffst) { + FDKpushBiDirectional(bs, bitCntOffst); + } +} + +void CRvlc_ElementCheck( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + const UINT flags, const INT elChannels) { + int ch; + + /* Required for MPS residuals. */ + if (pAacDecoderStaticChannelInfo == NULL) { + return; + } + + /* RVLC specific sanity checks */ + if ((flags & AC_ER_RVLC) && (elChannels == 2)) { /* to be reviewed */ + if (((pAacDecoderChannelInfo[0] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) || + (pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0)) && + pAacDecoderChannelInfo[0]->pComData->jointStereoData.MsMaskPresent) { + pAacDecoderChannelInfo[0] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; + pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; + } + + if ((pAacDecoderChannelInfo[0] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) && + (pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 1) && + (pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcIntensityUsed == 1)) { + pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; + } + } + + for (ch = 0; ch < elChannels; ch++) { + pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousBlockType = + (GetWindowSequence(&pAacDecoderChannelInfo[ch]->icsInfo) == BLOCK_SHORT) + ? 0 + : 1; + if (flags & AC_ER_RVLC) { + pAacDecoderStaticChannelInfo[ch] + ->concealmentInfo.rvlcPreviousScaleFactorOK = + pAacDecoderChannelInfo[ch] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK; + } else { + pAacDecoderStaticChannelInfo[ch] + ->concealmentInfo.rvlcPreviousScaleFactorOK = 0; + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlc.h new file mode 100644 index 0000000000000..9c60d519a74b1 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlc.h @@ -0,0 +1,153 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Defines structures and prototypes for RVLC + \author Robert Weidner +*/ + +#ifndef RVLC_H +#define RVLC_H + +#include "aacdecoder.h" +#include "channel.h" +#include "rvlc_info.h" + +/* ------------------------------------------------------------------- */ +/* errorLogRvlc: A word of 32 bits used for logging possible errors */ +/* within RVLC in case of distorted bitstreams. */ +/* ------------------------------------------------------------------- */ +#define RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID \ + 0x80000000 /* ESC-Dec During RVLC-Escape-decoding there have been more \ + bits decoded as there are available */ +#define RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_FWD \ + 0x40000000 /* RVL-Dec negative sum-bitcounter during RVL-fwd-decoding \ + (long+shrt) */ +#define RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_BWD \ + 0x20000000 /* RVL-Dec negative sum-bitcounter during RVL-fwd-decoding \ + (long+shrt) */ +#define RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD \ + 0x08000000 /* RVL-Dec forbidden codeword detected fwd (long+shrt) */ +#define RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD \ + 0x04000000 /* RVL-Dec forbidden codeword detected bwd (long+shrt) */ + +void CRvlc_Read(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs); + +void CRvlc_Decode(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + HANDLE_FDK_BITSTREAM bs); + +/** + * \brief performe sanity checks to the channel data corresponding to one + * channel element. + * \param pAacDecoderChannelInfo + * \param pAacDecoderStaticChannelInfo + * \param elChannels amount of channels of the channel element. + */ +void CRvlc_ElementCheck( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + const UINT flags, const INT elChannels); + +#endif /* RVLC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlc_info.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlc_info.h new file mode 100644 index 0000000000000..e7b3b999185a7 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlc_info.h @@ -0,0 +1,204 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Defines structures for RVLC + \author Robert Weidner +*/ +#ifndef RVLC_INFO_H +#define RVLC_INFO_H + +#define FWD 0 /* bitstream decoding direction forward (RVL coded part) */ +#define BWD 1 /* bitstream decoding direction backward (RVL coded part) */ + +#define MAX_RVL 7 /* positive RVLC escape */ +#define MIN_RVL -7 /* negative RVLC escape */ +#define MAX_ALLOWED_DPCM_INDEX \ + 14 /* the maximum allowed index of a decoded dpcm value (offset \ + 'TABLE_OFFSET' incl --> must be subtracted) */ +#define TABLE_OFFSET \ + 7 /* dpcm offset of valid output values of rvl table decoding, the rvl table \ + ouly returns positive values, therefore the offset */ +#define MAX_LEN_RVLC_CODE_WORD 9 /* max length of a RVL codeword in bits */ +#define MAX_LEN_RVLC_ESCAPE_WORD \ + 20 /* max length of huffman coded RVLC escape word in bits */ + +#define DPCM_NOISE_NRG_BITS 9 +#define SF_OFFSET 100 /* offset for correcting scf value */ + +#define CONCEAL_MAX_INIT 1311 /* arbitrary value */ +#define CONCEAL_MIN_INIT -1311 /* arbitrary value */ + +#define RVLC_MAX_SFB ((8) * (16)) + +/* sideinfo of RVLC */ +typedef struct { + /* ------- ESC 1 Data: --------- */ /* order of RVLC-bitstream components in + bitstream (RVLC-initialization), every + component appears only once in + bitstream */ + INT sf_concealment; /* 1 */ + INT rev_global_gain; /* 2 */ + SHORT length_of_rvlc_sf; /* 3 */ /* original value, gets modified + (subtract 9) in case of noise + (PNS); is kept for later use */ + INT dpcm_noise_nrg; /* 4 optional */ + INT sf_escapes_present; /* 5 */ + SHORT length_of_rvlc_escapes; /* 6 optional */ + INT dpcm_noise_last_position; /* 7 optional */ + + INT dpcm_is_last_position; + + SHORT length_of_rvlc_sf_fwd; /* length_of_rvlc_sf used for forward decoding */ + SHORT + length_of_rvlc_sf_bwd; /* length_of_rvlc_sf used for backward decoding */ + + /* for RVL-Codeword decoder to distinguish between fwd and bwd decoding */ + SHORT *pRvlBitCnt_RVL; + INT *pBitstrIndxRvl_RVL; + + UCHAR numWindowGroups; + UCHAR maxSfbTransmitted; + UCHAR first_noise_group; + UCHAR first_noise_band; + UCHAR direction; + + /* bitstream indices */ + INT bsAnchor; /* hcr bit buffer reference index */ + INT bitstreamIndexRvlFwd; /* base address of RVL-coded-scalefactor data (ESC + 2) for forward decoding */ + INT bitstreamIndexRvlBwd; /* base address of RVL-coded-scalefactor data (ESC + 2) for backward decoding */ + INT bitstreamIndexEsc; /* base address where RVLC-escapes start (ESC 2) */ + + /* decoding trees */ + const UINT *pHuffTreeRvlCodewds; + const UINT *pHuffTreeRvlcEscape; + + /* escape counters */ + UCHAR numDecodedEscapeWordsFwd; /* when decoding RVL-codes forward */ + UCHAR numDecodedEscapeWordsBwd; /* when decoding RVL-codes backward */ + UCHAR numDecodedEscapeWordsEsc; /* when decoding the escape-Words */ + + SCHAR noise_used; + SCHAR intensity_used; + SCHAR sf_used; + + SHORT firstScf; + SHORT lastScf; + SHORT firstNrg; + SHORT lastNrg; + SHORT firstIs; + SHORT lastIs; + + /* ------ RVLC error detection ------ */ + UINT errorLogRvlc; /* store RVLC errors */ + SHORT conceal_min; /* is set at backward decoding */ + SHORT conceal_max; /* is set at forward decoding */ + SHORT conceal_min_esc; /* is set at backward decoding */ + SHORT conceal_max_esc; /* is set at forward decoding */ +} CErRvlcInfo; + +typedef CErRvlcInfo RVLC_INFO; /* temp */ + +#endif /* RVLC_INFO_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcbit.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcbit.cpp new file mode 100644 index 0000000000000..b0c4596f33a8a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcbit.cpp @@ -0,0 +1,148 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief RVLC bitstream reading + \author Robert Weidner +*/ + +#include "rvlcbit.h" + +/*--------------------------------------------------------------------------------------------- + function: rvlcReadBitFromBitstream + + description: This function returns a bit from the bitstream according to +read direction. It is called very often, therefore it makes sense to inline it +(runtime). +----------------------------------------------------------------------------------------------- + input: - bitstream + - pPosition + - readDirection +----------------------------------------------------------------------------------------------- + return: - bit from bitstream +-------------------------------------------------------------------------------------------- +*/ + +UCHAR rvlcReadBitFromBitstream(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + INT *pPosition, UCHAR readDirection) { + UINT bit; + INT readBitOffset = (INT)FDKgetValidBits(bs) - bsAnchor + *pPosition; + + if (readBitOffset) { + FDKpushBiDirectional(bs, readBitOffset); + } + + if (readDirection == FWD) { + bit = FDKreadBits(bs, 1); + + *pPosition += 1; + } else { + /* to be replaced with a brother function of FDKreadBits() */ + bit = FDKreadBits(bs, 1); + FDKpushBack(bs, 2); + + *pPosition -= 1; + } + + return (bit); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcbit.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcbit.h new file mode 100644 index 0000000000000..2578453424d29 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcbit.h @@ -0,0 +1,111 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: RVLC Decoder: Bitstream reading + +*******************************************************************************/ + +#ifndef RVLCBIT_H +#define RVLCBIT_H + +#include "rvlc.h" + +UCHAR rvlcReadBitFromBitstream(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + INT *pPosition, UCHAR readDirection); + +#endif /* RVLCBIT_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcconceal.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcconceal.cpp new file mode 100644 index 0000000000000..77fda6819144f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcconceal.cpp @@ -0,0 +1,787 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief rvlc concealment + \author Josef Hoepfl +*/ + +#include "rvlcconceal.h" + +#include "block.h" +#include "rvlc.h" + +/*--------------------------------------------------------------------------------------------- + function: calcRefValFwd + + description: The function determines the scalefactor which is closed to the +scalefactorband conceal_min. The same is done for intensity data and noise +energies. +----------------------------------------------------------------------------------------------- + output: - reference value scf + - reference value internsity data + - reference value noise energy +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void calcRefValFwd(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + int *refIsFwd, int *refNrgFwd, int *refScfFwd) { + int band, bnds, group, startBand; + int idIs, idNrg, idScf; + int conceal_min, conceal_group_min; + int MaximumScaleFactorBands; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) + MaximumScaleFactorBands = 16; + else + MaximumScaleFactorBands = 64; + + conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands; + conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands; + + /* calculate first reference value for approach in forward direction */ + idIs = idNrg = idScf = 1; + + /* set reference values */ + *refIsFwd = -SF_OFFSET; + *refNrgFwd = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - + SF_OFFSET - 90 - 256; + *refScfFwd = + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET; + + startBand = conceal_min - 1; + for (group = conceal_group_min; group >= 0; group--) { + for (band = startBand; band >= 0; band--) { + bnds = 16 * group + band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (idIs) { + *refIsFwd = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + idIs = 0; /* reference value has been set */ + } + break; + case NOISE_HCB: + if (idNrg) { + *refNrgFwd = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + idNrg = 0; /* reference value has been set */ + } + break; + default: + if (idScf) { + *refScfFwd = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + idScf = 0; /* reference value has been set */ + } + break; + } + } + startBand = pRvlc->maxSfbTransmitted - 1; + } +} + +/*--------------------------------------------------------------------------------------------- + function: calcRefValBwd + + description: The function determines the scalefactor which is closed to the +scalefactorband conceal_max. The same is done for intensity data and noise +energies. +----------------------------------------------------------------------------------------------- + output: - reference value scf + - reference value internsity data + - reference value noise energy +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void calcRefValBwd(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + int *refIsBwd, int *refNrgBwd, int *refScfBwd) { + int band, bnds, group, startBand; + int idIs, idNrg, idScf; + int conceal_max, conceal_group_max; + int MaximumScaleFactorBands; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) + MaximumScaleFactorBands = 16; + else + MaximumScaleFactorBands = 64; + + conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands; + conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands; + + /* calculate first reference value for approach in backward direction */ + idIs = idNrg = idScf = 1; + + /* set reference values */ + *refIsBwd = pRvlc->dpcm_is_last_position - SF_OFFSET; + *refNrgBwd = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - + SF_OFFSET - 90 - 256 + pRvlc->dpcm_noise_nrg; + *refScfBwd = pRvlc->rev_global_gain - SF_OFFSET; + + startBand = conceal_max + 1; + + /* if needed, re-set reference values */ + for (group = conceal_group_max; group < pRvlc->numWindowGroups; group++) { + for (band = startBand; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (idIs) { + *refIsBwd = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + idIs = 0; /* reference value has been set */ + } + break; + case NOISE_HCB: + if (idNrg) { + *refNrgBwd = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + idNrg = 0; /* reference value has been set */ + } + break; + default: + if (idScf) { + *refScfBwd = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + idScf = 0; /* reference value has been set */ + } + break; + } + } + startBand = 0; + } +} + +/*--------------------------------------------------------------------------------------------- + function: BidirectionalEstimation_UseLowerScfOfCurrentFrame + + description: This approach by means of bidirectional estimation is generally +performed when a single bit error has been detected, the bit error can be +isolated between 'conceal_min' and 'conceal_max' and the 'sf_concealment' flag +is not set. The sets of scalefactors decoded in forward and backward direction +are compared with each other. The smaller scalefactor will be considered as the +correct one respectively. The reconstruction of the scalefactors with this +approach archieve good results in audio quality. The strategy must be applied to +scalefactors, intensity data and noise energy seperately. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data between +conceal_min and conceal_max +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +void BidirectionalEstimation_UseLowerScfOfCurrentFrame( + CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band, bnds, startBand, endBand, group; + int conceal_min, conceal_max; + int conceal_group_min, conceal_group_max; + int MaximumScaleFactorBands; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) { + MaximumScaleFactorBands = 16; + } else { + MaximumScaleFactorBands = 64; + } + + /* If an error was detected just in forward or backward direction, set the + corresponding border for concealment to a appropriate scalefactor band. The + border is set to first or last sfb respectively, because the error will + possibly not follow directly after the corrupt bit but just after decoding + some more (wrong) scalefactors. */ + if (pRvlc->conceal_min == CONCEAL_MIN_INIT) pRvlc->conceal_min = 0; + + if (pRvlc->conceal_max == CONCEAL_MAX_INIT) + pRvlc->conceal_max = + (pRvlc->numWindowGroups - 1) * 16 + pRvlc->maxSfbTransmitted - 1; + + conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands; + conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands; + conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands; + conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands; + + if (pRvlc->conceal_min == pRvlc->conceal_max) { + int refIsFwd, refNrgFwd, refScfFwd; + int refIsBwd, refNrgBwd, refScfBwd; + + bnds = pRvlc->conceal_min; + calcRefValFwd(pRvlc, pAacDecoderChannelInfo, &refIsFwd, &refNrgFwd, + &refScfFwd); + calcRefValBwd(pRvlc, pAacDecoderChannelInfo, &refIsBwd, &refNrgBwd, + &refScfBwd); + + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (refIsFwd < refIsBwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refIsFwd; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refIsBwd; + break; + case NOISE_HCB: + if (refNrgFwd < refNrgBwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refNrgFwd; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refNrgBwd; + break; + default: + if (refScfFwd < refScfBwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refScfFwd; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refScfBwd; + break; + } + } else { + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfFwd[pRvlc->conceal_max] = + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[pRvlc->conceal_max]; + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[pRvlc->conceal_min] = + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfFwd[pRvlc->conceal_min]; + + /* consider the smaller of the forward and backward decoded value as the + * correct one */ + startBand = conceal_min; + if (conceal_group_min == conceal_group_max) + endBand = conceal_max; + else + endBand = pRvlc->maxSfbTransmitted - 1; + + for (group = conceal_group_min; group <= conceal_group_max; group++) { + for (band = startBand; band <= endBand; band++) { + bnds = 16 * group + band; + if (pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds] < + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + } + startBand = 0; + if ((group + 1) == conceal_group_max) endBand = conceal_max; + } + } + + /* now copy all data to the output buffer which needs not to be concealed */ + if (conceal_group_min == 0) + endBand = conceal_min; + else + endBand = pRvlc->maxSfbTransmitted; + for (group = 0; group <= conceal_group_min; group++) { + for (band = 0; band < endBand; band++) { + bnds = 16 * group + band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + } + if ((group + 1) == conceal_group_min) endBand = conceal_min; + } + + startBand = conceal_max + 1; + for (group = conceal_group_max; group < pRvlc->numWindowGroups; group++) { + for (band = startBand; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + } + startBand = 0; + } +} + +/*--------------------------------------------------------------------------------------------- + function: BidirectionalEstimation_UseScfOfPrevFrameAsReference + + description: This approach by means of bidirectional estimation is generally +performed when a single bit error has been detected, the bit error can be +isolated between 'conceal_min' and 'conceal_max', the 'sf_concealment' flag is +set and the previous frame has the same block type as the current frame. The +scalefactor decoded in forward and backward direction and the scalefactor of the +previous frame are compared with each other. The smaller scalefactor will be +considered as the correct one. At this the codebook of the previous and current +frame must be of the same set (scf, nrg, is) in each scalefactorband. Otherwise +the scalefactor of the previous frame is not considered in the minimum +calculation. The reconstruction of the scalefactors with this approach archieve +good results in audio quality. The strategy must be applied to scalefactors, +intensity data and noise energy seperately. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data between +conceal_min and conceal_max +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +void BidirectionalEstimation_UseScfOfPrevFrameAsReference( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band, bnds, startBand, endBand, group; + int conceal_min, conceal_max; + int conceal_group_min, conceal_group_max; + int MaximumScaleFactorBands; + SHORT commonMin; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) { + MaximumScaleFactorBands = 16; + } else { + MaximumScaleFactorBands = 64; + } + + /* If an error was detected just in forward or backward direction, set the + corresponding border for concealment to a appropriate scalefactor band. The + border is set to first or last sfb respectively, because the error will + possibly not follow directly after the corrupt bit but just after decoding + some more (wrong) scalefactors. */ + if (pRvlc->conceal_min == CONCEAL_MIN_INIT) pRvlc->conceal_min = 0; + + if (pRvlc->conceal_max == CONCEAL_MAX_INIT) + pRvlc->conceal_max = + (pRvlc->numWindowGroups - 1) * 16 + pRvlc->maxSfbTransmitted - 1; + + conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands; + conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands; + conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands; + conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands; + + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfFwd[pRvlc->conceal_max] = + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[pRvlc->conceal_max]; + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[pRvlc->conceal_min] = + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfFwd[pRvlc->conceal_min]; + + /* consider the smaller of the forward and backward decoded value as the + * correct one */ + startBand = conceal_min; + if (conceal_group_min == conceal_group_max) + endBand = conceal_max; + else + endBand = pRvlc->maxSfbTransmitted - 1; + + for (group = conceal_group_min; group <= conceal_group_max; group++) { + for (band = startBand; band <= endBand; band++) { + bnds = 16 * group + band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0; + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + if ((pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] == INTENSITY_HCB) || + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] == INTENSITY_HCB2)) { + commonMin = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + fMin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + } + break; + + case NOISE_HCB: + if (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] == NOISE_HCB) { + commonMin = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + fMin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + } + break; + + default: + if ((pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != ZERO_HCB) && + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != NOISE_HCB) && + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != INTENSITY_HCB) && + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != INTENSITY_HCB2)) { + commonMin = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + fMin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + } + break; + } + } + startBand = 0; + if ((group + 1) == conceal_group_max) endBand = conceal_max; + } + + /* now copy all data to the output buffer which needs not to be concealed */ + if (conceal_group_min == 0) + endBand = conceal_min; + else + endBand = pRvlc->maxSfbTransmitted; + for (group = 0; group <= conceal_group_min; group++) { + for (band = 0; band < endBand; band++) { + bnds = 16 * group + band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + } + if ((group + 1) == conceal_group_min) endBand = conceal_min; + } + + startBand = conceal_max + 1; + for (group = conceal_group_max; group < pRvlc->numWindowGroups; group++) { + for (band = startBand; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + } + startBand = 0; + } +} + +/*--------------------------------------------------------------------------------------------- + function: StatisticalEstimation + + description: This approach by means of statistical estimation is generally +performed when both the start value and the end value are different and no +further errors have been detected. Considering the forward and backward decoded +scalefactors, the set with the lower scalefactors in sum will be considered as +the correct one. The scalefactors are differentially encoded. Normally it would +reach to compare one pair of the forward and backward decoded scalefactors to +specify the lower set. But having detected no further errors does not +necessarily mean the absence of errors. Therefore all scalefactors decoded in +forward and backward direction are summed up seperately. The set with the lower +sum will be used. The strategy must be applied to scalefactors, intensity data +and noise energy seperately. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +void StatisticalEstimation(CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band, bnds, group; + int sumIsFwd, sumIsBwd; /* sum of intensity data forward/backward */ + int sumNrgFwd, sumNrgBwd; /* sum of noise energy data forward/backward */ + int sumScfFwd, sumScfBwd; /* sum of scalefactor data forward/backward */ + int useIsFwd, useNrgFwd, useScfFwd; /* the flags signals the elements which + are used for the final result */ + + sumIsFwd = sumIsBwd = sumNrgFwd = sumNrgBwd = sumScfFwd = sumScfBwd = 0; + useIsFwd = useNrgFwd = useScfFwd = 0; + + /* calculate sum of each group (scf,nrg,is) of forward and backward direction + */ + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + sumIsFwd += + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + sumIsBwd += + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + + case NOISE_HCB: + sumNrgFwd += + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + sumNrgBwd += + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + + default: + sumScfFwd += + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + sumScfBwd += + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + } + } + } + + /* find for each group (scf,nrg,is) the correct direction */ + if (sumIsFwd < sumIsBwd) useIsFwd = 1; + + if (sumNrgFwd < sumNrgBwd) useNrgFwd = 1; + + if (sumScfFwd < sumScfBwd) useScfFwd = 1; + + /* conceal each group (scf,nrg,is) */ + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (useIsFwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + + case NOISE_HCB: + if (useNrgFwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + + default: + if (useScfFwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + } + } + } +} + +/*--------------------------------------------------------------------------------------------- + description: Approach by means of predictive interpolation + This approach by means of predictive estimation is generally +performed when the error cannot be isolated between 'conceal_min' and +'conceal_max', the 'sf_concealment' flag is set and the previous frame has the +same block type as the current frame. Check for each scalefactorband if the same +type of data (scalefactor, internsity data, noise energies) is transmitted. If +so use the scalefactor (intensity data, noise energy) in the current frame. +Otherwise set the scalefactor (intensity data, noise energy) for this +scalefactorband to zero. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +void PredictiveInterpolation( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band, bnds, group; + SHORT commonMin; + + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0; + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + if ((pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] == INTENSITY_HCB) || + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] == INTENSITY_HCB2)) { + commonMin = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + fMin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = -110; + } + break; + + case NOISE_HCB: + if (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] == NOISE_HCB) { + commonMin = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + fMin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = -110; + } + break; + + default: + if ((pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != ZERO_HCB) && + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != NOISE_HCB) && + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != INTENSITY_HCB) && + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != INTENSITY_HCB2)) { + commonMin = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + fMin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0; + } + break; + } + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcconceal.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcconceal.h new file mode 100644 index 0000000000000..8e2062ee2863d --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/rvlcconceal.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief rvlc concealment + \author Josef Hoepfl +*/ + +#ifndef RVLCCONCEAL_H +#define RVLCCONCEAL_H + +#include "rvlc.h" + +void BidirectionalEstimation_UseLowerScfOfCurrentFrame( + CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +void BidirectionalEstimation_UseScfOfPrevFrameAsReference( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo); + +void StatisticalEstimation(CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +void PredictiveInterpolation( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo); + +#endif /* RVLCCONCEAL_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/stereo.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/stereo.cpp new file mode 100644 index 0000000000000..47f1a31c36395 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/stereo.cpp @@ -0,0 +1,1238 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: joint stereo processing + +*******************************************************************************/ + +#include "stereo.h" + +#include "aac_rom.h" +#include "FDK_bitstream.h" +#include "channelinfo.h" +#include "FDK_audio.h" + +enum { L = 0, R = 1 }; + +#include "block.h" + +int CJointStereo_Read(HANDLE_FDK_BITSTREAM bs, + CJointStereoData *pJointStereoData, + const int windowGroups, + const int scaleFactorBandsTransmitted, + const int max_sfb_ste_clear, + CJointStereoPersistentData *pJointStereoPersistentData, + CCplxPredictionData *cplxPredictionData, + int cplxPredictionActiv, int scaleFactorBandsTotal, + int windowSequence, const UINT flags) { + int group, band; + + pJointStereoData->MsMaskPresent = (UCHAR)FDKreadBits(bs, 2); + + FDKmemclear(pJointStereoData->MsUsed, + scaleFactorBandsTransmitted * sizeof(UCHAR)); + + pJointStereoData->cplx_pred_flag = 0; + if (cplxPredictionActiv) { + cplxPredictionData->pred_dir = 0; + cplxPredictionData->complex_coef = 0; + cplxPredictionData->use_prev_frame = 0; + cplxPredictionData->igf_pred_dir = 0; + } + + switch (pJointStereoData->MsMaskPresent) { + case 0: /* no M/S */ + /* all flags are already cleared */ + break; + + case 1: /* read ms_used */ + for (group = 0; group < windowGroups; group++) { + for (band = 0; band < scaleFactorBandsTransmitted; band++) { + pJointStereoData->MsUsed[band] |= (FDKreadBits(bs, 1) << group); + } + } + break; + + case 2: /* full spectrum M/S */ + for (band = 0; band < scaleFactorBandsTransmitted; band++) { + pJointStereoData->MsUsed[band] = 255; /* set all flags to 1 */ + } + break; + + case 3: + /* M/S coding is disabled, complex stereo prediction is enabled */ + if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) { + if (cplxPredictionActiv) { /* 'if (stereoConfigIndex == 0)' */ + + pJointStereoData->cplx_pred_flag = 1; + + /* cplx_pred_data() cp. ISO/IEC FDIS 23003-3:2011(E) Table 26 */ + int cplx_pred_all = 0; /* local use only */ + cplx_pred_all = FDKreadBits(bs, 1); + + if (cplx_pred_all) { + for (group = 0; group < windowGroups; group++) { + UCHAR groupmask = ((UCHAR)1 << group); + for (band = 0; band < scaleFactorBandsTransmitted; band++) { + pJointStereoData->MsUsed[band] |= groupmask; + } + } + } else { + for (group = 0; group < windowGroups; group++) { + for (band = 0; band < scaleFactorBandsTransmitted; + band += SFB_PER_PRED_BAND) { + pJointStereoData->MsUsed[band] |= (FDKreadBits(bs, 1) << group); + if ((band + 1) < scaleFactorBandsTotal) { + pJointStereoData->MsUsed[band + 1] |= + (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group)); + } + } + } + } + } else { + return -1; + } + } + break; + } + + if (cplxPredictionActiv) { + /* If all sfb are MS-ed then no complex prediction */ + if (pJointStereoData->MsMaskPresent == 3) { + if (pJointStereoData->cplx_pred_flag) { + int delta_code_time = 0; + + /* set pointer to Huffman codebooks */ + const CodeBookDescription *hcb = &AACcodeBookDescriptionTable[BOOKSCL]; + /* set predictors to zero in case of a transition from long to short + * window sequences and vice versa */ + if (((windowSequence == BLOCK_SHORT) && + (pJointStereoPersistentData->winSeqPrev != BLOCK_SHORT)) || + ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) && + (windowSequence != BLOCK_SHORT))) { + FDKmemclear(pJointStereoPersistentData->alpha_q_re_prev, + JointStereoMaximumGroups * JointStereoMaximumBands * + sizeof(SHORT)); + FDKmemclear(pJointStereoPersistentData->alpha_q_im_prev, + JointStereoMaximumGroups * JointStereoMaximumBands * + sizeof(SHORT)); + } + { + FDKmemclear(cplxPredictionData->alpha_q_re, + JointStereoMaximumGroups * JointStereoMaximumBands * + sizeof(SHORT)); + FDKmemclear(cplxPredictionData->alpha_q_im, + JointStereoMaximumGroups * JointStereoMaximumBands * + sizeof(SHORT)); + } + + /* 0 = mid->side prediction, 1 = side->mid prediction */ + cplxPredictionData->pred_dir = FDKreadBits(bs, 1); + cplxPredictionData->complex_coef = FDKreadBits(bs, 1); + + if (cplxPredictionData->complex_coef) { + if (flags & AC_INDEP) { + cplxPredictionData->use_prev_frame = 0; + } else { + cplxPredictionData->use_prev_frame = FDKreadBits(bs, 1); + } + } + + if (flags & AC_INDEP) { + delta_code_time = 0; + } else { + delta_code_time = FDKreadBits(bs, 1); + } + + { + int last_alpha_q_re = 0, last_alpha_q_im = 0; + + for (group = 0; group < windowGroups; group++) { + for (band = 0; band < scaleFactorBandsTransmitted; + band += SFB_PER_PRED_BAND) { + if (delta_code_time == 1) { + if (group > 0) { + last_alpha_q_re = + cplxPredictionData->alpha_q_re[group - 1][band]; + last_alpha_q_im = + cplxPredictionData->alpha_q_im[group - 1][band]; + } else if ((windowSequence == BLOCK_SHORT) && + (pJointStereoPersistentData->winSeqPrev == + BLOCK_SHORT)) { + /* Included for error-robustness */ + if (pJointStereoPersistentData->winGroupsPrev == 0) return -1; + + last_alpha_q_re = + pJointStereoPersistentData->alpha_q_re_prev + [pJointStereoPersistentData->winGroupsPrev - 1][band]; + last_alpha_q_im = + pJointStereoPersistentData->alpha_q_im_prev + [pJointStereoPersistentData->winGroupsPrev - 1][band]; + } else { + last_alpha_q_re = + pJointStereoPersistentData->alpha_q_re_prev[group][band]; + last_alpha_q_im = + pJointStereoPersistentData->alpha_q_im_prev[group][band]; + } + + } else { + if (band > 0) { + last_alpha_q_re = + cplxPredictionData->alpha_q_re[group][band - 1]; + last_alpha_q_im = + cplxPredictionData->alpha_q_im[group][band - 1]; + } else { + last_alpha_q_re = 0; + last_alpha_q_im = 0; + } + + } /* if (delta_code_time == 1) */ + + if (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group)) { + int dpcm_alpha_re, dpcm_alpha_im; + + dpcm_alpha_re = CBlock_DecodeHuffmanWord(bs, hcb); + dpcm_alpha_re -= 60; + dpcm_alpha_re *= -1; + + cplxPredictionData->alpha_q_re[group][band] = + dpcm_alpha_re + last_alpha_q_re; + + if (cplxPredictionData->complex_coef) { + dpcm_alpha_im = CBlock_DecodeHuffmanWord(bs, hcb); + dpcm_alpha_im -= 60; + dpcm_alpha_im *= -1; + + cplxPredictionData->alpha_q_im[group][band] = + dpcm_alpha_im + last_alpha_q_im; + } else { + cplxPredictionData->alpha_q_im[group][band] = 0; + } + + } else { + cplxPredictionData->alpha_q_re[group][band] = 0; + cplxPredictionData->alpha_q_im[group][band] = 0; + } /* if (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group)) */ + + if ((band + 1) < + scaleFactorBandsTransmitted) { /* <= this should be the + correct way (cp. + ISO_IEC_FDIS_23003-0(E) */ + /* 7.7.2.3.2 Decoding of prediction coefficients) */ + cplxPredictionData->alpha_q_re[group][band + 1] = + cplxPredictionData->alpha_q_re[group][band]; + cplxPredictionData->alpha_q_im[group][band + 1] = + cplxPredictionData->alpha_q_im[group][band]; + } /* if ((band+1)alpha_q_re_prev[group][band] = + cplxPredictionData->alpha_q_re[group][band]; + pJointStereoPersistentData->alpha_q_im_prev[group][band] = + cplxPredictionData->alpha_q_im[group][band]; + } + + for (band = scaleFactorBandsTransmitted; band < max_sfb_ste_clear; + band++) { + cplxPredictionData->alpha_q_re[group][band] = 0; + cplxPredictionData->alpha_q_im[group][band] = 0; + pJointStereoPersistentData->alpha_q_re_prev[group][band] = 0; + pJointStereoPersistentData->alpha_q_im_prev[group][band] = 0; + } + } + } + } + } else { + for (group = 0; group < windowGroups; group++) { + for (band = 0; band < max_sfb_ste_clear; band++) { + pJointStereoPersistentData->alpha_q_re_prev[group][band] = 0; + pJointStereoPersistentData->alpha_q_im_prev[group][band] = 0; + } + } + } + + pJointStereoPersistentData->winGroupsPrev = windowGroups; + } + + return 0; +} + +static void CJointStereo_filterAndAdd( + FIXP_DBL *in, int len, int windowLen, const FIXP_FILT *coeff, FIXP_DBL *out, + UCHAR isCurrent /* output values with even index get a + positve addon (=1) or a negative addon + (=0) */ +) { + int i, j; + + int indices_1[] = {2, 1, 0, 1, 2, 3}; + int indices_2[] = {1, 0, 0, 2, 3, 4}; + int indices_3[] = {0, 0, 1, 3, 4, 5}; + + int subtr_1[] = {6, 5, 4, 2, 1, 1}; + int subtr_2[] = {5, 4, 3, 1, 1, 2}; + int subtr_3[] = {4, 3, 2, 1, 2, 3}; + + if (isCurrent == 1) { + /* exploit the symmetry of the table: coeff[6] = - coeff[0], + coeff[5] = - coeff[1], + coeff[4] = - coeff[2], + coeff[3] = 0 + */ + + for (i = 0; i < 3; i++) { + out[0] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[i]]) >> SR_FNA_OUT; + out[0] += + (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[5 - i]]) >> SR_FNA_OUT; + } + + for (i = 0; i < 3; i++) { + out[1] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[i]]) >> SR_FNA_OUT; + out[1] += + (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[5 - i]]) >> SR_FNA_OUT; + } + + for (i = 0; i < 3; i++) { + out[2] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[i]]) >> SR_FNA_OUT; + out[2] += + (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[5 - i]]) >> SR_FNA_OUT; + } + + for (j = 3; j < (len - 3); j++) { + for (i = 0; i < 3; i++) { + out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i]) >> SR_FNA_OUT; + out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i]) >> SR_FNA_OUT; + } + } + + for (i = 0; i < 3; i++) { + out[len - 3] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[i]]) >> SR_FNA_OUT; + out[len - 3] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[5 - i]]) >> SR_FNA_OUT; + } + + for (i = 0; i < 3; i++) { + out[len - 2] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[i]]) >> SR_FNA_OUT; + out[len - 2] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[5 - i]]) >> SR_FNA_OUT; + } + + for (i = 0; i < 3; i++) { + out[len - 1] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[i]]) >> SR_FNA_OUT; + out[len - 1] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[5 - i]]) >> SR_FNA_OUT; + } + + } else { + /* exploit the symmetry of the table: coeff[6] = coeff[0], + coeff[5] = coeff[1], + coeff[4] = coeff[2] + */ + + for (i = 0; i < 3; i++) { + out[0] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[i]] >> SR_FNA_OUT); + out[0] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[5 - i]] >> SR_FNA_OUT); + } + out[0] -= (FIXP_DBL)fMultDiv2(coeff[3], in[0] >> SR_FNA_OUT); + + for (i = 0; i < 3; i++) { + out[1] += (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[i]] >> SR_FNA_OUT); + out[1] += + (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[5 - i]] >> SR_FNA_OUT); + } + out[1] += (FIXP_DBL)fMultDiv2(coeff[3], in[1] >> SR_FNA_OUT); + + for (i = 0; i < 3; i++) { + out[2] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[i]] >> SR_FNA_OUT); + out[2] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[5 - i]] >> SR_FNA_OUT); + } + out[2] -= (FIXP_DBL)fMultDiv2(coeff[3], in[2] >> SR_FNA_OUT); + + for (j = 3; j < (len - 4); j++) { + for (i = 0; i < 3; i++) { + out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i] >> SR_FNA_OUT); + out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i] >> SR_FNA_OUT); + } + out[j] += (FIXP_DBL)fMultDiv2(coeff[3], in[j] >> SR_FNA_OUT); + + j++; + + for (i = 0; i < 3; i++) { + out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i] >> SR_FNA_OUT); + out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i] >> SR_FNA_OUT); + } + out[j] -= (FIXP_DBL)fMultDiv2(coeff[3], in[j] >> SR_FNA_OUT); + } + + for (i = 0; i < 3; i++) { + out[len - 3] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[i]] >> SR_FNA_OUT); + out[len - 3] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[5 - i]] >> SR_FNA_OUT); + } + out[len - 3] += (FIXP_DBL)fMultDiv2(coeff[3], in[len - 3] >> SR_FNA_OUT); + + for (i = 0; i < 3; i++) { + out[len - 2] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[i]] >> SR_FNA_OUT); + out[len - 2] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[5 - i]] >> SR_FNA_OUT); + } + out[len - 2] -= (FIXP_DBL)fMultDiv2(coeff[3], in[len - 2] >> SR_FNA_OUT); + + for (i = 0; i < 3; i++) { + out[len - 1] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[i]] >> SR_FNA_OUT); + out[len - 1] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[5 - i]] >> SR_FNA_OUT); + } + out[len - 1] += (FIXP_DBL)fMultDiv2(coeff[3], in[len - 1] >> SR_FNA_OUT); + } +} + +static inline void CJointStereo_GenerateMSOutput(FIXP_DBL *pSpecLCurrBand, + FIXP_DBL *pSpecRCurrBand, + UINT leftScale, + UINT rightScale, + UINT nSfbBands) { + unsigned int i; + + FIXP_DBL leftCoefficient0; + FIXP_DBL leftCoefficient1; + FIXP_DBL leftCoefficient2; + FIXP_DBL leftCoefficient3; + + FIXP_DBL rightCoefficient0; + FIXP_DBL rightCoefficient1; + FIXP_DBL rightCoefficient2; + FIXP_DBL rightCoefficient3; + + for (i = nSfbBands; i > 0; i -= 4) { + leftCoefficient0 = pSpecLCurrBand[i - 4]; + leftCoefficient1 = pSpecLCurrBand[i - 3]; + leftCoefficient2 = pSpecLCurrBand[i - 2]; + leftCoefficient3 = pSpecLCurrBand[i - 1]; + + rightCoefficient0 = pSpecRCurrBand[i - 4]; + rightCoefficient1 = pSpecRCurrBand[i - 3]; + rightCoefficient2 = pSpecRCurrBand[i - 2]; + rightCoefficient3 = pSpecRCurrBand[i - 1]; + + /* MS output generation */ + leftCoefficient0 >>= leftScale; + leftCoefficient1 >>= leftScale; + leftCoefficient2 >>= leftScale; + leftCoefficient3 >>= leftScale; + + rightCoefficient0 >>= rightScale; + rightCoefficient1 >>= rightScale; + rightCoefficient2 >>= rightScale; + rightCoefficient3 >>= rightScale; + + pSpecLCurrBand[i - 4] = leftCoefficient0 + rightCoefficient0; + pSpecLCurrBand[i - 3] = leftCoefficient1 + rightCoefficient1; + pSpecLCurrBand[i - 2] = leftCoefficient2 + rightCoefficient2; + pSpecLCurrBand[i - 1] = leftCoefficient3 + rightCoefficient3; + + pSpecRCurrBand[i - 4] = leftCoefficient0 - rightCoefficient0; + pSpecRCurrBand[i - 3] = leftCoefficient1 - rightCoefficient1; + pSpecRCurrBand[i - 2] = leftCoefficient2 - rightCoefficient2; + pSpecRCurrBand[i - 1] = leftCoefficient3 - rightCoefficient3; + } +} + +void CJointStereo_ApplyMS( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2], + FIXP_DBL *spectrumL, FIXP_DBL *spectrumR, SHORT *SFBleftScale, + SHORT *SFBrightScale, SHORT *specScaleL, SHORT *specScaleR, + const SHORT *pScaleFactorBandOffsets, const UCHAR *pWindowGroupLength, + const int windowGroups, const int max_sfb_ste_outside, + const int scaleFactorBandsTransmittedL, + const int scaleFactorBandsTransmittedR, FIXP_DBL *store_dmx_re_prev, + SHORT *store_dmx_re_prev_e, const int mainband_flag) { + int window, group, band; + UCHAR groupMask; + CJointStereoData *pJointStereoData = + &pAacDecoderChannelInfo[L]->pComData->jointStereoData; + CCplxPredictionData *cplxPredictionData = + pAacDecoderChannelInfo[L]->pComStaticData->cplxPredictionData; + + int max_sfb_ste = + fMax(scaleFactorBandsTransmittedL, scaleFactorBandsTransmittedR); + int min_sfb_ste = + fMin(scaleFactorBandsTransmittedL, scaleFactorBandsTransmittedR); + int scaleFactorBandsTransmitted = min_sfb_ste; + + if (pJointStereoData->cplx_pred_flag) { + int windowLen, groupwin, frameMaxScale; + CJointStereoPersistentData *pJointStereoPersistentData = + &pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData; + FIXP_DBL *const staticSpectralCoeffsL = + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.spectralCoeffs[L]; + FIXP_DBL *const staticSpectralCoeffsR = + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.spectralCoeffs[R]; + SHORT *const staticSpecScaleL = + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.specScale[L]; + SHORT *const staticSpecScaleR = + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.specScale[R]; + + FIXP_DBL *dmx_re = + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.scratchBuffer; + FIXP_DBL *dmx_re_prev = + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.scratchBuffer + + 1024; + + /* When MS is applied over the main band this value gets computed. Otherwise + * (for the tiles) it uses the assigned value */ + SHORT dmx_re_prev_e = *store_dmx_re_prev_e; + + const FIXP_FILT *pCoeff; + const FIXP_FILT *pCoeffPrev; + int coeffPointerOffset; + + int previousShape = (int)pJointStereoPersistentData->winShapePrev; + int currentShape = (int)pAacDecoderChannelInfo[L]->icsInfo.WindowShape; + + /* complex stereo prediction */ + + /* 0. preparations */ + + /* 0.0. get scratch buffer for downmix MDST */ + C_AALLOC_SCRATCH_START(dmx_im, FIXP_DBL, 1024); + + /* 0.1. window lengths */ + + /* get length of short window for current configuration */ + windowLen = + pAacDecoderChannelInfo[L]->granuleLength; /* framelength 768 => 96, + framelength 1024 => 128 */ + + /* if this is no short-block set length for long-block */ + if (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence != BLOCK_SHORT) { + windowLen *= 8; + } + + /* 0.2. set pointer to filter-coefficients for MDST excitation including + * previous frame portions */ + /* cp. ISO/IEC FDIS 23003-3:2011(E) table 125 */ + + /* set pointer to default-position */ + pCoeffPrev = mdst_filt_coef_prev[previousShape]; + + if (cplxPredictionData->complex_coef == 1) { + switch (pAacDecoderChannelInfo[L] + ->icsInfo.WindowSequence) { /* current window sequence */ + case BLOCK_SHORT: + case BLOCK_LONG: + pCoeffPrev = mdst_filt_coef_prev[previousShape]; + break; + + case BLOCK_START: + if ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) || + (pJointStereoPersistentData->winSeqPrev == BLOCK_START)) { + /* a stop-start-sequence can only follow on an eight-short-sequence + * or a start-sequence */ + pCoeffPrev = mdst_filt_coef_prev[2 + previousShape]; + } else { + pCoeffPrev = mdst_filt_coef_prev[previousShape]; + } + break; + + case BLOCK_STOP: + pCoeffPrev = mdst_filt_coef_prev[2 + previousShape]; + break; + + default: + pCoeffPrev = mdst_filt_coef_prev[previousShape]; + break; + } + } + + /* 0.3. set pointer to filter-coefficients for MDST excitation */ + + /* define offset of pointer to filter-coefficients for MDST exitation + * employing only the current frame */ + if ((previousShape == SHAPE_SINE) && (currentShape == SHAPE_SINE)) { + coeffPointerOffset = 0; + } else if ((previousShape == SHAPE_SINE) && (currentShape == SHAPE_KBD)) { + coeffPointerOffset = 2; + } else if ((previousShape == SHAPE_KBD) && (currentShape == SHAPE_KBD)) { + coeffPointerOffset = 1; + } else /* if ( (previousShape == SHAPE_KBD) && (currentShape == SHAPE_SINE) + ) */ + { + coeffPointerOffset = 3; + } + + /* set pointer to filter-coefficient table cp. ISO/IEC FDIS 23003-3:2011(E) + * table 124 */ + switch (pAacDecoderChannelInfo[L] + ->icsInfo.WindowSequence) { /* current window sequence */ + case BLOCK_SHORT: + case BLOCK_LONG: + pCoeff = mdst_filt_coef_curr[coeffPointerOffset]; + break; + + case BLOCK_START: + if ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) || + (pJointStereoPersistentData->winSeqPrev == BLOCK_START)) { + /* a stop-start-sequence can only follow on an eight-short-sequence or + * a start-sequence */ + pCoeff = mdst_filt_coef_curr[12 + coeffPointerOffset]; + } else { + pCoeff = mdst_filt_coef_curr[4 + coeffPointerOffset]; + } + break; + + case BLOCK_STOP: + pCoeff = mdst_filt_coef_curr[8 + coeffPointerOffset]; + break; + + default: + pCoeff = mdst_filt_coef_curr[coeffPointerOffset]; + } + + /* 0.4. find maximum common (l/r) band-scaling-factor for whole sequence + * (all windows) */ + frameMaxScale = 0; + for (window = 0, group = 0; group < windowGroups; group++) { + for (groupwin = 0; groupwin < pWindowGroupLength[group]; + groupwin++, window++) { + SHORT *leftScale = &SFBleftScale[window * 16]; + SHORT *rightScale = &SFBrightScale[window * 16]; + int windowMaxScale = 0; + + /* find maximum scaling factor of all bands in this window */ + for (band = 0; band < min_sfb_ste; band++) { + int lScale = leftScale[band]; + int rScale = rightScale[band]; + int commonScale = ((lScale > rScale) ? lScale : rScale); + windowMaxScale = + (windowMaxScale < commonScale) ? commonScale : windowMaxScale; + } + if (scaleFactorBandsTransmittedL > + min_sfb_ste) { /* i.e. scaleFactorBandsTransmittedL == max_sfb_ste + */ + for (; band < max_sfb_ste; band++) { + int lScale = leftScale[band]; + windowMaxScale = + (windowMaxScale < lScale) ? lScale : windowMaxScale; + } + } else { + if (scaleFactorBandsTransmittedR > + min_sfb_ste) { /* i.e. scaleFactorBandsTransmittedR == max_sfb_ste + */ + for (; band < max_sfb_ste; band++) { + int rScale = rightScale[band]; + windowMaxScale = + (windowMaxScale < rScale) ? rScale : windowMaxScale; + } + } + } + + /* find maximum common SF of all windows */ + frameMaxScale = + (frameMaxScale < windowMaxScale) ? windowMaxScale : frameMaxScale; + } + } + + /* add some headroom for overflow protection during filter and add operation + */ + frameMaxScale += 2; + + /* process on window-basis (i.e. iterate over all groups and corresponding + * windows) */ + for (window = 0, group = 0; group < windowGroups; group++) { + groupMask = 1 << group; + + for (groupwin = 0; groupwin < pWindowGroupLength[group]; + groupwin++, window++) { + /* initialize the MDST with zeros */ + FDKmemclear(&dmx_im[windowLen * window], windowLen * sizeof(FIXP_DBL)); + + /* 1. calculate the previous downmix MDCT. We do this once just for the + * Main band. */ + if (cplxPredictionData->complex_coef == 1) { + if ((cplxPredictionData->use_prev_frame == 1) && (mainband_flag)) { + /* if this is a long-block or the first window of a short-block + calculate the downmix MDCT of the previous frame. + use_prev_frame is assumed not to change during a frame! + */ + + /* first determine shiftfactors to scale left and right channel */ + if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence != + BLOCK_SHORT) || + (window == 0)) { + int index_offset = 0; + int srLeftChan = 0; + int srRightChan = 0; + if (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence == + BLOCK_SHORT) { + /* use the last window of the previous frame for MDCT + * calculation if this is a short-block. */ + index_offset = windowLen * 7; + if (staticSpecScaleL[7] > staticSpecScaleR[7]) { + srRightChan = staticSpecScaleL[7] - staticSpecScaleR[7]; + dmx_re_prev_e = staticSpecScaleL[7]; + } else { + srLeftChan = staticSpecScaleR[7] - staticSpecScaleL[7]; + dmx_re_prev_e = staticSpecScaleR[7]; + } + } else { + if (staticSpecScaleL[0] > staticSpecScaleR[0]) { + srRightChan = staticSpecScaleL[0] - staticSpecScaleR[0]; + dmx_re_prev_e = staticSpecScaleL[0]; + } else { + srLeftChan = staticSpecScaleR[0] - staticSpecScaleL[0]; + dmx_re_prev_e = staticSpecScaleR[0]; + } + } + + /* now scale channels and determine downmix MDCT of previous frame + */ + if (pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData + .clearSpectralCoeffs == 1) { + FDKmemclear(dmx_re_prev, windowLen * sizeof(FIXP_DBL)); + dmx_re_prev_e = 0; + } else { + if (cplxPredictionData->pred_dir == 0) { + for (int i = 0; i < windowLen; i++) { + dmx_re_prev[i] = + ((staticSpectralCoeffsL[index_offset + i] >> + fMin(DFRACT_BITS - 1, srLeftChan + 1)) + + (staticSpectralCoeffsR[index_offset + i] >> + fMin(DFRACT_BITS - 1, srRightChan + 1))); + } + } else { + for (int i = 0; i < windowLen; i++) { + dmx_re_prev[i] = + ((staticSpectralCoeffsL[index_offset + i] >> + fMin(DFRACT_BITS - 1, srLeftChan + 1)) - + (staticSpectralCoeffsR[index_offset + i] >> + fMin(DFRACT_BITS - 1, srRightChan + 1))); + } + } + } + + /* In case that we use INF we have to preserve the state of the + "dmx_re_prev" (original or computed). This is necessary because we + have to apply MS over the separate IGF tiles. */ + FDKmemcpy(store_dmx_re_prev, &dmx_re_prev[0], + windowLen * sizeof(FIXP_DBL)); + + /* Particular exponent of the computed/original "dmx_re_prev" must + * be kept for the tile MS calculations if necessary.*/ + *store_dmx_re_prev_e = dmx_re_prev_e; + + } /* if ( (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence != + BLOCK_SHORT) || (window == 0) ) */ + + } /* if ( pJointStereoData->use_prev_frame == 1 ) */ + + } /* if ( pJointStereoData->complex_coef == 1 ) */ + + /* 2. calculate downmix MDCT of current frame */ + + /* set pointer to scale-factor-bands of current window */ + SHORT *leftScale = &SFBleftScale[window * 16]; + SHORT *rightScale = &SFBrightScale[window * 16]; + + specScaleL[window] = specScaleR[window] = frameMaxScale; + + /* adapt scaling-factors to previous frame */ + if (cplxPredictionData->use_prev_frame == 1) { + if (window == 0) { + if (dmx_re_prev_e < frameMaxScale) { + if (mainband_flag == 0) { + scaleValues( + dmx_re_prev, store_dmx_re_prev, windowLen, + -fMin(DFRACT_BITS - 1, (frameMaxScale - dmx_re_prev_e))); + } else { + scaleValues( + dmx_re_prev, windowLen, + -fMin(DFRACT_BITS - 1, (frameMaxScale - dmx_re_prev_e))); + } + } else { + if (mainband_flag == 0) { + FDKmemcpy(dmx_re_prev, store_dmx_re_prev, + windowLen * sizeof(FIXP_DBL)); + } + specScaleL[0] = dmx_re_prev_e; + specScaleR[0] = dmx_re_prev_e; + } + } else { /* window != 0 */ + FDK_ASSERT(pAacDecoderChannelInfo[L]->icsInfo.WindowSequence == + BLOCK_SHORT); + if (specScaleL[window - 1] < frameMaxScale) { + scaleValues(&dmx_re[windowLen * (window - 1)], windowLen, + -fMin(DFRACT_BITS - 1, + (frameMaxScale - specScaleL[window - 1]))); + } else { + specScaleL[window] = specScaleL[window - 1]; + specScaleR[window] = specScaleR[window - 1]; + } + } + } /* if ( pJointStereoData->use_prev_frame == 1 ) */ + + /* scaling factors of both channels ought to be equal now */ + FDK_ASSERT(specScaleL[window] == specScaleR[window]); + + /* rescale signal and calculate downmix MDCT */ + for (band = 0; band < max_sfb_ste; band++) { + /* first adapt scaling of current band to scaling of current window => + * shift signal right */ + int lScale = leftScale[band]; + int rScale = rightScale[band]; + + lScale = fMin(DFRACT_BITS - 1, specScaleL[window] - lScale); + rScale = fMin(DFRACT_BITS - 1, + specScaleL[window] - rScale); /* L or R doesn't + matter, + specScales are + equal at this + point */ + + /* Write back to sfb scale to cover the case when max_sfb_ste < + * max_sfb */ + leftScale[band] = rightScale[band] = specScaleL[window]; + + for (int i = pScaleFactorBandOffsets[band]; + i < pScaleFactorBandOffsets[band + 1]; i++) { + spectrumL[windowLen * window + i] >>= lScale; + spectrumR[windowLen * window + i] >>= rScale; + } + + /* now calculate downmix MDCT */ + if (pJointStereoData->MsUsed[band] & groupMask) { + for (int i = pScaleFactorBandOffsets[band]; + i < pScaleFactorBandOffsets[band + 1]; i++) { + dmx_re[windowLen * window + i] = + spectrumL[windowLen * window + i]; + } + } else { + if (cplxPredictionData->pred_dir == 0) { + for (int i = pScaleFactorBandOffsets[band]; + i < pScaleFactorBandOffsets[band + 1]; i++) { + dmx_re[windowLen * window + i] = + (spectrumL[windowLen * window + i] + + spectrumR[windowLen * window + i]) >> + 1; + } + } else { + for (int i = pScaleFactorBandOffsets[band]; + i < pScaleFactorBandOffsets[band + 1]; i++) { + dmx_re[windowLen * window + i] = + (spectrumL[windowLen * window + i] - + spectrumR[windowLen * window + i]) >> + 1; + } + } + } + + } /* for ( band=0; bandcomplex_coef == 1) { + { + /* 3.1 move pointer in filter-coefficient table in case of short + * window sequence */ + /* (other coefficients are utilized for the last 7 short + * windows) */ + if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence == + BLOCK_SHORT) && + (window != 0)) { + pCoeff = mdst_filt_coef_curr[currentShape]; + pCoeffPrev = mdst_filt_coef_prev[currentShape]; + } + + /* The length of the filter processing must be extended because of + * filter boundary problems */ + int extended_band = fMin( + pScaleFactorBandOffsets[max_sfb_ste_outside] + 7, windowLen); + + /* 3.2. estimate downmix MDST from current frame downmix MDCT */ + if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence == + BLOCK_SHORT) && + (window != 0)) { + CJointStereo_filterAndAdd(&dmx_re[windowLen * window], + extended_band, windowLen, pCoeff, + &dmx_im[windowLen * window], 1); + + CJointStereo_filterAndAdd(&dmx_re[windowLen * (window - 1)], + extended_band, windowLen, pCoeffPrev, + &dmx_im[windowLen * window], 0); + } else { + CJointStereo_filterAndAdd(dmx_re, extended_band, windowLen, + pCoeff, dmx_im, 1); + + if (cplxPredictionData->use_prev_frame == 1) { + CJointStereo_filterAndAdd(dmx_re_prev, extended_band, windowLen, + pCoeffPrev, + &dmx_im[windowLen * window], 0); + } + } + + } /* if(pAacDecoderChannelInfo[L]->transform_splitting_active) */ + } /* if ( pJointStereoData->complex_coef == 1 ) */ + + /* 4. upmix process */ + LONG pred_dir = cplxPredictionData->pred_dir ? -1 : 1; + /* 0.1 in Q-3.34 */ + const FIXP_DBL pointOne = 0x66666666; /* 0.8 */ + /* Shift value for the downmix */ + const INT shift_dmx = SF_FNA_COEFFS + 1; + + for (band = 0; band < max_sfb_ste_outside; band++) { + if (pJointStereoData->MsUsed[band] & groupMask) { + FIXP_SGL tempRe = + (FIXP_SGL)cplxPredictionData->alpha_q_re[group][band]; + FIXP_SGL tempIm = + (FIXP_SGL)cplxPredictionData->alpha_q_im[group][band]; + + /* Find the minimum common headroom for alpha_re and alpha_im */ + int alpha_re_headroom = CountLeadingBits((INT)tempRe) - 16; + if (tempRe == (FIXP_SGL)0) alpha_re_headroom = 15; + int alpha_im_headroom = CountLeadingBits((INT)tempIm) - 16; + if (tempIm == (FIXP_SGL)0) alpha_im_headroom = 15; + int val = fMin(alpha_re_headroom, alpha_im_headroom); + + /* Multiply alpha by 0.1 with maximum precision */ + FDK_ASSERT(val >= 0); + FIXP_DBL alpha_re_tmp = fMult((FIXP_SGL)(tempRe << val), pointOne); + FIXP_DBL alpha_im_tmp = fMult((FIXP_SGL)(tempIm << val), pointOne); + + /* Calculate alpha exponent */ + /* (Q-3.34 * Q15.0) shifted left by "val" */ + int alpha_re_exp = -3 + 15 - val; + + int help3_shift = alpha_re_exp + 1; + + FIXP_DBL *p2CoeffL = &( + spectrumL[windowLen * window + pScaleFactorBandOffsets[band]]); + FIXP_DBL *p2CoeffR = &( + spectrumR[windowLen * window + pScaleFactorBandOffsets[band]]); + FIXP_DBL *p2dmxIm = + &(dmx_im[windowLen * window + pScaleFactorBandOffsets[band]]); + FIXP_DBL *p2dmxRe = + &(dmx_re[windowLen * window + pScaleFactorBandOffsets[band]]); + + for (int i = pScaleFactorBandOffsets[band]; + i < pScaleFactorBandOffsets[band + 1]; i++) { + /* Calculating helper term: + side = specR[i] - alpha_re[i] * dmx_re[i] - alpha_im[i] * + dmx_im[i]; + + Here "dmx_re" may be the same as "specL" or alternatively keep + the downmix. "dmx_re" and "specL" are two different pointers + pointing to separate arrays, which may or may not contain the + same data (with different scaling). + + specL[i] = + (specL[i] + side); + specR[i] = -/+ (specL[i] - side); + */ + FIXP_DBL side, left, right; + + side = fMultAddDiv2(fMultDiv2(alpha_re_tmp, *p2dmxRe++), + alpha_im_tmp, (*p2dmxIm++) << shift_dmx); + side = ((*p2CoeffR) >> 2) - + (FIXP_DBL)SATURATE_SHIFT(side, -(help3_shift - 2), + DFRACT_BITS - 2); + + left = ((*p2CoeffL) >> 2) + side; + right = ((*p2CoeffL) >> 2) - side; + right = (FIXP_DBL)((LONG)right * pred_dir); + + *p2CoeffL++ = SATURATE_LEFT_SHIFT_ALT(left, 2, DFRACT_BITS); + *p2CoeffR++ = SATURATE_LEFT_SHIFT_ALT(right, 2, DFRACT_BITS); + } + } + + } /* for ( band=0; band < max_sfb_ste; band++ ) */ + } /* for ( groupwin=0; groupwingranuleLength); + rightSpectrum = + SPEC(spectrumR, window, pAacDecoderChannelInfo[R]->granuleLength); + + for (band = 0; band < max_sfb_ste_outside; band++) { + if (pJointStereoData->MsUsed[band] & groupMask) { + int lScale = leftScale[band]; + int rScale = rightScale[band]; + int commonScale = lScale > rScale ? lScale : rScale; + unsigned int offsetCurrBand, offsetNextBand; + + /* ISO/IEC 14496-3 Chapter 4.6.8.1.1 : + M/S joint channel coding can only be used if common_window is 1. + */ + FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) == + GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo)); + FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) == + GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo)); + + commonScale++; + leftScale[band] = commonScale; + rightScale[band] = commonScale; + + lScale = fMin(DFRACT_BITS - 1, commonScale - lScale); + rScale = fMin(DFRACT_BITS - 1, commonScale - rScale); + + FDK_ASSERT(lScale >= 0 && rScale >= 0); + + offsetCurrBand = pScaleFactorBandOffsets[band]; + offsetNextBand = pScaleFactorBandOffsets[band + 1]; + + CJointStereo_GenerateMSOutput(&(leftSpectrum[offsetCurrBand]), + &(rightSpectrum[offsetCurrBand]), + lScale, rScale, + offsetNextBand - offsetCurrBand); + } + } + if (scaleFactorBandsTransmittedL > scaleFactorBandsTransmitted) { + for (; band < scaleFactorBandsTransmittedL; band++) { + if (pJointStereoData->MsUsed[band] & groupMask) { + rightScale[band] = leftScale[band]; + + for (int index = pScaleFactorBandOffsets[band]; + index < pScaleFactorBandOffsets[band + 1]; index++) { + FIXP_DBL leftCoefficient = leftSpectrum[index]; + /* FIXP_DBL rightCoefficient = (FIXP_DBL)0; */ + rightSpectrum[index] = leftCoefficient; + } + } + } + } else if (scaleFactorBandsTransmittedR > scaleFactorBandsTransmitted) { + for (; band < scaleFactorBandsTransmittedR; band++) { + if (pJointStereoData->MsUsed[band] & groupMask) { + leftScale[band] = rightScale[band]; + + for (int index = pScaleFactorBandOffsets[band]; + index < pScaleFactorBandOffsets[band + 1]; index++) { + /* FIXP_DBL leftCoefficient = (FIXP_DBL)0; */ + FIXP_DBL rightCoefficient = rightSpectrum[index]; + + leftSpectrum[index] = rightCoefficient; + rightSpectrum[index] = -rightCoefficient; + } + } + } + } + } + } + + /* Reset MsUsed flags if no explicit signalling was transmitted. Necessary + for intensity coding. PNS correlation signalling was mapped before + calling CJointStereo_ApplyMS(). */ + if (pJointStereoData->MsMaskPresent == 2) { + FDKmemclear(pJointStereoData->MsUsed, + JointStereoMaximumBands * sizeof(UCHAR)); + } + } +} + +void CJointStereo_ApplyIS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + const SHORT *pScaleFactorBandOffsets, + const UCHAR *pWindowGroupLength, + const int windowGroups, + const int scaleFactorBandsTransmitted) { + CJointStereoData *pJointStereoData = + &pAacDecoderChannelInfo[L]->pComData->jointStereoData; + + for (int window = 0, group = 0; group < windowGroups; group++) { + UCHAR *CodeBook; + SHORT *ScaleFactor; + UCHAR groupMask = 1 << group; + + CodeBook = &pAacDecoderChannelInfo[R]->pDynData->aCodeBook[group * 16]; + ScaleFactor = + &pAacDecoderChannelInfo[R]->pDynData->aScaleFactor[group * 16]; + + for (int groupwin = 0; groupwin < pWindowGroupLength[group]; + groupwin++, window++) { + FIXP_DBL *leftSpectrum, *rightSpectrum; + SHORT *leftScale = + &pAacDecoderChannelInfo[L]->pDynData->aSfbScale[window * 16]; + SHORT *rightScale = + &pAacDecoderChannelInfo[R]->pDynData->aSfbScale[window * 16]; + int band; + + leftSpectrum = SPEC(pAacDecoderChannelInfo[L]->pSpectralCoefficient, + window, pAacDecoderChannelInfo[L]->granuleLength); + rightSpectrum = SPEC(pAacDecoderChannelInfo[R]->pSpectralCoefficient, + window, pAacDecoderChannelInfo[R]->granuleLength); + + for (band = 0; band < scaleFactorBandsTransmitted; band++) { + if ((CodeBook[band] == INTENSITY_HCB) || + (CodeBook[band] == INTENSITY_HCB2)) { + int bandScale = -(ScaleFactor[band] + 100); + + int msb = bandScale >> 2; + int lsb = bandScale & 0x03; + + /* exponent of MantissaTable[lsb][0] is 1, thus msb+1 below. */ + FIXP_DBL scale = MantissaTable[lsb][0]; + + /* ISO/IEC 14496-3 Chapter 4.6.8.2.3 : + The use of intensity stereo coding is signaled by the use of the + pseudo codebooks INTENSITY_HCB and INTENSITY_HCB2 (15 and 14) only + in the right channel of a channel_pair_element() having a common + ics_info() (common_window == 1). */ + FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) == + GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo)); + FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) == + GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo)); + + rightScale[band] = leftScale[band] + msb + 1; + + if (pJointStereoData->MsUsed[band] & groupMask) { + if (CodeBook[band] == INTENSITY_HCB) /* _NOT_ in-phase */ + { + scale = -scale; + } + } else { + if (CodeBook[band] == INTENSITY_HCB2) /* out-of-phase */ + { + scale = -scale; + } + } + + for (int index = pScaleFactorBandOffsets[band]; + index < pScaleFactorBandOffsets[band + 1]; index++) { + rightSpectrum[index] = fMult(leftSpectrum[index], scale); + } + } + } + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/stereo.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/stereo.h new file mode 100644 index 0000000000000..af7a74f84dc06 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/stereo.h @@ -0,0 +1,211 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: joint stereo processing + +*******************************************************************************/ + +#ifndef STEREO_H +#define STEREO_H + +#include "machine_type.h" +#include "FDK_bitstream.h" +#include "common_fix.h" + +#define SFB_PER_PRED_BAND 2 + +#define SR_FNA_OUT \ + 0 /* Additional scaling of the CJointStereo_filterAndAdd()-output to avoid \ + overflows. */ + /* The scaling factor can be set to 0 if the coefficients are prescaled + * appropriately. */ +/* Prescaling via factor SF_FNA_COEFFS is done at compile-time but should only + * be */ +/* utilized if the coefficients are stored as FIXP_DBL. (cp. aac_rom.cpp/.h) */ + +/* The NO_CPLX_PRED_BUGFIX-switch was introduced to enable decoding of + conformance-streams in way that they are comparable to buggy + reference-streams. This is established by storing the prediction direction + for computation of the "downmix MDCT of previous frame". This is not standard + compliant. Once correct reference-streams for complex-stereo-prediction are + available this switch becomes obsolete. +*/ +/*#define NO_CPLX_PRED_BUGFIX*/ + +enum { JointStereoMaximumGroups = 8, JointStereoMaximumBands = 64 }; + +typedef struct { + UCHAR pred_dir; // 0 = prediction from mid to side channel, 1 = vice versa + UCHAR + igf_pred_dir; // 0 = prediction from mid to side channel, 1 = vice versa + UCHAR complex_coef; // 0 = alpha_q_im[x] is 0 for all prediction bands, 1 = + // alpha_q_im[x] is transmitted via bitstream + UCHAR use_prev_frame; // 0 = use current frame for MDST estimation, 1 = use + // current and previous frame + + SHORT alpha_q_re[JointStereoMaximumGroups][JointStereoMaximumBands]; + SHORT alpha_q_im[JointStereoMaximumGroups][JointStereoMaximumBands]; +} CCplxPredictionData; + +/* joint stereo scratch memory (valid for this frame) */ +typedef struct { + UCHAR MsMaskPresent; + UCHAR MsUsed[JointStereoMaximumBands]; /*!< every arry element contains flags + for up to 8 groups. this array is + also utilized for complex stereo + prediction. */ + UCHAR IGF_MsMaskPresent; + + UCHAR cplx_pred_flag; /* stereo complex prediction was signalled for this + frame */ + UCHAR igf_cplx_pred_flag; + + /* The following array and variable are needed for the case when INF is + * active */ + FIXP_DBL store_dmx_re_prev[1024]; + SHORT store_dmx_re_prev_e; + +} CJointStereoData; + +/* joint stereo persistent memory */ +typedef struct { + UCHAR clearSpectralCoeffs; /* indicates that the spectral coeffs must be + cleared because the transform splitting active + flag of the left and right channel was different + */ + + FIXP_DBL *scratchBuffer; /* pointer to scratch buffer */ + + FIXP_DBL + *spectralCoeffs[2]; /* spectral coefficients of this channel utilized by + complex stereo prediction */ + SHORT *specScale[2]; + + SHORT alpha_q_re_prev[JointStereoMaximumGroups][JointStereoMaximumBands]; + SHORT alpha_q_im_prev[JointStereoMaximumGroups][JointStereoMaximumBands]; + + UCHAR winSeqPrev; + UCHAR winShapePrev; + UCHAR winGroupsPrev; + +} CJointStereoPersistentData; + +/*! + \brief Read joint stereo data from bitstream + + The function reads joint stereo data from bitstream. + + \param bs bit stream handle data source. + \param pJointStereoData pointer to stereo data structure to receive decoded + data. \param windowGroups number of window groups. \param + scaleFactorBandsTransmitted number of transmitted scalefactor bands. \param + flags decoder flags + + \return 0 on success, -1 on error. +*/ +int CJointStereo_Read(HANDLE_FDK_BITSTREAM bs, + CJointStereoData *pJointStereoData, + const int windowGroups, + const int scaleFactorBandsTransmitted, + const int max_sfb_ste_clear, + CJointStereoPersistentData *pJointStereoPersistentData, + CCplxPredictionData *cplxPredictionData, + int cplxPredictionActiv, int scaleFactorBandsTotal, + int windowSequence, const UINT flags); + +#endif /* #ifndef STEREO_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_d4t64.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_d4t64.cpp new file mode 100644 index 0000000000000..43e06cdde5c53 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_d4t64.cpp @@ -0,0 +1,439 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: ACELP + +*******************************************************************************/ + +#include "usacdec_ace_d4t64.h" + +#define L_SUBFR 64 /* Subframe size */ + +/* + * D_ACELP_add_pulse + * + * Parameters: + * pos I: position of pulse + * nb_pulse I: number of pulses + * track I: track + * code O: fixed codebook + * + * Function: + * Add pulses to fixed codebook + * + * Returns: + * void + */ +static void D_ACELP_add_pulse(SHORT pos[], SHORT nb_pulse, SHORT track, + FIXP_COD code[]) { + SHORT i, k; + for (k = 0; k < nb_pulse; k++) { + /* i = ((pos[k] & (16-1))*NB_TRACK) + track; */ + i = ((pos[k] & (16 - 1)) << 2) + track; + if ((pos[k] & 16) == 0) { + code[i] = code[i] + (FIXP_COD)(512 << (COD_BITS - FRACT_BITS)); + } else { + code[i] = code[i] - (FIXP_COD)(512 << (COD_BITS - FRACT_BITS)); + } + } + return; +} +/* + * D_ACELP_decode_1p_N1 + * + * Parameters: + * index I: pulse index + * N I: number of bits for position + * offset I: offset + * pos O: position of the pulse + * + * Function: + * Decode 1 pulse with N+1 bits + * + * Returns: + * void + */ +static void D_ACELP_decode_1p_N1(LONG index, SHORT N, SHORT offset, + SHORT pos[]) { + SHORT pos1; + LONG i, mask; + + mask = ((1 << N) - 1); + /* + * Decode 1 pulse with N+1 bits + */ + pos1 = (SHORT)((index & mask) + offset); + i = ((index >> N) & 1); + if (i == 1) { + pos1 += 16; + } + pos[0] = pos1; + return; +} +/* + * D_ACELP_decode_2p_2N1 + * + * Parameters: + * index I: pulse index + * N I: number of bits for position + * offset I: offset + * pos O: position of the pulse + * + * Function: + * Decode 2 pulses with 2*N+1 bits + * + * Returns: + * void + */ +static void D_ACELP_decode_2p_2N1(LONG index, SHORT N, SHORT offset, + SHORT pos[]) { + SHORT pos1, pos2; + LONG mask, i; + mask = ((1 << N) - 1); + /* + * Decode 2 pulses with 2*N+1 bits + */ + pos1 = (SHORT)(((index >> N) & mask) + offset); + i = (index >> (2 * N)) & 1; + pos2 = (SHORT)((index & mask) + offset); + if ((pos2 - pos1) < 0) { + if (i == 1) { + pos1 += 16; + } else { + pos2 += 16; + } + } else { + if (i == 1) { + pos1 += 16; + pos2 += 16; + } + } + pos[0] = pos1; + pos[1] = pos2; + return; +} +/* + * D_ACELP_decode_3p_3N1 + * + * Parameters: + * index I: pulse index + * N I: number of bits for position + * offset I: offset + * pos O: position of the pulse + * + * Function: + * Decode 3 pulses with 3*N+1 bits + * + * Returns: + * void + */ +static void D_ACELP_decode_3p_3N1(LONG index, SHORT N, SHORT offset, + SHORT pos[]) { + SHORT j; + LONG mask, idx; + + /* + * Decode 3 pulses with 3*N+1 bits + */ + mask = ((1 << ((2 * N) - 1)) - 1); + idx = index & mask; + j = offset; + if (((index >> ((2 * N) - 1)) & 1) == 1) { + j += (1 << (N - 1)); + } + D_ACELP_decode_2p_2N1(idx, N - 1, j, pos); + mask = ((1 << (N + 1)) - 1); + idx = (index >> (2 * N)) & mask; + D_ACELP_decode_1p_N1(idx, N, offset, pos + 2); + return; +} +/* + * D_ACELP_decode_4p_4N1 + * + * Parameters: + * index I: pulse index + * N I: number of bits for position + * offset I: offset + * pos O: position of the pulse + * + * Function: + * Decode 4 pulses with 4*N+1 bits + * + * Returns: + * void + */ +static void D_ACELP_decode_4p_4N1(LONG index, SHORT N, SHORT offset, + SHORT pos[]) { + SHORT j; + LONG mask, idx; + /* + * Decode 4 pulses with 4*N+1 bits + */ + mask = ((1 << ((2 * N) - 1)) - 1); + idx = index & mask; + j = offset; + if (((index >> ((2 * N) - 1)) & 1) == 1) { + j += (1 << (N - 1)); + } + D_ACELP_decode_2p_2N1(idx, N - 1, j, pos); + mask = ((1 << ((2 * N) + 1)) - 1); + idx = (index >> (2 * N)) & mask; + D_ACELP_decode_2p_2N1(idx, N, offset, pos + 2); + return; +} +/* + * D_ACELP_decode_4p_4N + * + * Parameters: + * index I: pulse index + * N I: number of bits for position + * offset I: offset + * pos O: position of the pulse + * + * Function: + * Decode 4 pulses with 4*N bits + * + * Returns: + * void + */ +static void D_ACELP_decode_4p_4N(LONG index, SHORT N, SHORT offset, + SHORT pos[]) { + SHORT j, n_1; + /* + * Decode 4 pulses with 4*N bits + */ + n_1 = N - 1; + j = offset + (1 << n_1); + switch ((index >> ((4 * N) - 2)) & 3) { + case 0: + if (((index >> ((4 * n_1) + 1)) & 1) == 0) { + D_ACELP_decode_4p_4N1(index, n_1, offset, pos); + } else { + D_ACELP_decode_4p_4N1(index, n_1, j, pos); + } + break; + case 1: + D_ACELP_decode_1p_N1((index >> ((3 * n_1) + 1)), n_1, offset, pos); + D_ACELP_decode_3p_3N1(index, n_1, j, pos + 1); + break; + case 2: + D_ACELP_decode_2p_2N1((index >> ((2 * n_1) + 1)), n_1, offset, pos); + D_ACELP_decode_2p_2N1(index, n_1, j, pos + 2); + break; + case 3: + D_ACELP_decode_3p_3N1((index >> (n_1 + 1)), n_1, offset, pos); + D_ACELP_decode_1p_N1(index, n_1, j, pos + 3); + break; + } + return; +} + +/* + * D_ACELP_decode_4t + * + * Parameters: + * index I: index + * mode I: speech mode + * code I: (Q9) algebraic (fixed) codebook excitation + * + * Function: + * 20, 36, 44, 52, 64, 72, 88 bits algebraic codebook. + * 4 tracks x 16 positions per track = 64 samples. + * + * 20 bits 5+5+5+5 --> 4 pulses in a frame of 64 samples. + * 36 bits 9+9+9+9 --> 8 pulses in a frame of 64 samples. + * 44 bits 13+9+13+9 --> 10 pulses in a frame of 64 samples. + * 52 bits 13+13+13+13 --> 12 pulses in a frame of 64 samples. + * 64 bits 2+2+2+2+14+14+14+14 --> 16 pulses in a frame of 64 samples. + * 72 bits 10+2+10+2+10+14+10+14 --> 18 pulses in a frame of 64 samples. + * 88 bits 11+11+11+11+11+11+11+11 --> 24 pulses in a frame of 64 samples. + * + * All pulses can have two (2) possible amplitudes: +1 or -1. + * Each pulse can sixteen (16) possible positions. + * + * codevector length 64 + * number of track 4 + * number of position 16 + * + * Returns: + * void + */ +void D_ACELP_decode_4t64(SHORT index[], int nbits, FIXP_COD code[]) { + LONG L_index; + SHORT k, pos[6]; + + FDKmemclear(code, L_SUBFR * sizeof(FIXP_COD)); + + /* decode the positions and signs of pulses and build the codeword */ + switch (nbits) { + case 12: + for (k = 0; k < 4; k += 2) { + L_index = index[2 * (k / 2) + 1]; + D_ACELP_decode_1p_N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 1, 2 * (index[2 * (k / 2)]) + k / 2, code); + } + break; + case 16: { + int i = 0; + int offset = index[i++]; + offset = (offset == 0) ? 1 : 3; + for (k = 0; k < 4; k++) { + if (k != offset) { + L_index = index[i++]; + D_ACELP_decode_1p_N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 1, k, code); + } + } + } break; + case 20: + for (k = 0; k < 4; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_1p_N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 1, k, code); + } + break; + case 28: + for (k = 0; k < 4 - 2; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_2p_2N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 2, k, code); + } + for (k = 2; k < 4; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_1p_N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 1, k, code); + } + break; + case 36: + for (k = 0; k < 4; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_2p_2N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 2, k, code); + } + break; + case 44: + for (k = 0; k < 4 - 2; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_3p_3N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 3, k, code); + } + for (k = 2; k < 4; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_2p_2N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 2, k, code); + } + break; + case 52: + for (k = 0; k < 4; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_3p_3N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 3, k, code); + } + break; + case 64: + for (k = 0; k < 4; k++) { + L_index = (((LONG)index[k] << 14) + (LONG)index[k + 4]); + D_ACELP_decode_4p_4N(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 4, k, code); + } + break; + default: + FDK_ASSERT(0); + } + return; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_d4t64.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_d4t64.h new file mode 100644 index 0000000000000..76bc3d9922272 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_d4t64.h @@ -0,0 +1,117 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: ACELP + +*******************************************************************************/ + +#ifndef USACDEC_ACE_D4T64_H +#define USACDEC_ACE_D4T64_H + +#include "common_fix.h" + +/* Data type definition for the fixed codebook vector */ +#define FIXP_COD FIXP_SGL +#define FX_COD2FX_DBL(x) (FX_SGL2FX_DBL(x)) +#define FX_DBL2FX_COD(x) FX_DBL2FX_SGL((x) + (FIXP_DBL)0x8000) +#define FX_SGL2FX_COD(x) (x) +#define COD_BITS FRACT_BITS + +void D_ACELP_decode_4t64(SHORT index[], int nbits, FIXP_COD code[]); + +#endif /* USACDEC_ACE_D4T64_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_ltp.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_ltp.cpp new file mode 100644 index 0000000000000..5964b493575fe --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_ltp.cpp @@ -0,0 +1,229 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: USAC ACELP LTP filter + +*******************************************************************************/ + +#include "usacdec_ace_ltp.h" + +#include "genericStds.h" +#include "common_fix.h" + +#define UP_SAMP 4 +#define L_INTERPOL2 16 +#define L_SUBFR 64 + +#define A2 FL2FX_SGL(2 * 0.18f) +#define B FL2FX_SGL(0.64f) + +static const LONG Pred_lt4_inter4_2[UP_SAMP][L_INTERPOL2] = { + {(LONG)0x0000FFFC, (LONG)0x0008FFFC, (LONG)0xFFEB004C, (LONG)0xFF50014A, + (LONG)0xFDD90351, (LONG)0xFB2A06CD, (LONG)0xF6920D46, (LONG)0xEBB42B35, + (LONG)0x6D9EEF39, (LONG)0x0618FE0F, (LONG)0xFFE00131, (LONG)0xFE5501C5, + (LONG)0xFE5E015D, (LONG)0xFEF700B6, (LONG)0xFF920037, (LONG)0xFFEC0003}, + {(LONG)0x0002FFF2, (LONG)0x0026FFBD, (LONG)0x005DFF98, (LONG)0x0055FFEF, + (LONG)0xFF89015F, (LONG)0xFD3A04E5, (LONG)0xF7D90DAA, (LONG)0xE67A50EE, + (LONG)0x50EEE67A, (LONG)0x0DAAF7D9, (LONG)0x04E5FD3A, (LONG)0x015FFF89, + (LONG)0xFFEF0055, (LONG)0xFF98005D, (LONG)0xFFBD0026, (LONG)0xFFF20002}, + {(LONG)0x0003FFEC, (LONG)0x0037FF92, (LONG)0x00B6FEF7, (LONG)0x015DFE5E, + (LONG)0x01C5FE55, (LONG)0x0131FFE0, (LONG)0xFE0F0618, (LONG)0xEF396D9E, + (LONG)0x2B35EBB4, (LONG)0x0D46F692, (LONG)0x06CDFB2A, (LONG)0x0351FDD9, + (LONG)0x014AFF50, (LONG)0x004CFFEB, (LONG)0xFFFC0008, (LONG)0xFFFC0000}, + {(LONG)0x0002FFF2, (LONG)0x002BFF9E, (LONG)0x00B9FECE, (LONG)0x01CFFD75, + (LONG)0x035EFBC1, (LONG)0x0521FA0C, (LONG)0x06AAF8C9, (LONG)0x07907852, + (LONG)0x0790F8C9, (LONG)0x06AAFA0C, (LONG)0x0521FBC1, (LONG)0x035EFD75, + (LONG)0x01CFFECE, (LONG)0x00B9FF9E, (LONG)0x002BFFF2, (LONG)0x00020000}}; + +void Pred_lt4(FIXP_DBL exc[], /* in/out: excitation buffer */ + int T0, /* input : integer pitch lag */ + int frac /* input : fraction of lag in range 0..3 */ +) { + int j; + FIXP_DBL *x; + const LONG *interpol; + FIXP_DBL L_sumb, L_sumt; + + x = &exc[-T0 - L_INTERPOL2 + 1]; + + /* remap frac and x: + 0 -> 3 x (unchanged) + 1 -> 0 x-- + 2 -> 1 x-- + 3 -> 2 x-- + */ + + if (--frac < 0) + frac += UP_SAMP; + else + x--; + + j = L_SUBFR + 1; + do { + LONG filt; + FIXP_DBL x0, x1; + FIXP_DBL *xi = x++; + interpol = Pred_lt4_inter4_2[frac]; + int i = 3; + + filt = *interpol++; + x0 = *xi++; + x1 = *xi++; + L_sumt = fMultDiv2(x0, (FIXP_SGL)((SHORT)(filt >> 16))); + L_sumb = fMultDiv2(x1, (FIXP_SGL)((SHORT)filt)); + do { + filt = *interpol++; + x0 = *xi++; + x1 = *xi++; + L_sumt = fMultAddDiv2(L_sumt, x0, (FIXP_SGL)((SHORT)(filt >> 16))); + L_sumb = fMultAddDiv2(L_sumb, x1, (FIXP_SGL)((SHORT)filt)); + + filt = *interpol++; + x0 = *xi++; + x1 = *xi++; + L_sumt = fMultAddDiv2(L_sumt, x0, (FIXP_SGL)((SHORT)(filt >> 16))); + L_sumb = fMultAddDiv2(L_sumb, x1, (FIXP_SGL)((SHORT)filt)); + + filt = *interpol++; + x0 = *xi++; + x1 = *xi++; + L_sumt = fMultAddDiv2(L_sumt, x0, (FIXP_SGL)((SHORT)(filt >> 16))); + L_sumb = fMultAddDiv2(L_sumb, x1, (FIXP_SGL)((SHORT)filt)); + + filt = *interpol++; + x0 = *xi++; + x1 = *xi++; + L_sumt = fMultAddDiv2(L_sumt, x0, (FIXP_SGL)((SHORT)(filt >> 16))); + L_sumb = fMultAddDiv2(L_sumb, x1, (FIXP_SGL)((SHORT)filt)); + + filt = *interpol++; + x0 = *xi++; + x1 = *xi++; + L_sumt = fMultAddDiv2(L_sumt, x0, (FIXP_SGL)((SHORT)(filt >> 16))); + L_sumb = fMultAddDiv2(L_sumb, x1, (FIXP_SGL)((SHORT)filt)); + } while (--i != 0); + + L_sumb <<= 1; + L_sumb = fAddSaturate(L_sumt << 1, L_sumb); + *exc++ = L_sumb; + } while (--j != 0); + return; +} + +void Pred_lt4_postfilter(FIXP_DBL exc[] /* in/out: excitation buffer */ +) { + /* + exc[i] = A*exc[i-1] + B*exc[i] + A*exc[i+1] + exc[i+1] = A*exc[i] + B*exc[i+1] + A*exc[i+2] ; i = 0:2:62 + */ + int i; + FIXP_DBL sum0, sum1, a_exc0, a_exc1; + a_exc0 = fMultDiv2(A2, exc[-1]); + a_exc1 = fMultDiv2(A2, exc[0]); + + /* ARM926: 22 cycles/iteration */ + for (i = 0; i < L_SUBFR; i += 2) { + sum0 = a_exc0 + fMult(B, exc[i]); + sum1 = a_exc1 + fMult(B, exc[i + 1]); + a_exc0 = fMultDiv2(A2, exc[i + 1]); + a_exc1 = fMultDiv2(A2, exc[i + 2]); + exc[i] = sum0 + a_exc0; + exc[i + 1] = sum1 + a_exc1; + } + return; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_ltp.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_ltp.h new file mode 100644 index 0000000000000..5128acdd9515e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_ace_ltp.h @@ -0,0 +1,128 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: USAC ACELP LTP filter + +*******************************************************************************/ + +#ifndef USACDEC_ACE_LTP_H +#define USACDEC_ACE_LTP_H + +#include "common_fix.h" + +/** + * \brief Compute the initial adaptive codebook excitation v'(n) by + * interpolating the past excitation vector u'(n). + * \param exc points to adaptive codebook of current subframe (input/output) + * \param T0 integer part of decoded pitch lag (input) + * \param frac fractional part of decoded pitch lag (0..3) (input) + */ +void Pred_lt4(FIXP_DBL exc[], /* in/out: excitation buffer */ + int T0, /* input : integer pitch lag */ + int frac /* input : fraction of lag */ +); + +/** + * \brief Compute the adaptive codebook excitation v(n) in case of + * ltp_filtering_flag == 0. + * \param exc points to adaptive codebook of current subframe (input/output) + */ +void Pred_lt4_postfilter(FIXP_DBL exc[] /* in/out: excitation buffer */ +); + +#endif /* USACDEC_ACE_LTP_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_acelp.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_acelp.cpp new file mode 100644 index 0000000000000..9769a07a17c88 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_acelp.cpp @@ -0,0 +1,1299 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: USAC ACELP frame decoder + +*******************************************************************************/ + +#include "usacdec_acelp.h" + +#include "usacdec_ace_d4t64.h" +#include "usacdec_ace_ltp.h" +#include "usacdec_rom.h" +#include "usacdec_lpc.h" +#include "genericStds.h" + +#define PIT_FR2_12k8 128 /* Minimum pitch lag with resolution 1/2 */ +#define PIT_FR1_12k8 160 /* Minimum pitch lag with resolution 1 */ +#define TILT_CODE2 \ + FL2FXCONST_SGL(0.3f * 2.0f) /* ACELP code pre-emphasis factor ( *2 ) */ +#define PIT_SHARP \ + FL2FXCONST_SGL(0.85f) /* pitch sharpening factor */ +#define PREEMPH_FAC \ + FL2FXCONST_SGL(0.68f) /* ACELP synth pre-emphasis factor */ + +#define ACELP_HEADROOM 1 +#define ACELP_OUTSCALE (MDCT_OUT_HEADROOM - ACELP_HEADROOM) + +/** + * \brief Calculate pre-emphasis (1 - mu z^-1) on input signal. + * \param[in] in pointer to input signal; in[-1] is also needed. + * \param[out] out pointer to output signal. + * \param[in] L length of filtering. + */ +/* static */ +void E_UTIL_preemph(const FIXP_DBL *in, FIXP_DBL *out, INT L) { + int i; + + for (i = 0; i < L; i++) { + out[i] = fAddSaturate(in[i], -fMult(PREEMPH_FAC, in[i - 1])); + } + + return; +} + +/** + * \brief Calculate de-emphasis 1/(1 - TILT_CODE z^-1) on innovative codebook + * vector. + * \param[in,out] x innovative codebook vector. + */ +static void Preemph_code( + FIXP_COD x[] /* (i/o) : input signal overwritten by the output */ +) { + int i; + FIXP_DBL L_tmp; + + /* ARM926: 12 cycles per sample */ + for (i = L_SUBFR - 1; i > 0; i--) { + L_tmp = FX_COD2FX_DBL(x[i]); + L_tmp -= fMultDiv2(x[i - 1], TILT_CODE2); + x[i] = FX_DBL2FX_COD(L_tmp); + } +} + +/** + * \brief Apply pitch sharpener to the innovative codebook vector. + * \param[in,out] x innovative codebook vector. + * \param[in] pit_lag decoded pitch lag. + */ +static void Pit_shrp( + FIXP_COD x[], /* in/out: impulse response (or algebraic code) */ + int pit_lag /* input : pitch lag */ +) { + int i; + FIXP_DBL L_tmp; + + for (i = pit_lag; i < L_SUBFR; i++) { + L_tmp = FX_COD2FX_DBL(x[i]); + L_tmp += fMult(x[i - pit_lag], PIT_SHARP); + x[i] = FX_DBL2FX_COD(L_tmp); + } + + return; +} + + /** + * \brief Calculate Quantized codebook gain, Quantized pitch gain and unbiased + * Innovative code vector energy. + * \param[in] index index of quantizer. + * \param[in] code innovative code vector with exponent = SF_CODE. + * \param[out] gain_pit Quantized pitch gain g_p with exponent = SF_GAIN_P. + * \param[out] gain_code Quantized codebook gain g_c. + * \param[in] mean_ener mean_ener defined in open-loop (2 bits), exponent = 7. + * \param[out] E_code unbiased innovative code vector energy. + * \param[out] E_code_e exponent of unbiased innovative code vector energy. + */ + +#define SF_MEAN_ENER_LG10 9 + +/* pow(10.0, {18, 30, 42, 54}/20.0) /(float)(1<>= 1; + } else { + ener_code_e -= 6; + } + gcode_inov = invSqrtNorm2(ener_code, &gcode0_e); + gcode_inov_e = gcode0_e - (ener_code_e >> 1); + + if (bfi) { + FIXP_DBL tgcode; + FIXP_SGL tgpit; + + tgpit = *past_gpit; + + if (tgpit > FL2FXCONST_SGL(0.95f / (1 << SF_GAIN_P))) { + tgpit = FL2FXCONST_SGL(0.95f / (1 << SF_GAIN_P)); + } else if (tgpit < FL2FXCONST_SGL(0.5f / (1 << SF_GAIN_P))) { + tgpit = FL2FXCONST_SGL(0.5f / (1 << SF_GAIN_P)); + } + *gain_pit = tgpit; + tgpit = FX_DBL2FX_SGL(fMult(tgpit, FL2FXCONST_DBL(0.95f))); + *past_gpit = tgpit; + + tgpit = FL2FXCONST_SGL(1.4f / (1 << SF_GAIN_P)) - tgpit; + tgcode = fMult(*past_gcode, tgpit) << SF_GAIN_P; + *gain_code = scaleValue(fMult(tgcode, gcode_inov), gcode_inov_e); + *past_gcode = tgcode; + + return; + } + + /*-------------- Decode gains ---------------*/ + /* + gcode0 = pow(10.0, (float)mean_ener/20.0); + gcode0 = gcode0 / sqrt(ener_code/L_SUBFR); + */ + gcode0 = pow_10_mean_energy[mean_ener_bits]; + gcode0 = fMultDiv2(gcode0, gcode_inov); + gcode0_e = gcode0_e + SF_MEAN_ENER_LG10 - (ener_code_e >> 1) + 1; + + i = index << 1; + *gain_pit = fdk_t_qua_gain7b[i]; /* adaptive codebook gain */ + /* t_qua_gain[ind2p1] : fixed codebook gain correction factor */ + Ltmp = fMult(fdk_t_qua_gain7b[i + 1], gcode0); + *gain_code = scaleValue(Ltmp, gcode0_e - SF_GAIN_C + SF_QUA_GAIN7B); + + /* update bad frame handler */ + *past_gpit = *gain_pit; + + /*-------------------------------------------------------- + past_gcode = gain_code/gcode_inov + --------------------------------------------------------*/ + { + FIXP_DBL gcode_m; + INT gcode_e; + + gcode_m = fDivNormHighPrec(Ltmp, gcode_inov, &gcode_e); + gcode_e += (gcode0_e - SF_GAIN_C + SF_QUA_GAIN7B) - (gcode_inov_e); + *past_gcode = scaleValue(gcode_m, gcode_e); + } +} + +/** + * \brief Calculate period/voicing factor r_v + * \param[in] exc pitch excitation. + * \param[in] gain_pit gain of pitch g_p. + * \param[in] gain_code gain of code g_c. + * \param[in] gain_code_e exponent of gain of code. + * \param[in] ener_code unbiased innovative code vector energy. + * \param[in] ener_code_e exponent of unbiased innovative code vector energy. + * \return period/voice factor r_v (-1=unvoiced to 1=voiced), exponent SF_PFAC. + */ +static FIXP_DBL calc_period_factor(FIXP_DBL exc[], FIXP_SGL gain_pit, + FIXP_DBL gain_code, FIXP_DBL ener_code, + int ener_code_e) { + int ener_exc_e, L_tmp_e, s = 0; + FIXP_DBL ener_exc, L_tmp; + FIXP_DBL period_fac; + + /* energy of pitch excitation */ + ener_exc = (FIXP_DBL)0; + for (int i = 0; i < L_SUBFR; i++) { + ener_exc += fPow2Div2(exc[i]) >> s; + if (ener_exc >= FL2FXCONST_DBL(0.5f)) { + ener_exc >>= 1; + s++; + } + } + + ener_exc_e = fNorm(ener_exc); + ener_exc = fMult(ener_exc << ener_exc_e, fPow2(gain_pit)); + if (ener_exc != (FIXP_DBL)0) { + ener_exc_e = 2 * SF_EXC + 1 + 2 * SF_GAIN_P - ener_exc_e + s; + } else { + ener_exc_e = 0; + } + + /* energy of innovative code excitation */ + /* L_tmp = ener_code * gain_code*gain_code; */ + L_tmp_e = fNorm(gain_code); + L_tmp = fPow2(gain_code << L_tmp_e); + L_tmp = fMult(ener_code, L_tmp); + L_tmp_e = 2 * SF_GAIN_C + ener_code_e - 2 * L_tmp_e; + + /* Find common exponent */ + { + FIXP_DBL num, den; + int exp_diff; + + exp_diff = ener_exc_e - L_tmp_e; + if (exp_diff >= 0) { + ener_exc >>= 1; + if (exp_diff <= DFRACT_BITS - 2) { + L_tmp >>= exp_diff + 1; + } else { + L_tmp = (FIXP_DBL)0; + } + den = ener_exc + L_tmp; + if (ener_exc_e < DFRACT_BITS - 1) { + den += scaleValue(FL2FXCONST_DBL(0.01f), -ener_exc_e - 1); + } + } else { + if (exp_diff >= -(DFRACT_BITS - 2)) { + ener_exc >>= 1 - exp_diff; + } else { + ener_exc = (FIXP_DBL)0; + } + L_tmp >>= 1; + den = ener_exc + L_tmp; + if (L_tmp_e < DFRACT_BITS - 1) { + den += scaleValue(FL2FXCONST_DBL(0.01f), -L_tmp_e - 1); + } + } + num = (ener_exc - L_tmp); + num >>= SF_PFAC; + + if (den > (FIXP_DBL)0) { + if (ener_exc > L_tmp) { + period_fac = schur_div(num, den, 16); + } else { + period_fac = -schur_div(-num, den, 16); + } + } else { + period_fac = (FIXP_DBL)MAXVAL_DBL; + } + } + + /* exponent = SF_PFAC */ + return period_fac; +} + +/*------------------------------------------------------------* + * noise enhancer * + * ~~~~~~~~~~~~~~ * + * - Enhance excitation on noise. (modify gain of code) * + * If signal is noisy and LPC filter is stable, move gain * + * of code 1.5 dB toward gain of code threshold. * + * This decrease by 3 dB noise energy variation. * + *------------------------------------------------------------*/ +/** + * \brief Enhance excitation on noise. (modify gain of code) + * \param[in] gain_code Quantized codebook gain g_c, exponent = SF_GAIN_C. + * \param[in] period_fac periodicity factor, exponent = SF_PFAC. + * \param[in] stab_fac stability factor, exponent = SF_STAB. + * \param[in,out] p_gc_threshold modified gain of previous subframe. + * \return gain_code smoothed gain of code g_sc, exponent = SF_GAIN_C. + */ +static FIXP_DBL +noise_enhancer(/* (o) : smoothed gain g_sc SF_GAIN_C */ + FIXP_DBL gain_code, /* (i) : Quantized codebook gain SF_GAIN_C */ + FIXP_DBL period_fac, /* (i) : periodicity factor (-1=unvoiced to + 1=voiced), SF_PFAC */ + FIXP_SGL stab_fac, /* (i) : stability factor (0 <= ... < 1.0) + SF_STAB */ + FIXP_DBL + *p_gc_threshold) /* (io): gain of code threshold SF_GAIN_C */ +{ + FIXP_DBL fac, L_tmp, gc_thres; + + gc_thres = *p_gc_threshold; + + L_tmp = gain_code; + if (L_tmp < gc_thres) { + L_tmp += fMultDiv2(gain_code, + FL2FXCONST_SGL(2.0 * 0.19f)); /* +1.5dB => *(1.0+0.19) */ + if (L_tmp > gc_thres) { + L_tmp = gc_thres; + } + } else { + L_tmp = fMult(gain_code, + FL2FXCONST_SGL(1.0f / 1.19f)); /* -1.5dB => *10^(-1.5/20) */ + if (L_tmp < gc_thres) { + L_tmp = gc_thres; + } + } + *p_gc_threshold = L_tmp; + + /* voicing factor lambda = 0.5*(1-period_fac) */ + /* gain smoothing factor S_m = lambda*stab_fac (=fac) + = 0.5(stab_fac - stab_fac * period_fac) */ + fac = (FX_SGL2FX_DBL(stab_fac) >> (SF_PFAC + 1)) - + fMultDiv2(stab_fac, period_fac); + /* fac_e = SF_PFAC + SF_STAB */ + FDK_ASSERT(fac >= (FIXP_DBL)0); + + /* gain_code = (float)((fac*tmp) + ((1.0-fac)*gain_code)); */ + gain_code = fMult(fac, L_tmp) - + fMult(FL2FXCONST_DBL(-1.0f / (1 << (SF_PFAC + SF_STAB))) + fac, + gain_code); + gain_code <<= (SF_PFAC + SF_STAB); + + return gain_code; +} + +/** + * \brief Update adaptive codebook u'(n) (exc) + * Enhance pitch of c(n) and build post-processed excitation u(n) (exc2) + * \param[in] code innovative codevector c(n), exponent = SF_CODE. + * \param[in,out] exc filtered adaptive codebook v(n), exponent = SF_EXC. + * \param[in] gain_pit adaptive codebook gain, exponent = SF_GAIN_P. + * \param[in] gain_code innovative codebook gain g_c, exponent = SF_GAIN_C. + * \param[in] gain_code_smoothed smoothed innov. codebook gain g_sc, exponent = + * SF_GAIN_C. + * \param[in] period_fac periodicity factor r_v, exponent = SF_PFAC. + * \param[out] exc2 post-processed excitation u(n), exponent = SF_EXC. + */ +void BuildAdaptiveExcitation( + FIXP_COD code[], /* (i) : algebraic codevector c(n) Q9 */ + FIXP_DBL exc[], /* (io): filtered adaptive codebook v(n) Q15 */ + FIXP_SGL gain_pit, /* (i) : adaptive codebook gain g_p Q14 */ + FIXP_DBL gain_code, /* (i) : innovative codebook gain g_c Q16 */ + FIXP_DBL gain_code_smoothed, /* (i) : smoothed innov. codebook gain g_sc + Q16 */ + FIXP_DBL period_fac, /* (i) : periodicity factor r_v Q15 */ + FIXP_DBL exc2[] /* (o) : post-processed excitation u(n) Q15 */ +) { +/* Note: code[L_SUBFR] and exc2[L_SUBFR] share the same memory! + If exc2[i] is written, code[i] will be destroyed! +*/ +#define SF_HEADROOM (1) +#define SF (SF_CODE + SF_GAIN_C + 1 - SF_EXC - SF_HEADROOM) +#define SF_GAIN_P2 (SF_GAIN_P - SF_HEADROOM) + + int i; + FIXP_DBL tmp, cpe, code_smooth_prev, code_smooth; + + FIXP_COD code_i; + FIXP_DBL cpe_code_smooth, cpe_code_smooth_prev; + + /* cpe = (1+r_v)/8 * 2 ; ( SF = -1) */ + cpe = (period_fac >> (2 - SF_PFAC)) + FL2FXCONST_DBL(0.25f); + + /* u'(n) */ + tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P2 + 1); /* v(0)*g_p */ + *exc++ = (tmp + (fMultDiv2(code[0], gain_code) << SF)) << SF_HEADROOM; + + /* u(n) */ + code_smooth_prev = fMultDiv2(*code++, gain_code_smoothed) + << SF; /* c(0) * g_sc */ + code_i = *code++; + code_smooth = fMultDiv2(code_i, gain_code_smoothed) << SF; /* c(1) * g_sc */ + tmp += code_smooth_prev; /* tmp = v(0)*g_p + c(0)*g_sc */ + cpe_code_smooth = fMultDiv2(cpe, code_smooth); + *exc2++ = (tmp - cpe_code_smooth) << SF_HEADROOM; + cpe_code_smooth_prev = fMultDiv2(cpe, code_smooth_prev); + + i = L_SUBFR - 2; + do /* ARM926: 22 cycles per iteration */ + { + /* u'(n) */ + tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P2 + 1); + *exc++ = (tmp + (fMultDiv2(code_i, gain_code) << SF)) << SF_HEADROOM; + /* u(n) */ + tmp += code_smooth; /* += g_sc * c(i) */ + tmp -= cpe_code_smooth_prev; + cpe_code_smooth_prev = cpe_code_smooth; + code_i = *code++; + code_smooth = fMultDiv2(code_i, gain_code_smoothed) << SF; + cpe_code_smooth = fMultDiv2(cpe, code_smooth); + *exc2++ = (tmp - cpe_code_smooth) + << SF_HEADROOM; /* tmp - c_pe * g_sc * c(i+1) */ + } while (--i != 0); + + /* u'(n) */ + tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P2 + 1); + *exc = (tmp + (fMultDiv2(code_i, gain_code) << SF)) << SF_HEADROOM; + /* u(n) */ + tmp += code_smooth; + tmp -= cpe_code_smooth_prev; + *exc2++ = tmp << SF_HEADROOM; + + return; +} + +/** + * \brief Interpolate LPC vector in LSP domain for current subframe and convert + * to LP domain + * \param[in] lsp_old LPC vector (LSP domain) corresponding to the beginning of + * current ACELP frame. + * \param[in] lsp_new LPC vector (LSP domain) corresponding to the end of + * current ACELP frame. + * \param[in] subfr_nr number of current ACELP subframe 0..3. + * \param[in] nb_subfr total number of ACELP subframes in this frame. + * \param[out] A LP filter coefficients for current ACELP subframe, exponent = + * SF_A_COEFFS. + */ +/* static */ +void int_lpc_acelp( + const FIXP_LPC lsp_old[], /* input : LSPs from past frame */ + const FIXP_LPC lsp_new[], /* input : LSPs from present frame */ + int subfr_nr, int nb_subfr, + FIXP_LPC + A[], /* output: interpolated LP coefficients for current subframe */ + INT *A_exp) { + int i; + FIXP_LPC lsp_interpol[M_LP_FILTER_ORDER]; + FIXP_SGL fac_old, fac_new; + + FDK_ASSERT((nb_subfr == 3) || (nb_subfr == 4)); + + fac_old = lsp_interpol_factor[nb_subfr & 0x1][(nb_subfr - 1) - subfr_nr]; + fac_new = lsp_interpol_factor[nb_subfr & 0x1][subfr_nr]; + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp_interpol[i] = FX_DBL2FX_LPC( + (fMultDiv2(lsp_old[i], fac_old) + fMultDiv2(lsp_new[i], fac_new)) << 1); + } + + E_LPC_f_lsp_a_conversion(lsp_interpol, A, A_exp); + + return; +} + +/** + * \brief Perform LP synthesis by filtering the post-processed excitation u(n) + * through the LP synthesis filter 1/A(z) + * \param[in] a LP filter coefficients, exponent = SF_A_COEFFS. + * \param[in] length length of input/output signal. + * \param[in] x post-processed excitation u(n). + * \param[in,out] y LP synthesis signal and filter memory + * y[-M_LP_FILTER_ORDER..-1]. + */ + +/* static */ +void Syn_filt(const FIXP_LPC a[], /* (i) : a[m] prediction coefficients Q12 */ + const INT a_exp, + INT length, /* (i) : length of input/output signal (64|128) */ + FIXP_DBL x[], /* (i) : input signal Qx */ + FIXP_DBL y[] /* (i/o) : filter states / output signal Qx-s*/ +) { + int i, j; + FIXP_DBL L_tmp; + + for (i = 0; i < length; i++) { + L_tmp = (FIXP_DBL)0; + + for (j = 0; j < M_LP_FILTER_ORDER; j++) { + L_tmp -= fMultDiv2(a[j], y[i - (j + 1)]) >> (LP_FILTER_SCALE - 1); + } + + L_tmp = scaleValue(L_tmp, a_exp + LP_FILTER_SCALE); + y[i] = fAddSaturate(L_tmp, x[i]); + } + + return; +} + +/** + * \brief Calculate de-emphasis 1/(1 - mu z^-1) on input signal. + * \param[in] x input signal. + * \param[out] y output signal. + * \param[in] L length of signal. + * \param[in,out] mem memory (signal[-1]). + */ +/* static */ +void Deemph(FIXP_DBL *x, FIXP_DBL *y, int L, FIXP_DBL *mem) { + int i; + FIXP_DBL yi = *mem; + + for (i = 0; i < L; i++) { + FIXP_DBL xi = x[i] >> 1; + xi = fMultAddDiv2(xi, PREEMPH_FAC, yi); + yi = SATURATE_LEFT_SHIFT(xi, 1, 32); + y[i] = yi; + } + *mem = yi; + return; +} + +/** + * \brief Compute the LP residual by filtering the input speech through the + * analysis filter A(z). + * \param[in] a LP filter coefficients, exponent = SF_A_COEFFS + * \param[in] x input signal (note that values x[-m..-1] are needed), exponent = + * SF_SYNTH + * \param[out] y output signal (residual), exponent = SF_EXC + * \param[in] l length of filtering + */ +/* static */ +void E_UTIL_residu(const FIXP_LPC *a, const INT a_exp, FIXP_DBL *x, FIXP_DBL *y, + INT l) { + FIXP_DBL s; + INT i, j; + + /* (note that values x[-m..-1] are needed) */ + for (i = 0; i < l; i++) { + s = (FIXP_DBL)0; + + for (j = 0; j < M_LP_FILTER_ORDER; j++) { + s += fMultDiv2(a[j], x[i - j - 1]) >> (LP_FILTER_SCALE - 1); + } + + s = scaleValue(s, a_exp + LP_FILTER_SCALE); + y[i] = fAddSaturate(s, x[i]); + } + + return; +} + +/* use to map subfr number to number of bits used for acb_index */ +static const UCHAR num_acb_idx_bits_table[2][NB_SUBFR] = { + {9, 6, 9, 6}, /* coreCoderFrameLength == 1024 */ + {9, 6, 6, 0} /* coreCoderFrameLength == 768 */ +}; + +static int DecodePitchLag(HANDLE_FDK_BITSTREAM hBs, + const UCHAR num_acb_idx_bits, + const int PIT_MIN, /* TMIN */ + const int PIT_FR2, /* TFR2 */ + const int PIT_FR1, /* TFR1 */ + const int PIT_MAX, /* TMAX */ + int *pT0, int *pT0_frac, int *pT0_min, int *pT0_max) { + int acb_idx; + int error = 0; + int T0, T0_frac; + + FDK_ASSERT((num_acb_idx_bits == 9) || (num_acb_idx_bits == 6)); + + acb_idx = FDKreadBits(hBs, num_acb_idx_bits); + + if (num_acb_idx_bits == 6) { + /* When the pitch value is encoded on 6 bits, a pitch resolution of 1/4 is + always used in the range [T1-8, T1+7.75], where T1 is nearest integer to + the fractional pitch lag of the previous subframe. + */ + T0 = *pT0_min + acb_idx / 4; + T0_frac = acb_idx & 0x3; + } else { /* num_acb_idx_bits == 9 */ + /* When the pitch value is encoded on 9 bits, a fractional pitch delay is + used with resolutions 0.25 in the range [TMIN, TFR2-0.25], resolutions + 0.5 in the range [TFR2, TFR1-0.5], and integers only in the range [TFR1, + TMAX]. NOTE: for small sampling rates TMAX can get smaller than TFR1. + */ + int T0_min, T0_max; + + if (acb_idx < (PIT_FR2 - PIT_MIN) * 4) { + /* first interval with 0.25 pitch resolution */ + T0 = PIT_MIN + (acb_idx / 4); + T0_frac = acb_idx & 0x3; + } else if (acb_idx < ((PIT_FR2 - PIT_MIN) * 4 + (PIT_FR1 - PIT_FR2) * 2)) { + /* second interval with 0.5 pitch resolution */ + acb_idx -= (PIT_FR2 - PIT_MIN) * 4; + T0 = PIT_FR2 + (acb_idx / 2); + T0_frac = (acb_idx & 0x1) * 2; + } else { + /* third interval with 1.0 pitch resolution */ + T0 = acb_idx + PIT_FR1 - ((PIT_FR2 - PIT_MIN) * 4) - + ((PIT_FR1 - PIT_FR2) * 2); + T0_frac = 0; + } + /* find T0_min and T0_max for subframe 1 or 3 */ + T0_min = T0 - 8; + if (T0_min < PIT_MIN) { + T0_min = PIT_MIN; + } + T0_max = T0_min + 15; + if (T0_max > PIT_MAX) { + T0_max = PIT_MAX; + T0_min = T0_max - 15; + } + *pT0_min = T0_min; + *pT0_max = T0_max; + } + *pT0 = T0; + *pT0_frac = T0_frac; + + return error; +} +static void ConcealPitchLag(CAcelpStaticMem *acelp_mem, const int PIT_MAX, + int *pT0, int *pT0_frac) { + USHORT *pold_T0 = &acelp_mem->old_T0; + UCHAR *pold_T0_frac = &acelp_mem->old_T0_frac; + + if ((int)*pold_T0 >= PIT_MAX) { + *pold_T0 = (USHORT)(PIT_MAX - 5); + } + *pT0 = (int)*pold_T0; + *pT0_frac = (int)*pold_T0_frac; +} + +static UCHAR tab_coremode2nbits[8] = {20, 28, 36, 44, 52, 64, 12, 16}; + +static int MapCoreMode2NBits(int core_mode) { + return (int)tab_coremode2nbits[core_mode]; +} + +void CLpd_AcelpDecode(CAcelpStaticMem *acelp_mem, INT i_offset, + const FIXP_LPC lsp_old[M_LP_FILTER_ORDER], + const FIXP_LPC lsp_new[M_LP_FILTER_ORDER], + FIXP_SGL stab_fac, CAcelpChannelData *pAcelpData, + INT numLostSubframes, int lastLpcLost, int frameCnt, + FIXP_DBL synth[], int pT[], FIXP_DBL *pit_gain, + INT coreCoderFrameLength) { + int i_subfr, subfr_nr, l_div, T; + int T0 = -1, T0_frac = -1; /* mark invalid */ + + int pit_gain_index = 0; + + const int PIT_MAX = PIT_MAX_12k8 + (6 * i_offset); /* maximum pitch lag */ + + FIXP_COD *code; + FIXP_DBL *exc2; + FIXP_DBL *syn; + FIXP_DBL *exc; + FIXP_LPC A[M_LP_FILTER_ORDER]; + INT A_exp; + + FIXP_DBL period_fac; + FIXP_SGL gain_pit; + FIXP_DBL gain_code, gain_code_smooth, Ener_code; + int Ener_code_e; + int n; + int bfi = (numLostSubframes > 0) ? 1 : 0; + + C_ALLOC_SCRATCH_START( + exc_buf, FIXP_DBL, + PIT_MAX_MAX + L_INTERPOL + L_DIV + 1); /* 411 + 17 + 256 + 1 = 685 */ + C_ALLOC_SCRATCH_START(syn_buf, FIXP_DBL, + M_LP_FILTER_ORDER + L_DIV); /* 16 + 256 = 272 */ + /* use same memory for code[L_SUBFR] and exc2[L_SUBFR] */ + C_ALLOC_SCRATCH_START(tmp_buf, FIXP_DBL, L_SUBFR); /* 64 */ + /* make sure they don't overlap if they are accessed alternatingly in + * BuildAdaptiveExcitation() */ +#if (COD_BITS == FRACT_BITS) + code = (FIXP_COD *)(tmp_buf + L_SUBFR / 2); +#elif (COD_BITS == DFRACT_BITS) + code = (FIXP_COD *)tmp_buf; +#endif + exc2 = (FIXP_DBL *)tmp_buf; + + syn = syn_buf + M_LP_FILTER_ORDER; + exc = exc_buf + PIT_MAX_MAX + L_INTERPOL; + + FDKmemcpy(syn_buf, acelp_mem->old_syn_mem, + M_LP_FILTER_ORDER * sizeof(FIXP_DBL)); + FDKmemcpy(exc_buf, acelp_mem->old_exc_mem, + (PIT_MAX_MAX + L_INTERPOL) * sizeof(FIXP_DBL)); + + FDKmemclear(exc_buf + (PIT_MAX_MAX + L_INTERPOL), + (L_DIV + 1) * sizeof(FIXP_DBL)); + + l_div = coreCoderFrameLength / NB_DIV; + + for (i_subfr = 0, subfr_nr = 0; i_subfr < l_div; + i_subfr += L_SUBFR, subfr_nr++) { + /*-------------------------------------------------* + * - Decode pitch lag (T0 and T0_frac) * + *-------------------------------------------------*/ + if (bfi) { + ConcealPitchLag(acelp_mem, PIT_MAX, &T0, &T0_frac); + } else { + T0 = (int)pAcelpData->T0[subfr_nr]; + T0_frac = (int)pAcelpData->T0_frac[subfr_nr]; + } + + /*-------------------------------------------------* + * - Find the pitch gain, the interpolation filter * + * and the adaptive codebook vector. * + *-------------------------------------------------*/ + Pred_lt4(&exc[i_subfr], T0, T0_frac); + + if ((!bfi && pAcelpData->ltp_filtering_flag[subfr_nr] == 0) || + (bfi && numLostSubframes == 1 && stab_fac < FL2FXCONST_SGL(0.25f))) { + /* find pitch excitation with lp filter: v'(n) => v(n) */ + Pred_lt4_postfilter(&exc[i_subfr]); + } + + /*-------------------------------------------------------* + * - Decode innovative codebook. * + * - Add the fixed-gain pitch contribution to code[]. * + *-------------------------------------------------------*/ + if (bfi) { + for (n = 0; n < L_SUBFR; n++) { + code[n] = + FX_SGL2FX_COD((FIXP_SGL)E_UTIL_random(&acelp_mem->seed_ace)) >> 4; + } + } else { + int nbits = MapCoreMode2NBits((int)pAcelpData->acelp_core_mode); + D_ACELP_decode_4t64(pAcelpData->icb_index[subfr_nr], nbits, &code[0]); + } + + T = T0; + if (T0_frac > 2) { + T += 1; + } + + Preemph_code(code); + Pit_shrp(code, T); + + /* Output pitch lag for bass post-filter */ + if (T > PIT_MAX) { + pT[subfr_nr] = PIT_MAX; + } else { + pT[subfr_nr] = T; + } + D_gain2_plus( + pAcelpData->gains[subfr_nr], + code, /* (i) : Innovative code vector, exponent = SF_CODE */ + &gain_pit, /* (o) : Quantized pitch gain, exponent = SF_GAIN_P */ + &gain_code, /* (o) : Quantized codebook gain */ + pAcelpData + ->mean_energy, /* (i) : mean_ener defined in open-loop (2 bits) */ + bfi, &acelp_mem->past_gpit, &acelp_mem->past_gcode, + &Ener_code, /* (o) : Innovative code vector energy */ + &Ener_code_e); /* (o) : Innovative code vector energy exponent */ + + pit_gain[pit_gain_index++] = FX_SGL2FX_DBL(gain_pit); + + /* calc periodicity factor r_v */ + period_fac = + calc_period_factor(/* (o) : factor (-1=unvoiced to 1=voiced) */ + &exc[i_subfr], /* (i) : pitch excitation, exponent = + SF_EXC */ + gain_pit, /* (i) : gain of pitch, exponent = + SF_GAIN_P */ + gain_code, /* (i) : gain of code */ + Ener_code, /* (i) : Energy of code[] */ + Ener_code_e); /* (i) : Exponent of energy of code[] + */ + + if (lastLpcLost && frameCnt == 0) { + if (gain_pit > FL2FXCONST_SGL(1.0f / (1 << SF_GAIN_P))) { + gain_pit = FL2FXCONST_SGL(1.0f / (1 << SF_GAIN_P)); + } + } + + gain_code_smooth = + noise_enhancer(/* (o) : smoothed gain g_sc exponent = SF_GAIN_C */ + gain_code, /* (i) : Quantized codebook gain */ + period_fac, /* (i) : periodicity factor (-1=unvoiced to + 1=voiced) */ + stab_fac, /* (i) : stability factor (0 <= ... < 1), + exponent = 1 */ + &acelp_mem->gc_threshold); + + /* Compute adaptive codebook update u'(n), pitch enhancement c'(n) and + * post-processed excitation u(n). */ + BuildAdaptiveExcitation(code, exc + i_subfr, gain_pit, gain_code, + gain_code_smooth, period_fac, exc2); + + /* Interpolate filter coeffs for current subframe in lsp domain and convert + * to LP domain */ + int_lpc_acelp(lsp_old, /* input : LSPs from past frame */ + lsp_new, /* input : LSPs from present frame */ + subfr_nr, /* input : ACELP subframe index */ + coreCoderFrameLength / L_DIV, + A, /* output: LP coefficients of this subframe */ + &A_exp); + + Syn_filt(A, /* (i) : a[m] prediction coefficients */ + A_exp, L_SUBFR, /* (i) : length */ + exc2, /* (i) : input signal */ + &syn[i_subfr] /* (i/o) : filter states / output signal */ + ); + + } /* end of subframe loop */ + + /* update pitch value for bfi procedure */ + acelp_mem->old_T0_frac = T0_frac; + acelp_mem->old_T0 = T0; + + /* save old excitation and old synthesis memory for next ACELP frame */ + FDKmemcpy(acelp_mem->old_exc_mem, exc + l_div - (PIT_MAX_MAX + L_INTERPOL), + sizeof(FIXP_DBL) * (PIT_MAX_MAX + L_INTERPOL)); + FDKmemcpy(acelp_mem->old_syn_mem, syn_buf + l_div, + sizeof(FIXP_DBL) * M_LP_FILTER_ORDER); + + Deemph(syn, synth, l_div, + &acelp_mem->de_emph_mem); /* ref soft: mem = synth[-1] */ + + scaleValues(synth, l_div, -ACELP_OUTSCALE); + acelp_mem->deemph_mem_wsyn = acelp_mem->de_emph_mem; + + C_ALLOC_SCRATCH_END(tmp_buf, FIXP_DBL, L_SUBFR); + C_ALLOC_SCRATCH_END(syn_buf, FIXP_DBL, M_LP_FILTER_ORDER + L_DIV); + C_ALLOC_SCRATCH_END(exc_buf, FIXP_DBL, PIT_MAX_MAX + L_INTERPOL + L_DIV + 1); + return; +} + +void CLpd_AcelpReset(CAcelpStaticMem *acelp) { + acelp->gc_threshold = (FIXP_DBL)0; + + acelp->past_gpit = (FIXP_SGL)0; + acelp->past_gcode = (FIXP_DBL)0; + acelp->old_T0 = 64; + acelp->old_T0_frac = 0; + acelp->deemph_mem_wsyn = (FIXP_DBL)0; + acelp->wsyn_rms = (FIXP_DBL)0; + acelp->seed_ace = 0; +} + +/* TCX time domain concealment */ +/* Compare to figure 13a on page 54 in 3GPP TS 26.290 */ +void CLpd_TcxTDConceal(CAcelpStaticMem *acelp_mem, SHORT *pitch, + const FIXP_LPC lsp_old[M_LP_FILTER_ORDER], + const FIXP_LPC lsp_new[M_LP_FILTER_ORDER], + const FIXP_SGL stab_fac, INT nLostSf, FIXP_DBL synth[], + INT coreCoderFrameLength, UCHAR last_tcx_noise_factor) { + /* repeat past excitation with pitch from previous decoded TCX frame */ + C_ALLOC_SCRATCH_START( + exc_buf, FIXP_DBL, + PIT_MAX_MAX + L_INTERPOL + L_DIV); /* 411 + 17 + 256 + 1 = */ + C_ALLOC_SCRATCH_START(syn_buf, FIXP_DBL, + M_LP_FILTER_ORDER + L_DIV); /* 256 + 16 = */ + /* += */ + FIXP_DBL ns_buf[L_DIV + 1]; + FIXP_DBL *syn = syn_buf + M_LP_FILTER_ORDER; + FIXP_DBL *exc = exc_buf + PIT_MAX_MAX + L_INTERPOL; + FIXP_DBL *ns = ns_buf + 1; + FIXP_DBL tmp, fact_exc; + INT T = fMin(*pitch, (SHORT)PIT_MAX_MAX); + int i, i_subfr, subfr_nr; + int lDiv = coreCoderFrameLength / NB_DIV; + + FDKmemcpy(syn_buf, acelp_mem->old_syn_mem, + M_LP_FILTER_ORDER * sizeof(FIXP_DBL)); + FDKmemcpy(exc_buf, acelp_mem->old_exc_mem, + (PIT_MAX_MAX + L_INTERPOL) * sizeof(FIXP_DBL)); + + /* if we lost all packets (i.e. 1 packet of TCX-20 ms, 2 packets of + the TCX-40 ms or 4 packets of the TCX-80ms), we lost the whole + coded frame extrapolation strategy: repeat lost excitation and + use extrapolated LSFs */ + + /* AMR-WB+ like TCX TD concealment */ + + /* number of lost frame cmpt */ + if (nLostSf < 2) { + fact_exc = FL2FXCONST_DBL(0.8f); + } else { + fact_exc = FL2FXCONST_DBL(0.4f); + } + + /* repeat past excitation */ + for (i = 0; i < lDiv; i++) { + exc[i] = fMult(fact_exc, exc[i - T]); + } + + tmp = fMult(fact_exc, acelp_mem->wsyn_rms); + acelp_mem->wsyn_rms = tmp; + + /* init deemph_mem_wsyn */ + acelp_mem->deemph_mem_wsyn = exc[-1]; + + ns[-1] = acelp_mem->deemph_mem_wsyn; + + for (i_subfr = 0, subfr_nr = 0; i_subfr < lDiv; + i_subfr += L_SUBFR, subfr_nr++) { + FIXP_DBL tRes[L_SUBFR]; + FIXP_LPC A[M_LP_FILTER_ORDER]; + INT A_exp; + + /* interpolate LPC coefficients */ + int_lpc_acelp(lsp_old, lsp_new, subfr_nr, lDiv / L_SUBFR, A, &A_exp); + + Syn_filt(A, /* (i) : a[m] prediction coefficients */ + A_exp, L_SUBFR, /* (i) : length */ + &exc[i_subfr], /* (i) : input signal */ + &syn[i_subfr] /* (i/o) : filter states / output signal */ + ); + + E_LPC_a_weight( + A, A, + M_LP_FILTER_ORDER); /* overwrite A as it is not needed any longer */ + + E_UTIL_residu(A, A_exp, &syn[i_subfr], tRes, L_SUBFR); + + Deemph(tRes, &ns[i_subfr], L_SUBFR, &acelp_mem->deemph_mem_wsyn); + + /* Amplitude limiter (saturate at wsyn_rms) */ + for (i = i_subfr; i < i_subfr + L_SUBFR; i++) { + if (ns[i] > tmp) { + ns[i] = tmp; + } else { + if (ns[i] < -tmp) { + ns[i] = -tmp; + } + } + } + + E_UTIL_preemph(&ns[i_subfr], tRes, L_SUBFR); + + Syn_filt(A, /* (i) : a[m] prediction coefficients */ + A_exp, L_SUBFR, /* (i) : length */ + tRes, /* (i) : input signal */ + &syn[i_subfr] /* (i/o) : filter states / output signal */ + ); + + FDKmemmove(&synth[i_subfr], &syn[i_subfr], L_SUBFR * sizeof(FIXP_DBL)); + } + + /* save old excitation and old synthesis memory for next ACELP frame */ + FDKmemcpy(acelp_mem->old_exc_mem, exc + lDiv - (PIT_MAX_MAX + L_INTERPOL), + sizeof(FIXP_DBL) * (PIT_MAX_MAX + L_INTERPOL)); + FDKmemcpy(acelp_mem->old_syn_mem, syn_buf + lDiv, + sizeof(FIXP_DBL) * M_LP_FILTER_ORDER); + acelp_mem->de_emph_mem = acelp_mem->deemph_mem_wsyn; + + C_ALLOC_SCRATCH_END(syn_buf, FIXP_DBL, M_LP_FILTER_ORDER + L_DIV); + C_ALLOC_SCRATCH_END(exc_buf, FIXP_DBL, PIT_MAX_MAX + L_INTERPOL + L_DIV); +} + +void Acelp_PreProcessing(FIXP_DBL *synth_buf, FIXP_DBL *old_synth, INT *pitch, + INT *old_T_pf, FIXP_DBL *pit_gain, + FIXP_DBL *old_gain_pf, INT samplingRate, INT *i_offset, + INT coreCoderFrameLength, INT synSfd, + INT nbSubfrSuperfr) { + int n; + + /* init beginning of synth_buf with old synthesis from previous frame */ + FDKmemcpy(synth_buf, old_synth, sizeof(FIXP_DBL) * (PIT_MAX_MAX - BPF_DELAY)); + + /* calculate pitch lag offset for ACELP decoder */ + *i_offset = + (samplingRate * PIT_MIN_12k8 + (FSCALE_DENOM / 2)) / FSCALE_DENOM - + PIT_MIN_12k8; + + /* for bass postfilter */ + for (n = 0; n < synSfd; n++) { + pitch[n] = old_T_pf[n]; + pit_gain[n] = old_gain_pf[n]; + } + for (n = 0; n < nbSubfrSuperfr; n++) { + pitch[n + synSfd] = L_SUBFR; + pit_gain[n + synSfd] = (FIXP_DBL)0; + } +} + +void Acelp_PostProcessing(FIXP_DBL *synth_buf, FIXP_DBL *old_synth, INT *pitch, + INT *old_T_pf, INT coreCoderFrameLength, INT synSfd, + INT nbSubfrSuperfr) { + int n; + + /* store last part of synth_buf (which is not handled by the IMDCT overlap) + * for next frame */ + FDKmemcpy(old_synth, synth_buf + coreCoderFrameLength, + sizeof(FIXP_DBL) * (PIT_MAX_MAX - BPF_DELAY)); + + /* for bass postfilter */ + for (n = 0; n < synSfd; n++) { + old_T_pf[n] = pitch[nbSubfrSuperfr + n]; + } +} + +#define L_FAC_ZIR (LFAC) + +void CLpd_Acelp_Zir(const FIXP_LPC A[], const INT A_exp, + CAcelpStaticMem *acelp_mem, const INT length, + FIXP_DBL zir[], int doDeemph) { + C_ALLOC_SCRATCH_START(tmp_buf, FIXP_DBL, L_FAC_ZIR + M_LP_FILTER_ORDER); + FDK_ASSERT(length <= L_FAC_ZIR); + + FDKmemcpy(tmp_buf, acelp_mem->old_syn_mem, + M_LP_FILTER_ORDER * sizeof(FIXP_DBL)); + FDKmemset(tmp_buf + M_LP_FILTER_ORDER, 0, L_FAC_ZIR * sizeof(FIXP_DBL)); + + Syn_filt(A, A_exp, length, &tmp_buf[M_LP_FILTER_ORDER], + &tmp_buf[M_LP_FILTER_ORDER]); + if (!doDeemph) { + /* if last lpd mode was TD concealment, then bypass deemph */ + FDKmemcpy(zir, tmp_buf, length * sizeof(*zir)); + } else { + Deemph(&tmp_buf[M_LP_FILTER_ORDER], &zir[0], length, + &acelp_mem->de_emph_mem); + scaleValues(zir, length, -ACELP_OUTSCALE); + } + C_ALLOC_SCRATCH_END(tmp_buf, FIXP_DBL, L_FAC_ZIR + M_LP_FILTER_ORDER); +} + +void CLpd_AcelpPrepareInternalMem(const FIXP_DBL *synth, UCHAR last_lpd_mode, + UCHAR last_last_lpd_mode, + const FIXP_LPC *A_new, const INT A_new_exp, + const FIXP_LPC *A_old, const INT A_old_exp, + CAcelpStaticMem *acelp_mem, + INT coreCoderFrameLength, INT clearOldExc, + UCHAR lpd_mode) { + int l_div = + coreCoderFrameLength / NB_DIV; /* length of one ACELP/TCX20 frame */ + int l_div_partial; + FIXP_DBL *syn, *old_exc_mem; + + C_ALLOC_SCRATCH_START(synth_buf, FIXP_DBL, + PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER); + syn = &synth_buf[M_LP_FILTER_ORDER]; + + l_div_partial = PIT_MAX_MAX + L_INTERPOL - l_div; + old_exc_mem = acelp_mem->old_exc_mem; + + if (lpd_mode == 4) { + /* Bypass Domain conversion. TCXTD Concealment does no deemphasis in the + * end. */ + FDKmemcpy( + synth_buf, &synth[-(PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER)], + (PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER) * sizeof(FIXP_DBL)); + /* Set deemphasis memory state for TD concealment */ + acelp_mem->deemph_mem_wsyn = scaleValueSaturate(synth[-1], ACELP_OUTSCALE); + } else { + /* convert past [PIT_MAX_MAX+L_INTERPOL+M_LP_FILTER_ORDER] synthesis to + * preemph domain */ + E_UTIL_preemph(&synth[-(PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER)], + synth_buf, PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER); + scaleValuesSaturate(synth_buf, PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER, + ACELP_OUTSCALE); + } + + /* Set deemphasis memory state */ + acelp_mem->de_emph_mem = scaleValueSaturate(synth[-1], ACELP_OUTSCALE); + + /* update acelp synth filter memory */ + FDKmemcpy(acelp_mem->old_syn_mem, + &syn[PIT_MAX_MAX + L_INTERPOL - M_LP_FILTER_ORDER], + M_LP_FILTER_ORDER * sizeof(FIXP_DBL)); + + if (clearOldExc) { + FDKmemclear(old_exc_mem, (PIT_MAX_MAX + L_INTERPOL) * sizeof(FIXP_DBL)); + C_ALLOC_SCRATCH_END(synth_buf, FIXP_DBL, + PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER); + return; + } + + /* update past [PIT_MAX_MAX+L_INTERPOL] samples of exc memory */ + if (last_lpd_mode == 1) { /* last frame was TCX20 */ + if (last_last_lpd_mode == 0) { /* ACELP -> TCX20 -> ACELP transition */ + /* Delay valid part of excitation buffer (from previous ACELP frame) by + * l_div samples */ + FDKmemmove(old_exc_mem, old_exc_mem + l_div, + sizeof(FIXP_DBL) * l_div_partial); + } else if (last_last_lpd_mode > 0) { /* TCX -> TCX20 -> ACELP transition */ + E_UTIL_residu(A_old, A_old_exp, syn, old_exc_mem, l_div_partial); + } + E_UTIL_residu(A_new, A_new_exp, syn + l_div_partial, + old_exc_mem + l_div_partial, l_div); + } else { /* prev frame was FD, TCX40 or TCX80 */ + int exc_A_new_length = (coreCoderFrameLength / 2 > PIT_MAX_MAX + L_INTERPOL) + ? PIT_MAX_MAX + L_INTERPOL + : coreCoderFrameLength / 2; + int exc_A_old_length = PIT_MAX_MAX + L_INTERPOL - exc_A_new_length; + E_UTIL_residu(A_old, A_old_exp, syn, old_exc_mem, exc_A_old_length); + E_UTIL_residu(A_new, A_new_exp, &syn[exc_A_old_length], + &old_exc_mem[exc_A_old_length], exc_A_new_length); + } + C_ALLOC_SCRATCH_END(synth_buf, FIXP_DBL, + PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER); + + return; +} + +FIXP_DBL *CLpd_ACELP_GetFreeExcMem(CAcelpStaticMem *acelp_mem, INT length) { + FDK_ASSERT(length <= PIT_MAX_MAX + L_INTERPOL); + return acelp_mem->old_exc_mem; +} + +INT CLpd_AcelpRead(HANDLE_FDK_BITSTREAM hBs, CAcelpChannelData *acelp, + INT acelp_core_mode, INT coreCoderFrameLength, + INT i_offset) { + int nb_subfr = coreCoderFrameLength / L_DIV; + const UCHAR *num_acb_index_bits = + (nb_subfr == 4) ? num_acb_idx_bits_table[0] : num_acb_idx_bits_table[1]; + int nbits; + int error = 0; + + const int PIT_MIN = PIT_MIN_12k8 + i_offset; + const int PIT_FR2 = PIT_FR2_12k8 - i_offset; + const int PIT_FR1 = PIT_FR1_12k8; + const int PIT_MAX = PIT_MAX_12k8 + (6 * i_offset); + int T0, T0_frac, T0_min = 0, T0_max; + + if (PIT_MAX > PIT_MAX_MAX) { + error = AAC_DEC_DECODE_FRAME_ERROR; + goto bail; + } + + acelp->acelp_core_mode = acelp_core_mode; + + nbits = MapCoreMode2NBits(acelp_core_mode); + + /* decode mean energy with 2 bits : 18, 30, 42 or 54 dB */ + acelp->mean_energy = FDKreadBits(hBs, 2); + + for (int sfr = 0; sfr < nb_subfr; sfr++) { + /* read ACB index and store T0 and T0_frac for each ACELP subframe. */ + error = DecodePitchLag(hBs, num_acb_index_bits[sfr], PIT_MIN, PIT_FR2, + PIT_FR1, PIT_MAX, &T0, &T0_frac, &T0_min, &T0_max); + if (error) { + goto bail; + } + acelp->T0[sfr] = (USHORT)T0; + acelp->T0_frac[sfr] = (UCHAR)T0_frac; + acelp->ltp_filtering_flag[sfr] = FDKreadBits(hBs, 1); + switch (nbits) { + case 12: /* 12 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 1); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 1); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 5); + break; + case 16: /* 16 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 1); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 5); + break; + case 20: /* 20 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 5); + break; + case 28: /* 28 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 9); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 9); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 5); + break; + case 36: /* 36 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 9); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 9); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 9); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 9); + break; + case 44: /* 44 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 13); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 13); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 9); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 9); + break; + case 52: /* 52 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 13); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 13); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 13); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 13); + break; + case 64: /* 64 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 2); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 2); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 2); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 2); + acelp->icb_index[sfr][4] = FDKreadBits(hBs, 14); + acelp->icb_index[sfr][5] = FDKreadBits(hBs, 14); + acelp->icb_index[sfr][6] = FDKreadBits(hBs, 14); + acelp->icb_index[sfr][7] = FDKreadBits(hBs, 14); + break; + default: + FDK_ASSERT(0); + break; + } + acelp->gains[sfr] = FDKreadBits(hBs, 7); + } + +bail: + return error; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_acelp.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_acelp.h new file mode 100644 index 0000000000000..9de41ff9b7b7a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_acelp.h @@ -0,0 +1,281 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: USAC ACELP frame decoder + +*******************************************************************************/ + +#ifndef USACDEC_ACELP_H +#define USACDEC_ACELP_H + +#include "common_fix.h" +#include "FDK_bitstream.h" +#include "usacdec_const.h" +#include "usacdec_rom.h" + +//#define ENHANCED_TCX_TD_CONCEAL_ENABLE + +/** Structure which holds the ACELP internal persistent memory */ +typedef struct { + FIXP_DBL old_exc_mem[PIT_MAX_MAX + L_INTERPOL]; + FIXP_DBL old_syn_mem[M_LP_FILTER_ORDER]; /* synthesis filter states */ + FIXP_SGL A[M_LP_FILTER_ORDER]; + INT A_exp; + FIXP_DBL gc_threshold; + FIXP_DBL de_emph_mem; + FIXP_SGL past_gpit; + FIXP_DBL past_gcode; + USHORT old_T0; + UCHAR old_T0_frac; + FIXP_DBL deemph_mem_wsyn; + FIXP_DBL wsyn_rms; + SHORT seed_ace; +} CAcelpStaticMem; + +/** Structure which holds the parameter data needed to decode one ACELP frame. + */ +typedef struct { + UCHAR + acelp_core_mode; /**< mean excitation energy index for whole ACELP frame + */ + UCHAR mean_energy; /**< acelp core mode for whole ACELP frame */ + USHORT T0[NB_SUBFR]; + UCHAR T0_frac[NB_SUBFR]; + UCHAR ltp_filtering_flag[NB_SUBFR]; /**< controlls whether LTP postfilter is + active for each ACELP subframe */ + SHORT icb_index[NB_SUBFR] + [8]; /**< innovative codebook index for each ACELP subframe */ + UCHAR gains[NB_SUBFR]; /**< gain index for each ACELP subframe */ +} CAcelpChannelData; + +/** + * \brief Read the acelp_coding() bitstream part. + * \param[in] hBs bitstream handle to read data from. + * \param[out] acelpData pointer to structure to store the parsed data of one + * ACELP frame. + * \param[in] acelp_core_mode the ACELP core mode index. + * \param[in] coreCoderFrameLength length of core coder frame (1024|768) + */ +INT CLpd_AcelpRead(HANDLE_FDK_BITSTREAM hBs, CAcelpChannelData *acelpData, + INT acelp_core_mode, INT i_offset, INT coreCoderFrameLength); +/** + * \brief Initialization of memory before one LPD frame is decoded + * \param[out] synth_buf synthesis buffer to be initialized, exponent = SF_SYNTH + * \param[in] old_synth past synthesis of previous LPD frame, exponent = + * SF_SYNTH + * \param[out] synth_buf_fb fullband synthesis buffer to be initialized, + * exponent = SF_SYNTH + * \param[in] old_synth_fb past fullband synthesis of previous LPD frame, + * exponent = SF_SYNTH + * \param[out] pitch vector where decoded pitch lag values are stored + * \param[in] old_T_pf past pitch lag values of previous LPD frame + * \param[in] samplingRate sampling rate for pitch lag offset calculation + * \param[out] i_offset pitch lag offset for the decoding of the pitch lag + * \param[in] coreCoderFrameLength length of core coder frame (1024|768) + */ +void Acelp_PreProcessing(FIXP_DBL *synth_buf, FIXP_DBL *old_synth, INT *pitch, + INT *old_T_pf, FIXP_DBL *pit_gain, + FIXP_DBL *old_gain_pf, INT samplingRate, INT *i_offset, + INT coreCoderFrameLength, INT synSfd, + INT nbSubfrSuperfr); + +/** + * \brief Save tail of buffers for the initialization of the next LPD frame + * \param[in] synth_buf synthesis of current LPD frame, exponent = SF_SYNTH + * \param[out] old_synth memory where tail of fullband synth_buf is stored, + * exponent = SF_SYNTH + * \param[in] synth_buf_fb fullband synthesis of current LPD frame, exponent = + * SF_SYNTH + * \param[out] old_synth_fb memory where tail of fullband synth_buf is stored, + * exponent = SF_SYNTH + * \param[in] pitch decoded pitch lag values of current LPD frame + * \param[out] old_T_pf memory where last SYN_SFD pitch lag values are stored + */ +void Acelp_PostProcessing(FIXP_DBL *synth_buf, FIXP_DBL *old_synth, INT *pitch, + INT *old_T_pf, INT coreCoderFrameLength, INT synSfd, + INT nbSubfrSuperfr); + +/** + * \brief Decode one ACELP frame (three or four ACELP subframes with 64 samples + * each) + * \param[in,out] acelp_mem pointer to ACELP memory structure + * \param[in] i_offset pitch lag offset + * \param[in] lsp_old LPC filter in LSP domain corresponding to previous frame + * \param[in] lsp_new LPC filter in LSP domain corresponding to current frame + * \param[in] stab_fac stability factor constrained by 0<=stab_fac<=1.0, + * exponent = SF_STAB + * \param[in] acelpData pointer to struct with data which is needed for decoding + * one ACELP frame + * \param[out] synth ACELP output signal + * \param[out] pT four decoded pitch lag values + * \param[in] coreCoderFrameLength length of core coder frame (1024|768) + */ +void CLpd_AcelpDecode(CAcelpStaticMem *acelp_mem, INT i_offset, + const FIXP_LPC lsp_old[M_LP_FILTER_ORDER], + const FIXP_LPC lsp_new[M_LP_FILTER_ORDER], + FIXP_SGL stab_fac, CAcelpChannelData *acelpData, + INT numLostSubframes, int lastLpcLost, int frameCnt, + FIXP_DBL synth[], int pT[], FIXP_DBL *pit_gain, + INT coreCoderFrameLength); + +/** + * \brief Reset ACELP internal memory. + * \param[out] acelp_mem pointer to ACELP memory structure + */ +void CLpd_AcelpReset(CAcelpStaticMem *acelp_mem); + +/** + * \brief Initialize ACELP internal memory in case of FAC before ACELP decoder + * is called + * \param[in] synth points to end+1 of past valid synthesis signal, exponent = + * SF_SYNTH + * \param[in] last_lpd_mode last lpd mode + * \param[in] last_last_lpd_mode lpd mode before last_lpd_mode + * \param[in] A_new LP synthesis filter coeffs corresponding to last frame, + * exponent = SF_A_COEFFS + * \param[in] A_old LP synthesis filter coeffs corresponding to the frame before + * last frame, exponent = SF_A_COEFFS + * \param[in,out] acelp_mem pointer to ACELP memory structure + * \param[in] coreCoderFrameLength length of core coder frame (1024|768) + */ +void CLpd_AcelpPrepareInternalMem(const FIXP_DBL *synth, UCHAR last_lpd_mode, + UCHAR last_last_lpd_mode, + const FIXP_LPC *A_new, const INT A_new_exp, + const FIXP_LPC *A_old, const INT A_old_exp, + CAcelpStaticMem *acelp_mem, + INT coreCoderFrameLength, INT clearOldExc, + UCHAR lpd_mode); + +/** + * \brief Calculate zero input response (zir) of the acelp synthesis filter + * \param[in] A LP synthesis filter coefficients, exponent = SF_A_COEFFS + * \param[in,out] acelp_mem pointer to ACELP memory structure + * \param[in] length length of zir + * \param[out] zir pointer to zir output buffer, exponent = SF_SYNTH + */ +void CLpd_Acelp_Zir(const FIXP_LPC A[], const INT A_exp, + CAcelpStaticMem *acelp_mem, const INT length, + FIXP_DBL zir[], int doDeemph); + +/** + * \brief Borrow static excitation memory from ACELP decoder + * \param[in] acelp_mem pointer to ACELP memory structure + * \param[in] length number of requested FIXP_DBL values + * \return pointer to requested memory + * + * The caller has to take care not to overwrite valid memory areas. + * During TCX/FAC calculations and before CLpd_AcelpPrepareInternalMem() is + * called, the following memory size is available: + * - 256 samples in case of ACELP -> TCX20 -> ACELP transition + * - PIT_MAX_MAX+L_INTERPOL samples in all other cases + */ +FIXP_DBL *CLpd_ACELP_GetFreeExcMem(CAcelpStaticMem *acelp_mem, INT length); + +void CLpd_TcxTDConceal(CAcelpStaticMem *acelp_mem, SHORT *pitch, + const FIXP_LPC lsp_old[M_LP_FILTER_ORDER], + const FIXP_LPC lsp_new[M_LP_FILTER_ORDER], + const FIXP_SGL stab_fac, INT numLostSubframes, + FIXP_DBL synth[], INT coreCoderFrameLength, + UCHAR last_tcx_noise_factor); + +inline SHORT E_UTIL_random(SHORT *seed) { + *seed = (SHORT)((((LONG)*seed * (LONG)31821) >> 1) + (LONG)13849); + return (*seed); +} + +#endif /* USACDEC_ACELP_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_const.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_const.h new file mode 100644 index 0000000000000..f68e8083df1c1 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_const.h @@ -0,0 +1,203 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: USAC related constants + +*******************************************************************************/ + +#ifndef USACDEC_CONST_H +#define USACDEC_CONST_H + +/* scale factors */ +#define SF_CODE 6 /* exponent of code[], fixed codebook vector */ +#define SF_GAIN_C 16 /* exponent of gain code and smoothed gain code */ +#define SF_EXC 16 /* exponent of exc[] and exc2[], excitation buffer */ +#define SF_GAIN_P 1 /* exponent of gain_pit */ +#define SF_PFAC 0 /* exponent of period/voicing factor */ +#define SF_SYNTH SF_EXC /* exponent of synthesis buffer */ +#define SF_A_COEFFS 3 /* exponent of LP domain synthesis filter coefficient */ +#define SF_STAB 1 /* exponent of stability factor */ + +/* definitions which are independent of coreCoderFrameLength */ +#define M_LP_FILTER_ORDER 16 /* LP filter order */ +#define LP_FILTER_SCALE 4 /* LP filter scale */ + +#define PIT_MIN_12k8 34 /* Minimum pitch lag with resolution 1/4 */ +#define PIT_MAX_12k8 231 /* Maximum pitch lag for fs=12.8kHz */ +#define FSCALE_DENOM 12800 /* Frequency scale denominator */ +#define FAC_FSCALE_MIN \ + 6000 /* Minimum allowed frequency scale for acelp decoder */ + +#if !defined(LPD_MAX_CORE_SR) +#define LPD_MAX_CORE_SR 24000 /* Default value from ref soft */ +#endif +#define FAC_FSCALE_MAX \ + LPD_MAX_CORE_SR /* Maximum allowed frequency scale for acelp decoder */ + +/* Maximum pitch lag (= 411 for fs_max = 24000) */ +#define PIT_MAX_TMP \ + (PIT_MAX_12k8 + \ + (6 * \ + ((((FAC_FSCALE_MAX * PIT_MIN_12k8) + (FSCALE_DENOM / 2)) / FSCALE_DENOM) - \ + PIT_MIN_12k8))) +#if (PIT_MAX_TMP < \ + 256) /* cannot be smaller because of tcx time domain concealment */ +#define PIT_MAX_MAX 256 +#else +#define PIT_MAX_MAX PIT_MAX_TMP +#endif + +#define NB_DIV 4 /* number of division (20ms) per 80ms frame */ +#define L_SUBFR 64 /* subframe size (5ms) */ +#define BPF_SFD 1 /* bass postfilter delay (subframe) */ +#define BPF_DELAY (BPF_SFD * L_SUBFR) /* bass postfilter delay (samples) */ + +#define L_FILT 12 /* Delay of up-sampling filter (bass post-filter) */ +#define L_EXTRA 96 /* for bass post-filter */ +#define L_INTERPOL \ + (16 + 1) /* Length of filter for interpolation (acelp decoder) */ + +/* definitions for coreCoderFrameLength = 1024 */ +#define L_FRAME_PLUS_1024 1024 /* length of one 80ms superframe */ +#define L_DIV_1024 \ + (L_FRAME_PLUS_1024 / NB_DIV) /* length of one acelp or tcx20 frame */ +#define NB_SUBFR_1024 \ + (L_DIV_1024 / L_SUBFR) /* number of 5ms subframe per division */ +#define NB_SUBFR_SUPERFR_1024 \ + (L_FRAME_PLUS_1024 / L_SUBFR) /* number of 5ms subframe per 80ms frame */ +#define AAC_SFD_1024 (NB_SUBFR_SUPERFR_1024 / 2) /* AAC delay (subframe) */ +#define AAC_DELAY_1024 (AAC_SFD_1024 * L_SUBFR) /* AAC delay (samples) */ +#define SYN_SFD_1024 (AAC_SFD_1024 - BPF_SFD) /* synthesis delay (subframe) */ +#define SYN_DELAY_1024 \ + (SYN_SFD_1024 * L_SUBFR) /* synthesis delay (samples) \ + */ +#define LFAC_1024 (L_DIV_1024 / 2) /* FAC frame length */ +#define LFAC_SHORT_1024 \ + (L_DIV_1024 / 4) /* for transitions EIGHT_SHORT FD->LPD and vv. */ +#define FDNS_NPTS_1024 64 /* FD noise shaping resolution (64=100Hz/point) */ + +/* definitions for coreCoderFrameLength = 768 */ +#define L_FRAME_PLUS_768 768 +#define L_DIV_768 \ + (L_FRAME_PLUS_768 / NB_DIV) /* length of one acelp or tcx20 frame */ +#define NB_SUBFR_768 \ + (L_DIV_768 / L_SUBFR) /* number of 5ms subframe per division */ +#define NB_SUBFR_SUPERFR_768 \ + (L_FRAME_PLUS_768 / L_SUBFR) /* number of 5ms subframe per 80ms frame */ +#define AAC_SFD_768 (NB_SUBFR_SUPERFR_768 / 2) /* AAC delay (subframe) */ +#define AAC_DELAY_768 (AAC_SFD_768 * L_SUBFR) /* AAC delay (samples) */ +#define SYN_SFD_768 (AAC_SFD_768 - BPF_SFD) /* synthesis delay (subframe) */ +#define SYN_DELAY_768 (SYN_SFD_768 * L_SUBFR) /* synthesis delay (samples) */ +#define LFAC_768 (L_DIV_768 / 2) /* FAC frame length */ +#define LFAC_SHORT_768 \ + (L_DIV_768 / 4) /* for transitions EIGHT_SHORT FD->LPD and vv. */ + +/* maximum (used for memory allocation) */ +#define L_FRAME_PLUS L_FRAME_PLUS_1024 +#define L_DIV L_DIV_1024 +#define NB_SUBFR NB_SUBFR_1024 +#define NB_SUBFR_SUPERFR NB_SUBFR_SUPERFR_1024 +#define AAC_SFD AAC_SFD_1024 +#define AAC_DELAY AAC_DELAY_1024 +#define SYN_SFD SYN_SFD_1024 +#define SYN_DELAY SYN_DELAY_1024 +#define LFAC LFAC_1024 +#define LFAC_SHORT LFAC_SHORT_1024 +#define FDNS_NPTS FDNS_NPTS_1024 + +#endif /* USACDEC_CONST_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_fac.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_fac.cpp new file mode 100644 index 0000000000000..b24617118a0f8 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_fac.cpp @@ -0,0 +1,743 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: USAC FAC + +*******************************************************************************/ + +#include "usacdec_fac.h" + +#include "usacdec_const.h" +#include "usacdec_lpc.h" +#include "usacdec_acelp.h" +#include "usacdec_rom.h" +#include "dct.h" +#include "FDK_tools_rom.h" +#include "mdct.h" + +#define SPEC_FAC(ptr, i, gl) ((ptr) + ((i) * (gl))) + +FIXP_DBL *CLpd_FAC_GetMemory(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + UCHAR mod[NB_DIV], int *pState) { + FIXP_DBL *ptr; + int i; + int k = 0; + int max_windows = 8; + + FDK_ASSERT(*pState >= 0 && *pState < max_windows); + + /* Look for free space to store FAC data. 2 FAC data blocks fit into each TCX + * spectral data block. */ + for (i = *pState; i < max_windows; i++) { + if (mod[i >> 1] == 0) { + break; + } + } + + *pState = i + 1; + + if (i == max_windows) { + ptr = pAacDecoderChannelInfo->data.usac.fac_data0; + } else { + FDK_ASSERT(mod[(i >> 1)] == 0); + ptr = SPEC_FAC(pAacDecoderChannelInfo->pSpectralCoefficient, i, + pAacDecoderChannelInfo->granuleLength << k); + } + + return ptr; +} + +int CLpd_FAC_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pFac, SCHAR *pFacScale, + int length, int use_gain, int frame) { + FIXP_DBL fac_gain; + int fac_gain_e = 0; + + if (use_gain) { + CLpd_DecodeGain(&fac_gain, &fac_gain_e, FDKreadBits(hBs, 7)); + } + + if (CLpc_DecodeAVQ(hBs, pFac, 1, 1, length) != 0) { + return -1; + } + + { + int scale; + + scale = getScalefactor(pFac, length); + scaleValues(pFac, length, scale); + pFacScale[frame] = DFRACT_BITS - 1 - scale; + } + + if (use_gain) { + int i; + + pFacScale[frame] += fac_gain_e; + + for (i = 0; i < length; i++) { + pFac[i] = fMult(pFac[i], fac_gain); + } + } + return 0; +} + +/** + * \brief Apply synthesis filter with zero input to x. The overall filter gain + * is 1.0. + * \param a LPC filter coefficients. + * \param length length of the input/output data vector x. + * \param x input/output vector, where the synthesis filter is applied in place. + */ +static void Syn_filt_zero(const FIXP_LPC a[], const INT a_exp, INT length, + FIXP_DBL x[]) { + int i, j; + FIXP_DBL L_tmp; + + for (i = 0; i < length; i++) { + L_tmp = (FIXP_DBL)0; + + for (j = 0; j < fMin(i, M_LP_FILTER_ORDER); j++) { + L_tmp -= fMultDiv2(a[j], x[i - (j + 1)]) >> (LP_FILTER_SCALE - 1); + } + + L_tmp = scaleValue(L_tmp, a_exp + LP_FILTER_SCALE); + x[i] = fAddSaturate(x[i], L_tmp); + } +} + +/* Table is also correct for coreCoderFrameLength = 768. Factor 3/4 is canceled + out: gainFac = 0.5 * sqrt(fac_length/lFrame) +*/ +static const FIXP_DBL gainFac[4] = {0x40000000, 0x2d413ccd, 0x20000000, + 0x16a09e66}; + +void CFac_ApplyGains(FIXP_DBL fac_data[LFAC], const INT fac_length, + const FIXP_DBL tcx_gain, const FIXP_DBL alfd_gains[], + const INT mod) { + FIXP_DBL facFactor; + int i; + + FDK_ASSERT((fac_length == 128) || (fac_length == 96)); + + /* 2) Apply gain factor to FAC data */ + facFactor = fMult(gainFac[mod], tcx_gain); + for (i = 0; i < fac_length; i++) { + fac_data[i] = fMult(fac_data[i], facFactor); + } + + /* 3) Apply spectrum deshaping using alfd_gains */ + for (i = 0; i < fac_length / 4; i++) { + int k; + + k = i >> (3 - mod); + fac_data[i] = fMult(fac_data[i], alfd_gains[k]) + << 1; /* alfd_gains is scaled by one bit. */ + } +} + +static void CFac_CalcFacSignal(FIXP_DBL *pOut, FIXP_DBL *pFac, + const int fac_scale, const int fac_length, + const FIXP_LPC A[M_LP_FILTER_ORDER], + const INT A_exp, const int fAddZir, + const int isFdFac) { + FIXP_LPC wA[M_LP_FILTER_ORDER]; + FIXP_DBL tf_gain = (FIXP_DBL)0; + int wlength; + int scale = fac_scale; + + /* obtain tranform gain. */ + imdct_gain(&tf_gain, &scale, isFdFac ? 0 : fac_length); + + /* 4) Compute inverse DCT-IV of FAC data. Output scale of DCT IV is 16 bits. + */ + dct_IV(pFac, fac_length, &scale); + /* dct_IV scale = log2(fac_length). "- 7" is a factor of 2/128 */ + if (tf_gain != (FIXP_DBL)0) { /* non-radix 2 transform gain */ + int i; + + for (i = 0; i < fac_length; i++) { + pFac[i] = fMult(tf_gain, pFac[i]); + } + } + scaleValuesSaturate(pOut, pFac, fac_length, + scale); /* Avoid overflow issues and saturate. */ + + E_LPC_a_weight(wA, A, M_LP_FILTER_ORDER); + + /* We need the output of the IIR filter to be longer than "fac_length". + For this reason we run it with zero input appended to the end of the input + sequence, i.e. we generate its ZIR and extend the output signal.*/ + FDKmemclear(pOut + fac_length, fac_length * sizeof(FIXP_DBL)); + wlength = 2 * fac_length; + + /* 5) Apply weighted synthesis filter to FAC data, including optional Zir (5. + * item 4). */ + Syn_filt_zero(wA, A_exp, wlength, pOut); +} + +INT CLpd_FAC_Mdct2Acelp(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *pFac, + const int fac_scale, FIXP_LPC *A, INT A_exp, + INT nrOutSamples, const INT fac_length, + const INT isFdFac, UCHAR prevWindowShape) { + FIXP_DBL *pOvl; + FIXP_DBL *pOut0; + const FIXP_WTP *pWindow; + int i, fl, nrSamples = 0; + + FDK_ASSERT(fac_length <= 1024 / (4 * 2)); + + fl = fac_length * 2; + + pWindow = FDKgetWindowSlope(fl, prevWindowShape); + + /* Adapt window slope length in case of frame loss. */ + if (hMdct->prev_fr != fl) { + int nl = 0; + imdct_adapt_parameters(hMdct, &fl, &nl, fac_length, pWindow, nrOutSamples); + FDK_ASSERT(nl == 0); + } + + if (nrSamples < nrOutSamples) { + pOut0 = output; + nrSamples += hMdct->ov_offset; + /* Purge buffered output. */ + FDKmemcpy(pOut0, hMdct->overlap.time, hMdct->ov_offset * sizeof(pOut0[0])); + hMdct->ov_offset = 0; + } + + pOvl = hMdct->overlap.freq + hMdct->ov_size - 1; + + if (nrSamples >= nrOutSamples) { + pOut0 = hMdct->overlap.time + hMdct->ov_offset; + hMdct->ov_offset += hMdct->prev_nr + fl / 2; + } else { + pOut0 = output + nrSamples; + nrSamples += hMdct->prev_nr + fl / 2; + } + if (hMdct->prevPrevAliasSymmetry == 0) { + for (i = 0; i < hMdct->prev_nr; i++) { + FIXP_DBL x = -(*pOvl--); + *pOut0 = IMDCT_SCALE_DBL(x); + pOut0++; + } + } else { + for (i = 0; i < hMdct->prev_nr; i++) { + FIXP_DBL x = (*pOvl--); + *pOut0 = IMDCT_SCALE_DBL(x); + pOut0++; + } + } + hMdct->prev_nr = 0; + + { + if (pFac != NULL) { + /* Note: The FAC gain might have been applied directly after bit stream + * parse in this case. */ + CFac_CalcFacSignal(pOut0, pFac, fac_scale, fac_length, A, A_exp, 0, + isFdFac); + } else { + /* Clear buffer because of the overlap and ADD! */ + FDKmemclear(pOut0, fac_length * sizeof(FIXP_DBL)); + } + } + + i = 0; + + if (hMdct->prevPrevAliasSymmetry == 0) { + for (; i < fl / 2; i++) { + FIXP_DBL x0; + + /* Overlap Add */ + x0 = -fMult(*pOvl--, pWindow[i].v.re); + + *pOut0 = fAddSaturate(*pOut0, IMDCT_SCALE_DBL(x0)); + pOut0++; + } + } else { + for (; i < fl / 2; i++) { + FIXP_DBL x0; + + /* Overlap Add */ + x0 = fMult(*pOvl--, pWindow[i].v.re); + + *pOut0 = fAddSaturate(*pOut0, IMDCT_SCALE_DBL(x0)); + pOut0++; + } + } + if (hMdct->pFacZir != + 0) { /* this should only happen for ACELP -> TCX20 -> ACELP transition */ + FIXP_DBL *pOut = pOut0 - fl / 2; /* fl/2 == fac_length */ + for (i = 0; i < fl / 2; i++) { + pOut[i] = fAddSaturate(pOut[i], IMDCT_SCALE_DBL(hMdct->pFacZir[i])); + } + hMdct->pFacZir = NULL; + } + + hMdct->prev_fr = 0; + hMdct->prev_nr = 0; + hMdct->prev_tl = 0; + hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; + + return nrSamples; +} + +INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *_pSpec, + const SHORT spec_scale[], const int nSpec, + FIXP_DBL *pFac, const int fac_scale, + const INT fac_length, INT noOutSamples, const INT tl, + const FIXP_WTP *wrs, const INT fr, FIXP_LPC A[16], + INT A_exp, CAcelpStaticMem *acelp_mem, + const FIXP_DBL gain, const int last_frame_lost, + const int isFdFac, const UCHAR last_lpd_mode, + const int k, int currAliasingSymmetry) { + FIXP_DBL *pCurr, *pOvl, *pSpec; + const FIXP_WTP *pWindow; + const FIXP_WTB *FacWindowZir_conceal; + UCHAR doFacZirConceal = 0; + int doDeemph = 1; + const FIXP_WTB *FacWindowZir, *FacWindowSynth; + FIXP_DBL *pOut0 = output, *pOut1; + int w, i, fl, nl, nr, f_len, nrSamples = 0, s = 0, scale, total_gain_e; + FIXP_DBL *pF, *pFAC_and_FAC_ZIR = NULL; + FIXP_DBL total_gain = gain; + + FDK_ASSERT(fac_length <= 1024 / (4 * 2)); + switch (fac_length) { + /* coreCoderFrameLength = 1024 */ + case 128: + pWindow = SineWindow256; + FacWindowZir = FacWindowZir128; + FacWindowSynth = FacWindowSynth128; + break; + case 64: + pWindow = SineWindow128; + FacWindowZir = FacWindowZir64; + FacWindowSynth = FacWindowSynth64; + break; + case 32: + pWindow = SineWindow64; + FacWindowZir = FacWindowZir32; + FacWindowSynth = FacWindowSynth32; + break; + /* coreCoderFrameLength = 768 */ + case 96: + pWindow = SineWindow192; + FacWindowZir = FacWindowZir96; + FacWindowSynth = FacWindowSynth96; + break; + case 48: + pWindow = SineWindow96; + FacWindowZir = FacWindowZir48; + FacWindowSynth = FacWindowSynth48; + break; + default: + FDK_ASSERT(0); + return 0; + } + + FacWindowZir_conceal = FacWindowSynth; + /* Derive NR and NL */ + fl = fac_length * 2; + nl = (tl - fl) >> 1; + nr = (tl - fr) >> 1; + + if (noOutSamples > nrSamples) { + /* Purge buffered output. */ + FDKmemcpy(pOut0, hMdct->overlap.time, hMdct->ov_offset * sizeof(pOut0[0])); + nrSamples = hMdct->ov_offset; + hMdct->ov_offset = 0; + } + + if (nrSamples >= noOutSamples) { + pOut1 = hMdct->overlap.time + hMdct->ov_offset; + if (hMdct->ov_offset < fac_length) { + pOut0 = output + nrSamples; + } else { + pOut0 = pOut1; + } + hMdct->ov_offset += fac_length + nl; + } else { + pOut1 = output + nrSamples; + pOut0 = output + nrSamples; + } + + { + pFAC_and_FAC_ZIR = CLpd_ACELP_GetFreeExcMem(acelp_mem, 2 * fac_length); + { + const FIXP_DBL *pTmp1, *pTmp2; + + doFacZirConceal |= ((last_frame_lost != 0) && (k == 0)); + doDeemph &= (last_lpd_mode != 4); + if (doFacZirConceal) { + /* ACELP contribution in concealment case: + Use ZIR with a modified ZIR window to preserve some more energy. + Dont use FAC, which contains wrong information for concealed frame + Dont use last ACELP samples, but double ZIR, instead (afterwards) */ + FDKmemclear(pFAC_and_FAC_ZIR, 2 * fac_length * sizeof(FIXP_DBL)); + FacWindowSynth = (FIXP_WTB *)pFAC_and_FAC_ZIR; + FacWindowZir = FacWindowZir_conceal; + } else { + CFac_CalcFacSignal(pFAC_and_FAC_ZIR, pFac, fac_scale + s, fac_length, A, + A_exp, 1, isFdFac); + } + /* 6) Get windowed past ACELP samples and ACELP ZIR signal */ + + /* + * Get ACELP ZIR (pFac[]) and ACELP past samples (pOut0[]) and add them + * to the FAC synth signal contribution on pOut1[]. + */ + { + { + CLpd_Acelp_Zir(A, A_exp, acelp_mem, fac_length, pFac, doDeemph); + + pTmp1 = pOut0; + pTmp2 = pFac; + } + + for (i = 0, w = 0; i < fac_length; i++) { + FIXP_DBL x; + /* Div2 is compensated by table scaling */ + x = fMultDiv2(pTmp2[i], FacWindowZir[w]); + x += fMultDiv2(pTmp1[-i - 1], FacWindowSynth[w]); + pOut1[i] = fAddSaturate(x, pFAC_and_FAC_ZIR[i]); + w++; + } + } + + if (doFacZirConceal) { + /* ZIR is the only ACELP contribution, so double it */ + scaleValues(pOut1, fac_length, 1); + } + } + } + + if (nrSamples < noOutSamples) { + nrSamples += fac_length + nl; + } + + /* Obtain transform gain */ + total_gain = gain; + total_gain_e = 0; + imdct_gain(&total_gain, &total_gain_e, tl); + + /* IMDCT overlap add */ + scale = total_gain_e; + pSpec = _pSpec; + + /* Note:when comming from an LPD frame (TCX/ACELP) the previous alisaing + * symmetry must always be 0 */ + if (currAliasingSymmetry == 0) { + dct_IV(pSpec, tl, &scale); + } else { + FIXP_DBL _tmp[1024 + ALIGNMENT_DEFAULT / sizeof(FIXP_DBL)]; + FIXP_DBL *tmp = (FIXP_DBL *)ALIGN_PTR(_tmp); + C_ALLOC_ALIGNED_REGISTER(tmp, sizeof(_tmp)); + dst_III(pSpec, tmp, tl, &scale); + C_ALLOC_ALIGNED_UNREGISTER(tmp); + } + + /* Optional scaling of time domain - no yet windowed - of current spectrum */ + if (total_gain != (FIXP_DBL)0) { + for (i = 0; i < tl; i++) { + pSpec[i] = fMult(pSpec[i], total_gain); + } + } + int loc_scale = fixmin_I(spec_scale[0] + scale, (INT)DFRACT_BITS - 1); + scaleValuesSaturate(pSpec, tl, loc_scale); + + pOut1 += fl / 2 - 1; + pCurr = pSpec + tl - fl / 2; + + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x1; + + /* FAC signal is already on pOut1, because of that the += operator. */ + x1 = fMult(*pCurr++, pWindow[i].v.re); + FDK_ASSERT((pOut1 >= hMdct->overlap.time && + pOut1 < hMdct->overlap.time + hMdct->ov_size) || + (pOut1 >= output && pOut1 < output + 1024)); + *pOut1 = fAddSaturate(*pOut1, IMDCT_SCALE_DBL(-x1)); + pOut1--; + } + + /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */ + pOut1 += (fl / 2) + 1; + + pFAC_and_FAC_ZIR += fac_length; /* set pointer to beginning of FAC ZIR */ + + if (nl == 0) { + /* save pointer to write FAC ZIR data later */ + hMdct->pFacZir = pFAC_and_FAC_ZIR; + } else { + FDK_ASSERT(nl >= fac_length); + /* FAC ZIR will be added now ... */ + hMdct->pFacZir = NULL; + } + + pF = pFAC_and_FAC_ZIR; + f_len = fac_length; + + pCurr = pSpec + tl - fl / 2 - 1; + for (i = 0; i < nl; i++) { + FIXP_DBL x = -(*pCurr--); + /* 5) (item 4) Synthesis filter Zir component, FAC ZIR (another one). */ + if (i < f_len) { + x = fAddSaturate(x, *pF++); + } + + FDK_ASSERT((pOut1 >= hMdct->overlap.time && + pOut1 < hMdct->overlap.time + hMdct->ov_size) || + (pOut1 >= output && pOut1 < output + 1024)); + *pOut1 = IMDCT_SCALE_DBL(x); + pOut1++; + } + + hMdct->prev_nr = nr; + hMdct->prev_fr = fr; + hMdct->prev_wrs = wrs; + hMdct->prev_tl = tl; + hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; + hMdct->prevAliasSymmetry = currAliasingSymmetry; + fl = fr; + nl = nr; + + pOvl = pSpec + tl / 2 - 1; + pOut0 = pOut1; + + for (w = 1; w < nSpec; w++) /* for ACELP -> FD short */ + { + const FIXP_WTP *pWindow_prev; + + /* Setup window pointers */ + pWindow_prev = hMdct->prev_wrs; + + /* Current spectrum */ + pSpec = _pSpec + w * tl; + + scale = total_gain_e; + + /* For the second, third, etc. short frames the alisaing symmetry is equal, + * either (0,0) or (1,1) */ + if (currAliasingSymmetry == 0) { + /* DCT IV of current spectrum */ + dct_IV(pSpec, tl, &scale); + } else { + dst_IV(pSpec, tl, &scale); + } + + /* Optional scaling of time domain - no yet windowed - of current spectrum + */ + /* and de-scale current spectrum signal (time domain, no yet windowed) */ + if (total_gain != (FIXP_DBL)0) { + for (i = 0; i < tl; i++) { + pSpec[i] = fMult(pSpec[i], total_gain); + } + } + loc_scale = fixmin_I(spec_scale[w] + scale, (INT)DFRACT_BITS - 1); + scaleValuesSaturate(pSpec, tl, loc_scale); + + if (noOutSamples <= nrSamples) { + /* Divert output first half to overlap buffer if we already got enough + * output samples. */ + pOut0 = hMdct->overlap.time + hMdct->ov_offset; + hMdct->ov_offset += hMdct->prev_nr + fl / 2; + } else { + /* Account output samples */ + nrSamples += hMdct->prev_nr + fl / 2; + } + + /* NR output samples 0 .. NR. -overlap[TL/2..TL/2-NR] */ + for (i = 0; i < hMdct->prev_nr; i++) { + FIXP_DBL x = -(*pOvl--); + *pOut0 = IMDCT_SCALE_DBL(x); + pOut0++; + } + + if (noOutSamples <= nrSamples) { + /* Divert output second half to overlap buffer if we already got enough + * output samples. */ + pOut1 = hMdct->overlap.time + hMdct->ov_offset + fl / 2 - 1; + hMdct->ov_offset += fl / 2 + nl; + } else { + pOut1 = pOut0 + (fl - 1); + nrSamples += fl / 2 + nl; + } + + /* output samples before window crossing point NR .. TL/2. + * -overlap[TL/2-NR..TL/2-NR-FL/2] + current[NR..TL/2] */ + /* output samples after window crossing point TL/2 .. TL/2+FL/2. + * -overlap[0..FL/2] - current[TL/2..FL/2] */ + pCurr = pSpec + tl - fl / 2; + if (currAliasingSymmetry == 0) { + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + + cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]); + *pOut0 = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1 = IMDCT_SCALE_DBL_LSH1(-x1); + pOut0++; + pOut1--; + } + } else { + if (hMdct->prevPrevAliasSymmetry == 0) { + /* Jump DST II -> DST IV for the second window */ + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + + cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]); + *pOut0 = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1 = IMDCT_SCALE_DBL_LSH1(x1); + pOut0++; + pOut1--; + } + } else { + /* Jump DST IV -> DST IV from the second window on */ + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + + cplxMultDiv2(&x1, &x0, *pCurr++, *pOvl--, pWindow_prev[i]); + *pOut0 = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1 = IMDCT_SCALE_DBL_LSH1(x1); + pOut0++; + pOut1--; + } + } + } + + if (hMdct->pFacZir != 0) { + /* add FAC ZIR of previous ACELP -> mdct transition */ + FIXP_DBL *pOut = pOut0 - fl / 2; + FDK_ASSERT(fl / 2 <= 128); + for (i = 0; i < fl / 2; i++) { + pOut[i] = fAddSaturate(pOut[i], IMDCT_SCALE_DBL(hMdct->pFacZir[i])); + } + hMdct->pFacZir = NULL; + } + pOut0 += (fl / 2); + + /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */ + pOut1 += (fl / 2) + 1; + pCurr = pSpec + tl - fl / 2 - 1; + for (i = 0; i < nl; i++) { + FIXP_DBL x = -(*pCurr--); + *pOut1 = IMDCT_SCALE_DBL(x); + pOut1++; + } + + /* Set overlap source pointer for next window pOvl = pSpec + tl/2 - 1; */ + pOvl = pSpec + tl / 2 - 1; + + /* Previous window values. */ + hMdct->prev_nr = nr; + hMdct->prev_fr = fr; + hMdct->prev_tl = tl; + hMdct->prev_wrs = pWindow_prev; + hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; + hMdct->prevAliasSymmetry = currAliasingSymmetry; + } + + /* Save overlap */ + + pOvl = hMdct->overlap.freq + hMdct->ov_size - tl / 2; + FDK_ASSERT(pOvl >= hMdct->overlap.time + hMdct->ov_offset); + FDK_ASSERT(tl / 2 <= hMdct->ov_size); + for (i = 0; i < tl / 2; i++) { + pOvl[i] = _pSpec[i + (w - 1) * tl]; + } + + return nrSamples; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_fac.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_fac.h new file mode 100644 index 0000000000000..100a6fa471749 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_fac.h @@ -0,0 +1,191 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: USAC FAC + +*******************************************************************************/ + +#ifndef USACDEC_FAC_H +#define USACDEC_FAC_H + +#include "channelinfo.h" +#include "FDK_bitstream.h" + +/** + * \brief Get the address of a memory area of the spectral data memory were the + * FAC data can be stored into. + * \param spec SPECTRAL_PTR pointing to the current spectral data. + * \param mod the current LPD mod array. + * \param pState pointer to a private state variable which must be 0 for the + * first call and not changed externally. + * \param isFullbandLPD is 1 if fullband LPD mode is on, otherwise it is 0. + */ +FIXP_DBL *CLpd_FAC_GetMemory(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + UCHAR mod[NB_SUBFR], int *pState); + +/** + * \brief read a fac bitstream data block. + * \param hBs a bit stream handle, where the fac bitstream data is located. + * \param pFac pointer to were the FAC data will be stored into. + * \param pFacScale pointer to were the FAC data scale value will be stored + * into. + * \param tcx_gain value to be used as FAC gain. If zero, read fac_gain from + * bitstream. + * \param tcx_gain_e exponen value of tcx_gain. + * \param frame the subframe to be considered from the current superframe. + * Always 0 for FD case. + * \return 0 on success, -1 on error. + */ +int CLpd_FAC_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pFac, SCHAR *pFacScale, + int length, int use_gain, int frame); + +/** + * \brief Apply TCX and ALFD gains to FAC data. + * \param fac_data pointer to FAC data. + * \param fac_length FAC length (128 or 96). + * \param tcx_gain TCX gain + * \param alfd_gains pointer to alfd gains. + * \param mod mod value (1,2,3) of TCX frame where the FAC signal needs to be + * applied. + */ +void CFac_ApplyGains(FIXP_DBL fac_data[LFAC], const INT fac_length, + const FIXP_DBL tcx_gain, const FIXP_DBL alfd_gains[], + const INT mod); + +/** + * \brief Do FAC transition from frequency domain to ACELP domain. + */ +INT CLpd_FAC_Mdct2Acelp(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *pFac_data, + const int fac_data_e, FIXP_LPC *A, INT A_exp, + INT nrOutSamples, const INT fac_length, + const INT isFdFac, UCHAR prevWindowShape); + +/** + * \brief Do FAC transition from ACELP domain to frequency domain. + * \param hMdct MDCT context. + * \param output pointer for time domain output. + * \param pSpec pointer to MDCT spectrum input. + * \param spec_scale MDCT spectrum exponents. + * \param nSpec amount of contiguos MDCT spectra. + * \param pFac pointer to FAC MDCT domain data. + * \param fac_scale exponent of FAC data. + * \param fac_length length of FAC data. + * \param nrSamples room in samples in output buffer. + * \param tl MDCT transform length of pSpec. + * \param wrs right MDCT window slope. + * \param fr right MDCT window slope length. + * \param A LP domain filter coefficients. + * \param deemph_mem deemphasis filter state. + * \param gain gain to be applied to FAC data before overlap add. + * \param old_syn_mem Synthesis filter state. + * \param isFdFac indicates fac processing from or to FD. + * \param pFacData fac data stored for fullband LPD. + * \param elFlags element specific parser guidance flags. + * \param isFacForFullband indicates that fac is processed for fullband LPD. + */ +INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *pSpec, + const SHORT spec_scale[], const int nSpec, + FIXP_DBL *pFac_data, const int fac_data_e, + const INT fac_length, INT nrSamples, const INT tl, + const FIXP_WTP *wrs, const INT fr, FIXP_LPC A[16], + INT A_exp, CAcelpStaticMem *acelp_mem, + const FIXP_DBL gain, const int last_frame_lost, + const int isFdFac, const UCHAR last_lpd, const int k, + int currAliasingSymmetry); + +#endif /* USACDEC_FAC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpc.cpp new file mode 100644 index 0000000000000..88601b7acaf91 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpc.cpp @@ -0,0 +1,1196 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand, Manuel Jander + + Description: USAC LPC/AVQ decode + +*******************************************************************************/ + +#include "usacdec_lpc.h" + +#include "usacdec_rom.h" +#include "FDK_trigFcts.h" + +#define NQ_MAX 36 + +/* + * Helper functions. + */ + +/** + * \brief Read unary code. + * \param hBs bitstream handle as data source. + * \return decoded value. + */ +static int get_vlclbf(HANDLE_FDK_BITSTREAM hBs) { + int result = 0; + + while (FDKreadBits(hBs, 1) && result <= NQ_MAX) { + result++; + } + return result; +} + +/** + * \brief Read bit count limited unary code. + * \param hBs bitstream handle as data source + * \param n max amount of bits to be read. + * \return decoded value. + */ +static int get_vlclbf_n(HANDLE_FDK_BITSTREAM hBs, int n) { + int result = 0; + + while (FDKreadBits(hBs, 1)) { + result++; + n--; + if (n <= 0) { + break; + } + } + + return result; +} + +/* + * Algebraic Vector Quantizer + */ + +/* ZF_SCALE must be greater than (number of FIXP_ZF)/2 + because the loss of precision caused by fPow2Div2 in RE8_PPV() */ +//#define ZF_SCALE ((NQ_MAX-3)>>1) +#define ZF_SCALE ((DFRACT_BITS / 2)) +#define FIXP_ZF FIXP_DBL +#define INT2ZF(x, s) (FIXP_ZF)((x) << (ZF_SCALE - (s))) +#define ZF2INT(x) (INT)((x) >> ZF_SCALE) + +/* 1.0 in ZF format format */ +#define ONEZF ((FIXP_ZF)INT2ZF(1, 0)) + +/* static */ +void nearest_neighbor_2D8(FIXP_ZF x[8], int y[8]) { + FIXP_ZF s, em, e[8]; + int i, j, sum; + + /* round x into 2Z^8 i.e. compute y=(y1,...,y8) such that yi = 2[xi/2] + where [.] is the nearest integer operator + in the mean time, compute sum = y1+...+y8 + */ + sum = 0; + for (i = 0; i < 8; i++) { + FIXP_ZF tmp; + /* round to ..., -2, 0, 2, ... ([-1..1[ --> 0) */ + if (x[i] < (FIXP_ZF)0) { + tmp = ONEZF - x[i]; + y[i] = -2 * ((ZF2INT(tmp)) >> 1); + } else { + tmp = ONEZF + x[i]; + y[i] = 2 * ((ZF2INT(tmp)) >> 1); + } + sum += y[i]; + } + /* check if y1+...+y8 is a multiple of 4 + if not, y is not round xj in the wrong way where j is defined by + j = arg max_i | xi -yi| + (this is called the Wagner rule) + */ + if (sum % 4) { + /* find j = arg max_i | xi -yi| */ + em = (FIXP_SGL)0; + j = 0; + for (i = 0; i < 8; i++) { + /* compute ei = xi-yi */ + e[i] = x[i] - INT2ZF(y[i], 0); + } + for (i = 0; i < 8; i++) { + /* compute |ei| = | xi-yi | */ + if (e[i] < (FIXP_ZF)0) { + s = -e[i]; + } else { + s = e[i]; + } + /* check if |ei| is maximal, if so, set j=i */ + if (em < s) { + em = s; + j = i; + } + } + /* round xj in the "wrong way" */ + if (e[j] < (FIXP_ZF)0) { + y[j] -= 2; + } else { + y[j] += 2; + } + } +} + +/*-------------------------------------------------------------- + RE8_PPV(x,y) + NEAREST NEIGHBOR SEARCH IN INFINITE LATTICE RE8 + the algorithm is based on the definition of RE8 as + RE8 = (2D8) U (2D8+[1,1,1,1,1,1,1,1]) + it applies the coset decoding of Sloane and Conway + (i) x: point in R^8 in 32-ZF_SCALE.ZF_SCALE format + (o) y: point in RE8 (8-dimensional integer vector) + -------------------------------------------------------------- +*/ +/* static */ +void RE8_PPV(FIXP_ZF x[], SHORT y[], int r) { + int i, y0[8], y1[8]; + FIXP_ZF x1[8], tmp; + INT64 e; + + /* find the nearest neighbor y0 of x in 2D8 */ + nearest_neighbor_2D8(x, y0); + /* find the nearest neighbor y1 of x in 2D8+(1,...,1) (by coset decoding) */ + for (i = 0; i < 8; i++) { + x1[i] = x[i] - ONEZF; + } + nearest_neighbor_2D8(x1, y1); + for (i = 0; i < 8; i++) { + y1[i] += 1; + } + + /* compute e0=||x-y0||^2 and e1=||x-y1||^2 */ + e = 0; + for (i = 0; i < 8; i++) { + tmp = x[i] - INT2ZF(y0[i], 0); + e += (INT64)fPow2Div2( + tmp << r); /* shift left to ensure that no fract part bits get lost. */ + tmp = x[i] - INT2ZF(y1[i], 0); + e -= (INT64)fPow2Div2(tmp << r); + } + /* select best candidate y0 or y1 to minimize distortion */ + if (e < 0) { + for (i = 0; i < 8; i++) { + y[i] = y0[i]; + } + } else { + for (i = 0; i < 8; i++) { + y[i] = y1[i]; + } + } +} + +/* table look-up of unsigned value: find i where index >= table[i] + Note: range must be >= 2, index must be >= table[0] */ +static int table_lookup(const USHORT *table, unsigned int index, int range) { + int i; + + for (i = 4; i < range; i += 4) { + if (index < table[i]) { + break; + } + } + if (i > range) { + i = range; + } + + if (index < table[i - 2]) { + i -= 2; + } + if (index < table[i - 1]) { + i--; + } + i--; + + return (i); /* index >= table[i] */ +} + +/*-------------------------------------------------------------------------- + re8_decode_rank_of_permutation(rank, xs, x) + DECODING OF THE RANK OF THE PERMUTATION OF xs + (i) rank: index (rank) of a permutation + (i) xs: signed leader in RE8 (8-dimensional integer vector) + (o) x: point in RE8 (8-dimensional integer vector) + -------------------------------------------------------------------------- + */ +static void re8_decode_rank_of_permutation(int rank, int *xs, SHORT x[8]) { + INT a[8], w[8], B, fac, fac_B, target; + int i, j; + + /* --- pre-processing based on the signed leader xs --- + - compute the alphabet a=[a[0] ... a[q-1]] of x (q elements) + such that a[0]!=...!=a[q-1] + it is assumed that xs is sorted in the form of a signed leader + which can be summarized in 2 requirements: + a) |xs[0]| >= |xs[1]| >= |xs[2]| >= ... >= |xs[7]| + b) if |xs[i]|=|xs[i-1]|, xs[i]>=xs[i+1] + where |.| indicates the absolute value operator + - compute q (the number of symbols in the alphabet) + - compute w[0..q-1] where w[j] counts the number of occurences of + the symbol a[j] in xs + - compute B = prod_j=0..q-1 (w[j]!) where .! is the factorial */ + /* xs[i], xs[i-1] and ptr_w/a*/ + j = 0; + w[j] = 1; + a[j] = xs[0]; + B = 1; + for (i = 1; i < 8; i++) { + if (xs[i] != xs[i - 1]) { + j++; + w[j] = 1; + a[j] = xs[i]; + } else { + w[j]++; + B *= w[j]; + } + } + + /* --- actual rank decoding --- + the rank of x (where x is a permutation of xs) is based on + Schalkwijk's formula + it is given by rank=sum_{k=0..7} (A_k * fac_k/B_k) + the decoding of this rank is sequential and reconstructs x[0..7] + element by element from x[0] to x[7] + [the tricky part is the inference of A_k for each k...] + */ + + if (w[0] == 8) { + for (i = 0; i < 8; i++) { + x[i] = a[0]; /* avoid fac of 40320 */ + } + } else { + target = rank * B; + fac_B = 1; + /* decode x element by element */ + for (i = 0; i < 8; i++) { + fac = fac_B * fdk_dec_tab_factorial[i]; /* fac = 1..5040 */ + j = -1; + do { + target -= w[++j] * fac; + } while (target >= 0); /* max of 30 tests / SV */ + x[i] = a[j]; + /* update rank, denominator B (B_k) and counter w[j] */ + target += w[j] * fac; /* target = fac_B*B*rank */ + fac_B *= w[j]; + w[j]--; + } + } +} + +/*-------------------------------------------------------------------------- + re8_decode_base_index(n, I, y) + DECODING OF AN INDEX IN Qn (n=0,2,3 or 4) + (i) n: codebook number (*n is an integer defined in {0,2,3,4}) + (i) I: index of c (pointer to unsigned 16-bit word) + (o) y: point in RE8 (8-dimensional integer vector) + note: the index I is defined as a 32-bit word, but only + 16 bits are required (long can be replaced by unsigned integer) + -------------------------------------------------------------------------- + */ +static void re8_decode_base_index(int *n, UINT index, SHORT y[8]) { + int i, im, t, sign_code, ka, ks, rank, leader[8]; + + if (*n < 2) { + for (i = 0; i < 8; i++) { + y[i] = 0; + } + } else { + // index = (unsigned int)*I; + /* search for the identifier ka of the absolute leader (table-lookup) + Q2 is a subset of Q3 - the two cases are considered in the same branch + */ + switch (*n) { + case 2: + case 3: + i = table_lookup(fdk_dec_I3, index, NB_LDQ3); + ka = fdk_dec_A3[i]; + break; + case 4: + i = table_lookup(fdk_dec_I4, index, NB_LDQ4); + ka = fdk_dec_A4[i]; + break; + default: + FDK_ASSERT(0); + return; + } + /* reconstruct the absolute leader */ + for (i = 0; i < 8; i++) { + leader[i] = fdk_dec_Da[ka][i]; + } + /* search for the identifier ks of the signed leader (table look-up) + (this search is focused based on the identifier ka of the absolute + leader)*/ + t = fdk_dec_Ia[ka]; + im = fdk_dec_Ns[ka]; + ks = table_lookup(fdk_dec_Is + t, index, im); + + /* reconstruct the signed leader from its sign code */ + sign_code = 2 * fdk_dec_Ds[t + ks]; + for (i = 7; i >= 0; i--) { + leader[i] *= (1 - (sign_code & 2)); + sign_code >>= 1; + } + + /* compute and decode the rank of the permutation */ + rank = index - fdk_dec_Is[t + ks]; /* rank = index - cardinality offset */ + + re8_decode_rank_of_permutation(rank, leader, y); + } + return; +} + +/* re8_y2k(y,m,k) + VORONOI INDEXING (INDEX DECODING) k -> y + (i) k: Voronoi index k[0..7] + (i) m: Voronoi modulo (m = 2^r = 1<=2) + (i) r: Voronoi order (m = 2^r = 1<=2) + (o) y: 8-dimensional point y[0..7] in RE8 + */ +static void re8_k2y(int *k, int r, SHORT *y) { + int i, tmp, sum; + SHORT v[8]; + FIXP_ZF zf[8]; + + FDK_ASSERT(r <= ZF_SCALE); + + /* compute y = k M and z=(y-a)/m, where + M = [4 ] + [2 2 ] + [| \ ] + [2 2 ] + [1 1 _ 1 1] + a=(2,0,...,0) + m = 1<= 1; i--) { + tmp = 2 * k[i]; + sum += tmp; + y[i] += tmp; + zf[i] = INT2ZF(y[i], r); + } + y[0] += (4 * k[0] + sum); + zf[0] = INT2ZF(y[0] - 2, r); + /* find nearest neighbor v of z in infinite RE8 */ + RE8_PPV(zf, v, r); + /* compute y -= m v */ + for (i = 0; i < 8; i++) { + y[i] -= (SHORT)(v[i] << r); + } +} + +/*-------------------------------------------------------------------------- + RE8_dec(n, I, k, y) + MULTI-RATE INDEXING OF A POINT y in THE LATTICE RE8 (INDEX DECODING) + (i) n: codebook number (*n is an integer defined in {0,2,3,4,..,n_max}). n_max + = 36 (i) I: index of c (pointer to unsigned 16-bit word) (i) k: index of v + (8-dimensional vector of binary indices) = Voronoi index (o) y: point in RE8 + (8-dimensional integer vector) note: the index I is defined as a 32-bit word, + but only 16 bits are required (long can be replaced by unsigned integer) + + return 0 on success, -1 on error. + -------------------------------------------------------------------------- + */ +static int RE8_dec(int n, int I, int *k, FIXP_DBL *y) { + SHORT v[8]; + SHORT _y[8]; + UINT r; + int i; + + /* Check bound of codebook qn */ + if (n > NQ_MAX) { + return -1; + } + + /* decode the sub-indices I and kv[] according to the codebook number n: + if n=0,2,3,4, decode I (no Voronoi extension) + if n>4, Voronoi extension is used, decode I and kv[] */ + if (n <= 4) { + re8_decode_base_index(&n, I, _y); + for (i = 0; i < 8; i++) { + y[i] = (LONG)_y[i]; + } + } else { + /* compute the Voronoi modulo m = 2^r where r is extension order */ + r = ((n - 3) >> 1); + + while (n > 4) { + n -= 2; + } + /* decode base codebook index I into c (c is an element of Q3 or Q4) + [here c is stored in y to save memory] */ + re8_decode_base_index(&n, I, _y); + /* decode Voronoi index k[] into v */ + re8_k2y(k, r, v); + /* reconstruct y as y = m c + v (with m=2^r, r integer >=1) */ + for (i = 0; i < 8; i++) { + y[i] = (LONG)((_y[i] << r) + v[i]); + } + } + return 0; +} + +/**************************/ +/* start LPC decode stuff */ +/**************************/ +//#define M 16 +#define FREQ_MAX 6400.0f +#define FREQ_DIV 400.0f +#define LSF_GAP 50.0f + +/** + * \brief calculate inverse weighting factor and add non-weighted residual + * LSF vector to first stage LSF approximation + * \param lsfq first stage LSF approximation values. + * \param xq weighted residual LSF vector + * \param nk_mode code book number coding mode. + */ +static void lsf_weight_2st(FIXP_LPC *lsfq, FIXP_DBL *xq, int nk_mode) { + FIXP_LPC d[M_LP_FILTER_ORDER + 1]; + FIXP_SGL factor; + LONG w; /* inverse weight factor */ + int i; + + /* compute lsf distance */ + d[0] = lsfq[0]; + d[M_LP_FILTER_ORDER] = + FL2FXCONST_LPC(FREQ_MAX / (1 << LSF_SCALE)) - lsfq[M_LP_FILTER_ORDER - 1]; + for (i = 1; i < M_LP_FILTER_ORDER; i++) { + d[i] = lsfq[i] - lsfq[i - 1]; + } + + switch (nk_mode) { + case 0: + factor = FL2FXCONST_SGL(2.0f * 60.0f / FREQ_DIV); + break; /* abs */ + case 1: + factor = FL2FXCONST_SGL(2.0f * 65.0f / FREQ_DIV); + break; /* mid */ + case 2: + factor = FL2FXCONST_SGL(2.0f * 64.0f / FREQ_DIV); + break; /* rel1 */ + default: + factor = FL2FXCONST_SGL(2.0f * 63.0f / FREQ_DIV); + break; /* rel2 */ + } + /* add non-weighted residual LSF vector to LSF1st */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + w = (LONG)fMultDiv2(factor, sqrtFixp(fMult(d[i], d[i + 1]))); + lsfq[i] = fAddSaturate(lsfq[i], + FX_DBL2FX_LPC((FIXP_DBL)((INT64)w * (LONG)xq[i]))); + } + + return; +} + +/** + * \brief decode nqn amount of code book numbers. These values determine the + * amount of following bits for nqn AVQ RE8 vectors. + * \param nk_mode quantization mode. + * \param nqn amount code book number to read. + * \param qn pointer to output buffer to hold decoded code book numbers qn. + */ +static void decode_qn(HANDLE_FDK_BITSTREAM hBs, int nk_mode, int nqn, + int qn[]) { + int n; + + if (nk_mode == 1) { /* nk mode 1 */ + /* Unary code for mid LPC1/LPC3 */ + /* Q0=0, Q2=10, Q3=110, ... */ + for (n = 0; n < nqn; n++) { + qn[n] = get_vlclbf(hBs); + if (qn[n] > 0) { + qn[n]++; + } + } + } else { /* nk_mode 0, 3 and 2 */ + /* 2 bits to specify Q2,Q3,Q4,ext */ + for (n = 0; n < nqn; n++) { + qn[n] = 2 + FDKreadBits(hBs, 2); + } + if (nk_mode == 2) { + /* Unary code for rel LPC1/LPC3 */ + /* Q0 = 0, Q5=10, Q6=110, ... */ + for (n = 0; n < nqn; n++) { + if (qn[n] > 4) { + qn[n] = get_vlclbf(hBs); + if (qn[n] > 0) qn[n] += 4; + } + } + } else { /* nk_mode == (0 and 3) */ + /* Unary code for abs and rel LPC0/LPC2 */ + /* Q5 = 0, Q6=10, Q0=110, Q7=1110, ... */ + for (n = 0; n < nqn; n++) { + if (qn[n] > 4) { + qn[n] = get_vlclbf(hBs); + switch (qn[n]) { + case 0: + qn[n] = 5; + break; + case 1: + qn[n] = 6; + break; + case 2: + qn[n] = 0; + break; + default: + qn[n] += 4; + break; + } + } + } + } + } +} + +/** + * \brief reorder LSF coefficients to minimum distance. + * \param lsf pointer to buffer containing LSF coefficients and where reordered + * LSF coefficients will be stored into, scaled by LSF_SCALE. + * \param min_dist min distance scaled by LSF_SCALE + * \param n number of LSF/LSP coefficients. + */ +static void reorder_lsf(FIXP_LPC *lsf, FIXP_LPC min_dist, int n) { + FIXP_LPC lsf_min; + int i; + + lsf_min = min_dist; + for (i = 0; i < n; i++) { + if (lsf[i] < lsf_min) { + lsf[i] = lsf_min; + } + lsf_min = fAddSaturate(lsf[i], min_dist); + } + + /* reverse */ + lsf_min = FL2FXCONST_LPC(FREQ_MAX / (1 << LSF_SCALE)) - min_dist; + for (i = n - 1; i >= 0; i--) { + if (lsf[i] > lsf_min) { + lsf[i] = lsf_min; + } + + lsf_min = lsf[i] - min_dist; + } +} + +/** + * \brief First stage approximation + * \param hBs bitstream handle as data source + * \param lsfq pointer to output buffer to hold LPC coefficients scaled by + * LSF_SCALE. + */ +static void vlpc_1st_dec( + HANDLE_FDK_BITSTREAM hBs, /* input: codebook index */ + FIXP_LPC *lsfq /* i/o: i:prediction o:quantized lsf */ +) { + const FIXP_LPC *p_dico; + int i, index; + + index = FDKreadBits(hBs, 8); + p_dico = &fdk_dec_dico_lsf_abs_8b[index * M_LP_FILTER_ORDER]; + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsfq[i] = p_dico[i]; + } +} + +/** + * \brief Do first stage approximation weighting and multiply with AVQ + * refinement. + * \param hBs bitstream handle data ssource. + * \param lsfq buffer holding 1st stage approx, 2nd stage approx is added to + * this values. + * \param nk_mode quantization mode. + * \return 0 on success, -1 on error. + */ +static int vlpc_2st_dec( + HANDLE_FDK_BITSTREAM hBs, + FIXP_LPC *lsfq, /* i/o: i:1st stage o:1st+2nd stage */ + int nk_mode /* input: 0=abs, >0=rel */ +) { + int err; + FIXP_DBL xq[M_LP_FILTER_ORDER]; /* weighted residual LSF vector */ + + /* Decode AVQ refinement */ + { err = CLpc_DecodeAVQ(hBs, xq, nk_mode, 2, 8); } + if (err != 0) { + return -1; + } + + /* add non-weighted residual LSF vector to LSF1st */ + lsf_weight_2st(lsfq, xq, nk_mode); + + /* reorder */ + reorder_lsf(lsfq, FL2FXCONST_LPC(LSF_GAP / (1 << LSF_SCALE)), + M_LP_FILTER_ORDER); + + return 0; +} + +/* + * Externally visible functions + */ + +int CLpc_DecodeAVQ(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pOutput, int nk_mode, + int no_qn, int length) { + int i, l; + + for (i = 0; i < length; i += 8 * no_qn) { + int qn[2], nk, n, I; + int kv[8] = {0}; + + decode_qn(hBs, nk_mode, no_qn, qn); + + for (l = 0; l < no_qn; l++) { + if (qn[l] == 0) { + FDKmemclear(&pOutput[i + l * 8], 8 * sizeof(FIXP_DBL)); + } + + /* Voronoi extension order ( nk ) */ + nk = 0; + n = qn[l]; + if (qn[l] > 4) { + nk = (qn[l] - 3) >> 1; + n = qn[l] - nk * 2; + } + + /* Base codebook index, in reverse bit group order (!) */ + I = FDKreadBits(hBs, 4 * n); + + if (nk > 0) { + int j; + + for (j = 0; j < 8; j++) { + kv[j] = FDKreadBits(hBs, nk); + } + } + + if (RE8_dec(qn[l], I, kv, &pOutput[i + l * 8]) != 0) { + return -1; + } + } + } + return 0; +} + +int CLpc_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_LPC lsp[][M_LP_FILTER_ORDER], + FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER], + FIXP_LPC lsf_adaptive_mean_cand[M_LP_FILTER_ORDER], + FIXP_SGL pStability[], UCHAR *mod, int first_lpd_flag, + int last_lpc_lost, int last_frame_ok) { + int i, k, err; + int mode_lpc_bin = 0; /* mode_lpc bitstream representation */ + int lpc_present[5] = {0, 0, 0, 0, 0}; + int lpc0_available = 1; + int s = 0; + int l = 3; + const int nbDiv = NB_DIV; + + lpc_present[4 >> s] = 1; /* LPC4 */ + + /* Decode LPC filters in the following order: LPC 4,0,2,1,3 */ + + /*** Decode LPC4 ***/ + vlpc_1st_dec(hBs, lsp[4 >> s]); + err = vlpc_2st_dec(hBs, lsp[4 >> s], 0); /* nk_mode = 0 */ + if (err != 0) { + return err; + } + + /*** Decode LPC0 and LPC2 ***/ + k = 0; + if (!first_lpd_flag) { + lpc_present[0] = 1; + lpc0_available = !last_lpc_lost; + /* old LPC4 is new LPC0 */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[0][i] = lpc4_lsf[i]; + } + /* skip LPC0 and continue with LPC2 */ + k = 2; + } + + for (; k < l; k += 2) { + int nk_mode = 0; + + if ((k == 2) && (mod[0] == 3)) { + break; /* skip LPC2 */ + } + + lpc_present[k >> s] = 1; + + mode_lpc_bin = FDKreadBit(hBs); + + if (mode_lpc_bin == 0) { + /* LPC0/LPC2: Abs */ + vlpc_1st_dec(hBs, lsp[k >> s]); + } else { + /* LPC0/LPC2: RelR */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[k >> s][i] = lsp[4 >> s][i]; + } + nk_mode = 3; + } + + err = vlpc_2st_dec(hBs, lsp[k >> s], nk_mode); + if (err != 0) { + return err; + } + } + + /*** Decode LPC1 ***/ + if (mod[0] < 2) { /* else: skip LPC1 */ + lpc_present[1] = 1; + mode_lpc_bin = get_vlclbf_n(hBs, 2); + + switch (mode_lpc_bin) { + case 1: + /* LPC1: abs */ + vlpc_1st_dec(hBs, lsp[1]); + err = vlpc_2st_dec(hBs, lsp[1], 0); + if (err != 0) { + return err; + } + break; + case 2: + /* LPC1: mid0 (no second stage AVQ quantizer in this case) */ + if (lpc0_available) { /* LPC0/lsf[0] might be zero some times */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[1][i] = (lsp[0][i] >> 1) + (lsp[2][i] >> 1); + } + } else { + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[1][i] = lsp[2][i]; + } + } + break; + case 0: + /* LPC1: RelR */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[1][i] = lsp[2][i]; + } + err = vlpc_2st_dec(hBs, lsp[1], 2 << s); + if (err != 0) { + return err; + } + break; + } + } + + /*** Decode LPC3 ***/ + if ((mod[2] < 2)) { /* else: skip LPC3 */ + int nk_mode = 0; + lpc_present[3] = 1; + + mode_lpc_bin = get_vlclbf_n(hBs, 3); + + switch (mode_lpc_bin) { + case 1: + /* LPC3: abs */ + vlpc_1st_dec(hBs, lsp[3]); + break; + case 0: + /* LPC3: mid */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[3][i] = (lsp[2][i] >> 1) + (lsp[4][i] >> 1); + } + nk_mode = 1; + break; + case 2: + /* LPC3: relL */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[3][i] = lsp[2][i]; + } + nk_mode = 2; + break; + case 3: + /* LPC3: relR */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[3][i] = lsp[4][i]; + } + nk_mode = 2; + break; + } + err = vlpc_2st_dec(hBs, lsp[3], nk_mode); + if (err != 0) { + return err; + } + } + + if (!lpc0_available && !last_frame_ok) { + /* LPC(0) was lost. Use next available LPC(k) instead */ + for (k = 1; k < (nbDiv + 1); k++) { + if (lpc_present[k]) { + for (i = 0; i < M_LP_FILTER_ORDER; i++) { +#define LSF_INIT_TILT (0.25f) + if (mod[0] > 0) { + lsp[0][i] = FX_DBL2FX_LPC( + fMult(lsp[k][i], FL2FXCONST_SGL(1.0f - LSF_INIT_TILT)) + + fMult(fdk_dec_lsf_init[i], FL2FXCONST_SGL(LSF_INIT_TILT))); + } else { + lsp[0][i] = lsp[k][i]; + } + } + break; + } + } + } + + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lpc4_lsf[i] = lsp[4 >> s][i]; + } + + { + FIXP_DBL divFac; + int last, numLpc = 0; + + i = nbDiv; + do { + numLpc += lpc_present[i--]; + } while (i >= 0 && numLpc < 3); + + last = i; + + switch (numLpc) { + case 3: + divFac = FL2FXCONST_DBL(1.0f / 3.0f); + break; + case 2: + divFac = FL2FXCONST_DBL(1.0f / 2.0f); + break; + default: + divFac = FL2FXCONST_DBL(1.0f); + break; + } + + /* get the adaptive mean for the next (bad) frame */ + for (k = 0; k < M_LP_FILTER_ORDER; k++) { + FIXP_DBL tmp = (FIXP_DBL)0; + for (i = nbDiv; i > last; i--) { + if (lpc_present[i]) { + tmp = fMultAdd(tmp >> 1, lsp[i][k], divFac); + } + } + lsf_adaptive_mean_cand[k] = FX_DBL2FX_LPC(tmp); + } + } + + /* calculate stability factor Theta. Needed for ACELP decoder and concealment + */ + { + FIXP_LPC *lsf_prev, *lsf_curr; + k = 0; + + FDK_ASSERT(lpc_present[0] == 1 && lpc_present[4 >> s] == 1); + lsf_prev = lsp[0]; + for (i = 1; i < (nbDiv + 1); i++) { + if (lpc_present[i]) { + FIXP_DBL tmp = (FIXP_DBL)0; + int j; + lsf_curr = lsp[i]; + + /* sum = tmp * 2^(LSF_SCALE*2 + 4) */ + for (j = 0; j < M_LP_FILTER_ORDER; j++) { + tmp += fPow2Div2((FIXP_SGL)(lsf_curr[j] - lsf_prev[j])) >> 3; + } + + /* tmp = (float)(FL2FXCONST_DBL(1.25f) - fMult(tmp, + * FL2FXCONST_DBL(1/400000.0f))); */ + tmp = FL2FXCONST_DBL(1.25f / (1 << LSF_SCALE)) - + fMult(tmp, FL2FXCONST_DBL((1 << (LSF_SCALE + 4)) / 400000.0f)); + if (tmp >= FL2FXCONST_DBL(1.0f / (1 << LSF_SCALE))) { + pStability[k] = FL2FXCONST_SGL(1.0f / 2.0f); + } else if (tmp < FL2FXCONST_DBL(0.0f)) { + pStability[k] = FL2FXCONST_SGL(0.0f); + } else { + pStability[k] = FX_DBL2FX_SGL(tmp << (LSF_SCALE - 1)); + } + + lsf_prev = lsf_curr; + k = i; + } else { + /* Mark stability value as undefined. */ + pStability[i] = (FIXP_SGL)-1; + } + } + } + + /* convert into LSP domain */ + for (i = 0; i < (nbDiv + 1); i++) { + if (lpc_present[i]) { + for (k = 0; k < M_LP_FILTER_ORDER; k++) { + lsp[i][k] = FX_DBL2FX_LPC( + fixp_cos(fMult(lsp[i][k], + FL2FXCONST_SGL((1 << LSPARG_SCALE) * M_PI / 6400.0)), + LSF_SCALE - LSPARG_SCALE)); + } + } + } + + return 0; +} + +void CLpc_Conceal(FIXP_LPC lsp[][M_LP_FILTER_ORDER], + FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER], + FIXP_LPC lsf_adaptive_mean[M_LP_FILTER_ORDER], + const int first_lpd_flag) { + int i, j; + +#define BETA (FL2FXCONST_SGL(0.25f)) +#define ONE_BETA (FL2FXCONST_SGL(0.75f)) +#define BFI_FAC (FL2FXCONST_SGL(0.90f)) +#define ONE_BFI_FAC (FL2FXCONST_SGL(0.10f)) + + /* Frame loss concealment (could be improved) */ + + if (first_lpd_flag) { + /* Reset past LSF values */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[0][i] = lpc4_lsf[i] = fdk_dec_lsf_init[i]; + } + } else { + /* old LPC4 is new LPC0 */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[0][i] = lpc4_lsf[i]; + } + } + + /* LPC1 */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + FIXP_LPC lsf_mean = FX_DBL2FX_LPC(fMult(BETA, fdk_dec_lsf_init[i]) + + fMult(ONE_BETA, lsf_adaptive_mean[i])); + + lsp[1][i] = FX_DBL2FX_LPC(fMult(BFI_FAC, lpc4_lsf[i]) + + fMult(ONE_BFI_FAC, lsf_mean)); + } + + /* LPC2 - LPC4 */ + for (j = 2; j <= 4; j++) { + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + /* lsf_mean[i] = FX_DBL2FX_LPC(fMult((FIXP_LPC)(BETA + j * + FL2FXCONST_LPC(0.1f)), fdk_dec_lsf_init[i]) + + fMult((FIXP_LPC)(ONE_BETA - j * + FL2FXCONST_LPC(0.1f)), lsf_adaptive_mean[i])); */ + + FIXP_LPC lsf_mean = FX_DBL2FX_LPC( + fMult((FIXP_SGL)(BETA + (FIXP_SGL)(j * (INT)FL2FXCONST_SGL(0.1f))), + (FIXP_SGL)fdk_dec_lsf_init[i]) + + fMult( + (FIXP_SGL)(ONE_BETA - (FIXP_SGL)(j * (INT)FL2FXCONST_SGL(0.1f))), + lsf_adaptive_mean[i])); + + lsp[j][i] = FX_DBL2FX_LPC(fMult(BFI_FAC, lsp[j - 1][i]) + + fMult(ONE_BFI_FAC, lsf_mean)); + } + } + + /* Update past values for the future */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lpc4_lsf[i] = lsp[4][i]; + } + + /* convert into LSP domain */ + for (j = 0; j < 5; j++) { + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[j][i] = FX_DBL2FX_LPC(fixp_cos( + fMult(lsp[j][i], FL2FXCONST_SGL((1 << LSPARG_SCALE) * M_PI / 6400.0)), + LSF_SCALE - LSPARG_SCALE)); + } + } +} + +void E_LPC_a_weight(FIXP_LPC *wA, const FIXP_LPC *A, int m) { + FIXP_DBL f; + int i; + + f = FL2FXCONST_DBL(0.92f); + for (i = 0; i < m; i++) { + wA[i] = FX_DBL2FX_LPC(fMult(A[i], f)); + f = fMult(f, FL2FXCONST_DBL(0.92f)); + } +} + +void CLpd_DecodeGain(FIXP_DBL *gain, INT *gain_e, int gain_code) { + /* gain * 2^(gain_e) = 10^(gain_code/28) */ + *gain = fLdPow( + FL2FXCONST_DBL(3.3219280948873623478703194294894 / 4.0), /* log2(10)*/ + 2, + fMultDiv2((FIXP_DBL)gain_code << (DFRACT_BITS - 1 - 7), + FL2FXCONST_DBL(2.0f / 28.0f)), + 7, gain_e); +} + + /** + * \brief * Find the polynomial F1(z) or F2(z) from the LSPs. + * This is performed by expanding the product polynomials: + * + * F1(z) = product ( 1 - 2 LSP_i z^-1 + z^-2 ) + * i=0,2,4,6,8 + * F2(z) = product ( 1 - 2 LSP_i z^-1 + z^-2 ) + * i=1,3,5,7,9 + * + * where LSP_i are the LSPs in the cosine domain. + * R.A.Salami October 1990 + * \param lsp input, line spectral freq. (cosine domain) + * \param f output, the coefficients of F1 or F2, scaled by 8 bits + * \param n no of coefficients (m/2) + * \param flag 1 : F1(z) ; 2 : F2(z) + */ + +#define SF_F 8 + +static void get_lsppol(FIXP_LPC lsp[], FIXP_DBL f[], int n, int flag) { + FIXP_DBL b; + FIXP_LPC *plsp; + int i, j; + + plsp = lsp + flag - 1; + f[0] = FL2FXCONST_DBL(1.0f / (1 << SF_F)); + b = -FX_LPC2FX_DBL(*plsp); + f[1] = b >> (SF_F - 1); + for (i = 2; i <= n; i++) { + plsp += 2; + b = -FX_LPC2FX_DBL(*plsp); + f[i] = SATURATE_LEFT_SHIFT((fMultDiv2(b, f[i - 1]) + (f[i - 2] >> 1)), 2, + DFRACT_BITS); + for (j = i - 1; j > 1; j--) { + f[j] = SATURATE_LEFT_SHIFT( + ((f[j] >> 2) + fMultDiv2(b, f[j - 1]) + (f[j - 2] >> 2)), 2, + DFRACT_BITS); + } + f[1] = f[1] + (b >> (SF_F - 1)); + } + return; +} + +#define NC M_LP_FILTER_ORDER / 2 + +/** + * \brief lsp input LSP vector + * \brief a output LP filter coefficient vector scaled by SF_A_COEFFS. + */ +void E_LPC_f_lsp_a_conversion(FIXP_LPC *lsp, FIXP_LPC *a, INT *a_exp) { + FIXP_DBL f1[NC + 1], f2[NC + 1]; + int i, k; + + /*-----------------------------------------------------* + * Find the polynomials F1(z) and F2(z) * + *-----------------------------------------------------*/ + + get_lsppol(lsp, f1, NC, 1); + get_lsppol(lsp, f2, NC, 2); + + /*-----------------------------------------------------* + * Multiply F1(z) by (1+z^-1) and F2(z) by (1-z^-1) * + *-----------------------------------------------------*/ + scaleValues(f1, NC + 1, -2); + scaleValues(f2, NC + 1, -2); + + for (i = NC; i > 0; i--) { + f1[i] += f1[i - 1]; + f2[i] -= f2[i - 1]; + } + + FIXP_DBL aDBL[M_LP_FILTER_ORDER]; + + for (i = 1, k = M_LP_FILTER_ORDER - 1; i <= NC; i++, k--) { + aDBL[i - 1] = f1[i] + f2[i]; + aDBL[k] = f1[i] - f2[i]; + } + + int headroom_a = getScalefactor(aDBL, M_LP_FILTER_ORDER); + + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + a[i] = FX_DBL2FX_LPC(aDBL[i] << headroom_a); + } + + *a_exp = SF_F + (2 - 1) - headroom_a; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpc.h new file mode 100644 index 0000000000000..a6713c159d876 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpc.h @@ -0,0 +1,190 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand, Manuel Jander + + Description: USAC LPC/AVQ decode + +*******************************************************************************/ + +#ifndef USACDEC_LPC_H +#define USACDEC_LPC_H + +#include "channelinfo.h" +#include "common_fix.h" +#include "FDK_bitstream.h" +#include "usacdec_rom.h" + +#define LSPARG_SCALE 10 + +/** + * \brief AVQ (refinement) decode + * \param hBs bitstream handle + * \param lsfq buffer for AVQ decode output. + * \param nk_mode quantization mode. + * \param nqn amount of split/interleaved RE8 vectors. + * \param total amount of individual data values to decode. + * \return 0 on success, -1 on error. + */ +int CLpc_DecodeAVQ(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *lsfq, int nk_mode, + int nqn, int length); + +/** + * \brief Read and decode LPC coeficient sets. First stage approximation + AVQ + * decode. + * \param[in] hBs bitstream handle to read data from. + * \param[out] lsp buffer into which the decoded LSP coefficients will be stored + * into. + * \param[in,out] lpc4_lsf buffer into which the decoded LCP4 LSF coefficients + * will be stored into (persistent). + * \param[out] lsf_adaptive_mean_cand lsf adaptive mean vector needed for + * concealment. + * \param[out] pStability array with stability values for the ACELP decoder (and + * concealment). + * \param[in] mod array which defines modes (ACELP, TCX20|40|80) are used in + * the current superframe. + * \param[in] first_lpd_flag indicates the presence of LPC0 + * \param[in] last_lpc_lost indicate that LPC4 of previous frame was lost. + * \param[in] last_frame_ok indicate that the last frame was ok. + * \return 0 on success, -1 on error. + */ +int CLpc_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_LPC lsp[][M_LP_FILTER_ORDER], + FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER], + FIXP_LPC lsf_adaptive_mean_cand[M_LP_FILTER_ORDER], + FIXP_SGL pStability[], UCHAR *mod, int first_lpd_flag, + int last_lpc_lost, int last_frame_ok); + +/** + * \brief Generate LPC coefficient sets in case frame loss. + * \param lsp buffer into which the decoded LSP coefficients will be stored + * into. + * \param lpc4_lsf buffer into which the decoded LCP4 LSF coefficients will be + * stored into (persistent). + * \param isf_adaptive_mean + * \param first_lpd_flag indicates the previous LSF4 coefficients lpc4_lsf[] are + * not valid. + */ +void CLpc_Conceal(FIXP_LPC lsp[][M_LP_FILTER_ORDER], + FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER], + FIXP_LPC isf_adaptive_mean[M_LP_FILTER_ORDER], + const int first_lpd_flag); + +/** + * \brief apply absolute weighting + * \param A weighted LPC coefficient vector output. The first coeffcient is + * implicitly 1.0 + * \param A LPC coefficient vector. The first coeffcient is implicitly 1.0 + * \param m length of vector A + */ +/* static */ +void E_LPC_a_weight(FIXP_LPC *wA, const FIXP_LPC *A, const int m); + +/** + * \brief decode TCX/FAC gain. In case of TCX the lg/sqrt(rms) part + * must still be applied to obtain the gain value. + * \param gain (o) pointer were the gain mantissa is stored into. + * \param gain_e (o) pointer were the gain exponent is stored into. + * \param gain_code (i) the 7 bit binary word from the bitstream + * representing the gain. + */ +void CLpd_DecodeGain(FIXP_DBL *gain, INT *gain_e, int gain_code); + +/** + * \brief convert LSP coefficients into LP domain. + */ +void E_LPC_f_lsp_a_conversion(FIXP_LPC *lsp, FIXP_LPC *a, INT *a_exp); + +#endif /* USACDEC_LPC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpd.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpd.cpp new file mode 100644 index 0000000000000..fbf6fab93be96 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpd.cpp @@ -0,0 +1,2041 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: USAC Linear Prediction Domain coding + +*******************************************************************************/ + +#include "usacdec_lpd.h" + +#include "usacdec_rom.h" +#include "usacdec_fac.h" +#include "usacdec_lpc.h" +#include "FDK_tools_rom.h" +#include "fft.h" +#include "mdct.h" +#include "usacdec_acelp.h" +#include "overlapadd.h" + +#include "conceal.h" + +#include "block.h" + +#define SF_PITCH_TRACK 6 +#define SF_GAIN 3 +#define MIN_VAL FL2FXCONST_DBL(0.0f) +#define MAX_VAL (FIXP_DBL) MAXVAL_DBL + +#include "ac_arith_coder.h" + +void filtLP(const FIXP_DBL *syn, PCM_DEC *syn_out, FIXP_DBL *noise, + const FIXP_SGL *filt, const INT aacOutDataHeadroom, INT stop, + int len) { + INT i, j; + FIXP_DBL tmp; + + FDK_ASSERT((aacOutDataHeadroom - 1) >= -(MDCT_OUTPUT_SCALE)); + + for (i = 0; i < stop; i++) { + tmp = fMultDiv2(noise[i], filt[0]); // Filt in Q-1.16 + for (j = 1; j <= len; j++) { + tmp += fMult((noise[i - j] >> 1) + (noise[i + j] >> 1), filt[j]); + } + syn_out[i] = (PCM_DEC)( + IMDCT_SCALE((syn[i] >> 1) - (tmp >> 1), aacOutDataHeadroom - 1)); + } +} + +void bass_pf_1sf_delay( + FIXP_DBL *syn, /* (i) : 12.8kHz synthesis to postfilter */ + const INT *T_sf, /* (i) : Pitch period for all subframes (T_sf[16]) */ + FIXP_DBL *pit_gain, + const int frame_length, /* (i) : frame length (should be 768|1024) */ + const INT l_frame, + const INT l_next, /* (i) : look ahead for symmetric filtering */ + PCM_DEC *synth_out, /* (o) : filtered synthesis (with delay of 1 subfr) */ + const INT aacOutDataHeadroom, /* (i) : headroom of the output time signal to + prevent clipping */ + FIXP_DBL mem_bpf[]) /* i/o : memory state [L_FILT+L_SUBFR] */ +{ + INT i, sf, i_subfr, T, T2, lg; + + FIXP_DBL tmp, ener, corr, gain; + FIXP_DBL *noise, *noise_in; + FIXP_DBL + noise_buf[L_FILT + (2 * L_SUBFR)]; // L_FILT = 12, L_SUBFR = 64 => 140 + const FIXP_DBL *x, *y; + + { + noise = noise_buf + L_FILT; // L_FILT = 12 delay of upsampling filter + noise_in = noise_buf + L_FILT + L_SUBFR; + /* Input scaling of the BPF memory */ + scaleValues(mem_bpf, (L_FILT + L_SUBFR), 1); + } + + int gain_exp = 17; + + sf = 0; + for (i_subfr = 0; i_subfr < l_frame; i_subfr += L_SUBFR, sf++) { + T = T_sf[sf]; + gain = pit_gain[sf]; + + /* Gain is in Q17.14 */ + /* If gain > 1 set to 1 */ + if (gain > (FIXP_DBL)(1 << 14)) gain = (FIXP_DBL)(1 << 14); + + /* If gain < 0 set to 0 */ + if (gain < (FIXP_DBL)0) gain = (FIXP_DBL)0; + + if (gain > (FIXP_DBL)0) { + /* pitch tracker: test pitch/2 to avoid continuous pitch doubling */ + /* Note: pitch is limited to PIT_MIN (34 = 376Hz) at the encoder */ + T2 = T >> 1; + x = &syn[i_subfr - L_EXTRA]; + y = &syn[i_subfr - T2 - L_EXTRA]; + + ener = (FIXP_DBL)0; + corr = (FIXP_DBL)0; + tmp = (FIXP_DBL)0; + + int headroom_x = getScalefactor(x, L_SUBFR + L_EXTRA); + int headroom_y = getScalefactor(y, L_SUBFR + L_EXTRA); + + int width_shift = 7; + + for (i = 0; i < (L_SUBFR + L_EXTRA); i++) { + ener += fPow2Div2((x[i] << headroom_x)) >> width_shift; + corr += fMultDiv2((x[i] << headroom_x), (y[i] << headroom_y)) >> + width_shift; + tmp += fPow2Div2((y[i] << headroom_y)) >> width_shift; + } + + int exp_ener = ((17 - headroom_x) << 1) + width_shift + 1; + int exp_corr = (17 - headroom_x) + (17 - headroom_y) + width_shift + 1; + int exp_tmp = ((17 - headroom_y) << 1) + width_shift + 1; + + /* Add 0.01 to "ener". Adjust exponents */ + FIXP_DBL point_zero_one = (FIXP_DBL)0x51eb851f; /* In Q-6.37 */ + int diff; + ener = fAddNorm(ener, exp_ener, point_zero_one, -6, &exp_ener); + corr = fAddNorm(corr, exp_corr, point_zero_one, -6, &exp_corr); + tmp = fAddNorm(tmp, exp_tmp, point_zero_one, -6, &exp_tmp); + + /* use T2 if normalized correlation > 0.95 */ + INT s1, s2; + s1 = CntLeadingZeros(ener) - 1; + s2 = CntLeadingZeros(tmp) - 1; + + FIXP_DBL ener_by_tmp = fMultDiv2(ener << s1, tmp << s2); + int ener_by_tmp_exp = (exp_ener - s1) + (exp_tmp - s2) + 1; + + if (ener_by_tmp_exp & 1) { + ener_by_tmp <<= 1; + ener_by_tmp_exp -= 1; + } + + int temp_exp = 0; + + FIXP_DBL temp1 = invSqrtNorm2(ener_by_tmp, &temp_exp); + + int temp1_exp = temp_exp - (ener_by_tmp_exp >> 1); + + FIXP_DBL tmp_result = fMult(corr, temp1); + + int tmp_result_exp = exp_corr + temp1_exp; + + diff = tmp_result_exp - 0; + FIXP_DBL point95 = FL2FXCONST_DBL(0.95f); + if (diff >= 0) { + diff = fMin(diff, 31); + point95 = FL2FXCONST_DBL(0.95f) >> diff; + } else { + diff = fMax(diff, -31); + tmp_result >>= (-diff); + } + + if (tmp_result > point95) T = T2; + + /* prevent that noise calculation below reaches into not defined signal + parts at the end of the synth_buf or in other words restrict the below + used index (i+i_subfr+T) < l_frame + l_next + */ + lg = l_frame + l_next - T - i_subfr; + + if (lg > L_SUBFR) + lg = L_SUBFR; + else if (lg < 0) + lg = 0; + + /* limit gain to avoid problem on burst */ + if (lg > 0) { + FIXP_DBL tmp1; + + /* max(lg) = 64 => scale with 6 bits minus 1 (fPow2Div2) */ + + s1 = getScalefactor(&syn[i_subfr], lg); + s2 = getScalefactor(&syn[i_subfr + T], lg); + INT s = fixMin(s1, s2); + + tmp = (FIXP_DBL)0; + ener = (FIXP_DBL)0; + for (i = 0; i < lg; i++) { + tmp += fPow2Div2(syn[i + i_subfr] << s1) >> (SF_PITCH_TRACK); + ener += fPow2Div2(syn[i + i_subfr + T] << s2) >> (SF_PITCH_TRACK); + } + tmp = tmp >> fMin(DFRACT_BITS - 1, (2 * (s1 - s))); + ener = ener >> fMin(DFRACT_BITS - 1, (2 * (s2 - s))); + + /* error robustness: for the specific case syn[...] == -1.0f for all 64 + samples ener or tmp might overflow and become negative. For all sane + cases we have enough headroom. + */ + if (ener <= (FIXP_DBL)0) { + ener = (FIXP_DBL)1; + } + if (tmp <= (FIXP_DBL)0) { + tmp = (FIXP_DBL)1; + } + FDK_ASSERT(ener > (FIXP_DBL)0); + + /* tmp = sqrt(tmp/ener) */ + int result_e = 0; + tmp1 = fDivNorm(tmp, ener, &result_e); + if (result_e & 1) { + tmp1 >>= 1; + result_e += 1; + } + tmp = sqrtFixp(tmp1); + result_e >>= 1; + + gain_exp = 17; + + diff = result_e - gain_exp; + + FIXP_DBL gain1 = gain; + + if (diff >= 0) { + diff = fMin(diff, 31); + gain1 >>= diff; + } else { + result_e += (-diff); + diff = fMax(diff, -31); + tmp >>= (-diff); + } + + if (tmp < gain1) { + gain = tmp; + gain_exp = result_e; + } + } + + /* calculate noise based on voiced pitch */ + /* fMultDiv2() replaces weighting of gain with 0.5 */ + diff = gain_exp - 17; + if (diff >= 0) { + gain <<= diff; + } else { + gain >>= (-diff); + } + + s1 = CntLeadingZeros(gain) - 1; + s1 -= 16; /* Leading bits for SGL */ + + FIXP_SGL gainSGL = FX_DBL2FX_SGL(gain << 16); + + gainSGL = gainSGL << s1; + + { + for (i = 0; i < lg; i++) { + /* scaled with SF_SYNTH + gain_sf + 1; composition of scalefactor 2: + * one additional shift of syn values + fMult => fMultDiv2 */ + noise_in[i] = + scaleValue(fMultDiv2(gainSGL, (syn[i + i_subfr] >> 1) - + (syn[i + i_subfr - T] >> 2) - + (syn[i + i_subfr + T] >> 2)), + 2 - s1); + } + + for (i = lg; i < L_SUBFR; i++) { + /* scaled with SF_SYNTH + gain_sf + 1; composition of scalefactor 2: + * one additional shift of syn values + fMult => fMultDiv2 */ + noise_in[i] = + scaleValue(fMultDiv2(gainSGL, (syn[i + i_subfr] >> 1) - + (syn[i + i_subfr - T] >> 1)), + 2 - s1); + } + } + } else { + FDKmemset(noise_in, (FIXP_DBL)0, L_SUBFR * sizeof(FIXP_DBL)); + } + + { + FDKmemcpy(noise_buf, mem_bpf, (L_FILT + L_SUBFR) * sizeof(FIXP_DBL)); + + FDKmemcpy(mem_bpf, noise_buf + L_SUBFR, + (L_FILT + L_SUBFR) * sizeof(FIXP_DBL)); + } + + /* substract from voiced speech low-pass filtered noise */ + /* filter coefficients are scaled with factor SF_FILT_LP (1) */ + + { + filtLP(&syn[i_subfr - L_SUBFR], &synth_out[i_subfr], noise, + fdk_dec_filt_lp, aacOutDataHeadroom, L_SUBFR, L_FILT); + } + } + + { + + } + + // To be determined (info from Ben) + { + /* Output scaling of the BPF memory */ + scaleValues(mem_bpf, (L_FILT + L_SUBFR), -1); + /* Copy the rest of the signal (after the fac) */ + scaleValuesSaturate( + (PCM_DEC *)&synth_out[l_frame], (FIXP_DBL *)&syn[l_frame - L_SUBFR], + (frame_length - l_frame), MDCT_OUT_HEADROOM - aacOutDataHeadroom); + } + + return; +} + +/* + * Frequency Domain Noise Shaping + */ + +/** + * \brief Adaptive Low Frequencies Deemphasis of spectral coefficients. + * + * Ensure quantization of low frequencies in case where the + * signal dynamic is higher than the LPC noise shaping. + * This is the inverse operation of adap_low_freq_emph(). + * Output gain of all blocks. + * + * \param x pointer to the spectral coefficients, requires 1 bit headroom. + * \param lg length of x. + * \param bUseNewAlfe if set, apply ALFD for fullband lpd. + * \param gainLpc1 pointer to gain based on old input LPC coefficients. + * \param gainLpc2 pointer to gain based on new input LPC coefficients. + * \param alfd_gains pointer to output gains. + * \param s current scale shift factor of x. + */ +#define ALFDPOW2_SCALE 3 +/*static*/ +void CLpd_AdaptLowFreqDeemph(FIXP_DBL x[], int lg, FIXP_DBL alfd_gains[], + INT s) { + { + int i, j, k, i_max; + FIXP_DBL max, fac; + /* Note: This stack array saves temporary accumulation results to be used in + * a second run */ + /* The size should be limited to (1024/4)/8=32 */ + FIXP_DBL tmp_pow2[32]; + + s = s * 2 + ALFDPOW2_SCALE; + s = fMin(31, s); + + k = 8; + i_max = lg / 4; /* ALFD range = 1600Hz (lg = 6400Hz) */ + + /* find spectral peak */ + max = FL2FX_DBL(0.01f) >> s; + for (i = 0; i < i_max; i += k) { + FIXP_DBL tmp; + + tmp = FIXP_DBL(0); + FIXP_DBL *pX = &x[i]; + + j = 8; + do { + FIXP_DBL x0 = *pX++; + FIXP_DBL x1 = *pX++; + x0 = fPow2Div2(x0); + x1 = fPow2Div2(x1); + tmp = tmp + (x0 >> (ALFDPOW2_SCALE - 1)); + tmp = tmp + (x1 >> (ALFDPOW2_SCALE - 1)); + } while ((j = j - 2) != 0); + tmp = fMax(tmp, (FL2FX_DBL(0.01f) >> s)); + tmp_pow2[i >> 3] = tmp; + if (tmp > max) { + max = tmp; + } + } + + /* deemphasis of all blocks below the peak */ + fac = FL2FX_DBL(0.1f) >> 1; + for (i = 0; i < i_max; i += k) { + FIXP_DBL tmp; + INT shifti; + + tmp = tmp_pow2[i >> 3]; + + /* tmp = (float)sqrt(tmp/max); */ + + /* value of tmp is between 8/2*max^2 and max^2 / 2. */ + /* required shift factor of division can grow up to 27 + (grows exponentially for values toward zero) + thus using normalized division to assure valid result. */ + { + INT sd; + + if (tmp != (FIXP_DBL)0) { + tmp = fDivNorm(max, tmp, &sd); + if (sd & 1) { + sd++; + tmp >>= 1; + } + } else { + tmp = (FIXP_DBL)MAXVAL_DBL; + sd = 0; + } + tmp = invSqrtNorm2(tmp, &shifti); + tmp = scaleValue(tmp, shifti - 1 - (sd / 2)); + } + if (tmp > fac) { + fac = tmp; + } + FIXP_DBL *pX = &x[i]; + + j = 8; + do { + FIXP_DBL x0 = pX[0]; + FIXP_DBL x1 = pX[1]; + x0 = fMultDiv2(x0, fac); + x1 = fMultDiv2(x1, fac); + x0 = x0 << 2; + x1 = x1 << 2; + *pX++ = x0; + *pX++ = x1; + + } while ((j = j - 2) != 0); + /* Store gains for FAC */ + *alfd_gains++ = fac; + } + } +} + +/** + * \brief Interpolated Noise Shaping for mdct coefficients. + * This algorithm shapes temporally the spectral noise between + * the two spectral noise represention (FDNS_NPTS of resolution). + * The noise is shaped monotonically between the two points + * using a curved shape to favor the lower gain in mid-frame. + * ODFT and amplitud calculation are applied to the 2 LPC coefficients first. + * + * \param r pointer to spectrum data. + * \param rms RMS of output spectrum. + * \param lg length of r. + * \param A1 pointer to old input LPC coefficients of length M_LP_FILTER_ORDER + * scaled by SF_A_COEFFS. + * \param A2 pointer to new input LPC coefficients of length M_LP_FILTER_ORDER + * scaled by SF_A_COEFFS. + * \param bLpc2Mdct flags control lpc2mdct conversion and noise shaping. + * \param gainLpc1 pointer to gain based on old input LPC coefficients. + * \param gainLpc2 pointer to gain based on new input LPC coefficients. + * \param gLpc_e pointer to exponent of gainLpc1 and gainLpc2. + */ +/* static */ +#define NSHAPE_SCALE (4) + +#define LPC2MDCT_CALC (1) +#define LPC2MDCT_GAIN_LOAD (2) +#define LPC2MDCT_GAIN_SAVE (4) +#define LPC2MDCT_APPLY_NSHAPE (8) + +void lpc2mdctAndNoiseShaping(FIXP_DBL *r, SHORT *pScale, const INT lg, + const INT fdns_npts, const FIXP_LPC *A1, + const INT A1_exp, const FIXP_LPC *A2, + const INT A2_exp) { + FIXP_DBL *tmp2 = NULL; + FIXP_DBL rr_minus_one; + int i, k, s, step; + + C_AALLOC_SCRATCH_START(tmp1, FIXP_DBL, FDNS_NPTS * 8) + + { + tmp2 = tmp1 + fdns_npts * 4; + + /* lpc2mdct() */ + + /* ODFT. E_LPC_a_weight() for A1 and A2 vectors is included into the loop + * below. */ + FIXP_DBL f = FL2FXCONST_DBL(0.92f); + + const FIXP_STP *SinTab; + int k_step; + /* needed values: sin(phi), cos(phi); phi = i*PI/(2*fdns_npts), i = 0 ... + * M_LP_FILTER_ORDER */ + switch (fdns_npts) { + case 64: + SinTab = SineTable512; + k_step = (512 / 64); + FDK_ASSERT(512 >= 64); + break; + case 48: + SinTab = SineTable384; + k_step = 384 / 48; + FDK_ASSERT(384 >= 48); + break; + default: + FDK_ASSERT(0); + return; + } + + for (i = 0, k = k_step; i < M_LP_FILTER_ORDER; i++, k += k_step) { + FIXP_STP cs = SinTab[k]; + FIXP_DBL wA1, wA2; + + wA1 = fMult(A1[i], f); + wA2 = fMult(A2[i], f); + + /* r[i] = A[i]*cos() */ + tmp1[2 + i * 2] = fMult(wA1, cs.v.re); + tmp2[2 + i * 2] = fMult(wA2, cs.v.re); + /* i[i] = A[i]*sin() */ + tmp1[3 + i * 2] = -fMult(wA1, cs.v.im); + tmp2[3 + i * 2] = -fMult(wA2, cs.v.im); + + f = fMult(f, FL2FXCONST_DBL(0.92f)); + } + + /* Guarantee at least 2 bits of headroom for the FFT */ + /* "3" stands for 1.0 with 2 bits of headroom; (A1_exp + 2) guarantess 2 + * bits of headroom if A1_exp > 1 */ + int A1_exp_fix = fMax(3, A1_exp + 2); + int A2_exp_fix = fMax(3, A2_exp + 2); + + /* Set 1.0 in the proper format */ + tmp1[0] = (FIXP_DBL)(INT)((ULONG)0x80000000 >> A1_exp_fix); + tmp2[0] = (FIXP_DBL)(INT)((ULONG)0x80000000 >> A2_exp_fix); + + tmp1[1] = tmp2[1] = (FIXP_DBL)0; + + /* Clear the resto of the array */ + FDKmemclear( + tmp1 + 2 * (M_LP_FILTER_ORDER + 1), + 2 * (fdns_npts * 2 - (M_LP_FILTER_ORDER + 1)) * sizeof(FIXP_DBL)); + FDKmemclear( + tmp2 + 2 * (M_LP_FILTER_ORDER + 1), + 2 * (fdns_npts * 2 - (M_LP_FILTER_ORDER + 1)) * sizeof(FIXP_DBL)); + + /* Guarantee 2 bits of headroom for FFT */ + scaleValues(&tmp1[2], (2 * M_LP_FILTER_ORDER), (A1_exp - A1_exp_fix)); + scaleValues(&tmp2[2], (2 * M_LP_FILTER_ORDER), (A2_exp - A2_exp_fix)); + + INT s2; + s = A1_exp_fix; + s2 = A2_exp_fix; + + fft(2 * fdns_npts, tmp1, &s); + fft(2 * fdns_npts, tmp2, &s2); + + /* Adjust the exponents of both fft outputs if necessary*/ + if (s > s2) { + scaleValues(tmp2, 2 * fdns_npts, s2 - s); + s2 = s; + } else if (s < s2) { + scaleValues(tmp1, 2 * fdns_npts, s - s2); + s = s2; + } + + FDK_ASSERT(s == s2); + } + + /* Get amplitude and apply gains */ + step = lg / fdns_npts; + rr_minus_one = (FIXP_DBL)0; + + for (k = 0; k < fdns_npts; k++) { + FIXP_DBL g1, g2, inv_g1_g2, a, b; + INT inv_g1_g2_e; + int g_e, shift; + + { + FIXP_DBL real, imag; + int si1, si2, sInput; + + real = tmp1[k * 2]; + imag = tmp1[k * 2 + 1]; + sInput = fMax(fMin(fNorm(real), fNorm(imag)) - 1, 0); + real <<= sInput; + imag <<= sInput; + /* g1_e = si1 - 2*s/2 */ + g1 = invSqrtNorm2(fPow2(real) + fPow2(imag), &si1); + si1 += sInput; + + real = tmp2[k * 2]; + imag = tmp2[k * 2 + 1]; + sInput = fMax(fMin(fNorm(real), fNorm(imag)) - 1, 0); + real <<= sInput; + imag <<= sInput; + /* g2_e = si2 - 2*s/2 */ + g2 = invSqrtNorm2(fPow2(real) + fPow2(imag), &si2); + si2 += sInput; + + /* Pick a common scale factor for g1 and g2 */ + if (si1 > si2) { + g2 >>= si1 - si2; + g_e = si1 - s; + } else { + g1 >>= si2 - si1; + g_e = si2 - s; + } + } + + /* end of lpc2mdct() */ + + FDK_ASSERT(g1 >= (FIXP_DBL)0); + FDK_ASSERT(g2 >= (FIXP_DBL)0); + + /* mdct_IntNoiseShaping() */ + { + /* inv_g1_g2 * 2^inv_g1_g2_e = 1/(g1+g2) */ + inv_g1_g2 = (g1 >> 1) + (g2 >> 1); + if (inv_g1_g2 != (FIXP_DBL)0) { + inv_g1_g2 = fDivNorm(FL2FXCONST_DBL(0.5f), inv_g1_g2, &inv_g1_g2_e); + inv_g1_g2_e = inv_g1_g2_e - g_e; + } else { + inv_g1_g2 = (FIXP_DBL)MAXVAL_DBL; + inv_g1_g2_e = 0; + } + + if (g_e < 0) { + /* a_e = g_e + inv_g1_g2_e + 1 */ + a = scaleValue(fMult(fMult(g1, g2), inv_g1_g2), g_e); + /* b_e = g_e + inv_g1_g2_e */ + b = fMult(g2 - g1, inv_g1_g2); + shift = g_e + inv_g1_g2_e + 1 - NSHAPE_SCALE; + } else { + /* a_e = (g_e+g_e) + inv_g1_g2_e + 1 */ + a = fMult(fMult(g1, g2), inv_g1_g2); + /* b_e = (g_e+g_e) + inv_g1_g2_e */ + b = scaleValue(fMult(g2 - g1, inv_g1_g2), -g_e); + shift = (g_e + g_e) + inv_g1_g2_e + 1 - NSHAPE_SCALE; + } + + for (i = k * step; i < (k + 1) * step; i++) { + FIXP_DBL tmp; + + /* rr[i] = 2*a*r[i] + b*rr[i-1] */ + tmp = fMult(a, r[i]); + tmp += scaleValue(fMultDiv2(b, rr_minus_one), NSHAPE_SCALE); + tmp = scaleValueSaturate(tmp, shift); + rr_minus_one = tmp; + r[i] = tmp; + } + } + } + + /* end of mdct_IntNoiseShaping() */ + { *pScale += NSHAPE_SCALE; } + + C_AALLOC_SCRATCH_END(tmp1, FIXP_DBL, FDNS_NPTS * 8) +} + +/** + * \brief Calculates the energy. + * \param r pointer to spectrum. + * \param rs scale factor of spectrum r. + * \param lg frame length in audio samples. + * \param rms_e pointer to exponent of energy value. + * \return mantissa of energy value. + */ +static FIXP_DBL calcEnergy(const FIXP_DBL *r, const SHORT rs, const INT lg, + INT *rms_e) { + int headroom = getScalefactor(r, lg); + + FIXP_DBL rms_m = 0; + + /* Calculate number of growth bits due to addition */ + INT shift = (INT)(fNormz((FIXP_DBL)lg)); + shift = 31 - shift; + + /* Generate 1e-2 in Q-6.37 */ + const FIXP_DBL value0_01 = 0x51eb851e; + const INT value0_01_exp = -6; + + /* Find the exponent of the resulting energy value */ + *rms_e = ((rs - headroom) << 1) + shift + 1; + + INT delta = *rms_e - value0_01_exp; + if (delta > 0) { + /* Limit shift_to 31*/ + delta = fMin(31, delta); + rms_m = value0_01 >> delta; + } else { + rms_m = value0_01; + *rms_e = value0_01_exp; + shift = shift - delta; + /* Limit shift_to 31*/ + shift = fMin(31, shift); + } + + for (int i = 0; i < lg; i++) { + rms_m += fPow2Div2(r[i] << headroom) >> shift; + } + + return rms_m; +} + +/** + * \brief TCX gain calculation. + * \param pAacDecoderChannelInfo channel context data. + * \param r output spectrum. + * \param rms_e pointer to mantissa of energy value. + * \param rms_e pointer to exponent of energy value. + * \param frame the frame index of the LPD super frame. + * \param lg the frame length in audio samples. + * \param gain_m pointer to mantissa of TCX gain. + * \param gain_e pointer to exponent of TCX gain. + * \param elFlags element specific parser guidance flags. + * \param lg_fb the fullband frame length in audio samples. + * \param IGF_bgn the IGF start index. + */ +static void calcTCXGain(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + FIXP_DBL *r, FIXP_DBL rms_m, INT rms_e, const INT frame, + const INT lg) { + if ((rms_m != (FIXP_DBL)0)) { + FIXP_DBL tcx_gain_m; + INT tcx_gain_e; + + CLpd_DecodeGain(&tcx_gain_m, &tcx_gain_e, + pAacDecoderChannelInfo->pDynData->specificTo.usac + .tcx_global_gain[frame]); + + /* rms * 2^rms_e = lg/sqrt(sum(spec^2)) */ + if (rms_e & 1) { + rms_m >>= 1; + rms_e++; + } + + { + FIXP_DBL fx_lg; + INT fx_lg_e, s; + INT inv_e; + + /* lg = fx_lg * 2^fx_lg_e */ + s = fNorm((FIXP_DBL)lg); + fx_lg = (FIXP_DBL)lg << s; + fx_lg_e = DFRACT_BITS - 1 - s; + /* 1/sqrt(rms) */ + rms_m = invSqrtNorm2(rms_m, &inv_e); + rms_m = fMult(rms_m, fx_lg); + rms_e = inv_e - (rms_e >> 1) + fx_lg_e; + } + + { + int s = fNorm(tcx_gain_m); + tcx_gain_m = tcx_gain_m << s; + tcx_gain_e -= s; + } + + tcx_gain_m = fMultDiv2(tcx_gain_m, rms_m); + tcx_gain_e = tcx_gain_e + rms_e; + + /* global_gain * 2^(global_gain_e+rms_e) = (10^(global_gain/28)) * rms * + * 2^rms_e */ + { + { tcx_gain_e += 1; } + } + + pAacDecoderChannelInfo->data.usac.tcx_gain[frame] = tcx_gain_m; + pAacDecoderChannelInfo->data.usac.tcx_gain_e[frame] = tcx_gain_e; + + pAacDecoderChannelInfo->specScale[frame] += tcx_gain_e; + } +} + +/** + * \brief FDNS decoding. + * \param pAacDecoderChannelInfo channel context data. + * \param pAacDecoderStaticChannelInfo channel context static data. + * \param r output spectrum. + * \param lg the frame length in audio samples. + * \param frame the frame index of the LPD super frame. + * \param pScale pointer to current scale shift factor of r[]. + * \param A1 old input LPC coefficients of length M_LP_FILTER_ORDER. + * \param A2 new input LPC coefficients of length M_LP_FILTER_ORDER. + * \param pAlfdGains pointer for ALFD gains output scaled by 1. + * \param fdns_npts number of lines (FDNS_NPTS). + * \param inf_mask pointer to noise mask. + * \param IGF_win_mode IGF window mode (LONG, SHORT, TCX10, TCX20). + * \param frameType (IGF_FRAME_DIVISION_AAC_OR_TCX_LONG or + * IGF_FRAME_DIVISION_TCX_SHORT_1). + * \param elFlags element specific parser guidance flags. + * \param lg_fb the fullband frame length in audio samples. + * \param IGF_bgn the IGF start index. + * \param rms_m mantisse of energy. + * \param rms_e exponent of energy. + */ +/* static */ +void CLpd_FdnsDecode(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + FIXP_DBL r[], const INT lg, const INT frame, SHORT *pScale, + const FIXP_LPC A1[M_LP_FILTER_ORDER], const INT A1_exp, + const FIXP_LPC A2[M_LP_FILTER_ORDER], const INT A2_exp, + FIXP_DBL pAlfdGains[LFAC / 4], const INT fdns_npts) { + /* Weight LPC coefficients using Rm values */ + CLpd_AdaptLowFreqDeemph(r, lg, pAlfdGains, *pScale); + + FIXP_DBL rms_m = (FIXP_DBL)0; + INT rms_e = 0; + { + /* Calculate Energy */ + rms_m = calcEnergy(r, *pScale, lg, &rms_e); + } + + calcTCXGain(pAacDecoderChannelInfo, r, rms_m, rms_e, frame, lg); + + /* Apply ODFT and Noise Shaping. LP coefficient (A1, A2) weighting is done + * inside on the fly. */ + + lpc2mdctAndNoiseShaping(r, pScale, lg, fdns_npts, A1, A1_exp, A2, A2_exp); +} + +/** + * find pitch for TCX20 (time domain) concealment. + */ +static int find_mpitch(FIXP_DBL xri[], int lg) { + FIXP_DBL max, pitch; + INT pitch_e; + int i, n; + + max = (FIXP_DBL)0; + n = 2; + + /* find maximum below 400Hz */ + for (i = 2; i < (lg >> 4); i += 2) { + FIXP_DBL tmp = fPow2Div2(xri[i]) + fPow2Div2(xri[i + 1]); + if (tmp > max) { + max = tmp; + n = i; + } + } + + // pitch = ((float)lg<<1)/(float)n; + pitch = fDivNorm((FIXP_DBL)lg << 1, (FIXP_DBL)n, &pitch_e); + pitch >>= fixMax(0, DFRACT_BITS - 1 - pitch_e - 16); + + /* find pitch multiple under 20ms */ + if (pitch >= (FIXP_DBL)((256 << 16) - 1)) { /*231.0f*/ + n = 256; + } else { + FIXP_DBL mpitch = pitch; + while (mpitch < (FIXP_DBL)(255 << 16)) { + mpitch += pitch; + } + n = (int)(mpitch - pitch) >> 16; + } + + return (n); +} + +/** + * number of spectral coefficients / time domain samples using frame mode as + * index. + */ +static const int lg_table_ccfl[2][4] = { + {256, 256, 512, 1024}, /* coreCoderFrameLength = 1024 */ + {192, 192, 384, 768} /* coreCoderFrameLength = 768 */ +}; + +/** + * \brief Decode and render one MDCT-TCX frame. + * \param pAacDecoderChannelInfo channel context data. + * \param lg the frame length in audio samples. + * \param frame the frame index of the LPD super frame. + */ +static void CLpd_TcxDecode( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, UINT flags, + int mod, int last_mod, int frame, int frameOk) { + FIXP_DBL *pAlfd_gains = pAacDecoderStaticChannelInfo->last_alfd_gains; + ULONG *pSeed = &pAacDecoderStaticChannelInfo->nfRandomSeed; + int lg = (pAacDecoderChannelInfo->granuleLength == 128) + ? lg_table_ccfl[0][mod + 0] + : lg_table_ccfl[1][mod + 0]; + int next_frame = frame + (1 << (mod - 1)); + int isFullBandLpd = 0; + + /* Obtain r[] vector by combining the quant[] and noise[] vectors */ + { + FIXP_DBL noise_level; + FIXP_DBL *coeffs = + SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, frame, + pAacDecoderChannelInfo->granuleLength, isFullBandLpd); + int scale = pAacDecoderChannelInfo->specScale[frame]; + int i, nfBgn, nfEnd; + UCHAR tcx_noise_factor = pAacDecoderChannelInfo->pDynData->specificTo.usac + .tcx_noise_factor[frame]; + + /* find pitch for bfi case */ + pAacDecoderStaticChannelInfo->last_tcx_pitch = find_mpitch(coeffs, lg); + + if (frameOk) { + /* store for concealment */ + pAacDecoderStaticChannelInfo->last_tcx_noise_factor = tcx_noise_factor; + } else { + /* restore last frames value */ + tcx_noise_factor = pAacDecoderStaticChannelInfo->last_tcx_noise_factor; + } + + noise_level = + (FIXP_DBL)((LONG)FL2FXCONST_DBL(0.0625f) * (8 - tcx_noise_factor)); + noise_level = scaleValue(noise_level, -scale); + + const FIXP_DBL neg_noise_level = -noise_level; + + { + nfBgn = lg / 6; + nfEnd = lg; + } + + for (i = nfBgn; i < nfEnd - 7; i += 8) { + LONG tmp; + + /* Fill all 8 consecutive zero coeffs with noise */ + tmp = coeffs[i + 0] | coeffs[i + 1] | coeffs[i + 2] | coeffs[i + 3] | + coeffs[i + 4] | coeffs[i + 5] | coeffs[i + 6] | coeffs[i + 7]; + + if (tmp == 0) { + for (int k = i; k < i + 8; k++) { + UsacRandomSign(pSeed) ? (coeffs[k] = neg_noise_level) + : (coeffs[k] = noise_level); + } + } + } + if ((nfEnd - i) > + 0) { /* noise filling for last "band" with less than 8 bins */ + LONG tmp = (LONG)coeffs[i]; + int k; + + FDK_ASSERT((nfEnd - i) < 8); + for (k = 1; k < (nfEnd - i); k++) { + tmp |= (LONG)coeffs[i + k]; + } + if (tmp == 0) { + for (k = i; k < nfEnd; k++) { + UsacRandomSign(pSeed) ? (coeffs[k] = neg_noise_level) + : (coeffs[k] = noise_level); + } + } + } + } + + { + /* Convert LPC to LP domain */ + if (last_mod == 0) { + /* Note: The case where last_mod == 255 is handled by other means + * in CLpdChannelStream_Read() */ + E_LPC_f_lsp_a_conversion( + pAacDecoderChannelInfo->data.usac.lsp_coeff[frame], + pAacDecoderChannelInfo->data.usac.lp_coeff[frame], + &pAacDecoderChannelInfo->data.usac.lp_coeff_exp[frame]); + } + + E_LPC_f_lsp_a_conversion( + pAacDecoderChannelInfo->data.usac.lsp_coeff[next_frame], + pAacDecoderChannelInfo->data.usac.lp_coeff[next_frame], + &pAacDecoderChannelInfo->data.usac.lp_coeff_exp[next_frame]); + + /* FDNS decoding */ + CLpd_FdnsDecode( + pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, + SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, frame, + pAacDecoderChannelInfo->granuleLength, isFullBandLpd), + lg, frame, pAacDecoderChannelInfo->specScale + frame, + pAacDecoderChannelInfo->data.usac.lp_coeff[frame], + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[frame], + pAacDecoderChannelInfo->data.usac.lp_coeff[next_frame], + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[next_frame], pAlfd_gains, + pAacDecoderChannelInfo->granuleLength / 2 /* == FDNS_NPTS(ccfl) */ + ); + } +} + +/** + * \brief Read the tcx_coding bitstream part + * \param hBs bitstream handle to read from. + * \param pAacDecoderChannelInfo channel context info to store data into. + * \param lg the frame length in audio samples. + * \param first_tcx_flag flag indicating that this is the first TCX frame. + * \param frame the frame index of the LPD super frame. + */ +static AAC_DECODER_ERROR CLpd_TCX_Read( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, int lg, + int first_tcx_flag, int frame, UINT flags) { + AAC_DECODER_ERROR errorAAC = AAC_DEC_OK; + ARITH_CODING_ERROR error = ARITH_CODER_OK; + FIXP_DBL *pSpec; + int arith_reset_flag = 0; + int isFullBandLpd = 0; + + pSpec = SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, frame, + pAacDecoderChannelInfo->granuleLength, isFullBandLpd); + + /* TCX noise level */ + { + pAacDecoderChannelInfo->pDynData->specificTo.usac.tcx_noise_factor[frame] = + FDKreadBits(hBs, 3); + } + /* TCX global gain */ + pAacDecoderChannelInfo->pDynData->specificTo.usac.tcx_global_gain[frame] = + FDKreadBits(hBs, 7); + + /* Arithmetic coded residual/spectrum */ + if (first_tcx_flag) { + if (flags & AC_INDEP) { + arith_reset_flag = 1; + } else { + arith_reset_flag = FDKreadBits(hBs, 1); + } + } + + /* CArco_DecodeArithData() output scale of "pSpec" is DFRACT_BITS-1 */ + error = CArco_DecodeArithData(pAacDecoderStaticChannelInfo->hArCo, hBs, pSpec, + lg, lg, arith_reset_flag); + + /* Rescale residual/spectrum */ + { + int scale = getScalefactor(pSpec, lg) - 2; /* Leave 2 bits headroom */ + + /* Exponent of CArco_DecodeArithData() output is DFRACT_BITS; integer + * values. */ + scaleValues(pSpec, lg, scale); + scale = DFRACT_BITS - 1 - scale; + + pAacDecoderChannelInfo->specScale[frame] = scale; + } + + if (error == ARITH_CODER_ERROR) errorAAC = AAC_DEC_UNKNOWN; + + return errorAAC; +} + +/** + * \brief translate lpd_mode into the mod[] array which describes the mode of + * each each LPD frame + * \param mod[] the array that will be filled with the mode indexes of the + * inidividual frames. + * \param lpd_mode the lpd_mode field read from the lpd_channel_stream + */ +static AAC_DECODER_ERROR CLpd_ReadAndMapLpdModeToModArray( + UCHAR mod[4], HANDLE_FDK_BITSTREAM hBs, UINT elFlags) { + int lpd_mode; + + { + lpd_mode = FDKreadBits(hBs, 5); + + if (lpd_mode > 25 || lpd_mode < 0) { + return AAC_DEC_PARSE_ERROR; + } + + switch (lpd_mode) { + case 25: + /* 1 80MS frame */ + mod[0] = mod[1] = mod[2] = mod[3] = 3; + break; + case 24: + /* 2 40MS frames */ + mod[0] = mod[1] = mod[2] = mod[3] = 2; + break; + default: + switch (lpd_mode >> 2) { + case 4: + /* lpd_mode 19 - 16 => 1 40MS and 2 20MS frames */ + mod[0] = mod[1] = 2; + mod[2] = (lpd_mode & 1) ? 1 : 0; + mod[3] = (lpd_mode & 2) ? 1 : 0; + break; + case 5: + /* lpd_mode 23 - 20 => 2 20MS and 1 40MS frames */ + mod[2] = mod[3] = 2; + mod[0] = (lpd_mode & 1) ? 1 : 0; + mod[1] = (lpd_mode & 2) ? 1 : 0; + break; + default: + /* lpd_mode < 16 => 4 20MS frames */ + mod[0] = (lpd_mode & 1) ? 1 : 0; + mod[1] = (lpd_mode & 2) ? 1 : 0; + mod[2] = (lpd_mode & 4) ? 1 : 0; + mod[3] = (lpd_mode & 8) ? 1 : 0; + break; + } + break; + } + } + return AAC_DEC_OK; +} + +static void CLpd_Reset( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + int keep_past_signal) { + int i; + + /* Reset TCX / ACELP common memory */ + if (!keep_past_signal) { + FDKmemclear(pAacDecoderStaticChannelInfo->old_synth, + sizeof(pAacDecoderStaticChannelInfo->old_synth)); + } + + /* Initialize the LSFs */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + pAacDecoderStaticChannelInfo->lpc4_lsf[i] = fdk_dec_lsf_init[i]; + } + + /* Reset memory needed by bass post-filter */ + FDKmemclear(pAacDecoderStaticChannelInfo->mem_bpf, + sizeof(pAacDecoderStaticChannelInfo->mem_bpf)); + + pAacDecoderStaticChannelInfo->old_bpf_control_info = 0; + for (i = 0; i < SYN_SFD; i++) { + pAacDecoderStaticChannelInfo->old_T_pf[i] = 64; + pAacDecoderStaticChannelInfo->old_gain_pf[i] = (FIXP_DBL)0; + } + + /* Reset ACELP memory */ + CLpd_AcelpReset(&pAacDecoderStaticChannelInfo->acelp); + + pAacDecoderStaticChannelInfo->last_lpc_lost = 0; /* prev_lpc_lost */ + pAacDecoderStaticChannelInfo->last_tcx_pitch = L_DIV; /* pitch_tcx */ + pAacDecoderStaticChannelInfo->numLostLpdFrames = 0; /* nbLostCmpt */ +} + +/* + * Externally visible functions + */ + +AAC_DECODER_ERROR CLpdChannelStream_Read( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, UINT flags) { + AAC_DECODER_ERROR error = AAC_DEC_OK; + int first_tcx_flag; + int k, nbDiv, fFacDataPresent, first_lpd_flag, acelp_core_mode, + facGetMemState = 0; + UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod; + int lpd_mode_last, prev_frame_was_lpd; + USAC_COREMODE core_mode_last; + const int lg_table_offset = 0; + const int *lg_table = (pAacDecoderChannelInfo->granuleLength == 128) + ? &lg_table_ccfl[0][lg_table_offset] + : &lg_table_ccfl[1][lg_table_offset]; + int last_lpc_lost = pAacDecoderStaticChannelInfo->last_lpc_lost; + + int last_frame_ok = CConcealment_GetLastFrameOk( + &pAacDecoderStaticChannelInfo->concealmentInfo, 1); + + INT i_offset; + UINT samplingRate; + + samplingRate = pSamplingRateInfo->samplingRate; + + i_offset = + (INT)(samplingRate * PIT_MIN_12k8 + (FSCALE_DENOM / 2)) / FSCALE_DENOM - + (INT)PIT_MIN_12k8; + + if ((samplingRate < FAC_FSCALE_MIN) || (samplingRate > FAC_FSCALE_MAX)) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + + acelp_core_mode = FDKreadBits(hBs, 3); + + /* lpd_mode */ + error = CLpd_ReadAndMapLpdModeToModArray(mod, hBs, 0); + if (error != AAC_DEC_OK) { + goto bail; + } + + /* bpf_control_info */ + pAacDecoderChannelInfo->data.usac.bpf_control_info = FDKreadBit(hBs); + + /* last_core_mode */ + prev_frame_was_lpd = FDKreadBit(hBs); + /* fac_data_present */ + fFacDataPresent = FDKreadBit(hBs); + + /* Set valid values from + * pAacDecoderStaticChannelInfo->{last_core_mode,last_lpd_mode} */ + pAacDecoderChannelInfo->data.usac.core_mode_last = + pAacDecoderStaticChannelInfo->last_core_mode; + lpd_mode_last = pAacDecoderChannelInfo->data.usac.lpd_mode_last = + pAacDecoderStaticChannelInfo->last_lpd_mode; + + if (prev_frame_was_lpd == 0) { + /* Last frame was FD */ + pAacDecoderChannelInfo->data.usac.core_mode_last = FD_LONG; + pAacDecoderChannelInfo->data.usac.lpd_mode_last = 255; + } else { + /* Last frame was LPD */ + pAacDecoderChannelInfo->data.usac.core_mode_last = LPD; + if (((mod[0] == 0) && fFacDataPresent) || + ((mod[0] != 0) && !fFacDataPresent)) { + /* Currend mod is ACELP, fac data present -> TCX, current mod TCX, no fac + * data -> TCX */ + if (lpd_mode_last == 0) { + /* Bit stream interruption detected. Assume last TCX mode as TCX20. */ + pAacDecoderChannelInfo->data.usac.lpd_mode_last = 1; + } + /* Else assume that remembered TCX mode is correct. */ + } else { + pAacDecoderChannelInfo->data.usac.lpd_mode_last = 0; + } + } + + first_lpd_flag = (pAacDecoderChannelInfo->data.usac.core_mode_last != + LPD); /* Depends on bitstream configuration */ + first_tcx_flag = 1; + + if (pAacDecoderStaticChannelInfo->last_core_mode != + LPD) { /* ATTENTION: Reset depends on what we rendered before! */ + CLpd_Reset(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, 0); + + if (!last_frame_ok) { + /* If last rendered frame was not LPD and first lpd flag is not set, this + * must be an error - set last_lpc_lost flag */ + last_lpc_lost |= (first_lpd_flag) ? 0 : 1; + } + } + + core_mode_last = pAacDecoderChannelInfo->data.usac.core_mode_last; + lpd_mode_last = pAacDecoderChannelInfo->data.usac.lpd_mode_last; + + nbDiv = NB_DIV; + + /* k is the frame index. If a frame is of size 40MS or 80MS, + this frame index is incremented 2 or 4 instead of 1 respectively. */ + + k = 0; + while (k < nbDiv) { + /* Reset FAC data pointers in order to avoid applying old random FAC data. + */ + pAacDecoderChannelInfo->data.usac.fac_data[k] = NULL; + + if ((k == 0 && core_mode_last == LPD && fFacDataPresent) || + (lpd_mode_last == 0 && mod[k] > 0) || + ((lpd_mode_last != 255) && lpd_mode_last > 0 && mod[k] == 0)) { + int err; + + /* Assign FAC memory */ + pAacDecoderChannelInfo->data.usac.fac_data[k] = + CLpd_FAC_GetMemory(pAacDecoderChannelInfo, mod, &facGetMemState); + + /* FAC for (ACELP -> TCX) or (TCX -> ACELP) */ + err = CLpd_FAC_Read( + hBs, pAacDecoderChannelInfo->data.usac.fac_data[k], + pAacDecoderChannelInfo->data.usac.fac_data_e, + pAacDecoderChannelInfo->granuleLength, /* == fac_length */ + 0, k); + if (err != 0) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + + if (mod[k] == 0) /* acelp-mode */ + { + int err; + err = CLpd_AcelpRead( + hBs, &pAacDecoderChannelInfo->data.usac.acelp[k], acelp_core_mode, + pAacDecoderChannelInfo->granuleLength * 8 /* coreCoderFrameLength */, + i_offset); + if (err != 0) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + + lpd_mode_last = 0; + k++; + } else /* mode != 0 => TCX */ + { + error = CLpd_TCX_Read(hBs, pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo, lg_table[mod[k]], + first_tcx_flag, k, flags); + + lpd_mode_last = mod[k]; + first_tcx_flag = 0; + k += 1 << (mod[k] - 1); + } + if (error != AAC_DEC_OK) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + + { + int err; + + /* Read LPC coefficients */ + err = CLpc_Read( + hBs, pAacDecoderChannelInfo->data.usac.lsp_coeff, + pAacDecoderStaticChannelInfo->lpc4_lsf, + pAacDecoderChannelInfo->data.usac.lsf_adaptive_mean_cand, + pAacDecoderChannelInfo->data.usac.aStability, mod, first_lpd_flag, + /* if last lpc4 is available from concealment do not extrapolate lpc0 + from lpc2 */ + (mod[0] & 0x3) ? 0 + : (last_lpc_lost && + pAacDecoderStaticChannelInfo->last_core_mode != LPD), + last_frame_ok); + if (err != 0) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + + /* adjust old lsp[] following to a bad frame (to avoid overshoot) (ref: + * dec_LPD.c) */ + if (last_lpc_lost && !last_frame_ok) { + int k_next; + k = 0; + while (k < nbDiv) { + int i; + k_next = k + (((mod[k] & 0x3) == 0) ? 1 : (1 << (mod[k] - 1))); + FIXP_LPC *lsp_old = pAacDecoderChannelInfo->data.usac.lsp_coeff[k]; + FIXP_LPC *lsp_new = pAacDecoderChannelInfo->data.usac.lsp_coeff[k_next]; + + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + if (lsp_new[i] < lsp_old[i]) { + lsp_old[i] = lsp_new[i]; + } + } + k = k_next; + } + } + + if (!CConcealment_GetLastFrameOk( + &pAacDecoderStaticChannelInfo->concealmentInfo, 1)) { + E_LPC_f_lsp_a_conversion( + pAacDecoderChannelInfo->data.usac.lsp_coeff[0], + pAacDecoderChannelInfo->data.usac.lp_coeff[0], + &pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0]); + } else if (pAacDecoderStaticChannelInfo->last_lpd_mode != 0) { + if (pAacDecoderStaticChannelInfo->last_lpd_mode == 255) { + /* We need it for TCX decoding or ACELP excitation update */ + E_LPC_f_lsp_a_conversion( + pAacDecoderChannelInfo->data.usac.lsp_coeff[0], + pAacDecoderChannelInfo->data.usac.lp_coeff[0], + &pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0]); + } else { /* last_lpd_mode was TCX */ + /* Copy old LPC4 LP domain coefficients to LPC0 LP domain buffer (to avoid + * converting LSP coefficients again). */ + FDKmemcpy(pAacDecoderChannelInfo->data.usac.lp_coeff[0], + pAacDecoderStaticChannelInfo->lp_coeff_old[0], + M_LP_FILTER_ORDER * sizeof(FIXP_LPC)); + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0] = + pAacDecoderStaticChannelInfo->lp_coeff_old_exp[0]; + } + } /* case last_lpd_mode was ACELP is handled by CLpd_TcxDecode() */ + + if (fFacDataPresent && (core_mode_last != LPD)) { + int prev_frame_was_short; + + prev_frame_was_short = FDKreadBit(hBs); + + if (prev_frame_was_short) { + core_mode_last = pAacDecoderChannelInfo->data.usac.core_mode_last = + FD_SHORT; + pAacDecoderChannelInfo->data.usac.lpd_mode_last = 255; + + if ((pAacDecoderStaticChannelInfo->last_core_mode != FD_SHORT) && + CConcealment_GetLastFrameOk( + &pAacDecoderStaticChannelInfo->concealmentInfo, 1)) { + /* USAC Conformance document: + short_fac_flag shall be encoded with a value of 1 if the + window_sequence of the previous frame was 2 (EIGHT_SHORT_SEQUENCE). + Otherwise short_fac_flag shall be encoded with a + value of 0. */ + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + + /* Assign memory */ + pAacDecoderChannelInfo->data.usac.fac_data[0] = + CLpd_FAC_GetMemory(pAacDecoderChannelInfo, mod, &facGetMemState); + + { + int err; + + /* FAC for FD -> ACELP */ + err = CLpd_FAC_Read( + hBs, pAacDecoderChannelInfo->data.usac.fac_data[0], + pAacDecoderChannelInfo->data.usac.fac_data_e, + CLpd_FAC_getLength(core_mode_last != FD_SHORT, + pAacDecoderChannelInfo->granuleLength), + 1, 0); + if (err != 0) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + } + +bail: + if (error == AAC_DEC_OK) { + /* check consitency of last core/lpd mode values */ + if ((pAacDecoderChannelInfo->data.usac.core_mode_last != + pAacDecoderStaticChannelInfo->last_core_mode) && + (pAacDecoderStaticChannelInfo->last_lpc_lost == 0)) { + /* Something got wrong! */ + /* error = AAC_DEC_PARSE_ERROR; */ /* Throwing errors does not help */ + } else if ((pAacDecoderChannelInfo->data.usac.core_mode_last == LPD) && + (pAacDecoderChannelInfo->data.usac.lpd_mode_last != + pAacDecoderStaticChannelInfo->last_lpd_mode) && + (pAacDecoderStaticChannelInfo->last_lpc_lost == 0)) { + /* Something got wrong! */ + /* error = AAC_DEC_PARSE_ERROR; */ /* Throwing errors does not help */ + } + } + + return error; +} + +void CLpdChannelStream_Decode( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, UINT flags) { + UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod; + int k; + UCHAR last_lpd_mode; + int nbDiv = NB_DIV; + + /* k is the frame index. If a frame is of size 40MS or 80MS, + this frame index is incremented 2 or 4 instead of 1 respectively. */ + k = 0; + last_lpd_mode = + pAacDecoderChannelInfo->data.usac + .lpd_mode_last; /* could be different to what has been rendered */ + while (k < nbDiv) { + if (mod[k] == 0) { + /* ACELP */ + + /* If FAC (fac_data[k] != NULL), and previous frame was TCX, apply (TCX) + * gains to FAC data */ + if (last_lpd_mode > 0 && last_lpd_mode != 255 && + pAacDecoderChannelInfo->data.usac.fac_data[k]) { + CFac_ApplyGains(pAacDecoderChannelInfo->data.usac.fac_data[k], + pAacDecoderChannelInfo->granuleLength, + pAacDecoderStaticChannelInfo->last_tcx_gain, + pAacDecoderStaticChannelInfo->last_alfd_gains, + (last_lpd_mode < 4) ? last_lpd_mode : 3); + + pAacDecoderChannelInfo->data.usac.fac_data_e[k] += + pAacDecoderStaticChannelInfo->last_tcx_gain_e; + } + } else { + /* TCX */ + CLpd_TcxDecode(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, + flags, mod[k], last_lpd_mode, k, 1 /* frameOk == 1 */ + ); + + /* Store TCX gain scale for next possible FAC transition. */ + pAacDecoderStaticChannelInfo->last_tcx_gain = + pAacDecoderChannelInfo->data.usac.tcx_gain[k]; + pAacDecoderStaticChannelInfo->last_tcx_gain_e = + pAacDecoderChannelInfo->data.usac.tcx_gain_e[k]; + + /* If FAC (fac_data[k] != NULL), apply gains */ + if (last_lpd_mode == 0 && pAacDecoderChannelInfo->data.usac.fac_data[k]) { + CFac_ApplyGains( + pAacDecoderChannelInfo->data.usac.fac_data[k], + pAacDecoderChannelInfo->granuleLength /* == fac_length */, + pAacDecoderChannelInfo->data.usac.tcx_gain[k], + pAacDecoderStaticChannelInfo->last_alfd_gains, mod[k]); + + pAacDecoderChannelInfo->data.usac.fac_data_e[k] += + pAacDecoderChannelInfo->data.usac.tcx_gain_e[k]; + } + } + + /* remember previous mode */ + last_lpd_mode = mod[k]; + + /* Increase k to next frame */ + k += (mod[k] == 0) ? 1 : (1 << (mod[k] - 1)); + } +} + +AAC_DECODER_ERROR CLpd_RenderTimeSignal( + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC *pTimeData, + INT lFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk, + const INT aacOutDataHeadroom, UINT flags, UINT strmFlags) { + UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod; + AAC_DECODER_ERROR error = AAC_DEC_OK; + int k, i_offset; + int last_k; + int nrSamples = 0; + int facFB = 1; + int nbDiv = NB_DIV; + int lDiv = lFrame / nbDiv; /* length of division (acelp or tcx20 frame)*/ + int lFac = lDiv / 2; + int nbSubfr = + lFrame / (nbDiv * L_SUBFR); /* number of subframes per division */ + int nbSubfrSuperfr = nbDiv * nbSubfr; + int synSfd = (nbSubfrSuperfr / 2) - BPF_SFD; + int SynDelay = synSfd * L_SUBFR; + int aacDelay = lFrame / 2; + + /* + In respect to the reference software, the synth pointer here is lagging by + aacDelay ( == SYN_DELAY + BPF_DELAY ) samples. The corresponding old + synthesis samples are handled by the IMDCT overlap. + */ + + FIXP_DBL *synth_buf = + pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1->synth_buf; + FIXP_DBL *synth = synth_buf + PIT_MAX_MAX - BPF_DELAY; + UCHAR last_lpd_mode, last_last_lpd_mode, last_lpc_lost, last_frame_lost; + + INT pitch[NB_SUBFR_SUPERFR + SYN_SFD]; + FIXP_DBL pit_gain[NB_SUBFR_SUPERFR + SYN_SFD]; + + const int *lg_table; + int lg_table_offset = 0; + + UINT samplingRate = pSamplingRateInfo->samplingRate; + + FDKmemclear(pitch, (NB_SUBFR_SUPERFR + SYN_SFD) * sizeof(INT)); + + if (flags & AACDEC_FLUSH) { + CLpd_Reset(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, + flags & AACDEC_FLUSH); + frameOk = 0; + } + + switch (lFrame) { + case 1024: + lg_table = &lg_table_ccfl[0][lg_table_offset]; + break; + case 768: + lg_table = &lg_table_ccfl[1][lg_table_offset]; + break; + default: + FDK_ASSERT(0); + return AAC_DEC_UNKNOWN; + } + + last_frame_lost = !CConcealment_GetLastFrameOk( + &pAacDecoderStaticChannelInfo->concealmentInfo, 0); + + /* Maintain LPD mode from previous frame */ + if ((pAacDecoderStaticChannelInfo->last_core_mode == FD_LONG) || + (pAacDecoderStaticChannelInfo->last_core_mode == FD_SHORT)) { + pAacDecoderStaticChannelInfo->last_lpd_mode = 255; + } + + if (!frameOk) { + FIXP_DBL old_tcx_gain; + FIXP_SGL old_stab; + SCHAR old_tcx_gain_e; + int nLostSf; + + last_lpd_mode = pAacDecoderStaticChannelInfo->last_lpd_mode; + old_tcx_gain = pAacDecoderStaticChannelInfo->last_tcx_gain; + old_tcx_gain_e = pAacDecoderStaticChannelInfo->last_tcx_gain_e; + old_stab = pAacDecoderStaticChannelInfo->oldStability; + nLostSf = pAacDecoderStaticChannelInfo->numLostLpdFrames; + + /* patch the last LPD mode */ + pAacDecoderChannelInfo->data.usac.lpd_mode_last = last_lpd_mode; + + /* Do mode extrapolation and repeat the previous mode: + if previous mode = ACELP -> ACELP + if previous mode = TCX-20/40 -> TCX-20 + if previous mode = TCX-80 -> TCX-80 + notes: + - ACELP is not allowed after TCX (no pitch information to reuse) + - TCX-40 is not allowed in the mode repetition to keep the logic simple + */ + switch (last_lpd_mode) { + case 0: + mod[0] = mod[1] = mod[2] = mod[3] = 0; /* -> ACELP concealment */ + break; + case 3: + mod[0] = mod[1] = mod[2] = mod[3] = 3; /* -> TCX FD concealment */ + break; + case 2: + mod[0] = mod[1] = mod[2] = mod[3] = 2; /* -> TCX FD concealment */ + break; + case 1: + default: + mod[0] = mod[1] = mod[2] = mod[3] = 4; /* -> TCX TD concealment */ + break; + } + + /* LPC extrapolation */ + CLpc_Conceal(pAacDecoderChannelInfo->data.usac.lsp_coeff, + pAacDecoderStaticChannelInfo->lpc4_lsf, + pAacDecoderStaticChannelInfo->lsf_adaptive_mean, + /*(pAacDecoderStaticChannelInfo->numLostLpdFrames == 0) ||*/ + (last_lpd_mode == 255)); + + if ((last_lpd_mode > 0) && (last_lpd_mode < 255)) { + /* Copy old LPC4 LP domain coefficients to LPC0 LP domain buffer (to avoid + * converting LSP coefficients again). */ + FDKmemcpy(pAacDecoderChannelInfo->data.usac.lp_coeff[0], + pAacDecoderStaticChannelInfo->lp_coeff_old[0], + M_LP_FILTER_ORDER * sizeof(FIXP_LPC)); + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0] = + pAacDecoderStaticChannelInfo->lp_coeff_old_exp[0]; + } /* case last_lpd_mode was ACELP is handled by CLpd_TcxDecode() */ + /* case last_lpd_mode was Time domain TCX concealment is handled after this + * "if (!frameOk)"-block */ + + /* k is the frame index. If a frame is of size 40MS or 80MS, + this frame index is incremented 2 or 4 instead of 1 respectively. */ + k = 0; + while (k < nbDiv) { + pAacDecoderChannelInfo->data.usac.tcx_gain[k] = old_tcx_gain; + pAacDecoderChannelInfo->data.usac.tcx_gain_e[k] = old_tcx_gain_e; + + /* restore stability value from last frame */ + pAacDecoderChannelInfo->data.usac.aStability[k] = old_stab; + + /* Increase k to next frame */ + k += ((mod[k] & 0x3) == 0) ? 1 : (1 << ((mod[k] & 0x3) - 1)); + + nLostSf++; + } + } else { + if ((pAacDecoderStaticChannelInfo->last_lpd_mode == 4) && (mod[0] > 0)) { + /* Copy old LPC4 LP domain coefficients to LPC0 LP domain buffer (to avoid + * converting LSP coefficients again). */ + FDKmemcpy(pAacDecoderChannelInfo->data.usac.lp_coeff[0], + pAacDecoderStaticChannelInfo->lp_coeff_old[0], + M_LP_FILTER_ORDER * sizeof(FIXP_LPC)); + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0] = + pAacDecoderStaticChannelInfo->lp_coeff_old_exp[0]; + } + } + + Acelp_PreProcessing(synth_buf, pAacDecoderStaticChannelInfo->old_synth, pitch, + pAacDecoderStaticChannelInfo->old_T_pf, pit_gain, + pAacDecoderStaticChannelInfo->old_gain_pf, samplingRate, + &i_offset, lFrame, synSfd, nbSubfrSuperfr); + + /* k is the frame index. If a frame is of size 40MS or 80MS, + this frame index is incremented 2 or 4 instead of 1 respectively. */ + k = 0; + last_k = -1; /* mark invalid */ + last_lpd_mode = pAacDecoderStaticChannelInfo->last_lpd_mode; + last_last_lpd_mode = pAacDecoderStaticChannelInfo->last_last_lpd_mode; + last_lpc_lost = pAacDecoderStaticChannelInfo->last_lpc_lost | last_frame_lost; + + /* This buffer must be avalable for the case of FD->ACELP transition. The + beginning of the buffer is used after the BPF to overwrite the output signal. + Only the FAC area must be affected by the BPF */ + + while (k < nbDiv) { + if (frameOk == 0) { + pAacDecoderStaticChannelInfo->numLostLpdFrames++; + } else { + last_frame_lost |= + (pAacDecoderStaticChannelInfo->numLostLpdFrames > 0) ? 1 : 0; + pAacDecoderStaticChannelInfo->numLostLpdFrames = 0; + } + if (mod[k] == 0 || mod[k] == 4) { + /* ACELP or TCX time domain concealment */ + FIXP_DBL *acelp_out; + + /* FAC management */ + if ((last_lpd_mode != 0) && (last_lpd_mode != 4)) /* TCX TD concealment */ + { + FIXP_DBL *pFacData = NULL; + + if (frameOk && !last_frame_lost) { + pFacData = pAacDecoderChannelInfo->data.usac.fac_data[k]; + } + + nrSamples += CLpd_FAC_Mdct2Acelp( + &pAacDecoderStaticChannelInfo->IMdct, synth + nrSamples, pFacData, + pAacDecoderChannelInfo->data.usac.fac_data_e[k], + pAacDecoderChannelInfo->data.usac.lp_coeff[k], + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[k], + lFrame - nrSamples, + CLpd_FAC_getLength( + (pAacDecoderStaticChannelInfo->last_core_mode != FD_SHORT) || + (k > 0), + lFac), + (pAacDecoderStaticChannelInfo->last_core_mode != LPD) && (k == 0), + 0); + + FDKmemcpy( + synth + nrSamples, pAacDecoderStaticChannelInfo->IMdct.overlap.time, + pAacDecoderStaticChannelInfo->IMdct.ov_offset * sizeof(FIXP_DBL)); + { + FIXP_LPC *lp_prev = + pAacDecoderChannelInfo->data.usac + .lp_coeff[0]; /* init value does not real matter */ + INT lp_prev_exp = pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0]; + + if (last_lpd_mode != 255) { /* last mode was tcx */ + last_k = k - (1 << (last_lpd_mode - 1)); + if (last_k < 0) { + lp_prev = pAacDecoderStaticChannelInfo->lp_coeff_old[1]; + lp_prev_exp = pAacDecoderStaticChannelInfo->lp_coeff_old_exp[1]; + } else { + lp_prev = pAacDecoderChannelInfo->data.usac.lp_coeff[last_k]; + lp_prev_exp = + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[last_k]; + } + } + + CLpd_AcelpPrepareInternalMem( + synth + aacDelay + k * lDiv, last_lpd_mode, + (last_last_lpd_mode == 4) ? 0 : last_last_lpd_mode, + pAacDecoderChannelInfo->data.usac.lp_coeff[k], + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[k], lp_prev, + lp_prev_exp, &pAacDecoderStaticChannelInfo->acelp, lFrame, + (last_frame_lost && k < 2), mod[k]); + } + } else { + if (k == 0 && pAacDecoderStaticChannelInfo->IMdct.ov_offset != + lFrame / facFB / 2) { + pAacDecoderStaticChannelInfo->IMdct.ov_offset = lFrame / facFB / 2; + } + nrSamples += imdct_drain(&pAacDecoderStaticChannelInfo->IMdct, + synth + nrSamples, lFrame / facFB - nrSamples); + } + + if (nrSamples >= lFrame / facFB) { + /* Write ACELP time domain samples into IMDCT overlap buffer at + * pAacDecoderStaticChannelInfo->IMdct.overlap.time + + * pAacDecoderStaticChannelInfo->IMdct.ov_offset + */ + acelp_out = pAacDecoderStaticChannelInfo->IMdct.overlap.time + + pAacDecoderStaticChannelInfo->IMdct.ov_offset; + + /* Account ACELP time domain output samples to overlap buffer */ + pAacDecoderStaticChannelInfo->IMdct.ov_offset += lDiv; + } else { + /* Write ACELP time domain samples into output buffer at pTimeData + + * nrSamples */ + acelp_out = synth + nrSamples; + + /* Account ACELP time domain output samples to output buffer */ + nrSamples += lDiv; + } + + if (mod[k] == 4) { + pAacDecoderStaticChannelInfo->acelp.wsyn_rms = scaleValue( + pAacDecoderChannelInfo->data.usac.tcx_gain[k], + fixMin(0, + pAacDecoderChannelInfo->data.usac.tcx_gain_e[k] - SF_EXC)); + CLpd_TcxTDConceal(&pAacDecoderStaticChannelInfo->acelp, + &pAacDecoderStaticChannelInfo->last_tcx_pitch, + pAacDecoderChannelInfo->data.usac.lsp_coeff[k], + pAacDecoderChannelInfo->data.usac.lsp_coeff[k + 1], + pAacDecoderChannelInfo->data.usac.aStability[k], + pAacDecoderStaticChannelInfo->numLostLpdFrames, + acelp_out, lFrame, + pAacDecoderStaticChannelInfo->last_tcx_noise_factor); + + } else { + FDK_ASSERT(pAacDecoderChannelInfo->data.usac.aStability[k] >= + (FIXP_SGL)0); + CLpd_AcelpDecode(&pAacDecoderStaticChannelInfo->acelp, i_offset, + pAacDecoderChannelInfo->data.usac.lsp_coeff[k], + pAacDecoderChannelInfo->data.usac.lsp_coeff[k + 1], + pAacDecoderChannelInfo->data.usac.aStability[k], + &pAacDecoderChannelInfo->data.usac.acelp[k], + pAacDecoderStaticChannelInfo->numLostLpdFrames, + last_lpc_lost, k, acelp_out, + &pitch[(k * nbSubfr) + synSfd], + &pit_gain[(k * nbSubfr) + synSfd], lFrame); + } + + if (mod[k] != 4) { + if (last_lpd_mode != 0 && + pAacDecoderChannelInfo->data.usac + .bpf_control_info) { /* FD/TCX -> ACELP transition */ + /* bass post-filter past FAC area (past two (one for FD short) + * subframes) */ + int currentSf = synSfd + k * nbSubfr; + + if ((k > 0) || (pAacDecoderStaticChannelInfo->last_core_mode != + FD_SHORT)) { /* TCX or FD long -> ACELP */ + pitch[currentSf - 2] = pitch[currentSf - 1] = pitch[currentSf]; + pit_gain[currentSf - 2] = pit_gain[currentSf - 1] = + pit_gain[currentSf]; + } else { /* FD short -> ACELP */ + pitch[currentSf - 1] = pitch[currentSf]; + pit_gain[currentSf - 1] = pit_gain[currentSf]; + } + } + } + } else { /* TCX */ + int lg = lg_table[mod[k]]; + int isFullBandLpd = 0; + + /* FAC management */ + if ((last_lpd_mode == 0) || (last_lpd_mode == 4)) /* TCX TD concealment */ + { + C_AALLOC_SCRATCH_START(fac_buf, FIXP_DBL, 1024 / 8); + + /* pAacDecoderChannelInfo->data.usac.fac_data[k] == NULL means no FAC + * data available. */ + if (last_frame_lost == 1 || + pAacDecoderChannelInfo->data.usac.fac_data[k] == NULL) { + FDKmemclear(fac_buf, 1024 / 8 * sizeof(FIXP_DBL)); + pAacDecoderChannelInfo->data.usac.fac_data[k] = fac_buf; + pAacDecoderChannelInfo->data.usac.fac_data_e[k] = 0; + } + + nrSamples += CLpd_FAC_Acelp2Mdct( + &pAacDecoderStaticChannelInfo->IMdct, synth + nrSamples, + SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, k, + pAacDecoderChannelInfo->granuleLength, isFullBandLpd), + pAacDecoderChannelInfo->specScale + k, 1, + pAacDecoderChannelInfo->data.usac.fac_data[k], + pAacDecoderChannelInfo->data.usac.fac_data_e[k], + pAacDecoderChannelInfo->granuleLength /* == fac_length */, + lFrame - nrSamples, lg, + FDKgetWindowSlope(lDiv, + GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + lDiv, pAacDecoderChannelInfo->data.usac.lp_coeff[k], + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[k], + &pAacDecoderStaticChannelInfo->acelp, + pAacDecoderChannelInfo->data.usac.tcx_gain[k], + (last_frame_lost || !frameOk), 0 /* is not FD FAC */ + , + last_lpd_mode, k, + pAacDecoderChannelInfo + ->currAliasingSymmetry /* Note: The current aliasing + symmetry for a TCX (i.e. LPD) + frame must always be 0 */ + ); + + pitch[(k * nbSubfr) + synSfd + 1] = pitch[(k * nbSubfr) + synSfd] = + pitch[(k * nbSubfr) + synSfd - 1]; + pit_gain[(k * nbSubfr) + synSfd + 1] = + pit_gain[(k * nbSubfr) + synSfd] = + pit_gain[(k * nbSubfr) + synSfd - 1]; + + C_AALLOC_SCRATCH_END(fac_buf, FIXP_DBL, 1024 / 8); + } else { + int tl = lg; + int fl = lDiv; + int fr = lDiv; + + nrSamples += imlt_block( + &pAacDecoderStaticChannelInfo->IMdct, synth + nrSamples, + SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, k, + pAacDecoderChannelInfo->granuleLength, isFullBandLpd), + pAacDecoderChannelInfo->specScale + k, 1, lFrame - nrSamples, tl, + FDKgetWindowSlope(fl, + GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fl, + FDKgetWindowSlope(fr, + GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fr, pAacDecoderChannelInfo->data.usac.tcx_gain[k], + pAacDecoderChannelInfo->currAliasingSymmetry + ? MLT_FLAG_CURR_ALIAS_SYMMETRY + : 0); + } + } + /* remember previous mode */ + last_last_lpd_mode = last_lpd_mode; + last_lpd_mode = mod[k]; + last_lpc_lost = (frameOk == 0) ? 1 : 0; + + /* Increase k to next frame */ + last_k = k; + k += ((mod[k] & 0x3) == 0) ? 1 : (1 << (mod[k] - 1)); + } + + if (frameOk) { + /* assume data was ok => store for concealment */ + FDK_ASSERT(pAacDecoderChannelInfo->data.usac.aStability[last_k] >= + (FIXP_SGL)0); + pAacDecoderStaticChannelInfo->oldStability = + pAacDecoderChannelInfo->data.usac.aStability[last_k]; + FDKmemcpy(pAacDecoderStaticChannelInfo->lsf_adaptive_mean, + pAacDecoderChannelInfo->data.usac.lsf_adaptive_mean_cand, + M_LP_FILTER_ORDER * sizeof(FIXP_LPC)); + } + + /* store past lp coeffs for next superframe (they are only valid and needed if + * last_lpd_mode was tcx) */ + if (last_lpd_mode > 0) { + FDKmemcpy(pAacDecoderStaticChannelInfo->lp_coeff_old[0], + pAacDecoderChannelInfo->data.usac.lp_coeff[nbDiv], + M_LP_FILTER_ORDER * sizeof(FIXP_LPC)); + pAacDecoderStaticChannelInfo->lp_coeff_old_exp[0] = + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[nbDiv]; + FDKmemcpy(pAacDecoderStaticChannelInfo->lp_coeff_old[1], + pAacDecoderChannelInfo->data.usac.lp_coeff[last_k], + M_LP_FILTER_ORDER * sizeof(FIXP_LPC)); + pAacDecoderStaticChannelInfo->lp_coeff_old_exp[1] = + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[last_k]; + } + + FDK_ASSERT(nrSamples == lFrame); + + /* check whether usage of bass postfilter was de-activated in the bitstream; + if yes, set pitch gain to 0 */ + if (!(pAacDecoderChannelInfo->data.usac.bpf_control_info)) { + if (mod[0] != 0 && (pAacDecoderStaticChannelInfo->old_bpf_control_info)) { + for (int i = 2; i < nbSubfrSuperfr; i++) + pit_gain[synSfd + i] = (FIXP_DBL)0; + } else { + for (int i = 0; i < nbSubfrSuperfr; i++) + pit_gain[synSfd + i] = (FIXP_DBL)0; + } + } + + /* for bass postfilter */ + for (int n = 0; n < synSfd; n++) { + pAacDecoderStaticChannelInfo->old_T_pf[n] = pitch[nbSubfrSuperfr + n]; + pAacDecoderStaticChannelInfo->old_gain_pf[n] = pit_gain[nbSubfrSuperfr + n]; + } + + pAacDecoderStaticChannelInfo->old_bpf_control_info = + pAacDecoderChannelInfo->data.usac.bpf_control_info; + + { + INT lookahead = -BPF_DELAY; + int copySamp = (mod[nbDiv - 1] == 0) ? (aacDelay) : (aacDelay - lFac); + + /* Copy enough time domain samples from MDCT to synthesis buffer as needed + * by the bass postfilter */ + + lookahead += imdct_copy_ov_and_nr(&pAacDecoderStaticChannelInfo->IMdct, + synth + nrSamples, copySamp); + + FDK_ASSERT(lookahead == copySamp - BPF_DELAY); + + FIXP_DBL *p2_synth = synth + BPF_DELAY; + + /* recalculate pitch gain to allow postfilering on FAC area */ + for (int i = 0; i < nbSubfrSuperfr; i++) { + int T = pitch[i]; + FIXP_DBL gain = pit_gain[i]; + + if (gain > (FIXP_DBL)0) { + gain = get_gain(&p2_synth[i * L_SUBFR], &p2_synth[(i * L_SUBFR) - T], + L_SUBFR); + pit_gain[i] = gain; + } + } + + { + bass_pf_1sf_delay(p2_synth, pitch, pit_gain, lFrame, lFrame / facFB, + mod[nbDiv - 1] ? (SynDelay - (lDiv / 2)) : SynDelay, + pTimeData, aacOutDataHeadroom, + pAacDecoderStaticChannelInfo->mem_bpf); + } + } + + Acelp_PostProcessing(synth_buf, pAacDecoderStaticChannelInfo->old_synth, + pitch, pAacDecoderStaticChannelInfo->old_T_pf, lFrame, + synSfd, nbSubfrSuperfr); + + /* Store last mode for next super frame */ + { pAacDecoderStaticChannelInfo->last_core_mode = LPD; } + pAacDecoderStaticChannelInfo->last_lpd_mode = last_lpd_mode; + pAacDecoderStaticChannelInfo->last_last_lpd_mode = last_last_lpd_mode; + pAacDecoderStaticChannelInfo->last_lpc_lost = last_lpc_lost; + + return error; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpd.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpd.h new file mode 100644 index 0000000000000..448dc55c7ce21 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_lpd.h @@ -0,0 +1,201 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: USAC Linear Prediction Domain coding + +*******************************************************************************/ + +#ifndef USACDEC_LPD_H +#define USACDEC_LPD_H + +#include "channelinfo.h" + +#define OPTIMIZE_AVG_PERFORMANCE + +/** + * \brief read a lpd_channel_stream. + * \param hBs a bit stream handle, where the lpd_channel_stream is located. + * \param pAacDecoderChannelInfo the channel context structure for storing read + * data. + * \param flags bit stream syntax flags. + * \return AAC_DECODER_ERROR error code. + */ +AAC_DECODER_ERROR CLpdChannelStream_Read( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, UINT flags); + +/** + * \brief decode one lpd_channel_stream and render the audio output. + * \param pAacDecoderChannelInfo struct holding the channel information to be + * rendered. + * \param pAacDecoderStaticChannelInfo struct holding the persistent channel + * information to be rendered. + * \param pSamplingRateInfo holds the sampling rate information + * \param elFlags holds the internal decoder flags + */ +void CLpdChannelStream_Decode( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, UINT flags); + +/** + * \brief generate time domain output signal for LPD channel streams + * \param pAacDecoderStaticChannelInfo + * \param pAacDecoderChannelInfo + * \param pTimeData pointer to output buffer + * \param samplesPerFrame amount of output samples + * \param pSamplingRateInfo holds the sampling rate information + * \param aacOutDataHeadroom headroom of the output time signal to prevent + * clipping + */ +AAC_DECODER_ERROR CLpd_RenderTimeSignal( + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC *pTimeData, + INT samplesPerFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk, + const INT aacOutDataHeadroom, UINT flags, UINT strmFlags); + +static inline INT CLpd_FAC_getLength(int fNotShortBlock, int fac_length_long) { + if (fNotShortBlock) { + return (fac_length_long); + } else { + return fac_length_long / 2; + } +} + +void filtLP(const FIXP_DBL *syn, PCM_DEC *syn_out, FIXP_DBL *noise, + const FIXP_SGL *filt, const INT aacOutDataHeadroom, INT stop, + int len); + +/** + * \brief perform a low-frequency pitch enhancement on time domain signal + * \param[in] syn pointer to time domain input signal + * \param[in] synFB pointer to time domain input signal + * \param[in] upsampling factor + * \param[in] T_sf array with past decoded pitch period values for each subframe + * \param[in] non_zero_gain_flags indicates whether pitch gains of past + * subframes are zero or not, msb -> [1 BPF_DELAY subfr][7 SYN_DELAY subfr][16 + * new subfr] <- lsb + * \param[in] l_frame length of filtering, must be multiple of L_SUBFR + * \param[in] l_next length of allowed look ahead on syn[i], i < l_frame+l_next + * \param[out] synth_out pointer to time domain output signal + * \param[in] headroom of the output time signal to prevent clipping + * \param[in,out] mem_bpf pointer to filter memory (L_FILT+L_SUBFR) + */ + +void bass_pf_1sf_delay(FIXP_DBL syn[], const INT T_sf[], FIXP_DBL *pit_gain, + const int frame_length, const INT l_frame, + const INT l_next, PCM_DEC *synth_out, + const INT aacOutDataHeadroom, FIXP_DBL mem_bpf[]); + +/** + * \brief random sign generator for FD and TCX noise filling + * \param[in,out] seed pointer to random seed + * \return if return value is zero use positive sign + * \Note: This code is also implemented as a copy in block.cpp, grep for + * "UsacRandomSign" + */ +FDK_INLINE +int UsacRandomSign(ULONG *seed) { + *seed = (ULONG)((UINT64)(*seed) * 69069 + 5); + + return (int)((*seed) & 0x10000); +} + +void CFdp_Reset(CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo); + +#endif /* USACDEC_LPD_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_rom.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_rom.cpp new file mode 100644 index 0000000000000..ca3009e506efa --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_rom.cpp @@ -0,0 +1,1504 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): M. Jander + + Description: + +*******************************************************************************/ + +#include "usacdec_rom.h" + +#define NB_SPHERE 32 +#define NB_LEADER 37 +#define NB_LDSIGN 226 +#define NB_LDQ3 9 +#define NB_LDQ4 28 + +/* For bass post filter */ +#define FL2FXCONST_SGL_FILT(a) FL2FXCONST_SGL(a*(1 << SF_FILT_LP)) +#define SF_FILT_LP 1 + +/* table of factorial */ +const UINT fdk_dec_tab_factorial[8] = {5040, 720, 120, 24, 6, 2, 1, 1}; + +/* Da - Absolute leaders */ +const UCHAR fdk_dec_Da[NB_LEADER][8] = { + {1, 1, 1, 1, 1, 1, 1, 1}, {2, 2, 0, 0, 0, 0, 0, 0}, + {2, 2, 2, 2, 0, 0, 0, 0}, {3, 1, 1, 1, 1, 1, 1, 1}, + {4, 0, 0, 0, 0, 0, 0, 0}, {2, 2, 2, 2, 2, 2, 0, 0}, + {3, 3, 1, 1, 1, 1, 1, 1}, {4, 2, 2, 0, 0, 0, 0, 0}, + {2, 2, 2, 2, 2, 2, 2, 2}, {3, 3, 3, 1, 1, 1, 1, 1}, + {4, 2, 2, 2, 2, 0, 0, 0}, {4, 4, 0, 0, 0, 0, 0, 0}, + {5, 1, 1, 1, 1, 1, 1, 1}, {3, 3, 3, 3, 1, 1, 1, 1}, + {4, 2, 2, 2, 2, 2, 2, 0}, {4, 4, 2, 2, 0, 0, 0, 0}, + {5, 3, 1, 1, 1, 1, 1, 1}, {6, 2, 0, 0, 0, 0, 0, 0}, + {4, 4, 4, 0, 0, 0, 0, 0}, {6, 2, 2, 2, 0, 0, 0, 0}, + {6, 4, 2, 0, 0, 0, 0, 0}, {7, 1, 1, 1, 1, 1, 1, 1}, + {8, 0, 0, 0, 0, 0, 0, 0}, {6, 6, 0, 0, 0, 0, 0, 0}, + {8, 2, 2, 0, 0, 0, 0, 0}, {8, 4, 0, 0, 0, 0, 0, 0}, + {9, 1, 1, 1, 1, 1, 1, 1}, {10, 2, 0, 0, 0, 0, 0, 0}, + {8, 8, 0, 0, 0, 0, 0, 0}, {10, 6, 0, 0, 0, 0, 0, 0}, + {12, 0, 0, 0, 0, 0, 0, 0}, {12, 4, 0, 0, 0, 0, 0, 0}, + {10, 10, 0, 0, 0, 0, 0, 0}, {14, 2, 0, 0, 0, 0, 0, 0}, + {12, 8, 0, 0, 0, 0, 0, 0}, {16, 0, 0, 0, 0, 0, 0, 0}, + {20, 0, 0, 0, 0, 0, 0, 0}}; + +/* Ds - Sign codes of all signed leaders */ +const UCHAR fdk_dec_Ds[NB_LDSIGN] = { + 0, 3, 15, 63, 255, 0, 64, 192, 0, 16, 48, 112, 240, 1, 7, + 31, 127, 128, 131, 143, 191, 0, 128, 0, 4, 12, 28, 60, 124, 252, + 0, 3, 15, 63, 65, 71, 95, 192, 195, 207, 255, 0, 32, 96, 128, + 160, 224, 0, 1, 3, 7, 15, 31, 63, 127, 255, 1, 7, 31, 32, + 35, 47, 97, 103, 127, 224, 227, 239, 0, 8, 24, 56, 120, 128, 136, + 152, 184, 248, 0, 64, 192, 0, 3, 15, 63, 129, 135, 159, 255, 0, + 3, 15, 17, 23, 48, 51, 63, 113, 119, 240, 243, 255, 0, 2, 6, + 14, 30, 62, 126, 128, 130, 134, 142, 158, 190, 254, 0, 16, 48, 64, + 80, 112, 192, 208, 240, 1, 7, 31, 64, 67, 79, 127, 128, 131, 143, + 191, 193, 199, 223, 0, 64, 128, 192, 0, 32, 96, 224, 0, 16, 48, + 112, 128, 144, 176, 240, 0, 32, 64, 96, 128, 160, 192, 224, 1, 7, + 31, 127, 128, 131, 143, 191, 0, 128, 0, 64, 192, 0, 32, 96, 128, + 160, 224, 0, 64, 128, 192, 0, 3, 15, 63, 129, 135, 159, 255, 0, + 64, 128, 192, 0, 64, 192, 0, 64, 128, 192, 0, 128, 0, 64, 128, + 192, 0, 64, 192, 0, 64, 128, 192, 0, 64, 128, 192, 0, 128, 0, + 128}; + +/* Ns - Number of signed leader associated to a given absolute leader */ +const UCHAR fdk_dec_Ns[NB_LEADER] = { + 5, 3, 5, 8, 2, 7, 11, 6, 9, 12, 10, 3, 8, 13, 14, 9, 14, 4, 4, + 8, 8, 8, 2, 3, 6, 4, 8, 4, 3, 4, 2, 4, 3, 4, 4, 2, 2}; + +/* Ia - Position of the first signed leader associated to an absolute leader */ +const UCHAR fdk_dec_Ia[NB_LEADER] = { + 0, 5, 8, 13, 21, 23, 30, 41, 47, 56, 68, 78, 81, + 89, 102, 116, 125, 139, 143, 147, 155, 163, 171, 173, 176, 182, + 186, 194, 198, 201, 205, 207, 211, 214, 218, 222, 224}; + +/* Is - Cardinalite offset of signed leaders */ +const USHORT fdk_dec_Is[NB_LDSIGN] = { + 0, 1, 29, 99, 127, 128, 156, 212, 256, 326, 606, + 1026, 1306, 1376, 1432, 1712, 1880, 1888, 1896, 2064, 2344, 240, + 248, 0, 28, 196, 616, 1176, 1596, 1764, 1792, 1820, 2240, + 2660, 2688, 3024, 4144, 4480, 4508, 4928, 5348, 2400, 2568, 2904, + 3072, 3240, 3576, 5376, 5377, 5385, 5413, 5469, 5539, 5595, 5623, + 5631, 5632, 5912, 6472, 6528, 6696, 8376, 9216, 10056, 11736, 11904, + 11960, 12520, 12800, 13080, 14200, 15880, 17000, 17280, 17560, 18680, 20360, + 21480, 3744, 3772, 3828, 21760, 21768, 21936, 22216, 22272, 22328, 22608, + 22776, 22784, 22854, 23274, 23344, 24464, 25584, 26004, 28524, 28944, 30064, + 31184, 31254, 31674, 31744, 31800, 32136, 32976, 34096, 34936, 35272, 35328, + 35384, 35720, 36560, 37680, 38520, 38856, 38912, 39332, 40172, 40592, 41432, + 43112, 43952, 44372, 45212, 45632, 45968, 47088, 47424, 47480, 48320, 49160, + 49216, 49272, 50112, 50952, 51008, 51344, 52464, 3856, 3912, 3968, 4024, + 52800, 52856, 53024, 53192, 53248, 53528, 54368, 55208, 55488, 55768, 56608, + 57448, 57728, 58064, 58400, 58736, 59072, 59408, 59744, 60080, 60416, 60472, + 60752, 60920, 60928, 60936, 61104, 61384, 4080, 4088, 61440, 61468, 61524, + 61552, 61720, 62056, 62224, 62392, 62728, 62896, 62952, 63008, 63064, 63120, + 63128, 63296, 63576, 63632, 63688, 63968, 64136, 64144, 64200, 64256, 64312, + 64368, 64396, 64452, 64480, 64536, 64592, 64648, 64704, 64712, 64720, 64776, + 64832, 64888, 64944, 64972, 65028, 65056, 65112, 65168, 65224, 65280, 65336, + 65392, 65448, 65504, 65512, 65520, 65528}; + +/* A3 - Number of the absolute leaders in codebooks Q2 and Q3 */ +const UCHAR fdk_dec_A3[NB_LDQ3] = {0, 1, 4, 2, 3, 7, 11, 17, 22}; + +/* A4 - Number of the absolute leaders in codebook Q4 */ +const UCHAR fdk_dec_A4[NB_LDQ4] = {5, 6, 8, 9, 10, 12, 13, 14, 15, 16, + 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36}; + +/* I3 - Cardinality offsets for absolute leaders in Q3 */ +const USHORT fdk_dec_I3[NB_LDQ3] = {0, 128, 240, 256, 1376, + 2400, 3744, 3856, 4080}; + +/* I4 - Cardinality offset for absolute leaders in Q4 */ +const USHORT fdk_dec_I4[NB_LDQ4] = { + 0, 1792, 5376, 5632, 12800, 21760, 22784, 31744, 38912, 45632, + 52800, 53248, 57728, 60416, 61440, 61552, 62896, 63120, 64144, 64368, + 64480, 64704, 64720, 64944, 65056, 65280, 65504, 65520}; + +/* Initial ISF memory for concealment case */ +#define LSFI(x) ((x) << (FRACT_BITS - LSF_SCALE - 1)) + +const FIXP_LPC fdk_dec_lsf_init[16] = {1506, 3012, 4518, 6024, 7529, 9035, + 10541, 12047, 13553, 15059, 16565, 18071, + 19576, 21082, 22588, 24094}; + +/* dico_lsf_abs_8b is scaled by 1/(1<<13) */ +#define DICO(x) FX_DBL2FXCONST_LPC(x >> (LSF_SCALE - 13)) + +const FIXP_LPC fdk_dec_dico_lsf_abs_8b[] = { + DICO(0x05e57fe8), DICO(0x0ac00810), DICO(0x11ed8500), DICO(0x16d42ce0), + DICO(0x1beb1e20), DICO(0x217eaf40), DICO(0x2768c740), DICO(0x2d26f600), + DICO(0x32fe68c0), DICO(0x38b1d980), DICO(0x3e95bd80), DICO(0x446dab00), + DICO(0x4abfd280), DICO(0x5094b380), DICO(0x56ccb800), DICO(0x5c9aba00), + DICO(0x09660ca0), DICO(0x10ab4c00), DICO(0x15a16f20), DICO(0x19d3c780), + DICO(0x1ee99060), DICO(0x241d1200), DICO(0x29c83700), DICO(0x2f098f00), + DICO(0x34803fc0), DICO(0x3a37bc00), DICO(0x3ff55580), DICO(0x45da9280), + DICO(0x4bec6700), DICO(0x5169e300), DICO(0x57797c80), DICO(0x5d09ae80), + DICO(0x08a203b0), DICO(0x0d6ed1a0), DICO(0x152ccf20), DICO(0x19639dc0), + DICO(0x1d7e3e60), DICO(0x21f4a7c0), DICO(0x27b2f8c0), DICO(0x2dbb4480), + DICO(0x33ecde80), DICO(0x3982e100), DICO(0x3ea16100), DICO(0x43ab6080), + DICO(0x49534a80), DICO(0x4ea7e100), DICO(0x550d6300), DICO(0x5bcdcc80), + DICO(0x072dd048), DICO(0x0c654690), DICO(0x1436e940), DICO(0x19459680), + DICO(0x1e0041c0), DICO(0x2240dc80), DICO(0x26de4040), DICO(0x2b509b00), + DICO(0x309d8780), DICO(0x36151180), DICO(0x3c6c1200), DICO(0x42df6b80), + DICO(0x4a144400), DICO(0x50541280), DICO(0x56c34b80), DICO(0x5cb6c600), + DICO(0x051fef00), DICO(0x06b9fb48), DICO(0x0b4f9cc0), DICO(0x17e27800), + DICO(0x1b8c7340), DICO(0x1f772ca0), DICO(0x2478dc80), DICO(0x28242240), + DICO(0x2f27c640), DICO(0x33b03e80), DICO(0x381f20c0), DICO(0x3c662c00), + DICO(0x49565080), DICO(0x529b0f00), DICO(0x583ed080), DICO(0x5d8cec00), + DICO(0x071c4d18), DICO(0x097853b0), DICO(0x0f0f0690), DICO(0x157bf980), + DICO(0x1801f580), DICO(0x1deb0c20), DICO(0x2523da40), DICO(0x28534600), + DICO(0x2eb499c0), DICO(0x32eb5ac0), DICO(0x36749580), DICO(0x3a748200), + DICO(0x4325f700), DICO(0x515d8300), DICO(0x58a18700), DICO(0x5d722100), + DICO(0x06cbcd88), DICO(0x08bb6740), DICO(0x0dead310), DICO(0x152f0cc0), + DICO(0x18427640), DICO(0x1d9f2f20), DICO(0x22ba3b40), DICO(0x271a6e80), + DICO(0x2c677ec0), DICO(0x31061b00), DICO(0x349eef40), DICO(0x3c531b80), + DICO(0x4aed0580), DICO(0x4f8bbf80), DICO(0x54b74980), DICO(0x5bc9b700), + DICO(0x046410c8), DICO(0x06522ab0), DICO(0x0b6528c0), DICO(0x0f94bd90), + DICO(0x1a8f8b80), DICO(0x1ea57820), DICO(0x233ee180), DICO(0x27b3acc0), + DICO(0x2bd1d240), DICO(0x2fc4bcc0), DICO(0x3a98ea40), DICO(0x43d3f500), + DICO(0x49b37580), DICO(0x4e2afd00), DICO(0x55953300), DICO(0x5d36f600), + DICO(0x05d0f6c8), DICO(0x07e56d90), DICO(0x0be98080), DICO(0x0f956f30), + DICO(0x1259b3c0), DICO(0x1f08b240), DICO(0x25008c00), DICO(0x2900b180), + DICO(0x31ea6f00), DICO(0x352d1e00), DICO(0x3c970c80), DICO(0x45271200), + DICO(0x4b632280), DICO(0x5098a480), DICO(0x5672fc80), DICO(0x5c163180), + DICO(0x05bd81a0), DICO(0x07d4b8f0), DICO(0x0ce224b0), DICO(0x110abe20), + DICO(0x13dfeac0), DICO(0x17dedae0), DICO(0x2535c0c0), DICO(0x2a19da80), + DICO(0x2e5224c0), DICO(0x38ddeec0), DICO(0x3da99d80), DICO(0x42799100), + DICO(0x48973b00), DICO(0x4ea62880), DICO(0x53f77e80), DICO(0x5bd9c100), + DICO(0x0395cd50), DICO(0x058244b8), DICO(0x0af45520), DICO(0x1329cea0), + DICO(0x1a3970c0), DICO(0x1d9f2e00), DICO(0x21704400), DICO(0x277a34c0), + DICO(0x30215b40), DICO(0x33875040), DICO(0x3c159840), DICO(0x452fea00), + DICO(0x4981d200), DICO(0x4e15a980), DICO(0x54e84780), DICO(0x5c79ea00), + DICO(0x05413b98), DICO(0x08132a80), DICO(0x0dc7f050), DICO(0x13e25460), + DICO(0x1784bf80), DICO(0x1d630200), DICO(0x238bc880), DICO(0x28cc0880), + DICO(0x30da1a40), DICO(0x391e2200), DICO(0x415d8d00), DICO(0x48f13280), + DICO(0x4e300300), DICO(0x52e56580), DICO(0x5849fe80), DICO(0x5cdef400), + DICO(0x04a058c8), DICO(0x07569b88), DICO(0x0ef26610), DICO(0x13208140), + DICO(0x168c0500), DICO(0x1afec080), DICO(0x22a0abc0), DICO(0x2a057880), + DICO(0x2fd1c840), DICO(0x3703c680), DICO(0x3d326b80), DICO(0x43df2e80), + DICO(0x4a6f9000), DICO(0x50900d80), DICO(0x56c73f00), DICO(0x5cc3da80), + DICO(0x065c99e8), DICO(0x09060c50), DICO(0x0d1ef1c0), DICO(0x16bd9020), + DICO(0x1a04dae0), DICO(0x1e3c0580), DICO(0x25783700), DICO(0x29710ac0), + DICO(0x309cbb80), DICO(0x36c66280), DICO(0x3adb0580), DICO(0x41b37e00), + DICO(0x496ca700), DICO(0x4dab7600), DICO(0x52be6280), DICO(0x58fec480), + DICO(0x04640880), DICO(0x05a75ab8), DICO(0x0edba410), DICO(0x16e076a0), + DICO(0x198acec0), DICO(0x1eb5fae0), DICO(0x228c9000), DICO(0x29986c00), + DICO(0x2c780c80), DICO(0x38078dc0), DICO(0x3f42dc00), DICO(0x441ba900), + DICO(0x492f8080), DICO(0x4ed85d00), DICO(0x54605800), DICO(0x5d106a80), + DICO(0x045cb970), DICO(0x0627a828), DICO(0x0db35290), DICO(0x1778f780), + DICO(0x1a243c60), DICO(0x23c2dd40), DICO(0x27c57840), DICO(0x2f53cd80), + DICO(0x36f65600), DICO(0x3bc1b2c0), DICO(0x40c36500), DICO(0x46074180), + DICO(0x4b551b80), DICO(0x50a99700), DICO(0x569b6c80), DICO(0x5ca25780), + DICO(0x05ef2828), DICO(0x07d3adf8), DICO(0x0b5416d0), DICO(0x0f9adb70), + DICO(0x126e7360), DICO(0x1baff460), DICO(0x2b5decc0), DICO(0x31036200), + DICO(0x34ca7500), DICO(0x39681340), DICO(0x3da97100), DICO(0x4161ee00), + DICO(0x46a62e80), DICO(0x4d1b9380), DICO(0x530e0300), DICO(0x59ff0480), + DICO(0x04f5bc50), DICO(0x06e90d18), DICO(0x0c2af480), DICO(0x123f7400), + DICO(0x1530a160), DICO(0x18aa3dc0), DICO(0x1cc0a240), DICO(0x2cdb02c0), + DICO(0x32909a00), DICO(0x36bae640), DICO(0x3c917a80), DICO(0x40121900), + DICO(0x48a90d80), DICO(0x51ccc180), DICO(0x5884ea00), DICO(0x5dbc4280), + DICO(0x05791410), DICO(0x07b0dd80), DICO(0x0bec4190), DICO(0x13c30520), + DICO(0x17ac1900), DICO(0x1b6f1d00), DICO(0x26e54f40), DICO(0x2d4a8040), + DICO(0x311c6840), DICO(0x38ec4180), DICO(0x3f0c4340), DICO(0x427c5b00), + DICO(0x4886e480), DICO(0x504a0b00), DICO(0x56d48700), DICO(0x5c80f600), + DICO(0x04b58880), DICO(0x0743f0d8), DICO(0x0be95e20), DICO(0x0fd0d9b0), + DICO(0x1c2e11a0), DICO(0x2241af80), DICO(0x296e83c0), DICO(0x2f16adc0), + DICO(0x32cd6fc0), DICO(0x374ddec0), DICO(0x3da95f80), DICO(0x45d56c80), + DICO(0x4c6afa80), DICO(0x5141f380), DICO(0x5616b380), DICO(0x5c58f580), + DICO(0x03f4b368), DICO(0x05939890), DICO(0x09d95480), DICO(0x122cac60), + DICO(0x17e27e00), DICO(0x1f9dc680), DICO(0x26e26680), DICO(0x2ae64040), + DICO(0x2dd6cf40), DICO(0x3295c400), DICO(0x3e23b400), DICO(0x44fd0380), + DICO(0x4ad7a700), DICO(0x51295e80), DICO(0x594a9400), DICO(0x5e41aa00), + DICO(0x0424b9d8), DICO(0x05b30508), DICO(0x09380f20), DICO(0x0c9509c0), + DICO(0x18730860), DICO(0x219a9d40), DICO(0x24f699c0), DICO(0x289b2680), + DICO(0x2cb62240), DICO(0x36e88180), DICO(0x3e968800), DICO(0x48053c80), + DICO(0x4d6dca80), DICO(0x51d9a580), DICO(0x563e5a80), DICO(0x5c0b2b80), + DICO(0x03456ae8), DICO(0x04e49948), DICO(0x07dd0e88), DICO(0x0ed5cd30), + DICO(0x1b06e980), DICO(0x1de2b9c0), DICO(0x21160540), DICO(0x270a8240), + DICO(0x3352a280), DICO(0x3b8b6c00), DICO(0x40241400), DICO(0x43f60f80), + DICO(0x4a897900), DICO(0x51692a00), DICO(0x57449d00), DICO(0x5d497480), + DICO(0x04b94290), DICO(0x067e99d0), DICO(0x0ab06840), DICO(0x0e697070), + DICO(0x1745c460), DICO(0x22ee8040), DICO(0x2647e8c0), DICO(0x2bc2c680), + DICO(0x2fd57d00), DICO(0x37186680), DICO(0x3d074500), DICO(0x412b2800), + DICO(0x4579af00), DICO(0x4caff980), DICO(0x557add00), DICO(0x5c6ae780), + DICO(0x0423a090), DICO(0x05b9bca0), DICO(0x091b45d0), DICO(0x0c5b6d60), + DICO(0x194dd1c0), DICO(0x1fc85020), DICO(0x2486b080), DICO(0x2920af80), + DICO(0x2dd4f140), DICO(0x3598be40), DICO(0x3b9c1440), DICO(0x42d19280), + DICO(0x4a314280), DICO(0x50b00a00), DICO(0x56c55400), DICO(0x5d5ba300), + DICO(0x03e68b28), DICO(0x05a7b190), DICO(0x0917f000), DICO(0x0d247050), + DICO(0x19e637a0), DICO(0x2221a540), DICO(0x2777e540), DICO(0x2c103380), + DICO(0x30c2e040), DICO(0x389f1240), DICO(0x3f4a2c80), DICO(0x454a4c00), + DICO(0x4b0ab680), DICO(0x50cf6000), DICO(0x571c0700), DICO(0x5d2ef600), + DICO(0x04886f18), DICO(0x065103e8), DICO(0x0a607d40), DICO(0x0db91960), + DICO(0x13546f20), DICO(0x22f5e200), DICO(0x27064240), DICO(0x2e371d40), + DICO(0x33659240), DICO(0x38aa1c40), DICO(0x417bb280), DICO(0x47ca9480), + DICO(0x4dd6fb80), DICO(0x528e3480), DICO(0x57c49d80), DICO(0x5cc98100), + DICO(0x02db2370), DICO(0x04398848), DICO(0x07a8da38), DICO(0x10b90280), + DICO(0x1a2a4a20), DICO(0x20b1f640), DICO(0x277096c0), DICO(0x2dc568c0), + DICO(0x341b33c0), DICO(0x3a000640), DICO(0x40152880), DICO(0x45eeee00), + DICO(0x4c08c480), DICO(0x51bf0600), DICO(0x5799a180), DICO(0x5d23db80), + DICO(0x047b1498), DICO(0x06089848), DICO(0x0905af20), DICO(0x0bf13c20), + DICO(0x11fcf620), DICO(0x1f79cd00), DICO(0x257f6b40), DICO(0x2cfc2600), + DICO(0x31610040), DICO(0x35ea8280), DICO(0x3c774bc0), DICO(0x44417280), + DICO(0x4b432500), DICO(0x510e9480), DICO(0x56f2e480), DICO(0x5d282780), + DICO(0x02cfd0b0), DICO(0x042845d8), DICO(0x0a1fa610), DICO(0x15911fc0), + DICO(0x1bc07f00), DICO(0x2281d640), DICO(0x287abcc0), DICO(0x2ec6b400), + DICO(0x34a0d040), DICO(0x3aa4dcc0), DICO(0x4074d980), DICO(0x46726b80), + DICO(0x4c3bf900), DICO(0x52055100), DICO(0x57b20500), DICO(0x5d34da80), + DICO(0x04d4f768), DICO(0x06cad828), DICO(0x0b52a540), DICO(0x0ea224e0), + DICO(0x13c3f460), DICO(0x23808900), DICO(0x27d1cec0), DICO(0x2d6051c0), + DICO(0x33c5ff00), DICO(0x37ef2440), DICO(0x3d2a5300), DICO(0x43266000), + DICO(0x4a53a100), DICO(0x50acce80), DICO(0x57612100), DICO(0x5cdee380), + DICO(0x04039a88), DICO(0x0626dcb0), DICO(0x0c059620), DICO(0x12c3db20), + DICO(0x1bb9eb40), DICO(0x240fda00), DICO(0x2baab840), DICO(0x3177c5c0), + DICO(0x36cf2e40), DICO(0x3c025100), DICO(0x40bb8d00), DICO(0x45960800), + DICO(0x4adaca00), DICO(0x505a7300), DICO(0x566a6400), DICO(0x5c8ce000), + DICO(0x062891e8), DICO(0x09680810), DICO(0x0e9a11b0), DICO(0x1523e320), + DICO(0x1c57db00), DICO(0x21f22c80), DICO(0x28aeeb00), DICO(0x2e4fd600), + DICO(0x341cf000), DICO(0x3a5034c0), DICO(0x40600f80), DICO(0x461fde00), + DICO(0x4c368480), DICO(0x51dbbc00), DICO(0x57709780), DICO(0x5cce9880), + DICO(0x05d41f70), DICO(0x0a65bb30), DICO(0x132ddfa0), DICO(0x17d26820), + DICO(0x1e6d8380), DICO(0x24e68dc0), DICO(0x2b68c4c0), DICO(0x30fa2880), + DICO(0x361998c0), DICO(0x3aa1d640), DICO(0x3f942400), DICO(0x44d11680), + DICO(0x4ab8e580), DICO(0x50643b80), DICO(0x5697fe00), DICO(0x5cb3a780), + DICO(0x0707fa10), DICO(0x0cb8beb0), DICO(0x15011d20), DICO(0x1a4ad300), + DICO(0x20997080), DICO(0x26dbe240), DICO(0x2d907880), DICO(0x3307a3c0), + DICO(0x38819740), DICO(0x3d3e89c0), DICO(0x41ea2300), DICO(0x469ce200), + DICO(0x4be61680), DICO(0x51261b80), DICO(0x5716ef80), DICO(0x5cba2900), + DICO(0x084dc830), DICO(0x0f16f610), DICO(0x16ca2420), DICO(0x1bb58380), + DICO(0x22f00f00), DICO(0x296ba4c0), DICO(0x306d2600), DICO(0x362ca080), + DICO(0x3b86d280), DICO(0x3ffa96c0), DICO(0x446a5300), DICO(0x48d0fd00), + DICO(0x4d8a0800), DICO(0x525bf200), DICO(0x57f5aa00), DICO(0x5d569480), + DICO(0x08d664f0), DICO(0x110c8520), DICO(0x1865fa40), DICO(0x1efe3160), + DICO(0x26f38740), DICO(0x2d4608c0), DICO(0x32862500), DICO(0x374f8840), + DICO(0x3bfa9900), DICO(0x3ff5c8c0), DICO(0x4450c500), DICO(0x4918e680), + DICO(0x4e1d0f00), DICO(0x53342600), DICO(0x58a38e00), DICO(0x5dbbff00), + DICO(0x09143fd0), DICO(0x0f401c30), DICO(0x169c1ee0), DICO(0x1bcfb280), + DICO(0x2190dd00), DICO(0x27bf56c0), DICO(0x2e8e0640), DICO(0x34b67080), + DICO(0x3b534dc0), DICO(0x41134c00), DICO(0x467a3280), DICO(0x4bd63600), + DICO(0x50de8700), DICO(0x55657580), DICO(0x5a0cef00), DICO(0x5e8aa200), + DICO(0x06b5d860), DICO(0x0c8a5000), DICO(0x13343620), DICO(0x17a2abe0), + DICO(0x1caf7340), DICO(0x22a3f740), DICO(0x29059980), DICO(0x2ecff880), + DICO(0x34ce0f00), DICO(0x3ad32280), DICO(0x40f08d80), DICO(0x46d1d400), + DICO(0x4ca9df00), DICO(0x523b9580), DICO(0x57ea9b80), DICO(0x5d4a9a00), + DICO(0x03822fec), DICO(0x0522c670), DICO(0x099f89a0), DICO(0x12ddc9c0), + DICO(0x17c3d380), DICO(0x1d27ec20), DICO(0x2219e480), DICO(0x25fdf580), + DICO(0x329d6500), DICO(0x368ba040), DICO(0x3afedb00), DICO(0x430db980), + DICO(0x4a105380), DICO(0x51205080), DICO(0x5673b880), DICO(0x5ca2e500), + DICO(0x04e07408), DICO(0x06a13dc0), DICO(0x0b31c780), DICO(0x0e67fcd0), + DICO(0x13723240), DICO(0x1f87a840), DICO(0x2321ab00), DICO(0x2c604680), + DICO(0x310bc180), DICO(0x351eea40), DICO(0x3a2d6440), DICO(0x3e7ebac0), + DICO(0x4798ef80), DICO(0x50721100), DICO(0x57ff9880), DICO(0x5dc2e080), + DICO(0x05d626b8), DICO(0x07eaf140), DICO(0x0c5675b0), DICO(0x0eba7b00), + DICO(0x1a7f36c0), DICO(0x1f969200), DICO(0x244d8c00), DICO(0x29666440), + DICO(0x2c94b100), DICO(0x31865380), DICO(0x3713c000), DICO(0x3c228f40), + DICO(0x4296ed80), DICO(0x4dcbde00), DICO(0x56059a00), DICO(0x5c932d00), + DICO(0x07dceb20), DICO(0x0b533fe0), DICO(0x0eb18880), DICO(0x13124220), + DICO(0x167f74e0), DICO(0x1afbee40), DICO(0x229e2f80), DICO(0x26b05ec0), + DICO(0x2c7b4040), DICO(0x32806140), DICO(0x38da6540), DICO(0x3e495540), + DICO(0x444d3880), DICO(0x4e784400), DICO(0x5865f580), DICO(0x5e616180), + DICO(0x06395790), DICO(0x084b8f20), DICO(0x0d0e26a0), DICO(0x10897ac0), + DICO(0x14bcd080), DICO(0x1c5babe0), DICO(0x2108f9c0), DICO(0x274f8e80), + DICO(0x2b0ba180), DICO(0x305b8480), DICO(0x383ad300), DICO(0x3e34f440), + DICO(0x47f7aa00), DICO(0x4fdb5880), DICO(0x56b8c280), DICO(0x5d07d700), + DICO(0x051f0880), DICO(0x071b8fa8), DICO(0x0ce79c90), DICO(0x1005bd60), + DICO(0x14a4a080), DICO(0x183def40), DICO(0x1ee8d0a0), DICO(0x2c5b9bc0), + DICO(0x309f9dc0), DICO(0x35659380), DICO(0x3c0439c0), DICO(0x49603800), + DICO(0x5018a800), DICO(0x54862380), DICO(0x593edd80), DICO(0x5d415b80), + DICO(0x051c8108), DICO(0x06bd97d8), DICO(0x0b47d030), DICO(0x0d9c81a0), + DICO(0x178f0be0), DICO(0x1cdf7c80), DICO(0x2183db40), DICO(0x26ec7180), + DICO(0x2a3856c0), DICO(0x366c9b40), DICO(0x3d3611c0), DICO(0x42788100), + DICO(0x4981f200), DICO(0x4dd68380), DICO(0x55286a00), DICO(0x5cc72500), + DICO(0x06ee58c8), DICO(0x098b1310), DICO(0x0ccbd880), DICO(0x0f9d68f0), + DICO(0x1277ac40), DICO(0x1d71faa0), DICO(0x230d9480), DICO(0x276b8c00), + DICO(0x2ec77000), DICO(0x31f2a700), DICO(0x3bee0200), DICO(0x42250700), + DICO(0x466b7100), DICO(0x4de41980), DICO(0x56a08d80), DICO(0x5d700880), + DICO(0x062f1d80), DICO(0x091bcd30), DICO(0x0cd875e0), DICO(0x0fd42e60), + DICO(0x1322b980), DICO(0x1f11b480), DICO(0x2651e5c0), DICO(0x29f9b480), + DICO(0x2e238840), DICO(0x30fc58c0), DICO(0x37aa3040), DICO(0x3e9ac580), + DICO(0x44c6fd00), DICO(0x4eba4300), DICO(0x56fdad00), DICO(0x5d885700), + DICO(0x04213a78), DICO(0x05d028c0), DICO(0x09a1f9e0), DICO(0x0d28ae90), + DICO(0x151819a0), DICO(0x1c78c860), DICO(0x21d78f00), DICO(0x29992cc0), + DICO(0x2fbdc180), DICO(0x36bab700), DICO(0x3d4db1c0), DICO(0x4402a280), + DICO(0x4a920700), DICO(0x50988600), DICO(0x5717c100), DICO(0x5d52c200), + DICO(0x036af4bc), DICO(0x0514cf40), DICO(0x09ec2d30), DICO(0x113de160), + DICO(0x1991b700), DICO(0x20590bc0), DICO(0x23892a00), DICO(0x2654cd00), + DICO(0x2ff5c0c0), DICO(0x387ed380), DICO(0x3e305300), DICO(0x46137700), + DICO(0x4bc29100), DICO(0x4f96dd80), DICO(0x564aca00), DICO(0x5c4d9e80), + DICO(0x041051a0), DICO(0x0734dad8), DICO(0x1064e780), DICO(0x14d8bf00), + DICO(0x19727e40), DICO(0x1f7bede0), DICO(0x25b5ebc0), DICO(0x2c71fd40), + DICO(0x32813740), DICO(0x39340c80), DICO(0x3f974f40), DICO(0x45ca1580), + DICO(0x4be69f00), DICO(0x51c9c900), DICO(0x57a1ce80), DICO(0x5d0b2b00), + DICO(0x04b73008), DICO(0x06598b60), DICO(0x0b0aee00), DICO(0x15ac7ba0), + DICO(0x18b5e340), DICO(0x1f5308c0), DICO(0x23cfc4c0), DICO(0x27d3fdc0), + DICO(0x30138080), DICO(0x343c85c0), DICO(0x389cb540), DICO(0x42def900), + DICO(0x4aa6a000), DICO(0x4f719580), DICO(0x5585d080), DICO(0x5bc03f00), + DICO(0x05601b88), DICO(0x07616b88), DICO(0x0c22ba40), DICO(0x16bc8200), + DICO(0x192ebf80), DICO(0x1f71c120), DICO(0x25c59d00), DICO(0x28f76d00), + DICO(0x33dbdd80), DICO(0x39f40d80), DICO(0x3da0c880), DICO(0x432c1e00), + DICO(0x4aa19d80), DICO(0x51006f80), DICO(0x56a62e80), DICO(0x5c67d000), + DICO(0x053095d0), DICO(0x06c43fc8), DICO(0x0f80a460), DICO(0x139b4960), + DICO(0x1769ed80), DICO(0x1c828b00), DICO(0x21195980), DICO(0x26329800), + DICO(0x29f35900), DICO(0x2dc9df80), DICO(0x3795f0c0), DICO(0x43139b00), + DICO(0x4acae680), DICO(0x5048de00), DICO(0x57c11880), DICO(0x5db35900), + DICO(0x0466e180), DICO(0x05d31550), DICO(0x10cad200), DICO(0x168c2be0), + DICO(0x1a5e9580), DICO(0x1ef2d480), DICO(0x238db240), DICO(0x2920ce80), + DICO(0x2c80b4c0), DICO(0x30bb2700), DICO(0x38b257c0), DICO(0x46abd580), + DICO(0x4c30dd80), DICO(0x50e51880), DICO(0x5782ab80), DICO(0x5d23da80), + DICO(0x06700f78), DICO(0x085ec0a0), DICO(0x0c037280), DICO(0x16d90a60), + DICO(0x1bf46c00), DICO(0x1e6f4740), DICO(0x22c2c180), DICO(0x263fa2c0), + DICO(0x2c4a74c0), DICO(0x3642b040), DICO(0x3a476900), DICO(0x3ea12840), + DICO(0x46b6e880), DICO(0x4b5bad80), DICO(0x5152a500), DICO(0x5c1c6080), + DICO(0x041f8108), DICO(0x05ef1d98), DICO(0x0ce43300), DICO(0x11647cc0), + DICO(0x16e77fe0), DICO(0x1cdafc40), DICO(0x218832c0), DICO(0x26dd1b40), + DICO(0x2c776100), DICO(0x34f1eb80), DICO(0x3caf6100), DICO(0x45630a80), + DICO(0x4c0c5380), DICO(0x517ae980), DICO(0x567f4280), DICO(0x5c4bf900), + DICO(0x06673f18), DICO(0x091ee510), DICO(0x0d6ccb10), DICO(0x12503240), + DICO(0x158696e0), DICO(0x1f035420), DICO(0x24e6eac0), DICO(0x2a03bf40), + DICO(0x329aa000), DICO(0x375aafc0), DICO(0x3da133c0), DICO(0x45645600), + DICO(0x4c447c00), DICO(0x51a26b00), DICO(0x57917c00), DICO(0x5c557680), + DICO(0x04f84c18), DICO(0x06db4c30), DICO(0x0d53a940), DICO(0x1095cd20), + DICO(0x142b0b20), DICO(0x184229c0), DICO(0x20147280), DICO(0x25152740), + DICO(0x2db89fc0), DICO(0x35f3d200), DICO(0x400aa680), DICO(0x47a51c00), + DICO(0x4d9c5c00), DICO(0x525d1680), DICO(0x5832af00), DICO(0x5d27d580), + DICO(0x05c973d0), DICO(0x07c25810), DICO(0x0e928e50), DICO(0x12f5ad00), + DICO(0x16b2a800), DICO(0x1c2c9ce0), DICO(0x20b0f100), DICO(0x28be1940), + DICO(0x2d0f3c00), DICO(0x30a06f40), DICO(0x399e4340), DICO(0x46b48280), + DICO(0x4bbbc300), DICO(0x50283700), DICO(0x54a1a800), DICO(0x5ab20c80), + DICO(0x03df9390), DICO(0x055ff1e0), DICO(0x0bbeb640), DICO(0x17d906c0), + DICO(0x1ac20140), DICO(0x1fd84440), DICO(0x24502600), DICO(0x2a9fe640), + DICO(0x2ef79700), DICO(0x34cbed40), DICO(0x3c48cd00), DICO(0x43ccce80), + DICO(0x49b1d500), DICO(0x50145e00), DICO(0x56f16f80), DICO(0x5d46dd80), + DICO(0x04a69ef0), DICO(0x06470480), DICO(0x0defbd00), DICO(0x1590e900), + DICO(0x18114000), DICO(0x1bda6c60), DICO(0x1f64d160), DICO(0x28d8d640), + DICO(0x2d4e2880), DICO(0x34cfe380), DICO(0x3b7077c0), DICO(0x42f36a80), + DICO(0x49615580), DICO(0x4ff9d200), DICO(0x5657ef80), DICO(0x5cb91300), + DICO(0x038893dc), DICO(0x0535cdf0), DICO(0x0aabff80), DICO(0x146daaa0), + DICO(0x1848c700), DICO(0x1ce578c0), DICO(0x21116000), DICO(0x2b116d40), + DICO(0x32113500), DICO(0x3751a480), DICO(0x3e88c200), DICO(0x44cb1800), + DICO(0x4af1c200), DICO(0x5122b980), DICO(0x5782bc80), DICO(0x5d20be00), + DICO(0x03118434), DICO(0x04afe2e8), DICO(0x08f144f0), DICO(0x12c787c0), + DICO(0x1c32e4e0), DICO(0x1f701180), DICO(0x2362f740), DICO(0x2b995cc0), + DICO(0x3322c540), DICO(0x3951f200), DICO(0x3f7c2c80), DICO(0x4569c480), + DICO(0x4b2a6200), DICO(0x50905e80), DICO(0x56236680), DICO(0x5c32fa00), + DICO(0x0460c3b0), DICO(0x061e1378), DICO(0x0b07f610), DICO(0x166e0680), + DICO(0x18d0f020), DICO(0x21120340), DICO(0x24d4c000), DICO(0x29bafc00), + DICO(0x338c0740), DICO(0x36cfbc00), DICO(0x3f313900), DICO(0x47bf9c00), + DICO(0x4dd5d480), DICO(0x52848200), DICO(0x585add00), DICO(0x5cf7b480), + DICO(0x041a4bc8), DICO(0x05ca0920), DICO(0x0a3ae5b0), DICO(0x13fbb840), + DICO(0x1cdd3d00), DICO(0x209d5b80), DICO(0x27e78e80), DICO(0x2d1f4ec0), + DICO(0x32d84c80), DICO(0x3b8aa680), DICO(0x4289c180), DICO(0x46c33580), + DICO(0x4c23e580), DICO(0x51583180), DICO(0x56f52680), DICO(0x5c7a3d00), + DICO(0x03067404), DICO(0x05914038), DICO(0x10d33e60), DICO(0x17377180), + DICO(0x1d7f32a0), DICO(0x23848880), DICO(0x29d32200), DICO(0x2fb167c0), + DICO(0x356c8480), DICO(0x3b420280), DICO(0x4106d080), DICO(0x46d29280), + DICO(0x4c8a1200), DICO(0x52383300), DICO(0x57db8f80), DICO(0x5d61f200), + DICO(0x04baf368), DICO(0x06670a08), DICO(0x0e0cbd90), DICO(0x126299c0), + DICO(0x17ed7220), DICO(0x1e369900), DICO(0x22d7d300), DICO(0x2c0f9300), + DICO(0x2f5e7fc0), DICO(0x3b7c0d40), DICO(0x405aff80), DICO(0x44f2ef80), + DICO(0x4982b400), DICO(0x4e501380), DICO(0x539daa00), DICO(0x5c114b00), + DICO(0x0694c170), DICO(0x092d6890), DICO(0x0d0faee0), DICO(0x13800d00), + DICO(0x170f8d80), DICO(0x1bcd8240), DICO(0x246a8480), DICO(0x28bab640), + DICO(0x2f482ac0), DICO(0x36e736c0), DICO(0x3aaa68c0), DICO(0x3fc43500), + DICO(0x46e16000), DICO(0x4b3fbc00), DICO(0x4ff68e80), DICO(0x5aabf600), + DICO(0x05e849a0), DICO(0x0b485a80), DICO(0x14be52c0), DICO(0x1a079380), + DICO(0x1e8b1ce0), DICO(0x22fbca00), DICO(0x28c36a40), DICO(0x2e3b2a00), + DICO(0x34360b80), DICO(0x3a24cf00), DICO(0x3fff6200), DICO(0x45a6bf00), + DICO(0x4baf7800), DICO(0x51720e80), DICO(0x57560c80), DICO(0x5ce57e00), + DICO(0x0751da38), DICO(0x0f0949f0), DICO(0x18141860), DICO(0x1dfcb2c0), + DICO(0x24adbf00), DICO(0x296af240), DICO(0x2dbe60c0), DICO(0x3179ae40), + DICO(0x35ec4400), DICO(0x3ab76400), DICO(0x4034f400), DICO(0x45cfc700), + DICO(0x4bea6b00), DICO(0x516f5f00), DICO(0x57655300), DICO(0x5cfc0e00), + DICO(0x069900d0), DICO(0x0d379520), DICO(0x175d0560), DICO(0x1c4d92c0), + DICO(0x21407680), DICO(0x250d0340), DICO(0x29804940), DICO(0x2dfb9ac0), + DICO(0x337a1f80), DICO(0x39105fc0), DICO(0x3efd0380), DICO(0x44bce380), + DICO(0x4b07cc80), DICO(0x50ad7d00), DICO(0x56ddce80), DICO(0x5cb9a000), + DICO(0x069c6948), DICO(0x0a56ea10), DICO(0x0f7cca20), DICO(0x12d18680), + DICO(0x17036d00), DICO(0x1f4c1e80), DICO(0x262e5540), DICO(0x2b951e40), + DICO(0x3468ad40), DICO(0x3a2b2100), DICO(0x3f02f0c0), DICO(0x4383e400), + DICO(0x48374180), DICO(0x4d8eec80), DICO(0x54d74800), DICO(0x5c309600), + DICO(0x05a50158), DICO(0x0797e350), DICO(0x0cf1f230), DICO(0x14f3fb20), + DICO(0x17676400), DICO(0x20636780), DICO(0x2617ef80), DICO(0x29cbf700), + DICO(0x32ed57c0), DICO(0x374c3080), DICO(0x3b348e40), DICO(0x3fde0180), + DICO(0x44d38c00), DICO(0x4a8c6100), DICO(0x55f0e400), DICO(0x5dfed100), + DICO(0x04b74228), DICO(0x0623d3e0), DICO(0x0ab4c670), DICO(0x1bde7fa0), + DICO(0x1fcb6ac0), DICO(0x2344a540), DICO(0x275f7c40), DICO(0x2b7a8300), + DICO(0x31407440), DICO(0x35237700), DICO(0x38798540), DICO(0x3d0af340), + DICO(0x4224c980), DICO(0x49a17900), DICO(0x57702880), DICO(0x5dba4c00), + DICO(0x03c83c84), DICO(0x05cc52d8), DICO(0x0b644c10), DICO(0x129ab9a0), + DICO(0x1cee46c0), DICO(0x2152b080), DICO(0x247b1c00), DICO(0x27697180), + DICO(0x304f7500), DICO(0x3895d880), DICO(0x3c3a1740), DICO(0x413ace80), + DICO(0x462b0100), DICO(0x4ab07e00), DICO(0x50967580), DICO(0x5ba5e700), + DICO(0x06bcfda8), DICO(0x08c8b920), DICO(0x0de21530), DICO(0x1028d320), + DICO(0x168cfe00), DICO(0x20f78a40), DICO(0x248493c0), DICO(0x2c34bf80), + DICO(0x2ff88540), DICO(0x32d28c40), DICO(0x36d99640), DICO(0x4438e500), + DICO(0x4bacdb00), DICO(0x50343700), DICO(0x56b79080), DICO(0x5b694d00), + DICO(0x069109a0), DICO(0x0a73bc50), DICO(0x0e3c8330), DICO(0x13082620), + DICO(0x1c3a3760), DICO(0x200b5e80), DICO(0x256a4880), DICO(0x2b256ac0), + DICO(0x2f34afc0), DICO(0x35580200), DICO(0x3e0bd9c0), DICO(0x43d92900), + DICO(0x494e6e00), DICO(0x4f1a2780), DICO(0x5532a980), DICO(0x5a835a80), + DICO(0x04053450), DICO(0x05cb8fe0), DICO(0x097387b0), DICO(0x1121af00), + DICO(0x1abf62c0), DICO(0x1e39bbe0), DICO(0x243de300), DICO(0x2b440ec0), + DICO(0x2f2c1480), DICO(0x34697d80), DICO(0x405f8600), DICO(0x440b6f80), + DICO(0x47373100), DICO(0x4c764f80), DICO(0x55293780), DICO(0x5c59a780), + DICO(0x03c5b4a4), DICO(0x056fb380), DICO(0x09b8f910), DICO(0x13833fa0), + DICO(0x185eed60), DICO(0x1ce33d40), DICO(0x242e4100), DICO(0x282e5b80), + DICO(0x2cfe4d40), DICO(0x38a06d80), DICO(0x3e002240), DICO(0x423be400), + DICO(0x49a5e600), DICO(0x5092b780), DICO(0x57023d00), DICO(0x5d5f7c80), + DICO(0x077ada38), DICO(0x09d5ac70), DICO(0x0e58be30), DICO(0x14fb2040), + DICO(0x17fc9dc0), DICO(0x1c2c31e0), DICO(0x26cf1b00), DICO(0x2a91ba80), + DICO(0x2ed880c0), DICO(0x38cbf900), DICO(0x3d2fc700), DICO(0x405d2280), + DICO(0x439c1d00), DICO(0x4dd16800), DICO(0x5672c080), DICO(0x5d313880), + DICO(0x04272090), DICO(0x05d76e18), DICO(0x0b4d8080), DICO(0x12883f60), + DICO(0x17952180), DICO(0x2040d480), DICO(0x23e8cc00), DICO(0x2819c200), + DICO(0x2b871040), DICO(0x357c8f00), DICO(0x3caf9ac0), DICO(0x40a39380), + DICO(0x45bc2780), DICO(0x4e4aa300), DICO(0x568c2280), DICO(0x5cadc400), + DICO(0x0375b03c), DICO(0x056f0b40), DICO(0x0b0dc930), DICO(0x128c51e0), + DICO(0x189fa360), DICO(0x1c8197e0), DICO(0x1eed52a0), DICO(0x23ed4500), + DICO(0x2e5eb840), DICO(0x36415a40), DICO(0x3dcf6340), DICO(0x43126e80), + DICO(0x4aeb7f80), DICO(0x501e1280), DICO(0x5852b100), DICO(0x5d040d80), + DICO(0x06351b88), DICO(0x07f90ac0), DICO(0x0bab4ea0), DICO(0x18d04b40), + DICO(0x1f1e1480), DICO(0x219abcc0), DICO(0x261c31c0), DICO(0x2a611a00), + DICO(0x2e725480), DICO(0x36b511c0), DICO(0x3d362f00), DICO(0x40be6d80), + DICO(0x456dc400), DICO(0x4b74c580), DICO(0x55c82680), DICO(0x5e318480), + DICO(0x046212d8), DICO(0x05ca95e8), DICO(0x0a02d910), DICO(0x1ae58f40), + DICO(0x1e73ec20), DICO(0x2197d640), DICO(0x2581df00), DICO(0x29c83780), + DICO(0x31294300), DICO(0x356f8a40), DICO(0x3b97d240), DICO(0x4505cc80), + DICO(0x4b497600), DICO(0x504e8780), DICO(0x55644480), DICO(0x5bdedf80), + DICO(0x0514f798), DICO(0x06bd0d00), DICO(0x0fc31550), DICO(0x13dfb1a0), + DICO(0x17dda900), DICO(0x204a8c40), DICO(0x23095300), DICO(0x2d0da040), + DICO(0x31b2a540), DICO(0x34620180), DICO(0x3ab3e000), DICO(0x448ac300), + DICO(0x4be6a600), DICO(0x5114e280), DICO(0x562b0780), DICO(0x5b833c00), + DICO(0x070f5ef0), DICO(0x0919c2b0), DICO(0x0e778740), DICO(0x154db320), + DICO(0x177cfbe0), DICO(0x1ea66040), DICO(0x23666680), DICO(0x2839c400), + DICO(0x30cc4ec0), DICO(0x3444a280), DICO(0x38c93580), DICO(0x42a80e00), + DICO(0x4c433880), DICO(0x519e4f80), DICO(0x56ff8f80), DICO(0x5be18200), + DICO(0x066c5968), DICO(0x08a589f0), DICO(0x0ca4d7a0), DICO(0x0ffdefb0), + DICO(0x12943f40), DICO(0x1be84ee0), DICO(0x21276540), DICO(0x265a9540), + DICO(0x2e0de140), DICO(0x325148c0), DICO(0x3bd05d40), DICO(0x41e81780), + DICO(0x4b7cf400), DICO(0x53289400), DICO(0x597d9000), DICO(0x5e458e00), + DICO(0x04da3e40), DICO(0x06e8e1b0), DICO(0x0b9b1a20), DICO(0x11264bc0), + DICO(0x14f3d7e0), DICO(0x1cf9c100), DICO(0x23568f40), DICO(0x292b5380), + DICO(0x33878d40), DICO(0x38dac840), DICO(0x3d578200), DICO(0x4223a880), + DICO(0x473fb700), DICO(0x4c765500), DICO(0x546c6480), DICO(0x5c76d280), + DICO(0x05e63bb0), DICO(0x07a1a428), DICO(0x0ec4ff10), DICO(0x1348a100), + DICO(0x16204f40), DICO(0x1a0a6440), DICO(0x1e33f6c0), DICO(0x2ae8ccc0), + DICO(0x2ed5e6c0), DICO(0x32427600), DICO(0x379d9980), DICO(0x3c0f4080), + DICO(0x441ea680), DICO(0x4e592b00), DICO(0x56e27700), DICO(0x5da2e280), + DICO(0x0474de80), DICO(0x06167248), DICO(0x0ce650e0), DICO(0x135b4aa0), + DICO(0x16cea2a0), DICO(0x1d138ac0), DICO(0x220a84c0), DICO(0x275ca380), + DICO(0x2c300340), DICO(0x333b3d80), DICO(0x37a35080), DICO(0x40b83880), + DICO(0x494c4780), DICO(0x4ff71c80), DICO(0x56db2d80), DICO(0x5d0aac00), + DICO(0x0746cd00), DICO(0x09deff10), DICO(0x0e4a3560), DICO(0x14f005e0), + DICO(0x186a4de0), DICO(0x1cd0b240), DICO(0x22287bc0), DICO(0x26ced500), + DICO(0x2d57c440), DICO(0x31d943c0), DICO(0x364b0f80), DICO(0x3c85a040), + DICO(0x4240ca00), DICO(0x4a648080), DICO(0x54d12200), DICO(0x5d1a1c00), + DICO(0x05522eb0), DICO(0x0704efb8), DICO(0x0c66cd50), DICO(0x15aefca0), + DICO(0x184f7b00), DICO(0x1e4b26a0), DICO(0x22667640), DICO(0x284e4e00), + DICO(0x2d8be3c0), DICO(0x31376f00), DICO(0x39cd9800), DICO(0x3e46b740), + DICO(0x43af0380), DICO(0x4e1dec00), DICO(0x562ac500), DICO(0x5d45f580), + DICO(0x062f5708), DICO(0x08d079a0), DICO(0x0c1b4920), DICO(0x13f147c0), + DICO(0x1ae77c80), DICO(0x1d200ea0), DICO(0x236e4740), DICO(0x2b98d000), + DICO(0x2eefc600), DICO(0x34c674c0), DICO(0x3d36f540), DICO(0x411d8c00), + DICO(0x45c50300), DICO(0x4d207480), DICO(0x55603100), DICO(0x5c442d80), + DICO(0x0510bcd0), DICO(0x06ec00a0), DICO(0x0b639550), DICO(0x15daa2c0), + DICO(0x18c0ba60), DICO(0x1e0f7d60), DICO(0x24b05c80), DICO(0x280638c0), + DICO(0x314a6580), DICO(0x35e4b2c0), DICO(0x3aef2bc0), DICO(0x4158c280), + DICO(0x4d245100), DICO(0x53c69a80), DICO(0x597f1000), DICO(0x5dcb0080), + DICO(0x042cb748), DICO(0x05d710b0), DICO(0x0afe6130), DICO(0x1256cdc0), + DICO(0x15b8cd00), DICO(0x1dc72d20), DICO(0x2205fc00), DICO(0x2a3d0d00), + DICO(0x2f3ba600), DICO(0x33b3d840), DICO(0x3b5a5440), DICO(0x416c9d00), + DICO(0x497cdd80), DICO(0x50405e00), DICO(0x570ca980), DICO(0x5d3aa180), + DICO(0x0443b7b8), DICO(0x063d8588), DICO(0x0c76ef20), DICO(0x12709b40), + DICO(0x1649f0a0), DICO(0x20c522c0), DICO(0x24cde400), DICO(0x2ba78280), + DICO(0x3104c340), DICO(0x360b1740), DICO(0x3cd6a6c0), DICO(0x42573800), + DICO(0x48b18480), DICO(0x4fca1e00), DICO(0x5700c100), DICO(0x5cf14480), + DICO(0x05123628), DICO(0x06bf10b0), DICO(0x0bde7570), DICO(0x175b7ee0), + DICO(0x1a134460), DICO(0x20fa4100), DICO(0x25eda440), DICO(0x29c3b540), + DICO(0x318a1b40), DICO(0x35e0d500), DICO(0x3a147f00), DICO(0x3f08e980), + DICO(0x445d7580), DICO(0x4ec48c80), DICO(0x588bce80), DICO(0x5dfae300), + DICO(0x04c9e750), DICO(0x065224f8), DICO(0x0c6f1e30), DICO(0x1a2ffca0), + DICO(0x1cac6140), DICO(0x21c2a640), DICO(0x25fb8ac0), DICO(0x2ab90f00), + DICO(0x33189200), DICO(0x38088ac0), DICO(0x3bb7de40), DICO(0x40180800), + DICO(0x4453c300), DICO(0x4cdba880), DICO(0x54902680), DICO(0x5bb21700), + DICO(0x06958570), DICO(0x097f32b0), DICO(0x0cb418b0), DICO(0x141b6900), + DICO(0x1c8cfb00), DICO(0x1fab7920), DICO(0x2477c800), DICO(0x2aabed40), + DICO(0x2eb1a080), DICO(0x339f67c0), DICO(0x3abcc240), DICO(0x3f661b00), + DICO(0x45663280), DICO(0x4c680800), DICO(0x51703000), DICO(0x58a0e000), + DICO(0x069f6c88), DICO(0x095e1490), DICO(0x0cf442b0), DICO(0x10ea8d60), + DICO(0x1377b580), DICO(0x195ed480), DICO(0x26542b00), DICO(0x2c9ea700), + DICO(0x318d8ac0), DICO(0x364e5a40), DICO(0x3a0db000), DICO(0x3e1087c0), + DICO(0x450ca380), DICO(0x4c781d00), DICO(0x53cf7a00), DICO(0x5c7d1280), + DICO(0x06e51d98), DICO(0x09eb8d30), DICO(0x0e6683d0), DICO(0x129418a0), + DICO(0x1562fc80), DICO(0x1f708660), DICO(0x253f1000), DICO(0x293a16c0), + DICO(0x2e7c1d80), DICO(0x316e75c0), DICO(0x35a7fbc0), DICO(0x3bfbf780), + DICO(0x416a9200), DICO(0x4be36400), DICO(0x56dc7a80), DICO(0x5d64ea80), + DICO(0x0574d0c8), DICO(0x0748efd0), DICO(0x0b510860), DICO(0x0e219e00), + DICO(0x1299cc00), DICO(0x1ef706a0), DICO(0x22ca38c0), DICO(0x28820a00), + DICO(0x2cc635c0), DICO(0x31ef4740), DICO(0x3a5e89c0), DICO(0x42acaa00), + DICO(0x4b2bf500), DICO(0x515e0980), DICO(0x57949400), DICO(0x5d002500), + DICO(0x07c715d0), DICO(0x0b3fa110), DICO(0x0e745370), DICO(0x11e93560), + DICO(0x14bad680), DICO(0x189a0400), DICO(0x240b1240), DICO(0x2a6b3580), + DICO(0x2e5e1380), DICO(0x352072c0), DICO(0x3a5037c0), DICO(0x3e3726c0), + DICO(0x4725ed80), DICO(0x4f885900), DICO(0x54c8d580), DICO(0x5b261680), + DICO(0x075f02a8), DICO(0x0a214900), DICO(0x0e189de0), DICO(0x1376d5a0), + DICO(0x163d5c80), DICO(0x1a94b3e0), DICO(0x21376980), DICO(0x259c3140), + DICO(0x2e663bc0), DICO(0x337884c0), DICO(0x3a035c00), DICO(0x40b32c00), + DICO(0x4b21de00), DICO(0x53298f00), DICO(0x58788080), DICO(0x5cfa7c00), + DICO(0x05658988), DICO(0x0797f470), DICO(0x0d250810), DICO(0x102fc2a0), + DICO(0x13738fe0), DICO(0x1740bbc0), DICO(0x2491b380), DICO(0x28bc5800), + DICO(0x2c75a940), DICO(0x325cb500), DICO(0x37944740), DICO(0x405f2d80), + DICO(0x48eb8f00), DICO(0x50676f80), DICO(0x56f70380), DICO(0x5d62c000), + DICO(0x0531b540), DICO(0x06ae64c0), DICO(0x0cf7ad30), DICO(0x11c83000), + DICO(0x14edc980), DICO(0x18d436c0), DICO(0x1e184080), DICO(0x2603bb80), + DICO(0x2a2f2f80), DICO(0x33bdbe00), DICO(0x3a1066c0), DICO(0x42b9ff00), + DICO(0x4a617580), DICO(0x51619480), DICO(0x57ccd500), DICO(0x5d4d1600), + DICO(0x03e40bac), DICO(0x05f53158), DICO(0x0e76d3b0), DICO(0x17c157a0), + DICO(0x1ccb5bc0), DICO(0x250129c0), DICO(0x2b7d9d00), DICO(0x33224d80), + DICO(0x3966f600), DICO(0x3f399480), DICO(0x4449fc80), DICO(0x49401b80), + DICO(0x4e2ab580), DICO(0x53117000), DICO(0x5848e080), DICO(0x5d66a280), + DICO(0x041d4f60), DICO(0x070e8080), DICO(0x1390ec40), DICO(0x177c42c0), + DICO(0x1beb1400), DICO(0x208b0580), DICO(0x264cbb40), DICO(0x2bd30940), + DICO(0x30b30880), DICO(0x36978e80), DICO(0x3cb2a140), DICO(0x43f6b080), + DICO(0x4a881000), DICO(0x505ca780), DICO(0x569a5d80), DICO(0x5cae3580), + DICO(0x03f3c760), DICO(0x05564e08), DICO(0x09e310d0), DICO(0x1b9b3d00), + DICO(0x20909ac0), DICO(0x2382eec0), DICO(0x278c6700), DICO(0x2b34d500), + DICO(0x30fa2ac0), DICO(0x34d27d40), DICO(0x38e334c0), DICO(0x3d732440), + DICO(0x46d07800), DICO(0x51f4d400), DICO(0x57744f80), DICO(0x5d56bb80), + DICO(0x03abfdd8), DICO(0x0512b140), DICO(0x135f7500), DICO(0x19fcc4c0), + DICO(0x1d0b1b80), DICO(0x21eca540), DICO(0x258f8700), DICO(0x29e292c0), + DICO(0x2c51fe80), DICO(0x31e2a180), DICO(0x3c638640), DICO(0x44873a00), + DICO(0x4bb7e800), DICO(0x5078f700), DICO(0x57fc9b80), DICO(0x5def1c00), + DICO(0x04721ef0), DICO(0x06688158), DICO(0x0f65a5d0), DICO(0x14499840), + DICO(0x1bf5b8c0), DICO(0x1f33b700), DICO(0x264b6900), DICO(0x2c3e6780), + DICO(0x2ec8d440), DICO(0x323885c0), DICO(0x37143300), DICO(0x3bafa800), + DICO(0x49030480), DICO(0x54c16b00), DICO(0x58ec4b00), DICO(0x5d713d00), + DICO(0x03d114e4), DICO(0x067e5b40), DICO(0x10393420), DICO(0x14961300), + DICO(0x1a59cfa0), DICO(0x20854240), DICO(0x26b3f300), DICO(0x2e3e2840), + DICO(0x323bd300), DICO(0x37c49280), DICO(0x3d79e500), DICO(0x4352d880), + DICO(0x49e17980), DICO(0x4fc72f80), DICO(0x55c0c680), DICO(0x5c53c700), + DICO(0x053f5de8), DICO(0x075162b8), DICO(0x0fae8050), DICO(0x13ec0ee0), + DICO(0x17f92440), DICO(0x1f054440), DICO(0x24b15d40), DICO(0x2add4480), + DICO(0x2e306300), DICO(0x35420680), DICO(0x3c6b6e00), DICO(0x42fc0380), + DICO(0x4732e380), DICO(0x4ceb2200), DICO(0x522efe00), DICO(0x5aa12680), + DICO(0x06111728), DICO(0x08183c80), DICO(0x0d026650), DICO(0x14b41940), + DICO(0x17e37320), DICO(0x1c40b160), DICO(0x219c5400), DICO(0x26d88840), + DICO(0x2bfdfe00), DICO(0x315a2800), DICO(0x38cd7140), DICO(0x3de22740), + DICO(0x48ff1300), DICO(0x53ef4180), DICO(0x5a479380), DICO(0x5ea1e380), + DICO(0x07ea0fa8), DICO(0x0a844ef0), DICO(0x0e1023c0), DICO(0x1208d980), + DICO(0x15891360), DICO(0x1bebc380), DICO(0x2087da40), DICO(0x257ac940), + DICO(0x2caefa00), DICO(0x300defc0), DICO(0x376aa000), DICO(0x438aad80), + DICO(0x49f00500), DICO(0x4e023780), DICO(0x524e5800), DICO(0x5abcb980), + DICO(0x079cfc88), DICO(0x0a367240), DICO(0x0f224330), DICO(0x15b51540), + DICO(0x19065420), DICO(0x1ddbe0a0), DICO(0x23a99d80), DICO(0x28c2d340), + DICO(0x2f627e40), DICO(0x3487e080), DICO(0x38b76bc0), DICO(0x3d135580), + DICO(0x43799a80), DICO(0x489a5000), DICO(0x4ece6280), DICO(0x5a82f500), + DICO(0x06c37e40), DICO(0x093f0540), DICO(0x0e0d0c30), DICO(0x17487860), + DICO(0x1bf78020), DICO(0x20318000), DICO(0x260b8300), DICO(0x2c615980), + DICO(0x30c88440), DICO(0x36433b40), DICO(0x3bdb8c40), DICO(0x40050c80), + DICO(0x44062f80), DICO(0x48a8d480), DICO(0x4dd64d00), DICO(0x55abd380), + DICO(0x05e9e828), DICO(0x07f24330), DICO(0x0c8b4fe0), DICO(0x0ecd2820), + DICO(0x17f05c00), DICO(0x1fdb4560), DICO(0x24b4c940), DICO(0x2968d0c0), + DICO(0x2cbf3500), DICO(0x381eadc0), DICO(0x3d3baf40), DICO(0x42828080), + DICO(0x47f36300), DICO(0x4c8c6600), DICO(0x51d66f00), DICO(0x5a7e0300), + DICO(0x065c5cf8), DICO(0x08882540), DICO(0x0d887c70), DICO(0x112ac560), + DICO(0x150ccdc0), DICO(0x19e49c20), DICO(0x1eb65680), DICO(0x2a76e040), + DICO(0x2f65fc00), DICO(0x36d79cc0), DICO(0x3c85a900), DICO(0x408dc680), + DICO(0x44964700), DICO(0x4a98eb00), DICO(0x5528b500), DICO(0x5d660f80), + DICO(0x06b56230), DICO(0x08e340f0), DICO(0x0e1e4380), DICO(0x112d2d40), + DICO(0x158dfde0), DICO(0x227e6040), DICO(0x26bff7c0), DICO(0x2b73a100), + DICO(0x32199580), DICO(0x3585a240), DICO(0x398a5d40), DICO(0x3db8c6c0), + DICO(0x43905600), DICO(0x4945f800), DICO(0x4f310380), DICO(0x5a6d2400), + DICO(0x05cfc6f8), DICO(0x0832e650), DICO(0x0de82f80), DICO(0x1a1afe80), + DICO(0x1e9a1f80), DICO(0x221acd80), DICO(0x27fa00c0), DICO(0x2c4df980), + DICO(0x31e04bc0), DICO(0x38c9ed40), DICO(0x3db86080), DICO(0x428ec800), + DICO(0x48500500), DICO(0x4e1ca580), DICO(0x53d3f500), DICO(0x5aa6be00), + DICO(0x050cc4d0), DICO(0x070c2180), DICO(0x0c4ca980), DICO(0x0fce9f40), + DICO(0x14af4160), DICO(0x2206a780), DICO(0x25848e80), DICO(0x2c2b84c0), + DICO(0x35a39980), DICO(0x3914bd80), DICO(0x3caff580), DICO(0x3fcb0600), + DICO(0x4426b380), DICO(0x486c9700), DICO(0x4f730480), DICO(0x5afd3980), + DICO(0x05e40640), DICO(0x0830df50), DICO(0x0b9e83e0), DICO(0x158bacc0), + DICO(0x1d0692e0), DICO(0x2021e0c0), DICO(0x26572e00), DICO(0x2d58cc40), + DICO(0x30dd0f80), DICO(0x361d68c0), DICO(0x3e3086c0), DICO(0x42450800), + DICO(0x46c25800), DICO(0x4c45cf00), DICO(0x51dd4200), DICO(0x57326500), + DICO(0x04d32fa0), DICO(0x064ed2c0), DICO(0x0b07cd70), DICO(0x1c7f6da0), + DICO(0x213bc140), DICO(0x25051fc0), DICO(0x295cd1c0), DICO(0x2c9f4f80), + DICO(0x32271540), DICO(0x36a8ec80), DICO(0x3a8e6b40), DICO(0x3e137580), + DICO(0x42795480), DICO(0x4779b780), DICO(0x4f7d9600), DICO(0x5c09b000), + DICO(0x044b0748), DICO(0x05fee680), DICO(0x08f66960), DICO(0x11db5940), + DICO(0x219ede80), DICO(0x27fb96c0), DICO(0x2affc980), DICO(0x2eadc3c0), + DICO(0x32895700), DICO(0x37180d00), DICO(0x3d4bf880), DICO(0x41741980), + DICO(0x460d8280), DICO(0x4c34be80), DICO(0x54531e80), DICO(0x5c874000), + DICO(0x03e25dcc), DICO(0x069e8170), DICO(0x13b3d9c0), DICO(0x1a803260), + DICO(0x1ed3a4a0), DICO(0x23ea6380), DICO(0x2883b900), DICO(0x2e0ceac0), + DICO(0x3308e400), DICO(0x38796dc0), DICO(0x3e318e80), DICO(0x441da080), + DICO(0x4a892300), DICO(0x509b9f80), DICO(0x56caa380), DICO(0x5cc39e00), + DICO(0x05023038), DICO(0x06b6b4d8), DICO(0x0a449370), DICO(0x15b86ea0), + DICO(0x224a9200), DICO(0x272e6f40), DICO(0x2a617700), DICO(0x2e915d00), + DICO(0x3240ac40), DICO(0x37636300), DICO(0x3dd3ea80), DICO(0x420e1f80), + DICO(0x45bf0680), DICO(0x4a26d980), DICO(0x4f82a900), DICO(0x56576800), + DICO(0x03d630f4), DICO(0x082140a0), DICO(0x12644700), DICO(0x16b80cc0), + DICO(0x1ba90c40), DICO(0x21c38300), DICO(0x27dd1480), DICO(0x2e18ee00), + DICO(0x33fb72c0), DICO(0x39f9d980), DICO(0x40219300), DICO(0x4607fd00), + DICO(0x4c07e500), DICO(0x51ba8f00), DICO(0x57a24280), DICO(0x5d367700), + DICO(0x080a5880), DICO(0x0ef3f570), DICO(0x141fd6c0), DICO(0x17c163a0), + DICO(0x1c2840a0), DICO(0x2111fe00), DICO(0x27376bc0), DICO(0x2cc7edc0), + DICO(0x329b0100), DICO(0x386d3e40), DICO(0x3ec1bdc0), DICO(0x453f6200), + DICO(0x4bf16080), DICO(0x51bded00), DICO(0x57ba6800), DICO(0x5d2ffd80), + DICO(0x08643590), DICO(0x0e911f00), DICO(0x15911380), DICO(0x1ab5e180), + DICO(0x207ff600), DICO(0x26399b00), DICO(0x2cadae80), DICO(0x3276ca40), + DICO(0x389d9cc0), DICO(0x3eb22180), DICO(0x44570700), DICO(0x49d15800), + DICO(0x4f591300), DICO(0x54566a80), DICO(0x5967db00), DICO(0x5e307780), + DICO(0x07120fa8), DICO(0x0c791c60), DICO(0x112d3b60), DICO(0x149452a0), + DICO(0x19d2c100), DICO(0x202f1540), DICO(0x269c10c0), DICO(0x2be22880), + DICO(0x312a07c0), DICO(0x36984fc0), DICO(0x3c7ac3c0), DICO(0x435b5000), + DICO(0x4aa60280), DICO(0x50f50c00), DICO(0x5719f700), DICO(0x5cb98680), + DICO(0x05517c88), DICO(0x06ba0a70), DICO(0x0da167c0), DICO(0x19918440), + DICO(0x1bb37220), DICO(0x20681080), DICO(0x23dc6740), DICO(0x2a1403c0), + DICO(0x31a71580), DICO(0x34ff0600), DICO(0x395b7cc0), DICO(0x42019200), + DICO(0x4c818d00), DICO(0x513ff400), DICO(0x5731ce00), DICO(0x5c5f1180), + DICO(0x04f74ec0), DICO(0x067b4628), DICO(0x0dc4c9c0), DICO(0x19e9fa40), + DICO(0x1cf00a00), DICO(0x21602a80), DICO(0x25334a80), DICO(0x29b3a800), + DICO(0x2f9b3600), DICO(0x338c0540), DICO(0x370c3cc0), DICO(0x3abbc3c0), + DICO(0x4053a000), DICO(0x4f14d980), DICO(0x57e0b600), DICO(0x5d95e780), + DICO(0x05d844b8), DICO(0x07a05608), DICO(0x0b7837f0), DICO(0x161fb460), + DICO(0x19c31d00), DICO(0x1cf36280), DICO(0x20ccc200), DICO(0x24ae3980), + DICO(0x2e2b5800), DICO(0x3316af80), DICO(0x37432b00), DICO(0x4050b280), + DICO(0x4605be00), DICO(0x4cc78900), DICO(0x556d2080), DICO(0x5c578300), + DICO(0x0551b768), DICO(0x07024f60), DICO(0x1045fde0), DICO(0x16480120), + DICO(0x19974420), DICO(0x1ec2b280), DICO(0x228b30c0), DICO(0x295e0ec0), + DICO(0x2d8775c0), DICO(0x30ef1440), DICO(0x35978080), DICO(0x3a2ab480), + DICO(0x40229780), DICO(0x4da40980), DICO(0x5718e480), DICO(0x5d68d400), + DICO(0x03f903e4), DICO(0x06731580), DICO(0x0ecf4850), DICO(0x12e57920), + DICO(0x1a69ece0), DICO(0x1fe32700), DICO(0x2585b9c0), DICO(0x2aa006c0), + DICO(0x2f20ea80), DICO(0x37298bc0), DICO(0x3df2a000), DICO(0x44a6c600), + DICO(0x4b10de00), DICO(0x510fb880), DICO(0x5749c280), DICO(0x5d0b9480), + DICO(0x03c418fc), DICO(0x056c4cd0), DICO(0x0d0cf070), DICO(0x1907a2c0), + DICO(0x1be9bc00), DICO(0x21599480), DICO(0x25700e40), DICO(0x2c83e280), + DICO(0x329fa7c0), DICO(0x389f4cc0), DICO(0x3ef60900), DICO(0x44c19300), + DICO(0x4af56d00), DICO(0x512eec80), DICO(0x5772ad00), DICO(0x5d37f380), + DICO(0x04d57920), DICO(0x0716b5e0), DICO(0x0cb3bcc0), DICO(0x1197f740), + DICO(0x163e5fc0), DICO(0x2194e400), DICO(0x274bb600), DICO(0x2f5d7080), + DICO(0x361ee340), DICO(0x3b3b22c0), DICO(0x3f800400), DICO(0x4327ef80), + DICO(0x48b5d200), DICO(0x5116d300), DICO(0x59652e80), DICO(0x5e444d00), + DICO(0x0755b6b0), DICO(0x0b68c2c0), DICO(0x0f3441d0), DICO(0x124a01a0), + DICO(0x18910600), DICO(0x20911b80), DICO(0x281f7100), DICO(0x2e4dd640), + DICO(0x335bd8c0), DICO(0x37f14a80), DICO(0x3cab7b80), DICO(0x43be3180), + DICO(0x4beee100), DICO(0x52292180), DICO(0x57efea00), DICO(0x5d177300), + DICO(0x071a7748), DICO(0x0c6cf1b0), DICO(0x10db1500), DICO(0x143bca00), + DICO(0x1b86a900), DICO(0x22ed1d80), DICO(0x2a1f61c0), DICO(0x305f1400), + DICO(0x3645f580), DICO(0x3be45b00), DICO(0x4166ea80), DICO(0x46c3f200), + DICO(0x4c740400), DICO(0x51e30d00), DICO(0x57a37000), DICO(0x5cfc4980), + DICO(0x08cdd5b0), DICO(0x0daf9840), DICO(0x11cc02a0), DICO(0x1588ed40), + DICO(0x1cfef5e0), DICO(0x239f12c0), DICO(0x296d3b40), DICO(0x2e61c240), + DICO(0x333dc800), DICO(0x385d0000), DICO(0x3e1e5180), DICO(0x44196e00), + DICO(0x4a833000), DICO(0x503d7b80), DICO(0x56556680), DICO(0x5c410c00), + DICO(0x07372408), DICO(0x0d5c41f0), DICO(0x155dc140), DICO(0x1a9a3cc0), + DICO(0x21740980), DICO(0x27139f40), DICO(0x2c977040), DICO(0x30cfe5c0), + DICO(0x35381240), DICO(0x39b83140), DICO(0x3ef3fe80), DICO(0x44547200), + DICO(0x4a812800), DICO(0x5046c200), DICO(0x56957d00), DICO(0x5c85cd80), + DICO(0x06da6990), DICO(0x0bc41250), DICO(0x13d54800), DICO(0x1979c220), + DICO(0x1fad2f00), DICO(0x24bbe0c0), DICO(0x29c08f00), DICO(0x2e34b940), + DICO(0x32c89e40), DICO(0x376a2040), DICO(0x3cd81080), DICO(0x4267bd00), + DICO(0x48e8e800), DICO(0x4f150280), DICO(0x55cb1980), DICO(0x5c428b80), + DICO(0x087d45d0), DICO(0x0cf1ef20), DICO(0x135cba20), DICO(0x16fc7420), + DICO(0x1b2772e0), DICO(0x1fd4fe60), DICO(0x260a0b80), DICO(0x2bc54c00), + DICO(0x31694cc0), DICO(0x36d08080), DICO(0x3c245c80), DICO(0x41170900), + DICO(0x47b18600), DICO(0x4e706180), DICO(0x558d2000), DICO(0x5c428d00), + DICO(0x081e6490), DICO(0x0d16a7d0), DICO(0x124ccd20), DICO(0x154c20c0), + DICO(0x1945d8c0), DICO(0x1ee0b700), DICO(0x26a01f00), DICO(0x2d554e40), + DICO(0x3432eb80), DICO(0x3a605500), DICO(0x401d8980), DICO(0x45737680), + DICO(0x4b03cb00), DICO(0x50666780), DICO(0x56a0cd00), DICO(0x5cb46480), + DICO(0x06c58278), DICO(0x091b10b0), DICO(0x0e0e74f0), DICO(0x11faf980), + DICO(0x14a48600), DICO(0x1e6f7500), DICO(0x27f77100), DICO(0x2ab49940), + DICO(0x32a1f680), DICO(0x38cb2a80), DICO(0x3c3ff140), DICO(0x3f681cc0), + DICO(0x44310700), DICO(0x4fa21700), DICO(0x586c6180), DICO(0x5df74200), + DICO(0x06a3e478), DICO(0x09714400), DICO(0x0d90b7a0), DICO(0x12df2720), + DICO(0x1618f320), DICO(0x1ac52840), DICO(0x27612900), DICO(0x2e438e00), + DICO(0x322b6ac0), DICO(0x38022940), DICO(0x3d2a5180), DICO(0x40d76b80), + DICO(0x46671500), DICO(0x4c5bd480), DICO(0x517a2500), DICO(0x57775b00), + DICO(0x056c2230), DICO(0x07b8f9d8), DICO(0x0bc6e060), DICO(0x16ac2c80), + DICO(0x1a92fc00), DICO(0x1e15f000), DICO(0x28b73200), DICO(0x2cd9e5c0), + DICO(0x3196ecc0), DICO(0x3abae340), DICO(0x4040c580), DICO(0x44c18d80), + DICO(0x4c086800), DICO(0x50b78500), DICO(0x54e42600), DICO(0x5a549a80), + DICO(0x04f9fa10), DICO(0x07419358), DICO(0x0c3e15f0), DICO(0x174c1800), + DICO(0x1ab1fe60), DICO(0x23a12680), DICO(0x27955780), DICO(0x2d14b1c0), + DICO(0x35cefb00), DICO(0x39576700), DICO(0x3e82b780), DICO(0x42b6a680), + DICO(0x476d1880), DICO(0x4b6cdd00), DICO(0x52758680), DICO(0x5b69e500), + DICO(0x060b7ab0), DICO(0x081c05c0), DICO(0x0b540300), DICO(0x0f564270), + DICO(0x1210aa80), DICO(0x1771e060), DICO(0x25d73280), DICO(0x2e49e380), + DICO(0x319c1100), DICO(0x3771e700), DICO(0x3c532f40), DICO(0x40c9a900), + DICO(0x48cbf580), DICO(0x4f819980), DICO(0x566f9400), DICO(0x5cfdd980), + DICO(0x04efb7b8), DICO(0x0b8a3710), DICO(0x124fd520), DICO(0x1846dde0), + DICO(0x1e77a9e0), DICO(0x243ea800), DICO(0x2a4e3280), DICO(0x2ff532c0), + DICO(0x35d27680), DICO(0x3b8cdb00), DICO(0x41463000), DICO(0x4706c700), + DICO(0x4ca42d80), DICO(0x525d9200), DICO(0x57dabb80), DICO(0x5d59a800), + DICO(0x03620dec), DICO(0x095872e0), DICO(0x108d4920), DICO(0x16e9ea00), + DICO(0x1d60b2e0), DICO(0x235e9d00), DICO(0x29893b80), DICO(0x2f59a3c0), + DICO(0x3556b880), DICO(0x3b10bdc0), DICO(0x40f49500), DICO(0x469cc480), + DICO(0x4c762d00), DICO(0x51f16980), DICO(0x578c6d00), DICO(0x5c9b5a00), + DICO(0x05dd9bc0), DICO(0x079c5b20), DICO(0x0d319af0), DICO(0x18997040), + DICO(0x1c0a1980), DICO(0x20e926c0), DICO(0x25ca1640), DICO(0x29879340), + DICO(0x30b27040), DICO(0x36077340), DICO(0x39ac3d00), DICO(0x3d686cc0), + DICO(0x428e5f00), DICO(0x47c1bf80), DICO(0x4e720800), DICO(0x5b419880), + DICO(0x07694258), DICO(0x0b50db90), DICO(0x0f384950), DICO(0x140dac40), + DICO(0x17c50d80), DICO(0x1b49b300), DICO(0x24746200), DICO(0x2ce92fc0), + DICO(0x309fdac0), DICO(0x35c02a00), DICO(0x3aa3df00), DICO(0x3e1edb00), + DICO(0x431ad280), DICO(0x4b57f500), DICO(0x51463980), DICO(0x586b5200), + DICO(0x06401dd0), DICO(0x08d3d9b0), DICO(0x0ca0f510), DICO(0x10ed1920), + DICO(0x1451c2e0), DICO(0x2082f640), DICO(0x2872c0c0), DICO(0x2ca9da00), + DICO(0x3219cd00), DICO(0x35977300), DICO(0x3a8ba1c0), DICO(0x43d5f280), + DICO(0x49a51f00), DICO(0x4de9b400), DICO(0x5362ef80), DICO(0x59387300), + DICO(0x0589c430), DICO(0x07809918), DICO(0x0d086f80), DICO(0x10371c20), + DICO(0x151842c0), DICO(0x1bfcb1c0), DICO(0x22441040), DICO(0x2722b5c0), + DICO(0x2b603fc0), DICO(0x314465c0), DICO(0x40308b00), DICO(0x47d5a200), + DICO(0x4bf7e000), DICO(0x4f937200), DICO(0x5584eb00), DICO(0x5cb02200), + DICO(0x03b592f0), DICO(0x056ba738), DICO(0x0a8e2250), DICO(0x172436c0), + DICO(0x1ad35da0), DICO(0x1d72dc80), DICO(0x20cd3900), DICO(0x2a962940), + DICO(0x2f3b6700), DICO(0x33312b40), DICO(0x38dc6680), DICO(0x41659200), + DICO(0x4d36a380), DICO(0x52b00980), DICO(0x58c82800), DICO(0x5d741600), + DICO(0x05bdfe10), DICO(0x0756da20), DICO(0x0cd31fe0), DICO(0x130f1820), + DICO(0x1561caa0), DICO(0x1962ab20), DICO(0x1c310840), DICO(0x28bf6f80), + DICO(0x2d2d4500), DICO(0x3230f900), DICO(0x3ac2ea80), DICO(0x3ebe71c0), + DICO(0x48280700), DICO(0x50254900), DICO(0x5850a200), DICO(0x5e687200), + DICO(0x04e2b7e8), DICO(0x067f5430), DICO(0x0a8899a0), DICO(0x0d571560), + DICO(0x1c42f440), DICO(0x22e21fc0), DICO(0x27074340), DICO(0x2c493240), + DICO(0x2f7ece00), DICO(0x33959ec0), DICO(0x392d3000), DICO(0x459fc800), + DICO(0x4ba5f700), DICO(0x4fde7780), DICO(0x55f90380), DICO(0x5c928b00), + DICO(0x0557b940), DICO(0x075f0158), DICO(0x0bd8c540), DICO(0x0f4ee370), + DICO(0x141dc900), DICO(0x1b241f00), DICO(0x21c32a80), DICO(0x29a23980), + DICO(0x2e475380), DICO(0x3616f9c0), DICO(0x3a52a500), DICO(0x40345f00), + DICO(0x4763a500), DICO(0x4eb5bb80), DICO(0x561d4480), DICO(0x5d388580), + DICO(0x057d7d08), DICO(0x0738c240), DICO(0x0bf46e10), DICO(0x0ec93da0), + DICO(0x14ab3cc0), DICO(0x23d0f5c0), DICO(0x271e9900), DICO(0x2c0ee4c0), + DICO(0x301d1f00), DICO(0x33868040), DICO(0x37cdde00), DICO(0x3c805440), + DICO(0x43c69200), DICO(0x4f5c9a00), DICO(0x56eb3e80), DICO(0x5cdadc80), + DICO(0x06cdbab0), DICO(0x0999e600), DICO(0x0df39790), DICO(0x12ffc9a0), + DICO(0x15cfe7a0), DICO(0x1c599300), DICO(0x21afd600), DICO(0x26842bc0), + DICO(0x32067c00), DICO(0x368bb080), DICO(0x3c350c40), DICO(0x44e8be00), + DICO(0x4ac84000), DICO(0x4f9c1280), DICO(0x5449ec00), DICO(0x594d5880), + DICO(0x049a6bd0), DICO(0x06849f08), DICO(0x10592b40), DICO(0x168c1940), + DICO(0x1992df40), DICO(0x1e91b300), DICO(0x2237e100), DICO(0x2cd73a80), + DICO(0x30e7c100), DICO(0x361a45c0), DICO(0x3cdd1f40), DICO(0x41d5d100), + DICO(0x46f79480), DICO(0x4e44c880), DICO(0x55830e80), DICO(0x5d7c0680), + DICO(0x05087958), DICO(0x06fb7e40), DICO(0x0ac5ace0), DICO(0x14e91d80), + DICO(0x19ac68c0), DICO(0x1dbf7600), DICO(0x26f916c0), DICO(0x2bd2c980), + DICO(0x307f7900), DICO(0x38e07e40), DICO(0x3df7f1c0), DICO(0x41323d00), + DICO(0x44d2f480), DICO(0x48fb0480), DICO(0x51e17900), DICO(0x5c15d700), + DICO(0x0346cf40), DICO(0x05423408), DICO(0x0b640ce0), DICO(0x13055060), + DICO(0x1a8c0b60), DICO(0x1d8d2280), DICO(0x218b6500), DICO(0x2c385700), + DICO(0x30927b40), DICO(0x35d82880), DICO(0x3aa87e00), DICO(0x3da46a40), + DICO(0x45ea5280), DICO(0x511ecb80), DICO(0x57b53b00), DICO(0x5d491400), + DICO(0x056aa1c8), DICO(0x075a09a0), DICO(0x0a5d61d0), DICO(0x13cb9fe0), + DICO(0x1f924dc0), DICO(0x237a11c0), DICO(0x277d6b80), DICO(0x2c2ba440), + DICO(0x30195c80), DICO(0x35250cc0), DICO(0x3b718200), DICO(0x40113c80), + DICO(0x44df2680), DICO(0x49f0ed80), DICO(0x50791980), DICO(0x5ac10600), + DICO(0x046f1e50), DICO(0x061dd758), DICO(0x1236bec0), DICO(0x16c07340), + DICO(0x1a7399c0), DICO(0x1f61ee20), DICO(0x244b2280), DICO(0x2b803e40), + DICO(0x2eda5300), DICO(0x331210c0), DICO(0x3773bfc0), DICO(0x411c8400), + DICO(0x488ff380), DICO(0x4fad2700), DICO(0x55845000), DICO(0x5ca74c00), + DICO(0x04b456f0), DICO(0x05fca198), DICO(0x0ad056d0), DICO(0x19c3bfe0), + DICO(0x1d446100), DICO(0x20f67200), DICO(0x24a40b40), DICO(0x28d472c0), + DICO(0x2da813c0), DICO(0x31880200), DICO(0x35344f40), DICO(0x3ca7f340), + DICO(0x4aa94300), DICO(0x4f921500), DICO(0x5516d700), DICO(0x5c832880), + DICO(0x07f468c0), DICO(0x0bbb6e90), DICO(0x0f0f8730), DICO(0x143d6180), + DICO(0x198b84c0), DICO(0x1c6b30a0), DICO(0x219c8000), DICO(0x28795780), + DICO(0x2cce3d00), DICO(0x329b1100), DICO(0x3a8d2240), DICO(0x3f579080), + DICO(0x45a74400), DICO(0x4d000f80), DICO(0x52bd6880), DICO(0x5a743a80), + DICO(0x06979498), DICO(0x088fecf0), DICO(0x0f1dac90), DICO(0x12077160), + DICO(0x16d5b120), DICO(0x1c5465c0), DICO(0x21ad14c0), DICO(0x282be280), + DICO(0x2b66a380), DICO(0x2fa3f200), DICO(0x35a06500), DICO(0x3a458d00), + DICO(0x44aefc00), DICO(0x4e92f600), DICO(0x55b9fa80), DICO(0x5cfe0280), + DICO(0x0552b408), DICO(0x06f6ce38), DICO(0x0e8f8d80), DICO(0x1395e900), + DICO(0x17c7b440), DICO(0x1ec64dc0), DICO(0x236e2200), DICO(0x2abc0b80), + DICO(0x2e131240), DICO(0x32921100), DICO(0x372633c0), DICO(0x3ca97840), + DICO(0x496e5000), DICO(0x4f86a800), DICO(0x54072300), DICO(0x5be31c80), + DICO(0x0470c0b8), DICO(0x0662c468), DICO(0x0c493fd0), DICO(0x1a1949c0), + DICO(0x1febcc20), DICO(0x2364e900), DICO(0x2a0cce00), DICO(0x2f6f8140), + DICO(0x3418b000), DICO(0x3c5c7a40), DICO(0x42d39100), DICO(0x476c2b00), + DICO(0x4e11c300), DICO(0x53621500), DICO(0x583fd280), DICO(0x5ce26600), + DICO(0x04b006c0), DICO(0x09a1ed40), DICO(0x135aee00), DICO(0x193b5180), + DICO(0x1f3679a0), DICO(0x24fdbcc0), DICO(0x2b823e00), DICO(0x31835780), + DICO(0x37c74cc0), DICO(0x3df66780), DICO(0x43c18580), DICO(0x49465980), + DICO(0x4ed0ce00), DICO(0x53d6fb80), DICO(0x59064300), DICO(0x5deaa100), + DICO(0x03cbc49c), DICO(0x07735930), DICO(0x138aaa20), DICO(0x1a1e69a0), + DICO(0x21be93c0), DICO(0x2936f780), DICO(0x2fa76f80), DICO(0x34ae6b00), + DICO(0x396b7b80), DICO(0x3dbc6700), DICO(0x421a9100), DICO(0x46fd2180), + DICO(0x4c5dca80), DICO(0x51923b80), DICO(0x576d1300), DICO(0x5d288680), + DICO(0x03cab7d0), DICO(0x052c88b8), DICO(0x09ed24f0), DICO(0x1c261820), + DICO(0x209096c0), DICO(0x2361e080), DICO(0x27292800), DICO(0x2bbdc6c0), + DICO(0x3292da80), DICO(0x36866a40), DICO(0x3c4d5100), DICO(0x45233400), + DICO(0x4d928a00), DICO(0x52ca9d00), DICO(0x5820d000), DICO(0x5d903880), + DICO(0x03f83718), DICO(0x0540fa90), DICO(0x13028120), DICO(0x1ad6e160), + DICO(0x1d784880), DICO(0x22028900), DICO(0x25976b40), DICO(0x2b293700), + DICO(0x2ddb86c0), DICO(0x317c4340), DICO(0x34e62ec0), DICO(0x3b71bd00), + DICO(0x4bc34780), DICO(0x52982400), DICO(0x57fa2800), DICO(0x5f19cc00), + DICO(0x049ceb50), DICO(0x06a8d4e0), DICO(0x09db2470), DICO(0x120e3e60), + DICO(0x1c8ebb80), DICO(0x21221d00), DICO(0x2679bfc0), DICO(0x2b1e7600), + DICO(0x2ebbcf80), DICO(0x32d5afc0), DICO(0x3d1bef00), DICO(0x41b11a00), + DICO(0x45bb2d80), DICO(0x4cb70300), DICO(0x572fdc80), DICO(0x5d876e80), + DICO(0x04abda68), DICO(0x06698cd0), DICO(0x0ca87230), DICO(0x15086a80), + DICO(0x176cf4e0), DICO(0x22899440), DICO(0x268fc500), DICO(0x2ba2d940), + DICO(0x33505980), DICO(0x36944bc0), DICO(0x3b20c280), DICO(0x437e8f00), + DICO(0x4bf29e80), DICO(0x51776a80), DICO(0x57a77800), DICO(0x5cf6c180), + DICO(0x06d7f5c0), DICO(0x08fd3cc0), DICO(0x0d8807e0), DICO(0x1140d500), + DICO(0x146dfc80), DICO(0x1e9fbaa0), DICO(0x23d7bf00), DICO(0x28b2ae80), + DICO(0x2e5a9b00), DICO(0x327005c0), DICO(0x37736640), DICO(0x4001c500), + DICO(0x4a862b00), DICO(0x4f7a2e00), DICO(0x54a22080), DICO(0x5b76c380), + DICO(0x0671fb68), DICO(0x08e4bf30), DICO(0x0d801250), DICO(0x1176b820), + DICO(0x15128860), DICO(0x1ee21180), DICO(0x24799580), DICO(0x29415a40), + DICO(0x2efa2380), DICO(0x33fe5040), DICO(0x39bf6d00), DICO(0x3f28b380), + DICO(0x442b2280), DICO(0x493de680), DICO(0x54377700), DICO(0x5d3a5480), + DICO(0x065b7970), DICO(0x087820b0), DICO(0x0d8d6aa0), DICO(0x16718620), + DICO(0x1a3a8f40), DICO(0x1f4099c0), DICO(0x24d87b40), DICO(0x296d85c0), + DICO(0x2f887c80), DICO(0x342d1b40), DICO(0x3887fc40), DICO(0x3d758b40), + DICO(0x42641c80), DICO(0x47bf6980), DICO(0x55f82900), DICO(0x5e132a00), + DICO(0x05ddbc00), DICO(0x081f17a0), DICO(0x0bf23ac0), DICO(0x12fc8d60), + DICO(0x172bc440), DICO(0x1a833540), DICO(0x1e942200), DICO(0x21e477c0), + DICO(0x2e75da80), DICO(0x399efac0), DICO(0x3dfb6900), DICO(0x428b3780), + DICO(0x4922a080), DICO(0x4d4c1700), DICO(0x51bbee00), DICO(0x5b4cfc80), + DICO(0x06ecf380), DICO(0x08f83990), DICO(0x0cb55680), DICO(0x140b2860), + DICO(0x18084d00), DICO(0x1aff9940), DICO(0x1f5f6f00), DICO(0x224a3d80), + DICO(0x2b0f49c0), DICO(0x3613b280), DICO(0x39188f40), DICO(0x3efa3640), + DICO(0x4771e400), DICO(0x4ca32380), DICO(0x54627580), DICO(0x5cb91000), + DICO(0x069e7f98), DICO(0x0870c760), DICO(0x0d7b73a0), DICO(0x15ab1040), + DICO(0x18a4d220), DICO(0x1c4c1f20), DICO(0x1ffaf200), DICO(0x24142580), + DICO(0x30e47540), DICO(0x37340200), DICO(0x3a69af40), DICO(0x3ed471c0), + DICO(0x44157880), DICO(0x486b7f00), DICO(0x52ed2b00), DICO(0x5ce3a980), + DICO(0x047f1080), DICO(0x06463230), DICO(0x0b566e80), DICO(0x0edb9080), + DICO(0x128a2fa0), DICO(0x1748b340), DICO(0x210b2b00), DICO(0x28099b80), + DICO(0x2f519740), DICO(0x36fe82c0), DICO(0x3d924b80), DICO(0x43cd3c00), + DICO(0x4a774680), DICO(0x50d15f00), DICO(0x573b3580), DICO(0x5d4c1c00), + DICO(0x05fa6a68), DICO(0x0866e4c0), DICO(0x0d133cc0), DICO(0x156d6b20), + DICO(0x18abebe0), DICO(0x1d374900), DICO(0x23d23d00), DICO(0x27b370c0), + DICO(0x2f63ef00), DICO(0x352a0600), DICO(0x3a643a40), DICO(0x3f57f980), + DICO(0x457a7f00), DICO(0x520f6200), DICO(0x593b2c80), DICO(0x5e192b80), + DICO(0x04e4e0c8), DICO(0x067c3450), DICO(0x0acabe70), DICO(0x1865eec0), + DICO(0x1c5e9bc0), DICO(0x202facc0), DICO(0x24a609c0), DICO(0x28db7b00), + DICO(0x2efbd780), DICO(0x336fe5c0), DICO(0x3819a5c0), DICO(0x3e709b40), + DICO(0x4435ff80), DICO(0x4bd5fb80), DICO(0x5564a100), DICO(0x5d0a4980), + DICO(0x05a72f00), DICO(0x070199b0), DICO(0x0e654780), DICO(0x14fc7780), + DICO(0x174283c0), DICO(0x1b231480), DICO(0x1e7b9000), DICO(0x27a013c0), + DICO(0x2b42f500), DICO(0x2fd9ca00), DICO(0x3672a0c0), DICO(0x3cc23f40), + DICO(0x48299d80), DICO(0x4f92a800), DICO(0x564d7680), DICO(0x5d3ab580), + DICO(0x03e63764), DICO(0x05baa3f0), DICO(0x0ab2a300), DICO(0x12cc5f60), + DICO(0x19a8d5e0), DICO(0x1ea788e0), DICO(0x22cd50c0), DICO(0x25d48a00), + DICO(0x29924540), DICO(0x32762a00), DICO(0x3bba55c0), DICO(0x4222e800), + DICO(0x4aba1280), DICO(0x501d0b80), DICO(0x57091200), DICO(0x5d6bf180), + DICO(0x047daeb0), DICO(0x069548b8), DICO(0x0b002410), DICO(0x13ff7060), + DICO(0x186aec40), DICO(0x210db240), DICO(0x26f1ce80), DICO(0x2b73c9c0), + DICO(0x33d57240), DICO(0x385898c0), DICO(0x3eea8cc0), DICO(0x43c79b00), + DICO(0x496ec200), DICO(0x4e150780), DICO(0x54dcb700), DICO(0x5c3f7380), + DICO(0x079fd258), DICO(0x0b93bd50), DICO(0x0ff7d8b0), DICO(0x14bd4e00), + DICO(0x19536ae0), DICO(0x1d8b1640), DICO(0x23747cc0), DICO(0x2861f280), + DICO(0x2d7d2880), DICO(0x3583b040), DICO(0x3c3cab00), DICO(0x41b7b580), + DICO(0x498cfc80), DICO(0x506cbd00), DICO(0x57847600), DICO(0x5d05de80), + DICO(0x06434ec0), DICO(0x0805ccd0), DICO(0x0c4b4c00), DICO(0x13d551c0), + DICO(0x1685abe0), DICO(0x1a83ea60), DICO(0x1ddc3700), DICO(0x22bc4600), + DICO(0x2c7ca5c0), DICO(0x30a589c0), DICO(0x395a8700), DICO(0x40c92900), + DICO(0x472fae80), DICO(0x4f6f6e80), DICO(0x571b3f80), DICO(0x5d8e6980), + DICO(0x05ec21b0), DICO(0x079ee388), DICO(0x0e4b4580), DICO(0x11abf100), + DICO(0x16588ec0), DICO(0x1c984ec0), DICO(0x20a384c0), DICO(0x28d6be00), + DICO(0x2bcca740), DICO(0x3604b600), DICO(0x3f027280), DICO(0x434af000), + DICO(0x48dac280), DICO(0x4d7e8a00), DICO(0x51f61800), DICO(0x5a6d9380), + DICO(0x0552c6c0), DICO(0x070c22a0), DICO(0x0a411b50), DICO(0x0e3e5270), + DICO(0x1193bb60), DICO(0x1b177e00), DICO(0x275b2500), DICO(0x2b42bd80), + DICO(0x322d7e40), DICO(0x3a170880), DICO(0x3d66b580), DICO(0x41413280), + DICO(0x46a9ce80), DICO(0x4e4e3800), DICO(0x571f8380), DICO(0x5ddae380), + DICO(0x055602c0), DICO(0x06e69118), DICO(0x0c9d13f0), DICO(0x1090d500), + DICO(0x138d2280), DICO(0x171bf540), DICO(0x1b585180), DICO(0x288b9740), + DICO(0x2db202c0), DICO(0x3525e680), DICO(0x3c303900), DICO(0x4311df80), + DICO(0x49b92c00), DICO(0x509de900), DICO(0x56e9a080), DICO(0x5d523a80), + DICO(0x04e79810), DICO(0x069626e8), DICO(0x0a6cf680), DICO(0x0da668c0), + DICO(0x115872a0), DICO(0x2032eec0), DICO(0x25345dc0), DICO(0x2ae8ea40), + DICO(0x30224280), DICO(0x351ff640), DICO(0x3ce65a80), DICO(0x454bff00), + DICO(0x4ee08980), DICO(0x543b4280), DICO(0x59c19280), DICO(0x5ddfbb00), + DICO(0x03f0bb98), DICO(0x0588f4f0), DICO(0x0a862bc0), DICO(0x14ec76e0), + DICO(0x184b8a80), DICO(0x1f7bbd80), DICO(0x23f1a7c0), DICO(0x2c367900), + DICO(0x3234af80), DICO(0x35460ac0), DICO(0x38514c00), DICO(0x3d5f3540), + DICO(0x48394980), DICO(0x4fbdd380), DICO(0x56de0280), DICO(0x5d4e6500), + DICO(0x06050f28), DICO(0x08070af0), DICO(0x0be31240), DICO(0x0f5e53e0), + DICO(0x125f1740), DICO(0x215b1fc0), DICO(0x2883d880), DICO(0x2c181080), + DICO(0x32810280), DICO(0x35d56800), DICO(0x3a9b0880), DICO(0x3ffaaf80), + DICO(0x44c65500), DICO(0x4a45ae80), DICO(0x56b4ed80), DICO(0x5e4adc00), + DICO(0x0372bbb4), DICO(0x04ea4848), DICO(0x09b8de70), DICO(0x151b4a40), + DICO(0x1be65a00), DICO(0x207655c0), DICO(0x2720dd00), DICO(0x2fc6cc00), + DICO(0x35b063c0), DICO(0x39bd30c0), DICO(0x3dc5b580), DICO(0x42af7b00), + DICO(0x48d2bf00), DICO(0x4f46bb80), DICO(0x55f7ca80), DICO(0x5ca7e980), + DICO(0x033f868c), DICO(0x04d9a0e0), DICO(0x0a18d6d0), DICO(0x13da5580), + DICO(0x181ae880), DICO(0x207d8580), DICO(0x262022c0), DICO(0x2c6de040), + DICO(0x3321f100), DICO(0x3927f0c0), DICO(0x3f74ce40), DICO(0x4573e980), + DICO(0x4ba66c80), DICO(0x51a26100), DICO(0x57d3a800), DICO(0x5d52e780), + DICO(0x05189860), DICO(0x07231848), DICO(0x0b915710), DICO(0x0f05d6c0), + DICO(0x13bb0820), DICO(0x223adf00), DICO(0x26ce1ec0), DICO(0x2ce1ac00), + DICO(0x3401f6c0), DICO(0x3b8c2240), DICO(0x40e4a400), DICO(0x45674f00), + DICO(0x4b04b880), DICO(0x4f253200), DICO(0x54168600), DICO(0x58f52780), + DICO(0x0338d184), DICO(0x05205790), DICO(0x09abcd80), DICO(0x0f53ff60), + DICO(0x1a7fe900), DICO(0x1ef93860), DICO(0x238e2d80), DICO(0x2bd81bc0), + DICO(0x33161240), DICO(0x368cfb80), DICO(0x3a28b5c0), DICO(0x40c7a600), + DICO(0x4bac7780), DICO(0x524b7880), DICO(0x58638480), DICO(0x5da07b00), + DICO(0x04d06f38), DICO(0x065f1518), DICO(0x0c9b31b0), DICO(0x10570d40), + DICO(0x15e790a0), DICO(0x20f16380), DICO(0x246f23c0), DICO(0x2e222800), + DICO(0x3198bf00), DICO(0x34b84640), DICO(0x38f5b440), DICO(0x4312df80), + DICO(0x4d2d3000), DICO(0x5209ee80), DICO(0x579cf180), DICO(0x5cb37680), + DICO(0x042e6560), DICO(0x05eaff30), DICO(0x0a090d30), DICO(0x0d9f2ab0), + DICO(0x1a6f0260), DICO(0x209e0c00), DICO(0x25dc95c0), DICO(0x29f89840), + DICO(0x2f372840), DICO(0x3a301940), DICO(0x3f0e2e80), DICO(0x44465c80), + DICO(0x49207780), DICO(0x4dfdab80), DICO(0x532ec000), DICO(0x5acefd00), + DICO(0x04e18ad8), DICO(0x06d5b660), DICO(0x0b2a22d0), DICO(0x0e0e4ef0), + DICO(0x198304a0), DICO(0x1e4a25c0), DICO(0x23de37c0), DICO(0x290679c0), + DICO(0x2d523b00), DICO(0x337df940), DICO(0x37948100), DICO(0x3de07300), + DICO(0x49ee6e80), DICO(0x50576100), DICO(0x55fb1e00), DICO(0x5d080500), + DICO(0x05312308), DICO(0x070463f0), DICO(0x0daffba0), DICO(0x12d8c3c0), + DICO(0x163ab7a0), DICO(0x20c64c40), DICO(0x24c8fe40), DICO(0x2a6f65c0), + DICO(0x3055e100), DICO(0x34420d80), DICO(0x389ded00), DICO(0x3cc57640), + DICO(0x4280cd00), DICO(0x4e0a4c00), DICO(0x57675f00), DICO(0x5d87d480), + DICO(0x047bd598), DICO(0x06cb1498), DICO(0x0c359930), DICO(0x138165e0), + DICO(0x1cae3640), DICO(0x21647640), DICO(0x2836fac0), DICO(0x2cd7b840), + DICO(0x30d839c0), DICO(0x360c9440), DICO(0x3ae5ca40), DICO(0x40a93b00), + DICO(0x49401e80), DICO(0x4f739c80), DICO(0x54f33c00), DICO(0x5c190200), + DICO(0x051c0000), DICO(0x06b45258), DICO(0x0a5eee50), DICO(0x0d46fc30), + DICO(0x125bbc60), DICO(0x253d8cc0), DICO(0x2a1fd6c0), DICO(0x2df4cf80), + DICO(0x3239e3c0), DICO(0x35a683c0), DICO(0x3b0bb980), DICO(0x409b3d00), + DICO(0x46633580), DICO(0x4f2b0600), DICO(0x577cea80), DICO(0x5d86ef00), + DICO(0x03d19eec), DICO(0x07cce6d0), DICO(0x143b4b00), DICO(0x1a657880), + DICO(0x212e0280), DICO(0x2831fbc0), DICO(0x2f8ba080), DICO(0x35db8040), + DICO(0x3bf17f00), DICO(0x413eb100), DICO(0x46154900), DICO(0x4ae18080), + DICO(0x4f9ba180), DICO(0x5428ba00), DICO(0x590e9080), DICO(0x5de0d880), + DICO(0x08c7e720), DICO(0x0ff14810), DICO(0x1758cc40), DICO(0x1cc744c0), + DICO(0x23e45cc0), DICO(0x2b527940), DICO(0x32138580), DICO(0x37b77380), + DICO(0x3d7da480), DICO(0x4275a800), DICO(0x473ecf00), DICO(0x4bc7dc80), + DICO(0x50512400), DICO(0x54d2c600), DICO(0x598ce680), DICO(0x5e1e0800), + DICO(0x09167910), DICO(0x107644a0), DICO(0x171a59e0), DICO(0x1be1ea60), + DICO(0x21347680), DICO(0x265a5b00), DICO(0x2be41a40), DICO(0x3116e700), + DICO(0x368b0300), DICO(0x3c225e80), DICO(0x41a6e880), DICO(0x47631680), + DICO(0x4d47d900), DICO(0x52a28400), DICO(0x583f0e80), DICO(0x5d77bc80), + DICO(0x040bdf88), DICO(0x05b062a0), DICO(0x0b4a2f70), DICO(0x1b8cd880), + DICO(0x1ec58c40), DICO(0x23661880), DICO(0x2790ba80), DICO(0x2d0d6c40), + DICO(0x34f0bc40), DICO(0x3a353f80), DICO(0x3fc3bc40), DICO(0x44998700), + DICO(0x49b17080), DICO(0x4f31fa00), DICO(0x55311c80), DICO(0x5b5c8f80), + DICO(0x043e2bd0), DICO(0x0645b0f0), DICO(0x0ade5b90), DICO(0x0d653a90), + DICO(0x1bc224a0), DICO(0x1f623dc0), DICO(0x27e9a840), DICO(0x2c719bc0), + DICO(0x2f2ac040), DICO(0x32688300), DICO(0x36695c00), DICO(0x3b8abe40), + DICO(0x47153a80), DICO(0x52491b00), DICO(0x57ba7680), DICO(0x5ce6c300), + DICO(0x052940b8), DICO(0x06f28228), DICO(0x0a741c90), DICO(0x0daa3110), + DICO(0x113bb2e0), DICO(0x2010b640), DICO(0x2610f380), DICO(0x2a5c7740), + DICO(0x2f7703c0), DICO(0x3388d080), DICO(0x3ceabe40), DICO(0x42462a80), + DICO(0x47fb0e00), DICO(0x4f7ac480), DICO(0x5706f580), DICO(0x5d92b800), + DICO(0x03a134a4), DICO(0x05623470), DICO(0x090a0fe0), DICO(0x12f7d3e0), + DICO(0x1d63e440), DICO(0x20e6ac80), DICO(0x247da8c0), DICO(0x27d99600), + DICO(0x312e99c0), DICO(0x368fb380), DICO(0x3b3e3ec0), DICO(0x40fead80), + DICO(0x4888fa00), DICO(0x4fbd5600), DICO(0x5795a480), DICO(0x5d973000), + DICO(0x05697990), DICO(0x06f33800), DICO(0x0b298290), DICO(0x0de47a60), + DICO(0x12ef62a0), DICO(0x21e30a00), DICO(0x25f8ff00), DICO(0x2b2287c0), + DICO(0x2f11fc00), DICO(0x33138000), DICO(0x37b49f80), DICO(0x41325100), + DICO(0x4ab62800), DICO(0x501eae80), DICO(0x56228780), DICO(0x5c5d8300), + DICO(0x063830d8), DICO(0x08a76a30), DICO(0x0d376890), DICO(0x117d3a00), + DICO(0x1476e5c0), DICO(0x1e215720), DICO(0x24bcd680), DICO(0x29674ac0), + DICO(0x2faab340), DICO(0x33843a00), DICO(0x3822e900), DICO(0x3d30b6c0), + DICO(0x49cd5480), DICO(0x53187d00), DICO(0x591fe100), DICO(0x5db30f80), + DICO(0x05cdc378), DICO(0x075c50c8), DICO(0x0e01f830), DICO(0x12b70480), + DICO(0x15e333e0), DICO(0x192c9f40), DICO(0x1d2d6b80), DICO(0x2c09ca40), + DICO(0x2eea5cc0), DICO(0x32c89380), DICO(0x376a5b40), DICO(0x42a42600), + DICO(0x4c695900), DICO(0x5269e380), DICO(0x586d6c80), DICO(0x5cebdb80), + DICO(0x052bbb80), DICO(0x0702e268), DICO(0x0ca196d0), DICO(0x0f48cef0), + DICO(0x19d28b60), DICO(0x1ec44a40), DICO(0x24d40f00), DICO(0x29e1eac0), + DICO(0x2cafaa80), DICO(0x301bd4c0), DICO(0x357ec200), DICO(0x42254480), + DICO(0x4be32000), DICO(0x4f7a4a00), DICO(0x5447fc00), DICO(0x5cca6a00), + DICO(0x050fdd18), DICO(0x06c77e10), DICO(0x10561140), DICO(0x1564c340), + DICO(0x1867abe0), DICO(0x1f00fba0), DICO(0x22c06240), DICO(0x2aed7680), + DICO(0x2ecc24c0), DICO(0x32abb300), DICO(0x36b42340), DICO(0x3ed8f480), + DICO(0x4bbdfe80), DICO(0x516bf800), DICO(0x58688b00), DICO(0x5dd44980), + DICO(0x058aa130), DICO(0x07d69ba8), DICO(0x0d521f40), DICO(0x0ff37ba0), + DICO(0x18125ec0), DICO(0x1f3a4520), DICO(0x23349840), DICO(0x2c759580), + DICO(0x2fc21c00), DICO(0x33a42fc0), DICO(0x3dc92900), DICO(0x47befd00), + DICO(0x4ccd2480), DICO(0x5197a200), DICO(0x56a2ea00), DICO(0x5bdfa900), + DICO(0x05ac8640), DICO(0x076aec88), DICO(0x0e2e3230), DICO(0x114b6f40), + DICO(0x155d10a0), DICO(0x19bac600), DICO(0x1fbd75c0), DICO(0x2459c0c0), + DICO(0x28229b80), DICO(0x2f586fc0), DICO(0x3d0697c0), DICO(0x42a7a500), + DICO(0x49b0bb80), DICO(0x4e642e80), DICO(0x55774280), DICO(0x5d1a7900), + DICO(0x05efb470), DICO(0x0831c8a0), DICO(0x0d35ece0), DICO(0x13edc400), + DICO(0x16c8fec0), DICO(0x1bb25860), DICO(0x204f3140), DICO(0x277b8a40), + DICO(0x2fe9a000), DICO(0x33af7c40), DICO(0x3b7d2900), DICO(0x419c9a80), + DICO(0x4591dc80), DICO(0x4bdafd00), DICO(0x55638880), DICO(0x5cef2300), + DICO(0x05cf4988), DICO(0x078fa8c0), DICO(0x0c291950), DICO(0x12e05320), + DICO(0x155997e0), DICO(0x195df540), DICO(0x1c1b82c0), DICO(0x22c29400), + DICO(0x307edec0), DICO(0x34e829c0), DICO(0x3b1b5040), DICO(0x434de400), + DICO(0x496b9900), DICO(0x4ff88080), DICO(0x5604c480), DICO(0x5c84b080), + DICO(0x03679fa4), DICO(0x050d4a20), DICO(0x09feec10), DICO(0x100a21e0), + DICO(0x1483b260), DICO(0x1d76c780), DICO(0x24e75c80), DICO(0x2bd62880), + DICO(0x32350a40), DICO(0x38be01c0), DICO(0x3f05a280), DICO(0x45295e80), + DICO(0x4b554800), DICO(0x51618880), DICO(0x575a1500), DICO(0x5d109d80), + DICO(0x034ffd08), DICO(0x04dccea8), DICO(0x07e289b8), DICO(0x0d6950d0), + DICO(0x189acec0), DICO(0x1e3bf240), DICO(0x2535aa40), DICO(0x2b88d140), + DICO(0x329bbb00), DICO(0x386c3500), DICO(0x3e950800), DICO(0x44c43f00), + DICO(0x4b089780), DICO(0x51223280), DICO(0x574c9780), DICO(0x5d366400), + DICO(0x036d8db8), DICO(0x04fd88b8), DICO(0x09700a70), DICO(0x116b73c0), + DICO(0x17258c40), DICO(0x1fd03000), DICO(0x23fdf400), DICO(0x28e08dc0), + DICO(0x32d688c0), DICO(0x37920b00), DICO(0x3daaa080), DICO(0x46a16c00), + DICO(0x4f8c3100), DICO(0x54a13700), DICO(0x59d24b80), DICO(0x5cea4d80), + DICO(0x05797c88), DICO(0x080dc8f0), DICO(0x0bd21520), DICO(0x1095b540), + DICO(0x138fd400), DICO(0x1aed19c0), DICO(0x29fead00), DICO(0x2f70cec0), + DICO(0x3327df00), DICO(0x3a812d00), DICO(0x400a8380), DICO(0x449daa00), + DICO(0x4cd6b600), DICO(0x51f12400), DICO(0x56bdfd80), DICO(0x5be0a100), + DICO(0x04de6d78), DICO(0x072aed40), DICO(0x0c6fc460), DICO(0x0f260220), + DICO(0x179d00c0), DICO(0x1e8244e0), DICO(0x23867240), DICO(0x2baf7680), + DICO(0x2fa6d240), DICO(0x37e83d40), DICO(0x3d1cbfc0), DICO(0x439d0a00), + DICO(0x49fd3e00), DICO(0x50095e80), DICO(0x559f2080), DICO(0x5b889a00), + DICO(0x042f5c10), DICO(0x061ab3e8), DICO(0x0dd8f160), DICO(0x126e0b40), + DICO(0x16ea9040), DICO(0x20a31700), DICO(0x24608140), DICO(0x2ec65080), + DICO(0x334e1a40), DICO(0x38252100), DICO(0x3fff0900), DICO(0x46519a80), + DICO(0x4c5e0d80), DICO(0x518c5800), DICO(0x56c5b080), DICO(0x5c6ebb80), + DICO(0x045ce230), DICO(0x067547b0), DICO(0x0a21c670), DICO(0x1408b820), + DICO(0x1c0505c0), DICO(0x1e806c80), DICO(0x26d3c640), DICO(0x2ca573c0), + DICO(0x3014d880), DICO(0x377108c0), DICO(0x3f35cf80), DICO(0x43566100), + DICO(0x4a612900), DICO(0x5160c780), DICO(0x57d3e300), DICO(0x5d414b80), + DICO(0x04c8eda8), DICO(0x06a32320), DICO(0x09ab2590), DICO(0x14230760), + DICO(0x20fb23c0), DICO(0x24aa2880), DICO(0x285a2580), DICO(0x2c464ac0), + DICO(0x30098280), DICO(0x36232780), DICO(0x3e428d40), DICO(0x42982280), + DICO(0x47e60d80), DICO(0x4e1ecc00), DICO(0x55eb9200), DICO(0x5c81ed00), + DICO(0x040d0b90), DICO(0x0586c5c0), DICO(0x0bea2190), DICO(0x1dc8dd60), + DICO(0x20a07c40), DICO(0x2437e580), DICO(0x27ca5fc0), DICO(0x2d017980), + DICO(0x34100040), DICO(0x38d3afc0), DICO(0x3da9b700), DICO(0x42082480), + DICO(0x46586f00), DICO(0x4e3c3d80), DICO(0x55e1ee00), DICO(0x5c938d00), + DICO(0x03d18c64), DICO(0x05941d60), DICO(0x116b2560), DICO(0x19cc8820), + DICO(0x1ce930c0), DICO(0x22626080), DICO(0x26d2cf80), DICO(0x2ce2c980), + DICO(0x305361c0), DICO(0x34b65900), DICO(0x39ee5b40), DICO(0x41508400), + DICO(0x47ee1e80), DICO(0x50311180), DICO(0x56cb0c00), DICO(0x5d561680), + DICO(0x0af22cf0), DICO(0x154e1c60), DICO(0x1b44ff60), DICO(0x2087d0c0), + DICO(0x252f7380), DICO(0x28fe66c0), DICO(0x2d0e9800), DICO(0x30f7ee00), + DICO(0x3606d640), DICO(0x3bac0a40), DICO(0x417c3700), DICO(0x470c2900), + DICO(0x4cc20d00), DICO(0x51e55e80), DICO(0x576bc200), DICO(0x5caa7080), + DICO(0x043314e0), DICO(0x05cb47b0), DICO(0x0985df20), DICO(0x185a22c0), + DICO(0x1ea68300), DICO(0x21af9100), DICO(0x25cdcb40), DICO(0x297e0a80), + DICO(0x3142ac80), DICO(0x358bb040), DICO(0x3a1345c0), DICO(0x402ca580), + DICO(0x4d964780), DICO(0x5420cf80), DICO(0x592adf80), DICO(0x5dfe7a80), + DICO(0x04c70e20), DICO(0x062fd6f0), DICO(0x113c60a0), DICO(0x159e9900), + DICO(0x1933e5a0), DICO(0x1decffa0), DICO(0x22373400), DICO(0x27ed7180), + DICO(0x2a8349c0), DICO(0x2f78f940), DICO(0x3d5c8540), DICO(0x429c3500), + DICO(0x4936e300), DICO(0x4de08d00), DICO(0x52627700), DICO(0x5d822680), + DICO(0x04982770), DICO(0x06ab1ad8), DICO(0x0cba1090), DICO(0x10839d60), + DICO(0x1acd6a60), DICO(0x1f554560), DICO(0x2431c1c0), DICO(0x295db800), + DICO(0x2d374c00), DICO(0x31f2fd80), DICO(0x3a200480), DICO(0x416bea80), + DICO(0x4ba1ce00), DICO(0x52a88000), DICO(0x58d0db00), DICO(0x5d3e5800), + DICO(0x059e0e70), DICO(0x08166ba0), DICO(0x0c9df590), DICO(0x11de5f40), + DICO(0x14c08ea0), DICO(0x1c5ad6e0), DICO(0x24178ec0), DICO(0x28eb7640), + DICO(0x31626280), DICO(0x35d43100), DICO(0x3cad10c0), DICO(0x422e1480), + DICO(0x49baee00), DICO(0x53dd7180), DICO(0x5a17bb80), DICO(0x5e4bb180), + DICO(0x03c64d00), DICO(0x05de0b28), DICO(0x0ccb82b0), DICO(0x144b1c00), + DICO(0x19e39ec0), DICO(0x21e795c0), DICO(0x28149380), DICO(0x2f1ff7c0), + DICO(0x35b7c900), DICO(0x3c5f4800), DICO(0x42799c00), DICO(0x48746180), + DICO(0x4e8f4d00), DICO(0x53b98380), DICO(0x58d60000), DICO(0x5d71a000), + DICO(0x050a2990), DICO(0x071bdb88), DICO(0x0f0d76b0), DICO(0x17a78de0), + DICO(0x1aa20720), DICO(0x22eea3c0), DICO(0x276e9640), DICO(0x2ecc4d80), + DICO(0x335f7900), DICO(0x37838640), DICO(0x3c81be80), DICO(0x41a4e400), + DICO(0x476fa280), DICO(0x4f2ab780), DICO(0x56e87b80), DICO(0x5cbf2900), + DICO(0x06724c98), DICO(0x099f5e20), DICO(0x119bcec0), DICO(0x16be11a0), + DICO(0x19d53b00), DICO(0x1eb51360), DICO(0x2302c300), DICO(0x29c20d40), + DICO(0x30dd5200), DICO(0x36576a80), DICO(0x3e3e7540), DICO(0x45aa9f80), + DICO(0x4c833300), DICO(0x51d7ed00), DICO(0x57a4a380), DICO(0x5cce9100), + DICO(0x05588b60), DICO(0x075a70a0), DICO(0x0ef96e30), DICO(0x12ac1100), + DICO(0x1649dde0), DICO(0x1a50cdc0), DICO(0x22486140), DICO(0x27c7c800), + DICO(0x2e08bd80), DICO(0x355d20c0), DICO(0x3925a9c0), DICO(0x44e2b480), + DICO(0x4fa4e680), DICO(0x5470e180), DICO(0x595fee80), DICO(0x5d672f00), + DICO(0x04a781c0), DICO(0x060a89f0), DICO(0x111f56a0), DICO(0x16b93be0), + DICO(0x19ce9120), DICO(0x1e1fda60), DICO(0x2259f880), DICO(0x285cad80), + DICO(0x2b140ec0), DICO(0x2f069940), DICO(0x33bbce40), DICO(0x3dd3e6c0), + DICO(0x49154880), DICO(0x5008e380), DICO(0x568c4680), DICO(0x5da43780), + DICO(0x053ade38), DICO(0x0708a200), DICO(0x0bad43d0), DICO(0x1860cf40), + DICO(0x1c40dbe0), DICO(0x1f5a0120), DICO(0x25bcf7c0), DICO(0x29e0c840), + DICO(0x2f223840), DICO(0x390c8940), DICO(0x3e1d7340), DICO(0x41c6a000), + DICO(0x46cc2880), DICO(0x5006e280), DICO(0x5744e180), DICO(0x5d297780), + DICO(0x0401a3f0), DICO(0x07be4a08), DICO(0x14f5f1a0), DICO(0x1c348080), + DICO(0x226753c0), DICO(0x274b1b80), DICO(0x2c11a300), DICO(0x30798c00), + DICO(0x35598c80), DICO(0x3aab18c0), DICO(0x4030f380), DICO(0x45c7b400), + DICO(0x4be5be00), DICO(0x5180db80), DICO(0x57613b00), DICO(0x5cffff80), + DICO(0x084b3090), DICO(0x0fe5b3b0), DICO(0x16dfd480), DICO(0x1d0aa700), + DICO(0x24e08180), DICO(0x2b498640), DICO(0x30885b80), DICO(0x34ccc480), + DICO(0x38fedec0), DICO(0x3cdf9c40), DICO(0x41737600), DICO(0x46ab9800), + DICO(0x4c772e80), DICO(0x51e5b980), DICO(0x57df9900), DICO(0x5d5d7180), + DICO(0x09549f00), DICO(0x12b84da0), DICO(0x1aeaf1c0), DICO(0x2142a9c0), + DICO(0x275c9a00), DICO(0x2c260c80), DICO(0x3038c700), DICO(0x34081d00), + DICO(0x38612f40), DICO(0x3d0bf8c0), DICO(0x42473e00), DICO(0x47ecad80), + DICO(0x4db34380), DICO(0x52f0ab00), DICO(0x584cc980), DICO(0x5d62ae80), + DICO(0x0aeca1e0), DICO(0x14354700), DICO(0x19955ba0), DICO(0x1de331e0), + DICO(0x21cd60c0), DICO(0x25e72d80), DICO(0x2a402880), DICO(0x2efa64c0), + DICO(0x3478d9c0), DICO(0x3a889e80), DICO(0x40744e00), DICO(0x4626fe80), + DICO(0x4bd80900), DICO(0x51120f00), DICO(0x56d8d280), DICO(0x5c654400), + DICO(0x07a40af8), DICO(0x0e65ec20), DICO(0x14c76780), DICO(0x19b35a60), + DICO(0x1f76b7c0), DICO(0x24f512c0), DICO(0x2ae89f00), DICO(0x3036c3c0), + DICO(0x36041800), DICO(0x3bc4df80), DICO(0x41adb080), DICO(0x477fbb80), + DICO(0x4d5aa480), DICO(0x52cb0600), DICO(0x586f7280), DICO(0x5db40180), + DICO(0x03997610), DICO(0x06175db0), DICO(0x0ea8c9c0), DICO(0x14397000), + DICO(0x1ba34f60), DICO(0x22346680), DICO(0x28958080), DICO(0x2ea76840), + DICO(0x33ee68c0), DICO(0x39e769c0), DICO(0x3f862500), DICO(0x4579b080), + DICO(0x4b49cd00), DICO(0x5107da80), DICO(0x573cde00), DICO(0x5d090780), + DICO(0x046fc2f8), DICO(0x0640dbc0), DICO(0x09da7ab0), DICO(0x174e4220), + DICO(0x23dc8cc0), DICO(0x27016200), DICO(0x2a9a5240), DICO(0x2e6cc7c0), + DICO(0x321ced40), DICO(0x38ca2d00), DICO(0x41482680), DICO(0x451e3700), + DICO(0x4b90d800), DICO(0x50d0ba80), DICO(0x55602e80), DICO(0x5a465200), + DICO(0x03ca7e28), DICO(0x057c9dd0), DICO(0x0c9ff0e0), DICO(0x1957fae0), + DICO(0x1fef7860), DICO(0x27920c80), DICO(0x2cb233c0), DICO(0x32015c80), + DICO(0x36af4f40), DICO(0x3ac18240), DICO(0x3f93d8c0), DICO(0x44eaef80), + DICO(0x4aab5d80), DICO(0x50840e80), DICO(0x56c4cc80), DICO(0x5cb26600), + DICO(0x038d53f8), DICO(0x050d1118), DICO(0x0bc14690), DICO(0x18918000), + DICO(0x1e2a6ee0), DICO(0x24cc0c00), DICO(0x2a767d40), DICO(0x2e614940), + DICO(0x32859c40), DICO(0x377fd940), DICO(0x3d3a3e40), DICO(0x43e81380), + DICO(0x4aaac080), DICO(0x509e7800), DICO(0x57023a00), DICO(0x5d733c00), + DICO(0x04cfa5e0), DICO(0x06deeb38), DICO(0x0a501c40), DICO(0x136d8aa0), + DICO(0x17f16e40), DICO(0x1c119300), DICO(0x26154b00), DICO(0x2a0da100), + DICO(0x2f5935c0), DICO(0x37108d40), DICO(0x3aef07c0), DICO(0x3fccf340), + DICO(0x47e4a080), DICO(0x4d8de100), DICO(0x54eb6980), DICO(0x5cdb5380)}; + +/* ACELP: table for decoding + adaptive codebook gain g_p (left column). Scaled by 2.0f. + innovative codebook gain g_c (right column). Scaled by 16.0f. +*/ +const FIXP_SGL fdk_t_qua_gain7b[128 * 2] = { + 204, 441, 464, 1977, 869, 1077, 1072, 3062, 1281, 4759, 1647, + 1539, 1845, 7020, 1853, 634, 1995, 2336, 2351, 15400, 2661, 1165, + 2702, 3900, 2710, 10133, 3195, 1752, 3498, 2624, 3663, 849, 3984, + 5697, 4214, 3399, 4415, 1304, 4695, 2056, 5376, 4558, 5386, 676, + 5518, 23554, 5567, 7794, 5644, 3061, 5672, 1513, 5957, 2338, 6533, + 1060, 6804, 5998, 6820, 1767, 6937, 3837, 7277, 414, 7305, 2665, + 7466, 11304, 7942, 794, 8007, 1982, 8007, 1366, 8326, 3105, 8336, + 4810, 8708, 7954, 8989, 2279, 9031, 1055, 9247, 3568, 9283, 1631, + 9654, 6311, 9811, 2605, 10120, 683, 10143, 4179, 10245, 1946, 10335, + 1218, 10468, 9960, 10651, 3000, 10951, 1530, 10969, 5290, 11203, 2305, + 11325, 3562, 11771, 6754, 11839, 1849, 11941, 4495, 11954, 1298, 11975, + 15223, 11977, 883, 11986, 2842, 12438, 2141, 12593, 3665, 12636, 8367, + 12658, 1594, 12886, 2628, 12984, 4942, 13146, 1115, 13224, 524, 13341, + 3163, 13399, 1923, 13549, 5961, 13606, 1401, 13655, 2399, 13782, 3909, + 13868, 10923, 14226, 1723, 14232, 2939, 14278, 7528, 14439, 4598, 14451, + 984, 14458, 2265, 14792, 1403, 14818, 3445, 14899, 5709, 15017, 15362, + 15048, 1946, 15069, 2655, 15405, 9591, 15405, 4079, 15570, 7183, 15687, + 2286, 15691, 1624, 15699, 3068, 15772, 5149, 15868, 1205, 15970, 696, + 16249, 3584, 16338, 1917, 16424, 2560, 16483, 4438, 16529, 6410, 16620, + 11966, 16839, 8780, 17030, 3050, 17033, 18325, 17092, 1568, 17123, 5197, + 17351, 2113, 17374, 980, 17566, 26214, 17609, 3912, 17639, 32767, 18151, + 7871, 18197, 2516, 18202, 5649, 18679, 3283, 18930, 1370, 19271, 13757, + 19317, 4120, 19460, 1973, 19654, 10018, 19764, 6792, 19912, 5135, 20040, + 2841, 21234, 19833}; + +/* ACELP: factor table for interpolation of LPC coeffs in LSP domain */ +const FIXP_SGL lsp_interpol_factor[2][NB_SUBFR] = { + {FL2FXCONST_SGL(0.125f), FL2FXCONST_SGL(0.375f), FL2FXCONST_SGL(0.625f), + FL2FXCONST_SGL(0.875f)}, /* for coreCoderFrameLength = 1024 */ + {FL2FXCONST_SGL(0.166667f), FL2FXCONST_SGL(0.5f), FL2FXCONST_SGL(0.833333f), + 0x0} /* for coreCoderFrameLength = 768 */ +}; + +/* For bass post filter */ +#ifndef TABLE_filt_lp +const FIXP_SGL fdk_dec_filt_lp[1 + L_FILT] = { + FL2FXCONST_SGL_FILT(0.088250f), FL2FXCONST_SGL_FILT(0.086410f), + FL2FXCONST_SGL_FILT(0.081074f), FL2FXCONST_SGL_FILT(0.072768f), + FL2FXCONST_SGL_FILT(0.062294f), FL2FXCONST_SGL_FILT(0.050623f), + FL2FXCONST_SGL_FILT(0.038774f), FL2FXCONST_SGL_FILT(0.027692f), + FL2FXCONST_SGL_FILT(0.018130f), FL2FXCONST_SGL_FILT(0.010578f), + FL2FXCONST_SGL_FILT(0.005221f), FL2FXCONST_SGL_FILT(0.001946f), + FL2FXCONST_SGL_FILT(0.000385f)}; +#endif + +/* FAC window tables for coreCoderFrameLength = 1024 */ +const FIXP_WTB FacWindowSynth128[] = { + WTC(0x7fff6216), WTC(0x7ffa72d1), WTC(0x7ff09478), WTC(0x7fe1c76b), + WTC(0x7fce0c3e), WTC(0x7fb563b3), WTC(0x7f97cebd), WTC(0x7f754e80), + WTC(0x7f4de451), WTC(0x7f2191b4), WTC(0x7ef05860), WTC(0x7eba3a39), + WTC(0x7e7f3957), WTC(0x7e3f57ff), WTC(0x7dfa98a8), WTC(0x7db0fdf8), + WTC(0x7d628ac6), WTC(0x7d0f4218), WTC(0x7cb72724), WTC(0x7c5a3d50), + WTC(0x7bf88830), WTC(0x7b920b89), WTC(0x7b26cb4f), WTC(0x7ab6cba4), + WTC(0x7a4210d8), WTC(0x79c89f6e), WTC(0x794a7c12), WTC(0x78c7aba2), + WTC(0x78403329), WTC(0x77b417df), WTC(0x77235f2d), WTC(0x768e0ea6), + WTC(0x75f42c0b), WTC(0x7555bd4c), WTC(0x74b2c884), WTC(0x740b53fb), + WTC(0x735f6626), WTC(0x72af05a7), WTC(0x71fa3949), WTC(0x71410805), + WTC(0x708378ff), WTC(0x6fc19385), WTC(0x6efb5f12), WTC(0x6e30e34a), + WTC(0x6d6227fa), WTC(0x6c8f351c), WTC(0x6bb812d1), WTC(0x6adcc964), + WTC(0x69fd614a), WTC(0x6919e320), WTC(0x683257ab), WTC(0x6746c7d8), + WTC(0x66573cbb), WTC(0x6563bf92), WTC(0x646c59bf), WTC(0x637114cc), + WTC(0x6271fa69), WTC(0x616f146c), WTC(0x60686ccf), WTC(0x5f5e0db3), + WTC(0x5e50015d), WTC(0x5d3e5237), WTC(0x5c290acc), WTC(0x5b1035cf), + WTC(0x59f3de12), WTC(0x58d40e8c), WTC(0x57b0d256), WTC(0x568a34a9), + WTC(0x556040e2), WTC(0x5433027d), WTC(0x53028518), WTC(0x51ced46e), + WTC(0x5097fc5e), WTC(0x4f5e08e3), WTC(0x4e210617), WTC(0x4ce10034), + WTC(0x4b9e0390), WTC(0x4a581c9e), WTC(0x490f57ee), WTC(0x47c3c22f), + WTC(0x46756828), WTC(0x452456bd), WTC(0x43d09aed), WTC(0x427a41d0), + WTC(0x4121589b), WTC(0x3fc5ec98), WTC(0x3e680b2c), WTC(0x3d07c1d6), + WTC(0x3ba51e29), WTC(0x3a402dd2), WTC(0x38d8fe93), WTC(0x376f9e46), + WTC(0x36041ad9), WTC(0x34968250), WTC(0x3326e2c3), WTC(0x31b54a5e), + WTC(0x3041c761), WTC(0x2ecc681e), WTC(0x2d553afc), WTC(0x2bdc4e6f), + WTC(0x2a61b101), WTC(0x28e5714b), WTC(0x27679df4), WTC(0x25e845b6), + WTC(0x24677758), WTC(0x22e541af), WTC(0x2161b3a0), WTC(0x1fdcdc1b), + WTC(0x1e56ca1e), WTC(0x1ccf8cb3), WTC(0x1b4732ef), WTC(0x19bdcbf3), + WTC(0x183366e9), WTC(0x16a81305), WTC(0x151bdf86), WTC(0x138edbb1), + WTC(0x120116d5), WTC(0x1072a048), WTC(0x0ee38766), WTC(0x0d53db92), + WTC(0x0bc3ac35), WTC(0x0a3308bd), WTC(0x08a2009a), WTC(0x0710a345), + WTC(0x057f0035), WTC(0x03ed26e6), WTC(0x025b26d7), WTC(0x00c90f88), +}; +const FIXP_WTB FacWindowZir128[] = { + WTC(0x7f36f078), WTC(0x7da4d929), WTC(0x7c12d91a), WTC(0x7a80ffcb), + WTC(0x78ef5cbb), WTC(0x775dff66), WTC(0x75ccf743), WTC(0x743c53cb), + WTC(0x72ac246e), WTC(0x711c789a), WTC(0x6f8d5fb8), WTC(0x6dfee92b), + WTC(0x6c71244f), WTC(0x6ae4207a), WTC(0x6957ecfb), WTC(0x67cc9917), + WTC(0x6642340d), WTC(0x64b8cd11), WTC(0x6330734d), WTC(0x61a935e2), + WTC(0x602323e5), WTC(0x5e9e4c60), WTC(0x5d1abe51), WTC(0x5b9888a8), + WTC(0x5a17ba4a), WTC(0x5898620c), WTC(0x571a8eb5), WTC(0x559e4eff), + WTC(0x5423b191), WTC(0x52aac504), WTC(0x513397e2), WTC(0x4fbe389f), + WTC(0x4e4ab5a2), WTC(0x4cd91d3d), WTC(0x4b697db0), WTC(0x49fbe527), + WTC(0x489061ba), WTC(0x4727016d), WTC(0x45bfd22e), WTC(0x445ae1d7), + WTC(0x42f83e2a), WTC(0x4197f4d4), WTC(0x403a1368), WTC(0x3edea765), + WTC(0x3d85be30), WTC(0x3c2f6513), WTC(0x3adba943), WTC(0x398a97d8), + WTC(0x383c3dd1), WTC(0x36f0a812), WTC(0x35a7e362), WTC(0x3461fc70), + WTC(0x331effcc), WTC(0x31def9e9), WTC(0x30a1f71d), WTC(0x2f6803a2), + WTC(0x2e312b92), WTC(0x2cfd7ae8), WTC(0x2bccfd83), WTC(0x2a9fbf1e), + WTC(0x2975cb57), WTC(0x284f2daa), WTC(0x272bf174), WTC(0x260c21ee), + WTC(0x24efca31), WTC(0x23d6f534), WTC(0x22c1adc9), WTC(0x21affea3), + WTC(0x20a1f24d), WTC(0x1f979331), WTC(0x1e90eb94), WTC(0x1d8e0597), + WTC(0x1c8eeb34), WTC(0x1b93a641), WTC(0x1a9c406e), WTC(0x19a8c345), + WTC(0x18b93828), WTC(0x17cda855), WTC(0x16e61ce0), WTC(0x16029eb6), + WTC(0x1523369c), WTC(0x1447ed2f), WTC(0x1370cae4), WTC(0x129dd806), + WTC(0x11cf1cb6), WTC(0x1104a0ee), WTC(0x103e6c7b), WTC(0x0f7c8701), + WTC(0x0ebef7fb), WTC(0x0e05c6b7), WTC(0x0d50fa59), WTC(0x0ca099da), + WTC(0x0bf4ac05), WTC(0x0b4d377c), WTC(0x0aaa42b4), WTC(0x0a0bd3f5), + WTC(0x0971f15a), WTC(0x08dca0d3), WTC(0x084be821), WTC(0x07bfccd7), + WTC(0x0738545e), WTC(0x06b583ee), WTC(0x06376092), WTC(0x05bdef28), + WTC(0x0549345c), WTC(0x04d934b1), WTC(0x046df477), WTC(0x040777d0), + WTC(0x03a5c2b0), WTC(0x0348d8dc), WTC(0x02f0bde8), WTC(0x029d753a), + WTC(0x024f0208), WTC(0x02056758), WTC(0x01c0a801), WTC(0x0180c6a9), + WTC(0x0145c5c7), WTC(0x010fa7a0), WTC(0x00de6e4c), WTC(0x00b21baf), + WTC(0x008ab180), WTC(0x00683143), WTC(0x004a9c4d), WTC(0x0031f3c2), + WTC(0x001e3895), WTC(0x000f6b88), WTC(0x00058d2f), WTC(0x00009dea), +}; +const FIXP_WTB FacWindowSynth64[] = { + WTC(0x7ffd885a), WTC(0x7fe9cbc0), WTC(0x7fc25596), WTC(0x7f872bf3), + WTC(0x7f3857f6), WTC(0x7ed5e5c6), WTC(0x7e5fe493), WTC(0x7dd6668f), + WTC(0x7d3980ec), WTC(0x7c894bde), WTC(0x7bc5e290), WTC(0x7aef6323), + WTC(0x7a05eead), WTC(0x7909a92d), WTC(0x77fab989), WTC(0x76d94989), + WTC(0x75a585cf), WTC(0x745f9dd1), WTC(0x7307c3d0), WTC(0x719e2cd2), + WTC(0x7023109a), WTC(0x6e96a99d), WTC(0x6cf934fc), WTC(0x6b4af279), + WTC(0x698c246c), WTC(0x67bd0fbd), WTC(0x65ddfbd3), WTC(0x63ef3290), + WTC(0x61f1003f), WTC(0x5fe3b38d), WTC(0x5dc79d7c), WTC(0x5b9d1154), + WTC(0x59646498), WTC(0x571deefa), WTC(0x54ca0a4b), WTC(0x5269126e), + WTC(0x4ffb654d), WTC(0x4d8162c4), WTC(0x4afb6c98), WTC(0x4869e665), + WTC(0x45cd358f), WTC(0x4325c135), WTC(0x4073f21d), WTC(0x3db832a6), + WTC(0x3af2eeb7), WTC(0x382493b0), WTC(0x354d9057), WTC(0x326e54c7), + WTC(0x2f875262), WTC(0x2c98fbba), WTC(0x29a3c485), WTC(0x26a82186), + WTC(0x23a6887f), WTC(0x209f701c), WTC(0x1d934fe5), WTC(0x1a82a026), + WTC(0x176dd9de), WTC(0x145576b1), WTC(0x1139f0cf), WTC(0x0e1bc2e4), + WTC(0x0afb6805), WTC(0x07d95b9e), WTC(0x04b6195d), WTC(0x01921d20), +}; +const FIXP_WTB FacWindowZir64[] = { + WTC(0x7e6de2e0), WTC(0x7b49e6a3), WTC(0x7826a462), WTC(0x750497fb), + WTC(0x71e43d1c), WTC(0x6ec60f31), WTC(0x6baa894f), WTC(0x68922622), + WTC(0x657d5fda), WTC(0x626cb01b), WTC(0x5f608fe4), WTC(0x5c597781), + WTC(0x5957de7a), WTC(0x565c3b7b), WTC(0x53670446), WTC(0x5078ad9e), + WTC(0x4d91ab39), WTC(0x4ab26fa9), WTC(0x47db6c50), WTC(0x450d1149), + WTC(0x4247cd5a), WTC(0x3f8c0de3), WTC(0x3cda3ecb), WTC(0x3a32ca71), + WTC(0x3796199b), WTC(0x35049368), WTC(0x327e9d3c), WTC(0x30049ab3), + WTC(0x2d96ed92), WTC(0x2b35f5b5), WTC(0x28e21106), WTC(0x269b9b68), + WTC(0x2462eeac), WTC(0x22386284), WTC(0x201c4c73), WTC(0x1e0effc1), + WTC(0x1c10cd70), WTC(0x1a22042d), WTC(0x1842f043), WTC(0x1673db94), + WTC(0x14b50d87), WTC(0x1306cb04), WTC(0x11695663), WTC(0x0fdcef66), + WTC(0x0e61d32e), WTC(0x0cf83c30), WTC(0x0ba0622f), WTC(0x0a5a7a31), + WTC(0x0926b677), WTC(0x08054677), WTC(0x06f656d3), WTC(0x05fa1153), + WTC(0x05109cdd), WTC(0x043a1d70), WTC(0x0376b422), WTC(0x02c67f14), + WTC(0x02299971), WTC(0x01a01b6d), WTC(0x012a1a3a), WTC(0x00c7a80a), + WTC(0x0078d40d), WTC(0x003daa6a), WTC(0x00163440), WTC(0x000277a6), +}; +const FIXP_WTB FacWindowSynth32[] = { + WTC(0x7ff62182), WTC(0x7fa736b4), WTC(0x7f0991c4), WTC(0x7e1d93ea), + WTC(0x7ce3ceb2), WTC(0x7b5d039e), WTC(0x798a23b1), WTC(0x776c4edb), + WTC(0x7504d345), WTC(0x72552c85), WTC(0x6f5f02b2), WTC(0x6c242960), + WTC(0x68a69e81), WTC(0x64e88926), WTC(0x60ec3830), WTC(0x5cb420e0), + WTC(0x5842dd54), WTC(0x539b2af0), WTC(0x4ebfe8a5), WTC(0x49b41533), + WTC(0x447acd50), WTC(0x3f1749b8), WTC(0x398cdd32), WTC(0x33def287), + WTC(0x2e110a62), WTC(0x2826b928), WTC(0x2223a4c5), WTC(0x1c0b826a), + WTC(0x15e21445), WTC(0x0fab272b), WTC(0x096a9049), WTC(0x03242abf), +}; +const FIXP_WTB FacWindowZir32[] = { + WTC(0x7cdbd541), WTC(0x76956fb7), WTC(0x7054d8d5), WTC(0x6a1debbb), + WTC(0x63f47d96), WTC(0x5ddc5b3b), WTC(0x57d946d8), WTC(0x51eef59e), + WTC(0x4c210d79), WTC(0x467322ce), WTC(0x40e8b648), WTC(0x3b8532b0), + WTC(0x364beacd), WTC(0x3140175b), WTC(0x2c64d510), WTC(0x27bd22ac), + WTC(0x234bdf20), WTC(0x1f13c7d0), WTC(0x1b1776da), WTC(0x1759617f), + WTC(0x13dbd6a0), WTC(0x10a0fd4e), WTC(0x0daad37b), WTC(0x0afb2cbb), + WTC(0x0893b125), WTC(0x0675dc4f), WTC(0x04a2fc62), WTC(0x031c314e), + WTC(0x01e26c16), WTC(0x00f66e3c), WTC(0x0058c94c), WTC(0x0009de7e), +}; + +/* FAC window tables for coreCoderFrameLength = 768 */ +const FIXP_WTB FacWindowSynth96[] = { + WTC(0x7ffee744), WTC(0x7ff62182), WTC(0x7fe49698), WTC(0x7fca47b9), + WTC(0x7fa736b4), WTC(0x7f7b65ef), WTC(0x7f46d86c), WTC(0x7f0991c4), + WTC(0x7ec3962a), WTC(0x7e74ea6a), WTC(0x7e1d93ea), WTC(0x7dbd98a4), + WTC(0x7d54ff2e), WTC(0x7ce3ceb2), WTC(0x7c6a0ef2), WTC(0x7be7c847), + WTC(0x7b5d039e), WTC(0x7ac9ca7a), WTC(0x7a2e26f2), WTC(0x798a23b1), + WTC(0x78ddcbf5), WTC(0x78292b8d), WTC(0x776c4edb), WTC(0x76a742d1), + WTC(0x75da14ef), WTC(0x7504d345), WTC(0x74278c72), WTC(0x73424fa0), + WTC(0x72552c85), WTC(0x71603361), WTC(0x706374ff), WTC(0x6f5f02b2), + WTC(0x6e52ee52), WTC(0x6d3f4a40), WTC(0x6c242960), WTC(0x6b019f1a), + WTC(0x69d7bf57), WTC(0x68a69e81), WTC(0x676e5183), WTC(0x662eedc3), + WTC(0x64e88926), WTC(0x639b3a0b), WTC(0x62471749), WTC(0x60ec3830), + WTC(0x5f8ab487), WTC(0x5e22a487), WTC(0x5cb420e0), WTC(0x5b3f42ae), + WTC(0x59c42381), WTC(0x5842dd54), WTC(0x56bb8a90), WTC(0x552e4605), + WTC(0x539b2af0), WTC(0x520254ef), WTC(0x5063e008), WTC(0x4ebfe8a5), + WTC(0x4d168b8b), WTC(0x4b67e5e4), WTC(0x49b41533), WTC(0x47fb3757), + WTC(0x463d6a87), WTC(0x447acd50), WTC(0x42b37e96), WTC(0x40e79d8c), + WTC(0x3f1749b8), WTC(0x3d42a2ec), WTC(0x3b69c947), WTC(0x398cdd32), + WTC(0x37abff5d), WTC(0x35c750bc), WTC(0x33def287), WTC(0x31f30638), + WTC(0x3003ad85), WTC(0x2e110a62), WTC(0x2c1b3efb), WTC(0x2a226db5), + WTC(0x2826b928), WTC(0x26284422), WTC(0x2427319d), WTC(0x2223a4c5), + WTC(0x201dc0ef), WTC(0x1e15a99a), WTC(0x1c0b826a), WTC(0x19ff6f2a), + WTC(0x17f193c5), WTC(0x15e21445), WTC(0x13d114d0), WTC(0x11beb9aa), + WTC(0x0fab272b), WTC(0x0d9681c2), WTC(0x0b80edf1), WTC(0x096a9049), + WTC(0x07538d6b), WTC(0x053c0a01), WTC(0x03242abf), WTC(0x010c1460), +}; +const FIXP_WTB FacWindowZir96[] = { + WTC(0x7ef3eba0), WTC(0x7cdbd541), WTC(0x7ac3f5ff), WTC(0x78ac7295), + WTC(0x76956fb7), WTC(0x747f120f), WTC(0x72697e3e), WTC(0x7054d8d5), + WTC(0x6e414656), WTC(0x6c2eeb30), WTC(0x6a1debbb), WTC(0x680e6c3b), + WTC(0x660090d6), WTC(0x63f47d96), WTC(0x61ea5666), WTC(0x5fe23f11), + WTC(0x5ddc5b3b), WTC(0x5bd8ce63), WTC(0x59d7bbde), WTC(0x57d946d8), + WTC(0x55dd924b), WTC(0x53e4c105), WTC(0x51eef59e), WTC(0x4ffc527b), + WTC(0x4e0cf9c8), WTC(0x4c210d79), WTC(0x4a38af44), WTC(0x485400a3), + WTC(0x467322ce), WTC(0x449636b9), WTC(0x42bd5d14), WTC(0x40e8b648), + WTC(0x3f186274), WTC(0x3d4c816a), WTC(0x3b8532b0), WTC(0x39c29579), + WTC(0x3804c8a9), WTC(0x364beacd), WTC(0x34981a1c), WTC(0x32e97475), + WTC(0x3140175b), WTC(0x2f9c1ff8), WTC(0x2dfdab11), WTC(0x2c64d510), + WTC(0x2ad1b9fb), WTC(0x29447570), WTC(0x27bd22ac), WTC(0x263bdc7f), + WTC(0x24c0bd52), WTC(0x234bdf20), WTC(0x21dd5b79), WTC(0x20754b79), + WTC(0x1f13c7d0), WTC(0x1db8e8b7), WTC(0x1c64c5f5), WTC(0x1b1776da), + WTC(0x19d1123d), WTC(0x1891ae7d), WTC(0x1759617f), WTC(0x162840a9), + WTC(0x14fe60e6), WTC(0x13dbd6a0), WTC(0x12c0b5c0), WTC(0x11ad11ae), + WTC(0x10a0fd4e), WTC(0x0f9c8b01), WTC(0x0e9fcc9f), WTC(0x0daad37b), + WTC(0x0cbdb060), WTC(0x0bd8738e), WTC(0x0afb2cbb), WTC(0x0a25eb11), + WTC(0x0958bd2f), WTC(0x0893b125), WTC(0x07d6d473), WTC(0x0722340b), + WTC(0x0675dc4f), WTC(0x05d1d90e), WTC(0x05363586), WTC(0x04a2fc62), + WTC(0x041837b9), WTC(0x0395f10e), WTC(0x031c314e), WTC(0x02ab00d2), + WTC(0x0242675c), WTC(0x01e26c16), WTC(0x018b1596), WTC(0x013c69d6), + WTC(0x00f66e3c), WTC(0x00b92794), WTC(0x00849a11), WTC(0x0058c94c), + WTC(0x0035b847), WTC(0x001b6968), WTC(0x0009de7e), WTC(0x000118bc), +}; +const FIXP_WTB FacWindowSynth48[] = { + WTC(0x7ffb9d15), WTC(0x7fd8878e), WTC(0x7f92661d), WTC(0x7f294bfd), + WTC(0x7e9d55fc), WTC(0x7deeaa7a), WTC(0x7d1d7958), WTC(0x7c29fbee), + WTC(0x7b1474fd), WTC(0x79dd3098), WTC(0x78848414), WTC(0x770acdec), + WTC(0x757075ac), WTC(0x73b5ebd1), WTC(0x71dba9ab), WTC(0x6fe2313c), + WTC(0x6dca0d14), WTC(0x6b93d02e), WTC(0x694015c3), WTC(0x66cf8120), + WTC(0x6442bd7e), WTC(0x619a7dce), WTC(0x5ed77c8a), WTC(0x5bfa7b82), + WTC(0x590443a7), WTC(0x55f5a4d2), WTC(0x52cf758f), WTC(0x4f9292dc), + WTC(0x4c3fdff4), WTC(0x48d84609), WTC(0x455cb40c), WTC(0x41ce1e65), + WTC(0x3e2d7eb1), WTC(0x3a7bd382), WTC(0x36ba2014), WTC(0x32e96c09), + WTC(0x2f0ac320), WTC(0x2b1f34eb), WTC(0x2727d486), WTC(0x2325b847), + WTC(0x1f19f97b), WTC(0x1b05b40f), WTC(0x16ea0646), WTC(0x12c8106f), + WTC(0x0ea0f48c), WTC(0x0a75d60e), WTC(0x0647d97c), WTC(0x02182427), +}; +const FIXP_WTB FacWindowZir48[] = { + WTC(0x7de7dbd9), WTC(0x79b82684), WTC(0x758a29f2), WTC(0x715f0b74), + WTC(0x6d37ef91), WTC(0x6915f9ba), WTC(0x64fa4bf1), WTC(0x60e60685), + WTC(0x5cda47b9), WTC(0x58d82b7a), WTC(0x54e0cb15), WTC(0x50f53ce0), + WTC(0x4d1693f7), WTC(0x4945dfec), WTC(0x45842c7e), WTC(0x41d2814f), + WTC(0x3e31e19b), WTC(0x3aa34bf4), WTC(0x3727b9f7), WTC(0x33c0200c), + WTC(0x306d6d24), WTC(0x2d308a71), WTC(0x2a0a5b2e), WTC(0x26fbbc59), + WTC(0x2405847e), WTC(0x21288376), WTC(0x1e658232), WTC(0x1bbd4282), + WTC(0x19307ee0), WTC(0x16bfea3d), WTC(0x146c2fd2), WTC(0x1235f2ec), + WTC(0x101dcec4), WTC(0x0e245655), WTC(0x0c4a142f), WTC(0x0a8f8a54), + WTC(0x08f53214), WTC(0x077b7bec), WTC(0x0622cf68), WTC(0x04eb8b03), + WTC(0x03d60412), WTC(0x02e286a8), WTC(0x02115586), WTC(0x0162aa04), + WTC(0x00d6b403), WTC(0x006d99e3), WTC(0x00277872), WTC(0x000462eb), +}; diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_rom.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_rom.h new file mode 100644 index 0000000000000..f969e907b6d96 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACdec/src/usacdec_rom.h @@ -0,0 +1,154 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): M. Jander + + Description: re8.h + +*******************************************************************************/ + +#ifndef USACDEC_ROM_H +#define USACDEC_ROM_H + +#include "common_fix.h" +#include "FDK_lpc.h" + +#include "usacdec_const.h" + +/* RE8 lattice quantiser constants */ +#define NB_SPHERE 32 +#define NB_LEADER 37 +#define NB_LDSIGN 226 +#define NB_LDQ3 9 +#define NB_LDQ4 28 + +#define LSF_SCALE 13 + +/* RE8 lattice quantiser tables */ +extern const UINT fdk_dec_tab_factorial[8]; +extern const UCHAR fdk_dec_Ia[NB_LEADER]; +extern const UCHAR fdk_dec_Ds[NB_LDSIGN]; +extern const USHORT fdk_dec_Is[NB_LDSIGN]; +extern const UCHAR fdk_dec_Ns[], fdk_dec_A3[], fdk_dec_A4[]; +extern const UCHAR fdk_dec_Da[][8]; +extern const USHORT fdk_dec_I3[], fdk_dec_I4[]; + +/* temp float tables for LPC decoding */ +extern const FIXP_LPC fdk_dec_lsf_init[16]; +extern const FIXP_LPC fdk_dec_dico_lsf_abs_8b[16 * 256]; + +/* ACELP tables */ +#define SF_QUA_GAIN7B 4 +extern const FIXP_SGL fdk_t_qua_gain7b[128 * 2]; +extern const FIXP_SGL lsp_interpol_factor[2][NB_SUBFR]; + +/* For bass post filter */ +#define L_FILT 12 /* Delay of up-sampling filter */ + +extern const FIXP_SGL fdk_dec_filt_lp[1 + L_FILT]; + +extern const FIXP_WTB FacWindowSynth128[128]; +extern const FIXP_WTB FacWindowZir128[128]; +extern const FIXP_WTB FacWindowSynth64[64]; +extern const FIXP_WTB FacWindowZir64[64]; +extern const FIXP_WTB FacWindowSynth32[32]; +extern const FIXP_WTB FacWindowZir32[32]; +extern const FIXP_WTB FacWindowSynth96[96]; +extern const FIXP_WTB FacWindowZir96[96]; +extern const FIXP_WTB FacWindowSynth48[48]; +extern const FIXP_WTB FacWindowZir48[48]; + +#endif /* USACDEC_ROM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/include/aacenc_lib.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/include/aacenc_lib.h new file mode 100644 index 0000000000000..902ba118f4619 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/include/aacenc_lib.h @@ -0,0 +1,1709 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: + +*******************************************************************************/ + +/** + * \file aacenc_lib.h + * \brief FDK AAC Encoder library interface header file. + * +\mainpage Introduction + +\section Scope + +This document describes the high-level interface and usage of the ISO/MPEG-2/4 +AAC Encoder library developed by the Fraunhofer Institute for Integrated +Circuits (IIS). + +The library implements encoding on the basis of the MPEG-2 and MPEG-4 AAC +Low-Complexity standard, and depending on the library's configuration, MPEG-4 +High-Efficiency AAC v2 and/or AAC-ELD standard. + +All references to SBR (Spectral Band Replication) are only applicable to HE-AAC +or AAC-ELD versions of the library. All references to PS (Parametric Stereo) are +only applicable to HE-AAC v2 versions of the library. + +\section encBasics Encoder Basics + +This document can only give a rough overview about the ISO/MPEG-2 and ISO/MPEG-4 +AAC audio coding standard. To understand all the terms in this document, you are +encouraged to read the following documents. + +- ISO/IEC 13818-7 (MPEG-2 AAC), which defines the syntax of MPEG-2 AAC audio +bitstreams. +- ISO/IEC 14496-3 (MPEG-4 AAC, subparts 1 and 4), which defines the syntax of +MPEG-4 AAC audio bitstreams. +- Lutzky, Schuller, Gayer, Krämer, Wabnik, "A guideline to audio codec +delay", 116th AES Convention, May 8, 2004 + +MPEG Advanced Audio Coding is based on a time-to-frequency mapping of the +signal. The signal is partitioned into overlapping portions and transformed into +frequency domain. The spectral components are then quantized and coded. \n An +MPEG-2 or MPEG-4 AAC audio bitstream is composed of frames. Contrary to MPEG-1/2 +Layer-3 (mp3), the length of individual frames is not restricted to a fixed +number of bytes, but can take on any length between 1 and 768 bytes. + + +\page LIBUSE Library Usage + +\section InterfaceDescription API Files + +All API header files are located in the folder /include of the release package. +All header files are provided for usage in C/C++ programs. The AAC encoder +library API functions are located in aacenc_lib.h. + +\section CallingSequence Calling Sequence + +For encoding of ISO/MPEG-2/4 AAC bitstreams the following sequence is mandatory. +Input read and output write functions as well as the corresponding open and +close functions are left out, since they may be implemented differently +according to the user's specific requirements. The example implementation uses +file-based input/output. + +-# Call aacEncOpen() to allocate encoder instance with required \ref encOpen +"configuration". \code HANDLE_AACENCODER hAacEncoder = NULL; if ( (ErrorStatus = +aacEncOpen(&hAacEncoder,0,0)) != AACENC_OK ) { \endcode +-# Call aacEncoder_SetParam() for each parameter to be set. AOT, samplingrate, +channelMode, bitrate and transport type are \ref encParams "mandatory". \code +ErrorStatus = aacEncoder_SetParam(hAacEncoder, parameter, value); +\endcode +-# Call aacEncEncode() with NULL parameters to \ref encReconf "initialize" +encoder instance with present parameter set. \code ErrorStatus = +aacEncEncode(hAacEncoder, NULL, NULL, NULL, NULL); \endcode +-# Call aacEncInfo() to retrieve a configuration data block to be transmitted +out of band. This is required when using RFC3640 or RFC3016 like transport. +\code +AACENC_InfoStruct encInfo; +aacEncInfo(hAacEncoder, &encInfo); +\endcode +-# Encode input audio data in loop. +\code +do +{ +\endcode +Feed \ref feedInBuf "input buffer" with new audio data and provide input/output +\ref bufDes "arguments" to aacEncEncode(). \code ErrorStatus = +aacEncEncode(hAacEncoder, &inBufDesc, &outBufDesc, &inargs, &outargs); \endcode +Write \ref writeOutData "output data" to file or audio device. +\code +} while (ErrorStatus==AACENC_OK); +\endcode +-# Call aacEncClose() and destroy encoder instance. +\code +aacEncClose(&hAacEncoder); +\endcode + + +\section encOpen Encoder Instance Allocation + +The assignment of the aacEncOpen() function is very flexible and can be used in +the following way. +- If the amount of memory consumption is not an issue, the encoder instance can +be allocated for the maximum number of possible audio channels (for example 6 or +8) with the full functional range supported by the library. This is the default +open procedure for the AAC encoder if memory consumption does not need to be +minimized. \code aacEncOpen(&hAacEncoder,0,0) \endcode +- If the required MPEG-4 AOTs do not call for the full functional range of the +library, encoder modules can be allocated selectively. \verbatim +------------------------------------------------------ + AAC | SBR | PS | MD | FLAGS | value +-----+-----+-----+----+-----------------------+------- + X | - | - | - | (0x01) | 0x01 + X | X | - | - | (0x01|0x02) | 0x03 + X | X | X | - | (0x01|0x02|0x04) | 0x07 + X | - | - | X | (0x01 |0x10) | 0x11 + X | X | - | X | (0x01|0x02 |0x10) | 0x13 + X | X | X | X | (0x01|0x02|0x04|0x10) | 0x17 +------------------------------------------------------ + - AAC: Allocate AAC Core Encoder module. + - SBR: Allocate Spectral Band Replication module. + - PS: Allocate Parametric Stereo module. + - MD: Allocate Meta Data module within AAC encoder. +\endverbatim +\code aacEncOpen(&hAacEncoder,value,0) \endcode +- Specifying the maximum number of channels to be supported in the encoder +instance can be done as follows. + - For example allocate an encoder instance which supports 2 channels for all +supported AOTs. The library itself may be capable of encoding up to 6 or 8 +channels but in this example only 2 channel encoding is required and thus only +buffers for 2 channels are allocated to save data memory. \code +aacEncOpen(&hAacEncoder,0,2) \endcode + - Additionally the maximum number of supported channels in the SBR module can +be denoted separately.\n In this example the encoder instance provides a maximum +of 6 channels out of which up to 2 channels support SBR. This encoder instance +can produce for example 5.1 channel AAC-LC streams or stereo HE-AAC (v2) +streams. HE-AAC 5.1 multi channel is not possible since only 2 out of 6 channels +support SBR, which saves data memory. \code aacEncOpen(&hAacEncoder,0,6|(2<<8)) +\endcode \n + +\section bufDes Input/Output Arguments + +\subsection allocIOBufs Provide Buffer Descriptors +In the present encoder API, the input and output buffers are described with \ref +AACENC_BufDesc "buffer descriptors". This mechanism allows a flexible handling +of input and output buffers without impact to the actual encoding call. Optional +buffers are necessary e.g. for ancillary data, meta data input or additional +output buffers describing superframing data in DAB+ or DRM+.\n At least one +input buffer for audio input data and one output buffer for bitstream data must +be allocated. The input buffer size can be a user defined multiple of the number +of input channels. PCM input data will be copied from the user defined PCM +buffer to an internal input buffer and so input data can be less than one AAC +audio frame. The output buffer size should be 6144 bits per channel excluding +the LFE channel. If the output data does not fit into the provided buffer, an +AACENC_ERROR will be returned by aacEncEncode(). \code static INT_PCM +inputBuffer[8*2048]; static UCHAR ancillaryBuffer[50]; static +AACENC_MetaData metaDataSetup; static UCHAR outputBuffer[8192]; +\endcode + +All input and output buffer must be clustered in input and output buffer arrays. +\code +static void* inBuffer[] = { inputBuffer, ancillaryBuffer, &metaDataSetup +}; static INT inBufferIds[] = { IN_AUDIO_DATA, IN_ANCILLRY_DATA, +IN_METADATA_SETUP }; static INT inBufferSize[] = { sizeof(inputBuffer), +sizeof(ancillaryBuffer), sizeof(metaDataSetup) }; static INT inBufferElSize[] += { sizeof(INT_PCM), sizeof(UCHAR), sizeof(AACENC_MetaData) }; + +static void* outBuffer[] = { outputBuffer }; +static INT outBufferIds[] = { OUT_BITSTREAM_DATA }; +static INT outBufferSize[] = { sizeof(outputBuffer) }; +static INT outBufferElSize[] = { sizeof(UCHAR) }; +\endcode + +Allocate buffer descriptors +\code +AACENC_BufDesc inBufDesc; +AACENC_BufDesc outBufDesc; +\endcode + +Initialize input buffer descriptor +\code +inBufDesc.numBufs = sizeof(inBuffer)/sizeof(void*); +inBufDesc.bufs = (void**)&inBuffer; +inBufDesc.bufferIdentifiers = inBufferIds; +inBufDesc.bufSizes = inBufferSize; +inBufDesc.bufElSizes = inBufferElSize; +\endcode + +Initialize output buffer descriptor +\code +outBufDesc.numBufs = sizeof(outBuffer)/sizeof(void*); +outBufDesc.bufs = (void**)&outBuffer; +outBufDesc.bufferIdentifiers = outBufferIds; +outBufDesc.bufSizes = outBufferSize; +outBufDesc.bufElSizes = outBufferElSize; +\endcode + +\subsection argLists Provide Input/Output Argument Lists +The input and output arguments of an aacEncEncode() call are described in +argument structures. \code AACENC_InArgs inargs; AACENC_OutArgs outargs; +\endcode + +\section feedInBuf Feed Input Buffer +The input buffer should be handled as a modulo buffer. New audio data in the +form of pulse-code- modulated samples (PCM) must be read from external and be +fed to the input buffer depending on its fill level. The required sample bitrate +(represented by the data type INT_PCM which is 16, 24 or 32 bits wide) is fixed +and depends on library configuration (usually 16 bit). \code inargs.numInSamples ++= WAV_InputRead ( wavIn, &inputBuffer[inargs.numInSamples], + FDKmin(encInfo.inputChannels*encInfo.frameLength, + sizeof(inputBuffer) / + sizeof(INT_PCM)-inargs.numInSamples), + SAMPLE_BITS + ); +\endcode + +After the encoder's internal buffer is fed with incoming audio samples, and +aacEncEncode() processed the new input data, update/move remaining samples in +input buffer, simulating a modulo buffer: \code if (outargs.numInSamples>0) { + FDKmemmove( inputBuffer, + &inputBuffer[outargs.numInSamples], + sizeof(INT_PCM)*(inargs.numInSamples-outargs.numInSamples) ); + inargs.numInSamples -= outargs.numInSamples; +} +\endcode + +\section writeOutData Output Bitstream Data +If any AAC bitstream data is available, write it to output file or device as +follows. \code if (outargs.numOutBytes>0) { FDKfwrite(outputBuffer, +outargs.numOutBytes, 1, pOutFile); +} +\endcode + +\section cfgMetaData Meta Data Configuration + +If the present library is configured with Metadata support, it is possible to +insert meta data side info into the generated audio bitstream while encoding. + +To work with meta data the encoder instance has to be \ref encOpen "allocated" +with meta data support. The meta data mode must be configured with the +::AACENC_METADATA_MODE parameter and aacEncoder_SetParam() function. \code +aacEncoder_SetParam(hAacEncoder, AACENC_METADATA_MODE, 0-3); \endcode + +This configuration indicates how to embed meta data into bitstrem. Either no +insertion, MPEG or ETSI style. The meta data itself must be specified within the +meta data setup structure AACENC_MetaData. + +Changing one of the AACENC_MetaData setup parameters can be achieved from +outside the library within ::IN_METADATA_SETUP input buffer. There is no need to +supply meta data setup structure every frame. If there is no new meta setup data +available, the encoder uses the previous setup or the default configuration in +initial state. + +In general the audio compressor and limiter within the encoder library can be +configured with the ::AACENC_METADATA_DRC_PROFILE parameter +AACENC_MetaData::drc_profile and and AACENC_MetaData::comp_profile. +\n + +\section encReconf Encoder Reconfiguration + +The encoder library allows reconfiguration of the encoder instance with new +settings continuously between encoding frames. Each parameter to be changed must +be set with a single aacEncoder_SetParam() call. The internal status of each +parameter can be retrieved with an aacEncoder_GetParam() call.\n There is no +stand-alone reconfiguration function available. When parameters were modified +from outside the library, an internal control mechanism triggers the necessary +reconfiguration process which will be applied at the beginning of the following +aacEncEncode() call. This state can be observed from external via the +AACENC_INIT_STATUS and aacEncoder_GetParam() function. The reconfiguration +process can also be applied immediately when all parameters of an aacEncEncode() +call are NULL with a valid encoder handle.\n\n The internal reconfiguration +process can be controlled from extern with the following access. \code +aacEncoder_SetParam(hAacEncoder, AACENC_CONTROL_STATE, AACENC_CTRLFLAGS); +\endcode + + +\section encParams Encoder Parametrization + +All parameteres listed in ::AACENC_PARAM can be modified within an encoder +instance. + +\subsection encMandatory Mandatory Encoder Parameters +The following parameters must be specified when the encoder instance is +initialized. \code aacEncoder_SetParam(hAacEncoder, AACENC_AOT, value); +aacEncoder_SetParam(hAacEncoder, AACENC_BITRATE, value); +aacEncoder_SetParam(hAacEncoder, AACENC_SAMPLERATE, value); +aacEncoder_SetParam(hAacEncoder, AACENC_CHANNELMODE, value); +\endcode +Beyond that is an internal auto mode which preinitizializes the ::AACENC_BITRATE +parameter if the parameter was not set from extern. The bitrate depends on the +number of effective channels and sampling rate and is determined as follows. +\code +AAC-LC (AOT_AAC_LC): 1.5 bits per sample +HE-AAC (AOT_SBR): 0.625 bits per sample (dualrate sbr) +HE-AAC (AOT_SBR): 1.125 bits per sample (downsampled sbr) +HE-AAC v2 (AOT_PS): 0.5 bits per sample +\endcode + +\subsection channelMode Channel Mode Configuration +The input audio data is described with the ::AACENC_CHANNELMODE parameter in the +aacEncoder_SetParam() call. It is not possible to use the encoder instance with +a 'number of input channels' argument. Instead, the channelMode must be set as +follows. \code aacEncoder_SetParam(hAacEncoder, AACENC_CHANNELMODE, value); +\endcode The parameter is specified in ::CHANNEL_MODE and can be mapped from the +number of input channels in the following way. \code CHANNEL_MODE chMode = +MODE_INVALID; + +switch (nChannels) { + case 1: chMode = MODE_1; break; + case 2: chMode = MODE_2; break; + case 3: chMode = MODE_1_2; break; + case 4: chMode = MODE_1_2_1; break; + case 5: chMode = MODE_1_2_2; break; + case 6: chMode = MODE_1_2_2_1; break; + case 7: chMode = MODE_6_1; break; + case 8: chMode = MODE_7_1_BACK; break; + default: + chMode = MODE_INVALID; +} +return chMode; +\endcode + +\subsection peakbitrate Peak Bitrate Configuration +In AAC, the default bitreservoir configuration depends on the chosen bitrate per +frame and the number of effective channels. The size can be determined as below. +\f[ +bitreservoir = nEffChannels*6144 - (bitrate*framelength/samplerate) +\f] +Due to audio quality concerns it is not recommended to change the bitreservoir +size to a lower value than the default setting! However, for minimizing the +delay for streaming applications or for achieving a constant size of the +bitstream packages in each frame, it may be necessaray to limit the maximum bits +per frame size. This can be done with the ::AACENC_PEAK_BITRATE parameter. \code +aacEncoder_SetParam(hAacEncoder, AACENC_PEAK_BITRATE, value); +\endcode + +To achieve acceptable audio quality with a reduced bitreservoir size setting at +least 1000 bits per audio channel is recommended. For a multichannel audio file +with 5.1 channels the bitreservoir reduced to 5000 bits results in acceptable +audio quality. + + +\subsection vbrmode Variable Bitrate Mode +The variable bitrate (VBR) mode coding adapts the bit consumption to the +psychoacoustic requirements of the signal. The encoder ignores the user-defined +bit rate and selects a suitable pre-defined configuration based on the provided +AOT. The VBR mode 1 is tuned for HE-AACv2, for VBR mode 2, HE-AACv1 should be +used. VBR modes 3-5 should be used with Low-Complexity AAC. When encoding +AAC-ELD, the best mode is selected automatically. + +The bitrates given in the table are averages over time and different encoder +settings. They strongly depend on the type of audio signal. The VBR +configurations can be adjusted with the ::AACENC_BITRATEMODE encoder parameter. +\verbatim +----------------------------------------------- + VBR_MODE | Approx. Bitrate in kbps for stereo + | AAC-LC | AAC-ELD +----------+---------------+-------------------- + VBR_1 | 32 (HE-AACv2) | 48 + VBR_2 | 72 (HE-AACv1) | 56 + VBR_3 | 112 | 72 + VBR_4 | 148 | 148 + VBR_5 | 228 | 224 +-------------------------------------------- +\endverbatim +Note that these figures are valid for stereo encoding only. VBR modes 2-5 will +yield much lower bit rates when encoding single-channel input. For +configurations which are making use of downmix modules the AAC core channels +respectively downmix channels shall be considered. + +\subsection encQual Audio Quality Considerations +The default encoder configuration is suggested to be used. Encoder tools such as +TNS and PNS are activated by default and are internally controlled (see \ref +BEHAVIOUR_TOOLS). + +There is an additional quality parameter called ::AACENC_AFTERBURNER. In the +default configuration this quality switch is deactivated because it would cause +a workload increase which might be significant. If workload is not an issue in +the application we recommended to activate this feature. \code +aacEncoder_SetParam(hAacEncoder, AACENC_AFTERBURNER, 0/1); \endcode + +\subsection encELD ELD Auto Configuration Mode +For ELD configuration a so called auto configurator is available which +configures SBR and the SBR ratio by itself. The configurator is used when the +encoder parameter ::AACENC_SBR_MODE and ::AACENC_SBR_RATIO are not set +explicitly. + +Based on sampling rate and chosen bitrate a reasonable SBR configuration will be +used. \verbatim +------------------------------------------------------------------ + Sampling Rate | Total Bitrate | No. of | SBR | SBR Ratio + [kHz] | [bit/s] | Chan | | + | | | | +---------------+-----------------+--------+-----+----------------- + ]min, 16[ | min - max | 1 | off | --- +---------------+-----------------+--------------+----------------- + [16] | min - 27999 | 1 | on | downsampled SBR + | 28000 - max | 1 | off | --- +---------------+-----------------+--------------+----------------- + ]16 - 24] | min - 39999 | 1 | on | downsampled SBR + | 40000 - max | 1 | off | --- +---------------+-----------------+--------------+----------------- + ]24 - 32] | min - 27999 | 1 | on | dualrate SBR + | 28000 - 55999 | 1 | on | downsampled SBR + | 56000 - max | 1 | off | --- +---------------+-----------------+--------------+----------------- + ]32 - 44.1] | min - 63999 | 1 | on | dualrate SBR + | 64000 - max | 1 | off | --- +---------------+-----------------+--------------+----------------- + ]44.1 - 48] | min - 63999 | 1 | on | dualrate SBR + | 64000 - max | 1 | off | --- + | | | | +---------------+-----------------+--------+-----+----------------- + ]min, 16[ | min - max | 2 | off | --- +---------------+-----------------+--------------+----------------- + [16] | min - 31999 | 2 | on | downsampled SBR + | 32000 - 63999 | 2 | on | downsampled SBR + | 64000 - max | 2 | off | --- +---------------+-----------------+--------------+----------------- + ]16 - 24] | min - 47999 | 2 | on | downsampled SBR + | 48000 - 79999 | 2 | on | downsampled SBR + | 80000 - max | 2 | off | --- +---------------+-----------------+--------------+----------------- + ]24 - 32] | min - 31999 | 2 | on | dualrate SBR + | 32000 - 67999 | 2 | on | dualrate SBR + | 68000 - 95999 | 2 | on | downsampled SBR + | 96000 - max | 2 | off | --- +---------------+-----------------+--------------+----------------- + ]32 - 44.1] | min - 43999 | 2 | on | dualrate SBR + | 44000 - 127999 | 2 | on | dualrate SBR + | 128000 - max | 2 | off | --- +---------------+-----------------+--------------+----------------- + ]44.1 - 48] | min - 43999 | 2 | on | dualrate SBR + | 44000 - 127999 | 2 | on | dualrate SBR + | 128000 - max | 2 | off | --- + | | | +------------------------------------------------------------------ +\endverbatim + +\subsection encDsELD Reduced Delay (Downscaled) Mode +The downscaled mode of AAC-ELD reduces the algorithmic delay of AAC-ELD by +virtually increasing the sampling rate. When using the downscaled mode, the +bitrate should be increased for keeping the same audio quality level. For common +signals, the bitrate should be increased by 25% for a downscale factor of 2. + +Currently, downscaling factors 2 and 4 are supported. +To enable the downscaled mode in the encoder, the framelength parameter +AACENC_GRANULE_LENGTH must be set accordingly to 256 or 240 for a downscale +factor of 2 or 128 or 120 for a downscale factor of 4. The default values of 512 +or 480 mean that no downscaling is applied. \code +aacEncoder_SetParam(hAacEncoder, AACENC_GRANULE_LENGTH, 256); +aacEncoder_SetParam(hAacEncoder, AACENC_GRANULE_LENGTH, 128); +\endcode + +Downscaled bitstreams are fully backwards compatible. However, the legacy +decoder needs to support high sample rate, e.g. 96kHz. The signaled sampling +rate is multiplied by the downscale factor. Although not required, downscaling +should be applied when decoding downscaled bitstreams. It reduces CPU workload +and the output will have the same sampling rate as the input. In an ideal +configuration both encoder and decoder should run with the same downscale +factor. + +The following table shows approximate filter bank delays in ms for common +sampling rates(sr) at framesize(fs), and downscale factor(dsf), based on this +formula: \f[ 1000 * fs / (dsf * sr) \f] + +\verbatim +-------------------------------------- + | 512/2 | 512/4 | 480/2 | 480/4 +------+-------+-------+-------+------- +22050 | 17.41 | 8.71 | 16.33 | 8.16 +32000 | 12.00 | 6.00 | 11.25 | 5.62 +44100 | 8.71 | 4.35 | 8.16 | 4.08 +48000 | 8.00 | 4.00 | 7.50 | 3.75 +-------------------------------------- +\endverbatim + +\section audiochCfg Audio Channel Configuration +The MPEG standard refers often to the so-called Channel Configuration. This +Channel Configuration is used for a fixed Channel Mapping. The configurations +1-7 and 11,12,14 are predefined in MPEG standard and used for implicit +signalling within the encoded bitstream. For user defined Configurations the +Channel Configuration is set to 0 and the Channel Mapping must be explecitly +described with an appropriate Program Config Element. The present Encoder +implementation does not allow the user to configure this Channel Configuration +from extern. The Encoder implementation supports fixed Channel Modes which are +mapped to Channel Configuration as follow. \verbatim +---------------------------------------------------------------------------------------- + ChannelMode | ChCfg | Height | front_El | side_El | back_El | +lfe_El +-----------------------+-------+--------+---------------+----------+----------+--------- +MODE_1 | 1 | NORM | SCE | | | +MODE_2 | 2 | NORM | CPE | | | +MODE_1_2 | 3 | NORM | SCE, CPE | | | +MODE_1_2_1 | 4 | NORM | SCE, CPE | | SCE | +MODE_1_2_2 | 5 | NORM | SCE, CPE | | CPE | +MODE_1_2_2_1 | 6 | NORM | SCE, CPE | | CPE | +LFE MODE_1_2_2_2_1 | 7 | NORM | SCE, CPE, CPE | | CPE +| LFE MODE_6_1 | 11 | NORM | SCE, CPE | | CPE, +SCE | LFE MODE_7_1_BACK | 12 | NORM | SCE, CPE | | +CPE, CPE | LFE +-----------------------+-------+--------+---------------+----------+----------+--------- +MODE_7_1_TOP_FRONT | 14 | NORM | SCE, CPE | | CPE | +LFE | | TOP | CPE | | | +-----------------------+-------+--------+---------------+----------+----------+--------- +MODE_7_1_REAR_SURROUND | 0 | NORM | SCE, CPE | | CPE, CPE | +LFE MODE_7_1_FRONT_CENTER | 0 | NORM | SCE, CPE, CPE | | CPE +| LFE +---------------------------------------------------------------------------------------- +- NORM: Normal Height Layer. - TOP: Top Height Layer. - BTM: Bottom Height +Layer. +- SCE: Single Channel Element. - CPE: Channel Pair. - LFE: Low Frequency +Element. \endverbatim + +The Table describes all fixed Channel Elements for each Channel Mode which are +assigned to a speaker arrangement. The arrangement includes front, side, back +and lfe Audio Channel Elements in the normal height layer, possibly followed by +front, side, and back elements in the top and bottom layer (Channel +Configuration 14). \n This mapping of Audio Channel Elements is defined in MPEG +standard for Channel Config 1-7 and 11,12,14.\n In case of Channel Config 0 or +writing matrix mixdown coefficients, the encoder enables the writing of Program +Config Element itself as described in \ref encPCE. The configuration used in +Program Config Element refers to the denoted Table.\n Beside the Channel Element +assignment the Channel Modes are resposible for audio input data channel +mapping. The Channel Mapping of the audio data depends on the selected +::AACENC_CHANNELORDER which can be MPEG or WAV like order.\n Following table +describes the complete channel mapping for both Channel Order configurations. +\verbatim +--------------------------------------------------------------------------------------- +ChannelMode | MPEG-Channelorder | WAV-Channelorder +-----------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--- +MODE_1 | 0 | | | | | | | | 0 | | | | | | +| MODE_2 | 0 | 1 | | | | | | | 0 | 1 | | | | +| | MODE_1_2 | 0 | 1 | 2 | | | | | | 2 | 0 | 1 | | +| | | MODE_1_2_1 | 0 | 1 | 2 | 3 | | | | | 2 | 0 | 1 | 3 +| | | | MODE_1_2_2 | 0 | 1 | 2 | 3 | 4 | | | | 2 | 0 | 1 +| 3 | 4 | | | MODE_1_2_2_1 | 0 | 1 | 2 | 3 | 4 | 5 | | | 2 | 0 +| 1 | 4 | 5 | 3 | | MODE_1_2_2_2_1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2 +| 6 | 7 | 0 | 1 | 4 | 5 | 3 MODE_6_1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | +| 2 | 0 | 1 | 4 | 5 | 6 | 3 | MODE_7_1_BACK | 0 | 1 | 2 | 3 | 4 | 5 | 6 +| 7 | 2 | 0 | 1 | 6 | 7 | 4 | 5 | 3 MODE_7_1_TOP_FRONT | 0 | 1 | 2 | 3 | 4 | +5 | 6 | 7 | 2 | 0 | 1 | 4 | 5 | 3 | 6 | 7 +-----------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--- +MODE_7_1_REAR_SURROUND | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2 | 0 | 1 | 6 | 7 | 4 | +5 | 3 MODE_7_1_FRONT_CENTER | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2 | 6 | 7 | 0 | 1 +| 4 | 5 | 3 +--------------------------------------------------------------------------------------- +\endverbatim + +The denoted mapping is important for correct audio channel assignment when using +MPEG or WAV ordering. The incoming audio channels are distributed MPEG like +starting at the front channels and ending at the back channels. The distribution +is used as described in Table concering Channel Config and fix channel elements. +Please see the following example for clarification. + +\verbatim +Example: MODE_1_2_2_1 - WAV-Channelorder 5.1 +------------------------------------------ + Input Channel | Coder Channel +--------------------+--------------------- + 2 (front center) | 0 (SCE channel) + 0 (left center) | 1 (1st of 1st CPE) + 1 (right center) | 2 (2nd of 1st CPE) + 4 (left surround) | 3 (1st of 2nd CPE) + 5 (right surround) | 4 (2nd of 2nd CPE) + 3 (LFE) | 5 (LFE) +------------------------------------------ +\endverbatim + + +\section suppBitrates Supported Bitrates + +The FDK AAC Encoder provides a wide range of supported bitrates. +The minimum and maximum allowed bitrate depends on the Audio Object Type. For +AAC-LC the minimum bitrate is the bitrate that is required to write the most +basic and minimal valid bitstream. It consists of the bitstream format header +information and other static/mandatory information within the AAC payload. The +maximum AAC framesize allowed by the MPEG-4 standard determines the maximum +allowed bitrate for AAC-LC. For HE-AAC and HE-AAC v2 a library internal look-up +table is used. + +A good working point in terms of audio quality, sampling rate and bitrate, is at +1 to 1.5 bits/audio sample for AAC-LC, 0.625 bits/audio sample for dualrate +HE-AAC, 1.125 bits/audio sample for downsampled HE-AAC and 0.5 bits/audio sample +for HE-AAC v2. For example for one channel with a sampling frequency of 48 kHz, +the range from 48 kbit/s to 72 kbit/s achieves reasonable audio quality for +AAC-LC. + +For HE-AAC and HE-AAC v2 the lowest possible audio input sampling frequency is +16 kHz because then the AAC-LC core encoder operates in dual rate mode at its +lowest possible sampling frequency, which is 8 kHz. HE-AAC v2 requires stereo +input audio data. + +Please note that in HE-AAC or HE-AAC v2 mode the encoder supports much higher +bitrates than are appropriate for HE-AAC or HE-AAC v2. For example, at a bitrate +of more than 64 kbit/s for a stereo audio signal at 44.1 kHz it usually makes +sense to use AAC-LC, which will produce better audio quality at that bitrate +than HE-AAC or HE-AAC v2. + +\section reommendedConfig Recommended Sampling Rate and Bitrate Combinations + +The following table provides an overview of recommended encoder configuration +parameters which we determined by virtue of numerous listening tests. + +\subsection reommendedConfigLC AAC-LC, HE-AAC, HE-AACv2 in Dualrate SBR mode. +\verbatim +----------------------------------------------------------------------------------- +Audio Object Type | Bit Rate Range | Supported | Preferred | No. +of | [bit/s] | Sampling Rates | Sampl. | Chan. | +| [kHz] | Rate | | | +| [kHz] | +-------------------+------------------+-----------------------+------------+------- +AAC LC + SBR + PS | 8000 - 11999 | 22.05, 24.00 | 24.00 | 2 +AAC LC + SBR + PS | 12000 - 17999 | 32.00 | 32.00 | 2 +AAC LC + SBR + PS | 18000 - 39999 | 32.00, 44.10, 48.00 | 44.10 | 2 +AAC LC + SBR + PS | 40000 - 64000 | 32.00, 44.10, 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +AAC LC + SBR | 8000 - 11999 | 22.05, 24.00 | 24.00 | 1 +AAC LC + SBR | 12000 - 17999 | 32.00 | 32.00 | 1 +AAC LC + SBR | 18000 - 39999 | 32.00, 44.10, 48.00 | 44.10 | 1 +AAC LC + SBR | 40000 - 64000 | 32.00, 44.10, 48.00 | 48.00 | 1 +-------------------+------------------+-----------------------+------------+------- +AAC LC + SBR | 16000 - 27999 | 32.00, 44.10, 48.00 | 32.00 | 2 +AAC LC + SBR | 28000 - 63999 | 32.00, 44.10, 48.00 | 44.10 | 2 +AAC LC + SBR | 64000 - 128000 | 32.00, 44.10, 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +AAC LC + SBR | 64000 - 69999 | 32.00, 44.10, 48.00 | 32.00 | +5, 5.1 AAC LC + SBR | 70000 - 239999 | 32.00, 44.10, 48.00 | 44.10 +| 5, 5.1 AAC LC + SBR | 240000 - 319999 | 32.00, 44.10, 48.00 | +48.00 | 5, 5.1 +-------------------+------------------+-----------------------+------------+------- +AAC LC | 8000 - 15999 | 11.025, 12.00, 16.00 | 12.00 | 1 +AAC LC | 16000 - 23999 | 16.00 | 16.00 | 1 +AAC LC | 24000 - 31999 | 16.00, 22.05, 24.00 | 24.00 | 1 +AAC LC | 32000 - 55999 | 32.00 | 32.00 | 1 +AAC LC | 56000 - 160000 | 32.00, 44.10, 48.00 | 44.10 | 1 +AAC LC | 160001 - 288000 | 48.00 | 48.00 | 1 +-------------------+------------------+-----------------------+------------+------- +AAC LC | 16000 - 23999 | 11.025, 12.00, 16.00 | 12.00 | 2 +AAC LC | 24000 - 31999 | 16.00 | 16.00 | 2 +AAC LC | 32000 - 39999 | 16.00, 22.05, 24.00 | 22.05 | 2 +AAC LC | 40000 - 95999 | 32.00 | 32.00 | 2 +AAC LC | 96000 - 111999 | 32.00, 44.10, 48.00 | 32.00 | 2 +AAC LC | 112000 - 320001 | 32.00, 44.10, 48.00 | 44.10 | 2 +AAC LC | 320002 - 576000 | 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +AAC LC | 160000 - 239999 | 32.00 | 32.00 | +5, 5.1 AAC LC | 240000 - 279999 | 32.00, 44.10, 48.00 | 32.00 +| 5, 5.1 AAC LC | 280000 - 800000 | 32.00, 44.10, 48.00 | +44.10 | 5, 5.1 +----------------------------------------------------------------------------------- +\endverbatim \n + +\subsection reommendedConfigLD AAC-LD, AAC-ELD, AAC-ELD with SBR in Dualrate SBR +mode. Unlike to HE-AAC configuration the SBR is not covered by ELD audio object +type and needs to be enabled explicitly. Use ::AACENC_SBR_MODE to configure SBR +and its samplingrate ratio with ::AACENC_SBR_RATIO parameter. \verbatim +----------------------------------------------------------------------------------- +Audio Object Type | Bit Rate Range | Supported | Preferred | No. +of | [bit/s] | Sampling Rates | Sampl. | Chan. | +| [kHz] | Rate | | | +| [kHz] | +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 18000 - 24999 | 32.00 - 44.10 | 32.00 | 1 +ELD + SBR | 25000 - 31999 | 32.00 - 48.00 | 32.00 | 1 +ELD + SBR | 32000 - 64000 | 32.00 - 48.00 | 48.00 | 1 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 32000 - 51999 | 32.00 - 48.00 | 44.10 | 2 +ELD + SBR | 52000 - 128000 | 32.00 - 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 78000 - 160000 | 32.00 - 48.00 | 48.00 | 3 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 104000 - 212000 | 32.00 - 48.00 | 48.00 | 4 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 130000 - 246000 | 32.00 - 48.00 | 48.00 | +5, 5.1 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 16000 - 19999 | 16.00 - 24.00 | 16.00 | 1 +LD, ELD | 20000 - 39999 | 16.00 - 32.00 | 24.00 | 1 +LD, ELD | 40000 - 49999 | 22.05 - 32.00 | 32.00 | 1 +LD, ELD | 50000 - 61999 | 24.00 - 44.10 | 32.00 | 1 +LD, ELD | 62000 - 84999 | 32.00 - 48.00 | 44.10 | 1 +LD, ELD | 85000 - 192000 | 44.10 - 48.00 | 48.00 | 1 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 64000 - 75999 | 24.00 - 32.00 | 32.00 | 2 +LD, ELD | 76000 - 97999 | 24.00 - 44.10 | 32.00 | 2 +LD, ELD | 98000 - 135999 | 32.00 - 48.00 | 44.10 | 2 +LD, ELD | 136000 - 384000 | 44.10 - 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 96000 - 113999 | 24.00 - 32.00 | 32.00 | 3 +LD, ELD | 114000 - 146999 | 24.00 - 44.10 | 32.00 | 3 +LD, ELD | 147000 - 203999 | 32.00 - 48.00 | 44.10 | 3 +LD, ELD | 204000 - 576000 | 44.10 - 48.00 | 48.00 | 3 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 128000 - 151999 | 24.00 - 32.00 | 32.00 | 4 +LD, ELD | 152000 - 195999 | 24.00 - 44.10 | 32.00 | 4 +LD, ELD | 196000 - 271999 | 32.00 - 48.00 | 44.10 | 4 +LD, ELD | 272000 - 768000 | 44.10 - 48.00 | 48.00 | 4 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 160000 - 189999 | 24.00 - 32.00 | 32.00 | +5, 5.1 LD, ELD | 190000 - 244999 | 24.00 - 44.10 | 32.00 +| 5, 5.1 LD, ELD | 245000 - 339999 | 32.00 - 48.00 | +44.10 | 5, 5.1 LD, ELD | 340000 - 960000 | 44.10 - 48.00 | +48.00 | 5, 5.1 +----------------------------------------------------------------------------------- +\endverbatim \n + +\subsection reommendedConfigELD AAC-ELD with SBR in Downsampled SBR mode. +\verbatim +----------------------------------------------------------------------------------- +Audio Object Type | Bit Rate Range | Supported | Preferred | No. +of | [bit/s] | Sampling Rates | Sampl. | Chan. | +| [kHz] | Rate | | | +| [kHz] | +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 18000 - 24999 | 16.00 - 22.05 | 22.05 | 1 +(downsampled SBR) | 25000 - 31999 | 16.00 - 24.00 | 24.00 | 1 + | 32000 - 47999 | 22.05 - 32.00 | 32.00 | 1 + | 48000 - 64000 | 22.05 - 48.00 | 32.00 | 1 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 32000 - 51999 | 16.00 - 24.00 | 24.00 | 2 +(downsampled SBR) | 52000 - 59999 | 22.05 - 24.00 | 24.00 | 2 + | 60000 - 95999 | 22.05 - 32.00 | 32.00 | 2 + | 96000 - 128000 | 22.05 - 48.00 | 32.00 | 2 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 78000 - 99999 | 22.05 - 24.00 | 24.00 | 3 +(downsampled SBR) | 100000 - 143999 | 22.05 - 32.00 | 32.00 | 3 + | 144000 - 159999 | 22.05 - 48.00 | 32.00 | 3 + | 160000 - 192000 | 32.00 - 48.00 | 32.00 | 3 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 104000 - 149999 | 22.05 - 24.00 | 24.00 | 4 +(downsampled SBR) | 150000 - 191999 | 22.05 - 32.00 | 32.00 | 4 + | 192000 - 211999 | 22.05 - 48.00 | 32.00 | 4 + | 212000 - 256000 | 32.00 - 48.00 | 32.00 | 4 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 130000 - 171999 | 22.05 - 24.00 | 24.00 | +5, 5.1 (downsampled SBR) | 172000 - 239999 | 22.05 - 32.00 | 32.00 +| 5, 5.1 | 240000 - 320000 | 32.00 - 48.00 | 32.00 | 5, 5.1 +----------------------------------------------------------------------------------- +\endverbatim \n + +\subsection reommendedConfigELDv2 AAC-ELD v2, AAC-ELD v2 with SBR. +The ELD v2 212 configuration must be configured explicitly with +::AACENC_CHANNELMODE parameter according MODE_212 value. SBR can be configured +separately through ::AACENC_SBR_MODE and ::AACENC_SBR_RATIO parameter. Following +configurations shall apply to both framelengths 480 and 512. For ELD v2 +configuration without SBR and framelength 480 the supported sampling rate is +restricted to the range from 16 kHz up to 24 kHz. \verbatim +----------------------------------------------------------------------------------- +Audio Object Type | Bit Rate Range | Supported | Preferred | No. +of | [bit/s] | Sampling Rates | Sampl. | Chan. | +| [kHz] | Rate | | | +| [kHz] | +-------------------+------------------+-----------------------+------------+------- +ELD-212 | 16000 - 19999 | 16.00 - 24.00 | 16.00 | 2 +(without SBR) | 20000 - 39999 | 16.00 - 32.00 | 24.00 | 2 + | 40000 - 49999 | 22.05 - 32.00 | 32.00 | 2 + | 50000 - 61999 | 24.00 - 44.10 | 32.00 | 2 + | 62000 - 84999 | 32.00 - 48.00 | 44.10 | 2 + | 85000 - 192000 | 44.10 - 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +ELD-212 + SBR | 18000 - 20999 | 32.00 | 32.00 | 2 +(dualrate SBR) | 21000 - 25999 | 32.00 - 44.10 | 32.00 | 2 + | 26000 - 31999 | 32.00 - 48.00 | 44.10 | 2 + | 32000 - 64000 | 32.00 - 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +ELD-212 + SBR | 18000 - 19999 | 16.00 - 22.05 | 22.05 | 2 +(downsampled SBR) | 20000 - 24999 | 16.00 - 24.00 | 22.05 | 2 + | 25000 - 31999 | 16.00 - 24.00 | 24.00 | 2 + | 32000 - 64000 | 24.00 - 24.00 | 24.00 | 2 +-------------------+------------------+-----------------------+------------+------- +\endverbatim \n + +\page ENCODERBEHAVIOUR Encoder Behaviour + +\section BEHAVIOUR_BANDWIDTH Bandwidth + +The FDK AAC encoder usually does not use the full frequency range of the input +signal, but restricts the bandwidth according to certain library-internal +settings. They can be changed in the table "bandWidthTable" in the file +bandwidth.cpp (if available). + +The encoder API provides the ::AACENC_BANDWIDTH parameter to adjust the +bandwidth explicitly. \code aacEncoder_SetParam(hAacEncoder, AACENC_BANDWIDTH, +value); \endcode + +However it is not recommended to change these settings, because they are based +on numerous listening tests and careful tweaks to ensure the best overall +encoding quality. Also, the maximum bandwidth that can be set manually by the +user is 20kHz or fs/2, whichever value is smaller. + +Theoretically a signal of for example 48 kHz can contain frequencies up to 24 +kHz, but to use this full range in an audio encoder usually does not make sense. +Usually the encoder has a very limited amount of bits to spend (typically 128 +kbit/s for stereo 48 kHz content) and to allow full range bandwidth would waste +a lot of these bits for frequencies the human ear is hardly able to perceive +anyway, if at all. Hence it is wise to use the available bits for the really +important frequency range and just skip the rest. At lower bitrates (e. g. <= 80 +kbit/s for stereo 48 kHz content) the encoder will choose an even smaller +bandwidth, because an encoded signal with smaller bandwidth and hence less +artifacts sounds better than a signal with higher bandwidth but then more coding +artefacts across all frequencies. These artefacts would occur if small bitrates +and high bandwidths are chosen because the available bits are just not enough to +encode all frequencies well. + +Unfortunately some people evaluate encoding quality based on possible bandwidth +as well, but it is a double-edged sword considering the trade-off described +above. + +Another aspect is workload consumption. The higher the allowed bandwidth, the +more frequency lines have to be processed, which in turn increases the workload. + +\section FRAMESIZES_AND_BIT_RESERVOIR Frame Sizes & Bit Reservoir + +For AAC there is a difference between constant bit rate and constant frame +length due to the so-called bit reservoir technique, which allows the encoder to +use less bits in an AAC frame for those audio signal sections which are easy to +encode, and then spend them at a later point in time for more complex audio +sections. The extent to which this "bit exchange" is done is limited to allow +for reliable and relatively low delay real time streaming. Therefore, for +AAC-ELD, the bitreservoir is limited. It varies between 500 and 4000 bits/frame, +depending on the bitrate/channel. +- For a bitrate of 12kbps/channel and below, the AAC-ELD bitreservoir is 500 +bits/frame. +- For a bitrate of 70kbps/channel and above, the AAC-ELD bitreservoir is 4000 +bits/frame. +- Between 12kbps/channel and 70kbps/channel, the AAC-ELD bitrervoir is increased +linearly. +- For AAC-LC, the bitrate is only limited by the maximum AAC frame length. It +is, regardless of the available bit reservoir, defined as 6144 bits per channel. + +Over a longer period in time the bitrate will be constant in the AAC constant +bitrate mode, e.g. for ISDN transmission. This means that in AAC each bitstream +frame will in general have a different length in bytes but over time it +will reach the target bitrate. + + +One could also make an MPEG compliant +AAC encoder which always produces constant length packages for each AAC frame, +but the audio quality would be considerably worse since the bit reservoir +technique would have to be switched off completely. A higher bit rate would have +to be used to get the same audio quality as with an enabled bit reservoir. + +For mp3 by the way, the same bit reservoir technique exists, but there each bit +stream frame has a constant length for a given bit rate (ignoring the +padding byte). In mp3 there is a so-called "back pointer" which tells +the decoder which bits belong to the current mp3 frame - and in general some or +many bits have been transmitted in an earlier mp3 frame. Basically this leads to +the same "bit exchange between mp3 frames" as in AAC but with virtually constant +length frames. + +This variable frame length at "constant bit rate" is not something special +in this Fraunhofer IIS AAC encoder. AAC has been designed in that way. + +\subsection BEHAVIOUR_ESTIM_AVG_FRAMESIZES Estimating Average Frame Sizes + +A HE-AAC v1 or v2 audio frame contains 2048 PCM samples per channel. + +The number of HE-AAC frames \f$N\_FRAMES\f$ per second at 44.1 kHz is: + +\f[ +N\_FRAMES = 44100 / 2048 = 21.5332 +\f] + +At a bit rate of 8 kbps the average number of bits per frame +\f$N\_BITS\_PER\_FRAME\f$ is: + +\f[ +N\_BITS\_PER\_FRAME = 8000 / 21.5332 = 371.52 +\f] + +which is about 46.44 bytes per encoded frame. + +At a bit rate of 32 kbps, which is quite high for single channel HE-AAC v1, it +is: + +\f[ +N\_BITS\_PER\_FRAME = 32000 / 21.5332 = 1486 +\f] + +which is about 185.76 bytes per encoded frame. + +These bits/frame figures are average figures where each AAC frame generally has +a different size in bytes. To calculate the same for AAC-LC just use 1024 +instead of 2048 PCM samples per frame and channel. For AAC-LD/ELD it is either +480 or 512 PCM samples per frame and channel. + + +\section BEHAVIOUR_TOOLS Encoder Tools + +The AAC encoder supports TNS, PNS, MS, Intensity and activates these tools +depending on the audio signal and the encoder configuration (i.e. bitrate or +AOT). It is not required to configure these tools manually. + +PNS improves encoding quality only for certain bitrates. Therefore it makes +sense to activate PNS only for these bitrates and save the processing power +required for PNS (about 10 % of the encoder) when using other bitrates. This is +done automatically inside the encoder library. PNS is disabled inside the +encoder library if an MPEG-2 AOT is choosen since PNS is an MPEG-4 AAC feature. + +If SBR is activated, the encoder automatically deactivates PNS internally. If +TNS is disabled but PNS is allowed, the encoder deactivates PNS calculation +internally. + +*/ + +#ifndef AACENC_LIB_H +#define AACENC_LIB_H + +#include "machine_type.h" +#include "FDK_audio.h" + +#define AACENCODER_LIB_VL0 4 +#define AACENCODER_LIB_VL1 0 +#define AACENCODER_LIB_VL2 1 + +/** + * AAC encoder error codes. + */ +typedef enum { + AACENC_OK = 0x0000, /*!< No error happened. All fine. */ + + AACENC_INVALID_HANDLE = + 0x0020, /*!< Handle passed to function call was invalid. */ + AACENC_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */ + AACENC_UNSUPPORTED_PARAMETER = 0x0022, /*!< Parameter not available. */ + AACENC_INVALID_CONFIG = 0x0023, /*!< Configuration not provided. */ + + AACENC_INIT_ERROR = 0x0040, /*!< General initialization error. */ + AACENC_INIT_AAC_ERROR = 0x0041, /*!< AAC library initialization error. */ + AACENC_INIT_SBR_ERROR = 0x0042, /*!< SBR library initialization error. */ + AACENC_INIT_TP_ERROR = 0x0043, /*!< Transport library initialization error. */ + AACENC_INIT_META_ERROR = + 0x0044, /*!< Meta data library initialization error. */ + AACENC_INIT_MPS_ERROR = 0x0045, /*!< MPS library initialization error. */ + + AACENC_ENCODE_ERROR = 0x0060, /*!< The encoding process was interrupted by an + unexpected error. */ + + AACENC_ENCODE_EOF = 0x0080 /*!< End of file reached. */ + +} AACENC_ERROR; + +/** + * AAC encoder buffer descriptors identifier. + * This identifier are used within buffer descriptors + * AACENC_BufDesc::bufferIdentifiers. + */ +typedef enum { + /* Input buffer identifier. */ + IN_AUDIO_DATA = 0, /*!< Audio input buffer, interleaved INT_PCM samples. */ + IN_ANCILLRY_DATA = 1, /*!< Ancillary data to be embedded into bitstream. */ + IN_METADATA_SETUP = 2, /*!< Setup structure for embedding meta data. */ + + /* Output buffer identifier. */ + OUT_BITSTREAM_DATA = 3, /*!< Buffer holds bitstream output data. */ + OUT_AU_SIZES = + 4 /*!< Buffer contains sizes of each access unit. This information + is necessary for superframing. */ + +} AACENC_BufferIdentifier; + +/** + * AAC encoder handle. + */ +typedef struct AACENCODER *HANDLE_AACENCODER; + +/** + * Provides some info about the encoder configuration. + */ +typedef struct { + UINT maxOutBufBytes; /*!< Maximum number of encoder bitstream bytes within one + frame. Size depends on maximum number of supported + channels in encoder instance. */ + + UINT maxAncBytes; /*!< Maximum number of ancillary data bytes which can be + inserted into bitstream within one frame. */ + + UINT inBufFillLevel; /*!< Internal input buffer fill level in samples per + channel. This parameter will automatically be cleared + if samplingrate or channel(Mode/Order) changes. */ + + UINT inputChannels; /*!< Number of input channels expected in encoding + process. */ + + UINT frameLength; /*!< Amount of input audio samples consumed each frame per + channel, depending on audio object type configuration. */ + + UINT nDelay; /*!< Codec delay in PCM samples/channel. Depends on framelength + and AOT. Does not include framing delay for filling up encoder + PCM input buffer. */ + + UINT nDelayCore; /*!< Codec delay in PCM samples/channel, w/o delay caused by + the decoder SBR module. This delay is needed to correctly + write edit lists for gapless playback. The decoder may not + know how much delay is introdcued by SBR, since it may not + know if SBR is active at all (implicit signaling), + therefore the decoder must take into account any delay + caused by the SBR module. */ + + UCHAR confBuf[64]; /*!< Configuration buffer in binary format as an + AudioSpecificConfig or StreamMuxConfig according to the + selected transport type. */ + + UINT confSize; /*!< Number of valid bytes in confBuf. */ + +} AACENC_InfoStruct; + +/** + * Describes the input and output buffers for an aacEncEncode() call. + */ +typedef struct { + INT numBufs; /*!< Number of buffers. */ + void **bufs; /*!< Pointer to vector containing buffer addresses. */ + INT *bufferIdentifiers; /*!< Identifier of each buffer element. See + ::AACENC_BufferIdentifier. */ + INT *bufSizes; /*!< Size of each buffer in 8-bit bytes. */ + INT *bufElSizes; /*!< Size of each buffer element in bytes. */ + +} AACENC_BufDesc; + +/** + * Defines the input arguments for an aacEncEncode() call. + */ +typedef struct { + INT numInSamples; /*!< Number of valid input audio samples (multiple of input + channels). */ + INT numAncBytes; /*!< Number of ancillary data bytes to be encoded. */ + +} AACENC_InArgs; + +/** + * Defines the output arguments for an aacEncEncode() call. + */ +typedef struct { + INT numOutBytes; /*!< Number of valid bitstream bytes generated during + aacEncEncode(). */ + INT numInSamples; /*!< Number of input audio samples consumed by the encoder. + */ + INT numAncBytes; /*!< Number of ancillary data bytes consumed by the encoder. + */ + INT bitResState; /*!< State of the bit reservoir in bits. */ + +} AACENC_OutArgs; + +/** + * Meta Data Compression Profiles. + */ +typedef enum { + AACENC_METADATA_DRC_NONE = 0, /*!< None. */ + AACENC_METADATA_DRC_FILMSTANDARD = 1, /*!< Film standard. */ + AACENC_METADATA_DRC_FILMLIGHT = 2, /*!< Film light. */ + AACENC_METADATA_DRC_MUSICSTANDARD = 3, /*!< Music standard. */ + AACENC_METADATA_DRC_MUSICLIGHT = 4, /*!< Music light. */ + AACENC_METADATA_DRC_SPEECH = 5, /*!< Speech. */ + AACENC_METADATA_DRC_NOT_PRESENT = + 256 /*!< Disable writing gain factor (used for comp_profile only). */ + +} AACENC_METADATA_DRC_PROFILE; + +/** + * Meta Data setup structure. + */ +typedef struct { + AACENC_METADATA_DRC_PROFILE + drc_profile; /*!< MPEG DRC compression profile. See + ::AACENC_METADATA_DRC_PROFILE. */ + AACENC_METADATA_DRC_PROFILE + comp_profile; /*!< ETSI heavy compression profile. See + ::AACENC_METADATA_DRC_PROFILE. */ + + INT drc_TargetRefLevel; /*!< Used to define expected level to: + Scaled with 16 bit. x*2^16. */ + INT comp_TargetRefLevel; /*!< Adjust limiter to avoid overload. + Scaled with 16 bit. x*2^16. */ + + INT prog_ref_level_present; /*!< Flag, if prog_ref_level is present */ + INT prog_ref_level; /*!< Programme Reference Level = Dialogue Level: + -31.75dB .. 0 dB ; stepsize: 0.25dB + Scaled with 16 bit. x*2^16.*/ + + UCHAR PCE_mixdown_idx_present; /*!< Flag, if dmx-idx should be written in + programme config element */ + UCHAR ETSI_DmxLvl_present; /*!< Flag, if dmx-lvl should be written in + ETSI-ancData */ + + SCHAR centerMixLevel; /*!< Center downmix level (0...7, according to table) */ + SCHAR surroundMixLevel; /*!< Surround downmix level (0...7, according to + table) */ + + UCHAR + dolbySurroundMode; /*!< Indication for Dolby Surround Encoding Mode. + - 0: Dolby Surround mode not indicated + - 1: 2-ch audio part is not Dolby surround encoded + - 2: 2-ch audio part is Dolby surround encoded */ + + UCHAR drcPresentationMode; /*!< Indicatin for DRC Presentation Mode. + - 0: Presentation mode not inticated + - 1: Presentation mode 1 + - 2: Presentation mode 2 */ + + struct { + /* extended ancillary data */ + UCHAR extAncDataEnable; /*< Indicates if MPEG4_ext_ancillary_data() exists. + - 0: No MPEG4_ext_ancillary_data(). + - 1: Insert MPEG4_ext_ancillary_data(). */ + + UCHAR + extDownmixLevelEnable; /*< Indicates if ext_downmixing_levels() exists. + - 0: No ext_downmixing_levels(). + - 1: Insert ext_downmixing_levels(). */ + UCHAR extDownmixLevel_A; /*< Downmix level index A (0...7, according to + table) */ + UCHAR extDownmixLevel_B; /*< Downmix level index B (0...7, according to + table) */ + + UCHAR dmxGainEnable; /*< Indicates if ext_downmixing_global_gains() exists. + - 0: No ext_downmixing_global_gains(). + - 1: Insert ext_downmixing_global_gains(). */ + INT dmxGain5; /*< Gain factor for downmix to 5 channels. + -15.75dB .. -15.75dB; stepsize: 0.25dB + Scaled with 16 bit. x*2^16.*/ + INT dmxGain2; /*< Gain factor for downmix to 2 channels. + -15.75dB .. -15.75dB; stepsize: 0.25dB + Scaled with 16 bit. x*2^16.*/ + + UCHAR lfeDmxEnable; /*< Indicates if ext_downmixing_lfe_level() exists. + - 0: No ext_downmixing_lfe_level(). + - 1: Insert ext_downmixing_lfe_level(). */ + UCHAR lfeDmxLevel; /*< Downmix level index for LFE (0..15, according to + table) */ + + } ExtMetaData; + +} AACENC_MetaData; + +/** + * AAC encoder control flags. + * + * In interaction with the ::AACENC_CONTROL_STATE parameter it is possible to + * get information about the internal initialization process. It is also + * possible to overwrite the internal state from extern when necessary. + */ +typedef enum { + AACENC_INIT_NONE = 0x0000, /*!< Do not trigger initialization. */ + AACENC_INIT_CONFIG = + 0x0001, /*!< Initialize all encoder modules configuration. */ + AACENC_INIT_STATES = 0x0002, /*!< Reset all encoder modules history buffer. */ + AACENC_INIT_TRANSPORT = + 0x1000, /*!< Initialize transport lib with new parameters. */ + AACENC_RESET_INBUFFER = + 0x2000, /*!< Reset fill level of internal input buffer. */ + AACENC_INIT_ALL = 0xFFFF /*!< Initialize all. */ +} AACENC_CTRLFLAGS; + +/** + * \brief AAC encoder setting parameters. + * + * Use aacEncoder_SetParam() function to configure, or use aacEncoder_GetParam() + * function to read the internal status of the following parameters. + */ +typedef enum { + AACENC_AOT = + 0x0100, /*!< Audio object type. See ::AUDIO_OBJECT_TYPE in FDK_audio.h. + - 2: MPEG-4 AAC Low Complexity. + - 5: MPEG-4 AAC Low Complexity with Spectral Band Replication + (HE-AAC). + - 29: MPEG-4 AAC Low Complexity with Spectral Band + Replication and Parametric Stereo (HE-AAC v2). This + configuration can be used only with stereo input audio data. + - 23: MPEG-4 AAC Low-Delay. + - 39: MPEG-4 AAC Enhanced Low-Delay. Since there is no + ::AUDIO_OBJECT_TYPE for ELD in combination with SBR defined, + enable SBR explicitely by ::AACENC_SBR_MODE parameter. The ELD + v2 212 configuration can be configured by ::AACENC_CHANNELMODE + parameter. + - 129: MPEG-2 AAC Low Complexity. + - 132: MPEG-2 AAC Low Complexity with Spectral Band + Replication (HE-AAC). + + Please note that the virtual MPEG-2 AOT's basically disables + non-existing Perceptual Noise Substitution tool in AAC encoder + and controls the MPEG_ID flag in adts header. The virtual + MPEG-2 AOT doesn't prohibit specific transport formats. */ + + AACENC_BITRATE = 0x0101, /*!< Total encoder bitrate. This parameter is + mandatory and interacts with ::AACENC_BITRATEMODE. + - CBR: Bitrate in bits/second. + - VBR: Variable bitrate. Bitrate argument will + be ignored. See \ref suppBitrates for details. */ + + AACENC_BITRATEMODE = 0x0102, /*!< Bitrate mode. Configuration can be different + kind of bitrate configurations: + - 0: Constant bitrate, use bitrate according + to ::AACENC_BITRATE. (default) Within none + LD/ELD ::AUDIO_OBJECT_TYPE, the CBR mode makes + use of full allowed bitreservoir. In contrast, + at Low-Delay ::AUDIO_OBJECT_TYPE the + bitreservoir is kept very small. + - 1: Variable bitrate mode, \ref vbrmode + "very low bitrate". + - 2: Variable bitrate mode, \ref vbrmode + "low bitrate". + - 3: Variable bitrate mode, \ref vbrmode + "medium bitrate". + - 4: Variable bitrate mode, \ref vbrmode + "high bitrate". + - 5: Variable bitrate mode, \ref vbrmode + "very high bitrate". */ + + AACENC_SAMPLERATE = 0x0103, /*!< Audio input data sampling rate. Encoder + supports following sampling rates: 8000, 11025, + 12000, 16000, 22050, 24000, 32000, 44100, + 48000, 64000, 88200, 96000 */ + + AACENC_SBR_MODE = 0x0104, /*!< Configure SBR independently of the chosen Audio + Object Type ::AUDIO_OBJECT_TYPE. This parameter + is for ELD audio object type only. + - -1: Use ELD SBR auto configurator (default). + - 0: Disable Spectral Band Replication. + - 1: Enable Spectral Band Replication. */ + + AACENC_GRANULE_LENGTH = + 0x0105, /*!< Core encoder (AAC) audio frame length in samples: + - 1024: Default configuration. + - 512: Default length in LD/ELD configuration. + - 480: Length in LD/ELD configuration. + - 256: Length for ELD reduced delay mode (x2). + - 240: Length for ELD reduced delay mode (x2). + - 128: Length for ELD reduced delay mode (x4). + - 120: Length for ELD reduced delay mode (x4). */ + + AACENC_CHANNELMODE = 0x0106, /*!< Set explicit channel mode. Channel mode must + match with number of input channels. + - 1-7, 11,12,14 and 33,34: MPEG channel + modes supported, see ::CHANNEL_MODE in + FDK_audio.h. */ + + AACENC_CHANNELORDER = + 0x0107, /*!< Input audio data channel ordering scheme: + - 0: MPEG channel ordering (e. g. 5.1: C, L, R, SL, SR, LFE). + (default) + - 1: WAVE file format channel ordering (e. g. 5.1: L, R, C, + LFE, SL, SR). */ + + AACENC_SBR_RATIO = + 0x0108, /*!< Controls activation of downsampled SBR. With downsampled + SBR, the delay will be shorter. On the other hand, for + achieving the same quality level, downsampled SBR needs more + bits than dual-rate SBR. With downsampled SBR, the AAC encoder + will work at the same sampling rate as the SBR encoder (single + rate). Downsampled SBR is supported for AAC-ELD and HE-AACv1. + - 1: Downsampled SBR (default for ELD). + - 2: Dual-rate SBR (default for HE-AAC). */ + + AACENC_AFTERBURNER = + 0x0200, /*!< This parameter controls the use of the afterburner feature. + The afterburner is a type of analysis by synthesis algorithm + which increases the audio quality but also the required + processing power. It is recommended to always activate this if + additional memory consumption and processing power consumption + is not a problem. If increased MHz and memory consumption are + an issue then the MHz and memory cost of this optional module + need to be evaluated against the improvement in audio quality + on a case by case basis. + - 0: Disable afterburner (default). + - 1: Enable afterburner. */ + + AACENC_BANDWIDTH = 0x0203, /*!< Core encoder audio bandwidth: + - 0: Determine audio bandwidth internally + (default, see chapter \ref BEHAVIOUR_BANDWIDTH). + - 1 to fs/2: Audio bandwidth in Hertz. Limited + to 20kHz max. Not usable if SBR is active. This + setting is for experts only, better do not touch + this value to avoid degraded audio quality. */ + + AACENC_PEAK_BITRATE = + 0x0207, /*!< Peak bitrate configuration parameter to adjust maximum bits + per audio frame. Bitrate is in bits/second. The peak bitrate + will internally be limited to the chosen bitrate + ::AACENC_BITRATE as lower limit and the + number_of_effective_channels*6144 bit as upper limit. + + Setting the peak bitrate equal to ::AACENC_BITRATE does not + necessarily mean that the audio frames will be of constant + size. Since the peak bitate is in bits/second, the frame sizes + can vary by one byte in one or the other direction over various + frames. However, it is not recommended to reduce the peak + pitrate to ::AACENC_BITRATE - it would disable the + bitreservoir, which would affect the audio quality by a large + amount. */ + + AACENC_TRANSMUX = 0x0300, /*!< Transport type to be used. See ::TRANSPORT_TYPE + in FDK_audio.h. Following types can be configured + in encoder library: + - 0: raw access units + - 1: ADIF bitstream format + - 2: ADTS bitstream format + - 6: Audio Mux Elements (LATM) with + muxConfigPresent = 1 + - 7: Audio Mux Elements (LATM) with + muxConfigPresent = 0, out of band StreamMuxConfig + - 10: Audio Sync Stream (LOAS) */ + + AACENC_HEADER_PERIOD = + 0x0301, /*!< Frame count period for sending in-band configuration buffers + within LATM/LOAS transport layer. Additionally this parameter + configures the PCE repetition period in raw_data_block(). See + \ref encPCE. + - 0xFF: auto-mode default 10 for TT_MP4_ADTS, TT_MP4_LOAS and + TT_MP4_LATM_MCP1, otherwise 0. + - n: Frame count period. */ + + AACENC_SIGNALING_MODE = + 0x0302, /*!< Signaling mode of the extension AOT: + - 0: Implicit backward compatible signaling (default for + non-MPEG-4 based AOT's and for the transport formats ADIF and + ADTS) + - A stream that uses implicit signaling can be decoded + by every AAC decoder, even AAC-LC-only decoders + - An AAC-LC-only decoder will only decode the + low-frequency part of the stream, resulting in a band-limited + output + - This method works with all transport formats + - This method does not work with downsampled SBR + - 1: Explicit backward compatible signaling + - A stream that uses explicit backward compatible + signaling can be decoded by every AAC decoder, even AAC-LC-only + decoders + - An AAC-LC-only decoder will only decode the + low-frequency part of the stream, resulting in a band-limited + output + - A decoder not capable of decoding PS will only decode + the AAC-LC+SBR part. If the stream contained PS, the result + will be a a decoded mono downmix + - This method does not work with ADIF or ADTS. For + LOAS/LATM, it only works with AudioMuxVersion==1 + - This method does work with downsampled SBR + - 2: Explicit hierarchical signaling (default for MPEG-4 + based AOT's and for all transport formats excluding ADIF and + ADTS) + - A stream that uses explicit hierarchical signaling can + be decoded only by HE-AAC decoders + - An AAC-LC-only decoder will not decode a stream that + uses explicit hierarchical signaling + - A decoder not capable of decoding PS will not decode + the stream at all if it contained PS + - This method does not work with ADIF or ADTS. It works + with LOAS/LATM and the MPEG-4 File format + - This method does work with downsampled SBR + + For making sure that the listener always experiences the + best audio quality, explicit hierarchical signaling should be + used. This makes sure that only a full HE-AAC-capable decoder + will decode those streams. The audio is played at full + bandwidth. For best backwards compatibility, it is recommended + to encode with implicit SBR signaling. A decoder capable of + AAC-LC only will then only decode the AAC part, which means the + decoded audio will sound band-limited. + + For MPEG-2 transport types (ADTS,ADIF), only implicit + signaling is possible. + + For LOAS and LATM, explicit backwards compatible signaling + only works together with AudioMuxVersion==1. The reason is + that, for explicit backwards compatible signaling, additional + information will be appended to the ASC. A decoder that is only + capable of decoding AAC-LC will skip this part. Nevertheless, + for jumping to the end of the ASC, it needs to know the ASC + length. Transmitting the length of the ASC is a feature of + AudioMuxVersion==1, it is not possible to transmit the length + of the ASC with AudioMuxVersion==0, therefore an AAC-LC-only + decoder will not be able to parse a LOAS/LATM stream that was + being encoded with AudioMuxVersion==0. + + For downsampled SBR, explicit signaling is mandatory. The + reason for this is that the extension sampling frequency (which + is in case of SBR the sampling frequqncy of the SBR part) can + only be signaled in explicit mode. + + For AAC-ELD, the SBR information is transmitted in the + ELDSpecific Config, which is part of the AudioSpecificConfig. + Therefore, the settings here will have no effect on AAC-ELD.*/ + + AACENC_TPSUBFRAMES = + 0x0303, /*!< Number of sub frames in a transport frame for LOAS/LATM or + ADTS (default 1). + - ADTS: Maximum number of sub frames restricted to 4. + - LOAS/LATM: Maximum number of sub frames restricted to 2.*/ + + AACENC_AUDIOMUXVER = + 0x0304, /*!< AudioMuxVersion to be used for LATM. (AudioMuxVersionA, + currently not implemented): + - 0: Default, no transmission of tara Buffer fullness, no ASC + length and including actual latm Buffer fullnes. + - 1: Transmission of tara Buffer fullness, ASC length and + actual latm Buffer fullness. + - 2: Transmission of tara Buffer fullness, ASC length and + maximum level of latm Buffer fullness. */ + + AACENC_PROTECTION = 0x0306, /*!< Configure protection in transport layer: + - 0: No protection. (default) + - 1: CRC active for ADTS transport format. */ + + AACENC_ANCILLARY_BITRATE = + 0x0500, /*!< Constant ancillary data bitrate in bits/second. + - 0: Either no ancillary data or insert exact number of + bytes, denoted via input parameter, numAncBytes in + AACENC_InArgs. + - else: Insert ancillary data with specified bitrate. */ + + AACENC_METADATA_MODE = 0x0600, /*!< Configure Meta Data. See ::AACENC_MetaData + for further details: + - 0: Do not embed any metadata. + - 1: Embed dynamic_range_info metadata. + - 2: Embed dynamic_range_info and + ancillary_data metadata. + - 3: Embed ancillary_data metadata. */ + + AACENC_CONTROL_STATE = + 0xFF00, /*!< There is an automatic process which internally reconfigures + the encoder instance when a configuration parameter changed or + an error occured. This paramerter allows overwriting or getting + the control status of this process. See ::AACENC_CTRLFLAGS. */ + + AACENC_NONE = 0xFFFF /*!< ------ */ + +} AACENC_PARAM; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Open an instance of the encoder. + * + * Allocate memory for an encoder instance with a functional range denoted by + * the function parameters. Preinitialize encoder instance with default + * configuration. + * + * \param phAacEncoder A pointer to an encoder handle. Initialized on return. + * \param encModules Specify encoder modules to be supported in this encoder + * instance: + * - 0x0: Allocate memory for all available encoder + * modules. + * - else: Select memory allocation regarding encoder + * modules. Following flags are possible and can be combined. + * - 0x01: AAC module. + * - 0x02: SBR module. + * - 0x04: PS module. + * - 0x08: MPS module. + * - 0x10: Metadata module. + * - example: (0x01|0x02|0x04|0x08|0x10) allocates + * all modules and is equivalent to default configuration denotet by 0x0. + * \param maxChannels Number of channels to be allocated. This parameter can + * be used in different ways: + * - 0: Allocate maximum number of AAC and SBR channels as + * supported by the library. + * - nChannels: Use same maximum number of channels for + * allocating memory in AAC and SBR module. + * - nChannels | (nSbrCh<<8): Number of SBR channels can be + * different to AAC channels to save data memory. + * + * \return + * - AACENC_OK, on succes. + * - AACENC_INVALID_HANDLE, AACENC_MEMORY_ERROR, AACENC_INVALID_CONFIG, + * on failure. + */ +AACENC_ERROR aacEncOpen(HANDLE_AACENCODER *phAacEncoder, const UINT encModules, + const UINT maxChannels); + +/** + * \brief Close the encoder instance. + * + * Deallocate encoder instance and free whole memory. + * + * \param phAacEncoder Pointer to the encoder handle to be deallocated. + * + * \return + * - AACENC_OK, on success. + * - AACENC_INVALID_HANDLE, on failure. + */ +AACENC_ERROR aacEncClose(HANDLE_AACENCODER *phAacEncoder); + +/** + * \brief Encode audio data. + * + * This function is mainly for encoding audio data. In addition the function can + * be used for an encoder (re)configuration process. + * - PCM input data will be retrieved from external input buffer until the fill + * level allows encoding a single frame. This functionality allows an external + * buffer with reduced size in comparison to the AAC or HE-AAC audio frame + * length. + * - If the value of the input samples argument is zero, just internal + * reinitialization will be applied if it is requested. + * - At the end of a file the flushing process can be triggerd via setting the + * value of the input samples argument to -1. The encoder delay lines are fully + * flushed when the encoder returns no valid bitstream data + * AACENC_OutArgs::numOutBytes. Furthermore the end of file is signaled by the + * return value AACENC_ENCODE_EOF. + * - If an error occured in the previous frame or any of the encoder parameters + * changed, an internal reinitialization process will be applied before encoding + * the incoming audio samples. + * - The function can also be used for an independent reconfiguration process + * without encoding. The first parameter has to be a valid encoder handle and + * all other parameters can be set to NULL. + * - If the size of the external bitbuffer in outBufDesc is not sufficient for + * writing the whole bitstream, an internal error will be the return value and a + * reconfiguration will be triggered. + * + * \param hAacEncoder A valid AAC encoder handle. + * \param inBufDesc Input buffer descriptor, see AACENC_BufDesc: + * - At least one input buffer with audio data is + * expected. + * - Optionally a second input buffer with + * ancillary data can be fed. + * \param outBufDesc Output buffer descriptor, see AACENC_BufDesc: + * - Provide one output buffer for the encoded + * bitstream. + * \param inargs Input arguments, see AACENC_InArgs. + * \param outargs Output arguments, AACENC_OutArgs. + * + * \return + * - AACENC_OK, on success. + * - AACENC_INVALID_HANDLE, AACENC_ENCODE_ERROR, on failure in encoding + * process. + * - AACENC_INVALID_CONFIG, AACENC_INIT_ERROR, AACENC_INIT_AAC_ERROR, + * AACENC_INIT_SBR_ERROR, AACENC_INIT_TP_ERROR, AACENC_INIT_META_ERROR, + * AACENC_INIT_MPS_ERROR, on failure in encoder initialization. + * - AACENC_UNSUPPORTED_PARAMETER, on incorrect input or output buffer + * descriptor initialization. + * - AACENC_ENCODE_EOF, when flushing fully concluded. + */ +AACENC_ERROR aacEncEncode(const HANDLE_AACENCODER hAacEncoder, + const AACENC_BufDesc *inBufDesc, + const AACENC_BufDesc *outBufDesc, + const AACENC_InArgs *inargs, AACENC_OutArgs *outargs); + +/** + * \brief Acquire info about present encoder instance. + * + * This function retrieves information of the encoder configuration. In addition + * to informative internal states, a configuration data block of the current + * encoder settings will be returned. The format is either Audio Specific Config + * in case of Raw Packets transport format or StreamMuxConfig in case of + * LOAS/LATM transport format. The configuration data block is binary coded as + * specified in ISO/IEC 14496-3 (MPEG-4 audio), to be used directly for MPEG-4 + * File Format or RFC3016 or RFC3640 applications. + * + * \param hAacEncoder A valid AAC encoder handle. + * \param pInfo Pointer to AACENC_InfoStruct. Filled on return. + * + * \return + * - AACENC_OK, on succes. + * - AACENC_INVALID_HANDLE, AACENC_INIT_ERROR, on failure. + */ +AACENC_ERROR aacEncInfo(const HANDLE_AACENCODER hAacEncoder, + AACENC_InfoStruct *pInfo); + +/** + * \brief Set one single AAC encoder parameter. + * + * This function allows configuration of all encoder parameters specified in + * ::AACENC_PARAM. Each parameter must be set with a separate function call. An + * internal validation of the configuration value range will be done and an + * internal reconfiguration will be signaled. The actual configuration adoption + * is part of the subsequent aacEncEncode() call. + * + * \param hAacEncoder A valid AAC encoder handle. + * \param param Parameter to be set. See ::AACENC_PARAM. + * \param value Parameter value. See parameter description in + * ::AACENC_PARAM. + * + * \return + * - AACENC_OK, on success. + * - AACENC_INVALID_HANDLE, AACENC_UNSUPPORTED_PARAMETER, + * AACENC_INVALID_CONFIG, on failure. + */ +AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER hAacEncoder, + const AACENC_PARAM param, const UINT value); + +/** + * \brief Get one single AAC encoder parameter. + * + * This function is the complement to aacEncoder_SetParam(). After encoder + * reinitialization with user defined settings, the internal status can be + * obtained of each parameter, specified with ::AACENC_PARAM. + * + * \param hAacEncoder A valid AAC encoder handle. + * \param param Parameter to be returned. See ::AACENC_PARAM. + * + * \return Internal configuration value of specifed parameter ::AACENC_PARAM. + */ +UINT aacEncoder_GetParam(const HANDLE_AACENCODER hAacEncoder, + const AACENC_PARAM param); + +/** + * \brief Get information about encoder library build. + * + * Fill a given LIB_INFO structure with library version information. + * + * \param info Pointer to an allocated LIB_INFO struct. + * + * \return + * - AACENC_OK, on success. + * - AACENC_INVALID_HANDLE, AACENC_INIT_ERROR, on failure. + */ +AACENC_ERROR aacEncGetLibInfo(LIB_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif /* AACENC_LIB_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_ram.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_ram.cpp new file mode 100644 index 0000000000000..25e2aec405624 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_ram.cpp @@ -0,0 +1,208 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser, M. Gayer + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Memory layout + \author Markus Lohwasser +*/ + +#include "aacEnc_ram.h" + +C_AALLOC_MEM(AACdynamic_RAM, FIXP_DBL, AAC_ENC_DYN_RAM_SIZE / sizeof(FIXP_DBL)) + +/* + Static memory areas, must not be overwritten in other sections of the decoder + ! +*/ + +/* + The structure AacEncoder contains all Encoder structures. +*/ + +C_ALLOC_MEM(Ram_aacEnc_AacEncoder, struct AAC_ENC, 1) + +/* + The structure PSY_INTERNAl contains all psych configuration and data pointer. + * PsyStatic holds last and current Psych data. + * PsyInputBuffer contains time input. Signal is needed at the beginning of + Psych. Memory can be reused after signal is in time domain. + * PsyData contains spectral, nrg and threshold information. Necessary data + are copied into PsyOut, so memory is available after leaving psych. + * TnsData, ChaosMeasure, PnsData are temporarily necessary, e.g. use memory + from PsyInputBuffer. +*/ + +C_ALLOC_MEM2(Ram_aacEnc_PsyElement, PSY_ELEMENT, 1, ((8))) + +C_ALLOC_MEM(Ram_aacEnc_PsyInternal, PSY_INTERNAL, 1) +C_ALLOC_MEM2(Ram_aacEnc_PsyStatic, PSY_STATIC, 1, (8)) + +C_ALLOC_MEM2(Ram_aacEnc_PsyInputBuffer, INT_PCM, MAX_INPUT_BUFFER_SIZE, (8)) + +PSY_DYNAMIC *GetRam_aacEnc_PsyDynamic(int n, UCHAR *dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + P_BUF_1 + n*sizeof(PSY_DYNAMIC)) is sufficiently aligned, so + * the cast is safe */ + return reinterpret_cast(reinterpret_cast( + dynamic_RAM + P_BUF_1 + n * sizeof(PSY_DYNAMIC))); +} + +/* + The structure PSY_OUT holds all psychoaccoustic data needed + in quantization module +*/ +C_ALLOC_MEM2(Ram_aacEnc_PsyOut, PSY_OUT, 1, (1)) + +C_ALLOC_MEM2(Ram_aacEnc_PsyOutElements, PSY_OUT_ELEMENT, 1, (1) * ((8))) +C_ALLOC_MEM2(Ram_aacEnc_PsyOutChannel, PSY_OUT_CHANNEL, 1, (1) * (8)) + +/* + The structure QC_STATE contains preinitialized settings and quantizer + structures. + * AdjustThreshold structure contains element-wise settings. + * ElementBits contains elemnt-wise bit consumption settings. + * When CRC is active, lookup table is necessary for fast crc calculation. + * Bitcounter contains buffer to find optimal codebooks and minimal bit + consumption. Values are temporarily, so dynamic memory can be used. +*/ + +C_ALLOC_MEM(Ram_aacEnc_QCstate, QC_STATE, 1) +C_ALLOC_MEM(Ram_aacEnc_AdjustThreshold, ADJ_THR_STATE, 1) + +C_ALLOC_MEM2(Ram_aacEnc_AdjThrStateElement, ATS_ELEMENT, 1, ((8))) +C_ALLOC_MEM2(Ram_aacEnc_ElementBits, ELEMENT_BITS, 1, ((8))) +C_ALLOC_MEM(Ram_aacEnc_BitCntrState, struct BITCNTR_STATE, 1) + +INT *GetRam_aacEnc_BitLookUp(int n, UCHAR *dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + P_BUF_1) is sufficiently aligned, so the cast is safe */ + return reinterpret_cast( + reinterpret_cast(dynamic_RAM + P_BUF_1)); +} +INT *GetRam_aacEnc_MergeGainLookUp(int n, UCHAR *dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + P_BUF_1 + sizeof(INT)*(MAX_SFB_LONG*(CODE_BOOK_ESC_NDX+1))) + * is sufficiently aligned, so the cast is safe */ + return reinterpret_cast(reinterpret_cast( + dynamic_RAM + P_BUF_1 + + sizeof(INT) * (MAX_SFB_LONG * (CODE_BOOK_ESC_NDX + 1)))); +} + +/* + The structure QC_OUT contains settings and structures holding all necessary + information needed in bitstreamwriter. +*/ + +C_ALLOC_MEM2(Ram_aacEnc_QCout, QC_OUT, 1, (1)) +C_ALLOC_MEM2(Ram_aacEnc_QCelement, QC_OUT_ELEMENT, 1, (1) * ((8))) +QC_OUT_CHANNEL *GetRam_aacEnc_QCchannel(int n, UCHAR *dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + P_BUF_0 + n*sizeof(QC_OUT_CHANNEL)) is sufficiently aligned, + * so the cast is safe */ + return reinterpret_cast(reinterpret_cast( + dynamic_RAM + P_BUF_0 + n * ALIGN_SIZE(sizeof(QC_OUT_CHANNEL)))); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_ram.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_ram.h new file mode 100644 index 0000000000000..f24eef1e0aa05 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_ram.h @@ -0,0 +1,249 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser, M. Gayer + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Memory layout + \author Markus Lohwasser +*/ + +#ifndef AACENC_RAM_H +#define AACENC_RAM_H + +#include "common_fix.h" + +#include "aacenc.h" +#include "psy_data.h" +#include "interface.h" +#include "psy_main.h" +#include "bitenc.h" +#include "bit_cnt.h" +#include "psy_const.h" + +#define OUTPUTBUFFER_SIZE \ + (8192) /*!< Output buffer size has to be at least 6144 bits per channel \ + (768 bytes). FDK bitbuffer implementation expects buffer of \ + size 2^n. */ + +/* + Moved AAC_ENC struct definition from aac_enc.cpp into aacEnc_ram.h to get size + and respective static memory in aacEnc_ram.cpp. aac_enc.h is the outward + visible header file and putting the struct into would cause necessity of + additional visible header files outside library. +*/ + +/* define hBitstream size: max AAC framelength is 6144 bits/channel */ +/*#define BUFFER_BITSTR_SIZE ((6400*(8)/bbWordSize) +((bbWordSize - 1) / + * bbWordSize))*/ + +struct AAC_ENC { + AACENC_CONFIG *config; + + INT ancillaryBitsPerFrame; /* ancillary bits per frame calculated from + ancillary rate */ + + CHANNEL_MAPPING channelMapping; + + QC_STATE *qcKernel; + QC_OUT *qcOut[(1)]; + + PSY_OUT *psyOut[(1)]; + PSY_INTERNAL *psyKernel; + + /* lifetime vars */ + + CHANNEL_MODE encoderMode; + INT bandwidth90dB; + AACENC_BITRATE_MODE bitrateMode; + + INT dontWriteAdif; /* use: write ADIF header only before 1st frame */ + + FIXP_DBL *dynamic_RAM; + + INT maxChannels; /* used while allocation */ + INT maxElements; + INT maxFrames; + + AUDIO_OBJECT_TYPE aot; /* AOT to be used while encoding. */ +}; + +#define maxSize(a, b) (((a) > (b)) ? (a) : (b)) + +#define BIT_LOOK_UP_SIZE \ + (sizeof(INT) * (MAX_SFB_LONG * (CODE_BOOK_ESC_NDX + 1))) +#define MERGE_GAIN_LOOK_UP_SIZE (sizeof(INT) * MAX_SFB_LONG) + +/* Size of AhFlag buffer in function FDKaacEnc_adaptThresholdsToPe() */ +#define ADJ_THR_AH_FLAG_SIZE (sizeof(UCHAR) * ((8)) * (2) * MAX_GROUPED_SFB) +/* Size of ThrExp buffer in function FDKaacEnc_adaptThresholdsToPe() */ +#define ADJ_THR_THR_EXP_SIZE (sizeof(FIXP_DBL) * ((8)) * (2) * MAX_GROUPED_SFB) +/* Size of sfbNActiveLinesLdData buffer in function FDKaacEnc_correctThresh() */ +#define ADJ_THR_ACT_LIN_LD_DATA_SIZE \ + (sizeof(FIXP_DBL) * ((8)) * (2) * MAX_GROUPED_SFB) +/* Total amount of dynamic buffer needed in adjust thresholds functionality */ +#define ADJ_THR_SIZE \ + (ADJ_THR_AH_FLAG_SIZE + ADJ_THR_THR_EXP_SIZE + ADJ_THR_ACT_LIN_LD_DATA_SIZE) + +/* Dynamic RAM - Allocation */ +/* + +++++++++++++++++++++++++++++++++++++++++++++++++++++ + | P_BUF_0 | P_BUF_1 | + +++++++++++++++++++++++++++++++++++++++++++++++++++++ + | QC_OUT_CH | PSY_DYN | + +++++++++++++++++++++++++++++++++++++++++++++++++++++ + | | BitLookUp+MergeGainLookUp | + +++++++++++++++++++++++++++++++++++++++++++++++++++++ + | | AH_FLAG | THR_EXP | ACT_LIN_LD_DATA | + +++++++++++++++++++++++++++++++++++++++++++++++++++++ + | | Bitstream output buffer | + +++++++++++++++++++++++++++++++++++++++++++++++++++++ +*/ + +#define BUF_SIZE_0 (ALIGN_SIZE(sizeof(QC_OUT_CHANNEL)) * (8)) +#define BUF_SIZE_1 \ + (ALIGN_SIZE(maxSize(maxSize(sizeof(PSY_DYNAMIC), \ + (BIT_LOOK_UP_SIZE + MERGE_GAIN_LOOK_UP_SIZE)), \ + ADJ_THR_SIZE))) + +#define P_BUF_0 (0) +#define P_BUF_1 (P_BUF_0 + BUF_SIZE_0) + +#define AAC_ENC_DYN_RAM_SIZE (BUF_SIZE_0 + BUF_SIZE_1) + +H_ALLOC_MEM(AACdynamic_RAM, FIXP_DBL) +/* + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +END - Dynamic RAM - Allocation */ + +/* + See further Memory Allocation details in aacEnc_ram.cpp +*/ +H_ALLOC_MEM(Ram_aacEnc_AacEncoder, AAC_ENC) + +H_ALLOC_MEM(Ram_aacEnc_PsyElement, PSY_ELEMENT) + +H_ALLOC_MEM(Ram_aacEnc_PsyInternal, PSY_INTERNAL) +H_ALLOC_MEM(Ram_aacEnc_PsyStatic, PSY_STATIC) +H_ALLOC_MEM(Ram_aacEnc_PsyInputBuffer, INT_PCM) + +PSY_DYNAMIC *GetRam_aacEnc_PsyDynamic(int n, UCHAR *dynamic_RAM); + +H_ALLOC_MEM(Ram_aacEnc_PsyOutChannel, PSY_OUT_CHANNEL) + +H_ALLOC_MEM(Ram_aacEnc_PsyOut, PSY_OUT) +H_ALLOC_MEM(Ram_aacEnc_PsyOutElements, PSY_OUT_ELEMENT) + +H_ALLOC_MEM(Ram_aacEnc_QCstate, QC_STATE) +H_ALLOC_MEM(Ram_aacEnc_AdjustThreshold, ADJ_THR_STATE) + +H_ALLOC_MEM(Ram_aacEnc_AdjThrStateElement, ATS_ELEMENT) +H_ALLOC_MEM(Ram_aacEnc_ElementBits, ELEMENT_BITS) +H_ALLOC_MEM(Ram_aacEnc_BitCntrState, BITCNTR_STATE) + +INT *GetRam_aacEnc_BitLookUp(int n, UCHAR *dynamic_RAM); +INT *GetRam_aacEnc_MergeGainLookUp(int n, UCHAR *dynamic_RAM); +QC_OUT_CHANNEL *GetRam_aacEnc_QCchannel(int n, UCHAR *dynamic_RAM); + +H_ALLOC_MEM(Ram_aacEnc_QCout, QC_OUT) +H_ALLOC_MEM(Ram_aacEnc_QCelement, QC_OUT_ELEMENT) + +#endif /* #ifndef AACENC_RAM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_rom.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_rom.cpp new file mode 100644 index 0000000000000..ac0fa9d82c6db --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_rom.cpp @@ -0,0 +1,2486 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser, M. Gayer + + Description: + +*******************************************************************************/ + +#include "aacEnc_rom.h" + +/* + Huffman Tables +*/ +const ULONG FDKaacEnc_huff_ltab1_2[3][3][3][3] = { + {{{0x000b0009, 0x00090007, 0x000b0009}, + {0x000a0008, 0x00070006, 0x000a0008}, + {0x000b0009, 0x00090008, 0x000b0009}}, + {{0x000a0008, 0x00070006, 0x000a0007}, + {0x00070006, 0x00050005, 0x00070006}, + {0x00090007, 0x00070006, 0x000a0008}}, + {{0x000b0009, 0x00090007, 0x000b0008}, + {0x00090008, 0x00070006, 0x00090008}, + {0x000b0009, 0x00090007, 0x000b0009}}}, + {{{0x00090008, 0x00070006, 0x00090007}, + {0x00070006, 0x00050005, 0x00070006}, + {0x00090007, 0x00070006, 0x00090008}}, + {{0x00070006, 0x00050005, 0x00070006}, + {0x00050005, 0x00010003, 0x00050005}, + {0x00070006, 0x00050005, 0x00070006}}, + {{0x00090008, 0x00070006, 0x00090007}, + {0x00070006, 0x00050005, 0x00070006}, + {0x00090008, 0x00070006, 0x00090008}}}, + {{{0x000b0009, 0x00090007, 0x000b0009}, + {0x00090008, 0x00070006, 0x00090008}, + {0x000b0008, 0x00090007, 0x000b0009}}, + {{0x000a0008, 0x00070006, 0x00090007}, + {0x00070006, 0x00050004, 0x00070006}, + {0x00090008, 0x00070006, 0x000a0007}}, + {{0x000b0009, 0x00090007, 0x000b0009}, + {0x000a0007, 0x00070006, 0x00090008}, + {0x000b0009, 0x00090007, 0x000b0009}}}}; + +const ULONG FDKaacEnc_huff_ltab3_4[3][3][3][3] = { + {{{0x00010004, 0x00040005, 0x00080008}, + {0x00040005, 0x00050004, 0x00080008}, + {0x00090009, 0x00090008, 0x000a000b}}, + {{0x00040005, 0x00060005, 0x00090008}, + {0x00060005, 0x00060004, 0x00090008}, + {0x00090008, 0x00090007, 0x000a000a}}, + {{0x00090009, 0x000a0008, 0x000d000b}, + {0x00090008, 0x00090008, 0x000b000a}, + {0x000b000b, 0x000a000a, 0x000c000b}}}, + {{{0x00040004, 0x00060005, 0x000a0008}, + {0x00060004, 0x00070004, 0x000a0008}, + {0x000a0008, 0x000a0008, 0x000c000a}}, + {{0x00050004, 0x00070004, 0x000b0008}, + {0x00060004, 0x00070004, 0x000a0007}, + {0x00090008, 0x00090007, 0x000b0009}}, + {{0x00090008, 0x000a0008, 0x000d000a}, + {0x00080007, 0x00090007, 0x000c0009}, + {0x000a000a, 0x000b0009, 0x000c000a}}}, + {{{0x00080008, 0x000a0008, 0x000f000b}, + {0x00090008, 0x000b0007, 0x000f000a}, + {0x000d000b, 0x000e000a, 0x0010000c}}, + {{0x00080008, 0x000a0007, 0x000e000a}, + {0x00090007, 0x000a0007, 0x000e0009}, + {0x000c000a, 0x000c0009, 0x000f000b}}, + {{0x000b000b, 0x000c000a, 0x0010000c}, + {0x000a000a, 0x000b0009, 0x000f000b}, + {0x000c000b, 0x000c000a, 0x000f000b}}}}; + +const ULONG FDKaacEnc_huff_ltab5_6[9][9] = { + {0x000d000b, 0x000c000a, 0x000b0009, 0x000b0009, 0x000a0009, 0x000b0009, + 0x000b0009, 0x000c000a, 0x000d000b}, + {0x000c000a, 0x000b0009, 0x000a0008, 0x00090007, 0x00080007, 0x00090007, + 0x000a0008, 0x000b0009, 0x000c000a}, + {0x000c0009, 0x000a0008, 0x00090006, 0x00080006, 0x00070006, 0x00080006, + 0x00090006, 0x000a0008, 0x000b0009}, + {0x000b0009, 0x00090007, 0x00080006, 0x00050004, 0x00040004, 0x00050004, + 0x00080006, 0x00090007, 0x000b0009}, + {0x000a0009, 0x00080007, 0x00070006, 0x00040004, 0x00010004, 0x00040004, + 0x00070006, 0x00080007, 0x000b0009}, + {0x000b0009, 0x00090007, 0x00080006, 0x00050004, 0x00040004, 0x00050004, + 0x00080006, 0x00090007, 0x000b0009}, + {0x000b0009, 0x000a0008, 0x00090006, 0x00080006, 0x00070006, 0x00080006, + 0x00090006, 0x000a0008, 0x000b0009}, + {0x000c000a, 0x000b0009, 0x000a0008, 0x00090007, 0x00080007, 0x00090007, + 0x000a0007, 0x000b0008, 0x000c000a}, + {0x000d000b, 0x000c000a, 0x000c0009, 0x000b0009, 0x000a0009, 0x000a0009, + 0x000b0009, 0x000c000a, 0x000d000b}}; + +const ULONG FDKaacEnc_huff_ltab7_8[8][8] = { + {0x00010005, 0x00030004, 0x00060005, 0x00070006, 0x00080007, 0x00090008, + 0x000a0009, 0x000b000a}, + {0x00030004, 0x00040003, 0x00060004, 0x00070005, 0x00080006, 0x00080007, + 0x00090007, 0x00090008}, + {0x00060005, 0x00060004, 0x00070004, 0x00080005, 0x00080006, 0x00090007, + 0x00090007, 0x000a0008}, + {0x00070006, 0x00070005, 0x00080005, 0x00080006, 0x00090006, 0x00090007, + 0x000a0008, 0x000a0008}, + {0x00080007, 0x00080006, 0x00090006, 0x00090006, 0x000a0007, 0x000a0007, + 0x000a0008, 0x000b0009}, + {0x00090008, 0x00080007, 0x00090006, 0x00090007, 0x000a0007, 0x000a0008, + 0x000b0008, 0x000b000a}, + {0x000a0009, 0x00090007, 0x00090007, 0x000a0008, 0x000a0008, 0x000b0008, + 0x000c0009, 0x000c0009}, + {0x000b000a, 0x000a0008, 0x000a0008, 0x000a0008, 0x000b0009, 0x000b0009, + 0x000c0009, 0x000c000a}}; + +const ULONG FDKaacEnc_huff_ltab9_10[13][13] = { + {0x00010006, 0x00030005, 0x00060006, 0x00080006, 0x00090007, 0x000a0008, + 0x000a0009, 0x000b000a, 0x000b000a, 0x000c000a, 0x000c000b, 0x000d000b, + 0x000d000c}, + {0x00030005, 0x00040004, 0x00060004, 0x00070005, 0x00080006, 0x00080007, + 0x00090007, 0x000a0008, 0x000a0008, 0x000a0009, 0x000b000a, 0x000c000a, + 0x000c000b}, + {0x00060006, 0x00060004, 0x00070005, 0x00080005, 0x00080006, 0x00090006, + 0x000a0007, 0x000a0008, 0x000a0008, 0x000b0009, 0x000c0009, 0x000c000a, + 0x000c000a}, + {0x00080006, 0x00070005, 0x00080005, 0x00090005, 0x00090006, 0x000a0007, + 0x000a0007, 0x000b0008, 0x000b0008, 0x000b0009, 0x000c0009, 0x000c000a, + 0x000d000a}, + {0x00090007, 0x00080006, 0x00090006, 0x00090006, 0x000a0006, 0x000a0007, + 0x000b0007, 0x000b0008, 0x000b0008, 0x000c0009, 0x000c0009, 0x000c000a, + 0x000d000a}, + {0x000a0008, 0x00090007, 0x00090006, 0x000a0007, 0x000b0007, 0x000b0007, + 0x000b0008, 0x000c0008, 0x000b0008, 0x000c0009, 0x000c000a, 0x000d000a, + 0x000d000b}, + {0x000b0009, 0x00090007, 0x000a0007, 0x000b0007, 0x000b0007, 0x000b0008, + 0x000c0008, 0x000c0009, 0x000c0009, 0x000c0009, 0x000d000a, 0x000d000a, + 0x000d000b}, + {0x000b0009, 0x000a0008, 0x000a0008, 0x000b0008, 0x000b0008, 0x000c0008, + 0x000c0009, 0x000d0009, 0x000d0009, 0x000d000a, 0x000d000a, 0x000d000b, + 0x000d000b}, + {0x000b0009, 0x000a0008, 0x000a0008, 0x000b0008, 0x000b0008, 0x000b0008, + 0x000c0009, 0x000c0009, 0x000d000a, 0x000d000a, 0x000e000a, 0x000d000b, + 0x000e000b}, + {0x000b000a, 0x000a0009, 0x000b0009, 0x000b0009, 0x000c0009, 0x000c0009, + 0x000c0009, 0x000c000a, 0x000d000a, 0x000d000a, 0x000e000b, 0x000e000b, + 0x000e000c}, + {0x000c000a, 0x000b0009, 0x000b0009, 0x000c0009, 0x000c0009, 0x000c000a, + 0x000d000a, 0x000d000a, 0x000d000a, 0x000e000b, 0x000e000b, 0x000e000b, + 0x000f000c}, + {0x000c000b, 0x000b000a, 0x000c0009, 0x000c000a, 0x000c000a, 0x000d000a, + 0x000d000a, 0x000d000a, 0x000d000b, 0x000e000b, 0x000e000b, 0x000f000b, + 0x000f000c}, + {0x000d000b, 0x000c000a, 0x000c000a, 0x000c000a, 0x000d000a, 0x000d000a, + 0x000d000a, 0x000d000b, 0x000e000b, 0x000e000c, 0x000e000c, 0x000e000c, + 0x000f000c}}; + +const UCHAR FDKaacEnc_huff_ltab11[17][17] = { + {0x04, 0x05, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, + 0x0c, 0x0b, 0x0c, 0x0c, 0x0a}, + {0x05, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0b, 0x08}, + {0x06, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, + 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x07, 0x06, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, + 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x08, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, + 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x08, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, + 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x0a, 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0b, 0x08}, + {0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0b, 0x0b, 0x08}, + {0x0b, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0b, 0x0a, 0x0b, 0x0b, 0x08}, + {0x0b, 0x0a, 0x09, 0x09, 0x0a, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x08}, + {0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x09}, + {0x0b, 0x0a, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x09}, + {0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x09}, + {0x0c, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0c, 0x0c, 0x09}, + {0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x09, 0x05}}; + +const UCHAR FDKaacEnc_huff_ltabscf[121] = { + 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x12, 0x13, 0x12, + 0x11, 0x11, 0x10, 0x11, 0x10, 0x10, 0x10, 0x10, 0x0f, 0x0f, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, + 0x0c, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x07, + 0x06, 0x06, 0x05, 0x04, 0x03, 0x01, 0x04, 0x04, 0x05, 0x06, 0x06, + 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x10, 0x0f, + 0x10, 0x0f, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13}; + +const USHORT FDKaacEnc_huff_ctab1[3][3][3][3] = {{{{0x07f8, 0x01f1, 0x07fd}, + {0x03f5, 0x0068, 0x03f0}, + {0x07f7, 0x01ec, 0x07f5}}, + {{0x03f1, 0x0072, 0x03f4}, + {0x0074, 0x0011, 0x0076}, + {0x01eb, 0x006c, 0x03f6}}, + {{0x07fc, 0x01e1, 0x07f1}, + {0x01f0, 0x0061, 0x01f6}, + {0x07f2, 0x01ea, 0x07fb}}}, + {{{0x01f2, 0x0069, 0x01ed}, + {0x0077, 0x0017, 0x006f}, + {0x01e6, 0x0064, 0x01e5}}, + {{0x0067, 0x0015, 0x0062}, + {0x0012, 0x0000, 0x0014}, + {0x0065, 0x0016, 0x006d}}, + {{0x01e9, 0x0063, 0x01e4}, + {0x006b, 0x0013, 0x0071}, + {0x01e3, 0x0070, 0x01f3}}}, + {{{0x07fe, 0x01e7, 0x07f3}, + {0x01ef, 0x0060, 0x01ee}, + {0x07f0, 0x01e2, 0x07fa}}, + {{0x03f3, 0x006a, 0x01e8}, + {0x0075, 0x0010, 0x0073}, + {0x01f4, 0x006e, 0x03f7}}, + {{0x07f6, 0x01e0, 0x07f9}, + {0x03f2, 0x0066, 0x01f5}, + {0x07ff, 0x01f7, 0x07f4}}}}; + +const USHORT FDKaacEnc_huff_ctab2[3][3][3][3] = {{{{0x01f3, 0x006f, 0x01fd}, + {0x00eb, 0x0023, 0x00ea}, + {0x01f7, 0x00e8, 0x01fa}}, + {{0x00f2, 0x002d, 0x0070}, + {0x0020, 0x0006, 0x002b}, + {0x006e, 0x0028, 0x00e9}}, + {{0x01f9, 0x0066, 0x00f8}, + {0x00e7, 0x001b, 0x00f1}, + {0x01f4, 0x006b, 0x01f5}}}, + {{{0x00ec, 0x002a, 0x006c}, + {0x002c, 0x000a, 0x0027}, + {0x0067, 0x001a, 0x00f5}}, + {{0x0024, 0x0008, 0x001f}, + {0x0009, 0x0000, 0x0007}, + {0x001d, 0x000b, 0x0030}}, + {{0x00ef, 0x001c, 0x0064}, + {0x001e, 0x000c, 0x0029}, + {0x00f3, 0x002f, 0x00f0}}}, + {{{0x01fc, 0x0071, 0x01f2}, + {0x00f4, 0x0021, 0x00e6}, + {0x00f7, 0x0068, 0x01f8}}, + {{0x00ee, 0x0022, 0x0065}, + {0x0031, 0x0002, 0x0026}, + {0x00ed, 0x0025, 0x006a}}, + {{0x01fb, 0x0072, 0x01fe}, + {0x0069, 0x002e, 0x00f6}, + {0x01ff, 0x006d, 0x01f6}}}}; + +const USHORT FDKaacEnc_huff_ctab3[3][3][3][3] = {{{{0x0000, 0x0009, 0x00ef}, + {0x000b, 0x0019, 0x00f0}, + {0x01eb, 0x01e6, 0x03f2}}, + {{0x000a, 0x0035, 0x01ef}, + {0x0034, 0x0037, 0x01e9}, + {0x01ed, 0x01e7, 0x03f3}}, + {{0x01ee, 0x03ed, 0x1ffa}, + {0x01ec, 0x01f2, 0x07f9}, + {0x07f8, 0x03f8, 0x0ff8}}}, + {{{0x0008, 0x0038, 0x03f6}, + {0x0036, 0x0075, 0x03f1}, + {0x03eb, 0x03ec, 0x0ff4}}, + {{0x0018, 0x0076, 0x07f4}, + {0x0039, 0x0074, 0x03ef}, + {0x01f3, 0x01f4, 0x07f6}}, + {{0x01e8, 0x03ea, 0x1ffc}, + {0x00f2, 0x01f1, 0x0ffb}, + {0x03f5, 0x07f3, 0x0ffc}}}, + {{{0x00ee, 0x03f7, 0x7ffe}, + {0x01f0, 0x07f5, 0x7ffd}, + {0x1ffb, 0x3ffa, 0xffff}}, + {{0x00f1, 0x03f0, 0x3ffc}, + {0x01ea, 0x03ee, 0x3ffb}, + {0x0ff6, 0x0ffa, 0x7ffc}}, + {{0x07f2, 0x0ff5, 0xfffe}, + {0x03f4, 0x07f7, 0x7ffb}, + {0x0ff7, 0x0ff9, 0x7ffa}}}}; + +const USHORT FDKaacEnc_huff_ctab4[3][3][3][3] = {{{{0x0007, 0x0016, 0x00f6}, + {0x0018, 0x0008, 0x00ef}, + {0x01ef, 0x00f3, 0x07f8}}, + {{0x0019, 0x0017, 0x00ed}, + {0x0015, 0x0001, 0x00e2}, + {0x00f0, 0x0070, 0x03f0}}, + {{0x01ee, 0x00f1, 0x07fa}, + {0x00ee, 0x00e4, 0x03f2}, + {0x07f6, 0x03ef, 0x07fd}}}, + {{{0x0005, 0x0014, 0x00f2}, + {0x0009, 0x0004, 0x00e5}, + {0x00f4, 0x00e8, 0x03f4}}, + {{0x0006, 0x0002, 0x00e7}, + {0x0003, 0x0000, 0x006b}, + {0x00e3, 0x0069, 0x01f3}}, + {{0x00eb, 0x00e6, 0x03f6}, + {0x006e, 0x006a, 0x01f4}, + {0x03ec, 0x01f0, 0x03f9}}}, + {{{0x00f5, 0x00ec, 0x07fb}, + {0x00ea, 0x006f, 0x03f7}, + {0x07f9, 0x03f3, 0x0fff}}, + {{0x00e9, 0x006d, 0x03f8}, + {0x006c, 0x0068, 0x01f5}, + {0x03ee, 0x01f2, 0x07f4}}, + {{0x07f7, 0x03f1, 0x0ffe}, + {0x03ed, 0x01f1, 0x07f5}, + {0x07fe, 0x03f5, 0x07fc}}}}; + +const USHORT FDKaacEnc_huff_ctab5[9][9] = { + {0x1fff, 0x0ff7, 0x07f4, 0x07e8, 0x03f1, 0x07ee, 0x07f9, 0x0ff8, 0x1ffd}, + {0x0ffd, 0x07f1, 0x03e8, 0x01e8, 0x00f0, 0x01ec, 0x03ee, 0x07f2, 0x0ffa}, + {0x0ff4, 0x03ef, 0x01f2, 0x00e8, 0x0070, 0x00ec, 0x01f0, 0x03ea, 0x07f3}, + {0x07eb, 0x01eb, 0x00ea, 0x001a, 0x0008, 0x0019, 0x00ee, 0x01ef, 0x07ed}, + {0x03f0, 0x00f2, 0x0073, 0x000b, 0x0000, 0x000a, 0x0071, 0x00f3, 0x07e9}, + {0x07ef, 0x01ee, 0x00ef, 0x0018, 0x0009, 0x001b, 0x00eb, 0x01e9, 0x07ec}, + {0x07f6, 0x03eb, 0x01f3, 0x00ed, 0x0072, 0x00e9, 0x01f1, 0x03ed, 0x07f7}, + {0x0ff6, 0x07f0, 0x03e9, 0x01ed, 0x00f1, 0x01ea, 0x03ec, 0x07f8, 0x0ff9}, + {0x1ffc, 0x0ffc, 0x0ff5, 0x07ea, 0x03f3, 0x03f2, 0x07f5, 0x0ffb, 0x1ffe}}; + +const USHORT FDKaacEnc_huff_ctab6[9][9] = { + {0x07fe, 0x03fd, 0x01f1, 0x01eb, 0x01f4, 0x01ea, 0x01f0, 0x03fc, 0x07fd}, + {0x03f6, 0x01e5, 0x00ea, 0x006c, 0x0071, 0x0068, 0x00f0, 0x01e6, 0x03f7}, + {0x01f3, 0x00ef, 0x0032, 0x0027, 0x0028, 0x0026, 0x0031, 0x00eb, 0x01f7}, + {0x01e8, 0x006f, 0x002e, 0x0008, 0x0004, 0x0006, 0x0029, 0x006b, 0x01ee}, + {0x01ef, 0x0072, 0x002d, 0x0002, 0x0000, 0x0003, 0x002f, 0x0073, 0x01fa}, + {0x01e7, 0x006e, 0x002b, 0x0007, 0x0001, 0x0005, 0x002c, 0x006d, 0x01ec}, + {0x01f9, 0x00ee, 0x0030, 0x0024, 0x002a, 0x0025, 0x0033, 0x00ec, 0x01f2}, + {0x03f8, 0x01e4, 0x00ed, 0x006a, 0x0070, 0x0069, 0x0074, 0x00f1, 0x03fa}, + {0x07ff, 0x03f9, 0x01f6, 0x01ed, 0x01f8, 0x01e9, 0x01f5, 0x03fb, 0x07fc}}; + +const USHORT FDKaacEnc_huff_ctab7[8][8] = { + {0x0000, 0x0005, 0x0037, 0x0074, 0x00f2, 0x01eb, 0x03ed, 0x07f7}, + {0x0004, 0x000c, 0x0035, 0x0071, 0x00ec, 0x00ee, 0x01ee, 0x01f5}, + {0x0036, 0x0034, 0x0072, 0x00ea, 0x00f1, 0x01e9, 0x01f3, 0x03f5}, + {0x0073, 0x0070, 0x00eb, 0x00f0, 0x01f1, 0x01f0, 0x03ec, 0x03fa}, + {0x00f3, 0x00ed, 0x01e8, 0x01ef, 0x03ef, 0x03f1, 0x03f9, 0x07fb}, + {0x01ed, 0x00ef, 0x01ea, 0x01f2, 0x03f3, 0x03f8, 0x07f9, 0x07fc}, + {0x03ee, 0x01ec, 0x01f4, 0x03f4, 0x03f7, 0x07f8, 0x0ffd, 0x0ffe}, + {0x07f6, 0x03f0, 0x03f2, 0x03f6, 0x07fa, 0x07fd, 0x0ffc, 0x0fff}}; + +const USHORT FDKaacEnc_huff_ctab8[8][8] = { + {0x000e, 0x0005, 0x0010, 0x0030, 0x006f, 0x00f1, 0x01fa, 0x03fe}, + {0x0003, 0x0000, 0x0004, 0x0012, 0x002c, 0x006a, 0x0075, 0x00f8}, + {0x000f, 0x0002, 0x0006, 0x0014, 0x002e, 0x0069, 0x0072, 0x00f5}, + {0x002f, 0x0011, 0x0013, 0x002a, 0x0032, 0x006c, 0x00ec, 0x00fa}, + {0x0071, 0x002b, 0x002d, 0x0031, 0x006d, 0x0070, 0x00f2, 0x01f9}, + {0x00ef, 0x0068, 0x0033, 0x006b, 0x006e, 0x00ee, 0x00f9, 0x03fc}, + {0x01f8, 0x0074, 0x0073, 0x00ed, 0x00f0, 0x00f6, 0x01f6, 0x01fd}, + {0x03fd, 0x00f3, 0x00f4, 0x00f7, 0x01f7, 0x01fb, 0x01fc, 0x03ff}}; + +const USHORT FDKaacEnc_huff_ctab9[13][13] = { + {0x0000, 0x0005, 0x0037, 0x00e7, 0x01de, 0x03ce, 0x03d9, 0x07c8, 0x07cd, + 0x0fc8, 0x0fdd, 0x1fe4, 0x1fec}, + {0x0004, 0x000c, 0x0035, 0x0072, 0x00ea, 0x00ed, 0x01e2, 0x03d1, 0x03d3, + 0x03e0, 0x07d8, 0x0fcf, 0x0fd5}, + {0x0036, 0x0034, 0x0071, 0x00e8, 0x00ec, 0x01e1, 0x03cf, 0x03dd, 0x03db, + 0x07d0, 0x0fc7, 0x0fd4, 0x0fe4}, + {0x00e6, 0x0070, 0x00e9, 0x01dd, 0x01e3, 0x03d2, 0x03dc, 0x07cc, 0x07ca, + 0x07de, 0x0fd8, 0x0fea, 0x1fdb}, + {0x01df, 0x00eb, 0x01dc, 0x01e6, 0x03d5, 0x03de, 0x07cb, 0x07dd, 0x07dc, + 0x0fcd, 0x0fe2, 0x0fe7, 0x1fe1}, + {0x03d0, 0x01e0, 0x01e4, 0x03d6, 0x07c5, 0x07d1, 0x07db, 0x0fd2, 0x07e0, + 0x0fd9, 0x0feb, 0x1fe3, 0x1fe9}, + {0x07c4, 0x01e5, 0x03d7, 0x07c6, 0x07cf, 0x07da, 0x0fcb, 0x0fda, 0x0fe3, + 0x0fe9, 0x1fe6, 0x1ff3, 0x1ff7}, + {0x07d3, 0x03d8, 0x03e1, 0x07d4, 0x07d9, 0x0fd3, 0x0fde, 0x1fdd, 0x1fd9, + 0x1fe2, 0x1fea, 0x1ff1, 0x1ff6}, + {0x07d2, 0x03d4, 0x03da, 0x07c7, 0x07d7, 0x07e2, 0x0fce, 0x0fdb, 0x1fd8, + 0x1fee, 0x3ff0, 0x1ff4, 0x3ff2}, + {0x07e1, 0x03df, 0x07c9, 0x07d6, 0x0fca, 0x0fd0, 0x0fe5, 0x0fe6, 0x1feb, + 0x1fef, 0x3ff3, 0x3ff4, 0x3ff5}, + {0x0fe0, 0x07ce, 0x07d5, 0x0fc6, 0x0fd1, 0x0fe1, 0x1fe0, 0x1fe8, 0x1ff0, + 0x3ff1, 0x3ff8, 0x3ff6, 0x7ffc}, + {0x0fe8, 0x07df, 0x0fc9, 0x0fd7, 0x0fdc, 0x1fdc, 0x1fdf, 0x1fed, 0x1ff5, + 0x3ff9, 0x3ffb, 0x7ffd, 0x7ffe}, + {0x1fe7, 0x0fcc, 0x0fd6, 0x0fdf, 0x1fde, 0x1fda, 0x1fe5, 0x1ff2, 0x3ffa, + 0x3ff7, 0x3ffc, 0x3ffd, 0x7fff}}; + +const USHORT FDKaacEnc_huff_ctab10[13][13] = { + {0x0022, 0x0008, 0x001d, 0x0026, 0x005f, 0x00d3, 0x01cf, 0x03d0, 0x03d7, + 0x03ed, 0x07f0, 0x07f6, 0x0ffd}, + {0x0007, 0x0000, 0x0001, 0x0009, 0x0020, 0x0054, 0x0060, 0x00d5, 0x00dc, + 0x01d4, 0x03cd, 0x03de, 0x07e7}, + {0x001c, 0x0002, 0x0006, 0x000c, 0x001e, 0x0028, 0x005b, 0x00cd, 0x00d9, + 0x01ce, 0x01dc, 0x03d9, 0x03f1}, + {0x0025, 0x000b, 0x000a, 0x000d, 0x0024, 0x0057, 0x0061, 0x00cc, 0x00dd, + 0x01cc, 0x01de, 0x03d3, 0x03e7}, + {0x005d, 0x0021, 0x001f, 0x0023, 0x0027, 0x0059, 0x0064, 0x00d8, 0x00df, + 0x01d2, 0x01e2, 0x03dd, 0x03ee}, + {0x00d1, 0x0055, 0x0029, 0x0056, 0x0058, 0x0062, 0x00ce, 0x00e0, 0x00e2, + 0x01da, 0x03d4, 0x03e3, 0x07eb}, + {0x01c9, 0x005e, 0x005a, 0x005c, 0x0063, 0x00ca, 0x00da, 0x01c7, 0x01ca, + 0x01e0, 0x03db, 0x03e8, 0x07ec}, + {0x01e3, 0x00d2, 0x00cb, 0x00d0, 0x00d7, 0x00db, 0x01c6, 0x01d5, 0x01d8, + 0x03ca, 0x03da, 0x07ea, 0x07f1}, + {0x01e1, 0x00d4, 0x00cf, 0x00d6, 0x00de, 0x00e1, 0x01d0, 0x01d6, 0x03d1, + 0x03d5, 0x03f2, 0x07ee, 0x07fb}, + {0x03e9, 0x01cd, 0x01c8, 0x01cb, 0x01d1, 0x01d7, 0x01df, 0x03cf, 0x03e0, + 0x03ef, 0x07e6, 0x07f8, 0x0ffa}, + {0x03eb, 0x01dd, 0x01d3, 0x01d9, 0x01db, 0x03d2, 0x03cc, 0x03dc, 0x03ea, + 0x07ed, 0x07f3, 0x07f9, 0x0ff9}, + {0x07f2, 0x03ce, 0x01e4, 0x03cb, 0x03d8, 0x03d6, 0x03e2, 0x03e5, 0x07e8, + 0x07f4, 0x07f5, 0x07f7, 0x0ffb}, + {0x07fa, 0x03ec, 0x03df, 0x03e1, 0x03e4, 0x03e6, 0x03f0, 0x07e9, 0x07ef, + 0x0ff8, 0x0ffe, 0x0ffc, 0x0fff}}; + +const USHORT FDKaacEnc_huff_ctab11[21][17] = { + {0x0000, 0x0006, 0x0019, 0x003d, 0x009c, 0x00c6, 0x01a7, 0x0390, 0x03c2, + 0x03df, 0x07e6, 0x07f3, 0x0ffb, 0x07ec, 0x0ffa, 0x0ffe, 0x038e}, + {0x0005, 0x0001, 0x0008, 0x0014, 0x0037, 0x0042, 0x0092, 0x00af, 0x0191, + 0x01a5, 0x01b5, 0x039e, 0x03c0, 0x03a2, 0x03cd, 0x07d6, 0x00ae}, + {0x0017, 0x0007, 0x0009, 0x0018, 0x0039, 0x0040, 0x008e, 0x00a3, 0x00b8, + 0x0199, 0x01ac, 0x01c1, 0x03b1, 0x0396, 0x03be, 0x03ca, 0x009d}, + {0x003c, 0x0015, 0x0016, 0x001a, 0x003b, 0x0044, 0x0091, 0x00a5, 0x00be, + 0x0196, 0x01ae, 0x01b9, 0x03a1, 0x0391, 0x03a5, 0x03d5, 0x0094}, + {0x009a, 0x0036, 0x0038, 0x003a, 0x0041, 0x008c, 0x009b, 0x00b0, 0x00c3, + 0x019e, 0x01ab, 0x01bc, 0x039f, 0x038f, 0x03a9, 0x03cf, 0x0093}, + {0x00bf, 0x003e, 0x003f, 0x0043, 0x0045, 0x009e, 0x00a7, 0x00b9, 0x0194, + 0x01a2, 0x01ba, 0x01c3, 0x03a6, 0x03a7, 0x03bb, 0x03d4, 0x009f}, + {0x01a0, 0x008f, 0x008d, 0x0090, 0x0098, 0x00a6, 0x00b6, 0x00c4, 0x019f, + 0x01af, 0x01bf, 0x0399, 0x03bf, 0x03b4, 0x03c9, 0x03e7, 0x00a8}, + {0x01b6, 0x00ab, 0x00a4, 0x00aa, 0x00b2, 0x00c2, 0x00c5, 0x0198, 0x01a4, + 0x01b8, 0x038c, 0x03a4, 0x03c4, 0x03c6, 0x03dd, 0x03e8, 0x00ad}, + {0x03af, 0x0192, 0x00bd, 0x00bc, 0x018e, 0x0197, 0x019a, 0x01a3, 0x01b1, + 0x038d, 0x0398, 0x03b7, 0x03d3, 0x03d1, 0x03db, 0x07dd, 0x00b4}, + {0x03de, 0x01a9, 0x019b, 0x019c, 0x01a1, 0x01aa, 0x01ad, 0x01b3, 0x038b, + 0x03b2, 0x03b8, 0x03ce, 0x03e1, 0x03e0, 0x07d2, 0x07e5, 0x00b7}, + {0x07e3, 0x01bb, 0x01a8, 0x01a6, 0x01b0, 0x01b2, 0x01b7, 0x039b, 0x039a, + 0x03ba, 0x03b5, 0x03d6, 0x07d7, 0x03e4, 0x07d8, 0x07ea, 0x00ba}, + {0x07e8, 0x03a0, 0x01bd, 0x01b4, 0x038a, 0x01c4, 0x0392, 0x03aa, 0x03b0, + 0x03bc, 0x03d7, 0x07d4, 0x07dc, 0x07db, 0x07d5, 0x07f0, 0x00c1}, + {0x07fb, 0x03c8, 0x03a3, 0x0395, 0x039d, 0x03ac, 0x03ae, 0x03c5, 0x03d8, + 0x03e2, 0x03e6, 0x07e4, 0x07e7, 0x07e0, 0x07e9, 0x07f7, 0x0190}, + {0x07f2, 0x0393, 0x01be, 0x01c0, 0x0394, 0x0397, 0x03ad, 0x03c3, 0x03c1, + 0x03d2, 0x07da, 0x07d9, 0x07df, 0x07eb, 0x07f4, 0x07fa, 0x0195}, + {0x07f8, 0x03bd, 0x039c, 0x03ab, 0x03a8, 0x03b3, 0x03b9, 0x03d0, 0x03e3, + 0x03e5, 0x07e2, 0x07de, 0x07ed, 0x07f1, 0x07f9, 0x07fc, 0x0193}, + {0x0ffd, 0x03dc, 0x03b6, 0x03c7, 0x03cc, 0x03cb, 0x03d9, 0x03da, 0x07d3, + 0x07e1, 0x07ee, 0x07ef, 0x07f5, 0x07f6, 0x0ffc, 0x0fff, 0x019d}, + {0x01c2, 0x00b5, 0x00a1, 0x0096, 0x0097, 0x0095, 0x0099, 0x00a0, 0x00a2, + 0x00ac, 0x00a9, 0x00b1, 0x00b3, 0x00bb, 0x00c0, 0x018f, 0x0004}, + {0x0018, 0x002e, 0x0000, 0x005a, 0x00a5, 0x00f8, 0x00b7, 0x0094, 0x00f9, + 0x004d, 0x0021, 0x002b, 0x004f, 0x007b, 0x00bc, 0x0046, 0x0015}, + {0x0042, 0x0037, 0x0078, 0x000d, 0x0068, 0x005f, 0x000d, 0x005e, 0x005a, + 0x00be, 0x0063, 0x007e, 0x001f, 0x0092, 0x001a, 0x00ab, 0x0032}, + {0x00e6, 0x0037, 0x0000, 0x0058, 0x000b, 0x005a, 0x00e1, 0x005d, 0x0029, + 0x0017, 0x007e, 0x0069, 0x00aa, 0x0054, 0x0029, 0x0032, 0x0041}, + {0x0046, 0x00ea, 0x0034, 0x00ea, 0x0011, 0x001b, 0x00a9, 0x0094, 0x00e2, + 0x0031, 0x00d0, 0x00e5, 0x0007, 0x0070, 0x0069, 0x003e, 0x0021}}; + +const ULONG FDKaacEnc_huff_ctabscf[121] = { + 0x0003ffe8, 0x0003ffe6, 0x0003ffe7, 0x0003ffe5, 0x0007fff5, 0x0007fff1, + 0x0007ffed, 0x0007fff6, 0x0007ffee, 0x0007ffef, 0x0007fff0, 0x0007fffc, + 0x0007fffd, 0x0007ffff, 0x0007fffe, 0x0007fff7, 0x0007fff8, 0x0007fffb, + 0x0007fff9, 0x0003ffe4, 0x0007fffa, 0x0003ffe3, 0x0001ffef, 0x0001fff0, + 0x0000fff5, 0x0001ffee, 0x0000fff2, 0x0000fff3, 0x0000fff4, 0x0000fff1, + 0x00007ff6, 0x00007ff7, 0x00003ff9, 0x00003ff5, 0x00003ff7, 0x00003ff3, + 0x00003ff6, 0x00003ff2, 0x00001ff7, 0x00001ff5, 0x00000ff9, 0x00000ff7, + 0x00000ff6, 0x000007f9, 0x00000ff4, 0x000007f8, 0x000003f9, 0x000003f7, + 0x000003f5, 0x000001f8, 0x000001f7, 0x000000fa, 0x000000f8, 0x000000f6, + 0x00000079, 0x0000003a, 0x00000038, 0x0000001a, 0x0000000b, 0x00000004, + 0x00000000, 0x0000000a, 0x0000000c, 0x0000001b, 0x00000039, 0x0000003b, + 0x00000078, 0x0000007a, 0x000000f7, 0x000000f9, 0x000001f6, 0x000001f9, + 0x000003f4, 0x000003f6, 0x000003f8, 0x000007f5, 0x000007f4, 0x000007f6, + 0x000007f7, 0x00000ff5, 0x00000ff8, 0x00001ff4, 0x00001ff6, 0x00001ff8, + 0x00003ff8, 0x00003ff4, 0x0000fff0, 0x00007ff4, 0x0000fff6, 0x00007ff5, + 0x0003ffe2, 0x0007ffd9, 0x0007ffda, 0x0007ffdb, 0x0007ffdc, 0x0007ffdd, + 0x0007ffde, 0x0007ffd8, 0x0007ffd2, 0x0007ffd3, 0x0007ffd4, 0x0007ffd5, + 0x0007ffd6, 0x0007fff2, 0x0007ffdf, 0x0007ffe7, 0x0007ffe8, 0x0007ffe9, + 0x0007ffea, 0x0007ffeb, 0x0007ffe6, 0x0007ffe0, 0x0007ffe1, 0x0007ffe2, + 0x0007ffe3, 0x0007ffe4, 0x0007ffe5, 0x0007ffd7, 0x0007ffec, 0x0007fff4, + 0x0007fff3}; + +/* + table of (0.50000...1.00000) ^0.75 +*/ +const FIXP_QTD FDKaacEnc_mTab_3_4[MANT_SIZE] = { + QTC(0x4c1bf829), QTC(0x4c3880de), QTC(0x4c550603), QTC(0x4c71879c), + QTC(0x4c8e05aa), QTC(0x4caa8030), QTC(0x4cc6f72f), QTC(0x4ce36aab), + QTC(0x4cffdaa4), QTC(0x4d1c471d), QTC(0x4d38b019), QTC(0x4d55159a), + QTC(0x4d7177a1), QTC(0x4d8dd631), QTC(0x4daa314b), QTC(0x4dc688f3), + QTC(0x4de2dd2a), QTC(0x4dff2df2), QTC(0x4e1b7b4d), QTC(0x4e37c53d), + QTC(0x4e540bc5), QTC(0x4e704ee6), QTC(0x4e8c8ea3), QTC(0x4ea8cafd), + QTC(0x4ec503f7), QTC(0x4ee13992), QTC(0x4efd6bd0), QTC(0x4f199ab4), + QTC(0x4f35c640), QTC(0x4f51ee75), QTC(0x4f6e1356), QTC(0x4f8a34e4), + QTC(0x4fa65321), QTC(0x4fc26e10), QTC(0x4fde85b2), QTC(0x4ffa9a0a), + QTC(0x5016ab18), QTC(0x5032b8e0), QTC(0x504ec362), QTC(0x506acaa1), + QTC(0x5086cea0), QTC(0x50a2cf5e), QTC(0x50becce0), QTC(0x50dac725), + QTC(0x50f6be31), QTC(0x5112b205), QTC(0x512ea2a3), QTC(0x514a900d), + QTC(0x51667a45), QTC(0x5182614c), QTC(0x519e4524), QTC(0x51ba25cf), + QTC(0x51d60350), QTC(0x51f1dda7), QTC(0x520db4d6), QTC(0x522988e0), + QTC(0x524559c6), QTC(0x52612789), QTC(0x527cf22d), QTC(0x5298b9b1), + QTC(0x52b47e19), QTC(0x52d03f65), QTC(0x52ebfd98), QTC(0x5307b8b4), + QTC(0x532370b9), QTC(0x533f25aa), QTC(0x535ad789), QTC(0x53768656), + QTC(0x53923215), QTC(0x53addac6), QTC(0x53c9806b), QTC(0x53e52306), + QTC(0x5400c298), QTC(0x541c5f24), QTC(0x5437f8ab), QTC(0x54538f2e), + QTC(0x546f22af), QTC(0x548ab330), QTC(0x54a640b3), QTC(0x54c1cb38), + QTC(0x54dd52c2), QTC(0x54f8d753), QTC(0x551458eb), QTC(0x552fd78d), + QTC(0x554b5339), QTC(0x5566cbf3), QTC(0x558241bb), QTC(0x559db492), + QTC(0x55b9247b), QTC(0x55d49177), QTC(0x55effb87), QTC(0x560b62ad), + QTC(0x5626c6eb), QTC(0x56422842), QTC(0x565d86b4), QTC(0x5678e242), + QTC(0x56943aee), QTC(0x56af90b9), QTC(0x56cae3a4), QTC(0x56e633b2), + QTC(0x570180e4), QTC(0x571ccb3b), QTC(0x573812b8), QTC(0x5753575e), + QTC(0x576e992e), QTC(0x5789d829), QTC(0x57a51450), QTC(0x57c04da6), + QTC(0x57db842b), QTC(0x57f6b7e1), QTC(0x5811e8c9), QTC(0x582d16e6), + QTC(0x58484238), QTC(0x58636ac0), QTC(0x587e9081), QTC(0x5899b37c), + QTC(0x58b4d3b1), QTC(0x58cff123), QTC(0x58eb0bd3), QTC(0x590623c2), + QTC(0x592138f2), QTC(0x593c4b63), QTC(0x59575b19), QTC(0x59726812), + QTC(0x598d7253), QTC(0x59a879da), QTC(0x59c37eab), QTC(0x59de80c6), + QTC(0x59f9802d), QTC(0x5a147ce0), QTC(0x5a2f76e2), QTC(0x5a4a6e34), + QTC(0x5a6562d6), QTC(0x5a8054cb), QTC(0x5a9b4414), QTC(0x5ab630b2), + QTC(0x5ad11aa6), QTC(0x5aec01f1), QTC(0x5b06e696), QTC(0x5b21c895), + QTC(0x5b3ca7ef), QTC(0x5b5784a6), QTC(0x5b725ebc), QTC(0x5b8d3631), + QTC(0x5ba80b06), QTC(0x5bc2dd3e), QTC(0x5bddacd9), QTC(0x5bf879d8), + QTC(0x5c13443d), QTC(0x5c2e0c09), QTC(0x5c48d13e), QTC(0x5c6393dc), + QTC(0x5c7e53e5), QTC(0x5c99115a), QTC(0x5cb3cc3c), QTC(0x5cce848d), + QTC(0x5ce93a4e), QTC(0x5d03ed80), QTC(0x5d1e9e24), QTC(0x5d394c3b), + QTC(0x5d53f7c7), QTC(0x5d6ea0c9), QTC(0x5d894742), QTC(0x5da3eb33), + QTC(0x5dbe8c9e), QTC(0x5dd92b84), QTC(0x5df3c7e5), QTC(0x5e0e61c3), + QTC(0x5e28f920), QTC(0x5e438dfc), QTC(0x5e5e2059), QTC(0x5e78b037), + QTC(0x5e933d99), QTC(0x5eadc87e), QTC(0x5ec850e9), QTC(0x5ee2d6da), + QTC(0x5efd5a53), QTC(0x5f17db54), QTC(0x5f3259e0), QTC(0x5f4cd5f6), + QTC(0x5f674f99), QTC(0x5f81c6c8), QTC(0x5f9c3b87), QTC(0x5fb6add4), + QTC(0x5fd11db3), QTC(0x5feb8b23), QTC(0x6005f626), QTC(0x60205ebd), + QTC(0x603ac4e9), QTC(0x605528ac), QTC(0x606f8a05), QTC(0x6089e8f7), + QTC(0x60a44583), QTC(0x60be9fa9), QTC(0x60d8f76b), QTC(0x60f34cca), + QTC(0x610d9fc7), QTC(0x6127f062), QTC(0x61423e9e), QTC(0x615c8a7a), + QTC(0x6176d3f9), QTC(0x61911b1b), QTC(0x61ab5fe1), QTC(0x61c5a24d), + QTC(0x61dfe25f), QTC(0x61fa2018), QTC(0x62145b7a), QTC(0x622e9485), + QTC(0x6248cb3b), QTC(0x6262ff9d), QTC(0x627d31ab), QTC(0x62976167), + QTC(0x62b18ed1), QTC(0x62cbb9eb), QTC(0x62e5e2b6), QTC(0x63000933), + QTC(0x631a2d62), QTC(0x63344f45), QTC(0x634e6edd), QTC(0x63688c2b), + QTC(0x6382a730), QTC(0x639cbfec), QTC(0x63b6d661), QTC(0x63d0ea90), + QTC(0x63eafc7a), QTC(0x64050c1f), QTC(0x641f1982), QTC(0x643924a2), + QTC(0x64532d80), QTC(0x646d341f), QTC(0x6487387e), QTC(0x64a13a9e), + QTC(0x64bb3a81), QTC(0x64d53828), QTC(0x64ef3393), QTC(0x65092cc4), + QTC(0x652323bb), QTC(0x653d1879), QTC(0x65570b00), QTC(0x6570fb50), + QTC(0x658ae96b), QTC(0x65a4d550), QTC(0x65bebf01), QTC(0x65d8a680), + QTC(0x65f28bcc), QTC(0x660c6ee8), QTC(0x66264fd3), QTC(0x66402e8f), + QTC(0x665a0b1c), QTC(0x6673e57d), QTC(0x668dbdb0), QTC(0x66a793b8), + QTC(0x66c16795), QTC(0x66db3949), QTC(0x66f508d4), QTC(0x670ed636), + QTC(0x6728a172), QTC(0x67426a87), QTC(0x675c3177), QTC(0x6775f643), + QTC(0x678fb8eb), QTC(0x67a97971), QTC(0x67c337d5), QTC(0x67dcf418), + QTC(0x67f6ae3b), QTC(0x6810663f), QTC(0x682a1c25), QTC(0x6843cfed), + QTC(0x685d8199), QTC(0x68773129), QTC(0x6890de9f), QTC(0x68aa89fa), + QTC(0x68c4333d), QTC(0x68ddda67), QTC(0x68f77f7a), QTC(0x69112277), + QTC(0x692ac35e), QTC(0x69446230), QTC(0x695dfeee), QTC(0x6977999a), + QTC(0x69913232), QTC(0x69aac8ba), QTC(0x69c45d31), QTC(0x69ddef98), + QTC(0x69f77ff0), QTC(0x6a110e3a), QTC(0x6a2a9a77), QTC(0x6a4424a8), + QTC(0x6a5daccc), QTC(0x6a7732e6), QTC(0x6a90b6f6), QTC(0x6aaa38fd), + QTC(0x6ac3b8fb), QTC(0x6add36f2), QTC(0x6af6b2e2), QTC(0x6b102ccd), + QTC(0x6b29a4b2), QTC(0x6b431a92), QTC(0x6b5c8e6f), QTC(0x6b76004a), + QTC(0x6b8f7022), QTC(0x6ba8ddf9), QTC(0x6bc249d0), QTC(0x6bdbb3a7), + QTC(0x6bf51b80), QTC(0x6c0e815a), QTC(0x6c27e537), QTC(0x6c414718), + QTC(0x6c5aa6fd), QTC(0x6c7404e7), QTC(0x6c8d60d7), QTC(0x6ca6bace), + QTC(0x6cc012cc), QTC(0x6cd968d2), QTC(0x6cf2bce1), QTC(0x6d0c0ef9), + QTC(0x6d255f1d), QTC(0x6d3ead4b), QTC(0x6d57f985), QTC(0x6d7143cc), + QTC(0x6d8a8c21), QTC(0x6da3d283), QTC(0x6dbd16f5), QTC(0x6dd65976), + QTC(0x6def9a08), QTC(0x6e08d8ab), QTC(0x6e221560), QTC(0x6e3b5027), + QTC(0x6e548902), QTC(0x6e6dbff1), QTC(0x6e86f4f5), QTC(0x6ea0280e), + QTC(0x6eb9593e), QTC(0x6ed28885), QTC(0x6eebb5e3), QTC(0x6f04e15a), + QTC(0x6f1e0aea), QTC(0x6f373294), QTC(0x6f505859), QTC(0x6f697c39), + QTC(0x6f829e35), QTC(0x6f9bbe4e), QTC(0x6fb4dc85), QTC(0x6fcdf8d9), + QTC(0x6fe7134d), QTC(0x70002be0), QTC(0x70194293), QTC(0x70325767), + QTC(0x704b6a5d), QTC(0x70647b76), QTC(0x707d8ab1), QTC(0x70969811), + QTC(0x70afa394), QTC(0x70c8ad3d), QTC(0x70e1b50c), QTC(0x70fabb01), + QTC(0x7113bf1d), QTC(0x712cc161), QTC(0x7145c1ce), QTC(0x715ec064), + QTC(0x7177bd24), QTC(0x7190b80f), QTC(0x71a9b124), QTC(0x71c2a866), + QTC(0x71db9dd4), QTC(0x71f49170), QTC(0x720d8339), QTC(0x72267331), + QTC(0x723f6159), QTC(0x72584db0), QTC(0x72713838), QTC(0x728a20f1), + QTC(0x72a307db), QTC(0x72bbecf9), QTC(0x72d4d049), QTC(0x72edb1ce), + QTC(0x73069187), QTC(0x731f6f75), QTC(0x73384b98), QTC(0x735125f3), + QTC(0x7369fe84), QTC(0x7382d54d), QTC(0x739baa4e), QTC(0x73b47d89), + QTC(0x73cd4efd), QTC(0x73e61eab), QTC(0x73feec94), QTC(0x7417b8b8), + QTC(0x74308319), QTC(0x74494bb6), QTC(0x74621291), QTC(0x747ad7aa), + QTC(0x74939b02), QTC(0x74ac5c98), QTC(0x74c51c6f), QTC(0x74ddda86), + QTC(0x74f696de), QTC(0x750f5178), QTC(0x75280a54), QTC(0x7540c174), + QTC(0x755976d7), QTC(0x75722a7e), QTC(0x758adc69), QTC(0x75a38c9b), + QTC(0x75bc3b12), QTC(0x75d4e7cf), QTC(0x75ed92d4), QTC(0x76063c21), + QTC(0x761ee3b6), QTC(0x76378994), QTC(0x76502dbc), QTC(0x7668d02e), + QTC(0x768170eb), QTC(0x769a0ff3), QTC(0x76b2ad47), QTC(0x76cb48e7), + QTC(0x76e3e2d5), QTC(0x76fc7b10), QTC(0x7715119a), QTC(0x772da673), + QTC(0x7746399b), QTC(0x775ecb13), QTC(0x77775adc), QTC(0x778fe8f6), + QTC(0x77a87561), QTC(0x77c1001f), QTC(0x77d98930), QTC(0x77f21095), + QTC(0x780a964d), QTC(0x78231a5b), QTC(0x783b9cbd), QTC(0x78541d75), + QTC(0x786c9c84), QTC(0x788519e9), QTC(0x789d95a6), QTC(0x78b60fbb), + QTC(0x78ce8828), QTC(0x78e6feef), QTC(0x78ff740f), QTC(0x7917e78a), + QTC(0x7930595f), QTC(0x7948c990), QTC(0x7961381d), QTC(0x7979a506), + QTC(0x7992104c), QTC(0x79aa79f0), QTC(0x79c2e1f1), QTC(0x79db4852), + QTC(0x79f3ad11), QTC(0x7a0c1031), QTC(0x7a2471b0), QTC(0x7a3cd191), + QTC(0x7a552fd3), QTC(0x7a6d8c76), QTC(0x7a85e77d), QTC(0x7a9e40e6), + QTC(0x7ab698b2), QTC(0x7aceeee3), QTC(0x7ae74378), QTC(0x7aff9673), + QTC(0x7b17e7d2), QTC(0x7b303799), QTC(0x7b4885c5), QTC(0x7b60d259), + QTC(0x7b791d55), QTC(0x7b9166b9), QTC(0x7ba9ae86), QTC(0x7bc1f4bc), + QTC(0x7bda395c), QTC(0x7bf27c66), QTC(0x7c0abddb), QTC(0x7c22fdbb), + QTC(0x7c3b3c07), QTC(0x7c5378c0), QTC(0x7c6bb3e5), QTC(0x7c83ed78), + QTC(0x7c9c2579), QTC(0x7cb45be9), QTC(0x7ccc90c7), QTC(0x7ce4c414), + QTC(0x7cfcf5d2), QTC(0x7d152600), QTC(0x7d2d549f), QTC(0x7d4581b0), + QTC(0x7d5dad32), QTC(0x7d75d727), QTC(0x7d8dff8f), QTC(0x7da6266a), + QTC(0x7dbe4bba), QTC(0x7dd66f7d), QTC(0x7dee91b6), QTC(0x7e06b264), + QTC(0x7e1ed188), QTC(0x7e36ef22), QTC(0x7e4f0b34), QTC(0x7e6725bd), + QTC(0x7e7f3ebd), QTC(0x7e975636), QTC(0x7eaf6c28), QTC(0x7ec78093), + QTC(0x7edf9378), QTC(0x7ef7a4d7), QTC(0x7f0fb4b1), QTC(0x7f27c307), + QTC(0x7f3fcfd8), QTC(0x7f57db25), QTC(0x7f6fe4ef), QTC(0x7f87ed36), + QTC(0x7f9ff3fb), QTC(0x7fb7f93e), QTC(0x7fcffcff), QTC(0x7fe7ff40)}; + +/* + table of pow(2.0,0.25*q)/2.0, q[0..4) +*/ +const FIXP_QTD FDKaacEnc_quantTableQ[4] = {QTC(0x40000000), QTC(0x4c1bf7ff), + QTC(0x5a82797f), QTC(0x6ba27e7f)}; + +/* + table of pow(2.0,0.75*e)/8.0, e[0..4) +*/ +const FIXP_QTD FDKaacEnc_quantTableE[4] = {QTC(0x10000000), QTC(0x1ae89f99), + QTC(0x2d413ccd), QTC(0x4c1bf828)}; + +/* + table to count used number of bits +*/ +const SHORT FDKaacEnc_sideInfoTabLong[] = { + 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, + 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, + 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, + 0x0009, 0x0009, 0x0009, 0x0009, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, + 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, + 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e}; + +const SHORT FDKaacEnc_sideInfoTabShort[] = { + 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000d, 0x000d}; + +/* + Psy Configuration constants +*/ + +const SFB_PARAM_LONG p_FDKaacEnc_8000_long_1024 = { + 40, {12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, + 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 24, 24, 24, 28, + 28, 32, 36, 36, 40, 44, 48, 52, 56, 60, 64, 80}}; +const SFB_PARAM_SHORT p_FDKaacEnc_8000_short_128 = { + 15, {4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 20, 20}}; + +const SFB_PARAM_LONG p_FDKaacEnc_11025_long_1024 = { + 43, {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, + 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_11025_short_128 = { + 15, {4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20}}; + +const SFB_PARAM_LONG p_FDKaacEnc_12000_long_1024 = { + 43, {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, + 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_12000_short_128 = { + 15, {4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20}}; + +const SFB_PARAM_LONG p_FDKaacEnc_16000_long_1024 = { + 43, {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, + 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_16000_short_128 = { + 15, {4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20}}; +const SFB_PARAM_LONG p_FDKaacEnc_22050_long_1024 = { + 47, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, + 28, 28, 32, 36, 36, 40, 44, 48, 52, 52, 64, 64, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_22050_short_128 = { + 15, {4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 20}}; +const SFB_PARAM_LONG p_FDKaacEnc_24000_long_1024 = { + 47, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, + 28, 28, 32, 36, 36, 40, 44, 48, 52, 52, 64, 64, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_24000_short_128 = { + 15, {4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 20}}; +const SFB_PARAM_LONG p_FDKaacEnc_32000_long_1024 = { + 51, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}}; +const SFB_PARAM_SHORT p_FDKaacEnc_32000_short_128 = { + 14, {4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16}}; +const SFB_PARAM_LONG p_FDKaacEnc_44100_long_1024 = { + 49, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 96}}; +const SFB_PARAM_SHORT p_FDKaacEnc_44100_short_128 = { + 14, {4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16}}; +const SFB_PARAM_LONG p_FDKaacEnc_48000_long_1024 = { + 49, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 96}}; +const SFB_PARAM_SHORT p_FDKaacEnc_48000_short_128 = { + 14, {4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16}}; +const SFB_PARAM_LONG p_FDKaacEnc_64000_long_1024 = { + 47, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, + 8, 8, 12, 12, 12, 16, 16, 16, 20, 24, 24, 28, 36, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40}}; +const SFB_PARAM_SHORT p_FDKaacEnc_64000_short_128 = { + 12, {4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36}}; +const SFB_PARAM_LONG p_FDKaacEnc_88200_long_1024 = { + 41, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, + 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_88200_short_128 = { + 12, {4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36}}; +const SFB_PARAM_LONG p_FDKaacEnc_96000_long_1024 = { + 41, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, + 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_96000_short_128 = { + 12, {4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36}}; + +/* + TNS filter coefficients +*/ + +/* + 3 bit resolution +*/ +const FIXP_LPC FDKaacEnc_tnsEncCoeff3[8] = { + FX_DBL2FXCONST_LPC(0x81f1d201), FX_DBL2FXCONST_LPC(0x91261481), + FX_DBL2FXCONST_LPC(0xadb92301), FX_DBL2FXCONST_LPC(0xd438af00), + FX_DBL2FXCONST_LPC(0x00000000), FX_DBL2FXCONST_LPC(0x37898080), + FX_DBL2FXCONST_LPC(0x64130dff), FX_DBL2FXCONST_LPC(0x7cca6fff)}; +const FIXP_LPC FDKaacEnc_tnsCoeff3Borders[8] = { + FX_DBL2FXCONST_LPC(0x80000001) /*-4*/, + FX_DBL2FXCONST_LPC(0x87b826df) /*-3*/, + FX_DBL2FXCONST_LPC(0x9df24154) /*-2*/, + FX_DBL2FXCONST_LPC(0xbfffffe5) /*-1*/, + FX_DBL2FXCONST_LPC(0xe9c5e578) /* 0*/, + FX_DBL2FXCONST_LPC(0x1c7b90f0) /* 1*/, + FX_DBL2FXCONST_LPC(0x4fce83a9) /* 2*/, + FX_DBL2FXCONST_LPC(0x7352f2c3) /* 3*/ +}; + +/* + 4 bit resolution +*/ +const FIXP_LPC FDKaacEnc_tnsEncCoeff4[16] = { + FX_DBL2FXCONST_LPC(0x808bc881), FX_DBL2FXCONST_LPC(0x84e2e581), + FX_DBL2FXCONST_LPC(0x8d6b4a01), FX_DBL2FXCONST_LPC(0x99da9201), + FX_DBL2FXCONST_LPC(0xa9c45701), FX_DBL2FXCONST_LPC(0xbc9dde81), + FX_DBL2FXCONST_LPC(0xd1c2d500), FX_DBL2FXCONST_LPC(0xe87ae540), + FX_DBL2FXCONST_LPC(0x00000000), FX_DBL2FXCONST_LPC(0x1a9cd9c0), + FX_DBL2FXCONST_LPC(0x340ff240), FX_DBL2FXCONST_LPC(0x4b3c8bff), + FX_DBL2FXCONST_LPC(0x5f1f5e7f), FX_DBL2FXCONST_LPC(0x6ed9eb7f), + FX_DBL2FXCONST_LPC(0x79bc387f), FX_DBL2FXCONST_LPC(0x7f4c7e7f)}; +const FIXP_LPC FDKaacEnc_tnsCoeff4Borders[16] = { + FX_DBL2FXCONST_LPC(0x80000001) /*-8*/, + FX_DBL2FXCONST_LPC(0x822deff0) /*-7*/, + FX_DBL2FXCONST_LPC(0x88a4bfe6) /*-6*/, + FX_DBL2FXCONST_LPC(0x932c159d) /*-5*/, + FX_DBL2FXCONST_LPC(0xa16827c2) /*-4*/, + FX_DBL2FXCONST_LPC(0xb2dcde27) /*-3*/, + FX_DBL2FXCONST_LPC(0xc6f20b91) /*-2*/, + FX_DBL2FXCONST_LPC(0xdcf89c64) /*-1*/, + FX_DBL2FXCONST_LPC(0xf4308ce1) /* 0*/, + FX_DBL2FXCONST_LPC(0x0d613054) /* 1*/, + FX_DBL2FXCONST_LPC(0x278dde80) /* 2*/, + FX_DBL2FXCONST_LPC(0x4000001b) /* 3*/, + FX_DBL2FXCONST_LPC(0x55a6127b) /* 4*/, + FX_DBL2FXCONST_LPC(0x678dde8f) /* 5*/, + FX_DBL2FXCONST_LPC(0x74ef0ed7) /* 6*/, + FX_DBL2FXCONST_LPC(0x7d33f0da) /* 7*/ +}; +const FIXP_DBL FDKaacEnc_mTab_4_3Elc[512] = { + FL2FXCONST_DBL(0.3968502629920499), FL2FXCONST_DBL(0.3978840634868335), + FL2FXCONST_DBL(0.3989185359354711), FL2FXCONST_DBL(0.3999536794661432), + FL2FXCONST_DBL(0.4009894932098531), FL2FXCONST_DBL(0.4020259763004115), + FL2FXCONST_DBL(0.4030631278744227), FL2FXCONST_DBL(0.4041009470712695), + FL2FXCONST_DBL(0.4051394330330996), FL2FXCONST_DBL(0.4061785849048110), + FL2FXCONST_DBL(0.4072184018340380), FL2FXCONST_DBL(0.4082588829711372), + FL2FXCONST_DBL(0.4093000274691739), FL2FXCONST_DBL(0.4103418344839078), + FL2FXCONST_DBL(0.4113843031737798), FL2FXCONST_DBL(0.4124274326998980), + FL2FXCONST_DBL(0.4134712222260245), FL2FXCONST_DBL(0.4145156709185620), + FL2FXCONST_DBL(0.4155607779465400), FL2FXCONST_DBL(0.4166065424816022), + FL2FXCONST_DBL(0.4176529636979932), FL2FXCONST_DBL(0.4187000407725452), + FL2FXCONST_DBL(0.4197477728846652), FL2FXCONST_DBL(0.4207961592163222), + FL2FXCONST_DBL(0.4218451989520345), FL2FXCONST_DBL(0.4228948912788567), + FL2FXCONST_DBL(0.4239452353863673), FL2FXCONST_DBL(0.4249962304666564), + FL2FXCONST_DBL(0.4260478757143130), FL2FXCONST_DBL(0.4271001703264124), + FL2FXCONST_DBL(0.4281531135025046), FL2FXCONST_DBL(0.4292067044446017), + FL2FXCONST_DBL(0.4302609423571658), FL2FXCONST_DBL(0.4313158264470970), + FL2FXCONST_DBL(0.4323713559237216), FL2FXCONST_DBL(0.4334275299987803), + FL2FXCONST_DBL(0.4344843478864161), FL2FXCONST_DBL(0.4355418088031630), + FL2FXCONST_DBL(0.4365999119679339), FL2FXCONST_DBL(0.4376586566020096), + FL2FXCONST_DBL(0.4387180419290272), FL2FXCONST_DBL(0.4397780671749683), + FL2FXCONST_DBL(0.4408387315681480), FL2FXCONST_DBL(0.4419000343392039), + FL2FXCONST_DBL(0.4429619747210847), FL2FXCONST_DBL(0.4440245519490388), + FL2FXCONST_DBL(0.4450877652606038), FL2FXCONST_DBL(0.4461516138955953), + FL2FXCONST_DBL(0.4472160970960963), FL2FXCONST_DBL(0.4482812141064458), + FL2FXCONST_DBL(0.4493469641732286), FL2FXCONST_DBL(0.4504133465452648), + FL2FXCONST_DBL(0.4514803604735984), FL2FXCONST_DBL(0.4525480052114875), + FL2FXCONST_DBL(0.4536162800143939), FL2FXCONST_DBL(0.4546851841399719), + FL2FXCONST_DBL(0.4557547168480591), FL2FXCONST_DBL(0.4568248774006652), + FL2FXCONST_DBL(0.4578956650619623), FL2FXCONST_DBL(0.4589670790982746), + FL2FXCONST_DBL(0.4600391187780688), FL2FXCONST_DBL(0.4611117833719430), + FL2FXCONST_DBL(0.4621850721526184), FL2FXCONST_DBL(0.4632589843949278), + FL2FXCONST_DBL(0.4643335193758069), FL2FXCONST_DBL(0.4654086763742842), + FL2FXCONST_DBL(0.4664844546714713), FL2FXCONST_DBL(0.4675608535505532), + FL2FXCONST_DBL(0.4686378722967790), FL2FXCONST_DBL(0.4697155101974522), + FL2FXCONST_DBL(0.4707937665419216), FL2FXCONST_DBL(0.4718726406215713), + FL2FXCONST_DBL(0.4729521317298118), FL2FXCONST_DBL(0.4740322391620711), + FL2FXCONST_DBL(0.4751129622157845), FL2FXCONST_DBL(0.4761943001903867), + FL2FXCONST_DBL(0.4772762523873015), FL2FXCONST_DBL(0.4783588181099338), + FL2FXCONST_DBL(0.4794419966636599), FL2FXCONST_DBL(0.4805257873558190), + FL2FXCONST_DBL(0.4816101894957042), FL2FXCONST_DBL(0.4826952023945537), + FL2FXCONST_DBL(0.4837808253655421), FL2FXCONST_DBL(0.4848670577237714), + FL2FXCONST_DBL(0.4859538987862632), FL2FXCONST_DBL(0.4870413478719488), + FL2FXCONST_DBL(0.4881294043016621), FL2FXCONST_DBL(0.4892180673981298), + FL2FXCONST_DBL(0.4903073364859640), FL2FXCONST_DBL(0.4913972108916533), + FL2FXCONST_DBL(0.4924876899435545), FL2FXCONST_DBL(0.4935787729718844), + FL2FXCONST_DBL(0.4946704593087116), FL2FXCONST_DBL(0.4957627482879484), + FL2FXCONST_DBL(0.4968556392453423), FL2FXCONST_DBL(0.4979491315184684), + FL2FXCONST_DBL(0.4990432244467211), FL2FXCONST_DBL(0.5001379173713062), + FL2FXCONST_DBL(0.5012332096352328), FL2FXCONST_DBL(0.5023291005833056), + FL2FXCONST_DBL(0.5034255895621171), FL2FXCONST_DBL(0.5045226759200399), + FL2FXCONST_DBL(0.5056203590072181), FL2FXCONST_DBL(0.5067186381755611), + FL2FXCONST_DBL(0.5078175127787346), FL2FXCONST_DBL(0.5089169821721536), + FL2FXCONST_DBL(0.5100170457129749), FL2FXCONST_DBL(0.5111177027600893), + FL2FXCONST_DBL(0.5122189526741143), FL2FXCONST_DBL(0.5133207948173868), + FL2FXCONST_DBL(0.5144232285539552), FL2FXCONST_DBL(0.5155262532495726), + FL2FXCONST_DBL(0.5166298682716894), FL2FXCONST_DBL(0.5177340729894460), + FL2FXCONST_DBL(0.5188388667736652), FL2FXCONST_DBL(0.5199442489968457), + FL2FXCONST_DBL(0.5210502190331544), FL2FXCONST_DBL(0.5221567762584198), + FL2FXCONST_DBL(0.5232639200501247), FL2FXCONST_DBL(0.5243716497873989), + FL2FXCONST_DBL(0.5254799648510130), FL2FXCONST_DBL(0.5265888646233705), + FL2FXCONST_DBL(0.5276983484885021), FL2FXCONST_DBL(0.5288084158320574), + FL2FXCONST_DBL(0.5299190660412995), FL2FXCONST_DBL(0.5310302985050975), + FL2FXCONST_DBL(0.5321421126139198), FL2FXCONST_DBL(0.5332545077598274), + FL2FXCONST_DBL(0.5343674833364678), FL2FXCONST_DBL(0.5354810387390675), + FL2FXCONST_DBL(0.5365951733644262), FL2FXCONST_DBL(0.5377098866109097), + FL2FXCONST_DBL(0.5388251778784438), FL2FXCONST_DBL(0.5399410465685075), + FL2FXCONST_DBL(0.5410574920841272), FL2FXCONST_DBL(0.5421745138298695), + FL2FXCONST_DBL(0.5432921112118353), FL2FXCONST_DBL(0.5444102836376534), + FL2FXCONST_DBL(0.5455290305164744), FL2FXCONST_DBL(0.5466483512589642), + FL2FXCONST_DBL(0.5477682452772976), FL2FXCONST_DBL(0.5488887119851529), + FL2FXCONST_DBL(0.5500097507977050), FL2FXCONST_DBL(0.5511313611316194), + FL2FXCONST_DBL(0.5522535424050467), FL2FXCONST_DBL(0.5533762940376158), + FL2FXCONST_DBL(0.5544996154504284), FL2FXCONST_DBL(0.5556235060660528), + FL2FXCONST_DBL(0.5567479653085183), FL2FXCONST_DBL(0.5578729926033087), + FL2FXCONST_DBL(0.5589985873773569), FL2FXCONST_DBL(0.5601247490590389), + FL2FXCONST_DBL(0.5612514770781683), FL2FXCONST_DBL(0.5623787708659898), + FL2FXCONST_DBL(0.5635066298551742), FL2FXCONST_DBL(0.5646350534798125), + FL2FXCONST_DBL(0.5657640411754097), FL2FXCONST_DBL(0.5668935923788799), + FL2FXCONST_DBL(0.5680237065285404), FL2FXCONST_DBL(0.5691543830641059), + FL2FXCONST_DBL(0.5702856214266832), FL2FXCONST_DBL(0.5714174210587655), + FL2FXCONST_DBL(0.5725497814042271), FL2FXCONST_DBL(0.5736827019083177), + FL2FXCONST_DBL(0.5748161820176573), FL2FXCONST_DBL(0.5759502211802304), + FL2FXCONST_DBL(0.5770848188453810), FL2FXCONST_DBL(0.5782199744638067), + FL2FXCONST_DBL(0.5793556874875542), FL2FXCONST_DBL(0.5804919573700131), + FL2FXCONST_DBL(0.5816287835659116), FL2FXCONST_DBL(0.5827661655313104), + FL2FXCONST_DBL(0.5839041027235979), FL2FXCONST_DBL(0.5850425946014850), + FL2FXCONST_DBL(0.5861816406250000), FL2FXCONST_DBL(0.5873212402554834), + FL2FXCONST_DBL(0.5884613929555826), FL2FXCONST_DBL(0.5896020981892474), + FL2FXCONST_DBL(0.5907433554217242), FL2FXCONST_DBL(0.5918851641195517), + FL2FXCONST_DBL(0.5930275237505556), FL2FXCONST_DBL(0.5941704337838434), + FL2FXCONST_DBL(0.5953138936897999), FL2FXCONST_DBL(0.5964579029400819), + FL2FXCONST_DBL(0.5976024610076139), FL2FXCONST_DBL(0.5987475673665825), + FL2FXCONST_DBL(0.5998932214924321), FL2FXCONST_DBL(0.6010394228618597), + FL2FXCONST_DBL(0.6021861709528106), FL2FXCONST_DBL(0.6033334652444733), + FL2FXCONST_DBL(0.6044813052172748), FL2FXCONST_DBL(0.6056296903528761), + FL2FXCONST_DBL(0.6067786201341671), FL2FXCONST_DBL(0.6079280940452625), + FL2FXCONST_DBL(0.6090781115714966), FL2FXCONST_DBL(0.6102286721994192), + FL2FXCONST_DBL(0.6113797754167908), FL2FXCONST_DBL(0.6125314207125777), + FL2FXCONST_DBL(0.6136836075769482), FL2FXCONST_DBL(0.6148363355012674), + FL2FXCONST_DBL(0.6159896039780929), FL2FXCONST_DBL(0.6171434125011708), + FL2FXCONST_DBL(0.6182977605654305), FL2FXCONST_DBL(0.6194526476669808), + FL2FXCONST_DBL(0.6206080733031054), FL2FXCONST_DBL(0.6217640369722584), + FL2FXCONST_DBL(0.6229205381740598), FL2FXCONST_DBL(0.6240775764092919), + FL2FXCONST_DBL(0.6252351511798939), FL2FXCONST_DBL(0.6263932619889586), + FL2FXCONST_DBL(0.6275519083407275), FL2FXCONST_DBL(0.6287110897405869), + FL2FXCONST_DBL(0.6298708056950635), FL2FXCONST_DBL(0.6310310557118203), + FL2FXCONST_DBL(0.6321918392996523), FL2FXCONST_DBL(0.6333531559684823), + FL2FXCONST_DBL(0.6345150052293571), FL2FXCONST_DBL(0.6356773865944432), + FL2FXCONST_DBL(0.6368402995770224), FL2FXCONST_DBL(0.6380037436914881), + FL2FXCONST_DBL(0.6391677184533411), FL2FXCONST_DBL(0.6403322233791856), + FL2FXCONST_DBL(0.6414972579867254), FL2FXCONST_DBL(0.6426628217947594), + FL2FXCONST_DBL(0.6438289143231779), FL2FXCONST_DBL(0.6449955350929588), + FL2FXCONST_DBL(0.6461626836261636), FL2FXCONST_DBL(0.6473303594459330), + FL2FXCONST_DBL(0.6484985620764839), FL2FXCONST_DBL(0.6496672910431047), + FL2FXCONST_DBL(0.6508365458721518), FL2FXCONST_DBL(0.6520063260910459), + FL2FXCONST_DBL(0.6531766312282679), FL2FXCONST_DBL(0.6543474608133552), + FL2FXCONST_DBL(0.6555188143768979), FL2FXCONST_DBL(0.6566906914505349), + FL2FXCONST_DBL(0.6578630915669509), FL2FXCONST_DBL(0.6590360142598715), + FL2FXCONST_DBL(0.6602094590640603), FL2FXCONST_DBL(0.6613834255153149), + FL2FXCONST_DBL(0.6625579131504635), FL2FXCONST_DBL(0.6637329215073610), + FL2FXCONST_DBL(0.6649084501248851), FL2FXCONST_DBL(0.6660844985429335), + FL2FXCONST_DBL(0.6672610663024197), FL2FXCONST_DBL(0.6684381529452691), + FL2FXCONST_DBL(0.6696157580144163), FL2FXCONST_DBL(0.6707938810538011), + FL2FXCONST_DBL(0.6719725216083646), FL2FXCONST_DBL(0.6731516792240465), + FL2FXCONST_DBL(0.6743313534477807), FL2FXCONST_DBL(0.6755115438274927), + FL2FXCONST_DBL(0.6766922499120955), FL2FXCONST_DBL(0.6778734712514865), + FL2FXCONST_DBL(0.6790552073965435), FL2FXCONST_DBL(0.6802374578991223), + FL2FXCONST_DBL(0.6814202223120524), FL2FXCONST_DBL(0.6826035001891340), + FL2FXCONST_DBL(0.6837872910851345), FL2FXCONST_DBL(0.6849715945557853), + FL2FXCONST_DBL(0.6861564101577784), FL2FXCONST_DBL(0.6873417374487629), + FL2FXCONST_DBL(0.6885275759873420), FL2FXCONST_DBL(0.6897139253330697), + FL2FXCONST_DBL(0.6909007850464473), FL2FXCONST_DBL(0.6920881546889198), + FL2FXCONST_DBL(0.6932760338228737), FL2FXCONST_DBL(0.6944644220116332), + FL2FXCONST_DBL(0.6956533188194565), FL2FXCONST_DBL(0.6968427238115332), + FL2FXCONST_DBL(0.6980326365539813), FL2FXCONST_DBL(0.6992230566138435), + FL2FXCONST_DBL(0.7004139835590845), FL2FXCONST_DBL(0.7016054169585869), + FL2FXCONST_DBL(0.7027973563821499), FL2FXCONST_DBL(0.7039898014004843), + FL2FXCONST_DBL(0.7051827515852106), FL2FXCONST_DBL(0.7063762065088554), + FL2FXCONST_DBL(0.7075701657448483), FL2FXCONST_DBL(0.7087646288675196), + FL2FXCONST_DBL(0.7099595954520960), FL2FXCONST_DBL(0.7111550650746988), + FL2FXCONST_DBL(0.7123510373123402), FL2FXCONST_DBL(0.7135475117429202), + FL2FXCONST_DBL(0.7147444879452244), FL2FXCONST_DBL(0.7159419654989200), + FL2FXCONST_DBL(0.7171399439845538), FL2FXCONST_DBL(0.7183384229835486), + FL2FXCONST_DBL(0.7195374020782005), FL2FXCONST_DBL(0.7207368808516762), + FL2FXCONST_DBL(0.7219368588880097), FL2FXCONST_DBL(0.7231373357720997), + FL2FXCONST_DBL(0.7243383110897066), FL2FXCONST_DBL(0.7255397844274496), + FL2FXCONST_DBL(0.7267417553728043), FL2FXCONST_DBL(0.7279442235140992), + FL2FXCONST_DBL(0.7291471884405130), FL2FXCONST_DBL(0.7303506497420724), + FL2FXCONST_DBL(0.7315546070096487), FL2FXCONST_DBL(0.7327590598349553), + FL2FXCONST_DBL(0.7339640078105445), FL2FXCONST_DBL(0.7351694505298055), + FL2FXCONST_DBL(0.7363753875869610), FL2FXCONST_DBL(0.7375818185770647), + FL2FXCONST_DBL(0.7387887430959987), FL2FXCONST_DBL(0.7399961607404706), + FL2FXCONST_DBL(0.7412040711080108), FL2FXCONST_DBL(0.7424124737969701), + FL2FXCONST_DBL(0.7436213684065166), FL2FXCONST_DBL(0.7448307545366334), + FL2FXCONST_DBL(0.7460406317881158), FL2FXCONST_DBL(0.7472509997625686), + FL2FXCONST_DBL(0.7484618580624036), FL2FXCONST_DBL(0.7496732062908372), + FL2FXCONST_DBL(0.7508850440518872), FL2FXCONST_DBL(0.7520973709503704), + FL2FXCONST_DBL(0.7533101865919009), FL2FXCONST_DBL(0.7545234905828862), + FL2FXCONST_DBL(0.7557372825305252), FL2FXCONST_DBL(0.7569515620428062), + FL2FXCONST_DBL(0.7581663287285035), FL2FXCONST_DBL(0.7593815821971756), + FL2FXCONST_DBL(0.7605973220591619), FL2FXCONST_DBL(0.7618135479255810), + FL2FXCONST_DBL(0.7630302594083277), FL2FXCONST_DBL(0.7642474561200708), + FL2FXCONST_DBL(0.7654651376742505), FL2FXCONST_DBL(0.7666833036850760), + FL2FXCONST_DBL(0.7679019537675227), FL2FXCONST_DBL(0.7691210875373307), + FL2FXCONST_DBL(0.7703407046110011), FL2FXCONST_DBL(0.7715608046057948), + FL2FXCONST_DBL(0.7727813871397293), FL2FXCONST_DBL(0.7740024518315765), + FL2FXCONST_DBL(0.7752239983008605), FL2FXCONST_DBL(0.7764460261678551), + FL2FXCONST_DBL(0.7776685350535814), FL2FXCONST_DBL(0.7788915245798054), + FL2FXCONST_DBL(0.7801149943690360), FL2FXCONST_DBL(0.7813389440445223), + FL2FXCONST_DBL(0.7825633732302513), FL2FXCONST_DBL(0.7837882815509458), + FL2FXCONST_DBL(0.7850136686320621), FL2FXCONST_DBL(0.7862395340997874), + FL2FXCONST_DBL(0.7874658775810378), FL2FXCONST_DBL(0.7886926987034559), + FL2FXCONST_DBL(0.7899199970954088), FL2FXCONST_DBL(0.7911477723859853), + FL2FXCONST_DBL(0.7923760242049944), FL2FXCONST_DBL(0.7936047521829623), + FL2FXCONST_DBL(0.7948339559511308), FL2FXCONST_DBL(0.7960636351414546), + FL2FXCONST_DBL(0.7972937893865995), FL2FXCONST_DBL(0.7985244183199399), + FL2FXCONST_DBL(0.7997555215755570), FL2FXCONST_DBL(0.8009870987882359), + FL2FXCONST_DBL(0.8022191495934644), FL2FXCONST_DBL(0.8034516736274301), + FL2FXCONST_DBL(0.8046846705270185), FL2FXCONST_DBL(0.8059181399298110), + FL2FXCONST_DBL(0.8071520814740822), FL2FXCONST_DBL(0.8083864947987989), + FL2FXCONST_DBL(0.8096213795436166), FL2FXCONST_DBL(0.8108567353488784), + FL2FXCONST_DBL(0.8120925618556127), FL2FXCONST_DBL(0.8133288587055308), + FL2FXCONST_DBL(0.8145656255410253), FL2FXCONST_DBL(0.8158028620051674), + FL2FXCONST_DBL(0.8170405677417053), FL2FXCONST_DBL(0.8182787423950622), + FL2FXCONST_DBL(0.8195173856103341), FL2FXCONST_DBL(0.8207564970332875), + FL2FXCONST_DBL(0.8219960763103580), FL2FXCONST_DBL(0.8232361230886477), + FL2FXCONST_DBL(0.8244766370159234), FL2FXCONST_DBL(0.8257176177406150), + FL2FXCONST_DBL(0.8269590649118125), FL2FXCONST_DBL(0.8282009781792650), + FL2FXCONST_DBL(0.8294433571933784), FL2FXCONST_DBL(0.8306862016052132), + FL2FXCONST_DBL(0.8319295110664831), FL2FXCONST_DBL(0.8331732852295520), + FL2FXCONST_DBL(0.8344175237474336), FL2FXCONST_DBL(0.8356622262737878), + FL2FXCONST_DBL(0.8369073924629202), FL2FXCONST_DBL(0.8381530219697793), + FL2FXCONST_DBL(0.8393991144499545), FL2FXCONST_DBL(0.8406456695596752), + FL2FXCONST_DBL(0.8418926869558079), FL2FXCONST_DBL(0.8431401662958544), + FL2FXCONST_DBL(0.8443881072379507), FL2FXCONST_DBL(0.8456365094408642), + FL2FXCONST_DBL(0.8468853725639923), FL2FXCONST_DBL(0.8481346962673606), + FL2FXCONST_DBL(0.8493844802116208), FL2FXCONST_DBL(0.8506347240580492), + FL2FXCONST_DBL(0.8518854274685442), FL2FXCONST_DBL(0.8531365901056253), + FL2FXCONST_DBL(0.8543882116324307), FL2FXCONST_DBL(0.8556402917127157), + FL2FXCONST_DBL(0.8568928300108512), FL2FXCONST_DBL(0.8581458261918209), + FL2FXCONST_DBL(0.8593992799212207), FL2FXCONST_DBL(0.8606531908652563), + FL2FXCONST_DBL(0.8619075586907414), FL2FXCONST_DBL(0.8631623830650962), + FL2FXCONST_DBL(0.8644176636563452), FL2FXCONST_DBL(0.8656734001331161), + FL2FXCONST_DBL(0.8669295921646375), FL2FXCONST_DBL(0.8681862394207371), + FL2FXCONST_DBL(0.8694433415718407), FL2FXCONST_DBL(0.8707008982889695), + FL2FXCONST_DBL(0.8719589092437391), FL2FXCONST_DBL(0.8732173741083574), + FL2FXCONST_DBL(0.8744762925556232), FL2FXCONST_DBL(0.8757356642589241), + FL2FXCONST_DBL(0.8769954888922352), FL2FXCONST_DBL(0.8782557661301171), + FL2FXCONST_DBL(0.8795164956477146), FL2FXCONST_DBL(0.8807776771207545), + FL2FXCONST_DBL(0.8820393102255443), FL2FXCONST_DBL(0.8833013946389704), + FL2FXCONST_DBL(0.8845639300384969), FL2FXCONST_DBL(0.8858269161021629), + FL2FXCONST_DBL(0.8870903525085819), FL2FXCONST_DBL(0.8883542389369399), + FL2FXCONST_DBL(0.8896185750669933), FL2FXCONST_DBL(0.8908833605790678), + FL2FXCONST_DBL(0.8921485951540565), FL2FXCONST_DBL(0.8934142784734187), + FL2FXCONST_DBL(0.8946804102191776), FL2FXCONST_DBL(0.8959469900739191), + FL2FXCONST_DBL(0.8972140177207906), FL2FXCONST_DBL(0.8984814928434985), + FL2FXCONST_DBL(0.8997494151263077), FL2FXCONST_DBL(0.9010177842540390), + FL2FXCONST_DBL(0.9022865999120682), FL2FXCONST_DBL(0.9035558617863242), + FL2FXCONST_DBL(0.9048255695632878), FL2FXCONST_DBL(0.9060957229299895), + FL2FXCONST_DBL(0.9073663215740092), FL2FXCONST_DBL(0.9086373651834729), + FL2FXCONST_DBL(0.9099088534470528), FL2FXCONST_DBL(0.9111807860539647), + FL2FXCONST_DBL(0.9124531626939672), FL2FXCONST_DBL(0.9137259830573594), + FL2FXCONST_DBL(0.9149992468349805), FL2FXCONST_DBL(0.9162729537182071), + FL2FXCONST_DBL(0.9175471033989524), FL2FXCONST_DBL(0.9188216955696648), + FL2FXCONST_DBL(0.9200967299233258), FL2FXCONST_DBL(0.9213722061534494), + FL2FXCONST_DBL(0.9226481239540795), FL2FXCONST_DBL(0.9239244830197896), + FL2FXCONST_DBL(0.9252012830456805), FL2FXCONST_DBL(0.9264785237273793), + FL2FXCONST_DBL(0.9277562047610376), FL2FXCONST_DBL(0.9290343258433305), + FL2FXCONST_DBL(0.9303128866714547), FL2FXCONST_DBL(0.9315918869431275), + FL2FXCONST_DBL(0.9328713263565848), FL2FXCONST_DBL(0.9341512046105802), + FL2FXCONST_DBL(0.9354315214043836), FL2FXCONST_DBL(0.9367122764377792), + FL2FXCONST_DBL(0.9379934694110648), FL2FXCONST_DBL(0.9392751000250497), + FL2FXCONST_DBL(0.9405571679810542), FL2FXCONST_DBL(0.9418396729809072), + FL2FXCONST_DBL(0.9431226147269456), FL2FXCONST_DBL(0.9444059929220124), + FL2FXCONST_DBL(0.9456898072694558), FL2FXCONST_DBL(0.9469740574731275), + FL2FXCONST_DBL(0.9482587432373810), FL2FXCONST_DBL(0.9495438642670713), + FL2FXCONST_DBL(0.9508294202675522), FL2FXCONST_DBL(0.9521154109446763), + FL2FXCONST_DBL(0.9534018360047926), FL2FXCONST_DBL(0.9546886951547455), + FL2FXCONST_DBL(0.9559759881018738), FL2FXCONST_DBL(0.9572637145540087), + FL2FXCONST_DBL(0.9585518742194732), FL2FXCONST_DBL(0.9598404668070802), + FL2FXCONST_DBL(0.9611294920261317), FL2FXCONST_DBL(0.9624189495864168), + FL2FXCONST_DBL(0.9637088391982110), FL2FXCONST_DBL(0.9649991605722750), + FL2FXCONST_DBL(0.9662899134198524), FL2FXCONST_DBL(0.9675810974526697), + FL2FXCONST_DBL(0.9688727123829343), FL2FXCONST_DBL(0.9701647579233330), + FL2FXCONST_DBL(0.9714572337870316), FL2FXCONST_DBL(0.9727501396876727), + FL2FXCONST_DBL(0.9740434753393749), FL2FXCONST_DBL(0.9753372404567313), + FL2FXCONST_DBL(0.9766314347548087), FL2FXCONST_DBL(0.9779260579491460), + FL2FXCONST_DBL(0.9792211097557527), FL2FXCONST_DBL(0.9805165898911081), + FL2FXCONST_DBL(0.9818124980721600), FL2FXCONST_DBL(0.9831088340163232), + FL2FXCONST_DBL(0.9844055974414786), FL2FXCONST_DBL(0.9857027880659716), + FL2FXCONST_DBL(0.9870004056086111), FL2FXCONST_DBL(0.9882984497886684), + FL2FXCONST_DBL(0.9895969203258759), FL2FXCONST_DBL(0.9908958169404255), + FL2FXCONST_DBL(0.9921951393529680), FL2FXCONST_DBL(0.9934948872846116), + FL2FXCONST_DBL(0.9947950604569206), FL2FXCONST_DBL(0.9960956585919144), + FL2FXCONST_DBL(0.9973966814120665), FL2FXCONST_DBL(0.9986981286403025)}; + +const FIXP_DBL FDKaacEnc_specExpMantTableCombElc[4][14] = { + {FL2FXCONST_DBL(0.5000000000000000), FL2FXCONST_DBL(0.6299605249474366), + FL2FXCONST_DBL(0.7937005259840998), FL2FXCONST_DBL(0.5000000000000000), + FL2FXCONST_DBL(0.6299605249474366), FL2FXCONST_DBL(0.7937005259840998), + FL2FXCONST_DBL(0.5000000000000000), FL2FXCONST_DBL(0.6299605249474366), + FL2FXCONST_DBL(0.7937005259840998), FL2FXCONST_DBL(0.5000000000000000), + FL2FXCONST_DBL(0.6299605249474366), FL2FXCONST_DBL(0.7937005259840998), + FL2FXCONST_DBL(0.5000000000000000), FL2FXCONST_DBL(0.6299605249474366)}, + + {FL2FXCONST_DBL(0.5946035575013605), FL2FXCONST_DBL(0.7491535384383408), + FL2FXCONST_DBL(0.9438743126816935), FL2FXCONST_DBL(0.5946035575013605), + FL2FXCONST_DBL(0.7491535384383408), FL2FXCONST_DBL(0.9438743126816935), + FL2FXCONST_DBL(0.5946035575013605), FL2FXCONST_DBL(0.7491535384383408), + FL2FXCONST_DBL(0.9438743126816935), FL2FXCONST_DBL(0.5946035575013605), + FL2FXCONST_DBL(0.7491535384383408), FL2FXCONST_DBL(0.9438743126816935), + FL2FXCONST_DBL(0.5946035575013605), FL2FXCONST_DBL(0.7491535384383408)}, + + {FL2FXCONST_DBL(0.7071067811865476), FL2FXCONST_DBL(0.8908987181403393), + FL2FXCONST_DBL(0.5612310241546865), FL2FXCONST_DBL(0.7071067811865476), + FL2FXCONST_DBL(0.8908987181403393), FL2FXCONST_DBL(0.5612310241546865), + FL2FXCONST_DBL(0.7071067811865476), FL2FXCONST_DBL(0.8908987181403393), + FL2FXCONST_DBL(0.5612310241546865), FL2FXCONST_DBL(0.7071067811865476), + FL2FXCONST_DBL(0.8908987181403393), FL2FXCONST_DBL(0.5612310241546865), + FL2FXCONST_DBL(0.7071067811865476), FL2FXCONST_DBL(0.8908987181403393)}, + + {FL2FXCONST_DBL(0.8408964152537145), FL2FXCONST_DBL(0.5297315471796477), + FL2FXCONST_DBL(0.6674199270850172), FL2FXCONST_DBL(0.8408964152537145), + FL2FXCONST_DBL(0.5297315471796477), FL2FXCONST_DBL(0.6674199270850172), + FL2FXCONST_DBL(0.8408964152537145), FL2FXCONST_DBL(0.5297315471796477), + FL2FXCONST_DBL(0.6674199270850172), FL2FXCONST_DBL(0.8408964152537145), + FL2FXCONST_DBL(0.5297315471796477), FL2FXCONST_DBL(0.6674199270850172), + FL2FXCONST_DBL(0.8408964152537145), FL2FXCONST_DBL(0.5297315471796477)}}; + +const UCHAR FDKaacEnc_specExpTableComb[4][14] = { + {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18}, + {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18}, + {1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18}, + {1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19}}; + +#define WTS0 1 +#define WTS1 0 +#define WTS2 -2 + +const FIXP_WTB ELDAnalysis512[1536] = { + /* part 0 */ + WTC0(0xfac5a770), WTC0(0xfaafbab8), WTC0(0xfa996a40), WTC0(0xfa82bbd0), + WTC0(0xfa6bb538), WTC0(0xfa545c38), WTC0(0xfa3cb698), WTC0(0xfa24ca28), + WTC0(0xfa0c9ca8), WTC0(0xf9f433e8), WTC0(0xf9db9580), WTC0(0xf9c2c298), + WTC0(0xf9a9b800), WTC0(0xf9907250), WTC0(0xf976ee38), WTC0(0xf95d2b88), + WTC0(0xf9432d10), WTC0(0xf928f5c0), WTC0(0xf90e8868), WTC0(0xf8f3e400), + WTC0(0xf8d903a0), WTC0(0xf8bde238), WTC0(0xf8a27af0), WTC0(0xf886cde8), + WTC0(0xf86ae020), WTC0(0xf84eb6c0), WTC0(0xf83256f8), WTC0(0xf815c4b8), + WTC0(0xf7f902c0), WTC0(0xf7dc13b0), WTC0(0xf7befa60), WTC0(0xf7a1ba40), + WTC0(0xf78457c0), WTC0(0xf766d780), WTC0(0xf7493d90), WTC0(0xf72b8990), + WTC0(0xf70db5f0), WTC0(0xf6efbd30), WTC0(0xf6d19a20), WTC0(0xf6b352e0), + WTC0(0xf694f8c0), WTC0(0xf6769da0), WTC0(0xf6585310), WTC0(0xf63a28d0), + WTC0(0xf61c2c60), WTC0(0xf5fe6b10), WTC0(0xf5e0f250), WTC0(0xf5c3ceb0), + WTC0(0xf5a70be0), WTC0(0xf58ab5a0), WTC0(0xf56ed7b0), WTC0(0xf5537e40), + WTC0(0xf538b610), WTC0(0xf51e8bf0), WTC0(0xf5050c90), WTC0(0xf4ec4330), + WTC0(0xf4d439b0), WTC0(0xf4bcf9b0), WTC0(0xf4a68ce0), WTC0(0xf490fa80), + WTC0(0xf47c4760), WTC0(0xf4687830), WTC0(0xf4558f00), WTC0(0xf4434fc0), + WTC0(0xf4314070), WTC0(0xf41ee450), WTC0(0xf40bc130), WTC0(0xf3f799c0), + WTC0(0xf3e26d30), WTC0(0xf3cc3d70), WTC0(0xf3b50c80), WTC0(0xf39cdd60), + WTC0(0xf383b440), WTC0(0xf3699550), WTC0(0xf34e84c0), WTC0(0xf33286b0), + WTC0(0xf3159f10), WTC0(0xf2f7d1b0), WTC0(0xf2d92290), WTC0(0xf2b994d0), + WTC0(0xf2992ad0), WTC0(0xf277e6d0), WTC0(0xf255cb60), WTC0(0xf232dd00), + WTC0(0xf20f2240), WTC0(0xf1eaa1d0), WTC0(0xf1c56240), WTC0(0xf19f63d0), + WTC0(0xf178a0f0), WTC0(0xf15113a0), WTC0(0xf128b5c0), WTC0(0xf0ff7fd0), + WTC0(0xf0d56860), WTC0(0xf0aa6610), WTC0(0xf07e6fd0), WTC0(0xf0518190), + WTC0(0xf0239cd0), WTC0(0xeff4c320), WTC0(0xefc4f720), WTC0(0xef945080), + WTC0(0xef62fce0), WTC0(0xef312a40), WTC0(0xeeff05c0), WTC0(0xeecca2c0), + WTC0(0xee99faa0), WTC0(0xee6705a0), WTC0(0xee33bb60), WTC0(0xee000060), + WTC0(0xedcba660), WTC0(0xed967e80), WTC0(0xed605b80), WTC0(0xed293b40), + WTC0(0xecf146a0), WTC0(0xecb8a8a0), WTC0(0xec7f8bc0), WTC0(0xec461260), + WTC0(0xec0c5720), WTC0(0xebd27440), WTC0(0xeb988220), WTC0(0xeb5e7040), + WTC0(0xeb2404c0), WTC0(0xeae90440), WTC0(0xeaad33c0), WTC0(0xea7066c0), + WTC0(0xea327f60), WTC0(0xe9f36000), WTC0(0xe9b2ed60), WTC0(0xe9713920), + WTC0(0xe92e81e0), WTC0(0xe8eb08c0), WTC0(0xe8a70e60), WTC0(0xe862d8e0), + WTC0(0xe81eb340), WTC0(0xe7dae8a0), WTC0(0xe797c1a0), WTC0(0xe7554ca0), + WTC0(0xe7135dc0), WTC0(0xe6d1c6a0), WTC0(0xe6905720), WTC0(0xe64eb9c0), + WTC0(0xe60c7300), WTC0(0xe5c90600), WTC0(0xe583f920), WTC0(0xe53d1ce0), + WTC0(0xe4f48c80), WTC0(0xe4aa6640), WTC0(0xe45ecaa0), WTC0(0xe4120be0), + WTC0(0xe3c4ae60), WTC0(0xe3773860), WTC0(0xe32a2ea0), WTC0(0xe2ddeea0), + WTC0(0xe292af00), WTC0(0xe248a4a0), WTC0(0xe2000140), WTC0(0xe1b8b640), + WTC0(0xe1727440), WTC0(0xe12ce900), WTC0(0xe0e7c280), WTC0(0xe0a2b420), + WTC0(0xe05d76c0), WTC0(0xe017c360), WTC0(0xdfd15440), WTC0(0xdf8a0540), + WTC0(0xdf41d300), WTC0(0xdef8bb40), WTC0(0xdeaebd40), WTC0(0xde63e7c0), + WTC0(0xde185940), WTC0(0xddcc3180), WTC0(0xdd7f9000), WTC0(0xdd329e80), + WTC0(0xdce58e80), WTC0(0xdc989300), WTC0(0xdc4bde40), WTC0(0xdbff96c0), + WTC0(0xdbb3d780), WTC0(0xdb68bb80), WTC0(0xdb1e5c80), WTC0(0xdad4c380), + WTC0(0xda8be840), WTC0(0xda43c1c0), WTC0(0xd9fc4740), WTC0(0xd9b56640), + WTC0(0xd96f0440), WTC0(0xd9290600), WTC0(0xd8e35080), WTC0(0xd89dcd40), + WTC0(0xd8586b40), WTC0(0xd8131940), WTC0(0xd7cdc640), WTC0(0xd7886180), + WTC0(0xd742dc80), WTC0(0xd6fd2780), WTC0(0xd6b73400), WTC0(0xd670fd80), + WTC0(0xd62a8a40), WTC0(0xd5e3e080), WTC0(0xd59d0840), WTC0(0xd5562b80), + WTC0(0xd50f9540), WTC0(0xd4c992c0), WTC0(0xd4846f80), WTC0(0xd4405a80), + WTC0(0xd3fd6580), WTC0(0xd3bba140), WTC0(0xd37b1c80), WTC0(0xd33bb780), + WTC0(0xd2fd2400), WTC0(0xd2bf1240), WTC0(0xd2813300), WTC0(0xd2435ac0), + WTC0(0xd2057fc0), WTC0(0xd1c79a00), WTC0(0xd189a240), WTC0(0xd14b9dc0), + WTC0(0xd10d9e00), WTC0(0xd0cfb580), WTC0(0xd091f6c0), WTC0(0xd0548100), + WTC0(0xd0177f40), WTC0(0xcfdb1cc0), WTC0(0xcf9f84c0), WTC0(0xcf64d780), + WTC0(0xcf2b2b00), WTC0(0xcef29440), WTC0(0xcebb2640), WTC0(0xce84c000), + WTC0(0xce4f0bc0), WTC0(0xce19b200), WTC0(0xcde45d40), WTC0(0xcdaeedc0), + WTC0(0xcd7979c0), WTC0(0xcd4419c0), WTC0(0xcd0ee6c0), WTC0(0xccda0540), + WTC0(0xcca5a500), WTC0(0xcc71f640), WTC0(0xcc3f2800), WTC0(0xcc0d4300), + WTC0(0xcbdc2a00), WTC0(0xcbabbe80), WTC0(0xcb7be200), WTC0(0xcb4c8200), + WTC0(0xcb1d9800), WTC0(0xcaef1d40), WTC0(0xcac10bc0), WTC0(0xca936440), + WTC0(0xca662d00), WTC0(0xca396d40), WTC0(0xca0d2b80), WTC0(0xc9e16f80), + WTC0(0xc9b63f80), WTC0(0xc98ba2c0), WTC0(0xc961a000), WTC0(0xc9383ec0), + WTC0(0xc90a0440), WTC0(0xc8e0d280), WTC0(0xc8b73b80), WTC0(0xc88d4900), + WTC0(0xc86304c0), WTC0(0xc83878c0), WTC0(0xc80dae80), WTC0(0xc7e2afc0), + WTC0(0xc7b78640), WTC0(0xc78c3c40), WTC0(0xc760da80), WTC0(0xc7356640), + WTC0(0xc709de40), WTC0(0xc6de41c0), WTC0(0xc6b28fc0), WTC0(0xc686bd40), + WTC0(0xc65ab600), WTC0(0xc62e6580), WTC0(0xc601b880), WTC0(0xc5d4bac0), + WTC0(0xc5a79640), WTC0(0xc57a76c0), WTC0(0xc54d8780), WTC0(0xc520e840), + WTC0(0xc4f4acc0), WTC0(0xc4c8e880), WTC0(0xc49dad80), WTC0(0xc472e640), + WTC0(0xc44856c0), WTC0(0xc41dc140), WTC0(0xc3f2e940), WTC0(0xc3c7bc00), + WTC0(0xc39c4f00), WTC0(0xc370b9c0), WTC0(0xc34513c0), WTC0(0xc3197940), + WTC0(0xc2ee0a00), WTC0(0xc2c2e640), WTC0(0xc2982d80), WTC0(0xc26df5c0), + WTC0(0xc2444b00), WTC0(0xc21b3940), WTC0(0xc1f2cbc0), WTC0(0xc1cb05c0), + WTC0(0xc1a3e340), WTC0(0xc17d5f00), WTC0(0xc15773c0), WTC0(0xc1320940), + WTC0(0xc10cf480), WTC0(0xc0e80a00), WTC0(0xc0c31f00), WTC0(0xc09e2640), + WTC0(0xc0792ec0), WTC0(0xc0544940), WTC0(0xc02f86c0), WTC0(0xc00b04c0), + WTC0(0xbfe6ed01), WTC0(0xbfc36a01), WTC0(0xbfa0a581), WTC0(0xbf7eb581), + WTC0(0xbf5d9a81), WTC0(0xbf3d5501), WTC0(0xbf1de601), WTC0(0xbeff4801), + WTC0(0xbee17201), WTC0(0xbec45881), WTC0(0xbea7f301), WTC0(0xbe8c3781), + WTC0(0xbe712001), WTC0(0xbe56a381), WTC0(0xbe3cbc01), WTC0(0xbe236001), + WTC0(0xbe0a8581), WTC0(0xbdf22181), WTC0(0xbdda2a01), WTC0(0xbdc29a81), + WTC0(0xbdab7181), WTC0(0xbd94b001), WTC0(0xbd7e5581), WTC0(0xbd686681), + WTC0(0xbd52eb01), WTC0(0xbd3deb81), WTC0(0xbd297181), WTC0(0xbd158801), + WTC0(0xbd023f01), WTC0(0xbcefa601), WTC0(0xbcddcc81), WTC0(0xbcccbd01), + WTC0(0xbcbc7e01), WTC0(0xbcad1501), WTC0(0xbc9e8801), WTC0(0xbc90d481), + WTC0(0xbc83f201), WTC0(0xbc77d601), WTC0(0xbc6c7781), WTC0(0xbc61c401), + WTC0(0xbc57a301), WTC0(0xbc4dfb81), WTC0(0xbc44b481), WTC0(0xbc3bbc01), + WTC0(0xbc330781), WTC0(0xbc2a8c81), WTC0(0xbc224181), WTC0(0xbc1a2401), + WTC0(0xbc123b81), WTC0(0xbc0a8f01), WTC0(0xbc032601), WTC0(0xbbfc0f81), + WTC0(0xbbf56181), WTC0(0xbbef3301), WTC0(0xbbe99981), WTC0(0xbbe49d01), + WTC0(0xbbe03801), WTC0(0xbbdc6481), WTC0(0xbbd91b81), WTC0(0xbbd64d01), + WTC0(0xbbd3e101), WTC0(0xbbd1bd81), WTC0(0xbbcfca81), WTC0(0xbbce0601), + WTC0(0xbbcc8201), WTC0(0xbbcb5301), WTC0(0xbbca8d01), WTC0(0xbbca5081), + WTC0(0xbbcaca01), WTC0(0xbbcc2681), WTC0(0xbbce9181), WTC0(0xbbd21281), + WTC0(0xbbd68c81), WTC0(0xbbdbe201), WTC0(0xbbe1f401), WTC0(0xbbe89901), + WTC0(0xbbef9b81), WTC0(0xbbf6c601), WTC0(0xbbfde481), WTC0(0xbc04e381), + WTC0(0xbc0bcf81), WTC0(0xbc12b801), WTC0(0xbc19ab01), WTC0(0xbc20ae01), + WTC0(0xbc27bd81), WTC0(0xbc2ed681), WTC0(0xbc35f501), WTC0(0xbc3d1801), + WTC0(0xbc444081), WTC0(0xbc4b6e81), WTC0(0xbc52a381), WTC0(0xbc59df81), + WTC0(0xbc612301), WTC0(0xbc686e01), WTC0(0xbc6fc101), WTC0(0xbc771c01), + WTC0(0xbc7e7e01), WTC0(0xbc85e801), WTC0(0xbc8d5901), WTC0(0xbc94d201), + WTC0(0xbc9c5281), WTC0(0xbca3db01), WTC0(0xbcab6c01), WTC0(0xbcb30601), + WTC0(0xbcbaa801), WTC0(0xbcc25181), WTC0(0xbcca0301), WTC0(0xbcd1bb81), + WTC0(0xbcd97c81), WTC0(0xbce14601), WTC0(0xbce91801), WTC0(0xbcf0f381), + WTC0(0xbcf8d781), WTC0(0xbd00c381), WTC0(0xbd08b781), WTC0(0xbd10b381), + WTC0(0xbd18b781), WTC0(0xbd20c401), WTC0(0xbd28d981), WTC0(0xbd30f881), + WTC0(0xbd391f81), WTC0(0xbd414f01), WTC0(0xbd498601), WTC0(0xbd51c481), + WTC0(0xbd5a0b01), WTC0(0xbd625981), WTC0(0xbd6ab101), WTC0(0xbd731081), + WTC0(0xbd7b7781), WTC0(0xbd83e681), WTC0(0xbd8c5c01), WTC0(0xbd94d801), + WTC0(0xbd9d5b81), WTC0(0xbda5e601), WTC0(0xbdae7881), WTC0(0xbdb71201), + WTC0(0xbdbfb281), WTC0(0xbdc85981), WTC0(0xbdd10681), WTC0(0xbdd9b981), + WTC0(0xbde27201), WTC0(0xbdeb3101), WTC0(0xbdf3f701), WTC0(0xbdfcc301), + WTC0(0xbe059481), WTC0(0xbe0e6c01), WTC0(0xbe174781), WTC0(0xbe202801), + WTC0(0xbe290d01), WTC0(0xbe31f701), WTC0(0xbe3ae601), WTC0(0xbe43da81), + WTC0(0xbe4cd381), WTC0(0xbe55d001), WTC0(0xbe5ed081), WTC0(0xbe67d381), + WTC0(0xbe70da01), WTC0(0xbe79e481), WTC0(0xbe82f301), WTC0(0xbe8c0501), + WTC0(0xbe951a81), WTC0(0xbe9e3281), WTC0(0xbea74c81), WTC0(0xbeb06881), + WTC0(0xbeb98681), WTC0(0xbec2a781), WTC0(0xbecbca81), WTC0(0xbed4f081), + WTC0(0xbede1901), WTC0(0xbee74281), WTC0(0xbef06d01), WTC0(0xbef99901), + WTC0(0xbf02c581), WTC0(0xbf0bf381), WTC0(0xbf152381), WTC0(0xbf1e5501), + WTC0(0xbf278801), WTC0(0xbf30bb01), WTC0(0xbf39ee81), WTC0(0xbf432281), + WTC0(0xbf4c5681), WTC0(0xbf558b01), WTC0(0xbf5ec101), WTC0(0xbf67f801), + WTC0(0xbf712f01), WTC0(0xbf7a6681), WTC0(0xbf839d81), WTC0(0xbf8cd481), + WTC0(0xbf960b01), WTC0(0xbf9f4181), WTC0(0xbfa87901), WTC0(0xbfb1b101), + WTC0(0xbfbae981), WTC0(0xbfc42201), WTC0(0xbfcd5a01), WTC0(0xbfd69101), + WTC0(0xbfdfc781), WTC0(0xbfe8fc01), WTC0(0xbff22f81), WTC0(0xbffb6081), + /* part 1 */ + WTC1(0x80093e01), WTC1(0x801b9b01), WTC1(0x802df701), WTC1(0x80405101), + WTC1(0x8052a881), WTC1(0x8064fc81), WTC1(0x80774c81), WTC1(0x80899881), + WTC1(0x809bdf01), WTC1(0x80ae1f81), WTC1(0x80c05a01), WTC1(0x80d28d81), + WTC1(0x80e4bb81), WTC1(0x80f6e481), WTC1(0x81090981), WTC1(0x811b2981), + WTC1(0x812d4481), WTC1(0x813f5981), WTC1(0x81516701), WTC1(0x81636d81), + WTC1(0x81756d81), WTC1(0x81876781), WTC1(0x81995c01), WTC1(0x81ab4b01), + WTC1(0x81bd3401), WTC1(0x81cf1581), WTC1(0x81e0ee81), WTC1(0x81f2bf81), + WTC1(0x82048881), WTC1(0x82164a81), WTC1(0x82280581), WTC1(0x8239b981), + WTC1(0x824b6601), WTC1(0x825d0901), WTC1(0x826ea201), WTC1(0x82803101), + WTC1(0x8291b601), WTC1(0x82a33281), WTC1(0x82b4a601), WTC1(0x82c61101), + WTC1(0x82d77201), WTC1(0x82e8c801), WTC1(0x82fa1181), WTC1(0x830b4f81), + WTC1(0x831c8101), WTC1(0x832da781), WTC1(0x833ec381), WTC1(0x834fd481), + WTC1(0x8360d901), WTC1(0x8371d081), WTC1(0x8382ba01), WTC1(0x83939501), + WTC1(0x83a46181), WTC1(0x83b52101), WTC1(0x83c5d381), WTC1(0x83d67881), + WTC1(0x83e70f01), WTC1(0x83f79681), WTC1(0x84080d81), WTC1(0x84187401), + WTC1(0x8428ca01), WTC1(0x84391081), WTC1(0x84494881), WTC1(0x84597081), + WTC1(0x84698881), WTC1(0x84798f81), WTC1(0x84898481), WTC1(0x84996701), + WTC1(0x84a93801), WTC1(0x84b8f801), WTC1(0x84c8a701), WTC1(0x84d84601), + WTC1(0x84e7d381), WTC1(0x84f74e01), WTC1(0x8506b581), WTC1(0x85160981), + WTC1(0x85254a81), WTC1(0x85347901), WTC1(0x85439601), WTC1(0x8552a181), + WTC1(0x85619a01), WTC1(0x85707f81), WTC1(0x857f5101), WTC1(0x858e0e01), + WTC1(0x859cb781), WTC1(0x85ab4f01), WTC1(0x85b9d481), WTC1(0x85c84801), + WTC1(0x85d6a981), WTC1(0x85e4f801), WTC1(0x85f33281), WTC1(0x86015981), + WTC1(0x860f6e01), WTC1(0x861d7081), WTC1(0x862b6201), WTC1(0x86394301), + WTC1(0x86471281), WTC1(0x8654d001), WTC1(0x86627b01), WTC1(0x86701381), + WTC1(0x867d9a81), WTC1(0x868b1001), WTC1(0x86987581), WTC1(0x86a5ca81), + WTC1(0x86b30f01), WTC1(0x86c04381), WTC1(0x86cd6681), WTC1(0x86da7901), + WTC1(0x86e77b81), WTC1(0x86f46d81), WTC1(0x87014f81), WTC1(0x870e2301), + WTC1(0x871ae981), WTC1(0x8727a381), WTC1(0x87345381), WTC1(0x8740f681), + WTC1(0x874d8681), WTC1(0x8759fd01), WTC1(0x87665481), WTC1(0x87729701), + WTC1(0x877ede01), WTC1(0x878b4301), WTC1(0x8797dd81), WTC1(0x87a48b01), + WTC1(0x87b0ef01), WTC1(0x87bcab81), WTC1(0x87c76201), WTC1(0x87d0ca81), + WTC1(0x87fdd781), WTC1(0x881dd301), WTC1(0x88423301), WTC1(0x886a8a81), + WTC1(0x88962981), WTC1(0x88c45e81), WTC1(0x88f47901), WTC1(0x8925f101), + WTC1(0x89586901), WTC1(0x898b8301), WTC1(0x89bee581), WTC1(0x89f26101), + WTC1(0x8a25f301), WTC1(0x8a599a81), WTC1(0x8a8d5801), WTC1(0x8ac13381), + WTC1(0x8af53e81), WTC1(0x8b298b81), WTC1(0x8b5e2c81), WTC1(0x8b933001), + WTC1(0x8bc8a401), WTC1(0x8bfe9401), WTC1(0x8c350d01), WTC1(0x8c6c1b01), + WTC1(0x8ca3cb01), WTC1(0x8cdc2901), WTC1(0x8d154081), WTC1(0x8d4f1b01), + WTC1(0x8d89be81), WTC1(0x8dc53001), WTC1(0x8e017581), WTC1(0x8e3e9481), + WTC1(0x8e7c9301), WTC1(0x8ebb7581), WTC1(0x8efb4181), WTC1(0x8f3bfb01), + WTC1(0x8f7da401), WTC1(0x8fc03f01), WTC1(0x9003ce81), WTC1(0x90485401), + WTC1(0x908dd101), WTC1(0x90d44781), WTC1(0x911bb981), WTC1(0x91642781), + WTC1(0x91ad9281), WTC1(0x91f7f981), WTC1(0x92435d01), WTC1(0x928fbe01), + WTC1(0x92dd1b01), WTC1(0x932b7501), WTC1(0x937acb01), WTC1(0x93cb1c81), + WTC1(0x941c6901), WTC1(0x946eaf81), WTC1(0x94c1ee01), WTC1(0x95162381), + WTC1(0x956b4f81), WTC1(0x95c17081), WTC1(0x96188501), WTC1(0x96708b81), + WTC1(0x96c98381), WTC1(0x97236b01), WTC1(0x977e4181), WTC1(0x97da0481), + WTC1(0x9836b201), WTC1(0x98944901), WTC1(0x98f2c601), WTC1(0x99522801), + WTC1(0x99b26c81), WTC1(0x9a139101), WTC1(0x9a759301), WTC1(0x9ad87081), + WTC1(0x9b3c2801), WTC1(0x9ba0b701), WTC1(0x9c061b81), WTC1(0x9c6c5481), + WTC1(0x9cd35f81), WTC1(0x9d3b3b81), WTC1(0x9da3e601), WTC1(0x9e0d5e01), + WTC1(0x9e779f81), WTC1(0x9ee2a901), WTC1(0x9f4e7801), WTC1(0x9fbb0981), + WTC1(0xa0285d81), WTC1(0xa0967201), WTC1(0xa1054701), WTC1(0xa174da81), + WTC1(0xa1e52a81), WTC1(0xa2563501), WTC1(0xa2c7f801), WTC1(0xa33a7201), + WTC1(0xa3ada281), WTC1(0xa4218801), WTC1(0xa4962181), WTC1(0xa50b6e81), + WTC1(0xa5816e81), WTC1(0xa5f81f81), WTC1(0xa66f8201), WTC1(0xa6e79401), + WTC1(0xa7605601), WTC1(0xa7d9c681), WTC1(0xa853e501), WTC1(0xa8ceb201), + WTC1(0xa94a2c01), WTC1(0xa9c65401), WTC1(0xaa432981), WTC1(0xaac0ad01), + WTC1(0xab3edf01), WTC1(0xabbdc001), WTC1(0xac3d5001), WTC1(0xacbd9081), + WTC1(0xad3e8101), WTC1(0xadc02281), WTC1(0xae427481), WTC1(0xaec57801), + WTC1(0xaf492f01), WTC1(0xafcd9a81), WTC1(0xb052bc01), WTC1(0xb0d89401), + WTC1(0xb15f2381), WTC1(0xb1e66a01), WTC1(0xb26e6881), WTC1(0xb2f71f01), + WTC1(0xb3808d81), WTC1(0xb40ab501), WTC1(0xb4959501), WTC1(0xb5212e81), + WTC1(0x4a6cf67f), WTC1(0x49dffeff), WTC1(0x495265ff), WTC1(0x48c4277f), + WTC1(0x4835407f), WTC1(0x47a5aeff), WTC1(0x471570ff), WTC1(0x468484ff), + WTC1(0x45f2eaff), WTC1(0x4560a2ff), WTC1(0x44cdad7f), WTC1(0x443a0c7f), + WTC1(0x43a5c07f), WTC1(0x4310caff), WTC1(0x427b2bff), WTC1(0x41e4e3ff), + WTC1(0x414df2ff), WTC1(0x40b6557f), WTC1(0x401e06ff), WTC1(0x3f8503c0), + WTC1(0x3eeb4e00), WTC1(0x3e50ebc0), WTC1(0x3db5e680), WTC1(0x3d1a4680), + WTC1(0x3c7e10c0), WTC1(0x3be14cc0), WTC1(0x3b4402c0), WTC1(0x3aa63800), + WTC1(0x3a07e840), WTC1(0x39690880), WTC1(0x38c98700), WTC1(0x38295b40), + WTC1(0x37888a80), WTC1(0x36e71d40), WTC1(0x36451d80), WTC1(0x35a29400), + WTC1(0x34ff8800), WTC1(0x345c04c0), WTC1(0x33b81940), WTC1(0x3313d200), + WTC1(0x326f3800), WTC1(0x31ca5600), WTC1(0x31253840), WTC1(0x307fe8c0), + WTC1(0x2fda6e40), WTC1(0x2f34ce40), WTC1(0x2e8f0e40), WTC1(0x2de92ec0), + WTC1(0x2d432780), WTC1(0x2c9cea40), WTC1(0x2bf66300), WTC1(0x2b4f88c0), + WTC1(0x2aa864c0), WTC1(0x2a010240), WTC1(0x29596e40), WTC1(0x28b1ba80), + WTC1(0x2809ff40), WTC1(0x27625b80), WTC1(0x26baf580), WTC1(0x2613e7c0), + WTC1(0x256d3dc0), WTC1(0x24c70300), WTC1(0x24214380), WTC1(0x237c0800), + WTC1(0x22d75400), WTC1(0x22332a80), WTC1(0x218f8cc0), WTC1(0x20ec7e40), + WTC1(0x204a04c0), WTC1(0x1fa82540), WTC1(0x1f06e300), WTC1(0x1e664000), + WTC1(0x1dc63bc0), WTC1(0x1d26d3c0), WTC1(0x1c8803a0), WTC1(0x1be9cc40), + WTC1(0x1b4c34c0), WTC1(0x1aaf4480), WTC1(0x1a130260), WTC1(0x197774a0), + WTC1(0x18dca260), WTC1(0x184294e0), WTC1(0x17a95840), WTC1(0x1710fd80), + WTC1(0x16799ce0), WTC1(0x15e35340), WTC1(0x154e41a0), WTC1(0x14ba8360), + WTC1(0x14282be0), WTC1(0x13975100), WTC1(0x13080aa0), WTC1(0x127a6240), + WTC1(0x11ee50a0), WTC1(0x1163cc80), WTC1(0x10dacb20), WTC1(0x105333a0), + WTC1(0x0fccdb30), WTC1(0x0f478f40), WTC1(0x0ec31700), WTC1(0x0e3f4e80), + WTC1(0x0dbc27f0), WTC1(0x0d399000), WTC1(0x0cb76d00), WTC1(0x0c359d50), + WTC1(0x0bb3fd50), WTC1(0x0b326bd0), WTC1(0x0ab0ca80), WTC1(0x0a2f0dc0), + WTC1(0x09ad40c0), WTC1(0x092b7a90), WTC1(0x08a9db80), WTC1(0x08285c80), + WTC1(0x07a6c7b8), WTC1(0x0724e4e0), WTC1(0x06a27b80), WTC1(0x061f52f8), + WTC1(0x059b2ad0), WTC1(0x0515b568), WTC1(0x048ea058), WTC1(0x04066408), + WTC1(0x037e52d8), WTC1(0x02f7d3c8), WTC1(0x0274614c), WTC1(0x01f63008), + WTC1(0x0180403a), WTC1(0x0115c442), WTC1(0x00ba09e2), WTC1(0x006f077c), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + /* part 2 */ + WTC2(0xfff36be1), WTC2(0xffdafbc1), WTC2(0xffc28035), WTC2(0xffa9fe8a), + WTC2(0xff917c08), WTC2(0xff78fdfc), WTC2(0xff6089af), WTC2(0xff48246c), + WTC2(0xff2fd37f), WTC2(0xff179c31), WTC2(0xfeff83b6), WTC2(0xfee78d18), + WTC2(0xfecfb93e), WTC2(0xfeb808f2), WTC2(0xfea07d06), WTC2(0xfe8916b4), + WTC2(0xfe71d7a0), WTC2(0xfe5ac174), WTC2(0xfe43d5d6), WTC2(0xfe2d167e), + WTC2(0xfe16852e), WTC2(0xfe0023a6), WTC2(0xfde9f3f8), WTC2(0xfdd3ff7c), + WTC2(0xfdbe56c0), WTC2(0xfda90aa8), WTC2(0xfd942b78), WTC2(0xfd7fbb20), + WTC2(0xfd6bad50), WTC2(0xfd57f510), WTC2(0xfd44857c), WTC2(0xfd3153fc), + WTC2(0xfd1e5840), WTC2(0xfd0b8a0c), WTC2(0xfcf8e180), WTC2(0xfce65eec), + WTC2(0xfcd40ad0), WTC2(0xfcc1ee0c), WTC2(0xfcb011e8), WTC2(0xfc9e896c), + WTC2(0xfc8d716c), WTC2(0xfc7ce720), WTC2(0xfc6d072c), WTC2(0xfc5de09c), + WTC2(0xfc4f74e8), WTC2(0xfc41c4e8), WTC2(0xfc34d0dc), WTC2(0xfc288a68), + WTC2(0xfc1cd49c), WTC2(0xfc1191e0), WTC2(0xfc06a4d0), WTC2(0xfbfbf3e8), + WTC2(0xfbf16990), WTC2(0xfbe6f068), WTC2(0xfbdc7428), WTC2(0xfbd1fc68), + WTC2(0xfbc7ac50), WTC2(0xfbbda868), WTC2(0xfbb41500), WTC2(0xfbab1438), + WTC2(0xfba2c5f8), WTC2(0xfb9b4a00), WTC2(0xfb94bfa8), WTC2(0xfb8f3b48), + WTC2(0xfb8ac638), WTC2(0xfb876970), WTC2(0xfb852d20), WTC2(0xfb840ae0), + WTC2(0xfb83ed60), WTC2(0xfb84bec0), WTC2(0xfb866918), WTC2(0xfb88d4a8), + WTC2(0xfb8be810), WTC2(0xfb8f89d0), WTC2(0xfb93a080), WTC2(0xfb981418), + WTC2(0xfb9ccdf0), WTC2(0xfba1b770), WTC2(0xfba6bae0), WTC2(0xfbabd5c0), + WTC2(0xfbb118d8), WTC2(0xfbb695c0), WTC2(0xfbbc5e90), WTC2(0xfbc29030), + WTC2(0xfbc95268), WTC2(0xfbd0cd78), WTC2(0xfbd929c8), WTC2(0xfbe294d0), + WTC2(0xfbed4108), WTC2(0xfbf96118), WTC2(0xfc0726c8), WTC2(0xfc16b064), + WTC2(0xfc280890), WTC2(0xfc3b3920), WTC2(0xfc504a98), WTC2(0xfc67271c), + WTC2(0xfc7f9a74), WTC2(0xfc996f18), WTC2(0xfcb46eb8), WTC2(0xfcd050b0), + WTC2(0xfcecba24), WTC2(0xfd094f64), WTC2(0xfd25b720), WTC2(0xfd41ce40), + WTC2(0xfd5da7f8), WTC2(0xfd7959d8), WTC2(0xfd94fb74), WTC2(0xfdb0d3fc), + WTC2(0xfdcd5a34), WTC2(0xfdeb06e4), WTC2(0xfe0a5184), WTC2(0xfe2b92c4), + WTC2(0xfe4f0486), WTC2(0xfe74df54), WTC2(0xfe9d5886), WTC2(0xfec85b92), + WTC2(0xfef58a16), WTC2(0xff248275), WTC2(0xff54e401), WTC2(0xff866330), + WTC2(0xffb8c99b), WTC2(0xffebe1c9), WTC2(0x001f786a), WTC2(0x00538bf9), + WTC2(0x00884cbc), WTC2(0x00bded23), WTC2(0x00f49f54), WTC2(0x012c8ee4), + WTC2(0x0165e0d2), WTC2(0x01a0b9d6), WTC2(0x01dd3d80), WTC2(0x021b74d4), + WTC2(0x025b4e48), WTC2(0x029cb730), WTC2(0x02df9d0c), WTC2(0x0323f1a4), + WTC2(0x0369ab00), WTC2(0x03b0bf5c), WTC2(0x03f925a0), WTC2(0x0442e3d8), + WTC2(0x048e0f40), WTC2(0x04dabdb0), WTC2(0x05290430), WTC2(0x0578e428), + WTC2(0x05ca4b60), WTC2(0x061d26c0), WTC2(0x067163d8), WTC2(0x06c6ff10), + WTC2(0x071e03b0), WTC2(0x07767da0), WTC2(0x07d07918), WTC2(0x082c08e0), + WTC2(0x08894660), WTC2(0x08e84b70), WTC2(0x094930b0), WTC2(0x09abf8d0), + WTC2(0x0a109020), WTC2(0x0a76e210), WTC2(0x0adeda50), WTC2(0x0b486b80), + WTC2(0x0bb38f00), WTC2(0x0c203e80), WTC2(0x0c8e73e0), WTC2(0x0cfe2c30), + WTC2(0x0d6f6820), WTC2(0x0de22850), WTC2(0x0e566d90), WTC2(0x0ecc3dd0), + WTC2(0x0f43a3a0), WTC2(0x0fbca9f0), WTC2(0x10375b80), WTC2(0x10b3be20), + WTC2(0x1131d280), WTC2(0x11b19960), WTC2(0x123313a0), WTC2(0x12b64380), + WTC2(0x133b2d00), WTC2(0x13c1d440), WTC2(0x144a3d60), WTC2(0x14d46900), + WTC2(0x15605480), WTC2(0x15edfd20), WTC2(0x167d6040), WTC2(0x170e7e80), + WTC2(0x17a15b80), WTC2(0x1835fb00), WTC2(0x18cc60a0), WTC2(0x19648dc0), + WTC2(0x19fe80e0), WTC2(0x1a9a38a0), WTC2(0x1b37b3e0), WTC2(0x1bd6f400), + WTC2(0x1c77fd20), WTC2(0x1d1ad400), WTC2(0x1dbf7c80), WTC2(0x1e65f820), + WTC2(0x1f0e4540), WTC2(0x1fb861e0), WTC2(0x20644cc0), WTC2(0x21120640), + WTC2(0x21c19240), WTC2(0x2272f480), WTC2(0x23263000), WTC2(0x23db4580), + WTC2(0x24923340), WTC2(0x254af700), WTC2(0x26058e80), WTC2(0x26c1fa00), + WTC2(0x27803d00), WTC2(0x28405a40), WTC2(0x29025500), WTC2(0x29c62d40), + WTC2(0x2a8be0c0), WTC2(0x2b536cc0), WTC2(0x2c1ccf80), WTC2(0x2ce80840), + WTC2(0x2db519c0), WTC2(0x2e840600), WTC2(0x2f54cf80), WTC2(0x302775c0), + WTC2(0x30fbf640), WTC2(0x31d24e00), WTC2(0x32aa7a00), WTC2(0x338479c0), + WTC2(0x34604e40), WTC2(0x353df900), WTC2(0x361d7ac0), WTC2(0x36fed200), + WTC2(0x37e1fb40), WTC2(0x38c6f240), WTC2(0x39adb2c0), WTC2(0x3a963a00), + WTC2(0x3b808740), WTC2(0x3c6c9880), WTC2(0x3d5a6cc0), WTC2(0x3e4a0040), + WTC2(0x3f3b4bc0), WTC2(0x402e48ff), WTC2(0x4122f17f), WTC2(0x42193f7f), + WTC2(0x43112eff), WTC2(0x440abbff), WTC2(0x4505e2ff), WTC2(0x46029e7f), + WTC2(0x4700e9ff), WTC2(0x4800bfff), WTC2(0x49021bff), WTC2(0x4a050eff), + WTC2(0x4b09bc7f), WTC2(0x4c104aff), WTC2(0x4d18df7f), WTC2(0x4e23a07f), + WTC2(0x4f30b2ff), WTC2(0x50403c7f), WTC2(0x515262ff), WTC2(0x52674b7f), + WTC2(0x001678b2), WTC2(0x00061a3b), WTC2(0xfffb4622), WTC2(0xfff5ea94), + WTC2(0xfff5f5b9), WTC2(0xfffb55bd), WTC2(0x0005f8cb), WTC2(0x0015cd0c), + WTC2(0x002ac0ac), WTC2(0x0044c1d5), WTC2(0x0063beb2), WTC2(0x0087a56d), + WTC2(0x00b06431), WTC2(0x00dde929), WTC2(0x01102280), WTC2(0x0146fe5e), + WTC2(0x01826af2), WTC2(0x01c25662), WTC2(0x0206aedc), WTC2(0x024f6288), + WTC2(0x029c5f94), WTC2(0x02ed9424), WTC2(0x0342ee6c), WTC2(0x039c5c90), + WTC2(0x03f9ccbc), WTC2(0x045b2d18), WTC2(0x04c06bd8), WTC2(0x05297718), + WTC2(0x05963d10), WTC2(0x0606abe8), WTC2(0x067ab1c0), WTC2(0x06f23cd0), + WTC2(0x076d3b40), WTC2(0x07eb9b38), WTC2(0x086d4ae0), WTC2(0x08f23860), + WTC2(0x097a51f0), WTC2(0x0a0585b0), WTC2(0x0a93c1d0), WTC2(0x0b24f470), + WTC2(0x0bb90bc0), WTC2(0x0c4ff5f0), WTC2(0x0ce9a130), WTC2(0x0d85fb90), + WTC2(0x0e24f360), WTC2(0x0ec676b0), WTC2(0x0f6a73b0), WTC2(0x1010d880), + WTC2(0x10b99360), WTC2(0x11649280), WTC2(0x1211c400), WTC2(0x12c115e0), + WTC2(0x137276a0), WTC2(0x1425d420), WTC2(0x14db1ca0), WTC2(0x15923e60), + WTC2(0x164b2780), WTC2(0x1705c620), WTC2(0x17c20860), WTC2(0x187fdca0), + WTC2(0x193f30e0), WTC2(0x19fff340), WTC2(0x1ac21200), WTC2(0x1b857b40), + WTC2(0x1c4a1d40), WTC2(0x1d0fe600), WTC2(0x1dd6c3e0), WTC2(0x1e9ea4e0), + WTC2(0x1f677740), WTC2(0x20312940), WTC2(0x20fba8c0), WTC2(0x21c6e440), + WTC2(0x2292c9c0), WTC2(0x235f4780), WTC2(0x242c4b80), WTC2(0x24f9c400), + WTC2(0x25c79f40), WTC2(0x2695cb40), WTC2(0x27643680), WTC2(0x2832cec0), + WTC2(0x29018240), WTC2(0x29d03f80), WTC2(0x2a9ef480), WTC2(0x2b6d8f00), + WTC2(0x2c3bfdc0), WTC2(0x2d0a2ec0), WTC2(0x2dd81000), WTC2(0x2ea58fc0), + WTC2(0x2f729c40), WTC2(0x303f2380), WTC2(0x310b1400), WTC2(0x31d65b80), + WTC2(0x32a0e840), WTC2(0x336aa8c0), WTC2(0x34338ac0), WTC2(0x34fb7cc0), + WTC2(0x35c26cc0), WTC2(0x36884900), WTC2(0x374cff80), WTC2(0x38107e80), + WTC2(0x38d2b440), WTC2(0x39938ec0), WTC2(0x3a52fc40), WTC2(0x3b10eb00), + WTC2(0x3bcd4900), WTC2(0x3c880480), WTC2(0x3d410bc0), WTC2(0x3df84d00), + WTC2(0x3eadb600), WTC2(0x3f613540), WTC2(0x4012b8ff), WTC2(0x40c22eff), + WTC2(0x416f85ff), WTC2(0x421aab7f), WTC2(0x42c38e7f), WTC2(0x436a1c7f), + WTC2(0x440e437f), WTC2(0x44aff27f), WTC2(0x454f167f), WTC2(0x45eb9eff), + WTC2(0x468578ff), WTC2(0x471c937f), WTC2(0x47b0dc7f), WTC2(0x484241ff), + WTC2(0x48d0b1ff), WTC2(0x495c1a7f), WTC2(0x49e46a7f), WTC2(0x4a698f7f), + WTC2(0x4aeb77ff), WTC2(0x4b6a11ff), WTC2(0x4be54b7f), WTC2(0x4c5d12ff), + WTC2(0x4cd155ff), WTC2(0x4d4203ff), WTC2(0x4daf09ff), WTC2(0x4e18567f), + WTC2(0x4e7dd77f), WTC2(0x4edf7b7f), WTC2(0x4f3d307f), WTC2(0x4f96e47f), + WTC2(0x4fec85ff), WTC2(0x503e02ff), WTC2(0x508b497f), WTC2(0x50d447ff), + WTC2(0x5118ec7f), WTC2(0x515924ff), WTC2(0x5194dfff), WTC2(0x51cc0b7f), + WTC2(0x51fe95ff), WTC2(0x522c6cff), WTC2(0x52557eff), WTC2(0x5279b9ff), + WTC2(0x52990c7f), WTC2(0x52b364ff), WTC2(0x52c8b07f), WTC2(0x52d8ddff), + WTC2(0x52e3db7f), WTC2(0x52e996ff), WTC2(0x52e9ff7f), WTC2(0x52e501ff), + WTC2(0x52da8cff), WTC2(0x52ca8f7f), WTC2(0x52b4f67f), WTC2(0x5299b07f), + WTC2(0x5278ac7f), WTC2(0x5251d77f), WTC2(0x52251fff), WTC2(0x51f274ff), + WTC2(0x51b9c37f), WTC2(0x517af9ff), WTC2(0x5136077f), WTC2(0x50ead8ff), + WTC2(0x50995cff), WTC2(0x504181ff), WTC2(0x4fe335ff), WTC2(0x4f7e677f), + WTC2(0x4f1303ff), WTC2(0x4ea0f9ff), WTC2(0x4e2837ff), WTC2(0x4da8ab7f), + WTC2(0x4d2242ff), WTC2(0x4c94ecff), WTC2(0x4c0096ff), WTC2(0x4b652f7f), + WTC2(0x4ac2a4ff), WTC2(0x4a18e4ff), WTC2(0x4967ddff), WTC2(0x48af7e7f), + WTC2(0x47efb3ff), WTC2(0x47286cff), WTC2(0x4659ad7f), WTC2(0x45856f7f), + WTC2(0x44afa3ff), WTC2(0x43dc507f), WTC2(0x430f657f), WTC2(0x424ad47f), + WTC2(0x418e927f), WTC2(0x40da7bff), WTC2(0x402e6f7f), WTC2(0x3f8a3100), + WTC2(0x3eed6f40), WTC2(0x3e57d700), WTC2(0x3dc914c0), WTC2(0x3d40cc40), + WTC2(0x3cbe98c0), WTC2(0x3c421540), WTC2(0x3bcadbc0), WTC2(0x3b588880), + WTC2(0x3aeab780), WTC2(0x3a810540), WTC2(0x3a1b0e00), WTC2(0x39b86d00), + WTC2(0x3958bcc0), WTC2(0x38fb9700), WTC2(0x38a095c0), WTC2(0x38473d80), + WTC2(0x37eeff40), WTC2(0x37974b40), WTC2(0x373f9500), WTC2(0x36e7ae00), + WTC2(0x368fc4c0), WTC2(0x36380b80), WTC2(0x35e0b300), WTC2(0x3589c140), + WTC2(0x35331180), WTC2(0x34dc7c80), WTC2(0x3485dc80), WTC2(0x342f1600), + WTC2(0x33d81780), WTC2(0x3380d0c0), WTC2(0x33293100), WTC2(0x32d11800), + WTC2(0x32785780), WTC2(0x321ec0c0), WTC2(0x31c42680), WTC2(0x316885c0), + WTC2(0x310c0580), WTC2(0x30aecec0), WTC2(0x30510940), WTC2(0x2ff2b8c0), + WTC2(0x2f93bf40), WTC2(0x2f33fc00), WTC2(0x2ed350c0), WTC2(0x2e71ba80), + WTC2(0x2e0f5340), WTC2(0x2dac35c0), WTC2(0x2d487c80), WTC2(0x2ce431c0), + WTC2(0x2c7f4fc0), WTC2(0x2c19d080), WTC2(0x2bb3ad80), WTC2(0x2b4ce080), + WTC2(0x2ae56340), WTC2(0x2a7d2f80), WTC2(0x2a143f00), WTC2(0x29aa8b40)}; + +const FIXP_WTB ELDAnalysis480[1440] = { + WTC0(0xfacfbef0), WTC0(0xfab88c18), WTC0(0xfaa0e520), WTC0(0xfa88d110), + WTC0(0xfa7056e8), WTC0(0xfa577db0), WTC0(0xfa3e4c70), WTC0(0xfa24ca28), + WTC0(0xfa0afde0), WTC0(0xf9f0eea0), WTC0(0xf9d6a2c8), WTC0(0xf9bc1ab8), + WTC0(0xf9a15230), WTC0(0xf9864510), WTC0(0xf96af058), WTC0(0xf94f55c0), + WTC0(0xf93378e0), WTC0(0xf9175d80), WTC0(0xf8fb0468), WTC0(0xf8de68b8), + WTC0(0xf8c18438), WTC0(0xf8a450d8), WTC0(0xf886cde8), WTC0(0xf8690148), + WTC0(0xf84af148), WTC0(0xf82ca410), WTC0(0xf80e1e18), WTC0(0xf7ef62a0), + WTC0(0xf7d074e0), WTC0(0xf7b15870), WTC0(0xf7921240), WTC0(0xf772a7a0), + WTC0(0xf7531e50), WTC0(0xf7337820), WTC0(0xf713afd0), WTC0(0xf6f3bea0), + WTC0(0xf6d39dc0), WTC0(0xf6b352e0), WTC0(0xf692f280), WTC0(0xf6729250), + WTC0(0xf65247a0), WTC0(0xf63224c0), WTC0(0xf6123a00), WTC0(0xf5f297c0), + WTC0(0xf5d34dd0), WTC0(0xf5b46b10), WTC0(0xf595fd90), WTC0(0xf5781390), + WTC0(0xf55abba0), WTC0(0xf53e0510), WTC0(0xf521ff70), WTC0(0xf506ba30), + WTC0(0xf4ec4330), WTC0(0xf4d2a680), WTC0(0xf4b9efe0), WTC0(0xf4a22ac0), + WTC0(0xf48b5f70), WTC0(0xf4759310), WTC0(0xf460cde0), WTC0(0xf44cfcc0), + WTC0(0xf439aff0), WTC0(0xf4264e00), WTC0(0xf4123d90), WTC0(0xf3fd1370), + WTC0(0xf3e6be00), WTC0(0xf3cf41a0), WTC0(0xf3b6a030), WTC0(0xf39cdd60), + WTC0(0xf381fe00), WTC0(0xf3660760), WTC0(0xf348fe70), WTC0(0xf32ae820), + WTC0(0xf30bc940), WTC0(0xf2eba690), WTC0(0xf2ca8480), WTC0(0xf2a86670), + WTC0(0xf2854f40), WTC0(0xf2614190), WTC0(0xf23c41e0), WTC0(0xf21657a0), + WTC0(0xf1ef8ae0), WTC0(0xf1c7e3e0), WTC0(0xf19f63d0), WTC0(0xf1760450), + WTC0(0xf14bbdf0), WTC0(0xf1208960), WTC0(0xf0f45cd0), WTC0(0xf0c72ce0), + WTC0(0xf098ee00), WTC0(0xf06996f0), WTC0(0xf0392620), WTC0(0xf0079e10), + WTC0(0xefd4ffc0), WTC0(0xefa15ca0), WTC0(0xef6ce600), WTC0(0xef37d460), + WTC0(0xef025f80), WTC0(0xeecca2c0), WTC0(0xee969760), WTC0(0xee603440), + WTC0(0xee296d20), WTC0(0xedf21c00), WTC0(0xedba07e0), WTC0(0xed80f640), + WTC0(0xed46bf40), WTC0(0xed0b7b00), WTC0(0xeccf5fc0), WTC0(0xec92a120), + WTC0(0xec556d60), WTC0(0xec17e700), WTC0(0xebda2d40), WTC0(0xeb9c5fa0), + WTC0(0xeb5e7040), WTC0(0xeb201b20), WTC0(0xeae117c0), WTC0(0xeaa12000), + WTC0(0xea600180), WTC0(0xea1d9940), WTC0(0xe9d9c160), WTC0(0xe99468a0), + WTC0(0xe94dc040), WTC0(0xe9061940), WTC0(0xe8bdc140), WTC0(0xe8750ae0), + WTC0(0xe82c4fa0), WTC0(0xe7e3ea40), WTC0(0xe79c35e0), WTC0(0xe7554ca0), + WTC0(0xe70efc00), WTC0(0xe6c90c20), WTC0(0xe6833f00), WTC0(0xe63d2300), + WTC0(0xe5f620a0), WTC0(0xe5ad9dc0), WTC0(0xe5632080), WTC0(0xe5169da0), + WTC0(0xe4c83e60), WTC0(0xe4782400), WTC0(0xe4269840), WTC0(0xe3d42dc0), + WTC0(0xe38188c0), WTC0(0xe32f4be0), WTC0(0xe2ddeea0), WTC0(0xe28db520), + WTC0(0xe23ee000), WTC0(0xe1f1a580), WTC0(0xe1a5e3a0), WTC0(0xe15b35a0), + WTC0(0xe1113860), WTC0(0xe0c78a00), WTC0(0xe07dd0e0), WTC0(0xe033b7c0), + WTC0(0xdfe8e680), WTC0(0xdf9d1fc0), WTC0(0xdf5055c0), WTC0(0xdf0287c0), + WTC0(0xdeb3b340), WTC0(0xde63e7c0), WTC0(0xde134a00), WTC0(0xddc20000), + WTC0(0xdd703180), WTC0(0xdd1e1280), WTC0(0xdccbe080), WTC0(0xdc79d980), + WTC0(0xdc283600), WTC0(0xdbd71e00), WTC0(0xdb86b140), WTC0(0xdb3710c0), + WTC0(0xdae850c0), WTC0(0xda9a6bc0), WTC0(0xda4d5640), WTC0(0xda010640), + WTC0(0xd9b56640), WTC0(0xd96a5700), WTC0(0xd91fb700), WTC0(0xd8d56600), + WTC0(0xd88b4a40), WTC0(0xd8414f00), WTC0(0xd7f75f80), WTC0(0xd7ad6740), + WTC0(0xd76352c0), WTC0(0xd7191040), WTC0(0xd6ce8c80), WTC0(0xd683bd00), + WTC0(0xd638a5c0), WTC0(0xd5ed4f80), WTC0(0xd5a1c240), WTC0(0xd5562b80), + WTC0(0xd50ae500), WTC0(0xd4c04c80), WTC0(0xd476bb40), WTC0(0xd42e62c0), + WTC0(0xd3e75680), WTC0(0xd3a1ad00), WTC0(0xd35d6780), WTC0(0xd31a4300), + WTC0(0xd2d7dc00), WTC0(0xd295d080), WTC0(0xd253d8c0), WTC0(0xd211df40), + WTC0(0xd1cfdbc0), WTC0(0xd18dc480), WTC0(0xd14b9dc0), WTC0(0xd1097c80), + WTC0(0xd0c77700), WTC0(0xd085a500), WTC0(0xd0442f40), WTC0(0xd0034a80), + WTC0(0xcfc32c00), WTC0(0xcf840400), WTC0(0xcf45f400), WTC0(0xcf0913c0), + WTC0(0xcecd8000), WTC0(0xce932c80), WTC0(0xce59bf40), WTC0(0xce20cd40), + WTC0(0xcde7ec40), WTC0(0xcdaeedc0), WTC0(0xcd75ea00), WTC0(0xcd3cfec0), + WTC0(0xcd044b40), WTC0(0xcccbff00), WTC0(0xcc945480), WTC0(0xcc5d8780), + WTC0(0xcc27c3c0), WTC0(0xcbf2fc40), WTC0(0xcbbf0a00), WTC0(0xcb8bc7c0), + WTC0(0xcb591880), WTC0(0xcb26f0c0), WTC0(0xcaf54980), WTC0(0xcac41ac0), + WTC0(0xca936440), WTC0(0xca632d80), WTC0(0xca337f00), WTC0(0xca046180), + WTC0(0xc9d5dd40), WTC0(0xc9a7fa80), WTC0(0xc97ac200), WTC0(0xc94e3c00), + WTC0(0xc91d1840), WTC0(0xc8f15980), WTC0(0xc8c52340), WTC0(0xc8988100), + WTC0(0xc86b7f00), WTC0(0xc83e28c0), WTC0(0xc8108a80), WTC0(0xc7e2afc0), + WTC0(0xc7b4a480), WTC0(0xc7867480), WTC0(0xc7582b40), WTC0(0xc729cc80), + WTC0(0xc6fb5700), WTC0(0xc6ccca40), WTC0(0xc69e2180), WTC0(0xc66f49c0), + WTC0(0xc64029c0), WTC0(0xc610a740), WTC0(0xc5e0bfc0), WTC0(0xc5b09e80), + WTC0(0xc5807900), WTC0(0xc5508440), WTC0(0xc520e840), WTC0(0xc4f1bdc0), + WTC0(0xc4c31d00), WTC0(0xc4951780), WTC0(0xc4678a00), WTC0(0xc43a28c0), + WTC0(0xc40ca800), WTC0(0xc3deccc0), WTC0(0xc3b09940), WTC0(0xc3822c00), + WTC0(0xc353a0c0), WTC0(0xc3251740), WTC0(0xc2f6b500), WTC0(0xc2c8a140), + WTC0(0xc29b02c0), WTC0(0xc26df5c0), WTC0(0xc2418940), WTC0(0xc215cbc0), + WTC0(0xc1eaca00), WTC0(0xc1c08680), WTC0(0xc196fb00), WTC0(0xc16e22c0), + WTC0(0xc145f040), WTC0(0xc11e3a80), WTC0(0xc0f6cc00), WTC0(0xc0cf6ec0), + WTC0(0xc0a802c0), WTC0(0xc0809280), WTC0(0xc0593340), WTC0(0xc031f880), + WTC0(0xc00b04c0), WTC0(0xbfe48981), WTC0(0xbfbebb81), WTC0(0xbf99cb01), + WTC0(0xbf75cc81), WTC0(0xbf52c101), WTC0(0xbf30a901), WTC0(0xbf0f8301), + WTC0(0xbeef4601), WTC0(0xbecfe601), WTC0(0xbeb15701), WTC0(0xbe938c81), + WTC0(0xbe767e81), WTC0(0xbe5a2301), WTC0(0xbe3e7201), WTC0(0xbe236001), + WTC0(0xbe08e181), WTC0(0xbdeee981), WTC0(0xbdd56b81), WTC0(0xbdbc6381), + WTC0(0xbda3d081), WTC0(0xbd8bb281), WTC0(0xbd740b81), WTC0(0xbd5ce281), + WTC0(0xbd464281), WTC0(0xbd303581), WTC0(0xbd1ac801), WTC0(0xbd060c81), + WTC0(0xbcf21601), WTC0(0xbcdef701), WTC0(0xbcccbd01), WTC0(0xbcbb7001), + WTC0(0xbcab1781), WTC0(0xbc9bb901), WTC0(0xbc8d5101), WTC0(0xbc7fd301), + WTC0(0xbc733401), WTC0(0xbc676501), WTC0(0xbc5c4c81), WTC0(0xbc51cb01), + WTC0(0xbc47c281), WTC0(0xbc3e1981), WTC0(0xbc34c081), WTC0(0xbc2bab01), + WTC0(0xbc22cd81), WTC0(0xbc1a2401), WTC0(0xbc11b681), WTC0(0xbc098d81), + WTC0(0xbc01b381), WTC0(0xbbfa3c01), WTC0(0xbbf34281), WTC0(0xbbece281), + WTC0(0xbbe73201), WTC0(0xbbe23281), WTC0(0xbbdddb01), WTC0(0xbbda2501), + WTC0(0xbbd70201), WTC0(0xbbd45601), WTC0(0xbbd20301), WTC0(0xbbcfea81), + WTC0(0xbbce0601), WTC0(0xbbcc6b01), WTC0(0xbbcb3201), WTC0(0xbbca7481), + WTC0(0xbbca5d01), WTC0(0xbbcb2281), WTC0(0xbbccfc81), WTC0(0xbbd01301), + WTC0(0xbbd45881), WTC0(0xbbd9a781), WTC0(0xbbdfdb81), WTC0(0xbbe6c801), + WTC0(0xbbee2f81), WTC0(0xbbf5d181), WTC0(0xbbfd6c01), WTC0(0xbc04e381), + WTC0(0xbc0c4581), WTC0(0xbc13a481), WTC0(0xbc1b1081), WTC0(0xbc228f01), + WTC0(0xbc2a1a81), WTC0(0xbc31af01), WTC0(0xbc394901), WTC0(0xbc40e881), + WTC0(0xbc488e81), WTC0(0xbc503b81), WTC0(0xbc57f101), WTC0(0xbc5fae81), + WTC0(0xbc677501), WTC0(0xbc6f4401), WTC0(0xbc771c01), WTC0(0xbc7efc81), + WTC0(0xbc86e581), WTC0(0xbc8ed701), WTC0(0xbc96d101), WTC0(0xbc9ed481), + WTC0(0xbca6e101), WTC0(0xbcaef701), WTC0(0xbcb71701), WTC0(0xbcbf4001), + WTC0(0xbcc77181), WTC0(0xbccfac01), WTC0(0xbcd7ef01), WTC0(0xbce03b81), + WTC0(0xbce89281), WTC0(0xbcf0f381), WTC0(0xbcf95e81), WTC0(0xbd01d281), + WTC0(0xbd0a4f81), WTC0(0xbd12d581), WTC0(0xbd1b6501), WTC0(0xbd23ff01), + WTC0(0xbd2ca281), WTC0(0xbd355081), WTC0(0xbd3e0801), WTC0(0xbd46c801), + WTC0(0xbd4f9101), WTC0(0xbd586281), WTC0(0xbd613d81), WTC0(0xbd6a2201), + WTC0(0xbd731081), WTC0(0xbd7c0781), WTC0(0xbd850701), WTC0(0xbd8e0e01), + WTC0(0xbd971c81), WTC0(0xbda03381), WTC0(0xbda95301), WTC0(0xbdb27b01), + WTC0(0xbdbbab01), WTC0(0xbdc4e301), WTC0(0xbdce2181), WTC0(0xbdd76701), + WTC0(0xbde0b301), WTC0(0xbdea0681), WTC0(0xbdf36101), WTC0(0xbdfcc301), + WTC0(0xbe062b81), WTC0(0xbe0f9a01), WTC0(0xbe190d81), WTC0(0xbe228681), + WTC0(0xbe2c0501), WTC0(0xbe358901), WTC0(0xbe3f1381), WTC0(0xbe48a301), + WTC0(0xbe523781), WTC0(0xbe5bd001), WTC0(0xbe656c01), WTC0(0xbe6f0c01), + WTC0(0xbe78b001), WTC0(0xbe825801), WTC0(0xbe8c0501), WTC0(0xbe95b581), + WTC0(0xbe9f6901), WTC0(0xbea91f01), WTC0(0xbeb2d681), WTC0(0xbebc9181), + WTC0(0xbec64e81), WTC0(0xbed00f81), WTC0(0xbed9d281), WTC0(0xbee39801), + WTC0(0xbeed5f01), WTC0(0xbef72681), WTC0(0xbf00ef81), WTC0(0xbf0aba01), + WTC0(0xbf148681), WTC0(0xbf1e5501), WTC0(0xbf282501), WTC0(0xbf31f501), + WTC0(0xbf3bc601), WTC0(0xbf459681), WTC0(0xbf4f6801), WTC0(0xbf593a01), + WTC0(0xbf630d81), WTC0(0xbf6ce201), WTC0(0xbf76b701), WTC0(0xbf808b81), + WTC0(0xbf8a5f81), WTC0(0xbf943301), WTC0(0xbf9e0701), WTC0(0xbfa7dc01), + WTC0(0xbfb1b101), WTC0(0xbfbb8701), WTC0(0xbfc55c81), WTC0(0xbfcf3181), + WTC0(0xbfd90601), WTC0(0xbfe2d901), WTC0(0xbfecaa81), WTC0(0xbff67a01), + /* part 1 */ + WTC1(0x80130981), WTC1(0x80269f81), WTC1(0x803a3381), WTC1(0x804dc481), + WTC1(0x80615281), WTC1(0x8074dc01), WTC1(0x80886081), WTC1(0x809bdf01), + WTC1(0x80af5701), WTC1(0x80c2c781), WTC1(0x80d63101), WTC1(0x80e99401), + WTC1(0x80fcf181), WTC1(0x81104a01), WTC1(0x81239d81), WTC1(0x8136ea01), + WTC1(0x814a2f81), WTC1(0x815d6c01), WTC1(0x8170a181), WTC1(0x8183cf81), + WTC1(0x8196f781), WTC1(0x81aa1981), WTC1(0x81bd3401), WTC1(0x81d04681), + WTC1(0x81e34f81), WTC1(0x81f64f01), WTC1(0x82094581), WTC1(0x821c3401), + WTC1(0x822f1b01), WTC1(0x8241fa01), WTC1(0x8254cf01), WTC1(0x82679901), + WTC1(0x827a5801), WTC1(0x828d0b01), WTC1(0x829fb401), WTC1(0x82b25301), + WTC1(0x82c4e801), WTC1(0x82d77201), WTC1(0x82e9ef01), WTC1(0x82fc5f01), + WTC1(0x830ec081), WTC1(0x83211501), WTC1(0x83335c81), WTC1(0x83459881), + WTC1(0x8357c701), WTC1(0x8369e781), WTC1(0x837bf801), WTC1(0x838df801), + WTC1(0x839fe801), WTC1(0x83b1c881), WTC1(0x83c39a81), WTC1(0x83d55d01), + WTC1(0x83e70f01), WTC1(0x83f8b001), WTC1(0x840a3e81), WTC1(0x841bb981), + WTC1(0x842d2281), WTC1(0x843e7a81), WTC1(0x844fc081), WTC1(0x8460f581), + WTC1(0x84721701), WTC1(0x84832481), WTC1(0x84941d81), WTC1(0x84a50201), + WTC1(0x84b5d301), WTC1(0x84c69101), WTC1(0x84d73c01), WTC1(0x84e7d381), + WTC1(0x84f85581), WTC1(0x8508c181), WTC1(0x85191801), WTC1(0x85295881), + WTC1(0x85398481), WTC1(0x85499d01), WTC1(0x8559a081), WTC1(0x85698e81), + WTC1(0x85796601), WTC1(0x85892681), WTC1(0x8598d081), WTC1(0x85a86581), + WTC1(0x85b7e601), WTC1(0x85c75201), WTC1(0x85d6a981), WTC1(0x85e5eb81), + WTC1(0x85f51681), WTC1(0x86042c01), WTC1(0x86132c01), WTC1(0x86221801), + WTC1(0x8630f181), WTC1(0x863fb701), WTC1(0x864e6901), WTC1(0x865d0581), + WTC1(0x866b8d81), WTC1(0x867a0081), WTC1(0x86886001), WTC1(0x8696ad01), + WTC1(0x86a4e781), WTC1(0x86b30f01), WTC1(0x86c12401), WTC1(0x86cf2601), + WTC1(0x86dd1481), WTC1(0x86eaf081), WTC1(0x86f8ba81), WTC1(0x87067281), + WTC1(0x87141b01), WTC1(0x8721b481), WTC1(0x872f4201), WTC1(0x873cc201), + WTC1(0x874a2f01), WTC1(0x87578181), WTC1(0x8764b101), WTC1(0x8771c601), + WTC1(0x877ede01), WTC1(0x878c1881), WTC1(0x87998f01), WTC1(0x87a70e81), + WTC1(0x87b42481), WTC1(0x87c05e81), WTC1(0x87cb5101), WTC1(0x87d4ac81), + WTC1(0x87e73d81), WTC1(0x88124281), WTC1(0x88353501), WTC1(0x885f8481), + WTC1(0x888d3181), WTC1(0x88be1681), WTC1(0x88f13801), WTC1(0x8925f101), + WTC1(0x895bcd01), WTC1(0x89925a81), WTC1(0x89c92f81), WTC1(0x8a001f01), + WTC1(0x8a372881), WTC1(0x8a6e4a01), WTC1(0x8aa58681), WTC1(0x8adcee01), + WTC1(0x8b149701), WTC1(0x8b4c9701), WTC1(0x8b850281), WTC1(0x8bbde981), + WTC1(0x8bf75b01), WTC1(0x8c316681), WTC1(0x8c6c1b01), WTC1(0x8ca78781), + WTC1(0x8ce3ba81), WTC1(0x8d20c301), WTC1(0x8d5eaa01), WTC1(0x8d9d7781), + WTC1(0x8ddd3201), WTC1(0x8e1de001), WTC1(0x8e5f8881), WTC1(0x8ea23201), + WTC1(0x8ee5e301), WTC1(0x8f2aa101), WTC1(0x8f706f01), WTC1(0x8fb74f81), + WTC1(0x8fff4601), WTC1(0x90485401), WTC1(0x90927b81), WTC1(0x90ddc001), + WTC1(0x912a2201), WTC1(0x9177a301), WTC1(0x91c64301), WTC1(0x92160301), + WTC1(0x9266e281), WTC1(0x92b8e101), WTC1(0x930bff81), WTC1(0x93603d01), + WTC1(0x93b59901), WTC1(0x940c1281), WTC1(0x9463a881), WTC1(0x94bc5981), + WTC1(0x95162381), WTC1(0x95710601), WTC1(0x95ccff01), WTC1(0x962a0c81), + WTC1(0x96882e01), WTC1(0x96e76101), WTC1(0x9747a481), WTC1(0x97a8f681), + WTC1(0x980b5501), WTC1(0x986ebd81), WTC1(0x98d32d81), WTC1(0x9938a281), + WTC1(0x999f1981), WTC1(0x9a069001), WTC1(0x9a6f0381), WTC1(0x9ad87081), + WTC1(0x9b42d581), WTC1(0x9bae2f81), WTC1(0x9c1a7c81), WTC1(0x9c87ba81), + WTC1(0x9cf5e701), WTC1(0x9d650081), WTC1(0x9dd50481), WTC1(0x9e45f081), + WTC1(0x9eb7c101), WTC1(0x9f2a7281), WTC1(0x9f9e0301), WTC1(0xa0127081), + WTC1(0xa087b981), WTC1(0xa0fddd81), WTC1(0xa174da81), WTC1(0xa1ecae01), + WTC1(0xa2655581), WTC1(0xa2dece81), WTC1(0xa3591801), WTC1(0xa3d43001), + WTC1(0xa4501601), WTC1(0xa4ccc901), WTC1(0xa54a4701), WTC1(0xa5c89001), + WTC1(0xa647a301), WTC1(0xa6c77e01), WTC1(0xa7482101), WTC1(0xa7c98b01), + WTC1(0xa84bbb81), WTC1(0xa8ceb201), WTC1(0xa9526d81), WTC1(0xa9d6ef01), + WTC1(0xaa5c3601), WTC1(0xaae24301), WTC1(0xab691681), WTC1(0xabf0b181), + WTC1(0xac791401), WTC1(0xad023f01), WTC1(0xad8c3301), WTC1(0xae16f001), + WTC1(0xaea27681), WTC1(0xaf2ec901), WTC1(0xafbbe801), WTC1(0xb049d601), + WTC1(0xb0d89401), WTC1(0xb1682281), WTC1(0xb1f88181), WTC1(0xb289b181), + WTC1(0xb31bb301), WTC1(0xb3ae8601), WTC1(0xb4422b81), WTC1(0xb4d6a381), + WTC1(0x4a5a327f), WTC1(0x49c4adff), WTC1(0x492e637f), WTC1(0x48974f7f), + WTC1(0x47ff6d7f), WTC1(0x4766baff), WTC1(0x46cd35ff), WTC1(0x4632dd7f), + WTC1(0x4597b0ff), WTC1(0x44fbb1ff), WTC1(0x445eeaff), WTC1(0x43c165ff), + WTC1(0x4323227f), WTC1(0x4284277f), WTC1(0x41e48aff), WTC1(0x4144557f), + WTC1(0x40a3867f), WTC1(0x4001f5ff), WTC1(0x3f5f5d80), WTC1(0x3ebbad00), + WTC1(0x3e16ee40), WTC1(0x3d713d00), WTC1(0x3ccab700), WTC1(0x3c236500), + WTC1(0x3b7b5800), WTC1(0x3ad2ecc0), WTC1(0x3a2a6540), WTC1(0x3981b7c0), + WTC1(0x38d8ba00), WTC1(0x382f01c0), WTC1(0x37846240), WTC1(0x36d8eb00), + WTC1(0x362c9ec0), WTC1(0x357f7a00), WTC1(0x34d18340), WTC1(0x3422c900), + WTC1(0x33736c40), WTC1(0x32c39040), WTC1(0x32134280), WTC1(0x31629280), + WTC1(0x30b1a000), WTC1(0x30008380), WTC1(0x2f4f4240), WTC1(0x2e9df180), + WTC1(0x2decc780), WTC1(0x2d3bd640), WTC1(0x2c8b0cc0), WTC1(0x2bda3080), + WTC1(0x2b28ec80), WTC1(0x2a773500), WTC1(0x29c51b40), WTC1(0x291293c0), + WTC1(0x285f9280), WTC1(0x27ac35c0), WTC1(0x26f8ab40), WTC1(0x26454c00), + WTC1(0x25925600), WTC1(0x24dfd580), WTC1(0x242ddd40), WTC1(0x237c87c0), + WTC1(0x22cbe240), WTC1(0x221bef40), WTC1(0x216cb040), WTC1(0x20be2800), + WTC1(0x20105c80), WTC1(0x1f6352a0), WTC1(0x1eb71240), WTC1(0x1e0ba140), + WTC1(0x1d60fe40), WTC1(0x1cb723e0), WTC1(0x1c0e0300), WTC1(0x1b6596c0), + WTC1(0x1abde8a0), WTC1(0x1a16fbe0), WTC1(0x1970c680), WTC1(0x18cb4840), + WTC1(0x18268e20), WTC1(0x1782a0c0), WTC1(0x16df8960), WTC1(0x163d6300), + WTC1(0x159c52c0), WTC1(0x14fc87e0), WTC1(0x145e2c80), WTC1(0x13c15b60), + WTC1(0x13263240), WTC1(0x128cd9a0), WTC1(0x11f562a0), WTC1(0x115fc1c0), + WTC1(0x10cbf160), WTC1(0x1039f200), WTC1(0x0fa9a080), WTC1(0x0f1abd90), + WTC1(0x0e8d01d0), WTC1(0x0e003330), WTC1(0x0d743590), WTC1(0x0ce8ef40), + WTC1(0x0c5e1900), WTC1(0x0bd35d70), WTC1(0x0b488eb0), WTC1(0x0abd8410), + WTC1(0x0a320a00), WTC1(0x09a60e70), WTC1(0x0919ab00), WTC1(0x088d0de0), + WTC1(0x080065e0), WTC1(0x07739710), WTC1(0x06e65808), WTC1(0x06588348), + WTC1(0x05ca0ae0), WTC1(0x053aaaf8), WTC1(0x04a9faf0), WTC1(0x0417f698), + WTC1(0x03859ff4), WTC1(0x02f49be4), WTC1(0x0266b668), WTC1(0x01de554e), + WTC1(0x015f50ca), WTC1(0x00eb7e5d), WTC1(0x00904f24), WTC1(0x00212889), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + /* part 2 */ + WTC2(0xfffece02), WTC2(0xffe4c3df), WTC2(0xffcaaa55), WTC2(0xffb087d1), + WTC2(0xff9662bf), WTC2(0xff7c418b), WTC2(0xff622aa0), WTC2(0xff48246c), + WTC2(0xff2e355a), WTC2(0xff1463db), WTC2(0xfefab608), WTC2(0xfee12f0a), + WTC2(0xfec7cfd2), WTC2(0xfeae995a), WTC2(0xfe958cc4), WTC2(0xfe7cabce), + WTC2(0xfe63f882), WTC2(0xfe4b74e0), WTC2(0xfe3322f6), WTC2(0xfe1b04dc), + WTC2(0xfe031ccc), WTC2(0xfdeb6cf0), WTC2(0xfdd3ff7c), WTC2(0xfdbce834), + WTC2(0xfda63bb8), WTC2(0xfd900c68), WTC2(0xfd7a590c), WTC2(0xfd6511b4), + WTC2(0xfd5026c0), WTC2(0xfd3b8954), WTC2(0xfd272df0), WTC2(0xfd130adc), + WTC2(0xfcff15ac), WTC2(0xfceb4a68), WTC2(0xfcd7b110), WTC2(0xfcc454d0), + WTC2(0xfcb14064), WTC2(0xfc9e896c), WTC2(0xfc8c5264), WTC2(0xfc7abef0), + WTC2(0xfc69f078), WTC2(0xfc59f5e8), WTC2(0xfc4acfec), WTC2(0xfc3c8060), + WTC2(0xfc2f0264), WTC2(0xfc223b7c), WTC2(0xfc160714), WTC2(0xfc0a4150), + WTC2(0xfbfec920), WTC2(0xfbf38320), WTC2(0xfbe855d0), WTC2(0xfbdd2740), + WTC2(0xfbd1fc68), WTC2(0xfbc6fea0), WTC2(0xfbbc5a48), WTC2(0xfbb23b48), + WTC2(0xfba8ca78), WTC2(0xfba02e50), WTC2(0xfb988de0), WTC2(0xfb920b40), + WTC2(0xfb8cb870), WTC2(0xfb889f68), WTC2(0xfb85cbe8), WTC2(0xfb843dd0), + WTC2(0xfb83df78), WTC2(0xfb8495d0), WTC2(0xfb864660), WTC2(0xfb88d4a8), + WTC2(0xfb8c21e8), WTC2(0xfb900f28), WTC2(0xfb947dc0), WTC2(0xfb9950c0), + WTC2(0xfb9e6d08), WTC2(0xfba3b658), WTC2(0xfba91908), WTC2(0xfbae9e08), + WTC2(0xfbb45bd0), WTC2(0xfbba66f8), WTC2(0xfbc0dcf0), WTC2(0xfbc7ead8), + WTC2(0xfbcfc200), WTC2(0xfbd89330), WTC2(0xfbe294d0), WTC2(0xfbee03d0), + WTC2(0xfbfb1de8), WTC2(0xfc0a1da4), WTC2(0xfc1b22e0), WTC2(0xfc2e38f0), + WTC2(0xfc436d48), WTC2(0xfc5abf7c), WTC2(0xfc74024c), WTC2(0xfc8ef2e8), + WTC2(0xfcab51ac), WTC2(0xfcc8d024), WTC2(0xfce704f0), WTC2(0xfd0580cc), + WTC2(0xfd23d4d0), WTC2(0xfd41ce40), WTC2(0xfd5f81b0), WTC2(0xfd7d08f0), + WTC2(0xfd9a8560), WTC2(0xfdb85938), WTC2(0xfdd71798), WTC2(0xfdf753b8), + WTC2(0xfe1993ee), WTC2(0xfe3e30f8), WTC2(0xfe656cba), WTC2(0xfe8f8fdc), + WTC2(0xfebca8a4), WTC2(0xfeec590e), WTC2(0xff1e285c), WTC2(0xff51a0b7), + WTC2(0xff866330), WTC2(0xffbc2cbb), WTC2(0xfff2bbff), WTC2(0x0029d79d), + WTC2(0x00618a22), WTC2(0x009a1185), WTC2(0x00d3aa8c), WTC2(0x010e8ff6), + WTC2(0x014af29e), WTC2(0x0188fe56), WTC2(0x01c8e108), WTC2(0x020ab3c4), + WTC2(0x024e68a8), WTC2(0x0293e824), WTC2(0x02db1bc8), WTC2(0x0323f1a4), + WTC2(0x036e5d6c), WTC2(0x03ba5320), WTC2(0x0407c938), WTC2(0x0456cad0), + WTC2(0x04a77288), WTC2(0x04f9db88), WTC2(0x054e1888), WTC2(0x05a41ef0), + WTC2(0x05fbd6e0), WTC2(0x065528c0), WTC2(0x06b00838), WTC2(0x070c7ee0), + WTC2(0x076a9bb0), WTC2(0x07ca6d10), WTC2(0x082c08e0), WTC2(0x088f8da0), + WTC2(0x08f51ac0), WTC2(0x095ccc20), WTC2(0x09c69f70), WTC2(0x0a327b40), + WTC2(0x0aa046d0), WTC2(0x0b0febb0), WTC2(0x0b815dd0), WTC2(0x0bf49600), + WTC2(0x0c698c50), WTC2(0x0ce03ba0), WTC2(0x0d58a380), WTC2(0x0dd2c510), + WTC2(0x0e4ea110), WTC2(0x0ecc3dd0), WTC2(0x0f4ba800), WTC2(0x0fcced10), + WTC2(0x10501960), WTC2(0x10d532a0), WTC2(0x115c39c0), WTC2(0x11e52fa0), + WTC2(0x12701560), WTC2(0x12fcef20), WTC2(0x138bc200), WTC2(0x141c9300), + WTC2(0x14af64a0), WTC2(0x154434e0), WTC2(0x15db0020), WTC2(0x1673c360), + WTC2(0x170e7e80), WTC2(0x17ab35e0), WTC2(0x1849ee40), WTC2(0x18eaaba0), + WTC2(0x198d6f00), WTC2(0x1a3236a0), WTC2(0x1ad90080), WTC2(0x1b81cc60), + WTC2(0x1c2c9da0), WTC2(0x1cd97980), WTC2(0x1d8865c0), WTC2(0x1e396540), + WTC2(0x1eec7700), WTC2(0x1fa198c0), WTC2(0x2058c840), WTC2(0x21120640), + WTC2(0x21cd5700), WTC2(0x228abec0), WTC2(0x234a4180), WTC2(0x240bdf80), + WTC2(0x24cf95c0), WTC2(0x259561c0), WTC2(0x265d4200), WTC2(0x27273840), + WTC2(0x27f348c0), WTC2(0x28c17700), WTC2(0x2991c500), WTC2(0x2a643080), + WTC2(0x2b38b680), WTC2(0x2c0f53c0), WTC2(0x2ce80840), WTC2(0x2dc2d680), + WTC2(0x2e9fc100), WTC2(0x2f7ecac0), WTC2(0x305ff280), WTC2(0x314334c0), + WTC2(0x32288e00), WTC2(0x330ffb80), WTC2(0x33f97d80), WTC2(0x34e515c0), + WTC2(0x35d2c5c0), WTC2(0x36c28d00), WTC2(0x37b467c0), WTC2(0x38a85080), + WTC2(0x399e4240), WTC2(0x3a963a00), WTC2(0x3b903600), WTC2(0x3c8c3480), + WTC2(0x3d8a3380), WTC2(0x3e8a2dc0), WTC2(0x3f8c1b40), WTC2(0x408ff2ff), + WTC2(0x4195ae7f), WTC2(0x429d477f), WTC2(0x43a6b87f), WTC2(0x44b1fdff), + WTC2(0x45bf11ff), WTC2(0x46cdee7f), WTC2(0x47de8cff), WTC2(0x48f0e77f), + WTC2(0x4a050eff), WTC2(0x4b1b2dff), WTC2(0x4c3372ff), WTC2(0x4d4e0bff), + WTC2(0x4e6b257f), WTC2(0x4f8aedff), WTC2(0x50ad92ff), WTC2(0x51d341ff), + WTC2(0x002006a9), WTC2(0x000bfb36), WTC2(0xfffe45ac), WTC2(0xfff6d064), + WTC2(0xfff585bc), WTC2(0xfffa500d), WTC2(0x000519b4), WTC2(0x0015cd0c), + WTC2(0x002c5470), WTC2(0x00489a3b), WTC2(0x006a88c8), WTC2(0x00920a74), + WTC2(0x00bf0999), WTC2(0x00f17092), WTC2(0x012929bc), WTC2(0x01661f70), + WTC2(0x01a83c0c), WTC2(0x01ef69e8), WTC2(0x023b9364), WTC2(0x028ca2d4), + WTC2(0x02e2829c), WTC2(0x033d1d10), WTC2(0x039c5c90), WTC2(0x04002b78), + WTC2(0x04687418), WTC2(0x04d520e0), WTC2(0x05461c18), WTC2(0x05bb5020), + WTC2(0x0634a758), WTC2(0x06b20c20), WTC2(0x073368c8), WTC2(0x07b8a7b0), + WTC2(0x0841b340), WTC2(0x08ce75b0), WTC2(0x095ed980), WTC2(0x09f2c900), + WTC2(0x0a8a2e80), WTC2(0x0b24f470), WTC2(0x0bc30510), WTC2(0x0c644ad0), + WTC2(0x0d08b010), WTC2(0x0db01f10), WTC2(0x0e5a8250), WTC2(0x0f07c400), + WTC2(0x0fb7cea0), WTC2(0x106a8c80), WTC2(0x111fe800), WTC2(0x11d7cb60), + WTC2(0x12922120), WTC2(0x134ed3a0), WTC2(0x140dcd00), WTC2(0x14cef7e0), + WTC2(0x15923e60), WTC2(0x16578b00), WTC2(0x171ec820), WTC2(0x17e7e020), + WTC2(0x18b2bd20), WTC2(0x197f49c0), WTC2(0x1a4d7040), WTC2(0x1b1d1b00), + WTC2(0x1bee3460), WTC2(0x1cc0a6a0), WTC2(0x1d945c40), WTC2(0x1e693f80), + WTC2(0x1f3f3ac0), WTC2(0x20163880), WTC2(0x20ee22c0), WTC2(0x21c6e440), + WTC2(0x22a06740), WTC2(0x237a9600), WTC2(0x24555ac0), WTC2(0x2530a040), + WTC2(0x260c5080), WTC2(0x26e85600), WTC2(0x27c49b00), WTC2(0x28a10a00), + WTC2(0x297d8d80), WTC2(0x2a5a0f80), WTC2(0x2b367a80), WTC2(0x2c12b8c0), + WTC2(0x2ceeb500), WTC2(0x2dca5940), WTC2(0x2ea58fc0), WTC2(0x2f804340), + WTC2(0x305a5dc0), WTC2(0x3133ca00), WTC2(0x320c7200), WTC2(0x32e44000), + WTC2(0x33bb1ec0), WTC2(0x3490f880), WTC2(0x3565b7c0), WTC2(0x36394640), + WTC2(0x370b8f00), WTC2(0x37dc7c00), WTC2(0x38abf7c0), WTC2(0x3979ecc0), + WTC2(0x3a464500), WTC2(0x3b10eb00), WTC2(0x3bd9c940), WTC2(0x3ca0c9c0), + WTC2(0x3d65d740), WTC2(0x3e28dc00), WTC2(0x3ee9c240), WTC2(0x3fa87480), + WTC2(0x4064dcff), WTC2(0x411ee67f), WTC2(0x41d67a7f), WTC2(0x428b847f), + WTC2(0x433ded7f), WTC2(0x43eda0ff), WTC2(0x449a887f), WTC2(0x45448f7f), + WTC2(0x45eb9eff), WTC2(0x468fa1ff), WTC2(0x473082ff), WTC2(0x47ce2c7f), + WTC2(0x4868887f), WTC2(0x48ff80ff), WTC2(0x499300ff), WTC2(0x4a22f2ff), + WTC2(0x4aaf407f), WTC2(0x4b37d47f), WTC2(0x4bbc997f), WTC2(0x4c3d78ff), + WTC2(0x4cba5e7f), WTC2(0x4d33337f), WTC2(0x4da7e27f), WTC2(0x4e18567f), + WTC2(0x4e8478ff), WTC2(0x4eec347f), WTC2(0x4f4f737f), WTC2(0x4fae20ff), + WTC2(0x500825ff), WTC2(0x505d6dff), WTC2(0x50ade37f), WTC2(0x50f96f7f), + WTC2(0x513ffdff), WTC2(0x518177ff), WTC2(0x51bdc87f), WTC2(0x51f4d9ff), + WTC2(0x5226967f), WTC2(0x5252e87f), WTC2(0x5279b9ff), WTC2(0x529af5ff), + WTC2(0x52b6867f), WTC2(0x52cc55ff), WTC2(0x52dc4eff), WTC2(0x52e65aff), + WTC2(0x52ea657f), WTC2(0x52e857ff), WTC2(0x52e01d7f), WTC2(0x52d19fff), + WTC2(0x52bcc9ff), WTC2(0x52a1857f), WTC2(0x527fbd7f), WTC2(0x52575b7f), + WTC2(0x52284a7f), WTC2(0x51f274ff), WTC2(0x51b5c47f), WTC2(0x5172247f), + WTC2(0x51277dff), WTC2(0x50d5bc7f), WTC2(0x507cc9ff), WTC2(0x501c90ff), + WTC2(0x4fb4fb7f), WTC2(0x4f45f3ff), WTC2(0x4ecf64ff), WTC2(0x4e5138ff), + WTC2(0x4dcb597f), WTC2(0x4d3db1ff), WTC2(0x4ca82bff), WTC2(0x4c0ab27f), + WTC2(0x4b652f7f), WTC2(0x4ab78d7f), WTC2(0x4a01b67f), WTC2(0x4943957f), + WTC2(0x487d12ff), WTC2(0x47ae1f7f), WTC2(0x46d68f7f), WTC2(0x45f7187f), + WTC2(0x4513597f), WTC2(0x4430467f), WTC2(0x4352d2ff), WTC2(0x427e6bff), + WTC2(0x41b390ff), WTC2(0x40f2077f), WTC2(0x4039a87f), WTC2(0x3f8a3100), + WTC2(0x3ee33e00), WTC2(0x3e446ac0), WTC2(0x3dad5180), WTC2(0x3d1d7fc0), + WTC2(0x3c947b00), WTC2(0x3c11c7c0), WTC2(0x3b94ebc0), WTC2(0x3b1d6dc0), + WTC2(0x3aaad480), WTC2(0x3a3ca740), WTC2(0x39d26c40), WTC2(0x396ba8c0), + WTC2(0x3907e080), WTC2(0x38a69800), WTC2(0x38473d80), WTC2(0x37e923c0), + WTC2(0x378b9b80), WTC2(0x372e0380), WTC2(0x36d03a80), WTC2(0x36727f00), + WTC2(0x36150e40), WTC2(0x35b81540), WTC2(0x355b8000), WTC2(0x34ff1dc0), + WTC2(0x34a2bfc0), WTC2(0x34463e80), WTC2(0x33e982c0), WTC2(0x338c7880), + WTC2(0x332f0bc0), WTC2(0x32d11800), WTC2(0x327265c0), WTC2(0x3212bbc0), + WTC2(0x31b1e740), WTC2(0x314fef00), WTC2(0x30ed0540), WTC2(0x30895c80), + WTC2(0x30251880), WTC2(0x2fc02880), WTC2(0x2f5a6480), WTC2(0x2ef3a480), + WTC2(0x2e8bd640), WTC2(0x2e231100), WTC2(0x2db97680), WTC2(0x2d4f2700), + WTC2(0x2ce431c0), WTC2(0x2c789080), WTC2(0x2c0c3bc0), WTC2(0x2b9f2bc0), + WTC2(0x2b315940), WTC2(0x2ac2bc00), WTC2(0x2a534cc0), WTC2(0x29e303c0)}; + +const FIXP_WTB ELDAnalysis256[768] = { + WTC(0xfababde8), WTC(0xfa8e1e6a), WTC(0xfa6012a9), WTC(0xfa30c8dd), + WTC(0xfa006f4b), WTC(0xf9cf32c4), WTC(0xf99d1cc8), WTC(0xf96a148d), + WTC(0xf936184d), WTC(0xf9013d5b), WTC(0xf8cb7b67), WTC(0xf894ace0), + WTC(0xf85cd28e), WTC(0xf82413f8), WTC(0xf7ea90af), WTC(0xf7b05ee6), + WTC(0xf7759b0b), WTC(0xf73a671f), WTC(0xf6febea3), WTC(0xf6c27a0e), + WTC(0xf685ca33), WTC(0xf6493907), WTC(0xf60d437b), WTC(0xf5d2551f), + WTC(0xf598d273), WTC(0xf561199e), WTC(0xf52b8c6f), WTC(0xf4f8907d), + WTC(0xf4c87fdf), WTC(0xf49ba806), WTC(0xf4724286), WTC(0xf44c6127), + WTC(0xf4282435), WTC(0xf401ceae), WTC(0xf3d775a1), WTC(0xf3a91477), + WTC(0xf376c33f), WTC(0xf340a328), WTC(0xf306d4d6), WTC(0xf2c9775c), + WTC(0xf288a3ed), WTC(0xf2446e2a), WTC(0xf1fcfa45), WTC(0xf1b27b2d), + WTC(0xf164f3f4), WTC(0xf114365c), WTC(0xf0c00532), WTC(0xf06817a9), + WTC(0xf00c4ea4), WTC(0xefacbc7f), WTC(0xef4a205f), WTC(0xeee5dc33), + WTC(0xee808a0d), WTC(0xee19eeb2), WTC(0xedb12f6e), WTC(0xed44e8eb), + WTC(0xecd50a13), WTC(0xec62d8dd), WTC(0xebef68b2), WTC(0xeb7b805c), + WTC(0xeb069af4), WTC(0xea8eef1c), WTC(0xea131c86), WTC(0xe99234c6), + WTC(0xe90cd9c2), WTC(0xe884f65b), WTC(0xe7fcbd6d), WTC(0xe7767300), + WTC(0xe6f289d0), WTC(0xe66f958a), WTC(0xe5eae99f), WTC(0xe560c403), + WTC(0xe4cfaaa1), WTC(0xe43887dc), WTC(0xe39dedc4), WTC(0xe303f190), + WTC(0xe26d7f5d), WTC(0xe1dc34ff), WTC(0xe14f9ced), WTC(0xe0c53cd0), + WTC(0xe03ab085), WTC(0xdfadc948), WTC(0xdf1d640c), WTC(0xde896bb6), + WTC(0xddf256ad), WTC(0xdd591e3d), WTC(0xdcbf0aec), WTC(0xdc25ab0a), + WTC(0xdb8e334c), WTC(0xdaf97794), WTC(0xda67bed9), WTC(0xd9d8c524), + WTC(0xd94bfa62), WTC(0xd8c089b5), WTC(0xd835c151), WTC(0xd7ab1704), + WTC(0xd7200906), WTC(0xd69420dc), WTC(0xd6073c0d), WTC(0xd5799615), + WTC(0xd4ec7c87), WTC(0xd46241c9), WTC(0xd3dc5bde), WTC(0xd35b4a79), + WTC(0xd2de1032), WTC(0xd26246f5), WTC(0xd1e68ed2), WTC(0xd16aa0a4), + WTC(0xd0eea5d2), WTC(0xd073302b), WTC(0xcff93749), WTC(0xcf820f45), + WTC(0xcf0ebb30), WTC(0xce9fd702), WTC(0xce34596c), WTC(0xcdc9a803), + WTC(0xcd5ec5d6), WTC(0xccf468ec), WTC(0xcc8bb41e), WTC(0xcc2619cc), + WTC(0xcbc3e090), WTC(0xcb6422f5), WTC(0xcb064d2f), WTC(0xcaaa2a6d), + WTC(0xca4fbdc9), WTC(0xc9f73c43), WTC(0xc9a0dc9b), WTC(0xc94cdd02), + WTC(0xc8f578a4), WTC(0xc8a24d15), WTC(0xc84dc71f), WTC(0xc7f83516), + WTC(0xc7a1e4b9), WTC(0xc74b22b1), WTC(0xc6f41284), WTC(0xc69cabc1), + WTC(0xc644986d), WTC(0xc5eb4167), WTC(0xc5910312), WTC(0xc5372c7f), + WTC(0xc4deba2e), WTC(0xc4883eca), WTC(0xc43310f0), WTC(0xc3dd5c5a), + WTC(0xc3868802), WTC(0xc32f431d), WTC(0xc2d86c9e), WTC(0xc28300a6), + WTC(0xc22fae33), WTC(0xc1ded3f7), WTC(0xc1908d7d), WTC(0xc144b0ed), + WTC(0xc0fa7cee), WTC(0xc0b0a3b5), WTC(0xc066b8d3), WTC(0xc01d3b32), + WTC(0xbfd5161c), WTC(0xbf8f92af), WTC(0xbf4d5cea), WTC(0xbf0e7d5e), + WTC(0xbed2ce3a), WTC(0xbe9a0062), WTC(0xbe63cec2), WTC(0xbe2ffd2f), + WTC(0xbdfe4565), WTC(0xbdce5568), WTC(0xbda003df), WTC(0xbd735018), + WTC(0xbd485b2c), WTC(0xbd1f69bd), WTC(0xbcf8db7c), WTC(0xbcd52b0a), + WTC(0xbcb4ae4a), WTC(0xbc979382), WTC(0xbc7dcbab), WTC(0xbc6709dc), + WTC(0xbc52c1b1), WTC(0xbc402f2b), WTC(0xbc2ec37b), WTC(0xbc1e2cb3), + WTC(0xbc0e5d5f), WTC(0xbbff8f23), WTC(0xbbf238d2), WTC(0xbbe707d4), + WTC(0xbbde3c63), WTC(0xbbd7a658), WTC(0xbbd2c7f0), WTC(0xbbcee18b), + WTC(0xbbcbdebb), WTC(0xbbca5ab1), WTC(0xbbcb5622), WTC(0xbbd032e4), + WTC(0xbbd91d4d), WTC(0xbbe53757), WTC(0xbbf32f54), WTC(0xbc016781), + WTC(0xbc0f433a), WTC(0xbc1d2aa4), WTC(0xbc2b4912), WTC(0xbc3985df), + WTC(0xbc47d6b9), WTC(0xbc564099), WTC(0xbc64c78a), WTC(0xbc736d96), + WTC(0xbc823210), WTC(0xbc911484), WTC(0xbca015b8), WTC(0xbcaf37eb), + WTC(0xbcbe7bc3), WTC(0xbccdde4d), WTC(0xbcdd6037), WTC(0xbced049a), + WTC(0xbcfccc81), WTC(0xbd0cb482), WTC(0xbd1cbcaa), WTC(0xbd2ce7ea), + WTC(0xbd3d363b), WTC(0xbd4da445), WTC(0xbd5e312d), WTC(0xbd6edfd1), + WTC(0xbd7fae14), WTC(0xbd90991b), WTC(0xbda19fcf), WTC(0xbdb2c464), + WTC(0xbdc4053b), WTC(0xbdd55f4b), WTC(0xbde6d0a0), WTC(0xbdf85c51), + WTC(0xbe09ffa3), WTC(0xbe1bb724), WTC(0xbe2d8160), WTC(0xbe3f5f98), + WTC(0xbe515144), WTC(0xbe6351a9), WTC(0xbe755ebd), WTC(0xbe877b8e), + WTC(0xbe99a63d), WTC(0xbeabda45), WTC(0xbebe16b0), WTC(0xbed05d1c), + WTC(0xbee2ada9), WTC(0xbef502e2), WTC(0xbf075c40), WTC(0xbf19bc0b), + WTC(0xbf2c217f), WTC(0xbf3e887a), WTC(0xbf50f09d), WTC(0xbf635c77), + WTC(0xbf75cac0), WTC(0xbf883905), WTC(0xbf9aa62b), WTC(0xbfad14f1), + WTC(0xbfbf85c7), WTC(0xbfd1f592), WTC(0xbfe461fc), WTC(0xbff6c86a), + WTC(0x80126c8d), WTC(0x80372448), WTC(0x805bd2fd), WTC(0x80807315), + WTC(0x80a4fffa), WTC(0x80c9748d), WTC(0x80edd08b), WTC(0x81121a23), + WTC(0x81364fde), WTC(0x815a6b16), WTC(0x817e6b36), WTC(0x81a25433), + WTC(0x81c625c8), WTC(0x81e9d801), WTC(0x820d6a5c), WTC(0x8230e060), + WTC(0x825438c0), WTC(0x82776ac7), WTC(0x829a7555), WTC(0x82bd5ca3), + WTC(0x82e01e80), WTC(0x8302b200), WTC(0x83251590), WTC(0x83474d79), + WTC(0x8369566f), WTC(0x838b2957), WTC(0x83acc2d9), WTC(0x83ce27c1), + WTC(0x83ef54b9), WTC(0x841042d1), WTC(0x8430ef15), WTC(0x84515e84), + WTC(0x84718e32), WTC(0x84917804), WTC(0x84b11a25), WTC(0x84d0788d), + WTC(0x84ef9322), WTC(0x850e61ec), WTC(0x852ce400), WTC(0x854b1e0a), + WTC(0x85690f2c), WTC(0x8586b207), WTC(0x85a4057b), WTC(0x85c1107d), + WTC(0x85ddd335), WTC(0x85fa485e), WTC(0x86167172), WTC(0x8632549d), + WTC(0x864df388), WTC(0x8669497e), WTC(0x86845757), WTC(0x869f2218), + WTC(0x86b9ab5a), WTC(0x86d3f1bf), WTC(0x86edf68f), WTC(0x8707baf1), + WTC(0x872147e0), WTC(0x873aa6fc), WTC(0x8753c571), WTC(0x876c76e6), + WTC(0x87850ab7), WTC(0x879e373b), WTC(0x87b6ea37), WTC(0x87cc4188), + WTC(0x880d4300), WTC(0x8855e9ff), WTC(0x88acfca0), WTC(0x890d0f94), + WTC(0x8971e7d5), WTC(0x89d8a0c1), WTC(0x8a3fc425), WTC(0x8aa74105), + WTC(0x8b0f5b93), WTC(0x8b78a107), WTC(0x8be38bb3), WTC(0x8c508092), + WTC(0x8cbfe384), WTC(0x8d3214f1), WTC(0x8da75d21), WTC(0x8e1fe96c), + WTC(0x8e9be76a), WTC(0x8f1b806c), WTC(0x8f9ed314), WTC(0x9025f26a), + WTC(0x90b0ecea), WTC(0x913fd0eb), WTC(0x91d2a684), WTC(0x92696dea), + WTC(0x93042868), WTC(0x93a2d456), WTC(0x94456d20), WTC(0x94ebe9e5), + WTC(0x95964178), WTC(0x96446a05), WTC(0x96f65958), WTC(0x97ac059a), + WTC(0x98656089), WTC(0x99225a80), WTC(0x99e2e2e8), WTC(0x9aa6e666), + WTC(0x9b6e54b8), WTC(0x9c391d99), WTC(0x9d07338a), WTC(0x9dd8888d), + WTC(0x9ead0b5c), WTC(0x9f84a871), WTC(0xa05f4fb3), WTC(0xa13cf913), + WTC(0xa21d9891), WTC(0xa3011e27), WTC(0xa3e77eb4), WTC(0xa4d0b190), + WTC(0xa5bcb0d7), WTC(0xa6ab750c), WTC(0xa79cf884), WTC(0xa89135cb), + WTC(0xa9882a44), WTC(0xaa81d578), WTC(0xab7e39a6), WTC(0xac7d5a36), + WTC(0xad7f3ba5), WTC(0xae83dfed), WTC(0xaf8b4e16), WTC(0xb095911c), + WTC(0xb1a2afd1), WTC(0xb2b2ac9f), WTC(0xb3c58807), WTC(0xb4db4d5e), + WTC(0x4a268ead), WTC(0x490b5ba7), WTC(0x47ed8d30), WTC(0x46cd10c5), + WTC(0x45a9dcc1), WTC(0x4483f267), WTC(0x435b5aeb), WTC(0x42301d12), + WTC(0x41023a15), WTC(0x3fd19bf1), WTC(0x3e9e31e1), WTC(0x3d682986), + WTC(0x3c2fc001), WTC(0x3af52d8f), WTC(0x39b88b7d), WTC(0x38798642), + WTC(0x3737e6d3), WTC(0x35f3e98a), WTC(0x34add45c), WTC(0x33660083), + WTC(0x321ccf3a), WTC(0x30d2963e), WTC(0x2f87a28f), WTC(0x2e3c22cd), + WTC(0x2cf010e5), WTC(0x2ba2ffe5), WTC(0x2a54ba93), WTC(0x290596f5), + WTC(0x27b62806), WTC(0x266762b8), WTC(0x251a11b1), WTC(0x23ce94f9), + WTC(0x22852ddb), WTC(0x213df340), WTC(0x1ff90185), WTC(0x1eb67d94), + WTC(0x1d767485), WTC(0x1c38d477), WTC(0x1afda747), WTC(0x19c5248b), + WTC(0x188f8259), WTC(0x175d0d40), WTC(0x162e5320), WTC(0x150436cd), + WTC(0x13df8d3f), WTC(0x12c102f1), WTC(0x11a8dd65), WTC(0x1096d490), + WTC(0x0f8a1755), WTC(0x0e811dcd), WTC(0x0d7acb9a), WTC(0x0c767d00), + WTC(0x0b7334d9), WTC(0x0a6fef31), WTC(0x096c5a87), WTC(0x08691adb), + WTC(0x0765e395), WTC(0x06610309), WTC(0x0558a0d2), WTC(0x044a946c), + WTC(0x033acb52), WTC(0x0234706f), WTC(0x014939dc), WTC(0x00928577), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xffe73593), WTC(0xffb63fcf), WTC(0xff853c1f), WTC(0xff5454d7), + WTC(0xff23b44b), WTC(0xfef38417), WTC(0xfec3dc9a), WTC(0xfe94c511), + WTC(0xfe664753), WTC(0xfe387086), WTC(0xfe0b4e63), WTC(0xfddef15c), + WTC(0xfdb3a3f6), WTC(0xfd89e611), WTC(0xfd61c750), WTC(0xfd3ae585), + WTC(0xfd14ec09), WTC(0xfcef9b06), WTC(0xfccaf509), WTC(0xfca74180), + WTC(0xfc8518a3), WTC(0xfc655c7a), WTC(0xfc488545), WTC(0xfc2e9998), + WTC(0xfc1726bb), WTC(0xfc01463f), WTC(0xfbec2c64), WTC(0xfbd735ce), + WTC(0xfbc29e8e), WTC(0xfbaf8042), WTC(0xfb9eeba0), WTC(0xfb91dc05), + WTC(0xfb88f420), WTC(0xfb8479eb), WTC(0xfb84398b), WTC(0xfb87884b), + WTC(0xfb8da8bf), WTC(0xfb95d020), WTC(0xfb9f3e49), WTC(0xfba9448a), + WTC(0xfbb3cf10), WTC(0xfbbf67e7), WTC(0xfbccf65d), WTC(0xfbddba58), + WTC(0xfbf31f46), WTC(0xfc0eb236), WTC(0xfc3164f0), WTC(0xfc5b8269), + WTC(0xfc8c5bcd), WTC(0xfcc248ee), WTC(0xfcfb056c), WTC(0xfd33cc26), + WTC(0xfd6b84ee), WTC(0xfda2d9e7), WTC(0xfddc03fb), WTC(0xfe1aaf57), + WTC(0xfe61a0af), WTC(0xfeb28df7), WTC(0xff0cd343), WTC(0xff6d8388), + WTC(0xffd24331), WTC(0x00396fe3), WTC(0x00a2fb3e), WTC(0x01107050), + WTC(0x01831900), WTC(0x01fc2377), WTC(0x027bd1fc), WTC(0x03019a2d), + WTC(0x038d0a88), WTC(0x041dd88f), WTC(0x04b43495), WTC(0x0550c1ef), + WTC(0x05f38bd6), WTC(0x069c0523), WTC(0x074a114e), WTC(0x07fe0ceb), + WTC(0x08b88e33), WTC(0x097a5965), WTC(0x0a438318), WTC(0x0b137046), + WTC(0x0be9b5ab), WTC(0x0cc61fa9), WTC(0x0da897b2), WTC(0x0e9123b3), + WTC(0x0f7ff200), WTC(0x10755696), WTC(0x11717f94), WTC(0x127474a0), + WTC(0x137e489d), WTC(0x148f1b02), WTC(0x15a6f15e), WTC(0x16c5b7c9), + WTC(0x17eb72b1), WTC(0x19183e51), WTC(0x1a4c2444), WTC(0x1b871b1c), + WTC(0x1cc92e92), WTC(0x1e127ffc), WTC(0x1f6319b9), WTC(0x20baef78), + WTC(0x221a0861), WTC(0x23807f94), WTC(0x24ee5a89), WTC(0x2663898d), + WTC(0x27e0101e), WTC(0x2964058d), WTC(0x2aef6bcf), WTC(0x2c8230fc), + WTC(0x2e1c545b), WTC(0x2fbde72b), WTC(0x3166e76f), WTC(0x33173f5d), + WTC(0x34cee8c3), WTC(0x368debe1), WTC(0x38543d4f), WTC(0x3a21bd94), + WTC(0x3bf6576f), WTC(0x3dd1ff07), WTC(0x3fb4948e), WTC(0x419de414), + WTC(0x438dc202), WTC(0x45840e7d), WTC(0x4780a435), WTC(0x4983609f), + WTC(0x4b8cc548), WTC(0x4d9df796), WTC(0x4fb81f46), WTC(0x51dc8690), + WTC(0x000d970d), WTC(0xfff7ea67), WTC(0xfff7fc3d), WTC(0x000d3de2), + WTC(0x003720ad), WTC(0x007515f1), WTC(0x00c68f04), WTC(0x012afd3b), + WTC(0x01a1d1ec), WTC(0x022a7e69), WTC(0x02c47408), WTC(0x036f2420), + WTC(0x042a0001), WTC(0x04f47905), WTC(0x05ce007e), WTC(0x06b607be), + WTC(0x07ac0028), WTC(0x08af5b01), WTC(0x09bf89a7), WTC(0x0adbfd6d), + WTC(0x0c042798), WTC(0x0d377997), WTC(0x0e7564b5), WTC(0x0fbd5a3a), + WTC(0x110ecb85), WTC(0x126929fb), WTC(0x13cbe6e6), WTC(0x15367376), + WTC(0x16a8413f), WTC(0x1820c15f), WTC(0x199f6568), WTC(0x1b239e6b), + WTC(0x1cacdde2), WTC(0x1e3a951a), WTC(0x1fcc356f), WTC(0x2161301f), + WTC(0x22f8f6b7), WTC(0x2492fa4a), WTC(0x262eac3f), WTC(0x27cb7e20), + WTC(0x2968e0c4), WTC(0x2b064625), WTC(0x2ca31f1a), WTC(0x2e3edd2a), + WTC(0x2fd8f19f), WTC(0x3170ce00), WTC(0x3305e32c), WTC(0x3497a2df), + WTC(0x36257e78), WTC(0x37aee70b), WTC(0x39334e05), WTC(0x3ab22498), + WTC(0x3c2adc2c), WTC(0x3d9ce645), WTC(0x3f07b3ef), WTC(0x406ab6ca), + WTC(0x41c56001), WTC(0x4317214a), WTC(0x445f6b34), WTC(0x459daf5d), + WTC(0x46d15f56), WTC(0x47f9ed71), WTC(0x4916d11f), WTC(0x4a275770), + WTC(0x4b2b2fff), WTC(0x4c219eae), WTC(0x4d0a20cb), WTC(0x4de4288e), + WTC(0x4eaf263d), WTC(0x4f6a8bb8), WTC(0x5015ca33), WTC(0x50b052dd), + WTC(0x51399757), WTC(0x51b108c6), WTC(0x5216190a), WTC(0x5268387c), + WTC(0x52a6d933), WTC(0x52d16c19), WTC(0x52e7628b), WTC(0x52e82ea3), + WTC(0x52d3407d), WTC(0x52a80a28), WTC(0x5265fd43), WTC(0x520c8a1d), + WTC(0x519b22c8), WTC(0x511138e0), WTC(0x506e3c82), WTC(0x4fb1a037), + WTC(0x4edad4e3), WTC(0x4de94c2d), WTC(0x4cdc76d8), WTC(0x4bb3c683), + WTC(0x4a6eacd2), WTC(0x490c9abe), WTC(0x478d04f1), WTC(0x45f00420), + WTC(0x4445673f), WTC(0x42ac0d2e), WTC(0x41338364), WTC(0x3fdb5b58), + WTC(0x3ea1c30f), WTC(0x3d842780), WTC(0x3c7fa763), WTC(0x3b911b96), + WTC(0x3ab560bf), WTC(0x39e95908), WTC(0x3929debb), WTC(0x3873bd4d), + WTC(0x37c31db2), WTC(0x3713a59c), WTC(0x3663deb2), WTC(0x35b52f23), + WTC(0x3507c61e), WTC(0x345a7f42), WTC(0x33ac7e0c), WTC(0x32fd366f), + WTC(0x324baa28), WTC(0x319674e9), WTC(0x30dd7e1a), WTC(0x3021f3e8), + WTC(0x2f63f903), WTC(0x2ea2a1aa), WTC(0x2dddd97b), WTC(0x2d166985), + WTC(0x2c4ca42f), WTC(0x2b805cca), WTC(0x2ab162aa), WTC(0x29df7b17), +}; + +const FIXP_WTB ELDAnalysis240[720] = { + WTC(0xfab9477b), WTC(0xfa899344), WTC(0xfa5845dd), WTC(0xfa259762), + WTC(0xf9f1c005), WTC(0xf9bcefe6), WTC(0xf9871e8b), WTC(0xf9503397), + WTC(0xf9183f47), WTC(0xf8df4eac), WTC(0xf8a53ba7), WTC(0xf869f0be), + WTC(0xf82d9759), WTC(0xf7f0593e), WTC(0xf7b2520a), WTC(0xf773a37c), + WTC(0xf73475ce), WTC(0xf6f4bedd), WTC(0xf6b455a8), WTC(0xf6739525), + WTC(0xf6332510), WTC(0xf5f3938b), WTC(0xf5b56073), WTC(0xf57900bd), + WTC(0xf53ee82d), WTC(0xf5079149), WTC(0xf4d36ffc), WTC(0xf4a2e526), + WTC(0xf4763d91), WTC(0xf44d9872), WTC(0xf426eaed), WTC(0xf3fdc161), + WTC(0xf3d001ff), WTC(0xf39dafcc), WTC(0xf366eb43), WTC(0xf32bdcdc), + WTC(0xf2ecab80), WTC(0xf2a97b34), WTC(0xf26265ae), WTC(0xf2178a6f), + WTC(0xf1c92458), WTC(0xf17752b9), WTC(0xf121e6ac), WTC(0xf0c89a63), + WTC(0xf06b15ef), WTC(0xf0092e86), WTC(0xefa2fd42), WTC(0xef397ebc), + WTC(0xeece51c6), WTC(0xee61e8b6), WTC(0xedf3d92e), WTC(0xed82c330), + WTC(0xed0d58bb), WTC(0xec94891b), WTC(0xec19d435), WTC(0xeb9e4e4e), + WTC(0xeb221000), WTC(0xeaa32422), WTC(0xea1fb440), WTC(0xe99695d2), + WTC(0xe90859ab), WTC(0xe8775114), WTC(0xe7e62b37), WTC(0xe7578147), + WTC(0xe6cb3ac1), WTC(0xe63f5696), WTC(0xe5afe916), WTC(0xe519090f), + WTC(0xe47aab0d), WTC(0xe3d6c2d0), WTC(0xe331dae7), WTC(0xe29031e1), + WTC(0xe1f40926), WTC(0xe15d87d2), WTC(0xe0c9d727), WTC(0xe0360ad5), + WTC(0xdf9f81af), WTC(0xdf04f9f9), WTC(0xde66697f), WTC(0xddc48ca1), + WTC(0xdd20a42a), WTC(0xdc7c6853), WTC(0xdbd9a476), WTC(0xdb398a8c), + WTC(0xda9cd7c2), WTC(0xda0365cf), WTC(0xd96cad85), WTC(0xd8d7b7a3), + WTC(0xd8439e8c), WTC(0xd7afb73d), WTC(0xd71b6347), WTC(0xd686149a), + WTC(0xd5efab2c), WTC(0xd558877e), WTC(0xd4c29dbc), WTC(0xd430a0aa), + WTC(0xd3a3d490), WTC(0xd31c588f), WTC(0xd297e075), WTC(0xd213ef33), + WTC(0xd18fd566), WTC(0xd10b8d3f), WTC(0xd087b250), WTC(0xd0054ef2), + WTC(0xcf85f94a), WTC(0xcf0af5f7), WTC(0xce94faf5), WTC(0xce229409), + WTC(0xcdb0b5f8), WTC(0xcd3ec554), WTC(0xcccdbf58), WTC(0xcc5f39d5), + WTC(0xcbf49ef5), WTC(0xcb8d5f73), WTC(0xcb28801c), WTC(0xcac5a265), + WTC(0xca64ad2e), WTC(0xca05d7fd), WTC(0xc9a96602), WTC(0xc94f9f79), + WTC(0xc8f2b954), WTC(0xc899e795), WTC(0xc83f94aa), WTC(0xc7e41f63), + WTC(0xc787e69f), WTC(0xc72b3fd0), WTC(0xc6ce3f0f), WTC(0xc670c175), + WTC(0xc61224cf), WTC(0xc5b21fec), WTC(0xc55202a4), WTC(0xc4f3353a), + WTC(0xc4968597), WTC(0xc43b93f2), WTC(0xc3e03d26), WTC(0xc383a011), + WTC(0xc3268aed), WTC(0xc2ca1039), WTC(0xc26f5bcc), WTC(0xc21726c9), + WTC(0xc1c1d5b2), WTC(0xc16f66ba), WTC(0xc11f76d9), WTC(0xc0d0a9f6), + WTC(0xc081cddb), WTC(0xc0333180), WTC(0xbfe5bb54), WTC(0xbf9aee90), + WTC(0xbf53d587), WTC(0xbf108855), WTC(0xbed0de05), WTC(0xbe9477d7), + WTC(0xbe5b030f), WTC(0xbe243642), WTC(0xbdefb72f), WTC(0xbdbd29df), + WTC(0xbd8c71ab), WTC(0xbd5d99cb), WTC(0xbd30e375), WTC(0xbd06afcc), + WTC(0xbcdf8c7f), WTC(0xbcbbf704), WTC(0xbc9c307e), WTC(0xbc803b86), + WTC(0xbc67c0c7), WTC(0xbc521d3d), WTC(0xbc3e6561), WTC(0xbc2bf2cb), + WTC(0xbc1a6872), WTC(0xbc09ce15), WTC(0xbbfa764f), WTC(0xbbed1356), + WTC(0xbbe257fa), WTC(0xbbda4099), WTC(0xbbd46a31), WTC(0xbbcffa76), + WTC(0xbbcc766d), WTC(0xbbca782f), WTC(0xbbcb16c7), WTC(0xbbcff77c), + WTC(0xbbd978e6), WTC(0xbbe68e5f), WTC(0xbbf593ed), WTC(0xbc04a834), + WTC(0xbc136941), WTC(0xbc2252c3), WTC(0xbc31723d), WTC(0xbc40ab92), + WTC(0xbc4ffe2d), WTC(0xbc5f7072), WTC(0xbc6f0520), WTC(0xbc7ebd23), + WTC(0xbc8e9746), WTC(0xbc9e942f), WTC(0xbcaeb633), WTC(0xbcbefe8b), + WTC(0xbccf69bb), WTC(0xbcdff92e), WTC(0xbcf0b04f), WTC(0xbd018ebd), + WTC(0xbd129192), WTC(0xbd23b9b8), WTC(0xbd350afb), WTC(0xbd46820e), + WTC(0xbd581bfc), WTC(0xbd69db11), WTC(0xbd7bbf57), WTC(0xbd8dc584), + WTC(0xbd9feaad), WTC(0xbdb231a4), WTC(0xbdc498ea), WTC(0xbdd71cd1), + WTC(0xbde9bb57), WTC(0xbdfc77d9), WTC(0xbe0f4e93), WTC(0xbe223ae5), + WTC(0xbe353cf5), WTC(0xbe485689), WTC(0xbe5b8329), WTC(0xbe6ebe88), + WTC(0xbe820afd), WTC(0xbe956811), WTC(0xbea8d109), WTC(0xbebc4352), + WTC(0xbecfc0fb), WTC(0xbee34a07), WTC(0xbef6d884), WTC(0xbf0a6bb1), + WTC(0xbf1e0685), WTC(0xbf31a685), WTC(0xbf45483c), WTC(0xbf58eb6b), + WTC(0xbf6c9376), WTC(0xbf803c90), WTC(0xbf93e4b9), WTC(0xbfa78d05), + WTC(0xbfbb3830), WTC(0xbfcee339), WTC(0xbfe28aa9), WTC(0xbff62b89), + WTC(0x8013a5f4), WTC(0x803acfd6), WTC(0x8061eec7), WTC(0x8088fc73), + WTC(0x80aff270), WTC(0x80d6cbe5), WTC(0x80fd8c2a), WTC(0x812437a8), + WTC(0x814ac94f), WTC(0x81713adc), WTC(0x81979098), WTC(0x81bdccb7), + WTC(0x81e3e738), WTC(0x8209dd04), WTC(0x822fb23a), WTC(0x825565bb), + WTC(0x827aed94), WTC(0x82a04909), WTC(0x82c57c85), WTC(0x82ea831c), + WTC(0x830f539d), WTC(0x8333eeba), WTC(0x8358585a), WTC(0x837c882e), + WTC(0x83a07742), WTC(0x83c428a5), WTC(0x83e79c4c), WTC(0x840aca65), + WTC(0x842dad81), WTC(0x84504ac0), WTC(0x84729fb1), WTC(0x8494a4f1), + WTC(0x84b65932), WTC(0x84d7c0f8), WTC(0x84f8d936), WTC(0x85199a59), + WTC(0x853a05a1), WTC(0x855a2023), WTC(0x8579e46e), WTC(0x85994d55), + WTC(0x85b86190), WTC(0x85d723e6), WTC(0x85f58fa9), WTC(0x8613a3ce), + WTC(0x863167b5), WTC(0x864eddfe), WTC(0x866c0138), WTC(0x8688d2e4), + WTC(0x86a55901), WTC(0x86c19497), WTC(0x86dd8390), WTC(0x86f9288f), + WTC(0x871487e0), WTC(0x872fadd0), WTC(0x874a9a1e), WTC(0x876519d0), + WTC(0x877f471e), WTC(0x8799fb36), WTC(0x87b48b97), WTC(0x87cba021), + WTC(0x880f67ae), WTC(0x885e0f91), WTC(0x88bc84cd), WTC(0x89244640), + WTC(0x8990a45d), WTC(0x89fe6766), WTC(0x8a6c9065), WTC(0x8adb31e6), + WTC(0x8b4ad5b3), WTC(0x8bbc2068), WTC(0x8c2f93ff), WTC(0x8ca5a922), + WTC(0x8d1ed72d), WTC(0x8d9b7ddb), WTC(0x8e1bd6cc), WTC(0x8ea01924), + WTC(0x8f287716), WTC(0x8fb5143e), WTC(0x9046074e), WTC(0x90db612b), + WTC(0x91753263), WTC(0x92138094), WTC(0x92b64cf3), WTC(0x935d96c9), + WTC(0x94095a56), WTC(0x94b98fd4), WTC(0x956e2a87), WTC(0x96271ff6), + WTC(0x96e46309), WTC(0x97a5e80d), WTC(0x986b9e55), WTC(0x993572af), + WTC(0x9a0350ce), WTC(0x9ad52154), WTC(0x9baad10f), WTC(0x9c844cdd), + WTC(0x9d618437), WTC(0x9e4265b2), WTC(0x9f26d9ad), WTC(0xa00ec9b0), + WTC(0xa0fa2916), WTC(0xa1e8ec20), WTC(0xa2daffa4), WTC(0xa3d05468), + WTC(0xa4c8e007), WTC(0xa5c49ae4), WTC(0xa6c37c24), WTC(0xa7c57d03), + WTC(0xa8ca9750), WTC(0xa9d2c7f2), WTC(0xaade0f6f), WTC(0xabec7177), + WTC(0xacfdf2b1), WTC(0xae129740), WTC(0xaf2a6321), WTC(0xb04563a6), + WTC(0xb163a2e6), WTC(0xb28524c4), WTC(0xb3a9eaf7), WTC(0xb4d1ff1b), + WTC(0x4a1d2880), WTC(0x48eee56e), WTC(0x47bda882), WTC(0x46895c79), + WTC(0x4551f8a1), WTC(0x4417817b), WTC(0x42da023d), WTC(0x419980ca), + WTC(0x4055f463), WTC(0x3f0f3b51), WTC(0x3dc56e18), WTC(0x3c78d943), + WTC(0x3b29bf3d), WTC(0x39d84ea0), WTC(0x3884337d), WTC(0x372d2371), + WTC(0x35d364ea), WTC(0x34774cef), WTC(0x33194d3a), WTC(0x31b9d586), + WTC(0x30594fcf), WTC(0x2ef80b63), WTC(0x2d9630d5), WTC(0x2c337c00), + WTC(0x2acf6a9e), WTC(0x296a3205), WTC(0x28046825), WTC(0x269f1752), + WTC(0x253b5314), WTC(0x23d9993f), WTC(0x227a3c77), WTC(0x211d59a0), + WTC(0x1fc314fd), WTC(0x1e6b9834), WTC(0x1d16eb58), WTC(0x1bc4f82e), + WTC(0x1a75e481), WTC(0x1929f389), WTC(0x17e16ee3), WTC(0x169cd758), + WTC(0x155d1ae5), WTC(0x14235182), WTC(0x12f051de), WTC(0x11c4993b), + WTC(0x109fdf4c), WTC(0x0f81351c), WTC(0x0e66c5e6), WTC(0x0d4f4b16), + WTC(0x0c39f013), WTC(0x0b25765d), WTC(0x0a10c51e), WTC(0x08fbee35), + WTC(0x07e7986f), WTC(0x06d25fe7), WTC(0x05ba1b52), WTC(0x049c33b7), + WTC(0x0379ceb9), WTC(0x025ee7c7), WTC(0x015edc1c), WTC(0x00978deb), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xffe59474), WTC(0xffb158f8), WTC(0xff7d1275), WTC(0xff48f44c), + WTC(0xff1531e3), WTC(0xfee1faa9), WTC(0xfeaf626e), WTC(0xfe7d7227), + WTC(0xfe4c383f), WTC(0xfe1bc4ff), WTC(0xfdec297f), WTC(0xfdbd9f6c), + WTC(0xfd90bbf0), WTC(0xfd65ba73), WTC(0xfd3c2d32), WTC(0xfd13ab35), + WTC(0xfcebe811), WTC(0xfcc4eeae), WTC(0xfc9f1d64), WTC(0xfc7b48b0), + WTC(0xfc5a7282), WTC(0xfc3cef9b), WTC(0xfc229f4c), WTC(0xfc0a9e29), + WTC(0xfbf3dccb), WTC(0xfbdd80c3), WTC(0xfbc7556c), WTC(0xfbb289cf), + WTC(0xfba06f99), WTC(0xfb923aca), WTC(0xfb88bb57), WTC(0xfb84457f), + WTC(0xfb848c2e), WTC(0xfb88bd28), WTC(0xfb8feda1), WTC(0xfb9928eb), + WTC(0xfba38b9e), WTC(0xfbae711c), WTC(0xfbba3538), WTC(0xfbc7af9d), + WTC(0xfbd8485e), WTC(0xfbeda238), WTC(0xfc099de4), WTC(0xfc2d981f), + WTC(0xfc59fd0d), WTC(0xfc8e1583), WTC(0xfcc7e0d7), WTC(0xfd048d03), + WTC(0xfd40dfaf), WTC(0xfd7c1d35), WTC(0xfdb767cc), WTC(0xfdf64a9f), + WTC(0xfe3d0242), WTC(0xfe8e3316), WTC(0xfeead2b9), WTC(0xff4fff8c), + WTC(0xffba7b11), WTC(0x00281cae), WTC(0x009847d1), WTC(0x010cb653), + WTC(0x01870639), WTC(0x02089db5), WTC(0x0291b571), WTC(0x0321a4c1), + WTC(0x03b7eda0), WTC(0x04544c7f), WTC(0x04f74134), WTC(0x05a16810), + WTC(0x06525829), WTC(0x070994d4), WTC(0x07c767ba), WTC(0x088c69b8), + WTC(0x09598634), WTC(0x0a2f14ca), WTC(0x0b0c677b), WTC(0x0bf0f576), + WTC(0x0cdc7f73), WTC(0x0dceed54), WTC(0x0ec84a00), WTC(0x0fc8db86), + WTC(0x10d10278), WTC(0x11e0e05e), WTC(0x12f880cc), WTC(0x1418049b), + WTC(0x153f86b3), WTC(0x166ef5a3), WTC(0x17a64878), WTC(0x18e59dde), + WTC(0x1a2d088b), WTC(0x1b7c7e41), WTC(0x1cd40ab7), WTC(0x1e33d542), + WTC(0x1f9be7a5), WTC(0x210c344f), WTC(0x2284cb85), WTC(0x2405ca48), + WTC(0x258f2b7f), WTC(0x2720e063), WTC(0x28bafd49), WTC(0x2a5d950c), + WTC(0x2c0896e4), WTC(0x2dbbf7d4), WTC(0x2f77ca28), WTC(0x313c1273), + WTC(0x3308b7e4), WTC(0x34ddb0ec), WTC(0x36bb06b7), WTC(0x38a0a935), + WTC(0x3a8e7270), WTC(0x3c844ca9), WTC(0x3e82267e), WTC(0x4087ccfa), + WTC(0x42950352), WTC(0x44a99ce7), WTC(0x46c57093), WTC(0x48e84dbe), + WTC(0x4b127506), WTC(0x4d452d29), WTC(0x4f81e066), WTC(0x51ca11c4), + WTC(0x000c82e8), WTC(0xfff6f40c), WTC(0xfffa1260), WTC(0x001530bf), + WTC(0x0047a202), WTC(0x0090b903), WTC(0x00efc89f), WTC(0x016423af), + WTC(0x01ed1d0e), WTC(0x028a0796), WTC(0x033a3620), WTC(0x03fcfb89), + WTC(0x04d1aaaa), WTC(0x05b7965c), WTC(0x06ae1179), WTC(0x07b46ee8), + WTC(0x08ca0173), WTC(0x09ee1c00), WTC(0x0b201162), WTC(0x0c5f346e), + WTC(0x0daad808), WTC(0x0f024f17), WTC(0x1064ec4b), WTC(0x11d202c4), + WTC(0x1348e514), WTC(0x14c8e62f), WTC(0x1651590a), WTC(0x17e19051), + WTC(0x1978df27), WTC(0x1b169812), WTC(0x1cba0e15), WTC(0x1e629407), + WTC(0x200f7cd4), WTC(0x21c01b29), WTC(0x2373c228), WTC(0x2529c453), + WTC(0x26e174b9), WTC(0x289a262f), WTC(0x2a532bba), WTC(0x2c0bd7b2), + WTC(0x2dc37d92), WTC(0x2f796fce), WTC(0x312d017a), WTC(0x32dd8513), + WTC(0x348a4dde), WTC(0x3632aeb3), WTC(0x37d5fa29), WTC(0x39738334), + WTC(0x3b0a9c99), WTC(0x3c9a9926), WTC(0x3e22cc21), WTC(0x3fa287dc), + WTC(0x41191f89), WTC(0x4285e5fc), WTC(0x43e82e02), WTC(0x453f4a40), + WTC(0x468a8dd9), WTC(0x47c94c23), WTC(0x48fadc7c), WTC(0x4a1e75f9), + WTC(0x4b339ecf), WTC(0x4c3981b1), WTC(0x4d2f7cd3), WTC(0x4e14e381), + WTC(0x4ee90804), WTC(0x4fab3d6a), WTC(0x505ad6bd), WTC(0x50f726a3), + WTC(0x517f7fea), WTC(0x51f335fd), WTC(0x52519b0f), WTC(0x529a01f2), + WTC(0x52cbbe31), WTC(0x52e621d9), WTC(0x52e880aa), WTC(0x52d22c7a), + WTC(0x52a278a5), WTC(0x5258b880), WTC(0x51f43e1d), WTC(0x51745c38), + WTC(0x50d8669e), WTC(0x501faf0e), WTC(0x4f49897e), WTC(0x4e554804), + WTC(0x4d423d9e), WTC(0x4c0fbd8b), WTC(0x4abd1a4d), WTC(0x4949a698), + WTC(0x47b4b7f9), WTC(0x45fe2b6d), WTC(0x44375019), WTC(0x4284e96e), + WTC(0x40f7efa2), WTC(0x3f8f8b33), WTC(0x3e494311), WTC(0x3d21e35b), + WTC(0x3c15c621), WTC(0x3b2115f3), WTC(0x3a4008aa), WTC(0x396ed2a6), + WTC(0x38a99a1d), WTC(0x37ec1177), WTC(0x3730f154), WTC(0x36756c15), + WTC(0x35bafb0d), WTC(0x35020093), WTC(0x34492381), WTC(0x338f6226), + WTC(0x32d40a34), WTC(0x3215bd73), WTC(0x315302ce), WTC(0x308c7c41), + WTC(0x2fc3532f), WTC(0x2ef6de8f), WTC(0x2e265a7f), WTC(0x2d527bfd), + WTC(0x2c7bf035), WTC(0x2ba2975b), WTC(0x2ac63552), WTC(0x29e686ca), +}; + +const FIXP_WTB ELDAnalysis128[384] = { + WTC(0xfaa49e98), WTC(0xfa48929f), WTC(0xf9e7eb39), WTC(0xf983b829), + WTC(0xf91bc5cb), WTC(0xf8b0376f), WTC(0xf8408d62), WTC(0xf7cd8c1e), + WTC(0xf7580da3), WTC(0xf6e0b0dc), WTC(0xf667753c), WTC(0xf5efa4cf), + WTC(0xf57cb6de), WTC(0xf511b62b), WTC(0xf4b1a860), WTC(0xf45ee8f8), + WTC(0xf415710d), WTC(0xf3c0c4f3), WTC(0xf35c2af9), WTC(0xf2e89620), + WTC(0xf266f3cb), WTC(0xf1d819bf), WTC(0xf13cff2f), WTC(0xf09489d2), + WTC(0xefdcfa80), WTC(0xef182059), WTC(0xee4d6c60), WTC(0xed7b8da7), + WTC(0xec9c27b1), WTC(0xebb57d0d), WTC(0xeacb3918), WTC(0xe9d35591), + WTC(0xe8c9176e), WTC(0xe7b93e42), WTC(0xe6b10e47), WTC(0xe5a6b875), + WTC(0xe484c345), WTC(0xe3509f1b), WTC(0xe224254c), WTC(0xe10a4e18), + WTC(0xdff4a668), WTC(0xded3d881), WTC(0xdda5ed98), WTC(0xdc722d13), + WTC(0xdb437360), WTC(0xda1fefed), WTC(0xd90623b2), WTC(0xd7f070f5), + WTC(0xd6da361b), WTC(0xd5c0786f), WTC(0xd4a6e188), WTC(0xd39b37b4), + WTC(0xd2a01ff2), WTC(0xd1a8a05c), WTC(0xd0b0cf47), WTC(0xcfbd3527), + WTC(0xced6b8d7), WTC(0xcdff0a66), WTC(0xcd2978a4), WTC(0xcc587183), + WTC(0xcb93bfdb), WTC(0xcad80773), WTC(0xca233c2b), WTC(0xc9768b5e), + WTC(0xc8cc130c), WTC(0xc8231acd), WTC(0xc7768de4), WTC(0xc6c86bdf), + WTC(0xc6181aa1), WTC(0xc563f6ce), WTC(0xc4b33a2a), WTC(0xc4085fcf), + WTC(0xc35ae72e), WTC(0xc2ad7adf), WTC(0xc206ed94), WTC(0xc16a5744), + WTC(0xc0d59625), WTC(0xc041e21b), WTC(0xbfb1ee05), WTC(0xbf2d82ea), + WTC(0xbeb60fe9), WTC(0xbe499da8), WTC(0xbde61891), WTC(0xbd8975b6), + WTC(0xbd339d36), WTC(0xbce6a08b), WTC(0xbca5b2f9), WTC(0xbc721002), + WTC(0xbc494d41), WTC(0xbc266160), WTC(0xbc06d14f), WTC(0xbbec52c7), + WTC(0xbbdaaf79), WTC(0xbbd0be99), WTC(0xbbcae139), WTC(0xbbcd359c), + WTC(0xbbded5d3), WTC(0xbbfa58cf), WTC(0xbc162f9d), WTC(0xbc326534), + WTC(0xbc4f081c), WTC(0xbc6c1678), WTC(0xbc899f93), WTC(0xbca7a263), + WTC(0xbcc62954), WTC(0xbce52ddc), WTC(0xbd04bc7f), WTC(0xbd24cd8f), + WTC(0xbd456998), WTC(0xbd668428), WTC(0xbd88207c), WTC(0xbdaa2e4b), + WTC(0xbdccaf3e), WTC(0xbdef932c), WTC(0xbe12d936), WTC(0xbe366dd6), + WTC(0xbe5a4fd9), WTC(0xbe7e6b49), WTC(0xbea2bf3f), WTC(0xbec738b5), + WTC(0xbeebd791), WTC(0xbf108b49), WTC(0xbf3554aa), WTC(0xbf5a25cf), + WTC(0xbf7f020b), WTC(0xbfa3dd25), WTC(0xbfc8be1e), WTC(0xbfed95f6), + WTC(0x8024c933), WTC(0x806e24fb), WTC(0x80b73d96), WTC(0x80fff78c), + WTC(0x8148612f), WTC(0x8190626e), WTC(0x81d8030a), WTC(0x821f28e1), + WTC(0x8265d6be), WTC(0x82abed56), WTC(0x82f16e40), WTC(0x833636d2), + WTC(0x837a470a), WTC(0x83bd7be6), WTC(0x83ffd415), WTC(0x84412e66), + WTC(0x84818c4f), WTC(0x84c0d18c), WTC(0x84ff0429), WTC(0x853c09a5), + WTC(0x8577eacf), WTC(0x85b29402), WTC(0x85ec17bf), WTC(0x86246b50), + WTC(0x865ba7d7), WTC(0x8691c4c0), WTC(0x86c6d72a), WTC(0x86fae06c), + WTC(0x872dfcd1), WTC(0x87602c6a), WTC(0x87918a27), WTC(0x87c22ef8), + WTC(0x882f7c20), WTC(0x88dc38ab), WTC(0x89a52f47), WTC(0x8a737635), + WTC(0x8b43d08d), WTC(0x8c19be9f), WTC(0x8cf89ce7), WTC(0x8de337e9), + WTC(0x8edb3e02), WTC(0x8fe1e815), WTC(0x90f7e107), WTC(0x921d8b95), + WTC(0x9353008c), WTC(0x94982fd7), WTC(0x95ecdc6d), WTC(0x9750b87f), + WTC(0x98c36ad6), WTC(0x9a447674), WTC(0x9bd34e9c), WTC(0x9d6f76fa), + WTC(0x9f18780d), WTC(0xa0cdc487), WTC(0xa28eff8e), WTC(0xa45bbe4b), + WTC(0xa633baaf), WTC(0xa816bff0), WTC(0xaa04a90d), WTC(0xabfd7205), + WTC(0xae01356b), WTC(0xb0101477), WTC(0xb22a5244), WTC(0xb4500b02), + WTC(0x499946f3), WTC(0x475da5af), WTC(0x45173dce), WTC(0x42c610ad), + WTC(0x406a44b0), WTC(0x3e037ce8), WTC(0x3b92b806), WTC(0x39195cd0), + WTC(0x36962f17), WTC(0x340a1b28), WTC(0x3177cde6), WTC(0x2ee1f20d), + WTC(0x2c49b0d6), WTC(0x29ad3d74), WTC(0x270e9ec1), WTC(0x2474132f), + WTC(0x21e14a01), WTC(0x1f57704e), WTC(0x1cd758ce), WTC(0x1a610d48), + WTC(0x17f5db88), WTC(0x1598a188), WTC(0x134f7a40), WTC(0x111f1ca0), + WTC(0x0f053b83), WTC(0x0cf871db), WTC(0x0af19e60), WTC(0x08eaa56d), + WTC(0x06e3c473), WTC(0x04d25cc9), WTC(0x02b59b4d), WTC(0x00e5bc4c), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xffcebf14), WTC(0xff6cc249), WTC(0xff0b8bda), WTC(0xfeac3e5f), + WTC(0xfe4f4638), WTC(0xfdf5052f), WTC(0xfd9e8cf4), WTC(0xfd4e34ea), + WTC(0xfd023142), WTC(0xfcb8f6f7), WTC(0xfc74e090), WTC(0xfc3b33e8), + WTC(0xfc0c1254), WTC(0xfbe1b2eb), WTC(0xfbb8ce73), WTC(0xfb97e511), + WTC(0xfb86273d), WTC(0xfb857a3e), WTC(0xfb918813), WTC(0xfba43692), + WTC(0xfbb96f24), WTC(0xfbd4dcc3), WTC(0xfc000cd5), WTC(0xfc458653), + WTC(0xfca6cd98), WTC(0xfd178c8e), WTC(0xfd872979), WTC(0xfdfa721e), + WTC(0xfe88c77c), WTC(0xff3c8b5c), WTC(0x00059ebc), WTC(0x00d91db0), + WTC(0x01bec555), WTC(0x02bdfb80), WTC(0x03d4c846), WTC(0x0501ad53), + WTC(0x064719b2), WTC(0x07a34a2b), WTC(0x0918814b), WTC(0x0aaaaa6b), + WTC(0x0c5728b9), WTC(0x0e1c1a0f), WTC(0x0ff9ccd1), WTC(0x11f21ffb), + WTC(0x1405d073), WTC(0x1635776b), WTC(0x1880f4e5), WTC(0x1ae8bdcb), + WTC(0x1d6cede3), WTC(0x200e1d93), WTC(0x22cc56fd), WTC(0x25a80858), + WTC(0x28a11bdd), WTC(0x2bb7e363), WTC(0x2eec2f0f), WTC(0x323e298d), + WTC(0x35ad7f0b), WTC(0x393a1989), WTC(0x3ce34a65), WTC(0x40a8683d), + WTC(0x44881c94), WTC(0x48813cb3), WTC(0x4c94523d), WTC(0x50c8eff0), + WTC(0x00000000), WTC(0x00000000), WTC(0x0053a1ea), WTC(0x00f67066), + WTC(0x01e3f61b), WTC(0x0317bdaf), WTC(0x048d51ca), WTC(0x06403d11), + WTC(0x082c0a34), WTC(0x0a4c43d2), WTC(0x0c9c748e), WTC(0x0f182718), + WTC(0x11bae616), WTC(0x14803c1b), WTC(0x1763b3e6), WTC(0x1a60d832), + WTC(0x1d73336b), WTC(0x20965068), WTC(0x23c5b9d6), WTC(0x26fcfa1a), + WTC(0x2a379c30), WTC(0x2d712a75), WTC(0x30a52fba), WTC(0x33cf36a9), + WTC(0x36eaca15), WTC(0x39f3743b), WTC(0x3ce4bfc2), WTC(0x3fba37b8), + WTC(0x426f6671), WTC(0x44ffd6e8), WTC(0x47671326), WTC(0x49a0b2d0), + WTC(0x4ba81be1), WTC(0x4d78fd1e), WTC(0x4f0ed503), WTC(0x50652e28), + WTC(0x51779351), WTC(0x52418fbe), WTC(0x52bead75), WTC(0x52ea76cc), + WTC(0x52c07793), WTC(0x523c3918), WTC(0x5159470e), WTC(0x50132b36), + WTC(0x4e657128), WTC(0x4c4ba31d), WTC(0x49c14b60), WTC(0x46c1e9e4), + WTC(0x4374e179), WTC(0x408377b1), WTC(0x3e0fa0aa), WTC(0x3c05d584), + WTC(0x3a4d9888), WTC(0x38cdd8fa), WTC(0x376b75c4), WTC(0x360c51a7), + WTC(0x34b12fdc), WTC(0x33550d9f), WTC(0x31f1955c), WTC(0x307ffcb2), + WTC(0x2f03c44d), WTC(0x2d7a6b86), WTC(0x2be6d3d4), WTC(0x2a48d219), +}; + +const FIXP_WTB ELDAnalysis120[360] = { + WTC(0xfaa1a40a), WTC(0xfa3f173d), WTC(0xf9d7760c), WTC(0xf96bcc12), + WTC(0xf8fbe82c), WTC(0xf887bb26), WTC(0xf80f131a), WTC(0xf7930d03), + WTC(0xf714aeaf), WTC(0xf693f5a1), WTC(0xf613385b), WTC(0xf596ef0e), + WTC(0xf522dcc4), WTC(0xf4bab1f6), WTC(0xf461700c), WTC(0xf412e1fe), + WTC(0xf3b769b1), WTC(0xf349eaca), WTC(0xf2cb9164), WTC(0xf23d6d7b), + WTC(0xf1a0ab28), WTC(0xf0f5c20f), WTC(0xf03aadd9), WTC(0xef6e8c66), + WTC(0xee984910), WTC(0xedbbcbf8), WTC(0xecd1435b), WTC(0xebdc1b77), + WTC(0xeae31338), WTC(0xe9dbea9a), WTC(0xe8c005ea), WTC(0xe79e7068), + WTC(0xe6856dce), WTC(0xe5657c79), WTC(0xe42928e9), WTC(0xe2e0756e), + WTC(0xe1a83cf5), WTC(0xe0801fab), WTC(0xdf52bfeb), WTC(0xde15d1b1), + WTC(0xdcce71ba), WTC(0xdb8931bf), WTC(0xda4fbbe8), WTC(0xd9220a98), + WTC(0xd7f9af0c), WTC(0xd6d0e1df), WTC(0xd5a41f15), WTC(0xd4790330), + WTC(0xd35f84b8), WTC(0xd255e881), WTC(0xd14daf00), WTC(0xd04638e2), + WTC(0xcf47dff7), WTC(0xce5b8850), WTC(0xcd77b1d6), WTC(0xcc960ec0), + WTC(0xcbc0a6a4), WTC(0xcaf6d4f7), WTC(0xca34fa7d), WTC(0xc97c26c0), + WTC(0xc8c6868a), WTC(0xc811f873), WTC(0xc7599db8), WTC(0xc69f9780), + WTC(0xc5e24043), WTC(0xc5226384), WTC(0xc468f547), WTC(0xc3b20be9), + WTC(0xc2f826f0), WTC(0xc242ea02), WTC(0xc19844ae), WTC(0xc0f80714), + WTC(0xc05a6da1), WTC(0xbfbfe6d3), WTC(0xbf31b5b4), WTC(0xbeb24843), + WTC(0xbe3f4cb4), WTC(0xbdd63599), WTC(0xbd74c6b2), WTC(0xbd1b7128), + WTC(0xbccd4b41), WTC(0xbc8dc08e), WTC(0xbc5ca2bd), WTC(0xbc3509f1), + WTC(0xbc11f904), WTC(0xbbf37848), WTC(0xbbddfb6b), WTC(0xbbd214ea), + WTC(0xbbcb3a11), WTC(0xbbcce581), WTC(0xbbdfa6ba), WTC(0xbbfd2fa5), + WTC(0xbc1ad516), WTC(0xbc390c16), WTC(0xbc57b323), WTC(0xbc76dd1f), + WTC(0xbc969172), WTC(0xbcb6d611), WTC(0xbcd7ac8e), WTC(0xbcf91af9), + WTC(0xbd1b20bd), WTC(0xbd3dc1f5), WTC(0xbd60f678), WTC(0xbd84bec7), + WTC(0xbda909c0), WTC(0xbdcdd76e), WTC(0xbdf3161c), WTC(0xbe18c1e5), + WTC(0xbe3ec6c5), WTC(0xbe651f19), WTC(0xbe8bb78b), WTC(0xbeb288e1), + WTC(0xbed9848b), WTC(0xbf00a16f), WTC(0xbf27d681), WTC(0xbf4f1958), + WTC(0xbf76680e), WTC(0xbf9db85c), WTC(0xbfc50e09), WTC(0xbfec5bdf), + WTC(0x80273bdb), WTC(0x807577de), WTC(0x80c3630d), WTC(0x8110e4cb), + WTC(0x815e05da), WTC(0x81aab20f), WTC(0x81f6e68e), WTC(0x824290d0), + WTC(0x828da04c), WTC(0x82d8061f), WTC(0x8321a740), WTC(0x836a77f9), + WTC(0x83b2574f), WTC(0x83f93cc1), WTC(0x843f04a6), WTC(0x8483acd1), + WTC(0x84c71639), WTC(0x850944da), WTC(0x854a1d3a), WTC(0x8589a437), + WTC(0x85c7ccf9), WTC(0x8604a42f), WTC(0x86402cfb), WTC(0x867a740d), + WTC(0x86b37ff2), WTC(0x86eb5f6f), WTC(0x87222109), WTC(0x8757eb5f), + WTC(0x878c8341), WTC(0x87c0be51), WTC(0x88345fca), WTC(0x88ef97fb), + WTC(0x89c778c5), WTC(0x8aa3cc20), WTC(0x8b833d56), WTC(0x8c6a42a9), + WTC(0x8d5cb787), WTC(0x8e5d7787), WTC(0x8f6e3c5b), WTC(0x90902640), + WTC(0x91c3ca28), WTC(0x9309622d), WTC(0x9460e7d0), WTC(0x95ca1ad2), + WTC(0x97449dff), WTC(0x98d00612), WTC(0x9a6bbc19), WTC(0x9c17164d), + WTC(0x9dd180fc), WTC(0x9f9a6304), WTC(0xa1711f56), WTC(0xa355425e), + WTC(0xa5465846), WTC(0xa744190f), WTC(0xa94e4ca9), WTC(0xab64dcf0), + WTC(0xad87e068), WTC(0xafb77bfa), WTC(0xb1f3fb2b), WTC(0xb43d885c), + WTC(0x49866451), WTC(0x4723e56b), WTC(0x44b51e8d), WTC(0x423a2180), + WTC(0x3fb2fe0f), WTC(0x3d1f78f2), WTC(0x3a8153b7), WTC(0x37d906ff), + WTC(0x35259e7e), WTC(0x3269ba18), WTC(0x2fa8c1ea), WTC(0x2ce4fbab), + WTC(0x2a1cebd5), WTC(0x27519ac1), WTC(0x248a2de9), WTC(0x21cb7a79), + WTC(0x1f16fc13), WTC(0x1c6d9a50), WTC(0x19cf83c1), WTC(0x173e9943), + WTC(0x14bf6a71), WTC(0x12598f74), WTC(0x100fe27f), WTC(0x0ddab46a), + WTC(0x0bafab9d), WTC(0x09864fc7), WTC(0x075d3ac8), WTC(0x052c0fc2), + WTC(0x02ea842b), WTC(0x00f21d19), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xffcb7b4d), WTC(0xff62fb20), WTC(0xfefb82e2), WTC(0xfe965482), + WTC(0xfe33e4bf), WTC(0xfdd4b9b5), WTC(0xfd7b04ec), WTC(0xfd27cfe4), + WTC(0xfcd84cfd), WTC(0xfc8ce1d4), WTC(0xfc4b45e1), WTC(0xfc1666da), + WTC(0xfbe8af26), WTC(0xfbbcad9e), WTC(0xfb98c6ad), WTC(0xfb85dd87), + WTC(0xfb86355b), WTC(0xfb94589b), WTC(0xfba8ed8a), WTC(0xfbc0a735), + WTC(0xfbe23f8d), WTC(0xfc1a92c4), WTC(0xfc73315f), WTC(0xfce611a1), + WTC(0xfd5e94d9), WTC(0xfdd61cab), WTC(0xfe6427fd), WTC(0xff1c92da), + WTC(0xfff10542), WTC(0x00d1d58a), WTC(0x01c6daab), WTC(0x02d8dbc3), + WTC(0x040557a6), WTC(0x054b6f91), WTC(0x06ad2b2b), WTC(0x0828f4c5), + WTC(0x09c348d1), WTC(0x0b7dcb56), WTC(0x0d54d98e), WTC(0x0f47a599), + WTC(0x1157fa1b), WTC(0x138743ae), WTC(0x15d6423f), WTC(0x1844f0ae), + WTC(0x1ad3c273), WTC(0x1d82e65c), WTC(0x205306e1), WTC(0x23443d5c), + WTC(0x2656fae8), WTC(0x298b3a5a), WTC(0x2ce13a7d), WTC(0x3058e0e3), + WTC(0x33f22950), WTC(0x37acd0b2), WTC(0x3b885e6b), WTC(0x3f840412), + WTC(0x439e65ee), WTC(0x47d6014e), WTC(0x4c2aa857), WTC(0x50a46876), + WTC(0xfffe9b02), WTC(0x0004ac61), WTC(0x0069639d), WTC(0x0127578b), + WTC(0x02391efe), WTC(0x039950cc), WTC(0x054283bf), WTC(0x072f4eba), + WTC(0x095a488c), WTC(0x0bbe0802), WTC(0x0e5523f9), WTC(0x111a332e), + WTC(0x1407cca2), WTC(0x171886f5), WTC(0x1a46f927), WTC(0x1d8db9e1), + WTC(0x20e7600d), WTC(0x244e82a3), WTC(0x27bdb846), WTC(0x2b2f97a8), + WTC(0x2e9eb7ea), WTC(0x3205afd1), WTC(0x355f161c), WTC(0x38a581d7), + WTC(0x3bd3894a), WTC(0x3ee3c398), WTC(0x41d0c7ae), WTC(0x44952cb8), + WTC(0x472b8856), WTC(0x498e7eee), WTC(0x4bb88245), WTC(0x4da44d9f), + WTC(0x4f4c6b7d), WTC(0x50ab7298), WTC(0x51bbfa11), WTC(0x527898fb), + WTC(0x52dbe5f2), WTC(0x52e07778), WTC(0x5280e51f), WTC(0x51b7c4f1), + WTC(0x507fadc7), WTC(0x4ed336dd), WTC(0x4cacf749), WTC(0x4a078534), + WTC(0x46dd6dcc), WTC(0x43599e22), WTC(0x403f48da), WTC(0x3db1ed89), + WTC(0x3b98bd24), WTC(0x39d5b003), WTC(0x384a3292), WTC(0x36d328ff), + WTC(0x355e63a6), WTC(0x33ec69d8), WTC(0x32755ebd), WTC(0x30f01fce), + WTC(0x2f5d9646), WTC(0x2dbcc615), WTC(0x2c0fa145), WTC(0x2a56ce53), +}; diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_rom.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_rom.h new file mode 100644 index 0000000000000..fd50cab3ee8d8 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacEnc_rom.h @@ -0,0 +1,217 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser, M. Gayer + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Memory layout + \author Markus Lohwasser +*/ + +#ifndef AACENC_ROM_H +#define AACENC_ROM_H + +#include "common_fix.h" + +#include "psy_const.h" +#include "psy_configuration.h" +#include "FDK_tools_rom.h" +#include "FDK_lpc.h" + +/* + Huffman Tables +*/ +extern const ULONG FDKaacEnc_huff_ltab1_2[3][3][3][3]; +extern const ULONG FDKaacEnc_huff_ltab3_4[3][3][3][3]; +extern const ULONG FDKaacEnc_huff_ltab5_6[9][9]; +extern const ULONG FDKaacEnc_huff_ltab7_8[8][8]; +extern const ULONG FDKaacEnc_huff_ltab9_10[13][13]; +extern const UCHAR FDKaacEnc_huff_ltab11[17][17]; +extern const UCHAR FDKaacEnc_huff_ltabscf[121]; +extern const USHORT FDKaacEnc_huff_ctab1[3][3][3][3]; +extern const USHORT FDKaacEnc_huff_ctab2[3][3][3][3]; +extern const USHORT FDKaacEnc_huff_ctab3[3][3][3][3]; +extern const USHORT FDKaacEnc_huff_ctab4[3][3][3][3]; +extern const USHORT FDKaacEnc_huff_ctab5[9][9]; +extern const USHORT FDKaacEnc_huff_ctab6[9][9]; +extern const USHORT FDKaacEnc_huff_ctab7[8][8]; +extern const USHORT FDKaacEnc_huff_ctab8[8][8]; +extern const USHORT FDKaacEnc_huff_ctab9[13][13]; +extern const USHORT FDKaacEnc_huff_ctab10[13][13]; +extern const USHORT FDKaacEnc_huff_ctab11[21][17]; +extern const ULONG FDKaacEnc_huff_ctabscf[121]; + +/* + quantizer +*/ +#define MANT_DIGITS 9 +#define MANT_SIZE (1 << MANT_DIGITS) + +#if defined(ARCH_PREFER_MULT_32x16) +#define FIXP_QTD FIXP_SGL +#define QTC FX_DBL2FXCONST_SGL +#else +#define FIXP_QTD FIXP_DBL +#define QTC +#endif + +extern const FIXP_QTD FDKaacEnc_mTab_3_4[MANT_SIZE]; +extern const FIXP_QTD FDKaacEnc_quantTableQ[4]; +extern const FIXP_QTD FDKaacEnc_quantTableE[4]; + +extern const FIXP_DBL FDKaacEnc_mTab_4_3Elc[512]; +extern const FIXP_DBL FDKaacEnc_specExpMantTableCombElc[4][14]; +extern const UCHAR FDKaacEnc_specExpTableComb[4][14]; + +/* + table to count used number of bits +*/ +extern const SHORT FDKaacEnc_sideInfoTabLong[]; +extern const SHORT FDKaacEnc_sideInfoTabShort[]; + +/* + Psy Configuration constants +*/ +extern const SFB_PARAM_LONG p_FDKaacEnc_8000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_8000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_11025_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_11025_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_12000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_12000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_16000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_16000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_22050_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_22050_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_24000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_24000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_32000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_32000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_44100_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_44100_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_48000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_48000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_64000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_64000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_88200_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_88200_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_96000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_96000_short_128; + +/* + TNS filter coefficients +*/ +extern const FIXP_LPC FDKaacEnc_tnsEncCoeff3[8]; +extern const FIXP_LPC FDKaacEnc_tnsCoeff3Borders[8]; +extern const FIXP_LPC FDKaacEnc_tnsEncCoeff4[16]; +extern const FIXP_LPC FDKaacEnc_tnsCoeff4Borders[16]; + +#define WTC0 WTC +#define WTC1 WTC +#define WTC2 WTC + +extern const FIXP_WTB ELDAnalysis512[1536]; +extern const FIXP_WTB ELDAnalysis480[1440]; +extern const FIXP_WTB ELDAnalysis256[768]; +extern const FIXP_WTB ELDAnalysis240[720]; +extern const FIXP_WTB ELDAnalysis128[384]; +extern const FIXP_WTB ELDAnalysis120[360]; + +#endif /* #ifndef AACENC_ROM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc.cpp new file mode 100644 index 0000000000000..1af8a2e1800e4 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc.cpp @@ -0,0 +1,1066 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Schug / A. Groeschel + + Description: fast aac coder functions + +*******************************************************************************/ + +#include "aacenc.h" + +#include "bitenc.h" +#include "interface.h" +#include "psy_configuration.h" +#include "psy_main.h" +#include "qc_main.h" +#include "bandwidth.h" +#include "channel_map.h" +#include "tns_func.h" +#include "aacEnc_ram.h" + +#include "genericStds.h" + +#define BITRES_MIN \ + 300 /* default threshold for using reduced/disabled bitres mode */ +#define BITRES_MAX_LD 4000 +#define BITRES_MIN_LD 500 +#define BITRATE_MAX_LD 70000 /* Max assumed bitrate for bitres calculation */ +#define BITRATE_MIN_LD 12000 /* Min assumed bitrate for bitres calculation */ + +INT FDKaacEnc_CalcBitsPerFrame(const INT bitRate, const INT frameLength, + const INT samplingRate) { + int shift = 0; + while ((frameLength & ~((1 << (shift + 1)) - 1)) == frameLength && + (samplingRate & ~((1 << (shift + 1)) - 1)) == samplingRate) { + shift++; + } + + return (bitRate * (frameLength >> shift)) / (samplingRate >> shift); +} + +INT FDKaacEnc_CalcBitrate(const INT bitsPerFrame, const INT frameLength, + const INT samplingRate) { + int shift = 0; + while ((frameLength & ~((1 << (shift + 1)) - 1)) == frameLength && + (samplingRate & ~((1 << (shift + 1)) - 1)) == samplingRate) { + shift++; + } + + return (bitsPerFrame * (samplingRate >> shift)) / (frameLength >> shift); +} + +static AAC_ENCODER_ERROR FDKaacEnc_InitCheckAncillary( + INT bitRate, INT framelength, INT ancillaryRate, INT *ancillaryBitsPerFrame, + INT sampleRate); + +INT FDKaacEnc_LimitBitrate(HANDLE_TRANSPORTENC hTpEnc, AUDIO_OBJECT_TYPE aot, + INT coreSamplingRate, INT frameLength, INT nChannels, + INT nChannelsEff, INT bitRate, INT averageBits, + INT *pAverageBitsPerFrame, + AACENC_BITRATE_MODE bitrateMode, INT nSubFrames) { + INT transportBits, prevBitRate, averageBitsPerFrame, minBitrate = 0, iter = 0; + INT minBitsPerFrame = 40 * nChannels; + if (isLowDelay(aot)) { + minBitrate = 8000 * nChannelsEff; + } + + do { + prevBitRate = bitRate; + averageBitsPerFrame = + FDKaacEnc_CalcBitsPerFrame(bitRate, frameLength, coreSamplingRate) / + nSubFrames; + + if (pAverageBitsPerFrame != NULL) { + *pAverageBitsPerFrame = averageBitsPerFrame; + } + + if (hTpEnc != NULL) { + transportBits = transportEnc_GetStaticBits(hTpEnc, averageBitsPerFrame); + } else { + /* Assume some worst case */ + transportBits = 208; + } + + bitRate = fMax(bitRate, + fMax(minBitrate, + FDKaacEnc_CalcBitrate((minBitsPerFrame + transportBits), + frameLength, coreSamplingRate))); + FDK_ASSERT(bitRate >= 0); + + bitRate = fMin(bitRate, FDKaacEnc_CalcBitrate( + (nChannelsEff * MIN_BUFSIZE_PER_EFF_CHAN), + frameLength, coreSamplingRate)); + FDK_ASSERT(bitRate >= 0); + + } while (prevBitRate != bitRate && iter++ < 3); + + return bitRate; +} + +typedef struct { + AACENC_BITRATE_MODE bitrateMode; + int chanBitrate[2]; /* mono/stereo settings */ +} CONFIG_TAB_ENTRY_VBR; + +static const CONFIG_TAB_ENTRY_VBR configTabVBR[] = { + {AACENC_BR_MODE_CBR, {0, 0}}, + {AACENC_BR_MODE_VBR_1, {32000, 20000}}, + {AACENC_BR_MODE_VBR_2, {40000, 32000}}, + {AACENC_BR_MODE_VBR_3, {56000, 48000}}, + {AACENC_BR_MODE_VBR_4, {72000, 64000}}, + {AACENC_BR_MODE_VBR_5, {112000, 96000}}}; + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_GetVBRBitrate + description: Get VBR bitrate from vbr quality + input params: int vbrQuality (VBR0, VBR1, VBR2) + channelMode + returns: vbr bitrate + + ------------------------------------------------------------------------------*/ +INT FDKaacEnc_GetVBRBitrate(AACENC_BITRATE_MODE bitrateMode, + CHANNEL_MODE channelMode) { + INT bitrate = 0; + INT monoStereoMode = 0; /* default mono */ + + if (FDKaacEnc_GetMonoStereoMode(channelMode) == EL_MODE_STEREO) { + monoStereoMode = 1; + } + + switch (bitrateMode) { + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + bitrate = configTabVBR[bitrateMode].chanBitrate[monoStereoMode]; + break; + case AACENC_BR_MODE_INVALID: + case AACENC_BR_MODE_CBR: + case AACENC_BR_MODE_SFR: + case AACENC_BR_MODE_FF: + default: + bitrate = 0; + break; + } + + /* convert channel bitrate to overall bitrate*/ + bitrate *= FDKaacEnc_GetChannelModeConfiguration(channelMode)->nChannelsEff; + + return bitrate; +} + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_AdjustVBRBitrateMode + description: Adjust bitrate mode to given bitrate parameter + input params: int vbrQuality (VBR0, VBR1, VBR2) + bitrate + channelMode + returns: vbr bitrate mode + + ------------------------------------------------------------------------------*/ +AACENC_BITRATE_MODE FDKaacEnc_AdjustVBRBitrateMode( + AACENC_BITRATE_MODE bitrateMode, INT bitrate, CHANNEL_MODE channelMode) { + AACENC_BITRATE_MODE newBitrateMode = bitrateMode; + + if (bitrate != -1) { + const INT monoStereoMode = + (FDKaacEnc_GetMonoStereoMode(channelMode) == EL_MODE_STEREO) ? 1 : 0; + const INT nChannelsEff = + FDKaacEnc_GetChannelModeConfiguration(channelMode)->nChannelsEff; + newBitrateMode = AACENC_BR_MODE_INVALID; + + for (int idx = (int)(sizeof(configTabVBR) / sizeof(*configTabVBR)) - 1; + idx >= 0; idx--) { + if (bitrate >= + configTabVBR[idx].chanBitrate[monoStereoMode] * nChannelsEff) { + if (configTabVBR[idx].chanBitrate[monoStereoMode] * nChannelsEff < + FDKaacEnc_GetVBRBitrate(bitrateMode, channelMode)) { + newBitrateMode = configTabVBR[idx].bitrateMode; + } else { + newBitrateMode = bitrateMode; + } + break; + } + } + } + + return AACENC_BR_MODE_IS_VBR(newBitrateMode) ? newBitrateMode + : AACENC_BR_MODE_INVALID; +} + +/** + * \brief Convert encoder bitreservoir value for transport library. + * + * \param hAacEnc Encoder handle + * + * \return Corrected bitreservoir level used in transport library. + */ +static INT FDKaacEnc_EncBitresToTpBitres(const HANDLE_AAC_ENC hAacEnc) { + INT transportBitreservoir = 0; + + switch (hAacEnc->bitrateMode) { + case AACENC_BR_MODE_CBR: + transportBitreservoir = + hAacEnc->qcKernel->bitResTot; /* encoder bitreservoir level */ + break; + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + transportBitreservoir = FDK_INT_MAX; /* signal variable bitrate */ + break; + case AACENC_BR_MODE_SFR: + transportBitreservoir = 0; /* super framing and fixed framing */ + break; /* without bitreservoir signaling */ + default: + case AACENC_BR_MODE_INVALID: + transportBitreservoir = 0; /* invalid configuration*/ + } + + if (hAacEnc->config->audioMuxVersion == 2) { + transportBitreservoir = + MIN_BUFSIZE_PER_EFF_CHAN * hAacEnc->channelMapping.nChannelsEff; + } + + return transportBitreservoir; +} + +INT FDKaacEnc_GetBitReservoirState(const HANDLE_AAC_ENC hAacEncoder) { + return FDKaacEnc_EncBitresToTpBitres(hAacEncoder); +} + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_AacInitDefaultConfig + description: gives reasonable default configuration + returns: --- + + ------------------------------------------------------------------------------*/ +void FDKaacEnc_AacInitDefaultConfig(AACENC_CONFIG *config) { + /* make the preinitialization of the structs flexible */ + FDKmemclear(config, sizeof(AACENC_CONFIG)); + + /* default ancillary */ + config->anc_Rate = 0; /* no ancillary data */ + config->ancDataBitRate = 0; /* no additional consumed bitrate */ + + /* default configurations */ + config->bitRate = -1; /* bitrate must be set*/ + config->averageBits = + -1; /* instead of bitrate/s we can configure bits/superframe */ + config->bitrateMode = + AACENC_BR_MODE_CBR; /* set bitrate mode to constant bitrate */ + config->bandWidth = 0; /* get bandwidth from table */ + config->useTns = TNS_ENABLE_MASK; /* tns enabled completly */ + config->usePns = + 1; /* depending on channelBitrate this might be set to 0 later */ + config->useIS = 1; /* Intensity Stereo Configuration */ + config->useMS = 1; /* MS Stereo tool */ + config->framelength = -1; /* Framesize not configured */ + config->syntaxFlags = 0; /* default syntax with no specialities */ + config->epConfig = -1; /* no ER syntax -> no additional error protection */ + config->nSubFrames = 1; /* default, no sub frames */ + config->channelOrder = CH_ORDER_MPEG; /* Use MPEG channel ordering. */ + config->channelMode = MODE_UNKNOWN; + config->minBitsPerFrame = -1; /* minum number of bits in each AU */ + config->maxBitsPerFrame = -1; /* minum number of bits in each AU */ + config->audioMuxVersion = -1; /* audio mux version not configured */ + config->downscaleFactor = + 1; /* downscale factor for ELD reduced delay mode, 1 is normal ELD */ +} + +/*--------------------------------------------------------------------------- + + functionname: FDKaacEnc_Open + description: allocate and initialize a new encoder instance + returns: error code + + ---------------------------------------------------------------------------*/ +AAC_ENCODER_ERROR FDKaacEnc_Open(HANDLE_AAC_ENC *phAacEnc, const INT nElements, + const INT nChannels, const INT nSubFrames) { + AAC_ENCODER_ERROR ErrorStatus; + AAC_ENC *hAacEnc = NULL; + UCHAR *dynamicRAM = NULL; + + if (phAacEnc == NULL) { + return AAC_ENC_INVALID_HANDLE; + } + + /* allocate encoder structure */ + hAacEnc = GetRam_aacEnc_AacEncoder(); + if (hAacEnc == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + FDKmemclear(hAacEnc, sizeof(AAC_ENC)); + + if (NULL == (hAacEnc->dynamic_RAM = GetAACdynamic_RAM())) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + dynamicRAM = (UCHAR *)hAacEnc->dynamic_RAM; + + /* allocate the Psy aud Psy Out structure */ + ErrorStatus = + FDKaacEnc_PsyNew(&hAacEnc->psyKernel, nElements, nChannels, dynamicRAM); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + ErrorStatus = FDKaacEnc_PsyOutNew(hAacEnc->psyOut, nElements, nChannels, + nSubFrames, dynamicRAM); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + /* allocate the Q&C Out structure */ + ErrorStatus = FDKaacEnc_QCOutNew(hAacEnc->qcOut, nElements, nChannels, + nSubFrames, dynamicRAM); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + /* allocate the Q&C kernel */ + ErrorStatus = FDKaacEnc_QCNew(&hAacEnc->qcKernel, nElements, dynamicRAM); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + hAacEnc->maxChannels = nChannels; + hAacEnc->maxElements = nElements; + hAacEnc->maxFrames = nSubFrames; + +bail: + *phAacEnc = hAacEnc; + return ErrorStatus; +} + +AAC_ENCODER_ERROR FDKaacEnc_Initialize( + HANDLE_AAC_ENC hAacEnc, + AACENC_CONFIG *config, /* pre-initialized config struct */ + HANDLE_TRANSPORTENC hTpEnc, ULONG initFlags) { + AAC_ENCODER_ERROR ErrorStatus; + INT psyBitrate, tnsMask; // INT profile = 1; + CHANNEL_MAPPING *cm = NULL; + + INT mbfac_e, qbw; + FIXP_DBL mbfac, bw_ratio; + QC_INIT qcInit; + INT averageBitsPerFrame = 0; + const CHANNEL_MODE prevChannelMode = hAacEnc->encoderMode; + + if (config == NULL) return AAC_ENC_INVALID_HANDLE; + + /******************* sanity checks *******************/ + + /* check config structure */ + if (config->nChannels < 1 || config->nChannels > (8)) { + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + + /* check sample rate */ + switch (config->sampleRate) { + case 8000: + case 11025: + case 12000: + case 16000: + case 22050: + case 24000: + case 32000: + case 44100: + case 48000: + case 64000: + case 88200: + case 96000: + break; + default: + return AAC_ENC_UNSUPPORTED_SAMPLINGRATE; + } + + /* bitrate has to be set */ + if (config->bitRate == -1) { + return AAC_ENC_UNSUPPORTED_BITRATE; + } + + /* check bit rate */ + + if (FDKaacEnc_LimitBitrate( + hTpEnc, config->audioObjectType, config->sampleRate, + config->framelength, config->nChannels, + FDKaacEnc_GetChannelModeConfiguration(config->channelMode) + ->nChannelsEff, + config->bitRate, config->averageBits, &averageBitsPerFrame, + config->bitrateMode, config->nSubFrames) != config->bitRate && + !(AACENC_BR_MODE_IS_VBR(config->bitrateMode))) { + return AAC_ENC_UNSUPPORTED_BITRATE; + } + + if (config->syntaxFlags & AC_ER_VCB11) { + return AAC_ENC_UNSUPPORTED_ER_FORMAT; + } + if (config->syntaxFlags & AC_ER_HCR) { + return AAC_ENC_UNSUPPORTED_ER_FORMAT; + } + + /* check frame length */ + switch (config->framelength) { + case 1024: + if (isLowDelay(config->audioObjectType)) { + return AAC_ENC_INVALID_FRAME_LENGTH; + } + break; + case 128: + case 256: + case 512: + case 120: + case 240: + case 480: + if (!isLowDelay(config->audioObjectType)) { + return AAC_ENC_INVALID_FRAME_LENGTH; + } + break; + default: + return AAC_ENC_INVALID_FRAME_LENGTH; + } + + if (config->anc_Rate != 0) { + ErrorStatus = FDKaacEnc_InitCheckAncillary( + config->bitRate, config->framelength, config->anc_Rate, + &hAacEnc->ancillaryBitsPerFrame, config->sampleRate); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + /* update estimated consumed bitrate */ + config->ancDataBitRate += + FDKaacEnc_CalcBitrate(hAacEnc->ancillaryBitsPerFrame, + config->framelength, config->sampleRate); + } + + /* maximal allowed DSE bytes in frame */ + config->maxAncBytesPerAU = + fMin((256), fMax(0, FDKaacEnc_CalcBitsPerFrame( + (config->bitRate - (config->nChannels * 8000)), + config->framelength, config->sampleRate) >> + 3)); + + /* bind config to hAacEnc->config */ + hAacEnc->config = config; + + /* set hAacEnc->bitrateMode */ + hAacEnc->bitrateMode = config->bitrateMode; + + hAacEnc->encoderMode = config->channelMode; + + ErrorStatus = FDKaacEnc_InitChannelMapping( + hAacEnc->encoderMode, config->channelOrder, &hAacEnc->channelMapping); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + cm = &hAacEnc->channelMapping; + + ErrorStatus = FDKaacEnc_DetermineBandWidth( + config->bandWidth, config->bitRate - config->ancDataBitRate, + hAacEnc->bitrateMode, config->sampleRate, config->framelength, cm, + hAacEnc->encoderMode, &hAacEnc->config->bandWidth); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + hAacEnc->bandwidth90dB = (INT)hAacEnc->config->bandWidth; + + tnsMask = config->useTns ? TNS_ENABLE_MASK : 0x0; + psyBitrate = config->bitRate - config->ancDataBitRate; + + if ((hAacEnc->encoderMode != prevChannelMode) || (initFlags != 0)) { + /* Reinitialize psych states in case of channel configuration change ore if + * full reset requested. */ + ErrorStatus = FDKaacEnc_psyInit(hAacEnc->psyKernel, hAacEnc->psyOut, + hAacEnc->maxFrames, hAacEnc->maxChannels, + config->audioObjectType, cm); + if (ErrorStatus != AAC_ENC_OK) goto bail; + } + + ErrorStatus = FDKaacEnc_psyMainInit( + hAacEnc->psyKernel, config->audioObjectType, cm, config->sampleRate, + config->framelength, psyBitrate, tnsMask, hAacEnc->bandwidth90dB, + config->usePns, config->useIS, config->useMS, config->syntaxFlags, + initFlags); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + ErrorStatus = FDKaacEnc_QCOutInit(hAacEnc->qcOut, hAacEnc->maxFrames, cm); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + qcInit.channelMapping = &hAacEnc->channelMapping; + qcInit.sceCpe = 0; + + if (AACENC_BR_MODE_IS_VBR(config->bitrateMode)) { + qcInit.averageBits = (averageBitsPerFrame + 7) & ~7; + qcInit.bitRes = MIN_BUFSIZE_PER_EFF_CHAN * cm->nChannelsEff; + qcInit.maxBits = MIN_BUFSIZE_PER_EFF_CHAN * cm->nChannelsEff; + qcInit.maxBits = (config->maxBitsPerFrame != -1) + ? fixMin(qcInit.maxBits, config->maxBitsPerFrame) + : qcInit.maxBits; + qcInit.maxBits = fixMax(qcInit.maxBits, (averageBitsPerFrame + 7) & ~7); + qcInit.minBits = + (config->minBitsPerFrame != -1) ? config->minBitsPerFrame : 0; + qcInit.minBits = fixMin(qcInit.minBits, averageBitsPerFrame & ~7); + } else { + INT bitreservoir = -1; /* default bitreservoir size*/ + if (isLowDelay(config->audioObjectType)) { + INT brPerChannel = config->bitRate / config->nChannels; + brPerChannel = fMin(BITRATE_MAX_LD, fMax(BITRATE_MIN_LD, brPerChannel)); + + /* bitreservoir = + * (maxBitRes-minBitRes)/(maxBitRate-minBitrate)*(bitRate-minBitrate)+minBitRes; + */ + FIXP_DBL slope = fDivNorm( + (brPerChannel - BITRATE_MIN_LD), + BITRATE_MAX_LD - BITRATE_MIN_LD); /* calc slope for interpolation */ + bitreservoir = fMultI(slope, (INT)(BITRES_MAX_LD - BITRES_MIN_LD)) + + BITRES_MIN_LD; /* interpolate */ + bitreservoir = bitreservoir & ~7; /* align to bytes */ + } + + int maxBitres; + qcInit.averageBits = (averageBitsPerFrame + 7) & ~7; + maxBitres = + (MIN_BUFSIZE_PER_EFF_CHAN * cm->nChannelsEff) - qcInit.averageBits; + qcInit.bitRes = + (bitreservoir != -1) ? fMin(bitreservoir, maxBitres) : maxBitres; + + qcInit.maxBits = fixMin(MIN_BUFSIZE_PER_EFF_CHAN * cm->nChannelsEff, + ((averageBitsPerFrame + 7) & ~7) + qcInit.bitRes); + qcInit.maxBits = (config->maxBitsPerFrame != -1) + ? fixMin(qcInit.maxBits, config->maxBitsPerFrame) + : qcInit.maxBits; + qcInit.maxBits = + fixMin(MIN_BUFSIZE_PER_EFF_CHAN * cm->nChannelsEff, + fixMax(qcInit.maxBits, (averageBitsPerFrame + 7 + 8) & ~7)); + + qcInit.minBits = fixMax( + 0, ((averageBitsPerFrame - 1) & ~7) - qcInit.bitRes - + transportEnc_GetStaticBits( + hTpEnc, ((averageBitsPerFrame + 7) & ~7) + qcInit.bitRes)); + qcInit.minBits = (config->minBitsPerFrame != -1) + ? fixMax(qcInit.minBits, config->minBitsPerFrame) + : qcInit.minBits; + qcInit.minBits = fixMin( + qcInit.minBits, (averageBitsPerFrame - + transportEnc_GetStaticBits(hTpEnc, qcInit.maxBits)) & + ~7); + } + + qcInit.sampleRate = config->sampleRate; + qcInit.isLowDelay = isLowDelay(config->audioObjectType) ? 1 : 0; + qcInit.nSubFrames = config->nSubFrames; + qcInit.padding.paddingRest = config->sampleRate; + + if (qcInit.maxBits - qcInit.averageBits >= + ((qcInit.isLowDelay) ? BITRES_MIN_LD : BITRES_MIN) * config->nChannels) { + qcInit.bitResMode = AACENC_BR_MODE_FULL; /* full bitreservoir */ + } else if (qcInit.maxBits > qcInit.averageBits) { + qcInit.bitResMode = AACENC_BR_MODE_REDUCED; /* reduced bitreservoir */ + } else { + qcInit.bitResMode = AACENC_BR_MODE_DISABLED; /* disabled bitreservoir */ + } + + /* Configure bitrate distribution strategy. */ + switch (config->channelMode) { + case MODE_1_2: + case MODE_1_2_1: + case MODE_1_2_2: + case MODE_1_2_2_1: + case MODE_6_1: + case MODE_1_2_2_2_1: + case MODE_7_1_BACK: + case MODE_7_1_TOP_FRONT: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + qcInit.bitDistributionMode = 0; /* over all elements bitrate estimation */ + break; + case MODE_1: + case MODE_2: + default: /* all non mpeg defined channel modes */ + qcInit.bitDistributionMode = 1; /* element-wise bit bitrate estimation */ + } /* config->channelMode */ + + /* Calc meanPe: qcInit.meanPe = 10.0f * FRAME_LEN_LONG * + * hAacEnc->bandwidth90dB/(config->sampleRate/2.0f); */ + bw_ratio = + fDivNorm((FIXP_DBL)(10 * config->framelength * hAacEnc->bandwidth90dB), + (FIXP_DBL)(config->sampleRate), &qbw); + qcInit.meanPe = + fMax((INT)scaleValue(bw_ratio, qbw + 1 - (DFRACT_BITS - 1)), 1); + + /* Calc maxBitFac, scale it to 24 bit accuracy */ + mbfac = fDivNorm(qcInit.maxBits, qcInit.averageBits / qcInit.nSubFrames, + &mbfac_e); + qcInit.maxBitFac = scaleValue(mbfac, -(DFRACT_BITS - 1 - 24 - mbfac_e)); + + switch (config->bitrateMode) { + case AACENC_BR_MODE_CBR: + qcInit.bitrateMode = QCDATA_BR_MODE_CBR; + break; + case AACENC_BR_MODE_VBR_1: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_1; + break; + case AACENC_BR_MODE_VBR_2: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_2; + break; + case AACENC_BR_MODE_VBR_3: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_3; + break; + case AACENC_BR_MODE_VBR_4: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_4; + break; + case AACENC_BR_MODE_VBR_5: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_5; + break; + case AACENC_BR_MODE_SFR: + qcInit.bitrateMode = QCDATA_BR_MODE_SFR; + break; + case AACENC_BR_MODE_FF: + qcInit.bitrateMode = QCDATA_BR_MODE_FF; + break; + default: + ErrorStatus = AAC_ENC_UNSUPPORTED_BITRATE_MODE; + goto bail; + } + + qcInit.invQuant = (config->useRequant) ? 2 : 0; + + /* maxIterations should be set to the maximum number of requantization + * iterations that are allowed before the crash recovery functionality is + * activated. This setting should be adjusted to the processing power + * available, i.e. to the processing power headroom in one frame that is still + * left after normal encoding without requantization. Please note that if + * activated this functionality is used most likely only in cases where the + * encoder is operating beyond recommended settings, i.e. the audio quality is + * suboptimal anyway. Activating the crash recovery does not further reduce + * audio quality significantly in these cases. */ + if (isLowDelay(config->audioObjectType)) { + qcInit.maxIterations = 2; + } else { + qcInit.maxIterations = 5; + } + + qcInit.bitrate = config->bitRate - config->ancDataBitRate; + + qcInit.staticBits = transportEnc_GetStaticBits( + hTpEnc, qcInit.averageBits / qcInit.nSubFrames); + + ErrorStatus = FDKaacEnc_QCInit(hAacEnc->qcKernel, &qcInit, initFlags); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + /* Map virtual aot's to intern aot used in bitstream writer. */ + switch (hAacEnc->config->audioObjectType) { + case AOT_MP2_AAC_LC: + hAacEnc->aot = AOT_AAC_LC; + break; + case AOT_MP2_SBR: + hAacEnc->aot = AOT_SBR; + break; + default: + hAacEnc->aot = hAacEnc->config->audioObjectType; + } + + /* common things */ + + return AAC_ENC_OK; + +bail: + + return ErrorStatus; +} + +/*--------------------------------------------------------------------------- + + functionname: FDKaacEnc_EncodeFrame + description: encodes one frame + returns: error code + + ---------------------------------------------------------------------------*/ +AAC_ENCODER_ERROR FDKaacEnc_EncodeFrame( + HANDLE_AAC_ENC hAacEnc, /* encoder handle */ + HANDLE_TRANSPORTENC hTpEnc, INT_PCM *RESTRICT inputBuffer, + const UINT inputBufferBufSize, INT *nOutBytes, + AACENC_EXT_PAYLOAD extPayload[MAX_TOTAL_EXT_PAYLOADS]) { + AAC_ENCODER_ERROR ErrorStatus; + int el, n, c = 0; + UCHAR extPayloadUsed[MAX_TOTAL_EXT_PAYLOADS]; + + CHANNEL_MAPPING *cm = &hAacEnc->channelMapping; + + PSY_OUT *psyOut = hAacEnc->psyOut[c]; + QC_OUT *qcOut = hAacEnc->qcOut[c]; + + FDKmemclear(extPayloadUsed, MAX_TOTAL_EXT_PAYLOADS * sizeof(UCHAR)); + + qcOut->elementExtBits = 0; /* sum up all extended bit of each element */ + qcOut->staticBits = 0; /* sum up side info bits of each element */ + qcOut->totalNoRedPe = 0; /* sum up PE */ + + /* advance psychoacoustics */ + for (el = 0; el < cm->nElements; el++) { + ELEMENT_INFO elInfo = cm->elInfo[el]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + int ch; + + /* update pointer!*/ + for (ch = 0; ch < elInfo.nChannelsInEl; ch++) { + PSY_OUT_CHANNEL *psyOutChan = + psyOut->psyOutElement[el]->psyOutChannel[ch]; + QC_OUT_CHANNEL *qcOutChan = qcOut->qcElement[el]->qcOutChannel[ch]; + + psyOutChan->mdctSpectrum = qcOutChan->mdctSpectrum; + psyOutChan->sfbSpreadEnergy = qcOutChan->sfbSpreadEnergy; + psyOutChan->sfbEnergy = qcOutChan->sfbEnergy; + psyOutChan->sfbEnergyLdData = qcOutChan->sfbEnergyLdData; + psyOutChan->sfbMinSnrLdData = qcOutChan->sfbMinSnrLdData; + psyOutChan->sfbThresholdLdData = qcOutChan->sfbThresholdLdData; + } + + ErrorStatus = FDKaacEnc_psyMain( + elInfo.nChannelsInEl, hAacEnc->psyKernel->psyElement[el], + hAacEnc->psyKernel->psyDynamic, hAacEnc->psyKernel->psyConf, + psyOut->psyOutElement[el], inputBuffer, inputBufferBufSize, + cm->elInfo[el].ChannelIndex, cm->nChannels); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + /* FormFactor, Pe and staticBitDemand calculation */ + ErrorStatus = FDKaacEnc_QCMainPrepare( + &elInfo, hAacEnc->qcKernel->hAdjThr->adjThrStateElem[el], + psyOut->psyOutElement[el], qcOut->qcElement[el], hAacEnc->aot, + hAacEnc->config->syntaxFlags, hAacEnc->config->epConfig); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + /*-------------------------------------------- */ + + qcOut->qcElement[el]->extBitsUsed = 0; + qcOut->qcElement[el]->nExtensions = 0; + /* reset extension payload */ + FDKmemclear(&qcOut->qcElement[el]->extension, + (1) * sizeof(QC_OUT_EXTENSION)); + + for (n = 0; n < MAX_TOTAL_EXT_PAYLOADS; n++) { + if (!extPayloadUsed[n] && (extPayload[n].associatedChElement == el) && + (extPayload[n].dataSize > 0) && (extPayload[n].pData != NULL)) { + int idx = qcOut->qcElement[el]->nExtensions++; + + qcOut->qcElement[el]->extension[idx].type = + extPayload[n].dataType; /* Perform a sanity check on the type? */ + qcOut->qcElement[el]->extension[idx].nPayloadBits = + extPayload[n].dataSize; + qcOut->qcElement[el]->extension[idx].pPayload = extPayload[n].pData; + /* Now ask the bitstream encoder how many bits we need to encode the + * data with the current bitstream syntax: */ + qcOut->qcElement[el]->extBitsUsed += FDKaacEnc_writeExtensionData( + NULL, &qcOut->qcElement[el]->extension[idx], 0, 0, + hAacEnc->config->syntaxFlags, hAacEnc->aot, + hAacEnc->config->epConfig); + extPayloadUsed[n] = 1; + } + } + + /* sum up extension and static bits for all channel elements */ + qcOut->elementExtBits += qcOut->qcElement[el]->extBitsUsed; + qcOut->staticBits += qcOut->qcElement[el]->staticBitsUsed; + + /* sum up pe */ + qcOut->totalNoRedPe += qcOut->qcElement[el]->peData.pe; + } + } + + qcOut->nExtensions = 0; + qcOut->globalExtBits = 0; + + /* reset extension payload */ + FDKmemclear(&qcOut->extension, (2 + 2) * sizeof(QC_OUT_EXTENSION)); + + /* Add extension payload not assigned to an channel element + (Ancillary data is the only supported type up to now) */ + for (n = 0; n < MAX_TOTAL_EXT_PAYLOADS; n++) { + if (!extPayloadUsed[n] && (extPayload[n].associatedChElement == -1) && + (extPayload[n].pData != NULL)) { + UINT payloadBits = 0; + + if (extPayload[n].dataType == EXT_DATA_ELEMENT) { + if (hAacEnc->ancillaryBitsPerFrame) { + /* granted frame dse bitrate */ + payloadBits = hAacEnc->ancillaryBitsPerFrame; + } else { + /* write anc data if bitrate constraint fulfilled */ + if ((extPayload[n].dataSize >> 3) <= + hAacEnc->config->maxAncBytesPerAU) { + payloadBits = extPayload[n].dataSize; + } + } + payloadBits = fixMin(extPayload[n].dataSize, payloadBits); + } else { + payloadBits = extPayload[n].dataSize; + } + + if (payloadBits > 0) { + int idx = qcOut->nExtensions++; + + qcOut->extension[idx].type = + extPayload[n].dataType; /* Perform a sanity check on the type? */ + qcOut->extension[idx].nPayloadBits = payloadBits; + qcOut->extension[idx].pPayload = extPayload[n].pData; + /* Now ask the bitstream encoder how many bits we need to encode the + * data with the current bitstream syntax: */ + qcOut->globalExtBits += FDKaacEnc_writeExtensionData( + NULL, &qcOut->extension[idx], 0, 0, hAacEnc->config->syntaxFlags, + hAacEnc->aot, hAacEnc->config->epConfig); + if (extPayload[n].dataType == EXT_DATA_ELEMENT) { + /* substract the processed bits */ + extPayload[n].dataSize -= payloadBits; + } + extPayloadUsed[n] = 1; + } + } + } + + if (!(hAacEnc->config->syntaxFlags & (AC_SCALABLE | AC_ER))) { + qcOut->globalExtBits += EL_ID_BITS; /* add bits for ID_END */ + } + + /* build bitstream all nSubFrames */ + { + INT totalBits = 0; /* Total AU bits */ + ; + INT avgTotalBits = 0; + + /*-------------------------------------------- */ + /* Get average total bits */ + /*-------------------------------------------- */ + { + /* frame wise bitrate adaption */ + FDKaacEnc_AdjustBitrate( + hAacEnc->qcKernel, cm, &avgTotalBits, hAacEnc->config->bitRate, + hAacEnc->config->sampleRate, hAacEnc->config->framelength); + + /* adjust super frame bitrate */ + avgTotalBits *= hAacEnc->config->nSubFrames; + } + + /* Make first estimate of transport header overhead. + Take maximum possible frame size into account to prevent bitreservoir + underrun. */ + hAacEnc->qcKernel->globHdrBits = transportEnc_GetStaticBits( + hTpEnc, avgTotalBits + hAacEnc->qcKernel->bitResTot); + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + /*-------------------------------------------- */ + + ErrorStatus = FDKaacEnc_QCMain( + hAacEnc->qcKernel, hAacEnc->psyOut, hAacEnc->qcOut, avgTotalBits, cm, + hAacEnc->aot, hAacEnc->config->syntaxFlags, hAacEnc->config->epConfig); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + /*-------------------------------------------- */ + + /*-------------------------------------------- */ + ErrorStatus = FDKaacEnc_updateFillBits( + cm, hAacEnc->qcKernel, hAacEnc->qcKernel->elementBits, hAacEnc->qcOut); + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + /*-------------------------------------------- */ + ErrorStatus = FDKaacEnc_FinalizeBitConsumption( + cm, hAacEnc->qcKernel, qcOut, qcOut->qcElement, hTpEnc, hAacEnc->aot, + hAacEnc->config->syntaxFlags, hAacEnc->config->epConfig); + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + /*-------------------------------------------- */ + totalBits += qcOut->totalBits; + + /*-------------------------------------------- */ + FDKaacEnc_updateBitres(cm, hAacEnc->qcKernel, hAacEnc->qcOut); + + /*-------------------------------------------- */ + + /* for ( all sub frames ) ... */ + /* write bitstream header */ + if (TRANSPORTENC_OK != + transportEnc_WriteAccessUnit(hTpEnc, totalBits, + FDKaacEnc_EncBitresToTpBitres(hAacEnc), + cm->nChannelsEff)) { + return AAC_ENC_UNKNOWN; + } + + /* write bitstream */ + ErrorStatus = FDKaacEnc_WriteBitstream( + hTpEnc, cm, qcOut, psyOut, hAacEnc->qcKernel, hAacEnc->aot, + hAacEnc->config->syntaxFlags, hAacEnc->config->epConfig); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + /* transportEnc_EndAccessUnit() is being called inside + * FDKaacEnc_WriteBitstream() */ + if (TRANSPORTENC_OK != transportEnc_GetFrame(hTpEnc, nOutBytes)) { + return AAC_ENC_UNKNOWN; + } + + } /* -end- if (curFrame==hAacEnc->qcKernel->nSubFrames) */ + + /*-------------------------------------------- */ + return AAC_ENC_OK; +} + +/*--------------------------------------------------------------------------- + + functionname:FDKaacEnc_Close + description: delete encoder instance + returns: + + ---------------------------------------------------------------------------*/ + +void FDKaacEnc_Close(HANDLE_AAC_ENC *phAacEnc) /* encoder handle */ +{ + if (*phAacEnc == NULL) { + return; + } + AAC_ENC *hAacEnc = (AAC_ENC *)*phAacEnc; + + if (hAacEnc->dynamic_RAM != NULL) FreeAACdynamic_RAM(&hAacEnc->dynamic_RAM); + + FDKaacEnc_PsyClose(&hAacEnc->psyKernel, hAacEnc->psyOut); + + FDKaacEnc_QCClose(&hAacEnc->qcKernel, hAacEnc->qcOut); + + FreeRam_aacEnc_AacEncoder(phAacEnc); +} + +/* The following functions are in this source file only for convenience and */ +/* need not be visible outside of a possible encoder library. */ + +/* basic defines for ancillary data */ +#define MAX_ANCRATE 19200 /* ancillary rate >= 19200 isn't valid */ + +/*--------------------------------------------------------------------------- + + functionname: FDKaacEnc_InitCheckAncillary + description: initialize and check ancillary data struct + return: if success or NULL if error + + ---------------------------------------------------------------------------*/ +static AAC_ENCODER_ERROR FDKaacEnc_InitCheckAncillary( + INT bitRate, INT framelength, INT ancillaryRate, INT *ancillaryBitsPerFrame, + INT sampleRate) { + /* don't use negative ancillary rates */ + if (ancillaryRate < -1) return AAC_ENC_UNSUPPORTED_ANC_BITRATE; + + /* check if ancillary rate is ok */ + if ((ancillaryRate != (-1)) && (ancillaryRate != 0)) { + /* ancRate <= 15% of bitrate && ancRate < 19200 */ + if ((ancillaryRate >= MAX_ANCRATE) || + ((ancillaryRate * 20) > (bitRate * 3))) { + return AAC_ENC_UNSUPPORTED_ANC_BITRATE; + } + } else if (ancillaryRate == -1) { + /* if no special ancRate is requested but a ancillary file is + stated, then generate a ancillary rate matching to the bitrate */ + if (bitRate >= (MAX_ANCRATE * 10)) { + /* ancillary rate is 19199 */ + ancillaryRate = (MAX_ANCRATE - 1); + } else { /* 10% of bitrate */ + ancillaryRate = bitRate / 10; + } + } + + /* make ancillaryBitsPerFrame byte align */ + *ancillaryBitsPerFrame = + FDKaacEnc_CalcBitsPerFrame(ancillaryRate, framelength, sampleRate) & ~0x7; + + return AAC_ENC_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc.h new file mode 100644 index 0000000000000..2d95abbb2e2c6 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc.h @@ -0,0 +1,407 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Schug / A. Groeschel + + Description: fast aac coder interface library functions + +*******************************************************************************/ + +#ifndef AACENC_H +#define AACENC_H + +#include "common_fix.h" +#include "FDK_audio.h" + +#include "tpenc_lib.h" + +#include "sbr_encoder.h" + +#define MIN_BUFSIZE_PER_EFF_CHAN 6144 + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * AAC-LC error codes. + */ +typedef enum { + AAC_ENC_OK = 0x0000, /*!< All fine. */ + + AAC_ENC_UNKNOWN = 0x0002, /*!< Error condition is of unknown reason, or from + another module. */ + + /* initialization errors */ + aac_enc_init_error_start = 0x2000, + AAC_ENC_INVALID_HANDLE = 0x2020, /*!< The handle passed to the function call + was invalid (probably NULL). */ + AAC_ENC_INVALID_FRAME_LENGTH = + 0x2080, /*!< Invalid frame length (must be 1024 or 960). */ + AAC_ENC_INVALID_N_CHANNELS = + 0x20e0, /*!< Invalid amount of audio input channels. */ + AAC_ENC_INVALID_SFB_TABLE = 0x2140, /*!< Internal encoder error. */ + + AAC_ENC_UNSUPPORTED_AOT = + 0x3000, /*!< The Audio Object Type (AOT) is not supported. */ + AAC_ENC_UNSUPPORTED_FILTERBANK = + 0x3010, /*!< Filterbank type is not supported. */ + AAC_ENC_UNSUPPORTED_BITRATE = + 0x3020, /*!< The chosen bitrate is not supported. */ + AAC_ENC_UNSUPPORTED_BITRATE_MODE = + 0x3028, /*!< Unsupported bit rate mode (CBR or VBR). */ + AAC_ENC_UNSUPPORTED_ANC_BITRATE = + 0x3040, /*!< Unsupported ancillay bitrate. */ + AAC_ENC_UNSUPPORTED_ANC_MODE = 0x3060, + AAC_ENC_UNSUPPORTED_TRANSPORT_TYPE = + 0x3080, /*!< The bitstream format is not supported. */ + AAC_ENC_UNSUPPORTED_ER_FORMAT = + 0x30a0, /*!< The error resilience tool format is not supported. */ + AAC_ENC_UNSUPPORTED_EPCONFIG = + 0x30c0, /*!< The error protection format is not supported. */ + AAC_ENC_UNSUPPORTED_CHANNELCONFIG = + 0x30e0, /*!< The channel configuration (either number or arrangement) is + not supported. */ + AAC_ENC_UNSUPPORTED_SAMPLINGRATE = + 0x3100, /*!< Sample rate of audio input is not supported. */ + AAC_ENC_NO_MEMORY = 0x3120, /*!< Could not allocate memory. */ + AAC_ENC_PE_INIT_TABLE_NOT_FOUND = 0x3140, /*!< Internal encoder error. */ + + aac_enc_init_error_end, + + /* encode errors */ + aac_enc_error_start = 0x4000, + AAC_ENC_QUANT_ERROR = 0x4020, /*!< Too many bits used in quantization. */ + AAC_ENC_WRITTEN_BITS_ERROR = + 0x4040, /*!< Unexpected number of written bits, differs to + calculated number of bits. */ + AAC_ENC_PNS_TABLE_ERROR = 0x4060, /*!< PNS level out of range. */ + AAC_ENC_GLOBAL_GAIN_TOO_HIGH = 0x4080, /*!< Internal quantizer error. */ + AAC_ENC_BITRES_TOO_LOW = 0x40a0, /*!< Too few bits in bit reservoir. */ + AAC_ENC_BITRES_TOO_HIGH = 0x40a1, /*!< Too many bits in bit reservoir. */ + AAC_ENC_INVALID_CHANNEL_BITRATE = 0x4100, + AAC_ENC_INVALID_ELEMENTINFO_TYPE = 0x4120, /*!< Internal encoder error. */ + + AAC_ENC_WRITE_SCAL_ERROR = 0x41e0, /*!< Error writing scalefacData. */ + AAC_ENC_WRITE_SEC_ERROR = 0x4200, /*!< Error writing sectionData. */ + AAC_ENC_WRITE_SPEC_ERROR = 0x4220, /*!< Error writing spectralData. */ + aac_enc_error_end + +} AAC_ENCODER_ERROR; +/*-------------------------- defines --------------------------------------*/ + +#define ANC_DATA_BUFFERSIZE 1024 /* ancBuffer size */ + +#define MAX_TOTAL_EXT_PAYLOADS ((((8)) * (1)) + (2 + 2)) + +typedef enum { + AACENC_BR_MODE_INVALID = -1, /*!< Invalid bitrate mode. */ + AACENC_BR_MODE_CBR = 0, /*!< Constant bitrate mode. */ + AACENC_BR_MODE_VBR_1 = 1, /*!< Variable bitrate mode, very low bitrate. */ + AACENC_BR_MODE_VBR_2 = 2, /*!< Variable bitrate mode, low bitrate. */ + AACENC_BR_MODE_VBR_3 = 3, /*!< Variable bitrate mode, medium bitrate. */ + AACENC_BR_MODE_VBR_4 = 4, /*!< Variable bitrate mode, high bitrate. */ + AACENC_BR_MODE_VBR_5 = 5, /*!< Variable bitrate mode, very high bitrate. */ + AACENC_BR_MODE_FF = 6, /*!< Fixed frame mode. */ + AACENC_BR_MODE_SFR = 7 /*!< Superframe mode. */ + +} AACENC_BITRATE_MODE; + +#define AACENC_BR_MODE_IS_VBR(brMode) ((brMode >= 1) && (brMode <= 5)) + +typedef enum { + + CH_ORDER_MPEG = + 0, /*!< MPEG channel ordering (e. g. 5.1: C, L, R, SL, SR, LFE) */ + CH_ORDER_WAV, /*!< WAV fileformat channel ordering (e. g. 5.1: L, R, C, LFE, + SL, SR) */ + CH_ORDER_WG4 /*!< WG4 fileformat channel ordering (e. g. 5.1: L, R, SL, SR, C, LFE) */ + +} CHANNEL_ORDER; + +/*-------------------- structure definitions ------------------------------*/ + +struct AACENC_CONFIG { + INT sampleRate; /* encoder sample rate */ + INT bitRate; /* encoder bit rate in bits/sec */ + INT ancDataBitRate; /* additional bits consumed by anc data or sbr have to be + consiedered while configuration */ + + INT nSubFrames; /* number of frames in super frame (not ADTS/LATM subframes !) + */ + AUDIO_OBJECT_TYPE audioObjectType; /* Audio Object Type */ + + INT averageBits; /* encoder bit rate in bits/superframe */ + AACENC_BITRATE_MODE bitrateMode; /* encoder bitrate mode (CBR/VBR) */ + INT nChannels; /* number of channels to process */ + CHANNEL_ORDER channelOrder; /* input Channel ordering scheme. */ + INT bandWidth; /* targeted audio bandwidth in Hz */ + CHANNEL_MODE channelMode; /* encoder channel mode configuration */ + INT framelength; /* used frame size */ + + UINT syntaxFlags; /* bitstreams syntax configuration */ + SCHAR epConfig; /* error protection configuration */ + + INT anc_Rate; /* ancillary rate, 0 (disabled), -1 (default) else desired rate + */ + UINT maxAncBytesPerAU; + INT minBitsPerFrame; /* minimum number of bits in AU */ + INT maxBitsPerFrame; /* maximum number of bits in AU */ + + INT audioMuxVersion; /* audio mux version in loas/latm transport format */ + + UINT sbrRatio; /* sbr sampling rate ratio: dual- or single-rate */ + + UCHAR useTns; /* flag: use temporal noise shaping */ + UCHAR usePns; /* flag: use perceptual noise substitution */ + UCHAR useIS; /* flag: use intensity coding */ + UCHAR useMS; /* flag: use ms stereo tool */ + + UCHAR useRequant; /* flag: use afterburner */ + + UINT downscaleFactor; +}; + +typedef struct { + UCHAR *pData; /* pointer to extension payload data */ + UINT dataSize; /* extension payload data size in bits */ + EXT_PAYLOAD_TYPE dataType; /* extension payload data type */ + INT associatedChElement; /* number of the channel element the data is assigned + to */ +} AACENC_EXT_PAYLOAD; + +typedef struct AAC_ENC *HANDLE_AAC_ENC; + +/** + * \brief Calculate framesize in bits for given bit rate, frame length and + * sampling rate. + * + * \param bitRate Ttarget bitrate in bits per second. + * \param frameLength Number of audio samples in one frame. + * \param samplingRate Sampling rate in Hz. + * + * \return Framesize in bits per frame. + */ +INT FDKaacEnc_CalcBitsPerFrame(const INT bitRate, const INT frameLength, + const INT samplingRate); + +/** + * \brief Calculate bitrate in bits per second for given framesize, frame length + * and sampling rate. + * + * \param bitsPerFrame Framesize in bits per frame + * \param frameLength Number of audio samples in one frame. + * \param samplingRate Sampling rate in Hz. + * + * \return Bitrate in bits per second. + */ +INT FDKaacEnc_CalcBitrate(const INT bitsPerFrame, const INT frameLength, + const INT samplingRate); + +/** + * \brief Limit given bit rate to a valid value + * \param hTpEnc transport encoder handle + * \param aot audio object type + * \param coreSamplingRate the sample rate to be used for the AAC encoder + * \param frameLength the frameLength to be used for the AAC encoder + * \param nChannels number of total channels + * \param nChannelsEff number of effective channels + * \param bitRate the initial bit rate value for which the closest valid bit + * rate value is searched for + * \param averageBits average bits per frame for fixed framing. Set to -1 if not + * available. + * \param optional pointer where the current bits per frame are stored into. + * \param bitrateMode the current bit rate mode + * \param nSubFrames number of sub frames for super framing (not transport + * frames). + * \return a valid bit rate value as close as possible or identical to bitRate + */ +INT FDKaacEnc_LimitBitrate(HANDLE_TRANSPORTENC hTpEnc, AUDIO_OBJECT_TYPE aot, + INT coreSamplingRate, INT frameLength, INT nChannels, + INT nChannelsEff, INT bitRate, INT averageBits, + INT *pAverageBitsPerFrame, + AACENC_BITRATE_MODE bitrateMode, INT nSubFrames); + +/** + * \brief Get current state of the bit reservoir + * \param hAacEncoder encoder handle + * \return bit reservoir state in bits + */ +INT FDKaacEnc_GetBitReservoirState(const HANDLE_AAC_ENC hAacEncoder); + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_GetVBRBitrate + description: Get VBR bitrate from vbr quality + input params: int vbrQuality (VBR0, VBR1, VBR2) + channelMode + returns: vbr bitrate + +------------------------------------------------------------------------------*/ +INT FDKaacEnc_GetVBRBitrate(AACENC_BITRATE_MODE bitrateMode, + CHANNEL_MODE channelMode); + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_AdjustVBRBitrateMode + description: Adjust bitrate mode to given bitrate parameter + input params: int vbrQuality (VBR0, VBR1, VBR2) + bitrate + channelMode + returns: vbr bitrate mode + + ------------------------------------------------------------------------------*/ +AACENC_BITRATE_MODE FDKaacEnc_AdjustVBRBitrateMode( + AACENC_BITRATE_MODE bitrateMode, INT bitrate, CHANNEL_MODE channelMode); + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_AacInitDefaultConfig + description: gives reasonable default configuration + returns: --- + + ------------------------------------------------------------------------------*/ +void FDKaacEnc_AacInitDefaultConfig(AACENC_CONFIG *config); + +/*--------------------------------------------------------------------------- + + functionname:FDKaacEnc_Open + description: allocate and initialize a new encoder instance + returns: 0 if success + + ---------------------------------------------------------------------------*/ +AAC_ENCODER_ERROR FDKaacEnc_Open( + HANDLE_AAC_ENC + *phAacEnc, /* pointer to an encoder handle, initialized on return */ + const INT nElements, /* number of maximal elements in instance to support */ + const INT nChannels, /* number of maximal channels in instance to support */ + const INT nSubFrames); /* support superframing in instance */ + +AAC_ENCODER_ERROR FDKaacEnc_Initialize( + HANDLE_AAC_ENC + hAacEncoder, /* pointer to an encoder handle, initialized on return */ + AACENC_CONFIG *config, /* pre-initialized config struct */ + HANDLE_TRANSPORTENC hTpEnc, ULONG initFlags); + +/*--------------------------------------------------------------------------- + + functionname: FDKaacEnc_EncodeFrame + description: encode one frame + returns: 0 if success + + ---------------------------------------------------------------------------*/ + +AAC_ENCODER_ERROR FDKaacEnc_EncodeFrame( + HANDLE_AAC_ENC hAacEnc, /* encoder handle */ + HANDLE_TRANSPORTENC hTpEnc, INT_PCM *inputBuffer, + const UINT inputBufferBufSize, INT *numOutBytes, + AACENC_EXT_PAYLOAD extPayload[MAX_TOTAL_EXT_PAYLOADS]); + +/*--------------------------------------------------------------------------- + + functionname:FDKaacEnc_Close + description: delete encoder instance + returns: + + ---------------------------------------------------------------------------*/ + +void FDKaacEnc_Close(HANDLE_AAC_ENC *phAacEnc); /* encoder handle */ + +#ifdef __cplusplus +} +#endif + +#endif /* AACENC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_lib.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_lib.cpp new file mode 100644 index 0000000000000..ee7f91869ca51 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_lib.cpp @@ -0,0 +1,2550 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: FDK HE-AAC Encoder interface library functions + +*******************************************************************************/ + +#include "aacenc_lib.h" +#include "FDK_audio.h" +#include "aacenc.h" + +#include "aacEnc_ram.h" +#include "FDK_core.h" /* FDK_tools versioning info */ + +/* Encoder library info */ +#define AACENCODER_LIB_VL0 4 +#define AACENCODER_LIB_VL1 0 +#define AACENCODER_LIB_VL2 1 +#define AACENCODER_LIB_TITLE "AAC Encoder" +#ifdef SUPPRESS_BUILD_DATE_INFO +#define AACENCODER_LIB_BUILD_DATE "" +#define AACENCODER_LIB_BUILD_TIME "" +#else +#define AACENCODER_LIB_BUILD_DATE __DATE__ +#define AACENCODER_LIB_BUILD_TIME __TIME__ +#endif + +#include "pcm_utils.h" + +#include "sbr_encoder.h" +#include "../src/sbrenc_ram.h" +#include "channel_map.h" + +#include "psy_const.h" +#include "bitenc.h" + +#include "tpenc_lib.h" + +#include "metadata_main.h" +#include "mps_main.h" +#include "sacenc_lib.h" + +#define SBL(fl) \ + (fl / \ + 8) /*!< Short block length (hardcoded to 8 short blocks per long block) */ +#define BSLA(fl) \ + (4 * SBL(fl) + SBL(fl) / 2) /*!< AAC block switching look-ahead */ +#define DELAY_AAC(fl) (fl + BSLA(fl)) /*!< MDCT + blockswitching */ +#define DELAY_AACLD(fl) (fl) /*!< MDCT delay (no framing delay included) */ +#define DELAY_AACELD(fl) \ + ((fl) / 2) /*!< ELD FB delay (no framing delay included) */ + +#define MAX_DS_DELAY (100) /*!< Maximum downsampler delay in SBR. */ +#define INPUTBUFFER_SIZE \ + (2 * (1024) + MAX_DS_DELAY + 1537) /*!< Audio input samples + downsampler \ + delay + sbr/aac delay compensation */ + +#define DEFAULT_HEADER_PERIOD_REPETITION_RATE \ + 10 /*!< Default header repetition rate used in transport library and for SBR \ + header. */ + +//////////////////////////////////////////////////////////////////////////////////// +/** + * Flags to characterize encoder modules to be supported in present instance. + */ +enum { + ENC_MODE_FLAG_AAC = 0x0001, + ENC_MODE_FLAG_SBR = 0x0002, + ENC_MODE_FLAG_PS = 0x0004, + ENC_MODE_FLAG_SAC = 0x0008, + ENC_MODE_FLAG_META = 0x0010 +}; + +//////////////////////////////////////////////////////////////////////////////////// +typedef struct { + AUDIO_OBJECT_TYPE userAOT; /*!< Audio Object Type. */ + UINT userSamplerate; /*!< Sampling frequency. */ + UINT nChannels; /*!< will be set via channelMode. */ + CHANNEL_MODE userChannelMode; + UINT userBitrate; + UINT userBitrateMode; + UINT userBandwidth; + UINT userAfterburner; + UINT userFramelength; + UINT userAncDataRate; + UINT userPeakBitrate; + + UCHAR userTns; /*!< Use TNS coding. */ + UCHAR userPns; /*!< Use PNS coding. */ + UCHAR userIntensity; /*!< Use Intensity coding. */ + + TRANSPORT_TYPE userTpType; /*!< Transport type */ + UCHAR userTpSignaling; /*!< Extension AOT signaling mode. */ + UCHAR userTpNsubFrames; /*!< Number of sub frames in a transport frame for + LOAS/LATM or ADTS (default 1). */ + UCHAR userTpAmxv; /*!< AudioMuxVersion to be used for LATM (default 0). */ + UCHAR userTpProtection; + UCHAR userTpHeaderPeriod; /*!< Parameter used to configure LATM/LOAS SMC rate. + Moreover this parameters is used to configure + repetition rate of PCE in raw_data_block. */ + + UCHAR userErTools; /*!< Use VCB11, HCR and/or RVLC ER tool. */ + UINT userPceAdditions; /*!< Configure additional bits in PCE. */ + + UCHAR userMetaDataMode; /*!< Meta data library configuration. */ + + UCHAR userSbrEnabled; /*!< Enable SBR for ELD. */ + UINT userSbrRatio; /*!< SBR sampling rate ratio. Dual- or single-rate. */ + + UINT userDownscaleFactor; + +} USER_PARAM; + +/** + * SBR extenxion payload struct provides buffers to be filled in SBR encoder + * library. + */ +typedef struct { + UCHAR data[(1)][(8)][MAX_PAYLOAD_SIZE]; /*!< extension payload data buffer */ + UINT dataSize[(1)][(8)]; /*!< extension payload data size in bits */ +} SBRENC_EXT_PAYLOAD; + +//////////////////////////////////////////////////////////////////////////////////// + +/**************************************************************************** + Structure Definitions +****************************************************************************/ + +typedef struct AACENC_CONFIG *HANDLE_AACENC_CONFIG; + +struct AACENCODER { + USER_PARAM extParam; + CODER_CONFIG coderConfig; + + /* AAC */ + AACENC_CONFIG aacConfig; + HANDLE_AAC_ENC hAacEnc; + + /* SBR */ + HANDLE_SBR_ENCODER hEnvEnc; /* SBR encoder */ + SBRENC_EXT_PAYLOAD *pSbrPayload; /* SBR extension payload */ + + /* Meta Data */ + HANDLE_FDK_METADATA_ENCODER hMetadataEnc; + INT metaDataAllowed; /* Signal whether chosen configuration allows metadata. + Necessary for delay compensation. Metadata mode is a + separate parameter. */ + + HANDLE_MPS_ENCODER hMpsEnc; + + /* Transport */ + HANDLE_TRANSPORTENC hTpEnc; + + INT_PCM + *inputBuffer; /* Internal input buffer. Input source for AAC encoder */ + UCHAR *outBuffer; /* Internal bitstream buffer */ + + INT inputBufferSize; /* Size of internal input buffer */ + INT inputBufferSizePerChannel; /* Size of internal input buffer per channel */ + INT outBufferInBytes; /* Size of internal bitstream buffer*/ + + INT inputBufferOffset; /* Where to write new input samples. */ + + INT nSamplesToRead; /* number of input samples neeeded for encoding one frame + */ + INT nSamplesRead; /* number of input samples already in input buffer */ + INT nZerosAppended; /* appended zeros at end of file*/ + INT nDelay; /* codec delay */ + INT nDelayCore; /* codec delay, w/o the SBR decoder delay */ + + AACENC_EXT_PAYLOAD extPayload[MAX_TOTAL_EXT_PAYLOADS]; + + ULONG InitFlags; /* internal status to treggier re-initialization */ + + /* Memory allocation info. */ + INT nMaxAacElements; + INT nMaxAacChannels; + INT nMaxSbrElements; + INT nMaxSbrChannels; + + UINT encoder_modis; + + /* Capability flags */ + UINT CAPF_tpEnc; +}; + +typedef struct { + /* input */ + ULONG nChannels; /*!< Number of audio channels. */ + ULONG samplingRate; /*!< Encoder output sampling rate. */ + ULONG bitrateRange; /*!< Lower bitrate range for config entry. */ + + /* output*/ + UCHAR sbrMode; /*!< 0: ELD sbr off, + 1: ELD with downsampled sbr, + 2: ELD with dualrate sbr. */ + CHANNEL_MODE chMode; /*!< Channel mode. */ + +} ELD_SBR_CONFIGURATOR; + +/** + * \brief This table defines ELD/SBR default configurations. + */ +static const ELD_SBR_CONFIGURATOR eldSbrAutoConfigTab[] = { + {1, 48000, 0, 2, MODE_1}, {1, 48000, 64000, 0, MODE_1}, + + {1, 44100, 0, 2, MODE_1}, {1, 44100, 64000, 0, MODE_1}, + + {1, 32000, 0, 2, MODE_1}, {1, 32000, 28000, 1, MODE_1}, + {1, 32000, 56000, 0, MODE_1}, + + {1, 24000, 0, 1, MODE_1}, {1, 24000, 40000, 0, MODE_1}, + + {1, 16000, 0, 1, MODE_1}, {1, 16000, 28000, 0, MODE_1}, + + {1, 15999, 0, 0, MODE_1}, + + {2, 48000, 0, 2, MODE_2}, {2, 48000, 44000, 2, MODE_2}, + {2, 48000, 128000, 0, MODE_2}, + + {2, 44100, 0, 2, MODE_2}, {2, 44100, 44000, 2, MODE_2}, + {2, 44100, 128000, 0, MODE_2}, + + {2, 32000, 0, 2, MODE_2}, {2, 32000, 32000, 2, MODE_2}, + {2, 32000, 68000, 1, MODE_2}, {2, 32000, 96000, 0, MODE_2}, + + {2, 24000, 0, 1, MODE_2}, {2, 24000, 48000, 1, MODE_2}, + {2, 24000, 80000, 0, MODE_2}, + + {2, 16000, 0, 1, MODE_2}, {2, 16000, 32000, 1, MODE_2}, + {2, 16000, 64000, 0, MODE_2}, + + {2, 15999, 0, 0, MODE_2} + +}; + +/* + * \brief Configure SBR for ELD configuration. + * + * This function finds default SBR configuration for ELD based on number of + * channels, sampling rate and bitrate. + * + * \param nChannels Number of audio channels. + * \param samplingRate Audio signal sampling rate. + * \param bitrate Encoder bitrate. + * + * \return - pointer to eld sbr configuration. + * - NULL, on failure. + */ +static const ELD_SBR_CONFIGURATOR *eldSbrConfigurator(const ULONG nChannels, + const ULONG samplingRate, + const ULONG bitrate) { + int i; + const ELD_SBR_CONFIGURATOR *pSetup = NULL; + + for (i = 0; + i < (int)(sizeof(eldSbrAutoConfigTab) / sizeof(ELD_SBR_CONFIGURATOR)); + i++) { + if ((nChannels == eldSbrAutoConfigTab[i].nChannels) && + (samplingRate <= eldSbrAutoConfigTab[i].samplingRate) && + (bitrate >= eldSbrAutoConfigTab[i].bitrateRange)) { + pSetup = &eldSbrAutoConfigTab[i]; + } + } + + return pSetup; +} + +static inline INT isSbrActive(const HANDLE_AACENC_CONFIG hAacConfig) { + INT sbrUsed = 0; + + /* Note: Even if implicit signalling was selected, The AOT itself here is not + * AOT_AAC_LC */ + if ((hAacConfig->audioObjectType == AOT_SBR) || + (hAacConfig->audioObjectType == AOT_PS) || + (hAacConfig->audioObjectType == AOT_MP2_SBR)) { + sbrUsed = 1; + } + if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD && + (hAacConfig->syntaxFlags & AC_SBR_PRESENT)) { + sbrUsed = 1; + } + + return (sbrUsed); +} + +static inline INT isPsActive(const AUDIO_OBJECT_TYPE audioObjectType) { + INT psUsed = 0; + + if (audioObjectType == AOT_PS) { + psUsed = 1; + } + + return (psUsed); +} + +static CHANNEL_MODE GetCoreChannelMode( + const CHANNEL_MODE channelMode, const AUDIO_OBJECT_TYPE audioObjectType) { + CHANNEL_MODE mappedChannelMode = channelMode; + if ((isPsActive(audioObjectType) && (channelMode == MODE_2)) || + (channelMode == MODE_212)) { + mappedChannelMode = MODE_1; + } + return mappedChannelMode; +} + +static SBR_PS_SIGNALING getSbrSignalingMode( + const AUDIO_OBJECT_TYPE audioObjectType, const TRANSPORT_TYPE transportType, + const UCHAR transportSignaling, const UINT sbrRatio) + +{ + SBR_PS_SIGNALING sbrSignaling; + + if (transportType == TT_UNKNOWN || sbrRatio == 0) { + sbrSignaling = SIG_UNKNOWN; /* Needed parameters have not been set */ + return sbrSignaling; + } else { + sbrSignaling = + SIG_EXPLICIT_HIERARCHICAL; /* default: explicit hierarchical signaling + */ + } + + if ((audioObjectType == AOT_AAC_LC) || (audioObjectType == AOT_SBR) || + (audioObjectType == AOT_PS) || (audioObjectType == AOT_MP2_AAC_LC) || + (audioObjectType == AOT_MP2_SBR)) { + switch (transportType) { + case TT_MP4_ADIF: + case TT_MP4_ADTS: + sbrSignaling = SIG_IMPLICIT; /* For MPEG-2 transport types, only + implicit signaling is possible */ + break; + + case TT_MP4_RAW: + case TT_MP4_LATM_MCP1: + case TT_MP4_LATM_MCP0: + case TT_MP4_LOAS: + default: + if (transportSignaling == 0xFF) { + /* Defaults */ + sbrSignaling = SIG_EXPLICIT_HIERARCHICAL; + } else { + /* User set parameters */ + /* Attention: Backward compatible explicit signaling does only work + * with AMV1 for LATM/LOAS */ + sbrSignaling = (SBR_PS_SIGNALING)transportSignaling; + } + break; + } + } + + return sbrSignaling; +} + +static inline INT getAssociatedChElement(SBR_ELEMENT_INFO *elInfoSbr, + CHANNEL_MAPPING *channelMapping) { + ELEMENT_INFO *elInfo = channelMapping->elInfo; + INT nElements = channelMapping->nElements; + INT associatedChElement = -1; + int i; + + for (i = 0; i < nElements; i++) { + if (elInfoSbr->elType == elInfo[i].elType && + elInfoSbr->instanceTag == elInfo[i].instanceTag) { + associatedChElement = i; + break; + } + } + + return associatedChElement; +} + +/**************************************************************************** + Allocate Encoder +****************************************************************************/ + +H_ALLOC_MEM(_AacEncoder, AACENCODER) +C_ALLOC_MEM(_AacEncoder, struct AACENCODER, 1) + +/* + * Map Encoder specific config structures to CODER_CONFIG. + */ +static void FDKaacEnc_MapConfig(CODER_CONFIG *const cc, + const USER_PARAM *const extCfg, + const SBR_PS_SIGNALING sbrSignaling, + const HANDLE_AACENC_CONFIG hAacConfig) { + AUDIO_OBJECT_TYPE transport_AOT = AOT_NULL_OBJECT; + FDKmemclear(cc, sizeof(CODER_CONFIG)); + + cc->flags = 0; + + cc->samplesPerFrame = hAacConfig->framelength; + cc->samplingRate = hAacConfig->sampleRate; + cc->extSamplingRate = extCfg->userSamplerate; + + /* Map virtual aot to transport aot. */ + switch (hAacConfig->audioObjectType) { + case AOT_MP2_AAC_LC: + transport_AOT = AOT_AAC_LC; + break; + case AOT_MP2_SBR: + transport_AOT = AOT_SBR; + cc->flags |= CC_SBR; + break; + default: + transport_AOT = hAacConfig->audioObjectType; + } + + if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) { + cc->flags |= (hAacConfig->syntaxFlags & AC_SBR_PRESENT) ? CC_SBR : 0; + cc->flags |= (hAacConfig->syntaxFlags & AC_LD_MPS) ? CC_SAC : 0; + } + + /* transport type is usually AAC-LC. */ + if ((transport_AOT == AOT_SBR) || (transport_AOT == AOT_PS)) { + cc->aot = AOT_AAC_LC; + } else { + cc->aot = transport_AOT; + } + + /* Configure extension aot. */ + if (sbrSignaling == SIG_IMPLICIT) { + cc->extAOT = AOT_NULL_OBJECT; /* implicit */ + } else { + if ((sbrSignaling == SIG_EXPLICIT_BW_COMPATIBLE) && + ((transport_AOT == AOT_SBR) || (transport_AOT == AOT_PS))) { + cc->extAOT = AOT_SBR; /* explicit backward compatible */ + } else { + cc->extAOT = transport_AOT; /* explicit hierarchical */ + } + } + + if ((transport_AOT == AOT_SBR) || (transport_AOT == AOT_PS)) { + cc->sbrPresent = 1; + if (transport_AOT == AOT_PS) { + cc->psPresent = 1; + } + } + cc->sbrSignaling = sbrSignaling; + + if (hAacConfig->downscaleFactor > 1) { + cc->downscaleSamplingRate = cc->samplingRate; + cc->samplingRate *= hAacConfig->downscaleFactor; + cc->extSamplingRate *= hAacConfig->downscaleFactor; + } + + cc->bitRate = hAacConfig->bitRate; + cc->noChannels = hAacConfig->nChannels; + cc->flags |= CC_IS_BASELAYER; + cc->channelMode = hAacConfig->channelMode; + + cc->nSubFrames = (hAacConfig->nSubFrames > 1 && extCfg->userTpNsubFrames == 1) + ? hAacConfig->nSubFrames + : extCfg->userTpNsubFrames; + + cc->flags |= (extCfg->userTpProtection) ? CC_PROTECTION : 0; + + if (extCfg->userTpHeaderPeriod != 0xFF) { + cc->headerPeriod = extCfg->userTpHeaderPeriod; + } else { /* auto-mode */ + switch (extCfg->userTpType) { + case TT_MP4_ADTS: + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP1: + cc->headerPeriod = DEFAULT_HEADER_PERIOD_REPETITION_RATE; + break; + default: + cc->headerPeriod = 0; + } + } + + /* Mpeg-4 signaling for transport library. */ + switch (hAacConfig->audioObjectType) { + case AOT_MP2_AAC_LC: + case AOT_MP2_SBR: + cc->flags &= ~CC_MPEG_ID; /* Required for ADTS. */ + cc->extAOT = AOT_NULL_OBJECT; + break; + default: + cc->flags |= CC_MPEG_ID; + } + + /* ER-tools signaling. */ + cc->flags |= (hAacConfig->syntaxFlags & AC_ER_VCB11) ? CC_VCB11 : 0; + cc->flags |= (hAacConfig->syntaxFlags & AC_ER_HCR) ? CC_HCR : 0; + cc->flags |= (hAacConfig->syntaxFlags & AC_ER_RVLC) ? CC_RVLC : 0; + + /* Matrix mixdown coefficient configuration. */ + if ((extCfg->userPceAdditions & 0x1) && (hAacConfig->epConfig == -1) && + ((cc->channelMode == MODE_1_2_2) || (cc->channelMode == MODE_1_2_2_1))) { + cc->matrixMixdownA = ((extCfg->userPceAdditions >> 1) & 0x3) + 1; + cc->flags |= (extCfg->userPceAdditions >> 3) & 0x1 ? CC_PSEUDO_SURROUND : 0; + } else { + cc->matrixMixdownA = 0; + } + + cc->channelConfigZero = 0; +} + +/* + * Validate prefilled pointers within buffer descriptor. + * + * \param pBufDesc Pointer to buffer descriptor + + * \return - AACENC_OK, all fine. + * - AACENC_INVALID_HANDLE, on missing pointer initializiation. + * - AACENC_UNSUPPORTED_PARAMETER, on incorrect buffer descriptor + initialization. + */ +static AACENC_ERROR validateBufDesc(const AACENC_BufDesc *pBufDesc) { + AACENC_ERROR err = AACENC_OK; + + if (pBufDesc != NULL) { + int i; + if ((pBufDesc->bufferIdentifiers == NULL) || (pBufDesc->bufSizes == NULL) || + (pBufDesc->bufElSizes == NULL) || (pBufDesc->bufs == NULL)) { + err = AACENC_UNSUPPORTED_PARAMETER; + goto bail; + } + for (i = 0; i < pBufDesc->numBufs; i++) { + if (pBufDesc->bufs[i] == NULL) { + err = AACENC_UNSUPPORTED_PARAMETER; + goto bail; + } + } + } else { + err = AACENC_INVALID_HANDLE; + } +bail: + return err; +} + +/* + * Examine buffer descriptor regarding choosen identifier. + * + * \param pBufDesc Pointer to buffer descriptor + * \param identifier Buffer identifier to look for. + + * \return - Buffer descriptor index. + * -1, if there is no entry available. + */ +static INT getBufDescIdx(const AACENC_BufDesc *pBufDesc, + const AACENC_BufferIdentifier identifier) { + INT i, idx = -1; + + if (pBufDesc != NULL) { + for (i = 0; i < pBufDesc->numBufs; i++) { + if ((AACENC_BufferIdentifier)pBufDesc->bufferIdentifiers[i] == + identifier) { + idx = i; + break; + } + } + } + return idx; +} + +/**************************************************************************** + Function Declarations +****************************************************************************/ + +AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig, + USER_PARAM *config) { + /* make reasonable default settings */ + FDKaacEnc_AacInitDefaultConfig(hAacConfig); + + /* clear configuration structure and copy default settings */ + FDKmemclear(config, sizeof(USER_PARAM)); + + /* copy encoder configuration settings */ + config->nChannels = hAacConfig->nChannels; + config->userAOT = hAacConfig->audioObjectType = AOT_AAC_LC; + config->userSamplerate = hAacConfig->sampleRate; + config->userChannelMode = hAacConfig->channelMode; + config->userBitrate = hAacConfig->bitRate; + config->userBitrateMode = hAacConfig->bitrateMode; + config->userPeakBitrate = (UINT)-1; + config->userBandwidth = hAacConfig->bandWidth; + config->userTns = hAacConfig->useTns; + config->userPns = hAacConfig->usePns; + config->userIntensity = hAacConfig->useIS; + config->userAfterburner = hAacConfig->useRequant; + config->userFramelength = (UINT)-1; + + config->userDownscaleFactor = 1; + + /* initialize transport parameters */ + config->userTpType = TT_UNKNOWN; + config->userTpAmxv = 0; + config->userTpSignaling = 0xFF; /* choose signaling automatically */ + config->userTpNsubFrames = 1; + config->userTpProtection = 0; /* not crc protected*/ + config->userTpHeaderPeriod = 0xFF; /* header period in auto mode */ + config->userPceAdditions = 0; /* no matrix mixdown coefficient */ + config->userMetaDataMode = 0; /* do not embed any meta data info */ + + config->userAncDataRate = 0; + + /* SBR rate is set to 0 here, which means it should be set automatically + in FDKaacEnc_AdjustEncSettings() if the user did not set a rate + expilicitely. */ + config->userSbrRatio = 0; + + /* SBR enable set to -1 means to inquire ELD audio configurator for reasonable + * configuration. */ + config->userSbrEnabled = (UCHAR)-1; + + return AAC_ENC_OK; +} + +static void aacEncDistributeSbrBits(CHANNEL_MAPPING *channelMapping, + SBR_ELEMENT_INFO *sbrElInfo, INT bitRate) { + INT codebits = bitRate; + int el; + + /* Copy Element info */ + for (el = 0; el < channelMapping->nElements; el++) { + sbrElInfo[el].ChannelIndex[0] = channelMapping->elInfo[el].ChannelIndex[0]; + sbrElInfo[el].ChannelIndex[1] = channelMapping->elInfo[el].ChannelIndex[1]; + sbrElInfo[el].elType = channelMapping->elInfo[el].elType; + sbrElInfo[el].bitRate = + fMultIfloor(channelMapping->elInfo[el].relativeBits, bitRate); + sbrElInfo[el].instanceTag = channelMapping->elInfo[el].instanceTag; + sbrElInfo[el].nChannelsInEl = channelMapping->elInfo[el].nChannelsInEl; + sbrElInfo[el].fParametricStereo = 0; + sbrElInfo[el].fDualMono = 0; + + codebits -= sbrElInfo[el].bitRate; + } + sbrElInfo[0].bitRate += codebits; +} + +static INT aacEncoder_LimitBitrate(const HANDLE_TRANSPORTENC hTpEnc, + const INT samplingRate, + const INT frameLength, const INT nChannels, + const CHANNEL_MODE channelMode, INT bitRate, + const INT nSubFrames, const INT sbrActive, + const INT sbrDownSampleRate, + const UINT syntaxFlags, + const AUDIO_OBJECT_TYPE aot) { + INT coreSamplingRate; + CHANNEL_MAPPING cm; + + FDKaacEnc_InitChannelMapping(channelMode, CH_ORDER_MPEG, &cm); + + if (sbrActive) { + coreSamplingRate = + samplingRate >> + (sbrEncoder_IsSingleRatePossible(aot) ? (sbrDownSampleRate - 1) : 1); + } else { + coreSamplingRate = samplingRate; + } + + /* Limit bit rate in respect to the core coder */ + bitRate = FDKaacEnc_LimitBitrate(hTpEnc, aot, coreSamplingRate, frameLength, + nChannels, cm.nChannelsEff, bitRate, -1, + NULL, AACENC_BR_MODE_INVALID, nSubFrames); + + /* Limit bit rate in respect to available SBR modes if active */ + if (sbrActive) { + int numIterations = 0; + INT initialBitrate, adjustedBitrate; + adjustedBitrate = bitRate; + + /* Find total bitrate which provides valid configuration for each SBR + * element. */ + do { + int e; + SBR_ELEMENT_INFO sbrElInfo[((8))]; + FDK_ASSERT(cm.nElements <= ((8))); + + initialBitrate = adjustedBitrate; + + /* Get bit rate for each SBR element */ + aacEncDistributeSbrBits(&cm, sbrElInfo, initialBitrate); + + for (e = 0; e < cm.nElements; e++) { + INT sbrElementBitRateIn, sbrBitRateOut; + + if (cm.elInfo[e].elType != ID_SCE && cm.elInfo[e].elType != ID_CPE) { + continue; + } + sbrElementBitRateIn = sbrElInfo[e].bitRate; + + sbrBitRateOut = sbrEncoder_LimitBitRate(sbrElementBitRateIn, + cm.elInfo[e].nChannelsInEl, + coreSamplingRate, aot); + + if (sbrBitRateOut == 0) { + return 0; + } + + /* If bitrates don't match, distribution and limiting needs to be + determined again. Abort element loop and restart with adapted + bitrate. */ + if (sbrElementBitRateIn != sbrBitRateOut) { + if (sbrElementBitRateIn < sbrBitRateOut) { + adjustedBitrate = fMax(initialBitrate, + (INT)fDivNorm((FIXP_DBL)(sbrBitRateOut + 8), + cm.elInfo[e].relativeBits)); + break; + } + + if (sbrElementBitRateIn > sbrBitRateOut) { + adjustedBitrate = fMin(initialBitrate, + (INT)fDivNorm((FIXP_DBL)(sbrBitRateOut - 8), + cm.elInfo[e].relativeBits)); + break; + } + + } /* sbrElementBitRateIn != sbrBitRateOut */ + + } /* elements */ + + numIterations++; /* restrict iteration to worst case of num elements */ + + } while ((initialBitrate != adjustedBitrate) && + (numIterations <= cm.nElements)); + + /* Unequal bitrates mean that no reasonable bitrate configuration found. */ + bitRate = (initialBitrate == adjustedBitrate) ? adjustedBitrate : 0; + } + + /* Limit bit rate in respect to available MPS modes if active */ + if ((aot == AOT_ER_AAC_ELD) && (syntaxFlags & AC_LD_MPS) && + (channelMode == MODE_1)) { + bitRate = FDK_MpegsEnc_GetClosestBitRate( + aot, MODE_212, samplingRate, (sbrActive) ? sbrDownSampleRate : 0, + bitRate); + } + + return bitRate; +} + +/* + * \brief Get CBR bitrate + * + * \hAacConfig Internal encoder config + * \return Bitrate + */ +static INT FDKaacEnc_GetCBRBitrate(const HANDLE_AACENC_CONFIG hAacConfig, + const INT userSbrRatio) { + INT bitrate = FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode) + ->nChannelsEff * + hAacConfig->sampleRate; + + if (isPsActive(hAacConfig->audioObjectType)) { + bitrate = 1 * bitrate; /* 0.5 bit per sample */ + } else if (isSbrActive(hAacConfig)) { + if ((userSbrRatio == 2) || + ((userSbrRatio == 0) && + (hAacConfig->audioObjectType != AOT_ER_AAC_ELD))) { + bitrate = (bitrate + (bitrate >> 2)) >> 1; /* 0.625 bits per sample */ + } + if ((userSbrRatio == 1) || + ((userSbrRatio == 0) && + (hAacConfig->audioObjectType == AOT_ER_AAC_ELD))) { + bitrate = (bitrate + (bitrate >> 3)); /* 1.125 bits per sample */ + } + } else { + bitrate = bitrate + (bitrate >> 1); /* 1.5 bits per sample */ + } + + return bitrate; +} + +/* + * \brief Consistency check of given USER_PARAM struct and + * copy back configuration from public struct into internal + * encoder configuration struct. + * + * \hAacEncoder Internal encoder config which is to be updated + * \param config User provided config (public struct) + * \return returns always AAC_ENC_OK + */ +static AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, + USER_PARAM *config) { + AACENC_ERROR err = AACENC_OK; + + /* Get struct pointers. */ + HANDLE_AACENC_CONFIG hAacConfig = &hAacEncoder->aacConfig; + + /* Encoder settings update. */ + hAacConfig->sampleRate = config->userSamplerate; + if (config->userDownscaleFactor > 1) { + hAacConfig->useTns = 0; + hAacConfig->usePns = 0; + hAacConfig->useIS = 0; + } else { + hAacConfig->useTns = config->userTns; + hAacConfig->usePns = config->userPns; + hAacConfig->useIS = config->userIntensity; + } + + hAacConfig->audioObjectType = config->userAOT; + hAacConfig->channelMode = + GetCoreChannelMode(config->userChannelMode, hAacConfig->audioObjectType); + hAacConfig->nChannels = + FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode)->nChannels; + hAacConfig->bitrateMode = (AACENC_BITRATE_MODE)config->userBitrateMode; + hAacConfig->bandWidth = config->userBandwidth; + hAacConfig->useRequant = config->userAfterburner; + + hAacConfig->anc_Rate = config->userAncDataRate; + hAacConfig->syntaxFlags = 0; + hAacConfig->epConfig = -1; + + if (hAacConfig->audioObjectType != AOT_ER_AAC_ELD && + config->userDownscaleFactor > 1) { + return AACENC_INVALID_CONFIG; /* downscaling only allowed for AOT_ER_AAC_ELD + */ + } + if (config->userDownscaleFactor > 1 && config->userSbrEnabled == 1) { + return AACENC_INVALID_CONFIG; /* downscaling only allowed for AOT_ER_AAC_ELD + w/o SBR */ + } + if (config->userDownscaleFactor > 1 && config->userChannelMode == 128) { + return AACENC_INVALID_CONFIG; /* disallow downscaling for AAC-ELDv2 */ + } + + if (config->userTpType == TT_MP4_LATM_MCP1 || + config->userTpType == TT_MP4_LATM_MCP0 || + config->userTpType == TT_MP4_LOAS) { + hAacConfig->audioMuxVersion = config->userTpAmxv; + } else { + hAacConfig->audioMuxVersion = -1; + } + + /* Adapt internal AOT when necessary. */ + switch (config->userAOT) { + case AOT_MP2_AAC_LC: + case AOT_MP2_SBR: + hAacConfig->usePns = 0; + FDK_FALLTHROUGH; + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + config->userTpType = + (config->userTpType != TT_UNKNOWN) ? config->userTpType : TT_MP4_ADTS; + hAacConfig->framelength = (config->userFramelength != (UINT)-1) + ? config->userFramelength + : 1024; + if (hAacConfig->framelength != 1024 && hAacConfig->framelength != 960) { + return AACENC_INVALID_CONFIG; + } + break; + case AOT_ER_AAC_LD: + hAacConfig->epConfig = 0; + hAacConfig->syntaxFlags |= AC_ER | AC_LD; + hAacConfig->syntaxFlags |= + ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x4) ? AC_ER_RVLC : 0); + config->userTpType = + (config->userTpType != TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS; + hAacConfig->framelength = + (config->userFramelength != (UINT)-1) ? config->userFramelength : 512; + if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480) { + return AACENC_INVALID_CONFIG; + } + break; + case AOT_ER_AAC_ELD: + hAacConfig->epConfig = 0; + hAacConfig->syntaxFlags |= AC_ER | AC_ELD; + hAacConfig->syntaxFlags |= + ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x4) ? AC_ER_RVLC : 0); + hAacConfig->syntaxFlags |= + ((config->userSbrEnabled == 1) ? AC_SBR_PRESENT : 0); + hAacConfig->syntaxFlags |= + ((config->userChannelMode == MODE_212) ? AC_LD_MPS : 0); + config->userTpType = + (config->userTpType != TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS; + hAacConfig->framelength = + (config->userFramelength != (UINT)-1) ? config->userFramelength : 512; + + hAacConfig->downscaleFactor = config->userDownscaleFactor; + + switch (config->userDownscaleFactor) { + case 1: + break; + case 2: + case 4: + hAacConfig->syntaxFlags |= AC_ELD_DOWNSCALE; + break; + default: + return AACENC_INVALID_CONFIG; + } + + if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480 && + hAacConfig->framelength != 256 && hAacConfig->framelength != 240 && + hAacConfig->framelength != 128 && hAacConfig->framelength != 120) { + return AACENC_INVALID_CONFIG; + } + break; + default: + break; + } + + /* Initialize SBR parameters */ + if ((config->userSbrRatio == 0) && (isSbrActive(hAacConfig))) { + /* Automatic SBR ratio configuration + * - downsampled SBR for ELD + * - otherwise always dualrate SBR + */ + if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) { + hAacConfig->sbrRatio = ((hAacConfig->syntaxFlags & AC_LD_MPS) && + (hAacConfig->sampleRate >= 27713)) + ? 2 + : 1; + } else { + hAacConfig->sbrRatio = 2; + } + } else { + /* SBR ratio has been set by the user, so use it. */ + hAacConfig->sbrRatio = isSbrActive(hAacConfig) ? config->userSbrRatio : 0; + } + + /* Set default bitrate */ + hAacConfig->bitRate = config->userBitrate; + + switch (hAacConfig->bitrateMode) { + case AACENC_BR_MODE_CBR: + /* Set default bitrate if no external bitrate declared. */ + if (config->userBitrate == (UINT)-1) { + hAacConfig->bitRate = + FDKaacEnc_GetCBRBitrate(hAacConfig, config->userSbrRatio); + } + hAacConfig->averageBits = -1; + break; + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + /* Adjust bitrate mode in case given peak bitrate is lower than expected + * VBR bitrate. */ + if ((INT)config->userPeakBitrate != -1) { + hAacConfig->bitrateMode = FDKaacEnc_AdjustVBRBitrateMode( + hAacConfig->bitrateMode, config->userPeakBitrate, + hAacConfig->channelMode); + } + /* Get bitrate in VBR configuration */ + /* In VBR mode; SBR-modul depends on bitrate, core encoder on bitrateMode. + */ + hAacConfig->bitRate = FDKaacEnc_GetVBRBitrate(hAacConfig->bitrateMode, + hAacConfig->channelMode); + break; + default: + return AACENC_INVALID_CONFIG; + } + + /* set bitreservoir size */ + switch (hAacConfig->bitrateMode) { + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + case AACENC_BR_MODE_CBR: + if ((INT)config->userPeakBitrate != -1) { + hAacConfig->maxBitsPerFrame = + (FDKaacEnc_CalcBitsPerFrame( + fMax(hAacConfig->bitRate, (INT)config->userPeakBitrate), + hAacConfig->framelength, hAacConfig->sampleRate) + + 7) & + ~7; + } else { + hAacConfig->maxBitsPerFrame = -1; + } + if (hAacConfig->audioMuxVersion == 2) { + hAacConfig->minBitsPerFrame = + fMin(32 * 8, FDKaacEnc_CalcBitsPerFrame(hAacConfig->bitRate, + hAacConfig->framelength, + hAacConfig->sampleRate)) & + ~7; + } + break; + default: + return AACENC_INVALID_CONFIG; + } + + /* Max bits per frame limitation depending on transport format. */ + if ((config->userTpNsubFrames > 1)) { + int maxFrameLength = 8 * hAacEncoder->outBufferInBytes; + switch (config->userTpType) { + case TT_MP4_LOAS: + maxFrameLength = + fMin(maxFrameLength, 8 * (1 << 13)) / config->userTpNsubFrames; + break; + case TT_MP4_ADTS: + maxFrameLength = fMin(maxFrameLength, 8 * ((1 << 13) - 1)) / + config->userTpNsubFrames; + break; + default: + maxFrameLength = -1; + } + if (maxFrameLength != -1) { + if (hAacConfig->maxBitsPerFrame > maxFrameLength) { + return AACENC_INVALID_CONFIG; + } else if (hAacConfig->maxBitsPerFrame == -1) { + hAacConfig->maxBitsPerFrame = maxFrameLength; + } + } + } + + if ((hAacConfig->audioObjectType == AOT_ER_AAC_ELD) && + !(hAacConfig->syntaxFlags & AC_ELD_DOWNSCALE) && + (config->userSbrEnabled == (UCHAR)-1) && (config->userSbrRatio == 0) && + ((hAacConfig->syntaxFlags & AC_LD_MPS) == 0)) { + const ELD_SBR_CONFIGURATOR *pConfig = NULL; + + if (NULL != + (pConfig = eldSbrConfigurator( + FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode) + ->nChannels, + hAacConfig->sampleRate, hAacConfig->bitRate))) { + hAacConfig->syntaxFlags |= (pConfig->sbrMode == 0) ? 0 : AC_SBR_PRESENT; + hAacConfig->syntaxFlags |= (pConfig->chMode == MODE_212) ? AC_LD_MPS : 0; + hAacConfig->channelMode = + GetCoreChannelMode(pConfig->chMode, hAacConfig->audioObjectType); + hAacConfig->nChannels = + FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode) + ->nChannels; + hAacConfig->sbrRatio = + (pConfig->sbrMode == 0) ? 0 : (pConfig->sbrMode == 1) ? 1 : 2; + } + } + + { + UCHAR tpSignaling = + getSbrSignalingMode(hAacConfig->audioObjectType, config->userTpType, + config->userTpSignaling, hAacConfig->sbrRatio); + + if ((hAacConfig->audioObjectType == AOT_AAC_LC || + hAacConfig->audioObjectType == AOT_SBR || + hAacConfig->audioObjectType == AOT_PS) && + (config->userTpType == TT_MP4_LATM_MCP1 || + config->userTpType == TT_MP4_LATM_MCP0 || + config->userTpType == TT_MP4_LOAS) && + (tpSignaling == 1) && (config->userTpAmxv == 0)) { + /* For backward compatible explicit signaling, AMV1 has to be active */ + return AACENC_INVALID_CONFIG; + } + + if ((hAacConfig->audioObjectType == AOT_AAC_LC || + hAacConfig->audioObjectType == AOT_SBR || + hAacConfig->audioObjectType == AOT_PS) && + (tpSignaling == 0) && (hAacConfig->sbrRatio == 1)) { + /* Downsampled SBR has to be signaled explicitely (for transmission of SBR + * sampling fequency) */ + return AACENC_INVALID_CONFIG; + } + } + + switch (hAacConfig->bitrateMode) { + case AACENC_BR_MODE_CBR: + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + /* We need the frame length to call aacEncoder_LimitBitrate() */ + if (0 >= (hAacConfig->bitRate = aacEncoder_LimitBitrate( + NULL, hAacConfig->sampleRate, hAacConfig->framelength, + hAacConfig->nChannels, hAacConfig->channelMode, + hAacConfig->bitRate, hAacConfig->nSubFrames, + isSbrActive(hAacConfig), hAacConfig->sbrRatio, + hAacConfig->syntaxFlags, hAacConfig->audioObjectType))) { + return AACENC_INVALID_CONFIG; + } + break; + default: + break; + } + + /* Configure PNS */ + if (AACENC_BR_MODE_IS_VBR(hAacConfig->bitrateMode) /* VBR without PNS. */ + || (hAacConfig->useTns == 0)) /* TNS required. */ + { + hAacConfig->usePns = 0; + } + + if (hAacConfig->epConfig >= 0) { + hAacConfig->syntaxFlags |= AC_ER; + if (((INT)hAacConfig->channelMode < 1) || + ((INT)hAacConfig->channelMode > 14)) { + return AACENC_INVALID_CONFIG; /* Channel config 0 not supported. */ + } + } + + if ((hAacConfig->syntaxFlags & AC_LD_MPS) == 0) { + if (FDKaacEnc_DetermineEncoderMode(&hAacConfig->channelMode, + hAacConfig->nChannels) != AAC_ENC_OK) { + return AACENC_INVALID_CONFIG; /* nChannels doesn't match chMode, this is + just a check-up */ + } + } + + if ((hAacConfig->nChannels > hAacEncoder->nMaxAacChannels) || + ((FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode) + ->nChannelsEff > hAacEncoder->nMaxSbrChannels) && + isSbrActive(hAacConfig))) { + return AACENC_INVALID_CONFIG; /* not enough channels allocated */ + } + + /* Meta data restriction. */ + switch (hAacConfig->audioObjectType) { + /* Allow metadata support */ + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_MP2_AAC_LC: + case AOT_MP2_SBR: + hAacEncoder->metaDataAllowed = 1; + if (!((((INT)hAacConfig->channelMode >= 1) && + ((INT)hAacConfig->channelMode <= 14)) || + (MODE_7_1_REAR_SURROUND == hAacConfig->channelMode) || + (MODE_7_1_FRONT_CENTER == hAacConfig->channelMode))) { + config->userMetaDataMode = 0; + } + break; + /* Prohibit metadata support */ + default: + hAacEncoder->metaDataAllowed = 0; + } + + return err; +} + +static INT aacenc_SbrCallback(void *self, HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, + const INT elementIndex, const UCHAR harmonicSbr, + const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor) { + HANDLE_AACENCODER hAacEncoder = (HANDLE_AACENCODER)self; + + sbrEncoder_GetHeader(hAacEncoder->hEnvEnc, hBs, elementIndex, 0); + + return 0; +} + +INT aacenc_SscCallback(void *self, HANDLE_FDK_BITSTREAM hBs, + const AUDIO_OBJECT_TYPE coreCodec, + const INT samplingRate, const INT frameSize, + const INT numChannels, const INT stereoConfigIndex, + const INT coreSbrFrameLengthIndex, const INT configBytes, + const UCHAR configMode, UCHAR *configChanged) { + HANDLE_AACENCODER hAacEncoder = (HANDLE_AACENCODER)self; + + return (FDK_MpegsEnc_WriteSpatialSpecificConfig(hAacEncoder->hMpsEnc, hBs)); +} + +static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder, ULONG InitFlags, + USER_PARAM *config) { + AACENC_ERROR err = AACENC_OK; + + INT aacBufferOffset = 0; + HANDLE_SBR_ENCODER *hSbrEncoder = &hAacEncoder->hEnvEnc; + HANDLE_AACENC_CONFIG hAacConfig = &hAacEncoder->aacConfig; + + hAacEncoder->nZerosAppended = 0; /* count appended zeros */ + + INT frameLength = hAacConfig->framelength; + + if ((InitFlags & AACENC_INIT_CONFIG)) { + CHANNEL_MODE prevChMode = hAacConfig->channelMode; + + /* Verify settings and update: config -> heAacEncoder */ + if ((err = FDKaacEnc_AdjustEncSettings(hAacEncoder, config)) != AACENC_OK) { + return err; + } + frameLength = hAacConfig->framelength; /* adapt temporal framelength */ + + /* Seamless channel reconfiguration in sbr not fully implemented */ + if ((prevChMode != hAacConfig->channelMode) && isSbrActive(hAacConfig)) { + InitFlags |= AACENC_INIT_STATES; + } + } + + /* Clear input buffer */ + if (InitFlags == AACENC_INIT_ALL) { + FDKmemclear(hAacEncoder->inputBuffer, + sizeof(INT_PCM) * hAacEncoder->inputBufferSize); + } + + if ((InitFlags & AACENC_INIT_CONFIG)) { + aacBufferOffset = 0; + switch (hAacConfig->audioObjectType) { + case AOT_ER_AAC_LD: + hAacEncoder->nDelay = DELAY_AACLD(hAacConfig->framelength); + break; + case AOT_ER_AAC_ELD: + hAacEncoder->nDelay = DELAY_AACELD(hAacConfig->framelength); + break; + default: + hAacEncoder->nDelay = + DELAY_AAC(hAacConfig->framelength); /* AAC encoder delay */ + } + + hAacConfig->ancDataBitRate = 0; + } + + if ((NULL != hAacEncoder->hEnvEnc) && isSbrActive(hAacConfig) && + ((InitFlags & AACENC_INIT_CONFIG) || (InitFlags & AACENC_INIT_STATES))) { + INT sbrError; + UINT initFlag = 0; + SBR_ELEMENT_INFO sbrElInfo[(8)]; + CHANNEL_MAPPING channelMapping; + CHANNEL_MODE channelMode = isPsActive(hAacConfig->audioObjectType) + ? config->userChannelMode + : hAacConfig->channelMode; + INT numChannels = isPsActive(hAacConfig->audioObjectType) + ? config->nChannels + : hAacConfig->nChannels; + + if (FDKaacEnc_InitChannelMapping(channelMode, hAacConfig->channelOrder, + &channelMapping) != AAC_ENC_OK) { + return AACENC_INIT_ERROR; + } + + /* Check return value and if the SBR encoder can handle enough elements */ + if (channelMapping.nElements > (8)) { + return AACENC_INIT_ERROR; + } + + aacEncDistributeSbrBits(&channelMapping, sbrElInfo, hAacConfig->bitRate); + + initFlag += (InitFlags & AACENC_INIT_STATES) ? 1 : 0; + + /* Let the SBR encoder take a look at the configuration and change if + * required. */ + sbrError = sbrEncoder_Init( + *hSbrEncoder, sbrElInfo, channelMapping.nElements, + hAacEncoder->inputBuffer, hAacEncoder->inputBufferSizePerChannel, + &hAacConfig->bandWidth, &aacBufferOffset, &numChannels, + hAacConfig->syntaxFlags, &hAacConfig->sampleRate, &hAacConfig->sbrRatio, + &frameLength, hAacConfig->audioObjectType, &hAacEncoder->nDelay, + (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) ? 1 : TRANS_FAC, + (config->userTpHeaderPeriod != 0xFF) + ? config->userTpHeaderPeriod + : DEFAULT_HEADER_PERIOD_REPETITION_RATE, + initFlag); + + /* Suppress AOT reconfiguration and check error status. */ + if ((sbrError) || (numChannels != hAacConfig->nChannels)) { + return AACENC_INIT_SBR_ERROR; + } + + if (numChannels == 1) { + hAacConfig->channelMode = MODE_1; + } + + /* Never use PNS if SBR is active */ + if (hAacConfig->usePns) { + hAacConfig->usePns = 0; + } + + /* estimated bitrate consumed by SBR or PS */ + hAacConfig->ancDataBitRate = sbrEncoder_GetEstimateBitrate(*hSbrEncoder); + + } /* sbr initialization */ + + if ((hAacEncoder->hMpsEnc != NULL) && (hAacConfig->syntaxFlags & AC_LD_MPS)) { + int coreCoderDelay = DELAY_AACELD(hAacConfig->framelength); + + if (isSbrActive(hAacConfig)) { + coreCoderDelay = hAacConfig->sbrRatio * coreCoderDelay + + sbrEncoder_GetInputDataDelay(*hSbrEncoder); + } + + if (MPS_ENCODER_OK != + FDK_MpegsEnc_Init(hAacEncoder->hMpsEnc, hAacConfig->audioObjectType, + config->userSamplerate, hAacConfig->bitRate, + isSbrActive(hAacConfig) ? hAacConfig->sbrRatio : 0, + frameLength, /* for dual rate sbr this value is + already multiplied by 2 */ + hAacEncoder->inputBufferSizePerChannel, + coreCoderDelay)) { + return AACENC_INIT_MPS_ERROR; + } + } + hAacEncoder->nDelay = + fMax(FDK_MpegsEnc_GetDelay(hAacEncoder->hMpsEnc), hAacEncoder->nDelay); + + /* + * Initialize Transport - Module. + */ + if ((InitFlags & AACENC_INIT_TRANSPORT)) { + UINT flags = 0; + + FDKaacEnc_MapConfig( + &hAacEncoder->coderConfig, config, + getSbrSignalingMode(hAacConfig->audioObjectType, config->userTpType, + config->userTpSignaling, hAacConfig->sbrRatio), + hAacConfig); + + /* create flags for transport encoder */ + if (config->userTpAmxv != 0) { + flags |= TP_FLAG_LATM_AMV; + } + /* Clear output buffer */ + FDKmemclear(hAacEncoder->outBuffer, + hAacEncoder->outBufferInBytes * sizeof(UCHAR)); + + /* Initialize Bitstream encoder */ + if (transportEnc_Init(hAacEncoder->hTpEnc, hAacEncoder->outBuffer, + hAacEncoder->outBufferInBytes, config->userTpType, + &hAacEncoder->coderConfig, flags) != 0) { + return AACENC_INIT_TP_ERROR; + } + + } /* transport initialization */ + + /* + * Initialize AAC - Core. + */ + if ((InitFlags & AACENC_INIT_CONFIG) || (InitFlags & AACENC_INIT_STATES)) { + if (FDKaacEnc_Initialize( + hAacEncoder->hAacEnc, hAacConfig, hAacEncoder->hTpEnc, + (InitFlags & AACENC_INIT_STATES) ? 1 : 0) != AAC_ENC_OK) { + return AACENC_INIT_AAC_ERROR; + } + + } /* aac initialization */ + + /* + * Initialize Meta Data - Encoder. + */ + if (hAacEncoder->hMetadataEnc && (hAacEncoder->metaDataAllowed != 0) && + ((InitFlags & AACENC_INIT_CONFIG) || (InitFlags & AACENC_INIT_STATES))) { + INT inputDataDelay = DELAY_AAC(hAacConfig->framelength); + + if (isSbrActive(hAacConfig) && hSbrEncoder != NULL) { + inputDataDelay = hAacConfig->sbrRatio * inputDataDelay + + sbrEncoder_GetInputDataDelay(*hSbrEncoder); + } + + if (FDK_MetadataEnc_Init(hAacEncoder->hMetadataEnc, + ((InitFlags & AACENC_INIT_STATES) ? 1 : 0), + config->userMetaDataMode, inputDataDelay, + frameLength, config->userSamplerate, + config->nChannels, config->userChannelMode, + hAacConfig->channelOrder) != 0) { + return AACENC_INIT_META_ERROR; + } + + hAacEncoder->nDelay += FDK_MetadataEnc_GetDelay(hAacEncoder->hMetadataEnc); + } + + /* Get custom delay, i.e. the codec delay w/o the decoder's SBR- or MPS delay + */ + if ((hAacEncoder->hMpsEnc != NULL) && (hAacConfig->syntaxFlags & AC_LD_MPS)) { + hAacEncoder->nDelayCore = + hAacEncoder->nDelay - + fMax(0, FDK_MpegsEnc_GetDecDelay(hAacEncoder->hMpsEnc)); + } else if (isSbrActive(hAacConfig) && hSbrEncoder != NULL) { + hAacEncoder->nDelayCore = + hAacEncoder->nDelay - + fMax(0, sbrEncoder_GetSbrDecDelay(hAacEncoder->hEnvEnc)); + } else { + hAacEncoder->nDelayCore = hAacEncoder->nDelay; + } + + /* + * Update pointer to working buffer. + */ + if ((InitFlags & AACENC_INIT_CONFIG)) { + hAacEncoder->inputBufferOffset = aacBufferOffset; + + hAacEncoder->nSamplesToRead = frameLength * config->nChannels; + + } /* parameter changed */ + + return AACENC_OK; +} + +AACENC_ERROR aacEncOpen(HANDLE_AACENCODER *phAacEncoder, const UINT encModules, + const UINT maxChannels) { + AACENC_ERROR err = AACENC_OK; + HANDLE_AACENCODER hAacEncoder = NULL; + + if (phAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + /* allocate memory */ + hAacEncoder = Get_AacEncoder(); + + if (hAacEncoder == NULL) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + FDKmemclear(hAacEncoder, sizeof(AACENCODER)); + + /* Specify encoder modules to be allocated. */ + if (encModules == 0) { + C_ALLOC_SCRATCH_START(_pLibInfo, LIB_INFO, FDK_MODULE_LAST) + LIB_INFO(*pLibInfo) + [FDK_MODULE_LAST] = (LIB_INFO(*)[FDK_MODULE_LAST])_pLibInfo; + FDKinitLibInfo(*pLibInfo); + aacEncGetLibInfo(*pLibInfo); + + hAacEncoder->encoder_modis = ENC_MODE_FLAG_AAC; + if (FDKlibInfo_getCapabilities(*pLibInfo, FDK_SBRENC) & CAPF_SBR_HQ) { + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_SBR; + } + if (FDKlibInfo_getCapabilities(*pLibInfo, FDK_SBRENC) & CAPF_SBR_PS_MPEG) { + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_PS; + } + if (FDKlibInfo_getCapabilities(*pLibInfo, FDK_AACENC) & CAPF_AAC_DRC) { + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_META; + } + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_SAC; + + C_ALLOC_SCRATCH_END(_pLibInfo, LIB_INFO, FDK_MODULE_LAST) + } else { + hAacEncoder->encoder_modis = encModules; + } + + /* Determine max channel configuration. */ + if (maxChannels == 0) { + hAacEncoder->nMaxAacChannels = (8); + hAacEncoder->nMaxSbrChannels = (8); + } else { + hAacEncoder->nMaxAacChannels = (maxChannels & 0x00FF); + if ((hAacEncoder->encoder_modis & ENC_MODE_FLAG_SBR)) { + hAacEncoder->nMaxSbrChannels = (maxChannels & 0xFF00) + ? (maxChannels >> 8) + : hAacEncoder->nMaxAacChannels; + } + + if ((hAacEncoder->nMaxAacChannels > (8)) || + (hAacEncoder->nMaxSbrChannels > (8))) { + err = AACENC_INVALID_CONFIG; + goto bail; + } + } /* maxChannels==0 */ + + /* Max number of elements could be tuned any more. */ + hAacEncoder->nMaxAacElements = fixMin(((8)), hAacEncoder->nMaxAacChannels); + hAacEncoder->nMaxSbrElements = fixMin((8), hAacEncoder->nMaxSbrChannels); + + /* In case of memory overlay, allocate memory out of libraries */ + + if (hAacEncoder->encoder_modis & (ENC_MODE_FLAG_SBR | ENC_MODE_FLAG_PS)) + hAacEncoder->inputBufferSizePerChannel = INPUTBUFFER_SIZE; + else + hAacEncoder->inputBufferSizePerChannel = (1024); + + hAacEncoder->inputBufferSize = + hAacEncoder->nMaxAacChannels * hAacEncoder->inputBufferSizePerChannel; + + if (NULL == (hAacEncoder->inputBuffer = (INT_PCM *)FDKcalloc( + hAacEncoder->inputBufferSize, sizeof(INT_PCM)))) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + /* Open SBR Encoder */ + if (hAacEncoder->encoder_modis & ENC_MODE_FLAG_SBR) { + if (sbrEncoder_Open( + &hAacEncoder->hEnvEnc, hAacEncoder->nMaxSbrElements, + hAacEncoder->nMaxSbrChannels, + (hAacEncoder->encoder_modis & ENC_MODE_FLAG_PS) ? 1 : 0)) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + if (NULL == (hAacEncoder->pSbrPayload = (SBRENC_EXT_PAYLOAD *)FDKcalloc( + 1, sizeof(SBRENC_EXT_PAYLOAD)))) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + } /* (encoder_modis&ENC_MODE_FLAG_SBR) */ + + /* Open Aac Encoder */ + if (FDKaacEnc_Open(&hAacEncoder->hAacEnc, hAacEncoder->nMaxAacElements, + hAacEncoder->nMaxAacChannels, (1)) != AAC_ENC_OK) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + /* Bitstream output buffer */ + hAacEncoder->outBufferInBytes = + 1 << (DFRACT_BITS - CntLeadingZeros(fixMax( + 1, ((1) * hAacEncoder->nMaxAacChannels * 6144) >> + 3))); /* buffer has to be 2^n */ + if (NULL == (hAacEncoder->outBuffer = (UCHAR *)FDKcalloc( + hAacEncoder->outBufferInBytes, sizeof(UCHAR)))) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + /* Open Meta Data Encoder */ + if (hAacEncoder->encoder_modis & ENC_MODE_FLAG_META) { + if (FDK_MetadataEnc_Open(&hAacEncoder->hMetadataEnc, + (UINT)hAacEncoder->nMaxAacChannels)) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + } /* (encoder_modis&ENC_MODE_FLAG_META) */ + + /* Open MPEG Surround Encoder */ + if (hAacEncoder->encoder_modis & ENC_MODE_FLAG_SAC) { + if (MPS_ENCODER_OK != FDK_MpegsEnc_Open(&hAacEncoder->hMpsEnc)) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + } /* (hAacEncoder->encoder_modis&ENC_MODE_FLAG_SAC) */ + + /* Open Transport Encoder */ + if (transportEnc_Open(&hAacEncoder->hTpEnc) != 0) { + err = AACENC_MEMORY_ERROR; + goto bail; + } else { + C_ALLOC_SCRATCH_START(_pLibInfo, LIB_INFO, FDK_MODULE_LAST) + + LIB_INFO(*pLibInfo) + [FDK_MODULE_LAST] = (LIB_INFO(*)[FDK_MODULE_LAST])_pLibInfo; + + FDKinitLibInfo(*pLibInfo); + transportEnc_GetLibInfo(*pLibInfo); + + /* Get capabilty flag for transport encoder. */ + hAacEncoder->CAPF_tpEnc = FDKlibInfo_getCapabilities(*pLibInfo, FDK_TPENC); + + C_ALLOC_SCRATCH_END(_pLibInfo, LIB_INFO, FDK_MODULE_LAST) + } + if (transportEnc_RegisterSbrCallback(hAacEncoder->hTpEnc, aacenc_SbrCallback, + hAacEncoder) != 0) { + err = AACENC_INIT_TP_ERROR; + goto bail; + } + if (transportEnc_RegisterSscCallback(hAacEncoder->hTpEnc, aacenc_SscCallback, + hAacEncoder) != 0) { + err = AACENC_INIT_TP_ERROR; + goto bail; + } + + /* Initialize encoder instance with default parameters. */ + aacEncDefaultConfig(&hAacEncoder->aacConfig, &hAacEncoder->extParam); + + /* Initialize headerPeriod in coderConfig for aacEncoder_GetParam(). */ + hAacEncoder->coderConfig.headerPeriod = + hAacEncoder->extParam.userTpHeaderPeriod; + + /* All encoder modules have to be initialized */ + hAacEncoder->InitFlags = AACENC_INIT_ALL; + + /* Return encoder instance */ + *phAacEncoder = hAacEncoder; + + return err; + +bail: + aacEncClose(&hAacEncoder); + + return err; +} + +AACENC_ERROR aacEncClose(HANDLE_AACENCODER *phAacEncoder) { + AACENC_ERROR err = AACENC_OK; + + if (phAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + if (*phAacEncoder != NULL) { + HANDLE_AACENCODER hAacEncoder = *phAacEncoder; + + if (hAacEncoder->inputBuffer != NULL) { + FDKfree(hAacEncoder->inputBuffer); + hAacEncoder->inputBuffer = NULL; + } + if (hAacEncoder->outBuffer != NULL) { + FDKfree(hAacEncoder->outBuffer); + hAacEncoder->outBuffer = NULL; + } + + if (hAacEncoder->hEnvEnc) { + sbrEncoder_Close(&hAacEncoder->hEnvEnc); + } + if (hAacEncoder->pSbrPayload != NULL) { + FDKfree(hAacEncoder->pSbrPayload); + hAacEncoder->pSbrPayload = NULL; + } + if (hAacEncoder->hAacEnc) { + FDKaacEnc_Close(&hAacEncoder->hAacEnc); + } + + transportEnc_Close(&hAacEncoder->hTpEnc); + + if (hAacEncoder->hMetadataEnc) { + FDK_MetadataEnc_Close(&hAacEncoder->hMetadataEnc); + } + if (hAacEncoder->hMpsEnc) { + FDK_MpegsEnc_Close(&hAacEncoder->hMpsEnc); + } + + Free_AacEncoder(phAacEncoder); + } + +bail: + return err; +} + +AACENC_ERROR aacEncEncode(const HANDLE_AACENCODER hAacEncoder, + const AACENC_BufDesc *inBufDesc, + const AACENC_BufDesc *outBufDesc, + const AACENC_InArgs *inargs, + AACENC_OutArgs *outargs) { + AACENC_ERROR err = AACENC_OK; + INT i, nBsBytes = 0; + INT outBytes[(1)]; + int nExtensions = 0; + int ancDataExtIdx = -1; + + /* deal with valid encoder handle */ + if (hAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + /* + * Adjust user settings and trigger reinitialization. + */ + if (hAacEncoder->InitFlags != 0) { + err = + aacEncInit(hAacEncoder, hAacEncoder->InitFlags, &hAacEncoder->extParam); + + if (err != AACENC_OK) { + /* keep init flags alive! */ + goto bail; + } + hAacEncoder->InitFlags = AACENC_INIT_NONE; + } + + if (outargs != NULL) { + FDKmemclear(outargs, sizeof(AACENC_OutArgs)); + } + + if (outBufDesc != NULL) { + for (i = 0; i < outBufDesc->numBufs; i++) { + if (outBufDesc->bufs[i] != NULL) { + FDKmemclear(outBufDesc->bufs[i], outBufDesc->bufSizes[i]); + } + } + } + + /* + * If only encoder handle given, independent (re)initialization can be + * triggered. + */ + if ((inBufDesc == NULL) && (outBufDesc == NULL) && (inargs == NULL) && + (outargs == NULL)) { + goto bail; + } + + /* check if buffer descriptors are filled out properly. */ + if ((inargs == NULL) || (outargs == NULL) || + ((AACENC_OK != validateBufDesc(inBufDesc)) && + (inargs->numInSamples > 0)) || + (AACENC_OK != validateBufDesc(outBufDesc))) { + err = AACENC_UNSUPPORTED_PARAMETER; + goto bail; + } + + /* reset buffer wich signals number of valid bytes in output bitstream buffer + */ + FDKmemclear(outBytes, hAacEncoder->aacConfig.nSubFrames * sizeof(INT)); + + /* + * Manage incoming audio samples. + */ + if ((inBufDesc != NULL) && (inargs->numInSamples > 0) && + (getBufDescIdx(inBufDesc, IN_AUDIO_DATA) != -1)) { + /* Fetch data until nSamplesToRead reached */ + INT idx = getBufDescIdx(inBufDesc, IN_AUDIO_DATA); + INT newSamples = + fixMax(0, fixMin(inargs->numInSamples, hAacEncoder->nSamplesToRead - + hAacEncoder->nSamplesRead)); + INT_PCM *pIn = + hAacEncoder->inputBuffer + + hAacEncoder->inputBufferOffset / hAacEncoder->aacConfig.nChannels + + hAacEncoder->nSamplesRead / hAacEncoder->extParam.nChannels; + newSamples -= + (newSamples % + hAacEncoder->extParam + .nChannels); /* process multiple samples of input channels */ + + /* Copy new input samples to internal buffer */ + if (inBufDesc->bufElSizes[idx] == (INT)sizeof(INT_PCM)) { + FDK_deinterleave((INT_PCM *)inBufDesc->bufs[idx], pIn, + hAacEncoder->extParam.nChannels, + newSamples / hAacEncoder->extParam.nChannels, + hAacEncoder->inputBufferSizePerChannel); + } else if (inBufDesc->bufElSizes[idx] > (INT)sizeof(INT_PCM)) { + FDK_deinterleave((LONG *)inBufDesc->bufs[idx], pIn, + hAacEncoder->extParam.nChannels, + newSamples / hAacEncoder->extParam.nChannels, + hAacEncoder->inputBufferSizePerChannel); + } else { + FDK_deinterleave((SHORT *)inBufDesc->bufs[idx], pIn, + hAacEncoder->extParam.nChannels, + newSamples / hAacEncoder->extParam.nChannels, + hAacEncoder->inputBufferSizePerChannel); + } + hAacEncoder->nSamplesRead += newSamples; + + /* Number of fetched input buffer samples. */ + outargs->numInSamples = newSamples; + } + + /* input buffer completely filled ? */ + if (hAacEncoder->nSamplesRead < hAacEncoder->nSamplesToRead) { + /* - eof reached and flushing enabled, or + - return to main and wait for further incoming audio samples */ + if (inargs->numInSamples == -1) { + if ((hAacEncoder->nZerosAppended < hAacEncoder->nDelay)) { + int nZeros = (hAacEncoder->nSamplesToRead - hAacEncoder->nSamplesRead) / + hAacEncoder->extParam.nChannels; + + FDK_ASSERT(nZeros >= 0); + + /* clear out until end-of-buffer */ + if (nZeros) { + INT_PCM *pIn = + hAacEncoder->inputBuffer + + hAacEncoder->inputBufferOffset / + hAacEncoder->aacConfig.nChannels + + hAacEncoder->nSamplesRead / hAacEncoder->extParam.nChannels; + for (i = 0; i < (int)hAacEncoder->extParam.nChannels; i++) { + FDKmemclear(pIn + i * hAacEncoder->inputBufferSizePerChannel, + sizeof(INT_PCM) * nZeros); + } + hAacEncoder->nZerosAppended += nZeros; + hAacEncoder->nSamplesRead = hAacEncoder->nSamplesToRead; + } + } else { /* flushing completed */ + err = AACENC_ENCODE_EOF; /* eof reached */ + goto bail; + } + } else { /* inargs->numInSamples!= -1 */ + goto bail; /* not enough samples in input buffer and no flushing enabled + */ + } + } + + /* init payload */ + FDKmemclear(hAacEncoder->extPayload, + sizeof(AACENC_EXT_PAYLOAD) * MAX_TOTAL_EXT_PAYLOADS); + for (i = 0; i < MAX_TOTAL_EXT_PAYLOADS; i++) { + hAacEncoder->extPayload[i].associatedChElement = -1; + } + if (hAacEncoder->pSbrPayload != NULL) { + FDKmemclear(hAacEncoder->pSbrPayload, sizeof(*hAacEncoder->pSbrPayload)); + } + + /* + * Calculate Meta Data info. + */ + if ((hAacEncoder->hMetadataEnc != NULL) && + (hAacEncoder->metaDataAllowed != 0)) { + const AACENC_MetaData *pMetaData = NULL; + AACENC_EXT_PAYLOAD *pMetaDataExtPayload = NULL; + UINT nMetaDataExtensions = 0; + INT matrix_mixdown_idx = 0; + + /* New meta data info available ? */ + if (getBufDescIdx(inBufDesc, IN_METADATA_SETUP) != -1) { + pMetaData = + (AACENC_MetaData *) + inBufDesc->bufs[getBufDescIdx(inBufDesc, IN_METADATA_SETUP)]; + } + + FDK_MetadataEnc_Process( + hAacEncoder->hMetadataEnc, + hAacEncoder->inputBuffer + hAacEncoder->inputBufferOffset / + hAacEncoder->coderConfig.noChannels, + hAacEncoder->inputBufferSizePerChannel, hAacEncoder->nSamplesRead, + pMetaData, &pMetaDataExtPayload, &nMetaDataExtensions, + &matrix_mixdown_idx); + + for (i = 0; i < (INT)nMetaDataExtensions; + i++) { /* Get meta data extension payload. */ + hAacEncoder->extPayload[nExtensions++] = pMetaDataExtPayload[i]; + } + + if ((matrix_mixdown_idx != -1) && + ((hAacEncoder->extParam.userChannelMode == MODE_1_2_2) || + (hAacEncoder->extParam.userChannelMode == MODE_1_2_2_1))) { + /* Set matrix mixdown coefficient. */ + UINT pceValue = (UINT)((0 << 3) | ((matrix_mixdown_idx & 0x3) << 1) | 1); + if (hAacEncoder->extParam.userPceAdditions != pceValue) { + hAacEncoder->extParam.userPceAdditions = pceValue; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + } + } + + /* + * Encode MPS data. + */ + if ((hAacEncoder->hMpsEnc != NULL) && + (hAacEncoder->aacConfig.syntaxFlags & AC_LD_MPS)) { + AACENC_EXT_PAYLOAD mpsExtensionPayload; + FDKmemclear(&mpsExtensionPayload, sizeof(AACENC_EXT_PAYLOAD)); + + if (MPS_ENCODER_OK != + FDK_MpegsEnc_Process( + hAacEncoder->hMpsEnc, + hAacEncoder->inputBuffer + hAacEncoder->inputBufferOffset / + hAacEncoder->coderConfig.noChannels, + hAacEncoder->nSamplesRead, &mpsExtensionPayload)) { + err = AACENC_ENCODE_ERROR; + goto bail; + } + + if ((mpsExtensionPayload.pData != NULL) && + ((mpsExtensionPayload.dataSize != 0))) { + hAacEncoder->extPayload[nExtensions++] = mpsExtensionPayload; + } + } + + if ((NULL != hAacEncoder->hEnvEnc) && (NULL != hAacEncoder->pSbrPayload) && + isSbrActive(&hAacEncoder->aacConfig)) { + INT nPayload = 0; + + /* + * Encode SBR data. + */ + if (sbrEncoder_EncodeFrame(hAacEncoder->hEnvEnc, hAacEncoder->inputBuffer, + hAacEncoder->inputBufferSizePerChannel, + hAacEncoder->pSbrPayload->dataSize[nPayload], + hAacEncoder->pSbrPayload->data[nPayload])) { + err = AACENC_ENCODE_ERROR; + goto bail; + } else { + /* Add SBR extension payload */ + for (i = 0; i < (8); i++) { + if (hAacEncoder->pSbrPayload->dataSize[nPayload][i] > 0) { + hAacEncoder->extPayload[nExtensions].pData = + hAacEncoder->pSbrPayload->data[nPayload][i]; + { + hAacEncoder->extPayload[nExtensions].dataSize = + hAacEncoder->pSbrPayload->dataSize[nPayload][i]; + hAacEncoder->extPayload[nExtensions].associatedChElement = + getAssociatedChElement( + &hAacEncoder->hEnvEnc->sbrElement[i]->elInfo, + &hAacEncoder->hAacEnc->channelMapping); + if (hAacEncoder->extPayload[nExtensions].associatedChElement == + -1) { + err = AACENC_ENCODE_ERROR; + goto bail; + } + } + hAacEncoder->extPayload[nExtensions].dataType = + EXT_SBR_DATA; /* Once SBR Encoder supports SBR CRC set + EXT_SBR_DATA_CRC */ + nExtensions++; /* or EXT_SBR_DATA according to configuration. */ + FDK_ASSERT(nExtensions <= MAX_TOTAL_EXT_PAYLOADS); + } + } + nPayload++; + } + } /* sbrEnabled */ + + if ((inargs->numAncBytes > 0) && + (getBufDescIdx(inBufDesc, IN_ANCILLRY_DATA) != -1)) { + INT idx = getBufDescIdx(inBufDesc, IN_ANCILLRY_DATA); + hAacEncoder->extPayload[nExtensions].dataSize = inargs->numAncBytes * 8; + hAacEncoder->extPayload[nExtensions].pData = (UCHAR *)inBufDesc->bufs[idx]; + hAacEncoder->extPayload[nExtensions].dataType = EXT_DATA_ELEMENT; + hAacEncoder->extPayload[nExtensions].associatedChElement = -1; + ancDataExtIdx = nExtensions; /* store index */ + nExtensions++; + } + + /* + * Encode AAC - Core. + */ + if (FDKaacEnc_EncodeFrame(hAacEncoder->hAacEnc, hAacEncoder->hTpEnc, + hAacEncoder->inputBuffer, + hAacEncoder->inputBufferSizePerChannel, outBytes, + hAacEncoder->extPayload) != AAC_ENC_OK) { + err = AACENC_ENCODE_ERROR; + goto bail; + } + + if (ancDataExtIdx >= 0) { + outargs->numAncBytes = + inargs->numAncBytes - + (hAacEncoder->extPayload[ancDataExtIdx].dataSize >> 3); + } + + /* samples exhausted */ + hAacEncoder->nSamplesRead -= hAacEncoder->nSamplesToRead; + + /* + * Delay balancing buffer handling + */ + if (isSbrActive(&hAacEncoder->aacConfig)) { + sbrEncoder_UpdateBuffers(hAacEncoder->hEnvEnc, hAacEncoder->inputBuffer, + hAacEncoder->inputBufferSizePerChannel); + } + + /* + * Make bitstream public + */ + if ((outBufDesc != NULL) && (outBufDesc->numBufs >= 1)) { + INT bsIdx = getBufDescIdx(outBufDesc, OUT_BITSTREAM_DATA); + INT auIdx = getBufDescIdx(outBufDesc, OUT_AU_SIZES); + + for (i = 0, nBsBytes = 0; i < hAacEncoder->aacConfig.nSubFrames; i++) { + nBsBytes += outBytes[i]; + + if (auIdx != -1) { + ((INT *)outBufDesc->bufs[auIdx])[i] = outBytes[i]; + } + } + + if ((bsIdx != -1) && (outBufDesc->bufSizes[bsIdx] >= nBsBytes)) { + FDKmemcpy(outBufDesc->bufs[bsIdx], hAacEncoder->outBuffer, + sizeof(UCHAR) * nBsBytes); + outargs->numOutBytes = nBsBytes; + outargs->bitResState = + FDKaacEnc_GetBitReservoirState(hAacEncoder->hAacEnc); + } else { + /* output buffer too small, can't write valid bitstream */ + err = AACENC_ENCODE_ERROR; + goto bail; + } + } + +bail: + if (err == AACENC_ENCODE_ERROR) { + /* All encoder modules have to be initialized */ + hAacEncoder->InitFlags = AACENC_INIT_ALL; + } + + return err; +} + +static AAC_ENCODER_ERROR aacEncGetConf(HANDLE_AACENCODER hAacEncoder, + UINT *size, UCHAR *confBuffer) { + FDK_BITSTREAM tmpConf; + UINT confType; + UCHAR buf[64]; + int err; + + /* Init bit buffer */ + FDKinitBitStream(&tmpConf, buf, 64, 0, BS_WRITER); + + /* write conf in tmp buffer */ + err = transportEnc_GetConf(hAacEncoder->hTpEnc, &hAacEncoder->coderConfig, + &tmpConf, &confType); + + /* copy data to outbuffer: length in bytes */ + FDKbyteAlign(&tmpConf, 0); + + /* Check buffer size */ + if (FDKgetValidBits(&tmpConf) > ((*size) << 3)) return AAC_ENC_UNKNOWN; + + FDKfetchBuffer(&tmpConf, confBuffer, size); + + if (err != 0) + return AAC_ENC_UNKNOWN; + else + return AAC_ENC_OK; +} + +AACENC_ERROR aacEncGetLibInfo(LIB_INFO *info) { + int i = 0; + + if (info == NULL) { + return AACENC_INVALID_HANDLE; + } + + FDK_toolsGetLibInfo(info); + transportEnc_GetLibInfo(info); + sbrEncoder_GetLibInfo(info); + FDK_MpegsEnc_GetLibInfo(info); + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return AACENC_INIT_ERROR; + } + + info[i].module_id = FDK_AACENC; + info[i].build_date = AACENCODER_LIB_BUILD_DATE; + info[i].build_time = AACENCODER_LIB_BUILD_TIME; + info[i].title = AACENCODER_LIB_TITLE; + info[i].version = + LIB_VERSION(AACENCODER_LIB_VL0, AACENCODER_LIB_VL1, AACENCODER_LIB_VL2); + ; + LIB_VERSION_STRING(&info[i]); + + /* Capability flags */ + info[i].flags = 0 | CAPF_AAC_1024 | CAPF_AAC_LC | CAPF_AAC_512 | + CAPF_AAC_480 | CAPF_AAC_DRC | CAPF_AAC_ELD_DOWNSCALE; + /* End of flags */ + + return AACENC_OK; +} + +AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER hAacEncoder, + const AACENC_PARAM param, const UINT value) { + AACENC_ERROR err = AACENC_OK; + USER_PARAM *settings = &hAacEncoder->extParam; + + /* check encoder handle */ + if (hAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + /* apply param value */ + switch (param) { + case AACENC_AOT: + if (settings->userAOT != (AUDIO_OBJECT_TYPE)value) { + /* check if AOT matches the allocated modules */ + switch (value) { + case AOT_PS: + if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_PS))) { + err = AACENC_INVALID_CONFIG; + goto bail; + } + FDK_FALLTHROUGH; + case AOT_SBR: + case AOT_MP2_SBR: + if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_SBR))) { + err = AACENC_INVALID_CONFIG; + goto bail; + } + FDK_FALLTHROUGH; + case AOT_AAC_LC: + case AOT_MP2_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_AAC))) { + err = AACENC_INVALID_CONFIG; + goto bail; + } + break; + default: + err = AACENC_INVALID_CONFIG; + goto bail; + } /* switch value */ + settings->userAOT = (AUDIO_OBJECT_TYPE)value; + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_BITRATE: + if (settings->userBitrate != value) { + settings->userBitrate = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_BITRATEMODE: + if (settings->userBitrateMode != value) { + switch (value) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + settings->userBitrateMode = value; + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + break; + default: + err = AACENC_INVALID_CONFIG; + break; + } /* switch value */ + } + break; + case AACENC_SAMPLERATE: + if (settings->userSamplerate != value) { + if (!((value == 8000) || (value == 11025) || (value == 12000) || + (value == 16000) || (value == 22050) || (value == 24000) || + (value == 32000) || (value == 44100) || (value == 48000) || + (value == 64000) || (value == 88200) || (value == 96000))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userSamplerate = value; + hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */ + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_CHANNELMODE: + if (settings->userChannelMode != (CHANNEL_MODE)value) { + if (((CHANNEL_MODE)value == MODE_212) && + (NULL != hAacEncoder->hMpsEnc)) { + settings->userChannelMode = (CHANNEL_MODE)value; + settings->nChannels = 2; + } else { + const CHANNEL_MODE_CONFIG_TAB *pConfig = + FDKaacEnc_GetChannelModeConfiguration((CHANNEL_MODE)value); + if (pConfig == NULL) { + err = AACENC_INVALID_CONFIG; + break; + } + if ((pConfig->nElements > hAacEncoder->nMaxAacElements) || + (pConfig->nChannelsEff > hAacEncoder->nMaxAacChannels)) { + err = AACENC_INVALID_CONFIG; + break; + } + + settings->userChannelMode = (CHANNEL_MODE)value; + settings->nChannels = pConfig->nChannels; + } + hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */ + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + if (!((value >= 1) && (value <= 6))) { + hAacEncoder->InitFlags |= AACENC_INIT_STATES; + } + } + break; + case AACENC_BANDWIDTH: + if (settings->userBandwidth != value) { + settings->userBandwidth = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; + } + break; + case AACENC_CHANNELORDER: + if (hAacEncoder->aacConfig.channelOrder != (CHANNEL_ORDER)value) { + if (!((value == 0) || (value == 1) || (value == 2))) { + err = AACENC_INVALID_CONFIG; + break; + } + hAacEncoder->aacConfig.channelOrder = (CHANNEL_ORDER)value; + hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */ + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_AFTERBURNER: + if (settings->userAfterburner != value) { + if (!((value == 0) || (value == 1))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userAfterburner = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; + } + break; + case AACENC_GRANULE_LENGTH: + if (settings->userFramelength != value) { + switch (value) { + case 1024: + case 512: + case 480: + case 256: + case 240: + case 128: + case 120: + if ((value << 1) == 480 || (value << 1) == 512) { + settings->userDownscaleFactor = 2; + } else if ((value << 2) == 480 || (value << 2) == 512) { + settings->userDownscaleFactor = 4; + } + settings->userFramelength = value; + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + break; + default: + err = AACENC_INVALID_CONFIG; + break; + } + } + break; + case AACENC_SBR_RATIO: + if (settings->userSbrRatio != value) { + if (!((value == 0) || (value == 1) || (value == 2))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userSbrRatio = value; + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_SBR_MODE: + if ((settings->userSbrEnabled != value) && + (NULL != hAacEncoder->hEnvEnc)) { + settings->userSbrEnabled = value; + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_TRANSMUX: + if (settings->userTpType != (TRANSPORT_TYPE)value) { + TRANSPORT_TYPE type = (TRANSPORT_TYPE)value; + UINT flags = hAacEncoder->CAPF_tpEnc; + + if (!(((type == TT_MP4_ADIF) && (flags & CAPF_ADIF)) || + ((type == TT_MP4_ADTS) && (flags & CAPF_ADTS)) || + ((type == TT_MP4_LATM_MCP0) && + ((flags & CAPF_LATM) && (flags & CAPF_RAWPACKETS))) || + ((type == TT_MP4_LATM_MCP1) && + ((flags & CAPF_LATM) && (flags & CAPF_RAWPACKETS))) || + ((type == TT_MP4_LOAS) && (flags & CAPF_LOAS)) || + ((type == TT_MP4_RAW) && (flags & CAPF_RAWPACKETS)))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpType = (TRANSPORT_TYPE)value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_SIGNALING_MODE: + if (settings->userTpSignaling != value) { + if (!((value == 0) || (value == 1) || (value == 2))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpSignaling = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_PROTECTION: + if (settings->userTpProtection != value) { + if (!((value == 0) || (value == 1))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpProtection = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_HEADER_PERIOD: + if (settings->userTpHeaderPeriod != value) { + if (!(((INT)value >= 0) && (value <= 255))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpHeaderPeriod = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_AUDIOMUXVER: + if (settings->userTpAmxv != value) { + if (!((value == 0) || (value == 1) || (value == 2))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpAmxv = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_TPSUBFRAMES: + if (settings->userTpNsubFrames != value) { + if (!((value >= 1) && (value <= 4))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpNsubFrames = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_ANCILLARY_BITRATE: + if (settings->userAncDataRate != value) { + settings->userAncDataRate = value; + } + break; + case AACENC_CONTROL_STATE: + if (hAacEncoder->InitFlags != value) { + if (value & AACENC_RESET_INBUFFER) { + hAacEncoder->nSamplesRead = 0; + } + hAacEncoder->InitFlags = value; + } + break; + case AACENC_METADATA_MODE: + if ((UINT)settings->userMetaDataMode != value) { + if (!(((INT)value >= 0) && ((INT)value <= 3))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userMetaDataMode = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; + } + break; + case AACENC_PEAK_BITRATE: + if (settings->userPeakBitrate != value) { + settings->userPeakBitrate = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + } + break; + default: + err = AACENC_UNSUPPORTED_PARAMETER; + break; + } /* switch(param) */ + +bail: + return err; +} + +UINT aacEncoder_GetParam(const HANDLE_AACENCODER hAacEncoder, + const AACENC_PARAM param) { + UINT value = 0; + USER_PARAM *settings = &hAacEncoder->extParam; + + /* check encoder handle */ + if (hAacEncoder == NULL) { + goto bail; + } + + /* apply param value */ + switch (param) { + case AACENC_AOT: + value = (UINT)hAacEncoder->aacConfig.audioObjectType; + break; + case AACENC_BITRATE: + switch (hAacEncoder->aacConfig.bitrateMode) { + case AACENC_BR_MODE_CBR: + value = (UINT)hAacEncoder->aacConfig.bitRate; + break; + default: + value = (UINT)-1; + } + break; + case AACENC_BITRATEMODE: + value = (UINT)((hAacEncoder->aacConfig.bitrateMode != AACENC_BR_MODE_FF) + ? hAacEncoder->aacConfig.bitrateMode + : AACENC_BR_MODE_CBR); + break; + case AACENC_SAMPLERATE: + value = (UINT)hAacEncoder->coderConfig.extSamplingRate; + break; + case AACENC_CHANNELMODE: + if ((MODE_1 == hAacEncoder->aacConfig.channelMode) && + (hAacEncoder->aacConfig.syntaxFlags & AC_LD_MPS)) { + value = MODE_212; + } else { + value = (UINT)hAacEncoder->aacConfig.channelMode; + } + break; + case AACENC_BANDWIDTH: + value = (UINT)hAacEncoder->aacConfig.bandWidth; + break; + case AACENC_CHANNELORDER: + value = (UINT)hAacEncoder->aacConfig.channelOrder; + break; + case AACENC_AFTERBURNER: + value = (UINT)hAacEncoder->aacConfig.useRequant; + break; + case AACENC_GRANULE_LENGTH: + value = (UINT)hAacEncoder->aacConfig.framelength; + break; + case AACENC_SBR_RATIO: + value = isSbrActive(&hAacEncoder->aacConfig) + ? hAacEncoder->aacConfig.sbrRatio + : 0; + break; + case AACENC_SBR_MODE: + value = + (UINT)(hAacEncoder->aacConfig.syntaxFlags & AC_SBR_PRESENT) ? 1 : 0; + break; + case AACENC_TRANSMUX: + value = (UINT)settings->userTpType; + break; + case AACENC_SIGNALING_MODE: + value = (UINT)getSbrSignalingMode( + hAacEncoder->aacConfig.audioObjectType, settings->userTpType, + settings->userTpSignaling, hAacEncoder->aacConfig.sbrRatio); + break; + case AACENC_PROTECTION: + value = (UINT)settings->userTpProtection; + break; + case AACENC_HEADER_PERIOD: + value = (UINT)hAacEncoder->coderConfig.headerPeriod; + break; + case AACENC_AUDIOMUXVER: + value = (UINT)hAacEncoder->aacConfig.audioMuxVersion; + break; + case AACENC_TPSUBFRAMES: + value = (UINT)settings->userTpNsubFrames; + break; + case AACENC_ANCILLARY_BITRATE: + value = (UINT)hAacEncoder->aacConfig.anc_Rate; + break; + case AACENC_CONTROL_STATE: + value = (UINT)hAacEncoder->InitFlags; + break; + case AACENC_METADATA_MODE: + value = (hAacEncoder->metaDataAllowed == 0) + ? 0 + : (UINT)settings->userMetaDataMode; + break; + case AACENC_PEAK_BITRATE: + value = (UINT)-1; /* peak bitrate parameter is meaningless */ + if (((INT)hAacEncoder->extParam.userPeakBitrate != -1)) { + value = + (UINT)(fMax((INT)hAacEncoder->extParam.userPeakBitrate, + hAacEncoder->aacConfig + .bitRate)); /* peak bitrate parameter is in use */ + } + break; + + default: + // err = MPS_INVALID_PARAMETER; + break; + } /* switch(param) */ + +bail: + return value; +} + +AACENC_ERROR aacEncInfo(const HANDLE_AACENCODER hAacEncoder, + AACENC_InfoStruct *pInfo) { + AACENC_ERROR err = AACENC_OK; + + if ((hAacEncoder == NULL) || (pInfo == NULL)) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + FDKmemclear(pInfo, sizeof(AACENC_InfoStruct)); + pInfo->confSize = 64; /* pre-initialize */ + + pInfo->maxOutBufBytes = ((hAacEncoder->nMaxAacChannels * 6144) + 7) >> 3; + pInfo->maxAncBytes = hAacEncoder->aacConfig.maxAncBytesPerAU; + pInfo->inBufFillLevel = + hAacEncoder->nSamplesRead / hAacEncoder->extParam.nChannels; + pInfo->inputChannels = hAacEncoder->extParam.nChannels; + pInfo->frameLength = + hAacEncoder->nSamplesToRead / hAacEncoder->extParam.nChannels; + pInfo->nDelay = hAacEncoder->nDelay; + pInfo->nDelayCore = hAacEncoder->nDelayCore; + + /* Get encoder configuration */ + if (aacEncGetConf(hAacEncoder, &pInfo->confSize, &pInfo->confBuf[0]) != + AAC_ENC_OK) { + err = AACENC_INIT_ERROR; + goto bail; + } +bail: + return err; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_pns.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_pns.cpp new file mode 100644 index 0000000000000..f0571d6ae2b6e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_pns.cpp @@ -0,0 +1,541 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: pns.c + +*******************************************************************************/ + +#include "aacenc_pns.h" + +#include "psy_data.h" +#include "pnsparam.h" +#include "noisedet.h" +#include "bit_cnt.h" +#include "interface.h" + +/* minCorrelationEnergy = (1.0e-10f)^2 ~ 2^-67 = 2^-47 * 2^-20 */ +static const FIXP_DBL minCorrelationEnergy = + FL2FXCONST_DBL(0.0); /* FL2FXCONST_DBL((float)FDKpow(2.0,-47)); */ +/* noiseCorrelationThresh = 0.6^2 */ +static const FIXP_DBL noiseCorrelationThresh = FL2FXCONST_DBL(0.36); + +static void FDKaacEnc_FDKaacEnc_noiseDetection( + PNS_CONFIG *pnsConf, PNS_DATA *pnsData, const INT sfbActive, + const INT *sfbOffset, INT tnsOrder, INT tnsPredictionGain, INT tnsActive, + FIXP_DBL *mdctSpectrum, INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality); + +static void FDKaacEnc_CalcNoiseNrgs(const INT sfbActive, INT *pnsFlag, + FIXP_DBL *sfbEnergyLdData, INT *noiseNrg); + +/***************************************************************************** + + functionname: initPnsConfiguration + description: fill pnsConf with pns parameters + returns: error status + input: PNS Config struct (modified) + bitrate, samplerate, usePns, + number of sfb's, pointer to sfb offset + output: error code + +*****************************************************************************/ + +AAC_ENCODER_ERROR FDKaacEnc_InitPnsConfiguration( + PNS_CONFIG *pnsConf, INT bitRate, INT sampleRate, INT usePns, INT sfbCnt, + const INT *sfbOffset, const INT numChan, const INT isLC) { + AAC_ENCODER_ERROR ErrorStatus; + + /* init noise detection */ + ErrorStatus = FDKaacEnc_GetPnsParam(&pnsConf->np, bitRate, sampleRate, sfbCnt, + sfbOffset, &usePns, numChan, isLC); + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + pnsConf->minCorrelationEnergy = minCorrelationEnergy; + pnsConf->noiseCorrelationThresh = noiseCorrelationThresh; + + pnsConf->usePns = usePns; + + return AAC_ENC_OK; +} + +/***************************************************************************** + + functionname: FDKaacEnc_PnsDetect + description: do decision, if PNS shall used or not + returns: + input: pns config structure + pns data structure (modified), + lastWindowSequence (long or short blocks) + sfbActive + pointer to Sfb Energy, Threshold, Offset + pointer to mdct Spectrum + length of each group + pointer to tonality calculated in chaosmeasure + tns order and prediction gain + calculated noiseNrg at active PNS + output: pnsFlag in pns data structure + +*****************************************************************************/ +void FDKaacEnc_PnsDetect(PNS_CONFIG *pnsConf, PNS_DATA *pnsData, + const INT lastWindowSequence, const INT sfbActive, + const INT maxSfbPerGroup, FIXP_DBL *sfbThresholdLdData, + const INT *sfbOffset, FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality, + INT tnsOrder, INT tnsPredictionGain, INT tnsActive, + FIXP_DBL *sfbEnergyLdData, INT *noiseNrg) + +{ + int sfb; + int startNoiseSfb; + + /* Reset pns info. */ + FDKmemclear(pnsData->pnsFlag, sizeof(pnsData->pnsFlag)); + for (sfb = 0; sfb < MAX_GROUPED_SFB; sfb++) { + noiseNrg[sfb] = NO_NOISE_PNS; + } + + /* Disable PNS and skip detection in certain cases. */ + if (pnsConf->usePns == 0) { + return; + } else { + /* AAC - LC core encoder */ + if ((pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMPLEXITY) && + (lastWindowSequence == SHORT_WINDOW)) { + return; + } + /* AAC - (E)LD core encoder */ + if (!(pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMPLEXITY) && + (pnsConf->np.detectionAlgorithmFlags & JUST_LONG_WINDOW) && + (lastWindowSequence != LONG_WINDOW)) { + return; + } + } + + /* + call noise detection + */ + FDKaacEnc_FDKaacEnc_noiseDetection( + pnsConf, pnsData, sfbActive, sfbOffset, tnsOrder, tnsPredictionGain, + tnsActive, mdctSpectrum, sfbMaxScaleSpec, sfbtonality); + + /* set startNoiseSfb (long) */ + startNoiseSfb = pnsConf->np.startSfb; + + /* Set noise substitution status */ + for (sfb = 0; sfb < sfbActive; sfb++) { + /* No PNS below startNoiseSfb */ + if (sfb < startNoiseSfb) { + pnsData->pnsFlag[sfb] = 0; + continue; + } + + /* + do noise substitution if + fuzzy measure is high enough + sfb freq > minimum sfb freq + signal in coder band is not masked + */ + + if ((pnsData->noiseFuzzyMeasure[sfb] > FL2FXCONST_SGL(0.5)) && + ((sfbThresholdLdData[sfb] + + FL2FXCONST_DBL(0.5849625f / + 64.0f)) /* thr * 1.5 = thrLd +ld(1.5)/64 */ + < sfbEnergyLdData[sfb])) { + /* + mark in psyout flag array that we will code + this band with PNS + */ + pnsData->pnsFlag[sfb] = 1; /* PNS_ON */ + } else { + pnsData->pnsFlag[sfb] = 0; /* PNS_OFF */ + } + + /* no PNS if LTP is active */ + } + + /* avoid PNS holes */ + if ((pnsData->noiseFuzzyMeasure[0] > FL2FXCONST_SGL(0.5f)) && + (pnsData->pnsFlag[1])) { + pnsData->pnsFlag[0] = 1; + } + + for (sfb = 1; sfb < maxSfbPerGroup - 1; sfb++) { + if ((pnsData->noiseFuzzyMeasure[sfb] > pnsConf->np.gapFillThr) && + (pnsData->pnsFlag[sfb - 1]) && (pnsData->pnsFlag[sfb + 1])) { + pnsData->pnsFlag[sfb] = 1; + } + } + + if (maxSfbPerGroup > 0) { + /* avoid PNS hole */ + if ((pnsData->noiseFuzzyMeasure[maxSfbPerGroup - 1] > + pnsConf->np.gapFillThr) && + (pnsData->pnsFlag[maxSfbPerGroup - 2])) { + pnsData->pnsFlag[maxSfbPerGroup - 1] = 1; + } + /* avoid single PNS band */ + if (pnsData->pnsFlag[maxSfbPerGroup - 2] == 0) { + pnsData->pnsFlag[maxSfbPerGroup - 1] = 0; + } + } + + /* avoid single PNS bands */ + if (pnsData->pnsFlag[1] == 0) { + pnsData->pnsFlag[0] = 0; + } + + for (sfb = 1; sfb < maxSfbPerGroup - 1; sfb++) { + if ((pnsData->pnsFlag[sfb - 1] == 0) && (pnsData->pnsFlag[sfb + 1] == 0)) { + pnsData->pnsFlag[sfb] = 0; + } + } + + /* + calculate noiseNrg's + */ + FDKaacEnc_CalcNoiseNrgs(sfbActive, pnsData->pnsFlag, sfbEnergyLdData, + noiseNrg); +} + +/***************************************************************************** + + functionname:FDKaacEnc_FDKaacEnc_noiseDetection + description: wrapper for noisedet.c + returns: + input: pns config structure + pns data structure (modified), + sfbActive + tns order and prediction gain + pointer to mdct Spectrumand Sfb Energy + pointer to Sfb tonality + output: noiseFuzzyMeasure in structure pnsData + flags tonal / nontonal + +*****************************************************************************/ +static void FDKaacEnc_FDKaacEnc_noiseDetection( + PNS_CONFIG *pnsConf, PNS_DATA *pnsData, const INT sfbActive, + const INT *sfbOffset, int tnsOrder, INT tnsPredictionGain, INT tnsActive, + FIXP_DBL *mdctSpectrum, INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality) { + INT condition = TRUE; + if (!(pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMPLEXITY)) { + condition = (tnsOrder > 3); + } + /* + no PNS if heavy TNS activity + clear pnsData->noiseFuzzyMeasure + */ + if ((pnsConf->np.detectionAlgorithmFlags & USE_TNS_GAIN_THR) && + (tnsPredictionGain >= pnsConf->np.tnsGainThreshold) && condition && + !((pnsConf->np.detectionAlgorithmFlags & USE_TNS_PNS) && + (tnsPredictionGain >= pnsConf->np.tnsPNSGainThreshold) && + (tnsActive))) { + /* clear all noiseFuzzyMeasure */ + FDKmemclear(pnsData->noiseFuzzyMeasure, sfbActive * sizeof(FIXP_SGL)); + } else { + /* + call noise detection, output in pnsData->noiseFuzzyMeasure, + use real mdct spectral data + */ + FDKaacEnc_noiseDetect(mdctSpectrum, sfbMaxScaleSpec, sfbActive, sfbOffset, + pnsData->noiseFuzzyMeasure, &pnsConf->np, + sfbtonality); + } +} + +/***************************************************************************** + + functionname:FDKaacEnc_CalcNoiseNrgs + description: Calculate the NoiseNrg's + returns: + input: sfbActive + if pnsFlag calculate NoiseNrg + pointer to sfbEnergy and groupLen + pointer to noiseNrg (modified) + output: noiseNrg's in pnsFlaged sfb's + +*****************************************************************************/ + +static void FDKaacEnc_CalcNoiseNrgs(const INT sfbActive, INT *RESTRICT pnsFlag, + FIXP_DBL *RESTRICT sfbEnergyLdData, + INT *RESTRICT noiseNrg) { + int sfb; + INT tmp = (-LOG_NORM_PCM) << 2; + + for (sfb = 0; sfb < sfbActive; sfb++) { + if (pnsFlag[sfb]) { + INT nrg = (-sfbEnergyLdData[sfb] + FL2FXCONST_DBL(0.5f / 64.0f)) >> + (DFRACT_BITS - 1 - 7); + noiseNrg[sfb] = tmp - nrg; + } + } +} + +/***************************************************************************** + + functionname:FDKaacEnc_CodePnsChannel + description: Execute pns decission + returns: + input: sfbActive + pns config structure + use PNS if pnsFlag + pointer to Sfb Energy, noiseNrg, Threshold + output: set sfbThreshold high to code pe with 0, + noiseNrg marks flag for pns coding + +*****************************************************************************/ + +void FDKaacEnc_CodePnsChannel(const INT sfbActive, PNS_CONFIG *pnsConf, + INT *RESTRICT pnsFlag, + FIXP_DBL *RESTRICT sfbEnergyLdData, + INT *RESTRICT noiseNrg, + FIXP_DBL *RESTRICT sfbThresholdLdData) { + INT sfb; + INT lastiNoiseEnergy = 0; + INT firstPNSband = 1; /* TRUE for first PNS-coded band */ + + /* no PNS */ + if (!pnsConf->usePns) { + for (sfb = 0; sfb < sfbActive; sfb++) { + /* no PNS coding */ + noiseNrg[sfb] = NO_NOISE_PNS; + } + return; + } + + /* code PNS */ + for (sfb = 0; sfb < sfbActive; sfb++) { + if (pnsFlag[sfb]) { + /* high sfbThreshold causes pe = 0 */ + if (noiseNrg[sfb] != NO_NOISE_PNS) + sfbThresholdLdData[sfb] = + sfbEnergyLdData[sfb] + FL2FXCONST_DBL(1.0f / LD_DATA_SCALING); + + /* set noiseNrg in valid region */ + if (!firstPNSband) { + INT deltaiNoiseEnergy = noiseNrg[sfb] - lastiNoiseEnergy; + + if (deltaiNoiseEnergy > CODE_BOOK_PNS_LAV) + noiseNrg[sfb] -= deltaiNoiseEnergy - CODE_BOOK_PNS_LAV; + else if (deltaiNoiseEnergy < -CODE_BOOK_PNS_LAV) + noiseNrg[sfb] -= deltaiNoiseEnergy + CODE_BOOK_PNS_LAV; + } else { + firstPNSband = 0; + } + lastiNoiseEnergy = noiseNrg[sfb]; + } else { + /* no PNS coding */ + noiseNrg[sfb] = NO_NOISE_PNS; + } + } +} + +/***************************************************************************** + + functionname:FDKaacEnc_PreProcessPnsChannelPair + description: Calculate the correlation of noise in a channel pair + + returns: + input: sfbActive + pointer to sfb energies left, right and mid channel + pns config structure + pns data structure left and right (modified) + + output: noiseEnergyCorrelation in pns data structure + +*****************************************************************************/ + +void FDKaacEnc_PreProcessPnsChannelPair( + const INT sfbActive, FIXP_DBL *RESTRICT sfbEnergyLeft, + FIXP_DBL *RESTRICT sfbEnergyRight, FIXP_DBL *RESTRICT sfbEnergyLeftLD, + FIXP_DBL *RESTRICT sfbEnergyRightLD, FIXP_DBL *RESTRICT sfbEnergyMid, + PNS_CONFIG *RESTRICT pnsConf, PNS_DATA *pnsDataLeft, + PNS_DATA *pnsDataRight) { + INT sfb; + FIXP_DBL ccf; + + if (!pnsConf->usePns) return; + + FIXP_DBL *RESTRICT pNoiseEnergyCorrelationL = + pnsDataLeft->noiseEnergyCorrelation; + FIXP_DBL *RESTRICT pNoiseEnergyCorrelationR = + pnsDataRight->noiseEnergyCorrelation; + + for (sfb = 0; sfb < sfbActive; sfb++) { + FIXP_DBL quot = (sfbEnergyLeftLD[sfb] >> 1) + (sfbEnergyRightLD[sfb] >> 1); + + if (quot < FL2FXCONST_DBL(-32.0f / (float)LD_DATA_SCALING)) + ccf = FL2FXCONST_DBL(0.0f); + else { + FIXP_DBL accu = + sfbEnergyMid[sfb] - + (((sfbEnergyLeft[sfb] >> 1) + (sfbEnergyRight[sfb] >> 1)) >> 1); + INT sign = (accu < FL2FXCONST_DBL(0.0f)) ? 1 : 0; + accu = fixp_abs(accu); + + ccf = CalcLdData(accu) + + FL2FXCONST_DBL((float)1.0f / (float)LD_DATA_SCALING) - + quot; /* ld(accu*2) = ld(accu) + 1 */ + ccf = (ccf >= FL2FXCONST_DBL(0.0)) + ? ((FIXP_DBL)MAXVAL_DBL) + : (sign) ? -CalcInvLdData(ccf) : CalcInvLdData(ccf); + } + + pNoiseEnergyCorrelationL[sfb] = ccf; + pNoiseEnergyCorrelationR[sfb] = ccf; + } +} + +/***************************************************************************** + + functionname:FDKaacEnc_PostProcessPnsChannelPair + description: if PNS used at left and right channel, + use msMask to flag correlation + returns: + input: sfbActive + pns config structure + pns data structure left and right (modified) + pointer to msMask, flags correlation by pns coding (modified) + Digest of MS coding + output: pnsFlag in pns data structure, + msFlag in msMask (flags correlation) + +*****************************************************************************/ + +void FDKaacEnc_PostProcessPnsChannelPair(const INT sfbActive, + PNS_CONFIG *pnsConf, + PNS_DATA *pnsDataLeft, + PNS_DATA *pnsDataRight, + INT *RESTRICT msMask, INT *msDigest) { + INT sfb; + + if (!pnsConf->usePns) return; + + for (sfb = 0; sfb < sfbActive; sfb++) { + /* + MS post processing + */ + if (msMask[sfb]) { + if ((pnsDataLeft->pnsFlag[sfb]) && (pnsDataRight->pnsFlag[sfb])) { + /* AAC only: Standard */ + /* do this to avoid ms flags in layers that should not have it */ + if (pnsDataLeft->noiseEnergyCorrelation[sfb] <= + pnsConf->noiseCorrelationThresh) { + msMask[sfb] = 0; + *msDigest = MS_SOME; + } + } else { + /* + No PNS coding + */ + pnsDataLeft->pnsFlag[sfb] = 0; + pnsDataRight->pnsFlag[sfb] = 0; + } + } + + /* + Use MS flag to signal noise correlation if + pns is active in both channels + */ + if ((pnsDataLeft->pnsFlag[sfb]) && (pnsDataRight->pnsFlag[sfb])) { + if (pnsDataLeft->noiseEnergyCorrelation[sfb] > + pnsConf->noiseCorrelationThresh) { + msMask[sfb] = 1; + *msDigest = MS_SOME; + } + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_pns.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_pns.h new file mode 100644 index 0000000000000..4938fcf5daec0 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_pns.h @@ -0,0 +1,124 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: pns.h + +*******************************************************************************/ + +#ifndef AACENC_PNS_H +#define AACENC_PNS_H + +#include "common_fix.h" +#include "pnsparam.h" + +#define NO_NOISE_PNS FDK_INT_MIN + +typedef struct { + NOISEPARAMS np; + FIXP_DBL minCorrelationEnergy; + FIXP_DBL noiseCorrelationThresh; + INT usePns; +} PNS_CONFIG; + +typedef struct { + FIXP_SGL noiseFuzzyMeasure[MAX_GROUPED_SFB]; + FIXP_DBL noiseEnergyCorrelation[MAX_GROUPED_SFB]; + INT pnsFlag[MAX_GROUPED_SFB]; +} PNS_DATA; + +#endif /* AACENC_PNS_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_tns.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_tns.cpp new file mode 100644 index 0000000000000..4462600c377cb --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_tns.cpp @@ -0,0 +1,1191 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): Alex Groeschel, Tobias Chalupka + + Description: Temporal noise shaping + +*******************************************************************************/ + +#include "aacenc_tns.h" +#include "psy_const.h" +#include "psy_configuration.h" +#include "tns_func.h" +#include "aacEnc_rom.h" +#include "aacenc_tns.h" +#include "FDK_lpc.h" + +#define FILTER_DIRECTION 0 /* 0 = up, 1 = down */ + +static const FIXP_DBL acfWindowLong[12 + 3 + 1] = { + 0x7fffffff, 0x7fb80000, 0x7ee00000, 0x7d780000, 0x7b800000, 0x78f80000, + 0x75e00000, 0x72380000, 0x6e000000, 0x69380000, 0x63e00000, 0x5df80000, + 0x57800000, 0x50780000, 0x48e00000, 0x40b80000}; + +static const FIXP_DBL acfWindowShort[4 + 3 + 1] = { + 0x7fffffff, 0x7e000000, 0x78000000, 0x6e000000, + 0x60000000, 0x4e000000, 0x38000000, 0x1e000000}; + +typedef struct { + INT bitRateFrom[2]; /* noneSbr=0, useSbr=1 */ + INT bitRateTo[2]; /* noneSbr=0, useSbr=1 */ + TNS_PARAMETER_TABULATED paramTab[2]; /* mono=0, stereo=1 */ + +} TNS_INFO_TAB; + +#define TNS_TIMERES_SCALE (1) +#define FL2_TIMERES_FIX(a) (FL2FXCONST_DBL(a / (float)(1 << TNS_TIMERES_SCALE))) + +static const TNS_INFO_TAB tnsInfoTab[] = { + {{16000, 13500}, + {32000, 28000}, + {{{1, 1}, + {1437, 1500}, + {1400, 600}, + {12, 12}, + {FILTER_DIRECTION, FILTER_DIRECTION}, + {3, 1}, + {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.2f)}, + 1}, + {{1, 1}, + {1437, 1500}, + {1400, 600}, + {12, 12}, + {FILTER_DIRECTION, FILTER_DIRECTION}, + {3, 1}, + {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.2f)}, + 1}}}, + {{32001, 28001}, + {60000, 52000}, + {{{1, 1}, + {1437, 1500}, + {1400, 600}, + {12, 10}, + {FILTER_DIRECTION, FILTER_DIRECTION}, + {3, 1}, + {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, + 1}, + {{1, 1}, + {1437, 1500}, + {1400, 600}, + {12, 10}, + {FILTER_DIRECTION, FILTER_DIRECTION}, + {3, 1}, + {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, + 1}}}, + {{60001, 52001}, + {384000, 384000}, + {{{1, 1}, + {1437, 1500}, + {1400, 600}, + {12, 8}, + {FILTER_DIRECTION, FILTER_DIRECTION}, + {3, 1}, + {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, + 1}, + {{1, 1}, + {1437, 1500}, + {1400, 600}, + {12, 8}, + {FILTER_DIRECTION, FILTER_DIRECTION}, + {3, 1}, + {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, + 1}}}}; + +typedef struct { + INT samplingRate; + SCHAR maxBands[2]; /* long=0; short=1 */ + +} TNS_MAX_TAB_ENTRY; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab1024[] = { + {96000, {31, 9}}, {88200, {31, 9}}, {64000, {34, 10}}, {48000, {40, 14}}, + {44100, {42, 14}}, {32000, {51, 14}}, {24000, {46, 14}}, {22050, {46, 14}}, + {16000, {42, 14}}, {12000, {42, 14}}, {11025, {42, 14}}, {8000, {39, 14}}}; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab120[] = { + {48000, {12, -1}}, /* 48000 */ + {44100, {12, -1}}, /* 44100 */ + {32000, {15, -1}}, /* 32000 */ + {24000, {15, -1}}, /* 24000 */ + {22050, {15, -1}} /* 22050 */ +}; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab128[] = { + {48000, {12, -1}}, /* 48000 */ + {44100, {12, -1}}, /* 44100 */ + {32000, {15, -1}}, /* 32000 */ + {24000, {15, -1}}, /* 24000 */ + {22050, {15, -1}} /* 22050 */ +}; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab240[] = { + {96000, {22, -1}}, /* 96000 */ + {48000, {22, -1}}, /* 48000 */ + {44100, {22, -1}}, /* 44100 */ + {32000, {21, -1}}, /* 32000 */ + {24000, {21, -1}}, /* 24000 */ + {22050, {21, -1}} /* 22050 */ +}; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab256[] = { + {96000, {25, -1}}, /* 96000 */ + {48000, {25, -1}}, /* 48000 */ + {44100, {25, -1}}, /* 44100 */ + {32000, {24, -1}}, /* 32000 */ + {24000, {24, -1}}, /* 24000 */ + {22050, {24, -1}} /* 22050 */ +}; +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab480[] = {{48000, {31, -1}}, + {44100, {32, -1}}, + {32000, {37, -1}}, + {24000, {30, -1}}, + {22050, {30, -1}}}; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab512[] = {{48000, {31, -1}}, + {44100, {32, -1}}, + {32000, {37, -1}}, + {24000, {31, -1}}, + {22050, {31, -1}}}; + +static void FDKaacEnc_Parcor2Index(const FIXP_LPC *parcor, INT *RESTRICT index, + const INT order, const INT bitsPerCoeff); + +static void FDKaacEnc_Index2Parcor(const INT *index, FIXP_LPC *RESTRICT parcor, + const INT order, const INT bitsPerCoeff); + +static void FDKaacEnc_CalcGaussWindow(FIXP_DBL *win, const int winSize, + const INT samplingRate, + const INT transformResolution, + const FIXP_DBL timeResolution, + const INT timeResolution_e); + +static const TNS_PARAMETER_TABULATED *FDKaacEnc_GetTnsParam(const INT bitRate, + const INT channels, + const INT sbrLd) { + int i; + const TNS_PARAMETER_TABULATED *tnsConfigTab = NULL; + + for (i = 0; i < (int)(sizeof(tnsInfoTab) / sizeof(TNS_INFO_TAB)); i++) { + if ((bitRate >= tnsInfoTab[i].bitRateFrom[sbrLd ? 1 : 0]) && + bitRate <= tnsInfoTab[i].bitRateTo[sbrLd ? 1 : 0]) { + tnsConfigTab = &tnsInfoTab[i].paramTab[(channels == 1) ? 0 : 1]; + } + } + + return tnsConfigTab; +} + +static INT getTnsMaxBands(const INT sampleRate, const INT granuleLength, + const INT isShortBlock) { + int i; + INT numBands = -1; + const TNS_MAX_TAB_ENTRY *pMaxBandsTab = NULL; + int maxBandsTabSize = 0; + + switch (granuleLength) { + case 960: + case 1024: + pMaxBandsTab = tnsMaxBandsTab1024; + maxBandsTabSize = sizeof(tnsMaxBandsTab1024) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 120: + pMaxBandsTab = tnsMaxBandsTab120; + maxBandsTabSize = sizeof(tnsMaxBandsTab120) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 128: + pMaxBandsTab = tnsMaxBandsTab128; + maxBandsTabSize = sizeof(tnsMaxBandsTab128) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 240: + pMaxBandsTab = tnsMaxBandsTab240; + maxBandsTabSize = sizeof(tnsMaxBandsTab240) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 256: + pMaxBandsTab = tnsMaxBandsTab256; + maxBandsTabSize = sizeof(tnsMaxBandsTab256) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 480: + pMaxBandsTab = tnsMaxBandsTab480; + maxBandsTabSize = sizeof(tnsMaxBandsTab480) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 512: + pMaxBandsTab = tnsMaxBandsTab512; + maxBandsTabSize = sizeof(tnsMaxBandsTab512) / sizeof(TNS_MAX_TAB_ENTRY); + break; + default: + numBands = -1; + } + + if (pMaxBandsTab != NULL) { + for (i = 0; i < maxBandsTabSize; i++) { + numBands = pMaxBandsTab[i].maxBands[(!isShortBlock) ? 0 : 1]; + if (sampleRate >= pMaxBandsTab[i].samplingRate) { + break; + } + } + } + + return numBands; +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_FreqToBandWidthRounding + + Returns index of nearest band border + + \param frequency + \param sampling frequency + \param total number of bands + \param pointer to table of band borders + + \return band border +****************************************************************************/ + +INT FDKaacEnc_FreqToBandWidthRounding(const INT freq, const INT fs, + const INT numOfBands, + const INT *bandStartOffset) { + INT lineNumber, band; + + /* assert(freq >= 0); */ + lineNumber = (freq * bandStartOffset[numOfBands] * 4 / fs + 1) / 2; + + /* freq > fs/2 */ + if (lineNumber >= bandStartOffset[numOfBands]) return numOfBands; + + /* find band the line number lies in */ + for (band = 0; band < numOfBands; band++) { + if (bandStartOffset[band + 1] > lineNumber) break; + } + + /* round to nearest band border */ + if (lineNumber - bandStartOffset[band] > + bandStartOffset[band + 1] - lineNumber) { + band++; + } + + return (band); +} + +/***************************************************************************** + + functionname: FDKaacEnc_InitTnsConfiguration + description: fill TNS_CONFIG structure with sensible content + returns: + input: bitrate, samplerate, number of channels, + blocktype (long or short), + TNS Config struct (modified), + psy config struct, + tns active flag + output: + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration( + INT bitRate, INT sampleRate, INT channels, INT blockType, INT granuleLength, + INT isLowDelay, INT ldSbrPresent, TNS_CONFIG *tC, PSY_CONFIGURATION *pC, + INT active, INT useTnsPeak) { + int i; + // float acfTimeRes = (blockType == SHORT_WINDOW) ? 0.125f : 0.046875f; + + if (channels <= 0) return (AAC_ENCODER_ERROR)1; + + tC->isLowDelay = isLowDelay; + + /* initialize TNS filter flag, order, and coefficient resolution (in bits per + * coeff) */ + tC->tnsActive = (active) ? TRUE : FALSE; + tC->maxOrder = (blockType == SHORT_WINDOW) ? 5 : 12; /* maximum: 7, 20 */ + if (bitRate < 16000) tC->maxOrder -= 2; + tC->coefRes = (blockType == SHORT_WINDOW) ? 3 : 4; + + /* LPC stop line: highest MDCT line to be coded, but do not go beyond + * TNS_MAX_BANDS! */ + tC->lpcStopBand = getTnsMaxBands(sampleRate, granuleLength, + (blockType == SHORT_WINDOW) ? 1 : 0); + + if (tC->lpcStopBand < 0) { + return (AAC_ENCODER_ERROR)1; + } + + tC->lpcStopBand = fMin(tC->lpcStopBand, pC->sfbActive); + tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand]; + + switch (granuleLength) { + case 960: + case 1024: + /* TNS start line: skip lower MDCT lines to prevent artifacts due to + * filter mismatch */ + if (blockType == SHORT_WINDOW) { + tC->lpcStartBand[LOFILT] = 0; + } else { + tC->lpcStartBand[LOFILT] = + (sampleRate < 9391) ? 2 : ((sampleRate < 18783) ? 4 : 8); + } + tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]]; + + i = tC->lpcStopBand; + while (pC->sfbOffset[i] > + (tC->lpcStartLine[LOFILT] + + (tC->lpcStopLine - tC->lpcStartLine[LOFILT]) / 4)) + i--; + tC->lpcStartBand[HIFILT] = i; + tC->lpcStartLine[HIFILT] = pC->sfbOffset[i]; + + tC->confTab.threshOn[HIFILT] = 1437; + tC->confTab.threshOn[LOFILT] = 1500; + + tC->confTab.tnsLimitOrder[HIFILT] = tC->maxOrder; + tC->confTab.tnsLimitOrder[LOFILT] = fMax(0, tC->maxOrder - 7); + + tC->confTab.tnsFilterDirection[HIFILT] = FILTER_DIRECTION; + tC->confTab.tnsFilterDirection[LOFILT] = FILTER_DIRECTION; + + tC->confTab.acfSplit[HIFILT] = + -1; /* signal Merged4to2QuartersAutoCorrelation in + FDKaacEnc_MergedAutoCorrelation*/ + tC->confTab.acfSplit[LOFILT] = + -1; /* signal Merged4to2QuartersAutoCorrelation in + FDKaacEnc_MergedAutoCorrelation */ + + tC->confTab.filterEnabled[HIFILT] = 1; + tC->confTab.filterEnabled[LOFILT] = 1; + tC->confTab.seperateFiltersAllowed = 1; + + /* compute autocorrelation window based on maximum filter order for given + * block type */ + /* for (i = 0; i <= tC->maxOrder + 3; i++) { + float acfWinTemp = acfTimeRes * i; + acfWindow[i] = FL2FXCONST_DBL(1.0f - acfWinTemp * acfWinTemp); + } + */ + if (blockType == SHORT_WINDOW) { + FDKmemcpy(tC->acfWindow[HIFILT], acfWindowShort, + fMin((LONG)sizeof(acfWindowShort), + (LONG)sizeof(tC->acfWindow[HIFILT]))); + FDKmemcpy(tC->acfWindow[LOFILT], acfWindowShort, + fMin((LONG)sizeof(acfWindowShort), + (LONG)sizeof(tC->acfWindow[HIFILT]))); + } else { + FDKmemcpy(tC->acfWindow[HIFILT], acfWindowLong, + fMin((LONG)sizeof(acfWindowLong), + (LONG)sizeof(tC->acfWindow[HIFILT]))); + FDKmemcpy(tC->acfWindow[LOFILT], acfWindowLong, + fMin((LONG)sizeof(acfWindowLong), + (LONG)sizeof(tC->acfWindow[HIFILT]))); + } + break; + case 480: + case 512: { + const TNS_PARAMETER_TABULATED *pCfg = + FDKaacEnc_GetTnsParam(bitRate, channels, ldSbrPresent); + if (pCfg != NULL) { + FDKmemcpy(&(tC->confTab), pCfg, sizeof(tC->confTab)); + + tC->lpcStartBand[HIFILT] = FDKaacEnc_FreqToBandWidthRounding( + pCfg->filterStartFreq[HIFILT], sampleRate, pC->sfbCnt, + pC->sfbOffset); + tC->lpcStartLine[HIFILT] = pC->sfbOffset[tC->lpcStartBand[HIFILT]]; + tC->lpcStartBand[LOFILT] = FDKaacEnc_FreqToBandWidthRounding( + pCfg->filterStartFreq[LOFILT], sampleRate, pC->sfbCnt, + pC->sfbOffset); + tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]]; + + FDKaacEnc_CalcGaussWindow( + tC->acfWindow[HIFILT], tC->maxOrder + 1, sampleRate, granuleLength, + pCfg->tnsTimeResolution[HIFILT], TNS_TIMERES_SCALE); + FDKaacEnc_CalcGaussWindow( + tC->acfWindow[LOFILT], tC->maxOrder + 1, sampleRate, granuleLength, + pCfg->tnsTimeResolution[LOFILT], TNS_TIMERES_SCALE); + } else { + tC->tnsActive = + FALSE; /* no configuration available, disable tns tool */ + } + } break; + default: + tC->tnsActive = FALSE; /* no configuration available, disable tns tool */ + } + + return AAC_ENC_OK; +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_ScaleUpSpectrum + + Scales up spectrum lines in a given frequency section + + \param scaled spectrum + \param original spectrum + \param frequency line to start scaling + \param frequency line to enc scaling + + \return scale factor + +****************************************************************************/ +static inline INT FDKaacEnc_ScaleUpSpectrum(FIXP_DBL *dest, const FIXP_DBL *src, + const INT startLine, + const INT stopLine) { + INT i, scale; + + FIXP_DBL maxVal = FL2FXCONST_DBL(0.f); + + /* Get highest value in given spectrum */ + for (i = startLine; i < stopLine; i++) { + maxVal = fixMax(maxVal, fixp_abs(src[i])); + } + scale = CountLeadingBits(maxVal); + + /* Scale spectrum according to highest value */ + for (i = startLine; i < stopLine; i++) { + dest[i] = src[i] << scale; + } + + return scale; +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_CalcAutoCorrValue + + Calculate autocorellation value for one lag + + \param pointer to spectrum + \param start line + \param stop line + \param lag to be calculated + \param scaling of the lag + +****************************************************************************/ +static inline FIXP_DBL FDKaacEnc_CalcAutoCorrValue(const FIXP_DBL *spectrum, + const INT startLine, + const INT stopLine, + const INT lag, + const INT scale) { + int i; + FIXP_DBL result = FL2FXCONST_DBL(0.f); + + /* This versions allows to save memory accesses, when computing pow2 */ + /* It is of interest for ARM, XTENSA without parallel memory access */ + if (lag == 0) { + for (i = startLine; i < stopLine; i++) { + result += (fPow2(spectrum[i]) >> scale); + } + } else { + for (i = startLine; i < (stopLine - lag); i++) { + result += (fMult(spectrum[i], spectrum[i + lag]) >> scale); + } + } + + return result; +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_AutoCorrNormFac + + Autocorrelation function for 1st and 2nd half of the spectrum + + \param pointer to spectrum + \param pointer to autocorrelation window + \param filter start line + +****************************************************************************/ +static inline FIXP_DBL FDKaacEnc_AutoCorrNormFac(const FIXP_DBL value, + const INT scale, INT *sc) { +#define HLM_MIN_NRG 0.0000000037252902984619140625f /* 2^-28 */ +#define MAX_INV_NRGFAC (1.f / HLM_MIN_NRG) + + FIXP_DBL retValue; + FIXP_DBL A, B; + + if (scale >= 0) { + A = value; + B = FL2FXCONST_DBL(HLM_MIN_NRG) >> fixMin(DFRACT_BITS - 1, scale); + } else { + A = value >> fixMin(DFRACT_BITS - 1, (-scale)); + B = FL2FXCONST_DBL(HLM_MIN_NRG); + } + + if (A > B) { + int shift = 0; + FIXP_DBL tmp = invSqrtNorm2(value, &shift); + + retValue = fMult(tmp, tmp); + *sc += (2 * shift); + } else { + /* MAX_INV_NRGFAC*FDKpow(2,-28) = 1/2^-28 * 2^-28 = 1.0 */ + retValue = + /*FL2FXCONST_DBL(MAX_INV_NRGFAC*FDKpow(2,-28))*/ (FIXP_DBL)MAXVAL_DBL; + *sc += scale + 28; + } + + return retValue; +} + +static void FDKaacEnc_MergedAutoCorrelation( + const FIXP_DBL *spectrum, const INT isLowDelay, + const FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER + 3 + 1], + const INT lpcStartLine[MAX_NUM_OF_FILTERS], const INT lpcStopLine, + const INT maxOrder, const INT acfSplit[MAX_NUM_OF_FILTERS], FIXP_DBL *_rxx1, + FIXP_DBL *_rxx2) { + int i, idx0, idx1, idx2, idx3, idx4, lag; + FIXP_DBL rxx1_0, rxx2_0, rxx3_0, rxx4_0; + + /* buffer for temporal spectrum */ + C_ALLOC_SCRATCH_START(pSpectrum, FIXP_DBL, (1024)) + + /* MDCT line indices separating the 1st, 2nd, 3rd, and 4th analysis quarters + */ + if ((acfSplit[LOFILT] == -1) || (acfSplit[HIFILT] == -1)) { + /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the + * spectrum */ + idx0 = lpcStartLine[LOFILT]; + i = lpcStopLine - lpcStartLine[LOFILT]; + idx1 = idx0 + i / 4; + idx2 = idx0 + i / 2; + idx3 = idx0 + i * 3 / 4; + idx4 = lpcStopLine; + } else { + FDK_ASSERT(acfSplit[LOFILT] == 1); + FDK_ASSERT(acfSplit[HIFILT] == 3); + i = (lpcStopLine - lpcStartLine[HIFILT]) / 3; + idx0 = lpcStartLine[LOFILT]; + idx1 = lpcStartLine[HIFILT]; + idx2 = idx1 + i; + idx3 = idx2 + i; + idx4 = lpcStopLine; + } + + /* copy spectrum to temporal buffer and scale up as much as possible */ + INT sc1 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx0, idx1); + INT sc2 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx1, idx2); + INT sc3 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx2, idx3); + INT sc4 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx3, idx4); + + /* get scaling values for summation */ + INT nsc1, nsc2, nsc3, nsc4; + for (nsc1 = 1; (1 << nsc1) < (idx1 - idx0); nsc1++) + ; + for (nsc2 = 1; (1 << nsc2) < (idx2 - idx1); nsc2++) + ; + for (nsc3 = 1; (1 << nsc3) < (idx3 - idx2); nsc3++) + ; + for (nsc4 = 1; (1 << nsc4) < (idx4 - idx3); nsc4++) + ; + + /* compute autocorrelation value at lag zero, i. e. energy, for each quarter + */ + rxx1_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, 0, nsc1); + rxx2_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx1, idx2, 0, nsc2); + rxx3_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx2, idx3, 0, nsc3); + rxx4_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx3, idx4, 0, nsc4); + + /* compute energy normalization factors, i. e. 1/energy (saves some divisions) + */ + if (rxx1_0 != FL2FXCONST_DBL(0.f)) { + INT sc_fac1 = -1; + FIXP_DBL fac1 = + FDKaacEnc_AutoCorrNormFac(rxx1_0, ((-2 * sc1) + nsc1), &sc_fac1); + _rxx1[0] = scaleValue(fMult(rxx1_0, fac1), sc_fac1); + + if (isLowDelay) { + for (lag = 1; lag <= maxOrder; lag++) { + /* compute energy-normalized and windowed autocorrelation values at this + * lag */ + FIXP_DBL x1 = + FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1); + _rxx1[lag] = + fMult(scaleValue(fMult(x1, fac1), sc_fac1), acfWindow[LOFILT][lag]); + } + } else { + for (lag = 1; lag <= maxOrder; lag++) { + if ((3 * lag) <= maxOrder + 3) { + FIXP_DBL x1 = + FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1); + _rxx1[lag] = fMult(scaleValue(fMult(x1, fac1), sc_fac1), + acfWindow[LOFILT][3 * lag]); + } + } + } + } + + /* auto corr over upper 3/4 of spectrum */ + if (!((rxx2_0 == FL2FXCONST_DBL(0.f)) && (rxx3_0 == FL2FXCONST_DBL(0.f)) && + (rxx4_0 == FL2FXCONST_DBL(0.f)))) { + FIXP_DBL fac2, fac3, fac4; + fac2 = fac3 = fac4 = FL2FXCONST_DBL(0.f); + INT sc_fac2, sc_fac3, sc_fac4; + sc_fac2 = sc_fac3 = sc_fac4 = 0; + + if (rxx2_0 != FL2FXCONST_DBL(0.f)) { + fac2 = FDKaacEnc_AutoCorrNormFac(rxx2_0, ((-2 * sc2) + nsc2), &sc_fac2); + sc_fac2 -= 2; + } + if (rxx3_0 != FL2FXCONST_DBL(0.f)) { + fac3 = FDKaacEnc_AutoCorrNormFac(rxx3_0, ((-2 * sc3) + nsc3), &sc_fac3); + sc_fac3 -= 2; + } + if (rxx4_0 != FL2FXCONST_DBL(0.f)) { + fac4 = FDKaacEnc_AutoCorrNormFac(rxx4_0, ((-2 * sc4) + nsc4), &sc_fac4); + sc_fac4 -= 2; + } + + _rxx2[0] = scaleValue(fMult(rxx2_0, fac2), sc_fac2) + + scaleValue(fMult(rxx3_0, fac3), sc_fac3) + + scaleValue(fMult(rxx4_0, fac4), sc_fac4); + + for (lag = 1; lag <= maxOrder; lag++) { + /* merge quarters 2, 3, 4 into one autocorrelation; quarter 1 stays + * separate */ + FIXP_DBL x2 = scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue( + pSpectrum, idx1, idx2, lag, nsc2), + fac2), + sc_fac2) + + scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue( + pSpectrum, idx2, idx3, lag, nsc3), + fac3), + sc_fac3) + + scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue( + pSpectrum, idx3, idx4, lag, nsc4), + fac4), + sc_fac4); + + _rxx2[lag] = fMult(x2, acfWindow[HIFILT][lag]); + } + } + + C_ALLOC_SCRATCH_END(pSpectrum, FIXP_DBL, (1024)) +} + +/***************************************************************************** + functionname: FDKaacEnc_TnsDetect + description: do decision, if TNS shall be used or not + returns: + input: tns data structure (modified), + tns config structure, + scalefactor size and table, + spectrum, + subblock num, blocktype, + sfb-wise energy. + +*****************************************************************************/ +INT FDKaacEnc_TnsDetect(TNS_DATA *tnsData, const TNS_CONFIG *tC, + TNS_INFO *tnsInfo, INT sfbCnt, const FIXP_DBL *spectrum, + INT subBlockNumber, INT blockType) { + /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the + * spectrum. */ + FIXP_DBL rxx1[TNS_MAX_ORDER + 1]; /* higher part */ + FIXP_DBL rxx2[TNS_MAX_ORDER + 1]; /* lower part */ + FIXP_LPC parcor_tmp[TNS_MAX_ORDER]; + + int i; + + FDKmemclear(rxx1, sizeof(rxx1)); + FDKmemclear(rxx2, sizeof(rxx2)); + + TNS_SUBBLOCK_INFO *tsbi = + (blockType == SHORT_WINDOW) + ? &tnsData->dataRaw.Short.subBlockInfo[subBlockNumber] + : &tnsData->dataRaw.Long.subBlockInfo; + + tnsData->filtersMerged = FALSE; + + tsbi->tnsActive[HIFILT] = FALSE; + tsbi->predictionGain[HIFILT] = 1000; + tsbi->tnsActive[LOFILT] = FALSE; + tsbi->predictionGain[LOFILT] = 1000; + + tnsInfo->numOfFilters[subBlockNumber] = 0; + tnsInfo->coefRes[subBlockNumber] = tC->coefRes; + for (i = 0; i < tC->maxOrder; i++) { + tnsInfo->coef[subBlockNumber][HIFILT][i] = + tnsInfo->coef[subBlockNumber][LOFILT][i] = 0; + } + + tnsInfo->length[subBlockNumber][HIFILT] = + tnsInfo->length[subBlockNumber][LOFILT] = 0; + tnsInfo->order[subBlockNumber][HIFILT] = + tnsInfo->order[subBlockNumber][LOFILT] = 0; + + if ((tC->tnsActive) && (tC->maxOrder > 0)) { + int sumSqrCoef; + + FDKaacEnc_MergedAutoCorrelation( + spectrum, tC->isLowDelay, tC->acfWindow, tC->lpcStartLine, + tC->lpcStopLine, tC->maxOrder, tC->confTab.acfSplit, rxx1, rxx2); + + /* compute higher TNS filter coefficients in lattice form (ParCor) with + * LeRoux-Gueguen/Schur algorithm */ + { + FIXP_DBL predictionGain_m; + INT predictionGain_e; + + CLpc_AutoToParcor(rxx2, 0, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT], + &predictionGain_m, &predictionGain_e); + tsbi->predictionGain[HIFILT] = + (INT)fMultNorm(predictionGain_m, predictionGain_e, 1000, 31, 31); + } + + /* non-linear quantization of TNS lattice coefficients with given resolution + */ + FDKaacEnc_Parcor2Index(parcor_tmp, tnsInfo->coef[subBlockNumber][HIFILT], + tC->confTab.tnsLimitOrder[HIFILT], tC->coefRes); + + /* reduce filter order by truncating trailing zeros, compute sum(abs(coefs)) + */ + for (i = tC->confTab.tnsLimitOrder[HIFILT] - 1; i >= 0; i--) { + if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) { + break; + } + } + + tnsInfo->order[subBlockNumber][HIFILT] = i + 1; + + sumSqrCoef = 0; + for (; i >= 0; i--) { + sumSqrCoef += tnsInfo->coef[subBlockNumber][HIFILT][i] * + tnsInfo->coef[subBlockNumber][HIFILT][i]; + } + + tnsInfo->direction[subBlockNumber][HIFILT] = + tC->confTab.tnsFilterDirection[HIFILT]; + tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[HIFILT]; + + /* disable TNS if predictionGain is less than 3dB or sumSqrCoef is too small + */ + if ((tsbi->predictionGain[HIFILT] > tC->confTab.threshOn[HIFILT]) || + (sumSqrCoef > (tC->confTab.tnsLimitOrder[HIFILT] / 2 + 2))) { + tsbi->tnsActive[HIFILT] = TRUE; + tnsInfo->numOfFilters[subBlockNumber]++; + + /* compute second filter for lower quarter; only allowed for long windows! + */ + if ((blockType != SHORT_WINDOW) && (tC->confTab.filterEnabled[LOFILT]) && + (tC->confTab.seperateFiltersAllowed)) { + /* compute second filter for lower frequencies */ + + /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen + * algorithm */ + INT predGain; + { + FIXP_DBL predictionGain_m; + INT predictionGain_e; + + CLpc_AutoToParcor(rxx1, 0, parcor_tmp, + tC->confTab.tnsLimitOrder[LOFILT], + &predictionGain_m, &predictionGain_e); + predGain = + (INT)fMultNorm(predictionGain_m, predictionGain_e, 1000, 31, 31); + } + + /* non-linear quantization of TNS lattice coefficients with given + * resolution */ + FDKaacEnc_Parcor2Index(parcor_tmp, + tnsInfo->coef[subBlockNumber][LOFILT], + tC->confTab.tnsLimitOrder[LOFILT], tC->coefRes); + + /* reduce filter order by truncating trailing zeros, compute + * sum(abs(coefs)) */ + for (i = tC->confTab.tnsLimitOrder[LOFILT] - 1; i >= 0; i--) { + if (tnsInfo->coef[subBlockNumber][LOFILT][i] != 0) { + break; + } + } + tnsInfo->order[subBlockNumber][LOFILT] = i + 1; + + sumSqrCoef = 0; + for (; i >= 0; i--) { + sumSqrCoef += tnsInfo->coef[subBlockNumber][LOFILT][i] * + tnsInfo->coef[subBlockNumber][LOFILT][i]; + } + + tnsInfo->direction[subBlockNumber][LOFILT] = + tC->confTab.tnsFilterDirection[LOFILT]; + tnsInfo->length[subBlockNumber][LOFILT] = + tC->lpcStartBand[HIFILT] - tC->lpcStartBand[LOFILT]; + + /* filter lower quarter if gain is high enough, but not if it's too high + */ + if (((predGain > tC->confTab.threshOn[LOFILT]) && + (predGain < (16000 * tC->confTab.tnsLimitOrder[LOFILT]))) || + ((sumSqrCoef > 9) && + (sumSqrCoef < 22 * tC->confTab.tnsLimitOrder[LOFILT]))) { + /* compare lower to upper filter; if they are very similar, merge them + */ + tsbi->tnsActive[LOFILT] = TRUE; + sumSqrCoef = 0; + for (i = 0; i < tC->confTab.tnsLimitOrder[LOFILT]; i++) { + sumSqrCoef += fAbs(tnsInfo->coef[subBlockNumber][HIFILT][i] - + tnsInfo->coef[subBlockNumber][LOFILT][i]); + } + if ((sumSqrCoef < 2) && + (tnsInfo->direction[subBlockNumber][LOFILT] == + tnsInfo->direction[subBlockNumber][HIFILT])) { + tnsData->filtersMerged = TRUE; + tnsInfo->length[subBlockNumber][HIFILT] = + sfbCnt - tC->lpcStartBand[LOFILT]; + for (; i < tnsInfo->order[subBlockNumber][HIFILT]; i++) { + if (fAbs(tnsInfo->coef[subBlockNumber][HIFILT][i]) > 1) { + break; + } + } + for (i--; i >= 0; i--) { + if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) { + break; + } + } + if (i < tnsInfo->order[subBlockNumber][HIFILT]) { + tnsInfo->order[subBlockNumber][HIFILT] = i + 1; + } + } else { + tnsInfo->numOfFilters[subBlockNumber]++; + } + } /* filter lower part */ + tsbi->predictionGain[LOFILT] = predGain; + + } /* second filter allowed */ + } /* if predictionGain > 1437 ... */ + } /* maxOrder > 0 && tnsActive */ + + return 0; +} + +/***************************************************************************/ +/*! + \brief FDKaacLdEnc_TnsSync + + synchronize TNS parameters when TNS gain difference small (relative) + + \param pointer to TNS data structure (destination) + \param pointer to TNS data structure (source) + \param pointer to TNS config structure + \param number of sub-block + \param block type + + \return void +****************************************************************************/ +void FDKaacEnc_TnsSync(TNS_DATA *tnsDataDest, const TNS_DATA *tnsDataSrc, + TNS_INFO *tnsInfoDest, TNS_INFO *tnsInfoSrc, + const INT blockTypeDest, const INT blockTypeSrc, + const TNS_CONFIG *tC) { + int i, w, absDiff, nWindows; + TNS_SUBBLOCK_INFO *sbInfoDest; + const TNS_SUBBLOCK_INFO *sbInfoSrc; + + /* if one channel contains short blocks and the other not, do not synchronize + */ + if ((blockTypeSrc == SHORT_WINDOW && blockTypeDest != SHORT_WINDOW) || + (blockTypeDest == SHORT_WINDOW && blockTypeSrc != SHORT_WINDOW)) { + return; + } + + if (blockTypeDest != SHORT_WINDOW) { + sbInfoDest = &tnsDataDest->dataRaw.Long.subBlockInfo; + sbInfoSrc = &tnsDataSrc->dataRaw.Long.subBlockInfo; + nWindows = 1; + } else { + sbInfoDest = &tnsDataDest->dataRaw.Short.subBlockInfo[0]; + sbInfoSrc = &tnsDataSrc->dataRaw.Short.subBlockInfo[0]; + nWindows = 8; + } + + for (w = 0; w < nWindows; w++) { + const TNS_SUBBLOCK_INFO *pSbInfoSrcW = sbInfoSrc + w; + TNS_SUBBLOCK_INFO *pSbInfoDestW = sbInfoDest + w; + INT doSync = 1, absDiffSum = 0; + + /* if TNS is active in at least one channel, check if ParCor coefficients of + * higher filter are similar */ + if (pSbInfoDestW->tnsActive[HIFILT] || pSbInfoSrcW->tnsActive[HIFILT]) { + for (i = 0; i < tC->maxOrder; i++) { + absDiff = fAbs(tnsInfoDest->coef[w][HIFILT][i] - + tnsInfoSrc->coef[w][HIFILT][i]); + absDiffSum += absDiff; + /* if coefficients diverge too much between channels, do not synchronize + */ + if ((absDiff > 1) || (absDiffSum > 2)) { + doSync = 0; + break; + } + } + + if (doSync) { + /* if no significant difference was detected, synchronize coefficient + * sets */ + if (pSbInfoSrcW->tnsActive[HIFILT]) { + /* no dest filter, or more dest than source filters: use one dest + * filter */ + if ((!pSbInfoDestW->tnsActive[HIFILT]) || + ((pSbInfoDestW->tnsActive[HIFILT]) && + (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w]))) { + pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 1; + } + tnsDataDest->filtersMerged = tnsDataSrc->filtersMerged; + tnsInfoDest->order[w][HIFILT] = tnsInfoSrc->order[w][HIFILT]; + tnsInfoDest->length[w][HIFILT] = tnsInfoSrc->length[w][HIFILT]; + tnsInfoDest->direction[w][HIFILT] = tnsInfoSrc->direction[w][HIFILT]; + tnsInfoDest->coefCompress[w][HIFILT] = + tnsInfoSrc->coefCompress[w][HIFILT]; + + for (i = 0; i < tC->maxOrder; i++) { + tnsInfoDest->coef[w][HIFILT][i] = tnsInfoSrc->coef[w][HIFILT][i]; + } + } else + pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 0; + } + } + } +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_TnsEncode + + perform TNS encoding + + \param pointer to TNS info structure + \param pointer to TNS data structure + \param number of sfbs + \param pointer to TNS config structure + \param low-pass line + \param pointer to spectrum + \param number of sub-block + \param block type + + \return ERROR STATUS +****************************************************************************/ +INT FDKaacEnc_TnsEncode(TNS_INFO *tnsInfo, TNS_DATA *tnsData, + const INT numOfSfb, const TNS_CONFIG *tC, + const INT lowPassLine, FIXP_DBL *spectrum, + const INT subBlockNumber, const INT blockType) { + INT i, startLine, stopLine; + + if (((blockType == SHORT_WINDOW) && + (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber] + .tnsActive[HIFILT])) || + ((blockType != SHORT_WINDOW) && + (!tnsData->dataRaw.Long.subBlockInfo.tnsActive[HIFILT]))) { + return 1; + } + + startLine = (tnsData->filtersMerged) ? tC->lpcStartLine[LOFILT] + : tC->lpcStartLine[HIFILT]; + stopLine = tC->lpcStopLine; + + for (i = 0; i < tnsInfo->numOfFilters[subBlockNumber]; i++) { + INT lpcGainFactor; + FIXP_LPC LpcCoeff[TNS_MAX_ORDER]; + FIXP_DBL workBuffer[TNS_MAX_ORDER]; + FIXP_LPC parcor_tmp[TNS_MAX_ORDER]; + + FDKaacEnc_Index2Parcor(tnsInfo->coef[subBlockNumber][i], parcor_tmp, + tnsInfo->order[subBlockNumber][i], tC->coefRes); + + lpcGainFactor = CLpc_ParcorToLpc( + parcor_tmp, LpcCoeff, tnsInfo->order[subBlockNumber][i], workBuffer); + + FDKmemclear(workBuffer, TNS_MAX_ORDER * sizeof(FIXP_DBL)); + CLpc_Analysis(&spectrum[startLine], stopLine - startLine, LpcCoeff, + lpcGainFactor, tnsInfo->order[subBlockNumber][i], workBuffer, + NULL); + + /* update for second filter */ + startLine = tC->lpcStartLine[LOFILT]; + stopLine = tC->lpcStartLine[HIFILT]; + } + + return (0); +} + +static void FDKaacEnc_CalcGaussWindow(FIXP_DBL *win, const int winSize, + const INT samplingRate, + const INT transformResolution, + const FIXP_DBL timeResolution, + const INT timeResolution_e) { +#define PI_E (2) +#define PI_M FL2FXCONST_DBL(3.1416f / (float)(1 << PI_E)) + +#define EULER_E (2) +#define EULER_M FL2FXCONST_DBL(2.7183 / (float)(1 << EULER_E)) + +#define COEFF_LOOP_SCALE (4) + + INT i, e1, e2, gaussExp_e; + FIXP_DBL gaussExp_m; + + /* calc. window exponent from time resolution: + * + * gaussExp = PI * samplingRate * 0.001f * timeResolution / + * transformResolution; gaussExp = -0.5f * gaussExp * gaussExp; + */ + gaussExp_m = fMultNorm( + timeResolution, + fMult(PI_M, + fDivNorm((FIXP_DBL)(samplingRate), + (FIXP_DBL)(LONG)(transformResolution * 1000.f), &e1)), + &e2); + gaussExp_m = -fPow2Div2(gaussExp_m); + gaussExp_e = 2 * (e1 + e2 + timeResolution_e + PI_E); + + FDK_ASSERT(winSize < (1 << COEFF_LOOP_SCALE)); + + /* calc. window coefficients + * win[i] = (float)exp( gaussExp * (i+0.5) * (i+0.5) ); + */ + for (i = 0; i < winSize; i++) { + win[i] = fPow( + EULER_M, EULER_E, + fMult(gaussExp_m, + fPow2((i * FL2FXCONST_DBL(1.f / (float)(1 << COEFF_LOOP_SCALE)) + + FL2FXCONST_DBL(.5f / (float)(1 << COEFF_LOOP_SCALE))))), + gaussExp_e + 2 * COEFF_LOOP_SCALE, &e1); + + win[i] = scaleValueSaturate(win[i], e1); + } +} + +static INT FDKaacEnc_Search3(FIXP_LPC parcor) { + INT i, index = 0; + + for (i = 0; i < 8; i++) { + if (parcor > FDKaacEnc_tnsCoeff3Borders[i]) index = i; + } + return (index - 4); +} + +static INT FDKaacEnc_Search4(FIXP_LPC parcor) { + INT i, index = 0; + + for (i = 0; i < 16; i++) { + if (parcor > FDKaacEnc_tnsCoeff4Borders[i]) index = i; + } + return (index - 8); +} + +/***************************************************************************** + + functionname: FDKaacEnc_Parcor2Index + +*****************************************************************************/ +static void FDKaacEnc_Parcor2Index(const FIXP_LPC *parcor, INT *RESTRICT index, + const INT order, const INT bitsPerCoeff) { + INT i; + for (i = 0; i < order; i++) { + if (bitsPerCoeff == 3) + index[i] = FDKaacEnc_Search3(parcor[i]); + else + index[i] = FDKaacEnc_Search4(parcor[i]); + } +} + +/***************************************************************************** + + functionname: FDKaacEnc_Index2Parcor + description: inverse quantization for reflection coefficients + returns: - + input: quantized values, ptr. to reflection coefficients, + no. of coefficients, resolution + output: reflection coefficients + +*****************************************************************************/ +static void FDKaacEnc_Index2Parcor(const INT *index, FIXP_LPC *RESTRICT parcor, + const INT order, const INT bitsPerCoeff) { + INT i; + for (i = 0; i < order; i++) + parcor[i] = bitsPerCoeff == 4 ? FDKaacEnc_tnsEncCoeff4[index[i] + 8] + : FDKaacEnc_tnsEncCoeff3[index[i] + 4]; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_tns.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_tns.h new file mode 100644 index 0000000000000..a37f978e23e9c --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/aacenc_tns.h @@ -0,0 +1,213 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): Alex Groeschel + + Description: Temporal noise shaping + +*******************************************************************************/ + +#ifndef AACENC_TNS_H +#define AACENC_TNS_H + +#include "common_fix.h" + +#include "psy_const.h" + +#ifndef PI +#define PI 3.1415926535897931f +#endif + +/** + * TNS_ENABLE_MASK + * This bitfield defines which TNS features are enabled + * The TNS mask is composed of 4 bits. + * tnsMask |= 0x1; activate TNS short blocks + * tnsMask |= 0x2; activate TNS for long blocks + * tnsMask |= 0x4; activate TNS PEAK tool for short blocks + * tnsMask |= 0x8; activate TNS PEAK tool for long blocks + */ +#define TNS_ENABLE_MASK 0xf + +/* TNS max filter order for Low Complexity MPEG4 profile */ +#define TNS_MAX_ORDER 12 + +#define MAX_NUM_OF_FILTERS 2 + +#define HIFILT 0 /* index of higher filter */ +#define LOFILT 1 /* index of lower filter */ + +typedef struct { /* stuff that is tabulated dependent on bitrate etc. */ + INT filterEnabled[MAX_NUM_OF_FILTERS]; + INT threshOn[MAX_NUM_OF_FILTERS]; /* min. prediction gain for using tns + TABUL*/ + INT filterStartFreq[MAX_NUM_OF_FILTERS]; /* lowest freq for lpc TABUL*/ + INT tnsLimitOrder[MAX_NUM_OF_FILTERS]; /* Limit for TNS order TABUL*/ + INT tnsFilterDirection[MAX_NUM_OF_FILTERS]; /* Filtering direction, 0=up, + 1=down TABUL */ + INT acfSplit[MAX_NUM_OF_FILTERS]; + FIXP_DBL tnsTimeResolution[MAX_NUM_OF_FILTERS]; /* TNS max. time resolution + TABUL. Should be fract but + MSVC won't compile then */ + INT seperateFiltersAllowed; +} TNS_PARAMETER_TABULATED; + +typedef struct { /*assigned at InitTime*/ + TNS_PARAMETER_TABULATED confTab; + INT isLowDelay; + INT tnsActive; + INT maxOrder; /* max. order of tns filter */ + INT coefRes; + FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER + 3 + 1]; + /* now some things that only probably can be done at Init time; + could be they have to be split up for each individual (short) window or + even filter. */ + INT lpcStartBand[MAX_NUM_OF_FILTERS]; + INT lpcStartLine[MAX_NUM_OF_FILTERS]; + INT lpcStopBand; + INT lpcStopLine; + +} TNS_CONFIG; + +typedef struct { + INT tnsActive[MAX_NUM_OF_FILTERS]; + INT predictionGain[MAX_NUM_OF_FILTERS]; +} TNS_SUBBLOCK_INFO; + +typedef struct { /*changed at runTime*/ + TNS_SUBBLOCK_INFO subBlockInfo[TRANS_FAC]; + FIXP_DBL ratioMultTable[TRANS_FAC][MAX_SFB_SHORT]; +} TNS_DATA_SHORT; + +typedef struct { /*changed at runTime*/ + TNS_SUBBLOCK_INFO subBlockInfo; + FIXP_DBL ratioMultTable[MAX_SFB_LONG]; +} TNS_DATA_LONG; + +/* can be implemented as union */ +typedef shouldBeUnion { + TNS_DATA_LONG Long; + TNS_DATA_SHORT Short; +} +TNS_DATA_RAW; + +typedef struct { + INT numOfSubblocks; + TNS_DATA_RAW dataRaw; + INT tnsMaxScaleSpec; + INT filtersMerged; +} TNS_DATA; + +typedef struct { + INT numOfFilters[TRANS_FAC]; + INT coefRes[TRANS_FAC]; + INT length[TRANS_FAC][MAX_NUM_OF_FILTERS]; + INT order[TRANS_FAC][MAX_NUM_OF_FILTERS]; + INT direction[TRANS_FAC][MAX_NUM_OF_FILTERS]; + INT coefCompress[TRANS_FAC][MAX_NUM_OF_FILTERS]; + /* for Long: length TNS_MAX_ORDER (12 for LC) is required -> 12 */ + /* for Short: length TRANS_FAC*TNS_MAX_ORDER (only 5 for short LC) is required + * -> 8*5=40 */ + /* Currently TRANS_FAC*TNS_MAX_ORDER = 8*12 = 96 (for LC) is used (per + * channel)! Memory could be saved here! */ + INT coef[TRANS_FAC][MAX_NUM_OF_FILTERS][TNS_MAX_ORDER]; +} TNS_INFO; + +INT FDKaacEnc_FreqToBandWidthRounding(const INT freq, const INT fs, + const INT numOfBands, + const INT *bandStartOffset); + +#endif /* AACENC_TNS_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/adj_thr.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/adj_thr.cpp new file mode 100644 index 0000000000000..239abd00f2643 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/adj_thr.cpp @@ -0,0 +1,2914 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Threshold compensation + +*******************************************************************************/ + +#include "adj_thr.h" +#include "sf_estim.h" +#include "aacEnc_ram.h" + +#define NUM_NRG_LEVS (8) +#define INV_INT_TAB_SIZE (8) +static const FIXP_DBL invInt[INV_INT_TAB_SIZE] = { + 0x7fffffff, 0x7fffffff, 0x40000000, 0x2aaaaaaa, + 0x20000000, 0x19999999, 0x15555555, 0x12492492}; + +#define INV_SQRT4_TAB_SIZE (8) +static const FIXP_DBL invSqrt4[INV_SQRT4_TAB_SIZE] = { + 0x7fffffff, 0x7fffffff, 0x6ba27e65, 0x61424bb5, + 0x5a827999, 0x55994845, 0x51c8e33c, 0x4eb160d1}; + +/*static const INT invRedExp = 4;*/ +static const FIXP_DBL SnrLdMin1 = + (FIXP_DBL)0xfcad0ddf; /*FL2FXCONST_DBL(FDKlog(0.316)/FDKlog(2.0)/LD_DATA_SCALING);*/ +static const FIXP_DBL SnrLdMin2 = + (FIXP_DBL)0x0351e1a2; /*FL2FXCONST_DBL(FDKlog(3.16) + /FDKlog(2.0)/LD_DATA_SCALING);*/ +static const FIXP_DBL SnrLdFac = + (FIXP_DBL)0xff5b2c3e; /*FL2FXCONST_DBL(FDKlog(0.8) + /FDKlog(2.0)/LD_DATA_SCALING);*/ + +static const FIXP_DBL SnrLdMin3 = + (FIXP_DBL)0xfe000000; /*FL2FXCONST_DBL(FDKlog(0.5) + /FDKlog(2.0)/LD_DATA_SCALING);*/ +static const FIXP_DBL SnrLdMin4 = + (FIXP_DBL)0x02000000; /*FL2FXCONST_DBL(FDKlog(2.0) + /FDKlog(2.0)/LD_DATA_SCALING);*/ +static const FIXP_DBL SnrLdMin5 = + (FIXP_DBL)0xfc000000; /*FL2FXCONST_DBL(FDKlog(0.25) + /FDKlog(2.0)/LD_DATA_SCALING);*/ + +/* +The bits2Pe factors are choosen for the case that some times +the crash recovery strategy will be activated once. +*/ +#define AFTERBURNER_STATI 2 +#define MAX_ALLOWED_EL_CHANNELS 2 + +typedef struct { + INT bitrate; + FIXP_DBL bits2PeFactor[AFTERBURNER_STATI][MAX_ALLOWED_EL_CHANNELS]; +} BIT_PE_SFAC; + +typedef struct { + INT sampleRate; + const BIT_PE_SFAC *pPeTab; + INT nEntries; + +} BITS2PE_CFG_TAB; + +#define FL2B2PE(value) FL2FXCONST_DBL((value) / (1 << 2)) + +static const BIT_PE_SFAC S_Bits2PeTab16000[] = { + /* bitrate| afterburner off | afterburner on | | nCh=1 + | nCh=2 | nCh=1 | nCh=2 */ + {10000, + {{FL2B2PE(1.60f), FL2B2PE(0.00f)}, {FL2B2PE(1.40f), FL2B2PE(0.00f)}}}, + {24000, + {{FL2B2PE(1.80f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}}, + {32000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {48000, + {{FL2B2PE(1.60f), FL2B2PE(1.80f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}}, + {64000, + {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.20f), FL2B2PE(1.60f)}}}, + {96000, + {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}}, + {128000, + {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.80f)}}}, + {148000, + {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.40f)}}}}; + +static const BIT_PE_SFAC S_Bits2PeTab22050[] = { + /* bitrate| afterburner off | afterburner on | | nCh=1 + | nCh=2 | nCh=1 | nCh=2 */ + {16000, + {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}}, + {24000, + {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.40f), FL2B2PE(1.00f)}}}, + {32000, + {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.40f), FL2B2PE(1.20f)}}}, + {48000, + {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.20f), FL2B2PE(1.40f)}}}, + {64000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {96000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}}, + {128000, + {{FL2B2PE(1.80f), FL2B2PE(1.80f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}}, + {148000, + {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}}}; + +static const BIT_PE_SFAC S_Bits2PeTab24000[] = { + /* bitrate| afterburner off | afterburner on | | nCh=1 + | nCh=2 | nCh=1 | nCh=2 */ + {16000, + {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}}, + {24000, + {{FL2B2PE(1.60f), FL2B2PE(1.20f)}, {FL2B2PE(1.40f), FL2B2PE(1.00f)}}}, + {32000, + {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.40f), FL2B2PE(0.80f)}}}, + {48000, + {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.40f)}}}, + {64000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {96000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}}, + {128000, + {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.80f)}}}, + {148000, + {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.80f)}}}}; + +static const BIT_PE_SFAC S_Bits2PeTab32000[] = { + /* bitrate| afterburner off | afterburner on | | nCh=1 + | nCh=2 | nCh=1 | nCh=2 */ + {16000, + {{FL2B2PE(1.20f), FL2B2PE(1.40f)}, {FL2B2PE(0.80f), FL2B2PE(0.80f)}}}, + {24000, + {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.60f)}}}, + {32000, + {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}}, + {48000, + {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(1.20f)}}}, + {64000, + {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}}, + {96000, + {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {128000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}}, + {148000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}}, + {160000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}}, + {200000, + {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}}, + {320000, + {{FL2B2PE(3.20f), FL2B2PE(1.80f)}, {FL2B2PE(3.20f), FL2B2PE(1.80f)}}}}; + +static const BIT_PE_SFAC S_Bits2PeTab44100[] = { + /* bitrate| afterburner off | afterburner on | | nCh=1 + | nCh=2 | nCh=1 | nCh=2 */ + {16000, + {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(0.80f), FL2B2PE(1.00f)}}}, + {24000, + {{FL2B2PE(1.00f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}}, + {32000, + {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(0.80f), FL2B2PE(0.60f)}}}, + {48000, + {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}}, + {64000, + {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(1.00f)}}}, + {96000, + {{FL2B2PE(1.60f), FL2B2PE(1.20f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}}, + {128000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {148000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}}, + {160000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}}, + {200000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}}, + {320000, + {{FL2B2PE(3.20f), FL2B2PE(1.60f)}, {FL2B2PE(3.20f), FL2B2PE(1.60f)}}}}; + +static const BIT_PE_SFAC S_Bits2PeTab48000[] = { + /* bitrate| afterburner off | afterburner on | | nCh=1 + | nCh=2 | nCh=1 | nCh=2 */ + {16000, + {{FL2B2PE(1.40f), FL2B2PE(0.00f)}, {FL2B2PE(0.80f), FL2B2PE(0.00f)}}}, + {24000, + {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}}, + {32000, + {{FL2B2PE(1.00f), FL2B2PE(1.20f)}, {FL2B2PE(0.60f), FL2B2PE(0.80f)}}}, + {48000, + {{FL2B2PE(1.20f), FL2B2PE(1.00f)}, {FL2B2PE(0.80f), FL2B2PE(0.80f)}}}, + {64000, + {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(1.00f)}}}, + {96000, + {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}}, + {128000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {148000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {160000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {200000, + {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {320000, + {{FL2B2PE(3.20f), FL2B2PE(1.60f)}, {FL2B2PE(3.20f), FL2B2PE(1.60f)}}}}; + +static const BITS2PE_CFG_TAB bits2PeConfigTab[] = { + {16000, S_Bits2PeTab16000, sizeof(S_Bits2PeTab16000) / sizeof(BIT_PE_SFAC)}, + {22050, S_Bits2PeTab22050, sizeof(S_Bits2PeTab22050) / sizeof(BIT_PE_SFAC)}, + {24000, S_Bits2PeTab24000, sizeof(S_Bits2PeTab24000) / sizeof(BIT_PE_SFAC)}, + {32000, S_Bits2PeTab32000, sizeof(S_Bits2PeTab32000) / sizeof(BIT_PE_SFAC)}, + {44100, S_Bits2PeTab44100, sizeof(S_Bits2PeTab44100) / sizeof(BIT_PE_SFAC)}, + {48000, S_Bits2PeTab48000, + sizeof(S_Bits2PeTab48000) / sizeof(BIT_PE_SFAC)}}; + +/* values for avoid hole flag */ +enum _avoid_hole_state { NO_AH = 0, AH_INACTIVE = 1, AH_ACTIVE = 2 }; + +/* Q format definitions */ +#define Q_BITFAC \ + (24) /* Q scaling used in FDKaacEnc_bitresCalcBitFac() calculation */ +#define Q_AVGBITS (17) /* scale bit values */ + +/***************************************************************************** + functionname: FDKaacEnc_InitBits2PeFactor + description: retrieve bits2PeFactor from table +*****************************************************************************/ +static void FDKaacEnc_InitBits2PeFactor( + FIXP_DBL *bits2PeFactor_m, INT *bits2PeFactor_e, const INT bitRate, + const INT nChannels, const INT sampleRate, const INT advancedBitsToPe, + const INT dZoneQuantEnable, const INT invQuant) { + /**** 1) Set default bits2pe factor ****/ + FIXP_DBL bit2PE_m = FL2FXCONST_DBL(1.18f / (1 << (1))); + INT bit2PE_e = 1; + + /**** 2) For AAC-(E)LD, make use of advanced bits to pe factor table ****/ + if (advancedBitsToPe && nChannels <= (2)) { + int i; + const BIT_PE_SFAC *peTab = NULL; + INT size = 0; + + /*** 2.1) Get correct table entry ***/ + for (i = 0; i < (INT)(sizeof(bits2PeConfigTab) / sizeof(BITS2PE_CFG_TAB)); + i++) { + if (sampleRate >= bits2PeConfigTab[i].sampleRate) { + peTab = bits2PeConfigTab[i].pPeTab; + size = bits2PeConfigTab[i].nEntries; + } + } + + if ((peTab != NULL) && (size != 0)) { + INT startB = -1; /* bitrate entry in table that is the next-lower to + actual bitrate */ + INT stopB = -1; /* bitrate entry in table that is the next-higher to + actual bitrate */ + FIXP_DBL startPF = + FL2FXCONST_DBL(0.0f); /* bits2PE factor entry in table that is the + next-lower to actual bits2PE factor */ + FIXP_DBL stopPF = FL2FXCONST_DBL(0.0f); /* bits2PE factor entry in table + that is the next-higher to + actual bits2PE factor */ + FIXP_DBL slope = FL2FXCONST_DBL( + 0.0f); /* the slope from the start bits2Pe entry to the next one */ + const int qualityIdx = (invQuant == 0) ? 0 : 1; + + if (bitRate >= peTab[size - 1].bitrate) { + /* Chosen bitrate is higher than the highest bitrate in table. + The slope for extrapolating the bits2PE factor must be zero. + Values are set accordingly. */ + startB = peTab[size - 1].bitrate; + stopB = + bitRate + + 1; /* Can be an arbitrary value greater than startB and bitrate. */ + startPF = peTab[size - 1].bits2PeFactor[qualityIdx][nChannels - 1]; + stopPF = peTab[size - 1].bits2PeFactor[qualityIdx][nChannels - 1]; + } else { + for (i = 0; i < size - 1; i++) { + if ((peTab[i].bitrate <= bitRate) && + (peTab[i + 1].bitrate > bitRate)) { + startB = peTab[i].bitrate; + stopB = peTab[i + 1].bitrate; + startPF = peTab[i].bits2PeFactor[qualityIdx][nChannels - 1]; + stopPF = peTab[i + 1].bits2PeFactor[qualityIdx][nChannels - 1]; + break; + } + } + } + + /*** 2.2) Configuration available? ***/ + if (startB != -1) { + /** 2.2.1) linear interpolate to actual PEfactor **/ + FIXP_DBL bit2PE = 0; + + const FIXP_DBL maxBit2PE = FL2FXCONST_DBL(3.f / 4.f); + + /* bit2PE = ((stopPF-startPF)/(stopB-startB))*(bitRate-startB)+startPF; + */ + slope = fDivNorm(bitRate - startB, stopB - startB); + bit2PE = fMult(slope, stopPF - startPF) + startPF; + + bit2PE = fMin(maxBit2PE, bit2PE); + + /** 2.2.2) sanity check if bits2pe value is high enough **/ + if (bit2PE >= (FL2FXCONST_DBL(0.35f) >> 2)) { + bit2PE_m = bit2PE; + bit2PE_e = 2; /* table is fixed scaled */ + } + } /* br */ + } /* sr */ + } /* advancedBitsToPe */ + + if (dZoneQuantEnable) { + if (bit2PE_m >= (FL2FXCONST_DBL(0.6f)) >> bit2PE_e) { + /* Additional headroom for addition */ + bit2PE_m >>= 1; + bit2PE_e += 1; + } + + /* the quantTendencyCompensator compensates a lower bit consumption due to + * increasing the tendency to quantize low spectral values to the lower + * quantizer border for bitrates below a certain bitrate threshold --> see + * also function calcSfbDistLD in quantize.c */ + if ((bitRate / nChannels > 32000) && (bitRate / nChannels <= 40000)) { + bit2PE_m += (FL2FXCONST_DBL(0.4f)) >> bit2PE_e; + } else if (bitRate / nChannels > 20000) { + bit2PE_m += (FL2FXCONST_DBL(0.3f)) >> bit2PE_e; + } else if (bitRate / nChannels >= 16000) { + bit2PE_m += (FL2FXCONST_DBL(0.3f)) >> bit2PE_e; + } else { + bit2PE_m += (FL2FXCONST_DBL(0.0f)) >> bit2PE_e; + } + } + + /***** 3.) Return bits2pe factor *****/ + *bits2PeFactor_m = bit2PE_m; + *bits2PeFactor_e = bit2PE_e; +} + +/***************************************************************************** +functionname: FDKaacEnc_bits2pe2 +description: convert from bits to pe +*****************************************************************************/ +FDK_INLINE INT FDKaacEnc_bits2pe2(const INT bits, const FIXP_DBL factor_m, + const INT factor_e) { + return (INT)(fMult(factor_m, (FIXP_DBL)(bits << Q_AVGBITS)) >> + (Q_AVGBITS - factor_e)); +} + +/***************************************************************************** +functionname: FDKaacEnc_calcThreshExp +description: loudness calculation (threshold to the power of redExp) +*****************************************************************************/ +static void FDKaacEnc_calcThreshExp( + FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], + const QC_OUT_CHANNEL *const qcOutChannel[(2)], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], const INT nChannels) { + INT ch, sfb, sfbGrp; + FIXP_DBL thrExpLdData; + + for (ch = 0; ch < nChannels; ch++) { + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + thrExpLdData = psyOutChannel[ch]->sfbThresholdLdData[sfbGrp + sfb] >> 2; + thrExp[ch][sfbGrp + sfb] = CalcInvLdData(thrExpLdData); + } + } + } +} + +/***************************************************************************** + functionname: FDKaacEnc_adaptMinSnr + description: reduce minSnr requirements for bands with relative low +energies +*****************************************************************************/ +static void FDKaacEnc_adaptMinSnr( + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + const MINSNR_ADAPT_PARAM *const msaParam, const INT nChannels) { + INT ch, sfb, sfbGrp, nSfb; + FIXP_DBL avgEnLD64, dbRatio, minSnrRed; + FIXP_DBL minSnrLimitLD64 = + FL2FXCONST_DBL(-0.00503012648262f); /* ld64(0.8f) */ + FIXP_DBL nSfbLD64; + FIXP_DBL accu; + + FIXP_DBL msaParam_maxRed = msaParam->maxRed; + FIXP_DBL msaParam_startRatio = msaParam->startRatio; + FIXP_DBL msaParam_redRatioFac = + fMult(msaParam->redRatioFac, FL2FXCONST_DBL(0.3010299956f)); + FIXP_DBL msaParam_redOffs = msaParam->redOffs; + + for (ch = 0; ch < nChannels; ch++) { + /* calc average energy per scalefactor band */ + nSfb = 0; + accu = FL2FXCONST_DBL(0.0f); + + DWORD_ALIGNED(psyOutChannel[ch]->sfbEnergy); + + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + int maxSfbPerGroup = psyOutChannel[ch]->maxSfbPerGroup; + nSfb += maxSfbPerGroup; + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + accu += psyOutChannel[ch]->sfbEnergy[sfbGrp + sfb] >> 6; + } + } + + if ((accu == FL2FXCONST_DBL(0.0f)) || (nSfb == 0)) { + avgEnLD64 = FL2FXCONST_DBL(-1.0f); + } else { + nSfbLD64 = CalcLdInt(nSfb); + avgEnLD64 = CalcLdData(accu); + avgEnLD64 = avgEnLD64 + FL2FXCONST_DBL(0.09375f) - + nSfbLD64; /* 0.09375f: compensate shift with 6 */ + } + + /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */ + int maxSfbPerGroup = psyOutChannel[ch]->maxSfbPerGroup; + int sfbCnt = psyOutChannel[ch]->sfbCnt; + int sfbPerGroup = psyOutChannel[ch]->sfbPerGroup; + + for (sfbGrp = 0; sfbGrp < sfbCnt; sfbGrp += sfbPerGroup) { + FIXP_DBL *RESTRICT psfbEnergyLdData = + &qcOutChannel[ch]->sfbEnergyLdData[sfbGrp]; + FIXP_DBL *RESTRICT psfbMinSnrLdData = + &qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp]; + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + FIXP_DBL sfbEnergyLdData = *psfbEnergyLdData++; + FIXP_DBL sfbMinSnrLdData = *psfbMinSnrLdData; + dbRatio = avgEnLD64 - sfbEnergyLdData; + int update = (msaParam_startRatio < dbRatio) ? 1 : 0; + minSnrRed = msaParam_redOffs + fMult(msaParam_redRatioFac, + dbRatio); /* scaled by 1.0f/64.0f*/ + minSnrRed = + fixMax(minSnrRed, msaParam_maxRed); /* scaled by 1.0f/64.0f*/ + minSnrRed = (fMult(sfbMinSnrLdData, minSnrRed)) << 6; + minSnrRed = fixMin(minSnrLimitLD64, minSnrRed); + *psfbMinSnrLdData++ = update ? minSnrRed : sfbMinSnrLdData; + } + } + } +} + +/***************************************************************************** +functionname: FDKaacEnc_initAvoidHoleFlag +description: determine bands where avoid hole is not necessary resp. possible +*****************************************************************************/ +static void FDKaacEnc_initAvoidHoleFlag( + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + UCHAR ahFlag[(2)][MAX_GROUPED_SFB], const struct TOOLSINFO *const toolsInfo, + const INT nChannels, const AH_PARAM *const ahParam) { + INT ch, sfb, sfbGrp; + FIXP_DBL sfbEn, sfbEnm1; + FIXP_DBL sfbEnLdData; + FIXP_DBL avgEnLdData; + + /* decrease spread energy by 3dB for long blocks, resp. 2dB for shorts + (avoid more holes in long blocks) */ + for (ch = 0; ch < nChannels; ch++) { + QC_OUT_CHANNEL *const qcOutChan = qcOutChannel[ch]; + + if (psyOutChannel[ch]->lastWindowSequence != SHORT_WINDOW) { + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) + qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] >>= 1; + } else { + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) + qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] = fMult( + FL2FXCONST_DBL(0.63f), qcOutChan->sfbSpreadEnergy[sfbGrp + sfb]); + } + } + + /* increase minSnr for local peaks, decrease it for valleys */ + if (ahParam->modifyMinSnr) { + for (ch = 0; ch < nChannels; ch++) { + QC_OUT_CHANNEL *const qcOutChan = qcOutChannel[ch]; + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + FIXP_DBL sfbEnp1, avgEn; + if (sfb > 0) + sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp + sfb - 1]; + else + sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp + sfb]; + + if (sfb < psyOutChannel[ch]->maxSfbPerGroup - 1) + sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp + sfb + 1]; + else + sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp + sfb]; + + avgEn = (sfbEnm1 >> 1) + (sfbEnp1 >> 1); + avgEnLdData = CalcLdData(avgEn); + sfbEn = qcOutChan->sfbEnergy[sfbGrp + sfb]; + sfbEnLdData = qcOutChan->sfbEnergyLdData[sfbGrp + sfb]; + /* peak ? */ + if (sfbEn > avgEn) { + FIXP_DBL tmpMinSnrLdData; + if (psyOutChannel[ch]->lastWindowSequence == LONG_WINDOW) + tmpMinSnrLdData = SnrLdFac + fixMax(avgEnLdData - sfbEnLdData, + SnrLdMin1 - SnrLdFac); + else + tmpMinSnrLdData = SnrLdFac + fixMax(avgEnLdData - sfbEnLdData, + SnrLdMin3 - SnrLdFac); + + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] = fixMin( + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb], tmpMinSnrLdData); + } + /* valley ? */ + if (((sfbEnLdData + (FIXP_DBL)SnrLdMin4) < (FIXP_DBL)avgEnLdData) && + (sfbEn > FL2FXCONST_DBL(0.0))) { + FIXP_DBL tmpMinSnrLdData = avgEnLdData - sfbEnLdData - + (FIXP_DBL)SnrLdMin4 + + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]; + tmpMinSnrLdData = fixMin((FIXP_DBL)SnrLdFac, tmpMinSnrLdData); + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] = + fixMin(tmpMinSnrLdData, + (FIXP_DBL)(qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + + SnrLdMin2)); + } + } + } + } + } + + /* stereo: adapt the minimum requirements sfbMinSnr of mid and + side channels to avoid spending unnoticable bits */ + if (nChannels == 2) { + QC_OUT_CHANNEL *qcOutChanM = qcOutChannel[0]; + QC_OUT_CHANNEL *qcOutChanS = qcOutChannel[1]; + const PSY_OUT_CHANNEL *const psyOutChanM = psyOutChannel[0]; + for (sfbGrp = 0; sfbGrp < psyOutChanM->sfbCnt; + sfbGrp += psyOutChanM->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChanM->maxSfbPerGroup; sfb++) { + if (toolsInfo->msMask[sfbGrp + sfb]) { + FIXP_DBL maxSfbEnLd = + fixMax(qcOutChanM->sfbEnergyLdData[sfbGrp + sfb], + qcOutChanS->sfbEnergyLdData[sfbGrp + sfb]); + FIXP_DBL maxThrLd, sfbMinSnrTmpLd; + + if (((SnrLdMin5 >> 1) + (maxSfbEnLd >> 1) + + (qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] >> 1)) <= + FL2FXCONST_DBL(-0.5f)) + maxThrLd = FL2FXCONST_DBL(-1.0f); + else + maxThrLd = SnrLdMin5 + maxSfbEnLd + + qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb]; + + if (qcOutChanM->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f)) + sfbMinSnrTmpLd = + maxThrLd - qcOutChanM->sfbEnergyLdData[sfbGrp + sfb]; + else + sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f); + + qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] = + fixMax(qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb], sfbMinSnrTmpLd); + + if (qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] <= FL2FXCONST_DBL(0.0f)) + qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] = fixMin( + qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb], (FIXP_DBL)SnrLdFac); + + if (qcOutChanS->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f)) + sfbMinSnrTmpLd = + maxThrLd - qcOutChanS->sfbEnergyLdData[sfbGrp + sfb]; + else + sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f); + + qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] = + fixMax(qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb], sfbMinSnrTmpLd); + + if (qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] <= FL2FXCONST_DBL(0.0f)) + qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] = fixMin( + qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb], (FIXP_DBL)SnrLdFac); + + if (qcOutChanM->sfbEnergy[sfbGrp + sfb] > + qcOutChanM->sfbSpreadEnergy[sfbGrp + sfb]) + qcOutChanS->sfbSpreadEnergy[sfbGrp + sfb] = fMult( + qcOutChanS->sfbEnergy[sfbGrp + sfb], FL2FXCONST_DBL(0.9f)); + + if (qcOutChanS->sfbEnergy[sfbGrp + sfb] > + qcOutChanS->sfbSpreadEnergy[sfbGrp + sfb]) + qcOutChanM->sfbSpreadEnergy[sfbGrp + sfb] = fMult( + qcOutChanM->sfbEnergy[sfbGrp + sfb], FL2FXCONST_DBL(0.9f)); + + } /* if (toolsInfo->msMask[sfbGrp+sfb]) */ + } /* sfb */ + } /* sfbGrp */ + } /* nChannels==2 */ + + /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ + for (ch = 0; ch < nChannels; ch++) { + QC_OUT_CHANNEL *qcOutChan = qcOutChannel[ch]; + const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch]; + for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; + sfbGrp += psyOutChan->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) { + if ((qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] > + qcOutChan->sfbEnergy[sfbGrp + sfb]) || + (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f))) { + ahFlag[ch][sfbGrp + sfb] = NO_AH; + } else { + ahFlag[ch][sfbGrp + sfb] = AH_INACTIVE; + } + } + } + } +} + +/** + * \brief Calculate constants that do not change during successive pe + * calculations. + * + * \param peData Pointer to structure containing PE data of + * current element. + * \param psyOutChannel Pointer to PSY_OUT_CHANNEL struct holding + * nChannels elements. + * \param qcOutChannel Pointer to QC_OUT_CHANNEL struct holding + * nChannels elements. + * \param nChannels Number of channels in element. + * \param peOffset Fixed PE offset defined while + * FDKaacEnc_AdjThrInit() depending on bitrate. + * + * \return void + */ +static void FDKaacEnc_preparePe(PE_DATA *const peData, + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + const QC_OUT_CHANNEL *const qcOutChannel[(2)], + const INT nChannels, const INT peOffset) { + INT ch; + + for (ch = 0; ch < nChannels; ch++) { + const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch]; + FDKaacEnc_prepareSfbPe( + &peData->peChannelData[ch], psyOutChan->sfbEnergyLdData, + psyOutChan->sfbThresholdLdData, qcOutChannel[ch]->sfbFormFactorLdData, + psyOutChan->sfbOffsets, psyOutChan->sfbCnt, psyOutChan->sfbPerGroup, + psyOutChan->maxSfbPerGroup); + } + peData->offset = peOffset; +} + +/** + * \brief Calculate weighting factor for threshold adjustment. + * + * Calculate weighting factor to be applied at energies and thresholds in ld64 + * format. + * + * \param peData, Pointer to PE data in current element. + * \param psyOutChannel Pointer to PSY_OUT_CHANNEL struct holding + * nChannels elements. + * \param qcOutChannel Pointer to QC_OUT_CHANNEL struct holding + * nChannels elements. + * \param toolsInfo Pointer to tools info struct of current element. + * \param adjThrStateElement Pointer to ATS_ELEMENT holding enFacPatch + * states. + * \param nChannels Number of channels in element. + * \param usePatchTool Apply the weighting tool 0 (no) else (yes). + * + * \return void + */ +static void FDKaacEnc_calcWeighting( + const PE_DATA *const peData, + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const struct TOOLSINFO *const toolsInfo, + ATS_ELEMENT *const adjThrStateElement, const INT nChannels, + const INT usePatchTool) { + int ch, noShortWindowInFrame = TRUE; + INT exePatchM = 0; + + for (ch = 0; ch < nChannels; ch++) { + if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) { + noShortWindowInFrame = FALSE; + } + FDKmemclear(qcOutChannel[ch]->sfbEnFacLd, + MAX_GROUPED_SFB * sizeof(FIXP_DBL)); + } + + if (usePatchTool == 0) { + return; /* tool is disabled */ + } + + for (ch = 0; ch < nChannels; ch++) { + const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch]; + + if (noShortWindowInFrame) { /* retain energy ratio between blocks of + different length */ + + FIXP_DBL nrgSum14, nrgSum12, nrgSum34, nrgTotal; + FIXP_DBL nrgFacLd_14, nrgFacLd_12, nrgFacLd_34; + INT usePatch, exePatch; + int sfb, sfbGrp, nLinesSum = 0; + + nrgSum14 = nrgSum12 = nrgSum34 = nrgTotal = FL2FXCONST_DBL(0.f); + + /* calculate flatness of audible spectrum, i.e. spectrum above masking + * threshold. */ + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + FIXP_DBL nrgFac12 = CalcInvLdData( + psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1); /* nrg^(1/2) */ + FIXP_DBL nrgFac14 = CalcInvLdData( + psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 2); /* nrg^(1/4) */ + + /* maximal number of bands is 64, results scaling factor 6 */ + nLinesSum += peData->peChannelData[ch] + .sfbNLines[sfbGrp + sfb]; /* relevant lines */ + nrgTotal += + (psyOutChan->sfbEnergy[sfbGrp + sfb] >> 6); /* sum up nrg */ + nrgSum12 += (nrgFac12 >> 6); /* sum up nrg^(2/4) */ + nrgSum14 += (nrgFac14 >> 6); /* sum up nrg^(1/4) */ + nrgSum34 += (fMult(nrgFac14, nrgFac12) >> 6); /* sum up nrg^(3/4) */ + } + } + + nrgTotal = CalcLdData(nrgTotal); /* get ld64 of total nrg */ + + nrgFacLd_14 = + CalcLdData(nrgSum14) - nrgTotal; /* ld64(nrgSum14/nrgTotal) */ + nrgFacLd_12 = + CalcLdData(nrgSum12) - nrgTotal; /* ld64(nrgSum12/nrgTotal) */ + nrgFacLd_34 = + CalcLdData(nrgSum34) - nrgTotal; /* ld64(nrgSum34/nrgTotal) */ + + /* Note: nLinesSum cannot be larger than the number of total lines, thats + * taken care of in line_pe.cpp FDKaacEnc_prepareSfbPe() */ + adjThrStateElement->chaosMeasureEnFac[ch] = + fMax(FL2FXCONST_DBL(0.1875f), + fDivNorm(nLinesSum, psyOutChan->sfbOffsets[psyOutChan->sfbCnt])); + + usePatch = (adjThrStateElement->chaosMeasureEnFac[ch] > + FL2FXCONST_DBL(0.78125f)); + exePatch = ((usePatch) && (adjThrStateElement->lastEnFacPatch[ch])); + + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + INT sfbExePatch; + /* for MS coupled SFBs, also execute patch in side channel if done in + * mid channel */ + if ((ch == 1) && (toolsInfo->msMask[sfbGrp + sfb])) { + sfbExePatch = exePatchM; + } else { + sfbExePatch = exePatch; + } + + if ((sfbExePatch) && + (psyOutChan->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.f))) { + /* execute patch based on spectral flatness calculated above */ + if (adjThrStateElement->chaosMeasureEnFac[ch] > + FL2FXCONST_DBL(0.8125f)) { + qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] = + ((nrgFacLd_14 + + (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] + + (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1))) >> + 1); /* sfbEnergy^(3/4) */ + } else if (adjThrStateElement->chaosMeasureEnFac[ch] > + FL2FXCONST_DBL(0.796875f)) { + qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] = + ((nrgFacLd_12 + psyOutChan->sfbEnergyLdData[sfbGrp + sfb]) >> + 1); /* sfbEnergy^(2/4) */ + } else { + qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] = + ((nrgFacLd_34 + + (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1)) >> + 1); /* sfbEnergy^(1/4) */ + } + qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] = + fixMin(qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb], (FIXP_DBL)0); + } + } + } /* sfb loop */ + + adjThrStateElement->lastEnFacPatch[ch] = usePatch; + exePatchM = exePatch; + } else { + /* !noShortWindowInFrame */ + adjThrStateElement->chaosMeasureEnFac[ch] = FL2FXCONST_DBL(0.75f); + adjThrStateElement->lastEnFacPatch[ch] = + TRUE; /* allow use of sfbEnFac patch in upcoming frame */ + } + + } /* ch loop */ +} + +/***************************************************************************** +functionname: FDKaacEnc_calcPe +description: calculate pe for both channels +*****************************************************************************/ +static void FDKaacEnc_calcPe(const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + const QC_OUT_CHANNEL *const qcOutChannel[(2)], + PE_DATA *const peData, const INT nChannels) { + INT ch; + + peData->pe = peData->offset; + peData->constPart = 0; + peData->nActiveLines = 0; + for (ch = 0; ch < nChannels; ch++) { + PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch]; + + FDKaacEnc_calcSfbPe( + peChanData, qcOutChannel[ch]->sfbWeightedEnergyLdData, + qcOutChannel[ch]->sfbThresholdLdData, psyOutChannel[ch]->sfbCnt, + psyOutChannel[ch]->sfbPerGroup, psyOutChannel[ch]->maxSfbPerGroup, + psyOutChannel[ch]->isBook, psyOutChannel[ch]->isScale); + + peData->pe += peChanData->pe; + peData->constPart += peChanData->constPart; + peData->nActiveLines += peChanData->nActiveLines; + } +} + +void FDKaacEnc_peCalculation(PE_DATA *const peData, + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const struct TOOLSINFO *const toolsInfo, + ATS_ELEMENT *const adjThrStateElement, + const INT nChannels) { + /* constants that will not change during successive pe calculations */ + FDKaacEnc_preparePe(peData, psyOutChannel, qcOutChannel, nChannels, + adjThrStateElement->peOffset); + + /* calculate weighting factor for threshold adjustment */ + FDKaacEnc_calcWeighting(peData, psyOutChannel, qcOutChannel, toolsInfo, + adjThrStateElement, nChannels, 1); + { + /* no weighting of threholds and energies for mlout */ + /* weight energies and thresholds */ + int ch; + for (ch = 0; ch < nChannels; ch++) { + int sfb, sfbGrp; + QC_OUT_CHANNEL *pQcOutCh = qcOutChannel[ch]; + + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + pQcOutCh->sfbWeightedEnergyLdData[sfb + sfbGrp] = + pQcOutCh->sfbEnergyLdData[sfb + sfbGrp] - + pQcOutCh->sfbEnFacLd[sfb + sfbGrp]; + pQcOutCh->sfbThresholdLdData[sfb + sfbGrp] -= + pQcOutCh->sfbEnFacLd[sfb + sfbGrp]; + } + } + } + } + + /* pe without reduction */ + FDKaacEnc_calcPe(psyOutChannel, qcOutChannel, peData, nChannels); +} + +/***************************************************************************** +functionname: FDKaacEnc_FDKaacEnc_calcPeNoAH +description: sum the pe data only for bands where avoid hole is inactive +*****************************************************************************/ +#define CONSTPART_HEADROOM 4 +static void FDKaacEnc_FDKaacEnc_calcPeNoAH( + INT *const pe, INT *const constPart, INT *const nActiveLines, + const PE_DATA *const peData, const UCHAR ahFlag[(2)][MAX_GROUPED_SFB], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], const INT nChannels) { + INT ch, sfb, sfbGrp; + + INT pe_tmp = peData->offset; + INT constPart_tmp = 0; + INT nActiveLines_tmp = 0; + for (ch = 0; ch < nChannels; ch++) { + const PE_CHANNEL_DATA *const peChanData = &peData->peChannelData[ch]; + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + if (ahFlag[ch][sfbGrp + sfb] < AH_ACTIVE) { + pe_tmp += peChanData->sfbPe[sfbGrp + sfb]; + constPart_tmp += + peChanData->sfbConstPart[sfbGrp + sfb] >> CONSTPART_HEADROOM; + nActiveLines_tmp += peChanData->sfbNActiveLines[sfbGrp + sfb]; + } + } + } + } + /* correct scaled pe and constPart values */ + *pe = pe_tmp >> PE_CONSTPART_SHIFT; + *constPart = constPart_tmp >> (PE_CONSTPART_SHIFT - CONSTPART_HEADROOM); + + *nActiveLines = nActiveLines_tmp; +} + +/***************************************************************************** +functionname: FDKaacEnc_reduceThresholdsCBR +description: apply reduction formula +*****************************************************************************/ +static const FIXP_DBL limitThrReducedLdData = + (FIXP_DBL)0x00008000; /*FL2FXCONST_DBL(FDKpow(2.0,-LD_DATA_SCALING/4.0));*/ + +static void FDKaacEnc_reduceThresholdsCBR( + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + UCHAR ahFlag[(2)][MAX_GROUPED_SFB], + const FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], const INT nChannels, + const FIXP_DBL redVal_m, const SCHAR redVal_e) { + INT ch, sfb, sfbGrp; + FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData; + FIXP_DBL sfbThrExp; + + for (ch = 0; ch < nChannels; ch++) { + QC_OUT_CHANNEL *qcOutChan = qcOutChannel[ch]; + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb]; + sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp + sfb]; + sfbThrExp = thrExp[ch][sfbGrp + sfb]; + if ((sfbEnLdData > sfbThrLdData) && + (ahFlag[ch][sfbGrp + sfb] != AH_ACTIVE)) { + /* threshold reduction formula: + float tmp = thrExp[ch][sfb]+redVal; + tmp *= tmp; + sfbThrReduced = tmp*tmp; + */ + int minScale = fixMin(CountLeadingBits(sfbThrExp), + CountLeadingBits(redVal_m) - redVal_e) - + 1; + + /* 4*log( sfbThrExp + redVal ) */ + sfbThrReducedLdData = + CalcLdData(fAbs(scaleValue(sfbThrExp, minScale) + + scaleValue(redVal_m, redVal_e + minScale))) - + (FIXP_DBL)(minScale << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + sfbThrReducedLdData <<= 2; + + /* avoid holes */ + if ((sfbThrReducedLdData > + (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData)) && + (ahFlag[ch][sfbGrp + sfb] != NO_AH)) { + if (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] > + (FL2FXCONST_DBL(-1.0f) - sfbEnLdData)) { + sfbThrReducedLdData = fixMax( + (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData), + sfbThrLdData); + } else + sfbThrReducedLdData = sfbThrLdData; + ahFlag[ch][sfbGrp + sfb] = AH_ACTIVE; + } + + /* minimum of 29 dB Ratio for Thresholds */ + if ((sfbEnLdData + (FIXP_DBL)MAXVAL_DBL) > + FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)) { + sfbThrReducedLdData = fixMax( + sfbThrReducedLdData, + (sfbEnLdData - FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING))); + } + + qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData; + } + } + } + } +} + +/* similar to prepareSfbPe1() */ +static FIXP_DBL FDKaacEnc_calcChaosMeasure( + const PSY_OUT_CHANNEL *const psyOutChannel, + const FIXP_DBL *const sfbFormFactorLdData) { +#define SCALE_FORM_FAC \ + (4) /* (SCALE_FORM_FAC+FORM_FAC_SHIFT) >= ld(FRAME_LENGTH)*/ +#define SCALE_NRGS (8) +#define SCALE_NLINES (16) +#define SCALE_NRGS_SQRT4 (2) /* 0.25 * SCALE_NRGS */ +#define SCALE_NLINES_P34 (12) /* 0.75 * SCALE_NLINES */ + + INT sfbGrp, sfb; + FIXP_DBL chaosMeasure; + INT frameNLines = 0; + FIXP_DBL frameFormFactor = FL2FXCONST_DBL(0.f); + FIXP_DBL frameEnergy = FL2FXCONST_DBL(0.f); + + for (sfbGrp = 0; sfbGrp < psyOutChannel->sfbCnt; + sfbGrp += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if (psyOutChannel->sfbEnergyLdData[sfbGrp + sfb] > + psyOutChannel->sfbThresholdLdData[sfbGrp + sfb]) { + frameFormFactor += (CalcInvLdData(sfbFormFactorLdData[sfbGrp + sfb]) >> + SCALE_FORM_FAC); + frameNLines += (psyOutChannel->sfbOffsets[sfbGrp + sfb + 1] - + psyOutChannel->sfbOffsets[sfbGrp + sfb]); + frameEnergy += (psyOutChannel->sfbEnergy[sfbGrp + sfb] >> SCALE_NRGS); + } + } + } + + if (frameNLines > 0) { + /* frameNActiveLines = frameFormFactor*2^FORM_FAC_SHIFT * ((frameEnergy + *2^SCALE_NRGS)/frameNLines)^-0.25 chaosMeasure = frameNActiveLines / + frameNLines */ + chaosMeasure = CalcInvLdData( + (((CalcLdData(frameFormFactor) >> 1) - + (CalcLdData(frameEnergy) >> (2 + 1))) - + (fMultDiv2(FL2FXCONST_DBL(0.75f), + CalcLdData((FIXP_DBL)frameNLines + << (DFRACT_BITS - 1 - SCALE_NLINES))) - + (((FIXP_DBL)(-((-SCALE_FORM_FAC + SCALE_NRGS_SQRT4 - FORM_FAC_SHIFT + + SCALE_NLINES_P34) + << (DFRACT_BITS - 1 - LD_DATA_SHIFT)))) >> + 1))) + << 1); + } else { + /* assuming total chaos, if no sfb is above thresholds */ + chaosMeasure = FL2FXCONST_DBL(1.f); + } + + return chaosMeasure; +} + +/* apply reduction formula for VBR-mode */ +static void FDKaacEnc_reduceThresholdsVBR( + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + UCHAR ahFlag[(2)][MAX_GROUPED_SFB], + const FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], const INT nChannels, + const FIXP_DBL vbrQualFactor, FIXP_DBL *const chaosMeasureOld) { + INT ch, sfbGrp, sfb; + FIXP_DBL chGroupEnergy[TRANS_FAC][2]; /*energy for each group and channel*/ + FIXP_DBL chChaosMeasure[2]; + FIXP_DBL frameEnergy = FL2FXCONST_DBL(1e-10f); + FIXP_DBL chaosMeasure = FL2FXCONST_DBL(0.f); + FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrExp; + FIXP_DBL sfbThrReducedLdData; + FIXP_DBL chaosMeasureAvg; + INT groupCnt; /* loop counter */ + FIXP_DBL redVal[TRANS_FAC]; /* reduction values; in short-block case one + redVal for each group */ + QC_OUT_CHANNEL *qcOutChan = NULL; + const PSY_OUT_CHANNEL *psyOutChan = NULL; + +#define SCALE_GROUP_ENERGY (8) + +#define CONST_CHAOS_MEAS_AVG_FAC_0 (FL2FXCONST_DBL(0.25f)) +#define CONST_CHAOS_MEAS_AVG_FAC_1 (FL2FXCONST_DBL(1.f - 0.25f)) + +#define MIN_LDTHRESH (FL2FXCONST_DBL(-0.515625f)) + + for (ch = 0; ch < nChannels; ch++) { + psyOutChan = psyOutChannel[ch]; + + /* adding up energy for each channel and each group separately */ + FIXP_DBL chEnergy = FL2FXCONST_DBL(0.f); + groupCnt = 0; + + for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; + sfbGrp += psyOutChan->sfbPerGroup, groupCnt++) { + chGroupEnergy[groupCnt][ch] = FL2FXCONST_DBL(0.f); + for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) { + chGroupEnergy[groupCnt][ch] += + (psyOutChan->sfbEnergy[sfbGrp + sfb] >> SCALE_GROUP_ENERGY); + } + chEnergy += chGroupEnergy[groupCnt][ch]; + } + frameEnergy += chEnergy; + + /* chaosMeasure */ + if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) { + chChaosMeasure[ch] = FL2FXCONST_DBL( + 0.5f); /* assume a constant chaos measure of 0.5f for short blocks */ + } else { + chChaosMeasure[ch] = FDKaacEnc_calcChaosMeasure( + psyOutChannel[ch], qcOutChannel[ch]->sfbFormFactorLdData); + } + chaosMeasure += fMult(chChaosMeasure[ch], chEnergy); + } + + if (frameEnergy > chaosMeasure) { + INT scale = CntLeadingZeros(frameEnergy) - 1; + FIXP_DBL num = chaosMeasure << scale; + FIXP_DBL denum = frameEnergy << scale; + chaosMeasure = schur_div(num, denum, 16); + } else { + chaosMeasure = FL2FXCONST_DBL(1.f); + } + + chaosMeasureAvg = fMult(CONST_CHAOS_MEAS_AVG_FAC_0, chaosMeasure) + + fMult(CONST_CHAOS_MEAS_AVG_FAC_1, + *chaosMeasureOld); /* averaging chaos measure */ + *chaosMeasureOld = chaosMeasure = (fixMin( + chaosMeasure, chaosMeasureAvg)); /* use min-value, safe for next frame */ + + /* characteristic curve + chaosMeasure = 0.2f + 0.7f/0.3f * (chaosMeasure - 0.2f); + chaosMeasure = fixMin(1.0f, fixMax(0.1f, chaosMeasure)); + constants scaled by 4.f + */ + chaosMeasure = ((FL2FXCONST_DBL(0.2f) >> 2) + + fMult(FL2FXCONST_DBL(0.7f / (4.f * 0.3f)), + (chaosMeasure - FL2FXCONST_DBL(0.2f)))); + chaosMeasure = + (fixMin((FIXP_DBL)(FL2FXCONST_DBL(1.0f) >> 2), + fixMax((FIXP_DBL)(FL2FXCONST_DBL(0.1f) >> 2), chaosMeasure))) + << 2; + + /* calculation of reduction value */ + if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) { /* short-blocks */ + FDK_ASSERT(TRANS_FAC == 8); +#define WIN_TYPE_SCALE (3) + + groupCnt = 0; + for (sfbGrp = 0; sfbGrp < psyOutChannel[0]->sfbCnt; + sfbGrp += psyOutChannel[0]->sfbPerGroup, groupCnt++) { + FIXP_DBL groupEnergy = FL2FXCONST_DBL(0.f); + + for (ch = 0; ch < nChannels; ch++) { + groupEnergy += + chGroupEnergy[groupCnt] + [ch]; /* adding up the channels groupEnergy */ + } + + FDK_ASSERT(psyOutChannel[0]->groupLen[groupCnt] <= INV_INT_TAB_SIZE); + groupEnergy = fMult( + groupEnergy, + invInt[psyOutChannel[0]->groupLen[groupCnt]]); /* correction of + group energy */ + groupEnergy = fixMin(groupEnergy, + frameEnergy >> WIN_TYPE_SCALE); /* do not allow an + higher redVal as + calculated + framewise */ + + groupEnergy >>= + 2; /* 2*WIN_TYPE_SCALE = 6 => 6+2 = 8 ==> 8/4 = int number */ + + redVal[groupCnt] = + fMult(fMult(vbrQualFactor, chaosMeasure), + CalcInvLdData(CalcLdData(groupEnergy) >> 2)) + << (int)((2 + (2 * WIN_TYPE_SCALE) + SCALE_GROUP_ENERGY) >> 2); + } + } else { /* long-block */ + + redVal[0] = fMult(fMult(vbrQualFactor, chaosMeasure), + CalcInvLdData(CalcLdData(frameEnergy) >> 2)) + << (int)(SCALE_GROUP_ENERGY >> 2); + } + + for (ch = 0; ch < nChannels; ch++) { + qcOutChan = qcOutChannel[ch]; + psyOutChan = psyOutChannel[ch]; + + for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; + sfbGrp += psyOutChan->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) { + sfbEnLdData = (qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb]); + sfbThrLdData = (qcOutChan->sfbThresholdLdData[sfbGrp + sfb]); + sfbThrExp = thrExp[ch][sfbGrp + sfb]; + + if ((sfbThrLdData >= MIN_LDTHRESH) && (sfbEnLdData > sfbThrLdData) && + (ahFlag[ch][sfbGrp + sfb] != AH_ACTIVE)) { + /* Short-Window */ + if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) { + const int groupNumber = (int)sfb / psyOutChan->sfbPerGroup; + + FDK_ASSERT(INV_SQRT4_TAB_SIZE > psyOutChan->groupLen[groupNumber]); + + sfbThrExp = + fMult(sfbThrExp, + fMult(FL2FXCONST_DBL(2.82f / 4.f), + invSqrt4[psyOutChan->groupLen[groupNumber]])) + << 2; + + if (sfbThrExp <= (limitThrReducedLdData - redVal[groupNumber])) { + sfbThrReducedLdData = FL2FXCONST_DBL(-1.0f); + } else { + if ((FIXP_DBL)redVal[groupNumber] >= + FL2FXCONST_DBL(1.0f) - sfbThrExp) + sfbThrReducedLdData = FL2FXCONST_DBL(0.0f); + else { + /* threshold reduction formula */ + sfbThrReducedLdData = + CalcLdData(sfbThrExp + redVal[groupNumber]); + sfbThrReducedLdData <<= 2; + } + } + sfbThrReducedLdData += + (CalcLdInt(psyOutChan->groupLen[groupNumber]) - + ((FIXP_DBL)6 << (DFRACT_BITS - 1 - LD_DATA_SHIFT))); + } + + /* Long-Window */ + else { + if ((FIXP_DBL)redVal[0] >= FL2FXCONST_DBL(1.0f) - sfbThrExp) { + sfbThrReducedLdData = FL2FXCONST_DBL(0.0f); + } else { + /* threshold reduction formula */ + sfbThrReducedLdData = CalcLdData(sfbThrExp + redVal[0]); + sfbThrReducedLdData <<= 2; + } + } + + /* avoid holes */ + if (((sfbThrReducedLdData - sfbEnLdData) > + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]) && + (ahFlag[ch][sfbGrp + sfb] != NO_AH)) { + if (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] > + (FL2FXCONST_DBL(-1.0f) - sfbEnLdData)) { + sfbThrReducedLdData = fixMax( + (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData), + sfbThrLdData); + } else + sfbThrReducedLdData = sfbThrLdData; + ahFlag[ch][sfbGrp + sfb] = AH_ACTIVE; + } + + if (sfbThrReducedLdData < FL2FXCONST_DBL(-0.5f)) + sfbThrReducedLdData = FL2FXCONST_DBL(-1.f); + + sfbThrReducedLdData = fixMax(MIN_LDTHRESH, sfbThrReducedLdData); + + qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData; + } + } + } + } +} + +/***************************************************************************** +functionname: FDKaacEnc_correctThresh +description: if pe difference deltaPe between desired pe and real pe is small +enough, the difference can be distributed among the scale factor bands. New +thresholds can be derived from this pe-difference +*****************************************************************************/ +static void FDKaacEnc_correctThresh( + const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))], + const PSY_OUT_ELEMENT *const psyOutElement[((8))], + UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], + const FIXP_DBL thrExp[((8))][(2)][MAX_GROUPED_SFB], const FIXP_DBL redVal_m, + const SCHAR redVal_e, const INT deltaPe, const INT processElements, + const INT elementOffset) { + INT ch, sfb, sfbGrp; + QC_OUT_CHANNEL *qcOutChan; + PSY_OUT_CHANNEL *psyOutChan; + PE_CHANNEL_DATA *peChanData; + FIXP_DBL thrFactorLdData; + FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData; + FIXP_DBL *sfbPeFactorsLdData[((8))][(2)]; + FIXP_DBL(*sfbNActiveLinesLdData)[(2)][MAX_GROUPED_SFB]; + + INT normFactorInt; + FIXP_DBL normFactorLdData; + + INT nElements = elementOffset + processElements; + INT elementId; + + /* scratch is empty; use temporal memory from quantSpec in QC_OUT_CHANNEL */ + for (elementId = elementOffset; elementId < nElements; elementId++) { + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + /* The reinterpret_cast is used to suppress a compiler warning. We know + * that qcElement[elementId]->qcOutChannel[ch]->quantSpec is sufficiently + * aligned, so the cast is safe */ + sfbPeFactorsLdData[elementId][ch] = + reinterpret_cast(reinterpret_cast( + qcElement[elementId]->qcOutChannel[ch]->quantSpec)); + } + } + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * qcElement[0]->dynMem_SfbNActiveLinesLdData is sufficiently aligned, so the + * cast is safe */ + sfbNActiveLinesLdData = reinterpret_cast( + reinterpret_cast(qcElement[0]->dynMem_SfbNActiveLinesLdData)); + + /* for each sfb calc relative factors for pe changes */ + normFactorInt = 0; + + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + psyOutChan = psyOutElement[elementId]->psyOutChannel[ch]; + peChanData = &qcElement[elementId]->peData.peChannelData[ch]; + + for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; + sfbGrp += psyOutChan->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) { + if (peChanData->sfbNActiveLines[sfbGrp + sfb] == 0) { + sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] = + FL2FXCONST_DBL(-1.0f); + } else { + /* Both CalcLdInt and CalcLdData can be used! + * No offset has to be subtracted, because sfbNActiveLinesLdData + * is shorted while thrFactor calculation */ + sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] = + CalcLdInt(peChanData->sfbNActiveLines[sfbGrp + sfb]); + } + if (((ahFlag[elementId][ch][sfbGrp + sfb] < AH_ACTIVE) || + (deltaPe > 0)) && + peChanData->sfbNActiveLines[sfbGrp + sfb] != 0) { + if (thrExp[elementId][ch][sfbGrp + sfb] > -redVal_m) { + /* sfbPeFactors[ch][sfbGrp+sfb] = + peChanData->sfbNActiveLines[sfbGrp+sfb] / + (thrExp[elementId][ch][sfbGrp+sfb] + + redVal[elementId]); */ + + int minScale = + fixMin( + CountLeadingBits(thrExp[elementId][ch][sfbGrp + sfb]), + CountLeadingBits(redVal_m) - redVal_e) - + 1; + + /* sumld = ld64( sfbThrExp + redVal ) */ + FIXP_DBL sumLd = + CalcLdData(scaleValue(thrExp[elementId][ch][sfbGrp + sfb], + minScale) + + scaleValue(redVal_m, redVal_e + minScale)) - + (FIXP_DBL)(minScale << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + + if (sumLd < FL2FXCONST_DBL(0.f)) { + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] = + sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] - + sumLd; + } else { + if (sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] > + (FL2FXCONST_DBL(-1.f) + sumLd)) { + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] = + sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] - + sumLd; + } else { + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] = + sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb]; + } + } + + normFactorInt += (INT)CalcInvLdData( + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb]); + } else + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] = + FL2FXCONST_DBL(1.0f); + } else + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] = + FL2FXCONST_DBL(-1.0f); + } + } + } + } + } + + /* normFactorLdData = ld64(deltaPe/normFactorInt) */ + normFactorLdData = + CalcLdData((FIXP_DBL)((deltaPe < 0) ? (-deltaPe) : (deltaPe))) - + CalcLdData((FIXP_DBL)normFactorInt); + + /* distribute the pe difference to the scalefactors + and calculate the according thresholds */ + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + qcOutChan = qcElement[elementId]->qcOutChannel[ch]; + psyOutChan = psyOutElement[elementId]->psyOutChannel[ch]; + peChanData = &qcElement[elementId]->peData.peChannelData[ch]; + + for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; + sfbGrp += psyOutChan->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) { + if (peChanData->sfbNActiveLines[sfbGrp + sfb] > 0) { + /* pe difference for this sfb */ + if ((sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] == + FL2FXCONST_DBL(-1.0f)) || + (deltaPe == 0)) { + thrFactorLdData = FL2FXCONST_DBL(0.f); + } else { + /* new threshold */ + FIXP_DBL tmp = CalcInvLdData( + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] + + normFactorLdData - + sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] - + FL2FXCONST_DBL((float)LD_DATA_SHIFT / LD_DATA_SCALING)); + + /* limit thrFactor to 60dB */ + tmp = (deltaPe < 0) ? tmp : (-tmp); + thrFactorLdData = + fMin(tmp, FL2FXCONST_DBL(20.f / LD_DATA_SCALING)); + } + + /* new threshold */ + sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp + sfb]; + sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb]; + + if (thrFactorLdData < FL2FXCONST_DBL(0.f)) { + if (sfbThrLdData > (FL2FXCONST_DBL(-1.f) - thrFactorLdData)) { + sfbThrReducedLdData = sfbThrLdData + thrFactorLdData; + } else { + sfbThrReducedLdData = FL2FXCONST_DBL(-1.f); + } + } else { + sfbThrReducedLdData = sfbThrLdData + thrFactorLdData; + } + + /* avoid hole */ + if ((sfbThrReducedLdData - sfbEnLdData > + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]) && + (ahFlag[elementId][ch][sfbGrp + sfb] == AH_INACTIVE)) { + /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn, + * sfbThr); */ + if (sfbEnLdData > + (sfbThrLdData - qcOutChan->sfbMinSnrLdData[sfbGrp + sfb])) { + sfbThrReducedLdData = + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData; + } else { + sfbThrReducedLdData = sfbThrLdData; + } + ahFlag[elementId][ch][sfbGrp + sfb] = AH_ACTIVE; + } + + qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData; + } + } + } + } + } + } +} + +/***************************************************************************** + functionname: FDKaacEnc_reduceMinSnr + description: if the desired pe can not be reached, reduce pe by + reducing minSnr +*****************************************************************************/ +static void FDKaacEnc_reduceMinSnr( + const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))], + const PSY_OUT_ELEMENT *const psyOutElement[((8))], + const UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe, + INT *const redPeGlobal, const INT processElements, const INT elementOffset) + +{ + INT ch, elementId, globalMaxSfb = 0; + const INT nElements = elementOffset + processElements; + INT newGlobalPe = *redPeGlobal; + + if (newGlobalPe <= desiredPe) { + goto bail; + } + + /* global maximum of maxSfbPerGroup */ + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + globalMaxSfb = + fMax(globalMaxSfb, + psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup); + } + } + } + + /* as long as globalPE is above desirePE reduce SNR to 1.0 dB, starting at + * highest SFB */ + while ((newGlobalPe > desiredPe) && (--globalMaxSfb >= 0)) { + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + PE_DATA *peData = &qcElement[elementId]->peData; + + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + QC_OUT_CHANNEL *qcOutChan = qcElement[elementId]->qcOutChannel[ch]; + PSY_OUT_CHANNEL *psyOutChan = + psyOutElement[elementId]->psyOutChannel[ch]; + + /* try to reduce SNR of channel's uppermost SFB(s) */ + if (globalMaxSfb < psyOutChan->maxSfbPerGroup) { + INT sfb, deltaPe = 0; + + for (sfb = globalMaxSfb; sfb < psyOutChan->sfbCnt; + sfb += psyOutChan->sfbPerGroup) { + if (ahFlag[elementId][ch][sfb] != NO_AH && + qcOutChan->sfbMinSnrLdData[sfb] < SnrLdFac && + (qcOutChan->sfbWeightedEnergyLdData[sfb] > + qcOutChan->sfbThresholdLdData[sfb] - SnrLdFac)) { + /* increase threshold to new minSnr of 1dB */ + qcOutChan->sfbMinSnrLdData[sfb] = SnrLdFac; + qcOutChan->sfbThresholdLdData[sfb] = + qcOutChan->sfbWeightedEnergyLdData[sfb] + SnrLdFac; + + /* calc new pe */ + /* C2 + C3*ld(1/0.8) = 1.5 */ + deltaPe -= peData->peChannelData[ch].sfbPe[sfb]; + + /* sfbPe = 1.5 * sfbNLines */ + peData->peChannelData[ch].sfbPe[sfb] = + (3 * peData->peChannelData[ch].sfbNLines[sfb]) + << (PE_CONSTPART_SHIFT - 1); + deltaPe += peData->peChannelData[ch].sfbPe[sfb]; + } + + } /* sfb loop */ + + deltaPe >>= PE_CONSTPART_SHIFT; + peData->pe += deltaPe; + peData->peChannelData[ch].pe += deltaPe; + newGlobalPe += deltaPe; + + } /* if globalMaxSfb < maxSfbPerGroup */ + + /* stop if enough has been saved */ + if (newGlobalPe <= desiredPe) { + goto bail; + } + + } /* ch loop */ + } /* != ID_DSE */ + } /* elementId loop */ + } /* while ( newGlobalPe > desiredPe) && (--globalMaxSfb >= 0) ) */ + +bail: + /* update global PE */ + *redPeGlobal = newGlobalPe; +} + +/***************************************************************************** + functionname: FDKaacEnc_allowMoreHoles + description: if the desired pe can not be reached, some more scalefactor + bands have to be quantized to zero +*****************************************************************************/ +static void FDKaacEnc_allowMoreHoles( + const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))], + const PSY_OUT_ELEMENT *const psyOutElement[((8))], + const ATS_ELEMENT *const AdjThrStateElement[((8))], + UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe, + const INT currentPe, const int processElements, const int elementOffset) { + INT elementId; + INT nElements = elementOffset + processElements; + INT actPe = currentPe; + + if (actPe <= desiredPe) { + return; /* nothing to do */ + } + + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + INT ch, sfb, sfbGrp; + + PE_DATA *peData = &qcElement[elementId]->peData; + const INT nChannels = cm->elInfo[elementId].nChannelsInEl; + + QC_OUT_CHANNEL *qcOutChannel[(2)] = {NULL}; + PSY_OUT_CHANNEL *psyOutChannel[(2)] = {NULL}; + + for (ch = 0; ch < nChannels; ch++) { + /* init pointers */ + qcOutChannel[ch] = qcElement[elementId]->qcOutChannel[ch]; + psyOutChannel[ch] = psyOutElement[elementId]->psyOutChannel[ch]; + + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = psyOutChannel[ch]->maxSfbPerGroup; + sfb < psyOutChannel[ch]->sfbPerGroup; sfb++) { + peData->peChannelData[ch].sfbPe[sfbGrp + sfb] = 0; + } + } + } + + /* for MS allow hole in the channel with less energy */ + if (nChannels == 2 && psyOutChannel[0]->lastWindowSequence == + psyOutChannel[1]->lastWindowSequence) { + for (sfb = psyOutChannel[0]->maxSfbPerGroup - 1; sfb >= 0; sfb--) { + for (sfbGrp = 0; sfbGrp < psyOutChannel[0]->sfbCnt; + sfbGrp += psyOutChannel[0]->sfbPerGroup) { + if (psyOutElement[elementId]->toolsInfo.msMask[sfbGrp + sfb]) { + FIXP_DBL EnergyLd_L = + qcOutChannel[0]->sfbWeightedEnergyLdData[sfbGrp + sfb]; + FIXP_DBL EnergyLd_R = + qcOutChannel[1]->sfbWeightedEnergyLdData[sfbGrp + sfb]; + + /* allow hole in side channel ? */ + if ((ahFlag[elementId][1][sfbGrp + sfb] != NO_AH) && + (((FL2FXCONST_DBL(-0.02065512648f) >> 1) + + (qcOutChannel[0]->sfbMinSnrLdData[sfbGrp + sfb] >> 1)) > + ((EnergyLd_R >> 1) - (EnergyLd_L >> 1)))) { + ahFlag[elementId][1][sfbGrp + sfb] = NO_AH; + qcOutChannel[1]->sfbThresholdLdData[sfbGrp + sfb] = + FL2FXCONST_DBL(0.015625f) + EnergyLd_R; + actPe -= peData->peChannelData[1].sfbPe[sfbGrp + sfb] >> + PE_CONSTPART_SHIFT; + } + /* allow hole in mid channel ? */ + else if ((ahFlag[elementId][0][sfbGrp + sfb] != NO_AH) && + (((FL2FXCONST_DBL(-0.02065512648f) >> 1) + + (qcOutChannel[1]->sfbMinSnrLdData[sfbGrp + sfb] >> + 1)) > ((EnergyLd_L >> 1) - (EnergyLd_R >> 1)))) { + ahFlag[elementId][0][sfbGrp + sfb] = NO_AH; + qcOutChannel[0]->sfbThresholdLdData[sfbGrp + sfb] = + FL2FXCONST_DBL(0.015625f) + EnergyLd_L; + actPe -= peData->peChannelData[0].sfbPe[sfbGrp + sfb] >> + PE_CONSTPART_SHIFT; + } /* if (ahFlag) */ + } /* if MS */ + } /* sfbGrp */ + if (actPe <= desiredPe) { + return; /* stop if enough has been saved */ + } + } /* sfb */ + } /* MS possible ? */ + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + if (actPe > desiredPe) { + /* more holes necessary? subsequently erase bands starting with low energies + */ + INT ch, sfb, sfbGrp; + INT minSfb, maxSfb; + INT enIdx, ahCnt, done; + INT startSfb[(8)]; + INT sfbCnt[(8)]; + INT sfbPerGroup[(8)]; + INT maxSfbPerGroup[(8)]; + FIXP_DBL avgEn; + FIXP_DBL minEnLD64; + FIXP_DBL avgEnLD64; + FIXP_DBL enLD64[NUM_NRG_LEVS]; + INT avgEn_e; + + /* get the scaling factor over all audio elements and channels */ + maxSfb = 0; + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + for (sfbGrp = 0; + sfbGrp < psyOutElement[elementId]->psyOutChannel[ch]->sfbCnt; + sfbGrp += + psyOutElement[elementId]->psyOutChannel[ch]->sfbPerGroup) { + maxSfb += + psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup; + } + } + } + } + avgEn_e = + (DFRACT_BITS - fixnormz_D((LONG)fMax(0, maxSfb - 1))); /* ilog2() */ + + ahCnt = 0; + maxSfb = 0; + minSfb = MAX_SFB; + avgEn = FL2FXCONST_DBL(0.0f); + minEnLD64 = FL2FXCONST_DBL(0.0f); + + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch]; + QC_OUT_CHANNEL *qcOutChannel = qcElement[elementId]->qcOutChannel[ch]; + PSY_OUT_CHANNEL *psyOutChannel = + psyOutElement[elementId]->psyOutChannel[ch]; + + maxSfbPerGroup[chIdx] = psyOutChannel->maxSfbPerGroup; + sfbCnt[chIdx] = psyOutChannel->sfbCnt; + sfbPerGroup[chIdx] = psyOutChannel->sfbPerGroup; + + maxSfb = fMax(maxSfb, psyOutChannel->maxSfbPerGroup); + + if (psyOutChannel->lastWindowSequence != SHORT_WINDOW) { + startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbL; + } else { + startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbS; + } + + minSfb = fMin(minSfb, startSfb[chIdx]); + + sfbGrp = 0; + sfb = startSfb[chIdx]; + + do { + for (; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if ((ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH) && + (qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb] > + qcOutChannel->sfbThresholdLdData[sfbGrp + sfb])) { + minEnLD64 = fixMin(minEnLD64, + qcOutChannel->sfbEnergyLdData[sfbGrp + sfb]); + avgEn += qcOutChannel->sfbEnergy[sfbGrp + sfb] >> avgEn_e; + ahCnt++; + } + } + + sfbGrp += psyOutChannel->sfbPerGroup; + sfb = startSfb[chIdx]; + + } while (sfbGrp < psyOutChannel->sfbCnt); + } + } /* (cm->elInfo[elementId].elType != ID_DSE) */ + } /* (elementId = elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + PE_DATA *peData = &qcElement[elementId]->peData; + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch]; + QC_OUT_CHANNEL *qcOutChannel = + qcElement[elementId]->qcOutChannel[ch]; + if (sfb >= startSfb[chIdx] && sfb < maxSfbPerGroup[chIdx]) { + for (sfbGrp = 0; sfbGrp < sfbCnt[chIdx]; + sfbGrp += sfbPerGroup[chIdx]) { + /* sfb energy below border ? */ + if (ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH && + qcOutChannel->sfbEnergyLdData[sfbGrp + sfb] < + enLD64[enIdx]) { + /* allow hole */ + ahFlag[elementId][ch][sfbGrp + sfb] = NO_AH; + qcOutChannel->sfbThresholdLdData[sfbGrp + sfb] = + FL2FXCONST_DBL(0.015625f) + + qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb]; + actPe -= peData->peChannelData[ch].sfbPe[sfbGrp + sfb] >> + PE_CONSTPART_SHIFT; + } + if (actPe <= desiredPe) { + return; /* stop if enough has been saved */ + } + } /* sfbGrp */ + } /* sfb */ + } /* nChannelsInEl */ + } /* ID_DSE */ + } /* elementID */ + + sfb--; + if (sfb < minSfb) { + /* restart with next energy border */ + sfb = maxSfb; + enIdx++; + if (enIdx >= NUM_NRG_LEVS) { + done = 1; + } + } + } /* done */ + } /* (actPe <= desiredPe) */ +} + +/* reset avoid hole flags from AH_ACTIVE to AH_INACTIVE */ +static void FDKaacEnc_resetAHFlags( + UCHAR ahFlag[(2)][MAX_GROUPED_SFB], const INT nChannels, + const PSY_OUT_CHANNEL *const psyOutChannel[(2)]) { + int ch, sfb, sfbGrp; + + for (ch = 0; ch < nChannels; ch++) { + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + if (ahFlag[ch][sfbGrp + sfb] == AH_ACTIVE) { + ahFlag[ch][sfbGrp + sfb] = AH_INACTIVE; + } + } + } + } +} + +static FIXP_DBL CalcRedValPower(FIXP_DBL num, FIXP_DBL denum, INT *scaling) { + FIXP_DBL value = FL2FXCONST_DBL(0.f); + + if (num >= FL2FXCONST_DBL(0.f)) { + value = fDivNorm(num, denum, scaling); + } else { + value = -fDivNorm(-num, denum, scaling); + } + value = f2Pow(value, *scaling, scaling); + + return value; +} + +/***************************************************************************** +functionname: FDKaacEnc_adaptThresholdsToPe +description: two guesses for the reduction value and one final correction of +the thresholds +*****************************************************************************/ +static void FDKaacEnc_adaptThresholdsToPe( + const CHANNEL_MAPPING *const cm, + ATS_ELEMENT *const AdjThrStateElement[((8))], + QC_OUT_ELEMENT *const qcElement[((8))], + const PSY_OUT_ELEMENT *const psyOutElement[((8))], const INT desiredPe, + const INT maxIter2ndGuess, const INT processElements, + const INT elementOffset) { + FIXP_DBL reductionValue_m; + SCHAR reductionValue_e; + UCHAR(*pAhFlag)[(2)][MAX_GROUPED_SFB]; + FIXP_DBL(*pThrExp)[(2)][MAX_GROUPED_SFB]; + int iter; + + INT constPartGlobal, noRedPeGlobal, nActiveLinesGlobal, redPeGlobal; + constPartGlobal = noRedPeGlobal = nActiveLinesGlobal = redPeGlobal = 0; + + int elementId; + + int nElements = elementOffset + processElements; + if (nElements > cm->nElements) { + nElements = cm->nElements; + } + + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * qcElement[0]->dynMem_Ah_Flag is sufficiently aligned, so the cast is safe + */ + pAhFlag = reinterpret_cast( + reinterpret_cast(qcElement[0]->dynMem_Ah_Flag)); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * qcElement[0]->dynMem_Thr_Exp is sufficiently aligned, so the cast is safe + */ + pThrExp = reinterpret_cast( + reinterpret_cast(qcElement[0]->dynMem_Thr_Exp)); + + /* ------------------------------------------------------- */ + /* Part I: Initialize data structures and variables... */ + /* ------------------------------------------------------- */ + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* thresholds to the power of redExp */ + FDKaacEnc_calcThreshExp( + pThrExp[elementId], qcElement[elementId]->qcOutChannel, + psyOutElement[elementId]->psyOutChannel, nChannels); + + /* lower the minSnr requirements for low energies compared to the average + energy in this frame */ + FDKaacEnc_adaptMinSnr(qcElement[elementId]->qcOutChannel, + psyOutElement[elementId]->psyOutChannel, + &AdjThrStateElement[elementId]->minSnrAdaptParam, + nChannels); + + /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ + FDKaacEnc_initAvoidHoleFlag( + qcElement[elementId]->qcOutChannel, + psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId], + &psyOutElement[elementId]->toolsInfo, nChannels, + &AdjThrStateElement[elementId]->ahParam); + + /* sum up */ + constPartGlobal += peData->constPart; + noRedPeGlobal += peData->pe; + nActiveLinesGlobal += fixMax((INT)peData->nActiveLines, 1); + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + /* + First guess of reduction value: + avgThrExp = (float)pow(2.0f, (constPartGlobal - noRedPeGlobal)/(4.0f * + nActiveLinesGlobal)); redVal = (float)pow(2.0f, (constPartGlobal - + desiredPe)/(4.0f * nActiveLinesGlobal)) - avgThrExp; redVal = max(0.f, + redVal); + */ + int redVal_e, avgThrExp_e, result_e; + FIXP_DBL redVal_m, avgThrExp_m; + + redVal_m = CalcRedValPower(constPartGlobal - desiredPe, + 4 * nActiveLinesGlobal, &redVal_e); + avgThrExp_m = CalcRedValPower(constPartGlobal - noRedPeGlobal, + 4 * nActiveLinesGlobal, &avgThrExp_e); + result_e = fMax(redVal_e, avgThrExp_e) + 1; + + reductionValue_m = fMax(FL2FXCONST_DBL(0.f), + scaleValue(redVal_m, redVal_e - result_e) - + scaleValue(avgThrExp_m, avgThrExp_e - result_e)); + reductionValue_e = result_e; + + /* ----------------------------------------------------------------------- */ + /* Part II: Calculate bit consumption of initial bit constraints setup */ + /* ----------------------------------------------------------------------- */ + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* reduce thresholds */ + FDKaacEnc_reduceThresholdsCBR( + qcElement[elementId]->qcOutChannel, + psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId], + pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e); + + /* pe after first guess */ + FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel, + qcElement[elementId]->qcOutChannel, peData, nChannels); + + redPeGlobal += peData->pe; + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + /* -------------------------------------------------- */ + /* Part III: Iterate until bit constraints are met */ + /* -------------------------------------------------- */ + iter = 0; + while ((fixp_abs(redPeGlobal - desiredPe) > + fMultI(FL2FXCONST_DBL(0.05f), desiredPe)) && + (iter < maxIter2ndGuess)) { + INT desiredPeNoAHGlobal; + INT redPeNoAHGlobal = 0; + INT constPartNoAHGlobal = 0; + INT nActiveLinesNoAHGlobal = 0; + + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + INT redPeNoAH, constPartNoAH, nActiveLinesNoAH; + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* pe for bands where avoid hole is inactive */ + FDKaacEnc_FDKaacEnc_calcPeNoAH( + &redPeNoAH, &constPartNoAH, &nActiveLinesNoAH, peData, + pAhFlag[elementId], psyOutElement[elementId]->psyOutChannel, + nChannels); + + redPeNoAHGlobal += redPeNoAH; + constPartNoAHGlobal += constPartNoAH; + nActiveLinesNoAHGlobal += nActiveLinesNoAH; + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + /* Calculate new redVal ... */ + if (desiredPe < redPeGlobal) { + /* new desired pe without bands where avoid hole is active */ + desiredPeNoAHGlobal = desiredPe - (redPeGlobal - redPeNoAHGlobal); + + /* limit desiredPeNoAH to positive values, as the PE can not become + * negative */ + desiredPeNoAHGlobal = fMax(0, desiredPeNoAHGlobal); + + /* second guess (only if there are bands left where avoid hole is + * inactive)*/ + if (nActiveLinesNoAHGlobal > 0) { + /* + avgThrExp = (float)pow(2.0f, (constPartNoAHGlobal - redPeNoAHGlobal) / + (4.0f * nActiveLinesNoAHGlobal)); redVal += (float)pow(2.0f, + (constPartNoAHGlobal - desiredPeNoAHGlobal) / (4.0f * + nActiveLinesNoAHGlobal)) - avgThrExp; redVal = max(0.0f, redVal); + */ + + redVal_m = CalcRedValPower(constPartNoAHGlobal - desiredPeNoAHGlobal, + 4 * nActiveLinesNoAHGlobal, &redVal_e); + avgThrExp_m = CalcRedValPower(constPartNoAHGlobal - redPeNoAHGlobal, + 4 * nActiveLinesNoAHGlobal, &avgThrExp_e); + result_e = fMax(reductionValue_e, fMax(redVal_e, avgThrExp_e) + 1) + 1; + + reductionValue_m = + fMax(FL2FXCONST_DBL(0.f), + scaleValue(reductionValue_m, reductionValue_e - result_e) + + scaleValue(redVal_m, redVal_e - result_e) - + scaleValue(avgThrExp_m, avgThrExp_e - result_e)); + reductionValue_e = result_e; + + } /* nActiveLinesNoAHGlobal > 0 */ + } else { + /* redVal *= redPeGlobal/desiredPe; */ + int sc0, sc1; + reductionValue_m = fMultNorm( + reductionValue_m, + fDivNorm((FIXP_DBL)redPeGlobal, (FIXP_DBL)desiredPe, &sc0), &sc1); + reductionValue_e += sc0 + sc1; + + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + FDKaacEnc_resetAHFlags(pAhFlag[elementId], + cm->elInfo[elementId].nChannelsInEl, + psyOutElement[elementId]->psyOutChannel); + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + } + + redPeGlobal = 0; + /* Calculate new redVal's PE... */ + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* reduce thresholds */ + FDKaacEnc_reduceThresholdsCBR( + qcElement[elementId]->qcOutChannel, + psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId], + pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e); + + /* pe after second guess */ + FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel, + qcElement[elementId]->qcOutChannel, peData, nChannels); + redPeGlobal += peData->pe; + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + iter++; + } /* EOF while */ + + /* ------------------------------------------------------- */ + /* Part IV: if still required, further reduce constraints */ + /* ------------------------------------------------------- */ + /* 1.0* 1.15* 1.20* + * desiredPe desiredPe desiredPe + * | | | + * ...XXXXXXXXXXXXXXXXXXXXXXXXXXX| | + * | | |XXXXXXXXXXX... + * | |XXXXXXXXXXX| + * --- A --- | --- B --- | --- C --- + * + * (X): redPeGlobal + * (A): FDKaacEnc_correctThresh() + * (B): FDKaacEnc_allowMoreHoles() + * (C): FDKaacEnc_reduceMinSnr() + */ + + /* correct thresholds to get closer to the desired pe */ + if (redPeGlobal > desiredPe) { + FDKaacEnc_correctThresh(cm, qcElement, psyOutElement, pAhFlag, pThrExp, + reductionValue_m, reductionValue_e, + desiredPe - redPeGlobal, processElements, + elementOffset); + + /* update PE */ + redPeGlobal = 0; + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* pe after correctThresh */ + FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel, + qcElement[elementId]->qcOutChannel, peData, nChannels); + redPeGlobal += peData->pe; + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + } + + if (redPeGlobal > desiredPe) { + /* reduce pe by reducing minSnr requirements */ + FDKaacEnc_reduceMinSnr( + cm, qcElement, psyOutElement, pAhFlag, + (fMultI(FL2FXCONST_DBL(0.15f), desiredPe) + desiredPe), &redPeGlobal, + processElements, elementOffset); + + /* reduce pe by allowing additional spectral holes */ + FDKaacEnc_allowMoreHoles(cm, qcElement, psyOutElement, AdjThrStateElement, + pAhFlag, desiredPe, redPeGlobal, processElements, + elementOffset); + } +} + +/* similar to FDKaacEnc_adaptThresholdsToPe(), for VBR-mode */ +static void FDKaacEnc_AdaptThresholdsVBR( + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + ATS_ELEMENT *const AdjThrStateElement, + const struct TOOLSINFO *const toolsInfo, const INT nChannels) { + UCHAR(*pAhFlag)[MAX_GROUPED_SFB]; + FIXP_DBL(*pThrExp)[MAX_GROUPED_SFB]; + + /* allocate scratch memory */ + C_ALLOC_SCRATCH_START(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB) + C_ALLOC_SCRATCH_START(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB) + pAhFlag = (UCHAR(*)[MAX_GROUPED_SFB])_pAhFlag; + pThrExp = (FIXP_DBL(*)[MAX_GROUPED_SFB])_pThrExp; + + /* thresholds to the power of redExp */ + FDKaacEnc_calcThreshExp(pThrExp, qcOutChannel, psyOutChannel, nChannels); + + /* lower the minSnr requirements for low energies compared to the average + energy in this frame */ + FDKaacEnc_adaptMinSnr(qcOutChannel, psyOutChannel, + &AdjThrStateElement->minSnrAdaptParam, nChannels); + + /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ + FDKaacEnc_initAvoidHoleFlag(qcOutChannel, psyOutChannel, pAhFlag, toolsInfo, + nChannels, &AdjThrStateElement->ahParam); + + /* reduce thresholds */ + FDKaacEnc_reduceThresholdsVBR(qcOutChannel, psyOutChannel, pAhFlag, pThrExp, + nChannels, AdjThrStateElement->vbrQualFactor, + &AdjThrStateElement->chaosMeasureOld); + + /* free scratch memory */ + C_ALLOC_SCRATCH_END(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB) + C_ALLOC_SCRATCH_END(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB) +} + +/***************************************************************************** + + functionname: FDKaacEnc_calcBitSave + description: Calculates percentage of bit save, see figure below + returns: + input: parameters and bitres-fullness + output: percentage of bit save + +*****************************************************************************/ +/* + bitsave + maxBitSave(%)| clipLow + |---\ + | \ + | \ + | \ + | \ + |--------\--------------> bitres + | \ + minBitSave(%)| \------------ + clipHigh maxBitres +*/ +static FIXP_DBL FDKaacEnc_calcBitSave(FIXP_DBL fillLevel, + const FIXP_DBL clipLow, + const FIXP_DBL clipHigh, + const FIXP_DBL minBitSave, + const FIXP_DBL maxBitSave, + const FIXP_DBL bitsave_slope) { + FIXP_DBL bitsave; + + fillLevel = fixMax(fillLevel, clipLow); + fillLevel = fixMin(fillLevel, clipHigh); + + bitsave = maxBitSave - fMult((fillLevel - clipLow), bitsave_slope); + + return (bitsave); +} + +/***************************************************************************** + + functionname: FDKaacEnc_calcBitSpend + description: Calculates percentage of bit spend, see figure below + returns: + input: parameters and bitres-fullness + output: percentage of bit spend + +*****************************************************************************/ +/* + bitspend clipHigh + maxBitSpend(%)| /-----------maxBitres + | / + | / + | / + | / + | / + |----/-----------------> bitres + | / + minBitSpend(%)|--/ + clipLow +*/ +static FIXP_DBL FDKaacEnc_calcBitSpend(FIXP_DBL fillLevel, + const FIXP_DBL clipLow, + const FIXP_DBL clipHigh, + const FIXP_DBL minBitSpend, + const FIXP_DBL maxBitSpend, + const FIXP_DBL bitspend_slope) { + FIXP_DBL bitspend; + + fillLevel = fixMax(fillLevel, clipLow); + fillLevel = fixMin(fillLevel, clipHigh); + + bitspend = minBitSpend + fMult(fillLevel - clipLow, bitspend_slope); + + return (bitspend); +} + +/***************************************************************************** + + functionname: FDKaacEnc_adjustPeMinMax() + description: adjusts peMin and peMax parameters over time + returns: + input: current pe, peMin, peMax, bitres size + output: adjusted peMin/peMax + +*****************************************************************************/ +static void FDKaacEnc_adjustPeMinMax(const INT currPe, INT *peMin, INT *peMax) { + FIXP_DBL minFacHi = FL2FXCONST_DBL(0.3f), maxFacHi = (FIXP_DBL)MAXVAL_DBL, + minFacLo = FL2FXCONST_DBL(0.14f), maxFacLo = FL2FXCONST_DBL(0.07f); + INT diff; + + INT minDiff_fix = fMultI(FL2FXCONST_DBL(0.1666666667f), currPe); + + if (currPe > *peMax) { + diff = (currPe - *peMax); + *peMin += fMultI(minFacHi, diff); + *peMax += fMultI(maxFacHi, diff); + } else if (currPe < *peMin) { + diff = (*peMin - currPe); + *peMin -= fMultI(minFacLo, diff); + *peMax -= fMultI(maxFacLo, diff); + } else { + *peMin += fMultI(minFacHi, (currPe - *peMin)); + *peMax -= fMultI(maxFacLo, (*peMax - currPe)); + } + + if ((*peMax - *peMin) < minDiff_fix) { + INT peMax_fix = *peMax, peMin_fix = *peMin; + FIXP_DBL partLo_fix, partHi_fix; + + partLo_fix = (FIXP_DBL)fixMax(0, currPe - peMin_fix); + partHi_fix = (FIXP_DBL)fixMax(0, peMax_fix - currPe); + + peMax_fix = + (INT)(currPe + fMultI(fDivNorm(partHi_fix, (partLo_fix + partHi_fix)), + minDiff_fix)); + peMin_fix = + (INT)(currPe - fMultI(fDivNorm(partLo_fix, (partLo_fix + partHi_fix)), + minDiff_fix)); + peMin_fix = fixMax(0, peMin_fix); + + *peMax = peMax_fix; + *peMin = peMin_fix; + } +} + +/***************************************************************************** + + functionname: BitresCalcBitFac + description: calculates factor of spending bits for one frame + 1.0 : take all frame dynpart bits + >1.0 : take all frame dynpart bits + bitres + <1.0 : put bits in bitreservoir + returns: BitFac + input: bitres-fullness, pe, blockType, parameter-settings + output: + +*****************************************************************************/ +/* + bitfac(%) pemax + bitspend(%) | /-----------maxBitres + | / + | / + | / + | / + | / + |----/-----------------> pe + | / + bitsave(%) |--/ + pemin +*/ + +void FDKaacEnc_bitresCalcBitFac(const INT bitresBits, const INT maxBitresBits, + const INT pe, const INT lastWindowSequence, + const INT avgBits, const FIXP_DBL maxBitFac, + const ADJ_THR_STATE *const AdjThr, + ATS_ELEMENT *const adjThrChan, + FIXP_DBL *const pBitresFac, + INT *const pBitresFac_e) { + const BRES_PARAM *bresParam; + INT pex; + FIXP_DBL fillLevel; + INT fillLevel_e = 0; + + FIXP_DBL bitresFac; + INT bitresFac_e; + + FIXP_DBL bitSave, bitSpend; + FIXP_DBL bitsave_slope, bitspend_slope; + FIXP_DBL fillLevel_fix = MAXVAL_DBL; + + FIXP_DBL slope = MAXVAL_DBL; + + if (lastWindowSequence != SHORT_WINDOW) { + bresParam = &(AdjThr->bresParamLong); + bitsave_slope = FL2FXCONST_DBL(0.466666666); + bitspend_slope = FL2FXCONST_DBL(0.666666666); + } else { + bresParam = &(AdjThr->bresParamShort); + bitsave_slope = (FIXP_DBL)0x2E8BA2E9; + bitspend_slope = (FIXP_DBL)0x7fffffff; + } + + // fillLevel = (float)(bitresBits+avgBits) / (float)(maxBitresBits + avgBits); + if (bitresBits < maxBitresBits) { + fillLevel_fix = fDivNorm(bitresBits, maxBitresBits); + } + + pex = fMax(pe, adjThrChan->peMin); + pex = fMin(pex, adjThrChan->peMax); + + bitSave = FDKaacEnc_calcBitSave( + fillLevel_fix, bresParam->clipSaveLow, bresParam->clipSaveHigh, + bresParam->minBitSave, bresParam->maxBitSave, bitsave_slope); + + bitSpend = FDKaacEnc_calcBitSpend( + fillLevel_fix, bresParam->clipSpendLow, bresParam->clipSpendHigh, + bresParam->minBitSpend, bresParam->maxBitSpend, bitspend_slope); + + slope = schur_div((pex - adjThrChan->peMin), + (adjThrChan->peMax - adjThrChan->peMin), 31); + + /* scale down by 1 bit because the result of the following addition can be + * bigger than 1 (though smaller than 2) */ + bitresFac = ((FIXP_DBL)(MAXVAL_DBL >> 1) - (bitSave >> 1)); + bitresFac_e = 1; /* exp=1 */ + bitresFac = fMultAddDiv2(bitresFac, slope, bitSpend + bitSave); /* exp=1 */ + + /*** limit bitresFac for small bitreservoir ***/ + fillLevel = fDivNorm(bitresBits, avgBits, &fillLevel_e); + if (fillLevel_e < 0) { + fillLevel = scaleValue(fillLevel, fillLevel_e); + fillLevel_e = 0; + } + /* shift down value by 1 because of summation, ... */ + fillLevel >>= 1; + fillLevel_e += 1; + /* ..., this summation: */ + fillLevel += scaleValue(FL2FXCONST_DBL(0.7f), -fillLevel_e); + /* set bitresfactor to same exponent as fillLevel */ + if (scaleValue(bitresFac, -fillLevel_e + 1) > fillLevel) { + bitresFac = fillLevel; + bitresFac_e = fillLevel_e; + } + + /* limit bitresFac for high bitrates */ + if (scaleValue(bitresFac, bitresFac_e - (DFRACT_BITS - 1 - 24)) > maxBitFac) { + bitresFac = maxBitFac; + bitresFac_e = (DFRACT_BITS - 1 - 24); + } + + FDKaacEnc_adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax); + + /* output values */ + *pBitresFac = bitresFac; + *pBitresFac_e = bitresFac_e; +} + +/***************************************************************************** +functionname: FDKaacEnc_AdjThrNew +description: allocate ADJ_THR_STATE +*****************************************************************************/ +INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE **phAdjThr, INT nElements) { + INT err = 0; + INT i; + ADJ_THR_STATE *hAdjThr = GetRam_aacEnc_AdjustThreshold(); + if (hAdjThr == NULL) { + err = 1; + goto bail; + } + + for (i = 0; i < nElements; i++) { + hAdjThr->adjThrStateElem[i] = GetRam_aacEnc_AdjThrStateElement(i); + if (hAdjThr->adjThrStateElem[i] == NULL) { + err = 1; + goto bail; + } + } + +bail: + *phAdjThr = hAdjThr; + return err; +} + +/***************************************************************************** +functionname: FDKaacEnc_AdjThrInit +description: initialize ADJ_THR_STATE +*****************************************************************************/ +void FDKaacEnc_AdjThrInit( + ADJ_THR_STATE *const hAdjThr, const INT meanPe, const INT invQuant, + const CHANNEL_MAPPING *const channelMapping, const INT sampleRate, + const INT totalBitrate, const INT isLowDelay, + const AACENC_BITRES_MODE bitResMode, const INT dZoneQuantEnable, + const INT bitDistributionMode, const FIXP_DBL vbrQualFactor) { + INT i; + + FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f); + FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f); + + if (bitDistributionMode == 1) { + hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTRA_ELEMENT; + } else { + hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTER_ELEMENT; + } + + /* Max number of iterations in second guess is 3 for lowdelay aot and for + configurations with multiple audio elements in general, otherwise iteration + value is always 1. */ + hAdjThr->maxIter2ndGuess = + (isLowDelay != 0 || channelMapping->nElements > 1) ? 3 : 1; + + /* common for all elements: */ + /* parameters for bitres control */ + hAdjThr->bresParamLong.clipSaveLow = + (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamLong.clipSaveHigh = + (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */ + hAdjThr->bresParamLong.minBitSave = + (FIXP_DBL)0xf999999a; /* FL2FXCONST_DBL(-0.05f); */ + hAdjThr->bresParamLong.maxBitSave = + (FIXP_DBL)0x26666666; /* FL2FXCONST_DBL(0.3f); */ + hAdjThr->bresParamLong.clipSpendLow = + (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamLong.clipSpendHigh = + (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */ + hAdjThr->bresParamLong.minBitSpend = + (FIXP_DBL)0xf3333333; /* FL2FXCONST_DBL(-0.10f); */ + hAdjThr->bresParamLong.maxBitSpend = + (FIXP_DBL)0x33333333; /* FL2FXCONST_DBL(0.4f); */ + + hAdjThr->bresParamShort.clipSaveLow = + (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamShort.clipSaveHigh = + (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */ + hAdjThr->bresParamShort.minBitSave = + (FIXP_DBL)0x00000000; /* FL2FXCONST_DBL(0.0f); */ + hAdjThr->bresParamShort.maxBitSave = + (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamShort.clipSpendLow = + (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamShort.clipSpendHigh = + (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */ + hAdjThr->bresParamShort.minBitSpend = + (FIXP_DBL)0xf9999998; /* FL2FXCONST_DBL(-0.05f); */ + hAdjThr->bresParamShort.maxBitSpend = + (FIXP_DBL)0x40000000; /* FL2FXCONST_DBL(0.5f); */ + + /* specific for each element: */ + for (i = 0; i < channelMapping->nElements; i++) { + const FIXP_DBL relativeBits = channelMapping->elInfo[i].relativeBits; + const INT nChannelsInElement = channelMapping->elInfo[i].nChannelsInEl; + const INT bitrateInElement = + (relativeBits != (FIXP_DBL)MAXVAL_DBL) + ? (INT)fMultNorm(relativeBits, (FIXP_DBL)totalBitrate) + : totalBitrate; + const INT chBitrate = bitrateInElement >> (nChannelsInElement == 1 ? 0 : 1); + + ATS_ELEMENT *atsElem = hAdjThr->adjThrStateElem[i]; + MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam; + + /* parameters for bitres control */ + if (isLowDelay) { + atsElem->peMin = fMultI(POINT8, meanPe); + atsElem->peMax = fMultI(POINT6, meanPe) << 1; + } else { + atsElem->peMin = fMultI(POINT8, meanPe) >> 1; + atsElem->peMax = fMultI(POINT6, meanPe); + } + + /* for use in FDKaacEnc_reduceThresholdsVBR */ + atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f); + + /* additional pe offset to correct pe2bits for low bitrates */ + /* ---- no longer necessary, set by table ----- */ + atsElem->peOffset = 0; + + /* vbr initialisation */ + atsElem->vbrQualFactor = vbrQualFactor; + if (chBitrate < 32000) { + atsElem->peOffset = + fixMax(50, 100 - fMultI((FIXP_DBL)0x666667, chBitrate)); + } + + /* avoid hole parameters */ + if (chBitrate >= 20000) { + atsElem->ahParam.modifyMinSnr = TRUE; + atsElem->ahParam.startSfbL = 15; + atsElem->ahParam.startSfbS = 3; + } else { + atsElem->ahParam.modifyMinSnr = FALSE; + atsElem->ahParam.startSfbL = 0; + atsElem->ahParam.startSfbS = 0; + } + + /* minSnr adaptation */ + msaParam->maxRed = FL2FXCONST_DBL(0.00390625f); /* 0.25f/64.0f */ + /* start adaptation of minSnr for avgEn/sfbEn > startRatio */ + msaParam->startRatio = FL2FXCONST_DBL(0.05190512648f); /* ld64(10.0f) */ + /* maximum minSnr reduction to minSnr^maxRed is reached for + avgEn/sfbEn >= maxRatio */ + /* msaParam->maxRatio = 1000.0f; */ + /*msaParam->redRatioFac = ((float)1.0f - msaParam->maxRed) / + * ((float)10.0f*log10(msaParam->startRatio/msaParam->maxRatio)/log10(2.0f)*(float)0.3010299956f);*/ + msaParam->redRatioFac = FL2FXCONST_DBL(-0.375f); /* -0.0375f * 10.0f */ + /*msaParam->redOffs = (float)1.0f - msaParam->redRatioFac * (float)10.0f * + * log10(msaParam->startRatio)/log10(2.0f) * (float)0.3010299956f;*/ + msaParam->redOffs = FL2FXCONST_DBL(0.021484375); /* 1.375f/64.0f */ + + /* init pe correction */ + atsElem->peCorrectionFactor_m = FL2FXCONST_DBL(0.5f); /* 1.0 */ + atsElem->peCorrectionFactor_e = 1; + + atsElem->dynBitsLast = -1; + atsElem->peLast = 0; + + /* init bits to pe factor */ + + /* init bits2PeFactor */ + FDKaacEnc_InitBits2PeFactor( + &atsElem->bits2PeFactor_m, &atsElem->bits2PeFactor_e, bitrateInElement, + nChannelsInElement, sampleRate, isLowDelay, dZoneQuantEnable, invQuant); + + } /* for nElements */ +} + +/***************************************************************************** + functionname: FDKaacEnc_FDKaacEnc_calcPeCorrection + description: calc desired pe +*****************************************************************************/ +static void FDKaacEnc_FDKaacEnc_calcPeCorrection( + FIXP_DBL *const correctionFac_m, INT *const correctionFac_e, + const INT peAct, const INT peLast, const INT bitsLast, + const FIXP_DBL bits2PeFactor_m, const INT bits2PeFactor_e) { + if ((bitsLast > 0) && (peAct < 1.5f * peLast) && (peAct > 0.7f * peLast) && + (FDKaacEnc_bits2pe2(bitsLast, + fMult(FL2FXCONST_DBL(1.2f / 2.f), bits2PeFactor_m), + bits2PeFactor_e + 1) > peLast) && + (FDKaacEnc_bits2pe2(bitsLast, + fMult(FL2FXCONST_DBL(0.65f), bits2PeFactor_m), + bits2PeFactor_e) < peLast)) { + FIXP_DBL corrFac = *correctionFac_m; + + int scaling = 0; + FIXP_DBL denum = (FIXP_DBL)FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m, + bits2PeFactor_e); + FIXP_DBL newFac = fDivNorm((FIXP_DBL)peLast, denum, &scaling); + + /* dead zone, newFac and corrFac are scaled by 0.5 */ + if ((FIXP_DBL)peLast <= denum) { /* ratio <= 1.f */ + newFac = fixMax( + scaleValue(fixMin(fMult(FL2FXCONST_DBL(1.1f / 2.f), newFac), + scaleValue(FL2FXCONST_DBL(1.f / 2.f), -scaling)), + scaling), + FL2FXCONST_DBL(0.85f / 2.f)); + } else { /* ratio < 1.f */ + newFac = fixMax( + fixMin(scaleValue(fMult(FL2FXCONST_DBL(0.9f / 2.f), newFac), scaling), + FL2FXCONST_DBL(1.15f / 2.f)), + FL2FXCONST_DBL(1.f / 2.f)); + } + + if (((newFac > FL2FXCONST_DBL(1.f / 2.f)) && + (corrFac < FL2FXCONST_DBL(1.f / 2.f))) || + ((newFac < FL2FXCONST_DBL(1.f / 2.f)) && + (corrFac > FL2FXCONST_DBL(1.f / 2.f)))) { + corrFac = FL2FXCONST_DBL(1.f / 2.f); + } + + /* faster adaptation towards 1.0, slower in the other direction */ + if ((corrFac < FL2FXCONST_DBL(1.f / 2.f) && newFac < corrFac) || + (corrFac > FL2FXCONST_DBL(1.f / 2.f) && newFac > corrFac)) { + corrFac = fMult(FL2FXCONST_DBL(0.85f), corrFac) + + fMult(FL2FXCONST_DBL(0.15f), newFac); + } else { + corrFac = fMult(FL2FXCONST_DBL(0.7f), corrFac) + + fMult(FL2FXCONST_DBL(0.3f), newFac); + } + + corrFac = fixMax(fixMin(corrFac, FL2FXCONST_DBL(1.15f / 2.f)), + FL2FXCONST_DBL(0.85 / 2.f)); + + *correctionFac_m = corrFac; + *correctionFac_e = 1; + } else { + *correctionFac_m = FL2FXCONST_DBL(1.f / 2.f); + *correctionFac_e = 1; + } +} + +static void FDKaacEnc_calcPeCorrectionLowBitRes( + FIXP_DBL *const correctionFac_m, INT *const correctionFac_e, + const INT peLast, const INT bitsLast, const INT bitresLevel, + const INT nChannels, const FIXP_DBL bits2PeFactor_m, + const INT bits2PeFactor_e) { + /* tuning params */ + const FIXP_DBL amp = FL2FXCONST_DBL(0.005); + const FIXP_DBL maxDiff = FL2FXCONST_DBL(0.25f); + + if (bitsLast > 0) { + /* Estimate deviation of granted and used dynamic bits in previous frame, in + * PE units */ + const int bitsBalLast = + peLast - FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m, bits2PeFactor_e); + + /* reserve n bits per channel */ + int headroom = (bitresLevel >= 50 * nChannels) ? 0 : (100 * nChannels); + + /* in PE units */ + headroom = FDKaacEnc_bits2pe2(headroom, bits2PeFactor_m, bits2PeFactor_e); + + /* + * diff = amp * ((bitsBalLast - headroom) / (bitresLevel + headroom) + * diff = max ( min ( diff, maxDiff, -maxDiff)) / 2 + */ + FIXP_DBL denominator = (FIXP_DBL)FDKaacEnc_bits2pe2( + bitresLevel, bits2PeFactor_m, bits2PeFactor_e) + + (FIXP_DBL)headroom; + + int scaling = 0; + FIXP_DBL diff = + (bitsBalLast >= headroom) + ? fMult(amp, fDivNorm((FIXP_DBL)(bitsBalLast - headroom), + denominator, &scaling)) + : -fMult(amp, fDivNorm(-(FIXP_DBL)(bitsBalLast - headroom), + denominator, &scaling)); + + scaling -= 1; /* divide by 2 */ + + diff = (scaling <= 0) + ? fMax(fMin(diff >> (-scaling), maxDiff >> 1), -maxDiff >> 1) + : fMax(fMin(diff, maxDiff >> (1 + scaling)), + -maxDiff >> (1 + scaling)) + << scaling; + + /* + * corrFac += diff + * corrFac = max ( min ( corrFac/2.f, 1.f/2.f, 0.75f/2.f ) ) + */ + *correctionFac_m = + fMax(fMin((*correctionFac_m) + diff, FL2FXCONST_DBL(1.0f / 2.f)), + FL2FXCONST_DBL(0.75f / 2.f)); + *correctionFac_e = 1; + } else { + *correctionFac_m = FL2FXCONST_DBL(0.75 / 2.f); + *correctionFac_e = 1; + } +} + +void FDKaacEnc_DistributeBits( + ADJ_THR_STATE *adjThrState, ATS_ELEMENT *AdjThrStateElement, + PSY_OUT_CHANNEL *psyOutChannel[(2)], PE_DATA *peData, INT *grantedPe, + INT *grantedPeCorr, const INT nChannels, const INT commonWindow, + const INT grantedDynBits, const INT bitresBits, const INT maxBitresBits, + const FIXP_DBL maxBitFac, const AACENC_BITRES_MODE bitResMode) { + FIXP_DBL bitFactor; + INT bitFactor_e; + INT noRedPe = peData->pe; + + /* prefer short windows for calculation of bitFactor */ + INT curWindowSequence = LONG_WINDOW; + if (nChannels == 2) { + if ((psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) || + (psyOutChannel[1]->lastWindowSequence == SHORT_WINDOW)) { + curWindowSequence = SHORT_WINDOW; + } + } else { + curWindowSequence = psyOutChannel[0]->lastWindowSequence; + } + + if (grantedDynBits >= 1) { + if (bitResMode != AACENC_BR_MODE_FULL) { + /* small or disabled bitreservoir */ + *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits, + AdjThrStateElement->bits2PeFactor_m, + AdjThrStateElement->bits2PeFactor_e); + } else { + /* factor dependend on current fill level and pe */ + FDKaacEnc_bitresCalcBitFac( + bitresBits, maxBitresBits, noRedPe, curWindowSequence, grantedDynBits, + maxBitFac, adjThrState, AdjThrStateElement, &bitFactor, &bitFactor_e); + + /* desired pe for actual frame */ + /* Worst case max of grantedDynBits is = 1024 * 5.27 * 2 */ + *grantedPe = FDKaacEnc_bits2pe2( + grantedDynBits, fMult(bitFactor, AdjThrStateElement->bits2PeFactor_m), + AdjThrStateElement->bits2PeFactor_e + bitFactor_e); + } + } else { + *grantedPe = 0; /* prevent divsion by 0 */ + } + + /* correction of pe value */ + switch (bitResMode) { + case AACENC_BR_MODE_DISABLED: + case AACENC_BR_MODE_REDUCED: + /* correction of pe value for low bitres */ + FDKaacEnc_calcPeCorrectionLowBitRes( + &AdjThrStateElement->peCorrectionFactor_m, + &AdjThrStateElement->peCorrectionFactor_e, AdjThrStateElement->peLast, + AdjThrStateElement->dynBitsLast, bitresBits, nChannels, + AdjThrStateElement->bits2PeFactor_m, + AdjThrStateElement->bits2PeFactor_e); + break; + case AACENC_BR_MODE_FULL: + default: + /* correction of pe value for high bitres */ + FDKaacEnc_FDKaacEnc_calcPeCorrection( + &AdjThrStateElement->peCorrectionFactor_m, + &AdjThrStateElement->peCorrectionFactor_e, + fixMin(*grantedPe, noRedPe), AdjThrStateElement->peLast, + AdjThrStateElement->dynBitsLast, AdjThrStateElement->bits2PeFactor_m, + AdjThrStateElement->bits2PeFactor_e); + break; + } + + *grantedPeCorr = + (INT)(fMult((FIXP_DBL)(*grantedPe << Q_AVGBITS), + AdjThrStateElement->peCorrectionFactor_m) >> + (Q_AVGBITS - AdjThrStateElement->peCorrectionFactor_e)); + + /* update last pe */ + AdjThrStateElement->peLast = *grantedPe; + AdjThrStateElement->dynBitsLast = -1; +} + +/***************************************************************************** +functionname: FDKaacEnc_AdjustThresholds +description: adjust thresholds +*****************************************************************************/ +void FDKaacEnc_AdjustThresholds( + ADJ_THR_STATE *const hAdjThr, QC_OUT_ELEMENT *const qcElement[((8))], + QC_OUT *const qcOut, const PSY_OUT_ELEMENT *const psyOutElement[((8))], + const INT CBRbitrateMode, const CHANNEL_MAPPING *const cm) { + int i; + + if (CBRbitrateMode) { + /* In case, no bits must be shifted between different elements, */ + /* an element-wise execution of the pe-dependent threshold- */ + /* adaption becomes necessary... */ + if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTRA_ELEMENT) { + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* qcElement[i]->grantedPe = 2000; */ /* Use this only for debugging + */ + // if (totalGrantedPeCorr < totalNoRedPe) { + if (qcElement[i]->grantedPeCorr < qcElement[i]->peData.pe) { + /* calc threshold necessary for desired pe */ + FDKaacEnc_adaptThresholdsToPe( + cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement, + qcElement[i]->grantedPeCorr, hAdjThr->maxIter2ndGuess, + 1, /* Process only 1 element */ + i /* Process exactly THIS element */ + ); + } + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + } /* -end- element loop */ + } /* AACENC_BD_MODE_INTRA_ELEMENT */ + else if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTER_ELEMENT) { + /* Use global Pe to obtain the thresholds? */ + if (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) { + /* add equal loadness quantization noise to match the */ + /* desired pe calc threshold necessary for desired pe */ + /* Now carried out globally to cover all(!) channels. */ + FDKaacEnc_adaptThresholdsToPe(cm, hAdjThr->adjThrStateElem, qcElement, + psyOutElement, qcOut->totalGrantedPeCorr, + hAdjThr->maxIter2ndGuess, + cm->nElements, /* Process all elements */ + 0); /* Process exactly THIS element */ + } else { + /* In case global pe doesn't need to be reduced check each element to + hold estimated bitrate below maximum element bitrate. */ + for (i = 0; i < cm->nElements; i++) { + if ((cm->elInfo[i].elType == ID_SCE) || + (cm->elInfo[i].elType == ID_CPE) || + (cm->elInfo[i].elType == ID_LFE)) { + /* Element pe applies to dynamic bits of maximum element bitrate. */ + const int maxElementPe = FDKaacEnc_bits2pe2( + (cm->elInfo[i].nChannelsInEl * MIN_BUFSIZE_PER_EFF_CHAN) - + qcElement[i]->staticBitsUsed - qcElement[i]->extBitsUsed, + hAdjThr->adjThrStateElem[i]->bits2PeFactor_m, + hAdjThr->adjThrStateElem[i]->bits2PeFactor_e); + + if (maxElementPe < qcElement[i]->peData.pe) { + FDKaacEnc_adaptThresholdsToPe( + cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement, + maxElementPe, hAdjThr->maxIter2ndGuess, 1, i); + } + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + } /* -end- element loop */ + } /* (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) */ + } /* AACENC_BD_MODE_INTER_ELEMENT */ + } else { + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* for VBR-mode */ + FDKaacEnc_AdaptThresholdsVBR( + qcElement[i]->qcOutChannel, psyOutElement[i]->psyOutChannel, + hAdjThr->adjThrStateElem[i], &psyOutElement[i]->toolsInfo, + cm->elInfo[i].nChannelsInEl); + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + } + for (i = 0; i < cm->nElements; i++) { + int ch, sfb, sfbGrp; + /* no weighting of threholds and energies for mlout */ + /* weight energies and thresholds */ + for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) { + QC_OUT_CHANNEL *pQcOutCh = qcElement[i]->qcOutChannel[ch]; + for (sfbGrp = 0; sfbGrp < psyOutElement[i]->psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutElement[i]->psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutElement[i]->psyOutChannel[ch]->maxSfbPerGroup; + sfb++) { + pQcOutCh->sfbThresholdLdData[sfb + sfbGrp] += + pQcOutCh->sfbEnFacLd[sfb + sfbGrp]; + } + } + } + } +} + +void FDKaacEnc_AdjThrClose(ADJ_THR_STATE **phAdjThr) { + INT i; + ADJ_THR_STATE *hAdjThr = *phAdjThr; + + if (hAdjThr != NULL) { + for (i = 0; i < ((8)); i++) { + if (hAdjThr->adjThrStateElem[i] != NULL) { + FreeRam_aacEnc_AdjThrStateElement(&hAdjThr->adjThrStateElem[i]); + } + } + FreeRam_aacEnc_AdjustThreshold(phAdjThr); + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/adj_thr.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/adj_thr.h new file mode 100644 index 0000000000000..1f5f998a1c31d --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/adj_thr.h @@ -0,0 +1,166 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Threshold compensation + +*******************************************************************************/ + +#ifndef ADJ_THR_H +#define ADJ_THR_H + +#include "common_fix.h" +#include "adj_thr_data.h" +#include "qc_data.h" +#include "line_pe.h" +#include "interface.h" + +/***************************************************************************** + functionname: FDKaacEnc_peCalculation + description: +*****************************************************************************/ +void FDKaacEnc_peCalculation(PE_DATA *const peData, + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const struct TOOLSINFO *const toolsInfo, + ATS_ELEMENT *const adjThrStateElement, + const INT nChannels); + +/***************************************************************************** +functionname: FDKaacEnc_AdjThrNew +description: allocate ADJ_THR_STATE +*****************************************************************************/ +INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE **phAdjThr, INT nElements); + +/***************************************************************************** +functionname: FDKaacEnc_AdjThrInit +description: initialize ADJ_THR_STATE +*****************************************************************************/ +void FDKaacEnc_AdjThrInit( + ADJ_THR_STATE *const hAdjThr, const INT meanPe, const INT invQuant, + const CHANNEL_MAPPING *const channelMapping, const INT sampleRate, + const INT totalBitrate, const INT isLowDelay, + const AACENC_BITRES_MODE bitResMode, const INT dZoneQuantEnable, + const INT bitDistributionMode, const FIXP_DBL vbrQualFactor); + +/***************************************************************************** +functionname: FDKaacEnc_DistributeBits +description: +*****************************************************************************/ +void FDKaacEnc_DistributeBits( + ADJ_THR_STATE *adjThrState, ATS_ELEMENT *AdjThrStateElement, + PSY_OUT_CHANNEL *psyOutChannel[(2)], PE_DATA *peData, INT *grantedPe, + INT *grantedPeCorr, const INT nChannels, const INT commonWindow, + const INT avgBits, const INT bitresBits, const INT maxBitresBits, + const FIXP_DBL maxBitFac, const AACENC_BITRES_MODE bitResMode); + +/***************************************************************************** +functionname: FDKaacEnc_AdjustThresholds +description: adjust thresholds +*****************************************************************************/ +void FDKaacEnc_AdjustThresholds( + ADJ_THR_STATE *const hAdjThr, QC_OUT_ELEMENT *const qcElement[((8))], + QC_OUT *const qcOut, const PSY_OUT_ELEMENT *const psyOutElement[((8))], + const INT CBRbitrateMode, const CHANNEL_MAPPING *const cm); + +/***************************************************************************** +functionname: FDKaacEnc_AdjThrClose +description: +*****************************************************************************/ +void FDKaacEnc_AdjThrClose(ADJ_THR_STATE **hAdjThr); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/adj_thr_data.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/adj_thr_data.h new file mode 100644 index 0000000000000..4cd1299834145 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/adj_thr_data.h @@ -0,0 +1,175 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Schug / A. Groeschel + + Description: threshold calculations + +*******************************************************************************/ + +#ifndef ADJ_THR_DATA_H +#define ADJ_THR_DATA_H + +#include "psy_const.h" + +typedef enum { + AACENC_BD_MODE_INTER_ELEMENT = 0, + AACENC_BD_MODE_INTRA_ELEMENT = 1 +} AACENC_BIT_DISTRIBUTION_MODE; + +typedef enum { + AACENC_BR_MODE_FULL = 0, + AACENC_BR_MODE_REDUCED = 1, + AACENC_BR_MODE_DISABLED = 2 +} AACENC_BITRES_MODE; + +typedef struct { + FIXP_DBL clipSaveLow, clipSaveHigh; + FIXP_DBL minBitSave, maxBitSave; + FIXP_DBL clipSpendLow, clipSpendHigh; + FIXP_DBL minBitSpend, maxBitSpend; +} BRES_PARAM; + +typedef struct { + INT modifyMinSnr; + INT startSfbL, startSfbS; +} AH_PARAM; + +typedef struct { + FIXP_DBL maxRed; + FIXP_DBL startRatio; + FIXP_DBL maxRatio; + FIXP_DBL redRatioFac; + FIXP_DBL redOffs; +} MINSNR_ADAPT_PARAM; + +typedef struct { + /* parameters for bitreservoir control */ + INT peMin, peMax; + /* constant offset to pe */ + INT peOffset; + /* constant PeFactor */ + FIXP_DBL bits2PeFactor_m; + INT bits2PeFactor_e; + /* avoid hole parameters */ + AH_PARAM ahParam; + /* parameters for adaptation of minSnr */ + MINSNR_ADAPT_PARAM minSnrAdaptParam; + + /* values for correction of pe */ + INT peLast; + INT dynBitsLast; + FIXP_DBL peCorrectionFactor_m; + INT peCorrectionFactor_e; + + /* vbr encoding */ + FIXP_DBL vbrQualFactor; + FIXP_DBL chaosMeasureOld; + + /* threshold weighting */ + FIXP_DBL chaosMeasureEnFac[(2)]; + INT lastEnFacPatch[(2)]; + +} ATS_ELEMENT; + +typedef struct { + BRES_PARAM bresParamLong, bresParamShort; + ATS_ELEMENT* adjThrStateElem[((8))]; + AACENC_BIT_DISTRIBUTION_MODE bitDistributionMode; + INT maxIter2ndGuess; +} ADJ_THR_STATE; + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/band_nrg.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/band_nrg.cpp new file mode 100644 index 0000000000000..fb22dbb302079 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/band_nrg.cpp @@ -0,0 +1,361 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Band/Line energy calculations + +*******************************************************************************/ + +#include "band_nrg.h" + +/***************************************************************************** + functionname: FDKaacEnc_CalcSfbMaxScaleSpec + description: + input: + output: +*****************************************************************************/ +void FDKaacEnc_CalcSfbMaxScaleSpec(const FIXP_DBL *RESTRICT mdctSpectrum, + const INT *RESTRICT bandOffset, + INT *RESTRICT sfbMaxScaleSpec, + const INT numBands) { + INT i, j; + FIXP_DBL maxSpc, tmp; + + for (i = 0; i < numBands; i++) { + maxSpc = (FIXP_DBL)0; + + DWORD_ALIGNED(mdctSpectrum); + + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + tmp = fixp_abs(mdctSpectrum[j]); + maxSpc = fixMax(maxSpc, tmp); + } + j = CntLeadingZeros(maxSpc) - 1; + sfbMaxScaleSpec[i] = fixMin((DFRACT_BITS - 2), j); + /* CountLeadingBits() is not necessary here since test value is always > 0 + */ + } +} + +/***************************************************************************** + functionname: FDKaacEnc_CheckBandEnergyOptim + description: + input: + output: +*****************************************************************************/ +FIXP_DBL +FDKaacEnc_CheckBandEnergyOptim(const FIXP_DBL *const RESTRICT mdctSpectrum, + const INT *const RESTRICT sfbMaxScaleSpec, + const INT *const RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergy, + FIXP_DBL *RESTRICT bandEnergyLdData, + const INT minSpecShift) { + INT i, j, scale, nr = 0; + FIXP_DBL maxNrgLd = FL2FXCONST_DBL(-1.0f); + FIXP_DBL maxNrg = 0; + FIXP_DBL spec; + + for (i = 0; i < numBands; i++) { + scale = fixMax(0, sfbMaxScaleSpec[i] - 4); + FIXP_DBL tmp = 0; + + DWORD_ALIGNED(mdctSpectrum); + + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + spec = mdctSpectrum[j] << scale; + tmp = fPow2AddDiv2(tmp, spec); + } + bandEnergy[i] = tmp << 1; + + /* calculate ld of bandNrg, subtract scaling */ + bandEnergyLdData[i] = CalcLdData(bandEnergy[i]); + if (bandEnergyLdData[i] != FL2FXCONST_DBL(-1.0f)) { + bandEnergyLdData[i] -= scale * FL2FXCONST_DBL(2.0 / 64); + } + /* find index of maxNrg */ + if (bandEnergyLdData[i] > maxNrgLd) { + maxNrgLd = bandEnergyLdData[i]; + nr = i; + } + } + + /* return unscaled maxNrg*/ + scale = fixMax(0, sfbMaxScaleSpec[nr] - 4); + scale = fixMax(2 * (minSpecShift - scale), -(DFRACT_BITS - 1)); + + maxNrg = scaleValue(bandEnergy[nr], scale); + + return maxNrg; +} + +/***************************************************************************** + functionname: FDKaacEnc_CalcBandEnergyOptimLong + description: + input: + output: +*****************************************************************************/ +INT FDKaacEnc_CalcBandEnergyOptimLong(const FIXP_DBL *RESTRICT mdctSpectrum, + INT *RESTRICT sfbMaxScaleSpec, + const INT *RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergy, + FIXP_DBL *RESTRICT bandEnergyLdData) { + INT i, j, shiftBits = 0; + FIXP_DBL maxNrgLd = FL2FXCONST_DBL(0.0f); + + FIXP_DBL spec; + + for (i = 0; i < numBands; i++) { + INT leadingBits = sfbMaxScaleSpec[i] - + 4; /* max sfbWidth = 96 ; 2^7=128 => 7/2 = 4 (spc*spc) */ + FIXP_DBL tmp = FL2FXCONST_DBL(0.0); + /* don't use scaleValue() here, it increases workload quite sufficiently... + */ + if (leadingBits >= 0) { + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + spec = mdctSpectrum[j] << leadingBits; + tmp = fPow2AddDiv2(tmp, spec); + } + } else { + INT shift = -leadingBits; + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + spec = mdctSpectrum[j] >> shift; + tmp = fPow2AddDiv2(tmp, spec); + } + } + bandEnergy[i] = tmp << 1; + } + + /* calculate ld of bandNrg, subtract scaling */ + LdDataVector(bandEnergy, bandEnergyLdData, numBands); + for (i = numBands; i-- != 0;) { + FIXP_DBL scaleDiff = (sfbMaxScaleSpec[i] - 4) * FL2FXCONST_DBL(2.0 / 64); + + bandEnergyLdData[i] = (bandEnergyLdData[i] >= + ((FL2FXCONST_DBL(-1.f) >> 1) + (scaleDiff >> 1))) + ? bandEnergyLdData[i] - scaleDiff + : FL2FXCONST_DBL(-1.f); + /* find maxNrgLd */ + maxNrgLd = fixMax(maxNrgLd, bandEnergyLdData[i]); + } + + if (maxNrgLd <= (FIXP_DBL)0) { + for (i = numBands; i-- != 0;) { + INT scale = fixMin((sfbMaxScaleSpec[i] - 4) << 1, (DFRACT_BITS - 1)); + bandEnergy[i] = scaleValue(bandEnergy[i], -scale); + } + return 0; + } else { /* scale down NRGs */ + while (maxNrgLd > FL2FXCONST_DBL(0.0f)) { + maxNrgLd -= FL2FXCONST_DBL(2.0 / 64); + shiftBits++; + } + for (i = numBands; i-- != 0;) { + INT scale = fixMin(((sfbMaxScaleSpec[i] - 4) + shiftBits) << 1, + (DFRACT_BITS - 1)); + bandEnergyLdData[i] -= shiftBits * FL2FXCONST_DBL(2.0 / 64); + bandEnergy[i] = scaleValue(bandEnergy[i], -scale); + } + return shiftBits; + } +} + +/***************************************************************************** + functionname: FDKaacEnc_CalcBandEnergyOptimShort + description: + input: + output: +*****************************************************************************/ +void FDKaacEnc_CalcBandEnergyOptimShort(const FIXP_DBL *RESTRICT mdctSpectrum, + INT *RESTRICT sfbMaxScaleSpec, + const INT *RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergy) { + INT i, j; + + for (i = 0; i < numBands; i++) { + int leadingBits = sfbMaxScaleSpec[i] - + 3; /* max sfbWidth = 36 ; 2^6=64 => 6/2 = 3 (spc*spc) */ + FIXP_DBL tmp = FL2FXCONST_DBL(0.0); + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + FIXP_DBL spec = scaleValue(mdctSpectrum[j], leadingBits); + tmp = fPow2AddDiv2(tmp, spec); + } + bandEnergy[i] = tmp; + } + + for (i = 0; i < numBands; i++) { + INT scale = (2 * (sfbMaxScaleSpec[i] - 3)) - + 1; /* max sfbWidth = 36 ; 2^6=64 => 6/2 = 3 (spc*spc) */ + scale = fixMax(fixMin(scale, (DFRACT_BITS - 1)), -(DFRACT_BITS - 1)); + bandEnergy[i] = scaleValueSaturate(bandEnergy[i], -scale); + } +} + +/***************************************************************************** + functionname: FDKaacEnc_CalcBandNrgMSOpt + description: + input: + output: +*****************************************************************************/ +void FDKaacEnc_CalcBandNrgMSOpt( + const FIXP_DBL *RESTRICT mdctSpectrumLeft, + const FIXP_DBL *RESTRICT mdctSpectrumRight, + INT *RESTRICT sfbMaxScaleSpecLeft, INT *RESTRICT sfbMaxScaleSpecRight, + const INT *RESTRICT bandOffset, const INT numBands, + FIXP_DBL *RESTRICT bandEnergyMid, FIXP_DBL *RESTRICT bandEnergySide, + INT calcLdData, FIXP_DBL *RESTRICT bandEnergyMidLdData, + FIXP_DBL *RESTRICT bandEnergySideLdData) { + INT i, j, minScale; + FIXP_DBL NrgMid, NrgSide, specm, specs; + + for (i = 0; i < numBands; i++) { + NrgMid = NrgSide = FL2FXCONST_DBL(0.0); + minScale = fixMin(sfbMaxScaleSpecLeft[i], sfbMaxScaleSpecRight[i]) - 4; + minScale = fixMax(0, minScale); + + if (minScale > 0) { + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + FIXP_DBL specL = mdctSpectrumLeft[j] << (minScale - 1); + FIXP_DBL specR = mdctSpectrumRight[j] << (minScale - 1); + specm = specL + specR; + specs = specL - specR; + NrgMid = fPow2AddDiv2(NrgMid, specm); + NrgSide = fPow2AddDiv2(NrgSide, specs); + } + } else { + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + FIXP_DBL specL = mdctSpectrumLeft[j] >> 1; + FIXP_DBL specR = mdctSpectrumRight[j] >> 1; + specm = specL + specR; + specs = specL - specR; + NrgMid = fPow2AddDiv2(NrgMid, specm); + NrgSide = fPow2AddDiv2(NrgSide, specs); + } + } + bandEnergyMid[i] = fMin(NrgMid, (FIXP_DBL)MAXVAL_DBL >> 1) << 1; + bandEnergySide[i] = fMin(NrgSide, (FIXP_DBL)MAXVAL_DBL >> 1) << 1; + } + + if (calcLdData) { + LdDataVector(bandEnergyMid, bandEnergyMidLdData, numBands); + LdDataVector(bandEnergySide, bandEnergySideLdData, numBands); + } + + for (i = 0; i < numBands; i++) { + minScale = fixMin(sfbMaxScaleSpecLeft[i], sfbMaxScaleSpecRight[i]); + INT scale = fixMax(0, 2 * (minScale - 4)); + + if (calcLdData) { + /* using the minimal scaling of left and right channel can cause very + small energies; check ldNrg before subtract scaling multiplication: + fract*INT we don't need fMult */ + + int minus = scale * FL2FXCONST_DBL(1.0 / 64); + + if (bandEnergyMidLdData[i] != FL2FXCONST_DBL(-1.0f)) + bandEnergyMidLdData[i] -= minus; + + if (bandEnergySideLdData[i] != FL2FXCONST_DBL(-1.0f)) + bandEnergySideLdData[i] -= minus; + } + scale = fixMin(scale, (DFRACT_BITS - 1)); + bandEnergyMid[i] >>= scale; + bandEnergySide[i] >>= scale; + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/band_nrg.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/band_nrg.h new file mode 100644 index 0000000000000..4137565853739 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/band_nrg.h @@ -0,0 +1,142 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Band/Line energy calculation + +*******************************************************************************/ + +#ifndef BAND_NRG_H +#define BAND_NRG_H + +#include "common_fix.h" + +void FDKaacEnc_CalcSfbMaxScaleSpec(const FIXP_DBL *mdctSpectrum, + const INT *bandOffset, INT *sfbMaxScaleSpec, + const INT numBands); + +FIXP_DBL +FDKaacEnc_CheckBandEnergyOptim(const FIXP_DBL *const RESTRICT mdctSpectrum, + const INT *const RESTRICT sfbMaxScaleSpec, + const INT *const RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergy, + FIXP_DBL *RESTRICT bandEnergyLdData, + const INT minSpecShift); + +INT FDKaacEnc_CalcBandEnergyOptimLong(const FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, + const INT *bandOffset, const INT numBands, + FIXP_DBL *bandEnergy, + FIXP_DBL *bandEnergyLdData); + +void FDKaacEnc_CalcBandEnergyOptimShort(const FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, + const INT *bandOffset, + const INT numBands, + FIXP_DBL *bandEnergy); + +void FDKaacEnc_CalcBandNrgMSOpt( + const FIXP_DBL *RESTRICT mdctSpectrumLeft, + const FIXP_DBL *RESTRICT mdctSpectrumRight, + INT *RESTRICT sfbMaxScaleSpecLeft, INT *RESTRICT sfbMaxScaleSpecRight, + const INT *RESTRICT bandOffset, const INT numBands, + FIXP_DBL *RESTRICT bandEnergyMid, FIXP_DBL *RESTRICT bandEnergySide, + INT calcLdData, FIXP_DBL *RESTRICT bandEnergyMidLdData, + FIXP_DBL *RESTRICT bandEnergySideLdData); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bandwidth.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bandwidth.cpp new file mode 100644 index 0000000000000..e814f0519e619 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bandwidth.cpp @@ -0,0 +1,360 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Schug / A. Groeschel + + Description: bandwidth expert + +*******************************************************************************/ + +#include "channel_map.h" +#include "bandwidth.h" +#include "aacEnc_ram.h" + +typedef struct { + INT chanBitRate; + INT bandWidthMono; + INT bandWidth2AndMoreChan; + +} BANDWIDTH_TAB; + +static const BANDWIDTH_TAB bandWidthTable[] = { + {0, 3700, 5000}, {12000, 5000, 6400}, {20000, 6900, 9640}, + {28000, 9600, 13050}, {40000, 12060, 14260}, {56000, 13950, 15500}, + {72000, 14200, 16120}, {96000, 17000, 17000}, {576001, 17000, 17000}}; + +static const BANDWIDTH_TAB bandWidthTable_LD_22050[] = { + {8000, 2000, 2400}, {12000, 2500, 2700}, {16000, 3300, 3100}, + {24000, 6250, 7200}, {32000, 9200, 10500}, {40000, 16000, 16000}, + {48000, 16000, 16000}, {282241, 16000, 16000}}; + +static const BANDWIDTH_TAB bandWidthTable_LD_24000[] = { + {8000, 2000, 2000}, {12000, 2000, 2300}, {16000, 2200, 2500}, + {24000, 5650, 7200}, {32000, 11600, 12000}, {40000, 12000, 16000}, + {48000, 16000, 16000}, {64000, 16000, 16000}, {307201, 16000, 16000}}; + +static const BANDWIDTH_TAB bandWidthTable_LD_32000[] = { + {8000, 2000, 2000}, {12000, 2000, 2000}, {24000, 4250, 7200}, + {32000, 8400, 9000}, {40000, 9400, 11300}, {48000, 11900, 14700}, + {64000, 14800, 16000}, {76000, 16000, 16000}, {409601, 16000, 16000}}; + +static const BANDWIDTH_TAB bandWidthTable_LD_44100[] = { + {8000, 2000, 2000}, {24000, 2000, 2000}, {32000, 4400, 5700}, + {40000, 7400, 8800}, {48000, 9000, 10700}, {56000, 11000, 12900}, + {64000, 14400, 15500}, {80000, 16000, 16200}, {96000, 16500, 16000}, + {128000, 16000, 16000}, {564481, 16000, 16000}}; + +static const BANDWIDTH_TAB bandWidthTable_LD_48000[] = { + {8000, 2000, 2000}, {24000, 2000, 2000}, {32000, 4400, 5700}, + {40000, 7400, 8800}, {48000, 9000, 10700}, {56000, 11000, 12800}, + {64000, 14300, 15400}, {80000, 16000, 16200}, {96000, 16500, 16000}, + {128000, 16000, 16000}, {614401, 16000, 16000}}; + +typedef struct { + AACENC_BITRATE_MODE bitrateMode; + int bandWidthMono; + int bandWidth2AndMoreChan; +} BANDWIDTH_TAB_VBR; + +static const BANDWIDTH_TAB_VBR bandWidthTableVBR[] = { + {AACENC_BR_MODE_CBR, 0, 0}, + {AACENC_BR_MODE_VBR_1, 13000, 13000}, + {AACENC_BR_MODE_VBR_2, 13000, 13000}, + {AACENC_BR_MODE_VBR_3, 15750, 15750}, + {AACENC_BR_MODE_VBR_4, 16500, 16500}, + {AACENC_BR_MODE_VBR_5, 19293, 19293}, + {AACENC_BR_MODE_SFR, 0, 0}, + {AACENC_BR_MODE_FF, 0, 0} + +}; + +static INT GetBandwidthEntry(const INT frameLength, const INT sampleRate, + const INT chanBitRate, const INT entryNo) { + INT bandwidth = -1; + const BANDWIDTH_TAB *pBwTab = NULL; + INT bwTabSize = 0; + + switch (frameLength) { + case 960: + case 1024: + pBwTab = bandWidthTable; + bwTabSize = sizeof(bandWidthTable) / sizeof(BANDWIDTH_TAB); + break; + case 120: + case 128: + case 240: + case 256: + case 480: + case 512: + switch (sampleRate) { + case 8000: + case 11025: + case 12000: + case 16000: + case 22050: + pBwTab = bandWidthTable_LD_22050; + bwTabSize = sizeof(bandWidthTable_LD_22050) / sizeof(BANDWIDTH_TAB); + break; + case 24000: + pBwTab = bandWidthTable_LD_24000; + bwTabSize = sizeof(bandWidthTable_LD_24000) / sizeof(BANDWIDTH_TAB); + break; + case 32000: + pBwTab = bandWidthTable_LD_32000; + bwTabSize = sizeof(bandWidthTable_LD_32000) / sizeof(BANDWIDTH_TAB); + break; + case 44100: + pBwTab = bandWidthTable_LD_44100; + bwTabSize = sizeof(bandWidthTable_LD_44100) / sizeof(BANDWIDTH_TAB); + break; + case 48000: + case 64000: + case 88200: + case 96000: + pBwTab = bandWidthTable_LD_48000; + bwTabSize = sizeof(bandWidthTable_LD_48000) / sizeof(BANDWIDTH_TAB); + break; + } + break; + default: + pBwTab = NULL; + bwTabSize = 0; + } + + if (pBwTab != NULL) { + int i; + for (i = 0; i < bwTabSize - 1; i++) { + if (chanBitRate >= pBwTab[i].chanBitRate && + chanBitRate < pBwTab[i + 1].chanBitRate) { + switch (frameLength) { + case 960: + case 1024: + bandwidth = (entryNo == 0) ? pBwTab[i].bandWidthMono + : pBwTab[i].bandWidth2AndMoreChan; + break; + case 120: + case 128: + case 240: + case 256: + case 480: + case 512: { + INT q_res = 0; + INT startBw = (entryNo == 0) ? pBwTab[i].bandWidthMono + : pBwTab[i].bandWidth2AndMoreChan; + INT endBw = (entryNo == 0) ? pBwTab[i + 1].bandWidthMono + : pBwTab[i + 1].bandWidth2AndMoreChan; + INT startBr = pBwTab[i].chanBitRate; + INT endBr = pBwTab[i + 1].chanBitRate; + + FIXP_DBL bwFac_fix = + fDivNorm(chanBitRate - startBr, endBr - startBr, &q_res); + bandwidth = + (INT)scaleValue(fMult(bwFac_fix, (FIXP_DBL)(endBw - startBw)), + q_res) + + startBw; + } break; + default: + bandwidth = -1; + } + break; + } /* within bitrate range */ + } + } /* pBwTab!=NULL */ + + return bandwidth; +} + +AAC_ENCODER_ERROR FDKaacEnc_DetermineBandWidth( + const INT proposedBandWidth, const INT bitrate, + const AACENC_BITRATE_MODE bitrateMode, const INT sampleRate, + const INT frameLength, const CHANNEL_MAPPING *const cm, + const CHANNEL_MODE encoderMode, INT *const bandWidth) { + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + INT chanBitRate = bitrate / cm->nChannelsEff; + + switch (bitrateMode) { + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + if (proposedBandWidth != 0) { + /* use given bw */ + *bandWidth = proposedBandWidth; + } else { + /* take bw from table */ + switch (encoderMode) { + case MODE_1: + *bandWidth = bandWidthTableVBR[bitrateMode].bandWidthMono; + break; + case MODE_2: + case MODE_1_2: + case MODE_1_2_1: + case MODE_1_2_2: + case MODE_1_2_2_1: + case MODE_6_1: + case MODE_1_2_2_2_1: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + case MODE_7_1_BACK: + case MODE_7_1_TOP_FRONT: + *bandWidth = bandWidthTableVBR[bitrateMode].bandWidth2AndMoreChan; + break; + default: + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + } + break; + case AACENC_BR_MODE_CBR: + case AACENC_BR_MODE_SFR: + case AACENC_BR_MODE_FF: + + /* bandwidth limiting */ + if (proposedBandWidth != 0) { + *bandWidth = fMin(proposedBandWidth, fMin(20000, sampleRate >> 1)); + } else { /* search reasonable bandwidth */ + + int entryNo = 0; + + switch (encoderMode) { + case MODE_1: /* mono */ + entryNo = 0; /* use mono bandwidth settings */ + break; + + case MODE_2: /* stereo */ + case MODE_1_2: /* sce + cpe */ + case MODE_1_2_1: /* sce + cpe + sce */ + case MODE_1_2_2: /* sce + cpe + cpe */ + case MODE_1_2_2_1: /* (5.1) sce + cpe + cpe + lfe */ + case MODE_6_1: + case MODE_1_2_2_2_1: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + case MODE_7_1_BACK: + case MODE_7_1_TOP_FRONT: + entryNo = 1; /* use stereo bandwidth settings */ + break; + + default: + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + + *bandWidth = + GetBandwidthEntry(frameLength, sampleRate, chanBitRate, entryNo); + + if (*bandWidth == -1) { + switch (frameLength) { + case 120: + case 128: + case 240: + case 256: + *bandWidth = 16000; + break; + default: + ErrorStatus = AAC_ENC_INVALID_CHANNEL_BITRATE; + } + } + } + break; + default: + *bandWidth = 0; + return AAC_ENC_UNSUPPORTED_BITRATE_MODE; + } + + *bandWidth = fMin(*bandWidth, sampleRate / 2); + + return ErrorStatus; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bandwidth.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bandwidth.h new file mode 100644 index 0000000000000..088e82930b851 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bandwidth.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Schug / A. Groeschel + + Description: bandwidth expert + +*******************************************************************************/ + +#ifndef BANDWIDTH_H +#define BANDWIDTH_H + +#include "qc_data.h" + +AAC_ENCODER_ERROR FDKaacEnc_DetermineBandWidth( + const INT proposedBandWidth, const INT bitrate, + const AACENC_BITRATE_MODE bitrateMode, const INT sampleRate, + const INT frameLength, const CHANNEL_MAPPING *const cm, + const CHANNEL_MODE encoderMode, INT *const bandWidth); + +#endif /* BANDWIDTH_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bit_cnt.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bit_cnt.cpp new file mode 100644 index 0000000000000..579df8c6f7f85 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bit_cnt.cpp @@ -0,0 +1,950 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Huffman Bitcounter & coder + +*******************************************************************************/ + +#include "bit_cnt.h" + +#include "aacEnc_ram.h" + +#define HI_LTAB(a) (a >> 16) +#define LO_LTAB(a) (a & 0xffff) + +/***************************************************************************** + + + functionname: FDKaacEnc_count1_2_3_4_5_6_7_8_9_10_11 + description: counts tables 1-11 + returns: + input: quantized spectrum + output: bitCount for tables 1-11 + +*****************************************************************************/ + +static void FDKaacEnc_count1_2_3_4_5_6_7_8_9_10_11(const SHORT *const values, + const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc1_2, bc3_4, bc5_6, bc7_8, bc9_10, bc11, sc; + INT t0, t1, t2, t3; + bc1_2 = 0; + bc3_4 = 0; + bc5_6 = 0; + bc7_8 = 0; + bc9_10 = 0; + bc11 = 0; + sc = 0; + + DWORD_ALIGNED(values); + + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + + bc1_2 += (INT)FDKaacEnc_huff_ltab1_2[t0 + 1][t1 + 1][t2 + 1][t3 + 1]; + bc5_6 += (INT)FDKaacEnc_huff_ltab5_6[t0 + 4][t1 + 4] + + (INT)FDKaacEnc_huff_ltab5_6[t2 + 4][t3 + 4]; + + t0 = fixp_abs(t0); + sc += (t0 > 0); + t1 = fixp_abs(t1); + sc += (t1 > 0); + t2 = fixp_abs(t2); + sc += (t2 > 0); + t3 = fixp_abs(t3); + sc += (t3 > 0); + + bc3_4 += (INT)FDKaacEnc_huff_ltab3_4[t0][t1][t2][t3]; + bc7_8 += (INT)FDKaacEnc_huff_ltab7_8[t0][t1] + + (INT)FDKaacEnc_huff_ltab7_8[t2][t3]; + bc9_10 += (INT)FDKaacEnc_huff_ltab9_10[t0][t1] + + (INT)FDKaacEnc_huff_ltab9_10[t2][t3]; + bc11 += + (INT)FDKaacEnc_huff_ltab11[t0][t1] + (INT)FDKaacEnc_huff_ltab11[t2][t3]; + } + bitCount[1] = HI_LTAB(bc1_2); + bitCount[2] = LO_LTAB(bc1_2); + bitCount[3] = HI_LTAB(bc3_4) + sc; + bitCount[4] = LO_LTAB(bc3_4) + sc; + bitCount[5] = HI_LTAB(bc5_6); + bitCount[6] = LO_LTAB(bc5_6); + bitCount[7] = HI_LTAB(bc7_8) + sc; + bitCount[8] = LO_LTAB(bc7_8) + sc; + bitCount[9] = HI_LTAB(bc9_10) + sc; + bitCount[10] = LO_LTAB(bc9_10) + sc; + bitCount[11] = bc11 + sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_count3_4_5_6_7_8_9_10_11 + description: counts tables 3-11 + returns: + input: quantized spectrum + output: bitCount for tables 3-11 + +*****************************************************************************/ + +static void FDKaacEnc_count3_4_5_6_7_8_9_10_11(const SHORT *const values, + const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc3_4, bc5_6, bc7_8, bc9_10, bc11, sc; + INT t0, t1, t2, t3; + + bc3_4 = 0; + bc5_6 = 0; + bc7_8 = 0; + bc9_10 = 0; + bc11 = 0; + sc = 0; + + DWORD_ALIGNED(values); + + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + + bc5_6 += (INT)FDKaacEnc_huff_ltab5_6[t0 + 4][t1 + 4] + + (INT)FDKaacEnc_huff_ltab5_6[t2 + 4][t3 + 4]; + + t0 = fixp_abs(t0); + sc += (t0 > 0); + t1 = fixp_abs(t1); + sc += (t1 > 0); + t2 = fixp_abs(t2); + sc += (t2 > 0); + t3 = fixp_abs(t3); + sc += (t3 > 0); + + bc3_4 += (INT)FDKaacEnc_huff_ltab3_4[t0][t1][t2][t3]; + bc7_8 += (INT)FDKaacEnc_huff_ltab7_8[t0][t1] + + (INT)FDKaacEnc_huff_ltab7_8[t2][t3]; + bc9_10 += (INT)FDKaacEnc_huff_ltab9_10[t0][t1] + + (INT)FDKaacEnc_huff_ltab9_10[t2][t3]; + bc11 += + (INT)FDKaacEnc_huff_ltab11[t0][t1] + (INT)FDKaacEnc_huff_ltab11[t2][t3]; + } + + bitCount[1] = INVALID_BITCOUNT; + bitCount[2] = INVALID_BITCOUNT; + bitCount[3] = HI_LTAB(bc3_4) + sc; + bitCount[4] = LO_LTAB(bc3_4) + sc; + bitCount[5] = HI_LTAB(bc5_6); + bitCount[6] = LO_LTAB(bc5_6); + bitCount[7] = HI_LTAB(bc7_8) + sc; + bitCount[8] = LO_LTAB(bc7_8) + sc; + bitCount[9] = HI_LTAB(bc9_10) + sc; + bitCount[10] = LO_LTAB(bc9_10) + sc; + bitCount[11] = bc11 + sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_count5_6_7_8_9_10_11 + description: counts tables 5-11 + returns: + input: quantized spectrum + output: bitCount for tables 5-11 + +*****************************************************************************/ + +static void FDKaacEnc_count5_6_7_8_9_10_11(const SHORT *const values, + const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc5_6, bc7_8, bc9_10, bc11, sc; + INT t0, t1, t2, t3; + bc5_6 = 0; + bc7_8 = 0; + bc9_10 = 0; + bc11 = 0; + sc = 0; + + DWORD_ALIGNED(values); + + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + + bc5_6 += (INT)FDKaacEnc_huff_ltab5_6[t0 + 4][t1 + 4] + + (INT)FDKaacEnc_huff_ltab5_6[t2 + 4][t3 + 4]; + + t0 = fixp_abs(t0); + sc += (t0 > 0); + t1 = fixp_abs(t1); + sc += (t1 > 0); + t2 = fixp_abs(t2); + sc += (t2 > 0); + t3 = fixp_abs(t3); + sc += (t3 > 0); + + bc7_8 += (INT)FDKaacEnc_huff_ltab7_8[t0][t1] + + (INT)FDKaacEnc_huff_ltab7_8[t2][t3]; + bc9_10 += (INT)FDKaacEnc_huff_ltab9_10[t0][t1] + + (INT)FDKaacEnc_huff_ltab9_10[t2][t3]; + bc11 += + (INT)FDKaacEnc_huff_ltab11[t0][t1] + (INT)FDKaacEnc_huff_ltab11[t2][t3]; + } + bitCount[1] = INVALID_BITCOUNT; + bitCount[2] = INVALID_BITCOUNT; + bitCount[3] = INVALID_BITCOUNT; + bitCount[4] = INVALID_BITCOUNT; + bitCount[5] = HI_LTAB(bc5_6); + bitCount[6] = LO_LTAB(bc5_6); + bitCount[7] = HI_LTAB(bc7_8) + sc; + bitCount[8] = LO_LTAB(bc7_8) + sc; + bitCount[9] = HI_LTAB(bc9_10) + sc; + bitCount[10] = LO_LTAB(bc9_10) + sc; + bitCount[11] = bc11 + sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_count7_8_9_10_11 + description: counts tables 7-11 + returns: + input: quantized spectrum + output: bitCount for tables 7-11 + +*****************************************************************************/ + +static void FDKaacEnc_count7_8_9_10_11(const SHORT *const values, + const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc7_8, bc9_10, bc11, sc; + INT t0, t1, t2, t3; + + bc7_8 = 0; + bc9_10 = 0; + bc11 = 0; + sc = 0; + + DWORD_ALIGNED(values); + + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + + t0 = fixp_abs(t0); + sc += (t0 > 0); + t1 = fixp_abs(t1); + sc += (t1 > 0); + t2 = fixp_abs(t2); + sc += (t2 > 0); + t3 = fixp_abs(t3); + sc += (t3 > 0); + + bc7_8 += (INT)FDKaacEnc_huff_ltab7_8[t0][t1] + + (INT)FDKaacEnc_huff_ltab7_8[t2][t3]; + bc9_10 += (INT)FDKaacEnc_huff_ltab9_10[t0][t1] + + (INT)FDKaacEnc_huff_ltab9_10[t2][t3]; + bc11 += + (INT)FDKaacEnc_huff_ltab11[t0][t1] + (INT)FDKaacEnc_huff_ltab11[t2][t3]; + } + + bitCount[1] = INVALID_BITCOUNT; + bitCount[2] = INVALID_BITCOUNT; + bitCount[3] = INVALID_BITCOUNT; + bitCount[4] = INVALID_BITCOUNT; + bitCount[5] = INVALID_BITCOUNT; + bitCount[6] = INVALID_BITCOUNT; + bitCount[7] = HI_LTAB(bc7_8) + sc; + bitCount[8] = LO_LTAB(bc7_8) + sc; + bitCount[9] = HI_LTAB(bc9_10) + sc; + bitCount[10] = LO_LTAB(bc9_10) + sc; + bitCount[11] = bc11 + sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_count9_10_11 + description: counts tables 9-11 + returns: + input: quantized spectrum + output: bitCount for tables 9-11 + +*****************************************************************************/ + +static void FDKaacEnc_count9_10_11(const SHORT *const values, const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc9_10, bc11, sc; + INT t0, t1, t2, t3; + + bc9_10 = 0; + bc11 = 0; + sc = 0; + + DWORD_ALIGNED(values); + + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + + t0 = fixp_abs(t0); + sc += (t0 > 0); + t1 = fixp_abs(t1); + sc += (t1 > 0); + t2 = fixp_abs(t2); + sc += (t2 > 0); + t3 = fixp_abs(t3); + sc += (t3 > 0); + + bc9_10 += (INT)FDKaacEnc_huff_ltab9_10[t0][t1] + + (INT)FDKaacEnc_huff_ltab9_10[t2][t3]; + bc11 += + (INT)FDKaacEnc_huff_ltab11[t0][t1] + (INT)FDKaacEnc_huff_ltab11[t2][t3]; + } + + bitCount[1] = INVALID_BITCOUNT; + bitCount[2] = INVALID_BITCOUNT; + bitCount[3] = INVALID_BITCOUNT; + bitCount[4] = INVALID_BITCOUNT; + bitCount[5] = INVALID_BITCOUNT; + bitCount[6] = INVALID_BITCOUNT; + bitCount[7] = INVALID_BITCOUNT; + bitCount[8] = INVALID_BITCOUNT; + bitCount[9] = HI_LTAB(bc9_10) + sc; + bitCount[10] = LO_LTAB(bc9_10) + sc; + bitCount[11] = bc11 + sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_count11 + description: counts table 11 + returns: + input: quantized spectrum + output: bitCount for table 11 + +*****************************************************************************/ + +static void FDKaacEnc_count11(const SHORT *const values, const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc11, sc; + INT t0, t1, t2, t3; + + bc11 = 0; + sc = 0; + + DWORD_ALIGNED(values); + + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + + t0 = fixp_abs(t0); + sc += (t0 > 0); + t1 = fixp_abs(t1); + sc += (t1 > 0); + t2 = fixp_abs(t2); + sc += (t2 > 0); + t3 = fixp_abs(t3); + sc += (t3 > 0); + + bc11 += + (INT)FDKaacEnc_huff_ltab11[t0][t1] + (INT)FDKaacEnc_huff_ltab11[t2][t3]; + } + + bitCount[1] = INVALID_BITCOUNT; + bitCount[2] = INVALID_BITCOUNT; + bitCount[3] = INVALID_BITCOUNT; + bitCount[4] = INVALID_BITCOUNT; + bitCount[5] = INVALID_BITCOUNT; + bitCount[6] = INVALID_BITCOUNT; + bitCount[7] = INVALID_BITCOUNT; + bitCount[8] = INVALID_BITCOUNT; + bitCount[9] = INVALID_BITCOUNT; + bitCount[10] = INVALID_BITCOUNT; + bitCount[11] = bc11 + sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_countEsc + description: counts table 11 (with Esc) + returns: + input: quantized spectrum + output: bitCount for tables 11 (with Esc) + +*****************************************************************************/ + +static void FDKaacEnc_countEsc(const SHORT *const values, const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc11, ec, sc; + INT t0, t1, t00, t01; + + bc11 = 0; + sc = 0; + ec = 0; + for (i = 0; i < width; i += 2) { + t0 = fixp_abs(values[i + 0]); + t1 = fixp_abs(values[i + 1]); + + sc += (t0 > 0) + (t1 > 0); + + t00 = fixMin(t0, 16); + t01 = fixMin(t1, 16); + bc11 += (INT)FDKaacEnc_huff_ltab11[t00][t01]; + + if (t0 >= 16) { + ec += 5; + while ((t0 >>= 1) >= 16) ec += 2; + } + + if (t1 >= 16) { + ec += 5; + while ((t1 >>= 1) >= 16) ec += 2; + } + } + + for (i = 0; i < 11; i++) bitCount[i] = INVALID_BITCOUNT; + + bitCount[11] = bc11 + sc + ec; +} + +typedef void (*COUNT_FUNCTION)(const SHORT *const values, const INT width, + INT *RESTRICT bitCount); + +static const COUNT_FUNCTION countFuncTable[CODE_BOOK_ESC_LAV + 1] = { + + FDKaacEnc_count1_2_3_4_5_6_7_8_9_10_11, /* 0 */ + FDKaacEnc_count1_2_3_4_5_6_7_8_9_10_11, /* 1 */ + FDKaacEnc_count3_4_5_6_7_8_9_10_11, /* 2 */ + FDKaacEnc_count5_6_7_8_9_10_11, /* 3 */ + FDKaacEnc_count5_6_7_8_9_10_11, /* 4 */ + FDKaacEnc_count7_8_9_10_11, /* 5 */ + FDKaacEnc_count7_8_9_10_11, /* 6 */ + FDKaacEnc_count7_8_9_10_11, /* 7 */ + FDKaacEnc_count9_10_11, /* 8 */ + FDKaacEnc_count9_10_11, /* 9 */ + FDKaacEnc_count9_10_11, /* 10 */ + FDKaacEnc_count9_10_11, /* 11 */ + FDKaacEnc_count9_10_11, /* 12 */ + FDKaacEnc_count11, /* 13 */ + FDKaacEnc_count11, /* 14 */ + FDKaacEnc_count11, /* 15 */ + FDKaacEnc_countEsc /* 16 */ +}; + +INT FDKaacEnc_bitCount(const SHORT *const values, const INT width, + const INT maxVal, INT *const RESTRICT bitCount) { + /* + check if we can use codebook 0 + */ + + bitCount[0] = (maxVal == 0) ? 0 : INVALID_BITCOUNT; + + countFuncTable[fixMin(maxVal, (INT)CODE_BOOK_ESC_LAV)](values, width, + bitCount); + + return (0); +} + +/* + count difference between actual and zeroed lines +*/ +INT FDKaacEnc_countValues(SHORT *RESTRICT values, INT width, INT codeBook) { + INT i, t0, t1, t2, t3; + INT bitCnt = 0; + + switch (codeBook) { + case CODE_BOOK_ZERO_NO: + break; + + case CODE_BOOK_1_NO: + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + bitCnt += + HI_LTAB(FDKaacEnc_huff_ltab1_2[t0 + 1][t1 + 1][t2 + 1][t3 + 1]); + } + break; + + case CODE_BOOK_2_NO: + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + bitCnt += + LO_LTAB(FDKaacEnc_huff_ltab1_2[t0 + 1][t1 + 1][t2 + 1][t3 + 1]); + } + break; + + case CODE_BOOK_3_NO: + for (i = 0; i < width; i += 4) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + t2 = fixp_abs(values[i + 2]); + bitCnt += (t2 > 0); + t3 = fixp_abs(values[i + 3]); + bitCnt += (t3 > 0); + bitCnt += HI_LTAB(FDKaacEnc_huff_ltab3_4[t0][t1][t2][t3]); + } + break; + + case CODE_BOOK_4_NO: + for (i = 0; i < width; i += 4) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + t2 = fixp_abs(values[i + 2]); + bitCnt += (t2 > 0); + t3 = fixp_abs(values[i + 3]); + bitCnt += (t3 > 0); + bitCnt += LO_LTAB(FDKaacEnc_huff_ltab3_4[t0][t1][t2][t3]); + } + break; + + case CODE_BOOK_5_NO: + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + bitCnt += HI_LTAB(FDKaacEnc_huff_ltab5_6[t0 + 4][t1 + 4]) + + HI_LTAB(FDKaacEnc_huff_ltab5_6[t2 + 4][t3 + 4]); + } + break; + + case CODE_BOOK_6_NO: + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + bitCnt += LO_LTAB(FDKaacEnc_huff_ltab5_6[t0 + 4][t1 + 4]) + + LO_LTAB(FDKaacEnc_huff_ltab5_6[t2 + 4][t3 + 4]); + } + break; + + case CODE_BOOK_7_NO: + for (i = 0; i < width; i += 4) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + t2 = fixp_abs(values[i + 2]); + bitCnt += (t2 > 0); + t3 = fixp_abs(values[i + 3]); + bitCnt += (t3 > 0); + bitCnt += HI_LTAB(FDKaacEnc_huff_ltab7_8[t0][t1]) + + HI_LTAB(FDKaacEnc_huff_ltab7_8[t2][t3]); + } + break; + + case CODE_BOOK_8_NO: + for (i = 0; i < width; i += 4) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + t2 = fixp_abs(values[i + 2]); + bitCnt += (t2 > 0); + t3 = fixp_abs(values[i + 3]); + bitCnt += (t3 > 0); + bitCnt += LO_LTAB(FDKaacEnc_huff_ltab7_8[t0][t1]) + + LO_LTAB(FDKaacEnc_huff_ltab7_8[t2][t3]); + } + break; + + case CODE_BOOK_9_NO: + for (i = 0; i < width; i += 4) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + t2 = fixp_abs(values[i + 2]); + bitCnt += (t2 > 0); + t3 = fixp_abs(values[i + 3]); + bitCnt += (t3 > 0); + bitCnt += HI_LTAB(FDKaacEnc_huff_ltab9_10[t0][t1]) + + HI_LTAB(FDKaacEnc_huff_ltab9_10[t2][t3]); + } + break; + + case CODE_BOOK_10_NO: + for (i = 0; i < width; i += 4) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + t2 = fixp_abs(values[i + 2]); + bitCnt += (t2 > 0); + t3 = fixp_abs(values[i + 3]); + bitCnt += (t3 > 0); + bitCnt += LO_LTAB(FDKaacEnc_huff_ltab9_10[t0][t1]) + + LO_LTAB(FDKaacEnc_huff_ltab9_10[t2][t3]); + } + break; + + case CODE_BOOK_ESC_NO: + for (i = 0; i < width; i += 2) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + bitCnt += (INT)FDKaacEnc_huff_ltab11[fixMin(t0, 16)][fixMin(t1, 16)]; + if (t0 >= 16) { + bitCnt += 5; + while ((t0 >>= 1) >= 16) bitCnt += 2; + } + if (t1 >= 16) { + bitCnt += 5; + while ((t1 >>= 1) >= 16) bitCnt += 2; + } + } + break; + + default: + break; + } + + return (bitCnt); +} + +INT FDKaacEnc_codeValues(SHORT *RESTRICT values, INT width, INT codeBook, + HANDLE_FDK_BITSTREAM hBitstream) { + INT i, t0, t1, t2, t3, t00, t01; + INT codeWord, codeLength; + INT sign, signLength; + + DWORD_ALIGNED(values); + + switch (codeBook) { + case CODE_BOOK_ZERO_NO: + break; + + case CODE_BOOK_1_NO: + for (i = 0; i < width; i += 4) { + t0 = values[i + 0] + 1; + t1 = values[i + 1] + 1; + t2 = values[i + 2] + 1; + t3 = values[i + 3] + 1; + codeWord = FDKaacEnc_huff_ctab1[t0][t1][t2][t3]; + codeLength = HI_LTAB(FDKaacEnc_huff_ltab1_2[t0][t1][t2][t3]); + FDKwriteBits(hBitstream, codeWord, codeLength); + } + break; + + case CODE_BOOK_2_NO: + for (i = 0; i < width; i += 4) { + t0 = values[i + 0] + 1; + t1 = values[i + 1] + 1; + t2 = values[i + 2] + 1; + t3 = values[i + 3] + 1; + codeWord = FDKaacEnc_huff_ctab2[t0][t1][t2][t3]; + codeLength = LO_LTAB(FDKaacEnc_huff_ltab1_2[t0][t1][t2][t3]); + FDKwriteBits(hBitstream, codeWord, codeLength); + } + break; + + case CODE_BOOK_3_NO: + for (i = 0; i < (width >> 2); i++) { + sign = 0; + signLength = 0; + int index[4]; + for (int j = 0; j < 4; j++) { + int ti = *values++; + int zero = (ti == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)ti >> 31); + index[j] = fixp_abs(ti); + } + codeWord = FDKaacEnc_huff_ctab3[index[0]][index[1]][index[2]][index[3]]; + codeLength = HI_LTAB( + FDKaacEnc_huff_ltab3_4[index[0]][index[1]][index[2]][index[3]]); + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + } + break; + + case CODE_BOOK_4_NO: + for (i = 0; i < width; i += 4) { + sign = 0; + signLength = 0; + int index[4]; + for (int j = 0; j < 4; j++) { + int ti = *values++; + int zero = (ti == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)ti >> 31); + index[j] = fixp_abs(ti); + } + codeWord = FDKaacEnc_huff_ctab4[index[0]][index[1]][index[2]][index[3]]; + codeLength = LO_LTAB( + FDKaacEnc_huff_ltab3_4[index[0]][index[1]][index[2]][index[3]]); + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + } + break; + + case CODE_BOOK_5_NO: + for (i = 0; i < (width >> 2); i++) { + t0 = *values++ + 4; + t1 = *values++ + 4; + t2 = *values++ + 4; + t3 = *values++ + 4; + codeWord = FDKaacEnc_huff_ctab5[t0][t1]; + codeLength = + HI_LTAB(FDKaacEnc_huff_ltab5_6[t2][t3]); /* length of 2nd cw */ + codeWord = (codeWord << codeLength) + FDKaacEnc_huff_ctab5[t2][t3]; + codeLength += HI_LTAB(FDKaacEnc_huff_ltab5_6[t0][t1]); + FDKwriteBits(hBitstream, codeWord, codeLength); + } + break; + + case CODE_BOOK_6_NO: + for (i = 0; i < (width >> 2); i++) { + t0 = *values++ + 4; + t1 = *values++ + 4; + t2 = *values++ + 4; + t3 = *values++ + 4; + codeWord = FDKaacEnc_huff_ctab6[t0][t1]; + codeLength = + LO_LTAB(FDKaacEnc_huff_ltab5_6[t2][t3]); /* length of 2nd cw */ + codeWord = (codeWord << codeLength) + FDKaacEnc_huff_ctab6[t2][t3]; + codeLength += LO_LTAB(FDKaacEnc_huff_ltab5_6[t0][t1]); + FDKwriteBits(hBitstream, codeWord, codeLength); + } + break; + + case CODE_BOOK_7_NO: + for (i = 0; i < (width >> 1); i++) { + t0 = *values++; + sign = ((UINT)t0 >> 31); + t0 = fixp_abs(t0); + signLength = (t0 == 0) ? 0 : 1; + t1 = *values++; + INT zero = (t1 == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)t1 >> 31); + t1 = fixp_abs(t1); + codeWord = FDKaacEnc_huff_ctab7[t0][t1]; + codeLength = HI_LTAB(FDKaacEnc_huff_ltab7_8[t0][t1]); + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + } + break; + + case CODE_BOOK_8_NO: + for (i = 0; i < (width >> 1); i++) { + t0 = *values++; + sign = ((UINT)t0 >> 31); + t0 = fixp_abs(t0); + signLength = (t0 == 0) ? 0 : 1; + t1 = *values++; + INT zero = (t1 == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)t1 >> 31); + t1 = fixp_abs(t1); + codeWord = FDKaacEnc_huff_ctab8[t0][t1]; + codeLength = LO_LTAB(FDKaacEnc_huff_ltab7_8[t0][t1]); + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + } + break; + + case CODE_BOOK_9_NO: + for (i = 0; i < (width >> 1); i++) { + t0 = *values++; + sign = ((UINT)t0 >> 31); + t0 = fixp_abs(t0); + signLength = (t0 == 0) ? 0 : 1; + t1 = *values++; + INT zero = (t1 == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)t1 >> 31); + t1 = fixp_abs(t1); + codeWord = FDKaacEnc_huff_ctab9[t0][t1]; + codeLength = HI_LTAB(FDKaacEnc_huff_ltab9_10[t0][t1]); + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + } + break; + + case CODE_BOOK_10_NO: + for (i = 0; i < (width >> 1); i++) { + t0 = *values++; + sign = ((UINT)t0 >> 31); + t0 = fixp_abs(t0); + signLength = (t0 == 0) ? 0 : 1; + t1 = *values++; + INT zero = (t1 == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)t1 >> 31); + t1 = fixp_abs(t1); + codeWord = FDKaacEnc_huff_ctab10[t0][t1]; + codeLength = LO_LTAB(FDKaacEnc_huff_ltab9_10[t0][t1]); + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + } + break; + + case CODE_BOOK_ESC_NO: + for (i = 0; i < (width >> 1); i++) { + t0 = *values++; + sign = ((UINT)t0 >> 31); + t0 = fixp_abs(t0); + signLength = (t0 == 0) ? 0 : 1; + t1 = *values++; + INT zero = (t1 == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)t1 >> 31); + t1 = fixp_abs(t1); + + t00 = fixMin(t0, 16); + t01 = fixMin(t1, 16); + + codeWord = FDKaacEnc_huff_ctab11[t00][t01]; + codeLength = (INT)FDKaacEnc_huff_ltab11[t00][t01]; + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + for (int j = 0; j < 2; j++) { + if (t0 >= 16) { + INT n = 4, p = t0; + for (; (p >>= 1) >= 16;) n++; + FDKwriteBits(hBitstream, + (((1 << (n - 3)) - 2) << n) | (t0 - (1 << n)), + n + n - 3); + } + t0 = t1; + } + } + break; + + default: + break; + } + return (0); +} + +INT FDKaacEnc_codeScalefactorDelta(INT delta, HANDLE_FDK_BITSTREAM hBitstream) { + INT codeWord, codeLength; + + if (fixp_abs(delta) > CODE_BOOK_SCF_LAV) return (1); + + codeWord = FDKaacEnc_huff_ctabscf[delta + CODE_BOOK_SCF_LAV]; + codeLength = (INT)FDKaacEnc_huff_ltabscf[delta + CODE_BOOK_SCF_LAV]; + FDKwriteBits(hBitstream, codeWord, codeLength); + return (0); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bit_cnt.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bit_cnt.h new file mode 100644 index 0000000000000..7f4c45051c9fe --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bit_cnt.h @@ -0,0 +1,200 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Huffman Bitcounter & coder + +*******************************************************************************/ + +#ifndef BIT_CNT_H +#define BIT_CNT_H + +#include "common_fix.h" +#include "FDK_bitstream.h" +#include "aacEnc_rom.h" + +#define INVALID_BITCOUNT (FDK_INT_MAX / 4) + +/* + code book number table +*/ + +enum codeBookNo { + CODE_BOOK_ZERO_NO = 0, + CODE_BOOK_1_NO = 1, + CODE_BOOK_2_NO = 2, + CODE_BOOK_3_NO = 3, + CODE_BOOK_4_NO = 4, + CODE_BOOK_5_NO = 5, + CODE_BOOK_6_NO = 6, + CODE_BOOK_7_NO = 7, + CODE_BOOK_8_NO = 8, + CODE_BOOK_9_NO = 9, + CODE_BOOK_10_NO = 10, + CODE_BOOK_ESC_NO = 11, + CODE_BOOK_RES_NO = 12, + CODE_BOOK_PNS_NO = 13, + CODE_BOOK_IS_OUT_OF_PHASE_NO = 14, + CODE_BOOK_IS_IN_PHASE_NO = 15 + +}; + +/* + code book index table +*/ + +enum codeBookNdx { + CODE_BOOK_ZERO_NDX, + CODE_BOOK_1_NDX, + CODE_BOOK_2_NDX, + CODE_BOOK_3_NDX, + CODE_BOOK_4_NDX, + CODE_BOOK_5_NDX, + CODE_BOOK_6_NDX, + CODE_BOOK_7_NDX, + CODE_BOOK_8_NDX, + CODE_BOOK_9_NDX, + CODE_BOOK_10_NDX, + CODE_BOOK_ESC_NDX, + CODE_BOOK_RES_NDX, + CODE_BOOK_PNS_NDX, + CODE_BOOK_IS_OUT_OF_PHASE_NDX, + CODE_BOOK_IS_IN_PHASE_NDX, + NUMBER_OF_CODE_BOOKS +}; + +/* + code book lav table +*/ + +enum codeBookLav { + CODE_BOOK_ZERO_LAV = 0, + CODE_BOOK_1_LAV = 1, + CODE_BOOK_2_LAV = 1, + CODE_BOOK_3_LAV = 2, + CODE_BOOK_4_LAV = 2, + CODE_BOOK_5_LAV = 4, + CODE_BOOK_6_LAV = 4, + CODE_BOOK_7_LAV = 7, + CODE_BOOK_8_LAV = 7, + CODE_BOOK_9_LAV = 12, + CODE_BOOK_10_LAV = 12, + CODE_BOOK_ESC_LAV = 16, + CODE_BOOK_SCF_LAV = 60, + CODE_BOOK_PNS_LAV = 60 +}; + +INT FDKaacEnc_bitCount(const SHORT *aQuantSpectrum, const INT noOfSpecLines, + INT maxVal, INT *bitCountLut); + +INT FDKaacEnc_countValues(SHORT *values, INT width, INT codeBook); + +INT FDKaacEnc_codeValues(SHORT *values, INT width, INT codeBook, + HANDLE_FDK_BITSTREAM hBitstream); + +INT FDKaacEnc_codeScalefactorDelta(INT scalefactor, + HANDLE_FDK_BITSTREAM hBitstream); + +inline INT FDKaacEnc_bitCountScalefactorDelta(const INT delta) { + FDK_ASSERT((0 <= (delta + CODE_BOOK_SCF_LAV)) && + ((delta + CODE_BOOK_SCF_LAV) < + (int)(sizeof(FDKaacEnc_huff_ltabscf) / + sizeof((FDKaacEnc_huff_ltabscf[0]))))); + return ((INT)FDKaacEnc_huff_ltabscf[delta + CODE_BOOK_SCF_LAV]); +} + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bitenc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bitenc.cpp new file mode 100644 index 0000000000000..957e8216e7130 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bitenc.cpp @@ -0,0 +1,1322 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Bitstream encoder + +*******************************************************************************/ + +#include "bitenc.h" +#include "bit_cnt.h" +#include "dyn_bits.h" +#include "qc_data.h" +#include "interface.h" +#include "aacEnc_ram.h" + +#include "tpenc_lib.h" + +#include "FDK_tools_rom.h" /* needed for the bitstream syntax tables */ + +static const int globalGainOffset = 100; +static const int icsReservedBit = 0; +static const int noiseOffset = 90; + +/***************************************************************************** + + functionname: FDKaacEnc_encodeSpectralData + description: encode spectral data + returns: the number of written bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeSpectralData(INT *sfbOffset, + SECTION_DATA *sectionData, + SHORT *quantSpectrum, + HANDLE_FDK_BITSTREAM hBitStream) { + INT i, sfb; + INT dbgVal = FDKgetValidBits(hBitStream); + + for (i = 0; i < sectionData->noOfSections; i++) { + if (sectionData->huffsection[i].codeBook != CODE_BOOK_PNS_NO) { + /* huffencode spectral data for this huffsection */ + INT tmp = sectionData->huffsection[i].sfbStart + + sectionData->huffsection[i].sfbCnt; + for (sfb = sectionData->huffsection[i].sfbStart; sfb < tmp; sfb++) { + FDKaacEnc_codeValues(quantSpectrum + sfbOffset[sfb], + sfbOffset[sfb + 1] - sfbOffset[sfb], + sectionData->huffsection[i].codeBook, hBitStream); + } + } + } + return (FDKgetValidBits(hBitStream) - dbgVal); +} + +/***************************************************************************** + + functionname:FDKaacEnc_encodeGlobalGain + description: encodes Global Gain (common scale factor) + returns: the number of static bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeGlobalGain(INT globalGain, INT scalefac, + HANDLE_FDK_BITSTREAM hBitStream, + INT mdctScale) { + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, + globalGain - scalefac + globalGainOffset - + 4 * (LOG_NORM_PCM - mdctScale), + 8); + } + return (8); +} + +/***************************************************************************** + + functionname:FDKaacEnc_encodeIcsInfo + description: encodes Ics Info + returns: the number of static bits + input: + output: + +*****************************************************************************/ + +static INT FDKaacEnc_encodeIcsInfo(INT blockType, INT windowShape, + INT groupingMask, INT maxSfbPerGroup, + HANDLE_FDK_BITSTREAM hBitStream, + UINT syntaxFlags) { + INT statBits; + + if (blockType == SHORT_WINDOW) { + statBits = 8 + TRANS_FAC - 1; + } else { + if (syntaxFlags & AC_ELD) { + statBits = 6; + } else { + statBits = (!(syntaxFlags & AC_SCALABLE)) ? 11 : 10; + } + } + + if (hBitStream != NULL) { + if (!(syntaxFlags & AC_ELD)) { + FDKwriteBits(hBitStream, icsReservedBit, 1); + FDKwriteBits(hBitStream, blockType, 2); + FDKwriteBits(hBitStream, + (windowShape == LOL_WINDOW) ? KBD_WINDOW : windowShape, 1); + } + + switch (blockType) { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + FDKwriteBits(hBitStream, maxSfbPerGroup, 6); + + if (!(syntaxFlags & + (AC_SCALABLE | AC_ELD))) { /* If not scalable syntax then ... */ + /* No predictor data present */ + FDKwriteBits(hBitStream, 0, 1); + } + break; + + case SHORT_WINDOW: + FDKwriteBits(hBitStream, maxSfbPerGroup, 4); + + /* Write grouping bits */ + FDKwriteBits(hBitStream, groupingMask, TRANS_FAC - 1); + break; + } + } + + return (statBits); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeSectionData + description: encode section data (common Huffman codebooks for adjacent + SFB's) + returns: none + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeSectionData(SECTION_DATA *sectionData, + HANDLE_FDK_BITSTREAM hBitStream, + UINT useVCB11) { + if (hBitStream != NULL) { + INT sectEscapeVal = 0, sectLenBits = 0; + INT sectLen; + INT i; + INT dbgVal = FDKgetValidBits(hBitStream); + INT sectCbBits = 4; + + switch (sectionData->blockType) { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + sectEscapeVal = SECT_ESC_VAL_LONG; + sectLenBits = SECT_BITS_LONG; + break; + + case SHORT_WINDOW: + sectEscapeVal = SECT_ESC_VAL_SHORT; + sectLenBits = SECT_BITS_SHORT; + break; + } + + for (i = 0; i < sectionData->noOfSections; i++) { + INT codeBook = sectionData->huffsection[i].codeBook; + + FDKwriteBits(hBitStream, codeBook, sectCbBits); + + { + sectLen = sectionData->huffsection[i].sfbCnt; + + while (sectLen >= sectEscapeVal) { + FDKwriteBits(hBitStream, sectEscapeVal, sectLenBits); + sectLen -= sectEscapeVal; + } + FDKwriteBits(hBitStream, sectLen, sectLenBits); + } + } + return (FDKgetValidBits(hBitStream) - dbgVal); + } + return (0); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeScaleFactorData + description: encode DPCM coded scale factors + returns: none + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeScaleFactorData(UINT *maxValueInSfb, + SECTION_DATA *sectionData, + INT *scalefac, + HANDLE_FDK_BITSTREAM hBitStream, + INT *RESTRICT noiseNrg, + const INT *isScale, INT globalGain) { + if (hBitStream != NULL) { + INT i, j, lastValScf, deltaScf; + INT deltaPns; + INT lastValPns = 0; + INT noisePCMFlag = TRUE; + INT lastValIs; + + INT dbgVal = FDKgetValidBits(hBitStream); + + lastValScf = scalefac[sectionData->firstScf]; + lastValPns = globalGain - scalefac[sectionData->firstScf] + + globalGainOffset - 4 * LOG_NORM_PCM - noiseOffset; + lastValIs = 0; + + for (i = 0; i < sectionData->noOfSections; i++) { + if (sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) { + if ((sectionData->huffsection[i].codeBook == + CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (sectionData->huffsection[i].codeBook == + CODE_BOOK_IS_IN_PHASE_NO)) { + INT sfbStart = sectionData->huffsection[i].sfbStart; + INT tmp = sfbStart + sectionData->huffsection[i].sfbCnt; + for (j = sfbStart; j < tmp; j++) { + INT deltaIs = isScale[j] - lastValIs; + lastValIs = isScale[j]; + if (FDKaacEnc_codeScalefactorDelta(deltaIs, hBitStream)) { + return (1); + } + } /* sfb */ + } else if (sectionData->huffsection[i].codeBook == CODE_BOOK_PNS_NO) { + INT sfbStart = sectionData->huffsection[i].sfbStart; + INT tmp = sfbStart + sectionData->huffsection[i].sfbCnt; + for (j = sfbStart; j < tmp; j++) { + deltaPns = noiseNrg[j] - lastValPns; + lastValPns = noiseNrg[j]; + + if (noisePCMFlag) { + FDKwriteBits(hBitStream, deltaPns + (1 << (PNS_PCM_BITS - 1)), + PNS_PCM_BITS); + noisePCMFlag = FALSE; + } else { + if (FDKaacEnc_codeScalefactorDelta(deltaPns, hBitStream)) { + return (1); + } + } + } /* sfb */ + } else { + INT tmp = sectionData->huffsection[i].sfbStart + + sectionData->huffsection[i].sfbCnt; + for (j = sectionData->huffsection[i].sfbStart; j < tmp; j++) { + /* + check if we can repeat the last value to save bits + */ + if (maxValueInSfb[j] == 0) + deltaScf = 0; + else { + deltaScf = -(scalefac[j] - lastValScf); + lastValScf = scalefac[j]; + } + if (FDKaacEnc_codeScalefactorDelta(deltaScf, hBitStream)) { + return (1); + } + } /* sfb */ + } /* code scalefactor */ + } /* sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO */ + } /* section loop */ + + return (FDKgetValidBits(hBitStream) - dbgVal); + } /* if (hBitStream != NULL) */ + + return (0); +} + +/***************************************************************************** + + functionname:encodeMsInfo + description: encodes MS-Stereo Info + returns: the number of static bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeMSInfo(INT sfbCnt, INT grpSfb, INT maxSfb, + INT msDigest, INT *jsFlags, + HANDLE_FDK_BITSTREAM hBitStream) { + INT sfb, sfbOff, msBits = 0; + + if (hBitStream != NULL) { + switch (msDigest) { + case MS_NONE: + FDKwriteBits(hBitStream, SI_MS_MASK_NONE, 2); + msBits += 2; + break; + + case MS_ALL: + FDKwriteBits(hBitStream, SI_MS_MASK_ALL, 2); + msBits += 2; + break; + + case MS_SOME: + FDKwriteBits(hBitStream, SI_MS_MASK_SOME, 2); + msBits += 2; + for (sfbOff = 0; sfbOff < sfbCnt; sfbOff += grpSfb) { + for (sfb = 0; sfb < maxSfb; sfb++) { + if (jsFlags[sfbOff + sfb] & MS_ON) { + FDKwriteBits(hBitStream, 1, 1); + } else { + FDKwriteBits(hBitStream, 0, 1); + } + msBits += 1; + } + } + break; + } + } else { + msBits += 2; + if (msDigest == MS_SOME) { + for (sfbOff = 0; sfbOff < sfbCnt; sfbOff += grpSfb) { + for (sfb = 0; sfb < maxSfb; sfb++) { + msBits += 1; + } + } + } + } + return (msBits); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeTnsDataPresent + description: encode TNS data (filter order, coeffs, ..) + returns: the number of static bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeTnsDataPresent(TNS_INFO *tnsInfo, INT blockType, + HANDLE_FDK_BITSTREAM hBitStream) { + if ((hBitStream != NULL) && (tnsInfo != NULL)) { + INT i, tnsPresent = 0; + INT numOfWindows = (blockType == SHORT_WINDOW ? TRANS_FAC : 1); + + for (i = 0; i < numOfWindows; i++) { + if (tnsInfo->numOfFilters[i] != 0) { + tnsPresent = 1; + break; + } + } + + if (tnsPresent == 0) { + FDKwriteBits(hBitStream, 0, 1); + } else { + FDKwriteBits(hBitStream, 1, 1); + } + } + return (1); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeTnsData + description: encode TNS data (filter order, coeffs, ..) + returns: the number of static bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeTnsData(TNS_INFO *tnsInfo, INT blockType, + HANDLE_FDK_BITSTREAM hBitStream) { + INT tnsBits = 0; + + if (tnsInfo != NULL) { + INT i, j, k; + INT tnsPresent = 0; + INT coefBits; + INT numOfWindows = (blockType == SHORT_WINDOW ? TRANS_FAC : 1); + + for (i = 0; i < numOfWindows; i++) { + if (tnsInfo->numOfFilters[i] != 0) { + tnsPresent = 1; + } + } + + if (hBitStream != NULL) { + if (tnsPresent == 1) { /* there is data to be written*/ + for (i = 0; i < numOfWindows; i++) { + FDKwriteBits(hBitStream, tnsInfo->numOfFilters[i], + (blockType == SHORT_WINDOW ? 1 : 2)); + tnsBits += (blockType == SHORT_WINDOW ? 1 : 2); + if (tnsInfo->numOfFilters[i]) { + FDKwriteBits(hBitStream, (tnsInfo->coefRes[i] == 4 ? 1 : 0), 1); + tnsBits += 1; + } + for (j = 0; j < tnsInfo->numOfFilters[i]; j++) { + FDKwriteBits(hBitStream, tnsInfo->length[i][j], + (blockType == SHORT_WINDOW ? 4 : 6)); + tnsBits += (blockType == SHORT_WINDOW ? 4 : 6); + FDK_ASSERT(tnsInfo->order[i][j] <= 12); + FDKwriteBits(hBitStream, tnsInfo->order[i][j], + (blockType == SHORT_WINDOW ? 3 : 5)); + tnsBits += (blockType == SHORT_WINDOW ? 3 : 5); + if (tnsInfo->order[i][j]) { + FDKwriteBits(hBitStream, tnsInfo->direction[i][j], 1); + tnsBits += 1; /*direction*/ + if (tnsInfo->coefRes[i] == 4) { + coefBits = 3; + for (k = 0; k < tnsInfo->order[i][j]; k++) { + if (tnsInfo->coef[i][j][k] > 3 || + tnsInfo->coef[i][j][k] < -4) { + coefBits = 4; + break; + } + } + } else { + coefBits = 2; + for (k = 0; k < tnsInfo->order[i][j]; k++) { + if (tnsInfo->coef[i][j][k] > 1 || + tnsInfo->coef[i][j][k] < -2) { + coefBits = 3; + break; + } + } + } + FDKwriteBits(hBitStream, -(coefBits - tnsInfo->coefRes[i]), + 1); /*coef_compres*/ + tnsBits += 1; /*coef_compression */ + for (k = 0; k < tnsInfo->order[i][j]; k++) { + static const INT rmask[] = {0, 1, 3, 7, 15}; + FDKwriteBits(hBitStream, + tnsInfo->coef[i][j][k] & rmask[coefBits], + coefBits); + tnsBits += coefBits; + } + } + } + } + } + } else { + if (tnsPresent != 0) { + for (i = 0; i < numOfWindows; i++) { + tnsBits += (blockType == SHORT_WINDOW ? 1 : 2); + if (tnsInfo->numOfFilters[i]) { + tnsBits += 1; + for (j = 0; j < tnsInfo->numOfFilters[i]; j++) { + tnsBits += (blockType == SHORT_WINDOW ? 4 : 6); + tnsBits += (blockType == SHORT_WINDOW ? 3 : 5); + if (tnsInfo->order[i][j]) { + tnsBits += 1; /*direction*/ + tnsBits += 1; /*coef_compression */ + if (tnsInfo->coefRes[i] == 4) { + coefBits = 3; + for (k = 0; k < tnsInfo->order[i][j]; k++) { + if (tnsInfo->coef[i][j][k] > 3 || + tnsInfo->coef[i][j][k] < -4) { + coefBits = 4; + break; + } + } + } else { + coefBits = 2; + for (k = 0; k < tnsInfo->order[i][j]; k++) { + if (tnsInfo->coef[i][j][k] > 1 || + tnsInfo->coef[i][j][k] < -2) { + coefBits = 3; + break; + } + } + } + for (k = 0; k < tnsInfo->order[i][j]; k++) { + tnsBits += coefBits; + } + } + } + } + } + } + } + } /* (tnsInfo!=NULL) */ + + return (tnsBits); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeGainControlData + description: unsupported + returns: none + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeGainControlData(HANDLE_FDK_BITSTREAM hBitStream) { + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, 0, 1); + } + return (1); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodePulseData + description: not supported yet (dummy) + returns: none + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodePulseData(HANDLE_FDK_BITSTREAM hBitStream) { + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, 0, 1); + } + return (1); +} + +/***************************************************************************** + + functionname: FDKaacEnc_writeExtensionPayload + description: write extension payload to bitstream + returns: number of written bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_writeExtensionPayload(HANDLE_FDK_BITSTREAM hBitStream, + EXT_PAYLOAD_TYPE extPayloadType, + const UCHAR *extPayloadData, + INT extPayloadBits) { +#define EXT_TYPE_BITS (4) +#define DATA_EL_VERSION_BITS (4) +#define FILL_NIBBLE_BITS (4) + + INT extBitsUsed = 0; + + if (extPayloadBits >= EXT_TYPE_BITS) { + UCHAR fillByte = 0x00; /* for EXT_FIL and EXT_FILL_DATA */ + + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, extPayloadType, EXT_TYPE_BITS); + } + extBitsUsed += EXT_TYPE_BITS; + + switch (extPayloadType) { + /* case EXT_SAC_DATA: */ + case EXT_LDSAC_DATA: + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, *extPayloadData++, 4); /* nibble */ + } + extBitsUsed += 4; + FDK_FALLTHROUGH; + case EXT_DYNAMIC_RANGE: + case EXT_SBR_DATA: + case EXT_SBR_DATA_CRC: + if (hBitStream != NULL) { + int i, writeBits = extPayloadBits; + for (i = 0; writeBits >= 8; i++) { + FDKwriteBits(hBitStream, *extPayloadData++, 8); + writeBits -= 8; + } + if (writeBits > 0) { + FDKwriteBits(hBitStream, (*extPayloadData) >> (8 - writeBits), + writeBits); + } + } + extBitsUsed += extPayloadBits; + break; + + case EXT_DATA_ELEMENT: { + INT dataElementLength = (extPayloadBits + 7) >> 3; + INT cnt = dataElementLength; + int loopCounter = 1; + + while (dataElementLength >= 255) { + loopCounter++; + dataElementLength -= 255; + } + + if (hBitStream != NULL) { + int i; + FDKwriteBits( + hBitStream, 0x00, + DATA_EL_VERSION_BITS); /* data_element_version = ANC_DATA */ + + for (i = 1; i < loopCounter; i++) { + FDKwriteBits(hBitStream, 255, 8); + } + FDKwriteBits(hBitStream, dataElementLength, 8); + + for (i = 0; i < cnt; i++) { + FDKwriteBits(hBitStream, extPayloadData[i], 8); + } + } + extBitsUsed += DATA_EL_VERSION_BITS + (loopCounter * 8) + (cnt * 8); + } break; + + case EXT_FILL_DATA: + fillByte = 0xA5; + FDK_FALLTHROUGH; + case EXT_FIL: + default: + if (hBitStream != NULL) { + int writeBits = extPayloadBits; + FDKwriteBits(hBitStream, 0x00, FILL_NIBBLE_BITS); + writeBits -= + 8; /* acount for the extension type and the fill nibble */ + while (writeBits >= 8) { + FDKwriteBits(hBitStream, fillByte, 8); + writeBits -= 8; + } + } + extBitsUsed += FILL_NIBBLE_BITS + (extPayloadBits & ~0x7) - 8; + break; + } + } + + return (extBitsUsed); +} + +/***************************************************************************** + + functionname: FDKaacEnc_writeDataStreamElement + description: write data stream elements like ancillary data ... + returns: the amount of used bits + input: + output: + +******************************************************************************/ +static INT FDKaacEnc_writeDataStreamElement(HANDLE_TRANSPORTENC hTpEnc, + INT elementInstanceTag, + INT dataPayloadBytes, + UCHAR *dataBuffer, + UINT alignAnchor) { +#define DATA_BYTE_ALIGN_FLAG (0) + +#define EL_INSTANCE_TAG_BITS (4) +#define DATA_BYTE_ALIGN_FLAG_BITS (1) +#define DATA_LEN_COUNT_BITS (8) +#define DATA_LEN_ESC_COUNT_BITS (8) + +#define MAX_DATA_ALIGN_BITS (7) +#define MAX_DSE_DATA_BYTES (510) + + INT dseBitsUsed = 0; + + while (dataPayloadBytes > 0) { + int esc_count = -1; + int cnt = 0; + INT crcReg = -1; + + dseBitsUsed += EL_ID_BITS + EL_INSTANCE_TAG_BITS + + DATA_BYTE_ALIGN_FLAG_BITS + DATA_LEN_COUNT_BITS; + + if (DATA_BYTE_ALIGN_FLAG) { + dseBitsUsed += MAX_DATA_ALIGN_BITS; + } + + cnt = fixMin(MAX_DSE_DATA_BYTES, dataPayloadBytes); + if (cnt >= 255) { + esc_count = cnt - 255; + dseBitsUsed += DATA_LEN_ESC_COUNT_BITS; + } + + dataPayloadBytes -= cnt; + dseBitsUsed += cnt * 8; + + if (hTpEnc != NULL) { + HANDLE_FDK_BITSTREAM hBitStream = transportEnc_GetBitstream(hTpEnc); + int i; + + FDKwriteBits(hBitStream, ID_DSE, EL_ID_BITS); + + crcReg = transportEnc_CrcStartReg(hTpEnc, 0); + + FDKwriteBits(hBitStream, elementInstanceTag, EL_INSTANCE_TAG_BITS); + FDKwriteBits(hBitStream, DATA_BYTE_ALIGN_FLAG, DATA_BYTE_ALIGN_FLAG_BITS); + + /* write length field(s) */ + if (esc_count >= 0) { + FDKwriteBits(hBitStream, 255, DATA_LEN_COUNT_BITS); + FDKwriteBits(hBitStream, esc_count, DATA_LEN_ESC_COUNT_BITS); + } else { + FDKwriteBits(hBitStream, cnt, DATA_LEN_COUNT_BITS); + } + + if (DATA_BYTE_ALIGN_FLAG) { + INT tmp = (INT)FDKgetValidBits(hBitStream); + FDKbyteAlign(hBitStream, alignAnchor); + /* count actual bits */ + dseBitsUsed += + (INT)FDKgetValidBits(hBitStream) - tmp - MAX_DATA_ALIGN_BITS; + } + + /* write payload */ + for (i = 0; i < cnt; i++) { + FDKwriteBits(hBitStream, dataBuffer[i], 8); + } + transportEnc_CrcEndReg(hTpEnc, crcReg); + } + } + + return (dseBitsUsed); +} + +/***************************************************************************** + + functionname: FDKaacEnc_writeExtensionData + description: write extension payload to bitstream + returns: number of written bits + input: + output: + +*****************************************************************************/ +INT FDKaacEnc_writeExtensionData(HANDLE_TRANSPORTENC hTpEnc, + QC_OUT_EXTENSION *pExtension, + INT elInstanceTag, /* for DSE only */ + UINT alignAnchor, /* for DSE only */ + UINT syntaxFlags, AUDIO_OBJECT_TYPE aot, + SCHAR epConfig) { +#define FILL_EL_COUNT_BITS (4) +#define FILL_EL_ESC_COUNT_BITS (8) +#define MAX_FILL_DATA_BYTES (269) + + HANDLE_FDK_BITSTREAM hBitStream = NULL; + INT payloadBits = pExtension->nPayloadBits; + INT extBitsUsed = 0; + + if (hTpEnc != NULL) { + hBitStream = transportEnc_GetBitstream(hTpEnc); + } + + if (syntaxFlags & (AC_SCALABLE | AC_ER)) { + { + if ((syntaxFlags & AC_ELD) && ((pExtension->type == EXT_SBR_DATA) || + (pExtension->type == EXT_SBR_DATA_CRC))) { + if (hBitStream != NULL) { + int i, writeBits = payloadBits; + UCHAR *extPayloadData = pExtension->pPayload; + + for (i = 0; writeBits >= 8; i++) { + FDKwriteBits(hBitStream, extPayloadData[i], 8); + writeBits -= 8; + } + if (writeBits > 0) { + FDKwriteBits(hBitStream, extPayloadData[i] >> (8 - writeBits), + writeBits); + } + } + extBitsUsed += payloadBits; + } else { + /* ER or scalable syntax -> write extension en bloc */ + extBitsUsed += FDKaacEnc_writeExtensionPayload( + hBitStream, pExtension->type, pExtension->pPayload, payloadBits); + } + } + } else { + /* We have normal GA bitstream payload (AOT 2,5,29) so pack + the data into a fill elements or DSEs */ + + if (pExtension->type == EXT_DATA_ELEMENT) { + extBitsUsed += FDKaacEnc_writeDataStreamElement( + hTpEnc, elInstanceTag, pExtension->nPayloadBits >> 3, + pExtension->pPayload, alignAnchor); + } else { + while (payloadBits >= (EL_ID_BITS + FILL_EL_COUNT_BITS)) { + INT cnt, esc_count = -1, alignBits = 7; + + if ((pExtension->type == EXT_FILL_DATA) || + (pExtension->type == EXT_FIL)) { + payloadBits -= EL_ID_BITS + FILL_EL_COUNT_BITS; + if (payloadBits >= 15 * 8) { + payloadBits -= FILL_EL_ESC_COUNT_BITS; + esc_count = 0; /* write esc_count even if cnt becomes smaller 15 */ + } + alignBits = 0; + } + + cnt = fixMin(MAX_FILL_DATA_BYTES, (payloadBits + alignBits) >> 3); + + if (cnt >= 15) { + esc_count = cnt - 15 + 1; + } + + if (hBitStream != NULL) { + /* write bitstream */ + FDKwriteBits(hBitStream, ID_FIL, EL_ID_BITS); + if (esc_count >= 0) { + FDKwriteBits(hBitStream, 15, FILL_EL_COUNT_BITS); + FDKwriteBits(hBitStream, esc_count, FILL_EL_ESC_COUNT_BITS); + } else { + FDKwriteBits(hBitStream, cnt, FILL_EL_COUNT_BITS); + } + } + + extBitsUsed += EL_ID_BITS + FILL_EL_COUNT_BITS + + ((esc_count >= 0) ? FILL_EL_ESC_COUNT_BITS : 0); + + cnt = fixMin(cnt * 8, payloadBits); /* convert back to bits */ + extBitsUsed += FDKaacEnc_writeExtensionPayload( + hBitStream, pExtension->type, pExtension->pPayload, cnt); + payloadBits -= cnt; + } + } + } + + return (extBitsUsed); +} + +/***************************************************************************** + + functionname: FDKaacEnc_ByteAlignment + description: + returns: + input: + output: + +*****************************************************************************/ +static void FDKaacEnc_ByteAlignment(HANDLE_FDK_BITSTREAM hBitStream, + int alignBits) { + FDKwriteBits(hBitStream, 0, alignBits); +} + +AAC_ENCODER_ERROR FDKaacEnc_ChannelElementWrite( + HANDLE_TRANSPORTENC hTpEnc, ELEMENT_INFO *pElInfo, + QC_OUT_CHANNEL *qcOutChannel[(2)], PSY_OUT_ELEMENT *psyOutElement, + PSY_OUT_CHANNEL *psyOutChannel[(2)], UINT syntaxFlags, + AUDIO_OBJECT_TYPE aot, SCHAR epConfig, INT *pBitDemand, UCHAR minCnt) { + AAC_ENCODER_ERROR error = AAC_ENC_OK; + HANDLE_FDK_BITSTREAM hBitStream = NULL; + INT bitDemand = 0; + const element_list_t *list; + int i, ch, decision_bit; + INT crcReg1 = -1, crcReg2 = -1; + UCHAR numberOfChannels; + + if (hTpEnc != NULL) { + /* Get bitstream handle */ + hBitStream = transportEnc_GetBitstream(hTpEnc); + } + + if ((pElInfo->elType == ID_SCE) || (pElInfo->elType == ID_LFE)) { + numberOfChannels = 1; + } else { + numberOfChannels = 2; + } + + /* Get channel element sequence table */ + list = getBitstreamElementList(aot, epConfig, numberOfChannels, 0, 0); + if (list == NULL) { + error = AAC_ENC_UNSUPPORTED_AOT; + goto bail; + } + + if (!(syntaxFlags & (AC_SCALABLE | AC_ER))) { + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, pElInfo->elType, EL_ID_BITS); + } + bitDemand += EL_ID_BITS; + } + + /* Iterate through sequence table */ + i = 0; + ch = 0; + decision_bit = 0; + do { + /* some tmp values */ + SECTION_DATA *pChSectionData = NULL; + INT *pChScf = NULL; + UINT *pChMaxValueInSfb = NULL; + TNS_INFO *pTnsInfo = NULL; + INT chGlobalGain = 0; + INT chBlockType = 0; + INT chMaxSfbPerGrp = 0; + INT chSfbPerGrp = 0; + INT chSfbCnt = 0; + INT chFirstScf = 0; + + if (minCnt == 0) { + if (qcOutChannel != NULL) { + pChSectionData = &(qcOutChannel[ch]->sectionData); + pChScf = qcOutChannel[ch]->scf; + chGlobalGain = qcOutChannel[ch]->globalGain; + pChMaxValueInSfb = qcOutChannel[ch]->maxValueInSfb; + chBlockType = pChSectionData->blockType; + chMaxSfbPerGrp = pChSectionData->maxSfbPerGroup; + chSfbPerGrp = pChSectionData->sfbPerGroup; + chSfbCnt = pChSectionData->sfbCnt; + chFirstScf = pChScf[pChSectionData->firstScf]; + } else { + /* get values from PSY */ + chSfbCnt = psyOutChannel[ch]->sfbCnt; + chSfbPerGrp = psyOutChannel[ch]->sfbPerGroup; + chMaxSfbPerGrp = psyOutChannel[ch]->maxSfbPerGroup; + } + pTnsInfo = &psyOutChannel[ch]->tnsInfo; + } /* minCnt==0 */ + + if (qcOutChannel == NULL) { + chBlockType = psyOutChannel[ch]->lastWindowSequence; + } + + switch (list->id[i]) { + case element_instance_tag: + /* Write element instance tag */ + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, pElInfo->instanceTag, 4); + } + bitDemand += 4; + break; + + case common_window: + /* Write common window flag */ + decision_bit = psyOutElement->commonWindow; + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, psyOutElement->commonWindow, 1); + } + bitDemand += 1; + break; + + case ics_info: + /* Write individual channel info */ + bitDemand += + FDKaacEnc_encodeIcsInfo(chBlockType, psyOutChannel[ch]->windowShape, + psyOutChannel[ch]->groupingMask, + chMaxSfbPerGrp, hBitStream, syntaxFlags); + break; + + case ltp_data_present: + /* Write LTP data present flag */ + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, 0, 1); + } + bitDemand += 1; + break; + + case ltp_data: + /* Predictor data not supported. + Nothing to do here. */ + break; + + case ms: + /* Write MS info */ + bitDemand += FDKaacEnc_encodeMSInfo( + chSfbCnt, chSfbPerGrp, chMaxSfbPerGrp, + (minCnt == 0) ? psyOutElement->toolsInfo.msDigest : MS_NONE, + psyOutElement->toolsInfo.msMask, hBitStream); + break; + + case global_gain: + bitDemand += FDKaacEnc_encodeGlobalGain( + chGlobalGain, chFirstScf, hBitStream, psyOutChannel[ch]->mdctScale); + break; + + case section_data: { + INT siBits = FDKaacEnc_encodeSectionData( + pChSectionData, hBitStream, (syntaxFlags & AC_ER_VCB11) ? 1 : 0); + if (hBitStream != NULL) { + if (siBits != qcOutChannel[ch]->sectionData.sideInfoBits) { + error = AAC_ENC_WRITE_SEC_ERROR; + } + } + bitDemand += siBits; + } break; + + case scale_factor_data: { + INT sfDataBits = FDKaacEnc_encodeScaleFactorData( + pChMaxValueInSfb, pChSectionData, pChScf, hBitStream, + psyOutChannel[ch]->noiseNrg, psyOutChannel[ch]->isScale, + chGlobalGain); + if ((hBitStream != NULL) && + (sfDataBits != (qcOutChannel[ch]->sectionData.scalefacBits + + qcOutChannel[ch]->sectionData.noiseNrgBits))) { + error = AAC_ENC_WRITE_SCAL_ERROR; + } + bitDemand += sfDataBits; + } break; + + case esc2_rvlc: + if (syntaxFlags & AC_ER_RVLC) { + /* write RVLC data into bitstream (error sens. cat. 2) */ + error = AAC_ENC_UNSUPPORTED_AOT; + } + break; + + case pulse: + /* Write pulse data */ + bitDemand += FDKaacEnc_encodePulseData(hBitStream); + break; + + case tns_data_present: + /* Write TNS data present flag */ + bitDemand += + FDKaacEnc_encodeTnsDataPresent(pTnsInfo, chBlockType, hBitStream); + break; + case tns_data: + /* Write TNS data */ + bitDemand += FDKaacEnc_encodeTnsData(pTnsInfo, chBlockType, hBitStream); + break; + + case gain_control_data: + /* Nothing to do here */ + break; + + case gain_control_data_present: + bitDemand += FDKaacEnc_encodeGainControlData(hBitStream); + break; + + case esc1_hcr: + if (syntaxFlags & AC_ER_HCR) { + error = AAC_ENC_UNKNOWN; + } + break; + + case spectral_data: + if (hBitStream != NULL) { + INT spectralBits = 0; + + spectralBits = FDKaacEnc_encodeSpectralData( + psyOutChannel[ch]->sfbOffsets, pChSectionData, + qcOutChannel[ch]->quantSpec, hBitStream); + + if (spectralBits != qcOutChannel[ch]->sectionData.huffmanBits) { + return AAC_ENC_WRITE_SPEC_ERROR; + } + bitDemand += spectralBits; + } + break; + + /* Non data cases */ + case adtscrc_start_reg1: + if (hTpEnc != NULL) { + crcReg1 = transportEnc_CrcStartReg(hTpEnc, 192); + } + break; + case adtscrc_start_reg2: + if (hTpEnc != NULL) { + crcReg2 = transportEnc_CrcStartReg(hTpEnc, 128); + } + break; + case adtscrc_end_reg1: + case drmcrc_end_reg: + if (hTpEnc != NULL) { + transportEnc_CrcEndReg(hTpEnc, crcReg1); + } + break; + case adtscrc_end_reg2: + if (hTpEnc != NULL) { + transportEnc_CrcEndReg(hTpEnc, crcReg2); + } + break; + case drmcrc_start_reg: + if (hTpEnc != NULL) { + crcReg1 = transportEnc_CrcStartReg(hTpEnc, 0); + } + break; + case next_channel: + ch = (ch + 1) % numberOfChannels; + break; + case link_sequence: + list = list->next[decision_bit]; + i = -1; + break; + + default: + error = AAC_ENC_UNKNOWN; + break; + } + + if (error != AAC_ENC_OK) { + return error; + } + + i++; + + } while (list->id[i] != end_of_sequence); + +bail: + if (pBitDemand != NULL) { + *pBitDemand = bitDemand; + } + + return error; +} + +//----------------------------------------------------------------------------------------------- + +AAC_ENCODER_ERROR FDKaacEnc_WriteBitstream(HANDLE_TRANSPORTENC hTpEnc, + CHANNEL_MAPPING *channelMapping, + QC_OUT *qcOut, PSY_OUT *psyOut, + QC_STATE *qcKernel, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig) { + HANDLE_FDK_BITSTREAM hBs = transportEnc_GetBitstream(hTpEnc); + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + int i, n, doByteAlign = 1; + INT bitMarkUp; + INT frameBits; + /* Get first bit of raw data block. + In case of ADTS+PCE, AU would start at PCE. + This is okay because PCE assures alignment. */ + UINT alignAnchor = FDKgetValidBits(hBs); + + frameBits = bitMarkUp = alignAnchor; + + /* Channel element loop */ + for (i = 0; i < channelMapping->nElements; i++) { + ELEMENT_INFO elInfo = channelMapping->elInfo[i]; + INT elementUsedBits = 0; + + switch (elInfo.elType) { + case ID_SCE: /* single channel */ + case ID_CPE: /* channel pair */ + case ID_LFE: /* low freq effects channel */ + { + if (AAC_ENC_OK != + (ErrorStatus = FDKaacEnc_ChannelElementWrite( + hTpEnc, &elInfo, qcOut->qcElement[i]->qcOutChannel, + psyOut->psyOutElement[i], + psyOut->psyOutElement[i]->psyOutChannel, + syntaxFlags, /* syntaxFlags (ER tools ...) */ + aot, /* aot: AOT_AAC_LC, AOT_SBR, AOT_PS */ + epConfig, /* epConfig -1, 0, 1 */ + NULL, 0))) { + return ErrorStatus; + } + + if (!(syntaxFlags & AC_ER)) { + /* Write associated extension payload */ + for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) { + FDKaacEnc_writeExtensionData( + hTpEnc, &qcOut->qcElement[i]->extension[n], 0, alignAnchor, + syntaxFlags, aot, epConfig); + } + } + } break; + + /* In FDK, DSE signalling explicit done in elDSE. See channel_map.cpp */ + default: + return AAC_ENC_INVALID_ELEMENTINFO_TYPE; + + } /* switch */ + + if (elInfo.elType != ID_DSE) { + elementUsedBits -= bitMarkUp; + bitMarkUp = FDKgetValidBits(hBs); + elementUsedBits += bitMarkUp; + frameBits += elementUsedBits; + } + + } /* for (i=0; inElements; i++) { + for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) { + if ((qcOut->qcElement[i]->extension[n].type == EXT_SBR_DATA) || + (qcOut->qcElement[i]->extension[n].type == EXT_SBR_DATA_CRC)) { + /* Write sbr extension payload */ + FDKaacEnc_writeExtensionData( + hTpEnc, &qcOut->qcElement[i]->extension[n], 0, alignAnchor, + syntaxFlags, aot, epConfig); + + channelElementExtensionWritten[i][n] = 1; + } /* SBR */ + } /* n */ + } /* i */ + } /* AC_ELD */ + + for (i = 0; i < channelMapping->nElements; i++) { + for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) { + if (channelElementExtensionWritten[i][n] == 0) { + /* Write all ramaining extension payloads in element */ + FDKaacEnc_writeExtensionData(hTpEnc, + &qcOut->qcElement[i]->extension[n], 0, + alignAnchor, syntaxFlags, aot, epConfig); + } + } /* n */ + } /* i */ + } /* if AC_ER */ + + /* Extend global extension payload table with fill bits */ + n = qcOut->nExtensions; + + /* Add fill data / stuffing bits */ + qcOut->extension[n].type = EXT_FILL_DATA; + qcOut->extension[n].nPayloadBits = qcOut->totFillBits; + qcOut->nExtensions++; + + /* Write global extension payload and fill data */ + for (n = 0; (n < qcOut->nExtensions) && (n < (2 + 2)); n++) { + FDKaacEnc_writeExtensionData(hTpEnc, &qcOut->extension[n], 0, alignAnchor, + syntaxFlags, aot, epConfig); + + /* For EXT_FIL or EXT_FILL_DATA we could do an additional sanity check here + */ + } + + if (!(syntaxFlags & (AC_SCALABLE | AC_ER))) { + FDKwriteBits(hBs, ID_END, EL_ID_BITS); + } + + if (doByteAlign) { + /* Assure byte alignment*/ + if (((FDKgetValidBits(hBs) - alignAnchor + qcOut->alignBits) & 0x7) != 0) { + return AAC_ENC_WRITTEN_BITS_ERROR; + } + + FDKaacEnc_ByteAlignment(hBs, qcOut->alignBits); + } + + frameBits -= bitMarkUp; + frameBits += FDKgetValidBits(hBs); + + transportEnc_EndAccessUnit(hTpEnc, &frameBits); + + if (frameBits != qcOut->totalBits + qcKernel->globHdrBits) { + return AAC_ENC_WRITTEN_BITS_ERROR; + } + + return ErrorStatus; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bitenc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bitenc.h new file mode 100644 index 0000000000000..75dc068a73c38 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/bitenc.h @@ -0,0 +1,184 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Bitstream encoder + +*******************************************************************************/ + +#ifndef BITENC_H +#define BITENC_H + +#include "qc_data.h" +#include "aacenc_tns.h" +#include "channel_map.h" +#include "interface.h" /* obsolete, when PSY_OUT is thrown out of the WritBS-call! */ +#include "FDK_audio.h" +#include "aacenc.h" + +#include "tpenc_lib.h" + +typedef enum { + MAX_ENCODER_CHANNELS = 9, + MAX_BLOCK_TYPES = 4, + MAX_AAC_LAYERS = 9, + MAX_LAYERS = MAX_AAC_LAYERS, /* only one core layer if present */ + FIRST_LAY = 1 /* default layer number for AAC nonscalable */ +} _MAX_CONST; + +#define BUFFER_MX_HUFFCB_SIZE \ + (32 * sizeof(INT)) /* our FDK_bitbuffer needs size of power 2 */ + +#define EL_ID_BITS (3) + +/** + * \brief Arbitrary order bitstream writer. This function can either assemble a + * bit stream and write into the bit buffer of hTpEnc or calculate the number of + * static bits (signal independent) TpEnc handle must be NULL in this + * case. Or also Calculate the minimum possible number of static bits + * which by disabling all tools e.g. MS, TNS and sbfCnt=0. The minCnt + * parameter has to be 1 in this latter case. + * \param hTpEnc Transport encoder handle. If NULL, the number of static bits + * will be returned into *pBitDemand. + * \param pElInfo + * \param qcOutChannel + * \param hReorderInfo + * \param psyOutElement + * \param psyOutChannel + * \param syntaxFlags Bit stream syntax flags as defined in FDK_audio.h (Audio + * Codec flags). + * \param aot + * \param epConfig + * \param pBitDemand Pointer to an int where the amount of bits is returned + * into. The returned value depends on if hTpEnc is NULL and minCnt. + * \param minCnt If non-zero the value returned into *pBitDemand is the absolute + * minimum required amount of static bits in order to write a valid bit stream. + * \return AAC_ENCODER_ERROR error code + */ +AAC_ENCODER_ERROR FDKaacEnc_ChannelElementWrite( + HANDLE_TRANSPORTENC hTpEnc, ELEMENT_INFO *pElInfo, + QC_OUT_CHANNEL *qcOutChannel[(2)], PSY_OUT_ELEMENT *psyOutElement, + PSY_OUT_CHANNEL *psyOutChannel[(2)], UINT syntaxFlags, + AUDIO_OBJECT_TYPE aot, SCHAR epConfig, INT *pBitDemand, UCHAR minCnt); +/** + * \brief Write bit stream or account static bits + * \param hTpEnc transport encoder handle. If NULL, the function will + * not write any bit stream data but only count the amount + * of static (signal independent) bits + * \param channelMapping Channel mapping info + * \param qcOut + * \param psyOut + * \param qcKernel + * \param hBSE + * \param aot Audio Object Type being encoded + * \param syntaxFlags Flags indicating format specific detail + * \param epConfig Error protection config + */ +AAC_ENCODER_ERROR FDKaacEnc_WriteBitstream(HANDLE_TRANSPORTENC hTpEnc, + CHANNEL_MAPPING *channelMapping, + QC_OUT *qcOut, PSY_OUT *psyOut, + QC_STATE *qcKernel, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig); + +INT FDKaacEnc_writeExtensionData(HANDLE_TRANSPORTENC hTpEnc, + QC_OUT_EXTENSION *pExtension, + INT elInstanceTag, UINT alignAnchor, + UINT syntaxFlags, AUDIO_OBJECT_TYPE aot, + SCHAR epConfig); + +#endif /* BITENC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/block_switch.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/block_switch.cpp new file mode 100644 index 0000000000000..c132253fbd574 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/block_switch.cpp @@ -0,0 +1,582 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner, Tobias Chalupka + + Description: Block switching + +*******************************************************************************/ + +/****************** Includes *****************************/ + +#include "block_switch.h" +#include "genericStds.h" + +#define LOWOV_WINDOW _LOWOV_WINDOW + +/**************** internal function prototypes ***********/ + +static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], + const INT blSwWndIdx); + +static void FDKaacEnc_CalcWindowEnergy( + BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen, + const INT_PCM *pTimeSignal); + +/****************** Constants *****************************/ +/* LONG START + * SHORT STOP LOWOV */ +static const INT blockType2windowShape[2][5] = { + {SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW, SINE_WINDOW, KBD_WINDOW}, /* LD */ + {KBD_WINDOW, SINE_WINDOW, SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW}}; /* LC */ + +/* IIR high pass coeffs */ + +#ifndef SINETABLE_16BIT + +static const FIXP_DBL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = { + FL2FXCONST_DBL(-0.5095), FL2FXCONST_DBL(0.7548)}; + +static const FIXP_DBL accWindowNrgFac = + FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */ +static const FIXP_DBL oneMinusAccWindowNrgFac = FL2FXCONST_DBL(0.7f); +/* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */ +static const FIXP_DBL invAttackRatio = + FL2FXCONST_DBL(0.1f); /* inverted lower ratio limit for attacks */ + +/* The next constants are scaled, because they are used for comparison with + * scaled values*/ +/* minimum energy for attacks */ +static const FIXP_DBL minAttackNrg = + (FL2FXCONST_DBL(1e+6f * NORM_PCM_ENERGY) >> + BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */ + +#else + +static const FIXP_SGL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = { + FL2FXCONST_SGL(-0.5095), FL2FXCONST_SGL(0.7548)}; + +static const FIXP_DBL accWindowNrgFac = + FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */ +static const FIXP_SGL oneMinusAccWindowNrgFac = FL2FXCONST_SGL(0.7f); +/* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */ +static const FIXP_SGL invAttackRatio = + FL2FXCONST_SGL(0.1f); /* inverted lower ratio limit for attacks */ +/* minimum energy for attacks */ +static const FIXP_DBL minAttackNrg = + (FL2FXCONST_DBL(1e+6f * NORM_PCM_ENERGY) >> + BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */ + +#endif + +/**************** internal function prototypes ***********/ + +/****************** Routines ****************************/ +void FDKaacEnc_InitBlockSwitching( + BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay) { + FDKmemclear(blockSwitchingControl, sizeof(BLOCK_SWITCHING_CONTROL)); + + if (isLowDelay) { + blockSwitchingControl->nBlockSwitchWindows = 4; + blockSwitchingControl->allowShortFrames = 0; + blockSwitchingControl->allowLookAhead = 0; + } else { + blockSwitchingControl->nBlockSwitchWindows = 8; + blockSwitchingControl->allowShortFrames = 1; + blockSwitchingControl->allowLookAhead = 1; + } + + blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS; + + /* Initialize startvalue for blocktype */ + blockSwitchingControl->lastWindowSequence = LONG_WINDOW; + blockSwitchingControl->windowShape = + blockType2windowShape[blockSwitchingControl->allowShortFrames] + [blockSwitchingControl->lastWindowSequence]; +} + +static const INT suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = { + /* Attack in Window 0 */ {1, 3, 3, 1}, + /* Attack in Window 1 */ {1, 1, 3, 3}, + /* Attack in Window 2 */ {2, 1, 3, 2}, + /* Attack in Window 3 */ {3, 1, 3, 1}, + /* Attack in Window 4 */ {3, 1, 1, 3}, + /* Attack in Window 5 */ {3, 2, 1, 2}, + /* Attack in Window 6 */ {3, 3, 1, 1}, + /* Attack in Window 7 */ {3, 3, 1, 1}}; + +/* change block type depending on current blocktype and whether there's an + * attack */ +/* assume no look-ahead */ +static const INT chgWndSq[2][N_BLOCKTYPES] = { + /* LONG WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW, + LOWOV_WINDOW, WRONG_WINDOW */ + /*no attack*/ {LONG_WINDOW, STOP_WINDOW, WRONG_WINDOW, LONG_WINDOW, + STOP_WINDOW, WRONG_WINDOW}, + /*attack */ {START_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, START_WINDOW, + LOWOV_WINDOW, WRONG_WINDOW}}; + +/* change block type depending on current blocktype and whether there's an + * attack */ +/* assume look-ahead */ +static const INT chgWndSqLkAhd[2][2][N_BLOCKTYPES] = { + /*attack LONG WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW LOWOV_WINDOW, WRONG_WINDOW */ /* last attack */ + /*no attack*/ { + {LONG_WINDOW, SHORT_WINDOW, STOP_WINDOW, LONG_WINDOW, WRONG_WINDOW, + WRONG_WINDOW}, /* no attack */ + /*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, START_WINDOW, + WRONG_WINDOW, WRONG_WINDOW}}, /* no attack */ + /*no attack*/ {{LONG_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LONG_WINDOW, + WRONG_WINDOW, WRONG_WINDOW}, /* attack */ + /*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, + START_WINDOW, WRONG_WINDOW, + WRONG_WINDOW}} /* attack */ +}; + +int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, + const INT granuleLength, const int isLFE, + const INT_PCM *pTimeSignal) { + UINT i; + FIXP_DBL enM1, enMax; + + UINT nBlockSwitchWindows = blockSwitchingControl->nBlockSwitchWindows; + + /* for LFE : only LONG window allowed */ + if (isLFE) { + /* case LFE: */ + /* only long blocks, always use sine windows (MPEG2 AAC, MPEG4 AAC) */ + blockSwitchingControl->lastWindowSequence = LONG_WINDOW; + blockSwitchingControl->windowShape = SINE_WINDOW; + blockSwitchingControl->noOfGroups = 1; + blockSwitchingControl->groupLen[0] = 1; + + return (0); + }; + + /* Save current attack index as last attack index */ + blockSwitchingControl->lastattack = blockSwitchingControl->attack; + blockSwitchingControl->lastAttackIndex = blockSwitchingControl->attackIndex; + + /* Save current window energy as last window energy */ + FDKmemcpy(blockSwitchingControl->windowNrg[0], + blockSwitchingControl->windowNrg[1], + sizeof(blockSwitchingControl->windowNrg[0])); + FDKmemcpy(blockSwitchingControl->windowNrgF[0], + blockSwitchingControl->windowNrgF[1], + sizeof(blockSwitchingControl->windowNrgF[0])); + + if (blockSwitchingControl->allowShortFrames) { + /* Calculate suggested grouping info for the last frame */ + + /* Reset grouping info */ + FDKmemclear(blockSwitchingControl->groupLen, + sizeof(blockSwitchingControl->groupLen)); + + /* Set grouping info */ + blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS; + + FDKmemcpy(blockSwitchingControl->groupLen, + suggestedGroupingTable[blockSwitchingControl->lastAttackIndex], + sizeof(blockSwitchingControl->groupLen)); + + if (blockSwitchingControl->attack == TRUE) + blockSwitchingControl->maxWindowNrg = + FDKaacEnc_GetWindowEnergy(blockSwitchingControl->windowNrg[0], + blockSwitchingControl->lastAttackIndex); + else + blockSwitchingControl->maxWindowNrg = FL2FXCONST_DBL(0.0); + } + + /* Calculate unfiltered and filtered energies in subwindows and combine to + * segments */ + FDKaacEnc_CalcWindowEnergy( + blockSwitchingControl, + granuleLength >> (nBlockSwitchWindows == 4 ? 2 : 3), pTimeSignal); + + /* now calculate if there is an attack */ + + /* reset attack */ + blockSwitchingControl->attack = FALSE; + + /* look for attack */ + enMax = FL2FXCONST_DBL(0.0f); + enM1 = blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows - 1]; + + for (i = 0; i < nBlockSwitchWindows; i++) { + FIXP_DBL tmp = + fMultDiv2(oneMinusAccWindowNrgFac, blockSwitchingControl->accWindowNrg); + blockSwitchingControl->accWindowNrg = fMultAdd(tmp, accWindowNrgFac, enM1); + + if (fMult(blockSwitchingControl->windowNrgF[1][i], invAttackRatio) > + blockSwitchingControl->accWindowNrg) { + blockSwitchingControl->attack = TRUE; + blockSwitchingControl->attackIndex = i; + } + enM1 = blockSwitchingControl->windowNrgF[1][i]; + enMax = fixMax(enMax, enM1); + } + + if (enMax < minAttackNrg) blockSwitchingControl->attack = FALSE; + + /* Check if attack spreads over frame border */ + if ((blockSwitchingControl->attack == FALSE) && + (blockSwitchingControl->lastattack == TRUE)) { + /* if attack is in last window repeat SHORT_WINDOW */ + if (((blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows - 1] >> 4) > + fMult((FIXP_DBL)(10 << (DFRACT_BITS - 1 - 4)), + blockSwitchingControl->windowNrgF[1][1])) && + (blockSwitchingControl->lastAttackIndex == + (INT)nBlockSwitchWindows - 1)) { + blockSwitchingControl->attack = TRUE; + blockSwitchingControl->attackIndex = 0; + } + } + + if (blockSwitchingControl->allowLookAhead) { + blockSwitchingControl->lastWindowSequence = + chgWndSqLkAhd[blockSwitchingControl->lastattack] + [blockSwitchingControl->attack] + [blockSwitchingControl->lastWindowSequence]; + } else { + /* Low Delay */ + blockSwitchingControl->lastWindowSequence = + chgWndSq[blockSwitchingControl->attack] + [blockSwitchingControl->lastWindowSequence]; + } + + /* update window shape */ + blockSwitchingControl->windowShape = + blockType2windowShape[blockSwitchingControl->allowShortFrames] + [blockSwitchingControl->lastWindowSequence]; + + return (0); +} + +static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], + const INT blSwWndIdx) { + /* For coherency, change FDKaacEnc_GetWindowEnergy() to calcluate the energy + for a block switching analysis windows, not for a short block. The same is + done FDKaacEnc_CalcWindowEnergy(). The result of + FDKaacEnc_GetWindowEnergy() is used for a comparision of the max energy of + left/right channel. */ + + return in[blSwWndIdx]; +} + +static void FDKaacEnc_CalcWindowEnergy( + BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen, + const INT_PCM *pTimeSignal) { + INT i; + UINT w; + +#ifndef SINETABLE_16BIT + const FIXP_DBL hiPassCoeff0 = hiPassCoeff[0]; + const FIXP_DBL hiPassCoeff1 = hiPassCoeff[1]; +#else + const FIXP_SGL hiPassCoeff0 = hiPassCoeff[0]; + const FIXP_SGL hiPassCoeff1 = hiPassCoeff[1]; +#endif + + FIXP_DBL temp_iirState0 = blockSwitchingControl->iirStates[0]; + FIXP_DBL temp_iirState1 = blockSwitchingControl->iirStates[1]; + + /* sum up scalarproduct of timesignal as windowed Energies */ + for (w = 0; w < blockSwitchingControl->nBlockSwitchWindows; w++) { + ULONG temp_windowNrg = 0x0; + ULONG temp_windowNrgF = 0x0; + + /* windowNrg = sum(timesample^2) */ + for (i = 0; i < windowLen; i++) { + FIXP_DBL tempUnfiltered, t1, t2; + /* tempUnfiltered is scaled with 1 to prevent overflows during calculation + * of tempFiltred */ +#if SAMPLE_BITS == DFRACT_BITS + tempUnfiltered = (FIXP_DBL)*pTimeSignal++ >> 1; +#else + tempUnfiltered = (FIXP_DBL)*pTimeSignal++ + << (DFRACT_BITS - SAMPLE_BITS - 1); +#endif + t1 = fMultDiv2(hiPassCoeff1, tempUnfiltered - temp_iirState0); + t2 = fMultDiv2(hiPassCoeff0, temp_iirState1); + temp_iirState0 = tempUnfiltered; + temp_iirState1 = (t1 - t2) << 1; + + temp_windowNrg += (LONG)fPow2Div2(temp_iirState0) >> + (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2); + temp_windowNrgF += (LONG)fPow2Div2(temp_iirState1) >> + (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2); + } + blockSwitchingControl->windowNrg[1][w] = + (LONG)fMin(temp_windowNrg, (UINT)MAXVAL_DBL); + blockSwitchingControl->windowNrgF[1][w] = + (LONG)fMin(temp_windowNrgF, (UINT)MAXVAL_DBL); + } + blockSwitchingControl->iirStates[0] = temp_iirState0; + blockSwitchingControl->iirStates[1] = temp_iirState1; +} + +static const UCHAR synchronizedBlockTypeTable[5][5] = { + /* LONG_WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW + LOWOV_WINDOW*/ + /* LONG_WINDOW */ {LONG_WINDOW, START_WINDOW, SHORT_WINDOW, STOP_WINDOW, + LOWOV_WINDOW}, + /* START_WINDOW */ + {START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LOWOV_WINDOW}, + /* SHORT_WINDOW */ + {SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, WRONG_WINDOW}, + /* STOP_WINDOW */ + {STOP_WINDOW, SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW, LOWOV_WINDOW}, + /* LOWOV_WINDOW */ + {LOWOV_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, LOWOV_WINDOW, LOWOV_WINDOW}, +}; + +int FDKaacEnc_SyncBlockSwitching( + BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, + BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight, const INT nChannels, + const INT commonWindow) { + UCHAR patchType = LONG_WINDOW; + + if (nChannels == 2 && commonWindow == TRUE) { + /* could be better with a channel loop (need a handle to psy_data) */ + /* get suggested Block Types and synchronize */ + patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft + ->lastWindowSequence]; + patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight + ->lastWindowSequence]; + + /* sanity check (no change from low overlap window to short winow and vice + * versa) */ + if (patchType == WRONG_WINDOW) return -1; /* mixed up AAC-LC and AAC-LD */ + + /* Set synchronized Blocktype */ + blockSwitchingControlLeft->lastWindowSequence = patchType; + blockSwitchingControlRight->lastWindowSequence = patchType; + + /* update window shape */ + blockSwitchingControlLeft->windowShape = + blockType2windowShape[blockSwitchingControlLeft->allowShortFrames] + [blockSwitchingControlLeft->lastWindowSequence]; + blockSwitchingControlRight->windowShape = + blockType2windowShape[blockSwitchingControlLeft->allowShortFrames] + [blockSwitchingControlRight->lastWindowSequence]; + } + + if (blockSwitchingControlLeft->allowShortFrames) { + int i; + + if (nChannels == 2) { + if (commonWindow == TRUE) { + /* Synchronize grouping info */ + int windowSequenceLeftOld = + blockSwitchingControlLeft->lastWindowSequence; + int windowSequenceRightOld = + blockSwitchingControlRight->lastWindowSequence; + + /* Long Blocks */ + if (patchType != SHORT_WINDOW) { + /* Set grouping info */ + blockSwitchingControlLeft->noOfGroups = 1; + blockSwitchingControlRight->noOfGroups = 1; + blockSwitchingControlLeft->groupLen[0] = 1; + blockSwitchingControlRight->groupLen[0] = 1; + + for (i = 1; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = 0; + blockSwitchingControlRight->groupLen[i] = 0; + } + } + + /* Short Blocks */ + else { + /* in case all two channels were detected as short-blocks before + * syncing, use the grouping of channel with higher maxWindowNrg */ + if ((windowSequenceLeftOld == SHORT_WINDOW) && + (windowSequenceRightOld == SHORT_WINDOW)) { + if (blockSwitchingControlLeft->maxWindowNrg > + blockSwitchingControlRight->maxWindowNrg) { + /* Left Channel wins */ + blockSwitchingControlRight->noOfGroups = + blockSwitchingControlLeft->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlRight->groupLen[i] = + blockSwitchingControlLeft->groupLen[i]; + } + } else { + /* Right Channel wins */ + blockSwitchingControlLeft->noOfGroups = + blockSwitchingControlRight->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = + blockSwitchingControlRight->groupLen[i]; + } + } + } else if ((windowSequenceLeftOld == SHORT_WINDOW) && + (windowSequenceRightOld != SHORT_WINDOW)) { + /* else use grouping of short-block channel */ + blockSwitchingControlRight->noOfGroups = + blockSwitchingControlLeft->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlRight->groupLen[i] = + blockSwitchingControlLeft->groupLen[i]; + } + } else if ((windowSequenceRightOld == SHORT_WINDOW) && + (windowSequenceLeftOld != SHORT_WINDOW)) { + blockSwitchingControlLeft->noOfGroups = + blockSwitchingControlRight->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = + blockSwitchingControlRight->groupLen[i]; + } + } else { + /* syncing a start and stop window ... */ + blockSwitchingControlLeft->noOfGroups = + blockSwitchingControlRight->noOfGroups = 2; + blockSwitchingControlLeft->groupLen[0] = + blockSwitchingControlRight->groupLen[0] = 4; + blockSwitchingControlLeft->groupLen[1] = + blockSwitchingControlRight->groupLen[1] = 4; + } + } /* Short Blocks */ + } else { + /* stereo, no common window */ + if (blockSwitchingControlLeft->lastWindowSequence != SHORT_WINDOW) { + blockSwitchingControlLeft->noOfGroups = 1; + blockSwitchingControlLeft->groupLen[0] = 1; + for (i = 1; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = 0; + } + } + if (blockSwitchingControlRight->lastWindowSequence != SHORT_WINDOW) { + blockSwitchingControlRight->noOfGroups = 1; + blockSwitchingControlRight->groupLen[0] = 1; + for (i = 1; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlRight->groupLen[i] = 0; + } + } + } /* common window */ + } else { + /* Mono */ + if (blockSwitchingControlLeft->lastWindowSequence != SHORT_WINDOW) { + blockSwitchingControlLeft->noOfGroups = 1; + blockSwitchingControlLeft->groupLen[0] = 1; + + for (i = 1; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = 0; + } + } + } + } /* allowShortFrames */ + + /* Translate LOWOV_WINDOW block type to a meaningful window shape. */ + if (!blockSwitchingControlLeft->allowShortFrames) { + if (blockSwitchingControlLeft->lastWindowSequence != LONG_WINDOW && + blockSwitchingControlLeft->lastWindowSequence != STOP_WINDOW) { + blockSwitchingControlLeft->lastWindowSequence = LONG_WINDOW; + blockSwitchingControlLeft->windowShape = LOL_WINDOW; + } + } + if (nChannels == 2) { + if (!blockSwitchingControlRight->allowShortFrames) { + if (blockSwitchingControlRight->lastWindowSequence != LONG_WINDOW && + blockSwitchingControlRight->lastWindowSequence != STOP_WINDOW) { + blockSwitchingControlRight->lastWindowSequence = LONG_WINDOW; + blockSwitchingControlRight->windowShape = LOL_WINDOW; + } + } + } + + return 0; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/block_switch.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/block_switch.h new file mode 100644 index 0000000000000..ff20f8473c8ce --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/block_switch.h @@ -0,0 +1,162 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Block switching + +*******************************************************************************/ + +#ifndef BLOCK_SWITCH_H +#define BLOCK_SWITCH_H + +#include "common_fix.h" + +#include "psy_const.h" + +/****************** Defines ******************************/ +#define BLOCK_SWITCH_WINDOWS 8 /* number of windows for energy calculation */ + +#define BLOCK_SWITCHING_IIR_LEN \ + 2 /* Length of HighPass-IIR-Filter for Attack-Detection */ +#define BLOCK_SWITCH_ENERGY_SHIFT \ + 7 /* should be logDualis(BLOCK_SWITCH_WINDOW_LEN) to avoid overflow in \ + windowNrgs. */ + +#define LAST_WINDOW 0 +#define THIS_WINDOW 1 + +/****************** Structures ***************************/ +typedef struct { + INT lastWindowSequence; + INT windowShape; + INT lastWindowShape; + UINT nBlockSwitchWindows; /* number of windows for energy calculation */ + INT attack; + INT lastattack; + INT attackIndex; + INT lastAttackIndex; + INT allowShortFrames; /* for Low Delay, don't allow short frames */ + INT allowLookAhead; /* for Low Delay, don't do look-ahead */ + INT noOfGroups; + INT groupLen[MAX_NO_OF_GROUPS]; + FIXP_DBL maxWindowNrg; /* max energy in subwindows */ + + FIXP_DBL + windowNrg[2][BLOCK_SWITCH_WINDOWS]; /* time signal energy in Subwindows + (last and current) */ + FIXP_DBL windowNrgF[2][BLOCK_SWITCH_WINDOWS]; /* filtered time signal energy + in segments (last and + current) */ + FIXP_DBL accWindowNrg; /* recursively accumulated windowNrgF */ + + FIXP_DBL iirStates[BLOCK_SWITCHING_IIR_LEN]; /* filter delay-line */ + +} BLOCK_SWITCHING_CONTROL; + +void FDKaacEnc_InitBlockSwitching( + BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay); + +int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, + const INT granuleLength, const int isLFE, + const INT_PCM *pTimeSignal); + +int FDKaacEnc_SyncBlockSwitching( + BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, + BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight, const INT noOfChannels, + const INT commonWindow); + +#endif /* #ifndef BLOCK_SWITCH_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/channel_map.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/channel_map.cpp new file mode 100644 index 0000000000000..6ee91d56912d3 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/channel_map.cpp @@ -0,0 +1,664 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): A. Groeschel + + Description: channel mapping functionality + +*******************************************************************************/ + +#include "channel_map.h" +#include "bitenc.h" +#include "psy_const.h" +#include "qc_data.h" +#include "aacEnc_ram.h" +#include "FDK_tools_rom.h" + +/* channel_assignment treats the relationship of Input file channels + to the encoder channels. + This is necessary because the usual order in RIFF files (.wav) + is different from the elements order in the coder given + by Table 8.1 (implicit speaker mapping) of the AAC standard. + + In mono and stereo case, this is trivial. + In mc case, it looks like this: + + Channel Input file coder chan +5ch: + front center 2 0 (SCE channel) + left center 0 1 (1st of 1st CPE) + right center 1 2 (2nd of 1st CPE) + left surround 3 3 (1st of 2nd CPE) + right surround 4 4 (2nd of 2nd CPE) + +5.1ch: + front center 2 0 (SCE channel) + left center 0 1 (1st of 1st CPE) + right center 1 2 (2nd of 1st CPE) + left surround 4 3 (1st of 2nd CPE) + right surround 5 4 (2nd of 2nd CPE) + LFE 3 5 (LFE) +*/ + +/* Channel mode configuration tab provides, + corresponding number of channels and elements +*/ +static const CHANNEL_MODE_CONFIG_TAB channelModeConfig[] = { + {MODE_1, 1, 1, 1}, /* chCfg 1, SCE */ + {MODE_2, 2, 2, 1}, /* chCfg 2, CPE */ + {MODE_1_2, 3, 3, 2}, /* chCfg 3, SCE,CPE */ + {MODE_1_2_1, 4, 4, 3}, /* chCfg 4, SCE,CPE,SCE */ + {MODE_1_2_2, 5, 5, 3}, /* chCfg 5, SCE,CPE,CPE */ + {MODE_1_2_2_1, 6, 5, 4}, /* chCfg 6, SCE,CPE,CPE,LFE */ + {MODE_1_2_2_2_1, 8, 7, 5}, /* chCfg 7, SCE,CPE,CPE,CPE,LFE */ + {MODE_6_1, 7, 6, 5}, /* chCfg 11, SCE,CPE,CPE,SCE,LFE */ + {MODE_7_1_BACK, 8, 7, 5}, /* chCfg 12, SCE,CPE,CPE,CPE,LFE */ + {MODE_7_1_TOP_FRONT, 8, 7, 5}, /* chCfg 14, SCE,CPE,CPE,LFE,CPE */ + {MODE_7_1_REAR_SURROUND, 8, 7, + 5}, /* same as MODE_7_1_BACK, SCE,CPE,CPE,CPE,LFE */ + {MODE_7_1_FRONT_CENTER, 8, 7, + 5}, /* same as MODE_1_2_2_2_1, SCE,CPE,CPE,CPE,LFE */ + +}; + +AAC_ENCODER_ERROR FDKaacEnc_DetermineEncoderMode(CHANNEL_MODE* mode, + INT nChannels) { + INT i; + CHANNEL_MODE encMode = MODE_INVALID; + + if (*mode == MODE_UNKNOWN) { + for (i = 0; i < (INT)sizeof(channelModeConfig) / + (INT)sizeof(CHANNEL_MODE_CONFIG_TAB); + i++) { + if (channelModeConfig[i].nChannels == nChannels) { + encMode = channelModeConfig[i].encMode; + break; + } + } + *mode = encMode; + } else { + /* check if valid channel configuration */ + if (FDKaacEnc_GetChannelModeConfiguration(*mode)->nChannels == nChannels) { + encMode = *mode; + } + } + + if (encMode == MODE_INVALID) { + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + + return AAC_ENC_OK; +} + +static INT FDKaacEnc_initElement(ELEMENT_INFO* elInfo, MP4_ELEMENT_ID elType, + INT* cnt, FDK_channelMapDescr* mapDescr, + UINT mapIdx, INT* it_cnt, + const FIXP_DBL relBits) { + INT error = 0; + INT counter = *cnt; + + elInfo->elType = elType; + elInfo->relativeBits = relBits; + + switch (elInfo->elType) { + case ID_SCE: + case ID_LFE: + case ID_CCE: + elInfo->nChannelsInEl = 1; + elInfo->ChannelIndex[0] = + FDK_chMapDescr_getMapValue(mapDescr, counter++, mapIdx); + elInfo->instanceTag = it_cnt[elType]++; + break; + case ID_CPE: + elInfo->nChannelsInEl = 2; + elInfo->ChannelIndex[0] = + FDK_chMapDescr_getMapValue(mapDescr, counter++, mapIdx); + elInfo->ChannelIndex[1] = + FDK_chMapDescr_getMapValue(mapDescr, counter++, mapIdx); + elInfo->instanceTag = it_cnt[elType]++; + break; + case ID_DSE: + elInfo->nChannelsInEl = 0; + elInfo->ChannelIndex[0] = 0; + elInfo->ChannelIndex[1] = 0; + elInfo->instanceTag = it_cnt[elType]++; + break; + default: + error = 1; + }; + *cnt = counter; + return error; +} + +AAC_ENCODER_ERROR FDKaacEnc_InitChannelMapping(CHANNEL_MODE mode, + CHANNEL_ORDER co, + CHANNEL_MAPPING* cm) { + INT count = 0; /* count through coder channels */ + INT it_cnt[ID_END + 1]; + INT i; + UINT mapIdx; + FDK_channelMapDescr mapDescr; + + for (i = 0; i < ID_END; i++) it_cnt[i] = 0; + + FDKmemclear(cm, sizeof(CHANNEL_MAPPING)); + + /* init channel mapping*/ + for (i = 0; i < (INT)sizeof(channelModeConfig) / + (INT)sizeof(CHANNEL_MODE_CONFIG_TAB); + i++) { + if (channelModeConfig[i].encMode == mode) { + cm->encMode = channelModeConfig[i].encMode; + cm->nChannels = channelModeConfig[i].nChannels; + cm->nChannelsEff = channelModeConfig[i].nChannelsEff; + cm->nElements = channelModeConfig[i].nElements; + + break; + } + } + + /* init map descriptor */ + FDK_chMapDescr_init(&mapDescr, NULL, 0, (co == CH_ORDER_MPEG) ? 1 : 0); + switch (mode) { + case MODE_7_1_REAR_SURROUND: /* MODE_7_1_REAR_SURROUND is equivalent to + MODE_7_1_BACK */ + mapIdx = (INT)MODE_7_1_BACK; + break; + case MODE_7_1_FRONT_CENTER: /* MODE_7_1_FRONT_CENTER is equivalent to + MODE_1_2_2_2_1 */ + mapIdx = (INT)MODE_1_2_2_2_1; + break; + default: + mapIdx = + (INT)mode > 14 + ? 0 + : (INT) + mode; /* if channel config > 14 MPEG mapping will be used */ + } + + /* init element info struct */ + switch (mode) { + case MODE_1: + /* (mono) sce */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, (FIXP_DBL)MAXVAL_DBL); + break; + case MODE_2: + /* (stereo) cpe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, (FIXP_DBL)MAXVAL_DBL); + break; + + case MODE_1_2: + /* sce + cpe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.4f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.6f)); + break; + + case MODE_1_2_1: + /* sce + cpe + sce */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.3f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.4f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.3f)); + break; + + case MODE_1_2_2: + /* sce + cpe + cpe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.26f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.37f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.37f)); + break; + + case MODE_1_2_2_1: + /* (5.1) sce + cpe + cpe + lfe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.24f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.35f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.35f)); + FDKaacEnc_initElement(&cm->elInfo[3], ID_LFE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.06f)); + break; + + case MODE_6_1: + /* (6.1) sce + cpe + cpe + sce + lfe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.2f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.275f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.275f)); + FDKaacEnc_initElement(&cm->elInfo[3], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.2f)); + FDKaacEnc_initElement(&cm->elInfo[4], ID_LFE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.05f)); + break; + + case MODE_1_2_2_2_1: + case MODE_7_1_BACK: + case MODE_7_1_TOP_FRONT: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: { + /* (7.1) sce + cpe + cpe + cpe + lfe */ + /* (7.1 top) sce + cpe + cpe + lfe + cpe */ + + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.18f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.26f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.26f)); + if (mode != MODE_7_1_TOP_FRONT) { + FDKaacEnc_initElement(&cm->elInfo[3], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.26f)); + FDKaacEnc_initElement(&cm->elInfo[4], ID_LFE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.04f)); + } else { + FDKaacEnc_initElement(&cm->elInfo[3], ID_LFE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.04f)); + FDKaacEnc_initElement(&cm->elInfo[4], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.26f)); + } + break; + } + + default: + //*chMap=0; + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + }; + + FDK_ASSERT(cm->nElements <= ((8))); + + return AAC_ENC_OK; +} + +AAC_ENCODER_ERROR FDKaacEnc_InitElementBits(QC_STATE* hQC, CHANNEL_MAPPING* cm, + INT bitrateTot, INT averageBitsTot, + INT maxChannelBits) { + int sc_brTot = CountLeadingBits(bitrateTot); + + switch (cm->encMode) { + case MODE_1: + hQC->elementBits[0]->chBitrateEl = bitrateTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + break; + + case MODE_2: + hQC->elementBits[0]->chBitrateEl = bitrateTot >> 1; + + hQC->elementBits[0]->maxBitsEl = 2 * maxChannelBits; + + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + break; + case MODE_1_2: { + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + FIXP_DBL sceRate = cm->elInfo[0].relativeBits; + FIXP_DBL cpeRate = cm->elInfo[1].relativeBits; + + hQC->elementBits[0]->chBitrateEl = + fMult(sceRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + hQC->elementBits[1]->chBitrateEl = + fMult(cpeRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2 * maxChannelBits; + break; + } + case MODE_1_2_1: { + /* sce + cpe + sce */ + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits; + FIXP_DBL sce1Rate = cm->elInfo[0].relativeBits; + FIXP_DBL cpeRate = cm->elInfo[1].relativeBits; + FIXP_DBL sce2Rate = cm->elInfo[2].relativeBits; + + hQC->elementBits[0]->chBitrateEl = + fMult(sce1Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + hQC->elementBits[1]->chBitrateEl = + fMult(cpeRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[2]->chBitrateEl = + fMult(sce2Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[2]->maxBitsEl = maxChannelBits; + break; + } + case MODE_1_2_2: { + /* sce + cpe + cpe */ + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits; + FIXP_DBL sceRate = cm->elInfo[0].relativeBits; + FIXP_DBL cpe1Rate = cm->elInfo[1].relativeBits; + FIXP_DBL cpe2Rate = cm->elInfo[2].relativeBits; + + hQC->elementBits[0]->chBitrateEl = + fMult(sceRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + hQC->elementBits[1]->chBitrateEl = + fMult(cpe1Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[2]->chBitrateEl = + fMult(cpe2Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[2]->maxBitsEl = 2 * maxChannelBits; + break; + } + case MODE_1_2_2_1: { + /* (5.1) sce + cpe + cpe + lfe */ + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits; + hQC->elementBits[3]->relativeBitsEl = cm->elInfo[3].relativeBits; + FIXP_DBL sceRate = cm->elInfo[0].relativeBits; + FIXP_DBL cpe1Rate = cm->elInfo[1].relativeBits; + FIXP_DBL cpe2Rate = cm->elInfo[2].relativeBits; + FIXP_DBL lfeRate = cm->elInfo[3].relativeBits; + + int maxBitsTot = + maxChannelBits * 5; /* LFE does not add to bit reservoir */ + int sc = CountLeadingBits(fixMax(maxChannelBits, averageBitsTot)); + int maxLfeBits = (int)fMax( + (INT)((fMult(lfeRate, (FIXP_DBL)(maxChannelBits << sc)) >> sc) << 1), + (INT)((fMult(FL2FXCONST_DBL(1.1f / 2.f), + fMult(lfeRate, (FIXP_DBL)(averageBitsTot << sc))) + << 1) >> + sc)); + + maxChannelBits = (maxBitsTot - maxLfeBits); + sc = CountLeadingBits(maxChannelBits); + + maxChannelBits = + fMult((FIXP_DBL)maxChannelBits << sc, GetInvInt(5)) >> sc; + + hQC->elementBits[0]->chBitrateEl = + fMult(sceRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + hQC->elementBits[1]->chBitrateEl = + fMult(cpe1Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[2]->chBitrateEl = + fMult(cpe2Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[3]->chBitrateEl = + fMult(lfeRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[2]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[3]->maxBitsEl = maxLfeBits; + + break; + } + case MODE_6_1: { + /* (6.1) sce + cpe + cpe + sce + lfe */ + FIXP_DBL sceRate = hQC->elementBits[0]->relativeBitsEl = + cm->elInfo[0].relativeBits; + FIXP_DBL cpe1Rate = hQC->elementBits[1]->relativeBitsEl = + cm->elInfo[1].relativeBits; + FIXP_DBL cpe2Rate = hQC->elementBits[2]->relativeBitsEl = + cm->elInfo[2].relativeBits; + FIXP_DBL sce2Rate = hQC->elementBits[3]->relativeBitsEl = + cm->elInfo[3].relativeBits; + FIXP_DBL lfeRate = hQC->elementBits[4]->relativeBitsEl = + cm->elInfo[4].relativeBits; + + int maxBitsTot = + maxChannelBits * 6; /* LFE does not add to bit reservoir */ + int sc = CountLeadingBits(fixMax(maxChannelBits, averageBitsTot)); + int maxLfeBits = (int)fMax( + (INT)((fMult(lfeRate, (FIXP_DBL)(maxChannelBits << sc)) >> sc) << 1), + (INT)((fMult(FL2FXCONST_DBL(1.1f / 2.f), + fMult(lfeRate, (FIXP_DBL)(averageBitsTot << sc))) + << 1) >> + sc)); + + maxChannelBits = (maxBitsTot - maxLfeBits) / 6; + + hQC->elementBits[0]->chBitrateEl = + fMult(sceRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + hQC->elementBits[1]->chBitrateEl = + fMult(cpe1Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[2]->chBitrateEl = + fMult(cpe2Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[3]->chBitrateEl = + fMult(sce2Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[4]->chBitrateEl = + fMult(lfeRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[2]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[3]->maxBitsEl = maxChannelBits; + hQC->elementBits[4]->maxBitsEl = maxLfeBits; + break; + } + case MODE_7_1_TOP_FRONT: + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + case MODE_1_2_2_2_1: { + int cpe3Idx = (cm->encMode != MODE_7_1_TOP_FRONT) ? 3 : 4; + int lfeIdx = (cm->encMode != MODE_7_1_TOP_FRONT) ? 4 : 3; + + /* (7.1) sce + cpe + cpe + cpe + lfe */ + FIXP_DBL sceRate = hQC->elementBits[0]->relativeBitsEl = + cm->elInfo[0].relativeBits; + FIXP_DBL cpe1Rate = hQC->elementBits[1]->relativeBitsEl = + cm->elInfo[1].relativeBits; + FIXP_DBL cpe2Rate = hQC->elementBits[2]->relativeBitsEl = + cm->elInfo[2].relativeBits; + FIXP_DBL cpe3Rate = hQC->elementBits[cpe3Idx]->relativeBitsEl = + cm->elInfo[cpe3Idx].relativeBits; + FIXP_DBL lfeRate = hQC->elementBits[lfeIdx]->relativeBitsEl = + cm->elInfo[lfeIdx].relativeBits; + + int maxBitsTot = + maxChannelBits * 7; /* LFE does not add to bit reservoir */ + int sc = CountLeadingBits(fixMax(maxChannelBits, averageBitsTot)); + int maxLfeBits = (int)fMax( + (INT)((fMult(lfeRate, (FIXP_DBL)(maxChannelBits << sc)) >> sc) << 1), + (INT)((fMult(FL2FXCONST_DBL(1.1f / 2.f), + fMult(lfeRate, (FIXP_DBL)(averageBitsTot << sc))) + << 1) >> + sc)); + + maxChannelBits = (maxBitsTot - maxLfeBits) / 7; + + hQC->elementBits[0]->chBitrateEl = + fMult(sceRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + hQC->elementBits[1]->chBitrateEl = + fMult(cpe1Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[2]->chBitrateEl = + fMult(cpe2Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[cpe3Idx]->chBitrateEl = + fMult(cpe3Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[lfeIdx]->chBitrateEl = + fMult(lfeRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[2]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[cpe3Idx]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[lfeIdx]->maxBitsEl = maxLfeBits; + break; + } + + default: + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + + return AAC_ENC_OK; +} + +/********************************************************************************/ +/* */ +/* function: GetMonoStereoMODE(const CHANNEL_MODE mode) */ +/* */ +/* description: Determines encoder setting from channel mode. */ +/* Multichannel modes are mapped to mono or stereo modes */ +/* returns MODE_MONO in case of mono, */ +/* MODE_STEREO in case of stereo */ +/* MODE_INVALID in case of error */ +/* */ +/* input: CHANNEL_MODE mode: Encoder mode (see qc_data.h). */ +/* output: return: CM_STEREO_MODE monoStereoSetting */ +/* (MODE_INVALID: error, */ +/* MODE_MONO: mono */ +/* MODE_STEREO: stereo). */ +/* */ +/* misc: No memory is allocated. */ +/* */ +/********************************************************************************/ + +ELEMENT_MODE FDKaacEnc_GetMonoStereoMode(const CHANNEL_MODE mode) { + ELEMENT_MODE monoStereoSetting = EL_MODE_INVALID; + + switch (mode) { + case MODE_1: /* mono setups */ + monoStereoSetting = EL_MODE_MONO; + break; + + case MODE_2: /* stereo setups */ + case MODE_1_2: + case MODE_1_2_1: + case MODE_1_2_2: + case MODE_1_2_2_1: + case MODE_6_1: + case MODE_1_2_2_2_1: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + case MODE_7_1_BACK: + case MODE_7_1_TOP_FRONT: + monoStereoSetting = EL_MODE_STEREO; + break; + + default: /* error */ + monoStereoSetting = EL_MODE_INVALID; + break; + } + + return monoStereoSetting; +} + +const CHANNEL_MODE_CONFIG_TAB* FDKaacEnc_GetChannelModeConfiguration( + const CHANNEL_MODE mode) { + INT i; + const CHANNEL_MODE_CONFIG_TAB* cm_config = NULL; + + /* get channel mode config */ + for (i = 0; i < (INT)sizeof(channelModeConfig) / + (INT)sizeof(CHANNEL_MODE_CONFIG_TAB); + i++) { + if (channelModeConfig[i].encMode == mode) { + cm_config = &channelModeConfig[i]; + break; + } + } + return cm_config; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/channel_map.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/channel_map.h new file mode 100644 index 0000000000000..f9154cdd44e3b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/channel_map.h @@ -0,0 +1,136 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): A. Groeschel + + Description: channel mapping functionality + +*******************************************************************************/ + +#ifndef CHANNEL_MAP_H +#define CHANNEL_MAP_H + +#include "aacenc.h" +#include "psy_const.h" +#include "qc_data.h" + +typedef struct { + CHANNEL_MODE encMode; + INT nChannels; + INT nChannelsEff; + INT nElements; +} CHANNEL_MODE_CONFIG_TAB; + +/* Element mode */ +typedef enum { EL_MODE_INVALID = 0, EL_MODE_MONO, EL_MODE_STEREO } ELEMENT_MODE; + +AAC_ENCODER_ERROR FDKaacEnc_DetermineEncoderMode(CHANNEL_MODE* mode, + INT nChannels); + +AAC_ENCODER_ERROR FDKaacEnc_InitChannelMapping(CHANNEL_MODE mode, + CHANNEL_ORDER co, + CHANNEL_MAPPING* chMap); + +AAC_ENCODER_ERROR FDKaacEnc_InitElementBits(QC_STATE* hQC, CHANNEL_MAPPING* cm, + INT bitrateTot, INT averageBitsTot, + INT maxChannelBits); + +ELEMENT_MODE FDKaacEnc_GetMonoStereoMode(const CHANNEL_MODE mode); + +const CHANNEL_MODE_CONFIG_TAB* FDKaacEnc_GetChannelModeConfiguration( + const CHANNEL_MODE mode); + +#endif /* CHANNEL_MAP_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/chaosmeasure.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/chaosmeasure.cpp new file mode 100644 index 0000000000000..664284b8403a9 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/chaosmeasure.cpp @@ -0,0 +1,191 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Chaos measure calculation + +*******************************************************************************/ + +#include "chaosmeasure.h" + +/***************************************************************************** + functionname: FDKaacEnc_FDKaacEnc_CalculateChaosMeasurePeakFast + description: Eberlein method of chaos measure calculation by high-pass + filtering amplitude spectrum + A special case of FDKaacEnc_CalculateChaosMeasureTonalGeneric +-- highly optimized +*****************************************************************************/ +static void FDKaacEnc_FDKaacEnc_CalculateChaosMeasurePeakFast( + FIXP_DBL *RESTRICT paMDCTDataNM0, INT numberOfLines, + FIXP_DBL *RESTRICT chaosMeasure) { + INT i, j; + + /* calculate chaos measure by "peak filter" */ + /* make even and odd pass through data */ + FIXP_DBL left_0_div2, + center_0; /* left, center tap of filter, even numbered */ + FIXP_DBL left_1_div2, center_1; /* left, center tap of filter, odd numbered */ + + left_0_div2 = (FIXP_DBL)(((LONG)paMDCTDataNM0[0] ^ + ((LONG)paMDCTDataNM0[0] >> (DFRACT_BITS - 1))) >> + 1); + left_1_div2 = (FIXP_DBL)(((LONG)paMDCTDataNM0[1] ^ + ((LONG)paMDCTDataNM0[1] >> (DFRACT_BITS - 1))) >> + 1); + center_0 = (FIXP_DBL)((LONG)paMDCTDataNM0[2] ^ + ((LONG)paMDCTDataNM0[2] >> (DFRACT_BITS - 1))); + center_1 = (FIXP_DBL)((LONG)paMDCTDataNM0[3] ^ + ((LONG)paMDCTDataNM0[3] >> (DFRACT_BITS - 1))); + + for (j = 2; j < numberOfLines - 2; j += 2) { + FIXP_DBL right_0 = + (FIXP_DBL)((LONG)paMDCTDataNM0[j + 2] ^ + ((LONG)paMDCTDataNM0[j + 2] >> (DFRACT_BITS - 1))); + FIXP_DBL tmp_0 = left_0_div2 + (right_0 >> 1); + FIXP_DBL right_1 = + (FIXP_DBL)((LONG)paMDCTDataNM0[j + 3] ^ + ((LONG)paMDCTDataNM0[j + 3] >> (DFRACT_BITS - 1))); + FIXP_DBL tmp_1 = left_1_div2 + (right_1 >> 1); + + if (tmp_0 < center_0) { + INT leadingBits = CntLeadingZeros(center_0) - 1; + tmp_0 = schur_div(tmp_0 << leadingBits, center_0 << leadingBits, 8); + tmp_0 = fMult(tmp_0, tmp_0); + } else { + tmp_0 = (FIXP_DBL)MAXVAL_DBL; + } + chaosMeasure[j + 0] = tmp_0; + left_0_div2 = center_0 >> 1; + center_0 = right_0; + + if (tmp_1 < center_1) { + INT leadingBits = CntLeadingZeros(center_1) - 1; + tmp_1 = schur_div(tmp_1 << leadingBits, center_1 << leadingBits, 8); + tmp_1 = fMult(tmp_1, tmp_1); + } else { + tmp_1 = (FIXP_DBL)MAXVAL_DBL; + } + + left_1_div2 = center_1 >> 1; + center_1 = right_1; + chaosMeasure[j + 1] = tmp_1; + } + + /* provide chaos measure for first few lines */ + chaosMeasure[0] = chaosMeasure[2]; + chaosMeasure[1] = chaosMeasure[2]; + + /* provide chaos measure for last few lines */ + for (i = (numberOfLines - 3); i < numberOfLines; i++) + chaosMeasure[i] = FL2FXCONST_DBL(0.5); +} + +/***************************************************************************** + functionname: FDKaacEnc_CalculateChaosMeasure + description: calculates a chaosmeasure for every line, different methods + are available. 0 means tonal, 1 means noiselike + returns: + input: MDCT data, number of lines + output: chaosMeasure +*****************************************************************************/ +void FDKaacEnc_CalculateChaosMeasure(FIXP_DBL *paMDCTDataNM0, INT numberOfLines, + FIXP_DBL *chaosMeasure) + +{ + FDKaacEnc_FDKaacEnc_CalculateChaosMeasurePeakFast( + paMDCTDataNM0, numberOfLines, chaosMeasure); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/chaosmeasure.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/chaosmeasure.h new file mode 100644 index 0000000000000..60d413756a4b5 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/chaosmeasure.h @@ -0,0 +1,112 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Chaos measure calculation + +*******************************************************************************/ + +#ifndef CHAOSMEASURE_H +#define CHAOSMEASURE_H + +#include "common_fix.h" +#include "psy_const.h" + +void FDKaacEnc_CalculateChaosMeasure(FIXP_DBL *paMDCTDataNM0, INT numberOfLines, + FIXP_DBL *chaosMeasure); + +#endif /* CHAOSMEASURE_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/dyn_bits.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/dyn_bits.cpp new file mode 100644 index 0000000000000..74baeb88fb34d --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/dyn_bits.cpp @@ -0,0 +1,663 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Noiseless coder module + +*******************************************************************************/ + +#include "dyn_bits.h" +#include "bit_cnt.h" +#include "psy_const.h" +#include "aacenc_pns.h" +#include "aacEnc_ram.h" +#include "aacEnc_rom.h" + +typedef INT (*lookUpTable)[CODE_BOOK_ESC_NDX + 1]; + +static INT FDKaacEnc_getSideInfoBits(const SECTION_INFO* const huffsection, + const SHORT* const sideInfoTab, + const INT useHCR) { + INT sideInfoBits; + + if (useHCR && + ((huffsection->codeBook == 11) || (huffsection->codeBook >= 16))) { + sideInfoBits = 5; + } else { + sideInfoBits = sideInfoTab[huffsection->sfbCnt]; + } + + return (sideInfoBits); +} + +/* count bits using all possible tables */ +static void FDKaacEnc_buildBitLookUp( + const SHORT* const quantSpectrum, const INT maxSfb, + const INT* const sfbOffset, const UINT* const sfbMax, + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + SECTION_INFO* const huffsection) { + INT i, sfbWidth; + + for (i = 0; i < maxSfb; i++) { + huffsection[i].sfbCnt = 1; + huffsection[i].sfbStart = i; + huffsection[i].sectionBits = INVALID_BITCOUNT; + huffsection[i].codeBook = -1; + sfbWidth = sfbOffset[i + 1] - sfbOffset[i]; + FDKaacEnc_bitCount(quantSpectrum + sfbOffset[i], sfbWidth, sfbMax[i], + bitLookUp[i]); + } +} + +/* essential helper functions */ +static inline INT FDKaacEnc_findBestBook(const INT* const bc, INT* const book, + const INT useVCB11) { + INT minBits = INVALID_BITCOUNT, j; + + int end = CODE_BOOK_ESC_NDX; + + for (j = 0; j <= end; j++) { + if (bc[j] < minBits) { + minBits = bc[j]; + *book = j; + } + } + return (minBits); +} + +static inline INT FDKaacEnc_findMinMergeBits(const INT* const bc1, + const INT* const bc2, + const INT useVCB11) { + INT minBits = INVALID_BITCOUNT, j; + + DWORD_ALIGNED(bc1); + DWORD_ALIGNED(bc2); + + for (j = 0; j <= CODE_BOOK_ESC_NDX; j++) { + minBits = fixMin(minBits, bc1[j] + bc2[j]); + } + return (minBits); +} + +static inline void FDKaacEnc_mergeBitLookUp(INT* const RESTRICT bc1, + const INT* const RESTRICT bc2) { + int j; + + for (j = 0; j <= CODE_BOOK_ESC_NDX; j++) { + FDK_ASSERT(INVALID_BITCOUNT == 0x1FFFFFFF); + bc1[j] = fixMin(bc1[j] + bc2[j], INVALID_BITCOUNT); + } +} + +static inline INT FDKaacEnc_findMaxMerge(const INT* const mergeGainLookUp, + const SECTION_INFO* const huffsection, + const INT maxSfb, INT* const maxNdx) { + INT i, maxMergeGain = 0; + int lastMaxNdx = 0; + + for (i = 0; i + huffsection[i].sfbCnt < maxSfb; i += huffsection[i].sfbCnt) { + if (mergeGainLookUp[i] > maxMergeGain) { + maxMergeGain = mergeGainLookUp[i]; + lastMaxNdx = i; + } + } + *maxNdx = lastMaxNdx; + return (maxMergeGain); +} + +static inline INT FDKaacEnc_CalcMergeGain( + const SECTION_INFO* const huffsection, + const INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const SHORT* const sideInfoTab, const INT ndx1, const INT ndx2, + const INT useVCB11) { + INT MergeGain, MergeBits, SplitBits; + + MergeBits = + sideInfoTab[huffsection[ndx1].sfbCnt + huffsection[ndx2].sfbCnt] + + FDKaacEnc_findMinMergeBits(bitLookUp[ndx1], bitLookUp[ndx2], useVCB11); + SplitBits = + huffsection[ndx1].sectionBits + + huffsection[ndx2].sectionBits; /* Bit amount for splitted huffsections */ + MergeGain = SplitBits - MergeBits; + + if ((huffsection[ndx1].codeBook == CODE_BOOK_PNS_NO) || + (huffsection[ndx2].codeBook == CODE_BOOK_PNS_NO) || + (huffsection[ndx1].codeBook == CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (huffsection[ndx2].codeBook == CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (huffsection[ndx1].codeBook == CODE_BOOK_IS_IN_PHASE_NO) || + (huffsection[ndx2].codeBook == CODE_BOOK_IS_IN_PHASE_NO)) { + MergeGain = -1; + } + + return (MergeGain); +} + +/* sectioning Stage 0:find minimum codbooks */ +static void FDKaacEnc_gmStage0( + SECTION_INFO* const RESTRICT huffsection, + const INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], const INT maxSfb, + const INT* const noiseNrg, const INT* const isBook) { + INT i; + + for (i = 0; i < maxSfb; i++) { + /* Side-Info bits will be calculated in Stage 1! */ + if (huffsection[i].sectionBits == INVALID_BITCOUNT) { + /* intensity and pns codebooks are already allocated in bitcount.c */ + if (noiseNrg[i] != NO_NOISE_PNS) { + huffsection[i].codeBook = CODE_BOOK_PNS_NO; + huffsection[i].sectionBits = 0; + } else if (isBook[i]) { + huffsection[i].codeBook = isBook[i]; + huffsection[i].sectionBits = 0; + } else { + huffsection[i].sectionBits = + FDKaacEnc_findBestBook(bitLookUp[i], &(huffsection[i].codeBook), + 0); /* useVCB11 must be 0!!! */ + } + } + } +} + +/* + sectioning Stage 1:merge all connected regions with the same code book and + calculate side info + */ +static void FDKaacEnc_gmStage1( + SECTION_INFO* const RESTRICT huffsection, + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], const INT maxSfb, + const SHORT* const sideInfoTab, const INT useVCB11) { + INT mergeStart = 0, mergeEnd; + + do { + for (mergeEnd = mergeStart + 1; mergeEnd < maxSfb; mergeEnd++) { + if (huffsection[mergeStart].codeBook != huffsection[mergeEnd].codeBook) + break; + + /* we can merge. update tables, side info bits will be updated outside of + * this loop */ + huffsection[mergeStart].sfbCnt++; + huffsection[mergeStart].sectionBits += huffsection[mergeEnd].sectionBits; + + /* update bit look up for all code books */ + FDKaacEnc_mergeBitLookUp(bitLookUp[mergeStart], bitLookUp[mergeEnd]); + } + + /* add side info info bits */ + huffsection[mergeStart].sectionBits += FDKaacEnc_getSideInfoBits( + &huffsection[mergeStart], sideInfoTab, useVCB11); + huffsection[mergeEnd - 1].sfbStart = + huffsection[mergeStart].sfbStart; /* speed up prev search */ + + mergeStart = mergeEnd; + + } while (mergeStart < maxSfb); +} + +/* + sectioning Stage 2:greedy merge algorithm, merge connected sections with + maximum bit gain until no more gain is possible + */ +static inline void FDKaacEnc_gmStage2( + SECTION_INFO* const RESTRICT huffsection, + INT* const RESTRICT mergeGainLookUp, + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], const INT maxSfb, + const SHORT* const sideInfoTab, const INT useVCB11) { + INT i; + + for (i = 0; i + huffsection[i].sfbCnt < maxSfb; i += huffsection[i].sfbCnt) { + mergeGainLookUp[i] = + FDKaacEnc_CalcMergeGain(huffsection, bitLookUp, sideInfoTab, i, + i + huffsection[i].sfbCnt, useVCB11); + } + + while (TRUE) { + INT maxMergeGain, maxNdx, maxNdxNext, maxNdxLast; + + maxMergeGain = + FDKaacEnc_findMaxMerge(mergeGainLookUp, huffsection, maxSfb, &maxNdx); + + /* exit while loop if no more gain is possible */ + if (maxMergeGain <= 0) break; + + maxNdxNext = maxNdx + huffsection[maxNdx].sfbCnt; + + /* merge sections with maximum bit gain */ + huffsection[maxNdx].sfbCnt += huffsection[maxNdxNext].sfbCnt; + huffsection[maxNdx].sectionBits += + huffsection[maxNdxNext].sectionBits - maxMergeGain; + + /* update bit look up table for merged huffsection */ + FDKaacEnc_mergeBitLookUp(bitLookUp[maxNdx], bitLookUp[maxNdxNext]); + + /* update mergeLookUpTable */ + if (maxNdx != 0) { + maxNdxLast = huffsection[maxNdx - 1].sfbStart; + mergeGainLookUp[maxNdxLast] = FDKaacEnc_CalcMergeGain( + huffsection, bitLookUp, sideInfoTab, maxNdxLast, maxNdx, useVCB11); + } + maxNdxNext = maxNdx + huffsection[maxNdx].sfbCnt; + + huffsection[maxNdxNext - 1].sfbStart = huffsection[maxNdx].sfbStart; + + if (maxNdxNext < maxSfb) + mergeGainLookUp[maxNdx] = FDKaacEnc_CalcMergeGain( + huffsection, bitLookUp, sideInfoTab, maxNdx, maxNdxNext, useVCB11); + } +} + +/* count bits used by the noiseless coder */ +static void FDKaacEnc_noiselessCounter( + SECTION_DATA* const RESTRICT sectionData, INT mergeGainLookUp[MAX_SFB_LONG], + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const SHORT* const quantSpectrum, const UINT* const maxValueInSfb, + const INT* const sfbOffset, const INT blockType, const INT* const noiseNrg, + const INT* const isBook, const INT useVCB11) { + INT grpNdx, i; + const SHORT* sideInfoTab = NULL; + SECTION_INFO* huffsection; + + /* use appropriate side info table */ + switch (blockType) { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + default: + sideInfoTab = FDKaacEnc_sideInfoTabLong; + break; + case SHORT_WINDOW: + sideInfoTab = FDKaacEnc_sideInfoTabShort; + break; + } + + sectionData->noOfSections = 0; + sectionData->huffmanBits = 0; + sectionData->sideInfoBits = 0; + + if (sectionData->maxSfbPerGroup == 0) return; + + /* loop trough groups */ + for (grpNdx = 0; grpNdx < sectionData->sfbCnt; + grpNdx += sectionData->sfbPerGroup) { + huffsection = sectionData->huffsection + sectionData->noOfSections; + + /* count bits in this group */ + FDKaacEnc_buildBitLookUp(quantSpectrum, sectionData->maxSfbPerGroup, + sfbOffset + grpNdx, maxValueInSfb + grpNdx, + bitLookUp, huffsection); + + /* 0.Stage :Find minimum Codebooks */ + FDKaacEnc_gmStage0(huffsection, bitLookUp, sectionData->maxSfbPerGroup, + noiseNrg + grpNdx, isBook + grpNdx); + + /* 1.Stage :Merge all connected regions with the same code book */ + FDKaacEnc_gmStage1(huffsection, bitLookUp, sectionData->maxSfbPerGroup, + sideInfoTab, useVCB11); + + /* + 2.Stage + greedy merge algorithm, merge connected huffsections with maximum bit + gain until no more gain is possible + */ + + FDKaacEnc_gmStage2(huffsection, mergeGainLookUp, bitLookUp, + sectionData->maxSfbPerGroup, sideInfoTab, useVCB11); + + /* + compress output, calculate total huff and side bits + since we did not update the actual codebook in stage 2 + to save time, we must set it here for later use in bitenc + */ + + for (i = 0; i < sectionData->maxSfbPerGroup; i += huffsection[i].sfbCnt) { + if ((huffsection[i].codeBook == CODE_BOOK_PNS_NO) || + (huffsection[i].codeBook == CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (huffsection[i].codeBook == CODE_BOOK_IS_IN_PHASE_NO)) { + huffsection[i].sectionBits = 0; + } else { + /* the sections in the sectionData are now marked with the optimal code + * book */ + + FDKaacEnc_findBestBook(bitLookUp[i], &(huffsection[i].codeBook), + useVCB11); + + sectionData->huffmanBits += + huffsection[i].sectionBits - + FDKaacEnc_getSideInfoBits(&huffsection[i], sideInfoTab, useVCB11); + } + + huffsection[i].sfbStart += grpNdx; + + /* sum up side info bits (section data bits) */ + sectionData->sideInfoBits += + FDKaacEnc_getSideInfoBits(&huffsection[i], sideInfoTab, useVCB11); + sectionData->huffsection[sectionData->noOfSections++] = huffsection[i]; + } + } +} + +/******************************************************************************* + + functionname: FDKaacEnc_scfCount + returns : --- + description : count bits used by scalefactors. + + not in all cases if maxValueInSfb[] == 0 we set deltaScf + to zero. only if the difference of the last and future + scalefacGain is not greater then CODE_BOOK_SCF_LAV (60). + + example: + ^ + scalefacGain | + | + | last 75 + | | + | | + | | + | | current 50 + | | | + | | | + | | | + | | | + | | | future 5 + | | | | + --- ... ---------------------------- ... ---------> + sfb + + + if maxValueInSfb[] of current is zero because of a + notfallstrategie, we do not save bits and transmit a + deltaScf of 25. otherwise the deltaScf between the last + scalfacGain (75) and the future scalefacGain (5) is 70. + +********************************************************************************/ +static void FDKaacEnc_scfCount(const INT* const scalefacGain, + const UINT* const maxValueInSfb, + SECTION_DATA* const RESTRICT sectionData, + const INT* const isScale) { + INT i, j, k, m, n; + + INT lastValScf = 0; + INT deltaScf = 0; + INT found = 0; + INT scfSkipCounter = 0; + INT lastValIs = 0; + + sectionData->scalefacBits = 0; + + if (scalefacGain == NULL) return; + + sectionData->firstScf = 0; + + for (i = 0; i < sectionData->noOfSections; i++) { + if (sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) { + sectionData->firstScf = sectionData->huffsection[i].sfbStart; + lastValScf = scalefacGain[sectionData->firstScf]; + break; + } + } + + for (i = 0; i < sectionData->noOfSections; i++) { + if ((sectionData->huffsection[i].codeBook == + CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (sectionData->huffsection[i].codeBook == CODE_BOOK_IS_IN_PHASE_NO)) { + for (j = sectionData->huffsection[i].sfbStart; + j < sectionData->huffsection[i].sfbStart + + sectionData->huffsection[i].sfbCnt; + j++) { + INT deltaIs = isScale[j] - lastValIs; + lastValIs = isScale[j]; + sectionData->scalefacBits += + FDKaacEnc_bitCountScalefactorDelta(deltaIs); + } + } /* Intensity */ + else if ((sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) && + (sectionData->huffsection[i].codeBook != CODE_BOOK_PNS_NO)) { + INT tmp = sectionData->huffsection[i].sfbStart + + sectionData->huffsection[i].sfbCnt; + for (j = sectionData->huffsection[i].sfbStart; j < tmp; j++) { + /* check if we can repeat the last value to save bits */ + if (maxValueInSfb[j] == 0) { + found = 0; + /* are scalefactors skipped? */ + if (scfSkipCounter == 0) { + /* end of section */ + if (j == (tmp - 1)) + found = 0; /* search in other sections for maxValueInSfb != 0 */ + else { + /* search in this section for the next maxValueInSfb[] != 0 */ + for (k = (j + 1); k < tmp; k++) { + if (maxValueInSfb[k] != 0) { + found = 1; + if ((fixp_abs(scalefacGain[k] - lastValScf)) <= + CODE_BOOK_SCF_LAV) + deltaScf = 0; /* save bits */ + else { + /* do not save bits */ + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + scfSkipCounter = 0; + } + break; + } + /* count scalefactor skip */ + scfSkipCounter++; + } + } + + /* search for the next maxValueInSfb[] != 0 in all other sections */ + for (m = (i + 1); (m < sectionData->noOfSections) && (found == 0); + m++) { + if ((sectionData->huffsection[m].codeBook != CODE_BOOK_ZERO_NO) && + (sectionData->huffsection[m].codeBook != CODE_BOOK_PNS_NO)) { + INT end = sectionData->huffsection[m].sfbStart + + sectionData->huffsection[m].sfbCnt; + for (n = sectionData->huffsection[m].sfbStart; n < end; n++) { + if (maxValueInSfb[n] != 0) { + found = 1; + if (fixp_abs(scalefacGain[n] - lastValScf) <= + CODE_BOOK_SCF_LAV) + deltaScf = 0; /* save bits */ + else { + /* do not save bits */ + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + scfSkipCounter = 0; + } + break; + } + /* count scalefactor skip */ + scfSkipCounter++; + } + } + } + /* no maxValueInSfb[] != 0 found */ + if (found == 0) { + deltaScf = 0; + scfSkipCounter = 0; + } + } else { + /* consider skipped scalefactors */ + deltaScf = 0; + scfSkipCounter--; + } + } else { + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + } + sectionData->scalefacBits += + FDKaacEnc_bitCountScalefactorDelta(deltaScf); + } + } + } /* for (i=0; inoOfSections; i++) */ +} + +/* count bits used by pns */ +static void FDKaacEnc_noiseCount(SECTION_DATA* const RESTRICT sectionData, + const INT* const noiseNrg) { + INT noisePCMFlag = TRUE; + INT lastValPns = 0, deltaPns; + int i, j; + + sectionData->noiseNrgBits = 0; + + for (i = 0; i < sectionData->noOfSections; i++) { + if (sectionData->huffsection[i].codeBook == CODE_BOOK_PNS_NO) { + int sfbStart = sectionData->huffsection[i].sfbStart; + int sfbEnd = sfbStart + sectionData->huffsection[i].sfbCnt; + for (j = sfbStart; j < sfbEnd; j++) { + if (noisePCMFlag) { + sectionData->noiseNrgBits += PNS_PCM_BITS; + lastValPns = noiseNrg[j]; + noisePCMFlag = FALSE; + } else { + deltaPns = noiseNrg[j] - lastValPns; + lastValPns = noiseNrg[j]; + sectionData->noiseNrgBits += + FDKaacEnc_bitCountScalefactorDelta(deltaPns); + } + } + } + } +} + +INT FDKaacEnc_dynBitCount(BITCNTR_STATE* const hBC, + const SHORT* const quantSpectrum, + const UINT* const maxValueInSfb, + const INT* const scalefac, const INT blockType, + const INT sfbCnt, const INT maxSfbPerGroup, + const INT sfbPerGroup, const INT* const sfbOffset, + SECTION_DATA* const RESTRICT sectionData, + const INT* const noiseNrg, const INT* const isBook, + const INT* const isScale, const UINT syntaxFlags) { + sectionData->blockType = blockType; + sectionData->sfbCnt = sfbCnt; + sectionData->sfbPerGroup = sfbPerGroup; + sectionData->noOfGroups = sfbCnt / sfbPerGroup; + sectionData->maxSfbPerGroup = maxSfbPerGroup; + + FDKaacEnc_noiselessCounter(sectionData, hBC->mergeGainLookUp, + (lookUpTable)hBC->bitLookUp, quantSpectrum, + maxValueInSfb, sfbOffset, blockType, noiseNrg, + isBook, (syntaxFlags & AC_ER_VCB11) ? 1 : 0); + + FDKaacEnc_scfCount(scalefac, maxValueInSfb, sectionData, isScale); + + FDKaacEnc_noiseCount(sectionData, noiseNrg); + + return (sectionData->huffmanBits + sectionData->sideInfoBits + + sectionData->scalefacBits + sectionData->noiseNrgBits); +} + +INT FDKaacEnc_BCNew(BITCNTR_STATE** phBC, UCHAR* dynamic_RAM) { + BITCNTR_STATE* hBC = GetRam_aacEnc_BitCntrState(); + + if (hBC) { + *phBC = hBC; + hBC->bitLookUp = GetRam_aacEnc_BitLookUp(0, dynamic_RAM); + hBC->mergeGainLookUp = GetRam_aacEnc_MergeGainLookUp(0, dynamic_RAM); + if (hBC->bitLookUp == 0 || hBC->mergeGainLookUp == 0) { + return 1; + } + } + return (hBC == 0) ? 1 : 0; +} + +void FDKaacEnc_BCClose(BITCNTR_STATE** phBC) { + if (*phBC != NULL) { + FreeRam_aacEnc_BitCntrState(phBC); + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/dyn_bits.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/dyn_bits.h new file mode 100644 index 0000000000000..a727a30e65a85 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/dyn_bits.h @@ -0,0 +1,160 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Noiseless coder module + +*******************************************************************************/ + +#ifndef DYN_BITS_H +#define DYN_BITS_H + +#include "common_fix.h" + +#include "psy_const.h" +#include "aacenc_tns.h" + +#define MAX_SECTIONS MAX_GROUPED_SFB +#define SECT_ESC_VAL_LONG 31 +#define SECT_ESC_VAL_SHORT 7 +#define CODE_BOOK_BITS 4 +#define SECT_BITS_LONG 5 +#define SECT_BITS_SHORT 3 +#define PNS_PCM_BITS 9 + +typedef struct { + INT codeBook; + INT sfbStart; + INT sfbCnt; + INT sectionBits; /* huff + si ! */ +} SECTION_INFO; + +typedef struct { + INT blockType; + INT noOfGroups; + INT sfbCnt; + INT maxSfbPerGroup; + INT sfbPerGroup; + INT noOfSections; + SECTION_INFO huffsection[MAX_SECTIONS]; + INT sideInfoBits; /* sectioning bits */ + INT huffmanBits; /* huffman coded bits */ + INT scalefacBits; /* scalefac coded bits */ + INT noiseNrgBits; /* noiseEnergy coded bits */ + INT firstScf; /* first scf to be coded */ +} SECTION_DATA; + +struct BITCNTR_STATE { + INT* bitLookUp; + INT* mergeGainLookUp; +}; + +INT FDKaacEnc_BCNew(BITCNTR_STATE** phBC, UCHAR* dynamic_RAM); + +void FDKaacEnc_BCClose(BITCNTR_STATE** phBC); + +INT FDKaacEnc_dynBitCount(BITCNTR_STATE* const hBC, + const SHORT* const quantSpectrum, + const UINT* const maxValueInSfb, + const INT* const scalefac, const INT blockType, + const INT sfbCnt, const INT maxSfbPerGroup, + const INT sfbPerGroup, const INT* const sfbOffset, + SECTION_DATA* const RESTRICT sectionData, + const INT* const noiseNrg, const INT* const isBook, + const INT* const isScale, const UINT syntaxFlags); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/grp_data.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/grp_data.cpp new file mode 100644 index 0000000000000..bc9d85f37c3ab --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/grp_data.cpp @@ -0,0 +1,264 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Short block grouping + +*******************************************************************************/ + +#include "psy_const.h" +#include "interface.h" + +/* + * this routine does not work in-place + */ + +/* + * Don't use fAddSaturate2() because it looses one bit accuracy which is + * usefull for quality. + */ +static inline FIXP_DBL nrgAddSaturate(const FIXP_DBL a, const FIXP_DBL b) { + return ((a >= (FIXP_DBL)MAXVAL_DBL - b) ? (FIXP_DBL)MAXVAL_DBL : (a + b)); +} + +void FDKaacEnc_groupShortData(FIXP_DBL *mdctSpectrum, /* in-out */ + SFB_THRESHOLD *sfbThreshold, /* in-out */ + SFB_ENERGY *sfbEnergy, /* in-out */ + SFB_ENERGY *sfbEnergyMS, /* in-out */ + SFB_ENERGY *sfbSpreadEnergy, const INT sfbCnt, + const INT sfbActive, const INT *sfbOffset, + const FIXP_DBL *sfbMinSnrLdData, + INT *groupedSfbOffset, /* out */ + INT *maxSfbPerGroup, /* out */ + FIXP_DBL *groupedSfbMinSnrLdData, + const INT noOfGroups, const INT *groupLen, + const INT granuleLength) { + INT i, j; + INT line; /* counts through lines */ + INT sfb; /* counts through scalefactor bands */ + INT grp; /* counts through groups */ + INT wnd; /* counts through windows in a group */ + INT offset; /* needed in sfbOffset grouping */ + INT highestSfb; + INT granuleLength_short = granuleLength / TRANS_FAC; + + C_ALLOC_SCRATCH_START(tmpSpectrum, FIXP_DBL, (1024)) + + /* for short blocks: regroup spectrum and */ + /* group energies and thresholds according to grouping */ + + /* calculate maxSfbPerGroup */ + highestSfb = 0; + for (wnd = 0; wnd < TRANS_FAC; wnd++) { + for (sfb = sfbActive - 1; sfb >= highestSfb; sfb--) { + for (line = sfbOffset[sfb + 1] - 1; line >= sfbOffset[sfb]; line--) { + if (mdctSpectrum[wnd * granuleLength_short + line] != + FL2FXCONST_SPC(0.0)) + break; /* this band is not completely zero */ + } + if (line >= sfbOffset[sfb]) break; /* this band was not completely zero */ + } + highestSfb = fixMax(highestSfb, sfb); + } + highestSfb = highestSfb > 0 ? highestSfb : 0; + *maxSfbPerGroup = highestSfb + 1; + + /* calculate groupedSfbOffset */ + i = 0; + offset = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive + 1; sfb++) { + groupedSfbOffset[i++] = offset + sfbOffset[sfb] * groupLen[grp]; + } + i += sfbCnt - sfb; + offset += groupLen[grp] * granuleLength_short; + } + groupedSfbOffset[i++] = granuleLength; + + /* calculate groupedSfbMinSnr */ + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive; sfb++) { + groupedSfbMinSnrLdData[i++] = sfbMinSnrLdData[sfb]; + } + i += sfbCnt - sfb; + } + + /* sum up sfbThresholds */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive; sfb++) { + FIXP_DBL thresh = sfbThreshold->Short[wnd][sfb]; + for (j = 1; j < groupLen[grp]; j++) { + thresh = nrgAddSaturate(thresh, sfbThreshold->Short[wnd + j][sfb]); + } + sfbThreshold->Long[i++] = thresh; + } + i += sfbCnt - sfb; + wnd += groupLen[grp]; + } + + /* sum up sfbEnergies left/right */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive; sfb++) { + FIXP_DBL energy = sfbEnergy->Short[wnd][sfb]; + for (j = 1; j < groupLen[grp]; j++) { + energy = nrgAddSaturate(energy, sfbEnergy->Short[wnd + j][sfb]); + } + sfbEnergy->Long[i++] = energy; + } + i += sfbCnt - sfb; + wnd += groupLen[grp]; + } + + /* sum up sfbEnergies mid/side */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive; sfb++) { + FIXP_DBL energy = sfbEnergyMS->Short[wnd][sfb]; + for (j = 1; j < groupLen[grp]; j++) { + energy = nrgAddSaturate(energy, sfbEnergyMS->Short[wnd + j][sfb]); + } + sfbEnergyMS->Long[i++] = energy; + } + i += sfbCnt - sfb; + wnd += groupLen[grp]; + } + + /* sum up sfbSpreadEnergies */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive; sfb++) { + FIXP_DBL energy = sfbSpreadEnergy->Short[wnd][sfb]; + for (j = 1; j < groupLen[grp]; j++) { + energy = nrgAddSaturate(energy, sfbSpreadEnergy->Short[wnd + j][sfb]); + } + sfbSpreadEnergy->Long[i++] = energy; + } + i += sfbCnt - sfb; + wnd += groupLen[grp]; + } + + /* re-group spectrum */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive; sfb++) { + int width = sfbOffset[sfb + 1] - sfbOffset[sfb]; + FIXP_DBL *pMdctSpectrum = + &mdctSpectrum[sfbOffset[sfb]] + wnd * granuleLength_short; + for (j = 0; j < groupLen[grp]; j++) { + FIXP_DBL *pTmp = pMdctSpectrum; + for (line = width; line > 0; line--) { + tmpSpectrum[i++] = *pTmp++; + } + pMdctSpectrum += granuleLength_short; + } + } + i += (groupLen[grp] * (sfbOffset[sfbCnt] - sfbOffset[sfb])); + wnd += groupLen[grp]; + } + + FDKmemcpy(mdctSpectrum, tmpSpectrum, granuleLength * sizeof(FIXP_DBL)); + + C_ALLOC_SCRATCH_END(tmpSpectrum, FIXP_DBL, (1024)) +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/grp_data.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/grp_data.h new file mode 100644 index 0000000000000..3e1a7084f5e82 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/grp_data.h @@ -0,0 +1,123 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Short block grouping + +*******************************************************************************/ + +#ifndef GRP_DATA_H +#define GRP_DATA_H + +#include "common_fix.h" + +#include "psy_data.h" + +void FDKaacEnc_groupShortData(FIXP_DBL *mdctSpectrum, /* in-out */ + SFB_THRESHOLD *sfbThreshold, /* in-out */ + SFB_ENERGY *sfbEnergy, /* in-out */ + SFB_ENERGY *sfbEnergyMS, /* in-out */ + SFB_ENERGY *sfbSpreadEnergy, const INT sfbCnt, + const INT sfbActive, const INT *sfbOffset, + const FIXP_DBL *sfbMinSnrLdData, + INT *groupedSfbOffset, /* out */ + INT *maxSfbPerGroup, + FIXP_DBL *groupedSfbMinSnrLdData, + const INT noOfGroups, const INT *groupLen, + const INT granuleLength); + +#endif /* _INTERFACE_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/intensity.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/intensity.cpp new file mode 100644 index 0000000000000..0944fa365f4fe --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/intensity.cpp @@ -0,0 +1,817 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): A. Horndasch (code originally from lwr) / Josef Hoepfl (FDK) + + Description: intensity stereo processing + +*******************************************************************************/ + +#include "intensity.h" + +#include "interface.h" +#include "psy_configuration.h" +#include "psy_const.h" +#include "qc_main.h" +#include "bit_cnt.h" + +/* only set an IS seed it left/right channel correlation is above IS_CORR_THRESH + */ +#define IS_CORR_THRESH FL2FXCONST_DBL(0.95f) + +/* when expanding the IS region to more SFBs only accept an error that is + * not more than IS_TOTAL_ERROR_THRESH overall and + * not more than IS_LOCAL_ERROR_THRESH for the current SFB */ +#define IS_TOTAL_ERROR_THRESH FL2FXCONST_DBL(0.04f) +#define IS_LOCAL_ERROR_THRESH FL2FXCONST_DBL(0.01f) + +/* the maximum allowed change of the intensity direction (unit: IS scale) - + * scaled with factor 0.25 - */ +#define IS_DIRECTION_DEVIATION_THRESH_SF 2 +#define IS_DIRECTION_DEVIATION_THRESH \ + FL2FXCONST_DBL(2.0f / (1 << IS_DIRECTION_DEVIATION_THRESH_SF)) + +/* IS regions need to have a minimal percentage of the overall loudness, e.g. + * 0.06 == 6% */ +#define IS_REGION_MIN_LOUDNESS FL2FXCONST_DBL(0.1f) + +/* only perform IS if IS_MIN_SFBS neighboring SFBs can be processed */ +#define IS_MIN_SFBS 6 + +/* only do IS if + * if IS_LEFT_RIGHT_RATIO_THRESH < sfbEnergyLeft[sfb]/sfbEnergyRight[sfb] < 1 / + * IS_LEFT_RIGHT_RATIO_THRESH + * -> no IS if the panning angle is not far from the middle, MS will do */ +/* this is equivalent to a scale of +/-1.02914634566 */ +#define IS_LEFT_RIGHT_RATIO_THRESH FL2FXCONST_DBL(0.7f) + +/* scalefactor of realScale */ +#define REAL_SCALE_SF 1 + +/* scalefactor overallLoudness */ +#define OVERALL_LOUDNESS_SF 6 + +/* scalefactor for sum over max samples per goup */ +#define MAX_SFB_PER_GROUP_SF 6 + +/* scalefactor for sum of mdct spectrum */ +#define MDCT_SPEC_SF 6 + +typedef struct { + FIXP_DBL corr_thresh; /*!< Only set an IS seed it left/right channel + correlation is above corr_thresh */ + + FIXP_DBL total_error_thresh; /*!< When expanding the IS region to more SFBs + only accept an error that is not more than + 'total_error_thresh' overall. */ + + FIXP_DBL local_error_thresh; /*!< When expanding the IS region to more SFBs + only accept an error that is not more than + 'local_error_thresh' for the current SFB. */ + + FIXP_DBL direction_deviation_thresh; /*!< The maximum allowed change of the + intensity direction (unit: IS scale) + */ + + FIXP_DBL is_region_min_loudness; /*!< IS regions need to have a minimal + percentage of the overall loudness, e.g. + 0.06 == 6% */ + + INT min_is_sfbs; /*!< Only perform IS if 'min_is_sfbs' neighboring SFBs can be + processed */ + + FIXP_DBL left_right_ratio_threshold; /*!< No IS if the panning angle is not + far from the middle, MS will do */ + +} INTENSITY_PARAMETERS; + +/***************************************************************************** + + functionname: calcSfbMaxScale + + description: Calc max value in scalefactor band + + input: *mdctSpectrum + l1 + l2 + + output: none + + returns: scalefactor + +*****************************************************************************/ +static INT calcSfbMaxScale(const FIXP_DBL *mdctSpectrum, const INT l1, + const INT l2) { + INT i; + INT sfbMaxScale; + FIXP_DBL maxSpc; + + maxSpc = FL2FXCONST_DBL(0.0); + for (i = l1; i < l2; i++) { + FIXP_DBL tmp = fixp_abs((FIXP_DBL)mdctSpectrum[i]); + maxSpc = fixMax(maxSpc, tmp); + } + sfbMaxScale = (maxSpc == FL2FXCONST_DBL(0.0)) ? (DFRACT_BITS - 2) + : CntLeadingZeros(maxSpc) - 1; + + return sfbMaxScale; +} + +/***************************************************************************** + + functionname: FDKaacEnc_initIsParams + + description: Initialization of intensity parameters + + input: isParams + + output: isParams + + returns: none + +*****************************************************************************/ +static void FDKaacEnc_initIsParams(INTENSITY_PARAMETERS *isParams) { + isParams->corr_thresh = IS_CORR_THRESH; + isParams->total_error_thresh = IS_TOTAL_ERROR_THRESH; + isParams->local_error_thresh = IS_LOCAL_ERROR_THRESH; + isParams->direction_deviation_thresh = IS_DIRECTION_DEVIATION_THRESH; + isParams->is_region_min_loudness = IS_REGION_MIN_LOUDNESS; + isParams->min_is_sfbs = IS_MIN_SFBS; + isParams->left_right_ratio_threshold = IS_LEFT_RIGHT_RATIO_THRESH; +} + +/***************************************************************************** + + functionname: FDKaacEnc_prepareIntensityDecision + + description: Prepares intensity decision + + input: sfbEnergyLeft + sfbEnergyRight + sfbEnergyLdDataLeft + sfbEnergyLdDataRight + mdctSpectrumLeft + sfbEnergyLdDataRight + isParams + + output: hrrErr scale: none + isMask scale: none + realScale scale: LD_DATA_SHIFT + REAL_SCALE_SF + normSfbLoudness scale: none + + returns: none + +*****************************************************************************/ +static void FDKaacEnc_prepareIntensityDecision( + const FIXP_DBL *sfbEnergyLeft, const FIXP_DBL *sfbEnergyRight, + const FIXP_DBL *sfbEnergyLdDataLeft, const FIXP_DBL *sfbEnergyLdDataRight, + const FIXP_DBL *mdctSpectrumLeft, const FIXP_DBL *mdctSpectrumRight, + const INTENSITY_PARAMETERS *isParams, FIXP_DBL *hrrErr, INT *isMask, + FIXP_DBL *realScale, FIXP_DBL *normSfbLoudness, const INT sfbCnt, + const INT sfbPerGroup, const INT maxSfbPerGroup, const INT *sfbOffset) { + INT j, sfb, sfboffs; + INT grpCounter; + + /* temporary variables to compute loudness */ + FIXP_DBL overallLoudness[MAX_NO_OF_GROUPS]; + + /* temporary variables to compute correlation */ + FIXP_DBL channelCorr[MAX_GROUPED_SFB]; + FIXP_DBL ml, mr; + FIXP_DBL prod_lr; + FIXP_DBL square_l, square_r; + FIXP_DBL tmp_l, tmp_r; + FIXP_DBL inv_n; + + FDKmemclear(channelCorr, MAX_GROUPED_SFB * sizeof(FIXP_DBL)); + FDKmemclear(normSfbLoudness, MAX_GROUPED_SFB * sizeof(FIXP_DBL)); + FDKmemclear(overallLoudness, MAX_NO_OF_GROUPS * sizeof(FIXP_DBL)); + FDKmemclear(realScale, MAX_GROUPED_SFB * sizeof(FIXP_DBL)); + + for (grpCounter = 0, sfboffs = 0; sfboffs < sfbCnt; + sfboffs += sfbPerGroup, grpCounter++) { + overallLoudness[grpCounter] = FL2FXCONST_DBL(0.0f); + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + INT sL, sR, s; + FIXP_DBL isValue = sfbEnergyLdDataLeft[sfb + sfboffs] - + sfbEnergyLdDataRight[sfb + sfboffs]; + + /* delimitate intensity scale value to representable range */ + realScale[sfb + sfboffs] = fixMin( + FL2FXCONST_DBL(60.f / (1 << (REAL_SCALE_SF + LD_DATA_SHIFT))), + fixMax(FL2FXCONST_DBL(-60.f / (1 << (REAL_SCALE_SF + LD_DATA_SHIFT))), + isValue)); + + sL = fixMax(0, (CntLeadingZeros(sfbEnergyLeft[sfb + sfboffs]) - 1)); + sR = fixMax(0, (CntLeadingZeros(sfbEnergyRight[sfb + sfboffs]) - 1)); + s = (fixMin(sL, sR) >> 2) << 2; + normSfbLoudness[sfb + sfboffs] = + sqrtFixp(sqrtFixp(((sfbEnergyLeft[sfb + sfboffs] << s) >> 1) + + ((sfbEnergyRight[sfb + sfboffs] << s) >> 1))) >> + (s >> 2); + + overallLoudness[grpCounter] += + normSfbLoudness[sfb + sfboffs] >> OVERALL_LOUDNESS_SF; + /* don't do intensity if + * - panning angle is too close to the middle or + * - one channel is non-existent or + * - if it is dual mono */ + if ((sfbEnergyLeft[sfb + sfboffs] >= + fMult(isParams->left_right_ratio_threshold, + sfbEnergyRight[sfb + sfboffs])) && + (fMult(isParams->left_right_ratio_threshold, + sfbEnergyLeft[sfb + sfboffs]) <= + sfbEnergyRight[sfb + sfboffs])) { + /* this will prevent post processing from considering this SFB for + * merging */ + hrrErr[sfb + sfboffs] = FL2FXCONST_DBL(1.0 / 8.0); + } + } + } + + for (grpCounter = 0, sfboffs = 0; sfboffs < sfbCnt; + sfboffs += sfbPerGroup, grpCounter++) { + INT invOverallLoudnessSF; + FIXP_DBL invOverallLoudness; + + if (overallLoudness[grpCounter] == FL2FXCONST_DBL(0.0)) { + invOverallLoudness = FL2FXCONST_DBL(0.0); + invOverallLoudnessSF = 0; + } else { + invOverallLoudness = + fDivNorm((FIXP_DBL)MAXVAL_DBL, overallLoudness[grpCounter], + &invOverallLoudnessSF); + invOverallLoudnessSF = + invOverallLoudnessSF - OVERALL_LOUDNESS_SF + + 1; /* +1: compensate fMultDiv2() in subsequent loop */ + } + invOverallLoudnessSF = fixMin( + fixMax(invOverallLoudnessSF, -(DFRACT_BITS - 1)), DFRACT_BITS - 1); + + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + FIXP_DBL tmp; + + tmp = fMultDiv2((normSfbLoudness[sfb + sfboffs] >> OVERALL_LOUDNESS_SF) + << OVERALL_LOUDNESS_SF, + invOverallLoudness); + + normSfbLoudness[sfb + sfboffs] = scaleValue(tmp, invOverallLoudnessSF); + + channelCorr[sfb + sfboffs] = FL2FXCONST_DBL(0.0f); + + /* max width of scalefactorband is 96; width's are always even */ + /* inv_n is scaled with factor 2 to compensate fMultDiv2() in subsequent + * loops */ + inv_n = GetInvInt( + (sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs]) >> 1); + + if (inv_n > FL2FXCONST_DBL(0.0f)) { + INT s, sL, sR; + + /* correlation := Pearson's product-moment coefficient */ + /* compute correlation between channels and check if it is over + * threshold */ + ml = FL2FXCONST_DBL(0.0f); + mr = FL2FXCONST_DBL(0.0f); + prod_lr = FL2FXCONST_DBL(0.0f); + square_l = FL2FXCONST_DBL(0.0f); + square_r = FL2FXCONST_DBL(0.0f); + + sL = calcSfbMaxScale(mdctSpectrumLeft, sfbOffset[sfb + sfboffs], + sfbOffset[sfb + sfboffs + 1]); + sR = calcSfbMaxScale(mdctSpectrumRight, sfbOffset[sfb + sfboffs], + sfbOffset[sfb + sfboffs + 1]); + s = fixMin(sL, sR); + + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + ml += fMultDiv2((mdctSpectrumLeft[j] << s), + inv_n); // scaled with mdctScale - s + inv_n + mr += fMultDiv2((mdctSpectrumRight[j] << s), + inv_n); // scaled with mdctScale - s + inv_n + } + ml = fMultDiv2(ml, inv_n); // scaled with mdctScale - s + inv_n + mr = fMultDiv2(mr, inv_n); // scaled with mdctScale - s + inv_n + + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + tmp_l = fMultDiv2((mdctSpectrumLeft[j] << s), inv_n) - + ml; // scaled with mdctScale - s + inv_n + tmp_r = fMultDiv2((mdctSpectrumRight[j] << s), inv_n) - + mr; // scaled with mdctScale - s + inv_n + + prod_lr += fMultDiv2( + tmp_l, tmp_r); // scaled with 2*(mdctScale - s + inv_n) + 1 + square_l += + fPow2Div2(tmp_l); // scaled with 2*(mdctScale - s + inv_n) + 1 + square_r += + fPow2Div2(tmp_r); // scaled with 2*(mdctScale - s + inv_n) + 1 + } + prod_lr = prod_lr << 1; // scaled with 2*(mdctScale - s + inv_n) + square_l = square_l << 1; // scaled with 2*(mdctScale - s + inv_n) + square_r = square_r << 1; // scaled with 2*(mdctScale - s + inv_n) + + if (square_l > FL2FXCONST_DBL(0.0f) && + square_r > FL2FXCONST_DBL(0.0f)) { + INT channelCorrSF = 0; + + /* local scaling of square_l and square_r is compensated after sqrt + * calculation */ + sL = fixMax(0, (CntLeadingZeros(square_l) - 1)); + sR = fixMax(0, (CntLeadingZeros(square_r) - 1)); + s = ((sL + sR) >> 1) << 1; + sL = fixMin(sL, s); + sR = s - sL; + tmp = fMult(square_l << sL, square_r << sR); + tmp = sqrtFixp(tmp); + + FDK_ASSERT(tmp > FL2FXCONST_DBL(0.0f)); + + /* numerator and denominator have the same scaling */ + if (prod_lr < FL2FXCONST_DBL(0.0f)) { + channelCorr[sfb + sfboffs] = + -(fDivNorm(-prod_lr, tmp, &channelCorrSF)); + + } else { + channelCorr[sfb + sfboffs] = + (fDivNorm(prod_lr, tmp, &channelCorrSF)); + } + channelCorrSF = fixMin( + fixMax((channelCorrSF + ((sL + sR) >> 1)), -(DFRACT_BITS - 1)), + DFRACT_BITS - 1); + + if (channelCorrSF < 0) { + channelCorr[sfb + sfboffs] = + channelCorr[sfb + sfboffs] >> (-channelCorrSF); + } else { + /* avoid overflows due to limited computational accuracy */ + if (fAbs(channelCorr[sfb + sfboffs]) > + (((FIXP_DBL)MAXVAL_DBL) >> channelCorrSF)) { + if (channelCorr[sfb + sfboffs] < FL2FXCONST_DBL(0.0f)) + channelCorr[sfb + sfboffs] = -(FIXP_DBL)MAXVAL_DBL; + else + channelCorr[sfb + sfboffs] = (FIXP_DBL)MAXVAL_DBL; + } else { + channelCorr[sfb + sfboffs] = channelCorr[sfb + sfboffs] + << channelCorrSF; + } + } + } + } + + /* for post processing: hrrErr is the error in terms of (too little) + * correlation weighted with the loudness of the SFB; SFBs with small + * hrrErr can be merged */ + if (hrrErr[sfb + sfboffs] == FL2FXCONST_DBL(1.0 / 8.0)) { + continue; + } + + hrrErr[sfb + sfboffs] = + fMultDiv2((FL2FXCONST_DBL(0.25f) - (channelCorr[sfb + sfboffs] >> 2)), + normSfbLoudness[sfb + sfboffs]); + + /* set IS mask/vector to 1, if correlation is high enough */ + if (fAbs(channelCorr[sfb + sfboffs]) >= isParams->corr_thresh) { + isMask[sfb + sfboffs] = 1; + } + } + } +} + +/***************************************************************************** + + functionname: FDKaacEnc_finalizeIntensityDecision + + description: Finalizes intensity decision + + input: isParams scale: none + hrrErr scale: none + realIsScale scale: LD_DATA_SHIFT + REAL_SCALE_SF + normSfbLoudness scale: none + + output: isMask scale: none + + returns: none + +*****************************************************************************/ +static void FDKaacEnc_finalizeIntensityDecision( + const FIXP_DBL *hrrErr, INT *isMask, const FIXP_DBL *realIsScale, + const FIXP_DBL *normSfbLoudness, const INTENSITY_PARAMETERS *isParams, + const INT sfbCnt, const INT sfbPerGroup, const INT maxSfbPerGroup) { + INT sfb, sfboffs, j; + FIXP_DBL isScaleLast = FL2FXCONST_DBL(0.0f); + INT isStartValueFound = 0; + + for (sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup) { + INT startIsSfb = 0; + INT inIsBlock = 0; + INT currentIsSfbCount = 0; + FIXP_DBL overallHrrError = FL2FXCONST_DBL(0.0f); + FIXP_DBL isRegionLoudness = FL2FXCONST_DBL(0.0f); + + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + if (isMask[sfboffs + sfb] == 1) { + if (currentIsSfbCount == 0) { + startIsSfb = sfboffs + sfb; + } + if (isStartValueFound == 0) { + isScaleLast = realIsScale[sfboffs + sfb]; + isStartValueFound = 1; + } + inIsBlock = 1; + currentIsSfbCount++; + overallHrrError += hrrErr[sfboffs + sfb] >> (MAX_SFB_PER_GROUP_SF - 3); + isRegionLoudness += + normSfbLoudness[sfboffs + sfb] >> MAX_SFB_PER_GROUP_SF; + } else { + /* based on correlation, IS should not be used + * -> use it anyway, if overall error is below threshold + * and if local error does not exceed threshold + * otherwise: check if there are enough IS SFBs + */ + if (inIsBlock) { + overallHrrError += + hrrErr[sfboffs + sfb] >> (MAX_SFB_PER_GROUP_SF - 3); + isRegionLoudness += + normSfbLoudness[sfboffs + sfb] >> MAX_SFB_PER_GROUP_SF; + + if ((hrrErr[sfboffs + sfb] < (isParams->local_error_thresh >> 3)) && + (overallHrrError < + (isParams->total_error_thresh >> MAX_SFB_PER_GROUP_SF))) { + currentIsSfbCount++; + /* overwrite correlation based decision */ + isMask[sfboffs + sfb] = 1; + } else { + inIsBlock = 0; + } + } + } + /* check for large direction deviation */ + if (inIsBlock) { + if (fAbs(isScaleLast - realIsScale[sfboffs + sfb]) < + (isParams->direction_deviation_thresh >> + (REAL_SCALE_SF + LD_DATA_SHIFT - + IS_DIRECTION_DEVIATION_THRESH_SF))) { + isScaleLast = realIsScale[sfboffs + sfb]; + } else { + isMask[sfboffs + sfb] = 0; + inIsBlock = 0; + currentIsSfbCount--; + } + } + + if (currentIsSfbCount > 0 && (!inIsBlock || sfb == maxSfbPerGroup - 1)) { + /* not enough SFBs -> do not use IS */ + if (currentIsSfbCount < isParams->min_is_sfbs || + (isRegionLoudnessis_region_min_loudness>> + MAX_SFB_PER_GROUP_SF)) { + for (j = startIsSfb; j <= sfboffs + sfb; j++) { + isMask[j] = 0; + } + isScaleLast = FL2FXCONST_DBL(0.0f); + isStartValueFound = 0; + for (j = 0; j < startIsSfb; j++) { + if (isMask[j] != 0) { + isScaleLast = realIsScale[j]; + isStartValueFound = 1; + } + } + } + currentIsSfbCount = 0; + overallHrrError = FL2FXCONST_DBL(0.0f); + isRegionLoudness = FL2FXCONST_DBL(0.0f); + } + } + } +} + +/***************************************************************************** + + functionname: FDKaacEnc_IntensityStereoProcessing + + description: Intensity stereo processing tool + + input: sfbEnergyLeft + sfbEnergyRight + mdctSpectrumLeft + mdctSpectrumRight + sfbThresholdLeft + sfbThresholdRight + sfbSpreadEnLeft + sfbSpreadEnRight + sfbEnergyLdDataLeft + sfbEnergyLdDataRight + + output: isBook + isScale + pnsData->pnsFlag + msDigest zeroed from start to sfbCnt + msMask zeroed from start to sfbCnt + mdctSpectrumRight zeroed where isBook!=0 + sfbEnergyRight zeroed where isBook!=0 + sfbSpreadEnRight zeroed where isBook!=0 + sfbThresholdRight zeroed where isBook!=0 + sfbEnergyLdDataRight FL2FXCONST_DBL(-1.0) where isBook!=0 + sfbThresholdLdDataRight FL2FXCONST_DBL(-0.515625f) where +isBook!=0 + + returns: none + +*****************************************************************************/ +void FDKaacEnc_IntensityStereoProcessing( + FIXP_DBL *sfbEnergyLeft, FIXP_DBL *sfbEnergyRight, + FIXP_DBL *mdctSpectrumLeft, FIXP_DBL *mdctSpectrumRight, + FIXP_DBL *sfbThresholdLeft, FIXP_DBL *sfbThresholdRight, + FIXP_DBL *sfbThresholdLdDataRight, FIXP_DBL *sfbSpreadEnLeft, + FIXP_DBL *sfbSpreadEnRight, FIXP_DBL *sfbEnergyLdDataLeft, + FIXP_DBL *sfbEnergyLdDataRight, INT *msDigest, INT *msMask, + const INT sfbCnt, const INT sfbPerGroup, const INT maxSfbPerGroup, + const INT *sfbOffset, const INT allowIS, INT *isBook, INT *isScale, + PNS_DATA *RESTRICT pnsData[2]) { + INT sfb, sfboffs, j; + FIXP_DBL scale; + FIXP_DBL lr; + FIXP_DBL hrrErr[MAX_GROUPED_SFB]; + FIXP_DBL normSfbLoudness[MAX_GROUPED_SFB]; + FIXP_DBL realIsScale[MAX_GROUPED_SFB]; + INTENSITY_PARAMETERS isParams; + INT isMask[MAX_GROUPED_SFB]; + + FDKmemclear((void *)isBook, sfbCnt * sizeof(INT)); + FDKmemclear((void *)isMask, sfbCnt * sizeof(INT)); + FDKmemclear((void *)realIsScale, sfbCnt * sizeof(FIXP_DBL)); + FDKmemclear((void *)isScale, sfbCnt * sizeof(INT)); + FDKmemclear((void *)hrrErr, sfbCnt * sizeof(FIXP_DBL)); + + if (!allowIS) return; + + FDKaacEnc_initIsParams(&isParams); + + /* compute / set the following values per SFB: + * - left/right ratio between channels + * - normalized loudness + * + loudness == average of energy in channels to 0.25 + * + normalization: division by sum of all SFB loudnesses + * - isMask (is set to 0 if channels are the same or one is 0) + */ + FDKaacEnc_prepareIntensityDecision( + sfbEnergyLeft, sfbEnergyRight, sfbEnergyLdDataLeft, sfbEnergyLdDataRight, + mdctSpectrumLeft, mdctSpectrumRight, &isParams, hrrErr, isMask, + realIsScale, normSfbLoudness, sfbCnt, sfbPerGroup, maxSfbPerGroup, + sfbOffset); + + FDKaacEnc_finalizeIntensityDecision(hrrErr, isMask, realIsScale, + normSfbLoudness, &isParams, sfbCnt, + sfbPerGroup, maxSfbPerGroup); + + for (sfb = 0; sfb < sfbCnt; sfb += sfbPerGroup) { + for (sfboffs = 0; sfboffs < maxSfbPerGroup; sfboffs++) { + INT sL, sR; + FIXP_DBL inv_n; + INT mdct_spec_sf = MDCT_SPEC_SF; + + msMask[sfb + sfboffs] = 0; + if (isMask[sfb + sfboffs] == 0) { + continue; + } + + if ((sfbEnergyLeft[sfb + sfboffs] < sfbThresholdLeft[sfb + sfboffs]) && + (fMult(FL2FXCONST_DBL(1.0f / 1.5f), sfbEnergyRight[sfb + sfboffs]) > + sfbThresholdRight[sfb + sfboffs])) { + continue; + } + /* NEW: if there is a big-enough IS region, switch off PNS */ + if (pnsData[0]) { + if (pnsData[0]->pnsFlag[sfb + sfboffs]) { + pnsData[0]->pnsFlag[sfb + sfboffs] = 0; + } + if (pnsData[1]->pnsFlag[sfb + sfboffs]) { + pnsData[1]->pnsFlag[sfb + sfboffs] = 0; + } + } + + if (sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs] > + 1 << mdct_spec_sf) { + mdct_spec_sf++; /* This is for rare cases where the number of bins in a + scale factor band is > 64 */ + } + + inv_n = GetInvInt( + (sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs]) >> + 1); // scaled with 2 to compensate fMultDiv2() in subsequent loop + sL = calcSfbMaxScale(mdctSpectrumLeft, sfbOffset[sfb + sfboffs], + sfbOffset[sfb + sfboffs + 1]); + sR = calcSfbMaxScale(mdctSpectrumRight, sfbOffset[sfb + sfboffs], + sfbOffset[sfb + sfboffs + 1]); + + lr = FL2FXCONST_DBL(0.0f); + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; j++) + lr += fMultDiv2( + fMultDiv2(mdctSpectrumLeft[j] << sL, mdctSpectrumRight[j] << sR), + inv_n); + lr = lr << 1; + + if (lr < FL2FXCONST_DBL(0.0f)) { + /* This means OUT OF phase intensity stereo, cf. standard */ + INT s0, s1, s2; + FIXP_DBL tmp, d, ed = FL2FXCONST_DBL(0.0f); + + s0 = fixMin(sL, sR); + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + d = ((mdctSpectrumLeft[j] << s0) >> 1) - + ((mdctSpectrumRight[j] << s0) >> 1); + ed += fMultDiv2(d, d) >> (mdct_spec_sf - 1); + } + msMask[sfb + sfboffs] = 1; + tmp = fDivNorm(sfbEnergyLeft[sfb + sfboffs], ed, &s1); + s2 = (s1) + (2 * s0) - 2 - mdct_spec_sf; + if (s2 & 1) { + tmp = tmp >> 1; + s2 = s2 + 1; + } + s2 = (s2 >> 1) + 1; // +1 compensate fMultDiv2() in subsequent loop + s2 = fixMin(fixMax(s2, -(DFRACT_BITS - 1)), (DFRACT_BITS - 1)); + scale = sqrtFixp(tmp); + if (s2 < 0) { + s2 = -s2; + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j], scale) - + fMultDiv2(mdctSpectrumRight[j], scale)) >> + s2; + mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f); + } + } else { + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j], scale) - + fMultDiv2(mdctSpectrumRight[j], scale)) + << s2; + mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f); + } + } + } else { + /* This means IN phase intensity stereo, cf. standard */ + INT s0, s1, s2; + FIXP_DBL tmp, s, es = FL2FXCONST_DBL(0.0f); + + s0 = fixMin(sL, sR); + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + s = ((mdctSpectrumLeft[j] << s0) >> 1) + + ((mdctSpectrumRight[j] << s0) >> 1); + es += fMultDiv2(s, s) >> + (mdct_spec_sf - + 1); // scaled 2*(mdctScale - s0 + 1) + mdct_spec_sf + } + msMask[sfb + sfboffs] = 0; + tmp = fDivNorm(sfbEnergyLeft[sfb + sfboffs], es, &s1); + s2 = (s1) + (2 * s0) - 2 - mdct_spec_sf; + if (s2 & 1) { + tmp = tmp >> 1; + s2 = s2 + 1; + } + s2 = (s2 >> 1) + 1; // +1 compensate fMultDiv2() in subsequent loop + s2 = fixMin(fixMax(s2, -(DFRACT_BITS - 1)), (DFRACT_BITS - 1)); + scale = sqrtFixp(tmp); + if (s2 < 0) { + s2 = -s2; + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j], scale) + + fMultDiv2(mdctSpectrumRight[j], scale)) >> + s2; + mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f); + } + } else { + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j], scale) + + fMultDiv2(mdctSpectrumRight[j], scale)) + << s2; + mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f); + } + } + } + + isBook[sfb + sfboffs] = CODE_BOOK_IS_IN_PHASE_NO; + + if (realIsScale[sfb + sfboffs] < FL2FXCONST_DBL(0.0f)) { + isScale[sfb + sfboffs] = + (INT)(((realIsScale[sfb + sfboffs] >> 1) - + FL2FXCONST_DBL( + 0.5f / (1 << (REAL_SCALE_SF + LD_DATA_SHIFT + 1)))) >> + (DFRACT_BITS - 1 - REAL_SCALE_SF - LD_DATA_SHIFT - 1)) + + 1; + } else { + isScale[sfb + sfboffs] = + (INT)(((realIsScale[sfb + sfboffs] >> 1) + + FL2FXCONST_DBL( + 0.5f / (1 << (REAL_SCALE_SF + LD_DATA_SHIFT + 1)))) >> + (DFRACT_BITS - 1 - REAL_SCALE_SF - LD_DATA_SHIFT - 1)); + } + + sfbEnergyRight[sfb + sfboffs] = FL2FXCONST_DBL(0.0f); + sfbEnergyLdDataRight[sfb + sfboffs] = FL2FXCONST_DBL(-1.0f); + sfbThresholdRight[sfb + sfboffs] = FL2FXCONST_DBL(0.0f); + sfbThresholdLdDataRight[sfb + sfboffs] = FL2FXCONST_DBL(-0.515625f); + sfbSpreadEnRight[sfb + sfboffs] = FL2FXCONST_DBL(0.0f); + + *msDigest = MS_SOME; + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/intensity.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/intensity.h new file mode 100644 index 0000000000000..70f23d51b15e7 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/intensity.h @@ -0,0 +1,121 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): A. Horndasch (code originally from lwr and rtb) / Josef Hoepfl +(FDK) + + Description: intensity stereo prototype + +*******************************************************************************/ + +#ifndef INTENSITY_H +#define INTENSITY_H + +#include "aacenc_pns.h" +#include "common_fix.h" + +void FDKaacEnc_IntensityStereoProcessing( + FIXP_DBL *sfbEnergyLeft, FIXP_DBL *sfbEnergyRight, + FIXP_DBL *mdctSpectrumLeft, FIXP_DBL *mdctSpectrumRight, + FIXP_DBL *sfbThresholdLeft, FIXP_DBL *sfbThresholdRight, + FIXP_DBL *sfbThresholdLdDataRight, FIXP_DBL *sfbSpreadEnLeft, + FIXP_DBL *sfbSpreadEnRight, FIXP_DBL *sfbEnergyLdDataLeft, + FIXP_DBL *sfbEnergyLdDataRight, INT *msDigest, INT *msMask, + const INT sfbCnt, const INT sfbPerGroup, const INT maxSfbPerGroup, + const INT *sfbOffset, const INT allowIS, INT *isBook, INT *isScale, + PNS_DATA *RESTRICT pnsData[2]); + +#endif /* INTENSITY_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/interface.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/interface.h new file mode 100644 index 0000000000000..b1a31ef43df21 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/interface.h @@ -0,0 +1,168 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Interface psychoaccoustic/quantizer + +*******************************************************************************/ + +#ifndef INTERFACE_H +#define INTERFACE_H + +#include "common_fix.h" +#include "FDK_audio.h" + +#include "psy_data.h" +#include "aacenc_tns.h" + +enum { MS_NONE = 0, MS_SOME = 1, MS_ALL = 2 }; + +enum { MS_ON = 1 }; + +struct TOOLSINFO { + INT msDigest; /* 0 = no MS; 1 = some MS, 2 = all MS */ + INT msMask[MAX_GROUPED_SFB]; +}; + +typedef struct { + INT sfbCnt; + INT sfbPerGroup; + INT maxSfbPerGroup; + INT lastWindowSequence; + INT windowShape; + INT groupingMask; + INT sfbOffsets[MAX_GROUPED_SFB + 1]; + + INT mdctScale; /* number of transform shifts */ + INT groupLen[MAX_NO_OF_GROUPS]; + + TNS_INFO tnsInfo; + INT noiseNrg[MAX_GROUPED_SFB]; + INT isBook[MAX_GROUPED_SFB]; + INT isScale[MAX_GROUPED_SFB]; + + /* memory located in QC_OUT_CHANNEL */ + FIXP_DBL *mdctSpectrum; + FIXP_DBL *sfbEnergy; + FIXP_DBL *sfbSpreadEnergy; + FIXP_DBL *sfbThresholdLdData; + FIXP_DBL *sfbMinSnrLdData; + FIXP_DBL *sfbEnergyLdData; + +} PSY_OUT_CHANNEL; + +typedef struct { + /* information specific to each channel */ + PSY_OUT_CHANNEL *psyOutChannel[(2)]; + + /* information shared by both channels */ + INT commonWindow; + struct TOOLSINFO toolsInfo; + +} PSY_OUT_ELEMENT; + +typedef struct { + PSY_OUT_ELEMENT *psyOutElement[((8))]; + PSY_OUT_CHANNEL *pPsyOutChannels[(8)]; + +} PSY_OUT; + +inline int isLowDelay(AUDIO_OBJECT_TYPE aot) { + return (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD); +} + +#endif /* INTERFACE_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/line_pe.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/line_pe.cpp new file mode 100644 index 0000000000000..47734e550786e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/line_pe.cpp @@ -0,0 +1,234 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Perceptual entropie module + +*******************************************************************************/ + +#include "line_pe.h" +#include "sf_estim.h" +#include "bit_cnt.h" + +#include "genericStds.h" + +static const FIXP_DBL C1LdData = + FL2FXCONST_DBL(3.0 / LD_DATA_SCALING); /* C1 = 3.0 = log(8.0)/log(2) */ +static const FIXP_DBL C2LdData = FL2FXCONST_DBL( + 1.3219281 / LD_DATA_SCALING); /* C2 = 1.3219281 = log(2.5)/log(2) */ +static const FIXP_DBL C3LdData = FL2FXCONST_DBL(0.5593573); /* 1-C2/C1 */ + +/* constants that do not change during successive pe calculations */ +void FDKaacEnc_prepareSfbPe(PE_CHANNEL_DATA *RESTRICT const peChanData, + const FIXP_DBL *RESTRICT const sfbEnergyLdData, + const FIXP_DBL *RESTRICT const sfbThresholdLdData, + const FIXP_DBL *RESTRICT const sfbFormFactorLdData, + const INT *RESTRICT const sfbOffset, + const INT sfbCnt, const INT sfbPerGroup, + const INT maxSfbPerGroup) { + INT sfbGrp, sfb; + INT sfbWidth; + FIXP_DBL avgFormFactorLdData; + const FIXP_DBL formFacScaling = + FL2FXCONST_DBL((float)FORM_FAC_SHIFT / LD_DATA_SCALING); + + for (sfbGrp = 0; sfbGrp < sfbCnt; sfbGrp += sfbPerGroup) { + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + if ((FIXP_DBL)sfbEnergyLdData[sfbGrp + sfb] > + (FIXP_DBL)sfbThresholdLdData[sfbGrp + sfb]) { + sfbWidth = sfbOffset[sfbGrp + sfb + 1] - sfbOffset[sfbGrp + sfb]; + /* estimate number of active lines */ + avgFormFactorLdData = ((-sfbEnergyLdData[sfbGrp + sfb] >> 1) + + (CalcLdInt(sfbWidth) >> 1)) >> + 1; + peChanData->sfbNLines[sfbGrp + sfb] = (INT)CalcInvLdData( + (sfbFormFactorLdData[sfbGrp + sfb] + formFacScaling) + + avgFormFactorLdData); + /* Make sure sfbNLines is never greater than sfbWidth due to + * unaccuracies (e.g. sfbEnergyLdData[sfbGrp+sfb] = 0x80000000) */ + peChanData->sfbNLines[sfbGrp + sfb] = + fMin(sfbWidth, peChanData->sfbNLines[sfbGrp + sfb]); + } else { + peChanData->sfbNLines[sfbGrp + sfb] = 0; + } + } + } +} + +/* + formula for one sfb: + pe = n * ld(en/thr), if ld(en/thr) >= C1 + pe = n * (C2 + C3 * ld(en/thr)), if ld(en/thr) < C1 + n: estimated number of lines in sfb, + ld(x) = log(x)/log(2) + + constPart is sfbPe without the threshold part n*ld(thr) or n*C3*ld(thr) +*/ +void FDKaacEnc_calcSfbPe(PE_CHANNEL_DATA *RESTRICT const peChanData, + const FIXP_DBL *RESTRICT const sfbEnergyLdData, + const FIXP_DBL *RESTRICT const sfbThresholdLdData, + const INT sfbCnt, const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *RESTRICT const isBook, + const INT *RESTRICT const isScale) { + INT sfbGrp, sfb, thisSfb; + INT nLines; + FIXP_DBL logDataRatio; + FIXP_DBL scaleLd = (FIXP_DBL)0; + INT lastValIs = 0; + + FIXP_DBL pe = 0; + FIXP_DBL constPart = 0; + FIXP_DBL nActiveLines = 0; + + FIXP_DBL tmpPe, tmpConstPart, tmpNActiveLines; + + for (sfbGrp = 0; sfbGrp < sfbCnt; sfbGrp += sfbPerGroup) { + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + tmpPe = (FIXP_DBL)0; + tmpConstPart = (FIXP_DBL)0; + tmpNActiveLines = (FIXP_DBL)0; + + thisSfb = sfbGrp + sfb; + + if (sfbEnergyLdData[thisSfb] > sfbThresholdLdData[thisSfb]) { + logDataRatio = sfbEnergyLdData[thisSfb] - sfbThresholdLdData[thisSfb]; + nLines = peChanData->sfbNLines[thisSfb]; + + FIXP_DBL factor = nLines << (LD_DATA_SHIFT + PE_CONSTPART_SHIFT + 1); + if (logDataRatio >= C1LdData) { + /* scale sfbPe and sfbConstPart with PE_CONSTPART_SHIFT */ + tmpPe = fMultDiv2(logDataRatio, factor); + tmpConstPart = fMultDiv2(sfbEnergyLdData[thisSfb] + scaleLd, factor); + } else { + /* scale sfbPe and sfbConstPart with PE_CONSTPART_SHIFT */ + tmpPe = fMultDiv2( + ((FIXP_DBL)C2LdData + fMult(C3LdData, logDataRatio)), factor); + tmpConstPart = + fMultDiv2(((FIXP_DBL)C2LdData + + fMult(C3LdData, sfbEnergyLdData[thisSfb] + scaleLd)), + factor); + + nLines = fMultI(C3LdData, nLines); + } + tmpNActiveLines = (FIXP_DBL)nLines; + } else if (isBook[thisSfb]) { + /* provide for cost of scale factor for Intensity */ + INT delta = isScale[thisSfb] - lastValIs; + lastValIs = isScale[thisSfb]; + peChanData->sfbPe[thisSfb] = FDKaacEnc_bitCountScalefactorDelta(delta) + << PE_CONSTPART_SHIFT; + peChanData->sfbConstPart[thisSfb] = 0; + peChanData->sfbNActiveLines[thisSfb] = 0; + } + peChanData->sfbPe[thisSfb] = tmpPe; + peChanData->sfbConstPart[thisSfb] = tmpConstPart; + peChanData->sfbNActiveLines[thisSfb] = tmpNActiveLines; + + /* sum up peChanData values */ + pe += tmpPe; + constPart += tmpConstPart; + nActiveLines += tmpNActiveLines; + } + } + + /* correct scaled pe and constPart values */ + peChanData->pe = pe >> PE_CONSTPART_SHIFT; + peChanData->constPart = constPart >> PE_CONSTPART_SHIFT; + + peChanData->nActiveLines = nActiveLines; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/line_pe.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/line_pe.h new file mode 100644 index 0000000000000..ecc2388d0c56a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/line_pe.h @@ -0,0 +1,148 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Perceptual entropie module + +*******************************************************************************/ + +#ifndef LINE_PE_H +#define LINE_PE_H + +#include "common_fix.h" + +#include "psy_const.h" + +#define PE_CONSTPART_SHIFT FRACT_BITS + +typedef struct { + /* calculated by FDKaacEnc_prepareSfbPe */ + INT sfbNLines[MAX_GROUPED_SFB]; /* number of relevant lines in sfb */ + /* the rest is calculated by FDKaacEnc_calcSfbPe */ + INT sfbPe[MAX_GROUPED_SFB]; /* pe for each sfb */ + INT sfbConstPart[MAX_GROUPED_SFB]; /* constant part for each sfb */ + INT sfbNActiveLines[MAX_GROUPED_SFB]; /* number of active lines in sfb */ + INT pe; /* sum of sfbPe */ + INT constPart; /* sum of sfbConstPart */ + INT nActiveLines; /* sum of sfbNActiveLines */ +} PE_CHANNEL_DATA; + +typedef struct { + PE_CHANNEL_DATA peChannelData[(2)]; + INT pe; + INT constPart; + INT nActiveLines; + INT offset; +} PE_DATA; + +void FDKaacEnc_prepareSfbPe(PE_CHANNEL_DATA *RESTRICT const peChanData, + const FIXP_DBL *RESTRICT const sfbEnergyLdData, + const FIXP_DBL *RESTRICT const sfbThresholdLdData, + const FIXP_DBL *RESTRICT const sfbFormFactorLdData, + const INT *RESTRICT const sfbOffset, + const INT sfbCnt, const INT sfbPerGroup, + const INT maxSfbPerGroup); + +void FDKaacEnc_calcSfbPe(PE_CHANNEL_DATA *RESTRICT const peChanData, + const FIXP_DBL *RESTRICT const sfbEnergyLdData, + const FIXP_DBL *RESTRICT const sfbThresholdLdData, + const INT sfbCnt, const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *RESTRICT const isBook, + const INT *RESTRICT const isScale); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_compressor.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_compressor.cpp new file mode 100644 index 0000000000000..bdac80adc0044 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_compressor.cpp @@ -0,0 +1,1579 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Neusinger + + Description: Compressor for AAC Metadata Generator + +*******************************************************************************/ + +#include "metadata_compressor.h" +#include "channel_map.h" + +#define LOG2 0.69314718056f /* natural logarithm of 2 */ +#define ILOG2 1.442695041f /* 1/LOG2 */ +#define FIXP_ILOG2_DIV2 (FL2FXCONST_DBL(ILOG2 / 2)) + +/*----------------- defines ----------------------*/ + +#define MAX_DRC_CHANNELS (8) /*!< Max number of audio input channels. */ +#define DOWNMIX_SHIFT (3) /*!< Max 8 channel. */ +#define WEIGHTING_FILTER_SHIFT (2) /*!< Scaling used in weighting filter. */ + +#define METADATA_INT_BITS 10 +#define METADATA_LINT_BITS 20 +#define METADATA_INT_SCALE (INT64(1) << (METADATA_INT_BITS)) +#define METADATA_FRACT_BITS (DFRACT_BITS - 1 - METADATA_INT_BITS) +#define METADATA_FRACT_SCALE (INT64(1) << (METADATA_FRACT_BITS)) + +/** + * Enum for channel assignment. + */ +enum { L = 0, R = 1, C = 2, LFE = 3, LS = 4, RS = 5, S = 6, LS2 = 7, RS2 = 8 }; + +/*--------------- structure definitions --------------------*/ + +/** + * Structure holds weighting filter filter states. + */ +struct WEIGHTING_STATES { + FIXP_DBL x1; + FIXP_DBL x2; + FIXP_DBL y1; + FIXP_DBL y2; +}; + +/** + * Dynamic Range Control compressor structure. + */ +struct DRC_COMP { + FIXP_DBL maxBoostThr[2]; /*!< Max boost threshold. */ + FIXP_DBL boostThr[2]; /*!< Boost threshold. */ + FIXP_DBL earlyCutThr[2]; /*!< Early cut threshold. */ + FIXP_DBL cutThr[2]; /*!< Cut threshold. */ + FIXP_DBL maxCutThr[2]; /*!< Max cut threshold. */ + + FIXP_DBL boostFac[2]; /*!< Precalculated factor for boost compression. */ + FIXP_DBL + earlyCutFac[2]; /*!< Precalculated factor for early cut compression. */ + FIXP_DBL cutFac[2]; /*!< Precalculated factor for cut compression. */ + + FIXP_DBL maxBoost[2]; /*!< Maximum boost. */ + FIXP_DBL maxCut[2]; /*!< Maximum cut. */ + FIXP_DBL maxEarlyCut[2]; /*!< Maximum early cut. */ + + FIXP_DBL fastAttack[2]; /*!< Fast attack coefficient. */ + FIXP_DBL fastDecay[2]; /*!< Fast release coefficient. */ + FIXP_DBL slowAttack[2]; /*!< Slow attack coefficient. */ + FIXP_DBL slowDecay[2]; /*!< Slow release coefficient. */ + UINT holdOff[2]; /*!< Hold time in blocks. */ + + FIXP_DBL attackThr[2]; /*!< Slow/fast attack threshold. */ + FIXP_DBL decayThr[2]; /*!< Slow/fast release threshold. */ + + DRC_PROFILE profile[2]; /*!< DRC profile. */ + INT blockLength; /*!< Block length in samples. */ + UINT sampleRate; /*!< Sample rate. */ + CHANNEL_MODE chanConfig; /*!< Channel configuration. */ + + UCHAR useWeighting; /*!< Use weighting filter. */ + + UINT channels; /*!< Number of channels. */ + UINT fullChannels; /*!< Number of full range channels. */ + INT channelIdx[9]; /*!< Offsets of interleaved channel samples (L, R, C, LFE, + Ls, Rs, S, Ls2, Rs2). */ + + FIXP_DBL smoothLevel[2]; /*!< level smoothing states */ + FIXP_DBL smoothGain[2]; /*!< gain smoothing states */ + UINT holdCnt[2]; /*!< hold counter */ + + FIXP_DBL limGain[2]; /*!< limiter gain */ + FIXP_DBL limDecay; /*!< limiter decay (linear) */ + FIXP_DBL prevPeak[2]; /*!< max peak of previous block (stereo/mono)*/ + + WEIGHTING_STATES + filter[MAX_DRC_CHANNELS]; /*!< array holds weighting filter states */ +}; + +/*---------------- constants -----------------------*/ + +/** + * Profile tables. + */ +static const FIXP_DBL tabMaxBoostThr[] = { + (FIXP_DBL)(-(43 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(53 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(55 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(65 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(50 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(40 << METADATA_FRACT_BITS))}; +static const FIXP_DBL tabBoostThr[] = { + (FIXP_DBL)(-(31 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(41 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(31 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(41 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(31 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(31 << METADATA_FRACT_BITS))}; +static const FIXP_DBL tabEarlyCutThr[] = { + (FIXP_DBL)(-(26 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(21 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(26 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(21 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(26 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(20 << METADATA_FRACT_BITS))}; +static const FIXP_DBL tabCutThr[] = {(FIXP_DBL)(-(16 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(11 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(16 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(21 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(16 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(10 << METADATA_FRACT_BITS))}; +static const FIXP_DBL tabMaxCutThr[] = { + (FIXP_DBL)(4 << METADATA_FRACT_BITS), (FIXP_DBL)(9 << METADATA_FRACT_BITS), + (FIXP_DBL)(4 << METADATA_FRACT_BITS), (FIXP_DBL)(9 << METADATA_FRACT_BITS), + (FIXP_DBL)(4 << METADATA_FRACT_BITS), (FIXP_DBL)(4 << METADATA_FRACT_BITS)}; +static const FIXP_DBL tabBoostRatio[] = { + FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), + FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), + FL2FXCONST_DBL(((1.f / 5.f) - 1.f)), FL2FXCONST_DBL(((1.f / 5.f) - 1.f))}; +static const FIXP_DBL tabEarlyCutRatio[] = { + FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), + FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 1.f) - 1.f)), + FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f))}; +static const FIXP_DBL tabCutRatio[] = { + FL2FXCONST_DBL(((1.f / 20.f) - 1.f)), FL2FXCONST_DBL(((1.f / 20.f) - 1.f)), + FL2FXCONST_DBL(((1.f / 20.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), + FL2FXCONST_DBL(((1.f / 20.f) - 1.f)), FL2FXCONST_DBL(((1.f / 20.f) - 1.f))}; +static const FIXP_DBL tabMaxBoost[] = {(FIXP_DBL)(6 << METADATA_FRACT_BITS), + (FIXP_DBL)(6 << METADATA_FRACT_BITS), + (FIXP_DBL)(12 << METADATA_FRACT_BITS), + (FIXP_DBL)(12 << METADATA_FRACT_BITS), + (FIXP_DBL)(15 << METADATA_FRACT_BITS), + (FIXP_DBL)(15 << METADATA_FRACT_BITS)}; +static const FIXP_DBL tabMaxCut[] = {(FIXP_DBL)(24 << METADATA_FRACT_BITS), + (FIXP_DBL)(24 << METADATA_FRACT_BITS), + (FIXP_DBL)(24 << METADATA_FRACT_BITS), + (FIXP_DBL)(15 << METADATA_FRACT_BITS), + (FIXP_DBL)(24 << METADATA_FRACT_BITS), + (FIXP_DBL)(24 << METADATA_FRACT_BITS)}; +static const FIXP_DBL tabFastAttack[] = { + FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((0.f / 1000.f) / METADATA_INT_SCALE)}; +static const FIXP_DBL tabFastDecay[] = { + FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((200.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((0.f / 1000.f) / METADATA_INT_SCALE)}; +static const FIXP_DBL tabSlowAttack[] = { + FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((0.f / 1000.f) / METADATA_INT_SCALE)}; +static const FIXP_DBL tabSlowDecay[] = { + FL2FXCONST_DBL((3000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((3000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((10000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((3000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((0.f / 1000.f) / METADATA_INT_SCALE)}; + +static const INT tabHoldOff[] = {10, 10, 10, 10, 10, 0}; + +static const FIXP_DBL tabAttackThr[] = {(FIXP_DBL)(15 << METADATA_FRACT_BITS), + (FIXP_DBL)(15 << METADATA_FRACT_BITS), + (FIXP_DBL)(15 << METADATA_FRACT_BITS), + (FIXP_DBL)(15 << METADATA_FRACT_BITS), + (FIXP_DBL)(10 << METADATA_FRACT_BITS), + (FIXP_DBL)(0 << METADATA_FRACT_BITS)}; +static const FIXP_DBL tabDecayThr[] = {(FIXP_DBL)(20 << METADATA_FRACT_BITS), + (FIXP_DBL)(20 << METADATA_FRACT_BITS), + (FIXP_DBL)(20 << METADATA_FRACT_BITS), + (FIXP_DBL)(20 << METADATA_FRACT_BITS), + (FIXP_DBL)(10 << METADATA_FRACT_BITS), + (FIXP_DBL)(0 << METADATA_FRACT_BITS)}; + +/** + * Weighting filter coefficients (biquad bandpass). + */ +static const FIXP_DBL b0 = FL2FXCONST_DBL(0.53050662f); /* b1 = 0, b2 = -b0 */ +static const FIXP_DBL a1 = FL2FXCONST_DBL(-0.95237983f), + a2 = FL2FXCONST_DBL(-0.02248836f); /* a0 = 1 */ + +/*------------- function definitions ----------------*/ + +/** + * \brief Calculate scaling factor for denoted processing block. + * + * \param blockLength Length of processing block. + * + * \return shiftFactor + */ +static UINT getShiftFactor(const UINT length) { + UINT ldN; + for (ldN = 1; (((UINT)1) << ldN) < length; ldN++) + ; + + return ldN; +} + +/** + * \brief Sum up fixpoint values with best possible accuracy. + * + * \param value1 First input value. + * \param q1 Scaling factor of first input value. + * \param pValue2 Pointer to second input value, will be modified on + * return. + * \param pQ2 Pointer to second scaling factor, will be modified on + * return. + * + * \return void + */ +static void fixpAdd(const FIXP_DBL value1, const int q1, + FIXP_DBL* const pValue2, int* const pQ2) { + const int headroom1 = fNormz(fixp_abs(value1)) - 1; + const int headroom2 = fNormz(fixp_abs(*pValue2)) - 1; + int resultScale = fixMax(q1 - headroom1, (*pQ2) - headroom2); + + if ((value1 != FL2FXCONST_DBL(0.f)) && (*pValue2 != FL2FXCONST_DBL(0.f))) { + resultScale++; + } + + *pValue2 = scaleValue(value1, q1 - resultScale) + + scaleValue(*pValue2, (*pQ2) - resultScale); + *pQ2 = (*pValue2 != (FIXP_DBL)0) ? resultScale : DFRACT_BITS - 1; +} + +/** + * \brief Function for converting time constant to filter coefficient. + * + * \param t Time constant. + * \param sampleRate Sampling rate in Hz. + * \param blockLength Length of processing block in samples per channel. + * + * \return result = 1.0 - exp(-1.0/((t) * (f))) + */ +static FIXP_DBL tc2Coeff(const FIXP_DBL t, const INT sampleRate, + const INT blockLength) { + FIXP_DBL sampleRateFract; + FIXP_DBL blockLengthFract; + FIXP_DBL f, product; + FIXP_DBL exponent, result; + INT e_res; + + /* f = sampleRate/blockLength */ + sampleRateFract = + (FIXP_DBL)(sampleRate << (DFRACT_BITS - 1 - METADATA_LINT_BITS)); + blockLengthFract = + (FIXP_DBL)(blockLength << (DFRACT_BITS - 1 - METADATA_LINT_BITS)); + f = fDivNorm(sampleRateFract, blockLengthFract, &e_res); + f = scaleValue(f, e_res - METADATA_INT_BITS); /* convert to METADATA_FRACT */ + + /* product = t*f */ + product = fMultNorm(t, f, &e_res); + product = scaleValue( + product, e_res + METADATA_INT_BITS); /* convert to METADATA_FRACT */ + + /* exponent = (-1.0/((t) * (f))) */ + exponent = fDivNorm(METADATA_FRACT_SCALE, product, &e_res); + exponent = scaleValue( + exponent, e_res - METADATA_INT_BITS); /* convert to METADATA_FRACT */ + + /* exponent * ld(e) */ + exponent = fMult(exponent, FIXP_ILOG2_DIV2) << 1; /* e^(x) = 2^(x*ld(e)) */ + + /* exp(-1.0/((t) * (f))) */ + result = f2Pow(-exponent, DFRACT_BITS - 1 - METADATA_FRACT_BITS, &e_res); + + /* result = 1.0 - exp(-1.0/((t) * (f))) */ + result = (FIXP_DBL)MAXVAL_DBL - scaleValue(result, e_res); + + return result; +} + +static void findPeakLevels(HDRC_COMP drcComp, const INT_PCM* const inSamples, + const FIXP_DBL clev, const FIXP_DBL slev, + const FIXP_DBL ext_leva, const FIXP_DBL ext_levb, + const FIXP_DBL lfe_lev, const FIXP_DBL dmxGain5, + const FIXP_DBL dmxGain2, FIXP_DBL peak[2]) { + int i, c; + FIXP_DBL tmp = FL2FXCONST_DBL(0.f); + INT_PCM maxSample = 0; + + /* find peak level */ + peak[0] = peak[1] = FL2FXCONST_DBL(0.f); + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + /* single channels */ + for (c = 0; c < (int)drcComp->channels; c++) { + maxSample = fMax(maxSample, (INT_PCM)fAbs(pSamples[c])); + } + } + peak[0] = fixMax(peak[0], FX_PCM2FX_DBL(maxSample) >> DOWNMIX_SHIFT); + + /* 7.1/6.1 to 5.1 downmixes */ + if (drcComp->fullChannels > 5) { + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + /* channel 1 (L, Ls,...) */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lrs / Lss */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + (DOWNMIX_SHIFT - 1); /* L */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lvh */ + break; + default: + break; + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* channel 2 (R, Rs,...) */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rrs / Rss */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + (DOWNMIX_SHIFT - 1); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rvh */ + break; + default: + break; + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* channel 3 (C) */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + DOWNMIX_SHIFT); /* C */ + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc */ + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc */ + break; + default: + break; + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + } /* for (blocklength) */ + + /* take downmix gain into accout */ + peak[0] = fMult(dmxGain5, peak[0]) + << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + + /* 7.1 / 5.1 to stereo downmixes */ + if (drcComp->fullChannels > 2) { + /* Lt/Rt downmix */ + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + /* Lt */ + tmp = FL2FXCONST_DBL(0.f); + if (drcComp->channelIdx[LS] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >> + (DOWNMIX_SHIFT - 1); /* Ls2 */ + if (drcComp->channelIdx[RS] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >> + (DOWNMIX_SHIFT - 1); /* Rs2 */ + if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]]) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]]) >> + DOWNMIX_SHIFT); /* L */ + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* Rt */ + tmp = FL2FXCONST_DBL(0.f); + if (drcComp->channelIdx[LS] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >> + (DOWNMIX_SHIFT - 1); /* Ls2 */ + if (drcComp->channelIdx[RS] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >> + (DOWNMIX_SHIFT - 1); /* Rs2 */ + if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]]) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]]) >> + DOWNMIX_SHIFT); /* R */ + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + } + + /* Lo/Ro downmix */ + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + /* Lo */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lrs / Lss*/ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc */ + tmp += fMultDiv2(fMult(ext_leva, clev), + (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc - second path*/ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + (DOWNMIX_SHIFT - 1); /* L */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lvh */ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + default: + if (drcComp->channelIdx[LS] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >> + (DOWNMIX_SHIFT - 1); /* Ls2 */ + if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp += + fMultDiv2(slev, + fMult(FL2FXCONST_DBL(0.7f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]])) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += + fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + if (drcComp->channelIdx[3] >= 0) + tmp += fMultDiv2(lfe_lev, + (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]]) >> + DOWNMIX_SHIFT); /* L */ + break; + } + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* Ro */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rrs / Rss*/ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc */ + tmp += fMultDiv2(fMult(ext_leva, clev), + (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc - second path*/ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + (DOWNMIX_SHIFT - 1); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rvh */ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + default: + if (drcComp->channelIdx[RS] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >> + (DOWNMIX_SHIFT - 1); /* Rs2 */ + if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp += + fMultDiv2(slev, + fMult(FL2FXCONST_DBL(0.7f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]])) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += + fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + if (drcComp->channelIdx[3] >= 0) + tmp += fMultDiv2(lfe_lev, + (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]]) >> + DOWNMIX_SHIFT); /* R */ + } + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + } + } + + peak[1] = fixMax(peak[0], peak[1]); + + /* Mono Downmix - for comp_val only */ + if (drcComp->fullChannels > 1) { + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMult(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lrs / Lss*/ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rrs / Rss*/ + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc */ + tmp += fMultDiv2(fMult(ext_leva, clev), + (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc - second path*/ + tmp += fMultDiv2(fMult(ext_leva, clev), + (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc - second path*/ + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + (DOWNMIX_SHIFT - 1); /* L */ + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + (DOWNMIX_SHIFT - 1); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lvh */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rvh */ + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + default: + if (drcComp->channelIdx[LS] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >> + (DOWNMIX_SHIFT - 1); /* Ls2 */ + if (drcComp->channelIdx[RS] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >> + (DOWNMIX_SHIFT - 1); /* Rs2 */ + if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + /*if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp *=0.707f;*/ /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp += + fMultDiv2(slev, + fMult(FL2FXCONST_DBL(0.7f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]])) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C (2*clev) */ + if (drcComp->channelIdx[3] >= 0) + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]]) >> + DOWNMIX_SHIFT); /* R */ + } + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[1] = fixMax(peak[1], fixp_abs(tmp)); + } + } +} + +INT FDK_DRC_Generator_Open(HDRC_COMP* phDrcComp) { + INT err = 0; + HDRC_COMP hDcComp = NULL; + + if (phDrcComp == NULL) { + err = -1; + goto bail; + } + + /* allocate memory */ + hDcComp = (HDRC_COMP)FDKcalloc(1, sizeof(DRC_COMP)); + + if (hDcComp == NULL) { + err = -1; + goto bail; + } + + FDKmemclear(hDcComp, sizeof(DRC_COMP)); + + /* Return drc compressor instance */ + *phDrcComp = hDcComp; + return err; +bail: + FDK_DRC_Generator_Close(&hDcComp); + return err; +} + +INT FDK_DRC_Generator_Close(HDRC_COMP* phDrcComp) { + if (phDrcComp == NULL) { + return -1; + } + if (*phDrcComp != NULL) { + FDKfree(*phDrcComp); + *phDrcComp = NULL; + } + return 0; +} + +INT FDK_DRC_Generator_Initialize(HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF, + const INT blockLength, const UINT sampleRate, + const CHANNEL_MODE channelMode, + const CHANNEL_ORDER channelOrder, + const UCHAR useWeighting) { + int i; + CHANNEL_MAPPING channelMapping; + + drcComp->limDecay = + FL2FXCONST_DBL(((0.006f / 256) * blockLength) / METADATA_INT_SCALE); + + /* Save parameters. */ + drcComp->blockLength = blockLength; + drcComp->sampleRate = sampleRate; + drcComp->chanConfig = channelMode; + drcComp->useWeighting = useWeighting; + + if (FDK_DRC_Generator_setDrcProfile(drcComp, profileLine, profileRF) != + 0) { /* expects initialized blockLength and sampleRate */ + return (-1); + } + + /* Set number of channels and channel offsets. */ + if (FDKaacEnc_InitChannelMapping(channelMode, channelOrder, + &channelMapping) != AAC_ENC_OK) { + return (-2); + } + + for (i = 0; i < 9; i++) drcComp->channelIdx[i] = -1; + + switch (channelMode) { + case MODE_1: /* mono */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + break; + case MODE_2: /* stereo */ + drcComp->channelIdx[L] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[0].ChannelIndex[1]; + break; + case MODE_1_2: /* 3ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + break; + case MODE_1_2_1: /* 4ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[S] = channelMapping.elInfo[2].ChannelIndex[0]; + break; + case MODE_1_2_2: /* 5ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0]; + drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1]; + break; + case MODE_1_2_2_1: /* 5.1 ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[LFE] = channelMapping.elInfo[3].ChannelIndex[0]; + drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0]; + drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1]; + break; + case MODE_1_2_2_2_1: /* 7.1 ch */ + case MODE_7_1_FRONT_CENTER: + drcComp->channelIdx[L] = channelMapping.elInfo[2].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[2].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = + channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = + channelMapping.elInfo[3].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS] = + channelMapping.elInfo[3].ChannelIndex[1]; /* rs */ + drcComp->channelIdx[LS2] = + channelMapping.elInfo[1].ChannelIndex[0]; /* lc */ + drcComp->channelIdx[RS2] = + channelMapping.elInfo[1].ChannelIndex[1]; /* rc */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = + channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = + channelMapping.elInfo[3].ChannelIndex[0]; /* lrear */ + drcComp->channelIdx[RS] = + channelMapping.elInfo[3].ChannelIndex[1]; /* rrear */ + drcComp->channelIdx[LS2] = + channelMapping.elInfo[2].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS2] = + channelMapping.elInfo[2].ChannelIndex[1]; /* rs */ + break; + case MODE_6_1: + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = + channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = + channelMapping.elInfo[2].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS] = + channelMapping.elInfo[2].ChannelIndex[1]; /* rs */ + drcComp->channelIdx[S] = channelMapping.elInfo[3].ChannelIndex[0]; /* s */ + break; + case MODE_7_1_TOP_FRONT: + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = + channelMapping.elInfo[3].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = + channelMapping.elInfo[2].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS] = + channelMapping.elInfo[2].ChannelIndex[1]; /* rs */ + drcComp->channelIdx[LS2] = + channelMapping.elInfo[4].ChannelIndex[0]; /* lvh2 */ + drcComp->channelIdx[RS2] = + channelMapping.elInfo[4].ChannelIndex[1]; /* rvh2 */ + break; + default: + return (-1); + } + + drcComp->fullChannels = channelMapping.nChannelsEff; + drcComp->channels = channelMapping.nChannels; + + /* Init states. */ + drcComp->smoothLevel[0] = drcComp->smoothLevel[1] = + (FIXP_DBL)(-(135 << METADATA_FRACT_BITS)); + + FDKmemclear(drcComp->smoothGain, sizeof(drcComp->smoothGain)); + FDKmemclear(drcComp->holdCnt, sizeof(drcComp->holdCnt)); + FDKmemclear(drcComp->limGain, sizeof(drcComp->limGain)); + FDKmemclear(drcComp->prevPeak, sizeof(drcComp->prevPeak)); + FDKmemclear(drcComp->filter, sizeof(drcComp->filter)); + + return (0); +} + +INT FDK_DRC_Generator_setDrcProfile(HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF) { + int profileIdx, i; + + drcComp->profile[0] = profileLine; + drcComp->profile[1] = profileRF; + + for (i = 0; i < 2; i++) { + /* get profile index */ + switch (drcComp->profile[i]) { + case DRC_NONE: + case DRC_NOT_PRESENT: + case DRC_FILMSTANDARD: + profileIdx = 0; + break; + case DRC_FILMLIGHT: + profileIdx = 1; + break; + case DRC_MUSICSTANDARD: + profileIdx = 2; + break; + case DRC_MUSICLIGHT: + profileIdx = 3; + break; + case DRC_SPEECH: + profileIdx = 4; + break; + case DRC_DELAY_TEST: + profileIdx = 5; + break; + default: + return (-1); + } + + /* get parameters for selected profile */ + if (profileIdx >= 0) { + drcComp->maxBoostThr[i] = tabMaxBoostThr[profileIdx]; + drcComp->boostThr[i] = tabBoostThr[profileIdx]; + drcComp->earlyCutThr[i] = tabEarlyCutThr[profileIdx]; + drcComp->cutThr[i] = tabCutThr[profileIdx]; + drcComp->maxCutThr[i] = tabMaxCutThr[profileIdx]; + + drcComp->boostFac[i] = tabBoostRatio[profileIdx]; + drcComp->earlyCutFac[i] = tabEarlyCutRatio[profileIdx]; + drcComp->cutFac[i] = tabCutRatio[profileIdx]; + + drcComp->maxBoost[i] = tabMaxBoost[profileIdx]; + drcComp->maxCut[i] = tabMaxCut[profileIdx]; + drcComp->maxEarlyCut[i] = + -fMult((drcComp->cutThr[i] - drcComp->earlyCutThr[i]), + drcComp->earlyCutFac[i]); /* no scaling after mult needed, + earlyCutFac is in FIXP_DBL */ + + drcComp->fastAttack[i] = tc2Coeff( + tabFastAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->fastDecay[i] = tc2Coeff( + tabFastDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->slowAttack[i] = tc2Coeff( + tabSlowAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->slowDecay[i] = tc2Coeff( + tabSlowDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->holdOff[i] = tabHoldOff[profileIdx] * 256 / drcComp->blockLength; + + drcComp->attackThr[i] = tabAttackThr[profileIdx]; + drcComp->decayThr[i] = tabDecayThr[profileIdx]; + } + + drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f); + } + return (0); +} + +INT FDK_DRC_Generator_Calc(HDRC_COMP drcComp, const INT_PCM* const inSamples, + const UINT inSamplesBufSize, const INT dialnorm, + const INT drc_TargetRefLevel, + const INT comp_TargetRefLevel, const FIXP_DBL clev, + const FIXP_DBL slev, const FIXP_DBL ext_leva, + const FIXP_DBL ext_levb, const FIXP_DBL lfe_lev, + const INT dmxGain5, const INT dmxGain2, + INT* const pDynrng, INT* const pCompr) { + int i, c; + FIXP_DBL peak[2]; + + /************************************************************************** + * compressor + **************************************************************************/ + if ((drcComp->profile[0] != DRC_NONE) || (drcComp->profile[1] != DRC_NONE)) { + /* Calc loudness level */ + FIXP_DBL level_b = FL2FXCONST_DBL(0.f); + int level_e = DFRACT_BITS - 1; + + /* Increase energy time resolution with shorter processing blocks. 16 is an + * empiric value. */ + const int granuleLength = fixMin(16, drcComp->blockLength); + + if (drcComp->useWeighting) { + FIXP_DBL x1, x2, y, y1, y2; + /* sum of filter coefficients about 2.5 -> squared value is 6.25 + WEIGHTING_FILTER_SHIFT is 2 -> scaling about 16, therefore reduce + granuleShift by 1. + */ + const int granuleShift = getShiftFactor(granuleLength) - 1; + + for (c = 0; c < (int)drcComp->channels; c++) { + const INT_PCM* pSamples = inSamples + c * inSamplesBufSize; + + if (c == drcComp->channelIdx[LFE]) { + continue; /* skip LFE */ + } + + /* get filter states */ + x1 = drcComp->filter[c].x1; + x2 = drcComp->filter[c].x2; + y1 = drcComp->filter[c].y1; + y2 = drcComp->filter[c].y2; + + i = 0; + + do { + int offset = i; + FIXP_DBL accu = FL2FXCONST_DBL(0.f); + + for (i = offset; + i < fixMin(offset + granuleLength, drcComp->blockLength); i++) { + /* apply weighting filter */ + FIXP_DBL x = + FX_PCM2FX_DBL((FIXP_PCM)pSamples[i]) >> WEIGHTING_FILTER_SHIFT; + + /* y = b0 * (x - x2) - a1 * y1 - a2 * y2; */ + y = fMult(b0, x - x2) - fMult(a1, y1) - fMult(a2, y2); + + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + + accu += fPow2Div2(y) >> (granuleShift - 1); /* partial energy */ + } /* i */ + + fixpAdd(accu, granuleShift + 2 * WEIGHTING_FILTER_SHIFT, &level_b, + &level_e); /* sup up partial energies */ + + } while (i < drcComp->blockLength); + + /* save filter states */ + drcComp->filter[c].x1 = x1; + drcComp->filter[c].x2 = x2; + drcComp->filter[c].y1 = y1; + drcComp->filter[c].y2 = y2; + } /* c */ + } /* weighting */ + else { + const int granuleShift = getShiftFactor(granuleLength); + + for (c = 0; c < (int)drcComp->channels; c++) { + const INT_PCM* pSamples = inSamples + c * inSamplesBufSize; + + if ((int)c == drcComp->channelIdx[LFE]) { + continue; /* skip LFE */ + } + + i = 0; + + do { + int offset = i; + FIXP_DBL accu = FL2FXCONST_DBL(0.f); + + for (i = offset; + i < fixMin(offset + granuleLength, drcComp->blockLength); i++) { + /* partial energy */ + accu += fPow2Div2((FIXP_PCM)pSamples[i]) >> (granuleShift - 1); + } /* i */ + + fixpAdd(accu, granuleShift, &level_b, + &level_e); /* sup up partial energies */ + + } while (i < drcComp->blockLength); + } + } /* weighting */ + + /* + * Convert to dBFS, apply dialnorm + */ + /* level scaling */ + + /* descaled level in ld64 representation */ + FIXP_DBL ldLevel = + CalcLdData(level_b) + + (FIXP_DBL)((level_e - 12) << (DFRACT_BITS - 1 - LD_DATA_SHIFT)) - + CalcLdData((FIXP_DBL)(drcComp->blockLength << (DFRACT_BITS - 1 - 12))); + + /* if (level < 1e-10) level = 1e-10f; */ + ldLevel = + fMax(ldLevel, FL2FXCONST_DBL(-0.51905126482615036685473741085772f)); + + /* level = 10 * log(level)/log(10) + 3; + * = 10*log(2)/log(10) * ld(level) + 3; + * = 10 * 0.30102999566398119521373889472449 * ld(level) + 3 + * = 10 * (0.30102999566398119521373889472449 * ld(level) + 0.3) + * = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) + * * 64 + * + * additional scaling with METADATA_FRACT_BITS: + * = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) + * * 64 * 2^(METADATA_FRACT_BITS) = 10 * (0.30102999566398119521373889472449 + * * ld64(level) + 0.3/64) * 2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) = + * 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * ( + * 0.30102999566398119521373889472449 * ld64(level) + 0.3/64 ) + * */ + FIXP_DBL level = fMult( + (FIXP_DBL)(10 << (METADATA_FRACT_BITS + LD_DATA_SHIFT)), + fMult(FL2FXCONST_DBL(0.30102999566398119521373889472449f), ldLevel) + + (FIXP_DBL)(FL2FXCONST_DBL(0.3f) >> LD_DATA_SHIFT)); + + /* level -= dialnorm + 31 */ /* this is fixed to Dolby-ReferenceLevel as + compressor profiles are defined relative to + this */ + level -= ((FIXP_DBL)(dialnorm << (METADATA_FRACT_BITS - 16)) + + (FIXP_DBL)(31 << METADATA_FRACT_BITS)); + + for (i = 0; i < 2; i++) { + if (drcComp->profile[i] == DRC_NONE) { + /* no compression */ + drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f); + } else { + FIXP_DBL gain, alpha, lvl2smthlvl; + + /* calc static gain */ + if (level <= drcComp->maxBoostThr[i]) { + /* max boost */ + gain = drcComp->maxBoost[i]; + } else if (level < drcComp->boostThr[i]) { + /* boost range */ + gain = fMult((level - drcComp->boostThr[i]), drcComp->boostFac[i]); + } else if (level <= drcComp->earlyCutThr[i]) { + /* null band */ + gain = FL2FXCONST_DBL(0.f); + } else if (level <= drcComp->cutThr[i]) { + /* early cut range */ + gain = + fMult((level - drcComp->earlyCutThr[i]), drcComp->earlyCutFac[i]); + } else if (level < drcComp->maxCutThr[i]) { + /* cut range */ + gain = fMult((level - drcComp->cutThr[i]), drcComp->cutFac[i]) - + drcComp->maxEarlyCut[i]; + } else { + /* max cut */ + gain = -drcComp->maxCut[i]; + } + + /* choose time constant */ + lvl2smthlvl = level - drcComp->smoothLevel[i]; + if (gain < drcComp->smoothGain[i]) { + /* attack */ + if (lvl2smthlvl > drcComp->attackThr[i]) { + /* fast attack */ + alpha = drcComp->fastAttack[i]; + } else { + /* slow attack */ + alpha = drcComp->slowAttack[i]; + } + } else { + /* release */ + if (lvl2smthlvl < -drcComp->decayThr[i]) { + /* fast release */ + alpha = drcComp->fastDecay[i]; + } else { + /* slow release */ + alpha = drcComp->slowDecay[i]; + } + } + + /* smooth gain & level */ + if ((gain < drcComp->smoothGain[i]) || + (drcComp->holdCnt[i] == + 0)) { /* hold gain unless we have an attack or hold + period is over */ + FIXP_DBL accu; + + /* drcComp->smoothLevel[i] = (1-alpha) * drcComp->smoothLevel[i] + + * alpha * level; */ + accu = fMult(((FIXP_DBL)MAXVAL_DBL - alpha), drcComp->smoothLevel[i]); + accu += fMult(alpha, level); + drcComp->smoothLevel[i] = accu; + + /* drcComp->smoothGain[i] = (1-alpha) * drcComp->smoothGain[i] + + * alpha * gain; */ + accu = fMult(((FIXP_DBL)MAXVAL_DBL - alpha), drcComp->smoothGain[i]); + accu += fMult(alpha, gain); + drcComp->smoothGain[i] = accu; + } + + /* hold counter */ + if (drcComp->holdCnt[i]) { + drcComp->holdCnt[i]--; + } + if (gain < drcComp->smoothGain[i]) { + drcComp->holdCnt[i] = drcComp->holdOff[i]; + } + } /* profile != DRC_NONE */ + } /* for i=1..2 */ + } else { + /* no compression */ + drcComp->smoothGain[0] = FL2FXCONST_DBL(0.f); + drcComp->smoothGain[1] = FL2FXCONST_DBL(0.f); + } + + /************************************************************************** + * limiter + **************************************************************************/ + + findPeakLevels(drcComp, inSamples, clev, slev, ext_leva, ext_levb, lfe_lev, + (FIXP_DBL)((LONG)(dmxGain5) << (METADATA_FRACT_BITS - 16)), + (FIXP_DBL)((LONG)(dmxGain2) << (METADATA_FRACT_BITS - 16)), + peak); + + for (i = 0; i < 2; i++) { + FIXP_DBL tmp = drcComp->prevPeak[i]; + drcComp->prevPeak[i] = peak[i]; + peak[i] = fixMax(peak[i], tmp); + + /* + * Convert to dBFS, apply dialnorm + */ + /* descaled peak in ld64 representation */ + FIXP_DBL ld_peak = + CalcLdData(peak[i]) + + (FIXP_DBL)((LONG)DOWNMIX_SHIFT << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + + /* if (peak < 1e-6) level = 1e-6f; */ + ld_peak = + fMax(ld_peak, FL2FXCONST_DBL(-0.31143075889569022011284244651463f)); + + /* peak[i] = 20 * log(peak[i])/log(10) + 0.2f + + * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) peak[i] = 20 * + * log(2)/log(10) * ld(peak[i]) + 0.2f + + * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) peak[i] = 10 * + * 2*0.30102999566398119521373889472449 * ld(peak[i]) + 0.2f + + * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) + * + * additional scaling with METADATA_FRACT_BITS: + * peak[i] = (10 * 2*0.30102999566398119521373889472449 * ld64(peak[i]) * 64 + * + 0.2f + + * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS))*2^(-METADATA_FRACT_BITS) + * peak[i] = 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * + * 2*0.30102999566398119521373889472449 * ld64(peak[i]) + * + 0.2f*2^(-METADATA_FRACT_BITS) + drcComp->smoothGain[i] + */ + peak[i] = fMult( + (FIXP_DBL)(10 << (METADATA_FRACT_BITS + LD_DATA_SHIFT)), + fMult(FL2FX_DBL(2 * 0.30102999566398119521373889472449f), ld_peak)); + peak[i] += + (FL2FX_DBL(0.5f) >> METADATA_INT_BITS); /* add a little bit headroom */ + peak[i] += drcComp->smoothGain[i]; + } + + /* peak -= dialnorm + 31; */ /* this is Dolby style only */ + peak[0] -= (FIXP_DBL)((dialnorm - drc_TargetRefLevel) + << (METADATA_FRACT_BITS - + 16)); /* peak[0] -= dialnorm - drc_TargetRefLevel */ + + /* peak += 11; */ + /* this is Dolby style only */ /* RF mode output is 11dB higher */ + /*peak += comp_TargetRefLevel - drc_TargetRefLevel;*/ + peak[1] -= + (FIXP_DBL)((dialnorm - comp_TargetRefLevel) + << (METADATA_FRACT_BITS - + 16)); /* peak[1] -= dialnorm - comp_TargetRefLevel */ + + /* limiter gain */ + drcComp->limGain[0] += drcComp->limDecay; /* linear limiter release */ + drcComp->limGain[0] = fixMin(drcComp->limGain[0], -peak[0]); + + drcComp->limGain[1] += 2 * drcComp->limDecay; /* linear limiter release */ + drcComp->limGain[1] = fixMin(drcComp->limGain[1], -peak[1]); + + /*************************************************************************/ + + /* apply limiting, return DRC gains*/ + { + FIXP_DBL tmp; + + tmp = drcComp->smoothGain[0]; + if (drcComp->limGain[0] < FL2FXCONST_DBL(0.f)) { + tmp += drcComp->limGain[0]; + } + *pDynrng = (LONG)scaleValue(tmp, -(METADATA_FRACT_BITS - 16)); + + tmp = drcComp->smoothGain[1]; + if (drcComp->limGain[1] < FL2FXCONST_DBL(0.f)) { + tmp += drcComp->limGain[1]; + } + *pCompr = (LONG)scaleValue(tmp, -(METADATA_FRACT_BITS - 16)); + } + + return 0; +} + +DRC_PROFILE FDK_DRC_Generator_getDrcProfile(const HDRC_COMP drcComp) { + return drcComp->profile[0]; +} + +DRC_PROFILE FDK_DRC_Generator_getCompProfile(const HDRC_COMP drcComp) { + return drcComp->profile[1]; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_compressor.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_compressor.h new file mode 100644 index 0000000000000..1d0aa42f942ce --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_compressor.h @@ -0,0 +1,255 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Neusinger + + Description: Compressor for AAC Metadata Generator + +*******************************************************************************/ + +#ifndef METADATA_COMPRESSOR_H +#define METADATA_COMPRESSOR_H + +#include "FDK_audio.h" +#include "common_fix.h" + +#include "aacenc.h" + +#define LFE_LEV_SCALE 2 + +/** + * DRC compression profiles. + */ +typedef enum DRC_PROFILE { + DRC_NONE = 0, + DRC_FILMSTANDARD = 1, + DRC_FILMLIGHT = 2, + DRC_MUSICSTANDARD = 3, + DRC_MUSICLIGHT = 4, + DRC_SPEECH = 5, + DRC_DELAY_TEST = 6, + DRC_NOT_PRESENT = -2 + +} DRC_PROFILE; + +/** + * DRC Compressor handle. + */ +typedef struct DRC_COMP DRC_COMP, *HDRC_COMP; + +/** + * \brief Open a DRC Compressor instance. + * + * Allocate memory for a compressor instance. + * + * \param phDrcComp A pointer to a compressor handle. Initialized on + * return. + * + * \return + * - 0, on succes. + * - unequal 0, on failure. + */ +INT FDK_DRC_Generator_Open(HDRC_COMP *phDrcComp); + +/** + * \brief Close the DRC Compressor instance. + * + * Deallocate instance and free whole memory. + * + * \param phDrcComp Pointer to the compressor handle to be + * deallocated. + * + * \return + * - 0, on succes. + * - unequal 0, on failure. + */ +INT FDK_DRC_Generator_Close(HDRC_COMP *phDrcComp); + +/** + * \brief Configure DRC Compressor. + * + * \param drcComp Compressor handle. + * \param profileLine DRC profile for line mode. + * \param profileRF DRC profile for RF mode. + * \param blockLength Length of processing block in samples per + * channel. + * \param sampleRate Sampling rate in Hz. + * \param channelMode Channel configuration. + * \param channelOrder Channel order, MPEG or WAV. + * \param useWeighting Use weighting filter for loudness calculation + * + * \return + * - 0, on success, + * - unequal 0, on failure + */ +INT FDK_DRC_Generator_Initialize(HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF, + const INT blockLength, const UINT sampleRate, + const CHANNEL_MODE channelMode, + const CHANNEL_ORDER channelOrder, + const UCHAR useWeighting); + +/** + * \brief Calculate DRC Compressor Gain. + * + * \param drcComp Compressor handle. + * \param inSamples Pointer to interleaved input audio samples. + * \param inSamplesBufSize Size of inSamples for one channel. + * \param dialnorm Dialog Level in dB (typically -31...-1). + * \param drc_TargetRefLevel + * \param comp_TargetRefLevel + * \param clev Downmix center mix factor (typically 0.707, + * 0.595 or 0.5) + * \param slev Downmix surround mix factor (typically 0.707, + * 0.5, or 0) + * \param ext_leva Downmix gain factor A + * \param ext_levb Downmix gain factor B + * \param lfe_lev LFE gain factor + * \param dmxGain5 Gain factor for downmix to 5 channels + * \param dmxGain2 Gain factor for downmix to 2 channels + * \param dynrng Pointer to variable receiving line mode DRC gain + * in dB + * \param compr Pointer to variable receiving RF mode DRC gain + * in dB + * + * \return + * - 0, on success, + * - unequal 0, on failure + */ +INT FDK_DRC_Generator_Calc(HDRC_COMP drcComp, const INT_PCM *const inSamples, + const UINT inSamplesBufSize, const INT dialnorm, + const INT drc_TargetRefLevel, + const INT comp_TargetRefLevel, const FIXP_DBL clev, + const FIXP_DBL slev, const FIXP_DBL ext_leva, + const FIXP_DBL ext_levb, const FIXP_DBL lfe_lev, + const INT dmxGain5, const INT dmxGain2, + INT *const dynrng, INT *const compr); + +/** + * \brief Configure DRC Compressor Profile. + * + * \param drcComp Compressor handle. + * \param profileLine DRC profile for line mode. + * \param profileRF DRC profile for RF mode. + * + * \return + * - 0, on success, + * - unequal 0, on failure + */ +INT FDK_DRC_Generator_setDrcProfile(HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF); + +/** + * \brief Get DRC profile for line mode. + * + * \param drcComp Compressor handle. + * + * \return Current Profile. + */ +DRC_PROFILE FDK_DRC_Generator_getDrcProfile(const HDRC_COMP drcComp); + +/** + * \brief Get DRC profile for RF mode. + * + * \param drcComp Compressor handle. + * + * \return Current Profile. + */ +DRC_PROFILE FDK_DRC_Generator_getCompProfile(const HDRC_COMP drcComp); + +#endif /* METADATA_COMPRESSOR_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_main.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_main.cpp new file mode 100644 index 0000000000000..ada4502982377 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_main.cpp @@ -0,0 +1,1191 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): V. Bacigalupo + + Description: Metadata Encoder library interface functions + +*******************************************************************************/ + +#include "metadata_main.h" +#include "metadata_compressor.h" +#include "FDK_bitstream.h" +#include "FDK_audio.h" +#include "genericStds.h" + +/*----------------- defines ----------------------*/ +#define MAX_DRC_BANDS (1 << 4) +#define MAX_DRC_FRAMELEN (2 * 1024) +#define MAX_DELAY_FRAMES (3) + +/*--------------- structure definitions --------------------*/ + +typedef struct AAC_METADATA { + /* MPEG: Dynamic Range Control */ + struct { + UCHAR prog_ref_level_present; + SCHAR prog_ref_level; + + UCHAR dyn_rng_sgn[MAX_DRC_BANDS]; + UCHAR dyn_rng_ctl[MAX_DRC_BANDS]; + + UCHAR drc_bands_present; + UCHAR drc_band_incr; + UCHAR drc_band_top[MAX_DRC_BANDS]; + UCHAR drc_interpolation_scheme; + AACENC_METADATA_DRC_PROFILE drc_profile; + INT drc_TargetRefLevel; /* used for Limiter */ + + /* excluded channels */ + UCHAR excluded_chns_present; + UCHAR exclude_mask[2]; /* MAX_NUMBER_CHANNELS/8 */ + } mpegDrc; + + /* ETSI: addtl ancillary data */ + struct { + /* Heavy Compression */ + UCHAR compression_on; /* flag, if compression value should be written */ + UCHAR compression_value; /* compression value */ + AACENC_METADATA_DRC_PROFILE comp_profile; + INT comp_TargetRefLevel; /* used for Limiter */ + INT timecode_coarse_status; + INT timecode_fine_status; + + UCHAR extAncDataStatus; + + struct { + UCHAR ext_downmix_lvl_status; + UCHAR ext_downmix_gain_status; + UCHAR ext_lfe_downmix_status; + UCHAR + ext_dmix_a_idx; /* extended downmix level (0..7, according to table) + */ + UCHAR + ext_dmix_b_idx; /* extended downmix level (0..7, according to table) + */ + UCHAR dmx_gain_5_sgn; + UCHAR dmx_gain_5_idx; + UCHAR dmx_gain_2_sgn; + UCHAR dmx_gain_2_idx; + UCHAR ext_dmix_lfe_idx; /* extended downmix level for lfe (0..15, + according to table) */ + + } extAncData; + + } etsiAncData; + + SCHAR centerMixLevel; /* center downmix level (0...7, according to table) */ + SCHAR + surroundMixLevel; /* surround downmix level (0...7, according to table) */ + UCHAR WritePCEMixDwnIdx; /* flag */ + UCHAR DmxLvl_On; /* flag */ + + UCHAR dolbySurroundMode; + UCHAR drcPresentationMode; + + UCHAR + metadataMode; /* indicate meta data mode in current frame (delay line) */ + +} AAC_METADATA; + +typedef struct FDK_METADATA_ENCODER { + INT metadataMode; + HDRC_COMP hDrcComp; + AACENC_MetaData submittedMetaData; + + INT nAudioDataDelay; /* Additional delay to round up to next frame border (in + samples) */ + INT nMetaDataDelay; /* Meta data delay (in frames) */ + INT nChannels; + CHANNEL_MODE channelMode; + + INT_PCM* pAudioDelayBuffer; + + AAC_METADATA metaDataBuffer[MAX_DELAY_FRAMES]; + INT metaDataDelayIdx; + + UCHAR drcInfoPayload[12]; + UCHAR drcDsePayload[8]; + + INT matrix_mixdown_idx; + + AACENC_EXT_PAYLOAD exPayload[2]; + INT nExtensions; + + UINT maxChannels; /* Maximum number of audio channels to be supported. */ + + INT finalizeMetaData; /* Delay switch off by one frame and write default + configuration to finalize the metadata setup. */ + INT initializeMetaData; /* Fill up delay line with first meta data info. This + is required to have meta data already in first + frame. */ +} FDK_METADATA_ENCODER; + +/*---------------- constants -----------------------*/ +static const AACENC_MetaData defaultMetaDataSetup = { + AACENC_METADATA_DRC_NONE, /* drc_profile */ + AACENC_METADATA_DRC_NOT_PRESENT, /* comp_profile */ + -(31 << 16), /* drc_TargetRefLevel */ + -(23 << 16), /* comp_TargetRefLevel */ + 0, /* prog_ref_level_present */ + -(23 << 16), /* prog_ref_level */ + 0, /* PCE_mixdown_idx_present */ + 0, /* ETSI_DmxLvl_present */ + 0, /* centerMixLevel */ + 0, /* surroundMixLevel */ + 0, /* dolbySurroundMode */ + 0, /* drcPresentationMode */ + {0, 0, 0, 0, 0, 0, 0, 0, 0} /* ExtMetaData */ +}; + +static const FIXP_DBL dmxTable[8] = { + ((FIXP_DBL)MAXVAL_DBL), FL2FXCONST_DBL(0.841f), FL2FXCONST_DBL(0.707f), + FL2FXCONST_DBL(0.596f), FL2FXCONST_DBL(0.500f), FL2FXCONST_DBL(0.422f), + FL2FXCONST_DBL(0.355f), FL2FXCONST_DBL(0.000f)}; + +#define FL2DMXLFE(a) FL2FXCONST_DBL((a) / (1 << LFE_LEV_SCALE)) +static const FIXP_DBL dmxLfeTable[16] = { + FL2DMXLFE(3.162f), FL2DMXLFE(2.000f), FL2DMXLFE(1.679f), FL2DMXLFE(1.413f), + FL2DMXLFE(1.189f), FL2DMXLFE(1.000f), FL2DMXLFE(0.841f), FL2DMXLFE(0.707f), + FL2DMXLFE(0.596f), FL2DMXLFE(0.500f), FL2DMXLFE(0.316f), FL2DMXLFE(0.178f), + FL2DMXLFE(0.100f), FL2DMXLFE(0.032f), FL2DMXLFE(0.010f), FL2DMXLFE(0.000f)}; + +static const UCHAR surmix2matrix_mixdown_idx[8] = {0, 0, 0, 1, 1, 2, 2, 3}; + +/*--------------- function declarations --------------------*/ +static FDK_METADATA_ERROR WriteMetadataPayload( + const HANDLE_FDK_METADATA_ENCODER hMetaData, + const AAC_METADATA* const pMetadata); + +static INT WriteDynamicRangeInfoPayload(const AAC_METADATA* const pMetadata, + UCHAR* const pExtensionPayload); + +static INT WriteEtsiAncillaryDataPayload(const AAC_METADATA* const pMetadata, + UCHAR* const pExtensionPayload); + +static FDK_METADATA_ERROR CompensateAudioDelay( + HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples, + const UINT audioSamplesBufSize, const INT nAudioSamples); + +static FDK_METADATA_ERROR LoadSubmittedMetadata( + const AACENC_MetaData* const hMetadata, const INT nChannels, + const INT metadataMode, AAC_METADATA* const pAacMetaData); + +static FDK_METADATA_ERROR ProcessCompressor(AAC_METADATA* pMetadata, + HDRC_COMP hDrcComp, + const INT_PCM* const pSamples, + const UINT samplesBufSize, + const INT nSamples); + +/*------------- function definitions ----------------*/ + +static DRC_PROFILE convertProfile(AACENC_METADATA_DRC_PROFILE aacProfile) { + DRC_PROFILE drcProfile = DRC_NONE; + + switch (aacProfile) { + case AACENC_METADATA_DRC_NONE: + drcProfile = DRC_NONE; + break; + case AACENC_METADATA_DRC_FILMSTANDARD: + drcProfile = DRC_FILMSTANDARD; + break; + case AACENC_METADATA_DRC_FILMLIGHT: + drcProfile = DRC_FILMLIGHT; + break; + case AACENC_METADATA_DRC_MUSICSTANDARD: + drcProfile = DRC_MUSICSTANDARD; + break; + case AACENC_METADATA_DRC_MUSICLIGHT: + drcProfile = DRC_MUSICLIGHT; + break; + case AACENC_METADATA_DRC_SPEECH: + drcProfile = DRC_SPEECH; + break; + case AACENC_METADATA_DRC_NOT_PRESENT: + drcProfile = DRC_NOT_PRESENT; + break; + default: + drcProfile = DRC_NONE; + break; + } + return drcProfile; +} + +/* convert dialog normalization to program reference level */ +/* NOTE: this only is correct, if the decoder target level is set to -31dB for + * line mode / -20dB for RF mode */ +static UCHAR dialnorm2progreflvl(const INT d) { + return ((UCHAR)fMax(0, fMin((-d + (1 << 13)) >> 14, 127))); +} + +/* convert program reference level to dialog normalization */ +static INT progreflvl2dialnorm(const UCHAR p) { + return -((INT)(p << (16 - 2))); +} + +/* encode downmix levels to Downmixing_levels_MPEG4 */ +static SCHAR encodeDmxLvls(const SCHAR cmixlev, const SCHAR surmixlev) { + SCHAR dmxLvls = 0; + dmxLvls |= 0x80 | (cmixlev << 4); /* center_mix_level_on */ + dmxLvls |= 0x08 | surmixlev; /* surround_mix_level_on */ + + return dmxLvls; +} + +/* encode AAC DRC gain (ISO/IEC 14496-3:2005 4.5.2.7) */ +static void encodeDynrng(INT gain, UCHAR* const dyn_rng_ctl, + UCHAR* const dyn_rng_sgn) { + if (gain < 0) { + *dyn_rng_sgn = 1; + gain = -gain; + } else { + *dyn_rng_sgn = 0; + } + gain = fMin(gain, (127 << 14)); + + *dyn_rng_ctl = (UCHAR)((gain + (1 << 13)) >> 14); +} + +/* decode AAC DRC gain (ISO/IEC 14496-3:2005 4.5.2.7) */ +static INT decodeDynrng(const UCHAR dyn_rng_ctl, const UCHAR dyn_rng_sgn) { + INT tmp = ((INT)dyn_rng_ctl << (16 - 2)); + if (dyn_rng_sgn) tmp = -tmp; + + return tmp; +} + +/* encode AAC compression value (ETSI TS 101 154 page 99) */ +static UCHAR encodeCompr(INT gain) { + UCHAR x, y; + INT tmp; + + /* tmp = (int)((48.164f - gain) / 6.0206f * 15 + 0.5f); */ + tmp = ((3156476 - gain) * 15 + 197283) / 394566; + + if (tmp >= 240) { + return 0xFF; + } else if (tmp < 0) { + return 0; + } else { + x = tmp / 15; + y = tmp % 15; + } + + return (x << 4) | y; +} + +/* decode AAC compression value (ETSI TS 101 154 page 99) */ +static INT decodeCompr(const UCHAR compr) { + INT gain; + SCHAR x = compr >> 4; /* 4 MSB of compr */ + UCHAR y = (compr & 0x0F); /* 4 LSB of compr */ + + /* gain = (INT)((48.164f - 6.0206f * x - 0.4014f * y) ); */ + gain = (INT)( + scaleValue((FIXP_DBL)(((LONG)FL2FXCONST_DBL(6.0206f / 128.f) * (8 - x) - + (LONG)FL2FXCONST_DBL(0.4014f / 128.f) * y)), + -(DFRACT_BITS - 1 - 7 - 16))); + + return gain; +} + +FDK_METADATA_ERROR FDK_MetadataEnc_Open(HANDLE_FDK_METADATA_ENCODER* phMetaData, + const UINT maxChannels) { + FDK_METADATA_ERROR err = METADATA_OK; + HANDLE_FDK_METADATA_ENCODER hMetaData = NULL; + + if (phMetaData == NULL) { + err = METADATA_INVALID_HANDLE; + goto bail; + } + + /* allocate memory */ + if (NULL == (hMetaData = (HANDLE_FDK_METADATA_ENCODER)FDKcalloc( + 1, sizeof(FDK_METADATA_ENCODER)))) { + err = METADATA_MEMORY_ERROR; + goto bail; + } + FDKmemclear(hMetaData, sizeof(FDK_METADATA_ENCODER)); + + if (NULL == (hMetaData->pAudioDelayBuffer = (INT_PCM*)FDKcalloc( + maxChannels * MAX_DRC_FRAMELEN, sizeof(INT_PCM)))) { + err = METADATA_MEMORY_ERROR; + goto bail; + } + FDKmemclear(hMetaData->pAudioDelayBuffer, + maxChannels * MAX_DRC_FRAMELEN * sizeof(INT_PCM)); + hMetaData->maxChannels = maxChannels; + + /* Allocate DRC Compressor. */ + if (FDK_DRC_Generator_Open(&hMetaData->hDrcComp) != 0) { + err = METADATA_MEMORY_ERROR; + goto bail; + } + hMetaData->channelMode = MODE_UNKNOWN; + + /* Return metadata instance */ + *phMetaData = hMetaData; + + return err; + +bail: + FDK_MetadataEnc_Close(&hMetaData); + return err; +} + +FDK_METADATA_ERROR FDK_MetadataEnc_Close( + HANDLE_FDK_METADATA_ENCODER* phMetaData) { + FDK_METADATA_ERROR err = METADATA_OK; + + if (phMetaData == NULL) { + err = METADATA_INVALID_HANDLE; + goto bail; + } + + if (*phMetaData != NULL) { + FDK_DRC_Generator_Close(&(*phMetaData)->hDrcComp); + FDKfree((*phMetaData)->pAudioDelayBuffer); + FDKfree(*phMetaData); + *phMetaData = NULL; + } +bail: + return err; +} + +FDK_METADATA_ERROR FDK_MetadataEnc_Init( + HANDLE_FDK_METADATA_ENCODER hMetaData, const INT resetStates, + const INT metadataMode, const INT audioDelay, const UINT frameLength, + const UINT sampleRate, const UINT nChannels, const CHANNEL_MODE channelMode, + const CHANNEL_ORDER channelOrder) { + FDK_METADATA_ERROR err = METADATA_OK; + int i, nFrames, delay; + + if (hMetaData == NULL) { + err = METADATA_INVALID_HANDLE; + goto bail; + } + + /* Determine values for delay compensation. */ + for (nFrames = 0, delay = audioDelay - (INT)frameLength; delay > 0; + delay -= (INT)frameLength, nFrames++) + ; + + if ((nChannels > (8)) || (nChannels > hMetaData->maxChannels) || + ((-delay) > MAX_DRC_FRAMELEN) || nFrames >= MAX_DELAY_FRAMES) { + err = METADATA_INIT_ERROR; + goto bail; + } + + /* Initialize with default setup. */ + FDKmemcpy(&hMetaData->submittedMetaData, &defaultMetaDataSetup, + sizeof(AACENC_MetaData)); + + hMetaData->finalizeMetaData = + 0; /* finalize meta data only while on/off switching, else disabled */ + hMetaData->initializeMetaData = + 0; /* fill up meta data delay line only at a reset otherwise disabled */ + + /* Reset delay lines. */ + if (resetStates || (hMetaData->nAudioDataDelay != -delay) || + (hMetaData->channelMode != channelMode)) { + if (resetStates || (hMetaData->channelMode == MODE_UNKNOWN)) { + /* clear delay buffer */ + FDKmemclear(hMetaData->pAudioDelayBuffer, + hMetaData->maxChannels * MAX_DRC_FRAMELEN * sizeof(INT_PCM)); + } else { + /* if possible, keep static audio channels for seamless channel + * reconfiguration */ + FDK_channelMapDescr mapDescrPrev, mapDescr; + int c, src[2] = {-1, -1}, dst[2] = {-1, -1}; + + if (channelOrder == CH_ORDER_WG4) { + FDK_chMapDescr_init(&mapDescrPrev, FDK_mapInfoTabWg4, + FDK_mapInfoTabLenWg4, 0); + FDK_chMapDescr_init(&mapDescr, FDK_mapInfoTabWg4, + FDK_mapInfoTabLenWg4, 0); + } else { + FDK_chMapDescr_init(&mapDescrPrev, NULL, 0, + (channelOrder == CH_ORDER_MPEG) ? 1 : 0); + FDK_chMapDescr_init(&mapDescr, NULL, 0, + (channelOrder == CH_ORDER_MPEG) ? 1 : 0); + } + + switch (channelMode) { + case MODE_1: + if ((INT)nChannels != 2) { + /* preserve center channel */ + src[0] = FDK_chMapDescr_getMapValue(&mapDescrPrev, 0, + hMetaData->channelMode); + dst[0] = FDK_chMapDescr_getMapValue(&mapDescr, 0, channelMode); + } + break; + case MODE_2: + case MODE_1_2: + case MODE_1_2_1: + case MODE_1_2_2: + case MODE_1_2_2_1: + if (hMetaData->nChannels >= 2) { + /* preserve left/right channel */ + src[0] = FDK_chMapDescr_getMapValue( + &mapDescrPrev, ((hMetaData->channelMode == 2) ? 0 : 1), + hMetaData->channelMode); + src[1] = FDK_chMapDescr_getMapValue( + &mapDescrPrev, ((hMetaData->channelMode == 2) ? 1 : 2), + hMetaData->channelMode); + dst[0] = FDK_chMapDescr_getMapValue( + &mapDescr, ((channelMode == 2) ? 0 : 1), channelMode); + dst[1] = FDK_chMapDescr_getMapValue( + &mapDescr, ((channelMode == 2) ? 1 : 2), channelMode); + } + break; + default:; + } + C_ALLOC_SCRATCH_START(scratch_audioDelayBuffer, INT_PCM, (8)); + FDKmemclear(scratch_audioDelayBuffer, (8) * sizeof(INT_PCM)); + + i = (hMetaData->nChannels > (INT)nChannels) + ? 0 + : hMetaData->nAudioDataDelay - 1; + do { + for (c = 0; c < 2; c++) { + if (src[c] != -1 && dst[c] != -1) { + scratch_audioDelayBuffer[dst[c]] = + hMetaData->pAudioDelayBuffer[i * hMetaData->nChannels + src[c]]; + } + } + FDKmemcpy(&hMetaData->pAudioDelayBuffer[i * nChannels], + scratch_audioDelayBuffer, nChannels * sizeof(INT_PCM)); + i += (hMetaData->nChannels > (INT)nChannels) ? 1 : -1; + } while ((i < hMetaData->nAudioDataDelay) && (i >= 0)); + + C_ALLOC_SCRATCH_END(scratch_audioDelayBuffer, INT_PCM, (8)); + } + FDKmemclear(hMetaData->metaDataBuffer, sizeof(hMetaData->metaDataBuffer)); + hMetaData->metaDataDelayIdx = 0; + hMetaData->initializeMetaData = + 1; /* fill up delay line with first meta data info */ + } else { + /* Enable meta data. */ + if ((hMetaData->metadataMode == 0) && (metadataMode != 0)) { + /* disable meta data in all delay lines */ + for (i = 0; + i < (int)(sizeof(hMetaData->metaDataBuffer) / sizeof(AAC_METADATA)); + i++) { + LoadSubmittedMetadata(&hMetaData->submittedMetaData, nChannels, 0, + &hMetaData->metaDataBuffer[i]); + } + } + + /* Disable meta data.*/ + if ((hMetaData->metadataMode != 0) && (metadataMode == 0)) { + hMetaData->finalizeMetaData = hMetaData->metadataMode; + } + } + + /* Initialize delay. */ + hMetaData->nAudioDataDelay = -delay; + hMetaData->nMetaDataDelay = nFrames; + hMetaData->nChannels = nChannels; + hMetaData->channelMode = channelMode; + hMetaData->metadataMode = metadataMode; + + /* Initialize compressor. */ + if ((metadataMode == 1) || (metadataMode == 2)) { + if (FDK_DRC_Generator_Initialize(hMetaData->hDrcComp, DRC_NONE, DRC_NONE, + frameLength, sampleRate, channelMode, + channelOrder, 1) != 0) { + err = METADATA_INIT_ERROR; + } + } +bail: + return err; +} + +static FDK_METADATA_ERROR ProcessCompressor(AAC_METADATA* pMetadata, + HDRC_COMP hDrcComp, + const INT_PCM* const pSamples, + const UINT samplesBufSize, + const INT nSamples) { + FDK_METADATA_ERROR err = METADATA_OK; + + INT dynrng, compr; + INT dmxGain5, dmxGain2; + DRC_PROFILE profileDrc; + DRC_PROFILE profileComp; + + if ((pMetadata == NULL) || (hDrcComp == NULL)) { + err = METADATA_INVALID_HANDLE; + return err; + } + + profileDrc = convertProfile(pMetadata->mpegDrc.drc_profile); + profileComp = convertProfile(pMetadata->etsiAncData.comp_profile); + + /* first, check if profile is same as last frame + * otherwise, update setup */ + if ((profileDrc != FDK_DRC_Generator_getDrcProfile(hDrcComp)) || + (profileComp != FDK_DRC_Generator_getCompProfile(hDrcComp))) { + FDK_DRC_Generator_setDrcProfile(hDrcComp, profileDrc, profileComp); + } + + /* Sanity check */ + if (profileComp == DRC_NONE) { + pMetadata->etsiAncData.compression_value = 0x80; /* to ensure no external + values will be written + if not configured */ + } + + /* in case of embedding external values, copy this now (limiter may overwrite + * them) */ + dynrng = decodeDynrng(pMetadata->mpegDrc.dyn_rng_ctl[0], + pMetadata->mpegDrc.dyn_rng_sgn[0]); + compr = decodeCompr(pMetadata->etsiAncData.compression_value); + + dmxGain5 = decodeDynrng(pMetadata->etsiAncData.extAncData.dmx_gain_5_idx, + pMetadata->etsiAncData.extAncData.dmx_gain_5_sgn); + dmxGain2 = decodeDynrng(pMetadata->etsiAncData.extAncData.dmx_gain_2_idx, + pMetadata->etsiAncData.extAncData.dmx_gain_2_sgn); + + /* Call compressor */ + if (FDK_DRC_Generator_Calc( + hDrcComp, pSamples, samplesBufSize, + progreflvl2dialnorm(pMetadata->mpegDrc.prog_ref_level), + pMetadata->mpegDrc.drc_TargetRefLevel, + pMetadata->etsiAncData.comp_TargetRefLevel, + dmxTable[pMetadata->centerMixLevel], + dmxTable[pMetadata->surroundMixLevel], + dmxTable[pMetadata->etsiAncData.extAncData.ext_dmix_a_idx], + dmxTable[pMetadata->etsiAncData.extAncData.ext_dmix_b_idx], + pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status + ? dmxLfeTable[pMetadata->etsiAncData.extAncData.ext_dmix_lfe_idx] + : (FIXP_DBL)0, + dmxGain5, dmxGain2, &dynrng, &compr) != 0) { + err = METADATA_ENCODE_ERROR; + goto bail; + } + + /* Write DRC values */ + pMetadata->mpegDrc.drc_band_incr = 0; + encodeDynrng(dynrng, pMetadata->mpegDrc.dyn_rng_ctl, + pMetadata->mpegDrc.dyn_rng_sgn); + pMetadata->etsiAncData.compression_value = encodeCompr(compr); + +bail: + return err; +} + +FDK_METADATA_ERROR FDK_MetadataEnc_Process( + HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples, + const UINT audioSamplesBufSize, const INT nAudioSamples, + const AACENC_MetaData* const pMetadata, + AACENC_EXT_PAYLOAD** ppMetaDataExtPayload, UINT* nMetaDataExtensions, + INT* matrix_mixdown_idx) { + FDK_METADATA_ERROR err = METADATA_OK; + int metaDataDelayWriteIdx, metaDataDelayReadIdx, metadataMode; + + /* Where to write new meta data info */ + metaDataDelayWriteIdx = hMetaDataEnc->metaDataDelayIdx; + + /* How to write the data */ + metadataMode = hMetaDataEnc->metadataMode; + + /* Compensate meta data delay. */ + hMetaDataEnc->metaDataDelayIdx++; + if (hMetaDataEnc->metaDataDelayIdx > hMetaDataEnc->nMetaDataDelay) + hMetaDataEnc->metaDataDelayIdx = 0; + + /* Where to read pending meta data info from. */ + metaDataDelayReadIdx = hMetaDataEnc->metaDataDelayIdx; + + /* Submit new data if available. */ + if (pMetadata != NULL) { + FDKmemcpy(&hMetaDataEnc->submittedMetaData, pMetadata, + sizeof(AACENC_MetaData)); + } + + /* Write one additional frame with default configuration of meta data. Ensure + * defined behaviour on decoder side. */ + if ((hMetaDataEnc->finalizeMetaData != 0) && + (hMetaDataEnc->metadataMode == 0)) { + FDKmemcpy(&hMetaDataEnc->submittedMetaData, &defaultMetaDataSetup, + sizeof(AACENC_MetaData)); + metadataMode = hMetaDataEnc->finalizeMetaData; + hMetaDataEnc->finalizeMetaData = 0; + } + + /* Get last submitted data. */ + if ((err = LoadSubmittedMetadata( + &hMetaDataEnc->submittedMetaData, hMetaDataEnc->nChannels, + metadataMode, + &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx])) != + METADATA_OK) { + goto bail; + } + + /* Calculate compressor if necessary and updata meta data info */ + if ((hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx].metadataMode == 1) || + (hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx].metadataMode == 2)) { + if ((err = ProcessCompressor( + &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx], + hMetaDataEnc->hDrcComp, pAudioSamples, audioSamplesBufSize, + nAudioSamples)) != METADATA_OK) { + /* Get last submitted data again. */ + LoadSubmittedMetadata( + &hMetaDataEnc->submittedMetaData, hMetaDataEnc->nChannels, + metadataMode, &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx]); + } + } + + /* Fill up delay line with initial meta data info.*/ + if ((hMetaDataEnc->initializeMetaData != 0) && + (hMetaDataEnc->metadataMode != 0)) { + int i; + for (i = 0; + i < (int)(sizeof(hMetaDataEnc->metaDataBuffer) / sizeof(AAC_METADATA)); + i++) { + if (i != metaDataDelayWriteIdx) { + FDKmemcpy(&hMetaDataEnc->metaDataBuffer[i], + &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx], + sizeof(hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx])); + } + } + hMetaDataEnc->initializeMetaData = 0; + } + + /* Convert Meta Data side info to bitstream data. */ + FDK_ASSERT(metaDataDelayReadIdx < MAX_DELAY_FRAMES); + if ((err = WriteMetadataPayload( + hMetaDataEnc, + &hMetaDataEnc->metaDataBuffer[metaDataDelayReadIdx])) != + METADATA_OK) { + goto bail; + } + + /* Assign meta data to output */ + *ppMetaDataExtPayload = hMetaDataEnc->exPayload; + *nMetaDataExtensions = hMetaDataEnc->nExtensions; + *matrix_mixdown_idx = hMetaDataEnc->matrix_mixdown_idx; + +bail: + /* Compensate audio delay, reset err status. */ + err = CompensateAudioDelay(hMetaDataEnc, pAudioSamples, audioSamplesBufSize, + nAudioSamples / hMetaDataEnc->nChannels); + + return err; +} + +static FDK_METADATA_ERROR CompensateAudioDelay( + HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples, + const UINT audioSamplesBufSize, const INT nAudioSamples) { + FDK_METADATA_ERROR err = METADATA_OK; + + if (hMetaDataEnc->nAudioDataDelay) { + C_ALLOC_SCRATCH_START(scratch_audioDelayBuffer, INT_PCM, 1024); + + for (int c = 0; c < hMetaDataEnc->nChannels; c++) { + int M = 1024; + INT_PCM* pAudioSamples2 = pAudioSamples + c * audioSamplesBufSize; + int delayIdx = hMetaDataEnc->nAudioDataDelay; + + do { + M = fMin(M, delayIdx); + delayIdx -= M; + + FDKmemcpy(&scratch_audioDelayBuffer[0], + &pAudioSamples2[(nAudioSamples - M)], sizeof(INT_PCM) * M); + FDKmemmove(&pAudioSamples2[M], &pAudioSamples2[0], + sizeof(INT_PCM) * (nAudioSamples - M)); + FDKmemcpy( + &pAudioSamples2[0], + &hMetaDataEnc->pAudioDelayBuffer[delayIdx + + c * hMetaDataEnc->nAudioDataDelay], + sizeof(INT_PCM) * M); + FDKmemcpy( + &hMetaDataEnc->pAudioDelayBuffer[delayIdx + + c * hMetaDataEnc->nAudioDataDelay], + &scratch_audioDelayBuffer[0], sizeof(INT_PCM) * M); + + } while (delayIdx > 0); + } + + C_ALLOC_SCRATCH_END(scratch_audioDelayBuffer, INT_PCM, 1024); + } + + return err; +} + +/*----------------------------------------------------------------------------- + + functionname: WriteMetadataPayload + description: fills anc data and extension payload + returns: Error status + + ------------------------------------------------------------------------------*/ +static FDK_METADATA_ERROR WriteMetadataPayload( + const HANDLE_FDK_METADATA_ENCODER hMetaData, + const AAC_METADATA* const pMetadata) { + FDK_METADATA_ERROR err = METADATA_OK; + + if ((hMetaData == NULL) || (pMetadata == NULL)) { + err = METADATA_INVALID_HANDLE; + goto bail; + } + + hMetaData->nExtensions = 0; + hMetaData->matrix_mixdown_idx = -1; + + if (pMetadata->metadataMode != 0) { + /* AAC-DRC */ + if ((pMetadata->metadataMode == 1) || (pMetadata->metadataMode == 2)) { + hMetaData->exPayload[hMetaData->nExtensions].pData = + hMetaData->drcInfoPayload; + hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DYNAMIC_RANGE; + hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1; + + hMetaData->exPayload[hMetaData->nExtensions].dataSize = + WriteDynamicRangeInfoPayload( + pMetadata, hMetaData->exPayload[hMetaData->nExtensions].pData); + + hMetaData->nExtensions++; + } /* pMetadata->metadataMode==1 || pMetadata->metadataMode==2 */ + + /* Matrix Mixdown Coefficient in PCE */ + if (pMetadata->WritePCEMixDwnIdx) { + hMetaData->matrix_mixdown_idx = + surmix2matrix_mixdown_idx[pMetadata->surroundMixLevel]; + } + + /* ETSI TS 101 154 (DVB) - MPEG4 ancillary_data() */ + if ((pMetadata->metadataMode == 2) || + (pMetadata->metadataMode == 3)) /* MP4_METADATA_MPEG_ETSI */ + { + hMetaData->exPayload[hMetaData->nExtensions].pData = + hMetaData->drcDsePayload; + hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DATA_ELEMENT; + hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1; + + hMetaData->exPayload[hMetaData->nExtensions].dataSize = + WriteEtsiAncillaryDataPayload( + pMetadata, hMetaData->exPayload[hMetaData->nExtensions].pData); + + hMetaData->nExtensions++; + } /* metadataMode==2 || metadataMode==3 */ + + } /* metadataMode != 0 */ + +bail: + return err; +} + +static INT WriteDynamicRangeInfoPayload(const AAC_METADATA* const pMetadata, + UCHAR* const pExtensionPayload) { + const INT pce_tag_present = 0; /* yet fixed setting! */ + const INT prog_ref_lev_res_bits = 0; + INT i, drc_num_bands = 1; + + FDK_BITSTREAM bsWriter; + FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER); + + /* dynamic_range_info() */ + FDKwriteBits(&bsWriter, pce_tag_present, 1); /* pce_tag_present */ + if (pce_tag_present) { + FDKwriteBits(&bsWriter, 0x0, 4); /* pce_instance_tag */ + FDKwriteBits(&bsWriter, 0x0, 4); /* drc_tag_reserved_bits */ + } + + /* Exclude channels */ + FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.excluded_chns_present) ? 1 : 0, + 1); /* excluded_chns_present*/ + + /* Multiband DRC */ + FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.drc_bands_present) ? 1 : 0, + 1); /* drc_bands_present */ + if (pMetadata->mpegDrc.drc_bands_present) { + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_incr, + 4); /* drc_band_incr */ + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_interpolation_scheme, + 4); /* drc_interpolation_scheme */ + drc_num_bands += pMetadata->mpegDrc.drc_band_incr; + for (i = 0; i < drc_num_bands; i++) { + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_top[i], + 8); /* drc_band_top */ + } + } + + /* Program Reference Level */ + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level_present, + 1); /* prog_ref_level_present */ + if (pMetadata->mpegDrc.prog_ref_level_present) { + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level, + 7); /* prog_ref_level */ + FDKwriteBits(&bsWriter, prog_ref_lev_res_bits, + 1); /* prog_ref_level_reserved_bits */ + } + + /* DRC Values */ + for (i = 0; i < drc_num_bands; i++) { + FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.dyn_rng_sgn[i]) ? 1 : 0, + 1); /* dyn_rng_sgn[ */ + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.dyn_rng_ctl[i], + 7); /* dyn_rng_ctl */ + } + + /* return number of valid bits in extension payload. */ + return FDKgetValidBits(&bsWriter); +} + +static INT WriteEtsiAncillaryDataPayload(const AAC_METADATA* const pMetadata, + UCHAR* const pExtensionPayload) { + FDK_BITSTREAM bsWriter; + FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER); + + /* ancillary_data_sync */ + FDKwriteBits(&bsWriter, 0xBC, 8); + + /* bs_info */ + FDKwriteBits(&bsWriter, 0x3, 2); /* mpeg_audio_type */ + FDKwriteBits(&bsWriter, pMetadata->dolbySurroundMode, + 2); /* dolby_surround_mode */ + FDKwriteBits(&bsWriter, pMetadata->drcPresentationMode, + 2); /* DRC presentation mode */ + FDKwriteBits(&bsWriter, 0x0, 1); /* stereo_downmix_mode */ + FDKwriteBits(&bsWriter, 0x0, 1); /* reserved */ + + /* ancillary_data_status */ + FDKwriteBits(&bsWriter, 0, 3); /* 3 bit Reserved, set to "0" */ + FDKwriteBits(&bsWriter, (pMetadata->DmxLvl_On) ? 1 : 0, + 1); /* downmixing_levels_MPEG4_status */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncDataStatus, + 1); /* ext_anc_data_status */ + FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.compression_on) ? 1 : 0, + 1); /* audio_coding_mode_and_compression status */ + FDKwriteBits(&bsWriter, + (pMetadata->etsiAncData.timecode_coarse_status) ? 1 : 0, + 1); /* coarse_grain_timecode_status */ + FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.timecode_fine_status) ? 1 : 0, + 1); /* fine_grain_timecode_status */ + + /* downmixing_levels_MPEG4_status */ + if (pMetadata->DmxLvl_On) { + FDKwriteBits( + &bsWriter, + encodeDmxLvls(pMetadata->centerMixLevel, pMetadata->surroundMixLevel), + 8); + } + + /* audio_coding_mode_and_compression_status */ + if (pMetadata->etsiAncData.compression_on) { + FDKwriteBits(&bsWriter, 0x01, 8); /* audio coding mode */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.compression_value, + 8); /* compression value */ + } + + /* grain-timecode coarse/fine */ + if (pMetadata->etsiAncData.timecode_coarse_status) { + FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */ + } + + if (pMetadata->etsiAncData.timecode_fine_status) { + FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */ + } + + /* extended ancillary data structure */ + if (pMetadata->etsiAncData.extAncDataStatus) { + /* ext_ancillary_data_status */ + FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */ + FDKwriteBits(&bsWriter, + pMetadata->etsiAncData.extAncData.ext_downmix_lvl_status, + 1); /* ext_downmixing_levels_status */ + FDKwriteBits(&bsWriter, + pMetadata->etsiAncData.extAncData.ext_downmix_gain_status, + 1); /* ext_downmixing_global_gains_status */ + FDKwriteBits(&bsWriter, + pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status, + 1); /* ext_downmixing_lfe_level_status" */ + FDKwriteBits(&bsWriter, 0, 4); /* Reserved, set to "0" */ + + /* ext_downmixing_levels */ + if (pMetadata->etsiAncData.extAncData.ext_downmix_lvl_status) { + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.ext_dmix_a_idx, + 3); /* dmix_a_idx */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.ext_dmix_b_idx, + 3); /* dmix_b_idx */ + FDKwriteBits(&bsWriter, 0, 2); /* Reserved, set to "0" */ + } + + /* ext_downmixing_gains */ + if (pMetadata->etsiAncData.extAncData.ext_downmix_gain_status) { + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_5_sgn, + 1); /* dmx_gain_5_sign */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_5_idx, + 6); /* dmx_gain_5_idx */ + FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_2_sgn, + 1); /* dmx_gain_2_sign */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_2_idx, + 6); /* dmx_gain_2_idx */ + FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */ + } + + if (pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status) { + FDKwriteBits(&bsWriter, + pMetadata->etsiAncData.extAncData.ext_dmix_lfe_idx, + 4); /* dmix_lfe_idx */ + FDKwriteBits(&bsWriter, 0, 4); /* Reserved, set to "0" */ + } + } + + return FDKgetValidBits(&bsWriter); +} + +static FDK_METADATA_ERROR LoadSubmittedMetadata( + const AACENC_MetaData* const hMetadata, const INT nChannels, + const INT metadataMode, AAC_METADATA* const pAacMetaData) { + FDK_METADATA_ERROR err = METADATA_OK; + + if (pAacMetaData == NULL) { + err = METADATA_INVALID_HANDLE; + } else { + /* init struct */ + FDKmemclear(pAacMetaData, sizeof(AAC_METADATA)); + + if (hMetadata != NULL) { + /* convert data */ + pAacMetaData->mpegDrc.drc_profile = hMetadata->drc_profile; + pAacMetaData->etsiAncData.comp_profile = hMetadata->comp_profile; + pAacMetaData->mpegDrc.drc_TargetRefLevel = hMetadata->drc_TargetRefLevel; + pAacMetaData->etsiAncData.comp_TargetRefLevel = + hMetadata->comp_TargetRefLevel; + pAacMetaData->mpegDrc.prog_ref_level_present = + hMetadata->prog_ref_level_present; + pAacMetaData->mpegDrc.prog_ref_level = + dialnorm2progreflvl(hMetadata->prog_ref_level); + + pAacMetaData->centerMixLevel = hMetadata->centerMixLevel; + pAacMetaData->surroundMixLevel = hMetadata->surroundMixLevel; + pAacMetaData->WritePCEMixDwnIdx = hMetadata->PCE_mixdown_idx_present; + pAacMetaData->DmxLvl_On = hMetadata->ETSI_DmxLvl_present; + + pAacMetaData->etsiAncData.compression_on = + (hMetadata->comp_profile == AACENC_METADATA_DRC_NOT_PRESENT ? 0 : 1); + + if (pAacMetaData->mpegDrc.drc_profile == + AACENC_METADATA_DRC_NOT_PRESENT) { + pAacMetaData->mpegDrc.drc_profile = + AACENC_METADATA_DRC_NONE; /* MPEG DRC gains are + always present in BS + syntax */ + /* we should give a warning, but ErrorHandler does not support this */ + } + + if (nChannels == 2) { + pAacMetaData->dolbySurroundMode = + hMetadata->dolbySurroundMode; /* dolby_surround_mode */ + } else { + pAacMetaData->dolbySurroundMode = 0; + } + + pAacMetaData->drcPresentationMode = hMetadata->drcPresentationMode; + /* override external values if DVB DRC presentation mode is given */ + if (pAacMetaData->drcPresentationMode == 1) { + pAacMetaData->mpegDrc.drc_TargetRefLevel = + fMax(-(31 << 16), pAacMetaData->mpegDrc.drc_TargetRefLevel); + pAacMetaData->etsiAncData.comp_TargetRefLevel = fMax( + -(20 << 16), + pAacMetaData->etsiAncData.comp_TargetRefLevel); /* implies -23dB */ + } + if (pAacMetaData->drcPresentationMode == 2) { + pAacMetaData->mpegDrc.drc_TargetRefLevel = + fMax(-(23 << 16), pAacMetaData->mpegDrc.drc_TargetRefLevel); + pAacMetaData->etsiAncData.comp_TargetRefLevel = + fMax(-(23 << 16), pAacMetaData->etsiAncData.comp_TargetRefLevel); + } + if (pAacMetaData->etsiAncData.comp_profile == + AACENC_METADATA_DRC_NOT_PRESENT) { + /* DVB defines to revert to Light DRC if heavy is not present */ + if (pAacMetaData->drcPresentationMode != 0) { + /* we exclude the "not indicated" mode as this requires the user to + * define desired levels anyway */ + pAacMetaData->mpegDrc.drc_TargetRefLevel = + fMax(pAacMetaData->etsiAncData.comp_TargetRefLevel, + pAacMetaData->mpegDrc.drc_TargetRefLevel); + } + } + + pAacMetaData->etsiAncData.timecode_coarse_status = + 0; /* not yet supported - attention: Update + GetEstMetadataBytesPerFrame() if enable this! */ + pAacMetaData->etsiAncData.timecode_fine_status = + 0; /* not yet supported - attention: Update + GetEstMetadataBytesPerFrame() if enable this! */ + + /* extended ancillary data */ + pAacMetaData->etsiAncData.extAncDataStatus = + ((hMetadata->ExtMetaData.extAncDataEnable == 1) ? 1 : 0); + + if (pAacMetaData->etsiAncData.extAncDataStatus) { + pAacMetaData->etsiAncData.extAncData.ext_downmix_lvl_status = + (hMetadata->ExtMetaData.extDownmixLevelEnable ? 1 : 0); + pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status = + (hMetadata->ExtMetaData.dmxGainEnable ? 1 : 0); + pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status = + (hMetadata->ExtMetaData.lfeDmxEnable ? 1 : 0); + + pAacMetaData->etsiAncData.extAncData.ext_dmix_a_idx = + hMetadata->ExtMetaData.extDownmixLevel_A; + pAacMetaData->etsiAncData.extAncData.ext_dmix_b_idx = + hMetadata->ExtMetaData.extDownmixLevel_B; + + if (pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status) { + encodeDynrng(hMetadata->ExtMetaData.dmxGain5, + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx), + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn)); + encodeDynrng(hMetadata->ExtMetaData.dmxGain2, + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx), + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn)); + } else { + encodeDynrng(1 << 16, + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx), + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn)); + encodeDynrng(1 << 16, + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx), + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn)); + } + + if (pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status) { + pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx = + hMetadata->ExtMetaData.lfeDmxLevel; + } else { + pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx = + 15; /* -inf dB */ + } + } else { + pAacMetaData->etsiAncData.extAncData.ext_downmix_lvl_status = 0; + pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status = 0; + pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status = 0; + + pAacMetaData->etsiAncData.extAncData.ext_dmix_a_idx = 7; /* -inf dB */ + pAacMetaData->etsiAncData.extAncData.ext_dmix_b_idx = 7; /* -inf dB */ + + encodeDynrng(1 << 16, + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx), + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn)); + encodeDynrng(1 << 16, + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx), + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn)); + + pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx = + 15; /* -inf dB */ + } + + pAacMetaData->metadataMode = metadataMode; + } else { + pAacMetaData->metadataMode = 0; /* there is no configuration available */ + } + } + + return err; +} + +INT FDK_MetadataEnc_GetDelay(HANDLE_FDK_METADATA_ENCODER hMetadataEnc) { + INT delay = 0; + + if (hMetadataEnc != NULL) { + delay = hMetadataEnc->nAudioDataDelay; + } + + return delay; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_main.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_main.h new file mode 100644 index 0000000000000..d872c7790dfab --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/metadata_main.h @@ -0,0 +1,226 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): V. Bacigalupo + + Description: Metadata Encoder library interface functions + +*******************************************************************************/ + +#ifndef METADATA_MAIN_H +#define METADATA_MAIN_H + +/* Includes ******************************************************************/ +#include "aacenc_lib.h" +#include "aacenc.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ + +typedef enum { + METADATA_OK = 0x0000, /*!< No error happened. All fine. */ + METADATA_INVALID_HANDLE = + 0x0020, /*!< Handle passed to function call was invalid. */ + METADATA_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */ + METADATA_INIT_ERROR = 0x0040, /*!< General initialization error. */ + METADATA_ENCODE_ERROR = + 0x0060 /*!< The encoding process was interrupted by an unexpected error. + */ + +} FDK_METADATA_ERROR; + +/** + * Meta Data handle. + */ +typedef struct FDK_METADATA_ENCODER *HANDLE_FDK_METADATA_ENCODER; + +/** + * \brief Open a Meta Data instance. + * + * \param phMetadataEnc A pointer to a Meta Data handle to be allocated. + * Initialized on return. + * \param maxChannels Maximum number of supported audio channels. + * + * \return + * - METADATA_OK, on succes. + * - METADATA_INVALID_HANDLE, METADATA_MEMORY_ERROR, on failure. + */ +FDK_METADATA_ERROR FDK_MetadataEnc_Open( + HANDLE_FDK_METADATA_ENCODER *phMetadataEnc, const UINT maxChannels); + +/** + * \brief Initialize a Meta Data instance. + * + * \param hMetadataEnc Meta Data handle. + * \param resetStates Indication for full reset of all states. + * \param metadataMode Configures meta data output format (0,1,2,3). + * \param audioDelay Delay cause by the audio encoder. + * \param frameLength Number of samples to be processes within one + * frame. + * \param sampleRate Sampling rat in Hz of audio input signal. + * \param nChannels Number of audio input channels. + * \param channelMode Channel configuration which is used by the + * encoder. + * \param channelOrder Channel order of the input data. (WAV, MPEG) + * + * \return + * - METADATA_OK, on succes. + * - METADATA_INVALID_HANDLE, METADATA_INIT_ERROR, on failure. + */ +FDK_METADATA_ERROR FDK_MetadataEnc_Init( + HANDLE_FDK_METADATA_ENCODER hMetadataEnc, const INT resetStates, + const INT metadataMode, const INT audioDelay, const UINT frameLength, + const UINT sampleRate, const UINT nChannels, const CHANNEL_MODE channelMode, + const CHANNEL_ORDER channelOrder); + +/** + * \brief Calculate Meta Data processing. + * + * This function treats all step necessary for meta data processing. + * - Receive new meta data and make usable. + * - Calculate DRC compressor and extract meta data info. + * - Make meta data available for extern use. + * - Apply audio data and meta data delay compensation. + * + * \param hMetadataEnc Meta Data handle. + * \param pAudioSamples Pointer to audio input data. Existing function + * overwrites audio data with delayed audio samples. + * \param nAudioSamples Number of input audio samples to be prcessed. + * \param pMetadata Pointer to Metat Data input. + * \param ppMetaDataExtPayload Pointer to extension payload array. Filled on + * return. + * \param nMetaDataExtensions Pointer to variable to describe number of + * available extension payloads. Filled on return. + * \param matrix_mixdown_idx Pointer to variable for matrix mixdown + * coefficient. Filled on return. + * + * \return + * - METADATA_OK, on succes. + * - METADATA_INVALID_HANDLE, METADATA_ENCODE_ERROR, on failure. + */ +FDK_METADATA_ERROR FDK_MetadataEnc_Process( + HANDLE_FDK_METADATA_ENCODER hMetadataEnc, INT_PCM *const pAudioSamples, + const UINT audioSamplesBufSize, const INT nAudioSamples, + const AACENC_MetaData *const pMetadata, + AACENC_EXT_PAYLOAD **ppMetaDataExtPayload, UINT *nMetaDataExtensions, + INT *matrix_mixdown_idx); + +/** + * \brief Close the Meta Data instance. + * + * Deallocate instance and free whole memory. + * + * \param phMetaData Pointer to the Meta Data handle to be + * deallocated. + * + * \return + * - METADATA_OK, on succes. + * - METADATA_INVALID_HANDLE, on failure. + */ +FDK_METADATA_ERROR FDK_MetadataEnc_Close( + HANDLE_FDK_METADATA_ENCODER *phMetaData); + +/** + * \brief Get Meta Data Encoder delay. + * + * \param hMetadataEnc Meta Data Encoder handle. + * + * \return Delay caused by Meta Data module. + */ +INT FDK_MetadataEnc_GetDelay(HANDLE_FDK_METADATA_ENCODER hMetadataEnc); + +#endif /* METADATA_MAIN_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/mps_main.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/mps_main.cpp new file mode 100644 index 0000000000000..104822892d339 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/mps_main.cpp @@ -0,0 +1,529 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): Markus Lohwasser + + Description: Mpeg Surround library interface functions + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "mps_main.h" +#include "sacenc_lib.h" + +/* Data Types ****************************************************************/ +struct MPS_ENCODER { + HANDLE_MP4SPACE_ENCODER hSacEncoder; + + AUDIO_OBJECT_TYPE audioObjectType; + + FDK_bufDescr inBufDesc; + FDK_bufDescr outBufDesc; + SACENC_InArgs inargs; + SACENC_OutArgs outargs; + + void *pInBuffer[1]; + UINT pInBufferSize[1]; + UINT pInBufferElSize[1]; + UINT pInBufferType[1]; + + void *pOutBuffer[2]; + UINT pOutBufferSize[2]; + UINT pOutBufferElSize[2]; + UINT pOutBufferType[2]; + + UCHAR sacOutBuffer[1024]; /* Worst case memory consumption for ELDv2: 768 + bytes => 6144 bits (Core + SBR + MPS) */ +}; + +struct MPS_CONFIG_TAB { + AUDIO_OBJECT_TYPE audio_object_type; + CHANNEL_MODE channel_mode; + ULONG sbr_ratio; + ULONG sampling_rate; + ULONG bitrate_min; + ULONG bitrate_max; +}; + +/* Constants *****************************************************************/ +static const MPS_CONFIG_TAB mpsConfigTab[] = { + {AOT_ER_AAC_ELD, MODE_212, 0, 16000, 16000, 39999}, + {AOT_ER_AAC_ELD, MODE_212, 0, 22050, 16000, 49999}, + {AOT_ER_AAC_ELD, MODE_212, 0, 24000, 16000, 61999}, + {AOT_ER_AAC_ELD, MODE_212, 0, 32000, 20000, 84999}, + {AOT_ER_AAC_ELD, MODE_212, 0, 44100, 50000, 192000}, + {AOT_ER_AAC_ELD, MODE_212, 0, 48000, 62000, 192000}, + + {AOT_ER_AAC_ELD, MODE_212, 1, 16000, 18000, 31999}, + {AOT_ER_AAC_ELD, MODE_212, 1, 22050, 18000, 31999}, + {AOT_ER_AAC_ELD, MODE_212, 1, 24000, 20000, 64000}, + + {AOT_ER_AAC_ELD, MODE_212, 2, 32000, 18000, 64000}, + {AOT_ER_AAC_ELD, MODE_212, 2, 44100, 21000, 64000}, + {AOT_ER_AAC_ELD, MODE_212, 2, 48000, 26000, 64000} + +}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static INT FDK_MpegsEnc_WriteFrameHeader(HANDLE_MPS_ENCODER hMpsEnc, + UCHAR *const pOutputBuffer, + const int outputBufferSize); + +MPS_ENCODER_ERROR FDK_MpegsEnc_Open(HANDLE_MPS_ENCODER *phMpsEnc) { + MPS_ENCODER_ERROR error = MPS_ENCODER_OK; + HANDLE_MPS_ENCODER hMpsEnc = NULL; + + if (phMpsEnc == NULL) { + error = MPS_ENCODER_INVALID_HANDLE; + goto bail; + } + + if (NULL == + (hMpsEnc = (HANDLE_MPS_ENCODER)FDKcalloc(1, sizeof(MPS_ENCODER)))) { + error = MPS_ENCODER_MEMORY_ERROR; + goto bail; + } + FDKmemclear(hMpsEnc, sizeof(MPS_ENCODER)); + + if (SACENC_OK != FDK_sacenc_open(&hMpsEnc->hSacEncoder)) { + error = MPS_ENCODER_MEMORY_ERROR; + goto bail; + } + + /* Return mps encoder instance */ + *phMpsEnc = hMpsEnc; + +bail: + if (error != MPS_ENCODER_OK) { + FDK_MpegsEnc_Close(&hMpsEnc); + } + return error; +} + +MPS_ENCODER_ERROR FDK_MpegsEnc_Close(HANDLE_MPS_ENCODER *phMpsEnc) { + MPS_ENCODER_ERROR error = MPS_ENCODER_OK; + + if (phMpsEnc == NULL) { + error = MPS_ENCODER_INVALID_HANDLE; + goto bail; + } + + if (*phMpsEnc != NULL) { + FDK_sacenc_close(&(*phMpsEnc)->hSacEncoder); + FDKfree(*phMpsEnc); + *phMpsEnc = NULL; + } +bail: + return error; +} + +MPS_ENCODER_ERROR FDK_MpegsEnc_Init(HANDLE_MPS_ENCODER hMpsEnc, + const AUDIO_OBJECT_TYPE audioObjectType, + const UINT samplingrate, const UINT bitrate, + const UINT sbrRatio, const UINT framelength, + const UINT inputBufferSizePerChannel, + const UINT coreCoderDelay) { + MPS_ENCODER_ERROR error = MPS_ENCODER_OK; + const UINT fs_low = 27713; /* low MPS sampling frequencies */ + const UINT fs_high = 55426; /* high MPS sampling frequencies */ + UINT nTimeSlots = 0, nQmfBandsLd = 0; + + if (hMpsEnc == NULL) { + error = MPS_ENCODER_INVALID_HANDLE; + goto bail; + } + + /* Combine MPS with SBR only if the number of QMF band fits together.*/ + switch (sbrRatio) { + case 1: /* downsampled sbr - 32 QMF bands required */ + if (!(samplingrate < fs_low)) { + error = MPS_ENCODER_INIT_ERROR; + goto bail; + } + break; + case 2: /* dualrate - 64 QMF bands required */ + if (!((samplingrate >= fs_low) && (samplingrate < fs_high))) { + error = MPS_ENCODER_INIT_ERROR; + goto bail; + } + break; + case 0: + default:; /* time interface - no samplingrate restriction */ + } + + /* 32 QMF-Bands ( fs < 27713 ) + * 64 QMF-Bands ( 27713 >= fs <= 55426 ) + * 128 QMF-Bands ( fs > 55426 ) + */ + nQmfBandsLd = + (samplingrate < fs_low) ? 5 : ((samplingrate > fs_high) ? 7 : 6); + nTimeSlots = framelength >> nQmfBandsLd; + + /* check if number of qmf bands is usable for given framelength */ + if (framelength != (nTimeSlots << nQmfBandsLd)) { + error = MPS_ENCODER_INIT_ERROR; + goto bail; + } + + /* is given bitrate intended to be supported */ + if ((INT)bitrate != FDK_MpegsEnc_GetClosestBitRate(audioObjectType, MODE_212, + samplingrate, sbrRatio, + bitrate)) { + error = MPS_ENCODER_INIT_ERROR; + goto bail; + } + + /* init SAC library */ + switch (audioObjectType) { + case AOT_ER_AAC_ELD: { + const UINT noInterFrameCoding = 0; + + if ((SACENC_OK != + FDK_sacenc_setParam(hMpsEnc->hSacEncoder, SACENC_LOWDELAY, + (noInterFrameCoding == 1) ? 1 : 2)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_ENC_MODE, SACENC_212)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_SAMPLERATE, samplingrate)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_FRAME_TIME_SLOTS, + nTimeSlots)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_PARAM_BANDS, + SACENC_BANDS_15)) || + (SACENC_OK != + FDK_sacenc_setParam(hMpsEnc->hSacEncoder, SACENC_TIME_DOM_DMX, 2)) || + (SACENC_OK != + FDK_sacenc_setParam(hMpsEnc->hSacEncoder, SACENC_COARSE_QUANT, 0)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_QUANT_MODE, + SACENC_QUANTMODE_FINE)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_TIME_ALIGNMENT, 0)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_INDEPENDENCY_FACTOR, 20))) { + error = MPS_ENCODER_INIT_ERROR; + goto bail; + } + break; + } + default: + error = MPS_ENCODER_INIT_ERROR; + goto bail; + } + + if (SACENC_OK != FDK_sacenc_init(hMpsEnc->hSacEncoder, coreCoderDelay)) { + error = MPS_ENCODER_INIT_ERROR; + } + + hMpsEnc->audioObjectType = audioObjectType; + + hMpsEnc->inBufDesc.ppBase = (void **)&hMpsEnc->pInBuffer; + hMpsEnc->inBufDesc.pBufSize = hMpsEnc->pInBufferSize; + hMpsEnc->inBufDesc.pEleSize = hMpsEnc->pInBufferElSize; + hMpsEnc->inBufDesc.pBufType = hMpsEnc->pInBufferType; + hMpsEnc->inBufDesc.numBufs = 1; + + hMpsEnc->outBufDesc.ppBase = (void **)&hMpsEnc->pOutBuffer; + hMpsEnc->outBufDesc.pBufSize = hMpsEnc->pOutBufferSize; + hMpsEnc->outBufDesc.pEleSize = hMpsEnc->pOutBufferElSize; + hMpsEnc->outBufDesc.pBufType = hMpsEnc->pOutBufferType; + hMpsEnc->outBufDesc.numBufs = 2; + + hMpsEnc->pInBuffer[0] = NULL; + hMpsEnc->pInBufferSize[0] = 0; + hMpsEnc->pInBufferElSize[0] = sizeof(INT_PCM); + hMpsEnc->pInBufferType[0] = (FDK_BUF_TYPE_INPUT | FDK_BUF_TYPE_PCM_DATA); + + hMpsEnc->pOutBuffer[0] = NULL; + hMpsEnc->pOutBufferSize[0] = 0; + hMpsEnc->pOutBufferElSize[0] = sizeof(INT_PCM); + hMpsEnc->pOutBufferType[0] = (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA); + + hMpsEnc->pOutBuffer[1] = NULL; + hMpsEnc->pOutBufferSize[1] = 0; + hMpsEnc->pOutBufferElSize[1] = sizeof(UCHAR); + hMpsEnc->pOutBufferType[1] = (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_BS_DATA); + + hMpsEnc->inargs.isInputInterleaved = 0; + hMpsEnc->inargs.inputBufferSizePerChannel = inputBufferSizePerChannel; + +bail: + return error; +} + +MPS_ENCODER_ERROR FDK_MpegsEnc_Process(HANDLE_MPS_ENCODER hMpsEnc, + INT_PCM *const pAudioSamples, + const INT nAudioSamples, + AACENC_EXT_PAYLOAD *pMpsExtPayload) { + MPS_ENCODER_ERROR error = MPS_ENCODER_OK; + + if (hMpsEnc == NULL) { + error = MPS_ENCODER_INVALID_HANDLE; + } else { + int sacHeaderFlag = 1; + int sacOutBufferOffset = 0; + + /* In case of eld the ssc is explicit and doesn't need to be inband */ + if (hMpsEnc->audioObjectType == AOT_ER_AAC_ELD) { + sacHeaderFlag = 0; + } + + /* 4 bits nibble after extension type */ + hMpsEnc->sacOutBuffer[0] = (sacHeaderFlag == 0) ? 0x3 : 0x7; + sacOutBufferOffset += 1; + + if (sacHeaderFlag) { + sacOutBufferOffset += FDK_MpegsEnc_WriteFrameHeader( + hMpsEnc, &hMpsEnc->sacOutBuffer[sacOutBufferOffset], + sizeof(hMpsEnc->sacOutBuffer) - sacOutBufferOffset); + } + + /* Register input and output buffer. */ + hMpsEnc->pInBuffer[0] = (void *)pAudioSamples; + hMpsEnc->inargs.nInputSamples = nAudioSamples; + + hMpsEnc->pOutBuffer[0] = (void *)pAudioSamples; + hMpsEnc->pOutBufferSize[0] = sizeof(INT_PCM) * nAudioSamples / 2; + + hMpsEnc->pOutBuffer[1] = (void *)&hMpsEnc->sacOutBuffer[sacOutBufferOffset]; + hMpsEnc->pOutBufferSize[1] = + sizeof(hMpsEnc->sacOutBuffer) - sacOutBufferOffset; + + /* encode SAC frame */ + if (SACENC_OK != FDK_sacenc_encode(hMpsEnc->hSacEncoder, + &hMpsEnc->inBufDesc, + &hMpsEnc->outBufDesc, &hMpsEnc->inargs, + &hMpsEnc->outargs)) { + error = MPS_ENCODER_ENCODE_ERROR; + goto bail; + } + + /* export MPS payload */ + pMpsExtPayload->pData = (UCHAR *)hMpsEnc->sacOutBuffer; + pMpsExtPayload->dataSize = + hMpsEnc->outargs.nOutputBits + 8 * (sacOutBufferOffset - 1); + pMpsExtPayload->dataType = EXT_LDSAC_DATA; + pMpsExtPayload->associatedChElement = -1; + } + +bail: + return error; +} + +INT FDK_MpegsEnc_WriteSpatialSpecificConfig(HANDLE_MPS_ENCODER hMpsEnc, + HANDLE_FDK_BITSTREAM hBs) { + INT sscBits = 0; + + if (NULL != hMpsEnc) { + MP4SPACEENC_INFO mp4SpaceEncoderInfo; + FDK_sacenc_getInfo(hMpsEnc->hSacEncoder, &mp4SpaceEncoderInfo); + + if (hBs != NULL) { + int i; + int writtenBits = 0; + for (i = 0; inSscSizeBits>> 3; i++) { + FDKwriteBits(hBs, mp4SpaceEncoderInfo.pSscBuf->pSsc[i], 8); + writtenBits += 8; + } + FDKwriteBits(hBs, mp4SpaceEncoderInfo.pSscBuf->pSsc[i], + mp4SpaceEncoderInfo.pSscBuf->nSscSizeBits - writtenBits); + } /* hBS */ + + sscBits = mp4SpaceEncoderInfo.pSscBuf->nSscSizeBits; + + } /* valid hMpsEnc */ + + return sscBits; +} + +static INT FDK_MpegsEnc_WriteFrameHeader(HANDLE_MPS_ENCODER hMpsEnc, + UCHAR *const pOutputBuffer, + const int outputBufferSize) { + const int sacTimeAlignFlag = 0; + + /* Initialize variables */ + int numBits = 0; + + if ((NULL != hMpsEnc) && (NULL != pOutputBuffer)) { + UINT alignAnchor, cnt; + FDK_BITSTREAM Bs; + FDKinitBitStream(&Bs, pOutputBuffer, outputBufferSize, 0, BS_WRITER); + + /* Calculate SSC length information */ + cnt = (FDK_MpegsEnc_WriteSpatialSpecificConfig(hMpsEnc, NULL) + 7) >> 3; + + /* Write SSC */ + FDKwriteBits(&Bs, sacTimeAlignFlag, 1); + + if (cnt < 127) { + FDKwriteBits(&Bs, cnt, 7); + } else { + FDKwriteBits(&Bs, 127, 7); + FDKwriteBits(&Bs, cnt - 127, 16); + } + + alignAnchor = FDKgetValidBits(&Bs); + FDK_MpegsEnc_WriteSpatialSpecificConfig(hMpsEnc, &Bs); + FDKbyteAlign(&Bs, alignAnchor); /* bsFillBits */ + + if (sacTimeAlignFlag) { + FDK_ASSERT(1); /* time alignment not supported */ + } + + numBits = FDKgetValidBits(&Bs); + } /* valid handle */ + + return ((numBits + 7) >> 3); +} + +INT FDK_MpegsEnc_GetClosestBitRate(const AUDIO_OBJECT_TYPE audioObjectType, + const CHANNEL_MODE channelMode, + const UINT samplingrate, const UINT sbrRatio, + const UINT bitrate) { + unsigned int i; + int targetBitrate = -1; + + for (i = 0; i < sizeof(mpsConfigTab) / sizeof(MPS_CONFIG_TAB); i++) { + if ((mpsConfigTab[i].audio_object_type == audioObjectType) && + (mpsConfigTab[i].channel_mode == channelMode) && + (mpsConfigTab[i].sbr_ratio == sbrRatio) && + (mpsConfigTab[i].sampling_rate == samplingrate)) { + targetBitrate = fMin(fMax(bitrate, mpsConfigTab[i].bitrate_min), + mpsConfigTab[i].bitrate_max); + } + } + + return targetBitrate; +} + +INT FDK_MpegsEnc_GetDelay(HANDLE_MPS_ENCODER hMpsEnc) { + INT delay = 0; + + if (NULL != hMpsEnc) { + MP4SPACEENC_INFO mp4SpaceEncoderInfo; + FDK_sacenc_getInfo(hMpsEnc->hSacEncoder, &mp4SpaceEncoderInfo); + delay = mp4SpaceEncoderInfo.nCodecDelay; + } + + return delay; +} + +INT FDK_MpegsEnc_GetDecDelay(HANDLE_MPS_ENCODER hMpsEnc) { + INT delay = 0; + + if (NULL != hMpsEnc) { + MP4SPACEENC_INFO mp4SpaceEncoderInfo; + FDK_sacenc_getInfo(hMpsEnc->hSacEncoder, &mp4SpaceEncoderInfo); + delay = mp4SpaceEncoderInfo.nDecoderDelay; + } + + return delay; +} + +MPS_ENCODER_ERROR FDK_MpegsEnc_GetLibInfo(LIB_INFO *info) { + MPS_ENCODER_ERROR error = MPS_ENCODER_OK; + + if (NULL == info) { + error = MPS_ENCODER_INVALID_HANDLE; + } else if (SACENC_OK != FDK_sacenc_getLibInfo(info)) { + error = MPS_ENCODER_INIT_ERROR; + } + + return error; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/mps_main.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/mps_main.h new file mode 100644 index 0000000000000..f56678a1ebd8d --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/mps_main.h @@ -0,0 +1,270 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): Markus Lohwasser + + Description: Mpeg Surround library interface functions + +*******************************************************************************/ + +#ifndef MPS_MAIN_H +#define MPS_MAIN_H + +/* Includes ******************************************************************/ +#include "aacenc.h" +#include "FDK_audio.h" +#include "machine_type.h" + +/* Defines *******************************************************************/ +typedef enum { + MPS_ENCODER_OK = 0x0000, /*!< No error happened. All fine. */ + MPS_ENCODER_INVALID_HANDLE = + 0x0020, /*!< Handle passed to function call was invalid. */ + MPS_ENCODER_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */ + MPS_ENCODER_INIT_ERROR = 0x0040, /*!< General initialization error. */ + MPS_ENCODER_ENCODE_ERROR = + 0x0060 /*!< The encoding process was interrupted by an unexpected error. + */ + +} MPS_ENCODER_ERROR; + +/* Data Types ****************************************************************/ + +/** + * MPEG Surround Encoder interface handle. + */ +typedef struct MPS_ENCODER MPS_ENCODER, *HANDLE_MPS_ENCODER; + +/* Function / Class Declarations *********************************************/ + +/** + * \brief Open a Mpeg Surround Encoder instance. + * + * \phMpsEnc A pointer to a MPS handle to be allocated. + * Initialized on return. + * + * \return + * - MPS_ENCODER_OK, on succes. + * - MPS_ENCODER_INVALID_HANDLE, MPS_ENCODER_MEMORY_ERROR, on failure. + */ +MPS_ENCODER_ERROR FDK_MpegsEnc_Open(HANDLE_MPS_ENCODER *phMpsEnc); + +/** + * \brief Close the Mpeg Surround Encoder instance. + * + * Deallocate instance and free whole memory. + * + * \param phMpsEnc Pointer to the MPS handle to be deallocated. + * + * \return + * - MPS_ENCODER_OK, on succes. + * - MPS_ENCODER_INVALID_HANDLE, on failure. + */ +MPS_ENCODER_ERROR FDK_MpegsEnc_Close(HANDLE_MPS_ENCODER *phMpsEnc); + +/** + * \brief Initialize a Mpeg Surround Encoder instance. + * + * \param hMpsEnc MPS Encoder handle. + * \param audioObjectType Audio object type. + * \param samplingrate Sampling rate in Hz of audio input signal. + * \param bitrate Encder target bitrate. + * \param sbrRatio SBR sampling rate ratio. + * \param framelength Number of samples to be processes within one + * frame. + * \param inputBufferSizePerChannel Size of input buffer per channel. + * \param coreCoderDelay Core coder delay. + * + * \return + * - MPS_ENCODER_OK, on succes. + * - MPS_ENCODER_INVALID_HANDLE, MPS_ENCODER_ENCODE_ERROR, on failure. + */ +MPS_ENCODER_ERROR FDK_MpegsEnc_Init(HANDLE_MPS_ENCODER hMpsEnc, + const AUDIO_OBJECT_TYPE audioObjectType, + const UINT samplingrate, const UINT bitrate, + const UINT sbrRatio, const UINT framelength, + const UINT inputBufferSizePerChannel, + const UINT coreCoderDelay); + +/** + * \brief Calculate Mpeg Surround processing. + * + * This fuction applies the MPS processing. The MPS side info will be written to + * extension payload. The input audio data will be overwritten by the calculated + * downmix. + * + * \param hMpsEnc MPS Encoder handle. + * \param pAudioSamples Pointer to audio input/output data. + * \param nAudioSamples Number of input audio samples to be prcessed. + * \param pMpsExtPayload Pointer to extension payload to be filled on + * return. + * + * \return + * - MPS_ENCODER_OK, on succes. + * - MPS_ENCODER_INVALID_HANDLE, MPS_ENCODER_ENCODE_ERROR, on failure. + */ +MPS_ENCODER_ERROR FDK_MpegsEnc_Process(HANDLE_MPS_ENCODER hMpsEnc, + INT_PCM *const pAudioSamples, + const INT nAudioSamples, + AACENC_EXT_PAYLOAD *pMpsExtPayload); + +/** + * \brief Write Spatial Specific Config. + * + * This function can be called via call back from the transport library to write + * the Spatial Specific Config to given bitstream buffer. + * + * \param hMpsEnc MPS Encoder handle. + * \param hBs Bitstream buffer handle. + * + * \return Number of written bits. + */ +INT FDK_MpegsEnc_WriteSpatialSpecificConfig(HANDLE_MPS_ENCODER hMpsEnc, + HANDLE_FDK_BITSTREAM hBs); + +/** + * \brief Get closest valid bitrate supported by given config. + * + * \param audioObjectType Audio object type. + * \param channelMode Encoder channel mode. + * \param samplingrate Sampling rate in Hz of audio input signal. + * \param sbrRatio SBR sampling rate ratio. + * \param bitrate The desired target bitrate. + * + * \return Closest valid bitrate to given bitrate.. + */ +INT FDK_MpegsEnc_GetClosestBitRate(const AUDIO_OBJECT_TYPE audioObjectType, + const CHANNEL_MODE channelMode, + const UINT samplingrate, const UINT sbrRatio, + const UINT bitrate); + +/** + * \brief Get codec delay. + * + * This function returns delay of the whole en-/decoded signal, including + * corecoder delay. + * + * \param hMpsEnc MPS Encoder handle. + * + * \return Codec delay in samples. + */ +INT FDK_MpegsEnc_GetDelay(HANDLE_MPS_ENCODER hMpsEnc); + +/** + * \brief Get Mpeg Surround Decoder delay. + * + * This function returns delay of the Mpeg Surround decoder. + * + * \param hMpsEnc MPS Encoder handle. + * + * \return Mpeg Surround Decoder delay in samples. + */ +INT FDK_MpegsEnc_GetDecDelay(HANDLE_MPS_ENCODER hMpsEnc); + +/** + * \brief Get information about encoder library build. + * + * Fill a given LIB_INFO structure with library version information. + * + * \param info Pointer to an allocated LIB_INFO struct. + * + * \return + * - MPS_ENCODER_OK, on succes. + * - MPS_ENCODER_INVALID_HANDLE, MPS_ENCODER_INIT_ERROR, on failure. + */ +MPS_ENCODER_ERROR FDK_MpegsEnc_GetLibInfo(LIB_INFO *info); + +#endif /* MPS_MAIN_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/ms_stereo.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/ms_stereo.cpp new file mode 100644 index 0000000000000..6a121b212fd46 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/ms_stereo.cpp @@ -0,0 +1,295 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: MS stereo processing + +*******************************************************************************/ + +#include "ms_stereo.h" + +#include "psy_const.h" + +/* static const float scaleMinThres = 1.0f; */ /* 0.75f for 3db boost */ + +void FDKaacEnc_MsStereoProcessing(PSY_DATA *RESTRICT psyData[(2)], + PSY_OUT_CHANNEL *psyOutChannel[2], + const INT *isBook, INT *msDigest, /* output */ + INT *msMask, /* output */ + const INT allowMS, const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *sfbOffset) { + FIXP_DBL *sfbEnergyLeft = + psyData[0]->sfbEnergy.Long; /* modified where msMask==1 */ + FIXP_DBL *sfbEnergyRight = + psyData[1]->sfbEnergy.Long; /* modified where msMask==1 */ + const FIXP_DBL *sfbEnergyMid = psyData[0]->sfbEnergyMS.Long; + const FIXP_DBL *sfbEnergySide = psyData[1]->sfbEnergyMS.Long; + FIXP_DBL *sfbThresholdLeft = + psyData[0]->sfbThreshold.Long; /* modified where msMask==1 */ + FIXP_DBL *sfbThresholdRight = + psyData[1]->sfbThreshold.Long; /* modified where msMask==1 */ + + FIXP_DBL *sfbSpreadEnLeft = psyData[0]->sfbSpreadEnergy.Long; + FIXP_DBL *sfbSpreadEnRight = psyData[1]->sfbSpreadEnergy.Long; + + FIXP_DBL *sfbEnergyLeftLdData = + psyOutChannel[0]->sfbEnergyLdData; /* modified where msMask==1 */ + FIXP_DBL *sfbEnergyRightLdData = + psyOutChannel[1]->sfbEnergyLdData; /* modified where msMask==1 */ + FIXP_DBL *sfbEnergyMidLdData = psyData[0]->sfbEnergyMSLdData; + FIXP_DBL *sfbEnergySideLdData = psyData[1]->sfbEnergyMSLdData; + FIXP_DBL *sfbThresholdLeftLdData = + psyOutChannel[0]->sfbThresholdLdData; /* modified where msMask==1 */ + FIXP_DBL *sfbThresholdRightLdData = + psyOutChannel[1]->sfbThresholdLdData; /* modified where msMask==1 */ + + FIXP_DBL *mdctSpectrumLeft = + psyData[0]->mdctSpectrum; /* modified where msMask==1 */ + FIXP_DBL *mdctSpectrumRight = + psyData[1]->mdctSpectrum; /* modified where msMask==1 */ + + INT sfb, sfboffs, j; /* loop counters */ + FIXP_DBL pnlrLdData, pnmsLdData; + FIXP_DBL minThresholdLdData; + FIXP_DBL minThreshold; + INT useMS; + + INT msMaskTrueSomewhere = 0; /* to determine msDigest */ + INT numMsMaskFalse = + 0; /* number of non-intensity bands where L/R coding is used */ + + for (sfb = 0; sfb < sfbCnt; sfb += sfbPerGroup) { + for (sfboffs = 0; sfboffs < maxSfbPerGroup; sfboffs++) { + if ((isBook == NULL) ? 1 : (isBook[sfb + sfboffs] == 0)) { + FIXP_DBL tmp; + + /* + minThreshold=min(sfbThresholdLeft[sfb+sfboffs], + sfbThresholdRight[sfb+sfboffs])*scaleMinThres; pnlr = + (sfbThresholdLeft[sfb+sfboffs]/ + max(sfbEnergyLeft[sfb+sfboffs],sfbThresholdLeft[sfb+sfboffs]))* + (sfbThresholdRight[sfb+sfboffs]/ + max(sfbEnergyRight[sfb+sfboffs],sfbThresholdRight[sfb+sfboffs])); + pnms = + (minThreshold/max(sfbEnergyMid[sfb+sfboffs],minThreshold))* + (minThreshold/max(sfbEnergySide[sfb+sfboffs],minThreshold)); + useMS = (pnms > pnlr); + */ + + /* we assume that scaleMinThres == 1.0f and we can drop it */ + minThresholdLdData = fixMin(sfbThresholdLeftLdData[sfb + sfboffs], + sfbThresholdRightLdData[sfb + sfboffs]); + + /* pnlrLdData = sfbThresholdLeftLdData[sfb+sfboffs] - + max(sfbEnergyLeftLdData[sfb+sfboffs], + sfbThresholdLeftLdData[sfb+sfboffs]) + + sfbThresholdRightLdData[sfb+sfboffs] - + max(sfbEnergyRightLdData[sfb+sfboffs], + sfbThresholdRightLdData[sfb+sfboffs]); */ + tmp = fixMax(sfbEnergyLeftLdData[sfb + sfboffs], + sfbThresholdLeftLdData[sfb + sfboffs]); + pnlrLdData = (sfbThresholdLeftLdData[sfb + sfboffs] >> 1) - (tmp >> 1); + pnlrLdData = pnlrLdData + (sfbThresholdRightLdData[sfb + sfboffs] >> 1); + tmp = fixMax(sfbEnergyRightLdData[sfb + sfboffs], + sfbThresholdRightLdData[sfb + sfboffs]); + pnlrLdData = pnlrLdData - (tmp >> 1); + + /* pnmsLdData = minThresholdLdData - + max(sfbEnergyMidLdData[sfb+sfboffs], minThresholdLdData) + + minThresholdLdData - max(sfbEnergySideLdData[sfb+sfboffs], + minThresholdLdData); */ + tmp = fixMax(sfbEnergyMidLdData[sfb + sfboffs], minThresholdLdData); + pnmsLdData = minThresholdLdData - (tmp >> 1); + tmp = fixMax(sfbEnergySideLdData[sfb + sfboffs], minThresholdLdData); + pnmsLdData = pnmsLdData - (tmp >> 1); + useMS = ((allowMS != 0) && (pnmsLdData > pnlrLdData)) ? 1 : 0; + + if (useMS) { + msMask[sfb + sfboffs] = 1; + msMaskTrueSomewhere = 1; + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + FIXP_DBL specL, specR; + specL = mdctSpectrumLeft[j] >> 1; + specR = mdctSpectrumRight[j] >> 1; + mdctSpectrumLeft[j] = specL + specR; + mdctSpectrumRight[j] = specL - specR; + } + minThreshold = fixMin(sfbThresholdLeft[sfb + sfboffs], + sfbThresholdRight[sfb + sfboffs]); + sfbThresholdLeft[sfb + sfboffs] = sfbThresholdRight[sfb + sfboffs] = + minThreshold; + sfbThresholdLeftLdData[sfb + sfboffs] = + sfbThresholdRightLdData[sfb + sfboffs] = minThresholdLdData; + sfbEnergyLeft[sfb + sfboffs] = sfbEnergyMid[sfb + sfboffs]; + sfbEnergyRight[sfb + sfboffs] = sfbEnergySide[sfb + sfboffs]; + sfbEnergyLeftLdData[sfb + sfboffs] = + sfbEnergyMidLdData[sfb + sfboffs]; + sfbEnergyRightLdData[sfb + sfboffs] = + sfbEnergySideLdData[sfb + sfboffs]; + + sfbSpreadEnLeft[sfb + sfboffs] = sfbSpreadEnRight[sfb + sfboffs] = + fixMin(sfbSpreadEnLeft[sfb + sfboffs], + sfbSpreadEnRight[sfb + sfboffs]) >> + 1; + + } else { + msMask[sfb + sfboffs] = 0; + numMsMaskFalse++; + } /* useMS */ + } /* isBook */ + else { + /* keep mDigest from IS module */ + if (msMask[sfb + sfboffs]) { + msMaskTrueSomewhere = 1; + } + /* prohibit MS_MASK_ALL in combination with IS */ + numMsMaskFalse = 9; + } /* isBook */ + } /* sfboffs */ + } /* sfb */ + + if (msMaskTrueSomewhere == 1) { + if ((numMsMaskFalse == 0) || + ((numMsMaskFalse < maxSfbPerGroup) && (numMsMaskFalse < 9))) { + *msDigest = SI_MS_MASK_ALL; + /* loop through M/S bands; if msMask==0, set it to 1 and apply M/S */ + for (sfb = 0; sfb < sfbCnt; sfb += sfbPerGroup) { + for (sfboffs = 0; sfboffs < maxSfbPerGroup; sfboffs++) { + if (((isBook == NULL) ? 1 : (isBook[sfb + sfboffs] == 0)) && + (msMask[sfb + sfboffs] == 0)) { + msMask[sfb + sfboffs] = 1; + /* apply M/S coding */ + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + FIXP_DBL specL, specR; + specL = mdctSpectrumLeft[j] >> 1; + specR = mdctSpectrumRight[j] >> 1; + mdctSpectrumLeft[j] = specL + specR; + mdctSpectrumRight[j] = specL - specR; + } + minThreshold = fixMin(sfbThresholdLeft[sfb + sfboffs], + sfbThresholdRight[sfb + sfboffs]); + sfbThresholdLeft[sfb + sfboffs] = sfbThresholdRight[sfb + sfboffs] = + minThreshold; + minThresholdLdData = fixMin(sfbThresholdLeftLdData[sfb + sfboffs], + sfbThresholdRightLdData[sfb + sfboffs]); + sfbThresholdLeftLdData[sfb + sfboffs] = + sfbThresholdRightLdData[sfb + sfboffs] = minThresholdLdData; + sfbEnergyLeft[sfb + sfboffs] = sfbEnergyMid[sfb + sfboffs]; + sfbEnergyRight[sfb + sfboffs] = sfbEnergySide[sfb + sfboffs]; + sfbEnergyLeftLdData[sfb + sfboffs] = + sfbEnergyMidLdData[sfb + sfboffs]; + sfbEnergyRightLdData[sfb + sfboffs] = + sfbEnergySideLdData[sfb + sfboffs]; + + sfbSpreadEnLeft[sfb + sfboffs] = sfbSpreadEnRight[sfb + sfboffs] = + fixMin(sfbSpreadEnLeft[sfb + sfboffs], + sfbSpreadEnRight[sfb + sfboffs]) >> + 1; + } + } + } + } else { + *msDigest = SI_MS_MASK_SOME; + } + } else { + *msDigest = SI_MS_MASK_NONE; + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/ms_stereo.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/ms_stereo.h new file mode 100644 index 0000000000000..a2023078fc929 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/ms_stereo.h @@ -0,0 +1,117 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: MS stereo processing + +*******************************************************************************/ + +#ifndef MS_STEREO_H +#define MS_STEREO_H + +#include "interface.h" + +void FDKaacEnc_MsStereoProcessing(PSY_DATA *RESTRICT psyData[(2)], + PSY_OUT_CHANNEL *psyOutChannel[2], + const INT *isBook, INT *msDigest, /* output */ + INT *msMask, /* output */ + const INT allowMS, const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *sfbOffset); + +#endif /* MS_STEREO_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/noisedet.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/noisedet.cpp new file mode 100644 index 0000000000000..c9843040cddea --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/noisedet.cpp @@ -0,0 +1,235 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: noisedet.c + Routines for Noise Detection + +*******************************************************************************/ + +#include "noisedet.h" + +#include "aacenc_pns.h" +#include "pnsparam.h" + +/***************************************************************************** + + functionname: FDKaacEnc_fuzzyIsSmaller + description: Fuzzy value calculation for "testVal is smaller than refVal" + returns: fuzzy value + input: test and ref Value, + low and high Lim + output: return fuzzy value + +*****************************************************************************/ +static FIXP_SGL FDKaacEnc_fuzzyIsSmaller(FIXP_DBL testVal, FIXP_DBL refVal, + FIXP_DBL loLim, FIXP_DBL hiLim) { + if (refVal <= FL2FXCONST_DBL(0.0)) + return (FL2FXCONST_SGL(0.0f)); + else if (testVal >= fMult((hiLim >> 1) + (loLim >> 1), refVal)) + return (FL2FXCONST_SGL(0.0f)); + else + return ((FIXP_SGL)MAXVAL_SGL); +} + +/***************************************************************************** + + functionname: FDKaacEnc_noiseDetect + description: detect tonal sfb's; two tests + Powerdistribution: + sfb splittet in four regions, + compare the energy in all sections + PsychTonality: + compare tonality from chaosmeasure with reftonality + returns: + input: spectrum of one large mdct + number of sfb's + pointer to offset of sfb's + pointer to noiseFuzzyMeasure (modified) + noiseparams struct + pointer to sfb energies + pointer to tonality calculated in chaosmeasure + output: noiseFuzzy Measure + +*****************************************************************************/ + +void FDKaacEnc_noiseDetect(FIXP_DBL *RESTRICT mdctSpectrum, + INT *RESTRICT sfbMaxScaleSpec, INT sfbActive, + const INT *RESTRICT sfbOffset, + FIXP_SGL *RESTRICT noiseFuzzyMeasure, + NOISEPARAMS *np, FIXP_SGL *RESTRICT sfbtonality) + +{ + int i, k, sfb, sfbWidth; + FIXP_SGL fuzzy, fuzzyTotal; + FIXP_DBL refVal, testVal; + + /***** Start detection phase *****/ + /* Start noise detection for each band based on a number of checks */ + for (sfb = 0; sfb < sfbActive; sfb++) { + fuzzyTotal = (FIXP_SGL)MAXVAL_SGL; + sfbWidth = sfbOffset[sfb + 1] - sfbOffset[sfb]; + + /* Reset output for lower bands or too small bands */ + if (sfb < np->startSfb || sfbWidth < np->minSfbWidth) { + noiseFuzzyMeasure[sfb] = FL2FXCONST_SGL(0.0f); + continue; + } + + if ((np->detectionAlgorithmFlags & USE_POWER_DISTRIBUTION) && + (fuzzyTotal > FL2FXCONST_SGL(0.5f))) { + FIXP_DBL fhelp1, fhelp2, fhelp3, fhelp4, maxVal, minVal; + INT leadingBits = fixMax( + 0, (sfbMaxScaleSpec[sfb] - + 3)); /* max sfbWidth = 96/4 ; 2^5=32 => 5/2 = 3 (spc*spc) */ + + /* check power distribution in four regions */ + fhelp1 = fhelp2 = fhelp3 = fhelp4 = FL2FXCONST_DBL(0.0f); + k = sfbWidth >> 2; /* Width of a quarter band */ + + for (i = sfbOffset[sfb]; i < sfbOffset[sfb] + k; i++) { + fhelp1 = fPow2AddDiv2(fhelp1, mdctSpectrum[i] << leadingBits); + fhelp2 = fPow2AddDiv2(fhelp2, mdctSpectrum[i + k] << leadingBits); + fhelp3 = fPow2AddDiv2(fhelp3, mdctSpectrum[i + 2 * k] << leadingBits); + fhelp4 = fPow2AddDiv2(fhelp4, mdctSpectrum[i + 3 * k] << leadingBits); + } + + /* get max into fhelp: */ + maxVal = fixMax(fhelp1, fhelp2); + maxVal = fixMax(maxVal, fhelp3); + maxVal = fixMax(maxVal, fhelp4); + + /* get min into fhelp1: */ + minVal = fixMin(fhelp1, fhelp2); + minVal = fixMin(minVal, fhelp3); + minVal = fixMin(minVal, fhelp4); + + /* Normalize min and max Val */ + leadingBits = CountLeadingBits(maxVal); + testVal = maxVal << leadingBits; + refVal = minVal << leadingBits; + + /* calculate fuzzy value for power distribution */ + testVal = fMultDiv2(testVal, np->powDistPSDcurve[sfb]); + + fuzzy = FDKaacEnc_fuzzyIsSmaller( + testVal, /* 1/2 * maxValue * PSDcurve */ + refVal, /* 1 * minValue */ + FL2FXCONST_DBL(0.495), /* 1/2 * loLim (0.99f/2) */ + FL2FXCONST_DBL(0.505)); /* 1/2 * hiLim (1.01f/2) */ + + fuzzyTotal = fixMin(fuzzyTotal, fuzzy); + } + + if ((np->detectionAlgorithmFlags & USE_PSYCH_TONALITY) && + (fuzzyTotal > FL2FXCONST_SGL(0.5f))) { + /* Detection with tonality-value of psych. acoustic (here: 1 is tonal!)*/ + + testVal = FX_SGL2FX_DBL(sfbtonality[sfb]) >> 1; /* 1/2 * sfbTonality */ + refVal = np->refTonality; + + fuzzy = FDKaacEnc_fuzzyIsSmaller( + testVal, refVal, FL2FXCONST_DBL(0.45f), /* 1/2 * loLim (0.9f/2) */ + FL2FXCONST_DBL(0.55f)); /* 1/2 * hiLim (1.1f/2) */ + + fuzzyTotal = fixMin(fuzzyTotal, fuzzy); + } + + /* Output of final result */ + noiseFuzzyMeasure[sfb] = fuzzyTotal; + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/noisedet.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/noisedet.h new file mode 100644 index 0000000000000..478701f653da2 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/noisedet.h @@ -0,0 +1,116 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: noisedet.h + +*******************************************************************************/ + +#ifndef NOISEDET_H +#define NOISEDET_H + +#include "common_fix.h" + +#include "pnsparam.h" +#include "psy_data.h" + +void FDKaacEnc_noiseDetect(FIXP_DBL *mdctSpectrum, INT *sfbMaxScaleSpec, + INT sfbActive, const INT *sfbOffset, + FIXP_SGL noiseFuzzyMeasure[], NOISEPARAMS *np, + FIXP_SGL *sfbtonality); + +#endif /* NOISEDET_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pns_func.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pns_func.h new file mode 100644 index 0000000000000..88f45860d21d6 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pns_func.h @@ -0,0 +1,138 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: pns_func.h + +*******************************************************************************/ + +#ifndef PNS_FUNC_H +#define PNS_FUNC_H + +#include "common_fix.h" +#include "aacenc_pns.h" +#include "psy_data.h" + +AAC_ENCODER_ERROR FDKaacEnc_InitPnsConfiguration( + PNS_CONFIG *pnsConf, INT bitRate, INT sampleRate, INT usePns, INT sfbCnt, + const INT *sfbOffset, const INT numChan, const INT isLC); + +void FDKaacEnc_PnsDetect(PNS_CONFIG *pnsConf, PNS_DATA *pnsData, + const INT lastWindowSequence, const INT sfbActive, + const INT maxSfbPerGroup, FIXP_DBL *sfbThresholdLdData, + const INT *sfbOffset, FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality, + int tnsOrder, INT tnsPredictionGain, INT tnsActive, + FIXP_DBL *sfbEnergyLdData, INT *noiseNrg); + +void FDKaacEnc_CodePnsChannel(const INT sfbActive, PNS_CONFIG *pnsConf, + INT *pnsFlag, FIXP_DBL *sfbEnergy, INT *noiseNrg, + FIXP_DBL *sfbThreshold); + +void FDKaacEnc_PreProcessPnsChannelPair( + const INT sfbActive, FIXP_DBL *sfbEnergyLeft, FIXP_DBL *sfbEnergyRight, + FIXP_DBL *sfbEnergyLeftLD, FIXP_DBL *sfbEnergyRightLD, + FIXP_DBL *sfbEnergyMid, PNS_CONFIG *pnsConfLeft, PNS_DATA *pnsDataLeft, + PNS_DATA *pnsDataRight); + +void FDKaacEnc_PostProcessPnsChannelPair(const INT sfbActive, + PNS_CONFIG *pnsConf, + PNS_DATA *pnsDataLeft, + PNS_DATA *pnsDataRight, INT *msMask, + INT *msDigest); + +#endif /* PNS_FUNC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pnsparam.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pnsparam.cpp new file mode 100644 index 0000000000000..a6aab06b654e0 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pnsparam.cpp @@ -0,0 +1,574 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Lohwasser + + Description: PNS parameters depending on bitrate and bandwidth + +*******************************************************************************/ + +#include "pnsparam.h" + +#include "psy_configuration.h" + +typedef struct { + SHORT startFreq; + /* Parameters for detection */ + FIXP_SGL refPower; + FIXP_SGL refTonality; + SHORT tnsGainThreshold; /* scaled by TNS_PREDGAIN_SCALE (=1000) */ + SHORT tnsPNSGainThreshold; /* scaled by TNS_PREDGAIN_SCALE (=1000) */ + FIXP_SGL gapFillThr; + SHORT minSfbWidth; + USHORT detectionAlgorithmFlags; +} PNS_INFO_TAB; + +typedef struct { + ULONG brFrom; + ULONG brTo; + UCHAR S16000; + UCHAR S22050; + UCHAR S24000; + UCHAR S32000; + UCHAR S44100; + UCHAR S48000; +} AUTO_PNS_TAB; + +static const AUTO_PNS_TAB levelTable_mono[] = { + { + 0, + 11999, + 0, + 1, + 1, + 1, + 1, + 1, + }, + { + 12000, + 19999, + 0, + 1, + 1, + 1, + 1, + 1, + }, + { + 20000, + 28999, + 0, + 2, + 1, + 1, + 1, + 1, + }, + { + 29000, + 40999, + 0, + 4, + 4, + 4, + 2, + 2, + }, + { + 41000, + 55999, + 0, + 9, + 9, + 7, + 7, + 7, + }, + { + 56000, + 61999, + 0, + 0, + 0, + 0, + 9, + 9, + }, + { + 62000, + 75999, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 76000, + 92999, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 93000, + 999999, + 0, + 0, + 0, + 0, + 0, + 0, + }, +}; + +static const AUTO_PNS_TAB levelTable_stereo[] = { + { + 0, + 11999, + 0, + 1, + 1, + 1, + 1, + 1, + }, + { + 12000, + 19999, + 0, + 3, + 1, + 1, + 1, + 1, + }, + { + 20000, + 28999, + 0, + 3, + 3, + 3, + 2, + 2, + }, + { + 29000, + 40999, + 0, + 7, + 6, + 6, + 5, + 5, + }, + { + 41000, + 55999, + 0, + 9, + 9, + 7, + 7, + 7, + }, + { + 56000, + 79999, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 80000, + 99999, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 100000, + 999999, + 0, + 0, + 0, + 0, + 0, + 0, + }, +}; + +static const PNS_INFO_TAB pnsInfoTab[] = { + /*0 pns off */ + /*1*/ {4000, FL2FXCONST_SGL(0.04), FL2FXCONST_SGL(0.06), 1150, 1200, + FL2FXCONST_SGL(0.02), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS /*| JUST_LONG_WINDOW*/}, + /*2*/ + {4000, FL2FXCONST_SGL(0.04), FL2FXCONST_SGL(0.07), 1130, 1300, + FL2FXCONST_SGL(0.05), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS /*| JUST_LONG_WINDOW*/}, + /*3*/ + {4100, FL2FXCONST_SGL(0.04), FL2FXCONST_SGL(0.07), 1100, 1400, + FL2FXCONST_SGL(0.10), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS /*| JUST_LONG_WINDOW*/}, + /*4*/ + {4100, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.10), 1100, 1400, + FL2FXCONST_SGL(0.15), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS /*| JUST_LONG_WINDOW*/}, + /*5*/ + {4300, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.10), 1100, 1400, + FL2FXCONST_SGL(0.15), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /*6*/ + {5000, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.10), 1100, 1400, + FL2FXCONST_SGL(0.25), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /*7*/ + {5500, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.12), 1100, 1400, + FL2FXCONST_SGL(0.35), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /*8*/ + {6000, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.12), 1080, 1400, + FL2FXCONST_SGL(0.40), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /*9*/ + {6000, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.14), 1070, 1400, + FL2FXCONST_SGL(0.45), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, +}; + +static const AUTO_PNS_TAB levelTable_lowComplexity[] = { + { + 0, + 27999, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 28000, + 31999, + 0, + 2, + 2, + 2, + 2, + 2, + }, + { + 32000, + 47999, + 0, + 3, + 3, + 3, + 3, + 3, + }, + { + 48000, + 48000, + 0, + 4, + 4, + 4, + 4, + 4, + }, + { + 48001, + 999999, + 0, + 0, + 0, + 0, + 0, + 0, + }, +}; +/* conversion of old LC tuning tables to new (LD enc) structure (only entries + * which are actually used were converted) */ +static const PNS_INFO_TAB pnsInfoTab_lowComplexity[] = { + /*0 pns off */ + /* DEFAULT parameter set */ + /*1*/ {4100, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.16), 1100, 1400, + FL2FXCONST_SGL(0.5), 16, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /*2*/ + {4100, FL2FXCONST_SGL(0.05), FL2FXCONST_SGL(0.10), 1410, 1400, + FL2FXCONST_SGL(0.5), 16, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /*3*/ + {4100, FL2FXCONST_SGL(0.05), FL2FXCONST_SGL(0.10), 1100, 1400, + FL2FXCONST_SGL(0.5), 16, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /* LOWSUBST -> PNS is used less often than with DEFAULT parameter set (for + br: 48000 - 79999) */ + /*4*/ + {4100, FL2FXCONST_SGL(0.20), FL2FXCONST_SGL(0.10), 1410, 1400, + FL2FXCONST_SGL(0.5), 16, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, +}; + +/**************************************************************************** + function to look up used pns level +****************************************************************************/ +int FDKaacEnc_lookUpPnsUse(int bitRate, int sampleRate, int numChan, + const int isLC) { + int hUsePns = 0, size, i; + const AUTO_PNS_TAB *levelTable; + + if (isLC) { + levelTable = &levelTable_lowComplexity[0]; + size = sizeof(levelTable_lowComplexity); + } else { /* (E)LD */ + levelTable = (numChan > 1) ? &levelTable_stereo[0] : &levelTable_mono[0]; + size = (numChan > 1) ? sizeof(levelTable_stereo) : sizeof(levelTable_mono); + } + + for (i = 0; i < (int)(size / sizeof(AUTO_PNS_TAB)); i++) { + if (((ULONG)bitRate >= levelTable[i].brFrom) && + ((ULONG)bitRate <= levelTable[i].brTo)) + break; + } + + /* sanity check */ + if ((int)(sizeof(pnsInfoTab) / sizeof(PNS_INFO_TAB)) < i) { + return (PNS_TABLE_ERROR); + } + + switch (sampleRate) { + case 16000: + hUsePns = levelTable[i].S16000; + break; + case 22050: + hUsePns = levelTable[i].S22050; + break; + case 24000: + hUsePns = levelTable[i].S24000; + break; + case 32000: + hUsePns = levelTable[i].S32000; + break; + case 44100: + hUsePns = levelTable[i].S44100; + break; + case 48000: + hUsePns = levelTable[i].S48000; + break; + default: + if (isLC) { + hUsePns = levelTable[i].S48000; + } + break; + } + + return (hUsePns); +} + +/***************************************************************************** + + functionname: FDKaacEnc_GetPnsParam + description: Gets PNS parameters depending on bitrate and bandwidth or + bitsPerLine + returns: error status + input: Noiseparams struct, bitrate, sampling rate, + number of sfb's, pointer to sfb offset + output: PNS parameters + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_GetPnsParam(NOISEPARAMS *np, INT bitRate, + INT sampleRate, INT sfbCnt, + const INT *sfbOffset, INT *usePns, + INT numChan, const INT isLC) { + int i, hUsePns; + const PNS_INFO_TAB *pnsInfo; + + if (*usePns <= 0) return AAC_ENC_OK; + + if (isLC) { + np->detectionAlgorithmFlags = IS_LOW_COMPLEXITY; + + pnsInfo = pnsInfoTab_lowComplexity; + + /* new pns params */ + hUsePns = FDKaacEnc_lookUpPnsUse(bitRate, sampleRate, numChan, isLC); + if (hUsePns == 0) { + *usePns = 0; + return AAC_ENC_OK; + } + + if (hUsePns == PNS_TABLE_ERROR) { + return AAC_ENC_PNS_TABLE_ERROR; + } + + /* select correct row of tuning table */ + pnsInfo += hUsePns - 1; + + } else { + np->detectionAlgorithmFlags = 0; + pnsInfo = pnsInfoTab; + + /* new pns params */ + hUsePns = FDKaacEnc_lookUpPnsUse(bitRate, sampleRate, numChan, isLC); + if (hUsePns == 0) { + *usePns = 0; + return AAC_ENC_OK; + } + if (hUsePns == PNS_TABLE_ERROR) return AAC_ENC_PNS_TABLE_ERROR; + + /* select correct row of tuning table */ + pnsInfo += hUsePns - 1; + } + + np->startSfb = FDKaacEnc_FreqToBandWidthRounding( + pnsInfo->startFreq, sampleRate, sfbCnt, sfbOffset); + + np->detectionAlgorithmFlags |= pnsInfo->detectionAlgorithmFlags; + + np->refPower = FX_SGL2FX_DBL(pnsInfo->refPower); + np->refTonality = FX_SGL2FX_DBL(pnsInfo->refTonality); + np->tnsGainThreshold = pnsInfo->tnsGainThreshold; + np->tnsPNSGainThreshold = pnsInfo->tnsPNSGainThreshold; + np->minSfbWidth = pnsInfo->minSfbWidth; + + np->gapFillThr = + pnsInfo->gapFillThr; /* for LC it is always FL2FXCONST_SGL(0.5) */ + + /* assuming a constant dB/Hz slope in the signal's PSD curve, + the detection threshold needs to be corrected for the width of the band */ + + for (i = 0; i < (sfbCnt - 1); i++) { + INT qtmp, sfbWidth; + FIXP_DBL tmp; + + sfbWidth = sfbOffset[i + 1] - sfbOffset[i]; + + tmp = fPow(np->refPower, 0, sfbWidth, DFRACT_BITS - 1 - 5, &qtmp); + np->powDistPSDcurve[i] = (FIXP_SGL)((LONG)(scaleValue(tmp, qtmp) >> 16)); + } + np->powDistPSDcurve[sfbCnt] = np->powDistPSDcurve[sfbCnt - 1]; + + return AAC_ENC_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pnsparam.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pnsparam.h new file mode 100644 index 0000000000000..c37738aedfb9e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pnsparam.h @@ -0,0 +1,149 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: PNS parameters depending on bitrate and bandwidth + +*******************************************************************************/ + +#ifndef PNSPARAM_H +#define PNSPARAM_H + +#include "aacenc.h" +#include "common_fix.h" +#include "psy_const.h" + +#define NUM_PNSINFOTAB 4 +#define PNS_TABLE_ERROR -1 + +/* detection algorithm flags */ +#define USE_POWER_DISTRIBUTION (1 << 0) +#define USE_PSYCH_TONALITY (1 << 1) +#define USE_TNS_GAIN_THR (1 << 2) +#define USE_TNS_PNS (1 << 3) +#define JUST_LONG_WINDOW (1 << 4) +/* additional algorithm flags */ +#define IS_LOW_COMPLEXITY (1 << 5) + +typedef struct { + /* PNS start band */ + short startSfb; + + /* detection algorithm flags */ + USHORT detectionAlgorithmFlags; + + /* Parameters for detection */ + FIXP_DBL refPower; + FIXP_DBL refTonality; + INT tnsGainThreshold; + INT tnsPNSGainThreshold; + INT minSfbWidth; + FIXP_SGL powDistPSDcurve[MAX_GROUPED_SFB]; + FIXP_SGL gapFillThr; +} NOISEPARAMS; + +int FDKaacEnc_lookUpPnsUse(int bitRate, int sampleRate, int numChan, + const int isLC); + +/****** Definition of prototypes ******/ + +AAC_ENCODER_ERROR FDKaacEnc_GetPnsParam(NOISEPARAMS *np, INT bitRate, + INT sampleRate, INT sfbCnt, + const INT *sfbOffset, INT *usePns, + INT numChan, const INT isLC); + +#endif /* PNSPARAM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pre_echo_control.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pre_echo_control.cpp new file mode 100644 index 0000000000000..3d5d153c9b8a0 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pre_echo_control.cpp @@ -0,0 +1,176 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Pre echo control + +*******************************************************************************/ + +#include "pre_echo_control.h" +#include "psy_configuration.h" + +void FDKaacEnc_InitPreEchoControl(FIXP_DBL *RESTRICT pbThresholdNm1, + INT *calcPreEcho, INT numPb, + FIXP_DBL *RESTRICT sfbPcmQuantThreshold, + INT *mdctScalenm1) { + *mdctScalenm1 = PCM_QUANT_THR_SCALE >> 1; + + FDKmemcpy(pbThresholdNm1, sfbPcmQuantThreshold, numPb * sizeof(FIXP_DBL)); + + *calcPreEcho = 1; +} + +void FDKaacEnc_PreEchoControl(FIXP_DBL *RESTRICT pbThresholdNm1, + INT calcPreEcho, INT numPb, + INT maxAllowedIncreaseFactor, + FIXP_SGL minRemainingThresholdFactor, + FIXP_DBL *RESTRICT pbThreshold, INT mdctScale, + INT *mdctScalenm1) { + int i; + FIXP_DBL tmpThreshold1, tmpThreshold2; + int scaling; + + /* If lastWindowSequence in previous frame was start- or stop-window, + skip preechocontrol calculation */ + if (calcPreEcho == 0) { + /* copy thresholds to internal memory */ + FDKmemcpy(pbThresholdNm1, pbThreshold, numPb * sizeof(FIXP_DBL)); + *mdctScalenm1 = mdctScale; + return; + } + + if (mdctScale > *mdctScalenm1) { + /* if current thresholds are downscaled more than the ones from the last + * block */ + scaling = 2 * (mdctScale - *mdctScalenm1); + for (i = 0; i < numPb; i++) { + /* multiplication with return data type fract ist equivalent to int + * multiplication */ + FDK_ASSERT(scaling >= 0); + tmpThreshold1 = maxAllowedIncreaseFactor * (pbThresholdNm1[i] >> scaling); + tmpThreshold2 = fMult(minRemainingThresholdFactor, pbThreshold[i]); + + FIXP_DBL tmp = pbThreshold[i]; + + /* copy thresholds to internal memory */ + pbThresholdNm1[i] = tmp; + + tmp = fixMin(tmp, tmpThreshold1); + pbThreshold[i] = fixMax(tmp, tmpThreshold2); + } + } else { + /* if thresholds of last block are more downscaled than the current ones */ + scaling = 2 * (*mdctScalenm1 - mdctScale); + for (i = 0; i < numPb; i++) { + /* multiplication with return data type fract ist equivalent to int + * multiplication */ + tmpThreshold1 = (maxAllowedIncreaseFactor >> 1) * pbThresholdNm1[i]; + tmpThreshold2 = fMult(minRemainingThresholdFactor, pbThreshold[i]); + + /* copy thresholds to internal memory */ + pbThresholdNm1[i] = pbThreshold[i]; + + FDK_ASSERT(scaling >= 0); + if ((pbThreshold[i] >> (scaling + 1)) > tmpThreshold1) { + pbThreshold[i] = tmpThreshold1 << (scaling + 1); + } + pbThreshold[i] = fixMax(pbThreshold[i], tmpThreshold2); + } + } + + *mdctScalenm1 = mdctScale; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pre_echo_control.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pre_echo_control.h new file mode 100644 index 0000000000000..688efdb2a8616 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/pre_echo_control.h @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Pre echo control + +*******************************************************************************/ + +#ifndef PRE_ECHO_CONTROL_H +#define PRE_ECHO_CONTROL_H + +#include "common_fix.h" + +void FDKaacEnc_InitPreEchoControl(FIXP_DBL *pbThresholdnm1, INT *calcPreEcho, + INT numPb, FIXP_DBL *sfbPcmQuantThreshold, + INT *mdctScalenm1); + +void FDKaacEnc_PreEchoControl(FIXP_DBL *pbThresholdNm1, INT calcPreEcho, + INT numPb, INT maxAllowedIncreaseFactor, + FIXP_SGL minRemainingThresholdFactor, + FIXP_DBL *pbThreshold, INT mdctScale, + INT *mdctScalenm1); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_configuration.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_configuration.cpp new file mode 100644 index 0000000000000..eef90bc0f8b06 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_configuration.cpp @@ -0,0 +1,627 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Psychoaccoustic configuration + +*******************************************************************************/ + +#include "psy_configuration.h" +#include "adj_thr.h" +#include "aacEnc_rom.h" + +#include "genericStds.h" + +#include "FDK_trigFcts.h" + +typedef struct { + LONG sampleRate; + const SFB_PARAM_LONG *paramLong; + const SFB_PARAM_SHORT *paramShort; +} SFB_INFO_TAB; + +static const SFB_INFO_TAB sfbInfoTab[] = { + {8000, &p_FDKaacEnc_8000_long_1024, &p_FDKaacEnc_8000_short_128}, + {11025, &p_FDKaacEnc_11025_long_1024, &p_FDKaacEnc_11025_short_128}, + {12000, &p_FDKaacEnc_12000_long_1024, &p_FDKaacEnc_12000_short_128}, + {16000, &p_FDKaacEnc_16000_long_1024, &p_FDKaacEnc_16000_short_128}, + {22050, &p_FDKaacEnc_22050_long_1024, &p_FDKaacEnc_22050_short_128}, + {24000, &p_FDKaacEnc_24000_long_1024, &p_FDKaacEnc_24000_short_128}, + {32000, &p_FDKaacEnc_32000_long_1024, &p_FDKaacEnc_32000_short_128}, + {44100, &p_FDKaacEnc_44100_long_1024, &p_FDKaacEnc_44100_short_128}, + {48000, &p_FDKaacEnc_48000_long_1024, &p_FDKaacEnc_48000_short_128}, + {64000, &p_FDKaacEnc_64000_long_1024, &p_FDKaacEnc_64000_short_128}, + {88200, &p_FDKaacEnc_88200_long_1024, &p_FDKaacEnc_88200_short_128}, + {96000, &p_FDKaacEnc_96000_long_1024, &p_FDKaacEnc_96000_short_128} + +}; + +/* 22050 and 24000 Hz */ +static const SFB_PARAM_LONG p_22050_long_512 = { + 31, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, + 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}}; + +/* 32000 Hz */ +static const SFB_PARAM_LONG p_32000_long_512 = { + 37, + {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 16, 20, 24, 24, 28, 32, 32, 32, 32, 32, 32, 32}}; + +/* 44100 Hz */ +static const SFB_PARAM_LONG p_44100_long_512 = { + 36, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, + 8, 8, 12, 12, 12, 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 52}}; + +static const SFB_INFO_TAB sfbInfoTabLD512[] = { + {8000, &p_22050_long_512, NULL}, {11025, &p_22050_long_512, NULL}, + {12000, &p_22050_long_512, NULL}, {16000, &p_22050_long_512, NULL}, + {22050, &p_22050_long_512, NULL}, {24000, &p_22050_long_512, NULL}, + {32000, &p_32000_long_512, NULL}, {44100, &p_44100_long_512, NULL}, + {48000, &p_44100_long_512, NULL}, {64000, &p_44100_long_512, NULL}, + {88200, &p_44100_long_512, NULL}, {96000, &p_44100_long_512, NULL}, + {128000, &p_44100_long_512, NULL}, {176400, &p_44100_long_512, NULL}, + {192000, &p_44100_long_512, NULL}, {256000, &p_44100_long_512, NULL}, + {352800, &p_44100_long_512, NULL}, {384000, &p_44100_long_512, NULL}, +}; + +/* 22050 and 24000 Hz */ +static const SFB_PARAM_LONG p_22050_long_480 = { + 30, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, + 12, 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32}}; + +/* 32000 Hz */ +static const SFB_PARAM_LONG p_32000_long_480 = { + 37, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 16, 16, 20, 24, 32, 32, 32, 32, 32, 32, 32, 32}}; + +/* 44100 Hz */ +static const SFB_PARAM_LONG p_44100_long_480 = { + 35, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, + 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, 32, 32, 32, 32, 32, 32, 48}}; + +static const SFB_INFO_TAB sfbInfoTabLD480[] = { + {8000, &p_22050_long_480, NULL}, {11025, &p_22050_long_480, NULL}, + {12000, &p_22050_long_480, NULL}, {16000, &p_22050_long_480, NULL}, + {22050, &p_22050_long_480, NULL}, {24000, &p_22050_long_480, NULL}, + {32000, &p_32000_long_480, NULL}, {44100, &p_44100_long_480, NULL}, + {48000, &p_44100_long_480, NULL}, {64000, &p_44100_long_480, NULL}, + {88200, &p_44100_long_480, NULL}, {96000, &p_44100_long_480, NULL}, + {128000, &p_44100_long_480, NULL}, {176400, &p_44100_long_480, NULL}, + {192000, &p_44100_long_480, NULL}, {256000, &p_44100_long_480, NULL}, + {352800, &p_44100_long_480, NULL}, {384000, &p_44100_long_480, NULL}, +}; + +/* Fixed point precision definitions */ +#define Q_BARCVAL (25) + +AAC_ENCODER_ERROR FDKaacEnc_initSfbTable(const LONG sampleRate, + const INT blockType, + const INT granuleLength, + INT *const sfbOffset, + INT *const sfbCnt) { + INT i, specStartOffset = 0; + INT granuleLengthWindow = granuleLength; + const UCHAR *sfbWidth = NULL; + const SFB_INFO_TAB *sfbInfo = NULL; + int size; + + /* + select table + */ + switch (granuleLength) { + case 1024: + case 960: + sfbInfo = sfbInfoTab; + size = (INT)(sizeof(sfbInfoTab) / sizeof(SFB_INFO_TAB)); + break; + case 512: + sfbInfo = sfbInfoTabLD512; + size = sizeof(sfbInfoTabLD512); + break; + case 480: + sfbInfo = sfbInfoTabLD480; + size = sizeof(sfbInfoTabLD480); + break; + default: + return AAC_ENC_INVALID_FRAME_LENGTH; + } + + for (i = 0; i < size; i++) { + if (sfbInfo[i].sampleRate == sampleRate) { + switch (blockType) { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + sfbWidth = sfbInfo[i].paramLong->sfbWidth; + *sfbCnt = sfbInfo[i].paramLong->sfbCnt; + break; + case SHORT_WINDOW: + sfbWidth = sfbInfo[i].paramShort->sfbWidth; + *sfbCnt = sfbInfo[i].paramShort->sfbCnt; + granuleLengthWindow /= TRANS_FAC; + break; + } + break; + } + } + if (i == size) { + return AAC_ENC_UNSUPPORTED_SAMPLINGRATE; + } + + /* + calc sfb offsets + */ + for (i = 0; i < *sfbCnt; i++) { + sfbOffset[i] = specStartOffset; + specStartOffset += sfbWidth[i]; + if (specStartOffset >= granuleLengthWindow) { + i++; + break; + } + } + *sfbCnt = fixMin(i, *sfbCnt); + sfbOffset[*sfbCnt] = fixMin(specStartOffset, granuleLengthWindow); + return AAC_ENC_OK; +} + +/***************************************************************************** + + functionname: FDKaacEnc_BarcLineValue + description: Calculates barc value for one frequency line + returns: barc value of line + input: number of lines in transform, index of line to check, Fs + output: + +*****************************************************************************/ +static FIXP_DBL FDKaacEnc_BarcLineValue(INT noOfLines, INT fftLine, + LONG samplingFreq) { + FIXP_DBL FOURBY3EM4 = (FIXP_DBL)0x45e7b273; /* 4.0/3 * 0.0001 in q43 */ + FIXP_DBL PZZZ76 = (FIXP_DBL)0x639d5e4a; /* 0.00076 in q41 */ + FIXP_DBL ONE3P3 = (FIXP_DBL)0x35333333; /* 13.3 in q26 */ + FIXP_DBL THREEP5 = (FIXP_DBL)0x1c000000; /* 3.5 in q27 */ + FIXP_DBL INV480 = (FIXP_DBL)0x44444444; // 1/480 in q39 + + FIXP_DBL center_freq, x1, x2; + FIXP_DBL bvalFFTLine, atan1, atan2; + + /* Theoritical maximum of center_freq (samp_freq*0.5) is 96khz * 0.5 = 48000 + */ + /* Theoritical maximum of x1 is 1.3333333e-4f * center_freq = 6.4, can keep in + * q28 */ + /* Theoritical maximum of x2 is 0.00076f * center_freq = 36.48, can keep in + * q25 */ + + center_freq = fftLine * samplingFreq; /* q11 or q8 */ + + switch (noOfLines) { + case 1024: + center_freq = center_freq << 2; /* q13 */ + break; + case 128: + center_freq = center_freq << 5; /* q13 */ + break; + case 512: + center_freq = (fftLine * samplingFreq) << 3; // q13 + break; + case 480: + center_freq = fMult(center_freq, INV480) << 4; // q13 + break; + default: + center_freq = (FIXP_DBL)0; + } + + x1 = fMult(center_freq, FOURBY3EM4); /* q13 * q43 - (DFRACT_BITS-1) = q25 */ + x2 = fMult(center_freq, PZZZ76) + << 2; /* q13 * q41 - (DFRACT_BITS-1) + 2 = q25 */ + + atan1 = fixp_atan(x1); + atan2 = fixp_atan(x2); + + /* q25 (q26 * q30 - (DFRACT_BITS-1)) + q25 (q27 * q30 * q30) */ + bvalFFTLine = fMult(ONE3P3, atan2) + fMult(THREEP5, fMult(atan1, atan1)); + return (bvalFFTLine); +} + +/* + do not consider energies below a certain input signal level, + i.e. of -96dB or 1 bit at 16 bit PCM resolution, + might need to be configurable to e.g. 24 bit PCM Input or a lower + resolution for low bit rates +*/ +static void FDKaacEnc_InitMinPCMResolution(int numPb, int *pbOffset, + FIXP_DBL *sfbPCMquantThreshold) { +/* PCM_QUANT_NOISE = FDKpow(10.0f, - 20.f / 10.0f) * ABS_LOW * NORM_PCM_ENERGY * + * FDKpow(2,PCM_QUANT_THR_SCALE) */ +#define PCM_QUANT_NOISE ((FIXP_DBL)0x00547062) + + for (int i = 0; i < numPb; i++) { + sfbPCMquantThreshold[i] = (pbOffset[i + 1] - pbOffset[i]) * PCM_QUANT_NOISE; + } +} + +static FIXP_DBL getMaskFactor(const FIXP_DBL dbVal_fix, const INT dbVal_e, + const FIXP_DBL ten_fix, const INT ten_e) { + INT q_msk; + FIXP_DBL mask_factor; + + mask_factor = fPow(ten_fix, DFRACT_BITS - 1 - ten_e, -dbVal_fix, + DFRACT_BITS - 1 - dbVal_e, &q_msk); + q_msk = fixMin(DFRACT_BITS - 1, fixMax(-(DFRACT_BITS - 1), q_msk)); + + if ((q_msk > 0) && (mask_factor > (FIXP_DBL)MAXVAL_DBL >> q_msk)) { + mask_factor = (FIXP_DBL)MAXVAL_DBL; + } else { + mask_factor = scaleValue(mask_factor, q_msk); + } + + return (mask_factor); +} + +static void FDKaacEnc_initSpreading(INT numPb, FIXP_DBL *pbBarcValue, + FIXP_DBL *pbMaskLoFactor, + FIXP_DBL *pbMaskHiFactor, + FIXP_DBL *pbMaskLoFactorSprEn, + FIXP_DBL *pbMaskHiFactorSprEn, + const LONG bitrate, const INT blockType) + +{ + INT i; + FIXP_DBL MASKLOWSPREN, MASKHIGHSPREN; + + FIXP_DBL MASKHIGH = (FIXP_DBL)0x30000000; /* 1.5 in q29 */ + FIXP_DBL MASKLOW = (FIXP_DBL)0x60000000; /* 3.0 in q29 */ + FIXP_DBL MASKLOWSPRENLONG = (FIXP_DBL)0x60000000; /* 3.0 in q29 */ + FIXP_DBL MASKHIGHSPRENLONG = (FIXP_DBL)0x40000000; /* 2.0 in q29 */ + FIXP_DBL MASKHIGHSPRENLONGLOWBR = (FIXP_DBL)0x30000000; /* 1.5 in q29 */ + FIXP_DBL MASKLOWSPRENSHORT = (FIXP_DBL)0x40000000; /* 2.0 in q29 */ + FIXP_DBL MASKHIGHSPRENSHORT = (FIXP_DBL)0x30000000; /* 1.5 in q29 */ + FIXP_DBL TEN = (FIXP_DBL)0x50000000; /* 10.0 in q27 */ + + if (blockType != SHORT_WINDOW) { + MASKLOWSPREN = MASKLOWSPRENLONG; + MASKHIGHSPREN = + (bitrate > 20000) ? MASKHIGHSPRENLONG : MASKHIGHSPRENLONGLOWBR; + } else { + MASKLOWSPREN = MASKLOWSPRENSHORT; + MASKHIGHSPREN = MASKHIGHSPRENSHORT; + } + + for (i = 0; i < numPb; i++) { + if (i > 0) { + pbMaskHiFactor[i] = getMaskFactor( + fMult(MASKHIGH, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, 27); + + pbMaskLoFactor[i - 1] = getMaskFactor( + fMult(MASKLOW, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, 27); + + pbMaskHiFactorSprEn[i] = getMaskFactor( + fMult(MASKHIGHSPREN, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, + 27); + + pbMaskLoFactorSprEn[i - 1] = getMaskFactor( + fMult(MASKLOWSPREN, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, + 27); + } else { + pbMaskHiFactor[i] = (FIXP_DBL)0; + pbMaskLoFactor[numPb - 1] = (FIXP_DBL)0; + pbMaskHiFactorSprEn[i] = (FIXP_DBL)0; + pbMaskLoFactorSprEn[numPb - 1] = (FIXP_DBL)0; + } + } +} + +static void FDKaacEnc_initBarcValues(INT numPb, INT *pbOffset, INT numLines, + INT samplingFrequency, FIXP_DBL *pbBval) { + INT i; + FIXP_DBL MAX_BARC = (FIXP_DBL)0x30000000; /* 24.0 in q25 */ + + for (i = 0; i < numPb; i++) { + FIXP_DBL v1, v2, cur_bark; + v1 = FDKaacEnc_BarcLineValue(numLines, pbOffset[i], samplingFrequency); + v2 = FDKaacEnc_BarcLineValue(numLines, pbOffset[i + 1], samplingFrequency); + cur_bark = (v1 >> 1) + (v2 >> 1); + pbBval[i] = fixMin(cur_bark, MAX_BARC); + } +} + +static void FDKaacEnc_initMinSnr(const LONG bitrate, const LONG samplerate, + const INT numLines, const INT *sfbOffset, + const INT sfbActive, const INT blockType, + FIXP_DBL *sfbMinSnrLdData) { + INT sfb; + + /* Fix conversion variables */ + INT qbfac, qperwin, qdiv, qpeprt_const, qpeprt; + INT qtmp, qsnr, sfbWidth; + + FIXP_DBL MAX_BARC = (FIXP_DBL)0x30000000; /* 24.0 in q25 */ + FIXP_DBL MAX_BARCP1 = (FIXP_DBL)0x32000000; /* 25.0 in q25 */ + FIXP_DBL BITS2PEFAC = (FIXP_DBL)0x4b851eb8; /* 1.18 in q30 */ + FIXP_DBL PERS2P4 = (FIXP_DBL)0x624dd2f2; /* 0.024 in q36 */ + FIXP_DBL ONEP5 = (FIXP_DBL)0x60000000; /* 1.5 in q30 */ + FIXP_DBL MAX_SNR = (FIXP_DBL)0x33333333; /* 0.8 in q30 */ + FIXP_DBL MIN_SNR = (FIXP_DBL)0x003126e9; /* 0.003 in q30 */ + + FIXP_DBL barcFactor, pePerWindow, pePart, barcWidth; + FIXP_DBL pePart_const, tmp, snr, one_qsnr, one_point5; + + /* relative number of active barks */ + barcFactor = fDivNorm(fixMin(FDKaacEnc_BarcLineValue( + numLines, sfbOffset[sfbActive], samplerate), + MAX_BARC), + MAX_BARCP1, &qbfac); + + qbfac = DFRACT_BITS - 1 - qbfac; + + pePerWindow = fDivNorm(bitrate, samplerate, &qperwin); + qperwin = DFRACT_BITS - 1 - qperwin; + pePerWindow = fMult(pePerWindow, BITS2PEFAC); + qperwin = qperwin + 30 - (DFRACT_BITS - 1); + pePerWindow = fMult(pePerWindow, PERS2P4); + qperwin = qperwin + 36 - (DFRACT_BITS - 1); + + switch (numLines) { + case 1024: + qperwin = qperwin - 10; + break; + case 128: + qperwin = qperwin - 7; + break; + case 512: + qperwin = qperwin - 9; + break; + case 480: + qperwin = qperwin - 9; + pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(480.f / 512.f)); + break; + } + + /* for short blocks it is assumed that more bits are available */ + if (blockType == SHORT_WINDOW) { + pePerWindow = fMult(pePerWindow, ONEP5); + qperwin = qperwin + 30 - (DFRACT_BITS - 1); + } + pePart_const = fDivNorm(pePerWindow, barcFactor, &qdiv); + qpeprt_const = qperwin - qbfac + DFRACT_BITS - 1 - qdiv; + + for (sfb = 0; sfb < sfbActive; sfb++) { + barcWidth = + FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfb + 1], samplerate) - + FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfb], samplerate); + + /* adapt to sfb bands */ + pePart = fMult(pePart_const, barcWidth); + qpeprt = qpeprt_const + 25 - (DFRACT_BITS - 1); + + /* pe -> snr calculation */ + sfbWidth = (sfbOffset[sfb + 1] - sfbOffset[sfb]); + pePart = fDivNorm(pePart, sfbWidth, &qdiv); + qpeprt += DFRACT_BITS - 1 - qdiv; + + tmp = f2Pow(pePart, DFRACT_BITS - 1 - qpeprt, &qtmp); + qtmp = DFRACT_BITS - 1 - qtmp; + + /* Subtract 1.5 */ + qsnr = fixMin(qtmp, 30); + tmp = tmp >> (qtmp - qsnr); + + if ((30 + 1 - qsnr) > (DFRACT_BITS - 1)) + one_point5 = (FIXP_DBL)0; + else + one_point5 = (FIXP_DBL)(ONEP5 >> (30 + 1 - qsnr)); + + snr = (tmp >> 1) - (one_point5); + qsnr -= 1; + + /* max(snr, 1.0) */ + if (qsnr > 0) + one_qsnr = (FIXP_DBL)(1 << qsnr); + else + one_qsnr = (FIXP_DBL)0; + + snr = fixMax(one_qsnr, snr); + + /* 1/snr */ + snr = fDivNorm(one_qsnr, snr, &qsnr); + qsnr = DFRACT_BITS - 1 - qsnr; + snr = (qsnr > 30) ? (snr >> (qsnr - 30)) : snr; + + /* upper limit is -1 dB */ + snr = (snr > MAX_SNR) ? MAX_SNR : snr; + + /* lower limit is -25 dB */ + snr = (snr < MIN_SNR) ? MIN_SNR : snr; + snr = snr << 1; + + sfbMinSnrLdData[sfb] = CalcLdData(snr); + } +} + +AAC_ENCODER_ERROR FDKaacEnc_InitPsyConfiguration(INT bitrate, INT samplerate, + INT bandwidth, INT blocktype, + INT granuleLength, INT useIS, + INT useMS, + PSY_CONFIGURATION *psyConf, + FB_TYPE filterbank) { + AAC_ENCODER_ERROR ErrorStatus; + INT sfb; + FIXP_DBL sfbBarcVal[MAX_SFB]; + const INT frameLengthLong = granuleLength; + const INT frameLengthShort = granuleLength / TRANS_FAC; + INT downscaleFactor = 1; + + switch (granuleLength) { + case 256: + case 240: + downscaleFactor = 2; + break; + case 128: + case 120: + downscaleFactor = 4; + break; + default: + downscaleFactor = 1; + break; + } + + FDKmemclear(psyConf, sizeof(PSY_CONFIGURATION)); + psyConf->granuleLength = granuleLength; + psyConf->filterbank = filterbank; + + psyConf->allowIS = (useIS) && ((bitrate / bandwidth) < 5); + psyConf->allowMS = useMS; + + /* init sfb table */ + ErrorStatus = FDKaacEnc_initSfbTable(samplerate * downscaleFactor, blocktype, + granuleLength * downscaleFactor, + psyConf->sfbOffset, &psyConf->sfbCnt); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + /* calculate barc values for each pb */ + FDKaacEnc_initBarcValues(psyConf->sfbCnt, psyConf->sfbOffset, + psyConf->sfbOffset[psyConf->sfbCnt], samplerate, + sfbBarcVal); + + FDKaacEnc_InitMinPCMResolution(psyConf->sfbCnt, psyConf->sfbOffset, + psyConf->sfbPcmQuantThreshold); + + /* calculate spreading function */ + FDKaacEnc_initSpreading(psyConf->sfbCnt, sfbBarcVal, + psyConf->sfbMaskLowFactor, psyConf->sfbMaskHighFactor, + psyConf->sfbMaskLowFactorSprEn, + psyConf->sfbMaskHighFactorSprEn, bitrate, blocktype); + + /* init ratio */ + + psyConf->maxAllowedIncreaseFactor = 2; /* integer */ + psyConf->minRemainingThresholdFactor = (FIXP_SGL)0x0148; + /* FL2FXCONST_SGL(0.01f); */ /* fract */ + + psyConf->clipEnergy = + (FIXP_DBL)0x773593ff; /* FL2FXCONST_DBL(1.0e9*NORM_PCM_ENERGY); */ + + if (blocktype != SHORT_WINDOW) { + psyConf->lowpassLine = + (INT)((2 * bandwidth * frameLengthLong) / samplerate); + psyConf->lowpassLineLFE = LFE_LOWPASS_LINE; + } else { + psyConf->lowpassLine = + (INT)((2 * bandwidth * frameLengthShort) / samplerate); + psyConf->lowpassLineLFE = 0; /* LFE only in lonf blocks */ + /* psyConf->clipEnergy /= (TRANS_FAC * TRANS_FAC); */ + psyConf->clipEnergy >>= 6; + } + + for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) { + if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLine) break; + } + psyConf->sfbActive = fMax(sfb, 1); + + for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) { + if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLineLFE) break; + } + psyConf->sfbActiveLFE = sfb; + psyConf->sfbActive = fMax(psyConf->sfbActive, psyConf->sfbActiveLFE); + + /* calculate minSnr */ + FDKaacEnc_initMinSnr(bitrate, samplerate * downscaleFactor, + psyConf->sfbOffset[psyConf->sfbCnt], psyConf->sfbOffset, + psyConf->sfbActive, blocktype, psyConf->sfbMinSnrLdData); + + return AAC_ENC_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_configuration.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_configuration.h new file mode 100644 index 0000000000000..52b288707e638 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_configuration.h @@ -0,0 +1,171 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Psychoaccoustic configuration + +*******************************************************************************/ + +#ifndef PSY_CONFIGURATION_H +#define PSY_CONFIGURATION_H + +#include "aacenc.h" +#include "common_fix.h" + +#include "psy_const.h" +#include "aacenc_tns.h" +#include "aacenc_pns.h" + +#define THR_SHIFTBITS 4 +#define PCM_QUANT_THR_SCALE 16 +#define BITS_PER_LINE_SHIFT 3 + +#define C_RATIO \ + (FIXP_DBL)0x02940a10 /* FL2FXCONST_DBL(0.001258925f) << THR_SHIFTBITS; */ /* pow(10.0f, -(29.0f/10.0f)) */ + +typedef struct { + INT sfbCnt; /* number of existing sf bands */ + INT sfbActive; /* number of sf bands containing energy after lowpass */ + INT sfbActiveLFE; + INT sfbOffset[MAX_SFB + 1]; + + INT filterbank; /* LC, LD or ELD */ + + FIXP_DBL sfbPcmQuantThreshold[MAX_SFB]; + + INT maxAllowedIncreaseFactor; /* preecho control */ + FIXP_SGL minRemainingThresholdFactor; + + INT lowpassLine; + INT lowpassLineLFE; + FIXP_DBL clipEnergy; /* for level dependend tmn */ + + FIXP_DBL sfbMaskLowFactor[MAX_SFB]; + FIXP_DBL sfbMaskHighFactor[MAX_SFB]; + + FIXP_DBL sfbMaskLowFactorSprEn[MAX_SFB]; + FIXP_DBL sfbMaskHighFactorSprEn[MAX_SFB]; + + FIXP_DBL sfbMinSnrLdData[MAX_SFB]; /* minimum snr (formerly known as bmax) */ + + TNS_CONFIG tnsConf; + PNS_CONFIG pnsConf; + + INT granuleLength; + INT allowIS; + INT allowMS; +} PSY_CONFIGURATION; + +typedef struct { + UCHAR sfbCnt; /* Number of scalefactor bands */ + UCHAR sfbWidth[MAX_SFB_LONG]; /* Width of scalefactor bands for long blocks */ +} SFB_PARAM_LONG; + +typedef struct { + UCHAR sfbCnt; /* Number of scalefactor bands */ + UCHAR + sfbWidth[MAX_SFB_SHORT]; /* Width of scalefactor bands for short blocks */ +} SFB_PARAM_SHORT; + +AAC_ENCODER_ERROR FDKaacEnc_InitPsyConfiguration(INT bitrate, INT samplerate, + INT bandwidth, INT blocktype, + INT granuleLength, INT useIS, + INT useMS, + PSY_CONFIGURATION *psyConf, + FB_TYPE filterbank); + +#endif /* PSY_CONFIGURATION_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_const.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_const.h new file mode 100644 index 0000000000000..c2d53042c1244 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_const.h @@ -0,0 +1,168 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Global psychoaccoustic constants + +*******************************************************************************/ + +#ifndef PSY_CONST_H +#define PSY_CONST_H + +#define TRUE 1 +#define FALSE 0 + +#define TRANS_FAC 8 /* encoder short long ratio */ + +#define FRAME_MAXLEN_SHORT ((1024) / TRANS_FAC) +#define FRAME_LEN_SHORT_128 ((1024) / TRANS_FAC) +#define FRAME_LEN_SHORT_120 (FRAME_LEN_LONG_960 / TRANS_FAC) + +/* Filterbank type*/ +enum FB_TYPE { FB_LC = 0, FB_LD = 1, FB_ELD = 2 }; + +/* Block types */ +#define N_BLOCKTYPES 6 +enum { + LONG_WINDOW = 0, + START_WINDOW, + SHORT_WINDOW, + STOP_WINDOW, + _LOWOV_WINDOW, /* Do not use this block type out side of block_switch.cpp */ + WRONG_WINDOW +}; + +/* Window shapes */ +enum { + SINE_WINDOW = 0, + KBD_WINDOW = 1, + LOL_WINDOW = 2 /* Low OverLap window shape for AAC-LD */ +}; + +/* + MS stuff +*/ +enum { SI_MS_MASK_NONE = 0, SI_MS_MASK_SOME = 1, SI_MS_MASK_ALL = 2 }; + +#define MAX_NO_OF_GROUPS 4 +#define MAX_SFB_LONG \ + 51 /* 51 for a memory optimized implementation, maybe 64 for convenient \ + debugging */ +#define MAX_SFB_SHORT \ + 15 /* 15 for a memory optimized implementation, maybe 16 for convenient \ + debugging */ + +#define MAX_SFB \ + (MAX_SFB_SHORT > MAX_SFB_LONG ? MAX_SFB_SHORT : MAX_SFB_LONG) /* = 51 */ +#define MAX_GROUPED_SFB \ + (MAX_NO_OF_GROUPS * MAX_SFB_SHORT > MAX_SFB_LONG \ + ? MAX_NO_OF_GROUPS * MAX_SFB_SHORT \ + : MAX_SFB_LONG) /* = 60 */ + +#define MAX_INPUT_BUFFER_SIZE (2 * (1024)) /* 2048 */ + +#define PCM_LEVEL 1.0f +#define NORM_PCM (PCM_LEVEL / 32768.0f) +#define NORM_PCM_ENERGY (NORM_PCM * NORM_PCM) +#define LOG_NORM_PCM -15 + +#define TNS_PREDGAIN_SCALE (1000) + +#define LFE_LOWPASS_LINE 12 +#define LFE_LOWPASS_LINE_MIN 4 + +#endif /* PSY_CONST_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_data.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_data.h new file mode 100644 index 0000000000000..fc0473451dd65 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_data.h @@ -0,0 +1,169 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Psychoaccoustic data + +*******************************************************************************/ + +#ifndef PSY_DATA_H +#define PSY_DATA_H + +#include "block_switch.h" +#include "mdct.h" + +/* Be careful with MAX_SFB_LONG as length of the .Long arrays. + * sfbEnergy.Long and sfbEnergyMS.Long and sfbThreshold.Long are used as a + * temporary storage for the regrouped short energies and thresholds between + * FDKaacEnc_groupShortData() and BuildInterface() in FDKaacEnc_psyMain(). The + * space required for this is MAX_GROUPED_SFB ( = MAX_NO_OF_GROUPS*MAX_SFB_SHORT + * ). However, this is not important if unions are used (which is not possible + * with pfloat). */ + +typedef shouldBeUnion { + FIXP_DBL Long[MAX_GROUPED_SFB]; + FIXP_DBL Short[TRANS_FAC][MAX_SFB_SHORT]; +} +SFB_THRESHOLD; + +typedef shouldBeUnion { + FIXP_DBL Long[MAX_GROUPED_SFB]; + FIXP_DBL Short[TRANS_FAC][MAX_SFB_SHORT]; +} +SFB_ENERGY; + +typedef shouldBeUnion { + FIXP_DBL Long[MAX_GROUPED_SFB]; + FIXP_DBL Short[TRANS_FAC][MAX_SFB_SHORT]; +} +SFB_LD_ENERGY; + +typedef shouldBeUnion { + INT Long[MAX_GROUPED_SFB]; + INT Short[TRANS_FAC][MAX_SFB_SHORT]; +} +SFB_MAX_SCALE; + +typedef struct { + INT_PCM* psyInputBuffer; + FIXP_DBL overlapAddBuffer[3 * 512 / 2]; + + mdct_t mdctPers; /* MDCT persistent data */ + BLOCK_SWITCHING_CONTROL blockSwitchingControl; /* block switching */ + FIXP_DBL sfbThresholdnm1[MAX_SFB]; /* FDKaacEnc_PreEchoControl */ + INT mdctScalenm1; /* scale of last block's mdct (FDKaacEnc_PreEchoControl) */ + INT calcPreEcho; + INT isLFE; +} PSY_STATIC; + +typedef struct { + FIXP_DBL* mdctSpectrum; + SFB_THRESHOLD sfbThreshold; /* adapt */ + SFB_ENERGY sfbEnergy; /* sfb energies */ + SFB_LD_ENERGY sfbEnergyLdData; /* sfb energies in ldData format */ + SFB_MAX_SCALE sfbMaxScaleSpec; + SFB_ENERGY sfbEnergyMS; /* mid/side sfb energies */ + FIXP_DBL sfbEnergyMSLdData[MAX_GROUPED_SFB]; /* mid/side sfb energies in + ldData format */ + SFB_ENERGY sfbSpreadEnergy; + INT mdctScale; /* exponent of data in mdctSpectrum */ + INT groupedSfbOffset[MAX_GROUPED_SFB + 1]; + INT sfbActive; + INT lowpassLine; +} PSY_DATA; + +#endif /* PSY_DATA_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_main.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_main.cpp new file mode 100644 index 0000000000000..f6345e4e5ffad --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_main.cpp @@ -0,0 +1,1348 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Psychoaccoustic major function block + +*******************************************************************************/ + +#include "psy_const.h" + +#include "block_switch.h" +#include "transform.h" +#include "spreading.h" +#include "pre_echo_control.h" +#include "band_nrg.h" +#include "psy_configuration.h" +#include "psy_data.h" +#include "ms_stereo.h" +#include "interface.h" +#include "psy_main.h" +#include "grp_data.h" +#include "tns_func.h" +#include "pns_func.h" +#include "tonality.h" +#include "aacEnc_ram.h" +#include "intensity.h" + +/* blending to reduce gibbs artifacts */ +#define FADE_OUT_LEN 6 +static const FIXP_DBL fadeOutFactor[FADE_OUT_LEN] = { + 1840644096, 1533870080, 1227096064, 920322048, 613548032, 306774016}; + +/* forward definitions */ + +/***************************************************************************** + + functionname: FDKaacEnc_PsyNew + description: allocates memory for psychoacoustic + returns: an error code + input: pointer to a psych handle + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_PsyNew(PSY_INTERNAL **phpsy, const INT nElements, + const INT nChannels, UCHAR *dynamic_RAM) { + AAC_ENCODER_ERROR ErrorStatus; + PSY_INTERNAL *hPsy; + INT i; + + hPsy = GetRam_aacEnc_PsyInternal(); + *phpsy = hPsy; + if (hPsy == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + + for (i = 0; i < nElements; i++) { + /* PSY_ELEMENT */ + hPsy->psyElement[i] = GetRam_aacEnc_PsyElement(i); + if (hPsy->psyElement[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + } + + for (i = 0; i < nChannels; i++) { + /* PSY_STATIC */ + hPsy->pStaticChannels[i] = GetRam_aacEnc_PsyStatic(i); + if (hPsy->pStaticChannels[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + /* AUDIO INPUT BUFFER */ + hPsy->pStaticChannels[i]->psyInputBuffer = GetRam_aacEnc_PsyInputBuffer(i); + if (hPsy->pStaticChannels[i]->psyInputBuffer == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + } + + /* reusable psych memory */ + hPsy->psyDynamic = GetRam_aacEnc_PsyDynamic(0, dynamic_RAM); + + return AAC_ENC_OK; + +bail: + FDKaacEnc_PsyClose(phpsy, NULL); + + return ErrorStatus; +} + +/***************************************************************************** + + functionname: FDKaacEnc_PsyOutNew + description: allocates memory for psyOut struc + returns: an error code + input: pointer to a psych handle + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_PsyOutNew(PSY_OUT **phpsyOut, const INT nElements, + const INT nChannels, const INT nSubFrames, + UCHAR *dynamic_RAM) { + AAC_ENCODER_ERROR ErrorStatus; + int n, i; + int elInc = 0, chInc = 0; + + for (n = 0; n < nSubFrames; n++) { + phpsyOut[n] = GetRam_aacEnc_PsyOut(n); + + if (phpsyOut[n] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + + for (i = 0; i < nChannels; i++) { + phpsyOut[n]->pPsyOutChannels[i] = GetRam_aacEnc_PsyOutChannel(chInc++); + if (NULL == phpsyOut[n]->pPsyOutChannels[i]) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + } + + for (i = 0; i < nElements; i++) { + phpsyOut[n]->psyOutElement[i] = GetRam_aacEnc_PsyOutElements(elInc++); + if (phpsyOut[n]->psyOutElement[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + } + } /* nSubFrames */ + + return AAC_ENC_OK; + +bail: + FDKaacEnc_PsyClose(NULL, phpsyOut); + return ErrorStatus; +} + +AAC_ENCODER_ERROR FDKaacEnc_psyInitStates(PSY_INTERNAL *hPsy, + PSY_STATIC *psyStatic, + AUDIO_OBJECT_TYPE audioObjectType) { + /* init input buffer */ + FDKmemclear(psyStatic->psyInputBuffer, + MAX_INPUT_BUFFER_SIZE * sizeof(INT_PCM)); + + FDKaacEnc_InitBlockSwitching(&psyStatic->blockSwitchingControl, + isLowDelay(audioObjectType)); + + return AAC_ENC_OK; +} + +AAC_ENCODER_ERROR FDKaacEnc_psyInit(PSY_INTERNAL *hPsy, PSY_OUT **phpsyOut, + const INT nSubFrames, + const INT nMaxChannels, + const AUDIO_OBJECT_TYPE audioObjectType, + CHANNEL_MAPPING *cm) { + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + int i, ch, n, chInc = 0, resetChannels = 3; + + if ((nMaxChannels > 2) && (cm->nChannels == 2)) { + chInc = 1; + FDKaacEnc_psyInitStates(hPsy, hPsy->pStaticChannels[0], audioObjectType); + } + + if ((nMaxChannels == 2)) { + resetChannels = 0; + } + + for (i = 0; i < cm->nElements; i++) { + for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) { + hPsy->psyElement[i]->psyStatic[ch] = hPsy->pStaticChannels[chInc]; + if (cm->elInfo[i].elType != ID_LFE) { + if (chInc >= resetChannels) { + FDKaacEnc_psyInitStates(hPsy, hPsy->psyElement[i]->psyStatic[ch], + audioObjectType); + } + mdct_init(&(hPsy->psyElement[i]->psyStatic[ch]->mdctPers), NULL, 0); + hPsy->psyElement[i]->psyStatic[ch]->isLFE = 0; + } else { + hPsy->psyElement[i]->psyStatic[ch]->isLFE = 1; + } + chInc++; + } + } + + for (n = 0; n < nSubFrames; n++) { + chInc = 0; + for (i = 0; i < cm->nElements; i++) { + for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) { + phpsyOut[n]->psyOutElement[i]->psyOutChannel[ch] = + phpsyOut[n]->pPsyOutChannels[chInc++]; + } + } + } + + return ErrorStatus; +} + +/***************************************************************************** + + functionname: FDKaacEnc_psyMainInit + description: initializes psychoacoustic + returns: an error code + +*****************************************************************************/ + +AAC_ENCODER_ERROR FDKaacEnc_psyMainInit( + PSY_INTERNAL *hPsy, AUDIO_OBJECT_TYPE audioObjectType, CHANNEL_MAPPING *cm, + INT sampleRate, INT granuleLength, INT bitRate, INT tnsMask, INT bandwidth, + INT usePns, INT useIS, INT useMS, UINT syntaxFlags, ULONG initFlags) { + AAC_ENCODER_ERROR ErrorStatus; + int i, ch; + int channelsEff = cm->nChannelsEff; + int tnsChannels = 0; + FB_TYPE filterBank; + + switch (FDKaacEnc_GetMonoStereoMode(cm->encMode)) { + /* ... and map to tnsChannels */ + case EL_MODE_MONO: + tnsChannels = 1; + break; + case EL_MODE_STEREO: + tnsChannels = 2; + break; + default: + tnsChannels = 0; + } + + switch (audioObjectType) { + default: + filterBank = FB_LC; + break; + case AOT_ER_AAC_LD: + filterBank = FB_LD; + break; + case AOT_ER_AAC_ELD: + filterBank = FB_ELD; + break; + } + + hPsy->granuleLength = granuleLength; + + ErrorStatus = FDKaacEnc_InitPsyConfiguration( + bitRate / channelsEff, sampleRate, bandwidth, LONG_WINDOW, + hPsy->granuleLength, useIS, useMS, &(hPsy->psyConf[0]), filterBank); + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + ErrorStatus = FDKaacEnc_InitTnsConfiguration( + (bitRate * tnsChannels) / channelsEff, sampleRate, tnsChannels, + LONG_WINDOW, hPsy->granuleLength, isLowDelay(audioObjectType), + (syntaxFlags & AC_SBR_PRESENT) ? 1 : 0, &(hPsy->psyConf[0].tnsConf), + &hPsy->psyConf[0], (INT)(tnsMask & 2), (INT)(tnsMask & 8)); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + if (granuleLength > 512) { + ErrorStatus = FDKaacEnc_InitPsyConfiguration( + bitRate / channelsEff, sampleRate, bandwidth, SHORT_WINDOW, + hPsy->granuleLength, useIS, useMS, &hPsy->psyConf[1], filterBank); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + ErrorStatus = FDKaacEnc_InitTnsConfiguration( + (bitRate * tnsChannels) / channelsEff, sampleRate, tnsChannels, + SHORT_WINDOW, hPsy->granuleLength, isLowDelay(audioObjectType), + (syntaxFlags & AC_SBR_PRESENT) ? 1 : 0, &hPsy->psyConf[1].tnsConf, + &hPsy->psyConf[1], (INT)(tnsMask & 1), (INT)(tnsMask & 4)); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + } + + for (i = 0; i < cm->nElements; i++) { + for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) { + if (initFlags) { + /* reset states */ + FDKaacEnc_psyInitStates(hPsy, hPsy->psyElement[i]->psyStatic[ch], + audioObjectType); + } + + FDKaacEnc_InitPreEchoControl( + hPsy->psyElement[i]->psyStatic[ch]->sfbThresholdnm1, + &hPsy->psyElement[i]->psyStatic[ch]->calcPreEcho, + hPsy->psyConf[0].sfbCnt, hPsy->psyConf[0].sfbPcmQuantThreshold, + &hPsy->psyElement[i]->psyStatic[ch]->mdctScalenm1); + } + } + + ErrorStatus = FDKaacEnc_InitPnsConfiguration( + &hPsy->psyConf[0].pnsConf, bitRate / channelsEff, sampleRate, usePns, + hPsy->psyConf[0].sfbCnt, hPsy->psyConf[0].sfbOffset, + cm->elInfo[0].nChannelsInEl, (hPsy->psyConf[0].filterbank == FB_LC)); + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + if (granuleLength > 512) { + ErrorStatus = FDKaacEnc_InitPnsConfiguration( + &hPsy->psyConf[1].pnsConf, bitRate / channelsEff, sampleRate, usePns, + hPsy->psyConf[1].sfbCnt, hPsy->psyConf[1].sfbOffset, + cm->elInfo[1].nChannelsInEl, (hPsy->psyConf[1].filterbank == FB_LC)); + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + } + + return ErrorStatus; +} + +/***************************************************************************** + + functionname: FDKaacEnc_psyMain + description: psychoacoustic + returns: an error code + + This function assumes that enough input data is in the modulo buffer. + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels, PSY_ELEMENT *psyElement, + PSY_DYNAMIC *psyDynamic, + PSY_CONFIGURATION *psyConf, + PSY_OUT_ELEMENT *RESTRICT psyOutElement, + INT_PCM *pInput, const UINT inputBufSize, + INT *chIdx, INT totalChannels) { + const INT commonWindow = 1; + INT maxSfbPerGroup[(2)]; + INT mdctSpectrum_e; + INT ch; /* counts through channels */ + INT w; /* counts through windows */ + INT sfb; /* counts through scalefactor bands */ + INT line; /* counts through lines */ + + PSY_CONFIGURATION *RESTRICT hPsyConfLong = &psyConf[0]; + PSY_CONFIGURATION *RESTRICT hPsyConfShort = &psyConf[1]; + PSY_OUT_CHANNEL **RESTRICT psyOutChannel = psyOutElement->psyOutChannel; + FIXP_SGL sfbTonality[(2)][MAX_SFB_LONG]; + + PSY_STATIC **RESTRICT psyStatic = psyElement->psyStatic; + + PSY_DATA *RESTRICT psyData[(2)]; + TNS_DATA *RESTRICT tnsData[(2)]; + PNS_DATA *RESTRICT pnsData[(2)]; + + INT zeroSpec = TRUE; /* means all spectral lines are zero */ + + INT blockSwitchingOffset; + + PSY_CONFIGURATION *RESTRICT hThisPsyConf[(2)]; + INT windowLength[(2)]; + INT nWindows[(2)]; + INT wOffset; + + INT maxSfb[(2)]; + INT *pSfbMaxScaleSpec[(2)]; + FIXP_DBL *pSfbEnergy[(2)]; + FIXP_DBL *pSfbSpreadEnergy[(2)]; + FIXP_DBL *pSfbEnergyLdData[(2)]; + FIXP_DBL *pSfbEnergyMS[(2)]; + FIXP_DBL *pSfbThreshold[(2)]; + + INT isShortWindow[(2)]; + + /* number of incoming time samples to be processed */ + const INT nTimeSamples = psyConf->granuleLength; + + switch (hPsyConfLong->filterbank) { + case FB_LC: + blockSwitchingOffset = + nTimeSamples + (9 * nTimeSamples / (2 * TRANS_FAC)); + break; + case FB_LD: + case FB_ELD: + blockSwitchingOffset = nTimeSamples; + break; + default: + return AAC_ENC_UNSUPPORTED_FILTERBANK; + } + + for (ch = 0; ch < channels; ch++) { + psyData[ch] = &psyDynamic->psyData[ch]; + tnsData[ch] = &psyDynamic->tnsData[ch]; + pnsData[ch] = &psyDynamic->pnsData[ch]; + + psyData[ch]->mdctSpectrum = psyOutChannel[ch]->mdctSpectrum; + } + + /* block switching */ + if (hPsyConfLong->filterbank != FB_ELD) { + int err; + + for (ch = 0; ch < channels; ch++) { + C_ALLOC_SCRATCH_START(pTimeSignal, INT_PCM, (1024)) + + /* copy input data and use for block switching */ + FDKmemcpy(pTimeSignal, pInput + chIdx[ch] * inputBufSize, + nTimeSamples * sizeof(INT_PCM)); + + FDKaacEnc_BlockSwitching(&psyStatic[ch]->blockSwitchingControl, + nTimeSamples, psyStatic[ch]->isLFE, pTimeSignal); + + /* fill up internal input buffer, to 2xframelength samples */ + FDKmemcpy(psyStatic[ch]->psyInputBuffer + blockSwitchingOffset, + pTimeSignal, + (2 * nTimeSamples - blockSwitchingOffset) * sizeof(INT_PCM)); + + C_ALLOC_SCRATCH_END(pTimeSignal, INT_PCM, (1024)) + } + + /* synch left and right block type */ + err = FDKaacEnc_SyncBlockSwitching( + &psyStatic[0]->blockSwitchingControl, + (channels > 1) ? &psyStatic[1]->blockSwitchingControl : NULL, channels, + commonWindow); + + if (err) { + return AAC_ENC_UNSUPPORTED_AOT; /* mixed up LC and LD */ + } + + } else { + for (ch = 0; ch < channels; ch++) { + /* copy input data and use for block switching */ + FDKmemcpy(psyStatic[ch]->psyInputBuffer + blockSwitchingOffset, + pInput + chIdx[ch] * inputBufSize, + nTimeSamples * sizeof(INT_PCM)); + } + } + + for (ch = 0; ch < channels; ch++) + isShortWindow[ch] = + (psyStatic[ch]->blockSwitchingControl.lastWindowSequence == + SHORT_WINDOW); + + /* set parameters according to window length */ + for (ch = 0; ch < channels; ch++) { + if (isShortWindow[ch]) { + hThisPsyConf[ch] = hPsyConfShort; + windowLength[ch] = psyConf->granuleLength / TRANS_FAC; + nWindows[ch] = TRANS_FAC; + maxSfb[ch] = MAX_SFB_SHORT; + + pSfbMaxScaleSpec[ch] = psyData[ch]->sfbMaxScaleSpec.Short[0]; + pSfbEnergy[ch] = psyData[ch]->sfbEnergy.Short[0]; + pSfbSpreadEnergy[ch] = psyData[ch]->sfbSpreadEnergy.Short[0]; + pSfbEnergyLdData[ch] = psyData[ch]->sfbEnergyLdData.Short[0]; + pSfbEnergyMS[ch] = psyData[ch]->sfbEnergyMS.Short[0]; + pSfbThreshold[ch] = psyData[ch]->sfbThreshold.Short[0]; + + } else { + hThisPsyConf[ch] = hPsyConfLong; + windowLength[ch] = psyConf->granuleLength; + nWindows[ch] = 1; + maxSfb[ch] = MAX_GROUPED_SFB; + + pSfbMaxScaleSpec[ch] = psyData[ch]->sfbMaxScaleSpec.Long; + pSfbEnergy[ch] = psyData[ch]->sfbEnergy.Long; + pSfbSpreadEnergy[ch] = psyData[ch]->sfbSpreadEnergy.Long; + pSfbEnergyLdData[ch] = psyData[ch]->sfbEnergyLdData.Long; + pSfbEnergyMS[ch] = psyData[ch]->sfbEnergyMS.Long; + pSfbThreshold[ch] = psyData[ch]->sfbThreshold.Long; + } + } + + /* Transform and get mdctScaling for all channels and windows. */ + for (ch = 0; ch < channels; ch++) { + /* update number of active bands */ + if (psyStatic[ch]->isLFE) { + psyData[ch]->sfbActive = hThisPsyConf[ch]->sfbActiveLFE; + psyData[ch]->lowpassLine = hThisPsyConf[ch]->lowpassLineLFE; + } else { + psyData[ch]->sfbActive = hThisPsyConf[ch]->sfbActive; + psyData[ch]->lowpassLine = hThisPsyConf[ch]->lowpassLine; + } + + if (hThisPsyConf[ch]->filterbank == FB_ELD) { + if (FDKaacEnc_Transform_Real_Eld( + psyStatic[ch]->psyInputBuffer, psyData[ch]->mdctSpectrum, + psyStatic[ch]->blockSwitchingControl.lastWindowSequence, + psyStatic[ch]->blockSwitchingControl.windowShape, + &psyStatic[ch]->blockSwitchingControl.lastWindowShape, + nTimeSamples, &mdctSpectrum_e, hThisPsyConf[ch]->filterbank, + psyStatic[ch]->overlapAddBuffer) != 0) { + return AAC_ENC_UNSUPPORTED_FILTERBANK; + } + } else { + if (FDKaacEnc_Transform_Real( + psyStatic[ch]->psyInputBuffer, psyData[ch]->mdctSpectrum, + psyStatic[ch]->blockSwitchingControl.lastWindowSequence, + psyStatic[ch]->blockSwitchingControl.windowShape, + &psyStatic[ch]->blockSwitchingControl.lastWindowShape, + &psyStatic[ch]->mdctPers, nTimeSamples, &mdctSpectrum_e, + hThisPsyConf[ch]->filterbank) != 0) { + return AAC_ENC_UNSUPPORTED_FILTERBANK; + } + } + + for (w = 0; w < nWindows[ch]; w++) { + wOffset = w * windowLength[ch]; + + /* Low pass / highest sfb */ + FDKmemclear( + &psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine + wOffset], + (windowLength[ch] - psyData[ch]->lowpassLine) * sizeof(FIXP_DBL)); + + if ((hPsyConfLong->filterbank != FB_LC) && + (psyData[ch]->lowpassLine >= FADE_OUT_LEN)) { + /* Do blending to reduce gibbs artifacts */ + for (int i = 0; i < FADE_OUT_LEN; i++) { + psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine + wOffset - + FADE_OUT_LEN + i] = + fMult(psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine + + wOffset - FADE_OUT_LEN + i], + fadeOutFactor[i]); + } + } + + /* Check for zero spectrum. These loops will usually terminate very, very + * early. */ + for (line = 0; (line < psyData[ch]->lowpassLine) && (zeroSpec == TRUE); + line++) { + if (psyData[ch]->mdctSpectrum[line + wOffset] != (FIXP_DBL)0) { + zeroSpec = FALSE; + break; + } + } + + } /* w loop */ + + psyData[ch]->mdctScale = mdctSpectrum_e; + + /* rotate internal time samples */ + FDKmemmove(psyStatic[ch]->psyInputBuffer, + psyStatic[ch]->psyInputBuffer + nTimeSamples, + nTimeSamples * sizeof(INT_PCM)); + + /* ... and get remaining samples from input buffer */ + FDKmemcpy(psyStatic[ch]->psyInputBuffer + nTimeSamples, + pInput + (2 * nTimeSamples - blockSwitchingOffset) + + chIdx[ch] * inputBufSize, + (blockSwitchingOffset - nTimeSamples) * sizeof(INT_PCM)); + + } /* ch */ + + /* Do some rescaling to get maximum possible accuracy for energies */ + if (zeroSpec == FALSE) { + /* Calc possible spectrum leftshift for each sfb (1 means: 1 bit left shift + * is possible without overflow) */ + INT minSpecShift = MAX_SHIFT_DBL; + INT nrgShift = MAX_SHIFT_DBL; + INT finalShift = MAX_SHIFT_DBL; + FIXP_DBL currNrg = 0; + FIXP_DBL maxNrg = 0; + + for (ch = 0; ch < channels; ch++) { + for (w = 0; w < nWindows[ch]; w++) { + wOffset = w * windowLength[ch]; + FDKaacEnc_CalcSfbMaxScaleSpec( + psyData[ch]->mdctSpectrum + wOffset, hThisPsyConf[ch]->sfbOffset, + pSfbMaxScaleSpec[ch] + w * maxSfb[ch], psyData[ch]->sfbActive); + + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) + minSpecShift = fixMin(minSpecShift, + (pSfbMaxScaleSpec[ch] + w * maxSfb[ch])[sfb]); + } + } + + /* Calc possible energy leftshift for each sfb (1 means: 1 bit left shift is + * possible without overflow) */ + for (ch = 0; ch < channels; ch++) { + for (w = 0; w < nWindows[ch]; w++) { + wOffset = w * windowLength[ch]; + currNrg = FDKaacEnc_CheckBandEnergyOptim( + psyData[ch]->mdctSpectrum + wOffset, + pSfbMaxScaleSpec[ch] + w * maxSfb[ch], hThisPsyConf[ch]->sfbOffset, + psyData[ch]->sfbActive, pSfbEnergy[ch] + w * maxSfb[ch], + pSfbEnergyLdData[ch] + w * maxSfb[ch], minSpecShift - 4); + + maxNrg = fixMax(maxNrg, currNrg); + } + } + + if (maxNrg != (FIXP_DBL)0) { + nrgShift = (CountLeadingBits(maxNrg) >> 1) + (minSpecShift - 4); + } + + /* 2check: Hasn't this decision to be made for both channels? */ + /* For short windows 1 additional bit headroom is necessary to prevent + * overflows when summing up energies in FDKaacEnc_groupShortData() */ + if (isShortWindow[0]) nrgShift--; + + /* both spectrum and energies mustn't overflow */ + finalShift = fixMin(minSpecShift, nrgShift); + + /* do not shift more than 3 bits more to the left than signal without + * blockfloating point would be to avoid overflow of scaled PCM quantization + * thresholds */ + if (finalShift > psyData[0]->mdctScale + 3) + finalShift = psyData[0]->mdctScale + 3; + + FDK_ASSERT(finalShift >= 0); /* right shift is not allowed */ + + /* correct sfbEnergy and sfbEnergyLdData with new finalShift */ + FIXP_DBL ldShift = finalShift * FL2FXCONST_DBL(2.0 / 64); + for (ch = 0; ch < channels; ch++) { + INT maxSfb_ch = maxSfb[ch]; + INT w_maxSfb_ch = 0; + for (w = 0; w < nWindows[ch]; w++) { + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + INT scale = fixMax(0, (pSfbMaxScaleSpec[ch] + w_maxSfb_ch)[sfb] - 4); + scale = fixMin((scale - finalShift) << 1, DFRACT_BITS - 1); + if (scale >= 0) + (pSfbEnergy[ch] + w_maxSfb_ch)[sfb] >>= (scale); + else + (pSfbEnergy[ch] + w_maxSfb_ch)[sfb] <<= (-scale); + (pSfbThreshold[ch] + w_maxSfb_ch)[sfb] = + fMult((pSfbEnergy[ch] + w_maxSfb_ch)[sfb], C_RATIO); + (pSfbEnergyLdData[ch] + w_maxSfb_ch)[sfb] += ldShift; + } + w_maxSfb_ch += maxSfb_ch; + } + } + + if (finalShift != 0) { + for (ch = 0; ch < channels; ch++) { + INT wLen = windowLength[ch]; + INT lowpassLine = psyData[ch]->lowpassLine; + wOffset = 0; + FIXP_DBL *mdctSpectrum = &psyData[ch]->mdctSpectrum[0]; + for (w = 0; w < nWindows[ch]; w++) { + FIXP_DBL *spectrum = &mdctSpectrum[wOffset]; + for (line = 0; line < lowpassLine; line++) { + spectrum[line] <<= finalShift; + } + wOffset += wLen; + + /* update sfbMaxScaleSpec */ + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) + (pSfbMaxScaleSpec[ch] + w * maxSfb[ch])[sfb] -= finalShift; + } + /* update mdctScale */ + psyData[ch]->mdctScale -= finalShift; + } + } + + } else { + /* all spectral lines are zero */ + for (ch = 0; ch < channels; ch++) { + psyData[ch]->mdctScale = + 0; /* otherwise mdctScale would be for example 7 and PCM quantization + * thresholds would be shifted 14 bits to the right causing some of + * them to become 0 (which causes problems later) */ + /* clear sfbMaxScaleSpec */ + for (w = 0; w < nWindows[ch]; w++) { + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + (pSfbMaxScaleSpec[ch] + w * maxSfb[ch])[sfb] = 0; + (pSfbEnergy[ch] + w * maxSfb[ch])[sfb] = (FIXP_DBL)0; + (pSfbEnergyLdData[ch] + w * maxSfb[ch])[sfb] = FL2FXCONST_DBL(-1.0f); + (pSfbThreshold[ch] + w * maxSfb[ch])[sfb] = (FIXP_DBL)0; + } + } + } + } + + /* Advance psychoacoustics: Tonality and TNS */ + if ((channels >= 1) && (psyStatic[0]->isLFE)) { + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] = 0; + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] = 0; + } else { + for (ch = 0; ch < channels; ch++) { + if (!isShortWindow[ch]) { + /* tonality */ + FDKaacEnc_CalculateFullTonality( + psyData[ch]->mdctSpectrum, pSfbMaxScaleSpec[ch], + pSfbEnergyLdData[ch], sfbTonality[ch], psyData[ch]->sfbActive, + hThisPsyConf[ch]->sfbOffset, hThisPsyConf[ch]->pnsConf.usePns); + } + } /* ch */ + + if (hPsyConfLong->tnsConf.tnsActive || hPsyConfShort->tnsConf.tnsActive) { + INT tnsActive[TRANS_FAC] = {0}; + INT nrgScaling[2] = {0, 0}; + INT tnsSpecShift = 0; + + for (ch = 0; ch < channels; ch++) { + for (w = 0; w < nWindows[ch]; w++) { + wOffset = w * windowLength[ch]; + /* TNS */ + FDKaacEnc_TnsDetect( + tnsData[ch], &hThisPsyConf[ch]->tnsConf, + &psyOutChannel[ch]->tnsInfo, hThisPsyConf[ch]->sfbCnt, + psyData[ch]->mdctSpectrum + wOffset, w, + psyStatic[ch]->blockSwitchingControl.lastWindowSequence); + } + } + + if (channels == 2) { + FDKaacEnc_TnsSync( + tnsData[1], tnsData[0], &psyOutChannel[1]->tnsInfo, + &psyOutChannel[0]->tnsInfo, + + psyStatic[1]->blockSwitchingControl.lastWindowSequence, + psyStatic[0]->blockSwitchingControl.lastWindowSequence, + &hThisPsyConf[1]->tnsConf); + } + + if (channels >= 1) { + FDK_ASSERT(1 == commonWindow); /* all checks for TNS do only work for + common windows (which is always set)*/ + for (w = 0; w < nWindows[0]; w++) { + if (isShortWindow[0]) + tnsActive[w] = + tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[HIFILT] || + tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[LOFILT] || + tnsData[channels - 1] + ->dataRaw.Short.subBlockInfo[w] + .tnsActive[HIFILT] || + tnsData[channels - 1] + ->dataRaw.Short.subBlockInfo[w] + .tnsActive[LOFILT]; + else + tnsActive[w] = + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] || + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] || + tnsData[channels - 1] + ->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] || + tnsData[channels - 1] + ->dataRaw.Long.subBlockInfo.tnsActive[LOFILT]; + } + } + + for (ch = 0; ch < channels; ch++) { + if (tnsActive[0] && !isShortWindow[ch]) { + /* Scale down spectrum if tns is active in one of the two channels + * with same lastWindowSequence */ + /* first part of threshold calculation; it's not necessary to update + * sfbMaxScaleSpec */ + INT shift = 1; + for (sfb = 0; sfb < hThisPsyConf[ch]->lowpassLine; sfb++) { + psyData[ch]->mdctSpectrum[sfb] = + psyData[ch]->mdctSpectrum[sfb] >> shift; + } + + /* update thresholds */ + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + pSfbThreshold[ch][sfb] >>= (2 * shift); + } + + psyData[ch]->mdctScale += shift; /* update mdctScale */ + + /* calc sfbEnergies after tnsEncode again ! */ + } + } + + for (ch = 0; ch < channels; ch++) { + for (w = 0; w < nWindows[ch]; w++) { + wOffset = w * windowLength[ch]; + FDKaacEnc_TnsEncode( + &psyOutChannel[ch]->tnsInfo, tnsData[ch], + hThisPsyConf[ch]->sfbCnt, &hThisPsyConf[ch]->tnsConf, + hThisPsyConf[ch]->sfbOffset[psyData[ch]->sfbActive], + /*hThisPsyConf[ch]->lowpassLine*/ /* filter stops + before that + line ! */ + psyData[ch]->mdctSpectrum + + wOffset, + w, psyStatic[ch]->blockSwitchingControl.lastWindowSequence); + + if (tnsActive[w]) { + /* Calc sfb-bandwise mdct-energies for left and right channel again, + */ + /* if tns active in current channel or in one channel with same + * lastWindowSequence left and right */ + FDKaacEnc_CalcSfbMaxScaleSpec(psyData[ch]->mdctSpectrum + wOffset, + hThisPsyConf[ch]->sfbOffset, + pSfbMaxScaleSpec[ch] + w * maxSfb[ch], + psyData[ch]->sfbActive); + } + } + } + + for (ch = 0; ch < channels; ch++) { + for (w = 0; w < nWindows[ch]; w++) { + if (tnsActive[w]) { + if (isShortWindow[ch]) { + FDKaacEnc_CalcBandEnergyOptimShort( + psyData[ch]->mdctSpectrum + w * windowLength[ch], + pSfbMaxScaleSpec[ch] + w * maxSfb[ch], + hThisPsyConf[ch]->sfbOffset, psyData[ch]->sfbActive, + pSfbEnergy[ch] + w * maxSfb[ch]); + } else { + nrgScaling[ch] = /* with tns, energy calculation can overflow; -> + scaling */ + FDKaacEnc_CalcBandEnergyOptimLong( + psyData[ch]->mdctSpectrum, pSfbMaxScaleSpec[ch], + hThisPsyConf[ch]->sfbOffset, psyData[ch]->sfbActive, + pSfbEnergy[ch], pSfbEnergyLdData[ch]); + tnsSpecShift = + fixMax(tnsSpecShift, nrgScaling[ch]); /* nrgScaling is set + only if nrg would + have an overflow */ + } + } /* if tnsActive */ + } + } /* end channel loop */ + + /* adapt scaling to prevent nrg overflow, only for long blocks */ + for (ch = 0; ch < channels; ch++) { + if ((tnsSpecShift != 0) && !isShortWindow[ch]) { + /* scale down spectrum, nrg's and thresholds, if there was an overflow + * in sfbNrg calculation after tns */ + for (line = 0; line < hThisPsyConf[ch]->lowpassLine; line++) { + psyData[ch]->mdctSpectrum[line] >>= tnsSpecShift; + } + INT scale = (tnsSpecShift - nrgScaling[ch]) << 1; + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + pSfbEnergyLdData[ch][sfb] -= + scale * FL2FXCONST_DBL(1.0 / LD_DATA_SCALING); + pSfbEnergy[ch][sfb] >>= scale; + pSfbThreshold[ch][sfb] >>= (tnsSpecShift << 1); + } + psyData[ch]->mdctScale += tnsSpecShift; /* update mdctScale; not + necessary to update + sfbMaxScaleSpec */ + } + } /* end channel loop */ + + } /* TNS active */ + else { + /* In case of disable TNS, reset its dynamic data. Some of its elements is + * required in PNS detection below. */ + FDKmemclear(psyDynamic->tnsData, sizeof(psyDynamic->tnsData)); + } + } /* !isLFE */ + + /* Advance thresholds */ + for (ch = 0; ch < channels; ch++) { + INT headroom; + + FIXP_DBL clipEnergy; + INT energyShift = psyData[ch]->mdctScale * 2; + INT clipNrgShift = energyShift - THR_SHIFTBITS; + if (isShortWindow[ch]) + headroom = 6; + else + headroom = 0; + + if (clipNrgShift >= 0) + clipEnergy = hThisPsyConf[ch]->clipEnergy >> clipNrgShift; + else if (clipNrgShift >= -headroom) + clipEnergy = hThisPsyConf[ch]->clipEnergy << -clipNrgShift; + else + clipEnergy = (FIXP_DBL)MAXVAL_DBL; + + for (w = 0; w < nWindows[ch]; w++) { + INT i; + /* limit threshold to avoid clipping */ + for (i = 0; i < psyData[ch]->sfbActive; i++) { + *(pSfbThreshold[ch] + w * maxSfb[ch] + i) = + fixMin(*(pSfbThreshold[ch] + w * maxSfb[ch] + i), clipEnergy); + } + + /* spreading */ + FDKaacEnc_SpreadingMax(psyData[ch]->sfbActive, + hThisPsyConf[ch]->sfbMaskLowFactor, + hThisPsyConf[ch]->sfbMaskHighFactor, + pSfbThreshold[ch] + w * maxSfb[ch]); + + /* PCM quantization threshold */ + energyShift += PCM_QUANT_THR_SCALE; + if (energyShift >= 0) { + energyShift = fixMin(DFRACT_BITS - 1, energyShift); + for (i = 0; i < psyData[ch]->sfbActive; i++) { + *(pSfbThreshold[ch] + w * maxSfb[ch] + i) = fixMax( + *(pSfbThreshold[ch] + w * maxSfb[ch] + i) >> THR_SHIFTBITS, + (hThisPsyConf[ch]->sfbPcmQuantThreshold[i] >> energyShift)); + } + } else { + energyShift = fixMin(DFRACT_BITS - 1, -energyShift); + for (i = 0; i < psyData[ch]->sfbActive; i++) { + *(pSfbThreshold[ch] + w * maxSfb[ch] + i) = fixMax( + *(pSfbThreshold[ch] + w * maxSfb[ch] + i) >> THR_SHIFTBITS, + (hThisPsyConf[ch]->sfbPcmQuantThreshold[i] << energyShift)); + } + } + + if (!psyStatic[ch]->isLFE) { + /* preecho control */ + if (psyStatic[ch]->blockSwitchingControl.lastWindowSequence == + STOP_WINDOW) { + /* prevent FDKaacEnc_PreEchoControl from comparing stop + thresholds with short thresholds */ + for (i = 0; i < psyData[ch]->sfbActive; i++) { + psyStatic[ch]->sfbThresholdnm1[i] = (FIXP_DBL)MAXVAL_DBL; + } + + psyStatic[ch]->mdctScalenm1 = 0; + psyStatic[ch]->calcPreEcho = 0; + } + + FDKaacEnc_PreEchoControl( + psyStatic[ch]->sfbThresholdnm1, psyStatic[ch]->calcPreEcho, + psyData[ch]->sfbActive, hThisPsyConf[ch]->maxAllowedIncreaseFactor, + hThisPsyConf[ch]->minRemainingThresholdFactor, + pSfbThreshold[ch] + w * maxSfb[ch], psyData[ch]->mdctScale, + &psyStatic[ch]->mdctScalenm1); + + psyStatic[ch]->calcPreEcho = 1; + + if (psyStatic[ch]->blockSwitchingControl.lastWindowSequence == + START_WINDOW) { + /* prevent FDKaacEnc_PreEchoControl in next frame to compare start + thresholds with short thresholds */ + for (i = 0; i < psyData[ch]->sfbActive; i++) { + psyStatic[ch]->sfbThresholdnm1[i] = (FIXP_DBL)MAXVAL_DBL; + } + + psyStatic[ch]->mdctScalenm1 = 0; + psyStatic[ch]->calcPreEcho = 0; + } + } + + /* spread energy to avoid hole detection */ + FDKmemcpy(pSfbSpreadEnergy[ch] + w * maxSfb[ch], + pSfbEnergy[ch] + w * maxSfb[ch], + psyData[ch]->sfbActive * sizeof(FIXP_DBL)); + + FDKaacEnc_SpreadingMax(psyData[ch]->sfbActive, + hThisPsyConf[ch]->sfbMaskLowFactorSprEn, + hThisPsyConf[ch]->sfbMaskHighFactorSprEn, + pSfbSpreadEnergy[ch] + w * maxSfb[ch]); + } + } + + /* Calc bandwise energies for mid and side channel. Do it only if 2 channels + * exist */ + if (channels == 2) { + for (w = 0; w < nWindows[1]; w++) { + wOffset = w * windowLength[1]; + FDKaacEnc_CalcBandNrgMSOpt( + psyData[0]->mdctSpectrum + wOffset, + psyData[1]->mdctSpectrum + wOffset, + pSfbMaxScaleSpec[0] + w * maxSfb[0], + pSfbMaxScaleSpec[1] + w * maxSfb[1], hThisPsyConf[1]->sfbOffset, + psyData[0]->sfbActive, pSfbEnergyMS[0] + w * maxSfb[0], + pSfbEnergyMS[1] + w * maxSfb[1], + (psyStatic[1]->blockSwitchingControl.lastWindowSequence != + SHORT_WINDOW), + psyData[0]->sfbEnergyMSLdData, psyData[1]->sfbEnergyMSLdData); + } + } + + /* group short data (maxSfb[ch] for short blocks is determined here) */ + for (ch = 0; ch < channels; ch++) { + if (isShortWindow[ch]) { + int sfbGrp; + int noSfb = psyStatic[ch]->blockSwitchingControl.noOfGroups * + hPsyConfShort->sfbCnt; + /* At this point, energies and thresholds are copied/regrouped from the + * ".Short" to the ".Long" arrays */ + FDKaacEnc_groupShortData( + psyData[ch]->mdctSpectrum, &psyData[ch]->sfbThreshold, + &psyData[ch]->sfbEnergy, &psyData[ch]->sfbEnergyMS, + &psyData[ch]->sfbSpreadEnergy, hPsyConfShort->sfbCnt, + psyData[ch]->sfbActive, hPsyConfShort->sfbOffset, + hPsyConfShort->sfbMinSnrLdData, psyData[ch]->groupedSfbOffset, + &maxSfbPerGroup[ch], psyOutChannel[ch]->sfbMinSnrLdData, + psyStatic[ch]->blockSwitchingControl.noOfGroups, + psyStatic[ch]->blockSwitchingControl.groupLen, + psyConf[1].granuleLength); + + /* calculate ldData arrays (short values are in .Long-arrays after + * FDKaacEnc_groupShortData) */ + for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) { + LdDataVector(&psyData[ch]->sfbEnergy.Long[sfbGrp], + &psyOutChannel[ch]->sfbEnergyLdData[sfbGrp], + psyData[ch]->sfbActive); + } + + /* calc sfbThrld and set Values smaller 2^-31 to 2^-33*/ + for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) { + LdDataVector(&psyData[ch]->sfbThreshold.Long[sfbGrp], + &psyOutChannel[ch]->sfbThresholdLdData[sfbGrp], + psyData[ch]->sfbActive); + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + psyOutChannel[ch]->sfbThresholdLdData[sfbGrp + sfb] = + fixMax(psyOutChannel[ch]->sfbThresholdLdData[sfbGrp + sfb], + FL2FXCONST_DBL(-0.515625f)); + } + } + + if (channels == 2) { + for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) { + LdDataVector(&psyData[ch]->sfbEnergyMS.Long[sfbGrp], + &psyData[ch]->sfbEnergyMSLdData[sfbGrp], + psyData[ch]->sfbActive); + } + } + + FDKmemcpy(psyOutChannel[ch]->sfbOffsets, psyData[ch]->groupedSfbOffset, + (MAX_GROUPED_SFB + 1) * sizeof(INT)); + + } else { + int i; + /* maxSfb[ch] for long blocks */ + for (sfb = psyData[ch]->sfbActive - 1; sfb >= 0; sfb--) { + for (line = hPsyConfLong->sfbOffset[sfb + 1] - 1; + line >= hPsyConfLong->sfbOffset[sfb]; line--) { + if (psyData[ch]->mdctSpectrum[line] != FL2FXCONST_SGL(0.0f)) break; + } + if (line > hPsyConfLong->sfbOffset[sfb]) break; + } + maxSfbPerGroup[ch] = sfb + 1; + maxSfbPerGroup[ch] = + fixMax(fixMin(5, psyData[ch]->sfbActive), maxSfbPerGroup[ch]); + + /* sfbNrgLdData is calculated in FDKaacEnc_advancePsychLong, copy in + * psyOut structure */ + FDKmemcpy(psyOutChannel[ch]->sfbEnergyLdData, + psyData[ch]->sfbEnergyLdData.Long, + psyData[ch]->sfbActive * sizeof(FIXP_DBL)); + + FDKmemcpy(psyOutChannel[ch]->sfbOffsets, hPsyConfLong->sfbOffset, + (MAX_GROUPED_SFB + 1) * sizeof(INT)); + + /* sfbMinSnrLdData modified in adjust threshold, copy necessary */ + FDKmemcpy(psyOutChannel[ch]->sfbMinSnrLdData, + hPsyConfLong->sfbMinSnrLdData, + psyData[ch]->sfbActive * sizeof(FIXP_DBL)); + + /* sfbEnergyMSLdData ist already calculated in FDKaacEnc_CalcBandNrgMSOpt; + * only in long case */ + + /* calc sfbThrld and set Values smaller 2^-31 to 2^-33*/ + LdDataVector(psyData[ch]->sfbThreshold.Long, + psyOutChannel[ch]->sfbThresholdLdData, + psyData[ch]->sfbActive); + for (i = 0; i < psyData[ch]->sfbActive; i++) { + psyOutChannel[ch]->sfbThresholdLdData[i] = + fixMax(psyOutChannel[ch]->sfbThresholdLdData[i], + FL2FXCONST_DBL(-0.515625f)); + } + } + } + + /* + Intensity parameter intialization. + */ + for (ch = 0; ch < channels; ch++) { + FDKmemclear(psyOutChannel[ch]->isBook, MAX_GROUPED_SFB * sizeof(INT)); + FDKmemclear(psyOutChannel[ch]->isScale, MAX_GROUPED_SFB * sizeof(INT)); + } + + for (ch = 0; ch < channels; ch++) { + INT win = (isShortWindow[ch] ? 1 : 0); + if (!psyStatic[ch]->isLFE) { + /* PNS Decision */ + FDKaacEnc_PnsDetect( + &(psyConf[0].pnsConf), pnsData[ch], + psyStatic[ch]->blockSwitchingControl.lastWindowSequence, + psyData[ch]->sfbActive, + maxSfbPerGroup[ch], /* count of Sfb which are not zero. */ + psyOutChannel[ch]->sfbThresholdLdData, psyConf[win].sfbOffset, + psyData[ch]->mdctSpectrum, psyData[ch]->sfbMaxScaleSpec.Long, + sfbTonality[ch], psyOutChannel[ch]->tnsInfo.order[0][0], + tnsData[ch]->dataRaw.Long.subBlockInfo.predictionGain[HIFILT], + tnsData[ch]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT], + psyOutChannel[ch]->sfbEnergyLdData, psyOutChannel[ch]->noiseNrg); + } /* !isLFE */ + } /* ch */ + + /* + stereo Processing + */ + if (channels == 2) { + psyOutElement->toolsInfo.msDigest = MS_NONE; + psyOutElement->commonWindow = commonWindow; + if (psyOutElement->commonWindow) + maxSfbPerGroup[0] = maxSfbPerGroup[1] = + fixMax(maxSfbPerGroup[0], maxSfbPerGroup[1]); + if (psyStatic[0]->blockSwitchingControl.lastWindowSequence != + SHORT_WINDOW) { + /* PNS preprocessing depending on ms processing: PNS not in Short Window! + */ + FDKaacEnc_PreProcessPnsChannelPair( + psyData[0]->sfbActive, (&psyData[0]->sfbEnergy)->Long, + (&psyData[1]->sfbEnergy)->Long, psyOutChannel[0]->sfbEnergyLdData, + psyOutChannel[1]->sfbEnergyLdData, psyData[0]->sfbEnergyMS.Long, + &(psyConf[0].pnsConf), pnsData[0], pnsData[1]); + + FDKaacEnc_IntensityStereoProcessing( + psyData[0]->sfbEnergy.Long, psyData[1]->sfbEnergy.Long, + psyData[0]->mdctSpectrum, psyData[1]->mdctSpectrum, + psyData[0]->sfbThreshold.Long, psyData[1]->sfbThreshold.Long, + psyOutChannel[1]->sfbThresholdLdData, + psyData[0]->sfbSpreadEnergy.Long, psyData[1]->sfbSpreadEnergy.Long, + psyOutChannel[0]->sfbEnergyLdData, psyOutChannel[1]->sfbEnergyLdData, + &psyOutElement->toolsInfo.msDigest, psyOutElement->toolsInfo.msMask, + psyConf[0].sfbCnt, psyConf[0].sfbCnt, maxSfbPerGroup[0], + psyConf[0].sfbOffset, + psyConf[0].allowIS && psyOutElement->commonWindow, + psyOutChannel[1]->isBook, psyOutChannel[1]->isScale, pnsData); + + FDKaacEnc_MsStereoProcessing( + psyData, psyOutChannel, psyOutChannel[1]->isBook, + &psyOutElement->toolsInfo.msDigest, psyOutElement->toolsInfo.msMask, + psyConf[0].allowMS, psyData[0]->sfbActive, psyData[0]->sfbActive, + maxSfbPerGroup[0], psyOutChannel[0]->sfbOffsets); + + /* PNS postprocessing */ + FDKaacEnc_PostProcessPnsChannelPair( + psyData[0]->sfbActive, &(psyConf[0].pnsConf), pnsData[0], pnsData[1], + psyOutElement->toolsInfo.msMask, &psyOutElement->toolsInfo.msDigest); + + } else { + FDKaacEnc_IntensityStereoProcessing( + psyData[0]->sfbEnergy.Long, psyData[1]->sfbEnergy.Long, + psyData[0]->mdctSpectrum, psyData[1]->mdctSpectrum, + psyData[0]->sfbThreshold.Long, psyData[1]->sfbThreshold.Long, + psyOutChannel[1]->sfbThresholdLdData, + psyData[0]->sfbSpreadEnergy.Long, psyData[1]->sfbSpreadEnergy.Long, + psyOutChannel[0]->sfbEnergyLdData, psyOutChannel[1]->sfbEnergyLdData, + &psyOutElement->toolsInfo.msDigest, psyOutElement->toolsInfo.msMask, + psyStatic[0]->blockSwitchingControl.noOfGroups * + hPsyConfShort->sfbCnt, + psyConf[1].sfbCnt, maxSfbPerGroup[0], psyData[0]->groupedSfbOffset, + psyConf[0].allowIS && psyOutElement->commonWindow, + psyOutChannel[1]->isBook, psyOutChannel[1]->isScale, pnsData); + + /* it's OK to pass the ".Long" arrays here. They contain grouped short + * data since FDKaacEnc_groupShortData() */ + FDKaacEnc_MsStereoProcessing( + psyData, psyOutChannel, psyOutChannel[1]->isBook, + &psyOutElement->toolsInfo.msDigest, psyOutElement->toolsInfo.msMask, + psyConf[1].allowMS, + psyStatic[0]->blockSwitchingControl.noOfGroups * + hPsyConfShort->sfbCnt, + hPsyConfShort->sfbCnt, maxSfbPerGroup[0], + psyOutChannel[0]->sfbOffsets); + } + } /* (channels == 2) */ + + /* + PNS Coding + */ + for (ch = 0; ch < channels; ch++) { + if (psyStatic[ch]->isLFE) { + /* no PNS coding */ + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + psyOutChannel[ch]->noiseNrg[sfb] = NO_NOISE_PNS; + } + } else { + FDKaacEnc_CodePnsChannel( + psyData[ch]->sfbActive, &(hThisPsyConf[ch]->pnsConf), + pnsData[ch]->pnsFlag, psyData[ch]->sfbEnergyLdData.Long, + psyOutChannel[ch]->noiseNrg, /* this is the energy that will be + written to the bitstream */ + psyOutChannel[ch]->sfbThresholdLdData); + } + } + + /* + build output + */ + for (ch = 0; ch < channels; ch++) { + INT mask; + int grp; + psyOutChannel[ch]->maxSfbPerGroup = maxSfbPerGroup[ch]; + psyOutChannel[ch]->mdctScale = psyData[ch]->mdctScale; + if (isShortWindow[ch] == 0) { + psyOutChannel[ch]->sfbCnt = hPsyConfLong->sfbActive; + psyOutChannel[ch]->sfbPerGroup = hPsyConfLong->sfbActive; + psyOutChannel[ch]->lastWindowSequence = + psyStatic[ch]->blockSwitchingControl.lastWindowSequence; + psyOutChannel[ch]->windowShape = + psyStatic[ch]->blockSwitchingControl.windowShape; + } else { + INT sfbCnt = psyStatic[ch]->blockSwitchingControl.noOfGroups * + hPsyConfShort->sfbCnt; + + psyOutChannel[ch]->sfbCnt = sfbCnt; + psyOutChannel[ch]->sfbPerGroup = hPsyConfShort->sfbCnt; + psyOutChannel[ch]->lastWindowSequence = SHORT_WINDOW; + psyOutChannel[ch]->windowShape = SINE_WINDOW; + } + /* generate grouping mask */ + mask = 0; + for (grp = 0; grp < psyStatic[ch]->blockSwitchingControl.noOfGroups; + grp++) { + int j; + mask <<= 1; + for (j = 1; j < psyStatic[ch]->blockSwitchingControl.groupLen[grp]; j++) { + mask = (mask << 1) | 1; + } + } + psyOutChannel[ch]->groupingMask = mask; + + /* build interface */ + FDKmemcpy(psyOutChannel[ch]->groupLen, + psyStatic[ch]->blockSwitchingControl.groupLen, + MAX_NO_OF_GROUPS * sizeof(INT)); + FDKmemcpy(psyOutChannel[ch]->sfbEnergy, (&psyData[ch]->sfbEnergy)->Long, + MAX_GROUPED_SFB * sizeof(FIXP_DBL)); + FDKmemcpy(psyOutChannel[ch]->sfbSpreadEnergy, + (&psyData[ch]->sfbSpreadEnergy)->Long, + MAX_GROUPED_SFB * sizeof(FIXP_DBL)); + // FDKmemcpy(psyOutChannel[ch]->mdctSpectrum, + // psyData[ch]->mdctSpectrum, (1024)*sizeof(FIXP_DBL)); + } + + return AAC_ENC_OK; +} + +void FDKaacEnc_PsyClose(PSY_INTERNAL **phPsyInternal, PSY_OUT **phPsyOut) { + int n, i; + + if (phPsyInternal != NULL) { + PSY_INTERNAL *hPsyInternal = *phPsyInternal; + + if (hPsyInternal) { + for (i = 0; i < (8); i++) { + if (hPsyInternal->pStaticChannels[i]) { + if (hPsyInternal->pStaticChannels[i]->psyInputBuffer) + FreeRam_aacEnc_PsyInputBuffer( + &hPsyInternal->pStaticChannels[i] + ->psyInputBuffer); /* AUDIO INPUT BUFFER */ + + FreeRam_aacEnc_PsyStatic( + &hPsyInternal->pStaticChannels[i]); /* PSY_STATIC */ + } + } + + for (i = 0; i < ((8)); i++) { + if (hPsyInternal->psyElement[i]) + FreeRam_aacEnc_PsyElement( + &hPsyInternal->psyElement[i]); /* PSY_ELEMENT */ + } + + FreeRam_aacEnc_PsyInternal(phPsyInternal); + } + } + + if (phPsyOut != NULL) { + for (n = 0; n < (1); n++) { + if (phPsyOut[n]) { + for (i = 0; i < (8); i++) { + if (phPsyOut[n]->pPsyOutChannels[i]) + FreeRam_aacEnc_PsyOutChannel( + &phPsyOut[n]->pPsyOutChannels[i]); /* PSY_OUT_CHANNEL */ + } + + for (i = 0; i < ((8)); i++) { + if (phPsyOut[n]->psyOutElement[i]) + FreeRam_aacEnc_PsyOutElements( + &phPsyOut[n]->psyOutElement[i]); /* PSY_OUT_ELEMENTS */ + } + + FreeRam_aacEnc_PsyOut(&phPsyOut[n]); + } + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_main.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_main.h new file mode 100644 index 0000000000000..7cc01a3fb6a92 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/psy_main.h @@ -0,0 +1,161 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Psychoaccoustic major function block + +*******************************************************************************/ + +#ifndef PSY_MAIN_H +#define PSY_MAIN_H + +#include "psy_configuration.h" +#include "qc_data.h" +#include "aacenc_pns.h" + +/* + psych internal +*/ +typedef struct { + PSY_STATIC *psyStatic[(2)]; + +} PSY_ELEMENT; + +typedef struct { + PSY_DATA psyData[(2)]; + TNS_DATA tnsData[(2)]; + PNS_DATA pnsData[(2)]; + +} PSY_DYNAMIC; + +typedef struct { + PSY_CONFIGURATION psyConf[2]; /* LONG / SHORT */ + PSY_ELEMENT *psyElement[((8))]; + PSY_STATIC *pStaticChannels[(8)]; + PSY_DYNAMIC *psyDynamic; + INT granuleLength; + +} PSY_INTERNAL; + +AAC_ENCODER_ERROR FDKaacEnc_PsyNew(PSY_INTERNAL **phpsy, const INT nElements, + const INT nChannels, UCHAR *dynamic_RAM); + +AAC_ENCODER_ERROR FDKaacEnc_PsyOutNew(PSY_OUT **phpsyOut, const INT nElements, + const INT nChannels, const INT nSubFrames, + UCHAR *dynamic_RAM); + +AAC_ENCODER_ERROR FDKaacEnc_psyInit(PSY_INTERNAL *hPsy, PSY_OUT **phpsyOut, + const INT nSubFrames, + const INT nMaxChannels, + const AUDIO_OBJECT_TYPE audioObjectType, + CHANNEL_MAPPING *cm); + +AAC_ENCODER_ERROR FDKaacEnc_psyMainInit( + PSY_INTERNAL *hPsy, AUDIO_OBJECT_TYPE audioObjectType, CHANNEL_MAPPING *cm, + INT sampleRate, INT granuleLength, INT bitRate, INT tnsMask, INT bandwidth, + INT usePns, INT useIS, INT useMS, UINT syntaxFlags, ULONG initFlags); + +AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels, PSY_ELEMENT *psyElement, + PSY_DYNAMIC *psyDynamic, + PSY_CONFIGURATION *psyConf, + PSY_OUT_ELEMENT *psyOutElement, + INT_PCM *pInput, const UINT inputBufSize, + INT *chIdx, INT totalChannels); + +void FDKaacEnc_PsyClose(PSY_INTERNAL **phPsyInternal, PSY_OUT **phPsyOut); + +#endif /* PSY_MAIN_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/qc_data.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/qc_data.h new file mode 100644 index 0000000000000..6e671edff33cf --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/qc_data.h @@ -0,0 +1,299 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Quantizing & coding data + +*******************************************************************************/ + +#ifndef QC_DATA_H +#define QC_DATA_H + +#include "aacenc.h" +#include "psy_const.h" +#include "dyn_bits.h" +#include "adj_thr_data.h" +#include "line_pe.h" +#include "FDK_audio.h" +#include "interface.h" + +typedef enum { + QCDATA_BR_MODE_INVALID = -1, + QCDATA_BR_MODE_CBR = 0, /* Constant bit rate, given average bitrate */ + QCDATA_BR_MODE_VBR_1 = 1, /* Variable bit rate, very low */ + QCDATA_BR_MODE_VBR_2 = 2, /* Variable bit rate, low */ + QCDATA_BR_MODE_VBR_3 = 3, /* Variable bit rate, medium */ + QCDATA_BR_MODE_VBR_4 = 4, /* Variable bit rate, high */ + QCDATA_BR_MODE_VBR_5 = 5, /* Variable bit rate, very high */ + QCDATA_BR_MODE_FF = 6, /* Fixed frame mode. */ + QCDATA_BR_MODE_SFR = 7 /* Superframe mode. */ + +} QCDATA_BR_MODE; + +typedef struct { + MP4_ELEMENT_ID elType; + INT instanceTag; + INT nChannelsInEl; + INT ChannelIndex[2]; + FIXP_DBL relativeBits; +} ELEMENT_INFO; + +typedef struct { + CHANNEL_MODE encMode; + INT nChannels; + INT nChannelsEff; + INT nElements; + ELEMENT_INFO elInfo[((8))]; +} CHANNEL_MAPPING; + +typedef struct { + INT paddingRest; +} PADDING; + +/* Quantizing & coding stage */ + +struct QC_INIT { + CHANNEL_MAPPING *channelMapping; + INT sceCpe; /* not used yet */ + INT maxBits; /* maximum number of bits in reservoir */ + INT averageBits; /* average number of bits we should use */ + INT bitRes; + INT sampleRate; /* output sample rate */ + INT isLowDelay; /* if set, calc bits2PE factor depending on samplerate */ + INT staticBits; /* Bits per frame consumed by transport layers. */ + QCDATA_BR_MODE bitrateMode; + INT meanPe; + INT chBitrate; /* Bitrate/channel */ + INT invQuant; + INT maxIterations; /* Maximum number of allowed iterations before + FDKaacEnc_crashRecovery() is applied. */ + FIXP_DBL maxBitFac; + INT bitrate; + INT nSubFrames; /* helper variable */ + INT minBits; /* minimal number of bits in one frame*/ + AACENC_BITRES_MODE bitResMode; /* 0: full bitreservoir, 1: reduced + bitreservoir, 2: disabled bitreservoir */ + INT bitDistributionMode; /* Configure element-wise execution or execution over + all elements for the pe-dependent + threshold-adaption */ + + PADDING padding; +}; + +typedef struct { + FIXP_DBL mdctSpectrum[(1024)]; + + SHORT quantSpec[(1024)]; + + UINT maxValueInSfb[MAX_GROUPED_SFB]; + INT scf[MAX_GROUPED_SFB]; + INT globalGain; + SECTION_DATA sectionData; + + FIXP_DBL sfbFormFactorLdData[MAX_GROUPED_SFB]; + + FIXP_DBL sfbThresholdLdData[MAX_GROUPED_SFB]; + FIXP_DBL sfbMinSnrLdData[MAX_GROUPED_SFB]; + FIXP_DBL sfbEnergyLdData[MAX_GROUPED_SFB]; + FIXP_DBL sfbEnergy[MAX_GROUPED_SFB]; + FIXP_DBL sfbWeightedEnergyLdData[MAX_GROUPED_SFB]; + + FIXP_DBL sfbEnFacLd[MAX_GROUPED_SFB]; + + FIXP_DBL sfbSpreadEnergy[MAX_GROUPED_SFB]; + +} QC_OUT_CHANNEL; + +typedef struct { + EXT_PAYLOAD_TYPE type; /* type of the extension payload */ + INT nPayloadBits; /* size of the payload */ + UCHAR *pPayload; /* pointer to payload */ + +} QC_OUT_EXTENSION; + +typedef struct { + INT staticBitsUsed; /* for verification purposes */ + INT dynBitsUsed; /* for verification purposes */ + + INT extBitsUsed; /* bit consumption of extended fill elements */ + INT nExtensions; /* number of extension payloads for this element */ + QC_OUT_EXTENSION extension[(1)]; /* reffering extension payload */ + + INT grantedDynBits; + + INT grantedPe; + INT grantedPeCorr; + + PE_DATA peData; + + QC_OUT_CHANNEL *qcOutChannel[(2)]; + + UCHAR + *dynMem_Ah_Flag; /* pointer to dynamic buffer used by AhFlag in function + FDKaacEnc_adaptThresholdsToPe() */ + UCHAR + *dynMem_Thr_Exp; /* pointer to dynamic buffer used by ThrExp in function + FDKaacEnc_adaptThresholdsToPe() */ + UCHAR *dynMem_SfbNActiveLinesLdData; /* pointer to dynamic buffer used by + sfbNActiveLinesLdData in function + FDKaacEnc_correctThresh() */ + +} QC_OUT_ELEMENT; + +typedef struct { + QC_OUT_ELEMENT *qcElement[((8))]; + QC_OUT_CHANNEL *pQcOutChannels[(8)]; + QC_OUT_EXTENSION extension[(2 + 2)]; /* global extension payload */ + INT nExtensions; /* number of extension payloads for this AU */ + INT maxDynBits; /* maximal allowed dynamic bits in frame */ + INT grantedDynBits; /* granted dynamic bits in frame */ + INT totFillBits; /* fill bits */ + INT elementExtBits; /* element associated extension payload bits, e.g. sbr, + drc ... */ + INT globalExtBits; /* frame/au associated extension payload bits (anc data + ...) */ + INT staticBits; /* aac side info bits */ + + INT totalNoRedPe; + INT totalGrantedPeCorr; + + INT usedDynBits; /* number of dynamic bits in use */ + INT alignBits; /* AU alignment bits */ + INT totalBits; /* sum of static, dyn, sbr, fill, align and dse bits */ + +} QC_OUT; + +typedef struct { + INT chBitrateEl; /* channel bitrate in element + (totalbitrate*el_relativeBits/el_channels) */ + INT maxBitsEl; /* used in crash recovery */ + INT bitResLevelEl; /* update bitreservoir level in each call of + FDKaacEnc_QCMain */ + INT maxBitResBitsEl; /* nEffChannels*6144 - averageBitsInFrame */ + FIXP_DBL relativeBitsEl; /* Bits relative to total Bits*/ +} ELEMENT_BITS; + +typedef struct { + /* this is basically struct QC_INIT */ + + INT globHdrBits; + INT maxBitsPerFrame; /* maximal allowed bits per frame, 6144*nChannelsEff */ + INT minBitsPerFrame; /* minimal allowd bits per fram, superframing - DRM */ + INT nElements; + QCDATA_BR_MODE bitrateMode; + AACENC_BITRES_MODE bitResMode; /* 0: full bitreservoir, 1: reduced + bitreservoir, 2: disabled bitreservoir */ + INT bitResTot; + INT bitResTotMax; + INT maxIterations; /* Maximum number of allowed iterations before + FDKaacEnc_crashRecovery() is applied. */ + INT invQuant; + + FIXP_DBL vbrQualFactor; + FIXP_DBL maxBitFac; + + PADDING padding; + + ELEMENT_BITS *elementBits[((8))]; + BITCNTR_STATE *hBitCounter; + ADJ_THR_STATE *hAdjThr; + + INT dZoneQuantEnable; /* enable dead zone quantizer */ + +} QC_STATE; + +#endif /* QC_DATA_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/qc_main.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/qc_main.cpp new file mode 100644 index 0000000000000..9a425508127be --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/qc_main.cpp @@ -0,0 +1,1536 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Quantizing & coding + +*******************************************************************************/ + +#include "qc_main.h" +#include "quantize.h" +#include "interface.h" +#include "adj_thr.h" +#include "sf_estim.h" +#include "bit_cnt.h" +#include "dyn_bits.h" +#include "channel_map.h" +#include "aacEnc_ram.h" + +#include "genericStds.h" + +#define AACENC_DZQ_BR_THR 32000 /* Dead zone quantizer bitrate threshold */ + +typedef struct { + QCDATA_BR_MODE bitrateMode; + LONG vbrQualFactor; +} TAB_VBR_QUAL_FACTOR; + +static const TAB_VBR_QUAL_FACTOR tableVbrQualFactor[] = { + {QCDATA_BR_MODE_VBR_1, + FL2FXCONST_DBL(0.150f)}, /* Approx. 32 kbps mono AAC-LC + SBR + PS */ + {QCDATA_BR_MODE_VBR_2, + FL2FXCONST_DBL(0.162f)}, /* Approx. 64 kbps stereo AAC-LC + SBR */ + {QCDATA_BR_MODE_VBR_3, + FL2FXCONST_DBL(0.176f)}, /* Approx. 96 kbps stereo AAC-LC */ + {QCDATA_BR_MODE_VBR_4, + FL2FXCONST_DBL(0.120f)}, /* Approx. 128 kbps stereo AAC-LC */ + {QCDATA_BR_MODE_VBR_5, + FL2FXCONST_DBL(0.070f)} /* Approx. 192 kbps stereo AAC-LC */ +}; + +static INT isConstantBitrateMode(const QCDATA_BR_MODE bitrateMode) { + return (((bitrateMode == QCDATA_BR_MODE_CBR) || + (bitrateMode == QCDATA_BR_MODE_SFR) || + (bitrateMode == QCDATA_BR_MODE_FF)) + ? 1 + : 0); +} + +typedef enum { + FRAME_LEN_BYTES_MODULO = 1, + FRAME_LEN_BYTES_INT = 2 +} FRAME_LEN_RESULT_MODE; + +/* forward declarations */ + +static INT FDKaacEnc_calcMaxValueInSfb(INT sfbCnt, INT maxSfbPerGroup, + INT sfbPerGroup, INT* RESTRICT sfbOffset, + SHORT* RESTRICT quantSpectrum, + UINT* RESTRICT maxValue); + +static void FDKaacEnc_crashRecovery(INT nChannels, + PSY_OUT_ELEMENT* psyOutElement, + QC_OUT* qcOut, QC_OUT_ELEMENT* qcElement, + INT bitsToSave, AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig); + +static AAC_ENCODER_ERROR FDKaacEnc_reduceBitConsumption( + int* iterations, const int maxIterations, int gainAdjustment, + int* chConstraintsFulfilled, int* calculateQuant, int nChannels, + PSY_OUT_ELEMENT* psyOutElement, QC_OUT* qcOut, QC_OUT_ELEMENT* qcOutElement, + ELEMENT_BITS* elBits, AUDIO_OBJECT_TYPE aot, UINT syntaxFlags, + SCHAR epConfig); + +void FDKaacEnc_QCClose(QC_STATE** phQCstate, QC_OUT** phQC); + +/***************************************************************************** + + functionname: FDKaacEnc_calcFrameLen + description: + returns: + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_calcFrameLen(INT bitRate, INT sampleRate, + INT granuleLength, + FRAME_LEN_RESULT_MODE mode) { + INT result; + + result = ((granuleLength) >> 3) * (bitRate); + + switch (mode) { + case FRAME_LEN_BYTES_MODULO: + result %= sampleRate; + break; + case FRAME_LEN_BYTES_INT: + result /= sampleRate; + break; + } + return (result); +} + +/***************************************************************************** + + functionname:FDKaacEnc_framePadding + description: Calculates if padding is needed for actual frame + returns: + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_framePadding(INT bitRate, INT sampleRate, + INT granuleLength, INT* paddingRest) { + INT paddingOn; + INT difference; + + paddingOn = 0; + + difference = FDKaacEnc_calcFrameLen(bitRate, sampleRate, granuleLength, + FRAME_LEN_BYTES_MODULO); + *paddingRest -= difference; + + if (*paddingRest <= 0) { + paddingOn = 1; + *paddingRest += sampleRate; + } + + return (paddingOn); +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCOutNew + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCOutNew(QC_OUT** phQC, const INT nElements, + const INT nChannels, const INT nSubFrames, + UCHAR* dynamic_RAM) { + AAC_ENCODER_ERROR ErrorStatus; + int n, i; + int elInc = 0, chInc = 0; + + for (n = 0; n < nSubFrames; n++) { + phQC[n] = GetRam_aacEnc_QCout(n); + if (phQC[n] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCOutNew_bail; + } + + for (i = 0; i < nChannels; i++) { + phQC[n]->pQcOutChannels[i] = GetRam_aacEnc_QCchannel(chInc, dynamic_RAM); + if (phQC[n]->pQcOutChannels[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCOutNew_bail; + } + + chInc++; + } /* nChannels */ + + for (i = 0; i < nElements; i++) { + phQC[n]->qcElement[i] = GetRam_aacEnc_QCelement(elInc); + if (phQC[n]->qcElement[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCOutNew_bail; + } + elInc++; + + /* initialize pointer to dynamic buffer which are used in adjust + * thresholds */ + phQC[n]->qcElement[i]->dynMem_Ah_Flag = dynamic_RAM + (P_BUF_1); + phQC[n]->qcElement[i]->dynMem_Thr_Exp = + dynamic_RAM + (P_BUF_1) + ADJ_THR_AH_FLAG_SIZE; + phQC[n]->qcElement[i]->dynMem_SfbNActiveLinesLdData = + dynamic_RAM + (P_BUF_1) + ADJ_THR_AH_FLAG_SIZE + ADJ_THR_THR_EXP_SIZE; + + } /* nElements */ + + } /* nSubFrames */ + + return AAC_ENC_OK; + +QCOutNew_bail: + return ErrorStatus; +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCOutInit + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCOutInit(QC_OUT* phQC[(1)], const INT nSubFrames, + const CHANNEL_MAPPING* cm) { + INT n, i, ch; + + for (n = 0; n < nSubFrames; n++) { + INT chInc = 0; + for (i = 0; i < cm->nElements; i++) { + for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) { + phQC[n]->qcElement[i]->qcOutChannel[ch] = + phQC[n]->pQcOutChannels[chInc]; + chInc++; + } /* chInEl */ + } /* nElements */ + } /* nSubFrames */ + + return AAC_ENC_OK; +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCNew + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCNew(QC_STATE** phQC, INT nElements, + UCHAR* dynamic_RAM) { + AAC_ENCODER_ERROR ErrorStatus; + int i; + + QC_STATE* hQC = GetRam_aacEnc_QCstate(); + *phQC = hQC; + if (hQC == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCNew_bail; + } + + if (FDKaacEnc_AdjThrNew(&hQC->hAdjThr, nElements)) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCNew_bail; + } + + if (FDKaacEnc_BCNew(&(hQC->hBitCounter), dynamic_RAM)) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCNew_bail; + } + + for (i = 0; i < nElements; i++) { + hQC->elementBits[i] = GetRam_aacEnc_ElementBits(i); + if (hQC->elementBits[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCNew_bail; + } + } + + return AAC_ENC_OK; + +QCNew_bail: + FDKaacEnc_QCClose(phQC, NULL); + return ErrorStatus; +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCInit + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE* hQC, struct QC_INIT* init, + const ULONG initFlags) { + AAC_ENCODER_ERROR err = AAC_ENC_OK; + + int i; + hQC->maxBitsPerFrame = init->maxBits; + hQC->minBitsPerFrame = init->minBits; + hQC->nElements = init->channelMapping->nElements; + if ((initFlags != 0) || ((init->bitrateMode != QCDATA_BR_MODE_FF) && + (hQC->bitResTotMax != init->bitRes))) { + hQC->bitResTot = init->bitRes; + } + hQC->bitResTotMax = init->bitRes; + hQC->maxBitFac = init->maxBitFac; + hQC->bitrateMode = init->bitrateMode; + hQC->invQuant = init->invQuant; + hQC->maxIterations = init->maxIterations; + + /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */ + hQC->bitResMode = init->bitResMode; + + hQC->padding.paddingRest = init->padding.paddingRest; + + hQC->globHdrBits = init->staticBits; /* Bit overhead due to transport */ + + err = FDKaacEnc_InitElementBits( + hQC, init->channelMapping, init->bitrate, + (init->averageBits / init->nSubFrames) - hQC->globHdrBits, + hQC->maxBitsPerFrame / init->channelMapping->nChannelsEff); + if (err != AAC_ENC_OK) goto bail; + + hQC->vbrQualFactor = FL2FXCONST_DBL(0.f); + for (i = 0; + i < (int)(sizeof(tableVbrQualFactor) / sizeof(TAB_VBR_QUAL_FACTOR)); + i++) { + if (hQC->bitrateMode == tableVbrQualFactor[i].bitrateMode) { + hQC->vbrQualFactor = (FIXP_DBL)tableVbrQualFactor[i].vbrQualFactor; + break; + } + } + + if (init->channelMapping->nChannelsEff == 1 && + (init->bitrate / init->channelMapping->nChannelsEff) < + AACENC_DZQ_BR_THR && + init->isLowDelay != + 0) /* watch out here: init->bitrate is the bitrate "minus" the + standard SBR bitrate (=2500kbps) --> for the FDK the OFFSTE + tuning should start somewhere below 32000kbps-2500kbps ... so + everything is fine here */ + { + hQC->dZoneQuantEnable = 1; + } else { + hQC->dZoneQuantEnable = 0; + } + + FDKaacEnc_AdjThrInit( + hQC->hAdjThr, init->meanPe, hQC->invQuant, init->channelMapping, + init->sampleRate, /* output sample rate */ + init->bitrate, /* total bitrate */ + init->isLowDelay, /* if set, calc bits2PE factor + depending on samplerate */ + init->bitResMode /* for a small bitreservoir, the pe + correction is calc'd differently */ + , + hQC->dZoneQuantEnable, init->bitDistributionMode, hQC->vbrQualFactor); + +bail: + return err; +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCMainPrepare + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCMainPrepare( + ELEMENT_INFO* elInfo, ATS_ELEMENT* RESTRICT adjThrStateElement, + PSY_OUT_ELEMENT* RESTRICT psyOutElement, + QC_OUT_ELEMENT* RESTRICT qcOutElement, AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig) { + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + INT nChannels = elInfo->nChannelsInEl; + + PSY_OUT_CHANNEL** RESTRICT psyOutChannel = + psyOutElement->psyOutChannel; /* may be modified in-place */ + + FDKaacEnc_CalcFormFactor(qcOutElement->qcOutChannel, psyOutChannel, + nChannels); + + /* prepare and calculate PE without reduction */ + FDKaacEnc_peCalculation(&qcOutElement->peData, psyOutChannel, + qcOutElement->qcOutChannel, &psyOutElement->toolsInfo, + adjThrStateElement, nChannels); + + ErrorStatus = FDKaacEnc_ChannelElementWrite( + NULL, elInfo, NULL, psyOutElement, psyOutElement->psyOutChannel, + syntaxFlags, aot, epConfig, &qcOutElement->staticBitsUsed, 0); + + return ErrorStatus; +} + +/********************************************************************************* + + functionname: FDKaacEnc_AdjustBitrate + description: adjusts framelength via padding on a frame to frame +basis, to achieve a bitrate that demands a non byte aligned framelength return: +errorcode + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_AdjustBitrate( + QC_STATE* RESTRICT hQC, CHANNEL_MAPPING* RESTRICT cm, INT* avgTotalBits, + INT bitRate, /* total bitrate */ + INT sampleRate, /* output sampling rate */ + INT granuleLength) /* frame length */ +{ + INT paddingOn; + INT frameLen; + + /* Do we need an extra padding byte? */ + paddingOn = FDKaacEnc_framePadding(bitRate, sampleRate, granuleLength, + &hQC->padding.paddingRest); + + frameLen = + paddingOn + FDKaacEnc_calcFrameLen(bitRate, sampleRate, granuleLength, + FRAME_LEN_BYTES_INT); + + *avgTotalBits = frameLen << 3; + + return AAC_ENC_OK; +} + +#define isAudioElement(elType) \ + ((elType == ID_SCE) || (elType == ID_CPE) || (elType == ID_LFE)) + +/********************************************************************************* + + functionname: FDKaacEnc_distributeElementDynBits + description: distributes all bits over all elements. The relative bit + distibution is described in the ELEMENT_INFO of the + appropriate element. The bit distribution table is + initialized in FDKaacEnc_InitChannelMapping(). + return: errorcode + +**********************************************************************************/ +static AAC_ENCODER_ERROR FDKaacEnc_distributeElementDynBits( + QC_STATE* hQC, QC_OUT_ELEMENT* qcElement[((8))], CHANNEL_MAPPING* cm, + INT codeBits) { + INT i; /* counter variable */ + INT totalBits = 0; /* sum of bits over all elements */ + + for (i = (cm->nElements - 1); i >= 0; i--) { + if (isAudioElement(cm->elInfo[i].elType)) { + qcElement[i]->grantedDynBits = + fMax(0, fMultI(hQC->elementBits[i]->relativeBitsEl, codeBits)); + totalBits += qcElement[i]->grantedDynBits; + } + } + + /* Due to inaccuracies with the multiplication, codeBits may differ from + totalBits. For that case, the difference must be added/substracted again + to/from one element, i.e: + Negative differences are substracted from the element with the most bits. + Positive differences are added to the element with the least bits. + */ + if (codeBits != totalBits) { + INT elMaxBits = cm->nElements - 1; /* element with the most bits */ + INT elMinBits = cm->nElements - 1; /* element with the least bits */ + + /* Search for biggest and smallest audio element */ + for (i = (cm->nElements - 1); i >= 0; i--) { + if (isAudioElement(cm->elInfo[i].elType)) { + if (qcElement[i]->grantedDynBits > + qcElement[elMaxBits]->grantedDynBits) { + elMaxBits = i; + } + if (qcElement[i]->grantedDynBits < + qcElement[elMinBits]->grantedDynBits) { + elMinBits = i; + } + } + } + /* Compensate for bit distibution difference */ + if (codeBits - totalBits > 0) { + qcElement[elMinBits]->grantedDynBits += codeBits - totalBits; + } else { + qcElement[elMaxBits]->grantedDynBits += codeBits - totalBits; + } + } + + return AAC_ENC_OK; +} + +/** + * \brief Verify whether minBitsPerFrame criterion can be satisfied. + * + * This function evaluates the bit consumption only if minBitsPerFrame parameter + * is not 0. In hyperframing mode the difference between grantedDynBits and + * usedDynBits of all sub frames results the number of fillbits to be written. + * This bits can be distrubitued in superframe to reach minBitsPerFrame bit + * consumption in single AU's. The return value denotes if enough desired fill + * bits are available to achieve minBitsPerFrame in all frames. This check can + * only be used within superframes. + * + * \param qcOut Pointer to coding data struct. + * \param minBitsPerFrame Minimal number of bits to be consumed in each frame. + * \param nSubFrames Number of frames in superframe + * + * \return + * - 1: all fine + * - 0: criterion not fulfilled + */ +static int checkMinFrameBitsDemand(QC_OUT** qcOut, const INT minBitsPerFrame, + const INT nSubFrames) { + int result = 1; /* all fine*/ + return result; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/********************************************************************************* + + functionname: FDKaacEnc_getMinimalStaticBitdemand + description: calculate minmal size of static bits by reduction , + to zero spectrum and deactivating tns and MS + return: number of static bits + +**********************************************************************************/ +static int FDKaacEnc_getMinimalStaticBitdemand(CHANNEL_MAPPING* cm, + PSY_OUT** psyOut) { + AUDIO_OBJECT_TYPE aot = AOT_AAC_LC; + UINT syntaxFlags = 0; + SCHAR epConfig = -1; + int i, bitcount = 0; + + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + INT minElBits = 0; + + FDKaacEnc_ChannelElementWrite(NULL, &elInfo, NULL, + psyOut[0]->psyOutElement[i], + psyOut[0]->psyOutElement[i]->psyOutChannel, + syntaxFlags, aot, epConfig, &minElBits, 1); + bitcount += minElBits; + } + } + + return bitcount; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static AAC_ENCODER_ERROR FDKaacEnc_prepareBitDistribution( + QC_STATE* hQC, PSY_OUT** psyOut, QC_OUT** qcOut, CHANNEL_MAPPING* cm, + QC_OUT_ELEMENT* qcElement[(1)][((8))], INT avgTotalBits, + INT* totalAvailableBits, INT* avgTotalDynBits) { + int i; + /* get maximal allowed dynamic bits */ + qcOut[0]->grantedDynBits = + (fixMin(hQC->maxBitsPerFrame, avgTotalBits) - hQC->globHdrBits) & ~7; + qcOut[0]->grantedDynBits -= (qcOut[0]->globalExtBits + qcOut[0]->staticBits + + qcOut[0]->elementExtBits); + qcOut[0]->maxDynBits = ((hQC->maxBitsPerFrame) & ~7) - + (qcOut[0]->globalExtBits + qcOut[0]->staticBits + + qcOut[0]->elementExtBits); + /* assure that enough bits are available */ + if ((qcOut[0]->grantedDynBits + hQC->bitResTot) < 0) { + /* crash recovery allows to reduce static bits to a minimum */ + if ((qcOut[0]->grantedDynBits + hQC->bitResTot) < + (FDKaacEnc_getMinimalStaticBitdemand(cm, psyOut) - + qcOut[0]->staticBits)) + return AAC_ENC_BITRES_TOO_LOW; + } + + /* distribute dynamic bits to each element */ + FDKaacEnc_distributeElementDynBits(hQC, qcElement[0], cm, + qcOut[0]->grantedDynBits); + + *avgTotalDynBits = 0; /*frameDynBits;*/ + + *totalAvailableBits = avgTotalBits; + + /* sum up corrected granted PE */ + qcOut[0]->totalGrantedPeCorr = 0; + + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + int nChannels = elInfo.nChannelsInEl; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* for ( all sub frames ) ... */ + FDKaacEnc_DistributeBits( + hQC->hAdjThr, hQC->hAdjThr->adjThrStateElem[i], + psyOut[0]->psyOutElement[i]->psyOutChannel, &qcElement[0][i]->peData, + &qcElement[0][i]->grantedPe, &qcElement[0][i]->grantedPeCorr, + nChannels, psyOut[0]->psyOutElement[i]->commonWindow, + qcElement[0][i]->grantedDynBits, hQC->elementBits[i]->bitResLevelEl, + hQC->elementBits[i]->maxBitResBitsEl, hQC->maxBitFac, + hQC->bitResMode); + + *totalAvailableBits += hQC->elementBits[i]->bitResLevelEl; + /* get total corrected granted PE */ + qcOut[0]->totalGrantedPeCorr += qcElement[0][i]->grantedPeCorr; + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + *totalAvailableBits = fMin(hQC->maxBitsPerFrame, (*totalAvailableBits)); + + return AAC_ENC_OK; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static AAC_ENCODER_ERROR FDKaacEnc_updateUsedDynBits( + INT* sumDynBitsConsumed, QC_OUT_ELEMENT* qcElement[((8))], + CHANNEL_MAPPING* cm) { + INT i; + + *sumDynBitsConsumed = 0; + + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* sum up bits consumed */ + *sumDynBitsConsumed += qcElement[i]->dynBitsUsed; + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + return AAC_ENC_OK; +} + +static INT FDKaacEnc_getTotalConsumedDynBits(QC_OUT** qcOut, INT nSubFrames) { + INT c, totalBits = 0; + + /* sum up bit consumption for all sub frames */ + for (c = 0; c < nSubFrames; c++) { + /* bit consumption not valid if dynamic bits + not available in one sub frame */ + if (qcOut[c]->usedDynBits == -1) return -1; + totalBits += qcOut[c]->usedDynBits; + } + + return totalBits; +} + +static INT FDKaacEnc_getTotalConsumedBits(QC_OUT** qcOut, + QC_OUT_ELEMENT* qcElement[(1)][((8))], + CHANNEL_MAPPING* cm, INT globHdrBits, + INT nSubFrames) { + int c, i; + int totalUsedBits = 0; + + for (c = 0; c < nSubFrames; c++) { + int dataBits = 0; + for (i = 0; i < cm->nElements; i++) { + if ((cm->elInfo[i].elType == ID_SCE) || + (cm->elInfo[i].elType == ID_CPE) || + (cm->elInfo[i].elType == ID_LFE)) { + dataBits += qcElement[c][i]->dynBitsUsed + + qcElement[c][i]->staticBitsUsed + + qcElement[c][i]->extBitsUsed; + } + } + dataBits += qcOut[c]->globalExtBits; + + totalUsedBits += (8 - (dataBits) % 8) % 8; + totalUsedBits += dataBits + globHdrBits; /* header bits for every frame */ + } + return totalUsedBits; +} + +static AAC_ENCODER_ERROR FDKaacEnc_BitResRedistribution( + QC_STATE* const hQC, const CHANNEL_MAPPING* const cm, + const INT avgTotalBits) { + /* check bitreservoir fill level */ + if (hQC->bitResTot < 0) { + return AAC_ENC_BITRES_TOO_LOW; + } else if (hQC->bitResTot > hQC->bitResTotMax) { + return AAC_ENC_BITRES_TOO_HIGH; + } else { + INT i; + INT totalBits = 0, totalBits_max = 0; + + const int totalBitreservoir = + fMin(hQC->bitResTot, (hQC->maxBitsPerFrame - avgTotalBits)); + const int totalBitreservoirMax = + fMin(hQC->bitResTotMax, (hQC->maxBitsPerFrame - avgTotalBits)); + + for (i = (cm->nElements - 1); i >= 0; i--) { + if ((cm->elInfo[i].elType == ID_SCE) || + (cm->elInfo[i].elType == ID_CPE) || + (cm->elInfo[i].elType == ID_LFE)) { + hQC->elementBits[i]->bitResLevelEl = + fMultI(hQC->elementBits[i]->relativeBitsEl, totalBitreservoir); + totalBits += hQC->elementBits[i]->bitResLevelEl; + + hQC->elementBits[i]->maxBitResBitsEl = + fMultI(hQC->elementBits[i]->relativeBitsEl, totalBitreservoirMax); + totalBits_max += hQC->elementBits[i]->maxBitResBitsEl; + } + } + for (i = 0; i < cm->nElements; i++) { + if ((cm->elInfo[i].elType == ID_SCE) || + (cm->elInfo[i].elType == ID_CPE) || + (cm->elInfo[i].elType == ID_LFE)) { + int deltaBits = fMax(totalBitreservoir - totalBits, + -hQC->elementBits[i]->bitResLevelEl); + hQC->elementBits[i]->bitResLevelEl += deltaBits; + totalBits += deltaBits; + + deltaBits = fMax(totalBitreservoirMax - totalBits_max, + -hQC->elementBits[i]->maxBitResBitsEl); + hQC->elementBits[i]->maxBitResBitsEl += deltaBits; + totalBits_max += deltaBits; + } + } + } + + return AAC_ENC_OK; +} + +AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC, PSY_OUT** psyOut, + QC_OUT** qcOut, INT avgTotalBits, + CHANNEL_MAPPING* cm, + const AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig) { + int i, c; + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + INT avgTotalDynBits = 0; /* maximal allowed dynamic bits for all frames */ + INT totalAvailableBits = 0; + INT nSubFrames = 1; + const INT isCBRAdjustment = (isConstantBitrateMode(hQC->bitrateMode) || + (hQC->bitResMode != AACENC_BR_MODE_FULL)) + ? 1 + : 0; + + /*-------------------------------------------- */ + /* redistribute total bitreservoir to elements */ + ErrorStatus = FDKaacEnc_BitResRedistribution( + hQC, cm, (isCBRAdjustment == 0) ? hQC->maxBitsPerFrame : avgTotalBits); + if (ErrorStatus != AAC_ENC_OK) { + return ErrorStatus; + } + + /*-------------------------------------------- */ + /* fastenc needs one time threshold simulation, + in case of multiple frames, one more guess has to be calculated */ + + /*-------------------------------------------- */ + /* helper pointer */ + QC_OUT_ELEMENT* qcElement[(1)][((8))]; + + /* work on a copy of qcChannel and qcElement */ + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* for ( all sub frames ) ... */ + for (c = 0; c < nSubFrames; c++) { + { qcElement[c][i] = qcOut[c]->qcElement[i]; } + } + } + } + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + /* calc granted dynamic bits for sub frame and + distribute it to each element */ + ErrorStatus = FDKaacEnc_prepareBitDistribution( + hQC, psyOut, qcOut, cm, qcElement, + (isCBRAdjustment == 0) ? hQC->maxBitsPerFrame : avgTotalBits, + &totalAvailableBits, &avgTotalDynBits); + + if (ErrorStatus != AAC_ENC_OK) { + return ErrorStatus; + } + + /* for ( all sub frames ) ... */ + for (c = 0; c < nSubFrames; c++) { + /* for CBR and VBR mode */ + FDKaacEnc_AdjustThresholds(hQC->hAdjThr, qcElement[c], qcOut[c], + psyOut[c]->psyOutElement, isCBRAdjustment, cm); + + } /* -end- sub frame counter */ + + /*-------------------------------------------- */ + INT iterations[(1)][((8))]; + INT chConstraintsFulfilled[(1)][((8))][(2)]; + INT calculateQuant[(1)][((8))][(2)]; + INT constraintsFulfilled[(1)][((8))]; + /*-------------------------------------------- */ + + /* for ( all sub frames ) ... */ + for (c = 0; c < nSubFrames; c++) { + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + INT ch, nChannels = elInfo.nChannelsInEl; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* Turn thresholds into scalefactors, optimize bit consumption and + * verify conformance */ + FDKaacEnc_EstimateScaleFactors( + psyOut[c]->psyOutElement[i]->psyOutChannel, + qcElement[c][i]->qcOutChannel, hQC->invQuant, hQC->dZoneQuantEnable, + cm->elInfo[i].nChannelsInEl); + + /*-------------------------------------------- */ + constraintsFulfilled[c][i] = 1; + iterations[c][i] = 0; + + for (ch = 0; ch < nChannels; ch++) { + chConstraintsFulfilled[c][i][ch] = 1; + calculateQuant[c][i][ch] = 1; + } + + /*-------------------------------------------- */ + + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + qcOut[c]->usedDynBits = -1; + + } /* -end- sub frame counter */ + + INT quantizationDone = 0; + INT sumDynBitsConsumedTotal = 0; + INT decreaseBitConsumption = -1; /* no direction yet! */ + + /*-------------------------------------------- */ + /* -start- Quantization loop ... */ + /*-------------------------------------------- */ + do /* until max allowed bits per frame and maxDynBits!=-1*/ + { + quantizationDone = 0; + + c = 0; /* get frame to process */ + + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + INT ch, nChannels = elInfo.nChannelsInEl; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + do /* until element bits < nChannels*MIN_BUFSIZE_PER_EFF_CHAN */ + { + do /* until spectral values < MAX_QUANT */ + { + /*-------------------------------------------- */ + if (!constraintsFulfilled[c][i]) { + if ((ErrorStatus = FDKaacEnc_reduceBitConsumption( + &iterations[c][i], hQC->maxIterations, + (decreaseBitConsumption) ? 1 : -1, + chConstraintsFulfilled[c][i], calculateQuant[c][i], + nChannels, psyOut[c]->psyOutElement[i], qcOut[c], + qcElement[c][i], hQC->elementBits[i], aot, syntaxFlags, + epConfig)) != AAC_ENC_OK) { + return ErrorStatus; + } + } + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + constraintsFulfilled[c][i] = 1; + + /*-------------------------------------------- */ + /* quantize spectrum (per each channel) */ + for (ch = 0; ch < nChannels; ch++) { + /*-------------------------------------------- */ + chConstraintsFulfilled[c][i][ch] = 1; + + /*-------------------------------------------- */ + + if (calculateQuant[c][i][ch]) { + QC_OUT_CHANNEL* qcOutCh = qcElement[c][i]->qcOutChannel[ch]; + PSY_OUT_CHANNEL* psyOutCh = + psyOut[c]->psyOutElement[i]->psyOutChannel[ch]; + + calculateQuant[c][i][ch] = + 0; /* calculate quantization only if necessary */ + + /*-------------------------------------------- */ + FDKaacEnc_QuantizeSpectrum( + psyOutCh->sfbCnt, psyOutCh->maxSfbPerGroup, + psyOutCh->sfbPerGroup, psyOutCh->sfbOffsets, + qcOutCh->mdctSpectrum, qcOutCh->globalGain, qcOutCh->scf, + qcOutCh->quantSpec, hQC->dZoneQuantEnable); + + /*-------------------------------------------- */ + if (FDKaacEnc_calcMaxValueInSfb( + psyOutCh->sfbCnt, psyOutCh->maxSfbPerGroup, + psyOutCh->sfbPerGroup, psyOutCh->sfbOffsets, + qcOutCh->quantSpec, + qcOutCh->maxValueInSfb) > MAX_QUANT) { + chConstraintsFulfilled[c][i][ch] = 0; + constraintsFulfilled[c][i] = 0; + /* if quanizted value out of range; increase global gain! */ + decreaseBitConsumption = 1; + } + + /*-------------------------------------------- */ + + } /* if calculateQuant[c][i][ch] */ + + } /* channel loop */ + + /*-------------------------------------------- */ + /* quantize spectrum (per each channel) */ + + /*-------------------------------------------- */ + + } while (!constraintsFulfilled[c][i]); /* does not regard bit + consumption */ + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + qcElement[c][i]->dynBitsUsed = 0; /* reset dynamic bits */ + + /* quantization valid in current channel! */ + for (ch = 0; ch < nChannels; ch++) { + QC_OUT_CHANNEL* qcOutCh = qcElement[c][i]->qcOutChannel[ch]; + PSY_OUT_CHANNEL* psyOutCh = + psyOut[c]->psyOutElement[i]->psyOutChannel[ch]; + + /* count dynamic bits */ + INT chDynBits = FDKaacEnc_dynBitCount( + hQC->hBitCounter, qcOutCh->quantSpec, qcOutCh->maxValueInSfb, + qcOutCh->scf, psyOutCh->lastWindowSequence, psyOutCh->sfbCnt, + psyOutCh->maxSfbPerGroup, psyOutCh->sfbPerGroup, + psyOutCh->sfbOffsets, &qcOutCh->sectionData, psyOutCh->noiseNrg, + psyOutCh->isBook, psyOutCh->isScale, syntaxFlags); + + /* sum up dynamic channel bits */ + qcElement[c][i]->dynBitsUsed += chDynBits; + } + + /* save dynBitsUsed for correction of bits2pe relation */ + if (hQC->hAdjThr->adjThrStateElem[i]->dynBitsLast == -1) { + hQC->hAdjThr->adjThrStateElem[i]->dynBitsLast = + qcElement[c][i]->dynBitsUsed; + } + + /* hold total bit consumption in present element below maximum allowed + */ + if (qcElement[c][i]->dynBitsUsed > + ((nChannels * MIN_BUFSIZE_PER_EFF_CHAN) - + qcElement[c][i]->staticBitsUsed - + qcElement[c][i]->extBitsUsed)) { + constraintsFulfilled[c][i] = 0; + } + + } while (!constraintsFulfilled[c][i]); + + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + /* update dynBits of current subFrame */ + FDKaacEnc_updateUsedDynBits(&qcOut[c]->usedDynBits, qcElement[c], cm); + + /* get total consumed bits, dyn bits in all sub frames have to be valid */ + sumDynBitsConsumedTotal = + FDKaacEnc_getTotalConsumedDynBits(qcOut, nSubFrames); + + if (sumDynBitsConsumedTotal == -1) { + quantizationDone = 0; /* bit consumption not valid in all sub frames */ + } else { + int sumBitsConsumedTotal = FDKaacEnc_getTotalConsumedBits( + qcOut, qcElement, cm, hQC->globHdrBits, nSubFrames); + + /* in all frames are valid dynamic bits */ + if (((sumBitsConsumedTotal < totalAvailableBits) || + sumDynBitsConsumedTotal == 0) && + (decreaseBitConsumption == 1) && + checkMinFrameBitsDemand(qcOut, hQC->minBitsPerFrame, nSubFrames) + /*()*/) { + quantizationDone = 1; /* exit bit adjustment */ + } + if (sumBitsConsumedTotal > totalAvailableBits && + (decreaseBitConsumption == 0)) { + quantizationDone = 0; /* reset! */ + } + } + + /*-------------------------------------------- */ + + int emergencyIterations = 1; + int dynBitsOvershoot = 0; + + for (c = 0; c < nSubFrames; c++) { + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* iteration limitation */ + emergencyIterations &= + ((iterations[c][i] < hQC->maxIterations) ? 0 : 1); + } + } + /* detection if used dyn bits exceeds the maximal allowed criterion */ + dynBitsOvershoot |= + ((qcOut[c]->usedDynBits > qcOut[c]->maxDynBits) ? 1 : 0); + } + + if (quantizationDone == 0 || dynBitsOvershoot) { + int sumBitsConsumedTotal = FDKaacEnc_getTotalConsumedBits( + qcOut, qcElement, cm, hQC->globHdrBits, nSubFrames); + + if ((sumDynBitsConsumedTotal >= avgTotalDynBits) || + (sumDynBitsConsumedTotal == 0)) { + quantizationDone = 1; + } + if (emergencyIterations && (sumBitsConsumedTotal < totalAvailableBits)) { + quantizationDone = 1; + } + if ((sumBitsConsumedTotal > totalAvailableBits) || + !checkMinFrameBitsDemand(qcOut, hQC->minBitsPerFrame, nSubFrames)) { + quantizationDone = 0; + } + if ((sumBitsConsumedTotal < totalAvailableBits) && + checkMinFrameBitsDemand(qcOut, hQC->minBitsPerFrame, nSubFrames)) { + decreaseBitConsumption = 0; + } else { + decreaseBitConsumption = 1; + } + + if (dynBitsOvershoot) { + quantizationDone = 0; + decreaseBitConsumption = 1; + } + + /* reset constraints fullfilled flags */ + FDKmemclear(constraintsFulfilled, sizeof(constraintsFulfilled)); + FDKmemclear(chConstraintsFulfilled, sizeof(chConstraintsFulfilled)); + + } /* quantizationDone */ + + } while (!quantizationDone); + + /*-------------------------------------------- */ + /* ... -end- Quantization loop */ + /*-------------------------------------------- */ + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + + return AAC_ENC_OK; +} + +static AAC_ENCODER_ERROR FDKaacEnc_reduceBitConsumption( + int* iterations, const int maxIterations, int gainAdjustment, + int* chConstraintsFulfilled, int* calculateQuant, int nChannels, + PSY_OUT_ELEMENT* psyOutElement, QC_OUT* qcOut, QC_OUT_ELEMENT* qcOutElement, + ELEMENT_BITS* elBits, AUDIO_OBJECT_TYPE aot, UINT syntaxFlags, + SCHAR epConfig) { + int ch; + + /** SOLVING PROBLEM **/ + if ((*iterations) < maxIterations) { + /* increase gain (+ next iteration) */ + for (ch = 0; ch < nChannels; ch++) { + if (!chConstraintsFulfilled[ch]) { + qcOutElement->qcOutChannel[ch]->globalGain += gainAdjustment; + calculateQuant[ch] = 1; /* global gain has changed, recalculate + quantization in next iteration! */ + } + } + } else if ((*iterations) == maxIterations) { + if (qcOutElement->dynBitsUsed == 0) { + return AAC_ENC_QUANT_ERROR; + } else { + /* crash recovery */ + INT bitsToSave = 0; + if ((bitsToSave = fixMax( + (qcOutElement->dynBitsUsed + 8) - + (elBits->bitResLevelEl + qcOutElement->grantedDynBits), + (qcOutElement->dynBitsUsed + qcOutElement->staticBitsUsed + 8) - + (elBits->maxBitsEl))) > 0) { + FDKaacEnc_crashRecovery(nChannels, psyOutElement, qcOut, qcOutElement, + bitsToSave, aot, syntaxFlags, epConfig); + } else { + for (ch = 0; ch < nChannels; ch++) { + qcOutElement->qcOutChannel[ch]->globalGain += 1; + } + } + for (ch = 0; ch < nChannels; ch++) { + calculateQuant[ch] = 1; + } + } + } else { + /* (*iterations) > maxIterations */ + return AAC_ENC_QUANT_ERROR; + } + (*iterations)++; + + return AAC_ENC_OK; +} + +AAC_ENCODER_ERROR FDKaacEnc_updateFillBits(CHANNEL_MAPPING* cm, + QC_STATE* qcKernel, + ELEMENT_BITS* RESTRICT elBits[((8))], + QC_OUT** qcOut) { + switch (qcKernel->bitrateMode) { + case QCDATA_BR_MODE_SFR: + break; + + case QCDATA_BR_MODE_FF: + break; + case QCDATA_BR_MODE_VBR_1: + case QCDATA_BR_MODE_VBR_2: + case QCDATA_BR_MODE_VBR_3: + case QCDATA_BR_MODE_VBR_4: + case QCDATA_BR_MODE_VBR_5: + qcOut[0]->totFillBits = + (qcOut[0]->grantedDynBits - qcOut[0]->usedDynBits) & + 7; /* precalculate alignment bits */ + qcOut[0]->totalBits = qcOut[0]->staticBits + qcOut[0]->usedDynBits + + qcOut[0]->totFillBits + qcOut[0]->elementExtBits + + qcOut[0]->globalExtBits; + qcOut[0]->totFillBits += + (fixMax(0, qcKernel->minBitsPerFrame - qcOut[0]->totalBits) + 7) & ~7; + break; + case QCDATA_BR_MODE_CBR: + case QCDATA_BR_MODE_INVALID: + default: + INT bitResSpace = qcKernel->bitResTotMax - qcKernel->bitResTot; + /* processing fill-bits */ + INT deltaBitRes = qcOut[0]->grantedDynBits - qcOut[0]->usedDynBits; + qcOut[0]->totFillBits = fixMax( + (deltaBitRes & 7), (deltaBitRes - (fixMax(0, bitResSpace - 7) & ~7))); + qcOut[0]->totalBits = qcOut[0]->staticBits + qcOut[0]->usedDynBits + + qcOut[0]->totFillBits + qcOut[0]->elementExtBits + + qcOut[0]->globalExtBits; + qcOut[0]->totFillBits += + (fixMax(0, qcKernel->minBitsPerFrame - qcOut[0]->totalBits) + 7) & ~7; + break; + } /* switch (qcKernel->bitrateMode) */ + + return AAC_ENC_OK; +} + +/********************************************************************************* + + functionname: FDKaacEnc_calcMaxValueInSfb + description: + return: + +**********************************************************************************/ + +static INT FDKaacEnc_calcMaxValueInSfb(INT sfbCnt, INT maxSfbPerGroup, + INT sfbPerGroup, INT* RESTRICT sfbOffset, + SHORT* RESTRICT quantSpectrum, + UINT* RESTRICT maxValue) { + INT sfbOffs, sfb; + INT maxValueAll = 0; + + for (sfbOffs = 0; sfbOffs < sfbCnt; sfbOffs += sfbPerGroup) + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + INT line; + INT maxThisSfb = 0; + for (line = sfbOffset[sfbOffs + sfb]; line < sfbOffset[sfbOffs + sfb + 1]; + line++) { + INT tmp = fixp_abs(quantSpectrum[line]); + maxThisSfb = fixMax(tmp, maxThisSfb); + } + + maxValue[sfbOffs + sfb] = maxThisSfb; + maxValueAll = fixMax(maxThisSfb, maxValueAll); + } + return maxValueAll; +} + +/********************************************************************************* + + functionname: FDKaacEnc_updateBitres + description: + return: + +**********************************************************************************/ +void FDKaacEnc_updateBitres(CHANNEL_MAPPING* cm, QC_STATE* qcKernel, + QC_OUT** qcOut) { + switch (qcKernel->bitrateMode) { + case QCDATA_BR_MODE_VBR_1: + case QCDATA_BR_MODE_VBR_2: + case QCDATA_BR_MODE_VBR_3: + case QCDATA_BR_MODE_VBR_4: + case QCDATA_BR_MODE_VBR_5: + /* variable bitrate */ + qcKernel->bitResTot = + fMin(qcKernel->maxBitsPerFrame, qcKernel->bitResTotMax); + break; + case QCDATA_BR_MODE_CBR: + case QCDATA_BR_MODE_SFR: + case QCDATA_BR_MODE_INVALID: + default: + int c = 0; + /* constant bitrate */ + { + qcKernel->bitResTot += qcOut[c]->grantedDynBits - + (qcOut[c]->usedDynBits + qcOut[c]->totFillBits + + qcOut[c]->alignBits); + } + break; + } +} + +/********************************************************************************* + + functionname: FDKaacEnc_FinalizeBitConsumption + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_FinalizeBitConsumption( + CHANNEL_MAPPING* cm, QC_STATE* qcKernel, QC_OUT* qcOut, + QC_OUT_ELEMENT** qcElement, HANDLE_TRANSPORTENC hTpEnc, + AUDIO_OBJECT_TYPE aot, UINT syntaxFlags, SCHAR epConfig) { + QC_OUT_EXTENSION fillExtPayload; + INT totFillBits, alignBits; + + /* Get total consumed bits in AU */ + qcOut->totalBits = qcOut->staticBits + qcOut->usedDynBits + + qcOut->totFillBits + qcOut->elementExtBits + + qcOut->globalExtBits; + + if (qcKernel->bitrateMode == QCDATA_BR_MODE_CBR) { + /* Now we can get the exact transport bit amount, and hopefully it is equal + * to the estimated value */ + INT exactTpBits = transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits); + + if (exactTpBits != qcKernel->globHdrBits) { + INT diffFillBits = 0; + + /* How many bits can be take by bitreservoir */ + const INT bitresSpace = + qcKernel->bitResTotMax - + (qcKernel->bitResTot + + (qcOut->grantedDynBits - (qcOut->usedDynBits + qcOut->totFillBits))); + + /* Number of bits which can be moved to bitreservoir. */ + const INT bitsToBitres = qcKernel->globHdrBits - exactTpBits; + FDK_ASSERT(bitsToBitres >= 0); /* is always positive */ + + /* If bitreservoir can not take all bits, move ramaining bits to fillbits + */ + diffFillBits = fMax(0, bitsToBitres - bitresSpace); + + /* Assure previous alignment */ + diffFillBits = (diffFillBits + 7) & ~7; + + /* Move as many bits as possible to bitreservoir */ + qcKernel->bitResTot += (bitsToBitres - diffFillBits); + + /* Write remaing bits as fill bits */ + qcOut->totFillBits += diffFillBits; + qcOut->totalBits += diffFillBits; + qcOut->grantedDynBits += diffFillBits; + + /* Get new header bits */ + qcKernel->globHdrBits = + transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits); + + if (qcKernel->globHdrBits != exactTpBits) { + /* In previous step, fill bits and corresponding total bits were changed + when bitreservoir was completely filled. Now we can take the too much + taken bits caused by header overhead from bitreservoir. + */ + qcKernel->bitResTot -= (qcKernel->globHdrBits - exactTpBits); + } + } + + } /* MODE_CBR */ + + /* Update exact number of consumed header bits. */ + qcKernel->globHdrBits = transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits); + + /* Save total fill bits and distribut to alignment and fill bits */ + totFillBits = qcOut->totFillBits; + + /* fake a fill extension payload */ + FDKmemclear(&fillExtPayload, sizeof(QC_OUT_EXTENSION)); + + fillExtPayload.type = EXT_FILL_DATA; + fillExtPayload.nPayloadBits = totFillBits; + + /* ask bitstream encoder how many of that bits can be written in a fill + * extension data entity */ + qcOut->totFillBits = FDKaacEnc_writeExtensionData(NULL, &fillExtPayload, 0, 0, + syntaxFlags, aot, epConfig); + + /* now distribute extra fillbits and alignbits */ + alignBits = + 7 - (qcOut->staticBits + qcOut->usedDynBits + qcOut->elementExtBits + + qcOut->totFillBits + qcOut->globalExtBits - 1) % + 8; + + /* Maybe we could remove this */ + if (((alignBits + qcOut->totFillBits - totFillBits) == 8) && + (qcOut->totFillBits > 8)) + qcOut->totFillBits -= 8; + + qcOut->totalBits = qcOut->staticBits + qcOut->usedDynBits + + qcOut->totFillBits + alignBits + qcOut->elementExtBits + + qcOut->globalExtBits; + + if ((qcOut->totalBits > qcKernel->maxBitsPerFrame) || + (qcOut->totalBits < qcKernel->minBitsPerFrame)) { + return AAC_ENC_QUANT_ERROR; + } + + qcOut->alignBits = alignBits; + + return AAC_ENC_OK; +} + +/********************************************************************************* + + functionname: FDKaacEnc_crashRecovery + description: fulfills constraints by means of brute force... + => bits are saved by cancelling out spectral lines!! + (beginning at the highest frequencies) + return: errorcode + +**********************************************************************************/ + +static void FDKaacEnc_crashRecovery(INT nChannels, + PSY_OUT_ELEMENT* psyOutElement, + QC_OUT* qcOut, QC_OUT_ELEMENT* qcElement, + INT bitsToSave, AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig) { + INT ch; + INT savedBits = 0; + INT sfb, sfbGrp; + INT bitsPerScf[(2)][MAX_GROUPED_SFB]; + INT sectionToScf[(2)][MAX_GROUPED_SFB]; + INT* sfbOffset; + INT sect, statBitsNew; + QC_OUT_CHANNEL** qcChannel = qcElement->qcOutChannel; + PSY_OUT_CHANNEL** psyChannel = psyOutElement->psyOutChannel; + + /* create a table which converts frq-bins to bit-demand... [bitsPerScf] */ + /* ...and another one which holds the corresponding sections [sectionToScf] */ + for (ch = 0; ch < nChannels; ch++) { + sfbOffset = psyChannel[ch]->sfbOffsets; + + for (sect = 0; sect < qcChannel[ch]->sectionData.noOfSections; sect++) { + INT codeBook = qcChannel[ch]->sectionData.huffsection[sect].codeBook; + + for (sfb = qcChannel[ch]->sectionData.huffsection[sect].sfbStart; + sfb < qcChannel[ch]->sectionData.huffsection[sect].sfbStart + + qcChannel[ch]->sectionData.huffsection[sect].sfbCnt; + sfb++) { + bitsPerScf[ch][sfb] = 0; + if ((codeBook != CODE_BOOK_PNS_NO) /*&& + (sfb < (qcChannel[ch]->sectionData.noOfGroups*qcChannel[ch]->sectionData.maxSfbPerGroup))*/) { + INT sfbStartLine = sfbOffset[sfb]; + INT noOfLines = sfbOffset[sfb + 1] - sfbStartLine; + bitsPerScf[ch][sfb] = FDKaacEnc_countValues( + &(qcChannel[ch]->quantSpec[sfbStartLine]), noOfLines, codeBook); + } + sectionToScf[ch][sfb] = sect; + } + } + } + + /* LOWER [maxSfb] IN BOTH CHANNELS!! */ + /* Attention: in case of stereo: maxSfbL == maxSfbR, GroupingL == GroupingR ; + */ + + for (sfb = qcChannel[0]->sectionData.maxSfbPerGroup - 1; sfb >= 0; sfb--) { + for (sfbGrp = 0; sfbGrp < psyChannel[0]->sfbCnt; + sfbGrp += psyChannel[0]->sfbPerGroup) { + for (ch = 0; ch < nChannels; ch++) { + sect = sectionToScf[ch][sfbGrp + sfb]; + qcChannel[ch]->sectionData.huffsection[sect].sfbCnt--; + savedBits += bitsPerScf[ch][sfbGrp + sfb]; + + if (qcChannel[ch]->sectionData.huffsection[sect].sfbCnt == 0) { + savedBits += (psyChannel[ch]->lastWindowSequence != SHORT_WINDOW) + ? FDKaacEnc_sideInfoTabLong[0] + : FDKaacEnc_sideInfoTabShort[0]; + } + } + } + + /* ...have enough bits been saved? */ + if (savedBits >= bitsToSave) break; + + } /* sfb loop */ + + /* if not enough bits saved, + clean whole spectrum and remove side info overhead */ + if (sfb == -1) { + sfb = 0; + } + + for (ch = 0; ch < nChannels; ch++) { + qcChannel[ch]->sectionData.maxSfbPerGroup = sfb; + psyChannel[ch]->maxSfbPerGroup = sfb; + /* when no spectrum is coded save tools info in bitstream */ + if (sfb == 0) { + FDKmemclear(&psyChannel[ch]->tnsInfo, sizeof(TNS_INFO)); + FDKmemclear(&psyOutElement->toolsInfo, sizeof(TOOLSINFO)); + } + } + /* dynamic bits will be updated in iteration loop */ + + { /* if stop sfb has changed save bits in side info, e.g. MS or TNS coding */ + ELEMENT_INFO elInfo; + + FDKmemclear(&elInfo, sizeof(ELEMENT_INFO)); + elInfo.nChannelsInEl = nChannels; + elInfo.elType = (nChannels == 2) ? ID_CPE : ID_SCE; + + FDKaacEnc_ChannelElementWrite(NULL, &elInfo, NULL, psyOutElement, + psyChannel, syntaxFlags, aot, epConfig, + &statBitsNew, 0); + } + + savedBits = qcElement->staticBitsUsed - statBitsNew; + + /* update static and dynamic bits */ + qcElement->staticBitsUsed -= savedBits; + qcElement->grantedDynBits += savedBits; + + qcOut->staticBits -= savedBits; + qcOut->grantedDynBits += savedBits; + qcOut->maxDynBits += savedBits; +} + +void FDKaacEnc_QCClose(QC_STATE** phQCstate, QC_OUT** phQC) { + int n, i; + + if (phQC != NULL) { + for (n = 0; n < (1); n++) { + if (phQC[n] != NULL) { + QC_OUT* hQC = phQC[n]; + for (i = 0; i < (8); i++) { + } + + for (i = 0; i < ((8)); i++) { + if (hQC->qcElement[i]) FreeRam_aacEnc_QCelement(&hQC->qcElement[i]); + } + + FreeRam_aacEnc_QCout(&phQC[n]); + } + } + } + + if (phQCstate != NULL) { + if (*phQCstate != NULL) { + QC_STATE* hQCstate = *phQCstate; + + if (hQCstate->hAdjThr != NULL) FDKaacEnc_AdjThrClose(&hQCstate->hAdjThr); + + if (hQCstate->hBitCounter != NULL) + FDKaacEnc_BCClose(&hQCstate->hBitCounter); + + for (i = 0; i < ((8)); i++) { + if (hQCstate->elementBits[i] != NULL) { + FreeRam_aacEnc_ElementBits(&hQCstate->elementBits[i]); + } + } + FreeRam_aacEnc_QCstate(phQCstate); + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/qc_main.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/qc_main.h new file mode 100644 index 0000000000000..b9e8e2d0a28fa --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/qc_main.h @@ -0,0 +1,158 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Quantizing & coding + +*******************************************************************************/ + +#ifndef QC_MAIN_H +#define QC_MAIN_H + +#include "aacenc.h" +#include "qc_data.h" +#include "interface.h" +#include "psy_main.h" +#include "tpenc_lib.h" + +/* Quantizing & coding stage */ + +AAC_ENCODER_ERROR FDKaacEnc_QCOutNew(QC_OUT **phQC, const INT nElements, + const INT nChannels, const INT nSubFrames, + UCHAR *dynamic_RAM); + +AAC_ENCODER_ERROR FDKaacEnc_QCOutInit(QC_OUT *phQC[(1)], const INT nSubFrames, + const CHANNEL_MAPPING *cm); + +AAC_ENCODER_ERROR FDKaacEnc_QCNew(QC_STATE **phQC, INT nElements, + UCHAR *dynamic_RAM); + +AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC, struct QC_INIT *init, + const ULONG initFlags); + +AAC_ENCODER_ERROR FDKaacEnc_QCMainPrepare( + ELEMENT_INFO *elInfo, ATS_ELEMENT *RESTRICT adjThrStateElement, + PSY_OUT_ELEMENT *RESTRICT psyOutElement, + QC_OUT_ELEMENT *RESTRICT qcOutElement, /* returns error code */ + AUDIO_OBJECT_TYPE aot, UINT syntaxFlags, SCHAR epConfig); + +AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE *RESTRICT hQC, PSY_OUT **psyOut, + QC_OUT **qcOut, INT avgTotalBits, + CHANNEL_MAPPING *cm, AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig); + +AAC_ENCODER_ERROR FDKaacEnc_updateFillBits(CHANNEL_MAPPING *cm, + QC_STATE *qcKernel, + ELEMENT_BITS *RESTRICT elBits[((8))], + QC_OUT **qcOut); + +void FDKaacEnc_updateBitres(CHANNEL_MAPPING *cm, QC_STATE *qcKernel, + QC_OUT **qcOut); + +AAC_ENCODER_ERROR FDKaacEnc_FinalizeBitConsumption( + CHANNEL_MAPPING *cm, QC_STATE *hQC, QC_OUT *qcOut, + QC_OUT_ELEMENT **qcElement, HANDLE_TRANSPORTENC hTpEnc, + AUDIO_OBJECT_TYPE aot, UINT syntaxFlags, SCHAR epConfig); + +AAC_ENCODER_ERROR FDKaacEnc_AdjustBitrate(QC_STATE *RESTRICT hQC, + CHANNEL_MAPPING *RESTRICT cm, + INT *avgTotalBits, INT bitRate, + INT sampleRate, INT granuleLength); + +void FDKaacEnc_QCClose(QC_STATE **phQCstate, QC_OUT **phQC); + +#endif /* QC_MAIN_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/quantize.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/quantize.cpp new file mode 100644 index 0000000000000..4d25263c665cc --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/quantize.cpp @@ -0,0 +1,401 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Quantization + +*******************************************************************************/ + +#include "quantize.h" + +#include "aacEnc_rom.h" + +/***************************************************************************** + + functionname: FDKaacEnc_quantizeLines + description: quantizes spectrum lines + returns: + input: global gain, number of lines to process, spectral data + output: quantized spectrum + +*****************************************************************************/ +static void FDKaacEnc_quantizeLines(INT gain, INT noOfLines, + const FIXP_DBL *mdctSpectrum, + SHORT *quaSpectrum, INT dZoneQuantEnable) { + int line; + FIXP_DBL k = FL2FXCONST_DBL(0.0f); + FIXP_QTD quantizer = FDKaacEnc_quantTableQ[(-gain) & 3]; + INT quantizershift = ((-gain) >> 2) + 1; + const INT kShift = 16; + + if (dZoneQuantEnable) + k = FL2FXCONST_DBL(0.23f) >> kShift; + else + k = FL2FXCONST_DBL(-0.0946f + 0.5f) >> kShift; + + for (line = 0; line < noOfLines; line++) { + FIXP_DBL accu = fMultDiv2(mdctSpectrum[line], quantizer); + + if (accu < FL2FXCONST_DBL(0.0f)) { + accu = -accu; + /* normalize */ + INT accuShift = CntLeadingZeros(accu) - 1; /* CountLeadingBits() is not + necessary here since test + value is always > 0 */ + accu <<= accuShift; + INT tabIndex = + (INT)(accu >> (DFRACT_BITS - 2 - MANT_DIGITS)) & (~MANT_SIZE); + INT totalShift = quantizershift - accuShift + 1; + accu = fMultDiv2(FDKaacEnc_mTab_3_4[tabIndex], + FDKaacEnc_quantTableE[totalShift & 3]); + totalShift = (16 - 4) - (3 * (totalShift >> 2)); + FDK_ASSERT(totalShift >= 0); /* MAX_QUANT_VIOLATION */ + accu >>= fixMin(totalShift, DFRACT_BITS - 1); + quaSpectrum[line] = + (SHORT)(-((LONG)(k + accu) >> (DFRACT_BITS - 1 - 16))); + } else if (accu > FL2FXCONST_DBL(0.0f)) { + /* normalize */ + INT accuShift = CntLeadingZeros(accu) - 1; /* CountLeadingBits() is not + necessary here since test + value is always > 0 */ + accu <<= accuShift; + INT tabIndex = + (INT)(accu >> (DFRACT_BITS - 2 - MANT_DIGITS)) & (~MANT_SIZE); + INT totalShift = quantizershift - accuShift + 1; + accu = fMultDiv2(FDKaacEnc_mTab_3_4[tabIndex], + FDKaacEnc_quantTableE[totalShift & 3]); + totalShift = (16 - 4) - (3 * (totalShift >> 2)); + FDK_ASSERT(totalShift >= 0); /* MAX_QUANT_VIOLATION */ + accu >>= fixMin(totalShift, DFRACT_BITS - 1); + quaSpectrum[line] = (SHORT)((LONG)(k + accu) >> (DFRACT_BITS - 1 - 16)); + } else { + quaSpectrum[line] = 0; + } + } +} + +/***************************************************************************** + + functionname:iFDKaacEnc_quantizeLines + description: iquantizes spectrum lines + mdctSpectrum = iquaSpectrum^4/3 *2^(0.25*gain) + input: global gain, number of lines to process,quantized spectrum + output: spectral data + +*****************************************************************************/ +static void FDKaacEnc_invQuantizeLines(INT gain, INT noOfLines, + SHORT *quantSpectrum, + FIXP_DBL *mdctSpectrum) + +{ + INT iquantizermod; + INT iquantizershift; + INT line; + + iquantizermod = gain & 3; + iquantizershift = gain >> 2; + + for (line = 0; line < noOfLines; line++) { + if (quantSpectrum[line] < 0) { + FIXP_DBL accu; + INT ex, specExp, tabIndex; + FIXP_DBL s, t; + + accu = (FIXP_DBL)-quantSpectrum[line]; + + ex = CountLeadingBits(accu); + accu <<= ex; + specExp = (DFRACT_BITS - 1) - ex; + + FDK_ASSERT(specExp < 14); /* this fails if abs(value) > 8191 */ + + tabIndex = (INT)(accu >> (DFRACT_BITS - 2 - MANT_DIGITS)) & (~MANT_SIZE); + + /* calculate "mantissa" ^4/3 */ + s = FDKaacEnc_mTab_4_3Elc[tabIndex]; + + /* get approperiate exponent multiplier for specExp^3/4 combined with + * scfMod */ + t = FDKaacEnc_specExpMantTableCombElc[iquantizermod][specExp]; + + /* multiply "mantissa" ^4/3 with exponent multiplier */ + accu = fMult(s, t); + + /* get approperiate exponent shifter */ + specExp = FDKaacEnc_specExpTableComb[iquantizermod][specExp] - + 1; /* -1 to avoid overflows in accu */ + + if ((-iquantizershift - specExp) < 0) + accu <<= -(-iquantizershift - specExp); + else + accu >>= -iquantizershift - specExp; + + mdctSpectrum[line] = -accu; + } else if (quantSpectrum[line] > 0) { + FIXP_DBL accu; + INT ex, specExp, tabIndex; + FIXP_DBL s, t; + + accu = (FIXP_DBL)(INT)quantSpectrum[line]; + + ex = CountLeadingBits(accu); + accu <<= ex; + specExp = (DFRACT_BITS - 1) - ex; + + FDK_ASSERT(specExp < 14); /* this fails if abs(value) > 8191 */ + + tabIndex = (INT)(accu >> (DFRACT_BITS - 2 - MANT_DIGITS)) & (~MANT_SIZE); + + /* calculate "mantissa" ^4/3 */ + s = FDKaacEnc_mTab_4_3Elc[tabIndex]; + + /* get approperiate exponent multiplier for specExp^3/4 combined with + * scfMod */ + t = FDKaacEnc_specExpMantTableCombElc[iquantizermod][specExp]; + + /* multiply "mantissa" ^4/3 with exponent multiplier */ + accu = fMult(s, t); + + /* get approperiate exponent shifter */ + specExp = FDKaacEnc_specExpTableComb[iquantizermod][specExp] - + 1; /* -1 to avoid overflows in accu */ + + if ((-iquantizershift - specExp) < 0) + accu <<= -(-iquantizershift - specExp); + else + accu >>= -iquantizershift - specExp; + + mdctSpectrum[line] = accu; + } else { + mdctSpectrum[line] = FL2FXCONST_DBL(0.0f); + } + } +} + +/***************************************************************************** + + functionname: FDKaacEnc_QuantizeSpectrum + description: quantizes the entire spectrum + returns: + input: number of scalefactor bands to be quantized, ... + output: quantized spectrum + +*****************************************************************************/ +void FDKaacEnc_QuantizeSpectrum(INT sfbCnt, INT maxSfbPerGroup, INT sfbPerGroup, + const INT *sfbOffset, + const FIXP_DBL *mdctSpectrum, INT globalGain, + const INT *scalefactors, + SHORT *quantizedSpectrum, + INT dZoneQuantEnable) { + INT sfbOffs, sfb; + + /* in FDKaacEnc_quantizeLines quaSpectrum is calculated with: + spec^(3/4) * 2^(-3/16*QSS) * 2^(3/4*scale) + k + simplify scaling calculation and reduce QSS before: + spec^(3/4) * 2^(-3/16*(QSS - 4*scale)) */ + + for (sfbOffs = 0; sfbOffs < sfbCnt; sfbOffs += sfbPerGroup) + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + INT scalefactor = scalefactors[sfbOffs + sfb]; + + FDKaacEnc_quantizeLines( + globalGain - scalefactor, /* QSS */ + sfbOffset[sfbOffs + sfb + 1] - sfbOffset[sfbOffs + sfb], + mdctSpectrum + sfbOffset[sfbOffs + sfb], + quantizedSpectrum + sfbOffset[sfbOffs + sfb], dZoneQuantEnable); + } +} + +/***************************************************************************** + + functionname: FDKaacEnc_calcSfbDist + description: calculates distortion of quantized values + returns: distortion + input: gain, number of lines to process, spectral data + output: + +*****************************************************************************/ +FIXP_DBL FDKaacEnc_calcSfbDist(const FIXP_DBL *mdctSpectrum, + SHORT *quantSpectrum, INT noOfLines, INT gain, + INT dZoneQuantEnable) { + INT i, scale; + FIXP_DBL xfsf; + FIXP_DBL diff; + FIXP_DBL invQuantSpec; + + xfsf = FL2FXCONST_DBL(0.0f); + + for (i = 0; i < noOfLines; i++) { + /* quantization */ + FDKaacEnc_quantizeLines(gain, 1, &mdctSpectrum[i], &quantSpectrum[i], + dZoneQuantEnable); + + if (fAbs(quantSpectrum[i]) > MAX_QUANT) { + return FL2FXCONST_DBL(0.0f); + } + /* inverse quantization */ + FDKaacEnc_invQuantizeLines(gain, 1, &quantSpectrum[i], &invQuantSpec); + + /* dist */ + diff = fixp_abs(fixp_abs(invQuantSpec) - fixp_abs(mdctSpectrum[i] >> 1)); + + scale = CountLeadingBits(diff); + diff = scaleValue(diff, scale); + diff = fPow2(diff); + scale = fixMin(2 * (scale - 1), DFRACT_BITS - 1); + + diff = scaleValue(diff, -scale); + + xfsf = xfsf + diff; + } + + xfsf = CalcLdData(xfsf); + + return xfsf; +} + +/***************************************************************************** + + functionname: FDKaacEnc_calcSfbQuantEnergyAndDist + description: calculates energy and distortion of quantized values + returns: + input: gain, number of lines to process, quantized spectral data, + spectral data + output: energy, distortion + +*****************************************************************************/ +void FDKaacEnc_calcSfbQuantEnergyAndDist(FIXP_DBL *mdctSpectrum, + SHORT *quantSpectrum, INT noOfLines, + INT gain, FIXP_DBL *en, + FIXP_DBL *dist) { + INT i, scale; + FIXP_DBL invQuantSpec; + FIXP_DBL diff; + + FIXP_DBL energy = FL2FXCONST_DBL(0.0f); + FIXP_DBL distortion = FL2FXCONST_DBL(0.0f); + + for (i = 0; i < noOfLines; i++) { + if (fAbs(quantSpectrum[i]) > MAX_QUANT) { + *en = FL2FXCONST_DBL(0.0f); + *dist = FL2FXCONST_DBL(0.0f); + return; + } + + /* inverse quantization */ + FDKaacEnc_invQuantizeLines(gain, 1, &quantSpectrum[i], &invQuantSpec); + + /* energy */ + energy += fPow2(invQuantSpec); + + /* dist */ + diff = fixp_abs(fixp_abs(invQuantSpec) - fixp_abs(mdctSpectrum[i] >> 1)); + + scale = CountLeadingBits(diff); + diff = scaleValue(diff, scale); + diff = fPow2(diff); + + scale = fixMin(2 * (scale - 1), DFRACT_BITS - 1); + + diff = scaleValue(diff, -scale); + + distortion += diff; + } + + *en = CalcLdData(energy) + FL2FXCONST_DBL(0.03125f); + *dist = CalcLdData(distortion); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/quantize.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/quantize.h new file mode 100644 index 0000000000000..dfc2206bc5ae4 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/quantize.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Quantization + +*******************************************************************************/ + +#ifndef QUANTIZE_H +#define QUANTIZE_H + +#include "common_fix.h" + +/* quantizing */ + +#define MAX_QUANT 8191 + +void FDKaacEnc_QuantizeSpectrum(INT sfbCnt, INT maxSfbPerGroup, INT sfbPerGroup, + const INT *sfbOffset, + const FIXP_DBL *mdctSpectrum, INT globalGain, + const INT *scalefactors, + SHORT *quantizedSpectrum, INT dZoneQuantEnable); + +FIXP_DBL FDKaacEnc_calcSfbDist(const FIXP_DBL *mdctSpectrum, + SHORT *quantSpectrum, INT noOfLines, INT gain, + INT dZoneQuantEnable); + +void FDKaacEnc_calcSfbQuantEnergyAndDist(FIXP_DBL *mdctSpectrum, + SHORT *quantSpectrum, INT noOfLines, + INT gain, FIXP_DBL *en, + FIXP_DBL *dist); + +#endif /* QUANTIZE_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/sf_estim.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/sf_estim.cpp new file mode 100644 index 0000000000000..17a8ae27a28d3 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/sf_estim.cpp @@ -0,0 +1,1292 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Scale factor estimation + +*******************************************************************************/ + +#include "sf_estim.h" +#include "aacEnc_rom.h" +#include "quantize.h" +#include "bit_cnt.h" + +#ifdef __arm__ +#endif + +#define UPCOUNT_LIMIT 1 +#define AS_PE_FAC_SHIFT 7 +#define DIST_FAC_SHIFT 3 +#define AS_PE_FAC_FLOAT (float)(1 << AS_PE_FAC_SHIFT) +static const INT MAX_SCF_DELTA = 60; + +static const FIXP_DBL PE_C1 = FL2FXCONST_DBL( + 3.0f / AS_PE_FAC_FLOAT); /* (log(8.0)/log(2)) >> AS_PE_FAC_SHIFT */ +static const FIXP_DBL PE_C2 = FL2FXCONST_DBL( + 1.3219281f / AS_PE_FAC_FLOAT); /* (log(2.5)/log(2)) >> AS_PE_FAC_SHIFT */ +static const FIXP_DBL PE_C3 = FL2FXCONST_DBL(0.5593573f); /* 1-C2/C1 */ + +/* + Function; FDKaacEnc_FDKaacEnc_CalcFormFactorChannel + + Description: Calculates the formfactor + + sf: scale factor of the mdct spectrum + sfbFormFactorLdData is scaled with the factor 1/(((2^sf)^0.5) * + (2^FORM_FAC_SHIFT)) +*/ +static void FDKaacEnc_FDKaacEnc_CalcFormFactorChannel( + FIXP_DBL *RESTRICT sfbFormFactorLdData, + PSY_OUT_CHANNEL *RESTRICT psyOutChan) { + INT j, sfb, sfbGrp; + FIXP_DBL formFactor; + + int tmp0 = psyOutChan->sfbCnt; + int tmp1 = psyOutChan->maxSfbPerGroup; + int step = psyOutChan->sfbPerGroup; + for (sfbGrp = 0; sfbGrp < tmp0; sfbGrp += step) { + for (sfb = 0; sfb < tmp1; sfb++) { + formFactor = FL2FXCONST_DBL(0.0f); + /* calc sum of sqrt(spec) */ + for (j = psyOutChan->sfbOffsets[sfbGrp + sfb]; + j < psyOutChan->sfbOffsets[sfbGrp + sfb + 1]; j++) { + formFactor += + sqrtFixp(fixp_abs(psyOutChan->mdctSpectrum[j])) >> FORM_FAC_SHIFT; + } + sfbFormFactorLdData[sfbGrp + sfb] = CalcLdData(formFactor); + } + /* set sfbFormFactor for sfbs with zero spec to zero. Just for debugging. */ + for (; sfb < psyOutChan->sfbPerGroup; sfb++) { + sfbFormFactorLdData[sfbGrp + sfb] = FL2FXCONST_DBL(-1.0f); + } + } +} + +/* + Function: FDKaacEnc_CalcFormFactor + + Description: Calls FDKaacEnc_FDKaacEnc_CalcFormFactorChannel() for each + channel +*/ + +void FDKaacEnc_CalcFormFactor(QC_OUT_CHANNEL *qcOutChannel[(2)], + PSY_OUT_CHANNEL *psyOutChannel[(2)], + const INT nChannels) { + INT j; + for (j = 0; j < nChannels; j++) { + FDKaacEnc_FDKaacEnc_CalcFormFactorChannel( + qcOutChannel[j]->sfbFormFactorLdData, psyOutChannel[j]); + } +} + +/* + Function: FDKaacEnc_calcSfbRelevantLines + + Description: Calculates sfbNRelevantLines + + sfbNRelevantLines is scaled with the factor 1/((2^FORM_FAC_SHIFT) * 2.0) +*/ +static void FDKaacEnc_calcSfbRelevantLines( + const FIXP_DBL *const sfbFormFactorLdData, + const FIXP_DBL *const sfbEnergyLdData, + const FIXP_DBL *const sfbThresholdLdData, const INT *const sfbOffsets, + const INT sfbCnt, const INT sfbPerGroup, const INT maxSfbPerGroup, + FIXP_DBL *sfbNRelevantLines) { + INT sfbOffs, sfb; + FIXP_DBL sfbWidthLdData; + FIXP_DBL asPeFacLdData = + FL2FXCONST_DBL(0.109375); /* AS_PE_FAC_SHIFT*ld64(2) */ + FIXP_DBL accu; + + /* sfbNRelevantLines[i] = 2^( (sfbFormFactorLdData[i] - 0.25 * + * (sfbEnergyLdData[i] - ld64(sfbWidth[i]/(2^7)) - AS_PE_FAC_SHIFT*ld64(2)) * + * 64); */ + + FDKmemclear(sfbNRelevantLines, sfbCnt * sizeof(FIXP_DBL)); + + for (sfbOffs = 0; sfbOffs < sfbCnt; sfbOffs += sfbPerGroup) { + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + /* calc sum of sqrt(spec) */ + if ((FIXP_DBL)sfbEnergyLdData[sfbOffs + sfb] > + (FIXP_DBL)sfbThresholdLdData[sfbOffs + sfb]) { + INT sfbWidth = + sfbOffsets[sfbOffs + sfb + 1] - sfbOffsets[sfbOffs + sfb]; + + /* avgFormFactorLdData = + * sqrtFixp(sqrtFixp(sfbEnergyLdData[sfbOffs+sfb]/sfbWidth)); */ + /* sfbNRelevantLines[sfbOffs+sfb] = sfbFormFactor[sfbOffs+sfb] / + * avgFormFactorLdData; */ + sfbWidthLdData = + (FIXP_DBL)(sfbWidth << (DFRACT_BITS - 1 - AS_PE_FAC_SHIFT)); + sfbWidthLdData = CalcLdData(sfbWidthLdData); + + accu = sfbEnergyLdData[sfbOffs + sfb] - sfbWidthLdData - asPeFacLdData; + accu = sfbFormFactorLdData[sfbOffs + sfb] - (accu >> 2); + + sfbNRelevantLines[sfbOffs + sfb] = CalcInvLdData(accu) >> 1; + } + } + } +} + +/* + Function: FDKaacEnc_countSingleScfBits + + Description: + + scfBitsFract is scaled by 1/(2^(2*AS_PE_FAC_SHIFT)) +*/ +static FIXP_DBL FDKaacEnc_countSingleScfBits(INT scf, INT scfLeft, + INT scfRight) { + FIXP_DBL scfBitsFract; + + scfBitsFract = (FIXP_DBL)(FDKaacEnc_bitCountScalefactorDelta(scfLeft - scf) + + FDKaacEnc_bitCountScalefactorDelta(scf - scfRight)); + + scfBitsFract = scfBitsFract << (DFRACT_BITS - 1 - (2 * AS_PE_FAC_SHIFT)); + + return scfBitsFract; /* output scaled by 1/(2^(2*AS_PE_FAC)) */ +} + +/* + Function: FDKaacEnc_calcSingleSpecPe + + specPe is scaled by 1/(2^(2*AS_PE_FAC_SHIFT)) +*/ +static FIXP_DBL FDKaacEnc_calcSingleSpecPe(INT scf, FIXP_DBL sfbConstPePart, + FIXP_DBL nLines) { + FIXP_DBL specPe = FL2FXCONST_DBL(0.0f); + FIXP_DBL ldRatio; + FIXP_DBL scfFract; + + scfFract = (FIXP_DBL)(scf << (DFRACT_BITS - 1 - AS_PE_FAC_SHIFT)); + + ldRatio = sfbConstPePart - fMult(FL2FXCONST_DBL(0.375f), scfFract); + + if (ldRatio >= PE_C1) { + specPe = fMult(FL2FXCONST_DBL(0.7f), fMult(nLines, ldRatio)); + } else { + specPe = fMult(FL2FXCONST_DBL(0.7f), + fMult(nLines, (PE_C2 + fMult(PE_C3, ldRatio)))); + } + + return specPe; /* output scaled by 1/(2^(2*AS_PE_FAC)) */ +} + +/* + Function: FDKaacEnc_countScfBitsDiff + + scfBitsDiff is scaled by 1/(2^(2*AS_PE_FAC_SHIFT)) +*/ +static FIXP_DBL FDKaacEnc_countScfBitsDiff(INT *scfOld, INT *scfNew, INT sfbCnt, + INT startSfb, INT stopSfb) { + FIXP_DBL scfBitsFract; + INT scfBitsDiff = 0; + INT sfb = 0, sfbLast; + INT sfbPrev, sfbNext; + + /* search for first relevant sfb */ + sfbLast = startSfb; + while ((sfbLast < stopSfb) && (scfOld[sfbLast] == FDK_INT_MIN)) sfbLast++; + /* search for previous relevant sfb and count diff */ + sfbPrev = startSfb - 1; + while ((sfbPrev >= 0) && (scfOld[sfbPrev] == FDK_INT_MIN)) sfbPrev--; + if (sfbPrev >= 0) + scfBitsDiff += + FDKaacEnc_bitCountScalefactorDelta(scfNew[sfbPrev] - scfNew[sfbLast]) - + FDKaacEnc_bitCountScalefactorDelta(scfOld[sfbPrev] - scfOld[sfbLast]); + /* now loop through all sfbs and count diffs of relevant sfbs */ + for (sfb = sfbLast + 1; sfb < stopSfb; sfb++) { + if (scfOld[sfb] != FDK_INT_MIN) { + scfBitsDiff += + FDKaacEnc_bitCountScalefactorDelta(scfNew[sfbLast] - scfNew[sfb]) - + FDKaacEnc_bitCountScalefactorDelta(scfOld[sfbLast] - scfOld[sfb]); + sfbLast = sfb; + } + } + /* search for next relevant sfb and count diff */ + sfbNext = stopSfb; + while ((sfbNext < sfbCnt) && (scfOld[sfbNext] == FDK_INT_MIN)) sfbNext++; + if (sfbNext < sfbCnt) + scfBitsDiff += + FDKaacEnc_bitCountScalefactorDelta(scfNew[sfbLast] - scfNew[sfbNext]) - + FDKaacEnc_bitCountScalefactorDelta(scfOld[sfbLast] - scfOld[sfbNext]); + + scfBitsFract = + (FIXP_DBL)(scfBitsDiff << (DFRACT_BITS - 1 - (2 * AS_PE_FAC_SHIFT))); + + return scfBitsFract; +} + +/* + Function: FDKaacEnc_calcSpecPeDiff + + specPeDiff is scaled by 1/(2^(2*AS_PE_FAC_SHIFT)) +*/ +static FIXP_DBL FDKaacEnc_calcSpecPeDiff( + PSY_OUT_CHANNEL *psyOutChan, QC_OUT_CHANNEL *qcOutChannel, INT *scfOld, + INT *scfNew, FIXP_DBL *sfbConstPePart, FIXP_DBL *sfbFormFactorLdData, + FIXP_DBL *sfbNRelevantLines, INT startSfb, INT stopSfb) { + FIXP_DBL specPeDiff = FL2FXCONST_DBL(0.0f); + FIXP_DBL scfFract = FL2FXCONST_DBL(0.0f); + INT sfb; + + /* loop through all sfbs and count pe difference */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfOld[sfb] != FDK_INT_MIN) { + FIXP_DBL ldRatioOld, ldRatioNew, pOld, pNew; + + /* sfbConstPePart[sfb] = (float)log(psyOutChan->sfbEnergy[sfb] * 6.75f / + * sfbFormFactor[sfb]) * LOG2_1; */ + /* 0.02152255861f = log(6.75)/log(2)/AS_PE_FAC_FLOAT; LOG2_1 is 1.0 for + * log2 */ + /* 0.09375f = log(64.0)/log(2.0)/64.0 = scale of sfbFormFactorLdData */ + if (sfbConstPePart[sfb] == (FIXP_DBL)FDK_INT_MIN) + sfbConstPePart[sfb] = + ((psyOutChan->sfbEnergyLdData[sfb] - sfbFormFactorLdData[sfb] - + FL2FXCONST_DBL(0.09375f)) >> + 1) + + FL2FXCONST_DBL(0.02152255861f); + + scfFract = (FIXP_DBL)(scfOld[sfb] << (DFRACT_BITS - 1 - AS_PE_FAC_SHIFT)); + ldRatioOld = + sfbConstPePart[sfb] - fMult(FL2FXCONST_DBL(0.375f), scfFract); + + scfFract = (FIXP_DBL)(scfNew[sfb] << (DFRACT_BITS - 1 - AS_PE_FAC_SHIFT)); + ldRatioNew = + sfbConstPePart[sfb] - fMult(FL2FXCONST_DBL(0.375f), scfFract); + + if (ldRatioOld >= PE_C1) + pOld = ldRatioOld; + else + pOld = PE_C2 + fMult(PE_C3, ldRatioOld); + + if (ldRatioNew >= PE_C1) + pNew = ldRatioNew; + else + pNew = PE_C2 + fMult(PE_C3, ldRatioNew); + + specPeDiff += fMult(FL2FXCONST_DBL(0.7f), + fMult(sfbNRelevantLines[sfb], (pNew - pOld))); + } + } + + return specPeDiff; +} + +/* + Function: FDKaacEnc_improveScf + + Description: Calculate the distortion by quantization and inverse quantization + of the spectrum with various scalefactors. The scalefactor which provides the + best results will be used. +*/ +static INT FDKaacEnc_improveScf(const FIXP_DBL *spec, SHORT *quantSpec, + SHORT *quantSpecTmp, INT sfbWidth, + FIXP_DBL threshLdData, INT scf, INT minScf, + FIXP_DBL *distLdData, INT *minScfCalculated, + INT dZoneQuantEnable) { + FIXP_DBL sfbDistLdData; + INT scfBest = scf; + INT k; + FIXP_DBL distFactorLdData = FL2FXCONST_DBL(-0.0050301265); /* ld64(1/1.25) */ + + /* calc real distortion */ + sfbDistLdData = + FDKaacEnc_calcSfbDist(spec, quantSpec, sfbWidth, scf, dZoneQuantEnable); + *minScfCalculated = scf; + /* nmr > 1.25 -> try to improve nmr */ + if (sfbDistLdData > (threshLdData - distFactorLdData)) { + INT scfEstimated = scf; + FIXP_DBL sfbDistBestLdData = sfbDistLdData; + INT cnt; + /* improve by bigger scf ? */ + cnt = 0; + + while ((sfbDistLdData > (threshLdData - distFactorLdData)) && + (cnt++ < UPCOUNT_LIMIT)) { + scf++; + sfbDistLdData = FDKaacEnc_calcSfbDist(spec, quantSpecTmp, sfbWidth, scf, + dZoneQuantEnable); + + if (sfbDistLdData < sfbDistBestLdData) { + scfBest = scf; + sfbDistBestLdData = sfbDistLdData; + for (k = 0; k < sfbWidth; k++) quantSpec[k] = quantSpecTmp[k]; + } + } + /* improve by smaller scf ? */ + cnt = 0; + scf = scfEstimated; + sfbDistLdData = sfbDistBestLdData; + while ((sfbDistLdData > (threshLdData - distFactorLdData)) && (cnt++ < 1) && + (scf > minScf)) { + scf--; + sfbDistLdData = FDKaacEnc_calcSfbDist(spec, quantSpecTmp, sfbWidth, scf, + dZoneQuantEnable); + + if (sfbDistLdData < sfbDistBestLdData) { + scfBest = scf; + sfbDistBestLdData = sfbDistLdData; + for (k = 0; k < sfbWidth; k++) quantSpec[k] = quantSpecTmp[k]; + } + *minScfCalculated = scf; + } + *distLdData = sfbDistBestLdData; + } else { /* nmr <= 1.25 -> try to find bigger scf to use less bits */ + FIXP_DBL sfbDistBestLdData = sfbDistLdData; + FIXP_DBL sfbDistAllowedLdData = + fixMin(sfbDistLdData - distFactorLdData, threshLdData); + int cnt; + for (cnt = 0; cnt < UPCOUNT_LIMIT; cnt++) { + scf++; + sfbDistLdData = FDKaacEnc_calcSfbDist(spec, quantSpecTmp, sfbWidth, scf, + dZoneQuantEnable); + + if (sfbDistLdData < sfbDistAllowedLdData) { + *minScfCalculated = scfBest + 1; + scfBest = scf; + sfbDistBestLdData = sfbDistLdData; + for (k = 0; k < sfbWidth; k++) quantSpec[k] = quantSpecTmp[k]; + } + } + *distLdData = sfbDistBestLdData; + } + + /* return best scalefactor */ + return scfBest; +} + +/* + Function: FDKaacEnc_assimilateSingleScf + +*/ +static void FDKaacEnc_assimilateSingleScf( + const PSY_OUT_CHANNEL *psyOutChan, const QC_OUT_CHANNEL *qcOutChannel, + SHORT *quantSpec, SHORT *quantSpecTmp, INT dZoneQuantEnable, INT *scf, + const INT *minScf, FIXP_DBL *sfbDist, FIXP_DBL *sfbConstPePart, + const FIXP_DBL *sfbFormFactorLdData, const FIXP_DBL *sfbNRelevantLines, + INT *minScfCalculated, INT restartOnSuccess) { + INT sfbLast, sfbAct, sfbNext; + INT scfAct, *scfLast, *scfNext, scfMin, scfMax; + INT sfbWidth, sfbOffs; + FIXP_DBL enLdData; + FIXP_DBL sfbPeOld, sfbPeNew; + FIXP_DBL sfbDistNew; + INT i, k; + INT success = 0; + FIXP_DBL deltaPe = FL2FXCONST_DBL(0.0f); + FIXP_DBL deltaPeNew, deltaPeTmp; + INT prevScfLast[MAX_GROUPED_SFB], prevScfNext[MAX_GROUPED_SFB]; + FIXP_DBL deltaPeLast[MAX_GROUPED_SFB]; + INT updateMinScfCalculated; + + for (i = 0; i < psyOutChan->sfbCnt; i++) { + prevScfLast[i] = FDK_INT_MAX; + prevScfNext[i] = FDK_INT_MAX; + deltaPeLast[i] = (FIXP_DBL)FDK_INT_MAX; + } + + sfbLast = -1; + sfbAct = -1; + sfbNext = -1; + scfLast = 0; + scfNext = 0; + scfMin = FDK_INT_MAX; + scfMax = FDK_INT_MAX; + do { + /* search for new relevant sfb */ + sfbNext++; + while ((sfbNext < psyOutChan->sfbCnt) && (scf[sfbNext] == FDK_INT_MIN)) + sfbNext++; + if ((sfbLast >= 0) && (sfbAct >= 0) && (sfbNext < psyOutChan->sfbCnt)) { + /* relevant scfs to the left and to the right */ + scfAct = scf[sfbAct]; + scfLast = scf + sfbLast; + scfNext = scf + sfbNext; + scfMin = fixMin(*scfLast, *scfNext); + scfMax = fixMax(*scfLast, *scfNext); + } else if ((sfbLast == -1) && (sfbAct >= 0) && + (sfbNext < psyOutChan->sfbCnt)) { + /* first relevant scf */ + scfAct = scf[sfbAct]; + scfLast = &scfAct; + scfNext = scf + sfbNext; + scfMin = *scfNext; + scfMax = *scfNext; + } else if ((sfbLast >= 0) && (sfbAct >= 0) && + (sfbNext == psyOutChan->sfbCnt)) { + /* last relevant scf */ + scfAct = scf[sfbAct]; + scfLast = scf + sfbLast; + scfNext = &scfAct; + scfMin = *scfLast; + scfMax = *scfLast; + } + if (sfbAct >= 0) scfMin = fixMax(scfMin, minScf[sfbAct]); + + if ((sfbAct >= 0) && (sfbLast >= 0 || sfbNext < psyOutChan->sfbCnt) && + (scfAct > scfMin) && (scfAct <= scfMin + MAX_SCF_DELTA) && + (scfAct >= scfMax - MAX_SCF_DELTA) && + (scfAct <= + fixMin(scfMin, fixMin(*scfLast, *scfNext)) + MAX_SCF_DELTA) && + (*scfLast != prevScfLast[sfbAct] || *scfNext != prevScfNext[sfbAct] || + deltaPe < deltaPeLast[sfbAct])) { + /* bigger than neighbouring scf found, try to use smaller scf */ + success = 0; + + sfbWidth = + psyOutChan->sfbOffsets[sfbAct + 1] - psyOutChan->sfbOffsets[sfbAct]; + sfbOffs = psyOutChan->sfbOffsets[sfbAct]; + + /* estimate required bits for actual scf */ + enLdData = qcOutChannel->sfbEnergyLdData[sfbAct]; + + /* sfbConstPePart[sfbAct] = (float)log(6.75f*en/sfbFormFactor[sfbAct]) * + * LOG2_1; */ + /* 0.02152255861f = log(6.75)/log(2)/AS_PE_FAC_FLOAT; LOG2_1 is 1.0 for + * log2 */ + /* 0.09375f = log(64.0)/log(2.0)/64.0 = scale of sfbFormFactorLdData */ + if (sfbConstPePart[sfbAct] == (FIXP_DBL)FDK_INT_MIN) { + sfbConstPePart[sfbAct] = ((enLdData - sfbFormFactorLdData[sfbAct] - + FL2FXCONST_DBL(0.09375f)) >> + 1) + + FL2FXCONST_DBL(0.02152255861f); + } + + sfbPeOld = FDKaacEnc_calcSingleSpecPe(scfAct, sfbConstPePart[sfbAct], + sfbNRelevantLines[sfbAct]) + + FDKaacEnc_countSingleScfBits(scfAct, *scfLast, *scfNext); + + deltaPeNew = deltaPe; + updateMinScfCalculated = 1; + + do { + /* estimate required bits for smaller scf */ + scfAct--; + /* check only if the same check was not done before */ + if (scfAct < minScfCalculated[sfbAct] && + scfAct >= scfMax - MAX_SCF_DELTA) { + /* estimate required bits for new scf */ + sfbPeNew = FDKaacEnc_calcSingleSpecPe(scfAct, sfbConstPePart[sfbAct], + sfbNRelevantLines[sfbAct]) + + FDKaacEnc_countSingleScfBits(scfAct, *scfLast, *scfNext); + + /* use new scf if no increase in pe and + quantization error is smaller */ + deltaPeTmp = deltaPe + sfbPeNew - sfbPeOld; + /* 0.0006103515625f = 10.0f/(2^(2*AS_PE_FAC_SHIFT)) */ + if (deltaPeTmp < FL2FXCONST_DBL(0.0006103515625f)) { + /* distortion of new scf */ + sfbDistNew = FDKaacEnc_calcSfbDist( + qcOutChannel->mdctSpectrum + sfbOffs, quantSpecTmp + sfbOffs, + sfbWidth, scfAct, dZoneQuantEnable); + + if (sfbDistNew < sfbDist[sfbAct]) { + /* success, replace scf by new one */ + scf[sfbAct] = scfAct; + sfbDist[sfbAct] = sfbDistNew; + + for (k = 0; k < sfbWidth; k++) + quantSpec[sfbOffs + k] = quantSpecTmp[sfbOffs + k]; + + deltaPeNew = deltaPeTmp; + success = 1; + } + /* mark as already checked */ + if (updateMinScfCalculated) minScfCalculated[sfbAct] = scfAct; + } else { + /* from this scf value on not all new values have been checked */ + updateMinScfCalculated = 0; + } + } + } while (scfAct > scfMin); + + deltaPe = deltaPeNew; + + /* save parameters to avoid multiple computations of the same sfb */ + prevScfLast[sfbAct] = *scfLast; + prevScfNext[sfbAct] = *scfNext; + deltaPeLast[sfbAct] = deltaPe; + } + + if (success && restartOnSuccess) { + /* start again at first sfb */ + sfbLast = -1; + sfbAct = -1; + sfbNext = -1; + scfLast = 0; + scfNext = 0; + scfMin = FDK_INT_MAX; + scfMax = FDK_INT_MAX; + success = 0; + } else { + /* shift sfbs for next band */ + sfbLast = sfbAct; + sfbAct = sfbNext; + } + } while (sfbNext < psyOutChan->sfbCnt); +} + +/* + Function: FDKaacEnc_assimilateMultipleScf + +*/ +static void FDKaacEnc_assimilateMultipleScf( + PSY_OUT_CHANNEL *psyOutChan, QC_OUT_CHANNEL *qcOutChannel, SHORT *quantSpec, + SHORT *quantSpecTmp, INT dZoneQuantEnable, INT *scf, const INT *minScf, + FIXP_DBL *sfbDist, FIXP_DBL *sfbConstPePart, FIXP_DBL *sfbFormFactorLdData, + FIXP_DBL *sfbNRelevantLines) { + INT sfb, startSfb, stopSfb; + INT scfTmp[MAX_GROUPED_SFB], scfMin, scfMax, scfAct; + INT possibleRegionFound; + INT sfbWidth, sfbOffs, i, k; + FIXP_DBL sfbDistNew[MAX_GROUPED_SFB], distOldSum, distNewSum; + INT deltaScfBits; + FIXP_DBL deltaSpecPe; + FIXP_DBL deltaPe = FL2FXCONST_DBL(0.0f); + FIXP_DBL deltaPeNew; + INT sfbCnt = psyOutChan->sfbCnt; + + /* calc min and max scalfactors */ + scfMin = FDK_INT_MAX; + scfMax = FDK_INT_MIN; + for (sfb = 0; sfb < sfbCnt; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + scfMin = fixMin(scfMin, scf[sfb]); + scfMax = fixMax(scfMax, scf[sfb]); + } + } + + if (scfMax != FDK_INT_MIN && scfMax <= scfMin + MAX_SCF_DELTA) { + scfAct = scfMax; + + do { + /* try smaller scf */ + scfAct--; + for (i = 0; i < MAX_GROUPED_SFB; i++) scfTmp[i] = scf[i]; + stopSfb = 0; + do { + /* search for region where all scfs are bigger than scfAct */ + sfb = stopSfb; + while (sfb < sfbCnt && (scf[sfb] == FDK_INT_MIN || scf[sfb] <= scfAct)) + sfb++; + startSfb = sfb; + sfb++; + while (sfb < sfbCnt && (scf[sfb] == FDK_INT_MIN || scf[sfb] > scfAct)) + sfb++; + stopSfb = sfb; + + /* check if in all sfb of a valid region scfAct >= minScf[sfb] */ + possibleRegionFound = 0; + if (startSfb < sfbCnt) { + possibleRegionFound = 1; + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scf[sfb] != FDK_INT_MIN) + if (scfAct < minScf[sfb]) { + possibleRegionFound = 0; + break; + } + } + } + + if (possibleRegionFound) { /* region found */ + + /* replace scfs in region by scfAct */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) scfTmp[sfb] = scfAct; + } + + /* estimate change in bit demand for new scfs */ + deltaScfBits = FDKaacEnc_countScfBitsDiff(scf, scfTmp, sfbCnt, + startSfb, stopSfb); + + deltaSpecPe = FDKaacEnc_calcSpecPeDiff( + psyOutChan, qcOutChannel, scf, scfTmp, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines, startSfb, stopSfb); + + deltaPeNew = deltaPe + (FIXP_DBL)deltaScfBits + deltaSpecPe; + + /* new bit demand small enough ? */ + /* 0.0006103515625f = 10.0f/(2^(2*AS_PE_FAC_SHIFT)) */ + if (deltaPeNew < FL2FXCONST_DBL(0.0006103515625f)) { + /* quantize and calc sum of new distortion */ + distOldSum = distNewSum = FL2FXCONST_DBL(0.0f); + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) { + distOldSum += CalcInvLdData(sfbDist[sfb]) >> DIST_FAC_SHIFT; + + sfbWidth = psyOutChan->sfbOffsets[sfb + 1] - + psyOutChan->sfbOffsets[sfb]; + sfbOffs = psyOutChan->sfbOffsets[sfb]; + + sfbDistNew[sfb] = FDKaacEnc_calcSfbDist( + qcOutChannel->mdctSpectrum + sfbOffs, + quantSpecTmp + sfbOffs, sfbWidth, scfAct, dZoneQuantEnable); + + if (sfbDistNew[sfb] > qcOutChannel->sfbThresholdLdData[sfb]) { + /* no improvement, skip further dist. calculations */ + distNewSum = distOldSum << 1; + break; + } + distNewSum += CalcInvLdData(sfbDistNew[sfb]) >> DIST_FAC_SHIFT; + } + } + /* distortion smaller ? -> use new scalefactors */ + if (distNewSum < distOldSum) { + deltaPe = deltaPeNew; + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + sfbWidth = psyOutChan->sfbOffsets[sfb + 1] - + psyOutChan->sfbOffsets[sfb]; + sfbOffs = psyOutChan->sfbOffsets[sfb]; + scf[sfb] = scfAct; + sfbDist[sfb] = sfbDistNew[sfb]; + + for (k = 0; k < sfbWidth; k++) + quantSpec[sfbOffs + k] = quantSpecTmp[sfbOffs + k]; + } + } + } + } + } + + } while (stopSfb <= sfbCnt); + + } while (scfAct > scfMin); + } +} + +/* + Function: FDKaacEnc_FDKaacEnc_assimilateMultipleScf2 + +*/ +static void FDKaacEnc_FDKaacEnc_assimilateMultipleScf2( + PSY_OUT_CHANNEL *psyOutChan, QC_OUT_CHANNEL *qcOutChannel, SHORT *quantSpec, + SHORT *quantSpecTmp, INT dZoneQuantEnable, INT *scf, const INT *minScf, + FIXP_DBL *sfbDist, FIXP_DBL *sfbConstPePart, FIXP_DBL *sfbFormFactorLdData, + FIXP_DBL *sfbNRelevantLines) { + INT sfb, startSfb, stopSfb; + INT scfTmp[MAX_GROUPED_SFB], scfAct, scfNew; + INT scfPrev, scfNext, scfPrevNextMin, scfPrevNextMax, scfLo, scfHi; + INT scfMin, scfMax; + INT *sfbOffs = psyOutChan->sfbOffsets; + FIXP_DBL sfbDistNew[MAX_GROUPED_SFB], sfbDistMax[MAX_GROUPED_SFB]; + FIXP_DBL distOldSum, distNewSum; + INT deltaScfBits; + FIXP_DBL deltaSpecPe; + FIXP_DBL deltaPe = FL2FXCONST_DBL(0.0f); + FIXP_DBL deltaPeNew = FL2FXCONST_DBL(0.0f); + INT sfbCnt = psyOutChan->sfbCnt; + INT bSuccess, bCheckScf; + INT i, k; + + /* calc min and max scalfactors */ + scfMin = FDK_INT_MAX; + scfMax = FDK_INT_MIN; + for (sfb = 0; sfb < sfbCnt; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + scfMin = fixMin(scfMin, scf[sfb]); + scfMax = fixMax(scfMax, scf[sfb]); + } + } + + stopSfb = 0; + scfAct = FDK_INT_MIN; + do { + /* search for region with same scf values scfAct */ + scfPrev = scfAct; + + sfb = stopSfb; + while (sfb < sfbCnt && (scf[sfb] == FDK_INT_MIN)) sfb++; + startSfb = sfb; + scfAct = scf[startSfb]; + sfb++; + while (sfb < sfbCnt && + ((scf[sfb] == FDK_INT_MIN) || (scf[sfb] == scf[startSfb]))) + sfb++; + stopSfb = sfb; + + if (stopSfb < sfbCnt) + scfNext = scf[stopSfb]; + else + scfNext = scfAct; + + if (scfPrev == FDK_INT_MIN) scfPrev = scfAct; + + scfPrevNextMax = fixMax(scfPrev, scfNext); + scfPrevNextMin = fixMin(scfPrev, scfNext); + + /* try to reduce bits by checking scf values in the range + scf[startSfb]...scfHi */ + scfHi = fixMax(scfPrevNextMax, scfAct); + /* try to find a better solution by reducing the scf difference to + the nearest possible lower scf */ + if (scfPrevNextMax >= scfAct) + scfLo = fixMin(scfAct, scfPrevNextMin); + else + scfLo = scfPrevNextMax; + + if (startSfb < sfbCnt && + scfHi - scfLo <= MAX_SCF_DELTA) { /* region found */ + /* 1. try to save bits by coarser quantization */ + if (scfHi > scf[startSfb]) { + /* calculate the allowed distortion */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + /* sfbDistMax[sfb] = + * (float)pow(qcOutChannel->sfbThreshold[sfb]*sfbDist[sfb]*sfbDist[sfb],1.0f/3.0f); + */ + /* sfbDistMax[sfb] = + * fixMax(sfbDistMax[sfb],qcOutChannel->sfbEnergy[sfb]*FL2FXCONST_DBL(1.e-3f)); + */ + /* -0.15571537944 = ld64(1.e-3f)*/ + sfbDistMax[sfb] = fMult(FL2FXCONST_DBL(1.0f / 3.0f), + qcOutChannel->sfbThresholdLdData[sfb]) + + fMult(FL2FXCONST_DBL(1.0f / 3.0f), sfbDist[sfb]) + + fMult(FL2FXCONST_DBL(1.0f / 3.0f), sfbDist[sfb]); + sfbDistMax[sfb] = + fixMax(sfbDistMax[sfb], qcOutChannel->sfbEnergyLdData[sfb] - + FL2FXCONST_DBL(0.15571537944)); + sfbDistMax[sfb] = + fixMin(sfbDistMax[sfb], qcOutChannel->sfbThresholdLdData[sfb]); + } + } + + /* loop over all possible scf values for this region */ + bCheckScf = 1; + for (scfNew = scf[startSfb] + 1; scfNew <= scfHi; scfNew++) { + for (k = 0; k < MAX_GROUPED_SFB; k++) scfTmp[k] = scf[k]; + + /* replace scfs in region by scfNew */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) scfTmp[sfb] = scfNew; + } + + /* estimate change in bit demand for new scfs */ + deltaScfBits = FDKaacEnc_countScfBitsDiff(scf, scfTmp, sfbCnt, + startSfb, stopSfb); + + deltaSpecPe = FDKaacEnc_calcSpecPeDiff( + psyOutChan, qcOutChannel, scf, scfTmp, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines, startSfb, stopSfb); + + deltaPeNew = deltaPe + (FIXP_DBL)deltaScfBits + deltaSpecPe; + + /* new bit demand small enough ? */ + if (deltaPeNew < FL2FXCONST_DBL(0.0f)) { + bSuccess = 1; + + /* quantize and calc sum of new distortion */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) { + sfbDistNew[sfb] = FDKaacEnc_calcSfbDist( + qcOutChannel->mdctSpectrum + sfbOffs[sfb], + quantSpecTmp + sfbOffs[sfb], + sfbOffs[sfb + 1] - sfbOffs[sfb], scfNew, dZoneQuantEnable); + + if (sfbDistNew[sfb] > sfbDistMax[sfb]) { + /* no improvement, skip further dist. calculations */ + bSuccess = 0; + if (sfbDistNew[sfb] == qcOutChannel->sfbEnergyLdData[sfb]) { + /* if whole sfb is already quantized to 0, further + checks with even coarser quant. are useless*/ + bCheckScf = 0; + } + break; + } + } + } + if (bCheckScf == 0) /* further calculations useless ? */ + break; + /* distortion small enough ? -> use new scalefactors */ + if (bSuccess) { + deltaPe = deltaPeNew; + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + scf[sfb] = scfNew; + sfbDist[sfb] = sfbDistNew[sfb]; + + for (k = 0; k < sfbOffs[sfb + 1] - sfbOffs[sfb]; k++) + quantSpec[sfbOffs[sfb] + k] = + quantSpecTmp[sfbOffs[sfb] + k]; + } + } + } + } + } + } + + /* 2. only if coarser quantization was not successful, try to find + a better solution by finer quantization and reducing bits for + scalefactor coding */ + if (scfAct == scf[startSfb] && scfLo < scfAct && + scfMax - scfMin <= MAX_SCF_DELTA) { + int bminScfViolation = 0; + + for (k = 0; k < MAX_GROUPED_SFB; k++) scfTmp[k] = scf[k]; + + scfNew = scfLo; + + /* replace scfs in region by scfNew and + check if in all sfb scfNew >= minScf[sfb] */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) { + scfTmp[sfb] = scfNew; + if (scfNew < minScf[sfb]) bminScfViolation = 1; + } + } + + if (!bminScfViolation) { + /* estimate change in bit demand for new scfs */ + deltaScfBits = FDKaacEnc_countScfBitsDiff(scf, scfTmp, sfbCnt, + startSfb, stopSfb); + + deltaSpecPe = FDKaacEnc_calcSpecPeDiff( + psyOutChan, qcOutChannel, scf, scfTmp, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines, startSfb, stopSfb); + + deltaPeNew = deltaPe + (FIXP_DBL)deltaScfBits + deltaSpecPe; + } + + /* new bit demand small enough ? */ + if (!bminScfViolation && deltaPeNew < FL2FXCONST_DBL(0.0f)) { + /* quantize and calc sum of new distortion */ + distOldSum = distNewSum = FL2FXCONST_DBL(0.0f); + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) { + distOldSum += CalcInvLdData(sfbDist[sfb]) >> DIST_FAC_SHIFT; + + sfbDistNew[sfb] = FDKaacEnc_calcSfbDist( + qcOutChannel->mdctSpectrum + sfbOffs[sfb], + quantSpecTmp + sfbOffs[sfb], sfbOffs[sfb + 1] - sfbOffs[sfb], + scfNew, dZoneQuantEnable); + + if (sfbDistNew[sfb] > qcOutChannel->sfbThresholdLdData[sfb]) { + /* no improvement, skip further dist. calculations */ + distNewSum = distOldSum << 1; + break; + } + distNewSum += CalcInvLdData(sfbDistNew[sfb]) >> DIST_FAC_SHIFT; + } + } + /* distortion smaller ? -> use new scalefactors */ + if (distNewSum < fMult(FL2FXCONST_DBL(0.8f), distOldSum)) { + deltaPe = deltaPeNew; + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + scf[sfb] = scfNew; + sfbDist[sfb] = sfbDistNew[sfb]; + + for (k = 0; k < sfbOffs[sfb + 1] - sfbOffs[sfb]; k++) + quantSpec[sfbOffs[sfb] + k] = quantSpecTmp[sfbOffs[sfb] + k]; + } + } + } + } + } + + /* 3. try to find a better solution (save bits) by only reducing the + scalefactor without new quantization */ + if (scfMax - scfMin <= + MAX_SCF_DELTA - 3) { /* 3 bec. scf is reduced 3 times, + see for loop below */ + + for (k = 0; k < sfbCnt; k++) scfTmp[k] = scf[k]; + + for (i = 0; i < 3; i++) { + scfNew = scfTmp[startSfb] - 1; + /* replace scfs in region by scfNew */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) scfTmp[sfb] = scfNew; + } + /* estimate change in bit demand for new scfs */ + deltaScfBits = FDKaacEnc_countScfBitsDiff(scf, scfTmp, sfbCnt, + startSfb, stopSfb); + deltaPeNew = deltaPe + (FIXP_DBL)deltaScfBits; + /* new bit demand small enough ? */ + if (deltaPeNew <= FL2FXCONST_DBL(0.0f)) { + bSuccess = 1; + distOldSum = distNewSum = FL2FXCONST_DBL(0.0f); + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) { + FIXP_DBL sfbEnQ; + /* calc the energy and distortion of the quantized spectrum for + a smaller scf */ + FDKaacEnc_calcSfbQuantEnergyAndDist( + qcOutChannel->mdctSpectrum + sfbOffs[sfb], + quantSpec + sfbOffs[sfb], sfbOffs[sfb + 1] - sfbOffs[sfb], + scfNew, &sfbEnQ, &sfbDistNew[sfb]); + + distOldSum += CalcInvLdData(sfbDist[sfb]) >> DIST_FAC_SHIFT; + distNewSum += CalcInvLdData(sfbDistNew[sfb]) >> DIST_FAC_SHIFT; + + /* 0.00259488556167 = ld64(1.122f) */ + /* -0.00778722686652 = ld64(0.7079f) */ + if ((sfbDistNew[sfb] > + (sfbDist[sfb] + FL2FXCONST_DBL(0.00259488556167f))) || + (sfbEnQ < (qcOutChannel->sfbEnergyLdData[sfb] - + FL2FXCONST_DBL(0.00778722686652f)))) { + bSuccess = 0; + break; + } + } + } + /* distortion smaller ? -> use new scalefactors */ + if (distNewSum < distOldSum && bSuccess) { + deltaPe = deltaPeNew; + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + scf[sfb] = scfNew; + sfbDist[sfb] = sfbDistNew[sfb]; + } + } + } + } + } + } + } + } while (stopSfb <= sfbCnt); +} + +static void FDKaacEnc_EstimateScaleFactorsChannel( + QC_OUT_CHANNEL *qcOutChannel, PSY_OUT_CHANNEL *psyOutChannel, + INT *RESTRICT scf, INT *RESTRICT globalGain, + FIXP_DBL *RESTRICT sfbFormFactorLdData, const INT invQuant, + SHORT *RESTRICT quantSpec, const INT dZoneQuantEnable) { + INT i, j, sfb, sfbOffs; + INT scfInt; + INT maxSf; + INT minSf; + FIXP_DBL threshLdData; + FIXP_DBL energyLdData; + FIXP_DBL energyPartLdData; + FIXP_DBL thresholdPartLdData; + FIXP_DBL scfFract; + FIXP_DBL maxSpec; + INT minScfCalculated[MAX_GROUPED_SFB]; + FIXP_DBL sfbDistLdData[MAX_GROUPED_SFB]; + C_ALLOC_SCRATCH_START(quantSpecTmp, SHORT, (1024)) + INT minSfMaxQuant[MAX_GROUPED_SFB]; + + FIXP_DBL threshConstLdData = + FL2FXCONST_DBL(0.04304511722f); /* log10(6.75)/log10(2.0)/64.0 */ + FIXP_DBL convConst = FL2FXCONST_DBL(0.30102999566f); /* log10(2.0) */ + FIXP_DBL c1Const = + FL2FXCONST_DBL(-0.27083183594f); /* C1 = -69.33295 => C1/2^8 */ + + if (invQuant > 0) { + FDKmemclear(quantSpec, (1024) * sizeof(SHORT)); + } + + /* scfs without energy or with thresh>energy are marked with FDK_INT_MIN */ + for (i = 0; i < psyOutChannel->sfbCnt; i++) { + scf[i] = FDK_INT_MIN; + } + + for (i = 0; i < MAX_GROUPED_SFB; i++) { + minSfMaxQuant[i] = FDK_INT_MIN; + } + + for (sfbOffs = 0; sfbOffs < psyOutChannel->sfbCnt; + sfbOffs += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + threshLdData = qcOutChannel->sfbThresholdLdData[sfbOffs + sfb]; + energyLdData = qcOutChannel->sfbEnergyLdData[sfbOffs + sfb]; + + sfbDistLdData[sfbOffs + sfb] = energyLdData; + + if (energyLdData > threshLdData) { + FIXP_DBL tmp; + + /* energyPart = (float)log10(sfbFormFactor[sfbOffs+sfb]); */ + /* 0.09375f = log(64.0)/log(2.0)/64.0 = scale of sfbFormFactorLdData */ + energyPartLdData = + sfbFormFactorLdData[sfbOffs + sfb] + FL2FXCONST_DBL(0.09375f); + + /* influence of allowed distortion */ + /* thresholdPart = (float)log10(6.75*thresh+FLT_MIN); */ + thresholdPartLdData = threshConstLdData + threshLdData; + + /* scf calc */ + /* scfFloat = 8.8585f * (thresholdPart - energyPart); */ + scfFract = thresholdPartLdData - energyPartLdData; + /* conversion from log2 to log10 */ + scfFract = fMult(convConst, scfFract); + /* (8.8585f * scfFract)/8 = 8/8 * scfFract + 0.8585 * scfFract/8 */ + scfFract = scfFract + fMult(FL2FXCONST_DBL(0.8585f), scfFract >> 3); + + /* integer scalefactor */ + /* scfInt = (int)floor(scfFloat); */ + scfInt = + (INT)(scfFract >> + ((DFRACT_BITS - 1) - 3 - + LD_DATA_SHIFT)); /* 3 bits => scfFract/8.0; 6 bits => ld64 */ + + /* maximum of spectrum */ + maxSpec = FL2FXCONST_DBL(0.0f); + + /* Unroll by 4, allow dual memory access */ + DWORD_ALIGNED(qcOutChannel->mdctSpectrum); + for (j = psyOutChannel->sfbOffsets[sfbOffs + sfb]; + j < psyOutChannel->sfbOffsets[sfbOffs + sfb + 1]; j += 4) { + maxSpec = fMax(maxSpec, + fMax(fMax(fAbs(qcOutChannel->mdctSpectrum[j + 0]), + fAbs(qcOutChannel->mdctSpectrum[j + 1])), + fMax(fAbs(qcOutChannel->mdctSpectrum[j + 2]), + fAbs(qcOutChannel->mdctSpectrum[j + 3])))); + } + /* lower scf limit to avoid quantized values bigger than MAX_QUANT */ + /* C1 = -69.33295f, C2 = 5.77078f = 4/log(2) */ + /* minSfMaxQuant[sfbOffs+sfb] = (int)ceil(C1 + C2*log(maxSpec)); */ + /* C1/2^8 + 4/log(2.0)*log(maxSpec)/2^8 => C1/2^8 + + * log(maxSpec)/log(2.0)*4/2^8 => C1/2^8 + log(maxSpec)/log(2.0)/64.0 */ + + // minSfMaxQuant[sfbOffs+sfb] = ((INT) ((c1Const + CalcLdData(maxSpec)) + // >> ((DFRACT_BITS-1)-8))) + 1; + tmp = CalcLdData(maxSpec); + if (c1Const > FL2FXCONST_DBL(-1.f) - tmp) { + minSfMaxQuant[sfbOffs + sfb] = + ((INT)((c1Const + tmp) >> ((DFRACT_BITS - 1) - 8))) + 1; + } else { + minSfMaxQuant[sfbOffs + sfb] = + ((INT)(FL2FXCONST_DBL(-1.f) >> ((DFRACT_BITS - 1) - 8))) + 1; + } + + scfInt = fixMax(scfInt, minSfMaxQuant[sfbOffs + sfb]); + + /* find better scalefactor with analysis by synthesis */ + if (invQuant > 0) { + scfInt = FDKaacEnc_improveScf( + qcOutChannel->mdctSpectrum + + psyOutChannel->sfbOffsets[sfbOffs + sfb], + quantSpec + psyOutChannel->sfbOffsets[sfbOffs + sfb], + quantSpecTmp + psyOutChannel->sfbOffsets[sfbOffs + sfb], + psyOutChannel->sfbOffsets[sfbOffs + sfb + 1] - + psyOutChannel->sfbOffsets[sfbOffs + sfb], + threshLdData, scfInt, minSfMaxQuant[sfbOffs + sfb], + &sfbDistLdData[sfbOffs + sfb], &minScfCalculated[sfbOffs + sfb], + dZoneQuantEnable); + } + scf[sfbOffs + sfb] = scfInt; + } + } + } + + if (invQuant > 0) { + /* try to decrease scf differences */ + FIXP_DBL sfbConstPePart[MAX_GROUPED_SFB]; + FIXP_DBL sfbNRelevantLines[MAX_GROUPED_SFB]; + + for (i = 0; i < psyOutChannel->sfbCnt; i++) + sfbConstPePart[i] = (FIXP_DBL)FDK_INT_MIN; + + FDKaacEnc_calcSfbRelevantLines( + sfbFormFactorLdData, qcOutChannel->sfbEnergyLdData, + qcOutChannel->sfbThresholdLdData, psyOutChannel->sfbOffsets, + psyOutChannel->sfbCnt, psyOutChannel->sfbPerGroup, + psyOutChannel->maxSfbPerGroup, sfbNRelevantLines); + + FDKaacEnc_assimilateSingleScf( + psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, dZoneQuantEnable, + scf, minSfMaxQuant, sfbDistLdData, sfbConstPePart, sfbFormFactorLdData, + sfbNRelevantLines, minScfCalculated, 1); + + if (invQuant > 1) { + FDKaacEnc_assimilateMultipleScf( + psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, + dZoneQuantEnable, scf, minSfMaxQuant, sfbDistLdData, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines); + + FDKaacEnc_FDKaacEnc_assimilateMultipleScf2( + psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, + dZoneQuantEnable, scf, minSfMaxQuant, sfbDistLdData, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines); + } + } + + /* get min scalefac */ + minSf = FDK_INT_MAX; + for (sfbOffs = 0; sfbOffs < psyOutChannel->sfbCnt; + sfbOffs += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if (scf[sfbOffs + sfb] != FDK_INT_MIN) + minSf = fixMin(minSf, scf[sfbOffs + sfb]); + } + } + + /* limit scf delta */ + for (sfbOffs = 0; sfbOffs < psyOutChannel->sfbCnt; + sfbOffs += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if ((scf[sfbOffs + sfb] != FDK_INT_MIN) && + (minSf + MAX_SCF_DELTA) < scf[sfbOffs + sfb]) { + scf[sfbOffs + sfb] = minSf + MAX_SCF_DELTA; + if (invQuant > 0) { /* changed bands need to be quantized again */ + sfbDistLdData[sfbOffs + sfb] = FDKaacEnc_calcSfbDist( + qcOutChannel->mdctSpectrum + + psyOutChannel->sfbOffsets[sfbOffs + sfb], + quantSpec + psyOutChannel->sfbOffsets[sfbOffs + sfb], + psyOutChannel->sfbOffsets[sfbOffs + sfb + 1] - + psyOutChannel->sfbOffsets[sfbOffs + sfb], + scf[sfbOffs + sfb], dZoneQuantEnable); + } + } + } + } + + /* get max scalefac for global gain */ + maxSf = FDK_INT_MIN; + for (sfbOffs = 0; sfbOffs < psyOutChannel->sfbCnt; + sfbOffs += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + maxSf = fixMax(maxSf, scf[sfbOffs + sfb]); + } + } + + /* calc loop scalefactors, if spec is not all zero (i.e. maxSf == -99) */ + if (maxSf > FDK_INT_MIN) { + *globalGain = maxSf; + for (sfbOffs = 0; sfbOffs < psyOutChannel->sfbCnt; + sfbOffs += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if (scf[sfbOffs + sfb] == FDK_INT_MIN) { + scf[sfbOffs + sfb] = 0; + /* set band explicitely to zero */ + for (j = psyOutChannel->sfbOffsets[sfbOffs + sfb]; + j < psyOutChannel->sfbOffsets[sfbOffs + sfb + 1]; j++) { + qcOutChannel->mdctSpectrum[j] = FL2FXCONST_DBL(0.0f); + } + } else { + scf[sfbOffs + sfb] = maxSf - scf[sfbOffs + sfb]; + } + } + } + } else { + *globalGain = 0; + /* set spectrum explicitely to zero */ + for (sfbOffs = 0; sfbOffs < psyOutChannel->sfbCnt; + sfbOffs += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + scf[sfbOffs + sfb] = 0; + /* set band explicitely to zero */ + for (j = psyOutChannel->sfbOffsets[sfbOffs + sfb]; + j < psyOutChannel->sfbOffsets[sfbOffs + sfb + 1]; j++) { + qcOutChannel->mdctSpectrum[j] = FL2FXCONST_DBL(0.0f); + } + } + } + } + + /* free quantSpecTmp from scratch */ + C_ALLOC_SCRATCH_END(quantSpecTmp, SHORT, (1024)) +} + +void FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[], + QC_OUT_CHANNEL *qcOutChannel[], + const INT invQuant, + const INT dZoneQuantEnable, + const INT nChannels) { + int ch; + + for (ch = 0; ch < nChannels; ch++) { + FDKaacEnc_EstimateScaleFactorsChannel( + qcOutChannel[ch], psyOutChannel[ch], qcOutChannel[ch]->scf, + &qcOutChannel[ch]->globalGain, qcOutChannel[ch]->sfbFormFactorLdData, + invQuant, qcOutChannel[ch]->quantSpec, dZoneQuantEnable); + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/sf_estim.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/sf_estim.h new file mode 100644 index 0000000000000..ab2d3c265e481 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/sf_estim.h @@ -0,0 +1,124 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Scale factor estimation + +*******************************************************************************/ + +#ifndef SF_ESTIM_H +#define SF_ESTIM_H + +#include "common_fix.h" + +#include "psy_const.h" +#include "qc_data.h" +#include "interface.h" + +#define FORM_FAC_SHIFT 6 + +void FDKaacEnc_CalcFormFactor(QC_OUT_CHANNEL *qcOutChannel[(2)], + PSY_OUT_CHANNEL *psyOutChannel[(2)], + const INT nChannels); + +void FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[], + QC_OUT_CHANNEL *qcOutChannel[], + const INT invQuant, + const INT dZoneQuantEnable, + const INT nChannels); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/spreading.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/spreading.cpp new file mode 100644 index 0000000000000..0fb43bb7ef30a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/spreading.cpp @@ -0,0 +1,125 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Spreading of energy + +*******************************************************************************/ + +#include "spreading.h" + +void FDKaacEnc_SpreadingMax(const INT pbCnt, + const FIXP_DBL *RESTRICT maskLowFactor, + const FIXP_DBL *RESTRICT maskHighFactor, + FIXP_DBL *RESTRICT pbSpreadEnergy) { + int i; + FIXP_DBL delay; + + /* slope to higher frequencies */ + delay = pbSpreadEnergy[0]; + for (i = 1; i < pbCnt; i++) { + delay = fixMax(pbSpreadEnergy[i], fMult(maskHighFactor[i], delay)); + pbSpreadEnergy[i] = delay; + } + + /* slope to lower frequencies */ + delay = pbSpreadEnergy[pbCnt - 1]; + for (i = pbCnt - 2; i >= 0; i--) { + delay = fixMax(pbSpreadEnergy[i], fMult(maskLowFactor[i], delay)); + pbSpreadEnergy[i] = delay; + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/spreading.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/spreading.h new file mode 100644 index 0000000000000..e69303163b102 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/spreading.h @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Spreading of energy and weighted tonality + +*******************************************************************************/ + +#ifndef SPREADING_H +#define SPREADING_H + +#include "common_fix.h" + +void FDKaacEnc_SpreadingMax(const INT pbCnt, + const FIXP_DBL *RESTRICT maskLowFactor, + const FIXP_DBL *RESTRICT maskHighFactor, + FIXP_DBL *RESTRICT pbSpreadEnergy); + +#endif /* #ifndef SPREADING_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/tns_func.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/tns_func.h new file mode 100644 index 0000000000000..6099bc733b5b5 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/tns_func.h @@ -0,0 +1,129 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): Alex Goeschel + + Description: Temporal noise shaping + +*******************************************************************************/ + +#ifndef TNS_FUNC_H +#define TNS_FUNC_H + +#include "common_fix.h" + +#include "psy_configuration.h" + +AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration( + INT bitrate, INT samplerate, INT channels, INT blocktype, INT granuleLength, + INT isLowDelay, INT ldSbrPresent, TNS_CONFIG *tnsConfig, + PSY_CONFIGURATION *psyConfig, INT active, INT useTnsPeak); + +INT FDKaacEnc_TnsDetect(TNS_DATA *tnsData, const TNS_CONFIG *tC, + TNS_INFO *tnsInfo, INT sfbCnt, const FIXP_DBL *spectrum, + INT subBlockNumber, INT blockType); + +void FDKaacEnc_TnsSync(TNS_DATA *tnsDataDest, const TNS_DATA *tnsDataSrc, + TNS_INFO *tnsInfoDest, TNS_INFO *tnsInfoSrc, + const INT blockTypeDest, const INT blockTypeSrc, + const TNS_CONFIG *tC); + +INT FDKaacEnc_TnsEncode(TNS_INFO *tnsInfo, TNS_DATA *tnsData, + const INT numOfSfb, const TNS_CONFIG *tC, + const INT lowPassLine, FIXP_DBL *spectrum, + const INT subBlockNumber, const INT blockType); + +#endif /* TNS_FUNC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/tonality.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/tonality.cpp new file mode 100644 index 0000000000000..334e0f1c10bca --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/tonality.cpp @@ -0,0 +1,219 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Convert chaos measure to the tonality index + +*******************************************************************************/ + +#include "tonality.h" + +#include "chaosmeasure.h" + +#if defined(__arm__) +#endif + +static const FIXP_DBL normlog = + (FIXP_DBL)0xd977d949; /*FL2FXCONST_DBL(-0.4342944819f * + FDKlog(2.0)/FDKlog(2.7182818)); */ + +static void FDKaacEnc_CalcSfbTonality(FIXP_DBL *RESTRICT spectrum, + INT *RESTRICT sfbMaxScaleSpec, + FIXP_DBL *RESTRICT chaosMeasure, + FIXP_SGL *RESTRICT sfbTonality, + INT sfbCnt, const INT *RESTRICT sfbOffset, + FIXP_DBL *RESTRICT sfbEnergyLD64); + +void FDKaacEnc_CalculateFullTonality(FIXP_DBL *RESTRICT spectrum, + INT *RESTRICT sfbMaxScaleSpec, + FIXP_DBL *RESTRICT sfbEnergyLD64, + FIXP_SGL *RESTRICT sfbTonality, INT sfbCnt, + const INT *sfbOffset, INT usePns) { + INT j; + INT numberOfLines = sfbOffset[sfbCnt]; + + if (usePns) { + C_ALLOC_SCRATCH_START(chaosMeasurePerLine, FIXP_DBL, (1024)) + + /* calculate chaos measure */ + FDKaacEnc_CalculateChaosMeasure(spectrum, numberOfLines, + chaosMeasurePerLine); + + /* smooth ChaosMeasure */ + FIXP_DBL left = chaosMeasurePerLine[0]; + FIXP_DBL right; + for (j = 1; j < (numberOfLines - 1); j += 2) { + right = chaosMeasurePerLine[j]; + right = right - (right >> 2); + left = right + (left >> 2); + chaosMeasurePerLine[j] = left; /* 0.25 left + 0.75 right */ + + right = chaosMeasurePerLine[j + 1]; + right = right - (right >> 2); + left = right + (left >> 2); + chaosMeasurePerLine[j + 1] = left; + } + if (j == (numberOfLines - 1)) { + right = chaosMeasurePerLine[j]; + right = right - (right >> 2); + left = right + (left >> 2); + chaosMeasurePerLine[j] = left; + } + + FDKaacEnc_CalcSfbTonality(spectrum, sfbMaxScaleSpec, chaosMeasurePerLine, + sfbTonality, sfbCnt, sfbOffset, sfbEnergyLD64); + + C_ALLOC_SCRATCH_END(chaosMeasurePerLine, FIXP_DBL, (1024)) + } +} + +/***************************************************************************** + + functionname: CalculateTonalityIndex + description: computes tonality values out of unpredictability values + limits range and computes log() + returns: + input: ptr to energies, ptr to chaos measure values, + number of sfb + output: sfb wise tonality values + +*****************************************************************************/ +static void FDKaacEnc_CalcSfbTonality(FIXP_DBL *RESTRICT spectrum, + INT *RESTRICT sfbMaxScaleSpec, + FIXP_DBL *RESTRICT chaosMeasure, + FIXP_SGL *RESTRICT sfbTonality, + INT sfbCnt, const INT *RESTRICT sfbOffset, + FIXP_DBL *RESTRICT sfbEnergyLD64) { + INT i; + + for (i = 0; i < sfbCnt; i++) { + FIXP_DBL chaosMeasureSfbLD64; + INT shiftBits = + fixMax(0, sfbMaxScaleSpec[i] - + 4); /* max sfbWidth = 96 ; 2^7=128 => 7/2 = 4 (spc*spc) */ + + INT j; + FIXP_DBL chaosMeasureSfb = FL2FXCONST_DBL(0.0); + + /* calc chaosMeasurePerSfb */ + for (j = (sfbOffset[i + 1] - sfbOffset[i]) - 1; j >= 0; j--) { + FIXP_DBL tmp = (*spectrum++) << shiftBits; + FIXP_DBL lineNrg = fMultDiv2(tmp, tmp); + chaosMeasureSfb = fMultAddDiv2(chaosMeasureSfb, lineNrg, *chaosMeasure++); + } + + /* calc tonalityPerSfb */ + if (chaosMeasureSfb != FL2FXCONST_DBL(0.0)) { + /* add ld(convtone)/64 and 2/64 bec.fMultDiv2 */ + chaosMeasureSfbLD64 = CalcLdData((chaosMeasureSfb)) - sfbEnergyLD64[i]; + chaosMeasureSfbLD64 += FL2FXCONST_DBL(3.0f / 64) - + ((FIXP_DBL)(shiftBits) << (DFRACT_BITS - 6)); + + if (chaosMeasureSfbLD64 > + FL2FXCONST_DBL(-0.0519051)) /* > ld(0.05)+ld(2) */ + { + if (chaosMeasureSfbLD64 <= FL2FXCONST_DBL(0.0)) + sfbTonality[i] = + FX_DBL2FX_SGL(fMultDiv2(chaosMeasureSfbLD64, normlog) << 7); + else + sfbTonality[i] = FL2FXCONST_SGL(0.0); + } else + sfbTonality[i] = (FIXP_SGL)MAXVAL_SGL; + } else + sfbTonality[i] = (FIXP_SGL)MAXVAL_SGL; + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/tonality.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/tonality.h new file mode 100644 index 0000000000000..c5cf4c533a0c9 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/tonality.h @@ -0,0 +1,115 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: Calculate tonality index + +*******************************************************************************/ + +#ifndef TONALITY_H +#define TONALITY_H + +#include "common_fix.h" +#include "chaosmeasure.h" + +void FDKaacEnc_CalculateFullTonality(FIXP_DBL *RESTRICT spectrum, + INT *RESTRICT sfbMaxScaleSpec, + FIXP_DBL *RESTRICT sfbEnergyLD64, + FIXP_SGL *RESTRICT sfbTonality, INT sfbCnt, + const INT *sfbOffset, INT usePns); + +#endif /* TONALITY_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/transform.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/transform.cpp new file mode 100644 index 0000000000000..08b1c2fbe3212 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/transform.cpp @@ -0,0 +1,294 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): Tobias Chalupka + + Description: FDKaacLdEnc_MdctTransform480: + The module FDKaacLdEnc_MdctTransform will perform the MDCT. + The MDCT supports the sine window and + the zero padded window. The algorithm of the MDCT + can be divided in Windowing, PreModulation, Fft and + PostModulation. + +*******************************************************************************/ + +#include "transform.h" +#include "dct.h" +#include "psy_const.h" +#include "aacEnc_rom.h" +#include "FDK_tools_rom.h" + +#if defined(__arm__) +#endif + +INT FDKaacEnc_Transform_Real(const INT_PCM *pTimeData, + FIXP_DBL *RESTRICT mdctData, const INT blockType, + const INT windowShape, INT *prevWindowShape, + H_MDCT mdctPers, const INT frameLength, + INT *pMdctData_e, INT filterType) { + const INT_PCM *RESTRICT timeData; + + UINT numSpec; + UINT numMdctLines; + UINT offset; + int fr; /* fr: right window slope length */ + SHORT mdctData_e[8]; + + timeData = pTimeData; + + if (blockType == SHORT_WINDOW) { + numSpec = 8; + numMdctLines = frameLength >> 3; + } else { + numSpec = 1; + numMdctLines = frameLength; + } + + offset = (windowShape == LOL_WINDOW) ? ((frameLength * 3) >> 2) : 0; + switch (blockType) { + case LONG_WINDOW: + case STOP_WINDOW: + fr = frameLength - offset; + break; + case START_WINDOW: /* or StopStartSequence */ + case SHORT_WINDOW: + fr = frameLength >> 3; + break; + default: + FDK_ASSERT(0); + return -1; + } + + mdct_block(mdctPers, timeData, frameLength, mdctData, numSpec, numMdctLines, + FDKgetWindowSlope(fr, windowShape), fr, mdctData_e); + + if (blockType == SHORT_WINDOW) { + if (!(mdctData_e[0] == mdctData_e[1] && mdctData_e[1] == mdctData_e[2] && + mdctData_e[2] == mdctData_e[3] && mdctData_e[3] == mdctData_e[4] && + mdctData_e[4] == mdctData_e[5] && mdctData_e[5] == mdctData_e[6] && + mdctData_e[6] == mdctData_e[7])) { + return -1; + } + } + *prevWindowShape = windowShape; + *pMdctData_e = mdctData_e[0]; + + return 0; +} + +INT FDKaacEnc_Transform_Real_Eld(const INT_PCM *pTimeData, + FIXP_DBL *RESTRICT mdctData, + const INT blockType, const INT windowShape, + INT *prevWindowShape, const INT frameLength, + INT *mdctData_e, INT filterType, + FIXP_DBL *RESTRICT overlapAddBuffer) { + const INT_PCM *RESTRICT timeData; + + INT i; + + /* tl: transform length + fl: left window slope length + nl: left window slope offset + fr: right window slope length + nr: right window slope offset */ + const FIXP_WTB *pWindowELD = NULL; + int N = frameLength; + int L = frameLength; + + timeData = pTimeData; + + if (blockType != LONG_WINDOW) { + return -1; + } + + /* + * MDCT scale: + * + 1: fMultDiv2() in windowing. + * + 1: Because of factor 1/2 in Princen-Bradley compliant windowed TDAC. + */ + *mdctData_e = 1 + 1; + + switch (frameLength) { + case 512: + pWindowELD = ELDAnalysis512; + break; + case 480: + pWindowELD = ELDAnalysis480; + break; + case 256: + pWindowELD = ELDAnalysis256; + *mdctData_e += 1; + break; + case 240: + pWindowELD = ELDAnalysis240; + *mdctData_e += 1; + break; + case 128: + pWindowELD = ELDAnalysis128; + *mdctData_e += 2; + break; + case 120: + pWindowELD = ELDAnalysis120; + *mdctData_e += 2; + break; + default: + FDK_ASSERT(0); + return -1; + } + + for (i = 0; i < N / 4; i++) { + FIXP_DBL z0, outval; + + z0 = (fMult((FIXP_PCM)timeData[L + N * 3 / 4 - 1 - i], + pWindowELD[N / 2 - 1 - i]) + << (WTS0 - 1)) + + (fMult((FIXP_PCM)timeData[L + N * 3 / 4 + i], pWindowELD[N / 2 + i]) + << (WTS0 - 1)); + + outval = (fMultDiv2((FIXP_PCM)timeData[L + N * 3 / 4 - 1 - i], + pWindowELD[N + N / 2 - 1 - i]) >> + (-WTS1)); + outval += (fMultDiv2((FIXP_PCM)timeData[L + N * 3 / 4 + i], + pWindowELD[N + N / 2 + i]) >> + (-WTS1)); + outval += (fMultDiv2(overlapAddBuffer[N / 2 + i], pWindowELD[2 * N + i]) >> + (-WTS2 - 1)); + + overlapAddBuffer[N / 2 + i] = overlapAddBuffer[i]; + + overlapAddBuffer[i] = z0; + mdctData[i] = overlapAddBuffer[N / 2 + i] + + (fMultDiv2(overlapAddBuffer[N + N / 2 - 1 - i], + pWindowELD[2 * N + N / 2 + i]) >> + (-WTS2 - 1)); + + mdctData[N - 1 - i] = outval; + overlapAddBuffer[N + N / 2 - 1 - i] = outval; + } + + for (i = N / 4; i < N / 2; i++) { + FIXP_DBL z0, outval; + + z0 = fMult((FIXP_PCM)timeData[L + N * 3 / 4 - 1 - i], + pWindowELD[N / 2 - 1 - i]) + << (WTS0 - 1); + + outval = (fMultDiv2((FIXP_PCM)timeData[L + N * 3 / 4 - 1 - i], + pWindowELD[N + N / 2 - 1 - i]) >> + (-WTS1)); + outval += (fMultDiv2(overlapAddBuffer[N / 2 + i], pWindowELD[2 * N + i]) >> + (-WTS2 - 1)); + + overlapAddBuffer[N / 2 + i] = + overlapAddBuffer[i] + + (fMult((FIXP_PCM)timeData[L - N / 4 + i], pWindowELD[N / 2 + i]) + << (WTS0 - 1)); + + overlapAddBuffer[i] = z0; + mdctData[i] = overlapAddBuffer[N / 2 + i] + + (fMultDiv2(overlapAddBuffer[N + N / 2 - 1 - i], + pWindowELD[2 * N + N / 2 + i]) >> + (-WTS2 - 1)); + + mdctData[N - 1 - i] = outval; + overlapAddBuffer[N + N / 2 - 1 - i] = outval; + } + dct_IV(mdctData, frameLength, mdctData_e); + + *prevWindowShape = windowShape; + + return 0; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/transform.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/transform.h new file mode 100644 index 0000000000000..8f5ff46105660 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libAACenc/src/transform.h @@ -0,0 +1,163 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: MDCT Transform + +*******************************************************************************/ + +#ifndef TRANSFORM_H +#define TRANSFORM_H + +#include "mdct.h" +#include "common_fix.h" + +#define WTS0 1 +#define WTS1 0 +#define WTS2 -2 + +/** + * \brief: Performe MDCT transform of time domain data. + * \param timeData pointer to time domain input signal. + * \param mdctData pointer to store frequency domain output data. + * \param blockType index indicating the type of block. Either + * LONG_WINDOW, START_WINDOW, SHORT_WINDOW or STOP_WINDOW. + * \param windowShape index indicating the window slope type to be used. + * Values allowed are either SINE_WINDOW or KBD_WINDOW. + * \param previndowShape index indicating the window slope type used + * in the last frame. + * Values allowed are either SINE_WINDOW or KBD_WINDOW. + * \param frameLength length of the block. Either 1024 or 960. + * \param mdctData_e pointer to an INT where the exponent of the frequency + * domain output data is stored into. + * \param filterType xxx + * \return 0 in case of success, non-zero in case of error (inconsistent + * parameters). + */ +INT FDKaacEnc_Transform_Real(const INT_PCM* pTimeData, + FIXP_DBL* RESTRICT mdctData, const INT blockType, + const INT windowShape, INT* prevWindowShape, + H_MDCT mdctPers, const INT frameLength, + INT* pMdctData_e, INT filterType); + +/** + * \brief: Performe ELD filterbnank transform of time domain data. + * \param timeData pointer to time domain input signal. + * \param mdctData pointer to store frequency domain output data. + * \param blockType index indicating the type of block. Either + * LONG_WINDOW, START_WINDOW, SHORT_WINDOW or STOP_WINDOW. + * \param windowShape index indicating the window slope type to be used. + * Values allowed are either SINE_WINDOW or KBD_WINDOW. + * \param previndowShape index indicating the window slope type used + * in the last frame. + * Values allowed are either SINE_WINDOW or KBD_WINDOW. + * \param frameLength length of the block. Either 1024 or 960. + * \param mdctData_e pointer to an INT where the exponent of the frequency + * domain output data is stored into. + * \param filterType xxx + * \param overlapAddBuffer overlap add buffer for overlap of ELD filterbank + * \return 0 in case of success, non-zero in case of error (inconsistent + * parameters). + */ +INT FDKaacEnc_Transform_Real_Eld(const INT_PCM* pTimeData, + FIXP_DBL* RESTRICT mdctData, + const INT blockType, const INT windowShape, + INT* prevWindowShape, const INT frameLength, + INT* mdctData_e, INT filterType, + FIXP_DBL* RESTRICT overlapAddBuffer); + +#endif /* #!defined (TRANSFORM_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libArithCoding/include/ac_arith_coder.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libArithCoding/include/ac_arith_coder.h new file mode 100644 index 0000000000000..130c188d7ebf4 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libArithCoding/include/ac_arith_coder.h @@ -0,0 +1,142 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************** Arithmetic coder library *************************** + + Author(s): Oliver Weiss + + Description: Interface for Spectral Noiseless Coding Scheme based on an + Arithmetic Coder in Conjunction with an Adaptive Context + +*******************************************************************************/ + +#ifndef AC_ARITH_CODER_H +#define AC_ARITH_CODER_H + +#include "common_fix.h" +#include "FDK_bitstream.h" + +#include "FDK_audio.h" + +typedef enum { ARITH_CODER_OK = 0, ARITH_CODER_ERROR = 5 } ARITH_CODING_ERROR; + +typedef struct { + SHORT m_numberLinesPrev; + UCHAR c_prev[(1024 / 2) + 4]; /* 2-tuple context of previous frame, 4 bit */ +} CArcoData; + +/* prototypes */ + +CArcoData *CArco_Create(void); + +void CArco_Destroy(CArcoData *pArcoData); + +/** + * \brief decode a spectral data element by using an adaptive context dependent + * arithmetic coding scheme + * \param hBs bit stream handle + * \param spectrum pointer to quantized data output. + * \param lg number of quantized spectral coefficients (output by the arithmetic + * decoder). + * \param lg_max max number of quantized spectral coefficients. + * \param arith_reset_flag flag which indicates if the spectral noiseless + * context must be reset + * \return void + */ +ARITH_CODING_ERROR CArco_DecodeArithData(CArcoData *pArcoData, + HANDLE_FDK_BITSTREAM hBs, + FIXP_DBL *RESTRICT spectrum, int lg, + int lg_max, int arith_reset_flag); + +#endif /* AC_ARITH_CODER_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libArithCoding/src/ac_arith_coder.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libArithCoding/src/ac_arith_coder.cpp new file mode 100644 index 0000000000000..a433b08d8b197 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libArithCoding/src/ac_arith_coder.cpp @@ -0,0 +1,785 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************** Arithmetic coder library *************************** + + Author(s): Youliy Ninov, Oliver Weiss + + Description: Definition of Spectral Noiseless Coding Scheme based on an + Arithmetic Coder in Conjunction with an Adaptive Context + +*******************************************************************************/ + +#include "ac_arith_coder.h" + +#define cbitsnew 16 +#define stat_bitsnew 14 +#define ari_q4new (((long)1 << cbitsnew) - 1) /* 0xFFFF */ +#define ari_q1new (ari_q4new / 4 + 1) /* 0x4000 */ +#define ari_q2new (2 * ari_q1new) /* 0x8000 */ +#define ari_q3new (3 * ari_q1new) /* 0xC000 */ + +#define VAL_ESC 16 + +/* Arithmetic coder library info */ +#define AC_LIB_VL0 2 +#define AC_LIB_VL1 0 +#define AC_LIB_VL2 0 +#define AC_LIB_TITLE "Arithmetic Coder Lib" +#ifdef __ANDROID__ +#define AC_LIB_BUILD_DATE "" +#define AC_LIB_BUILD_TIME "" +#else +#define AC_LIB_BUILD_DATE __DATE__ +#define AC_LIB_BUILD_TIME __TIME__ +#endif + +const SHORT ari_lsb2[3][4] = { + {12571, 10569, 3696, 0}, {12661, 5700, 3751, 0}, {10827, 6884, 2929, 0}}; + +H_ALLOC_MEM(ArcoData, CArcoData) +/*! The structure ArcoData contains 2-tuple context of previous frame.
+ Dimension: 1 */ +C_ALLOC_MEM(ArcoData, CArcoData, 1) + +/* + This define triggers the use of the pre-known return values of function + get_pk_v2() for the cases, where parameter s is in range + 0x00000000..0x0000000F. Note: These 16 bytes have been moved into the first 4 + entries of ari_merged_hash_ps that are no more referenced. +*/ + +static const ULONG ari_merged_hash_ps[742] = { + 0x00001044UL, 0x00003D0AUL, 0x00005350UL, 0x000074D6UL, 0x0000A49FUL, + 0x0000F96EUL, 0x00111000UL, 0x01111E83UL, 0x01113146UL, 0x01114036UL, + 0x01116863UL, 0x011194E9UL, 0x0111F7EEUL, 0x0112269BUL, 0x01124775UL, + 0x01126DA1UL, 0x0112D912UL, 0x01131AF0UL, 0x011336DDUL, 0x01135CF5UL, + 0x01139DF8UL, 0x01141A5BUL, 0x01144773UL, 0x01146CF5UL, 0x0114FDE9UL, + 0x01166CF5UL, 0x0116FDE4UL, 0x01174CF3UL, 0x011FFDCFUL, 0x01211CC2UL, + 0x01213B2DUL, 0x01214036UL, 0x01216863UL, 0x012194D2UL, 0x0122197FUL, + 0x01223AADUL, 0x01224036UL, 0x01226878UL, 0x0122A929UL, 0x0122F4ABUL, + 0x01232B2DUL, 0x012347B6UL, 0x01237DF8UL, 0x0123B929UL, 0x012417DDUL, + 0x01245D76UL, 0x01249DF8UL, 0x0124F912UL, 0x01255D75UL, 0x0125FDE9UL, + 0x01265D75UL, 0x012B8DF7UL, 0x01311E2AUL, 0x01313B5EUL, 0x0131687BUL, + 0x01321A6DUL, 0x013237BCUL, 0x01326863UL, 0x0132F4EEUL, 0x01332B5EUL, + 0x01335DA1UL, 0x01338E24UL, 0x01341A5EUL, 0x01343DB6UL, 0x01348DF8UL, + 0x01351935UL, 0x01355DB7UL, 0x0135FE12UL, 0x01376DF7UL, 0x013FFE29UL, + 0x01400024UL, 0x01423821UL, 0x014318F6UL, 0x01433821UL, 0x0143F8E5UL, + 0x01443DA1UL, 0x01486E38UL, 0x014FF929UL, 0x01543EE3UL, 0x015FF912UL, + 0x016F298CUL, 0x018A5A69UL, 0x021007F1UL, 0x02112C2CUL, 0x02114B48UL, + 0x02117353UL, 0x0211F4AEUL, 0x02122FEAUL, 0x02124B48UL, 0x02127850UL, + 0x0212F72EUL, 0x02133A9EUL, 0x02134036UL, 0x02138864UL, 0x021414ADUL, + 0x0214379EUL, 0x02145DB6UL, 0x0214FE1FUL, 0x02166DB7UL, 0x02200DC4UL, + 0x02212FEAUL, 0x022147A0UL, 0x02218369UL, 0x0221F7EEUL, 0x02222AADUL, + 0x02224788UL, 0x02226863UL, 0x02229929UL, 0x0222F4ABUL, 0x02232A9EUL, + 0x02234F08UL, 0x02237864UL, 0x0223A929UL, 0x022417DEUL, 0x02244F36UL, + 0x02248863UL, 0x02251A74UL, 0x02256DA1UL, 0x0225FE12UL, 0x02263DB6UL, + 0x02276DF7UL, 0x022FFE29UL, 0x0231186DUL, 0x023137BCUL, 0x02314020UL, + 0x02319ED6UL, 0x0232196DUL, 0x023237BCUL, 0x02325809UL, 0x02329429UL, + 0x023317EDUL, 0x02333F08UL, 0x02335809UL, 0x023378E4UL, 0x02341A7CUL, + 0x02344221UL, 0x0234A8D3UL, 0x023514BCUL, 0x02354221UL, 0x0235F8DFUL, + 0x02364861UL, 0x023FFE29UL, 0x02400024UL, 0x0241583BUL, 0x024214C8UL, + 0x02424809UL, 0x02427EE6UL, 0x02431708UL, 0x02434809UL, 0x02436ED0UL, + 0x02441A76UL, 0x02443821UL, 0x024458E3UL, 0x0244F91FUL, 0x02454863UL, + 0x0246190AUL, 0x02464863UL, 0x024FF929UL, 0x02525ED0UL, 0x025314E1UL, + 0x025348FBUL, 0x025419A1UL, 0x025458D0UL, 0x0254F4E5UL, 0x02552861UL, + 0x025FF912UL, 0x02665993UL, 0x027F5A69UL, 0x029F1481UL, 0x02CF28A4UL, + 0x03100AF0UL, 0x031120AAUL, 0x031147A0UL, 0x03118356UL, 0x031217ECUL, + 0x03123B5EUL, 0x03124008UL, 0x03127350UL, 0x031314AAUL, 0x0313201EUL, + 0x03134F08UL, 0x03136863UL, 0x03141A5EUL, 0x03143F3CUL, 0x03200847UL, + 0x03212AADUL, 0x03214F20UL, 0x03218ED6UL, 0x032218ADUL, 0x032237BCUL, + 0x03225809UL, 0x03229416UL, 0x032317EDUL, 0x03234F20UL, 0x03237350UL, + 0x0323FA6BUL, 0x03243F08UL, 0x03246863UL, 0x0324F925UL, 0x03254221UL, + 0x0325F8DFUL, 0x03264821UL, 0x032FFE29UL, 0x03311E47UL, 0x03313F08UL, + 0x0331580DUL, 0x033214DEUL, 0x03323F08UL, 0x03324020UL, 0x03326350UL, + 0x033294E9UL, 0x033317DEUL, 0x03333F08UL, 0x0333627BUL, 0x0333A9A9UL, + 0x033417FCUL, 0x03343220UL, 0x0334627BUL, 0x0334A9A9UL, 0x0335148AUL, + 0x03353220UL, 0x033588E4UL, 0x03361A4AUL, 0x03363821UL, 0x0336F8D2UL, + 0x03376863UL, 0x03411939UL, 0x0341583BUL, 0x034214C8UL, 0x03424809UL, + 0x03426ED0UL, 0x03431588UL, 0x03434809UL, 0x03436ED0UL, 0x03441A48UL, + 0x0344480DUL, 0x03446ED0UL, 0x03451A4AUL, 0x03453809UL, 0x03455EFBUL, + 0x034614CAUL, 0x03463849UL, 0x034F8924UL, 0x03500A69UL, 0x035252D0UL, + 0x035314E0UL, 0x0353324DUL, 0x03535ED0UL, 0x035414E0UL, 0x0354324DUL, + 0x03545ED0UL, 0x0354F4E8UL, 0x0355384DUL, 0x03555ED0UL, 0x0355F4DFUL, + 0x03564350UL, 0x035969A6UL, 0x035FFA52UL, 0x036649A6UL, 0x036FFA52UL, + 0x037F4F66UL, 0x039D7492UL, 0x03BF6892UL, 0x03DF8A1FUL, 0x04100B84UL, + 0x04112107UL, 0x0411520DUL, 0x041214EAUL, 0x04124F20UL, 0x04131EDEUL, + 0x04133F08UL, 0x04135809UL, 0x0413F42BUL, 0x04142F08UL, 0x04200847UL, + 0x042121FCUL, 0x04214209UL, 0x04221407UL, 0x0422203CUL, 0x04224209UL, + 0x04226350UL, 0x04231A7CUL, 0x04234209UL, 0x0423637BUL, 0x04241A7CUL, + 0x04243220UL, 0x0424627BUL, 0x042514C8UL, 0x04254809UL, 0x042FF8E9UL, + 0x04311E47UL, 0x04313220UL, 0x0431527BUL, 0x043214FCUL, 0x04323220UL, + 0x04326250UL, 0x043315BCUL, 0x04333220UL, 0x0433527BUL, 0x04338413UL, + 0x04341488UL, 0x04344809UL, 0x04346ED0UL, 0x04351F48UL, 0x0435527BUL, + 0x0435F9A5UL, 0x04363809UL, 0x04375EFBUL, 0x043FF929UL, 0x04412E79UL, + 0x0441427BUL, 0x044219B9UL, 0x04423809UL, 0x0442537BUL, 0x044314C8UL, + 0x04432020UL, 0x0443527BUL, 0x044414CAUL, 0x04443809UL, 0x0444537BUL, + 0x04448993UL, 0x0445148AUL, 0x04453809UL, 0x04455ED0UL, 0x0445F4E5UL, + 0x0446384DUL, 0x045009A6UL, 0x045272D3UL, 0x045314A0UL, 0x0453324DUL, + 0x04535ED0UL, 0x045415A0UL, 0x0454324DUL, 0x04545ED0UL, 0x04551F60UL, + 0x0455324DUL, 0x04562989UL, 0x04564350UL, 0x045FF4D2UL, 0x04665993UL, + 0x047FFF62UL, 0x048FF725UL, 0x049F44BDUL, 0x04BFB7E5UL, 0x04EF8A25UL, + 0x04FFFB98UL, 0x051131F9UL, 0x051212C7UL, 0x05134209UL, 0x05200247UL, + 0x05211007UL, 0x05213E60UL, 0x052212C7UL, 0x05224209UL, 0x052319BCUL, + 0x05233220UL, 0x0523527BUL, 0x052414C8UL, 0x05243820UL, 0x053112F9UL, + 0x05313E49UL, 0x05321439UL, 0x05323E49UL, 0x0532537BUL, 0x053314C8UL, + 0x0533480DUL, 0x05337413UL, 0x05341488UL, 0x0534527BUL, 0x0534F4EBUL, + 0x05353809UL, 0x05356ED0UL, 0x0535F4E5UL, 0x0536427BUL, 0x054119B9UL, + 0x054212F9UL, 0x05423249UL, 0x05426ED3UL, 0x05431739UL, 0x05433249UL, + 0x05435ED0UL, 0x0543F4EBUL, 0x05443809UL, 0x05445ED0UL, 0x0544F4E8UL, + 0x0545324DUL, 0x054FF992UL, 0x055362D3UL, 0x0553F5ABUL, 0x05544350UL, + 0x055514CAUL, 0x0555427BUL, 0x0555F4E5UL, 0x0556327BUL, 0x055FF4D2UL, + 0x05665993UL, 0x05774F53UL, 0x059FF728UL, 0x05CC37FDUL, 0x05EFBA28UL, + 0x05FFFB98UL, 0x061131F9UL, 0x06121407UL, 0x06133E60UL, 0x061A72E4UL, + 0x06211E47UL, 0x06214E4BUL, 0x062214C7UL, 0x06223E60UL, 0x062312F9UL, + 0x06233E60UL, 0x063112F9UL, 0x06313E4CUL, 0x063219B9UL, 0x06323E49UL, + 0x06331439UL, 0x06333809UL, 0x06336EE6UL, 0x0633F5ABUL, 0x06343809UL, + 0x0634F42BUL, 0x0635427BUL, 0x063FF992UL, 0x064342FBUL, 0x0643F4EBUL, + 0x0644427BUL, 0x064524C9UL, 0x06655993UL, 0x0666170AUL, 0x066652E6UL, + 0x067A6F56UL, 0x0698473DUL, 0x06CF67D2UL, 0x06EF3A26UL, 0x06FFFAD8UL, + 0x071131CCUL, 0x07211307UL, 0x07222E79UL, 0x072292DCUL, 0x07234E4BUL, + 0x073112F9UL, 0x07322339UL, 0x073632CBUL, 0x073FF992UL, 0x074432CBUL, + 0x075549A6UL, 0x0776FF68UL, 0x07774350UL, 0x0788473DUL, 0x07CF4516UL, + 0x07EF3A26UL, 0x07FFFAD8UL, 0x08222E79UL, 0x083112F9UL, 0x0834330BUL, + 0x0845338BUL, 0x08756F5CUL, 0x0887F725UL, 0x08884366UL, 0x08AF649CUL, + 0x08F00898UL, 0x08FFFAD8UL, 0x091111C7UL, 0x0932330BUL, 0x0945338BUL, + 0x09774F7DUL, 0x0998C725UL, 0x09996416UL, 0x09EF87E5UL, 0x09FFFAD8UL, + 0x0A34330BUL, 0x0A45338BUL, 0x0A77467DUL, 0x0AA9F52BUL, 0x0AAA6416UL, + 0x0ABD67DFUL, 0x0AFFFA18UL, 0x0B33330BUL, 0x0B4443A6UL, 0x0B76467DUL, + 0x0BB9751FUL, 0x0BBB59BDUL, 0x0BEF5892UL, 0x0BFFFAD8UL, 0x0C221339UL, + 0x0C53338EUL, 0x0C76367DUL, 0x0CCAF52EUL, 0x0CCC6996UL, 0x0CFFFA18UL, + 0x0D44438EUL, 0x0D64264EUL, 0x0DDCF52EUL, 0x0DDD5996UL, 0x0DFFFA18UL, + 0x0E43338EUL, 0x0E68465CUL, 0x0EEE651CUL, 0x0EFFFA18UL, 0x0F33238EUL, + 0x0F553659UL, 0x0F8F451CUL, 0x0FAFF8AEUL, 0x0FF00A2EUL, 0x0FFF1ACCUL, + 0x0FFF33BDUL, 0x0FFF7522UL, 0x0FFFFAD8UL, 0x10002C72UL, 0x1111103EUL, + 0x11121E83UL, 0x11131E9AUL, 0x1121115AUL, 0x11221170UL, 0x112316F0UL, + 0x1124175DUL, 0x11311CC2UL, 0x11321182UL, 0x11331D42UL, 0x11411D48UL, + 0x11421836UL, 0x11431876UL, 0x11441DF5UL, 0x1152287BUL, 0x12111903UL, + 0x1212115AUL, 0x121316F0UL, 0x12211B30UL, 0x12221B30UL, 0x12231B02UL, + 0x12311184UL, 0x12321D04UL, 0x12331784UL, 0x12411D39UL, 0x12412020UL, + 0x12422220UL, 0x12511D89UL, 0x1252227BUL, 0x1258184AUL, 0x12832992UL, + 0x1311171AUL, 0x13121B30UL, 0x1312202CUL, 0x131320AAUL, 0x132120AAUL, + 0x132220ADUL, 0x13232FEDUL, 0x13312107UL, 0x13322134UL, 0x13332134UL, + 0x13411D39UL, 0x13431E74UL, 0x13441834UL, 0x134812B4UL, 0x1352230BUL, + 0x13611E4BUL, 0x136522E4UL, 0x141113C2UL, 0x141211C4UL, 0x143121F9UL, + 0x143221F9UL, 0x143321CAUL, 0x14351D34UL, 0x14431E47UL, 0x14441E74UL, + 0x144612B4UL, 0x1452230EUL, 0x14551E74UL, 0x1471130EUL, 0x151113C2UL, + 0x152121F9UL, 0x153121F9UL, 0x153221F9UL, 0x15331007UL, 0x15522E4EUL, + 0x15551E74UL, 0x1571130EUL, 0x161113C7UL, 0x162121F9UL, 0x163121F9UL, + 0x16611E79UL, 0x16661334UL, 0x171113C7UL, 0x172121F9UL, 0x17451E47UL, + 0x1771130CUL, 0x181113C7UL, 0x18211E47UL, 0x18511E4CUL, 0x1882130CUL, + 0x191113C7UL, 0x19331E79UL, 0x1A111307UL, 0x1A311E79UL, 0x1F52230EUL, + 0x200003C1UL, 0x20001027UL, 0x20004467UL, 0x200079E7UL, 0x2000E5EFUL, + 0x21100BC0UL, 0x211129C0UL, 0x21114011UL, 0x211189E7UL, 0x2111F5EFUL, + 0x21124011UL, 0x21127455UL, 0x211325C0UL, 0x21134011UL, 0x21137455UL, + 0x211425C0UL, 0x21212440UL, 0x21213001UL, 0x2121F9EFUL, 0x21222540UL, + 0x21226455UL, 0x2122F5EFUL, 0x21233051UL, 0x2123F56FUL, 0x21244451UL, + 0x21312551UL, 0x21323451UL, 0x21332551UL, 0x21844555UL, 0x221125C0UL, + 0x22113011UL, 0x2211F9EFUL, 0x22123051UL, 0x2212F9EFUL, 0x221329D1UL, + 0x22212541UL, 0x22213011UL, 0x2221F9EFUL, 0x22223451UL, 0x2222F9EFUL, + 0x22232551UL, 0x2223F56FUL, 0x22312551UL, 0x223229D1UL, 0x2232F56FUL, + 0x22332551UL, 0x2233F56FUL, 0x22875555UL, 0x22DAB5D7UL, 0x23112BD1UL, + 0x23115467UL, 0x231225D1UL, 0x232129D1UL, 0x232229D1UL, 0x2322F9EFUL, + 0x23233451UL, 0x2323F9EFUL, 0x23312551UL, 0x233229D1UL, 0x2332F9EFUL, + 0x2333F56FUL, 0x237FF557UL, 0x238569D5UL, 0x23D955D7UL, 0x24100BE7UL, + 0x248789E7UL, 0x24E315D7UL, 0x24FFFBEFUL, 0x259869E7UL, 0x25DFF5EFUL, + 0x25FFFBEFUL, 0x268789E7UL, 0x26DFA5D7UL, 0x26FFFBEFUL, 0x279649E7UL, + 0x27E425D7UL, 0x27FFFBEFUL, 0x288879E7UL, 0x28EFF5EFUL, 0x28FFFBEFUL, + 0x298439E7UL, 0x29F115EFUL, 0x29FFFBEFUL, 0x2A7659E7UL, 0x2AEF75D7UL, + 0x2AFFFBEFUL, 0x2B7C89E7UL, 0x2BEF95D7UL, 0x2BFFFBEFUL, 0x2C6659E7UL, + 0x2CD555D7UL, 0x2CFFFBEFUL, 0x2D6329E7UL, 0x2DDD55E7UL, 0x2DFFFBEBUL, + 0x2E8479D7UL, 0x2EEE35E7UL, 0x2EFFFBEFUL, 0x2F5459E7UL, 0x2FCF85D7UL, + 0x2FFEFBEBUL, 0x2FFFA5EFUL, 0x2FFFEBEFUL, 0x30001AE7UL, 0x30002001UL, + 0x311129C0UL, 0x31221015UL, 0x31232000UL, 0x31332451UL, 0x32112540UL, + 0x32131027UL, 0x32212440UL, 0x33452455UL, 0x4000F9D7UL, 0x4122F9D7UL, + 0x43F65555UL, 0x43FFF5D7UL, 0x44F55567UL, 0x44FFF5D7UL, 0x45F00557UL, + 0x45FFF5D7UL, 0x46F659D7UL, 0x471005E7UL, 0x47F449E7UL, 0x481005E7UL, + 0x48EFA9D5UL, 0x48FFF5EFUL, 0x49F449E7UL, 0x49FFF5EFUL, 0x4AEA79E7UL, + 0x4AFFF5EFUL, 0x4BE9C9D5UL, 0x4BFFF5EFUL, 0x4CE549E7UL, 0x4CFFF5EFUL, + 0x4DE359E7UL, 0x4DFFF5D7UL, 0x4EE469E7UL, 0x4EFFF5D7UL, 0x4FEF39E7UL, + 0x4FFFF5EFUL, 0x6000F9E7UL, 0x69FFF557UL, 0x6FFFF9D7UL, 0x811009D7UL, + 0x8EFFF555UL, 0xFFFFF9E7UL}; + +static const SHORT ari_pk[64][17] = { + {708, 706, 579, 569, 568, 567, 479, 469, 297, 138, 97, 91, 72, 52, 38, 34, + 0}, + {7619, 6917, 6519, 6412, 5514, 5003, 4683, 4563, 3907, 3297, 3125, 3060, + 2904, 2718, 2631, 2590, 0}, + {7263, 4888, 4810, 4803, 1889, 415, 335, 327, 195, 72, 52, 49, 36, 20, 15, + 14, 0}, + {3626, 2197, 2188, 2187, 582, 57, 47, 46, 30, 12, 9, 8, 6, 4, 3, 2, 0}, + {7806, 5541, 5451, 5441, 2720, 834, 691, 674, 487, 243, 179, 167, 139, 98, + 77, 70, 0}, + {6684, 4101, 4058, 4055, 1748, 426, 368, 364, 322, 257, 235, 232, 228, 222, + 217, 215, 0}, + {9162, 5964, 5831, 5819, 3269, 866, 658, 638, 535, 348, 258, 244, 234, 214, + 195, 186, 0}, + {10638, 8491, 8365, 8351, 4418, 2067, 1859, 1834, 1190, 601, 495, 478, 356, + 217, 174, 164, 0}, + {13389, 10514, 10032, 9961, 7166, 3488, 2655, 2524, 2015, 1140, 760, 672, + 585, 426, 325, 283, 0}, + {14861, 12788, 12115, 11952, 9987, 6657, 5323, 4984, 4324, 3001, 2205, 1943, + 1764, 1394, 1115, 978, 0}, + {12876, 10004, 9661, 9610, 7107, 3435, 2711, 2595, 2257, 1508, 1059, 952, + 893, 753, 609, 538, 0}, + {15125, 13591, 13049, 12874, 11192, 8543, 7406, 7023, 6291, 4922, 4104, + 3769, 3465, 2890, 2486, 2275, 0}, + {14574, 13106, 12731, 12638, 10453, 7947, 7233, 7037, 6031, 4618, 4081, + 3906, 3465, 2802, 2476, 2349, 0}, + {15070, 13179, 12517, 12351, 10742, 7657, 6200, 5825, 5264, 3998, 3014, + 2662, 2510, 2153, 1799, 1564, 0}, + {15542, 14466, 14007, 13844, 12489, 10409, 9481, 9132, 8305, 6940, 6193, + 5867, 5458, 4743, 4291, 4047, 0}, + {15165, 14384, 14084, 13934, 12911, 11485, 10844, 10513, 10002, 8993, 8380, + 8051, 7711, 7036, 6514, 6233, 0}, + {15642, 14279, 13625, 13393, 12348, 9971, 8405, 7858, 7335, 6119, 4918, + 4376, 4185, 3719, 3231, 2860, 0}, + {13408, 13407, 11471, 11218, 11217, 11216, 9473, 9216, 6480, 3689, 2857, + 2690, 2256, 1732, 1405, 1302, 0}, + {16098, 15584, 15191, 14931, 14514, 13578, 12703, 12103, 11830, 11172, + 10475, 9867, 9695, 9281, 8825, 8389, 0}, + {15844, 14873, 14277, 13996, 13230, 11535, 10205, 9543, 9107, 8086, 7085, + 6419, 6214, 5713, 5195, 4731, 0}, + {16131, 15720, 15443, 15276, 14848, 13971, 13314, 12910, 12591, 11874, + 11225, 10788, 10573, 10077, 9585, 9209, 0}, + {16331, 16330, 12283, 11435, 11434, 11433, 8725, 8049, 6065, 4138, 3187, + 2842, 2529, 2171, 1907, 1745, 0}, + {16011, 15292, 14782, 14528, 14008, 12767, 11556, 10921, 10591, 9759, 8813, + 8043, 7855, 7383, 6863, 6282, 0}, + {16380, 16379, 15159, 14610, 14609, 14608, 12859, 12111, 11046, 9536, 8348, + 7713, 7216, 6533, 5964, 5546, 0}, + {16367, 16333, 16294, 16253, 16222, 16143, 16048, 15947, 15915, 15832, + 15731, 15619, 15589, 15512, 15416, 15310, 0}, + {15967, 15319, 14937, 14753, 14010, 12638, 11787, 11360, 10805, 9706, 8934, + 8515, 8166, 7456, 6911, 6575, 0}, + {4906, 3005, 2985, 2984, 875, 102, 83, 81, 47, 17, 12, 11, 8, 5, 4, 3, 0}, + {7217, 4346, 4269, 4264, 1924, 428, 340, 332, 280, 203, 179, 175, 171, 164, + 159, 157, 0}, + {16010, 15415, 15032, 14805, 14228, 13043, 12168, 11634, 11265, 10419, 9645, + 9110, 8892, 8378, 7850, 7437, 0}, + {8573, 5218, 5046, 5032, 2787, 771, 555, 533, 443, 286, 218, 205, 197, 181, + 168, 162, 0}, + {11474, 8095, 7822, 7796, 4632, 1443, 1046, 1004, 748, 351, 218, 194, 167, + 121, 93, 83, 0}, + {16152, 15764, 15463, 15264, 14925, 14189, 13536, 13070, 12846, 12314, + 11763, 11277, 11131, 10777, 10383, 10011, 0}, + {14187, 11654, 11043, 10919, 8498, 4885, 3778, 3552, 2947, 1835, 1283, 1134, + 998, 749, 585, 514, 0}, + {14162, 11527, 10759, 10557, 8601, 5417, 4105, 3753, 3286, 2353, 1708, 1473, + 1370, 1148, 959, 840, 0}, + {16205, 15902, 15669, 15498, 15213, 14601, 14068, 13674, 13463, 12970, + 12471, 12061, 11916, 11564, 11183, 10841, 0}, + {15043, 12972, 12092, 11792, 10265, 7446, 5934, 5379, 4883, 3825, 3036, + 2647, 2507, 2185, 1901, 1699, 0}, + {15320, 13694, 12782, 12352, 11191, 8936, 7433, 6671, 6255, 5366, 4622, + 4158, 4020, 3712, 3420, 3198, 0}, + {16255, 16020, 15768, 15600, 15416, 14963, 14440, 14006, 13875, 13534, + 13137, 12697, 12602, 12364, 12084, 11781, 0}, + {15627, 14503, 13906, 13622, 12557, 10527, 9269, 8661, 8117, 6933, 5994, + 5474, 5222, 4664, 4166, 3841, 0}, + {16366, 16365, 14547, 14160, 14159, 14158, 11969, 11473, 8735, 6147, 4911, + 4530, 3865, 3180, 2710, 2473, 0}, + {16257, 16038, 15871, 15754, 15536, 15071, 14673, 14390, 14230, 13842, + 13452, 13136, 13021, 12745, 12434, 12154, 0}, + {15855, 14971, 14338, 13939, 13239, 11782, 10585, 9805, 9444, 8623, 7846, + 7254, 7079, 6673, 6262, 5923, 0}, + {9492, 6318, 6197, 6189, 3004, 652, 489, 477, 333, 143, 96, 90, 78, 60, 50, + 47, 0}, + {16313, 16191, 16063, 15968, 15851, 15590, 15303, 15082, 14968, 14704, + 14427, 14177, 14095, 13899, 13674, 13457, 0}, + {8485, 5473, 5389, 5383, 2411, 494, 386, 377, 278, 150, 117, 112, 103, 89, + 81, 78, 0}, + {10497, 7154, 6959, 6943, 3788, 1004, 734, 709, 517, 238, 152, 138, 120, 90, + 72, 66, 0}, + {16317, 16226, 16127, 16040, 15955, 15762, 15547, 15345, 15277, 15111, + 14922, 14723, 14671, 14546, 14396, 14239, 0}, + {16382, 16381, 15858, 15540, 15539, 15538, 14704, 14168, 13768, 13092, + 12452, 11925, 11683, 11268, 10841, 10460, 0}, + {5974, 3798, 3758, 3755, 1275, 205, 166, 162, 95, 35, 26, 24, 18, 11, 8, 7, + 0}, + {3532, 2258, 2246, 2244, 731, 135, 118, 115, 87, 45, 36, 34, 29, 21, 17, 16, + 0}, + {7466, 4882, 4821, 4811, 2476, 886, 788, 771, 688, 531, 469, 457, 437, 400, + 369, 361, 0}, + {9580, 5772, 5291, 5216, 3444, 1496, 1025, 928, 806, 578, 433, 384, 366, + 331, 296, 273, 0}, + {10692, 7730, 7543, 7521, 4679, 1746, 1391, 1346, 1128, 692, 495, 458, 424, + 353, 291, 268, 0}, + {11040, 7132, 6549, 6452, 4377, 1875, 1253, 1130, 958, 631, 431, 370, 346, + 296, 253, 227, 0}, + {12687, 9332, 8701, 8585, 6266, 3093, 2182, 2004, 1683, 1072, 712, 608, 559, + 458, 373, 323, 0}, + {13429, 9853, 8860, 8584, 6806, 4039, 2862, 2478, 2239, 1764, 1409, 1224, + 1178, 1077, 979, 903, 0}, + {14685, 12163, 11061, 10668, 9101, 6345, 4871, 4263, 3908, 3200, 2668, 2368, + 2285, 2106, 1942, 1819, 0}, + {13295, 11302, 10999, 10945, 7947, 5036, 4490, 4385, 3391, 2185, 1836, 1757, + 1424, 998, 833, 785, 0}, + {4992, 2993, 2972, 2970, 1269, 575, 552, 549, 530, 505, 497, 495, 493, 489, + 486, 485, 0}, + {15419, 13862, 13104, 12819, 11429, 8753, 7220, 6651, 6020, 4667, 3663, + 3220, 2995, 2511, 2107, 1871, 0}, + {12468, 9263, 8912, 8873, 5758, 2193, 1625, 1556, 1187, 589, 371, 330, 283, + 200, 149, 131, 0}, + {15870, 15076, 14615, 14369, 13586, 12034, 10990, 10423, 9953, 8908, 8031, + 7488, 7233, 6648, 6101, 5712, 0}, + {1693, 978, 976, 975, 194, 18, 16, 15, 11, 7, 6, 5, 4, 3, 2, 1, 0}, + {7992, 5218, 5147, 5143, 2152, 366, 282, 276, 173, 59, 38, 35, 27, 16, 11, + 10, 0}}; + +typedef struct { + int low; + int high; + int vobf; +} Tastat; + +static inline INT mul_sbc_14bits(INT r, INT c) { + return (((INT)r) * ((INT)c)) >> stat_bitsnew; +} + +static inline INT ari_decode_14bits(HANDLE_FDK_BITSTREAM hBs, Tastat *s, + const SHORT *RESTRICT c_freq, int cfl) { + INT symbol; + INT low, high, range, value; + INT c; + const SHORT *p; + + low = s->low; + high = s->high; + value = s->vobf; + + range = high - low + 1; + c = (((int)(value - low + 1)) << stat_bitsnew) - ((int)1); + p = (const SHORT *)(c_freq - 1); + + if (cfl == (VAL_ESC + 1)) { + /* In 50% of all cases, the first entry is the right one, so we check it + * prior to all others */ + if ((p[1] * range) > c) { + p += 1; + if ((p[8] * range) > c) { + p += 8; + } + if ((p[4] * range) > c) { + p += 4; + } + if ((p[2] * range) > c) { + p += 2; + } + if ((p[1] * range) > c) { + p += 1; + } + } + } else if (cfl == 4) { + if ((p[2] * range) > c) { + p += 2; + } + if ((p[1] * range) > c) { + p += 1; + } + } else if (cfl == 2) { + if ((p[1] * range) > c) { + p += 1; + } + } else if (cfl == 27) { + const SHORT *p_24 = p + 24; + + if ((p[16] * range) > c) { + p += 16; + } + if ((p[8] * range) > c) { + p += 8; + } + if (p != p_24) { + if ((p[4] * range) > c) { + p += 4; + } + } + if ((p[2] * range) > c) { + p += 2; + } + + if (p != &p_24[2]) { + if ((p[1] * range) > c) { + p += 1; + } + } + } + + symbol = (INT)(p - (const SHORT *)(c_freq - 1)); + + if (symbol) { + high = low + mul_sbc_14bits(range, c_freq[symbol - 1]) - 1; + } + + low += mul_sbc_14bits(range, c_freq[symbol]); + + USHORT us_high = (USHORT)high; + USHORT us_low = (USHORT)low; + while (1) { + if (us_high & 0x8000) { + if (!(us_low & 0x8000)) { + if (us_low & 0x4000 && !(us_high & 0x4000)) { + us_low -= 0x4000; + us_high -= 0x4000; + value -= 0x4000; + } else + break; + } + } + us_low = us_low << 1; + us_high = (us_high << 1) | 1; + value = (value << 1) | FDKreadBit(hBs); + } + s->low = (int)us_low; + s->high = (int)us_high; + s->vobf = value & 0xFFFF; + + return symbol; +} + +static inline void copyTableAmrwbArith2(UCHAR tab[], int sizeIn, int sizeOut) { + int i; + int j; + int k = 2; + + tab += 2; + + if (sizeIn < sizeOut) { + tab[sizeOut + 0] = tab[sizeIn + 0]; + tab[sizeOut + 1] = tab[sizeIn + 1]; + if (sizeIn < (sizeOut >> 2)) { + k = 8; + } else if (sizeIn == (sizeOut >> 2)) { + k = 4; + } + + i = sizeOut - 1; + j = sizeIn - 1; + + for (; i >= 0; j--) { + UCHAR tq_data0 = tab[j]; + + for (int l = (k >> 1); l > 0; l--) { + tab[i--] = tq_data0; + tab[i--] = tq_data0; + } + } + } else { + if (sizeOut < (sizeIn >> 2)) { + k = 8; + } else if (sizeOut == (sizeIn >> 2)) { + k = 4; + } + + for (i = 0, j = 0; i < sizeOut; j += k) { + UCHAR tq_data0 = tab[j]; + + tab[i++] = tq_data0; + } + tab[sizeOut + 0] = tab[sizeIn + 0]; + tab[sizeOut + 1] = tab[sizeIn + 1]; + } +} + +static inline ULONG get_pk_v2(ULONG s) { + const ULONG *p = ari_merged_hash_ps; + ULONG s12 = (fMax((UINT)s, (UINT)1) << 12) - 1; + if (s12 > p[485]) { + p += 486; /* 742 - 256 = 486 */ + } else { + if (s12 > p[255]) p += 256; + } + + if (s12 > p[127]) { + p += 128; + } + if (s12 > p[63]) { + p += 64; + } + if (s12 > p[31]) { + p += 32; + } + if (s12 > p[15]) { + p += 16; + } + if (s12 > p[7]) { + p += 8; + } + if (s12 > p[3]) { + p += 4; + } + if (s12 > p[1]) { + p += 2; + } + ULONG j = p[0]; + if (s12 > j) j = p[1]; + if (s != (j >> 12)) j >>= 6; + return (j & 0x3F); +} + +static ARITH_CODING_ERROR decode2(HANDLE_FDK_BITSTREAM bbuf, + UCHAR *RESTRICT c_prev, + FIXP_DBL *RESTRICT pSpectralCoefficient, + INT n, INT nt) { + Tastat as; + int i, l, r; + INT lev, esc_nb, pki; + USHORT state_inc; + UINT s; + ARITH_CODING_ERROR ErrorStatus = ARITH_CODER_OK; + + int c_3 = 0; /* context of current frame 3 time steps ago */ + int c_2 = 0; /* context of current frame 2 time steps ago */ + int c_1 = 0; /* context of current frame 1 time steps ago */ + int c_0 = 1; /* context of current frame to be calculated */ + + /* ari_start_decoding_14bits */ + as.low = 0; + as.high = ari_q4new; + as.vobf = FDKreadBits(bbuf, cbitsnew); + + /* arith_map_context */ + state_inc = c_prev[0] << 12; + + for (i = 0; i < n; i++) { + /* arith_get_context */ + s = state_inc >> 8; + s = s + (c_prev[i + 1] << 8); + s = (s << 4) + c_1; + + state_inc = s; + + if (i > 3) { + /* Cumulative amplitude below 2 */ + if ((c_1 + c_2 + c_3) < 5) { + s += 0x10000; + } + } + + /* MSBs decoding */ + for (lev = esc_nb = 0;;) { + pki = get_pk_v2(s + (esc_nb << (VAL_ESC + 1))); + r = ari_decode_14bits(bbuf, &as, ari_pk[pki], VAL_ESC + 1); + if (r < VAL_ESC) { + break; + } + + lev++; + + if (lev > 23) return ARITH_CODER_ERROR; + + if (esc_nb < 7) { + esc_nb++; + } + } + + /* Stop symbol */ + if (r == 0) { + if (esc_nb > 0) { + break; /* Stop symbol */ + } + c_0 = 1; + } else /* if (r==0) */ + { + INT b = r >> 2; + INT a = r & 0x3; + + /* LSBs decoding */ + for (l = 0; l < lev; l++) { + { + int pidx = (a == 0) ? 1 : ((b == 0) ? 0 : 2); + r = ari_decode_14bits(bbuf, &as, ari_lsb2[pidx], 4); + } + a = (a << 1) | (r & 1); + b = (b << 1) | (r >> 1); + } + + pSpectralCoefficient[2 * i] = (FIXP_DBL)a; + pSpectralCoefficient[2 * i + 1] = (FIXP_DBL)b; + + c_0 = a + b + 1; + if (c_0 > 0xF) { + c_0 = 0xF; + } + + } /* endif (r==0) */ + + /* arith_update_context */ + c_3 = c_2; + c_2 = c_1; + c_1 = c_0; + c_prev[i] = (UCHAR)c_0; + + } /* for (i=0; i> (bits - 1))) { + pSpectralCoefficient[2 * i] = -pSpectralCoefficient[2 * i]; + } + if (pSpectralCoefficient[2 * i + 1] != (FIXP_DBL)0 && !(r & 1)) { + pSpectralCoefficient[2 * i + 1] = -pSpectralCoefficient[2 * i + 1]; + } + } + } + + FDKmemset(&c_prev[i], 1, sizeof(c_prev[0]) * (nt - i)); + + return ErrorStatus; +} + +CArcoData *CArco_Create(void) { return GetArcoData(); } + +void CArco_Destroy(CArcoData *pArcoData) { FreeArcoData(&pArcoData); } + +ARITH_CODING_ERROR CArco_DecodeArithData(CArcoData *pArcoData, + HANDLE_FDK_BITSTREAM hBs, + FIXP_DBL *RESTRICT mdctSpectrum, + int lg, int lg_max, + int arith_reset_flag) { + ARITH_CODING_ERROR ErrorStatus = ARITH_CODER_OK; + + /* Check lg and lg_max consistency. */ + if (lg_max < lg) { + return ARITH_CODER_ERROR; + } + + FDKmemclear(mdctSpectrum, lg_max * sizeof(FIXP_DBL)); + + /* arith_map_context */ + if (arith_reset_flag) { + FDKmemclear(pArcoData->c_prev, + sizeof(pArcoData->c_prev[0]) * ((lg_max / 2) + 4)); + } else { + if (lg_max != pArcoData->m_numberLinesPrev) { + if (pArcoData->m_numberLinesPrev == 0) { + /* Cannot decode without a valid AC context */ + return ARITH_CODER_ERROR; + } + + /* short-to-long or long-to-short block transition */ + /* Current length differs compared to previous - perform up/downmix of + * m_qbuf */ + copyTableAmrwbArith2(pArcoData->c_prev, pArcoData->m_numberLinesPrev >> 1, + lg_max >> 1); + } + } + + pArcoData->m_numberLinesPrev = lg_max; + + if (lg > 0) { + ErrorStatus = + decode2(hBs, pArcoData->c_prev + 2, mdctSpectrum, lg >> 1, lg_max >> 1); + } else { + FDKmemset(&pArcoData->c_prev[2], 1, + sizeof(pArcoData->c_prev[2]) * (lg_max >> 1)); + } + + if ((INT)FDKgetValidBits(hBs) < 0) { + return ARITH_CODER_ERROR; + } + + return ErrorStatus; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/include/FDK_drcDecLib.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/include/FDK_drcDecLib.h new file mode 100644 index 0000000000000..79f8566b401df --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/include/FDK_drcDecLib.h @@ -0,0 +1,321 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): Bernhard Neugebauer + + Description: MPEG-D DRC Decoder + +*******************************************************************************/ + +#ifndef FDK_DRCDECLIB_H +#define FDK_DRCDECLIB_H + +#include "FDK_bitstream.h" +#include "FDK_audio.h" +#include "common_fix.h" + +/* DRC decoder according to ISO/IEC 23003-4 (MPEG-D DRC) */ +/* including ISO/IEC 23003-4/AMD1 (Amendment 1) */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define DRC_DEC_LOUDNESS_NOT_PRESENT (LONG)0x7FFFFFFE + +typedef struct s_drc_decoder* HANDLE_DRC_DECODER; +typedef struct s_uni_drc_interface* HANDLE_UNI_DRC_INTERFACE; +typedef struct s_selection_process_output* HANDLE_SEL_PROC_OUTPUT; + +typedef enum { + DRC_DEC_SELECTION = 0x1, /* DRC decoder instance for DRC set selection only */ + DRC_DEC_GAIN = 0x2, /* DRC decoder instance for applying DRC only */ + DRC_DEC_ALL = 0x3 /* DRC decoder with full functionality */ +} DRC_DEC_FUNCTIONAL_RANGE; + +typedef enum { + /* get and set userparams */ + DRC_DEC_BOOST, + DRC_DEC_COMPRESS, + /* set only userparams */ + DRC_DEC_LOUDNESS_NORMALIZATION_ON, + DRC_DEC_TARGET_LOUDNESS, /**< target loudness in dB, with exponent e = 7 */ + DRC_DEC_EFFECT_TYPE, + DRC_DEC_EFFECT_TYPE_FALLBACK_CODE, + DRC_DEC_LOUDNESS_MEASUREMENT_METHOD, + DRC_DEC_ALBUM_MODE, + /* set only system (not user) parameters */ + DRC_DEC_DOWNMIX_ID, + DRC_DEC_TARGET_CHANNEL_COUNT_REQUESTED, /**< number of output channels + notified to FDK_drcDecLib for + choosing an appropriate + downmixInstruction */ + DRC_DEC_BASE_CHANNEL_COUNT, + DRC_DEC_FRAME_SIZE, + DRC_DEC_SAMPLE_RATE, + /* get only system parameters */ + DRC_DEC_IS_MULTIBAND_DRC_1, + DRC_DEC_IS_MULTIBAND_DRC_2, + DRC_DEC_IS_ACTIVE, /**< MPEG-D DRC payload is present and at least one of + Dynamic Range Control (DRC) or Loudness Normalization + (LN) is activated */ + DRC_DEC_TARGET_CHANNEL_COUNT_SELECTED, /**< number of output channels if + appropriate downmixInstruction + exists */ + DRC_DEC_OUTPUT_LOUDNESS /**< output loudness in dB, with exponent e = 7, or + DRC_DEC_LOUDNESS_NOT_PRESENT if no loudness is + contained in the bitstream */ +} DRC_DEC_USERPARAM; + +typedef enum { + DRC_DEC_OK = 0, + + DRC_DEC_NOT_OK = -10000, + DRC_DEC_OUT_OF_MEMORY, + DRC_DEC_NOT_OPENED, + DRC_DEC_NOT_READY, + DRC_DEC_PARAM_OUT_OF_RANGE, + DRC_DEC_INVALID_PARAM, + DRC_DEC_UNSUPPORTED_FUNCTION +} DRC_DEC_ERROR; + +typedef enum { + DRC_DEC_TEST_TIME_DOMAIN = -100, + DRC_DEC_TEST_QMF_DOMAIN, + DRC_DEC_TEST_STFT_DOMAIN, + DRC_DEC_CODEC_MODE_UNDEFINED = -1, + DRC_DEC_MPEG_4_AAC, + DRC_DEC_MPEG_D_USAC, + DRC_DEC_MPEG_H_3DA +} DRC_DEC_CODEC_MODE; + +/* Apply only DRC sets dedicated to processing location. + DRC1: before downmix + DRC2: before or after downmix (AMD1: only after downmix) + DRC3: after downmix */ +typedef enum { + DRC_DEC_DRC1, + DRC_DEC_DRC1_DRC2, + DRC_DEC_DRC2, + DRC_DEC_DRC3, + DRC_DEC_DRC2_DRC3 +} DRC_DEC_LOCATION; + +DRC_DEC_ERROR +FDK_drcDec_Open(HANDLE_DRC_DECODER* phDrcDec, + const DRC_DEC_FUNCTIONAL_RANGE functionalRange); + +DRC_DEC_ERROR +FDK_drcDec_SetCodecMode(HANDLE_DRC_DECODER hDrcDec, + const DRC_DEC_CODEC_MODE codecMode); + +DRC_DEC_ERROR +FDK_drcDec_Init(HANDLE_DRC_DECODER hDrcDec, const int frameSize, + const int sampleRate, const int baseChannelCount); + +DRC_DEC_ERROR +FDK_drcDec_Close(HANDLE_DRC_DECODER* phDrcDec); + +/* set single user request */ +DRC_DEC_ERROR +FDK_drcDec_SetParam(HANDLE_DRC_DECODER hDrcDec, + const DRC_DEC_USERPARAM requestType, + const FIXP_DBL requestValue); + +LONG FDK_drcDec_GetParam(HANDLE_DRC_DECODER hDrcDec, + const DRC_DEC_USERPARAM requestType); + +DRC_DEC_ERROR +FDK_drcDec_SetInterfaceParameters(HANDLE_DRC_DECODER hDrcDec, + HANDLE_UNI_DRC_INTERFACE uniDrcInterface); + +DRC_DEC_ERROR +FDK_drcDec_SetSelectionProcessMpeghParameters_simple( + HANDLE_DRC_DECODER hDrcDec, const int groupPresetIdRequested, + const int numGroupIdsRequested, const int* groupIdsRequested); + +DRC_DEC_ERROR +FDK_drcDec_SetDownmixInstructions(HANDLE_DRC_DECODER hDrcDec, + const int numDowmixId, const int* downmixId, + const int* targetLayout, + const int* targetChannelCount); + +void FDK_drcDec_SetSelectionProcessOutput( + HANDLE_DRC_DECODER hDrcDec, HANDLE_SEL_PROC_OUTPUT hSelProcOutput); + +HANDLE_SEL_PROC_OUTPUT +FDK_drcDec_GetSelectionProcessOutput(HANDLE_DRC_DECODER hDrcDec); + +LONG /* FIXP_DBL, e = 7 */ +FDK_drcDec_GetGroupLoudness(HANDLE_SEL_PROC_OUTPUT hSelProcOutput, + const int groupID, int* groupLoudnessAvailable); + +void FDK_drcDec_SetChannelGains(HANDLE_DRC_DECODER hDrcDec, + const int numChannels, const int frameSize, + FIXP_DBL* channelGainDb, FIXP_DBL* audioBuffer, + const int audioBufferChannelOffset); + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcConfig(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +DRC_DEC_ERROR +FDK_drcDec_ReadLoudnessInfoSet(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +DRC_DEC_ERROR +FDK_drcDec_ReadLoudnessBox(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +DRC_DEC_ERROR +FDK_drcDec_ReadDownmixInstructions_Box(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcInstructions_Box(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcCoefficients_Box(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcGain(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +/* either call FDK_drcDec_ReadUniDrcConfig, FDK_drcDec_ReadLoudnessInfoSet and + FDK_drcDec_ReadUniDrcGain separately, or call FDK_drcDec_ReadUniDrc */ +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrc(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +/* calling sequence: + FDK_drcDec_Read...() + FDK_drcDec_SetChannelGains() + FDK_drcDec_Preprocess() + FDK_drcDec_Process...() */ + +DRC_DEC_ERROR +FDK_drcDec_Preprocess(HANDLE_DRC_DECODER hDrcDec); + +DRC_DEC_ERROR +FDK_drcDec_ProcessTime(HANDLE_DRC_DECODER hDrcDec, const int delaySamples, + const DRC_DEC_LOCATION drcLocation, + const int channelOffset, const int drcChannelOffset, + const int numChannelsProcessed, FIXP_DBL* realBuffer, + const int timeDataChannelOffset); + +DRC_DEC_ERROR +FDK_drcDec_ProcessFreq(HANDLE_DRC_DECODER hDrcDec, const int delaySamples, + const DRC_DEC_LOCATION drcLocation, + const int channelOffset, const int drcChannelOffset, + const int numChannelsProcessed, + const int processSingleTimeslot, FIXP_DBL** realBuffer, + FIXP_DBL** imagBuffer); + +DRC_DEC_ERROR +FDK_drcDec_ApplyDownmix(HANDLE_DRC_DECODER hDrcDec, int* reverseInChannelMap, + int* reverseOutChannelMap, FIXP_DBL* realBuffer, + int* pNChannels); + +/* Get library info for this module. */ +DRC_DEC_ERROR +FDK_drcDec_GetLibInfo(LIB_INFO* info); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/FDK_drcDecLib.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/FDK_drcDecLib.cpp new file mode 100644 index 0000000000000..26e5b78e86f96 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/FDK_drcDecLib.cpp @@ -0,0 +1,927 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): Bernhard Neugebauer + + Description: MPEG-D DRC Decoder + +*******************************************************************************/ + +#include "drcDec_reader.h" +#include "drcDec_gainDecoder.h" +#include "FDK_drcDecLib.h" + +#include "drcDec_selectionProcess.h" +#include "drcDec_tools.h" + +/* Decoder library info */ +#define DRCDEC_LIB_VL0 2 +#define DRCDEC_LIB_VL1 1 +#define DRCDEC_LIB_VL2 0 +#define DRCDEC_LIB_TITLE "MPEG-D DRC Decoder Lib" +#ifdef SUPPRESS_BUILD_DATE_INFO +#define DRCDEC_LIB_BUILD_DATE "" +#define DRCDEC_LIB_BUILD_TIME "" +#else +#define DRCDEC_LIB_BUILD_DATE __DATE__ +#define DRCDEC_LIB_BUILD_TIME __TIME__ +#endif + +typedef enum { + DRC_DEC_NOT_INITIALIZED = 0, + DRC_DEC_INITIALIZED, + DRC_DEC_NEW_GAIN_PAYLOAD, + DRC_DEC_INTERPOLATION_PREPARED +} DRC_DEC_STATUS; + +struct s_drc_decoder { + DRC_DEC_CODEC_MODE codecMode; + DRC_DEC_FUNCTIONAL_RANGE functionalRange; + DRC_DEC_STATUS status; + + /* handles of submodules */ + HANDLE_DRC_GAIN_DECODER hGainDec; + HANDLE_DRC_SELECTION_PROCESS hSelectionProc; + int selProcInputDiff; + + /* data structs */ + UNI_DRC_CONFIG uniDrcConfig; + LOUDNESS_INFO_SET loudnessInfoSet; + UNI_DRC_GAIN uniDrcGain; + + SEL_PROC_OUTPUT selProcOutput; +} DRC_DECODER; + +static int _getGainStatus(HANDLE_UNI_DRC_GAIN hUniDrcGain) { + return hUniDrcGain->status; +} + +static int isResetNeeded(HANDLE_DRC_DECODER hDrcDec, + const SEL_PROC_OUTPUT oldSelProcOutput) { + int i, resetNeeded = 0; + + if (hDrcDec->selProcOutput.numSelectedDrcSets != + oldSelProcOutput.numSelectedDrcSets) { + resetNeeded = 1; + } else { + for (i = 0; i < hDrcDec->selProcOutput.numSelectedDrcSets; i++) { + if (hDrcDec->selProcOutput.selectedDrcSetIds[i] != + oldSelProcOutput.selectedDrcSetIds[i]) + resetNeeded = 1; + if (hDrcDec->selProcOutput.selectedDownmixIds[i] != + oldSelProcOutput.selectedDownmixIds[i]) + resetNeeded = 1; + } + } + + if (hDrcDec->selProcOutput.boost != oldSelProcOutput.boost) resetNeeded = 1; + if (hDrcDec->selProcOutput.compress != oldSelProcOutput.compress) + resetNeeded = 1; + + /* Note: Changes in downmix matrix are not caught, as they don't affect the + * DRC gain decoder */ + + return resetNeeded; +} + +static void startSelectionProcess(HANDLE_DRC_DECODER hDrcDec) { + int uniDrcConfigHasChanged = 0; + SEL_PROC_OUTPUT oldSelProcOutput = hDrcDec->selProcOutput; + + if (!hDrcDec->status) return; + + if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { + uniDrcConfigHasChanged = hDrcDec->uniDrcConfig.diff; + if (hDrcDec->uniDrcConfig.diff || hDrcDec->loudnessInfoSet.diff || + hDrcDec->selProcInputDiff) { + /* in case of an error, signal that selection process was not successful + */ + hDrcDec->selProcOutput.numSelectedDrcSets = 0; + + drcDec_SelectionProcess_Process( + hDrcDec->hSelectionProc, &(hDrcDec->uniDrcConfig), + &(hDrcDec->loudnessInfoSet), &(hDrcDec->selProcOutput)); + + hDrcDec->selProcInputDiff = 0; + hDrcDec->uniDrcConfig.diff = 0; + hDrcDec->loudnessInfoSet.diff = 0; + } + } + + if (hDrcDec->functionalRange & DRC_DEC_GAIN) { + if (isResetNeeded(hDrcDec, oldSelProcOutput) || uniDrcConfigHasChanged) { + drcDec_GainDecoder_Config(hDrcDec->hGainDec, &(hDrcDec->uniDrcConfig), + hDrcDec->selProcOutput.numSelectedDrcSets, + hDrcDec->selProcOutput.selectedDrcSetIds, + hDrcDec->selProcOutput.selectedDownmixIds); + } + } +} + +DRC_DEC_ERROR +FDK_drcDec_Open(HANDLE_DRC_DECODER* phDrcDec, + const DRC_DEC_FUNCTIONAL_RANGE functionalRange) { + DRC_ERROR dErr = DE_OK; + DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; + HANDLE_DRC_DECODER hDrcDec; + + *phDrcDec = (HANDLE_DRC_DECODER)FDKcalloc(1, sizeof(DRC_DECODER)); + if (!*phDrcDec) return DRC_DEC_OUT_OF_MEMORY; + hDrcDec = *phDrcDec; + + hDrcDec->functionalRange = functionalRange; + + hDrcDec->status = DRC_DEC_NOT_INITIALIZED; + hDrcDec->codecMode = DRC_DEC_CODEC_MODE_UNDEFINED; + + if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { + sErr = drcDec_SelectionProcess_Create(&(hDrcDec->hSelectionProc)); + if (sErr) return DRC_DEC_OUT_OF_MEMORY; + sErr = drcDec_SelectionProcess_Init(hDrcDec->hSelectionProc); + if (sErr) return DRC_DEC_NOT_OK; + hDrcDec->selProcInputDiff = 1; + } + + if (hDrcDec->functionalRange & DRC_DEC_GAIN) { + dErr = drcDec_GainDecoder_Open(&(hDrcDec->hGainDec)); + if (dErr) return DRC_DEC_OUT_OF_MEMORY; + } + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_SetCodecMode(HANDLE_DRC_DECODER hDrcDec, + const DRC_DEC_CODEC_MODE codecMode) { + DRC_ERROR dErr = DE_OK; + DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + if (hDrcDec->codecMode == + DRC_DEC_CODEC_MODE_UNDEFINED) { /* Set codec mode, if it is set for the + first time */ + hDrcDec->codecMode = codecMode; + + if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { + sErr = drcDec_SelectionProcess_SetCodecMode( + hDrcDec->hSelectionProc, (SEL_PROC_CODEC_MODE)codecMode); + if (sErr) return DRC_DEC_NOT_OK; + hDrcDec->selProcInputDiff = 1; + } + + if (hDrcDec->functionalRange & DRC_DEC_GAIN) { + DELAY_MODE delayMode; + int timeDomainSupported; + SUBBAND_DOMAIN_MODE subbandDomainSupported; + + switch (hDrcDec->codecMode) { + case DRC_DEC_MPEG_4_AAC: + case DRC_DEC_MPEG_D_USAC: + case DRC_DEC_MPEG_H_3DA: + default: + delayMode = DM_REGULAR_DELAY; + } + + switch (hDrcDec->codecMode) { + case DRC_DEC_MPEG_4_AAC: + case DRC_DEC_MPEG_D_USAC: + timeDomainSupported = 1; + subbandDomainSupported = SDM_OFF; + break; + case DRC_DEC_MPEG_H_3DA: + timeDomainSupported = 1; + subbandDomainSupported = SDM_STFT256; + break; + + case DRC_DEC_TEST_TIME_DOMAIN: + timeDomainSupported = 1; + subbandDomainSupported = SDM_OFF; + break; + case DRC_DEC_TEST_QMF_DOMAIN: + timeDomainSupported = 0; + subbandDomainSupported = SDM_QMF64; + break; + case DRC_DEC_TEST_STFT_DOMAIN: + timeDomainSupported = 0; + subbandDomainSupported = SDM_STFT256; + break; + + default: + timeDomainSupported = 0; + subbandDomainSupported = SDM_OFF; + } + + dErr = drcDec_GainDecoder_SetCodecDependentParameters( + hDrcDec->hGainDec, delayMode, timeDomainSupported, + subbandDomainSupported); + if (dErr) return DRC_DEC_NOT_OK; + } + } + + /* Don't allow changing codecMode if it has already been set. */ + if (hDrcDec->codecMode != codecMode) return DRC_DEC_NOT_OK; + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_Init(HANDLE_DRC_DECODER hDrcDec, const int frameSize, + const int sampleRate, const int baseChannelCount) { + DRC_ERROR dErr = DE_OK; + DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (hDrcDec == NULL || frameSize == 0 || sampleRate == 0 || + baseChannelCount == 0) + return DRC_DEC_OK; /* return without doing anything */ + + if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_BASE_CHANNEL_COUNT, + (FIXP_DBL)baseChannelCount, &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_NOT_OK; + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_SAMPLE_RATE, (FIXP_DBL)sampleRate, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_NOT_OK; + } + + if (hDrcDec->functionalRange & DRC_DEC_GAIN) { + dErr = drcDec_GainDecoder_SetParam(hDrcDec->hGainDec, GAIN_DEC_FRAME_SIZE, + frameSize); + if (dErr) return DRC_DEC_NOT_OK; + dErr = drcDec_GainDecoder_SetParam(hDrcDec->hGainDec, GAIN_DEC_SAMPLE_RATE, + sampleRate); + if (dErr) return DRC_DEC_NOT_OK; + dErr = drcDec_GainDecoder_Init(hDrcDec->hGainDec); + if (dErr) return DRC_DEC_NOT_OK; + } + + hDrcDec->status = DRC_DEC_INITIALIZED; + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_Close(HANDLE_DRC_DECODER* phDrcDec) { + HANDLE_DRC_DECODER hDrcDec; + + if (phDrcDec == NULL) { + return DRC_DEC_OK; + } + + hDrcDec = *phDrcDec; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + if (hDrcDec->functionalRange & DRC_DEC_GAIN) { + drcDec_GainDecoder_Close(&(hDrcDec->hGainDec)); + } + + if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { + drcDec_SelectionProcess_Delete(&(hDrcDec->hSelectionProc)); + } + + FDKfree(*phDrcDec); + *phDrcDec = NULL; + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_SetParam(HANDLE_DRC_DECODER hDrcDec, + const DRC_DEC_USERPARAM requestType, + const FIXP_DBL requestValue) { + DRC_ERROR dErr = DE_OK; + DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int invalidParameter = 0; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + if (hDrcDec->functionalRange & DRC_DEC_GAIN) { + switch (requestType) { + case DRC_DEC_SAMPLE_RATE: + dErr = drcDec_GainDecoder_SetParam( + hDrcDec->hGainDec, GAIN_DEC_SAMPLE_RATE, (int)requestValue); + if (dErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_FRAME_SIZE: + dErr = drcDec_GainDecoder_SetParam( + hDrcDec->hGainDec, GAIN_DEC_FRAME_SIZE, (int)requestValue); + if (dErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + default: + invalidParameter |= DRC_DEC_GAIN; + } + } + + if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { + switch (requestType) { + case DRC_DEC_BOOST: + sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc, + SEL_PROC_BOOST, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_COMPRESS: + sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc, + SEL_PROC_COMPRESS, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_LOUDNESS_NORMALIZATION_ON: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_NORMALIZATION_ON, + requestValue, &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_TARGET_LOUDNESS: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_TARGET_LOUDNESS, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_EFFECT_TYPE: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_EFFECT_TYPE, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_DOWNMIX_ID: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_DOWNMIX_ID, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_TARGET_CHANNEL_COUNT_REQUESTED: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_TARGET_CHANNEL_COUNT, + requestValue, &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_BASE_CHANNEL_COUNT: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_BASE_CHANNEL_COUNT, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_NOT_OK; + break; + case DRC_DEC_LOUDNESS_MEASUREMENT_METHOD: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_MEASUREMENT_METHOD, + requestValue, &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_ALBUM_MODE: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_ALBUM_MODE, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + default: + invalidParameter |= DRC_DEC_SELECTION; + } + } + + if (invalidParameter == hDrcDec->functionalRange) + return DRC_DEC_INVALID_PARAM; + + /* All parameters need a new start of the selection process */ + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +LONG FDK_drcDec_GetParam(HANDLE_DRC_DECODER hDrcDec, + const DRC_DEC_USERPARAM requestType) { + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + switch (requestType) { + case DRC_DEC_BOOST: + return (LONG)hDrcDec->selProcOutput.boost; + case DRC_DEC_COMPRESS: + return (LONG)hDrcDec->selProcOutput.compress; + case DRC_DEC_IS_MULTIBAND_DRC_1: + return (LONG)bitstreamContainsMultibandDrc(&hDrcDec->uniDrcConfig, 0); + case DRC_DEC_IS_MULTIBAND_DRC_2: + return (LONG)bitstreamContainsMultibandDrc(&hDrcDec->uniDrcConfig, 0x7F); + case DRC_DEC_IS_ACTIVE: { + /* MPEG-D DRC is considered active (and overrides MPEG-4 DRC), if + * uniDrc payload is present (loudnessInfoSet and/or uniDrcConfig) + * at least one of DRC and Loudness Control is switched on */ + int drcOn = drcDec_SelectionProcess_GetParam( + hDrcDec->hSelectionProc, SEL_PROC_DYNAMIC_RANGE_CONTROL_ON); + int lnOn = drcDec_SelectionProcess_GetParam( + hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_NORMALIZATION_ON); + int uniDrcPayloadPresent = + (hDrcDec->loudnessInfoSet.loudnessInfoCount > 0); + uniDrcPayloadPresent |= + (hDrcDec->loudnessInfoSet.loudnessInfoAlbumCount > 0); + uniDrcPayloadPresent |= + (hDrcDec->uniDrcConfig.drcInstructionsUniDrcCount > 0); + uniDrcPayloadPresent |= + (hDrcDec->uniDrcConfig.downmixInstructionsCount > 0); + return (LONG)(uniDrcPayloadPresent && (drcOn || lnOn)); + } + case DRC_DEC_TARGET_CHANNEL_COUNT_SELECTED: + return (LONG)hDrcDec->selProcOutput.targetChannelCount; + case DRC_DEC_OUTPUT_LOUDNESS: + return (LONG)hDrcDec->selProcOutput.outputLoudness; + default: + return 0; + } +} + +DRC_DEC_ERROR +FDK_drcDec_SetInterfaceParameters(HANDLE_DRC_DECODER hDrcDec, + HANDLE_UNI_DRC_INTERFACE hUniDrcInterface) { + return DRC_DEC_UNSUPPORTED_FUNCTION; +} + +DRC_DEC_ERROR +FDK_drcDec_SetSelectionProcessMpeghParameters_simple( + HANDLE_DRC_DECODER hDrcDec, const int groupPresetIdRequested, + const int numGroupIdsRequested, const int* groupIdsRequested) { + return DRC_DEC_UNSUPPORTED_FUNCTION; +} + +DRC_DEC_ERROR +FDK_drcDec_SetDownmixInstructions(HANDLE_DRC_DECODER hDrcDec, + const int numDownmixId, const int* downmixId, + const int* targetLayout, + const int* targetChannelCount) { + return DRC_DEC_UNSUPPORTED_FUNCTION; +} + +void FDK_drcDec_SetSelectionProcessOutput( + HANDLE_DRC_DECODER hDrcDec, HANDLE_SEL_PROC_OUTPUT hSelProcOutput) {} + +HANDLE_SEL_PROC_OUTPUT +FDK_drcDec_GetSelectionProcessOutput(HANDLE_DRC_DECODER hDrcDec) { + if (hDrcDec == NULL) return NULL; + + return &(hDrcDec->selProcOutput); +} + +LONG /* FIXP_DBL, e = 7 */ +FDK_drcDec_GetGroupLoudness(HANDLE_SEL_PROC_OUTPUT hSelProcOutput, + const int groupID, int* groupLoudnessAvailable) { + return (LONG)0; +} + +void FDK_drcDec_SetChannelGains(HANDLE_DRC_DECODER hDrcDec, + const int numChannels, const int frameSize, + FIXP_DBL* channelGainDb, FIXP_DBL* audioBuffer, + const int audioBufferChannelOffset) { + int err; + + if (hDrcDec == NULL) return; + + err = drcDec_GainDecoder_SetLoudnessNormalizationGainDb( + hDrcDec->hGainDec, hDrcDec->selProcOutput.loudnessNormalizationGainDb); + if (err) return; + + drcDec_GainDecoder_SetChannelGains(hDrcDec->hGainDec, numChannels, frameSize, + channelGainDb, audioBufferChannelOffset, + audioBuffer); +} + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcConfig(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + if (hDrcDec->codecMode == DRC_DEC_MPEG_D_USAC) { + dErr = drcDec_readUniDrcConfig(hBitstream, &(hDrcDec->uniDrcConfig)); + } else + return DRC_DEC_NOT_OK; + + if (dErr) { + /* clear config, if parsing error occured */ + FDKmemclear(&hDrcDec->uniDrcConfig, sizeof(hDrcDec->uniDrcConfig)); + hDrcDec->uniDrcConfig.diff = 1; + } + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadDownmixInstructions_Box(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + return DRC_DEC_NOT_OK; + + if (dErr) { + /* clear config, if parsing error occurred */ + FDKmemclear(&hDrcDec->uniDrcConfig.downmixInstructions, + sizeof(hDrcDec->uniDrcConfig.downmixInstructions)); + hDrcDec->uniDrcConfig.downmixInstructionsCount = 0; + hDrcDec->uniDrcConfig.downmixInstructionsCountV0 = 0; + hDrcDec->uniDrcConfig.downmixInstructionsCountV1 = 0; + hDrcDec->uniDrcConfig.diff = 1; + } + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcInstructions_Box(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + return DRC_DEC_NOT_OK; + + if (dErr) { + /* clear config, if parsing error occurred */ + FDKmemclear(&hDrcDec->uniDrcConfig.drcInstructionsUniDrc, + sizeof(hDrcDec->uniDrcConfig.drcInstructionsUniDrc)); + hDrcDec->uniDrcConfig.drcInstructionsUniDrcCount = 0; + hDrcDec->uniDrcConfig.drcInstructionsUniDrcCountV0 = 0; + hDrcDec->uniDrcConfig.drcInstructionsUniDrcCountV1 = 0; + hDrcDec->uniDrcConfig.diff = 1; + } + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcCoefficients_Box(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + return DRC_DEC_NOT_OK; + + if (dErr) { + /* clear config, if parsing error occurred */ + FDKmemclear(&hDrcDec->uniDrcConfig.drcCoefficientsUniDrc, + sizeof(hDrcDec->uniDrcConfig.drcCoefficientsUniDrc)); + hDrcDec->uniDrcConfig.drcCoefficientsUniDrcCount = 0; + hDrcDec->uniDrcConfig.drcCoefficientsUniDrcCountV0 = 0; + hDrcDec->uniDrcConfig.drcCoefficientsUniDrcCountV1 = 0; + hDrcDec->uniDrcConfig.diff = 1; + } + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadLoudnessInfoSet(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + if (hDrcDec->codecMode == DRC_DEC_MPEG_D_USAC) { + dErr = drcDec_readLoudnessInfoSet(hBitstream, &(hDrcDec->loudnessInfoSet)); + } else + return DRC_DEC_NOT_OK; + + if (dErr) { + /* clear config, if parsing error occurred */ + FDKmemclear(&hDrcDec->loudnessInfoSet, sizeof(hDrcDec->loudnessInfoSet)); + hDrcDec->loudnessInfoSet.diff = 1; + } + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadLoudnessBox(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + return DRC_DEC_NOT_OK; + + if (dErr) { + /* clear config, if parsing error occurred */ + FDKmemclear(&hDrcDec->loudnessInfoSet, sizeof(hDrcDec->loudnessInfoSet)); + hDrcDec->loudnessInfoSet.diff = 1; + } + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcGain(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + if (!hDrcDec->status) { + return DRC_DEC_OK; + } + + dErr = drcDec_readUniDrcGain( + hBitstream, &(hDrcDec->uniDrcConfig), + drcDec_GainDecoder_GetFrameSize(hDrcDec->hGainDec), + drcDec_GainDecoder_GetDeltaTminDefault(hDrcDec->hGainDec), + &(hDrcDec->uniDrcGain)); + if (dErr) return DRC_DEC_NOT_OK; + + if (_getGainStatus(&(hDrcDec->uniDrcGain))) { + hDrcDec->status = DRC_DEC_NEW_GAIN_PAYLOAD; + } + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrc(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + if (!hDrcDec->status) return DRC_DEC_NOT_READY; + + dErr = drcDec_readUniDrc( + hBitstream, &(hDrcDec->uniDrcConfig), &(hDrcDec->loudnessInfoSet), + drcDec_GainDecoder_GetFrameSize(hDrcDec->hGainDec), + drcDec_GainDecoder_GetDeltaTminDefault(hDrcDec->hGainDec), + &(hDrcDec->uniDrcGain)); + + startSelectionProcess(hDrcDec); + if (dErr) return DRC_DEC_NOT_OK; + + if (_getGainStatus(&(hDrcDec->uniDrcGain))) { + hDrcDec->status = DRC_DEC_NEW_GAIN_PAYLOAD; + } + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_Preprocess(HANDLE_DRC_DECODER hDrcDec) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + if (!hDrcDec->status) return DRC_DEC_NOT_READY; + if (!(hDrcDec->functionalRange & DRC_DEC_GAIN)) return DRC_DEC_NOT_OK; + + if (hDrcDec->status != DRC_DEC_NEW_GAIN_PAYLOAD) { + /* no new gain payload was read, e.g. during concalment or flushing. + Generate DRC gains based on the stored DRC gains of last frames */ + drcDec_GainDecoder_Conceal(hDrcDec->hGainDec, &(hDrcDec->uniDrcConfig), + &(hDrcDec->uniDrcGain)); + } + + dErr = drcDec_GainDecoder_Preprocess( + hDrcDec->hGainDec, &(hDrcDec->uniDrcGain), + hDrcDec->selProcOutput.loudnessNormalizationGainDb, + hDrcDec->selProcOutput.boost, hDrcDec->selProcOutput.compress); + if (dErr) return DRC_DEC_NOT_OK; + hDrcDec->status = DRC_DEC_INTERPOLATION_PREPARED; + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ProcessTime(HANDLE_DRC_DECODER hDrcDec, const int delaySamples, + const DRC_DEC_LOCATION drcLocation, + const int channelOffset, const int drcChannelOffset, + const int numChannelsProcessed, FIXP_DBL* realBuffer, + const int timeDataChannelOffset) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + if (!(hDrcDec->functionalRange & DRC_DEC_GAIN)) return DRC_DEC_NOT_OK; + if (hDrcDec->status != DRC_DEC_INTERPOLATION_PREPARED) + return DRC_DEC_NOT_READY; + + dErr = drcDec_GainDecoder_ProcessTimeDomain( + hDrcDec->hGainDec, delaySamples, (GAIN_DEC_LOCATION)drcLocation, + channelOffset, drcChannelOffset, numChannelsProcessed, + timeDataChannelOffset, realBuffer); + if (dErr) return DRC_DEC_NOT_OK; + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ProcessFreq(HANDLE_DRC_DECODER hDrcDec, const int delaySamples, + const DRC_DEC_LOCATION drcLocation, + const int channelOffset, const int drcChannelOffset, + const int numChannelsProcessed, + const int processSingleTimeslot, FIXP_DBL** realBuffer, + FIXP_DBL** imagBuffer) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + if (!(hDrcDec->functionalRange & DRC_DEC_GAIN)) return DRC_DEC_NOT_OK; + if (hDrcDec->status != DRC_DEC_INTERPOLATION_PREPARED) + return DRC_DEC_NOT_READY; + + dErr = drcDec_GainDecoder_ProcessSubbandDomain( + hDrcDec->hGainDec, delaySamples, (GAIN_DEC_LOCATION)drcLocation, + channelOffset, drcChannelOffset, numChannelsProcessed, + processSingleTimeslot, realBuffer, imagBuffer); + if (dErr) return DRC_DEC_NOT_OK; + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ApplyDownmix(HANDLE_DRC_DECODER hDrcDec, int* reverseInChannelMap, + int* reverseOutChannelMap, FIXP_DBL* realBuffer, + int* pNChannels) { + SEL_PROC_OUTPUT* pSelProcOutput = &(hDrcDec->selProcOutput); + int baseChCnt = pSelProcOutput->baseChannelCount; + int targetChCnt = pSelProcOutput->targetChannelCount; + int frameSize, n, ic, oc; + FIXP_DBL tmp_out[8]; + FIXP_DBL* audioChannels[8]; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + if (!(hDrcDec->functionalRange & DRC_DEC_GAIN)) return DRC_DEC_NOT_OK; + + /* only downmix is performed here, no upmix. + Downmix is only performed if downmix coefficients are provided. + All other cases of downmix and upmix are treated by pcmDmx library. */ + if (pSelProcOutput->downmixMatrixPresent == 0) + return DRC_DEC_OK; /* no downmix */ + if (targetChCnt >= baseChCnt) return DRC_DEC_OK; /* downmix only */ + + /* sanity checks */ + if (realBuffer == NULL) return DRC_DEC_NOT_OK; + if (reverseInChannelMap == NULL) return DRC_DEC_NOT_OK; + if (reverseOutChannelMap == NULL) return DRC_DEC_NOT_OK; + if (baseChCnt > 8) return DRC_DEC_NOT_OK; + if (baseChCnt != *pNChannels) return DRC_DEC_NOT_OK; + if (targetChCnt > 8) return DRC_DEC_NOT_OK; + + frameSize = drcDec_GainDecoder_GetFrameSize(hDrcDec->hGainDec); + + for (ic = 0; ic < baseChCnt; ic++) { + audioChannels[ic] = &(realBuffer[ic * frameSize]); + } + + /* in-place downmix */ + for (n = 0; n < frameSize; n++) { + for (oc = 0; oc < targetChCnt; oc++) { + tmp_out[oc] = (FIXP_DBL)0; + for (ic = 0; ic < baseChCnt; ic++) { + tmp_out[oc] += + fMultDiv2(audioChannels[ic][n], + pSelProcOutput->downmixMatrix[reverseInChannelMap[ic]] + [reverseOutChannelMap[oc]]) + << 3; + } + } + for (oc = 0; oc < targetChCnt; oc++) { + if (oc >= baseChCnt) break; + audioChannels[oc][n] = tmp_out[oc]; + } + } + + for (oc = targetChCnt; oc < baseChCnt; oc++) { + FDKmemset(audioChannels[oc], 0, frameSize * sizeof(FIXP_DBL)); + } + + *pNChannels = targetChCnt; + + return DRC_DEC_OK; +} + +/* Get library info for this module. */ +DRC_DEC_ERROR +FDK_drcDec_GetLibInfo(LIB_INFO* info) { + int i; + + if (info == NULL) { + return DRC_DEC_INVALID_PARAM; + } + + /* Search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return DRC_DEC_NOT_OK; + } + + /* Add the library info */ + info[i].module_id = FDK_UNIDRCDEC; + info[i].version = LIB_VERSION(DRCDEC_LIB_VL0, DRCDEC_LIB_VL1, DRCDEC_LIB_VL2); + LIB_VERSION_STRING(info + i); + info[i].build_date = DRCDEC_LIB_BUILD_DATE; + info[i].build_time = DRCDEC_LIB_BUILD_TIME; + info[i].title = DRCDEC_LIB_TITLE; + + return DRC_DEC_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_gainDecoder.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_gainDecoder.cpp new file mode 100644 index 0000000000000..de54ddee433e6 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_gainDecoder.cpp @@ -0,0 +1,465 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "drcDec_types.h" +#include "drcDec_gainDecoder.h" +#include "drcGainDec_preprocess.h" +#include "drcGainDec_init.h" +#include "drcGainDec_process.h" +#include "drcDec_tools.h" + +/*******************************************/ +/* static functions */ +/*******************************************/ + +static int _fitsLocation(DRC_INSTRUCTIONS_UNI_DRC* pInst, + const GAIN_DEC_LOCATION drcLocation) { + int downmixId = pInst->drcApplyToDownmix ? pInst->downmixId[0] : 0; + switch (drcLocation) { + case GAIN_DEC_DRC1: + return (downmixId == 0); + case GAIN_DEC_DRC1_DRC2: + return ((downmixId == 0) || (downmixId == DOWNMIX_ID_ANY_DOWNMIX)); + case GAIN_DEC_DRC2: + return (downmixId == DOWNMIX_ID_ANY_DOWNMIX); + case GAIN_DEC_DRC3: + return ((downmixId != 0) && (downmixId != DOWNMIX_ID_ANY_DOWNMIX)); + case GAIN_DEC_DRC2_DRC3: + return (downmixId != 0); + } + return 0; +} + +static void _setChannelGains(HANDLE_DRC_GAIN_DECODER hGainDec, + const int numChannelGains, + const FIXP_DBL* channelGainDb) { + int i, channelGain_e; + FIXP_DBL channelGain; + FDK_ASSERT(numChannelGains <= 8); + for (i = 0; i < numChannelGains; i++) { + if (channelGainDb[i] == (FIXP_DBL)MINVAL_DBL) { + hGainDec->channelGain[i] = (FIXP_DBL)0; + } else { + /* add loudness normalisation gain (dB) to channel gain (dB) */ + FIXP_DBL tmp_channelGainDb = (channelGainDb[i] >> 1) + + (hGainDec->loudnessNormalisationGainDb >> 2); + tmp_channelGainDb = + SATURATE_LEFT_SHIFT(tmp_channelGainDb, 1, DFRACT_BITS); + channelGain = dB2lin(tmp_channelGainDb, 8, &channelGain_e); + hGainDec->channelGain[i] = scaleValue(channelGain, channelGain_e - 8); + } + } +} + +/*******************************************/ +/* public functions */ +/*******************************************/ + +DRC_ERROR +drcDec_GainDecoder_Open(HANDLE_DRC_GAIN_DECODER* phGainDec) { + DRC_GAIN_DECODER* hGainDec = NULL; + + hGainDec = (DRC_GAIN_DECODER*)FDKcalloc(1, sizeof(DRC_GAIN_DECODER)); + if (hGainDec == NULL) return DE_MEMORY_ERROR; + + hGainDec->multiBandActiveDrcIndex = -1; + hGainDec->channelGainActiveDrcIndex = -1; + + *phGainDec = hGainDec; + + return DE_OK; +} + +DRC_ERROR +drcDec_GainDecoder_Init(HANDLE_DRC_GAIN_DECODER hGainDec) { + DRC_ERROR err = DE_OK; + + err = initGainDec(hGainDec); + if (err) return err; + + initDrcGainBuffers(hGainDec->frameSize, &hGainDec->drcGainBuffers); + + return err; +} + +DRC_ERROR +drcDec_GainDecoder_SetParam(HANDLE_DRC_GAIN_DECODER hGainDec, + const GAIN_DEC_PARAM paramType, + const int paramValue) { + switch (paramType) { + case GAIN_DEC_FRAME_SIZE: + if (paramValue < 0) return DE_PARAM_OUT_OF_RANGE; + hGainDec->frameSize = paramValue; + break; + case GAIN_DEC_SAMPLE_RATE: + if (paramValue < 0) return DE_PARAM_OUT_OF_RANGE; + hGainDec->deltaTminDefault = getDeltaTmin(paramValue); + break; + default: + return DE_PARAM_INVALID; + } + return DE_OK; +} + +DRC_ERROR +drcDec_GainDecoder_SetCodecDependentParameters( + HANDLE_DRC_GAIN_DECODER hGainDec, const DELAY_MODE delayMode, + const int timeDomainSupported, + const SUBBAND_DOMAIN_MODE subbandDomainSupported) { + if ((delayMode != DM_REGULAR_DELAY) && (delayMode != DM_LOW_DELAY)) { + return DE_NOT_OK; + } + hGainDec->delayMode = delayMode; + hGainDec->timeDomainSupported = timeDomainSupported; + hGainDec->subbandDomainSupported = subbandDomainSupported; + + return DE_OK; +} + +DRC_ERROR +drcDec_GainDecoder_Config(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + const UCHAR numSelectedDrcSets, + const SCHAR* selectedDrcSetIds, + const UCHAR* selectedDownmixIds) { + DRC_ERROR err = DE_OK; + int a; + + hGainDec->nActiveDrcs = 0; + hGainDec->multiBandActiveDrcIndex = -1; + hGainDec->channelGainActiveDrcIndex = -1; + for (a = 0; a < numSelectedDrcSets; a++) { + err = initActiveDrc(hGainDec, hUniDrcConfig, selectedDrcSetIds[a], + selectedDownmixIds[a]); + if (err) return err; + } + + err = initActiveDrcOffset(hGainDec); + if (err) return err; + + return err; +} + +DRC_ERROR +drcDec_GainDecoder_Close(HANDLE_DRC_GAIN_DECODER* phGainDec) { + if (*phGainDec != NULL) { + FDKfree(*phGainDec); + *phGainDec = NULL; + } + + return DE_OK; +} + +DRC_ERROR +drcDec_GainDecoder_Preprocess(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_GAIN hUniDrcGain, + const FIXP_DBL loudnessNormalizationGainDb, + const FIXP_SGL boost, const FIXP_SGL compress) { + DRC_ERROR err = DE_OK; + int a, c; + + /* lnbPointer is the index on the most recent node buffer */ + hGainDec->drcGainBuffers.lnbPointer++; + if (hGainDec->drcGainBuffers.lnbPointer >= NUM_LNB_FRAMES) + hGainDec->drcGainBuffers.lnbPointer = 0; + + for (a = 0; a < hGainDec->nActiveDrcs; a++) { + /* prepare gain interpolation of sequences used by copying and modifying + * nodes in node buffers */ + err = prepareDrcGain(hGainDec, hUniDrcGain, compress, boost, + loudnessNormalizationGainDb, a); + if (err) return err; + } + + for (a = 0; a < MAX_ACTIVE_DRCS; a++) { + for (c = 0; c < 8; c++) { + hGainDec->activeDrc[a] + .lnbIndexForChannel[c][hGainDec->drcGainBuffers.lnbPointer] = + -1; /* "no DRC processing" */ + } + hGainDec->activeDrc[a].subbandGainsReady = 0; + } + + for (c = 0; c < 8; c++) { + hGainDec->drcGainBuffers + .channelGain[c][hGainDec->drcGainBuffers.lnbPointer] = + FL2FXCONST_DBL(1.0f / (float)(1 << 8)); + } + + return err; +} + +/* create gain sequence out of gain sequences of last frame for concealment and + * flushing */ +DRC_ERROR +drcDec_GainDecoder_Conceal(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_UNI_DRC_GAIN hUniDrcGain) { + int seq, gainSequenceCount; + DRC_COEFFICIENTS_UNI_DRC* pCoef = + selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); + if (pCoef && pCoef->gainSequenceCount) { + gainSequenceCount = fMin(pCoef->gainSequenceCount, (UCHAR)12); + } else { + gainSequenceCount = 1; + } + + for (seq = 0; seq < gainSequenceCount; seq++) { + int lastNodeIndex = 0; + FIXP_SGL lastGainDb = (FIXP_SGL)0; + + lastNodeIndex = hUniDrcGain->nNodes[seq] - 1; + if ((lastNodeIndex >= 0) && (lastNodeIndex < 16)) { + lastGainDb = hUniDrcGain->gainNode[seq][lastNodeIndex].gainDb; + } + + hUniDrcGain->nNodes[seq] = 1; + if (lastGainDb > (FIXP_SGL)0) { + hUniDrcGain->gainNode[seq][0].gainDb = + FX_DBL2FX_SGL(fMult(FL2FXCONST_SGL(0.9f), lastGainDb)); + } else { + hUniDrcGain->gainNode[seq][0].gainDb = + FX_DBL2FX_SGL(fMult(FL2FXCONST_SGL(0.98f), lastGainDb)); + } + hUniDrcGain->gainNode[seq][0].time = hGainDec->frameSize - 1; + } + return DE_OK; +} + +void drcDec_GainDecoder_SetChannelGains(HANDLE_DRC_GAIN_DECODER hGainDec, + const int numChannels, + const int frameSize, + const FIXP_DBL* channelGainDb, + const int audioBufferChannelOffset, + FIXP_DBL* audioBuffer) { + int c, i; + + if (hGainDec->channelGainActiveDrcIndex >= 0) { + /* channel gains will be applied in drcDec_GainDecoder_ProcessTimeDomain or + * drcDec_GainDecoder_ProcessSubbandDomain, respectively. */ + _setChannelGains(hGainDec, numChannels, channelGainDb); + + if (!hGainDec->status) { /* overwrite previous channel gains at startup */ + DRC_GAIN_BUFFERS* pDrcGainBuffers = &hGainDec->drcGainBuffers; + for (c = 0; c < numChannels; c++) { + for (i = 0; i < NUM_LNB_FRAMES; i++) { + pDrcGainBuffers->channelGain[c][i] = hGainDec->channelGain[c]; + } + } + hGainDec->status = 1; + } + } else { + /* smooth and apply channel gains */ + FIXP_DBL prevChannelGain[8]; + for (c = 0; c < numChannels; c++) { + prevChannelGain[c] = hGainDec->channelGain[c]; + } + + _setChannelGains(hGainDec, numChannels, channelGainDb); + + if (!hGainDec->status) { /* overwrite previous channel gains at startup */ + for (c = 0; c < numChannels; c++) + prevChannelGain[c] = hGainDec->channelGain[c]; + hGainDec->status = 1; + } + + for (c = 0; c < numChannels; c++) { + INT n_min = fMin(fMin(CntLeadingZeros(prevChannelGain[c]), + CntLeadingZeros(hGainDec->channelGain[c])) - + 1, + 9); + FIXP_DBL gain = prevChannelGain[c] << n_min; + FIXP_DBL stepsize = ((hGainDec->channelGain[c] << n_min) - gain); + if (stepsize != (FIXP_DBL)0) { + if (frameSize == 1024) + stepsize = stepsize >> 10; + else + stepsize = (LONG)stepsize / frameSize; + } + n_min = 9 - n_min; +#ifdef FUNCTION_drcDec_GainDecoder_SetChannelGains_func1 + drcDec_GainDecoder_SetChannelGains_func1(audioBuffer, gain, stepsize, + n_min, frameSize); +#else + for (i = 0; i < frameSize; i++) { + audioBuffer[i] = fMultDiv2(audioBuffer[i], gain) << n_min; + gain += stepsize; + } +#endif + audioBuffer += audioBufferChannelOffset; + } + } +} + +DRC_ERROR +drcDec_GainDecoder_ProcessTimeDomain( + HANDLE_DRC_GAIN_DECODER hGainDec, const int delaySamples, + const GAIN_DEC_LOCATION drcLocation, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int timeDataChannelOffset, FIXP_DBL* audioIOBuffer) { + DRC_ERROR err = DE_OK; + int a; + + if (!hGainDec->timeDomainSupported) { + return DE_NOT_OK; + } + + for (a = 0; a < hGainDec->nActiveDrcs; a++) { + if (!_fitsLocation(hGainDec->activeDrc[a].pInst, drcLocation)) continue; + + /* Apply DRC */ + err = processDrcTime(hGainDec, a, delaySamples, channelOffset, + drcChannelOffset, numChannelsProcessed, + timeDataChannelOffset, audioIOBuffer); + if (err) return err; + } + + return err; +} + +DRC_ERROR +drcDec_GainDecoder_ProcessSubbandDomain( + HANDLE_DRC_GAIN_DECODER hGainDec, const int delaySamples, + const GAIN_DEC_LOCATION drcLocation, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int processSingleTimeslot, FIXP_DBL* audioIOBufferReal[], + FIXP_DBL* audioIOBufferImag[]) { + DRC_ERROR err = DE_OK; + int a; + + if (hGainDec->subbandDomainSupported == SDM_OFF) { + return DE_NOT_OK; + } + + for (a = 0; a < hGainDec->nActiveDrcs; a++) { + if (!_fitsLocation(hGainDec->activeDrc[a].pInst, drcLocation)) continue; + + /* Apply DRC */ + err = processDrcSubband(hGainDec, a, delaySamples, channelOffset, + drcChannelOffset, numChannelsProcessed, + processSingleTimeslot, audioIOBufferReal, + audioIOBufferImag); + if (err) return err; + } + + return err; +} + +DRC_ERROR +drcDec_GainDecoder_SetLoudnessNormalizationGainDb( + HANDLE_DRC_GAIN_DECODER hGainDec, FIXP_DBL loudnessNormalizationGainDb) { + hGainDec->loudnessNormalisationGainDb = loudnessNormalizationGainDb; + + return DE_OK; +} + +int drcDec_GainDecoder_GetFrameSize(HANDLE_DRC_GAIN_DECODER hGainDec) { + if (hGainDec == NULL) return -1; + + return hGainDec->frameSize; +} + +int drcDec_GainDecoder_GetDeltaTminDefault(HANDLE_DRC_GAIN_DECODER hGainDec) { + if (hGainDec == NULL) return -1; + + return hGainDec->deltaTminDefault; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_gainDecoder.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_gainDecoder.h new file mode 100644 index 0000000000000..394b455c83797 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_gainDecoder.h @@ -0,0 +1,270 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCDEC_GAINDECODER_H +#define DRCDEC_GAINDECODER_H + +#include "drcDecoder.h" + +/* Definitions common to gainDecoder submodule */ + +#define NUM_LNB_FRAMES \ + 5 /* previous frame + this frame + one frame for DM_REGULAR_DELAY + (maximum \ + delaySamples)/frameSize */ + +/* QMF64 */ +#define SUBBAND_NUM_BANDS_QMF64 64 +#define SUBBAND_DOWNSAMPLING_FACTOR_QMF64 64 +#define SUBBAND_ANALYSIS_DELAY_QMF64 320 + +/* QMF71 (according to ISO/IEC 23003-1:2007) */ +#define SUBBAND_NUM_BANDS_QMF71 71 +#define SUBBAND_DOWNSAMPLING_FACTOR_QMF71 64 +#define SUBBAND_ANALYSIS_DELAY_QMF71 320 + 384 + +/* STFT256 (according to ISO/IEC 23008-3:2015/AMD3) */ +#define SUBBAND_NUM_BANDS_STFT256 256 +#define SUBBAND_DOWNSAMPLING_FACTOR_STFT256 256 +#define SUBBAND_ANALYSIS_DELAY_STFT256 256 + +typedef enum { + GAIN_DEC_DRC1, + GAIN_DEC_DRC1_DRC2, + GAIN_DEC_DRC2, + GAIN_DEC_DRC3, + GAIN_DEC_DRC2_DRC3 +} GAIN_DEC_LOCATION; + +typedef enum { GAIN_DEC_FRAME_SIZE, GAIN_DEC_SAMPLE_RATE } GAIN_DEC_PARAM; + +typedef struct { + FIXP_DBL gainLin; /* e = 7 */ + SHORT time; +} NODE_LIN; + +typedef struct { + GAIN_INTERPOLATION_TYPE gainInterpolationType; + int nNodes[NUM_LNB_FRAMES]; /* number of nodes, saturated to 16 */ + NODE_LIN linearNode[NUM_LNB_FRAMES][16]; +} LINEAR_NODE_BUFFER; + +typedef struct { + int lnbPointer; + LINEAR_NODE_BUFFER linearNodeBuffer[12]; + LINEAR_NODE_BUFFER dummyLnb; + FIXP_DBL channelGain[8][NUM_LNB_FRAMES]; /* e = 8 */ +} DRC_GAIN_BUFFERS; + +typedef struct { + int activeDrcOffset; + DRC_INSTRUCTIONS_UNI_DRC* pInst; + DRC_COEFFICIENTS_UNI_DRC* pCoef; + + DUCKING_MODIFICATION duckingModificationForChannelGroup[8]; + SCHAR channelGroupForChannel[8]; + + UCHAR bandCountForChannelGroup[8]; + UCHAR gainElementForGroup[8]; + UCHAR channelGroupIsParametricDrc[8]; + UCHAR gainElementCount; /* number of different DRC gains inluding all DRC + bands */ + int lnbIndexForChannel[8][NUM_LNB_FRAMES]; + int subbandGainsReady; +} ACTIVE_DRC; + +typedef struct { + int deltaTminDefault; + INT frameSize; + FIXP_DBL loudnessNormalisationGainDb; + DELAY_MODE delayMode; + + int nActiveDrcs; + ACTIVE_DRC activeDrc[MAX_ACTIVE_DRCS]; + int multiBandActiveDrcIndex; + int channelGainActiveDrcIndex; + FIXP_DBL channelGain[8]; /* e = 8 */ + + DRC_GAIN_BUFFERS drcGainBuffers; + FIXP_DBL subbandGains[12][4 * 1024 / 256]; + FIXP_DBL dummySubbandGains[4 * 1024 / 256]; + + int status; + int timeDomainSupported; + SUBBAND_DOMAIN_MODE subbandDomainSupported; +} DRC_GAIN_DECODER, *HANDLE_DRC_GAIN_DECODER; + +/* init functions */ +DRC_ERROR +drcDec_GainDecoder_Open(HANDLE_DRC_GAIN_DECODER* phGainDec); + +DRC_ERROR +drcDec_GainDecoder_Init(HANDLE_DRC_GAIN_DECODER hGainDec); + +DRC_ERROR +drcDec_GainDecoder_SetParam(HANDLE_DRC_GAIN_DECODER hGainDec, + const GAIN_DEC_PARAM paramType, + const int paramValue); + +DRC_ERROR +drcDec_GainDecoder_SetCodecDependentParameters( + HANDLE_DRC_GAIN_DECODER hGainDec, const DELAY_MODE delayMode, + const int timeDomainSupported, + const SUBBAND_DOMAIN_MODE subbandDomainSupported); + +DRC_ERROR +drcDec_GainDecoder_Config(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + const UCHAR numSelectedDrcSets, + const SCHAR* selectedDrcSetIds, + const UCHAR* selectedDownmixIds); + +/* close functions */ +DRC_ERROR +drcDec_GainDecoder_Close(HANDLE_DRC_GAIN_DECODER* phGainDec); + +/* process functions */ + +/* call drcDec_GainDecoder_Preprocess first */ +DRC_ERROR +drcDec_GainDecoder_Preprocess(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_GAIN hUniDrcGain, + const FIXP_DBL loudnessNormalizationGainDb, + const FIXP_SGL boost, const FIXP_SGL compress); + +/* Then call one of drcDec_GainDecoder_ProcessTimeDomain or + * drcDec_GainDecoder_ProcessSubbandDomain */ +DRC_ERROR +drcDec_GainDecoder_ProcessTimeDomain( + HANDLE_DRC_GAIN_DECODER hGainDec, const int delaySamples, + const GAIN_DEC_LOCATION drcLocation, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int timeDataChannelOffset, FIXP_DBL* audioIOBuffer); + +DRC_ERROR +drcDec_GainDecoder_ProcessSubbandDomain( + HANDLE_DRC_GAIN_DECODER hGainDec, const int delaySamples, + GAIN_DEC_LOCATION drcLocation, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int processSingleTimeslot, FIXP_DBL* audioIOBufferReal[], + FIXP_DBL* audioIOBufferImag[]); + +DRC_ERROR +drcDec_GainDecoder_Conceal(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_UNI_DRC_GAIN hUniDrcGain); + +DRC_ERROR +drcDec_GainDecoder_SetLoudnessNormalizationGainDb( + HANDLE_DRC_GAIN_DECODER hGainDec, FIXP_DBL loudnessNormalizationGainDb); + +int drcDec_GainDecoder_GetFrameSize(HANDLE_DRC_GAIN_DECODER hGainDec); + +int drcDec_GainDecoder_GetDeltaTminDefault(HANDLE_DRC_GAIN_DECODER hGainDec); + +void drcDec_GainDecoder_SetChannelGains(HANDLE_DRC_GAIN_DECODER hGainDec, + const int numChannels, + const int frameSize, + const FIXP_DBL* channelGainDb, + const int audioBufferChannelOffset, + FIXP_DBL* audioBuffer); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_reader.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_reader.cpp new file mode 100644 index 0000000000000..b080f50a82d44 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_reader.cpp @@ -0,0 +1,2043 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "fixpoint_math.h" +#include "drcDec_reader.h" +#include "drcDec_tools.h" +#include "drcDec_rom.h" +#include "drcDecoder.h" + +/* MPEG-D DRC AMD 1 */ + +#define UNIDRCCONFEXT_PARAM_DRC 0x1 +#define UNIDRCCONFEXT_V1 0x2 +#define UNIDRCLOUDEXT_EQ 0x1 + +#define UNIDRCGAINEXT_TERM 0x0 +#define UNIDRCLOUDEXT_TERM 0x0 +#define UNIDRCCONFEXT_TERM 0x0 + +static int _getZ(const int nNodesMax) { + /* Z is the minimum codeword length that is needed to encode all possible + * timeDelta values */ + /* Z = ceil(log2(2*nNodesMax)) */ + int Z = 1; + while ((1 << Z) < (2 * nNodesMax)) { + Z++; + } + return Z; +} + +static int _getTimeDeltaMin(const GAIN_SET* pGset, const int deltaTminDefault) { + if (pGset->timeDeltaMinPresent) { + return pGset->timeDeltaMin; + } else { + return deltaTminDefault; + } +} + +/* compare and assign */ +static inline int _compAssign(UCHAR* dest, const UCHAR src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = src; + return diff; +} + +static inline int _compAssign(ULONG* dest, const ULONG src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = src; + return diff; +} + +typedef const SCHAR (*Huffman)[2]; + +int _decodeHuffmanCW(Huffman h, /*!< pointer to huffman codebook table */ + HANDLE_FDK_BITSTREAM hBs) /*!< Handle to bitbuffer */ +{ + SCHAR index = 0; + int value, bit; + + while (index >= 0) { + bit = FDKreadBits(hBs, 1); + index = h[index][bit]; + } + + value = index + 64; /* Add offset */ + + return value; +} + +/**********/ +/* uniDrc */ +/**********/ + +DRC_ERROR +drcDec_readUniDrc(HANDLE_FDK_BITSTREAM hBs, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + const int frameSize, const int deltaTminDefault, + HANDLE_UNI_DRC_GAIN hUniDrcGain) { + DRC_ERROR err = DE_OK; + int loudnessInfoSetPresent, uniDrcConfigPresent; + + loudnessInfoSetPresent = FDKreadBits(hBs, 1); + if (loudnessInfoSetPresent) { + uniDrcConfigPresent = FDKreadBits(hBs, 1); + if (uniDrcConfigPresent) { + err = drcDec_readUniDrcConfig(hBs, hUniDrcConfig); + if (err) { + /* clear config, if parsing error occured */ + FDKmemclear(hUniDrcConfig, sizeof(UNI_DRC_CONFIG)); + hUniDrcConfig->diff = 1; + } + } + err = drcDec_readLoudnessInfoSet(hBs, hLoudnessInfoSet); + if (err) { + /* clear config, if parsing error occured */ + FDKmemclear(hLoudnessInfoSet, sizeof(LOUDNESS_INFO_SET)); + hLoudnessInfoSet->diff = 1; + } + } + + err = drcDec_readUniDrcGain(hBs, hUniDrcConfig, frameSize, deltaTminDefault, + hUniDrcGain); + + return err; +} + +/**************/ +/* uniDrcGain */ +/**************/ + +static FIXP_SGL _decodeGainInitial( + HANDLE_FDK_BITSTREAM hBs, const GAIN_CODING_PROFILE gainCodingProfile) { + int sign, magn; + FIXP_SGL gainInitial = (FIXP_SGL)0; + switch (gainCodingProfile) { + case GCP_REGULAR: + sign = FDKreadBits(hBs, 1); + magn = FDKreadBits(hBs, 8); + + gainInitial = + (FIXP_SGL)(magn << (FRACT_BITS - 1 - 3 - 7)); /* magn * 0.125; */ + if (sign) gainInitial = -gainInitial; + break; + case GCP_FADING: + sign = FDKreadBits(hBs, 1); + if (sign == 0) + gainInitial = (FIXP_SGL)0; + else { + magn = FDKreadBits(hBs, 10); + gainInitial = -(FIXP_SGL)( + (magn + 1) << (FRACT_BITS - 1 - 3 - 7)); /* - (magn + 1) * 0.125; */ + } + break; + case GCP_CLIPPING_DUCKING: + sign = FDKreadBits(hBs, 1); + if (sign == 0) + gainInitial = (FIXP_SGL)0; + else { + magn = FDKreadBits(hBs, 8); + gainInitial = -(FIXP_SGL)( + (magn + 1) << (FRACT_BITS - 1 - 3 - 7)); /* - (magn + 1) * 0.125; */ + } + break; + case GCP_CONSTANT: + break; + } + return gainInitial; +} + +static int _decodeNNodes(HANDLE_FDK_BITSTREAM hBs) { + int nNodes = 0, endMarker = 0; + + /* decode number of nodes */ + while (endMarker != 1) { + nNodes++; + if (nNodes >= 128) break; + endMarker = FDKreadBits(hBs, 1); + } + return nNodes; +} + +static void _decodeGains(HANDLE_FDK_BITSTREAM hBs, + const GAIN_CODING_PROFILE gainCodingProfile, + const int nNodes, GAIN_NODE* pNodes) { + int k, deltaGain; + Huffman deltaGainCodebook; + + pNodes[0].gainDb = _decodeGainInitial(hBs, gainCodingProfile); + + if (gainCodingProfile == GCP_CLIPPING_DUCKING) { + deltaGainCodebook = (Huffman)&deltaGain_codingProfile_2_huffman; + } else { + deltaGainCodebook = (Huffman)&deltaGain_codingProfile_0_1_huffman; + } + + for (k = 1; k < nNodes; k++) { + deltaGain = _decodeHuffmanCW(deltaGainCodebook, hBs); + if (k >= 16) continue; + /* gain_dB_e = 7 */ + pNodes[k].gainDb = + pNodes[k - 1].gainDb + + (FIXP_SGL)(deltaGain << (FRACT_BITS - 1 - 7 - + 3)); /* pNodes[k-1].gainDb + 0.125*deltaGain */ + } +} + +static void _decodeSlopes(HANDLE_FDK_BITSTREAM hBs, + const GAIN_INTERPOLATION_TYPE gainInterpolationType, + const int nNodes, GAIN_NODE* pNodes) { + int k = 0; + + if (gainInterpolationType == GIT_SPLINE) { + /* decode slope steepness */ + for (k = 0; k < nNodes; k++) { + _decodeHuffmanCW((Huffman)&slopeSteepness_huffman, hBs); + } + } +} + +static int _decodeTimeDelta(HANDLE_FDK_BITSTREAM hBs, const int Z) { + int prefix, mu; + + prefix = FDKreadBits(hBs, 2); + switch (prefix) { + case 0x0: + return 1; + case 0x1: + mu = FDKreadBits(hBs, 2); + return mu + 2; + case 0x2: + mu = FDKreadBits(hBs, 3); + return mu + 6; + case 0x3: + mu = FDKreadBits(hBs, Z); + return mu + 14; + default: + return 0; + } +} + +static void _decodeTimes(HANDLE_FDK_BITSTREAM hBs, const int deltaTmin, + const int frameSize, const int fullFrame, + const int timeOffset, const int Z, const int nNodes, + GAIN_NODE* pNodes) { + int timeDelta, k; + int timeOffs = timeOffset; + int frameEndFlag, nodeTimeTmp, nodeResFlag; + + if (fullFrame == 0) { + frameEndFlag = FDKreadBits(hBs, 1); + } else { + frameEndFlag = 1; + } + + if (frameEndFlag == + 1) { /* frameEndFlag == 1 signals that the last node is at the end of the + DRC frame */ + nodeResFlag = 0; + for (k = 0; k < nNodes - 1; k++) { + /* decode a delta time value */ + timeDelta = _decodeTimeDelta(hBs, Z); + if (k >= (16 - 1)) continue; + /* frameEndFlag == 1 needs special handling for last node with node + * reservoir */ + nodeTimeTmp = timeOffs + timeDelta * deltaTmin; + if (nodeTimeTmp > frameSize + timeOffset) { + if (nodeResFlag == 0) { + pNodes[k].time = frameSize + timeOffset; + nodeResFlag = 1; + } + pNodes[k + 1].time = nodeTimeTmp; + } else { + pNodes[k].time = nodeTimeTmp; + } + timeOffs = nodeTimeTmp; + } + if (nodeResFlag == 0) { + k = fMin(k, 16 - 1); + pNodes[k].time = frameSize + timeOffset; + } + } else { + for (k = 0; k < nNodes; k++) { + /* decode a delta time value */ + timeDelta = _decodeTimeDelta(hBs, Z); + if (k >= 16) continue; + pNodes[k].time = timeOffs + timeDelta * deltaTmin; + timeOffs = pNodes[k].time; + } + } +} + +static void _readNodes(HANDLE_FDK_BITSTREAM hBs, GAIN_SET* gainSet, + const int frameSize, const int timeDeltaMin, + UCHAR* pNNodes, GAIN_NODE* pNodes) { + int timeOffset, drcGainCodingMode, nNodes; + int Z = _getZ(frameSize / timeDeltaMin); + if (gainSet->timeAlignment == 0) { + timeOffset = -1; + } else { + timeOffset = -timeDeltaMin + + (timeDeltaMin - 1) / + 2; /* timeOffset = - deltaTmin + floor((deltaTmin-1)/2); */ + } + + drcGainCodingMode = FDKreadBits(hBs, 1); + if (drcGainCodingMode == 0) { + /* "simple" mode: only one node at the end of the frame with slope = 0 */ + nNodes = 1; + pNodes[0].gainDb = _decodeGainInitial( + hBs, (GAIN_CODING_PROFILE)gainSet->gainCodingProfile); + pNodes[0].time = frameSize + timeOffset; + } else { + nNodes = _decodeNNodes(hBs); + + _decodeSlopes(hBs, (GAIN_INTERPOLATION_TYPE)gainSet->gainInterpolationType, + nNodes, pNodes); + + _decodeTimes(hBs, timeDeltaMin, frameSize, gainSet->fullFrame, timeOffset, + Z, nNodes, pNodes); + + _decodeGains(hBs, (GAIN_CODING_PROFILE)gainSet->gainCodingProfile, nNodes, + pNodes); + } + *pNNodes = (UCHAR)nNodes; +} + +static void _readDrcGainSequence(HANDLE_FDK_BITSTREAM hBs, GAIN_SET* gainSet, + const int frameSize, const int timeDeltaMin, + UCHAR* pNNodes, GAIN_NODE pNodes[16]) { + SHORT timeBufPrevFrame[16], timeBufCurFrame[16]; + int nNodesNodeRes, nNodesCur, k, m; + + if (gainSet->gainCodingProfile == GCP_CONSTANT) { + *pNNodes = 1; + pNodes[0].time = frameSize - 1; + pNodes[0].gainDb = (FIXP_SGL)0; + } else { + _readNodes(hBs, gainSet, frameSize, timeDeltaMin, pNNodes, pNodes); + + /* count number of nodes in node reservoir */ + nNodesNodeRes = 0; + nNodesCur = 0; + /* count and buffer nodes from node reservoir */ + for (k = 0; k < *pNNodes; k++) { + if (k >= 16) continue; + if (pNodes[k].time >= frameSize) { + /* write node reservoir times into buffer */ + timeBufPrevFrame[nNodesNodeRes] = pNodes[k].time; + nNodesNodeRes++; + } else { /* times from current frame */ + timeBufCurFrame[nNodesCur] = pNodes[k].time; + nNodesCur++; + } + } + /* compose right time order (bit reservoir first) */ + for (k = 0; k < nNodesNodeRes; k++) { + /* subtract two time frameSize: one to remove node reservoir offset and + * one to get the negative index relative to the current frame + */ + pNodes[k].time = timeBufPrevFrame[k] - 2 * frameSize; + } + /* ...and times from current frame */ + for (m = 0; m < nNodesCur; m++, k++) { + pNodes[k].time = timeBufCurFrame[m]; + } + } +} + +static DRC_ERROR _readUniDrcGainExtension(HANDLE_FDK_BITSTREAM hBs, + UNI_DRC_GAIN_EXTENSION* pExt) { + DRC_ERROR err = DE_OK; + int k, bitSizeLen, extSizeBits, bitSize; + + k = 0; + pExt->uniDrcGainExtType[k] = FDKreadBits(hBs, 4); + while (pExt->uniDrcGainExtType[k] != UNIDRCGAINEXT_TERM) { + if (k >= (8 - 1)) return DE_MEMORY_ERROR; + bitSizeLen = FDKreadBits(hBs, 3); + extSizeBits = bitSizeLen + 4; + + bitSize = FDKreadBits(hBs, extSizeBits); + pExt->extBitSize[k] = bitSize + 1; + + switch (pExt->uniDrcGainExtType[k]) { + /* add future extensions here */ + default: + FDKpushFor(hBs, pExt->extBitSize[k]); + break; + } + k++; + pExt->uniDrcGainExtType[k] = FDKreadBits(hBs, 4); + } + + return err; +} + +DRC_ERROR +drcDec_readUniDrcGain(HANDLE_FDK_BITSTREAM hBs, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int frameSize, + const int deltaTminDefault, + HANDLE_UNI_DRC_GAIN hUniDrcGain) { + DRC_ERROR err = DE_OK; + int seq, gainSequenceCount; + DRC_COEFFICIENTS_UNI_DRC* pCoef = + selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); + if (hUniDrcGain == NULL) return DE_NOT_OK; + hUniDrcGain->status = 0; + if (pCoef) { + gainSequenceCount = fMin(pCoef->gainSequenceCount, (UCHAR)12); + } else { + gainSequenceCount = 0; + } + + for (seq = 0; seq < gainSequenceCount; seq++) { + UCHAR index = pCoef->gainSetIndexForGainSequence[seq]; + GAIN_SET* gainSet; + int timeDeltaMin; + UCHAR tmpNNodes = 0; + GAIN_NODE tmpNodes[16]; + + if ((index >= pCoef->gainSetCount) || (index >= 12)) return DE_NOT_OK; + gainSet = &(pCoef->gainSet[index]); + + timeDeltaMin = _getTimeDeltaMin(gainSet, deltaTminDefault); + + _readDrcGainSequence(hBs, gainSet, frameSize, timeDeltaMin, &tmpNNodes, + tmpNodes); + + hUniDrcGain->nNodes[seq] = tmpNNodes; + FDKmemcpy(hUniDrcGain->gainNode[seq], tmpNodes, + fMin(tmpNNodes, (UCHAR)16) * sizeof(GAIN_NODE)); + } + + if (pCoef && (gainSequenceCount == + pCoef->gainSequenceCount)) { /* all sequences have been read */ + hUniDrcGain->uniDrcGainExtPresent = FDKreadBits(hBs, 1); + if (hUniDrcGain->uniDrcGainExtPresent == 1) { + err = _readUniDrcGainExtension(hBs, &(hUniDrcGain->uniDrcGainExtension)); + if (err) return err; + } + } + + if (err == DE_OK && gainSequenceCount > 0) { + hUniDrcGain->status = 1; + } + return err; +} + +/****************/ +/* uniDrcConfig */ +/****************/ + +static void _decodeDuckingModification(HANDLE_FDK_BITSTREAM hBs, + DUCKING_MODIFICATION* pDMod, int isBox) { + int bsDuckingScaling, sigma, mu; + + if (isBox) FDKpushFor(hBs, 7); /* reserved */ + pDMod->duckingScalingPresent = FDKreadBits(hBs, 1); + + if (pDMod->duckingScalingPresent) { + if (isBox) FDKpushFor(hBs, 4); /* reserved */ + bsDuckingScaling = FDKreadBits(hBs, 4); + sigma = bsDuckingScaling >> 3; + mu = bsDuckingScaling & 0x7; + + if (sigma) { + pDMod->duckingScaling = (FIXP_SGL)( + (7 - mu) << (FRACT_BITS - 1 - 3 - 2)); /* 1.0 - 0.125 * (1 + mu); */ + } else { + pDMod->duckingScaling = (FIXP_SGL)( + (9 + mu) << (FRACT_BITS - 1 - 3 - 2)); /* 1.0 + 0.125 * (1 + mu); */ + } + } else { + pDMod->duckingScaling = (FIXP_SGL)(1 << (FRACT_BITS - 1 - 2)); /* 1.0 */ + } +} + +static void _decodeGainModification(HANDLE_FDK_BITSTREAM hBs, const int version, + int bandCount, GAIN_MODIFICATION* pGMod, + int isBox) { + int sign, bsGainOffset, bsAttenuationScaling, bsAmplificationScaling; + + if (version > 0) { + int b, shapeFilterPresent; + + if (isBox) { + FDKpushFor(hBs, 4); /* reserved */ + bandCount = FDKreadBits(hBs, 4); + } + + for (b = 0; b < bandCount; b++) { + if (isBox) { + FDKpushFor(hBs, 4); /* reserved */ + pGMod[b].targetCharacteristicLeftPresent = FDKreadBits(hBs, 1); + pGMod[b].targetCharacteristicRightPresent = FDKreadBits(hBs, 1); + pGMod[b].gainScalingPresent = FDKreadBits(hBs, 1); + pGMod[b].gainOffsetPresent = FDKreadBits(hBs, 1); + } + + if (!isBox) + pGMod[b].targetCharacteristicLeftPresent = FDKreadBits(hBs, 1); + if (pGMod[b].targetCharacteristicLeftPresent) { + if (isBox) FDKpushFor(hBs, 4); /* reserved */ + pGMod[b].targetCharacteristicLeftIndex = FDKreadBits(hBs, 4); + } + if (!isBox) + pGMod[b].targetCharacteristicRightPresent = FDKreadBits(hBs, 1); + if (pGMod[b].targetCharacteristicRightPresent) { + if (isBox) FDKpushFor(hBs, 4); /* reserved */ + pGMod[b].targetCharacteristicRightIndex = FDKreadBits(hBs, 4); + } + if (!isBox) pGMod[b].gainScalingPresent = FDKreadBits(hBs, 1); + if (pGMod[b].gainScalingPresent) { + bsAttenuationScaling = FDKreadBits(hBs, 4); + pGMod[b].attenuationScaling = (FIXP_SGL)( + bsAttenuationScaling + << (FRACT_BITS - 1 - 3 - 2)); /* bsAttenuationScaling * 0.125; */ + bsAmplificationScaling = FDKreadBits(hBs, 4); + pGMod[b].amplificationScaling = (FIXP_SGL)( + bsAmplificationScaling + << (FRACT_BITS - 1 - 3 - 2)); /* bsAmplificationScaling * 0.125; */ + } + if (!isBox) pGMod[b].gainOffsetPresent = FDKreadBits(hBs, 1); + if (pGMod[b].gainOffsetPresent) { + if (isBox) FDKpushFor(hBs, 2); /* reserved */ + sign = FDKreadBits(hBs, 1); + bsGainOffset = FDKreadBits(hBs, 5); + pGMod[b].gainOffset = (FIXP_SGL)( + (1 + bsGainOffset) + << (FRACT_BITS - 1 - 2 - 4)); /* (1+bsGainOffset) * 0.25; */ + if (sign) { + pGMod[b].gainOffset = -pGMod[b].gainOffset; + } + } + } + if (bandCount == 1) { + shapeFilterPresent = FDKreadBits(hBs, 1); + if (shapeFilterPresent) { + if (isBox) FDKpushFor(hBs, 3); /* reserved */ + FDKpushFor(hBs, 4); /* pGMod->shapeFilterIndex */ + } else { + if (isBox) FDKpushFor(hBs, 7); /* reserved */ + } + } + } else { + int b, gainScalingPresent, gainOffsetPresent; + FIXP_SGL attenuationScaling = FL2FXCONST_SGL(1.0f / (float)(1 << 2)), + amplificationScaling = FL2FXCONST_SGL(1.0f / (float)(1 << 2)), + gainOffset = (FIXP_SGL)0; + if (isBox) FDKpushFor(hBs, 7); /* reserved */ + gainScalingPresent = FDKreadBits(hBs, 1); + if (gainScalingPresent) { + bsAttenuationScaling = FDKreadBits(hBs, 4); + attenuationScaling = (FIXP_SGL)( + bsAttenuationScaling + << (FRACT_BITS - 1 - 3 - 2)); /* bsAttenuationScaling * 0.125; */ + bsAmplificationScaling = FDKreadBits(hBs, 4); + amplificationScaling = (FIXP_SGL)( + bsAmplificationScaling + << (FRACT_BITS - 1 - 3 - 2)); /* bsAmplificationScaling * 0.125; */ + } + if (isBox) FDKpushFor(hBs, 7); /* reserved */ + gainOffsetPresent = FDKreadBits(hBs, 1); + if (gainOffsetPresent) { + if (isBox) FDKpushFor(hBs, 2); /* reserved */ + sign = FDKreadBits(hBs, 1); + bsGainOffset = FDKreadBits(hBs, 5); + gainOffset = + (FIXP_SGL)((1 + bsGainOffset) << (FRACT_BITS - 1 - 2 - + 4)); /* (1+bsGainOffset) * 0.25; */ + if (sign) { + gainOffset = -gainOffset; + } + } + for (b = 0; b < 4; b++) { + pGMod[b].targetCharacteristicLeftPresent = 0; + pGMod[b].targetCharacteristicRightPresent = 0; + pGMod[b].gainScalingPresent = gainScalingPresent; + pGMod[b].attenuationScaling = attenuationScaling; + pGMod[b].amplificationScaling = amplificationScaling; + pGMod[b].gainOffsetPresent = gainOffsetPresent; + pGMod[b].gainOffset = gainOffset; + } + } +} + +static void _readDrcCharacteristic(HANDLE_FDK_BITSTREAM hBs, const int version, + DRC_CHARACTERISTIC* pDChar, int isBox) { + if (version == 0) { + if (isBox) FDKpushFor(hBs, 1); /* reserved */ + pDChar->cicpIndex = FDKreadBits(hBs, 7); + if (pDChar->cicpIndex > 0) { + pDChar->present = 1; + pDChar->isCICP = 1; + } else { + pDChar->present = 0; + } + } else { + pDChar->present = FDKreadBits(hBs, 1); + if (isBox) pDChar->isCICP = FDKreadBits(hBs, 1); + if (pDChar->present) { + if (!isBox) pDChar->isCICP = FDKreadBits(hBs, 1); + if (pDChar->isCICP) { + if (isBox) FDKpushFor(hBs, 1); /* reserved */ + pDChar->cicpIndex = FDKreadBits(hBs, 7); + } else { + pDChar->custom.left = FDKreadBits(hBs, 4); + pDChar->custom.right = FDKreadBits(hBs, 4); + } + } + } +} + +static void _readBandBorder(HANDLE_FDK_BITSTREAM hBs, BAND_BORDER* pBBord, + int drcBandType, int isBox) { + if (drcBandType) { + if (isBox) FDKpushFor(hBs, 4); /* reserved */ + pBBord->crossoverFreqIndex = FDKreadBits(hBs, 4); + } else { + if (isBox) FDKpushFor(hBs, 6); /* reserved */ + pBBord->startSubBandIndex = FDKreadBits(hBs, 10); + } +} + +static DRC_ERROR _readGainSet(HANDLE_FDK_BITSTREAM hBs, const int version, + int* gainSequenceIndex, GAIN_SET* pGSet, + int isBox) { + if (isBox) FDKpushFor(hBs, 2); /* reserved */ + pGSet->gainCodingProfile = FDKreadBits(hBs, 2); + pGSet->gainInterpolationType = FDKreadBits(hBs, 1); + pGSet->fullFrame = FDKreadBits(hBs, 1); + pGSet->timeAlignment = FDKreadBits(hBs, 1); + pGSet->timeDeltaMinPresent = FDKreadBits(hBs, 1); + + if (pGSet->timeDeltaMinPresent) { + int bsTimeDeltaMin; + if (isBox) FDKpushFor(hBs, 5); /* reserved */ + bsTimeDeltaMin = FDKreadBits(hBs, 11); + pGSet->timeDeltaMin = bsTimeDeltaMin + 1; + } + + if (pGSet->gainCodingProfile != GCP_CONSTANT) { + int i; + if (isBox) FDKpushFor(hBs, 3); /* reserved */ + pGSet->bandCount = FDKreadBits(hBs, 4); + if (pGSet->bandCount > 4) return DE_MEMORY_ERROR; + + if ((pGSet->bandCount > 1) || isBox) { + pGSet->drcBandType = FDKreadBits(hBs, 1); + } + + for (i = 0; i < pGSet->bandCount; i++) { + if (version == 0) { + *gainSequenceIndex = (*gainSequenceIndex) + 1; + } else { + int indexPresent; + indexPresent = (isBox) ? 1 : FDKreadBits(hBs, 1); + if (indexPresent) { + int bsIndex; + bsIndex = FDKreadBits(hBs, 6); + *gainSequenceIndex = bsIndex; + } else { + *gainSequenceIndex = (*gainSequenceIndex) + 1; + } + } + pGSet->gainSequenceIndex[i] = *gainSequenceIndex; + _readDrcCharacteristic(hBs, version, &(pGSet->drcCharacteristic[i]), + isBox); + } + for (i = 1; i < pGSet->bandCount; i++) { + _readBandBorder(hBs, &(pGSet->bandBorder[i]), pGSet->drcBandType, isBox); + } + } else { + pGSet->bandCount = 1; + *gainSequenceIndex = (*gainSequenceIndex) + 1; + pGSet->gainSequenceIndex[0] = *gainSequenceIndex; + } + + return DE_OK; +} + +static DRC_ERROR _readCustomDrcCharacteristic(HANDLE_FDK_BITSTREAM hBs, + const CHARACTERISTIC_SIDE side, + UCHAR* pCharacteristicFormat, + CUSTOM_DRC_CHAR* pCChar, + int isBox) { + if (isBox) FDKpushFor(hBs, 7); /* reserved */ + *pCharacteristicFormat = FDKreadBits(hBs, 1); + if (*pCharacteristicFormat == CF_SIGMOID) { + int bsGain, bsIoRatio, bsExp; + if (isBox) FDKpushFor(hBs, 1); /* reserved */ + bsGain = FDKreadBits(hBs, 6); + if (side == CS_LEFT) { + pCChar->sigmoid.gain = (FIXP_SGL)(bsGain << (FRACT_BITS - 1 - 6)); + } else { + pCChar->sigmoid.gain = (FIXP_SGL)(-bsGain << (FRACT_BITS - 1 - 6)); + } + bsIoRatio = FDKreadBits(hBs, 4); + /* pCChar->sigmoid.ioRatio = 0.05 + 0.15 * bsIoRatio; */ + pCChar->sigmoid.ioRatio = + FL2FXCONST_SGL(0.05f / (float)(1 << 2)) + + (FIXP_SGL)((((3 * bsIoRatio) << (FRACT_BITS - 1)) / 5) >> 4); + bsExp = FDKreadBits(hBs, 4); + if (bsExp < 15) { + pCChar->sigmoid.exp = (FIXP_SGL)((1 + 2 * bsExp) << (FRACT_BITS - 1 - 5)); + } else { + pCChar->sigmoid.exp = (FIXP_SGL)MAXVAL_SGL; /* represents infinity */ + } + pCChar->sigmoid.flipSign = FDKreadBits(hBs, 1); + } else { /* CF_NODES */ + int i, bsCharacteristicNodeCount, bsNodeLevelDelta, bsNodeGain; + if (isBox) FDKpushFor(hBs, 6); /* reserved */ + bsCharacteristicNodeCount = FDKreadBits(hBs, 2); + pCChar->nodes.characteristicNodeCount = bsCharacteristicNodeCount + 1; + if (pCChar->nodes.characteristicNodeCount > 4) return DE_MEMORY_ERROR; + pCChar->nodes.nodeLevel[0] = DRC_INPUT_LOUDNESS_TARGET_SGL; + pCChar->nodes.nodeGain[0] = (FIXP_SGL)0; + for (i = 0; i < pCChar->nodes.characteristicNodeCount; i++) { + if (isBox) FDKpushFor(hBs, 3); /* reserved */ + bsNodeLevelDelta = FDKreadBits(hBs, 5); + if (side == CS_LEFT) { + pCChar->nodes.nodeLevel[i + 1] = + pCChar->nodes.nodeLevel[i] - + (FIXP_SGL)((1 + bsNodeLevelDelta) << (FRACT_BITS - 1 - 7)); + } else { + pCChar->nodes.nodeLevel[i + 1] = + pCChar->nodes.nodeLevel[i] + + (FIXP_SGL)((1 + bsNodeLevelDelta) << (FRACT_BITS - 1 - 7)); + } + bsNodeGain = FDKreadBits(hBs, 8); + pCChar->nodes.nodeGain[i + 1] = (FIXP_SGL)( + (bsNodeGain - 128) + << (FRACT_BITS - 1 - 1 - 7)); /* 0.5f * bsNodeGain - 64.0f; */ + } + } + return DE_OK; +} + +static void _skipLoudEqInstructions(HANDLE_FDK_BITSTREAM hBs) { + int i; + int downmixIdPresent, additionalDownmixIdPresent, + additionalDownmixIdCount = 0; + int drcSetIdPresent, additionalDrcSetIdPresent, additionalDrcSetIdCount = 0; + int eqSetIdPresent, additionalEqSetIdPresent, additionalEqSetIdCount = 0; + int loudEqGainSequenceCount, drcCharacteristicFormatIsCICP; + + FDKpushFor(hBs, 4); /* loudEqSetId */ + FDKpushFor(hBs, 4); /* drcLocation */ + downmixIdPresent = FDKreadBits(hBs, 1); + if (downmixIdPresent) { + FDKpushFor(hBs, 7); /* downmixId */ + additionalDownmixIdPresent = FDKreadBits(hBs, 1); + if (additionalDownmixIdPresent) { + additionalDownmixIdCount = FDKreadBits(hBs, 7); + for (i = 0; i < additionalDownmixIdCount; i++) { + FDKpushFor(hBs, 7); /* additionalDownmixId */ + } + } + } + + drcSetIdPresent = FDKreadBits(hBs, 1); + if (drcSetIdPresent) { + FDKpushFor(hBs, 6); /* drcSetId */ + additionalDrcSetIdPresent = FDKreadBits(hBs, 1); + if (additionalDrcSetIdPresent) { + additionalDrcSetIdCount = FDKreadBits(hBs, 6); + for (i = 0; i < additionalDrcSetIdCount; i++) { + FDKpushFor(hBs, 6); /* additionalDrcSetId; */ + } + } + } + + eqSetIdPresent = FDKreadBits(hBs, 1); + if (eqSetIdPresent) { + FDKpushFor(hBs, 6); /* eqSetId */ + additionalEqSetIdPresent = FDKreadBits(hBs, 1); + if (additionalEqSetIdPresent) { + additionalEqSetIdCount = FDKreadBits(hBs, 6); + for (i = 0; i < additionalEqSetIdCount; i++) { + FDKpushFor(hBs, 6); /* additionalEqSetId; */ + } + } + } + + FDKpushFor(hBs, 1); /* loudnessAfterDrc */ + FDKpushFor(hBs, 1); /* loudnessAfterEq */ + loudEqGainSequenceCount = FDKreadBits(hBs, 6); + for (i = 0; i < loudEqGainSequenceCount; i++) { + FDKpushFor(hBs, 6); /* gainSequenceIndex */ + drcCharacteristicFormatIsCICP = FDKreadBits(hBs, 1); + if (drcCharacteristicFormatIsCICP) { + FDKpushFor(hBs, 7); /* drcCharacteristic */ + } else { + FDKpushFor(hBs, 4); /* drcCharacteristicLeftIndex */ + FDKpushFor(hBs, 4); /* drcCharacteristicRightIndex */ + } + FDKpushFor(hBs, 6); /* frequencyRangeIndex */ + FDKpushFor(hBs, 3); /* bsLoudEqScaling */ + FDKpushFor(hBs, 5); /* bsLoudEqOffset */ + } +} + +static void _skipEqSubbandGainSpline(HANDLE_FDK_BITSTREAM hBs) { + int nEqNodes, k, bits; + nEqNodes = FDKreadBits(hBs, 5); + nEqNodes += 2; + for (k = 0; k < nEqNodes; k++) { + bits = FDKreadBits(hBs, 1); + if (!bits) { + FDKpushFor(hBs, 4); + } + } + FDKpushFor(hBs, 4 * (nEqNodes - 1)); + bits = FDKreadBits(hBs, 2); + switch (bits) { + case 0: + FDKpushFor(hBs, 5); + break; + case 1: + case 2: + FDKpushFor(hBs, 4); + break; + case 3: + FDKpushFor(hBs, 3); + break; + } + FDKpushFor(hBs, 5 * (nEqNodes - 1)); +} + +static void _skipEqCoefficients(HANDLE_FDK_BITSTREAM hBs) { + int j, k; + int eqDelayMaxPresent; + int uniqueFilterBlockCount, filterElementCount, filterElementGainPresent; + int uniqueTdFilterElementCount, eqFilterFormat, bsRealZeroRadiusOneCount, + realZeroCount, genericZeroCount, realPoleCount, complexPoleCount, + firFilterOrder; + int uniqueEqSubbandGainsCount, eqSubbandGainRepresentation, + eqSubbandGainCount; + int eqSubbandGainFormat; + + eqDelayMaxPresent = FDKreadBits(hBs, 1); + if (eqDelayMaxPresent) { + FDKpushFor(hBs, 8); /* bsEqDelayMax */ + } + + uniqueFilterBlockCount = FDKreadBits(hBs, 6); + for (j = 0; j < uniqueFilterBlockCount; j++) { + filterElementCount = FDKreadBits(hBs, 6); + for (k = 0; k < filterElementCount; k++) { + FDKpushFor(hBs, 6); /* filterElementIndex */ + filterElementGainPresent = FDKreadBits(hBs, 1); + if (filterElementGainPresent) { + FDKpushFor(hBs, 10); /* bsFilterElementGain */ + } + } + } + uniqueTdFilterElementCount = FDKreadBits(hBs, 6); + for (j = 0; j < uniqueTdFilterElementCount; j++) { + eqFilterFormat = FDKreadBits(hBs, 1); + if (eqFilterFormat == 0) { /* pole/zero */ + bsRealZeroRadiusOneCount = FDKreadBits(hBs, 3); + realZeroCount = FDKreadBits(hBs, 6); + genericZeroCount = FDKreadBits(hBs, 6); + realPoleCount = FDKreadBits(hBs, 4); + complexPoleCount = FDKreadBits(hBs, 4); + FDKpushFor(hBs, 2 * bsRealZeroRadiusOneCount * 1); + FDKpushFor(hBs, realZeroCount * 8); + FDKpushFor(hBs, genericZeroCount * 14); + FDKpushFor(hBs, realPoleCount * 8); + FDKpushFor(hBs, complexPoleCount * 14); + } else { /* FIR coefficients */ + firFilterOrder = FDKreadBits(hBs, 7); + FDKpushFor(hBs, 1); + FDKpushFor(hBs, (firFilterOrder / 2 + 1) * 11); + } + } + uniqueEqSubbandGainsCount = FDKreadBits(hBs, 6); + if (uniqueEqSubbandGainsCount > 0) { + eqSubbandGainRepresentation = FDKreadBits(hBs, 1); + eqSubbandGainFormat = FDKreadBits(hBs, 4); + switch (eqSubbandGainFormat) { + case GF_QMF32: + eqSubbandGainCount = 32; + break; + case GF_QMFHYBRID39: + eqSubbandGainCount = 39; + break; + case GF_QMF64: + eqSubbandGainCount = 64; + break; + case GF_QMFHYBRID71: + eqSubbandGainCount = 71; + break; + case GF_QMF128: + eqSubbandGainCount = 128; + break; + case GF_QMFHYBRID135: + eqSubbandGainCount = 135; + break; + case GF_UNIFORM: + default: + eqSubbandGainCount = FDKreadBits(hBs, 8); + eqSubbandGainCount++; + break; + } + for (k = 0; k < uniqueEqSubbandGainsCount; k++) { + if (eqSubbandGainRepresentation == 1) { + _skipEqSubbandGainSpline(hBs); + } else { + FDKpushFor(hBs, eqSubbandGainCount * 9); + } + } + } +} + +static void _skipTdFilterCascade(HANDLE_FDK_BITSTREAM hBs, + const int eqChannelGroupCount) { + int i, eqCascadeGainPresent, filterBlockCount, eqPhaseAlignmentPresent; + for (i = 0; i < eqChannelGroupCount; i++) { + eqCascadeGainPresent = FDKreadBits(hBs, 1); + if (eqCascadeGainPresent) { + FDKpushFor(hBs, 10); /* bsEqCascadeGain */ + } + filterBlockCount = FDKreadBits(hBs, 4); + FDKpushFor(hBs, filterBlockCount * 7); /* filterBlockIndex */ + } + eqPhaseAlignmentPresent = FDKreadBits(hBs, 1); + { + if (eqPhaseAlignmentPresent) { + for (i = 0; i < eqChannelGroupCount; i++) { + FDKpushFor(hBs, (eqChannelGroupCount - i - 1) * 1); + } + } + } +} + +static DRC_ERROR _skipEqInstructions(HANDLE_FDK_BITSTREAM hBs, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { + DRC_ERROR err = DE_OK; + int c, i, k, channelCount; + int downmixIdPresent, downmixId, eqApplyToDownmix, additionalDownmixIdPresent, + additionalDownmixIdCount = 0; + int additionalDrcSetIdPresent, additionalDrcSetIdCount; + int dependsOnEqSetPresent, eqChannelGroupCount, tdFilterCascadePresent, + subbandGainsPresent, eqTransitionDurationPresent; + UCHAR eqChannelGroupForChannel[8]; + + FDKpushFor(hBs, 6); /* eqSetId */ + FDKpushFor(hBs, 4); /* eqSetComplexityLevel */ + downmixIdPresent = FDKreadBits(hBs, 1); + if (downmixIdPresent) { + downmixId = FDKreadBits(hBs, 7); + eqApplyToDownmix = FDKreadBits(hBs, 1); + additionalDownmixIdPresent = FDKreadBits(hBs, 1); + if (additionalDownmixIdPresent) { + additionalDownmixIdCount = FDKreadBits(hBs, 7); + FDKpushFor(hBs, additionalDownmixIdCount * 7); /* additionalDownmixId */ + } + } else { + downmixId = 0; + eqApplyToDownmix = 0; + } + FDKpushFor(hBs, 6); /* drcSetId */ + additionalDrcSetIdPresent = FDKreadBits(hBs, 1); + if (additionalDrcSetIdPresent) { + additionalDrcSetIdCount = FDKreadBits(hBs, 6); + for (i = 0; i < additionalDrcSetIdCount; i++) { + FDKpushFor(hBs, 6); /* additionalDrcSetId */ + } + } + FDKpushFor(hBs, 16); /* eqSetPurpose */ + dependsOnEqSetPresent = FDKreadBits(hBs, 1); + if (dependsOnEqSetPresent) { + FDKpushFor(hBs, 6); /* dependsOnEqSet */ + } else { + FDKpushFor(hBs, 1); /* noIndependentEqUse */ + } + + channelCount = hUniDrcConfig->channelLayout.baseChannelCount; + if ((downmixIdPresent == 1) && (eqApplyToDownmix == 1) && (downmixId != 0) && + (downmixId != DOWNMIX_ID_ANY_DOWNMIX) && + (additionalDownmixIdCount == 0)) { + DOWNMIX_INSTRUCTIONS* pDown = + selectDownmixInstructions(hUniDrcConfig, downmixId); + if (pDown == NULL) return DE_NOT_OK; + + channelCount = + pDown->targetChannelCount; /* targetChannelCountFromDownmixId*/ + } else if ((downmixId == DOWNMIX_ID_ANY_DOWNMIX) || + (additionalDownmixIdCount > 1)) { + channelCount = 1; + } + + eqChannelGroupCount = 0; + for (c = 0; c < channelCount; c++) { + int newGroup = 1; + if (c >= 8) return DE_MEMORY_ERROR; + eqChannelGroupForChannel[c] = FDKreadBits(hBs, 7); + for (k = 0; k < c; k++) { + if (eqChannelGroupForChannel[c] == eqChannelGroupForChannel[k]) { + newGroup = 0; + } + } + if (newGroup == 1) { + eqChannelGroupCount += 1; + } + } + tdFilterCascadePresent = FDKreadBits(hBs, 1); + if (tdFilterCascadePresent) { + _skipTdFilterCascade(hBs, eqChannelGroupCount); + } + subbandGainsPresent = FDKreadBits(hBs, 1); + if (subbandGainsPresent) { + FDKpushFor(hBs, eqChannelGroupCount * 6); /* subbandGainsIndex */ + } + eqTransitionDurationPresent = FDKreadBits(hBs, 1); + if (eqTransitionDurationPresent) { + FDKpushFor(hBs, 5); /* bsEqTransitionDuration */ + } + return err; +} + +static void _skipDrcCoefficientsBasic(HANDLE_FDK_BITSTREAM hBs) { + FDKpushFor(hBs, 4); /* drcLocation */ + FDKpushFor(hBs, 7); /* drcCharacteristic */ +} + +static DRC_ERROR _readDrcCoefficientsUniDrc(HANDLE_FDK_BITSTREAM hBs, + const int version, + DRC_COEFFICIENTS_UNI_DRC* pCoef) { + DRC_ERROR err = DE_OK; + int i, bsDrcFrameSize; + int gainSequenceIndex = -1; + + pCoef->drcLocation = FDKreadBits(hBs, 4); + pCoef->drcFrameSizePresent = FDKreadBits(hBs, 1); + + if (pCoef->drcFrameSizePresent == 1) { + bsDrcFrameSize = FDKreadBits(hBs, 15); + pCoef->drcFrameSize = bsDrcFrameSize + 1; + } + if (version == 0) { + int gainSequenceCount = 0, gainSetCount; + pCoef->characteristicLeftCount = 0; + pCoef->characteristicRightCount = 0; + gainSetCount = FDKreadBits(hBs, 6); + pCoef->gainSetCount = fMin(gainSetCount, 12); + for (i = 0; i < gainSetCount; i++) { + GAIN_SET tmpGset; + FDKmemclear(&tmpGset, sizeof(GAIN_SET)); + err = _readGainSet(hBs, version, &gainSequenceIndex, &tmpGset, 0); + if (err) return err; + gainSequenceCount += tmpGset.bandCount; + + if (i >= 12) continue; + pCoef->gainSet[i] = tmpGset; + } + pCoef->gainSequenceCount = gainSequenceCount; + } else { /* (version == 1) */ + UCHAR drcCharacteristicLeftPresent, drcCharacteristicRightPresent; + UCHAR shapeFiltersPresent, shapeFilterCount, tmpPresent; + int gainSetCount; + drcCharacteristicLeftPresent = FDKreadBits(hBs, 1); + if (drcCharacteristicLeftPresent) { + pCoef->characteristicLeftCount = FDKreadBits(hBs, 4); + if ((pCoef->characteristicLeftCount + 1) > 16) return DE_MEMORY_ERROR; + for (i = 0; i < pCoef->characteristicLeftCount; i++) { + err = _readCustomDrcCharacteristic( + hBs, CS_LEFT, &(pCoef->characteristicLeftFormat[i + 1]), + &(pCoef->customCharacteristicLeft[i + 1]), 0); + if (err) return err; + } + } + drcCharacteristicRightPresent = FDKreadBits(hBs, 1); + if (drcCharacteristicRightPresent) { + pCoef->characteristicRightCount = FDKreadBits(hBs, 4); + if ((pCoef->characteristicRightCount + 1) > 16) return DE_MEMORY_ERROR; + for (i = 0; i < pCoef->characteristicRightCount; i++) { + err = _readCustomDrcCharacteristic( + hBs, CS_RIGHT, &(pCoef->characteristicRightFormat[i + 1]), + &(pCoef->customCharacteristicRight[i + 1]), 0); + if (err) return err; + } + } + shapeFiltersPresent = FDKreadBits(hBs, 1); + if (shapeFiltersPresent) { + shapeFilterCount = FDKreadBits(hBs, 4); + for (i = 0; i < shapeFilterCount; i++) { + tmpPresent = FDKreadBits(hBs, 1); + if (tmpPresent) /* lfCutParams */ + FDKpushFor(hBs, 5); + + tmpPresent = FDKreadBits(hBs, 1); + if (tmpPresent) /* lfBoostParams */ + FDKpushFor(hBs, 5); + + tmpPresent = FDKreadBits(hBs, 1); + if (tmpPresent) /* hfCutParams */ + FDKpushFor(hBs, 5); + + tmpPresent = FDKreadBits(hBs, 1); + if (tmpPresent) /* hfBoostParams */ + FDKpushFor(hBs, 5); + } + } + pCoef->gainSequenceCount = FDKreadBits(hBs, 6); + gainSetCount = FDKreadBits(hBs, 6); + pCoef->gainSetCount = fMin(gainSetCount, 12); + for (i = 0; i < gainSetCount; i++) { + GAIN_SET tmpGset; + FDKmemclear(&tmpGset, sizeof(GAIN_SET)); + err = _readGainSet(hBs, version, &gainSequenceIndex, &tmpGset, 0); + if (err) return err; + + if (i >= 12) continue; + pCoef->gainSet[i] = tmpGset; + } + } + for (i = 0; i < 12; i++) { + pCoef->gainSetIndexForGainSequence[i] = 255; + } + for (i = 0; i < pCoef->gainSetCount; i++) { + int b; + for (b = 0; b < pCoef->gainSet[i].bandCount; b++) { + if (pCoef->gainSet[i].gainSequenceIndex[b] >= 12) continue; + pCoef->gainSetIndexForGainSequence[pCoef->gainSet[i] + .gainSequenceIndex[b]] = i; + } + } + + return err; +} + +static void _skipDrcInstructionsBasic(HANDLE_FDK_BITSTREAM hBs) { + int drcSetEffect; + int additionalDownmixIdPresent, additionalDownmixIdCount, + limiterPeakTargetPresent; + int drcSetTargetLoudnessPresent, drcSetTargetLoudnessValueLowerPresent; + + FDKpushFor(hBs, 6); /* drcSetId */ + FDKpushFor(hBs, 4); /* drcLocation */ + FDKpushFor(hBs, 7); /* downmixId */ + additionalDownmixIdPresent = FDKreadBits(hBs, 1); + if (additionalDownmixIdPresent) { + additionalDownmixIdCount = FDKreadBits(hBs, 3); + FDKpushFor(hBs, 7 * additionalDownmixIdCount); /* additionalDownmixId */ + } + + drcSetEffect = FDKreadBits(hBs, 16); + if (!(drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF))) { + limiterPeakTargetPresent = FDKreadBits(hBs, 1); + if (limiterPeakTargetPresent) { + FDKpushFor(hBs, 8); /* bsLimiterPeakTarget */ + } + } + + drcSetTargetLoudnessPresent = FDKreadBits(hBs, 1); + if (drcSetTargetLoudnessPresent) { + FDKpushFor(hBs, 6); /* bsDrcSetTargetLoudnessValueUpper */ + drcSetTargetLoudnessValueLowerPresent = FDKreadBits(hBs, 1); + if (drcSetTargetLoudnessValueLowerPresent) { + FDKpushFor(hBs, 6); /* bsDrcSetTargetLoudnessValueLower */ + } + } +} + +static DRC_ERROR _readDrcInstructionsUniDrc(HANDLE_FDK_BITSTREAM hBs, + const int version, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + DRC_INSTRUCTIONS_UNI_DRC* pInst) { + DRC_ERROR err = DE_OK; + int i, g, c; + int downmixIdPresent, additionalDownmixIdPresent, additionalDownmixIdCount; + int bsLimiterPeakTarget, channelCount; + DRC_COEFFICIENTS_UNI_DRC* pCoef = NULL; + int repeatParameters, bsRepeatParametersCount; + int repeatSequenceIndex, bsRepeatSequenceCount; + SCHAR* gainSetIndex = pInst->gainSetIndex; + SCHAR channelGroupForChannel[8]; + DUCKING_MODIFICATION duckingModificationForChannelGroup[8]; + + pInst->drcSetId = FDKreadBits(hBs, 6); + if (version == 0) { + /* Assume all v0 DRC sets to be manageable in terms of complexity */ + pInst->drcSetComplexityLevel = 2; + } else { + pInst->drcSetComplexityLevel = FDKreadBits(hBs, 4); + } + pInst->drcLocation = FDKreadBits(hBs, 4); + if (version == 0) { + downmixIdPresent = 1; + } else { + downmixIdPresent = FDKreadBits(hBs, 1); + } + if (downmixIdPresent) { + pInst->downmixId[0] = FDKreadBits(hBs, 7); + if (version == 0) { + if (pInst->downmixId[0] == 0) + pInst->drcApplyToDownmix = 0; + else + pInst->drcApplyToDownmix = 1; + } else { + pInst->drcApplyToDownmix = FDKreadBits(hBs, 1); + } + + additionalDownmixIdPresent = FDKreadBits(hBs, 1); + if (additionalDownmixIdPresent) { + additionalDownmixIdCount = FDKreadBits(hBs, 3); + if ((1 + additionalDownmixIdCount) > 8) return DE_MEMORY_ERROR; + for (i = 0; i < additionalDownmixIdCount; i++) { + pInst->downmixId[i + 1] = FDKreadBits(hBs, 7); + } + pInst->downmixIdCount = 1 + additionalDownmixIdCount; + } else { + pInst->downmixIdCount = 1; + } + } else { + pInst->downmixId[0] = 0; + pInst->downmixIdCount = 1; + } + + pInst->drcSetEffect = FDKreadBits(hBs, 16); + + if ((pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) == 0) { + pInst->limiterPeakTargetPresent = FDKreadBits(hBs, 1); + if (pInst->limiterPeakTargetPresent) { + bsLimiterPeakTarget = FDKreadBits(hBs, 8); + pInst->limiterPeakTarget = -(FIXP_SGL)( + bsLimiterPeakTarget + << (FRACT_BITS - 1 - 3 - 5)); /* - bsLimiterPeakTarget * 0.125; */ + } + } + + pInst->drcSetTargetLoudnessPresent = FDKreadBits(hBs, 1); + + /* set default values */ + pInst->drcSetTargetLoudnessValueUpper = 0; + pInst->drcSetTargetLoudnessValueLower = -63; + + if (pInst->drcSetTargetLoudnessPresent == 1) { + int bsDrcSetTargetLoudnessValueUpper, bsDrcSetTargetLoudnessValueLower; + int drcSetTargetLoudnessValueLowerPresent; + bsDrcSetTargetLoudnessValueUpper = FDKreadBits(hBs, 6); + pInst->drcSetTargetLoudnessValueUpper = + bsDrcSetTargetLoudnessValueUpper - 63; + drcSetTargetLoudnessValueLowerPresent = FDKreadBits(hBs, 1); + if (drcSetTargetLoudnessValueLowerPresent == 1) { + bsDrcSetTargetLoudnessValueLower = FDKreadBits(hBs, 6); + pInst->drcSetTargetLoudnessValueLower = + bsDrcSetTargetLoudnessValueLower - 63; + } + } + + pInst->dependsOnDrcSetPresent = FDKreadBits(hBs, 1); + + pInst->noIndependentUse = 0; + if (pInst->dependsOnDrcSetPresent) { + pInst->dependsOnDrcSet = FDKreadBits(hBs, 6); + } else { + pInst->noIndependentUse = FDKreadBits(hBs, 1); + } + + if (version == 0) { + pInst->requiresEq = 0; + } else { + pInst->requiresEq = FDKreadBits(hBs, 1); + } + + pCoef = selectDrcCoefficients(hUniDrcConfig, pInst->drcLocation); + + pInst->drcChannelCount = channelCount = + hUniDrcConfig->channelLayout.baseChannelCount; + + if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { + DUCKING_MODIFICATION* pDModForChannel = + pInst->duckingModificationForChannel; + c = 0; + while (c < channelCount) { + int bsGainSetIndex; + bsGainSetIndex = FDKreadBits(hBs, 6); + if (c >= 8) return DE_MEMORY_ERROR; + gainSetIndex[c] = bsGainSetIndex - 1; + _decodeDuckingModification(hBs, &(pDModForChannel[c]), 0); + + c++; + repeatParameters = FDKreadBits(hBs, 1); + if (repeatParameters == 1) { + bsRepeatParametersCount = FDKreadBits(hBs, 5); + bsRepeatParametersCount += 1; + for (i = 0; i < bsRepeatParametersCount; i++) { + if (c >= 8) return DE_MEMORY_ERROR; + gainSetIndex[c] = gainSetIndex[c - 1]; + pDModForChannel[c] = pDModForChannel[c - 1]; + c++; + } + } + } + if (c > channelCount) { + return DE_NOT_OK; + } + + err = deriveDrcChannelGroups( + pInst->drcSetEffect, pInst->drcChannelCount, gainSetIndex, + pDModForChannel, &pInst->nDrcChannelGroups, + pInst->gainSetIndexForChannelGroup, channelGroupForChannel, + duckingModificationForChannelGroup); + if (err) return (err); + } else { + int deriveChannelCount = 0; + if (((version == 0) || (pInst->drcApplyToDownmix != 0)) && + (pInst->downmixId[0] != DOWNMIX_ID_BASE_LAYOUT) && + (pInst->downmixId[0] != DOWNMIX_ID_ANY_DOWNMIX) && + (pInst->downmixIdCount == 1)) { + if (hUniDrcConfig->downmixInstructionsCount != 0) { + DOWNMIX_INSTRUCTIONS* pDown = + selectDownmixInstructions(hUniDrcConfig, pInst->downmixId[0]); + if (pDown == NULL) return DE_NOT_OK; + pInst->drcChannelCount = channelCount = + pDown->targetChannelCount; /* targetChannelCountFromDownmixId*/ + } else { + deriveChannelCount = 1; + channelCount = 1; + } + } else if (((version == 0) || (pInst->drcApplyToDownmix != 0)) && + ((pInst->downmixId[0] == DOWNMIX_ID_ANY_DOWNMIX) || + (pInst->downmixIdCount > 1))) { + /* Set maximum channel count as upper border. The effective channel count + * is set at the process function. */ + pInst->drcChannelCount = 8; + channelCount = 1; + } + + c = 0; + while (c < channelCount) { + int bsGainSetIndex; + bsGainSetIndex = FDKreadBits(hBs, 6); + if (c >= 8) return DE_MEMORY_ERROR; + gainSetIndex[c] = bsGainSetIndex - 1; + c++; + repeatSequenceIndex = FDKreadBits(hBs, 1); + + if (repeatSequenceIndex == 1) { + bsRepeatSequenceCount = FDKreadBits(hBs, 5); + bsRepeatSequenceCount += 1; + if (deriveChannelCount) { + channelCount = 1 + bsRepeatSequenceCount; + } + for (i = 0; i < bsRepeatSequenceCount; i++) { + if (c >= 8) return DE_MEMORY_ERROR; + gainSetIndex[c] = bsGainSetIndex - 1; + c++; + } + } + } + if (c > channelCount) { + return DE_NOT_OK; + } + if (deriveChannelCount) { + pInst->drcChannelCount = channelCount; + } + + /* DOWNMIX_ID_ANY_DOWNMIX: channelCount is 1. Distribute gainSetIndex to all + * channels. */ + if ((pInst->downmixId[0] == DOWNMIX_ID_ANY_DOWNMIX) || + (pInst->downmixIdCount > 1)) { + for (c = 1; c < pInst->drcChannelCount; c++) { + gainSetIndex[c] = gainSetIndex[0]; + } + } + + err = deriveDrcChannelGroups(pInst->drcSetEffect, pInst->drcChannelCount, + gainSetIndex, NULL, &pInst->nDrcChannelGroups, + pInst->gainSetIndexForChannelGroup, + channelGroupForChannel, NULL); + if (err) return (err); + + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + int set, bandCount; + set = pInst->gainSetIndexForChannelGroup[g]; + + /* get bandCount */ + if (pCoef != NULL && set < pCoef->gainSetCount) { + bandCount = pCoef->gainSet[set].bandCount; + } else { + bandCount = 1; + } + + _decodeGainModification(hBs, version, bandCount, + pInst->gainModificationForChannelGroup[g], 0); + } + } + + return err; +} + +static DRC_ERROR _readChannelLayout(HANDLE_FDK_BITSTREAM hBs, + CHANNEL_LAYOUT* pChan) { + DRC_ERROR err = DE_OK; + + pChan->baseChannelCount = FDKreadBits(hBs, 7); + + if (pChan->baseChannelCount > 8) return DE_NOT_OK; + + pChan->layoutSignalingPresent = FDKreadBits(hBs, 1); + + if (pChan->layoutSignalingPresent) { + pChan->definedLayout = FDKreadBits(hBs, 8); + + if (pChan->definedLayout == 0) { + int i; + for (i = 0; i < pChan->baseChannelCount; i++) { + if (i < 8) { + pChan->speakerPosition[i] = FDKreadBits(hBs, 7); + } else { + FDKpushFor(hBs, 7); + } + } + } + } + return err; +} + +static DRC_ERROR _readDownmixInstructions(HANDLE_FDK_BITSTREAM hBs, + const int version, + CHANNEL_LAYOUT* pChan, + DOWNMIX_INSTRUCTIONS* pDown) { + DRC_ERROR err = DE_OK; + + pDown->downmixId = FDKreadBits(hBs, 7); + pDown->targetChannelCount = FDKreadBits(hBs, 7); + pDown->targetLayout = FDKreadBits(hBs, 8); + pDown->downmixCoefficientsPresent = FDKreadBits(hBs, 1); + + if (pDown->downmixCoefficientsPresent) { + int nDownmixCoeffs = pDown->targetChannelCount * pChan->baseChannelCount; + int i; + if (nDownmixCoeffs > 8 * 8) return DE_NOT_OK; + if (version == 0) { + pDown->bsDownmixOffset = 0; + for (i = 0; i < nDownmixCoeffs; i++) { + /* LFE downmix coefficients are not supported. */ + pDown->downmixCoefficient[i] = downmixCoeff[FDKreadBits(hBs, 4)]; + } + } else { + pDown->bsDownmixOffset = FDKreadBits(hBs, 4); + for (i = 0; i < nDownmixCoeffs; i++) { + pDown->downmixCoefficient[i] = downmixCoeffV1[FDKreadBits(hBs, 5)]; + } + } + } + return err; +} + +static DRC_ERROR _readDrcExtensionV1(HANDLE_FDK_BITSTREAM hBs, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { + DRC_ERROR err = DE_OK; + int downmixInstructionsV1Present; + int drcCoeffsAndInstructionsUniDrcV1Present; + int loudEqInstructionsPresent, loudEqInstructionsCount; + int eqPresent, eqInstructionsCount; + int i, offset; + int diff = hUniDrcConfig->diff; + + downmixInstructionsV1Present = FDKreadBits(hBs, 1); + if (downmixInstructionsV1Present == 1) { + diff |= _compAssign(&hUniDrcConfig->downmixInstructionsCountV1, + FDKreadBits(hBs, 7)); + offset = hUniDrcConfig->downmixInstructionsCountV0; + hUniDrcConfig->downmixInstructionsCount = fMin( + (UCHAR)(offset + hUniDrcConfig->downmixInstructionsCountV1), (UCHAR)6); + for (i = 0; i < hUniDrcConfig->downmixInstructionsCountV1; i++) { + DOWNMIX_INSTRUCTIONS tmpDown; + FDKmemclear(&tmpDown, sizeof(DOWNMIX_INSTRUCTIONS)); + err = _readDownmixInstructions(hBs, 1, &hUniDrcConfig->channelLayout, + &tmpDown); + if (err) return err; + if ((offset + i) >= 6) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpDown, + &(hUniDrcConfig->downmixInstructions[offset + i]), + sizeof(DOWNMIX_INSTRUCTIONS)) != 0); + hUniDrcConfig->downmixInstructions[offset + i] = tmpDown; + } + } else { + diff |= _compAssign(&hUniDrcConfig->downmixInstructionsCountV1, 0); + } + + drcCoeffsAndInstructionsUniDrcV1Present = FDKreadBits(hBs, 1); + if (drcCoeffsAndInstructionsUniDrcV1Present == 1) { + diff |= _compAssign(&hUniDrcConfig->drcCoefficientsUniDrcCountV1, + FDKreadBits(hBs, 3)); + offset = hUniDrcConfig->drcCoefficientsUniDrcCountV0; + hUniDrcConfig->drcCoefficientsUniDrcCount = + fMin((UCHAR)(offset + hUniDrcConfig->drcCoefficientsUniDrcCountV1), + (UCHAR)2); + for (i = 0; i < hUniDrcConfig->drcCoefficientsUniDrcCountV1; i++) { + DRC_COEFFICIENTS_UNI_DRC tmpCoef; + FDKmemclear(&tmpCoef, sizeof(DRC_COEFFICIENTS_UNI_DRC)); + err = _readDrcCoefficientsUniDrc(hBs, 1, &tmpCoef); + if (err) return err; + if ((offset + i) >= 2) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpCoef, + &(hUniDrcConfig->drcCoefficientsUniDrc[offset + i]), + sizeof(DRC_COEFFICIENTS_UNI_DRC)) != 0); + hUniDrcConfig->drcCoefficientsUniDrc[offset + i] = tmpCoef; + } + + diff |= _compAssign(&hUniDrcConfig->drcInstructionsUniDrcCountV1, + FDKreadBits(hBs, 6)); + offset = hUniDrcConfig->drcInstructionsUniDrcCount; + hUniDrcConfig->drcInstructionsUniDrcCount = + fMin((UCHAR)(offset + hUniDrcConfig->drcInstructionsUniDrcCountV1), + (UCHAR)12); + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { + DRC_INSTRUCTIONS_UNI_DRC tmpInst; + FDKmemclear(&tmpInst, sizeof(DRC_INSTRUCTIONS_UNI_DRC)); + err = _readDrcInstructionsUniDrc(hBs, 1, hUniDrcConfig, &tmpInst); + if (err) return err; + if ((offset + i) >= 12) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpInst, + &(hUniDrcConfig->drcInstructionsUniDrc[offset + i]), + sizeof(DRC_INSTRUCTIONS_UNI_DRC)) != 0); + hUniDrcConfig->drcInstructionsUniDrc[offset + i] = tmpInst; + } + } else { + diff |= _compAssign(&hUniDrcConfig->drcCoefficientsUniDrcCountV1, 0); + diff |= _compAssign(&hUniDrcConfig->drcInstructionsUniDrcCountV1, 0); + } + + loudEqInstructionsPresent = FDKreadBits(hBs, 1); + if (loudEqInstructionsPresent == 1) { + loudEqInstructionsCount = FDKreadBits(hBs, 4); + for (i = 0; i < loudEqInstructionsCount; i++) { + _skipLoudEqInstructions(hBs); + } + } + + eqPresent = FDKreadBits(hBs, 1); + if (eqPresent == 1) { + _skipEqCoefficients(hBs); + eqInstructionsCount = FDKreadBits(hBs, 4); + for (i = 0; i < eqInstructionsCount; i++) { + _skipEqInstructions(hBs, hUniDrcConfig); + } + } + + hUniDrcConfig->diff = diff; + + return err; +} + +static DRC_ERROR _readUniDrcConfigExtension( + HANDLE_FDK_BITSTREAM hBs, HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { + DRC_ERROR err = DE_OK; + int k, bitSizeLen, extSizeBits, bitSize; + INT nBitsRemaining; + UNI_DRC_CONFIG_EXTENSION* pExt = &(hUniDrcConfig->uniDrcConfigExt); + + k = 0; + pExt->uniDrcConfigExtType[k] = FDKreadBits(hBs, 4); + while (pExt->uniDrcConfigExtType[k] != UNIDRCCONFEXT_TERM) { + if (k >= (8 - 1)) return DE_MEMORY_ERROR; + bitSizeLen = FDKreadBits(hBs, 4); + extSizeBits = bitSizeLen + 4; + + bitSize = FDKreadBits(hBs, extSizeBits); + pExt->extBitSize[k] = bitSize + 1; + nBitsRemaining = (INT)FDKgetValidBits(hBs); + + switch (pExt->uniDrcConfigExtType[k]) { + case UNIDRCCONFEXT_V1: + err = _readDrcExtensionV1(hBs, hUniDrcConfig); + if (err) return err; + if (nBitsRemaining != + ((INT)pExt->extBitSize[k] + (INT)FDKgetValidBits(hBs))) + return DE_NOT_OK; + break; + case UNIDRCCONFEXT_PARAM_DRC: + /* add future extensions here */ + default: + FDKpushFor(hBs, pExt->extBitSize[k]); + break; + } + k++; + pExt->uniDrcConfigExtType[k] = FDKreadBits(hBs, 4); + } + + return err; +} + +DRC_ERROR +drcDec_readUniDrcConfig(HANDLE_FDK_BITSTREAM hBs, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { + DRC_ERROR err = DE_OK; + int i, diff = 0; + int drcDescriptionBasicPresent, drcCoefficientsBasicCount, + drcInstructionsBasicCount; + CHANNEL_LAYOUT tmpChan; + FDKmemclear(&tmpChan, sizeof(CHANNEL_LAYOUT)); + if (hUniDrcConfig == NULL) return DE_NOT_OK; + + diff |= _compAssign(&hUniDrcConfig->sampleRatePresent, FDKreadBits(hBs, 1)); + + if (hUniDrcConfig->sampleRatePresent == 1) { + diff |= + _compAssign(&hUniDrcConfig->sampleRate, FDKreadBits(hBs, 18) + 1000); + } + + diff |= _compAssign(&hUniDrcConfig->downmixInstructionsCountV0, + FDKreadBits(hBs, 7)); + + drcDescriptionBasicPresent = FDKreadBits(hBs, 1); + if (drcDescriptionBasicPresent == 1) { + drcCoefficientsBasicCount = FDKreadBits(hBs, 3); + drcInstructionsBasicCount = FDKreadBits(hBs, 4); + } else { + drcCoefficientsBasicCount = 0; + drcInstructionsBasicCount = 0; + } + + diff |= _compAssign(&hUniDrcConfig->drcCoefficientsUniDrcCountV0, + FDKreadBits(hBs, 3)); + diff |= _compAssign(&hUniDrcConfig->drcInstructionsUniDrcCountV0, + FDKreadBits(hBs, 6)); + + err = _readChannelLayout(hBs, &tmpChan); + if (err) return err; + + if (!diff) + diff |= (FDKmemcmp(&tmpChan, &hUniDrcConfig->channelLayout, + sizeof(CHANNEL_LAYOUT)) != 0); + hUniDrcConfig->channelLayout = tmpChan; + + hUniDrcConfig->downmixInstructionsCount = + fMin(hUniDrcConfig->downmixInstructionsCountV0, (UCHAR)6); + for (i = 0; i < hUniDrcConfig->downmixInstructionsCountV0; i++) { + DOWNMIX_INSTRUCTIONS tmpDown; + FDKmemclear(&tmpDown, sizeof(DOWNMIX_INSTRUCTIONS)); + err = _readDownmixInstructions(hBs, 0, &hUniDrcConfig->channelLayout, + &tmpDown); + if (err) return err; + if (i >= 6) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpDown, &(hUniDrcConfig->downmixInstructions[i]), + sizeof(DOWNMIX_INSTRUCTIONS)) != 0); + hUniDrcConfig->downmixInstructions[i] = tmpDown; + } + + for (i = 0; i < drcCoefficientsBasicCount; i++) { + _skipDrcCoefficientsBasic(hBs); + } + for (i = 0; i < drcInstructionsBasicCount; i++) { + _skipDrcInstructionsBasic(hBs); + } + + hUniDrcConfig->drcCoefficientsUniDrcCount = + fMin(hUniDrcConfig->drcCoefficientsUniDrcCountV0, (UCHAR)2); + for (i = 0; i < hUniDrcConfig->drcCoefficientsUniDrcCountV0; i++) { + DRC_COEFFICIENTS_UNI_DRC tmpCoef; + FDKmemclear(&tmpCoef, sizeof(DRC_COEFFICIENTS_UNI_DRC)); + err = _readDrcCoefficientsUniDrc(hBs, 0, &tmpCoef); + if (err) return err; + if (i >= 2) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpCoef, &(hUniDrcConfig->drcCoefficientsUniDrc[i]), + sizeof(DRC_COEFFICIENTS_UNI_DRC)) != 0); + hUniDrcConfig->drcCoefficientsUniDrc[i] = tmpCoef; + } + + hUniDrcConfig->drcInstructionsUniDrcCount = + fMin(hUniDrcConfig->drcInstructionsUniDrcCountV0, (UCHAR)12); + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCountV0; i++) { + DRC_INSTRUCTIONS_UNI_DRC tmpInst; + FDKmemclear(&tmpInst, sizeof(DRC_INSTRUCTIONS_UNI_DRC)); + err = _readDrcInstructionsUniDrc(hBs, 0, hUniDrcConfig, &tmpInst); + if (err) return err; + if (i >= 12) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpInst, &(hUniDrcConfig->drcInstructionsUniDrc[i]), + sizeof(DRC_INSTRUCTIONS_UNI_DRC)) != 0); + hUniDrcConfig->drcInstructionsUniDrc[i] = tmpInst; + } + + diff |= + _compAssign(&hUniDrcConfig->uniDrcConfigExtPresent, FDKreadBits(hBs, 1)); + hUniDrcConfig->diff = diff; + + if (hUniDrcConfig->uniDrcConfigExtPresent == 1) { + err = _readUniDrcConfigExtension(hBs, hUniDrcConfig); + if (err) return err; + } + + return err; +} + +/*******************/ +/* loudnessInfoSet */ +/*******************/ + +static DRC_ERROR _decodeMethodValue(HANDLE_FDK_BITSTREAM hBs, + const UCHAR methodDefinition, + FIXP_DBL* methodValue, INT isBox) { + int tmp; + FIXP_DBL val; + switch (methodDefinition) { + case MD_UNKNOWN_OTHER: + case MD_PROGRAM_LOUDNESS: + case MD_ANCHOR_LOUDNESS: + case MD_MAX_OF_LOUDNESS_RANGE: + case MD_MOMENTARY_LOUDNESS_MAX: + case MD_SHORT_TERM_LOUDNESS_MAX: + tmp = FDKreadBits(hBs, 8); + val = FL2FXCONST_DBL(-57.75f / (float)(1 << 7)) + + (FIXP_DBL)( + tmp << (DFRACT_BITS - 1 - 2 - 7)); /* -57.75 + tmp * 0.25; */ + break; + case MD_LOUDNESS_RANGE: + tmp = FDKreadBits(hBs, 8); + if (tmp == 0) + val = (FIXP_DBL)0; + else if (tmp <= 128) + val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 2 - 7)); /* tmp * 0.25; */ + else if (tmp <= 204) { + val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 1 - 7)) - + FL2FXCONST_DBL(32.0f / (float)(1 << 7)); /* 0.5 * tmp - 32.0f; */ + } else { + /* downscale by 1 more bit to prevent overflow at intermediate result */ + val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 8)) - + FL2FXCONST_DBL(134.0f / (float)(1 << 8)); /* tmp - 134.0; */ + val <<= 1; + } + break; + case MD_MIXING_LEVEL: + tmp = FDKreadBits(hBs, isBox ? 8 : 5); + val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 7)) + + FL2FXCONST_DBL(80.0f / (float)(1 << 7)); /* tmp + 80.0; */ + break; + case MD_ROOM_TYPE: + tmp = FDKreadBits(hBs, isBox ? 8 : 2); + val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 7)); /* tmp; */ + break; + case MD_SHORT_TERM_LOUDNESS: + tmp = FDKreadBits(hBs, 8); + val = FL2FXCONST_DBL(-116.0f / (float)(1 << 7)) + + (FIXP_DBL)( + tmp << (DFRACT_BITS - 1 - 1 - 7)); /* -116.0 + tmp * 0.5; */ + break; + default: + return DE_NOT_OK; /* invalid methodDefinition value */ + } + *methodValue = val; + return DE_OK; +} + +static DRC_ERROR _readLoudnessMeasurement(HANDLE_FDK_BITSTREAM hBs, + LOUDNESS_MEASUREMENT* pMeas) { + DRC_ERROR err = DE_OK; + + pMeas->methodDefinition = FDKreadBits(hBs, 4); + err = + _decodeMethodValue(hBs, pMeas->methodDefinition, &pMeas->methodValue, 0); + if (err) return err; + pMeas->measurementSystem = FDKreadBits(hBs, 4); + pMeas->reliability = FDKreadBits(hBs, 2); + + return err; +} + +static DRC_ERROR _readLoudnessInfo(HANDLE_FDK_BITSTREAM hBs, const int version, + LOUDNESS_INFO* loudnessInfo) { + DRC_ERROR err = DE_OK; + int bsSamplePeakLevel, bsTruePeakLevel, i; + int measurementCount; + + loudnessInfo->drcSetId = FDKreadBits(hBs, 6); + if (version >= 1) { + loudnessInfo->eqSetId = FDKreadBits(hBs, 6); + } else { + loudnessInfo->eqSetId = 0; + } + loudnessInfo->downmixId = FDKreadBits(hBs, 7); + + loudnessInfo->samplePeakLevelPresent = FDKreadBits(hBs, 1); + if (loudnessInfo->samplePeakLevelPresent) { + bsSamplePeakLevel = FDKreadBits(hBs, 12); + if (bsSamplePeakLevel == 0) { + loudnessInfo->samplePeakLevelPresent = 0; + loudnessInfo->samplePeakLevel = (FIXP_DBL)0; + } else { /* 20.0 - bsSamplePeakLevel * 0.03125; */ + loudnessInfo->samplePeakLevel = + FL2FXCONST_DBL(20.0f / (float)(1 << 7)) - + (FIXP_DBL)(bsSamplePeakLevel << (DFRACT_BITS - 1 - 5 - 7)); + } + } + + loudnessInfo->truePeakLevelPresent = FDKreadBits(hBs, 1); + if (loudnessInfo->truePeakLevelPresent) { + bsTruePeakLevel = FDKreadBits(hBs, 12); + if (bsTruePeakLevel == 0) { + loudnessInfo->truePeakLevelPresent = 0; + loudnessInfo->truePeakLevel = (FIXP_DBL)0; + } else { + loudnessInfo->truePeakLevel = + FL2FXCONST_DBL(20.0f / (float)(1 << 7)) - + (FIXP_DBL)(bsTruePeakLevel << (DFRACT_BITS - 1 - 5 - 7)); + } + loudnessInfo->truePeakLevelMeasurementSystem = FDKreadBits(hBs, 4); + loudnessInfo->truePeakLevelReliability = FDKreadBits(hBs, 2); + } + + measurementCount = FDKreadBits(hBs, 4); + loudnessInfo->measurementCount = fMin(measurementCount, 8); + for (i = 0; i < measurementCount; i++) { + LOUDNESS_MEASUREMENT tmpMeas; + FDKmemclear(&tmpMeas, sizeof(LOUDNESS_MEASUREMENT)); + err = _readLoudnessMeasurement(hBs, &tmpMeas); + if (err) return err; + if (i >= 8) continue; + loudnessInfo->loudnessMeasurement[i] = tmpMeas; + } + + return err; +} + +static DRC_ERROR _readLoudnessInfoSetExtEq( + HANDLE_FDK_BITSTREAM hBs, HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet) { + DRC_ERROR err = DE_OK; + int i, offset; + int diff = hLoudnessInfoSet->diff; + + diff |= _compAssign(&hLoudnessInfoSet->loudnessInfoAlbumCountV1, + FDKreadBits(hBs, 6)); + diff |= + _compAssign(&hLoudnessInfoSet->loudnessInfoCountV1, FDKreadBits(hBs, 6)); + + offset = hLoudnessInfoSet->loudnessInfoAlbumCountV0; + hLoudnessInfoSet->loudnessInfoAlbumCount = fMin( + (UCHAR)(offset + hLoudnessInfoSet->loudnessInfoAlbumCountV1), (UCHAR)12); + for (i = 0; i < hLoudnessInfoSet->loudnessInfoAlbumCountV1; i++) { + LOUDNESS_INFO tmpLoud; + FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO)); + err = _readLoudnessInfo(hBs, 1, &tmpLoud); + if (err) return err; + if ((offset + i) >= 12) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpLoud, + &(hLoudnessInfoSet->loudnessInfoAlbum[offset + i]), + sizeof(LOUDNESS_INFO)) != 0); + hLoudnessInfoSet->loudnessInfoAlbum[offset + i] = tmpLoud; + } + + offset = hLoudnessInfoSet->loudnessInfoCountV0; + hLoudnessInfoSet->loudnessInfoCount = + fMin((UCHAR)(offset + hLoudnessInfoSet->loudnessInfoCountV1), (UCHAR)12); + for (i = 0; i < hLoudnessInfoSet->loudnessInfoCountV1; i++) { + LOUDNESS_INFO tmpLoud; + FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO)); + err = _readLoudnessInfo(hBs, 1, &tmpLoud); + if (err) return err; + if ((offset + i) >= 12) continue; + if (!diff) + diff |= + (FDKmemcmp(&tmpLoud, &(hLoudnessInfoSet->loudnessInfo[offset + i]), + sizeof(LOUDNESS_INFO)) != 0); + hLoudnessInfoSet->loudnessInfo[offset + i] = tmpLoud; + } + hLoudnessInfoSet->diff = diff; + return err; +} + +static DRC_ERROR _readLoudnessInfoSetExtension( + HANDLE_FDK_BITSTREAM hBs, HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet) { + DRC_ERROR err = DE_OK; + int k, bitSizeLen, extSizeBits, bitSize; + INT nBitsRemaining; + LOUDNESS_INFO_SET_EXTENSION* pExt = &(hLoudnessInfoSet->loudnessInfoSetExt); + + k = 0; + pExt->loudnessInfoSetExtType[k] = FDKreadBits(hBs, 4); + while (pExt->loudnessInfoSetExtType[k] != UNIDRCLOUDEXT_TERM) { + if (k >= (8 - 1)) return DE_MEMORY_ERROR; + bitSizeLen = FDKreadBits(hBs, 4); + extSizeBits = bitSizeLen + 4; + + bitSize = FDKreadBits(hBs, extSizeBits); + pExt->extBitSize[k] = bitSize + 1; + nBitsRemaining = (INT)FDKgetValidBits(hBs); + + switch (pExt->loudnessInfoSetExtType[k]) { + case UNIDRCLOUDEXT_EQ: + err = _readLoudnessInfoSetExtEq(hBs, hLoudnessInfoSet); + if (err) return err; + if (nBitsRemaining != + ((INT)pExt->extBitSize[k] + (INT)FDKgetValidBits(hBs))) + return DE_NOT_OK; + break; + /* add future extensions here */ + default: + FDKpushFor(hBs, pExt->extBitSize[k]); + break; + } + k++; + pExt->loudnessInfoSetExtType[k] = FDKreadBits(hBs, 4); + } + + return err; +} + +/* Parser for loundessInfoSet() */ +DRC_ERROR +drcDec_readLoudnessInfoSet(HANDLE_FDK_BITSTREAM hBs, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet) { + DRC_ERROR err = DE_OK; + int i, diff = 0; + if (hLoudnessInfoSet == NULL) return DE_NOT_OK; + + diff |= _compAssign(&hLoudnessInfoSet->loudnessInfoAlbumCountV0, + FDKreadBits(hBs, 6)); + diff |= + _compAssign(&hLoudnessInfoSet->loudnessInfoCountV0, FDKreadBits(hBs, 6)); + + hLoudnessInfoSet->loudnessInfoAlbumCount = + fMin(hLoudnessInfoSet->loudnessInfoAlbumCountV0, (UCHAR)12); + for (i = 0; i < hLoudnessInfoSet->loudnessInfoAlbumCountV0; i++) { + LOUDNESS_INFO tmpLoud; + FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO)); + err = _readLoudnessInfo(hBs, 0, &tmpLoud); + if (err) return err; + if (i >= 12) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpLoud, &(hLoudnessInfoSet->loudnessInfoAlbum[i]), + sizeof(LOUDNESS_INFO)) != 0); + hLoudnessInfoSet->loudnessInfoAlbum[i] = tmpLoud; + } + + hLoudnessInfoSet->loudnessInfoCount = + fMin(hLoudnessInfoSet->loudnessInfoCountV0, (UCHAR)12); + for (i = 0; i < hLoudnessInfoSet->loudnessInfoCountV0; i++) { + LOUDNESS_INFO tmpLoud; + FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO)); + err = _readLoudnessInfo(hBs, 0, &tmpLoud); + if (err) return err; + if (i >= 12) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpLoud, &(hLoudnessInfoSet->loudnessInfo[i]), + sizeof(LOUDNESS_INFO)) != 0); + hLoudnessInfoSet->loudnessInfo[i] = tmpLoud; + } + + diff |= _compAssign(&hLoudnessInfoSet->loudnessInfoSetExtPresent, + FDKreadBits(hBs, 1)); + hLoudnessInfoSet->diff = diff; + + if (hLoudnessInfoSet->loudnessInfoSetExtPresent) { + err = _readLoudnessInfoSetExtension(hBs, hLoudnessInfoSet); + if (err) return err; + } + + return err; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_reader.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_reader.h new file mode 100644 index 0000000000000..1ab9b5878f3a5 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_reader.h @@ -0,0 +1,130 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCDEC_READER_H +#define DRCDEC_READER_H + +#include "drcDecoder.h" +#include "drcDec_types.h" +#include "FDK_bitstream.h" + +DRC_ERROR +drcDec_readUniDrc(HANDLE_FDK_BITSTREAM hBs, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + const int frameSize, const int deltaTminDefault, + HANDLE_UNI_DRC_GAIN hUniDrcGain); + +DRC_ERROR +drcDec_readUniDrcGain(HANDLE_FDK_BITSTREAM hBs, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int frameSize, + const int deltaTminDefault, + HANDLE_UNI_DRC_GAIN hUniDrcGain); + +DRC_ERROR +drcDec_readUniDrcConfig(HANDLE_FDK_BITSTREAM hBs, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig); + +DRC_ERROR +drcDec_readLoudnessInfoSet(HANDLE_FDK_BITSTREAM hBs, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_rom.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_rom.cpp new file mode 100644 index 0000000000000..9f8968960b68a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_rom.cpp @@ -0,0 +1,323 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "drcDec_types.h" +#include "drcDec_rom.h" + +const SCHAR deltaGain_codingProfile_0_1_huffman[24][2] = { + {1, 2}, {3, 4}, {-63, -65}, {5, -66}, {-64, 6}, {-80, 7}, + {8, 9}, {-68, 10}, {11, 12}, {-56, -67}, {-61, 13}, {-62, -69}, + {14, 15}, {16, -72}, {-71, 17}, {-70, -60}, {18, -59}, {19, 20}, + {21, -79}, {-57, -73}, {22, -58}, {-76, 23}, {-75, -74}, {-78, -77}}; + +const SCHAR deltaGain_codingProfile_2_huffman[48][2] = { + {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}, + {13, -65}, {14, -64}, {15, -66}, {16, -67}, {17, 18}, {19, -68}, + {20, -63}, {-69, 21}, {-59, 22}, {-61, -62}, {-60, 23}, {24, -58}, + {-70, -57}, {-56, -71}, {25, 26}, {27, -55}, {-72, 28}, {-54, 29}, + {-53, 30}, {-73, -52}, {31, -74}, {32, 33}, {-75, 34}, {-76, 35}, + {-51, 36}, {-78, 37}, {-77, 38}, {-96, 39}, {-48, 40}, {-50, -79}, + {41, 42}, {-80, -81}, {-82, 43}, {44, -49}, {45, -84}, {-83, -89}, + {-86, 46}, {-90, -85}, {-91, -93}, {-92, 47}, {-88, -87}, {-95, -94}}; + +const FIXP_SGL slopeSteepness[] = {FL2FXCONST_SGL(-3.0518f / (float)(1 << 2)), + FL2FXCONST_SGL(-1.2207f / (float)(1 << 2)), + FL2FXCONST_SGL(-0.4883f / (float)(1 << 2)), + FL2FXCONST_SGL(-0.1953f / (float)(1 << 2)), + FL2FXCONST_SGL(-0.0781f / (float)(1 << 2)), + FL2FXCONST_SGL(-0.0312f / (float)(1 << 2)), + FL2FXCONST_SGL(-0.005f / (float)(1 << 2)), + FL2FXCONST_SGL(0.0f / (float)(1 << 2)), + FL2FXCONST_SGL(0.005f / (float)(1 << 2)), + FL2FXCONST_SGL(0.0312f / (float)(1 << 2)), + FL2FXCONST_SGL(0.0781f / (float)(1 << 2)), + FL2FXCONST_SGL(0.1953f / (float)(1 << 2)), + FL2FXCONST_SGL(0.4883f / (float)(1 << 2)), + FL2FXCONST_SGL(1.2207f / (float)(1 << 2)), + FL2FXCONST_SGL(3.0518f / (float)(1 << 2))}; + +const SCHAR slopeSteepness_huffman[14][2] = { + {1, -57}, {-58, 2}, {3, 4}, {5, 6}, {7, -56}, + {8, -60}, {-61, -55}, {9, -59}, {10, -54}, {-64, 11}, + {-51, 12}, {-62, -50}, {-63, 13}, {-52, -53}}; + +const FIXP_DBL downmixCoeff[] = { + FL2FXCONST_DBL(1.0000000000 / (float)(1 << 2)), + FL2FXCONST_DBL(0.9440608763 / (float)(1 << 2)), + FL2FXCONST_DBL(0.8912509381 / (float)(1 << 2)), + FL2FXCONST_DBL(0.8413951416 / (float)(1 << 2)), + FL2FXCONST_DBL(0.7943282347 / (float)(1 << 2)), + FL2FXCONST_DBL(0.7498942093 / (float)(1 << 2)), + FL2FXCONST_DBL(0.7079457844 / (float)(1 << 2)), + FL2FXCONST_DBL(0.6683439176 / (float)(1 << 2)), + FL2FXCONST_DBL(0.6309573445 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5956621435 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5623413252 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5308844442 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5011872336 / (float)(1 << 2)), + FL2FXCONST_DBL(0.4216965034 / (float)(1 << 2)), + FL2FXCONST_DBL(0.3548133892 / (float)(1 << 2)), + FL2FXCONST_DBL(0.0000000000 / (float)(1 << 2))}; + +const FIXP_DBL downmixCoeffV1[] = { + FL2FXCONST_DBL(3.1622776602 / (float)(1 << 2)), + FL2FXCONST_DBL(1.9952623150 / (float)(1 << 2)), + FL2FXCONST_DBL(1.6788040181 / (float)(1 << 2)), + FL2FXCONST_DBL(1.4125375446 / (float)(1 << 2)), + FL2FXCONST_DBL(1.1885022274 / (float)(1 << 2)), + FL2FXCONST_DBL(1.0000000000 / (float)(1 << 2)), + FL2FXCONST_DBL(0.9440608763 / (float)(1 << 2)), + FL2FXCONST_DBL(0.8912509381 / (float)(1 << 2)), + FL2FXCONST_DBL(0.8413951416 / (float)(1 << 2)), + FL2FXCONST_DBL(0.7943282347 / (float)(1 << 2)), + FL2FXCONST_DBL(0.7498942093 / (float)(1 << 2)), + FL2FXCONST_DBL(0.7079457844 / (float)(1 << 2)), + FL2FXCONST_DBL(0.6683439176 / (float)(1 << 2)), + FL2FXCONST_DBL(0.6309573445 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5956621435 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5623413252 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5308844442 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5011872336 / (float)(1 << 2)), + FL2FXCONST_DBL(0.4731512590 / (float)(1 << 2)), + FL2FXCONST_DBL(0.4466835922 / (float)(1 << 2)), + FL2FXCONST_DBL(0.4216965034 / (float)(1 << 2)), + FL2FXCONST_DBL(0.3981071706 / (float)(1 << 2)), + FL2FXCONST_DBL(0.3548133892 / (float)(1 << 2)), + FL2FXCONST_DBL(0.3162277660 / (float)(1 << 2)), + FL2FXCONST_DBL(0.2818382931 / (float)(1 << 2)), + FL2FXCONST_DBL(0.2511886432 / (float)(1 << 2)), + FL2FXCONST_DBL(0.1778279410 / (float)(1 << 2)), + FL2FXCONST_DBL(0.1000000000 / (float)(1 << 2)), + FL2FXCONST_DBL(0.0562341325 / (float)(1 << 2)), + FL2FXCONST_DBL(0.0316227766 / (float)(1 << 2)), + FL2FXCONST_DBL(0.0100000000 / (float)(1 << 2)), + FL2FXCONST_DBL(0.0000000000 / (float)(1 << 2))}; + +const CUSTOM_DRC_CHAR_SIGMOID cicpDrcCharSigmoidLeft[] = { + {FL2FXCONST_SGL(32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.0f / (float)(1 << 2)), + FL2FXCONST_SGL(9.0f / (float)(1 << 5)), 0}, /* 1 */ + {FL2FXCONST_SGL(32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.2f / (float)(1 << 2)), + FL2FXCONST_SGL(9.0f / (float)(1 << 5)), 0}, /* 2 */ + {FL2FXCONST_SGL(32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.4f / (float)(1 << 2)), + FL2FXCONST_SGL(9.0f / (float)(1 << 5)), 0}, /* 3 */ + {FL2FXCONST_SGL(32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.6f / (float)(1 << 2)), + FL2FXCONST_SGL(9.0f / (float)(1 << 5)), 0}, /* 4 */ + {FL2FXCONST_SGL(32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.8f / (float)(1 << 2)), + FL2FXCONST_SGL(6.0f / (float)(1 << 5)), 0}, /* 5 */ + {FL2FXCONST_SGL(32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(1.0f / (float)(1 << 2)), + FL2FXCONST_SGL(5.0f / (float)(1 << 5)), 0}, /* 6 */ +}; + +const CUSTOM_DRC_CHAR_SIGMOID cicpDrcCharSigmoidRight[] = { + {FL2FXCONST_SGL(-32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.0f / (float)(1 << 2)), + FL2FXCONST_SGL(12.0f / (float)(1 << 5)), 0}, /* 1 */ + {FL2FXCONST_SGL(-32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.2f / (float)(1 << 2)), + FL2FXCONST_SGL(12.0f / (float)(1 << 5)), 0}, /* 2 */ + {FL2FXCONST_SGL(-32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.4f / (float)(1 << 2)), + FL2FXCONST_SGL(12.0f / (float)(1 << 5)), 0}, /* 3 */ + {FL2FXCONST_SGL(-32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.6f / (float)(1 << 2)), + FL2FXCONST_SGL(10.0f / (float)(1 << 5)), 0}, /* 4 */ + {FL2FXCONST_SGL(-32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.8f / (float)(1 << 2)), + FL2FXCONST_SGL(8.0f / (float)(1 << 5)), 0}, /* 5 */ + {FL2FXCONST_SGL(-32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(1.0f / (float)(1 << 2)), + FL2FXCONST_SGL(6.0f / (float)(1 << 5)), 0}, /* 6 */ +}; + +const CUSTOM_DRC_CHAR_NODES cicpDrcCharNodesLeft[] = { + {2, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-41.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-53.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(6.0f / (float)(1 << 7))}}, /* 7 */ + {1, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-43.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(6.0f / (float)(1 << 7))}}, /* 8 */ + {2, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-41.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-65.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(12.0f / (float)(1 << 7))}}, /* 9 */ + {1, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-55.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(12.0f / (float)(1 << 7))}}, /* 10 */ + {1, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-50.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(15.0f / (float)(1 << 7))}} /* 11 */ +}; + +const CUSTOM_DRC_CHAR_NODES cicpDrcCharNodesRight[] = { + {4, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-21.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-11.0f / (float)(1 << 7)), + FL2FXCONST_SGL(9.0f / (float)(1 << 7)), + FL2FXCONST_SGL(19.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-5.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-24.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-34.0f / (float)(1 << 7))}}, /* 7 */ + {4, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-26.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-16.0f / (float)(1 << 7)), + FL2FXCONST_SGL(4.0f / (float)(1 << 7)), + FL2FXCONST_SGL(14.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-5.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-24.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-34.0f / (float)(1 << 7))}}, /* 8 */ + {3, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-21.0f / (float)(1 << 7)), + FL2FXCONST_SGL(9.0f / (float)(1 << 7)), + FL2FXCONST_SGL(29.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-15.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-35.0f / (float)(1 << 7))}}, /* 9 */ + {4, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-26.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-16.0f / (float)(1 << 7)), + FL2FXCONST_SGL(4.0f / (float)(1 << 7)), + FL2FXCONST_SGL(14.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-5.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-24.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-34.0f / (float)(1 << 7))}}, /* 10 */ + {4, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-26.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-16.0f / (float)(1 << 7)), + FL2FXCONST_SGL(4.0f / (float)(1 << 7)), + FL2FXCONST_SGL(14.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-5.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-24.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-34.0f / (float)(1 << 7))}} /* 11 */ +}; diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_rom.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_rom.h new file mode 100644 index 0000000000000..daee882567273 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_rom.h @@ -0,0 +1,120 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCDEC_ROM_H +#define DRCDEC_ROM_H + +extern const SCHAR deltaGain_codingProfile_0_1_huffman[24][2]; +extern const SCHAR deltaGain_codingProfile_2_huffman[48][2]; + +extern const FIXP_SGL slopeSteepness[]; +extern const SCHAR slopeSteepness_huffman[14][2]; + +extern const FIXP_DBL downmixCoeff[]; +extern const FIXP_DBL downmixCoeffV1[]; + +extern const CUSTOM_DRC_CHAR_SIGMOID cicpDrcCharSigmoidLeft[]; +extern const CUSTOM_DRC_CHAR_SIGMOID cicpDrcCharSigmoidRight[]; +extern const CUSTOM_DRC_CHAR_NODES cicpDrcCharNodesLeft[]; +extern const CUSTOM_DRC_CHAR_NODES cicpDrcCharNodesRight[]; + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_selectionProcess.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_selectionProcess.cpp new file mode 100644 index 0000000000000..46ed740f93eaa --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_selectionProcess.cpp @@ -0,0 +1,3165 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): Andreas Hoelzer + + Description: DRC Set Selection + +*******************************************************************************/ + +#include "drcDec_selectionProcess.h" +#include "drcDec_tools.h" + +typedef enum { + DETR_NONE = 0, + DETR_NIGHT = 1, + DETR_NOISY = 2, + DETR_LIMITED = 3, + DETR_LOWLEVEL = 4, + DETR_DIALOG = 5, + DETR_GENERAL_COMPR = 6, + DETR_EXPAND = 7, + DETR_ARTISTIC = 8, + DETR_COUNT +} DRC_EFFECT_TYPE_REQUEST; + +typedef enum { + DFRT_EFFECT_TYPE, + DFRT_DYNAMIC_RANGE, + DFRT_DRC_CHARACTERISTIC +} DRC_FEATURE_REQUEST_TYPE; + +typedef enum { + MDR_DEFAULT = 0, + MDR_PROGRAM_LOUDNESS = 1, + MDR_ANCHOR_LOUDNESS = 2 +} METHOD_DEFINITION_REQUEST; + +typedef enum { + MSR_DEFAULT = 0, + MSR_BS_1770_4 = 1, + MSR_USER = 2, + MSR_EXPERT_PANEL = 3, + MSR_RESERVED_A = 4, + MSR_RESERVED_B = 5, + MSR_RESERVED_C = 6, + MSR_RESERVED_D = 7, + MSR_RESERVED_E = 8 +} MEASUREMENT_SYSTEM_REQUEST; + +typedef enum { + LPR_DEFAULT = 0, + LPR_OFF = 1, + LPR_HIGHPASS = 2 +} LOUDNESS_PREPROCESSING_REQUEST; + +typedef enum { + DRMRT_SHORT_TERM_LOUDNESS_TO_AVG = 0, + DRMRT_MOMENTARY_LOUDNESS_TO_AVG = 1, + DRMRT_TOP_OF_LOUDNESS_RANGE_TO_AVG = 2 +} DYN_RANGE_MEASUREMENT_REQUEST_TYPE; + +typedef enum { + TCRT_DOWNMIX_ID = 0, + TCRT_TARGET_LAYOUT = 1, + TCRT_TARGET_CHANNEL_COUNT = 2 +} TARGET_CONFIG_REQUEST_TYPE; + +typedef shouldBeUnion { + struct { + UCHAR numRequests; + UCHAR numRequestsDesired; + DRC_EFFECT_TYPE_REQUEST request[MAX_REQUESTS_DRC_EFFECT_TYPE]; + } drcEffectType; + struct { + DYN_RANGE_MEASUREMENT_REQUEST_TYPE measurementRequestType; + UCHAR requestedIsRange; + FIXP_DBL requestValue; /* e = 7 */ + FIXP_DBL requestValueMin; /* e = 7 */ + FIXP_DBL requestValueMax; /* e = 7 */ + } dynamicRange; + UCHAR drcCharacteristic; +} +DRC_FEATURE_REQUEST; + +typedef struct { + /* system parameters */ + SCHAR baseChannelCount; + SCHAR baseLayout; /* not supported */ + TARGET_CONFIG_REQUEST_TYPE targetConfigRequestType; + UCHAR numDownmixIdRequests; + UCHAR downmixIdRequested[MAX_REQUESTS_DOWNMIX_ID]; + UCHAR targetLayoutRequested; + UCHAR targetChannelCountRequested; + LONG audioSampleRate; /* needed for complexity estimation, currently not + supported */ + + /* loudness normalization parameters */ + UCHAR loudnessNormalizationOn; + FIXP_DBL targetLoudness; /* e = 7 */ + UCHAR albumMode; + UCHAR peakLimiterPresent; + UCHAR loudnessDeviationMax; /* resolution: 1 dB */ + METHOD_DEFINITION_REQUEST loudnessMeasurementMethod; + MEASUREMENT_SYSTEM_REQUEST loudnessMeasurementSystem; + LOUDNESS_PREPROCESSING_REQUEST loudnessMeasurementPreProc; /* not supported */ + LONG deviceCutOffFrequency; /* not supported */ + FIXP_DBL loudnessNormalizationGainDbMax; /* e = 7 */ + FIXP_DBL loudnessNormalizationGainModificationDb; /* e = 7 */ + FIXP_DBL outputPeakLevelMax; /* e = 7 */ + + /* dynamic range control parameters */ + UCHAR dynamicRangeControlOn; + UCHAR numDrcFeatureRequests; + DRC_FEATURE_REQUEST_TYPE drcFeatureRequestType[MAX_REQUESTS_DRC_FEATURE]; + DRC_FEATURE_REQUEST drcFeatureRequest[MAX_REQUESTS_DRC_FEATURE]; + + /* other */ + FIXP_SGL boost; /* e = 1 */ + FIXP_SGL compress; /* e = 1 */ + UCHAR drcCharacteristicTarget; /* not supported */ +} SEL_PROC_INPUT, *HANDLE_SEL_PROC_INPUT; + +/* Table E.1 of ISO/IEC DIS 23003-4: Recommended order of fallback effect type + * requests */ +static DRC_EFFECT_TYPE_REQUEST fallbackEffectTypeRequests[6][5] = { + /* Night */ {DETR_GENERAL_COMPR, DETR_NOISY, DETR_LIMITED, DETR_LOWLEVEL, + DETR_DIALOG}, + /* Noisy */ + {DETR_GENERAL_COMPR, DETR_NIGHT, DETR_LIMITED, DETR_LOWLEVEL, DETR_DIALOG}, + /* Limited */ + {DETR_GENERAL_COMPR, DETR_NIGHT, DETR_NOISY, DETR_LOWLEVEL, DETR_DIALOG}, + /* LowLevel */ + {DETR_GENERAL_COMPR, DETR_NOISY, DETR_NIGHT, DETR_LIMITED, DETR_DIALOG}, + /* Dialog */ + {DETR_GENERAL_COMPR, DETR_NIGHT, DETR_NOISY, DETR_LIMITED, DETR_LOWLEVEL}, + /* General */ + {DETR_NIGHT, DETR_NOISY, DETR_LIMITED, DETR_LOWLEVEL, DETR_DIALOG}}; + +/*******************************************/ +typedef struct { + UCHAR selectionFlag; + UCHAR downmixIdRequestIndex; + FIXP_DBL outputPeakLevel; /* e = 7 */ + FIXP_DBL loudnessNormalizationGainDbAdjusted; /* e = 7 */ + FIXP_DBL outputLoudness; /* e = 7 */ + DRC_INSTRUCTIONS_UNI_DRC* pInst; + +} DRCDEC_SELECTION_DATA; + +typedef struct { + UCHAR numData; + DRCDEC_SELECTION_DATA data[(12 + 1 + 6)]; + +} DRCDEC_SELECTION; + +/*******************************************/ +/* helper functions */ +/*******************************************/ + +static int _isError(int x) { + if (x < DRCDEC_SELECTION_PROCESS_WARNING) { + return 1; + } + + return 0; +} + +/* compare and assign */ +static inline int _compAssign(UCHAR* dest, const UCHAR src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = src; + return diff; +} + +static inline int _compAssign(SCHAR* dest, const SCHAR src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = src; + return diff; +} + +static inline int _compAssign(FIXP_DBL* dest, const FIXP_DBL src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = src; + return diff; +} + +static inline int _compAssign(FIXP_SGL* dest, const FIXP_SGL src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = src; + return diff; +} + +static inline int _compAssign(TARGET_CONFIG_REQUEST_TYPE* dest, const int src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = (TARGET_CONFIG_REQUEST_TYPE)src; + return diff; +} + +static inline int _compAssign(METHOD_DEFINITION_REQUEST* dest, const int src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = (METHOD_DEFINITION_REQUEST)src; + return diff; +} + +static inline int _compAssign(DRC_FEATURE_REQUEST_TYPE* dest, const int src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = (DRC_FEATURE_REQUEST_TYPE)src; + return diff; +} + +static inline int _compAssign(DRC_EFFECT_TYPE_REQUEST* dest, const int src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = (DRC_EFFECT_TYPE_REQUEST)src; + return diff; +} + +static DRCDEC_SELECTION_DATA* _drcdec_selection_addNew( + DRCDEC_SELECTION* pSelection); + +static DRCDEC_SELECTION_DATA* _drcdec_selection_add( + DRCDEC_SELECTION* pSelection, DRCDEC_SELECTION_DATA* pDataIn); + +static int _drcdec_selection_clear(DRCDEC_SELECTION* pSelection); + +static int _drcdec_selection_getNumber(DRCDEC_SELECTION* pSelection); + +static int _drcdec_selection_setNumber(DRCDEC_SELECTION* pSelection, int num); + +static DRCDEC_SELECTION_DATA* _drcdec_selection_getAt( + DRCDEC_SELECTION* pSelection, int at); + +static int _swapSelectionAndClear(DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected); + +static int _swapSelection(DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected); + +/*******************************************/ +/* declarations of static functions */ +/*******************************************/ + +static DRCDEC_SELECTION_PROCESS_RETURN _initDefaultParams( + HANDLE_SEL_PROC_INPUT hSelProcInput); + +static DRCDEC_SELECTION_PROCESS_RETURN _initCodecModeParams( + HANDLE_SEL_PROC_INPUT hSelProcInput, const SEL_PROC_CODEC_MODE codecMode); + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetPreSelection( + SEL_PROC_INPUT* hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode); + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_peakValue0( + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected); + +static DRCDEC_SELECTION_PROCESS_RETURN _dynamicRangeMeasurement( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, DRC_INSTRUCTIONS_UNI_DRC* pInst, + UCHAR downmixIdRequested, + DYN_RANGE_MEASUREMENT_REQUEST_TYPE dynamicRangeMeasurementType, + int albumMode, int* peakToAveragePresent, FIXP_DBL* peakToAverage); + +static DRCDEC_SELECTION_PROCESS_RETURN _channelLayoutToDownmixIdMapping( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig); + +static DRCDEC_SELECTION_PROCESS_RETURN _generateVirtualDrcSets( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + SEL_PROC_CODEC_MODE codecMode); + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetRequestSelection( + SEL_PROC_INPUT* hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected); + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode); + +static DRCDEC_SELECTION_PROCESS_RETURN _generateOutputInfo( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_SEL_PROC_OUTPUT hSelProcOutput, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION_DATA* pSelectionData, SEL_PROC_CODEC_MODE codecMode); + +static DRCDEC_SELECTION_PROCESS_RETURN _selectDownmixMatrix( + HANDLE_SEL_PROC_OUTPUT hSelProcOutput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig); + +static DRCDEC_SELECTION_PROCESS_RETURN _getLoudness( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int albumMode, + METHOD_DEFINITION_REQUEST measurementMethodRequested, + MEASUREMENT_SYSTEM_REQUEST measurementSystemRequested, + FIXP_DBL targetLoudness, int drcSetId, int downmixIdRequested, + FIXP_DBL* pLoudnessNormalizationGain, FIXP_DBL* pLoudness); + +static DRCDEC_SELECTION_PROCESS_RETURN _getMixingLevel( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int downmixIdRequested, + int drcSetIdRequested, int albumMode, FIXP_DBL* pMixingLevel); + +static DRCDEC_SELECTION_PROCESS_RETURN _getSignalPeakLevel( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, DRC_INSTRUCTIONS_UNI_DRC* pInst, + int downmixIdRequested, int* explicitPeakInformationPresent, + FIXP_DBL* signalPeakLevelOut, /* e = 7 */ + SEL_PROC_CODEC_MODE codecMode); + +static DRCDEC_SELECTION_PROCESS_RETURN _extractLoudnessPeakToAverageValue( + LOUDNESS_INFO* loudnessInfo, + DYN_RANGE_MEASUREMENT_REQUEST_TYPE dynamicRangeMeasurementType, + int* pLoudnessPeakToAverageValuePresent, + FIXP_DBL* pLoudnessPeakToAverageValue); + +static DRCDEC_SELECTION_PROCESS_RETURN _selectAlbumLoudness( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected); + +static int _findMethodDefinition(LOUDNESS_INFO* pLoudnessInfo, + int methodDefinition, int startIndex); + +/*******************************************/ +/* public functions */ +/*******************************************/ + +struct s_drcdec_selection_process { + SEL_PROC_CODEC_MODE codecMode; + SEL_PROC_INPUT selProcInput; + DRCDEC_SELECTION + selectionData[2]; /* 2 instances, one before and one after selection */ +}; + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Create(HANDLE_DRC_SELECTION_PROCESS* phInstance) { + HANDLE_DRC_SELECTION_PROCESS hInstance; + hInstance = (HANDLE_DRC_SELECTION_PROCESS)FDKcalloc( + 1, sizeof(struct s_drcdec_selection_process)); + + if (!hInstance) return DRCDEC_SELECTION_PROCESS_OUTOFMEMORY; + + hInstance->codecMode = SEL_PROC_CODEC_MODE_UNDEFINED; + + *phInstance = hInstance; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Init(HANDLE_DRC_SELECTION_PROCESS hInstance) { + if (!hInstance) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + _initDefaultParams(&hInstance->selProcInput); + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_SetCodecMode(HANDLE_DRC_SELECTION_PROCESS hInstance, + const SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (!hInstance) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + switch (codecMode) { + case SEL_PROC_MPEG_4_AAC: + case SEL_PROC_MPEG_D_USAC: + case SEL_PROC_TEST_TIME_DOMAIN: + case SEL_PROC_TEST_QMF_DOMAIN: + case SEL_PROC_TEST_STFT_DOMAIN: + hInstance->codecMode = codecMode; + break; + + case SEL_PROC_CODEC_MODE_UNDEFINED: + default: + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + retVal = _initCodecModeParams(&(hInstance->selProcInput), + hInstance->codecMode = codecMode); + + return retVal; +} + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_SetParam(HANDLE_DRC_SELECTION_PROCESS hInstance, + const SEL_PROC_USER_PARAM requestType, + FIXP_DBL requestValue, int* pDiff) { + INT requestValueInt = (INT)requestValue; + int i, diff = 0; + SEL_PROC_INPUT* pSelProcInput = &(hInstance->selProcInput); + + switch (requestType) { + case SEL_PROC_LOUDNESS_NORMALIZATION_ON: + if ((requestValueInt != 0) && (requestValueInt != 1)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= + _compAssign(&pSelProcInput->loudnessNormalizationOn, requestValueInt); + break; + case SEL_PROC_TARGET_LOUDNESS: + /* Lower boundary: drcSetTargetLoudnessValueLower default value. + Upper boundary: drcSetTargetLoudnessValueUpper default value */ + if ((requestValue < FL2FXCONST_DBL(-63.0f / (float)(1 << 7))) || + (requestValue > (FIXP_DBL)0)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + if (requestValue > + FL2FXCONST_DBL(-10.0f / + (float)(1 << 7))) /* recommended maximum value */ + requestValue = FL2FXCONST_DBL(-10.0f / (float)(1 << 7)); + diff |= _compAssign(&pSelProcInput->targetLoudness, requestValue); + break; + case SEL_PROC_EFFECT_TYPE: + if ((requestValueInt < -1) || (requestValueInt >= DETR_COUNT)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + /* Caution. This overrides all drcFeatureRequests requested so far! */ + if (requestValueInt == -1) { + diff |= _compAssign(&pSelProcInput->dynamicRangeControlOn, 0); + } else if (requestValueInt == DETR_NONE) { + diff |= _compAssign(&pSelProcInput->dynamicRangeControlOn, 1); + diff |= _compAssign(&pSelProcInput->numDrcFeatureRequests, 0); + } else { + diff |= _compAssign(&pSelProcInput->dynamicRangeControlOn, 1); + diff |= _compAssign(&pSelProcInput->numDrcFeatureRequests, 1); + diff |= _compAssign(&pSelProcInput->drcFeatureRequestType[0], + DFRT_EFFECT_TYPE); + diff |= _compAssign(&pSelProcInput->drcFeatureRequest[0] + .drcEffectType.numRequestsDesired, + 1); + diff |= _compAssign( + &pSelProcInput->drcFeatureRequest[0].drcEffectType.request[0], + requestValueInt); + if ((requestValueInt > DETR_NONE) && + (requestValueInt <= DETR_GENERAL_COMPR)) { + /* use fallback effect type requests */ + for (i = 0; i < 5; i++) { + diff |= + _compAssign(&pSelProcInput->drcFeatureRequest[0] + .drcEffectType.request[i + 1], + fallbackEffectTypeRequests[requestValueInt - 1][i]); + } + diff |= _compAssign( + &pSelProcInput->drcFeatureRequest[0].drcEffectType.numRequests, + 6); + } else { + diff |= _compAssign( + &pSelProcInput->drcFeatureRequest[0].drcEffectType.numRequests, + 1); + } + } + break; + case SEL_PROC_LOUDNESS_MEASUREMENT_METHOD: + if ((requestValueInt < 0) || (requestValueInt > 2)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign(&pSelProcInput->loudnessMeasurementMethod, + requestValueInt); + break; + case SEL_PROC_ALBUM_MODE: + if ((requestValueInt < 0) || (requestValueInt > 1)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign(&pSelProcInput->albumMode, requestValueInt); + break; + case SEL_PROC_DOWNMIX_ID: + diff |= + _compAssign(&pSelProcInput->targetConfigRequestType, TCRT_DOWNMIX_ID); + if (requestValueInt < 0) { /* negative requests signal no downmixId */ + diff |= _compAssign(&pSelProcInput->numDownmixIdRequests, 0); + } else { + diff |= _compAssign(&pSelProcInput->numDownmixIdRequests, 1); + diff |= + _compAssign(&pSelProcInput->downmixIdRequested[0], requestValueInt); + } + break; + case SEL_PROC_TARGET_LAYOUT: + /* Request target layout according to ChannelConfiguration in ISO/IEC + * 23001-8 (CICP) */ + if ((requestValueInt < 1) || (requestValueInt > 63)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign(&pSelProcInput->targetConfigRequestType, + TCRT_TARGET_LAYOUT); + diff |= + _compAssign(&pSelProcInput->targetLayoutRequested, requestValueInt); + break; + case SEL_PROC_TARGET_CHANNEL_COUNT: + if ((requestValueInt < 1) || (requestValueInt > 8)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign(&pSelProcInput->targetConfigRequestType, + TCRT_TARGET_CHANNEL_COUNT); + diff |= _compAssign(&pSelProcInput->targetChannelCountRequested, + requestValueInt); + break; + case SEL_PROC_BASE_CHANNEL_COUNT: + if (requestValueInt < 0) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign(&pSelProcInput->baseChannelCount, requestValueInt); + break; + case SEL_PROC_SAMPLE_RATE: + if (requestValueInt < 0) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign(&pSelProcInput->audioSampleRate, requestValueInt); + break; + case SEL_PROC_BOOST: + if ((requestValue < (FIXP_DBL)0) || + (requestValue > FL2FXCONST_DBL(1.0f / (float)(1 << 1)))) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign( + &pSelProcInput->boost, + FX_DBL2FX_SGL( + requestValue + + (FIXP_DBL)(1 << 15))); /* convert to FIXP_SGL with rounding */ + break; + case SEL_PROC_COMPRESS: + if ((requestValue < (FIXP_DBL)0) || + (requestValue > FL2FXCONST_DBL(1.0f / (float)(1 << 1)))) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign( + &pSelProcInput->compress, + FX_DBL2FX_SGL( + requestValue + + (FIXP_DBL)(1 << 15))); /* convert to FIXP_SGL with rounding */ + break; + default: + return DRCDEC_SELECTION_PROCESS_INVALID_PARAM; + } + + if (pDiff != NULL) { + *pDiff |= diff; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +FIXP_DBL +drcDec_SelectionProcess_GetParam(HANDLE_DRC_SELECTION_PROCESS hInstance, + const SEL_PROC_USER_PARAM requestType) { + SEL_PROC_INPUT* pSelProcInput = &(hInstance->selProcInput); + + switch (requestType) { + case SEL_PROC_LOUDNESS_NORMALIZATION_ON: + return (FIXP_DBL)pSelProcInput->loudnessNormalizationOn; + case SEL_PROC_DYNAMIC_RANGE_CONTROL_ON: + return (FIXP_DBL)pSelProcInput->dynamicRangeControlOn; + default: + return (FIXP_DBL)0; + } +} + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Delete(HANDLE_DRC_SELECTION_PROCESS* phInstance) { + if (phInstance == NULL || *phInstance == NULL) + return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; + + FDKfree(*phInstance); + *phInstance = NULL; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Process(HANDLE_DRC_SELECTION_PROCESS hInstance, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + HANDLE_SEL_PROC_OUTPUT hSelProcOutput) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + DRCDEC_SELECTION* pCandidatesSelected; + DRCDEC_SELECTION* pCandidatesPotential; + + if (hInstance == NULL) return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; + + pCandidatesSelected = &(hInstance->selectionData[0]); + pCandidatesPotential = &(hInstance->selectionData[1]); + _drcdec_selection_setNumber(pCandidatesSelected, 0); + _drcdec_selection_setNumber(pCandidatesPotential, 0); + + retVal = _generateVirtualDrcSets(&(hInstance->selProcInput), hUniDrcConfig, + hInstance->codecMode); + if (retVal) return (retVal); + + if (hInstance->selProcInput.baseChannelCount != + hUniDrcConfig->channelLayout.baseChannelCount) { + hInstance->selProcInput.baseChannelCount = + hUniDrcConfig->channelLayout.baseChannelCount; + } + + if ((hInstance->selProcInput.targetConfigRequestType != 0) || + (hInstance->selProcInput.targetConfigRequestType == 0 && + hInstance->selProcInput.numDownmixIdRequests == 0)) { + retVal = _channelLayoutToDownmixIdMapping(&(hInstance->selProcInput), + hUniDrcConfig); + + if (_isError(retVal)) return (retVal); + } + + retVal = _drcSetPreSelection(&(hInstance->selProcInput), hUniDrcConfig, + hLoudnessInfoSet, &pCandidatesPotential, + &pCandidatesSelected, hInstance->codecMode); + if (retVal) return (retVal); + + if (hInstance->selProcInput.albumMode) { + _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); + + retVal = _selectAlbumLoudness(hLoudnessInfoSet, pCandidatesPotential, + pCandidatesSelected); + if (retVal) return (retVal); + + if (_drcdec_selection_getNumber(pCandidatesSelected) == 0) { + _swapSelection(&pCandidatesPotential, &pCandidatesSelected); + } + } + + _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); + + retVal = _drcSetRequestSelection(&(hInstance->selProcInput), hUniDrcConfig, + hLoudnessInfoSet, &pCandidatesPotential, + &pCandidatesSelected); + if (retVal) return (retVal); + + retVal = _drcSetFinalSelection(&(hInstance->selProcInput), hUniDrcConfig, + &pCandidatesPotential, &pCandidatesSelected, + hInstance->codecMode); + if (retVal) return (retVal); + + retVal = _generateOutputInfo( + &(hInstance->selProcInput), hSelProcOutput, hUniDrcConfig, + hLoudnessInfoSet, &(pCandidatesSelected->data[0]), hInstance->codecMode); + + if (_isError(retVal)) return (retVal); + + retVal = _selectDownmixMatrix(hSelProcOutput, hUniDrcConfig); + if (retVal) return (retVal); + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ +/* static functions */ +/*******************************************/ + +static DRCDEC_SELECTION_PROCESS_RETURN _initDefaultParams( + HANDLE_SEL_PROC_INPUT hSelProcInput) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (hSelProcInput == NULL) return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; + + /* system parameters */ + hSelProcInput->baseChannelCount = -1; + hSelProcInput->baseLayout = -1; + hSelProcInput->targetConfigRequestType = TCRT_DOWNMIX_ID; + hSelProcInput->numDownmixIdRequests = 0; + + /* loudness normalization parameters */ + hSelProcInput->albumMode = 0; + hSelProcInput->peakLimiterPresent = 0; + hSelProcInput->loudnessNormalizationOn = 1; + hSelProcInput->targetLoudness = FL2FXCONST_DBL(-24.0f / (float)(1 << 7)); + hSelProcInput->loudnessDeviationMax = DEFAULT_LOUDNESS_DEVIATION_MAX; + hSelProcInput->loudnessMeasurementMethod = MDR_ANCHOR_LOUDNESS; + hSelProcInput->loudnessMeasurementSystem = MSR_EXPERT_PANEL; + hSelProcInput->loudnessMeasurementPreProc = LPR_DEFAULT; + hSelProcInput->deviceCutOffFrequency = 500; + hSelProcInput->loudnessNormalizationGainDbMax = + (FIXP_DBL)MAXVAL_DBL; /* infinity as default */ + hSelProcInput->loudnessNormalizationGainModificationDb = (FIXP_DBL)0; + hSelProcInput->outputPeakLevelMax = (FIXP_DBL)0; + if (hSelProcInput->peakLimiterPresent == 1) { + hSelProcInput->outputPeakLevelMax = FL2FXCONST_DBL(6.0f / (float)(1 << 7)); + } + + /* dynamic range control parameters */ + hSelProcInput->dynamicRangeControlOn = 1; + + hSelProcInput->numDrcFeatureRequests = 0; + + /* other parameters */ + hSelProcInput->boost = FL2FXCONST_SGL(1.f / (float)(1 << 1)); + hSelProcInput->compress = FL2FXCONST_SGL(1.f / (float)(1 << 1)); + hSelProcInput->drcCharacteristicTarget = 0; + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _initCodecModeParams( + HANDLE_SEL_PROC_INPUT hSelProcInput, const SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (hSelProcInput == NULL) return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; + + switch (codecMode) { + case SEL_PROC_MPEG_H_3DA: + hSelProcInput->loudnessDeviationMax = 0; + hSelProcInput->peakLimiterPresent = 1; /* peak limiter is mandatory */ + /* The peak limiter also has to catch overshoots due to user + interactivity, downmixing etc. Therefore the maximum output peak level is + reduced to 0 dB. */ + hSelProcInput->outputPeakLevelMax = (FIXP_DBL)0; + break; + case SEL_PROC_MPEG_4_AAC: + case SEL_PROC_MPEG_D_USAC: + hSelProcInput->loudnessDeviationMax = DEFAULT_LOUDNESS_DEVIATION_MAX; + hSelProcInput->peakLimiterPresent = 1; + /* A peak limiter is present at the end of the decoder, therefore we can + * allow for a maximum output peak level greater than full scale + */ + hSelProcInput->outputPeakLevelMax = + FL2FXCONST_DBL(6.0f / (float)(1 << 7)); + break; + case SEL_PROC_TEST_TIME_DOMAIN: + case SEL_PROC_TEST_QMF_DOMAIN: + case SEL_PROC_TEST_STFT_DOMAIN: + /* for testing, adapt to default settings in reference software */ + hSelProcInput->loudnessNormalizationOn = 0; + hSelProcInput->dynamicRangeControlOn = 0; + break; + case SEL_PROC_CODEC_MODE_UNDEFINED: + default: + hSelProcInput->loudnessDeviationMax = DEFAULT_LOUDNESS_DEVIATION_MAX; + hSelProcInput->peakLimiterPresent = 0; + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _channelLayoutToDownmixIdMapping( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + DOWNMIX_INSTRUCTIONS* pDown = NULL; + + int i; + + hSelProcInput->numDownmixIdRequests = 0; + + switch (hSelProcInput->targetConfigRequestType) { + case TCRT_DOWNMIX_ID: + if (hSelProcInput->numDownmixIdRequests == 0) { + hSelProcInput->downmixIdRequested[0] = 0; + hSelProcInput->numDownmixIdRequests = 1; + } + + break; + + case TCRT_TARGET_LAYOUT: + if (hSelProcInput->targetLayoutRequested == hSelProcInput->baseLayout) { + hSelProcInput->downmixIdRequested[0] = 0; + hSelProcInput->numDownmixIdRequests = 1; + } + + if (hSelProcInput->numDownmixIdRequests == 0) { + for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { + pDown = &(hUniDrcConfig->downmixInstructions[i]); + + if (hSelProcInput->targetLayoutRequested == pDown->targetLayout) { + hSelProcInput + ->downmixIdRequested[hSelProcInput->numDownmixIdRequests] = + pDown->downmixId; + hSelProcInput->numDownmixIdRequests++; + } + } + } + + if (hSelProcInput->baseLayout == -1) { + retVal = DRCDEC_SELECTION_PROCESS_WARNING; + } + + if (hSelProcInput->numDownmixIdRequests == 0) { + hSelProcInput->downmixIdRequested[0] = 0; + hSelProcInput->numDownmixIdRequests = 1; + retVal = DRCDEC_SELECTION_PROCESS_WARNING; + } + + break; + + case TCRT_TARGET_CHANNEL_COUNT: + if (hSelProcInput->targetChannelCountRequested == + hSelProcInput->baseChannelCount) { + hSelProcInput->downmixIdRequested[0] = 0; + hSelProcInput->numDownmixIdRequests = 1; + } + + if (hSelProcInput->numDownmixIdRequests == 0) { + for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { + pDown = &(hUniDrcConfig->downmixInstructions[i]); + + if (hSelProcInput->targetChannelCountRequested == + pDown->targetChannelCount) { + hSelProcInput + ->downmixIdRequested[hSelProcInput->numDownmixIdRequests] = + pDown->downmixId; + hSelProcInput->numDownmixIdRequests++; + } + } + } + + if (hSelProcInput->baseChannelCount == -1) { + retVal = DRCDEC_SELECTION_PROCESS_WARNING; + } + + if (hSelProcInput->numDownmixIdRequests == 0) { + retVal = DRCDEC_SELECTION_PROCESS_WARNING; + hSelProcInput->downmixIdRequested[0] = 0; + hSelProcInput->numDownmixIdRequests = 1; + } + + break; + + default: + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + return retVal; +} + +/*******************************************/ + +/* Note: Numbering of DRC pre-selection steps according to MPEG-D Part-4 DRC + * Amd1 */ + +/* #1: DownmixId of DRC set matches the requested downmixId. + #2: Output channel layout of DRC set matches the requested layout. + #3: Channel count of DRC set matches the requested channel count. */ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement123( + int nRequestedDownmixId, DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, + int* pMatchFound) { + int i; + *pMatchFound = 0; + + for (i = 0; i < pDrcInstructionUniDrc->downmixIdCount; i++) { + if ((pDrcInstructionUniDrc->downmixId[i] == nRequestedDownmixId) || + (pDrcInstructionUniDrc->downmixId[i] == DOWNMIX_ID_ANY_DOWNMIX) || + ((pDrcInstructionUniDrc->downmixId[i] == DOWNMIX_ID_BASE_LAYOUT) && + (pDrcInstructionUniDrc->drcSetId > 0))) { + *pMatchFound = 1; + break; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/* #4: The DRC set is not a "Fade-" or "Ducking-" only DRC set. */ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement4( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction, int nDynamicRangeControlOn, + int* pMatchFound) { + *pMatchFound = 0; + + if (nDynamicRangeControlOn == 1) { + if ((pDrcInstruction->drcSetEffect != EB_FADE) && + (pDrcInstruction->drcSetEffect != EB_DUCK_OTHER) && + (pDrcInstruction->drcSetEffect != EB_DUCK_SELF) && + (pDrcInstruction->drcSetEffect != 0 || pDrcInstruction->drcSetId < 0)) { + *pMatchFound = 1; + } + } else { + *pMatchFound = 1; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/* #5: The number of DRC bands is supported. Moreover, gainSetIndex and + * gainSequenceIndex are within the allowed range. */ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement5( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, + DRC_COEFFICIENTS_UNI_DRC* pCoef, int* pMatchFound) { + int b, i; + + *pMatchFound = 1; + + if (pDrcInstructionUniDrc->drcSetId < 0) /* virtual DRC sets are okay */ + { + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + if (pCoef == NULL) /* check for parametricDRC */ + { + *pMatchFound = 0; /* parametricDRC not supported */ + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + if (pCoef->drcLocation != + pDrcInstructionUniDrc + ->drcLocation) /* drcLocation must be LOCATION_SELECTED */ + { + *pMatchFound = 0; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + for (i = 0; i < pDrcInstructionUniDrc->nDrcChannelGroups; i++) { + int indexDrcCoeff = pDrcInstructionUniDrc->gainSetIndexForChannelGroup[i]; + int bandCount = 0; + + if (indexDrcCoeff >= 12) { + *pMatchFound = 0; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + if (indexDrcCoeff > pCoef->gainSetCount - 1) /* check for parametricDRC */ + { + continue; + } + + GAIN_SET* gainSet = &(pCoef->gainSet[indexDrcCoeff]); + bandCount = gainSet->bandCount; + + if (bandCount > 4) { + *pMatchFound = 0; + } + + for (b = 0; b < bandCount; b++) { + if ((gainSet->gainSequenceIndex[b] >= 12) || + (gainSet->gainSequenceIndex[b] >= pCoef->gainSequenceCount)) { + *pMatchFound = 0; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/* #6: Independent use of DRC set is permitted.*/ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement6( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, int* pMatchFound) { + *pMatchFound = 0; + + if (((pDrcInstructionUniDrc->dependsOnDrcSetPresent == 0) && + (pDrcInstructionUniDrc->noIndependentUse == 0)) || + (pDrcInstructionUniDrc->dependsOnDrcSetPresent == 1)) { + *pMatchFound = 1; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/* #7: DRC sets that require EQ are only permitted if EQ is supported. */ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement7( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, int* pMatchFound) { + *pMatchFound = 1; + + if (pDrcInstructionUniDrc->requiresEq) { + /* EQ is not supported */ + *pMatchFound = 0; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static void _setSelectionDataInfo( + DRCDEC_SELECTION_DATA* pData, FIXP_DBL loudness, /* e = 7 */ + FIXP_DBL loudnessNormalizationGainDb, /* e = 7 */ + FIXP_DBL loudnessNormalizationGainDbMax, /* e = 7 */ + FIXP_DBL loudnessDeviationMax, /* e = 7 */ + FIXP_DBL signalPeakLevel, /* e = 7 */ + FIXP_DBL outputPeakLevelMax, /* e = 7 */ + int applyAdjustment) { + FIXP_DBL adjustment = 0; /* e = 8 */ + + /* use e = 8 for all function parameters to prevent overflow */ + loudness >>= 1; + loudnessNormalizationGainDb >>= 1; + loudnessNormalizationGainDbMax >>= 1; + loudnessDeviationMax >>= 1; + signalPeakLevel >>= 1; + outputPeakLevelMax >>= 1; + + if (applyAdjustment) { + adjustment = + fMax((FIXP_DBL)0, signalPeakLevel + loudnessNormalizationGainDb - + outputPeakLevelMax); + adjustment = fMin(adjustment, fMax((FIXP_DBL)0, loudnessDeviationMax)); + } + + pData->loudnessNormalizationGainDbAdjusted = fMin( + loudnessNormalizationGainDb - adjustment, loudnessNormalizationGainDbMax); + pData->outputLoudness = loudness + pData->loudnessNormalizationGainDbAdjusted; + pData->outputPeakLevel = + signalPeakLevel + pData->loudnessNormalizationGainDbAdjusted; + + /* shift back to e = 7 using saturation */ + pData->loudnessNormalizationGainDbAdjusted = SATURATE_LEFT_SHIFT( + pData->loudnessNormalizationGainDbAdjusted, 1, DFRACT_BITS); + pData->outputLoudness = + SATURATE_LEFT_SHIFT(pData->outputLoudness, 1, DFRACT_BITS); + pData->outputPeakLevel = + SATURATE_LEFT_SHIFT(pData->outputPeakLevel, 1, DFRACT_BITS); +} + +static int _targetLoudnessInRange( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, FIXP_DBL targetLoudness) { + int retVal = 0; + + FIXP_DBL drcSetTargetLoudnessValueUpper = + ((FIXP_DBL)pDrcInstructionUniDrc->drcSetTargetLoudnessValueUpper) + << (DFRACT_BITS - 1 - 7); + FIXP_DBL drcSetTargetLoudnessValueLower = + ((FIXP_DBL)pDrcInstructionUniDrc->drcSetTargetLoudnessValueLower) + << (DFRACT_BITS - 1 - 7); + + if (pDrcInstructionUniDrc->drcSetTargetLoudnessPresent && + drcSetTargetLoudnessValueUpper >= targetLoudness && + drcSetTargetLoudnessValueLower < targetLoudness) { + retVal = 1; + } + + return retVal; +} + +static int _drcSetIsUsable(HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + DRC_INSTRUCTIONS_UNI_DRC* pInst) { + int usable = 0; + DRC_COEFFICIENTS_UNI_DRC* pCoef = + selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); + + /* check if ID is unique */ + if (selectDrcInstructions(hUniDrcConfig, pInst->drcSetId) != pInst) return 0; + /* sanity check on drcInstructions */ + _preSelectionRequirement5(pInst, pCoef, &usable); + return usable; +} + +/* #8: The range of the target loudness specified for a DRC set has to include + * the requested decoder target loudness. */ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement8( + SEL_PROC_INPUT* hSelProcInput, int downmixIdIndex, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int explicitPeakInformationPresent; + FIXP_DBL signalPeakLevel; + int addToCandidate = 0; + + FIXP_DBL loudnessNormalizationGainDb; + FIXP_DBL loudness; + + FIXP_DBL loudnessDeviationMax = + ((FIXP_DBL)hSelProcInput->loudnessDeviationMax) << (DFRACT_BITS - 1 - 7); + + { + retVal = _getLoudness(hLoudnessInfoSet, hSelProcInput->albumMode, + hSelProcInput->loudnessMeasurementMethod, + hSelProcInput->loudnessMeasurementSystem, + hSelProcInput->targetLoudness, + pDrcInstructionUniDrc->drcSetId, + hSelProcInput->downmixIdRequested[downmixIdIndex], + &loudnessNormalizationGainDb, &loudness); + if (retVal) return (retVal); + } + + if (!hSelProcInput->loudnessNormalizationOn) { + loudnessNormalizationGainDb = (FIXP_DBL)0; + } + + retVal = _getSignalPeakLevel( + hSelProcInput, hUniDrcConfig, hLoudnessInfoSet, pDrcInstructionUniDrc, + hSelProcInput->downmixIdRequested[downmixIdIndex], + &explicitPeakInformationPresent, &signalPeakLevel, codecMode + + ); + if (retVal) return (retVal); + + if (hSelProcInput->dynamicRangeControlOn) { + if (explicitPeakInformationPresent == 0) { + if (pDrcInstructionUniDrc->drcSetTargetLoudnessPresent && + ((hSelProcInput->loudnessNormalizationOn && + _targetLoudnessInRange(pDrcInstructionUniDrc, + hSelProcInput->targetLoudness)) || + !hSelProcInput->loudnessNormalizationOn)) { + DRCDEC_SELECTION_DATA* pData = + _drcdec_selection_addNew(pCandidatesSelected); + if (pData == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + _setSelectionDataInfo(pData, loudness, loudnessNormalizationGainDb, + hSelProcInput->loudnessNormalizationGainDbMax, + loudnessDeviationMax, signalPeakLevel, + hSelProcInput->outputPeakLevelMax, 0); + pData->downmixIdRequestIndex = downmixIdIndex; + pData->pInst = pDrcInstructionUniDrc; + pData->selectionFlag = + 1; /* signal pre-selection step dealing with drcSetTargetLoudness */ + + if (hSelProcInput->loudnessNormalizationOn) { + pData->outputPeakLevel = + hSelProcInput->targetLoudness - + (((FIXP_DBL)pData->pInst->drcSetTargetLoudnessValueUpper) + << (DFRACT_BITS - 1 - 7)); + } else { + pData->outputPeakLevel = (FIXP_DBL)0; + } + } else { + if ((!hSelProcInput->loudnessNormalizationOn) || + (!pDrcInstructionUniDrc->drcSetTargetLoudnessPresent) || + (hSelProcInput->loudnessNormalizationOn && + _targetLoudnessInRange(pDrcInstructionUniDrc, + hSelProcInput->targetLoudness))) { + addToCandidate = 1; + } + } + } else { + addToCandidate = 1; + } + + if (addToCandidate) { + DRCDEC_SELECTION_DATA* pData = + _drcdec_selection_addNew(pCandidatesPotential); + if (pData == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + _setSelectionDataInfo(pData, loudness, loudnessNormalizationGainDb, + hSelProcInput->loudnessNormalizationGainDbMax, + loudnessDeviationMax, signalPeakLevel, + hSelProcInput->outputPeakLevelMax, 0); + pData->downmixIdRequestIndex = downmixIdIndex; + pData->pInst = pDrcInstructionUniDrc; + pData->selectionFlag = 0; + } + } else { + if (pDrcInstructionUniDrc->drcSetId < 0) { + DRCDEC_SELECTION_DATA* pData = + _drcdec_selection_addNew(pCandidatesSelected); + if (pData == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + _setSelectionDataInfo(pData, loudness, loudnessNormalizationGainDb, + hSelProcInput->loudnessNormalizationGainDbMax, + loudnessDeviationMax, signalPeakLevel, + hSelProcInput->outputPeakLevelMax, 1); + + pData->downmixIdRequestIndex = downmixIdIndex; + pData->pInst = pDrcInstructionUniDrc; + pData->selectionFlag = 0; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/* #9: Clipping is minimized. */ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement9( + SEL_PROC_INPUT* hSelProcInput, DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + if (pCandidate->outputPeakLevel <= hSelProcInput->outputPeakLevelMax) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetPreSelectionSingleInstruction( + SEL_PROC_INPUT* hSelProcInput, int downmixIdIndex, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int matchFound = 0; + DRC_COEFFICIENTS_UNI_DRC* pCoef = + selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); + + retVal = _preSelectionRequirement123( + hSelProcInput->downmixIdRequested[downmixIdIndex], pDrcInstructionUniDrc, + &matchFound); + + if (!retVal && matchFound) + retVal = _preSelectionRequirement4(pDrcInstructionUniDrc, + hSelProcInput->dynamicRangeControlOn, + &matchFound); + + if (!retVal && matchFound) + retVal = + _preSelectionRequirement5(pDrcInstructionUniDrc, pCoef, &matchFound); + + if (!retVal && matchFound) + retVal = _preSelectionRequirement6(pDrcInstructionUniDrc, &matchFound); + + if (!retVal && matchFound) + retVal = _preSelectionRequirement7(pDrcInstructionUniDrc, &matchFound); + + if (!retVal && matchFound) + retVal = _preSelectionRequirement8( + hSelProcInput, downmixIdIndex, hUniDrcConfig, hLoudnessInfoSet, + pDrcInstructionUniDrc, pCandidatesPotential, pCandidatesSelected, + codecMode); + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetSelectionAddCandidates( + SEL_PROC_INPUT* hSelProcInput, DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int nHitCount = 0; + int i; + + DRCDEC_SELECTION_DATA* pCandidate = NULL; + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pDrcInstructionUniDrc = pCandidate->pInst; + + if (_targetLoudnessInRange(pDrcInstructionUniDrc, + hSelProcInput->targetLoudness)) { + nHitCount++; + } + } + + if (nHitCount != 0) { + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pDrcInstructionUniDrc = pCandidate->pInst; + + if (_targetLoudnessInRange(pDrcInstructionUniDrc, + hSelProcInput->targetLoudness)) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } else { + FIXP_DBL lowestPeakLevel = MAXVAL_DBL; /* e = 7 */ + FIXP_DBL peakLevel = 0; /* e = 7 */ + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + peakLevel = pCandidate->outputPeakLevel; + + if (peakLevel < lowestPeakLevel) { + lowestPeakLevel = peakLevel; + } + } + + /* add all with lowest peak level or max 1dB above */ + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + FIXP_DBL loudnessDeviationMax = + ((FIXP_DBL)hSelProcInput->loudnessDeviationMax) + << (DFRACT_BITS - 1 - 7); /* e = 7 */ + + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + peakLevel = pCandidate->outputPeakLevel; + + if (peakLevel == lowestPeakLevel || + peakLevel <= + lowestPeakLevel + FL2FXCONST_DBL(1.0f / (float)(1 << 7))) { + FIXP_DBL adjustment = + fMax((FIXP_DBL)0, peakLevel - hSelProcInput->outputPeakLevelMax); + adjustment = fMin(adjustment, fMax((FIXP_DBL)0, loudnessDeviationMax)); + + pCandidate->loudnessNormalizationGainDbAdjusted -= adjustment; + pCandidate->outputPeakLevel -= adjustment; + pCandidate->outputLoudness -= adjustment; + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _dependentDrcInstruction( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRC_INSTRUCTIONS_UNI_DRC* pInst, + DRC_INSTRUCTIONS_UNI_DRC** ppDrcInstructionsDependent) { + int i; + DRC_INSTRUCTIONS_UNI_DRC* pDependentDrc = NULL; + + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { + pDependentDrc = + (DRC_INSTRUCTIONS_UNI_DRC*)&(hUniDrcConfig->drcInstructionsUniDrc[i]); + + if (pDependentDrc->drcSetId == pInst->dependsOnDrcSet) { + break; + } + } + + if (i == hUniDrcConfig->drcInstructionsUniDrcCount) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + if (pDependentDrc->dependsOnDrcSetPresent == 1) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + *ppDrcInstructionsDependent = pDependentDrc; + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectDrcSetEffectNone( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + if ((pCandidate->pInst->drcSetEffect & 0xff) == 0) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectSingleEffectType( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRC_EFFECT_TYPE_REQUEST effectType, + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + DRC_INSTRUCTIONS_UNI_DRC* pInst; + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionsDependent; + + if (effectType == DETR_NONE) { + retVal = _selectDrcSetEffectNone(hUniDrcConfig, pCandidatesPotential, + pCandidatesSelected); + if (retVal) return (retVal); + } else { + int effectBitPosition = 1 << (effectType - 1); + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pInst = pCandidate->pInst; + + if (!pInst->dependsOnDrcSetPresent) { + if ((pInst->drcSetEffect & effectBitPosition)) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } else { + retVal = _dependentDrcInstruction(hUniDrcConfig, pInst, + &pDrcInstructionsDependent); + if (retVal) return (retVal); + + if (((pInst->drcSetEffect & effectBitPosition)) || + ((pDrcInstructionsDependent->drcSetEffect & effectBitPosition))) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectEffectTypeFeature( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRC_FEATURE_REQUEST drcFeatureRequest, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int i; + int desiredEffectTypeFound = 0; + + for (i = 0; i < drcFeatureRequest.drcEffectType.numRequestsDesired; i++) { + retVal = _selectSingleEffectType( + hUniDrcConfig, drcFeatureRequest.drcEffectType.request[i], + *ppCandidatesPotential, *ppCandidatesSelected); + if (retVal) return (retVal); + + if (_drcdec_selection_getNumber(*ppCandidatesSelected)) { + desiredEffectTypeFound = 1; + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + } + } + + if (!desiredEffectTypeFound) { + for (i = drcFeatureRequest.drcEffectType.numRequestsDesired; + i < drcFeatureRequest.drcEffectType.numRequests; i++) { + retVal = _selectSingleEffectType( + hUniDrcConfig, drcFeatureRequest.drcEffectType.request[i], + *ppCandidatesPotential, *ppCandidatesSelected); + if (retVal) return (retVal); + + if (_drcdec_selection_getNumber(*ppCandidatesSelected)) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + break; + } + } + } + + _swapSelection(ppCandidatesPotential, ppCandidatesSelected); + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectDynamicRange( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRC_FEATURE_REQUEST drcFeatureRequest, UCHAR* pDownmixIdRequested, + int albumMode, DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* ppCandidatesSelected) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int i; + int peakToAveragePresent; + FIXP_DBL peakToAverage; + + FIXP_DBL minVal = MAXVAL_DBL; + FIXP_DBL val = 0; + + int numSelectedCandidates = _drcdec_selection_getNumber(ppCandidatesSelected); + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + retVal = _dynamicRangeMeasurement( + hLoudnessInfoSet, pCandidate->pInst, + pDownmixIdRequested[pCandidate->downmixIdRequestIndex], + drcFeatureRequest.dynamicRange.measurementRequestType, albumMode, + &peakToAveragePresent, &peakToAverage); + if (retVal) return (retVal); + + if (peakToAveragePresent) { + if (!drcFeatureRequest.dynamicRange.requestedIsRange) { + val = fAbs(drcFeatureRequest.dynamicRange.requestValue - peakToAverage); + + if (minVal > val) { + minVal = val; + + _drcdec_selection_setNumber(ppCandidatesSelected, + numSelectedCandidates); + } + if (_drcdec_selection_add(ppCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } else { + if ((peakToAverage >= drcFeatureRequest.dynamicRange.requestValueMin) && + (peakToAverage <= drcFeatureRequest.dynamicRange.requestValueMax)) { + if (_drcdec_selection_add(ppCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectSingleDrcCharacteristic( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, int requestedDrcCharacteristic, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + int i, j, b; + int hit = 0; + + DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; + DRC_COEFFICIENTS_UNI_DRC* pCoef = NULL; + GAIN_SET* pGainSet = NULL; + + if (requestedDrcCharacteristic < 1) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + pCoef = selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); + + if (pCoef == NULL) /* check for parametricDRC */ + { + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + for (i = 0; i < _drcdec_selection_getNumber(*ppCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(*ppCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pInst = pCandidate->pInst; + + hit = 0; + + for (j = 0; j < pInst->nDrcChannelGroups; j++) { + int bandCount = 0; + int indexDrcCoeff = pInst->gainSetIndexForChannelGroup[j]; + + if (indexDrcCoeff > pCoef->gainSetCount - 1) /* check for parametricDRC */ + { + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + pGainSet = &(pCoef->gainSet[indexDrcCoeff]); + bandCount = pGainSet->bandCount; + + for (b = 0; b < bandCount; b++) { + if ((pGainSet->drcCharacteristic[b].isCICP) && + (pGainSet->drcCharacteristic[b].cicpIndex == + requestedDrcCharacteristic)) { + hit = 1; + break; + } + } + + if (hit) break; + } + + if (hit) { + if (_drcdec_selection_add(*ppCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected)) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectDrcCharacteristic( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, int drcCharacteristicRequested, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + const int secondTry[12] = {0, 2, 3, 4, 5, 6, 5, 9, 10, 7, 8, 10}; + + retVal = _selectSingleDrcCharacteristic( + hUniDrcConfig, drcCharacteristicRequested, ppCandidatesPotential, + ppCandidatesSelected); + if (retVal) return (retVal); + + if ((drcCharacteristicRequested <= 11) && + (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0)) { + retVal = _selectSingleDrcCharacteristic( + hUniDrcConfig, secondTry[drcCharacteristicRequested], + ppCandidatesPotential, ppCandidatesSelected); + if (retVal) return (retVal); + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { + if ((drcCharacteristicRequested >= 2) && + (drcCharacteristicRequested <= 5)) { + retVal = _selectSingleDrcCharacteristic( + hUniDrcConfig, drcCharacteristicRequested - 1, ppCandidatesPotential, + ppCandidatesSelected); + if (retVal) return (retVal); + } else if (drcCharacteristicRequested == 11) { + retVal = _selectSingleDrcCharacteristic( + hUniDrcConfig, 9, ppCandidatesPotential, ppCandidatesSelected); + if (retVal) return (retVal); + } + } + + _swapSelection(ppCandidatesPotential, ppCandidatesSelected); + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_peakValue0( + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + if (pCandidate->outputPeakLevel <= FIXP_DBL(0)) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_downmixId( + HANDLE_SEL_PROC_INPUT hSelProcInput, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + int i, j; + DRCDEC_SELECTION_DATA* pCandidate = NULL; + DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(*ppCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(*ppCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pInst = pCandidate->pInst; + + for (j = 0; j < pInst->downmixIdCount; j++) { + if (DOWNMIX_ID_BASE_LAYOUT != pInst->downmixId[j] && + DOWNMIX_ID_ANY_DOWNMIX != pInst->downmixId[j] && + hSelProcInput + ->downmixIdRequested[pCandidate->downmixIdRequestIndex] == + pInst->downmixId[j]) { + if (_drcdec_selection_add(*ppCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { + _swapSelection(ppCandidatesPotential, ppCandidatesSelected); + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static int _crossSum(int value) { + int sum = 0; + + while (value != 0) { + if ((value & 1) == 1) { + sum++; + } + + value >>= 1; + } + + return sum; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_effectTypes( + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + int minNumEffects = 1000; + int numEffects = 0; + int effects = 0; + DRCDEC_SELECTION_DATA* pCandidate = NULL; + DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pInst = pCandidate->pInst; + + effects = pInst->drcSetEffect; + effects &= 0xffff ^ (EB_GENERAL_COMPR); + numEffects = _crossSum(effects); + + if (numEffects < minNumEffects) { + minNumEffects = numEffects; + } + } + + /* add all with minimum number of effects */ + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pInst = pCandidate->pInst; + + effects = pInst->drcSetEffect; + effects &= 0xffff ^ (EB_GENERAL_COMPR); + numEffects = _crossSum(effects); + + if (numEffects == minNumEffects) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectSmallestTargetLoudnessValueUpper( + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + SCHAR minVal = 0x7F; + SCHAR val = 0; + DRCDEC_SELECTION_DATA* pCandidate = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + val = pCandidate->pInst->drcSetTargetLoudnessValueUpper; + + if (val < minVal) { + minVal = val; + } + } + + /* add all with same smallest drcSetTargetLoudnessValueUpper */ + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + val = pCandidate->pInst->drcSetTargetLoudnessValueUpper; + + if (val == minVal) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_targetLoudness( + FIXP_DBL targetLoudness, DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int i; + DRCDEC_SELECTION_DATA* pCandidate = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + if (pCandidate->selectionFlag == 0) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + if (_drcdec_selection_getNumber(pCandidatesSelected) == 0) { + retVal = _selectSmallestTargetLoudnessValueUpper(pCandidatesPotential, + pCandidatesSelected); + if (retVal) return (retVal); + } + + if (_drcdec_selection_getNumber(pCandidatesSelected) > 1) { + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc = NULL; + + _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pDrcInstructionUniDrc = pCandidate->pInst; + + if (_targetLoudnessInRange(pDrcInstructionUniDrc, targetLoudness)) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + if (_drcdec_selection_getNumber(pCandidatesSelected) > 1) { + _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); + + retVal = _selectSmallestTargetLoudnessValueUpper(pCandidatesPotential, + pCandidatesSelected); + if (retVal) return (retVal); + } + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_peakValueLargest( + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + FIXP_DBL largestPeakLevel = MINVAL_DBL; + FIXP_DBL peakLevel = 0; + DRCDEC_SELECTION_DATA* pCandidate = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + peakLevel = pCandidate->outputPeakLevel; + + if (peakLevel > largestPeakLevel) { + largestPeakLevel = peakLevel; + } + } + + /* add all with same largest peak level */ + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + peakLevel = pCandidate->outputPeakLevel; + + if (peakLevel == largestPeakLevel) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_drcSetId( + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + int largestId = -1000; + int id = 0; + DRCDEC_SELECTION_DATA* pCandidate = NULL; + DRCDEC_SELECTION_DATA* pCandidateSelected = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + id = pCandidate->pInst->drcSetId; + + if (id > largestId) { + largestId = id; + pCandidateSelected = pCandidate; + } + } + + if (pCandidateSelected != NULL) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidateSelected) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } else { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (_drcdec_selection_getNumber(*ppCandidatesPotential) == 0) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } else if (_drcdec_selection_getNumber(*ppCandidatesPotential) == 1) { + _swapSelection(ppCandidatesPotential, ppCandidatesSelected); + /* finished */ + } else /* > 1 */ + { + retVal = _drcSetFinalSelection_peakValue0(*ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return (retVal); + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + retVal = _drcSetFinalSelection_downmixId( + hSelProcInput, ppCandidatesPotential, ppCandidatesSelected); + if (retVal) return (retVal); + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + retVal = _drcSetFinalSelection_effectTypes(*ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return (retVal); + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + retVal = _drcSetFinalSelection_targetLoudness( + hSelProcInput->targetLoudness, *ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return (retVal); + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + retVal = _drcSetFinalSelection_peakValueLargest(*ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return (retVal); + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + retVal = _drcSetFinalSelection_drcSetId(*ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return (retVal); + } + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _generateVirtualDrcSets( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + SEL_PROC_CODEC_MODE codecMode) { + int i; + int nMixes = hUniDrcConfig->downmixInstructionsCount + 1; + int index = hUniDrcConfig->drcInstructionsUniDrcCount; + int indexVirtual = -1; + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction = + &(hUniDrcConfig->drcInstructionsUniDrc[index]); + + if (codecMode == SEL_PROC_MPEG_H_3DA) { + nMixes = 1; + } + + if ((index + nMixes) > (12 + 1 + 6)) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + FDKmemset(pDrcInstruction, 0, sizeof(DRC_INSTRUCTIONS_UNI_DRC)); + + pDrcInstruction->drcSetId = indexVirtual; + index++; + indexVirtual--; + pDrcInstruction->downmixIdCount = 1; + + if ((codecMode == SEL_PROC_MPEG_H_3DA) && + (hSelProcInput->numDownmixIdRequests)) { + pDrcInstruction->downmixId[0] = hSelProcInput->downmixIdRequested[0]; + } else { + pDrcInstruction->downmixId[0] = DOWNMIX_ID_BASE_LAYOUT; + } + + for (i = 1; i < nMixes; i++) { + pDrcInstruction = &(hUniDrcConfig->drcInstructionsUniDrc[index]); + FDKmemset(pDrcInstruction, 0, sizeof(DRC_INSTRUCTIONS_UNI_DRC)); + pDrcInstruction->drcSetId = indexVirtual; + pDrcInstruction->downmixId[0] = + hUniDrcConfig->downmixInstructions[i - 1].downmixId; + pDrcInstruction->downmixIdCount = 1; + index++; + indexVirtual--; + } + + hUniDrcConfig->drcInstructionsCountInclVirtual = + hUniDrcConfig->drcInstructionsUniDrcCount + nMixes; + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _generateOutputInfo( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_SEL_PROC_OUTPUT hSelProcOutput, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION_DATA* pSelectionData, SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + int i, j; + int hasDependend = 0; + int hasFading = 0; + int hasDucking = 0; + int selectedDrcSetIds; + int selectedDownmixIds; + FIXP_DBL mixingLevel = 0; + int albumMode = hSelProcInput->albumMode; + UCHAR* pDownmixIdRequested = hSelProcInput->downmixIdRequested; + FIXP_SGL boost = hSelProcInput->boost; + FIXP_SGL compress = hSelProcInput->compress; + + hSelProcOutput->numSelectedDrcSets = 1; + hSelProcOutput->selectedDrcSetIds[0] = pSelectionData->pInst->drcSetId; + hSelProcOutput->selectedDownmixIds[0] = + pSelectionData->pInst->drcApplyToDownmix == 1 + ? pSelectionData->pInst->downmixId[0] + : 0; + hSelProcOutput->loudnessNormalizationGainDb = + pSelectionData->loudnessNormalizationGainDbAdjusted + + hSelProcInput->loudnessNormalizationGainModificationDb; + hSelProcOutput->outputPeakLevelDb = pSelectionData->outputPeakLevel; + hSelProcOutput->outputLoudness = pSelectionData->outputLoudness; + + hSelProcOutput->boost = boost; + hSelProcOutput->compress = compress; + hSelProcOutput->baseChannelCount = + hUniDrcConfig->channelLayout.baseChannelCount; + hSelProcOutput->targetChannelCount = + hUniDrcConfig->channelLayout.baseChannelCount; + hSelProcOutput->activeDownmixId = + pDownmixIdRequested[pSelectionData->downmixIdRequestIndex]; + + _getMixingLevel(hLoudnessInfoSet, *pDownmixIdRequested, + hSelProcOutput->selectedDrcSetIds[0], albumMode, + &mixingLevel); + hSelProcOutput->mixingLevel = mixingLevel; + + /*dependent*/ + if (pSelectionData->pInst->dependsOnDrcSetPresent) { + int dependsOnDrcSetID = pSelectionData->pInst->dependsOnDrcSet; + + for (i = 0; i < hUniDrcConfig->drcInstructionsCountInclVirtual; i++) { + DRC_INSTRUCTIONS_UNI_DRC* pInst = + &(hUniDrcConfig->drcInstructionsUniDrc[i]); + if (!_drcSetIsUsable(hUniDrcConfig, pInst)) continue; + + if (pInst->drcSetId == dependsOnDrcSetID) { + hSelProcOutput->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = + hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; + hSelProcOutput->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = + hUniDrcConfig->drcInstructionsUniDrc[i].drcApplyToDownmix == 1 + ? hUniDrcConfig->drcInstructionsUniDrc[i].downmixId[0] + : 0; + hSelProcOutput->numSelectedDrcSets++; + hasDependend = 1; + break; + } + } + } + + /* fading */ + if (hSelProcInput->albumMode == 0) { + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { + DRC_INSTRUCTIONS_UNI_DRC* pInst = + &(hUniDrcConfig->drcInstructionsUniDrc[i]); + if (!_drcSetIsUsable(hUniDrcConfig, pInst)) continue; + + if (pInst->drcSetEffect & EB_FADE) { + if (pInst->downmixId[0] == DOWNMIX_ID_ANY_DOWNMIX) { + hSelProcOutput->numSelectedDrcSets = hasDependend + 1; + hSelProcOutput + ->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = + hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; + hSelProcOutput + ->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = + hUniDrcConfig->drcInstructionsUniDrc[i].drcApplyToDownmix == 1 + ? hUniDrcConfig->drcInstructionsUniDrc[i].downmixId[0] + : 0; + hSelProcOutput->numSelectedDrcSets++; + hasFading = 1; + + } else { + retVal = DRCDEC_SELECTION_PROCESS_NOT_OK; + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + } + + /* ducking */ + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { + DRC_INSTRUCTIONS_UNI_DRC* pInst = + &(hUniDrcConfig->drcInstructionsUniDrc[i]); + if (!_drcSetIsUsable(hUniDrcConfig, pInst)) continue; + + if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { + for (j = 0; j < pInst->downmixIdCount; j++) { + if (pInst->downmixId[j] == hSelProcOutput->activeDownmixId) { + hSelProcOutput->numSelectedDrcSets = + hasDependend + 1; /* ducking overrides fading */ + + hSelProcOutput + ->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = + hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; + /* force ducking DRC set to be processed on base layout */ + hSelProcOutput + ->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = 0; + hSelProcOutput->numSelectedDrcSets++; + hasDucking = 1; + } + } + } + } + + /* repeat for DOWNMIX_ID_BASE_LAYOUT if no ducking found*/ + + if (!hasDucking) { + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { + DRC_INSTRUCTIONS_UNI_DRC* pInst = + &(hUniDrcConfig->drcInstructionsUniDrc[i]); + if (!_drcSetIsUsable(hUniDrcConfig, pInst)) continue; + + if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { + for (j = 0; j < pInst->downmixIdCount; j++) { + if (pInst->downmixId[j] == DOWNMIX_ID_BASE_LAYOUT) { + hSelProcOutput->numSelectedDrcSets = hasDependend + hasFading + 1; + hSelProcOutput + ->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = + hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; + /* force ducking DRC set to be processed on base layout */ + hSelProcOutput + ->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = 0; + hSelProcOutput->numSelectedDrcSets++; + } + } + } + } + } + + if (hSelProcOutput->numSelectedDrcSets > 3) { + /* maximum permitted number of applied DRC sets is 3, see section 6.3.5 of + * ISO/IEC 23003-4 */ + hSelProcOutput->numSelectedDrcSets = 0; + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + /* sorting: Ducking/Fading -> Dependent -> Selected */ + if (hSelProcOutput->numSelectedDrcSets == 3) { + selectedDrcSetIds = hSelProcOutput->selectedDrcSetIds[0]; + selectedDownmixIds = hSelProcOutput->selectedDownmixIds[0]; + hSelProcOutput->selectedDrcSetIds[0] = hSelProcOutput->selectedDrcSetIds[2]; + hSelProcOutput->selectedDownmixIds[0] = + hSelProcOutput->selectedDownmixIds[2]; + hSelProcOutput->selectedDrcSetIds[2] = selectedDrcSetIds; + hSelProcOutput->selectedDownmixIds[2] = selectedDownmixIds; + } else if (hSelProcOutput->numSelectedDrcSets == 2) { + selectedDrcSetIds = hSelProcOutput->selectedDrcSetIds[0]; + selectedDownmixIds = hSelProcOutput->selectedDownmixIds[0]; + hSelProcOutput->selectedDrcSetIds[0] = hSelProcOutput->selectedDrcSetIds[1]; + hSelProcOutput->selectedDownmixIds[0] = + hSelProcOutput->selectedDownmixIds[1]; + hSelProcOutput->selectedDrcSetIds[1] = selectedDrcSetIds; + hSelProcOutput->selectedDownmixIds[1] = selectedDownmixIds; + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectDownmixMatrix( + HANDLE_SEL_PROC_OUTPUT hSelProcOutput, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { + int i; + hSelProcOutput->baseChannelCount = + hUniDrcConfig->channelLayout.baseChannelCount; + hSelProcOutput->targetChannelCount = + hUniDrcConfig->channelLayout.baseChannelCount; + hSelProcOutput->targetLayout = -1; + hSelProcOutput->downmixMatrixPresent = 0; + + if (hSelProcOutput->activeDownmixId != 0) { + for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { + DOWNMIX_INSTRUCTIONS* pDown = &(hUniDrcConfig->downmixInstructions[i]); + if (pDown->targetChannelCount > 8) { + continue; + } + + if (hSelProcOutput->activeDownmixId == pDown->downmixId) { + hSelProcOutput->targetChannelCount = pDown->targetChannelCount; + hSelProcOutput->targetLayout = pDown->targetLayout; + + if (pDown->downmixCoefficientsPresent) { + int j, k; + FIXP_DBL downmixOffset = getDownmixOffset( + pDown, hSelProcOutput->baseChannelCount); /* e = 1 */ + + for (j = 0; j < hSelProcOutput->baseChannelCount; j++) { + for (k = 0; k < hSelProcOutput->targetChannelCount; k++) { + hSelProcOutput->downmixMatrix[j][k] = + fMultDiv2( + downmixOffset, + pDown->downmixCoefficient[j + k * hSelProcOutput + ->baseChannelCount]) + << 2; + } + } + + hSelProcOutput->downmixMatrixPresent = 1; + } + break; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetPreSelection( + SEL_PROC_INPUT* hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int i, j; + + for (i = 0; i < hSelProcInput->numDownmixIdRequests; i++) { + for (j = 0; j < hUniDrcConfig->drcInstructionsCountInclVirtual; j++) { + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction = + &(hUniDrcConfig->drcInstructionsUniDrc[j]); + /* check if ID is unique */ + if (selectDrcInstructions(hUniDrcConfig, pDrcInstruction->drcSetId) != + pDrcInstruction) + continue; + + retVal = _drcSetPreSelectionSingleInstruction( + hSelProcInput, i, hUniDrcConfig, hLoudnessInfoSet, pDrcInstruction, + *ppCandidatesPotential, *ppCandidatesSelected, codecMode); + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + retVal = _preSelectionRequirement9(hSelProcInput, *ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { + retVal = _drcSetSelectionAddCandidates( + hSelProcInput, *ppCandidatesPotential, *ppCandidatesSelected); + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetRequestSelection( + SEL_PROC_INPUT* hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + DRCDEC_SELECTION_PROCESS_RETURN retVal; + int i; + + if (_drcdec_selection_getNumber(*ppCandidatesPotential) == 0) { + retVal = DRCDEC_SELECTION_PROCESS_NOT_OK; + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + if (hSelProcInput->dynamicRangeControlOn) { + if (hSelProcInput->numDrcFeatureRequests == 0) { + retVal = _selectDrcSetEffectNone(hUniDrcConfig, *ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return (retVal); + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { + DRC_FEATURE_REQUEST fallbackRequest; + fallbackRequest.drcEffectType.numRequests = 5; + fallbackRequest.drcEffectType.numRequestsDesired = 5; + fallbackRequest.drcEffectType.request[0] = DETR_GENERAL_COMPR; + fallbackRequest.drcEffectType.request[1] = DETR_NIGHT; + fallbackRequest.drcEffectType.request[2] = DETR_NOISY; + fallbackRequest.drcEffectType.request[3] = DETR_LIMITED; + fallbackRequest.drcEffectType.request[4] = DETR_LOWLEVEL; + + retVal = _selectEffectTypeFeature(hUniDrcConfig, fallbackRequest, + ppCandidatesPotential, + ppCandidatesSelected); + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + } else { + for (i = 0; i < hSelProcInput->numDrcFeatureRequests; i++) { + if (hSelProcInput->drcFeatureRequestType[i] == DFRT_EFFECT_TYPE) { + retVal = _selectEffectTypeFeature( + hUniDrcConfig, hSelProcInput->drcFeatureRequest[i], + ppCandidatesPotential, ppCandidatesSelected); + + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + else if (hSelProcInput->drcFeatureRequestType[i] == + DFRT_DYNAMIC_RANGE) { + retVal = _selectDynamicRange( + hUniDrcConfig, hLoudnessInfoSet, + hSelProcInput->drcFeatureRequest[i], + hSelProcInput->downmixIdRequested, hSelProcInput->albumMode, + *ppCandidatesPotential, *ppCandidatesSelected); + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 0) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + } + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } else if (hSelProcInput->drcFeatureRequestType[i] == + DFRT_DRC_CHARACTERISTIC) { + retVal = _selectDrcCharacteristic( + hUniDrcConfig, + hSelProcInput->drcFeatureRequest[i].drcCharacteristic, + ppCandidatesPotential, ppCandidatesSelected); + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 0) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + } + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ +static DRCDEC_SELECTION_PROCESS_RETURN _dynamicRangeMeasurement( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, DRC_INSTRUCTIONS_UNI_DRC* pInst, + UCHAR downmixIdRequested, + DYN_RANGE_MEASUREMENT_REQUEST_TYPE dynamicRangeMeasurementType, + int albumMode, int* pPeakToAveragePresent, FIXP_DBL* pPeakToAverage) { + int i; + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int drcSetId = fMax(0, pInst->drcSetId); + + *pPeakToAveragePresent = 0; + + if (albumMode) { + for (i = 0; i < hLoudnessInfoSet->loudnessInfoAlbumCount; i++) { + LOUDNESS_INFO* pLoudnessInfo = &(hLoudnessInfoSet->loudnessInfoAlbum[i]); + + if (drcSetId == pLoudnessInfo->drcSetId) { + if (downmixIdRequested == pLoudnessInfo->downmixId) { + retVal = _extractLoudnessPeakToAverageValue( + pLoudnessInfo, dynamicRangeMeasurementType, pPeakToAveragePresent, + pPeakToAverage); + if (retVal) return (retVal); + } + } + } + } + + if (*pPeakToAveragePresent == 0) { + for (i = 0; i < hLoudnessInfoSet->loudnessInfoCount; i++) { + LOUDNESS_INFO* pLoudnessInfo = &(hLoudnessInfoSet->loudnessInfo[i]); + + if (drcSetId == pLoudnessInfo->drcSetId) { + if (downmixIdRequested == pLoudnessInfo->downmixId) { + retVal = _extractLoudnessPeakToAverageValue( + pLoudnessInfo, dynamicRangeMeasurementType, pPeakToAveragePresent, + pPeakToAverage); + if (retVal) return (retVal); + } + } + } + } + + return retVal; +} +/*******************************************/ + +static DRCDEC_SELECTION_DATA* _drcdec_selection_addNew( + DRCDEC_SELECTION* pSelection) { + if (pSelection->numData < (12 + 1 + 6)) { + DRCDEC_SELECTION_DATA* pData = &(pSelection->data[pSelection->numData]); + FDKmemset(pData, 0, sizeof(DRCDEC_SELECTION_DATA)); + pSelection->numData++; + + return pData; + } else { + return NULL; + } +} + +static DRCDEC_SELECTION_DATA* _drcdec_selection_add( + DRCDEC_SELECTION* pSelection, DRCDEC_SELECTION_DATA* pDataIn) { + if (pSelection->numData < (12 + 1 + 6)) { + DRCDEC_SELECTION_DATA* pData = &(pSelection->data[pSelection->numData]); + FDKmemcpy(pData, pDataIn, sizeof(DRCDEC_SELECTION_DATA)); + pSelection->numData++; + return pData; + } else { + return NULL; + } +} + +static int _drcdec_selection_clear(DRCDEC_SELECTION* pSelection) { + return pSelection->numData = 0; +} + +static int _drcdec_selection_getNumber(DRCDEC_SELECTION* pSelection) { + return pSelection->numData; +} + +static int _drcdec_selection_setNumber(DRCDEC_SELECTION* pSelection, int num) { + if (num >= 0 && num < pSelection->numData) { + return pSelection->numData = num; + } else { + return pSelection->numData; + } +} + +static DRCDEC_SELECTION_DATA* _drcdec_selection_getAt( + DRCDEC_SELECTION* pSelection, int at) { + if (at >= 0 && at < (12 + 1 + 6)) { + return &(pSelection->data[at]); + } else { + return NULL; + } +} + +static int _swapSelectionAndClear(DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + DRCDEC_SELECTION* pTmp = *ppCandidatesPotential; + *ppCandidatesPotential = *ppCandidatesSelected; + *ppCandidatesSelected = pTmp; + _drcdec_selection_clear(*ppCandidatesSelected); + return 0; +} + +static int _swapSelection(DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + DRCDEC_SELECTION* pTmp = *ppCandidatesPotential; + *ppCandidatesPotential = *ppCandidatesSelected; + *ppCandidatesSelected = pTmp; + return 0; +} + +/*******************************************/ + +static LOUDNESS_INFO* _getLoudnessInfoStructure( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, int downmixId, + int albumMode) { + int i, j; + int count; + + LOUDNESS_INFO* pLoudnessInfo = NULL; + + if (albumMode) { + count = hLoudnessInfoSet->loudnessInfoAlbumCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; + } else { + count = hLoudnessInfoSet->loudnessInfoCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; + } + + for (i = 0; i < count; i++) { + if ((pLoudnessInfo[i].drcSetId == drcSetId) && + (pLoudnessInfo[i].downmixId == downmixId)) { + for (j = 0; j < pLoudnessInfo[i].measurementCount; j++) { + if ((pLoudnessInfo[i].loudnessMeasurement[j].methodDefinition == 1) || + (pLoudnessInfo[i].loudnessMeasurement[j].methodDefinition == 2)) { + return &pLoudnessInfo[i]; + } + } + } + } + + return NULL; +} + +static LOUDNESS_INFO* _getApplicableLoudnessInfoStructure( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, + int downmixIdRequested, int albumMode) { + LOUDNESS_INFO* pLoudnessInfo = NULL; + + /* default value */ + pLoudnessInfo = _getLoudnessInfoStructure(hLoudnessInfoSet, drcSetId, + downmixIdRequested, albumMode); + + /* fallback values */ + if (pLoudnessInfo == NULL) { + pLoudnessInfo = + _getLoudnessInfoStructure(hLoudnessInfoSet, drcSetId, 0x7F, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = _getLoudnessInfoStructure(hLoudnessInfoSet, 0x3F, + downmixIdRequested, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = _getLoudnessInfoStructure(hLoudnessInfoSet, 0, + downmixIdRequested, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = + _getLoudnessInfoStructure(hLoudnessInfoSet, 0x3F, 0x7F, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = + _getLoudnessInfoStructure(hLoudnessInfoSet, 0, 0x7F, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = + _getLoudnessInfoStructure(hLoudnessInfoSet, drcSetId, 0, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = + _getLoudnessInfoStructure(hLoudnessInfoSet, 0x3F, 0, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = + _getLoudnessInfoStructure(hLoudnessInfoSet, 0, 0, albumMode); + } + + return pLoudnessInfo; +} + +/*******************************************/ + +typedef struct { + FIXP_DBL value; + int order; +} VALUE_ORDER; + +void _initValueOrder(VALUE_ORDER* pValue) { + pValue->value = (FIXP_DBL)0; + pValue->order = -1; +} + +enum { + MS_BONUS0 = 0, + MS_BONUS1770, + MS_BONUSUSER, + MS_BONUSEXPERT, + MS_RESA, + MS_RESB, + MS_RESC, + MS_RESD, + MS_RESE, + MS_PROGRAMLOUDNESS, + MS_PEAKLOUDNESS +}; + +static DRCDEC_SELECTION_PROCESS_RETURN _getMethodValue( + VALUE_ORDER* pValueOrder, FIXP_DBL value, int measurementSystem, + int measurementSystemRequested) { + const int rows = 11; + const int columns = 12; + const int pOrdering[rows][columns] = { + {0, 0, 8, 0, 1, 3, 0, 5, 6, 7, 4, 2}, /* default = bonus1770 */ + {0, 0, 8, 0, 1, 3, 0, 5, 6, 7, 4, 2}, /* bonus1770 */ + {0, 0, 1, 0, 8, 5, 0, 2, 3, 4, 6, 7}, /* bonusUser */ + {0, 0, 3, 0, 1, 8, 0, 4, 5, 6, 7, 2}, /* bonusExpert */ + {0, 0, 5, 0, 1, 3, 0, 8, 6, 7, 4, 2}, /* ResA */ + {0, 0, 5, 0, 1, 3, 0, 6, 8, 7, 4, 2}, /* ResB */ + {0, 0, 5, 0, 1, 3, 0, 6, 7, 8, 4, 2}, /* ResC */ + {0, 0, 3, 0, 1, 7, 0, 4, 5, 6, 8, 2}, /* ResD */ + {0, 0, 1, 0, 7, 5, 0, 2, 3, 4, 6, 8}, /* ResE */ + {0, 0, 1, 0, 0, 0, 0, 2, 3, 4, 0, 0}, /* ProgramLoudness */ + {0, 7, 0, 0, 0, 0, 6, 5, 4, 3, 2, 1} /* PeakLoudness */ + }; + + if (measurementSystemRequested < 0 || measurementSystemRequested >= rows || + measurementSystem < 0 || measurementSystem >= columns) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + if (pOrdering[measurementSystemRequested][measurementSystem] > + pValueOrder->order) { + pValueOrder->order = + pOrdering[measurementSystemRequested][measurementSystem]; + pValueOrder->value = value; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ + +static DRCDEC_SELECTION_PROCESS_RETURN _getLoudness( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int albumMode, + METHOD_DEFINITION_REQUEST measurementMethodRequested, + MEASUREMENT_SYSTEM_REQUEST measurementSystemRequested, + FIXP_DBL targetLoudness, /* e = 7 */ + int drcSetId, int downmixIdRequested, + FIXP_DBL* pLoudnessNormalizationGain, /* e = 7 */ + FIXP_DBL* pLoudness) /* e = 7 */ +{ + int index; + + LOUDNESS_INFO* pLoudnessInfo = NULL; + VALUE_ORDER valueOrder; + + /* map MDR_DEFAULT to MDR_PROGRAM_LOUDNESS */ + METHOD_DEFINITION_REQUEST requestedMethodDefinition = + measurementMethodRequested < MDR_ANCHOR_LOUDNESS ? MDR_PROGRAM_LOUDNESS + : MDR_ANCHOR_LOUDNESS; + + if (measurementMethodRequested > MDR_ANCHOR_LOUDNESS) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + _initValueOrder(&valueOrder); + + *pLoudness = UNDEFINED_LOUDNESS_VALUE; + *pLoudnessNormalizationGain = (FIXP_DBL)0; + + if (drcSetId < 0) { + drcSetId = 0; + } + + pLoudnessInfo = _getApplicableLoudnessInfoStructure( + hLoudnessInfoSet, drcSetId, downmixIdRequested, albumMode); + + if (albumMode && (pLoudnessInfo == NULL)) { + pLoudnessInfo = _getApplicableLoudnessInfoStructure( + hLoudnessInfoSet, drcSetId, downmixIdRequested, 0); + } + + if (pLoudnessInfo == NULL) { + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + index = -1; + + do { + index = _findMethodDefinition(pLoudnessInfo, requestedMethodDefinition, + index + 1); + + if (index >= 0) { + _getMethodValue( + &valueOrder, pLoudnessInfo->loudnessMeasurement[index].methodValue, + pLoudnessInfo->loudnessMeasurement[index].measurementSystem, + measurementSystemRequested); + } + } while (index >= 0); + + /* repeat with other method definition */ + if (valueOrder.order == -1) { + index = -1; + + do { + index = _findMethodDefinition( + pLoudnessInfo, + requestedMethodDefinition == MDR_PROGRAM_LOUDNESS + ? MDR_ANCHOR_LOUDNESS + : MDR_PROGRAM_LOUDNESS, + index + 1); + + if (index >= 0) { + _getMethodValue( + &valueOrder, pLoudnessInfo->loudnessMeasurement[index].methodValue, + pLoudnessInfo->loudnessMeasurement[index].measurementSystem, + measurementSystemRequested); + } + } while (index >= 0); + } + + if (valueOrder.order == -1) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } else { + *pLoudnessNormalizationGain = targetLoudness - valueOrder.value; + *pLoudness = valueOrder.value; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ + +static int _truePeakLevelIsPresent(HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + int drcSetId, int downmixId, int albumMode) { + int i; + int count; + LOUDNESS_INFO* pLoudnessInfo = NULL; + + if (albumMode) { + count = hLoudnessInfoSet->loudnessInfoAlbumCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; + } else { + count = hLoudnessInfoSet->loudnessInfoCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; + } + + for (i = 0; i < count; i++) { + if ((pLoudnessInfo[i].drcSetId == drcSetId) && + (pLoudnessInfo[i].downmixId == downmixId)) { + if (pLoudnessInfo[i].truePeakLevelPresent) return 1; + } + } + + return 0; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _getTruePeakLevel( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, int downmixId, + int albumMode, FIXP_DBL* pTruePeakLevel) { + int i; + int count; + LOUDNESS_INFO* pLoudnessInfo = NULL; + + if (albumMode) { + count = hLoudnessInfoSet->loudnessInfoAlbumCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; + } else { + count = hLoudnessInfoSet->loudnessInfoCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; + } + + for (i = 0; i < count; i++) { + if ((pLoudnessInfo[i].drcSetId == drcSetId) && + (pLoudnessInfo[i].downmixId == downmixId)) { + if (pLoudnessInfo[i].truePeakLevelPresent) { + *pTruePeakLevel = pLoudnessInfo[i].truePeakLevel; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NOT_OK; +} + +static int _samplePeakLevelIsPresent(HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + int drcSetId, int downmixId, + int albumMode) { + int i; + int count; + LOUDNESS_INFO* pLoudnessInfo = NULL; + + if (albumMode) { + count = hLoudnessInfoSet->loudnessInfoAlbumCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; + } else { + count = hLoudnessInfoSet->loudnessInfoCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; + } + + for (i = 0; i < count; i++) { + if ((pLoudnessInfo[i].drcSetId == drcSetId) && + (pLoudnessInfo[i].downmixId == downmixId)) { + if (pLoudnessInfo[i].samplePeakLevelPresent) return 1; + } + } + + return 0; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _getSamplePeakLevel( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, int downmixId, + int albumMode, FIXP_DBL* pSamplePeakLevel /* e = 7 */ +) { + int i; + int count; + LOUDNESS_INFO* pLoudnessInfo = NULL; + + if (albumMode) { + count = hLoudnessInfoSet->loudnessInfoAlbumCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; + } else { + count = hLoudnessInfoSet->loudnessInfoCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; + } + + for (i = 0; i < count; i++) { + if ((pLoudnessInfo[i].drcSetId == drcSetId) && + (pLoudnessInfo[i].downmixId == downmixId)) { + if (pLoudnessInfo[i].samplePeakLevelPresent) { + *pSamplePeakLevel = pLoudnessInfo[i].samplePeakLevel; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NOT_OK; +} + +static int _limiterPeakTargetIsPresent( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction, int drcSetId, int downmixId) { + int i; + + if (pDrcInstruction->limiterPeakTargetPresent) { + if ((pDrcInstruction->downmixId[0] == downmixId) || + (pDrcInstruction->downmixId[0] == 0x7F)) { + return 1; + } + + for (i = 0; i < pDrcInstruction->downmixIdCount; i++) { + if (pDrcInstruction->downmixId[i] == downmixId) { + return 1; + } + } + } + + return 0; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _getLimiterPeakTarget( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction, int drcSetId, int downmixId, + FIXP_DBL* pLimiterPeakTarget) { + int i; + + if (pDrcInstruction->limiterPeakTargetPresent) { + if ((pDrcInstruction->downmixId[0] == downmixId) || + (pDrcInstruction->downmixId[0] == 0x7F)) { + *pLimiterPeakTarget = + ((FX_SGL2FX_DBL(pDrcInstruction->limiterPeakTarget) >> 2)); + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + for (i = 0; i < pDrcInstruction->downmixIdCount; i++) { + if (pDrcInstruction->downmixId[i] == downmixId) { + *pLimiterPeakTarget = + ((FX_SGL2FX_DBL(pDrcInstruction->limiterPeakTarget) >> 2)); + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NOT_OK; +} + +static int _downmixCoefficientsArePresent(HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + int downmixId, int* pIndex) { + int i; + *pIndex = -1; + + for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { + if (hUniDrcConfig->downmixInstructions[i].downmixId == downmixId) { + if (hUniDrcConfig->downmixInstructions[i].downmixCoefficientsPresent) { + if (hUniDrcConfig->downmixInstructions[i].targetChannelCount > 8) + return 0; + *pIndex = i; + return 1; + } + } + } + + return 0; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _getSignalPeakLevel( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, DRC_INSTRUCTIONS_UNI_DRC* pInst, + int downmixIdRequested, int* explicitPeakInformationPresent, + FIXP_DBL* signalPeakLevelOut, /* e = 7 */ + SEL_PROC_CODEC_MODE codecMode + +) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + int albumMode = hSelProcInput->albumMode; + + FIXP_DBL signalPeakLevelTmp = (FIXP_DBL)0; + FIXP_DBL signalPeakLevel = FIXP_DBL(0); + + int dmxId = downmixIdRequested; + + int drcSetId = pInst->drcSetId; + + if (drcSetId < 0) { + drcSetId = 0; + } + + *explicitPeakInformationPresent = 1; + + if (_truePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, dmxId, albumMode)) { + retVal = _getTruePeakLevel(hLoudnessInfoSet, drcSetId, dmxId, albumMode, + &signalPeakLevel); + if (retVal) return (retVal); + } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, dmxId, + albumMode)) { + retVal = _getSamplePeakLevel(hLoudnessInfoSet, drcSetId, dmxId, albumMode, + &signalPeakLevel); + if (retVal) return (retVal); + } else if (_truePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, dmxId, + albumMode)) { + retVal = _getTruePeakLevel(hLoudnessInfoSet, 0x3F, dmxId, albumMode, + &signalPeakLevel); + if (retVal) return (retVal); + } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, dmxId, + albumMode)) { + retVal = _getSamplePeakLevel(hLoudnessInfoSet, 0x3F, dmxId, albumMode, + &signalPeakLevel); + if (retVal) return (retVal); + } else if (_limiterPeakTargetIsPresent(pInst, drcSetId, dmxId)) { + retVal = _getLimiterPeakTarget(pInst, drcSetId, dmxId, &signalPeakLevel); + if (retVal) return (retVal); + } else if (dmxId != 0) { + int downmixInstructionIndex = 0; + FIXP_DBL downmixPeakLevelDB = 0; + + *explicitPeakInformationPresent = 0; + + signalPeakLevelTmp = FIXP_DBL(0); + + if (_downmixCoefficientsArePresent(hUniDrcConfig, dmxId, + &downmixInstructionIndex)) { + FIXP_DBL dB_m; + int dB_e; + FIXP_DBL coeff; + FIXP_DBL sum, maxSum; /* e = 7, so it is possible to sum up up to 32 + downmix coefficients (with e = 2) */ + int i, j; + DOWNMIX_INSTRUCTIONS* pDown = + &(hUniDrcConfig->downmixInstructions[downmixInstructionIndex]); + FIXP_DBL downmixOffset = getDownmixOffset( + pDown, hUniDrcConfig->channelLayout.baseChannelCount); /* e = 1 */ + maxSum = (FIXP_DBL)0; + + for (i = 0; i < pDown->targetChannelCount; i++) { + sum = (FIXP_DBL)0; + for (j = 0; j < hUniDrcConfig->channelLayout.baseChannelCount; j++) { + coeff = pDown->downmixCoefficient[j + i * hUniDrcConfig->channelLayout + .baseChannelCount]; + sum += coeff >> 5; + } + if (maxSum < sum) maxSum = sum; + } + + maxSum = fMultDiv2(maxSum, downmixOffset) << 2; + + if (maxSum == FL2FXCONST_DBL(1.0f / (float)(1 << 7))) { + downmixPeakLevelDB = (FIXP_DBL)0; + } else { + dB_m = lin2dB(maxSum, 7, &dB_e); /* e_maxSum = 7 */ + downmixPeakLevelDB = + scaleValue(dB_m, dB_e - 7); /* e_downmixPeakLevelDB = 7 */ + } + } + + if (_truePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, 0, albumMode)) { + retVal = _getTruePeakLevel(hLoudnessInfoSet, drcSetId, 0, albumMode, + &signalPeakLevelTmp); + if (retVal) return (retVal); + } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, 0, + albumMode)) { + retVal = _getSamplePeakLevel(hLoudnessInfoSet, drcSetId, 0, albumMode, + &signalPeakLevelTmp); + if (retVal) return (retVal); + } else if (_truePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, 0, albumMode)) { + retVal = _getTruePeakLevel(hLoudnessInfoSet, 0x3F, 0, albumMode, + &signalPeakLevelTmp); + if (retVal) return (retVal); + } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, 0, + albumMode)) { + retVal = _getSamplePeakLevel(hLoudnessInfoSet, 0x3F, 0, albumMode, + &signalPeakLevelTmp); + if (retVal) return (retVal); + } else if (_limiterPeakTargetIsPresent(pInst, drcSetId, 0)) { + retVal = _getLimiterPeakTarget(pInst, drcSetId, 0, &signalPeakLevelTmp); + if (retVal) return (retVal); + } + + signalPeakLevel = signalPeakLevelTmp + downmixPeakLevelDB; + } else { + signalPeakLevel = FIXP_DBL(0); /* worst case estimate */ + *explicitPeakInformationPresent = FIXP_DBL(0); + } + + *signalPeakLevelOut = signalPeakLevel; + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _extractLoudnessPeakToAverageValue( + LOUDNESS_INFO* loudnessInfo, + DYN_RANGE_MEASUREMENT_REQUEST_TYPE dynamicRangeMeasurementType, + int* pLoudnessPeakToAverageValuePresent, + FIXP_DBL* pLoudnessPeakToAverageValue) { + int i; + + VALUE_ORDER valueOrderLoudness; + VALUE_ORDER valueOrderPeakLoudness; + + _initValueOrder(&valueOrderLoudness); + _initValueOrder(&valueOrderPeakLoudness); + + LOUDNESS_MEASUREMENT* pLoudnessMeasure = NULL; + + *pLoudnessPeakToAverageValuePresent = 0; + + for (i = 0; i < loudnessInfo->measurementCount; i++) { + pLoudnessMeasure = &(loudnessInfo->loudnessMeasurement[i]); + + if (pLoudnessMeasure->methodDefinition == MD_PROGRAM_LOUDNESS) { + _getMethodValue(&valueOrderLoudness, pLoudnessMeasure->methodValue, + pLoudnessMeasure->measurementSystem, MS_PROGRAMLOUDNESS); + } + + if ((dynamicRangeMeasurementType == DRMRT_SHORT_TERM_LOUDNESS_TO_AVG) && + (pLoudnessMeasure->methodDefinition == MD_SHORT_TERM_LOUDNESS_MAX)) { + _getMethodValue(&valueOrderPeakLoudness, pLoudnessMeasure->methodValue, + pLoudnessMeasure->measurementSystem, MS_PEAKLOUDNESS); + } + + if ((dynamicRangeMeasurementType == DRMRT_MOMENTARY_LOUDNESS_TO_AVG) && + (pLoudnessMeasure->methodDefinition == MD_MOMENTARY_LOUDNESS_MAX)) { + _getMethodValue(&valueOrderPeakLoudness, pLoudnessMeasure->methodValue, + pLoudnessMeasure->measurementSystem, MS_PEAKLOUDNESS); + } + + if ((dynamicRangeMeasurementType == DRMRT_TOP_OF_LOUDNESS_RANGE_TO_AVG) && + (pLoudnessMeasure->methodDefinition == MD_MAX_OF_LOUDNESS_RANGE)) { + _getMethodValue(&valueOrderPeakLoudness, pLoudnessMeasure->methodValue, + pLoudnessMeasure->measurementSystem, MS_PEAKLOUDNESS); + } + } + + if ((valueOrderLoudness.order > -1) && (valueOrderPeakLoudness.order > -1)) { + *pLoudnessPeakToAverageValue = + valueOrderPeakLoudness.value - valueOrderLoudness.value; + *pLoudnessPeakToAverageValuePresent = 1; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ + +static DRCDEC_SELECTION_PROCESS_RETURN _selectAlbumLoudness( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i, j; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + for (j = 0; j < hLoudnessInfoSet->loudnessInfoAlbumCount; j++) { + if (pCandidate->pInst->drcSetId == + hLoudnessInfoSet->loudnessInfoAlbum[j].drcSetId) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ + +static int _findMethodDefinition(LOUDNESS_INFO* pLoudnessInfo, + int methodDefinition, int startIndex) { + int i; + int index = -1; + + for (i = startIndex; i < pLoudnessInfo->measurementCount; i++) { + if (pLoudnessInfo->loudnessMeasurement[i].methodDefinition == + methodDefinition) { + index = i; + break; + } + } + + return index; +} + +/*******************************************/ + +static DRCDEC_SELECTION_PROCESS_RETURN _getMixingLevel( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int downmixIdRequested, + int drcSetIdRequested, int albumMode, FIXP_DBL* pMixingLevel) { + const FIXP_DBL mixingLevelDefault = FL2FXCONST_DBL(85.0f / (float)(1 << 7)); + + int i; + int count; + + LOUDNESS_INFO* pLoudnessInfo = NULL; + + *pMixingLevel = mixingLevelDefault; + + if (drcSetIdRequested < 0) { + drcSetIdRequested = 0; + } + + if (albumMode) { + count = hLoudnessInfoSet->loudnessInfoAlbumCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; + } else { + count = hLoudnessInfoSet->loudnessInfoCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; + } + + for (i = 0; i < count; i++) { + if ((drcSetIdRequested == pLoudnessInfo[i].drcSetId) && + ((downmixIdRequested == pLoudnessInfo[i].downmixId) || + (DOWNMIX_ID_ANY_DOWNMIX == pLoudnessInfo[i].downmixId))) { + int index = _findMethodDefinition(&pLoudnessInfo[i], MD_MIXING_LEVEL, 0); + + if (index >= 0) { + *pMixingLevel = pLoudnessInfo[i].loudnessMeasurement[index].methodValue; + break; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_selectionProcess.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_selectionProcess.h new file mode 100644 index 0000000000000..0f878cf126360 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_selectionProcess.h @@ -0,0 +1,220 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): Andreas Hoelzer + + Description: DRC Set Selection + +*******************************************************************************/ + +#ifndef DRCDEC_SELECTIONPROCESS_H +#define DRCDEC_SELECTIONPROCESS_H + +#include "drcDec_types.h" +#include "drcDecoder.h" + +/* DRC set selection according to section 6.2 of ISO/IEC 23003-4 (MPEG-D DRC) */ +/* including ISO/IEC 23003-4/AMD1 (Amendment 1) */ + +typedef struct s_drcdec_selection_process* HANDLE_DRC_SELECTION_PROCESS; + +#define UNDEFINED_LOUDNESS_VALUE (FIXP_DBL)(MAXVAL_DBL - 1) + +typedef enum { + DRCDEC_SELECTION_PROCESS_NO_ERROR = 0, + + DRCDEC_SELECTION_PROCESS_WARNING = -1000, + + DRCDEC_SELECTION_PROCESS_NOT_OK = -2000, + DRCDEC_SELECTION_PROCESS_OUTOFMEMORY, + DRCDEC_SELECTION_PROCESS_INVALID_HANDLE, + DRCDEC_SELECTION_PROCESS_NOT_SUPPORTED, + DRCDEC_SELECTION_PROCESS_INVALID_PARAM, + DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE + +} DRCDEC_SELECTION_PROCESS_RETURN; + +typedef enum { + SEL_PROC_TEST_TIME_DOMAIN = -100, + SEL_PROC_TEST_QMF_DOMAIN, + SEL_PROC_TEST_STFT_DOMAIN, + + SEL_PROC_CODEC_MODE_UNDEFINED = -1, + SEL_PROC_MPEG_4_AAC, + SEL_PROC_MPEG_D_USAC, + SEL_PROC_MPEG_H_3DA +} SEL_PROC_CODEC_MODE; + +typedef enum { + /* set and get user param */ + SEL_PROC_LOUDNESS_NORMALIZATION_ON, + /* get only user param */ + SEL_PROC_DYNAMIC_RANGE_CONTROL_ON, + /* set only user params */ + SEL_PROC_TARGET_LOUDNESS, + SEL_PROC_EFFECT_TYPE, + SEL_PROC_EFFECT_TYPE_FALLBACK_CODE, + SEL_PROC_LOUDNESS_MEASUREMENT_METHOD, + SEL_PROC_ALBUM_MODE, + SEL_PROC_DOWNMIX_ID, + SEL_PROC_TARGET_LAYOUT, + SEL_PROC_TARGET_CHANNEL_COUNT, + SEL_PROC_BASE_CHANNEL_COUNT, + SEL_PROC_SAMPLE_RATE, + SEL_PROC_BOOST, + SEL_PROC_COMPRESS +} SEL_PROC_USER_PARAM; + +typedef struct s_selection_process_output { + FIXP_DBL outputPeakLevelDb; /* e = 7 */ + FIXP_DBL loudnessNormalizationGainDb; /* e = 7 */ + FIXP_DBL outputLoudness; /* e = 7 */ + + UCHAR numSelectedDrcSets; + SCHAR selectedDrcSetIds[MAX_ACTIVE_DRCS]; + UCHAR selectedDownmixIds[MAX_ACTIVE_DRCS]; + + UCHAR activeDownmixId; + UCHAR baseChannelCount; + UCHAR targetChannelCount; + SCHAR targetLayout; + UCHAR downmixMatrixPresent; + FIXP_DBL downmixMatrix[8][8]; /* e = 2 */ + + FIXP_SGL boost; /* e = 1 */ + FIXP_SGL compress; /* e = 1 */ + + FIXP_DBL mixingLevel; /* e = 7 */ + +} SEL_PROC_OUTPUT, *HANDLE_SEL_PROC_OUTPUT; + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Create(HANDLE_DRC_SELECTION_PROCESS* phInstance); + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Delete(HANDLE_DRC_SELECTION_PROCESS* phInstance); + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Init(HANDLE_DRC_SELECTION_PROCESS hInstance); + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_SetCodecMode(HANDLE_DRC_SELECTION_PROCESS hInstance, + const SEL_PROC_CODEC_MODE codecMode); + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_SetParam(HANDLE_DRC_SELECTION_PROCESS hInstance, + const SEL_PROC_USER_PARAM requestType, + FIXP_DBL requestValue, int* pDiff); + +FIXP_DBL +drcDec_SelectionProcess_GetParam(HANDLE_DRC_SELECTION_PROCESS hInstance, + const SEL_PROC_USER_PARAM requestType); + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_SetMpeghParams( + HANDLE_DRC_SELECTION_PROCESS hInstance, const int numGroupIdsRequested, + const int* groupIdRequested, const int numGroupPresetIdsRequested, + const int* groupPresetIdRequested, + const int* numMembersGroupPresetIdsRequested, + const int groupPresetIdRequestedPreference, int* pDiff); + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Process(HANDLE_DRC_SELECTION_PROCESS hInstance, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + HANDLE_SEL_PROC_OUTPUT hSelProcOutput); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_tools.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_tools.cpp new file mode 100644 index 0000000000000..9a6feb13181b8 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_tools.cpp @@ -0,0 +1,371 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "drcDec_types.h" +#include "drcDec_tools.h" +#include "fixpoint_math.h" +#include "drcDecoder.h" + +int getDeltaTmin(const int sampleRate) { + /* half_ms = round (0.0005 * sampleRate); */ + int half_ms = (sampleRate + 1000) / 2000; + int deltaTmin = 1; + if (sampleRate < 1000) { + return DE_NOT_OK; + } + while (deltaTmin <= half_ms) { + deltaTmin = deltaTmin << 1; + } + return deltaTmin; +} + +DRC_COEFFICIENTS_UNI_DRC* selectDrcCoefficients( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int location) { + int n; + int c = -1; + for (n = 0; n < hUniDrcConfig->drcCoefficientsUniDrcCount; n++) { + if (hUniDrcConfig->drcCoefficientsUniDrc[n].drcLocation == location) { + c = n; + } + } + if (c >= 0) { + return &(hUniDrcConfig->drcCoefficientsUniDrc[c]); + } + return NULL; /* possible during bitstream parsing */ +} + +DRC_INSTRUCTIONS_UNI_DRC* selectDrcInstructions( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int drcSetId) { + int i; + for (i = 0; i < hUniDrcConfig->drcInstructionsCountInclVirtual; i++) { + if (hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId == drcSetId) { + return &(hUniDrcConfig->drcInstructionsUniDrc[i]); + } + } + return NULL; +} + +DOWNMIX_INSTRUCTIONS* selectDownmixInstructions( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int downmixId) { + int i; + for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { + if (hUniDrcConfig->downmixInstructions[i].downmixId == downmixId) { + return &(hUniDrcConfig->downmixInstructions[i]); + } + } + return NULL; +} + +DRC_ERROR +deriveDrcChannelGroups( + const int drcSetEffect, /* in */ + const int channelCount, /* in */ + const SCHAR* gainSetIndex, /* in */ + const DUCKING_MODIFICATION* duckingModificationForChannel, /* in */ + UCHAR* nDrcChannelGroups, /* out */ + SCHAR* uniqueIndex, /* out (gainSetIndexForChannelGroup) */ + SCHAR* groupForChannel, /* out */ + DUCKING_MODIFICATION* duckingModificationForChannelGroup) /* out */ +{ + int duckingSequence = -1; + int c, n, g, match, idx; + FIXP_SGL factor; + FIXP_SGL uniqueScaling[8]; + + for (g = 0; g < 8; g++) { + uniqueIndex[g] = -10; + uniqueScaling[g] = FIXP_SGL(-1.0f); + } + + g = 0; + + if (drcSetEffect & EB_DUCK_OTHER) { + for (c = 0; c < channelCount; c++) { + match = 0; + if (c >= 8) return DE_MEMORY_ERROR; + idx = gainSetIndex[c]; + factor = duckingModificationForChannel[c].duckingScaling; + if (idx < 0) { + for (n = 0; n < g; n++) { + if (uniqueScaling[n] == factor) { + match = 1; + groupForChannel[c] = n; + break; + } + } + if (match == 0) { + if (g >= 8) return DE_MEMORY_ERROR; + uniqueIndex[g] = idx; + uniqueScaling[g] = factor; + groupForChannel[c] = g; + g++; + } + } else { + if ((duckingSequence > 0) && (duckingSequence != idx)) { + return DE_NOT_OK; + } + duckingSequence = idx; + groupForChannel[c] = -1; + } + } + if (duckingSequence == -1) { + return DE_NOT_OK; + } + } else if (drcSetEffect & EB_DUCK_SELF) { + for (c = 0; c < channelCount; c++) { + match = 0; + if (c >= 8) return DE_MEMORY_ERROR; + idx = gainSetIndex[c]; + factor = duckingModificationForChannel[c].duckingScaling; + if (idx >= 0) { + for (n = 0; n < g; n++) { + if ((uniqueIndex[n] == idx) && (uniqueScaling[n] == factor)) { + match = 1; + groupForChannel[c] = n; + break; + } + } + if (match == 0) { + if (g >= 8) return DE_MEMORY_ERROR; + uniqueIndex[g] = idx; + uniqueScaling[g] = factor; + groupForChannel[c] = g; + g++; + } + } else { + groupForChannel[c] = -1; + } + } + } else { /* no ducking */ + for (c = 0; c < channelCount; c++) { + if (c >= 8) return DE_MEMORY_ERROR; + idx = gainSetIndex[c]; + match = 0; + if (idx >= 0) { + for (n = 0; n < g; n++) { + if (uniqueIndex[n] == idx) { + match = 1; + groupForChannel[c] = n; + break; + } + } + if (match == 0) { + if (g >= 8) return DE_MEMORY_ERROR; + uniqueIndex[g] = idx; + groupForChannel[c] = g; + g++; + } + } else { + groupForChannel[c] = -1; + } + } + } + *nDrcChannelGroups = g; + + if (drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { + for (g = 0; g < *nDrcChannelGroups; g++) { + if (drcSetEffect & EB_DUCK_OTHER) { + uniqueIndex[g] = duckingSequence; + } + duckingModificationForChannelGroup[g].duckingScaling = uniqueScaling[g]; + if (uniqueScaling[g] != FL2FXCONST_SGL(1.0f / (float)(1 << 2))) { + duckingModificationForChannelGroup[g].duckingScalingPresent = 1; + } else { + duckingModificationForChannelGroup[g].duckingScalingPresent = 0; + } + } + } + + return DE_OK; +} + +FIXP_DBL +dB2lin(const FIXP_DBL dB_m, const int dB_e, int* pLin_e) { + /* get linear value from dB. + return lin_val = 10^(dB_val/20) = 2^(log2(10)/20*dB_val) + with dB_val = dB_m *2^dB_e and lin_val = lin_m * 2^lin_e */ + FIXP_DBL lin_m = + f2Pow(fMult(dB_m, FL2FXCONST_DBL(0.1660964f * (float)(1 << 2))), dB_e - 2, + pLin_e); + + return lin_m; +} + +FIXP_DBL +lin2dB(const FIXP_DBL lin_m, const int lin_e, int* pDb_e) { + /* get dB value from linear value. + return dB_val = 20*log10(lin_val) + with dB_val = dB_m *2^dB_e and lin_val = lin_m * 2^lin_e */ + FIXP_DBL dB_m; + + if (lin_m == (FIXP_DBL)0) { /* return very small value representing -inf */ + dB_m = (FIXP_DBL)MINVAL_DBL; + *pDb_e = DFRACT_BITS - 1; + } else { + /* 20*log10(lin_val) = 20/log2(10)*log2(lin_val) */ + dB_m = fMultDiv2(FL2FXCONST_DBL(6.02059991f / (float)(1 << 3)), + fLog2(lin_m, lin_e, pDb_e)); + *pDb_e += 3 + 1; + } + + return dB_m; +} + +FIXP_DBL +approxDb2lin(const FIXP_DBL dB_m, const int dB_e, int* pLin_e) { + /* get linear value from approximate dB. + return lin_val = 2^(dB_val/6) + with dB_val = dB_m *2^dB_e and lin_val = lin_m * 2^lin_e */ + FIXP_DBL lin_m = + f2Pow(fMult(dB_m, FL2FXCONST_DBL(0.1666667f * (float)(1 << 2))), dB_e - 2, + pLin_e); + + return lin_m; +} + +int bitstreamContainsMultibandDrc(HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + const int downmixId) { + int i, g, d, seq; + DRC_INSTRUCTIONS_UNI_DRC* pInst; + DRC_COEFFICIENTS_UNI_DRC* pCoef = NULL; + int isMultiband = 0; + + pCoef = selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); + if (pCoef == NULL) return 0; + + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { + pInst = &(hUniDrcConfig->drcInstructionsUniDrc[i]); + for (d = 0; d < pInst->downmixIdCount; d++) { + if (downmixId == pInst->downmixId[d]) { + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + seq = pInst->gainSetIndexForChannelGroup[g]; + if (pCoef->gainSet[seq].bandCount > 1) { + isMultiband = 1; + } + } + } + } + } + + return isMultiband; +} + +FIXP_DBL getDownmixOffset(DOWNMIX_INSTRUCTIONS* pDown, int baseChannelCount) { + FIXP_DBL downmixOffset = FL2FXCONST_DBL(1.0f / (1 << 1)); /* e = 1 */ + if ((pDown->bsDownmixOffset == 1) || (pDown->bsDownmixOffset == 2)) { + int e_a, e_downmixOffset; + FIXP_DBL a, q; + if (baseChannelCount <= pDown->targetChannelCount) return downmixOffset; + + q = fDivNorm((FIXP_DBL)pDown->targetChannelCount, + (FIXP_DBL)baseChannelCount); /* e = 0 */ + a = lin2dB(q, 0, &e_a); + if (pDown->bsDownmixOffset == 2) { + e_a += 1; /* a *= 2 */ + } + /* a = 0.5 * round (a) */ + a = fixp_round(a, e_a) >> 1; + downmixOffset = dB2lin(a, e_a, &e_downmixOffset); + downmixOffset = scaleValue(downmixOffset, e_downmixOffset - 1); + } + return downmixOffset; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_tools.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_tools.h new file mode 100644 index 0000000000000..77a0ab7c1c39c --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_tools.h @@ -0,0 +1,146 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCDEC_TOOLS_H +#define DRCDEC_TOOLS_H + +#include "drcDec_types.h" +#include "drcDec_selectionProcess.h" + +int getDeltaTmin(const int sampleRate); + +DRC_COEFFICIENTS_UNI_DRC* selectDrcCoefficients( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int location); + +DRC_INSTRUCTIONS_UNI_DRC* selectDrcInstructions( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int drcSetId); + +DOWNMIX_INSTRUCTIONS* selectDownmixInstructions( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int downmixId); + +DRC_ERROR +deriveDrcChannelGroups( + const int drcSetEffect, /* in */ + const int channelCount, /* in */ + const SCHAR* gainSetIndex, /* in */ + const DUCKING_MODIFICATION* duckingModificationForChannel, /* in */ + UCHAR* nDrcChannelGroups, /* out */ + SCHAR* uniqueIndex, /* out (gainSetIndexForChannelGroup) */ + SCHAR* groupForChannel, /* out */ + DUCKING_MODIFICATION* duckingModificationForChannelGroup); /* out */ + +FIXP_DBL +dB2lin(const FIXP_DBL dB_m, const int dB_e, int* pLin_e); + +FIXP_DBL +lin2dB(const FIXP_DBL lin_m, const int lin_e, int* pDb_e); + +FIXP_DBL +approxDb2lin(const FIXP_DBL dB_m, const int dB_e, int* pLin_e); + +int bitstreamContainsMultibandDrc(HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + const int downmixId); + +FIXP_DBL +getDownmixOffset(DOWNMIX_INSTRUCTIONS* pDown, int baseChannelCount); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_types.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_types.h new file mode 100644 index 0000000000000..b0d89c1273fe2 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDec_types.h @@ -0,0 +1,431 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCDEC_TYPES_H +#define DRCDEC_TYPES_H + +#include "common_fix.h" + +/* Data structures corresponding to static and dynamic DRC/Loudness payload + as defined in section 7 of MPEG-D DRC standard, ISO/IEC 23003-4 */ + +/**************/ +/* uniDrcGain */ +/**************/ + +typedef struct { + FIXP_SGL gainDb; /* e = 7 */ + SHORT time; +} GAIN_NODE; + +/* uniDrcGainExtension() (Table 56) */ +typedef struct { + UCHAR uniDrcGainExtType[8]; + ULONG extBitSize[8 - 1]; +} UNI_DRC_GAIN_EXTENSION; + +/* uniDrcGain() (Table 55) */ +typedef struct { + UCHAR nNodes[12]; /* unsaturated value, i.e. as provided in bitstream */ + GAIN_NODE gainNode[12][16]; + + UCHAR uniDrcGainExtPresent; + UNI_DRC_GAIN_EXTENSION uniDrcGainExtension; + + /* derived data */ + UCHAR status; +} UNI_DRC_GAIN, *HANDLE_UNI_DRC_GAIN; + +/****************/ +/* uniDrcConfig */ +/****************/ + +typedef enum { + EB_NIGHT = 0x0001, + EB_NOISY = 0x0002, + EB_LIMITED = 0x0004, + EB_LOWLEVEL = 0x0008, + EB_DIALOG = 0x0010, + EB_GENERAL_COMPR = 0x0020, + EB_EXPAND = 0x0040, + EB_ARTISTIC = 0x0080, + EB_CLIPPING = 0x0100, + EB_FADE = 0x0200, + EB_DUCK_OTHER = 0x0400, + EB_DUCK_SELF = 0x0800 +} EFFECT_BIT; + +typedef enum { + GCP_REGULAR = 0, + GCP_FADING = 1, + GCP_CLIPPING_DUCKING = 2, + GCP_CONSTANT = 3 +} GAIN_CODING_PROFILE; + +typedef enum { GIT_SPLINE = 0, GIT_LINEAR = 1 } GAIN_INTERPOLATION_TYPE; + +typedef enum { CS_LEFT = 0, CS_RIGHT = 1 } CHARACTERISTIC_SIDE; + +typedef enum { CF_SIGMOID = 0, CF_NODES = 1 } CHARACTERISTIC_FORMAT; + +typedef enum { + GF_QMF32 = 0x1, + GF_QMFHYBRID39 = 0x2, + GF_QMF64 = 0x3, + GF_QMFHYBRID71 = 0x4, + GF_QMF128 = 0x5, + GF_QMFHYBRID135 = 0x6, + GF_UNIFORM = 0x7 +} EQ_SUBBAND_GAIN_FORMAT; + +typedef struct { + UCHAR duckingScalingPresent; + FIXP_SGL duckingScaling; /* e = 2 */ +} DUCKING_MODIFICATION; + +typedef struct { + UCHAR targetCharacteristicLeftPresent; + UCHAR targetCharacteristicLeftIndex; + UCHAR targetCharacteristicRightPresent; + UCHAR targetCharacteristicRightIndex; + UCHAR gainScalingPresent; + FIXP_SGL attenuationScaling; /* e = 2 */ + FIXP_SGL amplificationScaling; /* e = 2 */ + UCHAR gainOffsetPresent; + FIXP_SGL gainOffset; /* e = 4 */ +} GAIN_MODIFICATION; + +typedef union { + UCHAR crossoverFreqIndex; + USHORT startSubBandIndex; +} BAND_BORDER; + +typedef struct { + UCHAR left; + UCHAR right; +} CUSTOM_INDEX; + +typedef struct { + UCHAR present; + UCHAR isCICP; + union { + UCHAR cicpIndex; + CUSTOM_INDEX custom; + }; +} DRC_CHARACTERISTIC; + +typedef struct { + UCHAR gainCodingProfile; + UCHAR gainInterpolationType; + UCHAR fullFrame; + UCHAR timeAlignment; + UCHAR timeDeltaMinPresent; + USHORT timeDeltaMin; + UCHAR bandCount; + UCHAR drcBandType; + UCHAR gainSequenceIndex[4]; + DRC_CHARACTERISTIC drcCharacteristic[4]; + BAND_BORDER bandBorder[4]; +} GAIN_SET; + +typedef struct { + FIXP_SGL gain; /* e = 6 */ + FIXP_SGL ioRatio; /* e = 2 */ + FIXP_SGL exp; /* e = 5 */ + UCHAR flipSign; +} CUSTOM_DRC_CHAR_SIGMOID; + +typedef struct { + UCHAR characteristicNodeCount; + FIXP_SGL nodeLevel[4 + 1]; /* e = 7 */ + FIXP_SGL nodeGain[4 + 1]; /* e = 7 */ +} CUSTOM_DRC_CHAR_NODES; + +typedef shouldBeUnion { + CUSTOM_DRC_CHAR_SIGMOID sigmoid; + CUSTOM_DRC_CHAR_NODES nodes; +} +CUSTOM_DRC_CHAR; + +/* drcCoefficientsUniDrc() (Table 67) */ +typedef struct { + UCHAR drcLocation; + UCHAR drcFrameSizePresent; + USHORT drcFrameSize; + UCHAR characteristicLeftCount; + UCHAR characteristicLeftFormat[16]; + CUSTOM_DRC_CHAR customCharacteristicLeft[16]; + UCHAR characteristicRightCount; + UCHAR characteristicRightFormat[16]; + CUSTOM_DRC_CHAR customCharacteristicRight[16]; + UCHAR + gainSequenceCount; /* unsaturated value, i.e. as provided in bitstream */ + UCHAR gainSetCount; /* saturated to 12 */ + GAIN_SET gainSet[12]; + /* derived data */ + UCHAR gainSetIndexForGainSequence[12]; +} DRC_COEFFICIENTS_UNI_DRC; + +/* drcInstructionsUniDrc() (Table 72) */ +typedef struct { + SCHAR drcSetId; + UCHAR drcSetComplexityLevel; + UCHAR drcLocation; + UCHAR drcApplyToDownmix; + UCHAR downmixIdCount; + UCHAR downmixId[8]; + USHORT drcSetEffect; + UCHAR limiterPeakTargetPresent; + FIXP_SGL limiterPeakTarget; /* e = 5 */ + UCHAR drcSetTargetLoudnessPresent; + SCHAR drcSetTargetLoudnessValueUpper; + SCHAR drcSetTargetLoudnessValueLower; + UCHAR dependsOnDrcSetPresent; + union { + SCHAR dependsOnDrcSet; + UCHAR noIndependentUse; + }; + UCHAR requiresEq; + shouldBeUnion { + GAIN_MODIFICATION gainModificationForChannelGroup[8][4]; + DUCKING_MODIFICATION duckingModificationForChannel[8]; + }; + SCHAR gainSetIndex[8]; + + /* derived data */ + UCHAR drcChannelCount; + UCHAR nDrcChannelGroups; + SCHAR gainSetIndexForChannelGroup[8]; +} DRC_INSTRUCTIONS_UNI_DRC; + +/* channelLayout() (Table 62) */ +typedef struct { + UCHAR baseChannelCount; + UCHAR layoutSignalingPresent; + UCHAR definedLayout; + UCHAR speakerPosition[8]; +} CHANNEL_LAYOUT; + +/* downmixInstructions() (Table 63) */ +typedef struct { + UCHAR downmixId; + UCHAR targetChannelCount; + UCHAR targetLayout; + UCHAR downmixCoefficientsPresent; + UCHAR bsDownmixOffset; + FIXP_DBL downmixCoefficient[8 * 8]; /* e = 2 */ +} DOWNMIX_INSTRUCTIONS; + +typedef struct { + UCHAR uniDrcConfigExtType[8]; + ULONG extBitSize[8 - 1]; +} UNI_DRC_CONFIG_EXTENSION; + +/* uniDrcConfig() (Table 57) */ +typedef struct { + UCHAR sampleRatePresent; + ULONG sampleRate; + UCHAR downmixInstructionsCountV0; + UCHAR downmixInstructionsCountV1; + UCHAR downmixInstructionsCount; /* saturated to 6 */ + UCHAR drcCoefficientsUniDrcCountV0; + UCHAR drcCoefficientsUniDrcCountV1; + UCHAR drcCoefficientsUniDrcCount; /* saturated to 2 */ + UCHAR drcInstructionsUniDrcCountV0; + UCHAR drcInstructionsUniDrcCountV1; + UCHAR drcInstructionsUniDrcCount; /* saturated to (12 + 1 + 6) */ + CHANNEL_LAYOUT channelLayout; + DOWNMIX_INSTRUCTIONS downmixInstructions[6]; + DRC_COEFFICIENTS_UNI_DRC drcCoefficientsUniDrc[2]; + DRC_INSTRUCTIONS_UNI_DRC drcInstructionsUniDrc[(12 + 1 + 6)]; + UCHAR uniDrcConfigExtPresent; + UNI_DRC_CONFIG_EXTENSION uniDrcConfigExt; + + /* derived data */ + UCHAR drcInstructionsCountInclVirtual; + UCHAR diff; +} UNI_DRC_CONFIG, *HANDLE_UNI_DRC_CONFIG; + +/*******************/ +/* loudnessInfoSet */ +/*******************/ + +typedef enum { + MD_UNKNOWN_OTHER = 0, + MD_PROGRAM_LOUDNESS = 1, + MD_ANCHOR_LOUDNESS = 2, + MD_MAX_OF_LOUDNESS_RANGE = 3, + MD_MOMENTARY_LOUDNESS_MAX = 4, + MD_SHORT_TERM_LOUDNESS_MAX = 5, + MD_LOUDNESS_RANGE = 6, + MD_MIXING_LEVEL = 7, + MD_ROOM_TYPE = 8, + MD_SHORT_TERM_LOUDNESS = 9 +} METHOD_DEFINITION; + +typedef enum { + MS_UNKNOWN_OTHER = 0, + MS_EBU_R_128 = 1, + MS_BS_1770_4 = 2, + MS_BS_1770_4_PRE_PROCESSING = 3, + MS_USER = 4, + MS_EXPERT_PANEL = 5, + MS_BS_1771_1 = 6, + MS_RESERVED_A = 7, + MS_RESERVED_B = 8, + MS_RESERVED_C = 9, + MS_RESERVED_D = 10, + MS_RESERVED_E = 11 +} MEASUREMENT_SYSTEM; + +typedef enum { + R_UKNOWN = 0, + R_UNVERIFIED = 1, + R_CEILING = 2, + R_ACCURATE = 3 +} RELIABILITY; + +typedef struct { + UCHAR methodDefinition; + FIXP_DBL methodValue; /* e = 7 for all methodDefinitions */ + UCHAR measurementSystem; + UCHAR reliability; +} LOUDNESS_MEASUREMENT; + +/* loudnessInfo() (Table 59) */ +typedef struct { + SCHAR drcSetId; + UCHAR eqSetId; + UCHAR downmixId; + UCHAR samplePeakLevelPresent; + FIXP_DBL samplePeakLevel; /* e = 7 */ + UCHAR truePeakLevelPresent; + FIXP_DBL truePeakLevel; /* e = 7 */ + UCHAR truePeakLevelMeasurementSystem; + UCHAR truePeakLevelReliability; + UCHAR measurementCount; /* saturated to 8 */ + LOUDNESS_MEASUREMENT loudnessMeasurement[8]; +} LOUDNESS_INFO; + +/* loudnessInfoSetExtension() (Table 61) */ +typedef struct { + UCHAR loudnessInfoSetExtType[8]; + ULONG extBitSize[8 - 1]; +} LOUDNESS_INFO_SET_EXTENSION; + +/* loudnessInfoSet() (Table 58) */ +typedef struct { + UCHAR loudnessInfoAlbumCountV0; + UCHAR loudnessInfoAlbumCountV1; + UCHAR loudnessInfoAlbumCount; /* saturated to 12 */ + UCHAR loudnessInfoCountV0; + UCHAR loudnessInfoCountV1; + UCHAR loudnessInfoCount; /* saturated to 12 */ + LOUDNESS_INFO loudnessInfoAlbum[12]; + LOUDNESS_INFO loudnessInfo[12]; + UCHAR loudnessInfoSetExtPresent; + LOUDNESS_INFO_SET_EXTENSION loudnessInfoSetExt; + /* derived data */ + UCHAR diff; +} LOUDNESS_INFO_SET, *HANDLE_LOUDNESS_INFO_SET; + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDecoder.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDecoder.h new file mode 100644 index 0000000000000..9826a7b37f3a2 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcDecoder.h @@ -0,0 +1,142 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCDECODER_H +#define DRCDECODER_H + +/* drcDecoder.h: definitions used in all submodules */ + +#define MAX_ACTIVE_DRCS 3 + +typedef enum { DM_REGULAR_DELAY = 0, DM_LOW_DELAY = 1 } DELAY_MODE; + +typedef enum { + DE_OK = 0, + DE_NOT_OK = -100, + DE_PARAM_OUT_OF_RANGE, + DE_PARAM_INVALID, + DE_MEMORY_ERROR +} DRC_ERROR; + +typedef enum { SDM_OFF, SDM_QMF64, SDM_QMF71, SDM_STFT256 } SUBBAND_DOMAIN_MODE; + +#define DOWNMIX_ID_BASE_LAYOUT 0x0 +#define DOWNMIX_ID_ANY_DOWNMIX 0x7F +#define DRC_SET_ID_NO_DRC 0x0 +#define DRC_SET_ID_ANY_DRC 0x3F + +#define LOCATION_MP4_INSTREAM_UNIDRC 0x1 +#define LOCATION_MP4_DYN_RANGE_INFO 0x2 +#define LOCATION_MP4_COMPRESSION_VALUE 0x3 +#define LOCATION_SELECTED \ + LOCATION_MP4_INSTREAM_UNIDRC /* set to location selected by system */ + +#define MAX_REQUESTS_DOWNMIX_ID 15 +#define MAX_REQUESTS_DRC_FEATURE 7 +#define MAX_REQUESTS_DRC_EFFECT_TYPE 15 + +#define DEFAULT_LOUDNESS_DEVIATION_MAX 63 + +#define DRC_INPUT_LOUDNESS_TARGET FL2FXCONST_DBL(-31.0f / (float)(1 << 7)) +#define DRC_INPUT_LOUDNESS_TARGET_SGL FL2FXCONST_SGL(-31.0f / (float)(1 << 7)) + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_init.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_init.cpp new file mode 100644 index 0000000000000..89d0f557bc51e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_init.cpp @@ -0,0 +1,333 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "drcDec_types.h" +#include "drcDec_tools.h" +#include "drcDec_gainDecoder.h" +#include "drcGainDec_init.h" + +static DRC_ERROR _generateDrcInstructionsDerivedData( + HANDLE_DRC_GAIN_DECODER hGainDec, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + DRC_INSTRUCTIONS_UNI_DRC* pInst, DRC_COEFFICIENTS_UNI_DRC* pCoef, + ACTIVE_DRC* pActiveDrc) { + DRC_ERROR err = DE_OK; + int g; + int gainElementCount = 0; + UCHAR nDrcChannelGroups = 0; + SCHAR gainSetIndexForChannelGroup[8]; + + err = deriveDrcChannelGroups( + pInst->drcSetEffect, pInst->drcChannelCount, pInst->gainSetIndex, + pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF) + ? pInst->duckingModificationForChannel + : NULL, + &nDrcChannelGroups, gainSetIndexForChannelGroup, + pActiveDrc->channelGroupForChannel, + pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF) + ? pActiveDrc->duckingModificationForChannelGroup + : NULL); + if (err) return (err); + + /* sanity check */ + if (nDrcChannelGroups != pInst->nDrcChannelGroups) return DE_NOT_OK; + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + if (gainSetIndexForChannelGroup[g] != pInst->gainSetIndexForChannelGroup[g]) + return DE_NOT_OK; + } + + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + int seq = pInst->gainSetIndexForChannelGroup[g]; + if (seq != -1 && (hUniDrcConfig->drcCoefficientsUniDrcCount == 0 || + seq >= pCoef->gainSetCount)) { + pActiveDrc->channelGroupIsParametricDrc[g] = 1; + } else { + pActiveDrc->channelGroupIsParametricDrc[g] = 0; + if (seq >= pCoef->gainSetCount) { + return DE_NOT_OK; + } + } + } + + /* gainElementCount */ + if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + pActiveDrc->bandCountForChannelGroup[g] = 1; + } + pActiveDrc->gainElementCount = + pInst->nDrcChannelGroups; /* one gain element per channel group */ + } else { + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + if (pActiveDrc->channelGroupIsParametricDrc[g]) { + gainElementCount++; + pActiveDrc->bandCountForChannelGroup[g] = 1; + } else { + int seq, bandCount; + seq = pInst->gainSetIndexForChannelGroup[g]; + bandCount = pCoef->gainSet[seq].bandCount; + pActiveDrc->bandCountForChannelGroup[g] = bandCount; + gainElementCount += bandCount; + } + } + pActiveDrc->gainElementCount = gainElementCount; + } + + /* prepare gainElementForGroup (cumulated sum of bandCountForChannelGroup) */ + pActiveDrc->gainElementForGroup[0] = 0; + for (g = 1; g < pInst->nDrcChannelGroups; g++) { + pActiveDrc->gainElementForGroup[g] = + pActiveDrc->gainElementForGroup[g - 1] + + pActiveDrc->bandCountForChannelGroup[g - 1]; /* index of first gain + sequence in channel + group */ + } + + return DE_OK; +} + +DRC_ERROR +initGainDec(HANDLE_DRC_GAIN_DECODER hGainDec) { + int i, j, k; + + /* sanity check */ + if (hGainDec->deltaTminDefault > hGainDec->frameSize) return DE_NOT_OK; + + for (i = 0; i < MAX_ACTIVE_DRCS; i++) { + for (j = 0; j < 8; j++) { + /* use startup node at the beginning */ + hGainDec->activeDrc[i].lnbIndexForChannel[j][0] = 0; + for (k = 1; k < NUM_LNB_FRAMES; k++) { + hGainDec->activeDrc[i].lnbIndexForChannel[j][k] = -1; + } + } + } + + for (j = 0; j < 8; j++) { + hGainDec->channelGain[j] = FL2FXCONST_DBL(1.0f / (float)(1 << 8)); + } + + for (i = 0; i < 4 * 1024 / 256; i++) { + hGainDec->dummySubbandGains[i] = FL2FXCONST_DBL(1.0f / (float)(1 << 7)); + } + + hGainDec->status = 0; /* startup */ + + return DE_OK; +} + +void initDrcGainBuffers(const int frameSize, DRC_GAIN_BUFFERS* drcGainBuffers) { + int i, c, j; + /* prepare 12 instances of node buffers */ + for (i = 0; i < 12; i++) { + for (j = 0; j < NUM_LNB_FRAMES; j++) { + drcGainBuffers->linearNodeBuffer[i].nNodes[j] = 1; + drcGainBuffers->linearNodeBuffer[i].linearNode[j][0].gainLin = + FL2FXCONST_DBL(1.0f / (float)(1 << 7)); + if (j == 0) { + drcGainBuffers->linearNodeBuffer[i].linearNode[j][0].time = + 0; /* initialize last node with startup node */ + } else { + drcGainBuffers->linearNodeBuffer[i].linearNode[j][0].time = + frameSize - 1; + } + } + } + + /* prepare dummyLnb, a linearNodeBuffer containing a constant gain of 0 dB, + * for the "no DRC processing" case */ + drcGainBuffers->dummyLnb.gainInterpolationType = GIT_LINEAR; + for (i = 0; i < NUM_LNB_FRAMES; i++) { + drcGainBuffers->dummyLnb.nNodes[i] = 1; + drcGainBuffers->dummyLnb.linearNode[i][0].gainLin = + FL2FXCONST_DBL(1.0f / (float)(1 << 7)); + drcGainBuffers->dummyLnb.linearNode[i][0].time = frameSize - 1; + } + + /* prepare channelGain delay line */ + for (c = 0; c < 8; c++) { + for (i = 0; i < NUM_LNB_FRAMES; i++) { + drcGainBuffers->channelGain[c][i] = + FL2FXCONST_DBL(1.0f / (float)(1 << 8)); + } + } + + drcGainBuffers->lnbPointer = 0; +} + +DRC_ERROR +initActiveDrc(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int drcSetIdSelected, + const int downmixIdSelected) { + int g, isMultiband = 0; + DRC_ERROR err = DE_OK; + DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; + DRC_COEFFICIENTS_UNI_DRC* pCoef = NULL; + + pInst = selectDrcInstructions(hUniDrcConfig, drcSetIdSelected); + if (pInst == NULL) { + return DE_NOT_OK; + } + + if (pInst->drcSetId >= 0) { + pCoef = selectDrcCoefficients(hUniDrcConfig, pInst->drcLocation); + if (pCoef == NULL) { + return DE_NOT_OK; + } + + if (pCoef->drcFrameSizePresent) { + if (pCoef->drcFrameSize != hGainDec->frameSize) { + return DE_NOT_OK; + } + } + + err = _generateDrcInstructionsDerivedData( + hGainDec, hUniDrcConfig, pInst, pCoef, + &(hGainDec->activeDrc[hGainDec->nActiveDrcs])); + if (err) return err; + } + + hGainDec->activeDrc[hGainDec->nActiveDrcs].pInst = pInst; + hGainDec->activeDrc[hGainDec->nActiveDrcs].pCoef = pCoef; + + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + if (hGainDec->activeDrc[hGainDec->nActiveDrcs].bandCountForChannelGroup[g] > + 1) { + if (hGainDec->multiBandActiveDrcIndex != -1) { + return DE_NOT_OK; + } + isMultiband = 1; + } + } + + if (isMultiband) { + /* Keep activeDrc index of multiband DRC set */ + hGainDec->multiBandActiveDrcIndex = hGainDec->nActiveDrcs; + } + + if ((hGainDec->channelGainActiveDrcIndex == -1) && + (downmixIdSelected == DOWNMIX_ID_BASE_LAYOUT) && + (hUniDrcConfig->drcInstructionsUniDrcCount > + 0)) { /* use this activeDrc to apply channelGains */ + hGainDec->channelGainActiveDrcIndex = hGainDec->nActiveDrcs; + } + + hGainDec->nActiveDrcs++; + if (hGainDec->nActiveDrcs > MAX_ACTIVE_DRCS) return DE_NOT_OK; + + return DE_OK; +} + +DRC_ERROR +initActiveDrcOffset(HANDLE_DRC_GAIN_DECODER hGainDec) { + int a, accGainElementCount; + + accGainElementCount = 0; + for (a = 0; a < hGainDec->nActiveDrcs; a++) { + hGainDec->activeDrc[a].activeDrcOffset = accGainElementCount; + accGainElementCount += hGainDec->activeDrc[a].gainElementCount; + if (accGainElementCount > 12) { + hGainDec->nActiveDrcs = a; + return DE_NOT_OK; + } + } + + return DE_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_init.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_init.h new file mode 100644 index 0000000000000..c0b98538f4e4a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_init.h @@ -0,0 +1,119 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCGAINDEC_INIT_H +#define DRCGAINDEC_INIT_H + +DRC_ERROR +initGainDec(HANDLE_DRC_GAIN_DECODER hGainDec); + +void initDrcGainBuffers(const int frameSize, DRC_GAIN_BUFFERS* drcGainBuffers); + +DRC_ERROR +initActiveDrc(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int drcSetIdSelected, + const int downmixIdSelected); + +DRC_ERROR +initActiveDrcOffset(HANDLE_DRC_GAIN_DECODER hGainDec); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_preprocess.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_preprocess.cpp new file mode 100644 index 0000000000000..8d94ace4433ac --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_preprocess.cpp @@ -0,0 +1,718 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "drcDec_types.h" +#include "drcDec_gainDecoder.h" +#include "drcGainDec_preprocess.h" +#include "drcDec_tools.h" +#include "FDK_matrixCalloc.h" +#include "drcDec_rom.h" + +#define SLOPE_FACTOR_DB_TO_LINEAR \ + FL2FXCONST_DBL(0.1151f * (float)(1 << 3)) /* ln(10) / 20 */ + +typedef struct { + int drcSetEffect; + DUCKING_MODIFICATION* pDMod; + GAIN_MODIFICATION* pGMod; + int drcCharacteristicPresent; + CHARACTERISTIC_FORMAT characteristicFormatSource[2]; + const CUSTOM_DRC_CHAR* pCCharSource[2]; + CHARACTERISTIC_FORMAT characteristicFormatTarget[2]; + const CUSTOM_DRC_CHAR* pCCharTarget[2]; + int slopeIsNegative; + int limiterPeakTargetPresent; + FIXP_SGL limiterPeakTarget; + FIXP_DBL loudnessNormalizationGainDb; + FIXP_SGL compress; + FIXP_SGL boost; +} NODE_MODIFICATION; + +static DRC_ERROR _getCicpCharacteristic( + const int cicpCharacteristic, + CHARACTERISTIC_FORMAT pCharacteristicFormat[2], + const CUSTOM_DRC_CHAR* pCCharSource[2]) { + if ((cicpCharacteristic < 1) || (cicpCharacteristic > 11)) { + return DE_NOT_OK; + } + + if (cicpCharacteristic < 7) { /* sigmoid characteristic */ + pCharacteristicFormat[CS_LEFT] = CF_SIGMOID; + pCCharSource[CS_LEFT] = + (const CUSTOM_DRC_CHAR*)(&cicpDrcCharSigmoidLeft[cicpCharacteristic - + 1]); + pCharacteristicFormat[CS_RIGHT] = CF_SIGMOID; + pCCharSource[CS_RIGHT] = + (const CUSTOM_DRC_CHAR*)(&cicpDrcCharSigmoidRight[cicpCharacteristic - + 1]); + } else { /* nodes characteristic */ + pCharacteristicFormat[CS_LEFT] = CF_NODES; + pCCharSource[CS_LEFT] = + (const CUSTOM_DRC_CHAR*)(&cicpDrcCharNodesLeft[cicpCharacteristic - 7]); + pCharacteristicFormat[CS_RIGHT] = CF_NODES; + pCCharSource[CS_RIGHT] = + (const CUSTOM_DRC_CHAR*)(&cicpDrcCharNodesRight[cicpCharacteristic - + 7]); + } + return DE_OK; +} + +static int _getSign(FIXP_SGL in) { + if (in > (FIXP_DBL)0) return 1; + if (in < (FIXP_DBL)0) return -1; + return 0; +} + +static DRC_ERROR _getSlopeSign(const CHARACTERISTIC_FORMAT drcCharFormat, + const CUSTOM_DRC_CHAR* pCChar, int* pSlopeSign) { + if (drcCharFormat == CF_SIGMOID) { + *pSlopeSign = (pCChar->sigmoid.flipSign ? 1 : -1); + } else { + int k, slopeSign = 0, tmp_slopeSign; + for (k = 0; k < pCChar->nodes.characteristicNodeCount; k++) { + if (pCChar->nodes.nodeLevel[k + 1] > pCChar->nodes.nodeLevel[k]) { + tmp_slopeSign = + _getSign(pCChar->nodes.nodeGain[k + 1] - pCChar->nodes.nodeGain[k]); + } else { + tmp_slopeSign = -_getSign(pCChar->nodes.nodeGain[k + 1] - + pCChar->nodes.nodeGain[k]); + } + if ((slopeSign || tmp_slopeSign) && (slopeSign == -tmp_slopeSign)) + return DE_NOT_OK; /* DRC characteristic is not invertible */ + else + slopeSign = tmp_slopeSign; + } + *pSlopeSign = slopeSign; + } + return DE_OK; +} + +static DRC_ERROR _isSlopeNegative(const CHARACTERISTIC_FORMAT drcCharFormat[2], + const CUSTOM_DRC_CHAR* pCChar[2], + int* pSlopeIsNegative) { + DRC_ERROR err = DE_OK; + int slopeSign[2] = {0, 0}; + + err = _getSlopeSign(drcCharFormat[CS_LEFT], pCChar[CS_LEFT], + &slopeSign[CS_LEFT]); + if (err) return err; + + err = _getSlopeSign(drcCharFormat[CS_RIGHT], pCChar[CS_RIGHT], + &slopeSign[CS_RIGHT]); + if (err) return err; + + if ((slopeSign[CS_LEFT] || slopeSign[CS_RIGHT]) && + (slopeSign[CS_LEFT] == -slopeSign[CS_RIGHT])) + return DE_NOT_OK; /* DRC characteristic is not invertible */ + + *pSlopeIsNegative = (slopeSign[CS_LEFT] < 0); + return DE_OK; +} + +static DRC_ERROR _prepareDrcCharacteristic(const DRC_CHARACTERISTIC* pDChar, + DRC_COEFFICIENTS_UNI_DRC* pCoef, + const int b, + NODE_MODIFICATION* pNodeMod) { + DRC_ERROR err = DE_OK; + pNodeMod->drcCharacteristicPresent = pDChar->present; + if (pNodeMod->drcCharacteristicPresent) { + if (pDChar->isCICP == 1) { + err = _getCicpCharacteristic(pDChar->cicpIndex, + pNodeMod->characteristicFormatSource, + pNodeMod->pCCharSource); + if (err) return err; + } else { + pNodeMod->characteristicFormatSource[CS_LEFT] = + (CHARACTERISTIC_FORMAT) + pCoef->characteristicLeftFormat[pDChar->custom.left]; + pNodeMod->pCCharSource[CS_LEFT] = + &(pCoef->customCharacteristicLeft[pDChar->custom.left]); + pNodeMod->characteristicFormatSource[CS_RIGHT] = + (CHARACTERISTIC_FORMAT) + pCoef->characteristicRightFormat[pDChar->custom.right]; + pNodeMod->pCCharSource[CS_RIGHT] = + &(pCoef->customCharacteristicRight[pDChar->custom.right]); + } + err = _isSlopeNegative(pNodeMod->characteristicFormatSource, + pNodeMod->pCCharSource, &pNodeMod->slopeIsNegative); + if (err) return err; + + if (pNodeMod->pGMod != NULL) { + if (pNodeMod->pGMod[b].targetCharacteristicLeftPresent) { + pNodeMod->characteristicFormatTarget[CS_LEFT] = + (CHARACTERISTIC_FORMAT)pCoef->characteristicLeftFormat + [pNodeMod->pGMod[b].targetCharacteristicLeftIndex]; + pNodeMod->pCCharTarget[CS_LEFT] = + &(pCoef->customCharacteristicLeft + [pNodeMod->pGMod[b].targetCharacteristicLeftIndex]); + } + if (pNodeMod->pGMod[b].targetCharacteristicRightPresent) { + pNodeMod->characteristicFormatTarget[CS_RIGHT] = + (CHARACTERISTIC_FORMAT)pCoef->characteristicRightFormat + [pNodeMod->pGMod[b].targetCharacteristicRightIndex]; + pNodeMod->pCCharTarget[CS_RIGHT] = + &(pCoef->customCharacteristicRight + [pNodeMod->pGMod[b].targetCharacteristicRightIndex]); + } + } + } + return DE_OK; +} + +static DRC_ERROR _compressorIO_sigmoid_common( + const FIXP_DBL tmp, /* e = 7 */ + const FIXP_DBL gainDbLimit, /* e = 6 */ + const FIXP_DBL exp, /* e = 5 */ + const int inverse, FIXP_DBL* out) /* e = 7 */ +{ + FIXP_DBL x, tmp1, tmp2, invExp, denom; + int e_x, e_tmp1, e_tmp2, e_invExp, e_denom, e_out; + + if (exp < FL2FXCONST_DBL(1.0f / (float)(1 << 5))) { + return DE_NOT_OK; + } + + /* x = tmp / gainDbLimit; */ + x = fDivNormSigned(tmp, gainDbLimit, &e_x); + e_x += 7 - 6; + if (x < (FIXP_DBL)0) { + return DE_NOT_OK; + } + + /* out = tmp / pow(1.0f +/- pow(x, exp), 1.0f/exp); */ + tmp1 = fPow(x, e_x, exp, 5, &e_tmp1); + if (inverse) tmp1 = -tmp1; + tmp2 = fAddNorm(FL2FXCONST_DBL(1.0f / (float)(1 << 1)), 1, tmp1, e_tmp1, + &e_tmp2); + invExp = fDivNorm(FL2FXCONST_DBL(1.0f / (float)(1 << 1)), exp, &e_invExp); + e_invExp += 1 - 5; + if (tmp2 < (FIXP_DBL)0) { + return DE_NOT_OK; + } + denom = fPow(tmp2, e_tmp2, invExp, e_invExp, &e_denom); + *out = fDivNormSigned(tmp, denom, &e_out); + e_out += 7 - e_denom; + *out = scaleValueSaturate(*out, e_out - 7); + return DE_OK; +} + +static DRC_ERROR _compressorIO_sigmoid(const CUSTOM_DRC_CHAR_SIGMOID* pCChar, + const FIXP_DBL inLevelDb, /* e = 7 */ + FIXP_DBL* outGainDb) /* e = 7 */ +{ + FIXP_DBL tmp; + FIXP_SGL exp = pCChar->exp; + DRC_ERROR err = DE_OK; + + tmp = fMultDiv2((DRC_INPUT_LOUDNESS_TARGET >> 1) - (inLevelDb >> 1), + pCChar->ioRatio); + tmp = SATURATE_LEFT_SHIFT(tmp, 2 + 1 + 1, DFRACT_BITS); + if (exp < (FIXP_SGL)MAXVAL_SGL) { + /* x = tmp / gainDbLimit; */ + /* *outGainDb = tmp / pow(1.0f + pow(x, exp), 1.0f/exp); */ + err = _compressorIO_sigmoid_common(tmp, FX_SGL2FX_DBL(pCChar->gain), + FX_SGL2FX_DBL(exp), 0, outGainDb); + if (err) return err; + } else { + *outGainDb = + tmp; /* scaling of outGainDb (7) is equal to scaling of tmp (7) */ + } + if (pCChar->flipSign == 1) { + *outGainDb = -*outGainDb; + } + return err; +} + +static DRC_ERROR _compressorIO_sigmoid_inverse( + const CUSTOM_DRC_CHAR_SIGMOID* pCChar, const FIXP_SGL gainDb, + FIXP_DBL* inLev) { + DRC_ERROR err = DE_OK; + FIXP_SGL ioRatio = pCChar->ioRatio; + FIXP_SGL exp = pCChar->exp; + FIXP_DBL tmp = FX_SGL2FX_DBL(gainDb), tmp_out; + int e_out; + + if (pCChar->flipSign == 1) { + tmp = -tmp; + } + if (exp < (FIXP_SGL)MAXVAL_SGL) { + /* x = tmp / gainDbLimit; */ + /* tmp = tmp / pow(1.0f - pow(x, exp), 1.0f / exp); */ + err = _compressorIO_sigmoid_common(tmp, FX_SGL2FX_DBL(pCChar->gain), + FX_SGL2FX_DBL(exp), 1, &tmp); + if (err) return err; + } + if (ioRatio == (FIXP_SGL)0) { + return DE_NOT_OK; + } + tmp_out = fDivNormSigned(tmp, FX_SGL2FX_DBL(ioRatio), &e_out); + e_out += 7 - 2; + tmp_out = fAddNorm(DRC_INPUT_LOUDNESS_TARGET, 7, -tmp_out, e_out, &e_out); + *inLev = scaleValueSaturate(tmp_out, e_out - 7); + + return err; +} + +static DRC_ERROR _compressorIO_nodes(const CUSTOM_DRC_CHAR_NODES* pCChar, + const FIXP_DBL inLevelDb, /* e = 7 */ + FIXP_DBL* outGainDb) /* e = 7 */ +{ + int n; + FIXP_DBL w; + const FIXP_SGL* nodeLevel = pCChar->nodeLevel; + const FIXP_SGL* nodeGain = pCChar->nodeGain; + + if (inLevelDb < DRC_INPUT_LOUDNESS_TARGET) { + for (n = 0; n < pCChar->characteristicNodeCount; n++) { + if ((inLevelDb <= FX_SGL2FX_DBL(nodeLevel[n])) && + (inLevelDb > FX_SGL2FX_DBL(nodeLevel[n + 1]))) { + w = fDivNorm(inLevelDb - FX_SGL2FX_DBL(nodeLevel[n + 1]), + FX_SGL2FX_DBL(nodeLevel[n] - nodeLevel[n + 1])); + *outGainDb = fMult(w, nodeGain[n]) + + fMult((FIXP_DBL)MAXVAL_DBL - w, nodeGain[n + 1]); + /* *outGainDb = (w * nodeGain[n] + (1.0-w) * nodeGain[n+1]); */ + return DE_OK; + } + } + } else { + for (n = 0; n < pCChar->characteristicNodeCount; n++) { + if ((inLevelDb >= FX_SGL2FX_DBL(nodeLevel[n])) && + (inLevelDb < FX_SGL2FX_DBL(nodeLevel[n + 1]))) { + w = fDivNorm(FX_SGL2FX_DBL(nodeLevel[n + 1]) - inLevelDb, + FX_SGL2FX_DBL(nodeLevel[n + 1] - nodeLevel[n])); + *outGainDb = fMult(w, nodeGain[n]) + + fMult((FIXP_DBL)MAXVAL_DBL - w, nodeGain[n + 1]); + /* *outGainDb = (w * nodeGain[n] + (1.0-w) * nodeGain[n+1]); */ + return DE_OK; + } + } + } + *outGainDb = FX_SGL2FX_DBL(nodeGain[pCChar->characteristicNodeCount]); + return DE_OK; +} + +static DRC_ERROR _compressorIO_nodes_inverse( + const CUSTOM_DRC_CHAR_NODES* pCChar, const FIXP_SGL gainDb, /* e = 7 */ + FIXP_DBL* inLev) /* e = 7 */ +{ + int n; + int k; + FIXP_DBL w; + int gainIsNegative = 0; + const FIXP_SGL* nodeLevel = pCChar->nodeLevel; + const FIXP_SGL* nodeGain = pCChar->nodeGain; + int nodeCount = pCChar->characteristicNodeCount; + for (k = 0; k < nodeCount; k++) { + if (pCChar->nodeGain[k + 1] < (FIXP_SGL)0) { + gainIsNegative = 1; + } + } + if (gainIsNegative == 1) { + if (gainDb <= nodeGain[nodeCount]) { + *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]); + } else { + if (gainDb >= (FIXP_SGL)0) { + *inLev = DRC_INPUT_LOUDNESS_TARGET; + } else { + for (n = 0; n < nodeCount; n++) { + if ((gainDb <= nodeGain[n]) && (gainDb > nodeGain[n + 1])) { + FIXP_SGL gainDelta = nodeGain[n] - nodeGain[n + 1]; + if (gainDelta == (FIXP_SGL)0) { + *inLev = FX_SGL2FX_DBL(nodeLevel[n]); + return DE_OK; + } + w = fDivNorm(gainDb - nodeGain[n + 1], gainDelta); + *inLev = fMult(w, nodeLevel[n]) + + fMult((FIXP_DBL)MAXVAL_DBL - w, nodeLevel[n + 1]); + /* *inLev = (w * nodeLevel[n] + (1.0-w) * nodeLevel[n+1]); */ + return DE_OK; + } + } + *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]); + } + } + } else { + if (gainDb >= nodeGain[nodeCount]) { + *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]); + } else { + if (gainDb <= (FIXP_SGL)0) { + *inLev = DRC_INPUT_LOUDNESS_TARGET; + } else { + for (n = 0; n < nodeCount; n++) { + if ((gainDb >= nodeGain[n]) && (gainDb < nodeGain[n + 1])) { + FIXP_SGL gainDelta = nodeGain[n + 1] - nodeGain[n]; + if (gainDelta == (FIXP_SGL)0) { + *inLev = FX_SGL2FX_DBL(nodeLevel[n]); + return DE_OK; + } + w = fDivNorm(nodeGain[n + 1] - gainDb, gainDelta); + *inLev = fMult(w, nodeLevel[n]) + + fMult((FIXP_DBL)MAXVAL_DBL - w, nodeLevel[n + 1]); + /* *inLev = (w * nodeLevel[n] + (1.0-w) * nodeLevel[n+1]); */ + return DE_OK; + } + } + *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]); + } + } + } + return DE_OK; +} + +static DRC_ERROR _mapGain(const CHARACTERISTIC_FORMAT pCCharFormatSource, + const CUSTOM_DRC_CHAR* pCCharSource, + const CHARACTERISTIC_FORMAT pCCharFormatTarget, + const CUSTOM_DRC_CHAR* pCCharTarget, + const FIXP_SGL gainInDb, /* e = 7 */ + FIXP_DBL* gainOutDb) /* e = 7 */ +{ + FIXP_DBL inLevel = (FIXP_DBL)0; + DRC_ERROR err = DE_OK; + + switch (pCCharFormatSource) { + case CF_SIGMOID: + err = _compressorIO_sigmoid_inverse( + (const CUSTOM_DRC_CHAR_SIGMOID*)pCCharSource, gainInDb, &inLevel); + if (err) return err; + break; + case CF_NODES: + err = _compressorIO_nodes_inverse( + (const CUSTOM_DRC_CHAR_NODES*)pCCharSource, gainInDb, &inLevel); + if (err) return err; + break; + default: + return DE_NOT_OK; + } + switch (pCCharFormatTarget) { + case CF_SIGMOID: + err = _compressorIO_sigmoid((const CUSTOM_DRC_CHAR_SIGMOID*)pCCharTarget, + inLevel, gainOutDb); + if (err) return err; + break; + case CF_NODES: + err = _compressorIO_nodes((const CUSTOM_DRC_CHAR_NODES*)pCCharTarget, + inLevel, gainOutDb); + if (err) return err; + break; + default: + break; + } + return DE_OK; +} + +static DRC_ERROR _toLinear( + const NODE_MODIFICATION* nodeMod, const int drcBand, + const FIXP_SGL gainDb, /* in: gain value in dB, e = 7 */ + const FIXP_SGL slopeDb, /* in: slope value in dB/deltaTmin, e = 2 */ + FIXP_DBL* gainLin, /* out: linear gain value, e = 7 */ + FIXP_DBL* slopeLin) /* out: linear slope value, e = 7 */ +{ + FIXP_DBL gainRatio_m = FL2FXCONST_DBL(1.0f / (float)(1 << 1)); + GAIN_MODIFICATION* pGMod = NULL; + DUCKING_MODIFICATION* pDMod = nodeMod->pDMod; + FIXP_DBL tmp_dbl, gainDb_modified, gainDb_offset, gainDb_out, gainLin_m, + slopeLin_m; + int gainLin_e, gainRatio_e = 1, gainDb_out_e; + if (nodeMod->pGMod != NULL) { + pGMod = &(nodeMod->pGMod[drcBand]); + } + if (((nodeMod->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) == 0) && + (nodeMod->drcSetEffect != EB_FADE) && + (nodeMod->drcSetEffect != EB_CLIPPING)) { + DRC_ERROR err = DE_OK; + FIXP_DBL gainDbMapped; + + if ((pGMod != NULL) && (nodeMod->drcCharacteristicPresent)) { + if (((gainDb > (FIXP_SGL)0) && nodeMod->slopeIsNegative) || + ((gainDb < (FIXP_SGL)0) && !nodeMod->slopeIsNegative)) { + /* left side */ + if (pGMod->targetCharacteristicLeftPresent == 1) { + err = _mapGain(nodeMod->characteristicFormatSource[CS_LEFT], + nodeMod->pCCharSource[CS_LEFT], + nodeMod->characteristicFormatTarget[CS_LEFT], + nodeMod->pCCharTarget[CS_LEFT], gainDb, &gainDbMapped); + if (err) return err; + gainRatio_m = fDivNormSigned( + gainDbMapped, FX_SGL2FX_DBL(gainDb), + &gainRatio_e); /* target characteristic in payload */ + } + } + + else { /* if (((gainDb < (FIXP_SGL)0) && nodeMod->slopeIsNegative) || + ((gainDb > (FIXP_SGL)0) && !nodeMod->slopeIsNegative)) */ + + /* right side */ + if (pGMod->targetCharacteristicRightPresent == 1) { + err = + _mapGain(nodeMod->characteristicFormatSource[CS_RIGHT], + nodeMod->pCCharSource[CS_RIGHT], + nodeMod->characteristicFormatTarget[CS_RIGHT], + nodeMod->pCCharTarget[CS_RIGHT], gainDb, &gainDbMapped); + if (err) return err; + gainRatio_m = fDivNormSigned( + gainDbMapped, FX_SGL2FX_DBL(gainDb), + &gainRatio_e); /* target characteristic in payload */ + } + } + } + if (gainDb < (FIXP_SGL)0) { + gainRatio_m = fMultDiv2(gainRatio_m, nodeMod->compress); + } else { + gainRatio_m = fMultDiv2(gainRatio_m, nodeMod->boost); + } + gainRatio_e += 2; + } + if ((pGMod != NULL) && (pGMod->gainScalingPresent == 1)) { + if (gainDb < (FIXP_SGL)0) { + gainRatio_m = fMultDiv2(gainRatio_m, pGMod->attenuationScaling); + } else { + gainRatio_m = fMultDiv2(gainRatio_m, pGMod->amplificationScaling); + } + gainRatio_e += 3; + } + if ((pDMod != NULL) && + (nodeMod->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) && + (pDMod->duckingScalingPresent == 1)) { + gainRatio_m = fMultDiv2(gainRatio_m, pDMod->duckingScaling); + gainRatio_e += 3; + } + + gainDb_modified = + fMultDiv2(gainDb, gainRatio_m); /* resulting e: 7 + gainRatio_e + 1*/ + gainDb_offset = (FIXP_DBL)0; + + if ((pGMod != NULL) && (pGMod->gainOffsetPresent == 1)) { + /* *gainLin *= (float)pow(2.0, (double)(pGMod->gainOffset/6.0f)); */ + gainDb_offset += FX_SGL2FX_DBL(pGMod->gainOffset) >> 4; /* resulting e: 8 */ + } + if ((nodeMod->limiterPeakTargetPresent == 1) && + (nodeMod->drcSetEffect == + EB_CLIPPING)) { /* The only drcSetEffect is "clipping prevention" */ + /* loudnessNormalizationGainModificationDb is included in + * loudnessNormalizationGainDb */ + /* *gainLin *= (float)pow(2.0, max(0.0, -nodeModification->limiterPeakTarget + * - nodeModification->loudnessNormalizationGainDb)/6.0); */ + gainDb_offset += fMax( + (FIXP_DBL)0, + (FX_SGL2FX_DBL(-nodeMod->limiterPeakTarget) >> 3) - + (nodeMod->loudnessNormalizationGainDb >> 1)); /* resulting e: 8 */ + } + if (gainDb_offset != (FIXP_DBL)0) { + gainDb_out = fAddNorm(gainDb_modified, 7 + gainRatio_e + 1, gainDb_offset, + 8, &gainDb_out_e); + } else { + gainDb_out = gainDb_modified; + gainDb_out_e = 7 + gainRatio_e + 1; + } + + /* *gainLin = (float)pow(2.0, (double)(gainDb_modified[1] / 6.0f)); */ + gainLin_m = approxDb2lin(gainDb_out, gainDb_out_e, &gainLin_e); + *gainLin = scaleValueSaturate(gainLin_m, gainLin_e - 7); + + /* *slopeLin = SLOPE_FACTOR_DB_TO_LINEAR * gainRatio * *gainLin * slopeDb; */ + if (slopeDb == (FIXP_SGL)0) { + *slopeLin = (FIXP_DBL)0; + } else { + tmp_dbl = + fMult(slopeDb, SLOPE_FACTOR_DB_TO_LINEAR); /* resulting e: 2 - 3 = -1 */ + tmp_dbl = fMult(tmp_dbl, gainRatio_m); /* resulting e: -1 + gainRatio_e */ + if (gainDb_offset != + (FIXP_DBL)0) { /* recalculate gainLin from gainDb that wasn't modified + by gainOffset and limiterPeakTarget */ + gainLin_m = approxDb2lin(gainDb_modified, 7 + gainRatio_e, &gainLin_e); + } + slopeLin_m = fMult(tmp_dbl, gainLin_m); + *slopeLin = + scaleValueSaturate(slopeLin_m, -1 + gainRatio_e + gainLin_e - 7); + } + + if ((nodeMod->limiterPeakTargetPresent == 1) && + (nodeMod->drcSetEffect == EB_CLIPPING)) { + if (*gainLin >= FL2FXCONST_DBL(1.0f / (float)(1 << 7))) { + *gainLin = FL2FXCONST_DBL(1.0f / (float)(1 << 7)); + *slopeLin = (FIXP_DBL)0; + } + } + + return DE_OK; +} + +/* prepare buffers containing linear nodes for each gain sequence */ +DRC_ERROR +prepareDrcGain(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_GAIN hUniDrcGain, const FIXP_SGL compress, + const FIXP_SGL boost, const FIXP_DBL loudnessNormalizationGainDb, + const int activeDrcIndex) { + int b, g, gainElementIndex; + DRC_GAIN_BUFFERS* drcGainBuffers = &(hGainDec->drcGainBuffers); + NODE_MODIFICATION nodeMod; + FDKmemclear(&nodeMod, sizeof(NODE_MODIFICATION)); + ACTIVE_DRC* pActiveDrc = &(hGainDec->activeDrc[activeDrcIndex]); + DRC_INSTRUCTIONS_UNI_DRC* pInst = pActiveDrc->pInst; + if (pInst == NULL) return DE_NOT_OK; + + nodeMod.drcSetEffect = pInst->drcSetEffect; + + nodeMod.compress = compress; + nodeMod.boost = boost; + nodeMod.loudnessNormalizationGainDb = loudnessNormalizationGainDb; + nodeMod.limiterPeakTargetPresent = pInst->limiterPeakTargetPresent; + nodeMod.limiterPeakTarget = pInst->limiterPeakTarget; + + gainElementIndex = 0; + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + int gainSetIndex = 0; + int nDrcBands = 0; + DRC_COEFFICIENTS_UNI_DRC* pCoef = pActiveDrc->pCoef; + if (pCoef == NULL) return DE_NOT_OK; + + if (!pActiveDrc->channelGroupIsParametricDrc[g]) { + gainSetIndex = pInst->gainSetIndexForChannelGroup[g]; + + if (nodeMod.drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { + nodeMod.pDMod = &(pActiveDrc->duckingModificationForChannelGroup[g]); + nodeMod.pGMod = NULL; + } else { + nodeMod.pGMod = pInst->gainModificationForChannelGroup[g]; + nodeMod.pDMod = NULL; + } + + nDrcBands = pActiveDrc->bandCountForChannelGroup[g]; + for (b = 0; b < nDrcBands; b++) { + DRC_ERROR err = DE_OK; + GAIN_SET* pGainSet = &(pCoef->gainSet[gainSetIndex]); + int seq = pGainSet->gainSequenceIndex[b]; + DRC_CHARACTERISTIC* pDChar = &(pGainSet->drcCharacteristic[b]); + + /* linearNodeBuffer contains a copy of the gain sequences (consisting of + nodes) that are relevant for decoding. It also contains gain + sequences of previous frames. */ + LINEAR_NODE_BUFFER* pLnb = + &(drcGainBuffers->linearNodeBuffer[pActiveDrc->activeDrcOffset + + gainElementIndex]); + int i, lnbp; + lnbp = drcGainBuffers->lnbPointer; + pLnb->gainInterpolationType = + (GAIN_INTERPOLATION_TYPE)pGainSet->gainInterpolationType; + + err = _prepareDrcCharacteristic(pDChar, pCoef, b, &nodeMod); + if (err) return err; + + /* copy a node buffer and convert from dB to linear */ + pLnb->nNodes[lnbp] = fMin((int)hUniDrcGain->nNodes[seq], 16); + for (i = 0; i < pLnb->nNodes[lnbp]; i++) { + FIXP_DBL gainLin, slopeLin; + err = _toLinear(&nodeMod, b, hUniDrcGain->gainNode[seq][i].gainDb, + (FIXP_SGL)0, &gainLin, &slopeLin); + if (err) return err; + pLnb->linearNode[lnbp][i].gainLin = gainLin; + pLnb->linearNode[lnbp][i].time = hUniDrcGain->gainNode[seq][i].time; + } + gainElementIndex++; + } + } else { + /* parametric DRC not supported */ + gainElementIndex++; + } + } + return DE_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_preprocess.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_preprocess.h new file mode 100644 index 0000000000000..4647407e16230 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_preprocess.h @@ -0,0 +1,111 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCGAINDEC_PREPROCESS_H +#define DRCGAINDEC_PREPROCESS_H + +DRC_ERROR +prepareDrcGain(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_GAIN hUniDrcGain, const FIXP_SGL compress, + const FIXP_SGL boost, const FIXP_DBL loudnessNormalizationGainDb, + const int activeDrcIndex); +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_process.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_process.cpp new file mode 100644 index 0000000000000..70c953312a476 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_process.cpp @@ -0,0 +1,532 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "drcDec_types.h" +#include "drcDec_gainDecoder.h" +#include "drcGainDec_process.h" + +#define E_TGAINSTEP 12 + +static DRC_ERROR _prepareLnbIndex(ACTIVE_DRC* pActiveDrc, + const int channelOffset, + const int drcChannelOffset, + const int numChannelsProcessed, + const int lnbPointer) { + int g, c; + DRC_INSTRUCTIONS_UNI_DRC* pInst = pActiveDrc->pInst; + + /* channelOffset: start index of physical channels + numChannelsProcessed: number of processed channels, physical channels and + DRC channels channelOffset + drcChannelOffset: start index of DRC channels, + i.e. the channel order referenced in pInst.sequenceIndex */ + + /* sanity checks */ + if ((channelOffset + numChannelsProcessed) > 8) return DE_NOT_OK; + + if ((channelOffset + drcChannelOffset + numChannelsProcessed) > 8) + return DE_NOT_OK; + + if ((channelOffset + drcChannelOffset) < 0) return DE_NOT_OK; + + /* prepare lnbIndexForChannel, a map of indices from each channel to its + * corresponding linearNodeBuffer instance */ + for (c = channelOffset; c < channelOffset + numChannelsProcessed; c++) { + if (pInst->drcSetId > 0) { + int drcChannel = c + drcChannelOffset; + /* fallback for configuration with more physical channels than DRC + channels: reuse DRC gain of first channel. This is necessary for HE-AAC + mono with stereo output */ + if (drcChannel >= pInst->drcChannelCount) drcChannel = 0; + g = pActiveDrc->channelGroupForChannel[drcChannel]; + if ((g >= 0) && !pActiveDrc->channelGroupIsParametricDrc[g]) { + pActiveDrc->lnbIndexForChannel[c][lnbPointer] = + pActiveDrc->activeDrcOffset + pActiveDrc->gainElementForGroup[g]; + } + } + } + + return DE_OK; +} + +static DRC_ERROR _interpolateDrcGain( + const GAIN_INTERPOLATION_TYPE gainInterpolationType, + const SHORT timePrev, /* time0 */ + const SHORT tGainStep, /* time1 - time0 */ + const SHORT start, const SHORT stop, const SHORT stepsize, + const FIXP_DBL gainLeft, const FIXP_DBL gainRight, const FIXP_DBL slopeLeft, + const FIXP_DBL slopeRight, FIXP_DBL* buffer) { + int n, n_buf; + int start_modulo, start_offset; + + if (tGainStep < 0) { + return DE_NOT_OK; + } + if (tGainStep == 0) { + return DE_OK; + } + + /* get start index offset and buffer index for downsampled interpolation */ + /* start_modulo = (start+timePrev)%stepsize; */ /* stepsize is a power of 2 */ + start_modulo = (start + timePrev) & (stepsize - 1); + start_offset = (start_modulo ? stepsize - start_modulo : 0); + /* n_buf = (start + timePrev + start_offset)/stepsize; */ + n_buf = (start + timePrev + start_offset) >> (15 - fixnormz_S(stepsize)); + + { /* gainInterpolationType == GIT_LINEAR */ + LONG a; + /* runs = ceil((stop - start - start_offset)/stepsize). This works for + * stepsize = 2^N only. */ + INT runs = (INT)(stop - start - start_offset + stepsize - 1) >> + (30 - CountLeadingBits(stepsize)); + INT n_min = fMin( + fMin(CntLeadingZeros(gainRight), CntLeadingZeros(gainLeft)) - 1, 8); + a = (LONG)((gainRight << n_min) - (gainLeft << n_min)) / tGainStep; + LONG a_step = a * stepsize; + n = start + start_offset; + a = a * n + (LONG)(gainLeft << n_min); + buffer += n_buf; +#if defined(FUNCTION_interpolateDrcGain_func1) + interpolateDrcGain_func1(buffer, a, a_step, n_min, runs); +#else + a -= a_step; + n_min = 8 - n_min; + for (int i = 0; i < runs; i++) { + a += a_step; + buffer[i] = fMultDiv2(buffer[i], (FIXP_DBL)a) << n_min; + } +#endif /* defined(FUNCTION_interpolateDrcGain_func1) */ + } + return DE_OK; +} + +static DRC_ERROR _processNodeSegments( + const int frameSize, const GAIN_INTERPOLATION_TYPE gainInterpolationType, + const int nNodes, const NODE_LIN* pNodeLin, const int offset, + const SHORT stepsize, + const NODE_LIN nodePrevious, /* the last node of the previous frame */ + const FIXP_DBL channelGain, FIXP_DBL* buffer) { + DRC_ERROR err = DE_OK; + SHORT timePrev, duration, start, stop, time; + int n; + FIXP_DBL gainLin = FL2FXCONST_DBL(1.0f / (float)(1 << 7)), gainLinPrev; + FIXP_DBL slopeLin = (FIXP_DBL)0, slopeLinPrev = (FIXP_DBL)0; + + timePrev = nodePrevious.time + offset; + gainLinPrev = nodePrevious.gainLin; + for (n = 0; n < nNodes; n++) { + time = pNodeLin[n].time + offset; + duration = time - timePrev; + gainLin = pNodeLin[n].gainLin; + if (channelGain != FL2FXCONST_DBL(1.0f / (float)(1 << 8))) + gainLin = + SATURATE_LEFT_SHIFT(fMultDiv2(gainLin, channelGain), 9, DFRACT_BITS); + + if ((timePrev >= (frameSize - 1)) || + (time < 0)) { /* This segment (between previous and current node) lies + outside of this audio frame */ + timePrev = time; + gainLinPrev = gainLin; + slopeLinPrev = slopeLin; + continue; + } + + /* start and stop are the boundaries of the region of this segment that lie + within this audio frame. Their values are relative to the beginning of + this segment. stop is the first sample that isn't processed any more. */ + start = fMax(-timePrev, 1); + stop = fMin(time, (SHORT)(frameSize - 1)) - timePrev + 1; + + err = _interpolateDrcGain(gainInterpolationType, timePrev, duration, start, + stop, stepsize, gainLinPrev, gainLin, + slopeLinPrev, slopeLin, buffer); + if (err) return err; + + timePrev = time; + gainLinPrev = gainLin; + } + return err; +} + +/* process DRC on time-domain signal */ +DRC_ERROR +processDrcTime(HANDLE_DRC_GAIN_DECODER hGainDec, const int activeDrcIndex, + const int delaySamples, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int timeDataChannelOffset, FIXP_DBL* deinterleavedAudio) { + DRC_ERROR err = DE_OK; + int c, b, i; + ACTIVE_DRC* pActiveDrc = &(hGainDec->activeDrc[activeDrcIndex]); + DRC_GAIN_BUFFERS* pDrcGainBuffers = &(hGainDec->drcGainBuffers); + int lnbPointer = pDrcGainBuffers->lnbPointer, lnbIx; + LINEAR_NODE_BUFFER* pLinearNodeBuffer = pDrcGainBuffers->linearNodeBuffer; + LINEAR_NODE_BUFFER* pDummyLnb = &(pDrcGainBuffers->dummyLnb); + int offset = 0; + + if (hGainDec->delayMode == DM_REGULAR_DELAY) { + offset = hGainDec->frameSize; + } + + if ((delaySamples + offset) > + (NUM_LNB_FRAMES - 2) * + hGainDec->frameSize) /* if delaySamples is too big, NUM_LNB_FRAMES + should be increased */ + return DE_NOT_OK; + + err = _prepareLnbIndex(pActiveDrc, channelOffset, drcChannelOffset, + numChannelsProcessed, lnbPointer); + if (err) return err; + + deinterleavedAudio += + channelOffset * timeDataChannelOffset; /* apply channelOffset */ + + /* signal processing loop */ + for (c = channelOffset; c < channelOffset + numChannelsProcessed; c++) { + if (activeDrcIndex == hGainDec->channelGainActiveDrcIndex) + pDrcGainBuffers->channelGain[c][lnbPointer] = hGainDec->channelGain[c]; + + b = 0; + { + LINEAR_NODE_BUFFER *pLnb, *pLnbPrevious; + NODE_LIN nodePrevious; + int lnbPointerDiff; + FIXP_DBL channelGain; + /* get pointer to oldest linearNodes */ + lnbIx = lnbPointer + 1 - NUM_LNB_FRAMES; + while (lnbIx < 0) lnbIx += NUM_LNB_FRAMES; + + if (activeDrcIndex == hGainDec->channelGainActiveDrcIndex) + channelGain = pDrcGainBuffers->channelGain[c][lnbIx]; + else + channelGain = FL2FXCONST_DBL(1.0f / (float)(1 << 8)); + + /* Loop over all node buffers in linearNodeBuffer. + All nodes which are not relevant for the current frame are sorted out + inside _processNodeSegments. */ + for (i = 0; i < NUM_LNB_FRAMES - 1; i++) { + /* Prepare previous node */ + if (pActiveDrc->lnbIndexForChannel[c][lnbIx] >= 0) + pLnbPrevious = &( + pLinearNodeBuffer[pActiveDrc->lnbIndexForChannel[c][lnbIx] + b]); + else + pLnbPrevious = pDummyLnb; + nodePrevious = + pLnbPrevious->linearNode[lnbIx][pLnbPrevious->nNodes[lnbIx] - 1]; + nodePrevious.time -= hGainDec->frameSize; + if (channelGain != FL2FXCONST_DBL(1.0f / (float)(1 << 8))) + nodePrevious.gainLin = SATURATE_LEFT_SHIFT( + fMultDiv2(nodePrevious.gainLin, + pDrcGainBuffers->channelGain[c][lnbIx]), + 9, DFRACT_BITS); + + /* Prepare current linearNodeBuffer instance */ + lnbIx++; + if (lnbIx >= NUM_LNB_FRAMES) lnbIx = 0; + + /* if lnbIndexForChannel changes over time, use the old indices for + * smooth transitions */ + if (pActiveDrc->lnbIndexForChannel[c][lnbIx] >= 0) + pLnb = &( + pLinearNodeBuffer[pActiveDrc->lnbIndexForChannel[c][lnbIx] + b]); + else /* lnbIndexForChannel = -1 means "no DRC processing", due to + drcInstructionsIndex < 0, drcSetId < 0 or channel group < 0 */ + pLnb = pDummyLnb; + + if (activeDrcIndex == hGainDec->channelGainActiveDrcIndex) + channelGain = pDrcGainBuffers->channelGain[c][lnbIx]; + + /* number of frames of offset with respect to lnbPointer */ + lnbPointerDiff = i - (NUM_LNB_FRAMES - 2); + + err = _processNodeSegments( + hGainDec->frameSize, pLnb->gainInterpolationType, + pLnb->nNodes[lnbIx], pLnb->linearNode[lnbIx], + lnbPointerDiff * hGainDec->frameSize + delaySamples + offset, 1, + nodePrevious, channelGain, deinterleavedAudio); + if (err) return err; + } + deinterleavedAudio += timeDataChannelOffset; /* proceed to next channel */ + } + } + return DE_OK; +} + +/* process DRC on subband-domain signal */ +DRC_ERROR +processDrcSubband(HANDLE_DRC_GAIN_DECODER hGainDec, const int activeDrcIndex, + const int delaySamples, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int processSingleTimeslot, + FIXP_DBL* deinterleavedAudioReal[], + FIXP_DBL* deinterleavedAudioImag[]) { + DRC_ERROR err = DE_OK; + int b, c, g, m, m_start, m_stop, s, i; + FIXP_DBL gainSb; + DRC_INSTRUCTIONS_UNI_DRC* pInst = hGainDec->activeDrc[activeDrcIndex].pInst; + DRC_GAIN_BUFFERS* pDrcGainBuffers = &(hGainDec->drcGainBuffers); + ACTIVE_DRC* pActiveDrc = &(hGainDec->activeDrc[activeDrcIndex]); + int activeDrcOffset = pActiveDrc->activeDrcOffset; + int lnbPointer = pDrcGainBuffers->lnbPointer, lnbIx; + LINEAR_NODE_BUFFER* pLinearNodeBuffer = pDrcGainBuffers->linearNodeBuffer; + FIXP_DBL(*subbandGains)[4 * 1024 / 256] = hGainDec->subbandGains; + FIXP_DBL* dummySubbandGains = hGainDec->dummySubbandGains; + SUBBAND_DOMAIN_MODE subbandDomainMode = hGainDec->subbandDomainSupported; + int signalIndex = 0; + int frameSizeSb = 0; + int nDecoderSubbands; + SHORT L = 0; /* L: downsampling factor */ + int offset = 0; + FIXP_DBL *audioReal = NULL, *audioImag = NULL; + + if (hGainDec->delayMode == DM_REGULAR_DELAY) { + offset = hGainDec->frameSize; + } + + if ((delaySamples + offset) > + (NUM_LNB_FRAMES - 2) * + hGainDec->frameSize) /* if delaySamples is too big, NUM_LNB_FRAMES + should be increased */ + return DE_NOT_OK; + + switch (subbandDomainMode) { +#if ((1024 / 256) >= (4096 / SUBBAND_DOWNSAMPLING_FACTOR_QMF64)) + case SDM_QMF64: + nDecoderSubbands = SUBBAND_NUM_BANDS_QMF64; + L = SUBBAND_DOWNSAMPLING_FACTOR_QMF64; + /* analysisDelay = SUBBAND_ANALYSIS_DELAY_QMF64; */ + break; + case SDM_QMF71: + nDecoderSubbands = SUBBAND_NUM_BANDS_QMF71; + L = SUBBAND_DOWNSAMPLING_FACTOR_QMF71; + /* analysisDelay = SUBBAND_ANALYSIS_DELAY_QMF71; */ + break; +#else + case SDM_QMF64: + case SDM_QMF71: + /* QMF domain processing is not supported. */ + return DE_NOT_OK; +#endif + case SDM_STFT256: + nDecoderSubbands = SUBBAND_NUM_BANDS_STFT256; + L = SUBBAND_DOWNSAMPLING_FACTOR_STFT256; + /* analysisDelay = SUBBAND_ANALYSIS_DELAY_STFT256; */ + break; + default: + return DE_NOT_OK; + } + + /* frameSizeSb = hGainDec->frameSize/L; */ /* L is a power of 2 */ + frameSizeSb = + hGainDec->frameSize >> (15 - fixnormz_S(L)); /* timeslots per frame */ + + if ((processSingleTimeslot < 0) || (processSingleTimeslot >= frameSizeSb)) { + m_start = 0; + m_stop = frameSizeSb; + } else { + m_start = processSingleTimeslot; + m_stop = m_start + 1; + } + + err = _prepareLnbIndex(pActiveDrc, channelOffset, drcChannelOffset, + numChannelsProcessed, lnbPointer); + if (err) return err; + + if (!pActiveDrc->subbandGainsReady) /* only for the first time per frame that + processDrcSubband is called */ + { + /* write subbandGains */ + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + b = 0; + { + LINEAR_NODE_BUFFER* pLnb = + &(pLinearNodeBuffer[activeDrcOffset + + pActiveDrc->gainElementForGroup[g] + b]); + NODE_LIN nodePrevious; + int lnbPointerDiff; + + for (m = 0; m < frameSizeSb; m++) { + subbandGains[activeDrcOffset + g][b * frameSizeSb + m] = + FL2FXCONST_DBL(1.0f / (float)(1 << 7)); + } + + lnbIx = lnbPointer - (NUM_LNB_FRAMES - 1); + while (lnbIx < 0) lnbIx += NUM_LNB_FRAMES; + + /* Loop over all node buffers in linearNodeBuffer. + All nodes which are not relevant for the current frame are sorted out + inside _processNodeSegments. */ + for (i = 0; i < NUM_LNB_FRAMES - 1; i++) { + /* Prepare previous node */ + nodePrevious = pLnb->linearNode[lnbIx][pLnb->nNodes[lnbIx] - 1]; + nodePrevious.time -= hGainDec->frameSize; + + lnbIx++; + if (lnbIx >= NUM_LNB_FRAMES) lnbIx = 0; + + /* number of frames of offset with respect to lnbPointer */ + lnbPointerDiff = i - (NUM_LNB_FRAMES - 2); + + err = _processNodeSegments( + hGainDec->frameSize, pLnb->gainInterpolationType, + pLnb->nNodes[lnbIx], pLnb->linearNode[lnbIx], + lnbPointerDiff * hGainDec->frameSize + delaySamples + offset - + (L - 1) / 2, + L, nodePrevious, FL2FXCONST_DBL(1.0f / (float)(1 << 8)), + &(subbandGains[activeDrcOffset + g][b * frameSizeSb])); + if (err) return err; + } + } + } + pActiveDrc->subbandGainsReady = 1; + } + + for (c = channelOffset; c < channelOffset + numChannelsProcessed; c++) { + FIXP_DBL* thisSubbandGainsBuffer; + if (pInst->drcSetId > 0) + g = pActiveDrc->channelGroupForChannel[c + drcChannelOffset]; + else + g = -1; + + audioReal = deinterleavedAudioReal[signalIndex]; + if (subbandDomainMode != SDM_STFT256) { + audioImag = deinterleavedAudioImag[signalIndex]; + } + + if ((g >= 0) && !pActiveDrc->channelGroupIsParametricDrc[g]) { + thisSubbandGainsBuffer = subbandGains[activeDrcOffset + g]; + } else { + thisSubbandGainsBuffer = dummySubbandGains; + } + + for (m = m_start; m < m_stop; m++) { + INT n_min = 8; + { /* single-band DRC */ + gainSb = thisSubbandGainsBuffer[m]; + if (activeDrcIndex == hGainDec->channelGainActiveDrcIndex) + gainSb = SATURATE_LEFT_SHIFT( + fMultDiv2(gainSb, hGainDec->channelGain[c]), 9, DFRACT_BITS); + /* normalize gainSb for keeping signal precision */ + n_min = fMin(CntLeadingZeros(gainSb) - 1, n_min); + gainSb <<= n_min; + n_min = 8 - n_min; + if (subbandDomainMode == + SDM_STFT256) { /* For STFT filterbank, real and imaginary parts are + interleaved. */ + for (s = 0; s < nDecoderSubbands; s++) { + *audioReal = fMultDiv2(*audioReal, gainSb) << n_min; + audioReal++; + *audioReal = fMultDiv2(*audioReal, gainSb) << n_min; + audioReal++; + } + } else { + for (s = 0; s < nDecoderSubbands; s++) { + *audioReal = fMultDiv2(*audioReal, gainSb) << n_min; + audioReal++; + *audioImag = fMultDiv2(*audioImag, gainSb) << n_min; + audioImag++; + } + } + } + } + signalIndex++; + } + return DE_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_process.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_process.h new file mode 100644 index 0000000000000..f751aba0b2af2 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libDRCdec/src/drcGainDec_process.h @@ -0,0 +1,119 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCGAINDEC_PROCESS_H +#define DRCGAINDEC_PROCESS_H + +DRC_ERROR +processDrcTime(HANDLE_DRC_GAIN_DECODER hGainDec, const int activeDrcIndex, + const int delaySamples, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int timeDataChannelOffset, FIXP_DBL* deinterleavedAudio); + +DRC_ERROR +processDrcSubband(HANDLE_DRC_GAIN_DECODER hGainDec, const int activeDrcIndex, + const int delaySamples, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int processSingleTimeslot, + FIXP_DBL* deinterleavedAudioReal[], + FIXP_DBL* deinterleavedAudioImag[]); +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_archdef.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_archdef.h new file mode 100644 index 0000000000000..f3254f2958cf9 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_archdef.h @@ -0,0 +1,280 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef FDK_ARCHDEF_H +#define FDK_ARCHDEF_H + +/* Unify some few toolchain specific defines to avoid having large "or" macro + * contraptions all over the source code. */ + +/* Use single macro (the GCC built in macro) for architecture identification + * independent of the particular toolchain */ +#if defined(__i386__) || defined(__i486__) || defined(__i586__) || \ + defined(__i686__) || (defined(_MSC_VER) && defined(_M_IX86)) || \ + (defined(_MSC_VER) && defined(_M_X64)) || defined(__x86_64__) +#define __x86__ +#endif + +#if defined(_M_ARM) && !defined(__arm__) || defined(__aarch64__) || defined(_M_ARM64) +#define __arm__ +#endif + +#if defined(_ARCH_PPC) && !defined(__powerpc__) +#define __powerpc__ 1 +#endif + +#if (__TARGET_ARCH_ARM == 5) || defined(__TARGET_FEATURE_DSPMUL) || \ + (_M_ARM == 5) || defined(__ARM_ARCH_5TEJ__) || defined(__ARM_ARCH_7EM__) +/* Define __ARM_ARCH_5TE__ if armv5te features are supported */ +#define __ARM_ARCH_5TE__ +#endif + +#if (__TARGET_ARCH_ARM == 6) || defined(__ARM_ARCH_6J__) || \ + defined(__ARM_ARCH_6ZK__) +/* Define __ARM_ARCH_6__ if the armv6 intructions are being supported. */ +#define __ARM_ARCH_5TE__ +#define __ARM_ARCH_6__ +#endif + +#if defined(__TARGET_ARCH_7_R) || defined(__ARM_ARCH_7R__) +/* Define __ARM_ARCH_7_A__ if the armv7 intructions are being supported. */ +#define __ARM_ARCH_5TE__ +#define __ARM_ARCH_6__ +#define __ARM_ARCH_7_R__ +#endif + +#if defined(__TARGET_ARCH_7_A) || defined(__ARM_ARCH_7A__) || \ + ((__ARM_ARCH == 8) && (__ARM_32BIT_STATE == 1)) +/* Define __ARM_ARCH_7_A__ if the armv7 intructions are being supported. */ +#define __ARM_ARCH_5TE__ +#define __ARM_ARCH_6__ +#define __ARM_ARCH_7_A__ +#endif + +#if defined(__TARGET_ARCH_7_M) || defined(__ARM_ARCH_7_M__) +/* Define __ARM_ARCH_7M__ if the ARMv7-M instructions are being supported, e.g. + * Cortex-M3. */ +#define __ARM_ARCH_7M__ +#endif + +#if defined(__TARGET_ARCH_7E_M) || defined(__ARM_ARCH_7E_M__) +/* Define __ARM_ARCH_7EM__ if the ARMv7-ME instructions are being supported, + * e.g. Cortex-M4. */ +#define __ARM_ARCH_7EM__ +#endif + +#if defined(__aarch64__) || defined(_M_ARM64) +#define __ARM_ARCH_8__ +#endif + +#ifdef _M_ARM +#include "armintr.h" +#endif + +/* Define preferred Multiplication type */ + +#if defined(__mips__) +#define ARCH_PREFER_MULT_16x16 +#undef SINETABLE_16BIT +#undef POW2COEFF_16BIT +#undef LDCOEFF_16BIT +#undef WINDOWTABLE_16BIT + +#elif defined(__arm__) && defined(__ARM_ARCH_8__) +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__arm__) && defined(__ARM_ARCH_5TE__) +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__arm__) && defined(__ARM_ARCH_7M__) +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__arm__) && defined(__ARM_ARCH_7EM__) +#define ARCH_PREFER_MULT_32x32 +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__arm__) && !defined(__ARM_ARCH_5TE__) +#define ARCH_PREFER_MULT_16x16 +#undef SINETABLE_16BIT +#undef WINDOWTABLE_16BIT +#undef POW2COEFF_16BIT +#undef LDCOEFF_16BIT + +#elif defined(__x86__) +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define WINDOWTABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT + +#elif defined(__riscv) +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__powerpc__) +#define ARCH_PREFER_MULT_32x32 + +#elif defined(__s390x__) +#define ARCH_PREFER_MULT_32x32 +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#else +#warning >>>> Please set architecture characterization defines for your platform (FDK_HIGH_PERFORMANCE)! <<<< + +#endif /* Architecture switches */ + +#ifdef SINETABLE_16BIT +#define FIXP_STB FIXP_SGL /* STB sinus Tab used in transformation */ +#define FIXP_STP FIXP_SPK +#define STC(a) (FX_DBL2FXCONST_SGL(a)) +#else +#define FIXP_STB FIXP_DBL +#define FIXP_STP FIXP_DPK +#define STC(a) ((FIXP_DBL)(LONG)(a)) +#endif /* defined(SINETABLE_16BIT) */ + +#define STCP(cos, sin) \ + { \ + { STC(cos), STC(sin) } \ + } + +#ifdef WINDOWTABLE_16BIT +#define FIXP_WTB FIXP_SGL /* single FIXP_SGL values */ +#define FX_DBL2FX_WTB(x) FX_DBL2FX_SGL(x) +#define FIXP_WTP FIXP_SPK /* packed FIXP_SGL values */ +#define WTC(a) FX_DBL2FXCONST_SGL(a) +#else /* SINETABLE_16BIT */ +#define FIXP_WTB FIXP_DBL +#define FX_DBL2FX_WTB(x) (x) +#define FIXP_WTP FIXP_DPK +#define WTC(a) (FIXP_DBL)(a) +#endif /* SINETABLE_16BIT */ + +#define WTCP(a, b) \ + { \ + { WTC(a), WTC(b) } \ + } + +#endif /* FDK_ARCHDEF_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_bitbuffer.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_bitbuffer.h new file mode 100644 index 0000000000000..19a24b32133a6 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_bitbuffer.h @@ -0,0 +1,177 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser + + Description: common bitbuffer read/write routines + +*******************************************************************************/ + +#ifndef FDK_BITBUFFER_H +#define FDK_BITBUFFER_H + +#include "FDK_archdef.h" +#include "machine_type.h" + +/* leave 3 bits headroom so MAX_BUFSIZE can be represented in bits as well. */ +#define MAX_BUFSIZE_BYTES (0x10000000) + +typedef struct { + UINT ValidBits; + UINT ReadOffset; + UINT WriteOffset; + UINT BitNdx; + + UCHAR *Buffer; + UINT bufSize; + UINT bufBits; +} FDK_BITBUF; + +typedef FDK_BITBUF *HANDLE_FDK_BITBUF; + +#ifdef __cplusplus +extern "C" { +#endif + +extern const UINT BitMask[32 + 1]; + +/** The BitBuffer Functions are called straight from FDK_bitstream Interface. + For Functions functional survey look there. +*/ + +void FDK_CreateBitBuffer(HANDLE_FDK_BITBUF *hBitBuffer, UCHAR *pBuffer, + UINT bufSize); + +void FDK_InitBitBuffer(HANDLE_FDK_BITBUF hBitBuffer, UCHAR *pBuffer, + UINT bufSize, UINT validBits); + +void FDK_ResetBitBuffer(HANDLE_FDK_BITBUF hBitBuffer); + +void FDK_DeleteBitBuffer(HANDLE_FDK_BITBUF hBitBuffer); + +INT FDK_get(HANDLE_FDK_BITBUF hBitBuffer, const UINT numberOfBits); + +INT FDK_get32(HANDLE_FDK_BITBUF hBitBuf); + +void FDK_put(HANDLE_FDK_BITBUF hBitBuffer, UINT value, const UINT numberOfBits); + +INT FDK_getBwd(HANDLE_FDK_BITBUF hBitBuffer, const UINT numberOfBits); +void FDK_putBwd(HANDLE_FDK_BITBUF hBitBuffer, UINT value, + const UINT numberOfBits); + +void FDK_pushBack(HANDLE_FDK_BITBUF hBitBuffer, const UINT numberOfBits, + UCHAR config); + +void FDK_pushForward(HANDLE_FDK_BITBUF hBitBuffer, const UINT numberOfBits, + UCHAR config); + +UINT FDK_getValidBits(HANDLE_FDK_BITBUF hBitBuffer); + +INT FDK_getFreeBits(HANDLE_FDK_BITBUF hBitBuffer); + +void FDK_Feed(HANDLE_FDK_BITBUF hBitBuffer, const UCHAR inputBuffer[], + const UINT bufferSize, UINT *bytesValid); + +void FDK_Copy(HANDLE_FDK_BITBUF hBitBufDst, HANDLE_FDK_BITBUF hBitBufSrc, + UINT *bytesValid); + +void FDK_Fetch(HANDLE_FDK_BITBUF hBitBuffer, UCHAR outBuf[], UINT *writeBytes); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_bitstream.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_bitstream.h new file mode 100644 index 0000000000000..f799026796c7a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_bitstream.h @@ -0,0 +1,642 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser + + Description: bitstream interface to bitbuffer routines + +*******************************************************************************/ + +#ifndef FDK_BITSTREAM_H +#define FDK_BITSTREAM_H + +#include "FDK_bitbuffer.h" +#include "machine_type.h" + +#include "genericStds.h" + +#define CACHE_BITS 32 + +#define BUFSIZE_DUMMY_VALUE MAX_BUFSIZE_BYTES + +typedef enum { BS_READER, BS_WRITER } FDK_BS_CFG; + +typedef struct { + UINT CacheWord; + UINT BitsInCache; + FDK_BITBUF hBitBuf; + UINT ConfigCache; +} FDK_BITSTREAM; + +typedef FDK_BITSTREAM *HANDLE_FDK_BITSTREAM; + +/** + * \brief CreateBitStream Function. + * + * Create and initialize bitstream with extern allocated buffer. + * + * \param pBuffer Pointer to BitBuffer array. + * \param bufSize Length of BitBuffer array. (awaits size 2^n and <= + * MAX_BUFSIZE_BYTES) + * \param config Initialize BitStream as Reader or Writer. + */ +FDK_INLINE +HANDLE_FDK_BITSTREAM FDKcreateBitStream(UCHAR *pBuffer, UINT bufSize, + FDK_BS_CFG config = BS_READER) { + HANDLE_FDK_BITSTREAM hBitStream = + (HANDLE_FDK_BITSTREAM)FDKcalloc(1, sizeof(FDK_BITSTREAM)); + if (hBitStream == NULL) return NULL; + FDK_InitBitBuffer(&hBitStream->hBitBuf, pBuffer, bufSize, 0); + + /* init cache */ + hBitStream->CacheWord = hBitStream->BitsInCache = 0; + hBitStream->ConfigCache = config; + + return hBitStream; +} + +/** + * \brief Initialize BistreamBuffer. BitBuffer can point to filled BitBuffer + * array . + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param pBuffer Pointer to BitBuffer array. + * \param bufSize Length of BitBuffer array in bytes. (awaits size 2^n and <= + * MAX_BUFSIZE_BYTES) + * \param validBits Number of valid BitBuffer filled Bits. + * \param config Initialize BitStream as Reader or Writer. + * \return void + */ +FDK_INLINE +void FDKinitBitStream(HANDLE_FDK_BITSTREAM hBitStream, UCHAR *pBuffer, + UINT bufSize, UINT validBits, + FDK_BS_CFG config = BS_READER) { + FDK_InitBitBuffer(&hBitStream->hBitBuf, pBuffer, bufSize, validBits); + + /* init cache */ + hBitStream->CacheWord = hBitStream->BitsInCache = 0; + hBitStream->ConfigCache = config; +} + +/** + * \brief ResetBitbuffer Function. Reset states in BitBuffer and Cache. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param config Initialize BitStream as Reader or Writer. + * \return void + */ +FDK_INLINE void FDKresetBitbuffer(HANDLE_FDK_BITSTREAM hBitStream, + FDK_BS_CFG config = BS_READER) { + FDK_ResetBitBuffer(&hBitStream->hBitBuf); + + /* init cache */ + hBitStream->CacheWord = hBitStream->BitsInCache = 0; + hBitStream->ConfigCache = config; +} + +/** DeleteBitStream. + + Deletes the in Create Bitstream allocated BitStream and BitBuffer. +*/ +FDK_INLINE void FDKdeleteBitStream(HANDLE_FDK_BITSTREAM hBitStream) { + FDK_DeleteBitBuffer(&hBitStream->hBitBuf); + FDKfree(hBitStream); +} + +/** + * \brief ReadBits Function (forward). This function returns a number of + * sequential bits from the input bitstream. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param numberOfBits The number of bits to be retrieved. ( (0),1 <= + * numberOfBits <= 32) + * \return the requested bits, right aligned + * \return + */ + +FDK_INLINE UINT FDKreadBits(HANDLE_FDK_BITSTREAM hBitStream, + const UINT numberOfBits) { + UINT bits = 0; + INT missingBits = (INT)numberOfBits - (INT)hBitStream->BitsInCache; + + FDK_ASSERT(numberOfBits <= 32); + if (missingBits > 0) { + if (missingBits != 32) bits = hBitStream->CacheWord << missingBits; + hBitStream->CacheWord = FDK_get32(&hBitStream->hBitBuf); + hBitStream->BitsInCache += CACHE_BITS; + } + + hBitStream->BitsInCache -= numberOfBits; + + return (bits | (hBitStream->CacheWord >> hBitStream->BitsInCache)) & + BitMask[numberOfBits]; +} + +FDK_INLINE UINT FDKreadBit(HANDLE_FDK_BITSTREAM hBitStream) { + if (!hBitStream->BitsInCache) { + hBitStream->CacheWord = FDK_get32(&hBitStream->hBitBuf); + hBitStream->BitsInCache = CACHE_BITS - 1; + return hBitStream->CacheWord >> 31; + } + hBitStream->BitsInCache--; + + return (hBitStream->CacheWord >> hBitStream->BitsInCache) & 1; +} + +/** + * \brief Read2Bits Function (forward). This function reads 2 sequential + * bits from the input bitstream. It is the optimized version + of FDKreadBits() for reading 2 bits. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return the requested bits, right aligned + * \return + */ +FDK_INLINE UINT FDKread2Bits(HANDLE_FDK_BITSTREAM hBitStream) { + /* + ** Version corresponds to optimized FDKreadBits implementation + ** calling FDK_get32, that keeps read pointer aligned. + */ + UINT bits = 0; + INT missingBits = 2 - (INT)hBitStream->BitsInCache; + if (missingBits > 0) { + bits = hBitStream->CacheWord << missingBits; + hBitStream->CacheWord = FDK_get32(&hBitStream->hBitBuf); + hBitStream->BitsInCache += CACHE_BITS; + } + + hBitStream->BitsInCache -= 2; + + return (bits | (hBitStream->CacheWord >> hBitStream->BitsInCache)) & 0x3; +} + +/** + * \brief ReadBits Function (backward). This function returns a number of + * sequential bits from the input bitstream. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param numberOfBits The number of bits to be retrieved. + * \return the requested bits, right aligned + */ +FDK_INLINE UINT FDKreadBitsBwd(HANDLE_FDK_BITSTREAM hBitStream, + const UINT numberOfBits) { + const UINT validMask = BitMask[numberOfBits]; + + if (hBitStream->BitsInCache <= numberOfBits) { + const INT freeBits = (CACHE_BITS - 1) - hBitStream->BitsInCache; + + hBitStream->CacheWord = (hBitStream->CacheWord << freeBits) | + FDK_getBwd(&hBitStream->hBitBuf, freeBits); + hBitStream->BitsInCache += freeBits; + } + + hBitStream->BitsInCache -= numberOfBits; + + return (hBitStream->CacheWord >> hBitStream->BitsInCache) & validMask; +} + +/** + * \brief read an integer value using a varying number of bits from the + * bitstream + * + * q.v. ISO/IEC FDIS 23003-3 Table 16 + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param nBits1 number of bits to read for a small integer value or escape + * value + * \param nBits2 number of bits to read for a medium sized integer value or + * escape value + * \param nBits3 number of bits to read for a large integer value + * \return integer value read from bitstream + */ +FDK_INLINE UINT escapedValue(HANDLE_FDK_BITSTREAM hBitStream, int nBits1, + int nBits2, int nBits3) { + UINT value = FDKreadBits(hBitStream, nBits1); + + if (value == (UINT)(1 << nBits1) - 1) { + UINT valueAdd = FDKreadBits(hBitStream, nBits2); + value += valueAdd; + if (valueAdd == (UINT)(1 << nBits2) - 1) { + value += FDKreadBits(hBitStream, nBits3); + } + } + + return value; +} + +/** + * \brief return a number of bits from the bitBuffer. + * You have to know what you do! Cache has to be synchronized before + * using this function. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param numBits The number of bits to be retrieved. + * \return the requested bits, right aligned + */ +FDK_INLINE UINT FDKgetBits(HANDLE_FDK_BITSTREAM hBitStream, UINT numBits) { + return FDK_get(&hBitStream->hBitBuf, numBits); +} + +/** + * \brief WriteBits Function. This function writes numberOfBits of value into + * bitstream. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param value The data to be written + * \param numberOfBits The number of bits to be written + * \return Number of bits written + */ +FDK_INLINE UCHAR FDKwriteBits(HANDLE_FDK_BITSTREAM hBitStream, UINT value, + const UINT numberOfBits) { + const UINT validMask = BitMask[numberOfBits]; + + if (hBitStream == NULL) { + return numberOfBits; + } + + if ((hBitStream->BitsInCache + numberOfBits) < CACHE_BITS) { + hBitStream->BitsInCache += numberOfBits; + hBitStream->CacheWord = + (hBitStream->CacheWord << numberOfBits) | (value & validMask); + } else { + /* Put always 32 bits into memory */ + /* - fill cache's LSBits with MSBits of value */ + /* - store 32 bits in memory using subroutine */ + /* - fill remaining bits into cache's LSBits */ + /* - upper bits in cache are don't care */ + + /* Compute number of bits to be filled into cache */ + int missing_bits = CACHE_BITS - hBitStream->BitsInCache; + int remaining_bits = numberOfBits - missing_bits; + value = value & validMask; + /* Avoid shift left by 32 positions */ + UINT CacheWord = + (missing_bits == 32) ? 0 : (hBitStream->CacheWord << missing_bits); + CacheWord |= (value >> (remaining_bits)); + FDK_put(&hBitStream->hBitBuf, CacheWord, 32); + + hBitStream->CacheWord = value; + hBitStream->BitsInCache = remaining_bits; + } + + return numberOfBits; +} + +/** + * \brief WriteBits Function (backward). This function writes numberOfBits of + * value into bitstream. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param value Variable holds data to be written. + * \param numberOfBits The number of bits to be written. + * \return number of bits written + */ +FDK_INLINE UCHAR FDKwriteBitsBwd(HANDLE_FDK_BITSTREAM hBitStream, UINT value, + const UINT numberOfBits) { + const UINT validMask = BitMask[numberOfBits]; + + if ((hBitStream->BitsInCache + numberOfBits) <= CACHE_BITS) { + hBitStream->BitsInCache += numberOfBits; + hBitStream->CacheWord = + (hBitStream->CacheWord << numberOfBits) | (value & validMask); + } else { + FDK_putBwd(&hBitStream->hBitBuf, hBitStream->CacheWord, + hBitStream->BitsInCache); + hBitStream->BitsInCache = numberOfBits; + hBitStream->CacheWord = (value & validMask); + } + + return numberOfBits; +} + +/** + * \brief write an integer value using a varying number of bits from the + * bitstream + * + * q.v. ISO/IEC FDIS 23003-3 Table 16 + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param value the data to be written + * \param nBits1 number of bits to write for a small integer value or escape + * value + * \param nBits2 number of bits to write for a medium sized integer value or + * escape value + * \param nBits3 number of bits to write for a large integer value + * \return number of bits written + */ +FDK_INLINE UCHAR FDKwriteEscapedValue(HANDLE_FDK_BITSTREAM hBitStream, + UINT value, UINT nBits1, UINT nBits2, + UINT nBits3) { + UCHAR nbits = 0; + UINT tmp = (1 << nBits1) - 1; + + if (value < tmp) { + nbits += FDKwriteBits(hBitStream, value, nBits1); + } else { + nbits += FDKwriteBits(hBitStream, tmp, nBits1); + value -= tmp; + tmp = (1 << nBits2) - 1; + + if (value < tmp) { + nbits += FDKwriteBits(hBitStream, value, nBits2); + } else { + nbits += FDKwriteBits(hBitStream, tmp, nBits2); + value -= tmp; + + nbits += FDKwriteBits(hBitStream, value, nBits3); + } + } + + return nbits; +} + +/** + * \brief SyncCache Function. Clear cache after read forward. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return void + */ +FDK_INLINE void FDKsyncCache(HANDLE_FDK_BITSTREAM hBitStream) { + if (hBitStream->ConfigCache == BS_READER) + FDK_pushBack(&hBitStream->hBitBuf, hBitStream->BitsInCache, + hBitStream->ConfigCache); + else if (hBitStream->BitsInCache) /* BS_WRITER */ + FDK_put(&hBitStream->hBitBuf, hBitStream->CacheWord, + hBitStream->BitsInCache); + + hBitStream->BitsInCache = 0; + hBitStream->CacheWord = 0; +} + +/** + * \brief SyncCache Function. Clear cache after read backwards. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return void + */ +FDK_INLINE void FDKsyncCacheBwd(HANDLE_FDK_BITSTREAM hBitStream) { + if (hBitStream->ConfigCache == BS_READER) { + FDK_pushForward(&hBitStream->hBitBuf, hBitStream->BitsInCache, + hBitStream->ConfigCache); + } else { /* BS_WRITER */ + FDK_putBwd(&hBitStream->hBitBuf, hBitStream->CacheWord, + hBitStream->BitsInCache); + } + + hBitStream->BitsInCache = 0; + hBitStream->CacheWord = 0; +} + +/** + * \brief Byte Alignment Function with anchor + * This function performs the byte_alignment() syntactic function on the + * input stream, i.e. some bits will be discarded so that the next bits to be + * read/written would be aligned on a byte boundary with respect to the + * given alignment anchor. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param alignmentAnchor bit position to be considered as origin for byte + * alignment + * \return void + */ +FDK_INLINE void FDKbyteAlign(HANDLE_FDK_BITSTREAM hBitStream, + UINT alignmentAnchor) { + FDKsyncCache(hBitStream); + if (hBitStream->ConfigCache == BS_READER) { + FDK_pushForward( + &hBitStream->hBitBuf, + (UINT)((INT)8 - (((INT)alignmentAnchor - + (INT)FDK_getValidBits(&hBitStream->hBitBuf)) & + 0x07)) & + 0x07, + hBitStream->ConfigCache); + } else { + FDK_put(&hBitStream->hBitBuf, 0, + (8 - ((FDK_getValidBits(&hBitStream->hBitBuf) - alignmentAnchor) & + 0x07)) & + 0x07); + } +} + +/** + * \brief Push Back(Cache) / For / BiDirectional Function. + * PushBackCache function ungets a number of bits erroneously + * read/written by the last Get() call. NB: The number of bits to be stuffed + * back into the stream may never exceed the number of bits returned by + * the immediately preceding Get() call. + * + * PushBack function ungets a number of bits (combines cache and bitbuffer + * indices) PushFor function gets a number of bits (combines cache and + * bitbuffer indices) PushBiDirectional gets/ungets number of bits as + * defined in PusBack/For function NB: The sign of bits is not known, so + * the function checks direction and calls appropriate function. (positive + * sign pushFor, negative sign pushBack ) + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param numberOfBits The number of bits to be pushed back/for. + * \return void + */ +FDK_INLINE void FDKpushBackCache(HANDLE_FDK_BITSTREAM hBitStream, + const UINT numberOfBits) { + FDK_ASSERT((hBitStream->BitsInCache + numberOfBits) <= CACHE_BITS); + hBitStream->BitsInCache += numberOfBits; +} + +FDK_INLINE void FDKpushBack(HANDLE_FDK_BITSTREAM hBitStream, + const UINT numberOfBits) { + if ((hBitStream->BitsInCache + numberOfBits) < CACHE_BITS && + (hBitStream->ConfigCache == BS_READER)) { + hBitStream->BitsInCache += numberOfBits; + FDKsyncCache(hBitStream); /* sync cache to avoid invalid cache */ + } else { + FDKsyncCache(hBitStream); + FDK_pushBack(&hBitStream->hBitBuf, numberOfBits, hBitStream->ConfigCache); + } +} + +FDK_INLINE void FDKpushFor(HANDLE_FDK_BITSTREAM hBitStream, + const UINT numberOfBits) { + if ((hBitStream->BitsInCache > numberOfBits) && + (hBitStream->ConfigCache == BS_READER)) { + hBitStream->BitsInCache -= numberOfBits; + } else { + FDKsyncCache(hBitStream); + FDK_pushForward(&hBitStream->hBitBuf, numberOfBits, + hBitStream->ConfigCache); + } +} + +FDK_INLINE void FDKpushBiDirectional(HANDLE_FDK_BITSTREAM hBitStream, + const INT numberOfBits) { + if (numberOfBits >= 0) + FDKpushFor(hBitStream, numberOfBits); + else + FDKpushBack(hBitStream, -numberOfBits); +} + +/** + * \brief GetValidBits Function. Clear cache and return valid Bits from + * Bitbuffer. + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return amount of valid bits that still can be read or were already written. + * + */ +FDK_INLINE UINT FDKgetValidBits(HANDLE_FDK_BITSTREAM hBitStream) { + FDKsyncCache(hBitStream); + return FDK_getValidBits(&hBitStream->hBitBuf); +} + +/** + * \brief return amount of unused Bits from Bitbuffer. + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return amount of free bits that still can be written into the bitstream + */ +FDK_INLINE INT FDKgetFreeBits(HANDLE_FDK_BITSTREAM hBitStream) { + return FDK_getFreeBits(&hBitStream->hBitBuf); +} + +/** + * \brief Fill the BitBuffer with a number of input bytes from external source. + * The bytesValid variable returns the number of ramaining valid bytes in + * extern inputBuffer. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param inputBuffer Pointer to input buffer with bitstream data. + * \param bufferSize Total size of inputBuffer array. + * \param bytesValid Input: number of valid bytes in inputBuffer. Output: bytes + * still left unread in inputBuffer. + * \return void + */ +FDK_INLINE void FDKfeedBuffer(HANDLE_FDK_BITSTREAM hBitStream, + const UCHAR inputBuffer[], const UINT bufferSize, + UINT *bytesValid) { + FDKsyncCache(hBitStream); + FDK_Feed(&hBitStream->hBitBuf, inputBuffer, bufferSize, bytesValid); +} + +/** + * \brief fill destination BitBuffer with a number of bytes from source + * BitBuffer. The bytesValid variable returns the number of ramaining valid + * bytes in source BitBuffer. + * + * \param hBSDst HANDLE_FDK_BITSTREAM handle to write data into + * \param hBSSrc HANDLE_FDK_BITSTREAM handle to read data from + * \param bytesValid Input: number of valid bytes in inputBuffer. Output: + * bytes still left unread in inputBuffer. + * \return void + */ +FDK_INLINE void FDKcopyBuffer(HANDLE_FDK_BITSTREAM hBSDst, + HANDLE_FDK_BITSTREAM hBSSrc, UINT *bytesValid) { + FDKsyncCache(hBSSrc); + FDK_Copy(&hBSDst->hBitBuf, &hBSSrc->hBitBuf, bytesValid); +} + +/** + * \brief fill the outputBuffer with all valid bytes hold in BitBuffer. The + * WriteBytes variable returns the number of written Bytes. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param outputBuffer Pointer to output buffer. + * \param writeBytes Number of bytes write to output buffer. + * \return void + */ +FDK_INLINE void FDKfetchBuffer(HANDLE_FDK_BITSTREAM hBitStream, + UCHAR *outputBuffer, UINT *writeBytes) { + FDKsyncCache(hBitStream); + FDK_Fetch(&hBitStream->hBitBuf, outputBuffer, writeBytes); +} + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_core.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_core.h new file mode 100644 index 0000000000000..9543522b695fb --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_core.h @@ -0,0 +1,122 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander + + Description: FDK tools versioning support + +*******************************************************************************/ + +#ifndef FDK_CORE_H +#define FDK_CORE_H + +#include "FDK_audio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Get FDK_tools library information. + * @return Return 0 on success and a negative errorcode on failure (see + * errorcodes.h). + */ +int FDK_toolsGetLibInfo(LIB_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_crc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_crc.h new file mode 100644 index 0000000000000..6c7040c36d587 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_crc.h @@ -0,0 +1,225 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: CRC calculation + +*******************************************************************************/ + +#ifndef FDK_CRC_H +#define FDK_CRC_H + +#include "FDK_bitstream.h" + +#define MAX_CRC_REGS \ + 3 /*!< Maximal number of overlapping crc region in ADTS channel pair element \ + is two. Select three independent regions preventively. */ + +/** + * This structure describes single crc region used for crc calculation. + */ +typedef struct { + UCHAR isActive; + INT maxBits; + INT bitBufCntBits; + INT validBits; + +} CCrcRegData; + +/** + * CRC info structure. + */ +typedef struct { + CCrcRegData crcRegData[MAX_CRC_REGS]; /*!< Multiple crc region description. */ + const USHORT* + pCrcLookup; /*!< Pointer to lookup table filled in FDK_crcInit(). */ + + USHORT crcPoly; /*!< CRC generator polynom. */ + USHORT crcMask; /*!< CRC mask. */ + USHORT startValue; /*!< CRC start value. */ + UCHAR crcLen; /*!< CRC length. */ + + UINT regStart; /*!< Start region marker for synchronization. */ + UINT regStop; /*!< Stop region marker for synchronization. */ + + USHORT crcValue; /*!< Crc value to be calculated. */ + +} FDK_CRCINFO; + +/** + * CRC info handle. + */ +typedef FDK_CRCINFO* HANDLE_FDK_CRCINFO; + +/** + * \brief Initialize CRC structure. + * + * The function initializes existing crc info structure with denoted + * configuration. + * + * \param hCrcInfo Pointer to an outlying allocated crc info + * structure. + * \param crcPoly Configure crc polynom. + * \param crcStartValue Configure crc start value. + * \param crcLen Configure crc length. + * + * \return none + */ +void FDKcrcInit(HANDLE_FDK_CRCINFO hCrcInfo, const UINT crcPoly, + const UINT crcStartValue, const UINT crcLen); + +/** + * \brief Reset CRC info structure. + * + * This function clears all intern states of the crc structure. + * + * \param hCrcInfo Pointer to crc info stucture. + * + * \return none + */ +void FDKcrcReset(HANDLE_FDK_CRCINFO hCrcInfo); + +/** + * \brief Start CRC region with maximum number of bits. + * + * This function marks position in bitstream to be used as start point for crc + * calculation. Bitstream range for crc calculation can be limited or kept + * dynamic depending on mBits parameter. The crc region has to be terminated + * with FDKcrcEndReg() in each case. + * + * \param hCrcInfo Pointer to crc info stucture. + * \param hBs Pointer to current bit buffer structure. + * \param mBits Number of bits in crc region to be calculated. + * - mBits > 0: Zero padding will be used for CRC + * calculation, if there are less than mBits bits available. + * - mBits < 0: No zero padding is done. + * - mBits = 0: The number of bits used in crc + * calculation is dynamically, depending on bitstream position between + * FDKcrcStartReg() and FDKcrcEndReg() + * call. + * + * \return ID for the created region, -1 in case of an error + */ +INT FDKcrcStartReg(HANDLE_FDK_CRCINFO hCrcInfo, const HANDLE_FDK_BITSTREAM hBs, + const INT mBits); + +/** + * \brief Ends CRC region. + * + * This function terminates crc region specified with FDKcrcStartReg(). The + * number of bits in crc region depends on mBits parameter of FDKcrcStartReg(). + * This function calculates and updates crc in info structure. + * + * \param hCrcInfo Pointer to crc info stucture. + * \param hBs Pointer to current bit buffer structure. + * \param reg Crc region ID created in FDKcrcStartReg(). + * + * \return 0 on success + */ +INT FDKcrcEndReg(HANDLE_FDK_CRCINFO hCrcInfo, const HANDLE_FDK_BITSTREAM hBs, + const INT reg); + +/** + * \brief This function returns crc value from info struct. + * + * \param hCrcInfo Pointer to crc info stucture. + * + * \return CRC value masked with crc length. + */ +USHORT FDKcrcGetCRC(const HANDLE_FDK_CRCINFO hCrcInfo); + +#endif /* FDK_CRC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_decorrelate.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_decorrelate.h new file mode 100644 index 0000000000000..733aaae628372 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_decorrelate.h @@ -0,0 +1,314 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Markus Lohwasser + + Description: FDK Tools Decorrelator + +*******************************************************************************/ + +#ifndef FDK_DECORRELATE_H +#define FDK_DECORRELATE_H + +#include "common_fix.h" + +#define FIXP_MPS FIXP_DBL + +#ifndef ARCH_PREFER_MULT_32x32 +#define FIXP_DECORR FIXP_SGL +#define FX_DECORR2FX_DBL FX_SGL2FX_DBL +#define FX_DECORR2FX_SGL +#define FX_DBL2FX_DECORR FX_DBL2FX_SGL +#define FX_SGL2FX_DECORR +#define DECORR(a) (FX_DBL2FXCONST_SGL(a)) +#define FL2FXCONST_DECORR FL2FXCONST_SGL +#else +#define FIXP_DECORR FIXP_DBL +#define FX_DECORR2FX_DBL +#define FX_DECORR2FX_SGL FX_DBL2FX_SGL +#define FX_DBL2FX_DECORR +#define FX_SGL2FX_DECORR FX_SGL2FX_DBL +#define DECORR(a) FIXP_DBL(a) +#define FL2FXCONST_DECORR FL2FXCONST_DBL +#endif + +/*--------------- enums -------------------------------*/ + +/** + * Decorrelator types. + */ +typedef enum { + DECORR_MPS, /**< Decorrelator type used by MPS LP/HQ */ + DECORR_PS, /**< Decorrelator type used by HEAACv2 and MPS LP */ + DECORR_USAC, /**< Decorrelator type used by USAC */ + DECORR_LD /**< Decorrelator type used by MPS Low Delay */ +} FDK_DECORR_TYPE; + +/** + * Ducker types. + */ +typedef enum { + DUCKER_AUTOMATIC, /**< FDKdecorrelateInit() chooses correct ducker type + depending on provided parameters. */ + DUCKER_MPS, /**< Force ducker type to MPS. */ + DUCKER_PS /**< Force ducker type to PS. */ +} FDK_DUCKER_TYPE; + +/** + * Reverb band types. + */ +typedef enum { + NOT_EXIST, /**< Mark reverb band as non-existing (number of bands = 0). */ + DELAY, /**< Reverb bands just contains delay elements and no allpass filters. + */ + COMMON_REAL, /**< Real filter coeffs, common filter coeffs within one reverb + band */ + COMMON_CPLX, /**< Complex filter coeffs, common filter coeffs within one + reverb band */ + INDEP_CPLX, /**< Complex filter coeffs, independent filter coeffs for each + hybrid band */ + INDEP_CPLX_PS /**< PS optimized implementation of general INDEP_CPLX type */ +} REVBAND_FILT_TYPE; + +typedef struct DECORR_DEC *HANDLE_DECORR_DEC; + +typedef struct DUCKER_INSTANCE { + int hybridBands; + int parameterBands; + int partiallyComplex; + FDK_DUCKER_TYPE duckerType; + + const UCHAR *qs_next; + const UCHAR *mapProcBands2HybBands; + const UCHAR *mapHybBands2ProcBands; + /* interleaved SmoothDirectNrg[] and SmoothReverbNrg[], + non-interleaved SmoothDirectNrg[] in case of parametric stereo */ + FIXP_MPS SmoothDirRevNrg[2 * (28)]; + + /* + parametric stereo + */ + FIXP_MPS peakDecay[(28)]; + FIXP_MPS peakDiff[(28)]; + FIXP_DBL maxValDirectData; + FIXP_DBL maxValReverbData; + SCHAR scaleDirectNrg; + SCHAR scaleReverbNrg; + SCHAR scaleSmoothDirRevNrg; + SCHAR headroomSmoothDirRevNrg; + +} DUCKER_INSTANCE; + +typedef struct DECORR_FILTER_INSTANCE { + FIXP_MPS *stateCplx; + FIXP_DBL *DelayBufferCplx; + + const FIXP_DECORR *numeratorReal; + const FIXP_STP *coeffsPacked; + const FIXP_DECORR *denominatorReal; +} DECORR_FILTER_INSTANCE; + +typedef struct DECORR_DEC { + INT L_stateBufferCplx; + FIXP_DBL *stateBufferCplx; + INT L_delayBufferCplx; + FIXP_DBL *delayBufferCplx; + + const REVBAND_FILT_TYPE *REV_filtType; + const UCHAR *REV_bandOffset; + const UCHAR *REV_delay; + const SCHAR *REV_filterOrder; + INT reverbBandDelayBufferIndex[(4)]; + UCHAR stateBufferOffset[(3)]; + + DECORR_FILTER_INSTANCE Filter[(71)]; + DUCKER_INSTANCE ducker; + + int numbins; + int partiallyComplex; +} DECORR_DEC; + +/** + * \brief Create one instance of Decorrelator. + * + * \param hDecorrDec A pointer to a decorrelator instance which was + * allocated externally. + * \param bufferCplx Externally allocated buffer (allocate (2*( ( 825 ) + * + ( 373 ) )) FIXP_DBL values). + * \param bufLen Length of bufferCplx. Must be >= (2*( ( 825 ) + ( + * 373 ) )). + * + * \return 0 on success. + */ +INT FDKdecorrelateOpen(HANDLE_DECORR_DEC hDecorrDec, FIXP_DBL *bufferCplx, + const INT bufLen); + +/** + * \brief Initialize and configure Decorrelator instance. + * + * \param hDecorrDec A Decorrelator handle. + * \param nrHybBands Number of (hybrid) bands. + * \param decorrType Decorrelator type to use. + * \param duckerType Ducker type to use (in general use + * DUCKER_AUTOMATIC). + * \param decorrConfig Depending on decorrType values of 0,1,2 are + * allowed. + * \param seed Seed of decorrelator instance. Allowed maximum + * valued depends on decorrType. + * \param partiallyComplex Low power or high quality processing 0: HQ, 1: LQ + * (only allowed for DECORR_MPS | DECORR_PS). + * \param useFractDelay Indicate usage of fractional delay 0: off, 1: on + * (currently not supported). + * \param isLegacyPS Indicate if DECORR_PS is used for HEAACv2 (for all + * other cases: isLegacyPS = 0). The purpose of this parameter is to select the + * correct number of param bands for the ducker. + * \param initStatesFlag Indicates whether the states buffer has to be + * cleared. + * + * \return 0 on success. + */ +INT FDKdecorrelateInit(HANDLE_DECORR_DEC hDecorrDec, const INT nrHybBands, + const FDK_DECORR_TYPE decorrType, + const FDK_DUCKER_TYPE duckerType, const INT decorrConfig, + const INT seed, const INT partiallyComplex, + const INT useFractDelay, const INT isLegacyPS, + const INT initStatesFlag); + +/** + * \brief Apply Decorrelator on input data. + * + * Function applies decorrelator and ducker inplace on hybrid input data. + * Modified hybrid data will be returned inplace. + * + * \param hDecorrDec A decorrelator handle. + * \param dataRealIn In (hybrid) data. + * \param dataImagIn In (hybrid) data. + * \param dataRealOut Out (hybrid) data (can be same as dataRealIn for + * in-place calculation). + * \param dataImagOut Out (hybrid) data (can be same as dataImagIn for + * in-place calculation). + * \param startHybBand Hybrid band to start with decorrelation. + * + * \return 0 on success. + */ +INT FDKdecorrelateApply(HANDLE_DECORR_DEC hDecorrDec, FIXP_DBL *dataRealIn, + FIXP_DBL *dataImagIn, FIXP_DBL *dataRealOut, + FIXP_DBL *dataImagOut, const INT startHybBand); + +/** + * \brief Destroy a Decorrelator instance. + * + * Deallocate whole memory of decorraltor and inside ducker. + * + * \param hDecorrDec Pointer to a decoderrolator handle. Null initialized on + * return. + * + * \return 0 on success. + */ +INT FDKdecorrelateClose(HANDLE_DECORR_DEC hDecorrDec); + +/** + * \brief Get max value address of direct signal. + * + * Get max value address of direct signal needed for ducker energy calculation. + * + * \param hDecorrDec Pointer to a decoderrolator handle. + * + * \return address of max value + */ +FIXP_DBL *getAddrDirectSignalMaxVal(HANDLE_DECORR_DEC hDecorrDec); + +#endif /* FDK_DECORRELATE_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_hybrid.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_hybrid.h new file mode 100644 index 0000000000000..583f299471d18 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_hybrid.h @@ -0,0 +1,255 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Markus Lohwasser + + Description: FDK Tools Hybrid Filterbank + +*******************************************************************************/ + +#ifndef FDK_HYBRID_H +#define FDK_HYBRID_H + +#include "common_fix.h" + +/*--------------- enums -------------------------------*/ + +/** + * Hybrid Filterband modes. + */ +typedef enum { + THREE_TO_TEN, + THREE_TO_TWELVE, + THREE_TO_SIXTEEN + +} FDK_HYBRID_MODE; + +/*--------------- structure definitions ---------------*/ +typedef const struct FDK_HYBRID_SETUP *HANDLE_FDK_HYBRID_SETUP; + +typedef struct { + FIXP_DBL *bufferLFReal[3]; /*!< LF real filter states. */ + FIXP_DBL *bufferLFImag[3]; /*!< LF imag filter states. */ + FIXP_DBL *bufferHFReal[13]; /*!< HF real delay lines. */ + FIXP_DBL *bufferHFImag[13]; /*!< HF imag delay lines. */ + + INT bufferLFpos; /*!< Position to write incoming data into ringbuffer. */ + INT bufferHFpos; /*!< Delay line positioning. */ + INT nrBands; /*!< Number of QMF bands. */ + INT cplxBands; /*!< Number of complex QMF bands.*/ + UCHAR hfMode; /*!< Flag signalizes treatment of HF bands. */ + + FIXP_DBL *pLFmemory; /*!< Pointer to LF states buffer. */ + FIXP_DBL *pHFmemory; /*!< Pointer to HF states buffer. */ + + UINT LFmemorySize; /*!< Size of LF states buffer. */ + UINT HFmemorySize; /*!< Size of HF states buffer. */ + + HANDLE_FDK_HYBRID_SETUP pSetup; /*!< Pointer to filter setup. */ + +} FDK_ANA_HYB_FILTER; + +typedef struct { + INT nrBands; /*!< Number of QMF bands. */ + INT cplxBands; /*!< Number of complex QMF bands.*/ + + HANDLE_FDK_HYBRID_SETUP pSetup; /*!< Pointer to filter setup. */ + +} FDK_SYN_HYB_FILTER; + +typedef FDK_ANA_HYB_FILTER *HANDLE_FDK_ANA_HYB_FILTER; +typedef FDK_SYN_HYB_FILTER *HANDLE_FDK_SYN_HYB_FILTER; + +/** + * \brief Create one instance of Hybrid Analyis Filterbank. + * + * \param hAnalysisHybFilter Pointer to an outlying allocated Hybrid Analysis + * Filterbank structure. + * \param pLFmemory Pointer to outlying buffer used LF filtering. + * \param LFmemorySize Size of pLFmemory in bytes. + * \param pHFmemory Pointer to outlying buffer used HF delay line. + * \param HFmemorySize Size of pLFmemory in bytes. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisOpen(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + FIXP_DBL *const pLFmemory, const UINT LFmemorySize, + FIXP_DBL *const pHFmemory, const UINT HFmemorySize); + +/** + * \brief Initialize and configure Hybrid Analysis Filterbank instance. + * + * \param hAnalysisHybFilter A Hybrid Analysis Filterbank handle. + * \param mode Select hybrid filter configuration. + * \param qmfBands Number of qmf bands to be processed. + * \param cplxBands Number of complex qmf bands to be processed. + * \param initStatesFlag Indicates whether the states buffer has to be + * cleared. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisInit(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FDK_HYBRID_MODE mode, const INT qmfBands, + const INT cplxBands, const INT initStatesFlag); + +/** + * \brief Adjust Hybrid Analysis Filterbank states. + * + * \param hAnalysisHybFilter A Hybrid Analysis Filterbank handle. + * \param scalingValue Scaling value to be applied on filter states. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisScaleStates(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const INT scalingValue); + +/** + * \brief Apply Hybrid Analysis Filterbank on Qmf input data. + * + * \param hAnalysisHybFilter A Hybrid Analysis Filterbank handle. + * \param pQmfReal Qmf input data. + * \param pQmfImag Qmf input data. + * \param pHybridReal Hybrid output data. + * \param pHybridImag Hybrid output data. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisApply(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + FIXP_DBL *const pHybridReal, + FIXP_DBL *const pHybridImag); + +/** + * \brief Close a Hybrid Analysis Filterbank instance. + * + * \param hAnalysisHybFilter Pointer to a Hybrid Analysis Filterbank instance. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisClose(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter); + +/** + * \brief Initialize and configure Hybrdid Synthesis Filterbank instance. + * + * \param hSynthesisHybFilter A Hybrid Synthesis Filterbank handle. + * \param mode Select hybrid filter configuration. + * \param qmfBands Number of qmf bands to be processed. + * \param cplxBands Number of complex qmf bands to be processed. + * + * \return 0 on success. + */ +INT FDKhybridSynthesisInit(HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FDK_HYBRID_MODE mode, const INT qmfBands, + const INT cplxBands); + +/** + * \brief Apply Hybrid Analysis Filterbank on Hybrid data. + * + * \param hSynthesisHybFilter A Hybrid Analysis Filterbandk handle. + * \param pHybridReal Hybrid input data. + * \param pHybridImag Hybrid input data. + * \param pQmfReal Qmf output data. + * \param pQmfImag Qmf output data. + * + */ +void FDKhybridSynthesisApply(HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FIXP_DBL *const pHybridReal, + const FIXP_DBL *const pHybridImag, + FIXP_DBL *const pQmfReal, + FIXP_DBL *const pQmfImag); + +#endif /* FDK_HYBRID_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_lpc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_lpc.h new file mode 100644 index 0000000000000..851dd1f35bac7 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_lpc.h @@ -0,0 +1,218 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander + + Description: LPC related functions + +*******************************************************************************/ + +#ifndef FDK_LPC_H +#define FDK_LPC_H + +#include "common_fix.h" + +#define LPC_MAX_ORDER 24 + +/* + * Experimental solution for lattice filter substitution. + * LPC_SYNTHESIS_IIR macro must be activated in aacdec_tns.cpp. + * When LPC_SYNTHESIS_IIR enabled, there will be a substitution of the default + * lpc synthesis lattice filter by an IIR synthesis filter (with a conversionof + * the filter coefs). LPC_TNS related macros are intended to implement the data + * types used by the CLpc_Synthesis variant which is used for this solution. + * */ + +/* #define LPC_TNS_LOWER_PRECISION */ + +typedef FIXP_DBL FIXP_LPC_TNS; +#define FX_DBL2FX_LPC_TNS(x) (x) +#define FX_DBL2FXCONST_LPC_TNS(x) (x) +#define FX_LPC_TNS2FX_DBL(x) (x) +#define FL2FXCONST_LPC_TNS(val) FL2FXCONST_DBL(val) +#define MAXVAL_LPC_TNS MAXVAL_DBL + +typedef FIXP_SGL FIXP_LPC; +#define FX_DBL2FX_LPC(x) FX_DBL2FX_SGL((FIXP_DBL)(x)) +#define FX_DBL2FXCONST_LPC(x) FX_DBL2FXCONST_SGL(x) +#define FX_LPC2FX_DBL(x) FX_SGL2FX_DBL(x) +#define FL2FXCONST_LPC(val) FL2FXCONST_SGL(val) +#define MAXVAL_LPC MAXVAL_SGL + +/** + * \brief Obtain residual signal through LPC analysis. + * \param signal pointer to buffer holding signal to be analysed. Residual is + * returned there (in place) + * \param signal_size the size of the input data in pData + * \param lpcCoeff_m the LPC filter coefficient mantissas + * \param lpcCoeff_e the LPC filter coefficient exponent + * \param order the LPC filter order (size of coeff) + * \param filtState Pointer to state buffer of size order + * \param filtStateIndex pointer to state index storage + */ +void CLpc_Analysis(FIXP_DBL signal[], const int signal_size, + const FIXP_LPC lpcCoeff_m[], const int lpcCoeff_e, + const int order, FIXP_DBL *filtState, int *filtStateIndex); + +/** + * \brief Synthesize signal fom residual through LPC synthesis, using LP + * coefficients. + * \param signal pointer to buffer holding the residual signal. The synthesis is + * returned there (in place) + * \param signal_size the size of the input data in pData + * \param inc buffer traversal increment for signal + * \param coeff the LPC filter coefficients + * \param coeff_e exponent of coeff + * \param order the LPC filter order (size of coeff) + * \param state state buffer of size LPC_MAX_ORDER + * \param pStateIndex pointer to state index storage + */ +void CLpc_Synthesis(FIXP_DBL *signal, const int signal_size, const int signal_e, + const int inc, const FIXP_LPC_TNS *lpcCoeff_m, + const int lpcCoeff_e, const int order, FIXP_DBL *state, + int *pStateIndex); +void CLpc_Synthesis(FIXP_DBL *signal, const int signal_size, const int signal_e, + const int inc, const FIXP_LPC coeff[], const int coeff_e, + const int order, FIXP_DBL *filtState, int *pStateIndex); + +/** + * \brief Synthesize signal fom residual through LPC synthesis, using ParCor + * coefficients. The algorithm assumes a filter gain of max 1.0. If the filter + * gain is higher, this must be accounted into the values of signal_e + * and/or signal_e_out to avoid overflows. + * \param signal pointer to buffer holding the residual signal. The synthesis is + * returned there (in place) + * \param signal_size the size of the input data in pData + * \param inc buffer traversal increment for signal + * \param coeff the LPC filter coefficients + * \param coeff_e exponent of coeff + * \param order the LPC filter order (size of coeff) + * \param state state buffer of size LPC_MAX_ORDER + */ +void CLpc_SynthesisLattice(FIXP_DBL *signal, const int signal_size, + const int signal_e, const int signal_e_out, + const int inc, const FIXP_SGL *coeff, + const int order, FIXP_DBL *state); + +void CLpc_SynthesisLattice(FIXP_DBL *RESTRICT signal, const int signal_size, + const int signal_e, const int signal_e_out, + const int inc, const FIXP_DBL *RESTRICT coeff, + const int order, FIXP_DBL *RESTRICT state); + +/** + * \brief + */ +INT CLpc_ParcorToLpc(const FIXP_LPC_TNS reflCoeff[], FIXP_LPC_TNS LpcCoeff[], + INT numOfCoeff, FIXP_DBL workBuffer[]); +INT CLpc_ParcorToLpc(const FIXP_LPC reflCoeff[], FIXP_LPC LpcCoeff[], + const int numOfCoeff, FIXP_DBL workBuffer[]); + +/** + * \brief Calculate ParCor (Partial autoCorrelation, reflection) coefficients + * from autocorrelation coefficients using the Schur algorithm (instead of + * Levinson Durbin). + * \param acorr order+1 autocorrelation coefficients + * \param reflCoeff output reflection /ParCor coefficients. The first + * coefficient which is always 1.0 is ommitted. + * \param order number of acorr / reflCoeff coefficients. + * \param pPredictionGain_m prediction gain mantissa + * \param pPredictionGain_e prediction gain exponent + */ +void CLpc_AutoToParcor(FIXP_DBL acorr[], const int acorr_e, + FIXP_LPC reflCoeff[], const int order, + FIXP_DBL *pPredictionGain_m, INT *pPredictionGain_e); + +#endif /* FDK_LPC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_matrixCalloc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_matrixCalloc.h new file mode 100644 index 0000000000000..ffb54fe3d6fda --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_matrixCalloc.h @@ -0,0 +1,230 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: matrix memory allocation + +*******************************************************************************/ + +#ifndef FDK_MATRIXCALLOC_H +#define FDK_MATRIXCALLOC_H + +#include "machine_type.h" +#include "genericStds.h" + +/* It is recommended to use FDK_ALLOCATE_MEMORY_1D instead of fdkCallocMatrix1D + */ +void* fdkCallocMatrix1D(UINT dim1, UINT size); +void* fdkCallocMatrix1D_aligned(UINT dim1, UINT size); +/* It is recommended to use FDK_ALLOCATE_MEMORY_1D_INT instead of + * fdkCallocMatrix1D_int */ +void* fdkCallocMatrix1D_int(UINT dim1, UINT size, MEMORY_SECTION s); +void* fdkCallocMatrix1D_int_aligned(UINT dim1, UINT size, MEMORY_SECTION s); +/* It is recommended to use FDK_FREE_MEMORY_1D instead of fdkFreeMatrix1D */ +void fdkFreeMatrix1D(void* p); +void fdkFreeMatrix1D_aligned(void* p); + +/* It is recommended to use FDK_ALLOCATE_MEMORY_2D instead of fdkCallocMatrix2D + */ +void** fdkCallocMatrix2D(UINT dim1, UINT dim2, UINT size); +void** fdkCallocMatrix2D_aligned(UINT dim1, UINT dim2, UINT size); +/* It is recommended to use FDK_ALLOCATE_MEMORY_2D_INT instead of + * fdkCallocMatrix2D_int */ +void** fdkCallocMatrix2D_int(UINT dim1, UINT dim2, UINT size, MEMORY_SECTION s); +/* It is recommended to use FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED instead of + * fdkCallocMatrix2D_int_aligned */ +void** fdkCallocMatrix2D_int_aligned(UINT dim1, UINT dim2, UINT size, + MEMORY_SECTION s); +/* It is recommended to use FDK_FREE_MEMORY_2D instead of fdkFreeMatrix2D */ +void fdkFreeMatrix2D(void** p); +/* It is recommended to use FDK_FREE_MEMORY_2D_ALIGNED instead of + * fdkFreeMatrix2D_aligned */ +void fdkFreeMatrix2D_aligned(void** p); + +/* It is recommended to use FDK_ALLOCATE_MEMORY_3D instead of fdkCallocMatrix3D + */ +void*** fdkCallocMatrix3D(UINT dim1, UINT dim2, UINT dim3, UINT size); +/* It is recommended to use FDK_ALLOCATE_MEMORY_3D_INT instead of + * fdkCallocMatrix3D_int */ +void*** fdkCallocMatrix3D_int(UINT dim1, UINT dim2, UINT dim3, UINT size, + MEMORY_SECTION s); +/* It is recommended to use FDK_FREE_MEMORY_3D instead of fdkFreeMatrix3D */ +void fdkFreeMatrix3D(void*** p); + +#define FDK_ALLOCATE_MEMORY_1D(a, dim1, type) \ + if (((a) = (type*)fdkCallocMatrix1D((dim1), sizeof(type))) == NULL) { \ + goto bail; \ + } + +#define FDK_ALLOCATE_MEMORY_1D_ALIGNED(a, dim1, type) \ + if (((a) = (type*)fdkCallocMatrix1D_aligned((dim1), sizeof(type))) == \ + NULL) { \ + goto bail; \ + } + +#define FDK_ALLOCATE_MEMORY_1D_P(a, dim1, type, ptype) \ + if (((a) = (ptype)fdkCallocMatrix1D((dim1), sizeof(type))) == NULL) { \ + goto bail; \ + } + +#define FDK_ALLOCATE_MEMORY_1D_INT(a, dim1, type, s) \ + if (((a) = (type*)fdkCallocMatrix1D_int((dim1), sizeof(type), (s))) == \ + NULL) { \ + goto bail; \ + } + +#define FDK_FREE_MEMORY_1D(a) \ + do { \ + fdkFreeMatrix1D((void*)(a)); \ + (a) = NULL; \ + } while (0) + +#define FDK_FREE_MEMORY_1D_ALIGNED(a) \ + do { \ + fdkFreeMatrix1D_aligned((void*)(a)); \ + (a) = NULL; \ + } while (0) + +#define FDK_ALLOCATE_MEMORY_2D(a, dim1, dim2, type) \ + if (((a) = (type**)fdkCallocMatrix2D((dim1), (dim2), sizeof(type))) == \ + NULL) { \ + goto bail; \ + } + +#define FDK_ALLOCATE_MEMORY_2D_INT(a, dim1, dim2, type, s) \ + if (((a) = (type**)fdkCallocMatrix2D_int((dim1), (dim2), sizeof(type), \ + (s))) == NULL) { \ + goto bail; \ + } + +#define FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(a, dim1, dim2, type, s) \ + if (((a) = (type**)fdkCallocMatrix2D_int_aligned( \ + (dim1), (dim2), sizeof(type), (s))) == NULL) { \ + goto bail; \ + } + +#define FDK_FREE_MEMORY_2D(a) \ + do { \ + fdkFreeMatrix2D((void**)(a)); \ + (a) = NULL; \ + } while (0) + +#define FDK_FREE_MEMORY_2D_ALIGNED(a) \ + do { \ + fdkFreeMatrix2D_aligned((void**)(a)); \ + (a) = NULL; \ + } while (0) + +#define FDK_ALLOCATE_MEMORY_3D(a, dim1, dim2, dim3, type) \ + if (((a) = (type***)fdkCallocMatrix3D((dim1), (dim2), (dim3), \ + sizeof(type))) == NULL) { \ + goto bail; \ + } + +#define FDK_ALLOCATE_MEMORY_3D_INT(a, dim1, dim2, dim3, type, s) \ + if (((a) = (type***)fdkCallocMatrix3D_int((dim1), (dim2), (dim3), \ + sizeof(type), (s))) == NULL) { \ + goto bail; \ + } + +#define FDK_FREE_MEMORY_3D(a) \ + do { \ + fdkFreeMatrix3D((void***)(a)); \ + (a) = NULL; \ + } while (0) + +#endif /* FDK_MATRIXCALLOC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_qmf_domain.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_qmf_domain.h new file mode 100644 index 0000000000000..0e83da3a5998f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_qmf_domain.h @@ -0,0 +1,410 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Matthias Hildenbrand + + Description: Module to efficiently handle QMF data for multiple channels and + to share the data between e.g. SBR and MPS + +*******************************************************************************/ + +#ifndef FDK_QMF_DOMAIN_H +#define FDK_QMF_DOMAIN_H + +#include "qmf.h" + +typedef enum { + QMF_DOMAIN_OK = 0x0, /*!< No error occurred. */ + QMF_DOMAIN_OUT_OF_MEMORY = + 0x1, /*!< QMF-Configuration demands for more memory than allocated on + heap. */ + QMF_DOMAIN_INIT_ERROR = + 0x2, /*!< An error during filterbank-setup occurred. */ + QMF_DOMAIN_RESAMPLER_INIT_ERROR = + 0x3 /*!< An error during QMF-resampler-setup occurred. */ +} QMF_DOMAIN_ERROR; + +#define CMPLX_MOD (2) + +#define QMF_MAX_WB_SECTIONS (5) /* maximum number of workbuffer sections */ +#define QMF_WB_SECTION_SIZE (1024 * 2) + +H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore1, FIXP_DBL) +H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore3, FIXP_DBL) +H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore4, FIXP_DBL) +H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore6, FIXP_DBL) +H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore7, FIXP_DBL) + +#define QMF_DOMAIN_MAX_ANALYSIS_QMF_BANDS (64) +#define QMF_DOMAIN_MAX_SYNTHESIS_QMF_BANDS (QMF_MAX_SYNTHESIS_BANDS) +#define QMF_DOMAIN_MAX_QMF_PROC_BANDS (64) +#define QMF_DOMAIN_MAX_TIMESLOTS (64) +#define QMF_DOMAIN_MAX_OV_TIMESLOTS (12) + +#define QMF_DOMAIN_ANALYSIS_QMF_BANDS_16 (16) +#define QMF_DOMAIN_ANALYSIS_QMF_BANDS_24 (24) +#define QMF_DOMAIN_ANALYSIS_QMF_BANDS_32 (32) + +#define QMF_DOMAIN_TIMESLOTS_16 (16) +#define QMF_DOMAIN_TIMESLOTS_32 (32) + +#define QMF_DOMAIN_OV_TIMESLOTS_16 (3) +#define QMF_DOMAIN_OV_TIMESLOTS_32 (6) + +H_ALLOC_MEM(AnaQmfStates, FIXP_DBL) +H_ALLOC_MEM(SynQmfStates, FIXP_QSS) +H_ALLOC_MEM(QmfSlotsReal, FIXP_DBL *) +H_ALLOC_MEM(QmfSlotsImag, FIXP_DBL *) +H_ALLOC_MEM(QmfOverlapBuffer, FIXP_DBL) + +H_ALLOC_MEM(AnaQmfStates16, FIXP_DBL) +H_ALLOC_MEM(AnaQmfStates24, FIXP_DBL) +H_ALLOC_MEM(AnaQmfStates32, FIXP_DBL) +H_ALLOC_MEM(QmfSlotsReal16, FIXP_DBL *) +H_ALLOC_MEM(QmfSlotsReal32, FIXP_DBL *) +H_ALLOC_MEM(QmfSlotsImag16, FIXP_DBL *) +H_ALLOC_MEM(QmfSlotsImag32, FIXP_DBL *) +H_ALLOC_MEM(QmfOverlapBuffer16, FIXP_DBL) +H_ALLOC_MEM(QmfOverlapBuffer32, FIXP_DBL) + +/** + * Structure to hold the configuration data which is global whithin a QMF domain + * instance. + */ +typedef struct { + UCHAR qmfDomainExplicitConfig; /*!< Flag to signal that QMF domain is set + explicitly instead of SBR and MPS init + routines. */ + UCHAR nInputChannels; /*!< Number of QMF input channels. */ + UCHAR nInputChannels_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR nOutputChannels; /*!< Number of QMF output channels. */ + UCHAR nOutputChannels_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR + parkChannel; /*!< signal to automatically allocate additional memory to + park a channel if only one processing channel is + available. */ + UCHAR parkChannel_requested; + FIXP_DBL * + pWorkBuffer[QMF_MAX_WB_SECTIONS]; /*!< Pointerarray to volatile memory. */ + UINT flags; /*!< Flags to be set on all QMF analysis/synthesis filter + instances. */ + UINT flags_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR nBandsAnalysis; /*!< Number of QMF analysis bands for all input + channels. */ + UCHAR nBandsAnalysis_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + USHORT nBandsSynthesis; /*!< Number of QMF synthesis bands for all output + channels. */ + USHORT + nBandsSynthesis_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR nQmfTimeSlots; /*!< Number of QMF time slots (stored in work buffer + memory). */ + UCHAR nQmfTimeSlots_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR + nQmfOvTimeSlots; /*!< Number of QMF overlap/delay time slots (stored in + persistent memory). */ + UCHAR nQmfOvTimeSlots_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR nQmfProcBands; /*!< Number of QMF bands which are processed by the + decoder. Typically this is equal to nBandsSynthesis + but it may differ if the QMF based resampler is being + used. */ + UCHAR nQmfProcBands_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR + nQmfProcChannels; /*!< Number of complete QMF channels which need to + coexist in memory at the same time. For most cases + this is 1 which means the work buffer can be shared + between audio channels. */ + UCHAR + nQmfProcChannels_requested; /*!< Corresponding requested not yet active + configuration parameter. */ +} FDK_QMF_DOMAIN_GC; +typedef FDK_QMF_DOMAIN_GC *HANDLE_FDK_QMF_DOMAIN_GC; + +/** + * Structure representing one QMF input channel. This includes the QMF analysis + * and the QMF domain data representation needed by the codec. Work buffer data + * may be shared between channels if the codec processes all QMF channels in a + * consecutive order. + */ +typedef struct { + HANDLE_FDK_QMF_DOMAIN_GC + pGlobalConf; /*!< Pointer to global configuration structure. */ + QMF_FILTER_BANK fb; /*!< QMF (analysis) filter bank structure. */ + QMF_SCALE_FACTOR scaling; /*!< Structure with scaling information. */ + UCHAR workBuf_nTimeSlots; /*!< Work buffer dimension for this channel is + (workBuf_nTimeSlots * workBuf_nBands * + CMPLX_MOD). */ + UCHAR workBuf_nBands; /*!< Work buffer dimension for this channel is + (workBuf_nTimeSlots * workBuf_nBands * CMPLX_MOD). */ + USHORT workBufferOffset; /*!< Offset within work buffer. */ + USHORT workBufferSectSize; /*!< Size of work buffer section. */ + FIXP_DBL * + pAnaQmfStates; /*!< Pointer to QMF analysis states (persistent memory). */ + FIXP_DBL + *pOverlapBuffer; /*!< Pointer to QMF overlap/delay memory (persistent + memory). */ + FIXP_DBL **pWorkBuffer; /*!< Pointer array to available work buffers. */ + FIXP_DBL * + *hQmfSlotsReal; /*!< Handle for QMF real data time slot pointer array. */ + FIXP_DBL **hQmfSlotsImag; /*!< Handle for QMF imaginary data time slot pointer + array. */ +} FDK_QMF_DOMAIN_IN; +typedef FDK_QMF_DOMAIN_IN *HANDLE_FDK_QMF_DOMAIN_IN; + +/** + * Structure representing one QMF output channel. + */ +typedef struct { + QMF_FILTER_BANK fb; /*!< QMF (synthesis) filter bank structure. */ + FIXP_QSS *pSynQmfStates; /*!< Pointer to QMF synthesis states (persistent + memory). */ +} FDK_QMF_DOMAIN_OUT; +typedef FDK_QMF_DOMAIN_OUT *HANDLE_FDK_QMF_DOMAIN_OUT; + +/** + * Structure representing the QMF domain for multiple channels. + */ +typedef struct { + FDK_QMF_DOMAIN_GC globalConf; /*!< Global configuration structure. */ + FDK_QMF_DOMAIN_IN + QmfDomainIn[((8) + (1))]; /*!< Array of QMF domain input structures */ + FDK_QMF_DOMAIN_OUT + QmfDomainOut[((8) + (1))]; /*!< Array of QMF domain output structures */ +} FDK_QMF_DOMAIN; +typedef FDK_QMF_DOMAIN *HANDLE_FDK_QMF_DOMAIN; + +/** + * \brief Check whether analysis- and synthesis-filterbank-states have been + * initialized. + * + * \param qd Pointer to QMF domain structure. + * + * \return 1 if initialized, 0 else + */ +int FDK_QmfDomain_IsInitialized(const HANDLE_FDK_QMF_DOMAIN qd); + +/** + * \brief Initialize QMF analysis and synthesis filter banks and set up QMF data + * representation. + * + * \param qd Pointer to QMF domain structure. + * \param extra_flags Initialize filter banks with extra flags which were not + * set in the global config flags field. + * + * \return 0 on success. + */ +int FDK_QmfDomain_InitFilterBank(HANDLE_FDK_QMF_DOMAIN qd, UINT extra_flags); + +/** + * \brief When QMF processing of one channel is finished copy the overlap/delay + * part into the persistent memory to be used in the next frame. + * + * \param qd_ch Pointer to a QMF domain input channel. + * \param offset + * + * \return void + */ +void FDK_QmfDomain_SaveOverlap(HANDLE_FDK_QMF_DOMAIN_IN qd_ch, int offset); + +/** + * \brief Get one slot of QMF data and adapt the scaling. + * + * \param qd_ch Pointer to a QMF domain input channel. + * \param ts Time slot number to be obtained. + * \param start_band Start index of QMF bands to be obtained. + * \param stop_band Stop index of QMF band to be obtained. + * \param pQmfOutReal Output buffer (real QMF data). + * \param pQmfOutImag Output buffer (imag QMF data). + * \param exp_out Target exponent (scaling) of data. + * + * \return void + */ +void FDK_QmfDomain_GetSlot(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, const int ts, + const int start_band, const int stop_band, + FIXP_DBL *pQmfOutReal, FIXP_DBL *pQmfOutImag, + const int exp_out); + +/** + * \brief Direct access to the work buffer associated with a certain channel (no + * time slot pointer array is used). + * + * \param qd_ch Pointer to a QMF domain input channel. + * \param ts Time slot number to be obtained. + * \param ppQmfReal Returns the pointer to the requested part of the work buffer + * (real time slot). + * \param ppQmfImag Returns the pointer to the requested part of the work buffer + * (imag time slot). + * + * \return void + */ +void FDK_QmfDomain_GetWorkBuffer(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, + const int ts, FIXP_DBL **ppQmfReal, + FIXP_DBL **ppQmfImag); + +/** + * \brief For the case that the work buffer associated to this channel is not + * identical to the processing channel work buffer copy the data into the + * processing channel. + * + * \param qd_ch Pointer to a QMF domain input channel. + * \return void + */ +void FDK_QmfDomain_WorkBuffer2ProcChannel(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch); + +/** + * \brief For the case of stereoCfgIndex3 with HBE the HBE buffer is copied into + * the processing channel work buffer and the processing channel work buffer is + * copied into the HBE buffer. + * + * \param qd_ch Pointer to a QMF domain input channel. + * \param ppQmfReal Pointer to a HBE QMF data buffer (real). + * \param ppQmfImag Pointer to a HBE QMF data buffer (imag). + * + * \return void + */ +void FDK_QmfDomain_QmfData2HBE(HANDLE_FDK_QMF_DOMAIN_IN qd_ch, + FIXP_DBL **ppQmfReal, FIXP_DBL **ppQmfImag); + +/** + * \brief Set all fields for requested parametervalues in global config struct + * FDK_QMF_DOMAIN_GC to 0. + * + * \param hgc Pointer to a QMF domain global config struct. + */ +void FDK_QmfDomain_ClearRequested(HANDLE_FDK_QMF_DOMAIN_GC hgc); + +/** + * \brief Check for parameter-change requests in global config and + * (re-)configure QMF domain accordingly. + * + * \param hqd Pointer to QMF domain + * + * \return errorcode + */ +QMF_DOMAIN_ERROR FDK_QmfDomain_Configure(HANDLE_FDK_QMF_DOMAIN hqd); + +/** + * \brief Free QMF workbuffer, QMF persistent memory and configuration + * variables. + * + * \param hqd Pointer to QMF domain + */ +void FDK_QmfDomain_FreeMem(HANDLE_FDK_QMF_DOMAIN hqd); + +/** + * \brief Clear QMF overlap buffers and QMF filter bank states. + * + * \param hqd Pointer to QMF domain + */ +QMF_DOMAIN_ERROR FDK_QmfDomain_ClearPersistentMemory(HANDLE_FDK_QMF_DOMAIN hqd); + +/** + * \brief Free QMF workbuffer and QMF persistent memory. + * + * \param hqd Pointer to QMF domain + * + * \param dmx_lp_mode downmix low power mode flag + */ +void FDK_QmfDomain_Close(HANDLE_FDK_QMF_DOMAIN hqd); + +#endif /* FDK_QMF_DOMAIN_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_tools_rom.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_tools_rom.h new file mode 100644 index 0000000000000..d1cb9806c7d94 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_tools_rom.h @@ -0,0 +1,398 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Oliver Moser + + Description: ROM tables used by FDK tools + +*******************************************************************************/ + +#ifndef FDK_TOOLS_ROM_H +#define FDK_TOOLS_ROM_H + +#include "common_fix.h" +#include "FDK_audio.h" + +/* sinetables */ + +/* None radix2 rotation vectors */ +extern RAM_ALIGN const FIXP_STB RotVectorReal60[60]; +extern RAM_ALIGN const FIXP_STB RotVectorImag60[60]; +extern RAM_ALIGN const FIXP_STB RotVectorReal192[192]; +extern RAM_ALIGN const FIXP_STB RotVectorImag192[192]; +extern RAM_ALIGN const FIXP_STB RotVectorReal240[210]; +extern RAM_ALIGN const FIXP_STB RotVectorImag240[210]; +extern RAM_ALIGN const FIXP_STB RotVectorReal480[480]; +extern RAM_ALIGN const FIXP_STB RotVectorImag480[480]; +extern RAM_ALIGN const FIXP_STB RotVectorReal6[6]; +extern RAM_ALIGN const FIXP_STB RotVectorImag6[6]; +extern RAM_ALIGN const FIXP_STB RotVectorReal12[12]; +extern RAM_ALIGN const FIXP_STB RotVectorImag12[12]; +extern RAM_ALIGN const FIXP_STB RotVectorReal24[24]; +extern RAM_ALIGN const FIXP_STB RotVectorImag24[24]; +extern RAM_ALIGN const FIXP_STB RotVectorReal48[48]; +extern RAM_ALIGN const FIXP_STB RotVectorImag48[48]; +extern RAM_ALIGN const FIXP_STB RotVectorReal80[80]; +extern RAM_ALIGN const FIXP_STB RotVectorImag80[80]; +extern RAM_ALIGN const FIXP_STB RotVectorReal96[96]; +extern RAM_ALIGN const FIXP_STB RotVectorImag96[96]; +extern RAM_ALIGN const FIXP_STB RotVectorReal384[384]; +extern RAM_ALIGN const FIXP_STB RotVectorImag384[384]; +extern RAM_ALIGN const FIXP_STB RotVectorReal20[20]; +extern RAM_ALIGN const FIXP_STB RotVectorImag20[20]; +extern RAM_ALIGN const FIXP_STB RotVectorReal120[120]; +extern RAM_ALIGN const FIXP_STB RotVectorImag120[120]; + +/* Regular sine tables */ +extern RAM_ALIGN const FIXP_STP SineTable1024[]; +extern RAM_ALIGN const FIXP_STP SineTable512[]; +extern RAM_ALIGN const FIXP_STP SineTable480[]; +extern RAM_ALIGN const FIXP_STP SineTable384[]; +extern RAM_ALIGN const FIXP_STP SineTable80[]; +#ifdef INCLUDE_SineTable10 +extern RAM_ALIGN const FIXP_STP SineTable10[]; +#endif + +/* AAC-LC windows */ +extern RAM_ALIGN const FIXP_WTP SineWindow1024[]; +extern RAM_ALIGN const FIXP_WTP KBDWindow1024[]; +extern RAM_ALIGN const FIXP_WTP SineWindow128[]; +extern RAM_ALIGN const FIXP_WTP KBDWindow128[]; + +extern RAM_ALIGN const FIXP_WTP SineWindow960[]; +extern RAM_ALIGN const FIXP_WTP KBDWindow960[]; +extern RAM_ALIGN const FIXP_WTP SineWindow120[]; +extern RAM_ALIGN const FIXP_WTP KBDWindow120[]; + +/* AAC-LD windows */ +extern RAM_ALIGN const FIXP_WTP SineWindow512[]; +#define LowOverlapWindow512 SineWindow128 +extern RAM_ALIGN const FIXP_WTP SineWindow480[]; +#define LowOverlapWindow480 SineWindow120 + +/* USAC TCX Window */ +extern RAM_ALIGN const FIXP_WTP SineWindow256[256]; +extern RAM_ALIGN const FIXP_WTP SineWindow192[]; + +/* USAC 8/3 windows */ +extern RAM_ALIGN const FIXP_WTP SineWindow768[]; +extern RAM_ALIGN const FIXP_WTP KBDWindow768[]; +extern RAM_ALIGN const FIXP_WTP SineWindow96[]; +extern RAM_ALIGN const FIXP_WTP KBDWindow96[]; + +/* DCT and others */ +extern RAM_ALIGN const FIXP_WTP SineWindow64[]; +extern RAM_ALIGN const FIXP_WTP SineWindow48[]; +extern RAM_ALIGN const FIXP_WTP SineWindow32[]; +extern RAM_ALIGN const FIXP_WTP SineWindow24[]; +extern RAM_ALIGN const FIXP_WTP SineWindow16[]; +extern RAM_ALIGN const FIXP_WTP SineWindow8[]; + +/** + * \brief Helper table for window slope mapping. You should prefer the usage of + * the function FDKgetWindowSlope(), this table is only made public for some + * optimized access inside dct.cpp. + */ +extern const FIXP_WTP *const windowSlopes[2][4][9]; + +/** + * \brief Window slope access helper. Obtain a window of given length and shape. + * \param length Length of the window slope. + * \param shape Shape index of the window slope. 0: sine window, 1: + * Kaiser-Bessel. Any other value is applied a mask of 1 to, mapping it to + * either 0 or 1. + * \param Pointer to window slope or NULL if the requested window slope is not + * available. + */ +const FIXP_WTP *FDKgetWindowSlope(int length, int shape); + +extern const FIXP_WTP sin_twiddle_L64[]; + +/* + * Filter coefficient type definition + */ + +#if defined(ARCH_PREFER_MULT_16x16) || defined(ARCH_PREFER_MULT_32x16) +#define QMF_COEFF_16BIT +#endif + +#define QMF_FILTER_PROTOTYPE_SIZE 640 +#define QMF_NO_POLY 5 + +#ifdef QMF_COEFF_16BIT +#define FIXP_PFT FIXP_SGL +#define FIXP_QTW FIXP_SGL +#define FX_DBL2FX_QTW(x) FX_DBL2FX_SGL(x) +#else +#define FIXP_PFT FIXP_DBL +#define FIXP_QTW FIXP_DBL + +#define FX_DBL2FX_QTW(x) (x) + +#endif + +#define QMF640_PFT_TABLE_SIZE (640 / 2 + QMF_NO_POLY) + +/* Resampling twiddles for QMF */ + +/* Not resampling twiddles */ +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_cos32[32]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_sin32[32]; +/* Adapted analysis post-twiddles for down-sampled HQ SBR */ +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_cos_downsamp32[32]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_sin_downsamp32[32]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_cos64[64]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_sin64[64]; +extern RAM_ALIGN const FIXP_PFT + qmf_pfilt640[QMF640_PFT_TABLE_SIZE + QMF_NO_POLY]; +extern RAM_ALIGN const FIXP_PFT qmf_pfilt640_vector[640]; + +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_cos40[40]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_sin40[40]; +extern RAM_ALIGN const FIXP_PFT qmf_pfilt400[]; +extern RAM_ALIGN const FIXP_PFT qmf_pfilt200[]; +extern RAM_ALIGN const FIXP_PFT qmf_pfilt120[]; + +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_cos24[24]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_sin24[24]; +extern RAM_ALIGN const FIXP_PFT qmf_pfilt240[]; + +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_cos16[16]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_sin16[16]; + +#define QMF640_CLDFB_PFT_TABLE_SIZE (640) +#define QMF320_CLDFB_PFT_TABLE_SIZE (320) +#define QMF_CLDFB_PFT_SCALE 1 + +extern const FIXP_QTW qmf_phaseshift_cos32_cldfb_ana[32]; +extern const FIXP_QTW qmf_phaseshift_cos32_cldfb_syn[32]; +extern const FIXP_QTW qmf_phaseshift_sin32_cldfb[32]; + +extern const FIXP_QTW qmf_phaseshift_cos16_cldfb_ana[16]; +extern const FIXP_QTW qmf_phaseshift_cos16_cldfb_syn[16]; +extern const FIXP_QTW qmf_phaseshift_sin16_cldfb[16]; + +extern const FIXP_QTW qmf_phaseshift_cos8_cldfb_ana[8]; +extern const FIXP_QTW qmf_phaseshift_cos8_cldfb_syn[8]; +extern const FIXP_QTW qmf_phaseshift_sin8_cldfb[8]; + +extern const FIXP_QTW qmf_phaseshift_cos64_cldfb[64]; +extern const FIXP_QTW qmf_phaseshift_sin64_cldfb[64]; + +extern RAM_ALIGN const FIXP_PFT qmf_cldfb_640[QMF640_CLDFB_PFT_TABLE_SIZE]; +extern RAM_ALIGN const FIXP_PFT qmf_cldfb_320[QMF320_CLDFB_PFT_TABLE_SIZE]; +#define QMF160_CLDFB_PFT_TABLE_SIZE (160) +extern RAM_ALIGN const FIXP_PFT qmf_cldfb_160[QMF160_CLDFB_PFT_TABLE_SIZE]; +#define QMF80_CLDFB_PFT_TABLE_SIZE (80) +extern RAM_ALIGN const FIXP_PFT qmf_cldfb_80[QMF80_CLDFB_PFT_TABLE_SIZE]; + +#define QMF320_MPSLDFB_PFT_TABLE_SIZE (320) +#define QMF640_MPSLDFB_PFT_TABLE_SIZE (640) +#define QMF_MPSLDFB_PFT_SCALE 1 + +extern const FIXP_PFT qmf_mpsldfb_320[QMF320_MPSLDFB_PFT_TABLE_SIZE]; +extern RAM_ALIGN const FIXP_PFT qmf_mpsldfb_640[QMF640_MPSLDFB_PFT_TABLE_SIZE]; + +/** + * Audio bitstream element specific syntax flags: + */ +#define AC_EL_GA_CCE 0x00000001 /*!< GA AAC coupling channel element (CCE) */ + +/* + * Raw Data Block list items. + */ +typedef enum { + element_instance_tag, + common_window, /* -> decision for link_sequence */ + global_gain, + ics_info, /* ics_reserved_bit, window_sequence, window_shape, max_sfb, + scale_factor_grouping, predictor_data_present, ltp_data_present, + ltp_data */ + max_sfb, + ms, /* ms_mask_present, ms_used */ + /*predictor_data_present,*/ /* part of ics_info */ + ltp_data_present, + ltp_data, + section_data, + scale_factor_data, + pulse, /* pulse_data_present, pulse_data */ + tns_data_present, + tns_data, + gain_control_data_present, + gain_control_data, + esc1_hcr, + esc2_rvlc, + spectral_data, + + scale_factor_data_usac, + core_mode, /* -> decision for link_sequence */ + common_tw, + lpd_channel_stream, + tw_data, + noise, + ac_spectral_data, + fac_data, + tns_active, /* introduced in MPEG-D usac CD */ + tns_data_present_usac, + common_max_sfb, + + coupled_elements, /* only for CCE parsing */ + gain_element_lists, /* only for CCE parsing */ + + /* Non data list items */ + adtscrc_start_reg1, + adtscrc_start_reg2, + adtscrc_end_reg1, + adtscrc_end_reg2, + drmcrc_start_reg, + drmcrc_end_reg, + next_channel, + next_channel_loop, + link_sequence, + end_of_sequence +} rbd_id_t; + +struct element_list { + const rbd_id_t *id; + const struct element_list *next[2]; +}; + +typedef struct element_list element_list_t; +/** + * \brief get elementary stream pieces list for given parameters. + * \param aot audio object type + * \param epConfig the epConfig value from the current Audio Specific Config + * \param nChannels amount of channels contained in the current element. + * \param layer the layer of the current element. + * \param elFlags element specific flags. + * \return element_list_t parser guidance structure. + */ +const element_list_t *getBitstreamElementList(AUDIO_OBJECT_TYPE aot, + SCHAR epConfig, UCHAR nChannels, + UCHAR layer, UINT elFlags); + +typedef enum { + /* n.a. */ + FDK_FORMAT_1_0 = 1, /* mono */ + FDK_FORMAT_2_0 = 2, /* stereo */ + FDK_FORMAT_3_0_FC = 3, /* 3/0.0 */ + FDK_FORMAT_3_1_0 = 4, /* 3/1.0 */ + FDK_FORMAT_5_0 = 5, /* 3/2.0 */ + FDK_FORMAT_5_1 = 6, /* 5.1 */ + FDK_FORMAT_7_1_ALT = 7, /* 5/2.1 ALT */ + /* 8 n.a.*/ + FDK_FORMAT_3_0_RC = 9, /* 2/1.0 */ + FDK_FORMAT_2_2_0 = 10, /* 2/2.0 */ + FDK_FORMAT_6_1 = 11, /* 3/3.1 */ + FDK_FORMAT_7_1 = 12, /* 3/4.1 */ + FDK_FORMAT_22_2 = 13, /* 22.2 */ + FDK_FORMAT_5_2_1 = 14, /* 5/2.1*/ + FDK_FORMAT_5_5_2 = 15, /* 5/5.2 */ + FDK_FORMAT_9_1 = 16, /* 5/4.1 */ + FDK_FORMAT_6_5_1 = 17, /* 6/5.1 */ + FDK_FORMAT_6_7_1 = 18, /* 6/7.1 */ + FDK_FORMAT_5_6_1 = 19, /* 5/6.1 */ + FDK_FORMAT_7_6_1 = 20, /* 7/6.1 */ + FDK_FORMAT_IN_LISTOFCHANNELS = 21, + FDK_FORMAT_OUT_LISTOFCHANNELS = 22, + /* 20 formats + In & Out list of channels */ + FDK_NFORMATS = 23, + FDK_FORMAT_FAIL = -1 +} FDK_converter_formatid_t; + +extern const INT format_nchan[FDK_NFORMATS + 9 - 2]; + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_trigFcts.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_trigFcts.h new file mode 100644 index 0000000000000..153ca4c61a56b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/FDK_trigFcts.h @@ -0,0 +1,258 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Haricharan Lakshman, Manuel Jander + + Description: Trigonometric functions fixed point fractional implementation. + +*******************************************************************************/ + +#if !defined(FDK_TRIGFCTS_H) +#define FDK_TRIGFCTS_H + +#include "common_fix.h" + +#include "FDK_tools_rom.h" + +/* Fixed point precision definitions */ +#define Q(format) ((FIXP_DBL)(((LONG)1) << (format))) + +#ifndef M_PI +#define M_PI (3.14159265358979323846f) +#endif + +/*! + * Inverse tangent function. + */ + +/* --- fixp_atan() ---- */ +#define Q_ATANINP (25) // Input in q25, Output in q30 +#define Q_ATANOUT (30) +#define ATI_SF ((DFRACT_BITS - 1) - Q_ATANINP) /* 6 */ +#define ATI_SCALE ((float)(1 << ATI_SF)) +#define ATO_SF ((DFRACT_BITS - 1) - Q_ATANOUT) /* 1 ] -pi/2 .. pi/2 [ */ +#define ATO_SCALE ((float)(1 << ATO_SF)) +/* --- fixp_atan2() --- */ +#define Q_ATAN2OUT (29) +#define AT2O_SF ((DFRACT_BITS - 1) - Q_ATAN2OUT) /* 2 ] -pi .. pi ] */ +#define AT2O_SCALE ((float)(1 << AT2O_SF)) +// -------------------- + +FIXP_DBL fixp_atan(FIXP_DBL x); +FIXP_DBL fixp_atan2(FIXP_DBL y, FIXP_DBL x); + +FIXP_DBL fixp_cos(FIXP_DBL x, int scale); +FIXP_DBL fixp_sin(FIXP_DBL x, int scale); + +#define FIXP_COS_SIN + +#include "FDK_tools_rom.h" + +#define SINETAB SineTable512 +#define LD 9 + +#ifndef FUNCTION_inline_fixp_cos_sin + +#define FUNCTION_inline_fixp_cos_sin + +/* + * Calculates coarse lookup index and sign for sine. + * Returns delta x residual. + */ +static inline FIXP_DBL fixp_sin_cos_residual_inline(FIXP_DBL x, int scale, + FIXP_DBL *sine, + FIXP_DBL *cosine) { + FIXP_DBL residual; + int s; + int shift = (31 - scale - LD - 1); + int ssign = 1; + int csign = 1; + + residual = fMult(x, FL2FXCONST_DBL(1.0 / M_PI)); + s = ((LONG)residual) >> shift; + + residual &= ((1 << shift) - 1); + residual = fMult(residual, FL2FXCONST_DBL(M_PI / 4.0)) << 2; + residual <<= scale; + + /* Sine sign symmetry */ + if (s & ((1 << LD) << 1)) { + ssign = -ssign; + } + /* Cosine sign symmetry */ + if ((s + (1 << LD)) & ((1 << LD) << 1)) { + csign = -csign; + } + + s = fAbs(s); + + s &= (((1 << LD) << 1) - 1); /* Modulo PI */ + + if (s > (1 << LD)) { + s = ((1 << LD) << 1) - s; + } + + { + LONG sl, cl; + /* Because of packed table */ + if (s > (1 << (LD - 1))) { + FIXP_STP tmp; + /* Cosine/Sine simetry for angles greater than PI/4 */ + s = (1 << LD) - s; + tmp = SINETAB[s]; + sl = (LONG)tmp.v.re; + cl = (LONG)tmp.v.im; + } else { + FIXP_STP tmp; + tmp = SINETAB[s]; + sl = (LONG)tmp.v.im; + cl = (LONG)tmp.v.re; + } + +#ifdef SINETABLE_16BIT + *sine = (FIXP_DBL)((sl * ssign) << (DFRACT_BITS - FRACT_BITS)); + *cosine = (FIXP_DBL)((cl * csign) << (DFRACT_BITS - FRACT_BITS)); +#else + /* scale down by 1 for overflow prevention. This is undone at the calling + * function. */ + *sine = (FIXP_DBL)(sl * ssign) >> 1; + *cosine = (FIXP_DBL)(cl * csign) >> 1; +#endif + } + + return residual; +} + +/** + * \brief Calculate cosine and sine value each of 2 angles different angle + * values. + * \param x1 first angle value + * \param x2 second angle value + * \param scale exponent of x1 and x2 + * \param out pointer to 4 FIXP_DBL locations, were the values cos(x1), sin(x1), + * cos(x2), sin(x2) will be stored into. + */ +static inline void inline_fixp_cos_sin(FIXP_DBL x1, FIXP_DBL x2, + const int scale, FIXP_DBL *out) { + FIXP_DBL residual, error0, error1, sine, cosine; + residual = fixp_sin_cos_residual_inline(x1, scale, &sine, &cosine); + error0 = fMultDiv2(sine, residual); + error1 = fMultDiv2(cosine, residual); + +#ifdef SINETABLE_16BIT + *out++ = cosine - (error0 << 1); + *out++ = sine + (error1 << 1); +#else + /* Undo downscaling by 1 which was done at fixp_sin_cos_residual_inline */ + *out++ = SATURATE_LEFT_SHIFT(cosine - (error0 << 1), 1, DFRACT_BITS); + *out++ = SATURATE_LEFT_SHIFT(sine + (error1 << 1), 1, DFRACT_BITS); +#endif + + residual = fixp_sin_cos_residual_inline(x2, scale, &sine, &cosine); + error0 = fMultDiv2(sine, residual); + error1 = fMultDiv2(cosine, residual); + +#ifdef SINETABLE_16BIT + *out++ = cosine - (error0 << 1); + *out++ = sine + (error1 << 1); +#else + *out++ = SATURATE_LEFT_SHIFT(cosine - (error0 << 1), 1, DFRACT_BITS); + *out++ = SATURATE_LEFT_SHIFT(sine + (error1 << 1), 1, DFRACT_BITS); +#endif +} +#endif + +#endif /* !defined(FDK_TRIGFCTS_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/abs.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/abs.h new file mode 100644 index 0000000000000..0846c960aee78 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/abs.h @@ -0,0 +1,136 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser + + Description: fixed point abs definitions + +*******************************************************************************/ + +#if !defined(ABS_H) +#define ABS_H + +#if defined(__mips__) +#include "mips/abs_mips.h" + +#elif defined(__x86__) +#include "x86/abs_x86.h" + +#endif /* all cores */ + +/************************************************************************* + ************************************************************************* + Software fallbacks for missing functions +************************************************************************** +**************************************************************************/ + +#if !defined(FUNCTION_fixabs_D) +inline FIXP_DBL fixabs_D(FIXP_DBL x) { + return ((x) > (FIXP_DBL)(0)) ? (x) : -(x); +} +#endif + +#if !defined(FUNCTION_fixabs_I) +inline INT fixabs_I(INT x) { return ((x) > (INT)(0)) ? (x) : -(x); } +#endif + +#if !defined(FUNCTION_fixabs_S) +inline FIXP_SGL fixabs_S(FIXP_SGL x) { + return ((x) > (FIXP_SGL)(0)) ? (x) : -(x); +} +#endif + +#endif /* ABS_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/clz_arm.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/clz_arm.h new file mode 100644 index 0000000000000..1c3e1fb75b3ce --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/clz_arm.h @@ -0,0 +1,164 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(CLZ_ARM_H) +#define CLZ_ARM_H + +#if defined(__arm__) + +#if defined(__GNUC__) +/* ARM gcc*/ + +#if defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_8__) +#define FUNCTION_fixnormz_D +#define FUNCTION_fixnorm_D +#define FUNCTION_fixnormz_S +#define FUNCTION_fixnorm_S + +#ifdef FUNCTION_fixnormz_D +inline INT fixnormz_D(LONG value) { + INT result; +#if defined(__ARM_ARCH_8__) + asm("clz %w0, %w1 " : "=r"(result) : "r"(value)); +#else + asm("clz %0, %1 " : "=r"(result) : "r"(value)); +#endif + return result; +} +#endif /* #ifdef FUNCTION_fixnormz_D */ + +#ifdef FUNCTION_fixnorm_D +inline INT fixnorm_D(LONG value) { + if (!value) return 0; + if (value < 0) value = ~value; + return fixnormz_D(value) - 1; +} +#endif /* #ifdef FUNCTION_fixnorm_D */ + +#ifdef FUNCTION_fixnormz_S +inline INT fixnormz_S(SHORT value) { + INT result; + result = (LONG)(value << 16); + if (result == 0) + result = 16; + else + result = fixnormz_D(result); + return result; +} +#endif /* #ifdef FUNCTION_fixnormz_S */ + +#ifdef FUNCTION_fixnorm_S +inline INT fixnorm_S(SHORT value) { + LONG lvalue = (LONG)(value << 16); + if (!lvalue) return 0; + if (lvalue < 0) lvalue = ~lvalue; + return fixnormz_D(lvalue) - 1; +} +#endif /* #ifdef FUNCTION_fixnorm_S */ + +#endif + +#endif /* arm toolchain */ + +#endif /* __arm__ */ + +#endif /* !defined(CLZ_ARM_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/cplx_mul_arm.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/cplx_mul_arm.h new file mode 100644 index 0000000000000..a448e334059fa --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/cplx_mul_arm.h @@ -0,0 +1,201 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(CPLX_MUL_ARM_H) +#define CPLX_MUL_ARM_H + +#if defined(__arm__) && defined(__GNUC__) + +#if defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_6__) || \ + defined(__ARM_ARCH_8__) +#define FUNCTION_cplxMultDiv2_32x16 +#define FUNCTION_cplxMultDiv2_32x16X2 +#endif + +#define FUNCTION_cplxMultDiv2_32x32X2 +#ifdef FUNCTION_cplxMultDiv2_32x32X2 +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_DBL b_Re, + const FIXP_DBL b_Im) { + LONG tmp1, tmp2; + +#ifdef __ARM_ARCH_8__ + asm("smull %x0, %w2, %w4; \n" /* tmp1 = a_Re * b_Re */ + "smull %x1, %w2, %w5; \n" /* tmp2 = a_Re * b_Im */ + "smsubl %x0, %w3, %w5, %x0; \n" /* tmp1 -= a_Im * b_Im */ + "smaddl %x1, %w3, %w4, %x1; \n" /* tmp2 += a_Im * b_Re */ + "asr %x0, %x0, #32 \n" + "asr %x1, %x1, #32 \n" + : "=&r"(tmp1), "=&r"(tmp2) + : "r"(a_Re), "r"(a_Im), "r"(b_Re), "r"(b_Im)); +#elif defined(__ARM_ARCH_6__) + asm("smmul %0, %2, %4;\n" /* tmp1 = a_Re * b_Re */ + "smmls %0, %3, %5, %0;\n" /* tmp1 -= a_Im * b_Im */ + "smmul %1, %2, %5;\n" /* tmp2 = a_Re * b_Im */ + "smmla %1, %3, %4, %1;\n" /* tmp2 += a_Im * b_Re */ + : "=&r"(tmp1), "=&r"(tmp2) + : "r"(a_Re), "r"(a_Im), "r"(b_Re), "r"(b_Im)); +#else + LONG discard; + asm("smull %2, %0, %7, %6;\n" /* tmp1 = -a_Im * b_Im */ + "smlal %2, %0, %3, %5;\n" /* tmp1 += a_Re * b_Re */ + "smull %2, %1, %3, %6;\n" /* tmp2 = a_Re * b_Im */ + "smlal %2, %1, %4, %5;\n" /* tmp2 += a_Im * b_Re */ + : "=&r"(tmp1), "=&r"(tmp2), "=&r"(discard) + : "r"(a_Re), "r"(a_Im), "r"(b_Re), "r"(b_Im), "r"(-a_Im)); +#endif + *c_Re = tmp1; + *c_Im = tmp2; +} +#endif /* FUNCTION_cplxMultDiv2_32x32X2 */ + +#if defined(FUNCTION_cplxMultDiv2_32x16) +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, FIXP_SPK wpk) { +#ifdef __ARM_ARCH_8__ + FIXP_DBL b_Im = FX_SGL2FX_DBL(wpk.v.im); + FIXP_DBL b_Re = FX_SGL2FX_DBL(wpk.v.re); + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, b_Re, b_Im); +#else + LONG tmp1, tmp2; + const LONG w = wpk.w; + asm("smulwt %0, %3, %4;\n" + "rsb %1,%0,#0;\n" + "smlawb %0, %2, %4, %1;\n" + "smulwt %1, %2, %4;\n" + "smlawb %1, %3, %4, %1;\n" + : "=&r"(tmp1), "=&r"(tmp2) + : "r"(a_Re), "r"(a_Im), "r"(w)); + *c_Re = tmp1; + *c_Im = tmp2; +#endif +} +#endif /* FUNCTION_cplxMultDiv2_32x16 */ + +#ifdef FUNCTION_cplxMultDiv2_32x16X2 +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { +#ifdef __ARM_ARCH_8__ + FIXP_DBL b_re = FX_SGL2FX_DBL(b_Re); + FIXP_DBL b_im = FX_SGL2FX_DBL(b_Im); + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, b_re, b_im); +#else + LONG tmp1, tmp2; + + asm("smulwb %0, %3, %5;\n" /* %7 = -a_Im * b_Im */ + "rsb %1,%0,#0;\n" + "smlawb %0, %2, %4, %1;\n" /* tmp1 = a_Re * b_Re - a_Im * b_Im */ + "smulwb %1, %2, %5;\n" /* %7 = a_Re * b_Im */ + "smlawb %1, %3, %4, %1;\n" /* tmp2 = a_Im * b_Re + a_Re * b_Im */ + : "=&r"(tmp1), "=&r"(tmp2) + : "r"(a_Re), "r"(a_Im), "r"(b_Re), "r"(b_Im)); + + *c_Re = tmp1; + *c_Im = tmp2; +#endif +} +#endif /* FUNCTION_cplxMultDiv2_32x16X2 */ + +#endif + +#endif /* !defined(CPLX_MUL_ARM_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/fixmadd_arm.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/fixmadd_arm.h new file mode 100644 index 0000000000000..1378660dbe926 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/fixmadd_arm.h @@ -0,0 +1,220 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(FIXMADD_ARM_H) +#define FIXMADD_ARM_H + +#if defined(__arm__) + +/* ############################################################################# + */ +#if defined(__GNUC__) && defined(__arm__) +/* ############################################################################# + */ +/* ARM GNU GCC */ + +#ifdef __ARM_ARCH_8__ +#define FUNCTION_fixmadddiv2_DD +#ifdef FUNCTION_fixmadddiv2_DD +inline FIXP_DBL fixmadddiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT64 result; + asm("smull %x0, %w1, %w2; \n" + "asr %x0, %x0, #32; \n" + "add %w0, %w3, %w0; \n" + : "=&r"(result) + : "r"(a), "r"(b), "r"(x)); + return (INT)result; +} +#endif /* #ifdef FUNCTION_fixmadddiv2_DD */ + +#define FUNCTION_fixmsubdiv2_DD +#ifdef FUNCTION_fixmsubdiv2_DD +inline FIXP_DBL fixmsubdiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT64 result; + asm("smull %x0, %w1, %w2; \n" + "asr %x0, %x0, #32; \n" + "sub %w0, %w3, %w0; \n" + : "=&r"(result) + : "r"(a), "r"(b), "r"(x)); + return (INT)result; +} +#endif /* #ifdef FUNCTION_fixmsubdiv2_DD */ + +#elif defined(__ARM_ARCH_6__) +#define FUNCTION_fixmadddiv2_DD +#ifdef FUNCTION_fixmadddiv2_DD +inline FIXP_DBL fixmadddiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT result; + asm("smmla %0, %1, %2, %3;\n" : "=r"(result) : "r"(a), "r"(b), "r"(x)); + return result; +} +#endif /* #ifdef FUNCTION_fixmadddiv2_DD */ + +#define FUNCTION_fixmsubdiv2_DD +#ifdef FUNCTION_fixmsubdiv2_DD +inline FIXP_DBL fixmsubdiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT result; + asm("smmls %0, %1, %2, %3;\n" : "=r"(result) : "r"(a), "r"(b), "r"(x)); + return result; +} +#endif /* #ifdef FUNCTION_fixmsubdiv2_DD */ + +#else +#define FUNCTION_fixmadddiv2_DD +#ifdef FUNCTION_fixmadddiv2_DD +inline FIXP_DBL fixmadddiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT discard = 0; + INT result = x; + asm("smlal %0, %1, %2, %3;\n" : "+r"(discard), "+r"(result) : "r"(a), "r"(b)); + return result; +} +#endif /* #ifdef FUNCTION_fixmadddiv2_DD */ +#endif + +#if defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_6__) + +#define FUNCTION_fixmadddiv2_DS +#ifdef FUNCTION_fixmadddiv2_DS +inline FIXP_DBL fixmadddiv2_DS(FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { + INT result; + asm("smlawb %0, %1, %2, %3 " : "=r"(result) : "r"(a), "r"(b), "r"(x)); + return result; +} +#endif /* #ifdef FUNCTION_fixmadddiv2_DS */ + +#endif /* defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_6__) */ + +#define FUNCTION_fixmadddiv2BitExact_DD +#ifdef FUNCTION_fixmadddiv2BitExact_DD +#define fixmadddiv2BitExact_DD(a, b, c) fixmadddiv2_DD(a, b, c) +#endif /* #ifdef FUNCTION_fixmadddiv2BitExact_DD */ + +#define FUNCTION_fixmsubdiv2BitExact_DD +#ifdef FUNCTION_fixmsubdiv2BitExact_DD +inline FIXP_DBL fixmsubdiv2BitExact_DD(FIXP_DBL x, const FIXP_DBL a, + const FIXP_DBL b) { + return x - fixmuldiv2BitExact_DD(a, b); +} +#endif /* #ifdef FUNCTION_fixmsubdiv2BitExact_DD */ + +#define FUNCTION_fixmadddiv2BitExact_DS +#ifdef FUNCTION_fixmadddiv2BitExact_DS +#define fixmadddiv2BitExact_DS(a, b, c) fixmadddiv2_DS(a, b, c) +#endif /* #ifdef FUNCTION_fixmadddiv2BitExact_DS */ + +#define FUNCTION_fixmsubdiv2BitExact_DS +#ifdef FUNCTION_fixmsubdiv2BitExact_DS +inline FIXP_DBL fixmsubdiv2BitExact_DS(FIXP_DBL x, const FIXP_DBL a, + const FIXP_SGL b) { + return x - fixmuldiv2BitExact_DS(a, b); +} +#endif /* #ifdef FUNCTION_fixmsubdiv2BitExact_DS */ + +/* ############################################################################# + */ +#endif /* toolchain */ + /* ############################################################################# + */ + +#endif /* __arm__ */ + +#endif /* !defined(FIXMADD_ARM_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/fixmul_arm.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/fixmul_arm.h new file mode 100644 index 0000000000000..077e5c6cc3641 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/fixmul_arm.h @@ -0,0 +1,198 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(FIXMUL_ARM_H) +#define FIXMUL_ARM_H + +#if defined(__arm__) + +#if defined(__GNUC__) && defined(__arm__) +/* ARM with GNU compiler */ + +#define FUNCTION_fixmuldiv2_DD + +#define FUNCTION_fixmuldiv2BitExact_DD +#ifdef FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a, b) fixmuldiv2_DD(a, b) +#endif /* #ifdef FUNCTION_fixmuldiv2BitExact_DD */ + +#define FUNCTION_fixmulBitExact_DD +#ifdef FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD(a, b) (fixmuldiv2BitExact_DD(a, b) << 1) +#endif /* #ifdef FUNCTION_fixmulBitExact_DD */ + +#define FUNCTION_fixmuldiv2BitExact_DS +#ifdef FUNCTION_fixmuldiv2BitExact_DS +#define fixmuldiv2BitExact_DS(a, b) fixmuldiv2_DS(a, b) +#endif /* #ifdef FUNCTION_fixmuldiv2BitExact_DS */ + +#define FUNCTION_fixmulBitExact_DS +#ifdef FUNCTION_fixmulBitExact_DS +#define fixmulBitExact_DS(a, b) fixmul_DS(a, b) +#endif /* #ifdef FUNCTION_fixmulBitExact_DS */ + +#ifdef FUNCTION_fixmuldiv2_DD +inline INT fixmuldiv2_DD(const INT a, const INT b) { + INT result; +#if defined(__ARM_ARCH_8__) + INT64 result64; + __asm__( + "smull %x0, %w1, %w2;\n" + "asr %x0, %x0, #32; " + : "=r"(result64) + : "r"(a), "r"(b)); + result = (INT)result64; +#elif defined(__ARM_ARCH_6__) || defined(__TARGET_ARCH_7E_M) + __asm__("smmul %0, %1, %2" : "=r"(result) : "r"(a), "r"(b)); +#else + INT discard; + __asm__("smull %0, %1, %2, %3" + : "=&r"(discard), "=r"(result) + : "r"(a), "r"(b)); +#endif + return result; +} +#endif /* #ifdef FUNCTION_fixmuldiv2_DD */ + +#if defined(__ARM_ARCH_8__) +#define FUNCTION_fixmuldiv2_SD +#ifdef FUNCTION_fixmuldiv2_SD +inline INT fixmuldiv2_SD(const SHORT a, const INT b) { + return fixmuldiv2_DD((INT)(a << 16), b); +} +#endif /* #ifdef FUNCTION_fixmuldiv2_SD */ +#elif defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_6__) +#define FUNCTION_fixmuldiv2_SD +#ifdef FUNCTION_fixmuldiv2_SD +inline INT fixmuldiv2_SD(const SHORT a, const INT b) { + INT result; + __asm__("smulwb %0, %1, %2" : "=r"(result) : "r"(b), "r"(a)); + return result; +} +#endif /* #ifdef FUNCTION_fixmuldiv2_SD */ +#endif + +#define FUNCTION_fixmul_DD +#ifdef FUNCTION_fixmul_DD +#if defined(__ARM_ARCH_8__) +inline INT fixmul_DD(const INT a, const INT b) { + INT64 result64; + + __asm__( + "smull %x0, %w1, %w2;\n" + "asr %x0, %x0, #31; " + : "=r"(result64) + : "r"(a), "r"(b)); + return (INT)result64; +} +#else +inline INT fixmul_DD(const INT a, const INT b) { + return (fixmuldiv2_DD(a, b) << 1); +} +#endif /* __ARM_ARCH_8__ */ +#endif /* #ifdef FUNCTION_fixmul_DD */ + +#endif /* defined(__GNUC__) && defined(__arm__) */ + +#endif /* __arm__ */ + +#endif /* !defined(FIXMUL_ARM_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/scale_arm.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/scale_arm.h new file mode 100644 index 0000000000000..0bf4f66076b55 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/scale_arm.h @@ -0,0 +1,163 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: ARM scaling operations + +*******************************************************************************/ + +#if !defined(SCALE_ARM_H) +#define SCALE_ARM_H + +#if defined(__GNUC__) /* GCC Compiler */ + +#if defined(__ARM_ARCH_6__) + +inline static INT shiftRightSat(INT src, int scale) { + INT result; + asm("ssat %0,%2,%0;\n" + + : "=&r"(result) + : "r"(src >> scale), "M"(SAMPLE_BITS)); + + return result; +} + +#define SATURATE_INT_PCM_RIGHT_SHIFT(src, scale) shiftRightSat(src, scale) + +inline static INT shiftLeftSat(INT src, int scale) { + INT result; + asm("ssat %0,%2,%0;\n" + + : "=&r"(result) + : "r"(src << scale), "M"(SAMPLE_BITS)); + + return result; +} + +#define SATURATE_INT_PCM_LEFT_SHIFT(src, scale) shiftLeftSat(src, scale) + +#endif /* __ARM_ARCH_6__ */ + +#endif /* compiler selection */ + +#define FUNCTION_scaleValueInPlace +#ifdef FUNCTION_scaleValueInPlace +inline void scaleValueInPlace(FIXP_DBL *value, /*!< Value */ + INT scalefactor /*!< Scalefactor */ +) { + INT newscale; + if ((newscale = scalefactor) >= 0) + *value <<= newscale; + else + *value >>= -newscale; +} +#endif /* #ifdef FUNCTION_scaleValueInPlace */ + +#define SATURATE_RIGHT_SHIFT(src, scale, dBits) \ + ((((LONG)(src) ^ ((LONG)(src) >> (DFRACT_BITS - 1))) >> (scale)) > \ + (LONG)(((1U) << ((dBits)-1)) - 1)) \ + ? ((LONG)(src) >> (DFRACT_BITS - 1)) ^ (LONG)(((1U) << ((dBits)-1)) - 1) \ + : ((LONG)(src) >> (scale)) + +#define SATURATE_LEFT_SHIFT(src, scale, dBits) \ + (((LONG)(src) ^ ((LONG)(src) >> (DFRACT_BITS - 1))) > \ + ((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale))) \ + ? ((LONG)(src) >> (DFRACT_BITS - 1)) ^ (LONG)(((1U) << ((dBits)-1)) - 1) \ + : ((LONG)(src) << (scale)) + +#endif /* !defined(SCALE_ARM_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/scramble_arm.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/scramble_arm.h new file mode 100644 index 0000000000000..a7cfe65af2a17 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/arm/scramble_arm.h @@ -0,0 +1,174 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: bitreversal of input data + +*******************************************************************************/ + +#if !defined(SCRAMBLE_ARM_H) +#define SCRAMBLE_ARM_H + +#if defined(FUNCTION_scramble) +#if defined(__GNUC__) + +#define FUNCTION_scramble + +#if defined(__ARM_ARCH_5TE__) +#define USE_LDRD_STRD /* LDRD requires 8 byte data alignment. */ +#endif + +inline void scramble(FIXP_DBL x[], INT n) { + FDK_ASSERT(!(((INT)x) & (ALIGNMENT_DEFAULT - 1))); + asm("mov r2, #1;\n" /* r2(m) = 1; */ + "sub r3, %1, #1;\n" /* r3 = n-1; */ + "mov r4, #0;\n" /* r4(j) = 0; */ + + "scramble_m_loop%=:\n" /* { */ + "mov r5, %1;\n" /* r5(k) = 1; */ + + "scramble_k_loop%=:\n" /* { */ + "mov r5, r5, lsr #1;\n" /* k >>= 1; */ + "eor r4, r4, r5;\n" /* j ^=k; */ + "ands r10, r4, r5;\n" /* r10 = r4 & r5; */ + "beq scramble_k_loop%=;\n" /* } while (r10 == 0); */ + + "cmp r4, r2;\n" /* if (r4 < r2) break; */ + "bcc scramble_m_loop_end%=;\n" + +#ifdef USE_LDRD_STRD + "mov r5, r2, lsl #3;\n" /* m(r5) = r2*4*2 */ + "ldrd r10, [%0, r5];\n" /* r10 = x[r5], x7 = x[r5+1] */ + "mov r6, r4, lsl #3;\n" /* j(r6) = r4*4*2 */ + "ldrd r8, [%0, r6];\n" /* r8 = x[r6], r9 = x[r6+1]; */ + "strd r10, [%0, r6];\n" /* x[r6,r6+1] = r10,r11; */ + "strd r8, [%0, r5];\n" /* x[r5,r5+1] = r8,r9; */ +#else + "mov r5, r2, lsl #3;\n" /* m(r5) = r2*4*2 */ + "ldr r10, [%0, r5];\n" + "mov r6, r4, lsl #3;\n" /* j(r6) = r4*4*2 */ + "ldr r11, [%0, r6];\n" + + "str r10, [%0, r6];\n" + "str r11, [%0, r5];\n" + + "add r5, r5, #4;" + "ldr r10, [%0, r5];\n" + "add r6, r6, #4;" + "ldr r11, [%0, r6];\n" + "str r10, [%0, r6];\n" + "str r11, [%0, r5];\n" +#endif + "scramble_m_loop_end%=:\n" + "add r2, r2, #1;\n" /* r2++; */ + "cmp r2, r3;\n" + "bcc scramble_m_loop%=;\n" /* } while (r2(m) < r3(n-1)); */ + : + : "r"(x), "r"(n) +#ifdef USE_LDRD_STRD + : "r2", "r3", "r4", "r5", "r10", "r11", "r8", "r9", "r6"); +#else + : "r2", "r3", "r4", "r5", "r10", "r11", "r6"); +#endif +} +#else +/* Force C implementation if no assembler version available. */ +#undef FUNCTION_scramble +#endif /* Toolchain selection. */ + +#endif /* defined(FUNCTION_scramble) */ +#endif /* !defined(SCRAMBLE_ARM_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/autocorr2nd.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/autocorr2nd.h new file mode 100644 index 0000000000000..e01989b5d5bd2 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/autocorr2nd.h @@ -0,0 +1,137 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser + + Description: fixed point abs definitions + +*******************************************************************************/ + +#ifndef AUTOCORR2ND_H +#define AUTOCORR2ND_H + +#include "common_fix.h" + +typedef struct { + FIXP_DBL r00r; + FIXP_DBL r11r; + FIXP_DBL r22r; + FIXP_DBL r01r; + FIXP_DBL r02r; + FIXP_DBL r12r; + FIXP_DBL r01i; + FIXP_DBL r02i; + FIXP_DBL r12i; + FIXP_DBL det; + int det_scale; +} ACORR_COEFS; + +#define LPC_ORDER 2 + +INT autoCorr2nd_real( + ACORR_COEFS *ac, /*!< Pointer to autocorrelation coeffs */ + const FIXP_DBL *reBuffer, /*!< Pointer to to real part of spectrum */ + const int len /*!< Number of qmf slots */ +); + +INT autoCorr2nd_cplx( + ACORR_COEFS *ac, /*!< Pointer to autocorrelation coeffs */ + const FIXP_DBL *reBuffer, /*!< Pointer to to real part of spectrum */ + const FIXP_DBL *imBuffer, /*!< Pointer to imag part of spectrum */ + const int len /*!< Number of qmf slots */ +); + +#endif /* AUTOCORR2ND_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/clz.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/clz.h new file mode 100644 index 0000000000000..df75618974b49 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/clz.h @@ -0,0 +1,205 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Marc Gayer + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(CLZ_H) +#define CLZ_H + +#include "FDK_archdef.h" +#include "machine_type.h" + +#if defined(__arm__) +#include "arm/clz_arm.h" + +#elif defined(__mips__) +#include "mips/clz_mips.h" + +#elif defined(__x86__) +#include "x86/clz_x86.h" + +#elif defined(__powerpc__) +#include "ppc/clz_ppc.h" + +#endif /* all cores */ + +/************************************************************************* + ************************************************************************* + Software fallbacks for missing functions. +************************************************************************** +**************************************************************************/ + +#if !defined(FUNCTION_fixnormz_S) +#ifdef FUNCTION_fixnormz_D +inline INT fixnormz_S(SHORT a) { + if (a < 0) { + return 0; + } + return fixnormz_D((INT)(a)) - 16; +} +#else +inline INT fixnormz_S(SHORT a) { + int leadingBits = 0; + a = ~a; + while (a & 0x8000) { + leadingBits++; + a <<= 1; + } + + return (leadingBits); +} +#endif +#endif + +#if !defined(FUNCTION_fixnormz_D) +inline INT fixnormz_D(LONG a) { + INT leadingBits = 0; + a = ~a; + while (a & 0x80000000) { + leadingBits++; + a <<= 1; + } + + return (leadingBits); +} +#endif + +/***************************************************************************** + + functionname: fixnorm_D + description: Count leading ones or zeros of operand val for dfract/LONG INT +values. Return this value minus 1. Return 0 if operand==0. +*****************************************************************************/ +#if !defined(FUNCTION_fixnorm_S) +#ifdef FUNCTION_fixnorm_D +inline INT fixnorm_S(FIXP_SGL val) { + if (val == (FIXP_SGL)0) { + return 0; + } + return fixnorm_D((INT)(val)) - 16; +} +#else +inline INT fixnorm_S(FIXP_SGL val) { + INT leadingBits = 0; + if (val != (FIXP_SGL)0) { + if (val < (FIXP_SGL)0) { + val = ~val; + } + leadingBits = fixnormz_S(val) - 1; + } + return (leadingBits); +} +#endif +#endif + +#if !defined(FUNCTION_fixnorm_D) +inline INT fixnorm_D(FIXP_DBL val) { + INT leadingBits = 0; + if (val != (FIXP_DBL)0) { + if (val < (FIXP_DBL)0) { + val = ~val; + } + leadingBits = fixnormz_D(val) - 1; + } + return (leadingBits); +} +#endif + +#endif /* CLZ_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/common_fix.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/common_fix.h new file mode 100644 index 0000000000000..7c08225129924 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/common_fix.h @@ -0,0 +1,449 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser, M. Gayer + + Description: Flexible fixpoint library configuration + +*******************************************************************************/ + +#ifndef COMMON_FIX_H +#define COMMON_FIX_H + +#include "FDK_archdef.h" +#include "machine_type.h" + +/* ***** Start of former fix.h ****** */ + +/* Define bit sizes of integer fixpoint fractional data types */ +#define FRACT_BITS 16 /* single precision */ +#define DFRACT_BITS 32 /* double precision */ +#define ACCU_BITS 40 /* double precision plus overflow */ + +/* Fixpoint equivalent type fot PCM audio time domain data. */ +#if defined(SAMPLE_BITS) +#if (SAMPLE_BITS == DFRACT_BITS) +#define FIXP_PCM FIXP_DBL +#define MAXVAL_FIXP_PCM MAXVAL_DBL +#define MINVAL_FIXP_PCM MINVAL_DBL +#define FX_PCM2FX_DBL(x) ((FIXP_DBL)(x)) +#define FX_DBL2FX_PCM(x) ((INT_PCM)(x)) +#elif (SAMPLE_BITS == FRACT_BITS) +#define FIXP_PCM FIXP_SGL +#define MAXVAL_FIXP_PCM MAXVAL_SGL +#define MINVAL_FIXP_PCM MINVAL_SGL +#define FX_PCM2FX_DBL(x) FX_SGL2FX_DBL((FIXP_SGL)(x)) +#define FX_DBL2FX_PCM(x) FX_DBL2FX_SGL(x) +#else +#error SAMPLE_BITS different from FRACT_BITS or DFRACT_BITS not implemented! +#endif +#endif + +/* ****** End of former fix.h ****** */ + +#define SGL_MASK ((1UL << FRACT_BITS) - 1) /* 16bit: (2^16)-1 = 0xFFFF */ + +#define MAX_SHIFT_SGL \ + (FRACT_BITS - 1) /* maximum possible shift for FIXP_SGL values */ +#define MAX_SHIFT_DBL \ + (DFRACT_BITS - 1) /* maximum possible shift for FIXP_DBL values */ + +/* Scale factor from/to float/fixpoint values. DO NOT USE THESE VALUES AS + * SATURATION LIMITS !! */ +#define FRACT_FIX_SCALE ((INT64(1) << (FRACT_BITS - 1))) +#define DFRACT_FIX_SCALE ((INT64(1) << (DFRACT_BITS - 1))) + +/* Max and Min values for saturation purposes. DO NOT USE THESE VALUES AS SCALE + * VALUES !! */ +#define MAXVAL_SGL \ + ((signed)0x00007FFF) /* this has to be synchronized to FRACT_BITS */ +#define MINVAL_SGL \ + ((signed)0xFFFF8000) /* this has to be synchronized to FRACT_BITS */ +#define MAXVAL_DBL \ + ((signed)0x7FFFFFFF) /* this has to be synchronized to DFRACT_BITS */ +#define MINVAL_DBL \ + ((signed)0x80000000) /* this has to be synchronized to DFRACT_BITS */ + +#define FX_DBL2FXCONST_SGL(val) \ + ((((((val) >> (DFRACT_BITS - FRACT_BITS - 1)) + 1) > \ + (((LONG)1 << FRACT_BITS) - 1)) && \ + ((LONG)(val) > 0)) \ + ? (FIXP_SGL)(SHORT)(((LONG)1 << (FRACT_BITS - 1)) - 1) \ + : (FIXP_SGL)(SHORT)((((val) >> (DFRACT_BITS - FRACT_BITS - 1)) + 1) >> \ + 1)) + +#define shouldBeUnion union /* unions are possible */ + +typedef SHORT FIXP_SGL; +typedef LONG FIXP_DBL; + +/* macros for compile-time conversion of constant float values to fixedpoint */ +#define FL2FXCONST_SPC FL2FXCONST_DBL + +#define MINVAL_DBL_CONST MINVAL_DBL +#define MINVAL_SGL_CONST MINVAL_SGL + +#define FL2FXCONST_SGL(val) \ + (FIXP_SGL)( \ + ((val) >= 0) \ + ? ((((double)(val) * (FRACT_FIX_SCALE) + 0.5) >= \ + (double)(MAXVAL_SGL)) \ + ? (SHORT)(MAXVAL_SGL) \ + : (SHORT)((double)(val) * (double)(FRACT_FIX_SCALE) + 0.5)) \ + : ((((double)(val) * (FRACT_FIX_SCALE)-0.5) <= \ + (double)(MINVAL_SGL_CONST)) \ + ? (SHORT)(MINVAL_SGL_CONST) \ + : (SHORT)((double)(val) * (double)(FRACT_FIX_SCALE)-0.5))) + +#define FL2FXCONST_DBL(val) \ + (FIXP_DBL)( \ + ((val) >= 0) \ + ? ((((double)(val) * (DFRACT_FIX_SCALE) + 0.5) >= \ + (double)(MAXVAL_DBL)) \ + ? (LONG)(MAXVAL_DBL) \ + : (LONG)((double)(val) * (double)(DFRACT_FIX_SCALE) + 0.5)) \ + : ((((double)(val) * (DFRACT_FIX_SCALE)-0.5) <= \ + (double)(MINVAL_DBL_CONST)) \ + ? (LONG)(MINVAL_DBL_CONST) \ + : (LONG)((double)(val) * (double)(DFRACT_FIX_SCALE)-0.5))) + +/* macros for runtime conversion of float values to integer fixedpoint. NO + * OVERFLOW CHECK!!! */ +#define FL2FX_SPC FL2FX_DBL +#define FL2FX_SGL(val) \ + ((val) > 0.0f ? (SHORT)((val) * (float)(FRACT_FIX_SCALE) + 0.5f) \ + : (SHORT)((val) * (float)(FRACT_FIX_SCALE)-0.5f)) +#define FL2FX_DBL(val) \ + ((val) > 0.0f ? (LONG)((val) * (float)(DFRACT_FIX_SCALE) + 0.5f) \ + : (LONG)((val) * (float)(DFRACT_FIX_SCALE)-0.5f)) + +/* macros for runtime conversion of fixedpoint values to other fixedpoint. NO + * ROUNDING!!! */ +#define FX_ACC2FX_SGL(val) ((FIXP_SGL)((val) >> (ACCU_BITS - FRACT_BITS))) +#define FX_ACC2FX_DBL(val) ((FIXP_DBL)((val) >> (ACCU_BITS - DFRACT_BITS))) +#define FX_SGL2FX_ACC(val) ((FIXP_ACC)((LONG)(val) << (ACCU_BITS - FRACT_BITS))) +#define FX_SGL2FX_DBL(val) \ + ((FIXP_DBL)((LONG)(val) << (DFRACT_BITS - FRACT_BITS))) +#define FX_DBL2FX_SGL(val) ((FIXP_SGL)((val) >> (DFRACT_BITS - FRACT_BITS))) + +/* ############################################################# */ + +/* macros for runtime conversion of integer fixedpoint values to float. */ + +/* #define FX_DBL2FL(val) ((float)(pow(2.,-31.)*(float)val)) */ /* version #1 + */ +#define FX_DBL2FL(val) \ + ((float)((double)(val) / (double)DFRACT_FIX_SCALE)) /* version #2 - \ + identical to class \ + dfract cast from \ + dfract to float */ +#define FX_DBL2DOUBLE(val) (((double)(val) / (double)DFRACT_FIX_SCALE)) + +/* ############################################################# */ +#include "fixmul.h" + +FDK_INLINE LONG fMult(SHORT a, SHORT b) { return fixmul_SS(a, b); } +FDK_INLINE LONG fMult(SHORT a, LONG b) { return fixmul_SD(a, b); } +FDK_INLINE LONG fMult(LONG a, SHORT b) { return fixmul_DS(a, b); } +FDK_INLINE LONG fMult(LONG a, LONG b) { return fixmul_DD(a, b); } +FDK_INLINE LONG fPow2(LONG a) { return fixpow2_D(a); } +FDK_INLINE LONG fPow2(SHORT a) { return fixpow2_S(a); } + +FDK_INLINE LONG fMultDiv2(SHORT a, SHORT b) { return fixmuldiv2_SS(a, b); } +FDK_INLINE LONG fMultDiv2(SHORT a, LONG b) { return fixmuldiv2_SD(a, b); } +FDK_INLINE LONG fMultDiv2(LONG a, SHORT b) { return fixmuldiv2_DS(a, b); } +FDK_INLINE LONG fMultDiv2(LONG a, LONG b) { return fixmuldiv2_DD(a, b); } +FDK_INLINE LONG fPow2Div2(LONG a) { return fixpow2div2_D(a); } +FDK_INLINE LONG fPow2Div2(SHORT a) { return fixpow2div2_S(a); } + +FDK_INLINE LONG fMultDiv2BitExact(LONG a, LONG b) { + return fixmuldiv2BitExact_DD(a, b); +} +FDK_INLINE LONG fMultDiv2BitExact(SHORT a, LONG b) { + return fixmuldiv2BitExact_SD(a, b); +} +FDK_INLINE LONG fMultDiv2BitExact(LONG a, SHORT b) { + return fixmuldiv2BitExact_DS(a, b); +} +FDK_INLINE LONG fMultBitExact(LONG a, LONG b) { + return fixmulBitExact_DD(a, b); +} +FDK_INLINE LONG fMultBitExact(SHORT a, LONG b) { + return fixmulBitExact_SD(a, b); +} +FDK_INLINE LONG fMultBitExact(LONG a, SHORT b) { + return fixmulBitExact_DS(a, b); +} + +/* ******************************************************************************** + */ +#include "abs.h" + +FDK_INLINE FIXP_DBL fAbs(FIXP_DBL x) { return fixabs_D(x); } +FDK_INLINE FIXP_SGL fAbs(FIXP_SGL x) { return fixabs_S(x); } + +#if !defined(__LP64__) +FDK_INLINE INT fAbs(INT x) { return fixabs_I(x); } +#endif + + /* ******************************************************************************** + */ + +#include "clz.h" + +FDK_INLINE INT fNormz(INT64 x) { + INT clz = fixnormz_D((INT)(x >> 32)); + if (clz == 32) clz += fixnormz_D((INT)x); + return clz; +} +FDK_INLINE INT fNormz(FIXP_DBL x) { return fixnormz_D(x); } +FDK_INLINE INT fNormz(FIXP_SGL x) { return fixnormz_S(x); } +FDK_INLINE INT fNorm(FIXP_DBL x) { return fixnorm_D(x); } +FDK_INLINE INT fNorm(FIXP_SGL x) { return fixnorm_S(x); } + + /* ******************************************************************************** + */ + /* ******************************************************************************** + */ + /* ******************************************************************************** + */ + +#include "clz.h" +#define fixp_abs(x) fAbs(x) +#define fixMin(a, b) fMin(a, b) +#define fixMax(a, b) fMax(a, b) +#define CntLeadingZeros(x) fixnormz_D(x) +#define CountLeadingBits(x) fixnorm_D(x) + +#include "fixmadd.h" + +/* y = (x+0.5*a*b) */ +FDK_INLINE FIXP_DBL fMultAddDiv2(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) { + return fixmadddiv2_DD(x, a, b); +} +FDK_INLINE FIXP_DBL fMultAddDiv2(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) { + return fixmadddiv2_SD(x, a, b); +} +FDK_INLINE FIXP_DBL fMultAddDiv2(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) { + return fixmadddiv2_DS(x, a, b); +} +FDK_INLINE FIXP_DBL fMultAddDiv2(FIXP_DBL x, FIXP_SGL a, FIXP_SGL b) { + return fixmadddiv2_SS(x, a, b); +} + +FDK_INLINE FIXP_DBL fPow2AddDiv2(FIXP_DBL x, FIXP_DBL a) { + return fixpadddiv2_D(x, a); +} +FDK_INLINE FIXP_DBL fPow2AddDiv2(FIXP_DBL x, FIXP_SGL a) { + return fixpadddiv2_S(x, a); +} + +/* y = 2*(x+0.5*a*b) = (2x+a*b) */ +FDK_INLINE FIXP_DBL fMultAdd(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) { + return fixmadd_DD(x, a, b); +} +inline FIXP_DBL fMultAdd(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) { + return fixmadd_SD(x, a, b); +} +inline FIXP_DBL fMultAdd(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) { + return fixmadd_DS(x, a, b); +} +inline FIXP_DBL fMultAdd(FIXP_DBL x, FIXP_SGL a, FIXP_SGL b) { + return fixmadd_SS(x, a, b); +} + +inline FIXP_DBL fPow2Add(FIXP_DBL x, FIXP_DBL a) { return fixpadd_D(x, a); } +inline FIXP_DBL fPow2Add(FIXP_DBL x, FIXP_SGL a) { return fixpadd_S(x, a); } + +/* y = (x-0.5*a*b) */ +inline FIXP_DBL fMultSubDiv2(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) { + return fixmsubdiv2_DD(x, a, b); +} +inline FIXP_DBL fMultSubDiv2(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) { + return fixmsubdiv2_SD(x, a, b); +} +inline FIXP_DBL fMultSubDiv2(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) { + return fixmsubdiv2_DS(x, a, b); +} +inline FIXP_DBL fMultSubDiv2(FIXP_DBL x, FIXP_SGL a, FIXP_SGL b) { + return fixmsubdiv2_SS(x, a, b); +} + +/* y = 2*(x-0.5*a*b) = (2*x-a*b) */ +FDK_INLINE FIXP_DBL fMultSub(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) { + return fixmsub_DD(x, a, b); +} +inline FIXP_DBL fMultSub(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) { + return fixmsub_SD(x, a, b); +} +inline FIXP_DBL fMultSub(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) { + return fixmsub_DS(x, a, b); +} +inline FIXP_DBL fMultSub(FIXP_DBL x, FIXP_SGL a, FIXP_SGL b) { + return fixmsub_SS(x, a, b); +} + +FDK_INLINE FIXP_DBL fMultAddDiv2BitExact(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) { + return fixmadddiv2BitExact_DD(x, a, b); +} +FDK_INLINE FIXP_DBL fMultAddDiv2BitExact(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) { + return fixmadddiv2BitExact_SD(x, a, b); +} +FDK_INLINE FIXP_DBL fMultAddDiv2BitExact(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) { + return fixmadddiv2BitExact_DS(x, a, b); +} +FDK_INLINE FIXP_DBL fMultSubDiv2BitExact(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) { + return fixmsubdiv2BitExact_DD(x, a, b); +} +FDK_INLINE FIXP_DBL fMultSubDiv2BitExact(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) { + return fixmsubdiv2BitExact_SD(x, a, b); +} +FDK_INLINE FIXP_DBL fMultSubDiv2BitExact(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) { + return fixmsubdiv2BitExact_DS(x, a, b); +} + +#include "fixminmax.h" + +FDK_INLINE FIXP_DBL fMin(FIXP_DBL a, FIXP_DBL b) { return fixmin_D(a, b); } +FDK_INLINE FIXP_DBL fMax(FIXP_DBL a, FIXP_DBL b) { return fixmax_D(a, b); } + +FDK_INLINE FIXP_SGL fMin(FIXP_SGL a, FIXP_SGL b) { return fixmin_S(a, b); } +FDK_INLINE FIXP_SGL fMax(FIXP_SGL a, FIXP_SGL b) { return fixmax_S(a, b); } + +#if !defined(__LP64__) +FDK_INLINE INT fMax(INT a, INT b) { return fixmax_I(a, b); } +FDK_INLINE INT fMin(INT a, INT b) { return fixmin_I(a, b); } +#endif + +inline UINT fMax(UINT a, UINT b) { return fixmax_UI(a, b); } +inline UINT fMin(UINT a, UINT b) { return fixmin_UI(a, b); } + +inline UCHAR fMax(UCHAR a, UCHAR b) { + return (UCHAR)fixmax_UI((UINT)a, (UINT)b); +} +inline UCHAR fMin(UCHAR a, UCHAR b) { + return (UCHAR)fixmin_UI((UINT)a, (UINT)b); +} + +/* Complex data types */ +typedef shouldBeUnion { + /* vector representation for arithmetic */ + struct { + FIXP_SGL re; + FIXP_SGL im; + } v; + /* word representation for memory move */ + LONG w; +} +FIXP_SPK; + +typedef shouldBeUnion { + /* vector representation for arithmetic */ + struct { + FIXP_DBL re; + FIXP_DBL im; + } v; + /* word representation for memory move */ + INT64 w; +} +FIXP_DPK; + +#include "fixmul.h" +#include "fixmadd.h" +#include "cplx_mul.h" +#include "fixpoint_math.h" + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/cplx_mul.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/cplx_mul.h new file mode 100644 index 0000000000000..eb1afcea2432c --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/cplx_mul.h @@ -0,0 +1,266 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(CPLX_MUL_H) +#define CPLX_MUL_H + +#include "common_fix.h" + +#if defined(__arm__) || defined(_M_ARM) +#include "arm/cplx_mul_arm.h" + +#elif defined(__GNUC__) && defined(__mips__) && __mips_isa_rev < 6 +#include "mips/cplx_mul_mips.h" + +#endif /* #if defined all cores: bfin, arm, etc. */ + +/* ############################################################################# + */ + +/* Fallback generic implementations */ + +#if !defined(FUNCTION_cplxMultDiv2_32x16X2) +#define FUNCTION_cplxMultDiv2_32x16X2 + +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { + *c_Re = fMultDiv2(a_Re, b_Re) - fMultDiv2(a_Im, b_Im); + *c_Im = fMultDiv2(a_Re, b_Im) + fMultDiv2(a_Im, b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_16x16X2) +#define FUNCTION_cplxMultDiv2_16x16X2 + +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_SGL a_Re, + const FIXP_SGL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { + *c_Re = fMultDiv2(a_Re, b_Re) - fMultDiv2(a_Im, b_Im); + *c_Im = fMultDiv2(a_Re, b_Im) + fMultDiv2(a_Im, b_Re); +} + +inline void cplxMultDiv2(FIXP_SGL *c_Re, FIXP_SGL *c_Im, const FIXP_SGL a_Re, + const FIXP_SGL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { + *c_Re = FX_DBL2FX_SGL(fMultDiv2(a_Re, b_Re) - fMultDiv2(a_Im, b_Im)); + *c_Im = FX_DBL2FX_SGL(fMultDiv2(a_Re, b_Im) + fMultDiv2(a_Im, b_Re)); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_32x16) +#define FUNCTION_cplxMultDiv2_32x16 + +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_SPK w) { + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_16x16) +#define FUNCTION_cplxMultDiv2_16x16 + +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_SGL a_Re, + const FIXP_SGL a_Im, const FIXP_SPK w) { + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} + +inline void cplxMultDiv2(FIXP_SGL *c_Re, FIXP_SGL *c_Im, const FIXP_SGL a_Re, + const FIXP_SGL a_Im, const FIXP_SPK w) { + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + +#if !defined(FUNCTION_cplxMultSubDiv2_32x16X2) +#define FUNCTION_cplxMultSubDiv2_32x16X2 + +inline void cplxMultSubDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { + *c_Re -= fMultDiv2(a_Re, b_Re) - fMultDiv2(a_Im, b_Im); + *c_Im -= fMultDiv2(a_Re, b_Im) + fMultDiv2(a_Im, b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_32x32X2) +#define FUNCTION_cplxMultDiv2_32x32X2 + +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_DBL b_Re, + const FIXP_DBL b_Im) { + *c_Re = fMultDiv2(a_Re, b_Re) - fMultDiv2(a_Im, b_Im); + *c_Im = fMultDiv2(a_Re, b_Im) + fMultDiv2(a_Im, b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_32x32) +#define FUNCTION_cplxMultDiv2_32x32 + +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_DPK w) { + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + +#if !defined(FUNCTION_cplxMultSubDiv2_32x32X2) +#define FUNCTION_cplxMultSubDiv2_32x32X2 + +inline void cplxMultSubDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_DBL b_Re, + const FIXP_DBL b_Im) { + *c_Re -= fMultDiv2(a_Re, b_Re) - fMultDiv2(a_Im, b_Im); + *c_Im -= fMultDiv2(a_Re, b_Im) + fMultDiv2(a_Im, b_Re); +} +#endif + + /* ############################################################################# + */ + +#if !defined(FUNCTION_cplxMult_32x16X2) +#define FUNCTION_cplxMult_32x16X2 + +inline void cplxMult(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { + *c_Re = fMult(a_Re, b_Re) - fMult(a_Im, b_Im); + *c_Im = fMult(a_Re, b_Im) + fMult(a_Im, b_Re); +} +inline void cplxMult(FIXP_SGL *c_Re, FIXP_SGL *c_Im, const FIXP_SGL a_Re, + const FIXP_SGL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { + *c_Re = FX_DBL2FX_SGL(fMult(a_Re, b_Re) - fMult(a_Im, b_Im)); + *c_Im = FX_DBL2FX_SGL(fMult(a_Re, b_Im) + fMult(a_Im, b_Re)); +} +#endif + +#if !defined(FUNCTION_cplxMult_32x16) +#define FUNCTION_cplxMult_32x16 + +inline void cplxMult(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_SPK w) { + cplxMult(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + +#if !defined(FUNCTION_cplxMult_32x32X2) +#define FUNCTION_cplxMult_32x32X2 + +inline void cplxMult(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_DBL b_Re, + const FIXP_DBL b_Im) { + *c_Re = fMult(a_Re, b_Re) - fMult(a_Im, b_Im); + *c_Im = fMult(a_Re, b_Im) + fMult(a_Im, b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMult_32x32) +#define FUNCTION_cplxMult_32x32 +inline void cplxMult(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_DPK w) { + cplxMult(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + + /* ############################################################################# + */ + +#endif /* CPLX_MUL_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/dct.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/dct.h new file mode 100644 index 0000000000000..308afcb77156a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/dct.h @@ -0,0 +1,171 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: Library functions to calculate standard DCTs. This will most + likely be replaced by hand-optimized functions for the specific + target processor. + +*******************************************************************************/ + +#ifndef DCT_H +#define DCT_H + +#include "common_fix.h" + +void dct_getTables(const FIXP_WTP **ptwiddle, const FIXP_STP **sin_twiddle, + int *sin_step, int length); + +/** + * \brief Calculate DCT type II of given length. The DCT IV is + * calculated by a complex FFT, with some pre and post twiddeling. + * A factor of sqrt(2/(N-1)) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dct_II(FIXP_DBL *pDat, FIXP_DBL *tmp, int size, int *pDat_e); + +/** + * \brief Calculate DCT type III of given length. The DCT IV is + * calculated by a complex FFT, with some pre and post twiddeling. + * Note that the factor 0.5 for the sum term x[0] is 1.0 instead of 0.5. + * A factor of sqrt(2/N) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dct_III(FIXP_DBL *pDat, FIXP_DBL *tmp, int size, int *pDat_e); + +/** + * \brief Calculate DST type III of given length. The DST III is + * calculated by a DCT III of mirrored input and sign-flipping of odd + * output coefficients. + * Note that the factor 0.5 for the sum term x[N-1] is 1.0 instead of + * 0.5. A factor of sqrt(2/N) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dst_III(FIXP_DBL *pDat, FIXP_DBL *tmp, int size, int *pDat_e); + +/** + * \brief Calculate DCT type IV of given length. The DCT IV is + * calculated by a complex FFT, with some pre and post twiddeling. + * A factor of sqrt(2/N) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dct_IV(FIXP_DBL *pDat, int size, int *pDat_e); + +/** + * \brief Calculate DST type IV of given length. The DST IV is + * calculated by a complex FFT, with some pre and post twiddeling. + * A factor of sqrt(2/N) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dst_IV(FIXP_DBL *pDat, int size, int *pDat_e); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fft.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fft.h new file mode 100644 index 0000000000000..4ef62b435d7c6 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fft.h @@ -0,0 +1,263 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Josef Hoepfl, DSP Solutions + + Description: Fix point FFT + +*******************************************************************************/ + +#ifndef FFT_H +#define FFT_H + +#include "common_fix.h" + +/** + * \brief Perform an inplace complex valued FFT of length 2^n + * + * \param length Length of the FFT to be calculated. + * \param pInput Input/Output data buffer. The input data must have at least 1 + * bit scale headroom. The values are interleaved, real/imag pairs. + * \param scalefactor Pointer to an INT, which contains the current scale of the + * input data, which is updated according to the FFT scale. + */ +void fft(int length, FIXP_DBL *pInput, INT *scalefactor); + +/** + * \brief Perform an inplace complex valued IFFT of length 2^n + * + * \param length Length of the FFT to be calculated. + * \param pInput Input/Output data buffer. The input data must have at least 1 + * bit scale headroom. The values are interleaved, real/imag pairs. + * \param scalefactor Pointer to an INT, which contains the current scale of the + * input data, which is updated according to the IFFT scale. + */ +void ifft(int length, FIXP_DBL *pInput, INT *scalefactor); + +/* + * Frequently used and fixed short length FFTs. + */ + +#ifndef FUNCTION_fft_4 +/** + * \brief Perform an inplace complex valued FFT of length 4 + * + * \param pInput Input/Output data buffer. The input data must have at least 1 + * bit scale headroom. The values are interleaved, real/imag pairs. + */ +LNK_SECTION_CODE_L1 +static inline void fft_4(FIXP_DBL *x) { + FIXP_DBL a00, a10, a20, a30, tmp0, tmp1; + + a00 = (x[0] + x[4]) >> 1; /* Re A + Re B */ + a10 = (x[2] + x[6]) >> 1; /* Re C + Re D */ + a20 = (x[1] + x[5]) >> 1; /* Im A + Im B */ + a30 = (x[3] + x[7]) >> 1; /* Im C + Im D */ + + x[0] = a00 + a10; /* Re A' = Re A + Re B + Re C + Re D */ + x[1] = a20 + a30; /* Im A' = Im A + Im B + Im C + Im D */ + + tmp0 = a00 - x[4]; /* Re A - Re B */ + tmp1 = a20 - x[5]; /* Im A - Im B */ + + x[4] = a00 - a10; /* Re C' = Re A + Re B - Re C - Re D */ + x[5] = a20 - a30; /* Im C' = Im A + Im B - Im C - Im D */ + + a10 = a10 - x[6]; /* Re C - Re D */ + a30 = a30 - x[7]; /* Im C - Im D */ + + x[2] = tmp0 + a30; /* Re B' = Re A - Re B + Im C - Im D */ + x[6] = tmp0 - a30; /* Re D' = Re A - Re B - Im C + Im D */ + x[3] = tmp1 - a10; /* Im B' = Im A - Im B - Re C + Re D */ + x[7] = tmp1 + a10; /* Im D' = Im A - Im B + Re C - Re D */ +} +#endif /* FUNCTION_fft_4 */ + +#ifndef FUNCTION_fft_8 +LNK_SECTION_CODE_L1 +static inline void fft_8(FIXP_DBL *x) { + FIXP_SPK w_PiFOURTH = {{FIXP_SGL(0x5A82), FIXP_SGL(0x5A82)}}; + + FIXP_DBL a00, a10, a20, a30; + FIXP_DBL y[16]; + + a00 = (x[0] + x[8]) >> 1; + a10 = x[4] + x[12]; + a20 = (x[1] + x[9]) >> 1; + a30 = x[5] + x[13]; + + y[0] = a00 + (a10 >> 1); + y[4] = a00 - (a10 >> 1); + y[1] = a20 + (a30 >> 1); + y[5] = a20 - (a30 >> 1); + + a00 = a00 - x[8]; + a10 = (a10 >> 1) - x[12]; + a20 = a20 - x[9]; + a30 = (a30 >> 1) - x[13]; + + y[2] = a00 + a30; + y[6] = a00 - a30; + y[3] = a20 - a10; + y[7] = a20 + a10; + + a00 = (x[2] + x[10]) >> 1; + a10 = x[6] + x[14]; + a20 = (x[3] + x[11]) >> 1; + a30 = x[7] + x[15]; + + y[8] = a00 + (a10 >> 1); + y[12] = a00 - (a10 >> 1); + y[9] = a20 + (a30 >> 1); + y[13] = a20 - (a30 >> 1); + + a00 = a00 - x[10]; + a10 = (a10 >> 1) - x[14]; + a20 = a20 - x[11]; + a30 = (a30 >> 1) - x[15]; + + y[10] = a00 + a30; + y[14] = a00 - a30; + y[11] = a20 - a10; + y[15] = a20 + a10; + + FIXP_DBL vr, vi, ur, ui; + + ur = y[0] >> 1; + ui = y[1] >> 1; + vr = y[8]; + vi = y[9]; + x[0] = ur + (vr >> 1); + x[1] = ui + (vi >> 1); + x[8] = ur - (vr >> 1); + x[9] = ui - (vi >> 1); + + ur = y[4] >> 1; + ui = y[5] >> 1; + vi = y[12]; + vr = y[13]; + x[4] = ur + (vr >> 1); + x[5] = ui - (vi >> 1); + x[12] = ur - (vr >> 1); + x[13] = ui + (vi >> 1); + + ur = y[10]; + ui = y[11]; + + cplxMultDiv2(&vi, &vr, ui, ur, w_PiFOURTH); + + ur = y[2]; + ui = y[3]; + x[2] = (ur >> 1) + vr; + x[3] = (ui >> 1) + vi; + x[10] = (ur >> 1) - vr; + x[11] = (ui >> 1) - vi; + + ur = y[14]; + ui = y[15]; + + cplxMultDiv2(&vr, &vi, ui, ur, w_PiFOURTH); + + ur = y[6]; + ui = y[7]; + x[6] = (ur >> 1) + vr; + x[7] = (ui >> 1) - vi; + x[14] = (ur >> 1) - vr; + x[15] = (ui >> 1) + vi; +} +#endif /* FUNCTION_fft_8 */ + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fft_rad2.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fft_rad2.h new file mode 100644 index 0000000000000..b820b7d72de2c --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fft_rad2.h @@ -0,0 +1,121 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser, M. Gayer + + Description: + +*******************************************************************************/ + +#ifndef FFT_RAD2_H +#define FFT_RAD2_H + +#include "common_fix.h" + +/** + * \brief Performe an inplace complex valued FFT of 2^n length + * + * \param x Input/Output data buffer. The input data must have at least 1 bit + * scale headroom. The values are interleaved, real/imag pairs. + * \param ldn log2 of FFT length + * \param trigdata Pointer to a sinetable of a length of at least (2^ldn)/2 sine + * values. + * \param trigDataSize length of the sinetable "trigdata". + */ +void dit_fft(FIXP_DBL *x, const INT ldn, const FIXP_STP *trigdata, + const INT trigDataSize); + +#endif /* FFT_RAD2_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixmadd.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixmadd.h new file mode 100644 index 0000000000000..16724562fb218 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixmadd.h @@ -0,0 +1,333 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser, M. Gayer + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(FIXMADD_H) +#define FIXMADD_H + +#include "FDK_archdef.h" +#include "machine_type.h" +#include "fixmul.h" + +#if defined(__arm__) +#include "arm/fixmadd_arm.h" + +#endif /* all cores */ + +/************************************************************************* + ************************************************************************* + Software fallbacks for missing functions. +************************************************************************** +**************************************************************************/ + +/* Divide by two versions. */ + +#if !defined(FUNCTION_fixmadddiv2_DD) +inline FIXP_DBL fixmadddiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + return (x + fMultDiv2(a, b)); +} +#endif + +#if !defined(FUNCTION_fixmadddiv2_SD) +inline FIXP_DBL fixmadddiv2_SD(FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmadddiv2_DS + return fixmadddiv2_DS(x, b, a); +#else + return fixmadddiv2_DD(x, FX_SGL2FX_DBL(a), b); +#endif +} +#endif + +#if !defined(FUNCTION_fixmadddiv2_DS) +inline FIXP_DBL fixmadddiv2_DS(FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmadddiv2_SD + return fixmadddiv2_SD(x, b, a); +#else + return fixmadddiv2_DD(x, a, FX_SGL2FX_DBL(b)); +#endif +} +#endif + +#if !defined(FUNCTION_fixmadddiv2_SS) +inline FIXP_DBL fixmadddiv2_SS(FIXP_DBL x, const FIXP_SGL a, const FIXP_SGL b) { + return x + fMultDiv2(a, b); +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2_DD) +inline FIXP_DBL fixmsubdiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + return (x - fMultDiv2(a, b)); +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2_SD) +inline FIXP_DBL fixmsubdiv2_SD(FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmsubdiv2_DS + return fixmsubdiv2_DS(x, b, a); +#else + return fixmsubdiv2_DD(x, FX_SGL2FX_DBL(a), b); +#endif +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2_DS) +inline FIXP_DBL fixmsubdiv2_DS(FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmsubdiv2_SD + return fixmsubdiv2_SD(x, b, a); +#else + return fixmsubdiv2_DD(x, a, FX_SGL2FX_DBL(b)); +#endif +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2_SS) +inline FIXP_DBL fixmsubdiv2_SS(FIXP_DBL x, const FIXP_SGL a, const FIXP_SGL b) { + return x - fMultDiv2(a, b); +} +#endif + +#if !defined(FUNCTION_fixmadddiv2BitExact_DD) +#define FUNCTION_fixmadddiv2BitExact_DD +inline FIXP_DBL fixmadddiv2BitExact_DD(FIXP_DBL x, const FIXP_DBL a, + const FIXP_DBL b) { + return x + fMultDiv2BitExact(a, b); +} +#endif +#if !defined(FUNCTION_fixmadddiv2BitExact_SD) +#define FUNCTION_fixmadddiv2BitExact_SD +inline FIXP_DBL fixmadddiv2BitExact_SD(FIXP_DBL x, const FIXP_SGL a, + const FIXP_DBL b) { +#ifdef FUNCTION_fixmadddiv2BitExact_DS + return fixmadddiv2BitExact_DS(x, b, a); +#else + return x + fMultDiv2BitExact(a, b); +#endif +} +#endif +#if !defined(FUNCTION_fixmadddiv2BitExact_DS) +#define FUNCTION_fixmadddiv2BitExact_DS +inline FIXP_DBL fixmadddiv2BitExact_DS(FIXP_DBL x, const FIXP_DBL a, + const FIXP_SGL b) { +#ifdef FUNCTION_fixmadddiv2BitExact_SD + return fixmadddiv2BitExact_SD(x, b, a); +#else + return x + fMultDiv2BitExact(a, b); +#endif +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2BitExact_DD) +#define FUNCTION_fixmsubdiv2BitExact_DD +inline FIXP_DBL fixmsubdiv2BitExact_DD(FIXP_DBL x, const FIXP_DBL a, + const FIXP_DBL b) { + return x - fMultDiv2BitExact(a, b); +} +#endif +#if !defined(FUNCTION_fixmsubdiv2BitExact_SD) +#define FUNCTION_fixmsubdiv2BitExact_SD +inline FIXP_DBL fixmsubdiv2BitExact_SD(FIXP_DBL x, const FIXP_SGL a, + const FIXP_DBL b) { +#ifdef FUNCTION_fixmsubdiv2BitExact_DS + return fixmsubdiv2BitExact_DS(x, b, a); +#else + return x - fMultDiv2BitExact(a, b); +#endif +} +#endif +#if !defined(FUNCTION_fixmsubdiv2BitExact_DS) +#define FUNCTION_fixmsubdiv2BitExact_DS +inline FIXP_DBL fixmsubdiv2BitExact_DS(FIXP_DBL x, const FIXP_DBL a, + const FIXP_SGL b) { +#ifdef FUNCTION_fixmsubdiv2BitExact_SD + return fixmsubdiv2BitExact_SD(x, b, a); +#else + return x - fMultDiv2BitExact(a, b); +#endif +} +#endif + + /* Normal versions */ + +#if !defined(FUNCTION_fixmadd_DD) +inline FIXP_DBL fixmadd_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + return fixmadddiv2_DD(x, a, b) << 1; +} +#endif +#if !defined(FUNCTION_fixmadd_SD) +inline FIXP_DBL fixmadd_SD(FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmadd_DS + return fixmadd_DS(x, b, a); +#else + return fixmadd_DD(x, FX_SGL2FX_DBL(a), b); +#endif +} +#endif +#if !defined(FUNCTION_fixmadd_DS) +inline FIXP_DBL fixmadd_DS(FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmadd_SD + return fixmadd_SD(x, b, a); +#else + return fixmadd_DD(x, a, FX_SGL2FX_DBL(b)); +#endif +} +#endif +#if !defined(FUNCTION_fixmadd_SS) +inline FIXP_DBL fixmadd_SS(FIXP_DBL x, const FIXP_SGL a, const FIXP_SGL b) { + return (x + fMultDiv2(a, b)) << 1; +} +#endif + +#if !defined(FUNCTION_fixmsub_DD) +inline FIXP_DBL fixmsub_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + return fixmsubdiv2_DD(x, a, b) << 1; +} +#endif +#if !defined(FUNCTION_fixmsub_SD) +inline FIXP_DBL fixmsub_SD(FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmsub_DS + return fixmsub_DS(x, b, a); +#else + return fixmsub_DD(x, FX_SGL2FX_DBL(a), b); +#endif +} +#endif +#if !defined(FUNCTION_fixmsub_DS) +inline FIXP_DBL fixmsub_DS(FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmsub_SD + return fixmsub_SD(x, b, a); +#else + return fixmsub_DD(x, a, FX_SGL2FX_DBL(b)); +#endif +} +#endif +#if !defined(FUNCTION_fixmsub_SS) +inline FIXP_DBL fixmsub_SS(FIXP_DBL x, const FIXP_SGL a, const FIXP_SGL b) { + return (x - fMultDiv2(a, b)) << 1; +} +#endif + +#if !defined(FUNCTION_fixpow2adddiv2_D) +#ifdef FUNCTION_fixmadddiv2_DD +#define fixpadddiv2_D(x, a) fixmadddiv2_DD(x, a, a) +#else +inline INT fixpadddiv2_D(FIXP_DBL x, const FIXP_DBL a) { + return (x + fPow2Div2(a)); +} +#endif +#endif +#if !defined(FUNCTION_fixpow2add_D) +inline INT fixpadd_D(FIXP_DBL x, const FIXP_DBL a) { return (x + fPow2(a)); } +#endif + +#if !defined(FUNCTION_fixpow2adddiv2_S) +#ifdef FUNCTION_fixmadddiv2_SS +#define fixpadddiv2_S(x, a) fixmadddiv2_SS(x, a, a) +#else +inline INT fixpadddiv2_S(FIXP_DBL x, const FIXP_SGL a) { + return (x + fPow2Div2(a)); +} +#endif +#endif +#if !defined(FUNCTION_fixpow2add_S) +inline INT fixpadd_S(FIXP_DBL x, const FIXP_SGL a) { return (x + fPow2(a)); } +#endif + +#endif /* FIXMADD_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixminmax.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixminmax.h new file mode 100644 index 0000000000000..69ef35d1552b2 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixminmax.h @@ -0,0 +1,131 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser, M. Gayer + + Description: min/max inline functions and defines + +*******************************************************************************/ + +#ifndef FIXMINMAX_H +#define FIXMINMAX_H + +#include "FDK_archdef.h" +#include "machine_type.h" + +/* Inline Function to determine the smaller/bigger value of two values with same + * type. */ + +template +inline T fixmin(T a, T b) { + return (a < b ? a : b); +} + +template +inline T fixmax(T a, T b) { + return (a > b ? a : b); +} + +#define fixmax_D(a, b) fixmax(a, b) +#define fixmin_D(a, b) fixmin(a, b) +#define fixmax_S(a, b) fixmax(a, b) +#define fixmin_S(a, b) fixmin(a, b) +#define fixmax_I(a, b) fixmax(a, b) +#define fixmin_I(a, b) fixmin(a, b) +#define fixmax_UI(a, b) fixmax(a, b) +#define fixmin_UI(a, b) fixmin(a, b) + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixmul.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixmul.h new file mode 100644 index 0000000000000..8eeb7ab45e254 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixmul.h @@ -0,0 +1,298 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Stefan Gewinner + + Description: fixed point multiplication + +*******************************************************************************/ + +#if !defined(FIXMUL_H) +#define FIXMUL_H + +#include "FDK_archdef.h" +#include "machine_type.h" + +#if defined(__arm__) +#include "arm/fixmul_arm.h" + +#elif defined(__mips__) +#include "mips/fixmul_mips.h" + +#elif defined(__x86__) +#include "x86/fixmul_x86.h" + +#elif defined(__powerpc__) +#include "ppc/fixmul_ppc.h" + +#endif /* all cores */ + +/************************************************************************* + ************************************************************************* + Software fallbacks for missing functions +************************************************************************** +**************************************************************************/ + +#if !defined(FUNCTION_fixmuldiv2_DD) +#define FUNCTION_fixmuldiv2_DD +inline LONG fixmuldiv2_DD(const LONG a, const LONG b) { + return (LONG)((((INT64)a) * b) >> 32); +} +#endif + +#if !defined(FUNCTION_fixmuldiv2BitExact_DD) +#define FUNCTION_fixmuldiv2BitExact_DD +inline LONG fixmuldiv2BitExact_DD(const LONG a, const LONG b) { + return (LONG)((((INT64)a) * b) >> 32); +} +#endif + +#if !defined(FUNCTION_fixmul_DD) +#define FUNCTION_fixmul_DD +inline LONG fixmul_DD(const LONG a, const LONG b) { + return fixmuldiv2_DD(a, b) << 1; +} +#endif + +#if !defined(FUNCTION_fixmulBitExact_DD) +#define FUNCTION_fixmulBitExact_DD +inline LONG fixmulBitExact_DD(const LONG a, const LONG b) { + return ((LONG)((((INT64)a) * b) >> 32)) << 1; +} +#endif + +#if !defined(FUNCTION_fixmuldiv2_SS) +#define FUNCTION_fixmuldiv2_SS +inline LONG fixmuldiv2_SS(const SHORT a, const SHORT b) { + return ((LONG)a * b); +} +#endif + +#if !defined(FUNCTION_fixmul_SS) +#define FUNCTION_fixmul_SS +inline LONG fixmul_SS(const SHORT a, const SHORT b) { return (a * b) << 1; } +#endif + +#if !defined(FUNCTION_fixmuldiv2_SD) +#define FUNCTION_fixmuldiv2_SD +inline LONG fixmuldiv2_SD(const SHORT a, const LONG b) +#ifdef FUNCTION_fixmuldiv2_DS +{ + return fixmuldiv2_DS(b, a); +} +#else +{ + return fixmuldiv2_DD(FX_SGL2FX_DBL(a), b); +} +#endif +#endif + +#if !defined(FUNCTION_fixmuldiv2_DS) +#define FUNCTION_fixmuldiv2_DS +inline LONG fixmuldiv2_DS(const LONG a, const SHORT b) +#ifdef FUNCTION_fixmuldiv2_SD +{ + return fixmuldiv2_SD(b, a); +} +#else +{ + return fixmuldiv2_DD(a, FX_SGL2FX_DBL(b)); +} +#endif +#endif + +#if !defined(FUNCTION_fixmuldiv2BitExact_SD) +#define FUNCTION_fixmuldiv2BitExact_SD +inline LONG fixmuldiv2BitExact_SD(const SHORT a, const LONG b) +#ifdef FUNCTION_fixmuldiv2BitExact_DS +{ + return fixmuldiv2BitExact_DS(b, a); +} +#else +{ + return (LONG)((((INT64)a) * b) >> 16); +} +#endif +#endif + +#if !defined(FUNCTION_fixmuldiv2BitExact_DS) +#define FUNCTION_fixmuldiv2BitExact_DS +inline LONG fixmuldiv2BitExact_DS(const LONG a, const SHORT b) +#ifdef FUNCTION_fixmuldiv2BitExact_SD +{ + return fixmuldiv2BitExact_SD(b, a); +} +#else +{ + return (LONG)((((INT64)a) * b) >> 16); +} +#endif +#endif + +#if !defined(FUNCTION_fixmul_SD) +#define FUNCTION_fixmul_SD +inline LONG fixmul_SD(const SHORT a, const LONG b) { +#ifdef FUNCTION_fixmul_DS + return fixmul_DS(b, a); +#else + return fixmuldiv2_SD(a, b) << 1; +#endif +} +#endif + +#if !defined(FUNCTION_fixmul_DS) +#define FUNCTION_fixmul_DS +inline LONG fixmul_DS(const LONG a, const SHORT b) { +#ifdef FUNCTION_fixmul_SD + return fixmul_SD(b, a); +#else + return fixmuldiv2_DS(a, b) << 1; +#endif +} +#endif + +#if !defined(FUNCTION_fixmulBitExact_SD) +#define FUNCTION_fixmulBitExact_SD +inline LONG fixmulBitExact_SD(const SHORT a, const LONG b) +#ifdef FUNCTION_fixmulBitExact_DS +{ + return fixmulBitExact_DS(b, a); +} +#else +{ + return (LONG)(((((INT64)a) * b) >> 16) << 1); +} +#endif +#endif + +#if !defined(FUNCTION_fixmulBitExact_DS) +#define FUNCTION_fixmulBitExact_DS +inline LONG fixmulBitExact_DS(const LONG a, const SHORT b) +#ifdef FUNCTION_fixmulBitExact_SD +{ + return fixmulBitExact_SD(b, a); +} +#else +{ + return (LONG)(((((INT64)a) * b) >> 16) << 1); +} +#endif +#endif + +#if !defined(FUNCTION_fixpow2div2_D) +#define FUNCTION_fixpow2div2_D +inline LONG fixpow2div2_D(const LONG a) { return fixmuldiv2_DD(a, a); } +#endif + +#if !defined(FUNCTION_fixpow2_D) +#define FUNCTION_fixpow2_D +inline LONG fixpow2_D(const LONG a) { return fixpow2div2_D(a) << 1; } +#endif + +#if !defined(FUNCTION_fixpow2div2_S) +#define FUNCTION_fixpow2div2_S +inline LONG fixpow2div2_S(const SHORT a) { return fixmuldiv2_SS(a, a); } +#endif + +#if !defined(FUNCTION_fixpow2_S) +#define FUNCTION_fixpow2_S +inline LONG fixpow2_S(const SHORT a) { + LONG result = fixpow2div2_S(a) << 1; + return result ^ (result >> 31); +} +#endif + +#endif /* FIXMUL_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixpoint_math.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixpoint_math.h new file mode 100644 index 0000000000000..51df4d7d20089 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/fixpoint_math.h @@ -0,0 +1,952 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Gayer + + Description: Fixed point specific mathematical functions + +*******************************************************************************/ + +#ifndef FIXPOINT_MATH_H +#define FIXPOINT_MATH_H + +#include "common_fix.h" +#include "scale.h" + +/* + * Data definitions + */ + +#define LD_DATA_SCALING (64.0f) +#define LD_DATA_SHIFT 6 /* pow(2, LD_DATA_SHIFT) = LD_DATA_SCALING */ + +#define MAX_LD_PRECISION 10 +#define LD_PRECISION 10 + +/* Taylor series coefficients for ln(1-x), centered at 0 (MacLaurin polynomial). + */ +#ifndef LDCOEFF_16BIT +LNK_SECTION_CONSTDATA_L1 +static const FIXP_DBL ldCoeff[MAX_LD_PRECISION] = { + FL2FXCONST_DBL(-1.0), FL2FXCONST_DBL(-1.0 / 2.0), + FL2FXCONST_DBL(-1.0 / 3.0), FL2FXCONST_DBL(-1.0 / 4.0), + FL2FXCONST_DBL(-1.0 / 5.0), FL2FXCONST_DBL(-1.0 / 6.0), + FL2FXCONST_DBL(-1.0 / 7.0), FL2FXCONST_DBL(-1.0 / 8.0), + FL2FXCONST_DBL(-1.0 / 9.0), FL2FXCONST_DBL(-1.0 / 10.0)}; +#else /* LDCOEFF_16BIT */ +LNK_SECTION_CONSTDATA_L1 +static const FIXP_SGL ldCoeff[MAX_LD_PRECISION] = { + FL2FXCONST_SGL(-1.0), FL2FXCONST_SGL(-1.0 / 2.0), + FL2FXCONST_SGL(-1.0 / 3.0), FL2FXCONST_SGL(-1.0 / 4.0), + FL2FXCONST_SGL(-1.0 / 5.0), FL2FXCONST_SGL(-1.0 / 6.0), + FL2FXCONST_SGL(-1.0 / 7.0), FL2FXCONST_SGL(-1.0 / 8.0), + FL2FXCONST_SGL(-1.0 / 9.0), FL2FXCONST_SGL(-1.0 / 10.0)}; +#endif /* LDCOEFF_16BIT */ + +/***************************************************************************** + + functionname: invSqrtNorm2 + description: delivers 1/sqrt(op) normalized to .5...1 and the shift value +of the OUTPUT + +*****************************************************************************/ +#define SQRT_BITS 7 +#define SQRT_VALUES (128 + 2) +#define SQRT_BITS_MASK 0x7f +#define SQRT_FRACT_BITS_MASK 0x007FFFFF + +extern const FIXP_DBL invSqrtTab[SQRT_VALUES]; + +/* + * Hardware specific implementations + */ + +#if defined(__x86__) +#include "x86/fixpoint_math_x86.h" +#endif /* target architecture selector */ + +/* + * Fallback implementations + */ +#if !defined(FUNCTION_fIsLessThan) +/** + * \brief Compares two fixpoint values incl. scaling. + * \param a_m mantissa of the first input value. + * \param a_e exponent of the first input value. + * \param b_m mantissa of the second input value. + * \param b_e exponent of the second input value. + * \return non-zero if (a_m*2^a_e) < (b_m*2^b_e), 0 otherwise + */ +FDK_INLINE INT fIsLessThan(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e) { + INT n; + + n = fixnorm_D(a_m); + a_m <<= n; + a_e -= n; + + n = fixnorm_D(b_m); + b_m <<= n; + b_e -= n; + + if (a_m == (FIXP_DBL)0) a_e = b_e; + if (b_m == (FIXP_DBL)0) b_e = a_e; + + if (a_e > b_e) { + return ((b_m >> fMin(a_e - b_e, DFRACT_BITS - 1)) > a_m); + } else { + return ((a_m >> fMin(b_e - a_e, DFRACT_BITS - 1)) < b_m); + } +} + +FDK_INLINE INT fIsLessThan(FIXP_SGL a_m, INT a_e, FIXP_SGL b_m, INT b_e) { + INT n; + + n = fixnorm_S(a_m); + a_m <<= n; + a_e -= n; + + n = fixnorm_S(b_m); + b_m <<= n; + b_e -= n; + + if (a_m == (FIXP_SGL)0) a_e = b_e; + if (b_m == (FIXP_SGL)0) b_e = a_e; + + if (a_e > b_e) { + return ((b_m >> fMin(a_e - b_e, FRACT_BITS - 1)) > a_m); + } else { + return ((a_m >> fMin(b_e - a_e, FRACT_BITS - 1)) < b_m); + } +} +#endif + +/** + * \brief deprecated. Use fLog2() instead. + */ +#define CalcLdData(op) fLog2(op, 0) + +void LdDataVector(FIXP_DBL *srcVector, FIXP_DBL *destVector, INT number); + +extern const UINT exp2_tab_long[32]; +extern const UINT exp2w_tab_long[32]; +extern const UINT exp2x_tab_long[32]; + +LNK_SECTION_CODE_L1 +FDK_INLINE FIXP_DBL CalcInvLdData(const FIXP_DBL x) { + int set_zero = (x < FL2FXCONST_DBL(-31.0 / 64.0)) ? 0 : 1; + int set_max = (x >= FL2FXCONST_DBL(31.0 / 64.0)) | (x == FL2FXCONST_DBL(0.0)); + + FIXP_SGL frac = (FIXP_SGL)((LONG)x & 0x3FF); + UINT index3 = (UINT)(LONG)(x >> 10) & 0x1F; + UINT index2 = (UINT)(LONG)(x >> 15) & 0x1F; + UINT index1 = (UINT)(LONG)(x >> 20) & 0x1F; + int exp = fMin(31, ((x > FL2FXCONST_DBL(0.0f)) ? (31 - (int)(x >> 25)) + : (int)(-(x >> 25)))); + + UINT lookup1 = exp2_tab_long[index1] * set_zero; + UINT lookup2 = exp2w_tab_long[index2]; + UINT lookup3 = exp2x_tab_long[index3]; + UINT lookup3f = + lookup3 + (UINT)(LONG)fMultDiv2((FIXP_DBL)(0x0016302F), (FIXP_SGL)frac); + + UINT lookup12 = (UINT)(LONG)fMult((FIXP_DBL)lookup1, (FIXP_DBL)lookup2); + UINT lookup = (UINT)(LONG)fMult((FIXP_DBL)lookup12, (FIXP_DBL)lookup3f); + + FIXP_DBL retVal = (lookup << 3) >> exp; + + if (set_max) { + retVal = (FIXP_DBL)MAXVAL_DBL; + } + + return retVal; +} + +void InitLdInt(); +FIXP_DBL CalcLdInt(INT i); + +extern const USHORT sqrt_tab[49]; + +inline FIXP_DBL sqrtFixp_lookup(FIXP_DBL x) { + UINT y = (INT)x; + UCHAR is_zero = (y == 0); + INT zeros = fixnormz_D(y) & 0x1e; + y <<= zeros; + UINT idx = (y >> 26) - 16; + USHORT frac = (y >> 10) & 0xffff; + USHORT nfrac = 0xffff ^ frac; + UINT t = (UINT)nfrac * sqrt_tab[idx] + (UINT)frac * sqrt_tab[idx + 1]; + t = t >> (zeros >> 1); + return (is_zero ? 0 : t); +} + +inline FIXP_DBL sqrtFixp_lookup(FIXP_DBL x, INT *x_e) { + UINT y = (INT)x; + INT e; + + if (x == (FIXP_DBL)0) { + return x; + } + + /* Normalize */ + e = fixnormz_D(y); + y <<= e; + e = *x_e - e + 2; + + /* Correct odd exponent. */ + if (e & 1) { + y >>= 1; + e++; + } + /* Get square root */ + UINT idx = (y >> 26) - 16; + USHORT frac = (y >> 10) & 0xffff; + USHORT nfrac = 0xffff ^ frac; + UINT t = (UINT)nfrac * sqrt_tab[idx] + (UINT)frac * sqrt_tab[idx + 1]; + + /* Write back exponent */ + *x_e = e >> 1; + return (FIXP_DBL)(LONG)(t >> 1); +} + +void InitInvSqrtTab(); + +#ifndef FUNCTION_invSqrtNorm2 +/** + * \brief calculate 1.0/sqrt(op) + * \param op_m mantissa of input value. + * \param result_e pointer to return the exponent of the result + * \return mantissa of the result + */ +/***************************************************************************** + delivers 1/sqrt(op) normalized to .5...1 and the shift value of the OUTPUT, + i.e. the denormalized result is 1/sqrt(op) = invSqrtNorm(op) * 2^(shift) + uses Newton-iteration for approximation + Q(n+1) = Q(n) + Q(n) * (0.5 - 2 * V * Q(n)^2) + with Q = 0.5* V ^-0.5; 0.5 <= V < 1.0 +*****************************************************************************/ +static FDK_FORCEINLINE FIXP_DBL invSqrtNorm2(FIXP_DBL op, INT *shift) { + FIXP_DBL val = op; + FIXP_DBL reg1, reg2; + + if (val == FL2FXCONST_DBL(0.0)) { + *shift = 16; + return ((LONG)MAXVAL_DBL); /* maximum positive value */ + } + +#define INVSQRTNORM2_LINEAR_INTERPOLATE +#define INVSQRTNORM2_LINEAR_INTERPOLATE_HQ + + /* normalize input, calculate shift value */ + FDK_ASSERT(val > FL2FXCONST_DBL(0.0)); + *shift = fNormz(val) - 1; /* CountLeadingBits() is not necessary here since + test value is always > 0 */ + val <<= *shift; /* normalized input V */ + *shift += 2; /* bias for exponent */ + +#if defined(INVSQRTNORM2_LINEAR_INTERPOLATE) + INT index = + (INT)(val >> (DFRACT_BITS - 1 - (SQRT_BITS + 1))) & SQRT_BITS_MASK; + FIXP_DBL Fract = + (FIXP_DBL)(((INT)val & SQRT_FRACT_BITS_MASK) << (SQRT_BITS + 1)); + FIXP_DBL diff = invSqrtTab[index + 1] - invSqrtTab[index]; + reg1 = invSqrtTab[index] + (fMultDiv2(diff, Fract) << 1); +#if defined(INVSQRTNORM2_LINEAR_INTERPOLATE_HQ) + /* reg1 = t[i] + (t[i+1]-t[i])*fract ... already computed ... + + (1-fract)fract*(t[i+2]-t[i+1])/2 */ + if (Fract != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + Fract = fMultDiv2(Fract, (FIXP_DBL)((ULONG)0x80000000 - (ULONG)Fract)) << 1; + diff = diff - (invSqrtTab[index + 2] - invSqrtTab[index + 1]); + reg1 = fMultAddDiv2(reg1, Fract, diff); + } +#endif /* INVSQRTNORM2_LINEAR_INTERPOLATE_HQ */ +#else +#error \ + "Either define INVSQRTNORM2_NEWTON_ITERATE or INVSQRTNORM2_LINEAR_INTERPOLATE" +#endif + /* calculate the output exponent = input exp/2 */ + if (*shift & 0x00000001) { /* odd shift values ? */ + /* Note: Do not use rounded value 0x5A82799A to avoid overflow with + * shift-by-2 */ + reg2 = (FIXP_DBL)0x5A827999; + /* FL2FXCONST_DBL(0.707106781186547524400844362104849f);*/ /* 1/sqrt(2); + */ + reg1 = fMultDiv2(reg1, reg2) << 2; + } + + *shift = *shift >> 1; + + return (reg1); +} +#endif /* FUNCTION_invSqrtNorm2 */ + +#ifndef FUNCTION_sqrtFixp +static FDK_FORCEINLINE FIXP_DBL sqrtFixp(FIXP_DBL op) { + INT tmp_exp = 0; + FIXP_DBL tmp_inv = invSqrtNorm2(op, &tmp_exp); + + FDK_ASSERT(tmp_exp > 0); + return ((FIXP_DBL)(fMultDiv2((op << (tmp_exp - 1)), tmp_inv) << 2)); +} +#endif /* FUNCTION_sqrtFixp */ + +#ifndef FUNCTION_invFixp +/** + * \brief calculate 1.0/op + * \param op mantissa of the input value. + * \return mantissa of the result with implicit exponent of 31 + * \exceptions are provided for op=0,1 setting max. positive value + */ +static inline FIXP_DBL invFixp(FIXP_DBL op) { + if ((op == (FIXP_DBL)0x00000000) || (op == (FIXP_DBL)0x00000001)) { + return ((LONG)MAXVAL_DBL); + } + INT tmp_exp; + FIXP_DBL tmp_inv = invSqrtNorm2(op, &tmp_exp); + FDK_ASSERT((31 - (2 * tmp_exp + 1)) >= 0); + int shift = 31 - (2 * tmp_exp + 1); + tmp_inv = fPow2Div2(tmp_inv); + if (shift) { + tmp_inv = ((tmp_inv >> (shift - 1)) + (FIXP_DBL)1) >> 1; + } + return tmp_inv; +} + +/** + * \brief calculate 1.0/(op_m * 2^op_e) + * \param op_m mantissa of the input value. + * \param op_e pointer into were the exponent of the input value is stored, and + * the result will be stored into. + * \return mantissa of the result + */ +static inline FIXP_DBL invFixp(FIXP_DBL op_m, int *op_e) { + if ((op_m == (FIXP_DBL)0x00000000) || (op_m == (FIXP_DBL)0x00000001)) { + *op_e = 31 - *op_e; + return ((LONG)MAXVAL_DBL); + } + + INT tmp_exp; + FIXP_DBL tmp_inv = invSqrtNorm2(op_m, &tmp_exp); + + *op_e = (tmp_exp << 1) - *op_e + 1; + return fPow2Div2(tmp_inv); +} +#endif /* FUNCTION_invFixp */ + +#ifndef FUNCTION_schur_div + +/** + * \brief Divide two FIXP_DBL values with given precision. + * \param num dividend + * \param denum divisor + * \param count amount of significant bits of the result (starting to the MSB) + * \return num/divisor + */ + +FIXP_DBL schur_div(FIXP_DBL num, FIXP_DBL denum, INT count); + +#endif /* FUNCTION_schur_div */ + +FIXP_DBL mul_dbl_sgl_rnd(const FIXP_DBL op1, const FIXP_SGL op2); + +#ifndef FUNCTION_fMultNorm +/** + * \brief multiply two values with normalization, thus max precision. + * Author: Robert Weidner + * + * \param f1 first factor + * \param f2 second factor + * \param result_e pointer to an INT where the exponent of the result is stored + * into + * \return mantissa of the product f1*f2 + */ +FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2, INT *result_e); + +/** + * \brief Multiply 2 values using maximum precision. The exponent of the result + * is 0. + * \param f1_m mantissa of factor 1 + * \param f2_m mantissa of factor 2 + * \return mantissa of the result with exponent equal to 0 + */ +inline FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2) { + FIXP_DBL m; + INT e; + + m = fMultNorm(f1, f2, &e); + + m = scaleValueSaturate(m, e); + + return m; +} + +/** + * \brief Multiply 2 values with exponent and use given exponent for the + * mantissa of the result. + * \param f1_m mantissa of factor 1 + * \param f1_e exponent of factor 1 + * \param f2_m mantissa of factor 2 + * \param f2_e exponent of factor 2 + * \param result_e exponent for the returned mantissa of the result + * \return mantissa of the result with exponent equal to result_e + */ +inline FIXP_DBL fMultNorm(FIXP_DBL f1_m, INT f1_e, FIXP_DBL f2_m, INT f2_e, + INT result_e) { + FIXP_DBL m; + INT e; + + m = fMultNorm(f1_m, f2_m, &e); + + m = scaleValueSaturate(m, e + f1_e + f2_e - result_e); + + return m; +} +#endif /* FUNCTION_fMultNorm */ + +#ifndef FUNCTION_fMultI +/** + * \brief Multiplies a fractional value and a integer value and performs + * rounding to nearest + * \param a fractional value + * \param b integer value + * \return integer value + */ +inline INT fMultI(FIXP_DBL a, INT b) { + FIXP_DBL m, mi; + INT m_e; + + m = fMultNorm(a, (FIXP_DBL)b, &m_e); + + if (m_e < (INT)0) { + if (m_e > (INT)-DFRACT_BITS) { + m = m >> ((-m_e) - 1); + mi = (m + (FIXP_DBL)1) >> 1; + } else { + mi = (FIXP_DBL)0; + } + } else { + mi = scaleValueSaturate(m, m_e); + } + + return ((INT)mi); +} +#endif /* FUNCTION_fMultI */ + +#ifndef FUNCTION_fMultIfloor +/** + * \brief Multiplies a fractional value and a integer value and performs floor + * rounding + * \param a fractional value + * \param b integer value + * \return integer value + */ +inline INT fMultIfloor(FIXP_DBL a, INT b) { + FIXP_DBL m, mi; + INT m_e; + + m = fMultNorm(a, (FIXP_DBL)b, &m_e); + + if (m_e < (INT)0) { + if (m_e > (INT)-DFRACT_BITS) { + mi = m >> (-m_e); + } else { + mi = (FIXP_DBL)0; + if (m < (FIXP_DBL)0) { + mi = (FIXP_DBL)-1; + } + } + } else { + mi = scaleValueSaturate(m, m_e); + } + + return ((INT)mi); +} +#endif /* FUNCTION_fMultIfloor */ + +#ifndef FUNCTION_fMultIceil +/** + * \brief Multiplies a fractional value and a integer value and performs ceil + * rounding + * \param a fractional value + * \param b integer value + * \return integer value + */ +inline INT fMultIceil(FIXP_DBL a, INT b) { + FIXP_DBL m, mi; + INT m_e; + + m = fMultNorm(a, (FIXP_DBL)b, &m_e); + + if (m_e < (INT)0) { + if (m_e > (INT) - (DFRACT_BITS - 1)) { + mi = (m >> (-m_e)); + if ((LONG)m & ((1 << (-m_e)) - 1)) { + mi = mi + (FIXP_DBL)1; + } + } else { + if (m > (FIXP_DBL)0) { + mi = (FIXP_DBL)1; + } else { + if ((m_e == -(DFRACT_BITS - 1)) && (m == (FIXP_DBL)MINVAL_DBL)) { + mi = (FIXP_DBL)-1; + } else { + mi = (FIXP_DBL)0; + } + } + } + } else { + mi = scaleValueSaturate(m, m_e); + } + + return ((INT)mi); +} +#endif /* FUNCTION_fMultIceil */ + +#ifndef FUNCTION_fDivNorm +/** + * \brief Divide 2 FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denominator + * \param result_e pointer to an INT where the exponent of the result is stored + * into + * \return num/denum with exponent = *result_e + */ +FIXP_DBL fDivNorm(FIXP_DBL num, FIXP_DBL denom, INT *result_e); + +/** + * \brief Divide 2 positive FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denominator + * \return num/denum with exponent = 0 + */ +FIXP_DBL fDivNorm(FIXP_DBL num, FIXP_DBL denom); + +/** + * \brief Divide 2 signed FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denominator + * \param result_e pointer to an INT where the exponent of the result is stored + * into + * \return num/denum with exponent = *result_e + */ +FIXP_DBL fDivNormSigned(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e); + +/** + * \brief Divide 2 signed FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denominator + * \return num/denum with exponent = 0 + */ +FIXP_DBL fDivNormSigned(FIXP_DBL num, FIXP_DBL denom); +#endif /* FUNCTION_fDivNorm */ + +/** + * \brief Adjust mantissa to exponent -1 + * \param a_m mantissa of value to be adjusted + * \param pA_e pointer to the exponen of a_m + * \return adjusted mantissa + */ +inline FIXP_DBL fAdjust(FIXP_DBL a_m, INT *pA_e) { + INT shift; + + shift = fNorm(a_m) - 1; + *pA_e -= shift; + + return scaleValue(a_m, shift); +} + +#ifndef FUNCTION_fAddNorm +/** + * \brief Add two values with normalization + * \param a_m mantissa of first summand + * \param a_e exponent of first summand + * \param a_m mantissa of second summand + * \param a_e exponent of second summand + * \param pResult_e pointer to where the exponent of the result will be stored + * to. + * \return mantissa of result + */ +inline FIXP_DBL fAddNorm(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e, + INT *pResult_e) { + INT result_e; + FIXP_DBL result_m; + + /* If one of the summands is zero, return the other. + This is necessary for the summation of a very small number to zero */ + if (a_m == (FIXP_DBL)0) { + *pResult_e = b_e; + return b_m; + } + if (b_m == (FIXP_DBL)0) { + *pResult_e = a_e; + return a_m; + } + + a_m = fAdjust(a_m, &a_e); + b_m = fAdjust(b_m, &b_e); + + if (a_e > b_e) { + result_m = a_m + (b_m >> fMin(a_e - b_e, DFRACT_BITS - 1)); + result_e = a_e; + } else { + result_m = (a_m >> fMin(b_e - a_e, DFRACT_BITS - 1)) + b_m; + result_e = b_e; + } + + *pResult_e = result_e; + return result_m; +} + +inline FIXP_DBL fAddNorm(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e, + INT result_e) { + FIXP_DBL result_m; + + a_m = scaleValue(a_m, a_e - result_e); + b_m = scaleValue(b_m, b_e - result_e); + + result_m = a_m + b_m; + + return result_m; +} +#endif /* FUNCTION_fAddNorm */ + +/** + * \brief Divide 2 FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denomintator + * \return num/denum with exponent = 0 + */ +FIXP_DBL fDivNormHighPrec(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e); + +#ifndef FUNCTION_fPow +/** + * \brief return 2 ^ (exp_m * 2^exp_e) + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \param result_e pointer to a INT where the exponent of the result will be + * stored into + * \return mantissa of the result + */ +FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e, INT *result_e); + +/** + * \brief return 2 ^ (exp_m * 2^exp_e). This version returns only the mantissa + * with implicit exponent of zero. + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \return mantissa of the result + */ +FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e); + +/** + * \brief return x ^ (exp_m * 2^exp_e), where log2(x) = baseLd_m * 2^(baseLd_e). + * This saves the need to compute log2() of constant values (when x is a + * constant). + * \param baseLd_m mantissa of log2() of x. + * \param baseLd_e exponent of log2() of x. + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \param result_e pointer to a INT where the exponent of the result will be + * stored into + * \return mantissa of the result + */ +FIXP_DBL fLdPow(FIXP_DBL baseLd_m, INT baseLd_e, FIXP_DBL exp_m, INT exp_e, + INT *result_e); + +/** + * \brief return x ^ (exp_m * 2^exp_e), where log2(x) = baseLd_m * 2^(baseLd_e). + * This saves the need to compute log2() of constant values (when x is a + * constant). This version does not return an exponent, which is + * implicitly 0. + * \param baseLd_m mantissa of log2() of x. + * \param baseLd_e exponent of log2() of x. + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \return mantissa of the result + */ +FIXP_DBL fLdPow(FIXP_DBL baseLd_m, INT baseLd_e, FIXP_DBL exp_m, INT exp_e); + +/** + * \brief return (base_m * 2^base_e) ^ (exp * 2^exp_e). Use fLdPow() instead + * whenever possible. + * \param base_m mantissa of the base. + * \param base_e exponent of the base. + * \param exp_m mantissa of power to be calculated of the base. + * \param exp_e exponent of power to be calculated of the base. + * \param result_e pointer to a INT where the exponent of the result will be + * stored into. + * \return mantissa of the result. + */ +FIXP_DBL fPow(FIXP_DBL base_m, INT base_e, FIXP_DBL exp_m, INT exp_e, + INT *result_e); + +/** + * \brief return (base_m * 2^base_e) ^ N + * \param base_m mantissa of the base. Must not be negative. + * \param base_e exponent of the base + * \param N power to be calculated of the base + * \param result_e pointer to a INT where the exponent of the result will be + * stored into + * \return mantissa of the result + */ +FIXP_DBL fPowInt(FIXP_DBL base_m, INT base_e, INT N, INT *result_e); +#endif /* #ifndef FUNCTION_fPow */ + +#ifndef FUNCTION_fLog2 +/** + * \brief Calculate log(argument)/log(2) (logarithm with base 2). deprecated. + * Use fLog2() instead. + * \param arg mantissa of the argument + * \param arg_e exponent of the argument + * \param result_e pointer to an INT to store the exponent of the result + * \return the mantissa of the result. + * \param + */ +FIXP_DBL CalcLog2(FIXP_DBL arg, INT arg_e, INT *result_e); + +/** + * \brief calculate logarithm of base 2 of x_m * 2^(x_e) + * \param x_m mantissa of the input value. + * \param x_e exponent of the input value. + * \param pointer to an INT where the exponent of the result is returned into. + * \return mantissa of the result. + */ +FDK_INLINE FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e, INT *result_e) { + FIXP_DBL result_m; + + /* Short cut for zero and negative numbers. */ + if (x_m <= FL2FXCONST_DBL(0.0f)) { + *result_e = DFRACT_BITS - 1; + return FL2FXCONST_DBL(-1.0f); + } + + /* Calculate log2() */ + { + FIXP_DBL x2_m; + + /* Move input value x_m * 2^x_e toward 1.0, where the taylor approximation + of the function log(1-x) centered at 0 is most accurate. */ + { + INT b_norm; + + b_norm = fNormz(x_m) - 1; + x2_m = x_m << b_norm; + x_e = x_e - b_norm; + } + + /* map x from log(x) domain to log(1-x) domain. */ + x2_m = -(x2_m + FL2FXCONST_DBL(-1.0)); + + /* Taylor polynomial approximation of ln(1-x) */ + { + FIXP_DBL px2_m; + result_m = FL2FXCONST_DBL(0.0); + px2_m = x2_m; + for (int i = 0; i < LD_PRECISION; i++) { + result_m = fMultAddDiv2(result_m, ldCoeff[i], px2_m); + px2_m = fMult(px2_m, x2_m); + } + } + /* Multiply result with 1/ln(2) = 1.0 + 0.442695040888 (get log2(x) from + * ln(x) result). */ + result_m = + fMultAddDiv2(result_m, result_m, + FL2FXCONST_DBL(2.0 * 0.4426950408889634073599246810019)); + + /* Add exponent part. log2(x_m * 2^x_e) = log2(x_m) + x_e */ + if (x_e != 0) { + int enorm; + + enorm = DFRACT_BITS - fNorm((FIXP_DBL)x_e); + /* The -1 in the right shift of result_m compensates the fMultDiv2() above + * in the taylor polynomial evaluation loop.*/ + result_m = (result_m >> (enorm - 1)) + + ((FIXP_DBL)x_e << (DFRACT_BITS - 1 - enorm)); + + *result_e = enorm; + } else { + /* 1 compensates the fMultDiv2() above in the taylor polynomial evaluation + * loop.*/ + *result_e = 1; + } + } + + return result_m; +} + +/** + * \brief calculate logarithm of base 2 of x_m * 2^(x_e) + * \param x_m mantissa of the input value. + * \param x_e exponent of the input value. + * \return mantissa of the result with implicit exponent of LD_DATA_SHIFT. + */ +FDK_INLINE FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e) { + if (x_m <= FL2FXCONST_DBL(0.0f)) { + x_m = FL2FXCONST_DBL(-1.0f); + } else { + INT result_e; + x_m = fLog2(x_m, x_e, &result_e); + x_m = scaleValue(x_m, result_e - LD_DATA_SHIFT); + } + return x_m; +} + +#endif /* FUNCTION_fLog2 */ + +#ifndef FUNCTION_fAddSaturate +/** + * \brief Add with saturation of the result. + * \param a first summand + * \param b second summand + * \return saturated sum of a and b. + */ +inline FIXP_SGL fAddSaturate(const FIXP_SGL a, const FIXP_SGL b) { + LONG sum; + + sum = (LONG)(SHORT)a + (LONG)(SHORT)b; + sum = fMax(fMin((INT)sum, (INT)MAXVAL_SGL), (INT)MINVAL_SGL); + return (FIXP_SGL)(SHORT)sum; +} + +/** + * \brief Add with saturation of the result. + * \param a first summand + * \param b second summand + * \return saturated sum of a and b. + */ +inline FIXP_DBL fAddSaturate(const FIXP_DBL a, const FIXP_DBL b) { + LONG sum; + + sum = (LONG)(a >> 1) + (LONG)(b >> 1); + sum = fMax(fMin((INT)sum, (INT)(MAXVAL_DBL >> 1)), (INT)(MINVAL_DBL >> 1)); + return (FIXP_DBL)(LONG)(sum << 1); +} +#endif /* FUNCTION_fAddSaturate */ + +INT fixp_floorToInt(FIXP_DBL f_inp, INT sf); +FIXP_DBL fixp_floor(FIXP_DBL f_inp, INT sf); + +INT fixp_ceilToInt(FIXP_DBL f_inp, INT sf); +FIXP_DBL fixp_ceil(FIXP_DBL f_inp, INT sf); + +INT fixp_truncateToInt(FIXP_DBL f_inp, INT sf); +FIXP_DBL fixp_truncate(FIXP_DBL f_inp, INT sf); + +INT fixp_roundToInt(FIXP_DBL f_inp, INT sf); +FIXP_DBL fixp_round(FIXP_DBL f_inp, INT sf); + +/***************************************************************************** + + array for 1/n, n=1..80 + +****************************************************************************/ + +extern const FIXP_DBL invCount[80]; + +LNK_SECTION_INITCODE +inline void InitInvInt(void) {} + +/** + * \brief Calculate the value of 1/i where i is a integer value. It supports + * input values from 1 upto (80-1). + * \param intValue Integer input value. + * \param FIXP_DBL representation of 1/intValue + */ +inline FIXP_DBL GetInvInt(int intValue) { + return invCount[fMin(fMax(intValue, 0), 80 - 1)]; +} + +#endif /* FIXPOINT_MATH_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/huff_nodes.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/huff_nodes.h new file mode 100644 index 0000000000000..0dda5d36d78cc --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/huff_nodes.h @@ -0,0 +1,258 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Omer Osman + + Description: MPEG-D SAC/USAC/SAOC Huffman Part0 Tables + +*******************************************************************************/ + +#ifndef HUFF_NODES_H +#define HUFF_NODES_H + +#include "genericStds.h" + +typedef struct { + SHORT nodeTab[39][2]; + +} HUFF_RES_NODES; + +/* 1D Nodes */ +typedef struct { + SHORT nodeTab[30][2]; + +} HUFF_CLD_NOD_1D; + +typedef struct { + SHORT nodeTab[7][2]; + +} HUFF_ICC_NOD_1D; + +typedef struct { + SHORT nodeTab[50][2]; + +} HUFF_CPC_NOD_1D; + +typedef struct { + SHORT nodeTab[15][2]; + +} HUFF_OLD_NOD_1D; + +typedef struct { + SHORT nodeTab[63][2]; + +} HUFF_NRG_NOD_1D; + +/* 2D Nodes */ +typedef struct { + SHORT lav3[15][2]; + SHORT lav5[35][2]; + SHORT lav7[63][2]; + SHORT lav9[99][2]; + +} HUFF_CLD_NOD_2D; + +typedef struct { + SHORT lav1[3][2]; + SHORT lav3[15][2]; + SHORT lav5[35][2]; + SHORT lav7[63][2]; + +} HUFF_ICC_NOD_2D; + +typedef struct { + SHORT lav3[15][2]; + SHORT lav6[48][2]; + SHORT lav9[99][2]; + SHORT lav12[168][2]; + +} HUFF_OLD_NOD_2D; + +typedef struct { + SHORT lav3[15][2]; + SHORT lav5[35][2]; + SHORT lav7[63][2]; + SHORT lav9[99][2]; + +} HUFF_NRG_NOD_2D_df; + +typedef struct { + SHORT lav3[15][2]; + SHORT lav6[48][2]; + SHORT lav9[99][2]; + SHORT lav12[168][2]; + +} HUFF_NRG_NOD_2D_dt; + +typedef struct { + HUFF_NRG_NOD_2D_df df[2]; + HUFF_NRG_NOD_2D_dt dt[2]; + HUFF_NRG_NOD_2D_df dp[2]; + +} HUFF_NRG_NOD_2D; + +/* Complete bs Parameter Nodes */ +typedef struct { + const HUFF_CLD_NOD_1D *h1D[3]; + const HUFF_CLD_NOD_2D *h2D[3][2]; + +} HUFF_CLD_NODES; + +typedef struct { + const HUFF_ICC_NOD_1D *h1D[3]; + const HUFF_ICC_NOD_2D *h2D[3][2]; + +} HUFF_ICC_NODES; + +typedef struct { + const HUFF_OLD_NOD_1D *h1D[3]; + const HUFF_OLD_NOD_2D *h2D[3][2]; + +} HUFF_OLD_NODES; + +typedef struct { + const HUFF_NRG_NOD_1D *h1D[3]; + const HUFF_NRG_NOD_2D *h2D; + +} HUFF_NRG_NODES; + +/* parameter instance */ +typedef struct { + SHORT cld[30][2]; + SHORT icc[7][2]; + SHORT ipd[7][2]; + SHORT old[15][2]; + SHORT nrg[63][2]; +} HUFF_PT0_NODES; + +typedef struct { + SHORT nodeTab[3][2]; + +} HUFF_LAV_NODES; + +/* USAC specific */ +typedef struct { + SHORT nodeTab[7][2]; + +} HUFF_IPD_NOD_1D; + +typedef struct { + SHORT lav1[3][2]; + SHORT lav3[15][2]; + SHORT lav5[35][2]; + SHORT lav7[63][2]; + +} HUFF_IPD_NOD_2D; + +typedef struct { + HUFF_IPD_NOD_1D h1D[3]; + HUFF_IPD_NOD_2D h2D[3][2]; + +} HUFF_IPD_NODES; + +/* non-lossy coding decoder */ +extern const HUFF_PT0_NODES FDK_huffPart0Nodes; +extern const HUFF_LAV_NODES FDK_huffLavIdxNodes; + +extern const HUFF_ICC_NODES FDK_huffICCNodes; +extern const HUFF_CLD_NODES FDK_huffCLDNodes; +extern const HUFF_RES_NODES FDK_huffReshapeNodes; + +extern const HUFF_OLD_NODES huffOLDNodes; + +extern const HUFF_IPD_NODES FDK_huffIPDNodes; + +#endif /* HUFF_NODES_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mdct.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mdct.h new file mode 100644 index 0000000000000..e7cf3ad664a2e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mdct.h @@ -0,0 +1,251 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander, Josef Hoepfl, Youliy Ninov, Daniel Hagel + + Description: MDCT/MDST routines + +*******************************************************************************/ + +#ifndef MDCT_H +#define MDCT_H + +#include "common_fix.h" + +#define MDCT_OUT_HEADROOM 2 /* Output additional headroom */ + +#define PCM_OUT_BITS DFRACT_BITS +#define PCM_OUT_HEADROOM 8 /* Must have the same values as DMXH_HEADROOM */ + +#define MDCT_OUTPUT_SCALE (-MDCT_OUT_HEADROOM + (DFRACT_BITS - PCM_OUT_BITS)) +/* Refer to "Output word length" in ISO/IEC 14496-3:2008(E) 23.2.3.6 */ +#define MDCT_OUTPUT_GAIN 16 + +#define IMDCT_SCALE(x, s) \ + SATURATE_RIGHT_SHIFT((x), ((s) + MDCT_OUTPUT_SCALE), PCM_OUT_BITS) +#define IMDCT_SCALE_DBL(x) (FIXP_DBL)(x) +#define IMDCT_SCALE_DBL_LSH1(x) SATURATE_LEFT_SHIFT_ALT((x), 1, DFRACT_BITS) + +#define MLT_FLAG_CURR_ALIAS_SYMMETRY 1 + +typedef enum { + BLOCK_LONG = 0, /* normal long block */ + BLOCK_START, /* long start block */ + BLOCK_SHORT, /* 8 short blocks sequence */ + BLOCK_STOP /* long stop block*/ +} BLOCK_TYPE; + +typedef enum { SHAPE_SINE = 0, SHAPE_KBD, SHAPE_LOL } WINDOW_SHAPE; + +/** + * \brief MDCT persistent data + */ +typedef struct { + union { + FIXP_DBL *freq; + FIXP_DBL *time; + } overlap; /**< Pointer to overlap memory */ + + const FIXP_WTP *prev_wrs; /**< pointer to previous right window slope */ + int prev_tl; /**< previous transform length */ + int prev_nr; /**< previous right window offset */ + int prev_fr; /**< previous right window slope length */ + int ov_offset; /**< overlap time data fill level */ + int ov_size; /**< Overlap buffer size in words */ + + int prevAliasSymmetry; + int prevPrevAliasSymmetry; + + FIXP_DBL *pFacZir; + FIXP_DBL *pAsymOvlp; /**< pointer to asymmetric overlap (used for stereo LPD + transition) */ +} mdct_t; + +typedef mdct_t *H_MDCT; + +/** + * \brief Initialize as valid MDCT handle + * + * \param hMdct handle of an allocated MDCT handle. + * \param overlap pointer to FIXP_DBL overlap buffer. + * \param overlapBufferSize size in FIXP_DBLs of the given overlap buffer. + */ +void mdct_init(H_MDCT hMdct, FIXP_DBL *overlap, INT overlapBufferSize); + +/** + * \brief perform MDCT transform (time domain to frequency domain) with given + * parameters. + * + * \param hMdct handle of an allocated MDCT handle. + * \param pTimeData pointer to input time domain signal + * \param noInSamples number of input samples + * \param mdctData pointer to where the resulting MDCT spectrum will be stored + * into. + * \param nSpec number of spectra + * \param pMdctData_e pointer to the input data exponent. Updated accordingly on + * return for output data. + * \return number of input samples processed. + */ +INT mdct_block(H_MDCT hMdct, const INT_PCM *pTimeData, const INT noInSamples, + FIXP_DBL *RESTRICT mdctData, const INT nSpec, const INT tl, + const FIXP_WTP *pRightWindowPart, const INT fr, + SHORT *pMdctData_e); + +/** + * \brief add/multiply 2/N transform gain and MPEG4 part 3 defined output gain + * (see definition of MDCT_OUTPUT_GAIN) to given mantissa factor and exponent. + * \param pGain pointer to the mantissa of a gain factor to be applied to IMDCT + * data. + * \param pExponent pointer to the exponent of a gain factor to be applied to + * IMDCT data. + * \param tl length of the IMDCT where the gain *pGain * (2 ^ *pExponent) will + * be applied to. + */ +void imdct_gain(FIXP_DBL *pGain, int *pExponent, int tl); + +/** + * \brief drain buffered output samples into given buffer. Changes the MDCT + * state. + */ +INT imdct_drain(H_MDCT hMdct, FIXP_DBL *pTimeData, INT nrSamplesRoom); + +/** + * \brief Copy overlap time domain data to given buffer. Does not change the + * MDCT state. + * \return number of actually copied samples (ov + nr). + */ +INT imdct_copy_ov_and_nr(H_MDCT hMdct, FIXP_DBL *pTimeData, INT nrSamples); + +/** + * \brief Adapt MDCT parameters for non-matching window slopes. + * \param hMdct handle of an allocated MDCT handle. + * \param pfl pointer to left overlap window side length. + * \param pnl pointer to length of the left n part of the window. + * \param tl transform length. + * \param wls pointer to the left side overlap window coefficients. + * \param noOutSamples desired number of output samples. + */ +void imdct_adapt_parameters(H_MDCT hMdct, int *pfl, int *pnl, int tl, + const FIXP_WTP *wls, int noOutSamples); + +/** + * \brief perform several inverse MLT transforms (frequency domain to time + * domain) with given parameters. + * + * \param hMdct handle of an allocated MDCT handle. + * \param output pointer to where the output time domain signal will be stored + * into. + * \param spectrum pointer to the input MDCT spectra. + * \param scalefactors exponents of the input spectrum. + * \param nSpec number of MDCT spectrums. + * \param noOutSamples desired number of output samples. + * \param tl transform length. + * \param wls pointer to the left side overlap window coefficients. + * \param fl left overlap window side length. + * \param wrs pointer to the right side overlap window coefficients of all + * individual IMDCTs. + * \param fr right overlap window side length of all individual IMDCTs. + * \param gain factor to apply to output samples (if != 0). + * \param flags flags controlling the type of transform + * \return number of output samples returned. + */ +INT imlt_block(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *spectrum, + const SHORT scalefactor[], const INT nSpec, + const INT noOutSamples, const INT tl, const FIXP_WTP *wls, + INT fl, const FIXP_WTP *wrs, const INT fr, FIXP_DBL gain, + int flags); + +#endif /* MDCT_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/abs_mips.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/abs_mips.h new file mode 100644 index 0000000000000..5644bc0746579 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/abs_mips.h @@ -0,0 +1,125 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(ABS_MIPS_H) +#define ABS_MIPS_H + +#if defined(__mips__) + +#if defined(__GNUC__) && defined(__mips__) + +#if defined(__mips_dsp) && !defined(__mips16) +#define FUNCTION_fixabs_D +#define FUNCTION_fixabs_I +#define FUNCTION_fixabs_S +inline FIXP_DBL fixabs_D(FIXP_DBL x) { return __builtin_mips_absq_s_w(x); } +inline FIXP_SGL fixabs_S(FIXP_SGL x) { + return ((x) > (FIXP_SGL)(0)) ? (x) : -(x); +} +inline INT fixabs_I(INT x) { return __builtin_mips_absq_s_w(x); } +#endif /* __mips_dsp */ + +#endif /* defined(__GNUC__) && defined(__mips__) */ + +#endif /*__mips__ */ + +#endif /* !defined(ABS_MIPS_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/clz_mips.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/clz_mips.h new file mode 100644 index 0000000000000..748f6c2fcf526 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/clz_mips.h @@ -0,0 +1,134 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(CLZ_MIPS_H) +#define CLZ_MIPS_H + +#if defined(__mips__) + +#if defined(__mips__) && (__GNUC__ == 2) && (mips >= 32) + +#define FUNCTION_fixnormz_D +inline INT fixnormz_D(LONG value) { + INT result; + __asm__("clz %0,%1" : "=d"(result) : "d"(value)); + + return result; +} + +#elif defined(__mips__) && (__GNUC__ == 3) && (__mips >= 32) + +#define FUNCTION_fixnormz_D +INT inline fixnormz_D(LONG value) { + INT result; + __asm__("clz %[result], %[value]" + : [result] "=r"(result) + : [value] "r"(value)); + + return result; +} + +#endif + +#endif /* __mips__ */ + +#endif /* !defined(CLZ_MIPS_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/cplx_mul_mips.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/cplx_mul_mips.h new file mode 100644 index 0000000000000..4ade3e577a395 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/cplx_mul_mips.h @@ -0,0 +1,133 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(CPLX_MUL_MIPS_H) +#define CPLX_MUL_MIPS_H + +#if defined(__GNUC__) && defined(__mips__) + +//#define FUNCTION_cplxMultDiv2_32x16 +//#define FUNCTION_cplxMultDiv2_32x16X2 +#define FUNCTION_cplxMultDiv2_32x32X2 +//#define FUNCTION_cplxMult_32x16 +//#define FUNCTION_cplxMult_32x16X2 +#define FUNCTION_cplxMult_32x32X2 + +#if defined(FUNCTION_cplxMultDiv2_32x32X2) +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, FIXP_DBL a_Re, + FIXP_DBL a_Im, FIXP_DBL b_Re, FIXP_DBL b_Im) { + *c_Re = (((long long)a_Re * (long long)b_Re) - ((long long)a_Im * (long long)b_Im))>>32; + *c_Im = (((long long)a_Re * (long long)b_Im) + ((long long)a_Im * (long long)b_Re))>>32; +} +#endif + +#if defined(FUNCTION_cplxMult_32x32X2) +inline void cplxMult(FIXP_DBL *c_Re, FIXP_DBL *c_Im, FIXP_DBL a_Re, + FIXP_DBL a_Im, FIXP_DBL b_Re, FIXP_DBL b_Im) { + *c_Re = ((((long long)a_Re * (long long)b_Re) - ((long long)a_Im * (long long)b_Im))>>32)<<1; + *c_Im = ((((long long)a_Re * (long long)b_Im) + ((long long)a_Im * (long long)b_Re))>>32)<<1; +} +#endif + +#endif /* defined(__GNUC__) && defined(__mips__) */ + +#endif /* !defined(CPLX_MUL_MIPS_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/fixmul_mips.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/fixmul_mips.h new file mode 100644 index 0000000000000..06cf530ecbfc6 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/fixmul_mips.h @@ -0,0 +1,130 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(FIXMUL_MIPS_H) +#define FIXMUL_MIPS_H + +#if defined(__mips__) + +#if (__GNUC__) && defined(__mips__) +/* MIPS GCC based compiler */ + +#define FUNCTION_fixmuldiv2_DD + +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a, b) fixmuldiv2_DD(a, b) + +inline INT fixmuldiv2_DD(const INT a, const INT b) { + INT result; + + result = ((long long)a * b) >> 32; + + return result; +} + +#endif /* (__GNUC__) && defined(__mips__) */ + +#endif /* __mips__ */ + +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD fixmul_DD +#endif /* !defined(FIXMUL_MIPS_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/scale_mips.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/scale_mips.h new file mode 100644 index 0000000000000..882ef35c6acb1 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/scale_mips.h @@ -0,0 +1,122 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef SCALE_MIPS_H +#define SCALE_MIPS_H + +#if defined(__mips_dsp) && !defined(__mips16) + +/*! + * + * \brief Scale input value by 2^{scale} and saturate output to 2^{dBits-1} + * \return scaled and saturated value + * + * This macro scales src value right or left and applies saturation to + * (2^dBits)-1 maxima output. + */ +#define SATURATE_RIGHT_SHIFT(src, scale, dBits) \ + (__builtin_mips_shll_s_w((src) >> (scale), (DFRACT_BITS - (dBits))) >> \ + (DFRACT_BITS - (dBits))) + +#endif /*__mips_dsp */ + +#endif /* SCALE_MIPS_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/scramble_mips.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/scramble_mips.h new file mode 100644 index 0000000000000..08c2e6d1736cd --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/mips/scramble_mips.h @@ -0,0 +1,133 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef SCRAMBLE_MIPS_H +#define SCRAMBLE_MIPS_H + +#define FUNCTION_scramble + +#if defined(FUNCTION_scramble) +inline void scramble(FIXP_DBL *x, INT n) { + INT m, j; + int ldn = 1; + do { + ldn++; + } while ((1 << ldn) < n); + + for (m = 1, j = 0; m < n - 1; m++) { + j = __builtin_mips_bitrev(m) >> (16 - ldn); + + if (j > m) { + FIXP_DBL tmp; + tmp = x[2 * m]; + x[2 * m] = x[2 * j]; + x[2 * j] = tmp; + + tmp = x[2 * m + 1]; + x[2 * m + 1] = x[2 * j + 1]; + x[2 * j + 1] = tmp; + } + } +} +#endif + +#endif /* SCRAMBLE_MIPS_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/nlc_dec.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/nlc_dec.h new file mode 100644 index 0000000000000..aded569d3a861 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/nlc_dec.h @@ -0,0 +1,184 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Omer Osman + + Description: SAC/SAOC Dec Noiseless Coding + +*******************************************************************************/ + +#ifndef NLC_DEC_H +#define NLC_DEC_H + +#include "FDK_bitstream.h" +#include "huff_nodes.h" +#include "common_fix.h" + +typedef enum { + + SAC_DECODER, + SAOC_DECODER, + USAC_DECODER + +} DECODER_TYPE; + +typedef enum { + t_CLD, + t_ICC, + t_IPD, + t_OLD, + t_IOC, + t_NRG, + t_DCLD, + t_DMG, + t_PDG + +} DATA_TYPE; + +typedef enum { + + BACKWARDS = 0x0, + FORWARDS = 0x1 + +} DIRECTION; + +typedef enum { + + DIFF_FREQ = 0x0, + DIFF_TIME = 0x1 + +} DIFF_TYPE; + +typedef enum { + + HUFF_1D = 0x0, + HUFF_2D = 0x1 + +} CODING_SCHEME; + +typedef enum { + + FREQ_PAIR = 0x0, + TIME_PAIR = 0x1 + +} PAIRING; + +#ifndef HUFFDEC_PARAMS +#define HUFFDEC_PARMS + +#define MAX_ENTRIES 168 +#define HANDLE_HUFF_NODE const SHORT(*)[MAX_ENTRIES][2] + +#endif /* HUFFDECPARAMS */ + +#define HUFFDEC_OK 0 +#define HUFFDEC_NOTOK (-1) + +typedef int ERROR_t; + +ERROR_t EcDataPairDec(DECODER_TYPE DECODER, HANDLE_FDK_BITSTREAM strm, + SCHAR *aaOutData1, SCHAR *aaOutData2, SCHAR *aHistory, + DATA_TYPE data_type, int startBand, int dataBands, + int pair_flag, int coarse_flag, + int allowDiffTimeBack_flag); + +/* needed for GES- & STP-tool */ +ERROR_t huff_dec_reshape(HANDLE_FDK_BITSTREAM strm, int *out_data, int num_val); + +extern ERROR_t sym_restoreIPD(HANDLE_FDK_BITSTREAM strm, int lav, + SCHAR data[2]); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/ppc/clz_ppc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/ppc/clz_ppc.h new file mode 100644 index 0000000000000..bfd23c662e983 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/ppc/clz_ppc.h @@ -0,0 +1,102 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__powerpc__) && (defined(__GNUC__) || defined(__xlC__)) + +#define FUNCTION_fixnormz_D + +inline INT fixnormz_D(LONG value) +{ + INT result; + __asm__ ("cntlzw %0, %1" : "=r" (result) : "r" (value)); + return result; +} + +#endif /* __powerpc__ && (__GNUC__ || __xlC__) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/ppc/fixmul_ppc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/ppc/fixmul_ppc.h new file mode 100644 index 0000000000000..9e2745cc662b0 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/ppc/fixmul_ppc.h @@ -0,0 +1,115 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__powerpc__) && (defined(__GNUC__) || defined(__xlC__)) + +#define FUNCTION_fixmuldiv2_DD + +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a,b) fixmuldiv2_DD(a,b) + +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD(a,b) fixmul_DD(a,b) + +#define FUNCTION_fixmuldiv2BitExact_DS +#define fixmuldiv2BitExact_DS(a,b) fixmuldiv2_DS(a,b) + +#define FUNCTION_fixmulBitExact_DS +#define fixmulBitExact_DS(a,b) fixmul_DS(a,b) + + +inline INT fixmuldiv2_DD (const INT a, const INT b) +{ + INT result; + __asm__ ("mulhw %0, %1, %2" : "=r" (result) : "r" (a), "r" (b)); + return result; +} + +#endif /* __powerpc__ && (__GNUC__ || __xlC__) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/qmf.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/qmf.h new file mode 100644 index 0000000000000..78770b39e8047 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/qmf.h @@ -0,0 +1,334 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file qmf.h + \brief Complex qmf analysis/synthesis + \author Markus Werner + +*/ + +#ifndef QMF_H +#define QMF_H + +#include "common_fix.h" +#include "FDK_tools_rom.h" +#include "dct.h" + +#define FIXP_QAS FIXP_PCM +#define QAS_BITS SAMPLE_BITS +#define INT_PCM_QMFIN INT_PCM + +#define FIXP_QSS FIXP_DBL +#define QSS_BITS DFRACT_BITS + +/* Flags for QMF intialization */ +/* Low Power mode flag */ +#define QMF_FLAG_LP 1 +/* Filter is not symmetric. This flag is set internally in the QMF + * initialization as required. */ +/* DO NOT PASS THIS FLAG TO qmfInitAnalysisFilterBank or + * qmfInitSynthesisFilterBank */ +#define QMF_FLAG_NONSYMMETRIC 2 +/* Complex Low Delay Filter Bank (or std symmetric filter bank) */ +#define QMF_FLAG_CLDFB 4 +/* Flag indicating that the states should be kept. */ +#define QMF_FLAG_KEEP_STATES 8 +/* Complex Low Delay Filter Bank used in MPEG Surround Encoder */ +#define QMF_FLAG_MPSLDFB 16 +/* Complex Low Delay Filter Bank used in MPEG Surround Encoder allows a + * optimized calculation of the modulation in qmfForwardModulationHQ() */ +#define QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION 32 +/* Flag to indicate HE-AAC down-sampled SBR mode (decoder) -> adapt analysis + * post twiddling */ +#define QMF_FLAG_DOWNSAMPLED 64 + +#define QMF_MAX_SYNTHESIS_BANDS (64) + +/*! + * \brief Algorithmic scaling in sbrForwardModulation() + * + * The scaling in sbrForwardModulation() is caused by: + * + * \li 1 R_SHIFT in sbrForwardModulation() + * \li 5/6 R_SHIFT in dct3() if using 32/64 Bands + * \li 1 omitted gain of 2.0 in qmfForwardModulation() + */ +#define ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK 7 + +/*! + * \brief Algorithmic scaling in cplxSynthesisQmfFiltering() + * + * The scaling in cplxSynthesisQmfFiltering() is caused by: + * + * \li 5/6 R_SHIFT in dct2() if using 32/64 Bands + * \li 1 omitted gain of 2.0 in qmfInverseModulation() + * \li -6 division by 64 in synthesis filterbank + * \li x bits external influence + */ +#define ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK 1 + +typedef struct { + int lb_scale; /*!< Scale of low band area */ + int ov_lb_scale; /*!< Scale of adjusted overlap low band area */ + int hb_scale; /*!< Scale of high band area */ + int ov_hb_scale; /*!< Scale of adjusted overlap high band area */ +} QMF_SCALE_FACTOR; + +struct QMF_FILTER_BANK { + const FIXP_PFT *p_filter; /*!< Pointer to filter coefficients */ + + void *FilterStates; /*!< Pointer to buffer of filter states + FIXP_PCM in analyse and + FIXP_DBL in synthesis filter */ + int FilterSize; /*!< Size of prototype filter. */ + const FIXP_QTW *t_cos; /*!< Modulation tables. */ + const FIXP_QTW *t_sin; + int filterScale; /*!< filter scale */ + + int no_channels; /*!< Total number of channels (subbands) */ + int no_col; /*!< Number of time slots */ + int lsb; /*!< Top of low subbands */ + int usb; /*!< Top of high subbands */ + + int synScalefactor; /*!< Scale factor of synthesis qmf (syn only) */ + int outScalefactor; /*!< Scale factor of output data (syn only) */ + FIXP_DBL outGain_m; /*!< Mantissa of gain output data (syn only) (init with + 0x80000000 to ignore) */ + int outGain_e; /*!< Exponent of gain output data (syn only) */ + + UINT flags; /*!< flags */ + UCHAR p_stride; /*!< Stride Factor of polyphase filters */ +}; + +typedef struct QMF_FILTER_BANK *HANDLE_QMF_FILTER_BANK; + +int qmfInitAnalysisFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */ + FIXP_QAS *pFilterStates, /*!< Pointer to filter state buffer */ + int noCols, /*!< Number of time slots */ + int lsb, /*!< Number of lower bands */ + int usb, /*!< Number of upper bands */ + int no_channels, /*!< Number of critically sampled bands */ + int flags); /*!< Flags */ +#if SAMPLE_BITS == 16 + +int qmfInitAnalysisFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */ + FIXP_DBL *pFilterStates, /*!< Pointer to filter state buffer */ + int noCols, /*!< Number of time slots */ + int lsb, /*!< Number of lower bands */ + int usb, /*!< Number of upper bands */ + int no_channels, /*!< Number of critically sampled bands */ + int flags); /*!< Flags */ +#endif + +void qmfAnalysisFiltering( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ + FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ + QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ + const INT_PCM *timeIn, /*!< Time signal */ + const int timeIn_e, /*!< Exponent of audio data */ + const int stride, /*!< Stride factor of audio data */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +); +#if SAMPLE_BITS == 16 + +void qmfAnalysisFiltering( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ + FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ + QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ + const LONG *timeIn, /*!< Time signal */ + const int timeIn_e, /*!< Exponent of audio data */ + const int stride, /*!< Stride factor of audio data */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */ +); +#endif + +void qmfAnalysisFilteringSlot( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL *qmfReal, /*!< Low and High band, real */ + FIXP_DBL *qmfImag, /*!< Low and High band, imag */ + const INT_PCM *timeIn, /*!< Pointer to input */ + const int stride, /*!< stride factor of input */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +); +#if SAMPLE_BITS == 16 + +void qmfAnalysisFilteringSlot( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL *qmfReal, /*!< Low and High band, real */ + FIXP_DBL *qmfImag, /*!< Low and High band, imag */ + const LONG *timeIn, /*!< Pointer to input */ + const int stride, /*!< stride factor of input */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */ +); +#endif + +int qmfInitSynthesisFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */ + FIXP_QSS *pFilterStates, /*!< Pointer to filter state buffer */ + int noCols, /*!< Number of time slots */ + int lsb, /*!< Number of lower bands */ + int usb, /*!< Number of upper bands */ + int no_channels, /*!< Number of critically sampled bands */ + int flags); /*!< Flags */ + +void qmfSynthesisFiltering( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL **QmfBufferReal, /*!< Pointer to real subband slots */ + FIXP_DBL **QmfBufferImag, /*!< Pointer to imag subband slots */ + const QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ + const int ov_len, /*!< Length of band overlap */ + INT_PCM *timeOut, /*!< Time signal */ + const INT stride, /*!< Stride factor of audio data */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer. It must be + aligned */ +); +#if SAMPLE_BITS == 16 + +void qmfSynthesisFiltering( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL **QmfBufferReal, /*!< Pointer to real subband slots */ + FIXP_DBL **QmfBufferImag, /*!< Pointer to imag subband slots */ + const QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ + const int ov_len, /*!< Length of band overlap */ + LONG *timeOut, /*!< Time signal */ + const int timeOut_e, /*!< Target exponent for timeOut */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */ +); +#endif + +void qmfSynthesisFilteringSlot(HANDLE_QMF_FILTER_BANK synQmf, + const FIXP_DBL *realSlot, + const FIXP_DBL *imagSlot, + const int scaleFactorLowBand, + const int scaleFactorHighBand, INT_PCM *timeOut, + const int timeOut_e, FIXP_DBL *pWorkBuffer); +#if SAMPLE_BITS == 16 + +void qmfSynthesisFilteringSlot(HANDLE_QMF_FILTER_BANK synQmf, + const FIXP_DBL *realSlot, + const FIXP_DBL *imagSlot, + const int scaleFactorLowBand, + const int scaleFactorHighBand, LONG *timeOut, + const int timeOut_e, FIXP_DBL *pWorkBuffer); +#endif + +void qmfChangeOutScalefactor( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + int outScalefactor /*!< New scaling factor for output data */ +); + +int qmfGetOutScalefactor( + HANDLE_QMF_FILTER_BANK synQmf /*!< Handle of Qmf Synthesis Bank */ +); + +void qmfChangeOutGain( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL outputGain, /*!< New gain for output data (mantissa) */ + int outputGainScale /*!< New gain for output data (exponent) */ +); + +#endif /*ifndef QMF_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/qmf_pcm.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/qmf_pcm.h new file mode 100644 index 0000000000000..5da53db4fee1e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/qmf_pcm.h @@ -0,0 +1,621 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Markus Lohwasser, Josef Hoepfl, Manuel Jander + + Description: QMF filterbank + +*******************************************************************************/ + +#ifndef QMF_PCM_H +#define QMF_PCM_H + +/* + All Synthesis functions dependent on datatype INT_PCM_QMFOUT + Should only be included by qmf.cpp, but not compiled separately, please + exclude compilation from project, if done otherwise. Is optional included + twice to duplicate all functions with two different pre-definitions, as: + #define INT_PCM_QMFOUT LONG + and ... + #define INT_PCM_QMFOUT SHORT + needed to run QMF synthesis in both 16bit and 32bit sample output format. +*/ + +#define QSSCALE (0) +#define FX_DBL2FX_QSS(x) (x) +#define FX_QSS2FX_DBL(x) (x) + +/*! + \brief Perform Synthesis Prototype Filtering on a single slot of input data. + + The filter takes 2 * qmf->no_channels of input data and + generates qmf->no_channels time domain output samples. +*/ +/* static */ +#ifndef FUNCTION_qmfSynPrototypeFirSlot +void qmfSynPrototypeFirSlot( +#else +void qmfSynPrototypeFirSlot_fallback( +#endif + HANDLE_QMF_FILTER_BANK qmf, + FIXP_DBL *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ + FIXP_DBL *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ + INT_PCM_QMFOUT *RESTRICT timeOut, /*!< Time domain data */ + int stride) { + FIXP_QSS *FilterStates = (FIXP_QSS *)qmf->FilterStates; + int no_channels = qmf->no_channels; + const FIXP_PFT *p_Filter = qmf->p_filter; + int p_stride = qmf->p_stride; + int j; + FIXP_QSS *RESTRICT sta = FilterStates; + const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm; + int scale = (DFRACT_BITS - SAMPLE_BITS_QMFOUT) - 1 - qmf->outScalefactor - + qmf->outGain_e; + + p_flt = + p_Filter + p_stride * QMF_NO_POLY; /* 5th of 330 */ + p_fltm = p_Filter + (qmf->FilterSize / 2) - + p_stride * QMF_NO_POLY; /* 5 + (320 - 2*5) = 315th of 330 */ + + FIXP_SGL gain = FX_DBL2FX_SGL(qmf->outGain_m); + + FIXP_DBL rnd_val = 0; + + if (scale > 0) { + if (scale < (DFRACT_BITS - 1)) + rnd_val = FIXP_DBL(1 << (scale - 1)); + else + scale = (DFRACT_BITS - 1); + } else { + scale = fMax(scale, -(DFRACT_BITS - 1)); + } + + for (j = no_channels - 1; j >= 0; j--) { + FIXP_DBL imag = imagSlot[j]; /* no_channels-1 .. 0 */ + FIXP_DBL real = realSlot[j]; /* no_channels-1 .. 0 */ + { + INT_PCM_QMFOUT tmp; + FIXP_DBL Are = fMultAddDiv2(FX_QSS2FX_DBL(sta[0]), p_fltm[0], real); + + /* This PCM formatting performs: + - multiplication with 16-bit gain, if not -1.0f + - rounding, if shift right is applied + - apply shift left (or right) with saturation to 32 (or 16) bits + - store output with --stride in 32 (or 16) bit format + */ + if (gain != (FIXP_SGL)(-32768)) /* -1.0f */ + { + Are = fMult(Are, gain); + } + if (scale >= 0) { + FDK_ASSERT( + Are <= + (Are + rnd_val)); /* Round-addition must not overflow, might be + equal for rnd_val=0 */ + tmp = (INT_PCM_QMFOUT)( + SATURATE_RIGHT_SHIFT(Are + rnd_val, scale, SAMPLE_BITS_QMFOUT)); + } else { + tmp = (INT_PCM_QMFOUT)( + SATURATE_LEFT_SHIFT(Are, -scale, SAMPLE_BITS_QMFOUT)); + } + + { timeOut[(j)*stride] = tmp; } + } + + sta[0] = FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[1]), p_flt[4], imag)); + sta[1] = + FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[2]), p_fltm[1], real)); + sta[2] = FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[3]), p_flt[3], imag)); + sta[3] = + FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[4]), p_fltm[2], real)); + sta[4] = FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[5]), p_flt[2], imag)); + sta[5] = + FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[6]), p_fltm[3], real)); + sta[6] = FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[7]), p_flt[1], imag)); + sta[7] = + FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[8]), p_fltm[4], real)); + sta[8] = FX_DBL2FX_QSS(fMultDiv2(p_flt[0], imag)); + p_flt += (p_stride * QMF_NO_POLY); + p_fltm -= (p_stride * QMF_NO_POLY); + sta += 9; // = (2*QMF_NO_POLY-1); + } +} + +#ifndef FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric +/*! + \brief Perform Synthesis Prototype Filtering on a single slot of input data. + + The filter takes 2 * qmf->no_channels of input data and + generates qmf->no_channels time domain output samples. +*/ +static void qmfSynPrototypeFirSlot_NonSymmetric( + HANDLE_QMF_FILTER_BANK qmf, + FIXP_DBL *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ + FIXP_DBL *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ + INT_PCM_QMFOUT *RESTRICT timeOut, /*!< Time domain data */ + int stride) { + FIXP_QSS *FilterStates = (FIXP_QSS *)qmf->FilterStates; + int no_channels = qmf->no_channels; + const FIXP_PFT *p_Filter = qmf->p_filter; + int p_stride = qmf->p_stride; + int j; + FIXP_QSS *RESTRICT sta = FilterStates; + const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm; + int scale = (DFRACT_BITS - SAMPLE_BITS_QMFOUT) - 1 - qmf->outScalefactor - + qmf->outGain_e; + + p_flt = p_Filter; /*!< Pointer to first half of filter coefficients */ + p_fltm = + &p_flt[qmf->FilterSize / 2]; /* at index 320, overall 640 coefficients */ + + FIXP_SGL gain = FX_DBL2FX_SGL(qmf->outGain_m); + + FIXP_DBL rnd_val = (FIXP_DBL)0; + + if (scale > 0) { + if (scale < (DFRACT_BITS - 1)) + rnd_val = FIXP_DBL(1 << (scale - 1)); + else + scale = (DFRACT_BITS - 1); + } else { + scale = fMax(scale, -(DFRACT_BITS - 1)); + } + + for (j = no_channels - 1; j >= 0; j--) { + FIXP_DBL imag = imagSlot[j]; /* no_channels-1 .. 0 */ + FIXP_DBL real = realSlot[j]; /* no_channels-1 .. 0 */ + { + INT_PCM_QMFOUT tmp; + FIXP_DBL Are = sta[0] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[4], real)); + + /* This PCM formatting performs: + - multiplication with 16-bit gain, if not -1.0f + - rounding, if shift right is applied + - apply shift left (or right) with saturation to 32 (or 16) bits + - store output with --stride in 32 (or 16) bit format + */ + if (gain != (FIXP_SGL)(-32768)) /* -1.0f */ + { + Are = fMult(Are, gain); + } + if (scale > 0) { + FDK_ASSERT(Are < + (Are + rnd_val)); /* Round-addition must not overflow */ + tmp = (INT_PCM_QMFOUT)( + SATURATE_RIGHT_SHIFT(Are + rnd_val, scale, SAMPLE_BITS_QMFOUT)); + } else { + tmp = (INT_PCM_QMFOUT)( + SATURATE_LEFT_SHIFT(Are, -scale, SAMPLE_BITS_QMFOUT)); + } + timeOut[j * stride] = tmp; + } + + sta[0] = sta[1] + FX_DBL2FX_QSS(fMultDiv2(p_flt[4], imag)); + sta[1] = sta[2] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[3], real)); + sta[2] = sta[3] + FX_DBL2FX_QSS(fMultDiv2(p_flt[3], imag)); + + sta[3] = sta[4] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[2], real)); + sta[4] = sta[5] + FX_DBL2FX_QSS(fMultDiv2(p_flt[2], imag)); + sta[5] = sta[6] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[1], real)); + sta[6] = sta[7] + FX_DBL2FX_QSS(fMultDiv2(p_flt[1], imag)); + + sta[7] = sta[8] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[0], real)); + sta[8] = FX_DBL2FX_QSS(fMultDiv2(p_flt[0], imag)); + + p_flt += (p_stride * QMF_NO_POLY); + p_fltm += (p_stride * QMF_NO_POLY); + sta += 9; // = (2*QMF_NO_POLY-1); + } +} +#endif /* FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric */ + +void qmfSynthesisFilteringSlot(HANDLE_QMF_FILTER_BANK synQmf, + const FIXP_DBL *realSlot, + const FIXP_DBL *imagSlot, + const int scaleFactorLowBand, + const int scaleFactorHighBand, + INT_PCM_QMFOUT *timeOut, const int stride, + FIXP_DBL *pWorkBuffer) { + if (!(synQmf->flags & QMF_FLAG_LP)) + qmfInverseModulationHQ(synQmf, realSlot, imagSlot, scaleFactorLowBand, + scaleFactorHighBand, pWorkBuffer); + else { + if (synQmf->flags & QMF_FLAG_CLDFB) { + qmfInverseModulationLP_odd(synQmf, realSlot, scaleFactorLowBand, + scaleFactorHighBand, pWorkBuffer); + } else { + qmfInverseModulationLP_even(synQmf, realSlot, scaleFactorLowBand, + scaleFactorHighBand, pWorkBuffer); + } + } + + if (synQmf->flags & QMF_FLAG_NONSYMMETRIC) { + qmfSynPrototypeFirSlot_NonSymmetric(synQmf, pWorkBuffer, + pWorkBuffer + synQmf->no_channels, + timeOut, stride); + } else { + qmfSynPrototypeFirSlot(synQmf, pWorkBuffer, + pWorkBuffer + synQmf->no_channels, timeOut, stride); + } +} + +/*! + * + * \brief Perform complex-valued subband synthesis of the + * low band and the high band and store the + * time domain data in timeOut + * + * First step: Calculate the proper scaling factor of current + * spectral data in qmfReal/qmfImag, old spectral data in the overlap + * range and filter states. + * + * Second step: Perform Frequency-to-Time mapping with inverse + * Modulation slot-wise. + * + * Third step: Perform FIR-filter slot-wise. To save space for filter + * states, the MAC operations are executed directly on the filter states + * instead of accumulating several products in the accumulator. The + * buffer shift at the end of the function should be replaced by a + * modulo operation, which is available on some DSPs. + * + * Last step: Copy the upper part of the spectral data to the overlap buffer. + * + * The qmf coefficient table is symmetric. The symmetry is exploited by + * shrinking the coefficient table to half the size. The addressing mode + * takes care of the symmetries. If the #define #QMFTABLE_FULL is set, + * coefficient addressing works on the full table size. The code will be + * slightly faster and slightly more compact. + * + * Workbuffer requirement: 2 x sizeof(**QmfBufferReal) * synQmf->no_channels + * The workbuffer must be aligned + */ +void qmfSynthesisFiltering( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL **QmfBufferReal, /*!< Low and High band, real */ + FIXP_DBL **QmfBufferImag, /*!< Low and High band, imag */ + const QMF_SCALE_FACTOR *scaleFactor, + const INT ov_len, /*!< split Slot of overlap and actual slots */ + INT_PCM_QMFOUT *timeOut, /*!< Pointer to output */ + const INT stride, /*!< stride factor of output */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +) { + int i; + int L = synQmf->no_channels; + int scaleFactorHighBand; + int scaleFactorLowBand_ov, scaleFactorLowBand_no_ov; + + FDK_ASSERT(synQmf->no_channels >= synQmf->lsb); + FDK_ASSERT(synQmf->no_channels >= synQmf->usb); + + /* adapt scaling */ + scaleFactorHighBand = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - + scaleFactor->hb_scale - synQmf->filterScale; + scaleFactorLowBand_ov = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - + scaleFactor->ov_lb_scale - synQmf->filterScale; + scaleFactorLowBand_no_ov = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - + scaleFactor->lb_scale - synQmf->filterScale; + + for (i = 0; i < synQmf->no_col; i++) /* ----- no_col loop ----- */ + { + const FIXP_DBL *QmfBufferImagSlot = NULL; + + int scaleFactorLowBand = + (i < ov_len) ? scaleFactorLowBand_ov : scaleFactorLowBand_no_ov; + + if (!(synQmf->flags & QMF_FLAG_LP)) QmfBufferImagSlot = QmfBufferImag[i]; + + qmfSynthesisFilteringSlot(synQmf, QmfBufferReal[i], QmfBufferImagSlot, + scaleFactorLowBand, scaleFactorHighBand, + timeOut + (i * L * stride), stride, pWorkBuffer); + } /* no_col loop i */ +} + +/*! + * + * \brief Create QMF filter bank instance + * + * + * \return 0 if successful + * + */ +int qmfInitAnalysisFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ + FIXP_QAS *pFilterStates, /*!< Handle to filter states */ + int noCols, /*!< Number of timeslots per frame */ + int lsb, /*!< lower end of QMF */ + int usb, /*!< upper end of QMF */ + int no_channels, /*!< Number of channels (bands) */ + int flags) /*!< Low Power flag */ +{ + int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, + no_channels, flags, 0); + if (!(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL)) { + FDKmemclear(h_Qmf->FilterStates, + (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QAS)); + } + + FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb); + + return err; +} + +#ifndef FUNCTION_qmfAnaPrototypeFirSlot +/*! + \brief Perform Analysis Prototype Filtering on a single slot of input data. +*/ +static void qmfAnaPrototypeFirSlot( + FIXP_DBL *analysisBuffer, + INT no_channels, /*!< Number channels of analysis filter */ + const FIXP_PFT *p_filter, INT p_stride, /*!< Stride of analysis filter */ + FIXP_QAS *RESTRICT pFilterStates) { + INT k; + + FIXP_DBL accu; + const FIXP_PFT *RESTRICT p_flt = p_filter; + FIXP_DBL *RESTRICT pData_0 = analysisBuffer + 2 * no_channels - 1; + FIXP_DBL *RESTRICT pData_1 = analysisBuffer; + + FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates; + FIXP_QAS *RESTRICT sta_1 = + (FIXP_QAS *)pFilterStates + (2 * QMF_NO_POLY * no_channels) - 1; + INT pfltStep = QMF_NO_POLY * (p_stride); + INT staStep1 = no_channels << 1; + INT staStep2 = (no_channels << 3) - 1; /* Rewind one less */ + + /* FIR filters 127..64 0..63 */ + for (k = 0; k < no_channels; k++) { + accu = fMultDiv2(p_flt[0], *sta_1); + sta_1 -= staStep1; + accu += fMultDiv2(p_flt[1], *sta_1); + sta_1 -= staStep1; + accu += fMultDiv2(p_flt[2], *sta_1); + sta_1 -= staStep1; + accu += fMultDiv2(p_flt[3], *sta_1); + sta_1 -= staStep1; + accu += fMultDiv2(p_flt[4], *sta_1); + *pData_1++ = (accu << 1); + sta_1 += staStep2; + + p_flt += pfltStep; + accu = fMultDiv2(p_flt[0], *sta_0); + sta_0 += staStep1; + accu += fMultDiv2(p_flt[1], *sta_0); + sta_0 += staStep1; + accu += fMultDiv2(p_flt[2], *sta_0); + sta_0 += staStep1; + accu += fMultDiv2(p_flt[3], *sta_0); + sta_0 += staStep1; + accu += fMultDiv2(p_flt[4], *sta_0); + *pData_0-- = (accu << 1); + sta_0 -= staStep2; + } +} +#endif /* !defined(FUNCTION_qmfAnaPrototypeFirSlot) */ + +#ifndef FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric +/*! + \brief Perform Analysis Prototype Filtering on a single slot of input data. +*/ +static void qmfAnaPrototypeFirSlot_NonSymmetric( + FIXP_DBL *analysisBuffer, + int no_channels, /*!< Number channels of analysis filter */ + const FIXP_PFT *p_filter, int p_stride, /*!< Stride of analysis filter */ + FIXP_QAS *RESTRICT pFilterStates) { + const FIXP_PFT *RESTRICT p_flt = p_filter; + int p, k; + + for (k = 0; k < 2 * no_channels; k++) { + FIXP_DBL accu = (FIXP_DBL)0; + + p_flt += QMF_NO_POLY * (p_stride - 1); + + /* + Perform FIR-Filter + */ + for (p = 0; p < QMF_NO_POLY; p++) { + accu += fMultDiv2(*p_flt++, pFilterStates[2 * no_channels * p]); + } + analysisBuffer[2 * no_channels - 1 - k] = (accu << 1); + pFilterStates++; + } +} +#endif /* FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric */ + +/* + * \brief Perform one QMF slot analysis of the time domain data of timeIn + * with specified stride and stores the real part of the subband + * samples in rSubband, and the imaginary part in iSubband + * + * Note: anaQmf->lsb can be greater than anaQmf->no_channels in case + * of implicit resampling (USAC with reduced 3/4 core frame length). + */ +void qmfAnalysisFilteringSlot( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL *qmfReal, /*!< Low and High band, real */ + FIXP_DBL *qmfImag, /*!< Low and High band, imag */ + const INT_PCM_QMFIN *RESTRICT timeIn, /*!< Pointer to input */ + const int stride, /*!< stride factor of input */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +) { + int offset = anaQmf->no_channels * (QMF_NO_POLY * 2 - 1); + /* + Feed time signal into oldest anaQmf->no_channels states + */ + { + FIXP_QAS *FilterStatesAnaTmp = ((FIXP_QAS *)anaQmf->FilterStates) + offset; + + /* Feed and scale actual time in slot */ + for (int i = anaQmf->no_channels >> 1; i != 0; i--) { + /* Place INT_PCM value left aligned in scaledTimeIn */ + *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; + timeIn += stride; + *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; + timeIn += stride; + } + } + + if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) { + qmfAnaPrototypeFirSlot_NonSymmetric(pWorkBuffer, anaQmf->no_channels, + anaQmf->p_filter, anaQmf->p_stride, + (FIXP_QAS *)anaQmf->FilterStates); + } else { + qmfAnaPrototypeFirSlot(pWorkBuffer, anaQmf->no_channels, anaQmf->p_filter, + anaQmf->p_stride, (FIXP_QAS *)anaQmf->FilterStates); + } + + if (anaQmf->flags & QMF_FLAG_LP) { + if (anaQmf->flags & QMF_FLAG_CLDFB) + qmfForwardModulationLP_odd(anaQmf, pWorkBuffer, qmfReal); + else + qmfForwardModulationLP_even(anaQmf, pWorkBuffer, qmfReal); + + } else { + qmfForwardModulationHQ(anaQmf, pWorkBuffer, qmfReal, qmfImag); + } + /* + Shift filter states + + Should be realized with modulo addressing on a DSP instead of a true buffer + shift + */ + FDKmemmove(anaQmf->FilterStates, + (FIXP_QAS *)anaQmf->FilterStates + anaQmf->no_channels, + offset * sizeof(FIXP_QAS)); +} + +/*! + * + * \brief Perform complex-valued subband filtering of the time domain + * data of timeIn and stores the real part of the subband + * samples in rAnalysis, and the imaginary part in iAnalysis + * The qmf coefficient table is symmetric. The symmetry is expoited by + * shrinking the coefficient table to half the size. The addressing mode + * takes care of the symmetries. + * + * + * \sa PolyphaseFiltering + */ +void qmfAnalysisFiltering( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ + FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ + QMF_SCALE_FACTOR *scaleFactor, + const INT_PCM_QMFIN *timeIn, /*!< Time signal */ + const int timeIn_e, const int stride, + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +) { + int i; + int no_channels = anaQmf->no_channels; + + scaleFactor->lb_scale = + -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - timeIn_e; + scaleFactor->lb_scale -= anaQmf->filterScale; + + for (i = 0; i < anaQmf->no_col; i++) { + FIXP_DBL *qmfImagSlot = NULL; + + if (!(anaQmf->flags & QMF_FLAG_LP)) { + qmfImagSlot = qmfImag[i]; + } + + qmfAnalysisFilteringSlot(anaQmf, qmfReal[i], qmfImagSlot, timeIn, stride, + pWorkBuffer); + + timeIn += no_channels * stride; + + } /* no_col loop i */ +} +#endif /* QMF_PCM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/scale.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/scale.h new file mode 100644 index 0000000000000..a58614e67da0c --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/scale.h @@ -0,0 +1,296 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: Scaling operations + +*******************************************************************************/ + +#ifndef SCALE_H +#define SCALE_H + +#include "common_fix.h" +#include "genericStds.h" +#include "fixminmax.h" + +#define SCALE_INLINE + +#if defined(__arm__) +#include "arm/scale_arm.h" + +#elif defined(__mips__) +#include "mips/scale_mips.h" + +#endif + +void scaleValues(FIXP_SGL *vector, INT len, INT scalefactor); +void scaleValues(FIXP_DBL *vector, INT len, INT scalefactor); +void scaleValues(FIXP_DBL *dst, const FIXP_DBL *src, INT len, INT scalefactor); +#if (SAMPLE_BITS == 16) +void scaleValues(FIXP_PCM *dst, const FIXP_DBL *src, INT len, INT scalefactor); +#endif +void scaleValues(FIXP_SGL *dst, const FIXP_SGL *src, INT len, INT scalefactor); +void scaleCplxValues(FIXP_DBL *r_dst, FIXP_DBL *i_dst, const FIXP_DBL *r_src, + const FIXP_DBL *i_src, INT len, INT scalefactor); +void scaleValuesWithFactor(FIXP_DBL *vector, FIXP_DBL factor, INT len, + INT scalefactor); +void scaleValuesSaturate(FIXP_DBL *vector, INT len, INT scalefactor); +void scaleValuesSaturate(FIXP_DBL *dst, const FIXP_DBL *src, INT len, + INT scalefactor); +void scaleValuesSaturate(FIXP_SGL *dst, const FIXP_DBL *src, INT len, + INT scalefactor); +void scaleValuesSaturate(FIXP_SGL *vector, INT len, INT scalefactor); +void scaleValuesSaturate(FIXP_SGL *dst, const FIXP_SGL *src, INT len, + INT scalefactor); +INT getScalefactorShort(const SHORT *vector, INT len); +INT getScalefactorPCM(const INT_PCM *vector, INT len, INT stride); +INT getScalefactor(const FIXP_DBL *vector, INT len); +INT getScalefactor(const FIXP_SGL *vector, INT len); + +#ifndef FUNCTION_scaleValue +/*! + * + * \brief Multiply input by \f$ 2^{scalefactor} \f$ + * + * \return Scaled input + * + */ +#define FUNCTION_scaleValue +inline FIXP_DBL scaleValue(const FIXP_DBL value, /*!< Value */ + INT scalefactor /*!< Scalefactor */ +) { + if (scalefactor > 0) + return (value << scalefactor); + else + return (value >> (-scalefactor)); +} +inline FIXP_SGL scaleValue(const FIXP_SGL value, /*!< Value */ + INT scalefactor /*!< Scalefactor */ +) { + if (scalefactor > 0) + return (value << scalefactor); + else + return (value >> (-scalefactor)); +} +#endif + +#ifndef FUNCTION_scaleValueSaturate +/*! + * + * \brief Multiply input by \f$ 2^{scalefactor} \f$ + * \param value The value to be scaled. + * \param the shift amount + * \return \f$ value * 2^scalefactor \f$ + * + */ +#define FUNCTION_scaleValueSaturate +inline FIXP_DBL scaleValueSaturate(const FIXP_DBL value, + INT scalefactor /* in range -31 ... +31 */ +) { + int headroom = fixnormz_D( + (INT)value ^ (INT)((value >> 31))); /* headroom in range 1...32 */ + if (scalefactor >= 0) { + /* shift left: saturate in case of headroom less/equal scalefactor */ + if (headroom <= scalefactor) { + if (value > (FIXP_DBL)0) + return (FIXP_DBL)MAXVAL_DBL; /* 0x7FFF.FFFF */ + else + return (FIXP_DBL)MINVAL_DBL + (FIXP_DBL)1; /* 0x8000.0001 */ + } else { + return fMax((value << scalefactor), (FIXP_DBL)MINVAL_DBL + (FIXP_DBL)1); + } + } else { + scalefactor = -scalefactor; + /* shift right: clear in case of 32-headroom greater/equal -scalefactor */ + if ((DFRACT_BITS - headroom) <= scalefactor) { + return (FIXP_DBL)0; + } else { + return fMax((value >> scalefactor), (FIXP_DBL)MINVAL_DBL + (FIXP_DBL)1); + } + } +} +#endif + +#ifndef FUNCTION_scaleValueInPlace +/*! + * + * \brief Multiply input by \f$ 2^{scalefactor} \f$ in place + * + * \return void + * + */ +#define FUNCTION_scaleValueInPlace +inline void scaleValueInPlace(FIXP_DBL *value, /*!< Value */ + INT scalefactor /*!< Scalefactor */ +) { + INT newscale; + /* Note: The assignment inside the if conditional allows combining a load with + * the compare to zero (on ARM and maybe others) */ + if ((newscale = (scalefactor)) >= 0) { + *(value) <<= newscale; + } else { + *(value) >>= -newscale; + } +} +#endif + + /*! + * + * \brief Scale input value by 2^{scale} and saturate output to 2^{dBits-1} + * \return scaled and saturated value + * + * This macro scales src value right or left and applies saturation to + * (2^dBits)-1 maxima output. + */ + +#ifndef SATURATE_RIGHT_SHIFT +#define SATURATE_RIGHT_SHIFT(src, scale, dBits) \ + ((((LONG)(src) >> (scale)) > (LONG)(((1U) << ((dBits)-1)) - 1)) \ + ? (LONG)(((1U) << ((dBits)-1)) - 1) \ + : (((LONG)(src) >> (scale)) < ~((LONG)(((1U) << ((dBits)-1)) - 1))) \ + ? ~((LONG)(((1U) << ((dBits)-1)) - 1)) \ + : ((LONG)(src) >> (scale))) +#endif + +#ifndef SATURATE_LEFT_SHIFT +#define SATURATE_LEFT_SHIFT(src, scale, dBits) \ + (((LONG)(src) > ((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale))) \ + ? (LONG)(((1U) << ((dBits)-1)) - 1) \ + : ((LONG)(src) < ~((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale))) \ + ? ~((LONG)(((1U) << ((dBits)-1)) - 1)) \ + : ((LONG)(src) << (scale))) +#endif + +#ifndef SATURATE_SHIFT +#define SATURATE_SHIFT(src, scale, dBits) \ + (((scale) < 0) ? SATURATE_LEFT_SHIFT((src), -(scale), (dBits)) \ + : SATURATE_RIGHT_SHIFT((src), (scale), (dBits))) +#endif + +/* + * Alternative shift and saturate left, saturates to -0.99999 instead of -1.0000 + * to avoid problems when inverting the sign of the result. + */ +#ifndef SATURATE_LEFT_SHIFT_ALT +#define SATURATE_LEFT_SHIFT_ALT(src, scale, dBits) \ + (((LONG)(src) > ((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale))) \ + ? (LONG)(((1U) << ((dBits)-1)) - 1) \ + : ((LONG)(src) <= ~((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale))) \ + ? ~((LONG)(((1U) << ((dBits)-1)) - 2)) \ + : ((LONG)(src) << (scale))) +#endif + +#ifndef SATURATE_RIGHT_SHIFT_ALT +#define SATURATE_RIGHT_SHIFT_ALT(src, scale, dBits) \ + ((((LONG)(src) >> (scale)) > (LONG)(((1U) << ((dBits)-1)) - 1)) \ + ? (LONG)(((1U) << ((dBits)-1)) - 1) \ + : (((LONG)(src) >> (scale)) < ~((LONG)(((1U) << ((dBits)-1)) - 2))) \ + ? ~((LONG)(((1U) << ((dBits)-1)) - 2)) \ + : ((LONG)(src) >> (scale))) +#endif + +#ifndef SATURATE_INT_PCM_RIGHT_SHIFT +#define SATURATE_INT_PCM_RIGHT_SHIFT(src, scale) \ + SATURATE_RIGHT_SHIFT(src, scale, SAMPLE_BITS) +#endif + +#ifndef SATURATE_INT_PCM_LEFT_SHIFT +#define SATURATE_INT_PCM_LEFT_SHIFT(src, scale) \ + SATURATE_LEFT_SHIFT(src, scale, SAMPLE_BITS) +#endif + +#endif /* #ifndef SCALE_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/scramble.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/scramble.h new file mode 100644 index 0000000000000..e7cead9bcb647 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/scramble.h @@ -0,0 +1,153 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef SCRAMBLE_H +#define SCRAMBLE_H + +#include "common_fix.h" + +#if defined(__arm__) +#include "arm/scramble_arm.h" + +#elif defined(__mips__) && defined(__mips_dsp) && !defined(__mips16) +#include "mips/scramble_mips.h" + +#endif + +/***************************************************************************** + + functionname: scramble + description: bitreversal of input data + returns: + input: + output: + +*****************************************************************************/ +#if !defined(FUNCTION_scramble) + +/* default scramble functionality */ +inline void scramble(FIXP_DBL *x, INT length) { + INT m, k, j; + FDK_ASSERT(!(((INT)(INT64)x) & (ALIGNMENT_DEFAULT - 1))); + C_ALLOC_ALIGNED_CHECK(x); + + for (m = 1, j = 0; m < length - 1; m++) { + { + for (k = length >> 1; (!((j ^= k) & k)); k >>= 1) + ; + } + + if (j > m) { + FIXP_DBL tmp; + tmp = x[2 * m]; + x[2 * m] = x[2 * j]; + x[2 * j] = tmp; + + tmp = x[2 * m + 1]; + x[2 * m + 1] = x[2 * j + 1]; + x[2 * j + 1] = tmp; + } + } +} +#endif /* !defined(FUNCTION_scramble) */ + +#endif /* SCRAMBLE_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/abs_x86.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/abs_x86.h new file mode 100644 index 0000000000000..efd643345c4c0 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/abs_x86.h @@ -0,0 +1,123 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(ABS_X86_H) +#define ABS_X86_H + +#if defined(__x86__) + +#if defined(__x86_64__) + +inline INT fixabs_D(INT x) { return ((x) > (INT)(0)) ? (x) : -(x); } +inline INT fixabs_S(INT x) { return ((x) > (INT)(0)) ? (x) : -(x); } + +#define fixabs_I(x) fixabs_D(x) + +#define FUNCTION_fixabs_S +#define FUNCTION_fixabs_D +#define FUNCTION_fixabs_I + +#endif /* __x86_64__ */ + +#endif /*__x86__ */ + +#endif /* !defined(ABS_X86_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/clz_x86.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/clz_x86.h new file mode 100644 index 0000000000000..badca2938f205 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/clz_x86.h @@ -0,0 +1,165 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander + + Description: x86 version of count leading zero / bits + +*******************************************************************************/ + +#if !defined(CLZ_X86_H) +#define CLZ_X86_H + +#if defined(__GNUC__) && (defined(__x86__) || defined(__x86_64__)) + +#define FUNCTION_fixnormz_D +#define FUNCTION_fixnorm_D + +inline INT fixnormz_D(LONG value) { + INT result; + + if (value != 0) { + result = __builtin_clz(value); + } else { + result = 32; + } + return result; +} + +inline INT fixnorm_D(LONG value) { + INT result; + if (value == 0) { + return 0; + } + if (value < 0) { + value = ~value; + } + result = fixnormz_D(value); + return result - 1; +} + +#elif (_MSC_VER > 1200) && (defined(_M_IX86) || defined(_M_X64)) + +#include + +#define FUNCTION_fixnormz_D +#define FUNCTION_fixnorm_D + +inline INT fixnormz_D(LONG value) { + unsigned long result = 0; + unsigned char err; + err = _BitScanReverse(&result, value); + if (err) { + return 31 - result; + } else { + return 32; + } +} + +inline INT fixnorm_D(LONG value) { + INT result; + if (value == 0) { + return 0; + } + if (value < 0) { + value = ~value; + } + result = fixnormz_D(value); + return result - 1; +} + +#endif /* toolchain */ +#endif /* !defined(CLZ_X86_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/fixmul_x86.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/fixmul_x86.h new file mode 100644 index 0000000000000..84e631693d229 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/fixmul_x86.h @@ -0,0 +1,187 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(FIXMUL_X86_H) +#define FIXMUL_X86_H + +#if defined(__x86__) + +#if defined(_MSC_VER) && defined(_M_IX86) +/* Intel x86 */ + +#define FUNCTION_fixmul_DD +#define FUNCTION_fixmuldiv2_DD +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a, b) fixmuldiv2_DD(a, b) +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD(a, b) fixmul_DD(a, b) + +#define FUNCTION_fixmuldiv2BitExact_DS +#define fixmuldiv2BitExact_DS(a, b) fixmuldiv2_DS(a, b) + +#define FUNCTION_fixmulBitExact_DS +#define fixmulBitExact_DS(a, b) fixmul_DS(a, b) + +inline INT fixmul_DD(INT a, const INT b) { + __asm + { + mov eax, a + imul b + shl edx, 1 + mov a, edx + } + return a; +} + +inline INT fixmuldiv2_DD(INT a, const INT b) { + __asm + { + mov eax, a + imul b + mov a, edx + } + return a; +} + +/* ############################################################################# + */ +#elif (defined(__GNUC__) || defined(__gnu_linux__)) && defined(__x86__) + +#define FUNCTION_fixmul_DD +#define FUNCTION_fixmuldiv2_DD + +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a, b) fixmuldiv2_DD(a, b) + +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD(a, b) fixmul_DD(a, b) + +#define FUNCTION_fixmuldiv2BitExact_DS +#define fixmuldiv2BitExact_DS(a, b) fixmuldiv2_DS(a, b) + +#define FUNCTION_fixmulBitExact_DS +#define fixmulBitExact_DS(a, b) fixmul_DS(a, b) + +inline INT fixmul_DD(INT a, const INT b) { + INT result; + + asm("imul %2;\n" + "shl $1, %0;\n" + : "=d"(result), "+a"(a) + : "r"(b)); + + return result; +} + +inline INT fixmuldiv2_DD(INT a, const INT b) { + INT result; + + asm("imul %2;" : "=d"(result), "+a"(a) : "r"(b)); + + return result; +} + +#endif /* (defined(__GNUC__)||defined(__gnu_linux__)) && defined(__x86__) */ + +#endif /* __x86__ */ + +#endif /* !defined(FIXMUL_X86_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/fixpoint_math_x86.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/fixpoint_math_x86.h new file mode 100644 index 0000000000000..d81fb2661eeb1 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/include/x86/fixpoint_math_x86.h @@ -0,0 +1,208 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander + + Description: Fixed point specific mathematical functions for x86 + +*******************************************************************************/ + +#if !defined(FIXPOINT_MATH_X86_H) +#define FIXPOINT_MATH_X86_H + +#define FUNCTION_sqrtFixp + +#include + +#ifdef FUNCTION_sqrtFixp +static inline FIXP_DBL sqrtFixp(const FIXP_DBL op) { + FIXP_DBL result; + /* result = + * (FIXP_DBL)(INT)(sqrt((double)(INT)op)*46340.950011841578559133736114903); + */ + result = (FIXP_DBL)(INT)(sqrt((float)(INT)op) * 46340.9492f); + FDK_ASSERT(result >= (FIXP_DBL)0); + return result; +} +#endif /* FUNCTION_sqrtFixp */ + +#include + +#define FUNCTION_invSqrtNorm2 +/** + * \brief calculate 1.0/sqrt(op) + * \param op_m mantissa of input value. + * \param result_e pointer to return the exponent of the result + * \return mantissa of the result + */ +#ifdef FUNCTION_invSqrtNorm2 +inline FIXP_DBL invSqrtNorm2(FIXP_DBL op_m, INT *result_e) { + float result; + if (op_m == (FIXP_DBL)0) { + *result_e = 16; + return ((LONG)0x7fffffff); + } + result = (float)(1.0 / sqrt(0.5f * (float)(INT)op_m)); + result = (float)ldexp(frexpf(result, result_e), DFRACT_BITS - 1); + *result_e += 15; + + FDK_ASSERT(result >= 0); + return (FIXP_DBL)(INT)result; +} +#endif /* FUNCTION_invSqrtNorm2 */ + +#define FUNCTION_invFixp +/** + * \brief calculate 1.0/op + * \param op mantissa of the input value. + * \return mantissa of the result with implizit exponent of 31 + */ +#ifdef FUNCTION_invFixp +inline FIXP_DBL invFixp(FIXP_DBL op) { + float result; + INT result_e; + if ((op == (FIXP_DBL)0) || (op == (FIXP_DBL)1)) { + return ((LONG)0x7fffffff); + } + result = (float)(1.0 / (float)(INT)op); + result = frexpf(result, &result_e); + result = ldexpf(result, 31 + result_e); + + return (FIXP_DBL)(INT)result; +} + +/** + * \brief calculate 1.0/(op_m * 2^op_e) + * \param op_m mantissa of the input value. + * \param op_e pointer into were the exponent of the input value is stored, and + * the result will be stored into. + * \return mantissa of the result + */ +inline FIXP_DBL invFixp(FIXP_DBL op_m, int *op_e) { + float result; + INT result_e; + if ((op_m == (FIXP_DBL)0x00000000) || (op_m == (FIXP_DBL)0x00000001)) { + *op_e = 31 - *op_e; + return ((LONG)0x7fffffff); + } + result = (float)(1.0 / (float)(INT)op_m); + result = ldexpf(frexpf(result, &result_e), DFRACT_BITS - 1); + *op_e = result_e - *op_e + 31; + return (FIXP_DBL)(INT)result; +} +#endif /* FUNCTION_invFixp */ + +#define FUNCTION_schur_div +/** + * \brief Divide two FIXP_DBL values with given precision. + * \param num dividend + * \param denum divisor + * \param count amount of significant bits of the result (starting to the MSB) + * \return num/divisor + */ +#ifdef FUNCTION_schur_div +inline FIXP_DBL schur_div(FIXP_DBL num, FIXP_DBL denum, INT count) { + (void)count; + /* same asserts than for fallback implementation */ + FDK_ASSERT(num >= (FIXP_DBL)0); + FDK_ASSERT(denum > (FIXP_DBL)0); + FDK_ASSERT(num <= denum); + + return (num == denum) ? (FIXP_DBL)MAXVAL_DBL + : (FIXP_DBL)(INT)(((INT64)(INT)num << 31) / (INT)denum); +} +#endif /* FUNCTION_schur_div */ +#endif /* !defined(FIXPOINT_MATH_X86_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_bitbuffer.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_bitbuffer.cpp new file mode 100644 index 0000000000000..9b7f5b87ed03b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_bitbuffer.cpp @@ -0,0 +1,492 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser + + Description: common bitbuffer read/write routines + +*******************************************************************************/ + +#include "FDK_bitbuffer.h" + +#include "genericStds.h" +#include "common_fix.h" +#include "fixminmax.h" + +const UINT BitMask[32 + 1] = { + 0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, + 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, + 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff, 0x1ffff, + 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, + 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, + 0x3fffffff, 0x7fffffff, 0xffffffff}; + +void FDK_CreateBitBuffer(HANDLE_FDK_BITBUF *hBitBuf, UCHAR *pBuffer, + UINT bufSize) { + FDK_InitBitBuffer(*hBitBuf, pBuffer, bufSize, 0); + + FDKmemclear((*hBitBuf)->Buffer, bufSize * sizeof(UCHAR)); +} + +void FDK_DeleteBitBuffer(HANDLE_FDK_BITBUF hBitBuf) { ; } + +void FDK_InitBitBuffer(HANDLE_FDK_BITBUF hBitBuf, UCHAR *pBuffer, UINT bufSize, + UINT validBits) { + hBitBuf->ValidBits = validBits; + hBitBuf->ReadOffset = 0; + hBitBuf->WriteOffset = 0; + hBitBuf->BitNdx = 0; + + hBitBuf->Buffer = pBuffer; + hBitBuf->bufSize = bufSize; + hBitBuf->bufBits = (bufSize << 3); + /*assure bufsize (2^n) */ + FDK_ASSERT(hBitBuf->ValidBits <= hBitBuf->bufBits); + FDK_ASSERT((bufSize > 0) && (bufSize <= MAX_BUFSIZE_BYTES)); + { + UINT x = 0, n = bufSize; + for (x = 0; n > 0; x++, n >>= 1) { + } + if (bufSize != ((UINT)1 << (x - 1))) { + FDK_ASSERT(0); + } + } +} + +void FDK_ResetBitBuffer(HANDLE_FDK_BITBUF hBitBuf) { + hBitBuf->ValidBits = 0; + hBitBuf->ReadOffset = 0; + hBitBuf->WriteOffset = 0; + hBitBuf->BitNdx = 0; +} + +#ifndef FUNCTION_FDK_get +INT FDK_get(HANDLE_FDK_BITBUF hBitBuf, const UINT numberOfBits) { + UINT byteOffset = hBitBuf->BitNdx >> 3; + UINT bitOffset = hBitBuf->BitNdx & 0x07; + + hBitBuf->BitNdx = (hBitBuf->BitNdx + numberOfBits) & (hBitBuf->bufBits - 1); + hBitBuf->ValidBits -= numberOfBits; + + UINT byteMask = hBitBuf->bufSize - 1; + + UINT tx = (hBitBuf->Buffer[byteOffset & byteMask] << 24) | + (hBitBuf->Buffer[(byteOffset + 1) & byteMask] << 16) | + (hBitBuf->Buffer[(byteOffset + 2) & byteMask] << 8) | + hBitBuf->Buffer[(byteOffset + 3) & byteMask]; + + if (bitOffset) { + tx <<= bitOffset; + tx |= hBitBuf->Buffer[(byteOffset + 4) & byteMask] >> (8 - bitOffset); + } + + return (tx >> (32 - numberOfBits)); +} +#endif /* #ifndef FUNCTION_FDK_get */ + +#ifndef FUNCTION_FDK_get32 +INT FDK_get32(HANDLE_FDK_BITBUF hBitBuf) { + UINT BitNdx = hBitBuf->BitNdx + 32; + hBitBuf->BitNdx = BitNdx & (hBitBuf->bufBits - 1); + hBitBuf->ValidBits = (UINT)((INT)hBitBuf->ValidBits - (INT)32); + + UINT byteOffset = (BitNdx - 1) >> 3; + if (BitNdx <= hBitBuf->bufBits) { + UINT cache = (hBitBuf->Buffer[(byteOffset - 3)] << 24) | + (hBitBuf->Buffer[(byteOffset - 2)] << 16) | + (hBitBuf->Buffer[(byteOffset - 1)] << 8) | + hBitBuf->Buffer[(byteOffset - 0)]; + + if ((BitNdx = (BitNdx & 7)) != 0) { + cache = (cache >> (8 - BitNdx)) | + ((UINT)hBitBuf->Buffer[byteOffset - 4] << (24 + BitNdx)); + } + return (cache); + } else { + UINT byte_mask = hBitBuf->bufSize - 1; + UINT cache = (hBitBuf->Buffer[(byteOffset - 3) & byte_mask] << 24) | + (hBitBuf->Buffer[(byteOffset - 2) & byte_mask] << 16) | + (hBitBuf->Buffer[(byteOffset - 1) & byte_mask] << 8) | + hBitBuf->Buffer[(byteOffset - 0) & byte_mask]; + + if ((BitNdx = (BitNdx & 7)) != 0) { + cache = (cache >> (8 - BitNdx)) | + ((UINT)hBitBuf->Buffer[(byteOffset - 4) & byte_mask] + << (24 + BitNdx)); + } + return (cache); + } +} +#endif + +INT FDK_getBwd(HANDLE_FDK_BITBUF hBitBuf, const UINT numberOfBits) { + UINT byteOffset = hBitBuf->BitNdx >> 3; + UINT bitOffset = hBitBuf->BitNdx & 0x07; + UINT byteMask = hBitBuf->bufSize - 1; + int i; + + hBitBuf->BitNdx = (hBitBuf->BitNdx - numberOfBits) & (hBitBuf->bufBits - 1); + hBitBuf->ValidBits += numberOfBits; + + UINT tx = hBitBuf->Buffer[(byteOffset - 3) & byteMask] << 24 | + hBitBuf->Buffer[(byteOffset - 2) & byteMask] << 16 | + hBitBuf->Buffer[(byteOffset - 1) & byteMask] << 8 | + hBitBuf->Buffer[byteOffset & byteMask]; + UINT txa = 0x0; + + tx >>= (8 - bitOffset); + + if (bitOffset && numberOfBits > 24) { + tx |= hBitBuf->Buffer[(byteOffset - 4) & byteMask] << (24 + bitOffset); + } + + /* in place turn around */ + for (i = 0; i < 16; i++) { + UINT bitMaskR = 0x00000001 << i; + UINT bitMaskL = 0x80000000 >> i; + + txa |= (tx & bitMaskR) << (31 - (i << 1)); + txa |= (tx & bitMaskL) >> (31 - (i << 1)); + } + + return (txa >> (32 - numberOfBits)); +} + +void FDK_put(HANDLE_FDK_BITBUF hBitBuf, UINT value, const UINT numberOfBits) { + if (numberOfBits != 0) { + UINT byteOffset0 = hBitBuf->BitNdx >> 3; + UINT bitOffset = hBitBuf->BitNdx & 0x7; + + hBitBuf->BitNdx = (hBitBuf->BitNdx + numberOfBits) & (hBitBuf->bufBits - 1); + hBitBuf->ValidBits += numberOfBits; + + UINT byteMask = hBitBuf->bufSize - 1; + + UINT byteOffset1 = (byteOffset0 + 1) & byteMask; + UINT byteOffset2 = (byteOffset0 + 2) & byteMask; + UINT byteOffset3 = (byteOffset0 + 3) & byteMask; + + // Create tmp containing free bits at the left border followed by bits to + // write, LSB's are cleared, if available Create mask to apply upon all + // buffer bytes + UINT tmp = (value << (32 - numberOfBits)) >> bitOffset; + UINT mask = ~((BitMask[numberOfBits] << (32 - numberOfBits)) >> bitOffset); + + // read all 4 bytes from buffer and create a 32-bit cache + UINT cache = (((UINT)hBitBuf->Buffer[byteOffset0]) << 24) | + (((UINT)hBitBuf->Buffer[byteOffset1]) << 16) | + (((UINT)hBitBuf->Buffer[byteOffset2]) << 8) | + (((UINT)hBitBuf->Buffer[byteOffset3]) << 0); + + cache = (cache & mask) | tmp; + hBitBuf->Buffer[byteOffset0] = (UCHAR)(cache >> 24); + hBitBuf->Buffer[byteOffset1] = (UCHAR)(cache >> 16); + hBitBuf->Buffer[byteOffset2] = (UCHAR)(cache >> 8); + hBitBuf->Buffer[byteOffset3] = (UCHAR)(cache >> 0); + + if ((bitOffset + numberOfBits) > 32) { + UINT byteOffset4 = (byteOffset0 + 4) & byteMask; + // remaining bits: in range 1..7 + // replace MSBits of next byte in buffer by LSBits of "value" + int bits = (bitOffset + numberOfBits) & 7; + cache = + (UINT)hBitBuf->Buffer[byteOffset4] & (~(BitMask[bits] << (8 - bits))); + cache |= value << (8 - bits); + hBitBuf->Buffer[byteOffset4] = (UCHAR)cache; + } + } +} + +void FDK_putBwd(HANDLE_FDK_BITBUF hBitBuf, UINT value, + const UINT numberOfBits) { + UINT byteOffset = hBitBuf->BitNdx >> 3; + UINT bitOffset = 7 - (hBitBuf->BitNdx & 0x07); + UINT byteMask = hBitBuf->bufSize - 1; + + UINT mask = ~(BitMask[numberOfBits] << bitOffset); + UINT tmp = 0x0000; + int i; + + hBitBuf->BitNdx = (hBitBuf->BitNdx - numberOfBits) & (hBitBuf->bufBits - 1); + hBitBuf->ValidBits -= numberOfBits; + + /* in place turn around */ + for (i = 0; i < 16; i++) { + UINT bitMaskR = 0x00000001 << i; + UINT bitMaskL = 0x80000000 >> i; + + tmp |= (value & bitMaskR) << (31 - (i << 1)); + tmp |= (value & bitMaskL) >> (31 - (i << 1)); + } + value = tmp; + tmp = value >> (32 - numberOfBits) << bitOffset; + + hBitBuf->Buffer[byteOffset & byteMask] = + (hBitBuf->Buffer[byteOffset & byteMask] & (mask)) | (UCHAR)(tmp); + hBitBuf->Buffer[(byteOffset - 1) & byteMask] = + (hBitBuf->Buffer[(byteOffset - 1) & byteMask] & (mask >> 8)) | + (UCHAR)(tmp >> 8); + hBitBuf->Buffer[(byteOffset - 2) & byteMask] = + (hBitBuf->Buffer[(byteOffset - 2) & byteMask] & (mask >> 16)) | + (UCHAR)(tmp >> 16); + hBitBuf->Buffer[(byteOffset - 3) & byteMask] = + (hBitBuf->Buffer[(byteOffset - 3) & byteMask] & (mask >> 24)) | + (UCHAR)(tmp >> 24); + + if ((bitOffset + numberOfBits) > 32) { + hBitBuf->Buffer[(byteOffset - 4) & byteMask] = + (UCHAR)(value >> (64 - numberOfBits - bitOffset)) | + (hBitBuf->Buffer[(byteOffset - 4) & byteMask] & + ~(BitMask[bitOffset] >> (32 - numberOfBits))); + } +} + +#ifndef FUNCTION_FDK_pushBack +void FDK_pushBack(HANDLE_FDK_BITBUF hBitBuf, const UINT numberOfBits, + UCHAR config) { + hBitBuf->ValidBits = + (config == 0) ? (UINT)((INT)hBitBuf->ValidBits + (INT)numberOfBits) + : ((UINT)((INT)hBitBuf->ValidBits - (INT)numberOfBits)); + hBitBuf->BitNdx = ((UINT)((INT)hBitBuf->BitNdx - (INT)numberOfBits)) & + (hBitBuf->bufBits - 1); +} +#endif + +void FDK_pushForward(HANDLE_FDK_BITBUF hBitBuf, const UINT numberOfBits, + UCHAR config) { + hBitBuf->ValidBits = + (config == 0) ? ((UINT)((INT)hBitBuf->ValidBits - (INT)numberOfBits)) + : (UINT)((INT)hBitBuf->ValidBits + (INT)numberOfBits); + hBitBuf->BitNdx = + (UINT)((INT)hBitBuf->BitNdx + (INT)numberOfBits) & (hBitBuf->bufBits - 1); +} + +#ifndef FUNCTION_FDK_getValidBits +UINT FDK_getValidBits(HANDLE_FDK_BITBUF hBitBuf) { return hBitBuf->ValidBits; } +#endif /* #ifndef FUNCTION_FDK_getValidBits */ + +INT FDK_getFreeBits(HANDLE_FDK_BITBUF hBitBuf) { + return (hBitBuf->bufBits - hBitBuf->ValidBits); +} + +void FDK_Feed(HANDLE_FDK_BITBUF hBitBuf, const UCHAR *RESTRICT inputBuffer, + const UINT bufferSize, UINT *bytesValid) { + inputBuffer = &inputBuffer[bufferSize - *bytesValid]; + + UINT bTotal = 0; + + UINT bToRead = + fMin(hBitBuf->bufBits, + (UINT)fMax(0, ((INT)hBitBuf->bufBits - (INT)hBitBuf->ValidBits))) >> + 3; + UINT noOfBytes = + fMin(bToRead, + *bytesValid); //(bToRead < *bytesValid) ? bToRead : *bytesValid ; + + while (noOfBytes > 0) { + /* split read to buffer size */ + bToRead = hBitBuf->bufSize - hBitBuf->ReadOffset; + bToRead = fMin(bToRead, + noOfBytes); //(bToRead < noOfBytes) ? bToRead : noOfBytes ; + + /* copy 'bToRead' bytes from 'ptr' to inputbuffer */ + FDKmemcpy(&hBitBuf->Buffer[hBitBuf->ReadOffset], inputBuffer, + bToRead * sizeof(UCHAR)); + + /* add noOfBits to number of valid bits in buffer */ + hBitBuf->ValidBits = (UINT)((INT)hBitBuf->ValidBits + (INT)(bToRead << 3)); + bTotal += bToRead; + inputBuffer += bToRead; + + hBitBuf->ReadOffset = + (hBitBuf->ReadOffset + bToRead) & (hBitBuf->bufSize - 1); + noOfBytes -= bToRead; + } + + *bytesValid -= bTotal; +} + +void CopyAlignedBlock(HANDLE_FDK_BITBUF h_BitBufSrc, UCHAR *RESTRICT dstBuffer, + UINT bToRead) { + UINT byteOffset = h_BitBufSrc->BitNdx >> 3; + const UINT byteMask = h_BitBufSrc->bufSize - 1; + + UCHAR *RESTRICT pBBB = h_BitBufSrc->Buffer; + for (UINT i = 0; i < bToRead; i++) { + dstBuffer[i] = pBBB[(byteOffset + i) & byteMask]; + } + + bToRead <<= 3; + + h_BitBufSrc->BitNdx = + (h_BitBufSrc->BitNdx + bToRead) & (h_BitBufSrc->bufBits - 1); + h_BitBufSrc->ValidBits -= bToRead; +} + +void FDK_Copy(HANDLE_FDK_BITBUF h_BitBufDst, HANDLE_FDK_BITBUF h_BitBufSrc, + UINT *bytesValid) { + INT bTotal = 0; + + /* limit noOfBytes to valid bytes in src buffer and available bytes in dst + * buffer */ + UINT bToRead = h_BitBufSrc->ValidBits >> 3; + UINT noOfBytes = + fMin(bToRead, + *bytesValid); //(*bytesValid < bToRead) ? *bytesValid : bToRead ; + bToRead = FDK_getFreeBits(h_BitBufDst); + noOfBytes = + fMin(bToRead, noOfBytes); //(bToRead < noOfBytes) ? bToRead : noOfBytes; + + while (noOfBytes > 0) { + /* Split Read to buffer size */ + bToRead = h_BitBufDst->bufSize - h_BitBufDst->ReadOffset; + bToRead = fMin(noOfBytes, + bToRead); //(noOfBytes < bToRead) ? noOfBytes : bToRead ; + + /* copy 'bToRead' bytes from buffer to buffer */ + if (!(h_BitBufSrc->BitNdx & 0x07)) { + CopyAlignedBlock(h_BitBufSrc, + h_BitBufDst->Buffer + h_BitBufDst->ReadOffset, bToRead); + } else { + for (UINT i = 0; i < bToRead; i++) { + h_BitBufDst->Buffer[h_BitBufDst->ReadOffset + i] = + (UCHAR)FDK_get(h_BitBufSrc, 8); + } + } + + /* add noOfBits to number of valid bits in buffer */ + h_BitBufDst->ValidBits += bToRead << 3; + bTotal += bToRead; + + h_BitBufDst->ReadOffset = + (h_BitBufDst->ReadOffset + bToRead) & (h_BitBufDst->bufSize - 1); + noOfBytes -= bToRead; + } + + *bytesValid -= bTotal; +} + +void FDK_Fetch(HANDLE_FDK_BITBUF hBitBuf, UCHAR *outBuf, UINT *writeBytes) { + UCHAR *RESTRICT outputBuffer = outBuf; + UINT bTotal = 0; + + UINT bToWrite = (hBitBuf->ValidBits) >> 3; + UINT noOfBytes = + fMin(bToWrite, + *writeBytes); //(bToWrite < *writeBytes) ? bToWrite : *writeBytes ; + + while (noOfBytes > 0) { + /* split write to buffer size */ + bToWrite = hBitBuf->bufSize - hBitBuf->WriteOffset; + bToWrite = fMin( + bToWrite, noOfBytes); //(bToWrite < noOfBytes) ? bToWrite : noOfBytes ; + + /* copy 'bToWrite' bytes from bitbuffer to outputbuffer */ + FDKmemcpy(outputBuffer, &hBitBuf->Buffer[hBitBuf->WriteOffset], + bToWrite * sizeof(UCHAR)); + + /* sub noOfBits from number of valid bits in buffer */ + hBitBuf->ValidBits -= bToWrite << 3; + bTotal += bToWrite; + outputBuffer += bToWrite; + + hBitBuf->WriteOffset = + (hBitBuf->WriteOffset + bToWrite) & (hBitBuf->bufSize - 1); + noOfBytes -= bToWrite; + } + + *writeBytes = bTotal; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_core.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_core.cpp new file mode 100644 index 0000000000000..48db17e15c7a5 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_core.cpp @@ -0,0 +1,145 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander + + Description: FDK tools versioning support + +*******************************************************************************/ + +#include "FDK_core.h" + +/* FDK tools library info */ +#define FDK_TOOLS_LIB_VL0 3 +#define FDK_TOOLS_LIB_VL1 1 +#define FDK_TOOLS_LIB_VL2 0 +#define FDK_TOOLS_LIB_TITLE "FDK Tools" +#ifdef SUPPRESS_BUILD_DATE_INFO +#define FDK_TOOLS_LIB_BUILD_DATE "" +#define FDK_TOOLS_LIB_BUILD_TIME "" +#else +#define FDK_TOOLS_LIB_BUILD_DATE __DATE__ +#define FDK_TOOLS_LIB_BUILD_TIME __TIME__ +#endif + +int FDK_toolsGetLibInfo(LIB_INFO *info) { + UINT v; + int i; + + if (info == NULL) { + return -1; + } + + /* search for next free tab */ + i = FDKlibInfo_lookup(info, FDK_TOOLS); + if (i < 0) return -1; + + info += i; + + v = LIB_VERSION(FDK_TOOLS_LIB_VL0, FDK_TOOLS_LIB_VL1, FDK_TOOLS_LIB_VL2); + + FDKsprintf(info->versionStr, "%d.%d.%d", ((v >> 24) & 0xff), + ((v >> 16) & 0xff), ((v >> 8) & 0xff)); + + info->module_id = FDK_TOOLS; + info->version = v; + info->build_date = FDK_TOOLS_LIB_BUILD_DATE; + info->build_time = FDK_TOOLS_LIB_BUILD_TIME; + info->title = FDK_TOOLS_LIB_TITLE; + info->flags = 1; + + return 0; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_crc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_crc.cpp new file mode 100644 index 0000000000000..e2083383f0814 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_crc.cpp @@ -0,0 +1,479 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: CRC calculation + +*******************************************************************************/ + +#include "FDK_crc.h" + +/*---------------- constants -----------------------*/ + +/** + * \brief This table defines precalculated lookup tables for crc polynom x^16 + * + x^15 + x^2 + x^0. + */ +static const USHORT crcLookup_16_15_2_0[256] = { + 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, + 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, 0x8063, 0x0066, + 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, 0x0050, 0x8055, 0x805f, + 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, 0x80c3, 0x00c6, 0x00cc, 0x80c9, + 0x00d8, 0x80dd, 0x80d7, 0x00d2, 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, + 0x00ee, 0x00e4, 0x80e1, 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, + 0x00b4, 0x80b1, 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, + 0x0082, 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, + 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, 0x01e0, + 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, 0x81d3, 0x01d6, + 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, 0x0140, 0x8145, 0x814f, + 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, 0x8173, 0x0176, 0x017c, 0x8179, + 0x0168, 0x816d, 0x8167, 0x0162, 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, + 0x813d, 0x8137, 0x0132, 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, + 0x0104, 0x8101, 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, + 0x0312, 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, 0x8353, + 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, 0x03c0, 0x83c5, + 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, 0x83f3, 0x03f6, 0x03fc, + 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, 0x83a3, 0x03a6, 0x03ac, 0x83a9, + 0x03b8, 0x83bd, 0x83b7, 0x03b2, 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, + 0x038e, 0x0384, 0x8381, 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, + 0x0294, 0x8291, 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, + 0x02a2, 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, + 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, 0x8243, + 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, 0x0270, 0x8275, + 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, 0x0220, 0x8225, 0x822f, + 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, 0x8213, 0x0216, 0x021c, 0x8219, + 0x0208, 0x820d, 0x8207, 0x0202}; + +/** + * \brief This table defines precalculated lookup tables for crc polynom x^16 + * + x^12 + x^5 + x^0. + */ +static const USHORT crcLookup_16_12_5_0[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, + 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, + 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, + 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, + 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, + 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, + 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, + 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, + 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, + 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, + 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, + 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, + 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, + 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, + 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, + 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, + 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, + 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, + 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, + 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, + 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, + 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, + 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, + 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, + 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, + 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; + +/** + * \brief This table defines precalculated lookup tables for crc polynom x^16 + * + x^15 + x^5 + x^0. + */ + +static const USHORT crcLookup_16_15_5_0[256] = { + 0x0000, 0x8021, 0x8063, 0x0042, 0x80e7, 0x00c6, 0x0084, 0x80a5, 0x81ef, + 0x01ce, 0x018c, 0x81ad, 0x0108, 0x8129, 0x816b, 0x014a, 0x83ff, 0x03de, + 0x039c, 0x83bd, 0x0318, 0x8339, 0x837b, 0x035a, 0x0210, 0x8231, 0x8273, + 0x0252, 0x82f7, 0x02d6, 0x0294, 0x82b5, 0x87df, 0x07fe, 0x07bc, 0x879d, + 0x0738, 0x8719, 0x875b, 0x077a, 0x0630, 0x8611, 0x8653, 0x0672, 0x86d7, + 0x06f6, 0x06b4, 0x8695, 0x0420, 0x8401, 0x8443, 0x0462, 0x84c7, 0x04e6, + 0x04a4, 0x8485, 0x85cf, 0x05ee, 0x05ac, 0x858d, 0x0528, 0x8509, 0x854b, + 0x056a, 0x8f9f, 0x0fbe, 0x0ffc, 0x8fdd, 0x0f78, 0x8f59, 0x8f1b, 0x0f3a, + 0x0e70, 0x8e51, 0x8e13, 0x0e32, 0x8e97, 0x0eb6, 0x0ef4, 0x8ed5, 0x0c60, + 0x8c41, 0x8c03, 0x0c22, 0x8c87, 0x0ca6, 0x0ce4, 0x8cc5, 0x8d8f, 0x0dae, + 0x0dec, 0x8dcd, 0x0d68, 0x8d49, 0x8d0b, 0x0d2a, 0x0840, 0x8861, 0x8823, + 0x0802, 0x88a7, 0x0886, 0x08c4, 0x88e5, 0x89af, 0x098e, 0x09cc, 0x89ed, + 0x0948, 0x8969, 0x892b, 0x090a, 0x8bbf, 0x0b9e, 0x0bdc, 0x8bfd, 0x0b58, + 0x8b79, 0x8b3b, 0x0b1a, 0x0a50, 0x8a71, 0x8a33, 0x0a12, 0x8ab7, 0x0a96, + 0x0ad4, 0x8af5, 0x9f1f, 0x1f3e, 0x1f7c, 0x9f5d, 0x1ff8, 0x9fd9, 0x9f9b, + 0x1fba, 0x1ef0, 0x9ed1, 0x9e93, 0x1eb2, 0x9e17, 0x1e36, 0x1e74, 0x9e55, + 0x1ce0, 0x9cc1, 0x9c83, 0x1ca2, 0x9c07, 0x1c26, 0x1c64, 0x9c45, 0x9d0f, + 0x1d2e, 0x1d6c, 0x9d4d, 0x1de8, 0x9dc9, 0x9d8b, 0x1daa, 0x18c0, 0x98e1, + 0x98a3, 0x1882, 0x9827, 0x1806, 0x1844, 0x9865, 0x992f, 0x190e, 0x194c, + 0x996d, 0x19c8, 0x99e9, 0x99ab, 0x198a, 0x9b3f, 0x1b1e, 0x1b5c, 0x9b7d, + 0x1bd8, 0x9bf9, 0x9bbb, 0x1b9a, 0x1ad0, 0x9af1, 0x9ab3, 0x1a92, 0x9a37, + 0x1a16, 0x1a54, 0x9a75, 0x1080, 0x90a1, 0x90e3, 0x10c2, 0x9067, 0x1046, + 0x1004, 0x9025, 0x916f, 0x114e, 0x110c, 0x912d, 0x1188, 0x91a9, 0x91eb, + 0x11ca, 0x937f, 0x135e, 0x131c, 0x933d, 0x1398, 0x93b9, 0x93fb, 0x13da, + 0x1290, 0x92b1, 0x92f3, 0x12d2, 0x9277, 0x1256, 0x1214, 0x9235, 0x975f, + 0x177e, 0x173c, 0x971d, 0x17b8, 0x9799, 0x97db, 0x17fa, 0x16b0, 0x9691, + 0x96d3, 0x16f2, 0x9657, 0x1676, 0x1634, 0x9615, 0x14a0, 0x9481, 0x94c3, + 0x14e2, 0x9447, 0x1466, 0x1424, 0x9405, 0x954f, 0x156e, 0x152c, 0x950d, + 0x15a8, 0x9589, 0x95cb, 0x15ea, +}; + +/*--------------- function declarations --------------------*/ + +static inline INT calcCrc_Bits(USHORT *const pCrc, USHORT crcMask, + USHORT crcPoly, HANDLE_FDK_BITSTREAM hBs, + INT nBits); + +static inline INT calcCrc_Bytes(USHORT *const pCrc, const USHORT *pCrcLookup, + HANDLE_FDK_BITSTREAM hBs, INT nBytes); + +static void crcCalc(HANDLE_FDK_CRCINFO hCrcInfo, HANDLE_FDK_BITSTREAM hBs, + const INT reg); + +/*------------- function definitions ----------------*/ + +void FDKcrcInit(HANDLE_FDK_CRCINFO hCrcInfo, const UINT crcPoly, + const UINT crcStartValue, const UINT crcLen) { + /* crc polynom example: + x^16 + x^15 + x^5 + x^0 (1) 1000 0000 0010 0001 -> 0x8021 + x^16 + x^15 + x^2 + x^0 (1) 1000 0000 0000 0101 -> 0x8005 + x^16 + x^12 + x^5 + x^0 (1) 0001 0000 0010 0001 -> 0x1021 + x^8 + x^4 + x^3 + x^2 + x^0 (1) 0001 1101 -> 0x001d */ + + hCrcInfo->crcLen = crcLen; + hCrcInfo->crcPoly = crcPoly; + hCrcInfo->startValue = crcStartValue; + hCrcInfo->crcMask = (crcLen) ? (1 << (crcLen - 1)) : 0; + + FDKcrcReset(hCrcInfo); + + hCrcInfo->pCrcLookup = + 0; /* Preset 0 for "crcLen" != 16 or unknown 16-bit polynoms "crcPoly" */ + + if (hCrcInfo->crcLen == 16) { + switch (crcPoly) { + case 0x8021: + hCrcInfo->pCrcLookup = crcLookup_16_15_5_0; + break; + case 0x8005: + hCrcInfo->pCrcLookup = crcLookup_16_15_2_0; + break; + case 0x1021: + hCrcInfo->pCrcLookup = crcLookup_16_12_5_0; + break; + case 0x001d: + default: + /* no lookup table */ + break; + } + } +} + +void FDKcrcReset(HANDLE_FDK_CRCINFO hCrcInfo) { + int i; + + hCrcInfo->crcValue = hCrcInfo->startValue; + + for (i = 0; i < MAX_CRC_REGS; i++) { + hCrcInfo->crcRegData[i].isActive = 0; + } + hCrcInfo->regStart = 0; + hCrcInfo->regStop = 0; +} + +INT FDKcrcStartReg(HANDLE_FDK_CRCINFO hCrcInfo, const HANDLE_FDK_BITSTREAM hBs, + const INT mBits) { + int reg = hCrcInfo->regStart; + + FDK_ASSERT(hCrcInfo->crcRegData[reg].isActive == 0); + hCrcInfo->crcRegData[reg].isActive = 1; + hCrcInfo->crcRegData[reg].maxBits = mBits; + hCrcInfo->crcRegData[reg].validBits = (INT)FDKgetValidBits(hBs); + hCrcInfo->crcRegData[reg].bitBufCntBits = 0; + + hCrcInfo->regStart = (hCrcInfo->regStart + 1) % MAX_CRC_REGS; + + return (reg); +} + +INT FDKcrcEndReg(HANDLE_FDK_CRCINFO hCrcInfo, const HANDLE_FDK_BITSTREAM hBs, + const INT reg) { + FDK_ASSERT((reg == (INT)hCrcInfo->regStop) && + (hCrcInfo->crcRegData[reg].isActive == 1)); + + if (hBs->ConfigCache == BS_WRITER) { + hCrcInfo->crcRegData[reg].bitBufCntBits = + (INT)FDKgetValidBits(hBs) - hCrcInfo->crcRegData[reg].validBits; + } else { + hCrcInfo->crcRegData[reg].bitBufCntBits = + hCrcInfo->crcRegData[reg].validBits - (INT)FDKgetValidBits(hBs); + } + + if (hCrcInfo->crcRegData[reg].maxBits == 0) { + hCrcInfo->crcRegData[reg].maxBits = hCrcInfo->crcRegData[reg].bitBufCntBits; + } + + crcCalc(hCrcInfo, hBs, reg); + + hCrcInfo->crcRegData[reg].isActive = 0; + hCrcInfo->regStop = (hCrcInfo->regStop + 1) % MAX_CRC_REGS; + + return 0; +} + +USHORT FDKcrcGetCRC(const HANDLE_FDK_CRCINFO hCrcInfo) { + return (hCrcInfo->crcValue & (((hCrcInfo->crcMask - 1) << 1) + 1)); +} + +/** + * \brief Calculate crc bits. + * + * Calculate crc starting at current bitstream postion over nBits. + * + * \param pCrc Pointer to an outlying allocated crc info + * structure. + * \param crcMask CrcMask in use. + * \param crcPoly Crc polynom in use. + * \param hBs Handle to current bit buffer structure. + * \param nBits Number of processing bits. + * + * \return Number of processed bits. + */ +static inline INT calcCrc_Bits(USHORT *const pCrc, USHORT crcMask, + USHORT crcPoly, HANDLE_FDK_BITSTREAM hBs, + INT nBits) { + int i; + USHORT crc = *pCrc; /* get crc value */ + + if (hBs != NULL) { + for (i = 0; (i < nBits); i++) { + USHORT tmp = FDKreadBit(hBs); // process single bit + tmp ^= ((crc & crcMask) ? 1 : 0); + if (tmp != 0) tmp = crcPoly; + crc <<= 1; + crc ^= tmp; + } + } else { + for (i = 0; (i < nBits); i++) { + USHORT tmp = (crc & crcMask) ? crcPoly : 0; // process single bit + crc <<= 1; + crc ^= tmp; + } + } + *pCrc = crc; /* update crc value */ + + return nBits; +} + +/** + * \brief Calculate crc bytes. + * + * Calculate crc starting at current bitstream postion over nBytes. + * + * \param pCrc Pointer to an outlying allocated crc info + * structure. + * \param pCrcLookup Pointer to lookup table used for fast crc + * calculation. + * \param hBs Handle to current bit buffer structure. + * \param nBits Number of processing bytes. + * + * \return Number of processed bits. + */ + +static inline INT calcCrc_Bytes(USHORT *const pCrc, const USHORT *pCrcLookup, + HANDLE_FDK_BITSTREAM hBs, INT nBytes) { + int i; + USHORT crc = *pCrc; /* get crc value */ + + if (hBs != NULL) { + ULONG data; + INT bits; + for (i = 0; i < (nBytes >> 2); i++) { + data = (ULONG)FDKreadBits(hBs, 32); + crc = + (crc << 8) ^ pCrcLookup[((crc >> 8) ^ ((USHORT)(data >> 24))) & 0xFF]; + crc = + (crc << 8) ^ pCrcLookup[((crc >> 8) ^ ((USHORT)(data >> 16))) & 0xFF]; + crc = + (crc << 8) ^ pCrcLookup[((crc >> 8) ^ ((USHORT)(data >> 8))) & 0xFF]; + crc = + (crc << 8) ^ pCrcLookup[((crc >> 8) ^ ((USHORT)(data >> 0))) & 0xFF]; + } + bits = (nBytes & 3) << 3; + if (bits > 0) { + data = (ULONG)FDKreadBits(hBs, bits); + for (bits -= 8; bits >= 0; bits -= 8) + crc = (crc << 8) ^ + pCrcLookup[((crc >> 8) ^ (USHORT)(data >> bits)) & 0xFF]; + } + } else { + for (i = 0; i < nBytes; i++) { + crc = (crc << 8) ^ pCrcLookup[(crc >> 8) & 0xFF]; + } + } + + *pCrc = crc; /* update crc value */ + + return (nBytes); +} + +/** + * \brief Calculate crc. + * + * Calculate crc. Lenght depends on mBits parameter in FDKcrcStartReg() + * configuration. + * + * \param hCrcInfo Pointer to an outlying allocated crc info + * structure. + * \param hBs Pointer to current bit buffer structure. + * \param reg Crc region ID. + * + * \return Number of processed bits. + */ +static void crcCalc(HANDLE_FDK_CRCINFO hCrcInfo, HANDLE_FDK_BITSTREAM hBs, + const INT reg) { + USHORT crc = hCrcInfo->crcValue; + CCrcRegData *rD = &hCrcInfo->crcRegData[reg]; + FDK_BITSTREAM bsReader; + + if (hBs->ConfigCache == BS_READER) { + bsReader = *hBs; + FDKpushBiDirectional(&bsReader, + -(rD->validBits - (INT)FDKgetValidBits(&bsReader))); + } else { + FDKinitBitStream(&bsReader, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, + hBs->hBitBuf.ValidBits, BS_READER); + FDKpushBiDirectional(&bsReader, rD->validBits); + } + + int bits, rBits; + rBits = (rD->maxBits >= 0) ? rD->maxBits : -rD->maxBits; /* ramaining bits */ + if ((rD->maxBits > 0) && ((rD->bitBufCntBits >> 3 << 3) < rBits)) { + bits = rD->bitBufCntBits; + } else { + bits = rBits; + } + + int words = bits >> 3; /* processing bytes */ + int mBits = bits & 0x7; /* modulo bits */ + + if (hCrcInfo->pCrcLookup) { + rBits -= (calcCrc_Bytes(&crc, hCrcInfo->pCrcLookup, &bsReader, words) << 3); + } else { + rBits -= calcCrc_Bits(&crc, hCrcInfo->crcMask, hCrcInfo->crcPoly, &bsReader, + words << 3); + } + + /* remaining valid bits*/ + if (mBits != 0) { + rBits -= calcCrc_Bits(&crc, hCrcInfo->crcMask, hCrcInfo->crcPoly, &bsReader, + mBits); + } + + if (rBits != 0) { + /* zero bytes */ + if ((hCrcInfo->pCrcLookup) && (rBits > 8)) { + rBits -= + (calcCrc_Bytes(&crc, hCrcInfo->pCrcLookup, NULL, rBits >> 3) << 3); + } + /* remaining zero bits */ + if (rBits != 0) { + calcCrc_Bits(&crc, hCrcInfo->crcMask, hCrcInfo->crcPoly, NULL, rBits); + } + } + + hCrcInfo->crcValue = crc; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_decorrelate.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_decorrelate.cpp new file mode 100644 index 0000000000000..324983a407731 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_decorrelate.cpp @@ -0,0 +1,1714 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Markus Lohwasser + + Description: FDK Tools Decorrelator + +*******************************************************************************/ + +#include "FDK_decorrelate.h" + +#define PC_NUM_BANDS (8) +#define PC_NUM_HYB_BANDS (PC_NUM_BANDS - 3 + 10) + +#define DUCK_ALPHA (0.8f) +#define DUCK_GAMMA (1.5f) +#define ABS_THR (1e-9f * 32768 * 32768) +#define ABS_THR_FDK ((FIXP_DBL)1) + +#define DECORR_ZERO_PADDING 0 + +#define DECORR_FILTER_ORDER_BAND_0_MPS (20) +#define DECORR_FILTER_ORDER_BAND_1_MPS (15) +#define DECORR_FILTER_ORDER_BAND_2_MPS (6) +#define DECORR_FILTER_ORDER_BAND_3_MPS (3) + +#define DECORR_FILTER_ORDER_BAND_0_USAC (10) +#define DECORR_FILTER_ORDER_BAND_1_USAC (8) +#define DECORR_FILTER_ORDER_BAND_2_USAC (3) +#define DECORR_FILTER_ORDER_BAND_3_USAC (2) + +#define DECORR_FILTER_ORDER_BAND_0_LD (0) +#define DECORR_FILTER_ORDER_BAND_1_LD (DECORR_FILTER_ORDER_BAND_1_MPS) +#define DECORR_FILTER_ORDER_BAND_2_LD (DECORR_FILTER_ORDER_BAND_2_MPS) +#define DECORR_FILTER_ORDER_BAND_3_LD (DECORR_FILTER_ORDER_BAND_3_MPS) + +#define MAX_DECORR_SEED_MPS \ + (5) /* 4 is worst case for 7272 mode for low power */ + /* 5 is worst case for 7271 and 7272 mode for high quality */ +#define MAX_DECORR_SEED_USAC (1) +#define MAX_DECORR_SEED_LD (4) + +#define DECORR_FILTER_ORDER_PS (12) +#define NUM_DECORR_CONFIGS \ + (3) /* different configs defined by bsDecorrConfig bitstream field */ + +/* REV_bandOffset_... tables map (hybrid) bands to the corresponding reverb + bands. Within each reverb band the same processing is applied. Instead of QMF + split frequencies the corresponding hybrid band offsets are stored directly + */ +static const UCHAR REV_bandOffset_MPS_HQ[NUM_DECORR_CONFIGS][(4)] = { + {8, 21, 30, 71}, {8, 56, 71, 71}, {0, 21, 71, 71}}; +/* REV_bandOffset_USAC[] are equivalent to REV_bandOffset_MPS_HQ */ +static const UCHAR REV_bandOffset_PS_HQ[(4)] = {30, 42, 71, 71}; +static const UCHAR REV_bandOffset_PS_LP[(4)] = {14, 42, 71, 71}; +static const UCHAR REV_bandOffset_LD[NUM_DECORR_CONFIGS][(4)] = { + {0, 14, 23, 64}, {0, 49, 64, 64}, {0, 14, 64, 64}}; + +/* REV_delay_... tables define the number of delay elements within each reverb + * band */ +/* REV_filterOrder_... tables define the filter order within each reverb band */ +static const UCHAR REV_delay_MPS[(4)] = {8, 7, 2, 1}; +static const SCHAR REV_filterOrder_MPS[(4)] = { + DECORR_FILTER_ORDER_BAND_0_MPS, DECORR_FILTER_ORDER_BAND_1_MPS, + DECORR_FILTER_ORDER_BAND_2_MPS, DECORR_FILTER_ORDER_BAND_3_MPS}; +static const UCHAR REV_delay_PS_HQ[(4)] = {2, 14, 1, 0}; +static const UCHAR REV_delay_PS_LP[(4)] = {8, 14, 1, 0}; +static const SCHAR REV_filterOrder_PS[(4)] = {DECORR_FILTER_ORDER_PS, -1, -1, + -1}; +static const UCHAR REV_delay_USAC[(4)] = {11, 10, 5, 2}; +static const SCHAR REV_filterOrder_USAC[(4)] = { + DECORR_FILTER_ORDER_BAND_0_USAC, DECORR_FILTER_ORDER_BAND_1_USAC, + DECORR_FILTER_ORDER_BAND_2_USAC, DECORR_FILTER_ORDER_BAND_3_USAC}; + +/* REV_filtType_... tables define the type of processing (filtering with + different properties or pure delay) done in each reverb band. This is mapped + to specialized routines. */ +static const REVBAND_FILT_TYPE REV_filtType_MPS[(4)] = { + COMMON_REAL, COMMON_REAL, COMMON_REAL, COMMON_REAL}; + +static const REVBAND_FILT_TYPE REV_filtType_PS[(4)] = {INDEP_CPLX_PS, DELAY, + DELAY, NOT_EXIST}; + +/* initialization values of ring buffer offsets for the 3 concatenated allpass + * filters (PS type decorrelator). */ +static const UCHAR stateBufferOffsetInit[(3)] = {0, 6, 14}; + +static const REVBAND_FILT_TYPE REV_filtType_LD[(4)] = { + NOT_EXIST, COMMON_REAL, COMMON_REAL, COMMON_REAL}; + +/*** mapping of hybrid bands to processing (/parameter?) bands ***/ +/* table for PS decorr running in legacy PS decoder. */ +static const UCHAR kernels_20_to_71_PS[(71) + 1] = { + 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, + 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19}; + +/*** mapping of processing (/parameter?) bands to hybrid bands ***/ +/* table for PS decorr running in legacy PS decoder. */ +static const UCHAR kernels_20_to_71_offset_PS[(20) + 1] = { + 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71}; + +static const UCHAR kernels_28_to_71[(71) + 1] = { + 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, + 23, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, + 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27}; + +static const UCHAR kernels_28_to_71_offset[(28) + 1] = { + 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 21, 23, 25, 27, 30, 33, 37, 42, 48, 55, 71}; + +/* LD-MPS defined in SAOC standart (mapping qmf -> param bands)*/ +static const UCHAR kernels_23_to_64[(64) + 1] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, 14, + 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, + 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, +}; + +static const UCHAR kernels_23_to_64_offset[(23) + 1] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 14, 16, 18, 20, 23, 26, 30, 35, 41, 48, 64}; + +static inline int SpatialDecGetProcessingBand(int hybridBand, + const UCHAR *tab) { + return tab[hybridBand]; +} + +/* helper inline function */ +static inline int SpatialDecGetQmfBand(int paramBand, const UCHAR *tab) { + return (int)tab[paramBand]; +} + +#define DUCKER_MAX_NRG_SCALE (24) +#define DUCKER_HEADROOM_BITS (2) + +#define FILTER_SF (2) + +#ifdef ARCH_PREFER_MULT_32x32 +#define FIXP_DUCK_GAIN FIXP_DBL +#define FX_DBL2FX_DUCK_GAIN +#define FL2FXCONST_DUCK FL2FXCONST_DBL +#else +#define FIXP_DUCK_GAIN FIXP_SGL +#define FX_DBL2FX_DUCK_GAIN FX_DBL2FX_SGL +#define FL2FXCONST_DUCK FL2FXCONST_SGL +#endif +#define PS_DUCK_PEAK_DECAY_FACTOR (0.765928338364649f) +#define PS_DUCK_FILTER_COEFF (0.25f) +#define DUCK_ALPHA_FDK FL2FXCONST_DUCK(DUCK_ALPHA) +#define DUCK_ONE_MINUS_ALPHA_X4_FDK FL2FXCONST_DUCK(4.0f * (1.0f - DUCK_ALPHA)) +#define DUCK_GAMMA_FDK FL2FXCONST_DUCK(DUCK_GAMMA / 2) +#define PS_DUCK_PEAK_DECAY_FACTOR_FDK FL2FXCONST_DUCK(PS_DUCK_PEAK_DECAY_FACTOR) +#define PS_DUCK_FILTER_COEFF_FDK FL2FXCONST_DUCK(PS_DUCK_FILTER_COEFF) +RAM_ALIGN +const FIXP_STP DecorrPsCoeffsCplx[][4] = { + {STCP(0x5d6940eb, 0x5783153e), STCP(0xadcd41a8, 0x0e0373ed), + STCP(0xbad41f3e, 0x14fba045), STCP(0xc1eb6694, 0x0883227d)}, + {STCP(0x5d6940eb, 0xa87ceac2), STCP(0xadcd41a8, 0xf1fc8c13), + STCP(0xbad41f3e, 0xeb045fbb), STCP(0xc1eb6694, 0xf77cdd83)}, + {STCP(0xaec24162, 0x62e9d75b), STCP(0xb7169316, 0x28751048), + STCP(0xd224c0cc, 0x37e05050), STCP(0xc680864f, 0x18e88cba)}, + {STCP(0xaec24162, 0x9d1628a5), STCP(0xb7169316, 0xd78aefb8), + STCP(0xd224c0cc, 0xc81fafb0), STCP(0xc680864f, 0xe7177346)}, + {STCP(0x98012341, 0x4aa00ed1), STCP(0xc89ca1b2, 0xc1ab6bff), + STCP(0xf8ea394e, 0xb8106bf4), STCP(0xcf542d73, 0xd888b99b)}, + {STCP(0x43b137b3, 0x6ca2ca40), STCP(0xe0649cc4, 0xb2d69cca), + STCP(0x22130c21, 0xc0405382), STCP(0xdbbf8fba, 0xcce3c7cc)}, + {STCP(0x28fc4d71, 0x86bd3b87), STCP(0x09ccfeb9, 0xad319baf), + STCP(0x46e51f02, 0xf1e5ea55), STCP(0xf30d5e34, 0xc2b0e335)}, + {STCP(0xc798f756, 0x72e73c7d), STCP(0x3b6c3c1e, 0xc580dc72), + STCP(0x2828a6ba, 0x3c1a14fb), STCP(0x14b733bb, 0xc4dcaae1)}, + {STCP(0x46dcadd3, 0x956795c7), STCP(0x52f32fae, 0xf78048cd), + STCP(0xd7d75946, 0x3c1a14fb), STCP(0x306017cb, 0xd82c0a75)}, + {STCP(0xabe197de, 0x607a675e), STCP(0x460cef6e, 0x2d3b264e), + STCP(0xb91ae0fe, 0xf1e5ea55), STCP(0x3e03e5e0, 0xf706590e)}, + {STCP(0xb1b4f509, 0x9abcaf5f), STCP(0xfeb0b4be, 0x535fb8ba), + STCP(0x1ba96f8e, 0xbd37e6d8), STCP(0x30f6dbbb, 0x271a0743)}, + {STCP(0xce75b52a, 0x89f9be61), STCP(0xb26e4dda, 0x101054c5), + STCP(0x1a475d2e, 0x3f714b19), STCP(0xf491f154, 0x3a6baf46)}, + {STCP(0xee8fdfcb, 0x813181fa), STCP(0xe11e1a00, 0xbb9a6039), + STCP(0xc3e582f5, 0xe71ab533), STCP(0xc9eb35e2, 0x0ffd212a)}, + {STCP(0x0fd7d92f, 0x80fbf975), STCP(0x38adccbc, 0xd571bbf4), + STCP(0x38c3aefc, 0xe87cc794), STCP(0xdafe8c3d, 0xd9b16100)}, + {STCP(0x300d9e10, 0x895cc359), STCP(0x32b9843e, 0x2b52adcc), + STCP(0xe9ded9f4, 0x356ce0ed), STCP(0x0fdd5ca3, 0xd072932e)}, + {STCP(0x4d03b4f8, 0x99c2dec3), STCP(0xe2bc8d94, 0x3744e195), + STCP(0xeb40ec55, 0xcde9ed22), STCP(0x2e67e231, 0xf893470b)}, + {STCP(0x64c4deb3, 0xb112790f), STCP(0xc7b32682, 0xf099172d), + STCP(0x2ebf44cf, 0x135d014a), STCP(0x1a2bacd5, 0x23334254)}, + {STCP(0x75b5f9aa, 0xcdb81e14), STCP(0x028d9bb1, 0xc9dc45b9), + STCP(0xd497893f, 0x11faeee9), STCP(0xee40ff71, 0x24a91b85)}, + {STCP(0x7eb1cd81, 0xedc3feec), STCP(0x31491897, 0xf765f6d8), + STCP(0x1098dc89, 0xd7ee574e), STCP(0xda6b816d, 0x011f35cf)}, + {STCP(0x7f1cde01, 0x0f0b7727), STCP(0x118ce49d, 0x2a5ecda4), + STCP(0x0f36ca28, 0x24badaa3), STCP(0xef2908a4, 0xe1ee3743)}, + {STCP(0x76efee25, 0x2f4e8c3a), STCP(0xdde3be2a, 0x17f92215), + STCP(0xde9bf36c, 0xf22b4839), STCP(0x1128fc0c, 0xe5c95f5a)}, + {STCP(0x66b87d65, 0x4c5ede42), STCP(0xe43f351a, 0xe6bf22dc), + STCP(0x1e0d3e85, 0xf38d5a9a), STCP(0x1c0f44a3, 0x02c92fe3)}, + {STCP(0x4f8f36b7, 0x6445680f), STCP(0x10867ea2, 0xe3072740), + STCP(0xf4ef6cfa, 0x1ab67076), STCP(0x09562a8a, 0x1742bb8b)}, + {STCP(0x3304f6ec, 0x7564812a), STCP(0x1be4f1a8, 0x0894d75a), + STCP(0xf6517f5b, 0xe8a05d98), STCP(0xf1bb0053, 0x10a78853)}, + {STCP(0x1307b2c5, 0x7e93d532), STCP(0xfe098e27, 0x18f02a58), + STCP(0x1408d459, 0x084c6e44), STCP(0xedafe5bd, 0xfbc15b2e)}, + {STCP(0xf1c111cd, 0x7f346c97), STCP(0xeb5ca6a0, 0x02efee93), + STCP(0xef4df9b6, 0x06ea5be4), STCP(0xfc149289, 0xf0d53ce4)}, + {STCP(0xd1710001, 0x773b6beb), STCP(0xfa1aeb8c, 0xf06655ff), + STCP(0x05884983, 0xf2a4c7c5), STCP(0x094f13df, 0xf79c01bf)}, + {STCP(0xb446be0b, 0x6732cfca), STCP(0x0a743752, 0xf9220dfa), + STCP(0x04263722, 0x0a046a2c), STCP(0x08ced80b, 0x0347e9c2)}, + {STCP(0x9c3b1202, 0x503018a5), STCP(0x05fcf01a, 0x05cd8529), + STCP(0xf95263e2, 0xfd3bdb3f), STCP(0x00c68cf9, 0x0637cb7f)}, + {STCP(0x8aee2710, 0x33c187ec), STCP(0xfdd253f8, 0x038e09b9), + STCP(0x0356ce0f, 0xfe9ded9f), STCP(0xfd6c3054, 0x01c8060a)}}; + +const FIXP_DECORR DecorrNumeratorReal0_USAC + [MAX_DECORR_SEED_USAC][DECORR_FILTER_ORDER_BAND_0_USAC + 1] = { + {DECORR(0x05bf4880), DECORR(0x08321c00), DECORR(0xe9315ee0), + DECORR(0x07d9dd20), DECORR(0x02224994), DECORR(0x0009d200), + DECORR(0xf8a29358), DECORR(0xf4e310d0), DECORR(0xef901fc0), + DECORR(0xebda0460), DECORR(0x40000000)}}; + +const FIXP_DECORR DecorrNumeratorReal1_USAC + [MAX_DECORR_SEED_USAC][DECORR_FILTER_ORDER_BAND_1_USAC + 1] = { + {DECORR(0xf82f8378), DECORR(0xfef588c2), DECORR(0x02eddbd8), + DECORR(0x041c2450), DECORR(0xf7edcd60), DECORR(0x07e29310), + DECORR(0xfa4ece48), DECORR(0xed9f8a20), DECORR(0x40000000)}}; + +/* identical to MPS coeffs for reverb band 3: DecorrNumeratorReal3[0] */ +const FIXP_DECORR + DecorrNumeratorReal2_USAC[MAX_DECORR_SEED_USAC] + [DECORR_FILTER_ORDER_BAND_2_USAC + 1] = { + {DECORR(0x0248e8a8), DECORR(0xfde95838), + DECORR(0x084823c0), DECORR(0x40000000)}}; + +const FIXP_DECORR + DecorrNumeratorReal3_USAC[MAX_DECORR_SEED_USAC] + [DECORR_FILTER_ORDER_BAND_3_USAC + 1] = { + {DECORR(0xff2b020c), DECORR(0x02393830), + DECORR(0x40000000)}}; + +/* const FIXP_DECORR DecorrNumeratorReal0_LD[MAX_DECORR_SEED_LD][] does not + * exist */ + +RAM_ALIGN +const FIXP_DECORR DecorrNumeratorReal1_LD[MAX_DECORR_SEED_LD] + [DECORR_FILTER_ORDER_BAND_1_LD + 1] = { + { + DECORR(0xf310cb29), + DECORR(0x1932d745), + DECORR(0x0cc2d917), + DECORR(0xddde064e), + DECORR(0xf234a626), + DECORR(0x198551a6), + DECORR(0x17141b6a), + DECORR(0xf298803d), + DECORR(0xef98be92), + DECORR(0x09ea1706), + DECORR(0x28fbdff4), + DECORR(0x1a869eb9), + DECORR(0xdeefe147), + DECORR(0xcde2adda), + DECORR(0x13ddc619), + DECORR(0x40000000), + }, + { + DECORR(0x041d7dbf), + DECORR(0x01b7309c), + DECORR(0xfb599834), + DECORR(0x092fc5ed), + DECORR(0xf2fd7c25), + DECORR(0xdd51e2eb), + DECORR(0xf62fe72b), + DECORR(0x0b15d588), + DECORR(0xf1f091a7), + DECORR(0xed1bbbfe), + DECORR(0x03526899), + DECORR(0x180cb256), + DECORR(0xecf1433d), + DECORR(0xf626ab95), + DECORR(0x197dd27e), + DECORR(0x40000000), + }, + { + DECORR(0x157a786c), + DECORR(0x0028c98c), + DECORR(0xf5eff57b), + DECORR(0x11f7d04f), + DECORR(0xf390d28d), + DECORR(0x18947081), + DECORR(0xe5dc2319), + DECORR(0xf4cc0235), + DECORR(0x2394d47f), + DECORR(0xe069230e), + DECORR(0x03a1a773), + DECORR(0xfbc9b092), + DECORR(0x15a0173b), + DECORR(0x0e9ecdf0), + DECORR(0xd309b2c7), + DECORR(0x40000000), + }, + { + DECORR(0xe0ce703b), + DECORR(0xe508b672), + DECORR(0xef362398), + DECORR(0xffe788ef), + DECORR(0x2fda3749), + DECORR(0x4671c0c6), + DECORR(0x3c003494), + DECORR(0x2387707c), + DECORR(0xd2107d2e), + DECORR(0xb3e47e08), + DECORR(0xacd0abca), + DECORR(0xc70791df), + DECORR(0x0b586e85), + DECORR(0x2f11cda7), + DECORR(0x3a4a210b), + DECORR(0x40000000), + }, +}; + +RAM_ALIGN +const FIXP_DECORR DecorrNumeratorReal2_LD[MAX_DECORR_SEED_LD] + [DECORR_FILTER_ORDER_BAND_2_LD + 1 + + DECORR_ZERO_PADDING] = { + { + DECORR(0xffb4a234), + DECORR(0x01ac71a2), + DECORR(0xf2bca010), + DECORR(0xfe3d7593), + DECORR(0x093e9976), + DECORR(0xf2c5f3f5), + DECORR(0x40000000), + }, + { + DECORR(0xe303afb8), + DECORR(0xcd70c2bb), + DECORR(0xf1e2ad7e), + DECORR(0x0c8ffbe2), + DECORR(0x21f80abf), + DECORR(0x3d08410c), + DECORR(0x40000000), + }, + { + DECORR(0xe26809d5), + DECORR(0x0efbcfa4), + DECORR(0x210c1a97), + DECORR(0xfe60af4e), + DECORR(0xeda01a51), + DECORR(0x00faf468), + DECORR(0x40000000), + }, + { + DECORR(0x1edc5d64), + DECORR(0xe5b2e35c), + DECORR(0xe94b1c45), + DECORR(0x30a6f1e1), + DECORR(0xf04e52de), + DECORR(0xe30de45a), + DECORR(0x40000000), + }, +}; + +RAM_ALIGN +const FIXP_DECORR DecorrNumeratorReal3_LD[MAX_DECORR_SEED_LD] + [DECORR_FILTER_ORDER_BAND_3_LD + 1] = { + { + DECORR(0x0248e8a7), + DECORR(0xfde9583b), + DECORR(0x084823bb), + DECORR(0x40000000), + }, + { + DECORR(0x1db22d0e), + DECORR(0xfc773992), + DECORR(0x0e819a74), + DECORR(0x40000000), + }, + { + DECORR(0x0fcb923a), + DECORR(0x0154b7ff), + DECORR(0xe70cb647), + DECORR(0x40000000), + }, + { + DECORR(0xe39f559b), + DECORR(0xe06dd6ca), + DECORR(0x19f71f71), + DECORR(0x40000000), + }, +}; + +FIXP_DBL *getAddrDirectSignalMaxVal(HANDLE_DECORR_DEC self) { + return &(self->ducker.maxValDirectData); +} + +static INT DecorrFilterInit(DECORR_FILTER_INSTANCE *const self, + FIXP_MPS *pStateBufferCplx, + FIXP_DBL *pDelayBufferCplx, INT *offsetStateBuffer, + INT *offsetDelayBuffer, INT const decorr_seed, + INT const reverb_band, INT const useFractDelay, + INT const noSampleDelay, INT const filterOrder, + FDK_DECORR_TYPE const decorrType) { + INT errorCode = 0; + switch (decorrType) { + case DECORR_USAC: + if (useFractDelay) { + return 1; + } else { + FDK_ASSERT(decorr_seed == 0); + + switch (reverb_band) { + case 0: + self->numeratorReal = DecorrNumeratorReal0_USAC[decorr_seed]; + break; + case 1: + self->numeratorReal = DecorrNumeratorReal1_USAC[decorr_seed]; + break; + case 2: + self->numeratorReal = DecorrNumeratorReal2_USAC[decorr_seed]; + break; + case 3: + self->numeratorReal = DecorrNumeratorReal3_USAC[decorr_seed]; + break; + } + } + break; + case DECORR_LD: + FDK_ASSERT(decorr_seed < MAX_DECORR_SEED_LD); + switch (reverb_band) { + case 0: + self->numeratorReal = NULL; + break; + case 1: + self->numeratorReal = DecorrNumeratorReal1_LD[decorr_seed]; + break; + case 2: + self->numeratorReal = DecorrNumeratorReal2_LD[decorr_seed]; + break; + case 3: + self->numeratorReal = DecorrNumeratorReal3_LD[decorr_seed]; + break; + } + break; + default: + return 1; + } + + self->stateCplx = pStateBufferCplx + (*offsetStateBuffer); + *offsetStateBuffer += 2 * filterOrder; + self->DelayBufferCplx = pDelayBufferCplx + (*offsetDelayBuffer); + *offsetDelayBuffer += 2 * noSampleDelay; + + return errorCode; +} + +/******************************************************************************* +*******************************************************************************/ +static INT DecorrFilterInitPS(DECORR_FILTER_INSTANCE *const self, + FIXP_MPS *pStateBufferCplx, + FIXP_DBL *pDelayBufferCplx, + INT *offsetStateBuffer, INT *offsetDelayBuffer, + INT const hybridBand, INT const reverbBand, + INT const noSampleDelay) { + INT errorCode = 0; + + if (reverbBand == 0) { + self->coeffsPacked = DecorrPsCoeffsCplx[hybridBand]; + + self->stateCplx = pStateBufferCplx + (*offsetStateBuffer); + *offsetStateBuffer += 2 * DECORR_FILTER_ORDER_PS; + } + + self->DelayBufferCplx = pDelayBufferCplx + (*offsetDelayBuffer); + *offsetDelayBuffer += 2 * noSampleDelay; + + return errorCode; +} + +LNK_SECTION_CODE_L1 +static INT DecorrFilterApplyPASS(DECORR_FILTER_INSTANCE const filter[], + FIXP_DBL *dataRealIn, FIXP_DBL *dataImagIn, + FIXP_DBL *dataRealOut, FIXP_DBL *dataImagOut, + INT start, INT stop, + INT reverbBandNoSampleDelay, + INT reverbBandDelayBufferIndex) { + INT i; + INT offset = 2 * reverbBandNoSampleDelay; + FIXP_MPS *pDelayBuffer = + &filter[start].DelayBufferCplx[reverbBandDelayBufferIndex]; + + /* Memory for the delayline has been allocated in a consecutive order, so we + can address from filter to filter with a constant length. + Be aware that real and imaginary part of the delayline are stored in + interleaved order. + */ + if (dataImagIn == NULL) { + for (i = start; i < stop; i++) { + FIXP_DBL tmp; + + tmp = *pDelayBuffer; + *pDelayBuffer = dataRealIn[i]; + dataRealOut[i] = tmp; + pDelayBuffer += offset; + } + } else { + if ((i = stop - start) != 0) { + dataRealIn += start; + dataImagIn += start; + dataRealOut += start; + dataImagOut += start; + do { + FIXP_DBL delay_re, delay_im, real, imag; + + real = *dataRealIn++; + imag = *dataImagIn++; + delay_re = pDelayBuffer[0]; + delay_im = pDelayBuffer[1]; + pDelayBuffer[0] = real; + pDelayBuffer[1] = imag; + *dataRealOut++ = delay_re; + *dataImagOut++ = delay_im; + pDelayBuffer += offset; + } while (--i != 0); + } + } + + return (INT)0; +} + +#ifndef FUNCTION_DecorrFilterApplyREAL +LNK_SECTION_CODE_L1 +static INT DecorrFilterApplyREAL(DECORR_FILTER_INSTANCE const filter[], + FIXP_DBL *dataRealIn, FIXP_DBL *dataImagIn, + FIXP_DBL *dataRealOut, FIXP_DBL *dataImagOut, + INT start, INT stop, INT reverbFilterOrder, + INT reverbBandNoSampleDelay, + INT reverbBandDelayBufferIndex) { + INT i, j; + FIXP_DBL xReal, xImag, yReal, yImag; + + const FIXP_DECORR *pFilter = filter[start].numeratorReal; + + INT offsetDelayBuffer = (2 * reverbBandNoSampleDelay) - 1; + FIXP_MPS *pDelayBuffer = + &filter[start].DelayBufferCplx[reverbBandDelayBufferIndex]; + + INT offsetStates = 2 * reverbFilterOrder; + FIXP_DBL *pStates = filter[start].stateCplx; + + /* Memory for the delayline has been allocated in a consecutive order, so we + can address from filter to filter with a constant length. The same is valid + for the states. + Be aware that real and imaginary part of the delayline and the states are + stored in interleaved order. + All filter in a reverb band have the same filter coefficients. + Exploit symmetry: numeratorReal[i] = + denominatorReal[reverbFilterLength-1-i] Do not accumulate the highest + states which are always zero. + */ + if (reverbFilterOrder == 2) { + FIXP_DECORR nFilt0L, nFilt0H; + + nFilt0L = pFilter[0]; + nFilt0H = pFilter[1]; + + for (i = start; i < stop; i++) { + xReal = *pDelayBuffer; + *pDelayBuffer = dataRealIn[i]; + pDelayBuffer++; + + xImag = *pDelayBuffer; + *pDelayBuffer = dataImagIn[i]; + pDelayBuffer += offsetDelayBuffer; + + yReal = (pStates[0] + fMultDiv2(xReal, nFilt0L)) << FILTER_SF; + yImag = (pStates[1] + fMultDiv2(xImag, nFilt0L)) << FILTER_SF; + + dataRealOut[i] = yReal; + dataImagOut[i] = yImag; + + pStates[0] = + pStates[2] + fMultDiv2(xReal, nFilt0H) - fMultDiv2(yReal, nFilt0H); + pStates[1] = + pStates[3] + fMultDiv2(xImag, nFilt0H) - fMultDiv2(yImag, nFilt0H); + pStates[2] = (xReal >> FILTER_SF) - fMultDiv2(yReal, nFilt0L); + pStates[3] = (xImag >> FILTER_SF) - fMultDiv2(yImag, nFilt0L); + pStates += offsetStates; + } + } else if (reverbFilterOrder == 3) { + FIXP_DECORR nFilt0L, nFilt0H, nFilt1L; + + nFilt0L = pFilter[0]; + nFilt0H = pFilter[1]; + nFilt1L = pFilter[2]; + + for (i = start; i < stop; i++) { + xReal = *pDelayBuffer; + *pDelayBuffer = dataRealIn[i]; + pDelayBuffer++; + + xImag = *pDelayBuffer; + *pDelayBuffer = dataImagIn[i]; + pDelayBuffer += offsetDelayBuffer; + + yReal = (pStates[0] + fMultDiv2(xReal, nFilt0L)) << FILTER_SF; + yImag = (pStates[1] + fMultDiv2(xImag, nFilt0L)) << FILTER_SF; + + dataRealOut[i] = yReal; + dataImagOut[i] = yImag; + + pStates[0] = + pStates[2] + fMultDiv2(xReal, nFilt0H) - fMultDiv2(yReal, nFilt1L); + pStates[1] = + pStates[3] + fMultDiv2(xImag, nFilt0H) - fMultDiv2(yImag, nFilt1L); + pStates[2] = + pStates[4] + fMultDiv2(xReal, nFilt1L) - fMultDiv2(yReal, nFilt0H); + pStates[3] = + pStates[5] + fMultDiv2(xImag, nFilt1L) - fMultDiv2(yImag, nFilt0H); + pStates[4] = (xReal >> FILTER_SF) - fMultDiv2(yReal, nFilt0L); + pStates[5] = (xImag >> FILTER_SF) - fMultDiv2(yImag, nFilt0L); + pStates += offsetStates; + } + } else if (reverbFilterOrder == 6) { + FIXP_DECORR nFilt0L, nFilt0H, nFilt1L, nFilt1H, nFilt2L, nFilt2H; + + nFilt0L = pFilter[0]; + nFilt0H = pFilter[1]; + nFilt1L = pFilter[2]; + nFilt1H = pFilter[3]; + nFilt2L = pFilter[4]; + nFilt2H = pFilter[5]; + + for (i = start; i < stop; i++) { + xReal = *pDelayBuffer; + *pDelayBuffer = dataRealIn[i]; + pDelayBuffer++; + + xImag = *pDelayBuffer; + *pDelayBuffer = dataImagIn[i]; + pDelayBuffer += offsetDelayBuffer; + + yReal = (pStates[0] + fMultDiv2(xReal, nFilt0L)) << FILTER_SF; + yImag = (pStates[1] + fMultDiv2(xImag, nFilt0L)) << FILTER_SF; + dataRealOut[i] = yReal; + dataImagOut[i] = yImag; + + pStates[0] = + pStates[2] + fMultDiv2(xReal, nFilt0H) - fMultDiv2(yReal, nFilt2H); + pStates[1] = + pStates[3] + fMultDiv2(xImag, nFilt0H) - fMultDiv2(yImag, nFilt2H); + pStates[2] = + pStates[4] + fMultDiv2(xReal, nFilt1L) - fMultDiv2(yReal, nFilt2L); + pStates[3] = + pStates[5] + fMultDiv2(xImag, nFilt1L) - fMultDiv2(yImag, nFilt2L); + pStates[4] = + pStates[6] + fMultDiv2(xReal, nFilt1H) - fMultDiv2(yReal, nFilt1H); + pStates[5] = + pStates[7] + fMultDiv2(xImag, nFilt1H) - fMultDiv2(yImag, nFilt1H); + pStates[6] = + pStates[8] + fMultDiv2(xReal, nFilt2L) - fMultDiv2(yReal, nFilt1L); + pStates[7] = + pStates[9] + fMultDiv2(xImag, nFilt2L) - fMultDiv2(yImag, nFilt1L); + pStates[8] = + pStates[10] + fMultDiv2(xReal, nFilt2H) - fMultDiv2(yReal, nFilt0H); + pStates[9] = + pStates[11] + fMultDiv2(xImag, nFilt2H) - fMultDiv2(yImag, nFilt0H); + pStates[10] = (xReal >> FILTER_SF) - fMultDiv2(yReal, nFilt0L); + pStates[11] = (xImag >> FILTER_SF) - fMultDiv2(yImag, nFilt0L); + pStates += offsetStates; + } + } else { + FIXP_DECORR nFilt0L, nFilt0H; + for (i = start; i < stop; i++) { + xReal = *pDelayBuffer; + *pDelayBuffer = dataRealIn[i]; + pDelayBuffer++; + + xImag = *pDelayBuffer; + *pDelayBuffer = dataImagIn[i]; + pDelayBuffer += offsetDelayBuffer; + + nFilt0L = pFilter[0]; + yReal = (pStates[0] + fMultDiv2(xReal, nFilt0L)) << 2; + yImag = (pStates[1] + fMultDiv2(xImag, nFilt0L)) << 2; + dataRealOut[i] = yReal; + dataImagOut[i] = yImag; + + for (j = 1; j < reverbFilterOrder; j++) { + nFilt0L = pFilter[j]; + nFilt0H = pFilter[reverbFilterOrder - j]; + pStates[2 * j - 2] = pStates[2 * j] + fMultDiv2(xReal, nFilt0L) - + fMultDiv2(yReal, nFilt0H); + pStates[2 * j - 1] = pStates[2 * j + 1] + fMultDiv2(xImag, nFilt0L) - + fMultDiv2(yImag, nFilt0H); + } + nFilt0L = pFilter[j]; + nFilt0H = pFilter[reverbFilterOrder - j]; + pStates[2 * j - 2] = + fMultDiv2(xReal, nFilt0L) - fMultDiv2(yReal, nFilt0H); + pStates[2 * j - 1] = + fMultDiv2(xImag, nFilt0L) - fMultDiv2(yImag, nFilt0H); + + pStates += offsetStates; + } + } + + return (INT)0; +} +#endif /* #ifndef FUNCTION_DecorrFilterApplyREAL */ + +#ifndef FUNCTION_DecorrFilterApplyCPLX_PS +LNK_SECTION_CODE_L1 +static INT DecorrFilterApplyCPLX_PS( + DECORR_FILTER_INSTANCE const filter[], FIXP_DBL *dataRealIn, + FIXP_DBL *dataImagIn, FIXP_DBL *dataRealOut, FIXP_DBL *dataImagOut, + INT start, INT stop, INT reverbFilterOrder, INT reverbBandNoSampleDelay, + INT reverbBandDelayBufferIndex, UCHAR *stateBufferOffset) { + /* r = real, j = imaginary */ + FIXP_DBL r_data_a, j_data_a, r_data_b, j_data_b, r_stage_mult, j_stage_mult; + FIXP_STP rj_coeff; + + /* get pointer to current position in input delay buffer of filter with + * starting-index */ + FIXP_DBL *pDelayBuffer = + &filter[start].DelayBufferCplx[reverbBandDelayBufferIndex]; /* increases + by 2 every + other call + of this + function */ + /* determine the increment for this pointer to get to the correct position in + * the delay buffer of the next filter */ + INT offsetDelayBuffer = (2 * reverbBandNoSampleDelay) - 1; + + /* pointer to current position in state buffer */ + FIXP_DBL *pStates = filter[start].stateCplx; + INT pStatesIncrement = 2 * reverbFilterOrder; + + /* stateBufferOffset-pointers */ + FIXP_DBL *pStateBufferOffset0 = pStates + stateBufferOffset[0]; + FIXP_DBL *pStateBufferOffset1 = pStates + stateBufferOffset[1]; + FIXP_DBL *pStateBufferOffset2 = pStates + stateBufferOffset[2]; + + /* traverse all hybrid-bands inbetween start- and stop-index */ + for (int i = start; i < stop; i++) { + /* 1. input delay (real/imaginary values interleaved) */ + + /* load delayed real input value */ + r_data_a = *pDelayBuffer; + /* store incoming real data value to delay buffer and increment pointer */ + *pDelayBuffer++ = dataRealIn[i]; + + /* load delayed imaginary input value */ + j_data_a = *pDelayBuffer; + /* store incoming imaginary data value to delay buffer */ + *pDelayBuffer = dataImagIn[i]; + /* increase delay buffer by offset */ + pDelayBuffer += offsetDelayBuffer; + + /* 2. Phi(k)-stage */ + + /* create pointer to coefficient table (real and imaginary coefficients + * interleaved) */ + const FIXP_STP *pCoeffs = filter[i].coeffsPacked; + + /* the first two entries of the coefficient table are the + * Phi(k)-multiplicants */ + rj_coeff = *pCoeffs++; + /* multiply value from input delay buffer by looked-up values */ + cplxMultDiv2(&r_data_b, &j_data_b, r_data_a, j_data_a, rj_coeff); + + /* 3. process all three filter stages */ + + /* stage 0 */ + + /* get coefficients from lookup table */ + rj_coeff = *pCoeffs++; + + /* multiply output of last stage by coefficient */ + cplxMultDiv2(&r_stage_mult, &j_stage_mult, r_data_b, j_data_b, rj_coeff); + r_stage_mult <<= 1; + j_stage_mult <<= 1; + + /* read and add value from state buffer (this is the input for the next + * stage) */ + r_data_a = r_stage_mult + pStateBufferOffset0[0]; + j_data_a = j_stage_mult + pStateBufferOffset0[1]; + + /* negate r_data_a to perform multiplication with complex conjugate of + * rj_coeff */ + cplxMultDiv2(&r_stage_mult, &j_stage_mult, -r_data_a, j_data_a, rj_coeff); + + /* add stage input to shifted result */ + r_stage_mult = r_data_b + (r_stage_mult << 1); + j_stage_mult = j_data_b - (j_stage_mult << 1); + + /* store result to state buffer */ + pStateBufferOffset0[0] = r_stage_mult; + pStateBufferOffset0[1] = j_stage_mult; + pStateBufferOffset0 += pStatesIncrement; + + /* stage 1 */ + + /* get coefficients from lookup table */ + rj_coeff = *pCoeffs++; + + /* multiply output of last stage by coefficient */ + cplxMultDiv2(&r_stage_mult, &j_stage_mult, r_data_a, j_data_a, rj_coeff); + r_stage_mult <<= 1; + j_stage_mult <<= 1; + + /* read and add value from state buffer (this is the input for the next + * stage) */ + r_data_b = r_stage_mult + pStateBufferOffset1[0]; + j_data_b = j_stage_mult + pStateBufferOffset1[1]; + + /* negate r_data_b to perform multiplication with complex conjugate of + * rj_coeff */ + cplxMultDiv2(&r_stage_mult, &j_stage_mult, -r_data_b, j_data_b, rj_coeff); + + /* add stage input to shifted result */ + r_stage_mult = r_data_a + (r_stage_mult << 1); + j_stage_mult = j_data_a - (j_stage_mult << 1); + + /* store result to state buffer */ + pStateBufferOffset1[0] = r_stage_mult; + pStateBufferOffset1[1] = j_stage_mult; + pStateBufferOffset1 += pStatesIncrement; + + /* stage 2 */ + + /* get coefficients from lookup table */ + rj_coeff = *pCoeffs++; + + /* multiply output of last stage by coefficient */ + cplxMultDiv2(&r_stage_mult, &j_stage_mult, r_data_b, j_data_b, rj_coeff); + r_stage_mult <<= 1; + j_stage_mult <<= 1; + + /* read and add value from state buffer (this is the input for the next + * stage) */ + r_data_a = r_stage_mult + pStateBufferOffset2[0]; + j_data_a = j_stage_mult + pStateBufferOffset2[1]; + + /* negate r_data_a to perform multiplication with complex conjugate of + * rj_coeff */ + cplxMultDiv2(&r_stage_mult, &j_stage_mult, -r_data_a, j_data_a, rj_coeff); + + /* add stage input to shifted result */ + r_stage_mult = r_data_b + (r_stage_mult << 1); + j_stage_mult = j_data_b - (j_stage_mult << 1); + + /* store result to state buffer */ + pStateBufferOffset2[0] = r_stage_mult; + pStateBufferOffset2[1] = j_stage_mult; + pStateBufferOffset2 += pStatesIncrement; + + /* write filter output */ + dataRealOut[i] = r_data_a << 1; + dataImagOut[i] = j_data_a << 1; + + } /* end of band/filter loop (outer loop) */ + + /* update stateBufferOffset with respect to ring buffer boundaries */ + if (stateBufferOffset[0] == 4) + stateBufferOffset[0] = 0; + else + stateBufferOffset[0] += 2; + + if (stateBufferOffset[1] == 12) + stateBufferOffset[1] = 6; + else + stateBufferOffset[1] += 2; + + if (stateBufferOffset[2] == 22) + stateBufferOffset[2] = 14; + else + stateBufferOffset[2] += 2; + + return (INT)0; +} + +#endif /* FUNCTION_DecorrFilterApplyCPLX_PS */ + +/******************************************************************************* +*******************************************************************************/ +static INT DuckerInit(DUCKER_INSTANCE *const self, int const hybridBands, + int partiallyComplex, const FDK_DUCKER_TYPE duckerType, + const int nParamBands, int initStatesFlag) { + INT errorCode = 0; + + if (self) { + switch (nParamBands) { + case (20): + FDK_ASSERT(hybridBands == 71); + self->mapHybBands2ProcBands = kernels_20_to_71_PS; + self->mapProcBands2HybBands = kernels_20_to_71_offset_PS; + self->parameterBands = (20); + break; + case (28): + + self->mapHybBands2ProcBands = kernels_28_to_71; + self->mapProcBands2HybBands = kernels_28_to_71_offset; + self->parameterBands = (28); + break; + case (23): + FDK_ASSERT(hybridBands == 64 || hybridBands == 32); + self->mapHybBands2ProcBands = kernels_23_to_64; + self->mapProcBands2HybBands = kernels_23_to_64_offset; + self->parameterBands = (23); + break; + default: + return 1; + } + self->qs_next = &self->mapProcBands2HybBands[1]; + + self->maxValDirectData = FL2FXCONST_DBL(-1.0f); + self->maxValReverbData = FL2FXCONST_DBL(-1.0f); + self->scaleDirectNrg = 2 * DUCKER_MAX_NRG_SCALE; + self->scaleReverbNrg = 2 * DUCKER_MAX_NRG_SCALE; + self->scaleSmoothDirRevNrg = 2 * DUCKER_MAX_NRG_SCALE; + self->headroomSmoothDirRevNrg = 2 * DUCKER_MAX_NRG_SCALE; + self->hybridBands = hybridBands; + self->partiallyComplex = partiallyComplex; + + if (initStatesFlag && (duckerType == DUCKER_PS)) { + int pb; + for (pb = 0; pb < self->parameterBands; pb++) { + self->SmoothDirRevNrg[pb] = (FIXP_MPS)0; + } + } + } else + errorCode = 1; + + return errorCode; +} + + /******************************************************************************* + *******************************************************************************/ + +#ifndef FUNCTION_DuckerCalcEnergy +static INT DuckerCalcEnergy(DUCKER_INSTANCE *const self, + FIXP_DBL const inputReal[(71)], + FIXP_DBL const inputImag[(71)], + FIXP_DBL energy[(28)], FIXP_DBL inputMaxVal, + SCHAR *nrgScale, int mode, /* 1:(ps) 0:(else) */ + int startHybBand) { + INT err = 0; + int qs, maxHybBand; + int maxHybridBand = self->hybridBands - 1; + + maxHybBand = maxHybridBand; + + FDKmemclear(energy, (28) * sizeof(FIXP_DBL)); + + if (mode == 1) { + int pb; + int clz; + FIXP_DBL maxVal = FL2FXCONST_DBL(-1.0f); + + if (maxVal == FL2FXCONST_DBL(-1.0f)) { + clz = fMin(getScalefactor(&inputReal[startHybBand], + fMax(0, maxHybridBand - startHybBand + 1)), + getScalefactor(&inputImag[startHybBand], + fMax(0, maxHybBand - startHybBand + 1))); + } else { + clz = CntLeadingZeros(maxVal) - 1; + } + + clz = fMin(fMax(0, clz - DUCKER_HEADROOM_BITS), DUCKER_MAX_NRG_SCALE); + *nrgScale = (SCHAR)clz << 1; + + /* Initialize pb since it would stay uninitialized for the case startHybBand + * > maxHybBand. */ + pb = SpatialDecGetProcessingBand(maxHybBand, self->mapHybBands2ProcBands); + for (qs = startHybBand; qs <= maxHybBand; qs++) { + pb = SpatialDecGetProcessingBand(qs, self->mapHybBands2ProcBands); + energy[pb] = SATURATE_LEFT_SHIFT( + (energy[pb] >> 1) + (fPow2Div2(inputReal[qs] << clz) >> 1) + + (fPow2Div2(inputImag[qs] << clz) >> 1), + 1, DFRACT_BITS); + } + pb++; + + for (; pb <= SpatialDecGetProcessingBand(maxHybridBand, + self->mapHybBands2ProcBands); + pb++) { + FDK_ASSERT(pb != SpatialDecGetProcessingBand( + qs - 1, self->mapHybBands2ProcBands)); + int qs_next; + FIXP_DBL nrg = 0; + qs_next = (int)self->qs_next[pb]; + for (; qs < qs_next; qs++) { + nrg = fAddSaturate(nrg, fPow2Div2(inputReal[qs] << clz)); + } + energy[pb] = nrg; + } + } else { + int clz; + FIXP_DBL maxVal = FL2FXCONST_DBL(-1.0f); + + maxVal = inputMaxVal; + + if (maxVal == FL2FXCONST_DBL(-1.0f)) { + clz = fMin(getScalefactor(&inputReal[startHybBand], + fMax(0, maxHybridBand - startHybBand + 1)), + getScalefactor(&inputImag[startHybBand], + fMax(0, maxHybBand - startHybBand + 1))); + } else { + clz = CntLeadingZeros(maxVal) - 1; + } + + clz = fMin(fMax(0, clz - DUCKER_HEADROOM_BITS), DUCKER_MAX_NRG_SCALE); + *nrgScale = (SCHAR)clz << 1; + + for (qs = startHybBand; qs <= maxHybBand; qs++) { + int pb = SpatialDecGetProcessingBand(qs, self->mapHybBands2ProcBands); + energy[pb] = SATURATE_LEFT_SHIFT( + (energy[pb] >> 1) + (fPow2Div2(inputReal[qs] << clz) >> 1) + + (fPow2Div2(inputImag[qs] << clz) >> 1), + 1, DFRACT_BITS); + } + + for (; qs <= maxHybridBand; qs++) { + int pb = SpatialDecGetProcessingBand(qs, self->mapHybBands2ProcBands); + energy[pb] = fAddSaturate(energy[pb], fPow2Div2(inputReal[qs] << clz)); + } + } + + { + /* Catch overflows which have been observed in erred bitstreams to avoid + * assertion failures later. */ + int pb; + for (pb = 0; pb < (28); pb++) { + energy[pb] = (FIXP_DBL)((LONG)energy[pb] & (LONG)MAXVAL_DBL); + } + } + return err; +} +#endif /* #ifndef FUNCTION_DuckerCalcEnergy */ + +LNK_SECTION_CODE_L1 +static INT DuckerApply(DUCKER_INSTANCE *const self, + FIXP_DBL const directNrg[(28)], + FIXP_DBL outputReal[(71)], FIXP_DBL outputImag[(71)], + int startHybBand) { + INT err = 0; + int qs = startHybBand; + int qs_next = 0; + int pb = 0; + int startParamBand = 0; + int hybBands; + int hybridBands = self->hybridBands; + + C_ALLOC_SCRATCH_START(reverbNrg, FIXP_DBL, (28)); + + FIXP_DBL *smoothDirRevNrg = &self->SmoothDirRevNrg[0]; + FIXP_DUCK_GAIN duckGain = 0; + + int doScaleNrg = 0; + int scaleDirectNrg = 0; + int scaleReverbNrg = 0; + int scaleSmoothDirRevNrg = 0; + FIXP_DBL maxDirRevNrg = FL2FXCONST_DBL(0.0); + + hybBands = hybridBands; + + startParamBand = + SpatialDecGetProcessingBand(startHybBand, self->mapHybBands2ProcBands); + + DuckerCalcEnergy(self, outputReal, outputImag, reverbNrg, + self->maxValReverbData, &(self->scaleReverbNrg), 0, + startHybBand); + + if ((self->scaleDirectNrg != self->scaleReverbNrg) || + (self->scaleDirectNrg != self->scaleSmoothDirRevNrg) || + (self->headroomSmoothDirRevNrg == 0)) { + int scale; + + scale = fixMin(self->scaleDirectNrg, self->scaleSmoothDirRevNrg + + self->headroomSmoothDirRevNrg - 1); + scale = fixMin(scale, self->scaleReverbNrg); + + scaleDirectNrg = fMax(fMin(self->scaleDirectNrg - scale, (DFRACT_BITS - 1)), + -(DFRACT_BITS - 1)); + scaleReverbNrg = fMax(fMin(self->scaleReverbNrg - scale, (DFRACT_BITS - 1)), + -(DFRACT_BITS - 1)); + scaleSmoothDirRevNrg = + fMax(fMin(self->scaleSmoothDirRevNrg - scale, (DFRACT_BITS - 1)), + -(DFRACT_BITS - 1)); + + self->scaleSmoothDirRevNrg = (SCHAR)scale; + + doScaleNrg = 1; + } + for (pb = startParamBand; pb < self->parameterBands; pb++) { + FIXP_DBL tmp1; + FIXP_DBL tmp2; + INT s; + + /* smoothDirRevNrg[2*pb ] = fMult(smoothDirRevNrg[2*pb ],DUCK_ALPHA_FDK) + + fMultDiv2(directNrg[pb],DUCK_ONE_MINUS_ALPHA_X4_FDK); + smoothDirRevNrg[2*pb+1] = fMult(smoothDirRevNrg[2*pb+1],DUCK_ALPHA_FDK) + + fMultDiv2(reverbNrg[pb],DUCK_ONE_MINUS_ALPHA_X4_FDK); tmp1 = + fMult(smoothDirRevNrg[2*pb],DUCK_GAMMA_FDK); tmp2 = + smoothDirRevNrg[2*pb+1] >> 1; + */ + tmp1 = smoothDirRevNrg[2 * pb + 0]; + tmp2 = smoothDirRevNrg[2 * pb + 1]; + tmp1 = fMult(tmp1, DUCK_ALPHA_FDK); + tmp2 = fMult(tmp2, DUCK_ALPHA_FDK); + + if (doScaleNrg) { + int scaleSmoothDirRevNrg_asExponent = -scaleSmoothDirRevNrg; + + tmp1 = scaleValue(tmp1, scaleSmoothDirRevNrg_asExponent); + tmp2 = scaleValue(tmp2, scaleSmoothDirRevNrg_asExponent); + tmp1 = fMultAddDiv2(tmp1, scaleValue(directNrg[pb], -scaleDirectNrg), + DUCK_ONE_MINUS_ALPHA_X4_FDK); + tmp2 = fMultAddDiv2(tmp2, scaleValue(reverbNrg[pb], -scaleReverbNrg), + DUCK_ONE_MINUS_ALPHA_X4_FDK); + } else { + tmp1 = fMultAddDiv2(tmp1, directNrg[pb], DUCK_ONE_MINUS_ALPHA_X4_FDK); + tmp2 = fMultAddDiv2(tmp2, reverbNrg[pb], DUCK_ONE_MINUS_ALPHA_X4_FDK); + } + + smoothDirRevNrg[2 * pb] = tmp1; + smoothDirRevNrg[2 * pb + 1] = tmp2; + + maxDirRevNrg |= fAbs(tmp1); + maxDirRevNrg |= fAbs(tmp2); + + tmp1 = fMult(tmp1, DUCK_GAMMA_FDK); + tmp2 = tmp2 >> 1; + + qs_next = fMin((int)self->qs_next[pb], self->hybridBands); + + if (tmp2 > tmp1) { /* true for about 20% */ + /* gain smaller than 1.0 */ + tmp1 = sqrtFixp(tmp1); + tmp2 = invSqrtNorm2(tmp2, &s); + duckGain = FX_DBL2FX_DUCK_GAIN(fMultDiv2(tmp1, tmp2) << s); + } else { /* true for about 80 % */ + tmp2 = smoothDirRevNrg[2 * pb] >> 1; + tmp1 = fMult(smoothDirRevNrg[2 * pb + 1], DUCK_GAMMA_FDK); + if (tmp2 > tmp1) { /* true for about 20% */ + if (tmp1 <= (tmp2 >> 2)) { + /* limit gain to 2.0 */ + if (qs < hybBands) { + for (; qs < qs_next; qs++) { + outputReal[qs] = outputReal[qs] << 1; + outputImag[qs] = outputImag[qs] << 1; + } + } else { + for (; qs < qs_next; qs++) { + outputReal[qs] = outputReal[qs] << 1; + } + } + /* skip general gain*output section */ + continue; + } else { + /* gain from 1.0 to 2.0 */ + tmp2 = sqrtFixp(tmp2 >> 2); + tmp1 = invSqrtNorm2(tmp1, &s); + duckGain = FX_DBL2FX_DUCK_GAIN(fMult(tmp1, tmp2) << s); + } + } else { /* true for about 60% */ + /* gain = 1.0; output does not change; update qs index */ + qs = qs_next; + continue; + } + } + + /* general gain*output section */ + if (qs < hybBands) { /* true for about 39% */ + for (; qs < qs_next; qs++) { /* runs about 2 times */ + outputReal[qs] = fMultDiv2(outputReal[qs], duckGain) << 2; + outputImag[qs] = fMultDiv2(outputImag[qs], duckGain) << 2; + } + } else { + for (; qs < qs_next; qs++) { + outputReal[qs] = fMultDiv2(outputReal[qs], duckGain) << 2; + } + } + } /* pb */ + + self->headroomSmoothDirRevNrg = + (SCHAR)fixMax(0, CntLeadingZeros(maxDirRevNrg) - 1); + + C_ALLOC_SCRATCH_END(reverbNrg, FIXP_DBL, (28)); + + return err; +} + +LNK_SECTION_CODE_L1 +static INT DuckerApplyPS(DUCKER_INSTANCE *const self, + FIXP_DBL const directNrg[(28)], + FIXP_DBL outputReal[(71)], FIXP_DBL outputImag[(71)], + int startHybBand) { + int qs = startHybBand; + int pb = 0; + int startParamBand = + SpatialDecGetProcessingBand(startHybBand, self->mapHybBands2ProcBands); + int hybBands; + + int doScaleNrg = 0; + int scaleDirectNrg = 0; + int scaleSmoothDirRevNrg = 0; + FIXP_DBL maxDirRevNrg = FL2FXCONST_DBL(0.0); + + if ((self->scaleDirectNrg != self->scaleSmoothDirRevNrg) || + (self->headroomSmoothDirRevNrg == 0)) { + int scale; + + scale = fixMin(self->scaleDirectNrg, self->scaleSmoothDirRevNrg + + self->headroomSmoothDirRevNrg - 2); + + scaleDirectNrg = fMax(fMin(self->scaleDirectNrg - scale, (DFRACT_BITS - 1)), + -(DFRACT_BITS - 1)); + scaleSmoothDirRevNrg = + fMax(fMin(self->scaleSmoothDirRevNrg - scale, (DFRACT_BITS - 1)), + -(DFRACT_BITS - 1)); + + self->scaleSmoothDirRevNrg = (SCHAR)scale; + + doScaleNrg = 1; + } + + hybBands = self->hybridBands; + + FDK_ASSERT((self->parameterBands == (28)) || (self->parameterBands == (20))); + for (pb = startParamBand; pb < self->parameterBands; pb++) { + FIXP_DBL directNrg2 = directNrg[pb]; + + if (doScaleNrg) { + directNrg2 = scaleValue(directNrg2, -scaleDirectNrg); + self->peakDiff[pb] = + scaleValue(self->peakDiff[pb], -scaleSmoothDirRevNrg); + self->peakDecay[pb] = + scaleValue(self->peakDecay[pb], -scaleSmoothDirRevNrg); + self->SmoothDirRevNrg[pb] = + scaleValue(self->SmoothDirRevNrg[pb], -scaleSmoothDirRevNrg); + } + self->peakDecay[pb] = fixMax( + directNrg2, fMult(self->peakDecay[pb], PS_DUCK_PEAK_DECAY_FACTOR_FDK)); + self->peakDiff[pb] = + self->peakDiff[pb] + + fMult(PS_DUCK_FILTER_COEFF_FDK, + (self->peakDecay[pb] - directNrg2 - self->peakDiff[pb])); + self->SmoothDirRevNrg[pb] = + fixMax(self->SmoothDirRevNrg[pb] + + fMult(PS_DUCK_FILTER_COEFF_FDK, + (directNrg2 - self->SmoothDirRevNrg[pb])), + FL2FXCONST_DBL(0)); + + maxDirRevNrg |= fAbs(self->peakDiff[pb]); + maxDirRevNrg |= fAbs(self->SmoothDirRevNrg[pb]); + + if ((self->peakDiff[pb] == FL2FXCONST_DBL(0)) && + (self->SmoothDirRevNrg[pb] == FL2FXCONST_DBL(0))) { + int qs_next; + + qs = fMax(qs, SpatialDecGetQmfBand(pb, self->mapProcBands2HybBands)); + qs_next = fMin((int)self->qs_next[pb], self->hybridBands); + + FIXP_DBL *pOutputReal = &outputReal[qs]; + FIXP_DBL *pOutputImag = &outputImag[qs]; + + if (qs < hybBands) { + for (; qs < qs_next; qs++) { + *pOutputReal++ = FL2FXCONST_DBL(0); + *pOutputImag++ = FL2FXCONST_DBL(0); + } + } else { + for (; qs < qs_next; qs++) { + *pOutputReal++ = FL2FXCONST_DBL(0); + } + } + } else if (self->peakDiff[pb] != FL2FXCONST_DBL(0)) { + FIXP_DBL multiplication = + fMult(FL2FXCONST_DUCK(0.75f), self->peakDiff[pb]); + if (multiplication > (self->SmoothDirRevNrg[pb] >> 1)) { + FIXP_DBL num, denom, duckGain; + int scale, qs_next; + + /* implement x/y as (sqrt(x)*invSqrt(y))^2 */ + num = sqrtFixp(self->SmoothDirRevNrg[pb] >> 1); + denom = self->peakDiff[pb] + + FL2FXCONST_DBL(ABS_THR / (32768.0f * 32768.0f * 128.0f * 1.5f)); + denom = invSqrtNorm2(denom, &scale); + + /* duck output whether duckGain != 1.f */ + qs = fMax(qs, SpatialDecGetQmfBand(pb, self->mapProcBands2HybBands)); + qs_next = fMin((int)self->qs_next[pb], self->hybridBands); + + duckGain = fMult(num, denom); + duckGain = fPow2Div2(duckGain << scale); + duckGain = fMultDiv2(FL2FXCONST_DUCK(2.f / 3.f), duckGain) << 3; + + FIXP_DBL *pOutputReal = &outputReal[qs]; + FIXP_DBL *pOutputImag = &outputImag[qs]; + + if (qs < hybBands) { + for (; qs < qs_next; qs++) { + *pOutputReal = fMult(*pOutputReal, duckGain); + pOutputReal++; /* don't move in front of "=" above, because then the + fract class treats it differently and provides + wrong argument to fMult() (seen on win32/msvc8) */ + *pOutputImag = fMult(*pOutputImag, duckGain); + pOutputImag++; + } + } else { + for (; qs < qs_next; qs++) { + *pOutputReal = fMult(*pOutputReal, duckGain); + pOutputReal++; + } + } + } + } + } /* pb */ + + self->headroomSmoothDirRevNrg = + (SCHAR)fixMax(0, CntLeadingZeros(maxDirRevNrg) - 1); + + return 0; +} + +INT FDKdecorrelateOpen(HANDLE_DECORR_DEC hDecorrDec, FIXP_DBL *bufferCplx, + const INT bufLen) { + HANDLE_DECORR_DEC self = hDecorrDec; + + if (bufLen < (2 * ((825) + (373)))) return 1; + + /* assign all memory to stateBufferCplx. It is reassigned during + * FDKdecorrelateInit() */ + self->stateBufferCplx = bufferCplx; + self->L_stateBufferCplx = 0; + + self->delayBufferCplx = NULL; + self->L_delayBufferCplx = 0; + + return 0; +} + +static int distributeBuffer(HANDLE_DECORR_DEC self, const int L_stateBuf, + const int L_delayBuf) { + /* factor 2 because of complex values */ + if ((2 * ((825) + (373))) < 2 * (L_stateBuf + L_delayBuf)) { + return 1; + } + + self->L_stateBufferCplx = 2 * L_stateBuf; + self->delayBufferCplx = self->stateBufferCplx + 2 * L_stateBuf; + self->L_delayBufferCplx = 2 * L_delayBuf; + + return 0; +} +INT FDKdecorrelateInit(HANDLE_DECORR_DEC hDecorrDec, const INT nrHybBands, + const FDK_DECORR_TYPE decorrType, + const FDK_DUCKER_TYPE duckerType, const INT decorrConfig, + const INT seed, const INT partiallyComplex, + const INT useFractDelay, const INT isLegacyPS, + const INT initStatesFlag) { + INT errorCode = 0; + int i, rb, i_start; + int nParamBands = 28; + + INT offsetStateBuffer = 0; + INT offsetDelayBuffer = 0; + + const UCHAR *REV_bandOffset; + + const SCHAR *REV_filterOrder; + + hDecorrDec->partiallyComplex = partiallyComplex; + hDecorrDec->numbins = nrHybBands; + + switch (decorrType) { + case DECORR_PS: + /* ignore decorrConfig, seed */ + if (partiallyComplex) { + hDecorrDec->REV_bandOffset = REV_bandOffset_PS_LP; + hDecorrDec->REV_delay = REV_delay_PS_LP; + errorCode = distributeBuffer(hDecorrDec, (168), (533)); + } else { + hDecorrDec->REV_bandOffset = REV_bandOffset_PS_HQ; + hDecorrDec->REV_delay = REV_delay_PS_HQ; + errorCode = distributeBuffer(hDecorrDec, (360), (257)); + } + hDecorrDec->REV_filterOrder = REV_filterOrder_PS; + hDecorrDec->REV_filtType = REV_filtType_PS; + + /* Initialize ring buffer offsets for PS specific filter implementation. + */ + for (i = 0; i < (3); i++) + hDecorrDec->stateBufferOffset[i] = stateBufferOffsetInit[i]; + + break; + case DECORR_USAC: + if (partiallyComplex) return 1; + if (seed != 0) return 1; + hDecorrDec->REV_bandOffset = + REV_bandOffset_MPS_HQ[decorrConfig]; /* reverb band layout is + inherited from MPS standard */ + hDecorrDec->REV_filterOrder = REV_filterOrder_USAC; + hDecorrDec->REV_delay = REV_delay_USAC; + if (useFractDelay) { + return 1; /* not yet supported */ + } else { + hDecorrDec->REV_filtType = REV_filtType_MPS; /* the filter types are + inherited from MPS + standard */ + } + /* bsDecorrConfig == 1 is worst case */ + errorCode = distributeBuffer(hDecorrDec, (509), (643)); + break; + case DECORR_LD: + if (partiallyComplex) return 1; + if (useFractDelay) return 1; + if (decorrConfig > 2) return 1; + if (seed > (MAX_DECORR_SEED_LD - 1)) return 1; + if (!(nrHybBands == 64 || nrHybBands == 32)) + return 1; /* actually just qmf bands and no hybrid bands */ + hDecorrDec->REV_bandOffset = REV_bandOffset_LD[decorrConfig]; + hDecorrDec->REV_filterOrder = REV_filterOrder_MPS; /* the filter orders + are inherited from + MPS standard */ + hDecorrDec->REV_delay = + REV_delay_MPS; /* the delays in each reverb band are inherited from + MPS standard */ + hDecorrDec->REV_filtType = REV_filtType_LD; + errorCode = distributeBuffer(hDecorrDec, (825), (373)); + break; + default: + return 1; + } + + if (errorCode) { + return errorCode; + } + + if (initStatesFlag) { + FDKmemclear( + hDecorrDec->stateBufferCplx, + hDecorrDec->L_stateBufferCplx * sizeof(*hDecorrDec->stateBufferCplx)); + FDKmemclear( + hDecorrDec->delayBufferCplx, + hDecorrDec->L_delayBufferCplx * sizeof(*hDecorrDec->delayBufferCplx)); + FDKmemclear(hDecorrDec->reverbBandDelayBufferIndex, + sizeof(hDecorrDec->reverbBandDelayBufferIndex)); + } + + REV_bandOffset = hDecorrDec->REV_bandOffset; + + REV_filterOrder = hDecorrDec->REV_filterOrder; + + i_start = 0; + for (rb = 0; rb < (4); rb++) { + int i_stop; + + i_stop = REV_bandOffset[rb]; + + if (i_stop <= i_start) { + continue; + } + + for (i = i_start; i < i_stop; i++) { + switch (decorrType) { + case DECORR_PS: + errorCode = DecorrFilterInitPS( + &hDecorrDec->Filter[i], hDecorrDec->stateBufferCplx, + hDecorrDec->delayBufferCplx, &offsetStateBuffer, + &offsetDelayBuffer, i, rb, hDecorrDec->REV_delay[rb]); + break; + default: + errorCode = DecorrFilterInit( + &hDecorrDec->Filter[i], hDecorrDec->stateBufferCplx, + hDecorrDec->delayBufferCplx, &offsetStateBuffer, + &offsetDelayBuffer, seed, rb, useFractDelay, + hDecorrDec->REV_delay[rb], REV_filterOrder[rb], decorrType); + break; + } + } + + i_start = i_stop; + } /* loop over reverbBands */ + + if (!(offsetStateBuffer <= hDecorrDec->L_stateBufferCplx) || + !(offsetDelayBuffer <= hDecorrDec->L_delayBufferCplx)) { + return errorCode = 1; + } + + if (duckerType == DUCKER_AUTOMATIC) { + /* Choose correct ducker type according to standards: */ + switch (decorrType) { + case DECORR_PS: + hDecorrDec->ducker.duckerType = DUCKER_PS; + if (isLegacyPS) { + nParamBands = (20); + } else { + nParamBands = (28); + } + break; + case DECORR_USAC: + hDecorrDec->ducker.duckerType = DUCKER_MPS; + nParamBands = (28); + break; + case DECORR_LD: + hDecorrDec->ducker.duckerType = DUCKER_MPS; + nParamBands = (23); + break; + default: + return 1; + } + } + + errorCode = DuckerInit( + &hDecorrDec->ducker, hDecorrDec->numbins, hDecorrDec->partiallyComplex, + hDecorrDec->ducker.duckerType, nParamBands, initStatesFlag); + + return errorCode; +} + +INT FDKdecorrelateClose(HANDLE_DECORR_DEC hDecorrDec) { + INT err = 0; + + if (hDecorrDec == NULL) { + return 1; + } + + hDecorrDec->stateBufferCplx = NULL; + hDecorrDec->L_stateBufferCplx = 0; + hDecorrDec->delayBufferCplx = NULL; + hDecorrDec->L_delayBufferCplx = 0; + + return err; +} + +LNK_SECTION_CODE_L1 +INT FDKdecorrelateApply(HANDLE_DECORR_DEC hDecorrDec, FIXP_DBL *dataRealIn, + FIXP_DBL *dataImagIn, FIXP_DBL *dataRealOut, + FIXP_DBL *dataImagOut, const INT startHybBand) { + HANDLE_DECORR_DEC self = hDecorrDec; + INT err = 0; + INT rb, stop, start; + + if (self != NULL) { + int nHybBands = 0; + /* copy new samples */ + nHybBands = self->numbins; + + FIXP_DBL directNrg[(28)]; + + DuckerCalcEnergy( + &self->ducker, dataRealIn, dataImagIn, directNrg, + self->ducker.maxValDirectData, &(self->ducker.scaleDirectNrg), + (self->ducker.duckerType == DUCKER_PS) ? 1 : 0, startHybBand); + + /* complex-valued hybrid bands */ + for (stop = 0, rb = 0; rb < (4); rb++) { + start = fMax(stop, startHybBand); + stop = fMin(self->REV_bandOffset[rb], (UCHAR)nHybBands); + + if (start < stop) { + switch (hDecorrDec->REV_filtType[rb]) { + case DELAY: + err = DecorrFilterApplyPASS(&self->Filter[0], dataRealIn, + dataImagIn, dataRealOut, dataImagOut, + start, stop, self->REV_delay[rb], + self->reverbBandDelayBufferIndex[rb]); + break; + case INDEP_CPLX_PS: + err = DecorrFilterApplyCPLX_PS( + &self->Filter[0], dataRealIn, dataImagIn, dataRealOut, + dataImagOut, start, stop, self->REV_filterOrder[rb], + self->REV_delay[rb], self->reverbBandDelayBufferIndex[rb], + self->stateBufferOffset); + break; + case COMMON_REAL: + err = DecorrFilterApplyREAL( + &self->Filter[0], dataRealIn, dataImagIn, dataRealOut, + dataImagOut, start, stop, self->REV_filterOrder[rb], + self->REV_delay[rb], self->reverbBandDelayBufferIndex[rb]); + break; + default: + err = 1; + break; + } + if (err != 0) { + goto bail; + } + } /* if start < stop */ + } /* loop over reverb bands */ + + for (rb = 0; rb < (4); rb++) { + self->reverbBandDelayBufferIndex[rb] += 2; + if (self->reverbBandDelayBufferIndex[rb] >= 2 * self->REV_delay[rb]) + self->reverbBandDelayBufferIndex[rb] = 0; + } + + switch (self->ducker.duckerType) { + case DUCKER_PS: + err = DuckerApplyPS(&self->ducker, directNrg, dataRealOut, dataImagOut, + startHybBand); + if (err != 0) goto bail; + break; + default: + err = DuckerApply(&self->ducker, directNrg, dataRealOut, dataImagOut, + startHybBand); + if (err != 0) goto bail; + break; + } + } + +bail: + return err; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_hybrid.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_hybrid.cpp new file mode 100644 index 0000000000000..d208abd619734 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_hybrid.cpp @@ -0,0 +1,815 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Markus Lohwasser + + Description: FDK Tools Hybrid Filterbank + +*******************************************************************************/ + +#include "FDK_hybrid.h" + +#include "fft.h" + +/*--------------- defines -----------------------------*/ +#define FFT_IDX_R(a) (2 * a) +#define FFT_IDX_I(a) (2 * a + 1) + +#define HYB_COEF8_0 (0.00746082949812f) +#define HYB_COEF8_1 (0.02270420949825f) +#define HYB_COEF8_2 (0.04546865930473f) +#define HYB_COEF8_3 (0.07266113929591f) +#define HYB_COEF8_4 (0.09885108575264f) +#define HYB_COEF8_5 (0.11793710567217f) +#define HYB_COEF8_6 (0.12500000000000f) +#define HYB_COEF8_7 (HYB_COEF8_5) +#define HYB_COEF8_8 (HYB_COEF8_4) +#define HYB_COEF8_9 (HYB_COEF8_3) +#define HYB_COEF8_10 (HYB_COEF8_2) +#define HYB_COEF8_11 (HYB_COEF8_1) +#define HYB_COEF8_12 (HYB_COEF8_0) + +/*--------------- structure definitions ---------------*/ + +#if defined(ARCH_PREFER_MULT_32x16) +#define FIXP_HTB FIXP_SGL /* SGL data type. */ +#define FIXP_HTP FIXP_SPK /* Packed SGL data type. */ +#define HTC(a) (FX_DBL2FXCONST_SGL(a)) /* Cast to SGL */ +#define FL2FXCONST_HTB FL2FXCONST_SGL +#else +#define FIXP_HTB FIXP_DBL /* SGL data type. */ +#define FIXP_HTP FIXP_DPK /* Packed DBL data type. */ +#define HTC(a) ((FIXP_DBL)(LONG)(a)) /* Cast to DBL */ +#define FL2FXCONST_HTB FL2FXCONST_DBL +#endif + +#define HTCP(real, imag) \ + { \ + { HTC(real), HTC(imag) } \ + } /* How to arrange the packed values. */ + +struct FDK_HYBRID_SETUP { + UCHAR nrQmfBands; /*!< Number of QMF bands to be converted to hybrid. */ + UCHAR nHybBands[3]; /*!< Number of Hybrid bands generated by nrQmfBands. */ + UCHAR synHybScale[3]; /*!< Headroom needed in hybrid synthesis filterbank. */ + SCHAR kHybrid[3]; /*!< Filter configuration of each QMF band. */ + UCHAR protoLen; /*!< Prototype filter length. */ + UCHAR filterDelay; /*!< Delay caused by hybrid filter. */ + const INT + *pReadIdxTable; /*!< Helper table to access input data ringbuffer. */ +}; + +/*--------------- constants ---------------------------*/ +static const INT ringbuffIdxTab[2 * 13] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12}; + +static const FDK_HYBRID_SETUP setup_3_16 = { + 3, {8, 4, 4}, {4, 3, 3}, {8, 4, 4}, 13, (13 - 1) / 2, ringbuffIdxTab}; +static const FDK_HYBRID_SETUP setup_3_12 = { + 3, {8, 2, 2}, {4, 2, 2}, {8, 2, 2}, 13, (13 - 1) / 2, ringbuffIdxTab}; +static const FDK_HYBRID_SETUP setup_3_10 = { + 3, {6, 2, 2}, {3, 2, 2}, {-8, -2, 2}, 13, (13 - 1) / 2, ringbuffIdxTab}; + +static const FIXP_HTP HybFilterCoef8[] = { + HTCP(0x10000000, 0x00000000), HTCP(0x0df26407, 0xfa391882), + HTCP(0xff532109, 0x00acdef7), HTCP(0x08f26d36, 0xf70d92ca), + HTCP(0xfee34b5f, 0x02af570f), HTCP(0x038f276e, 0xf7684793), + HTCP(0x00000000, 0x05d1eac2), HTCP(0x00000000, 0x05d1eac2), + HTCP(0x038f276e, 0x0897b86d), HTCP(0xfee34b5f, 0xfd50a8f1), + HTCP(0x08f26d36, 0x08f26d36), HTCP(0xff532109, 0xff532109), + HTCP(0x0df26407, 0x05c6e77e)}; + +static const FIXP_HTB HybFilterCoef2[3] = {FL2FXCONST_HTB(0.01899487526049f), + FL2FXCONST_HTB(-0.07293139167538f), + FL2FXCONST_HTB(0.30596630545168f)}; + +static const FIXP_HTB HybFilterCoef4[13] = {FL2FXCONST_HTB(-0.00305151927305f), + FL2FXCONST_HTB(-0.00794862316203f), + FL2FXCONST_HTB(0.0f), + FL2FXCONST_HTB(0.04318924038756f), + FL2FXCONST_HTB(0.12542448210445f), + FL2FXCONST_HTB(0.21227807049160f), + FL2FXCONST_HTB(0.25f), + FL2FXCONST_HTB(0.21227807049160f), + FL2FXCONST_HTB(0.12542448210445f), + FL2FXCONST_HTB(0.04318924038756f), + FL2FXCONST_HTB(0.0f), + FL2FXCONST_HTB(-0.00794862316203f), + FL2FXCONST_HTB(-0.00305151927305f)}; + +/*--------------- function declarations ---------------*/ +static INT kChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const SCHAR hybridConfig); + +/*--------------- function definitions ----------------*/ + +INT FDKhybridAnalysisOpen(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + FIXP_DBL *const pLFmemory, const UINT LFmemorySize, + FIXP_DBL *const pHFmemory, const UINT HFmemorySize) { + INT err = 0; + + /* Save pointer to extern memory. */ + hAnalysisHybFilter->pLFmemory = pLFmemory; + hAnalysisHybFilter->LFmemorySize = LFmemorySize; + + hAnalysisHybFilter->pHFmemory = pHFmemory; + hAnalysisHybFilter->HFmemorySize = HFmemorySize; + + return err; +} + +INT FDKhybridAnalysisInit(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FDK_HYBRID_MODE mode, const INT qmfBands, + const INT cplxBands, const INT initStatesFlag) { + int k; + INT err = 0; + FIXP_DBL *pMem = NULL; + HANDLE_FDK_HYBRID_SETUP setup = NULL; + + switch (mode) { + case THREE_TO_TEN: + setup = &setup_3_10; + break; + case THREE_TO_TWELVE: + setup = &setup_3_12; + break; + case THREE_TO_SIXTEEN: + setup = &setup_3_16; + break; + default: + err = -1; + goto bail; + } + + /* Initialize handle. */ + hAnalysisHybFilter->pSetup = setup; + if (initStatesFlag) { + hAnalysisHybFilter->bufferLFpos = setup->protoLen - 1; + hAnalysisHybFilter->bufferHFpos = 0; + } + hAnalysisHybFilter->nrBands = qmfBands; + hAnalysisHybFilter->cplxBands = cplxBands; + hAnalysisHybFilter->hfMode = 0; + + /* Check available memory. */ + if (((2 * setup->nrQmfBands * setup->protoLen * sizeof(FIXP_DBL)) > + hAnalysisHybFilter->LFmemorySize)) { + err = -2; + goto bail; + } + if (hAnalysisHybFilter->HFmemorySize != 0) { + if (((setup->filterDelay * + ((qmfBands - setup->nrQmfBands) + (cplxBands - setup->nrQmfBands)) * + sizeof(FIXP_DBL)) > hAnalysisHybFilter->HFmemorySize)) { + err = -3; + goto bail; + } + } + + /* Distribute LF memory. */ + pMem = hAnalysisHybFilter->pLFmemory; + for (k = 0; k < setup->nrQmfBands; k++) { + hAnalysisHybFilter->bufferLFReal[k] = pMem; + pMem += setup->protoLen; + hAnalysisHybFilter->bufferLFImag[k] = pMem; + pMem += setup->protoLen; + } + + /* Distribute HF memory. */ + if (hAnalysisHybFilter->HFmemorySize != 0) { + pMem = hAnalysisHybFilter->pHFmemory; + for (k = 0; k < setup->filterDelay; k++) { + hAnalysisHybFilter->bufferHFReal[k] = pMem; + pMem += (qmfBands - setup->nrQmfBands); + hAnalysisHybFilter->bufferHFImag[k] = pMem; + pMem += (cplxBands - setup->nrQmfBands); + } + } + + if (initStatesFlag) { + /* Clear LF buffer */ + for (k = 0; k < setup->nrQmfBands; k++) { + FDKmemclear(hAnalysisHybFilter->bufferLFReal[k], + setup->protoLen * sizeof(FIXP_DBL)); + FDKmemclear(hAnalysisHybFilter->bufferLFImag[k], + setup->protoLen * sizeof(FIXP_DBL)); + } + + if (hAnalysisHybFilter->HFmemorySize != 0) { + if (qmfBands > setup->nrQmfBands) { + /* Clear HF buffer */ + for (k = 0; k < setup->filterDelay; k++) { + FDKmemclear(hAnalysisHybFilter->bufferHFReal[k], + (qmfBands - setup->nrQmfBands) * sizeof(FIXP_DBL)); + FDKmemclear(hAnalysisHybFilter->bufferHFImag[k], + (cplxBands - setup->nrQmfBands) * sizeof(FIXP_DBL)); + } + } + } + } + +bail: + return err; +} + +INT FDKhybridAnalysisScaleStates(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const INT scalingValue) { + INT err = 0; + + if (hAnalysisHybFilter == NULL) { + err = 1; /* invalid handle */ + } else { + int k; + HANDLE_FDK_HYBRID_SETUP setup = hAnalysisHybFilter->pSetup; + + /* Scale LF buffer */ + for (k = 0; k < setup->nrQmfBands; k++) { + scaleValues(hAnalysisHybFilter->bufferLFReal[k], setup->protoLen, + scalingValue); + scaleValues(hAnalysisHybFilter->bufferLFImag[k], setup->protoLen, + scalingValue); + } + if (hAnalysisHybFilter->nrBands > setup->nrQmfBands) { + /* Scale HF buffer */ + for (k = 0; k < setup->filterDelay; k++) { + scaleValues(hAnalysisHybFilter->bufferHFReal[k], + (hAnalysisHybFilter->nrBands - setup->nrQmfBands), + scalingValue); + scaleValues(hAnalysisHybFilter->bufferHFImag[k], + (hAnalysisHybFilter->cplxBands - setup->nrQmfBands), + scalingValue); + } + } + } + return err; +} + +INT FDKhybridAnalysisApply(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + FIXP_DBL *const pHybridReal, + FIXP_DBL *const pHybridImag) { + int k, hybOffset = 0; + INT err = 0; + const int nrQmfBandsLF = + hAnalysisHybFilter->pSetup + ->nrQmfBands; /* number of QMF bands to be converted to hybrid */ + + const int writIndex = hAnalysisHybFilter->bufferLFpos; + int readIndex = hAnalysisHybFilter->bufferLFpos; + + if (++readIndex >= hAnalysisHybFilter->pSetup->protoLen) readIndex = 0; + const INT *pBufferLFreadIdx = + &hAnalysisHybFilter->pSetup->pReadIdxTable[readIndex]; + + /* + * LF buffer. + */ + for (k = 0; k < nrQmfBandsLF; k++) { + /* New input sample. */ + hAnalysisHybFilter->bufferLFReal[k][writIndex] = pQmfReal[k]; + hAnalysisHybFilter->bufferLFImag[k][writIndex] = pQmfImag[k]; + + /* Perform hybrid filtering. */ + err |= + kChannelFiltering(hAnalysisHybFilter->bufferLFReal[k], + hAnalysisHybFilter->bufferLFImag[k], pBufferLFreadIdx, + pHybridReal + hybOffset, pHybridImag + hybOffset, + hAnalysisHybFilter->pSetup->kHybrid[k]); + + hybOffset += hAnalysisHybFilter->pSetup->nHybBands[k]; + } + + hAnalysisHybFilter->bufferLFpos = + readIndex; /* Index where to write next input sample. */ + + if (hAnalysisHybFilter->nrBands > nrQmfBandsLF) { + /* + * HF buffer. + */ + if (hAnalysisHybFilter->hfMode != 0) { + /* HF delay compensation was applied outside. */ + FDKmemcpy( + pHybridReal + hybOffset, &pQmfReal[nrQmfBandsLF], + (hAnalysisHybFilter->nrBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + FDKmemcpy( + pHybridImag + hybOffset, &pQmfImag[nrQmfBandsLF], + (hAnalysisHybFilter->cplxBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + } else { + FDK_ASSERT(hAnalysisHybFilter->HFmemorySize != 0); + /* HF delay compensation, filterlength/2. */ + FDKmemcpy( + pHybridReal + hybOffset, + hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], + (hAnalysisHybFilter->nrBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + FDKmemcpy( + pHybridImag + hybOffset, + hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], + (hAnalysisHybFilter->cplxBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + + FDKmemcpy( + hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], + &pQmfReal[nrQmfBandsLF], + (hAnalysisHybFilter->nrBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + FDKmemcpy( + hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], + &pQmfImag[nrQmfBandsLF], + (hAnalysisHybFilter->cplxBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + + if (++hAnalysisHybFilter->bufferHFpos >= + hAnalysisHybFilter->pSetup->filterDelay) + hAnalysisHybFilter->bufferHFpos = 0; + } + } /* process HF part*/ + + return err; +} + +INT FDKhybridAnalysisClose(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter) { + INT err = 0; + + if (hAnalysisHybFilter != NULL) { + hAnalysisHybFilter->pLFmemory = NULL; + hAnalysisHybFilter->pHFmemory = NULL; + hAnalysisHybFilter->LFmemorySize = 0; + hAnalysisHybFilter->HFmemorySize = 0; + } + + return err; +} + +INT FDKhybridSynthesisInit(HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FDK_HYBRID_MODE mode, const INT qmfBands, + const INT cplxBands) { + INT err = 0; + HANDLE_FDK_HYBRID_SETUP setup = NULL; + + switch (mode) { + case THREE_TO_TEN: + setup = &setup_3_10; + break; + case THREE_TO_TWELVE: + setup = &setup_3_12; + break; + case THREE_TO_SIXTEEN: + setup = &setup_3_16; + break; + default: + err = -1; + goto bail; + } + + hSynthesisHybFilter->pSetup = setup; + hSynthesisHybFilter->nrBands = qmfBands; + hSynthesisHybFilter->cplxBands = cplxBands; + +bail: + return err; +} + +void FDKhybridSynthesisApply(HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FIXP_DBL *const pHybridReal, + const FIXP_DBL *const pHybridImag, + FIXP_DBL *const pQmfReal, + FIXP_DBL *const pQmfImag) { + int k, n, hybOffset = 0; + const INT nrQmfBandsLF = hSynthesisHybFilter->pSetup->nrQmfBands; + + /* + * LF buffer. + */ + for (k = 0; k < nrQmfBandsLF; k++) { + const int nHybBands = hSynthesisHybFilter->pSetup->nHybBands[k]; + const int scale = hSynthesisHybFilter->pSetup->synHybScale[k]; + + FIXP_DBL accu1 = FL2FXCONST_DBL(0.f); + FIXP_DBL accu2 = FL2FXCONST_DBL(0.f); + + /* Perform hybrid filtering. */ + for (n = 0; n < nHybBands; n++) { + accu1 += pHybridReal[hybOffset + n] >> scale; + accu2 += pHybridImag[hybOffset + n] >> scale; + } + pQmfReal[k] = SATURATE_LEFT_SHIFT(accu1, scale, DFRACT_BITS); + pQmfImag[k] = SATURATE_LEFT_SHIFT(accu2, scale, DFRACT_BITS); + + hybOffset += nHybBands; + } + + if (hSynthesisHybFilter->nrBands > nrQmfBandsLF) { + /* + * HF buffer. + */ + FDKmemcpy(&pQmfReal[nrQmfBandsLF], &pHybridReal[hybOffset], + (hSynthesisHybFilter->nrBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + FDKmemcpy( + &pQmfImag[nrQmfBandsLF], &pHybridImag[hybOffset], + (hSynthesisHybFilter->cplxBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + } + + return; +} + +static void dualChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const INT invert) { + FIXP_DBL r1, r6; + FIXP_DBL i1, i6; + + const FIXP_HTB f0 = HybFilterCoef2[0]; /* corresponds to p1 and p11 */ + const FIXP_HTB f1 = HybFilterCoef2[1]; /* corresponds to p3 and p9 */ + const FIXP_HTB f2 = HybFilterCoef2[2]; /* corresponds to p5 and p7 */ + + /* symmetric filter coefficients */ + r1 = fMultDiv2(f0, pQmfReal[pReadIdx[1]]) + + fMultDiv2(f0, pQmfReal[pReadIdx[11]]); + i1 = fMultDiv2(f0, pQmfImag[pReadIdx[1]]) + + fMultDiv2(f0, pQmfImag[pReadIdx[11]]); + r1 += fMultDiv2(f1, pQmfReal[pReadIdx[3]]) + + fMultDiv2(f1, pQmfReal[pReadIdx[9]]); + i1 += fMultDiv2(f1, pQmfImag[pReadIdx[3]]) + + fMultDiv2(f1, pQmfImag[pReadIdx[9]]); + r1 += fMultDiv2(f2, pQmfReal[pReadIdx[5]]) + + fMultDiv2(f2, pQmfReal[pReadIdx[7]]); + i1 += fMultDiv2(f2, pQmfImag[pReadIdx[5]]) + + fMultDiv2(f2, pQmfImag[pReadIdx[7]]); + + r6 = pQmfReal[pReadIdx[6]] >> 2; + i6 = pQmfImag[pReadIdx[6]] >> 2; + + FDK_ASSERT((invert == 0) || (invert == 1)); + mHybridReal[0 + invert] = SATURATE_LEFT_SHIFT((r6 + r1), 1, DFRACT_BITS); + mHybridImag[0 + invert] = SATURATE_LEFT_SHIFT((i6 + i1), 1, DFRACT_BITS); + + mHybridReal[1 - invert] = SATURATE_LEFT_SHIFT((r6 - r1), 1, DFRACT_BITS); + mHybridImag[1 - invert] = SATURATE_LEFT_SHIFT((i6 - i1), 1, DFRACT_BITS); +} + +static void fourChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const INT invert) { + const FIXP_HTB *p = HybFilterCoef4; + + FIXP_DBL fft[8]; + + static const FIXP_DBL cr[13] = { + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(-1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(1.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(-1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(0.f)}; + static const FIXP_DBL ci[13] = { + FL2FXCONST_DBL(-1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(1.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(-1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(1.f)}; + + /* FIR filter. */ + /* pre twiddeling with pre-twiddling coefficients c[n] */ + /* multiplication with filter coefficients p[n] */ + /* hint: (a + ib)*(c + id) = (a*c - b*d) + i(a*d + b*c) */ + /* write to fft coefficient n' */ + fft[FFT_IDX_R(0)] = + (fMult(p[10], (fMultSub(fMultDiv2(cr[2], pQmfReal[pReadIdx[2]]), ci[2], + pQmfImag[pReadIdx[2]]))) + + fMult(p[6], (fMultSub(fMultDiv2(cr[6], pQmfReal[pReadIdx[6]]), ci[6], + pQmfImag[pReadIdx[6]]))) + + fMult(p[2], (fMultSub(fMultDiv2(cr[10], pQmfReal[pReadIdx[10]]), ci[10], + pQmfImag[pReadIdx[10]])))); + fft[FFT_IDX_I(0)] = + (fMult(p[10], (fMultAdd(fMultDiv2(ci[2], pQmfReal[pReadIdx[2]]), cr[2], + pQmfImag[pReadIdx[2]]))) + + fMult(p[6], (fMultAdd(fMultDiv2(ci[6], pQmfReal[pReadIdx[6]]), cr[6], + pQmfImag[pReadIdx[6]]))) + + fMult(p[2], (fMultAdd(fMultDiv2(ci[10], pQmfReal[pReadIdx[10]]), cr[10], + pQmfImag[pReadIdx[10]])))); + + /* twiddle dee dum */ + fft[FFT_IDX_R(1)] = + (fMult(p[9], (fMultSub(fMultDiv2(cr[3], pQmfReal[pReadIdx[3]]), ci[3], + pQmfImag[pReadIdx[3]]))) + + fMult(p[5], (fMultSub(fMultDiv2(cr[7], pQmfReal[pReadIdx[7]]), ci[7], + pQmfImag[pReadIdx[7]]))) + + fMult(p[1], (fMultSub(fMultDiv2(cr[11], pQmfReal[pReadIdx[11]]), ci[11], + pQmfImag[pReadIdx[11]])))); + fft[FFT_IDX_I(1)] = + (fMult(p[9], (fMultAdd(fMultDiv2(ci[3], pQmfReal[pReadIdx[3]]), cr[3], + pQmfImag[pReadIdx[3]]))) + + fMult(p[5], (fMultAdd(fMultDiv2(ci[7], pQmfReal[pReadIdx[7]]), cr[7], + pQmfImag[pReadIdx[7]]))) + + fMult(p[1], (fMultAdd(fMultDiv2(ci[11], pQmfReal[pReadIdx[11]]), cr[11], + pQmfImag[pReadIdx[11]])))); + + /* twiddle dee dee */ + fft[FFT_IDX_R(2)] = + (fMult(p[12], (fMultSub(fMultDiv2(cr[0], pQmfReal[pReadIdx[0]]), ci[0], + pQmfImag[pReadIdx[0]]))) + + fMult(p[8], (fMultSub(fMultDiv2(cr[4], pQmfReal[pReadIdx[4]]), ci[4], + pQmfImag[pReadIdx[4]]))) + + fMult(p[4], (fMultSub(fMultDiv2(cr[8], pQmfReal[pReadIdx[8]]), ci[8], + pQmfImag[pReadIdx[8]]))) + + fMult(p[0], (fMultSub(fMultDiv2(cr[12], pQmfReal[pReadIdx[12]]), ci[12], + pQmfImag[pReadIdx[12]])))); + fft[FFT_IDX_I(2)] = + (fMult(p[12], (fMultAdd(fMultDiv2(ci[0], pQmfReal[pReadIdx[0]]), cr[0], + pQmfImag[pReadIdx[0]]))) + + fMult(p[8], (fMultAdd(fMultDiv2(ci[4], pQmfReal[pReadIdx[4]]), cr[4], + pQmfImag[pReadIdx[4]]))) + + fMult(p[4], (fMultAdd(fMultDiv2(ci[8], pQmfReal[pReadIdx[8]]), cr[8], + pQmfImag[pReadIdx[8]]))) + + fMult(p[0], (fMultAdd(fMultDiv2(ci[12], pQmfReal[pReadIdx[12]]), cr[12], + pQmfImag[pReadIdx[12]])))); + + fft[FFT_IDX_R(3)] = + (fMult(p[11], (fMultSub(fMultDiv2(cr[1], pQmfReal[pReadIdx[1]]), ci[1], + pQmfImag[pReadIdx[1]]))) + + fMult(p[7], (fMultSub(fMultDiv2(cr[5], pQmfReal[pReadIdx[5]]), ci[5], + pQmfImag[pReadIdx[5]]))) + + fMult(p[3], (fMultSub(fMultDiv2(cr[9], pQmfReal[pReadIdx[9]]), ci[9], + pQmfImag[pReadIdx[9]])))); + fft[FFT_IDX_I(3)] = + (fMult(p[11], (fMultAdd(fMultDiv2(ci[1], pQmfReal[pReadIdx[1]]), cr[1], + pQmfImag[pReadIdx[1]]))) + + fMult(p[7], (fMultAdd(fMultDiv2(ci[5], pQmfReal[pReadIdx[5]]), cr[5], + pQmfImag[pReadIdx[5]]))) + + fMult(p[3], (fMultAdd(fMultDiv2(ci[9], pQmfReal[pReadIdx[9]]), cr[9], + pQmfImag[pReadIdx[9]])))); + + /* fft modulation */ + /* here: fast manual fft modulation for a fft of length M=4 */ + /* fft_4{x[n]} = x[0]*exp(-i*2*pi/4*m*0) + x[1]*exp(-i*2*pi/4*m*1) + + x[2]*exp(-i*2*pi/4*m*2) + x[3]*exp(-i*2*pi/4*m*3) */ + + /* + fft bin m=0: + X[0, n] = x[0] + x[1] + x[2] + x[3] + */ + mHybridReal[0] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] + + fft[FFT_IDX_R(3)]; + mHybridImag[0] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] + + fft[FFT_IDX_I(3)]; + + /* + fft bin m=1: + X[1, n] = x[0] - i*x[1] - x[2] + i*x[3] + */ + mHybridReal[1] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] - + fft[FFT_IDX_I(3)]; + mHybridImag[1] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] + + fft[FFT_IDX_R(3)]; + + /* + fft bin m=2: + X[2, n] = x[0] - x[1] + x[2] - x[3] + */ + mHybridReal[2] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] - + fft[FFT_IDX_R(3)]; + mHybridImag[2] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] - + fft[FFT_IDX_I(3)]; + + /* + fft bin m=3: + X[3, n] = x[0] + j*x[1] - x[2] - j*x[3] + */ + mHybridReal[3] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] + + fft[FFT_IDX_I(3)]; + mHybridImag[3] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] - + fft[FFT_IDX_R(3)]; +} + +static void eightChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const INT invert) { + const FIXP_HTP *p = HybFilterCoef8; + INT k, sc; + + FIXP_DBL mfft[16 + ALIGNMENT_DEFAULT]; + FIXP_DBL *pfft = (FIXP_DBL *)ALIGN_PTR(mfft); + + FIXP_DBL accu1, accu2, accu3, accu4; + + /* pre twiddeling */ + pfft[FFT_IDX_R(0)] = + pQmfReal[pReadIdx[6]] >> + (3 + 1); /* fMultDiv2(p[0].v.re, pQmfReal[pReadIdx[6]]); */ + pfft[FFT_IDX_I(0)] = + pQmfImag[pReadIdx[6]] >> + (3 + 1); /* fMultDiv2(p[0].v.re, pQmfImag[pReadIdx[6]]); */ + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[7]], pQmfImag[pReadIdx[7]], + p[1]); + pfft[FFT_IDX_R(1)] = accu1; + pfft[FFT_IDX_I(1)] = accu2; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[0]], pQmfImag[pReadIdx[0]], + p[2]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[8]], pQmfImag[pReadIdx[8]], + p[3]); + pfft[FFT_IDX_R(2)] = accu1 + accu3; + pfft[FFT_IDX_I(2)] = accu2 + accu4; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[1]], pQmfImag[pReadIdx[1]], + p[4]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[9]], pQmfImag[pReadIdx[9]], + p[5]); + pfft[FFT_IDX_R(3)] = accu1 + accu3; + pfft[FFT_IDX_I(3)] = accu2 + accu4; + + pfft[FFT_IDX_R(4)] = fMultDiv2(pQmfImag[pReadIdx[10]], p[7].v.im) - + fMultDiv2(pQmfImag[pReadIdx[2]], p[6].v.im); + pfft[FFT_IDX_I(4)] = fMultDiv2(pQmfReal[pReadIdx[2]], p[6].v.im) - + fMultDiv2(pQmfReal[pReadIdx[10]], p[7].v.im); + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[3]], pQmfImag[pReadIdx[3]], + p[8]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[11]], pQmfImag[pReadIdx[11]], + p[9]); + pfft[FFT_IDX_R(5)] = accu1 + accu3; + pfft[FFT_IDX_I(5)] = accu2 + accu4; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[4]], pQmfImag[pReadIdx[4]], + p[10]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[12]], pQmfImag[pReadIdx[12]], + p[11]); + pfft[FFT_IDX_R(6)] = accu1 + accu3; + pfft[FFT_IDX_I(6)] = accu2 + accu4; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[5]], pQmfImag[pReadIdx[5]], + p[12]); + pfft[FFT_IDX_R(7)] = accu1; + pfft[FFT_IDX_I(7)] = accu2; + + /* fft modulation */ + fft_8(pfft); + sc = 1 + 2; + + if (invert) { + mHybridReal[0] = pfft[FFT_IDX_R(7)] << sc; + mHybridImag[0] = pfft[FFT_IDX_I(7)] << sc; + mHybridReal[1] = pfft[FFT_IDX_R(0)] << sc; + mHybridImag[1] = pfft[FFT_IDX_I(0)] << sc; + + mHybridReal[2] = pfft[FFT_IDX_R(6)] << sc; + mHybridImag[2] = pfft[FFT_IDX_I(6)] << sc; + mHybridReal[3] = pfft[FFT_IDX_R(1)] << sc; + mHybridImag[3] = pfft[FFT_IDX_I(1)] << sc; + + mHybridReal[4] = SATURATE_LEFT_SHIFT( + (pfft[FFT_IDX_R(2)] + pfft[FFT_IDX_R(5)]), sc, DFRACT_BITS); + mHybridImag[4] = SATURATE_LEFT_SHIFT( + (pfft[FFT_IDX_I(2)] + pfft[FFT_IDX_I(5)]), sc, DFRACT_BITS); + + mHybridReal[5] = SATURATE_LEFT_SHIFT( + (pfft[FFT_IDX_R(3)] + pfft[FFT_IDX_R(4)]), sc, DFRACT_BITS); + mHybridImag[5] = SATURATE_LEFT_SHIFT( + (pfft[FFT_IDX_I(3)] + pfft[FFT_IDX_I(4)]), sc, DFRACT_BITS); + } else { + for (k = 0; k < 8; k++) { + mHybridReal[k] = pfft[FFT_IDX_R(k)] << sc; + mHybridImag[k] = pfft[FFT_IDX_I(k)] << sc; + } + } +} + +static INT kChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const SCHAR hybridConfig) { + INT err = 0; + + switch (hybridConfig) { + case 2: + case -2: + dualChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, + mHybridImag, (hybridConfig < 0) ? 1 : 0); + break; + case 4: + case -4: + fourChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, + mHybridImag, (hybridConfig < 0) ? 1 : 0); + break; + case 8: + case -8: + eightChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, + mHybridImag, (hybridConfig < 0) ? 1 : 0); + break; + default: + err = -1; + } + + return err; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_lpc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_lpc.cpp new file mode 100644 index 0000000000000..7d7e6912db7ee --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_lpc.cpp @@ -0,0 +1,487 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander + + Description: LPC related functions + +*******************************************************************************/ + +#include "FDK_lpc.h" + +/* Internal scaling of LPC synthesis to avoid overflow of filte states. + This depends on the LPC order, because the LPC order defines the amount + of MAC operations. */ +static SCHAR order_ld[LPC_MAX_ORDER] = { + /* Assume that Synthesis filter output does not clip and filter + accu does change no more than 1.0 for each iteration. + ceil(0.5*log((1:24))/log(2)) */ + 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3}; + +/* IIRLattice */ +#ifndef FUNCTION_CLpc_SynthesisLattice_SGL +void CLpc_SynthesisLattice(FIXP_DBL *signal, const int signal_size, + const int signal_e, const int signal_e_out, + const int inc, const FIXP_SGL *coeff, + const int order, FIXP_DBL *state) { + int i, j; + FIXP_DBL *pSignal; + int shift; + + FDK_ASSERT(order <= LPC_MAX_ORDER); + FDK_ASSERT(order > 0); + + if (inc == -1) + pSignal = &signal[signal_size - 1]; + else + pSignal = &signal[0]; + + /* + tmp = x(k) - K(M)*g(M); + for m=M-1:-1:1 + tmp = tmp - K(m) * g(m); + g(m+1) = g(m) + K(m) * tmp; + endfor + g(1) = tmp; + + y(k) = tmp; + */ + + shift = -order_ld[order - 1]; + + for (i = signal_size; i != 0; i--) { + FIXP_DBL *pState = state + order - 1; + const FIXP_SGL *pCoeff = coeff + order - 1; + FIXP_DBL tmp; + + tmp = scaleValue(*pSignal, shift + signal_e) - + fMultDiv2(*pCoeff--, *pState--); + for (j = order - 1; j != 0; j--) { + tmp = fMultSubDiv2(tmp, pCoeff[0], pState[0]); + pState[1] = pState[0] + (fMultDiv2(*pCoeff--, tmp) << 2); + pState--; + } + + *pSignal = scaleValueSaturate(tmp, -shift - signal_e_out); + + /* exponent of state[] is -1 */ + pState[1] = tmp << 1; + pSignal += inc; + } +} +#endif + +#ifndef FUNCTION_CLpc_SynthesisLattice_DBL +void CLpc_SynthesisLattice(FIXP_DBL *signal, const int signal_size, + const int signal_e, const int signal_e_out, + const int inc, const FIXP_DBL *coeff, + const int order, FIXP_DBL *state) { + int i, j; + FIXP_DBL *pSignal; + + FDK_ASSERT(order <= LPC_MAX_ORDER); + FDK_ASSERT(order > 0); + + if (inc == -1) + pSignal = &signal[signal_size - 1]; + else + pSignal = &signal[0]; + + FDK_ASSERT(signal_size > 0); + for (i = signal_size; i != 0; i--) { + FIXP_DBL *pState = state + order - 1; + const FIXP_DBL *pCoeff = coeff + order - 1; + FIXP_DBL tmp, accu; + + accu = + fMultSubDiv2(scaleValue(*pSignal, signal_e - 1), *pCoeff--, *pState--); + tmp = SATURATE_LEFT_SHIFT_ALT(accu, 1, DFRACT_BITS); + + for (j = order - 1; j != 0; j--) { + accu = fMultSubDiv2(tmp >> 1, pCoeff[0], pState[0]); + tmp = SATURATE_LEFT_SHIFT_ALT(accu, 1, DFRACT_BITS); + + accu = fMultAddDiv2(pState[0] >> 1, *pCoeff--, tmp); + pState[1] = SATURATE_LEFT_SHIFT_ALT(accu, 1, DFRACT_BITS); + + pState--; + } + + *pSignal = scaleValue(tmp, -signal_e_out); + + /* exponent of state[] is 0 */ + pState[1] = tmp; + pSignal += inc; + } +} + +#endif + +/* LPC_SYNTHESIS_IIR version */ +void CLpc_Synthesis(FIXP_DBL *signal, const int signal_size, const int signal_e, + const int inc, const FIXP_LPC_TNS *lpcCoeff_m, + const int lpcCoeff_e, const int order, FIXP_DBL *state, + int *pStateIndex) { + int i, j; + FIXP_DBL *pSignal; + int stateIndex = *pStateIndex; + + FIXP_LPC_TNS coeff[2 * LPC_MAX_ORDER]; + FDKmemcpy(&coeff[0], lpcCoeff_m, order * sizeof(FIXP_LPC_TNS)); + FDKmemcpy(&coeff[order], lpcCoeff_m, order * sizeof(FIXP_LPC_TNS)); + + FDK_ASSERT(order <= LPC_MAX_ORDER); + FDK_ASSERT(stateIndex < order); + + if (inc == -1) + pSignal = &signal[signal_size - 1]; + else + pSignal = &signal[0]; + + /* y(n) = x(n) - lpc[1]*y(n-1) - ... - lpc[order]*y(n-order) */ + + for (i = 0; i < signal_size; i++) { + FIXP_DBL x; + const FIXP_LPC_TNS *pCoeff = coeff + order - stateIndex; + + x = scaleValue(*pSignal, -(lpcCoeff_e + 1)); + for (j = 0; j < order; j++) { + x -= fMultDiv2(state[j], pCoeff[j]); + } + x = SATURATE_SHIFT(x, -lpcCoeff_e - 1, DFRACT_BITS); + + /* Update states */ + stateIndex = ((stateIndex - 1) < 0) ? (order - 1) : (stateIndex - 1); + state[stateIndex] = x; + + *pSignal = scaleValue(x, signal_e); + pSignal += inc; + } + + *pStateIndex = stateIndex; +} +/* default version */ +void CLpc_Synthesis(FIXP_DBL *signal, const int signal_size, const int signal_e, + const int inc, const FIXP_LPC *lpcCoeff_m, + const int lpcCoeff_e, const int order, FIXP_DBL *state, + int *pStateIndex) { + int i, j; + FIXP_DBL *pSignal; + int stateIndex = *pStateIndex; + + FIXP_LPC coeff[2 * LPC_MAX_ORDER]; + FDKmemcpy(&coeff[0], lpcCoeff_m, order * sizeof(FIXP_LPC)); + FDKmemcpy(&coeff[order], lpcCoeff_m, order * sizeof(FIXP_LPC)); + + FDK_ASSERT(order <= LPC_MAX_ORDER); + FDK_ASSERT(stateIndex < order); + + if (inc == -1) + pSignal = &signal[signal_size - 1]; + else + pSignal = &signal[0]; + + /* y(n) = x(n) - lpc[1]*y(n-1) - ... - lpc[order]*y(n-order) */ + + for (i = 0; i < signal_size; i++) { + FIXP_DBL x; + const FIXP_LPC *pCoeff = coeff + order - stateIndex; + + x = scaleValue(*pSignal, -(lpcCoeff_e + 1)); + for (j = 0; j < order; j++) { + x -= fMultDiv2(state[j], pCoeff[j]); + } + x = SATURATE_SHIFT(x, -lpcCoeff_e - 1, DFRACT_BITS); + + /* Update states */ + stateIndex = ((stateIndex - 1) < 0) ? (order - 1) : (stateIndex - 1); + state[stateIndex] = x; + + *pSignal = scaleValue(x, signal_e); + pSignal += inc; + } + + *pStateIndex = stateIndex; +} + +/* FIR */ +void CLpc_Analysis(FIXP_DBL *RESTRICT signal, const int signal_size, + const FIXP_LPC lpcCoeff_m[], const int lpcCoeff_e, + const int order, FIXP_DBL *RESTRICT filtState, + int *filtStateIndex) { + int stateIndex; + INT i, j, shift = lpcCoeff_e + 1; /* +1, because fMultDiv2 */ + FIXP_DBL tmp; + + if (order <= 0) { + return; + } + if (filtStateIndex != NULL) { + stateIndex = *filtStateIndex; + } else { + stateIndex = 0; + } + + /* keep filter coefficients twice and save memory copy operation in + modulo state buffer */ + FIXP_LPC coeff[2 * LPC_MAX_ORDER]; + FIXP_LPC *pCoeff; + FDKmemcpy(&coeff[0], lpcCoeff_m, order * sizeof(FIXP_LPC)); + FDKmemcpy(&coeff[order], lpcCoeff_m, order * sizeof(FIXP_LPC)); + + /* + # Analysis filter, obtain residual. + for k = 0:BL-1 + err(i-BL+k) = a * inputSignal(i-BL+k:-1:i-BL-M+k); + endfor + */ + + FDK_ASSERT(shift >= 0); + + for (j = 0; j < signal_size; j++) { + pCoeff = &coeff[(order - stateIndex)]; + + tmp = signal[j] >> shift; + for (i = 0; i < order; i++) { + tmp = fMultAddDiv2(tmp, pCoeff[i], filtState[i]); + } + + stateIndex = + ((stateIndex - 1) < 0) ? (stateIndex - 1 + order) : (stateIndex - 1); + filtState[stateIndex] = signal[j]; + + signal[j] = tmp << shift; + } + + if (filtStateIndex != NULL) { + *filtStateIndex = stateIndex; + } +} + +/* For the LPC_SYNTHESIS_IIR version */ +INT CLpc_ParcorToLpc(const FIXP_LPC_TNS reflCoeff[], FIXP_LPC_TNS LpcCoeff[], + INT numOfCoeff, FIXP_DBL workBuffer[]) { + INT i, j; + INT shiftval, + par2LpcShiftVal = 6; /* 6 should be enough, bec. max(numOfCoeff) = 20 */ + FIXP_DBL maxVal = (FIXP_DBL)0; + + workBuffer[0] = FX_LPC_TNS2FX_DBL(reflCoeff[0]) >> par2LpcShiftVal; + for (i = 1; i < numOfCoeff; i++) { + for (j = 0; j < i / 2; j++) { + FIXP_DBL tmp1, tmp2; + + tmp1 = workBuffer[j]; + tmp2 = workBuffer[i - 1 - j]; + workBuffer[j] += fMult(reflCoeff[i], tmp2); + workBuffer[i - 1 - j] += fMult(reflCoeff[i], tmp1); + } + if (i & 1) { + workBuffer[j] += fMult(reflCoeff[i], workBuffer[j]); + } + + workBuffer[i] = FX_LPC_TNS2FX_DBL(reflCoeff[i]) >> par2LpcShiftVal; + } + + /* calculate exponent */ + for (i = 0; i < numOfCoeff; i++) { + maxVal = fMax(maxVal, fAbs(workBuffer[i])); + } + + shiftval = fMin(fNorm(maxVal), par2LpcShiftVal); + + for (i = 0; i < numOfCoeff; i++) { + LpcCoeff[i] = FX_DBL2FX_LPC_TNS(workBuffer[i] << shiftval); + } + + return (par2LpcShiftVal - shiftval); +} +/* Default version */ +INT CLpc_ParcorToLpc(const FIXP_LPC reflCoeff[], FIXP_LPC LpcCoeff[], + INT numOfCoeff, FIXP_DBL workBuffer[]) { + INT i, j; + INT shiftval, + par2LpcShiftVal = 6; /* 6 should be enough, bec. max(numOfCoeff) = 20 */ + FIXP_DBL maxVal = (FIXP_DBL)0; + + workBuffer[0] = FX_LPC2FX_DBL(reflCoeff[0]) >> par2LpcShiftVal; + for (i = 1; i < numOfCoeff; i++) { + for (j = 0; j < i / 2; j++) { + FIXP_DBL tmp1, tmp2; + + tmp1 = workBuffer[j]; + tmp2 = workBuffer[i - 1 - j]; + workBuffer[j] += fMult(reflCoeff[i], tmp2); + workBuffer[i - 1 - j] += fMult(reflCoeff[i], tmp1); + } + if (i & 1) { + workBuffer[j] += fMult(reflCoeff[i], workBuffer[j]); + } + + workBuffer[i] = FX_LPC2FX_DBL(reflCoeff[i]) >> par2LpcShiftVal; + } + + /* calculate exponent */ + for (i = 0; i < numOfCoeff; i++) { + maxVal = fMax(maxVal, fAbs(workBuffer[i])); + } + + shiftval = fMin(fNorm(maxVal), par2LpcShiftVal); + + for (i = 0; i < numOfCoeff; i++) { + LpcCoeff[i] = FX_DBL2FX_LPC(workBuffer[i] << shiftval); + } + + return (par2LpcShiftVal - shiftval); +} + +void CLpc_AutoToParcor(FIXP_DBL acorr[], const int acorr_e, + FIXP_LPC reflCoeff[], const int numOfCoeff, + FIXP_DBL *pPredictionGain_m, INT *pPredictionGain_e) { + INT i, j, scale = 0; + FIXP_DBL parcorWorkBuffer[LPC_MAX_ORDER]; + + FIXP_DBL *workBuffer = parcorWorkBuffer; + FIXP_DBL autoCorr_0 = acorr[0]; + + FDKmemclear(reflCoeff, numOfCoeff * sizeof(FIXP_LPC)); + + if (autoCorr_0 == FL2FXCONST_DBL(0.0)) { + if (pPredictionGain_m != NULL) { + *pPredictionGain_m = FL2FXCONST_DBL(0.5f); + *pPredictionGain_e = 1; + } + return; + } + + FDKmemcpy(workBuffer, acorr + 1, numOfCoeff * sizeof(FIXP_DBL)); + for (i = 0; i < numOfCoeff; i++) { + LONG sign = ((LONG)workBuffer[0] >> (DFRACT_BITS - 1)); + FIXP_DBL tmp = (FIXP_DBL)((LONG)workBuffer[0] ^ sign); + + /* Check preconditions for division function: num<=denum */ + /* For 1st iteration acorr[0] cannot be 0, it is checked before loop */ + /* Due to exor operation with "sign", num(=tmp) is greater/equal 0 */ + if (acorr[0] < tmp) break; + + /* tmp = div(num, denum, 16) */ + tmp = (FIXP_DBL)((LONG)schur_div(tmp, acorr[0], FRACT_BITS) ^ (~sign)); + + reflCoeff[i] = FX_DBL2FX_LPC(tmp); + + for (j = numOfCoeff - i - 1; j >= 0; j--) { + FIXP_DBL accu1 = fMult(tmp, acorr[j]); + FIXP_DBL accu2 = fMult(tmp, workBuffer[j]); + workBuffer[j] += accu1; + acorr[j] += accu2; + } + /* Check preconditions for division function: denum (=acorr[0]) > 0 */ + if (acorr[0] == (FIXP_DBL)0) break; + + workBuffer++; + } + + if (pPredictionGain_m != NULL) { + if (acorr[0] > (FIXP_DBL)0) { + /* prediction gain = signal power / error (residual) power */ + *pPredictionGain_m = fDivNormSigned(autoCorr_0, acorr[0], &scale); + *pPredictionGain_e = scale; + } else { + *pPredictionGain_m = (FIXP_DBL)0; + *pPredictionGain_e = 0; + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_matrixCalloc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_matrixCalloc.cpp new file mode 100644 index 0000000000000..5d5c5212986ac --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_matrixCalloc.cpp @@ -0,0 +1,315 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: matrix memory allocation + +*******************************************************************************/ + +#include "FDK_matrixCalloc.h" + +#include "genericStds.h" + +void *fdkCallocMatrix1D_aligned(UINT dim1, UINT size) { + return FDKaalloc(dim1 * size, ALIGNMENT_DEFAULT); +} + +void *fdkCallocMatrix1D_int(UINT dim, UINT size, MEMORY_SECTION s) { + return FDKcalloc_L(dim, size, s); +} + +void *fdkCallocMatrix1D_int_aligned(UINT dim, UINT size, MEMORY_SECTION s) { + return FDKaalloc_L(dim * size, ALIGNMENT_DEFAULT, s); +} + +void fdkFreeMatrix1D(void *p) { + if (p != NULL) { + FDKfree_L(p); + } +} + +void fdkFreeMatrix1D_aligned(void *p) { + if (p != NULL) { + FDKafree_L(p); + } +} + +void *fdkCallocMatrix1D(UINT dim1, UINT size) { return FDKcalloc(dim1, size); } + +/* 2D */ +void **fdkCallocMatrix2D(UINT dim1, UINT dim2, UINT size) { + void **p1; + UINT i; + char *p2; + if (!dim1 || !dim2) return NULL; + if ((p1 = (void **)fdkCallocMatrix1D(dim1, sizeof(void *))) == NULL) { + goto bail; + } + if ((p2 = (char *)fdkCallocMatrix1D(dim1 * dim2, size)) == NULL) { + fdkFreeMatrix1D(p1); + p1 = NULL; + goto bail; + } + for (i = 0; i < dim1; i++) { + p1[i] = p2; + p2 += dim2 * size; + } +bail: + return p1; +} + +void **fdkCallocMatrix2D_aligned(UINT dim1, UINT dim2, UINT size) { + void **p1; + UINT i; + char *p2; + if (!dim1 || !dim2) return NULL; + if ((p1 = (void **)fdkCallocMatrix1D(dim1, sizeof(void *))) == NULL) { + goto bail; + } + if ((p2 = (char *)fdkCallocMatrix1D_aligned(dim1 * dim2, size)) == NULL) { + fdkFreeMatrix1D(p1); + p1 = NULL; + goto bail; + } + for (i = 0; i < dim1; i++) { + p1[i] = p2; + p2 += dim2 * size; + } +bail: + return p1; +} + +void fdkFreeMatrix2D(void **p) { + if (!p) return; + fdkFreeMatrix1D(p[0]); + fdkFreeMatrix1D(p); +} + +void fdkFreeMatrix2D_aligned(void **p) { + if (!p) return; + fdkFreeMatrix1D_aligned(p[0]); + fdkFreeMatrix1D(p); +} + +void **fdkCallocMatrix2D_int(UINT dim1, UINT dim2, UINT size, + MEMORY_SECTION s) { + void **p1; + UINT i; + char *p2; + + if (!dim1 || !dim2) return NULL; + if ((p1 = (void **)fdkCallocMatrix1D_int(dim1, sizeof(void *), s)) == NULL) { + goto bail; + } + if ((p2 = (char *)fdkCallocMatrix1D_int(dim1 * dim2, size, s)) == NULL) { + fdkFreeMatrix1D(p1); + p1 = NULL; + goto bail; + } + for (i = 0; i < dim1; i++) { + p1[i] = p2; + p2 += dim2 * size; + } +bail: + return p1; +} + +void **fdkCallocMatrix2D_int_aligned(UINT dim1, UINT dim2, UINT size, + MEMORY_SECTION s) { + void **p1; + UINT i; + char *p2; + + if (!dim1 || !dim2) return NULL; + if ((p1 = (void **)fdkCallocMatrix1D_int(dim1, sizeof(void *), s)) == NULL) { + goto bail; + } + if ((p2 = (char *)fdkCallocMatrix1D_int_aligned(dim1 * dim2, size, s)) == + NULL) { + fdkFreeMatrix1D(p1); + p1 = NULL; + goto bail; + } + for (i = 0; i < dim1; i++) { + p1[i] = p2; + p2 += dim2 * size; + } +bail: + return p1; +} + +/* 3D */ +void ***fdkCallocMatrix3D(UINT dim1, UINT dim2, UINT dim3, UINT size) { + void ***p1; + UINT i, j; + void **p2; + char *p3; + + if (!dim1 || !dim2 || !dim3) return NULL; + if ((p1 = (void ***)fdkCallocMatrix1D(dim1, sizeof(void **))) == NULL) { + goto bail; + } + if ((p2 = (void **)fdkCallocMatrix1D(dim1 * dim2, sizeof(void *))) == NULL) { + fdkFreeMatrix1D(p1); + p1 = NULL; + goto bail; + } + p1[0] = p2; + if ((p3 = (char *)fdkCallocMatrix1D(dim1 * dim2 * dim3, size)) == NULL) { + fdkFreeMatrix1D(p1); + fdkFreeMatrix1D(p2); + p1 = NULL; + p2 = NULL; + goto bail; + } + for (i = 0; i < dim1; i++) { + p1[i] = p2; + for (j = 0; j < dim2; j++) { + p2[j] = p3; + p3 += dim3 * size; + } + p2 += dim2; + } +bail: + return p1; +} + +void fdkFreeMatrix3D(void ***p) { + if (!p) return; + if (p[0] != NULL) fdkFreeMatrix1D(p[0][0]); + fdkFreeMatrix1D(p[0]); + fdkFreeMatrix1D(p); +} + +void ***fdkCallocMatrix3D_int(UINT dim1, UINT dim2, UINT dim3, UINT size, + MEMORY_SECTION s) { + void ***p1; + UINT i, j; + void **p2; + char *p3; + + if (!dim1 || !dim2 || !dim3) return NULL; + if ((p1 = (void ***)fdkCallocMatrix1D_int(dim1, sizeof(void **), s)) == + NULL) { + goto bail; + } + if ((p2 = (void **)fdkCallocMatrix1D_int(dim1 * dim2, sizeof(void *), s)) == + NULL) { + fdkFreeMatrix1D(p1); + p1 = NULL; + goto bail; + } + p1[0] = p2; + if ((p3 = (char *)fdkCallocMatrix1D_int(dim1 * dim2 * dim3, size, s)) == + NULL) { + fdkFreeMatrix1D(p1); + fdkFreeMatrix1D(p2); + p1 = NULL; + p2 = NULL; + goto bail; + } + for (i = 0; i < dim1; i++) { + p1[i] = p2; + for (j = 0; j < dim2; j++) { + p2[j] = p3; + p3 += dim3 * size; + } + p2 += dim2; + } +bail: + return p1; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_qmf_domain.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_qmf_domain.cpp new file mode 100644 index 0000000000000..77c5ca2969247 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_qmf_domain.cpp @@ -0,0 +1,1013 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Matthias Hildenbrand + + Description: Module to efficiently handle QMF data for multiple channels and + to share the data between e.g. SBR and MPS + +*******************************************************************************/ + +#include "FDK_qmf_domain.h" + +#include "common_fix.h" + +#define WORKBUFFER1_TAG 0 +#define WORKBUFFER3_TAG 4 +#define WORKBUFFER4_TAG 5 +#define WORKBUFFER6_TAG 7 +#define WORKBUFFER7_TAG 8 + +C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore1, FIXP_DBL, QMF_WB_SECTION_SIZE, + SECT_DATA_L1, WORKBUFFER1_TAG) +C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore3, FIXP_DBL, QMF_WB_SECTION_SIZE, + SECT_DATA_L2, WORKBUFFER3_TAG) +C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore4, FIXP_DBL, QMF_WB_SECTION_SIZE, + SECT_DATA_L2, WORKBUFFER4_TAG) +C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore6, FIXP_DBL, QMF_WB_SECTION_SIZE, + SECT_DATA_L2, WORKBUFFER6_TAG) +C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore7, FIXP_DBL, QMF_WB_SECTION_SIZE, + SECT_DATA_L2, WORKBUFFER7_TAG) + +/*! Analysis states buffer.
+ Dimension: #((8) + (1)) */ +C_AALLOC_MEM2(AnaQmfStates, FIXP_DBL, 10 * QMF_DOMAIN_MAX_ANALYSIS_QMF_BANDS, + ((8) + (1))) + +/*! Synthesis states buffer.
+ Dimension: #((8) + (1)) */ +C_AALLOC_MEM2(SynQmfStates, FIXP_QSS, 9 * QMF_DOMAIN_MAX_SYNTHESIS_QMF_BANDS, + ((8) + (1))) + +/*! Pointer to real qmf data for each time slot.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(QmfSlotsReal, FIXP_DBL *, + QMF_DOMAIN_MAX_TIMESLOTS + QMF_DOMAIN_MAX_OV_TIMESLOTS, + ((8) + (1))) + +/*! Pointer to imaginary qmf data for each time slot.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(QmfSlotsImag, FIXP_DBL *, + QMF_DOMAIN_MAX_TIMESLOTS + QMF_DOMAIN_MAX_OV_TIMESLOTS, + ((8) + (1))) + +/*! QMF overlap buffer.
+ Dimension: #((8) + (1)) */ +C_AALLOC_MEM2(QmfOverlapBuffer, FIXP_DBL, + 2 * QMF_DOMAIN_MAX_OV_TIMESLOTS * QMF_DOMAIN_MAX_QMF_PROC_BANDS, + ((8) + (1))) + +/*! Analysis states buffer.
+ Dimension: #((8) + (1)) */ +C_AALLOC_MEM2(AnaQmfStates16, FIXP_DBL, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_16, + ((8) + (1))) +/*! Analysis states buffer.
+ Dimension: #((8) + (1)) */ +C_AALLOC_MEM2(AnaQmfStates24, FIXP_DBL, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_24, + ((8) + (1))) + +/*! Analysis states buffer.
+ Dimension: #((8) + (1)) */ +C_AALLOC_MEM2(AnaQmfStates32, FIXP_DBL, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_32, + ((8) + (1))) + +/*! Pointer to real qmf data for each time slot.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(QmfSlotsReal16, FIXP_DBL *, + QMF_DOMAIN_TIMESLOTS_16 + QMF_DOMAIN_OV_TIMESLOTS_16, ((8) + (1))) + +/*! Pointer to real qmf data for each time slot.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(QmfSlotsReal32, FIXP_DBL *, + QMF_DOMAIN_TIMESLOTS_32 + QMF_DOMAIN_OV_TIMESLOTS_32, ((8) + (1))) + +/*! Pointer to imaginary qmf data for each time slot.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(QmfSlotsImag16, FIXP_DBL *, + QMF_DOMAIN_TIMESLOTS_16 + QMF_DOMAIN_OV_TIMESLOTS_16, ((8) + (1))) + +/*! Pointer to imaginary qmf data for each time slot.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(QmfSlotsImag32, FIXP_DBL *, + QMF_DOMAIN_TIMESLOTS_32 + QMF_DOMAIN_OV_TIMESLOTS_32, ((8) + (1))) + +/*! QMF overlap buffer.
+ Dimension: #((8) + (1)) */ +C_AALLOC_MEM2(QmfOverlapBuffer16, FIXP_DBL, + 2 * QMF_DOMAIN_OV_TIMESLOTS_16 * QMF_DOMAIN_MAX_QMF_PROC_BANDS, + ((8) + (1))) + +/*! QMF overlap buffer.
+ Dimension: #((8) + (1)) */ +C_AALLOC_MEM2(QmfOverlapBuffer32, FIXP_DBL, + 2 * QMF_DOMAIN_OV_TIMESLOTS_32 * QMF_DOMAIN_MAX_QMF_PROC_BANDS, + ((8) + (1))) + +static int FDK_QmfDomain_FreePersistentMemory(HANDLE_FDK_QMF_DOMAIN qd) { + int err = 0; + int ch; + + for (ch = 0; ch < ((8) + (1)); ch++) { + if (qd->QmfDomainIn[ch].pAnaQmfStates) { + if (qd->globalConf.nBandsAnalysis == QMF_DOMAIN_ANALYSIS_QMF_BANDS_16) { + FreeAnaQmfStates16(&qd->QmfDomainIn[ch].pAnaQmfStates); + } else if (qd->globalConf.nBandsAnalysis == + QMF_DOMAIN_ANALYSIS_QMF_BANDS_24) { + FreeAnaQmfStates24(&qd->QmfDomainIn[ch].pAnaQmfStates); + } else if (qd->globalConf.nBandsAnalysis == + QMF_DOMAIN_ANALYSIS_QMF_BANDS_32) { + FreeAnaQmfStates32(&qd->QmfDomainIn[ch].pAnaQmfStates); + } else { + FreeAnaQmfStates(&qd->QmfDomainIn[ch].pAnaQmfStates); + } + } + + if (qd->QmfDomainIn[ch].pOverlapBuffer) { + if (qd->globalConf.nQmfOvTimeSlots == QMF_DOMAIN_OV_TIMESLOTS_16) { + FreeQmfOverlapBuffer16(&qd->QmfDomainIn[ch].pOverlapBuffer); + } else if (qd->globalConf.nQmfOvTimeSlots == QMF_DOMAIN_OV_TIMESLOTS_32) { + FreeQmfOverlapBuffer32(&qd->QmfDomainIn[ch].pOverlapBuffer); + } else { + FreeQmfOverlapBuffer(&qd->QmfDomainIn[ch].pOverlapBuffer); + } + } + + if (qd->QmfDomainIn[ch].hQmfSlotsReal) { + if (qd->globalConf.nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_16) { + FreeQmfSlotsReal16(&qd->QmfDomainIn[ch].hQmfSlotsReal); + } else if (qd->globalConf.nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_32) { + FreeQmfSlotsReal32(&qd->QmfDomainIn[ch].hQmfSlotsReal); + } else { + FreeQmfSlotsReal(&qd->QmfDomainIn[ch].hQmfSlotsReal); + } + } + + if (qd->QmfDomainIn[ch].hQmfSlotsImag) { + if (qd->globalConf.nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_16) { + FreeQmfSlotsImag16(&qd->QmfDomainIn[ch].hQmfSlotsImag); + } + if (qd->globalConf.nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_32) { + FreeQmfSlotsImag32(&qd->QmfDomainIn[ch].hQmfSlotsImag); + } else { + FreeQmfSlotsImag(&qd->QmfDomainIn[ch].hQmfSlotsImag); + } + } + } + + for (ch = 0; ch < ((8) + (1)); ch++) { + if (qd->QmfDomainOut[ch].pSynQmfStates) { + FreeSynQmfStates(&qd->QmfDomainOut[ch].pSynQmfStates); + } + } + + return err; +} + +static int FDK_QmfDomain_AllocatePersistentMemory(HANDLE_FDK_QMF_DOMAIN qd) { + int err = 0; + int ch; + HANDLE_FDK_QMF_DOMAIN_GC gc = &qd->globalConf; + + if ((gc->nInputChannels > ((8) + (1))) || (gc->nOutputChannels > ((8) + (1)))) + return err = 1; + for (ch = 0; ch < gc->nInputChannels; ch++) { + int size; + + size = gc->nBandsAnalysis * 10; + if (size > 0) { + if (gc->nBandsAnalysis == QMF_DOMAIN_ANALYSIS_QMF_BANDS_16) { + if (qd->QmfDomainIn[ch].pAnaQmfStates == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates16(ch))) + goto bail; + } + } else if (gc->nBandsAnalysis == QMF_DOMAIN_ANALYSIS_QMF_BANDS_24) { + if (qd->QmfDomainIn[ch].pAnaQmfStates == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates24(ch))) + goto bail; + } + } else if (gc->nBandsAnalysis == QMF_DOMAIN_ANALYSIS_QMF_BANDS_32) { + if (qd->QmfDomainIn[ch].pAnaQmfStates == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates32(ch))) + goto bail; + } + } else { + if (qd->QmfDomainIn[ch].pAnaQmfStates == NULL) { + if (NULL == (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates(ch))) + goto bail; + } + } + } else { + qd->QmfDomainIn[ch].pAnaQmfStates = NULL; + } + + size = gc->nQmfOvTimeSlots + gc->nQmfTimeSlots; + if (size > 0) { + if (gc->nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_16) { + if (qd->QmfDomainIn[ch].hQmfSlotsReal == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].hQmfSlotsReal = GetQmfSlotsReal16(ch))) + goto bail; + } + if (qd->QmfDomainIn[ch].hQmfSlotsImag == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].hQmfSlotsImag = GetQmfSlotsImag16(ch))) + goto bail; + } + } else if (gc->nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_32) { + if (qd->QmfDomainIn[ch].hQmfSlotsReal == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].hQmfSlotsReal = GetQmfSlotsReal32(ch))) + goto bail; + } + if (qd->QmfDomainIn[ch].hQmfSlotsImag == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].hQmfSlotsImag = GetQmfSlotsImag32(ch))) + goto bail; + } + } else { + if (qd->QmfDomainIn[ch].hQmfSlotsReal == NULL) { + if (NULL == (qd->QmfDomainIn[ch].hQmfSlotsReal = GetQmfSlotsReal(ch))) + goto bail; + } + if (qd->QmfDomainIn[ch].hQmfSlotsImag == NULL) { + if (NULL == (qd->QmfDomainIn[ch].hQmfSlotsImag = GetQmfSlotsImag(ch))) + goto bail; + } + } + } else { + qd->QmfDomainIn[ch].hQmfSlotsReal = NULL; + qd->QmfDomainIn[ch].hQmfSlotsImag = NULL; + } + + size = gc->nQmfOvTimeSlots * gc->nQmfProcBands * CMPLX_MOD; + if (size > 0) { + if (gc->nQmfOvTimeSlots == QMF_DOMAIN_OV_TIMESLOTS_16) { + if (qd->QmfDomainIn[ch].pOverlapBuffer == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].pOverlapBuffer = GetQmfOverlapBuffer16(ch))) + goto bail; + } + } else if (gc->nQmfOvTimeSlots == QMF_DOMAIN_OV_TIMESLOTS_32) { + if (qd->QmfDomainIn[ch].pOverlapBuffer == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].pOverlapBuffer = GetQmfOverlapBuffer32(ch))) + goto bail; + } + } else { + if (qd->QmfDomainIn[ch].pOverlapBuffer == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].pOverlapBuffer = GetQmfOverlapBuffer(ch))) + goto bail; + } + } + } else { + qd->QmfDomainIn[ch].pOverlapBuffer = NULL; + } + } + + for (ch = 0; ch < gc->nOutputChannels; ch++) { + int size = gc->nBandsSynthesis * 9; + if (size > 0) { + if (qd->QmfDomainOut[ch].pSynQmfStates == NULL) { + if (NULL == (qd->QmfDomainOut[ch].pSynQmfStates = GetSynQmfStates(ch))) + goto bail; + } + } else { + qd->QmfDomainOut[ch].pSynQmfStates = NULL; + } + } + + return err; + +bail: + FDK_QmfDomain_FreePersistentMemory(qd); + return -1; +} + +QMF_DOMAIN_ERROR FDK_QmfDomain_ClearPersistentMemory( + HANDLE_FDK_QMF_DOMAIN hqd) { + QMF_DOMAIN_ERROR err = QMF_DOMAIN_OK; + int ch, size; + if (hqd) { + HANDLE_FDK_QMF_DOMAIN_GC gc = &hqd->globalConf; + + size = gc->nQmfOvTimeSlots * gc->nQmfProcBands * CMPLX_MOD; + for (ch = 0; ch < gc->nInputChannels; ch++) { + if (hqd->QmfDomainIn[ch].pOverlapBuffer) { + FDKmemclear(hqd->QmfDomainIn[ch].pOverlapBuffer, + size * sizeof(FIXP_DBL)); + } + } + if (FDK_QmfDomain_InitFilterBank(hqd, 0)) { + err = QMF_DOMAIN_INIT_ERROR; + } + } else { + err = QMF_DOMAIN_INIT_ERROR; + } + return err; +} + +/* + FDK_getWorkBuffer + + Parameters: + + pWorkBuffer i: array of pointers which point to different workbuffer + sections workBufferOffset i: offset in the workbuffer to the requested + memory memSize i: size of requested memory + + Function: + + The functions returns the address to the requested memory in the workbuffer. + + The overall workbuffer is divided into several sections. There are + QMF_MAX_WB_SECTIONS sections of size QMF_WB_SECTION_SIZE. The function + selects the workbuffer section with the help of the workBufferOffset and than + it verifies whether the requested amount of memory fits into the selected + workbuffer section. + + Returns: + + address to workbuffer +*/ +static FIXP_DBL *FDK_getWorkBuffer(FIXP_DBL **pWorkBuffer, + USHORT workBufferOffset, + USHORT workBufferSectSize, USHORT memSize) { + int idx1; + int idx2; + FIXP_DBL *pwb; + + /* a section must be a multiple of the number of processing bands (currently + * always 64) */ + FDK_ASSERT((workBufferSectSize % 64) == 0); + + /* calculate offset within the section */ + idx2 = workBufferOffset % workBufferSectSize; + /* calculate section number */ + idx1 = (workBufferOffset - idx2) / workBufferSectSize; + /* maximum sectionnumber is QMF_MAX_WB_SECTIONS */ + FDK_ASSERT(idx1 < QMF_MAX_WB_SECTIONS); + + /* check, whether workbuffer is available */ + FDK_ASSERT(pWorkBuffer[idx1] != NULL); + + /* check, whether buffer fits into selected section */ + FDK_ASSERT((idx2 + memSize) <= workBufferSectSize); + + /* get requested address to workbuffer */ + pwb = &pWorkBuffer[idx1][idx2]; + + return pwb; +} + +static int FDK_QmfDomain_FeedWorkBuffer(HANDLE_FDK_QMF_DOMAIN qd, int ch, + FIXP_DBL **pWorkBuffer, + USHORT workBufferOffset, + USHORT workBufferSectSize, int size) { + int err = 0; + int mem_needed; + + mem_needed = qd->QmfDomainIn[ch].workBuf_nBands * + qd->QmfDomainIn[ch].workBuf_nTimeSlots * CMPLX_MOD; + if (mem_needed > size) { + return (err = 1); + } + qd->QmfDomainIn[ch].pWorkBuffer = pWorkBuffer; + qd->QmfDomainIn[ch].workBufferOffset = workBufferOffset; + qd->QmfDomainIn[ch].workBufferSectSize = workBufferSectSize; + + return err; +} + +int FDK_QmfDomain_IsInitialized(const HANDLE_FDK_QMF_DOMAIN qd) { + FDK_ASSERT(qd != NULL); + return ((qd->QmfDomainIn[0].pAnaQmfStates == NULL) && + (qd->QmfDomainOut[0].pSynQmfStates == NULL)) + ? 0 + : 1; +} + +int FDK_QmfDomain_InitFilterBank(HANDLE_FDK_QMF_DOMAIN qd, UINT extra_flags) { + FDK_ASSERT(qd != NULL); + int err = 0; + int ch, ts; + HANDLE_FDK_QMF_DOMAIN_GC gc = &qd->globalConf; + int noCols = gc->nQmfTimeSlots; + int lsb = gc->nBandsAnalysis; + int usb = fMin((INT)gc->nBandsSynthesis, 64); + int nProcBands = gc->nQmfProcBands; + FDK_ASSERT(nProcBands % ALIGNMENT_DEFAULT == 0); + + if (extra_flags & QMF_FLAG_MPSLDFB) { + gc->flags &= ~QMF_FLAG_CLDFB; + gc->flags |= QMF_FLAG_MPSLDFB; + } + for (ch = 0; ch < gc->nInputChannels; ch++) { + /* distribute memory to slots array */ + FIXP_DBL *ptrOv = + qd->QmfDomainIn[ch].pOverlapBuffer; /* persistent memory for overlap */ + if ((ptrOv == NULL) && (gc->nQmfOvTimeSlots != 0)) { + err = 1; + return err; + } + /* This assumes the workbuffer defined for ch0 is the big one being used to + * hold one full frame of QMF data. */ + FIXP_DBL **ptr = + qd->QmfDomainIn[fMin(ch, fMax((INT)gc->nQmfProcChannels - 1, 0))] + .pWorkBuffer; /* non-persistent workbuffer */ + USHORT workBufferOffset = + qd->QmfDomainIn[fMin(ch, fMax((INT)gc->nQmfProcChannels - 1, 0))] + .workBufferOffset; + USHORT workBufferSectSize = + qd->QmfDomainIn[fMin(ch, fMax((INT)gc->nQmfProcChannels - 1, 0))] + .workBufferSectSize; + + if ((ptr == NULL) && (gc->nQmfTimeSlots != 0)) { + err = 1; + return err; + } + + qd->QmfDomainIn[ch].pGlobalConf = gc; + for (ts = 0; ts < gc->nQmfOvTimeSlots; ts++) { + qd->QmfDomainIn[ch].hQmfSlotsReal[ts] = ptrOv; + ptrOv += nProcBands; + qd->QmfDomainIn[ch].hQmfSlotsImag[ts] = ptrOv; + ptrOv += nProcBands; + } + for (; ts < (gc->nQmfOvTimeSlots + gc->nQmfTimeSlots); ts++) { + qd->QmfDomainIn[ch].hQmfSlotsReal[ts] = FDK_getWorkBuffer( + ptr, workBufferOffset, workBufferSectSize, nProcBands); + workBufferOffset += nProcBands; + qd->QmfDomainIn[ch].hQmfSlotsImag[ts] = FDK_getWorkBuffer( + ptr, workBufferOffset, workBufferSectSize, nProcBands); + workBufferOffset += nProcBands; + } + err |= qmfInitAnalysisFilterBank( + &qd->QmfDomainIn[ch].fb, qd->QmfDomainIn[ch].pAnaQmfStates, noCols, + (qd->QmfDomainIn[ch].fb.lsb == 0) ? lsb : qd->QmfDomainIn[ch].fb.lsb, + (qd->QmfDomainIn[ch].fb.usb == 0) ? usb : qd->QmfDomainIn[ch].fb.usb, + gc->nBandsAnalysis, gc->flags | extra_flags); + } + + for (ch = 0; ch < gc->nOutputChannels; ch++) { + FIXP_DBL outGain_m = qd->QmfDomainOut[ch].fb.outGain_m; + int outGain_e = qd->QmfDomainOut[ch].fb.outGain_e; + int outScale = qmfGetOutScalefactor(&qd->QmfDomainOut[ch].fb); + err |= qmfInitSynthesisFilterBank( + &qd->QmfDomainOut[ch].fb, qd->QmfDomainOut[ch].pSynQmfStates, noCols, + (qd->QmfDomainOut[ch].fb.lsb == 0) ? lsb : qd->QmfDomainOut[ch].fb.lsb, + (qd->QmfDomainOut[ch].fb.usb == 0) ? usb : qd->QmfDomainOut[ch].fb.usb, + gc->nBandsSynthesis, gc->flags | extra_flags); + if (outGain_m != (FIXP_DBL)0) { + qmfChangeOutGain(&qd->QmfDomainOut[ch].fb, outGain_m, outGain_e); + } + if (outScale) { + qmfChangeOutScalefactor(&qd->QmfDomainOut[ch].fb, outScale); + } + } + + return err; +} + +void FDK_QmfDomain_SaveOverlap(HANDLE_FDK_QMF_DOMAIN_IN qd_ch, int offset) { + FDK_ASSERT(qd_ch != NULL); + int ts; + HANDLE_FDK_QMF_DOMAIN_GC gc = qd_ch->pGlobalConf; + int ovSlots = gc->nQmfOvTimeSlots; + int nCols = gc->nQmfTimeSlots; + int nProcBands = gc->nQmfProcBands; + FIXP_DBL **qmfReal = qd_ch->hQmfSlotsReal; + FIXP_DBL **qmfImag = qd_ch->hQmfSlotsImag; + QMF_SCALE_FACTOR *pScaling = &qd_ch->scaling; + + /* for high part it would be enough to save only used part of overlap area */ + if (qmfImag != NULL) { + for (ts = offset; ts < ovSlots; ts++) { + FDKmemcpy(qmfReal[ts], qmfReal[nCols + ts], + sizeof(FIXP_DBL) * nProcBands); + FDKmemcpy(qmfImag[ts], qmfImag[nCols + ts], + sizeof(FIXP_DBL) * nProcBands); + } + } else { + for (ts = 0; ts < ovSlots; ts++) { + FDKmemcpy(qmfReal[ts], qmfReal[nCols + ts], + sizeof(FIXP_DBL) * nProcBands); + } + } + pScaling->ov_lb_scale = pScaling->lb_scale; +} + + /* Convert headroom bits to exponent */ +#define SCALE2EXP(s) (15 - (s)) +#define EXP2SCALE(e) (15 - (e)) + +void FDK_QmfDomain_GetSlot(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, const int ts, + const int start_band, const int stop_band, + FIXP_DBL *pQmfOutReal, FIXP_DBL *pQmfOutImag, + const int exp_out) { + FDK_ASSERT(qd_ch != NULL); + FDK_ASSERT(pQmfOutReal != NULL); + HANDLE_FDK_QMF_DOMAIN_GC gc = qd_ch->pGlobalConf; + const FIXP_DBL *real = qd_ch->hQmfSlotsReal[ts]; + const FIXP_DBL *imag = qd_ch->hQmfSlotsImag[ts]; + const int ovSlots = gc->nQmfOvTimeSlots; + const int exp_lb = SCALE2EXP((ts < ovSlots) ? qd_ch->scaling.ov_lb_scale + : qd_ch->scaling.lb_scale); + const int exp_hb = SCALE2EXP(qd_ch->scaling.hb_scale); + const int lsb = qd_ch->fb.lsb; + const int usb = qd_ch->fb.usb; + int b = start_band; + int lb_sf, hb_sf; + + int target_exp = + ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + qd_ch->fb.filterScale; + + FDK_ASSERT(ts < (gc->nQmfTimeSlots + gc->nQmfOvTimeSlots)); + FDK_ASSERT(start_band >= 0); + FDK_ASSERT(stop_band <= gc->nQmfProcBands); + + if (qd_ch->fb.no_channels == 24) { + target_exp -= 1; + } + + /* Limit scaling factors to maximum negative value to avoid faulty behaviour + due to right-shifts. Corresponding asserts were observed during robustness + testing. + */ + lb_sf = fMax(exp_lb - target_exp - exp_out, -31); + FDK_ASSERT(lb_sf < 32); + hb_sf = fMax(exp_hb - target_exp - exp_out, -31); + FDK_ASSERT(hb_sf < 32); + + if (pQmfOutImag == NULL) { + for (; b < fMin(lsb, stop_band); b++) { + pQmfOutReal[b] = scaleValueSaturate(real[b], lb_sf); + } + for (; b < fMin(usb, stop_band); b++) { + pQmfOutReal[b] = scaleValueSaturate(real[b], hb_sf); + } + for (; b < stop_band; b++) { + pQmfOutReal[b] = (FIXP_DBL)0; + } + } else { + FDK_ASSERT(imag != NULL); + for (; b < fMin(lsb, stop_band); b++) { + pQmfOutReal[b] = scaleValueSaturate(real[b], lb_sf); + pQmfOutImag[b] = scaleValueSaturate(imag[b], lb_sf); + } + for (; b < fMin(usb, stop_band); b++) { + pQmfOutReal[b] = scaleValueSaturate(real[b], hb_sf); + pQmfOutImag[b] = scaleValueSaturate(imag[b], hb_sf); + } + for (; b < stop_band; b++) { + pQmfOutReal[b] = (FIXP_DBL)0; + pQmfOutImag[b] = (FIXP_DBL)0; + } + } +} + +void FDK_QmfDomain_GetWorkBuffer(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, + const int ts, FIXP_DBL **ppQmfReal, + FIXP_DBL **ppQmfImag) { + FDK_ASSERT(qd_ch != NULL); + FDK_ASSERT(ppQmfReal != NULL); + FDK_ASSERT(ppQmfImag != NULL); + const int bands = qd_ch->workBuf_nBands; + FIXP_DBL **pWorkBuf = qd_ch->pWorkBuffer; + USHORT workBufferOffset = qd_ch->workBufferOffset; + USHORT workBufferSectSize = qd_ch->workBufferSectSize; + + FDK_ASSERT(bands > 0); + FDK_ASSERT(ts < qd_ch->workBuf_nTimeSlots); + + *ppQmfReal = FDK_getWorkBuffer( + pWorkBuf, workBufferOffset + (ts * CMPLX_MOD + 0) * bands, + workBufferSectSize, bands); + *ppQmfImag = FDK_getWorkBuffer( + pWorkBuf, workBufferOffset + (ts * CMPLX_MOD + 1) * bands, + workBufferSectSize, bands); +} + +void FDK_QmfDomain_WorkBuffer2ProcChannel( + const HANDLE_FDK_QMF_DOMAIN_IN qd_ch) { + FDK_ASSERT(qd_ch != NULL); + HANDLE_FDK_QMF_DOMAIN_GC gc = qd_ch->pGlobalConf; + FIXP_DBL **pWorkBuf = qd_ch->pWorkBuffer; + USHORT workBufferOffset = qd_ch->workBufferOffset; + USHORT workBufferSectSize = qd_ch->workBufferSectSize; + + if (FDK_getWorkBuffer(pWorkBuf, workBufferOffset, workBufferSectSize, + qd_ch->workBuf_nBands) == + qd_ch->hQmfSlotsReal[gc->nQmfOvTimeSlots]) { + /* work buffer is part of processing channel => nothing to do */ + return; + } else { + /* copy parked new QMF data to processing channel */ + const int bands = qd_ch->workBuf_nBands; + const int slots = qd_ch->workBuf_nTimeSlots; + int ts; + for (ts = 0; ts < slots; ts++) { + FDKmemcpy(qd_ch->hQmfSlotsReal[gc->nQmfOvTimeSlots + ts], + FDK_getWorkBuffer(pWorkBuf, workBufferOffset, + workBufferSectSize, bands), + sizeof(FIXP_DBL) * bands); // parkBuf_to_anaMatrix + workBufferOffset += bands; + FDKmemcpy(qd_ch->hQmfSlotsImag[gc->nQmfOvTimeSlots + ts], + FDK_getWorkBuffer(pWorkBuf, workBufferOffset, + workBufferSectSize, bands), + sizeof(FIXP_DBL) * bands); + workBufferOffset += bands; + } + } +} + +void FDK_QmfDomain_QmfData2HBE(HANDLE_FDK_QMF_DOMAIN_IN qd_ch, + FIXP_DBL **ppQmfReal, FIXP_DBL **ppQmfImag) { + FDK_ASSERT(qd_ch != NULL); + FDK_ASSERT(ppQmfReal != NULL); + FDK_ASSERT(ppQmfImag != NULL); + HANDLE_FDK_QMF_DOMAIN_GC gc = qd_ch->pGlobalConf; + FIXP_DBL **pWorkBuf = qd_ch->pWorkBuffer; + USHORT workBufferOffset = qd_ch->workBufferOffset; + USHORT workBufferSectSize = qd_ch->workBufferSectSize; + + if (FDK_getWorkBuffer(pWorkBuf, workBufferOffset, workBufferSectSize, + qd_ch->workBuf_nBands) == + qd_ch->hQmfSlotsReal[gc->nQmfOvTimeSlots]) { // left channel (anaMatrix) + int ts; + const int bands = gc->nBandsAnalysis; + const int slots = qd_ch->workBuf_nTimeSlots; + FDK_ASSERT(bands <= 64); + for (ts = 0; ts < slots; ts++) { + /* copy current data of processing channel */ + FIXP_DBL tmp[64]; // one slot + /* real */ + FDKmemcpy(tmp, qd_ch->hQmfSlotsReal[gc->nQmfOvTimeSlots + ts], + sizeof(FIXP_DBL) * bands); // anaMatrix_to_tmp + FDKmemcpy(qd_ch->hQmfSlotsReal[gc->nQmfOvTimeSlots + ts], ppQmfReal[ts], + sizeof(FIXP_DBL) * bands); // HBE_to_anaMatrix + FDKmemcpy(ppQmfReal[ts], tmp, sizeof(FIXP_DBL) * bands); // tmp_to_HBE + /* imag */ + FDKmemcpy(tmp, qd_ch->hQmfSlotsImag[gc->nQmfOvTimeSlots + ts], + sizeof(FIXP_DBL) * bands); + FDKmemcpy(qd_ch->hQmfSlotsImag[gc->nQmfOvTimeSlots + ts], ppQmfImag[ts], + sizeof(FIXP_DBL) * bands); + FDKmemcpy(ppQmfImag[ts], tmp, sizeof(FIXP_DBL) * bands); + } + } else { // right channel (parkBuf) + const int bands = qd_ch->workBuf_nBands; + const int slots = qd_ch->workBuf_nTimeSlots; + int ts; + FDK_ASSERT(qd_ch->workBuf_nBands == gc->nBandsAnalysis); + for (ts = 0; ts < slots; ts++) { + /* copy HBE QMF data buffer to processing channel */ + FDKmemcpy(qd_ch->hQmfSlotsReal[gc->nQmfOvTimeSlots + ts], ppQmfReal[ts], + sizeof(FIXP_DBL) * bands); // HBE_to_anaMatrix + FDKmemcpy(qd_ch->hQmfSlotsImag[gc->nQmfOvTimeSlots + ts], ppQmfImag[ts], + sizeof(FIXP_DBL) * bands); + /* copy parked new QMF data to HBE QMF data buffer */ + FDKmemcpy(ppQmfReal[ts], + FDK_getWorkBuffer(pWorkBuf, workBufferOffset, + workBufferSectSize, bands), + sizeof(FIXP_DBL) * bands); // parkBuf_to_HBE + workBufferOffset += bands; + FDKmemcpy(ppQmfImag[ts], + FDK_getWorkBuffer(pWorkBuf, workBufferOffset, + workBufferSectSize, bands), + sizeof(FIXP_DBL) * bands); + workBufferOffset += bands; + } + } +} + +void FDK_QmfDomain_ClearRequested(HANDLE_FDK_QMF_DOMAIN_GC hgc) { + hgc->qmfDomainExplicitConfig = 0; + hgc->flags_requested = 0; + hgc->nInputChannels_requested = 0; + hgc->nOutputChannels_requested = 0; + hgc->parkChannel_requested = 0; + hgc->nBandsAnalysis_requested = 0; + hgc->nBandsSynthesis_requested = 0; + hgc->nQmfTimeSlots_requested = 0; + hgc->nQmfOvTimeSlots_requested = 0; + hgc->nQmfProcBands_requested = 0; + hgc->nQmfProcChannels_requested = 0; +} + +static void FDK_QmfDomain_ClearConfigured(HANDLE_FDK_QMF_DOMAIN_GC hgc) { + hgc->flags = 0; + hgc->nInputChannels = 0; + hgc->nOutputChannels = 0; + hgc->parkChannel = 0; + hgc->nBandsAnalysis = 0; + hgc->nBandsSynthesis = 0; + hgc->nQmfTimeSlots = 0; + hgc->nQmfOvTimeSlots = 0; + hgc->nQmfProcBands = 0; + hgc->nQmfProcChannels = 0; +} + +static void FDK_QmfDomain_ClearFilterBank(HANDLE_FDK_QMF_DOMAIN hqd) { + int ch; + + for (ch = 0; ch < ((8) + (1)); ch++) { + FDKmemclear(&hqd->QmfDomainIn[ch].fb, sizeof(hqd->QmfDomainIn[ch].fb)); + } + + for (ch = 0; ch < ((8) + (1)); ch++) { + FDKmemclear(&hqd->QmfDomainOut[ch].fb, sizeof(hqd->QmfDomainIn[ch].fb)); + } +} + +QMF_DOMAIN_ERROR FDK_QmfDomain_Configure(HANDLE_FDK_QMF_DOMAIN hqd) { + FDK_ASSERT(hqd != NULL); + QMF_DOMAIN_ERROR err = QMF_DOMAIN_OK; + int i, size_main, size, size_temp = 0; + + HANDLE_FDK_QMF_DOMAIN_GC hgc = &hqd->globalConf; + FIXP_DBL **pWorkBuffer = hgc->pWorkBuffer; + + int hasChanged = 0; + + if ((hgc->nQmfProcChannels_requested > 0) && + (hgc->nQmfProcBands_requested != 64)) { + return QMF_DOMAIN_INIT_ERROR; + } + if (hgc->nBandsAnalysis_requested > hgc->nQmfProcBands_requested) { + /* In general the output of the qmf analysis is written to QMF memory slots + which size is defined by nQmfProcBands. nBandsSynthesis may be larger + than nQmfProcBands. This is e.g. the case if the QMF based resampler is + used. + */ + return QMF_DOMAIN_INIT_ERROR; + } + + /* 1. adjust change of processing channels by comparison of current and + * requested parameters */ + if ((hgc->nQmfProcChannels != hgc->nQmfProcChannels_requested) || + (hgc->nQmfProcBands != hgc->nQmfProcBands_requested) || + (hgc->nQmfTimeSlots != hgc->nQmfTimeSlots_requested)) { + for (i = 0; i < hgc->nQmfProcChannels_requested; i++) { + hqd->QmfDomainIn[i].workBuf_nBands = hgc->nQmfProcBands_requested; + hgc->nQmfProcBands = hgc->nQmfProcBands_requested; + + hqd->QmfDomainIn[i].workBuf_nTimeSlots = hgc->nQmfTimeSlots_requested; + } + + hgc->nQmfProcChannels = + hgc->nQmfProcChannels_requested; /* keep highest value encountered so + far as allocated */ + + hasChanged = 1; + } + + /* 2. reallocate persistent memory if necessary (analysis state-buffers, + * timeslot-pointer-array, overlap-buffers, synthesis state-buffers) */ + if ((hgc->nInputChannels != hgc->nInputChannels_requested) || + (hgc->nBandsAnalysis != hgc->nBandsAnalysis_requested) || + (hgc->nQmfTimeSlots != hgc->nQmfTimeSlots_requested) || + (hgc->nQmfOvTimeSlots != hgc->nQmfOvTimeSlots_requested) || + (hgc->nOutputChannels != hgc->nOutputChannels_requested) || + (hgc->nBandsSynthesis != hgc->nBandsSynthesis_requested) || + (hgc->parkChannel != hgc->parkChannel_requested)) { + hgc->nInputChannels = hgc->nInputChannels_requested; + hgc->nBandsAnalysis = hgc->nBandsAnalysis_requested; + hgc->nQmfTimeSlots = hgc->nQmfTimeSlots_requested; + hgc->nQmfOvTimeSlots = hgc->nQmfOvTimeSlots_requested; + hgc->nOutputChannels = hgc->nOutputChannels_requested; + hgc->nBandsSynthesis = hgc->nBandsSynthesis_requested; + hgc->parkChannel = hgc->parkChannel_requested; + + if (FDK_QmfDomain_AllocatePersistentMemory(hqd)) { + err = QMF_DOMAIN_OUT_OF_MEMORY; + goto bail; + } + + /* 3. set request-flag for downsampled SBR */ + if ((hgc->nBandsAnalysis == 32) && (hgc->nBandsSynthesis == 32) && + !(hgc->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) { + hgc->flags_requested |= QMF_FLAG_DOWNSAMPLED; + } + + hasChanged = 1; + } + + /* 4. initialize tables and buffer for QMF-resampler */ + + /* 5. set requested flags */ + if (hgc->flags != hgc->flags_requested) { + if ((hgc->flags_requested & QMF_FLAG_MPSLDFB) && + (hgc->flags_requested & QMF_FLAG_CLDFB)) { + hgc->flags_requested &= ~QMF_FLAG_CLDFB; + } + hgc->flags = hgc->flags_requested; + hasChanged = 1; + } + + if (hasChanged) { + /* 6. recalculate and check size of required workbuffer-space */ + + if (hgc->parkChannel && (hqd->globalConf.nQmfProcChannels == 1)) { + /* configure temp QMF buffer for parking right channel MPS212 output, + * (USAC stereoConfigIndex 3 only) */ + hqd->QmfDomainIn[1].workBuf_nBands = hqd->globalConf.nBandsAnalysis; + hqd->QmfDomainIn[1].workBuf_nTimeSlots = hqd->globalConf.nQmfTimeSlots; + size_temp = hqd->QmfDomainIn[1].workBuf_nBands * + hqd->QmfDomainIn[1].workBuf_nTimeSlots * CMPLX_MOD; + } + + size_main = hqd->QmfDomainIn[0].workBuf_nBands * + hqd->QmfDomainIn[0].workBuf_nTimeSlots * CMPLX_MOD; + + size = size_main * hgc->nQmfProcChannels + size_temp; + + if (size > (QMF_MAX_WB_SECTIONS * QMF_WB_SECTION_SIZE)) { + err = QMF_DOMAIN_OUT_OF_MEMORY; + goto bail; + } + + /* 7. allocate additional workbuffer if necessary */ + if ((size > 0 /* *QMF_WB_SECTION_SIZE */) && (pWorkBuffer[0] == NULL)) { + /* get work buffer of size QMF_WB_SECTION_SIZE */ + pWorkBuffer[0] = GetQmfWorkBufferCore6(); + } + + if ((size > 1 * QMF_WB_SECTION_SIZE) && (pWorkBuffer[1] == NULL)) { + /* get work buffer of size QMF_WB_SECTION_SIZE */ + pWorkBuffer[1] = GetQmfWorkBufferCore1(); + } + + if ((size > 2 * QMF_WB_SECTION_SIZE) && (pWorkBuffer[2] == NULL)) { + /* get work buffer of size QMF_WB_SECTION_SIZE */ + pWorkBuffer[2] = GetQmfWorkBufferCore3(); + } + + if ((size > 3 * QMF_WB_SECTION_SIZE) && (pWorkBuffer[3] == NULL)) { + /* get work buffer of size QMF_WB_SECTION_SIZE */ + pWorkBuffer[3] = GetQmfWorkBufferCore4(); + } + + if ((size > 4 * QMF_WB_SECTION_SIZE) && (pWorkBuffer[4] == NULL)) { + /* get work buffer of size QMF_WB_SECTION_SIZE */ + pWorkBuffer[4] = GetQmfWorkBufferCore7(); + } + + /* 8. distribute workbuffer over processing channels */ + for (i = 0; i < hgc->nQmfProcChannels; i++) { + FDK_QmfDomain_FeedWorkBuffer(hqd, i, pWorkBuffer, size_main * i, + QMF_WB_SECTION_SIZE, size_main); + } + if (hgc->parkChannel) { + for (; i < hgc->nInputChannels; i++) { + FDK_QmfDomain_FeedWorkBuffer(hqd, 1, pWorkBuffer, + size_main * hgc->nQmfProcChannels, + QMF_WB_SECTION_SIZE, size_temp); + } + } + + /* 9. (re-)init filterbank */ + for (i = 0; i < hgc->nOutputChannels; i++) { + if ((hqd->QmfDomainOut[i].fb.lsb == 0) && + (hqd->QmfDomainOut[i].fb.usb == 0)) { + /* Although lsb and usb are set in the SBR module, they are initialized + * at this point due to the case of using MPS without SBR. */ + hqd->QmfDomainOut[i].fb.lsb = hgc->nBandsAnalysis_requested; + hqd->QmfDomainOut[i].fb.usb = + fMin((INT)hgc->nBandsSynthesis_requested, 64); + } + } + if (FDK_QmfDomain_InitFilterBank(hqd, 0)) { + err = QMF_DOMAIN_INIT_ERROR; + } + } + +bail: + if (err) { + FDK_QmfDomain_FreeMem(hqd); + } + return err; +} + +static void FDK_QmfDomain_FreeWorkBuffer(HANDLE_FDK_QMF_DOMAIN hqd) { + FIXP_DBL **pWorkBuffer = hqd->globalConf.pWorkBuffer; + + if (pWorkBuffer[0]) FreeQmfWorkBufferCore6(&pWorkBuffer[0]); + if (pWorkBuffer[1]) FreeQmfWorkBufferCore1(&pWorkBuffer[1]); + if (pWorkBuffer[2]) FreeQmfWorkBufferCore3(&pWorkBuffer[2]); + if (pWorkBuffer[3]) FreeQmfWorkBufferCore4(&pWorkBuffer[3]); + if (pWorkBuffer[4]) FreeQmfWorkBufferCore7(&pWorkBuffer[4]); +} + +void FDK_QmfDomain_FreeMem(HANDLE_FDK_QMF_DOMAIN hqd) { + FDK_QmfDomain_FreeWorkBuffer(hqd); + + FDK_QmfDomain_FreePersistentMemory(hqd); + + FDK_QmfDomain_ClearFilterBank(hqd); + + FDK_QmfDomain_ClearConfigured(&hqd->globalConf); + + FDK_QmfDomain_ClearRequested(&hqd->globalConf); +} + +void FDK_QmfDomain_Close(HANDLE_FDK_QMF_DOMAIN hqd) { + FDK_QmfDomain_FreeWorkBuffer(hqd); + + FDK_QmfDomain_FreePersistentMemory(hqd); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_tools_rom.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_tools_rom.cpp new file mode 100644 index 0000000000000..009587817251d --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_tools_rom.cpp @@ -0,0 +1,7271 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Oliver Moser + + Description: ROM tables used by FDK tools + +*******************************************************************************/ + +#include "FDK_tools_rom.h" + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STP SineTable80[] = { + STCP(0x7fffffff, 0x00000000), STCP(0x7ff9af04, 0x02835b5a), + STCP(0x7fe6bcb0, 0x05067734), STCP(0x7fc72ae2, 0x07891418), + STCP(0x7f9afcb9, 0x0a0af299), STCP(0x7f62368f, 0x0c8bd35e), + STCP(0x7f1cde01, 0x0f0b7727), STCP(0x7ecaf9e5, 0x11899ed3), + STCP(0x7e6c9251, 0x14060b68), STCP(0x7e01b096, 0x16807e15), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d06aa16, 0x1b6e7b7a), + STCP(0x7c769e18, 0x1de189a6), STCP(0x7bda497d, 0x2051a4dd), + STCP(0x7b31bbb2, 0x22be8f87), STCP(0x7a7d055b, 0x25280c5e), + STCP(0x79bc384d, 0x278dde6e), STCP(0x78ef678f, 0x29efc925), + STCP(0x7816a759, 0x2c4d9050), STCP(0x77320d0d, 0x2ea6f827), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x7545a5a0, 0x334bbcde), + STCP(0x743e0918, 0x3596a46c), STCP(0x732af3a7, 0x37dc420c), + STCP(0x720c8075, 0x3a1c5c57), STCP(0x70e2cbc6, 0x3c56ba70), + STCP(0x6fadf2fc, 0x3e8b240e), STCP(0x6e6e1492, 0x40b9617d), + STCP(0x6d23501b, 0x42e13ba4), STCP(0x6bcdc639, 0x45027c0c), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6902ea1d, 0x4930590f), + STCP(0x678dde6e, 0x4b3c8c12), STCP(0x660e9a6a, 0x4d415234), + STCP(0x648543e4, 0x4f3e7875), STCP(0x62f201ac, 0x5133cc94), + STCP(0x6154fb91, 0x53211d18), STCP(0x5fae5a55, 0x55063951), + STCP(0x5dfe47ad, 0x56e2f15d), STCP(0x5c44ee40, 0x58b71632), + STCP(0x5a82799a, 0x5a82799a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STP SineTable384[] = { + STCP(0x7fffffff, 0x00000000), STCP(0x7fffb9d1, 0x00860a79), + STCP(0x7ffee744, 0x010c1460), STCP(0x7ffd885a, 0x01921d20), + STCP(0x7ffb9d15, 0x02182427), STCP(0x7ff92577, 0x029e28e2), + STCP(0x7ff62182, 0x03242abf), STCP(0x7ff2913a, 0x03aa292a), + STCP(0x7fee74a2, 0x0430238f), STCP(0x7fe9cbc0, 0x04b6195d), + STCP(0x7fe49698, 0x053c0a01), STCP(0x7fded530, 0x05c1f4e7), + STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd1adb9, 0x06cdb72f), + STCP(0x7fca47b9, 0x07538d6b), STCP(0x7fc25596, 0x07d95b9e), + STCP(0x7fb9d759, 0x085f2137), STCP(0x7fb0cd0a, 0x08e4dda0), + STCP(0x7fa736b4, 0x096a9049), STCP(0x7f9d1461, 0x09f0389f), + STCP(0x7f92661d, 0x0a75d60e), STCP(0x7f872bf3, 0x0afb6805), + STCP(0x7f7b65ef, 0x0b80edf1), STCP(0x7f6f141f, 0x0c066740), + STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f54cd4f, 0x0d1131ba), + STCP(0x7f46d86c, 0x0d9681c2), STCP(0x7f3857f6, 0x0e1bc2e4), + STCP(0x7f294bfd, 0x0ea0f48c), STCP(0x7f19b491, 0x0f26162a), + STCP(0x7f0991c4, 0x0fab272b), STCP(0x7ef8e3a6, 0x103026fe), + STCP(0x7ee7aa4c, 0x10b5150f), STCP(0x7ed5e5c6, 0x1139f0cf), + STCP(0x7ec3962a, 0x11beb9aa), STCP(0x7eb0bb8a, 0x12436f10), + STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e896595, 0x134c9d34), + STCP(0x7e74ea6a, 0x13d114d0), STCP(0x7e5fe493, 0x145576b1), + STCP(0x7e4a5426, 0x14d9c245), STCP(0x7e34393b, 0x155df6fc), + STCP(0x7e1d93ea, 0x15e21445), STCP(0x7e06644c, 0x1666198d), + STCP(0x7deeaa7a, 0x16ea0646), STCP(0x7dd6668f, 0x176dd9de), + STCP(0x7dbd98a4, 0x17f193c5), STCP(0x7da440d6, 0x1875336a), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d6ff3fe, 0x197c21ad), + STCP(0x7d54ff2e, 0x19ff6f2a), STCP(0x7d3980ec, 0x1a82a026), + STCP(0x7d1d7958, 0x1b05b40f), STCP(0x7d00e88f, 0x1b88aa55), + STCP(0x7ce3ceb2, 0x1c0b826a), STCP(0x7cc62bdf, 0x1c8e3bbe), + STCP(0x7ca80038, 0x1d10d5c2), STCP(0x7c894bde, 0x1d934fe5), + STCP(0x7c6a0ef2, 0x1e15a99a), STCP(0x7c4a4996, 0x1e97e251), + STCP(0x7c29fbee, 0x1f19f97b), STCP(0x7c09261d, 0x1f9bee8a), + STCP(0x7be7c847, 0x201dc0ef), STCP(0x7bc5e290, 0x209f701c), + STCP(0x7ba3751d, 0x2120fb83), STCP(0x7b808015, 0x21a26295), + STCP(0x7b5d039e, 0x2223a4c5), STCP(0x7b38ffde, 0x22a4c185), + STCP(0x7b1474fd, 0x2325b847), STCP(0x7aef6323, 0x23a6887f), + STCP(0x7ac9ca7a, 0x2427319d), STCP(0x7aa3ab29, 0x24a7b317), + STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a55d93a, 0x25a83ce6), + STCP(0x7a2e26f2, 0x26284422), STCP(0x7a05eead, 0x26a82186), + STCP(0x79dd3098, 0x2727d486), STCP(0x79b3ece0, 0x27a75c95), + STCP(0x798a23b1, 0x2826b928), STCP(0x795fd53a, 0x28a5e9b4), + STCP(0x793501a9, 0x2924edac), STCP(0x7909a92d, 0x29a3c485), + STCP(0x78ddcbf5, 0x2a226db5), STCP(0x78b16a32, 0x2aa0e8b0), + STCP(0x78848414, 0x2b1f34eb), STCP(0x785719cc, 0x2b9d51dd), + STCP(0x78292b8d, 0x2c1b3efb), STCP(0x77fab989, 0x2c98fbba), + STCP(0x77cbc3f2, 0x2d168792), STCP(0x779c4afc, 0x2d93e1f8), + STCP(0x776c4edb, 0x2e110a62), STCP(0x773bcfc4, 0x2e8e0048), + STCP(0x770acdec, 0x2f0ac320), STCP(0x76d94989, 0x2f875262), + STCP(0x76a742d1, 0x3003ad85), STCP(0x7674b9fa, 0x307fd401), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x760e22d1, 0x317780e2), + STCP(0x75da14ef, 0x31f30638), STCP(0x75a585cf, 0x326e54c7), + STCP(0x757075ac, 0x32e96c09), STCP(0x753ae4c0, 0x33644b76), + STCP(0x7504d345, 0x33def287), STCP(0x74ce4177, 0x345960b7), + STCP(0x74972f92, 0x34d3957e), STCP(0x745f9dd1, 0x354d9057), + STCP(0x74278c72, 0x35c750bc), STCP(0x73eefbb3, 0x3640d627), + STCP(0x73b5ebd1, 0x36ba2014), STCP(0x737c5d0b, 0x37332dfd), + STCP(0x73424fa0, 0x37abff5d), STCP(0x7307c3d0, 0x382493b0), + STCP(0x72ccb9db, 0x389cea72), STCP(0x72913201, 0x3915031f), + STCP(0x72552c85, 0x398cdd32), STCP(0x7218a9a7, 0x3a04782a), + STCP(0x71dba9ab, 0x3a7bd382), STCP(0x719e2cd2, 0x3af2eeb7), + STCP(0x71603361, 0x3b69c947), STCP(0x7121bd9c, 0x3be062b0), + STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70a35e25, 0x3cccd004), + STCP(0x706374ff, 0x3d42a2ec), STCP(0x7023109a, 0x3db832a6), + STCP(0x6fe2313c, 0x3e2d7eb1), STCP(0x6fa0d72c, 0x3ea2868c), + STCP(0x6f5f02b2, 0x3f1749b8), STCP(0x6f1cb416, 0x3f8bc7b4), + STCP(0x6ed9eba1, 0x40000000), STCP(0x6e96a99d, 0x4073f21d), + STCP(0x6e52ee52, 0x40e79d8c), STCP(0x6e0eba0c, 0x415b01ce), + STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6d84e7b7, 0x4240f2d1), + STCP(0x6d3f4a40, 0x42b37e96), STCP(0x6cf934fc, 0x4325c135), + STCP(0x6cb2a837, 0x4397ba32), STCP(0x6c6ba43e, 0x44096910), + STCP(0x6c242960, 0x447acd50), STCP(0x6bdc37eb, 0x44ebe679), + STCP(0x6b93d02e, 0x455cb40c), STCP(0x6b4af279, 0x45cd358f), + STCP(0x6b019f1a, 0x463d6a87), STCP(0x6ab7d663, 0x46ad5278), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a22e630, 0x478c395a), + STCP(0x69d7bf57, 0x47fb3757), STCP(0x698c246c, 0x4869e665), + STCP(0x694015c3, 0x48d84609), STCP(0x68f393ae, 0x494655cc), + STCP(0x68a69e81, 0x49b41533), STCP(0x68593691, 0x4a2183c8), + STCP(0x680b5c33, 0x4a8ea111), STCP(0x67bd0fbd, 0x4afb6c98), + STCP(0x676e5183, 0x4b67e5e4), STCP(0x671f21dc, 0x4bd40c80), + STCP(0x66cf8120, 0x4c3fdff4), STCP(0x667f6fa5, 0x4cab5fc9), + STCP(0x662eedc3, 0x4d168b8b), STCP(0x65ddfbd3, 0x4d8162c4), + STCP(0x658c9a2d, 0x4debe4fe), STCP(0x653ac92b, 0x4e5611c5), + STCP(0x64e88926, 0x4ebfe8a5), STCP(0x6495da79, 0x4f296928), + STCP(0x6442bd7e, 0x4f9292dc), STCP(0x63ef3290, 0x4ffb654d), + STCP(0x639b3a0b, 0x5063e008), STCP(0x6346d44b, 0x50cc029c), + STCP(0x62f201ac, 0x5133cc94), STCP(0x629cc28c, 0x519b3d80), + STCP(0x62471749, 0x520254ef), STCP(0x61f1003f, 0x5269126e), + STCP(0x619a7dce, 0x52cf758f), STCP(0x61439053, 0x53357ddf), + STCP(0x60ec3830, 0x539b2af0), STCP(0x609475c3, 0x54007c51), + STCP(0x603c496c, 0x54657194), STCP(0x5fe3b38d, 0x54ca0a4b), + STCP(0x5f8ab487, 0x552e4605), STCP(0x5f314cba, 0x55922457), + STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5e7d4458, 0x5658c709), + STCP(0x5e22a487, 0x56bb8a90), STCP(0x5dc79d7c, 0x571deefa), + STCP(0x5d6c2f99, 0x577ff3da), STCP(0x5d105b44, 0x57e198c7), + STCP(0x5cb420e0, 0x5842dd54), STCP(0x5c5780d3, 0x58a3c118), + STCP(0x5bfa7b82, 0x590443a7), STCP(0x5b9d1154, 0x59646498), + STCP(0x5b3f42ae, 0x59c42381), STCP(0x5ae10ff9, 0x5a237ffa), + STCP(0x5a82799a, 0x5a82799a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STP SineTable480[] = { + STCP(0x7fffffff, 0x00000000), STCP(0x7fffd315, 0x006b3b9b), + STCP(0x7fff4c54, 0x00d676eb), STCP(0x7ffe6bbf, 0x0141b1a5), + STCP(0x7ffd3154, 0x01aceb7c), STCP(0x7ffb9d15, 0x02182427), + STCP(0x7ff9af04, 0x02835b5a), STCP(0x7ff76721, 0x02ee90c8), + STCP(0x7ff4c56f, 0x0359c428), STCP(0x7ff1c9ef, 0x03c4f52f), + STCP(0x7fee74a2, 0x0430238f), STCP(0x7feac58d, 0x049b4f00), + STCP(0x7fe6bcb0, 0x05067734), STCP(0x7fe25a0f, 0x05719be2), + STCP(0x7fdd9dad, 0x05dcbcbe), STCP(0x7fd8878e, 0x0647d97c), + STCP(0x7fd317b4, 0x06b2f1d2), STCP(0x7fcd4e24, 0x071e0575), + STCP(0x7fc72ae2, 0x07891418), STCP(0x7fc0adf2, 0x07f41d72), + STCP(0x7fb9d759, 0x085f2137), STCP(0x7fb2a71b, 0x08ca1f1b), + STCP(0x7fab1d3d, 0x093516d4), STCP(0x7fa339c5, 0x09a00817), + STCP(0x7f9afcb9, 0x0a0af299), STCP(0x7f92661d, 0x0a75d60e), + STCP(0x7f8975f9, 0x0ae0b22c), STCP(0x7f802c52, 0x0b4b86a8), + STCP(0x7f76892f, 0x0bb65336), STCP(0x7f6c8c96, 0x0c21178c), + STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f578721, 0x0cf68662), + STCP(0x7f4c7e54, 0x0d61304e), STCP(0x7f411c2f, 0x0dcbd0d5), + STCP(0x7f3560b9, 0x0e3667ad), STCP(0x7f294bfd, 0x0ea0f48c), + STCP(0x7f1cde01, 0x0f0b7727), STCP(0x7f1016ce, 0x0f75ef33), + STCP(0x7f02f66f, 0x0fe05c64), STCP(0x7ef57cea, 0x104abe71), + STCP(0x7ee7aa4c, 0x10b5150f), STCP(0x7ed97e9c, 0x111f5ff4), + STCP(0x7ecaf9e5, 0x11899ed3), STCP(0x7ebc1c31, 0x11f3d164), + STCP(0x7eace58a, 0x125df75b), STCP(0x7e9d55fc, 0x12c8106f), + STCP(0x7e8d6d91, 0x13321c53), STCP(0x7e7d2c54, 0x139c1abf), + STCP(0x7e6c9251, 0x14060b68), STCP(0x7e5b9f93, 0x146fee03), + STCP(0x7e4a5426, 0x14d9c245), STCP(0x7e38b017, 0x154387e6), + STCP(0x7e26b371, 0x15ad3e9a), STCP(0x7e145e42, 0x1616e618), + STCP(0x7e01b096, 0x16807e15), STCP(0x7deeaa7a, 0x16ea0646), + STCP(0x7ddb4bfc, 0x17537e63), STCP(0x7dc79529, 0x17bce621), + STCP(0x7db3860f, 0x18263d36), STCP(0x7d9f1ebd, 0x188f8357), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d7547a7, 0x1961db9b), + STCP(0x7d5fd801, 0x19caed29), STCP(0x7d4a105d, 0x1a33ec9c), + STCP(0x7d33f0ca, 0x1a9cd9ac), STCP(0x7d1d7958, 0x1b05b40f), + STCP(0x7d06aa16, 0x1b6e7b7a), STCP(0x7cef8315, 0x1bd72fa4), + STCP(0x7cd80464, 0x1c3fd045), STCP(0x7cc02e15, 0x1ca85d12), + STCP(0x7ca80038, 0x1d10d5c2), STCP(0x7c8f7ade, 0x1d793a0b), + STCP(0x7c769e18, 0x1de189a6), STCP(0x7c5d69f7, 0x1e49c447), + STCP(0x7c43de8e, 0x1eb1e9a7), STCP(0x7c29fbee, 0x1f19f97b), + STCP(0x7c0fc22a, 0x1f81f37c), STCP(0x7bf53153, 0x1fe9d75f), + STCP(0x7bda497d, 0x2051a4dd), STCP(0x7bbf0aba, 0x20b95bac), + STCP(0x7ba3751d, 0x2120fb83), STCP(0x7b8788ba, 0x2188841a), + STCP(0x7b6b45a5, 0x21eff528), STCP(0x7b4eabf1, 0x22574e65), + STCP(0x7b31bbb2, 0x22be8f87), STCP(0x7b1474fd, 0x2325b847), + STCP(0x7af6d7e6, 0x238cc85d), STCP(0x7ad8e482, 0x23f3bf7e), + STCP(0x7aba9ae6, 0x245a9d65), STCP(0x7a9bfb27, 0x24c161c7), + STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a5db997, 0x258e9ce0), + STCP(0x7a3e17f2, 0x25f51307), STCP(0x7a1e2082, 0x265b6e8a), + STCP(0x79fdd35c, 0x26c1af22), STCP(0x79dd3098, 0x2727d486), + STCP(0x79bc384d, 0x278dde6e), STCP(0x799aea92, 0x27f3cc94), + STCP(0x7979477d, 0x28599eb0), STCP(0x79574f28, 0x28bf547b), + STCP(0x793501a9, 0x2924edac), STCP(0x79125f19, 0x298a69fc), + STCP(0x78ef678f, 0x29efc925), STCP(0x78cc1b26, 0x2a550adf), + STCP(0x78a879f4, 0x2aba2ee4), STCP(0x78848414, 0x2b1f34eb), + STCP(0x7860399e, 0x2b841caf), STCP(0x783b9aad, 0x2be8e5e8), + STCP(0x7816a759, 0x2c4d9050), STCP(0x77f15fbc, 0x2cb21ba0), + STCP(0x77cbc3f2, 0x2d168792), STCP(0x77a5d413, 0x2d7ad3de), + STCP(0x777f903c, 0x2ddf0040), STCP(0x7758f886, 0x2e430c6f), + STCP(0x77320d0d, 0x2ea6f827), STCP(0x770acdec, 0x2f0ac320), + STCP(0x76e33b3f, 0x2f6e6d16), STCP(0x76bb5521, 0x2fd1f5c1), + STCP(0x76931bae, 0x30355cdd), STCP(0x766a8f04, 0x3098a223), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x76187c77, 0x315ec617), + STCP(0x75eef6ce, 0x31c1a43b), STCP(0x75c51e61, 0x32245f72), + STCP(0x759af34c, 0x3286f779), STCP(0x757075ac, 0x32e96c09), + STCP(0x7545a5a0, 0x334bbcde), STCP(0x751a8346, 0x33ade9b3), + STCP(0x74ef0ebc, 0x340ff242), STCP(0x74c34820, 0x3471d647), + STCP(0x74972f92, 0x34d3957e), STCP(0x746ac52f, 0x35352fa1), + STCP(0x743e0918, 0x3596a46c), STCP(0x7410fb6b, 0x35f7f39c), + STCP(0x73e39c49, 0x36591cea), STCP(0x73b5ebd1, 0x36ba2014), + STCP(0x7387ea23, 0x371afcd5), STCP(0x73599760, 0x377bb2e9), + STCP(0x732af3a7, 0x37dc420c), STCP(0x72fbff1b, 0x383ca9fb), + STCP(0x72ccb9db, 0x389cea72), STCP(0x729d2409, 0x38fd032d), + STCP(0x726d3dc6, 0x395cf3e9), STCP(0x723d0734, 0x39bcbc63), + STCP(0x720c8075, 0x3a1c5c57), STCP(0x71dba9ab, 0x3a7bd382), + STCP(0x71aa82f7, 0x3adb21a1), STCP(0x71790c7e, 0x3b3a4672), + STCP(0x71474660, 0x3b9941b1), STCP(0x711530c2, 0x3bf8131c), + STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70b01790, 0x3cb5376b), + STCP(0x707d1443, 0x3d1389cb), STCP(0x7049c203, 0x3d71b14d), + STCP(0x701620f5, 0x3dcfadb0), STCP(0x6fe2313c, 0x3e2d7eb1), + STCP(0x6fadf2fc, 0x3e8b240e), STCP(0x6f79665b, 0x3ee89d86), + STCP(0x6f448b7e, 0x3f45ead8), STCP(0x6f0f6289, 0x3fa30bc1), + STCP(0x6ed9eba1, 0x40000000), STCP(0x6ea426ed, 0x405cc754), + STCP(0x6e6e1492, 0x40b9617d), STCP(0x6e37b4b6, 0x4115ce38), + STCP(0x6e010780, 0x41720d46), STCP(0x6dca0d14, 0x41ce1e65), + STCP(0x6d92c59b, 0x422a0154), STCP(0x6d5b313b, 0x4285b5d4), + STCP(0x6d23501b, 0x42e13ba4), STCP(0x6ceb2261, 0x433c9283), + STCP(0x6cb2a837, 0x4397ba32), STCP(0x6c79e1c2, 0x43f2b271), + STCP(0x6c40cf2c, 0x444d7aff), STCP(0x6c07709b, 0x44a8139e), + STCP(0x6bcdc639, 0x45027c0c), STCP(0x6b93d02e, 0x455cb40c), + STCP(0x6b598ea3, 0x45b6bb5e), STCP(0x6b1f01c0, 0x461091c2), + STCP(0x6ae429ae, 0x466a36f9), STCP(0x6aa90697, 0x46c3aac5), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a31e000, 0x4775fd1f), + STCP(0x69f5dcd3, 0x47cedb31), STCP(0x69b98f48, 0x482786dc), + STCP(0x697cf78a, 0x487fffe4), STCP(0x694015c3, 0x48d84609), + STCP(0x6902ea1d, 0x4930590f), STCP(0x68c574c4, 0x498838b6), + STCP(0x6887b5e2, 0x49dfe4c2), STCP(0x6849ada3, 0x4a375cf5), + STCP(0x680b5c33, 0x4a8ea111), STCP(0x67ccc1be, 0x4ae5b0da), + STCP(0x678dde6e, 0x4b3c8c12), STCP(0x674eb271, 0x4b93327c), + STCP(0x670f3df3, 0x4be9a3db), STCP(0x66cf8120, 0x4c3fdff4), + STCP(0x668f7c25, 0x4c95e688), STCP(0x664f2f2e, 0x4cebb75c), + STCP(0x660e9a6a, 0x4d415234), STCP(0x65cdbe05, 0x4d96b6d3), + STCP(0x658c9a2d, 0x4debe4fe), STCP(0x654b2f10, 0x4e40dc79), + STCP(0x65097cdb, 0x4e959d08), STCP(0x64c783bd, 0x4eea2670), + STCP(0x648543e4, 0x4f3e7875), STCP(0x6442bd7e, 0x4f9292dc), + STCP(0x63fff0ba, 0x4fe6756a), STCP(0x63bcddc7, 0x503a1fe5), + STCP(0x637984d4, 0x508d9211), STCP(0x6335e611, 0x50e0cbb4), + STCP(0x62f201ac, 0x5133cc94), STCP(0x62add7d6, 0x51869476), + STCP(0x626968be, 0x51d92321), STCP(0x6224b495, 0x522b7859), + STCP(0x61dfbb8a, 0x527d93e6), STCP(0x619a7dce, 0x52cf758f), + STCP(0x6154fb91, 0x53211d18), STCP(0x610f3505, 0x53728a4a), + STCP(0x60c92a5a, 0x53c3bcea), STCP(0x6082dbc1, 0x5414b4c1), + STCP(0x603c496c, 0x54657194), STCP(0x5ff5738d, 0x54b5f32c), + STCP(0x5fae5a55, 0x55063951), STCP(0x5f66fdf5, 0x555643c8), + STCP(0x5f1f5ea1, 0x55a6125c), STCP(0x5ed77c8a, 0x55f5a4d2), + STCP(0x5e8f57e2, 0x5644faf4), STCP(0x5e46f0dd, 0x5694148b), + STCP(0x5dfe47ad, 0x56e2f15d), STCP(0x5db55c86, 0x57319135), + STCP(0x5d6c2f99, 0x577ff3da), STCP(0x5d22c11c, 0x57ce1917), + STCP(0x5cd91140, 0x581c00b3), STCP(0x5c8f203b, 0x5869aa79), + STCP(0x5c44ee40, 0x58b71632), STCP(0x5bfa7b82, 0x590443a7), + STCP(0x5bafc837, 0x595132a2), STCP(0x5b64d492, 0x599de2ee), + STCP(0x5b19a0c8, 0x59ea5454), STCP(0x5ace2d0f, 0x5a36869f), + STCP(0x5a82799a, 0x5a82799a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STP SineTable512[] = { + STCP(0x7fffffff, 0x00000000), STCP(0x7fffd886, 0x006487e3), + STCP(0x7fff6216, 0x00c90f88), STCP(0x7ffe9cb2, 0x012d96b1), + STCP(0x7ffd885a, 0x01921d20), STCP(0x7ffc250f, 0x01f6a297), + STCP(0x7ffa72d1, 0x025b26d7), STCP(0x7ff871a2, 0x02bfa9a4), + STCP(0x7ff62182, 0x03242abf), STCP(0x7ff38274, 0x0388a9ea), + STCP(0x7ff09478, 0x03ed26e6), STCP(0x7fed5791, 0x0451a177), + STCP(0x7fe9cbc0, 0x04b6195d), STCP(0x7fe5f108, 0x051a8e5c), + STCP(0x7fe1c76b, 0x057f0035), STCP(0x7fdd4eec, 0x05e36ea9), + STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd37153, 0x06ac406f), + STCP(0x7fce0c3e, 0x0710a345), STCP(0x7fc85854, 0x077501be), + STCP(0x7fc25596, 0x07d95b9e), STCP(0x7fbc040a, 0x083db0a7), + STCP(0x7fb563b3, 0x08a2009a), STCP(0x7fae7495, 0x09064b3a), + STCP(0x7fa736b4, 0x096a9049), STCP(0x7f9faa15, 0x09cecf89), + STCP(0x7f97cebd, 0x0a3308bd), STCP(0x7f8fa4b0, 0x0a973ba5), + STCP(0x7f872bf3, 0x0afb6805), STCP(0x7f7e648c, 0x0b5f8d9f), + STCP(0x7f754e80, 0x0bc3ac35), STCP(0x7f6be9d4, 0x0c27c389), + STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f5834b7, 0x0cefdb76), + STCP(0x7f4de451, 0x0d53db92), STCP(0x7f434563, 0x0db7d376), + STCP(0x7f3857f6, 0x0e1bc2e4), STCP(0x7f2d1c0e, 0x0e7fa99e), + STCP(0x7f2191b4, 0x0ee38766), STCP(0x7f15b8ee, 0x0f475bff), + STCP(0x7f0991c4, 0x0fab272b), STCP(0x7efd1c3c, 0x100ee8ad), + STCP(0x7ef05860, 0x1072a048), STCP(0x7ee34636, 0x10d64dbd), + STCP(0x7ed5e5c6, 0x1139f0cf), STCP(0x7ec8371a, 0x119d8941), + STCP(0x7eba3a39, 0x120116d5), STCP(0x7eabef2c, 0x1264994e), + STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e8e6eb2, 0x132b7bf9), + STCP(0x7e7f3957, 0x138edbb1), STCP(0x7e6fb5f4, 0x13f22f58), + STCP(0x7e5fe493, 0x145576b1), STCP(0x7e4fc53e, 0x14b8b17f), + STCP(0x7e3f57ff, 0x151bdf86), STCP(0x7e2e9cdf, 0x157f0086), + STCP(0x7e1d93ea, 0x15e21445), STCP(0x7e0c3d29, 0x16451a83), + STCP(0x7dfa98a8, 0x16a81305), STCP(0x7de8a670, 0x170afd8d), + STCP(0x7dd6668f, 0x176dd9de), STCP(0x7dc3d90d, 0x17d0a7bc), + STCP(0x7db0fdf8, 0x183366e9), STCP(0x7d9dd55a, 0x18961728), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d769bb5, 0x195b49ea), + STCP(0x7d628ac6, 0x19bdcbf3), STCP(0x7d4e2c7f, 0x1a203e1b), + STCP(0x7d3980ec, 0x1a82a026), STCP(0x7d24881b, 0x1ae4f1d6), + STCP(0x7d0f4218, 0x1b4732ef), STCP(0x7cf9aef0, 0x1ba96335), + STCP(0x7ce3ceb2, 0x1c0b826a), STCP(0x7ccda169, 0x1c6d9053), + STCP(0x7cb72724, 0x1ccf8cb3), STCP(0x7ca05ff1, 0x1d31774d), + STCP(0x7c894bde, 0x1d934fe5), STCP(0x7c71eaf9, 0x1df5163f), + STCP(0x7c5a3d50, 0x1e56ca1e), STCP(0x7c4242f2, 0x1eb86b46), + STCP(0x7c29fbee, 0x1f19f97b), STCP(0x7c116853, 0x1f7b7481), + STCP(0x7bf88830, 0x1fdcdc1b), STCP(0x7bdf5b94, 0x203e300d), + STCP(0x7bc5e290, 0x209f701c), STCP(0x7bac1d31, 0x21009c0c), + STCP(0x7b920b89, 0x2161b3a0), STCP(0x7b77ada8, 0x21c2b69c), + STCP(0x7b5d039e, 0x2223a4c5), STCP(0x7b420d7a, 0x22847de0), + STCP(0x7b26cb4f, 0x22e541af), STCP(0x7b0b3d2c, 0x2345eff8), + STCP(0x7aef6323, 0x23a6887f), STCP(0x7ad33d45, 0x24070b08), + STCP(0x7ab6cba4, 0x24677758), STCP(0x7a9a0e50, 0x24c7cd33), + STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a5fb0d8, 0x2588349d), + STCP(0x7a4210d8, 0x25e845b6), STCP(0x7a24256f, 0x26483f6c), + STCP(0x7a05eead, 0x26a82186), STCP(0x79e76ca7, 0x2707ebc7), + STCP(0x79c89f6e, 0x27679df4), STCP(0x79a98715, 0x27c737d3), + STCP(0x798a23b1, 0x2826b928), STCP(0x796a7554, 0x288621b9), + STCP(0x794a7c12, 0x28e5714b), STCP(0x792a37fe, 0x2944a7a2), + STCP(0x7909a92d, 0x29a3c485), STCP(0x78e8cfb2, 0x2a02c7b8), + STCP(0x78c7aba2, 0x2a61b101), STCP(0x78a63d11, 0x2ac08026), + STCP(0x78848414, 0x2b1f34eb), STCP(0x786280bf, 0x2b7dcf17), + STCP(0x78403329, 0x2bdc4e6f), STCP(0x781d9b65, 0x2c3ab2b9), + STCP(0x77fab989, 0x2c98fbba), STCP(0x77d78daa, 0x2cf72939), + STCP(0x77b417df, 0x2d553afc), STCP(0x7790583e, 0x2db330c7), + STCP(0x776c4edb, 0x2e110a62), STCP(0x7747fbce, 0x2e6ec792), + STCP(0x77235f2d, 0x2ecc681e), STCP(0x76fe790e, 0x2f29ebcc), + STCP(0x76d94989, 0x2f875262), STCP(0x76b3d0b4, 0x2fe49ba7), + STCP(0x768e0ea6, 0x3041c761), STCP(0x76680376, 0x309ed556), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x761b1211, 0x3158970e), + STCP(0x75f42c0b, 0x31b54a5e), STCP(0x75ccfd42, 0x3211df04), + STCP(0x75a585cf, 0x326e54c7), STCP(0x757dc5ca, 0x32caab6f), + STCP(0x7555bd4c, 0x3326e2c3), STCP(0x752d6c6c, 0x3382fa88), + STCP(0x7504d345, 0x33def287), STCP(0x74dbf1ef, 0x343aca87), + STCP(0x74b2c884, 0x34968250), STCP(0x7489571c, 0x34f219a8), + STCP(0x745f9dd1, 0x354d9057), STCP(0x74359cbd, 0x35a8e625), + STCP(0x740b53fb, 0x36041ad9), STCP(0x73e0c3a3, 0x365f2e3b), + STCP(0x73b5ebd1, 0x36ba2014), STCP(0x738acc9e, 0x3714f02a), + STCP(0x735f6626, 0x376f9e46), STCP(0x7333b883, 0x37ca2a30), + STCP(0x7307c3d0, 0x382493b0), STCP(0x72db8828, 0x387eda8e), + STCP(0x72af05a7, 0x38d8fe93), STCP(0x72823c67, 0x3932ff87), + STCP(0x72552c85, 0x398cdd32), STCP(0x7227d61c, 0x39e6975e), + STCP(0x71fa3949, 0x3a402dd2), STCP(0x71cc5626, 0x3a99a057), + STCP(0x719e2cd2, 0x3af2eeb7), STCP(0x716fbd68, 0x3b4c18ba), + STCP(0x71410805, 0x3ba51e29), STCP(0x71120cc5, 0x3bfdfecd), + STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70b34525, 0x3caf50da), + STCP(0x708378ff, 0x3d07c1d6), STCP(0x70536771, 0x3d600d2c), + STCP(0x7023109a, 0x3db832a6), STCP(0x6ff27497, 0x3e10320d), + STCP(0x6fc19385, 0x3e680b2c), STCP(0x6f906d84, 0x3ebfbdcd), + STCP(0x6f5f02b2, 0x3f1749b8), STCP(0x6f2d532c, 0x3f6eaeb8), + STCP(0x6efb5f12, 0x3fc5ec98), STCP(0x6ec92683, 0x401d0321), + STCP(0x6e96a99d, 0x4073f21d), STCP(0x6e63e87f, 0x40cab958), + STCP(0x6e30e34a, 0x4121589b), STCP(0x6dfd9a1c, 0x4177cfb1), + STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6d963c54, 0x42244481), + STCP(0x6d6227fa, 0x427a41d0), STCP(0x6d2dd027, 0x42d0161e), + STCP(0x6cf934fc, 0x4325c135), STCP(0x6cc45698, 0x437b42e1), + STCP(0x6c8f351c, 0x43d09aed), STCP(0x6c59d0a9, 0x4425c923), + STCP(0x6c242960, 0x447acd50), STCP(0x6bee3f62, 0x44cfa740), + STCP(0x6bb812d1, 0x452456bd), STCP(0x6b81a3cd, 0x4578db93), + STCP(0x6b4af279, 0x45cd358f), STCP(0x6b13fef5, 0x4621647d), + STCP(0x6adcc964, 0x46756828), STCP(0x6aa551e9, 0x46c9405c), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a359db9, 0x47706d93), + STCP(0x69fd614a, 0x47c3c22f), STCP(0x69c4e37a, 0x4816ea86), + STCP(0x698c246c, 0x4869e665), STCP(0x69532442, 0x48bcb599), + STCP(0x6919e320, 0x490f57ee), STCP(0x68e06129, 0x4961cd33), + STCP(0x68a69e81, 0x49b41533), STCP(0x686c9b4b, 0x4a062fbd), + STCP(0x683257ab, 0x4a581c9e), STCP(0x67f7d3c5, 0x4aa9dba2), + STCP(0x67bd0fbd, 0x4afb6c98), STCP(0x67820bb7, 0x4b4ccf4d), + STCP(0x6746c7d8, 0x4b9e0390), STCP(0x670b4444, 0x4bef092d), + STCP(0x66cf8120, 0x4c3fdff4), STCP(0x66937e91, 0x4c9087b1), + STCP(0x66573cbb, 0x4ce10034), STCP(0x661abbc5, 0x4d31494b), + STCP(0x65ddfbd3, 0x4d8162c4), STCP(0x65a0fd0b, 0x4dd14c6e), + STCP(0x6563bf92, 0x4e210617), STCP(0x6526438f, 0x4e708f8f), + STCP(0x64e88926, 0x4ebfe8a5), STCP(0x64aa907f, 0x4f0f1126), + STCP(0x646c59bf, 0x4f5e08e3), STCP(0x642de50d, 0x4faccfab), + STCP(0x63ef3290, 0x4ffb654d), STCP(0x63b0426d, 0x5049c999), + STCP(0x637114cc, 0x5097fc5e), STCP(0x6331a9d4, 0x50e5fd6d), + STCP(0x62f201ac, 0x5133cc94), STCP(0x62b21c7b, 0x518169a5), + STCP(0x6271fa69, 0x51ced46e), STCP(0x62319b9d, 0x521c0cc2), + STCP(0x61f1003f, 0x5269126e), STCP(0x61b02876, 0x52b5e546), + STCP(0x616f146c, 0x53028518), STCP(0x612dc447, 0x534ef1b5), + STCP(0x60ec3830, 0x539b2af0), STCP(0x60aa7050, 0x53e73097), + STCP(0x60686ccf, 0x5433027d), STCP(0x60262dd6, 0x547ea073), + STCP(0x5fe3b38d, 0x54ca0a4b), STCP(0x5fa0fe1f, 0x55153fd4), + STCP(0x5f5e0db3, 0x556040e2), STCP(0x5f1ae274, 0x55ab0d46), + STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5e93dc1f, 0x56400758), + STCP(0x5e50015d, 0x568a34a9), STCP(0x5e0bec6e, 0x56d42c99), + STCP(0x5dc79d7c, 0x571deefa), STCP(0x5d8314b1, 0x57677b9d), + STCP(0x5d3e5237, 0x57b0d256), STCP(0x5cf95638, 0x57f9f2f8), + STCP(0x5cb420e0, 0x5842dd54), STCP(0x5c6eb258, 0x588b9140), + STCP(0x5c290acc, 0x58d40e8c), STCP(0x5be32a67, 0x591c550e), + STCP(0x5b9d1154, 0x59646498), STCP(0x5b56bfbd, 0x59ac3cfd), + STCP(0x5b1035cf, 0x59f3de12), STCP(0x5ac973b5, 0x5a3b47ab), + STCP(0x5a82799a, 0x5a82799a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STP SineTable1024[] = { + STCP(0x7fffffff, 0x00000000), STCP(0x7ffff621, 0x003243f5), + STCP(0x7fffd886, 0x006487e3), STCP(0x7fffa72c, 0x0096cbc1), + STCP(0x7fff6216, 0x00c90f88), STCP(0x7fff0943, 0x00fb5330), + STCP(0x7ffe9cb2, 0x012d96b1), STCP(0x7ffe1c65, 0x015fda03), + STCP(0x7ffd885a, 0x01921d20), STCP(0x7ffce093, 0x01c45ffe), + STCP(0x7ffc250f, 0x01f6a297), STCP(0x7ffb55ce, 0x0228e4e2), + STCP(0x7ffa72d1, 0x025b26d7), STCP(0x7ff97c18, 0x028d6870), + STCP(0x7ff871a2, 0x02bfa9a4), STCP(0x7ff75370, 0x02f1ea6c), + STCP(0x7ff62182, 0x03242abf), STCP(0x7ff4dbd9, 0x03566a96), + STCP(0x7ff38274, 0x0388a9ea), STCP(0x7ff21553, 0x03bae8b2), + STCP(0x7ff09478, 0x03ed26e6), STCP(0x7feeffe1, 0x041f6480), + STCP(0x7fed5791, 0x0451a177), STCP(0x7feb9b85, 0x0483ddc3), + STCP(0x7fe9cbc0, 0x04b6195d), STCP(0x7fe7e841, 0x04e8543e), + STCP(0x7fe5f108, 0x051a8e5c), STCP(0x7fe3e616, 0x054cc7b1), + STCP(0x7fe1c76b, 0x057f0035), STCP(0x7fdf9508, 0x05b137df), + STCP(0x7fdd4eec, 0x05e36ea9), STCP(0x7fdaf519, 0x0615a48b), + STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd6064c, 0x067a0d76), + STCP(0x7fd37153, 0x06ac406f), STCP(0x7fd0c8a3, 0x06de7262), + STCP(0x7fce0c3e, 0x0710a345), STCP(0x7fcb3c23, 0x0742d311), + STCP(0x7fc85854, 0x077501be), STCP(0x7fc560cf, 0x07a72f45), + STCP(0x7fc25596, 0x07d95b9e), STCP(0x7fbf36aa, 0x080b86c2), + STCP(0x7fbc040a, 0x083db0a7), STCP(0x7fb8bdb8, 0x086fd947), + STCP(0x7fb563b3, 0x08a2009a), STCP(0x7fb1f5fc, 0x08d42699), + STCP(0x7fae7495, 0x09064b3a), STCP(0x7faadf7c, 0x09386e78), + STCP(0x7fa736b4, 0x096a9049), STCP(0x7fa37a3c, 0x099cb0a7), + STCP(0x7f9faa15, 0x09cecf89), STCP(0x7f9bc640, 0x0a00ece8), + STCP(0x7f97cebd, 0x0a3308bd), STCP(0x7f93c38c, 0x0a6522fe), + STCP(0x7f8fa4b0, 0x0a973ba5), STCP(0x7f8b7227, 0x0ac952aa), + STCP(0x7f872bf3, 0x0afb6805), STCP(0x7f82d214, 0x0b2d7baf), + STCP(0x7f7e648c, 0x0b5f8d9f), STCP(0x7f79e35a, 0x0b919dcf), + STCP(0x7f754e80, 0x0bc3ac35), STCP(0x7f70a5fe, 0x0bf5b8cb), + STCP(0x7f6be9d4, 0x0c27c389), STCP(0x7f671a05, 0x0c59cc68), + STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f5d3f75, 0x0cbdd865), + STCP(0x7f5834b7, 0x0cefdb76), STCP(0x7f531655, 0x0d21dc87), + STCP(0x7f4de451, 0x0d53db92), STCP(0x7f489eaa, 0x0d85d88f), + STCP(0x7f434563, 0x0db7d376), STCP(0x7f3dd87c, 0x0de9cc40), + STCP(0x7f3857f6, 0x0e1bc2e4), STCP(0x7f32c3d1, 0x0e4db75b), + STCP(0x7f2d1c0e, 0x0e7fa99e), STCP(0x7f2760af, 0x0eb199a4), + STCP(0x7f2191b4, 0x0ee38766), STCP(0x7f1baf1e, 0x0f1572dc), + STCP(0x7f15b8ee, 0x0f475bff), STCP(0x7f0faf25, 0x0f7942c7), + STCP(0x7f0991c4, 0x0fab272b), STCP(0x7f0360cb, 0x0fdd0926), + STCP(0x7efd1c3c, 0x100ee8ad), STCP(0x7ef6c418, 0x1040c5bb), + STCP(0x7ef05860, 0x1072a048), STCP(0x7ee9d914, 0x10a4784b), + STCP(0x7ee34636, 0x10d64dbd), STCP(0x7edc9fc6, 0x11082096), + STCP(0x7ed5e5c6, 0x1139f0cf), STCP(0x7ecf1837, 0x116bbe60), + STCP(0x7ec8371a, 0x119d8941), STCP(0x7ec14270, 0x11cf516a), + STCP(0x7eba3a39, 0x120116d5), STCP(0x7eb31e78, 0x1232d979), + STCP(0x7eabef2c, 0x1264994e), STCP(0x7ea4ac58, 0x1296564d), + STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e95ec1a, 0x12f9c7aa), + STCP(0x7e8e6eb2, 0x132b7bf9), STCP(0x7e86ddc6, 0x135d2d53), + STCP(0x7e7f3957, 0x138edbb1), STCP(0x7e778166, 0x13c0870a), + STCP(0x7e6fb5f4, 0x13f22f58), STCP(0x7e67d703, 0x1423d492), + STCP(0x7e5fe493, 0x145576b1), STCP(0x7e57dea7, 0x148715ae), + STCP(0x7e4fc53e, 0x14b8b17f), STCP(0x7e47985b, 0x14ea4a1f), + STCP(0x7e3f57ff, 0x151bdf86), STCP(0x7e37042a, 0x154d71aa), + STCP(0x7e2e9cdf, 0x157f0086), STCP(0x7e26221f, 0x15b08c12), + STCP(0x7e1d93ea, 0x15e21445), STCP(0x7e14f242, 0x16139918), + STCP(0x7e0c3d29, 0x16451a83), STCP(0x7e0374a0, 0x1676987f), + STCP(0x7dfa98a8, 0x16a81305), STCP(0x7df1a942, 0x16d98a0c), + STCP(0x7de8a670, 0x170afd8d), STCP(0x7ddf9034, 0x173c6d80), + STCP(0x7dd6668f, 0x176dd9de), STCP(0x7dcd2981, 0x179f429f), + STCP(0x7dc3d90d, 0x17d0a7bc), STCP(0x7dba7534, 0x1802092c), + STCP(0x7db0fdf8, 0x183366e9), STCP(0x7da77359, 0x1864c0ea), + STCP(0x7d9dd55a, 0x18961728), STCP(0x7d9423fc, 0x18c7699b), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d808728, 0x192a0304), + STCP(0x7d769bb5, 0x195b49ea), STCP(0x7d6c9ce9, 0x198c8ce7), + STCP(0x7d628ac6, 0x19bdcbf3), STCP(0x7d58654d, 0x19ef0707), + STCP(0x7d4e2c7f, 0x1a203e1b), STCP(0x7d43e05e, 0x1a517128), + STCP(0x7d3980ec, 0x1a82a026), STCP(0x7d2f0e2b, 0x1ab3cb0d), + STCP(0x7d24881b, 0x1ae4f1d6), STCP(0x7d19eebf, 0x1b161479), + STCP(0x7d0f4218, 0x1b4732ef), STCP(0x7d048228, 0x1b784d30), + STCP(0x7cf9aef0, 0x1ba96335), STCP(0x7ceec873, 0x1bda74f6), + STCP(0x7ce3ceb2, 0x1c0b826a), STCP(0x7cd8c1ae, 0x1c3c8b8c), + STCP(0x7ccda169, 0x1c6d9053), STCP(0x7cc26de5, 0x1c9e90b8), + STCP(0x7cb72724, 0x1ccf8cb3), STCP(0x7cabcd28, 0x1d00843d), + STCP(0x7ca05ff1, 0x1d31774d), STCP(0x7c94df83, 0x1d6265dd), + STCP(0x7c894bde, 0x1d934fe5), STCP(0x7c7da505, 0x1dc4355e), + STCP(0x7c71eaf9, 0x1df5163f), STCP(0x7c661dbc, 0x1e25f282), + STCP(0x7c5a3d50, 0x1e56ca1e), STCP(0x7c4e49b7, 0x1e879d0d), + STCP(0x7c4242f2, 0x1eb86b46), STCP(0x7c362904, 0x1ee934c3), + STCP(0x7c29fbee, 0x1f19f97b), STCP(0x7c1dbbb3, 0x1f4ab968), + STCP(0x7c116853, 0x1f7b7481), STCP(0x7c0501d2, 0x1fac2abf), + STCP(0x7bf88830, 0x1fdcdc1b), STCP(0x7bebfb70, 0x200d888d), + STCP(0x7bdf5b94, 0x203e300d), STCP(0x7bd2a89e, 0x206ed295), + STCP(0x7bc5e290, 0x209f701c), STCP(0x7bb9096b, 0x20d0089c), + STCP(0x7bac1d31, 0x21009c0c), STCP(0x7b9f1de6, 0x21312a65), + STCP(0x7b920b89, 0x2161b3a0), STCP(0x7b84e61f, 0x219237b5), + STCP(0x7b77ada8, 0x21c2b69c), STCP(0x7b6a6227, 0x21f3304f), + STCP(0x7b5d039e, 0x2223a4c5), STCP(0x7b4f920e, 0x225413f8), + STCP(0x7b420d7a, 0x22847de0), STCP(0x7b3475e5, 0x22b4e274), + STCP(0x7b26cb4f, 0x22e541af), STCP(0x7b190dbc, 0x23159b88), + STCP(0x7b0b3d2c, 0x2345eff8), STCP(0x7afd59a4, 0x23763ef7), + STCP(0x7aef6323, 0x23a6887f), STCP(0x7ae159ae, 0x23d6cc87), + STCP(0x7ad33d45, 0x24070b08), STCP(0x7ac50dec, 0x243743fa), + STCP(0x7ab6cba4, 0x24677758), STCP(0x7aa8766f, 0x2497a517), + STCP(0x7a9a0e50, 0x24c7cd33), STCP(0x7a8b9348, 0x24f7efa2), + STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a6e648a, 0x2558235f), + STCP(0x7a5fb0d8, 0x2588349d), STCP(0x7a50ea47, 0x25b84012), + STCP(0x7a4210d8, 0x25e845b6), STCP(0x7a332490, 0x26184581), + STCP(0x7a24256f, 0x26483f6c), STCP(0x7a151378, 0x26783370), + STCP(0x7a05eead, 0x26a82186), STCP(0x79f6b711, 0x26d809a5), + STCP(0x79e76ca7, 0x2707ebc7), STCP(0x79d80f6f, 0x2737c7e3), + STCP(0x79c89f6e, 0x27679df4), STCP(0x79b91ca4, 0x27976df1), + STCP(0x79a98715, 0x27c737d3), STCP(0x7999dec4, 0x27f6fb92), + STCP(0x798a23b1, 0x2826b928), STCP(0x797a55e0, 0x2856708d), + STCP(0x796a7554, 0x288621b9), STCP(0x795a820e, 0x28b5cca5), + STCP(0x794a7c12, 0x28e5714b), STCP(0x793a6361, 0x29150fa1), + STCP(0x792a37fe, 0x2944a7a2), STCP(0x7919f9ec, 0x29743946), + STCP(0x7909a92d, 0x29a3c485), STCP(0x78f945c3, 0x29d34958), + STCP(0x78e8cfb2, 0x2a02c7b8), STCP(0x78d846fb, 0x2a323f9e), + STCP(0x78c7aba2, 0x2a61b101), STCP(0x78b6fda8, 0x2a911bdc), + STCP(0x78a63d11, 0x2ac08026), STCP(0x789569df, 0x2aefddd8), + STCP(0x78848414, 0x2b1f34eb), STCP(0x78738bb3, 0x2b4e8558), + STCP(0x786280bf, 0x2b7dcf17), STCP(0x7851633b, 0x2bad1221), + STCP(0x78403329, 0x2bdc4e6f), STCP(0x782ef08b, 0x2c0b83fa), + STCP(0x781d9b65, 0x2c3ab2b9), STCP(0x780c33b8, 0x2c69daa6), + STCP(0x77fab989, 0x2c98fbba), STCP(0x77e92cd9, 0x2cc815ee), + STCP(0x77d78daa, 0x2cf72939), STCP(0x77c5dc01, 0x2d263596), + STCP(0x77b417df, 0x2d553afc), STCP(0x77a24148, 0x2d843964), + STCP(0x7790583e, 0x2db330c7), STCP(0x777e5cc3, 0x2de2211e), + STCP(0x776c4edb, 0x2e110a62), STCP(0x775a2e89, 0x2e3fec8b), + STCP(0x7747fbce, 0x2e6ec792), STCP(0x7735b6af, 0x2e9d9b70), + STCP(0x77235f2d, 0x2ecc681e), STCP(0x7710f54c, 0x2efb2d95), + STCP(0x76fe790e, 0x2f29ebcc), STCP(0x76ebea77, 0x2f58a2be), + STCP(0x76d94989, 0x2f875262), STCP(0x76c69647, 0x2fb5fab2), + STCP(0x76b3d0b4, 0x2fe49ba7), STCP(0x76a0f8d2, 0x30133539), + STCP(0x768e0ea6, 0x3041c761), STCP(0x767b1231, 0x30705217), + STCP(0x76680376, 0x309ed556), STCP(0x7654e279, 0x30cd5115), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x762e69c4, 0x312a31f8), + STCP(0x761b1211, 0x3158970e), STCP(0x7607a828, 0x3186f487), + STCP(0x75f42c0b, 0x31b54a5e), STCP(0x75e09dbd, 0x31e39889), + STCP(0x75ccfd42, 0x3211df04), STCP(0x75b94a9c, 0x32401dc6), + STCP(0x75a585cf, 0x326e54c7), STCP(0x7591aedd, 0x329c8402), + STCP(0x757dc5ca, 0x32caab6f), STCP(0x7569ca99, 0x32f8cb07), + STCP(0x7555bd4c, 0x3326e2c3), STCP(0x75419de7, 0x3354f29b), + STCP(0x752d6c6c, 0x3382fa88), STCP(0x751928e0, 0x33b0fa84), + STCP(0x7504d345, 0x33def287), STCP(0x74f06b9e, 0x340ce28b), + STCP(0x74dbf1ef, 0x343aca87), STCP(0x74c7663a, 0x3468aa76), + STCP(0x74b2c884, 0x34968250), STCP(0x749e18cd, 0x34c4520d), + STCP(0x7489571c, 0x34f219a8), STCP(0x74748371, 0x351fd918), + STCP(0x745f9dd1, 0x354d9057), STCP(0x744aa63f, 0x357b3f5d), + STCP(0x74359cbd, 0x35a8e625), STCP(0x74208150, 0x35d684a6), + STCP(0x740b53fb, 0x36041ad9), STCP(0x73f614c0, 0x3631a8b8), + STCP(0x73e0c3a3, 0x365f2e3b), STCP(0x73cb60a8, 0x368cab5c), + STCP(0x73b5ebd1, 0x36ba2014), STCP(0x73a06522, 0x36e78c5b), + STCP(0x738acc9e, 0x3714f02a), STCP(0x73752249, 0x37424b7b), + STCP(0x735f6626, 0x376f9e46), STCP(0x73499838, 0x379ce885), + STCP(0x7333b883, 0x37ca2a30), STCP(0x731dc70a, 0x37f76341), + STCP(0x7307c3d0, 0x382493b0), STCP(0x72f1aed9, 0x3851bb77), + STCP(0x72db8828, 0x387eda8e), STCP(0x72c54fc1, 0x38abf0ef), + STCP(0x72af05a7, 0x38d8fe93), STCP(0x7298a9dd, 0x39060373), + STCP(0x72823c67, 0x3932ff87), STCP(0x726bbd48, 0x395ff2c9), + STCP(0x72552c85, 0x398cdd32), STCP(0x723e8a20, 0x39b9bebc), + STCP(0x7227d61c, 0x39e6975e), STCP(0x7211107e, 0x3a136712), + STCP(0x71fa3949, 0x3a402dd2), STCP(0x71e35080, 0x3a6ceb96), + STCP(0x71cc5626, 0x3a99a057), STCP(0x71b54a41, 0x3ac64c0f), + STCP(0x719e2cd2, 0x3af2eeb7), STCP(0x7186fdde, 0x3b1f8848), + STCP(0x716fbd68, 0x3b4c18ba), STCP(0x71586b74, 0x3b78a007), + STCP(0x71410805, 0x3ba51e29), STCP(0x7129931f, 0x3bd19318), + STCP(0x71120cc5, 0x3bfdfecd), STCP(0x70fa74fc, 0x3c2a6142), + STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70cb1128, 0x3c830a50), + STCP(0x70b34525, 0x3caf50da), STCP(0x709b67c0, 0x3cdb8e09), + STCP(0x708378ff, 0x3d07c1d6), STCP(0x706b78e3, 0x3d33ec39), + STCP(0x70536771, 0x3d600d2c), STCP(0x703b44ad, 0x3d8c24a8), + STCP(0x7023109a, 0x3db832a6), STCP(0x700acb3c, 0x3de4371f), + STCP(0x6ff27497, 0x3e10320d), STCP(0x6fda0cae, 0x3e3c2369), + STCP(0x6fc19385, 0x3e680b2c), STCP(0x6fa90921, 0x3e93e950), + STCP(0x6f906d84, 0x3ebfbdcd), STCP(0x6f77c0b3, 0x3eeb889c), + STCP(0x6f5f02b2, 0x3f1749b8), STCP(0x6f463383, 0x3f430119), + STCP(0x6f2d532c, 0x3f6eaeb8), STCP(0x6f1461b0, 0x3f9a5290), + STCP(0x6efb5f12, 0x3fc5ec98), STCP(0x6ee24b57, 0x3ff17cca), + STCP(0x6ec92683, 0x401d0321), STCP(0x6eaff099, 0x40487f94), + STCP(0x6e96a99d, 0x4073f21d), STCP(0x6e7d5193, 0x409f5ab6), + STCP(0x6e63e87f, 0x40cab958), STCP(0x6e4a6e66, 0x40f60dfb), + STCP(0x6e30e34a, 0x4121589b), STCP(0x6e174730, 0x414c992f), + STCP(0x6dfd9a1c, 0x4177cfb1), STCP(0x6de3dc11, 0x41a2fc1a), + STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6db02d29, 0x41f93689), + STCP(0x6d963c54, 0x42244481), STCP(0x6d7c3a98, 0x424f4845), + STCP(0x6d6227fa, 0x427a41d0), STCP(0x6d48047e, 0x42a5311b), + STCP(0x6d2dd027, 0x42d0161e), STCP(0x6d138afb, 0x42faf0d4), + STCP(0x6cf934fc, 0x4325c135), STCP(0x6cdece2f, 0x4350873c), + STCP(0x6cc45698, 0x437b42e1), STCP(0x6ca9ce3b, 0x43a5f41e), + STCP(0x6c8f351c, 0x43d09aed), STCP(0x6c748b3f, 0x43fb3746), + STCP(0x6c59d0a9, 0x4425c923), STCP(0x6c3f055d, 0x4450507e), + STCP(0x6c242960, 0x447acd50), STCP(0x6c093cb6, 0x44a53f93), + STCP(0x6bee3f62, 0x44cfa740), STCP(0x6bd3316a, 0x44fa0450), + STCP(0x6bb812d1, 0x452456bd), STCP(0x6b9ce39b, 0x454e9e80), + STCP(0x6b81a3cd, 0x4578db93), STCP(0x6b66536b, 0x45a30df0), + STCP(0x6b4af279, 0x45cd358f), STCP(0x6b2f80fb, 0x45f7526b), + STCP(0x6b13fef5, 0x4621647d), STCP(0x6af86c6c, 0x464b6bbe), + STCP(0x6adcc964, 0x46756828), STCP(0x6ac115e2, 0x469f59b4), + STCP(0x6aa551e9, 0x46c9405c), STCP(0x6a897d7d, 0x46f31c1a), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a51a361, 0x4746b2bc), + STCP(0x6a359db9, 0x47706d93), STCP(0x6a1987b0, 0x479a1d67), + STCP(0x69fd614a, 0x47c3c22f), STCP(0x69e12a8c, 0x47ed5be6), + STCP(0x69c4e37a, 0x4816ea86), STCP(0x69a88c19, 0x48406e08), + STCP(0x698c246c, 0x4869e665), STCP(0x696fac78, 0x48935397), + STCP(0x69532442, 0x48bcb599), STCP(0x69368bce, 0x48e60c62), + STCP(0x6919e320, 0x490f57ee), STCP(0x68fd2a3d, 0x49389836), + STCP(0x68e06129, 0x4961cd33), STCP(0x68c387e9, 0x498af6df), + STCP(0x68a69e81, 0x49b41533), STCP(0x6889a4f6, 0x49dd282a), + STCP(0x686c9b4b, 0x4a062fbd), STCP(0x684f8186, 0x4a2f2be6), + STCP(0x683257ab, 0x4a581c9e), STCP(0x68151dbe, 0x4a8101de), + STCP(0x67f7d3c5, 0x4aa9dba2), STCP(0x67da79c3, 0x4ad2a9e2), + STCP(0x67bd0fbd, 0x4afb6c98), STCP(0x679f95b7, 0x4b2423be), + STCP(0x67820bb7, 0x4b4ccf4d), STCP(0x676471c0, 0x4b756f40), + STCP(0x6746c7d8, 0x4b9e0390), STCP(0x67290e02, 0x4bc68c36), + STCP(0x670b4444, 0x4bef092d), STCP(0x66ed6aa1, 0x4c177a6e), + STCP(0x66cf8120, 0x4c3fdff4), STCP(0x66b187c3, 0x4c6839b7), + STCP(0x66937e91, 0x4c9087b1), STCP(0x6675658c, 0x4cb8c9dd), + STCP(0x66573cbb, 0x4ce10034), STCP(0x66390422, 0x4d092ab0), + STCP(0x661abbc5, 0x4d31494b), STCP(0x65fc63a9, 0x4d595bfe), + STCP(0x65ddfbd3, 0x4d8162c4), STCP(0x65bf8447, 0x4da95d96), + STCP(0x65a0fd0b, 0x4dd14c6e), STCP(0x65826622, 0x4df92f46), + STCP(0x6563bf92, 0x4e210617), STCP(0x6545095f, 0x4e48d0dd), + STCP(0x6526438f, 0x4e708f8f), STCP(0x65076e25, 0x4e984229), + STCP(0x64e88926, 0x4ebfe8a5), STCP(0x64c99498, 0x4ee782fb), + STCP(0x64aa907f, 0x4f0f1126), STCP(0x648b7ce0, 0x4f369320), + STCP(0x646c59bf, 0x4f5e08e3), STCP(0x644d2722, 0x4f857269), + STCP(0x642de50d, 0x4faccfab), STCP(0x640e9386, 0x4fd420a4), + STCP(0x63ef3290, 0x4ffb654d), STCP(0x63cfc231, 0x50229da1), + STCP(0x63b0426d, 0x5049c999), STCP(0x6390b34a, 0x5070e92f), + STCP(0x637114cc, 0x5097fc5e), STCP(0x635166f9, 0x50bf031f), + STCP(0x6331a9d4, 0x50e5fd6d), STCP(0x6311dd64, 0x510ceb40), + STCP(0x62f201ac, 0x5133cc94), STCP(0x62d216b3, 0x515aa162), + STCP(0x62b21c7b, 0x518169a5), STCP(0x6292130c, 0x51a82555), + STCP(0x6271fa69, 0x51ced46e), STCP(0x6251d298, 0x51f576ea), + STCP(0x62319b9d, 0x521c0cc2), STCP(0x6211557e, 0x524295f0), + STCP(0x61f1003f, 0x5269126e), STCP(0x61d09be5, 0x528f8238), + STCP(0x61b02876, 0x52b5e546), STCP(0x618fa5f7, 0x52dc3b92), + STCP(0x616f146c, 0x53028518), STCP(0x614e73da, 0x5328c1d0), + STCP(0x612dc447, 0x534ef1b5), STCP(0x610d05b7, 0x537514c2), + STCP(0x60ec3830, 0x539b2af0), STCP(0x60cb5bb7, 0x53c13439), + STCP(0x60aa7050, 0x53e73097), STCP(0x60897601, 0x540d2005), + STCP(0x60686ccf, 0x5433027d), STCP(0x604754bf, 0x5458d7f9), + STCP(0x60262dd6, 0x547ea073), STCP(0x6004f819, 0x54a45be6), + STCP(0x5fe3b38d, 0x54ca0a4b), STCP(0x5fc26038, 0x54efab9c), + STCP(0x5fa0fe1f, 0x55153fd4), STCP(0x5f7f8d46, 0x553ac6ee), + STCP(0x5f5e0db3, 0x556040e2), STCP(0x5f3c7f6b, 0x5585adad), + STCP(0x5f1ae274, 0x55ab0d46), STCP(0x5ef936d1, 0x55d05faa), + STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5eb5b3a2, 0x561adcb9), + STCP(0x5e93dc1f, 0x56400758), STCP(0x5e71f606, 0x566524aa), + STCP(0x5e50015d, 0x568a34a9), STCP(0x5e2dfe29, 0x56af3750), + STCP(0x5e0bec6e, 0x56d42c99), STCP(0x5de9cc33, 0x56f9147e), + STCP(0x5dc79d7c, 0x571deefa), STCP(0x5da5604f, 0x5742bc06), + STCP(0x5d8314b1, 0x57677b9d), STCP(0x5d60baa7, 0x578c2dba), + STCP(0x5d3e5237, 0x57b0d256), STCP(0x5d1bdb65, 0x57d5696d), + STCP(0x5cf95638, 0x57f9f2f8), STCP(0x5cd6c2b5, 0x581e6ef1), + STCP(0x5cb420e0, 0x5842dd54), STCP(0x5c9170bf, 0x58673e1b), + STCP(0x5c6eb258, 0x588b9140), STCP(0x5c4be5b0, 0x58afd6bd), + STCP(0x5c290acc, 0x58d40e8c), STCP(0x5c0621b2, 0x58f838a9), + STCP(0x5be32a67, 0x591c550e), STCP(0x5bc024f0, 0x594063b5), + STCP(0x5b9d1154, 0x59646498), STCP(0x5b79ef96, 0x598857b2), + STCP(0x5b56bfbd, 0x59ac3cfd), STCP(0x5b3381ce, 0x59d01475), + STCP(0x5b1035cf, 0x59f3de12), STCP(0x5aecdbc5, 0x5a1799d1), + STCP(0x5ac973b5, 0x5a3b47ab), STCP(0x5aa5fda5, 0x5a5ee79a), + STCP(0x5a82799a, 0x5a82799a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal6[] = { + STC(0x40000000), + STC(0xc0000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag6[] = { + STC(0x6ed9eba1), + STC(0x6ed9eba1), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal12[] = { + STC(0x6ed9eba1), + STC(0x40000000), + STC(0x40000000), + STC(0xc0000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag12[] = { + STC(0x40000000), + STC(0x6ed9eba1), + STC(0x6ed9eba1), + STC(0x6ed9eba1), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal24[] = { + STC(0x7ba3751d), STC(0x6ed9eba1), STC(0x5a82799a), STC(0x40000000), + STC(0x2120fb83), STC(0x00000000), STC(0xdedf047d), STC(0xc0000000), + STC(0xa57d8666), STC(0x9126145f), STC(0x845c8ae3), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag24[] = { + STC(0x2120fb83), STC(0x40000000), STC(0x5a82799a), STC(0x6ed9eba1), + STC(0x7ba3751d), STC(0x7fffffff), STC(0x7ba3751d), STC(0x6ed9eba1), + STC(0x5a82799a), STC(0x40000000), STC(0x2120fb83), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal48[] = { + STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), STC(0x7ba3751d), + STC(0x6ed9eba1), STC(0x5a82799a), STC(0x7641af3d), STC(0x5a82799a), + STC(0x30fbc54d), STC(0x6ed9eba1), STC(0x40000000), STC(0x00000000), + STC(0x658c9a2d), STC(0x2120fb83), STC(0xcf043ab3), STC(0x5a82799a), + STC(0x00000000), STC(0xa57d8666), STC(0x4debe4fe), STC(0xdedf047d), + STC(0x89be50c3), STC(0x40000000), STC(0xc0000000), STC(0x80000000), + STC(0x30fbc54d), STC(0xa57d8666), STC(0x89be50c3), STC(0x2120fb83), + STC(0x9126145f), STC(0xa57d8666), STC(0x10b5150f), STC(0x845c8ae3), + STC(0xcf043ab3), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag48[] = { + STC(0x10b5150f), STC(0x2120fb83), STC(0x30fbc54d), STC(0x2120fb83), + STC(0x40000000), STC(0x5a82799a), STC(0x30fbc54d), STC(0x5a82799a), + STC(0x7641af3d), STC(0x40000000), STC(0x6ed9eba1), STC(0x7fffffff), + STC(0x4debe4fe), STC(0x7ba3751d), STC(0x7641af3d), STC(0x5a82799a), + STC(0x7fffffff), STC(0x5a82799a), STC(0x658c9a2d), STC(0x7ba3751d), + STC(0x30fbc54d), STC(0x6ed9eba1), STC(0x6ed9eba1), STC(0x00000000), + STC(0x7641af3d), STC(0x5a82799a), STC(0xcf043ab3), STC(0x7ba3751d), + STC(0x40000000), STC(0xa57d8666), STC(0x7ee7aa4c), STC(0x2120fb83), + STC(0x89be50c3), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal80[] = { + STC(0x7f9afcb9), STC(0x7e6c9251), STC(0x7c769e18), STC(0x79bc384d), + STC(0x7e6c9251), STC(0x79bc384d), STC(0x720c8075), STC(0x678dde6e), + STC(0x7c769e18), STC(0x720c8075), STC(0x6154fb91), STC(0x4b3c8c12), + STC(0x79bc384d), STC(0x678dde6e), STC(0x4b3c8c12), STC(0x278dde6e), + STC(0x7641af3d), STC(0x5a82799a), STC(0x30fbc54d), STC(0x00000000), + STC(0x720c8075), STC(0x4b3c8c12), STC(0x14060b68), STC(0xd8722192), + STC(0x6d23501b), STC(0x3a1c5c57), STC(0xf5f50d67), STC(0xb4c373ee), + STC(0x678dde6e), STC(0x278dde6e), STC(0xd8722192), STC(0x98722192), + STC(0x6154fb91), STC(0x14060b68), STC(0xbd1ec45c), STC(0x8643c7b3), + STC(0x5a82799a), STC(0x00000000), STC(0xa57d8666), STC(0x80000000), + STC(0x53211d18), STC(0xebf9f498), STC(0x92dcafe5), STC(0x8643c7b3), + STC(0x4b3c8c12), STC(0xd8722192), STC(0x8643c7b3), STC(0x98722192), + STC(0x42e13ba4), STC(0xc5e3a3a9), STC(0x80650347), STC(0xb4c373ee), + STC(0x3a1c5c57), STC(0xb4c373ee), STC(0x81936daf), STC(0xd8722192), + STC(0x30fbc54d), STC(0xa57d8666), STC(0x89be50c3), STC(0x00000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag80[] = { + STC(0x0a0af299), STC(0x14060b68), STC(0x1de189a6), STC(0x278dde6e), + STC(0x14060b68), STC(0x278dde6e), STC(0x3a1c5c57), STC(0x4b3c8c12), + STC(0x1de189a6), STC(0x3a1c5c57), STC(0x53211d18), STC(0x678dde6e), + STC(0x278dde6e), STC(0x4b3c8c12), STC(0x678dde6e), STC(0x79bc384d), + STC(0x30fbc54d), STC(0x5a82799a), STC(0x7641af3d), STC(0x7fffffff), + STC(0x3a1c5c57), STC(0x678dde6e), STC(0x7e6c9251), STC(0x79bc384d), + STC(0x42e13ba4), STC(0x720c8075), STC(0x7f9afcb9), STC(0x678dde6e), + STC(0x4b3c8c12), STC(0x79bc384d), STC(0x79bc384d), STC(0x4b3c8c12), + STC(0x53211d18), STC(0x7e6c9251), STC(0x6d23501b), STC(0x278dde6e), + STC(0x5a82799a), STC(0x7fffffff), STC(0x5a82799a), STC(0x00000000), + STC(0x6154fb91), STC(0x7e6c9251), STC(0x42e13ba4), STC(0xd8722192), + STC(0x678dde6e), STC(0x79bc384d), STC(0x278dde6e), STC(0xb4c373ee), + STC(0x6d23501b), STC(0x720c8075), STC(0x0a0af299), STC(0x98722192), + STC(0x720c8075), STC(0x678dde6e), STC(0xebf9f498), STC(0x8643c7b3), + STC(0x7641af3d), STC(0x5a82799a), STC(0xcf043ab3), STC(0x80000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal96[] = { + STC(0x7fb9d759), STC(0x7ee7aa4c), STC(0x7ee7aa4c), STC(0x7ba3751d), + STC(0x7d8a5f40), STC(0x7641af3d), STC(0x7ba3751d), STC(0x6ed9eba1), + STC(0x793501a9), STC(0x658c9a2d), STC(0x7641af3d), STC(0x5a82799a), + STC(0x72ccb9db), STC(0x4debe4fe), STC(0x6ed9eba1), STC(0x40000000), + STC(0x6a6d98a4), STC(0x30fbc54d), STC(0x658c9a2d), STC(0x2120fb83), + STC(0x603c496c), STC(0x10b5150f), STC(0x5a82799a), STC(0x00000000), + STC(0x54657194), STC(0xef4aeaf1), STC(0x4debe4fe), STC(0xdedf047d), + STC(0x471cece7), STC(0xcf043ab3), STC(0x40000000), STC(0xc0000000), + STC(0x389cea72), STC(0xb2141b02), STC(0x30fbc54d), STC(0xa57d8666), + STC(0x2924edac), STC(0x9a7365d3), STC(0x2120fb83), STC(0x9126145f), + STC(0x18f8b83c), STC(0x89be50c3), STC(0x10b5150f), STC(0x845c8ae3), + STC(0x085f2137), STC(0x811855b4), STC(0x00000000), STC(0x80000000), + STC(0xf7a0dec9), STC(0x811855b4), STC(0xef4aeaf1), STC(0x845c8ae3), + STC(0xe70747c4), STC(0x89be50c3), STC(0xdedf047d), STC(0x9126145f), + STC(0xd6db1254), STC(0x9a7365d3), STC(0xcf043ab3), STC(0xa57d8666), + STC(0xc763158e), STC(0xb2141b02), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag96[] = { + STC(0x085f2137), STC(0x10b5150f), STC(0x10b5150f), STC(0x2120fb83), + STC(0x18f8b83c), STC(0x30fbc54d), STC(0x2120fb83), STC(0x40000000), + STC(0x2924edac), STC(0x4debe4fe), STC(0x30fbc54d), STC(0x5a82799a), + STC(0x389cea72), STC(0x658c9a2d), STC(0x40000000), STC(0x6ed9eba1), + STC(0x471cece7), STC(0x7641af3d), STC(0x4debe4fe), STC(0x7ba3751d), + STC(0x54657194), STC(0x7ee7aa4c), STC(0x5a82799a), STC(0x7fffffff), + STC(0x603c496c), STC(0x7ee7aa4c), STC(0x658c9a2d), STC(0x7ba3751d), + STC(0x6a6d98a4), STC(0x7641af3d), STC(0x6ed9eba1), STC(0x6ed9eba1), + STC(0x72ccb9db), STC(0x658c9a2d), STC(0x7641af3d), STC(0x5a82799a), + STC(0x793501a9), STC(0x4debe4fe), STC(0x7ba3751d), STC(0x40000000), + STC(0x7d8a5f40), STC(0x30fbc54d), STC(0x7ee7aa4c), STC(0x2120fb83), + STC(0x7fb9d759), STC(0x10b5150f), STC(0x7fffffff), STC(0x00000000), + STC(0x7fb9d759), STC(0xef4aeaf1), STC(0x7ee7aa4c), STC(0xdedf047d), + STC(0x7d8a5f40), STC(0xcf043ab3), STC(0x7ba3751d), STC(0xc0000000), + STC(0x793501a9), STC(0xb2141b02), STC(0x7641af3d), STC(0xa57d8666), + STC(0x72ccb9db), STC(0x9a7365d3), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal384[] = { + STC(0x7ffb9d15), STC(0x7fee74a2), STC(0x7fd8878e), STC(0x7fb9d759), + STC(0x7f92661d), STC(0x7f62368f), STC(0x7f294bfd), STC(0x7ee7aa4c), + STC(0x7e9d55fc), STC(0x7e4a5426), STC(0x7deeaa7a), STC(0x7fee74a2), + STC(0x7fb9d759), STC(0x7f62368f), STC(0x7ee7aa4c), STC(0x7e4a5426), + STC(0x7d8a5f40), STC(0x7ca80038), STC(0x7ba3751d), STC(0x7a7d055b), + STC(0x793501a9), STC(0x77cbc3f2), STC(0x7fd8878e), STC(0x7f62368f), + STC(0x7e9d55fc), STC(0x7d8a5f40), STC(0x7c29fbee), STC(0x7a7d055b), + STC(0x78848414), STC(0x7641af3d), STC(0x73b5ebd1), STC(0x70e2cbc6), + STC(0x6dca0d14), STC(0x7fb9d759), STC(0x7ee7aa4c), STC(0x7d8a5f40), + STC(0x7ba3751d), STC(0x793501a9), STC(0x7641af3d), STC(0x72ccb9db), + STC(0x6ed9eba1), STC(0x6a6d98a4), STC(0x658c9a2d), STC(0x603c496c), + STC(0x7f92661d), STC(0x7e4a5426), STC(0x7c29fbee), STC(0x793501a9), + STC(0x757075ac), STC(0x70e2cbc6), STC(0x6b93d02e), STC(0x658c9a2d), + STC(0x5ed77c8a), STC(0x577ff3da), STC(0x4f9292dc), STC(0x7f62368f), + STC(0x7d8a5f40), STC(0x7a7d055b), STC(0x7641af3d), STC(0x70e2cbc6), + STC(0x6a6d98a4), STC(0x62f201ac), STC(0x5a82799a), STC(0x5133cc94), + STC(0x471cece7), STC(0x3c56ba70), STC(0x7f294bfd), STC(0x7ca80038), + STC(0x78848414), STC(0x72ccb9db), STC(0x6b93d02e), STC(0x62f201ac), + STC(0x590443a7), STC(0x4debe4fe), STC(0x41ce1e65), STC(0x34d3957e), + STC(0x2727d486), STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), + STC(0x6ed9eba1), STC(0x658c9a2d), STC(0x5a82799a), STC(0x4debe4fe), + STC(0x40000000), STC(0x30fbc54d), STC(0x2120fb83), STC(0x10b5150f), + STC(0x7e9d55fc), STC(0x7a7d055b), STC(0x73b5ebd1), STC(0x6a6d98a4), + STC(0x5ed77c8a), STC(0x5133cc94), STC(0x41ce1e65), STC(0x30fbc54d), + STC(0x1f19f97b), STC(0x0c8bd35e), STC(0xf9b82684), STC(0x7e4a5426), + STC(0x793501a9), STC(0x70e2cbc6), STC(0x658c9a2d), STC(0x577ff3da), + STC(0x471cece7), STC(0x34d3957e), STC(0x2120fb83), STC(0x0c8bd35e), + STC(0xf7a0dec9), STC(0xe2ef2a3e), STC(0x7deeaa7a), STC(0x77cbc3f2), + STC(0x6dca0d14), STC(0x603c496c), STC(0x4f9292dc), STC(0x3c56ba70), + STC(0x2727d486), STC(0x10b5150f), STC(0xf9b82684), STC(0xe2ef2a3e), + STC(0xcd1693f7), STC(0x7d8a5f40), STC(0x7641af3d), STC(0x6a6d98a4), + STC(0x5a82799a), STC(0x471cece7), STC(0x30fbc54d), STC(0x18f8b83c), + STC(0x00000000), STC(0xe70747c4), STC(0xcf043ab3), STC(0xb8e31319), + STC(0x7d1d7958), STC(0x74972f92), STC(0x66cf8120), STC(0x54657194), + STC(0x3e2d7eb1), STC(0x25280c5e), STC(0x0a75d60e), STC(0xef4aeaf1), + STC(0xd4e0cb15), STC(0xbc6845ce), STC(0xa6fbbc59), STC(0x7ca80038), + STC(0x72ccb9db), STC(0x62f201ac), STC(0x4debe4fe), STC(0x34d3957e), + STC(0x18f8b83c), STC(0xfbcfdc71), STC(0xdedf047d), STC(0xc3a94590), + STC(0xab9a8e6c), STC(0x97f4a3cd), STC(0x7c29fbee), STC(0x70e2cbc6), + STC(0x5ed77c8a), STC(0x471cece7), STC(0x2b1f34eb), STC(0x0c8bd35e), + STC(0xed37ef91), STC(0xcf043ab3), STC(0xb3c0200c), STC(0x9d0dfe54), + STC(0x8c4a142f), STC(0x7ba3751d), STC(0x6ed9eba1), STC(0x5a82799a), + STC(0x40000000), STC(0x2120fb83), STC(0x00000000), STC(0xdedf047d), + STC(0xc0000000), STC(0xa57d8666), STC(0x9126145f), STC(0x845c8ae3), + STC(0x7b1474fd), STC(0x6cb2a837), STC(0x55f5a4d2), STC(0x389cea72), + STC(0x16ea0646), STC(0xf3742ca2), STC(0xd0f53ce0), STC(0xb2141b02), + STC(0x99307ee0), STC(0x88343c0e), STC(0x806d99e3), STC(0x7a7d055b), + STC(0x6a6d98a4), STC(0x5133cc94), STC(0x30fbc54d), STC(0x0c8bd35e), + STC(0xe70747c4), STC(0xc3a94590), STC(0xa57d8666), STC(0x8f1d343a), + STC(0x8275a0c0), STC(0x809dc971), STC(0x79dd3098), STC(0x680b5c33), + STC(0x4c3fdff4), STC(0x2924edac), STC(0x02182427), STC(0xdad7f3a2), + STC(0xb727b9f7), STC(0x9a7365d3), STC(0x877b7bec), STC(0x80118b5e), + STC(0x84eb8b03), STC(0x793501a9), STC(0x658c9a2d), STC(0x471cece7), + STC(0x2120fb83), STC(0xf7a0dec9), STC(0xcf043ab3), STC(0xab9a8e6c), + STC(0x9126145f), STC(0x8275a0c0), STC(0x811855b4), STC(0x8d334625), + STC(0x78848414), STC(0x62f201ac), STC(0x41ce1e65), STC(0x18f8b83c), + STC(0xed37ef91), STC(0xc3a94590), STC(0xa1288376), STC(0x89be50c3), + STC(0x80277872), STC(0x8582faa5), STC(0x99307ee0), STC(0x77cbc3f2), + STC(0x603c496c), STC(0x3c56ba70), STC(0x10b5150f), STC(0xe2ef2a3e), + STC(0xb8e31319), STC(0x97f4a3cd), STC(0x845c8ae3), STC(0x809dc971), + STC(0x8d334625), STC(0xa8800c26), STC(0x770acdec), STC(0x5d6c2f99), + STC(0x36ba2014), STC(0x085f2137), STC(0xd8d82b7a), STC(0xaecc336c), + STC(0x901dcec4), STC(0x811855b4), STC(0x83d60412), STC(0x97f4a3cd), + STC(0xbaa34bf4), STC(0x7641af3d), STC(0x5a82799a), STC(0x30fbc54d), + STC(0x00000000), STC(0xcf043ab3), STC(0xa57d8666), STC(0x89be50c3), + STC(0x80000000), STC(0x89be50c3), STC(0xa57d8666), STC(0xcf043ab3), + STC(0x757075ac), STC(0x577ff3da), STC(0x2b1f34eb), STC(0xf7a0dec9), + STC(0xc5842c7e), STC(0x9d0dfe54), STC(0x84eb8b03), STC(0x811855b4), + STC(0x9235f2ec), STC(0xb5715eef), STC(0xe4fa4bf1), STC(0x74972f92), + STC(0x54657194), STC(0x25280c5e), STC(0xef4aeaf1), STC(0xbc6845ce), + STC(0x9592675c), STC(0x81b5abda), STC(0x845c8ae3), STC(0x9d0dfe54), + STC(0xc763158e), STC(0xfbcfdc71), STC(0x73b5ebd1), STC(0x5133cc94), + STC(0x1f19f97b), STC(0xe70747c4), STC(0xb3c0200c), STC(0x8f1d343a), + STC(0x80277872), STC(0x89be50c3), STC(0xaa0a5b2e), STC(0xdad7f3a2), + STC(0x12c8106f), STC(0x72ccb9db), STC(0x4debe4fe), STC(0x18f8b83c), + STC(0xdedf047d), STC(0xab9a8e6c), STC(0x89be50c3), STC(0x804628a7), + STC(0x9126145f), STC(0xb8e31319), STC(0xef4aeaf1), STC(0x2924edac), + STC(0x71dba9ab), STC(0x4a8ea111), STC(0x12c8106f), STC(0xd6db1254), + STC(0xa405847e), STC(0x8582faa5), STC(0x82115586), STC(0x9a7365d3), + STC(0xc945dfec), STC(0x0430238f), STC(0x3e2d7eb1), STC(0x70e2cbc6), + STC(0x471cece7), STC(0x0c8bd35e), STC(0xcf043ab3), STC(0x9d0dfe54), + STC(0x8275a0c0), STC(0x8582faa5), STC(0xa57d8666), STC(0xdad7f3a2), + STC(0x18f8b83c), STC(0x5133cc94), STC(0x6fe2313c), STC(0x4397ba32), + STC(0x0647d97c), STC(0xc763158e), STC(0x96bfea3d), STC(0x809dc971), + STC(0x8a8f8a54), STC(0xb2141b02), STC(0xed37ef91), STC(0x2d168792), + STC(0x619a7dce), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag384[] = { + STC(0x02182427), STC(0x0430238f), STC(0x0647d97c), STC(0x085f2137), + STC(0x0a75d60e), STC(0x0c8bd35e), STC(0x0ea0f48c), STC(0x10b5150f), + STC(0x12c8106f), STC(0x14d9c245), STC(0x16ea0646), STC(0x0430238f), + STC(0x085f2137), STC(0x0c8bd35e), STC(0x10b5150f), STC(0x14d9c245), + STC(0x18f8b83c), STC(0x1d10d5c2), STC(0x2120fb83), STC(0x25280c5e), + STC(0x2924edac), STC(0x2d168792), STC(0x0647d97c), STC(0x0c8bd35e), + STC(0x12c8106f), STC(0x18f8b83c), STC(0x1f19f97b), STC(0x25280c5e), + STC(0x2b1f34eb), STC(0x30fbc54d), STC(0x36ba2014), STC(0x3c56ba70), + STC(0x41ce1e65), STC(0x085f2137), STC(0x10b5150f), STC(0x18f8b83c), + STC(0x2120fb83), STC(0x2924edac), STC(0x30fbc54d), STC(0x389cea72), + STC(0x40000000), STC(0x471cece7), STC(0x4debe4fe), STC(0x54657194), + STC(0x0a75d60e), STC(0x14d9c245), STC(0x1f19f97b), STC(0x2924edac), + STC(0x32e96c09), STC(0x3c56ba70), STC(0x455cb40c), STC(0x4debe4fe), + STC(0x55f5a4d2), STC(0x5d6c2f99), STC(0x6442bd7e), STC(0x0c8bd35e), + STC(0x18f8b83c), STC(0x25280c5e), STC(0x30fbc54d), STC(0x3c56ba70), + STC(0x471cece7), STC(0x5133cc94), STC(0x5a82799a), STC(0x62f201ac), + STC(0x6a6d98a4), STC(0x70e2cbc6), STC(0x0ea0f48c), STC(0x1d10d5c2), + STC(0x2b1f34eb), STC(0x389cea72), STC(0x455cb40c), STC(0x5133cc94), + STC(0x5bfa7b82), STC(0x658c9a2d), STC(0x6dca0d14), STC(0x74972f92), + STC(0x79dd3098), STC(0x10b5150f), STC(0x2120fb83), STC(0x30fbc54d), + STC(0x40000000), STC(0x4debe4fe), STC(0x5a82799a), STC(0x658c9a2d), + STC(0x6ed9eba1), STC(0x7641af3d), STC(0x7ba3751d), STC(0x7ee7aa4c), + STC(0x12c8106f), STC(0x25280c5e), STC(0x36ba2014), STC(0x471cece7), + STC(0x55f5a4d2), STC(0x62f201ac), STC(0x6dca0d14), STC(0x7641af3d), + STC(0x7c29fbee), STC(0x7f62368f), STC(0x7fd8878e), STC(0x14d9c245), + STC(0x2924edac), STC(0x3c56ba70), STC(0x4debe4fe), STC(0x5d6c2f99), + STC(0x6a6d98a4), STC(0x74972f92), STC(0x7ba3751d), STC(0x7f62368f), + STC(0x7fb9d759), STC(0x7ca80038), STC(0x16ea0646), STC(0x2d168792), + STC(0x41ce1e65), STC(0x54657194), STC(0x6442bd7e), STC(0x70e2cbc6), + STC(0x79dd3098), STC(0x7ee7aa4c), STC(0x7fd8878e), STC(0x7ca80038), + STC(0x757075ac), STC(0x18f8b83c), STC(0x30fbc54d), STC(0x471cece7), + STC(0x5a82799a), STC(0x6a6d98a4), STC(0x7641af3d), STC(0x7d8a5f40), + STC(0x7fffffff), STC(0x7d8a5f40), STC(0x7641af3d), STC(0x6a6d98a4), + STC(0x1b05b40f), STC(0x34d3957e), STC(0x4c3fdff4), STC(0x603c496c), + STC(0x6fe2313c), STC(0x7a7d055b), STC(0x7f92661d), STC(0x7ee7aa4c), + STC(0x78848414), STC(0x6cb2a837), STC(0x5bfa7b82), STC(0x1d10d5c2), + STC(0x389cea72), STC(0x5133cc94), STC(0x658c9a2d), STC(0x74972f92), + STC(0x7d8a5f40), STC(0x7fee74a2), STC(0x7ba3751d), STC(0x70e2cbc6), + STC(0x603c496c), STC(0x4a8ea111), STC(0x1f19f97b), STC(0x3c56ba70), + STC(0x55f5a4d2), STC(0x6a6d98a4), STC(0x78848414), STC(0x7f62368f), + STC(0x7e9d55fc), STC(0x7641af3d), STC(0x66cf8120), STC(0x5133cc94), + STC(0x36ba2014), STC(0x2120fb83), STC(0x40000000), STC(0x5a82799a), + STC(0x6ed9eba1), STC(0x7ba3751d), STC(0x7fffffff), STC(0x7ba3751d), + STC(0x6ed9eba1), STC(0x5a82799a), STC(0x40000000), STC(0x2120fb83), + STC(0x2325b847), STC(0x4397ba32), STC(0x5ed77c8a), STC(0x72ccb9db), + STC(0x7deeaa7a), STC(0x7f62368f), STC(0x770acdec), STC(0x658c9a2d), + STC(0x4c3fdff4), STC(0x2d168792), STC(0x0a75d60e), STC(0x25280c5e), + STC(0x471cece7), STC(0x62f201ac), STC(0x7641af3d), STC(0x7f62368f), + STC(0x7d8a5f40), STC(0x70e2cbc6), STC(0x5a82799a), STC(0x3c56ba70), + STC(0x18f8b83c), STC(0xf3742ca2), STC(0x2727d486), STC(0x4a8ea111), + STC(0x66cf8120), STC(0x793501a9), STC(0x7ffb9d15), STC(0x7a7d055b), + STC(0x694015c3), STC(0x4debe4fe), STC(0x2b1f34eb), STC(0x0430238f), + STC(0xdcda47b9), STC(0x2924edac), STC(0x4debe4fe), STC(0x6a6d98a4), + STC(0x7ba3751d), STC(0x7fb9d759), STC(0x7641af3d), STC(0x603c496c), + STC(0x40000000), STC(0x18f8b83c), STC(0xef4aeaf1), STC(0xc763158e), + STC(0x2b1f34eb), STC(0x5133cc94), STC(0x6dca0d14), STC(0x7d8a5f40), + STC(0x7e9d55fc), STC(0x70e2cbc6), STC(0x55f5a4d2), STC(0x30fbc54d), + STC(0x0647d97c), STC(0xdad7f3a2), STC(0xb3c0200c), STC(0x2d168792), + STC(0x54657194), STC(0x70e2cbc6), STC(0x7ee7aa4c), STC(0x7ca80038), + STC(0x6a6d98a4), STC(0x4a8ea111), STC(0x2120fb83), STC(0xf3742ca2), + STC(0xc763158e), STC(0xa293d067), STC(0x2f0ac320), STC(0x577ff3da), + STC(0x73b5ebd1), STC(0x7fb9d759), STC(0x79dd3098), STC(0x62f201ac), + STC(0x3e2d7eb1), STC(0x10b5150f), STC(0xe0e60685), STC(0xb5715eef), + STC(0x946c2fd2), STC(0x30fbc54d), STC(0x5a82799a), STC(0x7641af3d), + STC(0x7fffffff), STC(0x7641af3d), STC(0x5a82799a), STC(0x30fbc54d), + STC(0x00000000), STC(0xcf043ab3), STC(0xa57d8666), STC(0x89be50c3), + STC(0x32e96c09), STC(0x5d6c2f99), STC(0x78848414), STC(0x7fb9d759), + STC(0x71dba9ab), STC(0x5133cc94), STC(0x2325b847), STC(0xef4aeaf1), + STC(0xbe31e19b), STC(0x97f4a3cd), STC(0x82e286a8), STC(0x34d3957e), + STC(0x603c496c), STC(0x7a7d055b), STC(0x7ee7aa4c), STC(0x6cb2a837), + STC(0x471cece7), STC(0x14d9c245), STC(0xdedf047d), STC(0xaecc336c), + STC(0x8d334625), STC(0x80118b5e), STC(0x36ba2014), STC(0x62f201ac), + STC(0x7c29fbee), STC(0x7d8a5f40), STC(0x66cf8120), STC(0x3c56ba70), + STC(0x0647d97c), STC(0xcf043ab3), STC(0xa1288376), STC(0x8582faa5), + STC(0x8162aa04), STC(0x389cea72), STC(0x658c9a2d), STC(0x7d8a5f40), + STC(0x7ba3751d), STC(0x603c496c), STC(0x30fbc54d), STC(0xf7a0dec9), + STC(0xc0000000), STC(0x9592675c), STC(0x811855b4), STC(0x86cafe57), + STC(0x3a7bd382), STC(0x680b5c33), STC(0x7e9d55fc), STC(0x793501a9), + STC(0x590443a7), STC(0x25280c5e), STC(0xe915f9ba), STC(0xb2141b02), + STC(0x8c4a142f), STC(0x80118b5e), STC(0x901dcec4), STC(0x3c56ba70), + STC(0x6a6d98a4), STC(0x7f62368f), STC(0x7641af3d), STC(0x5133cc94), + STC(0x18f8b83c), STC(0xdad7f3a2), STC(0xa57d8666), STC(0x8582faa5), + STC(0x8275a0c0), STC(0x9d0dfe54), STC(0x3e2d7eb1), STC(0x6cb2a837), + STC(0x7fd8878e), STC(0x72ccb9db), STC(0x48d84609), STC(0x0c8bd35e), + STC(0xcd1693f7), STC(0x9a7365d3), STC(0x8162aa04), STC(0x88343c0e), + STC(0xad308a71), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal60[] = { + STC(0x7f4c7e54), STC(0x7d33f0ca), STC(0x79bc384d), STC(0x7d33f0ca), + STC(0x74ef0ebc), STC(0x678dde6e), STC(0x79bc384d), STC(0x678dde6e), + STC(0x4b3c8c12), STC(0x74ef0ebc), STC(0x55a6125c), STC(0x278dde6e), + STC(0x6ed9eba1), STC(0x40000000), STC(0x00000000), STC(0x678dde6e), + STC(0x278dde6e), STC(0xd8722192), STC(0x5f1f5ea1), STC(0x0d61304e), + STC(0xb4c373ee), STC(0x55a6125c), STC(0xf29ecfb2), STC(0x98722192), + STC(0x4b3c8c12), STC(0xd8722192), STC(0x8643c7b3), STC(0x40000000), + STC(0xc0000000), STC(0x80000000), STC(0x340ff242), STC(0xaa59eda4), + STC(0x8643c7b3), STC(0x278dde6e), STC(0x98722192), STC(0x98722192), + STC(0x1a9cd9ac), STC(0x8b10f144), STC(0xb4c373ee), STC(0x0d61304e), + STC(0x82cc0f36), STC(0xd8722192), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag60[] = { + STC(0x0d61304e), STC(0x1a9cd9ac), STC(0x278dde6e), STC(0x1a9cd9ac), + STC(0x340ff242), STC(0x4b3c8c12), STC(0x278dde6e), STC(0x4b3c8c12), + STC(0x678dde6e), STC(0x340ff242), STC(0x5f1f5ea1), STC(0x79bc384d), + STC(0x40000000), STC(0x6ed9eba1), STC(0x7fffffff), STC(0x4b3c8c12), + STC(0x79bc384d), STC(0x79bc384d), STC(0x55a6125c), STC(0x7f4c7e54), + STC(0x678dde6e), STC(0x5f1f5ea1), STC(0x7f4c7e54), STC(0x4b3c8c12), + STC(0x678dde6e), STC(0x79bc384d), STC(0x278dde6e), STC(0x6ed9eba1), + STC(0x6ed9eba1), STC(0x00000000), STC(0x74ef0ebc), STC(0x5f1f5ea1), + STC(0xd8722192), STC(0x79bc384d), STC(0x4b3c8c12), STC(0xb4c373ee), + STC(0x7d33f0ca), STC(0x340ff242), STC(0x98722192), STC(0x7f4c7e54), + STC(0x1a9cd9ac), STC(0x8643c7b3), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal120[] = { + STC(0x7fd317b4), STC(0x7f4c7e54), STC(0x7e6c9251), STC(0x7d33f0ca), + STC(0x7ba3751d), STC(0x79bc384d), STC(0x777f903c), STC(0x7f4c7e54), + STC(0x7d33f0ca), STC(0x79bc384d), STC(0x74ef0ebc), STC(0x6ed9eba1), + STC(0x678dde6e), STC(0x5f1f5ea1), STC(0x7e6c9251), STC(0x79bc384d), + STC(0x720c8075), STC(0x678dde6e), STC(0x5a82799a), STC(0x4b3c8c12), + STC(0x3a1c5c57), STC(0x7d33f0ca), STC(0x74ef0ebc), STC(0x678dde6e), + STC(0x55a6125c), STC(0x40000000), STC(0x278dde6e), STC(0x0d61304e), + STC(0x7ba3751d), STC(0x6ed9eba1), STC(0x5a82799a), STC(0x40000000), + STC(0x2120fb83), STC(0x00000000), STC(0xdedf047d), STC(0x79bc384d), + STC(0x678dde6e), STC(0x4b3c8c12), STC(0x278dde6e), STC(0x00000000), + STC(0xd8722192), STC(0xb4c373ee), STC(0x777f903c), STC(0x5f1f5ea1), + STC(0x3a1c5c57), STC(0x0d61304e), STC(0xdedf047d), STC(0xb4c373ee), + STC(0x94a6715d), STC(0x74ef0ebc), STC(0x55a6125c), STC(0x278dde6e), + STC(0xf29ecfb2), STC(0xc0000000), STC(0x98722192), STC(0x82cc0f36), + STC(0x720c8075), STC(0x4b3c8c12), STC(0x14060b68), STC(0xd8722192), + STC(0xa57d8666), STC(0x8643c7b3), STC(0x81936daf), STC(0x6ed9eba1), + STC(0x40000000), STC(0x00000000), STC(0xc0000000), STC(0x9126145f), + STC(0x80000000), STC(0x9126145f), STC(0x6b598ea3), STC(0x340ff242), + STC(0xebf9f498), STC(0xaa59eda4), STC(0x845c8ae3), STC(0x8643c7b3), + STC(0xaf726def), STC(0x678dde6e), STC(0x278dde6e), STC(0xd8722192), + STC(0x98722192), STC(0x80000000), STC(0x98722192), STC(0xd8722192), + STC(0x637984d4), STC(0x1a9cd9ac), STC(0xc5e3a3a9), STC(0x8b10f144), + STC(0x845c8ae3), STC(0xb4c373ee), STC(0x06b2f1d2), STC(0x5f1f5ea1), + STC(0x0d61304e), STC(0xb4c373ee), STC(0x82cc0f36), STC(0x9126145f), + STC(0xd8722192), STC(0x340ff242), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag120[] = { + STC(0x06b2f1d2), STC(0x0d61304e), STC(0x14060b68), STC(0x1a9cd9ac), + STC(0x2120fb83), STC(0x278dde6e), STC(0x2ddf0040), STC(0x0d61304e), + STC(0x1a9cd9ac), STC(0x278dde6e), STC(0x340ff242), STC(0x40000000), + STC(0x4b3c8c12), STC(0x55a6125c), STC(0x14060b68), STC(0x278dde6e), + STC(0x3a1c5c57), STC(0x4b3c8c12), STC(0x5a82799a), STC(0x678dde6e), + STC(0x720c8075), STC(0x1a9cd9ac), STC(0x340ff242), STC(0x4b3c8c12), + STC(0x5f1f5ea1), STC(0x6ed9eba1), STC(0x79bc384d), STC(0x7f4c7e54), + STC(0x2120fb83), STC(0x40000000), STC(0x5a82799a), STC(0x6ed9eba1), + STC(0x7ba3751d), STC(0x7fffffff), STC(0x7ba3751d), STC(0x278dde6e), + STC(0x4b3c8c12), STC(0x678dde6e), STC(0x79bc384d), STC(0x7fffffff), + STC(0x79bc384d), STC(0x678dde6e), STC(0x2ddf0040), STC(0x55a6125c), + STC(0x720c8075), STC(0x7f4c7e54), STC(0x7ba3751d), STC(0x678dde6e), + STC(0x45b6bb5e), STC(0x340ff242), STC(0x5f1f5ea1), STC(0x79bc384d), + STC(0x7f4c7e54), STC(0x6ed9eba1), STC(0x4b3c8c12), STC(0x1a9cd9ac), + STC(0x3a1c5c57), STC(0x678dde6e), STC(0x7e6c9251), STC(0x79bc384d), + STC(0x5a82799a), STC(0x278dde6e), STC(0xebf9f498), STC(0x40000000), + STC(0x6ed9eba1), STC(0x7fffffff), STC(0x6ed9eba1), STC(0x40000000), + STC(0x00000000), STC(0xc0000000), STC(0x45b6bb5e), STC(0x74ef0ebc), + STC(0x7e6c9251), STC(0x5f1f5ea1), STC(0x2120fb83), STC(0xd8722192), + STC(0x9c867b2c), STC(0x4b3c8c12), STC(0x79bc384d), STC(0x79bc384d), + STC(0x4b3c8c12), STC(0x00000000), STC(0xb4c373ee), STC(0x8643c7b3), + STC(0x508d9211), STC(0x7d33f0ca), STC(0x720c8075), STC(0x340ff242), + STC(0xdedf047d), STC(0x98722192), STC(0x802ce84c), STC(0x55a6125c), + STC(0x7f4c7e54), STC(0x678dde6e), STC(0x1a9cd9ac), STC(0xc0000000), + STC(0x8643c7b3), STC(0x8b10f144), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal192[] = { + STC(0x7fee74a2), STC(0x7fb9d759), STC(0x7f62368f), STC(0x7ee7aa4c), + STC(0x7e4a5426), STC(0x7d8a5f40), STC(0x7ca80038), STC(0x7ba3751d), + STC(0x7a7d055b), STC(0x793501a9), STC(0x77cbc3f2), STC(0x7641af3d), + STC(0x74972f92), STC(0x72ccb9db), STC(0x70e2cbc6), STC(0x7fb9d759), + STC(0x7ee7aa4c), STC(0x7d8a5f40), STC(0x7ba3751d), STC(0x793501a9), + STC(0x7641af3d), STC(0x72ccb9db), STC(0x6ed9eba1), STC(0x6a6d98a4), + STC(0x658c9a2d), STC(0x603c496c), STC(0x5a82799a), STC(0x54657194), + STC(0x4debe4fe), STC(0x471cece7), STC(0x7f62368f), STC(0x7d8a5f40), + STC(0x7a7d055b), STC(0x7641af3d), STC(0x70e2cbc6), STC(0x6a6d98a4), + STC(0x62f201ac), STC(0x5a82799a), STC(0x5133cc94), STC(0x471cece7), + STC(0x3c56ba70), STC(0x30fbc54d), STC(0x25280c5e), STC(0x18f8b83c), + STC(0x0c8bd35e), STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), + STC(0x6ed9eba1), STC(0x658c9a2d), STC(0x5a82799a), STC(0x4debe4fe), + STC(0x40000000), STC(0x30fbc54d), STC(0x2120fb83), STC(0x10b5150f), + STC(0x00000000), STC(0xef4aeaf1), STC(0xdedf047d), STC(0xcf043ab3), + STC(0x7e4a5426), STC(0x793501a9), STC(0x70e2cbc6), STC(0x658c9a2d), + STC(0x577ff3da), STC(0x471cece7), STC(0x34d3957e), STC(0x2120fb83), + STC(0x0c8bd35e), STC(0xf7a0dec9), STC(0xe2ef2a3e), STC(0xcf043ab3), + STC(0xbc6845ce), STC(0xab9a8e6c), STC(0x9d0dfe54), STC(0x7d8a5f40), + STC(0x7641af3d), STC(0x6a6d98a4), STC(0x5a82799a), STC(0x471cece7), + STC(0x30fbc54d), STC(0x18f8b83c), STC(0x00000000), STC(0xe70747c4), + STC(0xcf043ab3), STC(0xb8e31319), STC(0xa57d8666), STC(0x9592675c), + STC(0x89be50c3), STC(0x8275a0c0), STC(0x7ca80038), STC(0x72ccb9db), + STC(0x62f201ac), STC(0x4debe4fe), STC(0x34d3957e), STC(0x18f8b83c), + STC(0xfbcfdc71), STC(0xdedf047d), STC(0xc3a94590), STC(0xab9a8e6c), + STC(0x97f4a3cd), STC(0x89be50c3), STC(0x81b5abda), STC(0x804628a7), + STC(0x8582faa5), STC(0x7ba3751d), STC(0x6ed9eba1), STC(0x5a82799a), + STC(0x40000000), STC(0x2120fb83), STC(0x00000000), STC(0xdedf047d), + STC(0xc0000000), STC(0xa57d8666), STC(0x9126145f), STC(0x845c8ae3), + STC(0x80000000), STC(0x845c8ae3), STC(0x9126145f), STC(0xa57d8666), + STC(0x7a7d055b), STC(0x6a6d98a4), STC(0x5133cc94), STC(0x30fbc54d), + STC(0x0c8bd35e), STC(0xe70747c4), STC(0xc3a94590), STC(0xa57d8666), + STC(0x8f1d343a), STC(0x8275a0c0), STC(0x809dc971), STC(0x89be50c3), + STC(0x9d0dfe54), STC(0xb8e31319), STC(0xdad7f3a2), STC(0x793501a9), + STC(0x658c9a2d), STC(0x471cece7), STC(0x2120fb83), STC(0xf7a0dec9), + STC(0xcf043ab3), STC(0xab9a8e6c), STC(0x9126145f), STC(0x8275a0c0), + STC(0x811855b4), STC(0x8d334625), STC(0xa57d8666), STC(0xc763158e), + STC(0xef4aeaf1), STC(0x18f8b83c), STC(0x77cbc3f2), STC(0x603c496c), + STC(0x3c56ba70), STC(0x10b5150f), STC(0xe2ef2a3e), STC(0xb8e31319), + STC(0x97f4a3cd), STC(0x845c8ae3), STC(0x809dc971), STC(0x8d334625), + STC(0xa8800c26), STC(0xcf043ab3), STC(0xfbcfdc71), STC(0x2924edac), + STC(0x5133cc94), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag192[] = { + STC(0x0430238f), STC(0x085f2137), STC(0x0c8bd35e), STC(0x10b5150f), + STC(0x14d9c245), STC(0x18f8b83c), STC(0x1d10d5c2), STC(0x2120fb83), + STC(0x25280c5e), STC(0x2924edac), STC(0x2d168792), STC(0x30fbc54d), + STC(0x34d3957e), STC(0x389cea72), STC(0x3c56ba70), STC(0x085f2137), + STC(0x10b5150f), STC(0x18f8b83c), STC(0x2120fb83), STC(0x2924edac), + STC(0x30fbc54d), STC(0x389cea72), STC(0x40000000), STC(0x471cece7), + STC(0x4debe4fe), STC(0x54657194), STC(0x5a82799a), STC(0x603c496c), + STC(0x658c9a2d), STC(0x6a6d98a4), STC(0x0c8bd35e), STC(0x18f8b83c), + STC(0x25280c5e), STC(0x30fbc54d), STC(0x3c56ba70), STC(0x471cece7), + STC(0x5133cc94), STC(0x5a82799a), STC(0x62f201ac), STC(0x6a6d98a4), + STC(0x70e2cbc6), STC(0x7641af3d), STC(0x7a7d055b), STC(0x7d8a5f40), + STC(0x7f62368f), STC(0x10b5150f), STC(0x2120fb83), STC(0x30fbc54d), + STC(0x40000000), STC(0x4debe4fe), STC(0x5a82799a), STC(0x658c9a2d), + STC(0x6ed9eba1), STC(0x7641af3d), STC(0x7ba3751d), STC(0x7ee7aa4c), + STC(0x7fffffff), STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), + STC(0x14d9c245), STC(0x2924edac), STC(0x3c56ba70), STC(0x4debe4fe), + STC(0x5d6c2f99), STC(0x6a6d98a4), STC(0x74972f92), STC(0x7ba3751d), + STC(0x7f62368f), STC(0x7fb9d759), STC(0x7ca80038), STC(0x7641af3d), + STC(0x6cb2a837), STC(0x603c496c), STC(0x5133cc94), STC(0x18f8b83c), + STC(0x30fbc54d), STC(0x471cece7), STC(0x5a82799a), STC(0x6a6d98a4), + STC(0x7641af3d), STC(0x7d8a5f40), STC(0x7fffffff), STC(0x7d8a5f40), + STC(0x7641af3d), STC(0x6a6d98a4), STC(0x5a82799a), STC(0x471cece7), + STC(0x30fbc54d), STC(0x18f8b83c), STC(0x1d10d5c2), STC(0x389cea72), + STC(0x5133cc94), STC(0x658c9a2d), STC(0x74972f92), STC(0x7d8a5f40), + STC(0x7fee74a2), STC(0x7ba3751d), STC(0x70e2cbc6), STC(0x603c496c), + STC(0x4a8ea111), STC(0x30fbc54d), STC(0x14d9c245), STC(0xf7a0dec9), + STC(0xdad7f3a2), STC(0x2120fb83), STC(0x40000000), STC(0x5a82799a), + STC(0x6ed9eba1), STC(0x7ba3751d), STC(0x7fffffff), STC(0x7ba3751d), + STC(0x6ed9eba1), STC(0x5a82799a), STC(0x40000000), STC(0x2120fb83), + STC(0x00000000), STC(0xdedf047d), STC(0xc0000000), STC(0xa57d8666), + STC(0x25280c5e), STC(0x471cece7), STC(0x62f201ac), STC(0x7641af3d), + STC(0x7f62368f), STC(0x7d8a5f40), STC(0x70e2cbc6), STC(0x5a82799a), + STC(0x3c56ba70), STC(0x18f8b83c), STC(0xf3742ca2), STC(0xcf043ab3), + STC(0xaecc336c), STC(0x9592675c), STC(0x8582faa5), STC(0x2924edac), + STC(0x4debe4fe), STC(0x6a6d98a4), STC(0x7ba3751d), STC(0x7fb9d759), + STC(0x7641af3d), STC(0x603c496c), STC(0x40000000), STC(0x18f8b83c), + STC(0xef4aeaf1), STC(0xc763158e), STC(0xa57d8666), STC(0x8d334625), + STC(0x811855b4), STC(0x8275a0c0), STC(0x2d168792), STC(0x54657194), + STC(0x70e2cbc6), STC(0x7ee7aa4c), STC(0x7ca80038), STC(0x6a6d98a4), + STC(0x4a8ea111), STC(0x2120fb83), STC(0xf3742ca2), STC(0xc763158e), + STC(0xa293d067), STC(0x89be50c3), STC(0x80118b5e), STC(0x86cafe57), + STC(0x9d0dfe54), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal240[] = { + STC(0x7ff4c56f), STC(0x7fd317b4), STC(0x7f9afcb9), STC(0x7f4c7e54), + STC(0x7ee7aa4c), STC(0x7e6c9251), STC(0x7ddb4bfc), STC(0x7d33f0ca), + STC(0x7c769e18), STC(0x7ba3751d), STC(0x7aba9ae6), STC(0x79bc384d), + STC(0x78a879f4), STC(0x777f903c), STC(0x7641af3d), STC(0x7fd317b4), + STC(0x7f4c7e54), STC(0x7e6c9251), STC(0x7d33f0ca), STC(0x7ba3751d), + STC(0x79bc384d), STC(0x777f903c), STC(0x74ef0ebc), STC(0x720c8075), + STC(0x6ed9eba1), STC(0x6b598ea3), STC(0x678dde6e), STC(0x637984d4), + STC(0x5f1f5ea1), STC(0x5a82799a), STC(0x7f9afcb9), STC(0x7e6c9251), + STC(0x7c769e18), STC(0x79bc384d), STC(0x7641af3d), STC(0x720c8075), + STC(0x6d23501b), STC(0x678dde6e), STC(0x6154fb91), STC(0x5a82799a), + STC(0x53211d18), STC(0x4b3c8c12), STC(0x42e13ba4), STC(0x3a1c5c57), + STC(0x30fbc54d), STC(0x7f4c7e54), STC(0x7d33f0ca), STC(0x79bc384d), + STC(0x74ef0ebc), STC(0x6ed9eba1), STC(0x678dde6e), STC(0x5f1f5ea1), + STC(0x55a6125c), STC(0x4b3c8c12), STC(0x40000000), STC(0x340ff242), + STC(0x278dde6e), STC(0x1a9cd9ac), STC(0x0d61304e), STC(0x00000000), + STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), STC(0x6ed9eba1), + STC(0x658c9a2d), STC(0x5a82799a), STC(0x4debe4fe), STC(0x40000000), + STC(0x30fbc54d), STC(0x2120fb83), STC(0x10b5150f), STC(0x00000000), + STC(0xef4aeaf1), STC(0xdedf047d), STC(0xcf043ab3), STC(0x7e6c9251), + STC(0x79bc384d), STC(0x720c8075), STC(0x678dde6e), STC(0x5a82799a), + STC(0x4b3c8c12), STC(0x3a1c5c57), STC(0x278dde6e), STC(0x14060b68), + STC(0x00000000), STC(0xebf9f498), STC(0xd8722192), STC(0xc5e3a3a9), + STC(0xb4c373ee), STC(0xa57d8666), STC(0x7ddb4bfc), STC(0x777f903c), + STC(0x6d23501b), STC(0x5f1f5ea1), STC(0x4debe4fe), STC(0x3a1c5c57), + STC(0x245a9d65), STC(0x0d61304e), STC(0xf5f50d67), STC(0xdedf047d), + STC(0xc8e5032b), STC(0xb4c373ee), STC(0xa326eec0), STC(0x94a6715d), + STC(0x89be50c3), STC(0x7d33f0ca), STC(0x74ef0ebc), STC(0x678dde6e), + STC(0x55a6125c), STC(0x40000000), STC(0x278dde6e), STC(0x0d61304e), + STC(0xf29ecfb2), STC(0xd8722192), STC(0xc0000000), STC(0xaa59eda4), + STC(0x98722192), STC(0x8b10f144), STC(0x82cc0f36), STC(0x80000000), + STC(0x7c769e18), STC(0x720c8075), STC(0x6154fb91), STC(0x4b3c8c12), + STC(0x30fbc54d), STC(0x14060b68), STC(0xf5f50d67), STC(0xd8722192), + STC(0xbd1ec45c), STC(0xa57d8666), STC(0x92dcafe5), STC(0x8643c7b3), + STC(0x80650347), STC(0x81936daf), STC(0x89be50c3), STC(0x7ba3751d), + STC(0x6ed9eba1), STC(0x5a82799a), STC(0x40000000), STC(0x2120fb83), + STC(0x00000000), STC(0xdedf047d), STC(0xc0000000), STC(0xa57d8666), + STC(0x9126145f), STC(0x845c8ae3), STC(0x80000000), STC(0x845c8ae3), + STC(0x9126145f), STC(0xa57d8666), STC(0x7aba9ae6), STC(0x6b598ea3), + STC(0x53211d18), STC(0x340ff242), STC(0x10b5150f), STC(0xebf9f498), + STC(0xc8e5032b), STC(0xaa59eda4), STC(0x92dcafe5), STC(0x845c8ae3), + STC(0x800b3a91), STC(0x8643c7b3), STC(0x96830876), STC(0xaf726def), + STC(0xcf043ab3), STC(0x79bc384d), STC(0x678dde6e), STC(0x4b3c8c12), + STC(0x278dde6e), STC(0x00000000), STC(0xd8722192), STC(0xb4c373ee), + STC(0x98722192), STC(0x8643c7b3), STC(0x80000000), STC(0x8643c7b3), + STC(0x98722192), STC(0xb4c373ee), STC(0xd8722192), STC(0x00000000), + STC(0x78a879f4), STC(0x637984d4), STC(0x42e13ba4), STC(0x1a9cd9ac), + STC(0xef4aeaf1), STC(0xc5e3a3a9), STC(0xa326eec0), STC(0x8b10f144), + STC(0x80650347), STC(0x845c8ae3), STC(0x96830876), STC(0xb4c373ee), + STC(0xdba5629b), STC(0x06b2f1d2), STC(0x30fbc54d), STC(0x777f903c), + STC(0x5f1f5ea1), STC(0x3a1c5c57), STC(0x0d61304e), STC(0xdedf047d), + STC(0xb4c373ee), STC(0x94a6715d), STC(0x82cc0f36), STC(0x81936daf), + STC(0x9126145f), STC(0xaf726def), STC(0xd8722192), STC(0x06b2f1d2), + STC(0x340ff242), STC(0x5a82799a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag240[] = { + STC(0x0359c428), STC(0x06b2f1d2), STC(0x0a0af299), STC(0x0d61304e), + STC(0x10b5150f), STC(0x14060b68), STC(0x17537e63), STC(0x1a9cd9ac), + STC(0x1de189a6), STC(0x2120fb83), STC(0x245a9d65), STC(0x278dde6e), + STC(0x2aba2ee4), STC(0x2ddf0040), STC(0x30fbc54d), STC(0x06b2f1d2), + STC(0x0d61304e), STC(0x14060b68), STC(0x1a9cd9ac), STC(0x2120fb83), + STC(0x278dde6e), STC(0x2ddf0040), STC(0x340ff242), STC(0x3a1c5c57), + STC(0x40000000), STC(0x45b6bb5e), STC(0x4b3c8c12), STC(0x508d9211), + STC(0x55a6125c), STC(0x5a82799a), STC(0x0a0af299), STC(0x14060b68), + STC(0x1de189a6), STC(0x278dde6e), STC(0x30fbc54d), STC(0x3a1c5c57), + STC(0x42e13ba4), STC(0x4b3c8c12), STC(0x53211d18), STC(0x5a82799a), + STC(0x6154fb91), STC(0x678dde6e), STC(0x6d23501b), STC(0x720c8075), + STC(0x7641af3d), STC(0x0d61304e), STC(0x1a9cd9ac), STC(0x278dde6e), + STC(0x340ff242), STC(0x40000000), STC(0x4b3c8c12), STC(0x55a6125c), + STC(0x5f1f5ea1), STC(0x678dde6e), STC(0x6ed9eba1), STC(0x74ef0ebc), + STC(0x79bc384d), STC(0x7d33f0ca), STC(0x7f4c7e54), STC(0x7fffffff), + STC(0x10b5150f), STC(0x2120fb83), STC(0x30fbc54d), STC(0x40000000), + STC(0x4debe4fe), STC(0x5a82799a), STC(0x658c9a2d), STC(0x6ed9eba1), + STC(0x7641af3d), STC(0x7ba3751d), STC(0x7ee7aa4c), STC(0x7fffffff), + STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), STC(0x14060b68), + STC(0x278dde6e), STC(0x3a1c5c57), STC(0x4b3c8c12), STC(0x5a82799a), + STC(0x678dde6e), STC(0x720c8075), STC(0x79bc384d), STC(0x7e6c9251), + STC(0x7fffffff), STC(0x7e6c9251), STC(0x79bc384d), STC(0x720c8075), + STC(0x678dde6e), STC(0x5a82799a), STC(0x17537e63), STC(0x2ddf0040), + STC(0x42e13ba4), STC(0x55a6125c), STC(0x658c9a2d), STC(0x720c8075), + STC(0x7aba9ae6), STC(0x7f4c7e54), STC(0x7f9afcb9), STC(0x7ba3751d), + STC(0x7387ea23), STC(0x678dde6e), STC(0x581c00b3), STC(0x45b6bb5e), + STC(0x30fbc54d), STC(0x1a9cd9ac), STC(0x340ff242), STC(0x4b3c8c12), + STC(0x5f1f5ea1), STC(0x6ed9eba1), STC(0x79bc384d), STC(0x7f4c7e54), + STC(0x7f4c7e54), STC(0x79bc384d), STC(0x6ed9eba1), STC(0x5f1f5ea1), + STC(0x4b3c8c12), STC(0x340ff242), STC(0x1a9cd9ac), STC(0x00000000), + STC(0x1de189a6), STC(0x3a1c5c57), STC(0x53211d18), STC(0x678dde6e), + STC(0x7641af3d), STC(0x7e6c9251), STC(0x7f9afcb9), STC(0x79bc384d), + STC(0x6d23501b), STC(0x5a82799a), STC(0x42e13ba4), STC(0x278dde6e), + STC(0x0a0af299), STC(0xebf9f498), STC(0xcf043ab3), STC(0x2120fb83), + STC(0x40000000), STC(0x5a82799a), STC(0x6ed9eba1), STC(0x7ba3751d), + STC(0x7fffffff), STC(0x7ba3751d), STC(0x6ed9eba1), STC(0x5a82799a), + STC(0x40000000), STC(0x2120fb83), STC(0x00000000), STC(0xdedf047d), + STC(0xc0000000), STC(0xa57d8666), STC(0x245a9d65), STC(0x45b6bb5e), + STC(0x6154fb91), STC(0x74ef0ebc), STC(0x7ee7aa4c), STC(0x7e6c9251), + STC(0x7387ea23), STC(0x5f1f5ea1), STC(0x42e13ba4), STC(0x2120fb83), + STC(0xfca63bd8), STC(0xd8722192), STC(0xb780001c), STC(0x9c867b2c), + STC(0x89be50c3), STC(0x278dde6e), STC(0x4b3c8c12), STC(0x678dde6e), + STC(0x79bc384d), STC(0x7fffffff), STC(0x79bc384d), STC(0x678dde6e), + STC(0x4b3c8c12), STC(0x278dde6e), STC(0x00000000), STC(0xd8722192), + STC(0xb4c373ee), STC(0x98722192), STC(0x8643c7b3), STC(0x80000000), + STC(0x2aba2ee4), STC(0x508d9211), STC(0x6d23501b), STC(0x7d33f0ca), + STC(0x7ee7aa4c), STC(0x720c8075), STC(0x581c00b3), STC(0x340ff242), + STC(0x0a0af299), STC(0xdedf047d), STC(0xb780001c), STC(0x98722192), + STC(0x8545651a), STC(0x802ce84c), STC(0x89be50c3), STC(0x2ddf0040), + STC(0x55a6125c), STC(0x720c8075), STC(0x7f4c7e54), STC(0x7ba3751d), + STC(0x678dde6e), STC(0x45b6bb5e), STC(0x1a9cd9ac), STC(0xebf9f498), + STC(0xc0000000), STC(0x9c867b2c), STC(0x8643c7b3), STC(0x802ce84c), + STC(0x8b10f144), STC(0xa57d8666), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal480[] = { + STC(0x7ffd3154), STC(0x7ff4c56f), STC(0x7fe6bcb0), STC(0x7fd317b4), + STC(0x7fb9d759), STC(0x7f9afcb9), STC(0x7f76892f), STC(0x7f4c7e54), + STC(0x7f1cde01), STC(0x7ee7aa4c), STC(0x7eace58a), STC(0x7e6c9251), + STC(0x7e26b371), STC(0x7ddb4bfc), STC(0x7d8a5f40), STC(0x7d33f0ca), + STC(0x7cd80464), STC(0x7c769e18), STC(0x7c0fc22a), STC(0x7ba3751d), + STC(0x7b31bbb2), STC(0x7aba9ae6), STC(0x7a3e17f2), STC(0x79bc384d), + STC(0x793501a9), STC(0x78a879f4), STC(0x7816a759), STC(0x777f903c), + STC(0x76e33b3f), STC(0x7641af3d), STC(0x759af34c), STC(0x7ff4c56f), + STC(0x7fd317b4), STC(0x7f9afcb9), STC(0x7f4c7e54), STC(0x7ee7aa4c), + STC(0x7e6c9251), STC(0x7ddb4bfc), STC(0x7d33f0ca), STC(0x7c769e18), + STC(0x7ba3751d), STC(0x7aba9ae6), STC(0x79bc384d), STC(0x78a879f4), + STC(0x777f903c), STC(0x7641af3d), STC(0x74ef0ebc), STC(0x7387ea23), + STC(0x720c8075), STC(0x707d1443), STC(0x6ed9eba1), STC(0x6d23501b), + STC(0x6b598ea3), STC(0x697cf78a), STC(0x678dde6e), STC(0x658c9a2d), + STC(0x637984d4), STC(0x6154fb91), STC(0x5f1f5ea1), STC(0x5cd91140), + STC(0x5a82799a), STC(0x581c00b3), STC(0x7fe6bcb0), STC(0x7f9afcb9), + STC(0x7f1cde01), STC(0x7e6c9251), STC(0x7d8a5f40), STC(0x7c769e18), + STC(0x7b31bbb2), STC(0x79bc384d), STC(0x7816a759), STC(0x7641af3d), + STC(0x743e0918), STC(0x720c8075), STC(0x6fadf2fc), STC(0x6d23501b), + STC(0x6a6d98a4), STC(0x678dde6e), STC(0x648543e4), STC(0x6154fb91), + STC(0x5dfe47ad), STC(0x5a82799a), STC(0x56e2f15d), STC(0x53211d18), + STC(0x4f3e7875), STC(0x4b3c8c12), STC(0x471cece7), STC(0x42e13ba4), + STC(0x3e8b240e), STC(0x3a1c5c57), STC(0x3596a46c), STC(0x30fbc54d), + STC(0x2c4d9050), STC(0x7fd317b4), STC(0x7f4c7e54), STC(0x7e6c9251), + STC(0x7d33f0ca), STC(0x7ba3751d), STC(0x79bc384d), STC(0x777f903c), + STC(0x74ef0ebc), STC(0x720c8075), STC(0x6ed9eba1), STC(0x6b598ea3), + STC(0x678dde6e), STC(0x637984d4), STC(0x5f1f5ea1), STC(0x5a82799a), + STC(0x55a6125c), STC(0x508d9211), STC(0x4b3c8c12), STC(0x45b6bb5e), + STC(0x40000000), STC(0x3a1c5c57), STC(0x340ff242), STC(0x2ddf0040), + STC(0x278dde6e), STC(0x2120fb83), STC(0x1a9cd9ac), STC(0x14060b68), + STC(0x0d61304e), STC(0x06b2f1d2), STC(0x00000000), STC(0xf94d0e2e), + STC(0x7fb9d759), STC(0x7ee7aa4c), STC(0x7d8a5f40), STC(0x7ba3751d), + STC(0x793501a9), STC(0x7641af3d), STC(0x72ccb9db), STC(0x6ed9eba1), + STC(0x6a6d98a4), STC(0x658c9a2d), STC(0x603c496c), STC(0x5a82799a), + STC(0x54657194), STC(0x4debe4fe), STC(0x471cece7), STC(0x40000000), + STC(0x389cea72), STC(0x30fbc54d), STC(0x2924edac), STC(0x2120fb83), + STC(0x18f8b83c), STC(0x10b5150f), STC(0x085f2137), STC(0x00000000), + STC(0xf7a0dec9), STC(0xef4aeaf1), STC(0xe70747c4), STC(0xdedf047d), + STC(0xd6db1254), STC(0xcf043ab3), STC(0xc763158e), STC(0x7f9afcb9), + STC(0x7e6c9251), STC(0x7c769e18), STC(0x79bc384d), STC(0x7641af3d), + STC(0x720c8075), STC(0x6d23501b), STC(0x678dde6e), STC(0x6154fb91), + STC(0x5a82799a), STC(0x53211d18), STC(0x4b3c8c12), STC(0x42e13ba4), + STC(0x3a1c5c57), STC(0x30fbc54d), STC(0x278dde6e), STC(0x1de189a6), + STC(0x14060b68), STC(0x0a0af299), STC(0x00000000), STC(0xf5f50d67), + STC(0xebf9f498), STC(0xe21e765a), STC(0xd8722192), STC(0xcf043ab3), + STC(0xc5e3a3a9), STC(0xbd1ec45c), STC(0xb4c373ee), STC(0xacdee2e8), + STC(0xa57d8666), STC(0x9eab046f), STC(0x7f76892f), STC(0x7ddb4bfc), + STC(0x7b31bbb2), STC(0x777f903c), STC(0x72ccb9db), STC(0x6d23501b), + STC(0x668f7c25), STC(0x5f1f5ea1), STC(0x56e2f15d), STC(0x4debe4fe), + STC(0x444d7aff), STC(0x3a1c5c57), STC(0x2f6e6d16), STC(0x245a9d65), + STC(0x18f8b83c), STC(0x0d61304e), STC(0x01aceb7c), STC(0xf5f50d67), + STC(0xea52c166), STC(0xdedf047d), STC(0xd3b26fb0), STC(0xc8e5032b), + STC(0xbe8df2ba), STC(0xb4c373ee), STC(0xab9a8e6c), STC(0xa326eec0), + STC(0x9b7abc1c), STC(0x94a6715d), STC(0x8eb8b9a0), STC(0x89be50c3), + STC(0x85c1e80e), STC(0x7f4c7e54), STC(0x7d33f0ca), STC(0x79bc384d), + STC(0x74ef0ebc), STC(0x6ed9eba1), STC(0x678dde6e), STC(0x5f1f5ea1), + STC(0x55a6125c), STC(0x4b3c8c12), STC(0x40000000), STC(0x340ff242), + STC(0x278dde6e), STC(0x1a9cd9ac), STC(0x0d61304e), STC(0x00000000), + STC(0xf29ecfb2), STC(0xe5632654), STC(0xd8722192), STC(0xcbf00dbe), + STC(0xc0000000), STC(0xb4c373ee), STC(0xaa59eda4), STC(0xa0e0a15f), + STC(0x98722192), STC(0x9126145f), STC(0x8b10f144), STC(0x8643c7b3), + STC(0x82cc0f36), STC(0x80b381ac), STC(0x80000000), STC(0x80b381ac), + STC(0x7f1cde01), STC(0x7c769e18), STC(0x7816a759), STC(0x720c8075), + STC(0x6a6d98a4), STC(0x6154fb91), STC(0x56e2f15d), STC(0x4b3c8c12), + STC(0x3e8b240e), STC(0x30fbc54d), STC(0x22be8f87), STC(0x14060b68), + STC(0x05067734), STC(0xf5f50d67), STC(0xe70747c4), STC(0xd8722192), + STC(0xca695b94), STC(0xbd1ec45c), STC(0xb0c1878b), STC(0xa57d8666), + STC(0x9b7abc1c), STC(0x92dcafe5), STC(0x8bc1f6e8), STC(0x8643c7b3), + STC(0x8275a0c0), STC(0x80650347), STC(0x80194350), STC(0x81936daf), + STC(0x84ce444e), STC(0x89be50c3), STC(0x90520d04), STC(0x7ee7aa4c), + STC(0x7ba3751d), STC(0x7641af3d), STC(0x6ed9eba1), STC(0x658c9a2d), + STC(0x5a82799a), STC(0x4debe4fe), STC(0x40000000), STC(0x30fbc54d), + STC(0x2120fb83), STC(0x10b5150f), STC(0x00000000), STC(0xef4aeaf1), + STC(0xdedf047d), STC(0xcf043ab3), STC(0xc0000000), STC(0xb2141b02), + STC(0xa57d8666), STC(0x9a7365d3), STC(0x9126145f), STC(0x89be50c3), + STC(0x845c8ae3), STC(0x811855b4), STC(0x80000000), STC(0x811855b4), + STC(0x845c8ae3), STC(0x89be50c3), STC(0x9126145f), STC(0x9a7365d3), + STC(0xa57d8666), STC(0xb2141b02), STC(0x7eace58a), STC(0x7aba9ae6), + STC(0x743e0918), STC(0x6b598ea3), STC(0x603c496c), STC(0x53211d18), + STC(0x444d7aff), STC(0x340ff242), STC(0x22be8f87), STC(0x10b5150f), + STC(0xfe531484), STC(0xebf9f498), STC(0xda0aecf9), STC(0xc8e5032b), + STC(0xb8e31319), STC(0xaa59eda4), STC(0x9d969742), STC(0x92dcafe5), + STC(0x8a650cb4), STC(0x845c8ae3), STC(0x80e321ff), STC(0x800b3a91), + STC(0x81d94c8f), STC(0x8643c7b3), STC(0x8d334625), STC(0x96830876), + STC(0xa201b853), STC(0xaf726def), STC(0xbe8df2ba), STC(0xcf043ab3), + STC(0xe07e0c84), STC(0x7e6c9251), STC(0x79bc384d), STC(0x720c8075), + STC(0x678dde6e), STC(0x5a82799a), STC(0x4b3c8c12), STC(0x3a1c5c57), + STC(0x278dde6e), STC(0x14060b68), STC(0x00000000), STC(0xebf9f498), + STC(0xd8722192), STC(0xc5e3a3a9), STC(0xb4c373ee), STC(0xa57d8666), + STC(0x98722192), STC(0x8df37f8b), STC(0x8643c7b3), STC(0x81936daf), + STC(0x80000000), STC(0x81936daf), STC(0x8643c7b3), STC(0x8df37f8b), + STC(0x98722192), STC(0xa57d8666), STC(0xb4c373ee), STC(0xc5e3a3a9), + STC(0xd8722192), STC(0xebf9f498), STC(0x00000000), STC(0x14060b68), + STC(0x7e26b371), STC(0x78a879f4), STC(0x6fadf2fc), STC(0x637984d4), + STC(0x54657194), STC(0x42e13ba4), STC(0x2f6e6d16), STC(0x1a9cd9ac), + STC(0x05067734), STC(0xef4aeaf1), STC(0xda0aecf9), STC(0xc5e3a3a9), + STC(0xb36a1978), STC(0xa326eec0), STC(0x9592675c), STC(0x8b10f144), + STC(0x83f03dd6), STC(0x80650347), STC(0x808976d1), STC(0x845c8ae3), + STC(0x8bc1f6e8), STC(0x96830876), STC(0xa45037c9), STC(0xb4c373ee), + STC(0xc763158e), STC(0xdba5629b), STC(0xf0f488d9), STC(0x06b2f1d2), + STC(0x1c3fd045), STC(0x30fbc54d), STC(0x444d7aff), STC(0x7ddb4bfc), + STC(0x777f903c), STC(0x6d23501b), STC(0x5f1f5ea1), STC(0x4debe4fe), + STC(0x3a1c5c57), STC(0x245a9d65), STC(0x0d61304e), STC(0xf5f50d67), + STC(0xdedf047d), STC(0xc8e5032b), STC(0xb4c373ee), STC(0xa326eec0), + STC(0x94a6715d), STC(0x89be50c3), STC(0x82cc0f36), STC(0x800b3a91), + STC(0x81936daf), STC(0x8757860c), STC(0x9126145f), STC(0x9eab046f), + STC(0xaf726def), STC(0xc2ec7635), STC(0xd8722192), STC(0xef4aeaf1), + STC(0x06b2f1d2), STC(0x1de189a6), STC(0x340ff242), STC(0x487fffe4), + STC(0x5a82799a), STC(0x697cf78a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag480[] = { + STC(0x01aceb7c), STC(0x0359c428), STC(0x05067734), STC(0x06b2f1d2), + STC(0x085f2137), STC(0x0a0af299), STC(0x0bb65336), STC(0x0d61304e), + STC(0x0f0b7727), STC(0x10b5150f), STC(0x125df75b), STC(0x14060b68), + STC(0x15ad3e9a), STC(0x17537e63), STC(0x18f8b83c), STC(0x1a9cd9ac), + STC(0x1c3fd045), STC(0x1de189a6), STC(0x1f81f37c), STC(0x2120fb83), + STC(0x22be8f87), STC(0x245a9d65), STC(0x25f51307), STC(0x278dde6e), + STC(0x2924edac), STC(0x2aba2ee4), STC(0x2c4d9050), STC(0x2ddf0040), + STC(0x2f6e6d16), STC(0x30fbc54d), STC(0x3286f779), STC(0x0359c428), + STC(0x06b2f1d2), STC(0x0a0af299), STC(0x0d61304e), STC(0x10b5150f), + STC(0x14060b68), STC(0x17537e63), STC(0x1a9cd9ac), STC(0x1de189a6), + STC(0x2120fb83), STC(0x245a9d65), STC(0x278dde6e), STC(0x2aba2ee4), + STC(0x2ddf0040), STC(0x30fbc54d), STC(0x340ff242), STC(0x371afcd5), + STC(0x3a1c5c57), STC(0x3d1389cb), STC(0x40000000), STC(0x42e13ba4), + STC(0x45b6bb5e), STC(0x487fffe4), STC(0x4b3c8c12), STC(0x4debe4fe), + STC(0x508d9211), STC(0x53211d18), STC(0x55a6125c), STC(0x581c00b3), + STC(0x5a82799a), STC(0x5cd91140), STC(0x05067734), STC(0x0a0af299), + STC(0x0f0b7727), STC(0x14060b68), STC(0x18f8b83c), STC(0x1de189a6), + STC(0x22be8f87), STC(0x278dde6e), STC(0x2c4d9050), STC(0x30fbc54d), + STC(0x3596a46c), STC(0x3a1c5c57), STC(0x3e8b240e), STC(0x42e13ba4), + STC(0x471cece7), STC(0x4b3c8c12), STC(0x4f3e7875), STC(0x53211d18), + STC(0x56e2f15d), STC(0x5a82799a), STC(0x5dfe47ad), STC(0x6154fb91), + STC(0x648543e4), STC(0x678dde6e), STC(0x6a6d98a4), STC(0x6d23501b), + STC(0x6fadf2fc), STC(0x720c8075), STC(0x743e0918), STC(0x7641af3d), + STC(0x7816a759), STC(0x06b2f1d2), STC(0x0d61304e), STC(0x14060b68), + STC(0x1a9cd9ac), STC(0x2120fb83), STC(0x278dde6e), STC(0x2ddf0040), + STC(0x340ff242), STC(0x3a1c5c57), STC(0x40000000), STC(0x45b6bb5e), + STC(0x4b3c8c12), STC(0x508d9211), STC(0x55a6125c), STC(0x5a82799a), + STC(0x5f1f5ea1), STC(0x637984d4), STC(0x678dde6e), STC(0x6b598ea3), + STC(0x6ed9eba1), STC(0x720c8075), STC(0x74ef0ebc), STC(0x777f903c), + STC(0x79bc384d), STC(0x7ba3751d), STC(0x7d33f0ca), STC(0x7e6c9251), + STC(0x7f4c7e54), STC(0x7fd317b4), STC(0x7fffffff), STC(0x7fd317b4), + STC(0x085f2137), STC(0x10b5150f), STC(0x18f8b83c), STC(0x2120fb83), + STC(0x2924edac), STC(0x30fbc54d), STC(0x389cea72), STC(0x40000000), + STC(0x471cece7), STC(0x4debe4fe), STC(0x54657194), STC(0x5a82799a), + STC(0x603c496c), STC(0x658c9a2d), STC(0x6a6d98a4), STC(0x6ed9eba1), + STC(0x72ccb9db), STC(0x7641af3d), STC(0x793501a9), STC(0x7ba3751d), + STC(0x7d8a5f40), STC(0x7ee7aa4c), STC(0x7fb9d759), STC(0x7fffffff), + STC(0x7fb9d759), STC(0x7ee7aa4c), STC(0x7d8a5f40), STC(0x7ba3751d), + STC(0x793501a9), STC(0x7641af3d), STC(0x72ccb9db), STC(0x0a0af299), + STC(0x14060b68), STC(0x1de189a6), STC(0x278dde6e), STC(0x30fbc54d), + STC(0x3a1c5c57), STC(0x42e13ba4), STC(0x4b3c8c12), STC(0x53211d18), + STC(0x5a82799a), STC(0x6154fb91), STC(0x678dde6e), STC(0x6d23501b), + STC(0x720c8075), STC(0x7641af3d), STC(0x79bc384d), STC(0x7c769e18), + STC(0x7e6c9251), STC(0x7f9afcb9), STC(0x7fffffff), STC(0x7f9afcb9), + STC(0x7e6c9251), STC(0x7c769e18), STC(0x79bc384d), STC(0x7641af3d), + STC(0x720c8075), STC(0x6d23501b), STC(0x678dde6e), STC(0x6154fb91), + STC(0x5a82799a), STC(0x53211d18), STC(0x0bb65336), STC(0x17537e63), + STC(0x22be8f87), STC(0x2ddf0040), STC(0x389cea72), STC(0x42e13ba4), + STC(0x4c95e688), STC(0x55a6125c), STC(0x5dfe47ad), STC(0x658c9a2d), + STC(0x6c40cf2c), STC(0x720c8075), STC(0x76e33b3f), STC(0x7aba9ae6), + STC(0x7d8a5f40), STC(0x7f4c7e54), STC(0x7ffd3154), STC(0x7f9afcb9), + STC(0x7e26b371), STC(0x7ba3751d), STC(0x7816a759), STC(0x7387ea23), + STC(0x6e010780), STC(0x678dde6e), STC(0x603c496c), STC(0x581c00b3), + STC(0x4f3e7875), STC(0x45b6bb5e), STC(0x3b9941b1), STC(0x30fbc54d), + STC(0x25f51307), STC(0x0d61304e), STC(0x1a9cd9ac), STC(0x278dde6e), + STC(0x340ff242), STC(0x40000000), STC(0x4b3c8c12), STC(0x55a6125c), + STC(0x5f1f5ea1), STC(0x678dde6e), STC(0x6ed9eba1), STC(0x74ef0ebc), + STC(0x79bc384d), STC(0x7d33f0ca), STC(0x7f4c7e54), STC(0x7fffffff), + STC(0x7f4c7e54), STC(0x7d33f0ca), STC(0x79bc384d), STC(0x74ef0ebc), + STC(0x6ed9eba1), STC(0x678dde6e), STC(0x5f1f5ea1), STC(0x55a6125c), + STC(0x4b3c8c12), STC(0x40000000), STC(0x340ff242), STC(0x278dde6e), + STC(0x1a9cd9ac), STC(0x0d61304e), STC(0x00000000), STC(0xf29ecfb2), + STC(0x0f0b7727), STC(0x1de189a6), STC(0x2c4d9050), STC(0x3a1c5c57), + STC(0x471cece7), STC(0x53211d18), STC(0x5dfe47ad), STC(0x678dde6e), + STC(0x6fadf2fc), STC(0x7641af3d), STC(0x7b31bbb2), STC(0x7e6c9251), + STC(0x7fe6bcb0), STC(0x7f9afcb9), STC(0x7d8a5f40), STC(0x79bc384d), + STC(0x743e0918), STC(0x6d23501b), STC(0x648543e4), STC(0x5a82799a), + STC(0x4f3e7875), STC(0x42e13ba4), STC(0x3596a46c), STC(0x278dde6e), + STC(0x18f8b83c), STC(0x0a0af299), STC(0xfaf988cc), STC(0xebf9f498), + STC(0xdd417079), STC(0xcf043ab3), STC(0xc174dbf2), STC(0x10b5150f), + STC(0x2120fb83), STC(0x30fbc54d), STC(0x40000000), STC(0x4debe4fe), + STC(0x5a82799a), STC(0x658c9a2d), STC(0x6ed9eba1), STC(0x7641af3d), + STC(0x7ba3751d), STC(0x7ee7aa4c), STC(0x7fffffff), STC(0x7ee7aa4c), + STC(0x7ba3751d), STC(0x7641af3d), STC(0x6ed9eba1), STC(0x658c9a2d), + STC(0x5a82799a), STC(0x4debe4fe), STC(0x40000000), STC(0x30fbc54d), + STC(0x2120fb83), STC(0x10b5150f), STC(0x00000000), STC(0xef4aeaf1), + STC(0xdedf047d), STC(0xcf043ab3), STC(0xc0000000), STC(0xb2141b02), + STC(0xa57d8666), STC(0x9a7365d3), STC(0x125df75b), STC(0x245a9d65), + STC(0x3596a46c), STC(0x45b6bb5e), STC(0x54657194), STC(0x6154fb91), + STC(0x6c40cf2c), STC(0x74ef0ebc), STC(0x7b31bbb2), STC(0x7ee7aa4c), + STC(0x7ffd3154), STC(0x7e6c9251), STC(0x7a3e17f2), STC(0x7387ea23), + STC(0x6a6d98a4), STC(0x5f1f5ea1), STC(0x51d92321), STC(0x42e13ba4), + STC(0x3286f779), STC(0x2120fb83), STC(0x0f0b7727), STC(0xfca63bd8), + STC(0xea52c166), STC(0xd8722192), STC(0xc763158e), STC(0xb780001c), + STC(0xa91d0ea3), STC(0x9c867b2c), STC(0x91fef880), STC(0x89be50c3), + STC(0x83f03dd6), STC(0x14060b68), STC(0x278dde6e), STC(0x3a1c5c57), + STC(0x4b3c8c12), STC(0x5a82799a), STC(0x678dde6e), STC(0x720c8075), + STC(0x79bc384d), STC(0x7e6c9251), STC(0x7fffffff), STC(0x7e6c9251), + STC(0x79bc384d), STC(0x720c8075), STC(0x678dde6e), STC(0x5a82799a), + STC(0x4b3c8c12), STC(0x3a1c5c57), STC(0x278dde6e), STC(0x14060b68), + STC(0x00000000), STC(0xebf9f498), STC(0xd8722192), STC(0xc5e3a3a9), + STC(0xb4c373ee), STC(0xa57d8666), STC(0x98722192), STC(0x8df37f8b), + STC(0x8643c7b3), STC(0x81936daf), STC(0x80000000), STC(0x81936daf), + STC(0x15ad3e9a), STC(0x2aba2ee4), STC(0x3e8b240e), STC(0x508d9211), + STC(0x603c496c), STC(0x6d23501b), STC(0x76e33b3f), STC(0x7d33f0ca), + STC(0x7fe6bcb0), STC(0x7ee7aa4c), STC(0x7a3e17f2), STC(0x720c8075), + STC(0x668f7c25), STC(0x581c00b3), STC(0x471cece7), STC(0x340ff242), + STC(0x1f81f37c), STC(0x0a0af299), STC(0xf449acca), STC(0xdedf047d), + STC(0xca695b94), STC(0xb780001c), STC(0xa6aecd5e), STC(0x98722192), + STC(0x8d334625), STC(0x8545651a), STC(0x80e321ff), STC(0x802ce84c), + STC(0x8327fb9c), STC(0x89be50c3), STC(0x93bf30d4), STC(0x17537e63), + STC(0x2ddf0040), STC(0x42e13ba4), STC(0x55a6125c), STC(0x658c9a2d), + STC(0x720c8075), STC(0x7aba9ae6), STC(0x7f4c7e54), STC(0x7f9afcb9), + STC(0x7ba3751d), STC(0x7387ea23), STC(0x678dde6e), STC(0x581c00b3), + STC(0x45b6bb5e), STC(0x30fbc54d), STC(0x1a9cd9ac), STC(0x0359c428), + STC(0xebf9f498), STC(0xd545d11c), STC(0xc0000000), STC(0xacdee2e8), + STC(0x9c867b2c), STC(0x8f82ebbd), STC(0x8643c7b3), STC(0x811855b4), + STC(0x802ce84c), STC(0x838961e8), STC(0x8b10f144), STC(0x96830876), + STC(0xa57d8666), STC(0xb780001c), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal20[] = { + STC(0x79bc384d), STC(0x678dde6e), STC(0x4b3c8c12), STC(0x678dde6e), + STC(0x278dde6e), STC(0xd8722192), STC(0x4b3c8c12), STC(0xd8722192), + STC(0x8643c7b3), STC(0x278dde6e), STC(0x98722192), STC(0x98722192), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag20[] = { + STC(0x278dde6e), STC(0x4b3c8c12), STC(0x678dde6e), STC(0x4b3c8c12), + STC(0x79bc384d), STC(0x79bc384d), STC(0x678dde6e), STC(0x79bc384d), + STC(0x278dde6e), STC(0x79bc384d), STC(0x4b3c8c12), STC(0xb4c373ee), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow8[] = { + WTCP(0x7f62368f, 0x0c8bd35e), + WTCP(0x7a7d055b, 0x25280c5e), + WTCP(0x70e2cbc6, 0x3c56ba70), + WTCP(0x62f201ac, 0x5133cc94), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow12[] = { + WTCP(0x7fb9d759, 0x085f2137), WTCP(0x7d8a5f40, 0x18f8b83c), + WTCP(0x793501a9, 0x2924edac), WTCP(0x72ccb9db, 0x389cea72), + WTCP(0x6a6d98a4, 0x471cece7), WTCP(0x603c496c, 0x54657194), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow16[] = { + WTCP(0x7fd8878e, 0x0647d97c), WTCP(0x7e9d55fc, 0x12c8106f), + WTCP(0x7c29fbee, 0x1f19f97b), WTCP(0x78848414, 0x2b1f34eb), + WTCP(0x73b5ebd1, 0x36ba2014), WTCP(0x6dca0d14, 0x41ce1e65), + WTCP(0x66cf8120, 0x4c3fdff4), WTCP(0x5ed77c8a, 0x55f5a4d2), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow20[] = { + WTCP(0x7fe6bcb0, 0x05067734), WTCP(0x7f1cde01, 0x0f0b7727), + WTCP(0x7d8a5f40, 0x18f8b83c), WTCP(0x7b31bbb2, 0x22be8f87), + WTCP(0x7816a759, 0x2c4d9050), WTCP(0x743e0918, 0x3596a46c), + WTCP(0x6fadf2fc, 0x3e8b240e), WTCP(0x6a6d98a4, 0x471cece7), + WTCP(0x648543e4, 0x4f3e7875), WTCP(0x5dfe47ad, 0x56e2f15d), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow24[] = { + WTCP(0x7fee74a2, 0x0430238f), WTCP(0x7f62368f, 0x0c8bd35e), + WTCP(0x7e4a5426, 0x14d9c245), WTCP(0x7ca80038, 0x1d10d5c2), + WTCP(0x7a7d055b, 0x25280c5e), WTCP(0x77cbc3f2, 0x2d168792), + WTCP(0x74972f92, 0x34d3957e), WTCP(0x70e2cbc6, 0x3c56ba70), + WTCP(0x6cb2a837, 0x4397ba32), WTCP(0x680b5c33, 0x4a8ea111), + WTCP(0x62f201ac, 0x5133cc94), WTCP(0x5d6c2f99, 0x577ff3da), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow32[] = { + WTCP(0x7ff62182, 0x03242abf), WTCP(0x7fa736b4, 0x096a9049), + WTCP(0x7f0991c4, 0x0fab272b), WTCP(0x7e1d93ea, 0x15e21445), + WTCP(0x7ce3ceb2, 0x1c0b826a), WTCP(0x7b5d039e, 0x2223a4c5), + WTCP(0x798a23b1, 0x2826b928), WTCP(0x776c4edb, 0x2e110a62), + WTCP(0x7504d345, 0x33def287), WTCP(0x72552c85, 0x398cdd32), + WTCP(0x6f5f02b2, 0x3f1749b8), WTCP(0x6c242960, 0x447acd50), + WTCP(0x68a69e81, 0x49b41533), WTCP(0x64e88926, 0x4ebfe8a5), + WTCP(0x60ec3830, 0x539b2af0), WTCP(0x5cb420e0, 0x5842dd54), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow40[] = { + WTCP(0x7ff9af04, 0x02835b5a), WTCP(0x7fc72ae2, 0x07891418), + WTCP(0x7f62368f, 0x0c8bd35e), WTCP(0x7ecaf9e5, 0x11899ed3), + WTCP(0x7e01b096, 0x16807e15), WTCP(0x7d06aa16, 0x1b6e7b7a), + WTCP(0x7bda497d, 0x2051a4dd), WTCP(0x7a7d055b, 0x25280c5e), + WTCP(0x78ef678f, 0x29efc925), WTCP(0x77320d0d, 0x2ea6f827), + WTCP(0x7545a5a0, 0x334bbcde), WTCP(0x732af3a7, 0x37dc420c), + WTCP(0x70e2cbc6, 0x3c56ba70), WTCP(0x6e6e1492, 0x40b9617d), + WTCP(0x6bcdc639, 0x45027c0c), WTCP(0x6902ea1d, 0x4930590f), + WTCP(0x660e9a6a, 0x4d415234), WTCP(0x62f201ac, 0x5133cc94), + WTCP(0x5fae5a55, 0x55063951), WTCP(0x5c44ee40, 0x58b71632), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow48[] = { + WTCP(0x7ffb9d15, 0x02182427), WTCP(0x7fd8878e, 0x0647d97c), + WTCP(0x7f92661d, 0x0a75d60e), WTCP(0x7f294bfd, 0x0ea0f48c), + WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7deeaa7a, 0x16ea0646), + WTCP(0x7d1d7958, 0x1b05b40f), WTCP(0x7c29fbee, 0x1f19f97b), + WTCP(0x7b1474fd, 0x2325b847), WTCP(0x79dd3098, 0x2727d486), + WTCP(0x78848414, 0x2b1f34eb), WTCP(0x770acdec, 0x2f0ac320), + WTCP(0x757075ac, 0x32e96c09), WTCP(0x73b5ebd1, 0x36ba2014), + WTCP(0x71dba9ab, 0x3a7bd382), WTCP(0x6fe2313c, 0x3e2d7eb1), + WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x6b93d02e, 0x455cb40c), + WTCP(0x694015c3, 0x48d84609), WTCP(0x66cf8120, 0x4c3fdff4), + WTCP(0x6442bd7e, 0x4f9292dc), WTCP(0x619a7dce, 0x52cf758f), + WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5bfa7b82, 0x590443a7), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow64[] = { + WTCP(0x7ffd885a, 0x01921d20), WTCP(0x7fe9cbc0, 0x04b6195d), + WTCP(0x7fc25596, 0x07d95b9e), WTCP(0x7f872bf3, 0x0afb6805), + WTCP(0x7f3857f6, 0x0e1bc2e4), WTCP(0x7ed5e5c6, 0x1139f0cf), + WTCP(0x7e5fe493, 0x145576b1), WTCP(0x7dd6668f, 0x176dd9de), + WTCP(0x7d3980ec, 0x1a82a026), WTCP(0x7c894bde, 0x1d934fe5), + WTCP(0x7bc5e290, 0x209f701c), WTCP(0x7aef6323, 0x23a6887f), + WTCP(0x7a05eead, 0x26a82186), WTCP(0x7909a92d, 0x29a3c485), + WTCP(0x77fab989, 0x2c98fbba), WTCP(0x76d94989, 0x2f875262), + WTCP(0x75a585cf, 0x326e54c7), WTCP(0x745f9dd1, 0x354d9057), + WTCP(0x7307c3d0, 0x382493b0), WTCP(0x719e2cd2, 0x3af2eeb7), + WTCP(0x7023109a, 0x3db832a6), WTCP(0x6e96a99d, 0x4073f21d), + WTCP(0x6cf934fc, 0x4325c135), WTCP(0x6b4af279, 0x45cd358f), + WTCP(0x698c246c, 0x4869e665), WTCP(0x67bd0fbd, 0x4afb6c98), + WTCP(0x65ddfbd3, 0x4d8162c4), WTCP(0x63ef3290, 0x4ffb654d), + WTCP(0x61f1003f, 0x5269126e), WTCP(0x5fe3b38d, 0x54ca0a4b), + WTCP(0x5dc79d7c, 0x571deefa), WTCP(0x5b9d1154, 0x59646498), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow96[] = { + WTCP(0x7ffee744, 0x010c1460), WTCP(0x7ff62182, 0x03242abf), + WTCP(0x7fe49698, 0x053c0a01), WTCP(0x7fca47b9, 0x07538d6b), + WTCP(0x7fa736b4, 0x096a9049), WTCP(0x7f7b65ef, 0x0b80edf1), + WTCP(0x7f46d86c, 0x0d9681c2), WTCP(0x7f0991c4, 0x0fab272b), + WTCP(0x7ec3962a, 0x11beb9aa), WTCP(0x7e74ea6a, 0x13d114d0), + WTCP(0x7e1d93ea, 0x15e21445), WTCP(0x7dbd98a4, 0x17f193c5), + WTCP(0x7d54ff2e, 0x19ff6f2a), WTCP(0x7ce3ceb2, 0x1c0b826a), + WTCP(0x7c6a0ef2, 0x1e15a99a), WTCP(0x7be7c847, 0x201dc0ef), + WTCP(0x7b5d039e, 0x2223a4c5), WTCP(0x7ac9ca7a, 0x2427319d), + WTCP(0x7a2e26f2, 0x26284422), WTCP(0x798a23b1, 0x2826b928), + WTCP(0x78ddcbf5, 0x2a226db5), WTCP(0x78292b8d, 0x2c1b3efb), + WTCP(0x776c4edb, 0x2e110a62), WTCP(0x76a742d1, 0x3003ad85), + WTCP(0x75da14ef, 0x31f30638), WTCP(0x7504d345, 0x33def287), + WTCP(0x74278c72, 0x35c750bc), WTCP(0x73424fa0, 0x37abff5d), + WTCP(0x72552c85, 0x398cdd32), WTCP(0x71603361, 0x3b69c947), + WTCP(0x706374ff, 0x3d42a2ec), WTCP(0x6f5f02b2, 0x3f1749b8), + WTCP(0x6e52ee52, 0x40e79d8c), WTCP(0x6d3f4a40, 0x42b37e96), + WTCP(0x6c242960, 0x447acd50), WTCP(0x6b019f1a, 0x463d6a87), + WTCP(0x69d7bf57, 0x47fb3757), WTCP(0x68a69e81, 0x49b41533), + WTCP(0x676e5183, 0x4b67e5e4), WTCP(0x662eedc3, 0x4d168b8b), + WTCP(0x64e88926, 0x4ebfe8a5), WTCP(0x639b3a0b, 0x5063e008), + WTCP(0x62471749, 0x520254ef), WTCP(0x60ec3830, 0x539b2af0), + WTCP(0x5f8ab487, 0x552e4605), WTCP(0x5e22a487, 0x56bb8a90), + WTCP(0x5cb420e0, 0x5842dd54), WTCP(0x5b3f42ae, 0x59c42381), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow120[] = { + WTCP(0x7fff4c54, 0x00d676eb), WTCP(0x7ff9af04, 0x02835b5a), + WTCP(0x7fee74a2, 0x0430238f), WTCP(0x7fdd9dad, 0x05dcbcbe), + WTCP(0x7fc72ae2, 0x07891418), WTCP(0x7fab1d3d, 0x093516d4), + WTCP(0x7f8975f9, 0x0ae0b22c), WTCP(0x7f62368f, 0x0c8bd35e), + WTCP(0x7f3560b9, 0x0e3667ad), WTCP(0x7f02f66f, 0x0fe05c64), + WTCP(0x7ecaf9e5, 0x11899ed3), WTCP(0x7e8d6d91, 0x13321c53), + WTCP(0x7e4a5426, 0x14d9c245), WTCP(0x7e01b096, 0x16807e15), + WTCP(0x7db3860f, 0x18263d36), WTCP(0x7d5fd801, 0x19caed29), + WTCP(0x7d06aa16, 0x1b6e7b7a), WTCP(0x7ca80038, 0x1d10d5c2), + WTCP(0x7c43de8e, 0x1eb1e9a7), WTCP(0x7bda497d, 0x2051a4dd), + WTCP(0x7b6b45a5, 0x21eff528), WTCP(0x7af6d7e6, 0x238cc85d), + WTCP(0x7a7d055b, 0x25280c5e), WTCP(0x79fdd35c, 0x26c1af22), + WTCP(0x7979477d, 0x28599eb0), WTCP(0x78ef678f, 0x29efc925), + WTCP(0x7860399e, 0x2b841caf), WTCP(0x77cbc3f2, 0x2d168792), + WTCP(0x77320d0d, 0x2ea6f827), WTCP(0x76931bae, 0x30355cdd), + WTCP(0x75eef6ce, 0x31c1a43b), WTCP(0x7545a5a0, 0x334bbcde), + WTCP(0x74972f92, 0x34d3957e), WTCP(0x73e39c49, 0x36591cea), + WTCP(0x732af3a7, 0x37dc420c), WTCP(0x726d3dc6, 0x395cf3e9), + WTCP(0x71aa82f7, 0x3adb21a1), WTCP(0x70e2cbc6, 0x3c56ba70), + WTCP(0x701620f5, 0x3dcfadb0), WTCP(0x6f448b7e, 0x3f45ead8), + WTCP(0x6e6e1492, 0x40b9617d), WTCP(0x6d92c59b, 0x422a0154), + WTCP(0x6cb2a837, 0x4397ba32), WTCP(0x6bcdc639, 0x45027c0c), + WTCP(0x6ae429ae, 0x466a36f9), WTCP(0x69f5dcd3, 0x47cedb31), + WTCP(0x6902ea1d, 0x4930590f), WTCP(0x680b5c33, 0x4a8ea111), + WTCP(0x670f3df3, 0x4be9a3db), WTCP(0x660e9a6a, 0x4d415234), + WTCP(0x65097cdb, 0x4e959d08), WTCP(0x63fff0ba, 0x4fe6756a), + WTCP(0x62f201ac, 0x5133cc94), WTCP(0x61dfbb8a, 0x527d93e6), + WTCP(0x60c92a5a, 0x53c3bcea), WTCP(0x5fae5a55, 0x55063951), + WTCP(0x5e8f57e2, 0x5644faf4), WTCP(0x5d6c2f99, 0x577ff3da), + WTCP(0x5c44ee40, 0x58b71632), WTCP(0x5b19a0c8, 0x59ea5454), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow128[] = { + WTCP(0x7fff6216, 0x00c90f88), WTCP(0x7ffa72d1, 0x025b26d7), + WTCP(0x7ff09478, 0x03ed26e6), WTCP(0x7fe1c76b, 0x057f0035), + WTCP(0x7fce0c3e, 0x0710a345), WTCP(0x7fb563b3, 0x08a2009a), + WTCP(0x7f97cebd, 0x0a3308bd), WTCP(0x7f754e80, 0x0bc3ac35), + WTCP(0x7f4de451, 0x0d53db92), WTCP(0x7f2191b4, 0x0ee38766), + WTCP(0x7ef05860, 0x1072a048), WTCP(0x7eba3a39, 0x120116d5), + WTCP(0x7e7f3957, 0x138edbb1), WTCP(0x7e3f57ff, 0x151bdf86), + WTCP(0x7dfa98a8, 0x16a81305), WTCP(0x7db0fdf8, 0x183366e9), + WTCP(0x7d628ac6, 0x19bdcbf3), WTCP(0x7d0f4218, 0x1b4732ef), + WTCP(0x7cb72724, 0x1ccf8cb3), WTCP(0x7c5a3d50, 0x1e56ca1e), + WTCP(0x7bf88830, 0x1fdcdc1b), WTCP(0x7b920b89, 0x2161b3a0), + WTCP(0x7b26cb4f, 0x22e541af), WTCP(0x7ab6cba4, 0x24677758), + WTCP(0x7a4210d8, 0x25e845b6), WTCP(0x79c89f6e, 0x27679df4), + WTCP(0x794a7c12, 0x28e5714b), WTCP(0x78c7aba2, 0x2a61b101), + WTCP(0x78403329, 0x2bdc4e6f), WTCP(0x77b417df, 0x2d553afc), + WTCP(0x77235f2d, 0x2ecc681e), WTCP(0x768e0ea6, 0x3041c761), + WTCP(0x75f42c0b, 0x31b54a5e), WTCP(0x7555bd4c, 0x3326e2c3), + WTCP(0x74b2c884, 0x34968250), WTCP(0x740b53fb, 0x36041ad9), + WTCP(0x735f6626, 0x376f9e46), WTCP(0x72af05a7, 0x38d8fe93), + WTCP(0x71fa3949, 0x3a402dd2), WTCP(0x71410805, 0x3ba51e29), + WTCP(0x708378ff, 0x3d07c1d6), WTCP(0x6fc19385, 0x3e680b2c), + WTCP(0x6efb5f12, 0x3fc5ec98), WTCP(0x6e30e34a, 0x4121589b), + WTCP(0x6d6227fa, 0x427a41d0), WTCP(0x6c8f351c, 0x43d09aed), + WTCP(0x6bb812d1, 0x452456bd), WTCP(0x6adcc964, 0x46756828), + WTCP(0x69fd614a, 0x47c3c22f), WTCP(0x6919e320, 0x490f57ee), + WTCP(0x683257ab, 0x4a581c9e), WTCP(0x6746c7d8, 0x4b9e0390), + WTCP(0x66573cbb, 0x4ce10034), WTCP(0x6563bf92, 0x4e210617), + WTCP(0x646c59bf, 0x4f5e08e3), WTCP(0x637114cc, 0x5097fc5e), + WTCP(0x6271fa69, 0x51ced46e), WTCP(0x616f146c, 0x53028518), + WTCP(0x60686ccf, 0x5433027d), WTCP(0x5f5e0db3, 0x556040e2), + WTCP(0x5e50015d, 0x568a34a9), WTCP(0x5d3e5237, 0x57b0d256), + WTCP(0x5c290acc, 0x58d40e8c), WTCP(0x5b1035cf, 0x59f3de12), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow160[] = { + WTCP(0x7fff9aef, 0x00a0d951), WTCP(0x7ffc726f, 0x01e287fc), + WTCP(0x7ff62182, 0x03242abf), WTCP(0x7feca851, 0x0465b9aa), + WTCP(0x7fe00716, 0x05a72ccf), WTCP(0x7fd03e23, 0x06e87c3f), + WTCP(0x7fbd4dda, 0x0829a00c), WTCP(0x7fa736b4, 0x096a9049), + WTCP(0x7f8df93c, 0x0aab450d), WTCP(0x7f719611, 0x0bebb66c), + WTCP(0x7f520de6, 0x0d2bdc80), WTCP(0x7f2f6183, 0x0e6baf61), + WTCP(0x7f0991c4, 0x0fab272b), WTCP(0x7ee09f95, 0x10ea3bfd), + WTCP(0x7eb48bfb, 0x1228e5f8), WTCP(0x7e85580c, 0x13671d3d), + WTCP(0x7e5304f2, 0x14a4d9f4), WTCP(0x7e1d93ea, 0x15e21445), + WTCP(0x7de50646, 0x171ec45c), WTCP(0x7da95d6c, 0x185ae269), + WTCP(0x7d6a9ad5, 0x199666a0), WTCP(0x7d28c00c, 0x1ad14938), + WTCP(0x7ce3ceb2, 0x1c0b826a), WTCP(0x7c9bc87a, 0x1d450a78), + WTCP(0x7c50af2b, 0x1e7dd9a4), WTCP(0x7c02849f, 0x1fb5e836), + WTCP(0x7bb14ac5, 0x20ed2e7b), WTCP(0x7b5d039e, 0x2223a4c5), + WTCP(0x7b05b13d, 0x2359436c), WTCP(0x7aab55ca, 0x248e02cb), + WTCP(0x7a4df380, 0x25c1db44), WTCP(0x79ed8cad, 0x26f4c53e), + WTCP(0x798a23b1, 0x2826b928), WTCP(0x7923bb01, 0x2957af74), + WTCP(0x78ba5524, 0x2a87a09d), WTCP(0x784df4b3, 0x2bb68522), + WTCP(0x77de9c5b, 0x2ce45589), WTCP(0x776c4edb, 0x2e110a62), + WTCP(0x76f70f05, 0x2f3c9c40), WTCP(0x767edfbe, 0x306703bf), + WTCP(0x7603c3fd, 0x31903982), WTCP(0x7585becb, 0x32b83634), + WTCP(0x7504d345, 0x33def287), WTCP(0x74810499, 0x35046736), + WTCP(0x73fa5607, 0x36288d03), WTCP(0x7370cae2, 0x374b5cb9), + WTCP(0x72e4668f, 0x386ccf2a), WTCP(0x72552c85, 0x398cdd32), + WTCP(0x71c3204c, 0x3aab7fb7), WTCP(0x712e457f, 0x3bc8afa5), + WTCP(0x70969fca, 0x3ce465f3), WTCP(0x6ffc32eb, 0x3dfe9ba1), + WTCP(0x6f5f02b2, 0x3f1749b8), WTCP(0x6ebf12ff, 0x402e694c), + WTCP(0x6e1c67c4, 0x4143f379), WTCP(0x6d770506, 0x4257e166), + WTCP(0x6cceeed8, 0x436a2c45), WTCP(0x6c242960, 0x447acd50), + WTCP(0x6b76b8d6, 0x4589bdcf), WTCP(0x6ac6a180, 0x4696f710), + WTCP(0x6a13e7b8, 0x47a27271), WTCP(0x695e8fe5, 0x48ac2957), + WTCP(0x68a69e81, 0x49b41533), WTCP(0x67ec1817, 0x4aba2f84), + WTCP(0x672f013f, 0x4bbe71d1), WTCP(0x666f5ea6, 0x4cc0d5ae), + WTCP(0x65ad3505, 0x4dc154bb), WTCP(0x64e88926, 0x4ebfe8a5), + WTCP(0x64215fe5, 0x4fbc8b22), WTCP(0x6357be2a, 0x50b735f8), + WTCP(0x628ba8ef, 0x51afe2f6), WTCP(0x61bd253f, 0x52a68bfb), + WTCP(0x60ec3830, 0x539b2af0), WTCP(0x6018e6eb, 0x548db9cb), + WTCP(0x5f4336a7, 0x557e3292), WTCP(0x5e6b2ca8, 0x566c8f55), + WTCP(0x5d90ce45, 0x5758ca31), WTCP(0x5cb420e0, 0x5842dd54), + WTCP(0x5bd529eb, 0x592ac2f7), WTCP(0x5af3eee6, 0x5a107561), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow192[] = { + WTCP(0x7fffb9d1, 0x00860a79), WTCP(0x7ffd885a, 0x01921d20), + WTCP(0x7ff92577, 0x029e28e2), WTCP(0x7ff2913a, 0x03aa292a), + WTCP(0x7fe9cbc0, 0x04b6195d), WTCP(0x7fded530, 0x05c1f4e7), + WTCP(0x7fd1adb9, 0x06cdb72f), WTCP(0x7fc25596, 0x07d95b9e), + WTCP(0x7fb0cd0a, 0x08e4dda0), WTCP(0x7f9d1461, 0x09f0389f), + WTCP(0x7f872bf3, 0x0afb6805), WTCP(0x7f6f141f, 0x0c066740), + WTCP(0x7f54cd4f, 0x0d1131ba), WTCP(0x7f3857f6, 0x0e1bc2e4), + WTCP(0x7f19b491, 0x0f26162a), WTCP(0x7ef8e3a6, 0x103026fe), + WTCP(0x7ed5e5c6, 0x1139f0cf), WTCP(0x7eb0bb8a, 0x12436f10), + WTCP(0x7e896595, 0x134c9d34), WTCP(0x7e5fe493, 0x145576b1), + WTCP(0x7e34393b, 0x155df6fc), WTCP(0x7e06644c, 0x1666198d), + WTCP(0x7dd6668f, 0x176dd9de), WTCP(0x7da440d6, 0x1875336a), + WTCP(0x7d6ff3fe, 0x197c21ad), WTCP(0x7d3980ec, 0x1a82a026), + WTCP(0x7d00e88f, 0x1b88aa55), WTCP(0x7cc62bdf, 0x1c8e3bbe), + WTCP(0x7c894bde, 0x1d934fe5), WTCP(0x7c4a4996, 0x1e97e251), + WTCP(0x7c09261d, 0x1f9bee8a), WTCP(0x7bc5e290, 0x209f701c), + WTCP(0x7b808015, 0x21a26295), WTCP(0x7b38ffde, 0x22a4c185), + WTCP(0x7aef6323, 0x23a6887f), WTCP(0x7aa3ab29, 0x24a7b317), + WTCP(0x7a55d93a, 0x25a83ce6), WTCP(0x7a05eead, 0x26a82186), + WTCP(0x79b3ece0, 0x27a75c95), WTCP(0x795fd53a, 0x28a5e9b4), + WTCP(0x7909a92d, 0x29a3c485), WTCP(0x78b16a32, 0x2aa0e8b0), + WTCP(0x785719cc, 0x2b9d51dd), WTCP(0x77fab989, 0x2c98fbba), + WTCP(0x779c4afc, 0x2d93e1f8), WTCP(0x773bcfc4, 0x2e8e0048), + WTCP(0x76d94989, 0x2f875262), WTCP(0x7674b9fa, 0x307fd401), + WTCP(0x760e22d1, 0x317780e2), WTCP(0x75a585cf, 0x326e54c7), + WTCP(0x753ae4c0, 0x33644b76), WTCP(0x74ce4177, 0x345960b7), + WTCP(0x745f9dd1, 0x354d9057), WTCP(0x73eefbb3, 0x3640d627), + WTCP(0x737c5d0b, 0x37332dfd), WTCP(0x7307c3d0, 0x382493b0), + WTCP(0x72913201, 0x3915031f), WTCP(0x7218a9a7, 0x3a04782a), + WTCP(0x719e2cd2, 0x3af2eeb7), WTCP(0x7121bd9c, 0x3be062b0), + WTCP(0x70a35e25, 0x3cccd004), WTCP(0x7023109a, 0x3db832a6), + WTCP(0x6fa0d72c, 0x3ea2868c), WTCP(0x6f1cb416, 0x3f8bc7b4), + WTCP(0x6e96a99d, 0x4073f21d), WTCP(0x6e0eba0c, 0x415b01ce), + WTCP(0x6d84e7b7, 0x4240f2d1), WTCP(0x6cf934fc, 0x4325c135), + WTCP(0x6c6ba43e, 0x44096910), WTCP(0x6bdc37eb, 0x44ebe679), + WTCP(0x6b4af279, 0x45cd358f), WTCP(0x6ab7d663, 0x46ad5278), + WTCP(0x6a22e630, 0x478c395a), WTCP(0x698c246c, 0x4869e665), + WTCP(0x68f393ae, 0x494655cc), WTCP(0x68593691, 0x4a2183c8), + WTCP(0x67bd0fbd, 0x4afb6c98), WTCP(0x671f21dc, 0x4bd40c80), + WTCP(0x667f6fa5, 0x4cab5fc9), WTCP(0x65ddfbd3, 0x4d8162c4), + WTCP(0x653ac92b, 0x4e5611c5), WTCP(0x6495da79, 0x4f296928), + WTCP(0x63ef3290, 0x4ffb654d), WTCP(0x6346d44b, 0x50cc029c), + WTCP(0x629cc28c, 0x519b3d80), WTCP(0x61f1003f, 0x5269126e), + WTCP(0x61439053, 0x53357ddf), WTCP(0x609475c3, 0x54007c51), + WTCP(0x5fe3b38d, 0x54ca0a4b), WTCP(0x5f314cba, 0x55922457), + WTCP(0x5e7d4458, 0x5658c709), WTCP(0x5dc79d7c, 0x571deefa), + WTCP(0x5d105b44, 0x57e198c7), WTCP(0x5c5780d3, 0x58a3c118), + WTCP(0x5b9d1154, 0x59646498), WTCP(0x5ae10ff9, 0x5a237ffa), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow240[] = { + WTCP(0x7fffd315, 0x006b3b9b), WTCP(0x7ffe6bbf, 0x0141b1a5), + WTCP(0x7ffb9d15, 0x02182427), WTCP(0x7ff76721, 0x02ee90c8), + WTCP(0x7ff1c9ef, 0x03c4f52f), WTCP(0x7feac58d, 0x049b4f00), + WTCP(0x7fe25a0f, 0x05719be2), WTCP(0x7fd8878e, 0x0647d97c), + WTCP(0x7fcd4e24, 0x071e0575), WTCP(0x7fc0adf2, 0x07f41d72), + WTCP(0x7fb2a71b, 0x08ca1f1b), WTCP(0x7fa339c5, 0x09a00817), + WTCP(0x7f92661d, 0x0a75d60e), WTCP(0x7f802c52, 0x0b4b86a8), + WTCP(0x7f6c8c96, 0x0c21178c), WTCP(0x7f578721, 0x0cf68662), + WTCP(0x7f411c2f, 0x0dcbd0d5), WTCP(0x7f294bfd, 0x0ea0f48c), + WTCP(0x7f1016ce, 0x0f75ef33), WTCP(0x7ef57cea, 0x104abe71), + WTCP(0x7ed97e9c, 0x111f5ff4), WTCP(0x7ebc1c31, 0x11f3d164), + WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7e7d2c54, 0x139c1abf), + WTCP(0x7e5b9f93, 0x146fee03), WTCP(0x7e38b017, 0x154387e6), + WTCP(0x7e145e42, 0x1616e618), WTCP(0x7deeaa7a, 0x16ea0646), + WTCP(0x7dc79529, 0x17bce621), WTCP(0x7d9f1ebd, 0x188f8357), + WTCP(0x7d7547a7, 0x1961db9b), WTCP(0x7d4a105d, 0x1a33ec9c), + WTCP(0x7d1d7958, 0x1b05b40f), WTCP(0x7cef8315, 0x1bd72fa4), + WTCP(0x7cc02e15, 0x1ca85d12), WTCP(0x7c8f7ade, 0x1d793a0b), + WTCP(0x7c5d69f7, 0x1e49c447), WTCP(0x7c29fbee, 0x1f19f97b), + WTCP(0x7bf53153, 0x1fe9d75f), WTCP(0x7bbf0aba, 0x20b95bac), + WTCP(0x7b8788ba, 0x2188841a), WTCP(0x7b4eabf1, 0x22574e65), + WTCP(0x7b1474fd, 0x2325b847), WTCP(0x7ad8e482, 0x23f3bf7e), + WTCP(0x7a9bfb27, 0x24c161c7), WTCP(0x7a5db997, 0x258e9ce0), + WTCP(0x7a1e2082, 0x265b6e8a), WTCP(0x79dd3098, 0x2727d486), + WTCP(0x799aea92, 0x27f3cc94), WTCP(0x79574f28, 0x28bf547b), + WTCP(0x79125f19, 0x298a69fc), WTCP(0x78cc1b26, 0x2a550adf), + WTCP(0x78848414, 0x2b1f34eb), WTCP(0x783b9aad, 0x2be8e5e8), + WTCP(0x77f15fbc, 0x2cb21ba0), WTCP(0x77a5d413, 0x2d7ad3de), + WTCP(0x7758f886, 0x2e430c6f), WTCP(0x770acdec, 0x2f0ac320), + WTCP(0x76bb5521, 0x2fd1f5c1), WTCP(0x766a8f04, 0x3098a223), + WTCP(0x76187c77, 0x315ec617), WTCP(0x75c51e61, 0x32245f72), + WTCP(0x757075ac, 0x32e96c09), WTCP(0x751a8346, 0x33ade9b3), + WTCP(0x74c34820, 0x3471d647), WTCP(0x746ac52f, 0x35352fa1), + WTCP(0x7410fb6b, 0x35f7f39c), WTCP(0x73b5ebd1, 0x36ba2014), + WTCP(0x73599760, 0x377bb2e9), WTCP(0x72fbff1b, 0x383ca9fb), + WTCP(0x729d2409, 0x38fd032d), WTCP(0x723d0734, 0x39bcbc63), + WTCP(0x71dba9ab, 0x3a7bd382), WTCP(0x71790c7e, 0x3b3a4672), + WTCP(0x711530c2, 0x3bf8131c), WTCP(0x70b01790, 0x3cb5376b), + WTCP(0x7049c203, 0x3d71b14d), WTCP(0x6fe2313c, 0x3e2d7eb1), + WTCP(0x6f79665b, 0x3ee89d86), WTCP(0x6f0f6289, 0x3fa30bc1), + WTCP(0x6ea426ed, 0x405cc754), WTCP(0x6e37b4b6, 0x4115ce38), + WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x6d5b313b, 0x4285b5d4), + WTCP(0x6ceb2261, 0x433c9283), WTCP(0x6c79e1c2, 0x43f2b271), + WTCP(0x6c07709b, 0x44a8139e), WTCP(0x6b93d02e, 0x455cb40c), + WTCP(0x6b1f01c0, 0x461091c2), WTCP(0x6aa90697, 0x46c3aac5), + WTCP(0x6a31e000, 0x4775fd1f), WTCP(0x69b98f48, 0x482786dc), + WTCP(0x694015c3, 0x48d84609), WTCP(0x68c574c4, 0x498838b6), + WTCP(0x6849ada3, 0x4a375cf5), WTCP(0x67ccc1be, 0x4ae5b0da), + WTCP(0x674eb271, 0x4b93327c), WTCP(0x66cf8120, 0x4c3fdff4), + WTCP(0x664f2f2e, 0x4cebb75c), WTCP(0x65cdbe05, 0x4d96b6d3), + WTCP(0x654b2f10, 0x4e40dc79), WTCP(0x64c783bd, 0x4eea2670), + WTCP(0x6442bd7e, 0x4f9292dc), WTCP(0x63bcddc7, 0x503a1fe5), + WTCP(0x6335e611, 0x50e0cbb4), WTCP(0x62add7d6, 0x51869476), + WTCP(0x6224b495, 0x522b7859), WTCP(0x619a7dce, 0x52cf758f), + WTCP(0x610f3505, 0x53728a4a), WTCP(0x6082dbc1, 0x5414b4c1), + WTCP(0x5ff5738d, 0x54b5f32c), WTCP(0x5f66fdf5, 0x555643c8), + WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5e46f0dd, 0x5694148b), + WTCP(0x5db55c86, 0x57319135), WTCP(0x5d22c11c, 0x57ce1917), + WTCP(0x5c8f203b, 0x5869aa79), WTCP(0x5bfa7b82, 0x590443a7), + WTCP(0x5b64d492, 0x599de2ee), WTCP(0x5ace2d0f, 0x5a36869f), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow256[] = { + WTCP(0x7fffd886, 0x006487e3), WTCP(0x7ffe9cb2, 0x012d96b1), + WTCP(0x7ffc250f, 0x01f6a297), WTCP(0x7ff871a2, 0x02bfa9a4), + WTCP(0x7ff38274, 0x0388a9ea), WTCP(0x7fed5791, 0x0451a177), + WTCP(0x7fe5f108, 0x051a8e5c), WTCP(0x7fdd4eec, 0x05e36ea9), + WTCP(0x7fd37153, 0x06ac406f), WTCP(0x7fc85854, 0x077501be), + WTCP(0x7fbc040a, 0x083db0a7), WTCP(0x7fae7495, 0x09064b3a), + WTCP(0x7f9faa15, 0x09cecf89), WTCP(0x7f8fa4b0, 0x0a973ba5), + WTCP(0x7f7e648c, 0x0b5f8d9f), WTCP(0x7f6be9d4, 0x0c27c389), + WTCP(0x7f5834b7, 0x0cefdb76), WTCP(0x7f434563, 0x0db7d376), + WTCP(0x7f2d1c0e, 0x0e7fa99e), WTCP(0x7f15b8ee, 0x0f475bff), + WTCP(0x7efd1c3c, 0x100ee8ad), WTCP(0x7ee34636, 0x10d64dbd), + WTCP(0x7ec8371a, 0x119d8941), WTCP(0x7eabef2c, 0x1264994e), + WTCP(0x7e8e6eb2, 0x132b7bf9), WTCP(0x7e6fb5f4, 0x13f22f58), + WTCP(0x7e4fc53e, 0x14b8b17f), WTCP(0x7e2e9cdf, 0x157f0086), + WTCP(0x7e0c3d29, 0x16451a83), WTCP(0x7de8a670, 0x170afd8d), + WTCP(0x7dc3d90d, 0x17d0a7bc), WTCP(0x7d9dd55a, 0x18961728), + WTCP(0x7d769bb5, 0x195b49ea), WTCP(0x7d4e2c7f, 0x1a203e1b), + WTCP(0x7d24881b, 0x1ae4f1d6), WTCP(0x7cf9aef0, 0x1ba96335), + WTCP(0x7ccda169, 0x1c6d9053), WTCP(0x7ca05ff1, 0x1d31774d), + WTCP(0x7c71eaf9, 0x1df5163f), WTCP(0x7c4242f2, 0x1eb86b46), + WTCP(0x7c116853, 0x1f7b7481), WTCP(0x7bdf5b94, 0x203e300d), + WTCP(0x7bac1d31, 0x21009c0c), WTCP(0x7b77ada8, 0x21c2b69c), + WTCP(0x7b420d7a, 0x22847de0), WTCP(0x7b0b3d2c, 0x2345eff8), + WTCP(0x7ad33d45, 0x24070b08), WTCP(0x7a9a0e50, 0x24c7cd33), + WTCP(0x7a5fb0d8, 0x2588349d), WTCP(0x7a24256f, 0x26483f6c), + WTCP(0x79e76ca7, 0x2707ebc7), WTCP(0x79a98715, 0x27c737d3), + WTCP(0x796a7554, 0x288621b9), WTCP(0x792a37fe, 0x2944a7a2), + WTCP(0x78e8cfb2, 0x2a02c7b8), WTCP(0x78a63d11, 0x2ac08026), + WTCP(0x786280bf, 0x2b7dcf17), WTCP(0x781d9b65, 0x2c3ab2b9), + WTCP(0x77d78daa, 0x2cf72939), WTCP(0x7790583e, 0x2db330c7), + WTCP(0x7747fbce, 0x2e6ec792), WTCP(0x76fe790e, 0x2f29ebcc), + WTCP(0x76b3d0b4, 0x2fe49ba7), WTCP(0x76680376, 0x309ed556), + WTCP(0x761b1211, 0x3158970e), WTCP(0x75ccfd42, 0x3211df04), + WTCP(0x757dc5ca, 0x32caab6f), WTCP(0x752d6c6c, 0x3382fa88), + WTCP(0x74dbf1ef, 0x343aca87), WTCP(0x7489571c, 0x34f219a8), + WTCP(0x74359cbd, 0x35a8e625), WTCP(0x73e0c3a3, 0x365f2e3b), + WTCP(0x738acc9e, 0x3714f02a), WTCP(0x7333b883, 0x37ca2a30), + WTCP(0x72db8828, 0x387eda8e), WTCP(0x72823c67, 0x3932ff87), + WTCP(0x7227d61c, 0x39e6975e), WTCP(0x71cc5626, 0x3a99a057), + WTCP(0x716fbd68, 0x3b4c18ba), WTCP(0x71120cc5, 0x3bfdfecd), + WTCP(0x70b34525, 0x3caf50da), WTCP(0x70536771, 0x3d600d2c), + WTCP(0x6ff27497, 0x3e10320d), WTCP(0x6f906d84, 0x3ebfbdcd), + WTCP(0x6f2d532c, 0x3f6eaeb8), WTCP(0x6ec92683, 0x401d0321), + WTCP(0x6e63e87f, 0x40cab958), WTCP(0x6dfd9a1c, 0x4177cfb1), + WTCP(0x6d963c54, 0x42244481), WTCP(0x6d2dd027, 0x42d0161e), + WTCP(0x6cc45698, 0x437b42e1), WTCP(0x6c59d0a9, 0x4425c923), + WTCP(0x6bee3f62, 0x44cfa740), WTCP(0x6b81a3cd, 0x4578db93), + WTCP(0x6b13fef5, 0x4621647d), WTCP(0x6aa551e9, 0x46c9405c), + WTCP(0x6a359db9, 0x47706d93), WTCP(0x69c4e37a, 0x4816ea86), + WTCP(0x69532442, 0x48bcb599), WTCP(0x68e06129, 0x4961cd33), + WTCP(0x686c9b4b, 0x4a062fbd), WTCP(0x67f7d3c5, 0x4aa9dba2), + WTCP(0x67820bb7, 0x4b4ccf4d), WTCP(0x670b4444, 0x4bef092d), + WTCP(0x66937e91, 0x4c9087b1), WTCP(0x661abbc5, 0x4d31494b), + WTCP(0x65a0fd0b, 0x4dd14c6e), WTCP(0x6526438f, 0x4e708f8f), + WTCP(0x64aa907f, 0x4f0f1126), WTCP(0x642de50d, 0x4faccfab), + WTCP(0x63b0426d, 0x5049c999), WTCP(0x6331a9d4, 0x50e5fd6d), + WTCP(0x62b21c7b, 0x518169a5), WTCP(0x62319b9d, 0x521c0cc2), + WTCP(0x61b02876, 0x52b5e546), WTCP(0x612dc447, 0x534ef1b5), + WTCP(0x60aa7050, 0x53e73097), WTCP(0x60262dd6, 0x547ea073), + WTCP(0x5fa0fe1f, 0x55153fd4), WTCP(0x5f1ae274, 0x55ab0d46), + WTCP(0x5e93dc1f, 0x56400758), WTCP(0x5e0bec6e, 0x56d42c99), + WTCP(0x5d8314b1, 0x57677b9d), WTCP(0x5cf95638, 0x57f9f2f8), + WTCP(0x5c6eb258, 0x588b9140), WTCP(0x5be32a67, 0x591c550e), + WTCP(0x5b56bfbd, 0x59ac3cfd), WTCP(0x5ac973b5, 0x5a3b47ab), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow384[] = { + WTCP(0x7fffee74, 0x00430546), WTCP(0x7fff6216, 0x00c90f88), + WTCP(0x7ffe495b, 0x014f18ee), WTCP(0x7ffca443, 0x01d520e4), + WTCP(0x7ffa72d1, 0x025b26d7), WTCP(0x7ff7b507, 0x02e12a36), + WTCP(0x7ff46ae8, 0x03672a6c), WTCP(0x7ff09478, 0x03ed26e6), + WTCP(0x7fec31ba, 0x04731f13), WTCP(0x7fe742b4, 0x04f9125e), + WTCP(0x7fe1c76b, 0x057f0035), WTCP(0x7fdbbfe6, 0x0604e805), + WTCP(0x7fd52c29, 0x068ac93b), WTCP(0x7fce0c3e, 0x0710a345), + WTCP(0x7fc6602c, 0x0796758f), WTCP(0x7fbe27fa, 0x081c3f87), + WTCP(0x7fb563b3, 0x08a2009a), WTCP(0x7fac135f, 0x0927b836), + WTCP(0x7fa2370a, 0x09ad65c8), WTCP(0x7f97cebd, 0x0a3308bd), + WTCP(0x7f8cda84, 0x0ab8a082), WTCP(0x7f815a6b, 0x0b3e2c86), + WTCP(0x7f754e80, 0x0bc3ac35), WTCP(0x7f68b6ce, 0x0c491efe), + WTCP(0x7f5b9364, 0x0cce844e), WTCP(0x7f4de451, 0x0d53db92), + WTCP(0x7f3fa9a2, 0x0dd92439), WTCP(0x7f30e369, 0x0e5e5db0), + WTCP(0x7f2191b4, 0x0ee38766), WTCP(0x7f11b495, 0x0f68a0c8), + WTCP(0x7f014c1e, 0x0feda943), WTCP(0x7ef05860, 0x1072a048), + WTCP(0x7eded96d, 0x10f78543), WTCP(0x7ecccf5a, 0x117c57a2), + WTCP(0x7eba3a39, 0x120116d5), WTCP(0x7ea71a20, 0x1285c249), + WTCP(0x7e936f22, 0x130a596e), WTCP(0x7e7f3957, 0x138edbb1), + WTCP(0x7e6a78d3, 0x14134881), WTCP(0x7e552dae, 0x14979f4e), + WTCP(0x7e3f57ff, 0x151bdf86), WTCP(0x7e28f7de, 0x15a00897), + WTCP(0x7e120d63, 0x162419f2), WTCP(0x7dfa98a8, 0x16a81305), + WTCP(0x7de299c6, 0x172bf33f), WTCP(0x7dca10d8, 0x17afba11), + WTCP(0x7db0fdf8, 0x183366e9), WTCP(0x7d976142, 0x18b6f936), + WTCP(0x7d7d3ad3, 0x193a706a), WTCP(0x7d628ac6, 0x19bdcbf3), + WTCP(0x7d475139, 0x1a410b41), WTCP(0x7d2b8e4a, 0x1ac42dc5), + WTCP(0x7d0f4218, 0x1b4732ef), WTCP(0x7cf26cc1, 0x1bca1a2f), + WTCP(0x7cd50e65, 0x1c4ce2f6), WTCP(0x7cb72724, 0x1ccf8cb3), + WTCP(0x7c98b71f, 0x1d5216d8), WTCP(0x7c79be78, 0x1dd480d6), + WTCP(0x7c5a3d50, 0x1e56ca1e), WTCP(0x7c3a33ca, 0x1ed8f220), + WTCP(0x7c19a209, 0x1f5af84f), WTCP(0x7bf88830, 0x1fdcdc1b), + WTCP(0x7bd6e665, 0x205e9cf6), WTCP(0x7bb4bccb, 0x20e03a51), + WTCP(0x7b920b89, 0x2161b3a0), WTCP(0x7b6ed2c5, 0x21e30853), + WTCP(0x7b4b12a4, 0x226437dc), WTCP(0x7b26cb4f, 0x22e541af), + WTCP(0x7b01fced, 0x2366253d), WTCP(0x7adca7a6, 0x23e6e1fa), + WTCP(0x7ab6cba4, 0x24677758), WTCP(0x7a90690f, 0x24e7e4c9), + WTCP(0x7a698012, 0x256829c2), WTCP(0x7a4210d8, 0x25e845b6), + WTCP(0x7a1a1b8c, 0x26683818), WTCP(0x79f1a05a, 0x26e8005b), + WTCP(0x79c89f6e, 0x27679df4), WTCP(0x799f18f4, 0x27e71057), + WTCP(0x79750d1c, 0x286656f8), WTCP(0x794a7c12, 0x28e5714b), + WTCP(0x791f6605, 0x29645ec5), WTCP(0x78f3cb25, 0x29e31edb), + WTCP(0x78c7aba2, 0x2a61b101), WTCP(0x789b07ab, 0x2ae014ae), + WTCP(0x786ddf72, 0x2b5e4956), WTCP(0x78403329, 0x2bdc4e6f), + WTCP(0x78120300, 0x2c5a236f), WTCP(0x77e34f2c, 0x2cd7c7cc), + WTCP(0x77b417df, 0x2d553afc), WTCP(0x77845d4e, 0x2dd27c75), + WTCP(0x77541fab, 0x2e4f8bae), WTCP(0x77235f2d, 0x2ecc681e), + WTCP(0x76f21c09, 0x2f49113d), WTCP(0x76c05674, 0x2fc58680), + WTCP(0x768e0ea6, 0x3041c761), WTCP(0x765b44d5, 0x30bdd356), + WTCP(0x7627f939, 0x3139a9d7), WTCP(0x75f42c0b, 0x31b54a5e), + WTCP(0x75bfdd83, 0x3230b461), WTCP(0x758b0ddb, 0x32abe75a), + WTCP(0x7555bd4c, 0x3326e2c3), WTCP(0x751fec11, 0x33a1a612), + WTCP(0x74e99a65, 0x341c30c4), WTCP(0x74b2c884, 0x34968250), + WTCP(0x747b76a9, 0x35109a31), WTCP(0x7443a512, 0x358a77e0), + WTCP(0x740b53fb, 0x36041ad9), WTCP(0x73d283a2, 0x367d8296), + WTCP(0x73993447, 0x36f6ae91), WTCP(0x735f6626, 0x376f9e46), + WTCP(0x73251981, 0x37e85130), WTCP(0x72ea4e96, 0x3860c6cb), + WTCP(0x72af05a7, 0x38d8fe93), WTCP(0x72733ef3, 0x3950f804), + WTCP(0x7236fabe, 0x39c8b29a), WTCP(0x71fa3949, 0x3a402dd2), + WTCP(0x71bcfad6, 0x3ab76929), WTCP(0x717f3fa8, 0x3b2e641c), + WTCP(0x71410805, 0x3ba51e29), WTCP(0x7102542f, 0x3c1b96ce), + WTCP(0x70c3246b, 0x3c91cd88), WTCP(0x708378ff, 0x3d07c1d6), + WTCP(0x70435230, 0x3d7d7337), WTCP(0x7002b045, 0x3df2e129), + WTCP(0x6fc19385, 0x3e680b2c), WTCP(0x6f7ffc37, 0x3edcf0c0), + WTCP(0x6f3deaa4, 0x3f519164), WTCP(0x6efb5f12, 0x3fc5ec98), + WTCP(0x6eb859cc, 0x403a01dc), WTCP(0x6e74db1c, 0x40add0b2), + WTCP(0x6e30e34a, 0x4121589b), WTCP(0x6dec72a2, 0x41949917), + WTCP(0x6da7896e, 0x420791a8), WTCP(0x6d6227fa, 0x427a41d0), + WTCP(0x6d1c4e93, 0x42eca912), WTCP(0x6cd5fd85, 0x435ec6f0), + WTCP(0x6c8f351c, 0x43d09aed), WTCP(0x6c47f5a7, 0x4442248b), + WTCP(0x6c003f74, 0x44b3634f), WTCP(0x6bb812d1, 0x452456bd), + WTCP(0x6b6f700e, 0x4594fe58), WTCP(0x6b265779, 0x460559a4), + WTCP(0x6adcc964, 0x46756828), WTCP(0x6a92c61f, 0x46e52967), + WTCP(0x6a484dfc, 0x47549ce7), WTCP(0x69fd614a, 0x47c3c22f), + WTCP(0x69b2005e, 0x483298c4), WTCP(0x69662b8a, 0x48a1202c), + WTCP(0x6919e320, 0x490f57ee), WTCP(0x68cd2775, 0x497d3f93), + WTCP(0x687ff8dc, 0x49ead6a0), WTCP(0x683257ab, 0x4a581c9e), + WTCP(0x67e44436, 0x4ac51114), WTCP(0x6795bed3, 0x4b31b38d), + WTCP(0x6746c7d8, 0x4b9e0390), WTCP(0x66f75f9b, 0x4c0a00a6), + WTCP(0x66a78675, 0x4c75aa5a), WTCP(0x66573cbb, 0x4ce10034), + WTCP(0x660682c7, 0x4d4c01c0), WTCP(0x65b558f1, 0x4db6ae88), + WTCP(0x6563bf92, 0x4e210617), WTCP(0x6511b703, 0x4e8b07f9), + WTCP(0x64bf3f9f, 0x4ef4b3b9), WTCP(0x646c59bf, 0x4f5e08e3), + WTCP(0x641905bf, 0x4fc70704), WTCP(0x63c543fa, 0x502fada9), + WTCP(0x637114cc, 0x5097fc5e), WTCP(0x631c7892, 0x50fff2b2), + WTCP(0x62c76fa7, 0x51679033), WTCP(0x6271fa69, 0x51ced46e), + WTCP(0x621c1937, 0x5235bef4), WTCP(0x61c5cc6d, 0x529c4f51), + WTCP(0x616f146c, 0x53028518), WTCP(0x6117f191, 0x53685fd6), + WTCP(0x60c0643d, 0x53cddf1d), WTCP(0x60686ccf, 0x5433027d), + WTCP(0x60100ba8, 0x5497c988), WTCP(0x5fb74129, 0x54fc33ce), + WTCP(0x5f5e0db3, 0x556040e2), WTCP(0x5f0471a8, 0x55c3f056), + WTCP(0x5eaa6d6b, 0x562741bd), WTCP(0x5e50015d, 0x568a34a9), + WTCP(0x5df52de3, 0x56ecc8af), WTCP(0x5d99f35f, 0x574efd62), + WTCP(0x5d3e5237, 0x57b0d256), WTCP(0x5ce24acd, 0x58124720), + WTCP(0x5c85dd88, 0x58735b56), WTCP(0x5c290acc, 0x58d40e8c), + WTCP(0x5bcbd300, 0x5934605a), WTCP(0x5b6e3689, 0x59945054), + WTCP(0x5b1035cf, 0x59f3de12), WTCP(0x5ab1d138, 0x5a53092c), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow480[] = { + WTCP(0x7ffff4c5, 0x00359dd2), WTCP(0x7fff9aef, 0x00a0d951), + WTCP(0x7ffee744, 0x010c1460), WTCP(0x7ffdd9c4, 0x01774eb2), + WTCP(0x7ffc726f, 0x01e287fc), WTCP(0x7ffab147, 0x024dbff4), + WTCP(0x7ff8964d, 0x02b8f64e), WTCP(0x7ff62182, 0x03242abf), + WTCP(0x7ff352e8, 0x038f5cfb), WTCP(0x7ff02a82, 0x03fa8cb8), + WTCP(0x7feca851, 0x0465b9aa), WTCP(0x7fe8cc57, 0x04d0e386), + WTCP(0x7fe49698, 0x053c0a01), WTCP(0x7fe00716, 0x05a72ccf), + WTCP(0x7fdb1dd5, 0x06124ba5), WTCP(0x7fd5dad8, 0x067d6639), + WTCP(0x7fd03e23, 0x06e87c3f), WTCP(0x7fca47b9, 0x07538d6b), + WTCP(0x7fc3f7a0, 0x07be9973), WTCP(0x7fbd4dda, 0x0829a00c), + WTCP(0x7fb64a6e, 0x0894a0ea), WTCP(0x7faeed5f, 0x08ff9bc2), + WTCP(0x7fa736b4, 0x096a9049), WTCP(0x7f9f2671, 0x09d57e35), + WTCP(0x7f96bc9c, 0x0a40653a), WTCP(0x7f8df93c, 0x0aab450d), + WTCP(0x7f84dc55, 0x0b161d63), WTCP(0x7f7b65ef, 0x0b80edf1), + WTCP(0x7f719611, 0x0bebb66c), WTCP(0x7f676cc0, 0x0c56768a), + WTCP(0x7f5cea05, 0x0cc12dff), WTCP(0x7f520de6, 0x0d2bdc80), + WTCP(0x7f46d86c, 0x0d9681c2), WTCP(0x7f3b499d, 0x0e011d7c), + WTCP(0x7f2f6183, 0x0e6baf61), WTCP(0x7f232026, 0x0ed63727), + WTCP(0x7f16858e, 0x0f40b483), WTCP(0x7f0991c4, 0x0fab272b), + WTCP(0x7efc44d0, 0x10158ed4), WTCP(0x7eee9ebe, 0x107feb33), + WTCP(0x7ee09f95, 0x10ea3bfd), WTCP(0x7ed24761, 0x115480e9), + WTCP(0x7ec3962a, 0x11beb9aa), WTCP(0x7eb48bfb, 0x1228e5f8), + WTCP(0x7ea528e0, 0x12930586), WTCP(0x7e956ce1, 0x12fd180b), + WTCP(0x7e85580c, 0x13671d3d), WTCP(0x7e74ea6a, 0x13d114d0), + WTCP(0x7e642408, 0x143afe7b), WTCP(0x7e5304f2, 0x14a4d9f4), + WTCP(0x7e418d32, 0x150ea6ef), WTCP(0x7e2fbcd6, 0x15786522), + WTCP(0x7e1d93ea, 0x15e21445), WTCP(0x7e0b127a, 0x164bb40b), + WTCP(0x7df83895, 0x16b5442b), WTCP(0x7de50646, 0x171ec45c), + WTCP(0x7dd17b9c, 0x17883452), WTCP(0x7dbd98a4, 0x17f193c5), + WTCP(0x7da95d6c, 0x185ae269), WTCP(0x7d94ca03, 0x18c41ff6), + WTCP(0x7d7fde76, 0x192d4c21), WTCP(0x7d6a9ad5, 0x199666a0), + WTCP(0x7d54ff2e, 0x19ff6f2a), WTCP(0x7d3f0b90, 0x1a686575), + WTCP(0x7d28c00c, 0x1ad14938), WTCP(0x7d121cb0, 0x1b3a1a28), + WTCP(0x7cfb218c, 0x1ba2d7fc), WTCP(0x7ce3ceb2, 0x1c0b826a), + WTCP(0x7ccc2430, 0x1c74192a), WTCP(0x7cb42217, 0x1cdc9bf2), + WTCP(0x7c9bc87a, 0x1d450a78), WTCP(0x7c831767, 0x1dad6473), + WTCP(0x7c6a0ef2, 0x1e15a99a), WTCP(0x7c50af2b, 0x1e7dd9a4), + WTCP(0x7c36f824, 0x1ee5f447), WTCP(0x7c1ce9ef, 0x1f4df93a), + WTCP(0x7c02849f, 0x1fb5e836), WTCP(0x7be7c847, 0x201dc0ef), + WTCP(0x7bccb4f8, 0x2085831f), WTCP(0x7bb14ac5, 0x20ed2e7b), + WTCP(0x7b9589c3, 0x2154c2bb), WTCP(0x7b797205, 0x21bc3f97), + WTCP(0x7b5d039e, 0x2223a4c5), WTCP(0x7b403ea2, 0x228af1fe), + WTCP(0x7b232325, 0x22f226f8), WTCP(0x7b05b13d, 0x2359436c), + WTCP(0x7ae7e8fc, 0x23c04710), WTCP(0x7ac9ca7a, 0x2427319d), + WTCP(0x7aab55ca, 0x248e02cb), WTCP(0x7a8c8b01, 0x24f4ba50), + WTCP(0x7a6d6a37, 0x255b57e6), WTCP(0x7a4df380, 0x25c1db44), + WTCP(0x7a2e26f2, 0x26284422), WTCP(0x7a0e04a4, 0x268e9238), + WTCP(0x79ed8cad, 0x26f4c53e), WTCP(0x79ccbf22, 0x275adcee), + WTCP(0x79ab9c1c, 0x27c0d8fe), WTCP(0x798a23b1, 0x2826b928), + WTCP(0x796855f9, 0x288c7d24), WTCP(0x7946330c, 0x28f224ab), + WTCP(0x7923bb01, 0x2957af74), WTCP(0x7900edf2, 0x29bd1d3a), + WTCP(0x78ddcbf5, 0x2a226db5), WTCP(0x78ba5524, 0x2a87a09d), + WTCP(0x78968998, 0x2aecb5ac), WTCP(0x7872696a, 0x2b51ac9a), + WTCP(0x784df4b3, 0x2bb68522), WTCP(0x78292b8d, 0x2c1b3efb), + WTCP(0x78040e12, 0x2c7fd9e0), WTCP(0x77de9c5b, 0x2ce45589), + WTCP(0x77b8d683, 0x2d48b1b1), WTCP(0x7792bca5, 0x2dacee11), + WTCP(0x776c4edb, 0x2e110a62), WTCP(0x77458d40, 0x2e75065e), + WTCP(0x771e77f0, 0x2ed8e1c0), WTCP(0x76f70f05, 0x2f3c9c40), + WTCP(0x76cf529c, 0x2fa03599), WTCP(0x76a742d1, 0x3003ad85), + WTCP(0x767edfbe, 0x306703bf), WTCP(0x76562982, 0x30ca3800), + WTCP(0x762d2038, 0x312d4a03), WTCP(0x7603c3fd, 0x31903982), + WTCP(0x75da14ef, 0x31f30638), WTCP(0x75b01329, 0x3255afe0), + WTCP(0x7585becb, 0x32b83634), WTCP(0x755b17f2, 0x331a98ef), + WTCP(0x75301ebb, 0x337cd7cd), WTCP(0x7504d345, 0x33def287), + WTCP(0x74d935ae, 0x3440e8da), WTCP(0x74ad4615, 0x34a2ba81), + WTCP(0x74810499, 0x35046736), WTCP(0x74547158, 0x3565eeb6), + WTCP(0x74278c72, 0x35c750bc), WTCP(0x73fa5607, 0x36288d03), + WTCP(0x73ccce36, 0x3689a348), WTCP(0x739ef51f, 0x36ea9346), + WTCP(0x7370cae2, 0x374b5cb9), WTCP(0x73424fa0, 0x37abff5d), + WTCP(0x73138379, 0x380c7aee), WTCP(0x72e4668f, 0x386ccf2a), + WTCP(0x72b4f902, 0x38ccfbcb), WTCP(0x72853af3, 0x392d008f), + WTCP(0x72552c85, 0x398cdd32), WTCP(0x7224cdd8, 0x39ec9172), + WTCP(0x71f41f0f, 0x3a4c1d09), WTCP(0x71c3204c, 0x3aab7fb7), + WTCP(0x7191d1b1, 0x3b0ab937), WTCP(0x71603361, 0x3b69c947), + WTCP(0x712e457f, 0x3bc8afa5), WTCP(0x70fc082d, 0x3c276c0d), + WTCP(0x70c97b90, 0x3c85fe3d), WTCP(0x70969fca, 0x3ce465f3), + WTCP(0x706374ff, 0x3d42a2ec), WTCP(0x702ffb54, 0x3da0b4e7), + WTCP(0x6ffc32eb, 0x3dfe9ba1), WTCP(0x6fc81bea, 0x3e5c56d8), + WTCP(0x6f93b676, 0x3eb9e64b), WTCP(0x6f5f02b2, 0x3f1749b8), + WTCP(0x6f2a00c4, 0x3f7480dd), WTCP(0x6ef4b0d1, 0x3fd18b7a), + WTCP(0x6ebf12ff, 0x402e694c), WTCP(0x6e892772, 0x408b1a12), + WTCP(0x6e52ee52, 0x40e79d8c), WTCP(0x6e1c67c4, 0x4143f379), + WTCP(0x6de593ee, 0x41a01b97), WTCP(0x6dae72f7, 0x41fc15a6), + WTCP(0x6d770506, 0x4257e166), WTCP(0x6d3f4a40, 0x42b37e96), + WTCP(0x6d0742cf, 0x430eecf6), WTCP(0x6cceeed8, 0x436a2c45), + WTCP(0x6c964e83, 0x43c53c44), WTCP(0x6c5d61f9, 0x44201cb2), + WTCP(0x6c242960, 0x447acd50), WTCP(0x6beaa4e2, 0x44d54ddf), + WTCP(0x6bb0d4a7, 0x452f9e1e), WTCP(0x6b76b8d6, 0x4589bdcf), + WTCP(0x6b3c519a, 0x45e3acb1), WTCP(0x6b019f1a, 0x463d6a87), + WTCP(0x6ac6a180, 0x4696f710), WTCP(0x6a8b58f6, 0x46f0520f), + WTCP(0x6a4fc5a6, 0x47497b44), WTCP(0x6a13e7b8, 0x47a27271), + WTCP(0x69d7bf57, 0x47fb3757), WTCP(0x699b4cad, 0x4853c9b9), + WTCP(0x695e8fe5, 0x48ac2957), WTCP(0x69218929, 0x490455f4), + WTCP(0x68e438a4, 0x495c4f52), WTCP(0x68a69e81, 0x49b41533), + WTCP(0x6868baec, 0x4a0ba75b), WTCP(0x682a8e0f, 0x4a63058a), + WTCP(0x67ec1817, 0x4aba2f84), WTCP(0x67ad592f, 0x4b11250c), + WTCP(0x676e5183, 0x4b67e5e4), WTCP(0x672f013f, 0x4bbe71d1), + WTCP(0x66ef6891, 0x4c14c894), WTCP(0x66af87a4, 0x4c6ae9f2), + WTCP(0x666f5ea6, 0x4cc0d5ae), WTCP(0x662eedc3, 0x4d168b8b), + WTCP(0x65ee3529, 0x4d6c0b4e), WTCP(0x65ad3505, 0x4dc154bb), + WTCP(0x656bed84, 0x4e166795), WTCP(0x652a5ed6, 0x4e6b43a2), + WTCP(0x64e88926, 0x4ebfe8a5), WTCP(0x64a66ca5, 0x4f145662), + WTCP(0x6464097f, 0x4f688ca0), WTCP(0x64215fe5, 0x4fbc8b22), + WTCP(0x63de7003, 0x501051ae), WTCP(0x639b3a0b, 0x5063e008), + WTCP(0x6357be2a, 0x50b735f8), WTCP(0x6313fc90, 0x510a5340), + WTCP(0x62cff56c, 0x515d37a9), WTCP(0x628ba8ef, 0x51afe2f6), + WTCP(0x62471749, 0x520254ef), WTCP(0x620240a8, 0x52548d59), + WTCP(0x61bd253f, 0x52a68bfb), WTCP(0x6177c53c, 0x52f8509b), + WTCP(0x613220d2, 0x5349daff), WTCP(0x60ec3830, 0x539b2af0), + WTCP(0x60a60b88, 0x53ec4032), WTCP(0x605f9b0b, 0x543d1a8e), + WTCP(0x6018e6eb, 0x548db9cb), WTCP(0x5fd1ef59, 0x54de1db1), + WTCP(0x5f8ab487, 0x552e4605), WTCP(0x5f4336a7, 0x557e3292), + WTCP(0x5efb75ea, 0x55cde31e), WTCP(0x5eb37285, 0x561d5771), + WTCP(0x5e6b2ca8, 0x566c8f55), WTCP(0x5e22a487, 0x56bb8a90), + WTCP(0x5dd9da55, 0x570a48ec), WTCP(0x5d90ce45, 0x5758ca31), + WTCP(0x5d47808a, 0x57a70e29), WTCP(0x5cfdf157, 0x57f5149d), + WTCP(0x5cb420e0, 0x5842dd54), WTCP(0x5c6a0f59, 0x5890681a), + WTCP(0x5c1fbcf6, 0x58ddb4b8), WTCP(0x5bd529eb, 0x592ac2f7), + WTCP(0x5b8a566c, 0x597792a1), WTCP(0x5b3f42ae, 0x59c42381), + WTCP(0x5af3eee6, 0x5a107561), WTCP(0x5aa85b48, 0x5a5c880a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow512[] = { + WTCP(0x7ffff621, 0x003243f5), WTCP(0x7fffa72c, 0x0096cbc1), + WTCP(0x7fff0943, 0x00fb5330), WTCP(0x7ffe1c65, 0x015fda03), + WTCP(0x7ffce093, 0x01c45ffe), WTCP(0x7ffb55ce, 0x0228e4e2), + WTCP(0x7ff97c18, 0x028d6870), WTCP(0x7ff75370, 0x02f1ea6c), + WTCP(0x7ff4dbd9, 0x03566a96), WTCP(0x7ff21553, 0x03bae8b2), + WTCP(0x7feeffe1, 0x041f6480), WTCP(0x7feb9b85, 0x0483ddc3), + WTCP(0x7fe7e841, 0x04e8543e), WTCP(0x7fe3e616, 0x054cc7b1), + WTCP(0x7fdf9508, 0x05b137df), WTCP(0x7fdaf519, 0x0615a48b), + WTCP(0x7fd6064c, 0x067a0d76), WTCP(0x7fd0c8a3, 0x06de7262), + WTCP(0x7fcb3c23, 0x0742d311), WTCP(0x7fc560cf, 0x07a72f45), + WTCP(0x7fbf36aa, 0x080b86c2), WTCP(0x7fb8bdb8, 0x086fd947), + WTCP(0x7fb1f5fc, 0x08d42699), WTCP(0x7faadf7c, 0x09386e78), + WTCP(0x7fa37a3c, 0x099cb0a7), WTCP(0x7f9bc640, 0x0a00ece8), + WTCP(0x7f93c38c, 0x0a6522fe), WTCP(0x7f8b7227, 0x0ac952aa), + WTCP(0x7f82d214, 0x0b2d7baf), WTCP(0x7f79e35a, 0x0b919dcf), + WTCP(0x7f70a5fe, 0x0bf5b8cb), WTCP(0x7f671a05, 0x0c59cc68), + WTCP(0x7f5d3f75, 0x0cbdd865), WTCP(0x7f531655, 0x0d21dc87), + WTCP(0x7f489eaa, 0x0d85d88f), WTCP(0x7f3dd87c, 0x0de9cc40), + WTCP(0x7f32c3d1, 0x0e4db75b), WTCP(0x7f2760af, 0x0eb199a4), + WTCP(0x7f1baf1e, 0x0f1572dc), WTCP(0x7f0faf25, 0x0f7942c7), + WTCP(0x7f0360cb, 0x0fdd0926), WTCP(0x7ef6c418, 0x1040c5bb), + WTCP(0x7ee9d914, 0x10a4784b), WTCP(0x7edc9fc6, 0x11082096), + WTCP(0x7ecf1837, 0x116bbe60), WTCP(0x7ec14270, 0x11cf516a), + WTCP(0x7eb31e78, 0x1232d979), WTCP(0x7ea4ac58, 0x1296564d), + WTCP(0x7e95ec1a, 0x12f9c7aa), WTCP(0x7e86ddc6, 0x135d2d53), + WTCP(0x7e778166, 0x13c0870a), WTCP(0x7e67d703, 0x1423d492), + WTCP(0x7e57dea7, 0x148715ae), WTCP(0x7e47985b, 0x14ea4a1f), + WTCP(0x7e37042a, 0x154d71aa), WTCP(0x7e26221f, 0x15b08c12), + WTCP(0x7e14f242, 0x16139918), WTCP(0x7e0374a0, 0x1676987f), + WTCP(0x7df1a942, 0x16d98a0c), WTCP(0x7ddf9034, 0x173c6d80), + WTCP(0x7dcd2981, 0x179f429f), WTCP(0x7dba7534, 0x1802092c), + WTCP(0x7da77359, 0x1864c0ea), WTCP(0x7d9423fc, 0x18c7699b), + WTCP(0x7d808728, 0x192a0304), WTCP(0x7d6c9ce9, 0x198c8ce7), + WTCP(0x7d58654d, 0x19ef0707), WTCP(0x7d43e05e, 0x1a517128), + WTCP(0x7d2f0e2b, 0x1ab3cb0d), WTCP(0x7d19eebf, 0x1b161479), + WTCP(0x7d048228, 0x1b784d30), WTCP(0x7ceec873, 0x1bda74f6), + WTCP(0x7cd8c1ae, 0x1c3c8b8c), WTCP(0x7cc26de5, 0x1c9e90b8), + WTCP(0x7cabcd28, 0x1d00843d), WTCP(0x7c94df83, 0x1d6265dd), + WTCP(0x7c7da505, 0x1dc4355e), WTCP(0x7c661dbc, 0x1e25f282), + WTCP(0x7c4e49b7, 0x1e879d0d), WTCP(0x7c362904, 0x1ee934c3), + WTCP(0x7c1dbbb3, 0x1f4ab968), WTCP(0x7c0501d2, 0x1fac2abf), + WTCP(0x7bebfb70, 0x200d888d), WTCP(0x7bd2a89e, 0x206ed295), + WTCP(0x7bb9096b, 0x20d0089c), WTCP(0x7b9f1de6, 0x21312a65), + WTCP(0x7b84e61f, 0x219237b5), WTCP(0x7b6a6227, 0x21f3304f), + WTCP(0x7b4f920e, 0x225413f8), WTCP(0x7b3475e5, 0x22b4e274), + WTCP(0x7b190dbc, 0x23159b88), WTCP(0x7afd59a4, 0x23763ef7), + WTCP(0x7ae159ae, 0x23d6cc87), WTCP(0x7ac50dec, 0x243743fa), + WTCP(0x7aa8766f, 0x2497a517), WTCP(0x7a8b9348, 0x24f7efa2), + WTCP(0x7a6e648a, 0x2558235f), WTCP(0x7a50ea47, 0x25b84012), + WTCP(0x7a332490, 0x26184581), WTCP(0x7a151378, 0x26783370), + WTCP(0x79f6b711, 0x26d809a5), WTCP(0x79d80f6f, 0x2737c7e3), + WTCP(0x79b91ca4, 0x27976df1), WTCP(0x7999dec4, 0x27f6fb92), + WTCP(0x797a55e0, 0x2856708d), WTCP(0x795a820e, 0x28b5cca5), + WTCP(0x793a6361, 0x29150fa1), WTCP(0x7919f9ec, 0x29743946), + WTCP(0x78f945c3, 0x29d34958), WTCP(0x78d846fb, 0x2a323f9e), + WTCP(0x78b6fda8, 0x2a911bdc), WTCP(0x789569df, 0x2aefddd8), + WTCP(0x78738bb3, 0x2b4e8558), WTCP(0x7851633b, 0x2bad1221), + WTCP(0x782ef08b, 0x2c0b83fa), WTCP(0x780c33b8, 0x2c69daa6), + WTCP(0x77e92cd9, 0x2cc815ee), WTCP(0x77c5dc01, 0x2d263596), + WTCP(0x77a24148, 0x2d843964), WTCP(0x777e5cc3, 0x2de2211e), + WTCP(0x775a2e89, 0x2e3fec8b), WTCP(0x7735b6af, 0x2e9d9b70), + WTCP(0x7710f54c, 0x2efb2d95), WTCP(0x76ebea77, 0x2f58a2be), + WTCP(0x76c69647, 0x2fb5fab2), WTCP(0x76a0f8d2, 0x30133539), + WTCP(0x767b1231, 0x30705217), WTCP(0x7654e279, 0x30cd5115), + WTCP(0x762e69c4, 0x312a31f8), WTCP(0x7607a828, 0x3186f487), + WTCP(0x75e09dbd, 0x31e39889), WTCP(0x75b94a9c, 0x32401dc6), + WTCP(0x7591aedd, 0x329c8402), WTCP(0x7569ca99, 0x32f8cb07), + WTCP(0x75419de7, 0x3354f29b), WTCP(0x751928e0, 0x33b0fa84), + WTCP(0x74f06b9e, 0x340ce28b), WTCP(0x74c7663a, 0x3468aa76), + WTCP(0x749e18cd, 0x34c4520d), WTCP(0x74748371, 0x351fd918), + WTCP(0x744aa63f, 0x357b3f5d), WTCP(0x74208150, 0x35d684a6), + WTCP(0x73f614c0, 0x3631a8b8), WTCP(0x73cb60a8, 0x368cab5c), + WTCP(0x73a06522, 0x36e78c5b), WTCP(0x73752249, 0x37424b7b), + WTCP(0x73499838, 0x379ce885), WTCP(0x731dc70a, 0x37f76341), + WTCP(0x72f1aed9, 0x3851bb77), WTCP(0x72c54fc1, 0x38abf0ef), + WTCP(0x7298a9dd, 0x39060373), WTCP(0x726bbd48, 0x395ff2c9), + WTCP(0x723e8a20, 0x39b9bebc), WTCP(0x7211107e, 0x3a136712), + WTCP(0x71e35080, 0x3a6ceb96), WTCP(0x71b54a41, 0x3ac64c0f), + WTCP(0x7186fdde, 0x3b1f8848), WTCP(0x71586b74, 0x3b78a007), + WTCP(0x7129931f, 0x3bd19318), WTCP(0x70fa74fc, 0x3c2a6142), + WTCP(0x70cb1128, 0x3c830a50), WTCP(0x709b67c0, 0x3cdb8e09), + WTCP(0x706b78e3, 0x3d33ec39), WTCP(0x703b44ad, 0x3d8c24a8), + WTCP(0x700acb3c, 0x3de4371f), WTCP(0x6fda0cae, 0x3e3c2369), + WTCP(0x6fa90921, 0x3e93e950), WTCP(0x6f77c0b3, 0x3eeb889c), + WTCP(0x6f463383, 0x3f430119), WTCP(0x6f1461b0, 0x3f9a5290), + WTCP(0x6ee24b57, 0x3ff17cca), WTCP(0x6eaff099, 0x40487f94), + WTCP(0x6e7d5193, 0x409f5ab6), WTCP(0x6e4a6e66, 0x40f60dfb), + WTCP(0x6e174730, 0x414c992f), WTCP(0x6de3dc11, 0x41a2fc1a), + WTCP(0x6db02d29, 0x41f93689), WTCP(0x6d7c3a98, 0x424f4845), + WTCP(0x6d48047e, 0x42a5311b), WTCP(0x6d138afb, 0x42faf0d4), + WTCP(0x6cdece2f, 0x4350873c), WTCP(0x6ca9ce3b, 0x43a5f41e), + WTCP(0x6c748b3f, 0x43fb3746), WTCP(0x6c3f055d, 0x4450507e), + WTCP(0x6c093cb6, 0x44a53f93), WTCP(0x6bd3316a, 0x44fa0450), + WTCP(0x6b9ce39b, 0x454e9e80), WTCP(0x6b66536b, 0x45a30df0), + WTCP(0x6b2f80fb, 0x45f7526b), WTCP(0x6af86c6c, 0x464b6bbe), + WTCP(0x6ac115e2, 0x469f59b4), WTCP(0x6a897d7d, 0x46f31c1a), + WTCP(0x6a51a361, 0x4746b2bc), WTCP(0x6a1987b0, 0x479a1d67), + WTCP(0x69e12a8c, 0x47ed5be6), WTCP(0x69a88c19, 0x48406e08), + WTCP(0x696fac78, 0x48935397), WTCP(0x69368bce, 0x48e60c62), + WTCP(0x68fd2a3d, 0x49389836), WTCP(0x68c387e9, 0x498af6df), + WTCP(0x6889a4f6, 0x49dd282a), WTCP(0x684f8186, 0x4a2f2be6), + WTCP(0x68151dbe, 0x4a8101de), WTCP(0x67da79c3, 0x4ad2a9e2), + WTCP(0x679f95b7, 0x4b2423be), WTCP(0x676471c0, 0x4b756f40), + WTCP(0x67290e02, 0x4bc68c36), WTCP(0x66ed6aa1, 0x4c177a6e), + WTCP(0x66b187c3, 0x4c6839b7), WTCP(0x6675658c, 0x4cb8c9dd), + WTCP(0x66390422, 0x4d092ab0), WTCP(0x65fc63a9, 0x4d595bfe), + WTCP(0x65bf8447, 0x4da95d96), WTCP(0x65826622, 0x4df92f46), + WTCP(0x6545095f, 0x4e48d0dd), WTCP(0x65076e25, 0x4e984229), + WTCP(0x64c99498, 0x4ee782fb), WTCP(0x648b7ce0, 0x4f369320), + WTCP(0x644d2722, 0x4f857269), WTCP(0x640e9386, 0x4fd420a4), + WTCP(0x63cfc231, 0x50229da1), WTCP(0x6390b34a, 0x5070e92f), + WTCP(0x635166f9, 0x50bf031f), WTCP(0x6311dd64, 0x510ceb40), + WTCP(0x62d216b3, 0x515aa162), WTCP(0x6292130c, 0x51a82555), + WTCP(0x6251d298, 0x51f576ea), WTCP(0x6211557e, 0x524295f0), + WTCP(0x61d09be5, 0x528f8238), WTCP(0x618fa5f7, 0x52dc3b92), + WTCP(0x614e73da, 0x5328c1d0), WTCP(0x610d05b7, 0x537514c2), + WTCP(0x60cb5bb7, 0x53c13439), WTCP(0x60897601, 0x540d2005), + WTCP(0x604754bf, 0x5458d7f9), WTCP(0x6004f819, 0x54a45be6), + WTCP(0x5fc26038, 0x54efab9c), WTCP(0x5f7f8d46, 0x553ac6ee), + WTCP(0x5f3c7f6b, 0x5585adad), WTCP(0x5ef936d1, 0x55d05faa), + WTCP(0x5eb5b3a2, 0x561adcb9), WTCP(0x5e71f606, 0x566524aa), + WTCP(0x5e2dfe29, 0x56af3750), WTCP(0x5de9cc33, 0x56f9147e), + WTCP(0x5da5604f, 0x5742bc06), WTCP(0x5d60baa7, 0x578c2dba), + WTCP(0x5d1bdb65, 0x57d5696d), WTCP(0x5cd6c2b5, 0x581e6ef1), + WTCP(0x5c9170bf, 0x58673e1b), WTCP(0x5c4be5b0, 0x58afd6bd), + WTCP(0x5c0621b2, 0x58f838a9), WTCP(0x5bc024f0, 0x594063b5), + WTCP(0x5b79ef96, 0x598857b2), WTCP(0x5b3381ce, 0x59d01475), + WTCP(0x5aecdbc5, 0x5a1799d1), WTCP(0x5aa5fda5, 0x5a5ee79a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow768[] = { + WTCP(0x7ffffb9d, 0x002182a4), WTCP(0x7fffd886, 0x006487e3), + WTCP(0x7fff9257, 0x00a78d06), WTCP(0x7fff2910, 0x00ea91fc), + WTCP(0x7ffe9cb2, 0x012d96b1), WTCP(0x7ffded3d, 0x01709b13), + WTCP(0x7ffd1ab2, 0x01b39f11), WTCP(0x7ffc250f, 0x01f6a297), + WTCP(0x7ffb0c56, 0x0239a593), WTCP(0x7ff9d087, 0x027ca7f3), + WTCP(0x7ff871a2, 0x02bfa9a4), WTCP(0x7ff6efa7, 0x0302aa95), + WTCP(0x7ff54a98, 0x0345aab2), WTCP(0x7ff38274, 0x0388a9ea), + WTCP(0x7ff1973b, 0x03cba829), WTCP(0x7fef88ef, 0x040ea55e), + WTCP(0x7fed5791, 0x0451a177), WTCP(0x7feb031f, 0x04949c60), + WTCP(0x7fe88b9c, 0x04d79608), WTCP(0x7fe5f108, 0x051a8e5c), + WTCP(0x7fe33364, 0x055d854a), WTCP(0x7fe052af, 0x05a07abf), + WTCP(0x7fdd4eec, 0x05e36ea9), WTCP(0x7fda281b, 0x062660f6), + WTCP(0x7fd6de3d, 0x06695194), WTCP(0x7fd37153, 0x06ac406f), + WTCP(0x7fcfe15d, 0x06ef2d76), WTCP(0x7fcc2e5d, 0x07321897), + WTCP(0x7fc85854, 0x077501be), WTCP(0x7fc45f42, 0x07b7e8da), + WTCP(0x7fc04329, 0x07facdd9), WTCP(0x7fbc040a, 0x083db0a7), + WTCP(0x7fb7a1e6, 0x08809133), WTCP(0x7fb31cbf, 0x08c36f6a), + WTCP(0x7fae7495, 0x09064b3a), WTCP(0x7fa9a96a, 0x09492491), + WTCP(0x7fa4bb3f, 0x098bfb5c), WTCP(0x7f9faa15, 0x09cecf89), + WTCP(0x7f9a75ef, 0x0a11a106), WTCP(0x7f951ecc, 0x0a546fc0), + WTCP(0x7f8fa4b0, 0x0a973ba5), WTCP(0x7f8a079a, 0x0ada04a3), + WTCP(0x7f84478e, 0x0b1ccaa7), WTCP(0x7f7e648c, 0x0b5f8d9f), + WTCP(0x7f785e96, 0x0ba24d79), WTCP(0x7f7235ad, 0x0be50a23), + WTCP(0x7f6be9d4, 0x0c27c389), WTCP(0x7f657b0c, 0x0c6a799b), + WTCP(0x7f5ee957, 0x0cad2c45), WTCP(0x7f5834b7, 0x0cefdb76), + WTCP(0x7f515d2d, 0x0d32871a), WTCP(0x7f4a62bb, 0x0d752f20), + WTCP(0x7f434563, 0x0db7d376), WTCP(0x7f3c0528, 0x0dfa7409), + WTCP(0x7f34a20b, 0x0e3d10c7), WTCP(0x7f2d1c0e, 0x0e7fa99e), + WTCP(0x7f257334, 0x0ec23e7b), WTCP(0x7f1da77e, 0x0f04cf4c), + WTCP(0x7f15b8ee, 0x0f475bff), WTCP(0x7f0da787, 0x0f89e482), + WTCP(0x7f05734b, 0x0fcc68c2), WTCP(0x7efd1c3c, 0x100ee8ad), + WTCP(0x7ef4a25d, 0x10516432), WTCP(0x7eec05af, 0x1093db3d), + WTCP(0x7ee34636, 0x10d64dbd), WTCP(0x7eda63f3, 0x1118bb9f), + WTCP(0x7ed15ee9, 0x115b24d1), WTCP(0x7ec8371a, 0x119d8941), + WTCP(0x7ebeec89, 0x11dfe8dc), WTCP(0x7eb57f39, 0x12224392), + WTCP(0x7eabef2c, 0x1264994e), WTCP(0x7ea23c65, 0x12a6ea00), + WTCP(0x7e9866e6, 0x12e93594), WTCP(0x7e8e6eb2, 0x132b7bf9), + WTCP(0x7e8453cc, 0x136dbd1d), WTCP(0x7e7a1636, 0x13aff8ed), + WTCP(0x7e6fb5f4, 0x13f22f58), WTCP(0x7e653308, 0x1434604a), + WTCP(0x7e5a8d75, 0x14768bb3), WTCP(0x7e4fc53e, 0x14b8b17f), + WTCP(0x7e44da66, 0x14fad19e), WTCP(0x7e39ccf0, 0x153cebfb), + WTCP(0x7e2e9cdf, 0x157f0086), WTCP(0x7e234a36, 0x15c10f2d), + WTCP(0x7e17d4f8, 0x160317dc), WTCP(0x7e0c3d29, 0x16451a83), + WTCP(0x7e0082cb, 0x1687170f), WTCP(0x7df4a5e2, 0x16c90d6e), + WTCP(0x7de8a670, 0x170afd8d), WTCP(0x7ddc847a, 0x174ce75b), + WTCP(0x7dd04003, 0x178ecac6), WTCP(0x7dc3d90d, 0x17d0a7bc), + WTCP(0x7db74f9d, 0x18127e2a), WTCP(0x7daaa3b5, 0x18544dff), + WTCP(0x7d9dd55a, 0x18961728), WTCP(0x7d90e48f, 0x18d7d993), + WTCP(0x7d83d156, 0x1919952f), WTCP(0x7d769bb5, 0x195b49ea), + WTCP(0x7d6943ae, 0x199cf7b0), WTCP(0x7d5bc946, 0x19de9e72), + WTCP(0x7d4e2c7f, 0x1a203e1b), WTCP(0x7d406d5e, 0x1a61d69b), + WTCP(0x7d328be6, 0x1aa367df), WTCP(0x7d24881b, 0x1ae4f1d6), + WTCP(0x7d166201, 0x1b26746d), WTCP(0x7d08199c, 0x1b67ef93), + WTCP(0x7cf9aef0, 0x1ba96335), WTCP(0x7ceb2201, 0x1beacf42), + WTCP(0x7cdc72d3, 0x1c2c33a7), WTCP(0x7ccda169, 0x1c6d9053), + WTCP(0x7cbeadc8, 0x1caee534), WTCP(0x7caf97f4, 0x1cf03238), + WTCP(0x7ca05ff1, 0x1d31774d), WTCP(0x7c9105c3, 0x1d72b461), + WTCP(0x7c81896f, 0x1db3e962), WTCP(0x7c71eaf9, 0x1df5163f), + WTCP(0x7c622a64, 0x1e363ae5), WTCP(0x7c5247b6, 0x1e775743), + WTCP(0x7c4242f2, 0x1eb86b46), WTCP(0x7c321c1e, 0x1ef976de), + WTCP(0x7c21d33c, 0x1f3a79f7), WTCP(0x7c116853, 0x1f7b7481), + WTCP(0x7c00db66, 0x1fbc6669), WTCP(0x7bf02c7b, 0x1ffd4f9e), + WTCP(0x7bdf5b94, 0x203e300d), WTCP(0x7bce68b8, 0x207f07a6), + WTCP(0x7bbd53eb, 0x20bfd656), WTCP(0x7bac1d31, 0x21009c0c), + WTCP(0x7b9ac490, 0x214158b5), WTCP(0x7b894a0b, 0x21820c41), + WTCP(0x7b77ada8, 0x21c2b69c), WTCP(0x7b65ef6c, 0x220357b6), + WTCP(0x7b540f5b, 0x2243ef7d), WTCP(0x7b420d7a, 0x22847de0), + WTCP(0x7b2fe9cf, 0x22c502cb), WTCP(0x7b1da45e, 0x23057e2e), + WTCP(0x7b0b3d2c, 0x2345eff8), WTCP(0x7af8b43f, 0x23865816), + WTCP(0x7ae6099b, 0x23c6b676), WTCP(0x7ad33d45, 0x24070b08), + WTCP(0x7ac04f44, 0x244755b9), WTCP(0x7aad3f9b, 0x24879678), + WTCP(0x7a9a0e50, 0x24c7cd33), WTCP(0x7a86bb68, 0x2507f9d8), + WTCP(0x7a7346e9, 0x25481c57), WTCP(0x7a5fb0d8, 0x2588349d), + WTCP(0x7a4bf93a, 0x25c84299), WTCP(0x7a382015, 0x26084639), + WTCP(0x7a24256f, 0x26483f6c), WTCP(0x7a10094c, 0x26882e21), + WTCP(0x79fbcbb2, 0x26c81245), WTCP(0x79e76ca7, 0x2707ebc7), + WTCP(0x79d2ec30, 0x2747ba95), WTCP(0x79be4a53, 0x27877e9f), + WTCP(0x79a98715, 0x27c737d3), WTCP(0x7994a27d, 0x2806e61f), + WTCP(0x797f9c90, 0x28468971), WTCP(0x796a7554, 0x288621b9), + WTCP(0x79552cce, 0x28c5aee5), WTCP(0x793fc305, 0x290530e3), + WTCP(0x792a37fe, 0x2944a7a2), WTCP(0x79148bbf, 0x29841311), + WTCP(0x78febe4e, 0x29c3731e), WTCP(0x78e8cfb2, 0x2a02c7b8), + WTCP(0x78d2bfef, 0x2a4210ce), WTCP(0x78bc8f0d, 0x2a814e4d), + WTCP(0x78a63d11, 0x2ac08026), WTCP(0x788fca01, 0x2affa646), + WTCP(0x787935e4, 0x2b3ec09c), WTCP(0x786280bf, 0x2b7dcf17), + WTCP(0x784baa9a, 0x2bbcd1a6), WTCP(0x7834b37a, 0x2bfbc837), + WTCP(0x781d9b65, 0x2c3ab2b9), WTCP(0x78066262, 0x2c79911b), + WTCP(0x77ef0877, 0x2cb8634b), WTCP(0x77d78daa, 0x2cf72939), + WTCP(0x77bff203, 0x2d35e2d3), WTCP(0x77a83587, 0x2d749008), + WTCP(0x7790583e, 0x2db330c7), WTCP(0x77785a2d, 0x2df1c4fe), + WTCP(0x77603b5a, 0x2e304c9d), WTCP(0x7747fbce, 0x2e6ec792), + WTCP(0x772f9b8e, 0x2ead35cd), WTCP(0x77171aa1, 0x2eeb973b), + WTCP(0x76fe790e, 0x2f29ebcc), WTCP(0x76e5b6dc, 0x2f68336f), + WTCP(0x76ccd411, 0x2fa66e13), WTCP(0x76b3d0b4, 0x2fe49ba7), + WTCP(0x769aaccc, 0x3022bc19), WTCP(0x7681685f, 0x3060cf59), + WTCP(0x76680376, 0x309ed556), WTCP(0x764e7e17, 0x30dccdfe), + WTCP(0x7634d848, 0x311ab941), WTCP(0x761b1211, 0x3158970e), + WTCP(0x76012b79, 0x31966753), WTCP(0x75e72487, 0x31d42a00), + WTCP(0x75ccfd42, 0x3211df04), WTCP(0x75b2b5b2, 0x324f864e), + WTCP(0x75984ddc, 0x328d1fcc), WTCP(0x757dc5ca, 0x32caab6f), + WTCP(0x75631d82, 0x33082925), WTCP(0x7548550b, 0x334598de), + WTCP(0x752d6c6c, 0x3382fa88), WTCP(0x751263ae, 0x33c04e13), + WTCP(0x74f73ad7, 0x33fd936e), WTCP(0x74dbf1ef, 0x343aca87), + WTCP(0x74c088fe, 0x3477f350), WTCP(0x74a5000a, 0x34b50db5), + WTCP(0x7489571c, 0x34f219a8), WTCP(0x746d8e3a, 0x352f1716), + WTCP(0x7451a56e, 0x356c05f0), WTCP(0x74359cbd, 0x35a8e625), + WTCP(0x74197431, 0x35e5b7a3), WTCP(0x73fd2bd0, 0x36227a5b), + WTCP(0x73e0c3a3, 0x365f2e3b), WTCP(0x73c43bb1, 0x369bd334), + WTCP(0x73a79402, 0x36d86934), WTCP(0x738acc9e, 0x3714f02a), + WTCP(0x736de58d, 0x37516807), WTCP(0x7350ded7, 0x378dd0b9), + WTCP(0x7333b883, 0x37ca2a30), WTCP(0x7316729a, 0x3806745c), + WTCP(0x72f90d24, 0x3842af2b), WTCP(0x72db8828, 0x387eda8e), + WTCP(0x72bde3af, 0x38baf674), WTCP(0x72a01fc2, 0x38f702cd), + WTCP(0x72823c67, 0x3932ff87), WTCP(0x726439a8, 0x396eec93), + WTCP(0x7246178c, 0x39aac9e0), WTCP(0x7227d61c, 0x39e6975e), + WTCP(0x72097560, 0x3a2254fc), WTCP(0x71eaf561, 0x3a5e02aa), + WTCP(0x71cc5626, 0x3a99a057), WTCP(0x71ad97b9, 0x3ad52df4), + WTCP(0x718eba22, 0x3b10ab70), WTCP(0x716fbd68, 0x3b4c18ba), + WTCP(0x7150a195, 0x3b8775c2), WTCP(0x713166b1, 0x3bc2c279), + WTCP(0x71120cc5, 0x3bfdfecd), WTCP(0x70f293d9, 0x3c392aaf), + WTCP(0x70d2fbf6, 0x3c74460e), WTCP(0x70b34525, 0x3caf50da), + WTCP(0x70936f6e, 0x3cea4b04), WTCP(0x70737ad9, 0x3d253479), + WTCP(0x70536771, 0x3d600d2c), WTCP(0x7033353d, 0x3d9ad50b), + WTCP(0x7012e447, 0x3dd58c06), WTCP(0x6ff27497, 0x3e10320d), + WTCP(0x6fd1e635, 0x3e4ac711), WTCP(0x6fb1392c, 0x3e854b01), + WTCP(0x6f906d84, 0x3ebfbdcd), WTCP(0x6f6f8346, 0x3efa1f65), + WTCP(0x6f4e7a7b, 0x3f346fb8), WTCP(0x6f2d532c, 0x3f6eaeb8), + WTCP(0x6f0c0d62, 0x3fa8dc54), WTCP(0x6eeaa927, 0x3fe2f87c), + WTCP(0x6ec92683, 0x401d0321), WTCP(0x6ea7857f, 0x4056fc31), + WTCP(0x6e85c626, 0x4090e39e), WTCP(0x6e63e87f, 0x40cab958), + WTCP(0x6e41ec95, 0x41047d4e), WTCP(0x6e1fd271, 0x413e2f71), + WTCP(0x6dfd9a1c, 0x4177cfb1), WTCP(0x6ddb439f, 0x41b15dfe), + WTCP(0x6db8cf04, 0x41eada49), WTCP(0x6d963c54, 0x42244481), + WTCP(0x6d738b99, 0x425d9c97), WTCP(0x6d50bcdc, 0x4296e27b), + WTCP(0x6d2dd027, 0x42d0161e), WTCP(0x6d0ac584, 0x43093770), + WTCP(0x6ce79cfc, 0x43424661), WTCP(0x6cc45698, 0x437b42e1), + WTCP(0x6ca0f262, 0x43b42ce1), WTCP(0x6c7d7065, 0x43ed0452), + WTCP(0x6c59d0a9, 0x4425c923), WTCP(0x6c361339, 0x445e7b46), + WTCP(0x6c12381e, 0x44971aaa), WTCP(0x6bee3f62, 0x44cfa740), + WTCP(0x6bca2910, 0x450820f8), WTCP(0x6ba5f530, 0x454087c4), + WTCP(0x6b81a3cd, 0x4578db93), WTCP(0x6b5d34f1, 0x45b11c57), + WTCP(0x6b38a8a6, 0x45e949ff), WTCP(0x6b13fef5, 0x4621647d), + WTCP(0x6aef37e9, 0x46596bc1), WTCP(0x6aca538c, 0x46915fbb), + WTCP(0x6aa551e9, 0x46c9405c), WTCP(0x6a803308, 0x47010d96), + WTCP(0x6a5af6f5, 0x4738c758), WTCP(0x6a359db9, 0x47706d93), + WTCP(0x6a102760, 0x47a80039), WTCP(0x69ea93f2, 0x47df7f3a), + WTCP(0x69c4e37a, 0x4816ea86), WTCP(0x699f1604, 0x484e420f), + WTCP(0x69792b98, 0x488585c5), WTCP(0x69532442, 0x48bcb599), + WTCP(0x692d000c, 0x48f3d17c), WTCP(0x6906bf00, 0x492ad95f), + WTCP(0x68e06129, 0x4961cd33), WTCP(0x68b9e692, 0x4998ace9), + WTCP(0x68934f44, 0x49cf7871), WTCP(0x686c9b4b, 0x4a062fbd), + WTCP(0x6845cab1, 0x4a3cd2be), WTCP(0x681edd81, 0x4a736165), + WTCP(0x67f7d3c5, 0x4aa9dba2), WTCP(0x67d0ad88, 0x4ae04167), + WTCP(0x67a96ad5, 0x4b1692a5), WTCP(0x67820bb7, 0x4b4ccf4d), + WTCP(0x675a9038, 0x4b82f750), WTCP(0x6732f863, 0x4bb90aa0), + WTCP(0x670b4444, 0x4bef092d), WTCP(0x66e373e4, 0x4c24f2e9), + WTCP(0x66bb8750, 0x4c5ac7c4), WTCP(0x66937e91, 0x4c9087b1), + WTCP(0x666b59b3, 0x4cc632a0), WTCP(0x664318c0, 0x4cfbc883), + WTCP(0x661abbc5, 0x4d31494b), WTCP(0x65f242cc, 0x4d66b4e9), + WTCP(0x65c9addf, 0x4d9c0b4f), WTCP(0x65a0fd0b, 0x4dd14c6e), + WTCP(0x6578305a, 0x4e067837), WTCP(0x654f47d7, 0x4e3b8e9d), + WTCP(0x6526438f, 0x4e708f8f), WTCP(0x64fd238b, 0x4ea57b01), + WTCP(0x64d3e7d7, 0x4eda50e2), WTCP(0x64aa907f, 0x4f0f1126), + WTCP(0x64811d8e, 0x4f43bbbd), WTCP(0x64578f0f, 0x4f785099), + WTCP(0x642de50d, 0x4faccfab), WTCP(0x64041f95, 0x4fe138e5), + WTCP(0x63da3eb1, 0x50158c39), WTCP(0x63b0426d, 0x5049c999), + WTCP(0x63862ad5, 0x507df0f6), WTCP(0x635bf7f3, 0x50b20241), + WTCP(0x6331a9d4, 0x50e5fd6d), WTCP(0x63074084, 0x5119e26b), + WTCP(0x62dcbc0d, 0x514db12d), WTCP(0x62b21c7b, 0x518169a5), + WTCP(0x628761db, 0x51b50bc4), WTCP(0x625c8c38, 0x51e8977d), + WTCP(0x62319b9d, 0x521c0cc2), WTCP(0x62069017, 0x524f6b83), + WTCP(0x61db69b1, 0x5282b3b4), WTCP(0x61b02876, 0x52b5e546), + WTCP(0x6184cc74, 0x52e9002a), WTCP(0x615955b6, 0x531c0454), + WTCP(0x612dc447, 0x534ef1b5), WTCP(0x61021834, 0x5381c83f), + WTCP(0x60d65188, 0x53b487e5), WTCP(0x60aa7050, 0x53e73097), + WTCP(0x607e7497, 0x5419c249), WTCP(0x60525e6b, 0x544c3cec), + WTCP(0x60262dd6, 0x547ea073), WTCP(0x5ff9e2e5, 0x54b0ecd0), + WTCP(0x5fcd7da4, 0x54e321f5), WTCP(0x5fa0fe1f, 0x55153fd4), + WTCP(0x5f746462, 0x55474660), WTCP(0x5f47b07a, 0x5579358b), + WTCP(0x5f1ae274, 0x55ab0d46), WTCP(0x5eedfa5a, 0x55dccd86), + WTCP(0x5ec0f839, 0x560e763b), WTCP(0x5e93dc1f, 0x56400758), + WTCP(0x5e66a617, 0x567180d0), WTCP(0x5e39562d, 0x56a2e295), + WTCP(0x5e0bec6e, 0x56d42c99), WTCP(0x5dde68e7, 0x57055ed0), + WTCP(0x5db0cba4, 0x5736792b), WTCP(0x5d8314b1, 0x57677b9d), + WTCP(0x5d55441b, 0x57986619), WTCP(0x5d2759ee, 0x57c93891), + WTCP(0x5cf95638, 0x57f9f2f8), WTCP(0x5ccb3905, 0x582a9540), + WTCP(0x5c9d0260, 0x585b1f5c), WTCP(0x5c6eb258, 0x588b9140), + WTCP(0x5c4048f9, 0x58bbeadd), WTCP(0x5c11c64f, 0x58ec2c26), + WTCP(0x5be32a67, 0x591c550e), WTCP(0x5bb4754e, 0x594c6588), + WTCP(0x5b85a711, 0x597c5d87), WTCP(0x5b56bfbd, 0x59ac3cfd), + WTCP(0x5b27bf5e, 0x59dc03de), WTCP(0x5af8a602, 0x5a0bb21c), + WTCP(0x5ac973b5, 0x5a3b47ab), WTCP(0x5a9a2884, 0x5a6ac47c), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow960[] = { + WTCP(0x7ffffd31, 0x001aceea), WTCP(0x7fffe6bc, 0x00506cb9), + WTCP(0x7fffb9d1, 0x00860a79), WTCP(0x7fff7671, 0x00bba822), + WTCP(0x7fff1c9b, 0x00f145ab), WTCP(0x7ffeac50, 0x0126e309), + WTCP(0x7ffe2590, 0x015c8033), WTCP(0x7ffd885a, 0x01921d20), + WTCP(0x7ffcd4b0, 0x01c7b9c6), WTCP(0x7ffc0a91, 0x01fd561d), + WTCP(0x7ffb29fd, 0x0232f21a), WTCP(0x7ffa32f4, 0x02688db4), + WTCP(0x7ff92577, 0x029e28e2), WTCP(0x7ff80186, 0x02d3c39b), + WTCP(0x7ff6c720, 0x03095dd5), WTCP(0x7ff57647, 0x033ef786), + WTCP(0x7ff40efa, 0x037490a5), WTCP(0x7ff2913a, 0x03aa292a), + WTCP(0x7ff0fd07, 0x03dfc109), WTCP(0x7fef5260, 0x0415583b), + WTCP(0x7fed9148, 0x044aeeb5), WTCP(0x7febb9bd, 0x0480846e), + WTCP(0x7fe9cbc0, 0x04b6195d), WTCP(0x7fe7c752, 0x04ebad79), + WTCP(0x7fe5ac72, 0x052140b7), WTCP(0x7fe37b22, 0x0556d30f), + WTCP(0x7fe13361, 0x058c6478), WTCP(0x7fded530, 0x05c1f4e7), + WTCP(0x7fdc608f, 0x05f78453), WTCP(0x7fd9d57f, 0x062d12b4), + WTCP(0x7fd73401, 0x06629ffe), WTCP(0x7fd47c14, 0x06982c2b), + WTCP(0x7fd1adb9, 0x06cdb72f), WTCP(0x7fcec8f1, 0x07034101), + WTCP(0x7fcbcdbc, 0x0738c998), WTCP(0x7fc8bc1b, 0x076e50eb), + WTCP(0x7fc5940e, 0x07a3d6f0), WTCP(0x7fc25596, 0x07d95b9e), + WTCP(0x7fbf00b3, 0x080edeec), WTCP(0x7fbb9567, 0x084460cf), + WTCP(0x7fb813b0, 0x0879e140), WTCP(0x7fb47b91, 0x08af6033), + WTCP(0x7fb0cd0a, 0x08e4dda0), WTCP(0x7fad081b, 0x091a597e), + WTCP(0x7fa92cc5, 0x094fd3c3), WTCP(0x7fa53b09, 0x09854c66), + WTCP(0x7fa132e8, 0x09bac35d), WTCP(0x7f9d1461, 0x09f0389f), + WTCP(0x7f98df77, 0x0a25ac23), WTCP(0x7f949429, 0x0a5b1dde), + WTCP(0x7f903279, 0x0a908dc9), WTCP(0x7f8bba66, 0x0ac5fbd9), + WTCP(0x7f872bf3, 0x0afb6805), WTCP(0x7f82871f, 0x0b30d244), + WTCP(0x7f7dcbec, 0x0b663a8c), WTCP(0x7f78fa5b, 0x0b9ba0d5), + WTCP(0x7f74126b, 0x0bd10513), WTCP(0x7f6f141f, 0x0c066740), + WTCP(0x7f69ff76, 0x0c3bc74f), WTCP(0x7f64d473, 0x0c71253a), + WTCP(0x7f5f9315, 0x0ca680f5), WTCP(0x7f5a3b5e, 0x0cdbda79), + WTCP(0x7f54cd4f, 0x0d1131ba), WTCP(0x7f4f48e8, 0x0d4686b1), + WTCP(0x7f49ae2a, 0x0d7bd954), WTCP(0x7f43fd18, 0x0db12999), + WTCP(0x7f3e35b0, 0x0de67776), WTCP(0x7f3857f6, 0x0e1bc2e4), + WTCP(0x7f3263e9, 0x0e510bd8), WTCP(0x7f2c598a, 0x0e865248), + WTCP(0x7f2638db, 0x0ebb962c), WTCP(0x7f2001dd, 0x0ef0d77b), + WTCP(0x7f19b491, 0x0f26162a), WTCP(0x7f1350f8, 0x0f5b5231), + WTCP(0x7f0cd712, 0x0f908b86), WTCP(0x7f0646e2, 0x0fc5c220), + WTCP(0x7effa069, 0x0ffaf5f6), WTCP(0x7ef8e3a6, 0x103026fe), + WTCP(0x7ef2109d, 0x1065552e), WTCP(0x7eeb274d, 0x109a807e), + WTCP(0x7ee427b9, 0x10cfa8e5), WTCP(0x7edd11e1, 0x1104ce58), + WTCP(0x7ed5e5c6, 0x1139f0cf), WTCP(0x7ecea36b, 0x116f1040), + WTCP(0x7ec74acf, 0x11a42ca2), WTCP(0x7ebfdbf5, 0x11d945eb), + WTCP(0x7eb856de, 0x120e5c13), WTCP(0x7eb0bb8a, 0x12436f10), + WTCP(0x7ea909fc, 0x12787ed8), WTCP(0x7ea14235, 0x12ad8b63), + WTCP(0x7e996436, 0x12e294a7), WTCP(0x7e917000, 0x13179a9b), + WTCP(0x7e896595, 0x134c9d34), WTCP(0x7e8144f6, 0x13819c6c), + WTCP(0x7e790e25, 0x13b69836), WTCP(0x7e70c124, 0x13eb908c), + WTCP(0x7e685df2, 0x14208563), WTCP(0x7e5fe493, 0x145576b1), + WTCP(0x7e575508, 0x148a646e), WTCP(0x7e4eaf51, 0x14bf4e91), + WTCP(0x7e45f371, 0x14f43510), WTCP(0x7e3d2169, 0x152917e1), + WTCP(0x7e34393b, 0x155df6fc), WTCP(0x7e2b3ae8, 0x1592d257), + WTCP(0x7e222672, 0x15c7a9ea), WTCP(0x7e18fbda, 0x15fc7daa), + WTCP(0x7e0fbb22, 0x16314d8e), WTCP(0x7e06644c, 0x1666198d), + WTCP(0x7dfcf759, 0x169ae19f), WTCP(0x7df3744b, 0x16cfa5b9), + WTCP(0x7de9db23, 0x170465d2), WTCP(0x7de02be4, 0x173921e2), + WTCP(0x7dd6668f, 0x176dd9de), WTCP(0x7dcc8b25, 0x17a28dbe), + WTCP(0x7dc299a9, 0x17d73d79), WTCP(0x7db8921c, 0x180be904), + WTCP(0x7dae747f, 0x18409058), WTCP(0x7da440d6, 0x1875336a), + WTCP(0x7d99f721, 0x18a9d231), WTCP(0x7d8f9762, 0x18de6ca5), + WTCP(0x7d85219c, 0x191302bc), WTCP(0x7d7a95cf, 0x1947946c), + WTCP(0x7d6ff3fe, 0x197c21ad), WTCP(0x7d653c2b, 0x19b0aa75), + WTCP(0x7d5a6e57, 0x19e52ebb), WTCP(0x7d4f8a85, 0x1a19ae76), + WTCP(0x7d4490b6, 0x1a4e299d), WTCP(0x7d3980ec, 0x1a82a026), + WTCP(0x7d2e5b2a, 0x1ab71208), WTCP(0x7d231f70, 0x1aeb7f3a), + WTCP(0x7d17cdc2, 0x1b1fe7b3), WTCP(0x7d0c6621, 0x1b544b6a), + WTCP(0x7d00e88f, 0x1b88aa55), WTCP(0x7cf5550e, 0x1bbd046c), + WTCP(0x7ce9aba1, 0x1bf159a4), WTCP(0x7cddec48, 0x1c25a9f6), + WTCP(0x7cd21707, 0x1c59f557), WTCP(0x7cc62bdf, 0x1c8e3bbe), + WTCP(0x7cba2ad3, 0x1cc27d23), WTCP(0x7cae13e4, 0x1cf6b97c), + WTCP(0x7ca1e715, 0x1d2af0c1), WTCP(0x7c95a467, 0x1d5f22e7), + WTCP(0x7c894bde, 0x1d934fe5), WTCP(0x7c7cdd7b, 0x1dc777b3), + WTCP(0x7c705940, 0x1dfb9a48), WTCP(0x7c63bf2f, 0x1e2fb79a), + WTCP(0x7c570f4b, 0x1e63cfa0), WTCP(0x7c4a4996, 0x1e97e251), + WTCP(0x7c3d6e13, 0x1ecbefa4), WTCP(0x7c307cc2, 0x1efff78f), + WTCP(0x7c2375a8, 0x1f33fa0a), WTCP(0x7c1658c5, 0x1f67f70b), + WTCP(0x7c09261d, 0x1f9bee8a), WTCP(0x7bfbddb1, 0x1fcfe07d), + WTCP(0x7bee7f85, 0x2003ccdb), WTCP(0x7be10b99, 0x2037b39b), + WTCP(0x7bd381f1, 0x206b94b4), WTCP(0x7bc5e290, 0x209f701c), + WTCP(0x7bb82d76, 0x20d345cc), WTCP(0x7baa62a8, 0x210715b8), + WTCP(0x7b9c8226, 0x213adfda), WTCP(0x7b8e8bf5, 0x216ea426), + WTCP(0x7b808015, 0x21a26295), WTCP(0x7b725e8a, 0x21d61b1e), + WTCP(0x7b642756, 0x2209cdb6), WTCP(0x7b55da7c, 0x223d7a55), + WTCP(0x7b4777fe, 0x227120f3), WTCP(0x7b38ffde, 0x22a4c185), + WTCP(0x7b2a721f, 0x22d85c04), WTCP(0x7b1bcec4, 0x230bf065), + WTCP(0x7b0d15d0, 0x233f7ea0), WTCP(0x7afe4744, 0x237306ab), + WTCP(0x7aef6323, 0x23a6887f), WTCP(0x7ae06971, 0x23da0411), + WTCP(0x7ad15a2f, 0x240d7958), WTCP(0x7ac23561, 0x2440e84d), + WTCP(0x7ab2fb09, 0x247450e4), WTCP(0x7aa3ab29, 0x24a7b317), + WTCP(0x7a9445c5, 0x24db0edb), WTCP(0x7a84cade, 0x250e6427), + WTCP(0x7a753a79, 0x2541b2f3), WTCP(0x7a659496, 0x2574fb36), + WTCP(0x7a55d93a, 0x25a83ce6), WTCP(0x7a460867, 0x25db77fa), + WTCP(0x7a362220, 0x260eac6a), WTCP(0x7a262668, 0x2641da2d), + WTCP(0x7a161540, 0x26750139), WTCP(0x7a05eead, 0x26a82186), + WTCP(0x79f5b2b1, 0x26db3b0a), WTCP(0x79e5614f, 0x270e4dbd), + WTCP(0x79d4fa89, 0x27415996), WTCP(0x79c47e63, 0x27745e8c), + WTCP(0x79b3ece0, 0x27a75c95), WTCP(0x79a34602, 0x27da53a9), + WTCP(0x799289cc, 0x280d43bf), WTCP(0x7981b841, 0x28402cce), + WTCP(0x7970d165, 0x28730ecd), WTCP(0x795fd53a, 0x28a5e9b4), + WTCP(0x794ec3c3, 0x28d8bd78), WTCP(0x793d9d03, 0x290b8a12), + WTCP(0x792c60fe, 0x293e4f78), WTCP(0x791b0fb5, 0x29710da1), + WTCP(0x7909a92d, 0x29a3c485), WTCP(0x78f82d68, 0x29d6741b), + WTCP(0x78e69c69, 0x2a091c59), WTCP(0x78d4f634, 0x2a3bbd37), + WTCP(0x78c33acb, 0x2a6e56ac), WTCP(0x78b16a32, 0x2aa0e8b0), + WTCP(0x789f846b, 0x2ad37338), WTCP(0x788d897b, 0x2b05f63d), + WTCP(0x787b7963, 0x2b3871b5), WTCP(0x78695428, 0x2b6ae598), + WTCP(0x785719cc, 0x2b9d51dd), WTCP(0x7844ca53, 0x2bcfb67b), + WTCP(0x783265c0, 0x2c021369), WTCP(0x781fec15, 0x2c34689e), + WTCP(0x780d5d57, 0x2c66b611), WTCP(0x77fab989, 0x2c98fbba), + WTCP(0x77e800ad, 0x2ccb3990), WTCP(0x77d532c7, 0x2cfd6f8a), + WTCP(0x77c24fdb, 0x2d2f9d9f), WTCP(0x77af57eb, 0x2d61c3c7), + WTCP(0x779c4afc, 0x2d93e1f8), WTCP(0x77892910, 0x2dc5f829), + WTCP(0x7775f22a, 0x2df80653), WTCP(0x7762a64f, 0x2e2a0c6c), + WTCP(0x774f4581, 0x2e5c0a6b), WTCP(0x773bcfc4, 0x2e8e0048), + WTCP(0x7728451c, 0x2ebfedfa), WTCP(0x7714a58b, 0x2ef1d377), + WTCP(0x7700f115, 0x2f23b0b9), WTCP(0x76ed27be, 0x2f5585b5), + WTCP(0x76d94989, 0x2f875262), WTCP(0x76c55679, 0x2fb916b9), + WTCP(0x76b14e93, 0x2fead2b0), WTCP(0x769d31d9, 0x301c863f), + WTCP(0x76890050, 0x304e315d), WTCP(0x7674b9fa, 0x307fd401), + WTCP(0x76605edb, 0x30b16e23), WTCP(0x764beef8, 0x30e2ffb9), + WTCP(0x76376a52, 0x311488bc), WTCP(0x7622d0ef, 0x31460922), + WTCP(0x760e22d1, 0x317780e2), WTCP(0x75f95ffc, 0x31a8eff5), + WTCP(0x75e48874, 0x31da5651), WTCP(0x75cf9c3d, 0x320bb3ee), + WTCP(0x75ba9b5a, 0x323d08c3), WTCP(0x75a585cf, 0x326e54c7), + WTCP(0x75905ba0, 0x329f97f3), WTCP(0x757b1ccf, 0x32d0d23c), + WTCP(0x7565c962, 0x3302039b), WTCP(0x7550615c, 0x33332c06), + WTCP(0x753ae4c0, 0x33644b76), WTCP(0x75255392, 0x339561e1), + WTCP(0x750fadd7, 0x33c66f40), WTCP(0x74f9f391, 0x33f77388), + WTCP(0x74e424c5, 0x34286eb3), WTCP(0x74ce4177, 0x345960b7), + WTCP(0x74b849aa, 0x348a498b), WTCP(0x74a23d62, 0x34bb2927), + WTCP(0x748c1ca4, 0x34ebff83), WTCP(0x7475e772, 0x351ccc96), + WTCP(0x745f9dd1, 0x354d9057), WTCP(0x74493fc5, 0x357e4abe), + WTCP(0x7432cd51, 0x35aefbc2), WTCP(0x741c467b, 0x35dfa35a), + WTCP(0x7405ab45, 0x3610417f), WTCP(0x73eefbb3, 0x3640d627), + WTCP(0x73d837ca, 0x3671614b), WTCP(0x73c15f8d, 0x36a1e2e0), + WTCP(0x73aa7301, 0x36d25ae0), WTCP(0x7393722a, 0x3702c942), + WTCP(0x737c5d0b, 0x37332dfd), WTCP(0x736533a9, 0x37638908), + WTCP(0x734df607, 0x3793da5b), WTCP(0x7336a42b, 0x37c421ee), + WTCP(0x731f3e17, 0x37f45fb7), WTCP(0x7307c3d0, 0x382493b0), + WTCP(0x72f0355a, 0x3854bdcf), WTCP(0x72d892ba, 0x3884de0b), + WTCP(0x72c0dbf3, 0x38b4f45d), WTCP(0x72a91109, 0x38e500bc), + WTCP(0x72913201, 0x3915031f), WTCP(0x72793edf, 0x3944fb7e), + WTCP(0x726137a8, 0x3974e9d0), WTCP(0x72491c5e, 0x39a4ce0e), + WTCP(0x7230ed07, 0x39d4a82f), WTCP(0x7218a9a7, 0x3a04782a), + WTCP(0x72005242, 0x3a343df7), WTCP(0x71e7e6dc, 0x3a63f98d), + WTCP(0x71cf677a, 0x3a93aae5), WTCP(0x71b6d420, 0x3ac351f6), + WTCP(0x719e2cd2, 0x3af2eeb7), WTCP(0x71857195, 0x3b228120), + WTCP(0x716ca26c, 0x3b52092a), WTCP(0x7153bf5d, 0x3b8186ca), + WTCP(0x713ac86b, 0x3bb0f9fa), WTCP(0x7121bd9c, 0x3be062b0), + WTCP(0x71089ef2, 0x3c0fc0e6), WTCP(0x70ef6c74, 0x3c3f1491), + WTCP(0x70d62625, 0x3c6e5daa), WTCP(0x70bccc09, 0x3c9d9c28), + WTCP(0x70a35e25, 0x3cccd004), WTCP(0x7089dc7e, 0x3cfbf935), + WTCP(0x70704718, 0x3d2b17b3), WTCP(0x70569df8, 0x3d5a2b75), + WTCP(0x703ce122, 0x3d893474), WTCP(0x7023109a, 0x3db832a6), + WTCP(0x70092c65, 0x3de72604), WTCP(0x6fef3488, 0x3e160e85), + WTCP(0x6fd52907, 0x3e44ec22), WTCP(0x6fbb09e7, 0x3e73bed2), + WTCP(0x6fa0d72c, 0x3ea2868c), WTCP(0x6f8690db, 0x3ed14349), + WTCP(0x6f6c36f8, 0x3efff501), WTCP(0x6f51c989, 0x3f2e9bab), + WTCP(0x6f374891, 0x3f5d373e), WTCP(0x6f1cb416, 0x3f8bc7b4), + WTCP(0x6f020c1c, 0x3fba4d03), WTCP(0x6ee750a8, 0x3fe8c724), + WTCP(0x6ecc81be, 0x4017360e), WTCP(0x6eb19f64, 0x404599b9), + WTCP(0x6e96a99d, 0x4073f21d), WTCP(0x6e7ba06f, 0x40a23f32), + WTCP(0x6e6083de, 0x40d080f0), WTCP(0x6e4553ef, 0x40feb74f), + WTCP(0x6e2a10a8, 0x412ce246), WTCP(0x6e0eba0c, 0x415b01ce), + WTCP(0x6df35020, 0x418915de), WTCP(0x6dd7d2ea, 0x41b71e6f), + WTCP(0x6dbc426e, 0x41e51b77), WTCP(0x6da09eb1, 0x42130cf0), + WTCP(0x6d84e7b7, 0x4240f2d1), WTCP(0x6d691d87, 0x426ecd12), + WTCP(0x6d4d4023, 0x429c9bab), WTCP(0x6d314f93, 0x42ca5e94), + WTCP(0x6d154bd9, 0x42f815c5), WTCP(0x6cf934fc, 0x4325c135), + WTCP(0x6cdd0b00, 0x435360de), WTCP(0x6cc0cdea, 0x4380f4b7), + WTCP(0x6ca47dbf, 0x43ae7cb7), WTCP(0x6c881a84, 0x43dbf8d7), + WTCP(0x6c6ba43e, 0x44096910), WTCP(0x6c4f1af2, 0x4436cd58), + WTCP(0x6c327ea6, 0x446425a8), WTCP(0x6c15cf5d, 0x449171f8), + WTCP(0x6bf90d1d, 0x44beb240), WTCP(0x6bdc37eb, 0x44ebe679), + WTCP(0x6bbf4fcd, 0x45190e99), WTCP(0x6ba254c7, 0x45462a9a), + WTCP(0x6b8546de, 0x45733a73), WTCP(0x6b682617, 0x45a03e1d), + WTCP(0x6b4af279, 0x45cd358f), WTCP(0x6b2dac06, 0x45fa20c2), + WTCP(0x6b1052c6, 0x4626ffae), WTCP(0x6af2e6bc, 0x4653d24b), + WTCP(0x6ad567ef, 0x46809891), WTCP(0x6ab7d663, 0x46ad5278), + WTCP(0x6a9a321d, 0x46d9fff8), WTCP(0x6a7c7b23, 0x4706a10a), + WTCP(0x6a5eb17a, 0x473335a5), WTCP(0x6a40d527, 0x475fbdc3), + WTCP(0x6a22e630, 0x478c395a), WTCP(0x6a04e499, 0x47b8a864), + WTCP(0x69e6d067, 0x47e50ad8), WTCP(0x69c8a9a1, 0x481160ae), + WTCP(0x69aa704c, 0x483da9e0), WTCP(0x698c246c, 0x4869e665), + WTCP(0x696dc607, 0x48961635), WTCP(0x694f5523, 0x48c23949), + WTCP(0x6930d1c4, 0x48ee4f98), WTCP(0x69123bf1, 0x491a591c), + WTCP(0x68f393ae, 0x494655cc), WTCP(0x68d4d900, 0x497245a1), + WTCP(0x68b60bee, 0x499e2892), WTCP(0x68972c7d, 0x49c9fe99), + WTCP(0x68783ab1, 0x49f5c7ae), WTCP(0x68593691, 0x4a2183c8), + WTCP(0x683a2022, 0x4a4d32e1), WTCP(0x681af76a, 0x4a78d4f0), + WTCP(0x67fbbc6d, 0x4aa469ee), WTCP(0x67dc6f31, 0x4acff1d3), + WTCP(0x67bd0fbd, 0x4afb6c98), WTCP(0x679d9e14, 0x4b26da35), + WTCP(0x677e1a3e, 0x4b523aa2), WTCP(0x675e843e, 0x4b7d8dd8), + WTCP(0x673edc1c, 0x4ba8d3cf), WTCP(0x671f21dc, 0x4bd40c80), + WTCP(0x66ff5584, 0x4bff37e2), WTCP(0x66df771a, 0x4c2a55ef), + WTCP(0x66bf86a3, 0x4c55669f), WTCP(0x669f8425, 0x4c8069ea), + WTCP(0x667f6fa5, 0x4cab5fc9), WTCP(0x665f4929, 0x4cd64834), + WTCP(0x663f10b7, 0x4d012324), WTCP(0x661ec654, 0x4d2bf091), + WTCP(0x65fe6a06, 0x4d56b073), WTCP(0x65ddfbd3, 0x4d8162c4), + WTCP(0x65bd7bc0, 0x4dac077b), WTCP(0x659ce9d4, 0x4dd69e92), + WTCP(0x657c4613, 0x4e012800), WTCP(0x655b9083, 0x4e2ba3be), + WTCP(0x653ac92b, 0x4e5611c5), WTCP(0x6519f010, 0x4e80720e), + WTCP(0x64f90538, 0x4eaac490), WTCP(0x64d808a8, 0x4ed50945), + WTCP(0x64b6fa66, 0x4eff4025), WTCP(0x6495da79, 0x4f296928), + WTCP(0x6474a8e5, 0x4f538448), WTCP(0x645365b2, 0x4f7d917c), + WTCP(0x643210e4, 0x4fa790be), WTCP(0x6410aa81, 0x4fd18206), + WTCP(0x63ef3290, 0x4ffb654d), WTCP(0x63cda916, 0x50253a8b), + WTCP(0x63ac0e19, 0x504f01ba), WTCP(0x638a619e, 0x5078bad1), + WTCP(0x6368a3ad, 0x50a265c9), WTCP(0x6346d44b, 0x50cc029c), + WTCP(0x6324f37d, 0x50f59141), WTCP(0x6303014a, 0x511f11b2), + WTCP(0x62e0fdb8, 0x514883e7), WTCP(0x62bee8cc, 0x5171e7d9), + WTCP(0x629cc28c, 0x519b3d80), WTCP(0x627a8b00, 0x51c484d6), + WTCP(0x6258422c, 0x51edbdd4), WTCP(0x6235e816, 0x5216e871), + WTCP(0x62137cc5, 0x524004a7), WTCP(0x61f1003f, 0x5269126e), + WTCP(0x61ce7289, 0x529211c0), WTCP(0x61abd3ab, 0x52bb0295), + WTCP(0x618923a9, 0x52e3e4e6), WTCP(0x61666289, 0x530cb8ac), + WTCP(0x61439053, 0x53357ddf), WTCP(0x6120ad0d, 0x535e3479), + WTCP(0x60fdb8bb, 0x5386dc72), WTCP(0x60dab365, 0x53af75c3), + WTCP(0x60b79d10, 0x53d80065), WTCP(0x609475c3, 0x54007c51), + WTCP(0x60713d84, 0x5428e980), WTCP(0x604df459, 0x545147eb), + WTCP(0x602a9a48, 0x5479978a), WTCP(0x60072f57, 0x54a1d857), + WTCP(0x5fe3b38d, 0x54ca0a4b), WTCP(0x5fc026f0, 0x54f22d5d), + WTCP(0x5f9c8987, 0x551a4189), WTCP(0x5f78db56, 0x554246c6), + WTCP(0x5f551c65, 0x556a3d0d), WTCP(0x5f314cba, 0x55922457), + WTCP(0x5f0d6c5b, 0x55b9fc9e), WTCP(0x5ee97b4f, 0x55e1c5da), + WTCP(0x5ec5799b, 0x56098005), WTCP(0x5ea16747, 0x56312b17), + WTCP(0x5e7d4458, 0x5658c709), WTCP(0x5e5910d4, 0x568053d5), + WTCP(0x5e34ccc3, 0x56a7d174), WTCP(0x5e10782b, 0x56cf3fde), + WTCP(0x5dec1311, 0x56f69f0d), WTCP(0x5dc79d7c, 0x571deefa), + WTCP(0x5da31773, 0x57452f9d), WTCP(0x5d7e80fc, 0x576c60f1), + WTCP(0x5d59da1e, 0x579382ee), WTCP(0x5d3522de, 0x57ba958d), + WTCP(0x5d105b44, 0x57e198c7), WTCP(0x5ceb8355, 0x58088c96), + WTCP(0x5cc69b19, 0x582f70f3), WTCP(0x5ca1a295, 0x585645d7), + WTCP(0x5c7c99d1, 0x587d0b3b), WTCP(0x5c5780d3, 0x58a3c118), + WTCP(0x5c3257a0, 0x58ca6767), WTCP(0x5c0d1e41, 0x58f0fe23), + WTCP(0x5be7d4ba, 0x59178543), WTCP(0x5bc27b14, 0x593dfcc2), + WTCP(0x5b9d1154, 0x59646498), WTCP(0x5b779780, 0x598abcbe), + WTCP(0x5b520da1, 0x59b1052f), WTCP(0x5b2c73bb, 0x59d73de3), + WTCP(0x5b06c9d6, 0x59fd66d4), WTCP(0x5ae10ff9, 0x5a237ffa), + WTCP(0x5abb4629, 0x5a498950), WTCP(0x5a956c6e, 0x5a6f82ce), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow1024[] = { + WTCP(0x7ffffd88, 0x001921fb), WTCP(0x7fffe9cb, 0x004b65ee), + WTCP(0x7fffc251, 0x007da9d4), WTCP(0x7fff8719, 0x00afeda8), + WTCP(0x7fff3824, 0x00e23160), WTCP(0x7ffed572, 0x011474f6), + WTCP(0x7ffe5f03, 0x0146b860), WTCP(0x7ffdd4d7, 0x0178fb99), + WTCP(0x7ffd36ee, 0x01ab3e97), WTCP(0x7ffc8549, 0x01dd8154), + WTCP(0x7ffbbfe6, 0x020fc3c6), WTCP(0x7ffae6c7, 0x024205e8), + WTCP(0x7ff9f9ec, 0x027447b0), WTCP(0x7ff8f954, 0x02a68917), + WTCP(0x7ff7e500, 0x02d8ca16), WTCP(0x7ff6bcf0, 0x030b0aa4), + WTCP(0x7ff58125, 0x033d4abb), WTCP(0x7ff4319d, 0x036f8a51), + WTCP(0x7ff2ce5b, 0x03a1c960), WTCP(0x7ff1575d, 0x03d407df), + WTCP(0x7fefcca4, 0x040645c7), WTCP(0x7fee2e30, 0x04388310), + WTCP(0x7fec7c02, 0x046abfb3), WTCP(0x7feab61a, 0x049cfba7), + WTCP(0x7fe8dc78, 0x04cf36e5), WTCP(0x7fe6ef1c, 0x05017165), + WTCP(0x7fe4ee06, 0x0533ab20), WTCP(0x7fe2d938, 0x0565e40d), + WTCP(0x7fe0b0b1, 0x05981c26), WTCP(0x7fde7471, 0x05ca5361), + WTCP(0x7fdc247a, 0x05fc89b8), WTCP(0x7fd9c0ca, 0x062ebf22), + WTCP(0x7fd74964, 0x0660f398), WTCP(0x7fd4be46, 0x06932713), + WTCP(0x7fd21f72, 0x06c5598a), WTCP(0x7fcf6ce8, 0x06f78af6), + WTCP(0x7fcca6a7, 0x0729bb4e), WTCP(0x7fc9ccb2, 0x075bea8c), + WTCP(0x7fc6df08, 0x078e18a7), WTCP(0x7fc3dda9, 0x07c04598), + WTCP(0x7fc0c896, 0x07f27157), WTCP(0x7fbd9fd0, 0x08249bdd), + WTCP(0x7fba6357, 0x0856c520), WTCP(0x7fb7132b, 0x0888ed1b), + WTCP(0x7fb3af4e, 0x08bb13c5), WTCP(0x7fb037bf, 0x08ed3916), + WTCP(0x7facac7f, 0x091f5d06), WTCP(0x7fa90d8e, 0x09517f8f), + WTCP(0x7fa55aee, 0x0983a0a7), WTCP(0x7fa1949e, 0x09b5c048), + WTCP(0x7f9dbaa0, 0x09e7de6a), WTCP(0x7f99ccf4, 0x0a19fb04), + WTCP(0x7f95cb9a, 0x0a4c1610), WTCP(0x7f91b694, 0x0a7e2f85), + WTCP(0x7f8d8de1, 0x0ab0475c), WTCP(0x7f895182, 0x0ae25d8d), + WTCP(0x7f850179, 0x0b147211), WTCP(0x7f809dc5, 0x0b4684df), + WTCP(0x7f7c2668, 0x0b7895f0), WTCP(0x7f779b62, 0x0baaa53b), + WTCP(0x7f72fcb4, 0x0bdcb2bb), WTCP(0x7f6e4a5e, 0x0c0ebe66), + WTCP(0x7f698461, 0x0c40c835), WTCP(0x7f64aabf, 0x0c72d020), + WTCP(0x7f5fbd77, 0x0ca4d620), WTCP(0x7f5abc8a, 0x0cd6da2d), + WTCP(0x7f55a7fa, 0x0d08dc3f), WTCP(0x7f507fc7, 0x0d3adc4e), + WTCP(0x7f4b43f2, 0x0d6cda53), WTCP(0x7f45f47b, 0x0d9ed646), + WTCP(0x7f409164, 0x0dd0d01f), WTCP(0x7f3b1aad, 0x0e02c7d7), + WTCP(0x7f359057, 0x0e34bd66), WTCP(0x7f2ff263, 0x0e66b0c3), + WTCP(0x7f2a40d2, 0x0e98a1e9), WTCP(0x7f247ba5, 0x0eca90ce), + WTCP(0x7f1ea2dc, 0x0efc7d6b), WTCP(0x7f18b679, 0x0f2e67b8), + WTCP(0x7f12b67c, 0x0f604faf), WTCP(0x7f0ca2e7, 0x0f923546), + WTCP(0x7f067bba, 0x0fc41876), WTCP(0x7f0040f6, 0x0ff5f938), + WTCP(0x7ef9f29d, 0x1027d784), WTCP(0x7ef390ae, 0x1059b352), + WTCP(0x7eed1b2c, 0x108b8c9b), WTCP(0x7ee69217, 0x10bd6356), + WTCP(0x7edff570, 0x10ef377d), WTCP(0x7ed94538, 0x11210907), + WTCP(0x7ed28171, 0x1152d7ed), WTCP(0x7ecbaa1a, 0x1184a427), + WTCP(0x7ec4bf36, 0x11b66dad), WTCP(0x7ebdc0c6, 0x11e83478), + WTCP(0x7eb6aeca, 0x1219f880), WTCP(0x7eaf8943, 0x124bb9be), + WTCP(0x7ea85033, 0x127d7829), WTCP(0x7ea1039b, 0x12af33ba), + WTCP(0x7e99a37c, 0x12e0ec6a), WTCP(0x7e922fd6, 0x1312a230), + WTCP(0x7e8aa8ac, 0x13445505), WTCP(0x7e830dff, 0x137604e2), + WTCP(0x7e7b5fce, 0x13a7b1bf), WTCP(0x7e739e1d, 0x13d95b93), + WTCP(0x7e6bc8eb, 0x140b0258), WTCP(0x7e63e03b, 0x143ca605), + WTCP(0x7e5be40c, 0x146e4694), WTCP(0x7e53d462, 0x149fe3fc), + WTCP(0x7e4bb13c, 0x14d17e36), WTCP(0x7e437a9c, 0x1503153a), + WTCP(0x7e3b3083, 0x1534a901), WTCP(0x7e32d2f4, 0x15663982), + WTCP(0x7e2a61ed, 0x1597c6b7), WTCP(0x7e21dd73, 0x15c95097), + WTCP(0x7e194584, 0x15fad71b), WTCP(0x7e109a24, 0x162c5a3b), + WTCP(0x7e07db52, 0x165dd9f0), WTCP(0x7dff0911, 0x168f5632), + WTCP(0x7df62362, 0x16c0cef9), WTCP(0x7ded2a47, 0x16f2443e), + WTCP(0x7de41dc0, 0x1723b5f9), WTCP(0x7ddafdce, 0x17552422), + WTCP(0x7dd1ca75, 0x17868eb3), WTCP(0x7dc883b4, 0x17b7f5a3), + WTCP(0x7dbf298d, 0x17e958ea), WTCP(0x7db5bc02, 0x181ab881), + WTCP(0x7dac3b15, 0x184c1461), WTCP(0x7da2a6c6, 0x187d6c82), + WTCP(0x7d98ff17, 0x18aec0db), WTCP(0x7d8f4409, 0x18e01167), + WTCP(0x7d85759f, 0x19115e1c), WTCP(0x7d7b93da, 0x1942a6f3), + WTCP(0x7d719eba, 0x1973ebe6), WTCP(0x7d679642, 0x19a52ceb), + WTCP(0x7d5d7a74, 0x19d669fc), WTCP(0x7d534b50, 0x1a07a311), + WTCP(0x7d4908d9, 0x1a38d823), WTCP(0x7d3eb30f, 0x1a6a0929), + WTCP(0x7d3449f5, 0x1a9b361d), WTCP(0x7d29cd8c, 0x1acc5ef6), + WTCP(0x7d1f3dd6, 0x1afd83ad), WTCP(0x7d149ad5, 0x1b2ea43a), + WTCP(0x7d09e489, 0x1b5fc097), WTCP(0x7cff1af5, 0x1b90d8bb), + WTCP(0x7cf43e1a, 0x1bc1ec9e), WTCP(0x7ce94dfb, 0x1bf2fc3a), + WTCP(0x7cde4a98, 0x1c240786), WTCP(0x7cd333f3, 0x1c550e7c), + WTCP(0x7cc80a0f, 0x1c861113), WTCP(0x7cbcccec, 0x1cb70f43), + WTCP(0x7cb17c8d, 0x1ce80906), WTCP(0x7ca618f3, 0x1d18fe54), + WTCP(0x7c9aa221, 0x1d49ef26), WTCP(0x7c8f1817, 0x1d7adb73), + WTCP(0x7c837ad8, 0x1dabc334), WTCP(0x7c77ca65, 0x1ddca662), + WTCP(0x7c6c06c0, 0x1e0d84f5), WTCP(0x7c602fec, 0x1e3e5ee5), + WTCP(0x7c5445e9, 0x1e6f342c), WTCP(0x7c4848ba, 0x1ea004c1), + WTCP(0x7c3c3860, 0x1ed0d09d), WTCP(0x7c3014de, 0x1f0197b8), + WTCP(0x7c23de35, 0x1f325a0b), WTCP(0x7c179467, 0x1f63178f), + WTCP(0x7c0b3777, 0x1f93d03c), WTCP(0x7bfec765, 0x1fc4840a), + WTCP(0x7bf24434, 0x1ff532f2), WTCP(0x7be5ade6, 0x2025dcec), + WTCP(0x7bd9047c, 0x205681f1), WTCP(0x7bcc47fa, 0x208721f9), + WTCP(0x7bbf7860, 0x20b7bcfe), WTCP(0x7bb295b0, 0x20e852f6), + WTCP(0x7ba59fee, 0x2118e3dc), WTCP(0x7b989719, 0x21496fa7), + WTCP(0x7b8b7b36, 0x2179f64f), WTCP(0x7b7e4c45, 0x21aa77cf), + WTCP(0x7b710a49, 0x21daf41d), WTCP(0x7b63b543, 0x220b6b32), + WTCP(0x7b564d36, 0x223bdd08), WTCP(0x7b48d225, 0x226c4996), + WTCP(0x7b3b4410, 0x229cb0d5), WTCP(0x7b2da2fa, 0x22cd12bd), + WTCP(0x7b1feee5, 0x22fd6f48), WTCP(0x7b1227d3, 0x232dc66d), + WTCP(0x7b044dc7, 0x235e1826), WTCP(0x7af660c2, 0x238e646a), + WTCP(0x7ae860c7, 0x23beab33), WTCP(0x7ada4dd8, 0x23eeec78), + WTCP(0x7acc27f7, 0x241f2833), WTCP(0x7abdef25, 0x244f5e5c), + WTCP(0x7aafa367, 0x247f8eec), WTCP(0x7aa144bc, 0x24afb9da), + WTCP(0x7a92d329, 0x24dfdf20), WTCP(0x7a844eae, 0x250ffeb7), + WTCP(0x7a75b74f, 0x25401896), WTCP(0x7a670d0d, 0x25702cb7), + WTCP(0x7a584feb, 0x25a03b11), WTCP(0x7a497feb, 0x25d0439f), + WTCP(0x7a3a9d0f, 0x26004657), WTCP(0x7a2ba75a, 0x26304333), + WTCP(0x7a1c9ece, 0x26603a2c), WTCP(0x7a0d836d, 0x26902b39), + WTCP(0x79fe5539, 0x26c01655), WTCP(0x79ef1436, 0x26effb76), + WTCP(0x79dfc064, 0x271fda96), WTCP(0x79d059c8, 0x274fb3ae), + WTCP(0x79c0e062, 0x277f86b5), WTCP(0x79b15435, 0x27af53a6), + WTCP(0x79a1b545, 0x27df1a77), WTCP(0x79920392, 0x280edb23), + WTCP(0x79823f20, 0x283e95a1), WTCP(0x797267f2, 0x286e49ea), + WTCP(0x79627e08, 0x289df7f8), WTCP(0x79528167, 0x28cd9fc1), + WTCP(0x79427210, 0x28fd4140), WTCP(0x79325006, 0x292cdc6d), + WTCP(0x79221b4b, 0x295c7140), WTCP(0x7911d3e2, 0x298bffb2), + WTCP(0x790179cd, 0x29bb87bc), WTCP(0x78f10d0f, 0x29eb0957), + WTCP(0x78e08dab, 0x2a1a847b), WTCP(0x78cffba3, 0x2a49f920), + WTCP(0x78bf56f9, 0x2a796740), WTCP(0x78ae9fb0, 0x2aa8ced3), + WTCP(0x789dd5cb, 0x2ad82fd2), WTCP(0x788cf94c, 0x2b078a36), + WTCP(0x787c0a36, 0x2b36ddf7), WTCP(0x786b088c, 0x2b662b0e), + WTCP(0x7859f44f, 0x2b957173), WTCP(0x7848cd83, 0x2bc4b120), + WTCP(0x7837942b, 0x2bf3ea0d), WTCP(0x78264849, 0x2c231c33), + WTCP(0x7814e9df, 0x2c52478a), WTCP(0x780378f1, 0x2c816c0c), + WTCP(0x77f1f581, 0x2cb089b1), WTCP(0x77e05f91, 0x2cdfa071), + WTCP(0x77ceb725, 0x2d0eb046), WTCP(0x77bcfc3f, 0x2d3db928), + WTCP(0x77ab2ee2, 0x2d6cbb10), WTCP(0x77994f11, 0x2d9bb5f6), + WTCP(0x77875cce, 0x2dcaa9d5), WTCP(0x7775581d, 0x2df996a3), + WTCP(0x776340ff, 0x2e287c5a), WTCP(0x77511778, 0x2e575af3), + WTCP(0x773edb8b, 0x2e863267), WTCP(0x772c8d3a, 0x2eb502ae), + WTCP(0x771a2c88, 0x2ee3cbc1), WTCP(0x7707b979, 0x2f128d99), + WTCP(0x76f5340e, 0x2f41482e), WTCP(0x76e29c4b, 0x2f6ffb7a), + WTCP(0x76cff232, 0x2f9ea775), WTCP(0x76bd35c7, 0x2fcd4c19), + WTCP(0x76aa670d, 0x2ffbe95d), WTCP(0x76978605, 0x302a7f3a), + WTCP(0x768492b4, 0x30590dab), WTCP(0x76718d1c, 0x308794a6), + WTCP(0x765e7540, 0x30b61426), WTCP(0x764b4b23, 0x30e48c22), + WTCP(0x76380ec8, 0x3112fc95), WTCP(0x7624c031, 0x31416576), + WTCP(0x76115f63, 0x316fc6be), WTCP(0x75fdec60, 0x319e2067), + WTCP(0x75ea672a, 0x31cc7269), WTCP(0x75d6cfc5, 0x31fabcbd), + WTCP(0x75c32634, 0x3228ff5c), WTCP(0x75af6a7b, 0x32573a3f), + WTCP(0x759b9c9b, 0x32856d5e), WTCP(0x7587bc98, 0x32b398b3), + WTCP(0x7573ca75, 0x32e1bc36), WTCP(0x755fc635, 0x330fd7e1), + WTCP(0x754bafdc, 0x333debab), WTCP(0x7537876c, 0x336bf78f), + WTCP(0x75234ce8, 0x3399fb85), WTCP(0x750f0054, 0x33c7f785), + WTCP(0x74faa1b3, 0x33f5eb89), WTCP(0x74e63108, 0x3423d78a), + WTCP(0x74d1ae55, 0x3451bb81), WTCP(0x74bd199f, 0x347f9766), + WTCP(0x74a872e8, 0x34ad6b32), WTCP(0x7493ba34, 0x34db36df), + WTCP(0x747eef85, 0x3508fa66), WTCP(0x746a12df, 0x3536b5be), + WTCP(0x74552446, 0x356468e2), WTCP(0x744023bc, 0x359213c9), + WTCP(0x742b1144, 0x35bfb66e), WTCP(0x7415ece2, 0x35ed50c9), + WTCP(0x7400b69a, 0x361ae2d3), WTCP(0x73eb6e6e, 0x36486c86), + WTCP(0x73d61461, 0x3675edd9), WTCP(0x73c0a878, 0x36a366c6), + WTCP(0x73ab2ab4, 0x36d0d746), WTCP(0x73959b1b, 0x36fe3f52), + WTCP(0x737ff9ae, 0x372b9ee3), WTCP(0x736a4671, 0x3758f5f2), + WTCP(0x73548168, 0x37864477), WTCP(0x733eaa96, 0x37b38a6d), + WTCP(0x7328c1ff, 0x37e0c7cc), WTCP(0x7312c7a5, 0x380dfc8d), + WTCP(0x72fcbb8c, 0x383b28a9), WTCP(0x72e69db7, 0x38684c19), + WTCP(0x72d06e2b, 0x389566d6), WTCP(0x72ba2cea, 0x38c278d9), + WTCP(0x72a3d9f7, 0x38ef821c), WTCP(0x728d7557, 0x391c8297), + WTCP(0x7276ff0d, 0x39497a43), WTCP(0x7260771b, 0x39766919), + WTCP(0x7249dd86, 0x39a34f13), WTCP(0x72333251, 0x39d02c2a), + WTCP(0x721c7580, 0x39fd0056), WTCP(0x7205a716, 0x3a29cb91), + WTCP(0x71eec716, 0x3a568dd4), WTCP(0x71d7d585, 0x3a834717), + WTCP(0x71c0d265, 0x3aaff755), WTCP(0x71a9bdba, 0x3adc9e86), + WTCP(0x71929789, 0x3b093ca3), WTCP(0x717b5fd3, 0x3b35d1a5), + WTCP(0x7164169d, 0x3b625d86), WTCP(0x714cbbeb, 0x3b8ee03e), + WTCP(0x71354fc0, 0x3bbb59c7), WTCP(0x711dd220, 0x3be7ca1a), + WTCP(0x7106430e, 0x3c143130), WTCP(0x70eea28e, 0x3c408f03), + WTCP(0x70d6f0a4, 0x3c6ce38a), WTCP(0x70bf2d53, 0x3c992ec0), + WTCP(0x70a7589f, 0x3cc5709e), WTCP(0x708f728b, 0x3cf1a91c), + WTCP(0x70777b1c, 0x3d1dd835), WTCP(0x705f7255, 0x3d49fde1), + WTCP(0x70475839, 0x3d761a19), WTCP(0x702f2ccd, 0x3da22cd7), + WTCP(0x7016f014, 0x3dce3614), WTCP(0x6ffea212, 0x3dfa35c8), + WTCP(0x6fe642ca, 0x3e262bee), WTCP(0x6fcdd241, 0x3e52187f), + WTCP(0x6fb5507a, 0x3e7dfb73), WTCP(0x6f9cbd79, 0x3ea9d4c3), + WTCP(0x6f841942, 0x3ed5a46b), WTCP(0x6f6b63d8, 0x3f016a61), + WTCP(0x6f529d40, 0x3f2d26a0), WTCP(0x6f39c57d, 0x3f58d921), + WTCP(0x6f20dc92, 0x3f8481dd), WTCP(0x6f07e285, 0x3fb020ce), + WTCP(0x6eeed758, 0x3fdbb5ec), WTCP(0x6ed5bb10, 0x40074132), + WTCP(0x6ebc8db0, 0x4032c297), WTCP(0x6ea34f3d, 0x405e3a16), + WTCP(0x6e89ffb9, 0x4089a7a8), WTCP(0x6e709f2a, 0x40b50b46), + WTCP(0x6e572d93, 0x40e064ea), WTCP(0x6e3daaf8, 0x410bb48c), + WTCP(0x6e24175c, 0x4136fa27), WTCP(0x6e0a72c5, 0x416235b2), + WTCP(0x6df0bd35, 0x418d6729), WTCP(0x6dd6f6b1, 0x41b88e84), + WTCP(0x6dbd1f3c, 0x41e3abbc), WTCP(0x6da336dc, 0x420ebecb), + WTCP(0x6d893d93, 0x4239c7aa), WTCP(0x6d6f3365, 0x4264c653), + WTCP(0x6d551858, 0x428fbabe), WTCP(0x6d3aec6e, 0x42baa4e6), + WTCP(0x6d20afac, 0x42e584c3), WTCP(0x6d066215, 0x43105a50), + WTCP(0x6cec03af, 0x433b2585), WTCP(0x6cd1947c, 0x4365e65b), + WTCP(0x6cb71482, 0x43909ccd), WTCP(0x6c9c83c3, 0x43bb48d4), + WTCP(0x6c81e245, 0x43e5ea68), WTCP(0x6c67300b, 0x44108184), + WTCP(0x6c4c6d1a, 0x443b0e21), WTCP(0x6c319975, 0x44659039), + WTCP(0x6c16b521, 0x449007c4), WTCP(0x6bfbc021, 0x44ba74bd), + WTCP(0x6be0ba7b, 0x44e4d71c), WTCP(0x6bc5a431, 0x450f2edb), + WTCP(0x6baa7d49, 0x45397bf4), WTCP(0x6b8f45c7, 0x4563be60), + WTCP(0x6b73fdae, 0x458df619), WTCP(0x6b58a503, 0x45b82318), + WTCP(0x6b3d3bcb, 0x45e24556), WTCP(0x6b21c208, 0x460c5cce), + WTCP(0x6b0637c1, 0x46366978), WTCP(0x6aea9cf8, 0x46606b4e), + WTCP(0x6acef1b2, 0x468a624a), WTCP(0x6ab335f4, 0x46b44e65), + WTCP(0x6a9769c1, 0x46de2f99), WTCP(0x6a7b8d1e, 0x470805df), + WTCP(0x6a5fa010, 0x4731d131), WTCP(0x6a43a29a, 0x475b9188), + WTCP(0x6a2794c1, 0x478546de), WTCP(0x6a0b7689, 0x47aef12c), + WTCP(0x69ef47f6, 0x47d8906d), WTCP(0x69d3090e, 0x48022499), + WTCP(0x69b6b9d3, 0x482badab), WTCP(0x699a5a4c, 0x48552b9b), + WTCP(0x697dea7b, 0x487e9e64), WTCP(0x69616a65, 0x48a805ff), + WTCP(0x6944da10, 0x48d16265), WTCP(0x6928397e, 0x48fab391), + WTCP(0x690b88b5, 0x4923f97b), WTCP(0x68eec7b9, 0x494d341e), + WTCP(0x68d1f68f, 0x49766373), WTCP(0x68b5153a, 0x499f8774), + WTCP(0x689823bf, 0x49c8a01b), WTCP(0x687b2224, 0x49f1ad61), + WTCP(0x685e106c, 0x4a1aaf3f), WTCP(0x6840ee9b, 0x4a43a5b0), + WTCP(0x6823bcb7, 0x4a6c90ad), WTCP(0x68067ac3, 0x4a957030), + WTCP(0x67e928c5, 0x4abe4433), WTCP(0x67cbc6c0, 0x4ae70caf), + WTCP(0x67ae54ba, 0x4b0fc99d), WTCP(0x6790d2b6, 0x4b387af9), + WTCP(0x677340ba, 0x4b6120bb), WTCP(0x67559eca, 0x4b89badd), + WTCP(0x6737ecea, 0x4bb24958), WTCP(0x671a2b20, 0x4bdacc28), + WTCP(0x66fc596f, 0x4c034345), WTCP(0x66de77dc, 0x4c2baea9), + WTCP(0x66c0866d, 0x4c540e4e), WTCP(0x66a28524, 0x4c7c622d), + WTCP(0x66847408, 0x4ca4aa41), WTCP(0x6666531d, 0x4ccce684), + WTCP(0x66482267, 0x4cf516ee), WTCP(0x6629e1ec, 0x4d1d3b7a), + WTCP(0x660b91af, 0x4d455422), WTCP(0x65ed31b5, 0x4d6d60df), + WTCP(0x65cec204, 0x4d9561ac), WTCP(0x65b0429f, 0x4dbd5682), + WTCP(0x6591b38c, 0x4de53f5a), WTCP(0x657314cf, 0x4e0d1c30), + WTCP(0x6554666d, 0x4e34ecfc), WTCP(0x6535a86b, 0x4e5cb1b9), + WTCP(0x6516dacd, 0x4e846a60), WTCP(0x64f7fd98, 0x4eac16eb), + WTCP(0x64d910d1, 0x4ed3b755), WTCP(0x64ba147d, 0x4efb4b96), + WTCP(0x649b08a0, 0x4f22d3aa), WTCP(0x647bed3f, 0x4f4a4f89), + WTCP(0x645cc260, 0x4f71bf2e), WTCP(0x643d8806, 0x4f992293), + WTCP(0x641e3e38, 0x4fc079b1), WTCP(0x63fee4f8, 0x4fe7c483), + WTCP(0x63df7c4d, 0x500f0302), WTCP(0x63c0043b, 0x50363529), + WTCP(0x63a07cc7, 0x505d5af1), WTCP(0x6380e5f6, 0x50847454), + WTCP(0x63613fcd, 0x50ab814d), WTCP(0x63418a50, 0x50d281d5), + WTCP(0x6321c585, 0x50f975e6), WTCP(0x6301f171, 0x51205d7b), + WTCP(0x62e20e17, 0x5147388c), WTCP(0x62c21b7e, 0x516e0715), + WTCP(0x62a219aa, 0x5194c910), WTCP(0x628208a1, 0x51bb7e75), + WTCP(0x6261e866, 0x51e22740), WTCP(0x6241b8ff, 0x5208c36a), + WTCP(0x62217a72, 0x522f52ee), WTCP(0x62012cc2, 0x5255d5c5), + WTCP(0x61e0cff5, 0x527c4bea), WTCP(0x61c06410, 0x52a2b556), + WTCP(0x619fe918, 0x52c91204), WTCP(0x617f5f12, 0x52ef61ee), + WTCP(0x615ec603, 0x5315a50e), WTCP(0x613e1df0, 0x533bdb5d), + WTCP(0x611d66de, 0x536204d7), WTCP(0x60fca0d2, 0x53882175), + WTCP(0x60dbcbd1, 0x53ae3131), WTCP(0x60bae7e1, 0x53d43406), + WTCP(0x6099f505, 0x53fa29ed), WTCP(0x6078f344, 0x542012e1), + WTCP(0x6057e2a2, 0x5445eedb), WTCP(0x6036c325, 0x546bbdd7), + WTCP(0x601594d1, 0x54917fce), WTCP(0x5ff457ad, 0x54b734ba), + WTCP(0x5fd30bbc, 0x54dcdc96), WTCP(0x5fb1b104, 0x5502775c), + WTCP(0x5f90478a, 0x55280505), WTCP(0x5f6ecf53, 0x554d858d), + WTCP(0x5f4d4865, 0x5572f8ed), WTCP(0x5f2bb2c5, 0x55985f20), + WTCP(0x5f0a0e77, 0x55bdb81f), WTCP(0x5ee85b82, 0x55e303e6), + WTCP(0x5ec699e9, 0x5608426e), WTCP(0x5ea4c9b3, 0x562d73b2), + WTCP(0x5e82eae5, 0x565297ab), WTCP(0x5e60fd84, 0x5677ae54), + WTCP(0x5e3f0194, 0x569cb7a8), WTCP(0x5e1cf71c, 0x56c1b3a1), + WTCP(0x5dfade20, 0x56e6a239), WTCP(0x5dd8b6a7, 0x570b8369), + WTCP(0x5db680b4, 0x5730572e), WTCP(0x5d943c4e, 0x57551d80), + WTCP(0x5d71e979, 0x5779d65b), WTCP(0x5d4f883b, 0x579e81b8), + WTCP(0x5d2d189a, 0x57c31f92), WTCP(0x5d0a9a9a, 0x57e7afe4), + WTCP(0x5ce80e41, 0x580c32a7), WTCP(0x5cc57394, 0x5830a7d6), + WTCP(0x5ca2ca99, 0x58550f6c), WTCP(0x5c801354, 0x58796962), + WTCP(0x5c5d4dcc, 0x589db5b3), WTCP(0x5c3a7a05, 0x58c1f45b), + WTCP(0x5c179806, 0x58e62552), WTCP(0x5bf4a7d2, 0x590a4893), + WTCP(0x5bd1a971, 0x592e5e19), WTCP(0x5bae9ce7, 0x595265df), + WTCP(0x5b8b8239, 0x59765fde), WTCP(0x5b68596d, 0x599a4c12), + WTCP(0x5b452288, 0x59be2a74), WTCP(0x5b21dd90, 0x59e1faff), + WTCP(0x5afe8a8b, 0x5a05bdae), WTCP(0x5adb297d, 0x5a29727b), + WTCP(0x5ab7ba6c, 0x5a4d1960), WTCP(0x5a943d5e, 0x5a70b258), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow96[] = { + WTCP(0x7ffffffd, 0x0001a838), WTCP(0x7fffffe2, 0x00056e83), + WTCP(0x7fffff79, 0x000b9fda), WTCP(0x7ffffe45, 0x00150e8e), + WTCP(0x7ffffb4d, 0x0022aeeb), WTCP(0x7ffff4c6, 0x00359b36), + WTCP(0x7fffe792, 0x004f14ff), WTCP(0x7fffce8b, 0x0070858c), + WTCP(0x7fffa18f, 0x009b7d75), WTCP(0x7fff5439, 0x00d1b353), + WTCP(0x7ffed442, 0x0115018f), WTCP(0x7ffe0775, 0x01676335), + WTCP(0x7ffcc937, 0x01caefcb), WTCP(0x7ffae79f, 0x0241d62e), + WTCP(0x7ff82019, 0x02ce567f), WTCP(0x7ff41ba4, 0x0372bb25), + WTCP(0x7fee6ac3, 0x043150fc), WTCP(0x7fe68129, 0x050c5ec8), + WTCP(0x7fdbb164, 0x06061c0f), WTCP(0x7fcd2894, 0x0720a779), + WTCP(0x7fb9ea80, 0x085dfce2), WTCP(0x7fa0ce2e, 0x09bfeb4d), + WTCP(0x7f807b45, 0x0b480ae2), WTCP(0x7f576880, 0x0cf7b339), + WTCP(0x7f23db4e, 0x0ecff212), WTCP(0x7ee3e8ee, 0x10d182c0), + WTCP(0x7e95791f, 0x12fcc670), WTCP(0x7e364a74, 0x1551bd88), + WTCP(0x7dc3f864, 0x17d00238), WTCP(0x7d3c02fd, 0x1a76c47e), + WTCP(0x7c9bd82a, 0x1d44c7ad), WTCP(0x7be0de56, 0x203861a1), + WTCP(0x7b08803d, 0x234f7ba6), WTCP(0x7a103993, 0x26879530), + WTCP(0x78f5a442, 0x29ddc854), WTCP(0x77b685de, 0x2d4ed00f), + WTCP(0x7650dcf5, 0x30d7103d), WTCP(0x74c2ede4, 0x34729f2d), + WTCP(0x730b4edb, 0x381d50ad), WTCP(0x7128f2c1, 0x3bd2c273), + WTCP(0x6f1b32a9, 0x3f8e698f), WTCP(0x6ce1d5a0, 0x434ba0d6), + WTCP(0x6a7d16a3, 0x4705b7e5), WTCP(0x67eda890, 0x4ab80288), + WTCP(0x6534b7f8, 0x4e5de842), WTCP(0x6253eacd, 0x51f2f39a), + WTCP(0x5f4d5de1, 0x5572e0f7), WTCP(0x5c23a04a, 0x58d9acb9), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow120[] = { + WTCP(0x7ffffffe, 0x00017b6f), WTCP(0x7fffffef, 0x00042d2f), + WTCP(0x7fffffbb, 0x000849d0), WTCP(0x7fffff36, 0x000e3494), + WTCP(0x7ffffe0c, 0x00165efd), WTCP(0x7ffffbac, 0x002149be), + WTCP(0x7ffff72e, 0x002f854c), WTCP(0x7fffef24, 0x0041b235), + WTCP(0x7fffe167, 0x0058814f), WTCP(0x7fffcacd, 0x0074b3af), + WTCP(0x7fffa6d0, 0x00971a67), WTCP(0x7fff6f1e, 0x00c0960e), + WTCP(0x7fff1b12, 0x00f21602), WTCP(0x7ffe9f0b, 0x012c9775), + WTCP(0x7ffdebb2, 0x01712428), WTCP(0x7ffced1b, 0x01c0d0f7), + WTCP(0x7ffb89c2, 0x021cbc12), WTCP(0x7ff9a17c, 0x02860b05), + WTCP(0x7ff70c39, 0x02fde875), WTCP(0x7ff398bc, 0x038581b3), + WTCP(0x7fef0b3b, 0x041e040c), WTCP(0x7fe91bf3, 0x04c899f4), + WTCP(0x7fe175ba, 0x05866803), WTCP(0x7fd7b493, 0x065889d5), + WTCP(0x7fcb6459, 0x07400ed4), WTCP(0x7fbbff82, 0x083df6e9), + WTCP(0x7fa8ee09, 0x09532f37), WTCP(0x7f91849a, 0x0a808ed1), + WTCP(0x7f7503f2, 0x0bc6d381), WTCP(0x7f52989a, 0x0d269eb0), + WTCP(0x7f295af4, 0x0ea07270), WTCP(0x7ef84fb6, 0x1034aeb6), + WTCP(0x7ebe68c5, 0x11e38ed2), WTCP(0x7e7a8686, 0x13ad2733), + WTCP(0x7e2b79a3, 0x1591636d), WTCP(0x7dd0053c, 0x179004a7), + WTCP(0x7d66e18b, 0x19a8a05f), WTCP(0x7ceebef0, 0x1bda9fa2), + WTCP(0x7c664953, 0x1e253ea1), WTCP(0x7bcc2be8, 0x20878cce), + WTCP(0x7b1f1526, 0x23006d5d), WTCP(0x7a5dbb01, 0x258e9848), + WTCP(0x7986df3e, 0x28309bc6), WTCP(0x789953e0, 0x2ae4de3e), + WTCP(0x7793ff88, 0x2da9a0a8), WTCP(0x7675e1cc, 0x307d0163), + WTCP(0x753e1763, 0x335cff72), WTCP(0x73ebde10, 0x36477e1f), + WTCP(0x727e984e, 0x393a48f1), WTCP(0x70f5d09b, 0x3c3317f9), + WTCP(0x6f513c60, 0x3f2f945c), WTCP(0x6d90be61, 0x422d5d18), + WTCP(0x6bb468b1, 0x452a0bf3), WTCP(0x69bc7e1e, 0x48233a81), + WTCP(0x67a97317, 0x4b16873e), WTCP(0x657bedfa, 0x4e019a9d), + WTCP(0x6334c6d2, 0x50e22c0b), WTCP(0x60d50689, 0x53b606cb), + WTCP(0x5e5de588, 0x567b0ea7), WTCP(0x5bd0c9c6, 0x592f4460), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow128[] = { + WTCP(0x7ffffffe, 0x00016f63), WTCP(0x7ffffff1, 0x0003e382), + WTCP(0x7fffffc7, 0x00078f64), WTCP(0x7fffff5d, 0x000cc323), + WTCP(0x7ffffe76, 0x0013d9ed), WTCP(0x7ffffcaa, 0x001d3a9d), + WTCP(0x7ffff953, 0x0029581f), WTCP(0x7ffff372, 0x0038b1bd), + WTCP(0x7fffe98b, 0x004bd34d), WTCP(0x7fffd975, 0x00635538), + WTCP(0x7fffc024, 0x007fdc64), WTCP(0x7fff995b, 0x00a219f1), + WTCP(0x7fff5f5b, 0x00cacad0), WTCP(0x7fff0a75, 0x00fab72d), + WTCP(0x7ffe9091, 0x0132b1af), WTCP(0x7ffde49e, 0x01739689), + WTCP(0x7ffcf5ef, 0x01be4a63), WTCP(0x7ffbaf84, 0x0213b910), + WTCP(0x7ff9f73a, 0x0274d41e), WTCP(0x7ff7acf1, 0x02e2913a), + WTCP(0x7ff4a99a, 0x035de86c), WTCP(0x7ff0be3d, 0x03e7d233), + WTCP(0x7febb2f1, 0x0481457c), WTCP(0x7fe545d4, 0x052b357c), + WTCP(0x7fdd2a02, 0x05e68f77), WTCP(0x7fd30695, 0x06b4386f), + WTCP(0x7fc675b4, 0x07950acb), WTCP(0x7fb703be, 0x0889d3ef), + WTCP(0x7fa42e89, 0x099351e0), WTCP(0x7f8d64d8, 0x0ab230e0), + WTCP(0x7f7205f8, 0x0be70923), WTCP(0x7f516195, 0x0d325c93), + WTCP(0x7f2ab7d0, 0x0e9494ae), WTCP(0x7efd3997, 0x100e0085), + WTCP(0x7ec8094a, 0x119ed2ef), WTCP(0x7e8a3ba7, 0x134720d8), + WTCP(0x7e42d906, 0x1506dfdc), WTCP(0x7df0dee4, 0x16dde50b), + WTCP(0x7d9341b4, 0x18cbe3f7), WTCP(0x7d28ef02, 0x1ad06e07), + WTCP(0x7cb0cfcc, 0x1ceaf215), WTCP(0x7c29cb20, 0x1f1abc4f), + WTCP(0x7b92c8eb, 0x215ef677), WTCP(0x7aeab4ec, 0x23b6a867), + WTCP(0x7a3081d0, 0x2620b8ec), WTCP(0x79632c5a, 0x289beef5), + WTCP(0x7881be95, 0x2b26f30b), WTCP(0x778b5304, 0x2dc0511f), + WTCP(0x767f17c0, 0x30667aa2), WTCP(0x755c5178, 0x3317c8dd), + WTCP(0x74225e50, 0x35d27f98), WTCP(0x72d0b887, 0x3894cff3), + WTCP(0x7166f8e7, 0x3b5cdb7b), WTCP(0x6fe4d8e8, 0x3e28b770), + WTCP(0x6e4a3491, 0x40f6702a), WTCP(0x6c970bfc, 0x43c40caa), + WTCP(0x6acb8483, 0x468f9231), WTCP(0x68e7e994, 0x495707f5), + WTCP(0x66ecad1c, 0x4c187ac7), WTCP(0x64da6797, 0x4ed200c5), + WTCP(0x62b1d7b7, 0x5181bcea), WTCP(0x6073e1ae, 0x5425e28e), + WTCP(0x5e218e16, 0x56bcb8c2), WTCP(0x5bbc0875, 0x59449d76), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow256[] = { + WTCP(0x7fffffff, 0x000103c8), WTCP(0x7ffffffc, 0x000203ad), + WTCP(0x7ffffff5, 0x0003410a), WTCP(0x7fffffe9, 0x0004c6ce), + WTCP(0x7fffffd4, 0x00069ee0), WTCP(0x7fffffb2, 0x0008d376), + WTCP(0x7fffff7d, 0x000b6f5a), WTCP(0x7fffff2e, 0x000e7dfd), + WTCP(0x7ffffeba, 0x00120b83), WTCP(0x7ffffe16, 0x001624cd), + WTCP(0x7ffffd30, 0x001ad778), WTCP(0x7ffffbf3, 0x002031e2), + WTCP(0x7ffffa48, 0x00264330), WTCP(0x7ffff80d, 0x002d1b4b), + WTCP(0x7ffff51d, 0x0034cae6), WTCP(0x7ffff147, 0x003d637c), + WTCP(0x7fffec54, 0x0046f751), WTCP(0x7fffe5fe, 0x00519974), + WTCP(0x7fffddf3, 0x005d5dba), WTCP(0x7fffd3d2, 0x006a58c1), + WTCP(0x7fffc72a, 0x00789feb), WTCP(0x7fffb772, 0x0088495d), + WTCP(0x7fffa40e, 0x00996bfb), WTCP(0x7fff8c46, 0x00ac1f63), + WTCP(0x7fff6f46, 0x00c07bec), WTCP(0x7fff4c19, 0x00d69a9b), + WTCP(0x7fff21a6, 0x00ee9523), WTCP(0x7ffeeeab, 0x010885d9), + WTCP(0x7ffeb1b8, 0x012487b1), WTCP(0x7ffe692f, 0x0142b631), + WTCP(0x7ffe1335, 0x01632d6f), WTCP(0x7ffdadb8, 0x01860a00), + WTCP(0x7ffd3661, 0x01ab68f3), WTCP(0x7ffcaa91, 0x01d367c5), + WTCP(0x7ffc075b, 0x01fe2453), WTCP(0x7ffb497e, 0x022bbcd0), + WTCP(0x7ffa6d59, 0x025c4fba), WTCP(0x7ff96eeb, 0x028ffbc7), + WTCP(0x7ff849c6, 0x02c6dfdb), WTCP(0x7ff6f90b, 0x03011afc), + WTCP(0x7ff57760, 0x033ecc3a), WTCP(0x7ff3bee7, 0x038012a8), + WTCP(0x7ff1c939, 0x03c50d47), WTCP(0x7fef8f5a, 0x040ddaf6), + WTCP(0x7fed09b4, 0x045a9a64), WTCP(0x7fea300e, 0x04ab69f9), + WTCP(0x7fe6f980, 0x050067c7), WTCP(0x7fe35c70, 0x0559b17b), + WTCP(0x7fdf4e88, 0x05b76443), WTCP(0x7fdac4ad, 0x06199cc4), + WTCP(0x7fd5b2f8, 0x068076fe), WTCP(0x7fd00caf, 0x06ec0e41), + WTCP(0x7fc9c441, 0x075c7d16), WTCP(0x7fc2cb3b, 0x07d1dd2c), + WTCP(0x7fbb1242, 0x084c4745), WTCP(0x7fb28915, 0x08cbd323), + WTCP(0x7fa91e7e, 0x09509778), WTCP(0x7f9ec059, 0x09daa9cc), + WTCP(0x7f935b87, 0x0a6a1e74), WTCP(0x7f86dbf2, 0x0aff0877), + WTCP(0x7f792c8a, 0x0b997983), WTCP(0x7f6a3746, 0x0c3981d6), + WTCP(0x7f59e520, 0x0cdf3030), WTCP(0x7f481e1c, 0x0d8a91c3), + WTCP(0x7f34c949, 0x0e3bb222), WTCP(0x7f1fccc3, 0x0ef29b30), + WTCP(0x7f090dbc, 0x0faf5513), WTCP(0x7ef0707d, 0x1071e629), + WTCP(0x7ed5d872, 0x113a52f4), WTCP(0x7eb92831, 0x12089e14), + WTCP(0x7e9a4183, 0x12dcc836), WTCP(0x7e790571, 0x13b6d010), + WTCP(0x7e55544e, 0x1496b24f), WTCP(0x7e2f0dc8, 0x157c6998), + WTCP(0x7e0610f1, 0x1667ee77), WTCP(0x7dda3c54, 0x17593760), + WTCP(0x7dab6e06, 0x185038a3), WTCP(0x7d7983b3, 0x194ce46e), + WTCP(0x7d445ab5, 0x1a4f2ac4), WTCP(0x7d0bd028, 0x1b56f981), + WTCP(0x7ccfc0fd, 0x1c643c54), WTCP(0x7c900a11, 0x1d76dcc2), + WTCP(0x7c4c8844, 0x1e8ec227), WTCP(0x7c05188d, 0x1fabd1bb), + WTCP(0x7bb99817, 0x20cdee92), WTCP(0x7b69e455, 0x21f4f9a6), + WTCP(0x7b15db1a, 0x2320d1dc), WTCP(0x7abd5ab8, 0x2451540c), + WTCP(0x7a604213, 0x25865b09), WTCP(0x79fe70bf, 0x26bfbfaf), + WTCP(0x7997c716, 0x27fd58ed), WTCP(0x792c2654, 0x293efbd0), + WTCP(0x78bb70b0, 0x2a847b97), WTCP(0x78458976, 0x2bcda9bb), + WTCP(0x77ca551d, 0x2d1a5608), WTCP(0x7749b965, 0x2e6a4ea6), + WTCP(0x76c39d68, 0x2fbd6036), WTCP(0x7637e9b8, 0x311355dc), + WTCP(0x75a68873, 0x326bf95a), WTCP(0x750f6559, 0x33c71326), + WTCP(0x74726de1, 0x35246a7e), WTCP(0x73cf914f, 0x3683c582), + WTCP(0x7326c0c8, 0x37e4e94b), WTCP(0x7277ef5f, 0x39479a08), + WTCP(0x71c3122f, 0x3aab9b14), WTCP(0x71082063, 0x3c10af11), + WTCP(0x7047134a, 0x3d769807), WTCP(0x6f7fe661, 0x3edd177c), + WTCP(0x6eb29763, 0x4043ee92), WTCP(0x6ddf2651, 0x41aade26), + WTCP(0x6d05957c, 0x4311a6e8), WTCP(0x6c25e98f, 0x4478097b), + WTCP(0x6b402991, 0x45ddc693), WTCP(0x6a545ef0, 0x47429f13), + WTCP(0x6962957f, 0x48a65427), WTCP(0x686adb7c, 0x4a08a764), + WTCP(0x676d418d, 0x4b695ae8), WTCP(0x6669dac2, 0x4cc83171), + WTCP(0x6560bc90, 0x4e24ee7d), WTCP(0x6451fecf, 0x4f7f5668), + WTCP(0x633dbbb1, 0x50d72e85), WTCP(0x62240fbd, 0x522c3d3b), + WTCP(0x610519c7, 0x537e4a1f), WTCP(0x5fe0fae3, 0x54cd1e10), + WTCP(0x5eb7d65c, 0x5618834c), WTCP(0x5d89d1a5, 0x57604590), + WTCP(0x5c57144b, 0x58a43227), WTCP(0x5b1fc7e6, 0x59e41808), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow768[] = { + WTCP(0x7fffff85, 0x000b11d9), WTCP(0x7ffffef0, 0x00107aa9), + WTCP(0x7ffffe3e, 0x0015351c), WTCP(0x7ffffd6c, 0x0019b0a1), + WTCP(0x7ffffc77, 0x001e1656), WTCP(0x7ffffb5b, 0x00227a80), + WTCP(0x7ffffa16, 0x0026e8d3), WTCP(0x7ffff8a4, 0x002b68c9), + WTCP(0x7ffff700, 0x002fff8a), WTCP(0x7ffff528, 0x0034b0d9), + WTCP(0x7ffff316, 0x00397f9c), WTCP(0x7ffff0c6, 0x003e6e22), + WTCP(0x7fffee35, 0x00437e53), WTCP(0x7fffeb5b, 0x0048b1d0), + WTCP(0x7fffe836, 0x004e0a05), WTCP(0x7fffe4be, 0x00538837), + WTCP(0x7fffe0ef, 0x00592d8e), WTCP(0x7fffdcc3, 0x005efb1a), + WTCP(0x7fffd832, 0x0064f1da), WTCP(0x7fffd337, 0x006b12c1), + WTCP(0x7fffcdcb, 0x00715eb4), WTCP(0x7fffc7e7, 0x0077d692), + WTCP(0x7fffc182, 0x007e7b30), WTCP(0x7fffba96, 0x00854d61), + WTCP(0x7fffb31b, 0x008c4df0), WTCP(0x7fffab06, 0x00937da6), + WTCP(0x7fffa251, 0x009add48), WTCP(0x7fff98f1, 0x00a26d98), + WTCP(0x7fff8edd, 0x00aa2f57), WTCP(0x7fff840b, 0x00b22343), + WTCP(0x7fff7870, 0x00ba4a19), WTCP(0x7fff6c02, 0x00c2a495), + WTCP(0x7fff5eb5, 0x00cb3371), WTCP(0x7fff507e, 0x00d3f767), + WTCP(0x7fff4150, 0x00dcf130), WTCP(0x7fff311f, 0x00e62183), + WTCP(0x7fff1fde, 0x00ef8919), WTCP(0x7fff0d7f, 0x00f928a7), + WTCP(0x7ffef9f4, 0x010300e5), WTCP(0x7ffee52f, 0x010d1288), + WTCP(0x7ffecf20, 0x01175e47), WTCP(0x7ffeb7b8, 0x0121e4d6), + WTCP(0x7ffe9ee6, 0x012ca6eb), WTCP(0x7ffe849b, 0x0137a53b), + WTCP(0x7ffe68c4, 0x0142e07a), WTCP(0x7ffe4b50, 0x014e595c), + WTCP(0x7ffe2c2c, 0x015a1095), WTCP(0x7ffe0b45, 0x016606da), + WTCP(0x7ffde888, 0x01723cde), WTCP(0x7ffdc3df, 0x017eb353), + WTCP(0x7ffd9d37, 0x018b6aed), WTCP(0x7ffd7479, 0x0198645f), + WTCP(0x7ffd4990, 0x01a5a05b), WTCP(0x7ffd1c63, 0x01b31f92), + WTCP(0x7ffcecdc, 0x01c0e2b8), WTCP(0x7ffcbae2, 0x01ceea7d), + WTCP(0x7ffc865c, 0x01dd3793), WTCP(0x7ffc4f2f, 0x01ebcaaa), + WTCP(0x7ffc1542, 0x01faa472), WTCP(0x7ffbd879, 0x0209c59c), + WTCP(0x7ffb98b7, 0x02192ed7), WTCP(0x7ffb55e0, 0x0228e0d2), + WTCP(0x7ffb0fd6, 0x0238dc3c), WTCP(0x7ffac679, 0x024921c3), + WTCP(0x7ffa79ac, 0x0259b215), WTCP(0x7ffa294d, 0x026a8dde), + WTCP(0x7ff9d53b, 0x027bb5cc), WTCP(0x7ff97d54, 0x028d2a8a), + WTCP(0x7ff92175, 0x029eecc3), WTCP(0x7ff8c17a, 0x02b0fd23), + WTCP(0x7ff85d3f, 0x02c35c53), WTCP(0x7ff7f49d, 0x02d60afd), + WTCP(0x7ff7876e, 0x02e909ca), WTCP(0x7ff7158b, 0x02fc5960), + WTCP(0x7ff69eca, 0x030ffa69), WTCP(0x7ff62303, 0x0323ed89), + WTCP(0x7ff5a20a, 0x03383367), WTCP(0x7ff51bb3, 0x034ccca7), + WTCP(0x7ff48fd3, 0x0361b9ed), WTCP(0x7ff3fe3c, 0x0376fbdd), + WTCP(0x7ff366be, 0x038c9317), WTCP(0x7ff2c929, 0x03a2803e), + WTCP(0x7ff2254e, 0x03b8c3f2), WTCP(0x7ff17afa, 0x03cf5ed1), + WTCP(0x7ff0c9f9, 0x03e6517a), WTCP(0x7ff01218, 0x03fd9c8a), + WTCP(0x7fef5321, 0x0415409c), WTCP(0x7fee8cde, 0x042d3e4d), + WTCP(0x7fedbf17, 0x04459634), WTCP(0x7fece993, 0x045e48ec), + WTCP(0x7fec0c18, 0x0477570a), WTCP(0x7feb266a, 0x0490c127), + WTCP(0x7fea384e, 0x04aa87d5), WTCP(0x7fe94186, 0x04c4abaa), + WTCP(0x7fe841d3, 0x04df2d37), WTCP(0x7fe738f4, 0x04fa0d0d), + WTCP(0x7fe626a9, 0x05154bbc), WTCP(0x7fe50aaf, 0x0530e9d3), + WTCP(0x7fe3e4c1, 0x054ce7dd), WTCP(0x7fe2b49b, 0x05694667), + WTCP(0x7fe179f6, 0x058605fa), WTCP(0x7fe0348b, 0x05a3271e), + WTCP(0x7fdee410, 0x05c0aa5c), WTCP(0x7fdd883b, 0x05de9038), + WTCP(0x7fdc20c1, 0x05fcd935), WTCP(0x7fdaad53, 0x061b85d6), + WTCP(0x7fd92da5, 0x063a969c), WTCP(0x7fd7a166, 0x065a0c06), + WTCP(0x7fd60844, 0x0679e690), WTCP(0x7fd461ee, 0x069a26b6), + WTCP(0x7fd2ae10, 0x06baccf2), WTCP(0x7fd0ec55, 0x06dbd9bd), + WTCP(0x7fcf1c65, 0x06fd4d8c), WTCP(0x7fcd3de9, 0x071f28d3), + WTCP(0x7fcb5088, 0x07416c06), WTCP(0x7fc953e6, 0x07641794), + WTCP(0x7fc747a8, 0x07872bee), WTCP(0x7fc52b70, 0x07aaa97f), + WTCP(0x7fc2fedf, 0x07ce90b4), WTCP(0x7fc0c195, 0x07f2e1f4), + WTCP(0x7fbe732f, 0x08179da7), WTCP(0x7fbc134b, 0x083cc431), + WTCP(0x7fb9a183, 0x086255f7), WTCP(0x7fb71d72, 0x08885359), + WTCP(0x7fb486af, 0x08aebcb5), WTCP(0x7fb1dcd3, 0x08d59269), + WTCP(0x7faf1f72, 0x08fcd4cf), WTCP(0x7fac4e21, 0x09248440), + WTCP(0x7fa96873, 0x094ca111), WTCP(0x7fa66df8, 0x09752b98), + WTCP(0x7fa35e40, 0x099e2425), WTCP(0x7fa038db, 0x09c78b09), + WTCP(0x7f9cfd54, 0x09f16090), WTCP(0x7f99ab38, 0x0a1ba507), + WTCP(0x7f964210, 0x0a4658b6), WTCP(0x7f92c165, 0x0a717be2), + WTCP(0x7f8f28bf, 0x0a9d0ed1), WTCP(0x7f8b77a4, 0x0ac911c4), + WTCP(0x7f87ad97, 0x0af584fb), WTCP(0x7f83ca1d, 0x0b2268b2), + WTCP(0x7f7fccb5, 0x0b4fbd23), WTCP(0x7f7bb4e2, 0x0b7d8288), + WTCP(0x7f778221, 0x0babb915), WTCP(0x7f7333f1, 0x0bda60fd), + WTCP(0x7f6ec9cd, 0x0c097a72), WTCP(0x7f6a4330, 0x0c3905a1), + WTCP(0x7f659f94, 0x0c6902b6), WTCP(0x7f60de70, 0x0c9971d9), + WTCP(0x7f5bff3b, 0x0cca5331), WTCP(0x7f57016b, 0x0cfba6e3), + WTCP(0x7f51e474, 0x0d2d6d0e), WTCP(0x7f4ca7c8, 0x0d5fa5d2), + WTCP(0x7f474ad9, 0x0d92514a), WTCP(0x7f41cd17, 0x0dc56f90), + WTCP(0x7f3c2df1, 0x0df900bb), WTCP(0x7f366cd5, 0x0e2d04de), + WTCP(0x7f30892e, 0x0e617c0a), WTCP(0x7f2a8269, 0x0e96664e), + WTCP(0x7f2457ef, 0x0ecbc3b5), WTCP(0x7f1e0929, 0x0f019449), + WTCP(0x7f17957e, 0x0f37d80f), WTCP(0x7f10fc55, 0x0f6e8f0c), + WTCP(0x7f0a3d14, 0x0fa5b940), WTCP(0x7f03571d, 0x0fdd56a8), + WTCP(0x7efc49d4, 0x10156740), WTCP(0x7ef5149b, 0x104deb00), + WTCP(0x7eedb6d2, 0x1086e1dd), WTCP(0x7ee62fda, 0x10c04bca), + WTCP(0x7ede7f11, 0x10fa28b7), WTCP(0x7ed6a3d5, 0x11347890), + WTCP(0x7ece9d81, 0x116f3b3f), WTCP(0x7ec66b73, 0x11aa70ac), + WTCP(0x7ebe0d04, 0x11e618ba), WTCP(0x7eb5818d, 0x1222334c), + WTCP(0x7eacc869, 0x125ec03e), WTCP(0x7ea3e0ef, 0x129bbf6e), + WTCP(0x7e9aca75, 0x12d930b2), WTCP(0x7e918452, 0x131713e2), + WTCP(0x7e880ddb, 0x135568cf), WTCP(0x7e7e6665, 0x13942f49), + WTCP(0x7e748d43, 0x13d3671e), WTCP(0x7e6a81c8, 0x14131017), + WTCP(0x7e604347, 0x145329fa), WTCP(0x7e55d111, 0x1493b48c), + WTCP(0x7e4b2a76, 0x14d4af8e), WTCP(0x7e404ec8, 0x15161abe), + WTCP(0x7e353d55, 0x1557f5d7), WTCP(0x7e29f56c, 0x159a4090), + WTCP(0x7e1e765c, 0x15dcfaa0), WTCP(0x7e12bf72, 0x162023b7), + WTCP(0x7e06cffc, 0x1663bb86), WTCP(0x7dfaa746, 0x16a7c1b9), + WTCP(0x7dee449e, 0x16ec35f7), WTCP(0x7de1a74e, 0x173117e9), + WTCP(0x7dd4cea3, 0x17766731), WTCP(0x7dc7b9e7, 0x17bc236f), + WTCP(0x7dba6865, 0x18024c40), WTCP(0x7dacd968, 0x1848e13f), + WTCP(0x7d9f0c3a, 0x188fe204), WTCP(0x7d910025, 0x18d74e22), + WTCP(0x7d82b472, 0x191f252c), WTCP(0x7d74286c, 0x196766ae), + WTCP(0x7d655b5b, 0x19b01236), WTCP(0x7d564c8a, 0x19f9274b), + WTCP(0x7d46fb40, 0x1a42a574), WTCP(0x7d3766c8, 0x1a8c8c32), + WTCP(0x7d278e6a, 0x1ad6db06), WTCP(0x7d17716f, 0x1b21916c), + WTCP(0x7d070f22, 0x1b6caedf), WTCP(0x7cf666cb, 0x1bb832d5), + WTCP(0x7ce577b3, 0x1c041cc2), WTCP(0x7cd44124, 0x1c506c17), + WTCP(0x7cc2c269, 0x1c9d2044), WTCP(0x7cb0faca, 0x1cea38b2), + WTCP(0x7c9ee992, 0x1d37b4cc), WTCP(0x7c8c8e0c, 0x1d8593f5), + WTCP(0x7c79e782, 0x1dd3d592), WTCP(0x7c66f541, 0x1e227903), + WTCP(0x7c53b692, 0x1e717da3), WTCP(0x7c402ac3, 0x1ec0e2cf), + WTCP(0x7c2c5120, 0x1f10a7dc), WTCP(0x7c1828f6, 0x1f60cc21), + WTCP(0x7c03b193, 0x1fb14eef), WTCP(0x7beeea44, 0x20022f96), + WTCP(0x7bd9d259, 0x20536d61), WTCP(0x7bc46921, 0x20a5079a), + WTCP(0x7baeadec, 0x20f6fd8a), WTCP(0x7b98a00b, 0x21494e73), + WTCP(0x7b823ecf, 0x219bf998), WTCP(0x7b6b898b, 0x21eefe37), + WTCP(0x7b547f93, 0x22425b8d), WTCP(0x7b3d203a, 0x229610d4), + WTCP(0x7b256ad5, 0x22ea1d42), WTCP(0x7b0d5ebb, 0x233e800c), + WTCP(0x7af4fb42, 0x23933864), WTCP(0x7adc3fc2, 0x23e8457a), + WTCP(0x7ac32b95, 0x243da679), WTCP(0x7aa9be14, 0x24935a8d), + WTCP(0x7a8ff69a, 0x24e960dd), WTCP(0x7a75d485, 0x253fb88e), + WTCP(0x7a5b5731, 0x259660c3), WTCP(0x7a407dfe, 0x25ed589c), + WTCP(0x7a25484c, 0x26449f38), WTCP(0x7a09b57c, 0x269c33b1), + WTCP(0x79edc4f1, 0x26f41522), WTCP(0x79d1760e, 0x274c42a0), + WTCP(0x79b4c83b, 0x27a4bb40), WTCP(0x7997badd, 0x27fd7e15), + WTCP(0x797a4d5e, 0x28568a2f), WTCP(0x795c7f26, 0x28afde9a), + WTCP(0x793e4fa3, 0x29097a63), WTCP(0x791fbe40, 0x29635c92), + WTCP(0x7900ca6e, 0x29bd842e), WTCP(0x78e1739c, 0x2a17f03e), + WTCP(0x78c1b93d, 0x2a729fc2), WTCP(0x78a19ac4, 0x2acd91bc), + WTCP(0x788117a7, 0x2b28c52a), WTCP(0x78602f5e, 0x2b843909), + WTCP(0x783ee163, 0x2bdfec54), WTCP(0x781d2d2f, 0x2c3bde02), + WTCP(0x77fb1241, 0x2c980d0a), WTCP(0x77d89017, 0x2cf47862), + WTCP(0x77b5a632, 0x2d511efb), WTCP(0x77925416, 0x2dadffc6), + WTCP(0x776e9947, 0x2e0b19b3), WTCP(0x774a754d, 0x2e686bae), + WTCP(0x7725e7b0, 0x2ec5f4a4), WTCP(0x7700effd, 0x2f23b37d), + WTCP(0x76db8dbf, 0x2f81a721), WTCP(0x76b5c088, 0x2fdfce77), + WTCP(0x768f87e8, 0x303e2863), WTCP(0x7668e375, 0x309cb3c8), + WTCP(0x7641d2c4, 0x30fb6f88), WTCP(0x761a556e, 0x315a5a82), + WTCP(0x75f26b0e, 0x31b97394), WTCP(0x75ca1341, 0x3218b99c), + WTCP(0x75a14da8, 0x32782b74), WTCP(0x757819e4, 0x32d7c7f6), + WTCP(0x754e779a, 0x33378dfc), WTCP(0x75246671, 0x33977c5b), + WTCP(0x74f9e613, 0x33f791e9), WTCP(0x74cef62b, 0x3457cd7c), + WTCP(0x74a3966a, 0x34b82de6), WTCP(0x7477c67f, 0x3518b1f9), + WTCP(0x744b861e, 0x35795887), WTCP(0x741ed4ff, 0x35da205e), + WTCP(0x73f1b2da, 0x363b084e), WTCP(0x73c41f6b, 0x369c0f24), + WTCP(0x73961a71, 0x36fd33ac), WTCP(0x7367a3ac, 0x375e74b1), + WTCP(0x7338bae1, 0x37bfd0ff), WTCP(0x73095fd7, 0x3821475f), + WTCP(0x72d99257, 0x3882d699), WTCP(0x72a9522d, 0x38e47d75), + WTCP(0x72789f28, 0x39463aba), WTCP(0x7247791b, 0x39a80d2e), + WTCP(0x7215dfda, 0x3a09f397), WTCP(0x71e3d33d, 0x3a6becba), + WTCP(0x71b1531f, 0x3acdf75a), WTCP(0x717e5f5d, 0x3b30123b), + WTCP(0x714af7d7, 0x3b923c20), WTCP(0x71171c72, 0x3bf473cc), + WTCP(0x70e2cd14, 0x3c56b7ff), WTCP(0x70ae09a6, 0x3cb9077b), + WTCP(0x7078d215, 0x3d1b6101), WTCP(0x7043264f, 0x3d7dc353), + WTCP(0x700d0648, 0x3de02d2e), WTCP(0x6fd671f5, 0x3e429d55), + WTCP(0x6f9f694f, 0x3ea51285), WTCP(0x6f67ec52, 0x3f078b7f), + WTCP(0x6f2ffafb, 0x3f6a0701), WTCP(0x6ef7954e, 0x3fcc83ca), + WTCP(0x6ebebb4e, 0x402f009a), WTCP(0x6e856d05, 0x40917c2e), + WTCP(0x6e4baa7e, 0x40f3f546), WTCP(0x6e1173c6, 0x41566aa1), + WTCP(0x6dd6c8ef, 0x41b8dafc), WTCP(0x6d9baa0f, 0x421b4518), + WTCP(0x6d60173d, 0x427da7b1), WTCP(0x6d241094, 0x42e00189), + WTCP(0x6ce79632, 0x4342515e), WTCP(0x6caaa839, 0x43a495ef), + WTCP(0x6c6d46ce, 0x4406cdfd), WTCP(0x6c2f7218, 0x4468f848), + WTCP(0x6bf12a42, 0x44cb138f), WTCP(0x6bb26f7b, 0x452d1e94), + WTCP(0x6b7341f5, 0x458f1818), WTCP(0x6b33a1e3, 0x45f0fede), + WTCP(0x6af38f7e, 0x4652d1a6), WTCP(0x6ab30b01, 0x46b48f34), + WTCP(0x6a7214ab, 0x4716364c), WTCP(0x6a30acbd, 0x4777c5b2), + WTCP(0x69eed37c, 0x47d93c2a), WTCP(0x69ac8930, 0x483a987a), + WTCP(0x6969ce24, 0x489bd968), WTCP(0x6926a2a8, 0x48fcfdbb), + WTCP(0x68e3070c, 0x495e043b), WTCP(0x689efba7, 0x49beebb0), + WTCP(0x685a80cf, 0x4a1fb2e5), WTCP(0x681596e1, 0x4a8058a4), + WTCP(0x67d03e3b, 0x4ae0dbb8), WTCP(0x678a773f, 0x4b413aee), + WTCP(0x67444253, 0x4ba17514), WTCP(0x66fd9fde, 0x4c0188f8), + WTCP(0x66b6904c, 0x4c61756b), WTCP(0x666f140d, 0x4cc1393d), + WTCP(0x66272b91, 0x4d20d341), WTCP(0x65ded74d, 0x4d80424a), + WTCP(0x659617bb, 0x4ddf852d), WTCP(0x654ced55, 0x4e3e9ac1), + WTCP(0x6503589b, 0x4e9d81dc), WTCP(0x64b95a0d, 0x4efc3959), + WTCP(0x646ef230, 0x4f5ac010), WTCP(0x6424218d, 0x4fb914df), + WTCP(0x63d8e8ae, 0x501736a1), WTCP(0x638d4822, 0x50752438), + WTCP(0x6341407a, 0x50d2dc82), WTCP(0x62f4d24b, 0x51305e61), + WTCP(0x62a7fe2b, 0x518da8bb), WTCP(0x625ac4b5, 0x51eaba74), + WTCP(0x620d2686, 0x52479273), WTCP(0x61bf2440, 0x52a42fa2), + WTCP(0x6170be85, 0x530090ea), WTCP(0x6121f5fb, 0x535cb53a), + WTCP(0x60d2cb4e, 0x53b89b7e), WTCP(0x60833f28, 0x541442a8), + WTCP(0x60335239, 0x546fa9a9), WTCP(0x5fe30533, 0x54cacf77), + WTCP(0x5f9258cc, 0x5525b306), WTCP(0x5f414dbb, 0x55805350), + WTCP(0x5eefe4bc, 0x55daaf4e), WTCP(0x5e9e1e8c, 0x5634c5fe), + WTCP(0x5e4bfbec, 0x568e965c), WTCP(0x5df97d9e, 0x56e81f6c), + WTCP(0x5da6a46a, 0x5741602e), WTCP(0x5d537118, 0x579a57a8), + WTCP(0x5cffe474, 0x57f304e2), WTCP(0x5cabff4c, 0x584b66e4), + WTCP(0x5c57c271, 0x58a37cbb), WTCP(0x5c032eb7, 0x58fb4576), + WTCP(0x5bae44f4, 0x5952c024), WTCP(0x5b590602, 0x59a9ebd8), + WTCP(0x5b0372bb, 0x5a00c7a8), WTCP(0x5aad8bfe, 0x5a5752ac), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow960[] = { + WTCP(0x7fffff9e, 0x0009e6ac), WTCP(0x7fffff2b, 0x000e96d5), + WTCP(0x7ffffea6, 0x0012987e), WTCP(0x7ffffe0e, 0x001652b6), + WTCP(0x7ffffd60, 0x0019ebce), WTCP(0x7ffffc9c, 0x001d76bf), + WTCP(0x7ffffbbf, 0x0020fe79), WTCP(0x7ffffac9, 0x002489ef), + WTCP(0x7ffff9b7, 0x00281de2), WTCP(0x7ffff887, 0x002bbdbb), + WTCP(0x7ffff737, 0x002f6c0d), WTCP(0x7ffff5c6, 0x00332ad8), + WTCP(0x7ffff431, 0x0036fbb9), WTCP(0x7ffff276, 0x003ae004), + WTCP(0x7ffff092, 0x003ed8d8), WTCP(0x7fffee84, 0x0042e72f), + WTCP(0x7fffec48, 0x00470be3), WTCP(0x7fffe9dd, 0x004b47b8), + WTCP(0x7fffe73f, 0x004f9b5f), WTCP(0x7fffe46b, 0x0054077a), + WTCP(0x7fffe15f, 0x00588ca1), WTCP(0x7fffde17, 0x005d2b61), + WTCP(0x7fffda91, 0x0061e442), WTCP(0x7fffd6c9, 0x0066b7c2), + WTCP(0x7fffd2bb, 0x006ba65c), WTCP(0x7fffce65, 0x0070b087), + WTCP(0x7fffc9c2, 0x0075d6b5), WTCP(0x7fffc4cf, 0x007b1955), + WTCP(0x7fffbf87, 0x008078d5), WTCP(0x7fffb9e7, 0x0085f5a0), + WTCP(0x7fffb3ea, 0x008b901d), WTCP(0x7fffad8c, 0x009148b4), + WTCP(0x7fffa6c9, 0x00971fcb), WTCP(0x7fff9f9c, 0x009d15c7), + WTCP(0x7fff9800, 0x00a32b0b), WTCP(0x7fff8ff0, 0x00a95ff9), + WTCP(0x7fff8767, 0x00afb4f4), WTCP(0x7fff7e5f, 0x00b62a5c), + WTCP(0x7fff74d4, 0x00bcc093), WTCP(0x7fff6ac0, 0x00c377f8), + WTCP(0x7fff601c, 0x00ca50eb), WTCP(0x7fff54e3, 0x00d14bcb), + WTCP(0x7fff490e, 0x00d868f7), WTCP(0x7fff3c98, 0x00dfa8ce), + WTCP(0x7fff2f79, 0x00e70bad), WTCP(0x7fff21ac, 0x00ee91f3), + WTCP(0x7fff1328, 0x00f63bfe), WTCP(0x7fff03e7, 0x00fe0a2c), + WTCP(0x7ffef3e1, 0x0105fcd9), WTCP(0x7ffee310, 0x010e1462), + WTCP(0x7ffed16a, 0x01165126), WTCP(0x7ffebee9, 0x011eb381), + WTCP(0x7ffeab83, 0x01273bd0), WTCP(0x7ffe9731, 0x012fea6f), + WTCP(0x7ffe81ea, 0x0138bfbc), WTCP(0x7ffe6ba4, 0x0141bc12), + WTCP(0x7ffe5457, 0x014adfce), WTCP(0x7ffe3bfa, 0x01542b4d), + WTCP(0x7ffe2282, 0x015d9ee9), WTCP(0x7ffe07e6, 0x01673b01), + WTCP(0x7ffdec1b, 0x0170ffee), WTCP(0x7ffdcf17, 0x017aee0e), + WTCP(0x7ffdb0d0, 0x018505bc), WTCP(0x7ffd913b, 0x018f4754), + WTCP(0x7ffd704b, 0x0199b330), WTCP(0x7ffd4df7, 0x01a449ad), + WTCP(0x7ffd2a31, 0x01af0b25), WTCP(0x7ffd04ef, 0x01b9f7f4), + WTCP(0x7ffcde23, 0x01c51074), WTCP(0x7ffcb5c1, 0x01d05501), + WTCP(0x7ffc8bbc, 0x01dbc5f5), WTCP(0x7ffc6006, 0x01e763ab), + WTCP(0x7ffc3293, 0x01f32e7d), WTCP(0x7ffc0354, 0x01ff26c5), + WTCP(0x7ffbd23b, 0x020b4cde), WTCP(0x7ffb9f3a, 0x0217a120), + WTCP(0x7ffb6a41, 0x022423e6), WTCP(0x7ffb3342, 0x0230d58a), + WTCP(0x7ffafa2d, 0x023db664), WTCP(0x7ffabef2, 0x024ac6ce), + WTCP(0x7ffa8180, 0x02580720), WTCP(0x7ffa41c9, 0x026577b3), + WTCP(0x7ff9ffb9, 0x027318e0), WTCP(0x7ff9bb41, 0x0280eaff), + WTCP(0x7ff9744e, 0x028eee68), WTCP(0x7ff92acf, 0x029d2371), + WTCP(0x7ff8deb1, 0x02ab8a74), WTCP(0x7ff88fe2, 0x02ba23c7), + WTCP(0x7ff83e4d, 0x02c8efc0), WTCP(0x7ff7e9e1, 0x02d7eeb7), + WTCP(0x7ff79288, 0x02e72101), WTCP(0x7ff7382f, 0x02f686f5), + WTCP(0x7ff6dac1, 0x030620e9), WTCP(0x7ff67a29, 0x0315ef31), + WTCP(0x7ff61651, 0x0325f224), WTCP(0x7ff5af23, 0x03362a14), + WTCP(0x7ff5448a, 0x03469758), WTCP(0x7ff4d66d, 0x03573a42), + WTCP(0x7ff464b7, 0x03681327), WTCP(0x7ff3ef4f, 0x0379225a), + WTCP(0x7ff3761d, 0x038a682e), WTCP(0x7ff2f90a, 0x039be4f4), + WTCP(0x7ff277fb, 0x03ad9900), WTCP(0x7ff1f2d8, 0x03bf84a3), + WTCP(0x7ff16986, 0x03d1a82e), WTCP(0x7ff0dbec, 0x03e403f3), + WTCP(0x7ff049ef, 0x03f69840), WTCP(0x7fefb373, 0x04096568), + WTCP(0x7fef185d, 0x041c6bb8), WTCP(0x7fee7890, 0x042fab81), + WTCP(0x7fedd3f1, 0x04432510), WTCP(0x7fed2a61, 0x0456d8b4), + WTCP(0x7fec7bc4, 0x046ac6ba), WTCP(0x7febc7fb, 0x047eef70), + WTCP(0x7feb0ee8, 0x04935322), WTCP(0x7fea506b, 0x04a7f21d), + WTCP(0x7fe98c65, 0x04bcccab), WTCP(0x7fe8c2b7, 0x04d1e318), + WTCP(0x7fe7f33e, 0x04e735af), WTCP(0x7fe71ddb, 0x04fcc4ba), + WTCP(0x7fe6426c, 0x05129081), WTCP(0x7fe560ce, 0x0528994d), + WTCP(0x7fe478df, 0x053edf68), WTCP(0x7fe38a7c, 0x05556318), + WTCP(0x7fe29581, 0x056c24a5), WTCP(0x7fe199ca, 0x05832455), + WTCP(0x7fe09733, 0x059a626e), WTCP(0x7fdf8d95, 0x05b1df35), + WTCP(0x7fde7ccb, 0x05c99aef), WTCP(0x7fdd64af, 0x05e195e0), + WTCP(0x7fdc451a, 0x05f9d04b), WTCP(0x7fdb1de4, 0x06124a73), + WTCP(0x7fd9eee5, 0x062b0499), WTCP(0x7fd8b7f5, 0x0643ff00), + WTCP(0x7fd778ec, 0x065d39e7), WTCP(0x7fd6319e, 0x0676b58f), + WTCP(0x7fd4e1e2, 0x06907237), WTCP(0x7fd3898d, 0x06aa701d), + WTCP(0x7fd22873, 0x06c4af80), WTCP(0x7fd0be6a, 0x06df309c), + WTCP(0x7fcf4b44, 0x06f9f3ad), WTCP(0x7fcdced4, 0x0714f8f0), + WTCP(0x7fcc48ed, 0x0730409f), WTCP(0x7fcab960, 0x074bcaf5), + WTCP(0x7fc91fff, 0x0767982a), WTCP(0x7fc77c9a, 0x0783a877), + WTCP(0x7fc5cf02, 0x079ffc14), WTCP(0x7fc41705, 0x07bc9338), + WTCP(0x7fc25474, 0x07d96e19), WTCP(0x7fc0871b, 0x07f68ced), + WTCP(0x7fbeaeca, 0x0813efe7), WTCP(0x7fbccb4c, 0x0831973d), + WTCP(0x7fbadc70, 0x084f8320), WTCP(0x7fb8e200, 0x086db3c3), + WTCP(0x7fb6dbc8, 0x088c2957), WTCP(0x7fb4c993, 0x08aae40c), + WTCP(0x7fb2ab2b, 0x08c9e412), WTCP(0x7fb0805a, 0x08e92997), + WTCP(0x7fae48e9, 0x0908b4c9), WTCP(0x7fac04a0, 0x092885d6), + WTCP(0x7fa9b347, 0x09489ce8), WTCP(0x7fa754a6, 0x0968fa2c), + WTCP(0x7fa4e884, 0x09899dcb), WTCP(0x7fa26ea6, 0x09aa87ee), + WTCP(0x7f9fe6d1, 0x09cbb8be), WTCP(0x7f9d50cc, 0x09ed3062), + WTCP(0x7f9aac5a, 0x0a0eef00), WTCP(0x7f97f93f, 0x0a30f4bf), + WTCP(0x7f95373e, 0x0a5341c2), WTCP(0x7f92661b, 0x0a75d62e), + WTCP(0x7f8f8596, 0x0a98b224), WTCP(0x7f8c9572, 0x0abbd5c7), + WTCP(0x7f89956f, 0x0adf4137), WTCP(0x7f86854d, 0x0b02f494), + WTCP(0x7f8364cd, 0x0b26effd), WTCP(0x7f8033ae, 0x0b4b338f), + WTCP(0x7f7cf1ae, 0x0b6fbf67), WTCP(0x7f799e8b, 0x0b9493a0), + WTCP(0x7f763a03, 0x0bb9b056), WTCP(0x7f72c3d2, 0x0bdf15a2), + WTCP(0x7f6f3bb5, 0x0c04c39c), WTCP(0x7f6ba168, 0x0c2aba5d), + WTCP(0x7f67f4a6, 0x0c50f9fa), WTCP(0x7f643529, 0x0c77828a), + WTCP(0x7f6062ac, 0x0c9e5420), WTCP(0x7f5c7ce8, 0x0cc56ed1), + WTCP(0x7f588397, 0x0cecd2ae), WTCP(0x7f547670, 0x0d147fc8), + WTCP(0x7f50552c, 0x0d3c7630), WTCP(0x7f4c1f83, 0x0d64b5f6), + WTCP(0x7f47d52a, 0x0d8d3f26), WTCP(0x7f4375d9, 0x0db611ce), + WTCP(0x7f3f0144, 0x0ddf2dfa), WTCP(0x7f3a7723, 0x0e0893b4), + WTCP(0x7f35d729, 0x0e324306), WTCP(0x7f31210a, 0x0e5c3bf9), + WTCP(0x7f2c547b, 0x0e867e94), WTCP(0x7f27712e, 0x0eb10add), + WTCP(0x7f2276d8, 0x0edbe0da), WTCP(0x7f1d6529, 0x0f07008e), + WTCP(0x7f183bd3, 0x0f3269fc), WTCP(0x7f12fa89, 0x0f5e1d27), + WTCP(0x7f0da0fb, 0x0f8a1a0e), WTCP(0x7f082ed8, 0x0fb660b1), + WTCP(0x7f02a3d2, 0x0fe2f10f), WTCP(0x7efcff98, 0x100fcb25), + WTCP(0x7ef741d9, 0x103ceeee), WTCP(0x7ef16a42, 0x106a5c66), + WTCP(0x7eeb7884, 0x10981386), WTCP(0x7ee56c4a, 0x10c61447), + WTCP(0x7edf4543, 0x10f45ea0), WTCP(0x7ed9031b, 0x1122f288), + WTCP(0x7ed2a57f, 0x1151cff3), WTCP(0x7ecc2c1a, 0x1180f6d5), + WTCP(0x7ec59699, 0x11b06720), WTCP(0x7ebee4a6, 0x11e020c8), + WTCP(0x7eb815ed, 0x121023ba), WTCP(0x7eb12a18, 0x12406fe8), + WTCP(0x7eaa20d1, 0x1271053e), WTCP(0x7ea2f9c2, 0x12a1e3a9), + WTCP(0x7e9bb494, 0x12d30b15), WTCP(0x7e9450f0, 0x13047b6c), + WTCP(0x7e8cce7f, 0x13363497), WTCP(0x7e852ce9, 0x1368367f), + WTCP(0x7e7d6bd6, 0x139a8109), WTCP(0x7e758aee, 0x13cd141b), + WTCP(0x7e6d89d9, 0x13ffef99), WTCP(0x7e65683d, 0x14331368), + WTCP(0x7e5d25c1, 0x14667f67), WTCP(0x7e54c20b, 0x149a3379), + WTCP(0x7e4c3cc3, 0x14ce2f7c), WTCP(0x7e43958e, 0x1502734f), + WTCP(0x7e3acc11, 0x1536fece), WTCP(0x7e31dff2, 0x156bd1d6), + WTCP(0x7e28d0d7, 0x15a0ec41), WTCP(0x7e1f9e63, 0x15d64de9), + WTCP(0x7e16483d, 0x160bf6a5), WTCP(0x7e0cce08, 0x1641e64c), + WTCP(0x7e032f6a, 0x16781cb4), WTCP(0x7df96c05, 0x16ae99b2), + WTCP(0x7def837e, 0x16e55d18), WTCP(0x7de57579, 0x171c66ba), + WTCP(0x7ddb419a, 0x1753b667), WTCP(0x7dd0e784, 0x178b4bef), + WTCP(0x7dc666d9, 0x17c32721), WTCP(0x7dbbbf3e, 0x17fb47ca), + WTCP(0x7db0f056, 0x1833adb5), WTCP(0x7da5f9c3, 0x186c58ae), + WTCP(0x7d9adb29, 0x18a5487d), WTCP(0x7d8f9429, 0x18de7cec), + WTCP(0x7d842467, 0x1917f5c1), WTCP(0x7d788b86, 0x1951b2c2), + WTCP(0x7d6cc927, 0x198bb3b4), WTCP(0x7d60dced, 0x19c5f85a), + WTCP(0x7d54c67c, 0x1a008077), WTCP(0x7d488574, 0x1a3b4bcb), + WTCP(0x7d3c1979, 0x1a765a17), WTCP(0x7d2f822d, 0x1ab1ab18), + WTCP(0x7d22bf32, 0x1aed3e8d), WTCP(0x7d15d02b, 0x1b291432), + WTCP(0x7d08b4ba, 0x1b652bc1), WTCP(0x7cfb6c82, 0x1ba184f5), + WTCP(0x7cedf725, 0x1bde1f86), WTCP(0x7ce05445, 0x1c1afb2c), + WTCP(0x7cd28386, 0x1c58179c), WTCP(0x7cc48489, 0x1c95748d), + WTCP(0x7cb656f3, 0x1cd311b1), WTCP(0x7ca7fa65, 0x1d10eebd), + WTCP(0x7c996e83, 0x1d4f0b60), WTCP(0x7c8ab2f0, 0x1d8d674c), + WTCP(0x7c7bc74f, 0x1dcc0230), WTCP(0x7c6cab44, 0x1e0adbbb), + WTCP(0x7c5d5e71, 0x1e49f398), WTCP(0x7c4de07c, 0x1e894973), + WTCP(0x7c3e3108, 0x1ec8dcf8), WTCP(0x7c2e4fb9, 0x1f08add0), + WTCP(0x7c1e3c34, 0x1f48bba3), WTCP(0x7c0df61d, 0x1f890618), + WTCP(0x7bfd7d18, 0x1fc98cd6), WTCP(0x7becd0cc, 0x200a4f80), + WTCP(0x7bdbf0dd, 0x204b4dbc), WTCP(0x7bcadcf1, 0x208c872c), + WTCP(0x7bb994ae, 0x20cdfb71), WTCP(0x7ba817b9, 0x210faa2c), + WTCP(0x7b9665bb, 0x215192fc), WTCP(0x7b847e58, 0x2193b57f), + WTCP(0x7b726139, 0x21d61153), WTCP(0x7b600e05, 0x2218a614), + WTCP(0x7b4d8463, 0x225b735d), WTCP(0x7b3ac3fc, 0x229e78c7), + WTCP(0x7b27cc79, 0x22e1b5eb), WTCP(0x7b149d82, 0x23252a62), + WTCP(0x7b0136c1, 0x2368d5c2), WTCP(0x7aed97df, 0x23acb7a0), + WTCP(0x7ad9c087, 0x23f0cf92), WTCP(0x7ac5b063, 0x24351d2a), + WTCP(0x7ab1671e, 0x24799ffc), WTCP(0x7a9ce464, 0x24be5799), + WTCP(0x7a8827e1, 0x25034391), WTCP(0x7a733142, 0x25486375), + WTCP(0x7a5e0033, 0x258db6d2), WTCP(0x7a489461, 0x25d33d35), + WTCP(0x7a32ed7c, 0x2618f62c), WTCP(0x7a1d0b31, 0x265ee143), + WTCP(0x7a06ed2f, 0x26a4fe02), WTCP(0x79f09327, 0x26eb4bf5), + WTCP(0x79d9fcc8, 0x2731caa3), WTCP(0x79c329c2, 0x27787995), + WTCP(0x79ac19c9, 0x27bf5850), WTCP(0x7994cc8d, 0x2806665c), + WTCP(0x797d41c1, 0x284da33c), WTCP(0x79657918, 0x28950e74), + WTCP(0x794d7247, 0x28dca788), WTCP(0x79352d01, 0x29246dfa), + WTCP(0x791ca8fc, 0x296c614a), WTCP(0x7903e5ee, 0x29b480f9), + WTCP(0x78eae38d, 0x29fccc87), WTCP(0x78d1a191, 0x2a454372), + WTCP(0x78b81fb1, 0x2a8de537), WTCP(0x789e5da6, 0x2ad6b155), + WTCP(0x78845b29, 0x2b1fa745), WTCP(0x786a17f5, 0x2b68c684), + WTCP(0x784f93c4, 0x2bb20e8c), WTCP(0x7834ce53, 0x2bfb7ed7), + WTCP(0x7819c75c, 0x2c4516dc), WTCP(0x77fe7e9e, 0x2c8ed615), + WTCP(0x77e2f3d7, 0x2cd8bbf7), WTCP(0x77c726c5, 0x2d22c7fa), + WTCP(0x77ab1728, 0x2d6cf993), WTCP(0x778ec4c0, 0x2db75037), + WTCP(0x77722f4e, 0x2e01cb59), WTCP(0x77555695, 0x2e4c6a6d), + WTCP(0x77383a58, 0x2e972ce6), WTCP(0x771ada5a, 0x2ee21235), + WTCP(0x76fd3660, 0x2f2d19cc), WTCP(0x76df4e30, 0x2f78431a), + WTCP(0x76c12190, 0x2fc38d91), WTCP(0x76a2b047, 0x300ef89d), + WTCP(0x7683fa1e, 0x305a83af), WTCP(0x7664fede, 0x30a62e34), + WTCP(0x7645be51, 0x30f1f798), WTCP(0x76263842, 0x313ddf49), + WTCP(0x76066c7e, 0x3189e4b1), WTCP(0x75e65ad1, 0x31d6073d), + WTCP(0x75c60309, 0x32224657), WTCP(0x75a564f6, 0x326ea168), + WTCP(0x75848067, 0x32bb17da), WTCP(0x7563552d, 0x3307a917), + WTCP(0x7541e31a, 0x33545486), WTCP(0x75202a02, 0x33a1198e), + WTCP(0x74fe29b8, 0x33edf798), WTCP(0x74dbe211, 0x343aee09), + WTCP(0x74b952e3, 0x3487fc48), WTCP(0x74967c06, 0x34d521bb), + WTCP(0x74735d51, 0x35225dc7), WTCP(0x744ff69f, 0x356fafcf), + WTCP(0x742c47c9, 0x35bd173a), WTCP(0x740850ab, 0x360a9369), + WTCP(0x73e41121, 0x365823c1), WTCP(0x73bf8909, 0x36a5c7a4), + WTCP(0x739ab842, 0x36f37e75), WTCP(0x73759eab, 0x37414796), + WTCP(0x73503c26, 0x378f2268), WTCP(0x732a9095, 0x37dd0e4c), + WTCP(0x73049bda, 0x382b0aa4), WTCP(0x72de5ddb, 0x387916d0), + WTCP(0x72b7d67d, 0x38c73230), WTCP(0x729105a6, 0x39155c24), + WTCP(0x7269eb3f, 0x3963940c), WTCP(0x72428730, 0x39b1d946), + WTCP(0x721ad964, 0x3a002b31), WTCP(0x71f2e1c5, 0x3a4e892c), + WTCP(0x71caa042, 0x3a9cf296), WTCP(0x71a214c7, 0x3aeb66cc), + WTCP(0x71793f43, 0x3b39e52c), WTCP(0x71501fa6, 0x3b886d14), + WTCP(0x7126b5e3, 0x3bd6fde1), WTCP(0x70fd01eb, 0x3c2596f1), + WTCP(0x70d303b2, 0x3c74379f), WTCP(0x70a8bb2e, 0x3cc2df49), + WTCP(0x707e2855, 0x3d118d4c), WTCP(0x70534b1e, 0x3d604103), + WTCP(0x70282381, 0x3daef9cc), WTCP(0x6ffcb17a, 0x3dfdb702), + WTCP(0x6fd0f504, 0x3e4c7800), WTCP(0x6fa4ee1a, 0x3e9b3c25), + WTCP(0x6f789cbb, 0x3eea02ca), WTCP(0x6f4c00e5, 0x3f38cb4b), + WTCP(0x6f1f1a9a, 0x3f879505), WTCP(0x6ef1e9da, 0x3fd65f53), + WTCP(0x6ec46ea9, 0x40252990), WTCP(0x6e96a90b, 0x4073f318), + WTCP(0x6e689905, 0x40c2bb46), WTCP(0x6e3a3e9d, 0x41118176), + WTCP(0x6e0b99dd, 0x41604504), WTCP(0x6ddcaacc, 0x41af054a), + WTCP(0x6dad7177, 0x41fdc1a5), WTCP(0x6d7dede8, 0x424c7970), + WTCP(0x6d4e202e, 0x429b2c06), WTCP(0x6d1e0855, 0x42e9d8c4), + WTCP(0x6ceda66f, 0x43387f05), WTCP(0x6cbcfa8d, 0x43871e26), + WTCP(0x6c8c04c0, 0x43d5b581), WTCP(0x6c5ac51d, 0x44244474), + WTCP(0x6c293bb8, 0x4472ca5a), WTCP(0x6bf768a8, 0x44c14690), + WTCP(0x6bc54c06, 0x450fb873), WTCP(0x6b92e5e9, 0x455e1f5f), + WTCP(0x6b60366c, 0x45ac7ab2), WTCP(0x6b2d3dab, 0x45fac9c8), + WTCP(0x6af9fbc2, 0x46490bff), WTCP(0x6ac670d1, 0x469740b5), + WTCP(0x6a929cf6, 0x46e56747), WTCP(0x6a5e8053, 0x47337f13), + WTCP(0x6a2a1b0a, 0x47818779), WTCP(0x69f56d3e, 0x47cf7fd6), + WTCP(0x69c07715, 0x481d678a), WTCP(0x698b38b4, 0x486b3df3), + WTCP(0x6955b243, 0x48b90272), WTCP(0x691fe3ec, 0x4906b466), + WTCP(0x68e9cdd8, 0x49545330), WTCP(0x68b37033, 0x49a1de30), + WTCP(0x687ccb29, 0x49ef54c8), WTCP(0x6845dee9, 0x4a3cb657), + WTCP(0x680eaba3, 0x4a8a0242), WTCP(0x67d73187, 0x4ad737e9), + WTCP(0x679f70c7, 0x4b2456af), WTCP(0x67676997, 0x4b715df7), + WTCP(0x672f1c2b, 0x4bbe4d25), WTCP(0x66f688ba, 0x4c0b239c), + WTCP(0x66bdaf7b, 0x4c57e0c2), WTCP(0x668490a6, 0x4ca483fa), + WTCP(0x664b2c76, 0x4cf10cac), WTCP(0x66118326, 0x4d3d7a3b), + WTCP(0x65d794f3, 0x4d89cc0f), WTCP(0x659d621a, 0x4dd6018f), + WTCP(0x6562eada, 0x4e221a22), WTCP(0x65282f74, 0x4e6e1530), + WTCP(0x64ed302b, 0x4eb9f222), WTCP(0x64b1ed40, 0x4f05b061), + WTCP(0x647666f8, 0x4f514f57), WTCP(0x643a9d99, 0x4f9cce6f), + WTCP(0x63fe916a, 0x4fe82d13), WTCP(0x63c242b2, 0x50336aaf), + WTCP(0x6385b1bc, 0x507e86b0), WTCP(0x6348ded1, 0x50c98082), + WTCP(0x630bca3f, 0x51145793), WTCP(0x62ce7451, 0x515f0b51), + WTCP(0x6290dd57, 0x51a99b2b), WTCP(0x625305a0, 0x51f40692), + WTCP(0x6214ed7d, 0x523e4cf5), WTCP(0x61d69541, 0x52886dc5), + WTCP(0x6197fd3e, 0x52d26875), WTCP(0x615925c9, 0x531c3c77), + WTCP(0x611a0f39, 0x5365e93e), WTCP(0x60dab9e3, 0x53af6e3e), + WTCP(0x609b2621, 0x53f8caed), WTCP(0x605b544c, 0x5441fec0), + WTCP(0x601b44bf, 0x548b092e), WTCP(0x5fdaf7d5, 0x54d3e9ae), + WTCP(0x5f9a6deb, 0x551c9fb7), WTCP(0x5f59a761, 0x55652ac3), + WTCP(0x5f18a494, 0x55ad8a4d), WTCP(0x5ed765e6, 0x55f5bdcd), + WTCP(0x5e95ebb8, 0x563dc4c1), WTCP(0x5e54366d, 0x56859ea3), + WTCP(0x5e12466a, 0x56cd4af3), WTCP(0x5dd01c13, 0x5714c92d), + WTCP(0x5d8db7cf, 0x575c18d0), WTCP(0x5d4b1a05, 0x57a3395e), + WTCP(0x5d08431e, 0x57ea2a56), WTCP(0x5cc53384, 0x5830eb3a), + WTCP(0x5c81eba0, 0x58777b8e), WTCP(0x5c3e6bdf, 0x58bddad5), + WTCP(0x5bfab4af, 0x59040893), WTCP(0x5bb6c67c, 0x594a044f), + WTCP(0x5b72a1b6, 0x598fcd8e), WTCP(0x5b2e46ce, 0x59d563d9), + WTCP(0x5ae9b634, 0x5a1ac6b8), WTCP(0x5aa4f05a, 0x5a5ff5b5), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow1024[] = { + WTCP(0x7fffffa4, 0x0009962f), WTCP(0x7fffff39, 0x000e16fb), + WTCP(0x7ffffebf, 0x0011ea65), WTCP(0x7ffffe34, 0x0015750e), + WTCP(0x7ffffd96, 0x0018dc74), WTCP(0x7ffffce5, 0x001c332e), + WTCP(0x7ffffc1f, 0x001f83f5), WTCP(0x7ffffb43, 0x0022d59a), + WTCP(0x7ffffa4f, 0x00262cc2), WTCP(0x7ffff942, 0x00298cc4), + WTCP(0x7ffff81a, 0x002cf81f), WTCP(0x7ffff6d6, 0x003070c4), + WTCP(0x7ffff573, 0x0033f840), WTCP(0x7ffff3f1, 0x00378fd9), + WTCP(0x7ffff24d, 0x003b38a1), WTCP(0x7ffff085, 0x003ef381), + WTCP(0x7fffee98, 0x0042c147), WTCP(0x7fffec83, 0x0046a2a8), + WTCP(0x7fffea44, 0x004a9847), WTCP(0x7fffe7d8, 0x004ea2b7), + WTCP(0x7fffe53f, 0x0052c283), WTCP(0x7fffe274, 0x0056f829), + WTCP(0x7fffdf76, 0x005b4422), WTCP(0x7fffdc43, 0x005fa6dd), + WTCP(0x7fffd8d6, 0x006420c8), WTCP(0x7fffd52f, 0x0068b249), + WTCP(0x7fffd149, 0x006d5bc4), WTCP(0x7fffcd22, 0x00721d9a), + WTCP(0x7fffc8b6, 0x0076f828), WTCP(0x7fffc404, 0x007bebca), + WTCP(0x7fffbf06, 0x0080f8d9), WTCP(0x7fffb9bb, 0x00861fae), + WTCP(0x7fffb41e, 0x008b609e), WTCP(0x7fffae2c, 0x0090bbff), + WTCP(0x7fffa7e1, 0x00963224), WTCP(0x7fffa13a, 0x009bc362), + WTCP(0x7fff9a32, 0x00a17009), WTCP(0x7fff92c5, 0x00a7386c), + WTCP(0x7fff8af0, 0x00ad1cdc), WTCP(0x7fff82ad, 0x00b31da8), + WTCP(0x7fff79f9, 0x00b93b21), WTCP(0x7fff70cf, 0x00bf7596), + WTCP(0x7fff672a, 0x00c5cd57), WTCP(0x7fff5d05, 0x00cc42b1), + WTCP(0x7fff525c, 0x00d2d5f3), WTCP(0x7fff4729, 0x00d9876c), + WTCP(0x7fff3b66, 0x00e05769), WTCP(0x7fff2f10, 0x00e74638), + WTCP(0x7fff221f, 0x00ee5426), WTCP(0x7fff148e, 0x00f58182), + WTCP(0x7fff0658, 0x00fcce97), WTCP(0x7ffef776, 0x01043bb3), + WTCP(0x7ffee7e2, 0x010bc923), WTCP(0x7ffed795, 0x01137733), + WTCP(0x7ffec68a, 0x011b4631), WTCP(0x7ffeb4ba, 0x01233669), + WTCP(0x7ffea21d, 0x012b4827), WTCP(0x7ffe8eac, 0x01337bb8), + WTCP(0x7ffe7a61, 0x013bd167), WTCP(0x7ffe6533, 0x01444982), + WTCP(0x7ffe4f1c, 0x014ce454), WTCP(0x7ffe3813, 0x0155a229), + WTCP(0x7ffe2011, 0x015e834d), WTCP(0x7ffe070d, 0x0167880c), + WTCP(0x7ffdecff, 0x0170b0b2), WTCP(0x7ffdd1df, 0x0179fd8b), + WTCP(0x7ffdb5a2, 0x01836ee1), WTCP(0x7ffd9842, 0x018d0500), + WTCP(0x7ffd79b3, 0x0196c035), WTCP(0x7ffd59ee, 0x01a0a0ca), + WTCP(0x7ffd38e8, 0x01aaa70a), WTCP(0x7ffd1697, 0x01b4d341), + WTCP(0x7ffcf2f2, 0x01bf25b9), WTCP(0x7ffccdee, 0x01c99ebd), + WTCP(0x7ffca780, 0x01d43e99), WTCP(0x7ffc7f9e, 0x01df0597), + WTCP(0x7ffc563d, 0x01e9f401), WTCP(0x7ffc2b51, 0x01f50a22), + WTCP(0x7ffbfecf, 0x02004844), WTCP(0x7ffbd0ab, 0x020baeb1), + WTCP(0x7ffba0da, 0x02173db4), WTCP(0x7ffb6f4f, 0x0222f596), + WTCP(0x7ffb3bfd, 0x022ed6a1), WTCP(0x7ffb06d8, 0x023ae11f), + WTCP(0x7ffacfd3, 0x02471558), WTCP(0x7ffa96e0, 0x02537397), + WTCP(0x7ffa5bf2, 0x025ffc25), WTCP(0x7ffa1efc, 0x026caf4a), + WTCP(0x7ff9dfee, 0x02798d4f), WTCP(0x7ff99ebb, 0x0286967c), + WTCP(0x7ff95b55, 0x0293cb1b), WTCP(0x7ff915ab, 0x02a12b72), + WTCP(0x7ff8cdaf, 0x02aeb7cb), WTCP(0x7ff88351, 0x02bc706d), + WTCP(0x7ff83682, 0x02ca559f), WTCP(0x7ff7e731, 0x02d867a9), + WTCP(0x7ff7954e, 0x02e6a6d2), WTCP(0x7ff740c8, 0x02f51361), + WTCP(0x7ff6e98e, 0x0303ad9c), WTCP(0x7ff68f8f, 0x031275ca), + WTCP(0x7ff632ba, 0x03216c30), WTCP(0x7ff5d2fb, 0x03309116), + WTCP(0x7ff57042, 0x033fe4bf), WTCP(0x7ff50a7a, 0x034f6773), + WTCP(0x7ff4a192, 0x035f1975), WTCP(0x7ff43576, 0x036efb0a), + WTCP(0x7ff3c612, 0x037f0c78), WTCP(0x7ff35353, 0x038f4e02), + WTCP(0x7ff2dd24, 0x039fbfeb), WTCP(0x7ff26370, 0x03b06279), + WTCP(0x7ff1e623, 0x03c135ed), WTCP(0x7ff16527, 0x03d23a8b), + WTCP(0x7ff0e067, 0x03e37095), WTCP(0x7ff057cc, 0x03f4d84e), + WTCP(0x7fefcb40, 0x040671f7), WTCP(0x7fef3aad, 0x04183dd3), + WTCP(0x7feea5fa, 0x042a3c22), WTCP(0x7fee0d11, 0x043c6d25), + WTCP(0x7fed6fda, 0x044ed11d), WTCP(0x7fecce3d, 0x04616849), + WTCP(0x7fec2821, 0x047432eb), WTCP(0x7feb7d6c, 0x04873140), + WTCP(0x7feace07, 0x049a6388), WTCP(0x7fea19d6, 0x04adca01), + WTCP(0x7fe960c0, 0x04c164ea), WTCP(0x7fe8a2aa, 0x04d53481), + WTCP(0x7fe7df79, 0x04e93902), WTCP(0x7fe71712, 0x04fd72aa), + WTCP(0x7fe6495a, 0x0511e1b6), WTCP(0x7fe57634, 0x05268663), + WTCP(0x7fe49d83, 0x053b60eb), WTCP(0x7fe3bf2b, 0x05507189), + WTCP(0x7fe2db0f, 0x0565b879), WTCP(0x7fe1f110, 0x057b35f4), + WTCP(0x7fe10111, 0x0590ea35), WTCP(0x7fe00af3, 0x05a6d574), + WTCP(0x7fdf0e97, 0x05bcf7ea), WTCP(0x7fde0bdd, 0x05d351cf), + WTCP(0x7fdd02a6, 0x05e9e35c), WTCP(0x7fdbf2d2, 0x0600acc8), + WTCP(0x7fdadc40, 0x0617ae48), WTCP(0x7fd9becf, 0x062ee814), + WTCP(0x7fd89a5e, 0x06465a62), WTCP(0x7fd76eca, 0x065e0565), + WTCP(0x7fd63bf1, 0x0675e954), WTCP(0x7fd501b0, 0x068e0662), + WTCP(0x7fd3bfe4, 0x06a65cc3), WTCP(0x7fd2766a, 0x06beecaa), + WTCP(0x7fd1251e, 0x06d7b648), WTCP(0x7fcfcbda, 0x06f0b9d1), + WTCP(0x7fce6a7a, 0x0709f775), WTCP(0x7fcd00d8, 0x07236f65), + WTCP(0x7fcb8ecf, 0x073d21d2), WTCP(0x7fca1439, 0x07570eea), + WTCP(0x7fc890ed, 0x077136dd), WTCP(0x7fc704c7, 0x078b99da), + WTCP(0x7fc56f9d, 0x07a6380d), WTCP(0x7fc3d147, 0x07c111a4), + WTCP(0x7fc2299e, 0x07dc26cc), WTCP(0x7fc07878, 0x07f777b1), + WTCP(0x7fbebdac, 0x0813047d), WTCP(0x7fbcf90f, 0x082ecd5b), + WTCP(0x7fbb2a78, 0x084ad276), WTCP(0x7fb951bc, 0x086713f7), + WTCP(0x7fb76eaf, 0x08839206), WTCP(0x7fb58126, 0x08a04ccb), + WTCP(0x7fb388f4, 0x08bd446e), WTCP(0x7fb185ee, 0x08da7915), + WTCP(0x7faf77e5, 0x08f7eae7), WTCP(0x7fad5ead, 0x09159a09), + WTCP(0x7fab3a17, 0x0933869f), WTCP(0x7fa909f6, 0x0951b0cd), + WTCP(0x7fa6ce1a, 0x097018b7), WTCP(0x7fa48653, 0x098ebe7f), + WTCP(0x7fa23273, 0x09ada248), WTCP(0x7f9fd249, 0x09ccc431), + WTCP(0x7f9d65a4, 0x09ec245b), WTCP(0x7f9aec53, 0x0a0bc2e7), + WTCP(0x7f986625, 0x0a2b9ff3), WTCP(0x7f95d2e7, 0x0a4bbb9e), + WTCP(0x7f933267, 0x0a6c1604), WTCP(0x7f908472, 0x0a8caf43), + WTCP(0x7f8dc8d5, 0x0aad8776), WTCP(0x7f8aff5c, 0x0ace9eb9), + WTCP(0x7f8827d3, 0x0aeff526), WTCP(0x7f854204, 0x0b118ad8), + WTCP(0x7f824dbb, 0x0b335fe6), WTCP(0x7f7f4ac3, 0x0b557469), + WTCP(0x7f7c38e4, 0x0b77c879), WTCP(0x7f7917e9, 0x0b9a5c2b), + WTCP(0x7f75e79b, 0x0bbd2f97), WTCP(0x7f72a7c3, 0x0be042d0), + WTCP(0x7f6f5828, 0x0c0395ec), WTCP(0x7f6bf892, 0x0c2728fd), + WTCP(0x7f6888c9, 0x0c4afc16), WTCP(0x7f650894, 0x0c6f0f4a), + WTCP(0x7f6177b9, 0x0c9362a8), WTCP(0x7f5dd5ff, 0x0cb7f642), + WTCP(0x7f5a232a, 0x0cdcca26), WTCP(0x7f565f00, 0x0d01de63), + WTCP(0x7f528947, 0x0d273307), WTCP(0x7f4ea1c2, 0x0d4cc81f), + WTCP(0x7f4aa835, 0x0d729db7), WTCP(0x7f469c65, 0x0d98b3da), + WTCP(0x7f427e13, 0x0dbf0a92), WTCP(0x7f3e4d04, 0x0de5a1e9), + WTCP(0x7f3a08f9, 0x0e0c79e7), WTCP(0x7f35b1b4, 0x0e339295), + WTCP(0x7f3146f8, 0x0e5aebfa), WTCP(0x7f2cc884, 0x0e82861a), + WTCP(0x7f28361b, 0x0eaa60fd), WTCP(0x7f238f7c, 0x0ed27ca5), + WTCP(0x7f1ed467, 0x0efad917), WTCP(0x7f1a049d, 0x0f237656), + WTCP(0x7f151fdc, 0x0f4c5462), WTCP(0x7f1025e3, 0x0f75733d), + WTCP(0x7f0b1672, 0x0f9ed2e6), WTCP(0x7f05f146, 0x0fc8735e), + WTCP(0x7f00b61d, 0x0ff254a1), WTCP(0x7efb64b4, 0x101c76ae), + WTCP(0x7ef5fcca, 0x1046d981), WTCP(0x7ef07e19, 0x10717d15), + WTCP(0x7eeae860, 0x109c6165), WTCP(0x7ee53b5b, 0x10c7866a), + WTCP(0x7edf76c4, 0x10f2ec1e), WTCP(0x7ed99a58, 0x111e9279), + WTCP(0x7ed3a5d1, 0x114a7971), WTCP(0x7ecd98eb, 0x1176a0fc), + WTCP(0x7ec77360, 0x11a30910), WTCP(0x7ec134eb, 0x11cfb1a1), + WTCP(0x7ebadd44, 0x11fc9aa2), WTCP(0x7eb46c27, 0x1229c406), + WTCP(0x7eade14c, 0x12572dbf), WTCP(0x7ea73c6c, 0x1284d7bc), + WTCP(0x7ea07d41, 0x12b2c1ed), WTCP(0x7e99a382, 0x12e0ec42), + WTCP(0x7e92aee7, 0x130f56a8), WTCP(0x7e8b9f2a, 0x133e010b), + WTCP(0x7e847402, 0x136ceb59), WTCP(0x7e7d2d25, 0x139c157b), + WTCP(0x7e75ca4c, 0x13cb7f5d), WTCP(0x7e6e4b2d, 0x13fb28e6), + WTCP(0x7e66af7f, 0x142b1200), WTCP(0x7e5ef6f8, 0x145b3a92), + WTCP(0x7e572150, 0x148ba281), WTCP(0x7e4f2e3b, 0x14bc49b4), + WTCP(0x7e471d70, 0x14ed300f), WTCP(0x7e3eeea5, 0x151e5575), + WTCP(0x7e36a18e, 0x154fb9c9), WTCP(0x7e2e35e2, 0x15815ced), + WTCP(0x7e25ab56, 0x15b33ec1), WTCP(0x7e1d019e, 0x15e55f25), + WTCP(0x7e14386e, 0x1617bdf9), WTCP(0x7e0b4f7d, 0x164a5b19), + WTCP(0x7e02467e, 0x167d3662), WTCP(0x7df91d25, 0x16b04fb2), + WTCP(0x7defd327, 0x16e3a6e2), WTCP(0x7de66837, 0x17173bce), + WTCP(0x7ddcdc0a, 0x174b0e4d), WTCP(0x7dd32e53, 0x177f1e39), + WTCP(0x7dc95ec6, 0x17b36b69), WTCP(0x7dbf6d17, 0x17e7f5b3), + WTCP(0x7db558f9, 0x181cbcec), WTCP(0x7dab221f, 0x1851c0e9), + WTCP(0x7da0c83c, 0x1887017d), WTCP(0x7d964b05, 0x18bc7e7c), + WTCP(0x7d8baa2b, 0x18f237b6), WTCP(0x7d80e563, 0x19282cfd), + WTCP(0x7d75fc5e, 0x195e5e20), WTCP(0x7d6aeed0, 0x1994caee), + WTCP(0x7d5fbc6d, 0x19cb7335), WTCP(0x7d5464e6, 0x1a0256c2), + WTCP(0x7d48e7ef, 0x1a397561), WTCP(0x7d3d453b, 0x1a70cede), + WTCP(0x7d317c7c, 0x1aa86301), WTCP(0x7d258d65, 0x1ae03195), + WTCP(0x7d1977aa, 0x1b183a63), WTCP(0x7d0d3afc, 0x1b507d30), + WTCP(0x7d00d710, 0x1b88f9c5), WTCP(0x7cf44b97, 0x1bc1afe6), + WTCP(0x7ce79846, 0x1bfa9f58), WTCP(0x7cdabcce, 0x1c33c7e0), + WTCP(0x7ccdb8e4, 0x1c6d293f), WTCP(0x7cc08c39, 0x1ca6c337), + WTCP(0x7cb33682, 0x1ce0958a), WTCP(0x7ca5b772, 0x1d1a9ff8), + WTCP(0x7c980ebd, 0x1d54e240), WTCP(0x7c8a3c14, 0x1d8f5c21), + WTCP(0x7c7c3f2e, 0x1dca0d56), WTCP(0x7c6e17bc, 0x1e04f59f), + WTCP(0x7c5fc573, 0x1e4014b4), WTCP(0x7c514807, 0x1e7b6a53), + WTCP(0x7c429f2c, 0x1eb6f633), WTCP(0x7c33ca96, 0x1ef2b80f), + WTCP(0x7c24c9fa, 0x1f2eaf9e), WTCP(0x7c159d0d, 0x1f6adc98), + WTCP(0x7c064383, 0x1fa73eb2), WTCP(0x7bf6bd11, 0x1fe3d5a3), + WTCP(0x7be7096c, 0x2020a11e), WTCP(0x7bd7284a, 0x205da0d8), + WTCP(0x7bc71960, 0x209ad483), WTCP(0x7bb6dc65, 0x20d83bd1), + WTCP(0x7ba6710d, 0x2115d674), WTCP(0x7b95d710, 0x2153a41b), + WTCP(0x7b850e24, 0x2191a476), WTCP(0x7b7415ff, 0x21cfd734), + WTCP(0x7b62ee59, 0x220e3c02), WTCP(0x7b5196e9, 0x224cd28d), + WTCP(0x7b400f67, 0x228b9a82), WTCP(0x7b2e578a, 0x22ca938a), + WTCP(0x7b1c6f0b, 0x2309bd52), WTCP(0x7b0a55a1, 0x23491783), + WTCP(0x7af80b07, 0x2388a1c4), WTCP(0x7ae58ef5, 0x23c85bbf), + WTCP(0x7ad2e124, 0x2408451a), WTCP(0x7ac0014e, 0x24485d7c), + WTCP(0x7aacef2e, 0x2488a48a), WTCP(0x7a99aa7e, 0x24c919e9), + WTCP(0x7a8632f8, 0x2509bd3d), WTCP(0x7a728858, 0x254a8e29), + WTCP(0x7a5eaa5a, 0x258b8c50), WTCP(0x7a4a98b9, 0x25ccb753), + WTCP(0x7a365333, 0x260e0ed3), WTCP(0x7a21d983, 0x264f9271), + WTCP(0x7a0d2b68, 0x269141cb), WTCP(0x79f8489e, 0x26d31c80), + WTCP(0x79e330e4, 0x2715222f), WTCP(0x79cde3f8, 0x27575273), + WTCP(0x79b8619a, 0x2799acea), WTCP(0x79a2a989, 0x27dc3130), + WTCP(0x798cbb85, 0x281ededf), WTCP(0x7976974e, 0x2861b591), + WTCP(0x79603ca5, 0x28a4b4e0), WTCP(0x7949ab4c, 0x28e7dc65), + WTCP(0x7932e304, 0x292b2bb8), WTCP(0x791be390, 0x296ea270), + WTCP(0x7904acb3, 0x29b24024), WTCP(0x78ed3e30, 0x29f6046b), + WTCP(0x78d597cc, 0x2a39eed8), WTCP(0x78bdb94a, 0x2a7dff02), + WTCP(0x78a5a270, 0x2ac2347c), WTCP(0x788d5304, 0x2b068eda), + WTCP(0x7874cacb, 0x2b4b0dae), WTCP(0x785c098d, 0x2b8fb08a), + WTCP(0x78430f11, 0x2bd47700), WTCP(0x7829db1f, 0x2c1960a1), + WTCP(0x78106d7f, 0x2c5e6cfd), WTCP(0x77f6c5fb, 0x2ca39ba3), + WTCP(0x77dce45c, 0x2ce8ec23), WTCP(0x77c2c86e, 0x2d2e5e0b), + WTCP(0x77a871fa, 0x2d73f0e8), WTCP(0x778de0cd, 0x2db9a449), + WTCP(0x777314b2, 0x2dff77b8), WTCP(0x77580d78, 0x2e456ac4), + WTCP(0x773ccaeb, 0x2e8b7cf6), WTCP(0x77214cdb, 0x2ed1addb), + WTCP(0x77059315, 0x2f17fcfb), WTCP(0x76e99d69, 0x2f5e69e2), + WTCP(0x76cd6ba9, 0x2fa4f419), WTCP(0x76b0fda4, 0x2feb9b27), + WTCP(0x7694532e, 0x30325e96), WTCP(0x76776c17, 0x30793dee), + WTCP(0x765a4834, 0x30c038b5), WTCP(0x763ce759, 0x31074e72), + WTCP(0x761f4959, 0x314e7eab), WTCP(0x76016e0b, 0x3195c8e6), + WTCP(0x75e35545, 0x31dd2ca9), WTCP(0x75c4fedc, 0x3224a979), + WTCP(0x75a66aab, 0x326c3ed8), WTCP(0x75879887, 0x32b3ec4d), + WTCP(0x7568884b, 0x32fbb159), WTCP(0x754939d1, 0x33438d81), + WTCP(0x7529acf4, 0x338b8045), WTCP(0x7509e18e, 0x33d3892a), + WTCP(0x74e9d77d, 0x341ba7b1), WTCP(0x74c98e9e, 0x3463db5a), + WTCP(0x74a906cd, 0x34ac23a7), WTCP(0x74883fec, 0x34f48019), + WTCP(0x746739d8, 0x353cf02f), WTCP(0x7445f472, 0x3585736a), + WTCP(0x74246f9c, 0x35ce0949), WTCP(0x7402ab37, 0x3616b14c), + WTCP(0x73e0a727, 0x365f6af0), WTCP(0x73be6350, 0x36a835b5), + WTCP(0x739bdf95, 0x36f11118), WTCP(0x73791bdd, 0x3739fc98), + WTCP(0x7356180e, 0x3782f7b2), WTCP(0x7332d410, 0x37cc01e3), + WTCP(0x730f4fc9, 0x38151aa8), WTCP(0x72eb8b24, 0x385e417e), + WTCP(0x72c7860a, 0x38a775e1), WTCP(0x72a34066, 0x38f0b74d), + WTCP(0x727eba24, 0x393a053e), WTCP(0x7259f331, 0x39835f30), + WTCP(0x7234eb79, 0x39ccc49e), WTCP(0x720fa2eb, 0x3a163503), + WTCP(0x71ea1977, 0x3a5fafda), WTCP(0x71c44f0c, 0x3aa9349e), + WTCP(0x719e439d, 0x3af2c2ca), WTCP(0x7177f71a, 0x3b3c59d7), + WTCP(0x71516978, 0x3b85f940), WTCP(0x712a9aaa, 0x3bcfa07e), + WTCP(0x71038aa4, 0x3c194f0d), WTCP(0x70dc395e, 0x3c630464), + WTCP(0x70b4a6cd, 0x3cacbfff), WTCP(0x708cd2e9, 0x3cf68155), + WTCP(0x7064bdab, 0x3d4047e1), WTCP(0x703c670d, 0x3d8a131c), + WTCP(0x7013cf0a, 0x3dd3e27e), WTCP(0x6feaf59c, 0x3e1db580), + WTCP(0x6fc1dac1, 0x3e678b9b), WTCP(0x6f987e76, 0x3eb16449), + WTCP(0x6f6ee0b9, 0x3efb3f01), WTCP(0x6f45018b, 0x3f451b3d), + WTCP(0x6f1ae0eb, 0x3f8ef874), WTCP(0x6ef07edb, 0x3fd8d620), + WTCP(0x6ec5db5d, 0x4022b3b9), WTCP(0x6e9af675, 0x406c90b7), + WTCP(0x6e6fd027, 0x40b66c93), WTCP(0x6e446879, 0x410046c5), + WTCP(0x6e18bf71, 0x414a1ec6), WTCP(0x6decd517, 0x4193f40d), + WTCP(0x6dc0a972, 0x41ddc615), WTCP(0x6d943c8d, 0x42279455), + WTCP(0x6d678e71, 0x42715e45), WTCP(0x6d3a9f2a, 0x42bb235f), + WTCP(0x6d0d6ec5, 0x4304e31a), WTCP(0x6cdffd4f, 0x434e9cf1), + WTCP(0x6cb24ad6, 0x4398505b), WTCP(0x6c84576b, 0x43e1fcd1), + WTCP(0x6c56231c, 0x442ba1cd), WTCP(0x6c27adfd, 0x44753ec7), + WTCP(0x6bf8f81e, 0x44bed33a), WTCP(0x6bca0195, 0x45085e9d), + WTCP(0x6b9aca75, 0x4551e06b), WTCP(0x6b6b52d5, 0x459b581e), + WTCP(0x6b3b9ac9, 0x45e4c52f), WTCP(0x6b0ba26b, 0x462e2717), + WTCP(0x6adb69d3, 0x46777d52), WTCP(0x6aaaf11b, 0x46c0c75a), + WTCP(0x6a7a385c, 0x470a04a9), WTCP(0x6a493fb3, 0x475334b9), + WTCP(0x6a18073d, 0x479c5707), WTCP(0x69e68f17, 0x47e56b0c), + WTCP(0x69b4d761, 0x482e7045), WTCP(0x6982e039, 0x4877662c), + WTCP(0x6950a9c0, 0x48c04c3f), WTCP(0x691e341a, 0x490921f8), + WTCP(0x68eb7f67, 0x4951e6d5), WTCP(0x68b88bcd, 0x499a9a51), + WTCP(0x68855970, 0x49e33beb), WTCP(0x6851e875, 0x4a2bcb1f), + WTCP(0x681e3905, 0x4a74476b), WTCP(0x67ea4b47, 0x4abcb04c), + WTCP(0x67b61f63, 0x4b050541), WTCP(0x6781b585, 0x4b4d45c9), + WTCP(0x674d0dd6, 0x4b957162), WTCP(0x67182883, 0x4bdd878c), + WTCP(0x66e305b8, 0x4c2587c6), WTCP(0x66ada5a5, 0x4c6d7190), + WTCP(0x66780878, 0x4cb5446a), WTCP(0x66422e60, 0x4cfcffd5), + WTCP(0x660c1790, 0x4d44a353), WTCP(0x65d5c439, 0x4d8c2e64), + WTCP(0x659f348e, 0x4dd3a08c), WTCP(0x656868c3, 0x4e1af94b), + WTCP(0x6531610d, 0x4e623825), WTCP(0x64fa1da3, 0x4ea95c9d), + WTCP(0x64c29ebb, 0x4ef06637), WTCP(0x648ae48d, 0x4f375477), + WTCP(0x6452ef53, 0x4f7e26e1), WTCP(0x641abf46, 0x4fc4dcfb), + WTCP(0x63e254a2, 0x500b7649), WTCP(0x63a9afa2, 0x5051f253), + WTCP(0x6370d083, 0x5098509f), WTCP(0x6337b784, 0x50de90b3), + WTCP(0x62fe64e3, 0x5124b218), WTCP(0x62c4d8e0, 0x516ab455), + WTCP(0x628b13bc, 0x51b096f3), WTCP(0x625115b8, 0x51f6597b), + WTCP(0x6216df18, 0x523bfb78), WTCP(0x61dc701f, 0x52817c72), + WTCP(0x61a1c912, 0x52c6dbf5), WTCP(0x6166ea36, 0x530c198d), + WTCP(0x612bd3d2, 0x535134c5), WTCP(0x60f0862d, 0x53962d2a), + WTCP(0x60b50190, 0x53db024a), WTCP(0x60794644, 0x541fb3b1), + WTCP(0x603d5494, 0x546440ef), WTCP(0x60012cca, 0x54a8a992), + WTCP(0x5fc4cf33, 0x54eced2b), WTCP(0x5f883c1c, 0x55310b48), + WTCP(0x5f4b73d2, 0x5575037c), WTCP(0x5f0e76a5, 0x55b8d558), + WTCP(0x5ed144e5, 0x55fc806f), WTCP(0x5e93dee1, 0x56400452), + WTCP(0x5e5644ec, 0x56836096), WTCP(0x5e187757, 0x56c694cf), + WTCP(0x5dda7677, 0x5709a092), WTCP(0x5d9c429f, 0x574c8374), + WTCP(0x5d5ddc24, 0x578f3d0d), WTCP(0x5d1f435d, 0x57d1ccf2), + WTCP(0x5ce078a0, 0x581432bd), WTCP(0x5ca17c45, 0x58566e04), + WTCP(0x5c624ea4, 0x58987e63), WTCP(0x5c22f016, 0x58da6372), + WTCP(0x5be360f6, 0x591c1ccc), WTCP(0x5ba3a19f, 0x595daa0d), + WTCP(0x5b63b26c, 0x599f0ad1), WTCP(0x5b2393ba, 0x59e03eb6), + WTCP(0x5ae345e7, 0x5a214558), WTCP(0x5aa2c951, 0x5a621e56), +}; + +/** + * \brief Helper table containing the length, rasterand shape mapping to + * individual window slope tables. [0: sine ][0: radix2 raster + * ][ceil(log2(length)) length 4 .. 1024 ] [1: 10ms raster + * ][ceil(log2(length)) length 3.25 .. 960 ] [2: 3/4 of radix 2 + * raster][ceil(log2(length)) length 3 .. 768 ] [1: KBD ][0: + * radix2 raster ][ceil(log2(length)) length 128 .. 1024 ] [1: 10ms + * raster ][ceil(log2(length)) length 120 .. 960 ] [2: + * 3/4 of radix 2 raster][ceil(log2(length)) length 96 .. 768 ] + */ +const FIXP_WTP *const windowSlopes[2][4][9] = { + { /* Sine */ + {/* Radix 2 */ + NULL, SineWindow8, SineWindow16, SineWindow32, SineWindow64, + SineWindow128, SineWindow256, SineWindow512, SineWindow1024}, + { /* 10ms raster */ + NULL, /* 3.25 */ + NULL, /* 7.5 */ + NULL, NULL, NULL, SineWindow120, SineWindow240, SineWindow480, + SineWindow960}, + { /* 3/4 radix2 raster */ + NULL, /* 3 */ + NULL, /* 6 */ + SineWindow12, SineWindow24, SineWindow48, SineWindow96, SineWindow192, + SineWindow384, SineWindow768}, + { + /* 3/4 radix2 raster */ + NULL, + NULL, /* 3 */ + NULL, /* 6 */ + SineWindow20, + SineWindow40, + NULL, + SineWindow160, + NULL, + NULL, + }}, + { /* KBD */ + {/* Radix 2 */ + NULL, KBDWindow128, KBDWindow256, SineWindow512, KBDWindow1024}, + {/* 10ms raster */ + NULL, KBDWindow120, NULL, SineWindow480, KBDWindow960}, + {/* 3/4 radix2 raster */ + NULL, KBDWindow96, + SineWindow192, /* This entry might be accessed for erred bit streams. */ + NULL, KBDWindow768}, + {NULL, NULL, NULL, NULL}}}; + +const FIXP_WTP *FDKgetWindowSlope(int length, int shape) { + const FIXP_WTP *w = NULL; + int raster, ld2_length; + + /* Get ld2 of length - 2 + 1 + -2: because first table entry is window of size 4 + +1: because we already include +1 because of ceil(log2(length)) */ + ld2_length = DFRACT_BITS - 1 - fNormz((FIXP_DBL)length) - 1; + + /* Extract sort of "eigenvalue" (the 4 left most bits) of length. */ + switch ((length) >> (ld2_length - 2)) { + case 0x8: /* radix 2 */ + raster = 0; + ld2_length--; /* revert + 1 because of ceil(log2(length)) from above. */ + break; + case 0xf: /* 10 ms */ + raster = 1; + break; + case 0xc: /* 3/4 of radix 2 */ + raster = 2; + break; + default: + raster = 0; + break; + } + + /* The table for sine windows (shape == 0) is 4 entries longer. */ + if (shape == 1) { + ld2_length -= 4; + } + + /* Look up table */ + w = windowSlopes[shape & 1][raster][ld2_length]; + + FDK_ASSERT(w != NULL); + + return w; +} + + /* + * QMF filter and twiddle tables + */ + +#ifdef QMF_COEFF_16BIT +#define QFC(x) FX_DBL2FXCONST_SGL(x) +#define QTCFL(x) FL2FXCONST_SGL(x) +#define QTC(x) FX_DBL2FXCONST_SGL(x) +#else +#define QFC(x) ((FIXP_DBL)(x)) +#define QTCFL(x) FL2FXCONST_DBL(x) +#define QTC(x) ((FIXP_DBL)(x)) +#endif /* ARCH_PREFER_MULT_32x16 */ + +/*! + \name QMF + \brief QMF-Table + 64 channels, N = 640, optimized by PE 010516 + + The coeffs are rearranged compared with the reference in the following + way, exploiting symmetry : + sbr_qmf_64[5] = p_64_640_qmf[0]; + sbr_qmf_64[6] = p_64_640_qmf[128]; + sbr_qmf_64[7] = p_64_640_qmf[256]; + sbr_qmf_64[8] = p_64_640_qmf[384]; + sbr_qmf_64[9] = p_64_640_qmf[512]; + + sbr_qmf_64[10] = p_64_640_qmf[1]; + sbr_qmf_64[11] = p_64_640_qmf[129]; + sbr_qmf_64[12] = p_64_640_qmf[257]; + sbr_qmf_64[13] = p_64_640_qmf[385]; + sbr_qmf_64[14] = p_64_640_qmf[513]; + . + . + . + sbr_qmf_64_640_qmf[315] = p_64_640_qmf[62]; + sbr_qmf_64_640_qmf[316] = p_64_640_qmf[190]; + sbr_qmf_64_640_qmf[317] = p_64_640_qmf[318]; + sbr_qmf_64_640_qmf[318] = p_64_640_qmf[446]; + sbr_qmf_64_640_qmf[319] = p_64_640_qmf[574]; + + sbr_qmf_64_640_qmf[320] = p_64_640_qmf[63]; + sbr_qmf_64_640_qmf[321] = p_64_640_qmf[191]; + sbr_qmf_64_640_qmf[322] = p_64_640_qmf[319]; + sbr_qmf_64_640_qmf[323] = p_64_640_qmf[447]; + sbr_qmf_64_640_qmf[324] = p_64_640_qmf[575]; + + sbr_qmf_64_640_qmf[319] = p_64_640_qmf[64]; + sbr_qmf_64_640_qmf[318] = p_64_640_qmf[192]; + sbr_qmf_64_640_qmf[317] = p_64_640_qmf[320]; + sbr_qmf_64_640_qmf[316] = p_64_640_qmf[448]; + sbr_qmf_64_640_qmf[315] = p_64_640_qmf[576]; + + sbr_qmf_64_640_qmf[314] = p_64_640_qmf[65]; + sbr_qmf_64_640_qmf[313] = p_64_640_qmf[193]; + sbr_qmf_64_640_qmf[312] = p_64_640_qmf[321]; + sbr_qmf_64_640_qmf[311] = p_64_640_qmf[449]; + sbr_qmf_64_640_qmf[310] = p_64_640_qmf[577]; + . + . + . + sbr_qmf_64[9] = p_64_640_qmf[126] + sbr_qmf_64[8] = p_64_640_qmf[254]; + sbr_qmf_64[7] = p_64_640_qmf[382]; + sbr_qmf_64[6] = p_64_640_qmf[510]; + sbr_qmf_64[5] = p_64_640_qmf[638]; + + sbr_qmf_64[4] = p_64_640_qmf[127] + sbr_qmf_64[3] = p_64_640_qmf[255]; + sbr_qmf_64[2] = p_64_640_qmf[383]; + sbr_qmf_64[1] = p_64_640_qmf[511]; + sbr_qmf_64[0] = p_64_640_qmf[639]; + + Max sum of all FIR filter absolute coefficients is: 0x7FF5B201 + thus, the filter output is not required to be scaled. + + \showinitializer +*/ +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_PFT qmf_pfilt120[] = { + QFC(0x00000000), QFC(0x01b2e41d), QFC(0x2e3a7532), QFC(0xd1c58ace), + QFC(0xfe4d1be3), QFC(0xffefcdb5), QFC(0x02828e13), QFC(0x35eecfd1), + QFC(0xd94e53e3), QFC(0xfefdfe42), QFC(0xffec30b0), QFC(0x036b8e20), + QFC(0x3daa7c5c), QFC(0xe08b3fa6), QFC(0xff8f33fc), QFC(0xffe88ba8), + QFC(0x04694101), QFC(0x4547daeb), QFC(0xe75f8bb7), QFC(0x0000e790), + QFC(0xffe69150), QFC(0x057341bc), QFC(0x4c9ef50f), QFC(0xedb0fdbd), + QFC(0x00549c76), QFC(0xffe6db43), QFC(0x067ef951), QFC(0x5389d1bb), + QFC(0xf36dbfe6), QFC(0x008cbe92), QFC(0xffea353a), QFC(0x077fedb3), + QFC(0x59e2f69e), QFC(0xf887507c), QFC(0x00acbd2f), QFC(0xfff176e1), + QFC(0x086685a4), QFC(0x5f845914), QFC(0xfcf2b6c8), QFC(0x00b881db), + QFC(0xfffd1253), QFC(0x09233c49), QFC(0x64504658), QFC(0x00adb69e), + QFC(0x00b4790a), QFC(0x000d31b5), QFC(0x09a3e163), QFC(0x682b39a4), + QFC(0x03b8f8dc), QFC(0x00a520bb), QFC(0x0021e26b), QFC(0x09d536b4), + QFC(0x6afb0c80), QFC(0x06186566), QFC(0x008db1f0), QFC(0x003a81c0), + QFC(0x09a505f2), QFC(0x6cb28145), QFC(0x07d6e67c), QFC(0x00728512), + QFC(0x0055dba1), QFC(0x09015651), QFC(0x6d474e1d), QFC(0x09015651), + QFC(0x0055dba1), QFC(0xfe4d1be3), QFC(0xd1c58ace), QFC(0x2e3a7532), + QFC(0x01b2e41d), QFC(0x00000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_PFT qmf_pfilt200[] = { + QFC(0x00000000), QFC(0x01b2e41d), QFC(0x2e3a7532), QFC(0xd1c58ace), + QFC(0xfe4d1be3), QFC(0xffefd5d9), QFC(0x022c39a4), QFC(0x32d6e6f6), + QFC(0xd652421f), QFC(0xfebafd64), QFC(0xffef3d2e), QFC(0x02af2a39), + QFC(0x377b44a6), QFC(0xdac7ff47), QFC(0xff1d9e1f), QFC(0xffed03e9), + QFC(0x033b07ff), QFC(0x3c1fc4e4), QFC(0xdf2029d5), QFC(0xff74a37e), + QFC(0xffeab7cc), QFC(0x03cf3ade), QFC(0x40bc12f6), QFC(0xe3546cf8), + QFC(0xffc070af), QFC(0xffe88ba8), QFC(0x04694101), QFC(0x4547daeb), + QFC(0xe75f8bb7), QFC(0x0000e790), QFC(0xffe7546d), QFC(0x050826e6), + QFC(0x49ba0a48), QFC(0xeb3ac63a), QFC(0x0036aa5d), QFC(0xffe6665c), + QFC(0x05a92d73), QFC(0x4e0b0602), QFC(0xeee323fd), QFC(0x0061fdf9), + QFC(0xffe6858d), QFC(0x0649e26b), QFC(0x523225cf), QFC(0xf2549ca7), + QFC(0x00838276), QFC(0xffe7e0bd), QFC(0x06e7cba4), QFC(0x5627597c), + QFC(0xf58c23ae), QFC(0x009c49df), QFC(0xffea353a), QFC(0x077fedb3), + QFC(0x59e2f69e), QFC(0xf887507c), QFC(0x00acbd2f), QFC(0xffee0a64), + QFC(0x080e83ac), QFC(0x5d5bac5e), QFC(0xfb432a8a), QFC(0x00b5e294), + QFC(0xfff35c0f), QFC(0x08905893), QFC(0x608bf7c1), QFC(0xfdbfe2d8), + QFC(0x00b8dcd6), QFC(0xfffa67ed), QFC(0x0901a70f), QFC(0x636d2657), + QFC(0xfffccdc7), QFC(0x00b66387), QFC(0x0002f512), QFC(0x095eb98e), + QFC(0x65f9595d), QFC(0x01fa380f), QFC(0x00afb0f3), QFC(0x000d31b5), + QFC(0x09a3e163), QFC(0x682b39a4), QFC(0x03b8f8dc), QFC(0x00a520bb), + QFC(0x00193141), QFC(0x09cc1a7d), QFC(0x69fbfee3), QFC(0x05395430), + QFC(0x0097ce05), QFC(0x00269ad4), QFC(0x09d3fe14), QFC(0x6b69bfaf), + QFC(0x067e12f2), QFC(0x00889924), QFC(0x003567de), QFC(0x09b75cca), + QFC(0x6c716eb9), QFC(0x0789e850), QFC(0x00781556), QFC(0x0045436a), + QFC(0x097277a9), QFC(0x6d110fe4), QFC(0x085f29c6), QFC(0x00670cb6), + QFC(0x0055dba1), QFC(0x09015651), QFC(0x6d474e1d), QFC(0x09015651), + QFC(0x0055dba1), QFC(0xfe4d1be3), QFC(0xd1c58ace), QFC(0x2e3a7532), + QFC(0x01b2e41d), QFC(0x00000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_cos40[] = { + QTC(0x7fef5260), QTC(0x7f69ff76), QTC(0x7e5fe493), QTC(0x7cd21707), + QTC(0x7ac23561), QTC(0x783265c0), QTC(0x75255392), QTC(0x719e2cd2), + QTC(0x6da09eb1), QTC(0x6930d1c4), QTC(0x645365b2), QTC(0x5f0d6c5b), + QTC(0x59646498), QTC(0x535e3479), QTC(0x4d012324), QTC(0x4653d24b), + QTC(0x3f5d373e), QTC(0x382493b0), QTC(0x30b16e23), QTC(0x290b8a12), + QTC(0x213adfda), QTC(0x1947946c), QTC(0x1139f0cf), QTC(0x091a597e), + QTC(0x00f145ab), QTC(0xf8c73668), QTC(0xf0a4adcf), QTC(0xe8922622), + QTC(0xe09808f5), QTC(0xd8bea66a), QTC(0xd10e2c89), QTC(0xc98e9eb5), + QTC(0xc247cd5a), QTC(0xbb414dc0), QTC(0xb4827228), QTC(0xae12422c), + QTC(0xa7f7736a), QTC(0xa2386284), QTC(0x9cdb0c83), QTC(0x97e50896), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_sin40[] = { + QTC(0x0415583b), QTC(0x0c3bc74f), QTC(0x145576b1), QTC(0x1c59f557), + QTC(0x2440e84d), QTC(0x2c021369), QTC(0x339561e1), QTC(0x3af2eeb7), + QTC(0x42130cf0), QTC(0x48ee4f98), QTC(0x4f7d917c), QTC(0x55b9fc9e), + QTC(0x5b9d1154), QTC(0x6120ad0d), QTC(0x663f10b7), QTC(0x6af2e6bc), + QTC(0x6f374891), QTC(0x7307c3d0), QTC(0x76605edb), QTC(0x793d9d03), + QTC(0x7b9c8226), QTC(0x7d7a95cf), QTC(0x7ed5e5c6), QTC(0x7fad081b), + QTC(0x7fff1c9b), QTC(0x7fcbcdbc), QTC(0x7f1350f8), QTC(0x7dd6668f), + QTC(0x7c1658c5), QTC(0x79d4fa89), QTC(0x7714a58b), QTC(0x73d837ca), + QTC(0x7023109a), QTC(0x6bf90d1d), QTC(0x675e843e), QTC(0x6258422c), + QTC(0x5ceb8355), QTC(0x571deefa), QTC(0x50f59141), QTC(0x4a78d4f0), +}; + +/* This filter is scaled (0.8*pfilt) */ +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_PFT qmf_pfilt400[] = { + QFC(0x00000000), QFC(0x015be9b1), QFC(0x24fb90f5), QFC(0xdb046f0b), + QFC(0xfea4164f), QFC(0xfff15ed6), QFC(0x018b53a8), QFC(0x26d2bd4e), + QFC(0xdcd812f9), QFC(0xfed12595), QFC(0xfff3117b), QFC(0x01bcfae9), + QFC(0x28abebf8), QFC(0xdea834e5), QFC(0xfefbfdea), QFC(0xfff32e53), + QFC(0x01f075de), QFC(0x2a86e540), QFC(0xe07383c3), QFC(0xff24936e), + QFC(0xfff29758), QFC(0x0225bb61), QFC(0x2c629d51), QFC(0xe2399905), + QFC(0xff4ae4e6), QFC(0xfff1ab73), QFC(0x025cb6d7), QFC(0x2e3e69f9), + QFC(0xe3fa13fc), QFC(0xff6eefd4), QFC(0xfff0cfed), QFC(0x0295a000), + QFC(0x30196a50), QFC(0xe5b354ab), QFC(0xff9082cb), QFC(0xffefd442), + QFC(0x02d01d61), QFC(0x31f2b6ac), QFC(0xe765dadc), QFC(0xffb0037f), + QFC(0xffeef970), QFC(0x030c2f18), QFC(0x33c9a8c5), QFC(0xe910572d), + QFC(0xffcd26f2), QFC(0xffee0f91), QFC(0x03494088), QFC(0x359ce8be), + QFC(0xeab28265), QFC(0xffe8133f), QFC(0xffed3c86), QFC(0x03876734), + QFC(0x376caf22), QFC(0xec4c6fc6), QFC(0x0000b940), QFC(0xffecb05f), + QFC(0x03c6b32b), QFC(0x3936c186), QFC(0xeddbfa4a), QFC(0x00174372), + QFC(0xffec438a), QFC(0x04068585), QFC(0x3afb3b6d), QFC(0xef62382f), + QFC(0x002bbb7e), QFC(0xffebc5c7), QFC(0x0446af4f), QFC(0x3cb9159f), + QFC(0xf0de3518), QFC(0x003e0713), QFC(0xffeb8517), QFC(0x0487578f), + QFC(0x3e6f3802), QFC(0xf24f4ffd), QFC(0x004e64c7), QFC(0xffeb8b0d), + QFC(0x04c7cd0d), QFC(0x401d78d8), QFC(0xf3b6114c), QFC(0x005ccd60), + QFC(0xffeb9e0a), QFC(0x0507e855), QFC(0x41c1b7d9), QFC(0xf5107d52), + QFC(0x0069352b), QFC(0xffec0c97), QFC(0x054789e4), QFC(0x435c76d2), + QFC(0xf6600380), QFC(0x0073ff44), QFC(0xffecb3ca), QFC(0x05863c83), + QFC(0x44ec4796), QFC(0xf7a34fbf), QFC(0x007d07e5), QFC(0xffed65ae), + QFC(0x05c3bdde), QFC(0x46702a28), QFC(0xf8da6b28), QFC(0x008444ef), + QFC(0xffee90fb), QFC(0x05fff15c), QFC(0x47e8c54c), QFC(0xfa05d9fc), + QFC(0x008a30f2), QFC(0xffefff78), QFC(0x0639db53), QFC(0x4952ab1e), + QFC(0xfb23d977), QFC(0x008e9313), QFC(0xfff1a1ea), QFC(0x067202f0), + QFC(0x4aafbd18), QFC(0xfc35bba2), QFC(0x00918210), QFC(0xfff3a45f), + QFC(0x06a741b7), QFC(0x4bfdfb06), QFC(0xfd3aee85), QFC(0x009350b6), + QFC(0xfff5e33f), QFC(0x06d9e076), QFC(0x4d3cc634), QFC(0xfe331be0), + QFC(0x0093e3de), QFC(0xfff867de), QFC(0x07090b4f), QFC(0x4e6cc1b3), + QFC(0xff1f4fd2), QFC(0x00936109), QFC(0xfffb8658), QFC(0x073485a5), + QFC(0x4f8a8512), QFC(0xfffd716c), QFC(0x0091e939), QFC(0xfffec6af), + QFC(0x075c2159), QFC(0x50986228), QFC(0x00cfb536), QFC(0x008f7f85), + QFC(0x00025da8), QFC(0x077efad8), QFC(0x5194477e), QFC(0x0194f9a6), + QFC(0x008c8d8f), QFC(0x00064e63), QFC(0x079d423f), QFC(0x527db75e), + QFC(0x024d9e1c), QFC(0x00886b36), QFC(0x000a8e2a), QFC(0x07b64de9), + QFC(0x5355c7b6), QFC(0x02fa60b0), QFC(0x00841a2f), QFC(0x000f2b4f), + QFC(0x07c95704), QFC(0x5418bd4a), QFC(0x0399eb6f), QFC(0x007eea79), + QFC(0x00142767), QFC(0x07d67b97), QFC(0x54c998b6), QFC(0x042ddcf3), + QFC(0x0079719e), QFC(0x00193ee8), QFC(0x07dd27cf), QFC(0x55662c93), + QFC(0x04b5da5c), QFC(0x007369b7), QFC(0x001ee243), QFC(0x07dccb44), + QFC(0x55ee32f2), QFC(0x0531a8c2), QFC(0x006d4750), QFC(0x002471ce), + QFC(0x07d588d9), QFC(0x566317ad), QFC(0x05a2ff7a), QFC(0x0066c7aa), + QFC(0x002ab97f), QFC(0x07c5e3d5), QFC(0x56c12561), QFC(0x0607ed0d), + QFC(0x00601112), QFC(0x0030e1af), QFC(0x07ae9698), QFC(0x570be9e8), + QFC(0x0662a78a), QFC(0x005958bb), QFC(0x00376922), QFC(0x078ec621), + QFC(0x5740d984), QFC(0x06b287d1), QFC(0x00527092), QFC(0x003e065c), + QFC(0x0765b74d), QFC(0x57607ccb), QFC(0x06f819ec), QFC(0x004b9363), + QFC(0x0044afb4), QFC(0x0734450e), QFC(0x576c3e7e), QFC(0x0734450e), + QFC(0x0044afb4), QFC(0xfea4164f), QFC(0xdb046f0b), QFC(0x24fb90f5), + QFC(0x015be9b1), QFC(0x00000000), +}; + +const FIXP_QTW qmf_phaseshift_cos16[] = { + QTC(0x7fc25596), QTC(0x7dd6668f), QTC(0x7a05eead), QTC(0x745f9dd1), + QTC(0x6cf934fc), QTC(0x63ef3290), QTC(0x59646498), QTC(0x4d8162c4), + QTC(0x4073f21d), QTC(0x326e54c7), QTC(0x23a6887f), QTC(0x145576b1), + QTC(0x04b6195d), QTC(0xf50497fb), QTC(0xe57d5fda), QTC(0xd65c3b7b), +}; +const FIXP_QTW qmf_phaseshift_sin16[] = { + QTC(0x07d95b9e), QTC(0x176dd9de), QTC(0x26a82186), QTC(0x354d9057), + QTC(0x4325c135), QTC(0x4ffb654d), QTC(0x5b9d1154), QTC(0x65ddfbd3), + QTC(0x6e96a99d), QTC(0x75a585cf), QTC(0x7aef6323), QTC(0x7e5fe493), + QTC(0x7fe9cbc0), QTC(0x7f872bf3), QTC(0x7d3980ec), QTC(0x7909a92d), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_PFT qmf_pfilt240[] = { + /* FP filter implementation */ + QFC(0x00000000), QFC(0x0121ed68), QFC(0x1ed1a380), QFC(0xe12e5c80), + QFC(0xfede1298), QFC(0xfff4b438), QFC(0x0164d8de), QFC(0x21610064), + QFC(0xe3b64ef2), QFC(0xff1ba1be), QFC(0xfff533ce), QFC(0x01ac5eb8), + QFC(0x23f48a8e), QFC(0xe63437e4), QFC(0xff53fed7), QFC(0xfff40ee0), + QFC(0x01f7edb3), QFC(0x26895855), QFC(0xe8a5bb55), QFC(0xff871d30), + QFC(0xfff2cb20), QFC(0x0247b415), QFC(0x291c52e4), QFC(0xeb077fc7), + QFC(0xffb4cd53), QFC(0xfff18a22), QFC(0x029b070e), QFC(0x2baa29ab), + QFC(0xed57da15), QFC(0xffdd4df1), QFC(0xfff05d1b), QFC(0x02f0d600), + QFC(0x2e2fe755), QFC(0xef9507d5), QFC(0x00009a60), QFC(0xffefac36), + QFC(0x0348fcbc), QFC(0x30a98c1c), QFC(0xf1bba8f2), QFC(0x001eed4c), + QFC(0xffef0b8b), QFC(0x03a22bd2), QFC(0x3314a372), QFC(0xf3cb53d5), + QFC(0x0038684e), QFC(0xffeef3e0), QFC(0x03fbd58b), QFC(0x356de4ab), + QFC(0xf5c263c0), QFC(0x004d55d0), QFC(0xffef3cd8), QFC(0x0454a637), + QFC(0x37b13672), QFC(0xf79e7feb), QFC(0x005dd461), QFC(0xfff01619), + QFC(0x04abb9c0), QFC(0x39dc5c00), QFC(0xf95f9279), QFC(0x006a5b4d), + QFC(0xfff178d2), QFC(0x04fff3cb), QFC(0x3beca455), QFC(0xfb04e050), + QFC(0x007328ca), QFC(0xfff390f0), QFC(0x054fa1dc), QFC(0x3ddd668e), + QFC(0xfc8c7550), QFC(0x00788f16), QFC(0xfff64f40), QFC(0x0599ae6b), + QFC(0x3fad90c7), QFC(0xfdf72485), QFC(0x007b013c), QFC(0xfff9abe4), + QFC(0x05dcdec0), QFC(0x415aa155), QFC(0xff44c284), QFC(0x007ad0dd), + QFC(0xfffe0c37), QFC(0x06177d87), QFC(0x42e02f00), QFC(0x0073cf14), + QFC(0x007850b2), QFC(0x000314dd), QFC(0x0647fe8b), QFC(0x443e0472), + QFC(0x0185ddb7), QFC(0x00741328), QFC(0x0008cbce), QFC(0x066d40eb), + QFC(0x45722655), QFC(0x027b5093), QFC(0x006e15d2), QFC(0x000f67a8), + QFC(0x0684f772), QFC(0x46789539), QFC(0x03537bc9), QFC(0x0066c76d), + QFC(0x001696f2), QFC(0x068e247c), QFC(0x47520855), QFC(0x04104399), + QFC(0x005e76a0), QFC(0x001e5ed7), QFC(0x06874760), QFC(0x47fd3e55), + QFC(0x04b27f90), QFC(0x0055a663), QFC(0x0027012b), QFC(0x066e03f9), + QFC(0x487700c7), QFC(0x0539eefc), QFC(0x004c58b7), QFC(0x0030042f), + QFC(0x0641b0ab), QFC(0x48c0afc7), QFC(0x05a90172), QFC(0x0042c9e7), + QFC(0x00393d16), QFC(0x0600e435), QFC(0x48da3400), QFC(0x0600e435), + QFC(0x00393d16), QFC(0xfede1298), QFC(0xe12e5c80), QFC(0x1ed1a380), + QFC(0x0121ed68), QFC(0x00000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_cos24[] = { + QTC(0x7fded530), QTC(0x7ed5e5c6), QTC(0x7cc62bdf), QTC(0x79b3ece0), + QTC(0x75a585cf), QTC(0x70a35e25), QTC(0x6ab7d663), QTC(0x63ef3290), + QTC(0x5c5780d3), QTC(0x54007c51), QTC(0x4afb6c98), QTC(0x415b01ce), + QTC(0x37332dfd), QTC(0x2c98fbba), QTC(0x21a26295), QTC(0x1666198d), + QTC(0x0afb6805), QTC(0xff79f587), QTC(0xf3f998c0), QTC(0xe8922622), + QTC(0xdd5b3e7b), QTC(0xd26c1e08), QTC(0xc7db6c50), QTC(0xbdbf0d2f), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_sin24[] = { + QTC(0x05c1f4e7), QTC(0x1139f0cf), QTC(0x1c8e3bbe), QTC(0x27a75c95), + QTC(0x326e54c7), QTC(0x3cccd004), QTC(0x46ad5278), QTC(0x4ffb654d), + QTC(0x58a3c118), QTC(0x609475c3), QTC(0x67bd0fbd), QTC(0x6e0eba0c), + QTC(0x737c5d0b), QTC(0x77fab989), QTC(0x7b808015), QTC(0x7e06644c), + QTC(0x7f872bf3), QTC(0x7fffb9d1), QTC(0x7f6f141f), QTC(0x7dd6668f), + QTC(0x7b38ffde), QTC(0x779c4afc), QTC(0x7307c3d0), QTC(0x6d84e7b7), +}; + +/* qmf_pfilt640 is used with stride 2 instead of qmf_pfilt320[] */ + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_cos32[] = { + QTC(0x7fe9cbc0), QTC(0x7f3857f6), QTC(0x7dd6668f), QTC(0x7bc5e290), + QTC(0x7909a92d), QTC(0x75a585cf), QTC(0x719e2cd2), QTC(0x6cf934fc), + QTC(0x67bd0fbd), QTC(0x61f1003f), QTC(0x5b9d1154), QTC(0x54ca0a4b), + QTC(0x4d8162c4), QTC(0x45cd358f), QTC(0x3db832a6), QTC(0x354d9057), + QTC(0x2c98fbba), QTC(0x23a6887f), QTC(0x1a82a026), QTC(0x1139f0cf), + QTC(0x07d95b9e), QTC(0xfe6de2e0), QTC(0xf50497fb), QTC(0xebaa894f), + QTC(0xe26cb01b), QTC(0xd957de7a), QTC(0xd078ad9e), QTC(0xc7db6c50), + QTC(0xbf8c0de3), QTC(0xb796199b), QTC(0xb0049ab3), QTC(0xa8e21106), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_sin32[] = { + QTC(0x04b6195d), QTC(0x0e1bc2e4), QTC(0x176dd9de), QTC(0x209f701c), + QTC(0x29a3c485), QTC(0x326e54c7), QTC(0x3af2eeb7), QTC(0x4325c135), + QTC(0x4afb6c98), QTC(0x5269126e), QTC(0x59646498), QTC(0x5fe3b38d), + QTC(0x65ddfbd3), QTC(0x6b4af279), QTC(0x7023109a), QTC(0x745f9dd1), + QTC(0x77fab989), QTC(0x7aef6323), QTC(0x7d3980ec), QTC(0x7ed5e5c6), + QTC(0x7fc25596), QTC(0x7ffd885a), QTC(0x7f872bf3), QTC(0x7e5fe493), + QTC(0x7c894bde), QTC(0x7a05eead), QTC(0x76d94989), QTC(0x7307c3d0), + QTC(0x6e96a99d), QTC(0x698c246c), QTC(0x63ef3290), QTC(0x5dc79d7c), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_cos_downsamp32[] = { + QTC(0x7fd8878e), QTC(0x7e9d55fc), QTC(0x7c29fbee), QTC(0x78848414), + QTC(0x73b5ebd1), QTC(0x6dca0d14), QTC(0x66cf8120), QTC(0x5ed77c8a), + QTC(0x55f5a4d2), QTC(0x4c3fdff4), QTC(0x41ce1e65), QTC(0x36ba2014), + QTC(0x2b1f34eb), QTC(0x1f19f97b), QTC(0x12c8106f), QTC(0x0647d97c), + QTC(0xf9b82684), QTC(0xed37ef91), QTC(0xe0e60685), QTC(0xd4e0cb15), + QTC(0xc945dfec), QTC(0xbe31e19b), QTC(0xb3c0200c), QTC(0xaa0a5b2e), + QTC(0xa1288376), QTC(0x99307ee0), QTC(0x9235f2ec), QTC(0x8c4a142f), + QTC(0x877b7bec), QTC(0x83d60412), QTC(0x8162aa04), QTC(0x80277872), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_sin_downsamp32[] = { + QTC(0x0647d97c), QTC(0x12c8106f), QTC(0x1f19f97b), QTC(0x2b1f34eb), + QTC(0x36ba2014), QTC(0x41ce1e65), QTC(0x4c3fdff4), QTC(0x55f5a4d2), + QTC(0x5ed77c8a), QTC(0x66cf8120), QTC(0x6dca0d14), QTC(0x73b5ebd1), + QTC(0x78848414), QTC(0x7c29fbee), QTC(0x7e9d55fc), QTC(0x7fd8878e), + QTC(0x7fd8878e), QTC(0x7e9d55fc), QTC(0x7c29fbee), QTC(0x78848414), + QTC(0x73b5ebd1), QTC(0x6dca0d14), QTC(0x66cf8120), QTC(0x5ed77c8a), + QTC(0x55f5a4d2), QTC(0x4c3fdff4), QTC(0x41ce1e65), QTC(0x36ba2014), + QTC(0x2b1f34eb), QTC(0x1f19f97b), QTC(0x12c8106f), QTC(0x0647d97c), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_PFT qmf_pfilt640[] = { + QFC(0x00000000), QFC(0x01b2e41d), QFC(0x2e3a7532), QFC(0xd1c58ace), + QFC(0xfe4d1be3), QFC(0xffede50e), QFC(0x01d78bfc), QFC(0x2faa221c), + QFC(0xd3337b3d), QFC(0xfe70b8d1), QFC(0xffed978a), QFC(0x01fd3ba0), + QFC(0x311af3a4), QFC(0xd49fd55f), QFC(0xfe933dc0), QFC(0xffefc9b9), + QFC(0x02244a25), QFC(0x328cc6f0), QFC(0xd60a46e5), QFC(0xfeb48d0d), + QFC(0xfff0065d), QFC(0x024bf7a1), QFC(0x33ff670e), QFC(0xd7722f04), + QFC(0xfed4bec3), QFC(0xffeff6ca), QFC(0x0274ba43), QFC(0x3572ec70), + QFC(0xd8d7f21f), QFC(0xfef3f6ab), QFC(0xffef7b8b), QFC(0x029e35b4), + QFC(0x36e69691), QFC(0xda3b176a), QFC(0xff120d70), QFC(0xffeedfa4), + QFC(0x02c89901), QFC(0x385a49c4), QFC(0xdb9b5b12), QFC(0xff2ef725), + QFC(0xffee1650), QFC(0x02f3e48d), QFC(0x39ce0477), QFC(0xdcf898fb), + QFC(0xff4aabc8), QFC(0xffed651d), QFC(0x03201116), QFC(0x3b415115), + QFC(0xde529086), QFC(0xff6542d1), QFC(0xffecc31b), QFC(0x034d01f1), + QFC(0x3cb41219), QFC(0xdfa93ab5), QFC(0xff7ee3f1), QFC(0xffebe77b), + QFC(0x037ad438), QFC(0x3e25b17e), QFC(0xe0fc421e), QFC(0xff975c01), + QFC(0xffeb50b2), QFC(0x03a966bc), QFC(0x3f962fb8), QFC(0xe24b8f66), + QFC(0xffaea5d6), QFC(0xffea9192), QFC(0x03d8afe6), QFC(0x41058bc6), + QFC(0xe396a45d), QFC(0xffc4e365), QFC(0xffe9ca76), QFC(0x04083fec), + QFC(0x4272a385), QFC(0xe4de0cb0), QFC(0xffda17f2), QFC(0xffe940f4), + QFC(0x043889c6), QFC(0x43de620a), QFC(0xe620c476), QFC(0xffee183b), + QFC(0xffe88ba8), QFC(0x04694101), QFC(0x4547daeb), QFC(0xe75f8bb7), + QFC(0x0000e790), QFC(0xffe83a07), QFC(0x049aa82f), QFC(0x46aea856), + QFC(0xe89971b7), QFC(0x00131c75), QFC(0xffe79e16), QFC(0x04cc2fcf), + QFC(0x4812f848), QFC(0xe9cea84a), QFC(0x0023b989), QFC(0xffe7746e), + QFC(0x04fe20be), QFC(0x4973fef2), QFC(0xeafee7f1), QFC(0x0033b927), + QFC(0xffe6d466), QFC(0x05303f88), QFC(0x4ad237a2), QFC(0xec2a3f5f), + QFC(0x00426f36), QFC(0xffe6afed), QFC(0x05626209), QFC(0x4c2ca3df), + QFC(0xed50a31d), QFC(0x00504f41), QFC(0xffe65416), QFC(0x05950122), + QFC(0x4d83976d), QFC(0xee71b2fe), QFC(0x005d36df), QFC(0xffe681c6), + QFC(0x05c76fed), QFC(0x4ed62be3), QFC(0xef8d4d7b), QFC(0x006928a0), + QFC(0xffe66dd0), QFC(0x05f9c051), QFC(0x5024d70e), QFC(0xf0a3959f), + QFC(0x007400b8), QFC(0xffe66fab), QFC(0x062bf5ec), QFC(0x516eefb9), + QFC(0xf1b461ab), QFC(0x007e0393), QFC(0xffe69423), QFC(0x065dd56a), + QFC(0x52b449de), QFC(0xf2bf6ea4), QFC(0x00872c63), QFC(0xffe6fed4), + QFC(0x068f8b44), QFC(0x53f495aa), QFC(0xf3c4e887), QFC(0x008f87aa), + QFC(0xffe75361), QFC(0x06c0f0c0), QFC(0x552f8ff7), QFC(0xf4c473c5), + QFC(0x0096dcc2), QFC(0xffe80414), QFC(0x06f1825d), QFC(0x56654bdd), + QFC(0xf5be0fa9), QFC(0x009da526), QFC(0xffe85b4a), QFC(0x0721bf22), + QFC(0x579505f5), QFC(0xf6b1f3c3), QFC(0x00a3508f), QFC(0xffe954d0), + QFC(0x075112a2), QFC(0x58befacd), QFC(0xf79fa13a), QFC(0x00a85e94), + QFC(0xffea353a), QFC(0x077fedb3), QFC(0x59e2f69e), QFC(0xf887507c), + QFC(0x00acbd2f), QFC(0xffeb3849), QFC(0x07ad8c26), QFC(0x5b001db8), + QFC(0xf96916f5), QFC(0x00b06b68), QFC(0xffec8409), QFC(0x07da2b7f), + QFC(0x5c16d0ae), QFC(0xfa44a069), QFC(0x00b36acd), QFC(0xffedc418), + QFC(0x08061671), QFC(0x5d26be9b), QFC(0xfb19b7bd), QFC(0x00b58c8d), + QFC(0xffef2395), QFC(0x08303897), QFC(0x5e2f6367), QFC(0xfbe8f5bd), + QFC(0x00b73ab0), QFC(0xfff0e7ef), QFC(0x08594888), QFC(0x5f30ff5f), + QFC(0xfcb1d740), QFC(0x00b85f70), QFC(0xfff294c3), QFC(0x0880ffdd), + QFC(0x602b0c7f), QFC(0xfd7475d8), QFC(0x00b8c6b0), QFC(0xfff48700), + QFC(0x08a75da4), QFC(0x611d58a3), QFC(0xfe310657), QFC(0x00b8fe0d), + QFC(0xfff681d6), QFC(0x08cb4e23), QFC(0x6207f220), QFC(0xfee723c6), + QFC(0x00b8394b), QFC(0xfff91fc9), QFC(0x08edfeaa), QFC(0x62ea6474), + QFC(0xff96db8f), QFC(0x00b74c37), QFC(0xfffb42b0), QFC(0x090ec1fd), + QFC(0x63c45243), QFC(0x0040c497), QFC(0x00b5c867), QFC(0xfffdfa24), + QFC(0x092d7970), QFC(0x64964063), QFC(0x00e42fa2), QFC(0x00b3d15c), + QFC(0x00007134), QFC(0x0949eaac), QFC(0x655f63f2), QFC(0x01816e06), + QFC(0x00b1978d), QFC(0x00039609), QFC(0x0963ed46), QFC(0x661fd6b8), + QFC(0x02186a92), QFC(0x00af374c), QFC(0x0006b1cf), QFC(0x097c1ee9), + QFC(0x66d76725), QFC(0x02a99097), QFC(0x00abe79e), QFC(0x0009aa3f), + QFC(0x099140a7), QFC(0x6785c24d), QFC(0x03343534), QFC(0x00a8739d), + QFC(0x000d31b5), QFC(0x09a3e163), QFC(0x682b39a4), QFC(0x03b8f8dc), + QFC(0x00a520bb), QFC(0x0010bc63), QFC(0x09b3d780), QFC(0x68c7269c), + QFC(0x0437fb0a), QFC(0x00a1039c), QFC(0x001471f8), QFC(0x09c0e59f), + QFC(0x6959709d), QFC(0x04b0adcb), QFC(0x009d10bf), QFC(0x0018703f), + QFC(0x09cab9f2), QFC(0x69e29784), QFC(0x05237f9d), QFC(0x0098b855), + QFC(0x001c3549), QFC(0x09d19ca9), QFC(0x6a619c5e), QFC(0x0590a67d), + QFC(0x009424c6), QFC(0x002064f8), QFC(0x09d52709), QFC(0x6ad73e8e), + QFC(0x05f7fb90), QFC(0x008f4bfd), QFC(0x0024dd50), QFC(0x09d5560b), + QFC(0x6b42a864), QFC(0x06593912), QFC(0x008a7dd7), QFC(0x00293718), + QFC(0x09d1fa23), QFC(0x6ba4629f), QFC(0x06b559c3), QFC(0x0085c217), + QFC(0x002d8e42), QFC(0x09caeb0f), QFC(0x6bfbdd98), QFC(0x070bbf58), + QFC(0x00807994), QFC(0x00329ab6), QFC(0x09c018cf), QFC(0x6c492217), + QFC(0x075ca90c), QFC(0x007b3875), QFC(0x003745f9), QFC(0x09b18a1d), + QFC(0x6c8c4c7a), QFC(0x07a8127d), QFC(0x0075fded), QFC(0x003c1fa4), + QFC(0x099ec3dc), QFC(0x6cc59bab), QFC(0x07ee507c), QFC(0x0070c8a5), + QFC(0x004103f5), QFC(0x09881dc5), QFC(0x6cf4073e), QFC(0x082f552e), + QFC(0x006b47fa), QFC(0x00465348), QFC(0x096d0e22), QFC(0x6d18520e), + QFC(0x086b1eec), QFC(0x0065fde5), QFC(0x004b6c46), QFC(0x094d7ec2), + QFC(0x6d32730f), QFC(0x08a24899), QFC(0x006090c4), QFC(0x0050b177), + QFC(0x09299ead), QFC(0x6d41d964), QFC(0x08d3e41b), QFC(0x005b5371), + QFC(0x0055dba1), QFC(0x09015651), QFC(0x6d474e1d), QFC(0x09015651), + QFC(0x0055dba1), QFC(0xfe4d1be3), QFC(0xd1c58ace), QFC(0x2e3a7532), + QFC(0x01b2e41d), QFC(0x00000000), +}; + +/* This variant of the table above is used on platforms, that have vectorized + access to the table reading 4 filter sets (each of 5 coefficients) in a + block. Format: 1st row flt[0] of 4 sets (e.g. set 0, 1, 2, 3) 2nd row + flt[1] of 4 sets (e.g. set 0, 1, 2, 3) 3rd row flt[2] of 4 sets (e.g. set + 0, 1, 2, 3) 4th row flt[3] of 4 sets (e.g. set 0, 1, 2, 3) 5th row + flt[4] of 4 sets (e.g. set 0, 1, 2, 3) There are 32 blocks of 20 + coefficients, in total 640. Each of the rows must be at least 64-bit aligned + (see: RAM_ALIGN). +*/ +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_PFT qmf_pfilt640_vector[] = { + /*------------- 1 .. 4 ---------------*/ + QFC(0xFFEDE50E), + QFC(0xFFED978A), + QFC(0xFFEFC9B9), + QFC(0xFFF0065D), + QFC(0x01D78BFC), + QFC(0x01FD3BA0), + QFC(0x02244A25), + QFC(0x024BF7A1), + QFC(0x2FAA221C), + QFC(0x311AF3A4), + QFC(0x328CC6F0), + QFC(0x33FF670E), + QFC(0xD3337B3D), + QFC(0xD49FD55F), + QFC(0xD60A46E5), + QFC(0xD7722F04), + QFC(0xFE70B8D1), + QFC(0xFE933DC0), + QFC(0xFEB48D0D), + QFC(0xFED4BEC3), + /*------------- 5 .. 8 ---------------*/ + QFC(0xFFEFF6CA), + QFC(0xFFEF7B8B), + QFC(0xFFEEDFA4), + QFC(0xFFEE1650), + QFC(0x0274BA43), + QFC(0x029E35B4), + QFC(0x02C89901), + QFC(0x02F3E48D), + QFC(0x3572EC70), + QFC(0x36E69691), + QFC(0x385A49C4), + QFC(0x39CE0477), + QFC(0xD8D7F21F), + QFC(0xDA3B176A), + QFC(0xDB9B5B12), + QFC(0xDCF898FB), + QFC(0xFEF3F6AB), + QFC(0xFF120D70), + QFC(0xFF2EF725), + QFC(0xFF4AABC8), + /*------------- 9 .. 12 ---------------*/ + QFC(0xFFED651D), + QFC(0xFFECC31B), + QFC(0xFFEBE77B), + QFC(0xFFEB50B2), + QFC(0x03201116), + QFC(0x034D01F1), + QFC(0x037AD438), + QFC(0x03A966BC), + QFC(0x3B415115), + QFC(0x3CB41219), + QFC(0x3E25B17E), + QFC(0x3F962FB8), + QFC(0xDE529086), + QFC(0xDFA93AB5), + QFC(0xE0FC421E), + QFC(0xE24B8F66), + QFC(0xFF6542D1), + QFC(0xFF7EE3F1), + QFC(0xFF975C01), + QFC(0xFFAEA5D6), + /*------------- 13 .. 16 ---------------*/ + QFC(0xFFEA9192), + QFC(0xFFE9CA76), + QFC(0xFFE940F4), + QFC(0xFFE88BA8), + QFC(0x03D8AFE6), + QFC(0x04083FEC), + QFC(0x043889C6), + QFC(0x04694101), + QFC(0x41058BC6), + QFC(0x4272A385), + QFC(0x43DE620A), + QFC(0x4547DAEB), + QFC(0xE396A45D), + QFC(0xE4DE0CB0), + QFC(0xE620C476), + QFC(0xE75F8BB7), + QFC(0xFFC4E365), + QFC(0xFFDA17F2), + QFC(0xFFEE183B), + QFC(0x0000E790), + /*------------- 17 .. 20 ---------------*/ + QFC(0xFFE83A07), + QFC(0xFFE79E16), + QFC(0xFFE7746E), + QFC(0xFFE6D466), + QFC(0x049AA82F), + QFC(0x04CC2FCF), + QFC(0x04FE20BE), + QFC(0x05303F88), + QFC(0x46AEA856), + QFC(0x4812F848), + QFC(0x4973FEF2), + QFC(0x4AD237A2), + QFC(0xE89971B7), + QFC(0xE9CEA84A), + QFC(0xEAFEE7F1), + QFC(0xEC2A3F5F), + QFC(0x00131C75), + QFC(0x0023B989), + QFC(0x0033B927), + QFC(0x00426F36), + /*------------- 21 .. 24 ---------------*/ + QFC(0xFFE6AFED), + QFC(0xFFE65416), + QFC(0xFFE681C6), + QFC(0xFFE66DD0), + QFC(0x05626209), + QFC(0x05950122), + QFC(0x05C76FED), + QFC(0x05F9C051), + QFC(0x4C2CA3DF), + QFC(0x4D83976D), + QFC(0x4ED62BE3), + QFC(0x5024D70E), + QFC(0xED50A31D), + QFC(0xEE71B2FE), + QFC(0xEF8D4D7B), + QFC(0xF0A3959F), + QFC(0x00504F41), + QFC(0x005D36DF), + QFC(0x006928A0), + QFC(0x007400B8), + /*------------- 25 .. 28 ---------------*/ + QFC(0xFFE66FAB), + QFC(0xFFE69423), + QFC(0xFFE6FED4), + QFC(0xFFE75361), + QFC(0x062BF5EC), + QFC(0x065DD56A), + QFC(0x068F8B44), + QFC(0x06C0F0C0), + QFC(0x516EEFB9), + QFC(0x52B449DE), + QFC(0x53F495AA), + QFC(0x552F8FF7), + QFC(0xF1B461AB), + QFC(0xF2BF6EA4), + QFC(0xF3C4E887), + QFC(0xF4C473C5), + QFC(0x007E0393), + QFC(0x00872C63), + QFC(0x008F87AA), + QFC(0x0096DCC2), + /*------------- 29 .. 32 ---------------*/ + QFC(0xFFE80414), + QFC(0xFFE85B4A), + QFC(0xFFE954D0), + QFC(0xFFEA353A), + QFC(0x06F1825D), + QFC(0x0721BF22), + QFC(0x075112A2), + QFC(0x077FEDB3), + QFC(0x56654BDD), + QFC(0x579505F5), + QFC(0x58BEFACD), + QFC(0x59E2F69E), + QFC(0xF5BE0FA9), + QFC(0xF6B1F3C3), + QFC(0xF79FA13A), + QFC(0xF887507C), + QFC(0x009DA526), + QFC(0x00A3508F), + QFC(0x00A85E94), + QFC(0x00ACBD2F), + /*------------- 33 .. 36 ---------------*/ + QFC(0xFFEB3849), + QFC(0xFFEC8409), + QFC(0xFFEDC418), + QFC(0xFFEF2395), + QFC(0x07AD8C26), + QFC(0x07DA2B7F), + QFC(0x08061671), + QFC(0x08303897), + QFC(0x5B001DB8), + QFC(0x5C16D0AE), + QFC(0x5D26BE9B), + QFC(0x5E2F6367), + QFC(0xF96916F5), + QFC(0xFA44A069), + QFC(0xFB19B7BD), + QFC(0xFBE8F5BD), + QFC(0x00B06B68), + QFC(0x00B36ACD), + QFC(0x00B58C8D), + QFC(0x00B73AB0), + /*------------- 37 .. 40 ---------------*/ + QFC(0xFFF0E7EF), + QFC(0xFFF294C3), + QFC(0xFFF48700), + QFC(0xFFF681D6), + QFC(0x08594888), + QFC(0x0880FFDD), + QFC(0x08A75DA4), + QFC(0x08CB4E23), + QFC(0x5F30FF5F), + QFC(0x602B0C7F), + QFC(0x611D58A3), + QFC(0x6207F220), + QFC(0xFCB1D740), + QFC(0xFD7475D8), + QFC(0xFE310657), + QFC(0xFEE723C6), + QFC(0x00B85F70), + QFC(0x00B8C6B0), + QFC(0x00B8FE0D), + QFC(0x00B8394B), + /*------------- 41 .. 44 ---------------*/ + QFC(0xFFF91FC9), + QFC(0xFFFB42B0), + QFC(0xFFFDFA24), + QFC(0x00007134), + QFC(0x08EDFEAA), + QFC(0x090EC1FD), + QFC(0x092D7970), + QFC(0x0949EAAC), + QFC(0x62EA6474), + QFC(0x63C45243), + QFC(0x64964063), + QFC(0x655F63F2), + QFC(0xFF96DB8F), + QFC(0x0040C497), + QFC(0x00E42FA2), + QFC(0x01816E06), + QFC(0x00B74C37), + QFC(0x00B5C867), + QFC(0x00B3D15C), + QFC(0x00B1978D), + /*------------- 45 .. 48 ---------------*/ + QFC(0x00039609), + QFC(0x0006B1CF), + QFC(0x0009AA3F), + QFC(0x000D31B5), + QFC(0x0963ED46), + QFC(0x097C1EE9), + QFC(0x099140A7), + QFC(0x09A3E163), + QFC(0x661FD6B8), + QFC(0x66D76725), + QFC(0x6785C24D), + QFC(0x682B39A4), + QFC(0x02186A92), + QFC(0x02A99097), + QFC(0x03343534), + QFC(0x03B8F8DC), + QFC(0x00AF374C), + QFC(0x00ABE79E), + QFC(0x00A8739D), + QFC(0x00A520BB), + /*------------- 49 .. 52 ---------------*/ + QFC(0x0010BC63), + QFC(0x001471F8), + QFC(0x0018703F), + QFC(0x001C3549), + QFC(0x09B3D780), + QFC(0x09C0E59F), + QFC(0x09CAB9F2), + QFC(0x09D19CA9), + QFC(0x68C7269C), + QFC(0x6959709D), + QFC(0x69E29784), + QFC(0x6A619C5E), + QFC(0x0437FB0A), + QFC(0x04B0ADCB), + QFC(0x05237F9D), + QFC(0x0590A67D), + QFC(0x00A1039C), + QFC(0x009D10BF), + QFC(0x0098B855), + QFC(0x009424C6), + /*------------- 53 .. 56 ---------------*/ + QFC(0x002064F8), + QFC(0x0024DD50), + QFC(0x00293718), + QFC(0x002D8E42), + QFC(0x09D52709), + QFC(0x09D5560B), + QFC(0x09D1FA23), + QFC(0x09CAEB0F), + QFC(0x6AD73E8E), + QFC(0x6B42A864), + QFC(0x6BA4629F), + QFC(0x6BFBDD98), + QFC(0x05F7FB90), + QFC(0x06593912), + QFC(0x06B559C3), + QFC(0x070BBF58), + QFC(0x008F4BFD), + QFC(0x008A7DD7), + QFC(0x0085C217), + QFC(0x00807994), + /*------------- 57 .. 60 ---------------*/ + QFC(0x00329AB6), + QFC(0x003745F9), + QFC(0x003C1FA4), + QFC(0x004103F5), + QFC(0x09C018CF), + QFC(0x09B18A1D), + QFC(0x099EC3DC), + QFC(0x09881DC5), + QFC(0x6C492217), + QFC(0x6C8C4C7A), + QFC(0x6CC59BAB), + QFC(0x6CF4073E), + QFC(0x075CA90C), + QFC(0x07A8127D), + QFC(0x07EE507C), + QFC(0x082F552E), + QFC(0x007B3875), + QFC(0x0075FDED), + QFC(0x0070C8A5), + QFC(0x006B47FA), + /*------------- 61 .. 64 ---------------*/ + QFC(0x00465348), + QFC(0x004B6C46), + QFC(0x0050B177), + QFC(0x0055DBA1), + QFC(0x096D0E22), + QFC(0x094D7EC2), + QFC(0x09299EAD), + QFC(0x09015651), + QFC(0x6D18520E), + QFC(0x6D32730F), + QFC(0x6D41D964), + QFC(0x6D474E1D), + QFC(0x086B1EEC), + QFC(0x08A24899), + QFC(0x08D3E41B), + QFC(0x09015651), + QFC(0x0065FDE5), + QFC(0x006090C4), + QFC(0x005B5371), + QFC(0x0055DBA1), + /*------------- 63 .. 60 ---------------*/ + QFC(0x005B5371), + QFC(0x006090C4), + QFC(0x0065FDE5), + QFC(0x006B47FA), + QFC(0x08D3E41B), + QFC(0x08A24899), + QFC(0x086B1EEC), + QFC(0x082F552E), + QFC(0x6D41D964), + QFC(0x6D32730F), + QFC(0x6D18520E), + QFC(0x6CF4073E), + QFC(0x09299EAD), + QFC(0x094D7EC2), + QFC(0x096D0E22), + QFC(0x09881DC5), + QFC(0x0050B177), + QFC(0x004B6C46), + QFC(0x00465348), + QFC(0x004103F5), + /*------------- 59 .. 56 ---------------*/ + QFC(0x0070C8A5), + QFC(0x0075FDED), + QFC(0x007B3875), + QFC(0x00807994), + QFC(0x07EE507C), + QFC(0x07A8127D), + QFC(0x075CA90C), + QFC(0x070BBF58), + QFC(0x6CC59BAB), + QFC(0x6C8C4C7A), + QFC(0x6C492217), + QFC(0x6BFBDD98), + QFC(0x099EC3DC), + QFC(0x09B18A1D), + QFC(0x09C018CF), + QFC(0x09CAEB0F), + QFC(0x003C1FA4), + QFC(0x003745F9), + QFC(0x00329AB6), + QFC(0x002D8E42), + /*------------- 55 .. 52 ---------------*/ + QFC(0x0085C217), + QFC(0x008A7DD7), + QFC(0x008F4BFD), + QFC(0x009424C6), + QFC(0x06B559C3), + QFC(0x06593912), + QFC(0x05F7FB90), + QFC(0x0590A67D), + QFC(0x6BA4629F), + QFC(0x6B42A864), + QFC(0x6AD73E8E), + QFC(0x6A619C5E), + QFC(0x09D1FA23), + QFC(0x09D5560B), + QFC(0x09D52709), + QFC(0x09D19CA9), + QFC(0x00293718), + QFC(0x0024DD50), + QFC(0x002064F8), + QFC(0x001C3549), + /*------------- 51 .. 48 ---------------*/ + QFC(0x0098B855), + QFC(0x009D10BF), + QFC(0x00A1039C), + QFC(0x00A520BB), + QFC(0x05237F9D), + QFC(0x04B0ADCB), + QFC(0x0437FB0A), + QFC(0x03B8F8DC), + QFC(0x69E29784), + QFC(0x6959709D), + QFC(0x68C7269C), + QFC(0x682B39A4), + QFC(0x09CAB9F2), + QFC(0x09C0E59F), + QFC(0x09B3D780), + QFC(0x09A3E163), + QFC(0x0018703F), + QFC(0x001471F8), + QFC(0x0010BC63), + QFC(0x000D31B5), + /*------------- 47 .. 44 ---------------*/ + QFC(0x00A8739D), + QFC(0x00ABE79E), + QFC(0x00AF374C), + QFC(0x00B1978D), + QFC(0x03343534), + QFC(0x02A99097), + QFC(0x02186A92), + QFC(0x01816E06), + QFC(0x6785C24D), + QFC(0x66D76725), + QFC(0x661FD6B8), + QFC(0x655F63F2), + QFC(0x099140A7), + QFC(0x097C1EE9), + QFC(0x0963ED46), + QFC(0x0949EAAC), + QFC(0x0009AA3F), + QFC(0x0006B1CF), + QFC(0x00039609), + QFC(0x00007134), + /*------------- 43 .. 40 ---------------*/ + QFC(0x00B3D15C), + QFC(0x00B5C867), + QFC(0x00B74C37), + QFC(0x00B8394B), + QFC(0x00E42FA2), + QFC(0x0040C497), + QFC(0xFF96DB8F), + QFC(0xFEE723C6), + QFC(0x64964063), + QFC(0x63C45243), + QFC(0x62EA6474), + QFC(0x6207F220), + QFC(0x092D7970), + QFC(0x090EC1FD), + QFC(0x08EDFEAA), + QFC(0x08CB4E23), + QFC(0xFFFDFA24), + QFC(0xFFFB42B0), + QFC(0xFFF91FC9), + QFC(0xFFF681D6), + /*------------- 39 .. 36 ---------------*/ + QFC(0x00B8FE0D), + QFC(0x00B8C6B0), + QFC(0x00B85F70), + QFC(0x00B73AB0), + QFC(0xFE310657), + QFC(0xFD7475D8), + QFC(0xFCB1D740), + QFC(0xFBE8F5BD), + QFC(0x611D58A3), + QFC(0x602B0C7F), + QFC(0x5F30FF5F), + QFC(0x5E2F6367), + QFC(0x08A75DA4), + QFC(0x0880FFDD), + QFC(0x08594888), + QFC(0x08303897), + QFC(0xFFF48700), + QFC(0xFFF294C3), + QFC(0xFFF0E7EF), + QFC(0xFFEF2395), + /*------------- 35 .. 32 ---------------*/ + QFC(0x00B58C8D), + QFC(0x00B36ACD), + QFC(0x00B06B68), + QFC(0x00ACBD2F), + QFC(0xFB19B7BD), + QFC(0xFA44A069), + QFC(0xF96916F5), + QFC(0xF887507C), + QFC(0x5D26BE9B), + QFC(0x5C16D0AE), + QFC(0x5B001DB8), + QFC(0x59E2F69E), + QFC(0x08061671), + QFC(0x07DA2B7F), + QFC(0x07AD8C26), + QFC(0x077FEDB3), + QFC(0xFFEDC418), + QFC(0xFFEC8409), + QFC(0xFFEB3849), + QFC(0xFFEA353A), + /*------------- 31 .. 28 ---------------*/ + QFC(0x00A85E94), + QFC(0x00A3508F), + QFC(0x009DA526), + QFC(0x0096DCC2), + QFC(0xF79FA13A), + QFC(0xF6B1F3C3), + QFC(0xF5BE0FA9), + QFC(0xF4C473C5), + QFC(0x58BEFACD), + QFC(0x579505F5), + QFC(0x56654BDD), + QFC(0x552F8FF7), + QFC(0x075112A2), + QFC(0x0721BF22), + QFC(0x06F1825D), + QFC(0x06C0F0C0), + QFC(0xFFE954D0), + QFC(0xFFE85B4A), + QFC(0xFFE80414), + QFC(0xFFE75361), + /*------------- 27 .. 24 ---------------*/ + QFC(0x008F87AA), + QFC(0x00872C63), + QFC(0x007E0393), + QFC(0x007400B8), + QFC(0xF3C4E887), + QFC(0xF2BF6EA4), + QFC(0xF1B461AB), + QFC(0xF0A3959F), + QFC(0x53F495AA), + QFC(0x52B449DE), + QFC(0x516EEFB9), + QFC(0x5024D70E), + QFC(0x068F8B44), + QFC(0x065DD56A), + QFC(0x062BF5EC), + QFC(0x05F9C051), + QFC(0xFFE6FED4), + QFC(0xFFE69423), + QFC(0xFFE66FAB), + QFC(0xFFE66DD0), + /*------------- 23 .. 20 ---------------*/ + QFC(0x006928A0), + QFC(0x005D36DF), + QFC(0x00504F41), + QFC(0x00426F36), + QFC(0xEF8D4D7B), + QFC(0xEE71B2FE), + QFC(0xED50A31D), + QFC(0xEC2A3F5F), + QFC(0x4ED62BE3), + QFC(0x4D83976D), + QFC(0x4C2CA3DF), + QFC(0x4AD237A2), + QFC(0x05C76FED), + QFC(0x05950122), + QFC(0x05626209), + QFC(0x05303F88), + QFC(0xFFE681C6), + QFC(0xFFE65416), + QFC(0xFFE6AFED), + QFC(0xFFE6D466), + /*------------- 19 .. 16 ---------------*/ + QFC(0x0033B927), + QFC(0x0023B989), + QFC(0x00131C75), + QFC(0x0000E790), + QFC(0xEAFEE7F1), + QFC(0xE9CEA84A), + QFC(0xE89971B7), + QFC(0xE75F8BB7), + QFC(0x4973FEF2), + QFC(0x4812F848), + QFC(0x46AEA856), + QFC(0x4547DAEB), + QFC(0x04FE20BE), + QFC(0x04CC2FCF), + QFC(0x049AA82F), + QFC(0x04694101), + QFC(0xFFE7746E), + QFC(0xFFE79E16), + QFC(0xFFE83A07), + QFC(0xFFE88BA8), + /*------------- 15 .. 12 ---------------*/ + QFC(0xFFEE183B), + QFC(0xFFDA17F2), + QFC(0xFFC4E365), + QFC(0xFFAEA5D6), + QFC(0xE620C476), + QFC(0xE4DE0CB0), + QFC(0xE396A45D), + QFC(0xE24B8F66), + QFC(0x43DE620A), + QFC(0x4272A385), + QFC(0x41058BC6), + QFC(0x3F962FB8), + QFC(0x043889C6), + QFC(0x04083FEC), + QFC(0x03D8AFE6), + QFC(0x03A966BC), + QFC(0xFFE940F4), + QFC(0xFFE9CA76), + QFC(0xFFEA9192), + QFC(0xFFEB50B2), + /*------------- 11 .. 8 ---------------*/ + QFC(0xFF975C01), + QFC(0xFF7EE3F1), + QFC(0xFF6542D1), + QFC(0xFF4AABC8), + QFC(0xE0FC421E), + QFC(0xDFA93AB5), + QFC(0xDE529086), + QFC(0xDCF898FB), + QFC(0x3E25B17E), + QFC(0x3CB41219), + QFC(0x3B415115), + QFC(0x39CE0477), + QFC(0x037AD438), + QFC(0x034D01F1), + QFC(0x03201116), + QFC(0x02F3E48D), + QFC(0xFFEBE77B), + QFC(0xFFECC31B), + QFC(0xFFED651D), + QFC(0xFFEE1650), + /*------------- 7 .. 4 ---------------*/ + QFC(0xFF2EF725), + QFC(0xFF120D70), + QFC(0xFEF3F6AB), + QFC(0xFED4BEC3), + QFC(0xDB9B5B12), + QFC(0xDA3B176A), + QFC(0xD8D7F21F), + QFC(0xD7722F04), + QFC(0x385A49C4), + QFC(0x36E69691), + QFC(0x3572EC70), + QFC(0x33FF670E), + QFC(0x02C89901), + QFC(0x029E35B4), + QFC(0x0274BA43), + QFC(0x024BF7A1), + QFC(0xFFEEDFA4), + QFC(0xFFEF7B8B), + QFC(0xFFEFF6CA), + QFC(0xFFF0065D), + /*------------- 3 .. 0 ---------------*/ + QFC(0xFEB48D0D), + QFC(0xFE933DC0), + QFC(0xFE70B8D1), + QFC(0xFE4D1BE3), + QFC(0xD60A46E5), + QFC(0xD49FD55F), + QFC(0xD3337B3D), + QFC(0xD1C58ACE), + QFC(0x328CC6F0), + QFC(0x311AF3A4), + QFC(0x2FAA221C), + QFC(0x2E3A7532), + QFC(0x02244A25), + QFC(0x01FD3BA0), + QFC(0x01D78BFC), + QFC(0x01B2E41D), + QFC(0xFFEFC9B9), + QFC(0xFFED978A), + QFC(0xFFEDE50E), + QFC(0x00000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_cos64[] = { + QTC(0x7ff62182), QTC(0x7fa736b4), QTC(0x7f0991c4), QTC(0x7e1d93ea), + QTC(0x7ce3ceb2), QTC(0x7b5d039e), QTC(0x798a23b1), QTC(0x776c4edb), + QTC(0x7504d345), QTC(0x72552c85), QTC(0x6f5f02b2), QTC(0x6c242960), + QTC(0x68a69e81), QTC(0x64e88926), QTC(0x60ec3830), QTC(0x5cb420e0), + QTC(0x5842dd54), QTC(0x539b2af0), QTC(0x4ebfe8a5), QTC(0x49b41533), + QTC(0x447acd50), QTC(0x3f1749b8), QTC(0x398cdd32), QTC(0x33def287), + QTC(0x2e110a62), QTC(0x2826b928), QTC(0x2223a4c5), QTC(0x1c0b826a), + QTC(0x15e21445), QTC(0x0fab272b), QTC(0x096a9049), QTC(0x03242abf), + QTC(0xfcdbd541), QTC(0xf6956fb7), QTC(0xf054d8d5), QTC(0xea1debbb), + QTC(0xe3f47d96), QTC(0xdddc5b3b), QTC(0xd7d946d8), QTC(0xd1eef59e), + QTC(0xcc210d79), QTC(0xc67322ce), QTC(0xc0e8b648), QTC(0xbb8532b0), + QTC(0xb64beacd), QTC(0xb140175b), QTC(0xac64d510), QTC(0xa7bd22ac), + QTC(0xa34bdf20), QTC(0x9f13c7d0), QTC(0x9b1776da), QTC(0x9759617f), + QTC(0x93dbd6a0), QTC(0x90a0fd4e), QTC(0x8daad37b), QTC(0x8afb2cbb), + QTC(0x8893b125), QTC(0x8675dc4f), QTC(0x84a2fc62), QTC(0x831c314e), + QTC(0x81e26c16), QTC(0x80f66e3c), QTC(0x8058c94c), QTC(0x8009de7e), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_sin64[] = { + QTC(0x03242abf), QTC(0x096a9049), QTC(0x0fab272b), QTC(0x15e21445), + QTC(0x1c0b826a), QTC(0x2223a4c5), QTC(0x2826b928), QTC(0x2e110a62), + QTC(0x33def287), QTC(0x398cdd32), QTC(0x3f1749b8), QTC(0x447acd50), + QTC(0x49b41533), QTC(0x4ebfe8a5), QTC(0x539b2af0), QTC(0x5842dd54), + QTC(0x5cb420e0), QTC(0x60ec3830), QTC(0x64e88926), QTC(0x68a69e81), + QTC(0x6c242960), QTC(0x6f5f02b2), QTC(0x72552c85), QTC(0x7504d345), + QTC(0x776c4edb), QTC(0x798a23b1), QTC(0x7b5d039e), QTC(0x7ce3ceb2), + QTC(0x7e1d93ea), QTC(0x7f0991c4), QTC(0x7fa736b4), QTC(0x7ff62182), + QTC(0x7ff62182), QTC(0x7fa736b4), QTC(0x7f0991c4), QTC(0x7e1d93ea), + QTC(0x7ce3ceb2), QTC(0x7b5d039e), QTC(0x798a23b1), QTC(0x776c4edb), + QTC(0x7504d345), QTC(0x72552c85), QTC(0x6f5f02b2), QTC(0x6c242960), + QTC(0x68a69e81), QTC(0x64e88926), QTC(0x60ec3830), QTC(0x5cb420e0), + QTC(0x5842dd54), QTC(0x539b2af0), QTC(0x4ebfe8a5), QTC(0x49b41533), + QTC(0x447acd50), QTC(0x3f1749b8), QTC(0x398cdd32), QTC(0x33def287), + QTC(0x2e110a62), QTC(0x2826b928), QTC(0x2223a4c5), QTC(0x1c0b826a), + QTC(0x15e21445), QTC(0x0fab272b), QTC(0x096a9049), QTC(0x03242abf), +}; + +/* + * Low Delay QMF aka CLDFB + */ + +#if defined(QMF_COEFF_16BIT) +#define QTCFLLD(x) FL2FXCONST_SGL(x / (float)(1 << QMF_CLDFB_PFT_SCALE)) +#define QTCFLLDT(x) FL2FXCONST_SGL(x) +#else +#define QTCFLLD(x) FL2FXCONST_DBL(x / (float)(1 << QMF_CLDFB_PFT_SCALE)) +#define QTCFLLDT(x) FL2FXCONST_DBL(x) +#endif + +#ifndef LOW_POWER_SBR_ONLY +/*! + \name QMF-Twiddle + \brief QMF twiddle factors + + L=32, gain=2.0, angle = 0.75 +*/ +/* sin/cos (angle) / 2 */ +const FIXP_QTW qmf_phaseshift_cos32_cldfb_ana[32] = { + /* analysis twiddle table */ + QTCFLLDT(-7.071067e-01), QTCFLLDT(7.071070e-01), QTCFLLDT(7.071064e-01), + QTCFLLDT(-7.071073e-01), QTCFLLDT(-7.071061e-01), QTCFLLDT(7.071076e-01), + QTCFLLDT(7.071058e-01), QTCFLLDT(-7.071080e-01), QTCFLLDT(-7.071055e-01), + QTCFLLDT(7.071083e-01), QTCFLLDT(7.071052e-01), QTCFLLDT(-7.071086e-01), + QTCFLLDT(-7.071049e-01), QTCFLLDT(7.071089e-01), QTCFLLDT(7.071046e-01), + QTCFLLDT(-7.071092e-01), QTCFLLDT(-7.071042e-01), QTCFLLDT(7.071095e-01), + QTCFLLDT(7.071039e-01), QTCFLLDT(-7.071098e-01), QTCFLLDT(-7.071036e-01), + QTCFLLDT(7.071101e-01), QTCFLLDT(7.071033e-01), QTCFLLDT(-7.071104e-01), + QTCFLLDT(-7.071030e-01), QTCFLLDT(7.071107e-01), QTCFLLDT(7.071027e-01), + QTCFLLDT(-7.071111e-01), QTCFLLDT(-7.071024e-01), QTCFLLDT(7.071114e-01), + QTCFLLDT(7.071021e-01), QTCFLLDT(-7.071117e-01), +}; + +const FIXP_QTW qmf_phaseshift_cos32_cldfb_syn[32] = { + /* synthesis twiddle table */ + QTCFLLDT(7.071067e-01), QTCFLLDT(-7.071070e-01), QTCFLLDT(-7.071064e-01), + QTCFLLDT(7.071073e-01), QTCFLLDT(7.071061e-01), QTCFLLDT(-7.071076e-01), + QTCFLLDT(-7.071058e-01), QTCFLLDT(7.071080e-01), QTCFLLDT(7.071055e-01), + QTCFLLDT(-7.071083e-01), QTCFLLDT(-7.071052e-01), QTCFLLDT(7.071086e-01), + QTCFLLDT(7.071049e-01), QTCFLLDT(-7.071089e-01), QTCFLLDT(-7.071046e-01), + QTCFLLDT(7.071092e-01), QTCFLLDT(7.071042e-01), QTCFLLDT(-7.071095e-01), + QTCFLLDT(-7.071039e-01), QTCFLLDT(7.071098e-01), QTCFLLDT(7.071036e-01), + QTCFLLDT(-7.071101e-01), QTCFLLDT(-7.071033e-01), QTCFLLDT(7.071104e-01), + QTCFLLDT(7.071030e-01), QTCFLLDT(-7.071107e-01), QTCFLLDT(-7.071027e-01), + QTCFLLDT(7.071111e-01), QTCFLLDT(7.071024e-01), QTCFLLDT(-7.071114e-01), + QTCFLLDT(-7.071021e-01), QTCFLLDT(7.071117e-01), +}; + +const FIXP_QTW qmf_phaseshift_sin32_cldfb[32] = { + QTCFLLDT(7.071068e-01), QTCFLLDT(7.071065e-01), QTCFLLDT(-7.071072e-01), + QTCFLLDT(-7.071062e-01), QTCFLLDT(7.071075e-01), QTCFLLDT(7.071059e-01), + QTCFLLDT(-7.071078e-01), QTCFLLDT(-7.071056e-01), QTCFLLDT(7.071081e-01), + QTCFLLDT(7.071053e-01), QTCFLLDT(-7.071084e-01), QTCFLLDT(-7.071050e-01), + QTCFLLDT(7.071087e-01), QTCFLLDT(7.071047e-01), QTCFLLDT(-7.071090e-01), + QTCFLLDT(-7.071044e-01), QTCFLLDT(7.071093e-01), QTCFLLDT(7.071041e-01), + QTCFLLDT(-7.071096e-01), QTCFLLDT(-7.071038e-01), QTCFLLDT(7.071099e-01), + QTCFLLDT(7.071034e-01), QTCFLLDT(-7.071103e-01), QTCFLLDT(-7.071031e-01), + QTCFLLDT(7.071106e-01), QTCFLLDT(7.071028e-01), QTCFLLDT(-7.071109e-01), + QTCFLLDT(-7.071025e-01), QTCFLLDT(7.071112e-01), QTCFLLDT(7.071022e-01), + QTCFLLDT(-7.071115e-01), QTCFLLDT(-7.071019e-01), +}; + +/* twiddles for X=(8,16) band qmf are copied from float simpleplayer + * implementation: qmf_phaseshift_cosX_cldfb_ana = + * QMFlib_twiddle3RealX_SBRLD_A qmf_phaseshift_cosX_cldfb_syn = + * -(QMFlib_twiddle3RealX_SBRLD_A) qmf_phaseshift_sinX_cldfb = + * QMFlib_twiddle3ImagX_SBRLD_A + */ + +/* cos ((n + 0.5)*pi*angle/L) , order = 159, L=16 */ +const FIXP_QTW qmf_phaseshift_cos16_cldfb_ana[16] = { + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(-0.7071067812), +}; + +/* cos ((n + 0.5)*pi*angle/L) , order = 159, L=16 */ +const FIXP_QTW qmf_phaseshift_cos16_cldfb_syn[16] = { + QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(0.7071067812), +}; + +/* sin ((n + 0.5)*pi*angle/L) , order = 159, L=16 */ +const FIXP_QTW qmf_phaseshift_sin16_cldfb[16] = { + QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(-0.7071067812), +}; + +/* cos ((n + 0.5)*pi*angle/L) , order = 79, L=8 */ +const FIXP_QTW qmf_phaseshift_cos8_cldfb_ana[8] = { + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), +}; + +const FIXP_QTW qmf_phaseshift_cos8_cldfb_syn[8] = { + QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), +}; + +/* sin ((n + 0.5)*pi*angle/L) , order = 79, L=8 */ +const FIXP_QTW qmf_phaseshift_sin8_cldfb[8] = { + QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), +}; + +/* sin/cos (angle) / 128 */ +const FIXP_QTW qmf_phaseshift_cos64_cldfb[64] = { + QTCFLLDT(7.071068e-01), QTCFLLDT(-7.071066e-01), QTCFLLDT(-7.071070e-01), + QTCFLLDT(7.071065e-01), QTCFLLDT(7.071072e-01), QTCFLLDT(-7.071063e-01), + QTCFLLDT(-7.071074e-01), QTCFLLDT(7.071061e-01), QTCFLLDT(7.071075e-01), + QTCFLLDT(-7.071059e-01), QTCFLLDT(-7.071078e-01), QTCFLLDT(7.071057e-01), + QTCFLLDT(7.071080e-01), QTCFLLDT(-7.071055e-01), QTCFLLDT(-7.071081e-01), + QTCFLLDT(7.071053e-01), QTCFLLDT(7.071083e-01), QTCFLLDT(-7.071052e-01), + QTCFLLDT(-7.071085e-01), QTCFLLDT(7.071050e-01), QTCFLLDT(7.071087e-01), + QTCFLLDT(-7.071048e-01), QTCFLLDT(-7.071089e-01), QTCFLLDT(7.071046e-01), + QTCFLLDT(7.071090e-01), QTCFLLDT(-7.071044e-01), QTCFLLDT(-7.071092e-01), + QTCFLLDT(7.071042e-01), QTCFLLDT(7.071095e-01), QTCFLLDT(-7.071040e-01), + QTCFLLDT(-7.071096e-01), QTCFLLDT(7.071038e-01), QTCFLLDT(7.071098e-01), + QTCFLLDT(-7.071037e-01), QTCFLLDT(-7.071100e-01), QTCFLLDT(7.071035e-01), + QTCFLLDT(7.071102e-01), QTCFLLDT(-7.071033e-01), QTCFLLDT(-7.071103e-01), + QTCFLLDT(7.071031e-01), QTCFLLDT(7.071105e-01), QTCFLLDT(-7.071030e-01), + QTCFLLDT(-7.071107e-01), QTCFLLDT(7.071028e-01), QTCFLLDT(7.071109e-01), + QTCFLLDT(-7.071025e-01), QTCFLLDT(-7.071111e-01), QTCFLLDT(7.071024e-01), + QTCFLLDT(7.071113e-01), QTCFLLDT(-7.071022e-01), QTCFLLDT(-7.071115e-01), + QTCFLLDT(7.071020e-01), QTCFLLDT(7.071117e-01), QTCFLLDT(-7.071018e-01), + QTCFLLDT(-7.071118e-01), QTCFLLDT(7.071016e-01), QTCFLLDT(7.071120e-01), + QTCFLLDT(-7.071015e-01), QTCFLLDT(-7.071122e-01), QTCFLLDT(7.071013e-01), + QTCFLLDT(7.071124e-01), QTCFLLDT(-7.071011e-01), QTCFLLDT(-7.071126e-01), + QTCFLLDT(7.071009e-01), +}; +const FIXP_QTW qmf_phaseshift_sin64_cldfb[64] = { + QTCFLLDT(7.071067e-01), QTCFLLDT(7.071069e-01), QTCFLLDT(-7.071065e-01), + QTCFLLDT(-7.071071e-01), QTCFLLDT(7.071064e-01), QTCFLLDT(7.071073e-01), + QTCFLLDT(-7.071062e-01), QTCFLLDT(-7.071075e-01), QTCFLLDT(7.071060e-01), + QTCFLLDT(7.071077e-01), QTCFLLDT(-7.071058e-01), QTCFLLDT(-7.071078e-01), + QTCFLLDT(7.071056e-01), QTCFLLDT(7.071080e-01), QTCFLLDT(-7.071055e-01), + QTCFLLDT(-7.071082e-01), QTCFLLDT(7.071053e-01), QTCFLLDT(7.071084e-01), + QTCFLLDT(-7.071050e-01), QTCFLLDT(-7.071086e-01), QTCFLLDT(7.071049e-01), + QTCFLLDT(7.071088e-01), QTCFLLDT(-7.071047e-01), QTCFLLDT(-7.071090e-01), + QTCFLLDT(7.071045e-01), QTCFLLDT(7.071092e-01), QTCFLLDT(-7.071043e-01), + QTCFLLDT(-7.071093e-01), QTCFLLDT(7.071041e-01), QTCFLLDT(7.071095e-01), + QTCFLLDT(-7.071040e-01), QTCFLLDT(-7.071097e-01), QTCFLLDT(7.071038e-01), + QTCFLLDT(7.071099e-01), QTCFLLDT(-7.071036e-01), QTCFLLDT(-7.071100e-01), + QTCFLLDT(7.071034e-01), QTCFLLDT(7.071103e-01), QTCFLLDT(-7.071032e-01), + QTCFLLDT(-7.071105e-01), QTCFLLDT(7.071030e-01), QTCFLLDT(7.071106e-01), + QTCFLLDT(-7.071028e-01), QTCFLLDT(-7.071108e-01), QTCFLLDT(7.071027e-01), + QTCFLLDT(7.071110e-01), QTCFLLDT(-7.071025e-01), QTCFLLDT(-7.071112e-01), + QTCFLLDT(7.071023e-01), QTCFLLDT(7.071114e-01), QTCFLLDT(-7.071021e-01), + QTCFLLDT(-7.071115e-01), QTCFLLDT(7.071019e-01), QTCFLLDT(7.071117e-01), + QTCFLLDT(-7.071017e-01), QTCFLLDT(-7.071120e-01), QTCFLLDT(7.071015e-01), + QTCFLLDT(7.071121e-01), QTCFLLDT(-7.071013e-01), QTCFLLDT(-7.071123e-01), + QTCFLLDT(7.071012e-01), QTCFLLDT(7.071125e-01), QTCFLLDT(-7.071010e-01), + QTCFLLDT(-7.071127e-01), +}; + +//@} + +#endif /* #ifdef LOW_POWER_SBR_ONLY */ + +/*! + \name QMF + \brief QMF-Table + 64 channels, N = 640, optimized by PE 010516 + + The coeffs are rearranged compared with the reference in the following + way: + sbr_qmf_64[0] = sbr_qmf_64_reference[0]; + sbr_qmf_64[1] = sbr_qmf_64_reference[128]; + sbr_qmf_64[2] = sbr_qmf_64_reference[256]; + sbr_qmf_64[3] = sbr_qmf_64_reference[384]; + sbr_qmf_64[4] = sbr_qmf_64_reference[512]; + + sbr_qmf_64[5] = sbr_qmf_64_reference[1]; + sbr_qmf_64[6] = sbr_qmf_64_reference[129]; + sbr_qmf_64[7] = sbr_qmf_64_reference[257]; + sbr_qmf_64[8] = sbr_qmf_64_reference[385]; + sbr_qmf_64[9] = sbr_qmf_64_reference[513]; + . + . + . + sbr_qmf_64[635] = sbr_qmf_64_reference[127] + sbr_qmf_64[636] = sbr_qmf_64_reference[255]; + sbr_qmf_64[637] = sbr_qmf_64_reference[383]; + sbr_qmf_64[638] = sbr_qmf_64_reference[511]; + sbr_qmf_64[639] = sbr_qmf_64_reference[639]; + + + Symmetric properties of qmf coeffs: + + Use point symmetry: + + sbr_qmf_64_640_qmf[320..634] = p_64_640_qmf[314..0] + + Max sum of all FIR filter absolute coefficients is: 0x7FF5B201 + thus, the filter output is not required to be scaled. + + \showinitializer +*/ +//@{ + +LNK_SECTION_CONSTDATA_L1 +RAM_ALIGN +const FIXP_PFT qmf_cldfb_640[QMF640_CLDFB_PFT_TABLE_SIZE] = { + QTCFLLD(6.571760e-07), QTCFLLD(-8.010079e-06), QTCFLLD(-1.250743e-03), + QTCFLLD(8.996371e-03), QTCFLLD(5.128557e-01), QTCFLLD(4.118360e-07), + QTCFLLD(-1.469933e-05), QTCFLLD(-1.194743e-03), QTCFLLD(9.640299e-03), + QTCFLLD(5.299510e-01), QTCFLLD(8.109952e-07), QTCFLLD(4.840578e-06), + QTCFLLD(-1.151796e-03), QTCFLLD(1.033126e-02), QTCFLLD(5.470652e-01), + QTCFLLD(7.099633e-07), QTCFLLD(7.167101e-06), QTCFLLD(-1.099001e-03), + QTCFLLD(1.106959e-02), QTCFLLD(5.641523e-01), QTCFLLD(6.834210e-07), + QTCFLLD(1.088325e-05), QTCFLLD(-1.047655e-03), QTCFLLD(1.186211e-02), + QTCFLLD(5.811993e-01), QTCFLLD(4.292862e-07), QTCFLLD(1.013260e-05), + QTCFLLD(-9.862027e-04), QTCFLLD(1.270747e-02), QTCFLLD(5.981877e-01), + QTCFLLD(-5.426597e-09), QTCFLLD(5.869707e-06), QTCFLLD(-9.294665e-04), + QTCFLLD(1.361072e-02), QTCFLLD(6.151031e-01), QTCFLLD(6.355303e-08), + QTCFLLD(1.125135e-05), QTCFLLD(-9.767709e-04), QTCFLLD(1.456209e-02), + QTCFLLD(6.319284e-01), QTCFLLD(5.490570e-07), QTCFLLD(2.015445e-05), + QTCFLLD(-1.040598e-03), QTCFLLD(1.557759e-02), QTCFLLD(6.486438e-01), + QTCFLLD(1.620171e-06), QTCFLLD(2.800456e-05), QTCFLLD(-1.146268e-03), + QTCFLLD(1.665188e-02), QTCFLLD(6.652304e-01), QTCFLLD(-6.025110e-10), + QTCFLLD(8.975978e-06), QTCFLLD(-1.292866e-03), QTCFLLD(1.778249e-02), + QTCFLLD(6.816668e-01), QTCFLLD(-6.325664e-10), QTCFLLD(8.563820e-06), + QTCFLLD(-1.196638e-03), QTCFLLD(1.897506e-02), QTCFLLD(6.979337e-01), + QTCFLLD(-4.013525e-09), QTCFLLD(1.168895e-05), QTCFLLD(-9.726699e-04), + QTCFLLD(2.023525e-02), QTCFLLD(7.140087e-01), QTCFLLD(-4.244091e-09), + QTCFLLD(7.300589e-06), QTCFLLD(-8.029620e-04), QTCFLLD(2.156305e-02), + QTCFLLD(7.298746e-01), QTCFLLD(-1.846548e-08), QTCFLLD(3.965364e-06), + QTCFLLD(-6.754936e-04), QTCFLLD(2.296471e-02), QTCFLLD(7.455112e-01), + QTCFLLD(-3.870537e-09), QTCFLLD(1.374896e-06), QTCFLLD(-5.791145e-04), + QTCFLLD(2.443434e-02), QTCFLLD(7.609051e-01), QTCFLLD(-8.883499e-10), + QTCFLLD(3.798520e-07), QTCFLLD(-4.733148e-04), QTCFLLD(2.597957e-02), + QTCFLLD(7.760386e-01), QTCFLLD(5.303528e-08), QTCFLLD(4.469729e-06), + QTCFLLD(-2.998740e-04), QTCFLLD(2.760091e-02), QTCFLLD(7.908995e-01), + QTCFLLD(7.391974e-08), QTCFLLD(2.461877e-05), QTCFLLD(7.882620e-05), + QTCFLLD(2.931526e-02), QTCFLLD(8.054701e-01), QTCFLLD(1.723217e-09), + QTCFLLD(4.005269e-05), QTCFLLD(4.708010e-04), QTCFLLD(3.110861e-02), + QTCFLLD(8.197387e-01), QTCFLLD(2.443085e-07), QTCFLLD(5.272982e-05), + QTCFLLD(8.089812e-04), QTCFLLD(3.298151e-02), QTCFLLD(8.336864e-01), + QTCFLLD(1.387567e-08), QTCFLLD(4.939392e-05), QTCFLLD(1.127142e-03), + QTCFLLD(3.493300e-02), QTCFLLD(8.472987e-01), QTCFLLD(-5.690531e-06), + QTCFLLD(-4.256442e-05), QTCFLLD(1.417367e-03), QTCFLLD(3.696343e-02), + QTCFLLD(8.605543e-01), QTCFLLD(3.629067e-06), QTCFLLD(6.582328e-05), + QTCFLLD(1.725030e-03), QTCFLLD(3.907138e-02), QTCFLLD(8.734367e-01), + QTCFLLD(-5.393556e-08), QTCFLLD(6.481921e-05), QTCFLLD(1.948069e-03), + QTCFLLD(4.125570e-02), QTCFLLD(8.859232e-01), QTCFLLD(1.349944e-07), + QTCFLLD(3.367998e-05), QTCFLLD(2.033465e-03), QTCFLLD(4.355568e-02), + QTCFLLD(8.979959e-01), QTCFLLD(7.326611e-09), QTCFLLD(4.694252e-05), + QTCFLLD(2.239143e-03), QTCFLLD(4.599068e-02), QTCFLLD(9.096311e-01), + QTCFLLD(2.399696e-07), QTCFLLD(6.904415e-05), QTCFLLD(2.470456e-03), + QTCFLLD(4.849285e-02), QTCFLLD(9.208195e-01), QTCFLLD(3.330982e-07), + QTCFLLD(5.643103e-05), QTCFLLD(2.630472e-03), QTCFLLD(5.105621e-02), + QTCFLLD(9.315442e-01), QTCFLLD(4.767794e-07), QTCFLLD(7.095887e-05), + QTCFLLD(2.703019e-03), QTCFLLD(5.368313e-02), QTCFLLD(9.417976e-01), + QTCFLLD(3.428661e-07), QTCFLLD(7.872593e-05), QTCFLLD(2.729137e-03), + QTCFLLD(5.637219e-02), QTCFLLD(9.515675e-01), QTCFLLD(8.676848e-06), + QTCFLLD(2.666445e-04), QTCFLLD(2.719749e-03), QTCFLLD(5.911363e-02), + QTCFLLD(9.608520e-01), QTCFLLD(2.722296e-05), QTCFLLD(5.822201e-04), + QTCFLLD(2.530907e-03), QTCFLLD(6.192693e-02), QTCFLLD(9.696426e-01), + QTCFLLD(3.575651e-07), QTCFLLD(7.870355e-05), QTCFLLD(2.225524e-03), + QTCFLLD(6.480449e-02), QTCFLLD(9.779405e-01), QTCFLLD(6.293002e-07), + QTCFLLD(7.245096e-05), QTCFLLD(1.891972e-03), QTCFLLD(6.771675e-02), + QTCFLLD(9.857388e-01), QTCFLLD(1.070243e-06), QTCFLLD(7.194151e-05), + QTCFLLD(1.557112e-03), QTCFLLD(7.064948e-02), QTCFLLD(9.930380e-01), + QTCFLLD(-3.225913e-07), QTCFLLD(-7.679955e-05), QTCFLLD(1.194731e-03), + QTCFLLD(7.360559e-02), QTCFLLD(9.998286e-01), QTCFLLD(-9.597516e-09), + QTCFLLD(-6.093373e-05), QTCFLLD(6.415402e-04), QTCFLLD(7.657650e-02), + QTCFLLD(1.006109e+00), QTCFLLD(-8.908041e-08), QTCFLLD(-1.721347e-05), + QTCFLLD(1.092526e-04), QTCFLLD(7.955571e-02), QTCFLLD(1.011868e+00), + QTCFLLD(-2.285563e-05), QTCFLLD(-8.882305e-05), QTCFLLD(2.934876e-04), + QTCFLLD(8.251962e-02), QTCFLLD(1.017100e+00), QTCFLLD(1.013575e-05), + QTCFLLD(6.418658e-05), QTCFLLD(5.721223e-04), QTCFLLD(8.547716e-02), + QTCFLLD(1.021799e+00), QTCFLLD(-1.706941e-05), QTCFLLD(1.769262e-04), + QTCFLLD(6.976561e-04), QTCFLLD(8.841813e-02), QTCFLLD(1.025967e+00), + QTCFLLD(1.356728e-06), QTCFLLD(2.206341e-05), QTCFLLD(7.376101e-04), + QTCFLLD(9.133591e-02), QTCFLLD(1.029601e+00), QTCFLLD(-1.398913e-08), + QTCFLLD(-6.538879e-06), QTCFLLD(7.154124e-04), QTCFLLD(9.421624e-02), + QTCFLLD(1.032713e+00), QTCFLLD(3.552992e-08), QTCFLLD(-1.052707e-05), + QTCFLLD(7.139920e-04), QTCFLLD(9.705240e-02), QTCFLLD(1.035312e+00), + QTCFLLD(4.211177e-07), QTCFLLD(-9.075431e-06), QTCFLLD(6.944123e-04), + QTCFLLD(9.982958e-02), QTCFLLD(1.037422e+00), QTCFLLD(5.433719e-07), + QTCFLLD(-1.748285e-05), QTCFLLD(6.766320e-04), QTCFLLD(1.025398e-01), + QTCFLLD(1.039062e+00), QTCFLLD(8.226600e-08), QTCFLLD(-3.498286e-05), + QTCFLLD(6.887784e-04), QTCFLLD(1.051642e-01), QTCFLLD(1.040262e+00), + QTCFLLD(1.272705e-07), QTCFLLD(-4.489491e-05), QTCFLLD(6.673250e-04), + QTCFLLD(1.076972e-01), QTCFLLD(1.041043e+00), QTCFLLD(2.542598e-07), + QTCFLLD(-5.449816e-05), QTCFLLD(5.970697e-04), QTCFLLD(1.101216e-01), + QTCFLLD(1.041434e+00), QTCFLLD(6.322770e-07), QTCFLLD(-5.874199e-05), + QTCFLLD(4.749931e-04), QTCFLLD(1.124296e-01), QTCFLLD(1.041443e+00), + QTCFLLD(2.801882e-08), QTCFLLD(-7.934510e-05), QTCFLLD(3.189336e-04), + QTCFLLD(1.146042e-01), QTCFLLD(1.041087e+00), QTCFLLD(5.891904e-07), + QTCFLLD(-8.039232e-05), QTCFLLD(1.218226e-04), QTCFLLD(1.166399e-01), + QTCFLLD(1.040350e+00), QTCFLLD(7.301957e-07), QTCFLLD(-9.907631e-05), + QTCFLLD(-1.324292e-04), QTCFLLD(1.185243e-01), QTCFLLD(1.039228e+00), + QTCFLLD(-4.518603e-06), QTCFLLD(-2.217025e-04), QTCFLLD(-4.268575e-04), + QTCFLLD(1.202546e-01), QTCFLLD(1.037683e+00), QTCFLLD(-3.561585e-06), + QTCFLLD(-2.415166e-04), QTCFLLD(-7.804546e-04), QTCFLLD(1.218184e-01), + QTCFLLD(1.035694e+00), QTCFLLD(-1.074717e-07), QTCFLLD(-2.123672e-04), + QTCFLLD(-1.156680e-03), QTCFLLD(1.232132e-01), QTCFLLD(1.033206e+00), + QTCFLLD(1.323268e-06), QTCFLLD(-2.078299e-04), QTCFLLD(-1.525819e-03), + QTCFLLD(1.244270e-01), QTCFLLD(1.030199e+00), QTCFLLD(3.377815e-06), + QTCFLLD(-1.885286e-04), QTCFLLD(-1.914115e-03), QTCFLLD(1.254605e-01), + QTCFLLD(1.026616e+00), QTCFLLD(5.161607e-06), QTCFLLD(-1.728673e-04), + QTCFLLD(-2.292814e-03), QTCFLLD(1.262996e-01), QTCFLLD(1.022470e+00), + QTCFLLD(5.924001e-06), QTCFLLD(-1.744842e-04), QTCFLLD(-2.658042e-03), + QTCFLLD(1.269416e-01), QTCFLLD(1.017729e+00), QTCFLLD(6.310208e-06), + QTCFLLD(-1.784193e-04), QTCFLLD(-3.000423e-03), QTCFLLD(1.273648e-01), + QTCFLLD(1.012508e+00), QTCFLLD(3.357219e-06), QTCFLLD(-2.131406e-04), + QTCFLLD(-3.318858e-03), QTCFLLD(1.275561e-01), QTCFLLD(1.006893e+00), + QTCFLLD(5.189087e-06), QTCFLLD(-2.078886e-04), QTCFLLD(-3.597476e-03), + QTCFLLD(1.274568e-01), QTCFLLD(1.001463e+00), QTCFLLD(4.178050e-06), + QTCFLLD(-4.663778e-05), QTCFLLD(-3.870852e-03), QTCFLLD(1.273591e-01), + QTCFLLD(9.927544e-01), QTCFLLD(5.364807e-06), QTCFLLD(-5.889277e-06), + QTCFLLD(-4.135130e-03), QTCFLLD(1.272499e-01), QTCFLLD(9.807692e-01), + QTCFLLD(4.083719e-06), QTCFLLD(-1.774108e-05), QTCFLLD(-4.351668e-03), + QTCFLLD(1.268281e-01), QTCFLLD(9.690017e-01), QTCFLLD(3.567581e-06), + QTCFLLD(-2.599468e-08), QTCFLLD(-4.517190e-03), QTCFLLD(1.261262e-01), + QTCFLLD(9.568886e-01), QTCFLLD(3.262754e-06), QTCFLLD(1.260640e-05), + QTCFLLD(-4.636228e-03), QTCFLLD(1.251477e-01), QTCFLLD(9.443803e-01), + QTCFLLD(2.041128e-06), QTCFLLD(2.364519e-05), QTCFLLD(-4.704321e-03), + QTCFLLD(1.238869e-01), QTCFLLD(9.313874e-01), QTCFLLD(-2.567965e-08), + QTCFLLD(2.806963e-05), QTCFLLD(-4.722568e-03), QTCFLLD(1.223371e-01), + QTCFLLD(9.179666e-01), QTCFLLD(2.714879e-07), QTCFLLD(4.493916e-05), + QTCFLLD(-4.663276e-03), QTCFLLD(1.204854e-01), QTCFLLD(9.041286e-01), + QTCFLLD(2.150884e-06), QTCFLLD(5.408155e-05), QTCFLLD(-4.554811e-03), + QTCFLLD(1.183233e-01), QTCFLLD(8.899474e-01), QTCFLLD(5.818595e-06), + QTCFLLD(3.759630e-05), QTCFLLD(-4.369554e-03), QTCFLLD(1.158359e-01), + QTCFLLD(8.754641e-01), QTCFLLD(-1.686137e-09), QTCFLLD(2.515118e-05), + QTCFLLD(-4.091033e-03), QTCFLLD(1.130180e-01), QTCFLLD(8.607492e-01), + QTCFLLD(-1.775191e-09), QTCFLLD(2.406517e-05), QTCFLLD(-3.794425e-03), + QTCFLLD(1.098551e-01), QTCFLLD(8.458450e-01), QTCFLLD(-2.222072e-09), + QTCFLLD(3.628511e-05), QTCFLLD(-3.460363e-03), QTCFLLD(1.063455e-01), + QTCFLLD(8.308040e-01), QTCFLLD(-1.280675e-08), QTCFLLD(2.241546e-05), + QTCFLLD(-3.064311e-03), QTCFLLD(1.024805e-01), QTCFLLD(8.156523e-01), + QTCFLLD(-6.977078e-08), QTCFLLD(1.499170e-05), QTCFLLD(-2.621537e-03), + QTCFLLD(9.826251e-02), QTCFLLD(8.004165e-01), QTCFLLD(-1.409927e-08), + QTCFLLD(5.009913e-06), QTCFLLD(-2.124648e-03), QTCFLLD(9.368652e-02), + QTCFLLD(7.851012e-01), QTCFLLD(-2.986489e-09), QTCFLLD(1.277184e-06), + QTCFLLD(-1.594861e-03), QTCFLLD(8.875756e-02), QTCFLLD(7.697093e-01), + QTCFLLD(1.876022e-07), QTCFLLD(1.580189e-05), QTCFLLD(-1.061499e-03), + QTCFLLD(8.347151e-02), QTCFLLD(7.542294e-01), QTCFLLD(1.737277e-07), + QTCFLLD(5.533953e-05), QTCFLLD(-6.169855e-04), QTCFLLD(7.783300e-02), + QTCFLLD(7.386515e-01), QTCFLLD(3.818589e-09), QTCFLLD(8.870182e-05), + QTCFLLD(-2.004823e-04), QTCFLLD(7.184074e-02), QTCFLLD(7.229599e-01), + QTCFLLD(5.143615e-07), QTCFLLD(1.035783e-04), QTCFLLD(2.048499e-04), + QTCFLLD(6.550209e-02), QTCFLLD(7.071448e-01), QTCFLLD(2.820292e-08), + QTCFLLD(9.990758e-05), QTCFLLD(5.621721e-04), QTCFLLD(5.881297e-02), + QTCFLLD(6.911982e-01), QTCFLLD(4.677016e-06), QTCFLLD(1.181078e-04), + QTCFLLD(9.373975e-04), QTCFLLD(5.177965e-02), QTCFLLD(6.751199e-01), + QTCFLLD(3.361682e-06), QTCFLLD(2.126365e-05), QTCFLLD(1.344657e-03), + QTCFLLD(4.439684e-02), QTCFLLD(6.589149e-01), QTCFLLD(-4.880845e-08), + QTCFLLD(5.861800e-05), QTCFLLD(1.812176e-03), QTCFLLD(3.666943e-02), + QTCFLLD(6.425940e-01), QTCFLLD(2.267731e-07), QTCFLLD(5.021906e-05), + QTCFLLD(2.172866e-03), QTCFLLD(2.857528e-02), QTCFLLD(6.261725e-01), + QTCFLLD(5.158213e-09), QTCFLLD(4.150075e-05), QTCFLLD(1.985825e-03), + QTCFLLD(2.012237e-02), QTCFLLD(6.096690e-01), QTCFLLD(-2.066962e-07), + QTCFLLD(3.799972e-05), QTCFLLD(1.697653e-03), QTCFLLD(1.132324e-02), + QTCFLLD(5.930982e-01), QTCFLLD(4.883305e-07), QTCFLLD(6.606462e-05), + QTCFLLD(1.471167e-03), QTCFLLD(2.184257e-03), QTCFLLD(5.764735e-01), + QTCFLLD(8.254430e-07), QTCFLLD(9.755685e-05), QTCFLLD(1.232134e-03), + QTCFLLD(-7.298198e-03), QTCFLLD(5.598052e-01), QTCFLLD(9.464783e-07), + QTCFLLD(1.831121e-04), QTCFLLD(8.990256e-04), QTCFLLD(-1.711324e-02), + QTCFLLD(5.430990e-01), QTCFLLD(-1.232693e-05), QTCFLLD(-5.901618e-07), + QTCFLLD(6.150317e-04), QTCFLLD(-2.726484e-02), QTCFLLD(5.263554e-01), + QTCFLLD(3.867483e-05), QTCFLLD(-3.595054e-04), QTCFLLD(6.307841e-04), + QTCFLLD(-3.775928e-02), QTCFLLD(5.095721e-01), QTCFLLD(-9.870548e-07), + QTCFLLD(-1.815837e-04), QTCFLLD(4.366447e-04), QTCFLLD(-4.859006e-02), + QTCFLLD(4.927464e-01), QTCFLLD(-1.089501e-06), QTCFLLD(-9.204876e-05), + QTCFLLD(1.498232e-04), QTCFLLD(-5.973742e-02), QTCFLLD(4.758754e-01), + QTCFLLD(-1.569003e-06), QTCFLLD(-5.192444e-05), QTCFLLD(-9.099723e-05), + QTCFLLD(-7.120357e-02), QTCFLLD(4.589583e-01), QTCFLLD(-2.778618e-07), + QTCFLLD(6.487880e-05), QTCFLLD(-3.337967e-04), QTCFLLD(-8.298103e-02), + QTCFLLD(4.420014e-01), QTCFLLD(6.757015e-09), QTCFLLD(5.397065e-05), + QTCFLLD(-5.599348e-04), QTCFLLD(-9.506967e-02), QTCFLLD(4.250144e-01), + QTCFLLD(1.496436e-07), QTCFLLD(2.472024e-05), QTCFLLD(-7.677634e-04), + QTCFLLD(-1.074631e-01), QTCFLLD(4.080155e-01), QTCFLLD(2.068297e-05), + QTCFLLD(9.711682e-05), QTCFLLD(-9.730460e-04), QTCFLLD(-1.201629e-01), + QTCFLLD(3.910244e-01), QTCFLLD(-9.388963e-06), QTCFLLD(5.144969e-05), + QTCFLLD(-1.131860e-03), QTCFLLD(-1.331545e-01), QTCFLLD(3.740644e-01), + QTCFLLD(-1.402925e-05), QTCFLLD(-1.039264e-04), QTCFLLD(-1.283281e-03), + QTCFLLD(-1.464389e-01), QTCFLLD(3.571528e-01), QTCFLLD(-2.757611e-06), + QTCFLLD(2.853437e-06), QTCFLLD(-1.480543e-03), QTCFLLD(-1.600062e-01), + QTCFLLD(3.403074e-01), QTCFLLD(2.945239e-08), QTCFLLD(1.334091e-05), + QTCFLLD(-1.699161e-03), QTCFLLD(-1.738542e-01), QTCFLLD(3.235299e-01), + QTCFLLD(-7.873304e-08), QTCFLLD(2.443161e-05), QTCFLLD(-1.924845e-03), + QTCFLLD(-1.879712e-01), QTCFLLD(3.068187e-01), QTCFLLD(-9.897194e-07), + QTCFLLD(3.568555e-05), QTCFLLD(-2.152380e-03), QTCFLLD(-2.023548e-01), + QTCFLLD(2.901491e-01), QTCFLLD(-1.922074e-06), QTCFLLD(6.193370e-05), + QTCFLLD(-2.396404e-03), QTCFLLD(-2.169926e-01), QTCFLLD(2.734977e-01), + QTCFLLD(-2.765650e-07), QTCFLLD(1.176237e-04), QTCFLLD(-2.653819e-03), + QTCFLLD(-2.318815e-01), QTCFLLD(2.568176e-01), QTCFLLD(-4.636105e-07), + QTCFLLD(1.635906e-04), QTCFLLD(-2.927159e-03), QTCFLLD(-2.470098e-01), + QTCFLLD(2.400768e-01), QTCFLLD(-9.607069e-07), QTCFLLD(2.060394e-04), + QTCFLLD(-3.209093e-03), QTCFLLD(-2.623749e-01), QTCFLLD(2.232277e-01), + QTCFLLD(-1.907927e-06), QTCFLLD(2.346981e-04), QTCFLLD(-3.505531e-03), + QTCFLLD(-2.779638e-01), QTCFLLD(2.062605e-01), QTCFLLD(-1.551251e-08), + QTCFLLD(2.520607e-04), QTCFLLD(-3.811612e-03), QTCFLLD(-2.937725e-01), + QTCFLLD(1.891590e-01), QTCFLLD(-1.653464e-06), QTCFLLD(2.556450e-04), + QTCFLLD(-4.133640e-03), QTCFLLD(-3.097862e-01), QTCFLLD(1.719726e-01), + QTCFLLD(-2.043464e-06), QTCFLLD(3.157664e-04), QTCFLLD(-4.448993e-03), + QTCFLLD(-3.259994e-01), QTCFLLD(1.547461e-01), QTCFLLD(1.622786e-05), + QTCFLLD(6.205676e-04), QTCFLLD(-4.754192e-03), QTCFLLD(-3.423942e-01), + QTCFLLD(1.376150e-01), QTCFLLD(1.395221e-05), QTCFLLD(7.847840e-04), + QTCFLLD(-5.063851e-03), QTCFLLD(-3.589627e-01), QTCFLLD(1.206924e-01), + QTCFLLD(4.591010e-07), QTCFLLD(9.019129e-04), QTCFLLD(-5.394570e-03), + QTCFLLD(-3.756822e-01), QTCFLLD(1.042033e-01), QTCFLLD(-6.261944e-06), + QTCFLLD(1.054963e-03), QTCFLLD(-5.741103e-03), QTCFLLD(-3.925409e-01), + QTCFLLD(8.829745e-02), QTCFLLD(-1.606051e-05), QTCFLLD(1.089429e-03), + QTCFLLD(-6.109179e-03), QTCFLLD(-4.095160e-01), QTCFLLD(7.325979e-02), + QTCFLLD(-2.464228e-05), QTCFLLD(1.122503e-03), QTCFLLD(-6.500503e-03), + QTCFLLD(-4.265950e-01), QTCFLLD(5.918678e-02), QTCFLLD(-2.976824e-05), + QTCFLLD(1.177515e-03), QTCFLLD(-6.925141e-03), QTCFLLD(-4.437530e-01), + QTCFLLD(4.634696e-02), QTCFLLD(-3.177468e-05), QTCFLLD(1.226113e-03), + QTCFLLD(-7.380544e-03), QTCFLLD(-4.609829e-01), QTCFLLD(3.450719e-02), + QTCFLLD(-4.373302e-05), QTCFLLD(1.263569e-03), QTCFLLD(-7.876393e-03), + QTCFLLD(-4.782650e-01), QTCFLLD(2.353060e-02), QTCFLLD(-3.299004e-05), + QTCFLLD(1.287819e-03), QTCFLLD(-8.407749e-03), QTCFLLD(-4.956175e-01), + QTCFLLD(1.129580e-02), +}; + +RAM_ALIGN +const FIXP_PFT qmf_cldfb_320[QMF320_CLDFB_PFT_TABLE_SIZE] = { + QTCFLLD(5.345060e-07), QTCFLLD(-1.135471e-05), QTCFLLD(-1.222743e-03), + QTCFLLD(9.318335e-03), QTCFLLD(5.214033e-01), QTCFLLD(7.604792e-07), + QTCFLLD(6.003839e-06), QTCFLLD(-1.125398e-03), QTCFLLD(1.070043e-02), + QTCFLLD(5.556087e-01), QTCFLLD(5.563536e-07), QTCFLLD(1.050792e-05), + QTCFLLD(-1.016929e-03), QTCFLLD(1.228479e-02), QTCFLLD(5.896935e-01), + QTCFLLD(2.906322e-08), QTCFLLD(8.560527e-06), QTCFLLD(-9.531187e-04), + QTCFLLD(1.408640e-02), QTCFLLD(6.235157e-01), QTCFLLD(1.084614e-06), + QTCFLLD(2.407951e-05), QTCFLLD(-1.093433e-03), QTCFLLD(1.611474e-02), + QTCFLLD(6.569371e-01), QTCFLLD(-6.175387e-10), QTCFLLD(8.769899e-06), + QTCFLLD(-1.244752e-03), QTCFLLD(1.837877e-02), QTCFLLD(6.898003e-01), + QTCFLLD(-4.128808e-09), QTCFLLD(9.494767e-06), QTCFLLD(-8.878160e-04), + QTCFLLD(2.089915e-02), QTCFLLD(7.219416e-01), QTCFLLD(-1.116801e-08), + QTCFLLD(2.670130e-06), QTCFLLD(-6.273041e-04), QTCFLLD(2.369952e-02), + QTCFLLD(7.532082e-01), QTCFLLD(2.607347e-08), QTCFLLD(2.424790e-06), + QTCFLLD(-3.865944e-04), QTCFLLD(2.679024e-02), QTCFLLD(7.834691e-01), + QTCFLLD(3.782148e-08), QTCFLLD(3.233573e-05), QTCFLLD(2.748136e-04), + QTCFLLD(3.021193e-02), QTCFLLD(8.126044e-01), QTCFLLD(1.290921e-07), + QTCFLLD(5.106187e-05), QTCFLLD(9.680615e-04), QTCFLLD(3.395726e-02), + QTCFLLD(8.404925e-01), QTCFLLD(-1.030732e-06), QTCFLLD(1.162943e-05), + QTCFLLD(1.571198e-03), QTCFLLD(3.801740e-02), QTCFLLD(8.669955e-01), + QTCFLLD(4.052940e-08), QTCFLLD(4.924960e-05), QTCFLLD(1.990767e-03), + QTCFLLD(4.240569e-02), QTCFLLD(8.919595e-01), QTCFLLD(1.236481e-07), + QTCFLLD(5.799333e-05), QTCFLLD(2.354800e-03), QTCFLLD(4.724177e-02), + QTCFLLD(9.152253e-01), QTCFLLD(4.049388e-07), QTCFLLD(6.369496e-05), + QTCFLLD(2.666746e-03), QTCFLLD(5.236967e-02), QTCFLLD(9.366709e-01), + QTCFLLD(4.509857e-06), QTCFLLD(1.726852e-04), QTCFLLD(2.724443e-03), + QTCFLLD(5.774291e-02), QTCFLLD(9.562097e-01), QTCFLLD(1.379026e-05), + QTCFLLD(3.304619e-04), QTCFLLD(2.378216e-03), QTCFLLD(6.336571e-02), + QTCFLLD(9.737916e-01), QTCFLLD(8.497715e-07), QTCFLLD(7.219624e-05), + QTCFLLD(1.724542e-03), QTCFLLD(6.918311e-02), QTCFLLD(9.893883e-01), + QTCFLLD(-1.660944e-07), QTCFLLD(-6.886664e-05), QTCFLLD(9.181354e-04), + QTCFLLD(7.509105e-02), QTCFLLD(1.002969e+00), QTCFLLD(-1.147235e-05), + QTCFLLD(-5.301826e-05), QTCFLLD(2.013701e-04), QTCFLLD(8.103766e-02), + QTCFLLD(1.014484e+00), QTCFLLD(-3.466829e-06), QTCFLLD(1.205564e-04), + QTCFLLD(6.348892e-04), QTCFLLD(8.694765e-02), QTCFLLD(1.023883e+00), + QTCFLLD(6.713692e-07), QTCFLLD(7.762268e-06), QTCFLLD(7.265112e-04), + QTCFLLD(9.277608e-02), QTCFLLD(1.031157e+00), QTCFLLD(2.283238e-07), + QTCFLLD(-9.801253e-06), QTCFLLD(7.042022e-04), QTCFLLD(9.844099e-02), + QTCFLLD(1.036367e+00), QTCFLLD(3.128189e-07), QTCFLLD(-2.623285e-05), + QTCFLLD(6.827052e-04), QTCFLLD(1.038520e-01), QTCFLLD(1.039662e+00), + QTCFLLD(1.907652e-07), QTCFLLD(-4.969654e-05), QTCFLLD(6.321974e-04), + QTCFLLD(1.089094e-01), QTCFLLD(1.041239e+00), QTCFLLD(3.301479e-07), + QTCFLLD(-6.904354e-05), QTCFLLD(3.969634e-04), QTCFLLD(1.135169e-01), + QTCFLLD(1.041265e+00), QTCFLLD(6.596931e-07), QTCFLLD(-8.973431e-05), + QTCFLLD(-5.303260e-06), QTCFLLD(1.175821e-01), QTCFLLD(1.039789e+00), + QTCFLLD(-4.040094e-06), QTCFLLD(-2.316096e-04), QTCFLLD(-6.036561e-04), + QTCFLLD(1.210365e-01), QTCFLLD(1.036689e+00), QTCFLLD(6.078980e-07), + QTCFLLD(-2.100985e-04), QTCFLLD(-1.341249e-03), QTCFLLD(1.238201e-01), + QTCFLLD(1.031702e+00), QTCFLLD(4.269711e-06), QTCFLLD(-1.806979e-04), + QTCFLLD(-2.103464e-03), QTCFLLD(1.258800e-01), QTCFLLD(1.024543e+00), + QTCFLLD(6.117105e-06), QTCFLLD(-1.764517e-04), QTCFLLD(-2.829232e-03), + QTCFLLD(1.271532e-01), QTCFLLD(1.015119e+00), QTCFLLD(4.273153e-06), + QTCFLLD(-2.105146e-04), QTCFLLD(-3.458167e-03), QTCFLLD(1.275064e-01), + QTCFLLD(1.004178e+00), QTCFLLD(4.771428e-06), QTCFLLD(-2.626353e-05), + QTCFLLD(-4.002991e-03), QTCFLLD(1.273045e-01), QTCFLLD(9.867618e-01), + QTCFLLD(3.825650e-06), QTCFLLD(-8.883540e-06), QTCFLLD(-4.434429e-03), + QTCFLLD(1.264771e-01), QTCFLLD(9.629451e-01), QTCFLLD(2.651941e-06), + QTCFLLD(1.812579e-05), QTCFLLD(-4.670274e-03), QTCFLLD(1.245173e-01), + QTCFLLD(9.378839e-01), QTCFLLD(1.229041e-07), QTCFLLD(3.650440e-05), + QTCFLLD(-4.692922e-03), QTCFLLD(1.214113e-01), QTCFLLD(9.110476e-01), + QTCFLLD(3.984739e-06), QTCFLLD(4.583892e-05), QTCFLLD(-4.462183e-03), + QTCFLLD(1.170796e-01), QTCFLLD(8.827057e-01), QTCFLLD(-1.730664e-09), + QTCFLLD(2.460818e-05), QTCFLLD(-3.942729e-03), QTCFLLD(1.114366e-01), + QTCFLLD(8.532971e-01), QTCFLLD(-7.514413e-09), QTCFLLD(2.935029e-05), + QTCFLLD(-3.262337e-03), QTCFLLD(1.044130e-01), QTCFLLD(8.232281e-01), + QTCFLLD(-4.193503e-08), QTCFLLD(1.000081e-05), QTCFLLD(-2.373092e-03), + QTCFLLD(9.597452e-02), QTCFLLD(7.927589e-01), QTCFLLD(9.230786e-08), + QTCFLLD(8.539538e-06), QTCFLLD(-1.328180e-03), QTCFLLD(8.611453e-02), + QTCFLLD(7.619694e-01), QTCFLLD(8.877312e-08), QTCFLLD(7.202067e-05), + QTCFLLD(-4.087339e-04), QTCFLLD(7.483687e-02), QTCFLLD(7.308058e-01), + QTCFLLD(2.712822e-07), QTCFLLD(1.017429e-04), QTCFLLD(3.835110e-04), + QTCFLLD(6.215753e-02), QTCFLLD(6.991715e-01), QTCFLLD(4.019349e-06), + QTCFLLD(6.968570e-05), QTCFLLD(1.141027e-03), QTCFLLD(4.808825e-02), + QTCFLLD(6.670174e-01), QTCFLLD(8.898233e-08), QTCFLLD(5.441853e-05), + QTCFLLD(1.992521e-03), QTCFLLD(3.262236e-02), QTCFLLD(6.343833e-01), + QTCFLLD(-1.007690e-07), QTCFLLD(3.975024e-05), QTCFLLD(1.841739e-03), + QTCFLLD(1.572281e-02), QTCFLLD(6.013836e-01), QTCFLLD(6.568868e-07), + QTCFLLD(8.181074e-05), QTCFLLD(1.351651e-03), QTCFLLD(-2.556970e-03), + QTCFLLD(5.681393e-01), QTCFLLD(-5.690228e-06), QTCFLLD(9.126098e-05), + QTCFLLD(7.570286e-04), QTCFLLD(-2.218904e-02), QTCFLLD(5.347272e-01), + QTCFLLD(1.884389e-05), QTCFLLD(-2.705446e-04), QTCFLLD(5.337144e-04), + QTCFLLD(-4.317467e-02), QTCFLLD(5.011593e-01), QTCFLLD(-1.329252e-06), + QTCFLLD(-7.198660e-05), QTCFLLD(2.941296e-05), QTCFLLD(-6.547049e-02), + QTCFLLD(4.674168e-01), QTCFLLD(-1.355524e-07), QTCFLLD(5.942472e-05), + QTCFLLD(-4.468657e-04), QTCFLLD(-8.902535e-02), QTCFLLD(4.335079e-01), + QTCFLLD(1.041631e-05), QTCFLLD(6.091853e-05), QTCFLLD(-8.704047e-04), + QTCFLLD(-1.138130e-01), QTCFLLD(3.995200e-01), QTCFLLD(-1.170911e-05), + QTCFLLD(-2.623833e-05), QTCFLLD(-1.207570e-03), QTCFLLD(-1.397967e-01), + QTCFLLD(3.656086e-01), QTCFLLD(-1.364079e-06), QTCFLLD(8.097173e-06), + QTCFLLD(-1.589852e-03), QTCFLLD(-1.669302e-01), QTCFLLD(3.319187e-01), + QTCFLLD(-5.342262e-07), QTCFLLD(3.005858e-05), QTCFLLD(-2.038612e-03), + QTCFLLD(-1.951630e-01), QTCFLLD(2.984839e-01), QTCFLLD(-1.099320e-06), + QTCFLLD(8.977871e-05), QTCFLLD(-2.525111e-03), QTCFLLD(-2.244371e-01), + QTCFLLD(2.651577e-01), QTCFLLD(-7.121587e-07), QTCFLLD(1.848150e-04), + QTCFLLD(-3.068126e-03), QTCFLLD(-2.546924e-01), QTCFLLD(2.316523e-01), + QTCFLLD(-9.617199e-07), QTCFLLD(2.433794e-04), QTCFLLD(-3.658572e-03), + QTCFLLD(-2.858681e-01), QTCFLLD(1.977098e-01), QTCFLLD(-1.848464e-06), + QTCFLLD(2.857057e-04), QTCFLLD(-4.291316e-03), QTCFLLD(-3.178928e-01), + QTCFLLD(1.633594e-01), QTCFLLD(1.509004e-05), QTCFLLD(7.026758e-04), + QTCFLLD(-4.909021e-03), QTCFLLD(-3.506784e-01), QTCFLLD(1.291537e-01), + QTCFLLD(-2.901422e-06), QTCFLLD(9.784381e-04), QTCFLLD(-5.567837e-03), + QTCFLLD(-3.841116e-01), QTCFLLD(9.625038e-02), QTCFLLD(-2.035140e-05), + QTCFLLD(1.105966e-03), QTCFLLD(-6.304841e-03), QTCFLLD(-4.180555e-01), + QTCFLLD(6.622328e-02), QTCFLLD(-3.077146e-05), QTCFLLD(1.201814e-03), + QTCFLLD(-7.152842e-03), QTCFLLD(-4.523680e-01), QTCFLLD(4.042707e-02), + QTCFLLD(-3.836153e-05), QTCFLLD(1.275694e-03), QTCFLLD(-8.142071e-03), + QTCFLLD(-4.869413e-01), QTCFLLD(1.741320e-02), +}; + +RAM_ALIGN +const FIXP_PFT qmf_cldfb_160[QMF160_CLDFB_PFT_TABLE_SIZE] = { + QTCFLLD(6.114156e-07), QTCFLLD(-4.929378e-06), QTCFLLD(-1.173270e-03), + QTCFLLD(9.985781e-03), QTCFLLD(5.385081e-01), QTCFLLD(2.119298e-07), + QTCFLLD(8.001152e-06), QTCFLLD(-9.578346e-04), QTCFLLD(1.315910e-02), + QTCFLLD(6.066454e-01), QTCFLLD(8.097845e-07), QTCFLLD(1.849027e-05), + QTCFLLD(-1.219567e-03), QTCFLLD(1.721718e-02), QTCFLLD(6.734486e-01), + QTCFLLD(-1.135478e-08), QTCFLLD(5.632976e-06), QTCFLLD(-7.392278e-04), + QTCFLLD(2.226388e-02), QTCFLLD(7.376929e-01), QTCFLLD(6.347751e-08), + QTCFLLD(1.454425e-05), QTCFLLD(-1.105239e-04), QTCFLLD(2.845808e-02), + QTCFLLD(7.981848e-01), QTCFLLD(-2.838328e-06), QTCFLLD(3.414749e-06), + QTCFLLD(1.272254e-03), QTCFLLD(3.594821e-02), QTCFLLD(8.539265e-01), + QTCFLLD(7.116049e-08), QTCFLLD(4.031125e-05), QTCFLLD(2.136304e-03), + QTCFLLD(4.477318e-02), QTCFLLD(9.038135e-01), QTCFLLD(4.098227e-07), + QTCFLLD(7.484240e-05), QTCFLLD(2.716078e-03), QTCFLLD(5.502766e-02), + QTCFLLD(9.466825e-01), QTCFLLD(4.934327e-07), QTCFLLD(7.557725e-05), + QTCFLLD(2.058748e-03), QTCFLLD(6.626062e-02), QTCFLLD(9.818396e-01), + QTCFLLD(-4.933896e-08), QTCFLLD(-3.907360e-05), QTCFLLD(3.753964e-04), + QTCFLLD(7.806610e-02), QTCFLLD(1.008988e+00), QTCFLLD(-7.856341e-06), + QTCFLLD(9.949480e-05), QTCFLLD(7.176331e-04), QTCFLLD(8.987702e-02), + QTCFLLD(1.027784e+00), QTCFLLD(4.822448e-07), QTCFLLD(-1.327914e-05), + QTCFLLD(6.855222e-04), QTCFLLD(1.011847e-01), QTCFLLD(1.038242e+00), + QTCFLLD(4.432684e-07), QTCFLLD(-5.662008e-05), QTCFLLD(5.360314e-04), + QTCFLLD(1.112756e-01), QTCFLLD(1.041439e+00), QTCFLLD(-1.894204e-06), + QTCFLLD(-1.603894e-04), QTCFLLD(-2.796433e-04), QTCFLLD(1.193894e-01), + QTCFLLD(1.038456e+00), QTCFLLD(2.350541e-06), QTCFLLD(-1.981793e-04), + QTCFLLD(-1.719967e-03), QTCFLLD(1.249437e-01), QTCFLLD(1.028407e+00), + QTCFLLD(4.833713e-06), QTCFLLD(-1.957799e-04), QTCFLLD(-3.159640e-03), + QTCFLLD(1.274605e-01), QTCFLLD(1.009701e+00), QTCFLLD(4.724263e-06), + QTCFLLD(-1.181518e-05), QTCFLLD(-4.243399e-03), QTCFLLD(1.270390e-01), + QTCFLLD(9.748854e-01), QTCFLLD(1.007724e-06), QTCFLLD(2.585741e-05), + QTCFLLD(-4.713445e-03), QTCFLLD(1.231120e-01), QTCFLLD(9.246770e-01), + QTCFLLD(2.908454e-06), QTCFLLD(3.137374e-05), QTCFLLD(-4.230293e-03), + QTCFLLD(1.144269e-01), QTCFLLD(8.681067e-01), QTCFLLD(-4.128877e-08), + QTCFLLD(1.870358e-05), QTCFLLD(-2.842924e-03), QTCFLLD(1.003715e-01), + QTCFLLD(8.080344e-01), QTCFLLD(1.806649e-07), QTCFLLD(3.557071e-05), + QTCFLLD(-8.392422e-04), QTCFLLD(8.065225e-02), QTCFLLD(7.464405e-01), + QTCFLLD(2.352609e-06), QTCFLLD(1.090077e-04), QTCFLLD(7.497848e-04), + QTCFLLD(5.529631e-02), QTCFLLD(6.831591e-01), QTCFLLD(1.159657e-07), + QTCFLLD(4.585990e-05), QTCFLLD(2.079346e-03), QTCFLLD(2.434883e-02), + QTCFLLD(6.179208e-01), QTCFLLD(8.859606e-07), QTCFLLD(1.403345e-04), + QTCFLLD(1.065580e-03), QTCFLLD(-1.220572e-02), QTCFLLD(5.514521e-01), + QTCFLLD(-1.038278e-06), QTCFLLD(-1.368162e-04), QTCFLLD(2.932339e-04), + QTCFLLD(-5.416374e-02), QTCFLLD(4.843109e-01), QTCFLLD(7.820030e-08), + QTCFLLD(3.934544e-05), QTCFLLD(-6.638491e-04), QTCFLLD(-1.012664e-01), + QTCFLLD(4.165150e-01), QTCFLLD(-8.393432e-06), QTCFLLD(-5.053646e-05), + QTCFLLD(-1.381912e-03), QTCFLLD(-1.532225e-01), QTCFLLD(3.487301e-01), + QTCFLLD(-1.455897e-06), QTCFLLD(4.880962e-05), QTCFLLD(-2.274392e-03), + QTCFLLD(-2.096737e-01), QTCFLLD(2.818234e-01), QTCFLLD(-1.434317e-06), + QTCFLLD(2.203687e-04), QTCFLLD(-3.357312e-03), QTCFLLD(-2.701693e-01), + QTCFLLD(2.147441e-01), QTCFLLD(7.092199e-06), QTCFLLD(4.681670e-04), + QTCFLLD(-4.601593e-03), QTCFLLD(-3.341968e-01), QTCFLLD(1.461805e-01), + QTCFLLD(-1.116123e-05), QTCFLLD(1.072196e-03), QTCFLLD(-5.925141e-03), + QTCFLLD(-4.010285e-01), QTCFLLD(8.077862e-02), QTCFLLD(-3.775385e-05), + QTCFLLD(1.244841e-03), QTCFLLD(-7.628469e-03), QTCFLLD(-4.696240e-01), + QTCFLLD(2.901889e-02), +}; + +RAM_ALIGN +const FIXP_PFT qmf_cldfb_80[QMF80_CLDFB_PFT_TABLE_SIZE] = { + QTCFLLD(6.966921e-07), QTCFLLD(9.025176e-06), QTCFLLD(-1.073328e-03), + QTCFLLD(1.146585e-02), QTCFLLD(5.726758e-01), QTCFLLD(-2.323046e-09), + QTCFLLD(1.012638e-05), QTCFLLD(-1.084654e-03), QTCFLLD(1.960515e-02), + QTCFLLD(7.059712e-01), QTCFLLD(1.230159e-07), QTCFLLD(4.639126e-05), + QTCFLLD(6.398911e-04), QTCFLLD(3.204506e-02), QTCFLLD(8.267125e-01), + QTCFLLD(2.865339e-07), QTCFLLD(6.273759e-05), QTCFLLD(2.550464e-03), + QTCFLLD(4.977453e-02), QTCFLLD(9.261818e-01), QTCFLLD(3.738257e-07), + QTCFLLD(-2.429021e-06), QTCFLLD(1.375921e-03), QTCFLLD(7.212754e-02), + QTCFLLD(9.964333e-01), QTCFLLD(1.077039e-08), QTCFLLD(-8.532976e-06), + QTCFLLD(7.147022e-04), QTCFLLD(9.563432e-02), QTCFLLD(1.034012e+00), + QTCFLLD(3.086046e-07), QTCFLLD(-7.986870e-05), QTCFLLD(2.203781e-04), + QTCFLLD(1.156221e-01), QTCFLLD(1.040718e+00), QTCFLLD(5.542804e-06), + QTCFLLD(-1.736757e-04), QTCFLLD(-2.475428e-03), QTCFLLD(1.266206e-01), + QTCFLLD(1.020100e+00), QTCFLLD(3.415168e-06), QTCFLLD(6.290201e-06), + QTCFLLD(-4.576709e-03), QTCFLLD(1.256370e-01), QTCFLLD(9.506344e-01), + QTCFLLD(-1.998632e-09), QTCFLLD(3.017514e-05), QTCFLLD(-3.627394e-03), + QTCFLLD(1.081003e-01), QTCFLLD(8.383245e-01), QTCFLLD(2.590900e-07), + QTCFLLD(9.614004e-05), QTCFLLD(2.183786e-06), QTCFLLD(6.867141e-02), + QTCFLLD(7.150523e-01), QTCFLLD(1.408172e-07), QTCFLLD(5.203217e-05), + QTCFLLD(1.584410e-03), QTCFLLD(6.753749e-03), QTCFLLD(5.847858e-01), + QTCFLLD(-9.234326e-07), QTCFLLD(6.477183e-06), QTCFLLD(-2.123969e-04), + QTCFLLD(-7.709230e-02), QTCFLLD(4.504798e-01), QTCFLLD(-2.464033e-08), + QTCFLLD(1.888626e-05), QTCFLLD(-1.812003e-03), QTCFLLD(-1.809127e-01), + QTCFLLD(3.151743e-01), QTCFLLD(-8.344882e-07), QTCFLLD(2.538528e-04), + QTCFLLD(-3.972626e-03), QTCFLLD(-3.017793e-01), QTCFLLD(1.805658e-01), + QTCFLLD(-2.720526e-05), QTCFLLD(1.150009e-03), QTCFLLD(-6.712822e-03), + QTCFLLD(-4.351740e-01), QTCFLLD(5.276687e-02), +}; + +#if defined(QMF_COEFF_16BIT) +#define QTMFLLD(x) FL2FXCONST_SGL(x / (float)(1 << QMF_MPSLDFB_PFT_SCALE)) +#define QTMFLLDT(x) FX_DBL2FXCONST_SGL(x) +#else +#define QTMFLLD(x) FL2FXCONST_DBL(x / (float)(1 << QMF_MPSLDFB_PFT_SCALE)) +#define QTMFLLDT(x) (FIXP_DBL)(x) +#endif + +/*! + \name QMF + \brief QMF-Table + 32 channels, N = 320, + + The coefficients are derived from the MPS Low Delay coefficient set + with 640 samples. The coefficients are interpolated and rearranged + in the following way compared to the reference: + + qmf_mpsldfb_320[0] = (qmf_64_reference[ 0] + qmf_64_reference[ 1])/2.0; + qmf_mpsldfb_320[1] = (qmf_64_reference[128] + qmf_64_reference[129])/2.0; + qmf_mpsldfb_320[2] = (qmf_64_reference[256] + qmf_64_reference[257])/2.0; + qmf_mpsldfb_320[3] = (qmf_64_reference[384] + qmf_64_reference[385])/2.0; + qmf_mpsldfb_320[4] = (qmf_64_reference[512] + qmf_64_reference[513])/2.0; + + qmf_mpsldfb_320[5] = (qmf_64_reference[ 2] + qmf_64_reference[ 3])/2.0; + qmf_mpsldfb_320[6] = (qmf_64_reference[130] + qmf_64_reference[131])/2.0; + qmf_mpsldfb_320[7] = (qmf_64_reference[258] + qmf_64_reference[259])/2.0; + qmf_mpsldfb_320[8] = (qmf_64_reference[386] + qmf_64_reference[387])/2.0; + qmf_mpsldfb_320[9] = (qmf_64_reference[514] + qmf_64_reference[515])/2.0; + . + . + . + qmf_mpsldfb_320[315] = (qmf_64_reference[126] + qmf_64_reference[127])/2.0; + qmf_mpsldfb_320[316] = (qmf_64_reference[254] + qmf_64_reference[255])/2.0; + qmf_mpsldfb_320[317] = (qmf_64_reference[382] + qmf_64_reference[383])/2.0; + qmf_mpsldfb_320[318] = (qmf_64_reference[510] + qmf_64_reference[511])/2.0; + qmf_mpsldfb_320[319] = (qmf_64_reference[638] + qmf_64_reference[639])/2.0; + + The filter output is required to be scaled by 1 bit. + + \showinitializer +*/ +//@{ +const FIXP_PFT qmf_mpsldfb_320[QMF320_MPSLDFB_PFT_TABLE_SIZE] = { + QTMFLLD(1.0777725402e-004), QTMFLLD(-9.4703806099e-004), + QTMFLLD(6.1286436394e-003), QTMFLLD(-9.0161964297e-002), + QTMFLLD(5.5554401875e-001), QTMFLLD(1.2731316383e-004), + QTMFLLD(-1.2311334722e-003), QTMFLLD(4.9468209036e-003), + QTMFLLD(-1.1305026710e-001), QTMFLLD(5.2990418673e-001), + QTMFLLD(1.1927412561e-004), QTMFLLD(-1.5128203668e-003), + QTMFLLD(3.5794533323e-003), QTMFLLD(-1.3681203127e-001), + QTMFLLD(5.0423312187e-001), QTMFLLD(1.0006380762e-004), + QTMFLLD(-1.7925058492e-003), QTMFLLD(2.0164034795e-003), + QTMFLLD(-1.6139641404e-001), QTMFLLD(4.7861024737e-001), + QTMFLLD(7.2826202086e-005), QTMFLLD(-2.0697340369e-003), + QTMFLLD(2.4838969694e-004), QTMFLLD(-1.8674756587e-001), + QTMFLLD(4.5311337709e-001), QTMFLLD(3.8808015233e-005), + QTMFLLD(-2.3429044522e-003), QTMFLLD(-1.7331546405e-003), + QTMFLLD(-2.1280488372e-001), QTMFLLD(4.2781800032e-001), + QTMFLLD(-5.4359588830e-007), QTMFLLD(-2.6112669148e-003), + QTMFLLD(-3.9357249625e-003), QTMFLLD(-2.3950359225e-001), + QTMFLLD(4.0279802680e-001), QTMFLLD(-4.3614549213e-005), + QTMFLLD(-2.8741455171e-003), QTMFLLD(-6.3655078411e-003), + QTMFLLD(-2.6677471399e-001), QTMFLLD(3.7812507153e-001), + QTMFLLD(-8.9040157036e-005), QTMFLLD(-3.1308881007e-003), + QTMFLLD(-9.0275555849e-003), QTMFLLD(-2.9454550147e-001), + QTMFLLD(3.5386830568e-001), QTMFLLD(-1.3519046479e-004), + QTMFLLD(-3.3808732405e-003), QTMFLLD(-1.1925406754e-002), + QTMFLLD(-3.2273942232e-001), QTMFLLD(3.3009397984e-001), + QTMFLLD(-1.8045579782e-004), QTMFLLD(-3.6236830056e-003), + QTMFLLD(-1.5061311424e-002), QTMFLLD(-3.5127705336e-001), + QTMFLLD(3.0686509609e-001), QTMFLLD(-2.2396800341e-004), + QTMFLLD(-3.8587960880e-003), QTMFLLD(-1.8435835838e-002), + QTMFLLD(-3.8007527590e-001), QTMFLLD(2.8424069285e-001), + QTMFLLD(-2.6416976471e-004), QTMFLLD(-4.0859002620e-003), + QTMFLLD(-2.2048022598e-002), QTMFLLD(-4.0904915333e-001), + QTMFLLD(2.6227575541e-001), QTMFLLD(-3.0001887353e-004), + QTMFLLD(-4.3045589700e-003), QTMFLLD(-2.5894984603e-002), + QTMFLLD(-4.3811064959e-001), QTMFLLD(2.4102044106e-001), + QTMFLLD(-3.3083156450e-004), QTMFLLD(-4.5145484619e-003), + QTMFLLD(-2.9972121119e-002), QTMFLLD(-4.6717000008e-001), + QTMFLLD(2.2052007914e-001), QTMFLLD(-3.5614447552e-004), + QTMFLLD(-4.7155953944e-003), QTMFLLD(-3.4272894263e-002), + QTMFLLD(-4.9613577127e-001), QTMFLLD(2.0081442595e-001), + QTMFLLD(-3.7579826312e-004), QTMFLLD(-4.9072988331e-003), + QTMFLLD(-3.8788780570e-002), QTMFLLD(-5.2491527796e-001), + QTMFLLD(1.8193808198e-001), QTMFLLD(-3.8993739872e-004), + QTMFLLD(-5.0893351436e-003), QTMFLLD(-4.3509010226e-002), + QTMFLLD(-5.5341482162e-001), QTMFLLD(1.6391974688e-001), + QTMFLLD(-3.9912899956e-004), QTMFLLD(-5.2615385503e-003), + QTMFLLD(-4.8421185464e-002), QTMFLLD(-5.8154034615e-001), + QTMFLLD(1.4678207040e-001), QTMFLLD(-4.0421969607e-004), + QTMFLLD(-5.4236799479e-003), QTMFLLD(-5.3510606289e-002), + QTMFLLD(-6.0919785500e-001), QTMFLLD(1.3054165244e-001), + QTMFLLD(-4.0645478293e-004), QTMFLLD(-5.5756671354e-003), + QTMFLLD(-5.8760054410e-002), QTMFLLD(-6.3629388809e-001), + QTMFLLD(1.1520925164e-001), QTMFLLD(-4.0720938705e-004), + QTMFLLD(-5.7173836976e-003), QTMFLLD(-6.4149998128e-002), + QTMFLLD(-6.6273581982e-001), QTMFLLD(1.0078965127e-001), + QTMFLLD(-4.0812738007e-004), QTMFLLD(-5.8488911018e-003), + QTMFLLD(-6.9658569992e-002), QTMFLLD(-6.8843221664e-001), + QTMFLLD(8.7281554937e-002), QTMFLLD(-4.1120912647e-004), + QTMFLLD(-5.9703430161e-003), QTMFLLD(-7.5261354446e-002), + QTMFLLD(-7.1329379082e-001), QTMFLLD(7.4678033590e-002), + QTMFLLD(-4.1838851757e-004), QTMFLLD(-6.0821287334e-003), + QTMFLLD(-8.0931767821e-002), QTMFLLD(-7.3723363876e-001), + QTMFLLD(6.2966249883e-002), QTMFLLD(-4.3148122495e-004), + QTMFLLD(-6.1847940087e-003), QTMFLLD(-8.6640790105e-002), + QTMFLLD(-7.6016783714e-001), QTMFLLD(5.2128262818e-002), + QTMFLLD(-4.5229538227e-004), QTMFLLD(-6.2791546807e-003), + QTMFLLD(-9.2357128859e-002), QTMFLLD(-7.8201586008e-001), + QTMFLLD(4.2139917612e-002), QTMFLLD(-4.8211280955e-004), + QTMFLLD(-6.3661932945e-003), QTMFLLD(-9.8047181964e-002), + QTMFLLD(-8.0270123482e-001), QTMFLLD(3.2972395420e-002), + QTMFLLD(-5.2196672186e-004), QTMFLLD(-6.4471233636e-003), + QTMFLLD(-1.0367526114e-001), QTMFLLD(-8.2215231657e-001), + QTMFLLD(2.4589803070e-002), QTMFLLD(-5.7247944642e-004), + QTMFLLD(-6.5232971683e-003), QTMFLLD(-1.0920339823e-001), + QTMFLLD(-8.4030228853e-001), QTMFLLD(1.6952158883e-002), + QTMFLLD(-6.3343788497e-004), QTMFLLD(-6.5963375382e-003), + QTMFLLD(-1.1459194124e-001), QTMFLLD(-8.5709118843e-001), + QTMFLLD(1.0006074794e-002), QTMFLLD(-7.0449430496e-004), + QTMFLLD(-6.6681848839e-003), QTMFLLD(-1.1979964375e-001), + QTMFLLD(-8.7246519327e-001), QTMFLLD(3.6968050990e-003), + QTMFLLD(-7.9609593377e-004), QTMFLLD(-6.7403013818e-003), + QTMFLLD(-1.2478165329e-001), QTMFLLD(-8.8632321358e-001), + QTMFLLD(-1.6344460892e-003), QTMFLLD(-9.0200459817e-004), + QTMFLLD(-6.8151149899e-003), QTMFLLD(-1.2949258089e-001), + QTMFLLD(-8.9860773087e-001), QTMFLLD(-5.9283543378e-003), + QTMFLLD(-1.0116943158e-003), QTMFLLD(-6.8955891766e-003), + QTMFLLD(-1.3388808072e-001), QTMFLLD(-9.0933418274e-001), + QTMFLLD(-9.6466485411e-003), QTMFLLD(-1.1244935449e-003), + QTMFLLD(-6.9835213944e-003), QTMFLLD(-1.3791990280e-001), + QTMFLLD(-9.1846722364e-001), QTMFLLD(-1.2838950381e-002), + QTMFLLD(-1.2393904617e-003), QTMFLLD(-7.0809246972e-003), + QTMFLLD(-1.4153905213e-001), QTMFLLD(-9.2597639561e-001), + QTMFLLD(-1.5539921820e-002), QTMFLLD(-1.3542033266e-003), + QTMFLLD(-7.1895248257e-003), QTMFLLD(-1.4469626546e-001), + QTMFLLD(-9.3183851242e-001), QTMFLLD(-1.7783239484e-002), + QTMFLLD(-1.4669501688e-003), QTMFLLD(-7.3110014200e-003), + QTMFLLD(-1.4734169841e-001), QTMFLLD(-9.3603670597e-001), + QTMFLLD(-1.9597738981e-002), QTMFLLD(-1.5753224725e-003), + QTMFLLD(-7.4466220103e-003), QTMFLLD(-1.4942565560e-001), + QTMFLLD(-9.3856132030e-001), QTMFLLD(-2.1011535078e-002), + QTMFLLD(-1.6771152150e-003), QTMFLLD(-7.5972955674e-003), + QTMFLLD(-1.5089863539e-001), QTMFLLD(-9.3940949440e-001), + QTMFLLD(-2.2049814463e-002), QTMFLLD(-1.7698677257e-003), + QTMFLLD(-7.7634919435e-003), QTMFLLD(-1.5171185136e-001), + QTMFLLD(-9.3858534098e-001), QTMFLLD(-2.2738276049e-002), + QTMFLLD(-1.8512960523e-003), QTMFLLD(-7.9450644553e-003), + QTMFLLD(-1.5181747079e-001), QTMFLLD(-9.3610012531e-001), + QTMFLLD(-2.3101080209e-002), QTMFLLD(-1.9192657201e-003), + QTMFLLD(-8.1413704902e-003), QTMFLLD(-1.5116891265e-001), + QTMFLLD(-9.3197190762e-001), QTMFLLD(-2.3163486272e-002), + QTMFLLD(-1.9716904499e-003), QTMFLLD(-8.3509404212e-003), + QTMFLLD(-1.4972095191e-001), QTMFLLD(-9.2622530460e-001), + QTMFLLD(-2.2950030863e-002), QTMFLLD(-2.0066620782e-003), + QTMFLLD(-8.5715763271e-003), QTMFLLD(-1.4743055403e-001), + QTMFLLD(-9.1889131069e-001), QTMFLLD(-2.2486699745e-002), + QTMFLLD(-2.0227057394e-003), QTMFLLD(-8.8005559519e-003), + QTMFLLD(-1.4425669611e-001), QTMFLLD(-9.1000711918e-001), + QTMFLLD(-2.1799135953e-002), QTMFLLD(-2.0185527392e-003), + QTMFLLD(-9.0341167524e-003), QTMFLLD(-1.4016106725e-001), + QTMFLLD(-8.9961612225e-001), QTMFLLD(-2.0914383233e-002), + QTMFLLD(-1.9932338037e-003), QTMFLLD(-9.2674419284e-003), + QTMFLLD(-1.3510815799e-001), QTMFLLD(-8.8776648045e-001), + QTMFLLD(-1.9859094173e-002), QTMFLLD(-1.9461065531e-003), + QTMFLLD(-9.4948727638e-003), QTMFLLD(-1.2906542420e-001), + QTMFLLD(-8.7451159954e-001), QTMFLLD(-1.8660902977e-002), + QTMFLLD(-1.8770052120e-003), QTMFLLD(-9.7100129351e-003), + QTMFLLD(-1.2200380862e-001), QTMFLLD(-8.5991013050e-001), + QTMFLLD(-1.7346922308e-002), QTMFLLD(-1.7859865911e-003), + QTMFLLD(-9.9056493491e-003), QTMFLLD(-1.1389782280e-001), + QTMFLLD(-8.4402561188e-001), QTMFLLD(-1.5944939107e-002), + QTMFLLD(-1.6734169330e-003), QTMFLLD(-1.0073989630e-002), + QTMFLLD(-1.0472598672e-001), QTMFLLD(-8.2692527771e-001), + QTMFLLD(-1.4481747523e-002), QTMFLLD(-1.5399802942e-003), + QTMFLLD(-1.0205906816e-002), QTMFLLD(-9.4470888376e-002), + QTMFLLD(-8.0868041515e-001), QTMFLLD(-1.2984249741e-002), + QTMFLLD(-1.3865872752e-003), QTMFLLD(-1.0291703977e-002), + QTMFLLD(-8.3119556308e-002), QTMFLLD(-7.8936588764e-001), + QTMFLLD(-1.1477986351e-002), QTMFLLD(-1.2144348584e-003), + QTMFLLD(-1.0320962407e-002), QTMFLLD(-7.0663399994e-002), + QTMFLLD(-7.6905936003e-001), QTMFLLD(-9.9884867668e-003), + QTMFLLD(-1.0248266626e-003), QTMFLLD(-1.0282764211e-002), + QTMFLLD(-5.7098604739e-002), QTMFLLD(-7.4784147739e-001), + QTMFLLD(-8.5393209010e-003), QTMFLLD(-8.1919803051e-004), + QTMFLLD(-1.0165717453e-002), QTMFLLD(-4.2426198721e-002), + QTMFLLD(-7.2579479218e-001), QTMFLLD(-7.1533406153e-003), + QTMFLLD(-5.9914286248e-004), QTMFLLD(-9.9579729140e-003), + QTMFLLD(-2.6652012020e-002), QTMFLLD(-7.0300412178e-001), + QTMFLLD(-5.8508114889e-003), QTMFLLD(-3.6626873771e-004), + QTMFLLD(-9.6475090832e-003), QTMFLLD(-9.7871217877e-003), + QTMFLLD(-6.7955517769e-001), QTMFLLD(-4.6512838453e-003), + QTMFLLD(-1.2227181287e-004), QTMFLLD(-9.2221321538e-003), + QTMFLLD(8.1523396075e-003), QTMFLLD(-6.5553492308e-001), + QTMFLLD(-3.5699680448e-003), QTMFLLD(1.3090072025e-004), + QTMFLLD(-8.6695179343e-003), QTMFLLD(2.7145106345e-002), + QTMFLLD(-6.3103044033e-001), QTMFLLD(-2.6181070134e-003), + QTMFLLD(3.9128778735e-004), QTMFLLD(-7.9773496836e-003), + QTMFLLD(4.7164849937e-002), QTMFLLD(-6.0613000393e-001), + QTMFLLD(-1.7908872105e-003), QTMFLLD(6.5761915175e-004), + QTMFLLD(-7.1337916888e-003), QTMFLLD(6.8181537092e-002), + QTMFLLD(-5.8092808723e-001), QTMFLLD(-1.0135001503e-003)}; + +/*! + \name QMF + \brief QMF-Table + 64 channels, N = 640, + + The coeffs are rearranged compared with the reference in the following + way: + + qmf_64[0] = qmf_64_reference[0]; + qmf_64[1] = qmf_64_reference[128]; + qmf_64[2] = qmf_64_reference[256]; + qmf_64[3] = qmf_64_reference[384]; + qmf_64[4] = qmf_64_reference[512]; + + qmf_64[5] = qmf_64_reference[1]; + qmf_64[6] = qmf_64_reference[129]; + qmf_64[7] = qmf_64_reference[257]; + qmf_64[8] = qmf_64_reference[385]; + qmf_64[9] = qmf_64_reference[513]; + . + . + . + qmf_64[635] = qmf_64_reference[127] + qmf_64[636] = qmf_64_reference[255]; + qmf_64[637] = qmf_64_reference[383]; + qmf_64[638] = qmf_64_reference[511]; + qmf_64[639] = qmf_64_reference[639]; + + The filter output is required to be scaled by 1 bit. + + \showinitializer +*/ +//@{ +LNK_SECTION_CONSTDATA_L1 +RAM_ALIGN +const FIXP_PFT qmf_mpsldfb_640[QMF640_MPSLDFB_PFT_TABLE_SIZE] = { + QTMFLLD(9.3863010989e-005), QTMFLLD(-8.7536586216e-004), + QTMFLLD(6.4016343094e-003), QTMFLLD(-8.4552817047e-002), + QTMFLLD(5.6194400787e-001), QTMFLLD(1.2169149704e-004), + QTMFLLD(-1.0187102016e-003), QTMFLLD(5.8556534350e-003), + QTMFLLD(-9.5771118999e-002), QTMFLLD(5.4914402962e-001), + QTMFLLD(1.2793767382e-004), QTMFLLD(-1.1605311884e-003), + QTMFLLD(5.2649765275e-003), QTMFLLD(-1.0721673071e-001), + QTMFLLD(5.3632181883e-001), QTMFLLD(1.2668863928e-004), + QTMFLLD(-1.3017356396e-003), QTMFLLD(4.6286652796e-003), + QTMFLLD(-1.1888379604e-001), QTMFLLD(5.2348655462e-001), + QTMFLLD(1.2296593923e-004), QTMFLLD(-1.4426353155e-003), + QTMFLLD(3.9453012869e-003), QTMFLLD(-1.3076621294e-001), + QTMFLLD(5.1064836979e-001), QTMFLLD(1.1558231199e-004), + QTMFLLD(-1.5830053017e-003), QTMFLLD(3.2136053778e-003), + QTMFLLD(-1.4285783470e-001), QTMFLLD(4.9781781435e-001), + QTMFLLD(1.0582985124e-004), QTMFLLD(-1.7228506040e-003), + QTMFLLD(2.4323666003e-003), QTMFLLD(-1.5515175462e-001), + QTMFLLD(4.8500382900e-001), QTMFLLD(9.4297764008e-005), + QTMFLLD(-1.8621610943e-003), QTMFLLD(1.6004402423e-003), + QTMFLLD(-1.6764105856e-001), QTMFLLD(4.7221666574e-001), + QTMFLLD(8.0514568253e-005), QTMFLLD(-2.0008818246e-003), + QTMFLLD(7.1672687773e-004), QTMFLLD(-1.8031860888e-001), + QTMFLLD(4.5946595073e-001), QTMFLLD(6.5137835918e-005), + QTMFLLD(-2.1385864820e-003), QTMFLLD(-2.1994746930e-004), + QTMFLLD(-1.9317652285e-001), QTMFLLD(4.4676083326e-001), + QTMFLLD(4.8101064749e-005), QTMFLLD(-2.2751907818e-003), + QTMFLLD(-1.2104592752e-003), QTMFLLD(-2.0620720088e-001), + QTMFLLD(4.3411090970e-001), QTMFLLD(2.9514967537e-005), + QTMFLLD(-2.4106178898e-003), QTMFLLD(-2.2558500059e-003), + QTMFLLD(-2.1940255165e-001), QTMFLLD(4.2152509093e-001), + QTMFLLD(9.8814107332e-006), QTMFLLD(-2.5448307861e-003), + QTMFLLD(-3.3569468651e-003), QTMFLLD(-2.3275400698e-001), + QTMFLLD(4.0901294351e-001), QTMFLLD(-1.0968602510e-005), + QTMFLLD(-2.6777030434e-003), QTMFLLD(-4.5145032927e-003), + QTMFLLD(-2.4625316262e-001), QTMFLLD(3.9658311009e-001), + QTMFLLD(-3.2559255487e-005), QTMFLLD(-2.8091520071e-003), + QTMFLLD(-5.7292259298e-003), QTMFLLD(-2.5989097357e-001), + QTMFLLD(3.8424444199e-001), QTMFLLD(-5.4669842939e-005), + QTMFLLD(-2.9391390271e-003), QTMFLLD(-7.0017897524e-003), + QTMFLLD(-2.7365845442e-001), QTMFLLD(3.7200567126e-001), + QTMFLLD(-7.7506563684e-005), QTMFLLD(-3.0675258022e-003), + QTMFLLD(-8.3327051252e-003), QTMFLLD(-2.8754624724e-001), + QTMFLLD(3.5987523198e-001), QTMFLLD(-1.0057374311e-004), + QTMFLLD(-3.1942503992e-003), QTMFLLD(-9.7224051133e-003), + QTMFLLD(-3.0154475570e-001), QTMFLLD(3.4786140919e-001), + QTMFLLD(-1.2368557509e-004), QTMFLLD(-3.3192564733e-003), + QTMFLLD(-1.1171258055e-002), QTMFLLD(-3.1564420462e-001), + QTMFLLD(3.3597227931e-001), QTMFLLD(-1.4669535449e-004), + QTMFLLD(-3.4424900077e-003), QTMFLLD(-1.2679555453e-002), + QTMFLLD(-3.2983466983e-001), QTMFLLD(3.2421571016e-001), + QTMFLLD(-1.6928518016e-004), QTMFLLD(-3.5639149137e-003), + QTMFLLD(-1.4247507788e-002), QTMFLLD(-3.4410607815e-001), + QTMFLLD(3.1259948015e-001), QTMFLLD(-1.9162640092e-004), + QTMFLLD(-3.6834510975e-003), QTMFLLD(-1.5875114128e-002), + QTMFLLD(-3.5844799876e-001), QTMFLLD(3.0113074183e-001), + QTMFLLD(-2.1345751884e-004), QTMFLLD(-3.8009947166e-003), + QTMFLLD(-1.7562393099e-002), QTMFLLD(-3.7284970284e-001), + QTMFLLD(2.8981682658e-001), QTMFLLD(-2.3447850253e-004), + QTMFLLD(-3.9165974595e-003), QTMFLLD(-1.9309276715e-002), + QTMFLLD(-3.8730087876e-001), QTMFLLD(2.7866455913e-001), + QTMFLLD(-2.5462667691e-004), QTMFLLD(-4.0301652625e-003), + QTMFLLD(-2.1115457639e-002), QTMFLLD(-4.0179058909e-001), + QTMFLLD(2.6768052578e-001), QTMFLLD(-2.7371285250e-004), + QTMFLLD(-4.1416347958e-003), QTMFLLD(-2.2980585694e-002), + QTMFLLD(-4.1630774736e-001), QTMFLLD(2.5687095523e-001), + QTMFLLD(-2.9165804153e-004), QTMFLLD(-4.2509674095e-003), + QTMFLLD(-2.4904217571e-002), QTMFLLD(-4.3084129691e-001), + QTMFLLD(2.4624188244e-001), QTMFLLD(-3.0837973463e-004), + QTMFLLD(-4.3581505306e-003), QTMFLLD(-2.6885753497e-002), + QTMFLLD(-4.4538003206e-001), QTMFLLD(2.3579898477e-001), + QTMFLLD(-3.2378203468e-004), QTMFLLD(-4.4631510973e-003), + QTMFLLD(-2.8924530372e-002), QTMFLLD(-4.5991250873e-001), + QTMFLLD(2.2554755211e-001), QTMFLLD(-3.3788106521e-004), + QTMFLLD(-4.5659458265e-003), QTMFLLD(-3.1019711867e-002), + QTMFLLD(-4.7442746162e-001), QTMFLLD(2.1549259126e-001), + QTMFLLD(-3.5053401371e-004), QTMFLLD(-4.6664695255e-003), + QTMFLLD(-3.3170353621e-002), QTMFLLD(-4.8891320825e-001), + QTMFLLD(2.0563863218e-001), QTMFLLD(-3.6175493733e-004), + QTMFLLD(-4.7647207975e-003), QTMFLLD(-3.5375438631e-002), + QTMFLLD(-5.0335830450e-001), QTMFLLD(1.9599021971e-001), + QTMFLLD(-3.7159718340e-004), QTMFLLD(-4.8605888151e-003), + QTMFLLD(-3.7633713335e-002), QTMFLLD(-5.1775097847e-001), + QTMFLLD(1.8655113876e-001), QTMFLLD(-3.7999937194e-004), + QTMFLLD(-4.9540083855e-003), QTMFLLD(-3.9943847805e-002), + QTMFLLD(-5.3207957745e-001), QTMFLLD(1.7732504010e-001), + QTMFLLD(-3.8705617771e-004), QTMFLLD(-5.0450465642e-003), + QTMFLLD(-4.2304381728e-002), QTMFLLD(-5.4633224010e-001), + QTMFLLD(1.6831515729e-001), QTMFLLD(-3.9281861973e-004), + QTMFLLD(-5.1336232573e-003), QTMFLLD(-4.4713638723e-002), + QTMFLLD(-5.6049734354e-001), QTMFLLD(1.5952435136e-001), + QTMFLLD(-3.9737694897e-004), QTMFLLD(-5.2197398618e-003), + QTMFLLD(-4.7170232981e-002), QTMFLLD(-5.7456302643e-001), + QTMFLLD(1.5095503628e-001), QTMFLLD(-4.0088107926e-004), + QTMFLLD(-5.3033372387e-003), QTMFLLD(-4.9672137946e-002), + QTMFLLD(-5.8851766586e-001), QTMFLLD(1.4260910451e-001), + QTMFLLD(-4.0338383405e-004), QTMFLLD(-5.3843962960e-003), + QTMFLLD(-5.2217379212e-002), QTMFLLD(-6.0234934092e-001), + QTMFLLD(1.3448855281e-001), QTMFLLD(-4.0505555808e-004), + QTMFLLD(-5.4629631341e-003), QTMFLLD(-5.4803829640e-002), + QTMFLLD(-6.1604642868e-001), QTMFLLD(1.2659475207e-001), + QTMFLLD(-4.0614881436e-004), QTMFLLD(-5.5389581248e-003), + QTMFLLD(-5.7429198176e-002), QTMFLLD(-6.2959736586e-001), + QTMFLLD(1.1892842501e-001), QTMFLLD(-4.0676075150e-004), + QTMFLLD(-5.6123761460e-003), QTMFLLD(-6.0090914369e-002), + QTMFLLD(-6.4299046993e-001), QTMFLLD(1.1149007827e-001), + QTMFLLD(-4.0709332097e-004), QTMFLLD(-5.6832311675e-003), + QTMFLLD(-6.2786586583e-002), QTMFLLD(-6.5621429682e-001), + QTMFLLD(1.0428040475e-001), QTMFLLD(-4.0732545312e-004), + QTMFLLD(-5.7515366934e-003), QTMFLLD(-6.5513409674e-002), + QTMFLLD(-6.6925734282e-001), QTMFLLD(9.7298897803e-002), + QTMFLLD(-4.0770808118e-004), QTMFLLD(-5.8172862045e-003), + QTMFLLD(-6.8268470466e-002), QTMFLLD(-6.8210834265e-001), + QTMFLLD(9.0545162559e-002), QTMFLLD(-4.0854664985e-004), + QTMFLLD(-5.8804959990e-003), QTMFLLD(-7.1048669517e-002), + QTMFLLD(-6.9475615025e-001), QTMFLLD(8.4017947316e-002), + QTMFLLD(-4.1002241778e-004), QTMFLLD(-5.9412117116e-003), + QTMFLLD(-7.3850922287e-002), QTMFLLD(-7.0718955994e-001), + QTMFLLD(7.7716566622e-002), QTMFLLD(-4.1239586426e-004), + QTMFLLD(-5.9994738549e-003), QTMFLLD(-7.6671779156e-002), + QTMFLLD(-7.1939796209e-001), QTMFLLD(7.1639508009e-002), + QTMFLLD(-4.1594370850e-004), QTMFLLD(-6.0553550720e-003), + QTMFLLD(-7.9507902265e-002), QTMFLLD(-7.3137050867e-001), + QTMFLLD(6.5784148872e-002), QTMFLLD(-4.2083335575e-004), + QTMFLLD(-6.1089023948e-003), QTMFLLD(-8.2355625927e-002), + QTMFLLD(-7.4309676886e-001), QTMFLLD(6.0148354620e-002), + QTMFLLD(-4.2732476140e-004), QTMFLLD(-6.1602159403e-003), + QTMFLLD(-8.5211075842e-002), QTMFLLD(-7.5456637144e-001), + QTMFLLD(5.4730266333e-002), QTMFLLD(-4.3563771760e-004), + QTMFLLD(-6.2093720771e-003), QTMFLLD(-8.8070511818e-002), + QTMFLLD(-7.6576924324e-001), QTMFLLD(4.9526259303e-002), + QTMFLLD(-4.4600359979e-004), QTMFLLD(-6.2565426342e-003), + QTMFLLD(-9.0929701924e-002), QTMFLLD(-7.7669566870e-001), + QTMFLLD(4.4533081353e-002), QTMFLLD(-4.5858716476e-004), + QTMFLLD(-6.3017667271e-003), QTMFLLD(-9.3784548342e-002), + QTMFLLD(-7.8733605146e-001), QTMFLLD(3.9746750146e-002), + QTMFLLD(-4.7345875646e-004), QTMFLLD(-6.3452622853e-003), + QTMFLLD(-9.6630692482e-002), QTMFLLD(-7.9768097401e-001), + QTMFLLD(3.5163912922e-002), QTMFLLD(-4.9076689174e-004), + QTMFLLD(-6.3871243037e-003), QTMFLLD(-9.9463671446e-002), + QTMFLLD(-8.0772149563e-001), QTMFLLD(3.0780877918e-002), + QTMFLLD(-5.1067111781e-004), QTMFLLD(-6.4275567420e-003), + QTMFLLD(-1.0227891803e-001), QTMFLLD(-8.1744915247e-001), + QTMFLLD(2.6590615511e-002), QTMFLLD(-5.3326232592e-004), + QTMFLLD(-6.4666904509e-003), QTMFLLD(-1.0507161170e-001), + QTMFLLD(-8.2685548067e-001), QTMFLLD(2.2588992491e-002), + QTMFLLD(-5.5855646497e-004), QTMFLLD(-6.5047293901e-003), + QTMFLLD(-1.0783691704e-001), QTMFLLD(-8.3593225479e-001), + QTMFLLD(1.8772648647e-002), QTMFLLD(-5.8640236966e-004), + QTMFLLD(-6.5418654121e-003), QTMFLLD(-1.1056987941e-001), + QTMFLLD(-8.4467232227e-001), QTMFLLD(1.5131668188e-002), + QTMFLLD(-6.1692652525e-004), QTMFLLD(-6.5783206373e-003), + QTMFLLD(-1.1326543987e-001), QTMFLLD(-8.5306841135e-001), + QTMFLLD(1.1661184952e-002), QTMFLLD(-6.4994930290e-004), + QTMFLLD(-6.6143544391e-003), QTMFLLD(-1.1591844261e-001), + QTMFLLD(-8.6111402512e-001), QTMFLLD(8.3509646356e-003), + QTMFLLD(-6.8494328298e-004), QTMFLLD(-6.6502285190e-003), + QTMFLLD(-1.1852371693e-001), QTMFLLD(-8.6880439520e-001), + QTMFLLD(5.1832948811e-003), QTMFLLD(-7.2404538514e-004), + QTMFLLD(-6.6861407831e-003), QTMFLLD(-1.2107557058e-001), + QTMFLLD(-8.7612599134e-001), QTMFLLD(2.2103153169e-003), + QTMFLLD(-7.7061145566e-004), QTMFLLD(-6.7221261561e-003), + QTMFLLD(-1.2356808037e-001), QTMFLLD(-8.8305824995e-001), + QTMFLLD(-4.6855807886e-004), QTMFLLD(-8.2158041187e-004), + QTMFLLD(-6.7584766075e-003), QTMFLLD(-1.2599521875e-001), + QTMFLLD(-8.8958823681e-001), QTMFLLD(-2.8003340121e-003), + QTMFLLD(-8.7498105131e-004), QTMFLLD(-6.7957863212e-003), + QTMFLLD(-1.2835204601e-001), QTMFLLD(-8.9572954178e-001), + QTMFLLD(-4.9293786287e-003), QTMFLLD(-9.2902814504e-004), + QTMFLLD(-6.8344431929e-003), QTMFLLD(-1.3063311577e-001), + QTMFLLD(-9.0148586035e-001), QTMFLLD(-6.9273295812e-003), + QTMFLLD(-9.8383461591e-004), QTMFLLD(-6.8746237084e-003), + QTMFLLD(-1.3283239305e-001), QTMFLLD(-9.0685033798e-001), + QTMFLLD(-8.7857460603e-003), QTMFLLD(-1.0395538993e-003), + QTMFLLD(-6.9165546447e-003), QTMFLLD(-1.3494376838e-001), + QTMFLLD(-9.1181802750e-001), QTMFLLD(-1.0507551953e-002), + QTMFLLD(-1.0959620122e-003), QTMFLLD(-6.9604511373e-003), + QTMFLLD(-1.3696120679e-001), QTMFLLD(-9.1638565063e-001), + QTMFLLD(-1.2103702873e-002), QTMFLLD(-1.1530250777e-003), + QTMFLLD(-7.0065916516e-003), QTMFLLD(-1.3887859881e-001), + QTMFLLD(-9.2054879665e-001), QTMFLLD(-1.3574197888e-002), + QTMFLLD(-1.2105966453e-003), QTMFLLD(-7.0552495308e-003), + QTMFLLD(-1.4068968594e-001), QTMFLLD(-9.2430406809e-001), + QTMFLLD(-1.4923358336e-002), QTMFLLD(-1.2681842782e-003), + QTMFLLD(-7.1066003293e-003), QTMFLLD(-1.4238841832e-001), + QTMFLLD(-9.2764878273e-001), QTMFLLD(-1.6156485304e-002), + QTMFLLD(-1.3256429229e-003), QTMFLLD(-7.1608433500e-003), + QTMFLLD(-1.4396859705e-001), QTMFLLD(-9.3058031797e-001), + QTMFLLD(-1.7277117819e-002), QTMFLLD(-1.3827638468e-003), + QTMFLLD(-7.2182063013e-003), QTMFLLD(-1.4542391896e-001), + QTMFLLD(-9.3309664726e-001), QTMFLLD(-1.8289361149e-002), + QTMFLLD(-1.4391905861e-003), QTMFLLD(-7.2789187543e-003), + QTMFLLD(-1.4674818516e-001), QTMFLLD(-9.3519610167e-001), + QTMFLLD(-1.9195662811e-002), QTMFLLD(-1.4947097516e-003), + QTMFLLD(-7.3430840857e-003), QTMFLLD(-1.4793521166e-001), + QTMFLLD(-9.3687731028e-001), QTMFLLD(-1.9999813288e-002), + QTMFLLD(-1.5489540529e-003), QTMFLLD(-7.4108825065e-003), + QTMFLLD(-1.4897871017e-001), QTMFLLD(-9.3813979626e-001), + QTMFLLD(-2.0706148818e-002), QTMFLLD(-1.6016908921e-003), + QTMFLLD(-7.4823615141e-003), QTMFLLD(-1.4987260103e-001), + QTMFLLD(-9.3898290396e-001), QTMFLLD(-2.1316919476e-002), + QTMFLLD(-1.6526894178e-003), QTMFLLD(-7.5576924719e-003), + QTMFLLD(-1.5061059594e-001), QTMFLLD(-9.3940681219e-001), + QTMFLLD(-2.1835187450e-002), QTMFLLD(-1.7015410122e-003), + QTMFLLD(-7.6368991286e-003), QTMFLLD(-1.5118667483e-001), + QTMFLLD(-9.3941211700e-001), QTMFLLD(-2.2264443338e-002), + QTMFLLD(-1.7479787348e-003), QTMFLLD(-7.7200052328e-003), + QTMFLLD(-1.5159477293e-001), QTMFLLD(-9.3899971247e-001), + QTMFLLD(-2.2607907653e-002), QTMFLLD(-1.7917567166e-003), + QTMFLLD(-7.8069791198e-003), QTMFLLD(-1.5182891488e-001), + QTMFLLD(-9.3817096949e-001), QTMFLLD(-2.2868644446e-002), + QTMFLLD(-1.8325200072e-003), QTMFLLD(-7.8977877274e-003), + QTMFLLD(-1.5188319981e-001), QTMFLLD(-9.3692785501e-001), + QTMFLLD(-2.3049183190e-002), QTMFLLD(-1.8700722139e-003), + QTMFLLD(-7.9923402518e-003), QTMFLLD(-1.5175175667e-001), + QTMFLLD(-9.3527245522e-001), QTMFLLD(-2.3152977228e-002), + QTMFLLD(-1.9041235792e-003), QTMFLLD(-8.0905584618e-003), + QTMFLLD(-1.5142890811e-001), QTMFLLD(-9.3320751190e-001), + QTMFLLD(-2.3183524609e-002), QTMFLLD(-1.9344078610e-003), + QTMFLLD(-8.1921815872e-003), QTMFLLD(-1.5090890229e-001), + QTMFLLD(-9.3073624372e-001), QTMFLLD(-2.3143447936e-002), + QTMFLLD(-1.9606938586e-003), QTMFLLD(-8.2970457152e-003), + QTMFLLD(-1.5018628538e-001), QTMFLLD(-9.2786192894e-001), + QTMFLLD(-2.3035895079e-002), QTMFLLD(-1.9826870412e-003), + QTMFLLD(-8.4048351273e-003), QTMFLLD(-1.4925561845e-001), + QTMFLLD(-9.2458862066e-001), QTMFLLD(-2.2864164785e-002), + QTMFLLD(-2.0002126694e-003), QTMFLLD(-8.5152359679e-003), + QTMFLLD(-1.4811170101e-001), QTMFLLD(-9.2092043161e-001), + QTMFLLD(-2.2631708533e-002), QTMFLLD(-2.0131117199e-003), + QTMFLLD(-8.6279176176e-003), QTMFLLD(-1.4674940705e-001), + QTMFLLD(-9.1686213017e-001), QTMFLLD(-2.2341690958e-002), + QTMFLLD(-2.0211567171e-003), QTMFLLD(-8.7425475940e-003), + QTMFLLD(-1.4516362548e-001), QTMFLLD(-9.1241872311e-001), + QTMFLLD(-2.1996961907e-002), QTMFLLD(-2.0242547616e-003), + QTMFLLD(-8.8585643098e-003), QTMFLLD(-1.4334976673e-001), + QTMFLLD(-9.0759557486e-001), QTMFLLD(-2.1601308137e-002), + QTMFLLD(-2.0221893210e-003), QTMFLLD(-8.9755039662e-003), + QTMFLLD(-1.4130303264e-001), QTMFLLD(-9.0239852667e-001), + QTMFLLD(-2.1158147603e-002), QTMFLLD(-2.0149163902e-003), + QTMFLLD(-9.0927295387e-003), QTMFLLD(-1.3901908696e-001), + QTMFLLD(-8.9683371782e-001), QTMFLLD(-2.0670616999e-002), + QTMFLLD(-2.0022888202e-003), QTMFLLD(-9.2095714062e-003), + QTMFLLD(-1.3649365306e-001), QTMFLLD(-8.9090716839e-001), + QTMFLLD(-2.0142132416e-002), QTMFLLD(-1.9841785543e-003), + QTMFLLD(-9.3253115192e-003), QTMFLLD(-1.3372266293e-001), + QTMFLLD(-8.8462579250e-001), QTMFLLD(-1.9576057792e-002), + QTMFLLD(-1.9606270362e-003), QTMFLLD(-9.4392402098e-003), + QTMFLLD(-1.3070219755e-001), QTMFLLD(-8.7799650431e-001), + QTMFLLD(-1.8976125866e-002), QTMFLLD(-1.9315859536e-003), + QTMFLLD(-9.5505062491e-003), QTMFLLD(-1.2742865086e-001), + QTMFLLD(-8.7102663517e-001), QTMFLLD(-1.8345680088e-002), + QTMFLLD(-1.8970289966e-003), QTMFLLD(-9.6583357081e-003), + QTMFLLD(-1.2389861047e-001), QTMFLLD(-8.6372399330e-001), + QTMFLLD(-1.7687706277e-002), QTMFLLD(-1.8569815438e-003), + QTMFLLD(-9.7616901621e-003), QTMFLLD(-1.2010899931e-001), + QTMFLLD(-8.5609632730e-001), QTMFLLD(-1.7006140202e-002), + QTMFLLD(-1.8114587292e-003), QTMFLLD(-9.8597351462e-003), + QTMFLLD(-1.1605655402e-001), QTMFLLD(-8.4815198183e-001), + QTMFLLD(-1.6304368153e-002), QTMFLLD(-1.7605143366e-003), + QTMFLLD(-9.9515644833e-003), QTMFLLD(-1.1173909158e-001), + QTMFLLD(-8.3989918232e-001), QTMFLLD(-1.5585509129e-002), + QTMFLLD(-1.7042002873e-003), QTMFLLD(-1.0036026128e-002), + QTMFLLD(-1.0715358704e-001), QTMFLLD(-8.3134686947e-001), + QTMFLLD(-1.4853162691e-002), QTMFLLD(-1.6426335787e-003), + QTMFLLD(-1.0111952201e-002), QTMFLLD(-1.0229838639e-001), + QTMFLLD(-8.2250368595e-001), QTMFLLD(-1.4110331424e-002), + QTMFLLD(-1.5758809168e-003), QTMFLLD(-1.0178210214e-002), + QTMFLLD(-9.7171187401e-002), QTMFLLD(-8.1337898970e-001), + QTMFLLD(-1.3360806741e-002), QTMFLLD(-1.5040797880e-003), + QTMFLLD(-1.0233603418e-002), QTMFLLD(-9.1770596802e-002), + QTMFLLD(-8.0398184061e-001), QTMFLLD(-1.2607692741e-002), + QTMFLLD(-1.4273397392e-003), QTMFLLD(-1.0276827961e-002), + QTMFLLD(-8.6095176637e-002), QTMFLLD(-7.9432225227e-001), + QTMFLLD(-1.1853585951e-002), QTMFLLD(-1.3458349276e-003), + QTMFLLD(-1.0306579992e-002), QTMFLLD(-8.0143928528e-002), + QTMFLLD(-7.8440952301e-001), QTMFLLD(-1.1102385819e-002), + QTMFLLD(-1.2597256573e-003), QTMFLLD(-1.0321546346e-002), + QTMFLLD(-7.3915921152e-002), QTMFLLD(-7.7425378561e-001), + QTMFLLD(-1.0356968269e-002), QTMFLLD(-1.1691439431e-003), + QTMFLLD(-1.0320378467e-002), QTMFLLD(-6.7410878837e-002), + QTMFLLD(-7.6386493444e-001), QTMFLLD(-9.6200043336e-003), + QTMFLLD(-1.0743001476e-003), QTMFLLD(-1.0301630013e-002), + QTMFLLD(-6.0628447682e-002), QTMFLLD(-7.5325345993e-001), + QTMFLLD(-8.8949296623e-003), QTMFLLD(-9.7535311943e-004), + QTMFLLD(-1.0263898410e-002), QTMFLLD(-5.3568758070e-002), + QTMFLLD(-7.4242949486e-001), QTMFLLD(-8.1837112084e-003), + QTMFLLD(-8.7248592172e-004), QTMFLLD(-1.0205759667e-002), + QTMFLLD(-4.6232450753e-002), QTMFLLD(-7.3140352964e-001), + QTMFLLD(-7.4901022017e-003), QTMFLLD(-7.6591013931e-004), + QTMFLLD(-1.0125675239e-002), QTMFLLD(-3.8619950414e-002), + QTMFLLD(-7.2018599510e-001), QTMFLLD(-6.8165790290e-003), + QTMFLLD(-6.5580842784e-004), QTMFLLD(-1.0022218339e-002), + QTMFLLD(-3.0732547864e-002), QTMFLLD(-7.0878815651e-001), + QTMFLLD(-6.1642420478e-003), QTMFLLD(-5.4247735534e-004), + QTMFLLD(-9.8937284201e-003), QTMFLLD(-2.2571478039e-002), + QTMFLLD(-6.9722014666e-001), QTMFLLD(-5.5373813957e-003), + QTMFLLD(-4.2596619460e-004), QTMFLLD(-9.7389295697e-003), + QTMFLLD(-1.4138570987e-002), QTMFLLD(-6.8549299240e-001), + QTMFLLD(-4.9372608773e-003), QTMFLLD(-3.0657128082e-004), + QTMFLLD(-9.5560895279e-003), QTMFLLD(-5.4356725886e-003), + QTMFLLD(-6.7361742258e-001), QTMFLLD(-4.3653072789e-003), + QTMFLLD(-1.8451632059e-004), QTMFLLD(-9.3438196927e-003), + QTMFLLD(3.5346730147e-003), QTMFLLD(-6.6160440445e-001), + QTMFLLD(-3.8251809310e-003), QTMFLLD(-6.0027297877e-005), + QTMFLLD(-9.1004446149e-003), QTMFLLD(1.2770005502e-002), + QTMFLLD(-6.4946544170e-001), QTMFLLD(-3.3147553913e-003), + QTMFLLD(6.6618180426e-005), QTMFLLD(-8.8245263323e-003), + QTMFLLD(2.2267201915e-002), QTMFLLD(-6.3721030951e-001), + QTMFLLD(-2.8387091588e-003), QTMFLLD(1.9518326735e-004), + QTMFLLD(-8.5145104676e-003), QTMFLLD(3.2023012638e-002), + QTMFLLD(-6.2485051155e-001), QTMFLLD(-2.3975048680e-003), + QTMFLLD(3.2545044087e-004), QTMFLLD(-8.1687811762e-003), + QTMFLLD(4.2033810169e-002), QTMFLLD(-6.1239802837e-001), + QTMFLLD(-1.9807203207e-003), QTMFLLD(4.5712510473e-004), + QTMFLLD(-7.7859172598e-003), QTMFLLD(5.2295893431e-002), + QTMFLLD(-5.9986191988e-001), QTMFLLD(-1.6010539839e-003), + QTMFLLD(5.9015140869e-004), QTMFLLD(-7.3645371012e-003), + QTMFLLD(6.2805138528e-002), QTMFLLD(-5.8725595474e-001), + QTMFLLD(-1.2320743408e-003), QTMFLLD(7.2508689482e-004), + QTMFLLD(-6.9030462764e-003), QTMFLLD(7.3557935655e-002), + QTMFLLD(-5.7460016012e-001), QTMFLLD(-7.9492607620e-004)}; + +//@{ +/*! + \name DCT_II twiddle factors, L=64 +*/ +/*! sin (3.14159265358979323 / (2*L) * n) , L=64*/ +LNK_SECTION_CONSTDATA +RAM_ALIGN +const FIXP_WTP sin_twiddle_L64[] = { + WTCP(0x7fffffff, 0x00000000), WTCP(0x7ff62182, 0x03242abf), + WTCP(0x7fd8878e, 0x0647d97c), WTCP(0x7fa736b4, 0x096a9049), + WTCP(0x7f62368f, 0x0c8bd35e), WTCP(0x7f0991c4, 0x0fab272b), + WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7e1d93ea, 0x15e21445), + WTCP(0x7d8a5f40, 0x18f8b83c), WTCP(0x7ce3ceb2, 0x1c0b826a), + WTCP(0x7c29fbee, 0x1f19f97b), WTCP(0x7b5d039e, 0x2223a4c5), + WTCP(0x7a7d055b, 0x25280c5e), WTCP(0x798a23b1, 0x2826b928), + WTCP(0x78848414, 0x2b1f34eb), WTCP(0x776c4edb, 0x2e110a62), + WTCP(0x7641af3d, 0x30fbc54d), WTCP(0x7504d345, 0x33def287), + WTCP(0x73b5ebd1, 0x36ba2014), WTCP(0x72552c85, 0x398cdd32), + WTCP(0x70e2cbc6, 0x3c56ba70), WTCP(0x6f5f02b2, 0x3f1749b8), + WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x6c242960, 0x447acd50), + WTCP(0x6a6d98a4, 0x471cece7), WTCP(0x68a69e81, 0x49b41533), + WTCP(0x66cf8120, 0x4c3fdff4), WTCP(0x64e88926, 0x4ebfe8a5), + WTCP(0x62f201ac, 0x5133cc94), WTCP(0x60ec3830, 0x539b2af0), + WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5cb420e0, 0x5842dd54), + WTCP(0x5a82799a, 0x5a82799a), WTCP(0x5842dd54, 0x5cb420e0), + WTCP(0x55f5a4d2, 0x5ed77c8a), WTCP(0x539b2af0, 0x60ec3830), + WTCP(0x5133cc94, 0x62f201ac), WTCP(0x4ebfe8a5, 0x64e88926), + WTCP(0x4c3fdff4, 0x66cf8120), WTCP(0x49b41533, 0x68a69e81), + WTCP(0x471cece7, 0x6a6d98a4), WTCP(0x447acd50, 0x6c242960), + WTCP(0x41ce1e65, 0x6dca0d14), WTCP(0x3f1749b8, 0x6f5f02b2), + WTCP(0x3c56ba70, 0x70e2cbc6), WTCP(0x398cdd32, 0x72552c85), + WTCP(0x36ba2014, 0x73b5ebd1), WTCP(0x33def287, 0x7504d345), + WTCP(0x30fbc54d, 0x7641af3d), WTCP(0x2e110a62, 0x776c4edb), + WTCP(0x2b1f34eb, 0x78848414), WTCP(0x2826b928, 0x798a23b1), + WTCP(0x25280c5e, 0x7a7d055b), WTCP(0x2223a4c5, 0x7b5d039e), + WTCP(0x1f19f97b, 0x7c29fbee), WTCP(0x1c0b826a, 0x7ce3ceb2), + WTCP(0x18f8b83c, 0x7d8a5f40), WTCP(0x15e21445, 0x7e1d93ea), + WTCP(0x12c8106f, 0x7e9d55fc), WTCP(0x0fab272b, 0x7f0991c4), + WTCP(0x0c8bd35e, 0x7f62368f), WTCP(0x096a9049, 0x7fa736b4), + WTCP(0x0647d97c, 0x7fd8878e), WTCP(0x03242abf, 0x7ff62182)}; + +const USHORT sqrt_tab[49] = { + 0x5a82, 0x5d4b, 0x6000, 0x62a1, 0x6531, 0x67b1, 0x6a21, 0x6c84, 0x6ed9, + 0x7123, 0x7360, 0x7593, 0x77bb, 0x79da, 0x7bef, 0x7dfb, 0x8000, 0x81fc, + 0x83f0, 0x85dd, 0x87c3, 0x89a3, 0x8b7c, 0x8d4e, 0x8f1b, 0x90e2, 0x92a4, + 0x9460, 0x9617, 0x97ca, 0x9977, 0x9b20, 0x9cc4, 0x9e64, 0xa000, 0xa197, + 0xa32b, 0xa4ba, 0xa646, 0xa7cf, 0xa953, 0xaad5, 0xac53, 0xadcd, 0xaf45, + 0xb0b9, 0xb22b, 0xb399, 0xb504}; + +LNK_SECTION_CONSTDATA_L1 +const FIXP_DBL invCount[80] = /* This could be 16-bit wide */ + {0x00000000, 0x7fffffff, 0x40000000, 0x2aaaaaab, 0x20000000, 0x1999999a, + 0x15555555, 0x12492492, 0x10000000, 0x0e38e38e, 0x0ccccccd, 0x0ba2e8ba, + 0x0aaaaaab, 0x09d89d8a, 0x09249249, 0x08888889, 0x08000000, 0x07878788, + 0x071c71c7, 0x06bca1af, 0x06666666, 0x06186186, 0x05d1745d, 0x0590b216, + 0x05555555, 0x051eb852, 0x04ec4ec5, 0x04bda12f, 0x04924925, 0x0469ee58, + 0x04444444, 0x04210842, 0x04000000, 0x03e0f83e, 0x03c3c3c4, 0x03a83a84, + 0x038e38e4, 0x03759f23, 0x035e50d8, 0x03483483, 0x03333333, 0x031f3832, + 0x030c30c3, 0x02fa0be8, 0x02e8ba2f, 0x02d82d83, 0x02c8590b, 0x02b93105, + 0x02aaaaab, 0x029cbc15, 0x028f5c29, 0x02828283, 0x02762762, 0x026a439f, + 0x025ed098, 0x0253c825, 0x02492492, 0x023ee090, 0x0234f72c, 0x022b63cc, + 0x02222222, 0x02192e2a, 0x02108421, 0x02082082, 0x02000000, 0x01f81f82, + 0x01f07c1f, 0x01e9131b, 0x01e1e1e2, 0x01dae607, 0x01d41d42, 0x01cd8569, + 0x01c71c72, 0x01c0e070, 0x01bacf91, 0x01b4e81b, 0x01af286c, 0x01a98ef6, + 0x01a41a42, 0x019ec8e9}; + +/* + * Bitstream data lists + */ + +/* + * AOT {2,5,29} + * epConfig = -1 + */ + +static const rbd_id_t el_aac_sce[] = { + adtscrc_start_reg1, element_instance_tag, global_gain, ics_info, + section_data, scale_factor_data, pulse, tns_data_present, tns_data, + gain_control_data_present, + /* gain_control_data, */ + spectral_data, adtscrc_end_reg1, end_of_sequence}; + +static const struct element_list node_aac_sce = {el_aac_sce, {NULL, NULL}}; + +/* CCE */ +static const rbd_id_t el_aac_cce[] = { + adtscrc_start_reg1, element_instance_tag, + coupled_elements, /* CCE specific */ + global_gain, ics_info, section_data, scale_factor_data, pulse, + tns_data_present, tns_data, gain_control_data_present, + /* gain_control_data, */ + spectral_data, gain_element_lists, /* CCE specific */ + adtscrc_end_reg1, end_of_sequence}; + +static const struct element_list node_aac_cce = {el_aac_cce, {NULL, NULL}}; + +static const rbd_id_t el_aac_cpe[] = {adtscrc_start_reg1, element_instance_tag, + common_window, link_sequence}; + +static const rbd_id_t el_aac_cpe0[] = { + /*common_window = 0*/ + global_gain, ics_info, section_data, scale_factor_data, pulse, + tns_data_present, tns_data, gain_control_data_present, + /*gain_control_data,*/ + spectral_data, next_channel, + + adtscrc_start_reg2, global_gain, ics_info, section_data, scale_factor_data, + pulse, tns_data_present, tns_data, gain_control_data_present, + /*gain_control_data,*/ + spectral_data, adtscrc_end_reg1, adtscrc_end_reg2, end_of_sequence}; + +static const rbd_id_t el_aac_cpe1[] = { + /* common_window = 1 */ + ics_info, ms, + + global_gain, section_data, scale_factor_data, pulse, tns_data_present, + tns_data, gain_control_data_present, + /*gain_control_data,*/ + spectral_data, next_channel, + + adtscrc_start_reg2, global_gain, section_data, scale_factor_data, pulse, + tns_data_present, tns_data, gain_control_data_present, + /*gain_control_data,*/ + spectral_data, adtscrc_end_reg1, adtscrc_end_reg2, end_of_sequence}; + +static const struct element_list node_aac_cpe0 = {el_aac_cpe0, {NULL, NULL}}; + +static const struct element_list node_aac_cpe1 = {el_aac_cpe1, {NULL, NULL}}; + +static const element_list_t node_aac_cpe = {el_aac_cpe, + {&node_aac_cpe0, &node_aac_cpe1}}; + +/* + * AOT C- {17,23} + * epConfig = 0,1 + */ +static const rbd_id_t el_aac_sce_epc0[] = { + element_instance_tag, + global_gain, + ics_info, + section_data, + scale_factor_data, + pulse, + tns_data_present, + gain_control_data_present, + gain_control_data, + esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + tns_data, + spectral_data, + end_of_sequence}; + +static const struct element_list node_aac_sce_epc0 = {el_aac_sce_epc0, + {NULL, NULL}}; + +static const rbd_id_t el_aac_sce_epc1[] = { + element_instance_tag, global_gain, ics_info, section_data, + scale_factor_data, pulse, tns_data_present, gain_control_data_present, + /*gain_control_data,*/ + esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + tns_data, spectral_data, end_of_sequence}; + +static const struct element_list node_aac_sce_epc1 = {el_aac_sce_epc1, + {NULL, NULL}}; + +static const rbd_id_t el_aac_cpe_epc0[] = {element_instance_tag, common_window, + link_sequence}; + +static const rbd_id_t el_aac_cpe0_epc0[] = { + /* common_window = 0 */ + /* ESC 1: */ + global_gain, ics_info, + /* ltp_data_present, + ltp_data, + */ + section_data, scale_factor_data, pulse, tns_data_present, + gain_control_data_present, + /*gain_control_data,*/ + esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + /* ESC 2: */ + esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + /* ESC 3: */ + tns_data, + /* ESC 4: */ + spectral_data, next_channel, + + /* ESC 1: */ + global_gain, ics_info, + /* ltp_data_present, + ltp_data, + */ + section_data, scale_factor_data, pulse, tns_data_present, + gain_control_data_present, + /*gain_control_data,*/ + esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + /* ESC 2: */ + esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + /* ESC 3: */ + tns_data, + /* ESC 4: */ + spectral_data, end_of_sequence}; + +static const rbd_id_t el_aac_cpe1_epc0[] = { + /* common_window = 1 */ + /* ESC 0: */ + ics_info, + /* ltp_data_present, + ltp_data, + next_channel, + ltp_data_present, + ltp_data, + next_channel, + */ + ms, + + /* ESC 1: */ + global_gain, section_data, scale_factor_data, pulse, tns_data_present, + gain_control_data_present, + /*gain_control_data,*/ + esc1_hcr, /* length_of_reordered_spectral_data, length_of_longest_codeword + */ + /* ESC 2: */ + esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + /* ESC 3: */ + tns_data, + /* ESC 4: */ + spectral_data, next_channel, + + /* ESC 1: */ + global_gain, section_data, scale_factor_data, pulse, tns_data_present, + gain_control_data_present, + /*gain_control_data,*/ + esc1_hcr, /* length_of_reordered_spectral_data, length_of_longest_codeword + */ + /* ESC 2: */ + esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + /* ESC 3: */ + tns_data, + /* ESC 4: */ + spectral_data, end_of_sequence}; + +static const struct element_list node_aac_cpe0_epc0 = {el_aac_cpe0_epc0, + {NULL, NULL}}; + +static const struct element_list node_aac_cpe1_epc0 = {el_aac_cpe1_epc0, + {NULL, NULL}}; + +static const element_list_t node_aac_cpe_epc0 = { + el_aac_cpe_epc0, {&node_aac_cpe0_epc0, &node_aac_cpe1_epc0}}; + +static const rbd_id_t el_aac_cpe0_epc1[] = { + global_gain, ics_info, section_data, scale_factor_data, pulse, + tns_data_present, gain_control_data_present, + /*gain_control_data,*/ + next_channel, global_gain, ics_info, section_data, scale_factor_data, pulse, + tns_data_present, gain_control_data_present, + /*gain_control_data,*/ + next_channel, esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + next_channel, esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + next_channel, esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + next_channel, esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + next_channel, tns_data, next_channel, tns_data, next_channel, spectral_data, + next_channel, spectral_data, end_of_sequence}; + +static const rbd_id_t el_aac_cpe1_epc1[] = { + ics_info, ms, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, pulse, tns_data_present, + gain_control_data_present, + /*gain_control_data,*/ + next_channel, + + ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, pulse, tns_data_present, + gain_control_data_present, + /*gain_control_data,*/ + next_channel, esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + next_channel, esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + next_channel, esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + next_channel, esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + + next_channel, tns_data, next_channel, tns_data, next_channel, spectral_data, + next_channel, spectral_data, end_of_sequence}; + +static const struct element_list node_aac_cpe0_epc1 = {el_aac_cpe0_epc1, + {NULL, NULL}}; + +static const struct element_list node_aac_cpe1_epc1 = {el_aac_cpe1_epc1, + {NULL, NULL}}; + +static const element_list_t node_aac_cpe_epc1 = { + el_aac_cpe, {&node_aac_cpe0_epc1, &node_aac_cpe1_epc1}}; + +/* + * AOT = 20 + * epConfig = 0 + */ +static const rbd_id_t el_scal_sce_epc0[] = {ics_info, /* ESC 1 */ + tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, + scale_factor_data, esc1_hcr, + esc2_rvlc, /* ESC 2 */ + tns_data, /* ESC 3 */ + spectral_data, /* ESC 4 */ + end_of_sequence}; + +static const struct element_list node_scal_sce_epc0 = {el_scal_sce_epc0, + {NULL, NULL}}; + +static const rbd_id_t el_scal_cpe_epc0[] = { + ics_info, /* ESC 0 */ + ms, tns_data_present, /* ESC 1 (ch 0) */ + ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, + esc2_rvlc, /* ESC 2 (ch 0) */ + tns_data, /* ESC 3 (ch 0) */ + spectral_data, /* ESC 4 (ch 0) */ + next_channel, tns_data_present, /* ESC 1 (ch 1) */ + ltp_data_present, global_gain, section_data, scale_factor_data, esc1_hcr, + esc2_rvlc, /* ESC 2 (ch 1) */ + tns_data, /* ESC 3 (ch 1) */ + spectral_data, /* ESC 4 (ch 1) */ + end_of_sequence}; + +static const struct element_list node_scal_cpe_epc0 = {el_scal_cpe_epc0, + {NULL, NULL}}; + +/* + * AOT = 20 + * epConfig = 1 + */ +static const rbd_id_t el_scal_sce_epc1[] = { + ics_info, tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, tns_data, + spectral_data, end_of_sequence}; + +static const struct element_list node_scal_sce_epc1 = {el_scal_sce_epc1, + {NULL, NULL}}; + +static const rbd_id_t el_scal_cpe_epc1[] = { + ics_info, ms, tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, next_channel, + tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, next_channel, + tns_data, next_channel, tns_data, next_channel, spectral_data, next_channel, + spectral_data, end_of_sequence}; + +static const struct element_list node_scal_cpe_epc1 = {el_scal_cpe_epc1, + {NULL, NULL}}; + +/* + * Pseudo AOT for DRM/DRM+ (similar to AOT 20) + */ +static const rbd_id_t el_drm_sce[] = { + drmcrc_start_reg, ics_info, tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, tns_data, + drmcrc_end_reg, spectral_data, end_of_sequence}; + +static const struct element_list node_drm_sce = {el_drm_sce, {NULL, NULL}}; + +static const rbd_id_t el_drm_cpe[] = { + drmcrc_start_reg, ics_info, ms, tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, next_channel, + tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, next_channel, + tns_data, next_channel, tns_data, drmcrc_end_reg, next_channel, + spectral_data, next_channel, spectral_data, end_of_sequence}; + +static const struct element_list node_drm_cpe = {el_drm_cpe, {NULL, NULL}}; + +/* + * AOT = 39 + * epConfig = 0 + */ +static const rbd_id_t el_eld_sce_epc0[] = { + global_gain, ics_info, section_data, scale_factor_data, tns_data_present, + tns_data, esc1_hcr, esc2_rvlc, spectral_data, end_of_sequence}; + +static const struct element_list node_eld_sce_epc0 = {el_eld_sce_epc0, + {NULL, NULL}}; + +#define node_eld_sce_epc1 node_eld_sce_epc0 + +static const rbd_id_t el_eld_cpe_epc0[] = {ics_info, ms, + global_gain, section_data, + scale_factor_data, tns_data_present, + tns_data, esc1_hcr, + esc2_rvlc, spectral_data, + next_channel, global_gain, + section_data, scale_factor_data, + tns_data_present, tns_data, + esc1_hcr, esc2_rvlc, + spectral_data, end_of_sequence}; + +static const rbd_id_t el_eld_cpe_epc1[] = {ics_info, ms, + global_gain, section_data, + scale_factor_data, tns_data_present, + next_channel, global_gain, + section_data, scale_factor_data, + tns_data_present, next_channel, + tns_data, next_channel, + tns_data, next_channel, + esc1_hcr, esc2_rvlc, + spectral_data, next_channel, + esc1_hcr, esc2_rvlc, + spectral_data, end_of_sequence}; + +static const struct element_list node_eld_cpe_epc0 = {el_eld_cpe_epc0, + {NULL, NULL}}; + +static const struct element_list node_eld_cpe_epc1 = {el_eld_cpe_epc1, + {NULL, NULL}}; + +/* + * AOT = 42 + * epConfig = 0 + */ + +static const rbd_id_t el_usac_coremode[] = {core_mode, next_channel, + link_sequence}; + +static const rbd_id_t el_usac_sce0_epc0[] = { + tns_data_present, + /* fd_channel_stream */ + global_gain, noise, ics_info, tw_data, scale_factor_data_usac, tns_data, + ac_spectral_data, fac_data, end_of_sequence}; + +static const rbd_id_t el_usac_lfe_epc0[] = { + /* fd_channel_stream */ + global_gain, ics_info, scale_factor_data_usac, + ac_spectral_data, fac_data, end_of_sequence}; + +static const rbd_id_t el_usac_lpd_epc0[] = {lpd_channel_stream, + end_of_sequence}; + +static const struct element_list node_usac_sce0_epc0 = {el_usac_sce0_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_sce1_epc0 = {el_usac_lpd_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_sce_epc0 = { + el_usac_coremode, {&node_usac_sce0_epc0, &node_usac_sce1_epc0}}; + +static const rbd_id_t list_usac_cpe00_epc0[] = {tns_active, common_window, + link_sequence}; + +static const rbd_id_t el_usac_common_tw[] = {common_tw, link_sequence}; + +static const rbd_id_t list_usac_cpe0000_epc0[] = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 0 */ + /* common_tw = 0 */ + tns_data_present_usac, + global_gain, + noise, + ics_info, + tw_data, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + next_channel, + global_gain, + noise, + ics_info, + tw_data, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + end_of_sequence}; + +static const rbd_id_t list_usac_cpe0001_epc0[] = { + /* + core_mode0 = 0 + core_mode1 = 0 + common_window = 0 + common_tw = 1 + */ + tw_data, tns_data_present_usac, global_gain, noise, + ics_info, scale_factor_data_usac, tns_data, ac_spectral_data, + fac_data, next_channel, global_gain, noise, + ics_info, scale_factor_data_usac, tns_data, ac_spectral_data, + fac_data, end_of_sequence}; + +static const rbd_id_t list_usac_cpe001_epc0[] = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 1 */ + ics_info, common_max_sfb, ms, common_tw, link_sequence}; + +static const rbd_id_t list_usac_cpe0010_epc0[] = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 1 */ + /* common_tw = 0 */ + tns_data_present_usac, + global_gain, + noise, + tw_data, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + next_channel, + global_gain, + noise, + tw_data, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + end_of_sequence}; + +static const rbd_id_t list_usac_cpe0011_epc0[] = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 1 */ + /* common_tw = 1 */ + tw_data, + tns_data_present_usac, + global_gain, + noise, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + next_channel, + global_gain, + noise, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + end_of_sequence}; + +static const rbd_id_t list_usac_cpe10_epc0[] = { + /* core_mode0 = 1 */ + /* core_mode1 = 0 */ + lpd_channel_stream, + next_channel, + tns_data_present, + global_gain, + noise, + ics_info, + tw_data, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + end_of_sequence}; + +static const rbd_id_t list_usac_cpe01_epc0[] = { + /* core_mode0 = 0 */ + /* core_mode1 = 1 */ + tns_data_present, + global_gain, + noise, + ics_info, + tw_data, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + next_channel, + lpd_channel_stream, + end_of_sequence}; + +static const rbd_id_t list_usac_cpe11_epc0[] = { + /* core_mode0 = 1 */ + /* core_mode1 = 1 */ + lpd_channel_stream, next_channel, lpd_channel_stream, end_of_sequence}; + +static const struct element_list node_usac_cpe0000_epc0 = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 0 */ + /* common_tw = 0 */ + list_usac_cpe0000_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe0010_epc0 = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 1 */ + /* common_tw = 0 */ + list_usac_cpe0010_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe0001_epc0 = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 0 */ + /* common_tw = 1 */ + list_usac_cpe0001_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe0011_epc0 = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 1 */ + /* common_tw = 1 */ + list_usac_cpe0011_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe000_epc0 = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 0 */ + el_usac_common_tw, + {&node_usac_cpe0000_epc0, &node_usac_cpe0001_epc0}}; + +static const struct element_list node_usac_cpe001_epc0 = { + list_usac_cpe001_epc0, {&node_usac_cpe0010_epc0, &node_usac_cpe0011_epc0}}; + +static const struct element_list node_usac_cpe00_epc0 = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + list_usac_cpe00_epc0, + {&node_usac_cpe000_epc0, &node_usac_cpe001_epc0}}; + +static const struct element_list node_usac_cpe10_epc0 = { + /* core_mode0 = 1 */ + /* core_mode1 = 0 */ + list_usac_cpe10_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe01_epc0 = {list_usac_cpe01_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe11_epc0 = {list_usac_cpe11_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe0_epc0 = { + /* core_mode0 = 0 */ + el_usac_coremode, + {&node_usac_cpe00_epc0, &node_usac_cpe01_epc0}}; + +static const struct element_list node_usac_cpe1_epc0 = { + /* core_mode0 = 1 */ + el_usac_coremode, + {&node_usac_cpe10_epc0, &node_usac_cpe11_epc0}}; + +static const struct element_list node_usac_cpe_epc0 = { + el_usac_coremode, {&node_usac_cpe0_epc0, &node_usac_cpe1_epc0}}; + +static const struct element_list node_usac_lfe_epc0 = {el_usac_lfe_epc0, + {NULL, NULL}}; + +const element_list_t *getBitstreamElementList(AUDIO_OBJECT_TYPE aot, + SCHAR epConfig, UCHAR nChannels, + UCHAR layer, UINT elFlags) { + switch (aot) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + FDK_ASSERT(epConfig == -1); + if (elFlags & AC_EL_GA_CCE) { + return &node_aac_cce; + } else { + if (nChannels == 1) { + return &node_aac_sce; + } else { + return &node_aac_cpe; + } + } + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: + if (nChannels == 1) { + if (epConfig == 0) { + return &node_aac_sce_epc0; + } else { + return &node_aac_sce_epc1; + } + } else { + if (epConfig == 0) + return &node_aac_cpe_epc0; + else + return &node_aac_cpe_epc1; + } + case AOT_USAC: + if (elFlags & AC_EL_USAC_LFE) { + FDK_ASSERT(nChannels == 1); + return &node_usac_lfe_epc0; + } + if (nChannels == 1) { + return &node_usac_sce_epc0; + } else { + return &node_usac_cpe_epc0; + } + case AOT_ER_AAC_SCAL: + if (nChannels == 1) { + if (epConfig <= 0) + return &node_scal_sce_epc0; + else + return &node_scal_sce_epc1; + } else { + if (epConfig <= 0) + return &node_scal_cpe_epc0; + else + return &node_scal_cpe_epc1; + } + case AOT_ER_AAC_ELD: + if (nChannels == 1) { + if (epConfig <= 0) + return &node_eld_sce_epc0; + else + return &node_eld_sce_epc1; + } else { + if (epConfig <= 0) + return &node_eld_cpe_epc0; + else + return &node_eld_cpe_epc1; + } + case AOT_DRM_AAC: + case AOT_DRM_SBR: + case AOT_DRM_MPEG_PS: + case AOT_DRM_SURROUND: + FDK_ASSERT(epConfig == 1); + if (nChannels == 1) { + return &node_drm_sce; + } else { + return &node_drm_cpe; + } + default: + break; + } + return NULL; +} + +/* Inverse square root table for operands running from 0.5 to ~1.0 */ +/* (INT) (0.5 + 1.0/sqrt((op)/FDKpow(2.0,31))); */ +/* Note: First value is rnot rounded for accuracy reasons */ +/* Implicit exponent is 1. */ +/* Examples: 0x5A82799A = invSqrtNorm2 (0x4000.0000), exp=1 */ +/* 0x5A82799A = invSqrtNorm2 (0x4000.0000), exp=1 */ + +LNK_SECTION_CONSTDATA_L1 +const FIXP_DBL invSqrtTab[SQRT_VALUES] = { + 0x5A827999, 0x5A287E03, 0x59CF8CBC, 0x5977A0AC, 0x5920B4DF, 0x58CAC480, + 0x5875CADE, 0x5821C364, 0x57CEA99D, 0x577C7930, 0x572B2DE0, 0x56DAC38E, + 0x568B3632, 0x563C81E0, 0x55EEA2C4, 0x55A19522, 0x55555555, 0x5509DFD0, + 0x54BF311A, 0x547545D0, 0x542C1AA4, 0x53E3AC5B, 0x539BF7CD, 0x5354F9E7, + 0x530EAFA5, 0x52C91618, 0x52842A5F, 0x523FE9AC, 0x51FC5140, 0x51B95E6B, + 0x51770E8F, 0x51355F1A, 0x50F44D89, 0x50B3D768, 0x5073FA50, 0x5034B3E7, + 0x4FF601E0, 0x4FB7E1FA, 0x4F7A5202, 0x4F3D4FCF, 0x4F00D944, 0x4EC4EC4F, + 0x4E8986EA, 0x4E4EA718, 0x4E144AE9, 0x4DDA7073, 0x4DA115DA, 0x4D683948, + 0x4D2FD8F4, 0x4CF7F31B, 0x4CC08605, 0x4C899000, 0x4C530F65, 0x4C1D0294, + 0x4BE767F5, 0x4BB23DF9, 0x4B7D8317, 0x4B4935CF, 0x4B1554A6, 0x4AE1DE2A, + 0x4AAED0F0, 0x4A7C2B93, 0x4A49ECB3, 0x4A1812FA, 0x49E69D16, 0x49B589BB, + 0x4984D7A4, 0x49548592, 0x49249249, 0x48F4FC97, 0x48C5C34B, 0x4896E53D, + 0x48686148, 0x483A364D, 0x480C6332, 0x47DEE6E1, 0x47B1C049, 0x4784EE60, + 0x4758701C, 0x472C447C, 0x47006A81, 0x46D4E130, 0x46A9A794, 0x467EBCBA, + 0x46541FB4, 0x4629CF98, 0x45FFCB80, 0x45D6128A, 0x45ACA3D5, 0x45837E88, + 0x455AA1CB, 0x45320CC8, 0x4509BEB0, 0x44E1B6B4, 0x44B9F40B, 0x449275ED, + 0x446B3B96, 0x44444444, 0x441D8F3B, 0x43F71BBF, 0x43D0E917, 0x43AAF68F, + 0x43854374, 0x435FCF15, 0x433A98C6, 0x43159FDC, 0x42F0E3AE, 0x42CC6398, + 0x42A81EF6, 0x42841527, 0x4260458E, 0x423CAF8D, 0x4219528B, 0x41F62DF2, + 0x41D3412A, 0x41B08BA2, 0x418E0CC8, 0x416BC40D, 0x4149B0E5, 0x4127D2C3, + 0x41062920, 0x40E4B374, 0x40C3713B, 0x40A261EF, 0x40818512, 0x4060DA22, + 0x404060A1, 0x40201814, 0x40000000, 0x3FE017EC /* , 0x3FC05F61 */ +}; + +/* number of channels of the formats */ + +const INT format_nchan[FDK_NFORMATS + 9 - 2] = { + 0, /* any set-up, ChConfIdx = 0 */ + 1, /* mono ChConfIdx = 1 */ + 2, /* stereo ChConfIdx = 2 */ + 3, /* 3/0.0 ChConfIdx = 3 */ + 4, /* 3/1.0 ChConfIdx = 4 */ + 5, /* 3/2.0 ChConfIdx = 5 */ + 6, /* 5.1 ChConfIdx = 6 */ + 8, /* 5/2.1 ALT ChConfIdx = 7 */ + 0, /* Empty n.a. ChConfIdx = 8 */ + 3, /* 2/1.0 ChConfIdx = 9 */ + 4, /* 2/2.0 ChConfIdx = 10 */ + 7, /* 3/3.1 ChConfIdx = 11 */ + 8, /* 3/4.1 ChConfIdx = 12 */ + 24, /* 22.2 ChConfIdx = 13 */ + 8, /* 5/2.1 ChConfIdx = 14 */ + 12, /* 5/5.2 ChConfIdx = 15 */ + 10, /* 5/4.1 ChConfIdx = 16 */ + 12, /* 6/5.1 ChConfIdx = 17 */ + 14, /* 6/7.1 ChConfIdx = 18 */ + 12, /* 5/6.1 ChConfIdx = 19 */ + 14 /* 7/6.1 ChConfIdx = 20 */ +}; diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_trigFcts.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_trigFcts.cpp new file mode 100644 index 0000000000000..4bb62622ad1ac --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/FDK_trigFcts.cpp @@ -0,0 +1,340 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Haricharan Lakshman, Manuel Jander + + Description: Trigonometric functions fixed point fractional implementation. + +*******************************************************************************/ + +#include "FDK_trigFcts.h" + +#include "fixpoint_math.h" + +#define IMPROVE_ATAN2_ACCURACY 1 /* 0 --> 59 dB SNR 1 --> 65 dB SNR */ +#define MINSFTAB 7 +#define MAXSFTAB 25 + +#if IMPROVE_ATAN2_ACCURACY +static const FIXP_DBL f_atan_expand_range[MAXSFTAB - (MINSFTAB - 1)] = { + /***************************************************************************** + * + * Table holds fixp_atan() output values which are outside of input range + * of fixp_atan() to improve SNR of fixp_atan2(). + * + * This Table might also be used in fixp_atan() so there a wider input + * range can be covered, too. + * + *****************************************************************************/ + FL2FXCONST_DBL(7.775862990872099e-001), + FL2FXCONST_DBL(7.814919928673978e-001), + FL2FXCONST_DBL(7.834450483314648e-001), + FL2FXCONST_DBL(7.844216021392089e-001), + FL2FXCONST_DBL(7.849098823026687e-001), + FL2FXCONST_DBL(7.851540227918509e-001), + FL2FXCONST_DBL(7.852760930873737e-001), + FL2FXCONST_DBL(7.853371282415015e-001), + FL2FXCONST_DBL(7.853676458193612e-001), + FL2FXCONST_DBL(7.853829046083906e-001), + FL2FXCONST_DBL(7.853905340029177e-001), + FL2FXCONST_DBL(7.853943487001828e-001), + FL2FXCONST_DBL(7.853962560488155e-001), + FL2FXCONST_DBL(7.853972097231319e-001), + FL2FXCONST_DBL(7.853976865602901e-001), + FL2FXCONST_DBL(7.853979249788692e-001), + FL2FXCONST_DBL(7.853980441881587e-001), + FL2FXCONST_DBL(7.853981037928035e-001), + FL2FXCONST_DBL(7.853981335951259e-001) + /* pi/4 = 0.785398163397448 = pi/2/ATO_SCALE */ +}; +#endif + +FIXP_DBL fixp_atan2(FIXP_DBL y, FIXP_DBL x) { + FIXP_DBL q; + FIXP_DBL at; /* atan out */ + FIXP_DBL at2; /* atan2 out */ + FIXP_DBL ret = FL2FXCONST_DBL(-1.0f); + INT sf, sfo, stf; + + /* --- division */ + + if (y > FL2FXCONST_DBL(0.0f)) { + if (x > FL2FXCONST_DBL(0.0f)) { + q = fDivNormHighPrec(y, x, &sf); /* both pos. */ + } else if (x < FL2FXCONST_DBL(0.0f)) { + q = -fDivNormHighPrec(y, -x, &sf); /* x neg. */ + } else { /* (x == FL2FXCONST_DBL(0.0f)) */ + q = FL2FXCONST_DBL(+1.0f); /* y/x = pos/zero = +Inf */ + sf = 0; + } + } else if (y < FL2FXCONST_DBL(0.0f)) { + if (x > FL2FXCONST_DBL(0.0f)) { + q = -fDivNormHighPrec(-y, x, &sf); /* y neg. */ + } else if (x < FL2FXCONST_DBL(0.0f)) { + q = fDivNormHighPrec(-y, -x, &sf); /* both neg. */ + } else { /* (x == FL2FXCONST_DBL(0.0f)) */ + q = FL2FXCONST_DBL(-1.0f); /* y/x = neg/zero = -Inf */ + sf = 0; + } + } else { /* (y == FL2FXCONST_DBL(0.0f)) */ + q = FL2FXCONST_DBL(0.0f); + sf = 0; + } + sfo = sf; + + /* --- atan() */ + + if (sfo > ATI_SF) { + /* --- could not calc fixp_atan() here bec of input data out of range */ + /* ==> therefore give back boundary values */ + +#if IMPROVE_ATAN2_ACCURACY + if (sfo > MAXSFTAB) sfo = MAXSFTAB; +#endif + + if (q > FL2FXCONST_DBL(0.0f)) { +#if IMPROVE_ATAN2_ACCURACY + at = +f_atan_expand_range[sfo - ATI_SF - 1]; +#else + at = FL2FXCONST_DBL(+M_PI / 2 / ATO_SCALE); +#endif + } else if (q < FL2FXCONST_DBL(0.0f)) { +#if IMPROVE_ATAN2_ACCURACY + at = -f_atan_expand_range[sfo - ATI_SF - 1]; +#else + at = FL2FXCONST_DBL(-M_PI / 2 / ATO_SCALE); +#endif + } else { /* q == FL2FXCONST_DBL(0.0f) */ + at = FL2FXCONST_DBL(0.0f); + } + } else { + /* --- calc of fixp_atan() is possible; input data within range */ + /* ==> set q on fixed scale level as desired from fixp_atan() */ + stf = sfo - ATI_SF; + if (stf > 0) + q = q << (INT)fMin(stf, DFRACT_BITS - 1); + else + q = q >> (INT)fMin(-stf, DFRACT_BITS - 1); + at = fixp_atan(q); /* ATO_SF */ + } + + // --- atan2() + + at2 = at >> (AT2O_SF - ATO_SF); // now AT2O_SF for atan2 + if (x > FL2FXCONST_DBL(0.0f)) { + ret = at2; + } else if (x < FL2FXCONST_DBL(0.0f)) { + if (y >= FL2FXCONST_DBL(0.0f)) { + ret = at2 + FL2FXCONST_DBL(M_PI / AT2O_SCALE); + } else { + ret = at2 - FL2FXCONST_DBL(M_PI / AT2O_SCALE); + } + } else { + // x == 0 + if (y > FL2FXCONST_DBL(0.0f)) { + ret = FL2FXCONST_DBL(+M_PI / 2 / AT2O_SCALE); + } else if (y < FL2FXCONST_DBL(0.0f)) { + ret = FL2FXCONST_DBL(-M_PI / 2 / AT2O_SCALE); + } else if (y == FL2FXCONST_DBL(0.0f)) { + ret = FL2FXCONST_DBL(0.0f); + } + } + return ret; +} + +FIXP_DBL fixp_atan(FIXP_DBL x) { + INT sign; + FIXP_DBL result, temp; + + /* SNR of fixp_atan() = 56 dB */ + FIXP_DBL P281 = (FIXP_DBL)0x00013000; // 0.281 in q18 + FIXP_DBL ONEP571 = (FIXP_DBL)0x6487ef00; // 1.571 in q30 + + if (x < FIXP_DBL(0)) { + sign = 1; + x = -x; + } else { + sign = 0; + } + FDK_ASSERT(FL2FXCONST_DBL(1.0 / 64.0) == Q(Q_ATANINP)); + /* calc of arctan */ + if (x < FL2FXCONST_DBL(1.0 / 64.0)) + /* + Chebyshev polynomial approximation of atan(x) + 5th-order approximation: atan(x) = a1*x + a2*x^3 + a3*x^5 = x(a1 + x^2*(a2 + + a3*x^2)); a1 = 0.9949493661166540f, a2 = 0.2870606355326520f, a3 = + 0.0780371764464410f; 7th-order approximation: atan(x) = a1*x + a2*x^3 + + a3*x^5 + a3*x^7 = x(a1 + x^2*(a2 + x^2*(a3 + a4*x^2))); a1 = + 0.9991334482227801, a2 = -0.3205332923816640, a3 = 0.1449824901444650, a4 = + -0.0382544649702990; 7th-order approximation in use (the most accurate + solution) + */ + { + x <<= ATI_SF; + FIXP_DBL x2 = fPow2(x); + temp = fMultAddDiv2((FL2FXCONST_DBL(0.1449824901444650f) >> 1), x2, + FL2FXCONST_DBL(-0.0382544649702990)); + temp = fMultAddDiv2((FL2FXCONST_DBL(-0.3205332923816640f) >> 2), x2, temp); + temp = fMultAddDiv2((FL2FXCONST_DBL(0.9991334482227801f) >> 3), x2, temp); + result = fMult(x, (temp << 2)); + } else if (x < FL2FXCONST_DBL(1.28 / 64.0)) { + FIXP_DBL delta_fix; + FIXP_DBL PI_BY_4 = FL2FXCONST_DBL(3.1415926 / 4.0) >> 1; /* pi/4 in q30 */ + + delta_fix = (x - FL2FXCONST_DBL(1.0 / 64.0)) << 5; /* q30 */ + result = PI_BY_4 + (delta_fix >> 1) - (fPow2Div2(delta_fix)); + } else { + /* Other approximation for |x| > 1.28 */ + INT res_e; + + temp = fPow2Div2(x); /* q25 * q25 - (DFRACT_BITS-1) - 1 = q18 */ + temp = temp + P281; /* q18 + q18 = q18 */ + result = fDivNorm(x, temp, &res_e); + result = scaleValue(result, + (Q_ATANOUT - Q_ATANINP + 18 - DFRACT_BITS + 1) + res_e); + result = ONEP571 - result; /* q30 + q30 = q30 */ + } + if (sign) { + result = -result; + } + + return (result); +} + +#include "FDK_tools_rom.h" + +FIXP_DBL fixp_cos(FIXP_DBL x, int scale) { + FIXP_DBL residual, error, sine, cosine; + + residual = fixp_sin_cos_residual_inline(x, scale, &sine, &cosine); + error = fMult(sine, residual); + +#ifdef SINETABLE_16BIT + return cosine - error; +#else + /* Undo downscaling by 1 which was done at fixp_sin_cos_residual_inline */ + return SATURATE_LEFT_SHIFT(cosine - error, 1, DFRACT_BITS); +#endif +} + +FIXP_DBL fixp_sin(FIXP_DBL x, int scale) { + FIXP_DBL residual, error, sine, cosine; + + residual = fixp_sin_cos_residual_inline(x, scale, &sine, &cosine); + error = fMult(cosine, residual); + +#ifdef SINETABLE_16BIT + return sine + error; +#else + return SATURATE_LEFT_SHIFT(sine + error, 1, DFRACT_BITS); +#endif +} + +void fixp_cos_sin(FIXP_DBL x, int scale, FIXP_DBL *cos, FIXP_DBL *sin) { + FIXP_DBL residual, error0, error1, sine, cosine; + + residual = fixp_sin_cos_residual_inline(x, scale, &sine, &cosine); + error0 = fMult(sine, residual); + error1 = fMult(cosine, residual); + +#ifdef SINETABLE_16BIT + *cos = cosine - error0; + *sin = sine + error1; +#else + *cos = SATURATE_LEFT_SHIFT(cosine - error0, 1, DFRACT_BITS); + *sin = SATURATE_LEFT_SHIFT(sine + error1, 1, DFRACT_BITS); +#endif +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/arm/fft_rad2_arm.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/arm/fft_rad2_arm.cpp new file mode 100644 index 0000000000000..2c03b11351bca --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/arm/fft_rad2_arm.cpp @@ -0,0 +1,321 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: dit_fft ARM assembler replacements. + +*******************************************************************************/ + +#ifndef __FFT_RAD2_CPP__ +#error \ + "Do not compile this file separately. It is included on demand from fft_rad2.cpp" +#endif + +#ifndef FUNCTION_dit_fft +#if defined(SINETABLE_16BIT) + +#define FUNCTION_dit_fft +#if defined(FUNCTION_dit_fft) + +void dit_fft(FIXP_DBL *x, const INT ldn, const FIXP_STP *trigdata, + const INT trigDataSize) { + const INT n = 1 << ldn; + INT i; + + scramble(x, n); + /* + * 1+2 stage radix 4 + */ + + for (i = 0; i < n * 2; i += 8) { + FIXP_DBL a00, a10, a20, a30; + a00 = (x[i + 0] + x[i + 2]) >> 1; /* Re A + Re B */ + a10 = (x[i + 4] + x[i + 6]) >> 1; /* Re C + Re D */ + a20 = (x[i + 1] + x[i + 3]) >> 1; /* Im A + Im B */ + a30 = (x[i + 5] + x[i + 7]) >> 1; /* Im C + Im D */ + + x[i + 0] = a00 + a10; /* Re A' = Re A + Re B + Re C + Re D */ + x[i + 4] = a00 - a10; /* Re C' = Re A + Re B - Re C - Re D */ + x[i + 1] = a20 + a30; /* Im A' = Im A + Im B + Im C + Im D */ + x[i + 5] = a20 - a30; /* Im C' = Im A + Im B - Im C - Im D */ + + a00 = a00 - x[i + 2]; /* Re A - Re B */ + a10 = a10 - x[i + 6]; /* Re C - Re D */ + a20 = a20 - x[i + 3]; /* Im A - Im B */ + a30 = a30 - x[i + 7]; /* Im C - Im D */ + + x[i + 2] = a00 + a30; /* Re B' = Re A - Re B + Im C - Im D */ + x[i + 6] = a00 - a30; /* Re D' = Re A - Re B - Im C + Im D */ + x[i + 3] = a20 - a10; /* Im B' = Im A - Im B - Re C + Re D */ + x[i + 7] = a20 + a10; /* Im D' = Im A - Im B + Re C - Re D */ + } + + INT mh = 1 << 1; + INT ldm = ldn - 2; + INT trigstep = trigDataSize; + + do { + const FIXP_STP *pTrigData = trigdata; + INT j; + + mh <<= 1; + trigstep >>= 1; + + FDK_ASSERT(trigstep > 0); + + /* Do first iteration with c=1.0 and s=0.0 separately to avoid loosing to + much precision. Beware: The impact on the overal FFT precision is rather + large. */ + { + FIXP_DBL *xt1 = x; + int r = n; + + do { + FIXP_DBL *xt2 = xt1 + (mh << 1); + /* + FIXP_DBL *xt1 = x+ ((r)<<1); + FIXP_DBL *xt2 = xt1 + (mh<<1); + */ + FIXP_DBL vr, vi, ur, ui; + + // cplxMultDiv2(&vi, &vr, x[t2+1], x[t2], (FIXP_SGL)1.0, (FIXP_SGL)0.0); + vi = xt2[1] >> 1; + vr = xt2[0] >> 1; + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui + vi; + + xt2[0] = ur - vr; + xt2[1] = ui - vi; + + xt1 += mh; + xt2 += mh; + + // cplxMultDiv2(&vr, &vi, x[t2+1], x[t2], (FIXP_SGL)1.0, (FIXP_SGL)0.0); + vr = xt2[1] >> 1; + vi = xt2[0] >> 1; + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui - vi; + + xt2[0] = ur - vr; + xt2[1] = ui + vi; + + xt1 = xt2 + mh; + } while ((r = r - (mh << 1)) != 0); + } + for (j = 4; j < mh; j += 4) { + FIXP_DBL *xt1 = x + (j >> 1); + FIXP_SPK cs; + int r = n; + + pTrigData += trigstep; + cs = *pTrigData; + + do { + FIXP_DBL *xt2 = xt1 + (mh << 1); + FIXP_DBL vr, vi, ur, ui; + + cplxMultDiv2(&vi, &vr, xt2[1], xt2[0], cs); + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui + vi; + + xt2[0] = ur - vr; + xt2[1] = ui - vi; + + xt1 += mh; + xt2 += mh; + + cplxMultDiv2(&vr, &vi, xt2[1], xt2[0], cs); + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui - vi; + + xt2[0] = ur - vr; + xt2[1] = ui + vi; + + /* Same as above but for t1,t2 with j>mh/4 and thus cs swapped */ + xt1 = xt1 - (j); + xt2 = xt1 + (mh << 1); + + cplxMultDiv2(&vi, &vr, xt2[0], xt2[1], cs); + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui - vi; + + xt2[0] = ur - vr; + xt2[1] = ui + vi; + + xt1 += mh; + xt2 += mh; + + cplxMultDiv2(&vr, &vi, xt2[0], xt2[1], cs); + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur - vr; + xt1[1] = ui - vi; + + xt2[0] = ur + vr; + xt2[1] = ui + vi; + + xt1 = xt2 + (j); + } while ((r = r - (mh << 1)) != 0); + } + { + FIXP_DBL *xt1 = x + (mh >> 1); + int r = n; + + do { + FIXP_DBL *xt2 = xt1 + (mh << 1); + FIXP_DBL vr, vi, ur, ui; + + cplxMultDiv2(&vi, &vr, xt2[1], xt2[0], STC(0x5a82799a), + STC(0x5a82799a)); + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui + vi; + + xt2[0] = ur - vr; + xt2[1] = ui - vi; + + xt1 += mh; + xt2 += mh; + + cplxMultDiv2(&vr, &vi, xt2[1], xt2[0], STC(0x5a82799a), + STC(0x5a82799a)); + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui - vi; + + xt2[0] = ur - vr; + xt2[1] = ui + vi; + + xt1 = xt2 + mh; + } while ((r = r - (mh << 1)) != 0); + } + } while (--ldm != 0); +} + +#endif /* if defined(FUNCTION_dit_fft) */ + +#endif /* if defined(SINETABLE_16BIT) */ + +#endif /* ifndef FUNCTION_dit_fft */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/arm/scale_arm.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/arm/scale_arm.cpp new file mode 100644 index 0000000000000..92c9edc6bf212 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/arm/scale_arm.cpp @@ -0,0 +1,174 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Arthur Tritthart + + Description: Scaling operations for ARM + +*******************************************************************************/ + +/* prevent multiple inclusion with re-definitions */ +#ifndef __INCLUDE_SCALE_ARM__ +#define __INCLUDE_SCALE_ARM__ + +#if !defined(FUNCTION_scaleValuesWithFactor_DBL) +#define FUNCTION_scaleValuesWithFactor_DBL +SCALE_INLINE +void scaleValuesWithFactor(FIXP_DBL *vector, FIXP_DBL factor, INT len, + INT scalefactor) { + /* This code combines the fMult with the scaling */ + /* It performs a fMultDiv2 and increments shift by 1 */ + int shift = scalefactor + 1; + FIXP_DBL *mySpec = vector; + + shift = fixmin_I(shift, (INT)DFRACT_BITS - 1); + + if (shift >= 0) { + for (int i = 0; i < (len >> 2); i++) { + FIXP_DBL tmp0 = mySpec[0]; + FIXP_DBL tmp1 = mySpec[1]; + FIXP_DBL tmp2 = mySpec[2]; + FIXP_DBL tmp3 = mySpec[3]; + tmp0 = fMultDiv2(tmp0, factor); + tmp1 = fMultDiv2(tmp1, factor); + tmp2 = fMultDiv2(tmp2, factor); + tmp3 = fMultDiv2(tmp3, factor); + tmp0 <<= shift; + tmp1 <<= shift; + tmp2 <<= shift; + tmp3 <<= shift; + *mySpec++ = tmp0; + *mySpec++ = tmp1; + *mySpec++ = tmp2; + *mySpec++ = tmp3; + } + for (int i = len & 3; i--;) { + FIXP_DBL tmp0 = mySpec[0]; + tmp0 = fMultDiv2(tmp0, factor); + tmp0 <<= shift; + *mySpec++ = tmp0; + } + } else { + shift = -shift; + for (int i = 0; i < (len >> 2); i++) { + FIXP_DBL tmp0 = mySpec[0]; + FIXP_DBL tmp1 = mySpec[1]; + FIXP_DBL tmp2 = mySpec[2]; + FIXP_DBL tmp3 = mySpec[3]; + tmp0 = fMultDiv2(tmp0, factor); + tmp1 = fMultDiv2(tmp1, factor); + tmp2 = fMultDiv2(tmp2, factor); + tmp3 = fMultDiv2(tmp3, factor); + tmp0 >>= shift; + tmp1 >>= shift; + tmp2 >>= shift; + tmp3 >>= shift; + *mySpec++ = tmp0; + *mySpec++ = tmp1; + *mySpec++ = tmp2; + *mySpec++ = tmp3; + } + for (int i = len & 3; i--;) { + FIXP_DBL tmp0 = mySpec[0]; + tmp0 = fMultDiv2(tmp0, factor); + tmp0 >>= shift; + *mySpec++ = tmp0; + } + } +} +#endif /* #if !defined(FUNCTION_scaleValuesWithFactor_DBL) */ + +#endif /* #ifndef __INCLUDE_SCALE_ARM__ */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/autocorr2nd.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/autocorr2nd.cpp new file mode 100644 index 0000000000000..8c5673cd1ddae --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/autocorr2nd.cpp @@ -0,0 +1,292 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser + + Description: auto-correlation functions + +*******************************************************************************/ + +#include "autocorr2nd.h" + +/*! + * + * \brief Calculate second order autocorrelation using 2 accumulators + * + */ +#if !defined(FUNCTION_autoCorr2nd_real) +INT autoCorr2nd_real( + ACORR_COEFS *ac, /*!< Pointer to autocorrelation coeffs */ + const FIXP_DBL *reBuffer, /*!< Pointer to to real part of input samples */ + const int len /*!< Number input samples */ +) { + int j, autoCorrScaling, mScale; + + FIXP_DBL accu1, accu2, accu3, accu4, accu5; + + const FIXP_DBL *pReBuf; + + const FIXP_DBL *realBuf = reBuffer; + + const int len_scale = fMax(DFRACT_BITS - fNormz((FIXP_DBL)(len / 2)), 1); + /* + r11r,r22r + r01r,r12r + r02r + */ + pReBuf = realBuf - 2; + accu5 = + ((fMultDiv2(pReBuf[0], pReBuf[2]) + fMultDiv2(pReBuf[1], pReBuf[3])) >> + len_scale); + pReBuf++; + + /* len must be even */ + accu1 = fPow2Div2(pReBuf[0]) >> len_scale; + accu3 = fMultDiv2(pReBuf[0], pReBuf[1]) >> len_scale; + pReBuf++; + + for (j = (len - 2) >> 1; j != 0; j--, pReBuf += 2) { + accu1 += ((fPow2Div2(pReBuf[0]) + fPow2Div2(pReBuf[1])) >> len_scale); + + accu3 += + ((fMultDiv2(pReBuf[0], pReBuf[1]) + fMultDiv2(pReBuf[1], pReBuf[2])) >> + len_scale); + + accu5 += + ((fMultDiv2(pReBuf[0], pReBuf[2]) + fMultDiv2(pReBuf[1], pReBuf[3])) >> + len_scale); + } + + accu2 = (fPow2Div2(realBuf[-2]) >> len_scale); + accu2 += accu1; + + accu1 += (fPow2Div2(realBuf[len - 2]) >> len_scale); + + accu4 = (fMultDiv2(realBuf[-1], realBuf[-2]) >> len_scale); + accu4 += accu3; + + accu3 += (fMultDiv2(realBuf[len - 1], realBuf[len - 2]) >> len_scale); + + mScale = CntLeadingZeros( + (accu1 | accu2 | fAbs(accu3) | fAbs(accu4) | fAbs(accu5))) - + 1; + autoCorrScaling = mScale - 1 - len_scale; /* -1 because of fMultDiv2*/ + + /* Scale to common scale factor */ + ac->r11r = accu1 << mScale; + ac->r22r = accu2 << mScale; + ac->r01r = accu3 << mScale; + ac->r12r = accu4 << mScale; + ac->r02r = accu5 << mScale; + + ac->det = (fMultDiv2(ac->r11r, ac->r22r) - fMultDiv2(ac->r12r, ac->r12r)); + mScale = CountLeadingBits(fAbs(ac->det)); + + ac->det <<= mScale; + ac->det_scale = mScale - 1; + + return autoCorrScaling; +} +#endif + +#if !defined(FUNCTION_autoCorr2nd_cplx) +INT autoCorr2nd_cplx( + ACORR_COEFS *ac, /*!< Pointer to autocorrelation coeffs */ + const FIXP_DBL *reBuffer, /*!< Pointer to real part of input samples */ + const FIXP_DBL *imBuffer, /*!< Pointer to imag part of input samples */ + const int len /*!< Number of input samples (should be smaller than 128) */ +) { + int j, autoCorrScaling, mScale; + + FIXP_DBL accu0, accu1, accu2, accu3, accu4, accu5, accu6, accu7, accu8; + + const FIXP_DBL *pReBuf, *pImBuf; + + const FIXP_DBL *realBuf = reBuffer; + const FIXP_DBL *imagBuf = imBuffer; + + const int len_scale = fMax(DFRACT_BITS - fNormz((FIXP_DBL)len), 1); + /* + r00r, + r11r,r22r + r01r,r12r + r01i,r12i + r02r,r02i + */ + accu1 = accu3 = accu5 = accu7 = accu8 = FL2FXCONST_DBL(0.0f); + + pReBuf = realBuf - 2, pImBuf = imagBuf - 2; + accu7 += + ((fMultDiv2(pReBuf[2], pReBuf[0]) + fMultDiv2(pImBuf[2], pImBuf[0])) >> + len_scale); + accu8 += + ((fMultDiv2(pImBuf[2], pReBuf[0]) - fMultDiv2(pReBuf[2], pImBuf[0])) >> + len_scale); + + pReBuf = realBuf - 1, pImBuf = imagBuf - 1; + for (j = (len - 1); j != 0; j--, pReBuf++, pImBuf++) { + accu1 += ((fPow2Div2(pReBuf[0]) + fPow2Div2(pImBuf[0])) >> len_scale); + accu3 += + ((fMultDiv2(pReBuf[0], pReBuf[1]) + fMultDiv2(pImBuf[0], pImBuf[1])) >> + len_scale); + accu5 += + ((fMultDiv2(pImBuf[1], pReBuf[0]) - fMultDiv2(pReBuf[1], pImBuf[0])) >> + len_scale); + accu7 += + ((fMultDiv2(pReBuf[2], pReBuf[0]) + fMultDiv2(pImBuf[2], pImBuf[0])) >> + len_scale); + accu8 += + ((fMultDiv2(pImBuf[2], pReBuf[0]) - fMultDiv2(pReBuf[2], pImBuf[0])) >> + len_scale); + } + + accu2 = ((fPow2Div2(realBuf[-2]) + fPow2Div2(imagBuf[-2])) >> len_scale); + accu2 += accu1; + + accu1 += ((fPow2Div2(realBuf[len - 2]) + fPow2Div2(imagBuf[len - 2])) >> + len_scale); + accu0 = ((fPow2Div2(realBuf[len - 1]) + fPow2Div2(imagBuf[len - 1])) >> + len_scale) - + ((fPow2Div2(realBuf[-1]) + fPow2Div2(imagBuf[-1])) >> len_scale); + accu0 += accu1; + + accu4 = ((fMultDiv2(realBuf[-1], realBuf[-2]) + + fMultDiv2(imagBuf[-1], imagBuf[-2])) >> + len_scale); + accu4 += accu3; + + accu3 += ((fMultDiv2(realBuf[len - 1], realBuf[len - 2]) + + fMultDiv2(imagBuf[len - 1], imagBuf[len - 2])) >> + len_scale); + + accu6 = ((fMultDiv2(imagBuf[-1], realBuf[-2]) - + fMultDiv2(realBuf[-1], imagBuf[-2])) >> + len_scale); + accu6 += accu5; + + accu5 += ((fMultDiv2(imagBuf[len - 1], realBuf[len - 2]) - + fMultDiv2(realBuf[len - 1], imagBuf[len - 2])) >> + len_scale); + + mScale = + CntLeadingZeros((accu0 | accu1 | accu2 | fAbs(accu3) | fAbs(accu4) | + fAbs(accu5) | fAbs(accu6) | fAbs(accu7) | fAbs(accu8))) - + 1; + autoCorrScaling = mScale - 1 - len_scale; /* -1 because of fMultDiv2*/ + + /* Scale to common scale factor */ + ac->r00r = (FIXP_DBL)accu0 << mScale; + ac->r11r = (FIXP_DBL)accu1 << mScale; + ac->r22r = (FIXP_DBL)accu2 << mScale; + ac->r01r = (FIXP_DBL)accu3 << mScale; + ac->r12r = (FIXP_DBL)accu4 << mScale; + ac->r01i = (FIXP_DBL)accu5 << mScale; + ac->r12i = (FIXP_DBL)accu6 << mScale; + ac->r02r = (FIXP_DBL)accu7 << mScale; + ac->r02i = (FIXP_DBL)accu8 << mScale; + + ac->det = + (fMultDiv2(ac->r11r, ac->r22r) >> 1) - + ((fMultDiv2(ac->r12r, ac->r12r) + fMultDiv2(ac->r12i, ac->r12i)) >> 1); + mScale = CntLeadingZeros(fAbs(ac->det)) - 1; + + ac->det <<= mScale; + ac->det_scale = mScale - 2; + + return autoCorrScaling; +} + +#endif /* FUNCTION_autoCorr2nd_cplx */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/dct.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/dct.cpp new file mode 100644 index 0000000000000..35507b57a2154 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/dct.cpp @@ -0,0 +1,566 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file dct.cpp + \brief DCT Implementations + Library functions to calculate standard DCTs. This will most likely be + replaced by hand-optimized functions for the specific target processor. + + Three different implementations of the dct type II and the dct type III + transforms are provided. + + By default implementations which are based on a single, standard complex + FFT-kernel are used (dctII_f() and dctIII_f()). These are specifically helpful + in cases where optimized FFT libraries are already available. The FFT used in + these implementation is FFT rad2 from FDK_tools. + + Of course, one might also use DCT-libraries should they be available. The DCT + and DST type IV implementations are only available in a version based on a + complex FFT kernel. +*/ + +#include "dct.h" + +#include "FDK_tools_rom.h" +#include "fft.h" + +void dct_getTables(const FIXP_WTP **ptwiddle, const FIXP_STP **sin_twiddle, + int *sin_step, int length) { + const FIXP_WTP *twiddle; + int ld2_length; + + /* Get ld2 of length - 2 + 1 + -2: because first table entry is window of size 4 + +1: because we already include +1 because of ceil(log2(length)) */ + ld2_length = DFRACT_BITS - 1 - fNormz((FIXP_DBL)length) - 1; + + /* Extract sort of "eigenvalue" (the 4 left most bits) of length. */ + switch ((length) >> (ld2_length - 1)) { + case 0x4: /* radix 2 */ + *sin_twiddle = SineTable1024; + *sin_step = 1 << (10 - ld2_length); + twiddle = windowSlopes[0][0][ld2_length - 1]; + break; + case 0x7: /* 10 ms */ + *sin_twiddle = SineTable480; + *sin_step = 1 << (8 - ld2_length); + twiddle = windowSlopes[0][1][ld2_length]; + break; + case 0x6: /* 3/4 of radix 2 */ + *sin_twiddle = SineTable384; + *sin_step = 1 << (8 - ld2_length); + twiddle = windowSlopes[0][2][ld2_length]; + break; + case 0x5: /* 5/16 of radix 2*/ + *sin_twiddle = SineTable80; + *sin_step = 1 << (6 - ld2_length); + twiddle = windowSlopes[0][3][ld2_length]; + break; + default: + *sin_twiddle = NULL; + *sin_step = 0; + twiddle = NULL; + break; + } + + if (ptwiddle != NULL) { + FDK_ASSERT(twiddle != NULL); + *ptwiddle = twiddle; + } + + FDK_ASSERT(*sin_step > 0); +} + +#if !defined(FUNCTION_dct_III) +void dct_III(FIXP_DBL *pDat, /*!< pointer to input/output */ + FIXP_DBL *tmp, /*!< pointer to temporal working buffer */ + int L, /*!< lenght of transform */ + int *pDat_e) { + const FIXP_WTP *sin_twiddle; + int i; + FIXP_DBL xr, accu1, accu2; + int inc, index; + int M = L >> 1; + + FDK_ASSERT(L % 4 == 0); + dct_getTables(NULL, &sin_twiddle, &inc, L); + inc >>= 1; + + FIXP_DBL *pTmp_0 = &tmp[2]; + FIXP_DBL *pTmp_1 = &tmp[(M - 1) * 2]; + + index = 4 * inc; + + /* This loop performs multiplication for index i (i*inc) */ + for (i = 1; i> 1; i++, pTmp_0 += 2, pTmp_1 -= 2) { + FIXP_DBL accu3, accu4, accu5, accu6; + + cplxMultDiv2(&accu2, &accu1, pDat[L - i], pDat[i], sin_twiddle[i * inc]); + cplxMultDiv2(&accu4, &accu3, pDat[M + i], pDat[M - i], + sin_twiddle[(M - i) * inc]); + accu3 >>= 1; + accu4 >>= 1; + + /* This method is better for ARM926, that uses operand2 shifted right by 1 + * always */ + if (2 * i < (M / 2)) { + cplxMultDiv2(&accu6, &accu5, (accu3 - (accu1 >> 1)), + ((accu2 >> 1) + accu4), sin_twiddle[index]); + } else { + cplxMultDiv2(&accu6, &accu5, ((accu2 >> 1) + accu4), + (accu3 - (accu1 >> 1)), sin_twiddle[index]); + accu6 = -accu6; + } + xr = (accu1 >> 1) + accu3; + pTmp_0[0] = (xr >> 1) - accu5; + pTmp_1[0] = (xr >> 1) + accu5; + + xr = (accu2 >> 1) - accu4; + pTmp_0[1] = (xr >> 1) - accu6; + pTmp_1[1] = -((xr >> 1) + accu6); + + /* Create index helper variables for (4*i)*inc indexed equivalent values of + * short tables. */ + if (2 * i < ((M / 2) - 1)) { + index += 4 * inc; + } else if (2 * i >= ((M / 2))) { + index -= 4 * inc; + } + } + + xr = fMultDiv2(pDat[M], sin_twiddle[M * inc].v.re); /* cos((PI/(2*L))*M); */ + tmp[0] = ((pDat[0] >> 1) + xr) >> 1; + tmp[1] = ((pDat[0] >> 1) - xr) >> 1; + + cplxMultDiv2(&accu2, &accu1, pDat[L - (M / 2)], pDat[M / 2], + sin_twiddle[M * inc / 2]); + tmp[M] = accu1 >> 1; + tmp[M + 1] = accu2 >> 1; + + /* dit_fft expects 1 bit scaled input values */ + fft(M, tmp, pDat_e); + + /* ARM926: 12 cycles per 2-iteration, no overhead code by compiler */ + pTmp_1 = &tmp[L]; + for (i = M >> 1; i--;) { + FIXP_DBL tmp1, tmp2, tmp3, tmp4; + tmp1 = *tmp++; + tmp2 = *tmp++; + tmp3 = *--pTmp_1; + tmp4 = *--pTmp_1; + *pDat++ = tmp1; + *pDat++ = tmp3; + *pDat++ = tmp2; + *pDat++ = tmp4; + } + + *pDat_e += 2; +} + +void dst_III(FIXP_DBL *pDat, /*!< pointer to input/output */ + FIXP_DBL *tmp, /*!< pointer to temporal working buffer */ + int L, /*!< lenght of transform */ + int *pDat_e) { + int L2 = L >> 1; + int i; + FIXP_DBL t; + + /* note: DCT III is reused here, direct DST III implementation might be more + * efficient */ + + /* mirror input */ + for (i = 0; i < L2; i++) { + t = pDat[i]; + pDat[i] = pDat[L - 1 - i]; + pDat[L - 1 - i] = t; + } + + /* DCT-III */ + dct_III(pDat, tmp, L, pDat_e); + + /* flip signs at odd indices */ + for (i = 1; i < L; i += 2) pDat[i] = -pDat[i]; +} + +#endif + +#if !defined(FUNCTION_dct_II) +void dct_II( + FIXP_DBL *pDat, /*!< pointer to input/output */ + FIXP_DBL *tmp, /*!< pointer to temporal working buffer */ + int L, /*!< lenght of transform (has to be a multiple of 8 (or 4 in case + DCT_II_L_MULTIPLE_OF_4_SUPPORT is defined) */ + int *pDat_e) { + const FIXP_WTP *sin_twiddle; + FIXP_DBL accu1, accu2; + FIXP_DBL *pTmp_0, *pTmp_1; + + int i; + int inc, index = 0; + int M = L >> 1; + + FDK_ASSERT(L % 4 == 0); + dct_getTables(NULL, &sin_twiddle, &inc, L); + inc >>= 1; + + { + for (i = 0; i < M; i++) { + tmp[i] = pDat[2 * i] >> 2; + tmp[L - 1 - i] = pDat[2 * i + 1] >> 2; + } + } + + fft(M, tmp, pDat_e); + + pTmp_0 = &tmp[2]; + pTmp_1 = &tmp[(M - 1) * 2]; + + index = inc * 4; + + for (i = 1; i> 1; i++, pTmp_0 += 2, pTmp_1 -= 2) { + FIXP_DBL a1, a2; + FIXP_DBL accu3, accu4; + + a1 = ((pTmp_0[1] >> 1) + (pTmp_1[1] >> 1)); + a2 = ((pTmp_1[0] >> 1) - (pTmp_0[0] >> 1)); + + if (2 * i < (M / 2)) { + cplxMultDiv2(&accu1, &accu2, a2, a1, sin_twiddle[index]); + } else { + cplxMultDiv2(&accu1, &accu2, a1, a2, sin_twiddle[index]); + accu1 = -accu1; + } + accu1 <<= 1; + accu2 <<= 1; + + a1 = ((pTmp_0[0] >> 1) + (pTmp_1[0] >> 1)); + a2 = ((pTmp_0[1] >> 1) - (pTmp_1[1] >> 1)); + + cplxMult(&accu3, &accu4, (accu1 + a2), (a1 + accu2), sin_twiddle[i * inc]); + pDat[L - i] = -accu3; + pDat[i] = accu4; + + cplxMult(&accu3, &accu4, (accu1 - a2), (a1 - accu2), + sin_twiddle[(M - i) * inc]); + pDat[M + i] = -accu3; + pDat[M - i] = accu4; + + /* Create index helper variables for (4*i)*inc indexed equivalent values of + * short tables. */ + if (2 * i < ((M / 2) - 1)) { + index += 4 * inc; + } else if (2 * i >= ((M / 2))) { + index -= 4 * inc; + } + } + + cplxMult(&accu1, &accu2, tmp[M], tmp[M + 1], sin_twiddle[(M / 2) * inc]); + pDat[L - (M / 2)] = accu2; + pDat[M / 2] = accu1; + + pDat[0] = tmp[0] + tmp[1]; + pDat[M] = fMult(tmp[0] - tmp[1], + sin_twiddle[M * inc].v.re); /* cos((PI/(2*L))*M); */ + + *pDat_e += 2; +} +#endif + +#if !defined(FUNCTION_dct_IV) + +void dct_IV(FIXP_DBL *pDat, int L, int *pDat_e) { + int sin_step = 0; + int M = L >> 1; + + const FIXP_WTP *twiddle; + const FIXP_STP *sin_twiddle; + + FDK_ASSERT(L >= 4); + + FDK_ASSERT(L >= 4); + + dct_getTables(&twiddle, &sin_twiddle, &sin_step, L); + + { + FIXP_DBL *RESTRICT pDat_0 = &pDat[0]; + FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2]; + int i; + + /* 29 cycles on ARM926 */ + for (i = 0; i < M - 1; i += 2, pDat_0 += 2, pDat_1 -= 2) { + FIXP_DBL accu1, accu2, accu3, accu4; + + accu1 = pDat_1[1]; + accu2 = pDat_0[0]; + accu3 = pDat_0[1]; + accu4 = pDat_1[0]; + + cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]); + cplxMultDiv2(&accu3, &accu4, accu4, accu3, twiddle[i + 1]); + + pDat_0[0] = accu2 >> 1; + pDat_0[1] = accu1 >> 1; + pDat_1[0] = accu4 >> 1; + pDat_1[1] = -(accu3 >> 1); + } + if (M & 1) { + FIXP_DBL accu1, accu2; + + accu1 = pDat_1[1]; + accu2 = pDat_0[0]; + + cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]); + + pDat_0[0] = accu2 >> 1; + pDat_0[1] = accu1 >> 1; + } + } + + fft(M, pDat, pDat_e); + + { + FIXP_DBL *RESTRICT pDat_0 = &pDat[0]; + FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2]; + FIXP_DBL accu1, accu2, accu3, accu4; + int idx, i; + + /* Sin and Cos values are 0.0f and 1.0f */ + accu1 = pDat_1[0]; + accu2 = pDat_1[1]; + + pDat_1[1] = -pDat_0[1]; + + /* 28 cycles for ARM926 */ + for (idx = sin_step, i = 1; i<(M + 1)>> 1; i++, idx += sin_step) { + FIXP_STP twd = sin_twiddle[idx]; + cplxMult(&accu3, &accu4, accu1, accu2, twd); + pDat_0[1] = accu3; + pDat_1[0] = accu4; + + pDat_0 += 2; + pDat_1 -= 2; + + cplxMult(&accu3, &accu4, pDat_0[1], pDat_0[0], twd); + + accu1 = pDat_1[0]; + accu2 = pDat_1[1]; + + pDat_1[1] = -accu3; + pDat_0[0] = accu4; + } + + if ((M & 1) == 0) { + /* Last Sin and Cos value pair are the same */ + accu1 = fMult(accu1, WTC(0x5a82799a)); + accu2 = fMult(accu2, WTC(0x5a82799a)); + + pDat_1[0] = accu1 + accu2; + pDat_0[1] = accu1 - accu2; + } + } + + /* Add twiddeling scale. */ + *pDat_e += 2; +} +#endif /* defined (FUNCTION_dct_IV) */ + +#if !defined(FUNCTION_dst_IV) +void dst_IV(FIXP_DBL *pDat, int L, int *pDat_e) { + int sin_step = 0; + int M = L >> 1; + + const FIXP_WTP *twiddle; + const FIXP_STP *sin_twiddle; + + FDK_ASSERT(L >= 4); + + FDK_ASSERT(L >= 4); + + dct_getTables(&twiddle, &sin_twiddle, &sin_step, L); + + { + FIXP_DBL *RESTRICT pDat_0 = &pDat[0]; + FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2]; + int i; + + /* 34 cycles on ARM926 */ + for (i = 0; i < M - 1; i += 2, pDat_0 += 2, pDat_1 -= 2) { + FIXP_DBL accu1, accu2, accu3, accu4; + + accu1 = pDat_1[1] >> 1; + accu2 = -(pDat_0[0] >> 1); + accu3 = pDat_0[1] >> 1; + accu4 = -(pDat_1[0] >> 1); + + cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]); + cplxMultDiv2(&accu3, &accu4, accu4, accu3, twiddle[i + 1]); + + pDat_0[0] = accu2; + pDat_0[1] = accu1; + pDat_1[0] = accu4; + pDat_1[1] = -accu3; + } + if (M & 1) { + FIXP_DBL accu1, accu2; + + accu1 = pDat_1[1]; + accu2 = -pDat_0[0]; + + cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]); + + pDat_0[0] = accu2 >> 1; + pDat_0[1] = accu1 >> 1; + } + } + + fft(M, pDat, pDat_e); + + { + FIXP_DBL *RESTRICT pDat_0; + FIXP_DBL *RESTRICT pDat_1; + FIXP_DBL accu1, accu2, accu3, accu4; + int idx, i; + + pDat_0 = &pDat[0]; + pDat_1 = &pDat[L - 2]; + + /* Sin and Cos values are 0.0f and 1.0f */ + accu1 = pDat_1[0]; + accu2 = pDat_1[1]; + + pDat_1[1] = -pDat_0[0]; + pDat_0[0] = pDat_0[1]; + + for (idx = sin_step, i = 1; i<(M + 1)>> 1; i++, idx += sin_step) { + FIXP_STP twd = sin_twiddle[idx]; + + cplxMult(&accu3, &accu4, accu1, accu2, twd); + pDat_1[0] = -accu3; + pDat_0[1] = -accu4; + + pDat_0 += 2; + pDat_1 -= 2; + + cplxMult(&accu3, &accu4, pDat_0[1], pDat_0[0], twd); + + accu1 = pDat_1[0]; + accu2 = pDat_1[1]; + + pDat_0[0] = accu3; + pDat_1[1] = -accu4; + } + + if ((M & 1) == 0) { + /* Last Sin and Cos value pair are the same */ + accu1 = fMult(accu1, WTC(0x5a82799a)); + accu2 = fMult(accu2, WTC(0x5a82799a)); + + pDat_0[1] = -accu1 - accu2; + pDat_1[0] = accu2 - accu1; + } + } + + /* Add twiddeling scale. */ + *pDat_e += 2; +} +#endif /* !defined(FUNCTION_dst_IV) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/fft.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/fft.cpp new file mode 100644 index 0000000000000..c9ee784e9c15f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/fft.cpp @@ -0,0 +1,1922 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Josef Hoepfl, DSP Solutions + + Description: Fix point FFT + +*******************************************************************************/ + +#include "fft_rad2.h" +#include "FDK_tools_rom.h" + +#define W_PiFOURTH STC(0x5a82799a) +//#define W_PiFOURTH ((FIXP_DBL)(0x5a82799a)) +#ifndef SUMDIFF_PIFOURTH +#define SUMDIFF_PIFOURTH(diff, sum, a, b) \ + { \ + FIXP_DBL wa, wb; \ + wa = fMultDiv2(a, W_PiFOURTH); \ + wb = fMultDiv2(b, W_PiFOURTH); \ + diff = wb - wa; \ + sum = wb + wa; \ + } +#define SUMDIFF_PIFOURTH16(diff, sum, a, b) \ + { \ + FIXP_SGL wa, wb; \ + wa = FX_DBL2FX_SGL(fMultDiv2(a, W_PiFOURTH)); \ + wb = FX_DBL2FX_SGL(fMultDiv2(b, W_PiFOURTH)); \ + diff = wb - wa; \ + sum = wb + wa; \ + } +#endif + +#define SCALEFACTOR2048 10 +#define SCALEFACTOR1024 9 +#define SCALEFACTOR512 8 +#define SCALEFACTOR256 7 +#define SCALEFACTOR128 6 +#define SCALEFACTOR64 5 +#define SCALEFACTOR32 4 +#define SCALEFACTOR16 3 +#define SCALEFACTOR8 2 +#define SCALEFACTOR4 1 +#define SCALEFACTOR2 1 + +#define SCALEFACTOR3 1 +#define SCALEFACTOR5 1 +#define SCALEFACTOR6 (SCALEFACTOR2 + SCALEFACTOR3 + 2) +#define SCALEFACTOR7 2 +#define SCALEFACTOR9 2 +#define SCALEFACTOR10 5 +#define SCALEFACTOR12 3 +#define SCALEFACTOR15 3 +#define SCALEFACTOR18 (SCALEFACTOR2 + SCALEFACTOR9 + 2) +#define SCALEFACTOR20 (SCALEFACTOR4 + SCALEFACTOR5 + 2) +#define SCALEFACTOR21 (SCALEFACTOR3 + SCALEFACTOR7 + 2) +#define SCALEFACTOR24 (SCALEFACTOR2 + SCALEFACTOR12 + 2) +#define SCALEFACTOR30 (SCALEFACTOR2 + SCALEFACTOR15 + 2) +#define SCALEFACTOR40 (SCALEFACTOR5 + SCALEFACTOR8 + 2) +#define SCALEFACTOR48 (SCALEFACTOR4 + SCALEFACTOR12 + 2) +#define SCALEFACTOR60 (SCALEFACTOR4 + SCALEFACTOR15 + 2) +#define SCALEFACTOR80 (SCALEFACTOR5 + SCALEFACTOR16 + 2) +#define SCALEFACTOR96 (SCALEFACTOR3 + SCALEFACTOR32 + 2) +#define SCALEFACTOR120 (SCALEFACTOR8 + SCALEFACTOR15 + 2) +#define SCALEFACTOR160 (SCALEFACTOR10 + SCALEFACTOR16 + 2) +#define SCALEFACTOR168 (SCALEFACTOR21 + SCALEFACTOR8 + 2) +#define SCALEFACTOR192 (SCALEFACTOR12 + SCALEFACTOR16 + 2) +#define SCALEFACTOR240 (SCALEFACTOR16 + SCALEFACTOR15 + 2) +#define SCALEFACTOR320 (SCALEFACTOR10 + SCALEFACTOR32 + 2) +#define SCALEFACTOR336 (SCALEFACTOR21 + SCALEFACTOR16 + 2) +#define SCALEFACTOR384 (SCALEFACTOR12 + SCALEFACTOR32 + 2) +#define SCALEFACTOR480 (SCALEFACTOR32 + SCALEFACTOR15 + 2) + +#include "fft.h" + +#ifndef FUNCTION_fft2 + +/* Performs the FFT of length 2. Input vector unscaled, output vector scaled + * with factor 0.5 */ +static inline void fft2(FIXP_DBL *RESTRICT pDat) { + FIXP_DBL r1, i1; + FIXP_DBL r2, i2; + + /* real part */ + r1 = pDat[2]; + r2 = pDat[0]; + + /* imaginary part */ + i1 = pDat[3]; + i2 = pDat[1]; + + /* real part */ + pDat[0] = (r2 + r1) >> 1; + pDat[2] = (r2 - r1) >> 1; + + /* imaginary part */ + pDat[1] = (i2 + i1) >> 1; + pDat[3] = (i2 - i1) >> 1; +} +#endif /* FUNCTION_fft2 */ + +#define C31 (STC(0x91261468)) /* FL2FXCONST_DBL(-0.86602540) = -sqrt(3)/2 */ + +#ifndef FUNCTION_fft3 +/* Performs the FFT of length 3 according to the algorithm after winograd. */ +static inline void fft3(FIXP_DBL *RESTRICT pDat) { + FIXP_DBL r1, r2; + FIXP_DBL s1, s2; + FIXP_DBL pD; + + /* real part */ + r1 = pDat[2] + pDat[4]; + r2 = fMultDiv2((pDat[2] - pDat[4]), C31); + pD = pDat[0] >> 1; + pDat[0] = pD + (r1 >> 1); + r1 = pD - (r1 >> 2); + + /* imaginary part */ + s1 = pDat[3] + pDat[5]; + s2 = fMultDiv2((pDat[3] - pDat[5]), C31); + pD = pDat[1] >> 1; + pDat[1] = pD + (s1 >> 1); + s1 = pD - (s1 >> 2); + + /* combination */ + pDat[2] = r1 - s2; + pDat[4] = r1 + s2; + pDat[3] = s1 + r2; + pDat[5] = s1 - r2; +} +#endif /* #ifndef FUNCTION_fft3 */ + +#define F5C(x) STC(x) + +#define C51 (F5C(0x79bc3854)) /* FL2FXCONST_DBL( 0.95105652) */ +#define C52 (F5C(0x9d839db0)) /* FL2FXCONST_DBL(-1.53884180/2) */ +#define C53 (F5C(0xd18053ce)) /* FL2FXCONST_DBL(-0.36327126) */ +#define C54 (F5C(0x478dde64)) /* FL2FXCONST_DBL( 0.55901699) */ +#define C55 (F5C(0xb0000001)) /* FL2FXCONST_DBL(-1.25/2) */ + +/* performs the FFT of length 5 according to the algorithm after winograd */ +/* This version works with a prescale of 2 instead of 3 */ +static inline void fft5(FIXP_DBL *RESTRICT pDat) { + FIXP_DBL r1, r2, r3, r4; + FIXP_DBL s1, s2, s3, s4; + FIXP_DBL t; + + /* real part */ + r1 = (pDat[2] + pDat[8]) >> 1; + r4 = (pDat[2] - pDat[8]) >> 1; + r3 = (pDat[4] + pDat[6]) >> 1; + r2 = (pDat[4] - pDat[6]) >> 1; + t = fMult((r1 - r3), C54); + r1 = r1 + r3; + pDat[0] = (pDat[0] >> 1) + r1; + /* Bit shift left because of the constant C55 which was scaled with the factor + 0.5 because of the representation of the values as fracts */ + r1 = pDat[0] + (fMultDiv2(r1, C55) << (2)); + r3 = r1 - t; + r1 = r1 + t; + t = fMult((r4 + r2), C51); + /* Bit shift left because of the constant C55 which was scaled with the factor + 0.5 because of the representation of the values as fracts */ + r4 = t + (fMultDiv2(r4, C52) << (2)); + r2 = t + fMult(r2, C53); + + /* imaginary part */ + s1 = (pDat[3] + pDat[9]) >> 1; + s4 = (pDat[3] - pDat[9]) >> 1; + s3 = (pDat[5] + pDat[7]) >> 1; + s2 = (pDat[5] - pDat[7]) >> 1; + t = fMult((s1 - s3), C54); + s1 = s1 + s3; + pDat[1] = (pDat[1] >> 1) + s1; + /* Bit shift left because of the constant C55 which was scaled with the factor + 0.5 because of the representation of the values as fracts */ + s1 = pDat[1] + (fMultDiv2(s1, C55) << (2)); + s3 = s1 - t; + s1 = s1 + t; + t = fMult((s4 + s2), C51); + /* Bit shift left because of the constant C55 which was scaled with the factor + 0.5 because of the representation of the values as fracts */ + s4 = t + (fMultDiv2(s4, C52) << (2)); + s2 = t + fMult(s2, C53); + + /* combination */ + pDat[2] = r1 + s2; + pDat[8] = r1 - s2; + pDat[4] = r3 - s4; + pDat[6] = r3 + s4; + + pDat[3] = s1 - r2; + pDat[9] = s1 + r2; + pDat[5] = s3 + r4; + pDat[7] = s3 - r4; +} + +#define F5C(x) STC(x) + +#define C51 (F5C(0x79bc3854)) /* FL2FXCONST_DBL( 0.95105652) */ +#define C52 (F5C(0x9d839db0)) /* FL2FXCONST_DBL(-1.53884180/2) */ +#define C53 (F5C(0xd18053ce)) /* FL2FXCONST_DBL(-0.36327126) */ +#define C54 (F5C(0x478dde64)) /* FL2FXCONST_DBL( 0.55901699) */ +#define C55 (F5C(0xb0000001)) /* FL2FXCONST_DBL(-1.25/2) */ +/** + * \brief Function performs a complex 10-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR10 bits. + * + * WOPS FLC version: 1093 cycles + * WOPS with 32x16 bit multiplications: 196 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ +static void fft10(FIXP_DBL *x) // FIXP_DBL *re, FIXP_DBL *im, FIXP_SGL s) +{ + FIXP_DBL t; + FIXP_DBL x0, x1, x2, x3, x4; + FIXP_DBL r1, r2, r3, r4; + FIXP_DBL s1, s2, s3, s4; + FIXP_DBL y00, y01, y02, y03, y04, y05, y06, y07, y08, y09; + FIXP_DBL y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; + + const int s = 1; // stride factor + + /* 2 fft5 stages */ + + /* real part */ + x0 = (x[s * 0] >> SCALEFACTOR10); + x1 = (x[s * 4] >> SCALEFACTOR10); + x2 = (x[s * 8] >> SCALEFACTOR10); + x3 = (x[s * 12] >> SCALEFACTOR10); + x4 = (x[s * 16] >> SCALEFACTOR10); + + r1 = (x3 + x2); + r4 = (x3 - x2); + r3 = (x1 + x4); + r2 = (x1 - x4); + t = fMult((r1 - r3), C54); + r1 = (r1 + r3); + y00 = (x0 + r1); + r1 = (y00 + ((fMult(r1, C55) << 1))); + r3 = (r1 - t); + r1 = (r1 + t); + t = fMult((r4 + r2), C51); + r4 = (t + (fMult(r4, C52) << 1)); + r2 = (t + fMult(r2, C53)); + + /* imaginary part */ + x0 = (x[s * 0 + 1] >> SCALEFACTOR10); + x1 = (x[s * 4 + 1] >> SCALEFACTOR10); + x2 = (x[s * 8 + 1] >> SCALEFACTOR10); + x3 = (x[s * 12 + 1] >> SCALEFACTOR10); + x4 = (x[s * 16 + 1] >> SCALEFACTOR10); + + s1 = (x3 + x2); + s4 = (x3 - x2); + s3 = (x1 + x4); + s2 = (x1 - x4); + t = fMult((s1 - s3), C54); + s1 = (s1 + s3); + y01 = (x0 + s1); + s1 = (y01 + (fMult(s1, C55) << 1)); + s3 = (s1 - t); + s1 = (s1 + t); + t = fMult((s4 + s2), C51); + s4 = (t + (fMult(s4, C52) << 1)); + s2 = (t + fMult(s2, C53)); + + /* combination */ + y04 = (r1 + s2); + y16 = (r1 - s2); + y08 = (r3 - s4); + y12 = (r3 + s4); + + y05 = (s1 - r2); + y17 = (s1 + r2); + y09 = (s3 + r4); + y13 = (s3 - r4); + + /* real part */ + x0 = (x[s * 10] >> SCALEFACTOR10); + x1 = (x[s * 2] >> SCALEFACTOR10); + x2 = (x[s * 6] >> SCALEFACTOR10); + x3 = (x[s * 14] >> SCALEFACTOR10); + x4 = (x[s * 18] >> SCALEFACTOR10); + + r1 = (x1 + x4); + r4 = (x1 - x4); + r3 = (x3 + x2); + r2 = (x3 - x2); + t = fMult((r1 - r3), C54); + r1 = (r1 + r3); + y02 = (x0 + r1); + r1 = (y02 + ((fMult(r1, C55) << 1))); + r3 = (r1 - t); + r1 = (r1 + t); + t = fMult(((r4 + r2)), C51); + r4 = (t + (fMult(r4, C52) << 1)); + r2 = (t + fMult(r2, C53)); + + /* imaginary part */ + x0 = (x[s * 10 + 1] >> SCALEFACTOR10); + x1 = (x[s * 2 + 1] >> SCALEFACTOR10); + x2 = (x[s * 6 + 1] >> SCALEFACTOR10); + x3 = (x[s * 14 + 1] >> SCALEFACTOR10); + x4 = (x[s * 18 + 1] >> SCALEFACTOR10); + + s1 = (x1 + x4); + s4 = (x1 - x4); + s3 = (x3 + x2); + s2 = (x3 - x2); + t = fMult((s1 - s3), C54); + s1 = (s1 + s3); + y03 = (x0 + s1); + s1 = (y03 + (fMult(s1, C55) << 1)); + s3 = (s1 - t); + s1 = (s1 + t); + t = fMult((s4 + s2), C51); + s4 = (t + (fMult(s4, C52) << 1)); + s2 = (t + fMult(s2, C53)); + + /* combination */ + y06 = (r1 + s2); + y18 = (r1 - s2); + y10 = (r3 - s4); + y14 = (r3 + s4); + + y07 = (s1 - r2); + y19 = (s1 + r2); + y11 = (s3 + r4); + y15 = (s3 - r4); + + /* 5 fft2 stages */ + x[s * 0] = (y00 + y02); + x[s * 0 + 1] = (y01 + y03); + x[s * 10] = (y00 - y02); + x[s * 10 + 1] = (y01 - y03); + + x[s * 4] = (y04 + y06); + x[s * 4 + 1] = (y05 + y07); + x[s * 14] = (y04 - y06); + x[s * 14 + 1] = (y05 - y07); + + x[s * 8] = (y08 + y10); + x[s * 8 + 1] = (y09 + y11); + x[s * 18] = (y08 - y10); + x[s * 18 + 1] = (y09 - y11); + + x[s * 12] = (y12 + y14); + x[s * 12 + 1] = (y13 + y15); + x[s * 2] = (y12 - y14); + x[s * 2 + 1] = (y13 - y15); + + x[s * 16] = (y16 + y18); + x[s * 16 + 1] = (y17 + y19); + x[s * 6] = (y16 - y18); + x[s * 6 + 1] = (y17 - y19); +} + +#ifndef FUNCTION_fft12 +#define FUNCTION_fft12 + +#undef C31 +#define C31 (STC(0x91261468)) /* FL2FXCONST_DBL(-0.86602540) = -sqrt(3)/2 */ + +static inline void fft12(FIXP_DBL *pInput) { + FIXP_DBL aDst[24]; + FIXP_DBL *pSrc, *pDst; + int i; + + pSrc = pInput; + pDst = aDst; + FIXP_DBL r1, r2, s1, s2, pD; + + /* First 3*2 samples are shifted right by 2 before output */ + r1 = pSrc[8] + pSrc[16]; + r2 = fMultDiv2((pSrc[8] - pSrc[16]), C31); + pD = pSrc[0] >> 1; + pDst[0] = (pD + (r1 >> 1)) >> 1; + r1 = pD - (r1 >> 2); + + /* imaginary part */ + s1 = pSrc[9] + pSrc[17]; + s2 = fMultDiv2((pSrc[9] - pSrc[17]), C31); + pD = pSrc[1] >> 1; + pDst[1] = (pD + (s1 >> 1)) >> 1; + s1 = pD - (s1 >> 2); + + /* combination */ + pDst[2] = (r1 - s2) >> 1; + pDst[3] = (s1 + r2) >> 1; + pDst[4] = (r1 + s2) >> 1; + pDst[5] = (s1 - r2) >> 1; + pSrc += 2; + pDst += 6; + + const FIXP_STB *pVecRe = RotVectorReal12; + const FIXP_STB *pVecIm = RotVectorImag12; + FIXP_DBL re, im; + FIXP_STB vre, vim; + for (i = 0; i < 2; i++) { + /* sample 0,1 are shifted right by 2 before output */ + /* sample 2,3 4,5 are shifted right by 1 and complex multiplied before + * output */ + + r1 = pSrc[8] + pSrc[16]; + r2 = fMultDiv2((pSrc[8] - pSrc[16]), C31); + pD = pSrc[0] >> 1; + pDst[0] = (pD + (r1 >> 1)) >> 1; + r1 = pD - (r1 >> 2); + + /* imaginary part */ + s1 = pSrc[9] + pSrc[17]; + s2 = fMultDiv2((pSrc[9] - pSrc[17]), C31); + pD = pSrc[1] >> 1; + pDst[1] = (pD + (s1 >> 1)) >> 1; + s1 = pD - (s1 >> 2); + + /* combination */ + re = (r1 - s2) >> 0; + im = (s1 + r2) >> 0; + vre = *pVecRe++; + vim = *pVecIm++; + cplxMultDiv2(&pDst[3], &pDst[2], im, re, vre, vim); + + re = (r1 + s2) >> 0; + im = (s1 - r2) >> 0; + vre = *pVecRe++; + vim = *pVecIm++; + cplxMultDiv2(&pDst[5], &pDst[4], im, re, vre, vim); + + pDst += 6; + pSrc += 2; + } + /* sample 0,1 are shifted right by 2 before output */ + /* sample 2,3 is shifted right by 1 and complex multiplied with (0.0,+1.0) */ + /* sample 4,5 is shifted right by 1 and complex multiplied with (-1.0,0.0) */ + r1 = pSrc[8] + pSrc[16]; + r2 = fMultDiv2((pSrc[8] - pSrc[16]), C31); + pD = pSrc[0] >> 1; + pDst[0] = (pD + (r1 >> 1)) >> 1; + r1 = pD - (r1 >> 2); + + /* imaginary part */ + s1 = pSrc[9] + pSrc[17]; + s2 = fMultDiv2((pSrc[9] - pSrc[17]), C31); + pD = pSrc[1] >> 1; + pDst[1] = (pD + (s1 >> 1)) >> 1; + s1 = pD - (s1 >> 2); + + /* combination */ + pDst[2] = (s1 + r2) >> 1; + pDst[3] = (s2 - r1) >> 1; + pDst[4] = -((r1 + s2) >> 1); + pDst[5] = (r2 - s1) >> 1; + + /* Perform 3 times the fft of length 4. The input samples are at the address + of aDst and the output samples are at the address of pInput. The input vector + for the fft of length 4 is built of the interleaved samples in aDst, the + output samples are stored consecutively at the address of pInput. + */ + pSrc = aDst; + pDst = pInput; + for (i = 0; i < 3; i++) { + /* inline FFT4 merged with incoming resorting loop */ + FIXP_DBL a00, a10, a20, a30, tmp0, tmp1; + + a00 = (pSrc[0] + pSrc[12]) >> 1; /* Re A + Re B */ + a10 = (pSrc[6] + pSrc[18]) >> 1; /* Re C + Re D */ + a20 = (pSrc[1] + pSrc[13]) >> 1; /* Im A + Im B */ + a30 = (pSrc[7] + pSrc[19]) >> 1; /* Im C + Im D */ + + pDst[0] = a00 + a10; /* Re A' = Re A + Re B + Re C + Re D */ + pDst[1] = a20 + a30; /* Im A' = Im A + Im B + Im C + Im D */ + + tmp0 = a00 - pSrc[12]; /* Re A - Re B */ + tmp1 = a20 - pSrc[13]; /* Im A - Im B */ + + pDst[12] = a00 - a10; /* Re C' = Re A + Re B - Re C - Re D */ + pDst[13] = a20 - a30; /* Im C' = Im A + Im B - Im C - Im D */ + + a10 = a10 - pSrc[18]; /* Re C - Re D */ + a30 = a30 - pSrc[19]; /* Im C - Im D */ + + pDst[6] = tmp0 + a30; /* Re B' = Re A - Re B + Im C - Im D */ + pDst[18] = tmp0 - a30; /* Re D' = Re A - Re B - Im C + Im D */ + pDst[7] = tmp1 - a10; /* Im B' = Im A - Im B - Re C + Re D */ + pDst[19] = tmp1 + a10; /* Im D' = Im A - Im B + Re C - Re D */ + + pSrc += 2; + pDst += 2; + } +} +#endif /* FUNCTION_fft12 */ + +#ifndef FUNCTION_fft15 + +#define N3 3 +#define N5 5 +#define N6 6 +#define N15 15 + +/* Performs the FFT of length 15. It is split into FFTs of length 3 and + * length 5. */ +static inline void fft15(FIXP_DBL *pInput) { + FIXP_DBL aDst[2 * N15]; + FIXP_DBL aDst1[2 * N15]; + int i, k, l; + + /* Sort input vector for fft's of length 3 + input3(0:2) = [input(0) input(5) input(10)]; + input3(3:5) = [input(3) input(8) input(13)]; + input3(6:8) = [input(6) input(11) input(1)]; + input3(9:11) = [input(9) input(14) input(4)]; + input3(12:14) = [input(12) input(2) input(7)]; */ + { + const FIXP_DBL *pSrc = pInput; + FIXP_DBL *RESTRICT pDst = aDst; + /* Merge 3 loops into one, skip call of fft3 */ + for (i = 0, l = 0, k = 0; i < N5; i++, k += 6) { + pDst[k + 0] = pSrc[l]; + pDst[k + 1] = pSrc[l + 1]; + l += 2 * N5; + if (l >= (2 * N15)) l -= (2 * N15); + + pDst[k + 2] = pSrc[l]; + pDst[k + 3] = pSrc[l + 1]; + l += 2 * N5; + if (l >= (2 * N15)) l -= (2 * N15); + pDst[k + 4] = pSrc[l]; + pDst[k + 5] = pSrc[l + 1]; + l += (2 * N5) + (2 * N3); + if (l >= (2 * N15)) l -= (2 * N15); + + /* fft3 merged with shift right by 2 loop */ + FIXP_DBL r1, r2, r3; + FIXP_DBL s1, s2; + /* real part */ + r1 = pDst[k + 2] + pDst[k + 4]; + r2 = fMult((pDst[k + 2] - pDst[k + 4]), C31); + s1 = pDst[k + 0]; + pDst[k + 0] = (s1 + r1) >> 2; + r1 = s1 - (r1 >> 1); + + /* imaginary part */ + s1 = pDst[k + 3] + pDst[k + 5]; + s2 = fMult((pDst[k + 3] - pDst[k + 5]), C31); + r3 = pDst[k + 1]; + pDst[k + 1] = (r3 + s1) >> 2; + s1 = r3 - (s1 >> 1); + + /* combination */ + pDst[k + 2] = (r1 - s2) >> 2; + pDst[k + 4] = (r1 + s2) >> 2; + pDst[k + 3] = (s1 + r2) >> 2; + pDst[k + 5] = (s1 - r2) >> 2; + } + } + /* Sort input vector for fft's of length 5 + input5(0:4) = [output3(0) output3(3) output3(6) output3(9) output3(12)]; + input5(5:9) = [output3(1) output3(4) output3(7) output3(10) output3(13)]; + input5(10:14) = [output3(2) output3(5) output3(8) output3(11) output3(14)]; */ + /* Merge 2 loops into one, brings about 10% */ + { + const FIXP_DBL *pSrc = aDst; + FIXP_DBL *RESTRICT pDst = aDst1; + for (i = 0, l = 0, k = 0; i < N3; i++, k += 10) { + l = 2 * i; + pDst[k + 0] = pSrc[l + 0]; + pDst[k + 1] = pSrc[l + 1]; + pDst[k + 2] = pSrc[l + 0 + (2 * N3)]; + pDst[k + 3] = pSrc[l + 1 + (2 * N3)]; + pDst[k + 4] = pSrc[l + 0 + (4 * N3)]; + pDst[k + 5] = pSrc[l + 1 + (4 * N3)]; + pDst[k + 6] = pSrc[l + 0 + (6 * N3)]; + pDst[k + 7] = pSrc[l + 1 + (6 * N3)]; + pDst[k + 8] = pSrc[l + 0 + (8 * N3)]; + pDst[k + 9] = pSrc[l + 1 + (8 * N3)]; + fft5(&pDst[k]); + } + } + /* Sort output vector of length 15 + output = [out5(0) out5(6) out5(12) out5(3) out5(9) + out5(10) out5(1) out5(7) out5(13) out5(4) + out5(5) out5(11) out5(2) out5(8) out5(14)]; */ + /* optimize clumsy loop, brings about 5% */ + { + const FIXP_DBL *pSrc = aDst1; + FIXP_DBL *RESTRICT pDst = pInput; + for (i = 0, l = 0, k = 0; i < N3; i++, k += 10) { + pDst[k + 0] = pSrc[l]; + pDst[k + 1] = pSrc[l + 1]; + l += (2 * N6); + if (l >= (2 * N15)) l -= (2 * N15); + pDst[k + 2] = pSrc[l]; + pDst[k + 3] = pSrc[l + 1]; + l += (2 * N6); + if (l >= (2 * N15)) l -= (2 * N15); + pDst[k + 4] = pSrc[l]; + pDst[k + 5] = pSrc[l + 1]; + l += (2 * N6); + if (l >= (2 * N15)) l -= (2 * N15); + pDst[k + 6] = pSrc[l]; + pDst[k + 7] = pSrc[l + 1]; + l += (2 * N6); + if (l >= (2 * N15)) l -= (2 * N15); + pDst[k + 8] = pSrc[l]; + pDst[k + 9] = pSrc[l + 1]; + l += 2; /* no modulo check needed, it cannot occur */ + } + } +} +#endif /* FUNCTION_fft15 */ + +/* + Select shift placement. + Some processors like ARM may shift "for free" in combination with an addition + or substraction, but others don't so either combining shift with +/- or reduce + the total amount or shift operations is optimal + */ +#if !defined(__arm__) +#define SHIFT_A >> 1 +#define SHIFT_B +#else +#define SHIFT_A +#define SHIFT_B >> 1 +#endif + +#ifndef FUNCTION_fft_16 /* we check, if fft_16 (FIXP_DBL *) is not yet defined \ + */ + +/* This defines prevents this array to be declared twice, if 16-bit fft is + * enabled too */ +#define FUNCTION_DATA_fft_16_w16 +static const FIXP_STP fft16_w16[2] = {STCP(0x7641af3d, 0x30fbc54d), + STCP(0x30fbc54d, 0x7641af3d)}; + +LNK_SECTION_CODE_L1 +inline void fft_16(FIXP_DBL *RESTRICT x) { + FIXP_DBL vr, ur; + FIXP_DBL vr2, ur2; + FIXP_DBL vr3, ur3; + FIXP_DBL vr4, ur4; + FIXP_DBL vi, ui; + FIXP_DBL vi2, ui2; + FIXP_DBL vi3, ui3; + + vr = (x[0] >> 1) + (x[16] >> 1); /* Re A + Re B */ + ur = (x[1] >> 1) + (x[17] >> 1); /* Im A + Im B */ + vi = (x[8] SHIFT_A) + (x[24] SHIFT_A); /* Re C + Re D */ + ui = (x[9] SHIFT_A) + (x[25] SHIFT_A); /* Im C + Im D */ + x[0] = vr + (vi SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[1] = ur + (ui SHIFT_B); /* Im A' = sum of imag values */ + + vr2 = (x[4] >> 1) + (x[20] >> 1); /* Re A + Re B */ + ur2 = (x[5] >> 1) + (x[21] >> 1); /* Im A + Im B */ + + x[4] = vr - (vi SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[5] = ur - (ui SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + vr -= x[16]; /* Re A - Re B */ + vi = (vi SHIFT_B)-x[24]; /* Re C - Re D */ + ur -= x[17]; /* Im A - Im B */ + ui = (ui SHIFT_B)-x[25]; /* Im C - Im D */ + + vr3 = (x[2] >> 1) + (x[18] >> 1); /* Re A + Re B */ + ur3 = (x[3] >> 1) + (x[19] >> 1); /* Im A + Im B */ + + x[2] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + x[3] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + + vr4 = (x[6] >> 1) + (x[22] >> 1); /* Re A + Re B */ + ur4 = (x[7] >> 1) + (x[23] >> 1); /* Im A + Im B */ + + x[6] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + x[7] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + vi2 = (x[12] SHIFT_A) + (x[28] SHIFT_A); /* Re C + Re D */ + ui2 = (x[13] SHIFT_A) + (x[29] SHIFT_A); /* Im C + Im D */ + x[8] = vr2 + (vi2 SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[9] = ur2 + (ui2 SHIFT_B); /* Im A' = sum of imag values */ + x[12] = vr2 - (vi2 SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[13] = ur2 - (ui2 SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + vr2 -= x[20]; /* Re A - Re B */ + ur2 -= x[21]; /* Im A - Im B */ + vi2 = (vi2 SHIFT_B)-x[28]; /* Re C - Re D */ + ui2 = (ui2 SHIFT_B)-x[29]; /* Im C - Im D */ + + vi = (x[10] SHIFT_A) + (x[26] SHIFT_A); /* Re C + Re D */ + ui = (x[11] SHIFT_A) + (x[27] SHIFT_A); /* Im C + Im D */ + + x[10] = ui2 + vr2; /* Re B' = Im C - Im D + Re A - Re B */ + x[11] = ur2 - vi2; /* Im B'= -Re C + Re D + Im A - Im B */ + + vi3 = (x[14] SHIFT_A) + (x[30] SHIFT_A); /* Re C + Re D */ + ui3 = (x[15] SHIFT_A) + (x[31] SHIFT_A); /* Im C + Im D */ + + x[14] = vr2 - ui2; /* Re D' = -Im C + Im D + Re A - Re B */ + x[15] = vi2 + ur2; /* Im D'= Re C - Re D + Im A - Im B */ + + x[16] = vr3 + (vi SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[17] = ur3 + (ui SHIFT_B); /* Im A' = sum of imag values */ + x[20] = vr3 - (vi SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[21] = ur3 - (ui SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + vr3 -= x[18]; /* Re A - Re B */ + ur3 -= x[19]; /* Im A - Im B */ + vi = (vi SHIFT_B)-x[26]; /* Re C - Re D */ + ui = (ui SHIFT_B)-x[27]; /* Im C - Im D */ + x[18] = ui + vr3; /* Re B' = Im C - Im D + Re A - Re B */ + x[19] = ur3 - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + + x[24] = vr4 + (vi3 SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[28] = vr4 - (vi3 SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[25] = ur4 + (ui3 SHIFT_B); /* Im A' = sum of imag values */ + x[29] = ur4 - (ui3 SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + vr4 -= x[22]; /* Re A - Re B */ + ur4 -= x[23]; /* Im A - Im B */ + + x[22] = vr3 - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + x[23] = vi + ur3; /* Im D'= Re C - Re D + Im A - Im B */ + + vi3 = (vi3 SHIFT_B)-x[30]; /* Re C - Re D */ + ui3 = (ui3 SHIFT_B)-x[31]; /* Im C - Im D */ + x[26] = ui3 + vr4; /* Re B' = Im C - Im D + Re A - Re B */ + x[30] = vr4 - ui3; /* Re D' = -Im C + Im D + Re A - Re B */ + x[27] = ur4 - vi3; /* Im B'= -Re C + Re D + Im A - Im B */ + x[31] = vi3 + ur4; /* Im D'= Re C - Re D + Im A - Im B */ + + // xt1 = 0 + // xt2 = 8 + vr = x[8]; + vi = x[9]; + ur = x[0] >> 1; + ui = x[1] >> 1; + x[0] = ur + (vr >> 1); + x[1] = ui + (vi >> 1); + x[8] = ur - (vr >> 1); + x[9] = ui - (vi >> 1); + + // xt1 = 4 + // xt2 = 12 + vr = x[13]; + vi = x[12]; + ur = x[4] >> 1; + ui = x[5] >> 1; + x[4] = ur + (vr >> 1); + x[5] = ui - (vi >> 1); + x[12] = ur - (vr >> 1); + x[13] = ui + (vi >> 1); + + // xt1 = 16 + // xt2 = 24 + vr = x[24]; + vi = x[25]; + ur = x[16] >> 1; + ui = x[17] >> 1; + x[16] = ur + (vr >> 1); + x[17] = ui + (vi >> 1); + x[24] = ur - (vr >> 1); + x[25] = ui - (vi >> 1); + + // xt1 = 20 + // xt2 = 28 + vr = x[29]; + vi = x[28]; + ur = x[20] >> 1; + ui = x[21] >> 1; + x[20] = ur + (vr >> 1); + x[21] = ui - (vi >> 1); + x[28] = ur - (vr >> 1); + x[29] = ui + (vi >> 1); + + // xt1 = 2 + // xt2 = 10 + SUMDIFF_PIFOURTH(vi, vr, x[10], x[11]) + // vr = fMultDiv2((x[11] + x[10]),W_PiFOURTH); + // vi = fMultDiv2((x[11] - x[10]),W_PiFOURTH); + ur = x[2]; + ui = x[3]; + x[2] = (ur >> 1) + vr; + x[3] = (ui >> 1) + vi; + x[10] = (ur >> 1) - vr; + x[11] = (ui >> 1) - vi; + + // xt1 = 6 + // xt2 = 14 + SUMDIFF_PIFOURTH(vr, vi, x[14], x[15]) + ur = x[6]; + ui = x[7]; + x[6] = (ur >> 1) + vr; + x[7] = (ui >> 1) - vi; + x[14] = (ur >> 1) - vr; + x[15] = (ui >> 1) + vi; + + // xt1 = 18 + // xt2 = 26 + SUMDIFF_PIFOURTH(vi, vr, x[26], x[27]) + ur = x[18]; + ui = x[19]; + x[18] = (ur >> 1) + vr; + x[19] = (ui >> 1) + vi; + x[26] = (ur >> 1) - vr; + x[27] = (ui >> 1) - vi; + + // xt1 = 22 + // xt2 = 30 + SUMDIFF_PIFOURTH(vr, vi, x[30], x[31]) + ur = x[22]; + ui = x[23]; + x[22] = (ur >> 1) + vr; + x[23] = (ui >> 1) - vi; + x[30] = (ur >> 1) - vr; + x[31] = (ui >> 1) + vi; + + // xt1 = 0 + // xt2 = 16 + vr = x[16]; + vi = x[17]; + ur = x[0] >> 1; + ui = x[1] >> 1; + x[0] = ur + (vr >> 1); + x[1] = ui + (vi >> 1); + x[16] = ur - (vr >> 1); + x[17] = ui - (vi >> 1); + + // xt1 = 8 + // xt2 = 24 + vi = x[24]; + vr = x[25]; + ur = x[8] >> 1; + ui = x[9] >> 1; + x[8] = ur + (vr >> 1); + x[9] = ui - (vi >> 1); + x[24] = ur - (vr >> 1); + x[25] = ui + (vi >> 1); + + // xt1 = 2 + // xt2 = 18 + cplxMultDiv2(&vi, &vr, x[19], x[18], fft16_w16[0]); + ur = x[2]; + ui = x[3]; + x[2] = (ur >> 1) + vr; + x[3] = (ui >> 1) + vi; + x[18] = (ur >> 1) - vr; + x[19] = (ui >> 1) - vi; + + // xt1 = 10 + // xt2 = 26 + cplxMultDiv2(&vr, &vi, x[27], x[26], fft16_w16[0]); + ur = x[10]; + ui = x[11]; + x[10] = (ur >> 1) + vr; + x[11] = (ui >> 1) - vi; + x[26] = (ur >> 1) - vr; + x[27] = (ui >> 1) + vi; + + // xt1 = 4 + // xt2 = 20 + SUMDIFF_PIFOURTH(vi, vr, x[20], x[21]) + ur = x[4]; + ui = x[5]; + x[4] = (ur >> 1) + vr; + x[5] = (ui >> 1) + vi; + x[20] = (ur >> 1) - vr; + x[21] = (ui >> 1) - vi; + + // xt1 = 12 + // xt2 = 28 + SUMDIFF_PIFOURTH(vr, vi, x[28], x[29]) + ur = x[12]; + ui = x[13]; + x[12] = (ur >> 1) + vr; + x[13] = (ui >> 1) - vi; + x[28] = (ur >> 1) - vr; + x[29] = (ui >> 1) + vi; + + // xt1 = 6 + // xt2 = 22 + cplxMultDiv2(&vi, &vr, x[23], x[22], fft16_w16[1]); + ur = x[6]; + ui = x[7]; + x[6] = (ur >> 1) + vr; + x[7] = (ui >> 1) + vi; + x[22] = (ur >> 1) - vr; + x[23] = (ui >> 1) - vi; + + // xt1 = 14 + // xt2 = 30 + cplxMultDiv2(&vr, &vi, x[31], x[30], fft16_w16[1]); + ur = x[14]; + ui = x[15]; + x[14] = (ur >> 1) + vr; + x[15] = (ui >> 1) - vi; + x[30] = (ur >> 1) - vr; + x[31] = (ui >> 1) + vi; +} +#endif /* FUNCTION_fft_16 */ + +#ifndef FUNCTION_fft_32 +static const FIXP_STP fft32_w32[6] = { + STCP(0x7641af3d, 0x30fbc54d), STCP(0x30fbc54d, 0x7641af3d), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x6a6d98a4, 0x471cece7), + STCP(0x471cece7, 0x6a6d98a4), STCP(0x18f8b83c, 0x7d8a5f40)}; +#define W_PiFOURTH STC(0x5a82799a) + +LNK_SECTION_CODE_L1 +inline void fft_32(FIXP_DBL *const _x) { + /* + * 1+2 stage radix 4 + */ + + ///////////////////////////////////////////////////////////////////////////////////////// + { + FIXP_DBL *const x = _x; + FIXP_DBL vi, ui; + FIXP_DBL vi2, ui2; + FIXP_DBL vi3, ui3; + FIXP_DBL vr, ur; + FIXP_DBL vr2, ur2; + FIXP_DBL vr3, ur3; + FIXP_DBL vr4, ur4; + + // i = 0 + vr = (x[0] + x[32]) >> 1; /* Re A + Re B */ + ur = (x[1] + x[33]) >> 1; /* Im A + Im B */ + vi = (x[16] + x[48]) SHIFT_A; /* Re C + Re D */ + ui = (x[17] + x[49]) SHIFT_A; /* Im C + Im D */ + + x[0] = vr + (vi SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[1] = ur + (ui SHIFT_B); /* Im A' = sum of imag values */ + + vr2 = (x[4] + x[36]) >> 1; /* Re A + Re B */ + ur2 = (x[5] + x[37]) >> 1; /* Im A + Im B */ + + x[4] = vr - (vi SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[5] = ur - (ui SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr -= x[32]; /* Re A - Re B */ + ur -= x[33]; /* Im A - Im B */ + vi = (vi SHIFT_B)-x[48]; /* Re C - Re D */ + ui = (ui SHIFT_B)-x[49]; /* Im C - Im D */ + + vr3 = (x[2] + x[34]) >> 1; /* Re A + Re B */ + ur3 = (x[3] + x[35]) >> 1; /* Im A + Im B */ + + x[2] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + x[3] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + + vr4 = (x[6] + x[38]) >> 1; /* Re A + Re B */ + ur4 = (x[7] + x[39]) >> 1; /* Im A + Im B */ + + x[6] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + x[7] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + // i=16 + vi = (x[20] + x[52]) SHIFT_A; /* Re C + Re D */ + ui = (x[21] + x[53]) SHIFT_A; /* Im C + Im D */ + + x[16] = vr2 + (vi SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[17] = ur2 + (ui SHIFT_B); /* Im A' = sum of imag values */ + x[20] = vr2 - (vi SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[21] = ur2 - (ui SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr2 -= x[36]; /* Re A - Re B */ + ur2 -= x[37]; /* Im A - Im B */ + vi = (vi SHIFT_B)-x[52]; /* Re C - Re D */ + ui = (ui SHIFT_B)-x[53]; /* Im C - Im D */ + + vi2 = (x[18] + x[50]) SHIFT_A; /* Re C + Re D */ + ui2 = (x[19] + x[51]) SHIFT_A; /* Im C + Im D */ + + x[18] = ui + vr2; /* Re B' = Im C - Im D + Re A - Re B */ + x[19] = ur2 - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + + vi3 = (x[22] + x[54]) SHIFT_A; /* Re C + Re D */ + ui3 = (x[23] + x[55]) SHIFT_A; /* Im C + Im D */ + + x[22] = vr2 - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + x[23] = vi + ur2; /* Im D'= Re C - Re D + Im A - Im B */ + + // i = 32 + + x[32] = vr3 + (vi2 SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[33] = ur3 + (ui2 SHIFT_B); /* Im A' = sum of imag values */ + x[36] = vr3 - (vi2 SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[37] = ur3 - (ui2 SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr3 -= x[34]; /* Re A - Re B */ + ur3 -= x[35]; /* Im A - Im B */ + vi2 = (vi2 SHIFT_B)-x[50]; /* Re C - Re D */ + ui2 = (ui2 SHIFT_B)-x[51]; /* Im C - Im D */ + + x[34] = ui2 + vr3; /* Re B' = Im C - Im D + Re A - Re B */ + x[35] = ur3 - vi2; /* Im B'= -Re C + Re D + Im A - Im B */ + + // i=48 + + x[48] = vr4 + (vi3 SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[52] = vr4 - (vi3 SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[49] = ur4 + (ui3 SHIFT_B); /* Im A' = sum of imag values */ + x[53] = ur4 - (ui3 SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr4 -= x[38]; /* Re A - Re B */ + ur4 -= x[39]; /* Im A - Im B */ + + x[38] = vr3 - ui2; /* Re D' = -Im C + Im D + Re A - Re B */ + x[39] = vi2 + ur3; /* Im D'= Re C - Re D + Im A - Im B */ + + vi3 = (vi3 SHIFT_B)-x[54]; /* Re C - Re D */ + ui3 = (ui3 SHIFT_B)-x[55]; /* Im C - Im D */ + + x[50] = ui3 + vr4; /* Re B' = Im C - Im D + Re A - Re B */ + x[54] = vr4 - ui3; /* Re D' = -Im C + Im D + Re A - Re B */ + x[51] = ur4 - vi3; /* Im B'= -Re C + Re D + Im A - Im B */ + x[55] = vi3 + ur4; /* Im D'= Re C - Re D + Im A - Im B */ + + // i=8 + vr = (x[8] + x[40]) >> 1; /* Re A + Re B */ + ur = (x[9] + x[41]) >> 1; /* Im A + Im B */ + vi = (x[24] + x[56]) SHIFT_A; /* Re C + Re D */ + ui = (x[25] + x[57]) SHIFT_A; /* Im C + Im D */ + + x[8] = vr + (vi SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[9] = ur + (ui SHIFT_B); /* Im A' = sum of imag values */ + + vr2 = (x[12] + x[44]) >> 1; /* Re A + Re B */ + ur2 = (x[13] + x[45]) >> 1; /* Im A + Im B */ + + x[12] = vr - (vi SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[13] = ur - (ui SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr -= x[40]; /* Re A - Re B */ + ur -= x[41]; /* Im A - Im B */ + vi = (vi SHIFT_B)-x[56]; /* Re C - Re D */ + ui = (ui SHIFT_B)-x[57]; /* Im C - Im D */ + + vr3 = (x[10] + x[42]) >> 1; /* Re A + Re B */ + ur3 = (x[11] + x[43]) >> 1; /* Im A + Im B */ + + x[10] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + x[11] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + + vr4 = (x[14] + x[46]) >> 1; /* Re A + Re B */ + ur4 = (x[15] + x[47]) >> 1; /* Im A + Im B */ + + x[14] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + x[15] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + // i=24 + vi = (x[28] + x[60]) SHIFT_A; /* Re C + Re D */ + ui = (x[29] + x[61]) SHIFT_A; /* Im C + Im D */ + + x[24] = vr2 + (vi SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[28] = vr2 - (vi SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[25] = ur2 + (ui SHIFT_B); /* Im A' = sum of imag values */ + x[29] = ur2 - (ui SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr2 -= x[44]; /* Re A - Re B */ + ur2 -= x[45]; /* Im A - Im B */ + vi = (vi SHIFT_B)-x[60]; /* Re C - Re D */ + ui = (ui SHIFT_B)-x[61]; /* Im C - Im D */ + + vi2 = (x[26] + x[58]) SHIFT_A; /* Re C + Re D */ + ui2 = (x[27] + x[59]) SHIFT_A; /* Im C + Im D */ + + x[26] = ui + vr2; /* Re B' = Im C - Im D + Re A - Re B */ + x[27] = ur2 - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + + vi3 = (x[30] + x[62]) SHIFT_A; /* Re C + Re D */ + ui3 = (x[31] + x[63]) SHIFT_A; /* Im C + Im D */ + + x[30] = vr2 - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + x[31] = vi + ur2; /* Im D'= Re C - Re D + Im A - Im B */ + + // i=40 + + x[40] = vr3 + (vi2 SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[44] = vr3 - (vi2 SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[41] = ur3 + (ui2 SHIFT_B); /* Im A' = sum of imag values */ + x[45] = ur3 - (ui2 SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr3 -= x[42]; /* Re A - Re B */ + ur3 -= x[43]; /* Im A - Im B */ + vi2 = (vi2 SHIFT_B)-x[58]; /* Re C - Re D */ + ui2 = (ui2 SHIFT_B)-x[59]; /* Im C - Im D */ + + x[42] = ui2 + vr3; /* Re B' = Im C - Im D + Re A - Re B */ + x[43] = ur3 - vi2; /* Im B'= -Re C + Re D + Im A - Im B */ + + // i=56 + + x[56] = vr4 + (vi3 SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[60] = vr4 - (vi3 SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[57] = ur4 + (ui3 SHIFT_B); /* Im A' = sum of imag values */ + x[61] = ur4 - (ui3 SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr4 -= x[46]; /* Re A - Re B */ + ur4 -= x[47]; /* Im A - Im B */ + + x[46] = vr3 - ui2; /* Re D' = -Im C + Im D + Re A - Re B */ + x[47] = vi2 + ur3; /* Im D'= Re C - Re D + Im A - Im B */ + + vi3 = (vi3 SHIFT_B)-x[62]; /* Re C - Re D */ + ui3 = (ui3 SHIFT_B)-x[63]; /* Im C - Im D */ + + x[58] = ui3 + vr4; /* Re B' = Im C - Im D + Re A - Re B */ + x[62] = vr4 - ui3; /* Re D' = -Im C + Im D + Re A - Re B */ + x[59] = ur4 - vi3; /* Im B'= -Re C + Re D + Im A - Im B */ + x[63] = vi3 + ur4; /* Im D'= Re C - Re D + Im A - Im B */ + } + + { + FIXP_DBL *xt = _x; + + int j = 4; + do { + FIXP_DBL vi, ui, vr, ur; + + vr = xt[8]; + vi = xt[9]; + ur = xt[0] >> 1; + ui = xt[1] >> 1; + xt[0] = ur + (vr >> 1); + xt[1] = ui + (vi >> 1); + xt[8] = ur - (vr >> 1); + xt[9] = ui - (vi >> 1); + + vr = xt[13]; + vi = xt[12]; + ur = xt[4] >> 1; + ui = xt[5] >> 1; + xt[4] = ur + (vr >> 1); + xt[5] = ui - (vi >> 1); + xt[12] = ur - (vr >> 1); + xt[13] = ui + (vi >> 1); + + SUMDIFF_PIFOURTH(vi, vr, xt[10], xt[11]) + ur = xt[2]; + ui = xt[3]; + xt[2] = (ur >> 1) + vr; + xt[3] = (ui >> 1) + vi; + xt[10] = (ur >> 1) - vr; + xt[11] = (ui >> 1) - vi; + + SUMDIFF_PIFOURTH(vr, vi, xt[14], xt[15]) + ur = xt[6]; + ui = xt[7]; + + xt[6] = (ur >> 1) + vr; + xt[7] = (ui >> 1) - vi; + xt[14] = (ur >> 1) - vr; + xt[15] = (ui >> 1) + vi; + xt += 16; + } while (--j != 0); + } + + { + FIXP_DBL *const x = _x; + FIXP_DBL vi, ui, vr, ur; + + vr = x[16]; + vi = x[17]; + ur = x[0] >> 1; + ui = x[1] >> 1; + x[0] = ur + (vr >> 1); + x[1] = ui + (vi >> 1); + x[16] = ur - (vr >> 1); + x[17] = ui - (vi >> 1); + + vi = x[24]; + vr = x[25]; + ur = x[8] >> 1; + ui = x[9] >> 1; + x[8] = ur + (vr >> 1); + x[9] = ui - (vi >> 1); + x[24] = ur - (vr >> 1); + x[25] = ui + (vi >> 1); + + vr = x[48]; + vi = x[49]; + ur = x[32] >> 1; + ui = x[33] >> 1; + x[32] = ur + (vr >> 1); + x[33] = ui + (vi >> 1); + x[48] = ur - (vr >> 1); + x[49] = ui - (vi >> 1); + + vi = x[56]; + vr = x[57]; + ur = x[40] >> 1; + ui = x[41] >> 1; + x[40] = ur + (vr >> 1); + x[41] = ui - (vi >> 1); + x[56] = ur - (vr >> 1); + x[57] = ui + (vi >> 1); + + cplxMultDiv2(&vi, &vr, x[19], x[18], fft32_w32[0]); + ur = x[2]; + ui = x[3]; + x[2] = (ur >> 1) + vr; + x[3] = (ui >> 1) + vi; + x[18] = (ur >> 1) - vr; + x[19] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[27], x[26], fft32_w32[0]); + ur = x[10]; + ui = x[11]; + x[10] = (ur >> 1) + vr; + x[11] = (ui >> 1) - vi; + x[26] = (ur >> 1) - vr; + x[27] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[51], x[50], fft32_w32[0]); + ur = x[34]; + ui = x[35]; + x[34] = (ur >> 1) + vr; + x[35] = (ui >> 1) + vi; + x[50] = (ur >> 1) - vr; + x[51] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[59], x[58], fft32_w32[0]); + ur = x[42]; + ui = x[43]; + x[42] = (ur >> 1) + vr; + x[43] = (ui >> 1) - vi; + x[58] = (ur >> 1) - vr; + x[59] = (ui >> 1) + vi; + + SUMDIFF_PIFOURTH(vi, vr, x[20], x[21]) + ur = x[4]; + ui = x[5]; + x[4] = (ur >> 1) + vr; + x[5] = (ui >> 1) + vi; + x[20] = (ur >> 1) - vr; + x[21] = (ui >> 1) - vi; + + SUMDIFF_PIFOURTH(vr, vi, x[28], x[29]) + ur = x[12]; + ui = x[13]; + x[12] = (ur >> 1) + vr; + x[13] = (ui >> 1) - vi; + x[28] = (ur >> 1) - vr; + x[29] = (ui >> 1) + vi; + + SUMDIFF_PIFOURTH(vi, vr, x[52], x[53]) + ur = x[36]; + ui = x[37]; + x[36] = (ur >> 1) + vr; + x[37] = (ui >> 1) + vi; + x[52] = (ur >> 1) - vr; + x[53] = (ui >> 1) - vi; + + SUMDIFF_PIFOURTH(vr, vi, x[60], x[61]) + ur = x[44]; + ui = x[45]; + x[44] = (ur >> 1) + vr; + x[45] = (ui >> 1) - vi; + x[60] = (ur >> 1) - vr; + x[61] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[23], x[22], fft32_w32[1]); + ur = x[6]; + ui = x[7]; + x[6] = (ur >> 1) + vr; + x[7] = (ui >> 1) + vi; + x[22] = (ur >> 1) - vr; + x[23] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[31], x[30], fft32_w32[1]); + ur = x[14]; + ui = x[15]; + x[14] = (ur >> 1) + vr; + x[15] = (ui >> 1) - vi; + x[30] = (ur >> 1) - vr; + x[31] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[55], x[54], fft32_w32[1]); + ur = x[38]; + ui = x[39]; + x[38] = (ur >> 1) + vr; + x[39] = (ui >> 1) + vi; + x[54] = (ur >> 1) - vr; + x[55] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[63], x[62], fft32_w32[1]); + ur = x[46]; + ui = x[47]; + + x[46] = (ur >> 1) + vr; + x[47] = (ui >> 1) - vi; + x[62] = (ur >> 1) - vr; + x[63] = (ui >> 1) + vi; + + vr = x[32]; + vi = x[33]; + ur = x[0] >> 1; + ui = x[1] >> 1; + x[0] = ur + (vr >> 1); + x[1] = ui + (vi >> 1); + x[32] = ur - (vr >> 1); + x[33] = ui - (vi >> 1); + + vi = x[48]; + vr = x[49]; + ur = x[16] >> 1; + ui = x[17] >> 1; + x[16] = ur + (vr >> 1); + x[17] = ui - (vi >> 1); + x[48] = ur - (vr >> 1); + x[49] = ui + (vi >> 1); + + cplxMultDiv2(&vi, &vr, x[35], x[34], fft32_w32[2]); + ur = x[2]; + ui = x[3]; + x[2] = (ur >> 1) + vr; + x[3] = (ui >> 1) + vi; + x[34] = (ur >> 1) - vr; + x[35] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[51], x[50], fft32_w32[2]); + ur = x[18]; + ui = x[19]; + x[18] = (ur >> 1) + vr; + x[19] = (ui >> 1) - vi; + x[50] = (ur >> 1) - vr; + x[51] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[37], x[36], fft32_w32[0]); + ur = x[4]; + ui = x[5]; + x[4] = (ur >> 1) + vr; + x[5] = (ui >> 1) + vi; + x[36] = (ur >> 1) - vr; + x[37] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[53], x[52], fft32_w32[0]); + ur = x[20]; + ui = x[21]; + x[20] = (ur >> 1) + vr; + x[21] = (ui >> 1) - vi; + x[52] = (ur >> 1) - vr; + x[53] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[39], x[38], fft32_w32[3]); + ur = x[6]; + ui = x[7]; + x[6] = (ur >> 1) + vr; + x[7] = (ui >> 1) + vi; + x[38] = (ur >> 1) - vr; + x[39] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[55], x[54], fft32_w32[3]); + ur = x[22]; + ui = x[23]; + x[22] = (ur >> 1) + vr; + x[23] = (ui >> 1) - vi; + x[54] = (ur >> 1) - vr; + x[55] = (ui >> 1) + vi; + + SUMDIFF_PIFOURTH(vi, vr, x[40], x[41]) + ur = x[8]; + ui = x[9]; + x[8] = (ur >> 1) + vr; + x[9] = (ui >> 1) + vi; + x[40] = (ur >> 1) - vr; + x[41] = (ui >> 1) - vi; + + SUMDIFF_PIFOURTH(vr, vi, x[56], x[57]) + ur = x[24]; + ui = x[25]; + x[24] = (ur >> 1) + vr; + x[25] = (ui >> 1) - vi; + x[56] = (ur >> 1) - vr; + x[57] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[43], x[42], fft32_w32[4]); + ur = x[10]; + ui = x[11]; + + x[10] = (ur >> 1) + vr; + x[11] = (ui >> 1) + vi; + x[42] = (ur >> 1) - vr; + x[43] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[59], x[58], fft32_w32[4]); + ur = x[26]; + ui = x[27]; + x[26] = (ur >> 1) + vr; + x[27] = (ui >> 1) - vi; + x[58] = (ur >> 1) - vr; + x[59] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[45], x[44], fft32_w32[1]); + ur = x[12]; + ui = x[13]; + x[12] = (ur >> 1) + vr; + x[13] = (ui >> 1) + vi; + x[44] = (ur >> 1) - vr; + x[45] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[61], x[60], fft32_w32[1]); + ur = x[28]; + ui = x[29]; + x[28] = (ur >> 1) + vr; + x[29] = (ui >> 1) - vi; + x[60] = (ur >> 1) - vr; + x[61] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[47], x[46], fft32_w32[5]); + ur = x[14]; + ui = x[15]; + x[14] = (ur >> 1) + vr; + x[15] = (ui >> 1) + vi; + x[46] = (ur >> 1) - vr; + x[47] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[63], x[62], fft32_w32[5]); + ur = x[30]; + ui = x[31]; + x[30] = (ur >> 1) + vr; + x[31] = (ui >> 1) - vi; + x[62] = (ur >> 1) - vr; + x[63] = (ui >> 1) + vi; + } +} +#endif /* #ifndef FUNCTION_fft_32 */ + +/** + * \brief Apply rotation vectors to a data buffer. + * \param cl length of each row of input data. + * \param l total length of input data. + * \param pVecRe real part of rotation coefficient vector. + * \param pVecIm imaginary part of rotation coefficient vector. + */ + +/* + This defines patches each inaccurate 0x7FFF i.e. 0.9999 and uses 0x8000 + (-1.0) instead. At the end, the sign of the result is inverted +*/ +#define noFFT_APPLY_ROT_VECTOR_HQ + +#ifndef FUNCTION_fft_apply_rot_vector__FIXP_DBL +static inline void fft_apply_rot_vector(FIXP_DBL *RESTRICT pData, const int cl, + const int l, const FIXP_STB *pVecRe, + const FIXP_STB *pVecIm) { + FIXP_DBL re, im; + FIXP_STB vre, vim; + + int i, c; + + for (i = 0; i < cl; i++) { + re = pData[2 * i]; + im = pData[2 * i + 1]; + + pData[2 * i] = re >> 2; /* * 0.25 */ + pData[2 * i + 1] = im >> 2; /* * 0.25 */ + } + for (; i < l; i += cl) { + re = pData[2 * i]; + im = pData[2 * i + 1]; + + pData[2 * i] = re >> 2; /* * 0.25 */ + pData[2 * i + 1] = im >> 2; /* * 0.25 */ + + for (c = i + 1; c < i + cl; c++) { + re = pData[2 * c] >> 1; + im = pData[2 * c + 1] >> 1; + vre = *pVecRe++; + vim = *pVecIm++; + + cplxMultDiv2(&pData[2 * c + 1], &pData[2 * c], im, re, vre, vim); + } + } +} +#endif /* FUNCTION_fft_apply_rot_vector__FIXP_DBL */ + +/* select either switch case of function pointer. */ +//#define FFT_TWO_STAGE_SWITCH_CASE +#ifndef FUNCTION_fftN2_func +static inline void fftN2_func(FIXP_DBL *pInput, const int length, + const int dim1, const int dim2, + void (*const fft1)(FIXP_DBL *), + void (*const fft2)(FIXP_DBL *), + const FIXP_STB *RotVectorReal, + const FIXP_STB *RotVectorImag, FIXP_DBL *aDst, + FIXP_DBL *aDst2) { + /* The real part of the input samples are at the addresses with even indices + and the imaginary part of the input samples are at the addresses with odd + indices. The output samples are stored at the address of pInput + */ + FIXP_DBL *pSrc, *pDst, *pDstOut; + int i; + + FDK_ASSERT(length == dim1 * dim2); + + /* Perform dim2 times the fft of length dim1. The input samples are at the + address of pSrc and the output samples are at the address of pDst. The input + vector for the fft of length dim1 is built of the interleaved samples in pSrc, + the output samples are stored consecutively. + */ + pSrc = pInput; + pDst = aDst; + for (i = 0; i < dim2; i++) { + for (int j = 0; j < dim1; j++) { + pDst[2 * j] = pSrc[2 * j * dim2]; + pDst[2 * j + 1] = pSrc[2 * j * dim2 + 1]; + } + + /* fft of size dim1 */ +#ifndef FFT_TWO_STAGE_SWITCH_CASE + fft1(pDst); +#else + switch (dim1) { + case 2: + fft2(pDst); + break; + case 3: + fft3(pDst); + break; + case 4: + fft_4(pDst); + break; + /* case 5: fft5(pDst); break; */ + /* case 8: fft_8(pDst); break; */ + case 12: + fft12(pDst); + break; + /* case 15: fft15(pDst); break; */ + case 16: + fft_16(pDst); + break; + case 32: + fft_32(pDst); + break; + /*case 64: fft_64(pDst); break;*/ + /* case 128: fft_128(pDst); break; */ + } +#endif + pSrc += 2; + pDst = pDst + 2 * dim1; + } + + /* Perform the modulation of the output of the fft of length dim1 */ + pSrc = aDst; + fft_apply_rot_vector(pSrc, dim1, length, RotVectorReal, RotVectorImag); + + /* Perform dim1 times the fft of length dim2. The input samples are at the + address of aDst and the output samples are at the address of pInput. The input + vector for the fft of length dim2 is built of the interleaved samples in aDst, + the output samples are stored consecutively at the address of pInput. + */ + pSrc = aDst; + pDst = aDst2; + pDstOut = pInput; + for (i = 0; i < dim1; i++) { + for (int j = 0; j < dim2; j++) { + pDst[2 * j] = pSrc[2 * j * dim1]; + pDst[2 * j + 1] = pSrc[2 * j * dim1 + 1]; + } + +#ifndef FFT_TWO_STAGE_SWITCH_CASE + fft2(pDst); +#else + switch (dim2) { + case 4: + fft_4(pDst); + break; + case 9: + fft9(pDst); + break; + case 12: + fft12(pDst); + break; + case 15: + fft15(pDst); + break; + case 16: + fft_16(pDst); + break; + case 32: + fft_32(pDst); + break; + } +#endif + + for (int j = 0; j < dim2; j++) { + pDstOut[2 * j * dim1] = pDst[2 * j]; + pDstOut[2 * j * dim1 + 1] = pDst[2 * j + 1]; + } + pSrc += 2; + pDstOut += 2; + } +} +#endif /* FUNCTION_fftN2_function */ + +#define fftN2(DATA_TYPE, pInput, length, dim1, dim2, fft_func1, fft_func2, \ + RotVectorReal, RotVectorImag) \ + { \ + C_AALLOC_SCRATCH_START(aDst, DATA_TYPE, 2 * length) \ + C_AALLOC_SCRATCH_START(aDst2, DATA_TYPE, 2 * dim2) \ + fftN2_func(pInput, length, dim1, dim2, fft_func1, fft_func2, \ + RotVectorReal, RotVectorImag, aDst, aDst2); \ + C_AALLOC_SCRATCH_END(aDst2, DATA_TYPE, 2 * dim2) \ + C_AALLOC_SCRATCH_END(aDst, DATA_TYPE, 2 * length) \ + } + + /*! + * + * \brief complex FFT of length 12,18,24,30,48,60,96, 192, 240, 384, 480 + * \param pInput contains the input signal prescaled right by 2 + * pInput contains the output signal scaled by SCALEFACTOR<#length> + * The output signal does not have any fixed headroom + * \return void + * + */ + +#ifndef FUNCTION_fft6 +static inline void fft6(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 6, 2, 3, fft2, fft3, RotVectorReal6, RotVectorImag6); +} +#endif /* #ifndef FUNCTION_fft6 */ + +#ifndef FUNCTION_fft12 +static inline void fft12(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 12, 3, 4, fft3, fft_4, RotVectorReal12, + RotVectorImag12); /* 16,58 */ +} +#endif /* #ifndef FUNCTION_fft12 */ + +#ifndef FUNCTION_fft20 +static inline void fft20(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 20, 4, 5, fft_4, fft5, RotVectorReal20, + RotVectorImag20); +} +#endif /* FUNCTION_fft20 */ + +static inline void fft24(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 24, 2, 12, fft2, fft12, RotVectorReal24, + RotVectorImag24); /* 16,73 */ +} + +static inline void fft48(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 48, 4, 12, fft_4, fft12, RotVectorReal48, + RotVectorImag48); /* 16,32 */ +} + +#ifndef FUNCTION_fft60 +static inline void fft60(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 60, 4, 15, fft_4, fft15, RotVectorReal60, + RotVectorImag60); /* 15,51 */ +} +#endif /* FUNCTION_fft60 */ + +#ifndef FUNCTION_fft80 +static inline void fft80(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 80, 5, 16, fft5, fft_16, RotVectorReal80, + RotVectorImag80); /* */ +} +#endif + +#ifndef FUNCTION_fft96 +static inline void fft96(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 96, 3, 32, fft3, fft_32, RotVectorReal96, + RotVectorImag96); /* 15,47 */ +} +#endif /* FUNCTION_fft96*/ + +#ifndef FUNCTION_fft120 +static inline void fft120(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 120, 8, 15, fft_8, fft15, RotVectorReal120, + RotVectorImag120); +} +#endif /* FUNCTION_fft120 */ + +#ifndef FUNCTION_fft192 +static inline void fft192(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 192, 16, 12, fft_16, fft12, RotVectorReal192, + RotVectorImag192); /* 15,50 */ +} +#endif + +#ifndef FUNCTION_fft240 +static inline void fft240(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 240, 16, 15, fft_16, fft15, RotVectorReal240, + RotVectorImag240); /* 15.44 */ +} +#endif + +#ifndef FUNCTION_fft384 +static inline void fft384(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 384, 12, 32, fft12, fft_32, RotVectorReal384, + RotVectorImag384); /* 16.02 */ +} +#endif /* FUNCTION_fft384 */ + +#ifndef FUNCTION_fft480 +static inline void fft480(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 480, 32, 15, fft_32, fft15, RotVectorReal480, + RotVectorImag480); /* 15.84 */ +} +#endif /* FUNCTION_fft480 */ + +void fft(int length, FIXP_DBL *pInput, INT *pScalefactor) { + /* Ensure, that the io-ptr is always (at least 8-byte) aligned */ + C_ALLOC_ALIGNED_CHECK(pInput); + + if (length == 32) { + fft_32(pInput); + *pScalefactor += SCALEFACTOR32; + } else { + switch (length) { + case 16: + fft_16(pInput); + *pScalefactor += SCALEFACTOR16; + break; + case 8: + fft_8(pInput); + *pScalefactor += SCALEFACTOR8; + break; + case 2: + fft2(pInput); + *pScalefactor += SCALEFACTOR2; + break; + case 3: + fft3(pInput); + *pScalefactor += SCALEFACTOR3; + break; + case 4: + fft_4(pInput); + *pScalefactor += SCALEFACTOR4; + break; + case 5: + fft5(pInput); + *pScalefactor += SCALEFACTOR5; + break; + case 6: + fft6(pInput); + *pScalefactor += SCALEFACTOR6; + break; + case 10: + fft10(pInput); + *pScalefactor += SCALEFACTOR10; + break; + case 12: + fft12(pInput); + *pScalefactor += SCALEFACTOR12; + break; + case 15: + fft15(pInput); + *pScalefactor += SCALEFACTOR15; + break; + case 20: + fft20(pInput); + *pScalefactor += SCALEFACTOR20; + break; + case 24: + fft24(pInput); + *pScalefactor += SCALEFACTOR24; + break; + case 48: + fft48(pInput); + *pScalefactor += SCALEFACTOR48; + break; + case 60: + fft60(pInput); + *pScalefactor += SCALEFACTOR60; + break; + case 64: + dit_fft(pInput, 6, SineTable512, 512); + *pScalefactor += SCALEFACTOR64; + break; + case 80: + fft80(pInput); + *pScalefactor += SCALEFACTOR80; + break; + case 96: + fft96(pInput); + *pScalefactor += SCALEFACTOR96; + break; + case 120: + fft120(pInput); + *pScalefactor += SCALEFACTOR120; + break; + case 128: + dit_fft(pInput, 7, SineTable512, 512); + *pScalefactor += SCALEFACTOR128; + break; + case 192: + fft192(pInput); + *pScalefactor += SCALEFACTOR192; + break; + case 240: + fft240(pInput); + *pScalefactor += SCALEFACTOR240; + break; + case 256: + dit_fft(pInput, 8, SineTable512, 512); + *pScalefactor += SCALEFACTOR256; + break; + case 384: + fft384(pInput); + *pScalefactor += SCALEFACTOR384; + break; + case 480: + fft480(pInput); + *pScalefactor += SCALEFACTOR480; + break; + case 512: + dit_fft(pInput, 9, SineTable512, 512); + *pScalefactor += SCALEFACTOR512; + break; + default: + FDK_ASSERT(0); /* FFT length not supported! */ + break; + } + } +} + +void ifft(int length, FIXP_DBL *pInput, INT *scalefactor) { + switch (length) { + default: + FDK_ASSERT(0); /* IFFT length not supported! */ + break; + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/fft_rad2.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/fft_rad2.cpp new file mode 100644 index 0000000000000..f457f8b570ad1 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/fft_rad2.cpp @@ -0,0 +1,324 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser, M. Gayer + + Description: + +*******************************************************************************/ + +#include "fft_rad2.h" + +#include "scramble.h" + +#define __FFT_RAD2_CPP__ + +#if defined(__arm__) +#include "arm/fft_rad2_arm.cpp" + +#elif defined(__GNUC__) && defined(__mips__) && defined(__mips_dsp) && !defined(__mips16) +#include "mips/fft_rad2_mips.cpp" + +#endif + +/***************************************************************************** + + functionname: dit_fft (analysis) + description: dit-tukey-algorithm + scrambles data at entry + i.e. loop is made with scrambled data + returns: + input: + output: + +*****************************************************************************/ + +#ifndef FUNCTION_dit_fft + +void dit_fft(FIXP_DBL *x, const INT ldn, const FIXP_STP *trigdata, + const INT trigDataSize) { + const INT n = 1 << ldn; + INT trigstep, i, ldm; + + C_ALLOC_ALIGNED_CHECK(x); + + scramble(x, n); + /* + * 1+2 stage radix 4 + */ + + for (i = 0; i < n * 2; i += 8) { + FIXP_DBL a00, a10, a20, a30; + a00 = (x[i + 0] + x[i + 2]) >> 1; /* Re A + Re B */ + a10 = (x[i + 4] + x[i + 6]) >> 1; /* Re C + Re D */ + a20 = (x[i + 1] + x[i + 3]) >> 1; /* Im A + Im B */ + a30 = (x[i + 5] + x[i + 7]) >> 1; /* Im C + Im D */ + + x[i + 0] = a00 + a10; /* Re A' = Re A + Re B + Re C + Re D */ + x[i + 4] = a00 - a10; /* Re C' = Re A + Re B - Re C - Re D */ + x[i + 1] = a20 + a30; /* Im A' = Im A + Im B + Im C + Im D */ + x[i + 5] = a20 - a30; /* Im C' = Im A + Im B - Im C - Im D */ + + a00 = a00 - x[i + 2]; /* Re A - Re B */ + a10 = a10 - x[i + 6]; /* Re C - Re D */ + a20 = a20 - x[i + 3]; /* Im A - Im B */ + a30 = a30 - x[i + 7]; /* Im C - Im D */ + + x[i + 2] = a00 + a30; /* Re B' = Re A - Re B + Im C - Im D */ + x[i + 6] = a00 - a30; /* Re D' = Re A - Re B - Im C + Im D */ + x[i + 3] = a20 - a10; /* Im B' = Im A - Im B - Re C + Re D */ + x[i + 7] = a20 + a10; /* Im D' = Im A - Im B + Re C - Re D */ + } + + for (ldm = 3; ldm <= ldn; ++ldm) { + INT m = (1 << ldm); + INT mh = (m >> 1); + INT j, r; + + trigstep = ((trigDataSize << 2) >> ldm); + + FDK_ASSERT(trigstep > 0); + + /* Do first iteration with c=1.0 and s=0.0 separately to avoid loosing to + much precision. Beware: The impact on the overal FFT precision is rather + large. */ + { /* block 1 */ + + j = 0; + + for (r = 0; r < n; r += m) { + INT t1 = (r + j) << 1; + INT t2 = t1 + (mh << 1); + FIXP_DBL vr, vi, ur, ui; + + // cplxMultDiv2(&vi, &vr, x[t2+1], x[t2], (FIXP_SGL)1.0, (FIXP_SGL)0.0); + vi = x[t2 + 1] >> 1; + vr = x[t2] >> 1; + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui + vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui - vi; + + t1 += mh; + t2 = t1 + (mh << 1); + + // cplxMultDiv2(&vr, &vi, x[t2+1], x[t2], (FIXP_SGL)1.0, (FIXP_SGL)0.0); + vr = x[t2 + 1] >> 1; + vi = x[t2] >> 1; + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui - vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui + vi; + } + + } /* end of block 1 */ + + for (j = 1; j < mh / 4; ++j) { + FIXP_STP cs; + + cs = trigdata[j * trigstep]; + + for (r = 0; r < n; r += m) { + INT t1 = (r + j) << 1; + INT t2 = t1 + (mh << 1); + FIXP_DBL vr, vi, ur, ui; + + cplxMultDiv2(&vi, &vr, x[t2 + 1], x[t2], cs); + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui + vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui - vi; + + t1 += mh; + t2 = t1 + (mh << 1); + + cplxMultDiv2(&vr, &vi, x[t2 + 1], x[t2], cs); + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui - vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui + vi; + + /* Same as above but for t1,t2 with j>mh/4 and thus cs swapped */ + t1 = (r + mh / 2 - j) << 1; + t2 = t1 + (mh << 1); + + cplxMultDiv2(&vi, &vr, x[t2], x[t2 + 1], cs); + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui - vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui + vi; + + t1 += mh; + t2 = t1 + (mh << 1); + + cplxMultDiv2(&vr, &vi, x[t2], x[t2 + 1], cs); + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur - vr; + x[t1 + 1] = ui - vi; + + x[t2] = ur + vr; + x[t2 + 1] = ui + vi; + } + } + + { /* block 2 */ + j = mh / 4; + + for (r = 0; r < n; r += m) { + INT t1 = (r + j) << 1; + INT t2 = t1 + (mh << 1); + FIXP_DBL vr, vi, ur, ui; + + cplxMultDiv2(&vi, &vr, x[t2 + 1], x[t2], STC(0x5a82799a), + STC(0x5a82799a)); + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui + vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui - vi; + + t1 += mh; + t2 = t1 + (mh << 1); + + cplxMultDiv2(&vr, &vi, x[t2 + 1], x[t2], STC(0x5a82799a), + STC(0x5a82799a)); + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui - vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui + vi; + } + } /* end of block 2 */ + } +} + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/fixpoint_math.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/fixpoint_math.cpp new file mode 100644 index 0000000000000..1e26420533027 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/fixpoint_math.cpp @@ -0,0 +1,906 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Gayer + + Description: Fixed point specific mathematical functions + +*******************************************************************************/ + +#include "fixpoint_math.h" + +/* + * Hardware specific implementations + */ + +/* + * Fallback implementations + */ + +/***************************************************************************** + functionname: LdDataVector +*****************************************************************************/ +LNK_SECTION_CODE_L1 +void LdDataVector(FIXP_DBL *srcVector, FIXP_DBL *destVector, INT n) { + INT i; + for (i = 0; i < n; i++) { + destVector[i] = fLog2(srcVector[i], 0); + } +} + +#define MAX_POW2_PRECISION 8 +#ifndef SINETABLE_16BIT +#define POW2_PRECISION MAX_POW2_PRECISION +#else +#define POW2_PRECISION 5 +#endif + +/* + Taylor series coefficients of the function x^2. The first coefficient is + ommited (equal to 1.0). + + pow2Coeff[i-1] = (1/i!) d^i(2^x)/dx^i, i=1..MAX_POW2_PRECISION + To evaluate the taylor series around x = 0, the coefficients are: 1/!i * + ln(2)^i + */ +#ifndef POW2COEFF_16BIT +RAM_ALIGN +LNK_SECTION_CONSTDATA_L1 +static const FIXP_DBL pow2Coeff[MAX_POW2_PRECISION] = { + FL2FXCONST_DBL(0.693147180559945309417232121458177), /* ln(2)^1 /1! */ + FL2FXCONST_DBL(0.240226506959100712333551263163332), /* ln(2)^2 /2! */ + FL2FXCONST_DBL(0.0555041086648215799531422637686218), /* ln(2)^3 /3! */ + FL2FXCONST_DBL(0.00961812910762847716197907157365887), /* ln(2)^4 /4! */ + FL2FXCONST_DBL(0.00133335581464284434234122219879962), /* ln(2)^5 /5! */ + FL2FXCONST_DBL(1.54035303933816099544370973327423e-4), /* ln(2)^6 /6! */ + FL2FXCONST_DBL(1.52527338040598402800254390120096e-5), /* ln(2)^7 /7! */ + FL2FXCONST_DBL(1.32154867901443094884037582282884e-6) /* ln(2)^8 /8! */ +}; +#else +RAM_ALIGN +LNK_SECTION_CONSTDATA_L1 +static const FIXP_SGL pow2Coeff[MAX_POW2_PRECISION] = { + FL2FXCONST_SGL(0.693147180559945309417232121458177), /* ln(2)^1 /1! */ + FL2FXCONST_SGL(0.240226506959100712333551263163332), /* ln(2)^2 /2! */ + FL2FXCONST_SGL(0.0555041086648215799531422637686218), /* ln(2)^3 /3! */ + FL2FXCONST_SGL(0.00961812910762847716197907157365887), /* ln(2)^4 /4! */ + FL2FXCONST_SGL(0.00133335581464284434234122219879962), /* ln(2)^5 /5! */ + FL2FXCONST_SGL(1.54035303933816099544370973327423e-4), /* ln(2)^6 /6! */ + FL2FXCONST_SGL(1.52527338040598402800254390120096e-5), /* ln(2)^7 /7! */ + FL2FXCONST_SGL(1.32154867901443094884037582282884e-6) /* ln(2)^8 /8! */ +}; +#endif + +/***************************************************************************** + + functionname: CalcInvLdData + description: Delivers the inverse of function CalcLdData(). + Delivers 2^(op*LD_DATA_SCALING) + input: Input op is assumed to be fractional -1.0 < op < 1.0 + output: For op == 0, the result is MAXVAL_DBL (almost 1.0). + For negative input values the output should be treated as a +positive fractional value. For positive input values the output should be +treated as a positive integer value. This function does not output negative +values. + +*****************************************************************************/ +/* Date: 06-JULY-2012 Arthur Tritthart, IIS Fraunhofer Erlangen */ +/* Version with 3 table lookup and 1 linear interpolations */ +/* Algorithm: compute power of 2, argument x is in Q7.25 format */ +/* result = 2^(x/64) */ +/* We split exponent (x/64) into 5 components: */ +/* integer part: represented by b31..b25 (exp) */ +/* fractional part 1: represented by b24..b20 (lookup1) */ +/* fractional part 2: represented by b19..b15 (lookup2) */ +/* fractional part 3: represented by b14..b10 (lookup3) */ +/* fractional part 4: represented by b09..b00 (frac) */ +/* => result = (lookup1*lookup2*(lookup3+C1*frac)<<3)>>exp */ +/* Due to the fact, that all lookup values contain a factor 0.5 */ +/* the result has to be shifted by 3 to the right also. */ +/* Table exp2_tab_long contains the log2 for 0 to 1.0 in steps */ +/* of 1/32, table exp2w_tab_long the log2 for 0 to 1/32 in steps*/ +/* of 1/1024, table exp2x_tab_long the log2 for 0 to 1/1024 in */ +/* steps of 1/32768. Since the 2-logarithm of very very small */ +/* negative value is rather linear, we can use interpolation. */ +/* Limitations: */ +/* For x <= 0, the result is fractional positive */ +/* For x > 0, the result is integer in range 1...7FFF.FFFF */ +/* For x < -31/64, we have to clear the result */ +/* For x = 0, the result is ~1.0 (0x7FFF.FFFF) */ +/* For x >= 31/64, the result is 0x7FFF.FFFF */ + +/* This table is used for lookup 2^x with */ +/* x in range [0...1.0[ in steps of 1/32 */ +LNK_SECTION_DATA_L1 +const UINT exp2_tab_long[32] = { + 0x40000000, 0x4166C34C, 0x42D561B4, 0x444C0740, 0x45CAE0F2, 0x47521CC6, + 0x48E1E9BA, 0x4A7A77D4, 0x4C1BF829, 0x4DC69CDD, 0x4F7A9930, 0x51382182, + 0x52FF6B55, 0x54D0AD5A, 0x56AC1F75, 0x5891FAC1, 0x5A82799A, 0x5C7DD7A4, + 0x5E8451D0, 0x60962665, 0x62B39509, 0x64DCDEC3, 0x6712460B, 0x69540EC9, + 0x6BA27E65, 0x6DFDDBCC, 0x70666F76, 0x72DC8374, 0x75606374, 0x77F25CCE, + 0x7A92BE8B, 0x7D41D96E + // 0x80000000 +}; + +/* This table is used for lookup 2^x with */ +/* x in range [0...1/32[ in steps of 1/1024 */ +LNK_SECTION_DATA_L1 +const UINT exp2w_tab_long[32] = { + 0x40000000, 0x400B1818, 0x4016321B, 0x40214E0C, 0x402C6BE9, 0x40378BB4, + 0x4042AD6D, 0x404DD113, 0x4058F6A8, 0x40641E2B, 0x406F479E, 0x407A7300, + 0x4085A051, 0x4090CF92, 0x409C00C4, 0x40A733E6, 0x40B268FA, 0x40BD9FFF, + 0x40C8D8F5, 0x40D413DD, 0x40DF50B8, 0x40EA8F86, 0x40F5D046, 0x410112FA, + 0x410C57A2, 0x41179E3D, 0x4122E6CD, 0x412E3152, 0x41397DCC, 0x4144CC3B, + 0x41501CA0, 0x415B6EFB, + // 0x4166C34C, +}; +/* This table is used for lookup 2^x with */ +/* x in range [0...1/1024[ in steps of 1/32768 */ +LNK_SECTION_DATA_L1 +const UINT exp2x_tab_long[32] = { + 0x40000000, 0x400058B9, 0x4000B173, 0x40010A2D, 0x400162E8, 0x4001BBA3, + 0x4002145F, 0x40026D1B, 0x4002C5D8, 0x40031E95, 0x40037752, 0x4003D011, + 0x400428CF, 0x4004818E, 0x4004DA4E, 0x4005330E, 0x40058BCE, 0x4005E48F, + 0x40063D51, 0x40069613, 0x4006EED5, 0x40074798, 0x4007A05B, 0x4007F91F, + 0x400851E4, 0x4008AAA8, 0x4009036E, 0x40095C33, 0x4009B4FA, 0x400A0DC0, + 0x400A6688, 0x400ABF4F, + // 0x400B1818 +}; + +/***************************************************************************** + functionname: InitLdInt and CalcLdInt + description: Create and access table with integer LdData (0 to +LD_INT_TAB_LEN) +*****************************************************************************/ +#ifndef LD_INT_TAB_LEN +#define LD_INT_TAB_LEN \ + 193 /* Default tab length. Lower value should be set in fix.h */ +#endif + +#if (LD_INT_TAB_LEN <= 120) +LNK_SECTION_CONSTDATA_L1 +static const FIXP_DBL ldIntCoeff[] = { + (FIXP_DBL)0x80000001, (FIXP_DBL)0x00000000, (FIXP_DBL)0x02000000, + (FIXP_DBL)0x032b8034, (FIXP_DBL)0x04000000, (FIXP_DBL)0x04a4d3c2, + (FIXP_DBL)0x052b8034, (FIXP_DBL)0x059d5da0, (FIXP_DBL)0x06000000, + (FIXP_DBL)0x06570069, (FIXP_DBL)0x06a4d3c2, (FIXP_DBL)0x06eb3a9f, + (FIXP_DBL)0x072b8034, (FIXP_DBL)0x0766a009, (FIXP_DBL)0x079d5da0, + (FIXP_DBL)0x07d053f7, (FIXP_DBL)0x08000000, (FIXP_DBL)0x082cc7ee, + (FIXP_DBL)0x08570069, (FIXP_DBL)0x087ef05b, (FIXP_DBL)0x08a4d3c2, + (FIXP_DBL)0x08c8ddd4, (FIXP_DBL)0x08eb3a9f, (FIXP_DBL)0x090c1050, + (FIXP_DBL)0x092b8034, (FIXP_DBL)0x0949a785, (FIXP_DBL)0x0966a009, + (FIXP_DBL)0x0982809d, (FIXP_DBL)0x099d5da0, (FIXP_DBL)0x09b74949, + (FIXP_DBL)0x09d053f7, (FIXP_DBL)0x09e88c6b, (FIXP_DBL)0x0a000000, + (FIXP_DBL)0x0a16bad3, (FIXP_DBL)0x0a2cc7ee, (FIXP_DBL)0x0a423162, + (FIXP_DBL)0x0a570069, (FIXP_DBL)0x0a6b3d79, (FIXP_DBL)0x0a7ef05b, + (FIXP_DBL)0x0a92203d, (FIXP_DBL)0x0aa4d3c2, (FIXP_DBL)0x0ab7110e, + (FIXP_DBL)0x0ac8ddd4, (FIXP_DBL)0x0ada3f60, (FIXP_DBL)0x0aeb3a9f, + (FIXP_DBL)0x0afbd42b, (FIXP_DBL)0x0b0c1050, (FIXP_DBL)0x0b1bf312, + (FIXP_DBL)0x0b2b8034, (FIXP_DBL)0x0b3abb40, (FIXP_DBL)0x0b49a785, + (FIXP_DBL)0x0b584822, (FIXP_DBL)0x0b66a009, (FIXP_DBL)0x0b74b1fd, + (FIXP_DBL)0x0b82809d, (FIXP_DBL)0x0b900e61, (FIXP_DBL)0x0b9d5da0, + (FIXP_DBL)0x0baa708f, (FIXP_DBL)0x0bb74949, (FIXP_DBL)0x0bc3e9ca, + (FIXP_DBL)0x0bd053f7, (FIXP_DBL)0x0bdc899b, (FIXP_DBL)0x0be88c6b, + (FIXP_DBL)0x0bf45e09, (FIXP_DBL)0x0c000000, (FIXP_DBL)0x0c0b73cb, + (FIXP_DBL)0x0c16bad3, (FIXP_DBL)0x0c21d671, (FIXP_DBL)0x0c2cc7ee, + (FIXP_DBL)0x0c379085, (FIXP_DBL)0x0c423162, (FIXP_DBL)0x0c4caba8, + (FIXP_DBL)0x0c570069, (FIXP_DBL)0x0c6130af, (FIXP_DBL)0x0c6b3d79, + (FIXP_DBL)0x0c7527b9, (FIXP_DBL)0x0c7ef05b, (FIXP_DBL)0x0c88983f, + (FIXP_DBL)0x0c92203d, (FIXP_DBL)0x0c9b8926, (FIXP_DBL)0x0ca4d3c2, + (FIXP_DBL)0x0cae00d2, (FIXP_DBL)0x0cb7110e, (FIXP_DBL)0x0cc0052b, + (FIXP_DBL)0x0cc8ddd4, (FIXP_DBL)0x0cd19bb0, (FIXP_DBL)0x0cda3f60, + (FIXP_DBL)0x0ce2c97d, (FIXP_DBL)0x0ceb3a9f, (FIXP_DBL)0x0cf39355, + (FIXP_DBL)0x0cfbd42b, (FIXP_DBL)0x0d03fda9, (FIXP_DBL)0x0d0c1050, + (FIXP_DBL)0x0d140ca0, (FIXP_DBL)0x0d1bf312, (FIXP_DBL)0x0d23c41d, + (FIXP_DBL)0x0d2b8034, (FIXP_DBL)0x0d3327c7, (FIXP_DBL)0x0d3abb40, + (FIXP_DBL)0x0d423b08, (FIXP_DBL)0x0d49a785, (FIXP_DBL)0x0d510118, + (FIXP_DBL)0x0d584822, (FIXP_DBL)0x0d5f7cff, (FIXP_DBL)0x0d66a009, + (FIXP_DBL)0x0d6db197, (FIXP_DBL)0x0d74b1fd, (FIXP_DBL)0x0d7ba190, + (FIXP_DBL)0x0d82809d, (FIXP_DBL)0x0d894f75, (FIXP_DBL)0x0d900e61, + (FIXP_DBL)0x0d96bdad, (FIXP_DBL)0x0d9d5da0, (FIXP_DBL)0x0da3ee7f, + (FIXP_DBL)0x0daa708f, (FIXP_DBL)0x0db0e412, (FIXP_DBL)0x0db74949, + (FIXP_DBL)0x0dbda072, (FIXP_DBL)0x0dc3e9ca, (FIXP_DBL)0x0dca258e}; + +#elif (LD_INT_TAB_LEN <= 193) +LNK_SECTION_CONSTDATA_L1 +static const FIXP_DBL ldIntCoeff[] = { + (FIXP_DBL)0x80000001, (FIXP_DBL)0x00000000, (FIXP_DBL)0x02000000, + (FIXP_DBL)0x032b8034, (FIXP_DBL)0x04000000, (FIXP_DBL)0x04a4d3c2, + (FIXP_DBL)0x052b8034, (FIXP_DBL)0x059d5da0, (FIXP_DBL)0x06000000, + (FIXP_DBL)0x06570069, (FIXP_DBL)0x06a4d3c2, (FIXP_DBL)0x06eb3a9f, + (FIXP_DBL)0x072b8034, (FIXP_DBL)0x0766a009, (FIXP_DBL)0x079d5da0, + (FIXP_DBL)0x07d053f7, (FIXP_DBL)0x08000000, (FIXP_DBL)0x082cc7ee, + (FIXP_DBL)0x08570069, (FIXP_DBL)0x087ef05b, (FIXP_DBL)0x08a4d3c2, + (FIXP_DBL)0x08c8ddd4, (FIXP_DBL)0x08eb3a9f, (FIXP_DBL)0x090c1050, + (FIXP_DBL)0x092b8034, (FIXP_DBL)0x0949a785, (FIXP_DBL)0x0966a009, + (FIXP_DBL)0x0982809d, (FIXP_DBL)0x099d5da0, (FIXP_DBL)0x09b74949, + (FIXP_DBL)0x09d053f7, (FIXP_DBL)0x09e88c6b, (FIXP_DBL)0x0a000000, + (FIXP_DBL)0x0a16bad3, (FIXP_DBL)0x0a2cc7ee, (FIXP_DBL)0x0a423162, + (FIXP_DBL)0x0a570069, (FIXP_DBL)0x0a6b3d79, (FIXP_DBL)0x0a7ef05b, + (FIXP_DBL)0x0a92203d, (FIXP_DBL)0x0aa4d3c2, (FIXP_DBL)0x0ab7110e, + (FIXP_DBL)0x0ac8ddd4, (FIXP_DBL)0x0ada3f60, (FIXP_DBL)0x0aeb3a9f, + (FIXP_DBL)0x0afbd42b, (FIXP_DBL)0x0b0c1050, (FIXP_DBL)0x0b1bf312, + (FIXP_DBL)0x0b2b8034, (FIXP_DBL)0x0b3abb40, (FIXP_DBL)0x0b49a785, + (FIXP_DBL)0x0b584822, (FIXP_DBL)0x0b66a009, (FIXP_DBL)0x0b74b1fd, + (FIXP_DBL)0x0b82809d, (FIXP_DBL)0x0b900e61, (FIXP_DBL)0x0b9d5da0, + (FIXP_DBL)0x0baa708f, (FIXP_DBL)0x0bb74949, (FIXP_DBL)0x0bc3e9ca, + (FIXP_DBL)0x0bd053f7, (FIXP_DBL)0x0bdc899b, (FIXP_DBL)0x0be88c6b, + (FIXP_DBL)0x0bf45e09, (FIXP_DBL)0x0c000000, (FIXP_DBL)0x0c0b73cb, + (FIXP_DBL)0x0c16bad3, (FIXP_DBL)0x0c21d671, (FIXP_DBL)0x0c2cc7ee, + (FIXP_DBL)0x0c379085, (FIXP_DBL)0x0c423162, (FIXP_DBL)0x0c4caba8, + (FIXP_DBL)0x0c570069, (FIXP_DBL)0x0c6130af, (FIXP_DBL)0x0c6b3d79, + (FIXP_DBL)0x0c7527b9, (FIXP_DBL)0x0c7ef05b, (FIXP_DBL)0x0c88983f, + (FIXP_DBL)0x0c92203d, (FIXP_DBL)0x0c9b8926, (FIXP_DBL)0x0ca4d3c2, + (FIXP_DBL)0x0cae00d2, (FIXP_DBL)0x0cb7110e, (FIXP_DBL)0x0cc0052b, + (FIXP_DBL)0x0cc8ddd4, (FIXP_DBL)0x0cd19bb0, (FIXP_DBL)0x0cda3f60, + (FIXP_DBL)0x0ce2c97d, (FIXP_DBL)0x0ceb3a9f, (FIXP_DBL)0x0cf39355, + (FIXP_DBL)0x0cfbd42b, (FIXP_DBL)0x0d03fda9, (FIXP_DBL)0x0d0c1050, + (FIXP_DBL)0x0d140ca0, (FIXP_DBL)0x0d1bf312, (FIXP_DBL)0x0d23c41d, + (FIXP_DBL)0x0d2b8034, (FIXP_DBL)0x0d3327c7, (FIXP_DBL)0x0d3abb40, + (FIXP_DBL)0x0d423b08, (FIXP_DBL)0x0d49a785, (FIXP_DBL)0x0d510118, + (FIXP_DBL)0x0d584822, (FIXP_DBL)0x0d5f7cff, (FIXP_DBL)0x0d66a009, + (FIXP_DBL)0x0d6db197, (FIXP_DBL)0x0d74b1fd, (FIXP_DBL)0x0d7ba190, + (FIXP_DBL)0x0d82809d, (FIXP_DBL)0x0d894f75, (FIXP_DBL)0x0d900e61, + (FIXP_DBL)0x0d96bdad, (FIXP_DBL)0x0d9d5da0, (FIXP_DBL)0x0da3ee7f, + (FIXP_DBL)0x0daa708f, (FIXP_DBL)0x0db0e412, (FIXP_DBL)0x0db74949, + (FIXP_DBL)0x0dbda072, (FIXP_DBL)0x0dc3e9ca, (FIXP_DBL)0x0dca258e, + (FIXP_DBL)0x0dd053f7, (FIXP_DBL)0x0dd6753e, (FIXP_DBL)0x0ddc899b, + (FIXP_DBL)0x0de29143, (FIXP_DBL)0x0de88c6b, (FIXP_DBL)0x0dee7b47, + (FIXP_DBL)0x0df45e09, (FIXP_DBL)0x0dfa34e1, (FIXP_DBL)0x0e000000, + (FIXP_DBL)0x0e05bf94, (FIXP_DBL)0x0e0b73cb, (FIXP_DBL)0x0e111cd2, + (FIXP_DBL)0x0e16bad3, (FIXP_DBL)0x0e1c4dfb, (FIXP_DBL)0x0e21d671, + (FIXP_DBL)0x0e275460, (FIXP_DBL)0x0e2cc7ee, (FIXP_DBL)0x0e323143, + (FIXP_DBL)0x0e379085, (FIXP_DBL)0x0e3ce5d8, (FIXP_DBL)0x0e423162, + (FIXP_DBL)0x0e477346, (FIXP_DBL)0x0e4caba8, (FIXP_DBL)0x0e51daa8, + (FIXP_DBL)0x0e570069, (FIXP_DBL)0x0e5c1d0b, (FIXP_DBL)0x0e6130af, + (FIXP_DBL)0x0e663b74, (FIXP_DBL)0x0e6b3d79, (FIXP_DBL)0x0e7036db, + (FIXP_DBL)0x0e7527b9, (FIXP_DBL)0x0e7a1030, (FIXP_DBL)0x0e7ef05b, + (FIXP_DBL)0x0e83c857, (FIXP_DBL)0x0e88983f, (FIXP_DBL)0x0e8d602e, + (FIXP_DBL)0x0e92203d, (FIXP_DBL)0x0e96d888, (FIXP_DBL)0x0e9b8926, + (FIXP_DBL)0x0ea03232, (FIXP_DBL)0x0ea4d3c2, (FIXP_DBL)0x0ea96df0, + (FIXP_DBL)0x0eae00d2, (FIXP_DBL)0x0eb28c7f, (FIXP_DBL)0x0eb7110e, + (FIXP_DBL)0x0ebb8e96, (FIXP_DBL)0x0ec0052b, (FIXP_DBL)0x0ec474e4, + (FIXP_DBL)0x0ec8ddd4, (FIXP_DBL)0x0ecd4012, (FIXP_DBL)0x0ed19bb0, + (FIXP_DBL)0x0ed5f0c4, (FIXP_DBL)0x0eda3f60, (FIXP_DBL)0x0ede8797, + (FIXP_DBL)0x0ee2c97d, (FIXP_DBL)0x0ee70525, (FIXP_DBL)0x0eeb3a9f, + (FIXP_DBL)0x0eef69ff, (FIXP_DBL)0x0ef39355, (FIXP_DBL)0x0ef7b6b4, + (FIXP_DBL)0x0efbd42b, (FIXP_DBL)0x0effebcd, (FIXP_DBL)0x0f03fda9, + (FIXP_DBL)0x0f0809cf, (FIXP_DBL)0x0f0c1050, (FIXP_DBL)0x0f10113b, + (FIXP_DBL)0x0f140ca0, (FIXP_DBL)0x0f18028d, (FIXP_DBL)0x0f1bf312, + (FIXP_DBL)0x0f1fde3d, (FIXP_DBL)0x0f23c41d, (FIXP_DBL)0x0f27a4c0, + (FIXP_DBL)0x0f2b8034}; + +#else +#error "ldInt table size too small" + +#endif + +LNK_SECTION_INITCODE +void InitLdInt() { /* nothing to do! Use preinitialized logarithm table */ +} + +#if (LD_INT_TAB_LEN != 0) + +LNK_SECTION_CODE_L1 +FIXP_DBL CalcLdInt(INT i) { + /* calculates ld(op)/LD_DATA_SCALING */ + /* op is assumed to be an integer value between 1 and LD_INT_TAB_LEN */ + + FDK_ASSERT((LD_INT_TAB_LEN > 0) && + ((FIXP_DBL)ldIntCoeff[0] == + (FIXP_DBL)0x80000001)); /* tab has to be initialized */ + + if ((i > 0) && (i < LD_INT_TAB_LEN)) + return ldIntCoeff[i]; + else { + return (0); + } +} +#endif /* (LD_INT_TAB_LEN!=0) */ + +#if !defined(FUNCTION_schur_div) +/***************************************************************************** + + functionname: schur_div + description: delivers op1/op2 with op3-bit accuracy + +*****************************************************************************/ + +FIXP_DBL schur_div(FIXP_DBL num, FIXP_DBL denum, INT count) { + INT L_num = (LONG)num >> 1; + INT L_denum = (LONG)denum >> 1; + INT div = 0; + INT k = count; + + FDK_ASSERT(num >= (FIXP_DBL)0); + FDK_ASSERT(denum > (FIXP_DBL)0); + FDK_ASSERT(num <= denum); + + if (L_num != 0) + while (--k) { + div <<= 1; + L_num <<= 1; + if (L_num >= L_denum) { + L_num -= L_denum; + div++; + } + } + return (FIXP_DBL)(div << (DFRACT_BITS - count)); +} + +#endif /* !defined(FUNCTION_schur_div) */ + +#ifndef FUNCTION_fMultNorm +FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2, INT *result_e) { + INT product = 0; + INT norm_f1, norm_f2; + + if ((f1 == (FIXP_DBL)0) || (f2 == (FIXP_DBL)0)) { + *result_e = 0; + return (FIXP_DBL)0; + } + norm_f1 = CountLeadingBits(f1); + f1 = f1 << norm_f1; + norm_f2 = CountLeadingBits(f2); + f2 = f2 << norm_f2; + + if ((f1 == (FIXP_DBL)MINVAL_DBL) && (f2 == (FIXP_DBL)MINVAL_DBL)) { + product = -((FIXP_DBL)MINVAL_DBL >> 1); + *result_e = -(norm_f1 + norm_f2 - 1); + } else { + product = fMult(f1, f2); + *result_e = -(norm_f1 + norm_f2); + } + + return (FIXP_DBL)product; +} +#endif + +#ifndef FUNCTION_fDivNorm +FIXP_DBL fDivNorm(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e) { + FIXP_DBL div; + INT norm_num, norm_den; + + FDK_ASSERT(L_num >= (FIXP_DBL)0); + FDK_ASSERT(L_denum > (FIXP_DBL)0); + + if (L_num == (FIXP_DBL)0) { + *result_e = 0; + return ((FIXP_DBL)0); + } + + norm_num = CountLeadingBits(L_num); + L_num = L_num << norm_num; + L_num = L_num >> 1; + *result_e = -norm_num + 1; + + norm_den = CountLeadingBits(L_denum); + L_denum = L_denum << norm_den; + *result_e -= -norm_den; + + div = schur_div(L_num, L_denum, FRACT_BITS); + + return div; +} +#endif /* !FUNCTION_fDivNorm */ + +#ifndef FUNCTION_fDivNorm +FIXP_DBL fDivNorm(FIXP_DBL num, FIXP_DBL denom) { + INT e; + FIXP_DBL res; + + FDK_ASSERT(denom >= num); + + res = fDivNorm(num, denom, &e); + + /* Avoid overflow since we must output a value with exponent 0 + there is no other choice than saturating to almost 1.0f */ + if (res == (FIXP_DBL)(1 << (DFRACT_BITS - 2)) && e == 1) { + res = (FIXP_DBL)MAXVAL_DBL; + } else { + res = scaleValue(res, e); + } + + return res; +} +#endif /* !FUNCTION_fDivNorm */ + +#ifndef FUNCTION_fDivNormSigned +FIXP_DBL fDivNormSigned(FIXP_DBL num, FIXP_DBL denom) { + INT e; + FIXP_DBL res; + int sign; + + if (denom == (FIXP_DBL)0) { + return (FIXP_DBL)MAXVAL_DBL; + } + + sign = ((num >= (FIXP_DBL)0) != (denom >= (FIXP_DBL)0)); + res = fDivNormSigned(num, denom, &e); + + /* Saturate since we must output a value with exponent 0 */ + if ((e > 0) && (fAbs(res) >= FL2FXCONST_DBL(0.5))) { + if (sign) { + res = (FIXP_DBL)MINVAL_DBL; + } else { + res = (FIXP_DBL)MAXVAL_DBL; + } + } else { + res = scaleValue(res, e); + } + + return res; +} +FIXP_DBL fDivNormSigned(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e) { + FIXP_DBL div; + INT norm_num, norm_den; + int sign; + + sign = ((L_num >= (FIXP_DBL)0) != (L_denum >= (FIXP_DBL)0)); + + if (L_num == (FIXP_DBL)0) { + *result_e = 0; + return ((FIXP_DBL)0); + } + if (L_denum == (FIXP_DBL)0) { + *result_e = 14; + return ((FIXP_DBL)MAXVAL_DBL); + } + + norm_num = CountLeadingBits(L_num); + L_num = L_num << norm_num; + L_num = L_num >> 2; + L_num = fAbs(L_num); + *result_e = -norm_num + 1; + + norm_den = CountLeadingBits(L_denum); + L_denum = L_denum << norm_den; + L_denum = L_denum >> 1; + L_denum = fAbs(L_denum); + *result_e -= -norm_den; + + div = schur_div(L_num, L_denum, FRACT_BITS); + + if (sign) { + div = -div; + } + + return div; +} +#endif /* FUNCTION_fDivNormSigned */ + +#ifndef FUNCTION_fDivNormHighPrec +FIXP_DBL fDivNormHighPrec(FIXP_DBL num, FIXP_DBL denom, INT *result_e) { + FIXP_DBL div; + INT norm_num, norm_den; + + FDK_ASSERT(num >= (FIXP_DBL)0); + FDK_ASSERT(denom > (FIXP_DBL)0); + + if (num == (FIXP_DBL)0) { + *result_e = 0; + return ((FIXP_DBL)0); + } + + norm_num = CountLeadingBits(num); + num = num << norm_num; + num = num >> 1; + *result_e = -norm_num + 1; + + norm_den = CountLeadingBits(denom); + denom = denom << norm_den; + *result_e -= -norm_den; + + div = schur_div(num, denom, 31); + return div; +} +#endif /* !FUNCTION_fDivNormHighPrec */ + +#ifndef FUNCTION_fPow +FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e, INT *result_e) { + FIXP_DBL frac_part, result_m; + INT int_part; + + if (exp_e > 0) { + INT exp_bits = DFRACT_BITS - 1 - exp_e; + int_part = exp_m >> exp_bits; + frac_part = exp_m - (FIXP_DBL)(int_part << exp_bits); + frac_part = frac_part << exp_e; + } else { + int_part = 0; + frac_part = exp_m >> -exp_e; + } + + /* Best accuracy is around 0, so try to get there with the fractional part. */ + if (frac_part > FL2FXCONST_DBL(0.5f)) { + int_part = int_part + 1; + frac_part = frac_part + FL2FXCONST_DBL(-1.0f); + } + if (frac_part < FL2FXCONST_DBL(-0.5f)) { + int_part = int_part - 1; + frac_part = -(FL2FXCONST_DBL(-1.0f) - frac_part); + } + + /* "+ 1" compensates fMultAddDiv2() of the polynomial evaluation below. */ + *result_e = int_part + 1; + + /* Evaluate taylor polynomial which approximates 2^x */ + { + FIXP_DBL p; + + /* result_m ~= 2^frac_part */ + p = frac_part; + /* First taylor series coefficient a_0 = 1.0, scaled by 0.5 due to + * fMultDiv2(). */ + result_m = FL2FXCONST_DBL(1.0f / 2.0f); + for (INT i = 0; i < POW2_PRECISION; i++) { + /* next taylor series term: a_i * x^i, x=0 */ + result_m = fMultAddDiv2(result_m, pow2Coeff[i], p); + p = fMult(p, frac_part); + } + } + return result_m; +} + +FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e) { + FIXP_DBL result_m; + INT result_e; + + result_m = f2Pow(exp_m, exp_e, &result_e); + result_e = fixMin(DFRACT_BITS - 1, fixMax(-(DFRACT_BITS - 1), result_e)); + + return scaleValue(result_m, result_e); +} + +FIXP_DBL fPow(FIXP_DBL base_m, INT base_e, FIXP_DBL exp_m, INT exp_e, + INT *result_e) { + INT ans_lg2_e, baselg2_e; + FIXP_DBL base_lg2, ans_lg2, result; + + if (base_m <= (FIXP_DBL)0) { + result = (FIXP_DBL)0; + *result_e = 0; + return result; + } + + /* Calc log2 of base */ + base_lg2 = fLog2(base_m, base_e, &baselg2_e); + + /* Prepare exp */ + { + INT leadingBits; + + leadingBits = CountLeadingBits(fAbs(exp_m)); + exp_m = exp_m << leadingBits; + exp_e -= leadingBits; + } + + /* Calc base pow exp */ + ans_lg2 = fMult(base_lg2, exp_m); + ans_lg2_e = exp_e + baselg2_e; + + /* Calc antilog */ + result = f2Pow(ans_lg2, ans_lg2_e, result_e); + + return result; +} + +FIXP_DBL fLdPow(FIXP_DBL baseLd_m, INT baseLd_e, FIXP_DBL exp_m, INT exp_e, + INT *result_e) { + INT ans_lg2_e; + FIXP_DBL ans_lg2, result; + + /* Prepare exp */ + { + INT leadingBits; + + leadingBits = CountLeadingBits(fAbs(exp_m)); + exp_m = exp_m << leadingBits; + exp_e -= leadingBits; + } + + /* Calc base pow exp */ + ans_lg2 = fMult(baseLd_m, exp_m); + ans_lg2_e = exp_e + baseLd_e; + + /* Calc antilog */ + result = f2Pow(ans_lg2, ans_lg2_e, result_e); + + return result; +} + +FIXP_DBL fLdPow(FIXP_DBL baseLd_m, INT baseLd_e, FIXP_DBL exp_m, INT exp_e) { + FIXP_DBL result_m; + int result_e; + + result_m = fLdPow(baseLd_m, baseLd_e, exp_m, exp_e, &result_e); + + return SATURATE_SHIFT(result_m, -result_e, DFRACT_BITS); +} + +FIXP_DBL fPowInt(FIXP_DBL base_m, INT base_e, INT exp, INT *pResult_e) { + FIXP_DBL result; + + if (exp != 0) { + INT result_e = 0; + + if (base_m != (FIXP_DBL)0) { + { + INT leadingBits; + leadingBits = CountLeadingBits(base_m); + base_m <<= leadingBits; + base_e -= leadingBits; + } + + result = base_m; + + { + int i; + for (i = 1; i < fAbs(exp); i++) { + result = fMult(result, base_m); + } + } + + if (exp < 0) { + /* 1.0 / ans */ + result = fDivNorm(FL2FXCONST_DBL(0.5f), result, &result_e); + result_e++; + } else { + int ansScale = CountLeadingBits(result); + result <<= ansScale; + result_e -= ansScale; + } + + result_e += exp * base_e; + + } else { + result = (FIXP_DBL)0; + } + *pResult_e = result_e; + } else { + result = FL2FXCONST_DBL(0.5f); + *pResult_e = 1; + } + + return result; +} +#endif /* FUNCTION_fPow */ + +#ifndef FUNCTION_fLog2 +FIXP_DBL CalcLog2(FIXP_DBL base_m, INT base_e, INT *result_e) { + return fLog2(base_m, base_e, result_e); +} +#endif /* FUNCTION_fLog2 */ + +INT fixp_floorToInt(FIXP_DBL f_inp, INT sf) { + FDK_ASSERT(sf >= 0); + INT floorInt = (INT)(f_inp >> ((DFRACT_BITS - 1) - sf)); + return floorInt; +} + +FIXP_DBL fixp_floor(FIXP_DBL f_inp, INT sf) { + FDK_ASSERT(sf >= 0); + INT floorInt = fixp_floorToInt(f_inp, sf); + FIXP_DBL f_floor = (FIXP_DBL)(floorInt << ((DFRACT_BITS - 1) - sf)); + return f_floor; +} + +INT fixp_ceilToInt(FIXP_DBL f_inp, INT sf) // sf mantissaBits left of dot +{ + FDK_ASSERT(sf >= 0); + INT sx = (DFRACT_BITS - 1) - sf; // sx mantissaBits right of dot + INT inpINT = (INT)f_inp; + + INT mask = (0x1 << sx) - 1; + INT ceilInt = (INT)(f_inp >> sx); + + if (inpINT & mask) { + ceilInt++; // increment only, if there is at least one set mantissaBit + // right of dot [in inpINT] + } + + return ceilInt; +} + +FIXP_DBL fixp_ceil(FIXP_DBL f_inp, INT sf) { + FDK_ASSERT(sf >= 0); + INT sx = (DFRACT_BITS - 1) - sf; + INT ceilInt = fixp_ceilToInt(f_inp, sf); + ULONG mask = (ULONG)0x1 << (DFRACT_BITS - 1); // 0x80000000 + ceilInt = ceilInt + << sx; // no fract warn bec. shift into saturation done on int side + + if ((f_inp > FL2FXCONST_DBL(0.0f)) && (ceilInt & mask)) { + --ceilInt; + } + FIXP_DBL f_ceil = (FIXP_DBL)ceilInt; + + return f_ceil; +} + +/***************************************************************************** + fixp_truncateToInt() + Just remove the fractional part which is located right of decimal point + Same as which is done when a float is casted to (INT) : + result_INTtype = (INT)b_floatTypeInput; + + returns INT +*****************************************************************************/ +INT fixp_truncateToInt(FIXP_DBL f_inp, INT sf) // sf mantissaBits left of dot + // (without sign) e.g. at width + // 32 this would be [sign]7. + // supposed sf equals 8. +{ + FDK_ASSERT(sf >= 0); + INT sx = (DFRACT_BITS - 1) - sf; // sx mantissaBits right of dot + // at width 32 this would be .24 + // supposed sf equals 8. + INT fbaccu = (INT)f_inp; + INT mask = (0x1 << sx); + + if ((fbaccu < 0) && (fbaccu & (mask - 1))) { + fbaccu = fbaccu + mask; + } + + fbaccu = fbaccu >> sx; + return fbaccu; +} + +/***************************************************************************** + fixp_truncate() + Just remove the fractional part which is located right of decimal point + + returns FIXP_DBL +*****************************************************************************/ +FIXP_DBL fixp_truncate(FIXP_DBL f_inp, INT sf) { + FDK_ASSERT(sf >= 0); + INT truncateInt = fixp_truncateToInt(f_inp, sf); + FIXP_DBL f_truncate = (FIXP_DBL)(truncateInt << ((DFRACT_BITS - 1) - sf)); + return f_truncate; +} + +/***************************************************************************** + fixp_roundToInt() + round [typical rounding] + + See fct roundRef() [which is the reference] + returns INT +*****************************************************************************/ +INT fixp_roundToInt(FIXP_DBL f_inp, INT sf) { + FDK_ASSERT(sf >= 0); + INT sx = DFRACT_BITS - 1 - sf; + INT inp = (INT)f_inp; + INT mask1 = (0x1 << (sx - 1)); + INT mask2 = (0x1 << (sx)) - 1; + INT mask3 = 0x7FFFFFFF; + INT iam = inp & mask2; + INT rnd; + + if ((inp < 0) && !(iam == mask1)) + rnd = inp + mask1; + else if ((inp > 0) && !(inp == mask3)) + rnd = inp + mask1; + else + rnd = inp; + + rnd = rnd >> sx; + + if (inp == mask3) rnd++; + + return rnd; +} + +/***************************************************************************** + fixp_round() + round [typical rounding] + + See fct roundRef() [which is the reference] + returns FIXP_DBL +*****************************************************************************/ +FIXP_DBL fixp_round(FIXP_DBL f_inp, INT sf) { + FDK_ASSERT(sf >= 0); + INT sx = DFRACT_BITS - 1 - sf; + INT r = fixp_roundToInt(f_inp, sf); + ULONG mask = (ULONG)0x1 << (DFRACT_BITS - 1); // 0x80000000 + r = r << sx; + + if ((f_inp > FL2FXCONST_DBL(0.0f)) && (r & mask)) { + --r; + } + + FIXP_DBL f_round = (FIXP_DBL)r; + return f_round; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/huff_nodes.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/huff_nodes.cpp new file mode 100644 index 0000000000000..66dc908c7b7e3 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/huff_nodes.cpp @@ -0,0 +1,1084 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Omer Osman + + Description: MPEG-D SAC/USAC/SAOC Huffman Part0 Tables + +*******************************************************************************/ + +#include "huff_nodes.h" + +const HUFF_PT0_NODES FDK_huffPart0Nodes = { + {{2, 1}, {4, 3}, {6, 5}, {8, 7}, {10, 9}, {12, 11}, + {14, 13}, {-8, 15}, {-9, 16}, {-10, 17}, {-18, 18}, {-17, -19}, + {-16, 19}, {-11, -20}, {-15, -21}, {-7, 20}, {-22, 21}, {-12, -14}, + {-13, -23}, {23, 22}, {-24, -31}, {-6, 24}, {-25, -26}, {26, 25}, + {-5, -27}, {-28, 27}, {-4, 28}, {-29, 29}, {-1, -30}, {-2, -3}}, + {{2, 1}, {-5, 3}, {-4, -6}, {-3, 4}, {-2, 5}, {-1, 6}, {-7, -8}}, + {{-1, 1}, {-8, 2}, {-2, 3}, {5, 4}, {-7, 6}, {-3, -5}, {-4, -6}}, + {{-1, 1}, + {3, 2}, + {-8, 4}, + {6, 5}, + {-16, 7}, + {9, 8}, + {11, 10}, + {-2, -7}, + {-6, 12}, + {-4, -5}, + {-3, 13}, + {-10, 14}, + {-11, -12}, + {-14, -15}, + {-9, -13}}, + {{2, 1}, {4, 3}, {6, 5}, {8, 7}, {10, 9}, {12, 11}, + {14, 13}, {16, 15}, {18, 17}, {20, 19}, {22, 21}, {24, 23}, + {26, 25}, {28, 27}, {30, 29}, {32, 31}, {-47, 33}, {-54, 34}, + {-46, 35}, {-48, 36}, {-23, -27}, {-45, 37}, {-55, 38}, {-22, -49}, + {-24, -53}, {-44, 39}, {-57, 40}, {-28, 41}, {-52, -56}, {-43, 42}, + {-50, 43}, {-25, -26}, {-29, -64}, {-62, 44}, {-21, -51}, {-58, 45}, + {-32, 46}, {-31, -42}, {-60, 47}, {-30, 48}, {-20, -61}, {-41, -63}, + {-19, -59}, {-40, 49}, {-18, -38}, {-39, 50}, {-36, -37}, {-35, 51}, + {-17, 52}, {-16, -34}, {-33, 53}, {-15, 54}, {-14, 55}, {-13, 56}, + {-12, 57}, {-11, 58}, {-10, 59}, {-9, 60}, {-7, 61}, {-1, -4}, + {-6, 62}, {-5, -8}, {-2, -3}}}; + +const HUFF_LAV_NODES FDK_huffLavIdxNodes = {{{-1, 1}, {-2, 2}, {-3, -4}}}; + +static const HUFF_ICC_NOD_1D FDK_huffICCNodes_h1D_0 = { + {{-1, 1}, {-2, 2}, {-3, 3}, {-4, 4}, {-5, 5}, {-6, 6}, {-7, -8}}}; + +static const HUFF_ICC_NOD_2D FDK_huffICCNodes_h2D_0_0 = { + {{-1, 1}, {-18, 2}, {-2, -17}}, + {{2, 1}, + {-1, -52}, + {-2, 3}, + {5, 4}, + {-51, 6}, + {-18, 7}, + {-17, 8}, + {-3, 9}, + {-36, 10}, + {-19, -50}, + {-35, 11}, + {-4, 12}, + {-34, 13}, + {-33, 14}, + {-20, -49}}, + {{2, 1}, {-86, 3}, {-1, 4}, {6, 5}, {-2, 7}, {-85, 8}, + {-18, 9}, {11, 10}, {-17, 12}, {14, 13}, {-70, 15}, {-3, -19}, + {-69, 16}, {-84, 17}, {-68, 18}, {-20, -35}, {-34, -83}, {20, 19}, + {-4, 21}, {-33, 22}, {-5, 23}, {-53, 24}, {-36, -52}, {-67, 25}, + {-21, -82}, {-54, 26}, {-6, 27}, {-51, 28}, {-50, 29}, {-49, 30}, + {-37, 31}, {-38, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{2, 1}, {4, 3}, {-1, -120}, {6, 5}, {8, 7}, {-18, 9}, + {-2, 10}, {12, 11}, {14, 13}, {-17, -119}, {16, 15}, {-103, 17}, + {-104, 18}, {-52, 19}, {21, 20}, {-69, 22}, {24, 23}, {-3, -35}, + {-19, 25}, {-34, -85}, {27, 26}, {-86, 28}, {-118, 29}, {-37, 30}, + {32, 31}, {-102, 33}, {-20, -22}, {-4, -117}, {-87, 34}, {-100, 35}, + {-33, -36}, {37, 36}, {-70, -88}, {-101, 38}, {-5, 39}, {-51, -53}, + {-50, 40}, {-115, 41}, {-21, 42}, {-116, 43}, {-38, 44}, {-23, -84}, + {-49, -99}, {46, 45}, {-6, -114}, {-7, -72}, {-71, 47}, {-8, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}; +static const HUFF_ICC_NOD_2D FDK_huffICCNodes_h2D_0_1 = { + {{-1, 1}, {-18, 2}, {-2, -17}}, + {{2, 1}, + {-1, -52}, + {-17, 3}, + {5, 4}, + {-36, 6}, + {-2, 7}, + {-18, -33}, + {9, 8}, + {-20, 10}, + {-34, -51}, + {-49, 11}, + {-35, 12}, + {-19, 13}, + {-3, 14}, + {-4, -50}}, + {{2, 1}, {-86, 3}, {-1, 4}, {-17, 5}, {7, 6}, {-70, 8}, + {-33, 9}, {-18, 10}, {-2, 11}, {-54, 12}, {-49, 13}, {-38, 14}, + {-34, -65}, {-85, 15}, {-50, 16}, {-69, 17}, {-22, 18}, {-53, 19}, + {21, 20}, {-19, -81}, {-66, 22}, {-3, -35}, {24, 23}, {-37, 25}, + {-68, -84}, {-51, 26}, {28, 27}, {-20, -52}, {30, 29}, {-4, -36}, + {-83, 31}, {-67, 32}, {-82, 33}, {-21, 34}, {-5, -6}}, + {{2, 1}, {-1, 3}, {-120, 4}, {-17, 5}, {7, 6}, {-104, 8}, + {-33, 9}, {11, 10}, {13, 12}, {-49, 14}, {-88, 15}, {-18, -97}, + {-65, 16}, {-40, 17}, {-2, -72}, {19, 18}, {-113, 20}, {-34, 21}, + {-56, -81}, {23, 22}, {-50, 24}, {-82, -119}, {-24, -103}, {26, 25}, + {28, 27}, {30, 29}, {-55, -87}, {-66, 31}, {33, 32}, {-98, 34}, + {-35, -67}, {-19, 35}, {-70, 36}, {-71, 37}, {-51, -52}, {-3, 38}, + {40, 39}, {-86, -118}, {42, 41}, {-39, -69}, {-54, -83}, {44, 43}, + {-102, 45}, {-101, 46}, {-68, -85}, {-36, -53}, {-5, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}; +static const HUFF_ICC_NOD_2D FDK_huffICCNodes_h2D_1_0 = { + {{-1, 1}, {-18, 2}, {-2, -17}}, + {{-52, 1}, + {-1, 2}, + {4, 3}, + {-2, -17}, + {-18, 5}, + {-36, 6}, + {-51, 7}, + {9, 8}, + {-33, 10}, + {-34, 11}, + {-35, 12}, + {-19, -20}, + {-3, 13}, + {-49, 14}, + {-4, -50}}, + {{-1, 1}, {-86, 2}, {4, 3}, {-17, 5}, {-2, 6}, {-18, 7}, + {-70, 8}, {-85, 9}, {11, 10}, {13, 12}, {-33, 14}, {16, 15}, + {-34, -54}, {-69, 17}, {-38, 18}, {-50, 19}, {-35, -53}, {-49, 20}, + {-19, 21}, {-3, 22}, {-65, 23}, {-68, 24}, {-22, 25}, {-81, -84}, + {-66, 26}, {-37, 27}, {-20, -51}, {29, 28}, {-52, 30}, {-4, -83}, + {-36, 31}, {-67, 32}, {-5, 33}, {-82, 34}, {-21, 0}}, + {{-1, 1}, {-120, 2}, {4, 3}, {-17, 5}, {-2, 6}, {8, 7}, + {-18, 9}, {-104, 10}, {12, 11}, {14, 13}, {16, 15}, {-119, 17}, + {-81, 18}, {20, 19}, {-33, 21}, {-88, 22}, {-103, 23}, {-34, 24}, + {-56, 25}, {-72, 26}, {-49, 27}, {-82, 28}, {-50, 29}, {-65, 30}, + {-55, -87}, {-19, 31}, {-67, 32}, {-35, -40}, {34, 33}, {-52, -71}, + {-66, 35}, {-70, 36}, {38, 37}, {-51, -97}, {-86, -102}, {-3, 39}, + {-118, 40}, {42, 41}, {-24, -85}, {-54, 43}, {-39, 44}, {-98, -113}, + {-36, -37}, {-20, -69}, {-4, 45}, {-5, 46}, {-21, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}; +static const HUFF_ICC_NOD_2D FDK_huffICCNodes_h2D_1_1 = { + {{-1, 1}, {-18, 2}, {-2, -17}}, + {{-52, 1}, + {-1, 2}, + {4, 3}, + {-2, 5}, + {-17, -18}, + {-51, 6}, + {-36, 7}, + {9, 8}, + {-35, 10}, + {-3, 11}, + {-19, -34}, + {-33, 12}, + {-50, 13}, + {-20, 14}, + {-4, -49}}, + {{2, 1}, {-86, 3}, {-1, 4}, {6, 5}, {-18, 7}, {-2, -17}, + {9, 8}, {-70, 10}, {-69, -85}, {-35, 11}, {13, 12}, {-34, 14}, + {-19, 15}, {-53, 16}, {-68, 17}, {-33, 18}, {-3, -52}, {20, 19}, + {-54, 21}, {-84, 22}, {-50, 23}, {-20, -51}, {-36, 24}, {26, 25}, + {-83, 27}, {-4, -38}, {-49, 28}, {-37, 29}, {-67, 30}, {-5, 31}, + {-21, 32}, {-65, -66}, {-82, 33}, {-22, 34}, {-6, -81}}, + {{2, 1}, {-1, -120}, {4, 3}, {6, 5}, {-18, 7}, {9, 8}, + {-17, 10}, {-2, 11}, {-103, 12}, {-52, 13}, {-35, -104}, {-119, 14}, + {16, 15}, {-69, -86}, {18, 17}, {-34, 19}, {-19, 20}, {22, 21}, + {-70, 23}, {-87, 24}, {-102, 25}, {-85, 26}, {-33, 27}, {-36, 28}, + {-3, 29}, {-88, 30}, {-51, 31}, {-118, 32}, {34, 33}, {-68, 35}, + {-53, 36}, {-67, 37}, {-20, 38}, {-101, 39}, {-50, 40}, {42, 41}, + {-37, 43}, {-116, 44}, {-117, 45}, {-49, 46}, {-21, -100}, {48, 47}, + {-55, -71}, {-4, 49}, {-22, -84}, {-115, 50}, {-66, -82}, {-72, 51}, + {-5, -6}, {-54, 52}, {-38, 53}, {-83, 54}, {-40, 55}, {-39, 56}, + {-99, 57}, {-23, -56}, {-7, 58}, {-65, -97}, {-8, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}; + +const HUFF_ICC_NODES FDK_huffICCNodes = { + {&FDK_huffICCNodes_h1D_0, &FDK_huffICCNodes_h1D_0, &FDK_huffICCNodes_h1D_0}, + {{&FDK_huffICCNodes_h2D_0_0, &FDK_huffICCNodes_h2D_0_1}, + {&FDK_huffICCNodes_h2D_1_0, &FDK_huffICCNodes_h2D_1_1}, + {&FDK_huffICCNodes_h2D_0_1, &FDK_huffICCNodes_h2D_0_1}}}; + +static const HUFF_CLD_NOD_1D FDK_huffCLDNodes_h1D_0 = { + {{-1, 1}, {-2, 2}, {-3, 3}, {-4, 4}, {-5, 5}, {-6, 6}, + {-7, 7}, {-8, 8}, {-9, 9}, {-10, 10}, {-11, 11}, {-12, 12}, + {-13, 13}, {15, 14}, {-14, 16}, {-15, 17}, {-16, 18}, {-17, 19}, + {-18, 20}, {-19, 21}, {-20, -21}, {-23, 22}, {-22, 23}, {-24, 24}, + {-25, 25}, {27, 26}, {29, 28}, {-30, -31}, {-28, -29}, {-26, -27}}}; +static const HUFF_CLD_NOD_1D FDK_huffCLDNodes_h1D_1 = { + {{-1, 1}, {-2, 2}, {-3, 3}, {-4, 4}, {-5, 5}, {-6, 6}, + {-7, 7}, {9, 8}, {-8, 10}, {-9, 11}, {-10, 12}, {-11, 13}, + {-12, 14}, {-13, 15}, {-14, 16}, {-15, 17}, {-16, 18}, {-17, 19}, + {-18, 20}, {-19, -20}, {-21, 21}, {-22, 22}, {-23, 23}, {25, 24}, + {-24, 26}, {-25, 27}, {29, 28}, {-26, -31}, {-29, -30}, {-27, -28}}}; + +static const HUFF_CLD_NOD_2D FDK_huffCLDNodes_h2_0_0 = { + {{2, 1}, + {-1, -52}, + {4, 3}, + {-2, 5}, + {-51, 6}, + {-17, -18}, + {8, 7}, + {10, 9}, + {-3, -36}, + {-19, 11}, + {-35, -50}, + {-34, 12}, + {-4, 13}, + {-33, 14}, + {-20, -49}}, + {{2, 1}, {4, 3}, {-86, 5}, {7, 6}, {9, 8}, {-1, -2}, + {-85, 10}, {-18, 11}, {-17, 12}, {14, 13}, {-70, 15}, {17, 16}, + {-19, -69}, {-84, 18}, {-3, 19}, {21, 20}, {-34, -68}, {-20, 22}, + {-35, 23}, {-83, 24}, {-33, 25}, {-4, 26}, {-53, 27}, {-54, -67}, + {-36, 28}, {-21, -52}, {-82, 29}, {-5, -50}, {-51, 30}, {-38, 31}, + {-37, -49}, {-6, 32}, {-66, 33}, {-65, 34}, {-22, -81}}, + {{2, 1}, {4, 3}, {-120, 5}, {7, 6}, {9, 8}, {11, 10}, + {-1, 12}, {-18, -119}, {-2, 13}, {15, 14}, {-17, 16}, {-104, 17}, + {19, 18}, {-19, 20}, {-103, 21}, {-118, 22}, {24, 23}, {-3, 25}, + {27, 26}, {-34, 28}, {-102, 29}, {-20, 30}, {-35, 31}, {33, 32}, + {-117, 34}, {-33, 35}, {-88, 36}, {-4, 37}, {-87, 38}, {40, 39}, + {-36, -101}, {-86, 41}, {-21, -37}, {-85, -100}, {-52, 42}, {-22, 43}, + {-116, 44}, {-50, 45}, {47, 46}, {-5, -51}, {-115, 48}, {-70, 49}, + {-84, 50}, {-38, -49}, {-72, -99}, {-53, 51}, {-69, -71}, {-23, 52}, + {-6, -67}, {-114, 53}, {-7, 54}, {-66, -68}, {-55, 55}, {57, 56}, + {-54, -65}, {-8, -56}, {-82, -83}, {59, 58}, {-39, -40}, {-81, 60}, + {-98, 61}, {-97, 62}, {-24, -113}}, + {{2, 1}, {4, 3}, {6, 5}, {-154, 7}, {9, 8}, + {11, 10}, {13, 12}, {15, 14}, {-18, 16}, {-153, 17}, + {-1, -2}, {19, 18}, {-138, 20}, {-17, 21}, {23, 22}, + {25, 24}, {-19, -137}, {27, 26}, {-152, 28}, {30, 29}, + {-3, -34}, {32, 31}, {34, 33}, {36, 35}, {-136, 37}, + {-35, 38}, {-20, 39}, {-122, 40}, {-151, 41}, {-33, 42}, + {-121, 43}, {45, 44}, {47, 46}, {-4, 48}, {-36, -120}, + {-135, 49}, {51, 50}, {-21, 52}, {54, 53}, {56, 55}, + {-50, -150}, {58, 57}, {-51, 59}, {61, 60}, {-119, 62}, + {-52, 63}, {-5, 64}, {-37, 65}, {-117, -134}, {-39, -54}, + {-22, 66}, {-106, 67}, {-69, -102}, {-132, 68}, {-105, 69}, + {-49, 70}, {-149, 71}, {-24, -104}, {73, 72}, {-53, 74}, + {-38, -118}, {-103, 75}, {-6, 76}, {-66, -87}, {-133, -147}, + {-23, 77}, {-67, 78}, {-68, -86}, {-70, -101}, {-40, -148}, + {-116, 79}, {-55, 80}, {-84, -131}, {82, 81}, {-89, -90}, + {-7, -25}, {-85, -88}, {-65, 83}, {-72, -146}, {85, 84}, + {-9, -71}, {-83, 86}, {-82, 87}, {-8, 88}, {-100, 89}, + {-74, -99}, {-73, 90}, {-10, -81}, {-56, 91}, {-57, -98}, + {93, 92}, {-58, -114}, {-97, -115}, {95, 94}, {-41, 96}, + {-42, 97}, {-26, -129}, {-113, 98}, {-130, -145}}}; +static const HUFF_CLD_NOD_2D FDK_huffCLDNodes_h2_0_1 = { + {{-1, 1}, + {-52, 2}, + {-17, 3}, + {5, 4}, + {-36, 6}, + {-33, 7}, + {-2, -18}, + {-20, 8}, + {10, 9}, + {-34, -49}, + {-51, 11}, + {-35, 12}, + {-19, 13}, + {-3, 14}, + {-4, -50}}, + {{2, 1}, {4, 3}, {-86, 5}, {-1, 6}, {-17, 7}, {-70, 8}, + {10, 9}, {-18, 11}, {-33, 12}, {-54, 13}, {-2, 14}, {-34, 15}, + {-38, 16}, {-49, 17}, {-85, 18}, {-50, 19}, {-69, 20}, {-53, -65}, + {-22, 21}, {-66, 22}, {-19, 23}, {-37, 24}, {-35, -81}, {-3, 25}, + {-51, 26}, {-68, -84}, {-52, 27}, {29, 28}, {-20, 30}, {-4, -36}, + {-83, 31}, {-67, 32}, {-21, 33}, {-5, 34}, {-6, -82}}, + {{2, 1}, {4, 3}, {6, 5}, {-120, 7}, {-17, 8}, {-1, -104}, + {10, 9}, {12, 11}, {-18, 13}, {-33, -88}, {15, 14}, {17, 16}, + {-2, 18}, {-34, 19}, {-72, 20}, {-49, 21}, {-119, 22}, {-50, 23}, + {-103, 24}, {-56, 25}, {-65, 26}, {28, 27}, {-40, -87}, {-66, 29}, + {-82, 30}, {32, 31}, {-19, -81}, {-71, 33}, {-97, 34}, {-35, -55}, + {-24, 35}, {37, 36}, {-3, -98}, {-51, 38}, {-67, 39}, {-39, -118}, + {-113, 40}, {-102, 41}, {-86, 42}, {-70, -83}, {44, 43}, {-20, -54}, + {-52, 45}, {-36, 46}, {-4, 47}, {-68, 48}, {-85, 49}, {-101, -117}, + {-69, 50}, {52, 51}, {-21, -37}, {-53, 53}, {55, 54}, {-5, -100}, + {-116, 56}, {-84, 57}, {-38, 58}, {-22, -99}, {-115, 59}, {-6, 60}, + {-23, 61}, {-7, 62}, {-114, 0}}, + {{2, 1}, {4, 3}, {6, 5}, {-154, 7}, {9, 8}, + {-17, 10}, {-138, 11}, {-1, 12}, {14, 13}, {16, 15}, + {-33, -122}, {-18, 17}, {19, 18}, {-34, 20}, {-2, 21}, + {-106, 22}, {-49, 23}, {25, 24}, {-50, 26}, {-153, 27}, + {-90, 28}, {-137, 29}, {-65, 30}, {32, 31}, {-66, 33}, + {-121, 34}, {-74, 35}, {-81, 36}, {38, 37}, {-42, 39}, + {-82, 40}, {-105, 41}, {-19, -114}, {-58, 42}, {-35, 43}, + {-97, 44}, {46, 45}, {-129, 47}, {-26, -89}, {-57, -98}, + {-51, 48}, {-3, 49}, {-113, 50}, {-130, 51}, {-152, 52}, + {-67, -73}, {-99, -136}, {-145, 53}, {-120, 54}, {-41, 55}, + {-83, 56}, {-72, 57}, {-104, 58}, {-115, 59}, {-20, 60}, + {62, 61}, {-36, -88}, {-84, 63}, {-52, -56}, {65, 64}, + {-4, -87}, {-68, 66}, {-151, 67}, {-100, -135}, {69, 68}, + {-69, -119}, {-103, 70}, {-71, 71}, {73, 72}, {-21, 74}, + {-85, 75}, {-37, -53}, {-86, 76}, {78, 77}, {-102, -150}, + {-5, 79}, {-134, 80}, {-118, 81}, {-54, -117}, {83, 82}, + {-38, -70}, {-22, 84}, {-6, 85}, {87, 86}, {-55, 88}, + {-101, 89}, {-133, -149}, {-24, -39}, {91, 90}, {-132, 92}, + {-23, 93}, {-7, 94}, {-147, -148}, {-116, -131}, {-25, 95}, + {-40, 0}, {0, 0}, {0, 0}, {0, 0}}}; +static const HUFF_CLD_NOD_2D FDK_huffCLDNodes_h2_1_0 = { + {{-1, 1}, + {-52, 2}, + {-17, 3}, + {5, 4}, + {-2, -36}, + {-18, 6}, + {8, 7}, + {-51, 9}, + {-33, 10}, + {-34, 11}, + {-20, -35}, + {-19, 12}, + {-3, 13}, + {-49, 14}, + {-4, -50}}, + {{2, 1}, {-86, 3}, {-1, 4}, {-17, 5}, {7, 6}, {-70, 8}, + {-2, -18}, {10, 9}, {12, 11}, {-85, 13}, {-33, 14}, {-34, -54}, + {16, 15}, {-69, 17}, {19, 18}, {-50, -53}, {-19, 20}, {-38, 21}, + {-35, -49}, {-3, 22}, {24, 23}, {-68, 25}, {-84, 26}, {-65, 27}, + {-51, -66}, {-22, -37}, {-52, 28}, {-20, 29}, {-36, 30}, {-81, 31}, + {-4, -83}, {-67, 32}, {-21, 33}, {-5, 34}, {-6, -82}}, + {{2, 1}, {-120, 3}, {-1, 4}, {6, 5}, {-17, 7}, {-104, 8}, + {-18, 9}, {-2, 10}, {12, 11}, {14, 13}, {-119, 15}, {-33, 16}, + {-34, -88}, {-103, 17}, {19, 18}, {21, 20}, {23, 22}, {25, 24}, + {-19, -72}, {-50, 26}, {-49, 27}, {-87, 28}, {30, 29}, {32, 31}, + {-3, -35}, {34, 33}, {-56, 35}, {-65, -66}, {-40, 36}, {-82, -118}, + {-71, 37}, {-55, 38}, {-67, -102}, {-51, 39}, {-70, 40}, {42, 41}, + {-81, 43}, {-86, 44}, {-52, -97}, {-98, 45}, {-24, -39}, {-20, 46}, + {-54, -83}, {-36, 47}, {-85, 48}, {-68, 49}, {-4, 50}, {-69, -113}, + {-117, 51}, {-37, -101}, {-53, 52}, {-21, 53}, {55, 54}, {-84, -100}, + {-5, 56}, {-116, 57}, {-22, 58}, {-38, -115}, {60, 59}, {-6, -99}, + {-23, 61}, {-114, 62}, {-7, -8}}, + {{2, 1}, {-154, 3}, {5, 4}, {-1, 6}, {8, 7}, + {-17, 9}, {-138, 10}, {-18, 11}, {-2, 12}, {14, 13}, + {16, 15}, {-153, 17}, {-34, 18}, {-33, -122}, {20, 19}, + {22, 21}, {-137, 23}, {25, 24}, {27, 26}, {-106, 28}, + {30, 29}, {-50, 31}, {-19, 32}, {-49, -121}, {34, 33}, + {36, 35}, {-35, 37}, {-90, 38}, {-66, 39}, {-3, 40}, + {42, 41}, {-65, 43}, {-105, 44}, {46, 45}, {-74, 47}, + {-51, 48}, {-82, -152}, {-136, 49}, {-81, 50}, {-42, -89}, + {-114, 51}, {53, 52}, {-57, -58}, {-120, 54}, {-98, 55}, + {-67, 56}, {-97, 57}, {59, 58}, {-99, 60}, {-73, -104}, + {-72, 61}, {-113, 62}, {-20, -83}, {-84, -130}, {-36, 63}, + {-26, 64}, {-41, 65}, {-52, -129}, {-87, -88}, {67, 66}, + {-115, 68}, {-68, 69}, {-56, -69}, {-4, -100}, {-151, 70}, + {-135, 71}, {-103, -119}, {73, 72}, {-71, -145}, {-102, 74}, + {76, 75}, {-53, -85}, {-37, 77}, {-21, -86}, {79, 78}, + {-5, 80}, {-54, -134}, {-150, 81}, {-118, 82}, {-70, 83}, + {-117, 84}, {-22, -38}, {-101, 85}, {-55, 86}, {-149, 87}, + {-39, 88}, {-133, 89}, {-6, 90}, {-116, 91}, {-24, 92}, + {-7, -132}, {-23, 93}, {-40, 94}, {-131, -148}, {-25, 95}, + {-147, 96}, {-146, 97}, {-8, 0}, {0, 0}}}; +static const HUFF_CLD_NOD_2D FDK_huffCLDNodes_h2_1_1 = { + {{-1, 1}, + {-52, 2}, + {4, 3}, + {-2, 5}, + {-17, 6}, + {-18, 7}, + {-36, -51}, + {9, 8}, + {-35, 10}, + {-34, 11}, + {-19, -33}, + {-3, 12}, + {-20, 13}, + {-50, 14}, + {-4, -49}}, + {{2, 1}, {-86, 3}, {5, 4}, {-1, 6}, {8, 7}, {-17, -18}, + {-2, 9}, {-70, 10}, {-85, 11}, {13, 12}, {-69, 14}, {-34, 15}, + {17, 16}, {-19, 18}, {-33, -35}, {-54, 19}, {-53, 20}, {-3, 21}, + {-68, 22}, {-84, 23}, {-50, 24}, {-52, 25}, {-51, 26}, {-20, -36}, + {-49, 27}, {-38, 28}, {-37, 29}, {-4, -83}, {-67, 30}, {-66, 31}, + {-21, 32}, {-22, -65}, {-5, 33}, {-82, 34}, {-6, -81}}, + {{2, 1}, {4, 3}, {-120, 5}, {7, 6}, {9, 8}, {-1, 10}, + {-18, 11}, {-17, 12}, {-2, -104}, {-119, 13}, {15, 14}, {-103, 16}, + {18, 17}, {-34, 19}, {-19, 20}, {22, 21}, {-35, 23}, {-33, 24}, + {-88, 25}, {-87, 26}, {28, 27}, {-3, -102}, {-86, 29}, {-52, -118}, + {31, 30}, {-50, 32}, {-51, 33}, {-70, 34}, {-36, 35}, {-85, 36}, + {-20, 37}, {39, 38}, {-69, -71}, {-72, 40}, {-49, -67}, {42, 41}, + {-68, 43}, {-4, -101}, {-53, -117}, {-37, 44}, {-66, 45}, {-55, 46}, + {48, 47}, {-54, 49}, {-21, 50}, {-84, -100}, {-56, -65}, {52, 51}, + {-82, -83}, {54, 53}, {-5, -116}, {-22, 55}, {-38, 56}, {-39, -40}, + {58, 57}, {-81, -115}, {-98, -99}, {-6, 59}, {-23, 60}, {-24, 61}, + {-7, -97}, {-114, 62}, {-8, -113}}, + {{2, 1}, {4, 3}, {-154, 5}, {7, 6}, {9, 8}, + {11, 10}, {-1, 12}, {-18, 13}, {-17, 14}, {-2, -138}, + {16, 15}, {-153, 17}, {-137, 18}, {20, 19}, {22, 21}, + {-34, 23}, {-19, 24}, {-35, 25}, {27, 26}, {29, 28}, + {-121, 30}, {-120, 31}, {-136, 32}, {-33, -122}, {34, 33}, + {-152, 35}, {-3, 36}, {-51, 37}, {-52, 38}, {-69, 39}, + {-36, 40}, {-50, 41}, {43, 42}, {-20, 44}, {-104, 45}, + {-103, 46}, {-87, 47}, {-119, 48}, {-105, 49}, {-86, 50}, + {-102, 51}, {-106, 52}, {-49, -135}, {-68, 53}, {55, 54}, + {-53, 56}, {-67, -151}, {-4, 57}, {-84, 58}, {-85, 59}, + {-66, 60}, {-37, 61}, {-70, 62}, {-54, -88}, {-21, 63}, + {65, 64}, {-89, 66}, {-118, 67}, {-72, 68}, {-90, 69}, + {-71, 70}, {-65, -134}, {-150, 71}, {-83, 72}, {-5, 73}, + {-101, -117}, {-82, 74}, {76, 75}, {-99, 77}, {-38, 78}, + {-100, 79}, {-22, 80}, {-73, 81}, {-39, -74}, {83, 82}, + {-55, -81}, {-57, 84}, {-133, -149}, {-56, 85}, {-6, 86}, + {-98, 87}, {-132, 88}, {-23, 89}, {-114, 90}, {-116, 91}, + {-58, -115}, {-24, 92}, {-97, -148}, {-40, -41}, {-7, -42}, + {-147, 93}, {95, 94}, {-131, 96}, {-8, -130}, {-25, -113}, + {-9, 97}, {-26, -129}, {-146, 98}, {-10, -145}}}; + +const HUFF_CLD_NODES FDK_huffCLDNodes = { + {&FDK_huffCLDNodes_h1D_0, &FDK_huffCLDNodes_h1D_1, &FDK_huffCLDNodes_h1D_1}, + {{&FDK_huffCLDNodes_h2_0_0, &FDK_huffCLDNodes_h2_0_1}, + {&FDK_huffCLDNodes_h2_1_0, &FDK_huffCLDNodes_h2_1_1}, + {&FDK_huffCLDNodes_h2_0_1, &FDK_huffCLDNodes_h2_0_1}}}; + +const HUFF_RES_NODES FDK_huffReshapeNodes = { + {{2, 1}, {4, 3}, {6, 5}, {-33, 7}, {-17, 8}, {-49, 9}, + {-34, 10}, {12, 11}, {-18, -35}, {-50, 13}, {15, 14}, {-40, 16}, + {-36, 17}, {-19, 18}, {-1, -37}, {-51, 19}, {21, 20}, {-38, -65}, + {-2, -39}, {-20, 22}, {-52, 23}, {25, 24}, {-21, 26}, {-66, 27}, + {-53, 28}, {-3, 29}, {31, 30}, {-22, 32}, {-54, 33}, {-4, 34}, + {-56, 35}, {-24, -67}, {-23, -55}, {-8, -72}, {-5, 36}, {-68, 37}, + {-6, 38}, {-7, -69}, {-70, -71}}}; + +const HUFF_IPD_NODES FDK_huffIPDNodes = { + {{{{-1, 1}, {-8, 2}, {-2, 3}, {5, 4}, {-3, -7}, {-6, 6}, {-4, -5}}}, + {{{-1, 1}, {-2, 2}, {-8, 3}, {-3, 4}, {-7, 5}, {-4, 6}, {-5, -6}}}, + {{{-1, 1}, {-8, 2}, {-2, 3}, {5, 4}, {-3, -7}, {-6, 6}, {-4, -5}}}}, + {{{{{-1, 1}, {-18, 2}, {-17, 0}}, + {{-1, 1}, + {-36, 2}, + {-18, 3}, + {-35, 4}, + {-52, 5}, + {7, 6}, + {-34, 8}, + {-33, -49}, + {-20, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}, + {{-1, 1}, {3, 2}, {5, 4}, {-86, 6}, {-66, 7}, {9, 8}, + {11, 10}, {-18, 12}, {-51, 13}, {-37, -52}, {-69, 14}, {-38, 15}, + {-53, 16}, {-35, 17}, {-50, -70}, {-22, -49}, {-33, 18}, {-17, 19}, + {-34, -65}, {-81, 20}, {-54, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{2, 1}, {4, 3}, {-1, 5}, {-69, 6}, {-120, 7}, {-68, 8}, + {10, 9}, {12, 11}, {14, 13}, {-52, -54}, {-18, 15}, {-70, 16}, + {-67, 17}, {19, 18}, {-17, 20}, {-113, 21}, {23, 22}, {-83, 24}, + {-24, 25}, {-103, -104}, {-51, -55}, {27, 26}, {-71, 28}, {-86, 29}, + {-35, 30}, {-66, 31}, {-39, -50}, {-82, -98}, {-72, 32}, {-56, -87}, + {-34, 33}, {-33, -88}, {-40, -97}, {-65, 34}, {-49, 35}, {-81, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}, + {{{-1, 1}, {-18, 2}, {-17, 0}}, + {{-1, 1}, + {-36, 2}, + {-18, 3}, + {-35, 4}, + {-52, 5}, + {7, 6}, + {-34, 8}, + {-33, -49}, + {-20, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}, + {{-1, 1}, {3, 2}, {5, 4}, {-86, 6}, {-66, 7}, {9, 8}, + {11, 10}, {-18, 12}, {-51, 13}, {-37, -52}, {-69, 14}, {-38, 15}, + {-53, 16}, {-35, 17}, {-50, -70}, {-22, -49}, {-33, 18}, {-17, 19}, + {-34, -65}, {-81, 20}, {-54, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{2, 1}, {4, 3}, {-1, 5}, {-69, 6}, {-120, 7}, {-68, 8}, + {10, 9}, {12, 11}, {14, 13}, {-52, -54}, {-18, 15}, {-70, 16}, + {-67, 17}, {19, 18}, {-17, 20}, {-113, 21}, {23, 22}, {-83, 24}, + {-24, 25}, {-103, -104}, {-51, -55}, {27, 26}, {-71, 28}, {-86, 29}, + {-35, 30}, {-66, 31}, {-39, -50}, {-82, -98}, {-72, 32}, {-56, -87}, + {-34, 33}, {-33, -88}, {-40, -97}, {-65, 34}, {-49, 35}, {-81, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}}, + {{{{-1, 1}, {-18, 2}, {-17, 0}}, + {{-1, 1}, + {3, 2}, + {-18, 4}, + {-52, 5}, + {-34, -36}, + {-35, 6}, + {-17, 7}, + {-33, 8}, + {-20, 9}, + {-49, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}, + {{-1, 1}, {3, 2}, {-52, 4}, {-86, 5}, {-35, 6}, {-53, 7}, + {-70, 8}, {-17, 9}, {-37, 10}, {12, 11}, {-38, -66}, {-18, 13}, + {-51, 14}, {16, 15}, {-34, -69}, {18, 17}, {-54, -65}, {-50, 19}, + {-33, -49}, {-22, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{-1, 1}, {-69, 2}, {4, 3}, {-120, 5}, {7, 6}, {-113, 8}, + {-68, 9}, {11, 10}, {-17, 12}, {-52, 13}, {-24, 14}, {-18, 15}, + {17, 16}, {-104, 18}, {20, 19}, {-54, -70}, {22, 21}, {24, 23}, + {-86, -97}, {-103, 25}, {-83, 26}, {-35, 27}, {-34, -98}, {-40, 28}, + {-39, -67}, {30, 29}, {-33, -51}, {-87, 31}, {-88, 32}, {-82, 33}, + {-55, -81}, {-56, -71}, {-72, 34}, {-50, -66}, {-65, 35}, {-49, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}, + {{{-1, 1}, {-18, 2}, {-17, 0}}, + {{-1, 1}, + {3, 2}, + {-18, 4}, + {-52, 5}, + {-34, -36}, + {-35, 6}, + {-17, 7}, + {-33, 8}, + {-20, 9}, + {-49, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}, + {{-1, 1}, {3, 2}, {-52, 4}, {-86, 5}, {-35, 6}, {-53, 7}, + {-70, 8}, {-17, 9}, {-37, 10}, {12, 11}, {-38, -66}, {-18, 13}, + {-51, 14}, {16, 15}, {-34, -69}, {18, 17}, {-54, -65}, {-50, 19}, + {-33, -49}, {-22, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{-1, 1}, {-69, 2}, {4, 3}, {-120, 5}, {7, 6}, {-113, 8}, + {-68, 9}, {11, 10}, {-17, 12}, {-52, 13}, {-24, 14}, {-18, 15}, + {17, 16}, {-104, 18}, {20, 19}, {-54, -70}, {22, 21}, {24, 23}, + {-86, -97}, {-103, 25}, {-83, 26}, {-35, 27}, {-34, -98}, {-40, 28}, + {-39, -67}, {30, 29}, {-33, -51}, {-87, 31}, {-88, 32}, {-82, 33}, + {-55, -81}, {-56, -71}, {-72, 34}, {-50, -66}, {-65, 35}, {-49, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}}, + {{{{-1, 1}, {-18, 2}, {-17, 0}}, + {{-1, 1}, + {-36, 2}, + {-18, 3}, + {-35, 4}, + {-52, 5}, + {7, 6}, + {-34, 8}, + {-33, -49}, + {-20, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}, + {{-1, 1}, {3, 2}, {5, 4}, {-86, 6}, {-66, 7}, {9, 8}, + {11, 10}, {-18, 12}, {-51, 13}, {-37, -52}, {-69, 14}, {-38, 15}, + {-53, 16}, {-35, 17}, {-50, -70}, {-22, -49}, {-33, 18}, {-17, 19}, + {-34, -65}, {-81, 20}, {-54, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{2, 1}, {4, 3}, {-1, 5}, {-69, 6}, {-120, 7}, {-68, 8}, + {10, 9}, {12, 11}, {14, 13}, {-52, -54}, {-18, 15}, {-70, 16}, + {-67, 17}, {19, 18}, {-17, 20}, {-113, 21}, {23, 22}, {-83, 24}, + {-24, 25}, {-103, -104}, {-51, -55}, {27, 26}, {-71, 28}, {-86, 29}, + {-35, 30}, {-66, 31}, {-39, -50}, {-82, -98}, {-72, 32}, {-56, -87}, + {-34, 33}, {-33, -88}, {-40, -97}, {-65, 34}, {-49, 35}, {-81, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}, + {{{-1, 1}, {-18, 2}, {-17, 0}}, + {{-1, 1}, + {-36, 2}, + {-18, 3}, + {-35, 4}, + {-52, 5}, + {7, 6}, + {-34, 8}, + {-33, -49}, + {-20, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}, + {{-1, 1}, {3, 2}, {5, 4}, {-86, 6}, {-66, 7}, {9, 8}, + {11, 10}, {-18, 12}, {-51, 13}, {-37, -52}, {-69, 14}, {-38, 15}, + {-53, 16}, {-35, 17}, {-50, -70}, {-22, -49}, {-33, 18}, {-17, 19}, + {-34, -65}, {-81, 20}, {-54, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{2, 1}, {4, 3}, {-1, 5}, {-69, 6}, {-120, 7}, {-68, 8}, + {10, 9}, {12, 11}, {14, 13}, {-52, -54}, {-18, 15}, {-70, 16}, + {-67, 17}, {19, 18}, {-17, 20}, {-113, 21}, {23, 22}, {-83, 24}, + {-24, 25}, {-103, -104}, {-51, -55}, {27, 26}, {-71, 28}, {-86, 29}, + {-35, 30}, {-66, 31}, {-39, -50}, {-82, -98}, {-72, 32}, {-56, -87}, + {-34, 33}, {-33, -88}, {-40, -97}, {-65, 34}, {-49, 35}, {-81, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}}}}; + +static const HUFF_OLD_NOD_1D huffOLDNodes_h1D_0 = {{{-1, 1}, + {3, 2}, + {-2, 4}, + {-3, 5}, + {-4, 6}, + {-5, 7}, + {-6, -8}, + {-7, 8}, + {10, 9}, + {12, 11}, + {-9, -11}, + {-10, 13}, + {-12, 14}, + {-13, -16}, + {-14, -15}}}; + +static const HUFF_OLD_NOD_1D huffOLDNodes_h1D_1 = {{{-1, 1}, + {-2, 2}, + {4, 3}, + {-3, 5}, + {-4, 6}, + {-5, 7}, + {-6, -8}, + {-7, 8}, + {10, 9}, + {12, 11}, + {-9, 13}, + {-16, 14}, + {-10, -15}, + {-11, -12}, + {-13, -14}}}; + +static const HUFF_OLD_NOD_2D huffOLDNodes_h2D_0_0 = { + {{2, 1}, + {-1, 3}, + {5, 4}, + {-2, 6}, + {-3, -4}, + {-17, 7}, + {-18, 8}, + {-19, 9}, + {-20, 10}, + {-52, 11}, + {-33, 12}, + {-34, -35}, + {-36, 13}, + {-51, 14}, + {-49, -50}}, + {{-1, 1}, {3, 2}, {5, 4}, {7, 6}, {-103, 8}, {10, 9}, + {12, 11}, {-18, 13}, {15, 14}, {-2, 16}, {-86, 17}, {-35, 18}, + {20, 19}, {-102, 21}, {23, 22}, {-69, 24}, {-87, 25}, {-3, 26}, + {-17, 27}, {-19, 28}, {-52, 29}, {-34, -101}, {31, 30}, {-85, 32}, + {34, 33}, {-20, -70}, {-4, 35}, {-71, -100}, {-5, -33}, {-50, 36}, + {-36, -55}, {-54, -84}, {38, 37}, {-51, -53}, {-21, 39}, {-6, -99}, + {-37, -68}, {-83, 40}, {-7, -49}, {-22, -98}, {42, 41}, {44, 43}, + {-66, 45}, {-67, 46}, {-38, -39}, {-65, -82}, {-23, 47}, {-81, -97}}, + {{-1, 1}, {3, 2}, {5, 4}, {7, 6}, {9, 8}, + {11, 10}, {13, 12}, {15, 14}, {-154, 16}, {-103, 17}, + {19, 18}, {21, 20}, {-18, 22}, {24, 23}, {26, 25}, + {28, 27}, {-137, 29}, {31, 30}, {-2, -51}, {33, 32}, + {-35, 34}, {-26, 35}, {37, 36}, {-8, 38}, {-70, -153}, + {40, 39}, {-120, 41}, {-52, 42}, {44, 43}, {-3, -138}, + {46, 45}, {48, 47}, {-34, 49}, {-7, 50}, {-19, 51}, + {-17, 52}, {-152, 53}, {-4, -151}, {-33, 54}, {-106, 55}, + {-53, -122}, {-105, -136}, {-121, 56}, {-104, 57}, {-50, -118}, + {-20, 58}, {-5, 59}, {-38, 60}, {-133, 61}, {-148, 62}, + {-23, -135}, {-36, 63}, {-6, 64}, {66, 65}, {-21, -150}, + {68, 67}, {-49, 69}, {-134, 70}, {-119, 71}, {-37, 72}, + {-149, 73}, {-9, 74}, {-69, 75}, {-86, 76}, {-22, 77}, + {-68, 78}, {80, 79}, {82, 81}, {84, 83}, {-88, 85}, + {-132, 86}, {-90, 87}, {-10, -117}, {-67, 88}, {-71, 89}, + {-87, 90}, {-54, -66}, {-25, 91}, {-89, 92}, {-72, 93}, + {-131, 94}, {-113, -115}, {-99, 95}, {-73, -116}, {-24, -85}, + {-84, -102}, {-39, 96}, {-55, -98}, {-81, -97}, {-82, -83}, + {-114, 97}, {-146, -147}, {-42, -101}, {-57, -100}, {-65, -130}, + {-74, 98}, {-56, -58}, {-40, -129}, {-41, -145}}, + {{2, 1}, {4, 3}, {6, 5}, {8, 7}, {10, 9}, + {12, 11}, {-4, 13}, {-11, -28}, {-21, 14}, {-1, 15}, + {17, 16}, {19, 18}, {-38, 20}, {22, 21}, {24, 23}, + {26, 25}, {28, 27}, {-54, 29}, {31, 30}, {-44, 32}, + {-45, 33}, {-37, 34}, {-5, 35}, {-27, 36}, {38, 37}, + {40, 39}, {-53, 41}, {-12, 42}, {-22, 43}, {-20, 44}, + {-36, 45}, {-43, 46}, {-6, 47}, {-205, 48}, {-51, -52}, + {-35, 49}, {-34, 50}, {-13, 51}, {-42, 52}, {-29, 53}, + {-18, -41}, {55, 54}, {-17, -26}, {-19, 56}, {-7, 57}, + {-23, -188}, {59, 58}, {-10, 60}, {62, 61}, {-39, 63}, + {-33, 64}, {-2, 65}, {-204, 66}, {68, 67}, {-189, 69}, + {-171, 70}, {72, 71}, {74, 73}, {-203, 75}, {-3, -25}, + {-24, 76}, {78, 77}, {80, 79}, {82, 81}, {-173, 83}, + {-172, -187}, {85, 84}, {-86, 86}, {-50, 87}, {-202, 88}, + {90, 89}, {-154, 91}, {93, 92}, {-120, 94}, {96, 95}, + {-186, 97}, {99, 98}, {-69, 100}, {-156, -157}, {102, 101}, + {104, 103}, {-170, -201}, {-103, 105}, {107, 106}, {-155, 108}, + {-137, 109}, {-185, 110}, {-49, 111}, {-8, 112}, {-66, 113}, + {-67, 114}, {116, 115}, {-169, 117}, {-141, 118}, {120, 119}, + {122, 121}, {-200, 123}, {-68, -121}, {125, 124}, {-136, 126}, + {-140, 127}, {-71, 128}, {-139, 129}, {-151, -184}, {-82, 130}, + {-56, -101}, {132, 131}, {-9, -153}, {-40, 133}, {-138, 134}, + {-83, -199}, {-84, 135}, {-90, -168}, {-65, -91}, {-102, 136}, + {-135, -166}, {-72, -183}, {-87, -150}, {-181, 137}, {-125, 138}, + {-55, -70}, {-85, -152}, {-106, -124}, {-89, -123}, {-198, 139}, + {-57, 140}, {-105, 141}, {-167, -196}, {-81, -122}, {-182, 142}, + {-99, -180}, {-100, -104}, {-116, -165}, {-98, 143}, {-117, -119}, + {-88, -134}, {-197, 144}, {-73, -195}, {-92, -149}, {-118, -164}, + {-58, -108}, {-107, -179}, {-109, 145}, {-93, -97}, {-115, -194}, + {-114, 146}, {-113, 147}, {149, 148}, {151, 150}, {153, 152}, + {155, 154}, {157, 156}, {159, 158}, {161, 160}, {163, 162}, + {165, 164}, {167, 166}, {-178, -193}, {-163, -177}, {-161, -162}, + {-147, -148}, {-145, -146}, {-132, -133}, {-130, -131}, {-77, -129}, + {-75, -76}, {-61, -74}, {-59, -60}}}; + +static const HUFF_OLD_NOD_2D huffOLDNodes_h2D_0_1 = { + {{-1, 1}, + {3, 2}, + {5, 4}, + {-52, 6}, + {-49, 7}, + {9, 8}, + {-17, 10}, + {-36, 11}, + {-18, 12}, + {-2, -3}, + {-35, 13}, + {-34, -50}, + {-4, -33}, + {-20, 14}, + {-19, -51}}, + {{-1, 1}, {3, 2}, {-103, 4}, {6, 5}, {8, 7}, {-18, 9}, + {11, 10}, {-87, 12}, {-17, 13}, {15, 14}, {-86, 16}, {18, 17}, + {-71, 19}, {21, 20}, {-33, -35}, {-34, 22}, {-55, 23}, {-2, 24}, + {-50, -102}, {26, 25}, {-49, 27}, {-69, -70}, {-39, 28}, {-65, 29}, + {-66, 30}, {-54, 31}, {-19, 32}, {-23, -52}, {-51, 33}, {-81, 34}, + {-82, 35}, {-3, -38}, {-85, -101}, {-67, -97}, {37, 36}, {-20, -53}, + {-36, 38}, {40, 39}, {-100, 41}, {-4, -84}, {-68, 42}, {-21, 43}, + {-37, 44}, {-99, 45}, {-5, -83}, {-22, 46}, {-98, 47}, {-6, -7}}, + {{-1, 1}, {3, 2}, {5, 4}, {7, 6}, {9, 8}, + {-154, 10}, {12, 11}, {14, 13}, {-18, 15}, {17, 16}, + {19, 18}, {21, 20}, {-17, 22}, {-137, 23}, {-35, 24}, + {-138, 25}, {27, 26}, {-113, 28}, {-34, 29}, {31, 30}, + {33, 32}, {-122, 34}, {-33, 35}, {-73, 36}, {38, 37}, + {40, 39}, {-106, 41}, {-52, 42}, {-58, -120}, {-50, 43}, + {45, 44}, {-49, 46}, {-10, -103}, {-36, 47}, {-54, -90}, + {-53, 48}, {-2, 49}, {-98, -153}, {-121, 50}, {-66, 51}, + {-65, -72}, {-51, 52}, {-74, 53}, {-9, 54}, {-105, 55}, + {-71, -82}, {-19, -55}, {-81, 56}, {58, 57}, {-83, 59}, + {-68, -88}, {-89, -97}, {-70, 60}, {-3, 61}, {-67, 62}, + {64, 63}, {-69, 65}, {-104, 66}, {-136, -152}, {68, 67}, + {-8, -26}, {-37, 69}, {-4, 70}, {72, 71}, {-22, 73}, + {-42, 74}, {-7, -20}, {76, 75}, {78, 77}, {-6, 79}, + {-114, 80}, {-25, -135}, {-119, -151}, {-24, 81}, {-57, 82}, + {-5, 83}, {-99, 84}, {-23, -130}, {-129, 85}, {-118, 86}, + {-21, -41}, {-86, 87}, {-115, -145}, {-84, 88}, {-87, -150}, + {-38, -56}, {-134, 89}, {-100, 90}, {-85, -133}, {-149, 91}, + {-102, 92}, {-117, -148}, {94, 93}, {-39, 95}, {-101, 96}, + {-116, 97}, {-131, -132}, {-40, 98}, {-146, -147}}, + {{2, 1}, {-1, 3}, {5, 4}, {7, 6}, {9, 8}, + {-205, 10}, {12, 11}, {14, 13}, {16, 15}, {-18, 17}, + {19, 18}, {21, 20}, {23, 22}, {-189, 24}, {-188, 25}, + {27, 26}, {-17, 28}, {-173, 29}, {31, 30}, {33, 32}, + {-34, -157}, {-35, 34}, {-33, 35}, {37, 36}, {39, 38}, + {41, 40}, {-50, 42}, {-49, 43}, {-141, 44}, {-204, 45}, + {-2, -171}, {-172, 46}, {-66, 47}, {49, 48}, {51, 50}, + {-65, 52}, {-125, 53}, {-156, 54}, {-82, 55}, {57, 56}, + {59, 58}, {-19, -52}, {61, 60}, {-81, 62}, {64, 63}, + {-109, -140}, {-51, 65}, {67, 66}, {-98, 68}, {70, 69}, + {72, 71}, {-67, -93}, {74, 73}, {-203, 75}, {-154, 76}, + {-124, 77}, {-97, -187}, {-114, 78}, {-61, 79}, {-155, 80}, + {82, 81}, {-113, 83}, {-3, -146}, {-83, 84}, {-108, 85}, + {-20, 86}, {-76, 87}, {-45, -77}, {-139, 88}, {90, 89}, + {-69, -130}, {-129, 91}, {-36, 92}, {-99, -161}, {94, 93}, + {-92, -162}, {-68, 95}, {-29, 96}, {-86, 97}, {-60, 98}, + {-123, -177}, {-145, 99}, {-91, -131}, {101, 100}, {-137, -178}, + {-115, 102}, {-84, -116}, {-147, 103}, {-4, 104}, {-106, -202}, + {106, 105}, {-132, -186}, {-107, 107}, {-193, 108}, {-100, -120}, + {-75, -170}, {-44, 109}, {-122, -163}, {-138, 110}, {-90, 111}, + {-37, 112}, {-101, 113}, {-121, 114}, {116, 115}, {-103, 117}, + {-74, -201}, {-21, -85}, {-53, -59}, {-117, 118}, {-148, 119}, + {-5, 120}, {-169, 121}, {-105, -185}, {123, 122}, {-102, -133}, + {-136, 124}, {-153, 125}, {127, 126}, {-54, 128}, {130, 129}, + {-22, -104}, {-38, 131}, {-89, -118}, {-184, 132}, {-71, 133}, + {-87, 134}, {-70, 135}, {-200, 136}, {-168, 137}, {-152, 138}, + {-6, -23}, {-39, 139}, {-119, -199}, {141, 140}, {-55, 142}, + {-7, -151}, {-183, 143}, {145, 144}, {-135, 146}, {-56, 147}, + {-150, 148}, {-40, 149}, {-72, -198}, {-88, 150}, {-57, -134}, + {-41, 151}, {-166, -167}, {-25, -165}, {-9, 152}, {-8, -24}, + {-73, -181}, {-182, 153}, {155, 154}, {-197, 156}, {-42, -180}, + {158, 157}, {-43, -149}, {-196, 159}, {-58, -164}, {-26, 160}, + {162, 161}, {164, 163}, {166, 165}, {-195, 167}, {-179, -194}, + {-27, -28}, {-12, -13}, {-10, -11}}}; + +static const HUFF_OLD_NOD_2D huffOLDNodes_h2D_1_0 = { + {{-1, 1}, + {-52, 2}, + {4, 3}, + {-18, 5}, + {7, 6}, + {-17, 8}, + {-36, 9}, + {-35, 10}, + {-2, 11}, + {-19, 12}, + {-33, -51}, + {-20, -34}, + {14, 13}, + {-3, -49}, + {-4, -50}}, + {{-1, 1}, {3, 2}, {5, 4}, {-103, 6}, {8, 7}, {-18, 9}, + {11, 10}, {13, 12}, {-86, 14}, {-87, 15}, {17, 16}, {-35, 18}, + {-17, 19}, {21, 20}, {-34, -71}, {23, 22}, {-50, -55}, {-33, 24}, + {-69, 25}, {-2, -70}, {27, 26}, {-102, 28}, {-49, 29}, {-66, 30}, + {-39, -54}, {-52, 31}, {-51, 32}, {-65, 33}, {-19, 34}, {-38, -82}, + {-23, -85}, {-67, 35}, {-81, 36}, {-3, 37}, {-53, -101}, {-20, -97}, + {39, 38}, {-36, 40}, {-84, 41}, {-100, 42}, {-4, -68}, {-21, 43}, + {-37, 44}, {-83, 45}, {-5, -99}, {-22, 46}, {-98, 47}, {-6, -7}}, + {{-1, 1}, {3, 2}, {5, 4}, {7, 6}, {9, 8}, + {-154, 10}, {12, 11}, {14, 13}, {-18, 15}, {17, 16}, + {-113, 18}, {20, 19}, {-137, 21}, {23, 22}, {25, 24}, + {27, 26}, {-35, 28}, {-138, 29}, {-58, 30}, {-103, 31}, + {-98, 32}, {34, 33}, {-122, 35}, {-120, 36}, {-17, -73}, + {-34, 37}, {-106, 38}, {-50, 39}, {-83, -90}, {-74, 40}, + {-52, 41}, {-66, -121}, {-33, -88}, {43, 42}, {-82, -105}, + {-49, 44}, {-68, -153}, {-2, -89}, {-51, -65}, {-67, 45}, + {-81, -97}, {47, 46}, {-104, 48}, {-19, 49}, {51, 50}, + {53, 52}, {55, 54}, {-136, 56}, {-152, 57}, {-3, 58}, + {60, 59}, {62, 61}, {64, 63}, {-36, 65}, {-20, 66}, + {-53, 67}, {-114, 68}, {-57, -99}, {-72, 69}, {-69, 70}, + {-42, 71}, {-151, 72}, {-119, 73}, {-84, -118}, {-135, 74}, + {-4, -130}, {-115, 75}, {-26, -41}, {-87, 76}, {-56, -86}, + {-100, 77}, {-37, -129}, {-21, 78}, {-38, 79}, {-71, -145}, + {-134, 80}, {-85, 81}, {-150, 82}, {-5, 83}, {-133, 84}, + {-102, 85}, {-22, 86}, {-23, 87}, {-54, 88}, {-149, 89}, + {-117, -148}, {-70, 90}, {-6, -101}, {92, 91}, {-8, -55}, + {-7, 93}, {-132, 94}, {-39, -116}, {-24, 95}, {-147, 96}, + {-40, 97}, {-10, -131}, {-146, 98}, {-9, -25}}, + {{2, 1}, {-1, 3}, {5, 4}, {7, 6}, {9, 8}, + {11, 10}, {13, 12}, {-205, 14}, {16, 15}, {18, 17}, + {20, 19}, {-18, 21}, {23, 22}, {25, 24}, {27, 26}, + {29, 28}, {-188, 30}, {32, 31}, {34, 33}, {36, 35}, + {-189, 37}, {39, 38}, {-35, 40}, {42, 41}, {44, 43}, + {46, 45}, {-173, 47}, {49, 48}, {-34, 50}, {-17, 51}, + {53, 52}, {-157, 54}, {56, 55}, {58, 57}, {-171, 59}, + {-50, 60}, {62, 61}, {-66, -141}, {-172, 63}, {-125, 64}, + {66, 65}, {-33, 67}, {-52, 68}, {-204, 69}, {-82, 70}, + {-156, 71}, {-2, 72}, {74, 73}, {-109, 75}, {-51, -98}, + {77, 76}, {-49, -140}, {79, 78}, {-146, 80}, {-124, 81}, + {-61, -93}, {-19, -76}, {-81, -154}, {-65, -114}, {83, 82}, + {-83, -108}, {-67, 84}, {-77, 85}, {-130, 86}, {-99, -155}, + {88, 87}, {-97, 89}, {-69, -91}, {-92, 90}, {-131, 91}, + {93, 92}, {-116, -187}, {-123, 94}, {-60, 95}, {-86, -139}, + {97, 96}, {-68, -162}, {99, 98}, {-45, -113}, {-147, -203}, + {-115, 100}, {-75, 101}, {-84, -106}, {-129, 102}, {-3, 103}, + {-137, 104}, {-132, 105}, {-44, -120}, {-107, 106}, {-20, -100}, + {-36, 107}, {-90, -163}, {-161, 108}, {-59, -145}, {-101, 109}, + {-29, -138}, {-121, 110}, {-177, -178}, {-186, 111}, {-122, -148}, + {-117, 112}, {-85, -170}, {-202, 113}, {-4, 114}, {-37, -105}, + {-74, 115}, {-133, 116}, {-102, 117}, {119, 118}, {-89, -193}, + {-103, 120}, {-21, -53}, {-153, 121}, {123, 122}, {125, 124}, + {-185, 126}, {-104, -169}, {-201, 127}, {-136, 128}, {-118, 129}, + {-87, 130}, {-5, 131}, {-38, 132}, {-54, 133}, {-70, -184}, + {-71, -168}, {-22, 134}, {136, 135}, {-151, -152}, {-55, 137}, + {-6, 138}, {-39, -72}, {-200, 139}, {-167, 140}, {142, 141}, + {-119, -166}, {-88, 143}, {-23, -135}, {-199, 144}, {-165, 145}, + {-56, -150}, {-57, -183}, {-7, 146}, {-41, 147}, {-181, 148}, + {-134, 149}, {-24, -25}, {-40, 150}, {-73, 151}, {-9, 152}, + {-43, 153}, {-182, -197}, {-8, -195}, {-198, 154}, {-149, 155}, + {157, 156}, {159, 158}, {161, 160}, {163, 162}, {165, 164}, + {167, 166}, {-194, -196}, {-179, -180}, {-58, -164}, {-28, -42}, + {-26, -27}, {-12, -13}, {-10, -11}}}; + +static const HUFF_OLD_NOD_2D huffOLDNodes_h2D_1_1 = { + {{-1, 1}, + {-52, 2}, + {4, 3}, + {6, 5}, + {-18, 7}, + {-2, 8}, + {-17, 9}, + {-35, 10}, + {-36, -51}, + {-34, 11}, + {-33, 12}, + {-19, 13}, + {-3, -20}, + {-50, 14}, + {-4, -49}}, + {{-1, 1}, {3, 2}, {5, 4}, {-103, 6}, {8, 7}, {-18, 9}, + {11, 10}, {13, 12}, {-86, 14}, {16, 15}, {-2, -35}, {-17, 17}, + {-87, 18}, {-102, 19}, {21, 20}, {-69, 22}, {-34, 23}, {-19, 24}, + {26, 25}, {-3, 27}, {-52, -70}, {-33, -71}, {-85, 28}, {-101, 29}, + {31, 30}, {-50, 32}, {-51, 33}, {-20, 34}, {-36, 35}, {-4, -55}, + {-54, 36}, {-49, -100}, {-53, 37}, {-84, 38}, {-68, 39}, {41, 40}, + {-5, 42}, {-21, 43}, {-65, -66}, {-67, 44}, {-37, -99}, {-39, 45}, + {-6, 46}, {-38, -83}, {-22, 47}, {-81, -82}, {-7, -98}, {-23, -97}}, + {{-1, 1}, {3, 2}, {5, 4}, {7, 6}, {9, 8}, + {-154, 10}, {-103, 11}, {13, 12}, {-18, 14}, {16, 15}, + {-137, 17}, {19, 18}, {-35, 20}, {22, 21}, {-120, 23}, + {25, 24}, {-52, 26}, {-2, 27}, {-138, 28}, {-153, 29}, + {-17, 30}, {32, 31}, {34, 33}, {-34, 35}, {-19, 36}, + {38, 37}, {40, 39}, {-3, 41}, {-121, 42}, {-122, 43}, + {-136, -152}, {-33, 44}, {-104, 45}, {-105, 46}, {-51, -106}, + {-50, 47}, {-36, 48}, {-20, 49}, {-53, -119}, {-4, 50}, + {-135, -151}, {-68, 51}, {53, 52}, {-49, 54}, {56, 55}, + {-118, 57}, {-88, 58}, {60, 59}, {-5, -8}, {-38, 61}, + {63, 62}, {-21, 64}, {-37, -83}, {-67, 65}, {-66, -133}, + {-6, 66}, {-150, 67}, {-134, 68}, {-23, -65}, {-73, -90}, + {-69, -89}, {-148, 69}, {-7, -22}, {-98, -113}, {71, 70}, + {-82, 72}, {-86, -149}, {-58, -81}, {-74, 73}, {75, 74}, + {77, 76}, {-87, -97}, {-102, 78}, {80, 79}, {-84, 81}, + {-85, 82}, {-54, 83}, {-70, 84}, {-72, 85}, {-117, 86}, + {-71, 87}, {-99, 88}, {-101, 89}, {-39, -100}, {-55, 90}, + {-57, 91}, {-132, 92}, {-56, 93}, {-24, -114}, {-115, 94}, + {-40, -116}, {-42, -147}, {-9, -41}, {-131, 95}, {97, 96}, + {-129, 98}, {-25, -130}, {-26, -146}, {-10, -145}}, + {{2, 1}, {-1, 3}, {5, 4}, {7, 6}, {9, 8}, + {11, 10}, {13, 12}, {-205, 14}, {16, 15}, {18, 17}, + {-18, 19}, {21, 20}, {23, 22}, {-188, 24}, {26, 25}, + {28, 27}, {30, 29}, {-35, 31}, {33, 32}, {35, 34}, + {-171, 36}, {-189, 37}, {-204, 38}, {40, 39}, {-2, 41}, + {43, 42}, {-17, 44}, {-52, 45}, {-34, 46}, {-19, 47}, + {49, 48}, {-154, 50}, {52, 51}, {54, 53}, {-172, 55}, + {-173, 56}, {-69, -187}, {-203, 57}, {59, 58}, {-86, 60}, + {-3, 61}, {63, 62}, {-33, -50}, {-51, 64}, {-36, 65}, + {-137, 66}, {-20, 67}, {69, 68}, {-120, 70}, {72, 71}, + {-156, -157}, {-155, 73}, {-170, 74}, {76, 75}, {-186, -202}, + {78, 77}, {80, 79}, {82, 81}, {-4, -67}, {-49, -103}, + {-66, 83}, {-68, 84}, {-53, 85}, {-21, 86}, {-37, 87}, + {89, 88}, {91, 90}, {93, 92}, {-138, 94}, {-140, 95}, + {-141, -153}, {-139, 96}, {-201, 97}, {-185, 98}, {-121, 99}, + {-169, 100}, {-5, 101}, {-136, 102}, {-65, -84}, {-83, -85}, + {-82, 103}, {-70, 104}, {-54, 105}, {-38, 106}, {108, 107}, + {-101, 109}, {-22, -102}, {-122, -123}, {111, 110}, {113, 112}, + {-125, 114}, {-87, -124}, {-71, 115}, {-168, 116}, {-6, -200}, + {-184, 117}, {-152, 118}, {-81, 119}, {121, 120}, {-105, 122}, + {-106, 123}, {-99, 124}, {-98, -100}, {-23, 125}, {-104, 126}, + {-39, 127}, {-135, 128}, {-55, -151}, {130, 129}, {-91, -119}, + {-7, -199}, {-183, 131}, {-107, -108}, {-116, 132}, {-109, -117}, + {-56, -167}, {-97, 133}, {-90, 134}, {-72, 135}, {-115, -118}, + {-92, 136}, {-93, -166}, {-24, -114}, {-89, 137}, {-88, -150}, + {139, 138}, {-8, 140}, {-40, 141}, {-198, 142}, {-134, 143}, + {-113, 144}, {-182, 145}, {147, 146}, {-41, 148}, {-57, -181}, + {-131, 149}, {151, 150}, {-25, 152}, {-132, 153}, {155, 154}, + {-9, -76}, {-42, -165}, {-73, -133}, {-77, 156}, {-130, 157}, + {-75, -149}, {-10, -146}, {-26, 158}, {-197, 159}, {-180, 160}, + {-147, -196}, {-58, -74}, {-27, 161}, {-129, -148}, {-11, -61}, + {-60, 162}, {-59, 163}, {-43, -145}, {-12, -164}, {-161, 164}, + {-163, 165}, {-162, -195}, {-179, 166}, {-177, 167}, {-28, -178}, + {-45, -194}, {-29, -44}, {-13, -193}}}; + +const HUFF_OLD_NODES huffOLDNodes = { + {&huffOLDNodes_h1D_0, &huffOLDNodes_h1D_1, &huffOLDNodes_h1D_1}, + {{&huffOLDNodes_h2D_0_0, &huffOLDNodes_h2D_0_1}, + {&huffOLDNodes_h2D_1_0, &huffOLDNodes_h2D_1_1}, + {&huffOLDNodes_h2D_0_1, &huffOLDNodes_h2D_0_1}}}; diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mdct.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mdct.cpp new file mode 100644 index 0000000000000..0062b27b143ba --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mdct.cpp @@ -0,0 +1,727 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Josef Hoepfl, Manuel Jander, Youliy Ninov, Daniel Hagel + + Description: MDCT/MDST routines + +*******************************************************************************/ + +#include "mdct.h" + +#include "FDK_tools_rom.h" +#include "dct.h" +#include "fixpoint_math.h" + +void mdct_init(H_MDCT hMdct, FIXP_DBL *overlap, INT overlapBufferSize) { + hMdct->overlap.freq = overlap; + // FDKmemclear(overlap, overlapBufferSize*sizeof(FIXP_DBL)); + hMdct->prev_fr = 0; + hMdct->prev_nr = 0; + hMdct->prev_tl = 0; + hMdct->ov_size = overlapBufferSize; + hMdct->prevAliasSymmetry = 0; + hMdct->prevPrevAliasSymmetry = 0; + hMdct->pFacZir = NULL; + hMdct->pAsymOvlp = NULL; +} + +/* +This program implements the forward MDCT transform on an input block of data. +The input block is in a form (A,B,C,D) where A,B,C and D are the respective +1/4th segments of the block. The program takes the input block and folds it in +the form: +(-D-Cr,A-Br). This block is twice shorter and here the 'r' suffix denotes +flipping of the sequence (reversing the order of the samples). While folding the +input block in the above mentioned shorter block the program windows the data. +Because the two operations (windowing and folding) are not implemented +sequentially, but together the program's structure is not easy to understand. +Once the output (already windowed) block (-D-Cr,A-Br) is ready it is passed to +the DCT IV for processing. +*/ +INT mdct_block(H_MDCT hMdct, const INT_PCM *RESTRICT timeData, + const INT noInSamples, FIXP_DBL *RESTRICT mdctData, + const INT nSpec, const INT tl, const FIXP_WTP *pRightWindowPart, + const INT fr, SHORT *pMdctData_e) { + int i, n; + /* tl: transform length + fl: left window slope length + nl: left window slope offset + fr: right window slope length + nr: right window slope offset + See FDK_tools/doc/intern/mdct.tex for more detail. */ + int fl, nl, nr; + const FIXP_WTP *wls, *wrs; + + wrs = pRightWindowPart; + + /* Detect FRprevious / FL mismatches and override parameters accordingly */ + if (hMdct->prev_fr == + 0) { /* At start just initialize and pass parameters as they are */ + hMdct->prev_fr = fr; + hMdct->prev_wrs = wrs; + hMdct->prev_tl = tl; + } + + /* Derive NR */ + nr = (tl - fr) >> 1; + + /* Skip input samples if tl is smaller than block size */ + timeData += (noInSamples - tl) >> 1; + + /* windowing */ + for (n = 0; n < nSpec; n++) { + /* + * MDCT scale: + * + 1: fMultDiv2() in windowing. + * + 1: Because of factor 1/2 in Princen-Bradley compliant windowed TDAC. + */ + INT mdctData_e = 1 + 1; + + /* Derive left parameters */ + wls = hMdct->prev_wrs; + fl = hMdct->prev_fr; + nl = (tl - fl) >> 1; + + /* Here we implement a simplified version of what happens after the this + piece of code (see the comments below). We implement the folding of A and B + segments to (A-Br) but A is zero, because in this part of the MDCT sequence + the window coefficients with which A must be multiplied are zero. */ + for (i = 0; i < nl; i++) { +#if SAMPLE_BITS == DFRACT_BITS /* SPC_BITS and DFRACT_BITS should be equal. */ + mdctData[(tl / 2) + i] = -((FIXP_DBL)timeData[tl - i - 1] >> (1)); +#else + mdctData[(tl / 2) + i] = -(FIXP_DBL)timeData[tl - i - 1] + << (DFRACT_BITS - SAMPLE_BITS - 1); /* 0(A)-Br */ +#endif + } + + /* Implements the folding and windowing of the left part of the sequence, + that is segments A and B. The A segment is multiplied by the respective left + window coefficient and placed in a temporary variable. + + tmp0 = fMultDiv2((FIXP_PCM)timeData[i+nl], pLeftWindowPart[i].v.im); + + After this the B segment taken in reverse order is multiplied by the left + window and subtracted from the previously derived temporary variable, so + that finally we implement the A-Br operation. This output is written to the + right part of the MDCT output : (-D-Cr,A-Br). + + mdctData[(tl/2)+i+nl] = fMultSubDiv2(tmp0, (FIXP_PCM)timeData[tl-nl-i-1], + pLeftWindowPart[i].v.re);//A*window-Br*window + + The (A-Br) data is written to the output buffer (mdctData) without being + flipped. */ + for (i = 0; i < fl / 2; i++) { + FIXP_DBL tmp0; + tmp0 = fMultDiv2((FIXP_PCM)timeData[i + nl], wls[i].v.im); /* a*window */ + mdctData[(tl / 2) + i + nl] = + fMultSubDiv2(tmp0, (FIXP_PCM)timeData[tl - nl - i - 1], + wls[i].v.re); /* A*window-Br*window */ + } + + /* Right window slope offset */ + /* Here we implement a simplified version of what happens after the this + piece of code (see the comments below). We implement the folding of C and D + segments to (-D-Cr) but D is zero, because in this part of the MDCT sequence + the window coefficients with which D must be multiplied are zero. */ + for (i = 0; i < nr; i++) { +#if SAMPLE_BITS == \ + DFRACT_BITS /* This should be SPC_BITS instead of DFRACT_BITS. */ + mdctData[(tl / 2) - 1 - i] = -((FIXP_DBL)timeData[tl + i] >> (1)); +#else + mdctData[(tl / 2) - 1 - i] = + -(FIXP_DBL)timeData[tl + i] + << (DFRACT_BITS - SAMPLE_BITS - 1); /* -C flipped at placing */ +#endif + } + + /* Implements the folding and windowing of the right part of the sequence, + that is, segments C and D. The C segment is multiplied by the respective + right window coefficient and placed in a temporary variable. + + tmp1 = fMultDiv2((FIXP_PCM)timeData[tl+nr+i], pRightWindowPart[i].v.re); + + After this the D segment taken in reverse order is multiplied by the right + window and added from the previously derived temporary variable, so that we + get (C+Dr) operation. This output is negated to get (-C-Dr) and written to + the left part of the MDCT output while being reversed (flipped) at the same + time, so that from (-C-Dr) we get (-D-Cr)=> (-D-Cr,A-Br). + + mdctData[(tl/2)-nr-i-1] = -fMultAddDiv2(tmp1, + (FIXP_PCM)timeData[(tl*2)-nr-i-1], pRightWindowPart[i].v.im);*/ + for (i = 0; i < fr / 2; i++) { + FIXP_DBL tmp1; + tmp1 = fMultDiv2((FIXP_PCM)timeData[tl + nr + i], + wrs[i].v.re); /* C*window */ + mdctData[(tl / 2) - nr - i - 1] = + -fMultAddDiv2(tmp1, (FIXP_PCM)timeData[(tl * 2) - nr - i - 1], + wrs[i].v.im); /* -(C*window+Dr*window) and flip before + placing -> -Cr - D */ + } + + /* We pass the shortened folded data (-D-Cr,A-Br) to the MDCT function */ + dct_IV(mdctData, tl, &mdctData_e); + + pMdctData_e[n] = (SHORT)mdctData_e; + + timeData += tl; + mdctData += tl; + + hMdct->prev_wrs = wrs; + hMdct->prev_fr = fr; + hMdct->prev_tl = tl; + } + + return nSpec * tl; +} + +void imdct_gain(FIXP_DBL *pGain_m, int *pGain_e, int tl) { + FIXP_DBL gain_m = *pGain_m; + int gain_e = *pGain_e; + int log2_tl; + + gain_e += -MDCT_OUTPUT_GAIN - MDCT_OUT_HEADROOM + 1; + if (tl == 0) { + /* Dont regard the 2/N factor from the IDCT. It is compensated for somewhere + * else. */ + *pGain_e = gain_e; + return; + } + + log2_tl = DFRACT_BITS - 1 - fNormz((FIXP_DBL)tl); + gain_e += -log2_tl; + + /* Detect non-radix 2 transform length and add amplitude compensation factor + which cannot be included into the exponent above */ + switch ((tl) >> (log2_tl - 2)) { + case 0x7: /* 10 ms, 1/tl = 1.0/(FDKpow(2.0, -log2_tl) * + 0.53333333333333333333) */ + if (gain_m == (FIXP_DBL)0) { + gain_m = FL2FXCONST_DBL(0.53333333333333333333f); + } else { + gain_m = fMult(gain_m, FL2FXCONST_DBL(0.53333333333333333333f)); + } + break; + case 0x6: /* 3/4 of radix 2, 1/tl = 1.0/(FDKpow(2.0, -log2_tl) * 2.0/3.0) */ + if (gain_m == (FIXP_DBL)0) { + gain_m = FL2FXCONST_DBL(2.0 / 3.0f); + } else { + gain_m = fMult(gain_m, FL2FXCONST_DBL(2.0 / 3.0f)); + } + break; + case 0x5: /* 0.8 of radix 2 (e.g. tl 160), 1/tl = 1.0/(FDKpow(2.0, -log2_tl) + * 0.8/1.5) */ + if (gain_m == (FIXP_DBL)0) { + gain_m = FL2FXCONST_DBL(0.53333333333333333333f); + } else { + gain_m = fMult(gain_m, FL2FXCONST_DBL(0.53333333333333333333f)); + } + break; + case 0x4: + /* radix 2, nothing to do. */ + break; + default: + /* unsupported */ + FDK_ASSERT(0); + break; + } + + *pGain_m = gain_m; + *pGain_e = gain_e; +} + +INT imdct_drain(H_MDCT hMdct, FIXP_DBL *output, INT nrSamplesRoom) { + int buffered_samples = 0; + + if (nrSamplesRoom > 0) { + buffered_samples = hMdct->ov_offset; + + FDK_ASSERT(buffered_samples <= nrSamplesRoom); + + if (buffered_samples > 0) { + FDKmemcpy(output, hMdct->overlap.time, + buffered_samples * sizeof(FIXP_DBL)); + hMdct->ov_offset = 0; + } + } + return buffered_samples; +} + +INT imdct_copy_ov_and_nr(H_MDCT hMdct, FIXP_DBL *pTimeData, INT nrSamples) { + FIXP_DBL *pOvl; + int nt, nf, i; + + nt = fMin(hMdct->ov_offset, nrSamples); + nrSamples -= nt; + nf = fMin(hMdct->prev_nr, nrSamples); + FDKmemcpy(pTimeData, hMdct->overlap.time, nt * sizeof(FIXP_DBL)); + pTimeData += nt; + + pOvl = hMdct->overlap.freq + hMdct->ov_size - 1; + if (hMdct->prevPrevAliasSymmetry == 0) { + for (i = 0; i < nf; i++) { + FIXP_DBL x = -(*pOvl--); + *pTimeData = IMDCT_SCALE_DBL(x); + pTimeData++; + } + } else { + for (i = 0; i < nf; i++) { + FIXP_DBL x = (*pOvl--); + *pTimeData = IMDCT_SCALE_DBL(x); + pTimeData++; + } + } + + return (nt + nf); +} + +void imdct_adapt_parameters(H_MDCT hMdct, int *pfl, int *pnl, int tl, + const FIXP_WTP *wls, int noOutSamples) { + int fl = *pfl, nl = *pnl; + int window_diff, use_current = 0, use_previous = 0; + if (hMdct->prev_tl == 0) { + hMdct->prev_wrs = wls; + hMdct->prev_fr = fl; + hMdct->prev_nr = (noOutSamples - fl) >> 1; + hMdct->prev_tl = noOutSamples; + hMdct->ov_offset = 0; + use_current = 1; + } + + window_diff = (hMdct->prev_fr - fl) >> 1; + + /* check if the previous window slope can be adjusted to match the current + * window slope */ + if (hMdct->prev_nr + window_diff > 0) { + use_current = 1; + } + /* check if the current window slope can be adjusted to match the previous + * window slope */ + if (nl - window_diff > 0) { + use_previous = 1; + } + + /* if both is possible choose the larger of both window slope lengths */ + if (use_current && use_previous) { + if (fl < hMdct->prev_fr) { + use_current = 0; + } + } + /* + * If the previous transform block is big enough, enlarge previous window + * overlap, if not, then shrink current window overlap. + */ + if (use_current) { + hMdct->prev_nr += window_diff; + hMdct->prev_fr = fl; + hMdct->prev_wrs = wls; + } else { + nl -= window_diff; + fl = hMdct->prev_fr; + } + + *pfl = fl; + *pnl = nl; +} + +/* +This program implements the inverse modulated lapped transform, a generalized +version of the inverse MDCT transform. Setting none of the MLT_*_ALIAS_FLAG +flags computes the IMDCT, setting all of them computes the IMDST. Other +combinations of these flags compute type III transforms used by the RSVD60 +multichannel tool for transitions between MDCT/MDST. The following description +relates to the IMDCT only. + +If we pass the data block (A,B,C,D,E,F) to the FORWARD MDCT it will produce two +outputs. The first one will be over the (A,B,C,D) part =>(-D-Cr,A-Br) and the +second one will be over the (C,D,E,F) part => (-F-Er,C-Dr), since there is a +overlap between consequtive passes of the algorithm. This overlap is over the +(C,D) segments. The two outputs will be given sequentially to the DCT IV +algorithm. At the INVERSE MDCT side we get two consecutive outputs from the IDCT +IV algorithm, namely the same blocks: (-D-Cr,A-Br) and (-F-Er,C-Dr). The first +of them lands in the Overlap buffer and the second is in the working one, which, +one algorithm pass later will substitute the one residing in the overlap +register. The IMDCT algorithm has to produce the C and D segments from the two +buffers. In order to do this we take the left part of the overlap +buffer(-D-Cr,A-Br), namely (-D-Cr) and add it appropriately to the right part of +the working buffer (-F-Er,C-Dr), namely (C-Dr), so that we get first the C +segment and later the D segment. We do this in the following way: From the right +part of the working buffer(C-Dr) we subtract the flipped left part of the +overlap buffer(-D-Cr): + +Result = (C-Dr) - flipped(-D-Cr) = C -Dr + Dr + C = 2C +We divide by two and get the C segment. What we did is adding the right part of +the first frame to the left part of the second one. While applying these +operation we multiply the respective segments with the appropriate window +functions. + +In order to get the D segment we do the following: +From the negated second part of the working buffer(C-Dr) we subtract the flipped +first part of the overlap buffer (-D-Cr): + +Result= - (C -Dr) - flipped(-D-Cr)= -C +Dr +Dr +C = 2Dr. +After dividing by two and flipping we get the D segment.What we did is adding +the right part of the first frame to the left part of the second one. While +applying these operation we multiply the respective segments with the +appropriate window functions. + +Once we have obtained the C and D segments the overlap buffer is emptied and the +current buffer is sent in it, so that the E and F segments are available for +decoding in the next algorithm pass.*/ +INT imlt_block(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *spectrum, + const SHORT scalefactor[], const INT nSpec, + const INT noOutSamples, const INT tl, const FIXP_WTP *wls, + INT fl, const FIXP_WTP *wrs, const INT fr, FIXP_DBL gain, + int flags) { + FIXP_DBL *pOvl; + FIXP_DBL *pOut0 = output, *pOut1; + INT nl, nr; + int w, i, nrSamples = 0, specShiftScale, transform_gain_e = 0; + int currAliasSymmetry = (flags & MLT_FLAG_CURR_ALIAS_SYMMETRY); + + /* Derive NR and NL */ + nr = (tl - fr) >> 1; + nl = (tl - fl) >> 1; + + /* Include 2/N IMDCT gain into gain factor and exponent. */ + imdct_gain(&gain, &transform_gain_e, tl); + + /* Detect FRprevious / FL mismatches and override parameters accordingly */ + if (hMdct->prev_fr != fl) { + imdct_adapt_parameters(hMdct, &fl, &nl, tl, wls, noOutSamples); + } + + pOvl = hMdct->overlap.freq + hMdct->ov_size - 1; + + if (noOutSamples > nrSamples) { + /* Purge buffered output. */ + for (i = 0; i < hMdct->ov_offset; i++) { + *pOut0 = hMdct->overlap.time[i]; + pOut0++; + } + nrSamples = hMdct->ov_offset; + hMdct->ov_offset = 0; + } + + for (w = 0; w < nSpec; w++) { + FIXP_DBL *pSpec, *pCurr; + const FIXP_WTP *pWindow; + + /* Detect FRprevious / FL mismatches and override parameters accordingly */ + if (hMdct->prev_fr != fl) { + imdct_adapt_parameters(hMdct, &fl, &nl, tl, wls, noOutSamples); + } + + specShiftScale = transform_gain_e; + + /* Setup window pointers */ + pWindow = hMdct->prev_wrs; + + /* Current spectrum */ + pSpec = spectrum + w * tl; + + /* DCT IV of current spectrum. */ + if (currAliasSymmetry == 0) { + if (hMdct->prevAliasSymmetry == 0) { + dct_IV(pSpec, tl, &specShiftScale); + } else { + FIXP_DBL _tmp[1024 + ALIGNMENT_DEFAULT / sizeof(FIXP_DBL)]; + FIXP_DBL *tmp = (FIXP_DBL *)ALIGN_PTR(_tmp); + C_ALLOC_ALIGNED_REGISTER(tmp, sizeof(_tmp)); + dct_III(pSpec, tmp, tl, &specShiftScale); + C_ALLOC_ALIGNED_UNREGISTER(tmp); + } + } else { + if (hMdct->prevAliasSymmetry == 0) { + FIXP_DBL _tmp[1024 + ALIGNMENT_DEFAULT / sizeof(FIXP_DBL)]; + FIXP_DBL *tmp = (FIXP_DBL *)ALIGN_PTR(_tmp); + C_ALLOC_ALIGNED_REGISTER(tmp, sizeof(_tmp)); + dst_III(pSpec, tmp, tl, &specShiftScale); + C_ALLOC_ALIGNED_UNREGISTER(tmp); + } else { + dst_IV(pSpec, tl, &specShiftScale); + } + } + + /* Optional scaling of time domain - no yet windowed - of current spectrum + */ + /* and de-scale current spectrum signal (time domain, no yet windowed) */ + if (gain != (FIXP_DBL)0) { + for (i = 0; i < tl; i++) { + pSpec[i] = fMult(pSpec[i], gain); + } + } + + { + int loc_scale = + fixmin_I(scalefactor[w] + specShiftScale, (INT)DFRACT_BITS - 1); + DWORD_ALIGNED(pSpec); + scaleValuesSaturate(pSpec, tl, loc_scale); + } + + if (noOutSamples <= nrSamples) { + /* Divert output first half to overlap buffer if we already got enough + * output samples. */ + pOut0 = hMdct->overlap.time + hMdct->ov_offset; + hMdct->ov_offset += hMdct->prev_nr + fl / 2; + } else { + /* Account output samples */ + nrSamples += hMdct->prev_nr + fl / 2; + } + + /* NR output samples 0 .. NR. -overlap[TL/2..TL/2-NR] */ + if ((hMdct->pFacZir != 0) && (hMdct->prev_nr == fl / 2)) { + /* In the case of ACELP -> TCX20 -> FD short add FAC ZIR on nr signal part + */ + for (i = 0; i < hMdct->prev_nr; i++) { + FIXP_DBL x = -(*pOvl--); + *pOut0 = fAddSaturate(x, IMDCT_SCALE_DBL(hMdct->pFacZir[i])); + pOut0++; + } + hMdct->pFacZir = NULL; + } else { + /* Here we implement a simplified version of what happens after the this + piece of code (see the comments below). We implement the folding of C and + D segments from (-D-Cr) but D is zero, because in this part of the MDCT + sequence the window coefficients with which D must be multiplied are zero. + "pOut0" writes sequentially the C block from left to right. */ + if (hMdct->prevPrevAliasSymmetry == 0) { + for (i = 0; i < hMdct->prev_nr; i++) { + FIXP_DBL x = -(*pOvl--); + *pOut0 = IMDCT_SCALE_DBL(x); + pOut0++; + } + } else { + for (i = 0; i < hMdct->prev_nr; i++) { + FIXP_DBL x = *pOvl--; + *pOut0 = IMDCT_SCALE_DBL(x); + pOut0++; + } + } + } + + if (noOutSamples <= nrSamples) { + /* Divert output second half to overlap buffer if we already got enough + * output samples. */ + pOut1 = hMdct->overlap.time + hMdct->ov_offset + fl / 2 - 1; + hMdct->ov_offset += fl / 2 + nl; + } else { + pOut1 = pOut0 + (fl - 1); + nrSamples += fl / 2 + nl; + } + + /* output samples before window crossing point NR .. TL/2. + * -overlap[TL/2-NR..TL/2-NR-FL/2] + current[NR..TL/2] */ + /* output samples after window crossing point TL/2 .. TL/2+FL/2. + * -overlap[0..FL/2] - current[TL/2..FL/2] */ + pCurr = pSpec + tl - fl / 2; + DWORD_ALIGNED(pCurr); + C_ALLOC_ALIGNED_REGISTER(pWindow, fl); + DWORD_ALIGNED(pWindow); + C_ALLOC_ALIGNED_UNREGISTER(pWindow); + + if (hMdct->prevPrevAliasSymmetry == 0) { + if (hMdct->prevAliasSymmetry == 0) { + if (!hMdct->pAsymOvlp) { + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow[i]); + *pOut0 = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1 = IMDCT_SCALE_DBL_LSH1(-x1); + pOut0++; + pOut1--; + } + } else { + FIXP_DBL *pAsymOvl = hMdct->pAsymOvlp + fl / 2 - 1; + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + x1 = -fMultDiv2(*pCurr, pWindow[i].v.re) + + fMultDiv2(*pAsymOvl, pWindow[i].v.im); + x0 = fMultDiv2(*pCurr, pWindow[i].v.im) - + fMultDiv2(*pOvl, pWindow[i].v.re); + pCurr++; + pOvl--; + pAsymOvl--; + *pOut0++ = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1-- = IMDCT_SCALE_DBL_LSH1(x1); + } + hMdct->pAsymOvlp = NULL; + } + } else { /* prevAliasingSymmetry == 1 */ + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow[i]); + *pOut0 = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1 = IMDCT_SCALE_DBL_LSH1(x1); + pOut0++; + pOut1--; + } + } + } else { /* prevPrevAliasingSymmetry == 1 */ + if (hMdct->prevAliasSymmetry == 0) { + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + cplxMultDiv2(&x1, &x0, *pCurr++, *pOvl--, pWindow[i]); + *pOut0 = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1 = IMDCT_SCALE_DBL_LSH1(-x1); + pOut0++; + pOut1--; + } + } else { /* prevAliasingSymmetry == 1 */ + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + cplxMultDiv2(&x1, &x0, *pCurr++, *pOvl--, pWindow[i]); + *pOut0 = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1 = IMDCT_SCALE_DBL_LSH1(x1); + pOut0++; + pOut1--; + } + } + } + + if (hMdct->pFacZir != 0) { + /* add FAC ZIR of previous ACELP -> mdct transition */ + FIXP_DBL *pOut = pOut0 - fl / 2; + FDK_ASSERT(fl / 2 <= 128); + for (i = 0; i < fl / 2; i++) { + pOut[i] = fAddSaturate(pOut[i], IMDCT_SCALE_DBL(hMdct->pFacZir[i])); + } + hMdct->pFacZir = NULL; + } + pOut0 += (fl / 2) + nl; + + /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */ + pOut1 += (fl / 2) + 1; + pCurr = pSpec + tl - fl / 2 - 1; + /* Here we implement a simplified version of what happens above the this + piece of code (see the comments above). We implement the folding of C and D + segments from (C-Dr) but C is zero, because in this part of the MDCT + sequence the window coefficients with which C must be multiplied are zero. + "pOut1" writes sequentially the D block from left to right. */ + if (hMdct->prevAliasSymmetry == 0) { + for (i = 0; i < nl; i++) { + FIXP_DBL x = -(*pCurr--); + *pOut1++ = IMDCT_SCALE_DBL(x); + } + } else { + for (i = 0; i < nl; i++) { + FIXP_DBL x = *pCurr--; + *pOut1++ = IMDCT_SCALE_DBL(x); + } + } + + /* Set overlap source pointer for next window pOvl = pSpec + tl/2 - 1; */ + pOvl = pSpec + tl / 2 - 1; + + /* Previous window values. */ + hMdct->prev_nr = nr; + hMdct->prev_fr = fr; + hMdct->prev_tl = tl; + hMdct->prev_wrs = wrs; + + /* Previous aliasing symmetry */ + hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; + hMdct->prevAliasSymmetry = currAliasSymmetry; + } + + /* Save overlap */ + + pOvl = hMdct->overlap.freq + hMdct->ov_size - tl / 2; + FDKmemcpy(pOvl, &spectrum[(nSpec - 1) * tl], (tl / 2) * sizeof(FIXP_DBL)); + + return nrSamples; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mips/fft_rad2_mips.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mips/fft_rad2_mips.cpp new file mode 100644 index 0000000000000..7db8b4ed49df9 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mips/fft_rad2_mips.cpp @@ -0,0 +1,165 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: dit_fft MIPS assembler replacements. + +*******************************************************************************/ + +#ifndef __FFT_RAD2_CPP__ +#error \ + "Do not compile this file separately. It is included on demand from fft_rad2.cpp" +#endif + +#if defined(MIPS_DSP_LIB) + +#include "dsplib_util.h" +#include "dsplib_dsp.h" + +#define FUNCTION_dit_fft + +#ifdef FUNCTION_dit_fft + +#include "mips_fft_twiddles.cpp" + +void dit_fft(FIXP_DBL *x, const INT ldn, const FIXP_STP *trigdata, + const INT trigDataSize) { + int i; + + int32c *din = (int32c *)x; + int32c *dout = (int32c *)x; + + int32c scratch[1024]; + int32c *twiddles; + + switch (ldn) { + case 4: + twiddles = (int32c *)__twiddles_mips_fft32_16; + break; + case 5: + twiddles = (int32c *)__twiddles_mips_fft32_32; + break; + case 6: + twiddles = (int32c *)__twiddles_mips_fft32_64; + break; + case 7: + twiddles = (int32c *)__twiddles_mips_fft32_128; + break; + case 8: + twiddles = (int32c *)__twiddles_mips_fft32_256; + break; + case 9: + twiddles = (int32c *)__twiddles_mips_fft32_512; + break; + case 10: + twiddles = (int32c *)__twiddles_mips_fft32_1024; + break; + default: + FDK_ASSERT(0); + break; + } + + mips_fft32(dout, din, twiddles, scratch, ldn); + + for (i = 0; i < (1 << ldn); i++) { + x[2 * i] = dout[i].re << 1; + x[2 * i + 1] = dout[i].im << 1; + } +} +#endif + +#endif /* defined(MIPS_DSP_LIB) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mips/mips_fft_twiddles.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mips/mips_fft_twiddles.cpp new file mode 100644 index 0000000000000..f905f86a0a202 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mips/mips_fft_twiddles.cpp @@ -0,0 +1,931 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +static const INT __twiddles_mips_fft32_16[] = { + (0x7FFFFFFF), (0x00000000), (0x7641AF32), (0xCF043A9E), (0x5A827978), + (0xA57D8646), (0x30FBC547), (0x89BE50C2), (0xFFFFFFA3), (0x80000002), + (0xCF043AF8), (0x89BE50A8), (0xA57D865E), (0xA57D8670), (0x89BE5100), + (0xCF043A24), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000)}; + +static const INT __twiddles_mips_fft32_32[] = { + (0x7FFFFFFF), (0x00000000), (0x7D8A5F3C), (0xE70747B9), (0x7641AF32), + (0xCF043A9E), (0x6A6D98A1), (0xB8E31318), (0x5A827978), (0xA57D8646), + (0x471CED05), (0x95926772), (0x30FBC547), (0x89BE50C2), (0x18F8B888), + (0x8275A0D1), (0xFFFFFFA3), (0x80000002), (0xE70747BB), (0x8275A0C3), + (0xCF043AF8), (0x89BE50A8), (0xB8E3139E), (0x95926705), (0xA57D865E), + (0xA57D8670), (0x959266F7), (0xB8E313B4), (0x89BE5100), (0xCF043A24), + (0x8275A0BE), (0xE70747D4), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x37000000), (0x000080A3), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000)}; + +static const INT __twiddles_mips_fft32_64[] = { + (0x7FFFFFFF), (0x00000000), (0x7F62368D), (0xF3742C9D), (0x7D8A5F3C), + (0xE70747B9), (0x7A7D0559), (0xDAD7F3A2), (0x7641AF32), (0xCF043A9E), + (0x70E2CBCD), (0xC3A945A1), (0x6A6D98A1), (0xB8E31318), (0x62F201C4), + (0xAECC338B), (0x5A827978), (0xA57D8646), (0x5133CC8F), (0x9D0DFE52), + (0x471CED05), (0x95926772), (0x3C56BAB5), (0x8F1D3461), (0x30FBC547), + (0x89BE50C2), (0x25280C05), (0x8582FA8C), (0x18F8B888), (0x8275A0D1), + (0x0C8BD356), (0x809DC971), (0xFFFFFFA3), (0x80000002), (0xF3742CEE), + (0x809DC96B), (0xE70747BB), (0x8275A0C3), (0xDAD7F348), (0x8582FAC2), + (0xCF043AF8), (0x89BE50A8), (0xC3A94669), (0x8F1D33C8), (0xB8E3139E), + (0x95926705), (0xAECC33A5), (0x9D0DFE27), (0xA57D865E), (0xA57D8670), + (0x9D0DFE16), (0xAECC33B9), (0x959266F7), (0xB8E313B4), (0x8F1D34AD), + (0xC3A944BC), (0x89BE5100), (0xCF043A24), (0x8582FABB), (0xDAD7F360), + (0x8275A0BE), (0xE70747D4), (0x809DC968), (0xF3742D08), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0xFF7B0000), + (0x2E8050F1), (0x10214482), (0x1BA00005), (0x0000C0FF), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000)}; + +static const INT __twiddles_mips_fft32_128[] = { + (0x7FFFFFFF), (0x00000000), (0x7FD8878C), (0xF9B82681), (0x7F62368D), + (0xF3742C9D), (0x7E9D55FB), (0xED37EF91), (0x7D8A5F3C), (0xE70747B9), + (0x7C29FBEF), (0xE0E6068F), (0x7A7D0559), (0xDAD7F3A2), (0x78848419), + (0xD4E0CB28), (0x7641AF32), (0xCF043A9E), (0x73B5EBCF), (0xC945DFEB), + (0x70E2CBCD), (0xC3A945A1), (0x6DCA0D27), (0xBE31E1BF), (0x6A6D98A1), + (0xB8E31318), (0x66CF8103), (0xB3C01FE9), (0x62F201C4), (0xAECC338B), + (0x5ED77C86), (0xAA0A5B2C), (0x5A827978), (0xA57D8646), (0x55F5A4ED), + (0xA1288391), (0x5133CC8F), (0x9D0DFE52), (0x4C3FDFCC), (0x99307EC5), + (0x471CED05), (0x95926772), (0x41CE1ECD), (0x9235F32C), (0x3C56BAB5), + (0x8F1D3461), (0x36BA2034), (0x8C4A1440), (0x30FBC547), (0x89BE50C2), + (0x2B1F34BC), (0x877B7BDD), (0x25280C05), (0x8582FA8C), (0x1F19F9F0), + (0x83D60431), (0x18F8B888), (0x8275A0D1), (0x12C81090), (0x8162AA0A), + (0x0C8BD356), (0x809DC971), (0x0647D949), (0x80277871), (0xFFFFFFA3), + (0x80000002), (0xF9B826FB), (0x8027786E), (0xF3742CEE), (0x809DC96B), + (0xED37EFB3), (0x8162AA00), (0xE70747BB), (0x8275A0C3), (0xE0E60653), + (0x83D60420), (0xDAD7F348), (0x8582FAC2), (0xD4E0CB84), (0x877B7BC6), + (0xCF043AF8), (0x89BE50A8), (0xC945E00A), (0x8C4A1423), (0xC3A94669), + (0x8F1D33C8), (0xBE31E16E), (0x9235F309), (0xB8E3139E), (0x95926705), + (0xB3C01F9D), (0x99307F35), (0xAECC33A5), (0x9D0DFE27), (0xAA0A5A88), + (0xA128840F), (0xA57D865E), (0xA57D8670), (0xA12883FE), (0xAA0A5A9B), + (0x9D0DFE16), (0xAECC33B9), (0x99307F26), (0xB3C01FB2), (0x959266F7), + (0xB8E313B4), (0x9235F2FC), (0xBE31E184), (0x8F1D34AD), (0xC3A944BC), + (0x8C4A1418), (0xC945E021), (0x89BE5100), (0xCF043A24), (0x877B7BBD), + (0xD4E0CB9C), (0x8582FABB), (0xDAD7F360), (0x83D603DC), (0xE0E60764), + (0x8275A0BE), (0xE70747D4), (0x8162AA22), (0xED37EECF), (0x809DC968), + (0xF3742D08), (0x80277879), (0xF9B82615), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0xA4370000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0xFF770000), (0x2E8050F1), (0x1A214462), + (0x04D6D583), (0x40031282), (0x6469A735), (0x0B4C99A3), (0x0AF88594), + (0xF90969D7), (0x96131C92), (0x025EEA10), (0x3A1FE421), (0x614FF390), + (0x1CFDC327), (0xC177E04F), (0xF4D87E82), (0x78253F39), (0xBB839F94), + (0x998B3EB1), (0x0CBCC021), (0x41BEC843), (0xAC0EE121), (0x52719643), + (0x909A2B1D), (0xF38931E1), (0xF41327FF), (0xF6099847), (0xA70D219C), + (0x7BD52135), (0x78060F71), (0xEA3C87D8), (0x3FAF3A24), (0xE4B2C421), + (0xB99D1453), (0x2741E264), (0x2239813A), (0x2944DA20), (0x441EF7C4), + (0x0BD0B720), (0xED84EA26), (0x73E0C0D2), (0x678E3039), (0x21420109), + (0x8607492E), (0x28CEF440), (0x022768C8), (0xF68E3611), (0x84E84D55), + (0x73004C04), (0xF9B6630E), (0x677FFA8F), (0x530CB18F), (0x2C4EE310), + (0xABC7537C), (0x82CFDBCB), (0x100C63A2), (0x876D75BA), (0xC683F888), + (0x0CDC1E1E), (0xA600E833), (0x33036066), (0x4305049C), (0x40890713), + (0x9D12532E), (0x7B6E2FE2), (0xE244CC09), (0x9FFB2082), (0xAB3735D3), + (0x00000080), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000)}; + +static const INT __twiddles_mips_fft32_256[] = { + (0x7FFFFFFF), (0x00000000), (0x7FF62181), (0xFCDBD540), (0x7FD8878C), + (0xF9B82681), (0x7FA736B2), (0xF6956FB7), (0x7F62368D), (0xF3742C9D), + (0x7F0991C3), (0xF054D8DA), (0x7E9D55FB), (0xED37EF91), (0x7E1D93EA), + (0xEA1DEBC6), (0x7D8A5F3C), (0xE70747B9), (0x7CE3CEB0), (0xE3F47D95), + (0x7C29FBEF), (0xE0E6068F), (0x7B5D03A1), (0xDDDC5B4F), (0x7A7D0559), + (0xDAD7F3A2), (0x798A23A8), (0xD7D946C3), (0x78848419), (0xD4E0CB28), + (0x776C4ED9), (0xD1EEF59D), (0x7641AF32), (0xCF043A9E), (0x7504D34C), + (0xCC210D8B), (0x73B5EBCF), (0xC945DFEB), (0x72552C79), (0xC67322B9), + (0x70E2CBCD), (0xC3A945A1), (0x6F5F02CF), (0xC0E8B67E), (0x6DCA0D27), + (0xBE31E1BF), (0x6C242969), (0xBB8532C0), (0x6A6D98A1), (0xB8E31318), + (0x68A69E72), (0xB64BEAB9), (0x66CF8103), (0xB3C01FE9), (0x64E8894A), + (0xB140178C), (0x62F201C4), (0xAECC338B), (0x60EC383A), (0xAC64D51F), + (0x5ED77C86), (0xAA0A5B2C), (0x5CB420CD), (0xA7BD229A), (0x5A827978), + (0xA57D8646), (0x5842DD7E), (0xA34BDF4B), (0x55F5A4ED), (0xA1288391), + (0x539B2AFB), (0x9F13C7DC), (0x5133CC8F), (0x9D0DFE52), (0x4EBFE88F), + (0x9B1776CB), (0x4C3FDFCC), (0x99307EC5), (0x49B41562), (0x975961A2), + (0x471CED05), (0x95926772), (0x447ACD5D), (0x93DBD6AA), (0x41CE1ECD), + (0x9235F32C), (0x3F17499F), (0x90A0FD42), (0x3C56BAB5), (0x8F1D3461), + (0x398CDCF3), (0x8DAAD35D), (0x36BA2034), (0x8C4A1440), (0x33DEF21F), + (0x8AFB2C8E), (0x30FBC547), (0x89BE50C2), (0x2E110ABF), (0x8893B14A), + (0x2B1F34BC), (0x877B7BDD), (0x2826B95E), (0x8675DC62), (0x25280C05), + (0x8582FA8C), (0x2223A4D2), (0x84A2FC68), (0x1F19F9F0), (0x83D60431), + (0x1C0B824E), (0x831C314A), (0x18F8B888), (0x8275A0D1), (0x15E213FD), + (0x81E26C0B), (0x12C81090), (0x8162AA0A), (0x0FAB26B9), (0x80F66E30), + (0x0C8BD356), (0x809DC971), (0x096A90AB), (0x8058C955), (0x0647D949), + (0x80277871), (0x03242AF6), (0x8009DE81), (0xFFFFFFA3), (0x80000002), + (0xFCDBD54E), (0x8009DE7F), (0xF9B826FB), (0x8027786E), (0xF6956F99), + (0x8058C950), (0xF3742CEE), (0x809DC96B), (0xF054D88D), (0x80F66E47), + (0xED37EFB3), (0x8162AA00), (0xEA1DEB4A), (0x81E26C2C), (0xE70747BB), + (0x8275A0C3), (0xE3F47DF5), (0x831C313B), (0xE0E60653), (0x83D60420), + (0xDDDC5B6F), (0x84A2FC55), (0xDAD7F348), (0x8582FAC2), (0xD7D946E3), + (0x8675DC4D), (0xD4E0CB84), (0x877B7BC6), (0xD1EEF581), (0x8893B132), + (0xCF043AF8), (0x89BE50A8), (0xCC210D35), (0x8AFB2CDB), (0xC945E00A), + (0x8C4A1423), (0xC6732265), (0x8DAAD3B2), (0xC3A94669), (0x8F1D33C8), + (0xC0E8B69C), (0x90A0FD21), (0xBE31E16E), (0x9235F309), (0xBB853205), + (0x93DBD70E), (0xB8E3139E), (0x95926705), (0xB64BEAD5), (0x9759617B), + (0xB3C01F9D), (0x99307F35), (0xB140180C), (0x9B177652), (0xAECC33A5), + (0x9D0DFE27), (0xAC64D4D8), (0x9F13C803), (0xAA0A5A88), (0xA128840F), + (0xA7BD2310), (0xA34BDEC3), (0xA57D865E), (0xA57D8670), (0xA34BDEB2), + (0xA7BD2322), (0xA12883FE), (0xAA0A5A9B), (0x9F13C7F2), (0xAC64D4EB), + (0x9D0DFE16), (0xAECC33B9), (0x9B177642), (0xB1401820), (0x99307F26), + (0xB3C01FB2), (0x9759616C), (0xB64BEAEA), (0x959266F7), (0xB8E313B4), + (0x93DBD700), (0xBB85321A), (0x9235F2FC), (0xBE31E184), (0x90A0FD14), + (0xC0E8B6B2), (0x8F1D34AD), (0xC3A944BC), (0x8DAAD3A6), (0xC673227C), + (0x8C4A1418), (0xC945E021), (0x8AFB2C68), (0xCC210E37), (0x89BE5100), + (0xCF043A24), (0x8893B128), (0xD1EEF599), (0x877B7BBD), (0xD4E0CB9C), + (0x8675DC95), (0xD7D94608), (0x8582FABB), (0xDAD7F360), (0x84A2FC4F), + (0xDDDC5B88), (0x83D603DC), (0xE0E60764), (0x831C316D), (0xE3F47D14), + (0x8275A0BE), (0xE70747D4), (0x81E26BFB), (0xEA1DEC5F), (0x8162AA22), + (0xED37EECF), (0x80F66E44), (0xF054D8A6), (0x809DC968), (0xF3742D08), + (0x8058C93B), (0xF69570B2), (0x80277879), (0xF9B82615), (0x8009DE7E), + (0xFCDBD568), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0xF1FF7A00), (0xE23A8050), (0x841A2114), (0xC588DA75), (0x02400143), + (0xAED6AAD7), (0x94C2545B), (0x3E46156C), (0x05BFDF27), (0xB0822075), + (0xD24C7BC4), (0x62122054), (0x8CC41C49), (0x2C414972), (0x718D7C5E), + (0xDEE2A3D8), (0x4544C135), (0x64292573), (0x76B51F8A), (0x4B7D6557), + (0x87164907), (0xF59DBFEC), (0x04CEE9DE), (0xB4BC4C90), (0x9AFCCD30), + (0x8C7A316F), (0x90FDACA7), (0x4E0D6383), (0xAEF16C0B), (0x0622020A), + (0x37B6A738), (0xFFBB7D71), (0x5FEDD12F), (0xEE47FDC8), (0x3DC7913F), + (0xEAEEF7FD), (0x219DADEC), (0xF9E53F5F), (0xB3D82D9E), (0xBBB79BCB), + (0x43AD2AAB), (0x0E7ADBC0), (0xABBD0952), (0x1A6EF43A), (0xCD9B2A9D), + (0x7222B366), (0x979E89E9), (0x02C9113F), (0x1D511466), (0x57A92206), + (0x4A412075), (0xFD31D783), (0xA7542EFC), (0x24B76975), (0xB99962C7), + (0x19F1D356), (0x9D12C3CB), (0x6D37D542), (0x29E7214D), (0x8900F645), + (0xB154AD4A), (0xF047D988), (0x3F2E5E77), (0xAFB68C49), (0xC9F19E51), + (0x6192F53A), (0x5AE3D080), (0x1DA6C677), (0xD485D50C), (0x9AA7E8B2), + (0xF55EE1D5), (0xC00B6932), (0x85ACE912), (0x8208B1B9), (0x80E14170), + (0xA1D67C3F), (0x058035B3), (0xA4FE36CA), (0xBEE547E4), (0xEF276052), + (0x42AA4388), (0x9C11A2ED), (0x10202541), (0x2D480910), (0xB09B1AC4), + (0x19E7D17D), (0x52082450), (0x3EED1705), (0xF20FF8A1), (0x89F6E17F), + (0x17D7DC00), (0x09B9F2C3), (0x6378968C), (0xAF0607F6), (0xFDFDE0C9), + (0x3CE3DFEE), (0x5168229E), (0x7CF79734), (0xF5FFF56F), (0x30700093), + (0x135F5C75), (0xE6D73EEE), (0x6E400DF9), (0x58252ACB), (0x557311CA), + (0x5539B303), (0x56557355), (0xB6BDACEF), (0x59F9428D), (0x9AE63020), + (0x558FF7E7), (0x7955806D), (0x09D549F3), (0x603BF5B7), (0x3134413B), + (0xBCA7C1AA), (0xA98D1339), (0x57B29C97), (0x50F1FF07), (0xE4A13980), + (0xD0881A21), (0xC1FFE30A), (0xB0A66C19), (0x18416490), (0x160E0214), + (0xA584CBB5), (0x02AAA82A), (0x73981340), (0x964A24DE), (0x6E829FC4), + (0xDFD62360), (0x4C3BF152), (0x38721574), (0xD46BC912), (0x1EB7FDD8), + (0x1CA6CBC0), (0xBBCBC111), (0xA6FD1403), (0x76C688D9), (0xB47186CB), + (0x5E98936D), (0x9BBF7E2E), (0x8B7FBCEC), (0x9DAF7EF5), (0x7E3A79F1), + (0x9C896ACD), (0x628F249A), (0xDD6E51AF), (0xAF73994B), (0x5966995D), + (0xB7620597), (0x369B1E54), (0x7CEDC787), (0xE7B15B1F), (0xB36F5F7D), + (0xB5B73EF6), (0xD76EEEE2), (0x14E86186), (0xCC159291), (0x4EC85CA3), + (0xEC3C704E), (0x0B6633B3), (0x4D992D4B), (0xEB1B5774), (0xDFB9D508), + (0x11783719), (0x77BB10B0), (0xFCDF8350), (0xD34A7C65), (0xEF6E57BB), + (0xECD56C68), (0x8EB7CA36), (0x2F26B136), (0x55631269), (0xEF1213E1), + (0xA56AB844), (0xAA4B1D64), (0x64341EA9), (0x0CE9DB48), (0x460C2144), + (0xADC50205), (0x515C472F), (0x304C29BD), (0x76AF8711), (0x557CADB7), + (0x2A9BBC8E), (0xE50E145B), (0x9C2031FD), (0xD9121A8C), (0xF51A96FD), + (0x45CCBEBF), (0x5F884871), (0x66DAE291), (0x95ADC9E5), (0x33CF304D), + (0x23C87DCE), (0xA7014FB3), (0xFB351E71), (0x8D60F66F), (0xBFD6DDD5), + (0x151FE6F1), (0xDCC7935A), (0x0CACFBF0), (0xEE55A371), (0xBE46B755), + (0x0F79DCD2), (0x23DFF76D), (0x83DE76D7), (0x8B0E3AEE), (0xB01BFB44), + (0x4E3619FA), (0xA19F9E64), (0xBD492AD9), (0x0899E45F), (0x8156E41D), + (0x5DA539BA), (0x0AF35B2C), (0xDB89BAAE), (0xA128C966), (0xA02CEAEE), + (0xC5A1B291), (0x08CBA93E), (0x90FD887A), (0x60304386), (0x6A59F1EA), + (0xA461E67B), (0xC1622B76), (0x6FA2F906), (0xAA3A401A), (0xB68EA47B), + (0xC617A889), (0x6024A57B), (0x2DD53555), (0xF1FFEA30), (0x813A8050), + (0x8D1A21B4), (0xFFE72CF7), (0xA37415E1), (0x30A2C830), (0xA3A1CA28), + (0x4C5E3586), (0x309861B9), (0x1F49850D), (0x6164C748), (0x9D7048E5), + (0xC124569E), (0xCCB0E111), (0x15B2BB86), (0x18371D9C), (0xB2ABD94D), + (0x8EC656B3), (0xBF010995)}; + +static const INT __twiddles_mips_fft32_512[] = { + (0x7FFFFFFF), (0x00000000), (0x7FFD8859), (0xFE6DE2E0), (0x7FF62181), + (0xFCDBD540), (0x7FE9CBBE), (0xFB49E6A3), (0x7FD8878C), (0xF9B82681), + (0x7FC25595), (0xF826A464), (0x7FA736B2), (0xF6956FB7), (0x7F872BF2), + (0xF5049800), (0x7F62368D), (0xF3742C9D), (0x7F3857F4), (0xF1E43D1C), + (0x7F0991C3), (0xF054D8DA), (0x7ED5E5C6), (0xEEC60F3C), (0x7E9D55FB), + (0xED37EF91), (0x7E5FE490), (0xEBAA8944), (0x7E1D93EA), (0xEA1DEBC6), + (0x7DD6668D), (0xE8922621), (0x7D8A5F3C), (0xE70747B9), (0x7D3980ED), + (0xE57D5FE4), (0x7CE3CEB0), (0xE3F47D95), (0x7C894BDA), (0xE26CB010), + (0x7C29FBEF), (0xE0E6068F), (0x7BC5E296), (0xDF609002), (0x7B5D03A1), + (0xDDDC5B4F), (0x7AEF6325), (0xDC59778B), (0x7A7D0559), (0xDAD7F3A2), + (0x7A05EEA8), (0xD957DE6F), (0x798A23A8), (0xD7D946C3), (0x7909A935), + (0xD65C3B98), (0x78848419), (0xD4E0CB28), (0x77FAB98A), (0xD367044F), + (0x776C4ED9), (0xD1EEF59D), (0x76D94983), (0xD078AD93), (0x7641AF32), + (0xCF043A9E), (0x75A585D9), (0xCD91AB55), (0x7504D34C), (0xCC210D8B), + (0x745F9DD3), (0xCAB26FB2), (0x73B5EBCF), (0xC945DFEB), (0x7307C3C9), + (0xC7DB6C45), (0x72552C79), (0xC67322B9), (0x719E2CDE), (0xC50D1164), + (0x70E2CBCD), (0xC3A945A1), (0x7023109C), (0xC247CD62), (0x6F5F02CF), + (0xC0E8B67E), (0x6E96A995), (0xBF8C0DD8), (0x6DCA0D27), (0xBE31E1BF), + (0x6CF934E8), (0xBCDA3EAE), (0x6C242969), (0xBB8532C0), (0x6B4AF258), + (0xBA32CA42), (0x6A6D98A1), (0xB8E31318), (0x698C2487), (0xB79619C6), + (0x68A69E72), (0xB64BEAB9), (0x67BD0FCC), (0xB5049380), (0x66CF8103), + (0xB3C01FE9), (0x65DDFBD6), (0xB27E9D43), (0x64E8894A), (0xB140178C), + (0x63EF3286), (0xB0049AA9), (0x62F201C4), (0xAECC338B), (0x61F10027), + (0xAD96ED77), (0x60EC383A), (0xAC64D51F), (0x5FE3B366), (0xAB35F58C), + (0x5ED77C86), (0xAA0A5B2C), (0x5DC79D9C), (0xA8E2112C), (0x5CB420CD), + (0xA7BD229A), (0x5B9D1166), (0xA69B9B7D), (0x5A827978), (0xA57D8646), + (0x5964649B), (0xA462EEB2), (0x5842DD7E), (0xA34BDF4B), (0x571DEEED), + (0xA238627B), (0x55F5A4ED), (0xA1288391), (0x54CA0A2E), (0xA01C4C5C), + (0x539B2AFB), (0x9F13C7DC), (0x52691241), (0x9E0EFF9D), (0x5133CC8F), + (0x9D0DFE52), (0x4FFB6572), (0x9C10CD90), (0x4EBFE88F), (0x9B1776CB), + (0x4D8162D8), (0x9A22043F), (0x4C3FDFCC), (0x99307EC5), (0x4AFB6C9B), + (0x9842F048), (0x49B41562), (0x975961A2), (0x4869E657), (0x9673DB8C), + (0x471CED05), (0x95926772), (0x45CD356F), (0x94B50D74), (0x447ACD5D), + (0x93DBD6AA), (0x4325C102), (0x9306CAE7), (0x41CE1ECD), (0x9235F32C), + (0x4073F245), (0x9169567D), (0x3F17499F), (0x90A0FD42), (0x3DB8324C), + (0x8FDCEF37), (0x3C56BAB5), (0x8F1D3461), (0x3AF2EEBA), (0x8E61D331), + (0x398CDCF3), (0x8DAAD35D), (0x38249413), (0x8CF83C62), (0x36BA2034), + (0x8C4A1440), (0x354D9033), (0x8BA06221), (0x33DEF21F), (0x8AFB2C8E), + (0x326E5505), (0x8A5A7A4D), (0x30FBC547), (0x89BE50C2), (0x2F875216), + (0x8926B65A), (0x2E110ABF), (0x8893B14A), (0x2C98FBD1), (0x88054682), + (0x2B1F34BC), (0x877B7BDD), (0x29A3C40F), (0x86F656AC), (0x2826B95E), + (0x8675DC62), (0x26A82174), (0x85FA114F), (0x25280C05), (0x8582FA8C), + (0x23A688D3), (0x85109CF7), (0x2223A4D2), (0x84A2FC68), (0x209F6FE1), + (0x843A1D62), (0x1F19F9F0), (0x83D60431), (0x1D935011), (0x8376B42E), + (0x1C0B824E), (0x831C314A), (0x1A829FC0), (0x82C67F00), (0x18F8B888), + (0x8275A0D1), (0x176DD9E1), (0x82299974), (0x15E213FD), (0x81E26C0B), + (0x1455771D), (0x81A01B80), (0x12C81090), (0x8162AA0A), (0x1139F0A7), + (0x812A1A36), (0x0FAB26B9), (0x80F66E30), (0x0E1BC326), (0x80C7A813), + (0x0C8BD356), (0x809DC971), (0x0AFB67B2), (0x8078D407), (0x096A90AB), + (0x8058C955), (0x07D95BB6), (0x803DAA6D), (0x0647D949), (0x80277871), + (0x04B618DF), (0x8016343D), (0x03242AF6), (0x8009DE81), (0x01921D0C), + (0x800277A7), (0xFFFFFFA3), (0x80000002), (0xFE6DE338), (0x800277A6), + (0xFCDBD54E), (0x8009DE7F), (0xFB49E665), (0x80163444), (0xF9B826FB), + (0x8027786E), (0xF826A48E), (0x803DAA69), (0xF6956F99), (0x8058C950), + (0xF5049793), (0x8078D418), (0xF3742CEE), (0x809DC96B), (0xF1E43D1E), + (0x80C7A80C), (0xF054D88D), (0x80F66E47), (0xEEC60F9D), (0x812A1A2D), + (0xED37EFB3), (0x8162AA00), (0xEBAA8927), (0x81A01B75), (0xEA1DEB4A), + (0x81E26C2C), (0xE8922662), (0x82299967), (0xE70747BB), (0x8275A0C3), + (0xE57D5F89), (0x82C67F27), (0xE3F47DF5), (0x831C313B), (0xE26CB031), + (0x8376B41E), (0xE0E60653), (0x83D60420), (0xDF608F69), (0x843A1D92), + (0xDDDC5B6F), (0x84A2FC55), (0xDC59776E), (0x85109CE4), (0xDAD7F348), + (0x8582FAC2), (0xD957DECD), (0x85FA113A), (0xD7D946E3), (0x8675DC4D), + (0xD65C3B40), (0x86F656E9), (0xD4E0CB84), (0x877B7BC6), (0xD367046F), + (0x8805466A), (0xD1EEF581), (0x8893B132), (0xD078AD3C), (0x8926B6A0), + (0xCF043AF8), (0x89BE50A8), (0xCD91AB39), (0x8A5A7A32), (0xCC210D35), + (0x8AFB2CDB), (0xCAB2700B), (0x8BA06204), (0xC945E00A), (0x8C4A1423), + (0xC7DB6C2A), (0x8CF83C44), (0xC6732265), (0x8DAAD3B2), (0xC50D109F), + (0x8E61D388), (0xC3A94669), (0x8F1D33C8), (0xC247CDF0), (0x8FDCEF16), + (0xC0E8B69C), (0x90A0FD21), (0xBF8C0DF6), (0x9169565A), (0xBE31E16E), + (0x9235F309), (0xBCDA3E5E), (0x9306CB49), (0xBB853205), (0x93DBD70E), + (0xBA32CB35), (0x94B50D09), (0xB8E3139E), (0x95926705), (0xB79619E2), + (0x9673DB66), (0xB64BEAD5), (0x9759617B), (0xB5049334), (0x9842F06B), + (0xB3C01F9D), (0x99307F35), (0xB27E9C92), (0x9A2204B0), (0xB140180C), + (0x9B177652), (0xB0049B27), (0x9C10CD15), (0xAECC33A5), (0x9D0DFE27), + (0xAD96ED91), (0x9E0EFFC3), (0xAC64D4D8), (0x9F13C803), (0xAB35F545), + (0xA01C4CD8), (0xAA0A5A88), (0xA128840F), (0xA8E211A2), (0xA23861F5), + (0xA7BD2310), (0xA34BDEC3), (0xA69B9B96), (0xA462EE82), (0xA57D865E), + (0xA57D8670), (0xA462EE70), (0xA69B9BA8), (0xA34BDEB2), (0xA7BD2322), + (0xA23861E4), (0xA8E211B5), (0xA12883FE), (0xAA0A5A9B), (0xA01C4CC7), + (0xAB35F559), (0x9F13C7F2), (0xAC64D4EB), (0x9E0EFFB3), (0xAD96EDA5), + (0x9D0DFE16), (0xAECC33B9), (0x9C10CD05), (0xB0049B3B), (0x9B177642), + (0xB1401820), (0x9A2204A1), (0xB27E9CA6), (0x99307F26), (0xB3C01FB2), + (0x9842F05C), (0xB5049349), (0x9759616C), (0xB64BEAEA), (0x9673DB57), + (0xB79619F7), (0x959266F7), (0xB8E313B4), (0x94B50E13), (0xBA32C99E), + (0x93DBD700), (0xBB85321A), (0x9306CB3C), (0xBCDA3E74), (0x9235F2FC), + (0xBE31E184), (0x9169564D), (0xBF8C0E0C), (0x90A0FD14), (0xC0E8B6B2), + (0x8FDCEF09), (0xC247CE07), (0x8F1D34AD), (0xC3A944BC), (0x8E61D37C), + (0xC50D10B6), (0x8DAAD3A6), (0xC673227C), (0x8CF83C39), (0xC7DB6C41), + (0x8C4A1418), (0xC945E021), (0x8BA061F9), (0xCAB27022), (0x8AFB2C68), + (0xCC210E37), (0x8A5A7A8D), (0xCD91AA66), (0x89BE5100), (0xCF043A24), + (0x8926B697), (0xD078AD53), (0x8893B128), (0xD1EEF599), (0x88054661), + (0xD3670487), (0x877B7BBD), (0xD4E0CB9C), (0x86F6568E), (0xD65C3C4A), + (0x8675DC95), (0xD7D94608), (0x85FA1180), (0xD957DDF1), (0x8582FABB), + (0xDAD7F360), (0x85109CDD), (0xDC597787), (0x84A2FC4F), (0xDDDC5B88), + (0x843A1D4B), (0xDF60907A), (0x83D603DC), (0xE0E60764), (0x8376B454), + (0xE26CAF51), (0x831C316D), (0xE3F47D14), (0x82C67F21), (0xE57D5FA2), + (0x8275A0BE), (0xE70747D4), (0x82299962), (0xE892267C), (0x81E26BFB), + (0xEA1DEC5F), (0x81A01B48), (0xEBAA8A3D), (0x8162AA22), (0xED37EECF), + (0x812A1A4C), (0xEEC60EB9), (0x80F66E44), (0xF054D8A6), (0x80C7A809), + (0xF1E43D38), (0x809DC968), (0xF3742D08), (0x8078D3FF), (0xF50498AB), + (0x8058C93B), (0xF69570B2), (0x803DAA77), (0xF826A3A8), (0x80277879), + (0xF9B82615), (0x80163443), (0xFB49E67F), (0x8009DE7E), (0xFCDBD568), + (0x800277A6), (0xFE6DE352), (0x465220BB), (0xC66E1FFC), (0x2C61D356), + (0xAFFB176D), (0x88067E23), (0x3796F008), (0xC8D128F3), (0xB661A5FA), + (0xF19CE4F0), (0x3F7D0345), (0xE97E6030), (0x4ABA91CF), (0xDEEDAB0C), + (0x35FD1D77), (0xDD636439), (0x2F8B794C), (0x764E1D32), (0x7A8D0B1B), + (0x8EACB27F), (0x577AD67B), (0x2B3FE2C5), (0x8ACD024A), (0xEDF5C42C), + (0xF1CA951C), (0xB98B6D04), (0x6D12B864), (0x50E74D08), (0x73D1503B), + (0xC7D3F6A9), (0x1F365E97), (0xE1340E59), (0x89D21B9D), (0x9B756733), + (0x9024CD50), (0xE2C7FF52), (0xD9F061EF), (0x77151392), (0xA0E4A004), + (0x60BE820F), (0xC7603BAF), (0xA62E3DA9), (0xA400E11F), (0x155111D4), + (0x9030A374), (0x14185124), (0x8D043A00), (0x50945258), (0x20A6653E), + (0xA19BA8B9), (0x3CFBE692), (0x91471D98), (0x0B9D03FF), (0xA5BA8E29), + (0xFFC8EB22), (0x142CB1B0), (0x55317319), (0x33ADC77C), (0xF69BADCE), + (0x78423D3C), (0xBE67BBF0), (0x7D88BD15), (0x1E9EF673), (0x512098B3), + (0x326A3D3D), (0x161EF3B6), (0x0E4C4ED5), (0x4E9F9982), (0xD0AB6A36), + (0xF17DD377), (0x5E53F31C), (0xBE9112EA), (0x3DE1B0FF), (0xD7F39AE7), + (0xA34B9635), (0x49CFEE6C), (0x8A063AC6), (0xBA79BC0D), (0x6A588782), + (0x439BE593), (0x0A5F7E8D), (0xD2FC2561), (0x4698AC8F), (0x247C3BC2), + (0x5826523D), (0x4D2BD753), (0x4B8BCC17), (0x9B743503), (0x9F84E434), + (0x8B97B41A), (0x3CFCE75F), (0x32D2D487), (0x3E80B4AF), (0x42F8B0EA), + (0xEC0C81EE), (0x17279309), (0x681FA0F3), (0x8BAD208E), (0xD11792C6), + (0xF1FF07B3), (0x21338050), (0x8A1A21A4), (0xFF0358D8), (0x416C13C1), + (0x46348858), (0x83820519), (0xABC08822), (0x6A1A5200), (0x0C83122A), + (0xA67FDF06), (0x0629F970), (0xEFAA2743), (0x0C00AD95), (0xFF09F5CF), + (0xC784DB8B), (0xCB00BA7D), (0x6220909F), (0x7149B7DF), (0x5BD3EBEC), + (0x0485EF71), (0x07FE23B1), (0x80737668), (0x42A32645), (0xD6EDBB18), + (0x407E72C5), (0x901402E0), (0x0C1B7905), (0x01CE11FC), (0x00C64914), + (0x3037978A), (0xFABC9190), (0x43A0AC89), (0xB9998370), (0xD6D69209), + (0xF132455E), (0x9DAFF482), (0xA2D635C2), (0xBD976B5E), (0x79ED93ED), + (0x7D42CA22), (0x2E23F9C1), (0xCF0E7521), (0x96D88AC1), (0x420C2845), + (0x1E19573D), (0xF8FE9279), (0xC1495100), (0x201249C2), (0x8B183723), + (0x450615A5), (0x004C0112), (0x85EB5235), (0x1BD8BD48), (0xA2914F03), + (0x51420EAC), (0xCE788470), (0x0508030B), (0xA4CD2A6C), (0x9626C062), + (0xF88D2DE5), (0xA9D6B399), (0xB3C57BFD), (0xCB1E9C4C), (0x004A5094), + (0xD0CBC42A), (0x3BE1A694), (0x3C353FA7), (0xA5697C57), (0xFE961665), + (0xED6B7C7D), (0x433DCF8D), (0xDA7D6C24), (0x407112C1), (0x4B9D285D), + (0x6C9A2F57), (0x1BF9FAEF), (0x4EE3E2E9), (0xE5AE7E92), (0x60A11D3F), + (0x4B441B63), (0xC8419BB1), (0x2C4F6DDD), (0xCEC3CF6D), (0x325A65CA), + (0x818FC6A4), (0xC55E5E5B), (0x277445A3), (0x6B3289F7), (0x09147D55), + (0x4F378D53), (0x588B0DC8), (0xF70BA347), (0xCBC43FAE), (0xD98E6639), + (0x07AF9ED0), (0xE2E6305A), (0x5E003571), (0x18523E7A), (0xF70D1E27), + (0xD7288950), (0x12C11132), (0xFF1C9D17), (0x318050F1), (0x1A219821), + (0xBF21998A), (0x6C13C1FF), (0x8C605861), (0x0A183954), (0x7BE4C1B6), + (0xA2CBC410), (0x7CC00A55), (0x5E58A973), (0x1122EF86), (0x80568E39), + (0x2310C300), (0x0E152D0E), (0x9E017C1C), (0x851DFC26), (0xD1B1E662), + (0x81BA10B0), (0x96C2E977), (0x8688E419), (0x97C94989), (0x250D535E), + (0x35FDE732), (0x147AD183), (0xCF9D75C0), (0x6B2C183C), (0x1D326489), + (0xC0807D98), (0xC081622E), (0x15C87B87), (0x7404598C), (0xFC3C7FA6), + (0x28BA8CF5), (0xE311EA9B), (0xEABFD4A5), (0x8768834A), (0x0F7D7440), + (0x40593152), (0xCF1E8BF5), (0xE32017B6), (0x39E66070), (0x560ECE9D), + (0xF4132C77), (0x722945C1), (0x96ECB5D5), (0x0C100C06), (0x30E96C02), + (0xE0B0159B), (0x163A40CB), (0x1B28B750), (0x11420E11), (0x34DC5981), + (0xD2769C3C), (0x569402D0), (0xE4F157C0), (0x120DF24C), (0x40D86153), + (0x1942CD11), (0x22484C3B), (0x8B299144), (0x58F1AAF8), (0xB2CD4777), + (0x4A53AB02), (0x55A5DAD4), (0xC8D58D79), (0x6CAEC011), (0x1C955C84), + (0xDE08A6C6), (0xD402AF7D), (0x695E6FA4), (0x4DA863B9), (0x5118070C), + (0x5A97EF1C), (0x8880B388), (0x4D596B2D), (0x37D74DCF), (0x58138B38), + (0x5B7BCD4E), (0xAE6C4422), (0x4E5D1AF1), (0xDE7396A5), (0xB442F217), + (0x0DF7A006), (0x96EEF8A2), (0xE2847B26), (0x68B9F67B), (0x8FE1FA65), + (0xE0A87E56), (0x1BE8FC4C), (0xBBD65F9D), (0xE6F02C9D), (0x867C6EEC), + (0x43FAB725), (0xA4144419), (0x69BB6AAF), (0xCE27B744), (0x022241A9), + (0xC05DF14E), (0x8050F1FF), (0x218C2131), (0xBE25941A), (0x9041CD06), + (0x1EE8A9C0), (0xD530FEDD), (0x7495C808), (0x050918A6), (0x3CE732E9), + (0xF87262FC), (0x01B812F1), (0x1FBA4842), (0x3E86C7F2), (0x270DB358), + (0xF9D22834), (0x74D4F469), (0x9A6E87D2), (0x8CBB0A50), (0xC0784B92), + (0x278DA581), (0x9221A7D5), (0xDE801B54), (0x4B531FDA), (0xC8B91F91), + (0x7A90DA40), (0x2967A429), (0x50CC1D8D), (0x9AE9110E), (0x50F250EE), + (0xD695B072), (0xFC7A5718), (0x1F1A26E6), (0x7D5ADD4D), (0xC8978597), + (0xEB326DC3), (0x384E9824), (0xC3B9D78C), (0xD8D2E214), (0xEFFBB048), + (0x00AB7714), (0x9D89CA13), (0xF70688D0), (0xADDA3A37), (0x5FBE5943), + (0x4ED9D613), (0x8A9DCC93), (0x19814236), (0x09A68BCC), (0xCEAC33AC), + (0x0BA70BB3), (0x326272E1), (0x2A8C6D20), (0x23083D0B), (0xFA809C02), + (0x5825C6C2), (0x061B4695), (0x8DB97748), (0x5071E584), (0x08760959), + (0x44EA8D04), (0x5CE6E2AA), (0x009AD176), (0xAEC64F19), (0xCADDA632), + (0x8D795445), (0x16E3EA24), (0xF12648CA), (0xD5CC350C), (0x615EBAD7), + (0x4E769FB6), (0x6C5EB380), (0x5BB46425), (0xEAB6C77C), (0x10945408), + (0xC1291B86), (0x913B71A5), (0x003BA329), (0x91812854), (0xE200CB12), + (0x7A4696A8), (0x76E55D25), (0xD6D3C577), (0x8B1B79B1), (0x296B04CD), + (0xA024CC35), (0x3341A477), (0x8EC12358), (0xF5982B2F), (0x36F120C9), + (0x79DBE799), (0xED74F092), (0xA1031AE3), (0xB2D98C6B), (0x358CAB73), + (0x41153C19), (0x474D4548), (0xA7E834A9), (0x999738AE), (0x50F1FFE8), + (0x88612F80), (0xFD931A21), (0x23839ABD), (0xBE604701), (0x812274B9), + (0x4CA9EA32), (0xE5F2D207), (0xC1CF4653), (0x43561B23), (0x53B2E277), + (0x4F2B00EC), (0xF2B3BA80), (0xFC708CC5), (0xE7F63F00), (0x26120342), + (0x1A49C7A8), (0xA9350A7C), (0xE530A06C), (0x5CB9E550), (0xB1672913), + (0x65FA76F9), (0xC9F92DCA), (0x7D4E9195), (0x4DBB8265), (0x2036E26C), + (0xEDC026E6), (0xB9A617E0), (0x6469F0EE), (0xE9DAABB2), (0x26063210), + (0xAC545DF4), (0x134E035A), (0x216EDE10), (0xEC81158D), (0x122A2CAE), + (0xA263D0E1), (0x6CA1FB28), (0xBE287DF0), (0x548104E8), (0x35987D93), + (0xBC3E549C), (0x3ACEFD64), (0x3348CD92), (0x914472FD), (0x80F28098), + (0xDF3FABCD), (0x24D840AC), (0xBA95321C), (0xDC211D20), (0x15041942), + (0x61858ABD), (0x546084A1), (0xCEDC07F4), (0xEAB2DE00), (0x045BC1E8), + (0x82B2AE86), (0xE4BF2823), (0x9A01B47A), (0x1769438E), (0x015C7986), + (0x5FDFF97D), (0x5F28D62C), (0x83C84C8C), (0xDBAC601A), (0x1AE2844F), + (0x79F9DC1C), (0x01C3AB5C), (0xC971D839), (0x44DEA398), (0xC0A64EA1), + (0x387E24A5), (0x0600D59F), (0x5169B371), (0xEC782B6B), (0xF7FF769D), + (0x317B0AE8), (0xE33846C7), (0x2FE05849), (0x03273853), (0x2ED27A88), + (0x24DF4343), (0xFB03C70F), (0x82783231), (0xD31C0D29), (0xADC5BD8B), + (0x7D024F1B), (0x91C18D19), (0xA8EE58E2), (0x4C23A59F), (0xC61DCA9F), + (0x03BC91EC), (0x51986147), (0x05B8BE24), (0x872AC918), (0x8050F1FF), + (0x2184812F), (0xB20D941A), (0x9141CB0C), (0xF600A340), (0x80E82AC2), + (0x66028631), (0x120FFA45), (0x889F24CB), (0x81F0BB27), (0x3100D51A), + (0x2309A0B3), (0xAE004718), (0xAA584A8D), (0x9432DD2E), (0xDD0E93FA), + (0xC12993A6), (0x6E28035D), (0x9BF7772B), (0x1D608C32)}; + +static const INT __twiddles_mips_fft32_1024[] = { + (0x7FFFFFFF), (0x00000000), (0x7FFF6215), (0xFF36F078), (0x7FFD8859), + (0xFE6DE2E0), (0x7FFA72D0), (0xFDA4D929), (0x7FF62181), (0xFCDBD540), + (0x7FF09476), (0xFC12D91B), (0x7FE9CBBE), (0xFB49E6A3), (0x7FE1C76A), + (0xFA80FFCE), (0x7FD8878C), (0xF9B82681), (0x7FCE0C3D), (0xF8EF5CBC), + (0x7FC25595), (0xF826A464), (0x7FB563B2), (0xF75DFF6B), (0x7FA736B2), + (0xF6956FB7), (0x7F97CEBB), (0xF5CCF73E), (0x7F872BF2), (0xF5049800), + (0x7F754E7E), (0xF43C53CB), (0x7F62368D), (0xF3742C9D), (0x7F4DE450), + (0xF2AC2473), (0x7F3857F4), (0xF1E43D1C), (0x7F2191B2), (0xF11C7895), + (0x7F0991C3), (0xF054D8DA), (0x7EF05860), (0xEF8D5FC8), (0x7ED5E5C6), + (0xEEC60F3C), (0x7EBA3A38), (0xEDFEE930), (0x7E9D55FB), (0xED37EF91), + (0x7E7F3954), (0xEC71244A), (0x7E5FE490), (0xEBAA8944), (0x7E3F5800), + (0xEAE4208A), (0x7E1D93EA), (0xEA1DEBC6), (0x7DFA98A7), (0xE957ED00), + (0x7DD6668D), (0xE8922621), (0x7DB0FDF5), (0xE7CC9912), (0x7D8A5F3C), + (0xE70747B9), (0x7D628AC7), (0xE642341C), (0x7D3980ED), (0xE57D5FE4), + (0x7D0F4217), (0xE4B8CD16), (0x7CE3CEB0), (0xE3F47D95), (0x7CB72721), + (0xE3307347), (0x7C894BDA), (0xE26CB010), (0x7C5A3D52), (0xE1A935F1), + (0x7C29FBEF), (0xE0E6068F), (0x7BF88830), (0xE02323EA), (0x7BC5E296), + (0xDF609002), (0x7B920B86), (0xDE9E4C5B), (0x7B5D03A1), (0xDDDC5B4F), + (0x7B26CB49), (0xDD1ABE41), (0x7AEF6325), (0xDC59778B), (0x7AB6CB9A), + (0xDB98888E), (0x7A7D0559), (0xDAD7F3A2), (0x7A4210DE), (0xDA17BA63), + (0x7A05EEA8), (0xD957DE6F), (0x79C89F71), (0xD898621A), (0x798A23A8), + (0xD7D946C3), (0x794A7C11), (0xD71A8EBA), (0x7909A935), (0xD65C3B98), + (0x78C7AB9E), (0xD59E4EF9), (0x78848419), (0xD4E0CB28), (0x78403321), + (0xD423B181), (0x77FAB98A), (0xD367044F), (0x77B417D4), (0xD2AAC4EB), + (0x776C4ED9), (0xD1EEF59D), (0x77235F35), (0xD13397FA), (0x76D94983), + (0xD078AD93), (0x768E0EA9), (0xCFBE38AD), (0x7641AF32), (0xCF043A9E), + (0x75F42C0B), (0xCE4AB5A6), (0x75A585D9), (0xCD91AB55), (0x7555BD47), + (0xCCD91D37), (0x7504D34C), (0xCC210D8B), (0x74B2C87B), (0xCB697DA0), + (0x745F9DD3), (0xCAB26FB2), (0x740B53ED), (0xC9FBE50E), (0x73B5EBCF), + (0xC945DFEB), (0x735F662F), (0xC89061D1), (0x7307C3C9), (0xC7DB6C45), + (0x72AF05AB), (0xC727017A), (0x72552C79), (0xC67322B9), (0x71FA3948), + (0xC5BFD232), (0x719E2CDE), (0xC50D1164), (0x71410800), (0xC45AE1D1), + (0x70E2CBCD), (0xC3A945A1), (0x708378F4), (0xC2F83E1B), (0x7023109C), + (0xC247CD62), (0x6FC19376), (0xC197F4BB), (0x6F5F02CF), (0xC0E8B67E), + (0x6EFB5F1D), (0xC03A137E), (0x6E96A995), (0xBF8C0DD8), (0x6E30E32F), + (0xBEDEA73A), (0x6DCA0D27), (0xBE31E1BF), (0x6D6227FA), (0xBD85BE33), + (0x6CF934E8), (0xBCDA3EAE), (0x6C8F3538), (0xBC2F6544), (0x6C242969), + (0xBB8532C0), (0x6BB812C5), (0xBADBA934), (0x6B4AF258), (0xBA32CA42), + (0x6ADCC976), (0xB98A97F6), (0x6A6D98A1), (0xB8E31318), (0x69FD6132), + (0xB83C3DB1), (0x698C2487), (0xB79619C6), (0x6919E326), (0xB6F0A81D), + (0x68A69E72), (0xB64BEAB9), (0x68325786), (0xB5A7E331), (0x67BD0FCC), + (0xB5049380), (0x6746C7D1), (0xB461FC6A), (0x66CF8103), (0xB3C01FE9), + (0x66573CD5), (0xB31EFFF0), (0x65DDFBD6), (0xB27E9D43), (0x6563BF7E), + (0xB1DEF9D2), (0x64E8894A), (0xB140178C), (0x646C59CC), (0xB0A1F730), + (0x63EF3286), (0xB0049AA9), (0x637114AB), (0xAF68037B), (0x62F201C4), + (0xAECC338B), (0x6271FA69), (0xAE312B94), (0x61F10027), (0xAD96ED77), + (0x616F148E), (0xACFD7B13), (0x60EC383A), (0xAC64D51F), (0x60686CC0), + (0xABCCFD75), (0x5FE3B366), (0xAB35F58C), (0x5F5E0DC8), (0xAA9FBF38), + (0x5ED77C86), (0xAA0A5B2C), (0x5E500140), (0xA975CB39), (0x5DC79D9C), + (0xA8E2112C), (0x5D3E523E), (0xA84F2DB4), (0x5CB420CD), (0xA7BD229A), + (0x5C290AA0), (0xA72BF148), (0x5B9D1166), (0xA69B9B7D), (0x5B1035C7), + (0xA60C21E8), (0x5A827978), (0xA57D8646), (0x59F3DE30), (0xA4EFCA51), + (0x5964649B), (0xA462EEB2), (0x58D40E75), (0xA3D6F51F), (0x5842DD7E), + (0xA34BDF4B), (0x57B0D265), (0xA2C1ADDA), (0x571DEEED), (0xA238627B), + (0x568A3482), (0xA1AFFE81), (0x55F5A4ED), (0xA1288391), (0x556040E2), + (0xA0A1F24F), (0x54CA0A2E), (0xA01C4C5C), (0x543302A5), (0x9F979356), + (0x539B2AFB), (0x9F13C7DC), (0x53028507), (0x9E90EB88), (0x52691241), + (0x9E0EFF9D), (0x51CED486), (0x9D8E05AD), (0x5133CC8F), (0x9D0DFE52), + (0x5097FC3C), (0x9C8EEB1A), (0x4FFB6572), (0x9C10CD90), (0x4F5E08EB), + (0x9B93A649), (0x4EBFE88F), (0x9B1776CB), (0x4E2105E4), (0x9A9C4048), + (0x4D8162D8), (0x9A22043F), (0x4CE1002B), (0x99A8C340), (0x4C3FDFCC), + (0x99307EC5), (0x4B9E03B1), (0x98B93843), (0x4AFB6C9B), (0x9842F048), + (0x4A581C83), (0x97CDA844), (0x49B41562), (0x975961A2), (0x490F57FF), + (0x96E61CED), (0x4869E657), (0x9673DB8C), (0x47C3C202), (0x96029E99), + (0x471CED05), (0x95926772), (0x46756827), (0x9523369D), (0x45CD356F), + (0x94B50D74), (0x452456E9), (0x9447ED4D), (0x447ACD5D), (0x93DBD6AA), + (0x43D09AD9), (0x9370CADA), (0x4325C102), (0x9306CAE7), (0x427A417D), + (0x929DD7D5), (0x41CE1ECD), (0x9235F32C), (0x412158E3), (0x91CF1CE3), + (0x4073F245), (0x9169567D), (0x3FC5ECA0), (0x9104A0F4), (0x3F17499F), + (0x90A0FD42), (0x3E680AF3), (0x903E6C5D), (0x3DB8324C), (0x8FDCEF37), + (0x3D07C23C), (0x8F7C873A), (0x3C56BAB5), (0x8F1D3461), (0x3BA51E4D), + (0x8EBEF810), (0x3AF2EEBA), (0x8E61D331), (0x3A402DB4), (0x8E05C6AA), + (0x398CDCF3), (0x8DAAD35D), (0x38D8FE32), (0x8D50FA2B), (0x38249413), + (0x8CF83C62), (0x376F9E88), (0x8CA099FB), (0x36BA2034), (0x8C4A1440), + (0x36041AD7), (0x8BF4AC06), (0x354D9033), (0x8BA06221), (0x3496820A), + (0x8B4D375F), (0x33DEF21F), (0x8AFB2C8E), (0x3326E323), (0x8AAA42E0), + (0x326E5505), (0x8A5A7A4D), (0x31B54A79), (0x8A0BD403), (0x30FBC547), + (0x89BE50C2), (0x3041C737), (0x8971F14B), (0x2F875216), (0x8926B65A), + (0x2ECC67AF), (0x88DCA0A9), (0x2E110ABF), (0x8893B14A), (0x2D553B35), + (0x884BE838), (0x2C98FBD1), (0x88054682), (0x2BDC4E63), (0x87BFCCD5), + (0x2B1F34BC), (0x877B7BDD), (0x2A61B0AF), (0x87385443), (0x29A3C40F), + (0x86F656AC), (0x28E571A3), (0x86B5840E), (0x2826B95E), (0x8675DC62), + (0x27679E06), (0x8637609A), (0x26A82174), (0x85FA114F), (0x25E84581), + (0x85BDEF19), (0x25280C05), (0x8582FA8C), (0x246777D0), (0x85493482), + (0x23A688D3), (0x85109CF7), (0x22E541E0), (0x84D934C0), (0x2223A4D2), + (0x84A2FC68), (0x2161B389), (0x846DF472), (0x209F6FE1), (0x843A1D62), + (0x1FDCDBBB), (0x840777B9), (0x1F19F9F0), (0x83D60431), (0x1E56CA6E), + (0x83A5C2C5), (0x1D935011), (0x8376B42E), (0x1CCF8CBB), (0x8348D8DF), + (0x1C0B824E), (0x831C314A), (0x1B4732AE), (0x82F0BDDB), (0x1A829FC0), + (0x82C67F00), (0x19BDCC63), (0x829D7553), (0x18F8B888), (0x8275A0D1), + (0x18336710), (0x824F0211), (0x176DD9E1), (0x82299974), (0x16A812E3), + (0x82056754), (0x15E213FD), (0x81E26C0B), (0x151BDF19), (0x81C0A7F1), + (0x1455771D), (0x81A01B80), (0x138EDBF8), (0x8180C6B6), (0x12C81090), + (0x8162AA0A), (0x120116D2), (0x8145C5C8), (0x1139F0A7), (0x812A1A36), + (0x10729FFB), (0x810FA798), (0x0FAB26B9), (0x80F66E30), (0x0EE387CD), + (0x80DE6E5A), (0x0E1BC326), (0x80C7A813), (0x0D53DBAF), (0x80B21BB4), + (0x0C8BD356), (0x809DC971), (0x0BC3AC07), (0x808AB17E), (0x0AFB67B2), + (0x8078D407), (0x0A330844), (0x8068313B), (0x096A90AB), (0x8058C955), + (0x08A200D7), (0x804A9C53), (0x07D95BB6), (0x803DAA6D), (0x0710A337), + (0x8031F3C3), (0x0647D949), (0x80277871), (0x057EFFDC), (0x801E3892), + (0x04B618DF), (0x8016343D), (0x03ED2743), (0x800F6B8D), (0x03242AF6), + (0x8009DE81), (0x025B26E9), (0x80058D31), (0x01921D0C), (0x800277A7), + (0x00C90F4F), (0x80009DEB), (0xFFFFFFA3), (0x80000002), (0xFF36F0F5), + (0x80009DEB), (0xFE6DE338), (0x800277A6), (0xFDA4D95B), (0x80058D2F), + (0xFCDBD54E), (0x8009DE7F), (0xFC12D902), (0x800F6B8A), (0xFB49E665), + (0x80163444), (0xFA80FF69), (0x801E389A), (0xF9B826FB), (0x8027786E), + (0xF8EF5D0E), (0x8031F3BF), (0xF826A48E), (0x803DAA69), (0xF75DFF6D), + (0x804A9C4E), (0xF6956F99), (0x8058C950), (0xF5CCF701), (0x8068314A), + (0xF5049793), (0x8078D418), (0xF43C543D), (0x808AB177), (0xF3742CEE), + (0x809DC96B), (0xF2AC2495), (0x80B21BAD), (0xF1E43D1E), (0x80C7A80C), + (0xF11C7877), (0x80DE6E52), (0xF054D88D), (0x80F66E47), (0xEF8D5F4B), + (0x810FA7B0), (0xEEC60F9D), (0x812A1A2D), (0xEDFEE972), (0x8145C5BE), + (0xED37EFB3), (0x8162AA00), (0xEC71244C), (0x8180C6AB), (0xEBAA8927), + (0x81A01B75), (0xEAE4202D), (0x81C0A810), (0xEA1DEB4A), (0x81E26C2C), + (0xE957ED61), (0x82056748), (0xE8922662), (0x82299967), (0xE7CC9933), + (0x824F0204), (0xE70747BB), (0x8275A0C3), (0xE64233E0), (0x829D7545), + (0xE57D5F89), (0x82C67F27), (0xE4B8CC9B), (0x82F0BE03), (0xE3F47DF5), + (0x831C313B), (0xE3307388), (0x8348D8D0), (0xE26CB031), (0x8376B41E), + (0xE1A935D4), (0x83A5C2B5), (0xE0E60653), (0x83D60420), (0xE023238F), + (0x840777E8), (0xDF608F69), (0x843A1D92), (0xDE9E4CB9), (0x846DF460), + (0xDDDC5B6F), (0x84A2FC55), (0xDD1ABE62), (0x84D934AE), (0xDC59776E), + (0x85109CE4), (0xDB988872), (0x8549346E), (0xDAD7F348), (0x8582FAC2), + (0xDA17BAC1), (0x85BDEF05), (0xD957DECD), (0x85FA113A), (0xD898623B), + (0x86376085), (0xD7D946E3), (0x8675DC4D), (0xD71A8E9D), (0x86B583F8), + (0xD65C3B40), (0x86F656E9), (0xD59E4EA0), (0x87385481), (0xD4E0CB84), + (0x877B7BC6), (0xD423B1DD), (0x87BFCCBD), (0xD367046F), (0x8805466A), + (0xD2AAC50A), (0x884BE820), (0xD1EEF581), (0x8893B132), (0xD13397A2), + (0x88DCA0EE), (0xD078AD3C), (0x8926B6A0), (0xCFBE3908), (0x8971F132), + (0xCF043AF8), (0x89BE50A8), (0xCE4AB5C6), (0x8A0BD3E8), (0xCD91AB39), + (0x8A5A7A32), (0xCCD91D1C), (0x8AAA42C5), (0xCC210D35), (0x8AFB2CDB), + (0xCB697D4B), (0x8B4D37AC), (0xCAB2700B), (0x8BA06204), (0xC9FBE567), + (0x8BF4ABE9), (0xC945E00A), (0x8C4A1423), (0xC89061B6), (0x8CA099DE), + (0xC7DB6C2A), (0x8CF83C44), (0xC7270126), (0x8D50FA7F), (0xC6732265), + (0x8DAAD3B2), (0xC5BFD1A5), (0x8E05C6FF), (0xC50D109F), (0x8E61D388), + (0xC45AE10D), (0x8EBEF868), (0xC3A94669), (0x8F1D33C8), (0xC2F83EE1), + (0x8F7C86A0), (0xC247CDF0), (0x8FDCEF16), (0xC197F548), (0x903E6C3B), + (0xC0E8B69C), (0x90A0FD21), (0xC03A139B), (0x9104A0D2), (0xBF8C0DF6), + (0x9169565A), (0xBEDEA758), (0x91CF1CC0), (0xBE31E16E), (0x9235F309), + (0xBD85BDE2), (0x929DD837), (0xBCDA3E5E), (0x9306CB49), (0xBC2F6487), + (0x9370CB3D), (0xBB853205), (0x93DBD70E), (0xBADBA879), (0x9447EDB3), + (0xBA32CB35), (0x94B50D09), (0xB98A987D), (0x95233631), (0xB8E3139E), + (0x95926705), (0xB83C3E37), (0x96029E73), (0xB79619E2), (0x9673DB66), + (0xB6F0A839), (0x96E61CC6), (0xB64BEAD5), (0x9759617B), (0xB5A7E34D), + (0x97CDA867), (0xB5049334), (0x9842F06B), (0xB461FC1F), (0x98B93866), + (0xB3C01F9D), (0x99307F35), (0xB31EFF3F), (0x99A8C3B0), (0xB27E9C92), + (0x9A2204B0), (0xB1DEF922), (0x9A9C4109), (0xB140180C), (0x9B177652), + (0xB0A1F7AF), (0x9B93A5CF), (0xB0049B27), (0x9C10CD15), (0xAF6803F9), + (0x9C8EEAEF), (0xAECC33A5), (0x9D0DFE27), (0xAE312BAE), (0x9D8E0581), + (0xAD96ED91), (0x9E0EFFC3), (0xACFD7ACC), (0x9E90EBAF), (0xAC64D4D8), + (0x9F13C803), (0xABCCFD2E), (0x9F97937D), (0xAB35F545), (0xA01C4CD8), + (0xAA9FBE92), (0xA0A1F2CC), (0xAA0A5A88), (0xA128840F), (0xA975CC0F), + (0xA1AFFDFC), (0xA8E211A2), (0xA23861F5), (0xA84F2E2A), (0xA2C1AD53), + (0xA7BD2310), (0xA34BDEC3), (0xA72BF1BC), (0xA3D6F4F0), (0xA69B9B96), + (0xA462EE82), (0xA60C2200), (0xA4EFCA21), (0xA57D865E), (0xA57D8670), + (0xA4EFCA0F), (0xA60C2213), (0xA462EE70), (0xA69B9BA8), (0xA3D6F4DE), + (0xA72BF1CF), (0xA34BDEB2), (0xA7BD2322), (0xA2C1AD42), (0xA84F2E3D), + (0xA23861E4), (0xA8E211B5), (0xA1AFFF45), (0xA975CAA9), (0xA12883FE), + (0xAA0A5A9B), (0xA0A1F2BB), (0xAA9FBEA5), (0xA01C4CC7), (0xAB35F559), + (0x9F97936C), (0xABCCFD41), (0x9F13C7F2), (0xAC64D4EB), (0x9E90EB9E), + (0xACFD7ADF), (0x9E0EFFB3), (0xAD96EDA5), (0x9D8E0571), (0xAE312BC2), + (0x9D0DFE16), (0xAECC33B9), (0x9C8EEADF), (0xAF68040D), (0x9C10CD05), + (0xB0049B3B), (0x9B93A5BF), (0xB0A1F7C3), (0x9B177642), (0xB1401820), + (0x9A9C40F9), (0xB1DEF936), (0x9A2204A1), (0xB27E9CA6), (0x99A8C3A1), + (0xB31EFF54), (0x99307F26), (0xB3C01FB2), (0x98B93857), (0xB461FC33), + (0x9842F05C), (0xB5049349), (0x97CDA858), (0xB5A7E362), (0x9759616C), + (0xB64BEAEA), (0x96E61CB8), (0xB6F0A84E), (0x9673DB57), (0xB79619F7), + (0x96029E64), (0xB83C3E4C), (0x959266F7), (0xB8E313B4), (0x95233623), + (0xB98A9893), (0x94B50E13), (0xBA32C99E), (0x9447EDA5), (0xBADBA88F), + (0x93DBD700), (0xBB85321A), (0x9370CB30), (0xBC2F649D), (0x9306CB3C), + (0xBCDA3E74), (0x929DD829), (0xBD85BDF8), (0x9235F2FC), (0xBE31E184), + (0x91CF1CB3), (0xBEDEA76E), (0x9169564D), (0xBF8C0E0C), (0x9104A0C5), + (0xC03A13B2), (0x90A0FD14), (0xC0E8B6B2), (0x903E6C2F), (0xC197F55F), + (0x8FDCEF09), (0xC247CE07), (0x8F7C8694), (0xC2F83EF8), (0x8F1D34AD), + (0xC3A944BC), (0x8EBEF85C), (0xC45AE123), (0x8E61D37C), (0xC50D10B6), + (0x8E05C6F4), (0xC5BFD1BC), (0x8DAAD3A6), (0xC673227C), (0x8D50FA73), + (0xC727013D), (0x8CF83C39), (0xC7DB6C41), (0x8CA099D3), (0xC89061CD), + (0x8C4A1418), (0xC945E021), (0x8BF4ABDF), (0xC9FBE57E), (0x8BA061F9), + (0xCAB27022), (0x8B4D3738), (0xCB697E4C), (0x8AFB2C68), (0xCC210E37), + (0x8AAA4254), (0xCCD91E1E), (0x8A5A7A8D), (0xCD91AA66), (0x8A0BD442), + (0xCE4AB4F1), (0x89BE5100), (0xCF043A24), (0x8971F188), (0xCFBE3833), + (0x8926B697), (0xD078AD53), (0x88DCA0E4), (0xD13397BA), (0x8893B128), + (0xD1EEF599), (0x884BE817), (0xD2AAC522), (0x88054661), (0xD3670487), + (0x87BFCCB5), (0xD423B1F5), (0x877B7BBD), (0xD4E0CB9C), (0x87385424), + (0xD59E4FAA), (0x86F6568E), (0xD65C3C4A), (0x86B5839E), (0xD71A8FA8), + (0x8675DC95), (0xD7D94608), (0x863760CC), (0xD8986160), (0x85FA1180), + (0xD957DDF1), (0x85BDEF49), (0xDA17B9E5), (0x8582FABB), (0xDAD7F360), + (0x85493467), (0xDB98888A), (0x85109CDD), (0xDC597787), (0x84D934A7), + (0xDD1ABE7A), (0x84A2FC4F), (0xDDDC5B88), (0x846DF45A), (0xDE9E4CD2), + (0x843A1D4B), (0xDF60907A), (0x840777A2), (0xE02324A0), (0x83D603DC), + (0xE0E60764), (0x83A5C2EC), (0xE1A934F4), (0x8376B454), (0xE26CAF51), + (0x8348D904), (0xE33072A7), (0x831C316D), (0xE3F47D14), (0x82F0BDFE), + (0xE4B8CCB4), (0x82C67F21), (0xE57D5FA2), (0x829D7540), (0xE64233F9), + (0x8275A0BE), (0xE70747D4), (0x824F0200), (0xE7CC994C), (0x82299962), + (0xE892267C), (0x82056743), (0xE957ED7A), (0x81E26BFB), (0xEA1DEC5F), + (0x81C0A7E1), (0xEAE42143), (0x81A01B48), (0xEBAA8A3D), (0x8180C6CF), + (0xEC712368), (0x8162AA22), (0xED37EECF), (0x8145C5DF), (0xEDFEE88E), + (0x812A1A4C), (0xEEC60EB9), (0x810FA7AD), (0xEF8D5F65), (0x80F66E44), + (0xF054D8A6), (0x80DE6E4F), (0xF11C7891), (0x80C7A809), (0xF1E43D38), + (0x80B21BAA), (0xF2AC24AF), (0x809DC968), (0xF3742D08), (0x808AB175), + (0xF43C5456), (0x8078D3FF), (0xF50498AB), (0x80683134), (0xF5CCF819), + (0x8058C93B), (0xF69570B2), (0x804A9C5E), (0xF75DFE87), (0x803DAA77), + (0xF826A3A8), (0x8031F3CB), (0xF8EF5C28), (0x80277879), (0xF9B82615), + (0x801E3899), (0xFA80FF82), (0x80163443), (0xFB49E67F), (0x800F6B8A), + (0xFC12D91B), (0x8009DE7E), (0xFCDBD568), (0x80058D2F), (0xFDA4D975), + (0x800277A6), (0xFE6DE352), (0x80009DEA), (0xFF36F10F), (0x656DBCC8), + (0x7A9108CA), (0xBA3670F0), (0x699195A2), (0x172D2FD0), (0xBE386D51), + (0xC4AEA51C), (0x2AA77D7D), (0x8B51D3B4), (0xCF490FD9), (0x4A7BEBCA), + (0x91072E04), (0xA175872D), (0x54464A9E), (0x67A6CD02), (0x9E8204A8), + (0x10C14BF6), (0x75ACDA16), (0xF78D7B3E), (0x6AB3CF69), (0xA4D8C756), + (0xCB8FCD24), (0x75CC5713), (0xC13E5AE3), (0xA8C3176D), (0x5EE6D416), + (0x80C5DA0E), (0xD84A007C), (0x719E73C0), (0x765014B0), (0x0A391BC8), + (0x60A70223), (0x54CDA46B), (0x4606D455), (0xA606FB2A), (0xE4CE1557), + (0x73240820), (0x8037A8B4), (0xA1D88032), (0x75A3F1C7), (0x32BB0370), + (0x5F850242), (0x85EC8F5B), (0x8AA2B33C), (0x91B370C2), (0x938E9DDB), + (0xE6B6983E), (0x49602AA9), (0x6C2D9965), (0x5B16AE72), (0x69579B6B), + (0xCD3AB415), (0x5B7CF03C), (0xD7B27637), (0x2D69B79A), (0x3237B468), + (0x5F94D650), (0xAB37106D), (0x0B831457), (0xAFD80334), (0xB5A0B27B), + (0x16B763E9), (0x3B454756), (0x3167CD98), (0x707239AF), (0x0A4F132A), + (0x2782C8CA), (0x1AC1DD4E), (0x121CADFE), (0x9A911D90), (0x0157ADD6), + (0x1559BB95), (0x2854C84A), (0xD97E3685), (0x76308AA0), (0x8050F1FF), + (0x2180612F), (0xFFFB8A1A), (0x0BC1FFFF), (0x1032846C), (0x002A30C2), + (0x654C58F2), (0xA58ABACC), (0xC3E9831C), (0x27531B8C), (0xADBB8698), + (0x06801C12), (0xAFAEEC8E), (0xC3269291), (0x5C2E01A0), (0x4A61087C), + (0x60F21E7B), (0x6B92C670), (0xC9872364), (0x48464C97), (0x342E6499), + (0xA6849A48), (0xF034002D), (0x442B4488), (0x160B0442), (0xED52CF50), + (0x4D436C05), (0x6841C602), (0xA14F8A82), (0x9AC20DDE), (0x5B9251EE), + (0x8ED998D5), (0x92B6EA22), (0x5B136C4B), (0x97C0A45B), (0x459C94A4), + (0xCD9583C0), (0x6C589DF8), (0x3C9A17CD), (0x906601BF), (0x84D612E1), + (0x67176F5F), (0xE47D5A44), (0x37386D5E), (0x92A4D61B), (0x28C513FB), + (0x6E91599A), (0x653DA16D), (0xA19C39C0), (0x427690AD), (0x7005461C), + (0xAB6C1EE4), (0x80BACC2D), (0x780A18C5), (0x822DC774), (0xB6043036), + (0x00789C18), (0x106C9507), (0x4103A864), (0xC511585B), (0xF3E9B7F8), + (0x24D79C4D), (0x31B20EB5), (0xB1C0483E), (0xE25C56B9), (0x96991096), + (0x7CD4121F), (0x8A3B83F4), (0x704271C2), (0xB5C26ACC), (0x2B131AF0), + (0x549CB16C), (0x74649E69), (0xD8D48ADE), (0x1253AEDD), (0x80410FD2), + (0x5B36889D), (0x880CE1E7), (0x56C498E7), (0xFA2BAAB2), (0xD4154F5C), + (0x79516EED), (0xA42FDA7D), (0x278D2873), (0x19121535), (0x9C6EC6C7), + (0x402340CB), (0x5A6A32B3), (0xE4345F27), (0x8DC2D901), (0x02E7F88E), + (0x7B3C6BEB), (0xE0946A4F), (0x9452886C), (0xFF2F6187), (0x2F8050F1), + (0x2A217C61), (0x0AB21594), (0x801145C4), (0x1CF200A5), (0x82C544F1), + (0xCF3C50B0), (0xD577FEF7), (0x60AD3C6E), (0x91AFF79E), (0x070723B3), + (0x5870ECF6), (0x64C224E2), (0x24FB1EC8), (0xC3481048), (0x151ABF3C), + (0x136AC219), (0x4716CED1), (0xC8B8CE4E), (0x1D168210), (0x92334A81), + (0x90DC910C), (0x49A00220), (0xE5F2C831), (0xB67DC785), (0x3C495174), + (0x0D1F4C2A), (0x3AD787FD), (0xE9C9FB27), (0x7DFC2713), (0xEB39C4B3), + (0x96F75F18), (0x883CCC47), (0x91390BD1), (0x0EE25F6D), (0x6B688EF0), + (0x2C8557DC), (0xE80C9172), (0xDE63DE06), (0x3E1B707B), (0xB2CF2E76), + (0x490D1DF3), (0xCD1B51E1), (0xC228F0F9), (0xEEE2A00A), (0x081D834A), + (0x1D2C1403), (0x083FE940), (0x7614EDA0), (0x8282095A), (0xA7C08821), + (0x4CD47D20), (0x32299191), (0x52A030E6), (0xDF7CB76E), (0x232ED44B), + (0x8DAA150A), (0x1B593C51), (0x449CBA82), (0xABE6D3C4), (0xCCF6F5C3), + (0x9064C1C2), (0x031FF59C), (0x4159FE4E), (0x421482C0), (0x20F6F00A), + (0xB866CA49), (0x75A66FAA), (0x5453515F), (0xB545D486), (0x885D9493), + (0xEEC4EEB4), (0x88F9C893), (0xBBAA38B4), (0x5A57BA83), (0x12E848CC), + (0x2FB62160), (0x840A1A54), (0x2A7AEDD6), (0x89AF2DBD), (0xC8BAAE2E), + (0x56EEBD75), (0xE595B86D), (0xEEB123C6), (0x3F94EBC1), (0x78CFBEE2), + (0xCF901F11), (0x5A35A350), (0xDA22CB58), (0xBE4B8287), (0x25E078C0), + (0x2BD4F0D3), (0x6A464B99), (0x4884B156), (0xF1FF7630), (0xC1328050), + (0xD84C216C), (0x84A4D942), (0x2157A0A0), (0xF30A1412), (0x54AF6011), + (0x00D70542), (0xBDABE7DB), (0x1FF3534C), (0xD8672B4E), (0x7BE3BB3A), + (0xC5595540), (0x161E1BFF), (0xD4372309), (0x7BC2ED52), (0xC1C636ED), + (0x4DD32AA4), (0x86163246), (0x614EF688), (0x4EB44270), (0x88ED077C), + (0x2F229466), (0x1A585201), (0x65BB2EE2), (0xDBADA0DD), (0xE50995CB), + (0xCA1E2760), (0x583FD81F), (0xE48D4859), (0xC2006152), (0x8F1F770C), + (0x27CAA86F), (0x9610B845), (0xFC25BCE3), (0x37B8B39F), (0x10DCCDD1), + (0xD57A4CAB), (0x7D543DE8), (0x6F45B958), (0x12F0B979), (0x818E79F9), + (0xB4B2B01F), (0xF3035901), (0x372F7BD9), (0x5D592E67), (0xDB5A552F), + (0x6E61E625), (0x4E8A6A42), (0x2458ADB8), (0x5F12528C), (0x272B3ADE), + (0xDE666A83), (0x7F18CFD7), (0x2F877DD8), (0xD73FFFB6), (0x79867956), + (0x4E05FCAD), (0x19E78EEE), (0xE1BA6512), (0x99F6F091), (0x91690516), + (0x16AE4041), (0x04B96805), (0x7CA052FC), (0xA4D05EFD), (0x413D1F04), + (0x53E91CC0), (0x6F87A082), (0x604FD202), (0x0B368D9F), (0xD5F22E5C), + (0x2BE5A74E), (0x2F69EADE), (0x8BE537E1), (0x96975789), (0x3675A3A0), + (0x0A272B71), (0x754B1D61), (0x98600581), (0x659A2BE3), (0xB21BEF54), + (0xF26351B0), (0x1C599573), (0x6B423B59), (0xEA371C96), (0xC9BDA499), + (0xDDF25F37), (0xFBCAC4AD), (0x40CA788B), (0x13BC3981), (0x4176DA58), + (0xD848DA74), (0x94740642), (0x54FD5479), (0x71502362), (0x25E81CF9), + (0x53249562), (0x52814827), (0x55DC5F2C), (0x8825BC50), (0x8E4D04D9), + (0x8050F1FF), (0x212CC13E), (0x00C0D84C), (0x07711003), (0x406A5F45), + (0xED0A98DE), (0x8A619731), (0x796A3B04), (0x7EAECF71), (0x7DF3DABE), + (0x2B0FFB4A), (0xBA8A3FB8), (0x6202F8F2), (0x632C37B2), (0x205271AA), + (0xBA1C438C), (0xAA1C1182), (0xE6442A65), (0xD736E043), (0x95715C5C), + (0x3D604C28), (0xD21D0D74), (0xA1FB0C21), (0xCE8F065D), (0xB8B36463), + (0x7F788C33), (0x84AB53A5), (0x4B33AF46), (0x40C2736A), (0x0D6571B7), + (0xFC8D8292), (0x9D1C5182), (0xF7B670E2), (0xBB2B9E91), (0x137851D5), + (0xBCF87CA8), (0xE082A7A6), (0x502404E5), (0x5025A6E0), (0x25494EA6), + (0x5A6A8A14), (0xE301A689), (0x70CBEE6B), (0xC80644C1), (0xE9914CE6), + (0x9481F1E6), (0xB9E4DA34), (0x584B1ED8), (0xACC39648), (0x31EFCD62), + (0x07C82AE9), (0xEE9D90E5), (0x59BAEC75), (0x40178B0E), (0x9FDC1C9C), + (0xF3A6488F), (0x4B6C1367), (0x9F7DF109), (0xCBDF8EDF), (0xBA76ED33), + (0xF15DBB9F), (0xD48A197F), (0xF11E75EE), (0xA76B479B), (0x706DE78B), + (0x6559AC65), (0xC013C182), (0x461E93C7), (0xA989EAF1), (0x59448C00), + (0x721FAC38), (0x546DEA79), (0x223F67C0), (0x5434647C), (0xB3EF4F0A), + (0xD4FAF1F1), (0x0BD4E38A), (0xFF61527E), (0xD6EA5DD2), (0x644C7105), + (0x31AE2189), (0x11EC0A1A), (0x18B3AD80), (0x47D0E80A), (0x773D8BB2), + (0xEFA6747E), (0xF23DE8B0), (0x026BB1E7), (0x03C14060), (0xC1997DF7), + (0x95986B9C), (0x8A5D6170), (0x54DB3A56), (0x22961D41), (0x46813471), + (0xABED16A4), (0xD1F83E8C), (0x2594ACAC), (0x1D5560EA), (0x0432EFF4), + (0xA389D7E8), (0xAFE92C62), (0xFBBAF1E7), (0x42D0D0A1), (0xA2C3ECB2), + (0x603DD635), (0xEBBC5915), (0x5B0C7CE0), (0x8D03640C), (0x22E298DB), + (0x38CE3BDC), (0x21E6B6B4), (0xC9742C3F), (0x4BDF7448), (0xBAD09D00), + (0xED6A8397), (0xF6F8001A), (0x31E3591E), (0xAEC37EFE), (0x22D9AD06), + (0x5E254AEC), (0xD852D32E), (0xE1C968AE), (0xA3C3C265), (0xD67BD78A), + (0xF1FF9D8C), (0xC03A8050), (0x847A21FC), (0x810EDA5D), (0x63808951), + (0xC8FE9E9E), (0xFB6DD3E5), (0x77BD7A03), (0x6DC14677), (0xFF81D831), + (0x43201100), (0xA78E16FE), (0x393CD0A0), (0x514F6DDD), (0x427BA4BC), + (0xEBE7A676), (0xB771639B), (0x8DABB9E7), (0x812FA5AD), (0x3F102120), + (0x60E42454), (0xEFFBFFC5), (0xBEB1D5DD), (0x7A59DDFD), (0xE8968D7A), + (0x8AAD3462), (0xAB65327D), (0x0CF2ECFB), (0xFA3249A4), (0x97FC3A42), + (0x314A7089), (0x2991E6DC), (0xA98693C4), (0x65EB2011), (0xCB4D8594), + (0x1AAFF14E), (0x1D0D0492), (0x2E5A784D), (0xAE4EC738), (0xF16D667A), + (0xB0C26030), (0xADA3DFC9), (0x4ED874E5), (0xD441A6AE), (0x19E3AC05), + (0xC6B865DC), (0xE8E4285A), (0x99248C2B), (0xC2981122), (0x1B014288), + (0x442A0580), (0x84A0A1C1), (0x216F0248), (0x202E5602), (0xEAEBAACA), + (0xDD5ABEE7), (0x8B9C4B43), (0x5D5D46D7), (0x8FBE7C1D), (0x6F9CAB87), + (0xB0AB0AAE), (0x98BC7936), (0xF251B911), (0x4469F2D1), (0xA9099088), + (0xD219BD66), (0x7490AE22), (0xBC0A9820), (0x119D0136), (0x8592661C), + (0x260C0D18), (0xB9A1C5B1), (0xA68591E4), (0xFCBD4F29), (0x5965A3C7), + (0x7D1ED664), (0x9BDDEEE3), (0x92237D5A), (0xB7332DA6), (0xEA5632E5), + (0x9BFE1624), (0x6A2BB18A), (0x8C0DD72C), (0x4F319F56), (0xEE8B5B03), + (0x60967BC8), (0xB4918F75), (0xF295D5F6), (0x652AD80D), (0x0CCE9552), + (0x0BCAA0A6), (0x3CF2D28E), (0x1853956E), (0x7B38DEAA), (0xEAAB970B), + (0x64086D1F), (0x3E7645DD), (0x986F1342), (0xBBB0E188), (0x7D6D5642), + (0x6821827D), (0xFCBC4729), (0x3D114FB9), (0x2D2542E5), (0x654CC1F0), + (0x04F1B75E), (0x290B54AF), (0x7D79AB1A), (0xF34E31A2), (0x73A9F300), + (0x7ABCA89E), (0xB56DA974), (0xCACDB07C), (0x4EE1ADD4), (0xEF859B34), + (0x89F47B47), (0x515C155A), (0x38D06757), (0x8050F1FF), (0x21C8E03A), + (0xB155841A), (0x30716685), (0x0A2B48AC), (0x7041C40A), (0x104C44D0), + (0x1F51B618), (0xF0D4F39B), (0xFCAEBA52), (0x30EA62CD), (0xA294B772), + (0x221E0417), (0xAA8EF192), (0x3E568C78), (0xD386EF9A), (0x13B54FB1), + (0x84818EC3), (0xB87669F8), (0xCD90565A), (0x73D7C876), (0xD6191512), + (0xAC228704), (0xA7785D48), (0x17CF34DD), (0x8AF5AB40), (0x365C6AFA), + (0x17DFD59E), (0xB924C26E), (0xE9DE5844), (0x3DCDDCD9), (0xCDA2DFB4), + (0x8A5B534E), (0xA2D9DACA), (0x11679569), (0xAEF6E7E9), (0xC9D2417C), + (0x515DC9C3), (0x157A5B12), (0x4C960DD6), (0xD413CC01), (0x65319545), + (0x6CF1309D), (0x000338C7), (0x460AA7FC), (0xC1FA4440), (0x0E3AE048), + (0xF4B212B5), (0xC7895D2B), (0x676AFAF3), (0xEF404F75), (0xBFCDB17C), + (0xA37FE6C6), (0x20123DD5), (0xEE96BD3B), (0x3EB8A62E), (0x068845E1), + (0xC4960216), (0x7BB11D8D), (0x2D657467), (0xFC6FACC5), (0xC21AAD31), + (0x642745F4), (0x4507E139), (0xF7369DC9), (0x6198ADEB), (0x63B98B10), + (0xDEE585AB), (0xA38EFFAC), (0x30AE1E41), (0x820667A9), (0x6B77A007), + (0x240040A7), (0xB77A7D95), (0x208893CA), (0x085B4610), (0x14234854), + (0xAC022786), (0x2D57346F), (0xB64A1A67), (0x605D45B2), (0xE051C001), + (0x9176C11D), (0x23BBE945), (0x2C03E26A), (0xC2811BAD), (0x1DD814D4), + (0x3C674B68), (0x28EC33C7), (0xD9EDE5E4), (0x5C46C248), (0x4098898F), + (0x5BA96280), (0xEFF77B91), (0x3332CA5B), (0x661CAF6B), (0x6E0D564E), + (0xB70D0863), (0x240285C0), (0xBBBD3EA7), (0xCA2E568D), (0xD1D3F612), + (0xC916115E), (0xB7FC0A6C), (0x1961AE9A), (0xB5DF3965), (0xC1B95065), + (0x89E29665), (0x3F29FBED), (0x3F1BED73), (0xC155BE1D), (0x7256AE4C), + (0x4A59797B), (0x6009D13B), (0x91850385), (0xE4545920), (0x15ECCDA1), + (0xFFC7BA20), (0x2B8050F1), (0x1A21D4C0), (0x3008BE89), (0x6C0FF317), + (0x7444D852), (0x05841411), (0x84C80022), (0x07C630E0), (0x7E6F8FA3), + (0xF3BDF3C7), (0x4C55DFF7), (0xE0B1C8D1), (0xC3F5CF4D), (0x1C22A836), + (0xB29D3315), (0xD4966541), (0x45C85800), (0xAD8DBD46), (0x2C19CFAA), + (0x540FA674), (0xC3C913D8), (0xD2183753), (0xCB9FCF26), (0x8346FC89), + (0xA3408078), (0xCFD84CC1), (0xF580F035), (0x7FD067A7), (0x87E7FCB8), + (0x09C09406), (0xDDBB3131), (0xFF79FFE1), (0xEAFBEEF1), (0xB660BCE8), + (0x99899C31), (0x9FEB22C1), (0xC75EF68F), (0x13800B99), (0xCD7F3100), + (0x09502ADC), (0x101E00E8), (0x406CB945), (0x820A1B2B), (0x68A0B082), + (0x0C1B1864), (0xB3690354), (0x63C5B5A3), (0x535EB4C8), (0xF7D86918), + (0xD1BA58FC), (0xF42910FA), (0xFBDB1929), (0xC7C0C2A4), (0xD2074752), + (0xB96803B4), (0x84065E38), (0x819AF48E), (0xE9864FF3), (0xA6E41D0E), + (0x50E7442B), (0xC7574D7B), (0x196B6AB3), (0x041D5854), (0x629162D3), + (0x042713E0), (0x9AE31297), (0x4B2F4E36), (0xCB8CE0E0), (0xB2F0682A), + (0xAB33D6F5), (0x2F53D82E), (0x66A43815), (0x4433AAA8), (0x82EA0ED5), + (0x457876F2), (0xD30BD36C), (0x8D49D28C), (0x0E68260E), (0xD056512C), + (0x7B86DB11), (0x64633661), (0x8265FF25), (0x6D2B7148), (0x529DA0D8), + (0xBC180017), (0x19AB803B), (0x83F00020), (0x50F1FF07), (0xD4C02D80), + (0xFC881A21), (0xC1BF0100), (0x5841680B), (0x103B2CC0), (0xB042C28A), + (0x2324E8A8), (0x31531430), (0xEF71DD0E), (0x7C1B9D8E), (0x0998C228), + (0xD9EC6548), (0x8EEF8448), (0x0C561CAF), (0x4BA39DFD), (0x58947FE2), + (0x959B12A2), (0x6D52EAEC), (0x1D95DDD5), (0x310C222B), (0x63634B18), + (0x4DE6C5B8), (0x526C9106), (0x49B5E8CC), (0xC3C33004), (0x605CD287), + (0x09A6390C), (0x350C33BC), (0x953050CC), (0x960552A3), (0x54F01186), + (0x0E8D7CFE), (0x459A0022), (0xC3576966), (0xB0D6F6E8), (0xB8F13AAC), + (0xE440034C), (0x36118851), (0xF51BE727), (0x2E1689A0), (0xE82CCF55), + (0x6DF4E3CB), (0xEA665663), (0xC2E53D6F), (0x9DC1F06B), (0xFCC2E878), + (0x4292D162), (0x4840C433), (0xB618DB43), (0x06092C15), (0x500134C1), + (0xA6DB8955), (0xD5E8A5BB), (0x142B7829), (0x75F42939), (0x0EBF4D10), + (0x1A2B078C), (0x7C2A5A46), (0x3EA1B9A7), (0x31AAC898), (0x1327B852), + (0x277C65A1), (0x5280CE27), (0xFF512213), (0x39B47EBF), (0x154CA000), + (0x106E7DA2), (0xAFA4C925), (0xC48CE379), (0xAB2E4573), (0x5E44B8FD), + (0xECD2A424), (0x8C5300AA), (0xE425A180), (0x6D5D0D3B), (0xA70540A8), + (0xF8ECF432), (0x884696B0), (0xB79755BF), (0x62CAD419), (0x4BBB38B6), + (0xCD5C79D7), (0x82D4E29B), (0x6DD48E91), (0xA128A3A9), (0xF2ED6726), + (0x339A63F6), (0x35D6F4EA), (0x8DC8B491), (0xCA04D09C), (0xFF074FD0), + (0x2D8050F1), (0x1A21D880), (0x1900FE88), (0x6C09D1BF), (0x56483001), + (0xC20A1A29), (0x449180A3), (0x028C5160), (0x75FAECDD), (0x6250705B), + (0x89EA010A), (0x7B9F9851), (0x9D6C5994), (0x8602C3E4), (0x03D0E863), + (0x04322251), (0x116095B7), (0x789276CA), (0x00000000), (0x00000978), + (0x8000C688), (0x8000BCD8), (0x80010000), (0x9FC3F7B8), (0xDE47BC1B), + (0xE60FB4F8), (0xEA27469D), (0xCCA1E66D), (0x8FFF7010), (0x8000BCD8), + (0x000000D0), (0x8000B4B0), (0x8FFFFB24), (0x9FC3F7B8), (0x00000000), + (0x8000B418), (0x8FFF7010), (0x8000C688), (0x000000D0), (0x9FC3FD3C), + (0xD625F8C0), (0x478D832A), (0xF693D922), (0x3617D816), (0x80000648), + (0x00000000), (0x00000003), (0x00000012), (0x9FC49964), (0x46141924), + (0x4D834205), (0x16B799A6), (0xA39494A6), (0xCCF23C60), (0x00000001), + (0x9FC47468), (0x00000000), (0x00000072), (0x00008001), (0x8FFFFB58), + (0x00000003), (0x402C7413), (0x00000016), (0x402C7413), (0x9FC48498), + (0x00000000), (0x00000002), (0x00000001), (0x00000072), (0x9FC4783C), + (0x8000C690), (0x0358CDD5), (0x00000000), (0x00008001), (0x00000072), + (0x80000648), (0x00000000), (0x00008001), (0x8000BD40), (0x1A19F8D8), + (0x00008001), (0x800003C0), (0x00000003), (0x9FC428CC), (0xF6192015), + (0xFBB77F92), (0x8F2C8BFC), (0x3C391923), (0x4014428C), (0x140045AE), + (0xFFFD2BB6), (0x2D8050F1), (0x8000BD40), (0x00000003), (0x00000000), + (0x2CC05811), (0x00008001), (0x800003C0), (0x80000648), (0x80000648), + (0x9FC4206C), (0x8FFFFD78), (0x8FFFFEEC), (0x8000C668), (0x80000648), + (0x8FFFFD78), (0x00000000), (0x00003040), (0x8000FFC0), (0x8000BCD8), + (0x80010000), (0x9FC3F7B8), (0x00000000), (0x00002CC0), (0x80013340), + (0x8000BCD8), (0x80010FD0), (0x80012548)}; diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mips/scale_mips.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mips/scale_mips.cpp new file mode 100644 index 0000000000000..ff295d9ef3d7b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/mips/scale_mips.cpp @@ -0,0 +1,133 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +#if defined(__mips_dsp) && !defined(__mips16) + +#ifndef FUNCTION_getScalefactor_DBL +#define FUNCTION_getScalefactor_DBL +/*! + * + * \brief Calculate max possible scale factor for input vector + * + * \return Maximum scale factor + * + * This function can constitute a significant amount of computational + * complexity - very much depending on the bitrate. Since it is a rather small + * function, effective assembler optimization might be possible. + * + */ +SCALE_INLINE +INT getScalefactor(const FIXP_DBL *vector, /*!< Pointer to input vector */ + INT len) /*!< Length of input vector */ +{ + INT i; + FIXP_DBL maxVal = FL2FX_DBL(0.0f); + + for (i = len; i != 0; i--) { + maxVal |= __builtin_mips_absq_s_w(*vector++); + } + + return fixMax((INT)0, (CntLeadingZeros(maxVal) - 1)); +} +#endif + +#endif /*__mips_dsp */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/nlc_dec.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/nlc_dec.cpp new file mode 100644 index 0000000000000..3733d985e2ded --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/nlc_dec.cpp @@ -0,0 +1,1069 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Omer Osman + + Description: SAC/SAOC Dec Noiseless Coding + +*******************************************************************************/ + +#include "nlc_dec.h" +#include "FDK_tools_rom.h" + +/* MAX_PARAMETER_BANDS defines array length in huffdec */ + +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +ERROR_t sym_restoreIPD(HANDLE_FDK_BITSTREAM strm, int lav, SCHAR data[2]) { + int sum_val = data[0] + data[1]; + int diff_val = data[0] - data[1]; + + if (sum_val > lav) { + data[0] = -sum_val + (2 * lav + 1); + data[1] = -diff_val; + } else { + data[0] = sum_val; + data[1] = diff_val; + } + + if (data[0] - data[1] != 0) { + ULONG sym_bit; + sym_bit = FDKreadBits(strm, 1); + if (sym_bit) { + int tmp; + tmp = data[0]; + data[0] = data[1]; + data[1] = tmp; + } + } + + return HUFFDEC_OK; +} + +static int ilog2(unsigned int i) { + int l = 0; + + if (i) i--; + while (i > 0) { + i >>= 1; + l++; + } + + return l; +} + +static ERROR_t pcm_decode(HANDLE_FDK_BITSTREAM strm, SCHAR* out_data_1, + SCHAR* out_data_2, int offset, int num_val, + int num_levels) { + int i = 0, j = 0, idx = 0; + int max_grp_len = 0, next_val = 0; + ULONG tmp; + + int pcm_chunk_size[7] = {0}; + + switch (num_levels) { + case 3: + max_grp_len = 5; + break; + case 7: + max_grp_len = 6; + break; + case 11: + max_grp_len = 2; + break; + case 13: + max_grp_len = 4; + break; + case 19: + max_grp_len = 4; + break; + case 25: + max_grp_len = 3; + break; + case 51: + max_grp_len = 4; + break; + case 4: + case 8: + case 15: + case 16: + case 26: + case 31: + max_grp_len = 1; + break; + default: + return HUFFDEC_NOTOK; + } + + tmp = 1; + for (i = 1; i <= max_grp_len; i++) { + tmp *= num_levels; + pcm_chunk_size[i] = ilog2(tmp); + } + + for (i = 0; i < num_val; i += max_grp_len) { + int grp_len, grp_val, data; + grp_len = min(max_grp_len, num_val - i); + data = FDKreadBits(strm, pcm_chunk_size[grp_len]); + + grp_val = data; + + for (j = 0; j < grp_len; j++) { + idx = i + (grp_len - j - 1); + next_val = grp_val % num_levels; + + if (out_data_2 == NULL) { + out_data_1[idx] = next_val - offset; + } else if (out_data_1 == NULL) { + out_data_2[idx] = next_val - offset; + } else { + if (idx % 2) { + out_data_2[idx / 2] = next_val - offset; + } else { + out_data_1[idx / 2] = next_val - offset; + } + } + + grp_val = (grp_val - next_val) / num_levels; + } + } + + return HUFFDEC_OK; +} + +static ERROR_t huff_read(HANDLE_FDK_BITSTREAM strm, + const SHORT (*nodeTab)[MAX_ENTRIES][2], + int* out_data) { + int node = 0; + int len = 0; + + do { + ULONG next_bit; + next_bit = FDKreadBits(strm, 1); + len++; + node = (*nodeTab)[node][next_bit]; + } while (node > 0); + + *out_data = node; + + return HUFFDEC_OK; +} + +static ERROR_t huff_read_2D(HANDLE_FDK_BITSTREAM strm, + const SHORT (*nodeTab)[MAX_ENTRIES][2], + SCHAR out_data[2], int* escape) { + ERROR_t err = HUFFDEC_OK; + + int huff_2D_8bit = 0; + int node = 0; + + if ((err = huff_read(strm, nodeTab, &node)) != HUFFDEC_OK) { + goto bail; + } + *escape = (node == 0); + + if (*escape) { + out_data[0] = 0; + out_data[1] = 1; + } else { + huff_2D_8bit = -(node + 1); + out_data[0] = huff_2D_8bit >> 4; + out_data[1] = huff_2D_8bit & 0xf; + } + +bail: + return err; +} + +static ERROR_t sym_restore(HANDLE_FDK_BITSTREAM strm, int lav, SCHAR data[2]) { + ULONG sym_bit = 0; + + int sum_val = data[0] + data[1]; + int diff_val = data[0] - data[1]; + + if (sum_val > lav) { + data[0] = -sum_val + (2 * lav + 1); + data[1] = -diff_val; + } else { + data[0] = sum_val; + data[1] = diff_val; + } + + if (data[0] + data[1] != 0) { + sym_bit = FDKreadBits(strm, 1); + if (sym_bit) { + data[0] = -data[0]; + data[1] = -data[1]; + } + } + + if (data[0] - data[1] != 0) { + sym_bit = FDKreadBits(strm, 1); + if (sym_bit) { + int tmp; + tmp = data[0]; + data[0] = data[1]; + data[1] = tmp; + } + } + + return HUFFDEC_OK; +} + +static ERROR_t huff_dec_1D(HANDLE_FDK_BITSTREAM strm, const DATA_TYPE data_type, + const INT dim1, SCHAR* out_data, const INT num_val, + const INT p0_flag) + +{ + ERROR_t err = HUFFDEC_OK; + int i = 0, node = 0, offset = 0; + int od = 0, od_sign = 0; + ULONG data = 0; + int bitsAvail = 0; + + const SHORT(*partTab)[MAX_ENTRIES][2] = NULL; + const SHORT(*nodeTab)[MAX_ENTRIES][2] = NULL; + + switch (data_type) { + case t_CLD: + partTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.cld[0][0]; + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffCLDNodes.h1D[dim1]->nodeTab[0][0]; + break; + case t_ICC: + partTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.icc[0][0]; + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffICCNodes.h1D[dim1]->nodeTab[0][0]; + break; + case t_OLD: + partTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.old[0][0]; + nodeTab = (HANDLE_HUFF_NODE)&huffOLDNodes.h1D[dim1]->nodeTab[0][0]; + break; + case t_IPD: + partTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.ipd[0][0]; + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffIPDNodes.h1D[dim1].nodeTab[0][0]; + break; + default: + FDK_ASSERT(0); + err = HUFFDEC_NOTOK; + goto bail; + } + + if (p0_flag) { + if ((err = huff_read(strm, partTab, &node)) != HUFFDEC_OK) { + goto bail; + } + + out_data[0] = -(node + 1); + offset = 1; + } + + for (i = offset; i < num_val; i++) { + bitsAvail = FDKgetValidBits(strm); + if (bitsAvail < 1) { + err = HUFFDEC_NOTOK; + goto bail; + } + + if ((err = huff_read(strm, nodeTab, &node)) != HUFFDEC_OK) { + goto bail; + } + od = -(node + 1); + + if (data_type != t_IPD) { + if (od != 0) { + bitsAvail = FDKgetValidBits(strm); + if (bitsAvail < 1) { + err = HUFFDEC_NOTOK; + goto bail; + } + + data = FDKreadBits(strm, 1); + od_sign = data; + + if (od_sign) od = -od; + } + } + + out_data[i] = od; + } + +bail: + return err; +} + +static ERROR_t huff_dec_2D(HANDLE_FDK_BITSTREAM strm, const DATA_TYPE data_type, + const INT dim1, const INT dim2, SCHAR out_data[][2], + const INT num_val, const INT stride, + SCHAR* p0_data[2]) { + ERROR_t err = HUFFDEC_OK; + int i = 0, lav = 0, escape = 0, escCntr = 0; + int node = 0; + unsigned long data = 0; + + SCHAR esc_data[2][28] = {{0}}; + int escIdx[28] = {0}; + const SHORT(*nodeTab)[MAX_ENTRIES][2] = NULL; + + /* LAV */ + if ((err = + huff_read(strm, (HANDLE_HUFF_NODE)&FDK_huffLavIdxNodes.nodeTab[0][0], + &node)) != HUFFDEC_OK) { + goto bail; + } + data = -(node + 1); + + switch (data_type) { + case t_CLD: + lav = 2 * data + 3; /* 3, 5, 7, 9 */ + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.cld[0][0]; + break; + case t_ICC: + lav = 2 * data + 1; /* 1, 3, 5, 7 */ + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.icc[0][0]; + break; + case t_OLD: + lav = 3 * data + 3; + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.old[0][0]; + break; + case t_IPD: + if (data == 0) + data = 3; + else + data--; + lav = 2 * data + 1; /* 1, 3, 5, 7 */ + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.ipd[0][0]; + break; + default: + FDK_ASSERT(0); + err = HUFFDEC_NOTOK; + goto bail; + } + + /* Partition 0 */ + if (p0_data[0] != NULL) { + if ((err = huff_read(strm, nodeTab, &node)) != HUFFDEC_OK) { + goto bail; + } + *p0_data[0] = -(node + 1); + } + if (p0_data[1] != NULL) { + if ((err = huff_read(strm, nodeTab, &node)) != HUFFDEC_OK) { + goto bail; + } + *p0_data[1] = -(node + 1); + } + + switch (data_type) { + case t_CLD: + switch (lav) { + case 3: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffCLDNodes.h2D[dim1][dim2]->lav3[0][0]; + break; + case 5: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffCLDNodes.h2D[dim1][dim2]->lav5[0][0]; + break; + case 7: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffCLDNodes.h2D[dim1][dim2]->lav7[0][0]; + break; + case 9: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffCLDNodes.h2D[dim1][dim2]->lav9[0][0]; + break; + } + break; + case t_ICC: + switch (lav) { + case 1: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffICCNodes.h2D[dim1][dim2]->lav1[0][0]; + break; + case 3: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffICCNodes.h2D[dim1][dim2]->lav3[0][0]; + break; + case 5: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffICCNodes.h2D[dim1][dim2]->lav5[0][0]; + break; + case 7: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffICCNodes.h2D[dim1][dim2]->lav7[0][0]; + break; + } + break; + case t_OLD: + switch (lav) { + case 3: + nodeTab = (HANDLE_HUFF_NODE)&huffOLDNodes.h2D[dim1][dim2]->lav3[0][0]; + break; + case 6: + nodeTab = (HANDLE_HUFF_NODE)&huffOLDNodes.h2D[dim1][dim2]->lav6[0][0]; + break; + case 9: + nodeTab = (HANDLE_HUFF_NODE)&huffOLDNodes.h2D[dim1][dim2]->lav9[0][0]; + break; + case 12: + nodeTab = + (HANDLE_HUFF_NODE)&huffOLDNodes.h2D[dim1][dim2]->lav12[0][0]; + break; + } + break; + case t_IPD: + switch (lav) { + case 1: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffIPDNodes.h2D[dim1][dim2].lav1[0][0]; + break; + case 3: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffIPDNodes.h2D[dim1][dim2].lav3[0][0]; + break; + case 5: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffIPDNodes.h2D[dim1][dim2].lav5[0][0]; + break; + case 7: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffIPDNodes.h2D[dim1][dim2].lav7[0][0]; + break; + } + break; + default: + break; + } + + for (i = 0; i < num_val; i += stride) { + if ((err = huff_read_2D(strm, nodeTab, out_data[i], &escape)) != + HUFFDEC_OK) { + goto bail; + } + + if (escape) { + escIdx[escCntr++] = i; + } else { + if (data_type == t_IPD) { + if ((err = sym_restoreIPD(strm, lav, out_data[i])) != HUFFDEC_OK) { + goto bail; + } + } else { + if ((err = sym_restore(strm, lav, out_data[i])) != HUFFDEC_OK) { + goto bail; + } + } + } + } /* i */ + + if (escCntr > 0) { + if ((err = pcm_decode(strm, esc_data[0], esc_data[1], 0, 2 * escCntr, + (2 * lav + 1))) != HUFFDEC_OK) { + goto bail; + } + + for (i = 0; i < escCntr; i++) { + out_data[escIdx[i]][0] = esc_data[0][i] - lav; + out_data[escIdx[i]][1] = esc_data[1][i] - lav; + } + } +bail: + return err; +} + +static ERROR_t huff_decode(HANDLE_FDK_BITSTREAM strm, SCHAR* out_data_1, + SCHAR* out_data_2, DATA_TYPE data_type, + DIFF_TYPE diff_type_1, DIFF_TYPE diff_type_2, + int num_val, PAIRING* pairing_scheme, int ldMode) { + ERROR_t err = HUFFDEC_OK; + CODING_SCHEME coding_scheme = HUFF_1D; + DIFF_TYPE diff_type; + + int i = 0; + + SCHAR pair_vec[28][2]; + + SCHAR* p0_data_1[2] = {NULL, NULL}; + SCHAR* p0_data_2[2] = {NULL, NULL}; + + int p0_flag[2]; + + int num_val_1_int = num_val; + int num_val_2_int = num_val; + + SCHAR* out_data_1_int = out_data_1; + SCHAR* out_data_2_int = out_data_2; + + int df_rest_flag_1 = 0; + int df_rest_flag_2 = 0; + + int hufYY1; + int hufYY2; + int hufYY; + + /* Coding scheme */ + coding_scheme = (CODING_SCHEME)FDKreadBits(strm, 1); + + if (coding_scheme == HUFF_2D) { + if ((out_data_1 != NULL) && (out_data_2 != NULL) && (ldMode == 0)) { + *pairing_scheme = (PAIRING)FDKreadBits(strm, 1); + } else { + *pairing_scheme = FREQ_PAIR; + } + } + + { + hufYY1 = diff_type_1; + hufYY2 = diff_type_2; + } + + switch (coding_scheme) { + case HUFF_1D: + p0_flag[0] = (diff_type_1 == DIFF_FREQ); + p0_flag[1] = (diff_type_2 == DIFF_FREQ); + if (out_data_1 != NULL) { + if ((err = huff_dec_1D(strm, data_type, hufYY1, out_data_1, + num_val_1_int, p0_flag[0])) != HUFFDEC_OK) { + goto bail; + } + } + if (out_data_2 != NULL) { + if ((err = huff_dec_1D(strm, data_type, hufYY2, out_data_2, + num_val_2_int, p0_flag[1])) != HUFFDEC_OK) { + goto bail; + } + } + + break; /* HUFF_1D */ + + case HUFF_2D: + + switch (*pairing_scheme) { + case FREQ_PAIR: + + if (out_data_1 != NULL) { + if (diff_type_1 == DIFF_FREQ) { + p0_data_1[0] = &out_data_1[0]; + p0_data_1[1] = NULL; + + num_val_1_int -= 1; + out_data_1_int += 1; + } + df_rest_flag_1 = num_val_1_int % 2; + if (df_rest_flag_1) num_val_1_int -= 1; + if (num_val_1_int < 0) { + err = HUFFDEC_NOTOK; + goto bail; + } + } + if (out_data_2 != NULL) { + if (diff_type_2 == DIFF_FREQ) { + p0_data_2[0] = NULL; + p0_data_2[1] = &out_data_2[0]; + + num_val_2_int -= 1; + out_data_2_int += 1; + } + df_rest_flag_2 = num_val_2_int % 2; + if (df_rest_flag_2) num_val_2_int -= 1; + if (num_val_2_int < 0) { + err = HUFFDEC_NOTOK; + goto bail; + } + } + + if (out_data_1 != NULL) { + if ((err = huff_dec_2D(strm, data_type, hufYY1, FREQ_PAIR, pair_vec, + num_val_1_int, 2, p0_data_1)) != + HUFFDEC_OK) { + goto bail; + } + if (df_rest_flag_1) { + if ((err = huff_dec_1D(strm, data_type, hufYY1, + out_data_1_int + num_val_1_int, 1, 0)) != + HUFFDEC_OK) { + goto bail; + } + } + } + if (out_data_2 != NULL) { + if ((err = huff_dec_2D(strm, data_type, hufYY2, FREQ_PAIR, + pair_vec + 1, num_val_2_int, 2, + p0_data_2)) != HUFFDEC_OK) { + goto bail; + } + if (df_rest_flag_2) { + if ((err = huff_dec_1D(strm, data_type, hufYY2, + out_data_2_int + num_val_2_int, 1, 0)) != + HUFFDEC_OK) { + goto bail; + } + } + } + + if (out_data_1 != NULL) { + for (i = 0; i < num_val_1_int - 1; i += 2) { + out_data_1_int[i] = pair_vec[i][0]; + out_data_1_int[i + 1] = pair_vec[i][1]; + } + } + if (out_data_2 != NULL) { + for (i = 0; i < num_val_2_int - 1; i += 2) { + out_data_2_int[i] = pair_vec[i + 1][0]; + out_data_2_int[i + 1] = pair_vec[i + 1][1]; + } + } + break; /* FREQ_PAIR */ + + case TIME_PAIR: + if (((diff_type_1 == DIFF_FREQ) || (diff_type_2 == DIFF_FREQ))) { + p0_data_1[0] = &out_data_1[0]; + p0_data_1[1] = &out_data_2[0]; + + out_data_1_int += 1; + out_data_2_int += 1; + + num_val_1_int -= 1; + } + + if ((diff_type_1 == DIFF_TIME) || (diff_type_2 == DIFF_TIME)) { + diff_type = DIFF_TIME; + } else { + diff_type = DIFF_FREQ; + } + { hufYY = diff_type; } + + if ((err = huff_dec_2D(strm, data_type, hufYY, TIME_PAIR, pair_vec, + num_val_1_int, 1, p0_data_1)) != HUFFDEC_OK) { + goto bail; + } + + for (i = 0; i < num_val_1_int; i++) { + out_data_1_int[i] = pair_vec[i][0]; + out_data_2_int[i] = pair_vec[i][1]; + } + + break; /* TIME_PAIR */ + + default: + break; + } + + break; /* HUFF_2D */ + + default: + break; + } +bail: + return err; +} + +static void diff_freq_decode(const SCHAR* const diff_data, + SCHAR* const out_data, const int num_val) { + int i = 0; + out_data[0] = diff_data[0]; + + for (i = 1; i < num_val; i++) { + out_data[i] = out_data[i - 1] + diff_data[i]; + } +} + +static void diff_time_decode_backwards(const SCHAR* const prev_data, + const SCHAR* const diff_data, + SCHAR* const out_data, + const int mixed_diff_type, + const int num_val) { + int i = 0; /* default start value*/ + + if (mixed_diff_type) { + out_data[0] = diff_data[0]; + i = 1; /* new start value */ + } + for (; i < num_val; i++) { + out_data[i] = prev_data[i] + diff_data[i]; + } +} + +static void diff_time_decode_forwards(const SCHAR* const prev_data, + const SCHAR* const diff_data, + SCHAR* const out_data, + const int mixed_diff_type, + const int num_val) { + int i = 0; /* default start value*/ + + if (mixed_diff_type) { + out_data[0] = diff_data[0]; + i = 1; /* new start value */ + } + for (; i < num_val; i++) { + out_data[i] = prev_data[i] - diff_data[i]; + } +} + +static ERROR_t attach_lsb(HANDLE_FDK_BITSTREAM strm, SCHAR* in_data_msb, + int offset, int num_lsb, int num_val, + SCHAR* out_data) { + int i = 0, lsb = 0; + ULONG data = 0; + + for (i = 0; i < num_val; i++) { + int msb; + msb = in_data_msb[i]; + + if (num_lsb > 0) { + data = FDKreadBits(strm, num_lsb); + lsb = data; + + out_data[i] = ((msb << num_lsb) | lsb) - offset; + } else + out_data[i] = msb - offset; + } + + return HUFFDEC_OK; /* dummy */ +} + +ERROR_t EcDataPairDec(DECODER_TYPE DECODER, HANDLE_FDK_BITSTREAM strm, + SCHAR* aaOutData1, SCHAR* aaOutData2, SCHAR* aHistory, + DATA_TYPE data_type, int startBand, int dataBands, + int pair_flag, int coarse_flag, + int allowDiffTimeBack_flag) + +{ + ERROR_t err = HUFFDEC_OK; + + // int allowDiffTimeBack_flag = !independency_flag || (setIdx > 0); + int attachLsb_flag = 0; + int pcmCoding_flag = 0; + + int mixed_time_pair = 0, numValPcm = 0; + int quant_levels = 0, quant_offset = 0; + ULONG data = 0; + + SCHAR aaDataPair[2][28] = {{0}}; + SCHAR aaDataDiff[2][28] = {{0}}; + + SCHAR aHistoryMsb[28] = {0}; + + SCHAR* pDataVec[2] = {NULL, NULL}; + + DIFF_TYPE diff_type[2] = {DIFF_FREQ, DIFF_FREQ}; + PAIRING pairing = FREQ_PAIR; + DIRECTION direction = BACKWARDS; + + switch (data_type) { + case t_CLD: + if (coarse_flag) { + attachLsb_flag = 0; + quant_levels = 15; + quant_offset = 7; + } else { + attachLsb_flag = 0; + quant_levels = 31; + quant_offset = 15; + } + + break; + + case t_ICC: + if (coarse_flag) { + attachLsb_flag = 0; + quant_levels = 4; + quant_offset = 0; + } else { + attachLsb_flag = 0; + quant_levels = 8; + quant_offset = 0; + } + + break; + + case t_OLD: + if (coarse_flag) { + attachLsb_flag = 0; + quant_levels = 8; + quant_offset = 0; + } else { + attachLsb_flag = 0; + quant_levels = 16; + quant_offset = 0; + } + break; + + case t_NRG: + if (coarse_flag) { + attachLsb_flag = 0; + quant_levels = 32; + quant_offset = 0; + } else { + attachLsb_flag = 0; + quant_levels = 64; + quant_offset = 0; + } + break; + + case t_IPD: + if (!coarse_flag) { + attachLsb_flag = 1; + quant_levels = 16; + quant_offset = 0; + } else { + attachLsb_flag = 0; + quant_levels = 8; + quant_offset = 0; + } + break; + + default: + return HUFFDEC_NOTOK; + } + + data = FDKreadBits(strm, 1); + pcmCoding_flag = data; + + if (pcmCoding_flag) { + if (pair_flag) { + pDataVec[0] = aaDataPair[0]; + pDataVec[1] = aaDataPair[1]; + numValPcm = 2 * dataBands; + } else { + pDataVec[0] = aaDataPair[0]; + pDataVec[1] = NULL; + numValPcm = dataBands; + } + + err = pcm_decode(strm, pDataVec[0], pDataVec[1], quant_offset, numValPcm, + quant_levels); + if (err != HUFFDEC_OK) return HUFFDEC_NOTOK; + + } else { /* Differential/Huffman/LSB Coding */ + + if (pair_flag) { + pDataVec[0] = aaDataDiff[0]; + pDataVec[1] = aaDataDiff[1]; + } else { + pDataVec[0] = aaDataDiff[0]; + pDataVec[1] = NULL; + } + + diff_type[0] = DIFF_FREQ; + diff_type[1] = DIFF_FREQ; + + direction = BACKWARDS; + { + if (pair_flag || allowDiffTimeBack_flag) { + data = FDKreadBits(strm, 1); + diff_type[0] = (DIFF_TYPE)data; + } + + if (pair_flag && + ((diff_type[0] == DIFF_FREQ) || allowDiffTimeBack_flag)) { + data = FDKreadBits(strm, 1); + diff_type[1] = (DIFF_TYPE)data; + } + } + /* Huffman decoding */ + err = huff_decode(strm, pDataVec[0], pDataVec[1], data_type, diff_type[0], + diff_type[1], dataBands, &pairing, + (DECODER == SAOC_DECODER)); + if (err != HUFFDEC_OK) { + return HUFFDEC_NOTOK; + } + + { + /* Differential decoding */ + if ((diff_type[0] == DIFF_TIME) || (diff_type[1] == DIFF_TIME)) { + if (DECODER == SAOC_DECODER) { + direction = BACKWARDS; + } else { + if (pair_flag) { + if ((diff_type[0] == DIFF_TIME) && !allowDiffTimeBack_flag) { + direction = FORWARDS; + } else if (diff_type[1] == DIFF_TIME) { + direction = BACKWARDS; + } else { + data = FDKreadBits(strm, 1); + direction = (DIRECTION)data; + } + } else { + direction = BACKWARDS; + } + } + } + + mixed_time_pair = + (diff_type[0] != diff_type[1]) && (pairing == TIME_PAIR); + + if (direction == BACKWARDS) { + if (diff_type[0] == DIFF_FREQ) { + diff_freq_decode(aaDataDiff[0], aaDataPair[0], dataBands); + } else { + int i; + for (i = 0; i < dataBands; i++) { + aHistoryMsb[i] = aHistory[i + startBand] + quant_offset; + if (attachLsb_flag) { + aHistoryMsb[i] >>= 1; + } + } + diff_time_decode_backwards(aHistoryMsb, aaDataDiff[0], aaDataPair[0], + mixed_time_pair, dataBands); + } + if (diff_type[1] == DIFF_FREQ) { + diff_freq_decode(aaDataDiff[1], aaDataPair[1], dataBands); + } else { + diff_time_decode_backwards(aaDataPair[0], aaDataDiff[1], + aaDataPair[1], mixed_time_pair, dataBands); + } + } else { + /* diff_type[1] MUST BE DIFF_FREQ */ + diff_freq_decode(aaDataDiff[1], aaDataPair[1], dataBands); + + if (diff_type[0] == DIFF_FREQ) { + diff_freq_decode(aaDataDiff[0], aaDataPair[0], dataBands); + } else { + diff_time_decode_forwards(aaDataPair[1], aaDataDiff[0], aaDataPair[0], + mixed_time_pair, dataBands); + } + } + } + + /* LSB decoding */ + err = attach_lsb(strm, aaDataPair[0], quant_offset, attachLsb_flag ? 1 : 0, + dataBands, aaDataPair[0]); + if (err != HUFFDEC_OK) goto bail; + + if (pair_flag) { + err = attach_lsb(strm, aaDataPair[1], quant_offset, + attachLsb_flag ? 1 : 0, dataBands, aaDataPair[1]); + if (err != HUFFDEC_OK) goto bail; + } + } /* End: Differential/Huffman/LSB Coding */ + + /* Copy data to output arrays */ + FDKmemcpy(aaOutData1 + startBand, aaDataPair[0], sizeof(SCHAR) * dataBands); + if (pair_flag) { + FDKmemcpy(aaOutData2 + startBand, aaDataPair[1], sizeof(SCHAR) * dataBands); + } + +bail: + return err; +} + +ERROR_t huff_dec_reshape(HANDLE_FDK_BITSTREAM strm, int* out_data, + int num_val) { + ERROR_t err = HUFFDEC_OK; + int val_rcvd = 0, dummy = 0, i = 0, val = 0, len = 0; + SCHAR rl_data[2] = {0}; + + while (val_rcvd < num_val) { + err = huff_read_2D(strm, + (HANDLE_HUFF_NODE)&FDK_huffReshapeNodes.nodeTab[0][0], + rl_data, &dummy); + if (err != HUFFDEC_OK) goto bail; + val = rl_data[0]; + len = rl_data[1] + 1; + if (val_rcvd + len > num_val) { + err = HUFFDEC_NOTOK; + goto bail; + } + for (i = val_rcvd; i < val_rcvd + len; i++) { + out_data[i] = val; + } + val_rcvd += len; + } +bail: + return err; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/qmf.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/qmf.cpp new file mode 100644 index 0000000000000..440bec20ad6a5 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/qmf.cpp @@ -0,0 +1,833 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Markus Lohwasser, Josef Hoepfl, Manuel Jander + + Description: QMF filterbank + +*******************************************************************************/ + +/*! + \file + \brief Complex qmf analysis/synthesis + This module contains the qmf filterbank for analysis [ + cplxAnalysisQmfFiltering() ] and synthesis [ cplxSynthesisQmfFiltering() ]. It + is a polyphase implementation of a complex exponential modulated filter bank. + The analysis part usually runs at half the sample rate than the synthesis + part. (So called "dual-rate" mode.) + + The coefficients of the prototype filter are specified in #qmf_pfilt640 (in + sbr_rom.cpp). Thus only a 64 channel version (32 on the analysis side) with a + 640 tap prototype filter are used. + + \anchor PolyphaseFiltering

About polyphase filtering

+ The polyphase implementation of a filterbank requires filtering at the input + and output. This is implemented as part of cplxAnalysisQmfFiltering() and + cplxSynthesisQmfFiltering(). The implementation requires the filter + coefficients in a specific structure as described in #sbr_qmf_64_640_qmf (in + sbr_rom.cpp). + + This module comprises the computationally most expensive functions of the SBR + decoder. The accuracy of computations is also important and has a direct + impact on the overall sound quality. Therefore a special test program is + available which can be used to only test the filterbank: main_audio.cpp + + This modules also uses scaling of data to provide better SNR on fixed-point + processors. See #QMF_SCALE_FACTOR (in sbr_scale.h) for details. An interesting + note: The function getScalefactor() can constitute a significant amount of + computational complexity - very much depending on the bitrate. Since it is a + rather small function, effective assembler optimization might be possible. + +*/ + +#include "qmf.h" + +#include "FDK_trigFcts.h" +#include "fixpoint_math.h" +#include "dct.h" + +#define QSSCALE (0) +#define FX_DBL2FX_QSS(x) (x) +#define FX_QSS2FX_DBL(x) (x) + +/* moved to qmf_pcm.h: -> qmfSynPrototypeFirSlot */ +/* moved to qmf_pcm.h: -> qmfSynPrototypeFirSlot_NonSymmetric */ +/* moved to qmf_pcm.h: -> qmfSynthesisFilteringSlot */ + +/*! + * + * \brief Perform real-valued forward modulation of the time domain + * data of timeIn and stores the real part of the subband + * samples in rSubband + * + */ +static void qmfForwardModulationLP_even( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + FIXP_DBL *timeIn, /*!< Time Signal */ + FIXP_DBL *rSubband) /*!< Real Output */ +{ + int i; + int L = anaQmf->no_channels; + int M = L >> 1; + int scale = 0; + FIXP_DBL accu; + + const FIXP_DBL *timeInTmp1 = (FIXP_DBL *)&timeIn[3 * M]; + const FIXP_DBL *timeInTmp2 = timeInTmp1; + FIXP_DBL *rSubbandTmp = rSubband; + + rSubband[0] = timeIn[3 * M] >> 1; + + for (i = M - 1; i != 0; i--) { + accu = ((*--timeInTmp1) >> 1) + ((*++timeInTmp2) >> 1); + *++rSubbandTmp = accu; + } + + timeInTmp1 = &timeIn[2 * M]; + timeInTmp2 = &timeIn[0]; + rSubbandTmp = &rSubband[M]; + + for (i = L - M; i != 0; i--) { + accu = ((*timeInTmp1--) >> 1) - ((*timeInTmp2++) >> 1); + *rSubbandTmp++ = accu; + } + + dct_III(rSubband, timeIn, L, &scale); +} + +#if !defined(FUNCTION_qmfForwardModulationLP_odd) +static void qmfForwardModulationLP_odd( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + const FIXP_DBL *timeIn, /*!< Time Signal */ + FIXP_DBL *rSubband) /*!< Real Output */ +{ + int i; + int L = anaQmf->no_channels; + int M = L >> 1; + int shift = (anaQmf->no_channels >> 6) + 1; + + for (i = 0; i < M; i++) { + rSubband[M + i] = (timeIn[L - 1 - i] >> 1) - (timeIn[i] >> shift); + rSubband[M - 1 - i] = + (timeIn[L + i] >> 1) + (timeIn[2 * L - 1 - i] >> shift); + } + + dct_IV(rSubband, L, &shift); +} +#endif /* !defined(FUNCTION_qmfForwardModulationLP_odd) */ + +/*! + * + * \brief Perform complex-valued forward modulation of the time domain + * data of timeIn and stores the real part of the subband + * samples in rSubband, and the imaginary part in iSubband + * + * + */ +#if !defined(FUNCTION_qmfForwardModulationHQ) +static void qmfForwardModulationHQ( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + const FIXP_DBL *RESTRICT timeIn, /*!< Time Signal */ + FIXP_DBL *RESTRICT rSubband, /*!< Real Output */ + FIXP_DBL *RESTRICT iSubband /*!< Imaginary Output */ +) { + int i; + int L = anaQmf->no_channels; + int L2 = L << 1; + int shift = 0; + + /* Time advance by one sample, which is equivalent to the complex + rotation at the end of the analysis. Works only for STD mode. */ + if ((L == 64) && !(anaQmf->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) { + FIXP_DBL x, y; + + /*rSubband[0] = u[1] + u[0]*/ + /*iSubband[0] = u[1] - u[0]*/ + x = timeIn[1] >> 1; + y = timeIn[0]; + rSubband[0] = x + (y >> 1); + iSubband[0] = x - (y >> 1); + + /*rSubband[n] = u[n+1] - u[2M-n], n=1,...,M-1*/ + /*iSubband[n] = u[n+1] + u[2M-n], n=1,...,M-1*/ + for (i = 1; i < L; i++) { + x = timeIn[i + 1] >> 1; /*u[n+1] */ + y = timeIn[L2 - i]; /*u[2M-n] */ + rSubband[i] = x - (y >> 1); + iSubband[i] = x + (y >> 1); + } + } else { + for (i = 0; i < L; i += 2) { + FIXP_DBL x0, x1, y0, y1; + + x0 = timeIn[i + 0] >> 1; + x1 = timeIn[i + 1] >> 1; + y0 = timeIn[L2 - 1 - i]; + y1 = timeIn[L2 - 2 - i]; + + rSubband[i + 0] = x0 - (y0 >> 1); + rSubband[i + 1] = x1 - (y1 >> 1); + iSubband[i + 0] = x0 + (y0 >> 1); + iSubband[i + 1] = x1 + (y1 >> 1); + } + } + + dct_IV(rSubband, L, &shift); + dst_IV(iSubband, L, &shift); + + /* Do the complex rotation except for the case of 64 bands (in STD mode). */ + if ((L != 64) || (anaQmf->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) { + if (anaQmf->flags & QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION) { + FIXP_DBL iBand; + for (i = 0; i < fMin(anaQmf->lsb, L); i += 2) { + iBand = rSubband[i]; + rSubband[i] = -iSubband[i]; + iSubband[i] = iBand; + + iBand = -rSubband[i + 1]; + rSubband[i + 1] = iSubband[i + 1]; + iSubband[i + 1] = iBand; + } + } else { + const FIXP_QTW *sbr_t_cos; + const FIXP_QTW *sbr_t_sin; + const int len = L; /* was len = fMin(anaQmf->lsb, L) but in case of USAC + the signal above lsb is actually needed in some + cases (HBE?) */ + sbr_t_cos = anaQmf->t_cos; + sbr_t_sin = anaQmf->t_sin; + + for (i = 0; i < len; i++) { + cplxMult(&iSubband[i], &rSubband[i], iSubband[i], rSubband[i], + sbr_t_cos[i], sbr_t_sin[i]); + } + } + } +} +#endif /* FUNCTION_qmfForwardModulationHQ */ + +/*! + * + * \brief Perform low power inverse modulation of the subband + * samples stored in rSubband (real part) and iSubband (imaginary + * part) and stores the result in pWorkBuffer. + * + */ +inline static void qmfInverseModulationLP_even( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot (input) */ + const int scaleFactorLowBand, /*!< Scalefactor for Low band */ + const int scaleFactorHighBand, /*!< Scalefactor for High band */ + FIXP_DBL *pTimeOut /*!< Pointer to qmf subband slot (output)*/ +) { + int i; + int L = synQmf->no_channels; + int M = L >> 1; + int scale = 0; + FIXP_DBL tmp; + FIXP_DBL *RESTRICT tReal = pTimeOut; + FIXP_DBL *RESTRICT tImag = pTimeOut + L; + + /* Move input to output vector with offset */ + scaleValuesSaturate(&tReal[0], &qmfReal[0], synQmf->lsb, scaleFactorLowBand); + scaleValuesSaturate(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb], + synQmf->usb - synQmf->lsb, scaleFactorHighBand); + FDKmemclear(&tReal[0 + synQmf->usb], (L - synQmf->usb) * sizeof(FIXP_DBL)); + + /* Dct type-2 transform */ + dct_II(tReal, tImag, L, &scale); + + /* Expand output and replace inplace the output buffers */ + tImag[0] = tReal[M]; + tImag[M] = (FIXP_DBL)0; + tmp = tReal[0]; + tReal[0] = tReal[M]; + tReal[M] = tmp; + + for (i = 1; i < M / 2; i++) { + /* Imag */ + tmp = tReal[L - i]; + tImag[M - i] = tmp; + tImag[i + M] = -tmp; + + tmp = tReal[M + i]; + tImag[i] = tmp; + tImag[L - i] = -tmp; + + /* Real */ + tReal[M + i] = tReal[i]; + tReal[L - i] = tReal[M - i]; + tmp = tReal[i]; + tReal[i] = tReal[M - i]; + tReal[M - i] = tmp; + } + /* Remaining odd terms */ + tmp = tReal[M + M / 2]; + tImag[M / 2] = tmp; + tImag[M / 2 + M] = -tmp; + + tReal[M + M / 2] = tReal[M / 2]; +} + +inline static void qmfInverseModulationLP_odd( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot (input) */ + const int scaleFactorLowBand, /*!< Scalefactor for Low band */ + const int scaleFactorHighBand, /*!< Scalefactor for High band */ + FIXP_DBL *pTimeOut /*!< Pointer to qmf subband slot (output)*/ +) { + int i; + int L = synQmf->no_channels; + int M = L >> 1; + int shift = 0; + + /* Move input to output vector with offset */ + scaleValuesSaturate(pTimeOut + M, qmfReal, synQmf->lsb, scaleFactorLowBand); + scaleValuesSaturate(pTimeOut + M + synQmf->lsb, qmfReal + synQmf->lsb, + synQmf->usb - synQmf->lsb, scaleFactorHighBand); + FDKmemclear(pTimeOut + M + synQmf->usb, (L - synQmf->usb) * sizeof(FIXP_DBL)); + + dct_IV(pTimeOut + M, L, &shift); + for (i = 0; i < M; i++) { + pTimeOut[i] = pTimeOut[L - 1 - i]; + pTimeOut[2 * L - 1 - i] = -pTimeOut[L + i]; + } +} + +#ifndef FUNCTION_qmfInverseModulationHQ +/*! + * + * \brief Perform complex-valued inverse modulation of the subband + * samples stored in rSubband (real part) and iSubband (imaginary + * part) and stores the result in pWorkBuffer. + * + */ +inline static void qmfInverseModulationHQ( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot */ + const FIXP_DBL *qmfImag, /*!< Pointer to qmf imag subband slot */ + const int scaleFactorLowBand, /*!< Scalefactor for Low band */ + const int scaleFactorHighBand, /*!< Scalefactor for High band */ + FIXP_DBL *pWorkBuffer /*!< WorkBuffer (output) */ +) { + int i; + int L = synQmf->no_channels; + int M = L >> 1; + int shift = 0; + FIXP_DBL *RESTRICT tReal = pWorkBuffer; + FIXP_DBL *RESTRICT tImag = pWorkBuffer + L; + + if (synQmf->flags & QMF_FLAG_CLDFB) { + for (i = 0; i < synQmf->usb; i++) { + cplxMultDiv2(&tImag[i], &tReal[i], qmfImag[i], qmfReal[i], + synQmf->t_cos[i], synQmf->t_sin[i]); + } + scaleValuesSaturate(&tReal[0], synQmf->lsb, scaleFactorLowBand + 1); + scaleValuesSaturate(&tReal[0 + synQmf->lsb], synQmf->usb - synQmf->lsb, + scaleFactorHighBand + 1); + scaleValuesSaturate(&tImag[0], synQmf->lsb, scaleFactorLowBand + 1); + scaleValuesSaturate(&tImag[0 + synQmf->lsb], synQmf->usb - synQmf->lsb, + scaleFactorHighBand + 1); + } + + if ((synQmf->flags & QMF_FLAG_CLDFB) == 0) { + scaleValuesSaturate(&tReal[0], &qmfReal[0], synQmf->lsb, + scaleFactorLowBand); + scaleValuesSaturate(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb], + synQmf->usb - synQmf->lsb, scaleFactorHighBand); + scaleValuesSaturate(&tImag[0], &qmfImag[0], synQmf->lsb, + scaleFactorLowBand); + scaleValuesSaturate(&tImag[0 + synQmf->lsb], &qmfImag[0 + synQmf->lsb], + synQmf->usb - synQmf->lsb, scaleFactorHighBand); + } + + FDKmemclear(&tReal[synQmf->usb], + (synQmf->no_channels - synQmf->usb) * sizeof(FIXP_DBL)); + FDKmemclear(&tImag[synQmf->usb], + (synQmf->no_channels - synQmf->usb) * sizeof(FIXP_DBL)); + + dct_IV(tReal, L, &shift); + dst_IV(tImag, L, &shift); + + if (synQmf->flags & QMF_FLAG_CLDFB) { + for (i = 0; i < M; i++) { + FIXP_DBL r1, i1, r2, i2; + r1 = tReal[i]; + i2 = tImag[L - 1 - i]; + r2 = tReal[L - i - 1]; + i1 = tImag[i]; + + tReal[i] = (r1 - i1) >> 1; + tImag[L - 1 - i] = -(r1 + i1) >> 1; + tReal[L - i - 1] = (r2 - i2) >> 1; + tImag[i] = -(r2 + i2) >> 1; + } + } else { + /* The array accesses are negative to compensate the missing minus sign in + * the low and hi band gain. */ + /* 26 cycles on ARM926 */ + for (i = 0; i < M; i++) { + FIXP_DBL r1, i1, r2, i2; + r1 = -tReal[i]; + i2 = -tImag[L - 1 - i]; + r2 = -tReal[L - i - 1]; + i1 = -tImag[i]; + + tReal[i] = (r1 - i1) >> 1; + tImag[L - 1 - i] = -(r1 + i1) >> 1; + tReal[L - i - 1] = (r2 - i2) >> 1; + tImag[i] = -(r2 + i2) >> 1; + } + } +} +#endif /* #ifndef FUNCTION_qmfInverseModulationHQ */ + +/*! + * + * \brief Create QMF filter bank instance + * + * \return 0 if successful + * + */ +static int qmfInitFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Handle to return */ + void *pFilterStates, /*!< Handle to filter states */ + int noCols, /*!< Number of timeslots per frame */ + int lsb, /*!< Lower end of QMF frequency range */ + int usb, /*!< Upper end of QMF frequency range */ + int no_channels, /*!< Number of channels (bands) */ + UINT flags, /*!< flags */ + int synflag) /*!< 1: synthesis; 0: analysis */ +{ + FDKmemclear(h_Qmf, sizeof(QMF_FILTER_BANK)); + + if (flags & QMF_FLAG_MPSLDFB) { + flags |= QMF_FLAG_NONSYMMETRIC; + flags |= QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION; + + h_Qmf->t_cos = NULL; + h_Qmf->t_sin = NULL; + h_Qmf->filterScale = QMF_MPSLDFB_PFT_SCALE; + h_Qmf->p_stride = 1; + + switch (no_channels) { + case 64: + h_Qmf->p_filter = qmf_mpsldfb_640; + h_Qmf->FilterSize = 640; + break; + case 32: + h_Qmf->p_filter = qmf_mpsldfb_320; + h_Qmf->FilterSize = 320; + break; + default: + return -1; + } + } + + if (!(flags & QMF_FLAG_MPSLDFB) && (flags & QMF_FLAG_CLDFB)) { + flags |= QMF_FLAG_NONSYMMETRIC; + h_Qmf->filterScale = QMF_CLDFB_PFT_SCALE; + + h_Qmf->p_stride = 1; + switch (no_channels) { + case 64: + h_Qmf->t_cos = qmf_phaseshift_cos64_cldfb; + h_Qmf->t_sin = qmf_phaseshift_sin64_cldfb; + h_Qmf->p_filter = qmf_cldfb_640; + h_Qmf->FilterSize = 640; + break; + case 32: + h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos32_cldfb_syn + : qmf_phaseshift_cos32_cldfb_ana; + h_Qmf->t_sin = qmf_phaseshift_sin32_cldfb; + h_Qmf->p_filter = qmf_cldfb_320; + h_Qmf->FilterSize = 320; + break; + case 16: + h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos16_cldfb_syn + : qmf_phaseshift_cos16_cldfb_ana; + h_Qmf->t_sin = qmf_phaseshift_sin16_cldfb; + h_Qmf->p_filter = qmf_cldfb_160; + h_Qmf->FilterSize = 160; + break; + case 8: + h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos8_cldfb_syn + : qmf_phaseshift_cos8_cldfb_ana; + h_Qmf->t_sin = qmf_phaseshift_sin8_cldfb; + h_Qmf->p_filter = qmf_cldfb_80; + h_Qmf->FilterSize = 80; + break; + default: + return -1; + } + } + + if (!(flags & QMF_FLAG_MPSLDFB) && ((flags & QMF_FLAG_CLDFB) == 0)) { + switch (no_channels) { + case 64: + h_Qmf->p_filter = qmf_pfilt640; + h_Qmf->t_cos = qmf_phaseshift_cos64; + h_Qmf->t_sin = qmf_phaseshift_sin64; + h_Qmf->p_stride = 1; + h_Qmf->FilterSize = 640; + h_Qmf->filterScale = 0; + break; + case 40: + if (synflag) { + break; + } else { + h_Qmf->p_filter = qmf_pfilt400; /* Scaling factor 0.8 */ + h_Qmf->t_cos = qmf_phaseshift_cos40; + h_Qmf->t_sin = qmf_phaseshift_sin40; + h_Qmf->filterScale = 1; + h_Qmf->p_stride = 1; + h_Qmf->FilterSize = no_channels * 10; + } + break; + case 32: + h_Qmf->p_filter = qmf_pfilt640; + if (flags & QMF_FLAG_DOWNSAMPLED) { + h_Qmf->t_cos = qmf_phaseshift_cos_downsamp32; + h_Qmf->t_sin = qmf_phaseshift_sin_downsamp32; + } else { + h_Qmf->t_cos = qmf_phaseshift_cos32; + h_Qmf->t_sin = qmf_phaseshift_sin32; + } + h_Qmf->p_stride = 2; + h_Qmf->FilterSize = 640; + h_Qmf->filterScale = 0; + break; + case 20: + h_Qmf->p_filter = qmf_pfilt200; + h_Qmf->p_stride = 1; + h_Qmf->FilterSize = 200; + h_Qmf->filterScale = 0; + break; + case 12: + h_Qmf->p_filter = qmf_pfilt120; + h_Qmf->p_stride = 1; + h_Qmf->FilterSize = 120; + h_Qmf->filterScale = 0; + break; + case 8: + h_Qmf->p_filter = qmf_pfilt640; + h_Qmf->p_stride = 8; + h_Qmf->FilterSize = 640; + h_Qmf->filterScale = 0; + break; + case 16: + h_Qmf->p_filter = qmf_pfilt640; + h_Qmf->t_cos = qmf_phaseshift_cos16; + h_Qmf->t_sin = qmf_phaseshift_sin16; + h_Qmf->p_stride = 4; + h_Qmf->FilterSize = 640; + h_Qmf->filterScale = 0; + break; + case 24: + h_Qmf->p_filter = qmf_pfilt240; + h_Qmf->t_cos = qmf_phaseshift_cos24; + h_Qmf->t_sin = qmf_phaseshift_sin24; + h_Qmf->p_stride = 1; + h_Qmf->FilterSize = 240; + h_Qmf->filterScale = 1; + break; + default: + return -1; + } + } + + h_Qmf->synScalefactor = h_Qmf->filterScale; + // DCT|DST dependency + switch (no_channels) { + case 128: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + 1; + break; + case 40: { + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1; + } break; + case 64: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK; + break; + case 8: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 3; + break; + case 12: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK; + break; + case 20: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + 1; + break; + case 32: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1; + break; + case 16: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 2; + break; + case 24: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1; + break; + default: + return -1; + } + + h_Qmf->flags = flags; + + h_Qmf->no_channels = no_channels; + h_Qmf->no_col = noCols; + + h_Qmf->lsb = fMin(lsb, h_Qmf->no_channels); + h_Qmf->usb = synflag + ? fMin(usb, h_Qmf->no_channels) + : usb; /* was: h_Qmf->usb = fMin(usb, h_Qmf->no_channels); */ + + h_Qmf->FilterStates = (void *)pFilterStates; + + h_Qmf->outScalefactor = + (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + h_Qmf->filterScale) + + h_Qmf->synScalefactor; + + h_Qmf->outGain_m = + (FIXP_DBL)0x80000000; /* default init value will be not applied */ + h_Qmf->outGain_e = 0; + + return (0); +} + +/*! + * + * \brief Adjust synthesis qmf filter states + * + * \return void + * + */ +static inline void qmfAdaptFilterStates( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Filter Bank */ + int scaleFactorDiff) /*!< Scale factor difference to be applied */ +{ + if (synQmf == NULL || synQmf->FilterStates == NULL) { + return; + } + if (scaleFactorDiff > 0) { + scaleValuesSaturate((FIXP_QSS *)synQmf->FilterStates, + synQmf->no_channels * (QMF_NO_POLY * 2 - 1), + scaleFactorDiff); + } else { + scaleValues((FIXP_QSS *)synQmf->FilterStates, + synQmf->no_channels * (QMF_NO_POLY * 2 - 1), scaleFactorDiff); + } +} + +/*! + * + * \brief Create QMF filter bank instance + * + * + * \return 0 if succesful + * + */ +int qmfInitSynthesisFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ + FIXP_QSS *pFilterStates, /*!< Handle to filter states */ + int noCols, /*!< Number of timeslots per frame */ + int lsb, /*!< lower end of QMF */ + int usb, /*!< upper end of QMF */ + int no_channels, /*!< Number of channels (bands) */ + int flags) /*!< Low Power flag */ +{ + int oldOutScale = h_Qmf->outScalefactor; + int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, + no_channels, flags, 1); + if (h_Qmf->FilterStates != NULL) { + if (!(flags & QMF_FLAG_KEEP_STATES)) { + FDKmemclear( + h_Qmf->FilterStates, + (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QSS)); + } else { + qmfAdaptFilterStates(h_Qmf, oldOutScale - h_Qmf->outScalefactor); + } + } + + FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb); + FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->usb); + + return err; +} + +/*! + * + * \brief Change scale factor for output data and adjust qmf filter states + * + * \return void + * + */ +void qmfChangeOutScalefactor( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + int outScalefactor /*!< New scaling factor for output data */ +) { + if (synQmf == NULL) { + return; + } + + /* Add internal filterbank scale */ + outScalefactor += + (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + synQmf->filterScale) + + synQmf->synScalefactor; + + /* adjust filter states when scale factor has been changed */ + if (synQmf->outScalefactor != outScalefactor) { + int diff; + + diff = synQmf->outScalefactor - outScalefactor; + + qmfAdaptFilterStates(synQmf, diff); + + /* save new scale factor */ + synQmf->outScalefactor = outScalefactor; + } +} + +/*! + * + * \brief Get scale factor change which was set by qmfChangeOutScalefactor() + * + * \return scaleFactor + * + */ +int qmfGetOutScalefactor( + HANDLE_QMF_FILTER_BANK synQmf) /*!< Handle of Qmf Synthesis Bank */ +{ + int scaleFactor = synQmf->outScalefactor + ? (synQmf->outScalefactor - + (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + + synQmf->filterScale + synQmf->synScalefactor)) + : 0; + return scaleFactor; +} + +/*! + * + * \brief Change gain for output data + * + * \return void + * + */ +void qmfChangeOutGain( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL outputGain, /*!< New gain for output data (mantissa) */ + int outputGainScale /*!< New gain for output data (exponent) */ +) { + synQmf->outGain_m = outputGain; + synQmf->outGain_e = outputGainScale; +} + +#define INT_PCM_QMFOUT INT_PCM +#define SAMPLE_BITS_QMFOUT SAMPLE_BITS +#include "qmf_pcm.h" +#if SAMPLE_BITS == 16 + /* also create a 32 bit output version */ +#undef INT_PCM_QMFOUT +#undef SAMPLE_BITS_QMFOUT +#undef QMF_PCM_H +#undef FIXP_QAS +#undef QAS_BITS +#undef INT_PCM_QMFIN +#define INT_PCM_QMFOUT LONG +#define SAMPLE_BITS_QMFOUT 32 +#define FIXP_QAS FIXP_DBL +#define QAS_BITS 32 +#define INT_PCM_QMFIN LONG +#include "qmf_pcm.h" +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/scale.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/scale.cpp new file mode 100644 index 0000000000000..6192170d009f6 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libFDK/src/scale.cpp @@ -0,0 +1,720 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: Scaling operations + +*******************************************************************************/ + +#include "common_fix.h" + +#include "genericStds.h" + +/************************************************** + * Inline definitions + **************************************************/ + +#include "scale.h" + +#if defined(__mips__) +#include "mips/scale_mips.cpp" + +#elif defined(__arm__) +#include "arm/scale_arm.cpp" + +#endif + +#ifndef FUNCTION_scaleValues_SGL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param len must be larger than 4 + * \return void + * + */ +#define FUNCTION_scaleValues_SGL +void scaleValues(FIXP_SGL *vector, /*!< Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) return; + + if (scalefactor > 0) { + scalefactor = fixmin_I(scalefactor, (INT)(FRACT_BITS - 1)); + for (i = len & 3; i--;) { + *(vector++) <<= scalefactor; + } + for (i = len >> 2; i--;) { + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor, (INT)FRACT_BITS - 1); + for (i = len & 3; i--;) { + *(vector++) >>= negScalefactor; + } + for (i = len >> 2; i--;) { + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + } + } +} +#endif + +#ifndef FUNCTION_scaleValues_DBL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param len must be larger than 4 + * \return void + * + */ +#define FUNCTION_scaleValues_DBL +SCALE_INLINE +void scaleValues(FIXP_DBL *vector, /*!< Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) return; + + if (scalefactor > 0) { + scalefactor = fixmin_I(scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(vector++) <<= scalefactor; + } + for (i = len >> 2; i--;) { + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(vector++) >>= negScalefactor; + } + for (i = len >> 2; i--;) { + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + } + } +} +#endif + +#ifndef FUNCTION_scaleValuesSaturate_DBL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param vector source/destination buffer + * \param len length of vector + * \param scalefactor amount of shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValuesSaturate_DBL +SCALE_INLINE +void scaleValuesSaturate(FIXP_DBL *vector, /*!< Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) return; + + scalefactor = fixmax_I(fixmin_I(scalefactor, (INT)DFRACT_BITS - 1), + (INT) - (DFRACT_BITS - 1)); + + for (i = 0; i < len; i++) { + vector[i] = scaleValueSaturate(vector[i], scalefactor); + } +} +#endif /* FUNCTION_scaleValuesSaturate_DBL */ + +#ifndef FUNCTION_scaleValuesSaturate_DBL_DBL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param dst destination buffer + * \param src source buffer + * \param len length of vector + * \param scalefactor amount of shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValuesSaturate_DBL_DBL +SCALE_INLINE +void scaleValuesSaturate(FIXP_DBL *dst, /*!< Output */ + const FIXP_DBL *src, /*!< Input */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) { + FDKmemmove(dst, src, len * sizeof(FIXP_DBL)); + return; + } + + scalefactor = fixmax_I(fixmin_I(scalefactor, (INT)DFRACT_BITS - 1), + (INT) - (DFRACT_BITS - 1)); + + for (i = 0; i < len; i++) { + dst[i] = scaleValueSaturate(src[i], scalefactor); + } +} +#endif /* FUNCTION_scaleValuesSaturate_DBL_DBL */ + +#ifndef FUNCTION_scaleValuesSaturate_SGL_DBL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param dst destination buffer (FIXP_SGL) + * \param src source buffer (FIXP_DBL) + * \param len length of vector + * \param scalefactor amount of shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValuesSaturate_SGL_DBL +SCALE_INLINE +void scaleValuesSaturate(FIXP_SGL *dst, /*!< Output */ + const FIXP_DBL *src, /*!< Input */ + INT len, /*!< Length */ + INT scalefactor) /*!< Scalefactor */ +{ + INT i; + scalefactor = fixmax_I(fixmin_I(scalefactor, (INT)DFRACT_BITS - 1), + (INT) - (DFRACT_BITS - 1)); + + for (i = 0; i < len; i++) { + dst[i] = FX_DBL2FX_SGL(fAddSaturate(scaleValueSaturate(src[i], scalefactor), + (FIXP_DBL)0x8000)); + } +} +#endif /* FUNCTION_scaleValuesSaturate_SGL_DBL */ + +#ifndef FUNCTION_scaleValuesSaturate_SGL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param vector source/destination buffer + * \param len length of vector + * \param scalefactor amount of shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValuesSaturate_SGL +SCALE_INLINE +void scaleValuesSaturate(FIXP_SGL *vector, /*!< Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) return; + + scalefactor = fixmax_I(fixmin_I(scalefactor, (INT)DFRACT_BITS - 1), + (INT) - (DFRACT_BITS - 1)); + + for (i = 0; i < len; i++) { + vector[i] = FX_DBL2FX_SGL( + scaleValueSaturate(FX_SGL2FX_DBL(vector[i]), scalefactor)); + } +} +#endif /* FUNCTION_scaleValuesSaturate_SGL */ + +#ifndef FUNCTION_scaleValuesSaturate_SGL_SGL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param dst destination buffer + * \param src source buffer + * \param len length of vector + * \param scalefactor amount of shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValuesSaturate_SGL_SGL +SCALE_INLINE +void scaleValuesSaturate(FIXP_SGL *dst, /*!< Output */ + const FIXP_SGL *src, /*!< Input */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) { + FDKmemmove(dst, src, len * sizeof(FIXP_SGL)); + return; + } + + scalefactor = fixmax_I(fixmin_I(scalefactor, (INT)DFRACT_BITS - 1), + (INT) - (DFRACT_BITS - 1)); + + for (i = 0; i < len; i++) { + dst[i] = + FX_DBL2FX_SGL(scaleValueSaturate(FX_SGL2FX_DBL(src[i]), scalefactor)); + } +} +#endif /* FUNCTION_scaleValuesSaturate_SGL_SGL */ + +#ifndef FUNCTION_scaleValues_DBLDBL +/*! + * + * \brief Multiply input vector src by \f$ 2^{scalefactor} \f$ + * and place result into dst + * \param dst detination buffer + * \param src source buffer + * \param len must be larger than 4 + * \param scalefactor amount of left shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValues_DBLDBL +SCALE_INLINE +void scaleValues(FIXP_DBL *dst, /*!< dst Vector */ + const FIXP_DBL *src, /*!< src Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) { + if (dst != src) FDKmemmove(dst, src, len * sizeof(FIXP_DBL)); + } else { + if (scalefactor > 0) { + scalefactor = fixmin_I(scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(dst++) = *(src++) << scalefactor; + } + for (i = len >> 2; i--;) { + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(dst++) = *(src++) >> negScalefactor; + } + for (i = len >> 2; i--;) { + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + } + } + } +} +#endif + +#if (SAMPLE_BITS == 16) +#ifndef FUNCTION_scaleValues_PCMDBL +/*! + * + * \brief Multiply input vector src by \f$ 2^{scalefactor} \f$ + * and place result into dst + * \param dst detination buffer + * \param src source buffer + * \param len must be larger than 4 + * \param scalefactor amount of left shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValues_PCMDBL +SCALE_INLINE +void scaleValues(FIXP_PCM *dst, /*!< dst Vector */ + const FIXP_DBL *src, /*!< src Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + scalefactor -= DFRACT_BITS - SAMPLE_BITS; + + /* Return if scalefactor is Zero */ + { + if (scalefactor > 0) { + scalefactor = fixmin_I(scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(dst++) = (FIXP_PCM)(*(src++) << scalefactor); + } + for (i = len >> 2; i--;) { + *(dst++) = (FIXP_PCM)(*(src++) << scalefactor); + *(dst++) = (FIXP_PCM)(*(src++) << scalefactor); + *(dst++) = (FIXP_PCM)(*(src++) << scalefactor); + *(dst++) = (FIXP_PCM)(*(src++) << scalefactor); + } + } else { + INT negScalefactor = fixmin_I(-scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(dst++) = (FIXP_PCM)(*(src++) >> negScalefactor); + } + for (i = len >> 2; i--;) { + *(dst++) = (FIXP_PCM)(*(src++) >> negScalefactor); + *(dst++) = (FIXP_PCM)(*(src++) >> negScalefactor); + *(dst++) = (FIXP_PCM)(*(src++) >> negScalefactor); + *(dst++) = (FIXP_PCM)(*(src++) >> negScalefactor); + } + } + } +} +#endif +#endif /* (SAMPLE_BITS == 16) */ + +#ifndef FUNCTION_scaleValues_SGLSGL +/*! + * + * \brief Multiply input vector src by \f$ 2^{scalefactor} \f$ + * and place result into dst + * \param dst detination buffer + * \param src source buffer + * \param len must be larger than 4 + * \param scalefactor amount of left shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValues_SGLSGL +SCALE_INLINE +void scaleValues(FIXP_SGL *dst, /*!< dst Vector */ + const FIXP_SGL *src, /*!< src Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) { + if (dst != src) FDKmemmove(dst, src, len * sizeof(FIXP_DBL)); + } else { + if (scalefactor > 0) { + scalefactor = fixmin_I(scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(dst++) = *(src++) << scalefactor; + } + for (i = len >> 2; i--;) { + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(dst++) = *(src++) >> negScalefactor; + } + for (i = len >> 2; i--;) { + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + } + } + } +} +#endif + +#ifndef FUNCTION_scaleValuesWithFactor_DBL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param len must be larger than 4 + * \return void + * + */ +#define FUNCTION_scaleValuesWithFactor_DBL +SCALE_INLINE +void scaleValuesWithFactor(FIXP_DBL *vector, FIXP_DBL factor, INT len, + INT scalefactor) { + INT i; + + /* Compensate fMultDiv2 */ + scalefactor++; + + if (scalefactor > 0) { + scalefactor = fixmin_I(scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *vector = fMultDiv2(*vector, factor) << scalefactor; + vector++; + } + for (i = len >> 2; i--;) { + *vector = fMultDiv2(*vector, factor) << scalefactor; + vector++; + *vector = fMultDiv2(*vector, factor) << scalefactor; + vector++; + *vector = fMultDiv2(*vector, factor) << scalefactor; + vector++; + *vector = fMultDiv2(*vector, factor) << scalefactor; + vector++; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *vector = fMultDiv2(*vector, factor) >> negScalefactor; + vector++; + } + for (i = len >> 2; i--;) { + *vector = fMultDiv2(*vector, factor) >> negScalefactor; + vector++; + *vector = fMultDiv2(*vector, factor) >> negScalefactor; + vector++; + *vector = fMultDiv2(*vector, factor) >> negScalefactor; + vector++; + *vector = fMultDiv2(*vector, factor) >> negScalefactor; + vector++; + } + } +} +#endif /* FUNCTION_scaleValuesWithFactor_DBL */ + + /******************************************* + + IMPORTANT NOTE for usage of getScalefactor() + + If the input array contains negative values too, then these functions may + sometimes return the actual maximum value minus 1, due to the nature of the + applied algorithm. So be careful with possible fractional -1 values that may + lead to overflows when being fPow2()'ed. + + ********************************************/ + +#ifndef FUNCTION_getScalefactorShort +/*! + * + * \brief Calculate max possible scale factor for input vector of shorts + * + * \return Maximum scale factor / possible left shift + * + */ +#define FUNCTION_getScalefactorShort +SCALE_INLINE +INT getScalefactorShort(const SHORT *vector, /*!< Pointer to input vector */ + INT len /*!< Length of input vector */ +) { + INT i; + SHORT temp, maxVal = 0; + + for (i = len; i != 0; i--) { + temp = (SHORT)(*vector++); + maxVal |= (temp ^ (temp >> (SHORT_BITS - 1))); + } + + return fixmax_I((INT)0, (INT)(fixnormz_D((INT)maxVal) - (INT)1 - + (INT)(DFRACT_BITS - SHORT_BITS))); +} +#endif + +#ifndef FUNCTION_getScalefactorPCM +/*! + * + * \brief Calculate max possible scale factor for input vector of shorts + * + * \return Maximum scale factor + * + */ +#define FUNCTION_getScalefactorPCM +SCALE_INLINE +INT getScalefactorPCM(const INT_PCM *vector, /*!< Pointer to input vector */ + INT len, /*!< Length of input vector */ + INT stride) { + INT i; + INT_PCM temp, maxVal = 0; + + for (i = len; i != 0; i--) { + temp = (INT_PCM)(*vector); + vector += stride; + maxVal |= (temp ^ (temp >> ((sizeof(INT_PCM) * 8) - 1))); + } + return fixmax_I((INT)0, (INT)(fixnormz_D((INT)maxVal) - (INT)1 - + (INT)(DFRACT_BITS - SAMPLE_BITS))); +} +#endif + +#ifndef FUNCTION_getScalefactorShort +/*! + * + * \brief Calculate max possible scale factor for input vector of shorts + * \param stride, item increment between vector members. + * \return Maximum scale factor + * + */ +#define FUNCTION_getScalefactorShort +SCALE_INLINE +INT getScalefactorShort(const SHORT *vector, /*!< Pointer to input vector */ + INT len, /*!< Length of input vector */ + INT stride) { + INT i; + SHORT temp, maxVal = 0; + + for (i = len; i != 0; i--) { + temp = (SHORT)(*vector); + vector += stride; + maxVal |= (temp ^ (temp >> (SHORT_BITS - 1))); + } + + return fixmax_I((INT)0, (INT)(fixnormz_D((INT)maxVal) - (INT)1 - + (INT)(DFRACT_BITS - SHORT_BITS))); +} +#endif + +#ifndef FUNCTION_getScalefactor_DBL +/*! + * + * \brief Calculate max possible scale factor for input vector + * + * \return Maximum scale factor + * + * This function can constitute a significant amount of computational + * complexity - very much depending on the bitrate. Since it is a rather small + * function, effective assembler optimization might be possible. + * + * If all data is 0xFFFF.FFFF or 0x0000.0000 function returns 31 + * Note: You can skip data normalization only if return value is 0 + * + */ +#define FUNCTION_getScalefactor_DBL +SCALE_INLINE +INT getScalefactor(const FIXP_DBL *vector, /*!< Pointer to input vector */ + INT len) /*!< Length of input vector */ +{ + INT i; + FIXP_DBL temp, maxVal = (FIXP_DBL)0; + + for (i = len; i != 0; i--) { + temp = (LONG)(*vector++); + maxVal |= (FIXP_DBL)((LONG)temp ^ (LONG)(temp >> (DFRACT_BITS - 1))); + } + + return fixmax_I((INT)0, (INT)(fixnormz_D(maxVal) - 1)); +} +#endif + +#ifndef FUNCTION_getScalefactor_SGL +#define FUNCTION_getScalefactor_SGL +SCALE_INLINE +INT getScalefactor(const FIXP_SGL *vector, /*!< Pointer to input vector */ + INT len) /*!< Length of input vector */ +{ + INT i; + SHORT temp, maxVal = (FIXP_SGL)0; + + for (i = len; i != 0; i--) { + temp = (SHORT)(*vector++); + maxVal |= (temp ^ (temp >> (FRACT_BITS - 1))); + } + + return fixmax_I((INT)0, (INT)(fixnormz_S((FIXP_SGL)maxVal)) - 1); +} +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/include/tp_data.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/include/tp_data.h new file mode 100644 index 0000000000000..b63087a4b82ae --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/include/tp_data.h @@ -0,0 +1,466 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Manuel Jander + + Description: MPEG Transport data tables + +*******************************************************************************/ + +#ifndef TP_DATA_H +#define TP_DATA_H + +#include "machine_type.h" +#include "FDK_audio.h" +#include "FDK_bitstream.h" + +/* + * Configuration + */ + +#define TP_USAC_MAX_SPEAKERS (24) + +#define TP_USAC_MAX_EXT_ELEMENTS ((24)) + +#define TP_USAC_MAX_ELEMENTS ((24) + TP_USAC_MAX_EXT_ELEMENTS) + +#define TP_USAC_MAX_CONFIG_LEN \ + 512 /* next power of two of maximum of escapedValue(hBs, 4, 4, 8) in \ + AudioPreRoll() (285) */ + +#define TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES \ + (1) /* Number of frames for config change in USAC */ + +enum { + TPDEC_FLUSH_OFF = 0, + TPDEC_RSV60_CFG_CHANGE_ATSC_FLUSH_ON = 1, + TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON = 2, + TPDEC_USAC_DASH_IPF_FLUSH_ON = 3 +}; + +enum { + TPDEC_BUILD_UP_OFF = 0, + TPDEC_RSV60_BUILD_UP_ON = 1, + TPDEC_RSV60_BUILD_UP_ON_IN_BAND = 2, + TPDEC_USAC_BUILD_UP_ON = 3, + TPDEC_RSV60_BUILD_UP_IDLE = 4, + TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND = 5 +}; + +/** + * ProgramConfig struct. + */ +/* ISO/IEC 14496-3 4.4.1.1 Table 4.2 Program config element */ +#define PC_FSB_CHANNELS_MAX 16 /* Front/Side/Back channels */ +#define PC_LFE_CHANNELS_MAX 4 +#define PC_ASSOCDATA_MAX 8 +#define PC_CCEL_MAX 16 /* CC elements */ +#define PC_COMMENTLENGTH 256 +#define PC_NUM_HEIGHT_LAYER 3 + +typedef struct { + /* PCE bitstream elements: */ + UCHAR ElementInstanceTag; + UCHAR Profile; + UCHAR SamplingFrequencyIndex; + UCHAR NumFrontChannelElements; + UCHAR NumSideChannelElements; + UCHAR NumBackChannelElements; + UCHAR NumLfeChannelElements; + UCHAR NumAssocDataElements; + UCHAR NumValidCcElements; + + UCHAR MonoMixdownPresent; + UCHAR MonoMixdownElementNumber; + + UCHAR StereoMixdownPresent; + UCHAR StereoMixdownElementNumber; + + UCHAR MatrixMixdownIndexPresent; + UCHAR MatrixMixdownIndex; + UCHAR PseudoSurroundEnable; + + UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR FrontElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR SideElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR BackElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX]; + + UCHAR AssocDataElementTagSelect[PC_ASSOCDATA_MAX]; + + UCHAR CcElementIsIndSw[PC_CCEL_MAX]; + UCHAR ValidCcElementTagSelect[PC_CCEL_MAX]; + + UCHAR CommentFieldBytes; + UCHAR Comment[PC_COMMENTLENGTH]; + + /* Helper variables for administration: */ + UCHAR isValid; /*!< Flag showing if PCE has been read successfully. */ + UCHAR + NumChannels; /*!< Amount of audio channels summing all channel elements + including LFEs */ + UCHAR NumEffectiveChannels; /*!< Amount of audio channels summing only SCEs + and CPEs */ + UCHAR elCounter; + +} CProgramConfig; + +typedef enum { + ASCEXT_UNKOWN = -1, + ASCEXT_SBR = 0x2b7, + ASCEXT_PS = 0x548, + ASCEXT_MPS = 0x76a, + ASCEXT_SAOC = 0x7cb, + ASCEXT_LDMPS = 0x7cc + +} TP_ASC_EXTENSION_ID; + +/** + * GaSpecificConfig struct + */ +typedef struct { + UINT m_frameLengthFlag; + UINT m_dependsOnCoreCoder; + UINT m_coreCoderDelay; + + UINT m_extensionFlag; + UINT m_extensionFlag3; + + UINT m_layer; + UINT m_numOfSubFrame; + UINT m_layerLength; + +} CSGaSpecificConfig; + +typedef enum { + ELDEXT_TERM = 0x0, /* Termination tag */ + ELDEXT_SAOC = 0x1, /* SAOC config */ + ELDEXT_LDSAC = 0x2, /* LD MPEG Surround config */ + ELDEXT_DOWNSCALEINFO = 0x3 /* ELD sample rate adaptation */ + /* reserved */ +} ASC_ELD_EXT_TYPE; + +typedef struct { + UCHAR m_frameLengthFlag; + + UCHAR m_sbrPresentFlag; + UCHAR + m_useLdQmfTimeAlign; /* Use LD-MPS QMF in SBR to achive time alignment */ + UCHAR m_sbrSamplingRate; + UCHAR m_sbrCrcFlag; + UINT m_downscaledSamplingFrequency; + +} CSEldSpecificConfig; + +typedef struct { + USAC_EXT_ELEMENT_TYPE usacExtElementType; + USHORT usacExtElementConfigLength; + USHORT usacExtElementDefaultLength; + UCHAR usacExtElementPayloadFrag; + UCHAR usacExtElementHasAudioPreRoll; +} CSUsacExtElementConfig; + +typedef struct { + MP4_ELEMENT_ID usacElementType; + UCHAR m_noiseFilling; + UCHAR m_harmonicSBR; + UCHAR m_interTes; + UCHAR m_pvc; + UCHAR m_stereoConfigIndex; + CSUsacExtElementConfig extElement; +} CSUsacElementConfig; + +typedef struct { + UCHAR m_frameLengthFlag; + UCHAR m_coreSbrFrameLengthIndex; + UCHAR m_sbrRatioIndex; + UCHAR m_nUsacChannels; /* number of audio channels signaled in + UsacDecoderConfig() / rsv603daDecoderConfig() via + numElements and usacElementType */ + UCHAR m_channelConfigurationIndex; + UINT m_usacNumElements; + CSUsacElementConfig element[TP_USAC_MAX_ELEMENTS]; + + UCHAR numAudioChannels; + UCHAR m_usacConfigExtensionPresent; + UCHAR elementLengthPresent; + UCHAR UsacConfig[TP_USAC_MAX_CONFIG_LEN]; + USHORT UsacConfigBits; +} CSUsacConfig; + +/** + * Audio configuration struct, suitable for encoder and decoder configuration. + */ +typedef struct { + /* XYZ Specific Data */ + union { + CSGaSpecificConfig + m_gaSpecificConfig; /**< General audio specific configuration. */ + CSEldSpecificConfig m_eldSpecificConfig; /**< ELD specific configuration. */ + CSUsacConfig m_usacConfig; /**< USAC specific configuration */ + } m_sc; + + /* Common ASC parameters */ + CProgramConfig m_progrConfigElement; /**< Program configuration. */ + + AUDIO_OBJECT_TYPE m_aot; /**< Audio Object Type. */ + UINT m_samplingFrequency; /**< Samplerate. */ + UINT m_samplesPerFrame; /**< Amount of samples per frame. */ + UINT m_directMapping; /**< Document this please !! */ + + AUDIO_OBJECT_TYPE m_extensionAudioObjectType; /**< Audio object type */ + UINT m_extensionSamplingFrequency; /**< Samplerate */ + + SCHAR m_channelConfiguration; /**< Channel configuration index */ + + SCHAR m_epConfig; /**< Error protection index */ + SCHAR m_vcb11Flag; /**< aacSectionDataResilienceFlag */ + SCHAR m_rvlcFlag; /**< aacScalefactorDataResilienceFlag */ + SCHAR m_hcrFlag; /**< aacSpectralDataResilienceFlag */ + + SCHAR m_sbrPresentFlag; /**< Flag indicating the presence of SBR data in the + bitstream */ + SCHAR + m_psPresentFlag; /**< Flag indicating the presence of parametric stereo + data in the bitstream */ + UCHAR m_samplingFrequencyIndex; /**< Samplerate index */ + UCHAR m_extensionSamplingFrequencyIndex; /**< Samplerate index */ + SCHAR m_extensionChannelConfiguration; /**< Channel configuration index */ + + UCHAR + configMode; /**< The flag indicates if the callback shall work in memory + allocation mode or in config change detection mode */ + UCHAR AacConfigChanged; /**< The flag will be set if at least one aac config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + UCHAR SbrConfigChanged; /**< The flag will be set if at least one sbr config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + UCHAR SacConfigChanged; /**< The flag will be set if at least one sac config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + + UCHAR + config[TP_USAC_MAX_CONFIG_LEN]; /**< Configuration stored as bitstream */ + UINT configBits; /**< Configuration length in bits */ + +} CSAudioSpecificConfig; + +typedef struct { + SCHAR flushCnt; /**< Flush frame counter */ + UCHAR flushStatus; /**< Flag indicates flush mode: on|off */ + SCHAR buildUpCnt; /**< Build up frame counter */ + UCHAR buildUpStatus; /**< Flag indicates build up mode: on|off */ + UCHAR cfgChanged; /**< Flag indicates that the config changed and the decoder + needs to be initialized again via callback. Make sure + that memory is freed before initialization. */ + UCHAR contentChanged; /**< Flag indicates that the content changed i.e. a + right truncation occured before */ + UCHAR forceCfgChange; /**< Flag indicates if config change has to be forced + even if new config is the same */ +} CCtrlCFGChange; + +typedef INT (*cbUpdateConfig_t)(void *, const CSAudioSpecificConfig *, + const UCHAR configMode, UCHAR *configChanged); +typedef INT (*cbFreeMem_t)(void *, const CSAudioSpecificConfig *); +typedef INT (*cbCtrlCFGChange_t)(void *, const CCtrlCFGChange *); +typedef INT (*cbSsc_t)(void *, HANDLE_FDK_BITSTREAM, + const AUDIO_OBJECT_TYPE coreCodec, + const INT samplingRate, const INT frameSize, + const INT numChannels, const INT stereoConfigIndex, + const INT coreSbrFrameLengthIndex, const INT configBytes, + const UCHAR configMode, UCHAR *configChanged); + +typedef INT (*cbSbr_t)(void *self, HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const INT elementIndex, + const UCHAR harmonicSbr, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor); + +typedef INT (*cbUsac_t)(void *self, HANDLE_FDK_BITSTREAM hBs); + +typedef INT (*cbUniDrc_t)(void *self, HANDLE_FDK_BITSTREAM hBs, + const INT fullPayloadLength, const INT payloadType, + const INT subStreamIndex, const INT payloadStart, + const AUDIO_OBJECT_TYPE); + +typedef struct { + cbUpdateConfig_t cbUpdateConfig; /*!< Function pointer for Config change + notify callback. */ + void *cbUpdateConfigData; /*!< User data pointer for Config change notify + callback. */ + cbFreeMem_t cbFreeMem; /*!< Function pointer for free memory callback. */ + void *cbFreeMemData; /*!< User data pointer for free memory callback. */ + cbCtrlCFGChange_t cbCtrlCFGChange; /*!< Function pointer for config change + control callback. */ + void *cbCtrlCFGChangeData; /*!< User data pointer for config change control + callback. */ + cbSsc_t cbSsc; /*!< Function pointer for SSC parser callback. */ + void *cbSscData; /*!< User data pointer for SSC parser callback. */ + cbSbr_t cbSbr; /*!< Function pointer for SBR header parser callback. */ + void *cbSbrData; /*!< User data pointer for SBR header parser callback. */ + cbUsac_t cbUsac; + void *cbUsacData; + cbUniDrc_t cbUniDrc; /*!< Function pointer for uniDrcConfig and + loudnessInfoSet parser callback. */ + void *cbUniDrcData; /*!< User data pointer for uniDrcConfig and + loudnessInfoSet parser callback. */ +} CSTpCallBacks; + +static const UINT SamplingRateTable[] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, + 8000, 7350, 0, 0, 57600, 51200, 40000, 38400, 34150, 28800, 25600, + 20000, 19200, 17075, 14400, 12800, 9600, 0, 0, 0, 0}; + +static inline int getSamplingRateIndex(UINT samplingRate, UINT nBits) { + UINT sf_index; + UINT tableSize = (1 << nBits) - 1; + + for (sf_index = 0; sf_index < tableSize; sf_index++) { + if (SamplingRateTable[sf_index] == samplingRate) break; + } + + if (sf_index > tableSize) { + return tableSize - 1; + } + + return sf_index; +} + +/* + * Get Channel count from channel configuration + */ +static inline int getNumberOfTotalChannels(int channelConfig) { + switch (channelConfig) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + return channelConfig; + case 7: + case 12: + case 14: + return 8; + case 11: + return 7; + case 13: + return 24; + default: + return 0; + } +} + +static inline int getNumberOfEffectiveChannels( + const int + channelConfig) { /* index: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */ + const int n[] = {0, 1, 2, 3, 4, 5, 5, 7, 0, 0, 0, 6, 7, 22, 7, 0}; + return n[channelConfig]; +} + +#endif /* TP_DATA_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/include/tpdec_lib.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/include/tpdec_lib.h new file mode 100644 index 0000000000000..30e53c1606476 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/include/tpdec_lib.h @@ -0,0 +1,664 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Manuel Jander + + Description: MPEG Transport decoder + +*******************************************************************************/ + +#ifndef TPDEC_LIB_H +#define TPDEC_LIB_H + +#include "tp_data.h" + +#include "FDK_bitstream.h" + +typedef enum { + TRANSPORTDEC_OK = 0, /*!< All fine. */ + + /* Synchronization errors. Wait for new input data and try again. */ + tpdec_sync_error_start = 0x100, + TRANSPORTDEC_NOT_ENOUGH_BITS, /*!< Out of bits. Provide more bits and try + again. */ + TRANSPORTDEC_SYNC_ERROR, /*!< No sync was found or sync got lost. Keep trying. + */ + tpdec_sync_error_end, + + /* Decode errors. Mostly caused due to bit errors. */ + tpdec_decode_error_start = 0x400, + TRANSPORTDEC_PARSE_ERROR, /*!< Bitstream data showed inconsistencies (wrong + syntax). */ + TRANSPORTDEC_UNSUPPORTED_FORMAT, /*!< Unsupported format or feature found in + the bitstream data. */ + TRANSPORTDEC_CRC_ERROR, /*!< CRC error encountered in bitstream data. */ + tpdec_decode_error_end, + + /* Fatal errors. Stop immediately on one of these errors! */ + tpdec_fatal_error_start = 0x200, + TRANSPORTDEC_UNKOWN_ERROR, /*!< An unknown error occured. */ + TRANSPORTDEC_INVALID_PARAMETER, /*!< An invalid parameter was passed to a + function. */ + TRANSPORTDEC_NEED_TO_RESTART, /*!< The decoder needs to be restarted, since + the requiered configuration change cannot + be performed. */ + TRANSPORTDEC_TOO_MANY_BITS, /*!< In case of packet based formats: Supplied + number of bits exceed the size of the + internal bit buffer. */ + tpdec_fatal_error_end + +} TRANSPORTDEC_ERROR; + +/** Macro to identify decode errors. */ +#define TPDEC_IS_DECODE_ERROR(err) \ + (((err >= tpdec_decode_error_start) && (err <= tpdec_decode_error_end)) ? 1 \ + : 0) +/** Macro to identify fatal errors. */ +#define TPDEC_IS_FATAL_ERROR(err) \ + (((err >= tpdec_fatal_error_start) && (err <= tpdec_fatal_error_end)) ? 1 : 0) + +/** + * \brief Parameter identifiers for transportDec_SetParam() + */ +typedef enum { + TPDEC_PARAM_MINIMIZE_DELAY = 1, /** Delay minimization strategy. 0: none, 1: + discard as many frames as possible. */ + TPDEC_PARAM_EARLY_CONFIG, /** Enable early config discovery. */ + TPDEC_PARAM_IGNORE_BUFFERFULLNESS, /** Ignore buffer fullness. */ + TPDEC_PARAM_SET_BITRATE, /** Set average bit rate for bit stream interruption + frame misses estimation. */ + TPDEC_PARAM_RESET, /** Reset transport decoder instance status. */ + TPDEC_PARAM_BURST_PERIOD, /** Set data reception burst period in mili seconds. + */ + TPDEC_PARAM_TARGETLAYOUT, /** Set CICP target layout */ + TPDEC_PARAM_FORCE_CONFIG_CHANGE, /** Force config change for next received + config */ + TPDEC_PARAM_USE_ELEM_SKIPPING +} TPDEC_PARAM; + +/*! + \brief Reset Program Config Element. + \param pPce Program Config Element structure. + \return void +*/ +void CProgramConfig_Reset(CProgramConfig *pPce); + +/*! + \brief Initialize Program Config Element. + \param pPce Program Config Element structure. + \return void +*/ +void CProgramConfig_Init(CProgramConfig *pPce); + +/*! + \brief Inquire state of present Program Config Element + structure. \param pPce Program Config Element structure. \return + 1 if the PCE structure is filled correct, 0 if no valid PCE present. +*/ +int CProgramConfig_IsValid(const CProgramConfig *pPce); + +/*! + \brief Read Program Config Element. + \param pPce Program Config Element structure. + \param bs Bitstream buffer to read from. + \param alignAnchor Align bitstream to alignAnchor bits after all read + operations. \return void +*/ +void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs, + UINT alignAnchor); + +/*! + \brief Compare two Program Config Elements. + \param pPce1 Pointer to first Program Config Element structure. + \param pPce2 Pointer to second Program Config Element structure. + \return -1 if PCEs are completely different, + 0 if PCEs are completely equal, + 1 if PCEs are different but have the same channel + config, 2 if PCEs have different channel config but same number of channels. +*/ +int CProgramConfig_Compare(const CProgramConfig *const pPce1, + const CProgramConfig *const pPce2); + +/*! + \brief Get a Program Config Element that matches the predefined + MPEG-4 channel configurations 1-14. \param pPce Program Config + Element structure. \param channelConfig MPEG-4 channel configuration. \return + void +*/ +void CProgramConfig_GetDefault(CProgramConfig *pPce, const UINT channelConfig); + +/** + * \brief Lookup and verify a given element. The decoder calls this + * method with every new element ID found in the bitstream. + * + * \param pPce A valid Program config structure. + * \param chConfig MPEG-4 channel configuration. + * \param tag Tag of the current element to be looked up. + * \param channelIdx The current channel count of the decoder parser. + * \param chMapping Array to store the canonical channel mapping indexes. + * \param chType Array to store the audio channel type. + * \param chIndex Array to store the individual audio channel type index. + * \param chDescrLen Length of the output channel description array. + * \param elMapping Pointer where the canonical element index is stored. + * \param elType The element id of the current element to be looked up. + * + * \return Non-zero if the element belongs to the current program, + * zero if it does not. + */ +int CProgramConfig_LookupElement(CProgramConfig *pPce, UINT chConfig, + const UINT tag, const UINT channelIdx, + UCHAR chMapping[], AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[], const UINT chDescrLen, + UCHAR *elMapping, MP4_ELEMENT_ID elList[], + MP4_ELEMENT_ID elType); + +/** + * \brief Get table of channel indices in the order of their + * appearance in by the program config field. + * \param pPce A valid program config structure. + * \param pceChMap Array to store the channel mapping indices like they + * appear in the PCE. + * \param pceChMapLen Lenght of the channel mapping index array (pceChMap). + * + * \return Non-zero if any error occured otherwise zero. + */ +int CProgramConfig_GetPceChMap(const CProgramConfig *pPce, UCHAR pceChMap[], + const UINT pceChMapLen); + +/** + * \brief Get table of elements in canonical order from a + * give program config field. + * \param pPce A valid program config structure. + * \param table An array where the element IDs are stored. + * \param elListSize The length of the table array. + * \param pChMapIdx Pointer to a field receiving the corresponding + * implicit channel configuration index of the given + * PCE. If none can be found it receives the value 0. + * \return Total element count including all SCE, CPE and LFE. + */ +int CProgramConfig_GetElementTable(const CProgramConfig *pPce, + MP4_ELEMENT_ID table[], const INT elListSize, + UCHAR *pChMapIdx); + +/** + * \brief Get channel description (type and index) for implicit + configurations (chConfig > 0) in MPEG canonical order. + * \param chConfig MPEG-4 channel configuration. + * \param chType Array to store the audio channel type. + * \param chIndex Array to store the individual audio channel type index. + * \return void + */ +void CProgramConfig_GetChannelDescription(const UINT chConfig, + const CProgramConfig *pPce, + AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[]); + +/** + * \brief Initialize a given AudioSpecificConfig structure. + * \param pAsc A pointer to an allocated CSAudioSpecificConfig struct. + * \return void + */ +void AudioSpecificConfig_Init(CSAudioSpecificConfig *pAsc); + +/** + * \brief Parse a AudioSpecificConfig from a given bitstream handle. + * + * \param pAsc A pointer to an allocated + * CSAudioSpecificConfig struct. + * \param hBs Bitstream handle. + * \param fExplicitBackwardCompatible Do explicit backward compatibility + * parsing if set (flag). + * \param cb pointer to structure holding callback information + * \param configMode Config modes: memory allocation mode or config change + * detection mode. + * \param configChanged Indicates a config change. + * \param m_aot in case of unequal AOT_NULL_OBJECT only the specific config is + * parsed. + * + * \return Total element count including all SCE, CPE and LFE. + */ +TRANSPORTDEC_ERROR AudioSpecificConfig_Parse( + CSAudioSpecificConfig *pAsc, HANDLE_FDK_BITSTREAM hBs, + int fExplicitBackwardCompatible, CSTpCallBacks *cb, UCHAR configMode, + UCHAR configChanged, AUDIO_OBJECT_TYPE m_aot); + +/* CELP stuff */ +enum { MPE = 0, RPE = 1, fs8KHz = 0, fs16KHz = 1 }; + +/* Defintion of flags that can be passed to transportDecOpen() */ +#define TP_FLAG_MPEG4 1 + +/* Capability flags */ +#define CAPF_TPDEC_ADIF \ + 0x00001000 /**< Flag indicating support for ADIF transport format. */ +#define CAPF_TPDEC_ADTS \ + 0x00002000 /**< Flag indicating support for ADTS transport format. */ +#define CAPF_TPDEC_LOAS \ + 0x00004000 /**< Flag indicating support for LOAS transport format. */ +#define CAPF_TPDEC_LATM \ + 0x00008000 /**< Flag indicating support for LATM transport format. */ +#define CAPF_TPDEC_RAWPACKETS \ + 0x00010000 /**< Flag indicating support for raw packets transport format. */ + +typedef struct TRANSPORTDEC *HANDLE_TRANSPORTDEC; + +/** + * \brief Configure Transport Decoder via a binary coded AudioSpecificConfig or + * StreamMuxConfig. The previously requested configuration callback will be + * called as well. The buffer conf must containt a SMC in case of + * LOAS/LATM transport format, and an ASC elseways. + * + * \param hTp Handle of a transport decoder. + * \param conf UCHAR buffer of the binary coded config (ASC or SMC). + * \param length The length in bytes of the conf buffer. + * + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(const HANDLE_TRANSPORTDEC hTp, + UCHAR *conf, const UINT length, + const UINT layer); + +/** + * \brief Configure Transport Decoder via a binary coded USAC/RSV603DA Config. + * The buffer newConfig contains a binary coded USAC/RSV603DA config of + * length newConfigLength bytes. If the new config and the previous config are + * different configChanged is set to 1 otherwise it is set to 0. + * + * \param hTp Handle of a transport decoder. + * \param newConfig buffer of the binary coded config. + * \param newConfigLength Length of new config in bytes. + * \param buildUpStatus Indicates build up status: off|on|idle. + * \param configChanged Indicates if config changed. + * \param layer Instance layer. + * + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_InBandConfig( + const HANDLE_TRANSPORTDEC hTp, UCHAR *newConfig, const UINT newConfigLength, + const UCHAR buildUpStatus, UCHAR *configChanged, const UINT layer, + UCHAR *implicitExplicitCfgDiff); + +/** + * \brief Open Transport medium for reading. + * + * \param transportDecFmt Format of the transport decoder medium to be accessed. + * \param flags Transport decoder flags. Currently only TP_FLAG_MPEG4, + * which signals a MPEG4 capable decoder (relevant for ADTS only). + * + * \return A pointer to a valid and allocated HANDLE_TRANSPORTDEC or a null + * pointer on failure. + */ +HANDLE_TRANSPORTDEC transportDec_Open(TRANSPORT_TYPE transportDecFmt, + const UINT flags, const UINT nrOfLayer); + +/** + * \brief Register configuration change callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle audio config + * changes. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterAscCallback(HANDLE_TRANSPORTDEC hTp, + const cbUpdateConfig_t cbUpdateConfig, + void *user_data); + +/** + * \brief Register free memory callback. + * \param hTp Handle of transport decoder. + * \param cbFreeMem Pointer to a callback function to free config dependent + * memory. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterFreeMemCallback(HANDLE_TRANSPORTDEC hTp, + const cbFreeMem_t cbFreeMem, + void *user_data); + +/** + * \brief Register config change control callback. + * \param hTp Handle of transport decoder. + * \param cbCtrlCFGChange Pointer to a callback function for config change + * control. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterCtrlCFGChangeCallback( + HANDLE_TRANSPORTDEC hTp, const cbCtrlCFGChange_t cbCtrlCFGChange, + void *user_data); + +/** + * \brief Register SSC parser callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle SSC parsing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterSscCallback(HANDLE_TRANSPORTDEC hTp, + const cbSsc_t cbSscParse, void *user_data); + +/** + * \brief Register SBR header parser callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle SBR header + * parsing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterSbrCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbSbr_t cbSbr, void *user_data); + +/** + * \brief Register USAC SC parser callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle USAC SC + * parsing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterUsacCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUsac_t cbUsac, void *user_data); + +/** + * \brief Register uniDrcConfig and loudnessInfoSet parser + * callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle uniDrcConfig + * and loudnessInfoSet parsing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterUniDrcConfigCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUniDrc_t cbUniDrc, + void *user_data, + UINT *pLoudnessInfoSetPosition); + +/** + * \brief Fill internal input buffer with bitstream data from the external input + * buffer. The function only copies such data as long as the decoder-internal + * input buffer is not full. So it grabs whatever it can from pBuffer and + * returns information (bytesValid) so that at a subsequent call of + * %transportDec_FillData(), the right position in pBuffer can be determined to + * grab the next data. + * + * \param hTp Handle of transportDec. + * \param pBuffer Pointer to external input buffer. + * \param bufferSize Size of external input buffer. This argument is required + * because decoder-internally we need the information to calculate the offset to + * pBuffer, where the next available data is, which is then + * fed into the decoder-internal buffer (as much as + * possible). Our example framework implementation fills the + * buffer at pBuffer again, once it contains no available valid bytes anymore + * (meaning bytesValid equal 0). + * \param bytesValid Number of bitstream bytes in the external bitstream buffer + * that have not yet been copied into the decoder's internal bitstream buffer by + * calling this function. The value is updated according to + * the amount of newly copied bytes. + * \param layer The layer the bitstream belongs to. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_FillData(const HANDLE_TRANSPORTDEC hTp, + UCHAR *pBuffer, const UINT bufferSize, + UINT *pBytesValid, const INT layer); + +/** + * \brief Get transportDec bitstream handle. + * \param hTp Pointer to a transport decoder handle. + * \return HANDLE_FDK_BITSTREAM bitstream handle. + */ +HANDLE_FDK_BITSTREAM transportDec_GetBitstream(const HANDLE_TRANSPORTDEC hTp, + const UINT layer); + +/** + * \brief Get transport format. + * \param hTp Pointer to a transport decoder handle. + * \return The transport format. + */ +TRANSPORT_TYPE transportDec_GetFormat(const HANDLE_TRANSPORTDEC hTp); + +/** + * \brief Get the current buffer fullness value. + * + * \param hTp Handle of a transport decoder. + * + * \return Buffer fullness + */ +INT transportDec_GetBufferFullness(const HANDLE_TRANSPORTDEC hTp); + +/** + * \brief Close and deallocate transportDec. + * \param phTp Pointer to a previously allocated transport decoder handle. + * \return void + */ +void transportDec_Close(HANDLE_TRANSPORTDEC *phTp); + +/** + * \brief Read one access unit from the transportDec medium. + * \param hTp Handle of transportDec. + * \param length On return, this value is overwritten with the actual access + * unit length in bits. Set to -1 if length is unknown. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_ReadAccessUnit(const HANDLE_TRANSPORTDEC hTp, + const UINT layer); + +/** + * \brief Get AudioSpecificConfig. + * \param hTp Handle of transportDec. + * \param layer Transport layer. + * \param asc Pointer to AudioSpecificConfig. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_GetAsc(const HANDLE_TRANSPORTDEC hTp, + const UINT layer, + CSAudioSpecificConfig *asc); + +/** + * \brief Get the remaining amount of bits of the current access unit. The + * result can be below zero, meaning that too many bits have been read. + * \param hTp Handle of transportDec. + * \return amount of remaining bits. + */ +INT transportDec_GetAuBitsRemaining(const HANDLE_TRANSPORTDEC hTp, + const UINT layer); + +/** + * \brief Get the total amount of bits of the current access unit. + * \param hTp Handle of transportDec. + * \return amount of total bits. + */ +INT transportDec_GetAuBitsTotal(const HANDLE_TRANSPORTDEC hTp, + const UINT layer); + +/** + * \brief This function is required to be called when the decoder has + * finished parsing one Access Unit for bitstream housekeeping. + * \param hTp Transport Handle. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_EndAccessUnit(const HANDLE_TRANSPORTDEC hTp); + +/** + * \brief Obtain the amount of missing access units if applicable in case + * of a bit stream synchronization error. Each time + * transportDec_ReadAccessUnit() returns TRANSPORTDEC_SYNC_ERROR + * this function can be called to retrieve an estimate of the amount + * of missing access units. This works only in case of constant + * average bit rate (has to be known) and if the parameter + * TPDEC_PARAM_SET_BITRATE has been set accordingly. + * \param hTp Transport Handle. + * \param pNAccessUnits pointer to a memory location where the estimated lost + * frame count will be stored into. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount( + INT *pNAccessUnits, HANDLE_TRANSPORTDEC hTp); + +/** + * \brief Set a given setting. + * \param hTp Transport Handle. + * \param param Identifier of the parameter to be changed. + * \param value Value for the parameter to be changed. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_SetParam(const HANDLE_TRANSPORTDEC hTp, + const TPDEC_PARAM param, + const INT value); + +/** + * \brief Get number of subframes (for LATM or ADTS) + * \param hTp Transport Handle. + * \return Number of ADTS/LATM subframes (return 1 for all other transport + * types). + */ +UINT transportDec_GetNrOfSubFrames(HANDLE_TRANSPORTDEC hTp); + +/** + * \brief Get info structure of transport decoder library. + * \param info A pointer to an allocated LIB_INFO struct. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_GetLibInfo(LIB_INFO *info); + +/* ADTS CRC support */ + +/** + * \brief Set current bitstream position as start of a new data region. + * \param hTp Transport handle. + * \param mBits Size in bits of the data region. Set to 0 if it should not be + * of a fixed size. + * \return Data region ID, which should be used when calling + * transportDec_CrcEndReg(). + */ +int transportDec_CrcStartReg(const HANDLE_TRANSPORTDEC hTp, const INT mBits); + +/** + * \brief Set end of data region. + * \param hTp Transport handle. + * \param reg Data region ID, opbtained from transportDec_CrcStartReg(). + * \return void + */ +void transportDec_CrcEndReg(const HANDLE_TRANSPORTDEC hTp, const INT reg); + +/** + * \brief Calculate ADTS crc and check if it is correct. The ADTS checksum + * is held internally. + * \param hTp Transport handle. + * \return Return TRANSPORTDEC_OK if the CRC is ok, or error if CRC is not + * correct. + */ +TRANSPORTDEC_ERROR transportDec_CrcCheck(const HANDLE_TRANSPORTDEC hTp); + +/** + * \brief Only check whether a given config seems to be valid without modifying + * internal states. + * + * \param conf UCHAR buffer of the binary coded config (SDC type 9). + * \param length The length in bytes of the conf buffer. + * + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_DrmRawSdcAudioConfig_Check(UCHAR *conf, + const UINT length); + +#endif /* #ifndef TPDEC_LIB_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tp_version.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tp_version.h new file mode 100644 index 0000000000000..4faed8cb56624 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tp_version.h @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): + + Description: + +*******************************************************************************/ + +#if !defined(TP_VERSION_H) +#define TP_VERSION_H + +/* library info */ +#define TP_LIB_VL0 3 +#define TP_LIB_VL1 0 +#define TP_LIB_VL2 0 +#define TP_LIB_TITLE "MPEG Transport" +#ifdef __ANDROID__ +#define TP_LIB_BUILD_DATE "" +#define TP_LIB_BUILD_TIME "" +#else +#define TP_LIB_BUILD_DATE __DATE__ +#define TP_LIB_BUILD_TIME __TIME__ +#endif +#endif /* !defined(TP_VERSION_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adif.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adif.cpp new file mode 100644 index 0000000000000..ec20b9b70de0c --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adif.cpp @@ -0,0 +1,158 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Josef Hoepfl + + Description: ADIF reader + +*******************************************************************************/ + +#include "tpdec_adif.h" + +#include "FDK_bitstream.h" +#include "genericStds.h" + +TRANSPORTDEC_ERROR adifRead_DecodeHeader(CAdifHeader *pAdifHeader, + CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs) { + int i; + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + UINT startAnchor = FDKgetValidBits(bs); + + if ((INT)startAnchor < MIN_ADIF_HEADERLENGTH) { + return (TRANSPORTDEC_NOT_ENOUGH_BITS); + } + + if (FDKreadBits(bs, 8) != 'A') { + return (TRANSPORTDEC_SYNC_ERROR); + } + if (FDKreadBits(bs, 8) != 'D') { + return (TRANSPORTDEC_SYNC_ERROR); + } + if (FDKreadBits(bs, 8) != 'I') { + return (TRANSPORTDEC_SYNC_ERROR); + } + if (FDKreadBits(bs, 8) != 'F') { + return (TRANSPORTDEC_SYNC_ERROR); + } + + if ((pAdifHeader->CopyrightIdPresent = FDKreadBits(bs, 1)) != 0) + FDKpushBiDirectional(bs, 72); /* CopyrightId */ + + pAdifHeader->OriginalCopy = FDKreadBits(bs, 1); + pAdifHeader->Home = FDKreadBits(bs, 1); + pAdifHeader->BitstreamType = FDKreadBits(bs, 1); + + /* pAdifHeader->BitRate = FDKreadBits(bs, 23); */ + pAdifHeader->BitRate = FDKreadBits(bs, 16); + pAdifHeader->BitRate <<= 7; + pAdifHeader->BitRate |= FDKreadBits(bs, 7); + + pAdifHeader->NumProgramConfigElements = FDKreadBits(bs, 4) + 1; + + if (pAdifHeader->BitstreamType == 0) { + FDKpushBiDirectional(bs, 20); /* adif_buffer_fullness */ + } + + /* Parse all PCEs but keep only one */ + for (i = 0; i < pAdifHeader->NumProgramConfigElements; i++) { + CProgramConfig_Read(pPce, bs, startAnchor); + } + + FDKbyteAlign(bs, startAnchor); + + return (ErrorStatus); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adif.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adif.h new file mode 100644 index 0000000000000..72ccc6a73ea72 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adif.h @@ -0,0 +1,134 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Josef Hoepfl + + Description: ADIF reader + +*******************************************************************************/ + +#ifndef TPDEC_ADIF_H +#define TPDEC_ADIF_H + +#include "tpdec_lib.h" + +#define MIN_ADIF_HEADERLENGTH 63 /* in bits */ + +typedef struct { + INT NumProgramConfigElements; + UINT BitRate; + UCHAR CopyrightIdPresent; + UCHAR OriginalCopy; + UCHAR Home; + UCHAR BitstreamType; +} CAdifHeader; + +/** + * \brief Parse a ADIF header at the given bitstream and store the parsed data + * into a given CAdifHeader and CProgramConfig struct + * + * \param pAdifHeader pointer to a CAdifHeader structure to hold the parsed ADIF + * header data. + * \param pPce pointer to a CProgramConfig structure where the last PCE will + * remain. + * + * \return TRANSPORTDEC_ERROR error code + */ +TRANSPORTDEC_ERROR adifRead_DecodeHeader(CAdifHeader *pAdifHeader, + CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs); + +#endif /* TPDEC_ADIF_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adts.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adts.cpp new file mode 100644 index 0000000000000..f936634e3d6bd --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adts.cpp @@ -0,0 +1,432 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Josef Hoepfl + + Description: ADTS interface + +*******************************************************************************/ + +#include "tpdec_adts.h" + +#include "FDK_bitstream.h" + +void adtsRead_CrcInit( + HANDLE_ADTS pAdts) /*!< pointer to adts crc info stucture */ +{ + FDKcrcInit(&pAdts->crcInfo, 0x8005, 0xFFFF, 16); +} + +int adtsRead_CrcStartReg( + HANDLE_ADTS pAdts, /*!< pointer to adts stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ +) { + if (pAdts->bs.protection_absent) { + return 0; + } + + return (FDKcrcStartReg(&pAdts->crcInfo, hBs, mBits)); +} + +void adtsRead_CrcEndReg( + HANDLE_ADTS pAdts, /*!< pointer to adts crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ +) { + if (pAdts->bs.protection_absent == 0) { + FDKcrcEndReg(&pAdts->crcInfo, hBs, reg); + } +} + +TRANSPORTDEC_ERROR adtsRead_CrcCheck(HANDLE_ADTS pAdts) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + USHORT crc; + + if (pAdts->bs.protection_absent) return TRANSPORTDEC_OK; + + crc = FDKcrcGetCRC(&pAdts->crcInfo); + if (crc != pAdts->crcReadValue) { + return (TRANSPORTDEC_CRC_ERROR); + } + + return (ErrorStatus); +} + +#define Adts_Length_SyncWord 12 +#define Adts_Length_Id 1 +#define Adts_Length_Layer 2 +#define Adts_Length_ProtectionAbsent 1 +#define Adts_Length_Profile 2 +#define Adts_Length_SamplingFrequencyIndex 4 +#define Adts_Length_PrivateBit 1 +#define Adts_Length_ChannelConfiguration 3 +#define Adts_Length_OriginalCopy 1 +#define Adts_Length_Home 1 +#define Adts_Length_CopyrightIdentificationBit 1 +#define Adts_Length_CopyrightIdentificationStart 1 +#define Adts_Length_FrameLength 13 +#define Adts_Length_BufferFullness 11 +#define Adts_Length_NumberOfRawDataBlocksInFrame 2 +#define Adts_Length_CrcCheck 16 + +TRANSPORTDEC_ERROR adtsRead_DecodeHeader(HANDLE_ADTS pAdts, + CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM hBs, + const INT ignoreBufferFullness) { + INT crcReg; + + INT valBits; + INT cmp_buffer_fullness; + int i, adtsHeaderLength; + + STRUCT_ADTS_BS bs; + + CProgramConfig oldPce; + /* Store the old PCE temporarily. Maybe we'll need it later if we + have channelConfig=0 and no PCE in this frame. */ + FDKmemcpy(&oldPce, &pAsc->m_progrConfigElement, sizeof(CProgramConfig)); + + valBits = FDKgetValidBits(hBs) + ADTS_SYNCLENGTH; + + if (valBits < ADTS_HEADERLENGTH) { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + + /* adts_fixed_header */ + bs.mpeg_id = FDKreadBits(hBs, Adts_Length_Id); + bs.layer = FDKreadBits(hBs, Adts_Length_Layer); + bs.protection_absent = FDKreadBits(hBs, Adts_Length_ProtectionAbsent); + bs.profile = FDKreadBits(hBs, Adts_Length_Profile); + bs.sample_freq_index = FDKreadBits(hBs, Adts_Length_SamplingFrequencyIndex); + bs.private_bit = FDKreadBits(hBs, Adts_Length_PrivateBit); + bs.channel_config = FDKreadBits(hBs, Adts_Length_ChannelConfiguration); + bs.original = FDKreadBits(hBs, Adts_Length_OriginalCopy); + bs.home = FDKreadBits(hBs, Adts_Length_Home); + + /* adts_variable_header */ + bs.copyright_id = FDKreadBits(hBs, Adts_Length_CopyrightIdentificationBit); + bs.copyright_start = + FDKreadBits(hBs, Adts_Length_CopyrightIdentificationStart); + bs.frame_length = FDKreadBits(hBs, Adts_Length_FrameLength); + bs.adts_fullness = FDKreadBits(hBs, Adts_Length_BufferFullness); + bs.num_raw_blocks = + FDKreadBits(hBs, Adts_Length_NumberOfRawDataBlocksInFrame); + bs.num_pce_bits = 0; + + adtsHeaderLength = ADTS_HEADERLENGTH; + + if (valBits < bs.frame_length * 8) { + goto bail; + } + + FDKcrcReset(&pAdts->crcInfo); + if (!bs.protection_absent) { + FDKpushBack(hBs, 56); /* complete fixed and variable header! */ + crcReg = FDKcrcStartReg(&pAdts->crcInfo, hBs, 0); + FDKpushFor(hBs, 56); + } + + if (!bs.protection_absent && bs.num_raw_blocks > 0) { + if ((INT)FDKgetValidBits(hBs) < bs.num_raw_blocks * 16) { + goto bail; + } + for (i = 0; i < bs.num_raw_blocks; i++) { + pAdts->rawDataBlockDist[i] = (USHORT)FDKreadBits(hBs, 16); + adtsHeaderLength += 16; + } + /* Change raw data blocks to delta values */ + pAdts->rawDataBlockDist[bs.num_raw_blocks] = + bs.frame_length - 7 - bs.num_raw_blocks * 2 - 2; + for (i = bs.num_raw_blocks; i > 0; i--) { + pAdts->rawDataBlockDist[i] -= pAdts->rawDataBlockDist[i - 1]; + } + } + + /* adts_error_check */ + if (!bs.protection_absent) { + USHORT crc_check; + + FDKcrcEndReg(&pAdts->crcInfo, hBs, crcReg); + + if ((INT)FDKgetValidBits(hBs) < Adts_Length_CrcCheck) { + goto bail; + } + + crc_check = FDKreadBits(hBs, Adts_Length_CrcCheck); + adtsHeaderLength += Adts_Length_CrcCheck; + + pAdts->crcReadValue = crc_check; + /* Check header CRC in case of multiple raw data blocks */ + if (bs.num_raw_blocks > 0) { + if (pAdts->crcReadValue != FDKcrcGetCRC(&pAdts->crcInfo)) { + return TRANSPORTDEC_CRC_ERROR; + } + /* Reset CRC for the upcoming raw_data_block() */ + FDKcrcReset(&pAdts->crcInfo); + } + } + + /* check if valid header */ + if ((bs.layer != 0) || // we only support MPEG ADTS + (bs.sample_freq_index >= 13) // we only support 96kHz - 7350kHz + ) { + FDKpushFor(hBs, bs.frame_length * 8); // try again one frame later + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + /* special treatment of id-bit */ + if ((bs.mpeg_id == 0) && (pAdts->decoderCanDoMpeg4 == 0)) { + /* MPEG-2 decoder cannot play MPEG-4 bitstreams */ + + FDKpushFor(hBs, bs.frame_length * 8); // try again one frame later + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + if (!ignoreBufferFullness) { + cmp_buffer_fullness = + bs.frame_length * 8 + + bs.adts_fullness * 32 * getNumberOfEffectiveChannels(bs.channel_config); + + /* Evaluate buffer fullness */ + if (bs.adts_fullness != 0x7FF) { + if (pAdts->BufferFullnesStartFlag) { + if (valBits < cmp_buffer_fullness) { + /* Condition for start of decoding is not fulfilled */ + + /* The current frame will not be decoded */ + FDKpushBack(hBs, adtsHeaderLength); + + if ((cmp_buffer_fullness + adtsHeaderLength) > + (((8192 * 4) << 3) - 7)) { + return TRANSPORTDEC_SYNC_ERROR; + } else { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + } else { + pAdts->BufferFullnesStartFlag = 0; + } + } + } + } + + /* Get info from ADTS header */ + AudioSpecificConfig_Init(pAsc); + pAsc->m_aot = (AUDIO_OBJECT_TYPE)(bs.profile + 1); + pAsc->m_samplingFrequencyIndex = bs.sample_freq_index; + pAsc->m_samplingFrequency = SamplingRateTable[bs.sample_freq_index]; + pAsc->m_channelConfiguration = bs.channel_config; + pAsc->m_samplesPerFrame = 1024; + + if (bs.channel_config == 0) { + int pceBits = 0; + UINT alignAnchor = FDKgetValidBits(hBs); + CProgramConfig tmpPce; + + if (FDKreadBits(hBs, 3) == ID_PCE) { + /* Got luck! Parse the PCE */ + crcReg = adtsRead_CrcStartReg(pAdts, hBs, 0); + + CProgramConfig_Init(&tmpPce); + CProgramConfig_Read(&tmpPce, hBs, alignAnchor); + + if (CProgramConfig_IsValid(&tmpPce)) { + if (CProgramConfig_IsValid(&oldPce)) { + /* Compare the new and the old PCE (tags ignored) */ + switch (CProgramConfig_Compare(&tmpPce, &oldPce)) { + case 0: /* Nothing to do because PCE matches the old one exactly. */ + case 1: /* Channel configuration not changed. Just new metadata. */ + FDKmemcpy(&pAsc->m_progrConfigElement, &tmpPce, + sizeof(CProgramConfig)); + break; + case 2: /* The number of channels are identical but not the config + */ + case -1: /* The channel configuration is completely different */ + default: + FDKmemcpy(&pAsc->m_progrConfigElement, &oldPce, + sizeof(CProgramConfig)); + FDKpushBack(hBs, adtsHeaderLength); + return TRANSPORTDEC_PARSE_ERROR; + } + } else { + FDKmemcpy(&pAsc->m_progrConfigElement, &tmpPce, + sizeof(CProgramConfig)); + } + } else { + if (CProgramConfig_IsValid(&oldPce)) { + FDKmemcpy(&pAsc->m_progrConfigElement, &oldPce, + sizeof(CProgramConfig)); + } else { + FDKpushBack(hBs, adtsHeaderLength); + return TRANSPORTDEC_PARSE_ERROR; + } + } + + adtsRead_CrcEndReg(pAdts, hBs, crcReg); + pceBits = (INT)alignAnchor - (INT)FDKgetValidBits(hBs); + adtsHeaderLength += pceBits; + + if (pceBits > (INT)alignAnchor) { + goto bail; + } + + /* store the number of PCE bits */ + bs.num_pce_bits = pceBits; + } else { + /* No PCE in this frame! Push back the ID tag bits. */ + FDKpushBack(hBs, 3); + + /* Encoders do not have to write a PCE in each frame. + So if we already have a valid PCE we have to use it. */ + if (oldPce.isValid && + (bs.sample_freq_index == + pAdts->bs.sample_freq_index) /* we could compare the complete fixed + header (bytes) here! */ + && (bs.channel_config == pAdts->bs.channel_config) /* == 0 */ + && + (bs.mpeg_id == + pAdts->bs.mpeg_id)) { /* Restore previous PCE which is still valid */ + FDKmemcpy(&pAsc->m_progrConfigElement, &oldPce, sizeof(CProgramConfig)); + } else if (bs.mpeg_id == 0) { + /* If not it seems that we have a implicit channel configuration. + This mode is not allowed in the context of ISO/IEC 14496-3. + Skip this frame and try the next one. */ + FDKpushFor(hBs, (bs.frame_length << 3) - adtsHeaderLength - 3); + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + /* else { + ISO/IEC 13818-7 implicit channel mapping is allowed. + So just open the box of chocolates to see what we got. + } */ + } + } + + /* Copy bit stream data struct to persistent memory now, once we passed all + * sanity checks above. */ + FDKmemcpy(&pAdts->bs, &bs, sizeof(STRUCT_ADTS_BS)); + + return TRANSPORTDEC_OK; + +bail: + FDKpushBack(hBs, adtsHeaderLength); + return TRANSPORTDEC_NOT_ENOUGH_BITS; +} + +int adtsRead_GetRawDataBlockLength(HANDLE_ADTS pAdts, INT blockNum) { + int length; + + if (pAdts->bs.num_raw_blocks == 0) { + length = + (pAdts->bs.frame_length - 7) + << 3; /* aac_frame_length subtracted by the header size (7 bytes). */ + if (pAdts->bs.protection_absent == 0) + length -= 16; /* substract 16 bit CRC */ + } else { + if (pAdts->bs.protection_absent) { + length = -1; /* raw data block length is unknown */ + } else { + if (blockNum < 0 || blockNum > 3) { + length = -1; + } else { + length = (pAdts->rawDataBlockDist[blockNum] << 3) - 16; + } + } + } + if (blockNum == 0 && length > 0) { + length -= pAdts->bs.num_pce_bits; + } + return length; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adts.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adts.h new file mode 100644 index 0000000000000..68f3f6398434b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_adts.h @@ -0,0 +1,234 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Josef Hoepfl + + Description: ADTS interface + +*******************************************************************************/ + +#ifndef TPDEC_ADTS_H +#define TPDEC_ADTS_H + +#include "tpdec_lib.h" + +#define ADTS_SYNCWORD (0xfff) +#define ADTS_SYNCLENGTH (12) /* in bits */ +#define ADTS_HEADERLENGTH (56) /* minimum header size in bits */ +#define ADTS_FIXED_HEADERLENGTH (28) /* in bits */ +#define ADTS_VARIABLE_HEADERLENGTH (ADTS_HEADERLENGTH - ADTS_FIXED_HEADERLENGTH) + +#ifdef CHECK_TWO_SYNCS +#define ADTS_MIN_TP_BUF_SIZE (8191 + 2) +#else +#define ADTS_MIN_TP_BUF_SIZE (8191) +#endif + +#include "FDK_crc.h" + +typedef struct { + /* ADTS header fields */ + UCHAR mpeg_id; + UCHAR layer; + UCHAR protection_absent; + UCHAR profile; + UCHAR sample_freq_index; + UCHAR private_bit; + UCHAR channel_config; + UCHAR original; + UCHAR home; + UCHAR copyright_id; + UCHAR copyright_start; + USHORT frame_length; + USHORT adts_fullness; + UCHAR num_raw_blocks; + UCHAR num_pce_bits; +} STRUCT_ADTS_BS; + +struct STRUCT_ADTS { + STRUCT_ADTS_BS bs; + + UCHAR decoderCanDoMpeg4; + UCHAR BufferFullnesStartFlag; + + FDK_CRCINFO crcInfo; /* CRC state info */ + USHORT crcReadValue; /* CRC value read from bitstream data */ + USHORT rawDataBlockDist[4]; /* distance between each raw data block. Not the + same as found in the bitstream */ +}; + +typedef struct STRUCT_ADTS *HANDLE_ADTS; + +/*! + \brief Initialize ADTS CRC + + The function initialzes the crc buffer and the crc lookup table. + + \return none +*/ +void adtsRead_CrcInit(HANDLE_ADTS pAdts); + +/** + * \brief Starts CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if + * there are less than mBits bits available. If mBits is negative no zero + * padding is done. If mBits is zero the memory for the buffer is + * allocated dynamically, the number of bits is not limited. + * + * \param pAdts ADTS data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param mBits max number of bits in crc region to be considered + * + * \return ID for the created region, -1 in case of an error + */ +int adtsRead_CrcStartReg(HANDLE_ADTS pAdts, HANDLE_FDK_BITSTREAM hBs, + int mBits); + +/** + * \brief Ends CRC region identified by reg + * + * \param pAdts ADTS data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param reg CRC regions ID returned by adtsRead_CrcStartReg() + * + * \return none + */ +void adtsRead_CrcEndReg(HANDLE_ADTS pAdts, HANDLE_FDK_BITSTREAM hBs, int reg); + +/** + * \brief Check CRC + * + * Checks if the currently calculated CRC matches the CRC field read from the + * bitstream Deletes all CRC regions. + * + * \param pAdts ADTS data handle + * + * \return Returns 0 if they are identical otherwise 1 + */ +TRANSPORTDEC_ERROR adtsRead_CrcCheck(HANDLE_ADTS pAdts); + +/** + * \brief Check if we have a valid ADTS frame at the current bitbuffer position + * + * This function assumes enough bits in buffer for the current frame. + * It reads out the header bits to prepare the bitbuffer for the decode loop. + * In case the header bits show an invalid bitstream/frame, the whole frame is + * skipped. + * + * \param pAdts ADTS data handle which is filled with parsed ADTS header data + * \param bs handle of bitstream from whom the ADTS header is read + * + * \return error status + */ +TRANSPORTDEC_ERROR adtsRead_DecodeHeader(HANDLE_ADTS pAdts, + CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM bs, + const INT ignoreBufferFullness); + +/** + * \brief Get the raw data block length of the given block number. + * + * \param pAdts ADTS data handle + * \param blockNum current raw data block index + * \param pLength pointer to an INT where the length of the given raw data block + * is stored into the returned value might be -1, in which case the raw data + * block length is unknown. + * + * \return error status + */ +int adtsRead_GetRawDataBlockLength(HANDLE_ADTS pAdts, INT blockNum); + +#endif /* TPDEC_ADTS_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_asc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_asc.cpp new file mode 100644 index 0000000000000..8f77017a9bbd4 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_asc.cpp @@ -0,0 +1,2817 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Daniel Homm + + Description: + +*******************************************************************************/ + +#include "tpdec_lib.h" +#include "tp_data.h" + +#include "FDK_crc.h" + +#include "common_fix.h" + +/** + * The following arrays provide the IDs of the consecutive elements for each + * channel configuration. Every channel_configuration has to be finalized with + * ID_NONE. + */ +static const MP4_ELEMENT_ID channel_configuration_0[] = {ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_1[] = {ID_SCE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_2[] = {ID_CPE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_3[] = {ID_SCE, ID_CPE, + ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_4[] = {ID_SCE, ID_CPE, ID_SCE, + ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_5[] = {ID_SCE, ID_CPE, ID_CPE, + ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_6[] = {ID_SCE, ID_CPE, ID_CPE, + ID_LFE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_7[] = { + ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_8[] = { + ID_NONE}; /* reserved */ +static const MP4_ELEMENT_ID channel_configuration_9[] = { + ID_NONE}; /* reserved */ +static const MP4_ELEMENT_ID channel_configuration_10[] = { + ID_NONE}; /* reserved */ +static const MP4_ELEMENT_ID channel_configuration_11[] = { + ID_SCE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_12[] = { + ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_13[] = { + ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_LFE, ID_SCE, + ID_CPE, ID_CPE, ID_SCE, ID_CPE, ID_SCE, ID_SCE, ID_CPE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_14[] = { + ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_CPE, ID_NONE}; + +static const MP4_ELEMENT_ID *channel_configuration_array[] = { + channel_configuration_0, channel_configuration_1, + channel_configuration_2, channel_configuration_3, + channel_configuration_4, channel_configuration_5, + channel_configuration_6, channel_configuration_7, + channel_configuration_8, channel_configuration_9, + channel_configuration_10, channel_configuration_11, + channel_configuration_12, channel_configuration_13, + channel_configuration_14}; + +#define TP_USAC_MAX_CHANNEL_CONFIGURATION_INDEX (13) +#define SC_CHANNEL_CONFIG_TAB_SIZE (TP_USAC_MAX_CHANNEL_CONFIGURATION_INDEX + 1) + +/* channel config structure used for sanity check */ +typedef struct { + SCHAR nCh; /* number of channels */ + SCHAR nSCE; /* number of SCE's */ + SCHAR nCPE; /* number of CPE's */ + SCHAR nLFE; /* number of LFE's */ +} SC_CHANNEL_CONFIG; + +static const SC_CHANNEL_CONFIG sc_chan_config_tab[SC_CHANNEL_CONFIG_TAB_SIZE] = + { + /* nCh, nSCE, nCPE, nLFE, cci */ + {0, 0, 0, 0}, /* 0 */ + {1, 1, 0, 0}, /* 1 */ + {2, 0, 1, 0}, /* 2 */ + {3, 1, 1, 0}, /* 3 */ + {4, 2, 1, 0}, /* 4 */ + {5, 1, 2, 0}, /* 5 */ + {6, 1, 2, 1}, /* 6 */ + {8, 1, 3, 1}, /* 7 */ + {2, 2, 0, 0}, /* 8 */ + {3, 1, 1, 0}, /* 9 */ + {4, 0, 2, 0}, /* 10 */ + {7, 2, 2, 1}, /* 11 */ + {8, 1, 3, 1}, /* 12 */ + {24, 6, 8, 2} /* 13 */ +}; + +void CProgramConfig_Reset(CProgramConfig *pPce) { pPce->elCounter = 0; } + +void CProgramConfig_Init(CProgramConfig *pPce) { + FDKmemclear(pPce, sizeof(CProgramConfig)); + pPce->SamplingFrequencyIndex = 0xf; +} + +int CProgramConfig_IsValid(const CProgramConfig *pPce) { + return ((pPce->isValid) ? 1 : 0); +} + +#define PCE_HEIGHT_EXT_SYNC (0xAC) + +/* + * Read the extension for height info. + * return 0 if successfull, + * -1 if the CRC failed, + * -2 if invalid HeightInfo. + */ +static int CProgramConfig_ReadHeightExt(CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs, + int *const bytesAvailable, + const UINT alignmentAnchor) { + int err = 0; + FDK_CRCINFO crcInfo; /* CRC state info */ + INT crcReg; + FDKcrcInit(&crcInfo, 0x07, 0xFF, 8); + crcReg = FDKcrcStartReg(&crcInfo, bs, 0); + UINT startAnchor = FDKgetValidBits(bs); + + FDK_ASSERT(pPce != NULL); + FDK_ASSERT(bs != NULL); + FDK_ASSERT(bytesAvailable != NULL); + + if ((startAnchor >= 24) && (*bytesAvailable >= 3) && + (FDKreadBits(bs, 8) == PCE_HEIGHT_EXT_SYNC)) { + int i; + + for (i = 0; i < pPce->NumFrontChannelElements; i++) { + if ((pPce->FrontElementHeightInfo[i] = (UCHAR)FDKreadBits(bs, 2)) >= + PC_NUM_HEIGHT_LAYER) { + err = -2; /* height information is out of the valid range */ + } + } + for (i = 0; i < pPce->NumSideChannelElements; i++) { + if ((pPce->SideElementHeightInfo[i] = (UCHAR)FDKreadBits(bs, 2)) >= + PC_NUM_HEIGHT_LAYER) { + err = -2; /* height information is out of the valid range */ + } + } + for (i = 0; i < pPce->NumBackChannelElements; i++) { + if ((pPce->BackElementHeightInfo[i] = (UCHAR)FDKreadBits(bs, 2)) >= + PC_NUM_HEIGHT_LAYER) { + err = -2; /* height information is out of the valid range */ + } + } + FDKbyteAlign(bs, alignmentAnchor); + + FDKcrcEndReg(&crcInfo, bs, crcReg); + if ((USHORT)FDKreadBits(bs, 8) != FDKcrcGetCRC(&crcInfo)) { + /* CRC failed */ + err = -1; + } + if (err != 0) { + /* Reset whole height information in case an error occured during parsing. + The return value ensures that pPce->isValid is set to 0 and implicit + channel mapping is used. */ + FDKmemclear(pPce->FrontElementHeightInfo, + sizeof(pPce->FrontElementHeightInfo)); + FDKmemclear(pPce->SideElementHeightInfo, + sizeof(pPce->SideElementHeightInfo)); + FDKmemclear(pPce->BackElementHeightInfo, + sizeof(pPce->BackElementHeightInfo)); + } + } else { + /* No valid extension data found -> restore the initial bitbuffer state */ + FDKpushBack(bs, (INT)startAnchor - (INT)FDKgetValidBits(bs)); + } + + /* Always report the bytes read. */ + *bytesAvailable -= ((INT)startAnchor - (INT)FDKgetValidBits(bs)) >> 3; + + return (err); +} + +/** + * \brief Sanity checks for program config element. + * Check order of elements according to ISO/IEC 13818-7:2003(E), + * chapter 8.5.1 + * + * \param pPce pointer to program config element. + * + * \return 0 if successful, otherwise 1. + */ +static int CProgramConfig_Check(CProgramConfig *pPce) { + INT i; + INT err = 0; + INT numBackChannels[3] = {0}; + INT numSideChannels[3] = {0}; + INT numFrontChannels[3] = {0}; + UCHAR *pCpeFront = pPce->FrontElementIsCpe; + UCHAR *pCpeSide = pPce->SideElementIsCpe; + UCHAR *pCpeBack = pPce->BackElementIsCpe; + UCHAR *pHeight; + + pHeight = pPce->BackElementHeightInfo; + for (i = 0; i < pPce->NumBackChannelElements; i++) { + numBackChannels[*pHeight] += pPce->BackElementIsCpe[i] ? 2 : 1; + pHeight++; + } + pHeight = pPce->SideElementHeightInfo; + for (i = 0; i < pPce->NumSideChannelElements; i++) { + numSideChannels[*pHeight] += pPce->SideElementIsCpe[i] ? 2 : 1; + pHeight++; + } + pHeight = pPce->FrontElementHeightInfo; + for (i = 0; i < pPce->NumFrontChannelElements; i++) { + numFrontChannels[*pHeight] += pPce->FrontElementIsCpe[i] ? 2 : 1; + pHeight++; + } + + /* 0 = normal height channels, 1 = top height channels, 2 = bottom height + * channels */ + for (i = 0; i < 3; i++) { + /* if number of channels is odd => first element must be a SCE (front center + * channel) */ + if (numFrontChannels[i] & 1) { + if (*pCpeFront++ == ID_CPE) { + err = 1; + goto bail; + } + numFrontChannels[i]--; + } + while (numFrontChannels[i] > 0) { + /* must be CPE or paired SCE */ + if (*pCpeFront++ == ID_SCE) { + if (*pCpeFront++ == ID_CPE) { + err = 1; + goto bail; + } + } + numFrontChannels[i] -= 2; + }; + + /* in case that a top center surround channel (Ts) is transmitted the number + * of channels can be odd */ + if (i != 1) { + /* number of channels must be even */ + if (numSideChannels[i] & 1) { + err = 1; + goto bail; + } + while (numSideChannels[i] > 0) { + /* must be CPE or paired SCE */ + if (*pCpeSide++ == ID_SCE) { + if (*pCpeSide++ == ID_CPE) { + err = 1; + goto bail; + } + } + numSideChannels[i] -= 2; + }; + } + + while (numBackChannels[i] > 1) { + /* must be CPE or paired SCE */ + if (*pCpeBack++ == ID_SCE) { + if (*pCpeBack++ == ID_CPE) { + err = 1; + goto bail; + } + } + numBackChannels[i] -= 2; + }; + /* if number of channels is odd => last element must be a SCE (back center + * channel) */ + if (numBackChannels[i]) { + if (*pCpeBack++ == ID_CPE) { + err = 1; + goto bail; + } + } + } + +bail: + + return err; +} + +void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs, + UINT alignmentAnchor) { + int i; + int commentBytes; + UCHAR tag, isCpe; + UCHAR checkElementTagSelect[3][PC_FSB_CHANNELS_MAX] = {{0}}; + + pPce->isValid = 1; + pPce->NumEffectiveChannels = 0; + pPce->NumChannels = 0; + pPce->ElementInstanceTag = (UCHAR)FDKreadBits(bs, 4); + pPce->Profile = (UCHAR)FDKreadBits(bs, 2); + pPce->SamplingFrequencyIndex = (UCHAR)FDKreadBits(bs, 4); + pPce->NumFrontChannelElements = (UCHAR)FDKreadBits(bs, 4); + pPce->NumSideChannelElements = (UCHAR)FDKreadBits(bs, 4); + pPce->NumBackChannelElements = (UCHAR)FDKreadBits(bs, 4); + pPce->NumLfeChannelElements = (UCHAR)FDKreadBits(bs, 2); + pPce->NumAssocDataElements = (UCHAR)FDKreadBits(bs, 3); + pPce->NumValidCcElements = (UCHAR)FDKreadBits(bs, 4); + + if ((pPce->MonoMixdownPresent = (UCHAR)FDKreadBits(bs, 1)) != 0) { + pPce->MonoMixdownElementNumber = (UCHAR)FDKreadBits(bs, 4); + } + + if ((pPce->StereoMixdownPresent = (UCHAR)FDKreadBits(bs, 1)) != 0) { + pPce->StereoMixdownElementNumber = (UCHAR)FDKreadBits(bs, 4); + } + + if ((pPce->MatrixMixdownIndexPresent = (UCHAR)FDKreadBits(bs, 1)) != 0) { + pPce->MatrixMixdownIndex = (UCHAR)FDKreadBits(bs, 2); + pPce->PseudoSurroundEnable = (UCHAR)FDKreadBits(bs, 1); + } + + for (i = 0; i < pPce->NumFrontChannelElements; i++) { + pPce->FrontElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1); + pPce->FrontElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4); + pPce->NumChannels += pPce->FrontElementIsCpe[i] ? 2 : 1; + + /* Check element instance tag according to ISO/IEC 13818-7:2003(E), + * chapter 8.2.1.1 */ + if (checkElementTagSelect[isCpe][tag] == 0) { + checkElementTagSelect[isCpe][tag] = 1; + } else { + pPce->isValid = 0; + } + } + + for (i = 0; i < pPce->NumSideChannelElements; i++) { + pPce->SideElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1); + pPce->SideElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4); + pPce->NumChannels += pPce->SideElementIsCpe[i] ? 2 : 1; + + /* Check element instance tag according to ISO/IEC 13818-7:2003(E), + * chapter 8.2.1.1 */ + if (checkElementTagSelect[isCpe][tag] == 0) { + checkElementTagSelect[isCpe][tag] = 1; + } else { + pPce->isValid = 0; + } + } + + for (i = 0; i < pPce->NumBackChannelElements; i++) { + pPce->BackElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1); + pPce->BackElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4); + pPce->NumChannels += pPce->BackElementIsCpe[i] ? 2 : 1; + + /* Check element instance tag according to ISO/IEC 13818-7:2003(E), + * chapter 8.2.1.1 */ + if (checkElementTagSelect[isCpe][tag] == 0) { + checkElementTagSelect[isCpe][tag] = 1; + } else { + pPce->isValid = 0; + } + } + + pPce->NumEffectiveChannels = pPce->NumChannels; + + for (i = 0; i < pPce->NumLfeChannelElements; i++) { + pPce->LfeElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4); + pPce->NumChannels += 1; + + /* Check element instance tag according to ISO/IEC 13818-7:2003(E), + * chapter 8.2.1.1 */ + if (checkElementTagSelect[2][tag] == 0) { + checkElementTagSelect[2][tag] = 1; + } else { + pPce->isValid = 0; + } + } + + for (i = 0; i < pPce->NumAssocDataElements; i++) { + pPce->AssocDataElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); + } + + for (i = 0; i < pPce->NumValidCcElements; i++) { + pPce->CcElementIsIndSw[i] = (UCHAR)FDKreadBits(bs, 1); + pPce->ValidCcElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); + } + + FDKbyteAlign(bs, alignmentAnchor); + + pPce->CommentFieldBytes = (UCHAR)FDKreadBits(bs, 8); + commentBytes = pPce->CommentFieldBytes; + + /* Search for height info extension and read it if available */ + if (CProgramConfig_ReadHeightExt(pPce, bs, &commentBytes, alignmentAnchor)) { + pPce->isValid = 0; + } + + /* Check order of elements according to ISO / IEC 13818 - 7:2003(E), + * chapter 8.5.1 */ + if (CProgramConfig_Check(pPce)) { + pPce->isValid = 0; + } + + for (i = 0; i < commentBytes; i++) { + UCHAR text; + + text = (UCHAR)FDKreadBits(bs, 8); + + if (i < PC_COMMENTLENGTH) { + pPce->Comment[i] = text; + } + } +} + +/* + * Compare two program configurations. + * Returns the result of the comparison: + * -1 - completely different + * 0 - completely equal + * 1 - different but same channel configuration + * 2 - different channel configuration but same number of channels + */ +int CProgramConfig_Compare(const CProgramConfig *const pPce1, + const CProgramConfig *const pPce2) { + int result = 0; /* Innocent until proven false. */ + + if (FDKmemcmp(pPce1, pPce2, sizeof(CProgramConfig)) != + 0) { /* Configurations are not completely equal. + So look into details and analyse the channel configurations: */ + result = -1; + + if (pPce1->NumChannels == + pPce2->NumChannels) { /* Now the logic changes. We first assume to have + the same channel configuration and then prove + if this assumption is true. */ + result = 1; + + /* Front channels */ + if (pPce1->NumFrontChannelElements != pPce2->NumFrontChannelElements) { + result = 2; /* different number of front channel elements */ + } else { + int el, numCh1 = 0, numCh2 = 0; + for (el = 0; el < pPce1->NumFrontChannelElements; el += 1) { + if (pPce1->FrontElementHeightInfo[el] != + pPce2->FrontElementHeightInfo[el]) { + result = 2; /* different height info */ + break; + } + numCh1 += pPce1->FrontElementIsCpe[el] ? 2 : 1; + numCh2 += pPce2->FrontElementIsCpe[el] ? 2 : 1; + } + if (numCh1 != numCh2) { + result = 2; /* different number of front channels */ + } + } + /* Side channels */ + if (pPce1->NumSideChannelElements != pPce2->NumSideChannelElements) { + result = 2; /* different number of side channel elements */ + } else { + int el, numCh1 = 0, numCh2 = 0; + for (el = 0; el < pPce1->NumSideChannelElements; el += 1) { + if (pPce1->SideElementHeightInfo[el] != + pPce2->SideElementHeightInfo[el]) { + result = 2; /* different height info */ + break; + } + numCh1 += pPce1->SideElementIsCpe[el] ? 2 : 1; + numCh2 += pPce2->SideElementIsCpe[el] ? 2 : 1; + } + if (numCh1 != numCh2) { + result = 2; /* different number of side channels */ + } + } + /* Back channels */ + if (pPce1->NumBackChannelElements != pPce2->NumBackChannelElements) { + result = 2; /* different number of back channel elements */ + } else { + int el, numCh1 = 0, numCh2 = 0; + for (el = 0; el < pPce1->NumBackChannelElements; el += 1) { + if (pPce1->BackElementHeightInfo[el] != + pPce2->BackElementHeightInfo[el]) { + result = 2; /* different height info */ + break; + } + numCh1 += pPce1->BackElementIsCpe[el] ? 2 : 1; + numCh2 += pPce2->BackElementIsCpe[el] ? 2 : 1; + } + if (numCh1 != numCh2) { + result = 2; /* different number of back channels */ + } + } + /* LFE channels */ + if (pPce1->NumLfeChannelElements != pPce2->NumLfeChannelElements) { + result = 2; /* different number of lfe channels */ + } + /* LFEs are always SCEs so we don't need to count the channels. */ + } + } + + return result; +} + +void CProgramConfig_GetDefault(CProgramConfig *pPce, const UINT channelConfig) { + FDK_ASSERT(pPce != NULL); + + /* Init PCE */ + CProgramConfig_Init(pPce); + pPce->Profile = + 1; /* Set AAC LC because it is the only supported object type. */ + + switch (channelConfig) { + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 32: /* 7.1 side channel configuration as defined in FDK_audio.h */ + pPce->NumFrontChannelElements = 2; + pPce->FrontElementIsCpe[0] = 0; + pPce->FrontElementIsCpe[1] = 1; + pPce->NumSideChannelElements = 1; + pPce->SideElementIsCpe[0] = 1; + pPce->NumBackChannelElements = 1; + pPce->BackElementIsCpe[0] = 1; + pPce->NumLfeChannelElements = 1; + pPce->NumChannels = 8; + pPce->NumEffectiveChannels = 7; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 12: /* 3/0/4.1ch surround back */ + pPce->BackElementIsCpe[1] = 1; + pPce->NumChannels += 1; + pPce->NumEffectiveChannels += 1; + FDK_FALLTHROUGH; + case 11: /* 3/0/3.1ch */ + pPce->NumFrontChannelElements += 2; + pPce->FrontElementIsCpe[0] = 0; + pPce->FrontElementIsCpe[1] = 1; + pPce->NumBackChannelElements += 2; + pPce->BackElementIsCpe[0] = 1; + pPce->BackElementIsCpe[1] += 0; + pPce->NumLfeChannelElements += 1; + pPce->NumChannels += 7; + pPce->NumEffectiveChannels += 6; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 14: /* 2/0/0-3/0/2-0.1ch front height */ + pPce->FrontElementHeightInfo[2] = 1; /* Top speaker */ + FDK_FALLTHROUGH; + case 7: /* 5/0/2.1ch front */ + pPce->NumFrontChannelElements += 1; + pPce->FrontElementIsCpe[2] = 1; + pPce->NumChannels += 2; + pPce->NumEffectiveChannels += 2; + FDK_FALLTHROUGH; + case 6: /* 3/0/2.1ch */ + pPce->NumLfeChannelElements += 1; + pPce->NumChannels += 1; + FDK_FALLTHROUGH; + case 5: /* 3/0/2.0ch */ + case 4: /* 3/0/1.0ch */ + pPce->NumBackChannelElements += 1; + pPce->BackElementIsCpe[0] = (channelConfig > 4) ? 1 : 0; + pPce->NumChannels += (channelConfig > 4) ? 2 : 1; + pPce->NumEffectiveChannels += (channelConfig > 4) ? 2 : 1; + FDK_FALLTHROUGH; + case 3: /* 3/0/0.0ch */ + pPce->NumFrontChannelElements += 1; + pPce->FrontElementIsCpe[1] = 1; + pPce->NumChannels += 2; + pPce->NumEffectiveChannels += 2; + FDK_FALLTHROUGH; + case 1: /* 1/0/0.0ch */ + pPce->NumFrontChannelElements += 1; + pPce->FrontElementIsCpe[0] = 0; + pPce->NumChannels += 1; + pPce->NumEffectiveChannels += 1; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 2: /* 2/0/0.ch */ + pPce->NumFrontChannelElements = 1; + pPce->FrontElementIsCpe[0] = 1; + pPce->NumChannels += 2; + pPce->NumEffectiveChannels += 2; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + default: + pPce->isValid = 0; /* To be explicit! */ + break; + } + + if (pPce->isValid) { + /* Create valid element instance tags */ + int el, elTagSce = 0, elTagCpe = 0; + + for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { + pPce->FrontElementTagSelect[el] = + (pPce->FrontElementIsCpe[el]) ? elTagCpe++ : elTagSce++; + } + for (el = 0; el < pPce->NumSideChannelElements; el += 1) { + pPce->SideElementTagSelect[el] = + (pPce->SideElementIsCpe[el]) ? elTagCpe++ : elTagSce++; + } + for (el = 0; el < pPce->NumBackChannelElements; el += 1) { + pPce->BackElementTagSelect[el] = + (pPce->BackElementIsCpe[el]) ? elTagCpe++ : elTagSce++; + } + elTagSce = 0; + for (el = 0; el < pPce->NumLfeChannelElements; el += 1) { + pPce->LfeElementTagSelect[el] = elTagSce++; + } + } +} + +/** + * \brief get implicit audio channel type for given channelConfig and MPEG + * ordered channel index + * \param channelConfig MPEG channelConfiguration from 1 upto 14 + * \param index MPEG channel order index + * \return audio channel type. + */ +static void getImplicitAudioChannelTypeAndIndex(AUDIO_CHANNEL_TYPE *chType, + UCHAR *chIndex, + UINT channelConfig, + UINT index) { + if (index < 3) { + *chType = ACT_FRONT; + *chIndex = index; + } else { + switch (channelConfig) { + case 4: /* SCE, CPE, SCE */ + case 5: /* SCE, CPE, CPE */ + case 6: /* SCE, CPE, CPE, LFE */ + switch (index) { + case 3: + case 4: + *chType = ACT_BACK; + *chIndex = index - 3; + break; + case 5: + *chType = ACT_LFE; + *chIndex = 0; + break; + } + break; + case 7: /* SCE,CPE,CPE,CPE,LFE */ + switch (index) { + case 3: + case 4: + *chType = ACT_FRONT; + *chIndex = index; + break; + case 5: + case 6: + *chType = ACT_BACK; + *chIndex = index - 5; + break; + case 7: + *chType = ACT_LFE; + *chIndex = 0; + break; + } + break; + case 11: /* SCE,CPE,CPE,SCE,LFE */ + if (index < 6) { + *chType = ACT_BACK; + *chIndex = index - 3; + } else { + *chType = ACT_LFE; + *chIndex = 0; + } + break; + case 12: /* SCE,CPE,CPE,CPE,LFE */ + if (index < 7) { + *chType = ACT_BACK; + *chIndex = index - 3; + } else { + *chType = ACT_LFE; + *chIndex = 0; + } + break; + case 14: /* SCE,CPE,CPE,LFE,CPE */ + switch (index) { + case 3: + case 4: + *chType = ACT_BACK; + *chIndex = index - 3; + break; + case 5: + *chType = ACT_LFE; + *chIndex = 0; + break; + case 6: + case 7: + *chType = ACT_FRONT_TOP; + *chIndex = index - 6; /* handle the top layer independently */ + break; + } + break; + default: + *chType = ACT_NONE; + break; + } + } +} + +int CProgramConfig_LookupElement(CProgramConfig *pPce, UINT channelConfig, + const UINT tag, const UINT channelIdx, + UCHAR chMapping[], AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[], const UINT chDescrLen, + UCHAR *elMapping, MP4_ELEMENT_ID elList[], + MP4_ELEMENT_ID elType) { + if (channelConfig > 0) { + /* Constant channel mapping must have + been set during initialization. */ + if (IS_CHANNEL_ELEMENT(elType)) { + *elMapping = pPce->elCounter; + if (elList[pPce->elCounter] != elType && + !IS_USAC_CHANNEL_ELEMENT(elType)) { + /* Not in the list */ + if ((channelConfig == 2) && + (elType == ID_SCE)) { /* This scenario occurs with HE-AAC v2 streams + of buggy encoders. In other decoder + implementations decoding of this kind of + streams is desired. */ + channelConfig = 1; + } else if ((elList[pPce->elCounter] == ID_LFE) && + (elType == + ID_SCE)) { /* Decode bitstreams which wrongly use ID_SCE + instead of ID_LFE element type. */ + ; + } else { + return 0; + } + } + /* Assume all front channels */ + getImplicitAudioChannelTypeAndIndex( + &chType[channelIdx], &chIndex[channelIdx], channelConfig, channelIdx); + if (elType == ID_CPE || elType == ID_USAC_CPE) { + chType[channelIdx + 1] = chType[channelIdx]; + chIndex[channelIdx + 1] = chIndex[channelIdx] + 1; + } + pPce->elCounter++; + } + /* Accept all non-channel elements, too. */ + return 1; + } else { + if ((!pPce->isValid) || (pPce->NumChannels > chDescrLen)) { + /* Implicit channel mapping. */ + if (IS_USAC_CHANNEL_ELEMENT(elType)) { + *elMapping = pPce->elCounter++; + } else if (IS_MP4_CHANNEL_ELEMENT(elType)) { + /* Store all channel element IDs */ + elList[pPce->elCounter] = elType; + *elMapping = pPce->elCounter++; + } + } else { + /* Accept the additional channel(s), only if the tag is in the lists */ + int isCpe = 0, i; + /* Element counter */ + int ec[PC_NUM_HEIGHT_LAYER] = {0}; + /* Channel counters */ + int cc[PC_NUM_HEIGHT_LAYER] = {0}; + int fc[PC_NUM_HEIGHT_LAYER] = {0}; /* front channel counter */ + int sc[PC_NUM_HEIGHT_LAYER] = {0}; /* side channel counter */ + int bc[PC_NUM_HEIGHT_LAYER] = {0}; /* back channel counter */ + int lc = 0; /* lfe channel counter */ + + /* General MPEG (PCE) composition rules: + - Over all: + + - Within each height layer: + + - Exception: + The LFE channels have no height info and thus they are arranged at + the very end of the normal height layer channels. + */ + + switch (elType) { + case ID_CPE: + isCpe = 1; + FDK_FALLTHROUGH; + case ID_SCE: + /* search in front channels */ + for (i = 0; i < pPce->NumFrontChannelElements; i++) { + int heightLayer = pPce->FrontElementHeightInfo[i]; + if (isCpe == pPce->FrontElementIsCpe[i] && + pPce->FrontElementTagSelect[i] == tag) { + int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; + AUDIO_CHANNEL_TYPE aChType = + (AUDIO_CHANNEL_TYPE)((heightLayer << 4) | ACT_FRONT); + for (h = heightLayer - 1; h >= 0; h -= 1) { + int el; + /* Count front channels/elements */ + for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { + if (pPce->FrontElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + } + } + /* Count side channels/elements */ + for (el = 0; el < pPce->NumSideChannelElements; el += 1) { + if (pPce->SideElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + } + } + /* Count back channels/elements */ + for (el = 0; el < pPce->NumBackChannelElements; el += 1) { + if (pPce->BackElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + } + } + if (h == 0) { /* normal height */ + elIdx += pPce->NumLfeChannelElements; + chIdx += pPce->NumLfeChannelElements; + } + } + chMapping[chIdx] = channelIdx; + chType[chIdx] = aChType; + chIndex[chIdx] = fc[heightLayer]; + if (isCpe) { + chMapping[chIdx + 1] = channelIdx + 1; + chType[chIdx + 1] = aChType; + chIndex[chIdx + 1] = fc[heightLayer] + 1; + } + *elMapping = elIdx; + return 1; + } + ec[heightLayer] += 1; + if (pPce->FrontElementIsCpe[i]) { + cc[heightLayer] += 2; + fc[heightLayer] += 2; + } else { + cc[heightLayer] += 1; + fc[heightLayer] += 1; + } + } + /* search in side channels */ + for (i = 0; i < pPce->NumSideChannelElements; i++) { + int heightLayer = pPce->SideElementHeightInfo[i]; + if (isCpe == pPce->SideElementIsCpe[i] && + pPce->SideElementTagSelect[i] == tag) { + int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; + AUDIO_CHANNEL_TYPE aChType = + (AUDIO_CHANNEL_TYPE)((heightLayer << 4) | ACT_SIDE); + for (h = heightLayer - 1; h >= 0; h -= 1) { + int el; + /* Count front channels/elements */ + for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { + if (pPce->FrontElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + } + } + /* Count side channels/elements */ + for (el = 0; el < pPce->NumSideChannelElements; el += 1) { + if (pPce->SideElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + } + } + /* Count back channels/elements */ + for (el = 0; el < pPce->NumBackChannelElements; el += 1) { + if (pPce->BackElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + } + } + if (h == + 0) { /* LFE channels belong to the normal height layer */ + elIdx += pPce->NumLfeChannelElements; + chIdx += pPce->NumLfeChannelElements; + } + } + chMapping[chIdx] = channelIdx; + chType[chIdx] = aChType; + chIndex[chIdx] = sc[heightLayer]; + if (isCpe) { + chMapping[chIdx + 1] = channelIdx + 1; + chType[chIdx + 1] = aChType; + chIndex[chIdx + 1] = sc[heightLayer] + 1; + } + *elMapping = elIdx; + return 1; + } + ec[heightLayer] += 1; + if (pPce->SideElementIsCpe[i]) { + cc[heightLayer] += 2; + sc[heightLayer] += 2; + } else { + cc[heightLayer] += 1; + sc[heightLayer] += 1; + } + } + /* search in back channels */ + for (i = 0; i < pPce->NumBackChannelElements; i++) { + int heightLayer = pPce->BackElementHeightInfo[i]; + if (isCpe == pPce->BackElementIsCpe[i] && + pPce->BackElementTagSelect[i] == tag) { + int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; + AUDIO_CHANNEL_TYPE aChType = + (AUDIO_CHANNEL_TYPE)((heightLayer << 4) | ACT_BACK); + for (h = heightLayer - 1; h >= 0; h -= 1) { + int el; + /* Count front channels/elements */ + for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { + if (pPce->FrontElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + } + } + /* Count side channels/elements */ + for (el = 0; el < pPce->NumSideChannelElements; el += 1) { + if (pPce->SideElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + } + } + /* Count back channels/elements */ + for (el = 0; el < pPce->NumBackChannelElements; el += 1) { + if (pPce->BackElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + } + } + if (h == 0) { /* normal height */ + elIdx += pPce->NumLfeChannelElements; + chIdx += pPce->NumLfeChannelElements; + } + } + chMapping[chIdx] = channelIdx; + chType[chIdx] = aChType; + chIndex[chIdx] = bc[heightLayer]; + if (isCpe) { + chMapping[chIdx + 1] = channelIdx + 1; + chType[chIdx + 1] = aChType; + chIndex[chIdx + 1] = bc[heightLayer] + 1; + } + *elMapping = elIdx; + return 1; + } + ec[heightLayer] += 1; + if (pPce->BackElementIsCpe[i]) { + cc[heightLayer] += 2; + bc[heightLayer] += 2; + } else { + cc[heightLayer] += 1; + bc[heightLayer] += 1; + } + } + break; + + case ID_LFE: { /* Unfortunately we have to go through all normal height + layer elements to get the position of the LFE + channels. Start with counting the front + channels/elements at normal height */ + for (i = 0; i < pPce->NumFrontChannelElements; i += 1) { + int heightLayer = pPce->FrontElementHeightInfo[i]; + ec[heightLayer] += 1; + cc[heightLayer] += (pPce->FrontElementIsCpe[i]) ? 2 : 1; + } + /* Count side channels/elements at normal height */ + for (i = 0; i < pPce->NumSideChannelElements; i += 1) { + int heightLayer = pPce->SideElementHeightInfo[i]; + ec[heightLayer] += 1; + cc[heightLayer] += (pPce->SideElementIsCpe[i]) ? 2 : 1; + } + /* Count back channels/elements at normal height */ + for (i = 0; i < pPce->NumBackChannelElements; i += 1) { + int heightLayer = pPce->BackElementHeightInfo[i]; + ec[heightLayer] += 1; + cc[heightLayer] += (pPce->BackElementIsCpe[i]) ? 2 : 1; + } + + /* search in lfe channels */ + for (i = 0; i < pPce->NumLfeChannelElements; i++) { + int elIdx = + ec[0]; /* LFE channels belong to the normal height layer */ + int chIdx = cc[0]; + if (pPce->LfeElementTagSelect[i] == tag) { + chMapping[chIdx] = channelIdx; + *elMapping = elIdx; + chType[chIdx] = ACT_LFE; + chIndex[chIdx] = lc; + return 1; + } + ec[0] += 1; + cc[0] += 1; + lc += 1; + } + } break; + + /* Non audio elements */ + case ID_CCE: + /* search in cce channels */ + for (i = 0; i < pPce->NumValidCcElements; i++) { + if (pPce->ValidCcElementTagSelect[i] == tag) { + return 1; + } + } + break; + case ID_DSE: + /* search associated data elements */ + for (i = 0; i < pPce->NumAssocDataElements; i++) { + if (pPce->AssocDataElementTagSelect[i] == tag) { + return 1; + } + } + break; + default: + return 0; + } + return 0; /* not found in any list */ + } + } + + return 1; +} + +#define SPEAKER_PLANE_NORMAL 0 +#define SPEAKER_PLANE_TOP 1 +#define SPEAKER_PLANE_BOTTOM 2 + +void CProgramConfig_GetChannelDescription(const UINT chConfig, + const CProgramConfig *pPce, + AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[]) { + FDK_ASSERT(chType != NULL); + FDK_ASSERT(chIndex != NULL); + + if ((chConfig == 0) && (pPce != NULL)) { + if (pPce->isValid) { + int spkPlane, chIdx = 0; + for (spkPlane = SPEAKER_PLANE_NORMAL; spkPlane <= SPEAKER_PLANE_BOTTOM; + spkPlane += 1) { + int elIdx, grpChIdx = 0; + for (elIdx = 0; elIdx < pPce->NumFrontChannelElements; elIdx += 1) { + if (pPce->FrontElementHeightInfo[elIdx] == spkPlane) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_FRONT); + chIndex[chIdx++] = grpChIdx++; + if (pPce->FrontElementIsCpe[elIdx]) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_FRONT); + chIndex[chIdx++] = grpChIdx++; + } + } + } + grpChIdx = 0; + for (elIdx = 0; elIdx < pPce->NumSideChannelElements; elIdx += 1) { + if (pPce->SideElementHeightInfo[elIdx] == spkPlane) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_SIDE); + chIndex[chIdx++] = grpChIdx++; + if (pPce->SideElementIsCpe[elIdx]) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_SIDE); + chIndex[chIdx++] = grpChIdx++; + } + } + } + grpChIdx = 0; + for (elIdx = 0; elIdx < pPce->NumBackChannelElements; elIdx += 1) { + if (pPce->BackElementHeightInfo[elIdx] == spkPlane) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_BACK); + chIndex[chIdx++] = grpChIdx++; + if (pPce->BackElementIsCpe[elIdx]) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_BACK); + chIndex[chIdx++] = grpChIdx++; + } + } + } + grpChIdx = 0; + if (spkPlane == SPEAKER_PLANE_NORMAL) { + for (elIdx = 0; elIdx < pPce->NumLfeChannelElements; elIdx += 1) { + chType[chIdx] = ACT_LFE; + chIndex[chIdx++] = grpChIdx++; + } + } + } + } + } else { + int chIdx; + for (chIdx = 0; chIdx < getNumberOfTotalChannels(chConfig); chIdx += 1) { + getImplicitAudioChannelTypeAndIndex(&chType[chIdx], &chIndex[chIdx], + chConfig, chIdx); + } + } +} + +int CProgramConfig_GetPceChMap(const CProgramConfig *pPce, UCHAR pceChMap[], + const UINT pceChMapLen) { + const UCHAR *nElements = &pPce->NumFrontChannelElements; + const UCHAR *elHeight[3], *elIsCpe[3]; + unsigned chIdx, plane, grp, offset, totCh[3], numCh[3][4]; + + FDK_ASSERT(pPce != NULL); + FDK_ASSERT(pceChMap != NULL); + + /* Init counter: */ + FDKmemclear(totCh, 3 * sizeof(unsigned)); + FDKmemclear(numCh, 3 * 4 * sizeof(unsigned)); + + /* Analyse PCE: */ + elHeight[0] = pPce->FrontElementHeightInfo; + elIsCpe[0] = pPce->FrontElementIsCpe; + elHeight[1] = pPce->SideElementHeightInfo; + elIsCpe[1] = pPce->SideElementIsCpe; + elHeight[2] = pPce->BackElementHeightInfo; + elIsCpe[2] = pPce->BackElementIsCpe; + + for (plane = 0; plane <= SPEAKER_PLANE_BOTTOM; plane += 1) { + for (grp = 0; grp < 3; grp += 1) { /* front, side, back */ + unsigned el; + for (el = 0; el < nElements[grp]; el += 1) { + if (elHeight[grp][el] == plane) { + unsigned elCh = elIsCpe[grp][el] ? 2 : 1; + numCh[plane][grp] += elCh; + totCh[plane] += elCh; + } + } + } + if (plane == SPEAKER_PLANE_NORMAL) { + unsigned elCh = pPce->NumLfeChannelElements; + numCh[plane][grp] += elCh; + totCh[plane] += elCh; + } + } + /* Sanity checks: */ + chIdx = totCh[SPEAKER_PLANE_NORMAL] + totCh[SPEAKER_PLANE_TOP] + + totCh[SPEAKER_PLANE_BOTTOM]; + if (chIdx > pceChMapLen) { + return -1; + } + + /* Create map: */ + offset = grp = 0; + unsigned grpThresh = numCh[SPEAKER_PLANE_NORMAL][grp]; + for (chIdx = 0; chIdx < totCh[SPEAKER_PLANE_NORMAL]; chIdx += 1) { + while ((chIdx >= grpThresh) && (grp < 3)) { + offset += numCh[1][grp] + numCh[2][grp]; + grp += 1; + grpThresh += numCh[SPEAKER_PLANE_NORMAL][grp]; + } + pceChMap[chIdx] = chIdx + offset; + } + offset = 0; + for (grp = 0; grp < 4; grp += 1) { /* front, side, back and lfe */ + offset += numCh[SPEAKER_PLANE_NORMAL][grp]; + for (plane = SPEAKER_PLANE_TOP; plane <= SPEAKER_PLANE_BOTTOM; plane += 1) { + unsigned mapCh; + for (mapCh = 0; mapCh < numCh[plane][grp]; mapCh += 1) { + pceChMap[chIdx++] = offset; + offset += 1; + } + } + } + return 0; +} + +int CProgramConfig_GetElementTable(const CProgramConfig *pPce, + MP4_ELEMENT_ID elList[], + const INT elListSize, UCHAR *pChMapIdx) { + int i, el = 0; + + FDK_ASSERT(elList != NULL); + FDK_ASSERT(pChMapIdx != NULL); + FDK_ASSERT(pPce != NULL); + + *pChMapIdx = 0; + + if ((elListSize < + pPce->NumFrontChannelElements + pPce->NumSideChannelElements + + pPce->NumBackChannelElements + pPce->NumLfeChannelElements) || + (pPce->NumChannels == 0)) { + return 0; + } + + for (i = 0; i < pPce->NumFrontChannelElements; i += 1) { + elList[el++] = (pPce->FrontElementIsCpe[i]) ? ID_CPE : ID_SCE; + } + + for (i = 0; i < pPce->NumSideChannelElements; i += 1) { + elList[el++] = (pPce->SideElementIsCpe[i]) ? ID_CPE : ID_SCE; + } + + for (i = 0; i < pPce->NumBackChannelElements; i += 1) { + elList[el++] = (pPce->BackElementIsCpe[i]) ? ID_CPE : ID_SCE; + } + + for (i = 0; i < pPce->NumLfeChannelElements; i += 1) { + elList[el++] = ID_LFE; + } + + /* Find an corresponding channel configuration if possible */ + switch (pPce->NumChannels) { + case 1: + case 2: + /* One and two channels have no alternatives. */ + *pChMapIdx = pPce->NumChannels; + break; + case 3: + case 4: + case 5: + case 6: { /* Test if the number of channels can be used as channel config: + */ + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + /* Create a PCE for the config to test ... */ + CProgramConfig_GetDefault(tmpPce, pPce->NumChannels); + /* ... and compare it with the given one. */ + *pChMapIdx = (!(CProgramConfig_Compare(pPce, tmpPce) & 0xE)) + ? pPce->NumChannels + : 0; + /* If compare result is 0 or 1 we can be sure that it is channel + * config 11. */ + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + } break; + case 7: { + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + /* Create a PCE for the config to test ... */ + CProgramConfig_GetDefault(tmpPce, 11); + /* ... and compare it with the given one. */ + *pChMapIdx = (!(CProgramConfig_Compare(pPce, tmpPce) & 0xE)) ? 11 : 0; + /* If compare result is 0 or 1 we can be sure that it is channel + * config 11. */ + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + } break; + case 8: { /* Try the four possible 7.1ch configurations. One after the + other. */ + UCHAR testCfg[4] = {32, 14, 12, 7}; + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + for (i = 0; i < 4; i += 1) { + /* Create a PCE for the config to test ... */ + CProgramConfig_GetDefault(tmpPce, testCfg[i]); + /* ... and compare it with the given one. */ + if (!(CProgramConfig_Compare(pPce, tmpPce) & 0xE)) { + /* If the compare result is 0 or 1 than the two channel configurations + * match. */ + /* Explicit mapping of 7.1 side channel configuration to 7.1 rear + * channel mapping. */ + *pChMapIdx = (testCfg[i] == 32) ? 12 : testCfg[i]; + } + } + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + } break; + default: + /* The PCE does not match any predefined channel configuration. */ + *pChMapIdx = 0; + break; + } + + return el; +} + +static AUDIO_OBJECT_TYPE getAOT(HANDLE_FDK_BITSTREAM bs) { + int tmp = 0; + + tmp = FDKreadBits(bs, 5); + if (tmp == AOT_ESCAPE) { + int tmp2 = FDKreadBits(bs, 6); + tmp = 32 + tmp2; + } + + return (AUDIO_OBJECT_TYPE)tmp; +} + +static INT getSampleRate(HANDLE_FDK_BITSTREAM bs, UCHAR *index, int nBits) { + INT sampleRate; + int idx; + + idx = FDKreadBits(bs, nBits); + if (idx == (1 << nBits) - 1) { + if (FDKgetValidBits(bs) < 24) { + return 0; + } + sampleRate = FDKreadBits(bs, 24); + } else { + sampleRate = SamplingRateTable[idx]; + } + + *index = idx; + + return sampleRate; +} + +static TRANSPORTDEC_ERROR GaSpecificConfig_Parse(CSGaSpecificConfig *self, + CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM bs, + UINT ascStartAnchor) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + self->m_frameLengthFlag = FDKreadBits(bs, 1); + + self->m_dependsOnCoreCoder = FDKreadBits(bs, 1); + + if (self->m_dependsOnCoreCoder) self->m_coreCoderDelay = FDKreadBits(bs, 14); + + self->m_extensionFlag = FDKreadBits(bs, 1); + + if (asc->m_channelConfiguration == 0) { + CProgramConfig_Read(&asc->m_progrConfigElement, bs, ascStartAnchor); + } + + if ((asc->m_aot == AOT_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_SCAL)) { + self->m_layer = FDKreadBits(bs, 3); + } + + if (self->m_extensionFlag) { + if (asc->m_aot == AOT_ER_BSAC) { + self->m_numOfSubFrame = FDKreadBits(bs, 5); + self->m_layerLength = FDKreadBits(bs, 11); + } + + if ((asc->m_aot == AOT_ER_AAC_LC) || (asc->m_aot == AOT_ER_AAC_LTP) || + (asc->m_aot == AOT_ER_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_LD)) { + asc->m_vcb11Flag = FDKreadBits(bs, 1); /* aacSectionDataResilienceFlag */ + asc->m_rvlcFlag = + FDKreadBits(bs, 1); /* aacScalefactorDataResilienceFlag */ + asc->m_hcrFlag = FDKreadBits(bs, 1); /* aacSpectralDataResilienceFlag */ + } + + self->m_extensionFlag3 = FDKreadBits(bs, 1); + } + return (ErrorStatus); +} + +static INT skipSbrHeader(HANDLE_FDK_BITSTREAM hBs, int isUsac) { + /* Dummy parse SbrDfltHeader() */ + INT dflt_header_extra1, dflt_header_extra2, bitsToSkip = 0; + + if (!isUsac) { + bitsToSkip = 6; + FDKpushFor(hBs, 6); /* amp res 1, xover freq 3, reserved 2 */ + } + bitsToSkip += 8; + FDKpushFor(hBs, 8); /* start / stop freq */ + bitsToSkip += 2; + dflt_header_extra1 = FDKreadBit(hBs); + dflt_header_extra2 = FDKreadBit(hBs); + bitsToSkip += 5 * dflt_header_extra1 + 6 * dflt_header_extra2; + FDKpushFor(hBs, 5 * dflt_header_extra1 + 6 * dflt_header_extra2); + + return bitsToSkip; +} + +static INT ld_sbr_header(CSAudioSpecificConfig *asc, const INT dsFactor, + HANDLE_FDK_BITSTREAM hBs, CSTpCallBacks *cb) { + const int channelConfiguration = asc->m_channelConfiguration; + int i = 0, j = 0; + INT error = 0; + MP4_ELEMENT_ID element = ID_NONE; + + /* check whether the channelConfiguration is defined in + * channel_configuration_array */ + if (channelConfiguration < 0 || + channelConfiguration > (INT)(sizeof(channel_configuration_array) / + sizeof(MP4_ELEMENT_ID **) - + 1)) { + return TRANSPORTDEC_PARSE_ERROR; + } + + /* read elements of the passed channel_configuration until there is ID_NONE */ + while ((element = channel_configuration_array[channelConfiguration][j]) != + ID_NONE) { + /* Setup LFE element for upsampling too. This is essential especially for + * channel configs where the LFE element is not at the last position for + * example in channel config 13 or 14. It leads to memory leaks if the setup + * of the LFE element would be done later in the core. */ + if (element == ID_SCE || element == ID_CPE || element == ID_LFE) { + error |= cb->cbSbr( + cb->cbSbrData, hBs, asc->m_samplingFrequency / dsFactor, + asc->m_extensionSamplingFrequency / dsFactor, + asc->m_samplesPerFrame / dsFactor, AOT_ER_AAC_ELD, element, i++, 0, 0, + asc->configMode, &asc->SbrConfigChanged, dsFactor); + if (error != TRANSPORTDEC_OK) { + goto bail; + } + } + j++; + } +bail: + return error; +} + +static TRANSPORTDEC_ERROR EldSpecificConfig_Parse(CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + CSEldSpecificConfig *esc = &asc->m_sc.m_eldSpecificConfig; + UINT eldExtType; + int eldExtLen, len, cnt, ldSbrLen = 0, eldExtLenSum, numSbrHeader = 0, + sbrIndex, eldExtCnt = 0; + + unsigned char downscale_fill_nibble; + + FDKmemclear(esc, sizeof(CSEldSpecificConfig)); + + esc->m_frameLengthFlag = FDKreadBits(hBs, 1); + if (esc->m_frameLengthFlag) { + asc->m_samplesPerFrame = 480; + } else { + asc->m_samplesPerFrame = 512; + } + + asc->m_vcb11Flag = FDKreadBits(hBs, 1); + asc->m_rvlcFlag = FDKreadBits(hBs, 1); + asc->m_hcrFlag = FDKreadBits(hBs, 1); + + esc->m_sbrPresentFlag = FDKreadBits(hBs, 1); + + if (esc->m_sbrPresentFlag == 1) { + esc->m_sbrSamplingRate = + FDKreadBits(hBs, 1); /* 0: single rate, 1: dual rate */ + esc->m_sbrCrcFlag = FDKreadBits(hBs, 1); + + asc->m_extensionSamplingFrequency = asc->m_samplingFrequency + << esc->m_sbrSamplingRate; + + if (cb->cbSbr != NULL) { + /* ELD reduced delay mode: LD-SBR initialization has to know the downscale + information. Postpone LD-SBR initialization and read ELD extension + information first. */ + switch (asc->m_channelConfiguration) { + case 1: + case 2: + numSbrHeader = 1; + break; + case 3: + numSbrHeader = 2; + break; + case 4: + case 5: + case 6: + numSbrHeader = 3; + break; + case 7: + case 11: + case 12: + case 14: + numSbrHeader = 4; + break; + default: + numSbrHeader = 0; + break; + } + for (sbrIndex = 0; sbrIndex < numSbrHeader; sbrIndex++) { + ldSbrLen += skipSbrHeader(hBs, 0); + } + } else { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + } + esc->m_useLdQmfTimeAlign = 0; + + /* new ELD syntax */ + eldExtLenSum = FDKgetValidBits(hBs); + esc->m_downscaledSamplingFrequency = asc->m_samplingFrequency; + /* parse ExtTypeConfigData */ + while (((eldExtType = FDKreadBits(hBs, 4)) != ELDEXT_TERM) && + ((INT)FDKgetValidBits(hBs) >= 0) && (eldExtCnt++ < 15)) { + eldExtLen = len = FDKreadBits(hBs, 4); + if (len == 0xf) { + len = FDKreadBits(hBs, 8); + eldExtLen += len; + + if (len == 0xff) { + len = FDKreadBits(hBs, 16); + eldExtLen += len; + } + } + + switch (eldExtType) { + case ELDEXT_LDSAC: + esc->m_useLdQmfTimeAlign = 1; + if (cb->cbSsc != NULL) { + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbSsc( + cb->cbSscData, hBs, asc->m_aot, + asc->m_samplingFrequency << esc->m_sbrSamplingRate, + asc->m_samplesPerFrame << esc->m_sbrSamplingRate, + asc->m_channelConfiguration, 1, /* stereoConfigIndex */ + -1, /* nTimeSlots: read from bitstream */ + eldExtLen, asc->configMode, &asc->SacConfigChanged); + if (ErrorStatus != TRANSPORTDEC_OK) { + return TRANSPORTDEC_PARSE_ERROR; + } + if (esc->m_downscaledSamplingFrequency != asc->m_samplingFrequency) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; /* ELDv2 w/ ELD downscaled + mode not allowed */ + } + break; + } + + FDK_FALLTHROUGH; + default: + for (cnt = 0; cnt < eldExtLen; cnt++) { + FDKreadBits(hBs, 8); + } + break; + + case ELDEXT_DOWNSCALEINFO: + UCHAR tmpDownscaleFreqIdx; + esc->m_downscaledSamplingFrequency = + getSampleRate(hBs, &tmpDownscaleFreqIdx, 4); + if (esc->m_downscaledSamplingFrequency == 0 || + esc->m_downscaledSamplingFrequency > 96000) { + return TRANSPORTDEC_PARSE_ERROR; + } + downscale_fill_nibble = FDKreadBits(hBs, 4); + if (downscale_fill_nibble != 0x0) { + return TRANSPORTDEC_PARSE_ERROR; + } + if (esc->m_useLdQmfTimeAlign == 1) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; /* ELDv2 w/ ELD downscaled + mode not allowed */ + } + break; + } + } + if (eldExtType != ELDEXT_TERM) { + return TRANSPORTDEC_PARSE_ERROR; + } + + if ((INT)FDKgetValidBits(hBs) < 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + + if (esc->m_sbrPresentFlag == 1 && numSbrHeader != 0) { + INT dsFactor = 1; /* Downscale factor must be 1 or even for SBR */ + if (esc->m_downscaledSamplingFrequency != 0) { + if (asc->m_samplingFrequency % esc->m_downscaledSamplingFrequency != 0) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + dsFactor = asc->m_samplingFrequency / esc->m_downscaledSamplingFrequency; + if (dsFactor != 1 && (dsFactor)&1) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; /* SBR needs an even downscale + factor */ + } + if (dsFactor != 1 && dsFactor != 2 && dsFactor != 4) { + dsFactor = 1; /* don't apply dsf for not yet supported even dsfs */ + } + if ((INT)asc->m_samplesPerFrame % dsFactor != 0) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; /* frameSize/dsf must be an + integer number */ + } + } + eldExtLenSum = eldExtLenSum - FDKgetValidBits(hBs); + FDKpushBack(hBs, eldExtLenSum + ldSbrLen); + if (0 != ld_sbr_header(asc, dsFactor, hBs, cb)) { + return TRANSPORTDEC_PARSE_ERROR; + } + FDKpushFor(hBs, eldExtLenSum); + } + return (ErrorStatus); +} + +/* +Subroutine to store config in UCHAR buffer. Bit stream position does not change. +*/ +static UINT StoreConfigAsBitstream( + HANDLE_FDK_BITSTREAM hBs, const INT configSize_bits, /* If < 0 (> 0) config + to read is before + (after) current bit + stream position. */ + UCHAR *configTargetBuffer, const USHORT configTargetBufferSize_bytes) { + FDK_BITSTREAM usacConf; + UINT const nBits = fAbs(configSize_bits); + UINT j, tmp; + + if (nBits > 8 * (UINT)configTargetBufferSize_bytes) { + return 1; + } + FDKmemclear(configTargetBuffer, configTargetBufferSize_bytes); + + FDKinitBitStream(&usacConf, configTargetBuffer, configTargetBufferSize_bytes, + nBits, BS_WRITER); + if (configSize_bits < 0) { + FDKpushBack(hBs, nBits); + } + for (j = nBits; j > 31; j -= 32) { + tmp = FDKreadBits(hBs, 32); + FDKwriteBits(&usacConf, tmp, 32); + } + if (j > 0) { + tmp = FDKreadBits(hBs, j); + FDKwriteBits(&usacConf, tmp, j); + } + FDKsyncCache(&usacConf); + if (configSize_bits > 0) { + FDKpushBack(hBs, nBits); + } + + return 0; +} + +/* maps coreSbrFrameLengthIndex to coreCoderFrameLength */ +static const USHORT usacFrameLength[8] = {768, 1024, 2048, 2048, 4096, 0, 0, 0}; +/* maps coreSbrFrameLengthIndex to sbrRatioIndex */ +static const UCHAR sbrRatioIndex[8] = {0, 0, 2, 3, 1, 0, 0, 0}; + +/* + subroutine for parsing extension element configuration: + UsacExtElementConfig() q.v. ISO/IEC FDIS 23003-3:2011(E) Table 14 + rsv603daExtElementConfig() q.v. ISO/IEC DIS 23008-3 Table 13 +*/ +static TRANSPORTDEC_ERROR extElementConfig(CSUsacExtElementConfig *extElement, + HANDLE_FDK_BITSTREAM hBs, + const CSTpCallBacks *cb, + const UCHAR numSignalsInGroup, + const UINT coreFrameLength, + const int subStreamIndex, + const AUDIO_OBJECT_TYPE aot) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + UINT usacExtElementType = escapedValue(hBs, 4, 8, 16); + + /* recurve extension elements which are invalid for USAC */ + if (aot == AOT_USAC) { + switch (usacExtElementType) { + case ID_EXT_ELE_FILL: + case ID_EXT_ELE_MPEGS: + case ID_EXT_ELE_SAOC: + case ID_EXT_ELE_AUDIOPREROLL: + case ID_EXT_ELE_UNI_DRC: + break; + default: + usacExtElementType = ID_EXT_ELE_UNKNOWN; + break; + } + } + + int usacExtElementConfigLength = escapedValue(hBs, 4, 8, 16); + extElement->usacExtElementConfigLength = (USHORT)usacExtElementConfigLength; + INT bsAnchor; + + if (FDKreadBit(hBs)) /* usacExtElementDefaultLengthPresent */ + extElement->usacExtElementDefaultLength = escapedValue(hBs, 8, 16, 0) + 1; + else + extElement->usacExtElementDefaultLength = 0; + + extElement->usacExtElementPayloadFrag = FDKreadBit(hBs); + + bsAnchor = (INT)FDKgetValidBits(hBs); + + switch (usacExtElementType) { + case ID_EXT_ELE_UNKNOWN: + case ID_EXT_ELE_FILL: + break; + case ID_EXT_ELE_AUDIOPREROLL: + /* No configuration element */ + extElement->usacExtElementHasAudioPreRoll = 1; + break; + case ID_EXT_ELE_UNI_DRC: { + if (cb->cbUniDrc != NULL) { + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc( + cb->cbUniDrcData, hBs, usacExtElementConfigLength, + 0, /* uniDrcConfig */ + subStreamIndex, 0, aot); + if (ErrorStatus != TRANSPORTDEC_OK) { + return ErrorStatus; + } + } + } break; + default: + usacExtElementType = ID_EXT_ELE_UNKNOWN; + break; + } + extElement->usacExtElementType = (USAC_EXT_ELEMENT_TYPE)usacExtElementType; + + /* Adjust bit stream position. This is required because of byte alignment and + * unhandled extensions. */ + { + INT left_bits = (usacExtElementConfigLength << 3) - + (bsAnchor - (INT)FDKgetValidBits(hBs)); + if (left_bits >= 0) { + FDKpushFor(hBs, left_bits); + } else { + /* parsed too many bits */ + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + } + + return ErrorStatus; +} + +/* + subroutine for parsing the USAC / RSVD60 configuration extension: + UsacConfigExtension() q.v. ISO/IEC FDIS 23003-3:2011(E) Table 15 + rsv603daConfigExtension() q.v. ISO/IEC DIS 23008-3 Table 14 +*/ +static TRANSPORTDEC_ERROR configExtension(CSUsacConfig *usc, + HANDLE_FDK_BITSTREAM hBs, + const CSTpCallBacks *cb) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + int numConfigExtensions; + UINT usacConfigExtType; + int usacConfigExtLength; + int loudnessInfoSetIndex = + -1; /* index of loudnessInfoSet config extension. -1 if not contained. */ + int tmp_subStreamIndex = 0; + AUDIO_OBJECT_TYPE tmp_aot = AOT_USAC; + + numConfigExtensions = (int)escapedValue(hBs, 2, 4, 8) + 1; + for (int confExtIdx = 0; confExtIdx < numConfigExtensions; confExtIdx++) { + INT nbits; + int loudnessInfoSetConfigExtensionPosition = FDKgetValidBits(hBs); + usacConfigExtType = escapedValue(hBs, 4, 8, 16); + usacConfigExtLength = (int)escapedValue(hBs, 4, 8, 16); + + /* Start bit position of config extension */ + nbits = (INT)FDKgetValidBits(hBs); + + /* Return an error in case the bitbuffer fill level is too low. */ + if (nbits < usacConfigExtLength * 8) { + return TRANSPORTDEC_PARSE_ERROR; + } + + switch (usacConfigExtType) { + case ID_CONFIG_EXT_FILL: + for (int i = 0; i < usacConfigExtLength; i++) { + if (FDKreadBits(hBs, 8) != 0xa5) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + break; + case ID_CONFIG_EXT_LOUDNESS_INFO: { + if (cb->cbUniDrc != NULL) { + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc( + cb->cbUniDrcData, hBs, usacConfigExtLength, + 1, /* loudnessInfoSet */ + tmp_subStreamIndex, loudnessInfoSetConfigExtensionPosition, + tmp_aot); + if (ErrorStatus != TRANSPORTDEC_OK) { + return ErrorStatus; + } + loudnessInfoSetIndex = confExtIdx; + } + } break; + default: + break; + } + + /* Skip remaining bits. If too many bits were parsed, assume error. */ + usacConfigExtLength = + 8 * usacConfigExtLength - (nbits - (INT)FDKgetValidBits(hBs)); + if (usacConfigExtLength < 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + FDKpushFor(hBs, usacConfigExtLength); + } + + if (loudnessInfoSetIndex == -1 && cb->cbUniDrc != NULL) { + /* no loudnessInfoSet contained. Clear the loudnessInfoSet struct by feeding + * an empty config extension */ + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc( + cb->cbUniDrcData, NULL, 0, 1 /* loudnessInfoSet */, tmp_subStreamIndex, + 0, tmp_aot); + if (ErrorStatus != TRANSPORTDEC_OK) { + return ErrorStatus; + } + } + + return ErrorStatus; +} + +/* This function unifies decoder config parsing of USAC and RSV60: + rsv603daDecoderConfig() ISO/IEC DIS 23008-3 Table 8 + UsacDecoderConfig() ISO/IEC FDIS 23003-3 Table 6 + */ +static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse( + CSAudioSpecificConfig *asc, HANDLE_FDK_BITSTREAM hBs, + const CSTpCallBacks *cb) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + CSUsacConfig *usc = &asc->m_sc.m_usacConfig; + int i, numberOfElements; + int channelElementIdx = + 0; /* index for elements which contain audio channels (sce, cpe, lfe) */ + SC_CHANNEL_CONFIG sc_chan_config = {0, 0, 0, 0}; + int uniDrcElement = + -1; /* index of uniDrc extension element. -1 if not contained. */ + + numberOfElements = (int)escapedValue(hBs, 4, 8, 16) + 1; + usc->m_usacNumElements = numberOfElements; + if (numberOfElements > TP_USAC_MAX_ELEMENTS) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + usc->m_nUsacChannels = 0; + usc->m_channelConfigurationIndex = asc->m_channelConfiguration; + + if (asc->m_aot == AOT_USAC) { + sc_chan_config = sc_chan_config_tab[usc->m_channelConfigurationIndex]; + + if (sc_chan_config.nCh > (SCHAR)TP_USAC_MAX_SPEAKERS) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + + for (i = 0; i < numberOfElements; i++) { + MP4_ELEMENT_ID usacElementType = (MP4_ELEMENT_ID)( + FDKreadBits(hBs, 2) | USAC_ID_BIT); /* set USAC_ID_BIT to map + usacElementType to + MP4_ELEMENT_ID enum */ + usc->element[i].usacElementType = usacElementType; + + /* sanity check: update element counter */ + if (asc->m_aot == AOT_USAC) { + switch (usacElementType) { + case ID_USAC_SCE: + sc_chan_config.nSCE--; + break; + case ID_USAC_CPE: + sc_chan_config.nCPE--; + break; + case ID_USAC_LFE: + sc_chan_config.nLFE--; + break; + default: + break; + } + if (usc->m_channelConfigurationIndex) { + /* sanity check: no element counter may be smaller zero */ + if (sc_chan_config.nCPE < 0 || sc_chan_config.nSCE < 0 || + sc_chan_config.nLFE < 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + } + + switch (usacElementType) { + case ID_USAC_SCE: + /* UsacCoreConfig() ISO/IEC FDIS 23003-3 Table 10 */ + if (FDKreadBit(hBs)) { /* tw_mdct */ + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + usc->element[i].m_noiseFilling = FDKreadBits(hBs, 1); + /* end of UsacCoreConfig() */ + if (usc->m_sbrRatioIndex > 0) { + if (cb->cbSbr == NULL) { + return TRANSPORTDEC_UNKOWN_ERROR; + } + /* SbrConfig() ISO/IEC FDIS 23003-3 Table 11 */ + usc->element[i].m_harmonicSBR = FDKreadBit(hBs); + usc->element[i].m_interTes = FDKreadBit(hBs); + usc->element[i].m_pvc = FDKreadBit(hBs); + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, ID_SCE, + channelElementIdx, usc->element[i].m_harmonicSBR, + usc->element[i].m_stereoConfigIndex, asc->configMode, + &asc->SbrConfigChanged, 1)) { + return TRANSPORTDEC_PARSE_ERROR; + } + /* end of SbrConfig() */ + } + usc->m_nUsacChannels += 1; + channelElementIdx++; + break; + + case ID_USAC_CPE: + /* UsacCoreConfig() ISO/IEC FDIS 23003-3 Table 10 */ + if (FDKreadBit(hBs)) { /* tw_mdct */ + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + usc->element[i].m_noiseFilling = FDKreadBits(hBs, 1); + /* end of UsacCoreConfig() */ + if (usc->m_sbrRatioIndex > 0) { + if (cb->cbSbr == NULL) return TRANSPORTDEC_UNKOWN_ERROR; + /* SbrConfig() ISO/IEC FDIS 23003-3 */ + usc->element[i].m_harmonicSBR = FDKreadBit(hBs); + usc->element[i].m_interTes = FDKreadBit(hBs); + usc->element[i].m_pvc = FDKreadBit(hBs); + { + INT bitsToSkip = skipSbrHeader(hBs, 1); + /* read stereoConfigIndex */ + usc->element[i].m_stereoConfigIndex = FDKreadBits(hBs, 2); + /* rewind */ + FDKpushBack(hBs, bitsToSkip + 2); + } + { + MP4_ELEMENT_ID el_type = + (usc->element[i].m_stereoConfigIndex == 1 || + usc->element[i].m_stereoConfigIndex == 2) + ? ID_SCE + : ID_CPE; + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, el_type, + channelElementIdx, usc->element[i].m_harmonicSBR, + usc->element[i].m_stereoConfigIndex, asc->configMode, + &asc->SbrConfigChanged, 1)) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + /* end of SbrConfig() */ + + usc->element[i].m_stereoConfigIndex = + FDKreadBits(hBs, 2); /* Needed in RM5 syntax */ + + if (usc->element[i].m_stereoConfigIndex > 0) { + if (cb->cbSsc != NULL) { + int samplesPerFrame = asc->m_samplesPerFrame; + + if (usc->m_sbrRatioIndex == 1) samplesPerFrame <<= 2; + if (usc->m_sbrRatioIndex == 2) + samplesPerFrame = (samplesPerFrame * 8) / 3; + if (usc->m_sbrRatioIndex == 3) samplesPerFrame <<= 1; + + /* Mps212Config() ISO/IEC FDIS 23003-3 */ + if (cb->cbSsc(cb->cbSscData, hBs, asc->m_aot, + asc->m_extensionSamplingFrequency, samplesPerFrame, + 1, /* only downmix channels (residual channels are + not counted) */ + usc->element[i].m_stereoConfigIndex, + usc->m_coreSbrFrameLengthIndex, + 0, /* don't know the length */ + asc->configMode, &asc->SacConfigChanged)) { + return TRANSPORTDEC_PARSE_ERROR; + } + /* end of Mps212Config() */ + } else { + return TRANSPORTDEC_UNKOWN_ERROR; + } + } + } else { + usc->element[i].m_stereoConfigIndex = 0; + } + usc->m_nUsacChannels += 2; + + channelElementIdx++; + break; + + case ID_USAC_LFE: + usc->element[i].m_noiseFilling = 0; + usc->m_nUsacChannels += 1; + if (usc->m_sbrRatioIndex > 0) { + /* Use SBR for upsampling */ + if (cb->cbSbr == NULL) return ErrorStatus = TRANSPORTDEC_UNKOWN_ERROR; + usc->element[i].m_harmonicSBR = (UCHAR)0; + usc->element[i].m_interTes = (UCHAR)0; + usc->element[i].m_pvc = (UCHAR)0; + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, ID_LFE, + channelElementIdx, usc->element[i].m_harmonicSBR, + usc->element[i].m_stereoConfigIndex, asc->configMode, + &asc->SbrConfigChanged, 1)) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + } + channelElementIdx++; + break; + + case ID_USAC_EXT: + ErrorStatus = extElementConfig(&usc->element[i].extElement, hBs, cb, 0, + asc->m_samplesPerFrame, 0, asc->m_aot); + if (usc->element[i].extElement.usacExtElementType == + ID_EXT_ELE_UNI_DRC) { + uniDrcElement = i; + } + + if (ErrorStatus) { + return ErrorStatus; + } + break; + + default: + /* non USAC-element encountered */ + return TRANSPORTDEC_PARSE_ERROR; + } + } + + if (asc->m_aot == AOT_USAC) { + if (usc->m_channelConfigurationIndex) { + /* sanity check: all element counter must be zero */ + if (sc_chan_config.nCPE | sc_chan_config.nSCE | sc_chan_config.nLFE) { + return TRANSPORTDEC_PARSE_ERROR; + } + } else { + /* sanity check: number of audio channels shall be equal to or smaller + * than the accumulated sum of all channels */ + if ((INT)(-2 * sc_chan_config.nCPE - sc_chan_config.nSCE - + sc_chan_config.nLFE) < (INT)usc->numAudioChannels) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + } + + if (uniDrcElement == -1 && cb->cbUniDrc != NULL) { + /* no uniDrcConfig contained. Clear the uniDrcConfig struct by feeding an + * empty extension element */ + int subStreamIndex = 0; + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc( + cb->cbUniDrcData, NULL, 0, 0 /* uniDrcConfig */, subStreamIndex, 0, + asc->m_aot); + if (ErrorStatus != TRANSPORTDEC_OK) { + return ErrorStatus; + } + } + + return ErrorStatus; +} + +/* Mapping of coreSbrFrameLengthIndex defined by Table 70 in ISO/IEC 23003-3 */ +static TRANSPORTDEC_ERROR UsacConfig_SetCoreSbrFrameLengthIndex( + CSAudioSpecificConfig *asc, int coreSbrFrameLengthIndex) { + int sbrRatioIndex_val; + + if (coreSbrFrameLengthIndex > 4) { + return TRANSPORTDEC_PARSE_ERROR; /* reserved values */ + } + asc->m_sc.m_usacConfig.m_coreSbrFrameLengthIndex = coreSbrFrameLengthIndex; + asc->m_samplesPerFrame = usacFrameLength[coreSbrFrameLengthIndex]; + sbrRatioIndex_val = sbrRatioIndex[coreSbrFrameLengthIndex]; + asc->m_sc.m_usacConfig.m_sbrRatioIndex = sbrRatioIndex_val; + + if (sbrRatioIndex_val > 0) { + asc->m_sbrPresentFlag = 1; + asc->m_extensionSamplingFrequency = asc->m_samplingFrequency; + asc->m_extensionSamplingFrequencyIndex = asc->m_samplingFrequencyIndex; + switch (sbrRatioIndex_val) { + case 1: /* sbrRatio = 4:1 */ + asc->m_samplingFrequency >>= 2; + asc->m_samplesPerFrame >>= 2; + break; + case 2: /* sbrRatio = 8:3 */ + asc->m_samplingFrequency = (asc->m_samplingFrequency * 3) / 8; + asc->m_samplesPerFrame = (asc->m_samplesPerFrame * 3) / 8; + break; + case 3: /* sbrRatio = 2:1 */ + asc->m_samplingFrequency >>= 1; + asc->m_samplesPerFrame >>= 1; + break; + default: + return TRANSPORTDEC_PARSE_ERROR; + } + asc->m_samplingFrequencyIndex = + getSamplingRateIndex(asc->m_samplingFrequency, 4); + } + + return TRANSPORTDEC_OK; +} + +static TRANSPORTDEC_ERROR UsacConfig_Parse(CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb) { + int usacSamplingFrequency, channelConfigurationIndex, coreSbrFrameLengthIndex; + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + /* Start bit position of usacConfig */ + INT nbits = (INT)FDKgetValidBits(hBs); + + usacSamplingFrequency = getSampleRate(hBs, &asc->m_samplingFrequencyIndex, 5); + if (usacSamplingFrequency == 0 || usacSamplingFrequency > 96000) { + return TRANSPORTDEC_PARSE_ERROR; + } + asc->m_samplingFrequency = (UINT)usacSamplingFrequency; + + coreSbrFrameLengthIndex = FDKreadBits(hBs, 3); + if (UsacConfig_SetCoreSbrFrameLengthIndex(asc, coreSbrFrameLengthIndex) != + TRANSPORTDEC_OK) { + return TRANSPORTDEC_PARSE_ERROR; + } + + channelConfigurationIndex = FDKreadBits(hBs, 5); + if (channelConfigurationIndex > 2) { + return TRANSPORTDEC_PARSE_ERROR; /* only channelConfigurationIndex = [1,2] + are supported */ + } + + if (channelConfigurationIndex == 0) { + return TRANSPORTDEC_PARSE_ERROR; /* only channelConfigurationIndex = [1,2] + are supported */ + } + asc->m_channelConfiguration = channelConfigurationIndex; + + err = UsacRsv60DecoderConfig_Parse(asc, hBs, cb); + if (err != TRANSPORTDEC_OK) { + return err; + } + + if (FDKreadBits(hBs, 1)) { /* usacConfigExtensionPresent */ + err = configExtension(&asc->m_sc.m_usacConfig, hBs, cb); + if (err != TRANSPORTDEC_OK) { + return err; + } + } else if (cb->cbUniDrc != NULL) { + /* no loudnessInfoSet contained. Clear the loudnessInfoSet struct by feeding + * an empty config extension */ + err = (TRANSPORTDEC_ERROR)cb->cbUniDrc( + cb->cbUniDrcData, NULL, 0, 1 /* loudnessInfoSet */, 0, 0, asc->m_aot); + if (err != TRANSPORTDEC_OK) { + return err; + } + } + + /* sanity check whether number of channels signaled in UsacDecoderConfig() + matches the number of channels required by channelConfigurationIndex */ + if ((channelConfigurationIndex > 0) && + (sc_chan_config_tab[channelConfigurationIndex].nCh != + asc->m_sc.m_usacConfig.m_nUsacChannels)) { + return TRANSPORTDEC_PARSE_ERROR; + } + + /* Copy UsacConfig() to asc->m_sc.m_usacConfig.UsacConfig[] buffer. */ + INT configSize_bits = (INT)FDKgetValidBits(hBs) - nbits; + if (StoreConfigAsBitstream(hBs, configSize_bits, + asc->m_sc.m_usacConfig.UsacConfig, + TP_USAC_MAX_CONFIG_LEN)) { + return TRANSPORTDEC_PARSE_ERROR; + } + asc->m_sc.m_usacConfig.UsacConfigBits = fAbs(configSize_bits); + + return err; +} + +static TRANSPORTDEC_ERROR AudioSpecificConfig_ExtensionParse( + CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, CSTpCallBacks *cb) { + TP_ASC_EXTENSION_ID lastAscExt, ascExtId = ASCEXT_UNKOWN; + INT bitsAvailable = (INT)FDKgetValidBits(bs); + + while (bitsAvailable >= 11) { + lastAscExt = ascExtId; + ascExtId = (TP_ASC_EXTENSION_ID)FDKreadBits(bs, 11); + bitsAvailable -= 11; + + switch (ascExtId) { + case ASCEXT_SBR: /* 0x2b7 */ + if ((self->m_extensionAudioObjectType != AOT_SBR) && + (bitsAvailable >= 5)) { + self->m_extensionAudioObjectType = getAOT(bs); + + if ((self->m_extensionAudioObjectType == AOT_SBR) || + (self->m_extensionAudioObjectType == + AOT_ER_BSAC)) { /* Get SBR extension configuration */ + self->m_sbrPresentFlag = FDKreadBits(bs, 1); + if (self->m_aot == AOT_USAC && self->m_sbrPresentFlag > 0 && + self->m_sc.m_usacConfig.m_sbrRatioIndex == 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + + if (self->m_sbrPresentFlag == 1) { + self->m_extensionSamplingFrequency = getSampleRate( + bs, &self->m_extensionSamplingFrequencyIndex, 4); + + if (self->m_extensionSamplingFrequency == 0 || + self->m_extensionSamplingFrequency > 96000) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + if (self->m_extensionAudioObjectType == AOT_ER_BSAC) { + self->m_extensionChannelConfiguration = FDKreadBits(bs, 4); + } + } + /* Update counter because of variable length fields (AOT and sampling + * rate) */ + bitsAvailable = (INT)FDKgetValidBits(bs); + } + break; + case ASCEXT_PS: /* 0x548 */ + if ((lastAscExt == ASCEXT_SBR) && + (self->m_extensionAudioObjectType == AOT_SBR) && + (bitsAvailable > 0)) { /* Get PS extension configuration */ + self->m_psPresentFlag = FDKreadBits(bs, 1); + bitsAvailable -= 1; + } + break; + case ASCEXT_MPS: /* 0x76a */ + if (self->m_extensionAudioObjectType == AOT_MPEGS) break; + FDK_FALLTHROUGH; + case ASCEXT_LDMPS: /* 0x7cc */ + if ((ascExtId == ASCEXT_LDMPS) && + (self->m_extensionAudioObjectType == AOT_LD_MPEGS)) + break; + if (bitsAvailable >= 1) { + bitsAvailable -= 1; + if (FDKreadBits(bs, 1)) { /* self->m_mpsPresentFlag */ + int sscLen = FDKreadBits(bs, 8); + bitsAvailable -= 8; + if (sscLen == 0xFF) { + sscLen += FDKreadBits(bs, 16); + bitsAvailable -= 16; + } + FDKpushFor(bs, sscLen); /* Skip SSC to be able to read the next + extension if there is one. */ + + bitsAvailable -= sscLen * 8; + } + } + break; + case ASCEXT_SAOC: + if ((ascExtId == ASCEXT_SAOC) && + (self->m_extensionAudioObjectType == AOT_SAOC)) + break; + if (FDKreadBits(bs, 1)) { /* saocPresent */ + int saocscLen = FDKreadBits(bs, 8); + bitsAvailable -= 8; + if (saocscLen == 0xFF) { + saocscLen += FDKreadBits(bs, 16); + bitsAvailable -= 16; + } + FDKpushFor(bs, saocscLen); + bitsAvailable -= saocscLen * 8; + } + break; + default: + /* Just ignore anything. */ + return TRANSPORTDEC_OK; + } + } + + return TRANSPORTDEC_OK; +} + +/* + * API Functions + */ + +void AudioSpecificConfig_Init(CSAudioSpecificConfig *asc) { + FDKmemclear(asc, sizeof(CSAudioSpecificConfig)); + + /* Init all values that should not be zero. */ + asc->m_aot = AOT_NONE; + asc->m_samplingFrequencyIndex = 0xf; + asc->m_epConfig = -1; + asc->m_extensionAudioObjectType = AOT_NULL_OBJECT; + CProgramConfig_Init(&asc->m_progrConfigElement); +} + +TRANSPORTDEC_ERROR AudioSpecificConfig_Parse( + CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, + int fExplicitBackwardCompatible, CSTpCallBacks *cb, UCHAR configMode, + UCHAR configChanged, AUDIO_OBJECT_TYPE m_aot) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + UINT ascStartAnchor = FDKgetValidBits(bs); + int frameLengthFlag = -1; + + AudioSpecificConfig_Init(self); + + self->configMode = configMode; + self->AacConfigChanged = configChanged; + self->SbrConfigChanged = configChanged; + self->SacConfigChanged = configChanged; + + if (m_aot != AOT_NULL_OBJECT) { + self->m_aot = m_aot; + } else { + self->m_aot = getAOT(bs); + self->m_samplingFrequency = + getSampleRate(bs, &self->m_samplingFrequencyIndex, 4); + if (self->m_samplingFrequency <= 0 || + (self->m_samplingFrequency > 96000 && self->m_aot != 39) || + self->m_samplingFrequency > 4 * 96000) { + return TRANSPORTDEC_PARSE_ERROR; + } + + self->m_channelConfiguration = FDKreadBits(bs, 4); + + /* MPEG-04 standard ISO/IEC 14496-3: channelConfiguration == 0 is reserved + in er_raw_data_block (table 4.19) and er_raw_data_block_eld (table 4.75) + MPEG-04 conformance ISO/IEC 14496-4: channelConfiguration == 0 is not + permitted for AOT_ER_AAC_LC, AOT_ER_AAC_LTP, AOT_ER_AAC_LD, + AOT_ER_AAC_SCAL (chapter 6.6.4.1.2.1.1) */ + if ((self->m_channelConfiguration == 0) && + ((self->m_aot == AOT_ER_AAC_LC) || (self->m_aot == AOT_ER_AAC_LTP) || + (self->m_aot == AOT_ER_AAC_LD) || (self->m_aot == AOT_ER_AAC_SCAL) || + (self->m_aot == AOT_ER_AAC_ELD))) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + /* MPEG-04 conformance ISO/IEC 14496-4: channelConfiguration > 2 is not + * permitted for AOT_AAC_SCAL and AOT_ER_AAC_SCAL (chapter 6.6.4.1.2.1.1) */ + if ((self->m_channelConfiguration > 2) && + ((self->m_aot == AOT_AAC_SCAL) || (self->m_aot == AOT_ER_AAC_SCAL))) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + /* SBR extension ( explicit non-backwards compatible mode ) */ + self->m_sbrPresentFlag = 0; + self->m_psPresentFlag = 0; + + if (self->m_aot == AOT_SBR || self->m_aot == AOT_PS) { + self->m_extensionAudioObjectType = AOT_SBR; + + self->m_sbrPresentFlag = 1; + if (self->m_aot == AOT_PS) { + self->m_psPresentFlag = 1; + } + + self->m_extensionSamplingFrequency = + getSampleRate(bs, &self->m_extensionSamplingFrequencyIndex, 4); + if (self->m_extensionSamplingFrequency == 0 || + self->m_extensionSamplingFrequency > 96000) { + return TRANSPORTDEC_PARSE_ERROR; + } + self->m_aot = getAOT(bs); + + switch (self->m_aot) { + case AOT_AAC_LC: + break; + case AOT_ER_BSAC: + break; + default: + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + if (self->m_aot == AOT_ER_BSAC) { + self->m_extensionChannelConfiguration = FDKreadBits(bs, 4); + } + } else { + self->m_extensionAudioObjectType = AOT_NULL_OBJECT; + } + } + + /* Parse whatever specific configs */ + switch (self->m_aot) { + case AOT_AAC_LC: + case AOT_AAC_SCAL: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_SCAL: + case AOT_ER_BSAC: + if ((ErrorStatus = GaSpecificConfig_Parse(&self->m_sc.m_gaSpecificConfig, + self, bs, ascStartAnchor)) != + TRANSPORTDEC_OK) { + return (ErrorStatus); + } + frameLengthFlag = self->m_sc.m_gaSpecificConfig.m_frameLengthFlag; + break; + case AOT_MPEGS: + if (cb->cbSsc != NULL) { + if (cb->cbSsc(cb->cbSscData, bs, self->m_aot, self->m_samplingFrequency, + self->m_samplesPerFrame, self->m_channelConfiguration, 1, + -1, /* nTimeSlots: read from bitstream */ + 0, /* don't know the length */ + self->configMode, &self->SacConfigChanged)) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + } else { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + break; + case AOT_ER_AAC_ELD: + if ((ErrorStatus = EldSpecificConfig_Parse(self, bs, cb)) != + TRANSPORTDEC_OK) { + return (ErrorStatus); + } + frameLengthFlag = self->m_sc.m_eldSpecificConfig.m_frameLengthFlag; + self->m_sbrPresentFlag = self->m_sc.m_eldSpecificConfig.m_sbrPresentFlag; + self->m_extensionSamplingFrequency = + (self->m_sc.m_eldSpecificConfig.m_sbrSamplingRate + 1) * + self->m_samplingFrequency; + break; + case AOT_USAC: + if ((ErrorStatus = UsacConfig_Parse(self, bs, cb)) != TRANSPORTDEC_OK) { + return (ErrorStatus); + } + break; + + default: + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + /* Frame length */ + switch (self->m_aot) { + case AOT_AAC_LC: + case AOT_AAC_SCAL: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_SCAL: + case AOT_ER_BSAC: + /*case AOT_USAC:*/ + if (!frameLengthFlag) + self->m_samplesPerFrame = 1024; + else + self->m_samplesPerFrame = 960; + break; + case AOT_ER_AAC_LD: + if (!frameLengthFlag) + self->m_samplesPerFrame = 512; + else + self->m_samplesPerFrame = 480; + break; + default: + break; + } + + switch (self->m_aot) { + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + case AOT_ER_AAC_SCAL: + case AOT_ER_CELP: + case AOT_ER_HVXC: + case AOT_ER_BSAC: + self->m_epConfig = FDKreadBits(bs, 2); + + if (self->m_epConfig > 1) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; // EPCONFIG; + } + break; + default: + break; + } + + if (fExplicitBackwardCompatible && + (self->m_aot == AOT_AAC_LC || self->m_aot == AOT_ER_AAC_LD || + self->m_aot == AOT_ER_BSAC)) { + ErrorStatus = AudioSpecificConfig_ExtensionParse(self, bs, cb); + } + + /* Copy config() to asc->config[] buffer. */ + if ((ErrorStatus == TRANSPORTDEC_OK) && (self->m_aot == AOT_USAC)) { + INT configSize_bits = (INT)FDKgetValidBits(bs) - (INT)ascStartAnchor; + if (StoreConfigAsBitstream(bs, configSize_bits, self->config, + TP_USAC_MAX_CONFIG_LEN)) { + return TRANSPORTDEC_PARSE_ERROR; + } + self->configBits = fAbs(configSize_bits); + } + + return (ErrorStatus); +} + +static TRANSPORTDEC_ERROR Drm_xHEAACDecoderConfig( + CSAudioSpecificConfig *asc, HANDLE_FDK_BITSTREAM hBs, int audioMode, + CSTpCallBacks *cb /* use cb == NULL to signal config check only mode */ +) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + CSUsacConfig *usc = &asc->m_sc.m_usacConfig; + int elemIdx = 0; + + usc->element[elemIdx].m_stereoConfigIndex = 0; + + usc->m_usacNumElements = 1; /* Currently all extension elements are skipped + -> only one SCE or CPE. */ + + switch (audioMode) { + case 0: /* mono: ID_USAC_SCE */ + usc->element[elemIdx].usacElementType = ID_USAC_SCE; + usc->m_nUsacChannels = 1; + usc->element[elemIdx].m_noiseFilling = FDKreadBits(hBs, 1); + if (usc->m_sbrRatioIndex > 0) { + if (cb == NULL) { + return ErrorStatus; + } + if (cb->cbSbr != NULL) { + usc->element[elemIdx].m_harmonicSBR = FDKreadBit(hBs); + usc->element[elemIdx].m_interTes = FDKreadBit(hBs); + usc->element[elemIdx].m_pvc = FDKreadBit(hBs); + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, ID_SCE, elemIdx, + usc->element[elemIdx].m_harmonicSBR, + usc->element[elemIdx].m_stereoConfigIndex, + asc->configMode, &asc->SbrConfigChanged, 1)) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + } + } + break; + case 2: /* stereo: ID_USAC_CPE */ + usc->element[elemIdx].usacElementType = ID_USAC_CPE; + usc->m_nUsacChannels = 2; + usc->element[elemIdx].m_noiseFilling = FDKreadBits(hBs, 1); + if (usc->m_sbrRatioIndex > 0) { + usc->element[elemIdx].m_harmonicSBR = FDKreadBit(hBs); + usc->element[elemIdx].m_interTes = FDKreadBit(hBs); + usc->element[elemIdx].m_pvc = FDKreadBit(hBs); + { + INT bitsToSkip = skipSbrHeader(hBs, 1); + /* read stereoConfigIndex */ + usc->element[elemIdx].m_stereoConfigIndex = FDKreadBits(hBs, 2); + /* rewind */ + FDKpushBack(hBs, bitsToSkip + 2); + } + /* + The application of the following tools is mutually exclusive per audio + stream configuration (see clause 5.3.2, xHE-AAC codec configuration): + - MPS212 parametric stereo tool with residual coding + (stereoConfigIndex>1); and + - QMF based Harmonic Transposer (harmonicSBR==1). + */ + if ((usc->element[elemIdx].m_stereoConfigIndex > 1) && + usc->element[elemIdx].m_harmonicSBR) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + /* + The 4:1 sbrRatio (sbrRatioIndex==1 in [11]) may only be employed: + - in mono operation; or + - in stereo operation if parametric stereo (MPS212) without residual + coding is applied, i.e. if stereoConfigIndex==1 (see clause 5.3.2, + xHE-AAC codec configuration). + */ + if ((usc->m_sbrRatioIndex == 1) && + (usc->element[elemIdx].m_stereoConfigIndex != 1)) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + if (cb == NULL) { + return ErrorStatus; + } + { + MP4_ELEMENT_ID el_type = + (usc->element[elemIdx].m_stereoConfigIndex == 1 || + usc->element[elemIdx].m_stereoConfigIndex == 2) + ? ID_SCE + : ID_CPE; + if (cb->cbSbr == NULL) return ErrorStatus = TRANSPORTDEC_UNKOWN_ERROR; + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, el_type, elemIdx, + usc->element[elemIdx].m_harmonicSBR, + usc->element[elemIdx].m_stereoConfigIndex, + asc->configMode, &asc->SbrConfigChanged, 1)) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + } + /*usc->element[elemIdx].m_stereoConfigIndex =*/FDKreadBits(hBs, 2); + if (usc->element[elemIdx].m_stereoConfigIndex > 0) { + if (cb->cbSsc != NULL) { + int samplesPerFrame = asc->m_samplesPerFrame; + + if (usc->m_sbrRatioIndex == 1) samplesPerFrame <<= 2; + if (usc->m_sbrRatioIndex == 2) + samplesPerFrame = (samplesPerFrame * 8) / 3; + if (usc->m_sbrRatioIndex == 3) samplesPerFrame <<= 1; + + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbSsc( + cb->cbSscData, hBs, + AOT_DRM_USAC, /* syntax differs from MPEG Mps212Config() */ + asc->m_extensionSamplingFrequency, samplesPerFrame, + 1, /* only downmix channels (residual channels are not + counted) */ + usc->element[elemIdx].m_stereoConfigIndex, + usc->m_coreSbrFrameLengthIndex, 0, /* don't know the length */ + asc->configMode, &asc->SacConfigChanged); + } else { + /* ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; */ + } + } + } + break; + default: + return TRANSPORTDEC_PARSE_ERROR; + } + + return ErrorStatus; +} + +TRANSPORTDEC_ERROR Drm_xHEAACStaticConfig( + CSAudioSpecificConfig *asc, HANDLE_FDK_BITSTREAM bs, int audioMode, + CSTpCallBacks *cb /* use cb == NULL to signal config check only mode */ +) { + int coreSbrFrameLengthIndexDrm = FDKreadBits(bs, 2); + if (UsacConfig_SetCoreSbrFrameLengthIndex( + asc, coreSbrFrameLengthIndexDrm + 1) != TRANSPORTDEC_OK) { + return TRANSPORTDEC_PARSE_ERROR; + } + + asc->m_channelConfiguration = (audioMode) ? 2 : 1; + + if (Drm_xHEAACDecoderConfig(asc, bs, audioMode, cb) != TRANSPORTDEC_OK) { + return TRANSPORTDEC_PARSE_ERROR; + } + + return TRANSPORTDEC_OK; +} + +/* Mapping of DRM audio sampling rate field to MPEG usacSamplingFrequencyIndex + */ +const UCHAR mapSr2MPEGIdx[8] = { + 0x1b, /* 9.6 kHz */ + 0x09, /* 12.0 kHz */ + 0x08, /* 16.0 kHz */ + 0x17, /* 19.2 kHz */ + 0x06, /* 24.0 kHz */ + 0x05, /* 32.0 kHz */ + 0x12, /* 38.4 kHz */ + 0x03 /* 48.0 kHz */ +}; + +TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( + CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, + CSTpCallBacks *cb, /* use cb == NULL to signal config check only mode */ + UCHAR configMode, UCHAR configChanged) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + AudioSpecificConfig_Init(self); + + if ((INT)FDKgetValidBits(bs) < 16) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } else { + /* DRM - Audio information data entity - type 9 + - Short Id 2 bits (not part of the config buffer) + - Stream Id 2 bits (not part of the config buffer) + - audio coding 2 bits + - SBR flag 1 bit + - audio mode 2 bits + - audio sampling rate 3 bits + - text flag 1 bit + - enhancement flag 1 bit + - coder field 5 bits + - rfa 1 bit */ + + int audioCoding, audioMode, cSamplingFreq, coderField, sfIdx, sbrFlag; + + self->configMode = configMode; + self->AacConfigChanged = configChanged; + self->SbrConfigChanged = configChanged; + self->SacConfigChanged = configChanged; + + /* Read the SDC field */ + audioCoding = FDKreadBits(bs, 2); + sbrFlag = FDKreadBits(bs, 1); + audioMode = FDKreadBits(bs, 2); + cSamplingFreq = FDKreadBits(bs, 3); /* audio sampling rate */ + + FDKreadBits(bs, 2); /* Text and enhancement flag */ + coderField = FDKreadBits(bs, 5); + FDKreadBits(bs, 1); /* rfa */ + + /* Evaluate configuration and fill the ASC */ + if (audioCoding == 3) { + sfIdx = (int)mapSr2MPEGIdx[cSamplingFreq]; + sbrFlag = 0; /* rfa */ + } else { + switch (cSamplingFreq) { + case 0: /* 8 kHz */ + sfIdx = 11; + break; + case 1: /* 12 kHz */ + sfIdx = 9; + break; + case 2: /* 16 kHz */ + sfIdx = 8; + break; + case 3: /* 24 kHz */ + sfIdx = 6; + break; + case 5: /* 48 kHz */ + sfIdx = 3; + break; + case 4: /* reserved */ + case 6: /* reserved */ + case 7: /* reserved */ + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + + self->m_samplingFrequencyIndex = sfIdx; + self->m_samplingFrequency = SamplingRateTable[sfIdx]; + + if (sbrFlag) { + UINT i; + int tmp = -1; + self->m_sbrPresentFlag = 1; + self->m_extensionAudioObjectType = AOT_SBR; + self->m_extensionSamplingFrequency = self->m_samplingFrequency << 1; + for (i = 0; + i < (sizeof(SamplingRateTable) / sizeof(SamplingRateTable[0])); + i++) { + if (SamplingRateTable[i] == self->m_extensionSamplingFrequency) { + tmp = i; + break; + } + } + self->m_extensionSamplingFrequencyIndex = tmp; + } + + switch (audioCoding) { + case 0: /* AAC */ + if ((coderField >> 2) && (audioMode != 1)) { + self->m_aot = AOT_DRM_SURROUND; /* Set pseudo AOT for Drm Surround */ + } else { + self->m_aot = AOT_DRM_AAC; /* Set pseudo AOT for Drm AAC */ + } + switch (audioMode) { + case 1: /* parametric stereo */ + self->m_psPresentFlag = 1; + FDK_FALLTHROUGH; + case 0: /* mono */ + self->m_channelConfiguration = 1; + break; + case 2: /* stereo */ + self->m_channelConfiguration = 2; + break; + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + self->m_vcb11Flag = 1; + self->m_hcrFlag = 1; + self->m_samplesPerFrame = 960; + self->m_epConfig = 1; + break; + case 1: /* CELP */ + self->m_aot = AOT_ER_CELP; + self->m_channelConfiguration = 1; + break; + case 2: /* HVXC */ + self->m_aot = AOT_ER_HVXC; + self->m_channelConfiguration = 1; + break; + case 3: /* xHE-AAC */ + { + /* payload is MPEG conform -> no pseudo DRM AOT needed */ + self->m_aot = AOT_USAC; + } + switch (audioMode) { + case 0: /* mono */ + case 2: /* stereo */ + /* codec specific config 8n bits */ + ErrorStatus = Drm_xHEAACStaticConfig(self, bs, audioMode, cb); + break; + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + break; + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + self->m_aot = AOT_NONE; + break; + } + + if (self->m_psPresentFlag && !self->m_sbrPresentFlag) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + +bail: + return (ErrorStatus); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_drm.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_drm.cpp new file mode 100644 index 0000000000000..27c1c1d03a0ed --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_drm.cpp @@ -0,0 +1,148 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Christian Griebel + + Description: DRM transport stuff + +*******************************************************************************/ + +#include "tpdec_drm.h" + +#include "FDK_bitstream.h" + +void drmRead_CrcInit(HANDLE_DRM pDrm) /*!< pointer to drm crc info stucture */ +{ + FDK_ASSERT(pDrm != NULL); + + FDKcrcInit(&pDrm->crcInfo, 0x001d, 0xFFFF, 8); +} + +int drmRead_CrcStartReg( + HANDLE_DRM pDrm, /*!< pointer to drm stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ +) { + FDK_ASSERT(pDrm != NULL); + + FDKcrcReset(&pDrm->crcInfo); + + pDrm->crcReadValue = FDKreadBits(hBs, 8); + + return (FDKcrcStartReg(&pDrm->crcInfo, hBs, mBits)); +} + +void drmRead_CrcEndReg( + HANDLE_DRM pDrm, /*!< pointer to drm crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ +) { + FDK_ASSERT(pDrm != NULL); + + FDKcrcEndReg(&pDrm->crcInfo, hBs, reg); +} + +TRANSPORTDEC_ERROR drmRead_CrcCheck(HANDLE_DRM pDrm) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + USHORT crc; + + crc = FDKcrcGetCRC(&pDrm->crcInfo) ^ 0xFF; + if (crc != pDrm->crcReadValue) { + return (TRANSPORTDEC_CRC_ERROR); + } + + return (ErrorStatus); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_drm.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_drm.h new file mode 100644 index 0000000000000..09822dc24b018 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_drm.h @@ -0,0 +1,202 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Josef Hoepfl + + Description: DRM interface + +*******************************************************************************/ + +#ifndef TPDEC_DRM_H +#define TPDEC_DRM_H + +#include "tpdec_lib.h" + +#include "FDK_crc.h" + +typedef struct { + FDK_CRCINFO crcInfo; /* CRC state info */ + USHORT crcReadValue; /* CRC value read from bitstream data */ + +} STRUCT_DRM; + +typedef STRUCT_DRM *HANDLE_DRM; + +/*! + \brief Initialize DRM CRC + + The function initialzes the crc buffer and the crc lookup table. + + \return none +*/ +void drmRead_CrcInit(HANDLE_DRM pDrm); + +/** + * \brief Starts CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if + * there are less than mBits bits available. If mBits is negative no zero + * padding is done. If mBits is zero the memory for the buffer is + * allocated dynamically, the number of bits is not limited. + * + * \param pDrm DRM data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param mBits max number of bits in crc region to be considered + * + * \return ID for the created region, -1 in case of an error + */ +int drmRead_CrcStartReg(HANDLE_DRM pDrm, HANDLE_FDK_BITSTREAM hBs, int mBits); + +/** + * \brief Ends CRC region identified by reg + * + * \param pDrm DRM data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param reg CRC regions ID returned by drmRead_CrcStartReg() + * + * \return none + */ +void drmRead_CrcEndReg(HANDLE_DRM pDrm, HANDLE_FDK_BITSTREAM hBs, int reg); + +/** + * \brief Check CRC + * + * Checks if the currently calculated CRC matches the CRC field read from the + * bitstream Deletes all CRC regions. + * + * \param pDrm DRM data handle + * + * \return Returns 0 if they are identical otherwise 1 + */ +TRANSPORTDEC_ERROR drmRead_CrcCheck(HANDLE_DRM pDrm); + +/** + * \brief Check if we have a valid DRM frame at the current bitbuffer position + * + * This function assumes enough bits in buffer for the current frame. + * It reads out the header bits to prepare the bitbuffer for the decode loop. + * In case the header bits show an invalid bitstream/frame, the whole frame is + * skipped. + * + * \param pDrm DRM data handle which is filled with parsed DRM header data + * \param bs handle of bitstream from whom the DRM header is read + * + * \return error status + */ +TRANSPORTDEC_ERROR drmRead_DecodeHeader(HANDLE_DRM pDrm, + HANDLE_FDK_BITSTREAM bs); + +/** + * \brief Parse a Drm specific SDC audio config from a given bitstream handle. + * + * \param pAsc A pointer to an allocated + * CSAudioSpecificConfig struct. + * \param hBs Bitstream handle. + * \param cb A pointer to structure holding callback + * information Note: A NULL pointer for cb can be used to signal a "Check Config + * only functionality" + * \param configMode Config modes: memory allocation mode or + * config change detection mode + * \param configChanged Indicates a config change + * + * \return Total element count including all SCE, CPE and LFE. + */ +TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse(CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb, + const UCHAR configMode, + const UCHAR configChanged); + +#endif /* TPDEC_DRM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_latm.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_latm.cpp new file mode 100644 index 0000000000000..c32be54a9251b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_latm.cpp @@ -0,0 +1,677 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Daniel Homm + + Description: + +*******************************************************************************/ + +#include "tpdec_latm.h" + +#include "FDK_bitstream.h" + +#define TPDEC_TRACKINDEX(p, l) (1 * (p) + (l)) + +static UINT CLatmDemux_GetValue(HANDLE_FDK_BITSTREAM bs) { + UCHAR bytesForValue = 0, tmp = 0; + int value = 0; + + bytesForValue = (UCHAR)FDKreadBits(bs, 2); + + for (UINT i = 0; i <= bytesForValue; i++) { + value <<= 8; + tmp = (UCHAR)FDKreadBits(bs, 8); + value += tmp; + } + + return value; +} + +static TRANSPORTDEC_ERROR CLatmDemux_ReadAudioMuxElement( + HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux, int m_muxConfigPresent, + CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc, + int *pfConfigFound) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + if (m_muxConfigPresent) { + pLatmDemux->m_useSameStreamMux = FDKreadBits(bs, 1); + + if (!pLatmDemux->m_useSameStreamMux) { + int i; + UCHAR configChanged = 0; + UCHAR configMode = 0; + + FDK_BITSTREAM bsAnchor; + + FDK_BITSTREAM bsAnchorDummyParse; + + if (!pLatmDemux->applyAsc) { + bsAnchorDummyParse = *bs; + pLatmDemux->newCfgHasAudioPreRoll = 0; + /* do dummy-parsing of ASC to determine if there is an audioPreRoll */ + configMode |= AC_CM_DET_CFG_CHANGE; + if (TRANSPORTDEC_OK != + (ErrorStatus = CLatmDemux_ReadStreamMuxConfig( + bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound, + configMode, configChanged))) { + goto bail; + } + + /* Allow flushing only when audioPreroll functionality is enabled in + * current and new config otherwise the new config can be applied + * immediately. */ + if (pAsc->m_sc.m_usacConfig.element[0] + .extElement.usacExtElementHasAudioPreRoll && + pLatmDemux->newCfgHasAudioPreRoll) { + pLatmDemux->newCfgHasAudioPreRoll = 0; + /* with audioPreRoll we must flush before applying new cfg */ + pLatmDemux->applyAsc = 0; + } else { + *bs = bsAnchorDummyParse; + pLatmDemux->applyAsc = 1; /* apply new config immediate */ + } + } + + if (pLatmDemux->applyAsc) { + for (i = 0; i < 2; i++) { + configMode = 0; + + if (i == 0) { + configMode |= AC_CM_DET_CFG_CHANGE; + bsAnchor = *bs; + } else { + configMode |= AC_CM_ALLOC_MEM; + *bs = bsAnchor; + } + + if (TRANSPORTDEC_OK != + (ErrorStatus = CLatmDemux_ReadStreamMuxConfig( + bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound, + configMode, configChanged))) { + goto bail; + } + + if (ErrorStatus == TRANSPORTDEC_OK) { + if ((i == 0) && (pAsc->AacConfigChanged || pAsc->SbrConfigChanged || + pAsc->SacConfigChanged)) { + int errC; + + configChanged = 1; + errC = pTpDecCallbacks->cbFreeMem(pTpDecCallbacks->cbFreeMemData, + pAsc); + if (errC != 0) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + } + } + } + } + } + + /* If there was no configuration read, its not possible to parse + * PayloadLengthInfo below. */ + if (!*pfConfigFound) { + ErrorStatus = TRANSPORTDEC_SYNC_ERROR; + goto bail; + } + + if (pLatmDemux->m_AudioMuxVersionA == 0) { + /* Do only once per call, because parsing and decoding is done in-line. */ + if (TRANSPORTDEC_OK != + (ErrorStatus = CLatmDemux_ReadPayloadLengthInfo(bs, pLatmDemux))) { + *pfConfigFound = 0; + goto bail; + } + } else { + /* audioMuxVersionA > 0 is reserved for future extensions */ + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + *pfConfigFound = 0; + goto bail; + } + +bail: + if (ErrorStatus != TRANSPORTDEC_OK) { + pLatmDemux->applyAsc = 1; + } + + return (ErrorStatus); +} + +TRANSPORTDEC_ERROR CLatmDemux_Read(HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux, TRANSPORT_TYPE tt, + CSTpCallBacks *pTpDecCallbacks, + CSAudioSpecificConfig *pAsc, + int *pfConfigFound, + const INT ignoreBufferFullness) { + UINT cntBits; + UINT cmpBufferFullness; + UINT audioMuxLengthBytesLast = 0; + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + cntBits = FDKgetValidBits(bs); + + if ((INT)cntBits < MIN_LATM_HEADERLENGTH) { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + + if (TRANSPORTDEC_OK != (ErrorStatus = CLatmDemux_ReadAudioMuxElement( + bs, pLatmDemux, (tt != TT_MP4_LATM_MCP0), + pTpDecCallbacks, pAsc, pfConfigFound))) + return (ErrorStatus); + + if (!ignoreBufferFullness) { + cmpBufferFullness = + 24 + audioMuxLengthBytesLast * 8 + + pLatmDemux->m_linfo[0][0].m_bufferFullness * + pAsc[TPDEC_TRACKINDEX(0, 0)].m_channelConfiguration * 32; + + /* evaluate buffer fullness */ + + if (pLatmDemux->m_linfo[0][0].m_bufferFullness != 0xFF) { + if (!pLatmDemux->BufferFullnessAchieved) { + if (cntBits < cmpBufferFullness) { + /* condition for start of decoding is not fulfilled */ + + /* the current frame will not be decoded */ + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } else { + pLatmDemux->BufferFullnessAchieved = 1; + } + } + } + } + + return (ErrorStatus); +} + +TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig( + HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux, + CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc, + int *pfConfigFound, UCHAR configMode, UCHAR configChanged) { + CSAudioSpecificConfig ascDummy; /* the actual config is needed for flushing, + after that new config can be parsed */ + CSAudioSpecificConfig *pAscDummy; + pAscDummy = &ascDummy; + pLatmDemux->usacExplicitCfgChanged = 0; + LATM_LAYER_INFO *p_linfo = NULL; + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + UCHAR updateConfig[1 * 1] = {0}; + + pLatmDemux->m_AudioMuxVersion = FDKreadBits(bs, 1); + + if (pLatmDemux->m_AudioMuxVersion == 0) { + pLatmDemux->m_AudioMuxVersionA = 0; + } else { + pLatmDemux->m_AudioMuxVersionA = FDKreadBits(bs, 1); + } + + if (pLatmDemux->m_AudioMuxVersionA == 0) { + if (pLatmDemux->m_AudioMuxVersion == 1) { + pLatmDemux->m_taraBufferFullness = CLatmDemux_GetValue(bs); + } + pLatmDemux->m_allStreamsSameTimeFraming = FDKreadBits(bs, 1); + pLatmDemux->m_noSubFrames = FDKreadBits(bs, 6) + 1; + pLatmDemux->m_numProgram = FDKreadBits(bs, 4) + 1; + + if (pLatmDemux->m_numProgram > LATM_MAX_PROG) { + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + goto bail; + } + + int idCnt = 0; + for (UINT prog = 0; prog < pLatmDemux->m_numProgram; prog++) { + pLatmDemux->m_numLayer[prog] = FDKreadBits(bs, 3) + 1; + if (pLatmDemux->m_numLayer[prog] > LATM_MAX_LAYER) { + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + goto bail; + } + + for (UINT lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) { + int useSameConfig; + p_linfo = &pLatmDemux->m_linfo[prog][lay]; + + p_linfo->m_streamID = idCnt++; + p_linfo->m_frameLengthInBits = 0; + + if ((prog == 0) && (lay == 0)) { + useSameConfig = 0; + } else { + useSameConfig = FDKreadBits(bs, 1); + } + + if (useSameConfig) { + if (lay > 0) { + FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)], + &pAsc[TPDEC_TRACKINDEX(prog, lay - 1)], + sizeof(CSAudioSpecificConfig)); + } else { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } else { + UINT usacConfigLengthPrev = 0; + UCHAR usacConfigPrev[TP_USAC_MAX_CONFIG_LEN]; + + if (!(pLatmDemux->applyAsc) && + (pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == AOT_USAC)) { + usacConfigLengthPrev = + (UINT)(pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfigBits + + 7) >> + 3; /* store previous USAC config length */ + if (usacConfigLengthPrev > TP_USAC_MAX_CONFIG_LEN) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + FDKmemclear(usacConfigPrev, TP_USAC_MAX_CONFIG_LEN); + FDKmemcpy( + usacConfigPrev, + &pAsc[TPDEC_TRACKINDEX(prog, lay)].m_sc.m_usacConfig.UsacConfig, + usacConfigLengthPrev); /* store previous USAC config */ + } + if (pLatmDemux->m_AudioMuxVersion == 1) { + FDK_BITSTREAM tmpBs; + INT ascLen = 0; + ascLen = CLatmDemux_GetValue(bs); + /* The ascLen could be wrong, so check if validBits<=bufBits*/ + if (ascLen < 0 || ascLen > (INT)FDKgetValidBits(bs)) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + FDKsyncCache(bs); + tmpBs = *bs; + tmpBs.hBitBuf.ValidBits = ascLen; + + /* Read ASC */ + if (pLatmDemux->applyAsc) { + if (TRANSPORTDEC_OK != + (ErrorStatus = AudioSpecificConfig_Parse( + &pAsc[TPDEC_TRACKINDEX(prog, lay)], &tmpBs, 1, + pTpDecCallbacks, configMode, configChanged, + AOT_NULL_OBJECT))) + goto bail; + } else { + if (TRANSPORTDEC_OK != + (ErrorStatus = AudioSpecificConfig_Parse( + pAscDummy, &tmpBs, 1, pTpDecCallbacks, configMode, + configChanged, AOT_NULL_OBJECT))) + goto bail; + } + + /* The field p_linfo->m_ascLen could be wrong, so check if */ + if (0 > (INT)FDKgetValidBits(&tmpBs)) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + FDKpushFor(bs, ascLen); /* position bitstream after ASC */ + } else { + /* Read ASC */ + if (pLatmDemux->applyAsc) { + if (TRANSPORTDEC_OK != (ErrorStatus = AudioSpecificConfig_Parse( + &pAsc[TPDEC_TRACKINDEX(prog, lay)], + bs, 0, pTpDecCallbacks, configMode, + configChanged, AOT_NULL_OBJECT))) + goto bail; + } else { + if (TRANSPORTDEC_OK != + (ErrorStatus = AudioSpecificConfig_Parse( + pAscDummy, bs, 0, pTpDecCallbacks, configMode, + configChanged, AOT_NULL_OBJECT))) + goto bail; + } + } + if (!pLatmDemux->applyAsc) { + updateConfig[TPDEC_TRACKINDEX(prog, lay)] = 0; + } else { + updateConfig[TPDEC_TRACKINDEX(prog, lay)] = 1; + } + + if (!pLatmDemux->applyAsc) { + if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)].m_aot == + AOT_USAC) { /* flush in case SMC has changed */ + const UINT usacConfigLength = + (UINT)(pAscDummy->m_sc.m_usacConfig.UsacConfigBits + 7) >> 3; + if (usacConfigLength > TP_USAC_MAX_CONFIG_LEN) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + if (usacConfigLength != usacConfigLengthPrev) { + FDKmemclear(&pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfig, + TP_USAC_MAX_CONFIG_LEN); + FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfig, + &pAscDummy->m_sc.m_usacConfig.UsacConfig, + usacConfigLength); /* store new USAC config */ + pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfigBits = + pAscDummy->m_sc.m_usacConfig.UsacConfigBits; + pLatmDemux->usacExplicitCfgChanged = 1; + } else { + if (FDKmemcmp(usacConfigPrev, + pAscDummy->m_sc.m_usacConfig.UsacConfig, + usacConfigLengthPrev)) { + FDKmemclear(&pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfig, + TP_USAC_MAX_CONFIG_LEN); + FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfig, + &pAscDummy->m_sc.m_usacConfig.UsacConfig, + usacConfigLength); /* store new USAC config */ + pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfigBits = + pAscDummy->m_sc.m_usacConfig.UsacConfigBits; + pLatmDemux->usacExplicitCfgChanged = 1; + } + } + + if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.m_usacNumElements) { + if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.element[0] + .extElement.usacExtElementHasAudioPreRoll) { + pLatmDemux->newCfgHasAudioPreRoll = + 1; /* if dummy parsed cfg has audioPreRoll we first flush + before applying new cfg */ + } + } + } + } + } + + p_linfo->m_frameLengthType = FDKreadBits(bs, 3); + switch (p_linfo->m_frameLengthType) { + case 0: + p_linfo->m_bufferFullness = FDKreadBits(bs, 8); + + if (!pLatmDemux->m_allStreamsSameTimeFraming) { + if ((lay > 0) && + (pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == AOT_AAC_SCAL || + pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == + AOT_ER_AAC_SCAL) && + (pAsc[TPDEC_TRACKINDEX(prog, lay - 1)].m_aot == AOT_CELP || + pAsc[TPDEC_TRACKINDEX(prog, lay - 1)].m_aot == + AOT_ER_CELP)) { /* The layer maybe + ignored later so + read it anyway: */ + /* coreFrameOffset = */ FDKreadBits(bs, 6); + } + } + break; + case 1: + p_linfo->m_frameLengthInBits = FDKreadBits(bs, 9); + break; + case 3: + case 4: + case 5: + /* CELP */ + case 6: + case 7: + /* HVXC */ + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } /* switch framelengthtype*/ + + } /* layer loop */ + } /* prog loop */ + + pLatmDemux->m_otherDataPresent = FDKreadBits(bs, 1); + pLatmDemux->m_otherDataLength = 0; + + if (pLatmDemux->m_otherDataPresent) { + if (pLatmDemux->m_AudioMuxVersion == 1) { + pLatmDemux->m_otherDataLength = CLatmDemux_GetValue(bs); + } else { + int otherDataLenEsc = 0; + do { + pLatmDemux->m_otherDataLength <<= 8; // *= 256 + otherDataLenEsc = FDKreadBits(bs, 1); + pLatmDemux->m_otherDataLength += FDKreadBits(bs, 8); + } while (otherDataLenEsc); + } + if (pLatmDemux->m_audioMuxLengthBytes < + (pLatmDemux->m_otherDataLength >> 3)) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + + pLatmDemux->m_crcCheckPresent = FDKreadBits(bs, 1); + + if (pLatmDemux->m_crcCheckPresent) { + FDKreadBits(bs, 8); + } + + } else { + /* audioMuxVersionA > 0 is reserved for future extensions */ + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + /* Configure source decoder: */ + if (ErrorStatus == TRANSPORTDEC_OK) { + UINT prog; + for (prog = 0; prog < pLatmDemux->m_numProgram; prog++) { + UINT lay; + for (lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) { + if (updateConfig[TPDEC_TRACKINDEX(prog, lay)] != 0) { + int cbError; + cbError = pTpDecCallbacks->cbUpdateConfig( + pTpDecCallbacks->cbUpdateConfigData, + &pAsc[TPDEC_TRACKINDEX(prog, lay)], + pAsc[TPDEC_TRACKINDEX(prog, lay)].configMode, + &pAsc[TPDEC_TRACKINDEX(prog, lay)].AacConfigChanged); + if (cbError == TRANSPORTDEC_NEED_TO_RESTART) { + *pfConfigFound = 0; + ErrorStatus = TRANSPORTDEC_NEED_TO_RESTART; + goto bail; + } + if (cbError != 0) { + *pfConfigFound = 0; + if (lay == 0) { + ErrorStatus = TRANSPORTDEC_SYNC_ERROR; + goto bail; + } + } else { + *pfConfigFound = 1; + } + } else { + *pfConfigFound = 1; + } + } + } + } + +bail: + if (ErrorStatus != TRANSPORTDEC_OK) { + UCHAR applyAsc = pLatmDemux->applyAsc; + FDKmemclear(pLatmDemux, sizeof(CLatmDemux)); /* reset structure */ + pLatmDemux->applyAsc = applyAsc; + } else { + /* no error and config parsing is finished */ + if (configMode == AC_CM_ALLOC_MEM) pLatmDemux->applyAsc = 0; + } + + return (ErrorStatus); +} + +static int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs) { + int len = 0, tmp = 255; + int validBytes = (int)FDKgetValidBits(bs) >> 3; + + while (tmp == 255 && validBytes-- > 0) { + tmp = (int)FDKreadBits(bs, 8); + len += tmp; + } + + return ((tmp == 255) ? -1 : (len << 3)); +} + +TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + int totalPayloadBits = 0; + + if (pLatmDemux->m_allStreamsSameTimeFraming == 1) { + FDK_ASSERT(pLatmDemux->m_numProgram <= LATM_MAX_PROG); + for (UINT prog = 0; prog < pLatmDemux->m_numProgram; prog++) { + FDK_ASSERT(pLatmDemux->m_numLayer[prog] <= LATM_MAX_LAYER); + for (UINT lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) { + LATM_LAYER_INFO *p_linfo = &pLatmDemux->m_linfo[prog][lay]; + int auChunkLengthInfo = 0; + + switch (p_linfo->m_frameLengthType) { + case 0: + auChunkLengthInfo = CLatmDemux_ReadAuChunkLengthInfo(bs); + if (auChunkLengthInfo >= 0) { + p_linfo->m_frameLengthInBits = (UINT)auChunkLengthInfo; + totalPayloadBits += p_linfo->m_frameLengthInBits; + } else { + return TRANSPORTDEC_PARSE_ERROR; + } + break; + case 3: + case 5: + case 7: + default: + return TRANSPORTDEC_PARSE_ERROR; // AAC_DEC_LATM_INVALIDFRAMELENGTHTYPE; + } + } + } + } else { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; // AAC_DEC_LATM_TIMEFRAMING; + } + if (pLatmDemux->m_audioMuxLengthBytes > (UINT)0 && + totalPayloadBits > (int)pLatmDemux->m_audioMuxLengthBytes * 8) { + return TRANSPORTDEC_PARSE_ERROR; + } + + return (ErrorStatus); +} + +UINT CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux, const UINT prog, + const UINT layer) { + UINT nFrameLenBits = 0; + if (prog < pLatmDemux->m_numProgram) { + if (layer < pLatmDemux->m_numLayer[prog]) { + nFrameLenBits = pLatmDemux->m_linfo[prog][layer].m_frameLengthInBits; + } + } + return nFrameLenBits; +} + +UINT CLatmDemux_GetOtherDataPresentFlag(CLatmDemux *pLatmDemux) { + return pLatmDemux->m_otherDataPresent ? 1 : 0; +} + +UINT CLatmDemux_GetOtherDataLength(CLatmDemux *pLatmDemux) { + return pLatmDemux->m_otherDataLength; +} + +UINT CLatmDemux_GetNrOfSubFrames(CLatmDemux *pLatmDemux) { + return pLatmDemux->m_noSubFrames; +} + +UINT CLatmDemux_GetNrOfLayers(CLatmDemux *pLatmDemux, const UINT prog) { + UINT numLayer = 0; + if (prog < pLatmDemux->m_numProgram) { + numLayer = pLatmDemux->m_numLayer[prog]; + } + return numLayer; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_latm.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_latm.h new file mode 100644 index 0000000000000..8b8c97136dabe --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_latm.h @@ -0,0 +1,189 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Daniel Homm + + Description: + +*******************************************************************************/ + +#ifndef TPDEC_LATM_H +#define TPDEC_LATM_H + +#include "tpdec_lib.h" + +#include "FDK_bitstream.h" + +#define MIN_LATM_HEADERLENGTH 9 +#define MIN_LOAS_HEADERLENGTH MIN_LATM_HEADERLENGTH + 24 /* both in bits */ +#define MIN_TP_BUF_SIZE_LOAS (8194) + +enum { + LATM_MAX_PROG = 1, + LATM_MAX_LAYER = 1, + LATM_MAX_VAR_CHUNKS = 16, + LATM_MAX_ID = 16 +}; + +typedef struct { + UINT m_frameLengthType; + UINT m_bufferFullness; + UINT m_streamID; + UINT m_frameLengthInBits; +} LATM_LAYER_INFO; + +typedef struct { + LATM_LAYER_INFO m_linfo[LATM_MAX_PROG][LATM_MAX_LAYER]; + UINT m_taraBufferFullness; + UINT m_otherDataLength; + UINT m_audioMuxLengthBytes; /* Length of LOAS payload */ + + UCHAR m_useSameStreamMux; + UCHAR m_AudioMuxVersion; + UCHAR m_AudioMuxVersionA; + UCHAR m_allStreamsSameTimeFraming; + UCHAR m_noSubFrames; + UCHAR m_numProgram; + UCHAR m_numLayer[LATM_MAX_PROG]; + + UCHAR m_otherDataPresent; + UCHAR m_crcCheckPresent; + + SCHAR BufferFullnessAchieved; + UCHAR + usacExplicitCfgChanged; /* explicit config in case of USAC and LOAS/LATM + must be compared to IPF cfg */ + UCHAR applyAsc; /* apply ASC immediate without flushing */ + UCHAR newCfgHasAudioPreRoll; /* the new (dummy parsed) config has an + AudioPreRoll */ +} CLatmDemux; + +TRANSPORTDEC_ERROR CLatmDemux_Read(HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux, TRANSPORT_TYPE tt, + CSTpCallBacks *pTpDecCallbacks, + CSAudioSpecificConfig *pAsc, + int *pfConfigFound, + const INT ignoreBufferFullness); + +/** + * \brief Read StreamMuxConfig + * \param bs bit stream handle as data source + * \param pLatmDemux pointer to CLatmDemux struct of current LATM context + * \param pTpDecCallbacks Call back structure for configuration callbacks + * \param pAsc pointer to a ASC for configuration storage + * \param pfConfigFound pointer to a flag which is set to 1 if a configuration + * was found and processed successfully + * \param configMode Config modes: memory allocation mode or config change + * detection mode + * \param configChanged Indicates a config change + * \return error code + */ +TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig( + HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux, + CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc, + int *pfConfigFound, UCHAR configMode, UCHAR configChanged); + +TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux); + +UINT CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux, const UINT prog, + const UINT layer); +UINT CLatmDemux_GetOtherDataPresentFlag(CLatmDemux *pLatmDemux); +UINT CLatmDemux_GetOtherDataLength(CLatmDemux *pLatmDemux); +UINT CLatmDemux_GetNrOfSubFrames(CLatmDemux *pLatmDemux); +UINT CLatmDemux_GetNrOfLayers(CLatmDemux *pLatmDemux, const UINT program); + +#endif /* TPDEC_LATM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_lib.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_lib.cpp new file mode 100644 index 0000000000000..8cd9cb037b7aa --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPDec/src/tpdec_lib.cpp @@ -0,0 +1,1845 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2022 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Manuel Jander + + Description: MPEG Transport decoder + +*******************************************************************************/ + +#include "tpdec_lib.h" + +/* library version */ +#include "tp_version.h" + +#include "tp_data.h" + +#include "tpdec_adts.h" + +#include "tpdec_adif.h" + +#include "tpdec_latm.h" + +#include "tpdec_drm.h" + +#include "FDK_crc.h" + +#define MODULE_NAME "transportDec" + +typedef union { + STRUCT_ADTS adts; + + CAdifHeader adif; + + CLatmDemux latm; + + STRUCT_DRM drm; + +} transportdec_parser_t; + +#define MHAS_CONFIG_PRESENT 0x001 +#define MHAS_UI_PRESENT 0x002 + +struct TRANSPORTDEC { + TRANSPORT_TYPE transportFmt; /*!< MPEG4 transportDec type. */ + + CSTpCallBacks callbacks; /*!< Struct holding callback and its data */ + + FDK_BITSTREAM bitStream[1]; /* Bitstream reader */ + UCHAR *bsBuffer; /* Internal bitstreamd data buffer */ + + transportdec_parser_t parser; /* Format specific parser structs. */ + + CSAudioSpecificConfig asc[(1 * 1) + 1]; /* Audio specific config from the last + config found. One additional + CSAudioSpecificConfig is used + temporarily for parsing. */ + CCtrlCFGChange ctrlCFGChange[(1 * 1)]; /* Controls config change */ + + UINT globalFramePos; /* Global transport frame reference bit position. */ + UINT accessUnitAnchor[1]; /* Current access unit start bit position. */ + INT auLength[1]; /* Length of current access unit. */ + INT numberOfRawDataBlocks; /* Current number of raw data blocks contained + remaining from the current transport frame. */ + UINT avgBitRate; /* Average bit rate used for frame loss estimation. */ + UINT lastValidBufferFullness; /* Last valid buffer fullness value for frame + loss estimation */ + INT remainder; /* Reminder in division during lost access unit estimation. */ + INT missingAccessUnits; /* Estimated missing access units. */ + UINT burstPeriod; /* Data burst period in mili seconds. */ + UINT holdOffFrames; /* Amount of frames that were already hold off due to + buffer fullness condition not being met. */ + UINT flags; /* Flags. */ + INT targetLayout; /* CICP target layout. */ + UINT *pLoudnessInfoSetPosition; /* Reference and start position (bits) and + length (bytes) of loudnessInfoSet within + rsv603daConfig. */ +}; + +/* Flag bitmasks for "flags" member of struct TRANSPORTDEC */ +#define TPDEC_SYNCOK 1 +#define TPDEC_MINIMIZE_DELAY 2 +#define TPDEC_IGNORE_BUFFERFULLNESS 4 +#define TPDEC_EARLY_CONFIG 8 +#define TPDEC_LOST_FRAMES_PENDING 16 +#define TPDEC_CONFIG_FOUND 32 +#define TPDEC_USE_ELEM_SKIPPING 64 + +/* force config/content change */ +#define TPDEC_FORCE_CONFIG_CHANGE 1 +#define TPDEC_FORCE_CONTENT_CHANGE 2 + +/* skip packet */ +#define TPDEC_SKIP_PACKET 1 + +C_ALLOC_MEM(Ram_TransportDecoder, struct TRANSPORTDEC, 1) +C_ALLOC_MEM(Ram_TransportDecoderBuffer, UCHAR, (8192 * 4)) + +HANDLE_TRANSPORTDEC transportDec_Open(const TRANSPORT_TYPE transportFmt, + const UINT flags, const UINT nrOfLayers) { + HANDLE_TRANSPORTDEC hInput; + + hInput = GetRam_TransportDecoder(0); + if (hInput == NULL) { + return NULL; + } + + /* Init transportDec struct. */ + hInput->transportFmt = transportFmt; + + switch (transportFmt) { + case TT_MP4_ADIF: + break; + + case TT_MP4_ADTS: + if (flags & TP_FLAG_MPEG4) + hInput->parser.adts.decoderCanDoMpeg4 = 1; + else + hInput->parser.adts.decoderCanDoMpeg4 = 0; + adtsRead_CrcInit(&hInput->parser.adts); + hInput->parser.adts.BufferFullnesStartFlag = 1; + hInput->numberOfRawDataBlocks = 0; + break; + + case TT_DRM: + drmRead_CrcInit(&hInput->parser.drm); + break; + + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + hInput->parser.latm.usacExplicitCfgChanged = 0; + hInput->parser.latm.applyAsc = 1; + break; + case TT_MP4_LOAS: + hInput->parser.latm.usacExplicitCfgChanged = 0; + hInput->parser.latm.applyAsc = 1; + break; + case TT_MP4_RAW: + break; + + default: + FreeRam_TransportDecoder(&hInput); + hInput = NULL; + break; + } + + if (hInput != NULL) { + /* Create bitstream */ + { + hInput->bsBuffer = GetRam_TransportDecoderBuffer(0); + if (hInput->bsBuffer == NULL) { + transportDec_Close(&hInput); + return NULL; + } + if (nrOfLayers > 1) { + transportDec_Close(&hInput); + return NULL; + } + for (UINT i = 0; i < nrOfLayers; i++) { + FDKinitBitStream(&hInput->bitStream[i], hInput->bsBuffer, (8192 * 4), 0, + BS_READER); + } + } + hInput->burstPeriod = 0; + } + + return hInput; +} + +TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, + UCHAR *conf, const UINT length, + UINT layer) { + int i; + + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + + int fConfigFound = 0; + + UCHAR configChanged = 0; + UCHAR configMode = AC_CM_DET_CFG_CHANGE; + + UCHAR tmpConf[1024] = {0}; + if (length > 1024) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + FDKmemcpy(tmpConf, conf, length); + FDKinitBitStream(hBs, tmpConf, 1024, length << 3, BS_READER); + + for (i = 0; i < 2; i++) { + if (i > 0) { + FDKpushBack(hBs, (INT)length * 8 - (INT)FDKgetValidBits(hBs)); + configMode = AC_CM_ALLOC_MEM; + } + + /* config transport decoder */ + switch (hTp->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: { + if (layer != 0) { + return TRANSPORTDEC_INVALID_PARAMETER; + } + CLatmDemux *pLatmDemux = &hTp->parser.latm; + err = CLatmDemux_ReadStreamMuxConfig(hBs, pLatmDemux, &hTp->callbacks, + hTp->asc, &fConfigFound, + configMode, configChanged); + if (err != TRANSPORTDEC_OK) { + return err; + } + } break; + default: + fConfigFound = 1; + err = AudioSpecificConfig_Parse(&hTp->asc[(1 * 1)], hBs, 1, + &hTp->callbacks, configMode, + configChanged, AOT_NULL_OBJECT); + if (err == TRANSPORTDEC_OK) { + int errC; + + hTp->asc[layer] = hTp->asc[(1 * 1)]; + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer], + hTp->asc[layer].configMode, &hTp->asc[layer].AacConfigChanged); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + break; + case TT_DRM: + fConfigFound = 1; + err = DrmRawSdcAudioConfig_Parse(&hTp->asc[layer], hBs, &hTp->callbacks, + configMode, configChanged); + if (err == TRANSPORTDEC_OK) { + int errC; + + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer], + hTp->asc[layer].configMode, &hTp->asc[layer].AacConfigChanged); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + break; + } + + if (err == TRANSPORTDEC_OK) { + if ((i == 0) && (hTp->asc[layer].AacConfigChanged || + hTp->asc[layer].SbrConfigChanged || + hTp->asc[layer].SacConfigChanged)) { + int errC; + + configChanged = 1; + errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[layer]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + } + + /* if an error is detected terminate config parsing to avoid that an invalid + * config is accepted in the second pass */ + if (err != TRANSPORTDEC_OK) { + break; + } + } + + if (err == TRANSPORTDEC_OK && fConfigFound) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } + + return err; +} + +TRANSPORTDEC_ERROR transportDec_InBandConfig(HANDLE_TRANSPORTDEC hTp, + UCHAR *newConfig, + const UINT newConfigLength, + const UCHAR buildUpStatus, + UCHAR *configChanged, UINT layer, + UCHAR *implicitExplicitCfgDiff) { + int errC; + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + int fConfigFound = 0; + UCHAR configMode = AC_CM_ALLOC_MEM; + *implicitExplicitCfgDiff = 0; + + FDK_ASSERT(hTp->asc->m_aot == AOT_USAC); + + FDKinitBitStream(hBs, newConfig, TP_USAC_MAX_CONFIG_LEN, newConfigLength << 3, + BS_READER); + + if ((hTp->ctrlCFGChange[layer].flushStatus == TPDEC_FLUSH_OFF) && + (hTp->ctrlCFGChange[layer].buildUpStatus != + TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND)) { + if (hTp->asc->m_aot == AOT_USAC) { + if ((UINT)(hTp->asc->m_sc.m_usacConfig.UsacConfigBits + 7) >> 3 == + newConfigLength) { + if (0 == FDKmemcmp(newConfig, hTp->asc->m_sc.m_usacConfig.UsacConfig, + newConfigLength)) { + if (hTp->parser.latm.usacExplicitCfgChanged) { /* configChange from + LOAS/LATM parser */ + hTp->parser.latm.usacExplicitCfgChanged = 0; + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].flushStatus = + TPDEC_USAC_DASH_IPF_FLUSH_ON; + hTp->ctrlCFGChange[layer].buildUpCnt = 0; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF; + } else { + *configChanged = 0; + return err; + } + } else { + *implicitExplicitCfgDiff = 1; + } + } else { + *implicitExplicitCfgDiff = 1; + } + /* ISO/IEC 23003-3:2012/FDAM 3:2016(E) Annex F.2: explicit and implicit + * config shall be identical. */ + if (*implicitExplicitCfgDiff) { + switch (hTp->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + /* reset decoder to initial state to achieve definite behavior after + * error in config */ + hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[layer]); + hTp->parser.latm.usacExplicitCfgChanged = 0; + hTp->parser.latm.applyAsc = 1; + err = TRANSPORTDEC_PARSE_ERROR; + goto bail; + default: + break; + } + } + } + } + + { + if ((hTp->ctrlCFGChange[layer].flushStatus == TPDEC_FLUSH_OFF) && + (hTp->ctrlCFGChange[layer].buildUpStatus != + TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND)) { + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].buildUpCnt = 0; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF; + if (hTp->asc->m_aot == AOT_USAC) { + hTp->ctrlCFGChange[layer].flushStatus = TPDEC_USAC_DASH_IPF_FLUSH_ON; + } + } + + if ((hTp->ctrlCFGChange[layer].flushStatus == + TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON) || + (hTp->ctrlCFGChange[layer].flushStatus == + TPDEC_USAC_DASH_IPF_FLUSH_ON)) { + SCHAR counter = 0; + if (hTp->asc->m_aot == AOT_USAC) { + counter = TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES; + } + if (hTp->ctrlCFGChange[layer].flushCnt >= counter) { + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].flushStatus = TPDEC_FLUSH_OFF; + hTp->ctrlCFGChange[layer].forceCfgChange = 0; + if (hTp->asc->m_aot == AOT_USAC) { + hTp->ctrlCFGChange[layer].buildUpCnt = + TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES - 1; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_USAC_BUILD_UP_ON; + } + } + + /* Activate flush mode. After that continue with build up mode in core */ + if (hTp->callbacks.cbCtrlCFGChange(hTp->callbacks.cbCtrlCFGChangeData, + &hTp->ctrlCFGChange[layer]) != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + + if ((hTp->ctrlCFGChange[layer].flushStatus == + TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON) || + (hTp->ctrlCFGChange[layer].flushStatus == + TPDEC_USAC_DASH_IPF_FLUSH_ON)) { + hTp->ctrlCFGChange[layer].flushCnt++; + return err; + } + } + + if (hTp->asc->m_aot == AOT_USAC) { + fConfigFound = 1; + + if (err == TRANSPORTDEC_OK) { + *configChanged = 0; + configMode = AC_CM_DET_CFG_CHANGE; + + for (int i = 0; i < 2; i++) { + if (i > 0) { + FDKpushBack(hBs, + (INT)newConfigLength * 8 - (INT)FDKgetValidBits(hBs)); + configMode = AC_CM_ALLOC_MEM; + } + /* config transport decoder */ + err = AudioSpecificConfig_Parse( + &hTp->asc[(1 * 1)], hBs, 0, &hTp->callbacks, configMode, + *configChanged, hTp->asc[layer].m_aot); + if (err == TRANSPORTDEC_OK) { + hTp->asc[layer] = hTp->asc[(1 * 1)]; + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer], + hTp->asc[layer].configMode, &hTp->asc[layer].AacConfigChanged); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + + if (err == TRANSPORTDEC_OK) { + if ((i == 0) && (hTp->asc[layer].AacConfigChanged || + hTp->asc[layer].SbrConfigChanged || + hTp->asc[layer].SacConfigChanged)) { + *configChanged = 1; + errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[layer]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + } + + /* if an error is detected terminate config parsing to avoid that an + * invalid config is accepted in the second pass */ + if (err != TRANSPORTDEC_OK) { + break; + } + } + } + } + + bail: + /* save new config */ + if (err == TRANSPORTDEC_OK) { + if (hTp->asc->m_aot == AOT_USAC) { + hTp->asc->m_sc.m_usacConfig.UsacConfigBits = newConfigLength << 3; + FDKmemcpy(hTp->asc->m_sc.m_usacConfig.UsacConfig, newConfig, + newConfigLength); + /* in case of USAC reset transportDecoder variables here because + * otherwise without IPF they are not reset */ + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].flushStatus = TPDEC_FLUSH_OFF; + hTp->ctrlCFGChange[layer].buildUpCnt = 0; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF; + } + } else { + hTp->numberOfRawDataBlocks = 0; + + /* If parsing error while config found, clear ctrlCFGChange-struct */ + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].flushStatus = TPDEC_FLUSH_OFF; + hTp->ctrlCFGChange[layer].buildUpCnt = 0; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF; + hTp->ctrlCFGChange[layer].cfgChanged = 0; + hTp->ctrlCFGChange[layer].contentChanged = 0; + hTp->ctrlCFGChange[layer].forceCfgChange = 0; + + hTp->callbacks.cbCtrlCFGChange(hTp->callbacks.cbCtrlCFGChangeData, + &hTp->ctrlCFGChange[layer]); + } + } + + if (err == TRANSPORTDEC_OK && fConfigFound) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } + + return err; +} + +int transportDec_RegisterAscCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUpdateConfig_t cbUpdateConfig, + void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbUpdateConfig = cbUpdateConfig; + hTpDec->callbacks.cbUpdateConfigData = user_data; + return 0; +} + +int transportDec_RegisterFreeMemCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbFreeMem_t cbFreeMem, + void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbFreeMem = cbFreeMem; + hTpDec->callbacks.cbFreeMemData = user_data; + return 0; +} + +int transportDec_RegisterCtrlCFGChangeCallback( + HANDLE_TRANSPORTDEC hTpDec, const cbCtrlCFGChange_t cbCtrlCFGChange, + void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbCtrlCFGChange = cbCtrlCFGChange; + hTpDec->callbacks.cbCtrlCFGChangeData = user_data; + return 0; +} + +int transportDec_RegisterSscCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbSsc_t cbSsc, void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbSsc = cbSsc; + hTpDec->callbacks.cbSscData = user_data; + return 0; +} + +int transportDec_RegisterSbrCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbSbr_t cbSbr, void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbSbr = cbSbr; + hTpDec->callbacks.cbSbrData = user_data; + return 0; +} + +int transportDec_RegisterUsacCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUsac_t cbUsac, void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbUsac = cbUsac; + hTpDec->callbacks.cbUsacData = user_data; + return 0; +} + +int transportDec_RegisterUniDrcConfigCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUniDrc_t cbUniDrc, + void *user_data, + UINT *pLoudnessInfoSetPosition) { + if (hTpDec == NULL) { + return -1; + } + + hTpDec->callbacks.cbUniDrc = cbUniDrc; + hTpDec->callbacks.cbUniDrcData = user_data; + + hTpDec->pLoudnessInfoSetPosition = pLoudnessInfoSetPosition; + return 0; +} + +TRANSPORTDEC_ERROR transportDec_FillData(const HANDLE_TRANSPORTDEC hTp, + UCHAR *pBuffer, const UINT bufferSize, + UINT *pBytesValid, const INT layer) { + HANDLE_FDK_BITSTREAM hBs; + + if ((hTp == NULL) || (layer >= 1)) { + return TRANSPORTDEC_INVALID_PARAMETER; + } + + /* set bitbuffer shortcut */ + hBs = &hTp->bitStream[layer]; + + if (TT_IS_PACKET(hTp->transportFmt)) { + if (hTp->numberOfRawDataBlocks == 0) { + FDKresetBitbuffer(hBs); + FDKfeedBuffer(hBs, pBuffer, bufferSize, pBytesValid); + if (*pBytesValid != 0) { + return TRANSPORTDEC_TOO_MANY_BITS; + } + } + } else { + /* ... else feed bitbuffer with new stream data (append). */ + + if (*pBytesValid == 0) { + /* nothing to do */ + return TRANSPORTDEC_OK; + } else { + const int bytesValid = *pBytesValid; + FDKfeedBuffer(hBs, pBuffer, bufferSize, pBytesValid); + + if (hTp->numberOfRawDataBlocks > 0) { + hTp->globalFramePos += (bytesValid - *pBytesValid) * 8; + hTp->accessUnitAnchor[layer] = FDKgetValidBits(hBs); + } + } + } + + return TRANSPORTDEC_OK; +} + +HANDLE_FDK_BITSTREAM transportDec_GetBitstream(const HANDLE_TRANSPORTDEC hTp, + const UINT layer) { + return &hTp->bitStream[layer]; +} + +TRANSPORT_TYPE transportDec_GetFormat(const HANDLE_TRANSPORTDEC hTp) { + return hTp->transportFmt; +} + +INT transportDec_GetBufferFullness(const HANDLE_TRANSPORTDEC hTp) { + INT bufferFullness = -1; + + switch (hTp->transportFmt) { + case TT_MP4_ADTS: + if (hTp->parser.adts.bs.adts_fullness != 0x7ff) { + bufferFullness = hTp->parser.adts.bs.frame_length * 8 + + hTp->parser.adts.bs.adts_fullness * 32 * + getNumberOfEffectiveChannels( + hTp->parser.adts.bs.channel_config); + } + break; + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + if (hTp->parser.latm.m_linfo[0][0].m_bufferFullness != 0xff) { + bufferFullness = hTp->parser.latm.m_linfo[0][0].m_bufferFullness; + } + break; + default: + break; + } + + return bufferFullness; +} + +/** + * \brief adjust bit stream position and the end of an access unit. + * \param hTp transport decoder handle. + * \return error code. + */ +static TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit( + HANDLE_TRANSPORTDEC hTp) { + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0]; + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + /* Do byte align at the end of raw_data_block() because UsacFrame() is not + * byte aligned. */ + FDKbyteAlign(hBs, hTp->accessUnitAnchor[0]); + break; + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + if (hTp->numberOfRawDataBlocks == 0) { + /* Do byte align at the end of AudioMuxElement. */ + FDKbyteAlign(hBs, hTp->globalFramePos); + + /* Check global frame length */ + if (hTp->transportFmt == TT_MP4_LOAS && + hTp->parser.latm.m_audioMuxLengthBytes > 0) { + int loasOffset; + + loasOffset = ((INT)hTp->parser.latm.m_audioMuxLengthBytes * 8 + + (INT)FDKgetValidBits(hBs)) - + (INT)hTp->globalFramePos; + if (loasOffset != 0) { + FDKpushBiDirectional(hBs, loasOffset); + /* For ELD and other payloads there is an unknown amount of padding, + so ignore unread bits, but throw an error only if too many bits + where read. */ + if (loasOffset < 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + } + } + break; + + case TT_MP4_ADTS: + if (hTp->parser.adts.bs.protection_absent == 0) { + int offset; + + /* Calculate offset to end of AU */ + offset = hTp->parser.adts + .rawDataBlockDist[hTp->parser.adts.bs.num_raw_blocks - + hTp->numberOfRawDataBlocks] + << 3; + /* CAUTION: The PCE (if available) is declared to be a part of the + * header! */ + offset -= (INT)hTp->accessUnitAnchor[0] - (INT)FDKgetValidBits(hBs) + + 16 + hTp->parser.adts.bs.num_pce_bits; + FDKpushBiDirectional(hBs, offset); + } + if (hTp->parser.adts.bs.num_raw_blocks > 0 && + hTp->parser.adts.bs.protection_absent == 0) { + /* Note this CRC read currently happens twice because of + * transportDec_CrcCheck() */ + hTp->parser.adts.crcReadValue = FDKreadBits(hBs, 16); + } + if (hTp->numberOfRawDataBlocks == 0) { + /* Check global frame length */ + if (hTp->parser.adts.bs.protection_absent == 0) { + int offset; + + offset = (hTp->parser.adts.bs.frame_length * 8 - ADTS_SYNCLENGTH + + (INT)FDKgetValidBits(hBs)) - + (INT)hTp->globalFramePos; + if (offset != 0) { + FDKpushBiDirectional(hBs, offset); + } + } + } + break; + + default: + break; + } + + return err; +} + +/** + * \brief Determine additional buffer fullness contraint due to burst data + * reception. The parameter TPDEC_PARAM_BURSTPERIOD must have been set as a + * precondition. + * \param hTp transport decoder handle. + * \param bufferFullness the buffer fullness value of the first frame to be + * decoded. + * \param bitsAvail the amount of available bits at the end of the first frame + * to be decoded. + * \return error code + */ +static TRANSPORTDEC_ERROR additionalHoldOffNeeded(HANDLE_TRANSPORTDEC hTp, + INT bufferFullness, + INT bitsAvail) { + INT checkLengthBits, avgBitsPerFrame; + INT maxAU; /* maximum number of frames per Master Frame */ + INT samplesPerFrame = hTp->asc->m_samplesPerFrame; + INT samplingFrequency = (INT)hTp->asc->m_samplingFrequency; + + if ((hTp->avgBitRate == 0) || (hTp->burstPeriod == 0)) { + return TRANSPORTDEC_OK; + } + if ((samplesPerFrame == 0) || (samplingFrequency == 0)) { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + + /* One Master Frame is sent every hTp->burstPeriod ms */ + maxAU = hTp->burstPeriod * samplingFrequency + (samplesPerFrame * 1000 - 1); + maxAU = maxAU / (samplesPerFrame * 1000); + /* Subtract number of frames which were already held off. */ + maxAU -= hTp->holdOffFrames; + + avgBitsPerFrame = hTp->avgBitRate * samplesPerFrame + (samplingFrequency - 1); + avgBitsPerFrame = avgBitsPerFrame / samplingFrequency; + + /* Consider worst case of bufferFullness quantization. */ + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + case TT_MP4_ADTS: + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + bufferFullness += 31; + break; + default: /* added to avoid compiler warning */ + break; /* added to avoid compiler warning */ + } + + checkLengthBits = bufferFullness + (maxAU - 1) * avgBitsPerFrame; + + /* Check if buffer is big enough to fullfill buffer fullness condition */ + if ((checkLengthBits /*+headerBits*/) > (((8192 * 4) << 3) - 7)) { + return TRANSPORTDEC_SYNC_ERROR; + } + + if (bitsAvail < checkLengthBits) { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } else { + return TRANSPORTDEC_OK; + } +} + +static TRANSPORTDEC_ERROR transportDec_readHeader( + HANDLE_TRANSPORTDEC hTp, HANDLE_FDK_BITSTREAM hBs, int syncLength, + int ignoreBufferFullness, int *pRawDataBlockLength, + int *pfTraverseMoreFrames, int *pSyncLayerFrameBits, int *pfConfigFound, + int *pHeaderBits) { + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + int rawDataBlockLength = *pRawDataBlockLength; + int fTraverseMoreFrames = + (pfTraverseMoreFrames != NULL) ? *pfTraverseMoreFrames : 0; + int syncLayerFrameBits = + (pSyncLayerFrameBits != NULL) ? *pSyncLayerFrameBits : 0; + int fConfigFound = (pfConfigFound != NULL) ? *pfConfigFound : 0; + int startPos; + + startPos = (INT)FDKgetValidBits(hBs); + + switch (hTp->transportFmt) { + case TT_MP4_ADTS: + if (hTp->numberOfRawDataBlocks <= 0) { + int i, errC; + + hTp->globalFramePos = FDKgetValidBits(hBs); + + UCHAR configChanged = 0; + UCHAR configMode = AC_CM_DET_CFG_CHANGE; + + for (i = 0; i < 2; i++) { + if (i > 0) { + FDKpushBack(hBs, + (INT)hTp->globalFramePos - (INT)FDKgetValidBits(hBs)); + configMode = AC_CM_ALLOC_MEM; + } + + /* Parse ADTS header */ + err = adtsRead_DecodeHeader(&hTp->parser.adts, &hTp->asc[0], hBs, + ignoreBufferFullness); + if (err != TRANSPORTDEC_OK) { + if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[0], configMode, + &configChanged); + if (errC != 0) { + if (errC == TRANSPORTDEC_NEED_TO_RESTART) { + err = TRANSPORTDEC_NEED_TO_RESTART; + goto bail; + } else { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + fConfigFound = 1; + hTp->numberOfRawDataBlocks = + hTp->parser.adts.bs.num_raw_blocks + 1; + } + } + + if (err == TRANSPORTDEC_OK) { + if ((i == 0) && configChanged) { + errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[0]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + } + /* if an error is detected terminate config parsing to avoid that an + * invalid config is accepted in the second pass */ + if (err != TRANSPORTDEC_OK) { + break; + } + } + } else { + /* Reset CRC because the next bits are the beginning of a + * raw_data_block() */ + FDKcrcReset(&hTp->parser.adts.crcInfo); + hTp->parser.adts.bs.num_pce_bits = 0; + } + if (err == TRANSPORTDEC_OK) { + hTp->numberOfRawDataBlocks--; + rawDataBlockLength = adtsRead_GetRawDataBlockLength( + &hTp->parser.adts, + (hTp->parser.adts.bs.num_raw_blocks - hTp->numberOfRawDataBlocks)); + if (rawDataBlockLength <= 0) { + /* No further frame traversal possible. */ + fTraverseMoreFrames = 0; + } + syncLayerFrameBits = (hTp->parser.adts.bs.frame_length << 3) - + (startPos - (INT)FDKgetValidBits(hBs)) - + syncLength; + if (syncLayerFrameBits <= 0) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + hTp->numberOfRawDataBlocks = 0; + } + break; + case TT_MP4_LOAS: + if (hTp->numberOfRawDataBlocks <= 0) { + syncLayerFrameBits = (INT)FDKreadBits(hBs, 13); + hTp->parser.latm.m_audioMuxLengthBytes = syncLayerFrameBits; + syncLayerFrameBits <<= 3; + } + FDK_FALLTHROUGH; + case TT_MP4_LATM_MCP1: + case TT_MP4_LATM_MCP0: + if (hTp->numberOfRawDataBlocks <= 0) { + hTp->globalFramePos = FDKgetValidBits(hBs); + + err = CLatmDemux_Read(hBs, &hTp->parser.latm, hTp->transportFmt, + &hTp->callbacks, hTp->asc, &fConfigFound, + ignoreBufferFullness); + + if (err != TRANSPORTDEC_OK) { + if ((err != TRANSPORTDEC_NOT_ENOUGH_BITS) && + !TPDEC_IS_FATAL_ERROR(err)) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + hTp->numberOfRawDataBlocks = + CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm); + if (hTp->transportFmt == TT_MP4_LOAS) { + syncLayerFrameBits -= startPos - (INT)FDKgetValidBits(hBs) - (13); + if (syncLayerFrameBits <= 0) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } + } + } else { + err = CLatmDemux_ReadPayloadLengthInfo(hBs, &hTp->parser.latm); + if (err != TRANSPORTDEC_OK) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } + if (err == TRANSPORTDEC_OK) { + int layer; + rawDataBlockLength = 0; + for (layer = 0; + layer < (int)CLatmDemux_GetNrOfLayers(&hTp->parser.latm, 0); + layer += 1) { + rawDataBlockLength += + CLatmDemux_GetFrameLengthInBits(&hTp->parser.latm, 0, layer); + } + hTp->numberOfRawDataBlocks--; + } else { + hTp->numberOfRawDataBlocks = 0; + } + break; + default: { syncLayerFrameBits = 0; } break; + } + +bail: + + *pRawDataBlockLength = rawDataBlockLength; + + if (pHeaderBits != NULL) { + *pHeaderBits += startPos - (INT)FDKgetValidBits(hBs); + } + + for (int i = 0; i < (1 * 1); i++) { + /* If parsing error while config found, clear ctrlCFGChange-struct */ + if (hTp->ctrlCFGChange[i].cfgChanged && err != TRANSPORTDEC_OK) { + hTp->numberOfRawDataBlocks = 0; + hTp->ctrlCFGChange[i].flushCnt = 0; + hTp->ctrlCFGChange[i].flushStatus = TPDEC_FLUSH_OFF; + hTp->ctrlCFGChange[i].buildUpCnt = 0; + hTp->ctrlCFGChange[i].buildUpStatus = TPDEC_BUILD_UP_OFF; + hTp->ctrlCFGChange[i].cfgChanged = 0; + hTp->ctrlCFGChange[i].contentChanged = 0; + hTp->ctrlCFGChange[i].forceCfgChange = 0; + + hTp->callbacks.cbCtrlCFGChange(hTp->callbacks.cbCtrlCFGChangeData, + &hTp->ctrlCFGChange[i]); + } + } + + if (pfConfigFound != NULL) { + *pfConfigFound = fConfigFound; + } + + if (pfTraverseMoreFrames != NULL) { + *pfTraverseMoreFrames = fTraverseMoreFrames; + } + if (pSyncLayerFrameBits != NULL) { + *pSyncLayerFrameBits = syncLayerFrameBits; + } + + return err; +} + +/* How many bits to advance for synchronization search. */ +#define TPDEC_SYNCSKIP 8 + +static TRANSPORTDEC_ERROR synchronization(HANDLE_TRANSPORTDEC hTp, + INT *pHeaderBits) { + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK, errFirstFrame = TRANSPORTDEC_OK; + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0]; + + INT syncLayerFrameBits = 0; /* Length of sync layer frame (i.e. LOAS) */ + INT rawDataBlockLength = 0, rawDataBlockLengthPrevious; + INT totalBits; + INT headerBits = 0, headerBitsFirstFrame = 0, headerBitsPrevious; + INT numFramesTraversed = 0, fTraverseMoreFrames, + fConfigFound = (hTp->flags & TPDEC_CONFIG_FOUND), startPosFirstFrame = -1; + INT numRawDataBlocksFirstFrame = 0, numRawDataBlocksPrevious, + globalFramePosFirstFrame = 0, rawDataBlockLengthFirstFrame = 0; + INT ignoreBufferFullness = + hTp->flags & + (TPDEC_LOST_FRAMES_PENDING | TPDEC_IGNORE_BUFFERFULLNESS | TPDEC_SYNCOK); + UINT endTpFrameBitsPrevious = 0; + + /* Synch parameters */ + INT syncLength; /* Length of sync word in bits */ + UINT syncWord; /* Sync word to be found */ + UINT syncMask; /* Mask for sync word (for adding one bit, so comprising one + bit less) */ + C_ALLOC_SCRATCH_START(contextFirstFrame, transportdec_parser_t, 1); + + totalBits = (INT)FDKgetValidBits(hBs); + + if (totalBits <= 0) { + err = TRANSPORTDEC_NOT_ENOUGH_BITS; + goto bail; + } + + fTraverseMoreFrames = + (hTp->flags & (TPDEC_MINIMIZE_DELAY | TPDEC_EARLY_CONFIG)) && + !(hTp->flags & TPDEC_SYNCOK); + + /* Set transport specific sync parameters */ + switch (hTp->transportFmt) { + case TT_MP4_ADTS: + syncWord = ADTS_SYNCWORD; + syncLength = ADTS_SYNCLENGTH; + break; + case TT_MP4_LOAS: + syncWord = 0x2B7; + syncLength = 11; + break; + default: + syncWord = 0; + syncLength = 0; + break; + } + + syncMask = (1 << syncLength) - 1; + + do { + INT bitsAvail = 0; /* Bits available in bitstream buffer */ + INT checkLengthBits; /* Helper to check remaining bits and buffer boundaries + */ + UINT synch; /* Current sync word read from bitstream */ + + headerBitsPrevious = headerBits; + + bitsAvail = (INT)FDKgetValidBits(hBs); + + if (hTp->numberOfRawDataBlocks == 0) { + /* search synchword */ + + FDK_ASSERT((bitsAvail % TPDEC_SYNCSKIP) == 0); + + if ((bitsAvail - syncLength) < TPDEC_SYNCSKIP) { + err = TRANSPORTDEC_NOT_ENOUGH_BITS; + headerBits = 0; + } else { + synch = FDKreadBits(hBs, syncLength); + + if (!(hTp->flags & TPDEC_SYNCOK)) { + for (; (bitsAvail - syncLength) >= TPDEC_SYNCSKIP; + bitsAvail -= TPDEC_SYNCSKIP) { + if (synch == syncWord) { + break; + } + synch = ((synch << TPDEC_SYNCSKIP) & syncMask) | + FDKreadBits(hBs, TPDEC_SYNCSKIP); + } + } + if (synch != syncWord) { + /* No correct syncword found. */ + err = TRANSPORTDEC_SYNC_ERROR; + } else { + err = TRANSPORTDEC_OK; + } + headerBits = syncLength; + } + } else { + headerBits = 0; + } + + /* Save previous raw data block data */ + rawDataBlockLengthPrevious = rawDataBlockLength; + numRawDataBlocksPrevious = hTp->numberOfRawDataBlocks; + + /* Parse transport header (raw data block granularity) */ + + if (err == TRANSPORTDEC_OK) { + err = transportDec_readHeader(hTp, hBs, syncLength, ignoreBufferFullness, + &rawDataBlockLength, &fTraverseMoreFrames, + &syncLayerFrameBits, &fConfigFound, + &headerBits); + if (headerBits > bitsAvail) { + err = (headerBits < (INT)hBs->hBitBuf.bufBits) + ? TRANSPORTDEC_NOT_ENOUGH_BITS + : TRANSPORTDEC_SYNC_ERROR; + } + if (TPDEC_IS_FATAL_ERROR(err)) { + /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead + * next time. Ensure that the bit amount lands at a multiple of + * TPDEC_SYNCSKIP. */ + FDKpushBiDirectional( + hBs, -headerBits + TPDEC_SYNCSKIP + (bitsAvail % TPDEC_SYNCSKIP)); + + goto bail; + } + } + + bitsAvail -= headerBits; + + checkLengthBits = syncLayerFrameBits; + + /* Check if the whole frame would fit the bitstream buffer */ + if (err == TRANSPORTDEC_OK) { + if ((checkLengthBits + headerBits) > (((8192 * 4) << 3) - 7)) { + /* We assume that the size of the transport bit buffer has been + chosen to meet all system requirements, thus this condition + is considered a synchronisation error. */ + err = TRANSPORTDEC_SYNC_ERROR; + } else { + if (bitsAvail < checkLengthBits) { + err = TRANSPORTDEC_NOT_ENOUGH_BITS; + } + } + } + + if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) { + break; + } + + if (err == TRANSPORTDEC_SYNC_ERROR) { + int bits; + + /* Enforce re-sync of transport headers. */ + hTp->numberOfRawDataBlocks = 0; + + /* Ensure that the bit amount lands at a multiple of TPDEC_SYNCSKIP */ + bits = (bitsAvail + headerBits) % TPDEC_SYNCSKIP; + /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead + * next time. */ + FDKpushBiDirectional(hBs, -(headerBits - TPDEC_SYNCSKIP) + bits); + headerBits = 0; + } + + /* Frame traversal */ + if (fTraverseMoreFrames) { + /* Save parser context for early config discovery "rewind all frames" */ + if ((hTp->flags & TPDEC_EARLY_CONFIG) && + !(hTp->flags & TPDEC_MINIMIZE_DELAY)) { + /* ignore buffer fullness if just traversing additional frames for ECD + */ + ignoreBufferFullness = 1; + + /* Save context in order to return later */ + if (err == TRANSPORTDEC_OK && startPosFirstFrame == -1) { + startPosFirstFrame = FDKgetValidBits(hBs); + numRawDataBlocksFirstFrame = hTp->numberOfRawDataBlocks; + globalFramePosFirstFrame = hTp->globalFramePos; + rawDataBlockLengthFirstFrame = rawDataBlockLength; + headerBitsFirstFrame = headerBits; + errFirstFrame = err; + FDKmemcpy(contextFirstFrame, &hTp->parser, + sizeof(transportdec_parser_t)); + } + + /* Break when config was found or it is not possible anymore to find a + * config */ + if (startPosFirstFrame != -1 && + (fConfigFound || err != TRANSPORTDEC_OK)) { + /* In case of ECD and sync error, do not rewind anywhere. */ + if (err == TRANSPORTDEC_SYNC_ERROR) { + startPosFirstFrame = -1; + fConfigFound = 0; + numFramesTraversed = 0; + } + break; + } + } + + if (err == TRANSPORTDEC_OK) { + FDKpushFor(hBs, rawDataBlockLength); + numFramesTraversed++; + endTpFrameBitsPrevious = (INT)FDKgetValidBits(hBs); + /* Ignore error here itentionally. */ + transportDec_AdjustEndOfAccessUnit(hTp); + endTpFrameBitsPrevious -= FDKgetValidBits(hBs); + } + } + } while (fTraverseMoreFrames || + (err == TRANSPORTDEC_SYNC_ERROR && !(hTp->flags & TPDEC_SYNCOK))); + + /* Restore context in case of ECD frame traversal */ + if (startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK)) { + FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - startPosFirstFrame); + FDKmemcpy(&hTp->parser, contextFirstFrame, sizeof(transportdec_parser_t)); + hTp->numberOfRawDataBlocks = numRawDataBlocksFirstFrame; + hTp->globalFramePos = globalFramePosFirstFrame; + rawDataBlockLength = rawDataBlockLengthFirstFrame; + headerBits = headerBitsFirstFrame; + err = errFirstFrame; + numFramesTraversed = 0; + } + + /* Additional burst data mode buffer fullness check. */ + if (!(hTp->flags & (TPDEC_LOST_FRAMES_PENDING | TPDEC_IGNORE_BUFFERFULLNESS | + TPDEC_SYNCOK)) && + err == TRANSPORTDEC_OK) { + err = + additionalHoldOffNeeded(hTp, transportDec_GetBufferFullness(hTp), + (INT)FDKgetValidBits(hBs) - syncLayerFrameBits); + if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) { + hTp->holdOffFrames++; + } + } + + /* Rewind for retry because of not enough bits */ + if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) { + FDKpushBack(hBs, headerBits); + hTp->numberOfRawDataBlocks = numRawDataBlocksPrevious; + headerBits = 0; + rawDataBlockLength = rawDataBlockLengthPrevious; + } else { + /* reset hold off frame counter */ + hTp->holdOffFrames = 0; + } + + /* Return to last good frame in case of frame traversal but not ECD. */ + if (numFramesTraversed > 0) { + FDKpushBack(hBs, rawDataBlockLengthPrevious + endTpFrameBitsPrevious); + if (err != TRANSPORTDEC_OK) { + hTp->numberOfRawDataBlocks = numRawDataBlocksPrevious; + headerBits = headerBitsPrevious; + rawDataBlockLength = rawDataBlockLengthPrevious; + } + err = TRANSPORTDEC_OK; + } + +bail: + hTp->auLength[0] = rawDataBlockLength; + + /* Detect pointless TRANSPORTDEC_NOT_ENOUGH_BITS error case, where the bit + buffer is already full, or no new burst packet fits. Recover by advancing + the bit buffer. */ + if ((totalBits > 0) && (TRANSPORTDEC_NOT_ENOUGH_BITS == err) && + (FDKgetValidBits(hBs) >= + (((8192 * 4) * 8 - ((hTp->avgBitRate * hTp->burstPeriod) / 1000)) - + 7))) { + FDKpushFor(hBs, TPDEC_SYNCSKIP); + err = TRANSPORTDEC_SYNC_ERROR; + } + + if (err == TRANSPORTDEC_OK) { + hTp->flags |= TPDEC_SYNCOK; + } + + if (fConfigFound) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } + + if (pHeaderBits != NULL) { + *pHeaderBits = headerBits; + } + + if (err == TRANSPORTDEC_SYNC_ERROR) { + hTp->flags &= ~TPDEC_SYNCOK; + } + + C_ALLOC_SCRATCH_END(contextFirstFrame, transportdec_parser_t, 1); + + return err; +} + +/** + * \brief Synchronize to stream and estimate the amount of missing access units + * due to a current synchronization error in case of constant average bit rate. + */ +static TRANSPORTDEC_ERROR transportDec_readStream(HANDLE_TRANSPORTDEC hTp, + const UINT layer) { + TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK; + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[layer]; + + INT headerBits; + INT bitDistance, bfDelta; + + /* Obtain distance to next synch word */ + bitDistance = (INT)FDKgetValidBits(hBs); + error = synchronization(hTp, &headerBits); + bitDistance -= (INT)FDKgetValidBits(hBs); + + FDK_ASSERT(bitDistance >= 0); + + INT nAU = -1; + + if (error == TRANSPORTDEC_SYNC_ERROR || + (hTp->flags & TPDEC_LOST_FRAMES_PENDING)) { + /* Check if estimating lost access units is feasible. */ + if (hTp->avgBitRate > 0 && hTp->asc[0].m_samplesPerFrame > 0 && + hTp->asc[0].m_samplingFrequency > 0) { + if (error == TRANSPORTDEC_OK) { + int aj; + + aj = transportDec_GetBufferFullness(hTp); + if (aj > 0) { + bfDelta = aj; + } else { + bfDelta = 0; + } + /* sync was ok: last of a series of bad access units. */ + hTp->flags &= ~TPDEC_LOST_FRAMES_PENDING; + /* Add up bitDistance until end of the current frame. Later we substract + this frame from the grand total, since this current successfully + synchronized frame should not be skipped of course; but it must be + accounted into the bufferfulness math. */ + bitDistance += hTp->auLength[0]; + } else { + if (!(hTp->flags & TPDEC_LOST_FRAMES_PENDING)) { + /* sync not ok: one of many bad access units. */ + hTp->flags |= TPDEC_LOST_FRAMES_PENDING; + bfDelta = -(INT)hTp->lastValidBufferFullness; + } else { + bfDelta = 0; + } + } + + { + int num, denom; + + /* Obtain estimate of number of lost frames */ + num = (INT)hTp->asc[0].m_samplingFrequency * (bfDelta + bitDistance) + + hTp->remainder; + denom = hTp->avgBitRate * hTp->asc[0].m_samplesPerFrame; + if (num > 0) { + nAU = num / denom; + hTp->remainder = num % denom; + } else { + hTp->remainder = num; + } + + if (error == TRANSPORTDEC_OK) { + /* Final adjustment of remainder, taken -1 into account because + current frame should not be skipped, thus substract -1 or do + nothing instead of +1-1 accordingly. */ + if ((denom - hTp->remainder) >= hTp->remainder) { + nAU--; + } + + if (nAU < 0) { + /* There was one frame too much concealed, so unfortunately we will + * have to skip one good frame. */ + transportDec_EndAccessUnit(hTp); + error = synchronization(hTp, &headerBits); + nAU = -1; + } + hTp->remainder = 0; + /* Enforce last missed frames to be concealed. */ + if (nAU > 0) { + FDKpushBack(hBs, headerBits); + } + } + } + } + } + + /* Be sure that lost frames are handled correctly. This is necessary due to + some sync error sequences where later it turns out that there is not enough + data, but the bits upto the sync word are discarded, thus causing a value + of nAU > 0 */ + if (nAU > 0) { + error = TRANSPORTDEC_SYNC_ERROR; + } + + hTp->missingAccessUnits = nAU; + + return error; +} + +/* returns error code */ +TRANSPORTDEC_ERROR transportDec_ReadAccessUnit(const HANDLE_TRANSPORTDEC hTp, + const UINT layer) { + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + HANDLE_FDK_BITSTREAM hBs; + + if (!hTp) { + return TRANSPORTDEC_INVALID_PARAMETER; + } + + hBs = &hTp->bitStream[layer]; + + if ((INT)FDKgetValidBits(hBs) <= 0) { + /* This is only relevant for RAW and ADIF cases. + * For streaming formats err will get overwritten. */ + err = TRANSPORTDEC_NOT_ENOUGH_BITS; + hTp->numberOfRawDataBlocks = 0; + } + + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + /* Read header if not already done */ + if (!(hTp->flags & TPDEC_CONFIG_FOUND)) { + int i; + CProgramConfig *pce; + INT bsStart = FDKgetValidBits(hBs); + UCHAR configChanged = 0; + UCHAR configMode = AC_CM_DET_CFG_CHANGE; + + for (i = 0; i < 2; i++) { + if (i > 0) { + FDKpushBack(hBs, bsStart - (INT)FDKgetValidBits(hBs)); + configMode = AC_CM_ALLOC_MEM; + } + + AudioSpecificConfig_Init(&hTp->asc[0]); + pce = &hTp->asc[0].m_progrConfigElement; + err = adifRead_DecodeHeader(&hTp->parser.adif, pce, hBs); + if (err) goto bail; + + /* Map adif header to ASC */ + hTp->asc[0].m_aot = (AUDIO_OBJECT_TYPE)(pce->Profile + 1); + hTp->asc[0].m_samplingFrequencyIndex = pce->SamplingFrequencyIndex; + hTp->asc[0].m_samplingFrequency = + SamplingRateTable[pce->SamplingFrequencyIndex]; + hTp->asc[0].m_channelConfiguration = 0; + hTp->asc[0].m_samplesPerFrame = 1024; + hTp->avgBitRate = hTp->parser.adif.BitRate; + + /* Call callback to decoder. */ + { + int errC; + + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[0], configMode, + &configChanged); + if (errC == 0) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } else { + err = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + + if (err == TRANSPORTDEC_OK) { + if ((i == 0) && configChanged) { + int errC; + errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[0]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + } + } + } + hTp->auLength[layer] = -1; /* Access Unit data length is unknown. */ + break; + + case TT_MP4_RAW: + case TT_DRM: + /* One Access Unit was filled into buffer. + So get the length out of the buffer. */ + hTp->auLength[layer] = FDKgetValidBits(hBs); + hTp->flags |= TPDEC_SYNCOK; + break; + + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + if (err == TRANSPORTDEC_OK) { + int fConfigFound = hTp->flags & TPDEC_CONFIG_FOUND; + err = transportDec_readHeader(hTp, hBs, 0, 1, &hTp->auLength[layer], + NULL, NULL, &fConfigFound, NULL); + if (fConfigFound) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } + } + break; + + case TT_MP4_ADTS: + case TT_MP4_LOAS: + err = transportDec_readStream(hTp, layer); + break; + + default: + err = TRANSPORTDEC_UNSUPPORTED_FORMAT; + break; + } + + if (err == TRANSPORTDEC_OK) { + hTp->accessUnitAnchor[layer] = FDKgetValidBits(hBs); + } else { + hTp->accessUnitAnchor[layer] = 0; + } + +bail: + return err; +} + +TRANSPORTDEC_ERROR transportDec_GetAsc(const HANDLE_TRANSPORTDEC hTp, + const UINT layer, + CSAudioSpecificConfig *asc) { + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + if (hTp != NULL) { + *asc = hTp->asc[layer]; + err = TRANSPORTDEC_OK; + } else { + err = TRANSPORTDEC_INVALID_PARAMETER; + } + return err; +} + +INT transportDec_GetAuBitsRemaining(const HANDLE_TRANSPORTDEC hTp, + const UINT layer) { + INT bits; + + if (hTp->accessUnitAnchor[layer] > 0 && hTp->auLength[layer] > 0) { + bits = (INT)FDKgetValidBits(&hTp->bitStream[layer]); + if (bits >= 0) { + bits = hTp->auLength[layer] - ((INT)hTp->accessUnitAnchor[layer] - bits); + } + } else { + bits = FDKgetValidBits(&hTp->bitStream[layer]); + } + + return bits; +} + +INT transportDec_GetAuBitsTotal(const HANDLE_TRANSPORTDEC hTp, + const UINT layer) { + return hTp->auLength[layer]; +} + +TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount( + INT *pNAccessUnits, HANDLE_TRANSPORTDEC hTp) { + *pNAccessUnits = hTp->missingAccessUnits; + + return TRANSPORTDEC_OK; +} + +/* Inform the transportDec layer that reading of access unit has finished. */ +TRANSPORTDEC_ERROR transportDec_EndAccessUnit(HANDLE_TRANSPORTDEC hTp) { + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + switch (hTp->transportFmt) { + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: { + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0]; + if (hTp->numberOfRawDataBlocks == 0) { + /* Read other data if available. */ + if (CLatmDemux_GetOtherDataPresentFlag(&hTp->parser.latm)) { + int otherDataLen = CLatmDemux_GetOtherDataLength(&hTp->parser.latm); + + if ((INT)FDKgetValidBits(hBs) >= otherDataLen) { + FDKpushFor(hBs, otherDataLen); + } else { + /* Do byte align at the end of AudioMuxElement. */ + if (hTp->numberOfRawDataBlocks == 0) { + FDKbyteAlign(hBs, hTp->globalFramePos); + } + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + } + } else { + /* If bit buffer has not more bits but hTp->numberOfRawDataBlocks > 0 + then too many bits were read and obviously no more RawDataBlocks can + be read. Set numberOfRawDataBlocks to zero to attempt a new sync + attempt. */ + if ((INT)FDKgetValidBits(hBs) <= 0) { + hTp->numberOfRawDataBlocks = 0; + } + } + } break; + default: + break; + } + + err = transportDec_AdjustEndOfAccessUnit(hTp); + + switch (hTp->transportFmt) { + default: + break; + } + + return err; +} + +TRANSPORTDEC_ERROR transportDec_SetParam(const HANDLE_TRANSPORTDEC hTp, + const TPDEC_PARAM param, + const INT value) { + TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK; + + if (hTp == NULL) { + return TRANSPORTDEC_INVALID_PARAMETER; + } + + switch (param) { + case TPDEC_PARAM_MINIMIZE_DELAY: + if (value) { + hTp->flags |= TPDEC_MINIMIZE_DELAY; + } else { + hTp->flags &= ~TPDEC_MINIMIZE_DELAY; + } + break; + case TPDEC_PARAM_EARLY_CONFIG: + if (value) { + hTp->flags |= TPDEC_EARLY_CONFIG; + } else { + hTp->flags &= ~TPDEC_EARLY_CONFIG; + } + break; + case TPDEC_PARAM_IGNORE_BUFFERFULLNESS: + if (value) { + hTp->flags |= TPDEC_IGNORE_BUFFERFULLNESS; + } else { + hTp->flags &= ~TPDEC_IGNORE_BUFFERFULLNESS; + } + break; + case TPDEC_PARAM_SET_BITRATE: + hTp->avgBitRate = value; + break; + case TPDEC_PARAM_BURST_PERIOD: + hTp->burstPeriod = value; + break; + case TPDEC_PARAM_RESET: { + int i; + + for (i = 0; i < (1 * 1); i++) { + FDKresetBitbuffer(&hTp->bitStream[i]); + hTp->auLength[i] = 0; + hTp->accessUnitAnchor[i] = 0; + } + hTp->flags &= ~(TPDEC_SYNCOK | TPDEC_LOST_FRAMES_PENDING); + if (hTp->transportFmt != TT_MP4_ADIF) { + hTp->flags &= ~TPDEC_CONFIG_FOUND; + } + hTp->remainder = 0; + hTp->avgBitRate = 0; + hTp->missingAccessUnits = 0; + hTp->numberOfRawDataBlocks = 0; + hTp->globalFramePos = 0; + hTp->holdOffFrames = 0; + } break; + case TPDEC_PARAM_TARGETLAYOUT: + hTp->targetLayout = value; + break; + case TPDEC_PARAM_FORCE_CONFIG_CHANGE: + hTp->ctrlCFGChange[value].forceCfgChange = TPDEC_FORCE_CONFIG_CHANGE; + break; + case TPDEC_PARAM_USE_ELEM_SKIPPING: + if (value) { + hTp->flags |= TPDEC_USE_ELEM_SKIPPING; + } else { + hTp->flags &= ~TPDEC_USE_ELEM_SKIPPING; + } + break; + } + + return error; +} + +UINT transportDec_GetNrOfSubFrames(HANDLE_TRANSPORTDEC hTp) { + UINT nSubFrames = 0; + + if (hTp == NULL) return 0; + + if (hTp->transportFmt == TT_MP4_LATM_MCP1 || + hTp->transportFmt == TT_MP4_LATM_MCP0 || hTp->transportFmt == TT_MP4_LOAS) + nSubFrames = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm); + else if (hTp->transportFmt == TT_MP4_ADTS) + nSubFrames = hTp->parser.adts.bs.num_raw_blocks; + + return nSubFrames; +} + +void transportDec_Close(HANDLE_TRANSPORTDEC *phTp) { + if (phTp != NULL) { + if (*phTp != NULL) { + FreeRam_TransportDecoderBuffer(&(*phTp)->bsBuffer); + FreeRam_TransportDecoder(phTp); + } + } +} + +TRANSPORTDEC_ERROR transportDec_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return TRANSPORTDEC_UNKOWN_ERROR; + } + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) return TRANSPORTDEC_UNKOWN_ERROR; + info += i; + + info->module_id = FDK_TPDEC; +#ifdef SUPPRESS_BUILD_DATE_INFO + info->build_date = ""; + info->build_time = ""; +#else + info->build_date = __DATE__; + info->build_time = __TIME__; +#endif + info->title = TP_LIB_TITLE; + info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2); + LIB_VERSION_STRING(info); + info->flags = 0 | CAPF_ADIF | CAPF_ADTS | CAPF_LATM | CAPF_LOAS | + CAPF_RAWPACKETS | CAPF_DRM; + + return TRANSPORTDEC_OK; /* FDKERR_NOERROR; */ +} + +int transportDec_CrcStartReg(HANDLE_TRANSPORTDEC pTp, INT mBits) { + switch (pTp->transportFmt) { + case TT_MP4_ADTS: + return adtsRead_CrcStartReg(&pTp->parser.adts, &pTp->bitStream[0], mBits); + case TT_DRM: + return drmRead_CrcStartReg(&pTp->parser.drm, &pTp->bitStream[0], mBits); + default: + return -1; + } +} + +void transportDec_CrcEndReg(HANDLE_TRANSPORTDEC pTp, INT reg) { + switch (pTp->transportFmt) { + case TT_MP4_ADTS: + adtsRead_CrcEndReg(&pTp->parser.adts, &pTp->bitStream[0], reg); + break; + case TT_DRM: + drmRead_CrcEndReg(&pTp->parser.drm, &pTp->bitStream[0], reg); + break; + default: + break; + } +} + +TRANSPORTDEC_ERROR transportDec_CrcCheck(HANDLE_TRANSPORTDEC pTp) { + switch (pTp->transportFmt) { + case TT_MP4_ADTS: + if ((pTp->parser.adts.bs.num_raw_blocks > 0) && + (pTp->parser.adts.bs.protection_absent == 0)) { + transportDec_AdjustEndOfAccessUnit(pTp); + } + return adtsRead_CrcCheck(&pTp->parser.adts); + case TT_DRM: + return drmRead_CrcCheck(&pTp->parser.drm); + default: + return TRANSPORTDEC_OK; + } +} + +TRANSPORTDEC_ERROR transportDec_DrmRawSdcAudioConfig_Check(UCHAR *conf, + const UINT length) { + CSAudioSpecificConfig asc; + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + + FDKinitBitStream(hBs, conf, BUFSIZE_DUMMY_VALUE, length << 3, BS_READER); + + TRANSPORTDEC_ERROR err = + DrmRawSdcAudioConfig_Parse(&asc, hBs, NULL, (UCHAR)AC_CM_ALLOC_MEM, 0); + + return err; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/include/tp_data.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/include/tp_data.h new file mode 100644 index 0000000000000..464c4850b27bf --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/include/tp_data.h @@ -0,0 +1,466 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Manuel Jander + + Description: MPEG Transport data tables + +*******************************************************************************/ + +#ifndef TP_DATA_H +#define TP_DATA_H + +#include "machine_type.h" +#include "FDK_audio.h" +#include "FDK_bitstream.h" + +/* + * Configuration + */ + +#define TP_USAC_MAX_SPEAKERS (24) + +#define TP_USAC_MAX_EXT_ELEMENTS ((24)) + +#define TP_USAC_MAX_ELEMENTS ((24) + TP_USAC_MAX_EXT_ELEMENTS) + +#define TP_USAC_MAX_CONFIG_LEN \ + 512 /* next power of two of maximum of escapedValue(hBs, 4, 4, 8) in \ + AudioPreRoll() (285) */ + +#define TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES \ + (1) /* Number of frames for config change in USAC */ + +enum { + TPDEC_FLUSH_OFF = 0, + TPDEC_RSV60_CFG_CHANGE_ATSC_FLUSH_ON = 1, + TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON = 2, + TPDEC_USAC_DASH_IPF_FLUSH_ON = 3 +}; + +enum { + TPDEC_BUILD_UP_OFF = 0, + TPDEC_RSV60_BUILD_UP_ON = 1, + TPDEC_RSV60_BUILD_UP_ON_IN_BAND = 2, + TPDEC_USAC_BUILD_UP_ON = 3, + TPDEC_RSV60_BUILD_UP_IDLE = 4, + TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND = 5 +}; + +/** + * ProgramConfig struct. + */ +/* ISO/IEC 14496-3 4.4.1.1 Table 4.2 Program config element */ +#define PC_FSB_CHANNELS_MAX 16 /* Front/Side/Back channels */ +#define PC_LFE_CHANNELS_MAX 4 +#define PC_ASSOCDATA_MAX 8 +#define PC_CCEL_MAX 16 /* CC elements */ +#define PC_COMMENTLENGTH 256 +#define PC_NUM_HEIGHT_LAYER 3 + +typedef struct { + /* PCE bitstream elements: */ + UCHAR ElementInstanceTag; + UCHAR Profile; + UCHAR SamplingFrequencyIndex; + UCHAR NumFrontChannelElements; + UCHAR NumSideChannelElements; + UCHAR NumBackChannelElements; + UCHAR NumLfeChannelElements; + UCHAR NumAssocDataElements; + UCHAR NumValidCcElements; + + UCHAR MonoMixdownPresent; + UCHAR MonoMixdownElementNumber; + + UCHAR StereoMixdownPresent; + UCHAR StereoMixdownElementNumber; + + UCHAR MatrixMixdownIndexPresent; + UCHAR MatrixMixdownIndex; + UCHAR PseudoSurroundEnable; + + UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR FrontElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR SideElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR BackElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX]; + + UCHAR AssocDataElementTagSelect[PC_ASSOCDATA_MAX]; + + UCHAR CcElementIsIndSw[PC_CCEL_MAX]; + UCHAR ValidCcElementTagSelect[PC_CCEL_MAX]; + + UCHAR CommentFieldBytes; + UCHAR Comment[PC_COMMENTLENGTH]; + + /* Helper variables for administration: */ + UCHAR isValid; /*!< Flag showing if PCE has been read successfully. */ + UCHAR + NumChannels; /*!< Amount of audio channels summing all channel elements + including LFEs */ + UCHAR NumEffectiveChannels; /*!< Amount of audio channels summing only SCEs + and CPEs */ + UCHAR elCounter; + +} CProgramConfig; + +typedef enum { + ASCEXT_UNKOWN = -1, + ASCEXT_SBR = 0x2b7, + ASCEXT_PS = 0x548, + ASCEXT_MPS = 0x76a, + ASCEXT_SAOC = 0x7cb, + ASCEXT_LDMPS = 0x7cc + +} TP_ASC_EXTENSION_ID; + +/** + * GaSpecificConfig struct + */ +typedef struct { + UINT m_frameLengthFlag; + UINT m_dependsOnCoreCoder; + UINT m_coreCoderDelay; + + UINT m_extensionFlag; + UINT m_extensionFlag3; + + UINT m_layer; + UINT m_numOfSubFrame; + UINT m_layerLength; + +} CSGaSpecificConfig; + +typedef enum { + ELDEXT_TERM = 0x0, /* Termination tag */ + ELDEXT_SAOC = 0x1, /* SAOC config */ + ELDEXT_LDSAC = 0x2, /* LD MPEG Surround config */ + ELDEXT_DOWNSCALEINFO = 0x3 /* ELD sample rate adaptation */ + /* reserved */ +} ASC_ELD_EXT_TYPE; + +typedef struct { + UCHAR m_frameLengthFlag; + + UCHAR m_sbrPresentFlag; + UCHAR + m_useLdQmfTimeAlign; /* Use LD-MPS QMF in SBR to achive time alignment */ + UCHAR m_sbrSamplingRate; + UCHAR m_sbrCrcFlag; + UINT m_downscaledSamplingFrequency; + +} CSEldSpecificConfig; + +typedef struct { + USAC_EXT_ELEMENT_TYPE usacExtElementType; + USHORT usacExtElementConfigLength; + USHORT usacExtElementDefaultLength; + UCHAR usacExtElementPayloadFrag; + UCHAR usacExtElementHasAudioPreRoll; +} CSUsacExtElementConfig; + +typedef struct { + MP4_ELEMENT_ID usacElementType; + UCHAR m_noiseFilling; + UCHAR m_harmonicSBR; + UCHAR m_interTes; + UCHAR m_pvc; + UCHAR m_stereoConfigIndex; + CSUsacExtElementConfig extElement; +} CSUsacElementConfig; + +typedef struct { + UCHAR m_frameLengthFlag; + UCHAR m_coreSbrFrameLengthIndex; + UCHAR m_sbrRatioIndex; + UCHAR m_nUsacChannels; /* number of audio channels signaled in + UsacDecoderConfig() / rsv603daDecoderConfig() via + numElements and usacElementType */ + UCHAR m_channelConfigurationIndex; + UINT m_usacNumElements; + CSUsacElementConfig element[TP_USAC_MAX_ELEMENTS]; + + UCHAR numAudioChannels; + UCHAR m_usacConfigExtensionPresent; + UCHAR elementLengthPresent; + UCHAR UsacConfig[TP_USAC_MAX_CONFIG_LEN]; + USHORT UsacConfigBits; +} CSUsacConfig; + +/** + * Audio configuration struct, suitable for encoder and decoder configuration. + */ +typedef struct { + /* XYZ Specific Data */ + union { + CSGaSpecificConfig + m_gaSpecificConfig; /**< General audio specific configuration. */ + CSEldSpecificConfig m_eldSpecificConfig; /**< ELD specific configuration. */ + CSUsacConfig m_usacConfig; /**< USAC specific configuration */ + } m_sc; + + /* Common ASC parameters */ + CProgramConfig m_progrConfigElement; /**< Program configuration. */ + + AUDIO_OBJECT_TYPE m_aot; /**< Audio Object Type. */ + UINT m_samplingFrequency; /**< Samplerate. */ + UINT m_samplesPerFrame; /**< Amount of samples per frame. */ + UINT m_directMapping; /**< Document this please !! */ + + AUDIO_OBJECT_TYPE m_extensionAudioObjectType; /**< Audio object type */ + UINT m_extensionSamplingFrequency; /**< Samplerate */ + + SCHAR m_channelConfiguration; /**< Channel configuration index */ + + SCHAR m_epConfig; /**< Error protection index */ + SCHAR m_vcb11Flag; /**< aacSectionDataResilienceFlag */ + SCHAR m_rvlcFlag; /**< aacScalefactorDataResilienceFlag */ + SCHAR m_hcrFlag; /**< aacSpectralDataResilienceFlag */ + + SCHAR m_sbrPresentFlag; /**< Flag indicating the presence of SBR data in the + bitstream */ + SCHAR + m_psPresentFlag; /**< Flag indicating the presence of parametric stereo + data in the bitstream */ + UCHAR m_samplingFrequencyIndex; /**< Samplerate index */ + UCHAR m_extensionSamplingFrequencyIndex; /**< Samplerate index */ + SCHAR m_extensionChannelConfiguration; /**< Channel configuration index */ + + UCHAR + configMode; /**< The flag indicates if the callback shall work in memory + allocation mode or in config change detection mode */ + UCHAR AacConfigChanged; /**< The flag will be set if at least one aac config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + UCHAR SbrConfigChanged; /**< The flag will be set if at least one sbr config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + UCHAR SacConfigChanged; /**< The flag will be set if at least one sac config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + + UCHAR + config[TP_USAC_MAX_CONFIG_LEN]; /**< Configuration stored as bitstream */ + UINT configBits; /**< Configuration length in bits */ + +} CSAudioSpecificConfig; + +typedef struct { + SCHAR flushCnt; /**< Flush frame counter */ + UCHAR flushStatus; /**< Flag indicates flush mode: on|off */ + SCHAR buildUpCnt; /**< Build up frame counter */ + UCHAR buildUpStatus; /**< Flag indicates build up mode: on|off */ + UCHAR cfgChanged; /**< Flag indicates that the config changed and the decoder + needs to be initialized again via callback. Make sure + that memory is freed before initialization. */ + UCHAR contentChanged; /**< Flag indicates that the content changed i.e. a + right truncation occured before */ + UCHAR forceCfgChange; /**< Flag indicates if config change has to be forced + even if new config is the same */ +} CCtrlCFGChange; + +typedef INT (*cbUpdateConfig_t)(void *, const CSAudioSpecificConfig *, + const UCHAR configMode, UCHAR *configChanged); +typedef INT (*cbFreeMem_t)(void *, const CSAudioSpecificConfig *); +typedef INT (*cbCtrlCFGChange_t)(void *, const CCtrlCFGChange *); +typedef INT (*cbSsc_t)(void *, HANDLE_FDK_BITSTREAM, + const AUDIO_OBJECT_TYPE coreCodec, + const INT samplingRate, const INT frameSize, + const INT numChannels, const INT stereoConfigIndex, + const INT coreSbrFrameLengthIndex, const INT configBytes, + const UCHAR configMode, UCHAR *configChanged); + +typedef INT (*cbSbr_t)(void *self, HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const INT elementIndex, + const UCHAR harmonicSbr, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor); + +typedef INT (*cbUsac_t)(void *self, HANDLE_FDK_BITSTREAM hBs); + +typedef INT (*cbUniDrc_t)(void *self, HANDLE_FDK_BITSTREAM hBs, + const INT fullPayloadLength, const INT payloadType, + const INT subStreamIndex, const INT payloadStart, + const AUDIO_OBJECT_TYPE); + +typedef struct { + cbUpdateConfig_t cbUpdateConfig; /*!< Function pointer for Config change + notify callback. */ + void *cbUpdateConfigData; /*!< User data pointer for Config change notify + callback. */ + cbFreeMem_t cbFreeMem; /*!< Function pointer for free memory callback. */ + void *cbFreeMemData; /*!< User data pointer for free memory callback. */ + cbCtrlCFGChange_t cbCtrlCFGChange; /*!< Function pointer for config change + control callback. */ + void *cbCtrlCFGChangeData; /*!< User data pointer for config change control + callback. */ + cbSsc_t cbSsc; /*!< Function pointer for SSC parser callback. */ + void *cbSscData; /*!< User data pointer for SSC parser callback. */ + cbSbr_t cbSbr; /*!< Function pointer for SBR header parser callback. */ + void *cbSbrData; /*!< User data pointer for SBR header parser callback. */ + cbUsac_t cbUsac; + void *cbUsacData; + cbUniDrc_t cbUniDrc; /*!< Function pointer for uniDrcConfig and + loudnessInfoSet parser callback. */ + void *cbUniDrcData; /*!< User data pointer for uniDrcConfig and + loudnessInfoSet parser callback. */ +} CSTpCallBacks; + +static const UINT SamplingRateTable[] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, + 8000, 7350, 0, 0, 57600, 51200, 40000, 38400, 34150, 28800, 25600, + 20000, 19200, 17075, 14400, 12800, 9600, 0, 0, 0, 0}; + +static inline int getSamplingRateIndex(UINT samplingRate, UINT nBits) { + UINT sf_index; + UINT tableSize = (1 << nBits) - 1; + + for (sf_index = 0; sf_index < tableSize; sf_index++) { + if (SamplingRateTable[sf_index] == samplingRate) break; + } + + if (sf_index > tableSize) { + return tableSize - 1; + } + + return sf_index; +} + +/* + * Get Channel count from channel configuration + */ +static inline int getNumberOfTotalChannels(int channelConfig) { + switch (channelConfig) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + return channelConfig; + case 7: + case 12: + case 14: + return 8; + case 11: + return 7; + case 13: + return 24; + default: + return 0; + } +} + +static inline int getNumberOfEffectiveChannels( + const int + channelConfig) { /* index: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */ + const int n[] = {0, 1, 2, 3, 4, 5, 5, 7, 0, 0, 0, 6, 7, 22, 7, 0}; + return n[channelConfig]; +} + +#endif /* TP_DATA_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/include/tpenc_lib.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/include/tpenc_lib.h new file mode 100644 index 0000000000000..4eb89a77bdeb9 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/include/tpenc_lib.h @@ -0,0 +1,339 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Manuel Jander + + Description: MPEG Transport encode + +*******************************************************************************/ + +#ifndef TPENC_LIB_H +#define TPENC_LIB_H + +#include "tp_data.h" +#include "FDK_bitstream.h" + +#define TRANSPORTENC_INBUF_SIZE 8192 + +typedef enum { + TRANSPORTENC_OK = 0, /*!< All fine. */ + TRANSPORTENC_NO_MEM, /*!< Out of memory. */ + TRANSPORTENC_UNKOWN_ERROR = 1, /*!< Unknown error (embarrasing). */ + TRANSPORTENC_INVALID_PARAMETER, /*!< An invalid parameter was passed to a + function . */ + TRANSPORTENC_UNSUPPORTED_FORMAT, /*!< Unsupported transport format. */ + TRANSPORTENC_NOT_ENOUGH_BITS, /*!< Out of bits. Provide more bits and try + again. */ + + TRANSPORTENC_INVALID_CONFIG, /*!< Error in configuration. */ + TRANSPORTENC_LATM_INVALID_NR_OF_SUBFRAMES, /*!< LATM: number of subframes out + of range. */ + TRANSPORTENC_LOAS_NOT_AVAILABLE, /*!< LOAS format not supported. */ + TRANSPORTENC_INVALID_LATM_ALIGNMENT, /*!< AudioMuxElement length not aligned + to 1 byte. */ + + TRANSPORTENC_INVALID_TRANSMISSION_FRAME_LENGTH, /*!< Invalid transmission + frame length (< 0). */ + TRANSPORTENC_INVALID_CELP_FRAME_LENGTH, /*!< Invalid CELP frame length found + (>= 62). */ + TRANSPORTENC_INVALID_FRAME_BITS, /*!< Frame bits is not 40 and not 80. */ + TRANSPORTENC_INVALID_AOT, /*!< Unknown AOT found. */ + TRANSPORTENC_INVALID_AU_LENGTH /*!< Invalid Access Unit length (not + byte-aligned). */ + +} TRANSPORTENC_ERROR; + +typedef struct TRANSPORTENC *HANDLE_TRANSPORTENC; + +/** + * \brief Determine a reasonable channel configuration on the basis + * of channel_mode. + * \param noChannels Number of audio channels. + * \return CHANNEL_MODE value that matches the given amount of audio + * channels. + */ +CHANNEL_MODE transportEnc_GetChannelMode(int noChannels); + +/** + * \brief Register SBR heaqder writer callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle SBR header + * writing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportEnc_RegisterSbrCallback(HANDLE_TRANSPORTENC hTpEnc, + const cbSbr_t cbSbr, void *user_data); + +/** + * \brief Register USAC SC writer callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle USAC + * SCwriting. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportEnc_RegisterUsacCallback(HANDLE_TRANSPORTENC hTpEnc, + const cbUsac_t cbUsac, void *user_data); + +/** + * \brief Register SSC writer callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle SSC writing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportEnc_RegisterSscCallback(HANDLE_TRANSPORTENC hTpEnc, + const cbSsc_t cbSsc, void *user_data); + +/** + * \brief Write ASC from given parameters. + * \param asc A HANDLE_FDK_BITSTREAM where the ASC is written to. + * \param config Structure containing the codec configuration settings. + * \param cb callback information structure. + * \return 0 on success. + */ +int transportEnc_writeASC(HANDLE_FDK_BITSTREAM asc, CODER_CONFIG *config, + CSTpCallBacks *cb); + +/* Defintion of flags that can be passed to transportEnc_Open() */ +#define TP_FLAG_MPEG4 1 /** MPEG4 (instead of MPEG2) */ +#define TP_FLAG_LATM_AMV 2 /** LATM AudioMuxVersion */ +#define TP_FLAG_LATM_AMVA 4 /** LATM AudioMuxVersionA */ + +/** + * \brief Allocate transport encoder. + * \param phTpEnc Pointer to transport encoder handle. + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_Open(HANDLE_TRANSPORTENC *phTpEnc); + +/** + * \brief Init transport encoder. + * \param bsBuffer Pointer to transport encoder. + * \param bsBuffer Pointer to bitstream buffer. + * \param bsBufferSize Size in bytes of bsBuffer. + * \param transportFmt Format of the transport to be written. + * \param config Pointer to a valid CODER_CONFIG struct. + * \param flags Transport encoder flags. + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_Init(HANDLE_TRANSPORTENC hTpEnc, + UCHAR *bsBuffer, INT bsBufferSize, + TRANSPORT_TYPE transportFmt, + CODER_CONFIG *config, UINT flags); + +/** + * \brief Write additional bits in transport encoder. + * \param config Pointer to a valid CODER_CONFIG struct. + * \param nBits Number of additional bits. + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_AddOtherDataBits(HANDLE_TRANSPORTENC hTpEnc, + const int nBits); + +/** + * \brief Get transport encoder bitstream. + * \param hTp Pointer to a transport encoder handle. + * \return The handle to the requested FDK bitstream. + */ +HANDLE_FDK_BITSTREAM transportEnc_GetBitstream(HANDLE_TRANSPORTENC hTp); + +/** + * \brief Get amount of bits required by the transport headers. + * \param hTp Handle of transport encoder. + * \param auBits Amount of payload bits required for the current subframe. + * \return Error code. + */ +INT transportEnc_GetStaticBits(HANDLE_TRANSPORTENC hTp, int auBits); + +/** + * \brief Close transport encoder. This function assures that all + * allocated memory is freed. + * \param phTp Pointer to a previously allocated transport encoder handle. + */ +void transportEnc_Close(HANDLE_TRANSPORTENC *phTp); + +/** + * \brief Write one access unit. + * \param hTp Handle of transport encoder. + * \param total_bits Amount of total access unit bits. + * \param bufferFullness Value of current buffer fullness in bits. + * \param noConsideredChannels Number of bitrate wise considered channels (all + * minus LFE channels). + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_WriteAccessUnit(HANDLE_TRANSPORTENC hTp, + INT total_bits, + int bufferFullness, + int noConsideredChannels); + +/** + * \brief Inform the transportEnc layer that writing of access unit has + * finished. This function is required to be called when the encoder has + * finished writing one Access one Access Unit for bitstream + * housekeeping. + * \param hTp Transport handle. + * \param pBits Pointer to an int, where the current amount of frame bits is + * passed and where the current amount of subframe bits is returned. + * + * OR: This integer is modified by the amount of extra bit alignment that may + * occurr. + * + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_EndAccessUnit(HANDLE_TRANSPORTENC hTp, + int *pBits); + +/* + * \brief Get a payload frame. + * \param hTpEnc Transport encoder handle. + * \param nBytes Pointer to an int to hold the frame size in bytes. Returns + * zero if currently there is no complete frame for output (number of sub frames + * > 1). + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_GetFrame(HANDLE_TRANSPORTENC hTpEnc, + int *nbytes); + +/* ADTS CRC support */ + +/** + * \brief Set current bitstream position as start of a new data region. + * \param hTpEnc Transport encoder handle. + * \param mBits Size in bits of the data region. Set to 0 if it should not be + * of a fixed size. + * \return Data region ID, which should be used when calling + * transportEnc_CrcEndReg(). + */ +int transportEnc_CrcStartReg(HANDLE_TRANSPORTENC hTpEnc, int mBits); + +/** + * \brief Set end of data region. + * \param hTpEnc Transport encoder handle. + * \param reg Data region ID, opbtained from transportEnc_CrcStartReg(). + * \return void + */ +void transportEnc_CrcEndReg(HANDLE_TRANSPORTENC hTpEnc, int reg); + +/** + * \brief Get AudioSpecificConfig or StreamMuxConfig from transport + * encoder handle and write it to dataBuffer. + * \param hTpEnc Transport encoder handle. + * \param cc Pointer to the current and valid configuration contained + * in a CODER_CONFIG struct. + * \param dataBuffer Bitbuffer holding binary configuration. + * \param confType Pointer to an UINT where the configuration type is + * returned (0:ASC, 1:SMC). + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_GetConf(HANDLE_TRANSPORTENC hTpEnc, + CODER_CONFIG *cc, + FDK_BITSTREAM *dataBuffer, + UINT *confType); + +/** + * \brief Get information (version among other things) of the transport + * encoder library. + * \param info Pointer to an allocated LIB_INFO struct. + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_GetLibInfo(LIB_INFO *info); + +#endif /* #ifndef TPENC_LIB_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tp_version.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tp_version.h new file mode 100644 index 0000000000000..9f1aa22861593 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tp_version.h @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): + + Description: + +*******************************************************************************/ + +#if !defined(TP_VERSION_H) +#define TP_VERSION_H + +/* library info */ +#define TP_LIB_VL0 3 +#define TP_LIB_VL1 0 +#define TP_LIB_VL2 0 +#define TP_LIB_TITLE "MPEG Transport" +#ifdef __ANDROID__ +#define TP_LIB_BUILD_DATE "" +#define TP_LIB_BUILD_TIME "" +#else +#define TP_LIB_BUILD_DATE __DATE__ +#define TP_LIB_BUILD_TIME __TIME__ +#endif +#endif /* !defined(TP_VERSION_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adif.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adif.cpp new file mode 100644 index 0000000000000..b281effcdb83c --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adif.cpp @@ -0,0 +1,186 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): + + Description: ADIF Transport Headers writing + +*******************************************************************************/ + +#include "tpenc_adif.h" + +#include "tpenc_lib.h" +#include "tpenc_asc.h" + +int adifWrite_EncodeHeader(ADIF_INFO *adif, HANDLE_FDK_BITSTREAM hBs, + INT adif_buffer_fullness) { + /* ADIF/PCE/ADTS definitions */ + const char adifId[5] = "ADIF"; + const int copyRightIdPresent = 0; + const int originalCopy = 0; + const int home = 0; + int err = 0; + + int i; + + INT totalBitRate = adif->bitRate; + + if (adif->headerWritten) return 0; + + /* Align inside PCE with respect to the first bit of the header */ + UINT alignAnchor = FDKgetValidBits(hBs); + + /* Signal variable bitrate if buffer fullnes exceeds 20 bit */ + adif->bVariableRate = (adif_buffer_fullness >= (INT)(0x1 << 20)) ? 1 : 0; + + FDKwriteBits(hBs, adifId[0], 8); + FDKwriteBits(hBs, adifId[1], 8); + FDKwriteBits(hBs, adifId[2], 8); + FDKwriteBits(hBs, adifId[3], 8); + + FDKwriteBits(hBs, copyRightIdPresent ? 1 : 0, 1); + + if (copyRightIdPresent) { + for (i = 0; i < 72; i++) { + FDKwriteBits(hBs, 0, 1); + } + } + FDKwriteBits(hBs, originalCopy ? 1 : 0, 1); + FDKwriteBits(hBs, home ? 1 : 0, 1); + FDKwriteBits(hBs, adif->bVariableRate ? 1 : 0, 1); + FDKwriteBits(hBs, totalBitRate, 23); + + /* we write only one PCE at the moment */ + FDKwriteBits(hBs, 0, 4); + + if (!adif->bVariableRate) { + FDKwriteBits(hBs, adif_buffer_fullness, 20); + } + /* Write PCE */ + transportEnc_writePCE(hBs, adif->cm, adif->samplingRate, adif->instanceTag, + adif->profile, adif->matrixMixdownA, + (adif->pseudoSurroundEnable) ? 1 : 0, alignAnchor); + + return err; +} + +int adifWrite_GetHeaderBits(ADIF_INFO *adif) { + /* ADIF definitions */ + const int copyRightIdPresent = 0; + + if (adif->headerWritten) return 0; + + int bits = 0; + + bits += 8 * 4; /* ADIF ID */ + + bits += 1; /* Copyright present */ + + if (copyRightIdPresent) bits += 72; /* Copyright ID */ + + bits += 26; + + bits += 4; /* Number of PCE's */ + + if (!adif->bVariableRate) { + bits += 20; + } + + /* write PCE */ + bits = transportEnc_GetPCEBits(adif->cm, adif->matrixMixdownA, bits); + + return bits; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adif.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adif.h new file mode 100644 index 0000000000000..e001afc2eb0f7 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adif.h @@ -0,0 +1,146 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Alex Goeschel + + Description: Transport Headers support + +*******************************************************************************/ + +#ifndef TPENC_ADIF_H +#define TPENC_ADIF_H + +#include "machine_type.h" +#include "FDK_bitstream.h" + +#include "tp_data.h" + +typedef struct { + CHANNEL_MODE cm; + INT samplingRate; + INT bitRate; + int profile; + int bVariableRate; + int instanceTag; + int headerWritten; + int matrixMixdownA; + int pseudoSurroundEnable; + +} ADIF_INFO; + +/** + * \brief encodes ADIF Header + * + * \param adif pointer to ADIF_INFO structure + * \param hBitStream handle of bitstream, where the ADIF header is written into + * \param adif_buffer_fullness buffer fullness value for the ADIF header + * + * \return 0 on success + */ +int adifWrite_EncodeHeader(ADIF_INFO *adif, HANDLE_FDK_BITSTREAM hBitStream, + INT adif_buffer_fullness); + +/** + * \brief Get bit demand of a ADIF header + * + * \param adif pointer to ADIF_INFO structure + * + * \return amount of bits required to write the ADIF header according to the + * data contained in the adif parameter + */ +int adifWrite_GetHeaderBits(ADIF_INFO *adif); + +#endif /* TPENC_ADIF_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adts.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adts.cpp new file mode 100644 index 0000000000000..3f7e62c91f03a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adts.cpp @@ -0,0 +1,319 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Alex Groeschel + + Description: ADTS Transport Headers support + +*******************************************************************************/ + +#include "tpenc_adts.h" + +#include "tpenc_lib.h" +#include "tpenc_asc.h" + +int adtsWrite_CrcStartReg( + HANDLE_ADTS pAdts, /*!< pointer to adts stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ +) { + if (pAdts->protection_absent) { + return 0; + } + return (FDKcrcStartReg(&pAdts->crcInfo, hBs, mBits)); +} + +void adtsWrite_CrcEndReg( + HANDLE_ADTS pAdts, /*!< pointer to adts crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ +) { + if (pAdts->protection_absent == 0) { + FDKcrcEndReg(&pAdts->crcInfo, hBs, reg); + } +} + +int adtsWrite_GetHeaderBits(HANDLE_ADTS hAdts) { + int bits = 0; + + if (hAdts->currentBlock == 0) { + /* Static and variable header bits */ + bits = 56; + if (!hAdts->protection_absent) { + /* Add header/ single raw data block CRC bits */ + bits += 16; + if (hAdts->num_raw_blocks > 0) { + /* Add bits of raw data block position markers */ + bits += (hAdts->num_raw_blocks) * 16; + } + } + } + if (!hAdts->protection_absent && hAdts->num_raw_blocks > 0) { + /* Add raw data block CRC bits. Not really part of the header, put they + * cause bit overhead to be accounted. */ + bits += 16; + } + + hAdts->headerBits = bits; + + return bits; +} + +INT adtsWrite_Init(HANDLE_ADTS hAdts, CODER_CONFIG *config) { + /* Sanity checks */ + if (config->nSubFrames < 1 || config->nSubFrames > 4 || + (int)config->aot > 4 || (int)config->aot < 1) { + return -1; + } + + /* fixed header */ + if (config->flags & CC_MPEG_ID) { + hAdts->mpeg_id = 0; /* MPEG 4 */ + } else { + hAdts->mpeg_id = 1; /* MPEG 2 */ + } + hAdts->layer = 0; + hAdts->protection_absent = !(config->flags & CC_PROTECTION); + hAdts->profile = ((int)config->aot) - 1; + hAdts->sample_freq_index = getSamplingRateIndex(config->samplingRate, 4); + hAdts->sample_freq = config->samplingRate; + hAdts->private_bit = 0; + hAdts->channel_mode = config->channelMode; + hAdts->original = 0; + hAdts->home = 0; + /* variable header */ + hAdts->copyright_id = 0; + hAdts->copyright_start = 0; + + hAdts->num_raw_blocks = config->nSubFrames - 1; /* 0 means 1 raw data block */ + + hAdts->channel_config_zero = config->channelConfigZero; + + FDKcrcInit(&hAdts->crcInfo, 0x8005, 0xFFFF, 16); + + hAdts->currentBlock = 0; + + return 0; +} + +int adtsWrite_EncodeHeader(HANDLE_ADTS hAdts, HANDLE_FDK_BITSTREAM hBitStream, + int buffer_fullness, int frame_length) { + INT crcIndex = 0; + + hAdts->headerBits = adtsWrite_GetHeaderBits(hAdts); + + FDK_ASSERT(((frame_length + hAdts->headerBits) / 8) < 0x2000); /*13 bit*/ + FDK_ASSERT(buffer_fullness < 0x800); /* 11 bit */ + + if (!hAdts->protection_absent) { + FDKcrcReset(&hAdts->crcInfo); + } + + if (hAdts->currentBlock == 0) { + FDKresetBitbuffer(hBitStream, BS_WRITER); + } + + hAdts->subFrameStartBit = FDKgetValidBits(hBitStream); + + /* Skip new header if this is raw data block 1..n */ + if (hAdts->currentBlock == 0) { + FDKresetBitbuffer(hBitStream, BS_WRITER); + + if (hAdts->num_raw_blocks == 0) { + crcIndex = adtsWrite_CrcStartReg(hAdts, hBitStream, 0); + } + + /* fixed header */ + FDKwriteBits(hBitStream, 0xFFF, 12); + FDKwriteBits(hBitStream, hAdts->mpeg_id, 1); + FDKwriteBits(hBitStream, hAdts->layer, 2); + FDKwriteBits(hBitStream, hAdts->protection_absent, 1); + FDKwriteBits(hBitStream, hAdts->profile, 2); + FDKwriteBits(hBitStream, hAdts->sample_freq_index, 4); + FDKwriteBits(hBitStream, hAdts->private_bit, 1); + FDKwriteBits( + hBitStream, + getChannelConfig(hAdts->channel_mode, hAdts->channel_config_zero), 3); + FDKwriteBits(hBitStream, hAdts->original, 1); + FDKwriteBits(hBitStream, hAdts->home, 1); + /* variable header */ + FDKwriteBits(hBitStream, hAdts->copyright_id, 1); + FDKwriteBits(hBitStream, hAdts->copyright_start, 1); + FDKwriteBits(hBitStream, (frame_length + hAdts->headerBits) >> 3, 13); + FDKwriteBits(hBitStream, buffer_fullness, 11); + FDKwriteBits(hBitStream, hAdts->num_raw_blocks, 2); + + if (!hAdts->protection_absent) { + int i; + + /* End header CRC portion for single raw data block and write dummy zero + * values for unknown fields. */ + if (hAdts->num_raw_blocks == 0) { + adtsWrite_CrcEndReg(hAdts, hBitStream, crcIndex); + } else { + for (i = 0; i < hAdts->num_raw_blocks; i++) { + FDKwriteBits(hBitStream, 0, 16); + } + } + FDKwriteBits(hBitStream, 0, 16); + } + } /* End of ADTS header */ + + return 0; +} + +void adtsWrite_EndRawDataBlock(HANDLE_ADTS hAdts, HANDLE_FDK_BITSTREAM hBs, + int *pBits) { + if (!hAdts->protection_absent) { + FDK_BITSTREAM bsWriter; + + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, + BS_WRITER); + FDKpushFor(&bsWriter, 56); + + if (hAdts->num_raw_blocks == 0) { + FDKwriteBits(&bsWriter, FDKcrcGetCRC(&hAdts->crcInfo), 16); + } else { + int distance; + + /* Write CRC of current raw data block */ + FDKwriteBits(hBs, FDKcrcGetCRC(&hAdts->crcInfo), 16); + + /* Write distance to current data block */ + if (hAdts->currentBlock < hAdts->num_raw_blocks) { + FDKpushFor(&bsWriter, hAdts->currentBlock * 16); + distance = + FDKgetValidBits(hBs) - (56 + (hAdts->num_raw_blocks) * 16 + 16); + FDKwriteBits(&bsWriter, distance >> 3, 16); + } + } + FDKsyncCache(&bsWriter); + } + + /* Write total frame lenth for multiple raw data blocks and header CRC */ + if (hAdts->num_raw_blocks > 0 && + hAdts->currentBlock == hAdts->num_raw_blocks) { + FDK_BITSTREAM bsWriter; + int crcIndex = 0; + + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, + BS_WRITER); + + if (!hAdts->protection_absent) { + FDKcrcReset(&hAdts->crcInfo); + crcIndex = FDKcrcStartReg(&hAdts->crcInfo, &bsWriter, 0); + } + /* Write total frame length */ + FDKpushFor(&bsWriter, 56 - 28 + 2); + FDKwriteBits(&bsWriter, FDKgetValidBits(hBs) >> 3, 13); + + /* Write header CRC */ + if (!hAdts->protection_absent) { + FDKpushFor(&bsWriter, 11 + 2 + (hAdts->num_raw_blocks) * 16); + FDKcrcEndReg(&hAdts->crcInfo, &bsWriter, crcIndex); + FDKwriteBits(&bsWriter, FDKcrcGetCRC(&hAdts->crcInfo), 16); + } + FDKsyncCache(&bsWriter); + } + + /* Correct *pBits to reflect the amount of bits of the current subframe */ + *pBits -= hAdts->subFrameStartBit; + if (!hAdts->protection_absent && hAdts->num_raw_blocks > 0) { + /* Fixup CRC bits, since they come after each raw data block */ + *pBits += 16; + } + hAdts->currentBlock++; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adts.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adts.h new file mode 100644 index 0000000000000..fe863069efe33 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_adts.h @@ -0,0 +1,208 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Alex Groeschel + + Description: ADTS Transport writer + +*******************************************************************************/ + +#ifndef TPENC_ADTS_H +#define TPENC_ADTS_H + +#include "tp_data.h" + +#include "FDK_crc.h" + +typedef struct { + INT sample_freq; + CHANNEL_MODE channel_mode; + UCHAR decoderCanDoMpeg4; + UCHAR mpeg_id; + UCHAR layer; + UCHAR protection_absent; + UCHAR profile; + UCHAR sample_freq_index; + UCHAR private_bit; + UCHAR original; + UCHAR home; + UCHAR copyright_id; + UCHAR copyright_start; + USHORT frame_length; + UCHAR num_raw_blocks; + UCHAR BufferFullnesStartFlag; + UCHAR channel_config_zero; + int headerBits; /*!< Header bit demand for the current raw data block */ + int currentBlock; /*!< Index of current raw data block */ + int subFrameStartBit; /*!< Bit position where the current raw data block + begins */ + FDK_CRCINFO crcInfo; +} STRUCT_ADTS; + +typedef STRUCT_ADTS *HANDLE_ADTS; + +/** + * \brief Initialize ADTS data structure + * + * \param hAdts ADTS data handle + * \param config a valid CODER_CONFIG struct from where the required + * information for the ADTS header is extrated from + * + * \return 0 in case of success. + */ +INT adtsWrite_Init(HANDLE_ADTS hAdts, CODER_CONFIG *config); + +/** + * \brief Get the total bit overhead caused by ADTS + * + * \hAdts handle to ADTS data + * + * \return Amount of additional bits required for the current raw data block + */ +int adtsWrite_GetHeaderBits(HANDLE_ADTS hAdts); + +/** + * \brief Write an ADTS header into the given bitstream. May not write a header + * in case of multiple raw data blocks. + * + * \param hAdts ADTS data handle + * \param hBitStream bitstream handle into which the ADTS may be written into + * \param buffer_fullness the buffer fullness value for the ADTS header + * \param the current raw data block length + * + * \return 0 in case of success. + */ +INT adtsWrite_EncodeHeader(HANDLE_ADTS hAdts, HANDLE_FDK_BITSTREAM hBitStream, + int bufferFullness, int frame_length); +/** + * \brief Finish a ADTS raw data block + * + * \param hAdts ADTS data handle + * \param hBs bitstream handle into which the ADTS may be written into + * \param pBits a pointer to a integer holding the current bitstream buffer bit + * count, which is corrected to the current raw data block boundary. + * + */ +void adtsWrite_EndRawDataBlock(HANDLE_ADTS hAdts, HANDLE_FDK_BITSTREAM hBs, + int *bits); + +/** + * \brief Start CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if + * there are less than mBits bits available. If mBits is negative no zero + * padding is done. If mBits is zero the memory for the buffer is + * allocated dynamically, the number of bits is not limited. + * + * \param pAdts ADTS data handle + * \param hBs bitstream handle of which the CRC region ends + * \param mBits limit of number of bits to be considered for the requested CRC + * region + * + * \return ID for the created region, -1 in case of an error + */ +int adtsWrite_CrcStartReg(HANDLE_ADTS pAdts, HANDLE_FDK_BITSTREAM hBs, + int mBits); + +/** + * \brief Ends CRC region identified by reg + * + * \param pAdts ADTS data handle + * \param hBs bitstream handle of which the CRC region ends + * \param reg a CRC region ID returned previously by adtsWrite_CrcStartReg() + */ +void adtsWrite_CrcEndReg(HANDLE_ADTS pAdts, HANDLE_FDK_BITSTREAM hBs, int reg); + +#endif /* TPENC_ADTS_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_asc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_asc.cpp new file mode 100644 index 0000000000000..9591ba8dbf4a9 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_asc.cpp @@ -0,0 +1,996 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): + + Description: + +*******************************************************************************/ + +#include "tp_data.h" + +#include "tpenc_lib.h" +#include "tpenc_asc.h" +#include "FDK_bitstream.h" +#include "genericStds.h" + +#include "FDK_crc.h" + +#define PCE_HEIGHT_EXT_SYNC (0xAC) +#define HEIGHT_NORMAL 0 +#define HEIGHT_TOP 1 +#define HEIGHT_BOTTOM 2 +#define MAX_FRONT_ELEMENTS 8 +#define MAX_SIDE_ELEMENTS 3 +#define MAX_BACK_ELEMENTS 4 + +/** + * Describe additional PCE height information for front, side and back channel + * elements. + */ +typedef struct { + UCHAR + num_front_height_channel_elements[2]; /*!< Number of front channel + elements in top [0] and bottom + [1] plane. */ + UCHAR num_side_height_channel_elements[2]; /*!< Number of side channel + elements in top [0] and bottom + [1] plane. */ + UCHAR num_back_height_channel_elements[2]; /*!< Number of back channel + elements in top [0] and bottom + [1] plane. */ +} PCE_HEIGHT_NUM; + +/** + * Describe a PCE based on placed channel elements and element type sequence. + */ +typedef struct { + UCHAR num_front_channel_elements; /*!< Number of front channel elements. */ + UCHAR num_side_channel_elements; /*!< Number of side channel elements. */ + UCHAR num_back_channel_elements; /*!< Number of back channel elements. */ + UCHAR num_lfe_channel_elements; /*!< Number of lfe channel elements. */ + const MP4_ELEMENT_ID + *pEl_type; /*!< List contains sequence describing the elements + in present channel mode. (MPEG order) */ + const PCE_HEIGHT_NUM *pHeight_num; +} PCE_CONFIGURATION; + +/** + * Map an incoming channel mode to a existing PCE configuration entry. + */ +typedef struct { + CHANNEL_MODE channel_mode; /*!< Present channel mode. */ + PCE_CONFIGURATION + pce_configuration; /*!< Program config element description. */ + +} CHANNEL_CONFIGURATION; + +/** + * The following arrays provide the IDs of the consecutive elements for each + * mode. + */ +static const MP4_ELEMENT_ID elType_1[] = {ID_SCE}; +static const MP4_ELEMENT_ID elType_2[] = {ID_CPE}; +static const MP4_ELEMENT_ID elType_1_2[] = {ID_SCE, ID_CPE}; +static const MP4_ELEMENT_ID elType_1_2_1[] = {ID_SCE, ID_CPE, ID_SCE}; +static const MP4_ELEMENT_ID elType_1_2_2[] = {ID_SCE, ID_CPE, ID_CPE}; +static const MP4_ELEMENT_ID elType_1_2_2_1[] = {ID_SCE, ID_CPE, ID_CPE, ID_LFE}; +static const MP4_ELEMENT_ID elType_1_2_2_2_1[] = {ID_SCE, ID_CPE, ID_CPE, + ID_CPE, ID_LFE}; +static const MP4_ELEMENT_ID elType_6_1[] = {ID_SCE, ID_CPE, ID_CPE, ID_SCE, + ID_LFE}; +static const MP4_ELEMENT_ID elType_7_1_back[] = {ID_SCE, ID_CPE, ID_CPE, ID_CPE, + ID_LFE}; +static const MP4_ELEMENT_ID elType_7_1_top_front[] = {ID_SCE, ID_CPE, ID_CPE, + ID_LFE, ID_CPE}; +static const MP4_ELEMENT_ID elType_7_1_rear_surround[] = { + ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE}; +static const MP4_ELEMENT_ID elType_7_1_front_center[] = {ID_SCE, ID_CPE, ID_CPE, + ID_CPE, ID_LFE}; + +/** + * The following arrays provide information on how many front, side and back + * elements are assigned to the top or bottom plane for each mode that comprises + * height information. + */ +static const PCE_HEIGHT_NUM heightNum_7_1_top_front = {{1, 0}, {0, 0}, {0, 0}}; + +/** + * \brief Table contains all supported channel modes and according PCE + configuration description. + * + * The mode identifier is followed by the number of front, side, back, and LFE + elements. + * These are followed by a pointer to the IDs of the consecutive elements + (ID_SCE, ID_CPE, ID_LFE). + * + * For some modes (MODE_7_1_TOP_FRONT and MODE_22_2) additional height + information is transmitted. + * In this case the additional pointer provides information on how many front, + side and back elements + * are assigned to the top or bottom plane.The elements are arranged in the + following order: normal height (front, side, back, LFE), top height (front, + side, back), bottom height (front, side, back). + * + * + * E.g. MODE_7_1_TOP_FRONT means: + * - 3 elements are front channel elements. + * - 0 elements are side channel elements. + * - 1 element is back channel element. + * - 1 element is an LFE channel element. + * - the element order is ID_SCE, ID_CPE, ID_CPE, + ID_LFE, ID_CPE. + * - 1 of the front elements is in the top plane. + * + * This leads to the following mapping for the cconsecutive elements in the + MODE_7_1_TOP_FRONT bitstream: + * - ID_SCE -> normal height front, + - ID_CPE -> normal height front, + - ID_CPE -> normal height back, + - ID_LFE -> normal height LFE, + - ID_CPE -> top height front. + */ +static const CHANNEL_CONFIGURATION pceConfigTab[] = { + {MODE_1, + {1, 0, 0, 0, elType_1, + NULL}}, /* don't transmit height information in this mode */ + {MODE_2, + {1, 0, 0, 0, elType_2, + NULL}}, /* don't transmit height information in this mode */ + {MODE_1_2, + {2, 0, 0, 0, elType_1_2, + NULL}}, /* don't transmit height information in this mode */ + {MODE_1_2_1, + {2, 0, 1, 0, elType_1_2_1, + NULL}}, /* don't transmit height information in this mode */ + {MODE_1_2_2, + {2, 0, 1, 0, elType_1_2_2, + NULL}}, /* don't transmit height information in this mode */ + {MODE_1_2_2_1, + {2, 0, 1, 1, elType_1_2_2_1, + NULL}}, /* don't transmit height information in this mode */ + {MODE_1_2_2_2_1, + {3, 0, 1, 1, elType_1_2_2_2_1, + NULL}}, /* don't transmit height information in this mode */ + + {MODE_6_1, + {2, 0, 2, 1, elType_6_1, + NULL}}, /* don't transmit height information in this mode */ + {MODE_7_1_BACK, + {2, 0, 2, 1, elType_7_1_back, + NULL}}, /* don't transmit height information in this mode */ + {MODE_7_1_TOP_FRONT, + {3, 0, 1, 1, elType_7_1_top_front, &heightNum_7_1_top_front}}, + + {MODE_7_1_REAR_SURROUND, + {2, 0, 2, 1, elType_7_1_rear_surround, + NULL}}, /* don't transmit height information in this mode */ + {MODE_7_1_FRONT_CENTER, + {3, 0, 1, 1, elType_7_1_front_center, + NULL}} /* don't transmit height information in this mode */ +}; + +/** + * \brief Get program config element description for existing channel mode. + * + * \param channel_mode Current channel mode. + * + * \return + * - Pointer to PCE_CONFIGURATION entry, on success. + * - NULL, on failure. + */ +static const PCE_CONFIGURATION *getPceEntry(const CHANNEL_MODE channel_mode) { + UINT i; + const PCE_CONFIGURATION *pce_config = NULL; + + for (i = 0; i < (sizeof(pceConfigTab) / sizeof(CHANNEL_CONFIGURATION)); i++) { + if (pceConfigTab[i].channel_mode == channel_mode) { + pce_config = &pceConfigTab[i].pce_configuration; + break; + } + } + + return pce_config; +} + +int getChannelConfig(const CHANNEL_MODE channel_mode, + const UCHAR channel_config_zero) { + INT chan_config = 0; + + if (channel_config_zero != 0) { + chan_config = 0; + } else { + switch (channel_mode) { + case MODE_1: + chan_config = 1; + break; + case MODE_2: + chan_config = 2; + break; + case MODE_1_2: + chan_config = 3; + break; + case MODE_1_2_1: + chan_config = 4; + break; + case MODE_1_2_2: + chan_config = 5; + break; + case MODE_1_2_2_1: + chan_config = 6; + break; + case MODE_1_2_2_2_1: + chan_config = 7; + break; + case MODE_6_1: + chan_config = 11; + break; + case MODE_7_1_BACK: + chan_config = 12; + break; + case MODE_7_1_TOP_FRONT: + chan_config = 14; + break; + default: + chan_config = 0; + } + } + + return chan_config; +} + +CHANNEL_MODE transportEnc_GetChannelMode(int noChannels) { + CHANNEL_MODE chMode; + + if (noChannels <= 8 && noChannels > 0) + chMode = (CHANNEL_MODE)( + (noChannels == 8) ? 7 + : noChannels); /* see : iso/mpeg4 v1 audio subpart1*/ + else + chMode = MODE_UNKNOWN; + + return chMode; +} + +int transportEnc_writePCE(HANDLE_FDK_BITSTREAM hBs, CHANNEL_MODE channelMode, + INT sampleRate, int instanceTagPCE, int profile, + int matrixMixdownA, int pseudoSurroundEnable, + UINT alignAnchor) { + int sampleRateIndex, i; + const PCE_CONFIGURATION *config = NULL; + const MP4_ELEMENT_ID *pEl_list = NULL; + UCHAR cpeCnt = 0, sceCnt = 0, lfeCnt = 0, frntCnt = 0, sdCnt = 0, bckCnt = 0, + isCpe = 0, tag = 0, normalFrontEnd = 0, normalSideEnd = 0, + normalBackEnd = 0, topFrontEnd = 0, topSideEnd = 0, topBackEnd = 0, + bottomFrontEnd = 0, bottomSideEnd = 0; +#ifdef FDK_ASSERT_ENABLE + UCHAR bottomBackEnd = 0; +#endif + enum elementDepth { FRONT, SIDE, BACK } elDepth; + + sampleRateIndex = getSamplingRateIndex(sampleRate, 4); + if (sampleRateIndex == 15) { + return -1; + } + + if ((config = getPceEntry(channelMode)) == NULL) { + return -1; + } + + FDK_ASSERT(config->num_front_channel_elements <= MAX_FRONT_ELEMENTS); + FDK_ASSERT(config->num_side_channel_elements <= MAX_SIDE_ELEMENTS); + FDK_ASSERT(config->num_back_channel_elements <= MAX_BACK_ELEMENTS); + + UCHAR frontIsCpe[MAX_FRONT_ELEMENTS] = {0}, + frontTag[MAX_FRONT_ELEMENTS] = {0}, sideIsCpe[MAX_SIDE_ELEMENTS] = {0}, + sideTag[MAX_SIDE_ELEMENTS] = {0}, backIsCpe[MAX_BACK_ELEMENTS] = {0}, + backTag[MAX_BACK_ELEMENTS] = {0}; + + /* Write general information */ + + FDKwriteBits(hBs, instanceTagPCE, 4); /* Element instance tag */ + FDKwriteBits(hBs, profile, 2); /* Object type */ + FDKwriteBits(hBs, sampleRateIndex, 4); /* Sample rate index*/ + + FDKwriteBits(hBs, config->num_front_channel_elements, + 4); /* Front channel Elements */ + FDKwriteBits(hBs, config->num_side_channel_elements, + 4); /* No Side Channel Elements */ + FDKwriteBits(hBs, config->num_back_channel_elements, + 4); /* No Back channel Elements */ + FDKwriteBits(hBs, config->num_lfe_channel_elements, + 2); /* No Lfe channel elements */ + + FDKwriteBits(hBs, 0, 3); /* No assoc data elements */ + FDKwriteBits(hBs, 0, 4); /* No valid cc elements */ + FDKwriteBits(hBs, 0, 1); /* Mono mixdown present */ + FDKwriteBits(hBs, 0, 1); /* Stereo mixdown present */ + + if (matrixMixdownA != 0 && + ((channelMode == MODE_1_2_2) || (channelMode == MODE_1_2_2_1))) { + FDKwriteBits(hBs, 1, 1); /* Matrix mixdown present */ + FDKwriteBits(hBs, (matrixMixdownA - 1) & 0x3, 2); /* matrix_mixdown_idx */ + FDKwriteBits(hBs, (pseudoSurroundEnable) ? 1 : 0, + 1); /* pseudo_surround_enable */ + } else { + FDKwriteBits(hBs, 0, 1); /* Matrix mixdown not present */ + } + + if (config->pHeight_num != NULL) { + /* we have up to three different height levels, and in each height level we + * may have front, side and back channels. We need to know where each + * section ends to correctly count the tags */ + normalFrontEnd = config->num_front_channel_elements - + config->pHeight_num->num_front_height_channel_elements[0] - + config->pHeight_num->num_front_height_channel_elements[1]; + normalSideEnd = normalFrontEnd + config->num_side_channel_elements - + config->pHeight_num->num_side_height_channel_elements[0] - + config->pHeight_num->num_side_height_channel_elements[1]; + normalBackEnd = normalSideEnd + config->num_back_channel_elements - + config->pHeight_num->num_back_height_channel_elements[0] - + config->pHeight_num->num_back_height_channel_elements[1]; + + topFrontEnd = + normalBackEnd + config->num_lfe_channel_elements + + config->pHeight_num->num_front_height_channel_elements[0]; /* only + normal + height + LFEs + assumed */ + topSideEnd = + topFrontEnd + config->pHeight_num->num_side_height_channel_elements[0]; + topBackEnd = + topSideEnd + config->pHeight_num->num_back_height_channel_elements[0]; + + bottomFrontEnd = + topBackEnd + config->pHeight_num->num_front_height_channel_elements[1]; + bottomSideEnd = bottomFrontEnd + + config->pHeight_num->num_side_height_channel_elements[1]; +#ifdef FDK_ASSERT_ENABLE + bottomBackEnd = bottomSideEnd + + config->pHeight_num->num_back_height_channel_elements[1]; +#endif + + } else { + /* we have only one height level, so we don't care about top or bottom */ + normalFrontEnd = config->num_front_channel_elements; + normalSideEnd = normalFrontEnd + config->num_side_channel_elements; + normalBackEnd = normalSideEnd + config->num_back_channel_elements; + } + + /* assign cpe and tag information to either front, side or back channels */ + + pEl_list = config->pEl_type; + + for (i = 0; i < config->num_front_channel_elements + + config->num_side_channel_elements + + config->num_back_channel_elements + + config->num_lfe_channel_elements; + i++) { + if (*pEl_list == ID_LFE) { + pEl_list++; + continue; + } + isCpe = (*pEl_list++ == ID_CPE) ? 1 : 0; + tag = (isCpe) ? cpeCnt++ : sceCnt++; + + if (i < normalFrontEnd) + elDepth = FRONT; + else if (i < normalSideEnd) + elDepth = SIDE; + else if (i < normalBackEnd) + elDepth = BACK; + else if (i < topFrontEnd) + elDepth = FRONT; + else if (i < topSideEnd) + elDepth = SIDE; + else if (i < topBackEnd) + elDepth = BACK; + else if (i < bottomFrontEnd) + elDepth = FRONT; + else if (i < bottomSideEnd) + elDepth = SIDE; + else { + elDepth = BACK; + FDK_ASSERT(i < bottomBackEnd); /* won't fail if implementation of pce + configuration table is correct */ + } + + switch (elDepth) { + case FRONT: + FDK_ASSERT(frntCnt < config->num_front_channel_elements); + frontIsCpe[frntCnt] = isCpe; + frontTag[frntCnt++] = tag; + break; + case SIDE: + FDK_ASSERT(sdCnt < config->num_side_channel_elements); + sideIsCpe[sdCnt] = isCpe; + sideTag[sdCnt++] = tag; + break; + case BACK: + FDK_ASSERT(bckCnt < config->num_back_channel_elements); + backIsCpe[bckCnt] = isCpe; + backTag[bckCnt++] = tag; + break; + } + } + + /* Write front channel isCpe and tags */ + for (i = 0; i < config->num_front_channel_elements; i++) { + FDKwriteBits(hBs, frontIsCpe[i], 1); + FDKwriteBits(hBs, frontTag[i], 4); + } + /* Write side channel isCpe and tags */ + for (i = 0; i < config->num_side_channel_elements; i++) { + FDKwriteBits(hBs, sideIsCpe[i], 1); + FDKwriteBits(hBs, sideTag[i], 4); + } + /* Write back channel isCpe and tags */ + for (i = 0; i < config->num_back_channel_elements; i++) { + FDKwriteBits(hBs, backIsCpe[i], 1); + FDKwriteBits(hBs, backTag[i], 4); + } + /* Write LFE information */ + for (i = 0; i < config->num_lfe_channel_elements; i++) { + FDKwriteBits(hBs, lfeCnt++, 4); /* LFE channel Instance Tag. */ + } + + /* - num_valid_cc_elements always 0. + - num_assoc_data_elements always 0. */ + + /* Byte alignment: relative to alignAnchor + ADTS: align with respect to the first bit of the raw_data_block() + ADIF: align with respect to the first bit of the header + LATM: align with respect to the first bit of the ASC */ + FDKbyteAlign(hBs, alignAnchor); /* Alignment */ + + /* Write comment information */ + + if (config->pHeight_num != NULL) { + /* embed height information in comment field */ + + INT commentBytes = + 1 /* PCE_HEIGHT_EXT_SYNC */ + + ((((config->num_front_channel_elements + + config->num_side_channel_elements + + config->num_back_channel_elements) + << 1) + + 7) >> + 3) /* 2 bit height info per element, round up to full bytes */ + + 1; /* CRC */ + + FDKwriteBits(hBs, commentBytes, 8); /* comment size. */ + + FDK_CRCINFO crcInfo; /* CRC state info */ + INT crcReg; + + FDKcrcInit(&crcInfo, 0x07, 0xFF, 8); + crcReg = FDKcrcStartReg(&crcInfo, hBs, 0); + + FDKwriteBits(hBs, PCE_HEIGHT_EXT_SYNC, 8); /* indicate height extension */ + + /* front channel height information */ + for (i = 0; + i < config->num_front_channel_elements - + config->pHeight_num->num_front_height_channel_elements[0] - + config->pHeight_num->num_front_height_channel_elements[1]; + i++) + FDKwriteBits(hBs, HEIGHT_NORMAL, 2); + for (i = 0; i < config->pHeight_num->num_front_height_channel_elements[0]; + i++) + FDKwriteBits(hBs, HEIGHT_TOP, 2); + for (i = 0; i < config->pHeight_num->num_front_height_channel_elements[1]; + i++) + FDKwriteBits(hBs, HEIGHT_BOTTOM, 2); + + /* side channel height information */ + for (i = 0; + i < config->num_side_channel_elements - + config->pHeight_num->num_side_height_channel_elements[0] - + config->pHeight_num->num_side_height_channel_elements[1]; + i++) + FDKwriteBits(hBs, HEIGHT_NORMAL, 2); + for (i = 0; i < config->pHeight_num->num_side_height_channel_elements[0]; + i++) + FDKwriteBits(hBs, HEIGHT_TOP, 2); + for (i = 0; i < config->pHeight_num->num_side_height_channel_elements[1]; + i++) + FDKwriteBits(hBs, HEIGHT_BOTTOM, 2); + + /* back channel height information */ + for (i = 0; + i < config->num_back_channel_elements - + config->pHeight_num->num_back_height_channel_elements[0] - + config->pHeight_num->num_back_height_channel_elements[1]; + i++) + FDKwriteBits(hBs, HEIGHT_NORMAL, 2); + for (i = 0; i < config->pHeight_num->num_back_height_channel_elements[0]; + i++) + FDKwriteBits(hBs, HEIGHT_TOP, 2); + for (i = 0; i < config->pHeight_num->num_back_height_channel_elements[1]; + i++) + FDKwriteBits(hBs, HEIGHT_BOTTOM, 2); + + FDKbyteAlign(hBs, alignAnchor); /* Alignment */ + + FDKcrcEndReg(&crcInfo, hBs, crcReg); + FDKwriteBits(hBs, FDKcrcGetCRC(&crcInfo), 8); + + } else { + FDKwriteBits(hBs, 0, + 8); /* Do no write any comment or height information. */ + } + + return 0; +} + +int transportEnc_GetPCEBits(CHANNEL_MODE channelMode, int matrixMixdownA, + int bits) { + const PCE_CONFIGURATION *config = NULL; + + if ((config = getPceEntry(channelMode)) == NULL) { + return -1; /* unsupported channelmapping */ + } + + bits += + 4 + 2 + 4; /* Element instance tag + Object type + Sample rate index */ + bits += 4 + 4 + 4 + 2; /* No (front + side + back + lfe channel) elements */ + bits += 3 + 4; /* No (assoc data + valid cc) elements */ + bits += 1 + 1 + 1; /* Mono + Stereo + Matrix mixdown present */ + + if (matrixMixdownA != 0 && + ((channelMode == MODE_1_2_2) || (channelMode == MODE_1_2_2_1))) { + bits += 3; /* matrix_mixdown_idx + pseudo_surround_enable */ + } + + bits += (1 + 4) * (INT)config->num_front_channel_elements; + bits += (1 + 4) * (INT)config->num_side_channel_elements; + bits += (1 + 4) * (INT)config->num_back_channel_elements; + bits += (4) * (INT)config->num_lfe_channel_elements; + + /* - num_valid_cc_elements always 0. + - num_assoc_data_elements always 0. */ + + if ((bits % 8) != 0) { + bits += (8 - (bits % 8)); /* Alignment */ + } + + bits += 8; /* Comment field bytes */ + + if (config->pHeight_num != NULL) { + /* Comment field (height extension) */ + + bits += + 8 /* PCE_HEIGHT_EXT_SYNC */ + + + ((config->num_front_channel_elements + + config->num_side_channel_elements + config->num_back_channel_elements) + << 1) /* 2 bit height info per element */ + + 8; /* CRC */ + + if ((bits % 8) != 0) { + bits += (8 - (bits % 8)); /* Alignment */ + } + } + + return bits; +} + +static void writeAot(HANDLE_FDK_BITSTREAM hBitstreamBuffer, + AUDIO_OBJECT_TYPE aot) { + int tmp = (int)aot; + + if (tmp > 31) { + FDKwriteBits(hBitstreamBuffer, AOT_ESCAPE, 5); + FDKwriteBits(hBitstreamBuffer, tmp - 32, 6); /* AudioObjectType */ + } else { + FDKwriteBits(hBitstreamBuffer, tmp, 5); + } +} + +static void writeSampleRate(HANDLE_FDK_BITSTREAM hBs, int sampleRate, + int nBits) { + int srIdx = getSamplingRateIndex(sampleRate, nBits); + + FDKwriteBits(hBs, srIdx, nBits); + if (srIdx == (1 << nBits) - 1) { + FDKwriteBits(hBs, sampleRate, 24); + } +} + +static int transportEnc_writeGASpecificConfig(HANDLE_FDK_BITSTREAM asc, + CODER_CONFIG *config, int extFlg, + UINT alignAnchor) { + int aot = config->aot; + int samplesPerFrame = config->samplesPerFrame; + + /* start of GASpecificConfig according to ISO/IEC 14496-3 Subpart 4, 4.4.1 */ + FDKwriteBits(asc, + ((samplesPerFrame == 960 || samplesPerFrame == 480) ? 1 : 0), + 1); /* frameLengthFlag: 1 for a 960/480 (I)MDCT, 0 for a 1024/512 + (I)MDCT*/ + FDKwriteBits(asc, 0, + 1); /* dependsOnCoreCoder: Sampling Rate Coder Specific, see in + ISO/IEC 14496-3 Subpart 4, 4.4.1 */ + FDKwriteBits(asc, extFlg, + 1); /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23 */ + + /* Write PCE if channel config is not 1-7 */ + if (getChannelConfig(config->channelMode, config->channelConfigZero) == 0) { + transportEnc_writePCE(asc, config->channelMode, config->samplingRate, 0, 1, + config->matrixMixdownA, + (config->flags & CC_PSEUDO_SURROUND) ? 1 : 0, + alignAnchor); + } + if ((aot == AOT_AAC_SCAL) || (aot == AOT_ER_AAC_SCAL)) { + FDKwriteBits(asc, 0, 3); /* layerNr */ + } + if (extFlg) { + if (aot == AOT_ER_BSAC) { + FDKwriteBits(asc, config->BSACnumOfSubFrame, 5); /* numOfSubFrame */ + FDKwriteBits(asc, config->BSAClayerLength, 11); /* layer_length */ + } + if ((aot == AOT_ER_AAC_LC) || (aot == AOT_ER_AAC_LTP) || + (aot == AOT_ER_AAC_SCAL) || (aot == AOT_ER_AAC_LD)) { + FDKwriteBits(asc, (config->flags & CC_VCB11) ? 1 : 0, + 1); /* aacSectionDataResillienceFlag */ + FDKwriteBits(asc, (config->flags & CC_RVLC) ? 1 : 0, + 1); /* aacScaleFactorDataResillienceFlag */ + FDKwriteBits(asc, (config->flags & CC_HCR) ? 1 : 0, + 1); /* aacSpectralDataResillienceFlag */ + } + FDKwriteBits(asc, 0, 1); /* extensionFlag3: reserved. Shall be '0' */ + } + return 0; +} + +static int transportEnc_writeELDSpecificConfig(HANDLE_FDK_BITSTREAM hBs, + CODER_CONFIG *config, + int epConfig, + CSTpCallBacks *cb) { + UINT frameLengthFlag = 0; + switch (config->samplesPerFrame) { + case 512: + case 256: + case 128: + case 64: + frameLengthFlag = 0; + break; + case 480: + case 240: + case 160: + case 120: + case 60: + frameLengthFlag = 1; + break; + } + + FDKwriteBits(hBs, frameLengthFlag, 1); + + FDKwriteBits(hBs, (config->flags & CC_VCB11) ? 1 : 0, 1); + FDKwriteBits(hBs, (config->flags & CC_RVLC) ? 1 : 0, 1); + FDKwriteBits(hBs, (config->flags & CC_HCR) ? 1 : 0, 1); + + FDKwriteBits(hBs, (config->flags & CC_SBR) ? 1 : 0, 1); /* SBR header flag */ + if ((config->flags & CC_SBR)) { + FDKwriteBits(hBs, (config->samplingRate == config->extSamplingRate) ? 0 : 1, + 1); /* Samplerate Flag */ + FDKwriteBits(hBs, (config->flags & CC_SBRCRC) ? 1 : 0, 1); /* SBR CRC flag*/ + + if (cb->cbSbr != NULL) { + const PCE_CONFIGURATION *pPce; + int e, sbrElementIndex = 0; + + pPce = getPceEntry(config->channelMode); + + for (e = 0; e < pPce->num_front_channel_elements + + pPce->num_side_channel_elements + + pPce->num_back_channel_elements + + pPce->num_lfe_channel_elements; + e++) { + if ((pPce->pEl_type[e] == ID_SCE) || (pPce->pEl_type[e] == ID_CPE)) { + cb->cbSbr(cb->cbSbrData, hBs, 0, 0, 0, config->aot, pPce->pEl_type[e], + sbrElementIndex, 0, 0, 0, NULL, 1); + sbrElementIndex++; + } + } + } + } + + if ((config->flags & CC_SAC) && (cb->cbSsc != NULL)) { + FDKwriteBits(hBs, ELDEXT_LDSAC, 4); + + const INT eldExtLen = + (cb->cbSsc(cb->cbSscData, NULL, config->aot, config->extSamplingRate, 0, + 0, 0, 0, 0, 0, NULL) + + 7) >> + 3; + INT cnt = eldExtLen; + + if (cnt < 0xF) { + FDKwriteBits(hBs, cnt, 4); + } else { + FDKwriteBits(hBs, 0xF, 4); + cnt -= 0xF; + + if (cnt < 0xFF) { + FDKwriteBits(hBs, cnt, 8); + } else { + FDKwriteBits(hBs, 0xFF, 8); + cnt -= 0xFF; + + FDK_ASSERT(cnt <= 0xFFFF); + FDKwriteBits(hBs, cnt, 16); + } + } + + cb->cbSsc(cb->cbSscData, hBs, config->aot, config->extSamplingRate, 0, 0, 0, + 0, 0, 0, NULL); + } + + if (config->downscaleSamplingRate != 0 && + config->downscaleSamplingRate != config->extSamplingRate) { + /* downscale active */ + + /* eldExtLenDsc: Number of bytes for the ELD downscale extension (srIdx + needs 1 byte + + downscaleSamplingRate needs additional 3 bytes) */ + int eldExtLenDsc = 1; + int downscaleSamplingRate = config->downscaleSamplingRate; + FDKwriteBits(hBs, ELDEXT_DOWNSCALEINFO, 4); /* ELDEXT_DOWNSCALEINFO */ + + if ((downscaleSamplingRate != 96000) && (downscaleSamplingRate != 88200) && + (downscaleSamplingRate != 64000) && (downscaleSamplingRate != 48000) && + (downscaleSamplingRate != 44100) && (downscaleSamplingRate != 32000) && + (downscaleSamplingRate != 24000) && (downscaleSamplingRate != 22050) && + (downscaleSamplingRate != 16000) && (downscaleSamplingRate != 12000) && + (downscaleSamplingRate != 11025) && (downscaleSamplingRate != 8000) && + (downscaleSamplingRate != 7350)) { + eldExtLenDsc = 4; /* length extends to 4 if downscaleSamplingRate's value + is not one of the listed values */ + } + + FDKwriteBits(hBs, eldExtLenDsc, 4); + writeSampleRate(hBs, downscaleSamplingRate, 4); + FDKwriteBits(hBs, 0x0, 4); /* fill_nibble */ + } + + FDKwriteBits(hBs, ELDEXT_TERM, 4); /* ELDEXT_TERM */ + + return 0; +} + +static int transportEnc_writeUsacSpecificConfig(HANDLE_FDK_BITSTREAM hBs, + int extFlag, CODER_CONFIG *cc, + CSTpCallBacks *cb) { + FDK_BITSTREAM usacConf; + int usacConfigBits = cc->rawConfigBits; + + if ((usacConfigBits <= 0) || + ((usacConfigBits + 7) / 8 > (int)sizeof(cc->rawConfig))) { + return TRANSPORTENC_UNSUPPORTED_FORMAT; + } + FDKinitBitStream(&usacConf, cc->rawConfig, BUFSIZE_DUMMY_VALUE, + usacConfigBits, BS_READER); + + for (; usacConfigBits > 0; usacConfigBits--) { + UINT tmp = FDKreadBit(&usacConf); + FDKwriteBits(hBs, tmp, 1); + } + FDKsyncCache(hBs); + + return TRANSPORTENC_OK; +} + +int transportEnc_writeASC(HANDLE_FDK_BITSTREAM asc, CODER_CONFIG *config, + CSTpCallBacks *cb) { + UINT extFlag = 0; + int err; + int epConfig = 0; + + /* Required for the PCE. */ + UINT alignAnchor = FDKgetValidBits(asc); + + /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23,39 */ + switch (config->aot) { + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LTP: + case AOT_ER_AAC_SCAL: + case AOT_ER_TWIN_VQ: + case AOT_ER_BSAC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + case AOT_USAC: + extFlag = 1; + break; + default: + break; + } + + if (config->sbrSignaling == SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent) + writeAot(asc, config->extAOT); + else + writeAot(asc, config->aot); + + /* In case of USAC it is the output not the core sampling rate */ + writeSampleRate(asc, config->samplingRate, 4); + + /* Try to guess a reasonable channel mode if not given */ + if (config->channelMode == MODE_INVALID) { + config->channelMode = transportEnc_GetChannelMode(config->noChannels); + if (config->channelMode == MODE_INVALID) return -1; + } + + FDKwriteBits( + asc, getChannelConfig(config->channelMode, config->channelConfigZero), 4); + + if (config->sbrSignaling == SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent) { + writeSampleRate(asc, config->extSamplingRate, 4); + writeAot(asc, config->aot); + } + + switch (config->aot) { + case AOT_AAC_MAIN: + case AOT_AAC_LC: + case AOT_AAC_SSR: + case AOT_AAC_LTP: + case AOT_AAC_SCAL: + case AOT_TWIN_VQ: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LTP: + case AOT_ER_AAC_SCAL: + case AOT_ER_TWIN_VQ: + case AOT_ER_BSAC: + case AOT_ER_AAC_LD: + err = + transportEnc_writeGASpecificConfig(asc, config, extFlag, alignAnchor); + if (err) return err; + break; + case AOT_ER_AAC_ELD: + err = transportEnc_writeELDSpecificConfig(asc, config, epConfig, cb); + if (err) return err; + break; + case AOT_USAC: + err = transportEnc_writeUsacSpecificConfig(asc, extFlag, config, cb); + if (err) { + return err; + } + break; + default: + return -1; + } + + switch (config->aot) { + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LTP: + case AOT_ER_AAC_SCAL: + case AOT_ER_TWIN_VQ: + case AOT_ER_BSAC: + case AOT_ER_AAC_LD: + case AOT_ER_CELP: + case AOT_ER_HVXC: + case AOT_ER_HILN: + case AOT_ER_PARA: + case AOT_ER_AAC_ELD: + FDKwriteBits(asc, 0, 2); /* epconfig 0 */ + break; + default: + break; + } + + /* backward compatible explicit signaling of extension AOT */ + if (config->sbrSignaling == SIG_EXPLICIT_BW_COMPATIBLE) { + TP_ASC_EXTENSION_ID ascExtId = ASCEXT_UNKOWN; + + if (config->sbrPresent) { + ascExtId = ASCEXT_SBR; + FDKwriteBits(asc, ascExtId, 11); + writeAot(asc, config->extAOT); + FDKwriteBits(asc, 1, 1); /* sbrPresentFlag=1 */ + writeSampleRate(asc, config->extSamplingRate, 4); + if (config->psPresent) { + ascExtId = ASCEXT_PS; + FDKwriteBits(asc, ascExtId, 11); + FDKwriteBits(asc, 1, 1); /* psPresentFlag=1 */ + } + } + } + + /* Make sure all bits are sync'ed */ + FDKsyncCache(asc); + + return 0; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_asc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_asc.h new file mode 100644 index 0000000000000..5f5621e0b672b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_asc.h @@ -0,0 +1,147 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Manuel Jander + + Description: Audio Specific Config writer + +*******************************************************************************/ + +#ifndef TPENC_ASC_H +#define TPENC_ASC_H + +/** + * \brief Get channel config from channel mode. + * + * \param channel_mode channel mode + * \param channel_config_zero no standard channel configuration + * + * \return chanel config + */ +int getChannelConfig(const CHANNEL_MODE channel_mode, + const UCHAR channel_config_zero); + +/** + * \brief Write a Program Config Element. + * + * \param hBs bitstream handle into which the PCE is appended + * \param channelMode the channel mode to be used + * \param sampleRate the sample rate + * \param instanceTagPCE the instance tag of the Program Config Element + * \param profile the MPEG Audio profile to be used + * \param matrix mixdown gain + * \param pseudo surround indication + * \param reference bitstream position for alignment + * \return zero on success, non-zero on failure. + */ +int transportEnc_writePCE(HANDLE_FDK_BITSTREAM hBs, CHANNEL_MODE channelMode, + INT sampleRate, int instanceTagPCE, int profile, + int matrixMixdownA, int pseudoSurroundEnable, + UINT alignAnchor); + +/** + * \brief Get the bit count required by a Program Config Element + * + * \param channelMode the channel mode to be used + * \param matrix mixdown gain + * \param bit offset at which the PCE would start + * \return the amount of bits required for the PCE including the given bit + * offset. + */ +int transportEnc_GetPCEBits(CHANNEL_MODE channelMode, int matrixMixdownA, + int bits); + +#endif /* TPENC_ASC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_latm.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_latm.cpp new file mode 100644 index 0000000000000..2d35d4831a02a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_latm.cpp @@ -0,0 +1,850 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): + + Description: + +*******************************************************************************/ + +#include "tpenc_latm.h" + +#include "genericStds.h" + +static const short celpFrameLengthTable[64] = { + 154, 170, 186, 147, 156, 165, 114, 120, 186, 126, 132, 138, 142, + 146, 154, 166, 174, 182, 190, 198, 206, 210, 214, 110, 114, 118, + 120, 122, 218, 230, 242, 254, 266, 278, 286, 294, 318, 342, 358, + 374, 390, 406, 422, 136, 142, 148, 154, 160, 166, 170, 174, 186, + 198, 206, 214, 222, 230, 238, 216, 160, 280, 338, 0, 0}; + +/******* + write value to transport stream + first two bits define the size of the value itself + then the value itself, with a size of 0-3 bytes +*******/ +static UINT transportEnc_LatmWriteValue(HANDLE_FDK_BITSTREAM hBs, int value) { + UCHAR valueBytes = 4; + unsigned int bitsWritten = 0; + int i; + + if (value < (1 << 8)) { + valueBytes = 1; + } else if (value < (1 << 16)) { + valueBytes = 2; + } else if (value < (1 << 24)) { + valueBytes = 3; + } else { + valueBytes = 4; + } + + FDKwriteBits(hBs, valueBytes - 1, 2); /* size of value in Bytes */ + for (i = 0; i < valueBytes; i++) { + /* write most significant Byte first */ + FDKwriteBits(hBs, (UCHAR)(value >> ((valueBytes - 1 - i) << 3)), 8); + } + + bitsWritten = (valueBytes << 3) + 2; + + return bitsWritten; +} + +static UINT transportEnc_LatmCountFixBitDemandHeader(HANDLE_LATM_STREAM hAss) { + int bitDemand = 0; + int insertSetupData = 0; + + /* only if start of new latm frame */ + if (hAss->subFrameCnt == 0) { + /* AudioSyncStream */ + + if (hAss->tt == TT_MP4_LOAS) { + bitDemand += 11; /* syncword */ + bitDemand += 13; /* audioMuxLengthBytes */ + } + + /* AudioMuxElement*/ + + /* AudioMuxElement::Stream Mux Config */ + if (hAss->muxConfigPeriod > 0) { + insertSetupData = (hAss->latmFrameCounter == 0); + } else { + insertSetupData = 0; + } + + if (hAss->tt != TT_MP4_LATM_MCP0) { + /* AudioMuxElement::useSameStreamMux Flag */ + bitDemand += 1; + + if (insertSetupData) { + bitDemand += hAss->streamMuxConfigBits; + } + } + + /* AudioMuxElement::otherDataBits */ + bitDemand += hAss->otherDataLenBits; + + /* AudioMuxElement::ByteAlign */ + if (bitDemand % 8) { + hAss->fillBits = 8 - (bitDemand % 8); + bitDemand += hAss->fillBits; + } else { + hAss->fillBits = 0; + } + } + + return bitDemand; +} + +static UINT transportEnc_LatmCountVarBitDemandHeader( + HANDLE_LATM_STREAM hAss, unsigned int streamDataLength) { + int bitDemand = 0; + int prog, layer; + + /* Payload Length Info*/ + if (hAss->allStreamsSameTimeFraming) { + for (prog = 0; prog < hAss->noProgram; prog++) { + for (layer = 0; layer < LATM_MAX_LAYERS; layer++) { + LATM_LAYER_INFO *p_linfo = &(hAss->m_linfo[prog][layer]); + + if (p_linfo->streamID >= 0) { + switch (p_linfo->frameLengthType) { + case 0: + if (streamDataLength > 0) { + streamDataLength -= bitDemand; + while (streamDataLength >= (255 << 3)) { + bitDemand += 8; + streamDataLength -= (255 << 3); + } + bitDemand += 8; + } + break; + + case 1: + case 4: + case 6: + bitDemand += 2; + break; + + default: + return 0; + } + } + } + } + } else { + /* there are many possibilities to use this mechanism. */ + switch (hAss->varMode) { + case LATMVAR_SIMPLE_SEQUENCE: { + /* Use the sequence generated by the encoder */ + // int streamCntPosition = transportEnc_SetWritePointer( + // hAss->hAssemble, 0 ); int streamCntPosition = FDKgetValidBits( + // hAss->hAssemble ); + bitDemand += 4; + + hAss->varStreamCnt = 0; + for (prog = 0; prog < hAss->noProgram; prog++) { + for (layer = 0; layer < LATM_MAX_LAYERS; layer++) { + LATM_LAYER_INFO *p_linfo = &(hAss->m_linfo[prog][layer]); + + if (p_linfo->streamID >= 0) { + bitDemand += 4; /* streamID */ + switch (p_linfo->frameLengthType) { + case 0: + streamDataLength -= bitDemand; + while (streamDataLength >= (255 << 3)) { + bitDemand += 8; + streamDataLength -= (255 << 3); + } + + bitDemand += 8; + break; + /*bitDemand += 1; endFlag + break;*/ + + case 1: + case 4: + case 6: + + break; + + default: + return 0; + } + hAss->varStreamCnt++; + } + } + } + bitDemand += 4; + // transportEnc_UpdateBitstreamField( hAss->hAssemble, + // streamCntPosition, hAss->varStreamCnt-1, 4 ); UINT pos = + // streamCntPosition-FDKgetValidBits(hAss->hAssemble); FDKpushBack( + // hAss->hAssemble, pos); FDKwriteBits( hAss->hAssemble, + // hAss->varStreamCnt-1, 4); FDKpushFor( hAss->hAssemble, pos-4); + } break; + + default: + return 0; + } + } + + return bitDemand; +} + +TRANSPORTENC_ERROR +CreateStreamMuxConfig(HANDLE_LATM_STREAM hAss, HANDLE_FDK_BITSTREAM hBs, + int bufferFullness, CSTpCallBacks *cb) { + INT streamIDcnt, tmp; + int layer, prog; + + USHORT coreFrameOffset = 0; + + hAss->taraBufferFullness = 0xFF; + hAss->audioMuxVersionA = 0; /* for future extensions */ + hAss->streamMuxConfigBits = 0; + + FDKwriteBits(hBs, hAss->audioMuxVersion, 1); /* audioMuxVersion */ + hAss->streamMuxConfigBits += 1; + + if (hAss->audioMuxVersion == 1) { + FDKwriteBits(hBs, hAss->audioMuxVersionA, 1); /* audioMuxVersionA */ + hAss->streamMuxConfigBits += 1; + } + + if (hAss->audioMuxVersionA == 0) { + if (hAss->audioMuxVersion == 1) { + hAss->streamMuxConfigBits += transportEnc_LatmWriteValue( + hBs, hAss->taraBufferFullness); /* taraBufferFullness */ + } + FDKwriteBits(hBs, hAss->allStreamsSameTimeFraming ? 1 : 0, + 1); /* allStreamsSameTimeFraming */ + FDKwriteBits(hBs, hAss->noSubframes - 1, 6); /* Number of Subframes */ + FDKwriteBits(hBs, hAss->noProgram - 1, 4); /* Number of Programs */ + + hAss->streamMuxConfigBits += 11; + + streamIDcnt = 0; + for (prog = 0; prog < hAss->noProgram; prog++) { + int transLayer = 0; + + FDKwriteBits(hBs, hAss->noLayer[prog] - 1, 3); + hAss->streamMuxConfigBits += 3; + + for (layer = 0; layer < LATM_MAX_LAYERS; layer++) { + LATM_LAYER_INFO *p_linfo = &(hAss->m_linfo[prog][layer]); + CODER_CONFIG *p_lci = hAss->config[prog][layer]; + + p_linfo->streamID = -1; + + if (hAss->config[prog][layer] != NULL) { + int useSameConfig = 0; + + if (transLayer > 0) { + FDKwriteBits(hBs, useSameConfig ? 1 : 0, 1); + hAss->streamMuxConfigBits += 1; + } + if ((useSameConfig == 0) || (transLayer == 0)) { + const UINT alignAnchor = FDKgetValidBits(hBs); + + if (0 != + (transportEnc_writeASC(hBs, hAss->config[prog][layer], cb))) { + return TRANSPORTENC_UNKOWN_ERROR; + } + + if (hAss->audioMuxVersion == 1) { + UINT ascLen = transportEnc_LatmWriteValue(hBs, 0); + FDKbyteAlign(hBs, alignAnchor); + ascLen = FDKgetValidBits(hBs) - alignAnchor - ascLen; + FDKpushBack(hBs, FDKgetValidBits(hBs) - alignAnchor); + + transportEnc_LatmWriteValue(hBs, ascLen); + + if (0 != + (transportEnc_writeASC(hBs, hAss->config[prog][layer], cb))) { + return TRANSPORTENC_UNKOWN_ERROR; + } + + FDKbyteAlign(hBs, alignAnchor); /* asc length fillbits */ + } + + hAss->streamMuxConfigBits += + FDKgetValidBits(hBs) - + alignAnchor; /* add asc length to smc summary */ + } + transLayer++; + + if (!hAss->allStreamsSameTimeFraming) { + if (streamIDcnt >= LATM_MAX_STREAM_ID) + return TRANSPORTENC_INVALID_CONFIG; + } + p_linfo->streamID = streamIDcnt++; + + switch (p_lci->aot) { + case AOT_AAC_MAIN: + case AOT_AAC_LC: + case AOT_AAC_SSR: + case AOT_AAC_LTP: + case AOT_AAC_SCAL: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + case AOT_USAC: + p_linfo->frameLengthType = 0; + + FDKwriteBits(hBs, p_linfo->frameLengthType, + 3); /* frameLengthType */ + FDKwriteBits(hBs, bufferFullness, 8); /* bufferFullness */ + hAss->streamMuxConfigBits += 11; + + if (!hAss->allStreamsSameTimeFraming) { + CODER_CONFIG *p_lci_prev = hAss->config[prog][layer - 1]; + if (((p_lci->aot == AOT_AAC_SCAL) || + (p_lci->aot == AOT_ER_AAC_SCAL)) && + ((p_lci_prev->aot == AOT_CELP) || + (p_lci_prev->aot == AOT_ER_CELP))) { + FDKwriteBits(hBs, coreFrameOffset, 6); /* coreFrameOffset */ + hAss->streamMuxConfigBits += 6; + } + } + break; + + case AOT_TWIN_VQ: + p_linfo->frameLengthType = 1; + tmp = ((p_lci->bitsFrame + 7) >> 3) - + 20; /* transmission frame length in bytes */ + if ((tmp < 0)) { + return TRANSPORTENC_INVALID_TRANSMISSION_FRAME_LENGTH; + } + FDKwriteBits(hBs, p_linfo->frameLengthType, + 3); /* frameLengthType */ + FDKwriteBits(hBs, tmp, 9); + hAss->streamMuxConfigBits += 12; + + p_linfo->frameLengthBits = (tmp + 20) << 3; + break; + + case AOT_CELP: + p_linfo->frameLengthType = 4; + FDKwriteBits(hBs, p_linfo->frameLengthType, + 3); /* frameLengthType */ + hAss->streamMuxConfigBits += 3; + { + int i; + for (i = 0; i < 62; i++) { + if (celpFrameLengthTable[i] == p_lci->bitsFrame) break; + } + if (i >= 62) { + return TRANSPORTENC_INVALID_CELP_FRAME_LENGTH; + } + + FDKwriteBits(hBs, i, 6); /* CELPframeLengthTabelIndex */ + hAss->streamMuxConfigBits += 6; + } + p_linfo->frameLengthBits = p_lci->bitsFrame; + break; + + case AOT_HVXC: + p_linfo->frameLengthType = 6; + FDKwriteBits(hBs, p_linfo->frameLengthType, + 3); /* frameLengthType */ + hAss->streamMuxConfigBits += 3; + { + int i; + + if (p_lci->bitsFrame == 40) { + i = 0; + } else if (p_lci->bitsFrame == 80) { + i = 1; + } else { + return TRANSPORTENC_INVALID_FRAME_BITS; + } + FDKwriteBits(hBs, i, 1); /* HVXCframeLengthTableIndex */ + hAss->streamMuxConfigBits += 1; + } + p_linfo->frameLengthBits = p_lci->bitsFrame; + break; + + case AOT_NULL_OBJECT: + default: + return TRANSPORTENC_INVALID_AOT; + } + } + } + } + + FDKwriteBits(hBs, (hAss->otherDataLenBits > 0) ? 1 : 0, + 1); /* otherDataPresent */ + hAss->streamMuxConfigBits += 1; + + if (hAss->otherDataLenBits > 0) { + FDKwriteBits(hBs, 0, 1); + FDKwriteBits(hBs, hAss->otherDataLenBits, 8); + hAss->streamMuxConfigBits += 9; + } + + FDKwriteBits(hBs, 0, 1); /* crcCheckPresent=0 */ + hAss->streamMuxConfigBits += 1; + + } else { /* if ( audioMuxVersionA == 0 ) */ + + /* for future extensions */ + } + + return TRANSPORTENC_OK; +} + +static TRANSPORTENC_ERROR WriteAuPayloadLengthInfo( + HANDLE_FDK_BITSTREAM hBitStream, int AuLengthBits) { + int restBytes; + + if (AuLengthBits % 8) return TRANSPORTENC_INVALID_AU_LENGTH; + + while (AuLengthBits >= 255 * 8) { + FDKwriteBits(hBitStream, 255, 8); /* 255 shows incomplete AU */ + AuLengthBits -= (255 * 8); + } + + restBytes = (AuLengthBits) >> 3; + FDKwriteBits(hBitStream, restBytes, 8); + + return TRANSPORTENC_OK; +} + +static TRANSPORTENC_ERROR transportEnc_LatmSetNrOfSubframes( + HANDLE_LATM_STREAM hAss, INT noSubframes_next) /* nr of access units / + payloads within a latm + frame */ +{ + /* sanity chk */ + if (noSubframes_next < 1 || noSubframes_next > MAX_NR_OF_SUBFRAMES) { + return TRANSPORTENC_LATM_INVALID_NR_OF_SUBFRAMES; + } + + hAss->noSubframes_next = noSubframes_next; + + /* if at start then we can take over the value immediately, otherwise we have + * to wait for the next SMC */ + if ((hAss->subFrameCnt == 0) && (hAss->latmFrameCounter == 0)) { + hAss->noSubframes = noSubframes_next; + } + + return TRANSPORTENC_OK; +} + +static int allStreamsSameTimeFraming(HANDLE_LATM_STREAM hAss, UCHAR noProgram, + UCHAR noLayer[] /* return */) { + int prog, layer; + + signed int lastNoSamples = -1; + signed int minFrameSamples = FDK_INT_MAX; + signed int maxFrameSamples = 0; + + signed int highestSamplingRate = -1; + + for (prog = 0; prog < noProgram; prog++) { + noLayer[prog] = 0; + + for (layer = 0; layer < LATM_MAX_LAYERS; layer++) { + if (hAss->config[prog][layer] != NULL) { + INT hsfSamplesFrame; + + noLayer[prog]++; + + if (highestSamplingRate < 0) + highestSamplingRate = hAss->config[prog][layer]->samplingRate; + + hsfSamplesFrame = hAss->config[prog][layer]->samplesPerFrame * + highestSamplingRate / + hAss->config[prog][layer]->samplingRate; + + if (hsfSamplesFrame <= minFrameSamples) + minFrameSamples = hsfSamplesFrame; + if (hsfSamplesFrame >= maxFrameSamples) + maxFrameSamples = hsfSamplesFrame; + + if (lastNoSamples == -1) { + lastNoSamples = hsfSamplesFrame; + } else { + if (hsfSamplesFrame != lastNoSamples) { + return 0; + } + } + } + } + } + + return 1; +} + +/** + * Initialize LATM/LOAS Stream and add layer 0 at program 0. + */ +static TRANSPORTENC_ERROR transportEnc_InitLatmStream( + HANDLE_LATM_STREAM hAss, int fractDelayPresent, + signed int + muxConfigPeriod, /* insert setup data every muxConfigPeriod frames */ + UINT audioMuxVersion, TRANSPORT_TYPE tt) { + TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK; + + if (hAss == NULL) return TRANSPORTENC_INVALID_PARAMETER; + + hAss->tt = tt; + + hAss->noProgram = 1; + + hAss->audioMuxVersion = audioMuxVersion; + + /* Fill noLayer array using hAss->config */ + hAss->allStreamsSameTimeFraming = + allStreamsSameTimeFraming(hAss, hAss->noProgram, hAss->noLayer); + /* Only allStreamsSameTimeFraming==1 is supported */ + FDK_ASSERT(hAss->allStreamsSameTimeFraming); + + hAss->fractDelayPresent = fractDelayPresent; + hAss->otherDataLenBits = 0; + + hAss->varMode = LATMVAR_SIMPLE_SEQUENCE; + + /* initialize counters */ + hAss->subFrameCnt = 0; + hAss->noSubframes = DEFAULT_LATM_NR_OF_SUBFRAMES; + hAss->noSubframes_next = DEFAULT_LATM_NR_OF_SUBFRAMES; + + /* sync layer related */ + hAss->audioMuxLengthBytes = 0; + + hAss->latmFrameCounter = 0; + hAss->muxConfigPeriod = muxConfigPeriod; + + return ErrorStatus; +} + +/** + * + */ +UINT transportEnc_LatmCountTotalBitDemandHeader(HANDLE_LATM_STREAM hAss, + unsigned int streamDataLength) { + UINT bitDemand = 0; + + switch (hAss->tt) { + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + if (hAss->subFrameCnt == 0) { + bitDemand = transportEnc_LatmCountFixBitDemandHeader(hAss); + } + bitDemand += transportEnc_LatmCountVarBitDemandHeader( + hAss, streamDataLength /*- bitDemand*/); + break; + default: + break; + } + + return bitDemand; +} + +static TRANSPORTENC_ERROR AdvanceAudioMuxElement(HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + int auBits, int bufferFullness, + CSTpCallBacks *cb) { + TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK; + int insertMuxSetup; + + /* Insert setup data to assemble Buffer */ + if (hAss->subFrameCnt == 0) { + if (hAss->muxConfigPeriod > 0) { + insertMuxSetup = (hAss->latmFrameCounter == 0); + } else { + insertMuxSetup = 0; + } + + if (hAss->tt != TT_MP4_LATM_MCP0) { + if (insertMuxSetup) { + FDKwriteBits(hBs, 0, 1); /* useSameStreamMux useNewStreamMux */ + if (TRANSPORTENC_OK != (ErrorStatus = CreateStreamMuxConfig( + hAss, hBs, bufferFullness, cb))) { + return ErrorStatus; + } + } else { + FDKwriteBits(hBs, 1, 1); /* useSameStreamMux */ + } + } + } + + /* PayloadLengthInfo */ + { + int prog, layer; + + for (prog = 0; prog < hAss->noProgram; prog++) { + for (layer = 0; layer < hAss->noLayer[prog]; layer++) { + ErrorStatus = WriteAuPayloadLengthInfo(hBs, auBits); + if (ErrorStatus != TRANSPORTENC_OK) return ErrorStatus; + } + } + } + /* At this point comes the access unit. */ + + return TRANSPORTENC_OK; +} + +TRANSPORTENC_ERROR +transportEnc_LatmWrite(HANDLE_LATM_STREAM hAss, HANDLE_FDK_BITSTREAM hBs, + int auBits, int bufferFullness, CSTpCallBacks *cb) { + TRANSPORTENC_ERROR ErrorStatus; + + if (hAss->subFrameCnt == 0) { + /* Start new frame */ + FDKresetBitbuffer(hBs, BS_WRITER); + } + + hAss->latmSubframeStart = FDKgetValidBits(hBs); + + /* Insert syncword and syncword distance + - only if loas + - we must update the syncword distance (=audiomuxlengthbytes) later + */ + if (hAss->tt == TT_MP4_LOAS && hAss->subFrameCnt == 0) { + /* Start new LOAS frame */ + FDKwriteBits(hBs, 0x2B7, 11); + hAss->audioMuxLengthBytes = 0; + hAss->audioMuxLengthBytesPos = + FDKgetValidBits(hBs); /* store read pointer position */ + FDKwriteBits(hBs, hAss->audioMuxLengthBytes, 13); + } + + ErrorStatus = AdvanceAudioMuxElement(hAss, hBs, auBits, bufferFullness, cb); + + if (ErrorStatus != TRANSPORTENC_OK) return ErrorStatus; + + return ErrorStatus; +} + +void transportEnc_LatmAdjustSubframeBits(HANDLE_LATM_STREAM hAss, int *bits) { + /* Substract bits from possible previous subframe */ + *bits -= hAss->latmSubframeStart; + /* Add fill bits */ + if (hAss->subFrameCnt == 0) { + *bits += hAss->otherDataLenBits; + *bits += hAss->fillBits; + } +} + +TRANSPORTENC_ERROR transportEnc_LatmGetFrame(HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + int *pBytes) { + TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK; + + hAss->subFrameCnt++; + if (hAss->subFrameCnt >= hAss->noSubframes) { + /* Add LOAS frame length if required. */ + if (hAss->tt == TT_MP4_LOAS) { + FDK_BITSTREAM tmpBuf; + + /* Determine frame length info */ + hAss->audioMuxLengthBytes = + ((FDKgetValidBits(hBs) + hAss->otherDataLenBits + 7) >> 3) - + 3; /* 3=Syncword + length */ + + /* Check frame length info */ + if (hAss->audioMuxLengthBytes >= (1 << 13)) { + ErrorStatus = TRANSPORTENC_INVALID_AU_LENGTH; + goto bail; + } + + /* Write length info into assembler buffer */ + FDKinitBitStream(&tmpBuf, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, + BS_WRITER); + FDKpushFor(&tmpBuf, hAss->audioMuxLengthBytesPos); + FDKwriteBits(&tmpBuf, hAss->audioMuxLengthBytes, 13); + FDKsyncCache(&tmpBuf); + } + + /* Write AudioMuxElement other data bits */ + FDKwriteBits(hBs, 0, hAss->otherDataLenBits); + + /* Write AudioMuxElement byte alignment fill bits */ + FDKwriteBits(hBs, 0, hAss->fillBits); + + FDK_ASSERT((FDKgetValidBits(hBs) % 8) == 0); + + hAss->subFrameCnt = 0; + + FDKsyncCache(hBs); + *pBytes = (FDKgetValidBits(hBs) + 7) >> 3; + + if (hAss->muxConfigPeriod > 0) { + hAss->latmFrameCounter++; + + if (hAss->latmFrameCounter >= hAss->muxConfigPeriod) { + hAss->latmFrameCounter = 0; + hAss->noSubframes = hAss->noSubframes_next; + } + } + } else { + /* No data this time */ + *pBytes = 0; + } + +bail: + return ErrorStatus; +} + +/** + * Init LATM/LOAS + */ +TRANSPORTENC_ERROR transportEnc_Latm_Init(HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + CODER_CONFIG *layerConfig, + UINT audioMuxVersion, + TRANSPORT_TYPE tt, + CSTpCallBacks *cb) { + TRANSPORTENC_ERROR ErrorStatus; + int fractDelayPresent = 0; + int prog, layer; + + int setupDataDistanceFrames = layerConfig->headerPeriod; + + FDK_ASSERT(setupDataDistanceFrames >= 0); + + for (prog = 0; prog < LATM_MAX_PROGRAMS; prog++) { + for (layer = 0; layer < LATM_MAX_LAYERS; layer++) { + hAss->config[prog][layer] = NULL; + hAss->m_linfo[prog][layer].streamID = -1; + } + } + + hAss->config[0][0] = layerConfig; + hAss->m_linfo[0][0].streamID = 0; + + ErrorStatus = transportEnc_InitLatmStream(hAss, fractDelayPresent, + setupDataDistanceFrames, + (audioMuxVersion) ? 1 : 0, tt); + if (ErrorStatus != TRANSPORTENC_OK) goto bail; + + ErrorStatus = + transportEnc_LatmSetNrOfSubframes(hAss, layerConfig->nSubFrames); + if (ErrorStatus != TRANSPORTENC_OK) goto bail; + + /* Get the size of the StreamMuxConfig somehow */ + if (TRANSPORTENC_OK != + (ErrorStatus = AdvanceAudioMuxElement(hAss, hBs, 0, 0, cb))) { + goto bail; + } + + // CreateStreamMuxConfig(hAss, hBs, 0); + +bail: + return ErrorStatus; +} + +TRANSPORTENC_ERROR transportEnc_LatmAddOtherDataBits(HANDLE_LATM_STREAM hAss, + const int otherDataBits) { + TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK; + + if ((hAss->otherDataLenBits != 0) || (otherDataBits % 8 != 0)) { + /* This implementation allows to add other data bits only once. + To keep existing alignment only whole bytes are allowed. */ + ErrorStatus = TRANSPORTENC_UNKOWN_ERROR; + } else { + /* Ensure correct addional bits in payload. */ + if (hAss->tt == TT_MP4_LATM_MCP0) { + hAss->otherDataLenBits = otherDataBits; + } else { + hAss->otherDataLenBits = otherDataBits - 9; + hAss->streamMuxConfigBits += 9; + } + } + + return ErrorStatus; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_latm.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_latm.h new file mode 100644 index 0000000000000..d65035761542b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_latm.h @@ -0,0 +1,274 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef TPENC_LATM_H +#define TPENC_LATM_H + +#include "tpenc_lib.h" +#include "FDK_bitstream.h" + +#define DEFAULT_LATM_NR_OF_SUBFRAMES 1 +#define DEFAULT_LATM_SMC_REPEAT 8 + +#define MAX_AAC_LAYERS 9 + +#define LATM_MAX_PROGRAMS 1 +#define LATM_MAX_STREAM_ID 16 + +#define LATM_MAX_LAYERS 1 /*MAX_AAC_LAYERS*/ + +#define MAX_NR_OF_SUBFRAMES \ + 2 /* set this carefully to avoid buffer overflows \ + */ + +typedef enum { LATMVAR_SIMPLE_SEQUENCE } LATM_VAR_MODE; + +typedef struct { + signed int frameLengthType; + signed int frameLengthBits; + signed int varFrameLengthTable[4]; + signed int streamID; +} LATM_LAYER_INFO; + +typedef struct { + LATM_LAYER_INFO m_linfo[LATM_MAX_PROGRAMS][LATM_MAX_LAYERS]; + CODER_CONFIG *config[LATM_MAX_PROGRAMS][LATM_MAX_LAYERS]; + + LATM_VAR_MODE varMode; + TRANSPORT_TYPE tt; + + int audioMuxLengthBytes; + + int audioMuxLengthBytesPos; + int taraBufferFullness; /* state of the bit reservoir */ + int varStreamCnt; + + UCHAR + latmFrameCounter; /* Current frame number. Counts modulo muxConfigPeriod + */ + UCHAR muxConfigPeriod; /* Distance in frames between MuxConfig */ + + UCHAR + audioMuxVersion; /* AMV1 supports transmission of taraBufferFullness and + ASC lengths */ + UCHAR audioMuxVersionA; /* for future extensions */ + + UCHAR noProgram; + UCHAR noLayer[LATM_MAX_PROGRAMS]; + UCHAR fractDelayPresent; + + UCHAR allStreamsSameTimeFraming; + UCHAR subFrameCnt; /* Current Subframe frame */ + UCHAR noSubframes; /* Number of subframes */ + UINT latmSubframeStart; /* Position of current subframe start */ + UCHAR noSubframes_next; + + UCHAR otherDataLenBits; /* AudioMuxElement other data bits */ + UCHAR fillBits; /* AudioMuxElement fill bits */ + UINT streamMuxConfigBits; + +} LATM_STREAM; + +typedef LATM_STREAM *HANDLE_LATM_STREAM; + +/** + * \brief Initialize LATM_STREAM Handle. Creates automatically one program with + * one layer with the given layerConfig. The layerConfig must be persisten + * because references to this pointer are made at any time again. Use + * transportEnc_Latm_AddLayer() to add more programs/layers. + * + * \param hLatmStreamInfo HANDLE_LATM_STREAM handle + * \param hBs Bitstream handle + * \param layerConfig a valid CODER_CONFIG struct containing the current audio + * configuration parameters + * \param audioMuxVersion the LATM audioMuxVersion to be used + * \param tt the specific TRANSPORT_TYPE to be used, either TT_MP4_LOAS, + * TT_MP4_LATM_MCP1 or TT_MP4_LATM_MCP0 LOAS + * \param cb callback information structure. + * + * \return an TRANSPORTENC_ERROR error code + */ +TRANSPORTENC_ERROR transportEnc_Latm_Init(HANDLE_LATM_STREAM hLatmStreamInfo, + HANDLE_FDK_BITSTREAM hBs, + CODER_CONFIG *layerConfig, + UINT audioMuxVersion, + TRANSPORT_TYPE tt, CSTpCallBacks *cb); + +/** + * \brief Write addional other data bits in AudioMuxElement + * + * \param hAss HANDLE_LATM_STREAM handle + * \param otherDataBits number of other data bits to be written + * + * \return an TRANSPORTENC_ERROR error code + */ +TRANSPORTENC_ERROR transportEnc_LatmAddOtherDataBits(HANDLE_LATM_STREAM hAss, + const int otherDataBits); + +/** + * \brief Get bit demand of next LATM/LOAS header + * + * \param hAss HANDLE_LATM_STREAM handle + * \param streamDataLength the length of the payload + * + * \return the number of bits required by the LATM/LOAS headers + */ +unsigned int transportEnc_LatmCountTotalBitDemandHeader( + HANDLE_LATM_STREAM hAss, unsigned int streamDataLength); + +/** + * \brief Write LATM/LOAS header into given bitstream handle + * + * \param hLatmStreamInfo HANDLE_LATM_STREAM handle + * \param hBitstream Bitstream handle + * \param auBits amount of current payload bits + * \param bufferFullness LATM buffer fullness value + * \param cb callback information structure. + * + * \return an TRANSPORTENC_ERROR error code + */ +TRANSPORTENC_ERROR +transportEnc_LatmWrite(HANDLE_LATM_STREAM hAss, HANDLE_FDK_BITSTREAM hBitstream, + int auBits, int bufferFullness, CSTpCallBacks *cb); + +/** + * \brief Adjust bit count relative to current subframe + * + * \param hAss HANDLE_LATM_STREAM handle + * \param pBits pointer to an int, where the current frame bit count is + * contained, and where the subframe relative bit count will be returned into + * + * \return void + */ +void transportEnc_LatmAdjustSubframeBits(HANDLE_LATM_STREAM hAss, int *pBits); + +/** + * \brief Request an LATM frame, which may, or may not be available + * + * \param hAss HANDLE_LATM_STREAM handle + * \param hBs Bitstream handle + * \param pBytes pointer to an int, where the current frame byte count stored + * into. A return value of zero means that currently no LATM/LOAS frame can be + * returned. The latter is expected in case of multiple subframes being + * used. + * + * \return an TRANSPORTENC_ERROR error code + */ +TRANSPORTENC_ERROR transportEnc_LatmGetFrame(HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + int *pBytes); + +/** + * \brief Write a StreamMuxConfig into the given bitstream handle + * + * \param hAss HANDLE_LATM_STREAM handle + * \param hBs Bitstream handle + * \param bufferFullness LATM buffer fullness value + * \param cb callback information structure. + * + * \return void + */ +TRANSPORTENC_ERROR +CreateStreamMuxConfig(HANDLE_LATM_STREAM hAss, HANDLE_FDK_BITSTREAM hBs, + int bufferFullness, CSTpCallBacks *cb); + +#endif /* TPENC_LATM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_lib.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_lib.cpp new file mode 100644 index 0000000000000..77c19b5043b8a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libMpegTPEnc/src/tpenc_lib.cpp @@ -0,0 +1,664 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Manuel Jander + + Description: MPEG Transport encode + +*******************************************************************************/ + +#include "tpenc_lib.h" + +/* library info */ +#include "tp_version.h" + +#define MODULE_NAME "transportEnc" + +#include "tpenc_asc.h" + +#include "tpenc_adts.h" + +#include "tpenc_adif.h" + +#include "tpenc_latm.h" + +typedef struct { + int curSubFrame; + int nSubFrames; + int prevBits; +} RAWPACKETS_INFO; + +struct TRANSPORTENC { + CODER_CONFIG config; + TRANSPORT_TYPE transportFmt; /*!< MPEG4 transport type. */ + + FDK_BITSTREAM bitStream; + UCHAR *bsBuffer; + INT bsBufferSize; + + INT pceFrameCounter; /*!< Indicates frame period when PCE must be written in + raw_data_block. -1 means not to write a PCE in + raw_dat_block. */ + union { + STRUCT_ADTS adts; + + ADIF_INFO adif; + + LATM_STREAM latm; + + RAWPACKETS_INFO raw; + + } writer; + + CSTpCallBacks callbacks; +}; + +typedef struct _TRANSPORTENC_STRUCT TRANSPORTENC_STRUCT; + +/* + * MEMORY Declaration + */ + +C_ALLOC_MEM(Ram_TransportEncoder, struct TRANSPORTENC, 1) + +TRANSPORTENC_ERROR transportEnc_Open(HANDLE_TRANSPORTENC *phTpEnc) { + HANDLE_TRANSPORTENC hTpEnc; + + if (phTpEnc == NULL) { + return TRANSPORTENC_INVALID_PARAMETER; + } + + hTpEnc = GetRam_TransportEncoder(0); + + if (hTpEnc == NULL) { + return TRANSPORTENC_NO_MEM; + } + + *phTpEnc = hTpEnc; + return TRANSPORTENC_OK; +} + +/** + * \brief Get frame period of PCE in raw_data_block. + * + * - Write PCE only if necessary. PCE can be part of the ASC if chConfig==0 + * whererfore no additonal PCE will be written in raw_data_block. + * - A matrixMixdown coefficient can only be written if chConfig is 5.0 or 5.1. + * - The PCE repetition rate in raw_data_block can be controlled via + * headerPeriod parameter. + * + * \param channelMode Encoder Channel Mode. + * \param channelConfigZero No standard channel configuration. + * \param transportFmt Format of the transport to be written. + * \param headerPeriod Chosen PCE frame repetition rate. + * \param matrixMixdownA Indicates if a valid Matrix Mixdown coefficient + * is available. + * + * \return PCE frame repetition rate. -1 means no PCE present in + * raw_data_block. + */ +static INT getPceRepetitionRate(const CHANNEL_MODE channelMode, + const int channelConfigZero, + const TRANSPORT_TYPE transportFmt, + const int headerPeriod, + const int matrixMixdownA) { + INT pceFrameCounter = -1; /* variable to be returned */ + + if (headerPeriod > 0) { + switch (getChannelConfig(channelMode, channelConfigZero)) { + case 0: + switch (transportFmt) { + case TT_MP4_ADTS: + case TT_MP4_LATM_MCP0: + case TT_MP4_RAW: + pceFrameCounter = headerPeriod; + break; + case TT_MP4_ADIF: /* ADIF header comprises PCE */ + if ((channelMode == MODE_1_2_2) || (channelMode == MODE_1_2_2_1)) { + pceFrameCounter = headerPeriod; /* repeating pce only meaningful + for potential matrix mixdown */ + break; + } + FDK_FALLTHROUGH; + case TT_MP4_LOAS: /* PCE in ASC if chChonfig==0 */ + case TT_MP4_LATM_MCP1: /* PCE in ASC if chChonfig==0 */ + default: + pceFrameCounter = -1; /* no PCE in raw_data_block */ + } + break; + case 5: /* MODE_1_2_2 */ + case 6: /* MODE_1_2_2_1 */ + /* matrixMixdownCoefficient can only be written if 5.0 and 5.1 config + * present. */ + if (matrixMixdownA != 0) { + switch (transportFmt) { + case TT_MP4_ADIF: /* ADIF header comprises PCE */ + case TT_MP4_ADTS: + case TT_MP4_LOAS: /* no PCE in ASC because chConfig!=0 */ + case TT_MP4_LATM_MCP1: /* no PCE in ASC because chConfig!=0 */ + case TT_MP4_LATM_MCP0: + case TT_MP4_RAW: + pceFrameCounter = headerPeriod; + break; + default: + pceFrameCounter = -1; /* no PCE in raw_data_block */ + } /* switch transportFmt */ + } /* if matrixMixdownA!=0 */ + break; + default: + pceFrameCounter = -1; /* no PCE in raw_data_block */ + } /* switch getChannelConfig() */ + } /* if headerPeriod>0 */ + else { + pceFrameCounter = -1; /* no PCE in raw_data_block */ + } + + return pceFrameCounter; +} + +TRANSPORTENC_ERROR transportEnc_Init(HANDLE_TRANSPORTENC hTpEnc, + UCHAR *bsBuffer, INT bsBufferSize, + TRANSPORT_TYPE transportFmt, + CODER_CONFIG *cconfig, UINT flags) { + /* Copy configuration structure */ + FDKmemcpy(&hTpEnc->config, cconfig, sizeof(CODER_CONFIG)); + + /* Init transportEnc struct. */ + hTpEnc->transportFmt = transportFmt; + + hTpEnc->bsBuffer = bsBuffer; + hTpEnc->bsBufferSize = bsBufferSize; + + FDKinitBitStream(&hTpEnc->bitStream, hTpEnc->bsBuffer, hTpEnc->bsBufferSize, + 0, BS_WRITER); + + switch (transportFmt) { + case TT_MP4_ADIF: + /* Sanity checks */ + if ((hTpEnc->config.aot != AOT_AAC_LC) || + (hTpEnc->config.samplesPerFrame != 1024)) { + return TRANSPORTENC_INVALID_PARAMETER; + } + hTpEnc->writer.adif.headerWritten = 0; + hTpEnc->writer.adif.samplingRate = hTpEnc->config.samplingRate; + hTpEnc->writer.adif.bitRate = hTpEnc->config.bitRate; + hTpEnc->writer.adif.profile = ((int)hTpEnc->config.aot) - 1; + hTpEnc->writer.adif.cm = hTpEnc->config.channelMode; + hTpEnc->writer.adif.bVariableRate = 0; + hTpEnc->writer.adif.instanceTag = 0; + hTpEnc->writer.adif.matrixMixdownA = hTpEnc->config.matrixMixdownA; + hTpEnc->writer.adif.pseudoSurroundEnable = + (hTpEnc->config.flags & CC_PSEUDO_SURROUND) ? 1 : 0; + break; + + case TT_MP4_ADTS: + /* Sanity checks */ + if ((hTpEnc->config.aot != AOT_AAC_LC) || + (hTpEnc->config.samplesPerFrame != 1024)) { + return TRANSPORTENC_INVALID_PARAMETER; + } + if (adtsWrite_Init(&hTpEnc->writer.adts, &hTpEnc->config) != 0) { + return TRANSPORTENC_INVALID_PARAMETER; + } + break; + + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: { + TRANSPORTENC_ERROR error; + + error = transportEnc_Latm_Init(&hTpEnc->writer.latm, &hTpEnc->bitStream, + &hTpEnc->config, flags & TP_FLAG_LATM_AMV, + transportFmt, &hTpEnc->callbacks); + if (error != TRANSPORTENC_OK) { + return error; + } + } break; + + case TT_MP4_RAW: + hTpEnc->writer.raw.curSubFrame = 0; + hTpEnc->writer.raw.nSubFrames = hTpEnc->config.nSubFrames; + break; + + default: + return TRANSPORTENC_INVALID_PARAMETER; + } + + /* pceFrameCounter indicates if PCE must be written in raw_data_block. */ + hTpEnc->pceFrameCounter = getPceRepetitionRate( + hTpEnc->config.channelMode, hTpEnc->config.channelConfigZero, + transportFmt, hTpEnc->config.headerPeriod, hTpEnc->config.matrixMixdownA); + + return TRANSPORTENC_OK; +} + +TRANSPORTENC_ERROR transportEnc_AddOtherDataBits(HANDLE_TRANSPORTENC hTpEnc, + const int nBits) { + TRANSPORTENC_ERROR tpErr = TRANSPORTENC_OK; + + switch (hTpEnc->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + tpErr = transportEnc_LatmAddOtherDataBits(&hTpEnc->writer.latm, nBits); + break; + case TT_MP4_ADTS: + case TT_MP4_ADIF: + case TT_MP4_RAW: + default: + tpErr = TRANSPORTENC_UNKOWN_ERROR; + } + + return tpErr; +} + +HANDLE_FDK_BITSTREAM transportEnc_GetBitstream(HANDLE_TRANSPORTENC hTp) { + return &hTp->bitStream; +} + +int transportEnc_RegisterSbrCallback(HANDLE_TRANSPORTENC hTpEnc, + const cbSbr_t cbSbr, void *user_data) { + if (hTpEnc == NULL) { + return -1; + } + hTpEnc->callbacks.cbSbr = cbSbr; + hTpEnc->callbacks.cbSbrData = user_data; + return 0; +} +int transportEnc_RegisterUsacCallback(HANDLE_TRANSPORTENC hTpEnc, + const cbUsac_t cbUsac, void *user_data) { + if (hTpEnc == NULL) { + return -1; + } + hTpEnc->callbacks.cbUsac = cbUsac; + hTpEnc->callbacks.cbUsacData = user_data; + return 0; +} + +int transportEnc_RegisterSscCallback(HANDLE_TRANSPORTENC hTpEnc, + const cbSsc_t cbSsc, void *user_data) { + if (hTpEnc == NULL) { + return -1; + } + hTpEnc->callbacks.cbSsc = cbSsc; + hTpEnc->callbacks.cbSscData = user_data; + return 0; +} + +TRANSPORTENC_ERROR transportEnc_WriteAccessUnit(HANDLE_TRANSPORTENC hTp, + INT frameUsedBits, + int bufferFullness, int ncc) { + TRANSPORTENC_ERROR err = TRANSPORTENC_OK; + + if (!hTp) { + return TRANSPORTENC_INVALID_PARAMETER; + } + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream; + + /* In case of writing PCE in raw_data_block frameUsedBits must be adapted. */ + if (hTp->pceFrameCounter >= hTp->config.headerPeriod) { + frameUsedBits += transportEnc_GetPCEBits( + hTp->config.channelMode, hTp->config.matrixMixdownA, + 3); /* Consider 3 bits ID signalling in alignment */ + } + + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0, + BS_WRITER); + if (0 != adifWrite_EncodeHeader(&hTp->writer.adif, hBs, bufferFullness)) { + err = TRANSPORTENC_INVALID_CONFIG; + } + break; + case TT_MP4_ADTS: + bufferFullness /= ncc; /* Number of Considered Channels */ + bufferFullness /= 32; + bufferFullness = FDKmin(0x7FF, bufferFullness); /* Signal variable rate */ + adtsWrite_EncodeHeader(&hTp->writer.adts, &hTp->bitStream, bufferFullness, + frameUsedBits); + break; + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + bufferFullness /= ncc; /* Number of Considered Channels */ + bufferFullness /= 32; + bufferFullness = FDKmin(0xFF, bufferFullness); /* Signal variable rate */ + transportEnc_LatmWrite(&hTp->writer.latm, hBs, frameUsedBits, + bufferFullness, &hTp->callbacks); + break; + case TT_MP4_RAW: + if (hTp->writer.raw.curSubFrame >= hTp->writer.raw.nSubFrames) { + hTp->writer.raw.curSubFrame = 0; + FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0, + BS_WRITER); + } + hTp->writer.raw.prevBits = FDKgetValidBits(hBs); + break; + default: + err = TRANSPORTENC_UNSUPPORTED_FORMAT; + break; + } + + /* Write PCE in raw_data_block if required */ + if (hTp->pceFrameCounter >= hTp->config.headerPeriod) { + INT crcIndex = 0; + /* Align inside PCE with repsect to the first bit of the raw_data_block() */ + UINT alignAnchor = FDKgetValidBits(&hTp->bitStream); + + /* Write PCE element ID bits */ + FDKwriteBits(&hTp->bitStream, ID_PCE, 3); + + if ((hTp->transportFmt == TT_MP4_ADTS) && + !hTp->writer.adts.protection_absent) { + crcIndex = adtsWrite_CrcStartReg(&hTp->writer.adts, &hTp->bitStream, 0); + } + + /* Write PCE as first raw_data_block element */ + transportEnc_writePCE( + &hTp->bitStream, hTp->config.channelMode, hTp->config.samplingRate, 0, + 1, hTp->config.matrixMixdownA, + (hTp->config.flags & CC_PSEUDO_SURROUND) ? 1 : 0, alignAnchor); + + if ((hTp->transportFmt == TT_MP4_ADTS) && + !hTp->writer.adts.protection_absent) { + adtsWrite_CrcEndReg(&hTp->writer.adts, &hTp->bitStream, crcIndex); + } + hTp->pceFrameCounter = 0; /* reset pce frame counter */ + } + + if (hTp->pceFrameCounter != -1) { + hTp->pceFrameCounter++; /* Update pceFrameCounter only if PCE writing is + active. */ + } + + return err; +} + +TRANSPORTENC_ERROR transportEnc_EndAccessUnit(HANDLE_TRANSPORTENC hTp, + int *bits) { + switch (hTp->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + transportEnc_LatmAdjustSubframeBits(&hTp->writer.latm, bits); + break; + case TT_MP4_ADTS: + adtsWrite_EndRawDataBlock(&hTp->writer.adts, &hTp->bitStream, bits); + break; + case TT_MP4_ADIF: + /* Substract ADIF header from AU bits, not to be considered. */ + *bits -= adifWrite_GetHeaderBits(&hTp->writer.adif); + hTp->writer.adif.headerWritten = 1; + break; + case TT_MP4_RAW: + *bits -= hTp->writer.raw.prevBits; + break; + default: + break; + } + + return TRANSPORTENC_OK; +} + +TRANSPORTENC_ERROR transportEnc_GetFrame(HANDLE_TRANSPORTENC hTpEnc, + int *nbytes) { + TRANSPORTENC_ERROR tpErr = TRANSPORTENC_OK; + HANDLE_FDK_BITSTREAM hBs = &hTpEnc->bitStream; + + switch (hTpEnc->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + *nbytes = hTpEnc->bsBufferSize; + tpErr = transportEnc_LatmGetFrame(&hTpEnc->writer.latm, hBs, nbytes); + break; + case TT_MP4_ADTS: + if (hTpEnc->writer.adts.currentBlock >= + hTpEnc->writer.adts.num_raw_blocks + 1) { + *nbytes = (FDKgetValidBits(hBs) + 7) >> 3; + hTpEnc->writer.adts.currentBlock = 0; + } else { + *nbytes = 0; + } + break; + case TT_MP4_ADIF: + FDK_ASSERT((INT)FDKgetValidBits(hBs) >= 0); + *nbytes = (FDKgetValidBits(hBs) + 7) >> 3; + break; + case TT_MP4_RAW: + FDKsyncCache(hBs); + hTpEnc->writer.raw.curSubFrame++; + *nbytes = ((FDKgetValidBits(hBs) - hTpEnc->writer.raw.prevBits) + 7) >> 3; + break; + default: + break; + } + + return tpErr; +} + +INT transportEnc_GetStaticBits(HANDLE_TRANSPORTENC hTp, int auBits) { + INT nbits = 0, nPceBits = 0; + + /* Write PCE within raw_data_block in transport lib. */ + if (hTp->pceFrameCounter >= hTp->config.headerPeriod) { + nPceBits = transportEnc_GetPCEBits( + hTp->config.channelMode, hTp->config.matrixMixdownA, + 3); /* Consider 3 bits ID signalling in alignment */ + auBits += nPceBits; /* Adapt required raw_data_block bit consumtpion for AU + length information e.g. in LATM/LOAS configuration. + */ + } + + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + case TT_MP4_RAW: + nbits = 0; /* Do not consider the ADIF header into the total bitrate */ + break; + case TT_MP4_ADTS: + nbits = adtsWrite_GetHeaderBits(&hTp->writer.adts); + break; + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + nbits = + transportEnc_LatmCountTotalBitDemandHeader(&hTp->writer.latm, auBits); + break; + default: + nbits = 0; + break; + } + + /* PCE is written in the transport library therefore the bit consumption is + * part of the transport static bits. */ + nbits += nPceBits; + + return nbits; +} + +void transportEnc_Close(HANDLE_TRANSPORTENC *phTp) { + if (phTp != NULL) { + if (*phTp != NULL) { + FreeRam_TransportEncoder(phTp); + } + } +} + +int transportEnc_CrcStartReg(HANDLE_TRANSPORTENC hTpEnc, int mBits) { + int crcReg = 0; + + switch (hTpEnc->transportFmt) { + case TT_MP4_ADTS: + crcReg = adtsWrite_CrcStartReg(&hTpEnc->writer.adts, &hTpEnc->bitStream, + mBits); + break; + default: + break; + } + + return crcReg; +} + +void transportEnc_CrcEndReg(HANDLE_TRANSPORTENC hTpEnc, int reg) { + switch (hTpEnc->transportFmt) { + case TT_MP4_ADTS: + adtsWrite_CrcEndReg(&hTpEnc->writer.adts, &hTpEnc->bitStream, reg); + break; + default: + break; + } +} + +TRANSPORTENC_ERROR transportEnc_GetConf(HANDLE_TRANSPORTENC hTpEnc, + CODER_CONFIG *cc, + FDK_BITSTREAM *dataBuffer, + UINT *confType) { + TRANSPORTENC_ERROR tpErr = TRANSPORTENC_OK; + HANDLE_LATM_STREAM hLatmConfig = &hTpEnc->writer.latm; + + *confType = 0; /* set confType variable to default */ + + /* write StreamMuxConfig or AudioSpecificConfig depending on format used */ + switch (hTpEnc->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + tpErr = + CreateStreamMuxConfig(hLatmConfig, dataBuffer, 0, &hTpEnc->callbacks); + *confType = 1; /* config is SMC */ + break; + default: + if (transportEnc_writeASC(dataBuffer, cc, &hTpEnc->callbacks) != 0) { + tpErr = TRANSPORTENC_UNKOWN_ERROR; + } + } + + return tpErr; +} + +TRANSPORTENC_ERROR transportEnc_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return TRANSPORTENC_INVALID_PARAMETER; + } + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return TRANSPORTENC_UNKOWN_ERROR; + } + info += i; + + info->module_id = FDK_TPENC; + info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2); + LIB_VERSION_STRING(info); +#ifdef SUPPRESS_BUILD_DATE_INFO + info->build_date = ""; + info->build_time = ""; +#else + info->build_date = __DATE__; + info->build_time = __TIME__; +#endif + info->title = TP_LIB_TITLE; + + /* Set flags */ + info->flags = + 0 | CAPF_ADIF | CAPF_ADTS | CAPF_LATM | CAPF_LOAS | CAPF_RAWPACKETS; + + return TRANSPORTENC_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/include/limiter.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/include/limiter.h new file mode 100644 index 0000000000000..419e8917164e9 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/include/limiter.h @@ -0,0 +1,265 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): Matthias Neusinger + + Description: Hard limiter for clipping prevention + +*******************************************************************************/ + +#ifndef LIMITER_H +#define LIMITER_H + +#include "common_fix.h" +#include "FDK_audio.h" + +#define TDL_ATTACK_DEFAULT_MS (15) /* default attack time in ms */ +#define TDL_RELEASE_DEFAULT_MS (50) /* default release time in ms */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct TDLimiter { + unsigned int attack; + FIXP_DBL attackConst, releaseConst; + unsigned int attackMs, releaseMs, maxAttackMs; + FIXP_DBL threshold; + unsigned int channels, maxChannels; + UINT sampleRate, maxSampleRate; + FIXP_DBL cor, max; + FIXP_DBL* maxBuf; + FIXP_DBL* delayBuf; + unsigned int maxBufIdx, delayBufIdx; + FIXP_DBL smoothState0; + FIXP_DBL minGain; + INT scaling; +}; + +typedef enum { + TDLIMIT_OK = 0, + TDLIMIT_UNKNOWN = -1, + + __error_codes_start = -100, + + TDLIMIT_INVALID_HANDLE, + TDLIMIT_INVALID_PARAMETER, + + __error_codes_end +} TDLIMITER_ERROR; + +struct TDLimiter; +typedef struct TDLimiter* TDLimiterPtr; + +#define PCM_LIM LONG +#define FIXP_DBL2PCM_LIM(x) (x) +#define PCM_LIM2FIXP_DBL(x) (x) +#define PCM_LIM_BITS 32 +#define FIXP_PCM_LIM FIXP_DBL + +#define SAMPLE_BITS_LIM DFRACT_BITS + +/****************************************************************************** + * pcmLimiter_Reset * + * limiter: limiter handle * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_Reset(TDLimiterPtr limiter); + +/****************************************************************************** + * pcmLimiter_Destroy * + * limiter: limiter handle * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_Destroy(TDLimiterPtr limiter); + +/****************************************************************************** + * pcmLimiter_GetDelay * + * limiter: limiter handle * + * returns: exact delay caused by the limiter in samples per channel * + ******************************************************************************/ +unsigned int pcmLimiter_GetDelay(TDLimiterPtr limiter); + +/****************************************************************************** + * pcmLimiter_GetMaxGainReduction * + * limiter: limiter handle * + * returns: maximum gain reduction in last processed block in dB * + ******************************************************************************/ +INT pcmLimiter_GetMaxGainReduction(TDLimiterPtr limiter); + +/****************************************************************************** + * pcmLimiter_SetNChannels * + * limiter: limiter handle * + * nChannels: number of channels ( <= maxChannels specified on create) * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_SetNChannels(TDLimiterPtr limiter, + unsigned int nChannels); + +/****************************************************************************** + * pcmLimiter_SetSampleRate * + * limiter: limiter handle * + * sampleRate: sampling rate in Hz ( <= maxSampleRate specified on create) * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_SetSampleRate(TDLimiterPtr limiter, UINT sampleRate); + +/****************************************************************************** + * pcmLimiter_SetAttack * + * limiter: limiter handle * + * attackMs: attack time in ms ( <= maxAttackMs specified on create) * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_SetAttack(TDLimiterPtr limiter, + unsigned int attackMs); + +/****************************************************************************** + * pcmLimiter_SetRelease * + * limiter: limiter handle * + * releaseMs: release time in ms * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_SetRelease(TDLimiterPtr limiter, + unsigned int releaseMs); + +/****************************************************************************** + * pcmLimiter_GetLibInfo * + * info: pointer to an allocated and initialized LIB_INFO structure * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_GetLibInfo(LIB_INFO* info); + +#ifdef __cplusplus +} +#endif + +/****************************************************************************** + * pcmLimiter_Create * + * maxAttackMs: maximum and initial attack/lookahead time in milliseconds * + * releaseMs: release time in milliseconds (90% time constant) * + * threshold: limiting threshold * + * maxChannels: maximum and initial number of channels * + * maxSampleRate: maximum and initial sampling rate in Hz * + * returns: limiter handle * + ******************************************************************************/ +TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs, + FIXP_DBL threshold, unsigned int maxChannels, + UINT maxSampleRate); + +/****************************************************************************** + * pcmLimiter_SetThreshold * + * limiter: limiter handle * + * threshold: limiter threshold * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter, + FIXP_DBL threshold); + +/****************************************************************************** + * pcmLimiter_Apply * + * limiter: limiter handle * + * samplesIn: pointer to input buffer containing interleaved samples * + * samplesOut: pointer to output buffer containing interleaved samples * + * pGainPerSample: pointer to gains for each sample * + * scaling: scaling of output samples * + * nSamples: number of samples per channel * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, + INT_PCM* samplesOut, FIXP_DBL* pGainPerSample, + const INT scaling, const UINT nSamples); + +#endif /* #ifndef LIMITER_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/include/pcm_utils.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/include/pcm_utils.h new file mode 100644 index 0000000000000..073bcfcb8899e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/include/pcm_utils.h @@ -0,0 +1,131 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): Alfonso Pino Garcia + + Description: Functions that perform (de)interleaving combined with format +change + +*******************************************************************************/ + +#if !defined(PCM_UTILS_H) +#define PCM_UTILS_H + +#include "common_fix.h" + +void FDK_interleave(const FIXP_DBL *RESTRICT pIn, LONG *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); +void FDK_interleave(const FIXP_DBL *RESTRICT pIn, SHORT *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); +void FDK_interleave(const FIXP_SGL *RESTRICT pIn, SHORT *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); + +void FDK_deinterleave(const LONG *RESTRICT pIn, SHORT *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); +void FDK_deinterleave(const LONG *RESTRICT pIn, LONG *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); +void FDK_deinterleave(const SHORT *RESTRICT pIn, SHORT *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); +void FDK_deinterleave(const SHORT *RESTRICT pIn, LONG *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); +#endif /* !defined(PCM_UTILS_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/include/pcmdmx_lib.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/include/pcmdmx_lib.h new file mode 100644 index 0000000000000..d37a851b8c82b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/include/pcmdmx_lib.h @@ -0,0 +1,460 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): Christian Griebel + + Description: + +*******************************************************************************/ + +/** + * \file pcmdmx_lib.h + * \brief FDK PCM audio mixdown library interface header file. + + \page INTRO Introduction + + + \section SCOPE Scope + + This document describes the high-level application interface and usage of the + FDK PCM audio mixdown module library developed by the Fraunhofer Institute for + Integrated Circuits (IIS). Depending on the library configuration, the module + can manipulate the number of audio channels of a given PCM signal. It can + create for example a two channel stereo audio signal from a given multi-channel + configuration (e.g. 5.1 channels). + + + \page ABBREV List of abbreviations + + \li \b AAC - Advanced Audio Coding\n + Is an audio coding standard for lossy digital audio compression standardized + by ISO and IEC, as part of the MPEG-2 (ISO/IEC 13818-7:2006) and MPEG-4 + (ISO/IEC 14496-3:2009) specifications. + + \li \b DSE - Data Stream Element\n + A syntactical element of the MPEG-2/4 Advanced Audio Coding bitstream + standardized in ISO/IEC 14496-3:2009. It can convey any kind of data associated + to one program. + + \li \b PCE - Program Config Element\n + A syntactical element of the MPEG-2/4 Advanced Audio Coding bitstream + standardized in ISO/IEC 14496-3:2009 that can define the stream configuration + for a single program. In addition it can comprise simple downmix meta data. + + */ + +#ifndef PCMDMX_LIB_H +#define PCMDMX_LIB_H + +#include "machine_type.h" +#include "common_fix.h" +#include "FDK_audio.h" +#include "FDK_bitstream.h" + +/** + * \enum PCMDMX_ERROR + * + * Error codes that can be returned by module interface functions. + */ +typedef enum { + PCMDMX_OK = 0x0, /*!< No error happened. */ + PCMDMX_UNSUPPORTED = + 0x1, /*!< The requested feature/service is unavailable. This can + occur if the module was built for a wrong configuration. */ + pcm_dmx_fatal_error_start, + PCMDMX_OUT_OF_MEMORY, /*!< Not enough memory to set up an instance of the + module. */ + pcm_dmx_fatal_error_end, + + PCMDMX_INVALID_HANDLE, /*!< The given instance handle is not valid. */ + PCMDMX_INVALID_ARGUMENT, /*!< One of the parameters handed over is invalid. */ + PCMDMX_INVALID_CH_CONFIG, /*!< The given channel configuration is not + supported and thus no processing was performed. + */ + PCMDMX_INVALID_MODE, /*!< The set configuration/mode is not applicable. */ + PCMDMX_UNKNOWN_PARAM, /*!< The handed parameter is not known/supported. */ + PCMDMX_UNABLE_TO_SET_PARAM, /*!< Unable to set the specific parameter. Most + probably the value ist out of range. + */ + PCMDMX_CORRUPT_ANC_DATA, /*!< The read ancillary data was corrupt. */ + PCMDMX_OUTPUT_BUFFER_TOO_SMALL /*!< The size of pcm output buffer is too + small. */ + +} PCMDMX_ERROR; + +/** Macro to identify fatal errors. */ +#define PCMDMX_IS_FATAL_ERROR(err) \ + ((((err) >= pcm_dmx_fatal_error_start) && \ + ((err) <= pcm_dmx_fatal_error_end)) \ + ? 1 \ + : 0) + +/** + * \enum PCMDMX_PARAM + * + * Modules dynamic runtime parameters that can be handed to function + * pcmDmx_SetParam() and pcmDmx_GetParam(). + */ +typedef enum { + DMX_PROFILE_SETTING = + 0x01, /*!< Defines which equations, coefficients and default/ + fallback values used for downmixing. See + ::DMX_PROFILE_TYPE type for details. */ + DMX_BS_DATA_EXPIRY_FRAME = + 0x10, /*!< The number of frames without new metadata that + have to go by before the bitstream data expires. + The value 0 disables expiry. */ + DMX_BS_DATA_DELAY = + 0x11, /*!< The number of delay frames of the output samples + compared to the bitstream data. */ + MIN_NUMBER_OF_OUTPUT_CHANNELS = + 0x20, /*!< The minimum number of output channels. For all + input configurations that have less than the given + channels the module will modify the output + automatically to obtain the given number of output + channels. Mono signals will be duplicated. If more + than two output channels are desired the module + just adds empty channels. The parameter value must + be either -1, 0, 1, 2, 6 or 8. If the value is + greater than zero and exceeds the value of + parameter ::MAX_NUMBER_OF_OUTPUT_CHANNELS the + latter will be set to the same value. Both values + -1 and 0 disable the feature. */ + MAX_NUMBER_OF_OUTPUT_CHANNELS = + 0x21, /*!< The maximum number of output channels. For all + input configurations that have more than the given + channels the module will apply a mixdown + automatically to obtain the given number of output + channels. The value must be either -1, 0, 1, 2, 6 + or 8. If it's greater than zero and lower or equal + than the value of ::MIN_NUMBER_OF_OUTPUT_CHANNELS + parameter the latter will be set to the same value. + The values -1 and 0 disable the feature. */ + DMX_DUAL_CHANNEL_MODE = + 0x30, /*!< Downmix mode for two channel audio data. See type + ::DUAL_CHANNEL_MODE for details. */ + DMX_PSEUDO_SURROUND_MODE = + 0x31 /*!< Defines how module handles pseudo surround + compatible signals. See ::PSEUDO_SURROUND_MODE + type for details. */ +} PCMDMX_PARAM; + +/** + * \enum DMX_PROFILE_TYPE + * + * Valid value list for parameter ::DMX_PROFILE_SETTING. + */ +typedef enum { + DMX_PRFL_STANDARD = + 0x0, /*!< The standard profile creates mixdown signals based on + the advanced downmix metadata (from a DSE), equations + and default values defined in ISO/IEC 14496:3 + Ammendment 4. Any other (legacy) downmix metadata will + be ignored. */ + DMX_PRFL_MATRIX_MIX = + 0x1, /*!< This profile behaves just as the standard profile if + advanced downmix metadata (from a DSE) is available. If + not, the matrix_mixdown information embedded in the + program configuration element (PCE) will be applied. If + neither is the case the module creates a mixdown using + the default coefficients defined in MPEG-4 Ammendment 4. + The profile can be used e.g. to support legacy digital + TV (e.g. DVB) streams. */ + DMX_PRFL_FORCE_MATRIX_MIX = + 0x2, /*!< Similar to the ::DMX_PRFL_MATRIX_MIX profile but if both + the advanced (DSE) and the legacy (PCE) MPEG downmix + metadata are available the latter will be applied. */ + DMX_PRFL_ARIB_JAPAN = + 0x3 /*!< Downmix creation as described in ABNT NBR 15602-2. But + if advanced downmix metadata is available it will be + prefered. */ +} DMX_PROFILE_TYPE; + +/** + * \enum PSEUDO_SURROUND_MODE + * + * Valid value list for parameter ::DMX_PSEUDO_SURROUND_MODE. + */ +typedef enum { + NEVER_DO_PS_DMX = + -1, /*!< Ignore any metadata and do never create a pseudo surround + compatible downmix. (Default) */ + AUTO_PS_DMX = 0, /*!< Create a pseudo surround compatible downmix only if + signalled in bitstreams meta data. */ + FORCE_PS_DMX = + 1 /*!< Always create a pseudo surround compatible downmix. + CAUTION: This can lead to excessive signal cancellations + and signal level differences for non-compatible signals. */ +} PSEUDO_SURROUND_MODE; + +/** + * \enum DUAL_CHANNEL_MODE + * + * Valid value list for parameter ::DMX_DUAL_CHANNEL_MODE. + */ +typedef enum { + STEREO_MODE = 0x0, /*!< Leave stereo signals as they are. */ + CH1_MODE = 0x1, /*!< Create a dual mono output signal from channel 1. */ + CH2_MODE = 0x2, /*!< Create a dual mono output signal from channel 2. */ + MIXED_MODE = 0x3 /*!< Create a dual mono output signal by mixing the two + channels. */ +} DUAL_CHANNEL_MODE; + +#define DMX_PCM FIXP_DBL +#define DMX_PCMF FIXP_DBL +#define DMX_PCM_BITS DFRACT_BITS +#define FX_DMX2FX_PCM(x) FX_DBL2FX_PCM((FIXP_DBL)(x)) + +/* ------------------------ * + * MODULES INTERFACE: * + * ------------------------ */ +typedef struct PCM_DMX_INSTANCE *HANDLE_PCM_DOWNMIX; + +/*! \addtogroup pcmDmxResetFlags Modules reset flags + * Macros that can be used as parameter for function pcmDmx_Reset() to specify + * which parts of the module shall be reset. + * @{ + * + * \def PCMDMX_RESET_PARAMS + * Only reset the user specific parameters that have been modified with + * pcmDmx_SetParam(). + * + * \def PCMDMX_RESET_BS_DATA + * Delete the meta data that has been fed with the appropriate interface + * functions. + * + * \def PCMDMX_RESET_FULL + * Reset the complete module instance to the state after pcmDmx_Open() had been + * called. + */ +#define PCMDMX_RESET_PARAMS (1) +#define PCMDMX_RESET_BS_DATA (2) +#define PCMDMX_RESET_FULL (PCMDMX_RESET_PARAMS | PCMDMX_RESET_BS_DATA) +/*! @} */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Open and initialize an instance of the PCM downmix module + * @param[out] pSelf Pointer to a buffer receiving the handle of the new + *instance. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_Open(HANDLE_PCM_DOWNMIX *pSelf); + +/** Set one parameter for a single instance of the PCM downmix module. + * @param[in] self Handle of PCM downmix instance. + * @param[in] param Parameter to be set. Can be one from the ::PCMDMX_PARAM + *list. + * @param[in] value Parameter value. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_SetParam(HANDLE_PCM_DOWNMIX self, const PCMDMX_PARAM param, + const INT value); + +/** Get one parameter value of a single PCM downmix module instance. + * @param[in] self Handle of PCM downmix module instance. + * @param[in] param Parameter to query. Can be one from the ::PCMDMX_PARAM + *list. + * @param[out] pValue Pointer to buffer receiving the parameter value. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_GetParam(HANDLE_PCM_DOWNMIX self, const PCMDMX_PARAM param, + INT *const pValue); + +/** \cond + * Extract relevant downmix meta-data directly from a given bitstream. The + *function can handle both data specified in ETSI TS 101 154 or ISO/IEC + *14496-3:2009/Amd.4:2013. + * @param[in] self Handle of PCM downmix instance. + * @param[in] hBitStream Handle of FDK bitstream buffer. + * @param[in] ancDataBits Length of ancillary data in bits. + * @param[in] isMpeg2 Flag indicating wheter the ancillary data is from a + *MPEG-1/2 or a MPEG-4 stream. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_Parse(HANDLE_PCM_DOWNMIX self, + HANDLE_FDK_BITSTREAM hBitStream, UINT ancDataBits, + int isMpeg2); +/** \endcond */ + +/** Read from a given ancillary data buffer and extract the relevant downmix + *meta-data. The function can handle both data specified in ETSI TS 101 154 or + *ISO/IEC 14496-3:2009/Amd.4:2013. + * @param[in] self Handle of PCM downmix instance. + * @param[in] pAncDataBuf Pointer to ancillary buffer holding the data. + * @param[in] ancDataBytes Size of ancillary data in bytes. + * @param[in] isMpeg2 Flag indicating wheter the ancillary data is from a + *MPEG-1/2 or a MPEG-4 stream. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_ReadDvbAncData(HANDLE_PCM_DOWNMIX self, UCHAR *pAncDataBuf, + UINT ancDataBytes, int isMpeg2); + +/** Set the matrix mixdown information extracted from the PCE of an AAC + *bitstream. + * @param[in] self Handle of PCM downmix instance. + * @param[in] matrixMixdownPresent Matrix mixdown index present flag extracted + *from PCE. + * @param[in] matrixMixdownIdx The 2 bit matrix mixdown index extracted + *from PCE. + * @param[in] pseudoSurroundEnable The pseudo surround enable flag extracted + *from PCE. + * @returns Returns an error code of type + *::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_SetMatrixMixdownFromPce(HANDLE_PCM_DOWNMIX self, + int matrixMixdownPresent, + int matrixMixdownIdx, + int pseudoSurroundEnable); + +/** Reset the module. + * @param[in] self Handle of PCM downmix instance. + * @param[in] flags Flags telling which parts of the module shall be reset. + * See \ref pcmDmxResetFlags for details. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_Reset(HANDLE_PCM_DOWNMIX self, UINT flags); + +/** Create a mixdown, bypass or extend the output signal depending on the + *modules settings and the respective given input configuration. + * + * \param[in] self Handle of PCM downmix module instance. + * \param[in,out] pPcmBuf Pointer to time buffer with PCM samples. + * \param[in] pcmBufSize Size of pPcmBuf buffer. + * \param[in] frameSize The I/O block size which is the number of samples per channel. + * \param[in,out] nChannels Pointer to buffer that holds the number of input channels and + * where the amount of output channels is written + *to. + * \param[in] fInterleaved Input and output samples are processed interleaved. + * \param[in,out] channelType Array were the corresponding channel type for each output audio + * channel is stored into. + * \param[in,out] channelIndices Array were the corresponding channel type index for each output + * audio channel is stored into. + * \param[in] mapDescr Pointer to a FDK channel mapping descriptor that contains the + * channel mapping to be used. + * \param[out] pDmxOutScale Pointer on a field receiving the scale factor that has to be + * applied on all samples afterwards. If the + *handed pointer is NULL the final scaling is done internally. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_ApplyFrame(HANDLE_PCM_DOWNMIX self, DMX_PCM *pPcmBuf, + const int pcmBufSize, UINT frameSize, + INT *nChannels, INT fInterleaved, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const FDK_channelMapDescr *const mapDescr, + INT *pDmxOutScale); + +/** Close an instance of the PCM downmix module. + * @param[in,out] pSelf Pointer to a buffer containing the handle of the + *instance. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_Close(HANDLE_PCM_DOWNMIX *pSelf); + +/** Get library info for this module. + * @param[out] info Pointer to an allocated LIB_INFO structure. + * @returns Returns an error code of type ::PCMDMX_ERROR. + */ +PCMDMX_ERROR pcmDmx_GetLibInfo(LIB_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif /* PCMDMX_LIB_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/limiter.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/limiter.cpp new file mode 100644 index 0000000000000..c6b868751d77d --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/limiter.cpp @@ -0,0 +1,555 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): Matthias Neusinger + + Description: Hard limiter for clipping prevention + +*******************************************************************************/ + +#include "limiter.h" +#include "FDK_core.h" + +/* library version */ +#include "version.h" +/* library title */ +#define TDLIMIT_LIB_TITLE "TD Limiter Lib" + +/* create limiter */ +TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs, + FIXP_DBL threshold, unsigned int maxChannels, + UINT maxSampleRate) { + TDLimiterPtr limiter = NULL; + unsigned int attack, release; + FIXP_DBL attackConst, releaseConst, exponent; + INT e_ans; + + /* calc attack and release time in samples */ + attack = (unsigned int)(maxAttackMs * maxSampleRate / 1000); + release = (unsigned int)(releaseMs * maxSampleRate / 1000); + + /* alloc limiter struct */ + limiter = (TDLimiterPtr)FDKcalloc(1, sizeof(struct TDLimiter)); + if (!limiter) return NULL; + + /* alloc max and delay buffers */ + limiter->maxBuf = (FIXP_DBL*)FDKcalloc(attack + 1, sizeof(FIXP_DBL)); + limiter->delayBuf = + (FIXP_DBL*)FDKcalloc(attack * maxChannels, sizeof(FIXP_DBL)); + + if (!limiter->maxBuf || !limiter->delayBuf) { + pcmLimiter_Destroy(limiter); + return NULL; + } + + /* attackConst = pow(0.1, 1.0 / (attack + 1)) */ + exponent = invFixp(attack + 1); + attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + attackConst = scaleValue(attackConst, e_ans); + + /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */ + exponent = invFixp(release + 1); + releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + releaseConst = scaleValue(releaseConst, e_ans); + + /* init parameters */ + limiter->attackMs = maxAttackMs; + limiter->maxAttackMs = maxAttackMs; + limiter->releaseMs = releaseMs; + limiter->attack = attack; + limiter->attackConst = attackConst; + limiter->releaseConst = releaseConst; + limiter->threshold = threshold; + limiter->channels = maxChannels; + limiter->maxChannels = maxChannels; + limiter->sampleRate = maxSampleRate; + limiter->maxSampleRate = maxSampleRate; + + pcmLimiter_Reset(limiter); + + return limiter; +} + +/* apply limiter */ +TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, + INT_PCM* samplesOut, FIXP_DBL* pGainPerSample, + const INT scaling, const UINT nSamples) { + unsigned int i, j; + FIXP_DBL tmp2; + FIXP_DBL tmp, old, gain, additionalGain = 0; + FIXP_DBL minGain = FL2FXCONST_DBL(1.0f / (1 << 1)); + UINT additionalGainAvailable = 1; + + if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; + + { + unsigned int channels = limiter->channels; + unsigned int attack = limiter->attack; + FIXP_DBL attackConst = limiter->attackConst; + FIXP_DBL releaseConst = limiter->releaseConst; + FIXP_DBL threshold = limiter->threshold >> scaling; + + FIXP_DBL max = limiter->max; + FIXP_DBL* maxBuf = limiter->maxBuf; + unsigned int maxBufIdx = limiter->maxBufIdx; + FIXP_DBL cor = limiter->cor; + FIXP_DBL* delayBuf = limiter->delayBuf; + unsigned int delayBufIdx = limiter->delayBufIdx; + + FIXP_DBL smoothState0 = limiter->smoothState0; + + if (limiter->scaling != scaling) { + scaleValuesSaturate(delayBuf, attack * channels, + limiter->scaling - scaling); + scaleValuesSaturate(maxBuf, attack + 1, limiter->scaling - scaling); + max = scaleValueSaturate(max, limiter->scaling - scaling); + limiter->scaling = scaling; + } + + if (pGainPerSample == NULL) { + additionalGainAvailable = 0; + } + + for (i = 0; i < nSamples; i++) { + /* get maximum absolute sample value of all channels, including the + * additional gain. */ + tmp = (FIXP_DBL)0; + for (j = 0; j < channels; j++) { + tmp2 = PCM_LIM2FIXP_DBL(samplesIn[j]); + tmp2 = + (tmp2 == (FIXP_DBL)MINVAL_DBL) ? (FIXP_DBL)MAXVAL_DBL : fAbs(tmp2); + tmp = fMax(tmp, tmp2); + } + + if (additionalGainAvailable) { + additionalGain = pGainPerSample[i]; + tmp = fMult(tmp, additionalGain); + } + + /* set threshold as lower border to save calculations in running maximum + * algorithm */ + tmp = fMax(tmp, threshold); + + /* running maximum */ + old = maxBuf[maxBufIdx]; + maxBuf[maxBufIdx] = tmp; + + if (tmp >= max) { + /* new sample is greater than old maximum, so it is the new maximum */ + max = tmp; + } else if (old < max) { + /* maximum does not change, as the sample, which has left the window was + not the maximum */ + } else { + /* the old maximum has left the window, we have to search the complete + buffer for the new max */ + max = maxBuf[0]; + for (j = 1; j <= attack; j++) { + max = fMax(max, maxBuf[j]); + } + } + maxBufIdx++; + if (maxBufIdx >= attack + 1) maxBufIdx = 0; + + /* calc gain */ + /* gain is downscaled by one, so that gain = 1.0 can be represented */ + if (max > threshold) { + gain = fDivNorm(threshold, max) >> 1; + } else { + gain = FL2FXCONST_DBL(1.0f / (1 << 1)); + } + + /* gain smoothing, method: TDL_EXPONENTIAL */ + /* first order IIR filter with attack correction to avoid overshoots */ + + /* correct the 'aiming' value of the exponential attack to avoid the + * remaining overshoot */ + if (gain < smoothState0) { + cor = fMin(cor, + fMultDiv2((gain - fMultDiv2(FL2FXCONST_SGL(0.1f * (1 << 1)), + smoothState0)), + FL2FXCONST_SGL(1.11111111f / (1 << 1))) + << 2); + } else { + cor = gain; + } + + /* smoothing filter */ + if (cor < smoothState0) { + smoothState0 = + fMult(attackConst, (smoothState0 - cor)) + cor; /* attack */ + smoothState0 = fMax(smoothState0, gain); /* avoid overshooting target */ + } else { + /* sign inversion twice to round towards +infinity, + so that gain can converge to 1.0 again, + for bit-identical output when limiter is not active */ + smoothState0 = + -fMult(releaseConst, -(smoothState0 - cor)) + cor; /* release */ + } + + gain = smoothState0; + + FIXP_DBL* p_delayBuf = &delayBuf[delayBufIdx * channels + 0]; + if (gain < FL2FXCONST_DBL(1.0f / (1 << 1))) { + gain <<= 1; + /* lookahead delay, apply gain */ + for (j = 0; j < channels; j++) { + tmp = p_delayBuf[j]; + + if (additionalGainAvailable) { + p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain); + } else { + p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]); + } + + /* Apply gain to delayed signal */ + tmp = fMultDiv2(tmp, gain); +#if (SAMPLE_BITS == DFRACT_BITS) + samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM( + (FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling + 1, DFRACT_BITS)); +#else + samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT( + tmp + ((FIXP_DBL)0x8000 >> (scaling + 1)), scaling + 1, + DFRACT_BITS)); +#endif + } + gain >>= 1; + } else { + /* lookahead delay, apply gain=1.0f */ + for (j = 0; j < channels; j++) { + tmp = p_delayBuf[j]; + if (additionalGainAvailable) { + p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain); + } else { + p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]); + } + +#if (SAMPLE_BITS == DFRACT_BITS) + samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM( + (FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling, DFRACT_BITS)); +#else + samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT( + (tmp >> 1) + ((FIXP_DBL)0x8000 >> (scaling + 1)), scaling + 1, + DFRACT_BITS)); +#endif + } + } + + delayBufIdx++; + if (delayBufIdx >= attack) { + delayBufIdx = 0; + } + + /* save minimum gain factor */ + if (gain < minGain) { + minGain = gain; + } + + /* advance sample pointer by samples */ + samplesIn += channels; + samplesOut += channels; + } + + limiter->max = max; + limiter->maxBufIdx = maxBufIdx; + limiter->cor = cor; + limiter->delayBufIdx = delayBufIdx; + + limiter->smoothState0 = smoothState0; + + limiter->minGain = minGain; + + return TDLIMIT_OK; + } +} + +/* set limiter threshold */ +TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter, + FIXP_DBL threshold) { + if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; + + limiter->threshold = threshold; + + return TDLIMIT_OK; +} + +/* reset limiter */ +TDLIMITER_ERROR pcmLimiter_Reset(TDLimiterPtr limiter) { + if (limiter != NULL) { + limiter->maxBufIdx = 0; + limiter->delayBufIdx = 0; + limiter->max = (FIXP_DBL)0; + limiter->cor = FL2FXCONST_DBL(1.0f / (1 << 1)); + limiter->smoothState0 = FL2FXCONST_DBL(1.0f / (1 << 1)); + limiter->minGain = FL2FXCONST_DBL(1.0f / (1 << 1)); + limiter->scaling = 0; + + FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL)); + FDKmemset(limiter->delayBuf, 0, + limiter->attack * limiter->channels * sizeof(FIXP_DBL)); + } else { + return TDLIMIT_INVALID_HANDLE; + } + + return TDLIMIT_OK; +} + +/* destroy limiter */ +TDLIMITER_ERROR pcmLimiter_Destroy(TDLimiterPtr limiter) { + if (limiter != NULL) { + FDKfree(limiter->maxBuf); + FDKfree(limiter->delayBuf); + + FDKfree(limiter); + } else { + return TDLIMIT_INVALID_HANDLE; + } + return TDLIMIT_OK; +} + +/* get delay in samples */ +unsigned int pcmLimiter_GetDelay(TDLimiterPtr limiter) { + FDK_ASSERT(limiter != NULL); + return limiter->attack; +} + +/* get maximum gain reduction of last processed block */ +INT pcmLimiter_GetMaxGainReduction(TDLimiterPtr limiter) { + /* maximum gain reduction in dB = -20 * log10(limiter->minGain) + = -20 * log2(limiter->minGain)/log2(10) = -6.0206*log2(limiter->minGain) */ + int e_ans; + FIXP_DBL loggain, maxGainReduction; + + FDK_ASSERT(limiter != NULL); + + loggain = fLog2(limiter->minGain, 1, &e_ans); + + maxGainReduction = fMult(loggain, FL2FXCONST_DBL(-6.0206f / (1 << 3))); + + return fixp_roundToInt(maxGainReduction, (e_ans + 3)); +} + +/* set number of channels */ +TDLIMITER_ERROR pcmLimiter_SetNChannels(TDLimiterPtr limiter, + unsigned int nChannels) { + if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; + + if (nChannels > limiter->maxChannels) return TDLIMIT_INVALID_PARAMETER; + + limiter->channels = nChannels; + // pcmLimiter_Reset(limiter); + + return TDLIMIT_OK; +} + +/* set sampling rate */ +TDLIMITER_ERROR pcmLimiter_SetSampleRate(TDLimiterPtr limiter, + UINT sampleRate) { + unsigned int attack, release; + FIXP_DBL attackConst, releaseConst, exponent; + INT e_ans; + + if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; + + if (sampleRate > limiter->maxSampleRate) return TDLIMIT_INVALID_PARAMETER; + + /* update attack and release time in samples */ + attack = (unsigned int)(limiter->attackMs * sampleRate / 1000); + release = (unsigned int)(limiter->releaseMs * sampleRate / 1000); + + /* attackConst = pow(0.1, 1.0 / (attack + 1)) */ + exponent = invFixp(attack + 1); + attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + attackConst = scaleValue(attackConst, e_ans); + + /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */ + exponent = invFixp(release + 1); + releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + releaseConst = scaleValue(releaseConst, e_ans); + + limiter->attack = attack; + limiter->attackConst = attackConst; + limiter->releaseConst = releaseConst; + limiter->sampleRate = sampleRate; + + /* reset */ + // pcmLimiter_Reset(limiter); + + return TDLIMIT_OK; +} + +/* set attack time */ +TDLIMITER_ERROR pcmLimiter_SetAttack(TDLimiterPtr limiter, + unsigned int attackMs) { + unsigned int attack; + FIXP_DBL attackConst, exponent; + INT e_ans; + + if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; + + if (attackMs > limiter->maxAttackMs) return TDLIMIT_INVALID_PARAMETER; + + /* calculate attack time in samples */ + attack = (unsigned int)(attackMs * limiter->sampleRate / 1000); + + /* attackConst = pow(0.1, 1.0 / (attack + 1)) */ + exponent = invFixp(attack + 1); + attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + attackConst = scaleValue(attackConst, e_ans); + + limiter->attack = attack; + limiter->attackConst = attackConst; + limiter->attackMs = attackMs; + + return TDLIMIT_OK; +} + +/* set release time */ +TDLIMITER_ERROR pcmLimiter_SetRelease(TDLimiterPtr limiter, + unsigned int releaseMs) { + unsigned int release; + FIXP_DBL releaseConst, exponent; + INT e_ans; + + if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; + + /* calculate release time in samples */ + release = (unsigned int)(releaseMs * limiter->sampleRate / 1000); + + /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */ + exponent = invFixp(release + 1); + releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + releaseConst = scaleValue(releaseConst, e_ans); + + limiter->releaseConst = releaseConst; + limiter->releaseMs = releaseMs; + + return TDLIMIT_OK; +} + +/* Get library info for this module. */ +TDLIMITER_ERROR pcmLimiter_GetLibInfo(LIB_INFO* info) { + int i; + + if (info == NULL) { + return TDLIMIT_INVALID_PARAMETER; + } + + /* Search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return TDLIMIT_UNKNOWN; + } + + /* Add the library info */ + info[i].module_id = FDK_TDLIMIT; + info[i].version = + LIB_VERSION(PCMUTIL_LIB_VL0, PCMUTIL_LIB_VL1, PCMUTIL_LIB_VL2); + LIB_VERSION_STRING(info + i); + info[i].build_date = PCMUTIL_LIB_BUILD_DATE; + info[i].build_time = PCMUTIL_LIB_BUILD_TIME; + info[i].title = TDLIMIT_LIB_TITLE; + + /* Set flags */ + info[i].flags = CAPF_LIMITER; + + /* Add lib info for FDK tools (if not yet done). */ + FDK_toolsGetLibInfo(info); + + return TDLIMIT_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/pcm_utils.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/pcm_utils.cpp new file mode 100644 index 0000000000000..5dd18d94cebc0 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/pcm_utils.cpp @@ -0,0 +1,195 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): Arthur Tritthart, Alfonso Pino Garcia + + Description: Functions that perform (de)interleaving combined with format +change + +*******************************************************************************/ + +#include "pcm_utils.h" + +/* library version */ +#include "version.h" + +void FDK_interleave(const FIXP_DBL *RESTRICT pIn, LONG *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT sample = 0; sample < length; sample++) { + const FIXP_DBL *In = &pIn[sample]; + for (UINT ch = 0; ch < channels; ch++) { + *pOut++ = (LONG)In[0]; + In += frameSize; + } + } +} + +void FDK_interleave(const FIXP_DBL *RESTRICT pIn, SHORT *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT sample = 0; sample < length; sample++) { + const FIXP_DBL *In = &pIn[sample]; + for (UINT ch = 0; ch < channels; ch++) { + *pOut++ = (SHORT)FX_DBL2FX_SGL(In[0]); + In += frameSize; + } + } +} + +void FDK_interleave(const FIXP_SGL *RESTRICT pIn, SHORT *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT sample = 0; sample < length; sample++) { + const FIXP_SGL *In = &pIn[sample]; + for (UINT ch = 0; ch < channels; ch++) { + *pOut++ = (SHORT)In[0]; + In += frameSize; + } + } +} + +void FDK_deinterleave(const LONG *RESTRICT pIn, SHORT *RESTRICT _pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT ch = 0; ch < channels; ch++) { + SHORT *pOut = _pOut + length * ch; + const LONG *In = &pIn[ch]; + for (UINT sample = 0; sample < frameSize; sample++) { + *pOut++ = (SHORT)(In[0] >> 16); + In += channels; + } + } +} + +void FDK_deinterleave(const LONG *RESTRICT pIn, LONG *RESTRICT _pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT ch = 0; ch < channels; ch++) { + LONG *pOut = _pOut + length * ch; + const LONG *In = &pIn[ch]; + for (UINT sample = 0; sample < frameSize; sample++) { + *pOut++ = In[0]; + In += channels; + } + } +} + +void FDK_deinterleave(const SHORT *RESTRICT pIn, SHORT *RESTRICT _pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT ch = 0; ch < channels; ch++) { + SHORT *pOut = _pOut + length * ch; + const SHORT *In = &pIn[ch]; + for (UINT sample = 0; sample < frameSize; sample++) { + *pOut++ = In[0]; + In += channels; + } + } +} + +void FDK_deinterleave(const SHORT *RESTRICT pIn, LONG *RESTRICT _pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT ch = 0; ch < channels; ch++) { + LONG *pOut = _pOut + length * ch; + const SHORT *In = &pIn[ch]; + for (UINT sample = 0; sample < frameSize; sample++) { + *pOut++ = (LONG)In[0] << 16; + In += channels; + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/pcmdmx_lib.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/pcmdmx_lib.cpp new file mode 100644 index 0000000000000..fca12ce5f5fbb --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/pcmdmx_lib.cpp @@ -0,0 +1,2690 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): Christian Griebel + + Description: Defines functions that perform downmixing or a simple channel + expansion in the PCM time domain. + +*******************************************************************************/ + +#include "pcmdmx_lib.h" + +#include "genericStds.h" +#include "fixpoint_math.h" +#include "FDK_core.h" + +/* library version */ +#include "version.h" +/* library title */ +#define PCMDMX_LIB_TITLE "PCM Downmix Lib" + +#define FALSE 0 +#define TRUE 1 +#define IN 0 +#define OUT 1 + +/* Type definitions: */ +#define FIXP_DMX FIXP_SGL +#define FX_DMX2FX_DBL(x) FX_SGL2FX_DBL((FIXP_SGL)(x)) +#define FX_DBL2FX_DMX(x) FX_DBL2FX_SGL(x) +#define FL2FXCONST_DMX(x) FL2FXCONST_SGL(x) +#define MAXVAL_DMX MAXVAL_SGL +#define FX_DMX2SHRT(x) ((SHORT)(x)) +#define FX_DMX2FL(x) FX_DBL2FL(FX_DMX2FX_DBL(x)) + +/* Fixed and unique channel group indices. + * The last group index has to be smaller than ( 4 ). */ +#define CH_GROUP_FRONT (0) +#define CH_GROUP_SIDE (1) +#define CH_GROUP_REAR (2) +#define CH_GROUP_LFE (3) + +/* Fixed and unique channel plain indices. */ +#define CH_PLAIN_NORMAL (0) +#define CH_PLAIN_TOP (1) +#define CH_PLAIN_BOTTOM (2) + +/* The ordering of the following fixed channel labels has to be in MPEG-4 style. + * From the center to the back with left and right channel interleaved (starting + * with left). The last channel label index has to be smaller than ( 8 ). */ +#define CENTER_FRONT_CHANNEL (0) /* C */ +#define LEFT_FRONT_CHANNEL (1) /* L */ +#define RIGHT_FRONT_CHANNEL (2) /* R */ +#define LEFT_REAR_CHANNEL \ + (3) /* Lr (aka left back channel) or center back channel */ +#define RIGHT_REAR_CHANNEL (4) /* Rr (aka right back channel) */ +#define LOW_FREQUENCY_CHANNEL (5) /* Lf */ +#define LEFT_MULTIPRPS_CHANNEL (6) /* Left multipurpose channel */ +#define RIGHT_MULTIPRPS_CHANNEL (7) /* Right multipurpose channel */ + +/* 22.2 channel specific fixed channel lables: */ +#define LEFT_SIDE_CHANNEL (8) /* Lss */ +#define RIGHT_SIDE_CHANNEL (9) /* Rss */ +#define CENTER_REAR_CHANNEL (10) /* Cs */ +#define CENTER_FRONT_CHANNEL_TOP (11) /* Cv */ +#define LEFT_FRONT_CHANNEL_TOP (12) /* Lv */ +#define RIGHT_FRONT_CHANNEL_TOP (13) /* Rv */ +#define LEFT_SIDE_CHANNEL_TOP (14) /* Lvss */ +#define RIGHT_SIDE_CHANNEL_TOP (15) /* Rvss */ +#define CENTER_SIDE_CHANNEL_TOP (16) /* Ts */ +#define LEFT_REAR_CHANNEL_TOP (17) /* Lvr */ +#define RIGHT_REAR_CHANNEL_TOP (18) /* Rvr */ +#define CENTER_REAR_CHANNEL_TOP (19) /* Cvr */ +#define CENTER_FRONT_CHANNEL_BOTTOM (20) /* Cb */ +#define LEFT_FRONT_CHANNEL_BOTTOM (21) /* Lb */ +#define RIGHT_FRONT_CHANNEL_BOTTOM (22) /* Rb */ +#define LOW_FREQUENCY_CHANNEL_2 (23) /* LFE2 */ + +/* More constants */ +#define ONE_CHANNEL (1) +#define TWO_CHANNEL (2) +#define SIX_CHANNEL (6) +#define EIGHT_CHANNEL (8) +#define TWENTY_FOUR_CHANNEL (24) + +#define PCMDMX_THRESHOLD_MAP_HEAT_1 (0) /* Store only exact matches */ +#define PCMDMX_THRESHOLD_MAP_HEAT_2 (20) +#define PCMDMX_THRESHOLD_MAP_HEAT_3 \ + (256) /* Do not assign normal channels to LFE */ + +#define SP_Z_NRM (0) +#define SP_Z_TOP (2) +#define SP_Z_BOT (-2) +#define SP_Z_LFE (-18) +#define SP_Z_MUL (8) /* Should be smaller than SP_Z_LFE */ + +typedef struct { + SCHAR x; /* horizontal position: center (0), left (-), right (+) */ + SCHAR y; /* deepth position: front, side, back, position */ + SCHAR z; /* heigth positions: normal, top, bottom, lfe */ +} PCM_DMX_SPEAKER_POSITION; + +/* CAUTION: The maximum x-value should be less or equal to + * PCMDMX_SPKR_POS_X_MAX_WIDTH. */ +static const PCM_DMX_SPEAKER_POSITION spkrSlotPos[] = { + /* x, y, z */ + {0, 0, SP_Z_NRM}, /* 0 CENTER_FRONT_CHANNEL */ + {-2, 0, SP_Z_NRM}, /* 1 LEFT_FRONT_CHANNEL */ + {2, 0, SP_Z_NRM}, /* 2 RIGHT_FRONT_CHANNEL */ + {-3, 4, SP_Z_NRM}, /* 3 LEFT_REAR_CHANNEL */ + {3, 4, SP_Z_NRM}, /* 4 RIGHT_REAR_CHANNEL */ + {0, 0, SP_Z_LFE}, /* 5 LOW_FREQUENCY_CHANNEL */ + {-2, 2, SP_Z_MUL}, /* 6 LEFT_MULTIPRPS_CHANNEL */ + {2, 2, SP_Z_MUL} /* 7 RIGHT_MULTIPRPS_CHANNEL */ +}; + +/* List of packed channel modes */ +typedef enum { /* CH_MODE____ */ + CH_MODE_UNDEFINED = 0x0000, + /* 1 channel */ + CH_MODE_1_0_0_0 = 0x0001, /* chCfg 1 */ + /* 2 channels */ + CH_MODE_2_0_0_0 = 0x0002 /* chCfg 2 */ + /* 3 channels */ + , + CH_MODE_3_0_0_0 = 0x0003, /* chCfg 3 */ + CH_MODE_2_0_1_0 = 0x0102, + CH_MODE_2_0_0_1 = 0x1002, + /* 4 channels */ + CH_MODE_3_0_1_0 = 0x0103, /* chCfg 4 */ + CH_MODE_2_0_2_0 = 0x0202, + CH_MODE_2_0_1_1 = 0x1102, + CH_MODE_4_0_0_0 = 0x0004, + /* 5 channels */ + CH_MODE_3_0_2_0 = 0x0203, /* chCfg 5 */ + CH_MODE_2_0_2_1 = 0x1202, + CH_MODE_3_0_1_1 = 0x1103, + CH_MODE_3_2_0_0 = 0x0023, + CH_MODE_5_0_0_0 = 0x0005, + /* 6 channels */ + CH_MODE_3_0_2_1 = 0x1203, /* chCfg 6 */ + CH_MODE_3_2_0_1 = 0x1023, + CH_MODE_3_2_1_0 = 0x0123, + CH_MODE_5_0_1_0 = 0x0105, + CH_MODE_6_0_0_0 = 0x0006, + /* 7 channels */ + CH_MODE_2_2_2_1 = 0x1222, + CH_MODE_3_0_3_1 = 0x1303, /* chCfg 11 */ + CH_MODE_3_2_1_1 = 0x1123, + CH_MODE_3_2_2_0 = 0x0223, + CH_MODE_3_0_2_2 = 0x2203, + CH_MODE_5_0_2_0 = 0x0205, + CH_MODE_5_0_1_1 = 0x1105, + CH_MODE_7_0_0_0 = 0x0007, + /* 8 channels */ + CH_MODE_3_2_2_1 = 0x1223, + CH_MODE_3_0_4_1 = 0x1403, /* chCfg 12 */ + CH_MODE_5_0_2_1 = 0x1205, /* chCfg 7 + 14 */ + CH_MODE_5_2_1_0 = 0x0125, + CH_MODE_3_2_1_2 = 0x2123, + CH_MODE_2_2_2_2 = 0x2222, + CH_MODE_3_0_3_2 = 0x2303, + CH_MODE_8_0_0_0 = 0x0008 + +} PCM_DMX_CHANNEL_MODE; + +/* These are the channel configurations linked to + the number of output channels give by the user: */ +static const PCM_DMX_CHANNEL_MODE outChModeTable[(8) + 1] = { + CH_MODE_UNDEFINED, + CH_MODE_1_0_0_0, /* 1 channel */ + CH_MODE_2_0_0_0 /* 2 channels */ + , + CH_MODE_3_0_0_0, /* 3 channels */ + CH_MODE_3_0_1_0, /* 4 channels */ + CH_MODE_3_0_2_0, /* 5 channels */ + CH_MODE_3_0_2_1 /* 6 channels */ + , + CH_MODE_3_0_3_1, /* 7 channels */ + CH_MODE_3_0_4_1 /* 8 channels */ +}; + +static const FIXP_DMX abMixLvlValueTab[8] = { + FL2FXCONST_DMX(0.500f), /* scaled by 1 */ + FL2FXCONST_DMX(0.841f), FL2FXCONST_DMX(0.707f), FL2FXCONST_DMX(0.596f), + FL2FXCONST_DMX(0.500f), FL2FXCONST_DMX(0.422f), FL2FXCONST_DMX(0.355f), + FL2FXCONST_DMX(0.0f)}; + +static const FIXP_DMX lfeMixLvlValueTab[16] = { + /* value, scale */ + FL2FXCONST_DMX(0.7905f), /* 2 */ + FL2FXCONST_DMX(0.5000f), /* 2 */ + FL2FXCONST_DMX(0.8395f), /* 1 */ + FL2FXCONST_DMX(0.7065f), /* 1 */ + FL2FXCONST_DMX(0.5945f), /* 1 */ + FL2FXCONST_DMX(0.500f), /* 1 */ + FL2FXCONST_DMX(0.841f), /* 0 */ + FL2FXCONST_DMX(0.707f), /* 0 */ + FL2FXCONST_DMX(0.596f), /* 0 */ + FL2FXCONST_DMX(0.500f), /* 0 */ + FL2FXCONST_DMX(0.316f), /* 0 */ + FL2FXCONST_DMX(0.178f), /* 0 */ + FL2FXCONST_DMX(0.100f), /* 0 */ + FL2FXCONST_DMX(0.032f), /* 0 */ + FL2FXCONST_DMX(0.010f), /* 0 */ + FL2FXCONST_DMX(0.000f) /* 0 */ +}; + +/* MPEG matrix mixdown: + Set 1: L' = (1 + 2^-0.5 + A )^-1 * [L + C * 2^-0.5 + A * Ls]; + R' = (1 + 2^-0.5 + A )^-1 * [R + C * 2^-0.5 + A * Rs]; + + Set 2: L' = (1 + 2^-0.5 + 2A )^-1 * [L + C * 2^-0.5 - A * (Ls + Rs)]; + R' = (1 + 2^-0.5 + 2A )^-1 * [R + C * 2^-0.5 + A * (Ls + Rs)]; + + M = (3 + 2A)^-1 * [L + C + R + A*(Ls + Rs)]; +*/ +static const FIXP_DMX mpegMixDownIdx2Coef[4] = { + FL2FXCONST_DMX(0.70710678f), FL2FXCONST_DMX(0.5f), + FL2FXCONST_DMX(0.35355339f), FL2FXCONST_DMX(0.0f)}; + +static const FIXP_DMX mpegMixDownIdx2PreFact[3][4] = { + {/* Set 1: */ + FL2FXCONST_DMX(0.4142135623730950f), FL2FXCONST_DMX(0.4530818393219728f), + FL2FXCONST_DMX(0.4852813742385703f), FL2FXCONST_DMX(0.5857864376269050f)}, + {/* Set 2: */ + FL2FXCONST_DMX(0.3203772410170407f), FL2FXCONST_DMX(0.3693980625181293f), + FL2FXCONST_DMX(0.4142135623730950f), FL2FXCONST_DMX(0.5857864376269050f)}, + {/* Mono DMX set: */ + FL2FXCONST_DMX(0.2265409196609864f), FL2FXCONST_DMX(0.25f), + FL2FXCONST_DMX(0.2697521433898179f), FL2FXCONST_DMX(0.3333333333333333f)}}; + +#define TYPE_NONE (0x00) +#define TYPE_PCE_DATA (0x01) +#define TYPE_DSE_CLEV_DATA (0x02) +#define TYPE_DSE_SLEV_DATA (0x04) +#define TYPE_DSE_DMIX_AB_DATA (0x08) +#define TYPE_DSE_DMIX_LFE_DATA (0x10) +#define TYPE_DSE_DMX_GAIN_DATA (0x20) +#define TYPE_DSE_DMX_CGL_DATA (0x40) +#define TYPE_DSE_DATA (0x7E) + +typedef struct { + UINT typeFlags; + /* From DSE */ + UCHAR cLevIdx; + UCHAR sLevIdx; + UCHAR dmixIdxA; + UCHAR dmixIdxB; + UCHAR dmixIdxLfe; + UCHAR dmxGainIdx2; + UCHAR dmxGainIdx5; + /* From PCE */ + UCHAR matrixMixdownIdx; + /* Attributes: */ + SCHAR pseudoSurround; /*!< If set to 1 the signal is pseudo surround + compatible. The value 0 tells that it is not. If the + value is -1 the information is not available. */ + UINT expiryCount; /*!< Counter to monitor the life time of a meta data set. */ + +} DMX_BS_META_DATA; + +/* Default metadata */ +static const DMX_BS_META_DATA dfltMetaData = {0, 2, 2, 2, 2, 15, + 0, 0, 0, -1, 0}; + +/* Dynamic (user) params: + See the definition of PCMDMX_PARAM for details on the specific fields. */ +typedef struct { + DMX_PROFILE_TYPE dmxProfile; /*!< Linked to DMX_PRFL_STANDARD */ + UINT expiryFrame; /*!< Linked to DMX_BS_DATA_EXPIRY_FRAME */ + DUAL_CHANNEL_MODE dualChannelMode; /*!< Linked to DMX_DUAL_CHANNEL_MODE */ + PSEUDO_SURROUND_MODE + pseudoSurrMode; /*!< Linked to DMX_PSEUDO_SURROUND_MODE */ + SHORT numOutChannelsMin; /*!< Linked to MIN_NUMBER_OF_OUTPUT_CHANNELS */ + SHORT numOutChannelsMax; /*!< Linked to MAX_NUMBER_OF_OUTPUT_CHANNELS */ + UCHAR frameDelay; /*!< Linked to DMX_BS_DATA_DELAY */ + +} PCM_DMX_USER_PARAMS; + +/* Modules main data structure: */ +struct PCM_DMX_INSTANCE { + /* Metadata */ + DMX_BS_META_DATA bsMetaData[(1) + 1]; + PCM_DMX_USER_PARAMS userParams; + + UCHAR applyProcessing; /*!< Flag to en-/disable modules processing. + The max channel limiting is done independently. */ +}; + +/* Memory allocation macro */ +C_ALLOC_MEM(PcmDmxInstance, struct PCM_DMX_INSTANCE, 1) + +static UINT getSpeakerDistance(PCM_DMX_SPEAKER_POSITION posA, + PCM_DMX_SPEAKER_POSITION posB) { + PCM_DMX_SPEAKER_POSITION diff; + + diff.x = posA.x - posB.x; + diff.y = posA.y - posB.y; + diff.z = posA.z - posB.z; + + return ((diff.x * diff.x) + (diff.y * diff.y) + (diff.z * diff.z)); +} + +static PCM_DMX_SPEAKER_POSITION getSpeakerPos(AUDIO_CHANNEL_TYPE chType, + UCHAR chIndex, UCHAR numChInGrp) { +#define PCMDMX_SPKR_POS_X_MAX_WIDTH (3) +#define PCMDMX_SPKR_POS_Y_SPREAD (2) +#define PCMDMX_SPKR_POS_Z_SPREAD (2) + + PCM_DMX_SPEAKER_POSITION spkrPos = {0, 0, 0}; + AUDIO_CHANNEL_TYPE chGrp = (AUDIO_CHANNEL_TYPE)(chType & 0x0F); + unsigned fHasCenter = numChInGrp & 0x1; + unsigned chGrpWidth = numChInGrp >> 1; + unsigned fIsCenter = 0; + unsigned fIsLfe = (chType == ACT_LFE) ? 1 : 0; + int offset = 0; + + FDK_ASSERT(chIndex < numChInGrp); + + if ((chGrp == ACT_FRONT) && fHasCenter) { + if (chIndex == 0) fIsCenter = 1; + chIndex = (UCHAR)fMax(0, chIndex - 1); + } else if (fHasCenter && (chIndex == numChInGrp - 1)) { + fIsCenter = 1; + } + /* now all even indices are left (-) */ + if (!fIsCenter) { + offset = chIndex >> 1; + if ((chGrp > ACT_FRONT) && (chType != ACT_SIDE) && !fIsLfe) { + /* the higher the index the lower the distance to the center position */ + offset = chGrpWidth - fHasCenter - offset; + } + if ((chIndex & 0x1) == 0) { /* even */ + offset = -(offset + 1); + } else { + offset += 1; + } + } + /* apply the offset */ + if (chType == ACT_SIDE) { + spkrPos.x = (offset < 0) ? -PCMDMX_SPKR_POS_X_MAX_WIDTH + : PCMDMX_SPKR_POS_X_MAX_WIDTH; + spkrPos.y = /* 1x */ PCMDMX_SPKR_POS_Y_SPREAD + (SCHAR)fAbs(offset) - 1; + spkrPos.z = 0; + } else { + unsigned spread = + ((chGrpWidth == 1) && (!fIsLfe)) ? PCMDMX_SPKR_POS_X_MAX_WIDTH - 1 : 1; + spkrPos.x = (SCHAR)offset * (SCHAR)spread; + if (fIsLfe) { + spkrPos.y = 0; + spkrPos.z = SP_Z_LFE; + } else { + spkrPos.y = (SCHAR)fMax((SCHAR)chGrp - 1, 0) * PCMDMX_SPKR_POS_Y_SPREAD; + spkrPos.z = (SCHAR)chType >> 4; + if (spkrPos.z == 2) { /* ACT_BOTTOM */ + spkrPos.z = -1; + } + spkrPos.z *= PCMDMX_SPKR_POS_Z_SPREAD; + } + } + return spkrPos; +} + +/** Return the channel mode of a given horizontal channel plain (normal, top, + *bottom) for a given channel configuration. NOTE: This function shall get + *obsolete once the channel mode has been changed to be nonambiguous. + * @param [in] Index of the requested channel plain. + * @param [in] The packed channel mode for the complete channel configuration + *(all plains). + * @param [in] The MPEG-4 channel configuration index which is necessary in + *cases where the (packed) channel mode is ambiguous. + * @returns Returns the packed channel mode of the requested channel plain. + **/ +static PCM_DMX_CHANNEL_MODE getChMode4Plain( + const int plainIndex, const PCM_DMX_CHANNEL_MODE totChMode, + const int chCfg) { + PCM_DMX_CHANNEL_MODE plainChMode = totChMode; + + switch (totChMode) { + case CH_MODE_5_0_2_1: + if (chCfg == 14) { + switch (plainIndex) { + case CH_PLAIN_BOTTOM: + plainChMode = (PCM_DMX_CHANNEL_MODE)0x0000; + break; + case CH_PLAIN_TOP: + plainChMode = CH_MODE_2_0_0_0; + break; + case CH_PLAIN_NORMAL: + default: + plainChMode = CH_MODE_3_0_2_1; + break; + } + } + break; + default: + break; + } + + return plainChMode; +} + +/** Validates the channel indices of all channels present in the bitstream. + * The channel indices have to be consecutive and unique for each audio channel + *type. + * @param [in] The total number of channels of the given configuration. + * @param [in] The total number of channels of the current audio channel type of + *the given configuration. + * @param [in] Audio channel type to be examined. + * @param [in] Array holding the corresponding channel types for each channel. + * @param [in] Array holding the corresponding channel type indices for each + *channel. + * @returns Returns 1 on success, returns 0 on error. + **/ +static UINT validateIndices(UINT numChannels, UINT numChannelsPlaneAndGrp, + AUDIO_CHANNEL_TYPE aChType, + const AUDIO_CHANNEL_TYPE channelType[], + const UCHAR channelIndices[]) { + for (UINT reqValue = 0; reqValue < numChannelsPlaneAndGrp; reqValue++) { + int found = FALSE; + for (UINT i = 0; i < numChannels; i++) { + if (channelType[i] == aChType) { + if (channelIndices[i] == reqValue) { + if (found == TRUE) { + return 0; /* Found channel index a second time */ + } else { + found = TRUE; /* Found channel index */ + } + } + } + } + if (found == FALSE) { + return 0; /* Did not find channel index */ + } + } + return 1; /* Successfully validated channel indices */ +} + +/** Evaluate a given channel configuration and extract a packed channel mode. In + *addition the function generates a channel offset table for the mapping to the + *internal representation. This function is the inverse to the + *getChannelDescription() routine. + * @param [in] The total number of channels of the given configuration. + * @param [in] Array holding the corresponding channel types for each channel. + * @param [in] Array holding the corresponding channel type indices for each + *channel. + * @param [out] Array where the buffer offsets for each channel are stored into. + * @param [out] The generated packed channel mode that represents the given + *input configuration. + * @returns Returns an error code. + **/ +static PCMDMX_ERROR getChannelMode( + const UINT numChannels, /* in */ + const AUDIO_CHANNEL_TYPE channelType[], /* in */ + UCHAR channelIndices[], /* in */ + UCHAR offsetTable[(8)], /* out */ + PCM_DMX_CHANNEL_MODE *chMode /* out */ +) { + UCHAR numCh[(3)][(4)]; + UCHAR mapped[(8)]; + PCM_DMX_SPEAKER_POSITION spkrPos[(8)]; + PCMDMX_ERROR err = PCMDMX_OK; + unsigned ch, numMappedInChs = 0; + unsigned startSlot; + unsigned stopSlot = LOW_FREQUENCY_CHANNEL; + + FDK_ASSERT(channelType != NULL); + FDK_ASSERT(channelIndices != NULL); + FDK_ASSERT(offsetTable != NULL); + FDK_ASSERT(chMode != NULL); + + /* For details see ISO/IEC 13818-7:2005(E), 8.5.3 Channel configuration */ + FDKmemclear(numCh, (3) * (4) * sizeof(UCHAR)); + FDKmemclear(mapped, (8) * sizeof(UCHAR)); + FDKmemclear(spkrPos, (8) * sizeof(PCM_DMX_SPEAKER_POSITION)); + /* Init output */ + FDKmemset(offsetTable, 255, (8) * sizeof(UCHAR)); + *chMode = CH_MODE_UNDEFINED; + + /* Determine how many channels are assigned to each channels each group: */ + for (ch = 0; ch < numChannels; ch += 1) { + unsigned chGrp = fMax( + (channelType[ch] & 0x0F) - 1, + 0); /* Assign all undefined channels (ACT_NONE) to front channels. */ + numCh[channelType[ch] >> 4][chGrp] += 1; + } + + { + int chGrp; + /* Sanity check on the indices */ + for (chGrp = 0; chGrp < (4); chGrp += 1) { + int plane; + for (plane = 0; plane < (3); plane += 1) { + if (numCh[plane][chGrp] == 0) continue; + AUDIO_CHANNEL_TYPE aChType = + (AUDIO_CHANNEL_TYPE)((plane << 4) | ((chGrp + 1) & 0xF)); + if (!validateIndices(numChannels, numCh[plane][chGrp], aChType, + channelType, channelIndices)) { + unsigned idxCnt = 0; + for (ch = 0; ch < numChannels; ch += 1) { + if (channelType[ch] == aChType) { + channelIndices[ch] = idxCnt++; + } + } + err = PCMDMX_INVALID_CH_CONFIG; + } + } + } + } + /* Mapping HEAT 1: + * Determine the speaker position of each input channel and map it to a + * internal slot if it matches exactly (with zero distance). */ + for (ch = 0; ch < numChannels; ch += 1) { + UINT mapDist = (unsigned)-1; + unsigned mapCh, mapPos = (unsigned)-1; + unsigned chGrp = fMax( + (channelType[ch] & 0x0F) - 1, + 0); /* Assign all undefined channels (ACT_NONE) to front channels. */ + + spkrPos[ch] = getSpeakerPos(channelType[ch], channelIndices[ch], + numCh[channelType[ch] >> 4][chGrp]); + + for (mapCh = 0; mapCh <= stopSlot; mapCh += 1) { + if (offsetTable[mapCh] == 255) { + UINT dist = getSpeakerDistance(spkrPos[ch], spkrSlotPos[mapCh]); + if (dist < mapDist) { + mapPos = mapCh; + mapDist = dist; + } + } + } + if (mapDist <= PCMDMX_THRESHOLD_MAP_HEAT_1) { + offsetTable[mapPos] = (UCHAR)ch; + mapped[ch] = 1; + numMappedInChs += 1; + } + } + + /* Mapping HEAT 2: + * Go through the unmapped input channels and assign them to the internal + * slots that matches best (least distance). But assign center channels to + * center slots only. */ + startSlot = + ((numCh[CH_PLAIN_NORMAL][CH_GROUP_FRONT] & 0x1) || (numChannels >= (8))) + ? 0 + : 1; + for (ch = 0; ch < (unsigned)numChannels; ch += 1) { + if (!mapped[ch]) { + UINT mapDist = (unsigned)-1; + unsigned mapCh, mapPos = (unsigned)-1; + + for (mapCh = startSlot; mapCh <= stopSlot; mapCh += 1) { + if (offsetTable[mapCh] == 255) { + UINT dist = getSpeakerDistance(spkrPos[ch], spkrSlotPos[mapCh]); + if (dist < mapDist) { + mapPos = mapCh; + mapDist = dist; + } + } + } + if ((mapPos <= stopSlot) && (mapDist < PCMDMX_THRESHOLD_MAP_HEAT_2) && + (((spkrPos[ch].x != 0) && (spkrSlotPos[mapPos].x != 0)) /* XOR */ + || ((spkrPos[ch].x == 0) && + (spkrSlotPos[mapPos].x == + 0)))) { /* Assign center channels to center slots only. */ + offsetTable[mapPos] = (UCHAR)ch; + mapped[ch] = 1; + numMappedInChs += 1; + } + } + } + + /* Mapping HEAT 3: + * Assign the rest by searching for the nearest input channel for each + * internal slot. */ + for (ch = startSlot; (ch < (8)) && (numMappedInChs < numChannels); ch += 1) { + if (offsetTable[ch] == 255) { + UINT mapDist = (unsigned)-1; + unsigned mapCh, mapPos = (unsigned)-1; + + for (mapCh = 0; mapCh < (unsigned)numChannels; mapCh += 1) { + if (!mapped[mapCh]) { + UINT dist = getSpeakerDistance(spkrPos[mapCh], spkrSlotPos[ch]); + if (dist < mapDist) { + mapPos = mapCh; + mapDist = dist; + } + } + } + if (mapDist < PCMDMX_THRESHOLD_MAP_HEAT_3) { + offsetTable[ch] = (UCHAR)mapPos; + mapped[mapPos] = 1; + numMappedInChs += 1; + if ((spkrPos[mapPos].x == 0) && (spkrSlotPos[ch].x != 0) && + (numChannels < + (8))) { /* Skip the paired slot if we assigned a center channel. */ + ch += 1; + } + } + } + } + + /* Finaly compose the channel mode */ + for (ch = 0; ch < (4); ch += 1) { + int plane, numChInGrp = 0; + for (plane = 0; plane < (3); plane += 1) { + numChInGrp += numCh[plane][ch]; + } + *chMode = (PCM_DMX_CHANNEL_MODE)(*chMode | (numChInGrp << (ch * 4))); + } + + return err; +} + +/** Generate a channel offset table and complete channel description for a given + *(packed) channel mode. This function is the inverse to the getChannelMode() + *routine but does not support weird channel configurations. + * @param [in] The packed channel mode of the configuration to be processed. + * @param [in] Array containing the channel mapping to be used (From MPEG PCE + *ordering to whatever is required). + * @param [out] Array where corresponding channel types for each channels are + *stored into. + * @param [out] Array where corresponding channel type indices for each output + *channel are stored into. + * @param [out] Array where the buffer offsets for each channel are stored into. + * @returns None. + **/ +static void getChannelDescription( + const PCM_DMX_CHANNEL_MODE chMode, /* in */ + const FDK_channelMapDescr *const mapDescr, /* in */ + AUDIO_CHANNEL_TYPE channelType[], /* out */ + UCHAR channelIndices[], /* out */ + UCHAR offsetTable[(8)] /* out */ +) { + int grpIdx, plainIdx, numPlains = 1, numTotalChannels = 0; + int chCfg, ch = 0; + + FDK_ASSERT(channelType != NULL); + FDK_ASSERT(channelIndices != NULL); + FDK_ASSERT(mapDescr != NULL); + FDK_ASSERT(offsetTable != NULL); + + /* Init output arrays */ + FDKmemclear(channelType, (8) * sizeof(AUDIO_CHANNEL_TYPE)); + FDKmemclear(channelIndices, (8) * sizeof(UCHAR)); + FDKmemset(offsetTable, 255, (8) * sizeof(UCHAR)); + + /* Summerize to get the total number of channels */ + for (grpIdx = 0; grpIdx < (4); grpIdx += 1) { + numTotalChannels += (chMode >> (grpIdx * 4)) & 0xF; + } + + /* Get the appropriate channel map */ + switch (chMode) { + case CH_MODE_1_0_0_0: + case CH_MODE_2_0_0_0: + case CH_MODE_3_0_0_0: + case CH_MODE_3_0_1_0: + case CH_MODE_3_0_2_0: + case CH_MODE_3_0_2_1: + chCfg = numTotalChannels; + break; + case CH_MODE_3_0_3_1: + chCfg = 11; + break; + case CH_MODE_3_0_4_1: + chCfg = 12; + break; + case CH_MODE_5_0_2_1: + chCfg = 7; + break; + default: + /* fallback */ + chCfg = 0; + break; + } + + /* Compose channel offset table */ + + for (plainIdx = 0; plainIdx < numPlains; plainIdx += 1) { + PCM_DMX_CHANNEL_MODE plainChMode; + UCHAR numChInGrp[(4)]; + + plainChMode = getChMode4Plain(plainIdx, chMode, chCfg); + + /* Extract the number of channels per group */ + numChInGrp[CH_GROUP_FRONT] = plainChMode & 0xF; + numChInGrp[CH_GROUP_SIDE] = (plainChMode >> 4) & 0xF; + numChInGrp[CH_GROUP_REAR] = (plainChMode >> 8) & 0xF; + numChInGrp[CH_GROUP_LFE] = (plainChMode >> 12) & 0xF; + + /* Non-symmetric channels */ + if ((numChInGrp[CH_GROUP_FRONT] & 0x1) && (plainIdx == CH_PLAIN_NORMAL)) { + /* Odd number of front channels -> we have a center channel. + In MPEG-4 the center has the index 0. */ + int mappedIdx = FDK_chMapDescr_getMapValue(mapDescr, (UCHAR)ch, chCfg); + offsetTable[CENTER_FRONT_CHANNEL] = (UCHAR)mappedIdx; + channelType[mappedIdx] = ACT_FRONT; + channelIndices[mappedIdx] = 0; + ch += 1; + } + + for (grpIdx = 0; grpIdx < (4); grpIdx += 1) { + AUDIO_CHANNEL_TYPE type = ACT_NONE; + int chMapPos = 0, maxChannels = 0; + int chIdx = 0; /* Index of channel within the specific group */ + + switch (grpIdx) { + case CH_GROUP_FRONT: + type = (AUDIO_CHANNEL_TYPE)((plainIdx << 4) | ACT_FRONT); + switch (plainIdx) { + default: + chMapPos = LEFT_FRONT_CHANNEL; + chIdx = numChInGrp[grpIdx] & 0x1; + break; + } + maxChannels = 3; + break; + case CH_GROUP_SIDE: + /* Always map side channels to the multipurpose group. */ + type = (AUDIO_CHANNEL_TYPE)((plainIdx << 4) | ACT_SIDE); + if (plainIdx == CH_PLAIN_TOP) { + chMapPos = LEFT_SIDE_CHANNEL_TOP; + maxChannels = 3; + } else { + chMapPos = LEFT_MULTIPRPS_CHANNEL; + maxChannels = 2; + } + break; + case CH_GROUP_REAR: + type = (AUDIO_CHANNEL_TYPE)((plainIdx << 4) | ACT_BACK); + if (plainIdx == CH_PLAIN_TOP) { + chMapPos = LEFT_REAR_CHANNEL_TOP; + maxChannels = 3; + } else { + chMapPos = LEFT_REAR_CHANNEL; + maxChannels = 2; + } + break; + case CH_GROUP_LFE: + if (plainIdx == CH_PLAIN_NORMAL) { + type = ACT_LFE; + chMapPos = LOW_FREQUENCY_CHANNEL; + maxChannels = 1; + } + break; + default: + break; + } + + /* Map all channels in this group */ + for (; chIdx < numChInGrp[grpIdx]; chIdx += 1) { + int mappedIdx = FDK_chMapDescr_getMapValue(mapDescr, (UCHAR)ch, chCfg); + if ((chIdx == maxChannels) || (offsetTable[chMapPos] < 255)) { + /* No space left in this channel group! */ + if (offsetTable[LEFT_MULTIPRPS_CHANNEL] == + 255) { /* Use the multipurpose group: */ + chMapPos = LEFT_MULTIPRPS_CHANNEL; + } else { + FDK_ASSERT(0); + } + } + offsetTable[chMapPos] = (UCHAR)mappedIdx; + channelType[mappedIdx] = type; + channelIndices[mappedIdx] = (UCHAR)chIdx; + chMapPos += 1; + ch += 1; + } + } + } +} + +/** Private helper function for downmix matrix manipulation that initializes + * one row in a given downmix matrix (corresponding to one output channel). + * @param [inout] Pointer to fixed-point parts of the downmix matrix. + * @param [inout] Pointer to scale factor matrix associated to the downmix + *factors. + * @param [in] Index of channel (row) to be initialized. + * @returns Nothing to return. + **/ +static void dmxInitChannel(FIXP_DMX mixFactors[(8)][(8)], + INT mixScales[(8)][(8)], const unsigned int outCh) { + unsigned int inCh; + for (inCh = 0; inCh < (8); inCh += 1) { + if (inCh == outCh) { + mixFactors[outCh][inCh] = FL2FXCONST_DMX(0.5f); + mixScales[outCh][inCh] = 1; + } else { + mixFactors[outCh][inCh] = FL2FXCONST_DMX(0.0f); + mixScales[outCh][inCh] = 0; + } + } +} + +/** Private helper function for downmix matrix manipulation that does a reset + * of one row in a given downmix matrix (corresponding to one output channel). + * @param [inout] Pointer to fixed-point parts of the downmix matrix. + * @param [inout] Pointer to scale factor matrix associated to the downmix + *factors. + * @param [in] Index of channel (row) to be cleared/reset. + * @returns Nothing to return. + **/ +static void dmxClearChannel(FIXP_DMX mixFactors[(8)][(8)], + INT mixScales[(8)][(8)], const unsigned int outCh) { + FDK_ASSERT((outCh >= 0) && (outCh < (8))); + FDKmemclear(&mixFactors[outCh], (8) * sizeof(FIXP_DMX)); + FDKmemclear(&mixScales[outCh], (8) * sizeof(INT)); +} + +/** Private helper function for downmix matrix manipulation that applies a + *source channel (row) scaled by a given mix factor to a destination channel + *(row) in a given downmix matrix. Existing mix factors of the destination + *channel (row) will get overwritten. + * @param [inout] Pointer to fixed-point parts of the downmix matrix. + * @param [inout] Pointer to scale factor matrix associated to the downmix + *factors. + * @param [in] Index of source channel (row). + * @param [in] Index of destination channel (row). + * @param [in] Fixed-point part of mix factor to be applied. + * @param [in] Scale factor of mix factor to be applied. + * @returns Nothing to return. + **/ +static void dmxSetChannel(FIXP_DMX mixFactors[(8)][(8)], + INT mixScales[(8)][(8)], const unsigned int dstCh, + const unsigned int srcCh, const FIXP_DMX factor, + const INT scale) { + int ch; + for (ch = 0; ch < (8); ch += 1) { + if (mixFactors[srcCh][ch] != (FIXP_DMX)0) { + mixFactors[dstCh][ch] = + FX_DBL2FX_DMX(fMult(mixFactors[srcCh][ch], factor)); + mixScales[dstCh][ch] = mixScales[srcCh][ch] + scale; + } + } +} + +/** Private helper function for downmix matrix manipulation that adds a source + *channel (row) scaled by a given mix factor to a destination channel (row) in a + *given downmix matrix. + * @param [inout] Pointer to fixed-point parts of the downmix matrix. + * @param [inout] Pointer to scale factor matrix associated to the downmix + *factors. + * @param [in] Index of source channel (row). + * @param [in] Index of destination channel (row). + * @param [in] Fixed-point part of mix factor to be applied. + * @param [in] Scale factor of mix factor to be applied. + * @returns Nothing to return. + **/ +static void dmxAddChannel(FIXP_DMX mixFactors[(8)][(8)], + INT mixScales[(8)][(8)], const unsigned int dstCh, + const unsigned int srcCh, const FIXP_DMX factor, + const INT scale) { + int ch; + for (ch = 0; ch < (8); ch += 1) { + FIXP_DBL addFact = fMult(mixFactors[srcCh][ch], factor); + if (addFact != (FIXP_DMX)0) { + INT newScale = mixScales[srcCh][ch] + scale; + if (mixFactors[dstCh][ch] != (FIXP_DMX)0) { + if (newScale > mixScales[dstCh][ch]) { + mixFactors[dstCh][ch] >>= newScale - mixScales[dstCh][ch]; + } else { + addFact >>= mixScales[dstCh][ch] - newScale; + newScale = mixScales[dstCh][ch]; + } + } + mixFactors[dstCh][ch] += FX_DBL2FX_DMX(addFact); + mixScales[dstCh][ch] = newScale; + } + } +} + +/** Private function that creates a downmix factor matrix depending on the input + and output + * configuration, the user parameters as well as the given metadata. This + function is the modules + * brain and hold all downmix algorithms. + * @param [in] Flag that indicates if inChMode holds a real (packed) channel + mode or has been converted to a MPEG-4 channel configuration index. + * @param [in] Dependent on the inModeIsCfg flag this field hands in a (packed) + channel mode or the corresponding MPEG-4 channel configuration index.of the + input configuration. + * @param [in] The (packed) channel mode of the output configuration. + * @param [in] Pointer to structure holding all current user parameter. + * @param [in] Pointer to field holding all current meta data. + * @param [out] Pointer to fixed-point parts of the downmix matrix. Normalized + to one scale factor. + * @param [out] The common scale factor of the downmix matrix. + * @returns An error code. + **/ +static PCMDMX_ERROR getMixFactors(const UCHAR inModeIsCfg, + PCM_DMX_CHANNEL_MODE inChMode, + const PCM_DMX_CHANNEL_MODE outChMode, + const PCM_DMX_USER_PARAMS *pParams, + const DMX_BS_META_DATA *pMetaData, + FIXP_DMX mixFactors[(8)][(8)], + INT *pOutScale) { + PCMDMX_ERROR err = PCMDMX_OK; + INT mixScales[(8)][(8)]; + INT maxScale = 0; + int numInChannel; + int numOutChannel; + int dmxMethod; + unsigned int outCh, inChCfg = 0; + unsigned int valid[(8)] = {0}; + + FDK_ASSERT(pMetaData != NULL); + FDK_ASSERT(mixFactors != NULL); + /* Check on a supported output configuration. + Add new one only after extensive testing! */ + if (!((outChMode == CH_MODE_1_0_0_0) || (outChMode == CH_MODE_2_0_0_0) || + (outChMode == CH_MODE_3_0_2_1) || (outChMode == CH_MODE_3_0_4_1) || + (outChMode == CH_MODE_5_0_2_1))) { + FDK_ASSERT(0); + } + + if (inModeIsCfg) { + /* Convert channel config to channel mode: */ + inChCfg = (unsigned int)inChMode; + switch (inChCfg) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + inChMode = outChModeTable[inChCfg]; + break; + case 11: + inChMode = CH_MODE_3_0_3_1; + break; + case 12: + inChMode = CH_MODE_3_0_4_1; + break; + case 7: + case 14: + inChMode = CH_MODE_5_0_2_1; + break; + default: + FDK_ASSERT(0); + } + } + + /* Extract the total number of input channels */ + numInChannel = (inChMode & 0xF) + ((inChMode >> 4) & 0xF) + + ((inChMode >> 8) & 0xF) + ((inChMode >> 12) & 0xF); + /* Extract the total number of output channels */ + numOutChannel = (outChMode & 0xF) + ((outChMode >> 4) & 0xF) + + ((outChMode >> 8) & 0xF) + ((outChMode >> 12) & 0xF); + + /* MPEG ammendment 4 aka ETSI metadata and fallback mode: */ + + /* Create identity DMX matrix: */ + for (outCh = 0; outCh < (8); outCh += 1) { + dmxInitChannel(mixFactors, mixScales, outCh); + } + if (((inChMode >> 12) & 0xF) == 0) { + /* Clear empty or wrongly mapped input channel */ + dmxClearChannel(mixFactors, mixScales, LOW_FREQUENCY_CHANNEL); + } + + /* FIRST STAGE: */ + if (numInChannel > SIX_CHANNEL) { /* Always use MPEG equations either with + meta data or with default values. */ + FIXP_DMX dMixFactA, dMixFactB; + INT dMixScaleA, dMixScaleB; + int isValidCfg = TRUE; + + /* Get factors from meta data */ + dMixFactA = abMixLvlValueTab[pMetaData->dmixIdxA]; + dMixScaleA = (pMetaData->dmixIdxA == 0) ? 1 : 0; + dMixFactB = abMixLvlValueTab[pMetaData->dmixIdxB]; + dMixScaleB = (pMetaData->dmixIdxB == 0) ? 1 : 0; + + /* Check if input is in the list of supported configurations */ + switch (inChMode) { + case CH_MODE_3_2_1_1: /* chCfg 11 but with side channels */ + case CH_MODE_3_2_1_0: + isValidCfg = FALSE; + err = PCMDMX_INVALID_MODE; + FDK_FALLTHROUGH; + case CH_MODE_3_0_3_1: /* chCfg 11 */ + /* 6.1ch: C' = C; L' = L; R' = R; LFE' = LFE; + Ls' = Ls*dmix_a_idx + Cs*dmix_b_idx; + Rs' = Rs*dmix_a_idx + Cs*dmix_b_idx; */ + dmxClearChannel( + mixFactors, mixScales, + RIGHT_MULTIPRPS_CHANNEL); /* clear empty input channel */ + dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL, + LEFT_REAR_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL, + LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + dmxSetChannel(mixFactors, mixScales, RIGHT_REAR_CHANNEL, + RIGHT_REAR_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, RIGHT_REAR_CHANNEL, + LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + break; + case CH_MODE_3_0_4_1: /* chCfg 12 */ + /* 7.1ch Surround Back: C' = C; L' = L; R' = R; LFE' = LFE; + Ls' = Ls*dmix_a_idx + Lsr*dmix_b_idx; + Rs' = Rs*dmix_a_idx + Rsr*dmix_b_idx; */ + dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL, + LEFT_REAR_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL, + LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + dmxSetChannel(mixFactors, mixScales, RIGHT_REAR_CHANNEL, + RIGHT_REAR_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, RIGHT_REAR_CHANNEL, + RIGHT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + break; + case CH_MODE_5_0_1_0: + case CH_MODE_5_0_1_1: + dmxClearChannel(mixFactors, mixScales, + RIGHT_REAR_CHANNEL); /* clear empty input channel */ + dmxSetChannel(mixFactors, mixScales, RIGHT_REAR_CHANNEL, + LEFT_REAR_CHANNEL, FL2FXCONST_DMX(0.5f), 1); + dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL, + LEFT_REAR_CHANNEL, FL2FXCONST_DMX(0.5f), 1); + FDK_FALLTHROUGH; + case CH_MODE_5_2_1_0: + isValidCfg = FALSE; + err = PCMDMX_INVALID_MODE; + FDK_FALLTHROUGH; + case CH_MODE_5_0_2_1: /* chCfg 7 || 14 */ + if (inChCfg == 14) { + /* 7.1ch Front Height: C' = C; Ls' = Ls; Rs' = Rs; LFE' = LFE; + L' = L*dmix_a_idx + Lv*dmix_b_idx; + R' = R*dmix_a_idx + Rv*dmix_b_idx; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + } else { + /* 7.1ch Front: Ls' = Ls; Rs' = Rs; LFE' = LFE; + C' = C + (Lc+Rc)*dmix_a_idx; + L' = L + Lc*dmix_b_idx; + R' = R + Rc*dmix_b_idx; */ + dmxSetChannel(mixFactors, mixScales, CENTER_FRONT_CHANNEL, + LEFT_MULTIPRPS_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, CENTER_FRONT_CHANNEL, + RIGHT_MULTIPRPS_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 1); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 1); + } + break; + default: + /* Nothing to do. Just use the identity matrix. */ + isValidCfg = FALSE; + err = PCMDMX_INVALID_MODE; + break; + } + + /* Add additional DMX gain */ + if ((isValidCfg == TRUE) && + (pMetaData->dmxGainIdx5 != 0)) { /* Apply DMX gain 5 */ + FIXP_DMX dmxGain; + INT dmxScale; + INT sign = (pMetaData->dmxGainIdx5 & 0x40) ? -1 : 1; + INT val = pMetaData->dmxGainIdx5 & 0x3F; + + /* 10^(dmx_gain_5/80) */ + dmxGain = FX_DBL2FX_DMX( + fLdPow(FL2FXCONST_DBL(0.830482023721841f), 2, /* log2(10) */ + (FIXP_DBL)(sign * val * (LONG)FL2FXCONST_DBL(0.0125f)), 0, + &dmxScale)); + /* Currently only positive scale factors supported! */ + if (dmxScale < 0) { + dmxGain >>= -dmxScale; + dmxScale = 0; + } + + dmxSetChannel(mixFactors, mixScales, CENTER_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, dmxGain, dmxScale); + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, dmxGain, dmxScale); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, dmxGain, dmxScale); + dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL, LEFT_REAR_CHANNEL, + dmxGain, dmxScale); + dmxSetChannel(mixFactors, mixScales, RIGHT_REAR_CHANNEL, + RIGHT_REAR_CHANNEL, dmxGain, dmxScale); + dmxSetChannel(mixFactors, mixScales, LOW_FREQUENCY_CHANNEL, + LOW_FREQUENCY_CHANNEL, dmxGain, dmxScale); + } + + /* Mark the output channels */ + valid[CENTER_FRONT_CHANNEL] = 1; + valid[LEFT_FRONT_CHANNEL] = 1; + valid[RIGHT_FRONT_CHANNEL] = 1; + valid[LEFT_REAR_CHANNEL] = 1; + valid[RIGHT_REAR_CHANNEL] = 1; + valid[LOW_FREQUENCY_CHANNEL] = 1; + + /* Update channel mode for the next stage */ + inChMode = CH_MODE_3_0_2_1; + } + + /* For the X (> 6) to 6 channel downmix we had no choice. + To mix from 6 to 2 (or 1) channel(s) we have several possibilities (MPEG + DSE | MPEG PCE | ITU | ARIB | DLB). Use profile and the metadata + available flags to determine which equation to use: */ + +#define DMX_METHOD_MPEG_AMD4 1 +#define DMX_METHOD_MPEG_LEGACY 2 +#define DMX_METHOD_ARIB_JAPAN 4 +#define DMX_METHOD_ITU_RECOM 8 +#define DMX_METHOD_CUSTOM 16 + + dmxMethod = DMX_METHOD_MPEG_AMD4; /* default */ + + if ((pParams->dmxProfile == DMX_PRFL_FORCE_MATRIX_MIX) && + (pMetaData->typeFlags & TYPE_PCE_DATA)) { + dmxMethod = DMX_METHOD_MPEG_LEGACY; + } else if (!(pMetaData->typeFlags & + (TYPE_DSE_CLEV_DATA | TYPE_DSE_SLEV_DATA))) { + switch (pParams->dmxProfile) { + default: + case DMX_PRFL_STANDARD: + /* dmxMethod = DMX_METHOD_MPEG_AMD4; */ + break; + case DMX_PRFL_MATRIX_MIX: + case DMX_PRFL_FORCE_MATRIX_MIX: + if (pMetaData->typeFlags & TYPE_PCE_DATA) { + dmxMethod = DMX_METHOD_MPEG_LEGACY; + } + break; + case DMX_PRFL_ARIB_JAPAN: + dmxMethod = DMX_METHOD_ARIB_JAPAN; + break; + } + } + + /* SECOND STAGE: */ + if (numOutChannel <= TWO_CHANNEL) { + /* Create DMX matrix according to input configuration */ + switch (inChMode) { + case CH_MODE_2_0_0_0: /* chCfg 2 */ + /* Apply the dual channel mode. */ + switch (pParams->dualChannelMode) { + case CH1_MODE: /* L' = 0.707 * Ch1; + R' = 0.707 * Ch1; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + break; + case CH2_MODE: /* L' = 0.707 * Ch2; + R' = 0.707 * Ch2; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + break; + case MIXED_MODE: /* L' = 0.5*Ch1 + 0.5*Ch2; + R' = 0.5*Ch1 + 0.5*Ch2; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0); + break; + default: + case STEREO_MODE: + /* Nothing to do */ + break; + } + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * - - - - - - - - - - - - - - - - - - - */ + case CH_MODE_2_0_1_0: { + FIXP_DMX sMixLvl; + if (dmxMethod == DMX_METHOD_ARIB_JAPAN) { + /* L' = 0.707*L + 0.5*S; R' = 0.707*R + 0.5*S; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + sMixLvl = FL2FXCONST_DMX(0.5f); + } else { /* L' = L + 0.707*S; R' = R + 0.707*S; */ + sMixLvl = FL2FXCONST_DMX(0.707f); + } + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, sMixLvl, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, sMixLvl, 0); + } break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * - - - - - - - - - - - - - - - - - - - */ + case CH_MODE_3_0_0_0: /* chCfg 3 */ + { + FIXP_DMX cMixLvl; + if (dmxMethod == DMX_METHOD_ARIB_JAPAN) { + /* L' = 0.707*L + 0.5*C; R' = 0.707*R + 0.5*C; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + cMixLvl = FL2FXCONST_DMX(0.5f); + } else { /* L' = L + 0.707*C; R' = R + 0.707*C; */ + cMixLvl = FL2FXCONST_DMX(0.707f); + } + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, cMixLvl, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, cMixLvl, 0); + } break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * - - - - - - - - - - - - - - - - - - - */ + case CH_MODE_3_0_1_0: /* chCfg 4 */ + { + FIXP_DMX csMixLvl; + if (dmxMethod == DMX_METHOD_ARIB_JAPAN) { + /* L' = 0.707*L + 0.5*C + 0.5*S; R' = 0.707*R + 0.5*C + 0.5*S; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + csMixLvl = FL2FXCONST_DMX(0.5f); + } else { /* L' = L + 0.707*C + 0.707*S; + R' = R + 0.707*C + 0.707*S; */ + csMixLvl = FL2FXCONST_DMX(0.707f); + } + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, csMixLvl, 0); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, csMixLvl, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, csMixLvl, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, csMixLvl, 0); + } break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * - - - - - - - - - - - - - - - - - - - */ + case CH_MODE_3_0_2_0: /* chCfg 5 */ + case CH_MODE_3_0_2_1: /* chCfg 6 */ + { + switch (dmxMethod) { + default: + case DMX_METHOD_MPEG_AMD4: { + FIXP_DMX cMixLvl, sMixLvl, lMixLvl; + INT cMixScale, sMixScale, lMixScale; + + /* Get factors from meta data */ + cMixLvl = abMixLvlValueTab[pMetaData->cLevIdx]; + cMixScale = (pMetaData->cLevIdx == 0) ? 1 : 0; + sMixLvl = abMixLvlValueTab[pMetaData->sLevIdx]; + sMixScale = (pMetaData->sLevIdx == 0) ? 1 : 0; + lMixLvl = lfeMixLvlValueTab[pMetaData->dmixIdxLfe]; + if (pMetaData->dmixIdxLfe <= 1) { + lMixScale = 2; + } else if (pMetaData->dmixIdxLfe <= 5) { + lMixScale = 1; + } else { + lMixScale = 0; + } + /* Setup the DMX matrix */ + if ((pParams->pseudoSurrMode == FORCE_PS_DMX) || + ((pParams->pseudoSurrMode == AUTO_PS_DMX) && + (pMetaData->pseudoSurround == + 1))) { /* L' = L + C*clev - (Ls+Rs)*slev + LFE*lflev; + R' = R + C*clev + (Ls+Rs)*slev + LFE*lflev; */ + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, cMixLvl, cMixScale); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, -sMixLvl, sMixScale); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + RIGHT_REAR_CHANNEL, -sMixLvl, sMixScale); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, cMixLvl, cMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, sMixLvl, sMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_REAR_CHANNEL, sMixLvl, sMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale); + } else { /* L' = L + C*clev + Ls*slev + LFE*llev; + R' = R + C*clev + Rs*slev + LFE*llev; */ + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, cMixLvl, cMixScale); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, sMixLvl, sMixScale); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, cMixLvl, cMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_REAR_CHANNEL, sMixLvl, sMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale); + } + + /* Add additional DMX gain */ + if (pMetaData->dmxGainIdx2 != 0) { /* Apply DMX gain 2 */ + FIXP_DMX dmxGain; + INT dmxScale; + INT sign = (pMetaData->dmxGainIdx2 & 0x40) ? -1 : 1; + INT val = pMetaData->dmxGainIdx2 & 0x3F; + + /* 10^(dmx_gain_2/80) */ + dmxGain = FX_DBL2FX_DMX( + fLdPow(FL2FXCONST_DBL(0.830482023721841f), 2, /* log2(10) */ + (FIXP_DBL)(sign * val * (LONG)FL2FXCONST_DBL(0.0125f)), + 0, &dmxScale)); + /* Currently only positive scale factors supported! */ + if (dmxScale < 0) { + dmxGain >>= -dmxScale; + dmxScale = 0; + } + + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, dmxGain, dmxScale); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, dmxGain, dmxScale); + } + } break; + case DMX_METHOD_ARIB_JAPAN: + case DMX_METHOD_MPEG_LEGACY: { + FIXP_DMX flev, clev, slevLL, slevLR, slevRL, slevRR; + FIXP_DMX mtrxMixDwnCoef = + mpegMixDownIdx2Coef[pMetaData->matrixMixdownIdx]; + + if ((pParams->pseudoSurrMode == FORCE_PS_DMX) || + ((pParams->pseudoSurrMode == AUTO_PS_DMX) && + (pMetaData->pseudoSurround == 1))) { + if (dmxMethod == DMX_METHOD_ARIB_JAPAN) { + /* 3/2 input: L' = 0.707 * [L+0.707*C-k*Ls-k*Rs]; + R' = 0.707 * [R+0.707*C+k*Ls+k*Rs]; */ + flev = mpegMixDownIdx2Coef[0]; /* a = 0.707 */ + } else { /* 3/2 input: L' = (1.707+2*A)^-1 * + [L+0.707*C-A*Ls-A*Rs]; R' = (1.707+2*A)^-1 * + [R+0.707*C+A*Ls+A*Rs]; */ + flev = mpegMixDownIdx2PreFact[1][pMetaData->matrixMixdownIdx]; + } + slevRR = slevRL = FX_DBL2FX_DMX(fMult(flev, mtrxMixDwnCoef)); + slevLL = slevLR = -slevRL; + } else { + if (dmxMethod == DMX_METHOD_ARIB_JAPAN) { + /* 3/2 input: L' = 0.707 * [L+0.707*C+k*Ls]; + R' = 0.707 * [R+0.707*C+k*Rs]; */ + flev = mpegMixDownIdx2Coef[0]; /* a = 0.707 */ + } else { /* 3/2 input: L' = (1.707+A)^-1 * [L+0.707*C+A*Ls]; + R' = (1.707+A)^-1 * [R+0.707*C+A*Rs]; */ + flev = mpegMixDownIdx2PreFact[0][pMetaData->matrixMixdownIdx]; + } + slevRR = slevLL = FX_DBL2FX_DMX(fMult(flev, mtrxMixDwnCoef)); + slevLR = slevRL = (FIXP_DMX)0; + } + /* common factor */ + clev = + FX_DBL2FX_DMX(fMult(flev, mpegMixDownIdx2Coef[0] /* 0.707 */)); + + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, flev, 0); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, clev, 0); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, slevLL, 0); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + RIGHT_REAR_CHANNEL, slevLR, 0); + + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, flev, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, clev, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, slevRL, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_REAR_CHANNEL, slevRR, 0); + } break; + } /* switch (dmxMethod) */ + } break; + default: + /* This configuration does not fit to any known downmix equation! */ + err = PCMDMX_INVALID_MODE; + break; + } /* switch (inChMode) */ + + /* Mark the output channels */ + FDKmemclear(valid, (8) * sizeof(unsigned int)); + valid[LEFT_FRONT_CHANNEL] = 1; + valid[RIGHT_FRONT_CHANNEL] = 1; + } + + if (numOutChannel == ONE_CHANNEL) { + FIXP_DMX monoMixLevel; + INT monoMixScale = 0; + + dmxClearChannel(mixFactors, mixScales, + CENTER_FRONT_CHANNEL); /* C is not in the mix */ + + if (dmxMethod == + DMX_METHOD_MPEG_LEGACY) { /* C' = (3+2*A)^-1 * [C+L+R+A*Ls+A+Rs]; */ + monoMixLevel = mpegMixDownIdx2PreFact[2][pMetaData->matrixMixdownIdx]; + + mixFactors[CENTER_FRONT_CHANNEL][CENTER_FRONT_CHANNEL] = monoMixLevel; + mixFactors[CENTER_FRONT_CHANNEL][LEFT_FRONT_CHANNEL] = monoMixLevel; + mixFactors[CENTER_FRONT_CHANNEL][RIGHT_FRONT_CHANNEL] = monoMixLevel; + monoMixLevel = FX_DBL2FX_DMX(fMult( + monoMixLevel, mpegMixDownIdx2Coef[pMetaData->matrixMixdownIdx])); + mixFactors[CENTER_FRONT_CHANNEL][LEFT_REAR_CHANNEL] = monoMixLevel; + mixFactors[CENTER_FRONT_CHANNEL][RIGHT_REAR_CHANNEL] = monoMixLevel; + } else { + switch (dmxMethod) { + case DMX_METHOD_MPEG_AMD4: + /* C' = L + R; */ + monoMixLevel = FL2FXCONST_DMX(0.5f); + monoMixScale = 1; + break; + default: + /* C' = 0.5*L + 0.5*R; */ + monoMixLevel = FL2FXCONST_DMX(0.5f); + monoMixScale = 0; + break; + } + dmxSetChannel(mixFactors, mixScales, CENTER_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, monoMixLevel, monoMixScale); + dmxAddChannel(mixFactors, mixScales, CENTER_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, monoMixLevel, monoMixScale); + } + + /* Mark the output channel */ + FDKmemclear(valid, (8) * sizeof(unsigned int)); + valid[CENTER_FRONT_CHANNEL] = 1; + } + +#define MAX_SEARCH_START_VAL (-7) + + { + LONG chSum[(8)]; + INT chSumMax = MAX_SEARCH_START_VAL; + + /* Determine the current maximum scale factor */ + for (outCh = 0; outCh < (8); outCh += 1) { + if (valid[outCh] != 0) { + unsigned int inCh; + for (inCh = 0; inCh < (8); inCh += 1) { + if (mixScales[outCh][inCh] > maxScale) { /* Store the new maximum */ + maxScale = mixScales[outCh][inCh]; + } + } + } + } + + /* Individualy analyse output chanal levels */ + for (outCh = 0; outCh < (8); outCh += 1) { + chSum[outCh] = MAX_SEARCH_START_VAL; + if (valid[outCh] != 0) { + int ovrflwProtScale = 0; + unsigned int inCh; + + /* Accumulate all factors for each output channel */ + chSum[outCh] = 0; + for (inCh = 0; inCh < (8); inCh += 1) { + SHORT addFact = FX_DMX2SHRT(mixFactors[outCh][inCh]); + if (mixScales[outCh][inCh] <= maxScale) { + addFact >>= maxScale - mixScales[outCh][inCh]; + } else { + addFact <<= mixScales[outCh][inCh] - maxScale; + } + chSum[outCh] += addFact; + } + if (chSum[outCh] > (LONG)MAXVAL_SGL) { + while (chSum[outCh] > (LONG)MAXVAL_SGL) { + ovrflwProtScale += 1; + chSum[outCh] >>= 1; + } + } else if (chSum[outCh] > 0) { + while ((chSum[outCh] << 1) <= (LONG)MAXVAL_SGL) { + ovrflwProtScale -= 1; + chSum[outCh] <<= 1; + } + } + /* Store the differential scaling in the same array */ + chSum[outCh] = ovrflwProtScale; + } + } + + for (outCh = 0; outCh < (8); outCh += 1) { + if ((valid[outCh] != 0) && + (chSum[outCh] > chSumMax)) { /* Store the new maximum */ + chSumMax = chSum[outCh]; + } + } + maxScale = fMax(maxScale + chSumMax, 0); + + /* Normalize all factors */ + for (outCh = 0; outCh < (8); outCh += 1) { + if (valid[outCh] != 0) { + unsigned int inCh; + for (inCh = 0; inCh < (8); inCh += 1) { + if (mixFactors[outCh][inCh] != (FIXP_DMX)0) { + if (mixScales[outCh][inCh] <= maxScale) { + mixFactors[outCh][inCh] >>= maxScale - mixScales[outCh][inCh]; + } else { + mixFactors[outCh][inCh] <<= mixScales[outCh][inCh] - maxScale; + } + mixScales[outCh][inCh] = maxScale; + } + } + } + } + } + + /* return the scale factor */ + *pOutScale = maxScale; + + return (err); +} + +/** Open and initialize an instance of the PCM downmix module + * @param [out] Pointer to a buffer receiving the handle of the new instance. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Open(HANDLE_PCM_DOWNMIX *pSelf) { + HANDLE_PCM_DOWNMIX self; + + if (pSelf == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + *pSelf = NULL; + + self = (HANDLE_PCM_DOWNMIX)GetPcmDmxInstance(0); + if (self == NULL) { + return (PCMDMX_OUT_OF_MEMORY); + } + + /* Reset the full instance */ + pcmDmx_Reset(self, PCMDMX_RESET_FULL); + + *pSelf = self; + + return (PCMDMX_OK); +} + +/** Reset all static values like e.g. mixdown coefficients. + * @param [in] Handle of PCM downmix module instance. + * @param [in] Flags telling which parts of the module shall be reset. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Reset(HANDLE_PCM_DOWNMIX self, UINT flags) { + if (self == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + if (flags & PCMDMX_RESET_PARAMS) { + PCM_DMX_USER_PARAMS *pParams = &self->userParams; + + pParams->dualChannelMode = STEREO_MODE; + pParams->pseudoSurrMode = NEVER_DO_PS_DMX; + pParams->numOutChannelsMax = (6); + pParams->numOutChannelsMin = (0); + pParams->frameDelay = 0; + pParams->expiryFrame = (0); + + self->applyProcessing = 0; + } + + if (flags & PCMDMX_RESET_BS_DATA) { + int slot; + /* Init all slots with a default set */ + for (slot = 0; slot <= (1); slot += 1) { + FDKmemcpy(&self->bsMetaData[slot], &dfltMetaData, + sizeof(DMX_BS_META_DATA)); + } + } + + return (PCMDMX_OK); +} + +/** Set one parameter for one instance of the PCM downmix module. + * @param [in] Handle of PCM downmix module instance. + * @param [in] Parameter to be set. + * @param [in] Parameter value. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_SetParam(HANDLE_PCM_DOWNMIX self, const PCMDMX_PARAM param, + const INT value) { + switch (param) { + case DMX_PROFILE_SETTING: + switch ((DMX_PROFILE_TYPE)value) { + case DMX_PRFL_STANDARD: + case DMX_PRFL_MATRIX_MIX: + case DMX_PRFL_FORCE_MATRIX_MIX: + case DMX_PRFL_ARIB_JAPAN: + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) return (PCMDMX_INVALID_HANDLE); + self->userParams.dmxProfile = (DMX_PROFILE_TYPE)value; + break; + + case DMX_BS_DATA_EXPIRY_FRAME: + if (self == NULL) return (PCMDMX_INVALID_HANDLE); + self->userParams.expiryFrame = (value > 0) ? (UINT)value : 0; + break; + + case DMX_BS_DATA_DELAY: + if ((value > (1)) || (value < 0)) { + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + self->userParams.frameDelay = (UCHAR)value; + break; + + case MIN_NUMBER_OF_OUTPUT_CHANNELS: + switch (value) { /* supported output channels */ + case -1: + case 0: + case ONE_CHANNEL: + case TWO_CHANNEL: + case SIX_CHANNEL: + case EIGHT_CHANNEL: + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) return (PCMDMX_INVALID_HANDLE); + /* Store the new value */ + self->userParams.numOutChannelsMin = (value > 0) ? (SHORT)value : -1; + if ((value > 0) && (self->userParams.numOutChannelsMax > 0) && + (value > self->userParams + .numOutChannelsMax)) { /* MIN > MAX would be an invalid + state. Thus set MAX = MIN in + this case. */ + self->userParams.numOutChannelsMax = self->userParams.numOutChannelsMin; + } + break; + + case MAX_NUMBER_OF_OUTPUT_CHANNELS: + switch (value) { /* supported output channels */ + case -1: + case 0: + case ONE_CHANNEL: + case TWO_CHANNEL: + case SIX_CHANNEL: + case EIGHT_CHANNEL: + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) return (PCMDMX_INVALID_HANDLE); + /* Store the new value */ + self->userParams.numOutChannelsMax = (value > 0) ? (SHORT)value : -1; + if ((value > 0) && + (value < self->userParams + .numOutChannelsMin)) { /* MAX < MIN would be an invalid + state. Thus set MIN = MAX in + this case. */ + self->userParams.numOutChannelsMin = self->userParams.numOutChannelsMax; + } + break; + + case DMX_DUAL_CHANNEL_MODE: + switch ((DUAL_CHANNEL_MODE)value) { + case STEREO_MODE: + case CH1_MODE: + case CH2_MODE: + case MIXED_MODE: + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) return (PCMDMX_INVALID_HANDLE); + self->userParams.dualChannelMode = (DUAL_CHANNEL_MODE)value; + self->applyProcessing = ((DUAL_CHANNEL_MODE)value != STEREO_MODE) + ? 1 + : 0; /* Force processing if necessary. */ + break; + + case DMX_PSEUDO_SURROUND_MODE: + switch ((PSEUDO_SURROUND_MODE)value) { + case NEVER_DO_PS_DMX: + case AUTO_PS_DMX: + case FORCE_PS_DMX: + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) return (PCMDMX_INVALID_HANDLE); + self->userParams.pseudoSurrMode = (PSEUDO_SURROUND_MODE)value; + break; + + default: + return (PCMDMX_UNKNOWN_PARAM); + } + + return (PCMDMX_OK); +} + +/** Get one parameter value of one PCM downmix module instance. + * @param [in] Handle of PCM downmix module instance. + * @param [in] Parameter to be set. + * @param [out] Pointer to buffer receiving the parameter value. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_GetParam(HANDLE_PCM_DOWNMIX self, const PCMDMX_PARAM param, + INT *const pValue) { + PCM_DMX_USER_PARAMS *pUsrParams; + + if ((self == NULL) || (pValue == NULL)) { + return (PCMDMX_INVALID_HANDLE); + } + pUsrParams = &self->userParams; + + switch (param) { + case DMX_PROFILE_SETTING: + *pValue = (INT)pUsrParams->dmxProfile; + break; + case DMX_BS_DATA_EXPIRY_FRAME: + *pValue = (INT)pUsrParams->expiryFrame; + break; + case DMX_BS_DATA_DELAY: + *pValue = (INT)pUsrParams->frameDelay; + break; + case MIN_NUMBER_OF_OUTPUT_CHANNELS: + *pValue = (INT)pUsrParams->numOutChannelsMin; + break; + case MAX_NUMBER_OF_OUTPUT_CHANNELS: + *pValue = (INT)pUsrParams->numOutChannelsMax; + break; + case DMX_DUAL_CHANNEL_MODE: + *pValue = (INT)pUsrParams->dualChannelMode; + break; + case DMX_PSEUDO_SURROUND_MODE: + *pValue = (INT)pUsrParams->pseudoSurrMode; + break; + default: + return (PCMDMX_UNKNOWN_PARAM); + } + + return (PCMDMX_OK); +} + +/* + * Read DMX meta-data from a data stream element. + */ +PCMDMX_ERROR pcmDmx_Parse(HANDLE_PCM_DOWNMIX self, HANDLE_FDK_BITSTREAM hBs, + UINT ancDataBits, int isMpeg2) { + PCMDMX_ERROR errorStatus = PCMDMX_OK; + +#define MAX_DSE_ANC_BYTES (16) /* 15 bytes */ +#define ANC_DATA_SYNC_BYTE (0xBC) /* ancillary data sync byte. */ + + DMX_BS_META_DATA *pBsMetaData; + + int skip4Dmx = 0, skip4Ext = 0; + int dmxLvlAvail = 0, extDataAvail = 0; + UINT foundNewData = 0; + UINT minAncBits = ((isMpeg2) ? 5 : 3) * 8; + + if ((self == NULL) || (hBs == NULL)) { + return (PCMDMX_INVALID_HANDLE); + } + + /* sanity checks */ + if ((ancDataBits < minAncBits) || (ancDataBits > FDKgetValidBits(hBs))) { + return (PCMDMX_CORRUPT_ANC_DATA); + } + + pBsMetaData = &self->bsMetaData[0]; + + if (isMpeg2) { + /* skip DVD ancillary data */ + FDKpushFor(hBs, 16); + } + + /* check sync word */ + if (FDKreadBits(hBs, 8) != ANC_DATA_SYNC_BYTE) { + return (PCMDMX_CORRUPT_ANC_DATA); + } + + /* skip MPEG audio type and Dolby surround mode */ + FDKpushFor(hBs, 4); + + if (isMpeg2) { + /* int numAncBytes = */ FDKreadBits(hBs, 4); + /* advanced dynamic range control */ + if (FDKreadBit(hBs)) skip4Dmx += 24; + /* dialog normalization */ + if (FDKreadBit(hBs)) skip4Dmx += 8; + /* reproduction_level */ + if (FDKreadBit(hBs)) skip4Dmx += 8; + } else { + FDKpushFor(hBs, 2); /* drc presentation mode */ + pBsMetaData->pseudoSurround = (SCHAR)FDKreadBit(hBs); + FDKpushFor(hBs, 4); /* reserved bits */ + } + + /* downmixing levels MPEGx status */ + dmxLvlAvail = FDKreadBit(hBs); + + if (isMpeg2) { + /* scale factor CRC status */ + if (FDKreadBit(hBs)) skip4Ext += 16; + } else { + /* ancillary data extension status */ + extDataAvail = FDKreadBit(hBs); + } + + /* audio coding and compression status */ + if (FDKreadBit(hBs)) skip4Ext += 16; + /* coarse grain timecode status */ + if (FDKreadBit(hBs)) skip4Ext += 16; + /* fine grain timecode status */ + if (FDKreadBit(hBs)) skip4Ext += 16; + + /* skip the useless data to get to the DMX levels */ + FDKpushFor(hBs, skip4Dmx); + + /* downmix_levels_MPEGX */ + if (dmxLvlAvail) { + if (FDKreadBit(hBs)) { /* center_mix_level_on */ + pBsMetaData->cLevIdx = (UCHAR)FDKreadBits(hBs, 3); + foundNewData |= TYPE_DSE_CLEV_DATA; + } else { + FDKreadBits(hBs, 3); + } + if (FDKreadBit(hBs)) { /* surround_mix_level_on */ + pBsMetaData->sLevIdx = (UCHAR)FDKreadBits(hBs, 3); + foundNewData |= TYPE_DSE_SLEV_DATA; + } else { + FDKreadBits(hBs, 3); + } + } + + /* skip the useless data to get to the ancillary data extension */ + FDKpushFor(hBs, skip4Ext); + + /* anc data extension (MPEG-4 only) */ + if (extDataAvail) { + int extDmxLvlSt, extDmxGainSt, extDmxLfeSt; + + FDKreadBit(hBs); /* reserved bit */ + extDmxLvlSt = FDKreadBit(hBs); + extDmxGainSt = FDKreadBit(hBs); + extDmxLfeSt = FDKreadBit(hBs); + FDKreadBits(hBs, 4); /* reserved bits */ + + if (extDmxLvlSt) { + pBsMetaData->dmixIdxA = (UCHAR)FDKreadBits(hBs, 3); + pBsMetaData->dmixIdxB = (UCHAR)FDKreadBits(hBs, 3); + FDKreadBits(hBs, 2); /* reserved bits */ + foundNewData |= TYPE_DSE_DMIX_AB_DATA; + } + if (extDmxGainSt) { + pBsMetaData->dmxGainIdx5 = (UCHAR)FDKreadBits(hBs, 7); + FDKreadBit(hBs); /* reserved bit */ + pBsMetaData->dmxGainIdx2 = (UCHAR)FDKreadBits(hBs, 7); + FDKreadBit(hBs); /* reserved bit */ + foundNewData |= TYPE_DSE_DMX_GAIN_DATA; + } + if (extDmxLfeSt) { + pBsMetaData->dmixIdxLfe = (UCHAR)FDKreadBits(hBs, 4); + FDKreadBits(hBs, 4); /* reserved bits */ + foundNewData |= TYPE_DSE_DMIX_LFE_DATA; + } + } + + /* final sanity check on the amount of read data */ + if ((INT)FDKgetValidBits(hBs) < 0) { + errorStatus = PCMDMX_CORRUPT_ANC_DATA; + } + + if ((errorStatus == PCMDMX_OK) && (foundNewData != 0)) { + /* announce new data */ + pBsMetaData->typeFlags |= foundNewData; + /* reset expiry counter */ + pBsMetaData->expiryCount = 0; + } + + return (errorStatus); +} + +/* + * Read DMX meta-data from a data stream element. + */ +PCMDMX_ERROR pcmDmx_ReadDvbAncData(HANDLE_PCM_DOWNMIX self, UCHAR *pAncDataBuf, + UINT ancDataBytes, int isMpeg2) { + PCMDMX_ERROR errorStatus = PCMDMX_OK; + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + + if (self == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + /* sanity checks */ + if ((pAncDataBuf == NULL) || (ancDataBytes == 0)) { + return (PCMDMX_CORRUPT_ANC_DATA); + } + + FDKinitBitStream(hBs, pAncDataBuf, MAX_DSE_ANC_BYTES, ancDataBytes * 8, + BS_READER); + + errorStatus = pcmDmx_Parse(self, hBs, ancDataBytes * 8, isMpeg2); + + return (errorStatus); +} + +/** Set the matrix mixdown information extracted from the PCE of an AAC + *bitstream. Note: Call only if matrix_mixdown_idx_present is true. + * @param [in] Handle of PCM downmix module instance. + * @param [in] The 2 bit matrix mixdown index extracted from PCE. + * @param [in] The pseudo surround enable flag extracted from PCE. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_SetMatrixMixdownFromPce(HANDLE_PCM_DOWNMIX self, + int matrixMixdownPresent, + int matrixMixdownIdx, + int pseudoSurroundEnable) { + if (self == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + { + DMX_BS_META_DATA *pBsMetaData = &self->bsMetaData[0]; + + if (matrixMixdownPresent) { + pBsMetaData->pseudoSurround = (pseudoSurroundEnable) ? 1 : 0; + pBsMetaData->matrixMixdownIdx = matrixMixdownIdx & 0x03; + pBsMetaData->typeFlags |= TYPE_PCE_DATA; + /* Reset expiry counter */ + pBsMetaData->expiryCount = 0; + } + } + + return (PCMDMX_OK); +} + +/** Apply down or up mixing. + * @param [in] Handle of PCM downmix module instance. + * @param [inout] Pointer to buffer that hold the time domain signal. + * @param [in] Pointer where the amount of output samples is returned into. + * @param [in] Size of pPcmBuf. + * @param [inout] Pointer where the amount of output channels is returned into. + * @param [in] Input and output samples are processed interleaved. + * @param [inout] Array where the corresponding channel type for each output + *audio channel is stored into. + * @param [inout] Array where the corresponding channel type index for each + *output audio channel is stored into. + * @param [in] Array containing the out channel mapping to be used (From MPEG + *PCE ordering to whatever is required). + * @param [out] Pointer on a field receiving the scale factor that has to be + *applied on all samples afterwards. If the handed pointer is NULL scaling is + *done internally. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_ApplyFrame(HANDLE_PCM_DOWNMIX self, DMX_PCM *pPcmBuf, + const int pcmBufSize, UINT frameSize, + INT *nChannels, INT fInterleaved, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const FDK_channelMapDescr *const mapDescr, + INT *pDmxOutScale) { + PCM_DMX_USER_PARAMS *pParam = NULL; + PCMDMX_ERROR errorStatus = PCMDMX_OK; + DUAL_CHANNEL_MODE dualChannelMode; + PCM_DMX_CHANNEL_MODE inChMode; + PCM_DMX_CHANNEL_MODE outChMode; + INT devNull; /* Just a dummy to avoid a lot of branches in the code */ + int numOutChannels, numInChannels; + int inStride, outStride, offset; + int dmxMaxScale, dmxScale; + int slot; + UCHAR inOffsetTable[(8)]; + + DMX_BS_META_DATA bsMetaData; + + if ((self == NULL) || (nChannels == NULL) || (channelType == NULL) || + (channelIndices == NULL) || (!FDK_chMapDescr_isValid(mapDescr))) { + return (PCMDMX_INVALID_HANDLE); + } + + /* Init the output scaling */ + dmxScale = 0; + if (pDmxOutScale != NULL) { + /* Avoid final scaling internally and hand it to the outside world. */ + *pDmxOutScale = 0; + dmxMaxScale = (3); + } else { + /* Apply the scaling internally. */ + pDmxOutScale = &devNull; /* redirect to temporal stack memory */ + dmxMaxScale = 0; + } + + pParam = &self->userParams; + numInChannels = *nChannels; + + /* Perform some input sanity checks */ + if (pPcmBuf == NULL) { + return (PCMDMX_INVALID_ARGUMENT); + } + if (frameSize == 0) { + return (PCMDMX_INVALID_ARGUMENT); + } + if (numInChannels == 0) { + return (PCMDMX_INVALID_ARGUMENT); + } + if (numInChannels > (8)) { + return (PCMDMX_INVALID_CH_CONFIG); + } + + /* Check on misconfiguration */ + FDK_ASSERT((pParam->numOutChannelsMax <= 0) || + (pParam->numOutChannelsMax >= pParam->numOutChannelsMin)); + + /* Determine if the module has to do processing */ + if ((self->applyProcessing == 0) && + ((pParam->numOutChannelsMax <= 0) || + (pParam->numOutChannelsMax >= numInChannels)) && + (pParam->numOutChannelsMin <= numInChannels)) { + /* Nothing to do */ + return (errorStatus); + } + + /* Determine the number of output channels */ + if ((pParam->numOutChannelsMax > 0) && + (numInChannels > pParam->numOutChannelsMax)) { + numOutChannels = pParam->numOutChannelsMax; + } else if (numInChannels < pParam->numOutChannelsMin) { + numOutChannels = pParam->numOutChannelsMin; + } else { + numOutChannels = numInChannels; + } + + /* Check I/O buffer size */ + if ((UINT)pcmBufSize < (UINT)numOutChannels * frameSize) { + return (PCMDMX_OUTPUT_BUFFER_TOO_SMALL); + } + + dualChannelMode = pParam->dualChannelMode; + + /* Analyse input channel configuration and get channel offset + * table that can be accessed with the fixed channel labels. */ + errorStatus = getChannelMode(numInChannels, channelType, channelIndices, + inOffsetTable, &inChMode); + if (PCMDMX_IS_FATAL_ERROR(errorStatus) || (inChMode == CH_MODE_UNDEFINED)) { + /* We don't need to restore because the channel + configuration has not been changed. Just exit. */ + return (PCMDMX_INVALID_CH_CONFIG); + } + + /* Set input stride and offset */ + if (fInterleaved) { + inStride = numInChannels; + offset = 1; /* Channel specific offset factor */ + } else { + inStride = 1; + offset = frameSize; /* Channel specific offset factor */ + } + + /* Reset downmix meta data if necessary */ + if ((pParam->expiryFrame > 0) && + (++self->bsMetaData[0].expiryCount > + pParam + ->expiryFrame)) { /* The metadata read from bitstream is too old. */ +#ifdef FDK_ASSERT_ENABLE + PCMDMX_ERROR err = pcmDmx_Reset(self, PCMDMX_RESET_BS_DATA); + FDK_ASSERT(err == PCMDMX_OK); +#else + pcmDmx_Reset(self, PCMDMX_RESET_BS_DATA); +#endif + } + FDKmemcpy(&bsMetaData, &self->bsMetaData[pParam->frameDelay], + sizeof(DMX_BS_META_DATA)); + /* Maintain delay line */ + for (slot = pParam->frameDelay; slot > 0; slot -= 1) { + FDKmemcpy(&self->bsMetaData[slot], &self->bsMetaData[slot - 1], + sizeof(DMX_BS_META_DATA)); + } + + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * - - - - - - - - - - - - - - - - - - */ + if (numInChannels > numOutChannels) { /* Apply downmix */ + DMX_PCM *pInPcm[(8)] = {NULL}; + DMX_PCM *pOutPcm[(8)] = {NULL}; + FIXP_DMX mixFactors[(8)][(8)]; + UCHAR outOffsetTable[(8)]; + UINT sample; + int chCfg = 0; + int bypScale = 0; + + if (numInChannels > SIX_CHANNEL) { + AUDIO_CHANNEL_TYPE multiPurposeChType[2]; + + /* Get the type of the multipurpose channels */ + multiPurposeChType[0] = + channelType[inOffsetTable[LEFT_MULTIPRPS_CHANNEL]]; + multiPurposeChType[1] = + channelType[inOffsetTable[RIGHT_MULTIPRPS_CHANNEL]]; + + /* Check if the input configuration is one defined in the standard. */ + switch (inChMode) { + case CH_MODE_5_0_2_1: /* chCfg 7 || 14 */ + /* Further analyse the input config to distinguish the two + * CH_MODE_5_0_2_1 configs. */ + if ((multiPurposeChType[0] == ACT_FRONT_TOP) && + (multiPurposeChType[1] == ACT_FRONT_TOP)) { + chCfg = 14; + } else { + chCfg = 7; + } + break; + case CH_MODE_3_0_3_1: /* chCfg 11 */ + chCfg = 11; + break; + case CH_MODE_3_0_4_1: /* chCfg 12 */ + chCfg = 12; + break; + default: + chCfg = 0; /* Not a known config */ + break; + } + } + + /* Set this stages output stride and channel mode: */ + outStride = (fInterleaved) ? numOutChannels : 1; + outChMode = outChModeTable[numOutChannels]; + FDK_ASSERT(outChMode != CH_MODE_UNDEFINED); + + /* Get channel description and channel mapping for the desired output + * configuration. */ + getChannelDescription(outChMode, mapDescr, channelType, channelIndices, + outOffsetTable); + /* Now there is no way back because we modified the channel configuration! + */ + + /* Create the DMX matrix */ + errorStatus = + getMixFactors((chCfg > 0) ? 1 : 0, + (chCfg > 0) ? (PCM_DMX_CHANNEL_MODE)chCfg : inChMode, + outChMode, pParam, &bsMetaData, mixFactors, &dmxScale); + /* No fatal errors can occur here. The function is designed to always return + a valid matrix. The error code is used to signal configurations and + matrices that are not conform to any standard. */ + + /* Determine the final scaling */ + bypScale = fMin(dmxMaxScale, dmxScale); + *pDmxOutScale += bypScale; + dmxScale -= bypScale; + + { /* Set channel pointer for input. Remove empty cols. */ + int inCh, outCh, map[(8)]; + int ch = 0; + for (inCh = 0; inCh < (8); inCh += 1) { + if (inOffsetTable[inCh] < (UCHAR)numInChannels) { + pInPcm[ch] = &pPcmBuf[inOffsetTable[inCh] * offset]; + map[ch++] = inCh; + } + } + for (; ch < (8); ch += 1) { + map[ch] = ch; + } + + /* Remove unused cols from factor matrix */ + for (inCh = 0; inCh < numInChannels; inCh += 1) { + if (inCh != map[inCh]) { + for (outCh = 0; outCh < (8); outCh += 1) { + mixFactors[outCh][inCh] = mixFactors[outCh][map[inCh]]; + } + } + } + + /* Set channel pointer for output. Remove empty cols. */ + ch = 0; + for (outCh = 0; outCh < (8); outCh += 1) { + if (outOffsetTable[outCh] < (UCHAR)numOutChannels) { + pOutPcm[ch] = &pPcmBuf[outOffsetTable[outCh] * offset]; + map[ch++] = outCh; + } + } + for (; ch < (8); ch += 1) { + map[ch] = ch; + } + + /* Remove unused rows from factor matrix */ + for (outCh = 0; outCh < numOutChannels; outCh += 1) { + if (outCh != map[outCh]) { + FDKmemcpy(&mixFactors[outCh], &mixFactors[map[outCh]], + (8) * sizeof(FIXP_DMX)); + } + } + } + + /* Sample processing loop */ + for (sample = 0; sample < frameSize; sample++) { + DMX_PCM tIn[(8)] = {0}; + FIXP_DBL tOut[(8)] = {(FIXP_DBL)0}; + int inCh, outCh; + + /* Preload all input samples */ + for (inCh = 0; inCh < numInChannels; inCh += 1) { + if (pInPcm[inCh] != NULL) { + tIn[inCh] = *pInPcm[inCh]; + pInPcm[inCh] += inStride; + } else { + tIn[inCh] = (DMX_PCM)0; + } + } + /* Apply downmix coefficients to input samples and accumulate for output + */ + for (outCh = 0; outCh < numOutChannels; outCh += 1) { + for (inCh = 0; inCh < numInChannels; inCh += 1) { + tOut[outCh] += fMult((DMX_PCMF)tIn[inCh], mixFactors[outCh][inCh]); + } + FDK_ASSERT(pOutPcm[outCh] >= pPcmBuf); + FDK_ASSERT(pOutPcm[outCh] < &pPcmBuf[pcmBufSize]); + /* Write sample */ + *pOutPcm[outCh] = (DMX_PCM)SATURATE_SHIFT( + tOut[outCh], DFRACT_BITS - DMX_PCM_BITS - dmxScale, DMX_PCM_BITS); + pOutPcm[outCh] += outStride; + } + } + + /* Update the number of output channels */ + *nChannels = numOutChannels; + + } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - */ + else if (numInChannels < numOutChannels) { /* Apply rudimentary upmix */ + /* Set up channel pointer */ + UCHAR outOffsetTable[(8)]; + + /* FIRST STAGE + Create a stereo/dual channel signal */ + if (numInChannels == ONE_CHANNEL) { + DMX_PCM *pInPcm[(8)]; + DMX_PCM *pOutLF, *pOutRF; + UINT sample; + + /* Set this stages output stride and channel mode: */ + outStride = (fInterleaved) ? TWO_CHANNEL : 1; + outChMode = outChModeTable[TWO_CHANNEL]; + + /* Get channel description and channel mapping for this + * stages number of output channels (always STEREO). */ + getChannelDescription(outChMode, mapDescr, channelType, channelIndices, + outOffsetTable); + /* Now there is no way back because we modified the channel configuration! + */ + + /* Set input channel pointer. The first channel is always at index 0. */ + pInPcm[CENTER_FRONT_CHANNEL] = + &pPcmBuf[(frameSize - 1) * + inStride]; /* Considering input mapping could lead to a + invalid pointer here if the channel is not + declared to be a front channel. */ + + /* Set output channel pointer (for this stage). */ + pOutLF = &pPcmBuf[outOffsetTable[LEFT_FRONT_CHANNEL] * offset + + (frameSize - 1) * outStride]; + pOutRF = &pPcmBuf[outOffsetTable[RIGHT_FRONT_CHANNEL] * offset + + (frameSize - 1) * outStride]; + + /* 1/0 input: */ + for (sample = 0; sample < frameSize; sample++) { + /* L' = C; R' = C; */ + *pOutLF = *pOutRF = *pInPcm[CENTER_FRONT_CHANNEL]; + + pInPcm[CENTER_FRONT_CHANNEL] -= inStride; + pOutLF -= outStride; + pOutRF -= outStride; + } + + /* Prepare for next stage: */ + inStride = outStride; + inChMode = outChMode; + FDKmemcpy(inOffsetTable, outOffsetTable, (8) * sizeof(UCHAR)); + } + + /* SECOND STAGE + Extend with zero channels to achieved the desired number of output + channels. */ + if (numOutChannels > TWO_CHANNEL) { + DMX_PCM *pIn[(8)] = {NULL}; + DMX_PCM *pOut[(8)] = {NULL}; + UINT sample; + AUDIO_CHANNEL_TYPE inChTypes[(8)]; + UCHAR inChIndices[(8)]; + UCHAR numChPerGrp[2][(4)]; + int nContentCh = 0; /* Number of channels with content */ + int nEmptyCh = 0; /* Number of channels with content */ + int ch, chGrp, isCompatible = 1; + + /* Do not change the signalling which is the channel types and indices. + Just reorder and add channels. So first save the input signalling. */ + FDKmemcpy(inChTypes, channelType, + numInChannels * sizeof(AUDIO_CHANNEL_TYPE)); + FDKmemclear(inChTypes + numInChannels, + ((8) - numInChannels) * sizeof(AUDIO_CHANNEL_TYPE)); + FDKmemcpy(inChIndices, channelIndices, numInChannels * sizeof(UCHAR)); + FDKmemclear(inChIndices + numInChannels, + ((8) - numInChannels) * sizeof(UCHAR)); + + /* Set this stages output stride and channel mode: */ + outStride = (fInterleaved) ? numOutChannels : 1; + outChMode = outChModeTable[numOutChannels]; + FDK_ASSERT(outChMode != CH_MODE_UNDEFINED); + + /* Check if input channel config can be easily mapped to the desired + * output config. */ + for (chGrp = 0; chGrp < (4); chGrp += 1) { + numChPerGrp[IN][chGrp] = (inChMode >> (chGrp * 4)) & 0xF; + numChPerGrp[OUT][chGrp] = (outChMode >> (chGrp * 4)) & 0xF; + + if (numChPerGrp[IN][chGrp] > numChPerGrp[OUT][chGrp]) { + isCompatible = 0; + break; + } + } + + if (isCompatible) { + /* Get new channel description and channel + * mapping for the desired output channel mode. */ + getChannelDescription(outChMode, mapDescr, channelType, channelIndices, + outOffsetTable); + /* If the input config has a back center channel but the output + config has not, copy it to left and right (if available). */ + if ((numChPerGrp[IN][CH_GROUP_REAR] % 2) && + !(numChPerGrp[OUT][CH_GROUP_REAR] % 2)) { + if (numChPerGrp[IN][CH_GROUP_REAR] == 1) { + inOffsetTable[RIGHT_REAR_CHANNEL] = + inOffsetTable[LEFT_REAR_CHANNEL]; + } else if (numChPerGrp[IN][CH_GROUP_REAR] == 3) { + inOffsetTable[RIGHT_MULTIPRPS_CHANNEL] = + inOffsetTable[LEFT_MULTIPRPS_CHANNEL]; + } + } + } else { + /* Just copy and extend the original config */ + FDKmemcpy(outOffsetTable, inOffsetTable, (8) * sizeof(UCHAR)); + } + + /* Set I/O channel pointer. + Note: The following assignment algorithm clears the channel offset + tables. Thus they can not be used afterwards. */ + for (ch = 0; ch < (8); ch += 1) { + if ((outOffsetTable[ch] < 255) && + (inOffsetTable[ch] < 255)) { /* Set I/O pointer: */ + pIn[nContentCh] = + &pPcmBuf[inOffsetTable[ch] * offset + (frameSize - 1) * inStride]; + pOut[nContentCh] = &pPcmBuf[outOffsetTable[ch] * offset + + (frameSize - 1) * outStride]; + /* Update signalling */ + channelType[outOffsetTable[ch]] = inChTypes[inOffsetTable[ch]]; + channelIndices[outOffsetTable[ch]] = inChIndices[inOffsetTable[ch]]; + inOffsetTable[ch] = 255; + outOffsetTable[ch] = 255; + nContentCh += 1; + } + } + if (isCompatible) { + /* Assign the remaining input channels. + This is just a safety appliance. We should never need it. */ + for (ch = 0; ch < (8); ch += 1) { + if (inOffsetTable[ch] < 255) { + int outCh; + for (outCh = 0; outCh < (8); outCh += 1) { + if (outOffsetTable[outCh] < 255) { + break; + } + } + if (outCh >= (8)) { + FDK_ASSERT(0); + break; + } + /* Set I/O pointer: */ + pIn[nContentCh] = &pPcmBuf[inOffsetTable[ch] * offset + + (frameSize - 1) * inStride]; + pOut[nContentCh] = &pPcmBuf[outOffsetTable[outCh] * offset + + (frameSize - 1) * outStride]; + /* Update signalling */ + FDK_ASSERT(inOffsetTable[outCh] < numInChannels); + FDK_ASSERT(outOffsetTable[outCh] < numOutChannels); + channelType[outOffsetTable[outCh]] = inChTypes[inOffsetTable[ch]]; + channelIndices[outOffsetTable[outCh]] = + inChIndices[inOffsetTable[ch]]; + inOffsetTable[ch] = 255; + outOffsetTable[outCh] = 255; + nContentCh += 1; + } + } + /* Set the remaining output channel pointer */ + for (ch = 0; ch < (8); ch += 1) { + if (outOffsetTable[ch] < 255) { + pOut[nContentCh + nEmptyCh] = &pPcmBuf[outOffsetTable[ch] * offset + + (frameSize - 1) * outStride]; + /* Expand output signalling */ + channelType[outOffsetTable[ch]] = ACT_NONE; + channelIndices[outOffsetTable[ch]] = (UCHAR)nEmptyCh; + outOffsetTable[ch] = 255; + nEmptyCh += 1; + } + } + } else { + /* Set the remaining output channel pointer */ + for (ch = nContentCh; ch < numOutChannels; ch += 1) { + pOut[ch] = &pPcmBuf[ch * offset + (frameSize - 1) * outStride]; + /* Expand output signalling */ + channelType[ch] = ACT_NONE; + channelIndices[ch] = (UCHAR)nEmptyCh; + nEmptyCh += 1; + } + } + + /* First copy the channels that have signal */ + for (sample = 0; sample < frameSize; sample += 1) { + DMX_PCM tIn[(8)]; + /* Read all channel samples */ + for (ch = 0; ch < nContentCh; ch += 1) { + tIn[ch] = *pIn[ch]; + pIn[ch] -= inStride; + } + /* Write all channel samples */ + for (ch = 0; ch < nContentCh; ch += 1) { + *pOut[ch] = tIn[ch]; + pOut[ch] -= outStride; + } + } + + /* Clear all the other channels */ + for (sample = 0; sample < frameSize; sample++) { + for (ch = nContentCh; ch < numOutChannels; ch += 1) { + *pOut[ch] = (DMX_PCM)0; + pOut[ch] -= outStride; + } + } + } + + /* update the number of output channels */ + *nChannels = numOutChannels; + } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - */ + else if (numInChannels == numOutChannels) { + /* Don't need to change the channel description here */ + + switch (numInChannels) { + case 2: { /* Set up channel pointer */ + DMX_PCM *pInPcm[(8)]; + DMX_PCM *pOutL, *pOutR; + FIXP_DMX flev; + + UINT sample; + + if (fInterleaved) { + inStride = numInChannels; + outStride = + 2; /* fixed !!! (below stereo is donwmixed to mono if required */ + offset = 1; /* Channel specific offset factor */ + } else { + inStride = 1; + outStride = 1; + offset = frameSize; /* Channel specific offset factor */ + } + + /* Set input channel pointer */ + pInPcm[LEFT_FRONT_CHANNEL] = + &pPcmBuf[inOffsetTable[LEFT_FRONT_CHANNEL] * offset]; + pInPcm[RIGHT_FRONT_CHANNEL] = + &pPcmBuf[inOffsetTable[RIGHT_FRONT_CHANNEL] * offset]; + + /* Set output channel pointer (same as input) */ + pOutL = pInPcm[LEFT_FRONT_CHANNEL]; + pOutR = pInPcm[RIGHT_FRONT_CHANNEL]; + + /* Set downmix levels: */ + flev = FL2FXCONST_DMX(0.70710678f); + /* 2/0 input: */ + switch (dualChannelMode) { + case CH1_MODE: /* L' = 0.707 * Ch1; R' = 0.707 * Ch1 */ + for (sample = 0; sample < frameSize; sample++) { + *pOutL = *pOutR = (DMX_PCM)SATURATE_RIGHT_SHIFT( + fMult((DMX_PCMF)*pInPcm[LEFT_FRONT_CHANNEL], flev), + DFRACT_BITS - DMX_PCM_BITS, DMX_PCM_BITS); + + pInPcm[LEFT_FRONT_CHANNEL] += inStride; + pOutL += outStride; + pOutR += outStride; + } + break; + case CH2_MODE: /* L' = 0.707 * Ch2; R' = 0.707 * Ch2 */ + for (sample = 0; sample < frameSize; sample++) { + *pOutL = *pOutR = (DMX_PCM)SATURATE_RIGHT_SHIFT( + fMult((DMX_PCMF)*pInPcm[RIGHT_FRONT_CHANNEL], flev), + DFRACT_BITS - DMX_PCM_BITS, DMX_PCM_BITS); + + pInPcm[RIGHT_FRONT_CHANNEL] += inStride; + pOutL += outStride; + pOutR += outStride; + } + break; + case MIXED_MODE: /* L' = 0.5*Ch1 + 0.5*Ch2; R' = 0.5*Ch1 + 0.5*Ch2 */ + for (sample = 0; sample < frameSize; sample++) { + *pOutL = *pOutR = (*pInPcm[LEFT_FRONT_CHANNEL] >> 1) + + (*pInPcm[RIGHT_FRONT_CHANNEL] >> 1); + + pInPcm[LEFT_FRONT_CHANNEL] += inStride; + pInPcm[RIGHT_FRONT_CHANNEL] += inStride; + pOutL += outStride; + pOutR += outStride; + } + break; + default: + case STEREO_MODE: + /* nothing to do */ + break; + } + } break; + + default: + /* nothing to do */ + break; + } + } + + return (errorStatus); +} + +/** Close an instance of the PCM downmix module. + * @param [inout] Pointer to a buffer containing the handle of the instance. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Close(HANDLE_PCM_DOWNMIX *pSelf) { + if (pSelf == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + FreePcmDmxInstance(pSelf); + *pSelf = NULL; + + return (PCMDMX_OK); +} + +/** Get library info for this module. + * @param [out] Pointer to an allocated LIB_INFO structure. + * @returns Returns an error code. + */ +PCMDMX_ERROR pcmDmx_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return PCMDMX_INVALID_ARGUMENT; + } + + /* Search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return PCMDMX_INVALID_ARGUMENT; + } + + /* Add the library info */ + info[i].module_id = FDK_PCMDMX; + info[i].version = + LIB_VERSION(PCMUTIL_LIB_VL0, PCMUTIL_LIB_VL1, PCMUTIL_LIB_VL2); + LIB_VERSION_STRING(info + i); + info[i].build_date = PCMUTIL_LIB_BUILD_DATE; + info[i].build_time = PCMUTIL_LIB_BUILD_TIME; + info[i].title = PCMDMX_LIB_TITLE; + + /* Set flags */ + info[i].flags = 0 | CAPF_DMX_BLIND /* At least blind downmixing is possible */ + | CAPF_DMX_PCE /* Guided downmix with data from MPEG-2/4 + Program Config Elements (PCE). */ + | CAPF_DMX_ARIB /* PCE guided downmix with slightly different + equations and levels. */ + | CAPF_DMX_DVB /* Guided downmix with data from DVB ancillary + data fields. */ + | CAPF_DMX_CH_EXP /* Simple upmixing by dublicating channels + or adding zero channels. */ + | CAPF_DMX_6_CH | CAPF_DMX_8_CH; + + /* Add lib info for FDK tools (if not yet done). */ + FDK_toolsGetLibInfo(info); + + return PCMDMX_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/version.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/version.h new file mode 100644 index 0000000000000..871aa9074a767 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libPCMutils/src/version.h @@ -0,0 +1,119 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#if !defined(VERSION_H) +#define VERSION_H + +/* library info */ +#define PCMUTIL_LIB_VL0 3 +#define PCMUTIL_LIB_VL1 1 +#define PCMUTIL_LIB_VL2 0 +#define PCMUTIL_LIB_TITLE "PCM Utility Lib" +#ifdef SUPPRESS_BUILD_DATE_INFO +#define PCMUTIL_LIB_BUILD_DATE "" +#define PCMUTIL_LIB_BUILD_TIME "" +#else +#define PCMUTIL_LIB_BUILD_DATE __DATE__ +#define PCMUTIL_LIB_BUILD_TIME __TIME__ +#endif + +#endif /* !defined(VERSION_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/include/sac_dec_errorcodes.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/include/sac_dec_errorcodes.h new file mode 100644 index 0000000000000..ee8b9f85b71b8 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/include/sac_dec_errorcodes.h @@ -0,0 +1,157 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: error codes for mpeg surround decoder + +*******************************************************************************/ + +#ifndef SAC_DEC_ERRORCODES_H +#define SAC_DEC_ERRORCODES_H + +typedef enum { + + __mps_error_start = -1000, + + MPS_OK = 0, + + /* generic/init errors */ + MPS_NOTOK = __mps_error_start, + + MPS_OUTOFMEMORY, + MPS_INVALID_HANDLE, + MPS_INVALID_PARAMETER, /* SetParam not successfull */ + MPS_UNSUPPORTED_HRTFMODEL, /* SetHRTFModel() not successfull */ + MPS_UNSUPPORTED_HRTFFREQ, /* SetHRTFModel() not successfull */ + + MPS_UNSUPPORTED_UPMIX_TYPE, /* CheckLevelTreeUpmixType() */ + MPS_UNSUPPORTED_FORMAT, /* various functions; unknown aot or no_channels in + filterbank */ + MPS_OUTPUT_BUFFER_TOO_SMALL, /* Size of provided output time buffer is too + small */ + + /* ssc errors */ + MPS_INVALID_PARAMETERBANDS, /* unsupported numParameterBands in + SpatialDecDecodeHeader() */ + MPS_INVALID_TREECONFIG, + MPS_INVALID_HRTFSET, /* SpatialDecDecodeHeader() */ + MPS_INVALID_TTT, /* SpatialDecDecodeHeader() */ + MPS_INVALID_BOXIDX, /* ecDataDec() */ + MPS_INVALID_SETIDX, /* ecDataDec() */ + MPS_INVALID_QUANTMODE, /* SpatialDecParseSpecificConfig() */ + MPS_UNEQUAL_SSC, /* FDK_SpatialDecCompareSpatialSpecificConfigHeader() */ + MPS_UNSUPPORTED_CONFIG, /* number of core channels; 3DStereoInversion; */ + + /* parse errors */ + MPS_PARSE_ERROR, + MPS_INVALID_TEMPSHAPE, /* SpatialDecParseFrameData() */ + + /* render errors */ + MPS_WRONG_PARAMETERSETS, + MPS_WRONG_PARAMETERBANDS, /* decodeAndMapFrameSmg() */ + MPS_WRONG_TREECONFIG, + MPS_WRONG_BLINDCONFIG, + MPS_WRONG_OTT, + MPS_WRONG_QUANTMODE, + MPS_RESDEC_ERROR, + MPS_APPLY_M2_ERROR, /* error in applyM2x()selection */ + + __mps_error_end + +} SACDEC_ERROR; + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/include/sac_dec_lib.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/include/sac_dec_lib.h new file mode 100644 index 0000000000000..5aad4e0fdbcf8 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/include/sac_dec_lib.h @@ -0,0 +1,482 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: Space Decoder + +*******************************************************************************/ + +#ifndef SAC_DEC_LIB_H +#define SAC_DEC_LIB_H + +#include "common_fix.h" +#include "FDK_audio.h" +#include "sac_dec_errorcodes.h" +#include "FDK_bitstream.h" +#include "FDK_qmf_domain.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \brief MPEG Surround input data interface mode. + **/ +typedef enum { + SAC_INTERFACE_QMF = + 0, /*!< Use QMF domain interface for the input downmix audio. */ + SAC_INTERFACE_TIME, /*!< Use time domain interface for the input downmix + audio. */ + SAC_INTERFACE_AUTO /*!< */ +} SAC_INPUT_CONFIG; + +/** + * \brief MPEG Surround output mode. + **/ +typedef enum { + SACDEC_OUT_MODE_NORMAL = + 0, /*!< Normal multi channel processing without output restrictions. */ + SACDEC_OUT_MODE_BINAURAL, /*!< Two channel output with binaural processsing. + */ + SACDEC_OUT_MODE_STEREO, /*!< Always two channel output mode. */ + SACDEC_OUT_MODE_6CHANNEL /*!< Always process with 5.1 channel output. */ +} SAC_DEC_OUTPUT_MODE; + +/** + * \brief MPEG Surround binaural HRTF model. + * HRTF will be applied only in combination with upmixtype + *SAC_UPMIX_TYPE_BINAURAL. + **/ +typedef enum { + SAC_BINAURAL_HRTF_KEMAR = 0, + SAC_BINAURAL_HRTF_VAST, + SAC_BINAURAL_HRTF_MPSVT, + SAC_BINAURAL_SINGLE_HRTFS +} SAC_BINAURAL_HRTF_MODEL; + +/** + * \brief MPEG Surround decoder instance available. + **/ +typedef enum { + SAC_INSTANCE_NOT_FULL_AVAILABLE = + 0, /*!< MPEG Surround decoder instance not full available. */ + SAC_INSTANCE_FULL_AVAILABLE /*!< MPEG Surround decoder instance full + available. */ +} SAC_INSTANCE_AVAIL; + +/** + * \brief MPEG Surround decoder dynamic parameters. + * + * Use mpegSurroundDecoder_SetParam() function to configure internal status of + * following parameters. + */ +typedef enum { + SACDEC_OUTPUT_MODE = 0x0001, /*!< Set MPEG Surround decoder output mode. See + SAC_DEC_OUTPUT_MODE. */ + SACDEC_BLIND_ENABLE = + 0x0002, /*!< Multi channel output without MPEG Surround side info. */ + SACDEC_PARTIALLY_COMPLEX = + 0x0003, /*!< Set partially complex flag for MPEG Surround. + 0: Use complex valued QMF data. + 1: Use real valued QMF data (low power mode) */ + SACDEC_INTERFACE = + 0x0004, /*!< Select signal input interface for MPEG Surround. + Switch time interface off: 0 + Switch time interface on: 1 */ + SACDEC_BS_DELAY = 0x0005, /*!< Select bit stream delay for MPEG Surround. + Switch bit stream delay off: 0 + Switch bit stream delay on: 1 */ + SACDEC_BINAURAL_QUALITY = + 0x0102, /*!< Set binaural quality for MPEG Surround binaural mode. + 0: Low Complexity, + 1: High Quality */ + SACDEC_BINAURAL_DISTANCE = 0x0103, /*!< Set perceived distance for binaural + playback (binaural mode only). The valid + values range from 0 to 100. Where 100 + corresponds to the farthest perceived + distance. */ + SACDEC_BINAURAL_DIALOG_CLARITY = + 0x0104, /*!< Set dialog clarity (for binaural playback). + The valid values range from 0 to 100. */ + SACDEC_BINAURAL_FRONT_ANGLE = 0x0105, /*!< Set angle between the virtual front + speaker pair (binaural mode only). + The valid range is from 0 to 180 + angular degrees. */ + SACDEC_BINAURAL_BACK_ANGLE = 0x0106, /*!< Set angle between the virtual back + speaker pair (binaural mode only). The + valid range is from 0 to 180 angular + degrees. */ + SACDEC_BINAURAL_PRESET = 0x0107, /*!< Set a virtual speaker setup preset for + binaural playback (binaural mode only). + This meta-parameter implicitly modifies + the following parameters: + SACDEC_BINAURAL_DISTANCE, + SACDEC_BINAURAL_DIALOG_CLARITY, + SACDEC_BINAURAL_FRONT_ANGLE and + SACDEC_BINAURAL_BACK_ANGLE. + The following presets are available: + 1: Dry room + 2: Living room (default) + 3: Cinema */ + + SACDEC_BS_INTERRUPTION = + 0x0200, /*!< If the given value is unequal to 0 hint the MPEG Surround + decoder that the next input data is discontinuous, because of + frame loss, seeking, etc. Announce the decoder that the + bitstream data was interrupted (fSync = 0). This will cause the + surround decoder not to parse any new bitstream data until a + new header with a valid Spatial Specific Config and a + independently decodable frame is found. Specially important + when the MPEG Surround data is split accross several frames + (for example in the case of AAC-LC downmix with 1024 + framelength and 2048 surround frame length) and a discontinuity + in the bitstream data occurs. If fSync is 1, assume that MPEG + Surround data is in sync (out of band config for example). */ + SACDEC_CLEAR_HISTORY = 0x0201, /*!< If the given value is unequal to 0 clear + all internal states (delay lines, QMF + states, ...) of the MPEG Surround decoder. + This will cause a discontinuity in the audio + output signal. */ + + SACDEC_CONCEAL_NUM_KEEP_FRAMES = + 0x0301, /*!< Error concealment: The Number of frames the module keeps the + last spatial image before fading to the particular spatial + scenario starts. The default is 10 frames. */ + SACDEC_CONCEAL_FADE_OUT_SLOPE_LENGTH = + 0x0302, /*!< Error concealment: Length of the slope (in frames) the module + creates to fade from the last spatial scenario to the + particular default scenario (downmix) in case of consecutive + errors. Default is 5. */ + SACDEC_CONCEAL_FADE_IN_SLOPE_LENGTH = + 0x0303, /*!< Error concealment: Length of the slope (in frames) the module + creates to fade from the default spatial scenario (downmix) to + the current scenario after fade-out. Default parameter value + is 5. */ + SACDEC_CONCEAL_NUM_RELEASE_FRAMES = + 0x0304 /*!< Error concealment: The number of error free frames before the + module starts fading from default to the current spatial + scenario. Default parameter value is 3 frames. */ +} SACDEC_PARAM; + +#define PCM_MPS LONG + +/** + * \brief MPEG Surround decoder handle. + */ +typedef struct MpegSurroundDecoder CMpegSurroundDecoder; + +/** + * \brief Check if the full MPEG Surround decoder instance is allocated. + * + * Check if the full MPEG Surround decoder instance is allocated. + * + * \param pMpegSurroundDecoder A pointer to a decoder stucture. + * + * \return SACDEC_ERROR error code + */ +SAC_INSTANCE_AVAIL +mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable( + CMpegSurroundDecoder *pMpegSurroundDecoder); + +/** + * \brief Open one instance of the MPEG Surround decoder. + * + * Allocate one instance of decoder and input buffers. + * - Allocate decoder structure + * - Allocate input buffers (QMF/time/MPS data) + * + * \param pMpegSurroundDecoder A pointer to a decoder handle; filled on + * return. + * \param splitMemoryAllocation Allocate only outer layer of MPS decoder. Core + * part is reallocated later if needed. + * \param stereoConfigIndex USAC: Save memory by opening the MPS decoder + * for a specific stereoConfigIndex. (Needs optimization macros enabled.) + * \param pQmfDomain Pointer to QMF domain data structure. + * + * \return SACDEC_ERROR error code + */ +SACDEC_ERROR mpegSurroundDecoder_Open( + CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex, + HANDLE_FDK_QMF_DOMAIN pQmfDomain); + +/** + * \brief Init one instance of the MPEG Surround decoder. + * + * Init one instance of the MPEG Surround decoder + * + * \param pMpegSurroundDecoder A pointer to a decoder handle; + * + * \return SACDEC_ERROR error code + */ +SACDEC_ERROR mpegSurroundDecoder_Init( + CMpegSurroundDecoder *pMpegSurroundDecoder); + +/** + * \brief Read and parse SpatialSpecificConfig. + * + * \param pMpegSurroundDecoder A pointer to a decoder handle. + * \param hBs bitstream handle config parsing data source. + * + * \return SACDEC_ERROR error code + */ +SACDEC_ERROR mpegSurroundDecoder_Config( + CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs, + AUDIO_OBJECT_TYPE coreCodec, INT samplingRate, INT frameSize, + INT numChannels, INT stereoConfigIndex, INT coreSbrFrameLengthIndex, + INT configBytes, const UCHAR configMode, UCHAR *configChanged); + +SACDEC_ERROR +mpegSurroundDecoder_ConfigureQmfDomain( + CMpegSurroundDecoder *pMpegSurroundDecoder, + SAC_INPUT_CONFIG sac_dec_interface, UINT coreSamplingRate, + AUDIO_OBJECT_TYPE coreCodec); + +/** + * \brief Parse MPEG Surround data without header + * + * \param pMpegSurroundDecoder A MPEG Surrround decoder handle. + * \param hBs Bit stream handle data input source + * \param pMpsDataBits Pointer to number of valid bits in extension + * payload. Function updates mpsDataBits while parsing bitstream. + * \param fGlobalIndependencyFlag Global independency flag of current frame. + * + * \return Error code. + */ +int mpegSurroundDecoder_ParseNoHeader( + CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs, + int *pMpsDataBits, int fGlobalIndependencyFlag); + +/* #ifdef SACDEC_MPS_ENABLE */ +/** + * \brief Parse MPEG Surround data with header. Header is ancType, ancStart, + ancStop (4 bits total). Body is ancDataSegmentByte[i]. + * + * \param pMpegSurroundDecoder A MPEG Surrround decoder handle. + * \param hBs Bit stream handle data input source + * \param pMpsDataBits Pointer to number of valid bits in extension + payload. Function updates mpsDataBits while parsing bitstream. Needs to be a + multiple of 8 + 4 (4 bits header). + * \param coreCodec The audio object type of the core codec handling + the downmix input signal. + * \param sampleRate Samplerate of input downmix data. + * \param nChannels Amount of input channels. + * \param frameSize Amount of input samples. + * \param fGlobalIndependencyFlag Global independency flag of current frame. + * + * \return Error code. + */ +int mpegSurroundDecoder_Parse(CMpegSurroundDecoder *pMpegSurroundDecoder, + HANDLE_FDK_BITSTREAM hBs, int *pMpsDataBits, + AUDIO_OBJECT_TYPE coreCodec, int sampleRate, + int frameSize, int fGlobalIndependencyFlag); +/* #endif */ + +/** + * \brief Apply MPEG Surround upmix. + * + * Process one downmix audio frame and decode one surround frame if it applies. + * Downmix framing can be different from surround framing, so depending on the + * frame size of the downmix audio data and the framing being used by the MPEG + * Surround decoder, it could be that only every second call, for example, of + * this function actually surround data was decoded. The returned value of + * frameSize will be zero, if no surround data was decoded. + * + * Decoding one MPEG Surround frame. Depending on interface configuration + * mpegSurroundDecoder_SetParam(self, SACDEC_INTERFACE, value), the QMF or time + * interface will be applied. External access to QMF buffer interface can be + * achieved by mpegSurroundDecoder_GetQmfBuffer() call before decode frame. + * While using time interface, pTimeData buffer will be shared as input and + * output buffer. + * + * \param pMpegSurroundDecoder A MPEG Surrround decoder handle. + * \param pTimeData Pointer to time buffer. Depending on interface + * configuration, the content of pTimeData is ignored, and the internal QMF + * buffer will be used as input data source. + * Otherwise, the MPEG Surround processing is applied to the timesignal + * pTimeData. For both variants, the resulting MPEG + * Surround signal is written into pTimeData. + * \param timeDataSize Size of pTimeData (available buffer size). + * \param timeDataFrameSize Frame size of input timedata + * \param nChannels Pointer where the amount of input channels is + * given and amount of output channels is returned. + * \param frameSize Pointer where the amount of output samples is + * returned into. + * \param channelType Array were the corresponding channel type for + * each output audio channel is stored into. + * \param channelIndices Array were the corresponding channel type index + * for each output audio channel is stored into. + * \param mapDescr Channep map descriptor for output channel mapping + * to be used (From MPEG PCE ordering to whatever is required). + * \param inDataHeadroom Headroom of SAC input time signal to prevent + * clipping. + * \param outDataHeadroom Pointer to headroom of SAC output time signal to + * prevent clipping. + * + * \return Error code. + */ +int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder, + PCM_MPS *input, PCM_MPS *pTimeData, + const int timeDataSize, int timeDataFrameSize, + int *nChannels, int *frameSize, int sampleRate, + AUDIO_OBJECT_TYPE coreCodec, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const FDK_channelMapDescr *const mapDescr, + const INT inDataHeadroom, INT *outDataHeadroom); + +/** + * \brief Deallocate a MPEG Surround decoder instance. + * \param pMpegSurroundDecoder A decoder handle. + * \return No return value. + */ +void mpegSurroundDecoder_Close(CMpegSurroundDecoder *pMpegSurroundDecoder); + +/** + * \brief Free config dependent MPEG Surround memory. + * \param pMpegSurroundDecoder A decoder handle. + * \return error. + */ +SACDEC_ERROR mpegSurroundDecoder_FreeMem( + CMpegSurroundDecoder *pMpegSurroundDecoder); + +/** + * \brief Set one single MPEG Surround decoder parameter. + * + * \param pMpegSurroundDecoder A MPEG Surrround decoder handle. Must not be + * NULL pointer. + * \param param Parameter to be set. See SACDEC_PARAM. + * \param value Parameter value. See SACDEC_PARAM. + * + * \return 0 on sucess, and non-zero on failure. + */ +SACDEC_ERROR mpegSurroundDecoder_SetParam( + CMpegSurroundDecoder *pMpegSurroundDecoder, const SACDEC_PARAM param, + const INT value); + +/** + * \brief Retrieve MPEG Surround decoder library info and fill info list with all depending library infos. + * \param libInfo Pointer to library info list to be filled. + * \return 0 on sucess, and non-zero on failure. + **/ +int mpegSurroundDecoder_GetLibInfo(LIB_INFO *libInfo); + +/** + * \brief Set one single MPEG Surround decoder parameter. + * + * \param pMpegSurroundDecoder A valid MPEG Surrround decoder handle. + * + * \return The additional signal delay caused by the module. + */ +UINT mpegSurroundDecoder_GetDelay(const CMpegSurroundDecoder *self); + +/** + * \brief Get info on whether the USAC pseudo LR feature is active. + * + * \param pMpegSurroundDecoder A valid MPEG Surrround decoder handle. + * \param bsPseudoLr Pointer to return wether pseudo LR USAC feature + * is used. + * + * \return 0 on sucess, and non-zero on failure. + */ +SACDEC_ERROR mpegSurroundDecoder_IsPseudoLR( + CMpegSurroundDecoder *pMpegSurroundDecoder, int *bsPseudoLr); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* #ifndef SAC_DEC_LIB_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_bitdec.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_bitdec.cpp new file mode 100644 index 0000000000000..25b3d9ed306d1 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_bitdec.cpp @@ -0,0 +1,2175 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec bitstream decoder + +*******************************************************************************/ + +#include "sac_bitdec.h" + +#include "sac_dec_errorcodes.h" +#include "nlc_dec.h" +#include "sac_rom.h" +#include "FDK_matrixCalloc.h" +#include "sac_tsd.h" + +enum { + ottVsTotInactiv = 0, + ottVsTotDb1Activ = 1, + ottVsTotDb2Activ = 2, + ottVsTotDb1Db2Activ = 3 +}; + +static SACDEC_ERROR SpatialDecDecodeHelperInfo( + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, UPMIXTYPE upmixType) { + int i; + UINT syntaxFlags; + + /* Determine bit stream syntax */ + syntaxFlags = 0; + switch (pSpatialSpecificConfig->coreCodec) { + case AOT_ER_AAC_ELD: + case AOT_ER_AAC_LD: + syntaxFlags |= SACDEC_SYNTAX_LD; + break; + case AOT_USAC: + syntaxFlags |= SACDEC_SYNTAX_USAC; + break; + case AOT_NONE: + default: + return MPS_UNSUPPORTED_FORMAT; + } + + pSpatialSpecificConfig->syntaxFlags = syntaxFlags; + + switch (pSpatialSpecificConfig->treeConfig) { + case TREE_212: { + pSpatialSpecificConfig->ottCLDdefault[0] = 0; + } break; + default: + return MPS_INVALID_TREECONFIG; + } + + if (syntaxFlags & SACDEC_SYNTAX_USAC) { + if (pSpatialSpecificConfig->bsOttBandsPhasePresent) { + pSpatialSpecificConfig->numOttBandsIPD = + pSpatialSpecificConfig->bsOttBandsPhase; + } else { + int numParameterBands; + + numParameterBands = pSpatialSpecificConfig->freqRes; + switch (numParameterBands) { + case 4: + case 5: + pSpatialSpecificConfig->numOttBandsIPD = 2; + break; + case 7: + pSpatialSpecificConfig->numOttBandsIPD = 3; + break; + case 10: + pSpatialSpecificConfig->numOttBandsIPD = 5; + break; + case 14: + pSpatialSpecificConfig->numOttBandsIPD = 7; + break; + case 20: + case 28: + pSpatialSpecificConfig->numOttBandsIPD = 10; + break; + default: + return MPS_INVALID_PARAMETERBANDS; + } + } + } else { + pSpatialSpecificConfig->numOttBandsIPD = 0; + } + for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) { + { + pSpatialSpecificConfig->bitstreamOttBands[i] = + pSpatialSpecificConfig->freqRes; + } + { + pSpatialSpecificConfig->numOttBands[i] = + pSpatialSpecificConfig->bitstreamOttBands[i]; + if (syntaxFlags & SACDEC_SYNTAX_USAC && + !pSpatialSpecificConfig->bsOttBandsPhasePresent) { + if (pSpatialSpecificConfig->bResidualCoding && + pSpatialSpecificConfig->ResidualConfig[i].bResidualPresent && + (pSpatialSpecificConfig->numOttBandsIPD < + pSpatialSpecificConfig->ResidualConfig[i].nResidualBands)) { + pSpatialSpecificConfig->numOttBandsIPD = + pSpatialSpecificConfig->ResidualConfig[i].nResidualBands; + } + } + } + } /* i */ + + return MPS_OK; +} + +/******************************************************************************* + Functionname: SpatialDecParseExtensionConfig + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ + +static SACDEC_ERROR SpatialDecParseExtensionConfig( + HANDLE_FDK_BITSTREAM bitstream, SPATIAL_SPECIFIC_CONFIG *config, + int numOttBoxes, int numTttBoxes, int numOutChan, int bitsAvailable) { + SACDEC_ERROR err = MPS_OK; + INT ba = bitsAvailable; + + config->sacExtCnt = 0; + config->bResidualCoding = 0; + + ba = fMin((int)FDKgetValidBits(bitstream), ba); + + while ((ba >= 8) && (config->sacExtCnt < MAX_NUM_EXT_TYPES)) { + int bitsRead, nFillBits; + INT tmp; + UINT sacExtLen; + + config->sacExtType[config->sacExtCnt] = FDKreadBits(bitstream, 4); + ba -= 4; + + sacExtLen = FDKreadBits(bitstream, 4); + ba -= 4; + + if (sacExtLen == 15) { + sacExtLen += FDKreadBits(bitstream, 8); + ba -= 8; + if (sacExtLen == 15 + 255) { + sacExtLen += FDKreadBits(bitstream, 16); + ba -= 16; + } + } + + tmp = (INT)FDKgetValidBits( + bitstream); /* Extension config payload start anchor. */ + if ((tmp <= 0) || (tmp < (INT)sacExtLen * 8) || (ba < (INT)sacExtLen * 8)) { + err = MPS_PARSE_ERROR; + goto bail; + } + + switch (config->sacExtType[config->sacExtCnt]) { + default:; /* unknown extension data => do nothing */ + } + + /* skip remaining extension data */ + bitsRead = tmp - FDKgetValidBits(bitstream); + nFillBits = 8 * sacExtLen - bitsRead; + + if (nFillBits < 0) { + err = MPS_PARSE_ERROR; + goto bail; + } else { + /* Skip fill bits or an unkown extension. */ + FDKpushFor(bitstream, nFillBits); + } + + ba -= 8 * sacExtLen; + config->sacExtCnt++; + } + +bail: + return err; +} + +SACDEC_ERROR SpatialDecParseSpecificConfigHeader( + HANDLE_FDK_BITSTREAM bitstream, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + AUDIO_OBJECT_TYPE coreCodec, SPATIAL_DEC_UPMIX_TYPE upmixType) { + SACDEC_ERROR err = MPS_OK; + INT numFillBits; + int sacHeaderLen = 0; + int sacTimeAlignFlag = 0; + + sacTimeAlignFlag = FDKreadBits(bitstream, 1); + sacHeaderLen = FDKreadBits(bitstream, 7); + + if (sacHeaderLen == 127) { + sacHeaderLen += FDKreadBits(bitstream, 16); + } + numFillBits = (INT)FDKgetValidBits(bitstream); + + err = SpatialDecParseSpecificConfig(bitstream, pSpatialSpecificConfig, + sacHeaderLen, coreCodec); + + numFillBits -= + (INT)FDKgetValidBits(bitstream); /* the number of read bits (tmpBits) */ + numFillBits = (8 * sacHeaderLen) - numFillBits; + if (numFillBits < 0) { + /* Parsing went wrong */ + err = MPS_PARSE_ERROR; + } + /* Move to the very end of the SSC */ + FDKpushBiDirectional(bitstream, numFillBits); + + if ((err == MPS_OK) && sacTimeAlignFlag) { + /* not supported */ + FDKreadBits(bitstream, 16); + err = MPS_UNSUPPORTED_CONFIG; + } + + /* Derive additional helper variables */ + SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, (UPMIXTYPE)upmixType); + + return err; +} + +SACDEC_ERROR SpatialDecParseMps212Config( + HANDLE_FDK_BITSTREAM bitstream, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int samplingRate, + AUDIO_OBJECT_TYPE coreCodec, INT stereoConfigIndex, + INT coreSbrFrameLengthIndex) { + int i; + + FDKmemclear(pSpatialSpecificConfig, sizeof(SPATIAL_SPECIFIC_CONFIG)); + + pSpatialSpecificConfig->stereoConfigIndex = stereoConfigIndex; + pSpatialSpecificConfig->coreSbrFrameLengthIndex = coreSbrFrameLengthIndex; + pSpatialSpecificConfig->freqRes = + (SPATIALDEC_FREQ_RES)freqResTable[FDKreadBits(bitstream, 3)]; + if (pSpatialSpecificConfig->freqRes == 0) { + return MPS_PARSE_ERROR; /* reserved value */ + } + + switch (coreCodec) { + case AOT_DRM_USAC: + pSpatialSpecificConfig->bsFixedGainDMX = + (SPATIALDEC_FIXED_GAINS)FDKreadBits(bitstream, 3); + /* tempShapeConfig = (bsTempShapeConfigDrm == 1) ? 3 : 0 */ + pSpatialSpecificConfig->tempShapeConfig = + (SPATIALDEC_TS_CONF)(FDKreadBits(bitstream, 1) * 3); + pSpatialSpecificConfig->decorrConfig = (SPATIALDEC_DECORR_CONF)0; + pSpatialSpecificConfig->bsDecorrType = 0; + break; + case AOT_USAC: + pSpatialSpecificConfig->bsFixedGainDMX = + (SPATIALDEC_FIXED_GAINS)FDKreadBits(bitstream, 3); + pSpatialSpecificConfig->tempShapeConfig = + (SPATIALDEC_TS_CONF)FDKreadBits(bitstream, 2); + pSpatialSpecificConfig->decorrConfig = + (SPATIALDEC_DECORR_CONF)FDKreadBits(bitstream, 2); + if (pSpatialSpecificConfig->decorrConfig > 2) { + return MPS_PARSE_ERROR; /* reserved value */ + } + pSpatialSpecificConfig->bsDecorrType = 0; + break; + default: + return MPS_UNSUPPORTED_FORMAT; + } + pSpatialSpecificConfig->nTimeSlots = (coreSbrFrameLengthIndex == 4) ? 64 : 32; + pSpatialSpecificConfig->bsHighRateMode = (UCHAR)FDKreadBits(bitstream, 1); + + { + pSpatialSpecificConfig->bsPhaseCoding = (UCHAR)FDKreadBits(bitstream, 1); + pSpatialSpecificConfig->bsOttBandsPhasePresent = + (UCHAR)FDKreadBits(bitstream, 1); + if (pSpatialSpecificConfig->bsOttBandsPhasePresent) { + if (MAX_PARAMETER_BANDS < (pSpatialSpecificConfig->bsOttBandsPhase = + FDKreadBits(bitstream, 5))) { + return MPS_PARSE_ERROR; + } + } else { + pSpatialSpecificConfig->bsOttBandsPhase = 0; + } + } + + if (stereoConfigIndex > 1) { /* do residual coding */ + pSpatialSpecificConfig->bResidualCoding = 1; + pSpatialSpecificConfig->ResidualConfig->bResidualPresent = 1; + if (pSpatialSpecificConfig->freqRes < + (pSpatialSpecificConfig->ResidualConfig->nResidualBands = + FDKreadBits(bitstream, 5))) { + return MPS_PARSE_ERROR; + } + pSpatialSpecificConfig->bsOttBandsPhase = + fMax(pSpatialSpecificConfig->bsOttBandsPhase, + pSpatialSpecificConfig->ResidualConfig->nResidualBands); + pSpatialSpecificConfig->bsPseudoLr = (UCHAR)FDKreadBits(bitstream, 1); + + if (pSpatialSpecificConfig->bsPhaseCoding) { + pSpatialSpecificConfig->bsPhaseCoding = 3; + } + } else { + pSpatialSpecificConfig->bResidualCoding = 0; + pSpatialSpecificConfig->ResidualConfig->bResidualPresent = 0; + } + + if (pSpatialSpecificConfig->tempShapeConfig == 2) { + switch (coreCodec) { + case AOT_USAC: + pSpatialSpecificConfig->envQuantMode = FDKreadBits(bitstream, 1); + break; + default: /* added to avoid compiler warning */ + break; /* added to avoid compiler warning */ + } + } + + /* Static parameters */ + + pSpatialSpecificConfig->samplingFreq = + samplingRate; /* wrong for stereoConfigIndex == 3 but value is unused */ + pSpatialSpecificConfig->treeConfig = SPATIALDEC_MODE_RSVD7; + pSpatialSpecificConfig->nOttBoxes = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numOttBoxes; + pSpatialSpecificConfig->nInputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numInputChannels; + pSpatialSpecificConfig->nOutputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numOutputChannels; + + pSpatialSpecificConfig->bArbitraryDownmix = 0; + + for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) { + pSpatialSpecificConfig->OttConfig[i].nOttBands = 0; + } + + if (coreCodec == AOT_DRM_USAC) { + /* MPS payload is MPEG conform -> no need for pseudo DRM AOT */ + coreCodec = AOT_USAC; + } + pSpatialSpecificConfig->coreCodec = coreCodec; + + /* Derive additional helper variables */ + SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, UPMIXTYPE_NORMAL); + + return MPS_OK; +} + +SACDEC_ERROR SpatialDecParseSpecificConfig( + HANDLE_FDK_BITSTREAM bitstream, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int sacHeaderLen, + AUDIO_OBJECT_TYPE coreCodec) { + SACDEC_ERROR err = MPS_OK; + int i; + int bsSamplingFreqIndex; + int bsFreqRes, b3DaudioMode = 0; + int numHeaderBits; + int cfgStartPos, bitsAvailable; + + FDKmemclear(pSpatialSpecificConfig, sizeof(SPATIAL_SPECIFIC_CONFIG)); + + cfgStartPos = FDKgetValidBits(bitstream); + /* It might be that we do not know the SSC length beforehand. */ + if (sacHeaderLen == 0) { + bitsAvailable = cfgStartPos; + } else { + bitsAvailable = 8 * sacHeaderLen; + if (bitsAvailable > cfgStartPos) { + err = MPS_PARSE_ERROR; + goto bail; + } + } + + bsSamplingFreqIndex = FDKreadBits(bitstream, 4); + + if (bsSamplingFreqIndex == 15) { + pSpatialSpecificConfig->samplingFreq = FDKreadBits(bitstream, 24); + } else { + pSpatialSpecificConfig->samplingFreq = + samplingFreqTable[bsSamplingFreqIndex]; + if (pSpatialSpecificConfig->samplingFreq == 0) { + err = MPS_PARSE_ERROR; + goto bail; + } + } + + pSpatialSpecificConfig->nTimeSlots = FDKreadBits(bitstream, 5) + 1; + if ((pSpatialSpecificConfig->nTimeSlots < 1) || + (pSpatialSpecificConfig->nTimeSlots > MAX_TIME_SLOTS)) { + err = MPS_PARSE_ERROR; + goto bail; + } + + bsFreqRes = FDKreadBits(bitstream, 3); + + pSpatialSpecificConfig->freqRes = + (SPATIALDEC_FREQ_RES)freqResTable_LD[bsFreqRes]; + + { + UINT treeConfig = FDKreadBits(bitstream, 4); + + switch (treeConfig) { + case SPATIALDEC_MODE_RSVD7: + pSpatialSpecificConfig->treeConfig = (SPATIALDEC_TREE_CONFIG)treeConfig; + break; + default: + err = MPS_UNSUPPORTED_CONFIG; + goto bail; + } + } + + { + pSpatialSpecificConfig->nOttBoxes = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numOttBoxes; + pSpatialSpecificConfig->nTttBoxes = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numTttBoxes; + pSpatialSpecificConfig->nInputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numInputChannels; + pSpatialSpecificConfig->nOutputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numOutputChannels; + } + + pSpatialSpecificConfig->quantMode = + (SPATIALDEC_QUANT_MODE)FDKreadBits(bitstream, 2); + + pSpatialSpecificConfig->bArbitraryDownmix = FDKreadBits(bitstream, 1); + + pSpatialSpecificConfig->bsFixedGainDMX = + (SPATIALDEC_FIXED_GAINS)FDKreadBits(bitstream, 3); + + pSpatialSpecificConfig->tempShapeConfig = + (SPATIALDEC_TS_CONF)FDKreadBits(bitstream, 2); + if (pSpatialSpecificConfig->tempShapeConfig > 2) { + return MPS_PARSE_ERROR; /* reserved value */ + } + + pSpatialSpecificConfig->decorrConfig = + (SPATIALDEC_DECORR_CONF)FDKreadBits(bitstream, 2); + if (pSpatialSpecificConfig->decorrConfig > 2) { + return MPS_PARSE_ERROR; /* reserved value */ + } + + for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) { + pSpatialSpecificConfig->OttConfig[i].nOttBands = 0; + } + + for (i = 0; i < pSpatialSpecificConfig->nTttBoxes; i++) { + int bTttDualMode = FDKreadBits(bitstream, 1); + FDKreadBits(bitstream, 3); /* not supported */ + + if (bTttDualMode) { + FDKreadBits(bitstream, 8); /* not supported */ + } + } + + if (pSpatialSpecificConfig->tempShapeConfig == 2) { + pSpatialSpecificConfig->envQuantMode = FDKreadBits(bitstream, 1); + } + + if (b3DaudioMode) { + if (FDKreadBits(bitstream, 2) == 0) { /* b3DaudioHRTFset ? */ + int hc; + int HRTFnumBand; + int HRTFfreqRes = FDKreadBits(bitstream, 3); + int HRTFnumChan = FDKreadBits(bitstream, 4); + int HRTFasymmetric = FDKreadBits(bitstream, 1); + + HRTFnumBand = freqResTable_LD[HRTFfreqRes]; + + for (hc = 0; hc < HRTFnumChan; hc++) { + FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFlevelLeft[hc][hb] */ + if (HRTFasymmetric) { + FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFlevelRight[hc][hb] */ + } + if (FDKreadBits(bitstream, 1)) { /* HRTFphase[hc] ? */ + FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFphaseLR[hc][hb] */ + } + if (FDKreadBits(bitstream, 1)) { /* HRTFicc[hc] ? */ + FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFiccLR[hc][hb] */ + } + } + } + } + + FDKbyteAlign(bitstream, + cfgStartPos); /* ISO/IEC FDIS 23003-1: 5.2. ... byte alignment + with respect to the beginning of the syntactic + element in which ByteAlign() occurs. */ + + numHeaderBits = cfgStartPos - (INT)FDKgetValidBits(bitstream); + bitsAvailable -= numHeaderBits; + if (bitsAvailable < 0) { + err = MPS_PARSE_ERROR; + goto bail; + } + + pSpatialSpecificConfig->sacExtCnt = 0; + pSpatialSpecificConfig->bResidualCoding = 0; + + err = SpatialDecParseExtensionConfig( + bitstream, pSpatialSpecificConfig, pSpatialSpecificConfig->nOttBoxes, + pSpatialSpecificConfig->nTttBoxes, + pSpatialSpecificConfig->nOutputChannels, bitsAvailable); + + FDKbyteAlign( + bitstream, + cfgStartPos); /* Same alignment anchor as above because + SpatialExtensionConfig() always reads full bytes */ + + pSpatialSpecificConfig->coreCodec = coreCodec; + + SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, UPMIXTYPE_NORMAL); + +bail: + if (sacHeaderLen > 0) { + /* If the config is of known length then assure that the + bitbuffer is exactly at its end when leaving the function. */ + FDKpushBiDirectional( + bitstream, + (sacHeaderLen * 8) - (cfgStartPos - (INT)FDKgetValidBits(bitstream))); + } + + return err; +} + +int SpatialDecDefaultSpecificConfig( + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + AUDIO_OBJECT_TYPE coreCodec, int samplingFreq, int nTimeSlots, + int sacDecoderLevel, int isBlind, int numCoreChannels) + +{ + int err = MPS_OK; + int i; + + FDK_ASSERT(coreCodec != AOT_NONE); + FDK_ASSERT(nTimeSlots > 0); + FDK_ASSERT(samplingFreq > 0); + + pSpatialSpecificConfig->coreCodec = coreCodec; + pSpatialSpecificConfig->samplingFreq = samplingFreq; + pSpatialSpecificConfig->nTimeSlots = nTimeSlots; + if ((pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_ELD) || + (pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_LD)) + pSpatialSpecificConfig->freqRes = SPATIALDEC_FREQ_RES_23; + else + pSpatialSpecificConfig->freqRes = SPATIALDEC_FREQ_RES_28; + + { + pSpatialSpecificConfig->treeConfig = + SPATIALDEC_MODE_RSVD7; /* 212 configuration */ + } + + { + pSpatialSpecificConfig->nOttBoxes = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numOttBoxes; + pSpatialSpecificConfig->nInputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numInputChannels; + pSpatialSpecificConfig->nOutputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numOutputChannels; + } + + pSpatialSpecificConfig->quantMode = SPATIALDEC_QUANT_FINE_DEF; + pSpatialSpecificConfig->bArbitraryDownmix = 0; + pSpatialSpecificConfig->bResidualCoding = 0; + if ((pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_ELD) || + (pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_LD)) + pSpatialSpecificConfig->bsFixedGainDMX = SPATIALDEC_GAIN_RSVD2; + else + pSpatialSpecificConfig->bsFixedGainDMX = SPATIALDEC_GAIN_MODE0; + + pSpatialSpecificConfig->tempShapeConfig = SPATIALDEC_TS_TPNOWHITE; + pSpatialSpecificConfig->decorrConfig = SPATIALDEC_DECORR_MODE0; + + for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) { + pSpatialSpecificConfig->OttConfig[i].nOttBands = 0; + } + + return err; +} + +/******************************************************************************* + Functionname: coarse2fine + ******************************************************************************* + + Description: + Parameter index mapping from coarse to fine quantization + + Arguments: + +Input: + +Output: + +*******************************************************************************/ +static void coarse2fine(SCHAR *data, DATA_TYPE dataType, int startBand, + int numBands) { + int i; + + for (i = startBand; i < startBand + numBands; i++) { + data[i] <<= 1; + } + + if (dataType == t_CLD) { + for (i = startBand; i < startBand + numBands; i++) { + if (data[i] == -14) + data[i] = -15; + else if (data[i] == 14) + data[i] = 15; + } + } +} + +/******************************************************************************* + Functionname: fine2coarse + ******************************************************************************* + + Description: + Parameter index mapping from fine to coarse quantization + + Arguments: + +Input: + +Output: + +*******************************************************************************/ +static void fine2coarse(SCHAR *data, DATA_TYPE dataType, int startBand, + int numBands) { + int i; + + for (i = startBand; i < startBand + numBands; i++) { + /* Note: the if cases below actually make a difference (negative values) */ + if (dataType == t_CLD) + data[i] /= 2; + else + data[i] >>= 1; + } +} + +/******************************************************************************* + Functionname: getStrideMap + ******************************************************************************* + + Description: + Index Mapping accroding to pbStrides + + Arguments: + +Input: + +Output: + +*******************************************************************************/ +static int getStrideMap(int freqResStride, int startBand, int stopBand, + int *aStrides) { + int i, pb, pbStride, dataBands, strOffset; + + pbStride = pbStrideTable[freqResStride]; + dataBands = (stopBand - startBand - 1) / pbStride + 1; + + aStrides[0] = startBand; + for (pb = 1; pb <= dataBands; pb++) { + aStrides[pb] = aStrides[pb - 1] + pbStride; + } + strOffset = 0; + while (aStrides[dataBands] > stopBand) { + if (strOffset < dataBands) strOffset++; + for (i = strOffset; i <= dataBands; i++) { + aStrides[i]--; + } + } + + return dataBands; +} + +/******************************************************************************* + Functionname: ecDataDec + ******************************************************************************* + + Description: + Do delta decoding and dequantization + + Arguments: + +Input: + +Output: + + +*******************************************************************************/ + +static SACDEC_ERROR ecDataDec( + const SPATIAL_BS_FRAME *frame, UINT syntaxFlags, + HANDLE_FDK_BITSTREAM bitstream, LOSSLESSDATA *const llData, + SCHAR (*data)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], SCHAR **lastdata, + int datatype, int boxIdx, int startBand, int stopBand, SCHAR defaultValue) { + SACDEC_ERROR err = MPS_OK; + int i, j, pb, dataSets, setIdx, bsDataPair, dataBands, oldQuantCoarseXXX; + INT aStrides[MAX_PARAMETER_BANDS + 1] = {0}; + + dataSets = 0; + for (i = 0; i < frame->numParameterSets; i++) { + llData->bsXXXDataMode[i] = (SCHAR)FDKreadBits(bitstream, 2); + + if ((frame->bsIndependencyFlag == 1) && (i == 0) && + (llData->bsXXXDataMode[i] == 1 || + llData->bsXXXDataMode[i] == 2)) { /* This check catches bitstreams + generated by older encoder that + cause trouble */ + return MPS_PARSE_ERROR; + } + if ((i >= frame->numParameterSets - 1) && + (llData->bsXXXDataMode[i] == + 2)) { /* The interpolation mode must not be active for the last + parameter set */ + return MPS_PARSE_ERROR; + } + + if (llData->bsXXXDataMode[i] == 3) { + dataSets++; + } + } + + setIdx = 0; + bsDataPair = 0; + oldQuantCoarseXXX = llData->state->bsQuantCoarseXXXprevParse; + + for (i = 0; i < frame->numParameterSets; i++) { + if (llData->bsXXXDataMode[i] == 0) { + for (pb = startBand; pb < stopBand; pb++) { + lastdata[boxIdx][pb] = defaultValue; + } + + oldQuantCoarseXXX = 0; + } + + if (llData->bsXXXDataMode[i] == 3) { + if (bsDataPair) { + bsDataPair = 0; + } else { + bsDataPair = FDKreadBits(bitstream, 1); + llData->bsQuantCoarseXXX[setIdx] = (UCHAR)FDKreadBits(bitstream, 1); + llData->bsFreqResStrideXXX[setIdx] = (UCHAR)FDKreadBits(bitstream, 2); + + if (llData->bsQuantCoarseXXX[setIdx] != oldQuantCoarseXXX) { + if (oldQuantCoarseXXX) { + coarse2fine(lastdata[boxIdx], (DATA_TYPE)datatype, startBand, + stopBand - startBand); + } else { + fine2coarse(lastdata[boxIdx], (DATA_TYPE)datatype, startBand, + stopBand - startBand); + } + } + + dataBands = getStrideMap(llData->bsFreqResStrideXXX[setIdx], startBand, + stopBand, aStrides); + + for (pb = 0; pb < dataBands; pb++) { + lastdata[boxIdx][startBand + pb] = lastdata[boxIdx][aStrides[pb]]; + } + + if (boxIdx > MAX_NUM_OTT) return MPS_INVALID_BOXIDX; + if ((setIdx + bsDataPair) > MAX_PARAMETER_SETS) + return MPS_INVALID_SETIDX; + + /* DECODER_TYPE defined in FDK_tools */ + DECODER_TYPE this_decoder_type = SAC_DECODER; + if (syntaxFlags & (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) { + this_decoder_type = USAC_DECODER; + } else if (syntaxFlags & SACDEC_SYNTAX_LD) { + this_decoder_type = SAOC_DECODER; + } + + err = (SACDEC_ERROR)EcDataPairDec( + this_decoder_type, bitstream, data[boxIdx][setIdx + 0], + data[boxIdx][setIdx + 1], lastdata[boxIdx], (DATA_TYPE)datatype, + startBand, dataBands, bsDataPair, llData->bsQuantCoarseXXX[setIdx], + !(frame->bsIndependencyFlag && (i == 0)) || (setIdx > 0)); + if (err != MPS_OK) goto bail; + + if (datatype == t_IPD) { + const SCHAR mask = (llData->bsQuantCoarseXXX[setIdx]) ? 7 : 15; + for (pb = 0; pb < dataBands; pb++) { + for (j = aStrides[pb]; j < aStrides[pb + 1]; j++) { + lastdata[boxIdx][j] = + data[boxIdx][setIdx + bsDataPair][startBand + pb] & mask; + } + } + } else { + for (pb = 0; pb < dataBands; pb++) { + for (j = aStrides[pb]; j < aStrides[pb + 1]; j++) { + lastdata[boxIdx][j] = + data[boxIdx][setIdx + bsDataPair][startBand + pb]; + } + } + } + + oldQuantCoarseXXX = llData->bsQuantCoarseXXX[setIdx]; + + if (bsDataPair) { + llData->bsQuantCoarseXXX[setIdx + 1] = + llData->bsQuantCoarseXXX[setIdx]; + llData->bsFreqResStrideXXX[setIdx + 1] = + llData->bsFreqResStrideXXX[setIdx]; + } + setIdx += bsDataPair + 1; + } /* !bsDataPair */ + } /* llData->bsXXXDataMode[i] == 3 */ + } + + llData->state->bsQuantCoarseXXXprevParse = oldQuantCoarseXXX; + +bail: + return err; +} + +/******************************************************************************* + Functionname: parseArbitraryDownmixData + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static SACDEC_ERROR parseArbitraryDownmixData( + spatialDec *self, const SPATIAL_SPECIFIC_CONFIG *pSSC, + const UINT syntaxFlags, const SPATIAL_BS_FRAME *frame, + HANDLE_FDK_BITSTREAM bitstream) { + SACDEC_ERROR err = MPS_OK; + int ch; + int offset = pSSC->nOttBoxes; + + /* CLD (arbitrary down-mix gains) */ + for (ch = 0; ch < pSSC->nInputChannels; ch++) { + err = ecDataDec(frame, syntaxFlags, bitstream, + &frame->CLDLosslessData[offset + ch], + frame->cmpArbdmxGainIdx, self->cmpArbdmxGainIdxPrev, t_CLD, + ch, 0, pSSC->freqRes, arbdmxGainDefault); + if (err != MPS_OK) return err; + } + + return err; + +} /* parseArbitraryDownmixData */ + +/******************************************************************************* + Functionname: SpatialDecParseFrame + ******************************************************************************* + + Description: + + Arguments: + + Input: + + Output: + +*******************************************************************************/ + +static int nBitsParamSlot(int i) { + int bitsParamSlot; + + bitsParamSlot = fMax(0, DFRACT_BITS - 1 - fNormz((FIXP_DBL)i)); + if ((1 << bitsParamSlot) < i) { + bitsParamSlot++; + } + FDK_ASSERT((bitsParamSlot >= 0) && (bitsParamSlot <= 32)); + + return bitsParamSlot; +} + +SACDEC_ERROR SpatialDecParseFrameData( + spatialDec_struct *self, SPATIAL_BS_FRAME *frame, + HANDLE_FDK_BITSTREAM bitstream, + const SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, UPMIXTYPE upmixType, + int fGlobalIndependencyFlag) { + SACDEC_ERROR err = MPS_OK; + int bsFramingType, dataBands, ps, pg, i; + int pb; + int numTempShapeChan = 0; + int bsNumOutputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig] + .numOutputChannels; /* CAUTION: Maybe different to + pSpatialSpecificConfig->treeConfig in some + modes! */ + int paramSetErr = 0; + UINT alignAnchor = FDKgetValidBits( + bitstream); /* Anchor for ByteAlign() function. See comment below. */ + UINT syntaxFlags; + + syntaxFlags = pSpatialSpecificConfig->syntaxFlags; + + if ((syntaxFlags & (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) && + pSpatialSpecificConfig->bsHighRateMode == 0) { + bsFramingType = 0; /* fixed framing */ + frame->numParameterSets = 1; + } else { + bsFramingType = FDKreadBits(bitstream, 1); + if (syntaxFlags & SACDEC_SYNTAX_LD) + frame->numParameterSets = FDKreadBits(bitstream, 1) + 1; + else + frame->numParameterSets = FDKreadBits(bitstream, 3) + 1; + } + + /* Any error after this line shall trigger parameter invalidation at bail + * label. */ + paramSetErr = 1; + + if (frame->numParameterSets >= MAX_PARAMETER_SETS) { + goto bail; + } + + /* Basic config check. */ + if (pSpatialSpecificConfig->nInputChannels <= 0 || + pSpatialSpecificConfig->nOutputChannels <= 0) { + err = MPS_UNSUPPORTED_CONFIG; + goto bail; + } + + if (bsFramingType) { + int prevParamSlot = -1; + int bitsParamSlot; + + { + bitsParamSlot = nBitsParamSlot(pSpatialSpecificConfig->nTimeSlots); + + for (i = 0; i < frame->numParameterSets; i++) { + frame->paramSlot[i] = FDKreadBits(bitstream, bitsParamSlot); + /* Sanity check */ + if ((frame->paramSlot[i] <= prevParamSlot) || + (frame->paramSlot[i] >= pSpatialSpecificConfig->nTimeSlots)) { + err = MPS_PARSE_ERROR; + goto bail; + } + prevParamSlot = frame->paramSlot[i]; + } + } + } else { + for (i = 0; i < frame->numParameterSets; i++) { + frame->paramSlot[i] = ((pSpatialSpecificConfig->nTimeSlots * (i + 1)) / + frame->numParameterSets) - + 1; + } + } + + if ((syntaxFlags & (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) && + fGlobalIndependencyFlag) { + frame->bsIndependencyFlag = 1; + } else { + frame->bsIndependencyFlag = (UCHAR)FDKreadBits(bitstream, 1); + } + + /* + * OttData() + */ + for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) { + err = ecDataDec(frame, syntaxFlags, bitstream, &frame->CLDLosslessData[i], + frame->cmpOttCLDidx, self->cmpOttCLDidxPrev, t_CLD, i, 0, + pSpatialSpecificConfig->bitstreamOttBands[i], + pSpatialSpecificConfig->ottCLDdefault[i]); + if (err != MPS_OK) { + goto bail; + } + } /* i < numOttBoxes */ + + { + for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) { + err = ecDataDec(frame, syntaxFlags, bitstream, &frame->ICCLosslessData[i], + frame->cmpOttICCidx, self->cmpOttICCidxPrev, t_ICC, i, 0, + pSpatialSpecificConfig->bitstreamOttBands[i], ICCdefault); + if (err != MPS_OK) { + goto bail; + } + } /* i < numOttBoxes */ + } /* !oneICC */ + + if ((pSpatialSpecificConfig->treeConfig == SPATIALDEC_MODE_RSVD7) && + (pSpatialSpecificConfig->bsPhaseCoding)) { + frame->phaseMode = FDKreadBits(bitstream, 1); + + if (frame->phaseMode == 0) { + for (pb = 0; pb < pSpatialSpecificConfig->numOttBandsIPD; pb++) { + self->cmpOttIPDidxPrev[0][pb] = 0; + for (i = 0; i < frame->numParameterSets; i++) { + frame->cmpOttIPDidx[0][i][pb] = 0; + // frame->ottIPDidx[0][i][pb] = 0; + } + /* self->ottIPDidxPrev[0][pb] = 0; */ + } + frame->OpdSmoothingMode = 0; + } else { + frame->OpdSmoothingMode = FDKreadBits(bitstream, 1); + err = ecDataDec(frame, syntaxFlags, bitstream, &frame->IPDLosslessData[0], + frame->cmpOttIPDidx, self->cmpOttIPDidxPrev, t_IPD, 0, 0, + pSpatialSpecificConfig->numOttBandsIPD, IPDdefault); + if (err != MPS_OK) { + goto bail; + } + } + } + + /* + * SmgData() + */ + + { + if (!pSpatialSpecificConfig->bsHighRateMode && + (syntaxFlags & SACDEC_SYNTAX_USAC)) { + for (ps = 0; ps < frame->numParameterSets; ps++) { + frame->bsSmoothMode[ps] = 0; + } + } else { + for (ps = 0; ps < frame->numParameterSets; ps++) { + frame->bsSmoothMode[ps] = (UCHAR)FDKreadBits(bitstream, 2); + if (frame->bsSmoothMode[ps] >= 2) { + frame->bsSmoothTime[ps] = (UCHAR)FDKreadBits(bitstream, 2); + } + if (frame->bsSmoothMode[ps] == 3) { + frame->bsFreqResStrideSmg[ps] = (UCHAR)FDKreadBits(bitstream, 2); + dataBands = (pSpatialSpecificConfig->freqRes - 1) / + pbStrideTable[frame->bsFreqResStrideSmg[ps]] + + 1; + for (pg = 0; pg < dataBands; pg++) { + frame->bsSmgData[ps][pg] = (UCHAR)FDKreadBits(bitstream, 1); + } + } + } /* ps < numParameterSets */ + } + } + + /* + * TempShapeData() + */ + if ((pSpatialSpecificConfig->tempShapeConfig == 3) && + (syntaxFlags & SACDEC_SYNTAX_USAC)) { + int TsdErr; + TsdErr = TsdRead(bitstream, pSpatialSpecificConfig->nTimeSlots, + &frame->TsdData[0]); + if (TsdErr) { + err = MPS_PARSE_ERROR; + goto bail; + } + } else { + frame->TsdData[0].bsTsdEnable = 0; + } + + for (i = 0; i < bsNumOutputChannels; i++) { + frame->tempShapeEnableChannelSTP[i] = 0; + frame->tempShapeEnableChannelGES[i] = 0; + } + + if ((pSpatialSpecificConfig->tempShapeConfig == 1) || + (pSpatialSpecificConfig->tempShapeConfig == 2)) { + int bsTempShapeEnable = FDKreadBits(bitstream, 1); + if (bsTempShapeEnable) { + numTempShapeChan = + tempShapeChanTable[pSpatialSpecificConfig->tempShapeConfig - 1] + [pSpatialSpecificConfig->treeConfig]; + switch (pSpatialSpecificConfig->tempShapeConfig) { + case 1: /* STP */ + for (i = 0; i < numTempShapeChan; i++) { + int stpEnable = FDKreadBits(bitstream, 1); + frame->tempShapeEnableChannelSTP[i] = stpEnable; + } + break; + case 2: /* GES */ + { + UCHAR gesChannelEnable[MAX_OUTPUT_CHANNELS]; + + for (i = 0; i < numTempShapeChan; i++) { + gesChannelEnable[i] = (UCHAR)FDKreadBits(bitstream, 1); + frame->tempShapeEnableChannelGES[i] = gesChannelEnable[i]; + } + for (i = 0; i < numTempShapeChan; i++) { + if (gesChannelEnable[i]) { + int envShapeData_tmp[MAX_TIME_SLOTS]; + if (huff_dec_reshape(bitstream, envShapeData_tmp, + pSpatialSpecificConfig->nTimeSlots) != 0) { + err = MPS_PARSE_ERROR; + goto bail; + } + for (int ts = 0; ts < pSpatialSpecificConfig->nTimeSlots; ts++) { + if (!(envShapeData_tmp[ts] >= 0) && + (envShapeData_tmp[ts] <= 4)) { + err = MPS_PARSE_ERROR; + goto bail; + } + frame->bsEnvShapeData[i][ts] = (UCHAR)envShapeData_tmp[ts]; + } + } + } + } break; + default: + err = MPS_INVALID_TEMPSHAPE; + goto bail; + } + } /* bsTempShapeEnable */ + } /* pSpatialSpecificConfig->tempShapeConfig != 0 */ + + if (pSpatialSpecificConfig->bArbitraryDownmix != 0) { + err = parseArbitraryDownmixData(self, pSpatialSpecificConfig, syntaxFlags, + frame, bitstream); + if (err != MPS_OK) goto bail; + } + + if (1 && (!(syntaxFlags & (SACDEC_SYNTAX_USAC)))) { + FDKbyteAlign(bitstream, + alignAnchor); /* ISO/IEC FDIS 23003-1: 5.2. ... byte alignment + with respect to the beginning of the syntactic + element in which ByteAlign() occurs. */ + } + +bail: + if (err != MPS_OK && paramSetErr != 0) { + /* Since the parameter set data has already been written to the instance we + * need to ... */ + frame->numParameterSets = 0; /* ... signal that it is corrupt ... */ + } + + return err; + +} /* SpatialDecParseFrame */ + +/******************************************************************************* + Functionname: createMapping + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static void createMapping(int aMap[MAX_PARAMETER_BANDS + 1], int startBand, + int stopBand, int stride) { + int inBands, outBands, bandsAchived, bandsDiff, incr, k, i; + int vDk[MAX_PARAMETER_BANDS + 1]; + inBands = stopBand - startBand; + outBands = (inBands - 1) / stride + 1; + + if (outBands < 1) { + outBands = 1; + } + + bandsAchived = outBands * stride; + bandsDiff = inBands - bandsAchived; + for (i = 0; i < outBands; i++) { + vDk[i] = stride; + } + + if (bandsDiff > 0) { + incr = -1; + k = outBands - 1; + } else { + incr = 1; + k = 0; + } + + while (bandsDiff != 0) { + vDk[k] = vDk[k] - incr; + k = k + incr; + bandsDiff = bandsDiff + incr; + if (k >= outBands) { + if (bandsDiff > 0) { + k = outBands - 1; + } else if (bandsDiff < 0) { + k = 0; + } + } + } + aMap[0] = startBand; + for (i = 0; i < outBands; i++) { + aMap[i + 1] = aMap[i] + vDk[i]; + } +} /* createMapping */ + +/******************************************************************************* + Functionname: mapFrequency + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static void mapFrequency(const SCHAR *pInput, /* Input */ + SCHAR *pOutput, /* Output */ + int *pMap, /* Mapping function */ + int dataBands) /* Number of data Bands */ +{ + int i, j; + int startBand0 = pMap[0]; + + for (i = 0; i < dataBands; i++) { + int startBand, stopBand, value; + + value = pInput[i + startBand0]; + + startBand = pMap[i]; + stopBand = pMap[i + 1]; + for (j = startBand; j < stopBand; j++) { + pOutput[j] = value; + } + } +} + +/******************************************************************************* + Functionname: deq + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static int deqIdx(int value, int paramType) { + int idx = -1; + + switch (paramType) { + case t_CLD: + if (((value + 15) >= 0) && ((value + 15) < 31)) { + idx = (value + 15); + } + break; + + case t_ICC: + if ((value >= 0) && (value < 8)) { + idx = value; + } + break; + + case t_IPD: + /* (+/-)15 * MAX_PARAMETER_BANDS for differential coding in frequency + * domain (according to rbl) */ + if ((value >= -420) && (value <= 420)) { + idx = (value & 0xf); + } + break; + + default: + FDK_ASSERT(0); + } + + return idx; +} + + /******************************************************************************* + Functionname: factorFunct + ******************************************************************************* + + Description: + + Arguments: + + Return: + + *******************************************************************************/ + +#define SF_IDX (7) +#define SF_FACTOR (3) +#define SCALE_FACTOR (1 << SF_FACTOR) +#define SCALE_CLD_C1C2 (1 << SF_CLD_C1C2) + +static FIXP_DBL factorFunct(FIXP_DBL ottVsTotDb, INT quantMode) { + FIXP_DBL factor; + + if (ottVsTotDb > FL2FXCONST_DBL(0.0)) { + ottVsTotDb = FL2FXCONST_DBL(0.0); + } + + ottVsTotDb = -ottVsTotDb; + + switch (quantMode) { + case 0: + factor = FL2FXCONST_DBL(1.0f / SCALE_FACTOR); + break; + case 1: + if (ottVsTotDb >= FL2FXCONST_DBL(21.0f / SCALE_CLD_C1C2)) + factor = FL2FXCONST_DBL(5.0f / SCALE_FACTOR); + else if (ottVsTotDb <= FL2FXCONST_DBL(1.0f / SCALE_CLD_C1C2)) + factor = FL2FXCONST_DBL(1.0f / SCALE_FACTOR); + else + factor = (fMult(FL2FXCONST_DBL(0.2f), ottVsTotDb) + + FL2FXCONST_DBL(0.8f / SCALE_CLD_C1C2)) + << (SF_CLD_C1C2 - SF_FACTOR); + break; + case 2: + if (ottVsTotDb >= FL2FXCONST_DBL(25.0f / SCALE_CLD_C1C2)) { + FDK_ASSERT(SF_FACTOR == 3); + factor = (FIXP_DBL) + MAXVAL_DBL; /* avoid warning: FL2FXCONST_DBL(8.0f/SCALE_FACTOR) */ + } else if (ottVsTotDb <= FL2FXCONST_DBL(1.0f / SCALE_CLD_C1C2)) + factor = FL2FXCONST_DBL(1.0f / SCALE_FACTOR); + else + factor = (fMult(FL2FXCONST_DBL(7.0f / 24.0f), ottVsTotDb) + + FL2FXCONST_DBL((17.0f / 24.0f) / SCALE_CLD_C1C2)) + << (SF_CLD_C1C2 - SF_FACTOR); + break; + default: + factor = FL2FXCONST_DBL(0.0f); + } + + return (factor); +} + +/******************************************************************************* + Functionname: factorCLD + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static void factorCLD(SCHAR *idx, FIXP_DBL ottVsTotDb, FIXP_DBL *ottVsTotDb1, + FIXP_DBL *ottVsTotDb2, SCHAR ottVsTotDbMode, + INT quantMode) { + FIXP_DBL factor; + FIXP_DBL cldIdxFract; + INT cldIdx; + + factor = factorFunct(ottVsTotDb, quantMode); + + cldIdxFract = + fMult((FIXP_DBL)((*idx) << ((DFRACT_BITS - 1) - SF_IDX)), factor); + cldIdxFract += FL2FXCONST_DBL(15.5f / (1 << (SF_FACTOR + SF_IDX))); + cldIdx = fixp_truncateToInt(cldIdxFract, SF_FACTOR + SF_IDX); + + cldIdx = fMin(cldIdx, 30); + cldIdx = fMax(cldIdx, 0); + + *idx = cldIdx - 15; + + if (ottVsTotDbMode & ottVsTotDb1Activ) + (*ottVsTotDb1) = ottVsTotDb + dequantCLD_c1[cldIdx]; + + if (ottVsTotDbMode & ottVsTotDb2Activ) + (*ottVsTotDb2) = ottVsTotDb + dequantCLD_c1[30 - cldIdx]; +} + +/******************************************************************************* + Functionname: mapIndexData + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static SACDEC_ERROR mapIndexData( + LOSSLESSDATA *llData, SCHAR ***outputDataIdx, SCHAR ***outputIdxData, + const SCHAR (*cmpIdxData)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], + SCHAR ***diffIdxData, SCHAR xttIdx, SCHAR **idxPrev, int paramIdx, + int paramType, int startBand, int stopBand, SCHAR defaultValue, + int numParameterSets, const int *paramSlot, int extendFrame, int quantMode, + SpatialDecConcealmentInfo *concealmentInfo, SCHAR ottVsTotDbMode, + FIXP_DBL (*pOttVsTotDbIn)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], + FIXP_DBL (*pOttVsTotDb1)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], + FIXP_DBL (*pOttVsTotDb2)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]) { + int aParamSlots[MAX_PARAMETER_SETS]; + int aInterpolate[MAX_PARAMETER_SETS] = {0}; + + int dataSets; + int aMap[MAX_PARAMETER_BANDS + 1]; + + int setIdx, i, band, parmSlot; + int dataBands; + int ps, pb; + int i1; + + if (numParameterSets > MAX_PARAMETER_SETS) return MPS_WRONG_PARAMETERSETS; + + dataSets = 0; + for (i = 0; i < numParameterSets; i++) { + if (llData->bsXXXDataMode[i] == 3) { + aParamSlots[dataSets] = i; + dataSets++; + } + } + + setIdx = 0; + + /* Main concealment stage is here: */ + SpatialDecConcealment_Apply( + concealmentInfo, cmpIdxData[xttIdx], + (diffIdxData != NULL) ? diffIdxData[xttIdx] : NULL, idxPrev[xttIdx], + llData->bsXXXDataMode, startBand, stopBand, defaultValue, paramType, + numParameterSets); + + /* Prepare data */ + for (i = 0; i < numParameterSets; i++) { + if (llData->bsXXXDataMode[i] == 0) { + llData->nocmpQuantCoarseXXX[i] = 0; + for (band = startBand; band < stopBand; band++) { + outputIdxData[xttIdx][i][band] = defaultValue; + } + for (band = startBand; band < stopBand; band++) { + idxPrev[xttIdx][band] = outputIdxData[xttIdx][i][band]; + } + /* Because the idxPrev are also set to the defaultValue -> signalize fine + */ + llData->state->bsQuantCoarseXXXprev = 0; + } + + if (llData->bsXXXDataMode[i] == 1) { + for (band = startBand; band < stopBand; band++) { + outputIdxData[xttIdx][i][band] = idxPrev[xttIdx][band]; + } + llData->nocmpQuantCoarseXXX[i] = llData->state->bsQuantCoarseXXXprev; + } + + if (llData->bsXXXDataMode[i] == 2) { + for (band = startBand; band < stopBand; band++) { + outputIdxData[xttIdx][i][band] = idxPrev[xttIdx][band]; + } + llData->nocmpQuantCoarseXXX[i] = llData->state->bsQuantCoarseXXXprev; + aInterpolate[i] = 1; + } else { + aInterpolate[i] = 0; + } + + if (llData->bsXXXDataMode[i] == 3) { + int stride; + + parmSlot = aParamSlots[setIdx]; + stride = pbStrideTable[llData->bsFreqResStrideXXX[setIdx]]; + dataBands = (stopBand - startBand - 1) / stride + 1; + createMapping(aMap, startBand, stopBand, stride); + mapFrequency(&cmpIdxData[xttIdx][setIdx][0], + &outputIdxData[xttIdx][parmSlot][0], aMap, dataBands); + for (band = startBand; band < stopBand; band++) { + idxPrev[xttIdx][band] = outputIdxData[xttIdx][parmSlot][band]; + } + llData->state->bsQuantCoarseXXXprev = llData->bsQuantCoarseXXX[setIdx]; + llData->nocmpQuantCoarseXXX[i] = llData->bsQuantCoarseXXX[setIdx]; + + setIdx++; + } + if (diffIdxData != NULL) { + for (band = startBand; band < stopBand; band++) { + outputIdxData[xttIdx][i][band] += diffIdxData[xttIdx][i][band]; + } + } + } /* for( i = 0 ; i < numParameterSets; i++ ) */ + + /* Map all coarse data to fine */ + for (i = 0; i < numParameterSets; i++) { + if (llData->nocmpQuantCoarseXXX[i] == 1) { + coarse2fine(outputIdxData[xttIdx][i], (DATA_TYPE)paramType, startBand, + stopBand - startBand); + llData->nocmpQuantCoarseXXX[i] = 0; + } + } + + /* Interpolate */ + i1 = 0; + for (i = 0; i < numParameterSets; i++) { + if (aInterpolate[i] != 1) { + i1 = i; + } else { + int xi, i2, x1, x2; + + for (i2 = i; i2 < numParameterSets; i2++) { + if (aInterpolate[i2] != 1) break; + } + if (i2 >= numParameterSets) return MPS_WRONG_PARAMETERSETS; + + x1 = paramSlot[i1]; + xi = paramSlot[i]; + x2 = paramSlot[i2]; + + for (band = startBand; band < stopBand; band++) { + int yi, y1, y2; + y1 = outputIdxData[xttIdx][i1][band]; + y2 = outputIdxData[xttIdx][i2][band]; + if (x1 != x2) { + yi = y1 + (xi - x1) * (y2 - y1) / (x2 - x1); + } else { + yi = y1 /*+ (xi-x1)*(y2-y1)/1e-12*/; + } + outputIdxData[xttIdx][i][band] = yi; + } + } + } /* for( i = 0 ; i < numParameterSets; i++ ) */ + + /* Dequantize data and apply factorCLD if necessary */ + for (ps = 0; ps < numParameterSets; ps++) { + if (quantMode && (paramType == t_CLD)) { + if (pOttVsTotDbIn == 0) return MPS_WRONG_OTT; + if ((pOttVsTotDb1 == 0) && (ottVsTotDbMode & ottVsTotDb1Activ)) + return MPS_WRONG_OTT; + if ((pOttVsTotDb2 == 0) && (ottVsTotDbMode & ottVsTotDb2Activ)) + return MPS_WRONG_OTT; + + for (pb = startBand; pb < stopBand; pb++) { + factorCLD(&(outputIdxData[xttIdx][ps][pb]), (*pOttVsTotDbIn)[ps][pb], + (pOttVsTotDb1 != NULL) ? &((*pOttVsTotDb1)[ps][pb]) : NULL, + (pOttVsTotDb2 != NULL) ? &((*pOttVsTotDb2)[ps][pb]) : NULL, + ottVsTotDbMode, quantMode); + } + } + + /* Dequantize data */ + for (band = startBand; band < stopBand; band++) { + outputDataIdx[xttIdx][ps][band] = + deqIdx(outputIdxData[xttIdx][ps][band], paramType); + if (outputDataIdx[xttIdx][ps][band] == -1) { + outputDataIdx[xttIdx][ps][band] = defaultValue; + } + } + } /* for( i = 0 ; i < numParameterSets; i++ ) */ + + if (extendFrame) { + if (paramType == t_IPD) { + llData->bsQuantCoarseXXX[numParameterSets] = + llData->bsQuantCoarseXXX[numParameterSets - 1]; + } + for (band = startBand; band < stopBand; band++) { + outputDataIdx[xttIdx][numParameterSets][band] = + outputDataIdx[xttIdx][numParameterSets - 1][band]; + } + } + + return MPS_OK; +} + +/******************************************************************************* + Functionname: decodeAndMapFrameOtt + ******************************************************************************* + + Description: + Do delta decoding and dequantization + + Arguments: + +Input: + +Output: + +*******************************************************************************/ +static SACDEC_ERROR decodeAndMapFrameOtt(HANDLE_SPATIAL_DEC self, + SPATIAL_BS_FRAME *pCurBs) { + int i, ottIdx; + int numOttBoxes; + + SACDEC_ERROR err = MPS_OK; + + numOttBoxes = self->numOttBoxes; + + switch (self->treeConfig) { + default: { + if (self->quantMode != 0) { + goto bail; + } + } + for (i = 0; i < numOttBoxes; i++) { + err = mapIndexData( + &pCurBs->CLDLosslessData[i], /* LOSSLESSDATA *llData,*/ + self->ottCLD__FDK, self->outIdxData, + pCurBs + ->cmpOttCLDidx, /* int + cmpIdxData[MAX_NUM_OTT][MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], + */ + NULL, /* no differential data */ + i, /* int xttIdx, Which ott/ttt index to use for input and + output buffers */ + self->ottCLDidxPrev, /* int + idxPrev[MAX_NUM_OTT][MAX_PARAMETER_BANDS], + */ + i, t_CLD, 0, /* int startBand, */ + self->pConfigCurrent->bitstreamOttBands[i], /* int stopBand, */ + self->pConfigCurrent->ottCLDdefault[i], /* int defaultValue, */ + pCurBs->numParameterSets, /* int numParameterSets) */ + pCurBs->paramSlot, self->extendFrame, self->quantMode, + &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL); + if (err != MPS_OK) goto bail; + + } /* for(i = 0; i < numOttBoxes ; i++ ) */ + break; + } /* case */ + + for (ottIdx = 0; ottIdx < numOttBoxes; ottIdx++) { + /* Read ICC */ + err = mapIndexData( + &pCurBs->ICCLosslessData[ottIdx], /* LOSSLESSDATA *llData,*/ + self->ottICC__FDK, self->outIdxData, + pCurBs + ->cmpOttICCidx, /* int + cmpIdxData[MAX_NUM_OTT][MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], + */ + self->ottICCdiffidx, /* differential data */ + ottIdx, /* int xttIdx, Which ott/ttt index to use for input and + output buffers */ + self->ottICCidxPrev, /* int idxPrev[MAX_NUM_OTT][MAX_PARAMETER_BANDS], + */ + ottIdx, t_ICC, 0, /* int startBand, */ + self->pConfigCurrent->bitstreamOttBands[ottIdx], /* int stopBand, */ + ICCdefault, /* int defaultValue, */ + pCurBs->numParameterSets, /* int numParameterSets) */ + pCurBs->paramSlot, self->extendFrame, self->quantMode, + &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL); + if (err != MPS_OK) goto bail; + } /* ottIdx */ + + if ((self->treeConfig == TREE_212) && (self->phaseCoding)) { + if (pCurBs->phaseMode == 0) { + for (int pb = 0; pb < self->pConfigCurrent->numOttBandsIPD; pb++) { + self->ottIPDidxPrev[0][pb] = 0; + } + } + for (ottIdx = 0; ottIdx < numOttBoxes; ottIdx++) { + err = mapIndexData( + &pCurBs->IPDLosslessData[ottIdx], self->ottIPD__FDK, self->outIdxData, + pCurBs->cmpOttIPDidx, NULL, ottIdx, self->ottIPDidxPrev, ottIdx, + t_IPD, 0, self->numOttBandsIPD, IPDdefault, pCurBs->numParameterSets, + pCurBs->paramSlot, self->extendFrame, self->quantMode, + &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL); + } + } + +bail: + + return MPS_OK; + +} /* decodeAndMapFrameOtt */ + +/******************************************************************************* + Functionname: decodeAndMapFrameSmg + ******************************************************************************* + + Description: + Decode smoothing flags + + Arguments: + +Input: + +Output: + + +*******************************************************************************/ +static SACDEC_ERROR decodeAndMapFrameSmg(HANDLE_SPATIAL_DEC self, + const SPATIAL_BS_FRAME *frame) { + int ps, pb, pg, pbStride, dataBands, pbStart, pbStop, + aGroupToBand[MAX_PARAMETER_BANDS + 1]; + + if (frame->numParameterSets > MAX_PARAMETER_SETS) + return MPS_WRONG_PARAMETERSETS; + if (self->bitstreamParameterBands > MAX_PARAMETER_BANDS) + return MPS_WRONG_PARAMETERBANDS; + + for (ps = 0; ps < frame->numParameterSets; ps++) { + switch (frame->bsSmoothMode[ps]) { + case 0: + self->smgTime[ps] = 256; + FDKmemclear(self->smgData[ps], + self->bitstreamParameterBands * sizeof(UCHAR)); + break; + + case 1: + if (ps > 0) { + self->smgTime[ps] = self->smgTime[ps - 1]; + FDKmemcpy(self->smgData[ps], self->smgData[ps - 1], + self->bitstreamParameterBands * sizeof(UCHAR)); + } else { + self->smgTime[ps] = self->smoothState->prevSmgTime; + FDKmemcpy(self->smgData[ps], self->smoothState->prevSmgData, + self->bitstreamParameterBands * sizeof(UCHAR)); + } + break; + + case 2: + self->smgTime[ps] = smgTimeTable[frame->bsSmoothTime[ps]]; + for (pb = 0; pb < self->bitstreamParameterBands; pb++) { + self->smgData[ps][pb] = 1; + } + break; + + case 3: + self->smgTime[ps] = smgTimeTable[frame->bsSmoothTime[ps]]; + pbStride = pbStrideTable[frame->bsFreqResStrideSmg[ps]]; + dataBands = (self->bitstreamParameterBands - 1) / pbStride + 1; + createMapping(aGroupToBand, 0, self->bitstreamParameterBands, pbStride); + for (pg = 0; pg < dataBands; pg++) { + pbStart = aGroupToBand[pg]; + pbStop = aGroupToBand[pg + 1]; + for (pb = pbStart; pb < pbStop; pb++) { + self->smgData[ps][pb] = frame->bsSmgData[ps][pg]; + } + } + break; + } + } + + self->smoothState->prevSmgTime = self->smgTime[frame->numParameterSets - 1]; + FDKmemcpy(self->smoothState->prevSmgData, + self->smgData[frame->numParameterSets - 1], + self->bitstreamParameterBands * sizeof(UCHAR)); + + if (self->extendFrame) { + self->smgTime[frame->numParameterSets] = + self->smgTime[frame->numParameterSets - 1]; + FDKmemcpy(self->smgData[frame->numParameterSets], + self->smgData[frame->numParameterSets - 1], + self->bitstreamParameterBands * sizeof(UCHAR)); + } + + return MPS_OK; +} + +/******************************************************************************* + Functionname: decodeAndMapFrameArbdmx + ******************************************************************************* + + Description: + Do delta decoding and dequantization + + Arguments: + +Input: + +Output: + +*******************************************************************************/ +static SACDEC_ERROR decodeAndMapFrameArbdmx(HANDLE_SPATIAL_DEC self, + const SPATIAL_BS_FRAME *frame) { + SACDEC_ERROR err = MPS_OK; + int ch; + int offset = self->numOttBoxes; + + for (ch = 0; ch < self->numInputChannels; ch++) { + err = mapIndexData(&frame->CLDLosslessData[offset + ch], + self->arbdmxGain__FDK, self->outIdxData, + frame->cmpArbdmxGainIdx, NULL, /* no differential data */ + ch, self->arbdmxGainIdxPrev, offset + ch, t_CLD, 0, + self->bitstreamParameterBands, + 0 /*self->arbdmxGainDefault*/, frame->numParameterSets, + frame->paramSlot, self->extendFrame, 0, + &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL); + if (err != MPS_OK) goto bail; + } + +bail: + return err; +} /* decodeAndMapFrameArbdmx */ + +/******************************************************************************* + Functionname: SpatialDecDecodeFrame + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +SACDEC_ERROR SpatialDecDecodeFrame(spatialDec *self, SPATIAL_BS_FRAME *frame) { + SACDEC_ERROR err = MPS_OK; + + self->extendFrame = 0; + if (frame->paramSlot[frame->numParameterSets - 1] != self->timeSlots - 1) { + self->extendFrame = 1; + } + + self->TsdTs = 0; + + /****** DTDF and MAP DATA ********/ + if ((err = decodeAndMapFrameOtt(self, frame)) != MPS_OK) goto bail; + + if ((err = decodeAndMapFrameSmg(self, frame)) != MPS_OK) goto bail; + + if (self->arbitraryDownmix != 0) { + if ((err = decodeAndMapFrameArbdmx(self, frame)) != MPS_OK) goto bail; + } + + if (self->extendFrame) { + frame->numParameterSets = + fixMin(MAX_PARAMETER_SETS, frame->numParameterSets + 1); + frame->paramSlot[frame->numParameterSets - 1] = self->timeSlots - 1; + + for (int p = 0; p < frame->numParameterSets; p++) { + if (frame->paramSlot[p] > self->timeSlots - 1) { + frame->paramSlot[p] = self->timeSlots - 1; + err = MPS_PARSE_ERROR; + } + } + if (err != MPS_OK) { + goto bail; + } + } + +bail: + return err; +} /* SpatialDecDecodeFrame() */ + +/******************************************************************************* + Functionname: SpatialDecodeHeader + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ + +SACDEC_ERROR SpatialDecDecodeHeader( + spatialDec *self, SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig) { + SACDEC_ERROR err = MPS_OK; + int i; + + self->samplingFreq = pSpatialSpecificConfig->samplingFreq; + self->timeSlots = pSpatialSpecificConfig->nTimeSlots; + self->frameLength = self->timeSlots * self->qmfBands; + self->bitstreamParameterBands = pSpatialSpecificConfig->freqRes; + + if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) + self->hybridBands = self->qmfBands; + else + self->hybridBands = SacGetHybridSubbands(self->qmfBands); + self->tp_hybBandBorder = 12; + + self->numParameterBands = self->bitstreamParameterBands; + + if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) { + switch (self->numParameterBands) { + case 4: + self->kernels = kernels_4_to_64; + break; + case 5: + self->kernels = kernels_5_to_64; + break; + case 7: + self->kernels = kernels_7_to_64; + break; + case 9: + self->kernels = kernels_9_to_64; + break; + case 12: + self->kernels = kernels_12_to_64; + break; + case 15: + self->kernels = kernels_15_to_64; + break; + case 23: + self->kernels = kernels_23_to_64; + break; + default: + return MPS_INVALID_PARAMETERBANDS; /* unsupported numParameterBands */ + } + } else { + switch (self->numParameterBands) { + case 4: + self->kernels = kernels_4_to_71; + break; + case 5: + self->kernels = kernels_5_to_71; + break; + case 7: + self->kernels = kernels_7_to_71; + break; + case 10: + self->kernels = kernels_10_to_71; + break; + case 14: + self->kernels = kernels_14_to_71; + break; + case 20: + self->kernels = kernels_20_to_71; + break; + case 28: + self->kernels = kernels_28_to_71; + break; + default: + return MPS_INVALID_PARAMETERBANDS; /* unsupported numParameterBands */ + } + } + + /* create param to hyb band table */ + FDKmemclear(self->param2hyb, (MAX_PARAMETER_BANDS + 1) * sizeof(int)); + for (i = 0; i < self->hybridBands; i++) { + self->param2hyb[self->kernels[i] + 1] = i + 1; + } + { + int pb = self->kernels[i - 1] + 2; + for (; pb < (MAX_PARAMETER_BANDS + 1); pb++) { + self->param2hyb[pb] = i; + } + for (pb = 0; pb < MAX_PARAMETER_BANDS; pb += 1) { + self->kernels_width[pb] = self->param2hyb[pb + 1] - self->param2hyb[pb]; + } + } + + self->treeConfig = pSpatialSpecificConfig->treeConfig; + + self->numOttBoxes = pSpatialSpecificConfig->nOttBoxes; + + self->numInputChannels = pSpatialSpecificConfig->nInputChannels; + + self->numOutputChannels = pSpatialSpecificConfig->nOutputChannels; + + self->quantMode = pSpatialSpecificConfig->quantMode; + + self->arbitraryDownmix = pSpatialSpecificConfig->bArbitraryDownmix; + + self->numM2rows = self->numOutputChannels; + + { + self->residualCoding = 0; + if (self->arbitraryDownmix == 2) + self->arbitraryDownmix = 1; /* no arbitrary downmix residuals */ + } + if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC)) { + self->residualCoding = pSpatialSpecificConfig->bResidualCoding; + } + + self->clipProtectGain__FDK = + FX_CFG2FX_DBL(clipGainTable__FDK[pSpatialSpecificConfig->bsFixedGainDMX]); + self->clipProtectGainSF__FDK = + clipGainSFTable__FDK[pSpatialSpecificConfig->bsFixedGainDMX]; + + self->tempShapeConfig = pSpatialSpecificConfig->tempShapeConfig; + + self->decorrConfig = pSpatialSpecificConfig->decorrConfig; + + if (self->upmixType == UPMIXTYPE_BYPASS) { + self->numOutputChannels = self->numInputChannels; + } + + self->numOutputChannelsAT = self->numOutputChannels; + + self->numOttBandsIPD = pSpatialSpecificConfig->numOttBandsIPD; + self->phaseCoding = pSpatialSpecificConfig->bsPhaseCoding; + for (i = 0; i < self->numOttBoxes; i++) { + { + self->pConfigCurrent->bitstreamOttBands[i] = + self->bitstreamParameterBands; + } + self->numOttBands[i] = self->pConfigCurrent->bitstreamOttBands[i]; + } /* i */ + + if (self->residualCoding) { + int numBoxes = self->numOttBoxes; + for (i = 0; i < numBoxes; i++) { + self->residualPresent[i] = + pSpatialSpecificConfig->ResidualConfig[i].bResidualPresent; + + if (self->residualPresent[i]) { + self->residualBands[i] = + pSpatialSpecificConfig->ResidualConfig[i].nResidualBands; + /* conversion from hybrid bands to qmf bands */ + self->residualQMFBands[i] = + fMax(self->param2hyb[self->residualBands[i]] + 3 - 10, + 3); /* simplification for the lowest 10 hybrid bands */ + } else { + self->residualBands[i] = 0; + self->residualQMFBands[i] = 0; + } + } + } /* self->residualCoding */ + else { + int boxes = self->numOttBoxes; + for (i = 0; i < boxes; i += 1) { + self->residualPresent[i] = 0; + self->residualBands[i] = 0; + } + } + + switch (self->treeConfig) { + case TREE_212: + self->numDirektSignals = 1; + self->numDecorSignals = 1; + self->numXChannels = 1; + if (self->arbitraryDownmix == 2) { + self->numXChannels += 1; + } + self->numVChannels = self->numDirektSignals + self->numDecorSignals; + break; + default: + return MPS_INVALID_TREECONFIG; + } + + self->highRateMode = pSpatialSpecificConfig->bsHighRateMode; + self->decorrType = pSpatialSpecificConfig->bsDecorrType; + + SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, UPMIXTYPE_NORMAL); + + return err; +} + +/******************************************************************************* + Functionname: SpatialDecCreateBsFrame + ******************************************************************************* + + Description: Create spatial bitstream structure + + Arguments: spatialDec* self + const SPATIAL_BS_FRAME **bsFrame + + Return: - + +*******************************************************************************/ +SACDEC_ERROR SpatialDecCreateBsFrame(SPATIAL_BS_FRAME *bsFrame, + BS_LL_STATE *llState) { + SPATIAL_BS_FRAME *pBs = bsFrame; + + const int maxNumOtt = MAX_NUM_OTT; + const int maxNumInputChannels = MAX_INPUT_CHANNELS; + + FDK_ALLOCATE_MEMORY_1D_P( + pBs->cmpOttIPDidx, maxNumOtt * MAX_PARAMETER_SETS * MAX_PARAMETER_BANDS, + SCHAR, SCHAR(*)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]) + + /* Arbitrary Downmix */ + FDK_ALLOCATE_MEMORY_1D_P( + pBs->cmpArbdmxGainIdx, + maxNumInputChannels * MAX_PARAMETER_SETS * MAX_PARAMETER_BANDS, SCHAR, + SCHAR(*)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]) + + /* Lossless control */ + FDK_ALLOCATE_MEMORY_1D(pBs->CLDLosslessData, MAX_NUM_PARAMETERS, LOSSLESSDATA) + FDK_ALLOCATE_MEMORY_1D(pBs->ICCLosslessData, MAX_NUM_PARAMETERS, LOSSLESSDATA) + + FDK_ALLOCATE_MEMORY_1D(pBs->IPDLosslessData, MAX_NUM_PARAMETERS, LOSSLESSDATA) + + pBs->newBsData = 0; + pBs->numParameterSets = 1; + + /* Link lossless states */ + for (int x = 0; x < MAX_NUM_PARAMETERS; x++) { + pBs->CLDLosslessData[x].state = &llState->CLDLosslessState[x]; + pBs->ICCLosslessData[x].state = &llState->ICCLosslessState[x]; + + pBs->IPDLosslessData[x].state = &llState->IPDLosslessState[x]; + } + + return MPS_OK; + +bail: + return MPS_OUTOFMEMORY; +} + +/******************************************************************************* + Functionname: SpatialDecCloseBsFrame + ******************************************************************************* + + Description: Close spatial bitstream structure + + Arguments: spatialDec* self + + Return: - + +*******************************************************************************/ +void SpatialDecCloseBsFrame(SPATIAL_BS_FRAME *pBs) { + if (pBs != NULL) { + /* These arrays contain the compact indices, only one value per pbstride, + * only paramsets actually containing data. */ + + FDK_FREE_MEMORY_1D(pBs->cmpOttIPDidx); + + /* Arbitrary Downmix */ + FDK_FREE_MEMORY_1D(pBs->cmpArbdmxGainIdx); + + /* Lossless control */ + FDK_FREE_MEMORY_1D(pBs->IPDLosslessData); + FDK_FREE_MEMORY_1D(pBs->CLDLosslessData); + FDK_FREE_MEMORY_1D(pBs->ICCLosslessData); + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_bitdec.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_bitdec.h new file mode 100644 index 0000000000000..cb0c7d2cec88b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_bitdec.h @@ -0,0 +1,161 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec bitstream decoder + +*******************************************************************************/ + +/*! + \file + \brief Spatial Audio bitstream decoder +*/ + +#ifndef SAC_BITDEC_H +#define SAC_BITDEC_H + +#include "sac_dec.h" + +typedef struct { + SCHAR numInputChannels; + SCHAR numOutputChannels; + SCHAR numOttBoxes; + SCHAR numTttBoxes; + SCHAR ottModeLfe[MAX_NUM_OTT]; +} TREEPROPERTIES; + +enum { TREE_212 = 7, TREE_DUMMY = 255 }; + +enum { QUANT_FINE = 0, QUANT_EBQ1 = 1, QUANT_EBQ2 = 2 }; + +SACDEC_ERROR SpatialDecParseSpecificConfigHeader( + HANDLE_FDK_BITSTREAM bitstream, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + AUDIO_OBJECT_TYPE coreCodec, SPATIAL_DEC_UPMIX_TYPE upmixType); + +SACDEC_ERROR SpatialDecParseMps212Config( + HANDLE_FDK_BITSTREAM bitstream, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int samplingRate, + AUDIO_OBJECT_TYPE coreCodec, INT stereoConfigIndex, + INT coreSbrFrameLengthIndex); + +SACDEC_ERROR SpatialDecParseSpecificConfig( + HANDLE_FDK_BITSTREAM bitstream, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int sacHeaderLen, + AUDIO_OBJECT_TYPE coreCodec); + +int SpatialDecDefaultSpecificConfig( + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + AUDIO_OBJECT_TYPE coreCodec, int samplingFreq, int nTimeSlots, + int sacDecoderLevel, int isBlind, int coreChannels); + +SACDEC_ERROR SpatialDecCreateBsFrame(SPATIAL_BS_FRAME *bsFrame, + BS_LL_STATE *llState); + +void SpatialDecCloseBsFrame(SPATIAL_BS_FRAME *bsFrame); + +SACDEC_ERROR SpatialDecParseFrameData( + spatialDec *self, SPATIAL_BS_FRAME *frame, HANDLE_FDK_BITSTREAM bitstream, + const SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, UPMIXTYPE upmixType, + int fGlobalIndependencyFlag); + +SACDEC_ERROR SpatialDecDecodeFrame(spatialDec *self, SPATIAL_BS_FRAME *frame); + +SACDEC_ERROR SpatialDecDecodeHeader( + spatialDec *self, SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_calcM1andM2.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_calcM1andM2.cpp new file mode 100644 index 0000000000000..5826275d47b36 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_calcM1andM2.cpp @@ -0,0 +1,774 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec M1 and M2 calculation + +*******************************************************************************/ + +#include "sac_calcM1andM2.h" +#include "sac_bitdec.h" +#include "sac_process.h" +#include "sac_rom.h" +#include "sac_smoothing.h" +#include "FDK_trigFcts.h" + +/* assorted definitions and constants */ + +#define ABS_THR2 1.0e-9 +#define SQRT2_FDK \ + ((FIXP_DBL)FL2FXCONST_DBL(0.70710678118f)) /* FDKsqrt(2.0) scaled by 0.5 */ + +static void param2UMX_PS__FDK(spatialDec* self, + FIXP_DBL H11[MAX_PARAMETER_BANDS], + FIXP_DBL H12[MAX_PARAMETER_BANDS], + FIXP_DBL H21[MAX_PARAMETER_BANDS], + FIXP_DBL H22[MAX_PARAMETER_BANDS], + FIXP_DBL c_l[MAX_PARAMETER_BANDS], + FIXP_DBL c_r[MAX_PARAMETER_BANDS], int ottBoxIndx, + int parameterSetIndx, int resBands); + +static void param2UMX_PS_Core__FDK( + const SCHAR cld[MAX_PARAMETER_BANDS], const SCHAR icc[MAX_PARAMETER_BANDS], + const int numOttBands, const int resBands, + FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS], + FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS], + FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS]); + +static void param2UMX_PS_IPD_OPD__FDK( + spatialDec* self, const SPATIAL_BS_FRAME* frame, + FIXP_DBL H11re[MAX_PARAMETER_BANDS], FIXP_DBL H12re[MAX_PARAMETER_BANDS], + FIXP_DBL H21re[MAX_PARAMETER_BANDS], FIXP_DBL H22re[MAX_PARAMETER_BANDS], + FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS], + int ottBoxIndx, int parameterSetIndx, int residualBands); + +static void param2UMX_Prediction__FDK( + spatialDec* self, FIXP_DBL H11re[MAX_PARAMETER_BANDS], + FIXP_DBL H11im[MAX_PARAMETER_BANDS], FIXP_DBL H12re[MAX_PARAMETER_BANDS], + FIXP_DBL H12im[MAX_PARAMETER_BANDS], FIXP_DBL H21re[MAX_PARAMETER_BANDS], + FIXP_DBL H21im[MAX_PARAMETER_BANDS], FIXP_DBL H22re[MAX_PARAMETER_BANDS], + FIXP_DBL H22im[MAX_PARAMETER_BANDS], int ottBoxIndx, int parameterSetIndx, + int resBands); + +/* static void SpatialDecCalculateM0(spatialDec* self,int ps); */ +static SACDEC_ERROR SpatialDecCalculateM1andM2_212( + spatialDec* self, int ps, const SPATIAL_BS_FRAME* frame); + +/******************************************************************************* + Functionname: SpatialDecGetResidualIndex + ******************************************************************************* + + Description: + + Arguments: + + Input: + + Output: + +*******************************************************************************/ +int SpatialDecGetResidualIndex(spatialDec* self, int row) { + return row2residual[self->treeConfig][row]; +} + +/******************************************************************************* + Functionname: UpdateAlpha + ******************************************************************************* + + Description: + + Arguments: + + Input: + + Output: + +*******************************************************************************/ +static void updateAlpha(spatialDec* self) { + int nChIn = self->numInputChannels; + int ch; + + for (ch = 0; ch < nChIn; ch++) { + FIXP_DBL alpha = /* FL2FXCONST_DBL(1.0f) */ (FIXP_DBL)MAXVAL_DBL; + + self->arbdmxAlphaPrev__FDK[ch] = self->arbdmxAlpha__FDK[ch]; + + self->arbdmxAlpha__FDK[ch] = alpha; + } +} + +/******************************************************************************* + Functionname: SpatialDecCalculateM1andM2 + ******************************************************************************* + Description: + Arguments: +*******************************************************************************/ +SACDEC_ERROR SpatialDecCalculateM1andM2(spatialDec* self, int ps, + const SPATIAL_BS_FRAME* frame) { + SACDEC_ERROR err = MPS_OK; + + if ((self->arbitraryDownmix != 0) && (ps == 0)) { + updateAlpha(self); + } + + self->pActivM2ParamBands = NULL; + + switch (self->upmixType) { + case UPMIXTYPE_BYPASS: + case UPMIXTYPE_NORMAL: + switch (self->treeConfig) { + case TREE_212: + err = SpatialDecCalculateM1andM2_212(self, ps, frame); + break; + default: + err = MPS_WRONG_TREECONFIG; + }; + break; + + default: + err = MPS_WRONG_TREECONFIG; + } + + if (err != MPS_OK) { + goto bail; + } + +bail: + return err; +} + +/******************************************************************************* + Functionname: SpatialDecCalculateM1andM2_212 + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static SACDEC_ERROR SpatialDecCalculateM1andM2_212( + spatialDec* self, int ps, const SPATIAL_BS_FRAME* frame) { + SACDEC_ERROR err = MPS_OK; + int pb; + + FIXP_DBL H11re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)}; + FIXP_DBL H12re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)}; + FIXP_DBL H21re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)}; + FIXP_DBL H22re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)}; + FIXP_DBL H11im[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)}; + FIXP_DBL H21im[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)}; + + INT phaseCoding = self->phaseCoding; + + switch (phaseCoding) { + case 1: + /* phase coding: yes; residuals: no */ + param2UMX_PS_IPD_OPD__FDK(self, frame, H11re, H12re, H21re, H22re, NULL, + NULL, 0, ps, self->residualBands[0]); + break; + case 3: + /* phase coding: yes; residuals: yes */ + param2UMX_Prediction__FDK(self, H11re, H11im, H12re, NULL, H21re, H21im, + H22re, NULL, 0, ps, self->residualBands[0]); + break; + default: + if (self->residualCoding) { + /* phase coding: no; residuals: yes */ + param2UMX_Prediction__FDK(self, H11re, NULL, H12re, NULL, H21re, NULL, + H22re, NULL, 0, ps, self->residualBands[0]); + } else { + /* phase coding: no; residuals: no */ + param2UMX_PS__FDK(self, H11re, H12re, H21re, H22re, NULL, NULL, 0, ps, + 0); + } + break; + } + + for (pb = 0; pb < self->numParameterBands; pb++) { + self->M2Real__FDK[0][0][pb] = (H11re[pb]); + self->M2Real__FDK[0][1][pb] = (H12re[pb]); + + self->M2Real__FDK[1][0][pb] = (H21re[pb]); + self->M2Real__FDK[1][1][pb] = (H22re[pb]); + } + if (phaseCoding == 3) { + for (pb = 0; pb < self->numParameterBands; pb++) { + self->M2Imag__FDK[0][0][pb] = (H11im[pb]); + self->M2Imag__FDK[1][0][pb] = (H21im[pb]); + self->M2Imag__FDK[0][1][pb] = (FIXP_DBL)0; // H12im[pb]; + self->M2Imag__FDK[1][1][pb] = (FIXP_DBL)0; // H22im[pb]; + } + } + + if (self->phaseCoding == 1) { + SpatialDecSmoothOPD( + self, frame, + ps); /* INPUT: PhaseLeft, PhaseRight, (opdLeftState, opdRightState) */ + } + + return err; +} + +/******************************************************************************* + Functionname: param2UMX_PS_Core + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static void param2UMX_PS_Core__FDK( + const SCHAR cld[MAX_PARAMETER_BANDS], const SCHAR icc[MAX_PARAMETER_BANDS], + const int numOttBands, const int resBands, + FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS], + FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS], + FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS]) { + int band; + + if ((c_l != NULL) && (c_r != NULL)) { + for (band = 0; band < numOttBands; band++) { + SpatialDequantGetCLDValues(cld[band], &c_l[band], &c_r[band]); + } + } + + band = 0; + FDK_ASSERT(resBands == 0); + for (; band < numOttBands; band++) { + /* compute mixing variables: */ + const int idx1 = cld[band]; + const int idx2 = icc[band]; + H11[band] = FX_CFG2FX_DBL(H11_nc[idx1][idx2]); + H21[band] = FX_CFG2FX_DBL(H11_nc[30 - idx1][idx2]); + H12[band] = FX_CFG2FX_DBL(H12_nc[idx1][idx2]); + H22[band] = FX_CFG2FX_DBL(-H12_nc[30 - idx1][idx2]); + } +} + +/******************************************************************************* + Functionname: param2UMX_PS + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static void param2UMX_PS__FDK(spatialDec* self, + FIXP_DBL H11[MAX_PARAMETER_BANDS], + FIXP_DBL H12[MAX_PARAMETER_BANDS], + FIXP_DBL H21[MAX_PARAMETER_BANDS], + FIXP_DBL H22[MAX_PARAMETER_BANDS], + FIXP_DBL c_l[MAX_PARAMETER_BANDS], + FIXP_DBL c_r[MAX_PARAMETER_BANDS], int ottBoxIndx, + int parameterSetIndx, int residualBands) { + int band; + param2UMX_PS_Core__FDK(self->ottCLD__FDK[ottBoxIndx][parameterSetIndx], + self->ottICC__FDK[ottBoxIndx][parameterSetIndx], + self->numOttBands[ottBoxIndx], residualBands, H11, H12, + H21, H22, c_l, c_r); + + for (band = self->numOttBands[ottBoxIndx]; band < self->numParameterBands; + band++) { + H11[band] = H21[band] = H12[band] = H22[band] = FL2FXCONST_DBL(0.f); + } +} + +#define N_CLD (31) +#define N_IPD (16) + +static const FIXP_DBL sinIpd_tab[N_IPD] = { + FIXP_DBL(0x00000000), FIXP_DBL(0x30fbc54e), FIXP_DBL(0x5a827999), + FIXP_DBL(0x7641af3d), FIXP_DBL(0x7fffffff), FIXP_DBL(0x7641af3d), + FIXP_DBL(0x5a82799a), FIXP_DBL(0x30fbc54d), FIXP_DBL(0xffffffff), + FIXP_DBL(0xcf043ab3), FIXP_DBL(0xa57d8666), FIXP_DBL(0x89be50c3), + FIXP_DBL(0x80000000), FIXP_DBL(0x89be50c3), FIXP_DBL(0xa57d8666), + FIXP_DBL(0xcf043ab2), +}; + +/* cosIpd[i] = sinIpd[(i+4)&15] */ +#define SIN_IPD(a) (sinIpd_tab[(a)]) +#define COS_IPD(a) (sinIpd_tab[((a) + 4) & 15]) //(cosIpd_tab[(a)]) + +static const FIXP_SGL sqrt_one_minus_ICC2[8] = { + FL2FXCONST_SGL(0.0f), + FL2FXCONST_SGL(0.349329357483736f), + FL2FXCONST_SGL(0.540755219669676f), + FL2FXCONST_SGL(0.799309172723546f), + FL2FXCONST_SGL(0.929968187843004f), + FX_DBL2FXCONST_SGL(MAXVAL_DBL), + FL2FXCONST_SGL(0.80813303360276f), + FL2FXCONST_SGL(0.141067359796659f), +}; + +/* exponent of sqrt(CLD) */ +static const SCHAR sqrt_CLD_e[N_CLD] = { + -24, -7, -6, -5, -4, -4, -3, -3, -2, -2, -1, -1, 0, 0, 0, 1, + 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 25}; + +static const FIXP_DBL sqrt_CLD_m[N_CLD] = { + FL2FXCONST_DBL(0.530542153566195f), + FL2FXCONST_DBL(0.719796896243647f), + FL2FXCONST_DBL(0.64f), + FL2FXCONST_DBL(0.569049411212455f), + FL2FXCONST_DBL(0.505964425626941f), + FL2FXCONST_DBL(0.899746120304559f), + FL2FXCONST_DBL(0.635462587779425f), + FL2FXCONST_DBL(0.897614763441571f), + FL2FXCONST_DBL(0.633957276984445f), + FL2FXCONST_DBL(0.895488455427336f), + FL2FXCONST_DBL(0.632455532033676f), + FL2FXCONST_DBL(0.796214341106995f), + FL2FXCONST_DBL(0.501187233627272f), + FL2FXCONST_DBL(0.630957344480193f), + FL2FXCONST_DBL(0.794328234724281f), + FL2FXCONST_DBL(0.5f), + FL2FXCONST_DBL(0.629462705897084f), + FL2FXCONST_DBL(0.792446596230557f), + FL2FXCONST_DBL(0.99763115748444f), + FL2FXCONST_DBL(0.627971607877395f), + FL2FXCONST_DBL(0.790569415042095f), + FL2FXCONST_DBL(0.558354490188704f), + FL2FXCONST_DBL(0.788696680600242f), + FL2FXCONST_DBL(0.557031836333591f), + FL2FXCONST_DBL(0.786828382371355f), + FL2FXCONST_DBL(0.555712315637163f), + FL2FXCONST_DBL(0.988211768802619f), + FL2FXCONST_DBL(0.87865832060992f), + FL2FXCONST_DBL(0.78125f), + FL2FXCONST_DBL(0.694640394546454f), + FL2FXCONST_DBL(0.942432183077448f), +}; + +static const FIXP_DBL CLD_m[N_CLD] = { + FL2FXCONST_DBL(0.281474976710656f), + FL2FXCONST_DBL(0.518107571841987f), + FL2FXCONST_DBL(0.4096f), + FL2FXCONST_DBL(0.323817232401242f), + FL2FXCONST_DBL(0.256f), + FL2FXCONST_DBL(0.809543081003105f), + FL2FXCONST_DBL(0.403812700467324f), + FL2FXCONST_DBL(0.805712263548267f), + FL2FXCONST_DBL(0.401901829041533f), + FL2FXCONST_DBL(0.801899573803636f), + FL2FXCONST_DBL(0.4f), + FL2FXCONST_DBL(0.633957276984445f), + FL2FXCONST_DBL(0.251188643150958f), + FL2FXCONST_DBL(0.398107170553497f), + FL2FXCONST_DBL(0.630957344480193f), + FL2FXCONST_DBL(0.25f), + FL2FXCONST_DBL(0.396223298115278f), + FL2FXCONST_DBL(0.627971607877395f), + FL2FXCONST_DBL(0.995267926383743f), + FL2FXCONST_DBL(0.394348340300121f), + FL2FXCONST_DBL(0.625f), + FL2FXCONST_DBL(0.311759736713887f), + FL2FXCONST_DBL(0.62204245398984f), + FL2FXCONST_DBL(0.310284466689172f), + FL2FXCONST_DBL(0.619098903305123f), + FL2FXCONST_DBL(0.308816177750818f), + FL2FXCONST_DBL(0.9765625f), + FL2FXCONST_DBL(0.772040444377046f), + FL2FXCONST_DBL(0.6103515625f), + FL2FXCONST_DBL(0.482525277735654f), + FL2FXCONST_DBL(0.888178419700125), +}; + +static void calculateOpd(spatialDec* self, INT ottBoxIndx, INT parameterSetIndx, + FIXP_DBL opd[MAX_PARAMETER_BANDS]) { + INT band; + + for (band = 0; band < self->numOttBandsIPD; band++) { + INT idxCld = self->ottCLD__FDK[ottBoxIndx][parameterSetIndx][band]; + INT idxIpd = self->ottIPD__FDK[ottBoxIndx][parameterSetIndx][band]; + INT idxIcc = self->ottICC__FDK[ottBoxIndx][parameterSetIndx][band]; + FIXP_DBL cld, ipd; + + ipd = FX_CFG2FX_DBL(dequantIPD__FDK[idxIpd]); + + SpatialDequantGetCLD2Values(idxCld, &cld); + + /* ipd(idxIpd==8) == PI */ + if (((cld == FL2FXCONST_DBL(0.0f)) && (idxIpd == 8)) || (idxIpd == 0)) { + opd[2 * band] = FL2FXCONST_DBL(0.0f); + } else { + FDK_ASSERT(idxIpd > 0); + opd[2 * band] = + dequantIPD_CLD_ICC_splitAngle__FDK[idxIpd - 1][idxCld][idxIcc]; + } + opd[2 * band + 1] = opd[2 * band] - ipd; + } +} + +/* wrap phase in rad to the range of 0 <= x < 2*pi */ +static FIXP_DBL wrapPhase(FIXP_DBL phase) { + while (phase < (FIXP_DBL)0) phase += PIx2__IPD; + while (phase >= PIx2__IPD) phase -= PIx2__IPD; + FDK_ASSERT((phase >= (FIXP_DBL)0) && (phase < PIx2__IPD)); + + return phase; +} + +/******************************************************************************* + Functionname: param2UMX_PS_IPD + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static void param2UMX_PS_IPD_OPD__FDK( + spatialDec* self, const SPATIAL_BS_FRAME* frame, + FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS], + FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS], + FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS], + int ottBoxIndx, int parameterSetIndx, int residualBands) { + INT band; + FIXP_DBL opd[2 * MAX_PARAMETER_BANDS]; + INT numOttBands = self->numOttBands[ottBoxIndx]; + INT numIpdBands; + + numIpdBands = frame->phaseMode ? self->numOttBandsIPD : 0; + + FDK_ASSERT(self->residualCoding == 0); + + param2UMX_PS_Core__FDK(self->ottCLD__FDK[ottBoxIndx][parameterSetIndx], + self->ottICC__FDK[ottBoxIndx][parameterSetIndx], + self->numOttBands[ottBoxIndx], residualBands, H11, H12, + H21, H22, c_l, c_r); + + for (band = self->numOttBands[ottBoxIndx]; band < self->numParameterBands; + band++) { + H11[band] = H21[band] = H12[band] = H22[band] = FL2FXCONST_DBL(0.f); + } + + if (frame->phaseMode) { + calculateOpd(self, ottBoxIndx, parameterSetIndx, opd); + + for (band = 0; band < numIpdBands; band++) { + self->PhaseLeft__FDK[band] = wrapPhase(opd[2 * band]); + self->PhaseRight__FDK[band] = wrapPhase(opd[2 * band + 1]); + } + } + + for (band = numIpdBands; band < numOttBands; band++) { + self->PhaseLeft__FDK[band] = FL2FXCONST_DBL(0.0f); + self->PhaseRight__FDK[band] = FL2FXCONST_DBL(0.0f); + } +} + +FDK_INLINE void param2UMX_Prediction_Core__FDK( + FIXP_DBL* H11re, FIXP_DBL* H11im, FIXP_DBL* H12re, FIXP_DBL* H12im, + FIXP_DBL* H21re, FIXP_DBL* H21im, FIXP_DBL* H22re, FIXP_DBL* H22im, + int cldIdx, int iccIdx, int ipdIdx, int band, int numOttBandsIPD, + int resBands) { +#define MAX_WEIGHT (1.2f) + FDK_ASSERT((H12im == NULL) && (H22im == NULL)); /* always == 0 */ + + if ((band < numOttBandsIPD) && (cldIdx == 15) && (iccIdx == 0) && + (ipdIdx == 8)) { + const FIXP_DBL gain = + FL2FXCONST_DBL(0.5f / MAX_WEIGHT) >> SCALE_PARAM_M2_212_PRED; + + *H11re = gain; + if (band < resBands) { + *H21re = gain; + *H12re = gain; + *H22re = -gain; + } else { + *H21re = -gain; + *H12re = (FIXP_DBL)0; + *H22re = (FIXP_DBL)0; + } + if ((H11im != NULL) && + (H21im != NULL) /*&& (H12im!=NULL) && (H22im!=NULL)*/) { + *H11im = (FIXP_DBL)0; + *H21im = (FIXP_DBL)0; + /* *H12im = (FIXP_DBL)0; */ + /* *H22im = (FIXP_DBL)0; */ + } + } else { + const FIXP_DBL one_m = (FIXP_DBL)MAXVAL_DBL; + const int one_e = 0; + /* iidLin = sqrt(cld); */ + FIXP_DBL iidLin_m = sqrt_CLD_m[cldIdx]; + int iidLin_e = sqrt_CLD_e[cldIdx]; + /* iidLin2 = cld; */ + FIXP_DBL iidLin2_m = CLD_m[cldIdx]; + int iidLin2_e = sqrt_CLD_e[cldIdx] << 1; + /* iidLin21 = iidLin2 + 1.0f; */ + int iidLin21_e; + FIXP_DBL iidLin21_m = + fAddNorm(iidLin2_m, iidLin2_e, one_m, one_e, &iidLin21_e); + /* iidIcc2 = iidLin * icc * 2.0f; */ + FIXP_CFG icc = dequantICC__FDK[iccIdx]; + int iidIcc2_e = iidLin_e + 1; + FIXP_DBL iidIcc2_m = fMult(iidLin_m, icc); + FIXP_DBL temp_m, sqrt_temp_m, inv_temp_m, weight_m; + int temp_e, sqrt_temp_e, inv_temp_e, weight_e, scale; + FIXP_DBL cosIpd, sinIpd; + + cosIpd = COS_IPD((band < numOttBandsIPD) ? ipdIdx : 0); + sinIpd = SIN_IPD((band < numOttBandsIPD) ? ipdIdx : 0); + + /* temp = iidLin21 + iidIcc2 * cosIpd; */ + temp_m = fAddNorm(iidLin21_m, iidLin21_e, fMult(iidIcc2_m, cosIpd), + iidIcc2_e, &temp_e); + + /* calculate 1/temp needed later */ + inv_temp_e = temp_e; + inv_temp_m = invFixp(temp_m, &inv_temp_e); + + /* 1/weight = sqrt(temp) * 1/sqrt(iidLin21) */ + if (temp_e & 1) { + sqrt_temp_m = temp_m >> 1; + sqrt_temp_e = (temp_e + 1) >> 1; + } else { + sqrt_temp_m = temp_m; + sqrt_temp_e = temp_e >> 1; + } + sqrt_temp_m = sqrtFixp(sqrt_temp_m); + if (iidLin21_e & 1) { + iidLin21_e += 1; + iidLin21_m >>= 1; + } + /* weight_[m,e] is actually 1/weight in the next few lines */ + weight_m = invSqrtNorm2(iidLin21_m, &weight_e); + weight_e -= iidLin21_e >> 1; + weight_m = fMult(sqrt_temp_m, weight_m); + weight_e += sqrt_temp_e; + scale = fNorm(weight_m); + weight_m = scaleValue(weight_m, scale); + weight_e -= scale; + /* weight = 0.5 * max(1/weight, 1/maxWeight) */ + if ((weight_e < 0) || + ((weight_e == 0) && (weight_m < FL2FXCONST_DBL(1.f / MAX_WEIGHT)))) { + weight_m = FL2FXCONST_DBL(1.f / MAX_WEIGHT); + weight_e = 0; + } + weight_e -= 1; + + { + FIXP_DBL alphaRe_m, alphaIm_m, accu_m; + int alphaRe_e, alphaIm_e, accu_e; + /* alphaRe = (1.0f - iidLin2) / temp; */ + alphaRe_m = fAddNorm(one_m, one_e, -iidLin2_m, iidLin2_e, &alphaRe_e); + alphaRe_m = fMult(alphaRe_m, inv_temp_m); + alphaRe_e += inv_temp_e; + + /* H11re = weight - alphaRe * weight; */ + /* H21re = weight + alphaRe * weight; */ + accu_m = fMult(alphaRe_m, weight_m); + accu_e = alphaRe_e + weight_e; + { + int accu2_e; + FIXP_DBL accu2_m; + accu2_m = fAddNorm(weight_m, weight_e, -accu_m, accu_e, &accu2_e); + *H11re = scaleValue(accu2_m, accu2_e - SCALE_PARAM_M2_212_PRED); + accu2_m = fAddNorm(weight_m, weight_e, accu_m, accu_e, &accu2_e); + *H21re = scaleValue(accu2_m, accu2_e - SCALE_PARAM_M2_212_PRED); + } + + if ((H11im != NULL) && + (H21im != NULL) /*&& (H12im != NULL) && (H22im != NULL)*/) { + /* alphaIm = -iidIcc2 * sinIpd / temp; */ + alphaIm_m = fMult(-iidIcc2_m, sinIpd); + alphaIm_m = fMult(alphaIm_m, inv_temp_m); + alphaIm_e = iidIcc2_e + inv_temp_e; + /* H11im = -alphaIm * weight; */ + /* H21im = alphaIm * weight; */ + accu_m = fMult(alphaIm_m, weight_m); + accu_e = alphaIm_e + weight_e; + accu_m = scaleValue(accu_m, accu_e - SCALE_PARAM_M2_212_PRED); + *H11im = -accu_m; + *H21im = accu_m; + + /* *H12im = (FIXP_DBL)0; */ + /* *H22im = (FIXP_DBL)0; */ + } + } + if (band < resBands) { + FIXP_DBL weight = + scaleValue(weight_m, weight_e - SCALE_PARAM_M2_212_PRED); + *H12re = weight; + *H22re = -weight; + } else { + /* beta = 2.0f * iidLin * (float) sqrt(1.0f - icc * icc) * weight / temp; + */ + FIXP_DBL beta_m; + int beta_e; + beta_m = FX_SGL2FX_DBL(sqrt_one_minus_ICC2[iccIdx]); + beta_e = 1; /* multipication with 2.0f */ + beta_m = fMult(beta_m, weight_m); + beta_e += weight_e; + beta_m = fMult(beta_m, iidLin_m); + beta_e += iidLin_e; + beta_m = fMult(beta_m, inv_temp_m); + beta_e += inv_temp_e; + + beta_m = scaleValue(beta_m, beta_e - SCALE_PARAM_M2_212_PRED); + *H12re = beta_m; + *H22re = -beta_m; + } + } +} + +static void param2UMX_Prediction__FDK(spatialDec* self, FIXP_DBL* H11re, + FIXP_DBL* H11im, FIXP_DBL* H12re, + FIXP_DBL* H12im, FIXP_DBL* H21re, + FIXP_DBL* H21im, FIXP_DBL* H22re, + FIXP_DBL* H22im, int ottBoxIndx, + int parameterSetIndx, int resBands) { + int band; + FDK_ASSERT((H12im == NULL) && (H22im == NULL)); /* always == 0 */ + + for (band = 0; band < self->numParameterBands; band++) { + int cldIdx = self->ottCLD__FDK[ottBoxIndx][parameterSetIndx][band]; + int iccIdx = self->ottICC__FDK[ottBoxIndx][parameterSetIndx][band]; + int ipdIdx = self->ottIPD__FDK[ottBoxIndx][parameterSetIndx][band]; + + param2UMX_Prediction_Core__FDK( + &H11re[band], (H11im ? &H11im[band] : NULL), &H12re[band], NULL, + &H21re[band], (H21im ? &H21im[band] : NULL), &H22re[band], NULL, cldIdx, + iccIdx, ipdIdx, band, self->numOttBandsIPD, resBands); + } +} + +/******************************************************************************* + Functionname: initM1andM2 + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ + +SACDEC_ERROR initM1andM2(spatialDec* self, int initStatesFlag, + int configChanged) { + SACDEC_ERROR err = MPS_OK; + + self->bOverwriteM1M2prev = (configChanged && !initStatesFlag) ? 1 : 0; + + { self->numM2rows = self->numOutputChannels; } + + if (initStatesFlag) { + int i, j, k; + + for (i = 0; i < self->numM2rows; i++) { + for (j = 0; j < self->numVChannels; j++) { + for (k = 0; k < MAX_PARAMETER_BANDS; k++) { + self->M2Real__FDK[i][j][k] = FL2FXCONST_DBL(0); + self->M2RealPrev__FDK[i][j][k] = FL2FXCONST_DBL(0); + } + } + } + } + + return err; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_calcM1andM2.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_calcM1andM2.h new file mode 100644 index 0000000000000..cefc4bb6dd08b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_calcM1andM2.h @@ -0,0 +1,132 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec M1 and M2 calculation + +*******************************************************************************/ + +/* sa_calcM1andM2.h */ + +#ifndef SAC_CALCM1ANDM2_H +#define SAC_CALCM1ANDM2_H + +#include "sac_dec.h" + +#define SCALE_PARAM_M1 3 + +/* Scaling of M2 matrix, but only for binaural upmix type. */ +#define SCALE_PARAM_CALC_M2 (3) +#define SCALE_PARAM_M2_515X (3) +#define SCALE_PARAM_M2_525 (SCALE_PARAM_M1 + HRG_SF + 1 - SCALE_PARAM_CALC_M2) +#define SCALE_PARAM_M2_212_PRED (3) +/* Scaling of spectral data after applying M2 matrix, but only for binaural + upmix type Scaling is compensated later in synthesis qmf filterbank */ +#define SCALE_DATA_APPLY_M2 (1) +/* Applying M2 parameter in combination with phase coding needs 2 bits headroom + * because up to a maximum of 4 spectral values can be added for USAC */ +#define SCALE_DATA_APPLY_M2_PC (2) + +SACDEC_ERROR initM1andM2(spatialDec* self, int initStatesFlag, + int configChanged); + +int SpatialDecGetResidualIndex(spatialDec* self, int row); + +SACDEC_ERROR SpatialDecCalculateM1andM2(spatialDec* self, int ps, + const SPATIAL_BS_FRAME* frame); + +#endif /* SAC_CALCM1ANDM2_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec.cpp new file mode 100644 index 0000000000000..a26e2518f8f2f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec.cpp @@ -0,0 +1,1548 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Decoder Library + +*******************************************************************************/ + +#include "sac_dec_errorcodes.h" +#include "sac_dec.h" + +#include "sac_process.h" +#include "sac_bitdec.h" +#include "sac_smoothing.h" +#include "sac_calcM1andM2.h" +#include "sac_reshapeBBEnv.h" +#include "sac_stp.h" +#include "sac_rom.h" + +#include "FDK_decorrelate.h" + +#include "FDK_trigFcts.h" +#include "FDK_matrixCalloc.h" + +/* static int pbStrideTable[] = {1, 2, 5, 28}; see sac_rom.cpp */ + +enum { + APPLY_M2_NONE = 0, /* init value */ + APPLY_M2 = 1, /* apply m2 fallback implementation */ + APPLY_M2_MODE212 = 2, /* apply m2 for 212 mode */ + APPLY_M2_MODE212_Res_PhaseCoding = + 3 /* apply m2 for 212 mode with residuals and phase coding */ +}; + +/******************************************************************************************/ +/* function: FDK_SpatialDecInitDefaultSpatialSpecificConfig */ +/* output: struct of type SPATIAL_SPECIFIC_CONFIG */ +/* input: core coder audio object type */ +/* input: nr of core channels */ +/* input: sampling rate */ +/* input: nr of time slots */ +/* input: decoder level */ +/* input: flag indicating upmix type blind */ +/* */ +/* returns: error code */ +/******************************************************************************************/ +int FDK_SpatialDecInitDefaultSpatialSpecificConfig( + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + AUDIO_OBJECT_TYPE coreCodec, int coreChannels, int samplingFreq, + int nTimeSlots, int decoderLevel, int isBlind) { + return SpatialDecDefaultSpecificConfig(pSpatialSpecificConfig, coreCodec, + samplingFreq, nTimeSlots, decoderLevel, + isBlind, coreChannels); +} + +/******************************************************************************************/ +/* function: FDK_SpatialDecCompareSpatialSpecificConfigHeader */ +/* input: 2 pointers to a ssc */ +/* */ +/* output: - */ +/* returns: error code (0 = equal, <>0 unequal) */ +/******************************************************************************************/ +int FDK_SpatialDecCompareSpatialSpecificConfigHeader( + SPATIAL_SPECIFIC_CONFIG *pSsc1, SPATIAL_SPECIFIC_CONFIG *pSsc2) { + int result = MPS_OK; + + /* we assume: every bit must be equal */ + if (FDKmemcmp(pSsc1, pSsc2, sizeof(SPATIAL_SPECIFIC_CONFIG)) != 0) { + result = MPS_UNEQUAL_SSC; + } + return result; +} + +/******************************************************************************* + Functionname: SpatialDecClearFrameData + ******************************************************************************* + + Description: Clear/Fake frame data to avoid misconfiguration and allow proper + error concealment. + Arguments: + Input: self (frame data) + Output: No return value. + +*******************************************************************************/ +static void SpatialDecClearFrameData( + spatialDec *self, /* Shall be removed */ + SPATIAL_BS_FRAME *bsFrame, const SACDEC_CREATION_PARAMS *const setup) { + int i; + + FDK_ASSERT(self != NULL); + FDK_ASSERT(bsFrame != NULL); + FDK_ASSERT(setup != NULL); + + /* do not apply shaping tools (GES or STP) */ + for (i = 0; i < setup->maxNumOutputChannels; + i += 1) { /* MAX_OUTPUT_CHANNELS */ + bsFrame->tempShapeEnableChannelSTP[i] = 0; + bsFrame->tempShapeEnableChannelGES[i] = 0; + } + + bsFrame->TsdData->bsTsdEnable = 0; + + /* use only 1 parameter set at the end of the frame */ + bsFrame->numParameterSets = 1; + bsFrame->paramSlot[0] = self->timeSlots - 1; + + /* parameter smoothing tool set to off */ + bsFrame->bsSmoothMode[0] = 0; + initParameterSmoothing(self); + + /* reset residual data */ + { + int resQmfBands, resTimeSlots = (1); + + resQmfBands = setup->maxNumQmfBands; + + for (i = 0; i < setup->bProcResidual + ? fMin(setup->maxNumResChannels, + setup->maxNumOttBoxes + setup->maxNumInputChannels) + : 0; + i += 1) { + for (int j = 0; j < resTimeSlots; j += 1) { + for (int k = 0; k < resQmfBands; k += 1) { + self->qmfResidualReal__FDK[i][j][k] = FL2FXCONST_DBL(0.0f); + self->qmfResidualImag__FDK[i][j][k] = FL2FXCONST_DBL(0.0f); + } + } + } + } + + return; +} + +/******************************************************************************* + Functionname: FDK_SpatialDecOpen + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +spatialDec *FDK_SpatialDecOpen(const SPATIAL_DEC_CONFIG *config, + int stereoConfigIndex) { + int i; + int lfSize, hfSize; + spatialDec *self = NULL; + SACDEC_CREATION_PARAMS setup; + + switch (config->decoderLevel) { + case DECODER_LEVEL_0: /* 212 maxNumOutputChannels== 2 */ + setup.maxNumInputChannels = 1; + setup.maxNumOutputChannels = 2; + setup.maxNumQmfBands = 64; + setup.maxNumXChannels = 2; + setup.maxNumVChannels = 2; + setup.maxNumDecorChannels = 1; + setup.bProcResidual = 1; + setup.maxNumResidualChannels = 0; + setup.maxNumOttBoxes = 1; + setup.maxNumParams = setup.maxNumInputChannels + setup.maxNumOttBoxes; + break; + default: + return NULL; + } + + setup.maxNumResChannels = 1; + + { + switch (config->maxNumOutputChannels) { + case OUTPUT_CHANNELS_2_0: + setup.maxNumOutputChannels = fMin(setup.maxNumOutputChannels, 2); + break; + case OUTPUT_CHANNELS_DEFAULT: + default: + break; + } + } + + setup.maxNumHybridBands = SacGetHybridSubbands(setup.maxNumQmfBands); + + switch (config->decoderMode) { + case EXT_HQ_ONLY: + setup.maxNumCmplxQmfBands = setup.maxNumQmfBands; + setup.maxNumCmplxHybBands = setup.maxNumHybridBands; + break; + default: + setup.maxNumCmplxQmfBands = fixMax(PC_NUM_BANDS, setup.maxNumQmfBands); + setup.maxNumCmplxHybBands = + fixMax(PC_NUM_HYB_BANDS, setup.maxNumHybridBands); + break; + } /* switch config->decoderMode */ + + FDK_ALLOCATE_MEMORY_1D_INT(self, 1, spatialDec, SECT_DATA_L2) + + self->createParams = setup; + + FDK_ALLOCATE_MEMORY_1D(self->param2hyb, MAX_PARAMETER_BANDS + 1, int) + + FDK_ALLOCATE_MEMORY_1D(self->numOttBands, setup.maxNumOttBoxes, int) + + /* allocate arrays */ + + FDK_ALLOCATE_MEMORY_1D(self->smgTime, MAX_PARAMETER_SETS, int) + FDK_ALLOCATE_MEMORY_2D(self->smgData, MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, + UCHAR) + + FDK_ALLOCATE_MEMORY_3D(self->ottCLD__FDK, setup.maxNumOttBoxes, + MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_3D(self->ottICC__FDK, setup.maxNumOttBoxes, + MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_3D(self->ottIPD__FDK, setup.maxNumOttBoxes, + MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR) + + /* Last parameters from prev frame */ + FDK_ALLOCATE_MEMORY_2D(self->ottCLDidxPrev, setup.maxNumOttBoxes, + MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_2D(self->ottICCidxPrev, setup.maxNumOttBoxes, + MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_3D(self->ottICCdiffidx, setup.maxNumOttBoxes, + MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_2D(self->ottIPDidxPrev, setup.maxNumOttBoxes, + MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_2D(self->arbdmxGainIdxPrev, setup.maxNumInputChannels, + MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_2D(self->cmpOttCLDidxPrev, setup.maxNumOttBoxes, + MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_2D(self->cmpOttICCidxPrev, setup.maxNumOttBoxes, + MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_3D(self->outIdxData, setup.maxNumOttBoxes, + MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR) + + FDK_ALLOCATE_MEMORY_3D(self->arbdmxGain__FDK, setup.maxNumInputChannels, + MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_1D(self->arbdmxAlpha__FDK, setup.maxNumInputChannels, + FIXP_DBL) + FDK_ALLOCATE_MEMORY_1D(self->arbdmxAlphaPrev__FDK, setup.maxNumInputChannels, + FIXP_DBL) + FDK_ALLOCATE_MEMORY_2D(self->cmpArbdmxGainIdxPrev, setup.maxNumInputChannels, + MAX_PARAMETER_BANDS, SCHAR) + + FDK_ALLOCATE_MEMORY_2D(self->cmpOttIPDidxPrev, setup.maxNumOttBoxes, + MAX_PARAMETER_BANDS, SCHAR) + + FDK_ALLOCATE_MEMORY_3D_INT(self->M2Real__FDK, setup.maxNumOutputChannels, + setup.maxNumVChannels, MAX_PARAMETER_BANDS, + FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_3D(self->M2Imag__FDK, setup.maxNumOutputChannels, + setup.maxNumVChannels, MAX_PARAMETER_BANDS, FIXP_DBL) + + FDK_ALLOCATE_MEMORY_3D_INT(self->M2RealPrev__FDK, setup.maxNumOutputChannels, + setup.maxNumVChannels, MAX_PARAMETER_BANDS, + FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_3D(self->M2ImagPrev__FDK, setup.maxNumOutputChannels, + setup.maxNumVChannels, MAX_PARAMETER_BANDS, FIXP_DBL) + + FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED( + self->qmfInputReal__FDK, setup.maxNumInputChannels, setup.maxNumQmfBands, + FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED( + self->qmfInputImag__FDK, setup.maxNumInputChannels, + setup.maxNumCmplxQmfBands, FIXP_DBL, SECT_DATA_L2) + + FDK_ALLOCATE_MEMORY_2D_INT(self->hybInputReal__FDK, setup.maxNumInputChannels, + setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_2D_INT(self->hybInputImag__FDK, setup.maxNumInputChannels, + setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2) + + if (setup.bProcResidual) { + FDK_ALLOCATE_MEMORY_1D(self->qmfResidualReal__FDK, setup.maxNumResChannels, + FIXP_DBL **) + FDK_ALLOCATE_MEMORY_1D(self->qmfResidualImag__FDK, setup.maxNumResChannels, + FIXP_DBL **) + + FDK_ALLOCATE_MEMORY_1D(self->hybResidualReal__FDK, setup.maxNumResChannels, + FIXP_DBL *) + FDK_ALLOCATE_MEMORY_1D(self->hybResidualImag__FDK, setup.maxNumResChannels, + FIXP_DBL *) + + for (i = 0; i < setup.maxNumResChannels; i++) { + int resQmfBands = (config->decoderMode == EXT_LP_ONLY) + ? PC_NUM_BANDS + : setup.maxNumQmfBands; + int resHybBands = (config->decoderMode == EXT_LP_ONLY) + ? PC_NUM_HYB_BANDS + : setup.maxNumHybridBands; + /* Alignment is needed for USAC residuals because QMF analysis directly + * writes to this buffer. */ + FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(self->qmfResidualReal__FDK[i], (1), + resQmfBands, FIXP_DBL, SECT_DATA_L1) + FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(self->qmfResidualImag__FDK[i], (1), + resQmfBands, FIXP_DBL, SECT_DATA_L1) + + FDK_ALLOCATE_MEMORY_1D(self->hybResidualReal__FDK[i], + setup.maxNumHybridBands, FIXP_DBL) + FDK_ALLOCATE_MEMORY_1D(self->hybResidualImag__FDK[i], resHybBands, + FIXP_DBL) + } + } /* if (setup.bProcResidual) */ + + FDK_ALLOCATE_MEMORY_2D_INT(self->wReal__FDK, setup.maxNumVChannels, + setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_2D_INT(self->wImag__FDK, setup.maxNumVChannels, + setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2) + + FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputRealDry__FDK, + setup.maxNumOutputChannels, + setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputImagDry__FDK, + setup.maxNumOutputChannels, + setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2) + + FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputRealWet__FDK, + setup.maxNumOutputChannels, + setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputImagWet__FDK, + setup.maxNumOutputChannels, + setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2) + + FDK_ALLOCATE_MEMORY_1D(self->hybridSynthesis, setup.maxNumOutputChannels, + FDK_SYN_HYB_FILTER) + + FDK_ALLOCATE_MEMORY_1D( + self->hybridAnalysis, + setup.bProcResidual ? setup.maxNumInputChannels + setup.maxNumResChannels + : setup.maxNumInputChannels, + FDK_ANA_HYB_FILTER) + + lfSize = 2 * BUFFER_LEN_LF * MAX_QMF_BANDS_TO_HYBRID; + { + hfSize = + BUFFER_LEN_HF * ((setup.maxNumQmfBands - MAX_QMF_BANDS_TO_HYBRID) + + (setup.maxNumCmplxQmfBands - MAX_QMF_BANDS_TO_HYBRID)); + } + + FDK_ALLOCATE_MEMORY_2D_INT(self->pHybridAnaStatesLFdmx, + setup.maxNumInputChannels, lfSize, FIXP_DBL, + SECT_DATA_L2) { + FDK_ALLOCATE_MEMORY_2D(self->pHybridAnaStatesHFdmx, + setup.maxNumInputChannels, hfSize, FIXP_DBL) + } + + for (i = 0; i < setup.maxNumInputChannels; i++) { + FIXP_DBL *pHybridAnaStatesHFdmx; + + pHybridAnaStatesHFdmx = self->pHybridAnaStatesHFdmx[i]; + + FDKhybridAnalysisOpen(&self->hybridAnalysis[i], + self->pHybridAnaStatesLFdmx[i], + lfSize * sizeof(FIXP_DBL), pHybridAnaStatesHFdmx, + hfSize * sizeof(FIXP_DBL)); + } + if (setup.bProcResidual) { + lfSize = 2 * BUFFER_LEN_LF * MAX_QMF_BANDS_TO_HYBRID; + hfSize = BUFFER_LEN_HF * + ((((config->decoderMode == EXT_LP_ONLY) ? PC_NUM_BANDS + : setup.maxNumQmfBands) - + MAX_QMF_BANDS_TO_HYBRID) + + (setup.maxNumCmplxQmfBands - MAX_QMF_BANDS_TO_HYBRID)); + + FDK_ALLOCATE_MEMORY_2D_INT(self->pHybridAnaStatesLFres, + setup.maxNumResChannels, lfSize, FIXP_DBL, + SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_2D(self->pHybridAnaStatesHFres, setup.maxNumResChannels, + hfSize, FIXP_DBL) + + for (i = setup.maxNumInputChannels; + i < (setup.maxNumInputChannels + setup.maxNumResChannels); i++) { + FDKhybridAnalysisOpen( + &self->hybridAnalysis[i], + self->pHybridAnaStatesLFres[i - setup.maxNumInputChannels], + lfSize * sizeof(FIXP_DBL), + self->pHybridAnaStatesHFres[i - setup.maxNumInputChannels], + hfSize * sizeof(FIXP_DBL)); + } + } + + FDK_ALLOCATE_MEMORY_1D(self->smoothState, 1, SMOOTHING_STATE) + FDK_ALLOCATE_MEMORY_1D(self->reshapeBBEnvState, 1, RESHAPE_BBENV_STATE) + + FDK_ALLOCATE_MEMORY_1D(self->apDecor, setup.maxNumDecorChannels, DECORR_DEC) + FDK_ALLOCATE_MEMORY_2D_INT(self->pDecorBufferCplx, setup.maxNumDecorChannels, + (2 * ((825) + (373))), FIXP_DBL, SECT_DATA_L2) + + for (i = 0; i < setup.maxNumDecorChannels; i++) { + if (FDKdecorrelateOpen(&self->apDecor[i], self->pDecorBufferCplx[i], + (2 * ((825) + (373))))) { + goto bail; + } + } + + if (subbandTPCreate(&self->hStpDec) != MPS_OK) { + goto bail; + } + + /* save general decoder configuration */ + self->decoderLevel = config->decoderLevel; + self->decoderMode = config->decoderMode; + self->binauralMode = config->binauralMode; + + /* preinitialize configuration */ + self->partiallyComplex = (config->decoderMode != EXT_HQ_ONLY) ? 1 : 0; + + /* Set to default state */ + SpatialDecConcealment_Init(&self->concealInfo, MPEGS_CONCEAL_RESET_ALL); + + /* Everything is fine so return the handle */ + return self; + +bail: + /* Collector for all errors. + Deallocate all memory and return a invalid handle. */ + FDK_SpatialDecClose(self); + + return NULL; +} + +/******************************************************************************* + Functionname: isValidConfig + ******************************************************************************* + + Description: Validate if configuration is supported in present instance + + Arguments: + + Return: 1: all okay + 0: configuration not supported +*******************************************************************************/ +static int isValidConfig(spatialDec const *const self, + const SPATIAL_DEC_UPMIX_TYPE upmixType, + SPATIALDEC_PARAM const *const pUserParams, + const AUDIO_OBJECT_TYPE coreAot) { + UPMIXTYPE nUpmixType; + + FDK_ASSERT(self != NULL); + FDK_ASSERT(pUserParams != NULL); + + nUpmixType = (UPMIXTYPE)upmixType; + + switch (nUpmixType) { + case UPMIXTYPE_BYPASS: /* UPMIX_TYPE_BYPASS */ + break; + case UPMIXTYPE_NORMAL: /* UPMIX_TYPE_NORMAL */ + break; + default: + return 0; /* unsupported upmixType */ + } + + return 1; /* upmixType supported */ +} + +static SACDEC_ERROR CheckLevelTreeUpmixType( + const SACDEC_CREATION_PARAMS *const pCreateParams, + const SPATIAL_SPECIFIC_CONFIG *const pSsc, const int decoderLevel, + const UPMIXTYPE upmixType) { + SACDEC_ERROR err = MPS_OK; + int nOutputChannels, treeConfig; + + FDK_ASSERT(pCreateParams != NULL); + FDK_ASSERT(pSsc != NULL); + + treeConfig = pSsc->treeConfig; + + switch (decoderLevel) { + case 0: { + if (treeConfig != SPATIALDEC_MODE_RSVD7) { + err = MPS_INVALID_TREECONFIG; + goto bail; + } + break; + } + default: + err = MPS_INVALID_PARAMETER /* MPS_UNIMPLEMENTED */; + goto bail; + } + + switch (upmixType) { + case UPMIXTYPE_BYPASS: + nOutputChannels = pSsc->nInputChannels; + break; + default: + nOutputChannels = pSsc->nOutputChannels; + break; + } + + /* Is sufficient memory allocated. */ + if ((pSsc->nInputChannels > pCreateParams->maxNumInputChannels) || + (nOutputChannels > pCreateParams->maxNumOutputChannels) || + (pSsc->nOttBoxes > pCreateParams->maxNumOttBoxes)) { + err = MPS_INVALID_PARAMETER; + } + +bail: + return err; +} + +void SpatialDecInitParserContext(spatialDec *self) { + int i, j; + + for (i = 0; i < self->createParams.maxNumOttBoxes; i += 1) { + for (j = 0; j < MAX_PARAMETER_BANDS; j++) { + self->ottCLDidxPrev[i][j] = 0; + self->ottICCidxPrev[i][j] = 0; + self->cmpOttCLDidxPrev[i][j] = 0; + self->cmpOttICCidxPrev[i][j] = 0; + } + } + for (i = 0; i < self->createParams.maxNumInputChannels; i++) { + for (j = 0; j < MAX_PARAMETER_BANDS; j++) { + self->arbdmxGainIdxPrev[i][j] = 0; + self->cmpArbdmxGainIdxPrev[i][j] = 0; + } + } +} + +/******************************************************************************* + Functionname: FDK_SpatialDecInit + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ + +SACDEC_ERROR FDK_SpatialDecInit(spatialDec *self, SPATIAL_BS_FRAME *frame, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + int nQmfBands, + SPATIAL_DEC_UPMIX_TYPE const upmixType, + SPATIALDEC_PARAM *pUserParams, UINT initFlags) { + SACDEC_ERROR err = MPS_OK; + int nCh, i, j, k; + int maxQmfBands; + int bypassMode = 0; + + self->useFDreverb = 0; + + /* check configuration parameter */ + if (!isValidConfig(self, upmixType, pUserParams, + pSpatialSpecificConfig->coreCodec)) { + return MPS_INVALID_PARAMETER; + } + + /* check tree configuration */ + err = CheckLevelTreeUpmixType(&self->createParams, pSpatialSpecificConfig, + self->decoderLevel, (UPMIXTYPE)upmixType); + if (err != MPS_OK) { + goto bail; + } + + /* Store and update instance after all checks passed successfully: */ + self->upmixType = (UPMIXTYPE)upmixType; + + if (initFlags & MPEGS_INIT_PARAMS_ERROR_CONCEALMENT) { /* At least one error + concealment + parameter changed */ + err = SpatialDecConcealment_SetParam( + &self->concealInfo, SAC_DEC_CONCEAL_METHOD, pUserParams->concealMethod); + if (err != MPS_OK) { + goto bail; + } + err = SpatialDecConcealment_SetParam(&self->concealInfo, + SAC_DEC_CONCEAL_NUM_KEEP_FRAMES, + pUserParams->concealNumKeepFrames); + if (err != MPS_OK) { + goto bail; + } + err = SpatialDecConcealment_SetParam( + &self->concealInfo, SAC_DEC_CONCEAL_FADE_OUT_SLOPE_LENGTH, + pUserParams->concealFadeOutSlopeLength); + if (err != MPS_OK) { + goto bail; + } + err = SpatialDecConcealment_SetParam(&self->concealInfo, + SAC_DEC_CONCEAL_FADE_IN_SLOPE_LENGTH, + pUserParams->concealFadeInSlopeLength); + if (err != MPS_OK) { + goto bail; + } + err = SpatialDecConcealment_SetParam(&self->concealInfo, + SAC_DEC_CONCEAL_NUM_RELEASE_FRAMES, + pUserParams->concealNumReleaseFrames); + if (err != MPS_OK) { + goto bail; + } + } + + if (initFlags & + MPEGS_INIT_STATES_ERROR_CONCEALMENT) { /* Set to default state */ + SpatialDecConcealment_Init(&self->concealInfo, MPEGS_CONCEAL_RESET_STATE); + } + + /* determine bypass mode */ + bypassMode |= pUserParams->bypassMode; + bypassMode |= ((self->upmixType == UPMIXTYPE_BYPASS) ? 1 : 0); + + /* static decoder scale depends on number of qmf bands */ + switch (nQmfBands) { + case 16: + case 24: + case 32: + self->staticDecScale = 21; + break; + case 64: + self->staticDecScale = 22; + break; + default: + return MPS_INVALID_PARAMETER; + } + + self->numParameterSetsPrev = 1; + + self->qmfBands = nQmfBands; + /* self->hybridBands will be updated in SpatialDecDecodeHeader() below. */ + + self->bShareDelayWithSBR = 0; + + err = SpatialDecDecodeHeader(self, pSpatialSpecificConfig); + if (err != MPS_OK) { + goto bail; + } + + self->stereoConfigIndex = pSpatialSpecificConfig->stereoConfigIndex; + + if (initFlags & MPEGS_INIT_STATES_ANA_QMF_FILTER) { + self->qmfInputDelayBufPos = 0; + self->pc_filterdelay = 1; /* Division by 0 not possible */ + } + + maxQmfBands = self->qmfBands; + + /* init residual decoder */ + + /* init tonality smoothing */ + if (initFlags & MPEGS_INIT_STATES_PARAM) { + initParameterSmoothing(self); + } + + /* init GES */ + initBBEnv(self, (initFlags & MPEGS_INIT_STATES_GES) ? 1 : 0); + + /* Clip protection is applied only for normal processing. */ + if (!isTwoChMode(self->upmixType) && !bypassMode) { + self->staticDecScale += self->clipProtectGainSF__FDK; + } + + { + UINT flags = 0; + INT initStatesFlag = (initFlags & MPEGS_INIT_STATES_ANA_QMF_FILTER) ? 1 : 0; + INT useLdFilter = + (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) ? 1 : 0; + + flags = self->pQmfDomain->globalConf.flags_requested; + flags &= (~(UINT)QMF_FLAG_LP); + + if (initStatesFlag) + flags &= ~QMF_FLAG_KEEP_STATES; + else + flags |= QMF_FLAG_KEEP_STATES; + + if (useLdFilter) + flags |= QMF_FLAG_MPSLDFB; + else + flags &= ~QMF_FLAG_MPSLDFB; + + self->pQmfDomain->globalConf.flags_requested = flags; + FDK_QmfDomain_Configure(self->pQmfDomain); + + /* output scaling */ + for (nCh = 0; nCh < self->numOutputChannelsAT; nCh++) { + int outputScale = 0, outputGain_e = 0, scale = -(8) + (1); + FIXP_DBL outputGain_m = getChGain(self, nCh, &outputGain_e); + + if (!isTwoChMode(self->upmixType) && !bypassMode) { + outputScale += + self->clipProtectGainSF__FDK; /* consider clip protection scaling at + synthesis qmf */ + } + + scale += outputScale; + + qmfChangeOutScalefactor(&self->pQmfDomain->QmfDomainOut[nCh].fb, scale); + qmfChangeOutGain(&self->pQmfDomain->QmfDomainOut[nCh].fb, outputGain_m, + outputGain_e); + } + } + + for (nCh = 0; nCh < self->numOutputChannelsAT; nCh++) { + FDKhybridSynthesisInit(&self->hybridSynthesis[nCh], THREE_TO_TEN, + self->qmfBands, maxQmfBands); + } + + /* for input, residual channels and arbitrary down-mix residual channels */ + for (nCh = 0; nCh < self->createParams.maxNumInputChannels; nCh++) { + FDKhybridAnalysisInit( + &self->hybridAnalysis[nCh], THREE_TO_TEN, self->qmfBands, maxQmfBands, + (initFlags & MPEGS_INIT_STATES_ANA_HYB_FILTER) ? 1 : 0); + } + for (; nCh < (self->createParams.bProcResidual + ? (self->createParams.maxNumInputChannels + + self->createParams.maxNumResChannels) + : self->createParams.maxNumInputChannels); + nCh++) { + FDKhybridAnalysisInit(&self->hybridAnalysis[nCh], THREE_TO_TEN, maxQmfBands, + maxQmfBands, 0); + } + + { + for (k = 0; k < self->numDecorSignals; k++) { + int errCode, idec; + FDK_DECORR_TYPE decorrType = DECORR_PS; + decorrType = DECORR_LD; + if (self->pConfigCurrent->syntaxFlags & + (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) { + decorrType = + ((self->treeConfig == TREE_212) && (self->decorrType == DECORR_PS)) + ? DECORR_PS + : DECORR_USAC; + } + { + idec = k; + if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) { + if (self->treeConfig == TREE_212 && k == 0) { + idec = 2; + } + } + } + errCode = FDKdecorrelateInit( + &self->apDecor[k], self->hybridBands, decorrType, DUCKER_AUTOMATIC, + self->decorrConfig, idec, 0, /* self->partiallyComplex */ + 0, 0, /* isLegacyPS */ + (initFlags & MPEGS_INIT_STATES_DECORRELATOR) ? 1 : 0); + if (errCode) return MPS_NOTOK; + } + } /* !self->partiallyComplex */ + + err = initM1andM2(self, (initFlags & MPEGS_INIT_STATES_M1M2) ? 1 : 0, + (initFlags & MPEGS_INIT_CONFIG) ? 1 : 0); + if (err != MPS_OK) return err; + + /* Initialization of previous frame data */ + if (initFlags & MPEGS_INIT_STATES_PARAM) { + for (i = 0; i < self->createParams.maxNumOttBoxes; i += 1) { + /* reset icc diff data */ + for (k = 0; k < MAX_PARAMETER_SETS; k += 1) { + for (j = 0; j < MAX_PARAMETER_BANDS; j += 1) { + self->ottICCdiffidx[i][k][j] = 0; + } + } + } + /* Parameter Smoothing */ + /* robustness: init with one of the values of smgTimeTable[] = {64, 128, + 256, 512} to avoid division by zero in calcFilterCoeff__FDK() */ + self->smoothState->prevSmgTime = smgTimeTable[2]; /* == 256 */ + FDKmemclear(self->smoothState->prevSmgData, + MAX_PARAMETER_BANDS * sizeof(UCHAR)); + FDKmemclear(self->smoothState->opdLeftState__FDK, + MAX_PARAMETER_BANDS * sizeof(FIXP_DBL)); + FDKmemclear(self->smoothState->opdRightState__FDK, + MAX_PARAMETER_BANDS * sizeof(FIXP_DBL)); + } + + self->prevTimeSlot = -1; + self->curTimeSlot = + MAX_TIME_SLOTS + 1; /* Initialize with a invalid value to trigger + concealment if first frame has no valid data. */ + self->curPs = 0; + + subbandTPInit(self->hStpDec); + +bail: + return err; +} + +void SpatialDecChannelProperties(spatialDec *self, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const FDK_channelMapDescr *const mapDescr) { + if ((self == NULL) || (channelType == NULL) || (channelIndices == NULL) || + (mapDescr == NULL)) { + return; /* no extern buffer to be filled */ + } + + if (self->numOutputChannelsAT != + treePropertyTable[self->treeConfig].numOutputChannels) { + int ch; + /* Declare all channels to be front channels: */ + for (ch = 0; ch < self->numOutputChannelsAT; ch += 1) { + channelType[ch] = ACT_FRONT; + channelIndices[ch] = ch; + } + } else { + /* ISO/IEC FDIS 23003-1:2006(E), page 46, Table 40 bsTreeConfig */ + switch (self->treeConfig) { + case TREE_212: + channelType[0] = ACT_FRONT; + channelIndices[0] = 0; + channelType[1] = ACT_FRONT; + channelIndices[1] = 1; + break; + default:; + } + } +} + +/******************************************************************************* + Functionname: FDK_SpatialDecClose + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ + +void FDK_SpatialDecClose(spatialDec *self) { + if (self) { + int k; + + if (self->apDecor != NULL) { + for (k = 0; k < self->createParams.maxNumDecorChannels; k++) { + FDKdecorrelateClose(&(self->apDecor[k])); + } + FDK_FREE_MEMORY_1D(self->apDecor); + } + if (self->pDecorBufferCplx != NULL) { + FDK_FREE_MEMORY_2D(self->pDecorBufferCplx); + } + + subbandTPDestroy(&self->hStpDec); + + FDK_FREE_MEMORY_1D(self->reshapeBBEnvState); + FDK_FREE_MEMORY_1D(self->smoothState); + + FDK_FREE_MEMORY_2D(self->pHybridAnaStatesLFdmx); + FDK_FREE_MEMORY_2D(self->pHybridAnaStatesHFdmx); + FDK_FREE_MEMORY_2D(self->pHybridAnaStatesLFres); + FDK_FREE_MEMORY_2D(self->pHybridAnaStatesHFres); + FDK_FREE_MEMORY_1D(self->hybridAnalysis); + + FDK_FREE_MEMORY_1D(self->hybridSynthesis); + + /* The time buffer is passed to the decoder from outside to avoid copying + * (zero copy). */ + /* FDK_FREE_MEMORY_2D(self->timeOut__FDK); */ + + FDK_FREE_MEMORY_2D(self->hybOutputImagWet__FDK); + FDK_FREE_MEMORY_2D(self->hybOutputRealWet__FDK); + + FDK_FREE_MEMORY_2D(self->hybOutputImagDry__FDK); + FDK_FREE_MEMORY_2D(self->hybOutputRealDry__FDK); + + FDK_FREE_MEMORY_2D(self->wImag__FDK); + FDK_FREE_MEMORY_2D(self->wReal__FDK); + + if (self->createParams.bProcResidual) { + int i; + + for (i = 0; i < self->createParams.maxNumResChannels; i++) { + if (self->hybResidualImag__FDK != NULL) + FDK_FREE_MEMORY_1D(self->hybResidualImag__FDK[i]); + if (self->hybResidualReal__FDK != NULL) + FDK_FREE_MEMORY_1D(self->hybResidualReal__FDK[i]); + if (self->qmfResidualImag__FDK != NULL) + FDK_FREE_MEMORY_2D_ALIGNED(self->qmfResidualImag__FDK[i]); + if (self->qmfResidualReal__FDK != NULL) + FDK_FREE_MEMORY_2D_ALIGNED(self->qmfResidualReal__FDK[i]); + } + + FDK_FREE_MEMORY_1D(self->hybResidualImag__FDK); + FDK_FREE_MEMORY_1D(self->hybResidualReal__FDK); + + FDK_FREE_MEMORY_1D(self->qmfResidualImag__FDK); + FDK_FREE_MEMORY_1D(self->qmfResidualReal__FDK); + + } /* self->createParams.bProcResidual */ + + FDK_FREE_MEMORY_2D(self->hybInputImag__FDK); + FDK_FREE_MEMORY_2D(self->hybInputReal__FDK); + + FDK_FREE_MEMORY_2D_ALIGNED(self->qmfInputImag__FDK); + FDK_FREE_MEMORY_2D_ALIGNED(self->qmfInputReal__FDK); + + FDK_FREE_MEMORY_3D(self->M2ImagPrev__FDK); + + FDK_FREE_MEMORY_3D(self->M2RealPrev__FDK); + + FDK_FREE_MEMORY_3D(self->M2Imag__FDK); + + FDK_FREE_MEMORY_3D(self->M2Real__FDK); + + FDK_FREE_MEMORY_1D(self->arbdmxAlphaPrev__FDK); + FDK_FREE_MEMORY_1D(self->arbdmxAlpha__FDK); + + FDK_FREE_MEMORY_3D(self->arbdmxGain__FDK); + + FDK_FREE_MEMORY_3D(self->ottIPD__FDK); + FDK_FREE_MEMORY_3D(self->ottICC__FDK); + FDK_FREE_MEMORY_3D(self->ottCLD__FDK); + + /* Last parameters from prev frame */ + FDK_FREE_MEMORY_2D(self->ottCLDidxPrev); + FDK_FREE_MEMORY_2D(self->ottICCidxPrev); + FDK_FREE_MEMORY_3D(self->ottICCdiffidx); + FDK_FREE_MEMORY_2D(self->ottIPDidxPrev); + FDK_FREE_MEMORY_2D(self->arbdmxGainIdxPrev); + + FDK_FREE_MEMORY_2D(self->cmpOttCLDidxPrev); + FDK_FREE_MEMORY_2D(self->cmpOttICCidxPrev); + FDK_FREE_MEMORY_3D(self->outIdxData); + FDK_FREE_MEMORY_2D(self->cmpOttIPDidxPrev); + FDK_FREE_MEMORY_2D(self->cmpArbdmxGainIdxPrev); + + FDK_FREE_MEMORY_2D(self->smgData); + FDK_FREE_MEMORY_1D(self->smgTime); + + FDK_FREE_MEMORY_1D(self->numOttBands); + + FDK_FREE_MEMORY_1D(self->param2hyb); + + FDK_FREE_MEMORY_1D(self); + } + + return; +} + +/** + * \brief Apply Surround bypass buffer copies + * \param self spatialDec handle + * \param hybInputReal + * \param hybInputImag + * \param hybOutputReal + * \param hybOutputImag + * \param numInputChannels amount if input channels available in hybInputReal + * and hybInputImag, which may differ from self->numInputChannels. + */ +static void SpatialDecApplyBypass(spatialDec *self, FIXP_DBL **hybInputReal, + FIXP_DBL **hybInputImag, + FIXP_DBL **hybOutputReal, + FIXP_DBL **hybOutputImag, + const int numInputChannels) { + int complexHybBands; + + complexHybBands = self->hybridBands; + + { + int ch; + int rf = -1, lf = -1, cf = -1; /* Right Front, Left Front, Center Front */ + + /* Determine output channel indices according to tree config */ + switch (self->treeConfig) { + case TREE_212: /* 212 */ + lf = 0; + rf = 1; + break; + default:; + } + + /* Note: numInputChannels might not match the tree config ! */ + switch (numInputChannels) { + case 1: + if (cf > 0) { + FDKmemcpy(hybOutputReal[cf], hybInputReal[0], + self->hybridBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputImag[cf], hybInputImag[0], + complexHybBands * sizeof(FIXP_DBL)); + } else { + FDKmemcpy(hybOutputReal[lf], hybInputReal[0], + self->hybridBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputReal[rf], hybInputReal[0], + self->hybridBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputImag[lf], hybInputImag[0], + complexHybBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputImag[rf], hybInputImag[0], + complexHybBands * sizeof(FIXP_DBL)); + } + break; + case 2: + FDK_ASSERT(lf != -1); + FDK_ASSERT(rf != -1); + FDKmemcpy(hybOutputReal[lf], hybInputReal[0], + self->hybridBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputReal[rf], hybInputReal[1], + self->hybridBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputImag[lf], hybInputImag[0], + complexHybBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputImag[rf], hybInputImag[1], + complexHybBands * sizeof(FIXP_DBL)); + break; + } + for (ch = 0; ch < self->numOutputChannelsAT; ch++) { + if (ch == lf || ch == rf || ch == cf) { + continue; /* Skip bypassed channels */ + } + FDKmemclear(hybOutputReal[ch], self->hybridBands * sizeof(FIXP_DBL)); + FDKmemclear(hybOutputImag[ch], complexHybBands * sizeof(FIXP_DBL)); + } + } +} + +/** + * \brief Set internal error and reset error status + * + * \param self spatialDec handle. + * \param bypassMode pointer to bypassMode. + * \param err error status. + * + * \return error status. + */ +static SACDEC_ERROR SpatialDecSetInternalError(spatialDec *self, + int *bypassMode, + SACDEC_ERROR err) { + *bypassMode = 1; + + if (self->errInt == MPS_OK) { + /* store internal error before it gets overwritten */ + self->errInt = err; + } + + return MPS_OK; +} + +/******************************************************************************* + Functionname: SpatialDecApplyParameterSets + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static SACDEC_ERROR SpatialDecApplyParameterSets( + spatialDec *self, const SPATIAL_BS_FRAME *frame, SPATIALDEC_INPUT_MODE mode, + PCM_MPS *inData, /* Time domain input */ + FIXP_DBL **qmfInDataReal, /* QMF domain data l/r */ + FIXP_DBL **qmfInDataImag, /* QMF domain data l/r */ + UINT nSamples, UINT controlFlags, int numInputChannels, + const FDK_channelMapDescr *const mapDescr) { + SACDEC_ERROR err = MPS_OK; + + FIXP_SGL alpha = FL2FXCONST_SGL(0.0); + + int ts; + int ch; + int hyb; + + int prevSlot = self->prevTimeSlot; + int ps = self->curPs; + int ts_io = 0; /* i/o dependent slot */ + int bypassMode = (controlFlags & MPEGS_BYPASSMODE) ? 1 : 0; + + /* Bypass can be triggered by the upmixType, too. */ + bypassMode |= ((self->upmixType == UPMIXTYPE_BYPASS) ? 1 : 0); + + /* + * Decode available slots + */ + for (ts = self->curTimeSlot; + ts <= fixMin(self->curTimeSlot + (int)nSamples / self->qmfBands - 1, + self->timeSlots - 1); + ts++, ts_io++) { + int currSlot = frame->paramSlot[ps]; + + err = (currSlot < ts) ? MPS_WRONG_PARAMETERSETS : MPS_OK; + if (err != MPS_OK) { + err = SpatialDecSetInternalError(self, &bypassMode, err); + } + + /* + * Get new parameter set + */ + if (ts == prevSlot + 1) { + if (bypassMode == 0) { + err = SpatialDecCalculateM1andM2( + self, ps, frame); /* input: ottCLD, ottICC, ... */ + /* output: M1param(Real/Imag), M2(Real/Imag) */ + if (err != MPS_OK) { + err = SpatialDecSetInternalError(self, &bypassMode, err); + } + } + + if ((ps == 0) && (self->bOverwriteM1M2prev != 0)) { + /* copy matrix entries of M1/M2 of the first parameter set to the + previous matrices (of the last frame). This avoids the interpolation + of incompatible values. E.g. for residual bands the coefficients are + calculated differently compared to non-residual bands. + */ + SpatialDecBufferMatrices(self); /* input: M(1/2)param(Real/Imag) */ + /* output: M(1/2)param(Real/Imag)Prev */ + self->bOverwriteM1M2prev = 0; + } + + if (bypassMode == 0) { + SpatialDecSmoothM1andM2( + self, frame, + ps); /* input: M1param(Real/Imag)(Prev), M2(Real/Imag)(Prev) */ + } /* output: M1param(Real/Imag), M2(Real/Imag) */ + } + + if (bypassMode == 0) { + alpha = FX_DBL2FX_SGL(fDivNorm(ts - prevSlot, currSlot - prevSlot)); + } + + switch (mode) { + case INPUTMODE_QMF_SBR: + if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) + self->bShareDelayWithSBR = 0; /* We got no hybrid delay */ + else + self->bShareDelayWithSBR = 1; + SpatialDecFeedQMF( + self, qmfInDataReal, qmfInDataImag, ts_io, bypassMode, + self->qmfInputReal__FDK, self->qmfInputImag__FDK, + (bypassMode) ? numInputChannels : self->numInputChannels); + break; + case INPUTMODE_TIME: + self->bShareDelayWithSBR = 0; + SpatialDecQMFAnalysis( + self, inData, ts_io, bypassMode, self->qmfInputReal__FDK, + self->qmfInputImag__FDK, + (bypassMode) ? numInputChannels : self->numInputChannels); + break; + default: + break; + } + + if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) && + self->residualCoding) { + int offset; + ch = 1; + + offset = self->pQmfDomain->globalConf.nBandsSynthesis * + self->pQmfDomain->globalConf.nQmfTimeSlots; + + { + const PCM_MPS *inSamples = + &inData[ts * self->pQmfDomain->globalConf.nBandsAnalysis]; + + CalculateSpaceAnalysisQmf( + &self->pQmfDomain->QmfDomainIn[ch].fb, inSamples + (ch * offset), + self->qmfResidualReal__FDK[0][0], self->qmfResidualImag__FDK[0][0]); + + if (!isTwoChMode(self->upmixType) && !bypassMode) { + int i; + FIXP_DBL *RESTRICT self_qmfResidualReal__FDK_0_0 = + &self->qmfResidualReal__FDK[0][0][0]; + FIXP_DBL *RESTRICT self_qmfResidualImag__FDK_0_0 = + &self->qmfResidualImag__FDK[0][0][0]; + + if ((self->pQmfDomain->globalConf.nBandsAnalysis == 24) && + !(self->stereoConfigIndex == 3)) { + for (i = 0; i < self->qmfBands; i++) { + self_qmfResidualReal__FDK_0_0[i] = + fMult(scaleValueSaturate(self_qmfResidualReal__FDK_0_0[i], + 1 + self->sacInDataHeadroom - (1)), + self->clipProtectGain__FDK); + self_qmfResidualImag__FDK_0_0[i] = + fMult(scaleValueSaturate(self_qmfResidualImag__FDK_0_0[i], + 1 + self->sacInDataHeadroom - (1)), + self->clipProtectGain__FDK); + } + } else { + for (i = 0; i < self->qmfBands; i++) { + self_qmfResidualReal__FDK_0_0[i] = + fMult(scaleValueSaturate(self_qmfResidualReal__FDK_0_0[i], + self->sacInDataHeadroom - (1)), + self->clipProtectGain__FDK); + self_qmfResidualImag__FDK_0_0[i] = + fMult(scaleValueSaturate(self_qmfResidualImag__FDK_0_0[i], + self->sacInDataHeadroom - (1)), + self->clipProtectGain__FDK); + } + } + } + } + } + + SpatialDecHybridAnalysis( + self, /* input: qmfInput(Real/Imag), qmfResidual(Real/Imag) */ + self->qmfInputReal__FDK, self->qmfInputImag__FDK, + self->hybInputReal__FDK, self->hybInputImag__FDK, ts, numInputChannels); + + if (bypassMode) { + SpatialDecApplyBypass( + self, self->hybInputReal__FDK, /* input: hybInput(Real/Imag) */ + self->hybInputImag__FDK, + self->hybOutputRealDry__FDK, /* output: hybOutput(Real/Imag)Dry */ + self->hybOutputImagDry__FDK, numInputChannels); + } else /* !bypassMode */ + { + FIXP_DBL *pxReal[MAX_NUM_XCHANNELS] = {NULL}; + FIXP_DBL *pxImag[MAX_NUM_XCHANNELS] = {NULL}; + + SpatialDecCreateX(self, + self->hybInputReal__FDK, /* input: hybInput(Real/Imag), + hybResidual(Real/Imag) */ + self->hybInputImag__FDK, pxReal, pxImag); + + { + SpatialDecApplyM1_CreateW_Mode212( + self, frame, pxReal, pxImag, + self->wReal__FDK, /* output: w(Real/Imag) */ + self->wImag__FDK); + } + if (err != MPS_OK) goto bail; + + int applyM2Config = APPLY_M2_NONE; + + applyM2Config = APPLY_M2; + if ((self->pConfigCurrent->syntaxFlags & + (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) && + (self->tempShapeConfig != 1) && (self->tempShapeConfig != 2)) { + if (self->phaseCoding == 3) + applyM2Config = APPLY_M2_MODE212_Res_PhaseCoding; + else + applyM2Config = APPLY_M2_MODE212; + } + + switch (applyM2Config) { + case APPLY_M2_MODE212: { + err = SpatialDecApplyM2_Mode212( + self, ps, alpha, self->wReal__FDK, self->wImag__FDK, + self->hybOutputRealDry__FDK, self->hybOutputImagDry__FDK); + } break; + case APPLY_M2_MODE212_Res_PhaseCoding: + err = SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding( + self, ps, alpha, self->wReal__FDK, self->wImag__FDK, + self->hybOutputRealDry__FDK, self->hybOutputImagDry__FDK); + break; + case APPLY_M2: + err = SpatialDecApplyM2( + self, ps, alpha, self->wReal__FDK, self->wImag__FDK, + self->hybOutputRealDry__FDK, self->hybOutputImagDry__FDK, + self->hybOutputRealWet__FDK, self->hybOutputImagWet__FDK); + break; + default: + err = MPS_APPLY_M2_ERROR; + goto bail; + } + + if (err != MPS_OK) goto bail; + + if ((self->tempShapeConfig == 2) && (!isTwoChMode(self->upmixType))) { + SpatialDecReshapeBBEnv(self, frame, + ts); /* input: reshapeBBEnvState, + hybOutput(Real/Imag)(Dry/Wet), + hybInput(Real/Imag) */ + } /* output: hybOutput(Real/Imag)Dry */ + + /* Merge parts of the dry and wet QMF buffers. */ + if ((self->tempShapeConfig == 1) && (!isTwoChMode(self->upmixType))) { + for (ch = 0; ch < self->numOutputChannels; ch++) { + for (hyb = 0; hyb < self->tp_hybBandBorder; hyb++) { + self->hybOutputRealDry__FDK[ch][hyb] = + fAddSaturate(self->hybOutputRealDry__FDK[ch][hyb], + self->hybOutputRealWet__FDK[ch][hyb]); + self->hybOutputImagDry__FDK[ch][hyb] = + fAddSaturate(self->hybOutputImagDry__FDK[ch][hyb], + self->hybOutputImagWet__FDK[ch][hyb]); + } /* loop hyb */ + } /* loop ch */ + err = subbandTPApply( + self, frame); /* input: hStpDec, hybOutput(Real/Imag)Dry/Wet */ + /* output: hStpDec, hybOutput(Real/Imag)Dry */ + if (err != MPS_OK) goto bail; + } /* (self->tempShapeConfig == 1) */ + else { + /* The wet signal is added to the dry signal in applyM2 if GES and STP + * are disabled */ + if ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) { + int nHybBands; + nHybBands = self->hybridBands; + + for (ch = 0; ch < self->numOutputChannels; ch++) { + FIXP_DBL *RESTRICT pRealDry = self->hybOutputRealDry__FDK[ch]; + FIXP_DBL *RESTRICT pImagDry = self->hybOutputImagDry__FDK[ch]; + FIXP_DBL *RESTRICT pRealWet = self->hybOutputRealWet__FDK[ch]; + FIXP_DBL *RESTRICT pImagWet = self->hybOutputImagWet__FDK[ch]; + for (hyb = 0; hyb < nHybBands; hyb++) { + pRealDry[hyb] = fAddSaturate(pRealDry[hyb], pRealWet[hyb]); + pImagDry[hyb] = fAddSaturate(pImagDry[hyb], pImagWet[hyb]); + } /* loop hyb */ + for (; hyb < self->hybridBands; hyb++) { + pRealDry[hyb] = fAddSaturate(pRealDry[hyb], pRealWet[hyb]); + } /* loop hyb */ + } /* loop ch */ + } /* ( self->tempShapeConfig == 1 ) || ( self->tempShapeConfig == 2 ) */ + } /* !self->tempShapeConfig == 1 */ + } /* !bypassMode */ + + if ((self->phaseCoding == 1) && (bypassMode == 0)) { + /* only if bsPhaseCoding == 1 and bsResidualCoding == 0 */ + + SpatialDecApplyPhase( + self, alpha, (ts == currSlot) /* signal the last slot of the set */ + ); + } + + /* + * Synthesis Filtering + */ + + err = SpatialDecSynthesis( + self, ts_io, + self->hybOutputRealDry__FDK, /* input: hybOutput(Real/Imag)Dry */ + self->hybOutputImagDry__FDK, self->timeOut__FDK, /* output: timeOut */ + numInputChannels, mapDescr); + + if (err != MPS_OK) goto bail; + + /* + * Update parameter buffer + */ + if (ts == currSlot) { + SpatialDecBufferMatrices(self); /* input: M(1/2)param(Real/Imag) */ + /* output: M(1/2)param(Real/Imag)Prev */ + + prevSlot = currSlot; + ps++; + } /* if (ts==currSlot) */ + + } /* ts loop */ + + /* + * Save parameter states + */ + self->prevTimeSlot = prevSlot; + self->curTimeSlot = ts; + self->curPs = ps; + +bail: + + return err; +} + +SACDEC_ERROR SpatialDecApplyFrame( + spatialDec *self, + SPATIAL_BS_FRAME *frame, /* parsed frame data to be applied */ + SPATIALDEC_INPUT_MODE inputMode, PCM_MPS *inData, /* Time domain input */ + FIXP_DBL **qmfInDataReal, /* QMF domain data l/r */ + FIXP_DBL **qmfInDataImag, /* QMF domain data l/r */ + PCM_MPS *pcmOutBuf, /* MAX_OUTPUT_CHANNELS*MAX_TIME_SLOTS*NUM_QMF_BANDS] */ + UINT nSamples, UINT *pControlFlags, int numInputChannels, + const FDK_channelMapDescr *const mapDescr) { + SACDEC_ERROR err = MPS_OK; + + int fDecAndMapFrameData; + int controlFlags; + + FDK_ASSERT(self != NULL); + FDK_ASSERT(pControlFlags != NULL); + FDK_ASSERT(pcmOutBuf != NULL); + FDK_ASSERT(self->sacInDataHeadroom >= (1)); + + self->errInt = err; /* Init internal error */ + + controlFlags = *pControlFlags; + + if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) && + (self->stereoConfigIndex > 1)) { + numInputChannels = + 1; /* Do not count residual channel as input channel. It is handled + seperately. */ + } + + /* Check if input amount of channels is consistent */ + if (numInputChannels != self->numInputChannels) { + controlFlags |= MPEGS_CONCEAL; + if (numInputChannels > self->createParams.maxNumInputChannels) { + return MPS_INVALID_PARAMETER; + } + } + + self->timeOut__FDK = pcmOutBuf; + + /* Determine local function control flags */ + fDecAndMapFrameData = frame->newBsData; + + if (((fDecAndMapFrameData == + 0) /* assures that conceal flag will not be set for blind mode */ + && (self->curTimeSlot + (int)nSamples / self->qmfBands > + self->timeSlots)) || + (frame->numParameterSets == + 0)) { /* New input samples but missing side info */ + fDecAndMapFrameData = 1; + controlFlags |= MPEGS_CONCEAL; + } + + if ((fDecAndMapFrameData == 0) && + (frame->paramSlot[fMax(0, frame->numParameterSets - 1)] != + (self->timeSlots - 1) || + self->curTimeSlot > + frame->paramSlot[self->curPs])) { /* Detected faulty parameter slot + data. */ + fDecAndMapFrameData = 1; + controlFlags |= MPEGS_CONCEAL; + } + + /* Update concealment state machine */ + SpatialDecConcealment_UpdateState( + &self->concealInfo, + (controlFlags & MPEGS_CONCEAL) + ? 0 + : 1); /* convert from conceal flag to frame ok flag */ + + if (fDecAndMapFrameData) { + /* Reset spatial framing control vars */ + frame->newBsData = 0; + self->prevTimeSlot = -1; + self->curTimeSlot = 0; + self->curPs = 0; + + if (controlFlags & MPEGS_CONCEAL) { + /* Reset frame data to avoid misconfiguration. */ + SpatialDecClearFrameData(self, frame, &self->createParams); + } + + { + err = SpatialDecDecodeFrame(self, frame); /* input: ... */ + /* output: decodeAndMapFrameDATA */ + } + + if (err != MPS_OK) { + /* Rescue strategy is to apply bypass mode in order + to keep at least the downmix channels continuous. */ + controlFlags |= MPEGS_CONCEAL; + if (self->errInt == MPS_OK) { + /* store internal error befor it gets overwritten */ + self->errInt = err; + } + } + } + + err = SpatialDecApplyParameterSets( + self, frame, inputMode, inData, qmfInDataReal, qmfInDataImag, nSamples, + controlFlags | ((err == MPS_OK) ? 0 : MPEGS_BYPASSMODE), numInputChannels, + mapDescr); + if (err != MPS_OK) { + goto bail; + } + +bail: + + *pControlFlags = controlFlags; + + return err; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec.h new file mode 100644 index 0000000000000..1c3df71664fb7 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec.h @@ -0,0 +1,542 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Decoder Library structures + +*******************************************************************************/ + +#ifndef SAC_DEC_H +#define SAC_DEC_H + +#include "common_fix.h" + +#include "sac_dec_interface.h" /* library interface in ../include */ + +#include "FDK_qmf_domain.h" +#include "sac_qmf.h" +#include "FDK_bitstream.h" /* mp4 bitbuffer */ +#include "sac_calcM1andM2.h" +#include "FDK_hybrid.h" +#include "FDK_decorrelate.h" +#include "sac_reshapeBBEnv.h" + +#include "sac_dec_conceal.h" + +#include "sac_tsd.h" + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#define ICCdefault 0 +#define IPDdefault 0 +#define arbdmxGainDefault 0 +#define CPCdefault 10 +#define tttCLD1default 15 +#define tttCLD2default 0 + +#define IS_HQ_ONLY(aot) \ + ((aot) == AOT_ER_AAC_LD || (aot) == AOT_ER_AAC_ELD || (aot) == AOT_USAC || \ + (aot) == AOT_RSVD50) + +#define SCONST(x) FL2FXCONST_DBL(x) + +#define PC_NUM_BANDS (8) +#define PC_NUM_HYB_BANDS (PC_NUM_BANDS - 3 + 10) +#define ABS_THR (1e-9f * 32768 * 32768) + +#define MAX_HYBRID_BANDS (MAX_NUM_QMF_BANDS - 3 + 10) +#define HYBRID_FILTER_DELAY (6) + +#define MAX_RESIDUAL_FRAMES (4) +#define MAX_RESIDUAL_BISTREAM \ + (836) /* 48000 bps * 3 res / (8 * 44100 / 2048 ) */ +#define MAX_MDCT_COEFFS (1024) +#define SACDEC_RESIDUAL_BS_BUF_SIZE \ + (1024) /* used to setup and check residual bitstream buffer */ + +#define MAX_NUM_PARAMS (MAX_NUM_OTT + 4 * MAX_NUM_TTT + MAX_INPUT_CHANNELS) +#define MAX_NUM_PARAMETERS (MAX(MAX_NUM_PARAMS, MAX_NUM_OTT)) + +#define MAX_PARAMETER_SETS (9) + +#define MAX_M2_INPUT (MAX_OUTPUT_CHANNELS) /* 3 direct + 5 diffuse */ + +#define MAX_QMF_BANDS_TO_HYBRID \ + (3) /* 3 bands are filtered again in "40 bands" case */ +#define PROTO_LEN (13) +#define BUFFER_LEN_LF (PROTO_LEN) +#define BUFFER_LEN_HF ((PROTO_LEN - 1) / 2) + +#define MAX_NO_DECORR_CHANNELS (MAX_OUTPUT_CHANNELS) +#define HRTF_AZIMUTHS (5) + +#define MAX_NUM_OTT_AT 0 + +/* left out */ + +typedef enum { + UPMIXTYPE_BYPASS = -1, /*just bypass the input channels without processing*/ + UPMIXTYPE_NORMAL = 0 /*multichannel loudspeaker upmix with spatial data*/ +} UPMIXTYPE; + +static inline int isTwoChMode(UPMIXTYPE upmixType) { + int retval = 0; + return retval; +} + + /* left out end */ + +#define MPEGS_BYPASSMODE (0x00000001) +#define MPEGS_CONCEAL (0x00000002) + +typedef struct STP_DEC *HANDLE_STP_DEC; + +typedef struct { + SCHAR bsQuantCoarseXXXprev; + SCHAR bsQuantCoarseXXXprevParse; +} LOSSLESSSTATE; + +typedef struct { + SCHAR bsXXXDataMode[MAX_PARAMETER_SETS]; + SCHAR bsQuantCoarseXXX[MAX_PARAMETER_SETS]; + SCHAR bsFreqResStrideXXX[MAX_PARAMETER_SETS]; + SCHAR nocmpQuantCoarseXXX[MAX_PARAMETER_SETS]; + LOSSLESSSTATE *state; /* Link to persistent state information */ +} LOSSLESSDATA; + +struct SPATIAL_BS_FRAME_struct { + UCHAR bsIndependencyFlag; + UCHAR newBsData; + UCHAR numParameterSets; + + /* + If bsFramingType == 0, then the paramSlot[ps] for 0 <= ps < numParamSets is + calculated as follows: paramSlot[ps] = ceil(numSlots*(ps+1)/numParamSets) - 1 + Otherwise, it is + paramSlot[ps] = bsParamSlot[ps] + */ + INT paramSlot[MAX_PARAMETER_SETS]; + + /* These arrays contain the compact indices, only one value per pbstride, only + * paramsets actually containing data. */ + /* These values are written from the parser in ecDataDec() and read during + * decode in mapIndexData() */ + SCHAR cmpOttCLDidx[MAX_NUM_OTT + MAX_NUM_OTT_AT][MAX_PARAMETER_SETS] + [MAX_PARAMETER_BANDS]; + SCHAR cmpOttICCidx[MAX_NUM_OTT][MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]; + + /* Smoothing */ + UCHAR bsSmoothMode[MAX_PARAMETER_SETS]; + UCHAR bsSmoothTime[MAX_PARAMETER_SETS]; + UCHAR bsFreqResStrideSmg[MAX_PARAMETER_SETS]; + UCHAR bsSmgData[MAX_PARAMETER_SETS] + [MAX_PARAMETER_BANDS]; /* smoothing flags, one if band is + smoothed, otherwise zero */ + + /* Arbitrary Downmix */ + SCHAR (*cmpArbdmxGainIdx)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]; + + /* Lossless control */ + LOSSLESSDATA *CLDLosslessData; + LOSSLESSDATA *ICCLosslessData; + /* LOSSLESSDATA *ADGLosslessData; -> is stored in CLDLosslessData[offset] */ + + LOSSLESSDATA *IPDLosslessData; + SCHAR (*cmpOttIPDidx)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]; + int phaseMode; + int OpdSmoothingMode; + + UCHAR tempShapeEnableChannelGES[MAX_OUTPUT_CHANNELS]; /*!< GES side info. */ + UCHAR bsEnvShapeData[MAX_OUTPUT_CHANNELS] + [MAX_TIME_SLOTS]; /*!< GES side info (quantized). */ + + UCHAR tempShapeEnableChannelSTP[MAX_OUTPUT_CHANNELS]; /*!< STP side info. */ + + TSD_DATA TsdData[1]; /*!< TSD data structure. */ +}; + +typedef struct { + /* Lossless state */ + LOSSLESSSTATE CLDLosslessState[MAX_NUM_PARAMETERS]; + LOSSLESSSTATE ICCLosslessState[MAX_NUM_PARAMETERS]; + LOSSLESSSTATE IPDLosslessState[MAX_NUM_PARAMETERS]; +} BS_LL_STATE; + +typedef struct { + int prevParamSlot; + int prevSmgTime; + UCHAR prevSmgData[MAX_PARAMETER_BANDS]; + + FIXP_DBL opdLeftState__FDK[MAX_PARAMETER_BANDS]; + FIXP_DBL opdRightState__FDK[MAX_PARAMETER_BANDS]; + +} SMOOTHING_STATE; + +typedef struct { + FIXP_DBL alpha__FDK; + FIXP_DBL beta__FDK; + FIXP_DBL partNrgPrev__FDK[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS] + [BB_ENV_SIZE]; + FIXP_DBL normNrgPrev__FDK[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]; + FIXP_DBL frameNrgPrev__FDK[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]; + INT partNrgPrevSF[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]; + INT partNrgPrev2SF[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]; + INT normNrgPrevSF[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]; + INT frameNrgPrevSF[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]; +} RESHAPE_BBENV_STATE; + +typedef struct { + int maxNumInputChannels; + int maxNumOutputChannels; + int maxNumQmfBands; + int maxNumHybridBands; + int maxNumXChannels; + int maxNumVChannels; + int maxNumDecorChannels; + int maxNumCmplxQmfBands; + int maxNumCmplxHybBands; + int maxNumResChannels; + int bProcResidual; /* process residual */ + int maxNumResidualChannels; + int maxNumOttBoxes; + int maxNumParams; + +} SACDEC_CREATION_PARAMS; + +struct spatialDec_struct { + SACDEC_ERROR + errInt; /* Field to store internal errors. + Will be clear at the very beginning of each process call. */ + int staticDecScale; /* static scale of decoder */ + + /* GENERAL */ + int samplingFreq; /* [Hz] */ + CFG_LEVEL decoderLevel; /* 0..5 */ + CFG_EXTENT decoderMode; + CFG_BINAURAL binauralMode; + + SACDEC_CREATION_PARAMS createParams; + + int numComplexProcessingBands; + + int treeConfig; /* TREE_5151 = 5151, TREE_5152 = 5152, TREE_525 = 525, defined + in sac_bitdec.h */ + + int numInputChannels; /* 1 (M) or 2 (L,R) */ + int numOutputChannels; /* 6 for 3/2.1 (FL,FR,FC,LF,BL,BR) */ + int numOttBoxes; /* number of ott boxes */ + int numM2rows; + + int numOutputChannelsAT; /* Number of output channels after arbitrary tree + processing */ + + int quantMode; /* QUANT_FINE, QUANT_EBQ1, QUANT_EBQ2, defined in sac_bitdec.h + */ + int arbitraryDownmix; /* (arbitraryDownmix != 0) 1 arbitrary downmix data + present, 2 arbitrary downmix residual data present*/ + int residualCoding; /* (residualCoding != 0) => residual coding data present + */ + UCHAR nrResidualFrame; + UCHAR nrArbDownmixResidualFrame; + FDK_BITSTREAM **hResidualBitstreams; + int tempShapeConfig; /* */ + int decorrType; /* Indicates to use PS or none PS decorrelator. */ + int decorrConfig; /* chosen decorrelator */ + int envQuantMode; /* quantization mode of envelope reshaping data */ + + FIXP_DBL clipProtectGain__FDK; /* global gain for upmix */ + char clipProtectGainSF__FDK; /* global gain for upmix */ + + /* Currently ignoring center decorr + numVChannels = numDirektSignals + numDecorSignals */ + int numDirektSignals; /* needed for W, Number of direkt signals 515 -> 1 525 + -> 3 */ + int wStartResidualIdx; /* Where to start read residuals for W, = 0 for 515, = + 1 for 525 since one residual is used in V */ + int numDecorSignals; /* needed for W, Number of residual and decorrelated + signals, = 2, 3 for center deccorelation*/ + int numVChannels; /* direct signals + decorelator signals */ + int numXChannels; /* direct input signals + TTT-residuals */ + + int timeSlots; /* length of spatial frame in QMF samples */ + int curTimeSlot; /* pointer to the current time slot used for hyperframing */ + int prevTimeSlot; /* */ + int curPs; + int frameLength; /* number of output waveform samples/channel/frame */ + UPMIXTYPE upmixType; + int partiallyComplex; + int useFDreverb; + + int bShareDelayWithSBR; + + int tp_hybBandBorder; /* Hybrid band indicating the HP filter cut-off. */ + + /* FREQUENCY MAPPING */ + int qmfBands; + int hybridBands; + const SCHAR *kernels; /* Mapping hybrid band to parameter band. */ + + int TsdTs; /**< TSD QMF slot counter 0<= ts < numSlots */ + + int *param2hyb; /* Mapping parameter bands to hybrid bands */ + int kernels_width[MAX_PARAMETER_BANDS]; /* Mapping parmeter band to hybrid + band offsets. */ + + /* Residual coding */ + int residualSamplingFreq; + UCHAR residualPresent[MAX_NUM_OTT + MAX_NUM_TTT]; + UCHAR residualBands[MAX_NUM_OTT + MAX_NUM_TTT]; /* 0, if no residual data + present for this box */ + UCHAR residualQMFBands[MAX_NUM_OTT + MAX_NUM_TTT]; /* needed for optimized + mdct2qmf calculation */ + SPATIAL_SPECIFIC_CONFIG *pConfigCurrent; + + int arbdmxFramesPerSpatialFrame; + int arbdmxUpdQMF; + + int numParameterBands; /* Number of parameter bands 40, 28, 20, 14, 10, ... + .*/ + int bitstreamParameterBands; + int *numOttBands; /* number of bands for each ott, is != numParameterBands for + LFEs */ + + /* 1 MAPPING */ + UCHAR extendFrame; + UCHAR numParameterSetsPrev; + + int *smgTime; + UCHAR **smgData; + + /* PARAMETER DATA decoded and dequantized */ + + /* Last parameters from prev frame required during decode in mapIndexData() + * and not touched during parse */ + SCHAR **ottCLDidxPrev; + SCHAR **ottICCidxPrev; + SCHAR **arbdmxGainIdxPrev; + SCHAR **ottIPDidxPrev; + SCHAR ***outIdxData; /* is this really persistent memory ? */ + + /* State mem required during parse in SpatialDecParseFrameData() */ + SCHAR **cmpOttCLDidxPrev; + SCHAR **cmpOttICCidxPrev; + SCHAR ***ottICCdiffidx; + SCHAR **cmpOttIPDidxPrev; + + /* State mem required in parseArbitraryDownmixData */ + SCHAR **cmpArbdmxGainIdxPrev; + + SCHAR ***ottCLD__FDK; + SCHAR ***ottICC__FDK; + + SCHAR ***arbdmxGain__FDK; /* Holds the artistic downmix correction index.*/ + + FIXP_DBL *arbdmxAlpha__FDK; + FIXP_DBL *arbdmxAlphaPrev__FDK; + + UCHAR stereoConfigIndex; + int highRateMode; + + int phaseCoding; + + SCHAR ***ottIPD__FDK; + + FIXP_DBL PhaseLeft__FDK[MAX_PARAMETER_BANDS]; + FIXP_DBL PhaseRight__FDK[MAX_PARAMETER_BANDS]; + FIXP_DBL PhasePrevLeft__FDK[MAX_PARAMETER_BANDS]; + FIXP_DBL PhasePrevRight__FDK[MAX_PARAMETER_BANDS]; + int numOttBandsIPD; + + /* GAIN MATRICIES FOR CURRENT and PREVIOUS PARMATER SET(s)*/ + FIXP_DBL ***M2Real__FDK; + FIXP_DBL ***M2Imag__FDK; + FIXP_DBL ***M2RealPrev__FDK; + FIXP_DBL ***M2ImagPrev__FDK; + + /* INPUT SIGNALS */ + FIXP_DBL ***qmfInputRealDelayBuffer__FDK; + FIXP_DBL ***qmfInputImagDelayBuffer__FDK; + + int pc_filterdelay; /* additional delay to align HQ with LP before hybird + analysis */ + int qmfInputDelayBufPos; + FIXP_DBL **qmfInputReal__FDK; + FIXP_DBL **qmfInputImag__FDK; + + FIXP_DBL **hybInputReal__FDK; + FIXP_DBL **hybInputImag__FDK; + + FIXP_DBL **binInputReverb; + + FIXP_DBL binGain, reverbGain; + FIXP_DBL binCenterGain, reverbCenterGain; + + /* RESIDUAL SIGNALS */ + + FIXP_DBL ***qmfResidualReal__FDK; + FIXP_DBL ***qmfResidualImag__FDK; + + FIXP_DBL **hybResidualReal__FDK; + FIXP_DBL **hybResidualImag__FDK; + + int qmfOutputRealDryDelayBufPos; + FIXP_DBL ***qmfOutputRealDryDelayBuffer__FDK; + FIXP_DBL ***qmfOutputImagDryFilterBuffer__FDK; + FIXP_DBL *qmfOutputImagDryFilterBufferBase__FDK; + + /* TEMPORARY SIGNALS */ + + FIXP_DBL **wReal__FDK; + FIXP_DBL **wImag__FDK; + + /* OUTPUT SIGNALS */ + FIXP_DBL **hybOutputRealDry__FDK; + FIXP_DBL **hybOutputImagDry__FDK; + FIXP_DBL **hybOutputRealWet__FDK; + FIXP_DBL **hybOutputImagWet__FDK; + PCM_MPS *timeOut__FDK; + + HANDLE_FDK_QMF_DOMAIN pQmfDomain; + + FDK_ANA_HYB_FILTER + *hybridAnalysis; /*!< pointer Analysis hybrid filterbank array. */ + FDK_SYN_HYB_FILTER + *hybridSynthesis; /*!< pointer Synthesis hybrid filterbank array. */ + FIXP_DBL ** + pHybridAnaStatesLFdmx; /*!< pointer to analysis hybrid filter states LF */ + FIXP_DBL ** + pHybridAnaStatesHFdmx; /*!< pointer to analysis hybrid filter states HF */ + FIXP_DBL ** + pHybridAnaStatesLFres; /*!< pointer to analysis hybrid filter states LF */ + FIXP_DBL ** + pHybridAnaStatesHFres; /*!< pointer to analysis hybrid filter states HF */ + + DECORR_DEC *apDecor; /*!< pointer decorrelator array. */ + FIXP_DBL **pDecorBufferCplx; + + SMOOTHING_STATE *smoothState; /*!< Pointer to smoothing states. */ + + RESHAPE_BBENV_STATE *reshapeBBEnvState; /*!< GES handle. */ + SCHAR row2channelDmxGES[MAX_OUTPUT_CHANNELS]; + + HANDLE_STP_DEC hStpDec; /*!< STP handle. */ + + const UCHAR *pActivM2ParamBands; + + int bOverwriteM1M2prev; /* Overwrite previous M2/M2 params with first set of + new frame after SSC change (aka + decodeAfterConfigHasChangedFlag). */ + SpatialDecConcealmentInfo concealInfo; + + INT sacInDataHeadroom; /* Headroom of the SAC input time signal to prevent + clipping */ +}; + +#define SACDEC_SYNTAX_MPS 1 +#define SACDEC_SYNTAX_USAC 2 +#define SACDEC_SYNTAX_RSVD50 4 +#define SACDEC_SYNTAX_L2 8 +#define SACDEC_SYNTAX_L3 16 +#define SACDEC_SYNTAX_LD 32 + +static inline int GetProcBand(spatialDec_struct *self, int qs) { + return self->kernels[qs]; +} + +#endif /* SAC_DEC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_conceal.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_conceal.cpp new file mode 100644 index 0000000000000..dfeef7b2d48d6 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_conceal.cpp @@ -0,0 +1,392 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): Christian Ertel, Christian Griebel + + Description: SAC Dec error concealment + +*******************************************************************************/ + +#include "sac_dec_conceal.h" + +void SpatialDecConcealment_Init(SpatialDecConcealmentInfo *info, + const UINT resetFlags) { + FDK_ASSERT(info != NULL); + + if (resetFlags & MPEGS_CONCEAL_RESET_STATE) { + info->concealState = SpatialDecConcealState_Init; + /* Frame counters will be initialized implicitely in function + * SpatialDecConcealment_UpdateState(). */ + } + + if (resetFlags & MPEGS_CONCEAL_RESET_PARAMETER) { + /* Set default params */ + info->concealParams.method = MPEGS_CONCEAL_DEFAULT_METHOD; + info->concealParams.numKeepFrames = MPEGS_CONCEAL_DEFAULT_NUM_KEEP_FRAMES; + info->concealParams.numFadeOutFrames = + MPEGS_CONCEAL_DEFAULT_FADE_OUT_SLOPE_LENGTH; + info->concealParams.numFadeInFrames = + MPEGS_CONCEAL_DEFAULT_FADE_IN_SLOPE_LENGTH; + info->concealParams.numReleaseFrames = + MPEGS_CONCEAL_DEFAULT_NUM_RELEASE_FRAMES; + } + + return; +} + +int SpatialDecConcealment_Apply( + SpatialDecConcealmentInfo *info, + const SCHAR (*cmpIdxData)[MAX_PARAMETER_BANDS], SCHAR **diffIdxData, + SCHAR * + idxPrev, /* char + idxPrev[SPATIALDEC_MAX_NUM_OTT][SPATIALDEC_MAX_PARAMETER_BANDS], + */ + SCHAR *bsXXXDataMode, const int startBand, const int stopBand, + const SCHAR defaultValue, const int paramType, const int numParamSets) { + int appliedProcessing = 0; + int band, dataMode = -1; + + FDK_ASSERT(info != NULL); + FDK_ASSERT(cmpIdxData != NULL); + FDK_ASSERT(idxPrev != NULL); + FDK_ASSERT(bsXXXDataMode != NULL); + + /* Processing depends only on the internal state */ + switch (info->concealState) { + case SpatialDecConcealState_Init: + dataMode = 0; /* default */ + break; + + case SpatialDecConcealState_Ok: + /* Nothing to do */ + break; + + case SpatialDecConcealState_Keep: + dataMode = 1; /* keep */ + break; + + case SpatialDecConcealState_FadeToDefault: { + /* Start simple fade out */ + FIXP_DBL fac = fDivNorm(info->cntStateFrames + 1, + info->concealParams.numFadeOutFrames + 1); + + for (band = startBand; band < stopBand; band += 1) { + /* idxPrev = fac * defaultValue + (1-fac) * idxPrev; */ + idxPrev[band] = + fMultI(fac, defaultValue - idxPrev[band]) + idxPrev[band]; + } + dataMode = 1; /* keep */ + appliedProcessing = 1; + } break; + + case SpatialDecConcealState_Default: + for (band = startBand; band < stopBand; band += 1) { + idxPrev[band] = defaultValue; + } + dataMode = 1; /* keep */ + appliedProcessing = 1; + break; + + case SpatialDecConcealState_FadeFromDefault: { + FIXP_DBL fac = fDivNorm(info->cntValidFrames + 1, + info->concealParams.numFadeInFrames + 1); + + for (band = startBand; band < stopBand; band += 1) { + /* idxPrev = fac * cmpIdxData + (1-fac) * defaultValue; */ + idxPrev[band] = + fMultI(fac, cmpIdxData[numParamSets - 1][band] - defaultValue) + + defaultValue; + } + dataMode = 1; /* keep */ + appliedProcessing = 1; + } break; + + default: + FDK_ASSERT(0); /* All valid states shall be handled above. */ + break; + } + + if (dataMode >= 0) { + int i; + for (i = 0; i < numParamSets; i += 1) { + bsXXXDataMode[i] = dataMode; + if (diffIdxData != NULL) { + for (band = startBand; band < stopBand; band += 1) { + diffIdxData[i][band] = 0; + } + } + } + } + + return appliedProcessing; +} + +void SpatialDecConcealment_UpdateState(SpatialDecConcealmentInfo *info, + const int frameOk) { + FDK_ASSERT(info != NULL); + + if (frameOk) { + info->cntValidFrames += 1; + } else { + info->cntValidFrames = 0; + } + + switch (info->concealState) { + case SpatialDecConcealState_Init: + if (frameOk) { + /* NEXT STATE: Ok */ + info->concealState = SpatialDecConcealState_Ok; + info->cntStateFrames = 0; + } + break; + + case SpatialDecConcealState_Ok: + if (!frameOk) { + /* NEXT STATE: Keep */ + info->concealState = SpatialDecConcealState_Keep; + info->cntStateFrames = 0; + } + break; + + case SpatialDecConcealState_Keep: + info->cntStateFrames += 1; + if (frameOk) { + /* NEXT STATE: Ok */ + info->concealState = SpatialDecConcealState_Ok; + } else { + if (info->cntStateFrames >= info->concealParams.numKeepFrames) { + if (info->concealParams.numFadeOutFrames == 0) { + /* NEXT STATE: Default */ + info->concealState = SpatialDecConcealState_Default; + } else { + /* NEXT STATE: Fade to default */ + info->concealState = SpatialDecConcealState_FadeToDefault; + info->cntStateFrames = 0; + } + } + } + break; + + case SpatialDecConcealState_FadeToDefault: + info->cntStateFrames += 1; + if (info->cntValidFrames > 0) { + /* NEXT STATE: Fade in from default */ + info->concealState = SpatialDecConcealState_FadeFromDefault; + info->cntStateFrames = 0; + } else { + if (info->cntStateFrames >= info->concealParams.numFadeOutFrames) { + /* NEXT STATE: Default */ + info->concealState = SpatialDecConcealState_Default; + } + } + break; + + case SpatialDecConcealState_Default: + if (info->cntValidFrames > 0) { + if (info->concealParams.numFadeInFrames == 0) { + /* NEXT STATE: Ok */ + info->concealState = SpatialDecConcealState_Ok; + } else { + /* NEXT STATE: Fade in from default */ + info->concealState = SpatialDecConcealState_FadeFromDefault; + info->cntValidFrames = 0; + } + } + break; + + case SpatialDecConcealState_FadeFromDefault: + info->cntValidFrames += 1; + if (frameOk) { + if (info->cntValidFrames >= info->concealParams.numFadeInFrames) { + /* NEXT STATE: Ok */ + info->concealState = SpatialDecConcealState_Ok; + } + } else { + /* NEXT STATE: Fade to default */ + info->concealState = SpatialDecConcealState_FadeToDefault; + info->cntStateFrames = 0; + } + break; + + default: + FDK_ASSERT(0); /* All valid states should be handled above! */ + break; + } +} + +SACDEC_ERROR SpatialDecConcealment_SetParam(SpatialDecConcealmentInfo *self, + const SAC_DEC_CONCEAL_PARAM param, + const INT value) { + SACDEC_ERROR err = MPS_OK; + + switch (param) { + case SAC_DEC_CONCEAL_METHOD: + switch ((SpatialDecConcealmentMethod)value) { + case SAC_DEC_CONCEAL_WITH_ZERO_VALUED_OUTPUT: + case SAC_DEC_CONCEAL_BY_FADING_PARAMETERS: + break; + default: + err = MPS_INVALID_PARAMETER; + goto bail; + } + if (self != NULL) { + /* store parameter value */ + self->concealParams.method = (SpatialDecConcealmentMethod)value; + } else { + err = MPS_INVALID_HANDLE; + goto bail; + } + break; + case SAC_DEC_CONCEAL_NUM_KEEP_FRAMES: + if (value < 0) { + err = MPS_INVALID_PARAMETER; + goto bail; + } + if (self != NULL) { + /* store parameter value */ + self->concealParams.numKeepFrames = (UINT)value; + } else { + err = MPS_INVALID_HANDLE; + goto bail; + } + break; + case SAC_DEC_CONCEAL_FADE_OUT_SLOPE_LENGTH: + if (value < 0) { + err = MPS_INVALID_PARAMETER; + goto bail; + } + if (self != NULL) { + /* store parameter value */ + self->concealParams.numFadeOutFrames = (UINT)value; + } else { + err = MPS_INVALID_HANDLE; + goto bail; + } + break; + case SAC_DEC_CONCEAL_FADE_IN_SLOPE_LENGTH: + if (value < 0) { + err = MPS_INVALID_PARAMETER; + goto bail; + } + if (self != NULL) { + /* store parameter value */ + self->concealParams.numFadeInFrames = (UINT)value; + } else { + err = MPS_INVALID_HANDLE; + goto bail; + } + break; + case SAC_DEC_CONCEAL_NUM_RELEASE_FRAMES: + if (value < 0) { + err = MPS_INVALID_PARAMETER; + goto bail; + } + if (self != NULL) { + /* store parameter value */ + self->concealParams.numReleaseFrames = (UINT)value; + } else { + err = MPS_INVALID_HANDLE; + goto bail; + } + break; + default: + err = MPS_INVALID_PARAMETER; + goto bail; + } + +bail: + return err; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_conceal.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_conceal.h new file mode 100644 index 0000000000000..27f52490851dc --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_conceal.h @@ -0,0 +1,187 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): Christian Ertel, Christian Griebel + + Description: SAC Dec error concealment + +*******************************************************************************/ + +#ifndef SAC_DEC_CONCEAL_H +#define SAC_DEC_CONCEAL_H + +#include "sac_dec_interface.h" + +/* Modules dynamic parameters: */ +typedef enum { + SAC_DEC_CONCEAL_METHOD = 0, + SAC_DEC_CONCEAL_NUM_KEEP_FRAMES, + SAC_DEC_CONCEAL_FADE_OUT_SLOPE_LENGTH, + SAC_DEC_CONCEAL_FADE_IN_SLOPE_LENGTH, + SAC_DEC_CONCEAL_NUM_RELEASE_FRAMES + +} SAC_DEC_CONCEAL_PARAM; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* sac_dec_interface.h */ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - */ +typedef enum { + SAC_DEC_CONCEAL_WITH_ZERO_VALUED_OUTPUT = 0, + SAC_DEC_CONCEAL_BY_FADING_PARAMETERS = 1 + +} SpatialDecConcealmentMethod; +/* - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* Default dynamic parameter values: */ +#define MPEGS_CONCEAL_DEFAULT_METHOD SAC_DEC_CONCEAL_BY_FADING_PARAMETERS +#define MPEGS_CONCEAL_DEFAULT_NUM_KEEP_FRAMES (10) +#define MPEGS_CONCEAL_DEFAULT_FADE_OUT_SLOPE_LENGTH (5) +#define MPEGS_CONCEAL_DEFAULT_FADE_IN_SLOPE_LENGTH (5) +#define MPEGS_CONCEAL_DEFAULT_NUM_RELEASE_FRAMES (3) + +typedef enum { + SpatialDecConcealState_Init = 0, + SpatialDecConcealState_Ok, + SpatialDecConcealState_Keep, + SpatialDecConcealState_FadeToDefault, + SpatialDecConcealState_Default, + SpatialDecConcealState_FadeFromDefault + +} SpatialDecConcealmentState; + +typedef struct { + SpatialDecConcealmentMethod method; + + UINT numKeepFrames; + UINT numFadeOutFrames; + UINT numFadeInFrames; + UINT numReleaseFrames; + +} SpatialDecConcealmentParams; + +typedef struct { + SpatialDecConcealmentParams concealParams; /* User set params */ + SpatialDecConcealmentState + concealState; /* State of internal state machine (fade-in/out etc) */ + + UINT cntStateFrames; /* Counter for fade-in/out handling */ + UINT cntValidFrames; /* Counter for the number of consecutive good frames*/ + +} SpatialDecConcealmentInfo; + +/* Module reset flags */ +#define MPEGS_CONCEAL_RESET_STATE (0x01) +#define MPEGS_CONCEAL_RESET_PARAMETER (0x02) +#define MPEGS_CONCEAL_RESET_ALL (0xFF) + +void SpatialDecConcealment_Init(SpatialDecConcealmentInfo *info, + const UINT resetFlags); + +int SpatialDecConcealment_Apply(SpatialDecConcealmentInfo *info, + const SCHAR (*cmpIdxData)[MAX_PARAMETER_BANDS], + SCHAR **diffIdxData, SCHAR *idxPrev, + SCHAR *bsXXXDataMode, const int startBand, + const int stopBand, const SCHAR defaultValue, + const int paramType, const int numParamSets); + +void SpatialDecConcealment_UpdateState(SpatialDecConcealmentInfo *info, + const int frameOk); + +SACDEC_ERROR SpatialDecConcealment_SetParam(SpatialDecConcealmentInfo *info, + const SAC_DEC_CONCEAL_PARAM param, + const INT value); + +#endif /* SAC_DEC_CONCEAL_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_interface.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_interface.h new file mode 100644 index 0000000000000..05a9a75353782 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_interface.h @@ -0,0 +1,335 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Decoder Library Interface + +*******************************************************************************/ + +#ifndef SAC_DEC_INTERFACE_H +#define SAC_DEC_INTERFACE_H + +#include "common_fix.h" +#include "FDK_audio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sac_dec_errorcodes.h" +#include "sac_dec_ssc_struct.h" + +/** + * \brief Baseline MPEG-Surround profile Level 1-5. + */ +typedef enum { + DECODER_LEVEL_0 = 0, /*!< Level 0: dummy level; 212 only */ + DECODER_LEVEL_6 = 6 /*!< Level 6: no support */ +} CFG_LEVEL; + +/* + * \brief Number of output channels restriction. + */ +typedef enum { + OUTPUT_CHANNELS_DEFAULT, /*!< Default configuration depending on Decoder Level + */ + OUTPUT_CHANNELS_2_0, /*!< Limitation to stereo output */ + OUTPUT_CHANNELS_5_1 /*!< Limitation to 5.1 output */ +} CFG_RESTRICTION; + +/* + * \brief Supported decoder mode. + */ +typedef enum { + EXT_HQ_ONLY = 0, /*!< High Quality processing only */ + EXT_LP_ONLY = 1, /*!< Low Power procesing only */ + EXT_HQ_AND_LP = 2 /*!< Support both HQ and LP processing */ +} CFG_EXTENT; + +/* + * \brief Supported binaural mode. + */ +typedef enum { + BINAURAL_NONE = -1 /*!< No binaural procesing supported */ +} CFG_BINAURAL; + +/** + * \brief Decoder configuration structure. + * + * These structure contains all parameters necessary for decoder open function. + * The configuration specifies the functional range of the decoder instance. + */ +typedef struct { + CFG_LEVEL decoderLevel; + CFG_EXTENT decoderMode; + CFG_RESTRICTION maxNumOutputChannels; + CFG_BINAURAL binauralMode; + +} SPATIAL_DEC_CONFIG; + +typedef enum { + INPUTMODE_QMF = 1000, + INPUTMODE_QMF_SBR = 1001, + INPUTMODE_TIME = 1002 +} SPATIALDEC_INPUT_MODE; + +/** + * \brief MPEG Surround upmix type mode. + **/ +typedef enum { + UPMIX_TYPE_BYPASS = + -1, /*!< Bypass the downmix channels from the core decoder. */ + UPMIX_TYPE_NORMAL = 0 /*!< Multi channel output. */ + +} SPATIAL_DEC_UPMIX_TYPE; + +/** + * \brief Dynamic decoder parameters. + */ +typedef struct { + /* Basics */ + UCHAR outputMode; + UCHAR blindEnable; + UCHAR bypassMode; + + /* Error concealment */ + UCHAR concealMethod; + UINT concealNumKeepFrames; + UINT concealFadeOutSlopeLength; + UINT concealFadeInSlopeLength; + UINT concealNumReleaseFrames; + +} SPATIALDEC_PARAM; + +/** + * \brief Flags which control the initialization + **/ +typedef enum { + MPEGS_INIT_NONE = 0x00000000, /*!< Indicates no initialization */ + + MPEGS_INIT_CONFIG = 0x00000010, /*!< Indicates a configuration change due to + SSC value changes */ + + MPEGS_INIT_STATES_ANA_QMF_FILTER = + 0x00000100, /*!< Controls the initialization of the analysis qmf filter + states */ + MPEGS_INIT_STATES_SYN_QMF_FILTER = + 0x00000200, /*!< Controls the initialization of the synthesis qmf filter + states */ + MPEGS_INIT_STATES_ANA_HYB_FILTER = 0x00000400, /*!< Controls the + initialization of the + analysis hybrid filter + states */ + MPEGS_INIT_STATES_DECORRELATOR = + 0x00000800, /*!< Controls the initialization of the decorrelator states */ + MPEGS_INIT_STATES_M1M2 = 0x00002000, /*!< Controls the initialization of the + history in m1 and m2 parameter + calculation */ + MPEGS_INIT_STATES_GES = 0x00004000, /*!< Controls the initialization of the + history in the ges calculation */ + MPEGS_INIT_STATES_REVERB = + 0x00008000, /*!< Controls the initialization of the reverb states */ + MPEGS_INIT_STATES_PARAM = + 0x00020000, /*!< Controls the initialization of the history of all other + parameter */ + MPEGS_INIT_STATES_ERROR_CONCEALMENT = + 0x00080000, /*!< Controls the initialization of the error concealment + module state */ + MPEGS_INIT_PARAMS_ERROR_CONCEALMENT = 0x00200000 /*!< Controls the + initialization of the + whole error concealment + parameter set */ + +} MPEGS_INIT_CTRL_FLAGS; + +#define MASK_MPEGS_INIT_ALL_STATES (0x000FFF00) +#define MASK_MPEGS_INIT_ALL_PARAMS (0x00F00000) + +typedef struct spatialDec_struct spatialDec, *HANDLE_SPATIAL_DEC; + +typedef struct SPATIAL_BS_FRAME_struct SPATIAL_BS_FRAME; + +typedef struct { + UINT sizePersistent; /* persistent memory */ + UINT sizeFastPersistent; /* fast persistent memory */ + +} MEM_REQUIREMENTS; + +#define PCM_MPS LONG +#define PCM_MPSF FIXP_DBL + +#define FIXP_DBL2PCM_MPS(x) ((LONG)(x)) + +/* exposed functions (library interface) */ + +int FDK_SpatialDecCompareSpatialSpecificConfigHeader( + SPATIAL_SPECIFIC_CONFIG *pSsc1, SPATIAL_SPECIFIC_CONFIG *pSsc2); + +int FDK_SpatialDecInitDefaultSpatialSpecificConfig( + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + AUDIO_OBJECT_TYPE coreCodec, int coreChannels, int samplingFreq, + int nTimeSlots, int decoderLevel, int isBlind); + +spatialDec *FDK_SpatialDecOpen(const SPATIAL_DEC_CONFIG *config, + int stereoConfigIndex); + +/** + * \brief Initialize state variables of the MPS parser + */ +void SpatialDecInitParserContext(spatialDec *self); + +/** + * \brief Initialize state of MPS decoder. This may happen after the first parse + * operation. + */ +SACDEC_ERROR FDK_SpatialDecInit(spatialDec *self, SPATIAL_BS_FRAME *frame, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + int nQmfBands, + SPATIAL_DEC_UPMIX_TYPE const upmixType, + SPATIALDEC_PARAM *pUserParams, + UINT initFlags /* MPEGS_INIT_CTRL_FLAGS */ +); + +/** + * \brief Apply decoded MPEG Surround parameters to time domain or QMF down mix + * data. + * \param self spatial decoder handle. + * \param inData Pointer to time domain input down mix data if any. + * \param qmfInDataReal Pointer array of QMF domain down mix input data (real + * part). + * \param qmfInDataImag Pointer array of QMF domain down mix input data + * (imaginary part). + * \param pcmOutBuf Pointer to a time domain buffer were the upmixed output data + * will be stored into. + * \param nSamples Amount of audio samples per channel of down mix input data + * (frame length). + * \param pControlFlags pointer to control flags field; input/output. + * \param numInputChannels amount of down mix input channels. Might not match + * the current tree config, useful for internal sanity checks and bypass mode. + * \param channelMapping array containing the desired output channel ordering to + * transform MPEG PCE style ordering to any other channel ordering. First + * dimension is the total channel count. + */ +SACDEC_ERROR SpatialDecApplyFrame( + spatialDec *self, SPATIAL_BS_FRAME *frame, SPATIALDEC_INPUT_MODE inputMode, + PCM_MPS *inData, /* Time domain input */ + FIXP_DBL **qmfInDataReal, /* interleaved l/r */ + FIXP_DBL **qmfInDataImag, /* interleaved l/r */ + PCM_MPS *pcmOutBuf, /* MAX_OUTPUT_CHANNELS*MAX_TIME_SLOTS*NUM_QMF_BANDS] */ + UINT nSamples, UINT *pControlFlags, int numInputChannels, + const FDK_channelMapDescr *const mapDescr); + +/** + * \brief Fill given arrays with audio channel types and indices. + * \param self spatial decoder handle. + * \param channelType array where corresponding channel types fr each output + * channels are stored into. + * \param channelIndices array where corresponding channel type indices fr each + * output channels are stored into. + */ +void SpatialDecChannelProperties(spatialDec *self, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const FDK_channelMapDescr *const mapDescr); + +void FDK_SpatialDecClose(spatialDec *self); + +#ifdef __cplusplus +} +#endif + +#endif /* SAC_DEC_INTERFACE_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_lib.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_lib.cpp new file mode 100644 index 0000000000000..d30131ff0fe30 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_lib.cpp @@ -0,0 +1,2014 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Decoder Library Interface + +*******************************************************************************/ + +#include "sac_dec_lib.h" +#include "sac_dec_interface.h" +#include "sac_dec.h" +#include "sac_bitdec.h" +#include "FDK_matrixCalloc.h" + +#define MPS_DATA_BUFFER_SIZE (2048) + +/** + * \brief MPEG Surround data indication. + **/ +typedef enum { + MPEGS_ANCTYPE_FRAME = 0, /*!< MPEG Surround frame, see ISO/IEC 23003-1 */ + MPEGS_ANCTYPE_HEADER_AND_FRAME = 1, /*!< MPEG Surround header and MPEG + Surround frame, see ISO/IEC 23003-1 */ + MPEGS_ANCTYPE_RESERVED_1 = 2, /*!< reserved, see ISO/IEC 23003-1 */ + MPEGS_ANCTYPE_RESERVED_2 = 3 /*!< reserved, see ISO/IEC 23003-1*/ +} MPEGS_ANCTYPE; + +/** + * \brief MPEG Surround data segment indication. + **/ +typedef enum { + MPEGS_CONTINUE = 0, /*!< Indicates if data segment continues a data block. */ + MPEGS_STOP = 1, /*!< Indicates if data segment ends a data block. */ + MPEGS_START = 2, /*!< Indicates if data segment begins a data block. */ + MPEGS_START_STOP = + 3 /*!< Indicates if data segment begins and ends a data block. */ +} MPEGS_ANCSTARTSTOP; + +/** + * \brief MPEG Surround synchronizaiton state. + * + * CAUTION: Changing the enumeration values can break the sync mechanism + *because it is based on comparing the state values. + **/ +typedef enum { + MPEGS_SYNC_LOST = + 0, /*!< Indicates lost sync because of current discontinuity. */ + MPEGS_SYNC_FOUND = 1, /*!< Parsed a valid header and (re)intialization was + successfully completed. */ + MPEGS_SYNC_COMPLETE = 2 /*!< In sync and continuous. Found an independent + frame in addition to MPEGS_SYNC_FOUND. + Precondition: MPEGS_SYNC_FOUND. */ +} MPEGS_SYNCSTATE; + +/** + * \brief MPEG Surround operation mode. + **/ +typedef enum { + MPEGS_OPMODE_EMM = 0, /*!< Mode: Enhanced Matrix Mode (Blind) */ + MPEGS_OPMODE_MPS_PAYLOAD = 1, /*!< Mode: Normal, Stereo or Binaural */ + MPEGS_OPMODE_NO_MPS_PAYLOAD = 2 /*!< Mode: no MPEG Surround payload */ +} MPEGS_OPMODE; + +/** + * \brief MPEG Surround init flags. + **/ +typedef enum { + MPEGS_INIT_OK = 0x00000000, /*!< indicate correct initialization */ + MPEGS_INIT_ENFORCE_REINIT = + 0x00000001, /*!< indicate complete initialization */ + + MPEGS_INIT_CHANGE_OUTPUT_MODE = + 0x00000010, /*!< indicate change of the output mode */ + MPEGS_INIT_CHANGE_PARTIALLY_COMPLEX = + 0x00000020, /*!< indicate change of low power/high quality */ + MPEGS_INIT_CHANGE_TIME_FREQ_INTERFACE = + 0x00000040, /*!< indicate change of qmf/time interface */ + MPEGS_INIT_CHANGE_HEADER = 0x00000080, /*!< indicate change of header */ + + MPEGS_INIT_ERROR_PAYLOAD = + 0x00000100, /*!< indicate payload/ancType/ancStartStop error */ + + MPEGS_INIT_BS_INTERRUPTION = + 0x00001000, /*!< indicate bitstream interruption */ + MPEGS_INIT_CLEAR_HISTORY = + 0x00002000, /*!< indicate that all states shall be cleared */ + + /* Re-initialization of submodules */ + + MPEGS_INIT_CHANGE_CONCEAL_PARAMS = 0x00100000, /*!< indicate a change of at + least one error concealment + param */ + + /* No re-initialization needed, currently not used */ + MPEGS_INIT_CHANGE_BYPASS_MODE = + 0x01000000, /*!< indicate change of bypass mode */ + + /* Re-initialization needed, currently not used */ + MPEGS_INIT_ERROR_ANC_TYPE = 0x10000000, /*!< indicate ancType error*/ + MPEGS_INIT_ERROR_ANC_STARTSTOP = + 0x20000000 /*!< indicate ancStartStop error */ +} MPEGS_INIT_FLAGS; + +struct MpegSurroundDecoder { + HANDLE_FDK_QMF_DOMAIN pQmfDomain; + UCHAR mpsData[MPS_DATA_BUFFER_SIZE]; /* Buffer for MPS payload accross more + than one segment */ + INT mpsDataBits; /* Amount of bits in mpsData */ + /* MPEG Surround decoder */ + SPATIAL_SPECIFIC_CONFIG spatialSpecificConfig[1]; /* SSC delay line which is + used during decoding */ + spatialDec *pSpatialDec; + SPATIAL_SPECIFIC_CONFIG + spatialSpecificConfigBackup; /* SSC used while parsing */ + + /* Creation parameter */ + UCHAR mpegSurroundDecoderLevel; + /* Run-time parameter */ + UCHAR mpegSurroundSscIsGlobalCfg; /* Flag telling that the SSC + (::spatialSpecificConfig) is a + out-of-band configuration. */ + UCHAR mpegSurroundUseTimeInterface; + + SPATIAL_BS_FRAME + bsFrames[1]; /* Bitstream Structs that contain data read from the + SpatialFrame() bitstream element */ + BS_LL_STATE llState; /* Bit stream parser state memory */ + UCHAR bsFrameParse; /* Current parse frame context index */ + UCHAR bsFrameDecode; /* Current decode/apply frame context index */ + UCHAR bsFrameDelay; /* Amount of frames delay between parsing and processing. + Required i.e. for interpolation error concealment. */ + + /* User prameters */ + SPATIALDEC_PARAM mpegSurroundUserParams; + + /* Internal flags */ + SPATIAL_DEC_UPMIX_TYPE upmixType; + int initFlags[1]; + MPEGS_ANCSTARTSTOP ancStartStopPrev; + MPEGS_SYNCSTATE fOnSync[1]; + + /* Inital decoder configuration */ + SPATIAL_DEC_CONFIG decConfig; +}; + +SACDEC_ERROR +static sscCheckOutOfBand(const SPATIAL_SPECIFIC_CONFIG *pSsc, + const INT coreCodec, const INT sampleRate, + const INT frameSize); + +static SACDEC_ERROR sscParseCheck(const SPATIAL_SPECIFIC_CONFIG *pSsc); + +/** + * \brief Get the number of QMF bands from the sampling frequency (in Hz) + **/ +static int mpegSurroundDecoder_GetNrOfQmfBands( + const SPATIAL_SPECIFIC_CONFIG *pSsc, UINT sampleRate) { + UINT samplingFrequency = sampleRate; + int qmfBands = 64; + + if (pSsc != NULL) { + switch (pSsc->coreCodec) { + case AOT_USAC: + if ((pSsc->stereoConfigIndex == 3)) { + static const UCHAR mapIdx2QmfBands[3] = {24, 32, 16}; + FDK_ASSERT((pSsc->coreSbrFrameLengthIndex >= 2) && + (pSsc->coreSbrFrameLengthIndex <= 4)); + qmfBands = mapIdx2QmfBands[pSsc->coreSbrFrameLengthIndex - 2]; + } + return qmfBands; + default: + samplingFrequency = pSsc->samplingFreq; + break; + } + } + + /* number of QMF bands depend on sampling frequency, see FDIS 23003-1:2006 + * Chapter 6.3.3 */ + if (samplingFrequency < 27713) { + qmfBands = 32; + } + if (samplingFrequency > 55426) { + qmfBands = 128; + } + + return qmfBands; +} + +/** + * \brief Analyse init flags + **/ +static int mpegSurroundDecoder_CalcInitFlags(SPATIAL_SPECIFIC_CONFIG *pSsc1, + SPATIAL_SPECIFIC_CONFIG *pSsc2, + int upmixTypeFlag, + int binauralQualityFlag, + int partiallyComplexFlag, + int *ctrlFlags) { + /* Analyse core coder */ + if (pSsc1->coreCodec != pSsc2->coreCodec) { + *ctrlFlags |= MASK_MPEGS_INIT_ALL_STATES; + *ctrlFlags |= MASK_MPEGS_INIT_ALL_PARAMS; + } else { + /* Analyse elements for initialization of space analysis qmf filterbank */ + if ((partiallyComplexFlag) || (pSsc1->treeConfig != pSsc2->treeConfig) || + (pSsc1->samplingFreq != pSsc2->samplingFreq)) { + *ctrlFlags |= MPEGS_INIT_STATES_ANA_QMF_FILTER; + *ctrlFlags |= MPEGS_INIT_STATES_ANA_HYB_FILTER; + } + + /* Analyse elements for initialization of space synthesis qmf filterbank */ + if ((upmixTypeFlag) || (partiallyComplexFlag) || + (pSsc1->treeConfig != pSsc2->treeConfig) || + (pSsc1->samplingFreq != pSsc2->samplingFreq) || + (pSsc1->bsFixedGainDMX != pSsc2->bsFixedGainDMX)) { + *ctrlFlags |= MPEGS_INIT_STATES_SYN_QMF_FILTER; + } + + /* Analyse elements for initialization of decorrelator */ + if ((upmixTypeFlag) || (partiallyComplexFlag) || + (pSsc1->treeConfig != pSsc2->treeConfig) || + (pSsc1->samplingFreq != pSsc2->samplingFreq) || + (pSsc1->decorrConfig != pSsc2->decorrConfig)) { + *ctrlFlags |= MPEGS_INIT_STATES_DECORRELATOR; + } + + /* Analyse elements for initialization of m1 and m2 calculation */ + if ((upmixTypeFlag) || (binauralQualityFlag) || + (pSsc1->treeConfig != pSsc2->treeConfig) || + (pSsc1->samplingFreq != pSsc2->samplingFreq)) + + { + *ctrlFlags |= MPEGS_INIT_STATES_M1M2; + } + + /* Analyse elements for initialization of GES */ + if ((upmixTypeFlag) || (pSsc1->treeConfig != pSsc2->treeConfig) || + (pSsc1->tempShapeConfig != pSsc2->tempShapeConfig)) { + *ctrlFlags |= MPEGS_INIT_STATES_GES; + } + + /* Analyse elements for initialization of FDreverb */ + if ((upmixTypeFlag) || (binauralQualityFlag) || (partiallyComplexFlag) || + (pSsc1->samplingFreq != pSsc2->samplingFreq) || + (pSsc1->nTimeSlots != pSsc2->nTimeSlots)) { + *ctrlFlags |= MPEGS_INIT_STATES_REVERB; + } + + /* Reset previous frame data whenever the config changes */ + if (*ctrlFlags & MPEGS_INIT_CONFIG) { + *ctrlFlags |= MPEGS_INIT_STATES_PARAM; + } + } + + return MPS_OK; +} + +/** + * \brief Reset MPEG Surround status info + **/ +static void updateMpegSurroundDecoderStatus( + CMpegSurroundDecoder *pMpegSurroundDecoder, int initFlags, + MPEGS_SYNCSTATE fOnSync, MPEGS_ANCSTARTSTOP ancStartStopPrev) { + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + initFlags; + if ((pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg != 0) && + (pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] >= + MPEGS_SYNC_FOUND) && + (fOnSync < MPEGS_SYNC_FOUND)) { + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] = + MPEGS_SYNC_FOUND; + } else { + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] = + fOnSync; + } + pMpegSurroundDecoder->ancStartStopPrev = ancStartStopPrev; +} + +static SACDEC_ERROR mpegSurroundDecoder_Create( + CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex, + HANDLE_FDK_QMF_DOMAIN pQmfDomain); + +SAC_INSTANCE_AVAIL +mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable( + CMpegSurroundDecoder *pMpegSurroundDecoder) { + SAC_INSTANCE_AVAIL instanceAvailable = SAC_INSTANCE_NOT_FULL_AVAILABLE; + + if (pMpegSurroundDecoder->pSpatialDec != NULL) { + instanceAvailable = SAC_INSTANCE_FULL_AVAILABLE; + } + + return instanceAvailable; +} + +SACDEC_ERROR mpegSurroundDecoder_Open( + CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex, + HANDLE_FDK_QMF_DOMAIN pQmfDomain) { + SACDEC_ERROR error; + + error = mpegSurroundDecoder_Create(pMpegSurroundDecoder, stereoConfigIndex, + pQmfDomain); + + return error; +} + +/** + * \brief Renamed function from getUpmixType to check_UParam_Build_DecConfig. + * This function checks if user params, decoder config and SSC are valid + * and if the decoder build can handle all this settings. + * The upmix type may be modified by this function. + * It is called in initMpegSurroundDecoder() after the ssc parse check, + * to have all checks in one place and to ensure these checks are always + * performed if config changes (inband and out-of-band). + * + * \param pUserParams User data handle. + * \param pDecConfig decoder config handle. + * \param pSsc spatial specific config handle. + * \param pUpmixType upmix type which is set by this function + * + * \return MPS_OK on sucess, and else on failure. + */ +static SACDEC_ERROR check_UParam_Build_DecConfig( + SPATIALDEC_PARAM const *pUserParams, SPATIAL_DEC_CONFIG const *pDecConfig, + const SPATIAL_SPECIFIC_CONFIG *pSsc, SPATIAL_DEC_UPMIX_TYPE *pUpmixType) { + int dmxChannels, outChannels, maxNumOutChannels; + + FDK_ASSERT(pUserParams != NULL); + FDK_ASSERT(pUpmixType != NULL); + + /* checks if implementation can handle the Ssc */ + + switch (pSsc->treeConfig) { + case SPATIALDEC_MODE_RSVD7: /* 212 */ + dmxChannels = 1; + outChannels = 2; + break; + default: + return MPS_UNSUPPORTED_CONFIG; + } + + /* ------------------------------------------- */ + + /* Analyse pDecConfig params */ + switch (pDecConfig->binauralMode) { + case BINAURAL_NONE: + break; + default: + return MPS_UNSUPPORTED_CONFIG; + } + + switch (pDecConfig->decoderMode) { + case EXT_HQ_ONLY: + break; + default: + return MPS_UNSUPPORTED_CONFIG; + } + + switch (pDecConfig->maxNumOutputChannels) { + case OUTPUT_CHANNELS_DEFAULT: + /* No special restrictions -> Get the level restriction: */ + switch (pDecConfig->decoderLevel) { + case DECODER_LEVEL_0: + maxNumOutChannels = 2; + break; + default: + return MPS_UNSUPPORTED_CONFIG; + } + break; + case OUTPUT_CHANNELS_2_0: + maxNumOutChannels = 2; + break; + default: + return MPS_UNSUPPORTED_CONFIG; + } + /* ------------------------- */ + + /* check if we can handle user params */ + if (pUserParams->blindEnable == 1) { + return MPS_UNSUPPORTED_CONFIG; + } + { + switch ((SAC_DEC_OUTPUT_MODE)pUserParams->outputMode) { + case SACDEC_OUT_MODE_NORMAL: + if (maxNumOutChannels >= outChannels) { + *pUpmixType = UPMIX_TYPE_NORMAL; + } else { + { *pUpmixType = UPMIX_TYPE_BYPASS; } + } + break; + case SACDEC_OUT_MODE_STEREO: + if (dmxChannels == 1) { + if (outChannels == 2) { + *pUpmixType = UPMIX_TYPE_NORMAL; + } + } else { + *pUpmixType = UPMIX_TYPE_BYPASS; + } + break; + case SACDEC_OUT_MODE_6CHANNEL: + if (outChannels > 6) { + { *pUpmixType = UPMIX_TYPE_BYPASS; } + } else { + *pUpmixType = UPMIX_TYPE_NORMAL; + } + break; + default: + return MPS_UNSUPPORTED_CONFIG; + } + } + + return MPS_OK; +} + +/** + * \brief Init MPEG Surround decoder. + **/ +static SACDEC_ERROR initMpegSurroundDecoder( + CMpegSurroundDecoder *pMpegSurroundDecoder) { + SACDEC_ERROR err; + int initFlags = MPEGS_INIT_NONE, initFlagsDec; + int upmixTypeCurr = pMpegSurroundDecoder->upmixType; + + FDK_ASSERT(pMpegSurroundDecoder != NULL); + + SPATIAL_SPECIFIC_CONFIG *const pSSCinput = + &pMpegSurroundDecoder->spatialSpecificConfigBackup; + SPATIAL_SPECIFIC_CONFIG *const pSSCtarget = + &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode]; + initFlagsDec = + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode]; + + if (pSSCinput->coreCodec != AOT_USAC) { + /* here we check if we have a valid Ssc */ + err = sscParseCheck(pSSCinput); + if (err != MPS_OK) goto bail; + } + + /* here we check if Ssc matches build; also check UParams and DecConfig */ + /* if desired upmixType is changes */ + err = check_UParam_Build_DecConfig( + &pMpegSurroundDecoder->mpegSurroundUserParams, + &pMpegSurroundDecoder->decConfig, pSSCinput, + &pMpegSurroundDecoder->upmixType); + if (err != MPS_OK) goto bail; + + /* init config */ + if (initFlagsDec & MPEGS_INIT_CHANGE_HEADER) { + initFlags |= MPEGS_INIT_CONFIG; + } + /* init all states */ + if (initFlagsDec & MPEGS_INIT_CLEAR_HISTORY) { + initFlags |= MASK_MPEGS_INIT_ALL_STATES; + } + if (initFlagsDec & MPEGS_INIT_CHANGE_CONCEAL_PARAMS) { + initFlags |= MPEGS_INIT_PARAMS_ERROR_CONCEALMENT; + } + + if (initFlagsDec & MPEGS_INIT_ENFORCE_REINIT) { + /* init all states */ + initFlags |= MASK_MPEGS_INIT_ALL_STATES; + initFlags |= MASK_MPEGS_INIT_ALL_PARAMS; + } else { + /* analyse states which have to be initialized */ + mpegSurroundDecoder_CalcInitFlags( + pSSCtarget, pSSCinput, + (upmixTypeCurr != + pMpegSurroundDecoder->upmixType), /* upmixType changed */ + 0, (initFlagsDec & MPEGS_INIT_CHANGE_PARTIALLY_COMPLEX) ? 1 : 0, + &initFlags); + } + + { + int nrOfQmfBands; + FDKmemcpy(pSSCtarget, pSSCinput, sizeof(SPATIAL_SPECIFIC_CONFIG)); + + nrOfQmfBands = mpegSurroundDecoder_GetNrOfQmfBands( + pSSCtarget, pSSCtarget->samplingFreq); + err = FDK_SpatialDecInit( + pMpegSurroundDecoder->pSpatialDec, + &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode], + pSSCtarget, nrOfQmfBands, pMpegSurroundDecoder->upmixType, + &pMpegSurroundDecoder->mpegSurroundUserParams, initFlags); + + if (err != MPS_OK) goto bail; + + /* Signal that we got a header and can go on decoding */ + if (err == MPS_OK) { + initFlagsDec = MPEGS_INIT_OK; + { + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] = + MPEGS_SYNC_FOUND; + } + } + } + +bail: + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] = + initFlagsDec; + return err; +} + +/** + * \brief Init MPEG Surround decoder. + **/ +SACDEC_ERROR mpegSurroundDecoder_Init( + CMpegSurroundDecoder *pMpegSurroundDecoder) { + SACDEC_ERROR err = MPS_OK; + + if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode]) { + err = initMpegSurroundDecoder(pMpegSurroundDecoder); + } + return err; +} + +/** + * \brief Open MPEG Surround decoder. + **/ +static SACDEC_ERROR mpegSurroundDecoder_Create( + CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex, + HANDLE_FDK_QMF_DOMAIN pQmfDomain) { + SACDEC_ERROR err = MPS_OK; + CMpegSurroundDecoder *sacDec = NULL; + spatialDec *self = NULL; + + /* decoderLevel decoderMode maxNumOutputChannels binauralMode */ + static const SPATIAL_DEC_CONFIG decConfig = { + (CFG_LEVEL)(0), EXT_HQ_ONLY, OUTPUT_CHANNELS_DEFAULT, BINAURAL_NONE}; + + if (*pMpegSurroundDecoder == NULL) { + FDK_ALLOCATE_MEMORY_1D(*pMpegSurroundDecoder, 1, CMpegSurroundDecoder) + + for (int i = 0; i < 1; i++) { + err = SpatialDecCreateBsFrame(&(*pMpegSurroundDecoder)->bsFrames[i], + &(*pMpegSurroundDecoder)->llState); + if (err != MPS_OK) { + sacDec = *pMpegSurroundDecoder; + goto bail; + } + } + (*pMpegSurroundDecoder)->pQmfDomain = pQmfDomain; + + (*pMpegSurroundDecoder)->bsFrameDelay = 1; + (*pMpegSurroundDecoder)->bsFrameParse = 0; + (*pMpegSurroundDecoder)->bsFrameDecode = 0; + + return err; + } else { + sacDec = *pMpegSurroundDecoder; + } + + if (sacDec->pSpatialDec == NULL) { + if ((self = FDK_SpatialDecOpen(&decConfig, stereoConfigIndex)) == NULL) { + err = MPS_OUTOFMEMORY; + goto bail; + } + } else { + self = sacDec->pSpatialDec; + } + + self->pQmfDomain = sacDec->pQmfDomain; + + sacDec->pSpatialDec = self; + + /* default parameter set */ + sacDec->mpegSurroundUserParams.outputMode = SACDEC_OUT_MODE_NORMAL; + sacDec->mpegSurroundUserParams.blindEnable = 0; + sacDec->mpegSurroundUserParams.bypassMode = 0; + sacDec->mpegSurroundUserParams.concealMethod = 1; + sacDec->mpegSurroundUserParams.concealNumKeepFrames = 10; + sacDec->mpegSurroundUserParams.concealFadeOutSlopeLength = 5; + sacDec->mpegSurroundUserParams.concealFadeInSlopeLength = 5; + sacDec->mpegSurroundUserParams.concealNumReleaseFrames = 3; + sacDec->mpegSurroundSscIsGlobalCfg = 0; + sacDec->mpegSurroundUseTimeInterface = 1; + sacDec->mpegSurroundDecoderLevel = decConfig.decoderLevel; + + sacDec->upmixType = UPMIX_TYPE_NORMAL; + + /* signalize spatial decoder re-initalization */ + updateMpegSurroundDecoderStatus(sacDec, MPEGS_INIT_ENFORCE_REINIT, + MPEGS_SYNC_LOST, MPEGS_STOP); + + /* return decoder instance */ + *pMpegSurroundDecoder = sacDec; + sacDec->decConfig = decConfig; + + SpatialDecInitParserContext(sacDec->pSpatialDec); + + return err; + +bail: + if (sacDec != NULL) { + mpegSurroundDecoder_Close(sacDec); + } + *pMpegSurroundDecoder = NULL; + if (err == MPS_OK) { + return MPS_OUTOFMEMORY; + } else { + return err; + } +} + +/** + * \brief Config MPEG Surround decoder. + **/ +SACDEC_ERROR mpegSurroundDecoder_Config( + CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs, + AUDIO_OBJECT_TYPE coreCodec, INT samplingRate, INT frameSize, + INT numChannels, INT stereoConfigIndex, INT coreSbrFrameLengthIndex, + INT configBytes, const UCHAR configMode, UCHAR *configChanged) { + SACDEC_ERROR err = MPS_OK; + INT nInputChannels; + SPATIAL_SPECIFIC_CONFIG spatialSpecificConfig; + SPATIAL_SPECIFIC_CONFIG *pSsc = + &pMpegSurroundDecoder->spatialSpecificConfigBackup; + + switch (coreCodec) { + case AOT_DRM_USAC: + case AOT_USAC: + if (configMode == AC_CM_DET_CFG_CHANGE) { + /* In config detection mode write spatial specific config parameters + * into temporarily allocated structure */ + err = SpatialDecParseMps212Config( + hBs, &spatialSpecificConfig, samplingRate, coreCodec, + stereoConfigIndex, coreSbrFrameLengthIndex); + nInputChannels = spatialSpecificConfig.nInputChannels; + pSsc = &spatialSpecificConfig; + } else { + err = SpatialDecParseMps212Config( + hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup, + samplingRate, coreCodec, stereoConfigIndex, + coreSbrFrameLengthIndex); + nInputChannels = + pMpegSurroundDecoder->spatialSpecificConfigBackup.nInputChannels; + } + if ((err == MPS_OK) && (numChannels != nInputChannels)) { + err = MPS_PARSE_ERROR; + } + break; + case AOT_ER_AAC_ELD: + case AOT_ER_AAC_LD: + if (configMode == AC_CM_DET_CFG_CHANGE) { + /* In config detection mode write spatial specific config parameters + * into temporarily allocated structure */ + err = SpatialDecParseSpecificConfig(hBs, &spatialSpecificConfig, + configBytes, coreCodec); + nInputChannels = spatialSpecificConfig.nInputChannels; + pSsc = &spatialSpecificConfig; + } else { + err = SpatialDecParseSpecificConfig( + hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup, + configBytes, coreCodec); + nInputChannels = + pMpegSurroundDecoder->spatialSpecificConfigBackup.nInputChannels; + } + /* check number of channels for channel_configuration > 0 */ + if ((err == MPS_OK) && (numChannels > 0) && + (numChannels != nInputChannels)) { + err = MPS_PARSE_ERROR; + } + break; + default: + err = MPS_UNSUPPORTED_FORMAT; + break; + } + + if (err != MPS_OK) { + goto bail; + } + + err = sscCheckOutOfBand(pSsc, coreCodec, samplingRate, frameSize); + + if (err != MPS_OK) { + goto bail; + } + + if (configMode & AC_CM_DET_CFG_CHANGE) { + return err; + } + + if (configMode & AC_CM_ALLOC_MEM) { + if (*configChanged) { + err = mpegSurroundDecoder_Open(&pMpegSurroundDecoder, stereoConfigIndex, + NULL); + if (err) { + return err; + } + } + } + + { + SPATIAL_SPECIFIC_CONFIG *sscParse = + &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse]; + + if (FDK_SpatialDecCompareSpatialSpecificConfigHeader( + &pMpegSurroundDecoder->spatialSpecificConfigBackup, sscParse)) { + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameParse] |= + MPEGS_INIT_CHANGE_HEADER; + /* Error resilience code */ + if (pMpegSurroundDecoder->pSpatialDec == NULL) { + err = MPS_NOTOK; + goto bail; + } + SpatialDecInitParserContext(pMpegSurroundDecoder->pSpatialDec); + pMpegSurroundDecoder->pSpatialDec->pConfigCurrent = + &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode]; + } + } + + if (err == MPS_OK) { + /* We got a valid out-of-band configuration so label it accordingly. */ + pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg = 1; + } + +bail: + return err; +} + +/** + * \brief Determine MPEG Surround operation mode. + **/ +static MPEGS_OPMODE mpegSurroundOperationMode( + CMpegSurroundDecoder *pMpegSurroundDecoder, int mpsDataBits) { + MPEGS_OPMODE mode; + + { + if ((mpsDataBits > 0) && + (pMpegSurroundDecoder->mpegSurroundUserParams.blindEnable == 0)) { + mode = MPEGS_OPMODE_MPS_PAYLOAD; /* Mode: Normal, Stereo or Binaural */ + } else { + mode = MPEGS_OPMODE_NO_MPS_PAYLOAD; /* Mode: No MPEG Surround Payload */ + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST, + MPEGS_STOP); + } + } + + return (mode); +} + +/** + * \brief Check ssc for parse errors. + * This one is called in initMpegSurroundDecoder() + * to ensure checking of inband and out-of-band mps configs. + * Only parse errors checked here! Check for valid config is done + * in check_UParam_Build_DecConfig()! + * + * \param pSsc spatial specific config handle. + * + * \return MPS_OK on sucess, and else on parse error. + */ +static SACDEC_ERROR sscParseCheck(const SPATIAL_SPECIFIC_CONFIG *pSsc) { + if (pSsc->samplingFreq > 96000) return MPS_PARSE_ERROR; + if (pSsc->samplingFreq < 8000) return MPS_PARSE_ERROR; + + if ((pSsc->treeConfig < 0) || (pSsc->treeConfig > 7)) { + return MPS_PARSE_ERROR; + } + + if ((pSsc->quantMode < 0) || (pSsc->quantMode > 2)) { + return MPS_PARSE_ERROR; + } + + /* now we are sure there were no parsing errors */ + + return MPS_OK; +} + +/** + * \brief Check number of time slots + * + * Basically the mps frame length must be a multiple of the core coder frame + * length. The below table shows all valid configurations in detail. See ISO/IEC + * 23003-1: "Table 4A - Allowed values for bsFrameLength in the Baseline MPEG + * Surround Profile" + * + * Downmix Coder Downmix Code Allowed values for bsFrameLength + * Allowed frame sizes for normal, downsampled and upsampled MPS Framelength + * (QMF Samples) + * + * AAC 1024 16 15, 31, 47, 63 1024 2048 3072 4096 + * downsampled MPS 32 31, 63 1024 2048 upsampled MPS + * 8 7, 15, 23, 31, 39, 47, 55, 63, 71 1024 2048 3072 4096 + * 5120 6144 7168 8192 9216 + * + * AAC 960 15 14, 29, 44, 59 960 1920 2880 3840 + * downsampled MPS 30 29, 59 960 1920 upsampled MPS + * 7,5 14, 29, 44, 59 1920 3840 5760 7680 + * + * HE-AAC 1024/2048 32 31, 63 2048 4096 downsampled MPS + * 64 63 2048 upsampled MPS + * 16 15, 31, 47, 63 2048 4096 6144 8192 + * + * HE-AAC 960/1920 30 29, 59 1920 3840 downsampled MPS + * 60 59 1920 upsampled MPS + * 15 14, 29, 44, 59 1920 3840 5760 7680 + * + * BSAC 16 15, 31, 47, 63 1024 2048 3072 4096 + * downsampled MPS 32 31, 63 1024 2048 upsampled MPS + * 8 7, 15, 23, 31, 39, 47, 55, 63, 71 1024 2048 3072 4096 + * 5120 6144 7168 8192 9216 + * + * BSAC with SBR 32 31, 63 2048 4096 downsampled MPS + * 64 63 2048 upsampled MPS + * 16 15, 31, 47, 63 2048 4096 6144 8192 + * + * AAC LD 512 8 7, 15, 23, 31, 39, 47, 55, 63, 71 + * 512 1024 1536 2048 2560 3072 3584 4096 4608 downsampled MPS + * 16 15, 31, 47, 63 512 1024 1536 2048 + * + * AAC ELD 512 8 7, 15, 23, 31, 39, 47, 55, 63, 71 + * 512 1024 1536 2048 2560 3072 3584 4096 4608 downsampled MPS + * 16 15, 31, 47, 63 512 1024 1536 2048 + * + * AAC ELD with SBR 512/1024 16 15, 31, 47, 63 1024 2048 3072 4096 + * downsampled MPS 32 31, 63 1024 2048 upsampled MPS + * 8 7, 15, 23, 31, 39, 47, 55, 63, 71 1024 2048 3072 4096 + * 5120 6144 7168 8192 9216 + * + * MPEG1/2 Layer II 18 17, 35, 53, 71 1152 2304 3456 4608 + * downsampled MPS 36 35, 71 1152 2304 + * + * MPEG1/2 Layer III 18 17, 35, 53, 71 1152 2304 3456 4608 + * downsampled MPS 36 35, 71 1152 2304 + * + * \param frameLength + * \param qmfBands + * \param timeSlots + * + * \return error code + */ +SACDEC_ERROR checkTimeSlots(int frameLength, int qmfBands, int timeSlots) { + int len; + int maxFrameLength; + + if (qmfBands == 64) { + /* normal MPEG Surround */ + switch (frameLength) { + case 960: + case 1920: + maxFrameLength = 3840; + break; + case 1024: + case 2048: + maxFrameLength = 4096; + break; + case 512: + case 1152: + maxFrameLength = 4608; + break; + default: + return MPS_PARSE_ERROR; + } + } else if (qmfBands == 32) { + /* downsampled MPEG Surround */ + switch (frameLength) { + case 960: + case 1920: + maxFrameLength = 1920; + break; + case 512: + case 1024: + case 2048: + maxFrameLength = 2048; + break; + case 1152: + maxFrameLength = 2304; + break; + default: + return MPS_PARSE_ERROR; + } + } else if (qmfBands == 128) { + /* upsampled MPEG Surround */ + switch (frameLength) { + case 1920: + maxFrameLength = 7680; + break; + case 1024: + maxFrameLength = 9216; + break; + case 2048: + maxFrameLength = 8192; + break; + case 512: + case 960: + case 1152: + /* no break, no support for upsampled MPEG Surround */ + default: + return MPS_PARSE_ERROR; + } + } else { + return MPS_PARSE_ERROR; + } + + len = frameLength; + + while (len <= maxFrameLength) { + if (len == timeSlots * qmfBands) { + return MPS_OK; + } + len += frameLength; + } + return MPS_PARSE_ERROR; +} + +/** + * \brief Check ssc for consistency (e.g. bit errors could cause trouble) + * First of currently two ssc-checks. + * This (old) one is called in mpegSurroundDecoder_Apply() + * only if inband mps config is contained in stream. + * + * New ssc check is split in two functions sscParseCheck() and + * check_UParam_Build_DecConfig(). sscParseCheck() checks only for correct + * parsing. check_UParam_Build_DecConfig() is used to check if we have a + * valid config. Both are called in initMpegSurroundDecoder() to ensure + * checking of inband and out-of-band mps configs. + * + * If this function can be integrated into the new functions. + * We can remove this one. + * + * \param pSsc spatial specific config handle. + * \param frameLength + * \param sampleRate + * + * \return MPS_OK on sucess, and else on failure. + */ +static SACDEC_ERROR sscCheckInBand(SPATIAL_SPECIFIC_CONFIG *pSsc, + int frameLength, int sampleRate) { + SACDEC_ERROR err = MPS_OK; + int qmfBands; + + FDK_ASSERT(pSsc != NULL); + + /* check ssc for parse errors */ + if (sscParseCheck(pSsc) != MPS_OK) { + err = MPS_PARSE_ERROR; + } + + /* core fs and mps fs must match */ + if (pSsc->samplingFreq != sampleRate) { + err = MPS_PARSE_ERROR /* MPEGSDEC_SSC_PARSE_ERROR */; + } + + qmfBands = mpegSurroundDecoder_GetNrOfQmfBands(pSsc, pSsc->samplingFreq); + + if (checkTimeSlots(frameLength, qmfBands, pSsc->nTimeSlots) != MPS_OK) { + err = MPS_PARSE_ERROR; + } + + return err; +} + +SACDEC_ERROR +mpegSurroundDecoder_ConfigureQmfDomain( + CMpegSurroundDecoder *pMpegSurroundDecoder, + SAC_INPUT_CONFIG sac_dec_interface, UINT coreSamplingRate, + AUDIO_OBJECT_TYPE coreCodec) { + SACDEC_ERROR err = MPS_OK; + FDK_QMF_DOMAIN_GC *pGC = NULL; + + if (pMpegSurroundDecoder == NULL) { + return MPS_INVALID_HANDLE; + } + + FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec); + + pGC = &pMpegSurroundDecoder->pQmfDomain->globalConf; + if (pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg) { + SPATIAL_SPECIFIC_CONFIG *pSSC = + &pMpegSurroundDecoder->spatialSpecificConfigBackup; + if (sac_dec_interface == SAC_INTERFACE_TIME) { + /* For SAC_INTERFACE_QMF these parameters are set by SBR. */ + pGC->nBandsAnalysis_requested = mpegSurroundDecoder_GetNrOfQmfBands( + pSSC, coreSamplingRate); /* coreSamplingRate == outputSamplingRate for + SAC_INTERFACE_TIME */ + pGC->nBandsSynthesis_requested = pGC->nBandsAnalysis_requested; + pGC->nInputChannels_requested = + fMax((UINT)pSSC->nInputChannels, (UINT)pGC->nInputChannels_requested); + } + pGC->nOutputChannels_requested = + fMax((UINT)pSSC->nOutputChannels, (UINT)pGC->nOutputChannels_requested); + } else { + if (sac_dec_interface == SAC_INTERFACE_TIME) { + /* For SAC_INTERFACE_QMF these parameters are set by SBR. */ + pGC->nBandsAnalysis_requested = mpegSurroundDecoder_GetNrOfQmfBands( + NULL, coreSamplingRate); /* coreSamplingRate == outputSamplingRate for + SAC_INTERFACE_TIME */ + pGC->nBandsSynthesis_requested = pGC->nBandsAnalysis_requested; + pGC->nInputChannels_requested = + pMpegSurroundDecoder->pSpatialDec->createParams.maxNumInputChannels; + } + pGC->nOutputChannels_requested = + pMpegSurroundDecoder->pSpatialDec->createParams.maxNumOutputChannels; + } + pGC->nQmfProcBands_requested = 64; + pGC->nQmfProcChannels_requested = + fMin((INT)pGC->nInputChannels_requested, + pMpegSurroundDecoder->pSpatialDec->createParams.maxNumInputChannels); + + if (coreCodec == AOT_ER_AAC_ELD) { + pGC->flags_requested |= QMF_FLAG_MPSLDFB; + pGC->flags_requested &= ~QMF_FLAG_CLDFB; + } + + return err; +} + +/** + * \brief Check out-of-band config + * + * \param pSsc spatial specific config handle. + * \param coreCodec core codec. + * \param sampleRate sampling frequency. + * + * \return errorStatus + */ +SACDEC_ERROR +sscCheckOutOfBand(const SPATIAL_SPECIFIC_CONFIG *pSsc, const INT coreCodec, + const INT sampleRate, const INT frameSize) { + FDK_ASSERT(pSsc != NULL); + int qmfBands = 0; + + /* check ssc for parse errors */ + if (sscParseCheck(pSsc) != MPS_OK) { + return MPS_PARSE_ERROR; + } + + switch (coreCodec) { + case AOT_USAC: + case AOT_DRM_USAC: + /* ISO/IEC 23003-1:2007(E), Chapter 6.3.3, Support for lower and higher + * sampling frequencies */ + if (pSsc->samplingFreq >= 55426) { + return MPS_PARSE_ERROR; + } + break; + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + /* core fs and mps fs must match */ + if (pSsc->samplingFreq != sampleRate) { + return MPS_PARSE_ERROR; + } + + /* ISO/IEC 14496-3:2009 FDAM 3: Chapter 1.5.2.3, Levels for the Low Delay + * AAC v2 profile */ + if (pSsc->samplingFreq > 48000) { + return MPS_PARSE_ERROR; + } + + qmfBands = mpegSurroundDecoder_GetNrOfQmfBands(pSsc, pSsc->samplingFreq); + switch (frameSize) { + case 480: + if (!((qmfBands == 32) && (pSsc->nTimeSlots == 15))) { + return MPS_PARSE_ERROR; + } + break; + case 960: + if (!((qmfBands == 64) && (pSsc->nTimeSlots == 15))) { + return MPS_PARSE_ERROR; + } + break; + case 512: + if (!(((qmfBands == 32) && (pSsc->nTimeSlots == 16)) || + ((qmfBands == 64) && (pSsc->nTimeSlots == 8)))) { + return MPS_PARSE_ERROR; + } + break; + case 1024: + if (!((qmfBands == 64) && (pSsc->nTimeSlots == 16))) { + return MPS_PARSE_ERROR; + } + break; + default: + return MPS_PARSE_ERROR; + } + break; + default: + return MPS_PARSE_ERROR; + break; + } + + return MPS_OK; +} + +/** + * \brief Decode MPEG Surround frame. + **/ +int mpegSurroundDecoder_ParseNoHeader( + CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs, + int *pMpsDataBits, int fGlobalIndependencyFlag) { + SACDEC_ERROR err = MPS_OK; + SPATIAL_SPECIFIC_CONFIG *sscParse; + int bitsAvail, numSacBits; + + if (pMpegSurroundDecoder == NULL || hBs == NULL) { + return MPS_INVALID_HANDLE; + } + + sscParse = &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse]; + + bitsAvail = FDKgetValidBits(hBs); + + /* First spatial specific config is parsed into spatialSpecificConfigBackup, + * second spatialSpecificConfigBackup is copied into + * spatialSpecificConfig[bsFrameDecode] */ + if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameParse]) { + FDKmemcpy(sscParse, &pMpegSurroundDecoder->spatialSpecificConfigBackup, + sizeof(SPATIAL_SPECIFIC_CONFIG)); + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameParse] = + MPEGS_SYNC_FOUND; + } + + if (bitsAvail <= 0) { + err = MPS_PARSE_ERROR; + } else { + err = SpatialDecParseFrameData( + pMpegSurroundDecoder->pSpatialDec, + &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse], + hBs, sscParse, (UPMIXTYPE)pMpegSurroundDecoder->upmixType, + fGlobalIndependencyFlag); + if (err == MPS_OK) { + pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse] + .newBsData = 1; + } + } + + numSacBits = bitsAvail - (INT)FDKgetValidBits(hBs); + + if (numSacBits > bitsAvail) { + pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse] + .newBsData = 0; + err = MPS_PARSE_ERROR; + } + + *pMpsDataBits -= numSacBits; + + return err; +} + +/** + * \brief Check, if ancType is valid. + **/ +static int isValidAncType(CMpegSurroundDecoder *pMpegSurroundDecoder, + int ancType) { + int ret = 1; + + if ((ancType != MPEGS_ANCTYPE_HEADER_AND_FRAME) && + (ancType != MPEGS_ANCTYPE_FRAME)) { + ret = 0; + } + + if (ret == 0) { + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST, + MPEGS_STOP); + } + + return (ret); +} + +/** + * \brief Check, if ancStartStop is valid. + **/ +static int isValidAncStartStop(CMpegSurroundDecoder *pMpegSurroundDecoder, + int ancStartStop) { + int ret = 1; + + switch (ancStartStop) { + case MPEGS_START: + /* Sequence start - start and continue - start not allowed */ + if ((pMpegSurroundDecoder->ancStartStopPrev == MPEGS_START) || + (pMpegSurroundDecoder->ancStartStopPrev == MPEGS_CONTINUE)) { + ret = 0; + } + break; + + case MPEGS_STOP: + /* MPS payload of the previous frame must be valid if current type is stop + Sequence startstop - stop and stop - stop not allowed + Sequence startstop - continue and stop - continue are allowed */ + if ((pMpegSurroundDecoder->ancStartStopPrev == MPEGS_STOP) || + (pMpegSurroundDecoder->ancStartStopPrev == MPEGS_START_STOP)) { + ret = 0; + } + break; + + case MPEGS_CONTINUE: + case MPEGS_START_STOP: + /* No error detection possible for this states */ + break; + } + + if (ret == 0) { + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST, + MPEGS_STOP); + } else { + pMpegSurroundDecoder->ancStartStopPrev = (MPEGS_ANCSTARTSTOP)ancStartStop; + } + + return (ret); +} + +int mpegSurroundDecoder_Parse(CMpegSurroundDecoder *pMpegSurroundDecoder, + HANDLE_FDK_BITSTREAM hBs, int *pMpsDataBits, + AUDIO_OBJECT_TYPE coreCodec, int sampleRate, + int frameSize, int fGlobalIndependencyFlag) { + SACDEC_ERROR err = MPS_OK; + SPATIAL_SPECIFIC_CONFIG *sscParse; + SPATIAL_BS_FRAME *bsFrame; + HANDLE_FDK_BITSTREAM hMpsBsData = NULL; + FDK_BITSTREAM mpsBsData; + int mpsDataBits = *pMpsDataBits; + int mpsBsBits; + MPEGS_ANCTYPE ancType; + MPEGS_ANCSTARTSTOP ancStartStop; + + if (pMpegSurroundDecoder == NULL) { + return MPS_INVALID_HANDLE; + } + + FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec); + + mpsBsBits = (INT)FDKgetValidBits(hBs); + + sscParse = &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse]; + bsFrame = &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse]; + + /* + Find operation mode of mpeg surround decoder: + - MPEGS_OPMODE_EMM: Mode: Enhanced Matrix Mode (Blind) + - MPEGS_OPMODE_MPS_PAYLOAD: Mode: Normal, Stereo or Binaural + - MPEGS_OPMODE_NO_MPS_PAYLOAD: Mode: No MpegSurround Payload + */ + { + /* Parse ancType and ancStartStop */ + ancType = (MPEGS_ANCTYPE)FDKreadBits(hBs, 2); + ancStartStop = (MPEGS_ANCSTARTSTOP)FDKreadBits(hBs, 2); + mpsDataBits -= 4; + + /* Set valid anc type flag, if ancType signals a payload with either header + * and frame or frame */ + if (isValidAncType(pMpegSurroundDecoder, ancType)) { + /* Set valid anc startstop flag, if transmitted sequence is not illegal */ + if (isValidAncStartStop(pMpegSurroundDecoder, ancStartStop)) { + switch (ancStartStop) { + case MPEGS_START: + /* Assuming that core coder frame size (AAC) is smaller than MPS + coder frame size. Save audio data for next frame. */ + if (mpsDataBits > MPS_DATA_BUFFER_SIZE * 8) { + err = MPS_NOTOK; + goto bail; + } + for (int i = 0; i < mpsDataBits / 8; i++) { + pMpegSurroundDecoder->mpsData[i] = FDKreadBits(hBs, 8); + } + pMpegSurroundDecoder->mpsDataBits = mpsDataBits; + break; + + case MPEGS_CONTINUE: + case MPEGS_STOP: + /* Assuming that core coder frame size (AAC) is smaller than MPS + coder frame size. Save audio data for next frame. */ + if ((pMpegSurroundDecoder->mpsDataBits + mpsDataBits) > + MPS_DATA_BUFFER_SIZE * 8) { + err = MPS_NOTOK; + goto bail; + } + for (int i = 0; i < mpsDataBits / 8; i++) { + pMpegSurroundDecoder + ->mpsData[(pMpegSurroundDecoder->mpsDataBits / 8) + i] = + FDKreadBits(hBs, 8); + } + pMpegSurroundDecoder->mpsDataBits += mpsDataBits; + FDKinitBitStream(&mpsBsData, pMpegSurroundDecoder->mpsData, + MAX_BUFSIZE_BYTES, + pMpegSurroundDecoder->mpsDataBits, BS_READER); + hMpsBsData = &mpsBsData; + break; + + case MPEGS_START_STOP: + pMpegSurroundDecoder->mpsDataBits = mpsDataBits; + hMpsBsData = hBs; + break; + + default: + FDK_ASSERT(0); + } + + if ((ancStartStop == MPEGS_STOP) || + (ancStartStop == MPEGS_START_STOP)) { + switch (ancType) { + case MPEGS_ANCTYPE_HEADER_AND_FRAME: { + int parseResult, bitsRead; + SPATIAL_SPECIFIC_CONFIG spatialSpecificConfigTmp = + pMpegSurroundDecoder->spatialSpecificConfigBackup; + + /* Parse spatial specific config */ + bitsRead = (INT)FDKgetValidBits(hMpsBsData); + + err = SpatialDecParseSpecificConfigHeader( + hMpsBsData, + &pMpegSurroundDecoder->spatialSpecificConfigBackup, coreCodec, + pMpegSurroundDecoder->upmixType); + + bitsRead = (bitsRead - (INT)FDKgetValidBits(hMpsBsData)); + parseResult = ((err == MPS_OK) ? bitsRead : -bitsRead); + + if (parseResult < 0) { + parseResult = -parseResult; + err = MPS_PARSE_ERROR; + } else if (err == MPS_OK) { + /* Check SSC for consistency (e.g. bit errors could cause + * trouble) */ + err = sscCheckInBand( + &pMpegSurroundDecoder->spatialSpecificConfigBackup, + frameSize, sampleRate); + } + if (err != MPS_OK) { + pMpegSurroundDecoder->spatialSpecificConfigBackup = + spatialSpecificConfigTmp; + break; + } + + pMpegSurroundDecoder->mpsDataBits -= parseResult; + + /* Initiate re-initialization, if header has changed */ + if (FDK_SpatialDecCompareSpatialSpecificConfigHeader( + &pMpegSurroundDecoder->spatialSpecificConfigBackup, + sscParse) == MPS_UNEQUAL_SSC) { + pMpegSurroundDecoder + ->initFlags[pMpegSurroundDecoder->bsFrameParse] |= + MPEGS_INIT_CHANGE_HEADER; + SpatialDecInitParserContext(pMpegSurroundDecoder->pSpatialDec); + /* We found a valid in-band configuration. Therefore any + * previous config is invalid now. */ + pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg = 0; + } + } + FDK_FALLTHROUGH; + case MPEGS_ANCTYPE_FRAME: + + if (pMpegSurroundDecoder + ->initFlags[pMpegSurroundDecoder->bsFrameParse] & + MPEGS_INIT_ERROR_PAYLOAD) { + err = MPS_PARSE_ERROR; + break; + } + + /* First spatial specific config is parsed into + * spatialSpecificConfigBackup, second spatialSpecificConfigBackup + * is copied into spatialSpecificConfig[bsFrameDecode] */ + if (pMpegSurroundDecoder + ->initFlags[pMpegSurroundDecoder->bsFrameParse]) { + FDKmemcpy(sscParse, + &pMpegSurroundDecoder->spatialSpecificConfigBackup, + sizeof(SPATIAL_SPECIFIC_CONFIG)); + pMpegSurroundDecoder + ->fOnSync[pMpegSurroundDecoder->bsFrameParse] = + MPEGS_SYNC_FOUND; + } + + if (pMpegSurroundDecoder + ->fOnSync[pMpegSurroundDecoder->bsFrameParse] >= + MPEGS_SYNC_FOUND) { + int nbits = 0, bitsAvail; + + if (err != MPS_OK) { + break; + } + + bitsAvail = FDKgetValidBits(hMpsBsData); + + if (bitsAvail <= 0) { + err = MPS_PARSE_ERROR; + } else { + err = SpatialDecParseFrameData( + pMpegSurroundDecoder->pSpatialDec, bsFrame, hMpsBsData, + sscParse, (UPMIXTYPE)pMpegSurroundDecoder->upmixType, + fGlobalIndependencyFlag); + if (err == MPS_OK) { + bsFrame->newBsData = 1; + } + } + + nbits = bitsAvail - (INT)FDKgetValidBits(hMpsBsData); + + if ((nbits > bitsAvail) || + (nbits > pMpegSurroundDecoder->mpsDataBits) || + (pMpegSurroundDecoder->mpsDataBits > nbits + 7 && + !IS_LOWDELAY(coreCodec))) { + bsFrame->newBsData = 0; + err = MPS_PARSE_ERROR; + break; + } + pMpegSurroundDecoder->mpsDataBits -= nbits; + } + break; + + default: /* added to avoid compiler warning */ + err = MPS_NOTOK; + break; /* added to avoid compiler warning */ + } /* switch (ancType) */ + + if (err == MPS_OK) { + pMpegSurroundDecoder->ancStartStopPrev = ancStartStop; + } else { + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_ERROR_PAYLOAD, + MPEGS_SYNC_LOST, MPEGS_STOP); + pMpegSurroundDecoder->mpsDataBits = 0; + } + } /* (ancStartStop == MPEGS_STOP) || (ancStartStop == MPEGS_START_STOP) + */ + } /* validAncStartStop */ + } /* validAncType */ + } + +bail: + + *pMpsDataBits -= (mpsBsBits - (INT)FDKgetValidBits(hBs)); + + return err; +} + +int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder, + PCM_MPS *input, PCM_MPS *pTimeData, + const int timeDataSize, int timeDataFrameSize, + int *nChannels, int *frameSize, int sampleRate, + AUDIO_OBJECT_TYPE coreCodec, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const FDK_channelMapDescr *const mapDescr, + const INT inDataHeadroom, INT *outDataHeadroom) { + SACDEC_ERROR err = MPS_OK; + PCM_MPS *pTimeOut = pTimeData; + PCM_MPS *TDinput = NULL; + UINT initControlFlags = 0, controlFlags = 0; + int timeDataRequiredSize = 0; + int newData; + + if (pMpegSurroundDecoder == NULL) { + return MPS_INVALID_HANDLE; + } + + FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec); + + if (!FDK_chMapDescr_isValid(mapDescr)) { + return MPS_INVALID_HANDLE; + } + + if ((*nChannels <= 0) || (*nChannels > 2)) { + return MPS_NOTOK; + } + + pMpegSurroundDecoder->pSpatialDec->sacInDataHeadroom = inDataHeadroom; + *outDataHeadroom = (INT)(8); + + pMpegSurroundDecoder->pSpatialDec->pConfigCurrent = + &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode]; + newData = pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse] + .newBsData; + + switch (mpegSurroundOperationMode(pMpegSurroundDecoder, 1000)) { + case MPEGS_OPMODE_MPS_PAYLOAD: + if (pMpegSurroundDecoder + ->initFlags[pMpegSurroundDecoder->bsFrameDecode]) { + err = initMpegSurroundDecoder(pMpegSurroundDecoder); + } + + if (err == MPS_OK) { + if ((pMpegSurroundDecoder + ->fOnSync[pMpegSurroundDecoder->bsFrameDecode] != + MPEGS_SYNC_COMPLETE) && + (pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode] + .bsIndependencyFlag == 1)) { + /* We got a valid header and independently decodeable frame data. + -> Go to the next sync level and start processing. */ + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] = + MPEGS_SYNC_COMPLETE; + } + } else { + /* We got a valid config header but found an error while parsing the + bitstream. Wait for the next independent frame and apply error + conealment in the meantime. */ + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] = + MPEGS_SYNC_FOUND; + controlFlags |= MPEGS_CONCEAL; + err = MPS_OK; + } + /* + Concealment: + - Bitstream is available, no sync found during bitstream processing + - Bitstream is available, sync lost due to corrupted bitstream + - Bitstream is available, sync found but no independent frame + */ + if (pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] != + MPEGS_SYNC_COMPLETE) { + controlFlags |= MPEGS_CONCEAL; + } + break; + + case MPEGS_OPMODE_NO_MPS_PAYLOAD: + /* Concealment: No bitstream is available */ + controlFlags |= MPEGS_CONCEAL; + break; + + default: + err = MPS_NOTOK; + } + + if (err != MPS_OK) { + goto bail; + } + + /* + * Force BypassMode if choosen by user + */ + if (pMpegSurroundDecoder->mpegSurroundUserParams.bypassMode) { + controlFlags |= MPEGS_BYPASSMODE; + } + + if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode]) { + int startWithDfltCfg = 0; + /* + * Init with a default configuration if we came here and are still not + * initialized. + */ + if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] & + MPEGS_INIT_ENFORCE_REINIT) { + /* Get default spatial specific config */ + if (FDK_SpatialDecInitDefaultSpatialSpecificConfig( + &pMpegSurroundDecoder->spatialSpecificConfigBackup, coreCodec, + *nChannels, sampleRate, + *frameSize / + mpegSurroundDecoder_GetNrOfQmfBands(NULL, sampleRate), + pMpegSurroundDecoder->mpegSurroundDecoderLevel, + pMpegSurroundDecoder->mpegSurroundUserParams.blindEnable)) { + err = MPS_NOTOK; + goto bail; + } + + /* Initiate re-initialization, if header has changed */ + if (FDK_SpatialDecCompareSpatialSpecificConfigHeader( + &pMpegSurroundDecoder->spatialSpecificConfigBackup, + &pMpegSurroundDecoder->spatialSpecificConfig + [pMpegSurroundDecoder->bsFrameDecode]) == MPS_UNEQUAL_SSC) { + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_HEADER; + SpatialDecInitParserContext(pMpegSurroundDecoder->pSpatialDec); + } + + startWithDfltCfg = 1; + } + + /* First spatial specific config is parsed into spatialSpecificConfigBackup, + * second spatialSpecificConfigBackup is copied into spatialSpecificConfig + */ + err = initMpegSurroundDecoder(pMpegSurroundDecoder); + + if (startWithDfltCfg) { + /* initialized with default config, but no sync found */ + /* maybe use updateMpegSurroundDecoderStatus later on */ + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] = + MPEGS_SYNC_LOST; + } + + /* Since we do not have state MPEGS_SYNC_COMPLETE apply concealment */ + controlFlags |= MPEGS_CONCEAL; + + if (err != MPS_OK) { + goto bail; + } + } + + /* + * Process MPEG Surround Audio + */ + initControlFlags = controlFlags; + + /* Check that provided output buffer is large enough. */ + if (pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis == 0) { + err = MPS_UNSUPPORTED_FORMAT; + goto bail; + } + timeDataRequiredSize = + (timeDataFrameSize * + pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT * + pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsSynthesis) / + pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis; + if (timeDataSize < timeDataRequiredSize) { + err = MPS_OUTPUT_BUFFER_TOO_SMALL; + goto bail; + } + + if ((pMpegSurroundDecoder->pSpatialDec->pConfigCurrent->syntaxFlags & + SACDEC_SYNTAX_USAC) && + (pMpegSurroundDecoder->pSpatialDec->stereoConfigIndex > 1)) { + FDK_ASSERT(timeDataRequiredSize >= timeDataFrameSize * *nChannels); + /* Place samples comprising QMF time slots spaced at QMF output Band raster + * to allow slot wise processing */ + int timeDataFrameSizeOut = + (timeDataFrameSize * + pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsSynthesis) / + pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis; + TDinput = pTimeData + timeDataFrameSizeOut - timeDataFrameSize; + for (int i = *nChannels - 1; i >= 0; i--) { + FDKmemmove(pTimeData + (i + 1) * timeDataFrameSizeOut - timeDataFrameSize, + pTimeData + timeDataFrameSize * i, + sizeof(PCM_MPS) * timeDataFrameSize); + FDKmemclear(pTimeData + i * timeDataFrameSizeOut, + sizeof(PCM_MPS) * (timeDataFrameSizeOut - timeDataFrameSize)); + } + } else { + if (pMpegSurroundDecoder->mpegSurroundUseTimeInterface) { + FDKmemcpy(input, pTimeData, + sizeof(PCM_MPS) * (*nChannels) * (*frameSize)); + TDinput = input; + } + } + + /* + * Process MPEG Surround Audio + */ + err = SpatialDecApplyFrame( + pMpegSurroundDecoder->pSpatialDec, + &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode], + pMpegSurroundDecoder->mpegSurroundUseTimeInterface ? INPUTMODE_TIME + : INPUTMODE_QMF_SBR, + TDinput, NULL, NULL, pTimeOut, *frameSize, &controlFlags, *nChannels, + mapDescr); + *nChannels = pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT; + + if (err != + MPS_OK) { /* A fatal error occured. Go back to start and try again: */ + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_ENFORCE_REINIT, MPEGS_SYNC_LOST, + MPEGS_STOP); + *frameSize = + 0; /* Declare that framework can not use the data in pTimeOut. */ + } else { + if (((controlFlags & MPEGS_CONCEAL) && + !(initControlFlags & MPEGS_CONCEAL)) || + (pMpegSurroundDecoder->pSpatialDec->errInt != + MPS_OK)) { /* Account for errors that occured in + SpatialDecApplyFrame(): */ + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST, + MPEGS_STOP); + } + } + + if ((err == MPS_OK) && !(controlFlags & MPEGS_BYPASSMODE) && + !(pMpegSurroundDecoder->upmixType == UPMIX_TYPE_BYPASS)) { + SpatialDecChannelProperties(pMpegSurroundDecoder->pSpatialDec, channelType, + channelIndices, mapDescr); + } + +bail: + + if (newData) { + /* numParameterSetsPrev shall only be read in the decode process, because of + that we can update this state variable here */ + pMpegSurroundDecoder->pSpatialDec->numParameterSetsPrev = + pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode] + .numParameterSets; + } + + return (err); +} + +/** + * \brief Free config dependent MPEG Surround memory. + **/ +SACDEC_ERROR mpegSurroundDecoder_FreeMem( + CMpegSurroundDecoder *pMpegSurroundDecoder) { + SACDEC_ERROR err = MPS_OK; + + if (pMpegSurroundDecoder != NULL) { + FDK_SpatialDecClose(pMpegSurroundDecoder->pSpatialDec); + pMpegSurroundDecoder->pSpatialDec = NULL; + } + + return err; +} + +/** + * \brief Close MPEG Surround decoder. + **/ +void mpegSurroundDecoder_Close(CMpegSurroundDecoder *pMpegSurroundDecoder) { + if (pMpegSurroundDecoder != NULL) { + FDK_SpatialDecClose(pMpegSurroundDecoder->pSpatialDec); + pMpegSurroundDecoder->pSpatialDec = NULL; + + for (int i = 0; i < 1; i++) { + SpatialDecCloseBsFrame(&pMpegSurroundDecoder->bsFrames[i]); + } + + FDK_FREE_MEMORY_1D(pMpegSurroundDecoder); + } +} + +#define SACDEC_VL0 2 +#define SACDEC_VL1 1 +#define SACDEC_VL2 0 + +int mpegSurroundDecoder_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return -1; + } + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) return -1; + + info += i; + + info->module_id = FDK_MPSDEC; +#ifdef SUPPRESS_BUILD_DATE_INFO + info->build_date = ""; + info->build_time = ""; +#else + info->build_date = __DATE__; + info->build_time = __TIME__; +#endif + info->title = "MPEG Surround Decoder"; + info->version = LIB_VERSION(SACDEC_VL0, SACDEC_VL1, SACDEC_VL2); + LIB_VERSION_STRING(info); + info->flags = 0 | CAPF_MPS_LD | CAPF_MPS_USAC | CAPF_MPS_HQ | + CAPF_MPS_1CH_IN | CAPF_MPS_2CH_OUT; /* end flags */ + + return 0; +} + +SACDEC_ERROR mpegSurroundDecoder_SetParam( + CMpegSurroundDecoder *pMpegSurroundDecoder, const SACDEC_PARAM param, + const INT value) { + SACDEC_ERROR err = MPS_OK; + SPATIALDEC_PARAM *pUserParams = NULL; + + /* check decoder handle */ + if (pMpegSurroundDecoder != NULL) { + /* init local shortcuts */ + pUserParams = &pMpegSurroundDecoder->mpegSurroundUserParams; + } else { + err = MPS_INVALID_HANDLE; + /* check the parameter values before exiting. */ + } + + /* apply param value */ + switch (param) { + case SACDEC_OUTPUT_MODE: + switch ((SAC_DEC_OUTPUT_MODE)value) { + case SACDEC_OUT_MODE_NORMAL: + case SACDEC_OUT_MODE_STEREO: + break; + default: + err = MPS_INVALID_PARAMETER; + } + if (err == MPS_OK) { + if (0) { + err = MPS_INVALID_PARAMETER; + } else if (pUserParams->outputMode != (UCHAR)value) { + pUserParams->outputMode = (UCHAR)value; + pMpegSurroundDecoder + ->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_OUTPUT_MODE; + } + } + break; + + case SACDEC_INTERFACE: + if (value < 0 || value > 1) { + err = MPS_INVALID_PARAMETER; + } + if (err != MPS_OK) { + goto bail; + } + if (pMpegSurroundDecoder->mpegSurroundUseTimeInterface != (UCHAR)value) { + pMpegSurroundDecoder->mpegSurroundUseTimeInterface = (UCHAR)value; + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_TIME_FREQ_INTERFACE; + } + break; + + case SACDEC_BS_INTERRUPTION: + if ((err == MPS_OK) && (value != 0)) { + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_BS_INTERRUPTION, + MPEGS_SYNC_LOST, MPEGS_STOP); + } + break; + + case SACDEC_CLEAR_HISTORY: + if ((err == MPS_OK) && (value != 0)) { + /* Just reset the states and go on. */ + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_CLEAR_HISTORY, + MPEGS_SYNC_LOST, MPEGS_STOP); + } + break; + + case SACDEC_CONCEAL_NUM_KEEP_FRAMES: + if (value < 0) { /* Check valid value range */ + err = MPS_INVALID_PARAMETER; + } + if (err != MPS_OK) { + goto bail; + } + if (pUserParams->concealNumKeepFrames != (UINT)value) { + pUserParams->concealNumKeepFrames = (UINT)value; + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_CONCEAL_PARAMS; + } + break; + + case SACDEC_CONCEAL_FADE_OUT_SLOPE_LENGTH: + if (value < 0) { /* Check valid value range */ + err = MPS_INVALID_PARAMETER; + } + if (err != MPS_OK) { + goto bail; + } + if (pUserParams->concealFadeOutSlopeLength != (UINT)value) { + pUserParams->concealFadeOutSlopeLength = (UINT)value; + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_CONCEAL_PARAMS; + } + break; + + case SACDEC_CONCEAL_FADE_IN_SLOPE_LENGTH: + if (value < 0) { /* Check valid value range */ + err = MPS_INVALID_PARAMETER; + } + if (err != MPS_OK) { + goto bail; + } + if (pUserParams->concealFadeInSlopeLength != (UINT)value) { + pUserParams->concealFadeInSlopeLength = (UINT)value; + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_CONCEAL_PARAMS; + } + break; + + case SACDEC_CONCEAL_NUM_RELEASE_FRAMES: + if (value < 0) { /* Check valid value range */ + err = MPS_INVALID_PARAMETER; + } + if (err != MPS_OK) { + goto bail; + } + if (pUserParams->concealNumReleaseFrames != (UINT)value) { + pUserParams->concealNumReleaseFrames = (UINT)value; + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_CONCEAL_PARAMS; + } + break; + + default: + err = MPS_INVALID_PARAMETER; + break; + } /* switch(param) */ + +bail: + return err; +} + +SACDEC_ERROR mpegSurroundDecoder_IsPseudoLR( + CMpegSurroundDecoder *pMpegSurroundDecoder, int *bsPseudoLr) { + if (pMpegSurroundDecoder != NULL) { + const SPATIAL_SPECIFIC_CONFIG *sscDecode = + &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode]; + *bsPseudoLr = (int)sscDecode->bsPseudoLr; + return MPS_OK; + } else + return MPS_INVALID_HANDLE; +} + +/** + * \brief Get the signal delay caused by the MPEG Surround decoder module. + **/ +UINT mpegSurroundDecoder_GetDelay(const CMpegSurroundDecoder *self) { + INT outputDelay = 0; + + if (self != NULL) { + const SPATIAL_SPECIFIC_CONFIG *sscDecode = + &self->spatialSpecificConfig[self->bsFrameDecode]; + AUDIO_OBJECT_TYPE coreCodec = sscDecode->coreCodec; + + /* See chapter 4.5 (delay and synchronization) of ISO/IEC FDIS 23003-1 and + chapter 5.4.3 of ISO/IEC FDIS 23003-2 for details on the following + figures. */ + + if (coreCodec > AOT_NULL_OBJECT) { + if (IS_LOWDELAY(coreCodec)) { + /* All low delay variants (ER-AAC-(E)LD): */ + outputDelay += 256; + } else if (!IS_USAC(coreCodec)) { + /* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...) + * branch: */ + outputDelay += 320 + 257; /* cos to exp delay + QMF synthesis */ + if (self->mpegSurroundUseTimeInterface) { + outputDelay += 320 + 384; /* QMF and hybrid analysis */ + } + } + } + } + + return (outputDelay); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_ssc_struct.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_ssc_struct.h new file mode 100644 index 0000000000000..b67b465813987 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_dec_ssc_struct.h @@ -0,0 +1,283 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: interface - spatial specific config struct + +*******************************************************************************/ + +#ifndef SAC_DEC_SSC_STRUCT_H +#define SAC_DEC_SSC_STRUCT_H + +#include "FDK_audio.h" + +#define MAX_NUM_QMF_BANDS (128) +#define MAX_TIME_SLOTS 64 +#define MAX_INPUT_CHANNELS 1 +#define MAX_OUTPUT_CHANNELS \ + 2 /* CAUTION: This does NOT restrict the number of \ + output channels exclusively! In addition it \ + affects the max number of bitstream and residual channels! */ +#define MAX_NUM_OTT (5) +#define MAX_NUM_TTT (0) +#define MAX_NUM_EXT_TYPES (8) +#define MAX_PARAMETER_BANDS (28) +#define MAX_PARAMETER_BANDS_LD (23) + +#define MAX_NUM_XCHANNELS (6) + +#define MAX_ARBITRARY_TREE_LEVELS (0) + +typedef enum { + /* CAUTION: Do not change enum values! */ + SPATIALDEC_FREQ_RES_40 = 40, + SPATIALDEC_FREQ_RES_28 = 28, + SPATIALDEC_FREQ_RES_23 = 23, + SPATIALDEC_FREQ_RES_20 = 20, + SPATIALDEC_FREQ_RES_15 = 15, + SPATIALDEC_FREQ_RES_14 = 14, + SPATIALDEC_FREQ_RES_12 = 12, + SPATIALDEC_FREQ_RES_10 = 10, + SPATIALDEC_FREQ_RES_9 = 9, + SPATIALDEC_FREQ_RES_7 = 7, + SPATIALDEC_FREQ_RES_5 = 5, + SPATIALDEC_FREQ_RES_4 = 4 + +} SPATIALDEC_FREQ_RES; + +typedef enum { + + SPATIALDEC_QUANT_FINE_DEF = 0, + SPATIALDEC_QUANT_EDQ1 = 1, + SPATIALDEC_QUANT_EDQ2 = 2, + SPATIALDEC_QUANT_RSVD3 = 3, + SPATIALDEC_QUANT_RSVD4 = 4, + SPATIALDEC_QUANT_RSVD5 = 5, + SPATIALDEC_QUANT_RSVD6 = 6, + SPATIALDEC_QUANT_RSVD7 = 7 + +} SPATIALDEC_QUANT_MODE; + +typedef enum { SPATIALDEC_MODE_RSVD7 = 7 } SPATIALDEC_TREE_CONFIG; + +typedef enum { + + SPATIALDEC_GAIN_MODE0 = 0, + SPATIALDEC_GAIN_RSVD1 = 1, + SPATIALDEC_GAIN_RSVD2 = 2, + SPATIALDEC_GAIN_RSVD3 = 3, + SPATIALDEC_GAIN_RSVD4 = 4, + SPATIALDEC_GAIN_RSVD5 = 5, + SPATIALDEC_GAIN_RSVD6 = 6, + SPATIALDEC_GAIN_RSVD7 = 7, + SPATIALDEC_GAIN_RSVD8 = 8, + SPATIALDEC_GAIN_RSVD9 = 9, + SPATIALDEC_GAIN_RSVD10 = 10, + SPATIALDEC_GAIN_RSVD11 = 11, + SPATIALDEC_GAIN_RSVD12 = 12, + SPATIALDEC_GAIN_RSVD13 = 13, + SPATIALDEC_GAIN_RSVD14 = 14, + SPATIALDEC_GAIN_RSVD15 = 15 + +} SPATIALDEC_FIXED_GAINS; + +typedef enum { + + SPATIALDEC_TS_TPNOWHITE = 0, + SPATIALDEC_TS_TPWHITE = 1, + SPATIALDEC_TS_TES = 2, + SPATIALDEC_TS_NOTS = 3, + SPATIALDEC_TS_RSVD4 = 4, + SPATIALDEC_TS_RSVD5 = 5, + SPATIALDEC_TS_RSVD6 = 6, + SPATIALDEC_TS_RSVD7 = 7, + SPATIALDEC_TS_RSVD8 = 8, + SPATIALDEC_TS_RSVD9 = 9, + SPATIALDEC_TS_RSVD10 = 10, + SPATIALDEC_TS_RSVD11 = 11, + SPATIALDEC_TS_RSVD12 = 12, + SPATIALDEC_TS_RSVD13 = 13, + SPATIALDEC_TS_RSVD14 = 14, + SPATIALDEC_TS_RSVD15 = 15 + +} SPATIALDEC_TS_CONF; + +typedef enum { + + SPATIALDEC_DECORR_MODE0 = 0, + SPATIALDEC_DECORR_MODE1 = 1, + SPATIALDEC_DECORR_MODE2 = 2, + SPATIALDEC_DECORR_RSVD3 = 3, + SPATIALDEC_DECORR_RSVD4 = 4, + SPATIALDEC_DECORR_RSVD5 = 5, + SPATIALDEC_DECORR_RSVD6 = 6, + SPATIALDEC_DECORR_RSVD7 = 7, + SPATIALDEC_DECORR_RSVD8 = 8, + SPATIALDEC_DECORR_RSVD9 = 9, + SPATIALDEC_DECORR_RSVD10 = 10, + SPATIALDEC_DECORR_RSVD11 = 11, + SPATIALDEC_DECORR_RSVD12 = 12, + SPATIALDEC_DECORR_RSVD13 = 13, + SPATIALDEC_DECORR_RSVD14 = 14, + SPATIALDEC_DECORR_RSVD15 = 15 + +} SPATIALDEC_DECORR_CONF; + +typedef struct T_SPATIALDEC_OTT_CONF { + int nOttBands; + +} SPATIALDEC_OTT_CONF; + +typedef struct T_SPATIALDEC_RESIDUAL_CONF { + int bResidualPresent; + int nResidualBands; + +} SPATIALDEC_RESIDUAL_CONF; + +typedef struct T_SPATIAL_SPECIFIC_CONFIG { + UINT syntaxFlags; + int samplingFreq; + int nTimeSlots; + SPATIALDEC_FREQ_RES freqRes; + SPATIALDEC_TREE_CONFIG treeConfig; + SPATIALDEC_QUANT_MODE quantMode; + int bArbitraryDownmix; + + int bResidualCoding; + SPATIALDEC_FIXED_GAINS bsFixedGainDMX; + + SPATIALDEC_TS_CONF tempShapeConfig; + SPATIALDEC_DECORR_CONF decorrConfig; + + int nInputChannels; /* derived from treeConfig */ + int nOutputChannels; /* derived from treeConfig */ + + /* ott config */ + int nOttBoxes; /* derived from treeConfig */ + SPATIALDEC_OTT_CONF OttConfig[MAX_NUM_OTT]; /* dimension nOttBoxes */ + + /* ttt config */ + int nTttBoxes; /* derived from treeConfig */ + + /* residual config */ + SPATIALDEC_RESIDUAL_CONF + ResidualConfig[MAX_NUM_OTT + + MAX_NUM_TTT]; /* dimension (nOttBoxes + nTttBoxes) */ + + int sacExtCnt; + int sacExtType[MAX_NUM_EXT_TYPES]; + int envQuantMode; + + AUDIO_OBJECT_TYPE coreCodec; + + UCHAR stereoConfigIndex; + UCHAR coreSbrFrameLengthIndex; /* Table 70 in ISO/IEC FDIS 23003-3:2011 */ + UCHAR bsHighRateMode; + UCHAR bsDecorrType; + UCHAR bsPseudoLr; + UCHAR bsPhaseCoding; + UCHAR bsOttBandsPhasePresent; + int bsOttBandsPhase; + + SCHAR ottCLDdefault[MAX_NUM_OTT]; + UCHAR numOttBandsIPD; + UCHAR bitstreamOttBands[MAX_NUM_OTT]; + UCHAR numOttBands[MAX_NUM_OTT]; + +} SPATIAL_SPECIFIC_CONFIG; + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_process.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_process.cpp new file mode 100644 index 0000000000000..33a164765d511 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_process.cpp @@ -0,0 +1,1085 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Processing + +*******************************************************************************/ + +/* data structures and interfaces for spatial audio reference software */ +#include "sac_process.h" + +#include "sac_bitdec.h" +#include "sac_calcM1andM2.h" +#include "sac_smoothing.h" +#include "sac_rom.h" + +#include "sac_dec_errorcodes.h" + +#include "FDK_trigFcts.h" +#include "FDK_decorrelate.h" + +#define SAC_DEC_APPLY_M2_SCALE(spec, s) ((spec) >> (-(s))) + +/** + * \brief Linear interpolation between two parameter values. + * a*alpha + b*(1-alpha) + * = a*alpha + b - b*alpha + * + * \param alpha Weighting factor. + * \param a Parameter a. + * \param b Parameter b. + * + * \return Interpolated parameter value. + */ +FDK_INLINE FIXP_DBL interpolateParameter(const FIXP_SGL alpha, const FIXP_DBL a, + const FIXP_DBL b) { + return (b - fMult(alpha, b) + fMult(alpha, a)); +} + +/** + * \brief Map MPEG Surround channel indices to MPEG 4 PCE like channel indices. + * \param self Spatial decoder handle. + * \param ch MPEG Surround channel index. + * \return MPEG 4 PCE style channel index, corresponding to the given MPEG + * Surround channel index. + */ +static UINT mapChannel(spatialDec *self, UINT ch) { + static const UCHAR chanelIdx[][8] = { + {0, 1, 2, 3, 4, 5, 6, 7}, /* binaural, TREE_212, arbitrary tree */ + }; + + int idx = 0; + + return (chanelIdx[idx][ch]); +} + +FIXP_DBL getChGain(spatialDec *self, UINT ch, INT *scale) { + /* init no gain modifier */ + FIXP_DBL gain = 0x80000000; + *scale = 0; + + if ((!isTwoChMode(self->upmixType)) && + (self->upmixType != UPMIXTYPE_BYPASS)) { + if ((ch == 0) || (ch == 1) || (ch == 2)) { + /* no modifier */ + } + } + + return gain; +} + +SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData, + const INT ts, const INT bypassMode, + FIXP_DBL **qmfReal, FIXP_DBL **qmfImag, + const int numInputChannels) { + SACDEC_ERROR err = MPS_OK; + int ch, offset; + + offset = self->pQmfDomain->globalConf.nBandsSynthesis * + self->pQmfDomain->globalConf.nQmfTimeSlots; + + { + for (ch = 0; ch < numInputChannels; ch++) { + const PCM_MPS *inSamples = + &inData[ts * self->pQmfDomain->globalConf.nBandsAnalysis]; + FIXP_DBL *pQmfRealAnalysis = qmfReal[ch]; /* no delay in blind mode */ + FIXP_DBL *pQmfImagAnalysis = qmfImag[ch]; + + CalculateSpaceAnalysisQmf(&self->pQmfDomain->QmfDomainIn[ch].fb, + inSamples + (ch * offset), pQmfRealAnalysis, + pQmfImagAnalysis); + + if (!isTwoChMode(self->upmixType) && !bypassMode) { + int i; + for (i = 0; i < self->qmfBands; i++) { + qmfReal[ch][i] = fMult( + scaleValueSaturate(qmfReal[ch][i], self->sacInDataHeadroom - (1)), + self->clipProtectGain__FDK); + qmfImag[ch][i] = fMult( + scaleValueSaturate(qmfImag[ch][i], self->sacInDataHeadroom - (1)), + self->clipProtectGain__FDK); + } + } + } + } + + self->qmfInputDelayBufPos = + (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay; + + return err; +} + +SACDEC_ERROR SpatialDecFeedQMF(spatialDec *self, FIXP_DBL **qmfInDataReal, + FIXP_DBL **qmfInDataImag, const INT ts, + const INT bypassMode, FIXP_DBL **qmfReal__FDK, + FIXP_DBL **qmfImag__FDK, + const INT numInputChannels) { + SACDEC_ERROR err = MPS_OK; + int ch; + + { + for (ch = 0; ch < numInputChannels; ch++) { + FIXP_DBL *pQmfRealAnalysis = + qmfReal__FDK[ch]; /* no delay in blind mode */ + FIXP_DBL *pQmfImagAnalysis = qmfImag__FDK[ch]; + + /* Write Input data to pQmfRealAnalysis. */ + if (self->bShareDelayWithSBR) { + FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], + ts + HYBRID_FILTER_DELAY, 0, + MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis, + pQmfImagAnalysis, 15 + (1)); + FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, + MAX_QMF_BANDS_TO_HYBRID, self->qmfBands, + pQmfRealAnalysis, pQmfImagAnalysis, 15 + (1)); + } else { + FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 0, + self->qmfBands, pQmfRealAnalysis, + pQmfImagAnalysis, 15 + (1)); + } + if (ts == self->pQmfDomain->globalConf.nQmfTimeSlots - 1) { + /* Is currently also needed in case we dont have any overlap. We need to + * save lb_scale to ov_lb_scale */ + FDK_QmfDomain_SaveOverlap(&self->pQmfDomain->QmfDomainIn[ch], 0); + } + + /* Apply clip protection to output. */ + if (!isTwoChMode(self->upmixType) && !bypassMode) { + int i; + for (i = 0; i < self->qmfBands; i++) { + qmfReal__FDK[ch][i] = + fMult(qmfReal__FDK[ch][i], self->clipProtectGain__FDK); + qmfImag__FDK[ch][i] = + fMult(qmfImag__FDK[ch][i], self->clipProtectGain__FDK); + } + } + + } /* End of loop over numInputChannels */ + } + + self->qmfInputDelayBufPos = + (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay; + + return err; +} + +/******************************************************************************* + Functionname: SpatialDecHybridAnalysis + ******************************************************************************* + + Description: + + Arguments: + + Input: + float** pointers[4] leftReal, leftIm, rightReal, rightIm + + Output: + float self->qmfInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS]; + float self->qmfInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS]; + + float +self->hybInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS]; float +self->hybInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS]; + + +*******************************************************************************/ +SACDEC_ERROR SpatialDecHybridAnalysis(spatialDec *self, FIXP_DBL **qmfInputReal, + FIXP_DBL **qmfInputImag, + FIXP_DBL **hybOutputReal, + FIXP_DBL **hybOutputImag, const INT ts, + const INT numInputChannels) { + SACDEC_ERROR err = MPS_OK; + int ch; + + for (ch = 0; ch < numInputChannels; + ch++) /* hybrid filtering for down-mix signals */ + { + if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) { + int k; + /* No hybrid filtering. Just copy the QMF data. */ + for (k = 0; k < self->hybridBands; k += 1) { + hybOutputReal[ch][k] = qmfInputReal[ch][k]; + hybOutputImag[ch][k] = qmfInputImag[ch][k]; + } + } else { + self->hybridAnalysis[ch].hfMode = self->bShareDelayWithSBR; + + if (self->stereoConfigIndex == 3) + FDK_ASSERT(self->hybridAnalysis[ch].hfMode == 0); + FDKhybridAnalysisApply(&self->hybridAnalysis[ch], qmfInputReal[ch], + qmfInputImag[ch], hybOutputReal[ch], + hybOutputImag[ch]); + } + } + + if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) && + self->residualCoding) { + self->hybridAnalysis[numInputChannels].hfMode = 0; + FDKhybridAnalysisApply( + &self->hybridAnalysis[numInputChannels], + self->qmfResidualReal__FDK[0][0], self->qmfResidualImag__FDK[0][0], + self->hybResidualReal__FDK[0], self->hybResidualImag__FDK[0]); + } + + return err; +} + +SACDEC_ERROR SpatialDecCreateX(spatialDec *self, FIXP_DBL **hybInputReal, + FIXP_DBL **hybInputImag, FIXP_DBL **pxReal, + FIXP_DBL **pxImag) { + SACDEC_ERROR err = MPS_OK; + int row; + + /* Creating wDry */ + for (row = 0; row < self->numInputChannels; row++) { + /* pointer to direct signals */ + pxReal[row] = hybInputReal[row]; + pxImag[row] = hybInputImag[row]; + } + + return err; +} + +static void M2ParamToKernelMult(FIXP_SGL *RESTRICT pKernel, + FIXP_DBL *RESTRICT Mparam, + FIXP_DBL *RESTRICT MparamPrev, + int *RESTRICT pWidth, FIXP_SGL alpha__FDK, + int nBands) { + int pb; + + for (pb = 0; pb < nBands; pb++) { + FIXP_SGL tmp = FX_DBL2FX_SGL( + interpolateParameter(alpha__FDK, Mparam[pb], MparamPrev[pb])); + + int i = pWidth[pb]; + if (i & 1) *pKernel++ = tmp; + if (i & 2) { + *pKernel++ = tmp; + *pKernel++ = tmp; + } + for (i >>= 2; i--;) { + *pKernel++ = tmp; + *pKernel++ = tmp; + *pKernel++ = tmp; + *pKernel++ = tmp; + } + } +} + +SACDEC_ERROR SpatialDecApplyM1_CreateW_Mode212( + spatialDec *self, const SPATIAL_BS_FRAME *frame, FIXP_DBL **xReal, + FIXP_DBL **xImag, FIXP_DBL **vReal, FIXP_DBL **vImag) { + SACDEC_ERROR err = MPS_OK; + int res; + FIXP_DBL *decorrInReal = vReal[0]; + FIXP_DBL *decorrInImag = vImag[0]; + + /* M1 does not do anything in 212 mode, so use simplified processing */ + FDK_ASSERT(self->numVChannels == 2); + FDK_ASSERT(self->numDirektSignals == 1); + FDK_ASSERT(self->numDecorSignals == 1); + FDKmemcpy(vReal[0], xReal[0], self->hybridBands * sizeof(FIXP_DBL)); + FDKmemcpy(vImag[0], xImag[0], self->hybridBands * sizeof(FIXP_DBL)); + + if (isTsdActive(frame->TsdData)) { + /* Generate v_{x,nonTr} as input for allpass based decorrelator */ + TsdGenerateNonTr(self->hybridBands, frame->TsdData, self->TsdTs, vReal[0], + vImag[0], vReal[1], vImag[1], &decorrInReal, + &decorrInImag); + } + /* - Decorrelate */ + res = SpatialDecGetResidualIndex(self, 1); + if (FDKdecorrelateApply(&self->apDecor[0], decorrInReal, decorrInImag, + vReal[1], vImag[1], + self->param2hyb[self->residualBands[res]])) { + return MPS_NOTOK; + } + if (isTsdActive(frame->TsdData)) { + /* Generate v_{x,Tr}, apply transient decorrelator and add to allpass based + * decorrelator output */ + TsdApply(self->hybridBands, frame->TsdData, &self->TsdTs, + vReal[0], /* input: v_x */ + vImag[0], + vReal[1], /* input: d_{x,nonTr}; output: d_{x,nonTr} + d_{x,Tr} */ + vImag[1]); + } + + /* Write residual signal in approriate parameter bands */ + if (self->residualBands[res] > 0) { + int stopBand = self->param2hyb[self->residualBands[res]]; + FDKmemcpy(vReal[1], self->hybResidualReal__FDK[res], + fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL)); + FDKmemcpy(vImag[1], self->hybResidualImag__FDK[res], + fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL)); + } /* (self->residualBands[res]>0) */ + + return err; +} + +SACDEC_ERROR SpatialDecApplyM2_Mode212(spatialDec *self, INT ps, + const FIXP_SGL alpha, FIXP_DBL **wReal, + FIXP_DBL **wImag, + FIXP_DBL **hybOutputRealDry, + FIXP_DBL **hybOutputImagDry) { + SACDEC_ERROR err = MPS_OK; + INT row; + + INT *pWidth = self->kernels_width; + /* for stereoConfigIndex == 3 case hybridBands is < 71 */ + INT pb_max = self->kernels[self->hybridBands - 1] + 1; + INT max_row = self->numOutputChannels; + + INT M2_exp = 0; + if (self->residualCoding) M2_exp = 3; + + for (row = 0; row < max_row; row++) // 2 times + { + FIXP_DBL *Mparam0 = self->M2Real__FDK[row][0]; + FIXP_DBL *Mparam1 = self->M2Real__FDK[row][1]; + FIXP_DBL *MparamPrev0 = self->M2RealPrev__FDK[row][0]; + FIXP_DBL *MparamPrev1 = self->M2RealPrev__FDK[row][1]; + + FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row]; + FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row]; + + FIXP_DBL *RESTRICT pWReal0 = wReal[0]; + FIXP_DBL *RESTRICT pWReal1 = wReal[1]; + FIXP_DBL *RESTRICT pWImag0 = wImag[0]; + FIXP_DBL *RESTRICT pWImag1 = wImag[1]; + for (INT pb = 0; pb < pb_max; pb++) { + FIXP_DBL tmp0, tmp1; + + tmp0 = interpolateParameter(alpha, Mparam0[pb], MparamPrev0[pb]); + tmp1 = interpolateParameter(alpha, Mparam1[pb], MparamPrev1[pb]); + + INT i = pWidth[pb]; + + do // about 3-4 times + { + FIXP_DBL var0, var1, real, imag; + + var0 = *pWReal0++; + var1 = *pWReal1++; + real = fMultDiv2(var0, tmp0); + var0 = *pWImag0++; + real = fMultAddDiv2(real, var1, tmp1); + var1 = *pWImag1++; + imag = fMultDiv2(var0, tmp0); + *pHybOutRealDry++ = real << (1 + M2_exp); + imag = fMultAddDiv2(imag, var1, tmp1); + *pHybOutImagDry++ = imag << (1 + M2_exp); + } while (--i != 0); + } + } + return err; +} + +SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding( + spatialDec *self, INT ps, const FIXP_SGL alpha, FIXP_DBL **wReal, + FIXP_DBL **wImag, FIXP_DBL **hybOutputRealDry, + FIXP_DBL **hybOutputImagDry) { + SACDEC_ERROR err = MPS_OK; + INT row; + INT scale_param_m2; + INT *pWidth = self->kernels_width; + INT pb_max = self->kernels[self->hybridBands - 1] + 1; + + scale_param_m2 = SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2; + + for (row = 0; row < self->numM2rows; row++) { + INT qs, pb; + + FIXP_DBL *RESTRICT pWReal0 = wReal[0]; + FIXP_DBL *RESTRICT pWImag0 = wImag[0]; + FIXP_DBL *RESTRICT pWReal1 = wReal[1]; + FIXP_DBL *RESTRICT pWImag1 = wImag[1]; + + FIXP_DBL *MReal0 = self->M2Real__FDK[row][0]; + FIXP_DBL *MImag0 = self->M2Imag__FDK[row][0]; + FIXP_DBL *MReal1 = self->M2Real__FDK[row][1]; + FIXP_DBL *MRealPrev0 = self->M2RealPrev__FDK[row][0]; + FIXP_DBL *MImagPrev0 = self->M2ImagPrev__FDK[row][0]; + FIXP_DBL *MRealPrev1 = self->M2RealPrev__FDK[row][1]; + + FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row]; + FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row]; + + FDK_ASSERT(!(self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD)); + FDK_ASSERT((pWidth[0] + pWidth[1]) >= 3); + + for (pb = 0, qs = 3; pb < 2; pb++) { + INT s; + FIXP_DBL maxVal; + FIXP_DBL mReal1; + FIXP_DBL mReal0, mImag0; + FIXP_DBL iReal0, iImag0, iReal1; + + iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]); + iImag0 = -interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]); + iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]); + + maxVal = fAbs(iReal0) | fAbs(iImag0); + maxVal |= fAbs(iReal1); + + s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2); + + mReal0 = scaleValue(iReal0, s); + mImag0 = scaleValue(iImag0, s); + mReal1 = scaleValue(iReal1, s); + + s = scale_param_m2 - s; + + INT i = pWidth[pb]; + + do { + FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1; + + wReal0 = *pWReal0++; + wImag0 = *pWImag0++; + wReal1 = *pWReal1++; + wImag1 = *pWImag1++; + + cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0); + + *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s; + *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s; + + if (qs > 0) { + mImag0 = -mImag0; + qs--; + } + } while (--i != 0); + } + + for (; pb < pb_max; pb++) { + INT s; + FIXP_DBL maxVal; + FIXP_SGL mReal1; + FIXP_SGL mReal0, mImag0; + FIXP_DBL iReal0, iImag0, iReal1; + + iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]); + iImag0 = interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]); + iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]); + + maxVal = fAbs(iReal0) | fAbs(iImag0); + maxVal |= fAbs(iReal1); + + s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2); + + mReal0 = FX_DBL2FX_SGL(scaleValue(iReal0, s)); + mImag0 = FX_DBL2FX_SGL(scaleValue(iImag0, s)); + mReal1 = FX_DBL2FX_SGL(scaleValue(iReal1, s)); + + s = scale_param_m2 - s; + + INT i = pWidth[pb]; + + do { + FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1; + + wReal0 = *pWReal0++; + wImag0 = *pWImag0++; + wReal1 = *pWReal1++; + wImag1 = *pWImag1++; + + cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0); + + *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s; + *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s; + } while (--i != 0); + } + } + + return err; +} + +SACDEC_ERROR SpatialDecApplyM2(spatialDec *self, INT ps, const FIXP_SGL alpha, + FIXP_DBL **wReal, FIXP_DBL **wImag, + FIXP_DBL **hybOutputRealDry, + FIXP_DBL **hybOutputImagDry, + FIXP_DBL **hybOutputRealWet, + FIXP_DBL **hybOutputImagWet) { + SACDEC_ERROR err = MPS_OK; + + { + int qs, row, col; + int complexHybBands; + int complexParBands; + int scale_param_m2 = 0; + int toolsDisabled; + + UCHAR activParamBands; + FIXP_DBL *RESTRICT pWReal, *RESTRICT pWImag, *RESTRICT pHybOutRealDry, + *RESTRICT pHybOutImagDry, *RESTRICT pHybOutRealWet, + *RESTRICT pHybOutImagWet; + C_ALLOC_SCRATCH_START(pKernel, FIXP_SGL, MAX_HYBRID_BANDS); + + /* The wet signal is added to the dry signal directly in applyM2 if GES and + * STP are disabled */ + toolsDisabled = + ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) ? 0 : 1; + + { + complexHybBands = self->hybridBands; + complexParBands = self->numParameterBands; + } + + FDKmemclear(hybOutputImagDry[0], + self->createParams.maxNumOutputChannels * + self->createParams.maxNumCmplxHybBands * sizeof(FIXP_DBL)); + FDKmemclear(hybOutputRealDry[0], self->createParams.maxNumOutputChannels * + self->createParams.maxNumHybridBands * + sizeof(FIXP_DBL)); + + if (!toolsDisabled) { + FDKmemclear(hybOutputRealWet[0], + self->createParams.maxNumOutputChannels * + self->createParams.maxNumHybridBands * sizeof(FIXP_DBL)); + FDKmemclear(hybOutputImagWet[0], + self->createParams.maxNumOutputChannels * + self->createParams.maxNumCmplxHybBands * + sizeof(FIXP_DBL)); + } + + if (self->phaseCoding == 3) { + scale_param_m2 = -(SCALE_DATA_APPLY_M2_PC - 1); + } + + for (row = 0; row < self->numM2rows; row++) { + pHybOutRealDry = hybOutputRealDry[row]; + pHybOutImagDry = hybOutputImagDry[row]; + + if (toolsDisabled) { + pHybOutRealWet = hybOutputRealDry[row]; + pHybOutImagWet = hybOutputImagDry[row]; + } else { + pHybOutRealWet = hybOutputRealWet[row]; + pHybOutImagWet = hybOutputImagWet[row]; + } + + for (col = 0; col < self->numDirektSignals; col++) { + if (self->pActivM2ParamBands == + 0) { /* default setting, calculate all rows and columns */ + activParamBands = 1; + } else { + if (self->pActivM2ParamBands[MAX_M2_INPUT * row + + col]) /* table with activ and inactiv + bands exists for current + configuration */ + activParamBands = 1; + else + activParamBands = 0; + } + if (activParamBands) { + pWReal = wReal[col]; + pWImag = wImag[col]; + + M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col], + self->M2RealPrev__FDK[row][col], + self->kernels_width, alpha, + self->numParameterBands); + + if (1 && (self->phaseCoding != 3)) { + /* direct signals */ + { + /* only one sample will be assigned to each row, hence + * accumulation is not neccessary; that is valid for all + * configurations */ + for (qs = 0; qs < complexHybBands; qs++) { + pHybOutRealDry[qs] = fMult(pWReal[qs], pKernel[qs]); + pHybOutImagDry[qs] = fMult(pWImag[qs], pKernel[qs]); + } + } + } else { /* isBinauralMode(self->upmixType) */ + + for (qs = 0; qs < complexHybBands; qs++) { + pHybOutRealDry[qs] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2); + pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2); + } + + M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col], + self->M2ImagPrev__FDK[row][col], + self->kernels_width, alpha, complexParBands); + + /* direct signals sign is -1 for qs = 0,2 */ + pHybOutRealDry[0] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2); + pHybOutImagDry[0] -= SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2); + + pHybOutRealDry[2] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2); + pHybOutImagDry[2] -= SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2); + + /* direct signals sign is +1 for qs = 1,3,4,5,...,complexHybBands */ + pHybOutRealDry[1] -= SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2); + pHybOutImagDry[1] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2); + + for (qs = 3; qs < complexHybBands; qs++) { + pHybOutRealDry[qs] -= SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2); + pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2); + } + } /* self->upmixType */ + } /* if (activParamBands) */ + } /* self->numDirektSignals */ + + for (; col < self->numVChannels; col++) { + if (self->pActivM2ParamBands == + 0) { /* default setting, calculate all rows and columns */ + activParamBands = 1; + } else { + if (self->pActivM2ParamBands[MAX_M2_INPUT * row + + col]) /* table with activ and inactiv + bands exists for current + configuration */ + activParamBands = 1; + else + activParamBands = 0; + } + + if (activParamBands) { + int resBandIndex; + int resHybIndex; + + resBandIndex = + self->residualBands[SpatialDecGetResidualIndex(self, col)]; + resHybIndex = self->param2hyb[resBandIndex]; + + pWReal = wReal[col]; + pWImag = wImag[col]; + + M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col], + self->M2RealPrev__FDK[row][col], + self->kernels_width, alpha, + self->numParameterBands); + + if (1 && (self->phaseCoding != 3)) { + /* residual signals */ + for (qs = 0; qs < resHybIndex; qs++) { + pHybOutRealDry[qs] += fMult(pWReal[qs], pKernel[qs]); + pHybOutImagDry[qs] += fMult(pWImag[qs], pKernel[qs]); + } + /* decor signals */ + for (; qs < complexHybBands; qs++) { + pHybOutRealWet[qs] += fMult(pWReal[qs], pKernel[qs]); + pHybOutImagWet[qs] += fMult(pWImag[qs], pKernel[qs]); + } + } else { /* self->upmixType */ + /* residual signals */ + FIXP_DBL *RESTRICT pHybOutReal; + FIXP_DBL *RESTRICT pHybOutImag; + + for (qs = 0; qs < resHybIndex; qs++) { + pHybOutRealDry[qs] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2); + pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2); + } + /* decor signals */ + for (; qs < complexHybBands; qs++) { + pHybOutRealWet[qs] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2); + pHybOutImagWet[qs] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2); + } + + M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col], + self->M2ImagPrev__FDK[row][col], + self->kernels_width, alpha, complexParBands); + + /* direct signals sign is -1 for qs = 0,2 */ + /* direct signals sign is +1 for qs = 1,3.. */ + if (toolsDisabled) { + pHybOutRealDry[0] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2); + pHybOutImagDry[0] -= SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2); + + pHybOutRealDry[1] -= SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2); + pHybOutImagDry[1] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2); + + pHybOutRealDry[2] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2); + pHybOutImagDry[2] -= SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2); + } else { + pHybOutReal = &pHybOutRealDry[0]; + pHybOutImag = &pHybOutImagDry[0]; + if (0 == resHybIndex) { + pHybOutReal = &pHybOutRealWet[0]; + pHybOutImag = &pHybOutImagWet[0]; + } + pHybOutReal[0] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2); + pHybOutImag[0] -= SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2); + + if (1 == resHybIndex) { + pHybOutReal = &pHybOutRealWet[0]; + pHybOutImag = &pHybOutImagWet[0]; + } + pHybOutReal[1] -= SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2); + pHybOutImag[1] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2); + + if (2 == resHybIndex) { + pHybOutReal = &pHybOutRealWet[0]; + pHybOutImag = &pHybOutImagWet[0]; + } + pHybOutReal[2] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2); + pHybOutImag[2] -= SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2); + } + + for (qs = 3; qs < resHybIndex; qs++) { + pHybOutRealDry[qs] -= SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2); + pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2); + } + /* decor signals */ + for (; qs < complexHybBands; qs++) { + pHybOutRealWet[qs] -= SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2); + pHybOutImagWet[qs] += SAC_DEC_APPLY_M2_SCALE( + fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2); + } + } /* self->upmixType */ + } /* if (activParamBands) { */ + } /* self->numVChannels */ + + if (self->phaseCoding == 3) { + scaleValuesSaturate(pHybOutRealDry, complexHybBands, + SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC); + scaleValuesSaturate(pHybOutImagDry, complexHybBands, + SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC); + + if (!toolsDisabled) { + scaleValuesSaturate(pHybOutRealWet, complexHybBands, + SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC); + scaleValuesSaturate(pHybOutImagWet, complexHybBands, + SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC); + } + } + } + + C_ALLOC_SCRATCH_END(pKernel, FIXP_SGL, MAX_HYBRID_BANDS); + } + + return err; +} + +SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts, + FIXP_DBL **hybOutputReal, + FIXP_DBL **hybOutputImag, PCM_MPS *timeOut, + const INT numInputChannels, + const FDK_channelMapDescr *const mapDescr) { + SACDEC_ERROR err = MPS_OK; + + int ch; + int stride, offset; + + stride = self->numOutputChannelsAT; + offset = 1; + + PCM_MPS *pTimeOut__FDK = + &timeOut[stride * self->pQmfDomain->globalConf.nBandsSynthesis * ts]; + C_ALLOC_SCRATCH_START(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS); + C_ALLOC_SCRATCH_START(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS); + + for (ch = 0; ch < self->numOutputChannelsAT; ch++) { + if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) { + int k; + /* No hybrid filtering. Just copy the QMF data. */ + for (k = 0; k < self->hybridBands; k += 1) { + pQmfReal[k] = hybOutputReal[ch][k]; + pQmfImag[k] = hybOutputImag[ch][k]; + } + } else { + FDKhybridSynthesisApply(&self->hybridSynthesis[ch], hybOutputReal[ch], + hybOutputImag[ch], pQmfReal, pQmfImag); + } + + /* Map channel indices from MPEG Surround -> PCE style -> channelMapping[] + */ + FDK_ASSERT(self->numOutputChannelsAT <= 6); + int outCh = FDK_chMapDescr_getMapValue(mapDescr, mapChannel(self, ch), + self->numOutputChannelsAT); + + { + if (self->stereoConfigIndex == 3) { + /* MPS -> SBR */ + int i; + FIXP_DBL *pWorkBufReal, *pWorkBufImag; + FDK_ASSERT((self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_m == + (FIXP_DBL)0x80000000) && + (self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_e == 0)); + FDK_QmfDomain_GetWorkBuffer(&self->pQmfDomain->QmfDomainIn[outCh], ts, + &pWorkBufReal, &pWorkBufImag); + FDK_ASSERT(self->qmfBands <= + self->pQmfDomain->QmfDomainIn[outCh].workBuf_nBands); + for (i = 0; i < self->qmfBands; i++) { + pWorkBufReal[i] = pQmfReal[i]; + pWorkBufImag[i] = pQmfImag[i]; + } + self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale = + -7; /*-ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK;*/ + self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= + self->pQmfDomain->QmfDomainIn[outCh].fb.filterScale; + self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= + self->clipProtectGainSF__FDK; + + self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= (1); + } else { + /* Call the QMF synthesis for dry. */ + err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh], + pQmfReal, pQmfImag, stride, + pTimeOut__FDK + (offset * outCh)); + } + if (err != MPS_OK) goto bail; + } + } /* ch loop */ + +bail: + C_ALLOC_SCRATCH_END(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS); + C_ALLOC_SCRATCH_END(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS); + + return err; +} + +void SpatialDecBufferMatrices(spatialDec *self) { + int row, col; + int complexParBands; + complexParBands = self->numParameterBands; + + /* + buffer matrices M2 + */ + for (row = 0; row < self->numM2rows; row++) { + for (col = 0; col < self->numVChannels; col++) { + FDKmemcpy(self->M2RealPrev__FDK[row][col], self->M2Real__FDK[row][col], + self->numParameterBands * sizeof(FIXP_DBL)); + if (0 || (self->phaseCoding == 3)) { + FDKmemcpy(self->M2ImagPrev__FDK[row][col], self->M2Imag__FDK[row][col], + complexParBands * sizeof(FIXP_DBL)); + } + } + } + + /* buffer phase */ + FDKmemcpy(self->PhasePrevLeft__FDK, self->PhaseLeft__FDK, + self->numParameterBands * sizeof(FIXP_DBL)); + FDKmemcpy(self->PhasePrevRight__FDK, self->PhaseRight__FDK, + self->numParameterBands * sizeof(FIXP_DBL)); +} + +#define PHASE_SCALE 2 + +#ifndef P_PI +#define P_PI 3.1415926535897932 +#endif + +/* For better precision, PI (pi_x2) is already doubled */ +static FIXP_DBL interp_angle__FDK(FIXP_DBL angle1, FIXP_DBL angle2, + FIXP_SGL alpha, FIXP_DBL pi_x2) { + if (angle2 - angle1 > (pi_x2 >> 1)) angle2 -= pi_x2; + + if (angle1 - angle2 > (pi_x2 >> 1)) angle1 -= pi_x2; + + return interpolateParameter(alpha, angle2, angle1); +} + +/* + * + */ +void SpatialDecApplyPhase(spatialDec *self, FIXP_SGL alpha__FDK, + int lastSlotOfParamSet) { + int pb, qs; + FIXP_DBL ppb[MAX_PARAMETER_BANDS * + 4]; /* left real, imag - right real, imag interleaved */ + + const FIXP_DBL pi_x2 = PIx2__IPD; + for (pb = 0; pb < self->numParameterBands; pb++) { + FIXP_DBL pl, pr; + + pl = interp_angle__FDK(self->PhasePrevLeft__FDK[pb], + self->PhaseLeft__FDK[pb], alpha__FDK, pi_x2); + pr = interp_angle__FDK(self->PhasePrevRight__FDK[pb], + self->PhaseRight__FDK[pb], alpha__FDK, pi_x2); + + inline_fixp_cos_sin(pl, pr, IPD_SCALE, &ppb[4 * pb]); + } + + /* sign is -1 for qs = 0,2 and +1 for qs = 1 */ + + const SCHAR *kernels = &self->kernels[0]; + + FIXP_DBL *Dry_real0 = &self->hybOutputRealDry__FDK[0][0]; + FIXP_DBL *Dry_imag0 = &self->hybOutputImagDry__FDK[0][0]; + FIXP_DBL *Dry_real1 = &self->hybOutputRealDry__FDK[1][0]; + FIXP_DBL *Dry_imag1 = &self->hybOutputImagDry__FDK[1][0]; + + for (qs = 2; qs >= 0; qs--) { + FIXP_DBL out_re, out_im; + + pb = *kernels++; + if (qs == 1) /* sign[qs] >= 0 */ + { + cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0], + ppb[4 * pb + 1]); + out_re <<= PHASE_SCALE - 1; + out_im <<= PHASE_SCALE - 1; + *Dry_real0++ = out_re; + *Dry_imag0++ = out_im; + + cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2], + ppb[4 * pb + 3]); + out_re <<= PHASE_SCALE - 1; + out_im <<= PHASE_SCALE - 1; + *Dry_real1++ = out_re; + *Dry_imag1++ = out_im; + } else { + cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0], + -ppb[4 * pb + 1]); + out_re <<= PHASE_SCALE - 1; + out_im <<= PHASE_SCALE - 1; + *Dry_real0++ = out_re; + *Dry_imag0++ = out_im; + + cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2], + -ppb[4 * pb + 3]); + out_re <<= PHASE_SCALE - 1; + out_im <<= PHASE_SCALE - 1; + *Dry_real1++ = out_re; + *Dry_imag1++ = out_im; + } + } + + /* sign is +1 for qs >=3 */ + for (qs = self->hybridBands - 3; qs--;) { + FIXP_DBL out_re, out_im; + + pb = *kernels++; + cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0], + ppb[4 * pb + 1]); + out_re <<= PHASE_SCALE - 1; + out_im <<= PHASE_SCALE - 1; + *Dry_real0++ = out_re; + *Dry_imag0++ = out_im; + + cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2], + ppb[4 * pb + 3]); + out_re <<= PHASE_SCALE - 1; + out_im <<= PHASE_SCALE - 1; + *Dry_real1++ = out_re; + *Dry_imag1++ = out_im; + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_process.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_process.h new file mode 100644 index 0000000000000..ee2f2fea722ec --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_process.h @@ -0,0 +1,297 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Processing + +*******************************************************************************/ + +/*! + \file + \brief Polyphase Filterbank +*/ + +#ifndef SAC_PROCESS_H +#define SAC_PROCESS_H + +#include "sac_dec.h" + +void SpatialDecApplyPhase(spatialDec *self, FIXP_SGL alpha, + int lastSlotOfParamSet); + +/** + * \brief Apply QMF Analysis Filterbank. + * + * Calculates qmf data on downmix input time data. + * Delaylines will be applied if necessaray. + * + * \param self A spatial decoder handle. + * \param inData Downmix channel time data as input. + * \param ts Signals time slot offset for input buffer. + * \param qmfReal Downmix channel qmf output data. + * \param qmfImag Downmix channel qmf output data. + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData, + const INT ts, const INT bypassMode, + FIXP_DBL **qmfReal, FIXP_DBL **qmfImag, + const int numInputChannels); + +/** + * \brief Feed spatial decoder with external qmf data. + * + * \param self A spatial decoder handle. + * \param qmfInDataReal External qmf downmix data as input. + * \param qmfInDataImag External qmf downmix data as input. + * \param ts Signals time slot in input buffer to process. + * \param qmfReal Downmix channel qmf output data. + * \param qmfImag Downmix channel qmf output data. + * \param numInputChannels Number of input channels. Might differ from + * self->numInputChannels. + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecFeedQMF(spatialDec *self, FIXP_DBL **qmfInDataReal, + FIXP_DBL **qmfInDataImag, const INT ts, + const INT bypassMode, FIXP_DBL **qmfReal, + FIXP_DBL **qmfImag, const INT numInputChannels); + +/** + * \brief Apply Hybrdid Analysis Filterbank. + * + * Calculates hybrid data on downmix input data. + * Residual hybrid signals will also be calculated on current slot if available. + * + * \param self A spatial decoder handle. + * \param qmfInputReal Downmix channel qmf data as input. + * \param qmfInputImag Downmix channel qmf data as input. + * \param hybOutputReal Downmix channel hybrid output data. + * \param hybOutputImag Downmix channel hybrid output data. + * \param ts Signals time slot in spatial frame to process. + * \param numInputChannels Number of input channels. Might differ from + * self->numInputChannels. + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecHybridAnalysis(spatialDec *self, FIXP_DBL **qmfInputReal, + FIXP_DBL **qmfInputImag, + FIXP_DBL **hybOutputReal, + FIXP_DBL **hybOutputImag, const INT ts, + const INT numInputChannels); + +/** + * \brief Create X data. + * + * Returns a pointer list over Xchannels pointing to downmix input channels + * and to residual channels when provided. + * + * \param self A spatial decoder handle. + * \param hybInputReal Downmix channel hybrid data as input. + * \param hybInputImag Downmix channel hybrid data as input. + * \param pxReal Pointer to hybrid and residual data as output. + * \param pxImag Pointer to hybrid and residual data as output. + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecCreateX(spatialDec *self, FIXP_DBL **hybInputReal, + FIXP_DBL **hybInputImag, FIXP_DBL **pxReal, + FIXP_DBL **pxImag); + +/** + * \brief MPS212 combined version of apply M1 parameters and create wet signal + * + * \param self A spatial decoder handle. + * \param xReal Downmix and residual X data as input. + * \param xImag Downmix and residual X data as input. + * \param vReal output data: [0] direct signal (V); [1] wet signal + * (W). + * \param vImag output data: [0] direct signal (V); [1] wet signal + * (W). + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecApplyM1_CreateW_Mode212( + spatialDec *self, const SPATIAL_BS_FRAME *frame, FIXP_DBL **xReal, + FIXP_DBL **xImag, FIXP_DBL **vReal, FIXP_DBL **vImag); + +/** + * \brief Apply M2 parameters. + * + * \param self A spatial decoder handle. + * \param ps Signals parameter band from where M2 parameter to + * use. + * \param alpha Smoothing factor between current and previous + * parameter band. Rangeability between 0.f and 1.f. + * \param wReal Wet input data. + * \param wImag Wet input data. + * \param hybOutputRealDry Dry output data. + * \param hybOutputImagDry Dry output data. + * \param hybOutputRealWet Wet output data. + * \param hybOutputImagWet Wet output data. + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecApplyM2(spatialDec *self, INT ps, const FIXP_SGL alpha, + FIXP_DBL **wReal, FIXP_DBL **wImag, + FIXP_DBL **hybOutputRealDry, + FIXP_DBL **hybOutputImagDry, + FIXP_DBL **hybOutputRealWet, + FIXP_DBL **hybOutputImagWet); + +/** + * \brief Apply M2 parameter for 212 mode with residualCoding and phaseCoding. + * + * \param self [i] A spatial decoder handle. + * \param ps [i] Signals parameter band from where M2 parameter + * to use. + * \param alpha [i] Smoothing factor between current and previous + * parameter band. Rangeability between 0.f and 1.f. + * \param wReal [i] Wet input data. + * \param wImag [i] Wet input data. + * \param hybOutputRealDry [o] Dry output data. + * \param hybOutputImagDry [o] Dry output data. + * + * \return error + */ +SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding( + spatialDec *self, INT ps, const FIXP_SGL alpha, FIXP_DBL **wReal, + FIXP_DBL **wImag, FIXP_DBL **hybOutputRealDry, FIXP_DBL **hybOutputImagDry); + +/** + * \brief Apply M2 parameter for 212 mode, upmix from mono to stereo. + * + * \param self [i] A spatial decoder handle. + * \param ps [i] Signals parameter band from where M2 parameter + * to use. + * \param alpha [i] Smoothing factor between current and previous + * parameter band. Rangeability between 0.f and 1.f. + * \param wReal [i] Wet input data. + * \param wImag [i] Wet input data. + * \param hybOutputRealDry [o] Dry output data. + * \param hybOutputImagDry [o] Dry output data. + * + * \return error + */ +SACDEC_ERROR SpatialDecApplyM2_Mode212(spatialDec *self, INT ps, + const FIXP_SGL alpha, FIXP_DBL **wReal, + FIXP_DBL **wImag, + FIXP_DBL **hybOutputRealDry, + FIXP_DBL **hybOutputImagDry); + +/** + * \brief Convert Hybrid input to output audio data. + * + * \param hSpaceSynthesisQmf A spatial decoder handle. + * \param ts Signals time slot in spatial frame to process. + * \param hybOutputReal Hybrid data as input. + * \param hybOutputImag Hybrid data as input. + * \param timeOut audio output data. + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts, + FIXP_DBL **hybOutputReal, + FIXP_DBL **hybOutputImag, PCM_MPS *timeOut, + const INT numInputChannels, + const FDK_channelMapDescr *const mapDescr); + +void SpatialDecBufferMatrices(spatialDec *self); + +FIXP_DBL getChGain(spatialDec *self, UINT ch, INT *scale); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_qmf.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_qmf.cpp new file mode 100644 index 0000000000000..fd7599da4bf55 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_qmf.cpp @@ -0,0 +1,156 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec QMF processing + +*******************************************************************************/ + +#include "sac_qmf.h" + +#include "FDK_matrixCalloc.h" +#include "sac_dec_interface.h" +#include "sac_rom.h" + +#include "qmf.h" + +SACDEC_ERROR CalculateSpaceSynthesisQmf( + const HANDLE_FDK_QMF_DOMAIN_OUT hQmfDomainOutCh, const FIXP_DBL *Sr, + const FIXP_DBL *Si, const INT stride, PCM_MPS *timeSig) { + SACDEC_ERROR err = MPS_OK; + + if (hQmfDomainOutCh == NULL) { + err = MPS_INVALID_HANDLE; + } else { + HANDLE_SPACE_SYNTHESIS_QMF hSpaceSynthesisQmf = &hQmfDomainOutCh->fb; +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, + (QMF_MAX_SYNTHESIS_BANDS << 1)); +#else + C_AALLOC_STACK_START(pWorkBuffer, FIXP_DBL, (QMF_MAX_SYNTHESIS_BANDS << 1)); +#endif + + qmfSynthesisFilteringSlot(hSpaceSynthesisQmf, Sr, Si, 0, 0, timeSig, stride, + pWorkBuffer); + +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (QMF_MAX_SYNTHESIS_BANDS << 1)); +#else + C_AALLOC_STACK_END(pWorkBuffer, FIXP_DBL, (QMF_MAX_SYNTHESIS_BANDS << 1)); +#endif + } + + return err; +} + +SACDEC_ERROR CalculateSpaceAnalysisQmf( + HANDLE_SPACE_ANALYSIS_QMF hSpaceAnalysisQmf, const PCM_MPS *timeSig, + FIXP_DBL *Sr, FIXP_DBL *Si) { + SACDEC_ERROR err = MPS_OK; + + if (hSpaceAnalysisQmf == NULL) { + err = MPS_INVALID_HANDLE; + } else { + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (64 << 1)); + + qmfAnalysisFilteringSlot(hSpaceAnalysisQmf, Sr, Si, timeSig, 1, + pWorkBuffer); + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (64 << 1)); + } + + return err; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_qmf.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_qmf.h new file mode 100644 index 0000000000000..5cd573e6e3e68 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_qmf.h @@ -0,0 +1,143 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec QMF processing + +*******************************************************************************/ + +#ifndef SAC_QMF_H +#define SAC_QMF_H + +#include "common_fix.h" + +#include "sac_dec_interface.h" + +#include "FDK_qmf_domain.h" +#define HANDLE_SPACE_ANALYSIS_QMF HANDLE_QMF_FILTER_BANK +#define HANDLE_SPACE_SYNTHESIS_QMF HANDLE_QMF_FILTER_BANK + +/** + * \brief Convert Qmf input to output audio data. + * + * \param hSpaceSynthesisQmf A Qmf Synthesis Filterbank handle. + * \param Sr Pointer to Qmf input buffer. + * \param Si Pointer to Qmf input buffer. + * \param stride Stride factor for output data, 1 if none. + * \param timeSig (None-)Interleaved audio output data. + * + * \return Error status. + */ +SACDEC_ERROR CalculateSpaceSynthesisQmf( + const HANDLE_FDK_QMF_DOMAIN_OUT hQmfDomainOutCh, const FIXP_DBL *Sr, + const FIXP_DBL *Si, const INT stride, PCM_MPS *timeSig); + +/** + * \brief Convert audio input data to qmf representation. + * + * \param hSpaceAnalysisQmf A Qmf Analysis Filterbank handle. + * \param timeSig (None-)Interleavd audio input data. + * \param Sr Pointer to Qmf output buffer. + * \param Si Pointer to Qmf output buffer. + * + * \return Error status. + */ +SACDEC_ERROR CalculateSpaceAnalysisQmf( + HANDLE_SPACE_ANALYSIS_QMF hSpaceAnalysisQmf, const PCM_MPS *timeSig, + FIXP_DBL *Sr, FIXP_DBL *Si); + +#endif /* SAC_QMF_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_reshapeBBEnv.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_reshapeBBEnv.cpp new file mode 100644 index 0000000000000..72f4e58072149 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_reshapeBBEnv.cpp @@ -0,0 +1,678 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec guided envelope shaping + +*******************************************************************************/ + +#include "sac_reshapeBBEnv.h" + +#include "sac_dec.h" +#include "sac_bitdec.h" +#include "sac_calcM1andM2.h" +#include "sac_reshapeBBEnv.h" +#include "sac_rom.h" + +#define INP_DRY_WET 0 +#define INP_DMX 1 + +#define SF_SHAPE 1 +#define SF_DIV32 6 +#define SF_FACTOR_SLOT 5 + +#define START_BB_ENV 0 /* 10 */ +#define END_BB_ENV 9 /* 18 */ + +#define SF_ALPHA1 8 +#define SF_BETA1 4 + +void initBBEnv(spatialDec *self, int initStatesFlag) { + INT ch, k; + + for (ch = 0; ch < self->numOutputChannels; ch++) { + k = row2channelGES[self->treeConfig][ch]; + self->row2channelDmxGES[ch] = k; + if (k == -1) continue; + + switch (self->treeConfig) { + case TREE_212: + self->row2channelDmxGES[ch] = 0; + break; + default:; + } + } + + if (initStatesFlag) { + for (k = 0; k < 2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS; k++) { + self->reshapeBBEnvState->normNrgPrev__FDK[k] = + FL2FXCONST_DBL(0.5f); /* 32768.f*32768.f */ + self->reshapeBBEnvState->normNrgPrevSF[k] = DFRACT_BITS - 1; + self->reshapeBBEnvState->partNrgPrevSF[k] = 0; + self->reshapeBBEnvState->partNrgPrev2SF[k] = 0; + self->reshapeBBEnvState->frameNrgPrevSF[k] = 0; + } + } + + self->reshapeBBEnvState->alpha__FDK = + FL2FXCONST_DBL(0.99637845575f); /* FDKexp(-64 / (0.4f * 44100)) */ + self->reshapeBBEnvState->beta__FDK = + FL2FXCONST_DBL(0.96436909488f); /* FDKexp(-64 / (0.04f * 44100)) */ +} + +static inline void getSlotNrgHQ(FIXP_DBL *RESTRICT pReal, + FIXP_DBL *RESTRICT pImag, + FIXP_DBL *RESTRICT slotNrg, INT maxValSF, + INT hybBands) { + INT qs; + FIXP_DBL nrg; + + /* qs = 12, 13, 14 */ + slotNrg[0] = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + slotNrg[1] = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + slotNrg[2] = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + /* qs = 15 */ + slotNrg[3] = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + /* qs = 16, 17 */ + nrg = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + slotNrg[4] = + nrg + ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + /* qs = 18, 19, 20 */ + nrg = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + nrg += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + slotNrg[5] = + nrg + ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + /* qs = 21, 22 */ + nrg = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + slotNrg[6] = + nrg + ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + /* qs = 23, 24 */ + if (hybBands > 23) { + slotNrg[6] += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + slotNrg[6] += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + /* qs = 25, 26, 29, 28, 29 */ + nrg = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + nrg += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + nrg += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + nrg += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + slotNrg[7] = + nrg + ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + /* qs = 30 ... min(41,hybBands-1) */ + nrg = ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + for (qs = 31; qs < hybBands; qs++) { + nrg += ((fPow2Div2((*pReal++) << maxValSF) >> (SF_FACTOR_SLOT - 1)) + + (fPow2Div2((*pImag++) << maxValSF) >> (SF_FACTOR_SLOT - 1))); + } + slotNrg[8] = nrg; + } else { + slotNrg[7] = (FIXP_DBL)0; + slotNrg[8] = (FIXP_DBL)0; + } +} + +static inline void combineDryWet(FIXP_DBL *RESTRICT pReal, + FIXP_DBL *RESTRICT pImag, + FIXP_DBL *RESTRICT pHybOutputRealDry, + FIXP_DBL *RESTRICT pHybOutputImagDry, + FIXP_DBL *RESTRICT pHybOutputRealWet, + FIXP_DBL *RESTRICT pHybOutputImagWet, + INT cplxBands, INT hybBands) { + INT qs; + + for (qs = 12; qs < cplxBands; qs++) { + pReal[qs] = (pHybOutputRealDry[qs] >> 1) + (pHybOutputRealWet[qs] >> 1); + pImag[qs] = (pHybOutputImagDry[qs] >> 1) + (pHybOutputImagWet[qs] >> 1); + } + for (; qs < hybBands; qs++) { + pReal[qs] = (pHybOutputRealDry[qs] >> 1) + (pHybOutputRealWet[qs] >> 1); + } +} + +static inline void slotAmp( + FIXP_DBL *RESTRICT slotAmp_dry, INT *RESTRICT slotAmp_dry_e, + FIXP_DBL *RESTRICT slotAmp_wet, INT *RESTRICT slotAmp_wet_e, + FIXP_DBL *RESTRICT pHybOutputRealDry, FIXP_DBL *RESTRICT pHybOutputImagDry, + FIXP_DBL *RESTRICT pHybOutputRealWet, FIXP_DBL *RESTRICT pHybOutputImagWet, + INT cplxBands, INT hybBands) { + INT qs, s1, s2, headroom_dry, headroom_wet; + FIXP_DBL dry, wet; + + /* headroom can be reduced by 1 bit due to use of fPow2Div2 */ + s1 = DFRACT_BITS - 1 - CntLeadingZeros(hybBands + cplxBands); + headroom_dry = fMin(getScalefactor(pHybOutputRealDry, hybBands), + getScalefactor(pHybOutputImagDry, cplxBands)); + headroom_wet = fMin(getScalefactor(pHybOutputRealWet, hybBands), + getScalefactor(pHybOutputImagWet, cplxBands)); + + dry = wet = FL2FXCONST_DBL(0.0f); + for (qs = 0; qs < cplxBands; qs++) { + /* sum up dry part */ + dry += (fPow2Div2(pHybOutputRealDry[qs] << headroom_dry) >> s1); + dry += (fPow2Div2(pHybOutputImagDry[qs] << headroom_dry) >> s1); + /* sum up wet part */ + wet += (fPow2Div2(pHybOutputRealWet[qs] << headroom_wet) >> s1); + wet += (fPow2Div2(pHybOutputImagWet[qs] << headroom_wet) >> s1); + } + for (; qs < hybBands; qs++) { + dry += (fPow2Div2(pHybOutputRealDry[qs] << headroom_dry) >> s1); + wet += (fPow2Div2(pHybOutputRealWet[qs] << headroom_wet) >> s1); + } + + /* consider fPow2Div2() */ + s1 += 1; + + /* normalize dry part, ensure that exponent is even */ + s2 = fixMax(0, CntLeadingZeros(dry) - 1); + *slotAmp_dry = dry << s2; + *slotAmp_dry_e = s1 - s2 - 2 * headroom_dry; + if (*slotAmp_dry_e & 1) { + *slotAmp_dry = *slotAmp_dry >> 1; + *slotAmp_dry_e += 1; + } + + /* normalize wet part, ensure that exponent is even */ + s2 = fixMax(0, CntLeadingZeros(wet) - 1); + *slotAmp_wet = wet << s2; + *slotAmp_wet_e = s1 - s2 - 2 * headroom_wet; + if (*slotAmp_wet_e & 1) { + *slotAmp_wet = *slotAmp_wet >> 1; + *slotAmp_wet_e += 1; + } +} + +#if defined(__aarch64__) +__attribute__((noinline)) +#endif +static void +shapeBBEnv(FIXP_DBL *pHybOutputRealDry, FIXP_DBL *pHybOutputImagDry, + FIXP_DBL dryFac, INT scale, INT cplxBands, INT hybBands) { + INT qs; + + if (scale == 0) { + for (qs = 0; qs < cplxBands; qs++) { + pHybOutputRealDry[qs] = fMultDiv2(pHybOutputRealDry[qs], dryFac); + pHybOutputImagDry[qs] = fMultDiv2(pHybOutputImagDry[qs], dryFac); + } + for (; qs < hybBands; qs++) { + pHybOutputRealDry[qs] = fMultDiv2(pHybOutputRealDry[qs], dryFac); + } + } else { + for (qs = 0; qs < cplxBands; qs++) { + pHybOutputRealDry[qs] = SATURATE_LEFT_SHIFT( + fMultDiv2(pHybOutputRealDry[qs], dryFac), scale, DFRACT_BITS); + pHybOutputImagDry[qs] = SATURATE_LEFT_SHIFT( + fMultDiv2(pHybOutputImagDry[qs], dryFac), scale, DFRACT_BITS); + } + for (; qs < hybBands; qs++) { + pHybOutputRealDry[qs] = SATURATE_LEFT_SHIFT( + fMultDiv2(pHybOutputRealDry[qs], dryFac), scale, DFRACT_BITS); + } + } +} + +static void extractBBEnv(spatialDec *self, INT inp, INT start, INT channels, + FIXP_DBL *pEnv, const SPATIAL_BS_FRAME *frame) { + INT ch, pb, prevChOffs; + INT clz, scale, scale_min, envSF; + INT scaleCur, scalePrev, commonScale; + INT slotNrgSF, partNrgSF, frameNrgSF; + INT *pPartNrgPrevSF, *pFrameNrgPrevSF; + INT *pNormNrgPrevSF, *pPartNrgPrev2SF; + + FIXP_DBL maxVal, env, frameNrg, normNrg; + FIXP_DBL *pReal, *pImag; + FIXP_DBL *partNrg, *partNrgPrev; + + C_ALLOC_SCRATCH_START(pScratchBuffer, FIXP_DBL, + (2 * 42 + MAX_PARAMETER_BANDS)); + C_ALLOC_SCRATCH_START(resPb, FIXP_DBL, (END_BB_ENV - START_BB_ENV)); + C_ALLOC_SCRATCH_START(resPbSF, INT, (END_BB_ENV - START_BB_ENV)); + + FIXP_DBL *slotNrg = pScratchBuffer + (2 * 42); + + RESHAPE_BBENV_STATE *pBBEnvState = self->reshapeBBEnvState; + + FIXP_DBL alpha = pBBEnvState->alpha__FDK; + /*FIXP_DBL alpha1 = (FL2FXCONST_DBL(1.0f) - alpha) << SF_ALPHA1;*/ + FIXP_DBL alpha1 = ((FIXP_DBL)MAXVAL_DBL - alpha) << SF_ALPHA1; + FIXP_DBL beta = pBBEnvState->beta__FDK; + /*FIXP_DBL beta1 = (FL2FXCONST_DBL(1.0f) - beta) << SF_BETA1;*/ + FIXP_DBL beta1 = ((FIXP_DBL)MAXVAL_DBL - beta) << SF_BETA1; + + INT shapeActiv = 1; + INT hybBands = fixMin(42, self->hybridBands); + INT staticScale = self->staticDecScale + (1); + INT cplxBands; + cplxBands = fixMin(42, self->hybridBands); + + for (ch = start; ch < channels; ch++) { + if (inp == INP_DRY_WET) { + INT ch2 = row2channelGES[self->treeConfig][ch]; + if (ch2 == -1) { + continue; + } else { + if (frame->tempShapeEnableChannelGES[ch2]) { + shapeActiv = 1; + } else { + shapeActiv = 0; + } + } + prevChOffs = ch; + pReal = pScratchBuffer; + pImag = pScratchBuffer + 42; + combineDryWet(pReal, pImag, self->hybOutputRealDry__FDK[ch], + self->hybOutputImagDry__FDK[ch], + self->hybOutputRealWet__FDK[ch], + self->hybOutputImagWet__FDK[ch], cplxBands, hybBands); + clz = fMin(getScalefactor(&pReal[12], fMax(0, hybBands - 12)), + getScalefactor(&pImag[12], fMax(0, cplxBands - 12))); + } else { + prevChOffs = ch + self->numOutputChannels; + pReal = self->hybInputReal__FDK[ch]; + pImag = self->hybInputImag__FDK[ch]; + clz = fMin(getScalefactor(&pReal[12], fMax(0, hybBands - 12)), + getScalefactor(&pImag[12], fMax(0, cplxBands - 12))); + } + + partNrg = partNrgPrev = pBBEnvState->partNrgPrev__FDK[prevChOffs]; + pPartNrgPrevSF = &pBBEnvState->partNrgPrevSF[prevChOffs]; + pFrameNrgPrevSF = &pBBEnvState->frameNrgPrevSF[prevChOffs]; + pNormNrgPrevSF = &pBBEnvState->normNrgPrevSF[prevChOffs]; + pPartNrgPrev2SF = &pBBEnvState->partNrgPrev2SF[prevChOffs]; + + /* calculate slot energy */ + { + getSlotNrgHQ(&pReal[12], &pImag[12], slotNrg, clz, + fixMin(42, self->hybridBands)); /* scale slotNrg: + 2*(staticScale-clz) + + SF_FACTOR_SLOT */ + } + + slotNrgSF = 2 * (staticScale - clz + ((inp == INP_DRY_WET) ? 1 : 0)) + + SF_FACTOR_SLOT; + frameNrgSF = 2 * (staticScale - clz + ((inp == INP_DRY_WET) ? 1 : 0)) + + SF_FACTOR_SLOT; + + partNrgSF = fixMax(slotNrgSF - SF_ALPHA1 + 1, + pPartNrgPrevSF[0] - pPartNrgPrev2SF[0] + 1); + scalePrev = fixMax(fixMin(partNrgSF - pPartNrgPrevSF[0], DFRACT_BITS - 1), + -(DFRACT_BITS - 1)); + scaleCur = + fixMax(fixMin(partNrgSF - slotNrgSF + SF_ALPHA1, DFRACT_BITS - 1), + -(DFRACT_BITS - 1)); + + maxVal = FL2FXCONST_DBL(0.0f); + frameNrg = FL2FXCONST_DBL(0.0f); + if ((scaleCur < 0) && (scalePrev < 0)) { + scaleCur = -scaleCur; + scalePrev = -scalePrev; + for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) { + partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) << scaleCur) + + (fMultDiv2(alpha, partNrgPrev[pb]) << scalePrev)) + << 1; + maxVal |= partNrg[pb]; + frameNrg += slotNrg[pb] >> 3; + } + } else if ((scaleCur >= 0) && (scalePrev >= 0)) { + for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) { + partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) >> scaleCur) + + (fMultDiv2(alpha, partNrgPrev[pb]) >> scalePrev)) + << 1; + maxVal |= partNrg[pb]; + frameNrg += slotNrg[pb] >> 3; + } + } else if ((scaleCur < 0) && (scalePrev >= 0)) { + scaleCur = -scaleCur; + for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) { + partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) << scaleCur) + + (fMultDiv2(alpha, partNrgPrev[pb]) >> scalePrev)) + << 1; + maxVal |= partNrg[pb]; + frameNrg += slotNrg[pb] >> 3; + } + } else { /* if ( (scaleCur >= 0) && (scalePrev < 0) ) */ + scalePrev = -scalePrev; + for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) { + partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) >> scaleCur) + + (fMultDiv2(alpha, partNrgPrev[pb]) << scalePrev)) + << 1; + maxVal |= partNrg[pb]; + frameNrg += slotNrg[pb] >> 3; + } + } + + /* frameNrg /= (END_BB_ENV - START_BB_ENV); 0.88888888888f = + * (1/(END_BB_ENV-START_BB_ENV)<<3; shift with 3 is compensated in loop + * above */ + frameNrg = fMult(frameNrg, FL2FXCONST_DBL(0.88888888888f)); + + /* store scalefactor and headroom for part nrg prev */ + pPartNrgPrevSF[0] = partNrgSF; + pPartNrgPrev2SF[0] = fixMax(0, CntLeadingZeros(maxVal) - 1); + + commonScale = fixMax(frameNrgSF - SF_ALPHA1 + 1, pFrameNrgPrevSF[0] + 1); + scalePrev = fixMin(commonScale - pFrameNrgPrevSF[0], DFRACT_BITS - 1); + scaleCur = fixMin(commonScale - frameNrgSF + SF_ALPHA1, DFRACT_BITS - 1); + frameNrgSF = commonScale; + + frameNrg = ((fMultDiv2(alpha1, frameNrg) >> scaleCur) + + (fMultDiv2(alpha, pBBEnvState->frameNrgPrev__FDK[prevChOffs]) >> + scalePrev)) + << 1; + + clz = fixMax(0, CntLeadingZeros(frameNrg) - 1); + pBBEnvState->frameNrgPrev__FDK[prevChOffs] = frameNrg << clz; + pFrameNrgPrevSF[0] = frameNrgSF - clz; + + env = FL2FXCONST_DBL(0.0f); + scale = clz + partNrgSF - frameNrgSF; + scale_min = DFRACT_BITS - 1; + for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) { + if ((partNrg[pb] | slotNrg[pb]) != FL2FXCONST_DBL(0.0f)) { + INT s; + INT sc = 0; + INT sn = fixMax(0, CntLeadingZeros(slotNrg[pb]) - 1); + FIXP_DBL inv_sqrt = invSqrtNorm2(partNrg[pb], &sc); + FIXP_DBL res = fMult(slotNrg[pb] << sn, fPow2(inv_sqrt)); + + s = fixMax(0, CntLeadingZeros(res) - 1); + res = res << s; + + sc = scale - (2 * sc - sn - s); + scale_min = fixMin(scale_min, sc); + + resPb[pb] = res; + resPbSF[pb] = sc; + } else { + resPb[pb] = (FIXP_DBL)0; + resPbSF[pb] = 0; + } + } + + scale_min = 4 - scale_min; + + for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) { + INT sc = fixMax(fixMin(resPbSF[pb] + scale_min, DFRACT_BITS - 1), + -(DFRACT_BITS - 1)); + + if (sc < 0) { + env += resPb[pb] << (-sc); + } else { + env += resPb[pb] >> (sc); + } + } + + env = fMultDiv2(env, pBBEnvState->frameNrgPrev__FDK[prevChOffs]); + envSF = slotNrgSF + scale_min + 1; + + commonScale = fixMax(envSF - SF_BETA1 + 1, pNormNrgPrevSF[0] + 1); + scalePrev = fixMin(commonScale - pNormNrgPrevSF[0], DFRACT_BITS - 1); + scaleCur = fixMin(commonScale - envSF + SF_BETA1, DFRACT_BITS - 1); + + normNrg = ((fMultDiv2(beta1, env) >> scaleCur) + + (fMultDiv2(beta, pBBEnvState->normNrgPrev__FDK[prevChOffs]) >> + scalePrev)) + << 1; + + clz = fixMax(0, CntLeadingZeros(normNrg) - 1); + pBBEnvState->normNrgPrev__FDK[prevChOffs] = normNrg << clz; + pNormNrgPrevSF[0] = commonScale - clz; + + if (shapeActiv) { + if ((env | normNrg) != FL2FXCONST_DBL(0.0f)) { + INT sc, se, sn; + se = fixMax(0, CntLeadingZeros(env) - 1); + sc = commonScale + SF_DIV32 - envSF + se; + env = fMult(sqrtFixp((env << se) >> (sc & 0x1)), + invSqrtNorm2(normNrg, &sn)); + + sc = fixMin((sc >> 1) - sn, DFRACT_BITS - 1); + if (sc < 0) { + env <<= (-sc); + } else { + env >>= (sc); + } + } + /* env is scaled by SF_DIV32/2 bits */ + } + pEnv[ch] = env; + } + + C_ALLOC_SCRATCH_END(resPbSF, INT, (END_BB_ENV - START_BB_ENV)); + C_ALLOC_SCRATCH_END(resPb, FIXP_DBL, (END_BB_ENV - START_BB_ENV)); + C_ALLOC_SCRATCH_END(pScratchBuffer, FIXP_DBL, (2 * 42 + MAX_PARAMETER_BANDS)); +} + +void SpatialDecReshapeBBEnv(spatialDec *self, const SPATIAL_BS_FRAME *frame, + INT ts) { + INT ch, scale; + INT dryFacSF, slotAmpSF; + INT slotAmp_dry_e, slotAmp_wet_e; + FIXP_DBL tmp, dryFac, envShape; + FIXP_DBL slotAmp_dry, slotAmp_wet, slotAmp_ratio; + FIXP_DBL envDry[MAX_OUTPUT_CHANNELS], envDmx[2]; + + INT cplxBands; + INT hybBands = self->hybridBands - 6; + + cplxBands = self->hybridBands - 6; + + /* extract downmix envelope(s) */ + switch (self->treeConfig) { + default: + extractBBEnv(self, INP_DMX, 0, fMin(self->numInputChannels, 2), envDmx, + frame); + } + + /* extract dry and wet envelopes */ + extractBBEnv(self, INP_DRY_WET, 0, self->numOutputChannels, envDry, frame); + + for (ch = 0; ch < self->numOutputChannels; ch++) { + INT ch2; + + ch2 = row2channelGES[self->treeConfig][ch]; + + if (ch2 == -1) continue; + + if (frame->tempShapeEnableChannelGES[ch2]) { + INT sc; + + /* reshape dry and wet signals according to transmitted envelope */ + + /* De-quantize GES data */ + FDK_ASSERT((frame->bsEnvShapeData[ch2][ts] >= 0) && + (frame->bsEnvShapeData[ch2][ts] <= 4)); + FDK_ASSERT((self->envQuantMode == 0) || (self->envQuantMode == 1)); + envShape = + FX_CFG2FX_DBL(envShapeDataTable__FDK[frame->bsEnvShapeData[ch2][ts]] + [self->envQuantMode]); + + /* get downmix channel */ + ch2 = self->row2channelDmxGES[ch]; + + /* multiply ratio with dmx envelope; tmp is scaled by SF_DIV32/2+SF_SHAPE + * bits */ + if (ch2 == 2) { + tmp = fMultDiv2(envShape, envDmx[0]) + fMultDiv2(envShape, envDmx[1]); + } else { + tmp = fMult(envShape, envDmx[ch2]); + } + + /* weighting factors */ + dryFacSF = slotAmpSF = 0; + dryFac = slotAmp_ratio = FL2FXCONST_DBL(0.0f); + + /* dryFac will be scaled by dryFacSF bits */ + if (envDry[ch] != FL2FXCONST_DBL(0.0f)) { + envDry[ch] = invSqrtNorm2(envDry[ch], &dryFacSF); + dryFac = fMultDiv2(tmp, fPow2Div2(envDry[ch])) << 2; + dryFacSF = SF_SHAPE + 2 * dryFacSF; + } + + slotAmp_dry_e = slotAmp_wet_e = 0; + + /* calculate slotAmp_dry and slotAmp_wet */ + slotAmp(&slotAmp_dry, &slotAmp_dry_e, &slotAmp_wet, &slotAmp_wet_e, + &self->hybOutputRealDry__FDK[ch][6], + &self->hybOutputImagDry__FDK[ch][6], + &self->hybOutputRealWet__FDK[ch][6], + &self->hybOutputImagWet__FDK[ch][6], cplxBands, hybBands); + + /* exponents must be even due to subsequent square root calculation */ + FDK_ASSERT(((slotAmp_dry_e & 1) == 0) && ((slotAmp_wet_e & 1) == 0)); + + /* slotAmp_ratio will be scaled by slotAmpSF bits */ + if (slotAmp_dry != FL2FXCONST_DBL(0.0f)) { + slotAmp_wet = sqrtFixp(slotAmp_wet); + slotAmp_dry = invSqrtNorm2(slotAmp_dry, &slotAmpSF); + + slotAmp_ratio = fMult(slotAmp_wet, slotAmp_dry); + slotAmpSF = slotAmpSF + (slotAmp_wet_e >> 1) - (slotAmp_dry_e >> 1); + } + + /* calculate common scale factor */ + scale = + fixMax(3, fixMax(dryFacSF, slotAmpSF)); /* scale is at least with 3 + bits to avoid overflows + when calculating dryFac */ + dryFac = dryFac >> fixMin(scale - dryFacSF, DFRACT_BITS - 1); + slotAmp_ratio = + slotAmp_ratio >> fixMin(scale - slotAmpSF, DFRACT_BITS - 1); + + /* limit dryFac */ + dryFac = fixMax( + FL2FXCONST_DBL(0.25f) >> (INT)fixMin(2 * scale, DFRACT_BITS - 1), + fMult(dryFac, slotAmp_ratio) - + (slotAmp_ratio >> fixMin(scale, DFRACT_BITS - 1)) + + (dryFac >> fixMin(scale, DFRACT_BITS - 1))); + dryFac = fixMin( + FL2FXCONST_DBL(0.50f) >> (INT)fixMin(2 * scale - 3, DFRACT_BITS - 1), + dryFac); /* reduce shift bits by 3, because upper + limit 4.0 is scaled with 3 bits */ + scale = 2 * scale + 1; + + /* improve precision for dryFac */ + sc = fixMax(0, CntLeadingZeros(dryFac) - 1); + dryFac = dryFac << (INT)fixMin(scale, sc); + scale = scale - fixMin(scale, sc); + + /* shaping */ + shapeBBEnv(&self->hybOutputRealDry__FDK[ch][6], + &self->hybOutputImagDry__FDK[ch][6], dryFac, + fixMin(scale, DFRACT_BITS - 1), cplxBands, hybBands); + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_reshapeBBEnv.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_reshapeBBEnv.h new file mode 100644 index 0000000000000..16585307baa4f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_reshapeBBEnv.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec guided envelope shaping + +*******************************************************************************/ + +#ifndef SAC_RESHAPEBBENV_H +#define SAC_RESHAPEBBENV_H + +#include "sac_dec_interface.h" + +#define BB_ENV_SIZE 9 /* END_BB_ENV - START_BB_ENV */ + +void initBBEnv(spatialDec *self, int initStatesFlag); +void SpatialDecReshapeBBEnv(spatialDec *self, const SPATIAL_BS_FRAME *frame, + int ts); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_rom.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_rom.cpp new file mode 100644 index 0000000000000..600203fbc4970 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_rom.cpp @@ -0,0 +1,4461 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec tables + +*******************************************************************************/ + +#include "sac_rom.h" +#include "sac_calcM1andM2.h" + +#define SCALE_CPC(a) (FL2FXCONST_CFG(a / (float)(1 << SCALE_PARAM_M1))) +const FIXP_CFG dequantCPC__FDK[] = { + SCALE_CPC(-2.0f), SCALE_CPC(-1.9f), SCALE_CPC(-1.8f), SCALE_CPC(-1.7f), + SCALE_CPC(-1.6f), SCALE_CPC(-1.5f), SCALE_CPC(-1.4f), SCALE_CPC(-1.3f), + SCALE_CPC(-1.2f), SCALE_CPC(-1.1f), SCALE_CPC(-1.0f), SCALE_CPC(-0.9f), + SCALE_CPC(-0.8f), SCALE_CPC(-0.7f), SCALE_CPC(-0.6f), SCALE_CPC(-0.5f), + SCALE_CPC(-0.4f), SCALE_CPC(-0.3f), SCALE_CPC(-0.2f), SCALE_CPC(-0.1f), + SCALE_CPC(0.0f), SCALE_CPC(0.1f), SCALE_CPC(0.2f), SCALE_CPC(0.3f), + SCALE_CPC(0.4f), SCALE_CPC(0.5f), SCALE_CPC(0.6f), SCALE_CPC(0.7f), + SCALE_CPC(0.8f), SCALE_CPC(0.9f), SCALE_CPC(1.0f), SCALE_CPC(1.1f), + SCALE_CPC(1.2f), SCALE_CPC(1.3f), SCALE_CPC(1.4f), SCALE_CPC(1.5f), + SCALE_CPC(1.6f), SCALE_CPC(1.7f), SCALE_CPC(1.8f), SCALE_CPC(1.9f), + SCALE_CPC(2.0f), SCALE_CPC(2.1f), SCALE_CPC(2.2f), SCALE_CPC(2.3f), + SCALE_CPC(2.4f), SCALE_CPC(2.5f), SCALE_CPC(2.6f), SCALE_CPC(2.7f), + SCALE_CPC(2.8f), SCALE_CPC(2.9f), SCALE_CPC(3.0f)}; + +#define SCALE_ICC(a) (FL2FXCONST_CFG(a)) +const FIXP_CFG dequantICC__FDK[8] = { + /*SCALE_ICC(1.00000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL), + SCALE_ICC(0.9370f), + SCALE_ICC(0.84118f), + SCALE_ICC(0.60092f), + SCALE_ICC(0.36764f), + SCALE_ICC(0.0000f), + SCALE_ICC(-0.58900f), + SCALE_ICC(-0.9900f)}; + +#define SCALE_CLD2(a) (FL2FXCONST_CFG(a / (float)(1 << 8))) +const FIXP_CFG dequantCLD__FDK[31] = { + SCALE_CLD2(-150.0f), SCALE_CLD2(-45.0f), SCALE_CLD2(-40.0f), + SCALE_CLD2(-35.0f), SCALE_CLD2(-30.0f), SCALE_CLD2(-25.0f), + SCALE_CLD2(-22.0f), SCALE_CLD2(-19.0f), SCALE_CLD2(-16.0f), + SCALE_CLD2(-13.0f), SCALE_CLD2(-10.0f), SCALE_CLD2(-8.0f), + SCALE_CLD2(-6.0f), SCALE_CLD2(-4.0f), SCALE_CLD2(-2.0f), + SCALE_CLD2(0.0f), SCALE_CLD2(2.0f), SCALE_CLD2(4.0f), + SCALE_CLD2(6.0f), SCALE_CLD2(8.0f), SCALE_CLD2(10.0f), + SCALE_CLD2(13.0f), SCALE_CLD2(16.0f), SCALE_CLD2(19.0f), + SCALE_CLD2(22.0f), SCALE_CLD2(25.0f), SCALE_CLD2(30.0f), + SCALE_CLD2(35.0f), SCALE_CLD2(40.0f), SCALE_CLD2(45.0f), + SCALE_CLD2(150.0f)}; + +#define SCALE_IPD(a) (FL2FXCONST_CFG(a / (float)(1 << IPD_SCALE))) +const FIXP_CFG dequantIPD__FDK[16] = { + /* SCALE_IPD(0.000000000f), SCALE_IPD(0.392699082f), + SCALE_IPD(0.785398163f), SCALE_IPD(1.178097245f), + SCALE_IPD(1.570796327f), SCALE_IPD(1.963495408f), + SCALE_IPD(2.356194490f), SCALE_IPD(2.748893572f), + SCALE_IPD(3.141592654f), SCALE_IPD(3.534291735f), + SCALE_IPD(3.926990817f), SCALE_IPD(4.319689899f), + SCALE_IPD(4.712388980f), SCALE_IPD(5.105088062f), + SCALE_IPD(5.497787144f), SCALE_IPD(5.890486225f) */ + SCALE_IPD(0.00000000000000f), SCALE_IPD(0.392699082f), + SCALE_IPD(0.78539816339745f), SCALE_IPD(1.178097245f), + SCALE_IPD(1.57079632679490f), SCALE_IPD(1.963495408f), + SCALE_IPD(2.35619449019234f), SCALE_IPD(2.748893572f), + SCALE_IPD(3.14159265358979f), SCALE_IPD(3.534291735f), + SCALE_IPD(3.92699081698724f), SCALE_IPD(4.319689899f), + SCALE_IPD(4.71238898038469f), SCALE_IPD(5.105088062f), + SCALE_IPD(5.49778714378214f), SCALE_IPD(5.890486225f)}; + +#define SCALE_SPLIT_ANGLE(a) (FL2FXCONST_DBL(a / (float)(1 << IPD_SCALE))) +/* + Generate table dequantIPD_CLD_ICC_splitAngle__FDK[16][31][8]: + + #define ABS_THR ( 1e-9f * 32768 * 32768 ) + + float dequantICC[] = + {1.0000f,0.9370f,0.84118f,0.60092f,0.36764f,0.0f,-0.5890f,-0.9900f}; float + dequantCLD[] = + {-150.0,-45.0,-40.0,-35.0,-30.0,-25.0,-22.0,-19.0,-16.0,-13.0,-10.0, -8.0, + -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, + 10.0, 13.0, 16.0, 19.0, 22.0, 25.0, 30.0, 35.0, 40.0, 45.0, 150.0 }; float + dequantIPD[] = + {0.f,0.392699082f,0.785398163f,1.178097245f,1.570796327f,1.963495408f, + 2.35619449f,2.748893572f,3.141592654f,3.534291735f,3.926990817f, + 4.319689899f,4.71238898f,5.105088062f,5.497787144f,5.890486225f}; + + for (ipdIdx=0; ipdIdx<16; ipdIdx++) + for (cldIdx=0; cldIdx<31; cldIdx++) + for (iccIdx=0; iccIdx<8; iccIdx++) { + ipd = dequantIPD[ipdIdx]; + cld = dequantCLD[cldIdx]; + icc = dequantICC[iccIdx]; + iidLin = (float) pow(10.0f, cld / 20.0f); + iidLin2 = iidLin * iidLin; + iidLin21 = iidLin2 + 1.0f; + sinIpd = (float) sin(ipd); + cosIpd = (float) cos(ipd); + temp1 = 2.0f * icc * iidLin; + temp1c = temp1 * cosIpd; + ratio = (iidLin21 + temp1c) / (iidLin21 + temp1) + ABS_THR; + w2 = (float) pow(ratio, 0.25f); + w1 = 2.0f - w2; + dequantIPD_CLD_ICC_splitAngle__FDK[ipdIdx][cldIdx][iccIdx] = (float) + atan2(w2 * sinIpd, w1 * iidLin + w2 * cosIpd); + } +*/ +const FIXP_DBL dequantIPD_CLD_ICC_splitAngle__FDK[15][31][8] = { + { + {SCALE_SPLIT_ANGLE(0.39269909262657), + SCALE_SPLIT_ANGLE(0.39269909262657), + SCALE_SPLIT_ANGLE(0.39269909262657), + SCALE_SPLIT_ANGLE(0.39269909262657), + SCALE_SPLIT_ANGLE(0.39269909262657), + SCALE_SPLIT_ANGLE(0.39269909262657), + SCALE_SPLIT_ANGLE(0.39269909262657), + SCALE_SPLIT_ANGLE(0.39269909262657)}, + {SCALE_SPLIT_ANGLE(0.39055734872818), + SCALE_SPLIT_ANGLE(0.39055740833282), + SCALE_SPLIT_ANGLE(0.39055749773979), + SCALE_SPLIT_ANGLE(0.39055770635605), + SCALE_SPLIT_ANGLE(0.39055791497231), + SCALE_SPLIT_ANGLE(0.39055824279785), + SCALE_SPLIT_ANGLE(0.39055877923965), + SCALE_SPLIT_ANGLE(0.39055916666985)}, + {SCALE_SPLIT_ANGLE(0.38890451192856), + SCALE_SPLIT_ANGLE(0.38890469074249), + SCALE_SPLIT_ANGLE(0.38890495896339), + SCALE_SPLIT_ANGLE(0.38890564441681), + SCALE_SPLIT_ANGLE(0.38890630006790), + SCALE_SPLIT_ANGLE(0.38890734314919), + SCALE_SPLIT_ANGLE(0.38890904188156), + SCALE_SPLIT_ANGLE(0.38891020417213)}, + {SCALE_SPLIT_ANGLE(0.38599541783333), + SCALE_SPLIT_ANGLE(0.38599592447281), + SCALE_SPLIT_ANGLE(0.38599672913551), + SCALE_SPLIT_ANGLE(0.38599878549576), + SCALE_SPLIT_ANGLE(0.38600078225136), + SCALE_SPLIT_ANGLE(0.38600403070450), + SCALE_SPLIT_ANGLE(0.38600939512253), + SCALE_SPLIT_ANGLE(0.38601315021515)}, + {SCALE_SPLIT_ANGLE(0.38091576099396), + SCALE_SPLIT_ANGLE(0.38091731071472), + SCALE_SPLIT_ANGLE(0.38091966509819), + SCALE_SPLIT_ANGLE(0.38092571496964), + SCALE_SPLIT_ANGLE(0.38093179464340), + SCALE_SPLIT_ANGLE(0.38094165921211), + SCALE_SPLIT_ANGLE(0.38095843791962), + SCALE_SPLIT_ANGLE(0.38097056746483)}, + {SCALE_SPLIT_ANGLE(0.37216997146606), + SCALE_SPLIT_ANGLE(0.37217426300049), + SCALE_SPLIT_ANGLE(0.37218090891838), + SCALE_SPLIT_ANGLE(0.37219807505608), + SCALE_SPLIT_ANGLE(0.37221556901932), + SCALE_SPLIT_ANGLE(0.37224492430687), + SCALE_SPLIT_ANGLE(0.37229704856873), + SCALE_SPLIT_ANGLE(0.37233674526215)}, + {SCALE_SPLIT_ANGLE(0.36424967646599), + SCALE_SPLIT_ANGLE(0.36425727605820), + SCALE_SPLIT_ANGLE(0.36426907777786), + SCALE_SPLIT_ANGLE(0.36430004239082), + SCALE_SPLIT_ANGLE(0.36433213949203), + SCALE_SPLIT_ANGLE(0.36438730359077), + SCALE_SPLIT_ANGLE(0.36448970437050), + SCALE_SPLIT_ANGLE(0.36457163095474)}, + {SCALE_SPLIT_ANGLE(0.35356888175011), + SCALE_SPLIT_ANGLE(0.35358175635338), + SCALE_SPLIT_ANGLE(0.35360190272331), + SCALE_SPLIT_ANGLE(0.35365560650826), + SCALE_SPLIT_ANGLE(0.35371258854866), + SCALE_SPLIT_ANGLE(0.35381385684013), + SCALE_SPLIT_ANGLE(0.35401365160942), + SCALE_SPLIT_ANGLE(0.35418578982353)}, + {SCALE_SPLIT_ANGLE(0.33942583203316), + SCALE_SPLIT_ANGLE(0.33944645524025), + SCALE_SPLIT_ANGLE(0.33947896957397), + SCALE_SPLIT_ANGLE(0.33956742286682), + SCALE_SPLIT_ANGLE(0.33966416120529), + SCALE_SPLIT_ANGLE(0.33984372019768), + SCALE_SPLIT_ANGLE(0.34023007750511), + SCALE_SPLIT_ANGLE(0.34060221910477)}, + {SCALE_SPLIT_ANGLE(0.32115450501442), + SCALE_SPLIT_ANGLE(0.32118520140648), + SCALE_SPLIT_ANGLE(0.32123416662216), + SCALE_SPLIT_ANGLE(0.32137048244476), + SCALE_SPLIT_ANGLE(0.32152509689331), + SCALE_SPLIT_ANGLE(0.32182863354683), + SCALE_SPLIT_ANGLE(0.32256561517715), + SCALE_SPLIT_ANGLE(0.32340893149376)}, + {SCALE_SPLIT_ANGLE(0.29830521345139), + SCALE_SPLIT_ANGLE(0.29834723472595), + SCALE_SPLIT_ANGLE(0.29841500520706), + SCALE_SPLIT_ANGLE(0.29860860109329), + SCALE_SPLIT_ANGLE(0.29883742332458), + SCALE_SPLIT_ANGLE(0.29931786656380), + SCALE_SPLIT_ANGLE(0.30069106817245), + SCALE_SPLIT_ANGLE(0.30275771021843)}, + {SCALE_SPLIT_ANGLE(0.28050789237022), + SCALE_SPLIT_ANGLE(0.28055712580681), + SCALE_SPLIT_ANGLE(0.28063708543777), + SCALE_SPLIT_ANGLE(0.28086942434311), + SCALE_SPLIT_ANGLE(0.28115189075470), + SCALE_SPLIT_ANGLE(0.28177404403687), + SCALE_SPLIT_ANGLE(0.28380545973778), + SCALE_SPLIT_ANGLE(0.28782638907433)}, + {SCALE_SPLIT_ANGLE(0.26083287596703), + SCALE_SPLIT_ANGLE(0.26088824868202), + SCALE_SPLIT_ANGLE(0.26097872853279), + SCALE_SPLIT_ANGLE(0.26124578714371), + SCALE_SPLIT_ANGLE(0.26157897710800), + SCALE_SPLIT_ANGLE(0.26234793663025), + SCALE_SPLIT_ANGLE(0.26525345444679), + SCALE_SPLIT_ANGLE(0.27373576164246)}, + {SCALE_SPLIT_ANGLE(0.23960022628307), + SCALE_SPLIT_ANGLE(0.23966011404991), + SCALE_SPLIT_ANGLE(0.23975846171379), + SCALE_SPLIT_ANGLE(0.24005253612995), + SCALE_SPLIT_ANGLE(0.24042735993862), + SCALE_SPLIT_ANGLE(0.24132782220840), + SCALE_SPLIT_ANGLE(0.24525125324726), + SCALE_SPLIT_ANGLE(0.26534587144852)}, + {SCALE_SPLIT_ANGLE(0.21727463603020), + SCALE_SPLIT_ANGLE(0.21733720600605), + SCALE_SPLIT_ANGLE(0.21744030714035), + SCALE_SPLIT_ANGLE(0.21775111556053), + SCALE_SPLIT_ANGLE(0.21815299987793), + SCALE_SPLIT_ANGLE(0.21914559602737), + SCALE_SPLIT_ANGLE(0.22397418320179), + SCALE_SPLIT_ANGLE(0.27997341752052)}, + {SCALE_SPLIT_ANGLE(0.19442924857140), + SCALE_SPLIT_ANGLE(0.19449260830879), + SCALE_SPLIT_ANGLE(0.19459712505341), + SCALE_SPLIT_ANGLE(0.19491320848465), + SCALE_SPLIT_ANGLE(0.19532410800457), + SCALE_SPLIT_ANGLE(0.19634956121445), + SCALE_SPLIT_ANGLE(0.20156545937061), + SCALE_SPLIT_ANGLE(0.33650875091553)}, + {SCALE_SPLIT_ANGLE(0.17168679833412), + SCALE_SPLIT_ANGLE(0.17174908518791), + SCALE_SPLIT_ANGLE(0.17185173928738), + SCALE_SPLIT_ANGLE(0.17216140031815), + SCALE_SPLIT_ANGLE(0.17256212234497), + SCALE_SPLIT_ANGLE(0.17355351150036), + SCALE_SPLIT_ANGLE(0.17841057479382), + SCALE_SPLIT_ANGLE(0.23922468721867)}, + {SCALE_SPLIT_ANGLE(0.14965108036995), + SCALE_SPLIT_ANGLE(0.14971046149731), + SCALE_SPLIT_ANGLE(0.14980803430080), + SCALE_SPLIT_ANGLE(0.15010002255440), + SCALE_SPLIT_ANGLE(0.15047283470631), + SCALE_SPLIT_ANGLE(0.15137128531933), + SCALE_SPLIT_ANGLE(0.15533345937729), + SCALE_SPLIT_ANGLE(0.17691856622696)}, + {SCALE_SPLIT_ANGLE(0.12884500622749), + SCALE_SPLIT_ANGLE(0.12889973819256), + SCALE_SPLIT_ANGLE(0.12898921966553), + SCALE_SPLIT_ANGLE(0.12925371527672), + SCALE_SPLIT_ANGLE(0.12958450615406), + SCALE_SPLIT_ANGLE(0.13035117089748), + SCALE_SPLIT_ANGLE(0.13329000771046), + SCALE_SPLIT_ANGLE(0.14226883649826)}, + {SCALE_SPLIT_ANGLE(0.10966771841049), + SCALE_SPLIT_ANGLE(0.10971628874540), + SCALE_SPLIT_ANGLE(0.10979522019625), + SCALE_SPLIT_ANGLE(0.11002497375011), + SCALE_SPLIT_ANGLE(0.11030506342649), + SCALE_SPLIT_ANGLE(0.11092507839203), + SCALE_SPLIT_ANGLE(0.11297956109047), + SCALE_SPLIT_ANGLE(0.11718676239252)}, + {SCALE_SPLIT_ANGLE(0.09237616509199), + SCALE_SPLIT_ANGLE(0.09241759032011), + SCALE_SPLIT_ANGLE(0.09248441457748), + SCALE_SPLIT_ANGLE(0.09267570823431), + SCALE_SPLIT_ANGLE(0.09290253371000), + SCALE_SPLIT_ANGLE(0.09338124841452), + SCALE_SPLIT_ANGLE(0.09476862102747), + SCALE_SPLIT_ANGLE(0.09691140055656)}, + {SCALE_SPLIT_ANGLE(0.07020132243633), + SCALE_SPLIT_ANGLE(0.07023159414530), + SCALE_SPLIT_ANGLE(0.07027988880873), + SCALE_SPLIT_ANGLE(0.07041462510824), + SCALE_SPLIT_ANGLE(0.07056795060635), + SCALE_SPLIT_ANGLE(0.07087047398090), + SCALE_SPLIT_ANGLE(0.07161350548267), + SCALE_SPLIT_ANGLE(0.07247893512249)}, + {SCALE_SPLIT_ANGLE(0.05244029685855), + SCALE_SPLIT_ANGLE(0.05246063694358), + SCALE_SPLIT_ANGLE(0.05249277502298), + SCALE_SPLIT_ANGLE(0.05258031934500), + SCALE_SPLIT_ANGLE(0.05267634987831), + SCALE_SPLIT_ANGLE(0.05285539478064), + SCALE_SPLIT_ANGLE(0.05324416980147), + SCALE_SPLIT_ANGLE(0.05362326279283)}, + {SCALE_SPLIT_ANGLE(0.03864165768027), + SCALE_SPLIT_ANGLE(0.03865439072251), + SCALE_SPLIT_ANGLE(0.03867433592677), + SCALE_SPLIT_ANGLE(0.03872758522630), + SCALE_SPLIT_ANGLE(0.03878424316645), + SCALE_SPLIT_ANGLE(0.03888526186347), + SCALE_SPLIT_ANGLE(0.03908598423004), + SCALE_SPLIT_ANGLE(0.03926040604711)}, + {SCALE_SPLIT_ANGLE(0.02817477472126), + SCALE_SPLIT_ANGLE(0.02818230912089), + SCALE_SPLIT_ANGLE(0.02819401398301), + SCALE_SPLIT_ANGLE(0.02822477556765), + SCALE_SPLIT_ANGLE(0.02825673110783), + SCALE_SPLIT_ANGLE(0.02831180393696), + SCALE_SPLIT_ANGLE(0.02841453813016), + SCALE_SPLIT_ANGLE(0.02849725075066)}, + {SCALE_SPLIT_ANGLE(0.02037953026593), + SCALE_SPLIT_ANGLE(0.02038379199803), + SCALE_SPLIT_ANGLE(0.02039037831128), + SCALE_SPLIT_ANGLE(0.02040746994317), + SCALE_SPLIT_ANGLE(0.02042490243912), + SCALE_SPLIT_ANGLE(0.02045420184731), + SCALE_SPLIT_ANGLE(0.02050646767020), + SCALE_SPLIT_ANGLE(0.02054644003510)}, + {SCALE_SPLIT_ANGLE(0.01173160225153), + SCALE_SPLIT_ANGLE(0.01173313986510), + SCALE_SPLIT_ANGLE(0.01173550263047), + SCALE_SPLIT_ANGLE(0.01174154505134), + SCALE_SPLIT_ANGLE(0.01174758374691), + SCALE_SPLIT_ANGLE(0.01175745483488), + SCALE_SPLIT_ANGLE(0.01177425310016), + SCALE_SPLIT_ANGLE(0.01178644131869)}, + {SCALE_SPLIT_ANGLE(0.00668647512794), + SCALE_SPLIT_ANGLE(0.00668699946254), + SCALE_SPLIT_ANGLE(0.00668780272827), + SCALE_SPLIT_ANGLE(0.00668983906507), + SCALE_SPLIT_ANGLE(0.00669185025617), + SCALE_SPLIT_ANGLE(0.00669508520514), + SCALE_SPLIT_ANGLE(0.00670044543222), + SCALE_SPLIT_ANGLE(0.00670422753319)}, + {SCALE_SPLIT_ANGLE(0.00378898042254), + SCALE_SPLIT_ANGLE(0.00378915388137), + SCALE_SPLIT_ANGLE(0.00378941884264), + SCALE_SPLIT_ANGLE(0.00379008660093), + SCALE_SPLIT_ANGLE(0.00379074062221), + SCALE_SPLIT_ANGLE(0.00379178463481), + SCALE_SPLIT_ANGLE(0.00379348872229), + SCALE_SPLIT_ANGLE(0.00379467196763)}, + {SCALE_SPLIT_ANGLE(0.00213995971717), + SCALE_SPLIT_ANGLE(0.00214001606219), + SCALE_SPLIT_ANGLE(0.00214010174386), + SCALE_SPLIT_ANGLE(0.00214031711221), + SCALE_SPLIT_ANGLE(0.00214052735828), + SCALE_SPLIT_ANGLE(0.00214086147025), + SCALE_SPLIT_ANGLE(0.00214140163735), + SCALE_SPLIT_ANGLE(0.00214177416638)}, + {SCALE_SPLIT_ANGLE(0.00000001210151), + SCALE_SPLIT_ANGLE(0.00000001210151), + SCALE_SPLIT_ANGLE(0.00000001210151), + SCALE_SPLIT_ANGLE(0.00000001210151), + SCALE_SPLIT_ANGLE(0.00000001210151), + SCALE_SPLIT_ANGLE(0.00000001210151), + SCALE_SPLIT_ANGLE(0.00000001210151), + SCALE_SPLIT_ANGLE(0.00000001210151)}, + }, + { + {SCALE_SPLIT_ANGLE(0.78539812564850), + SCALE_SPLIT_ANGLE(0.78539812564850), + SCALE_SPLIT_ANGLE(0.78539812564850), + SCALE_SPLIT_ANGLE(0.78539812564850), + SCALE_SPLIT_ANGLE(0.78539812564850), + SCALE_SPLIT_ANGLE(0.78539812564850), + SCALE_SPLIT_ANGLE(0.78539812564850), + SCALE_SPLIT_ANGLE(0.78539812564850)}, + {SCALE_SPLIT_ANGLE(0.78143113851547), + SCALE_SPLIT_ANGLE(0.78143155574799), + SCALE_SPLIT_ANGLE(0.78143215179443), + SCALE_SPLIT_ANGLE(0.78143370151520), + SCALE_SPLIT_ANGLE(0.78143519163132), + SCALE_SPLIT_ANGLE(0.78143757581711), + SCALE_SPLIT_ANGLE(0.78144145011902), + SCALE_SPLIT_ANGLE(0.78144407272339)}, + {SCALE_SPLIT_ANGLE(0.77835679054260), + SCALE_SPLIT_ANGLE(0.77835804224014), + SCALE_SPLIT_ANGLE(0.77835988998413), + SCALE_SPLIT_ANGLE(0.77836471796036), + SCALE_SPLIT_ANGLE(0.77836942672729), + SCALE_SPLIT_ANGLE(0.77837687730789), + SCALE_SPLIT_ANGLE(0.77838897705078), + SCALE_SPLIT_ANGLE(0.77839738130569)}, + {SCALE_SPLIT_ANGLE(0.77291858196259), + SCALE_SPLIT_ANGLE(0.77292239665985), + SCALE_SPLIT_ANGLE(0.77292817831039), + SCALE_SPLIT_ANGLE(0.77294290065765), + SCALE_SPLIT_ANGLE(0.77295738458633), + SCALE_SPLIT_ANGLE(0.77298063039780), + SCALE_SPLIT_ANGLE(0.77301889657974), + SCALE_SPLIT_ANGLE(0.77304571866989)}, + {SCALE_SPLIT_ANGLE(0.76334190368652), + SCALE_SPLIT_ANGLE(0.76335322856903), + SCALE_SPLIT_ANGLE(0.76337057352066), + SCALE_SPLIT_ANGLE(0.76341474056244), + SCALE_SPLIT_ANGLE(0.76345866918564), + SCALE_SPLIT_ANGLE(0.76353001594543), + SCALE_SPLIT_ANGLE(0.76365023851395), + SCALE_SPLIT_ANGLE(0.76373648643494)}, + {SCALE_SPLIT_ANGLE(0.74662178754807), + SCALE_SPLIT_ANGLE(0.74665385484695), + SCALE_SPLIT_ANGLE(0.74670320749283), + SCALE_SPLIT_ANGLE(0.74683058261871), + SCALE_SPLIT_ANGLE(0.74695950746536), + SCALE_SPLIT_ANGLE(0.74717390537262), + SCALE_SPLIT_ANGLE(0.74754953384399), + SCALE_SPLIT_ANGLE(0.74783092737198)}, + {SCALE_SPLIT_ANGLE(0.73124057054520), + SCALE_SPLIT_ANGLE(0.73129826784134), + SCALE_SPLIT_ANGLE(0.73138761520386), + SCALE_SPLIT_ANGLE(0.73162078857422), + SCALE_SPLIT_ANGLE(0.73186045885086), + SCALE_SPLIT_ANGLE(0.73226773738861), + SCALE_SPLIT_ANGLE(0.73300832509995), + SCALE_SPLIT_ANGLE(0.73358738422394)}, + {SCALE_SPLIT_ANGLE(0.71016556024551), + SCALE_SPLIT_ANGLE(0.71026545763016), + SCALE_SPLIT_ANGLE(0.71042120456696), + SCALE_SPLIT_ANGLE(0.71083343029022), + SCALE_SPLIT_ANGLE(0.71126621961594), + SCALE_SPLIT_ANGLE(0.71202337741852), + SCALE_SPLIT_ANGLE(0.71347540616989), + SCALE_SPLIT_ANGLE(0.71468448638916)}, + {SCALE_SPLIT_ANGLE(0.68173062801361), + SCALE_SPLIT_ANGLE(0.68189471960068), + SCALE_SPLIT_ANGLE(0.68215268850327), + SCALE_SPLIT_ANGLE(0.68284785747528), + SCALE_SPLIT_ANGLE(0.68359774351120), + SCALE_SPLIT_ANGLE(0.68496215343475), + SCALE_SPLIT_ANGLE(0.68778359889984), + SCALE_SPLIT_ANGLE(0.69036644697189)}, + {SCALE_SPLIT_ANGLE(0.64424294233322), + SCALE_SPLIT_ANGLE(0.64449471235275), + SCALE_SPLIT_ANGLE(0.64489430189133), + SCALE_SPLIT_ANGLE(0.64599478244781), + SCALE_SPLIT_ANGLE(0.64722269773483), + SCALE_SPLIT_ANGLE(0.64957273006439), + SCALE_SPLIT_ANGLE(0.65497380495071), + SCALE_SPLIT_ANGLE(0.66069257259369)}, + {SCALE_SPLIT_ANGLE(0.59645885229111), + SCALE_SPLIT_ANGLE(0.59681373834610), + SCALE_SPLIT_ANGLE(0.59738290309906), + SCALE_SPLIT_ANGLE(0.59898978471756), + SCALE_SPLIT_ANGLE(0.60085380077362), + SCALE_SPLIT_ANGLE(0.60464859008789), + SCALE_SPLIT_ANGLE(0.61471658945084), + SCALE_SPLIT_ANGLE(0.62811440229416)}, + {SCALE_SPLIT_ANGLE(0.55878311395645), + SCALE_SPLIT_ANGLE(0.55920600891113), + SCALE_SPLIT_ANGLE(0.55988913774490), + SCALE_SPLIT_ANGLE(0.56185030937195), + SCALE_SPLIT_ANGLE(0.56418746709824), + SCALE_SPLIT_ANGLE(0.56916546821594), + SCALE_SPLIT_ANGLE(0.58402228355408), + SCALE_SPLIT_ANGLE(0.60877442359924)}, + {SCALE_SPLIT_ANGLE(0.51690864562988), + SCALE_SPLIT_ANGLE(0.51739054918289), + SCALE_SPLIT_ANGLE(0.51817405223846), + SCALE_SPLIT_ANGLE(0.52045875787735), + SCALE_SPLIT_ANGLE(0.52325224876404), + SCALE_SPLIT_ANGLE(0.52947413921356), + SCALE_SPLIT_ANGLE(0.55062562227249), + SCALE_SPLIT_ANGLE(0.59875661134720)}, + {SCALE_SPLIT_ANGLE(0.47171193361282), + SCALE_SPLIT_ANGLE(0.47223743796349), + SCALE_SPLIT_ANGLE(0.47309640049934), + SCALE_SPLIT_ANGLE(0.47563400864601), + SCALE_SPLIT_ANGLE(0.47880488634109), + SCALE_SPLIT_ANGLE(0.48615166544914), + SCALE_SPLIT_ANGLE(0.51456981897354), + SCALE_SPLIT_ANGLE(0.61478358507156)}, + {SCALE_SPLIT_ANGLE(0.42445337772369), + SCALE_SPLIT_ANGLE(0.42500329017639), + SCALE_SPLIT_ANGLE(0.42590543627739), + SCALE_SPLIT_ANGLE(0.42859473824501), + SCALE_SPLIT_ANGLE(0.43200695514679), + SCALE_SPLIT_ANGLE(0.44014197587967), + SCALE_SPLIT_ANGLE(0.47505444288254), + SCALE_SPLIT_ANGLE(0.70435541868210)}, + {SCALE_SPLIT_ANGLE(0.37662339210510), + SCALE_SPLIT_ANGLE(0.37717753648758), + SCALE_SPLIT_ANGLE(0.37808802723885), + SCALE_SPLIT_ANGLE(0.38081303238869), + SCALE_SPLIT_ANGLE(0.38429373502731), + SCALE_SPLIT_ANGLE(0.39269909262657), + SCALE_SPLIT_ANGLE(0.43061128258705), + SCALE_SPLIT_ANGLE(0.89949643611908)}, + {SCALE_SPLIT_ANGLE(0.32972764968872), + SCALE_SPLIT_ANGLE(0.33026659488678), + SCALE_SPLIT_ANGLE(0.33115157485008), + SCALE_SPLIT_ANGLE(0.33379590511322), + SCALE_SPLIT_ANGLE(0.33716440200806), + SCALE_SPLIT_ANGLE(0.34525617957115), + SCALE_SPLIT_ANGLE(0.38098797202110), + SCALE_SPLIT_ANGLE(0.66312330961227)}, + {SCALE_SPLIT_ANGLE(0.28508263826370), + SCALE_SPLIT_ANGLE(0.28558859229088), + SCALE_SPLIT_ANGLE(0.28641715645790), + SCALE_SPLIT_ANGLE(0.28887593746185), + SCALE_SPLIT_ANGLE(0.29197177290916), + SCALE_SPLIT_ANGLE(0.29924646019936), + SCALE_SPLIT_ANGLE(0.32879719138145), + SCALE_SPLIT_ANGLE(0.45467028021812)}, + {SCALE_SPLIT_ANGLE(0.24368345737457), + SCALE_SPLIT_ANGLE(0.24414120614529), + SCALE_SPLIT_ANGLE(0.24488738179207), + SCALE_SPLIT_ANGLE(0.24707712233067), + SCALE_SPLIT_ANGLE(0.24978286027908), + SCALE_SPLIT_ANGLE(0.25592401623726), + SCALE_SPLIT_ANGLE(0.27806487679482), + SCALE_SPLIT_ANGLE(0.33706206083298)}, + {SCALE_SPLIT_ANGLE(0.20616286993027), + SCALE_SPLIT_ANGLE(0.20656119287014), + SCALE_SPLIT_ANGLE(0.20720668137074), + SCALE_SPLIT_ANGLE(0.20907410979271), + SCALE_SPLIT_ANGLE(0.21132774651051), + SCALE_SPLIT_ANGLE(0.21623271703720), + SCALE_SPLIT_ANGLE(0.23177997767925), + SCALE_SPLIT_ANGLE(0.26115790009499)}, + {SCALE_SPLIT_ANGLE(0.17282110452652), + SCALE_SPLIT_ANGLE(0.17315416038036), + SCALE_SPLIT_ANGLE(0.17369024455547), + SCALE_SPLIT_ANGLE(0.17521673440933), + SCALE_SPLIT_ANGLE(0.17701178789139), + SCALE_SPLIT_ANGLE(0.18074953556061), + SCALE_SPLIT_ANGLE(0.19124270975590), + SCALE_SPLIT_ANGLE(0.20666223764420)}, + {SCALE_SPLIT_ANGLE(0.13066084682941), + SCALE_SPLIT_ANGLE(0.13089758157730), + SCALE_SPLIT_ANGLE(0.13127475976944), + SCALE_SPLIT_ANGLE(0.13232271373272), + SCALE_SPLIT_ANGLE(0.13350808620453), + SCALE_SPLIT_ANGLE(0.13582544028759), + SCALE_SPLIT_ANGLE(0.14140741527081), + SCALE_SPLIT_ANGLE(0.14774028956890)}, + {SCALE_SPLIT_ANGLE(0.09729286283255), + SCALE_SPLIT_ANGLE(0.09744835644960), + SCALE_SPLIT_ANGLE(0.09769364446402), + SCALE_SPLIT_ANGLE(0.09835994243622), + SCALE_SPLIT_ANGLE(0.09908767789602), + SCALE_SPLIT_ANGLE(0.10043603181839), + SCALE_SPLIT_ANGLE(0.10332850366831), + SCALE_SPLIT_ANGLE(0.10610697418451)}, + {SCALE_SPLIT_ANGLE(0.07155895978212), + SCALE_SPLIT_ANGLE(0.07165451347828), + SCALE_SPLIT_ANGLE(0.07180397957563), + SCALE_SPLIT_ANGLE(0.07220225036144), + SCALE_SPLIT_ANGLE(0.07262472063303), + SCALE_SPLIT_ANGLE(0.07337479293346), + SCALE_SPLIT_ANGLE(0.07485356926918), + SCALE_SPLIT_ANGLE(0.07612708956003)}, + {SCALE_SPLIT_ANGLE(0.05212157219648), + SCALE_SPLIT_ANGLE(0.05217727646232), + SCALE_SPLIT_ANGLE(0.05226379260421), + SCALE_SPLIT_ANGLE(0.05249078199267), + SCALE_SPLIT_ANGLE(0.05272606015205), + SCALE_SPLIT_ANGLE(0.05313042178750), + SCALE_SPLIT_ANGLE(0.05388085916638), + SCALE_SPLIT_ANGLE(0.05448162183166)}, + {SCALE_SPLIT_ANGLE(0.03767965734005), + SCALE_SPLIT_ANGLE(0.03771083429456), + SCALE_SPLIT_ANGLE(0.03775899112225), + SCALE_SPLIT_ANGLE(0.03788382932544), + SCALE_SPLIT_ANGLE(0.03801096230745), + SCALE_SPLIT_ANGLE(0.03822423517704), + SCALE_SPLIT_ANGLE(0.03860339149833), + SCALE_SPLIT_ANGLE(0.03889226913452)}, + {SCALE_SPLIT_ANGLE(0.02168158628047), + SCALE_SPLIT_ANGLE(0.02169270813465), + SCALE_SPLIT_ANGLE(0.02170977368951), + SCALE_SPLIT_ANGLE(0.02175341546535), + SCALE_SPLIT_ANGLE(0.02179697528481), + SCALE_SPLIT_ANGLE(0.02186812832952), + SCALE_SPLIT_ANGLE(0.02198898419738), + SCALE_SPLIT_ANGLE(0.02207652665675)}, + {SCALE_SPLIT_ANGLE(0.01235581003129), + SCALE_SPLIT_ANGLE(0.01235957816243), + SCALE_SPLIT_ANGLE(0.01236534118652), + SCALE_SPLIT_ANGLE(0.01237995270640), + SCALE_SPLIT_ANGLE(0.01239436585456), + SCALE_SPLIT_ANGLE(0.01241754554212), + SCALE_SPLIT_ANGLE(0.01245592255145), + SCALE_SPLIT_ANGLE(0.01248296815902)}, + {SCALE_SPLIT_ANGLE(0.00700127054006), + SCALE_SPLIT_ANGLE(0.00700251059607), + SCALE_SPLIT_ANGLE(0.00700440211222), + SCALE_SPLIT_ANGLE(0.00700917327777), + SCALE_SPLIT_ANGLE(0.00701385037974), + SCALE_SPLIT_ANGLE(0.00702130328864), + SCALE_SPLIT_ANGLE(0.00703346775845), + SCALE_SPLIT_ANGLE(0.00704190973192)}, + {SCALE_SPLIT_ANGLE(0.00395415630192), + SCALE_SPLIT_ANGLE(0.00395455770195), + SCALE_SPLIT_ANGLE(0.00395516818389), + SCALE_SPLIT_ANGLE(0.00395670533180), + SCALE_SPLIT_ANGLE(0.00395820522681), + SCALE_SPLIT_ANGLE(0.00396058429033), + SCALE_SPLIT_ANGLE(0.00396443530917), + SCALE_SPLIT_ANGLE(0.00396708538756)}, + {SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068)}, + }, + { + {SCALE_SPLIT_ANGLE(1.17809724807739), + SCALE_SPLIT_ANGLE(1.17809724807739), + SCALE_SPLIT_ANGLE(1.17809724807739), + SCALE_SPLIT_ANGLE(1.17809724807739), + SCALE_SPLIT_ANGLE(1.17809724807739), + SCALE_SPLIT_ANGLE(1.17809724807739), + SCALE_SPLIT_ANGLE(1.17809724807739), + SCALE_SPLIT_ANGLE(1.17809724807739)}, + {SCALE_SPLIT_ANGLE(1.17289519309998), + SCALE_SPLIT_ANGLE(1.17289638519287), + SCALE_SPLIT_ANGLE(1.17289805412292), + SCALE_SPLIT_ANGLE(1.17290234565735), + SCALE_SPLIT_ANGLE(1.17290651798248), + SCALE_SPLIT_ANGLE(1.17291307449341), + SCALE_SPLIT_ANGLE(1.17292368412018), + SCALE_SPLIT_ANGLE(1.17293095588684)}, + {SCALE_SPLIT_ANGLE(1.16883802413940), + SCALE_SPLIT_ANGLE(1.16884148120880), + SCALE_SPLIT_ANGLE(1.16884684562683), + SCALE_SPLIT_ANGLE(1.16886019706726), + SCALE_SPLIT_ANGLE(1.16887319087982), + SCALE_SPLIT_ANGLE(1.16889393329620), + SCALE_SPLIT_ANGLE(1.16892755031586), + SCALE_SPLIT_ANGLE(1.16895067691803)}, + {SCALE_SPLIT_ANGLE(1.16160655021667), + SCALE_SPLIT_ANGLE(1.16161727905273), + SCALE_SPLIT_ANGLE(1.16163372993469), + SCALE_SPLIT_ANGLE(1.16167509555817), + SCALE_SPLIT_ANGLE(1.16171574592590), + SCALE_SPLIT_ANGLE(1.16178059577942), + SCALE_SPLIT_ANGLE(1.16188669204712), + SCALE_SPLIT_ANGLE(1.16196048259735)}, + {SCALE_SPLIT_ANGLE(1.14870405197144), + SCALE_SPLIT_ANGLE(1.14873659610748), + SCALE_SPLIT_ANGLE(1.14878630638123), + SCALE_SPLIT_ANGLE(1.14891266822815), + SCALE_SPLIT_ANGLE(1.14903748035431), + SCALE_SPLIT_ANGLE(1.14923894405365), + SCALE_SPLIT_ANGLE(1.14957404136658), + SCALE_SPLIT_ANGLE(1.14981138706207)}, + {SCALE_SPLIT_ANGLE(1.12567496299744), + SCALE_SPLIT_ANGLE(1.12576997280121), + SCALE_SPLIT_ANGLE(1.12591612339020), + SCALE_SPLIT_ANGLE(1.12629067897797), + SCALE_SPLIT_ANGLE(1.12666594982147), + SCALE_SPLIT_ANGLE(1.12728190422058), + SCALE_SPLIT_ANGLE(1.12833762168884), + SCALE_SPLIT_ANGLE(1.12910997867584)}, + {SCALE_SPLIT_ANGLE(1.10394382476807), + SCALE_SPLIT_ANGLE(1.10412001609802), + SCALE_SPLIT_ANGLE(1.10439181327820), + SCALE_SPLIT_ANGLE(1.10509443283081), + SCALE_SPLIT_ANGLE(1.10580694675446), + SCALE_SPLIT_ANGLE(1.10699594020844), + SCALE_SPLIT_ANGLE(1.10909199714661), + SCALE_SPLIT_ANGLE(1.11067581176758)}, + {SCALE_SPLIT_ANGLE(1.07335853576660), + SCALE_SPLIT_ANGLE(1.07367515563965), + SCALE_SPLIT_ANGLE(1.07416594028473), + SCALE_SPLIT_ANGLE(1.07544887065887), + SCALE_SPLIT_ANGLE(1.07677161693573), + SCALE_SPLIT_ANGLE(1.07902932167053), + SCALE_SPLIT_ANGLE(1.08317446708679), + SCALE_SPLIT_ANGLE(1.08645892143250)}, + {SCALE_SPLIT_ANGLE(1.03070926666260), + SCALE_SPLIT_ANGLE(1.03125381469727), + SCALE_SPLIT_ANGLE(1.03210365772247), + SCALE_SPLIT_ANGLE(1.03435742855072), + SCALE_SPLIT_ANGLE(1.03673219680786), + SCALE_SPLIT_ANGLE(1.04091238975525), + SCALE_SPLIT_ANGLE(1.04904520511627), + SCALE_SPLIT_ANGLE(1.05597066879272)}, + {SCALE_SPLIT_ANGLE(0.97233027219772), + SCALE_SPLIT_ANGLE(0.97321176528931), + SCALE_SPLIT_ANGLE(0.97459858655930), + SCALE_SPLIT_ANGLE(0.97834444046021), + SCALE_SPLIT_ANGLE(0.98240250349045), + SCALE_SPLIT_ANGLE(0.98984360694885), + SCALE_SPLIT_ANGLE(1.00556409358978), + SCALE_SPLIT_ANGLE(1.02053046226501)}, + {SCALE_SPLIT_ANGLE(0.89506644010544), + SCALE_SPLIT_ANGLE(0.89638090133667), + SCALE_SPLIT_ANGLE(0.89846849441528), + SCALE_SPLIT_ANGLE(0.90423041582108), + SCALE_SPLIT_ANGLE(0.91068577766418), + SCALE_SPLIT_ANGLE(0.92315071821213), + SCALE_SPLIT_ANGLE(0.95268243551254), + SCALE_SPLIT_ANGLE(0.98626506328583)}, + {SCALE_SPLIT_ANGLE(0.83257329463959), + SCALE_SPLIT_ANGLE(0.83419400453568), + SCALE_SPLIT_ANGLE(0.83678525686264), + SCALE_SPLIT_ANGLE(0.84404885768890), + SCALE_SPLIT_ANGLE(0.85238879919052), + SCALE_SPLIT_ANGLE(0.86914122104645), + SCALE_SPLIT_ANGLE(0.91285765171051), + SCALE_SPLIT_ANGLE(0.97222852706909)}, + {SCALE_SPLIT_ANGLE(0.76227337121964), + SCALE_SPLIT_ANGLE(0.76417022943497), + SCALE_SPLIT_ANGLE(0.76722234487534), + SCALE_SPLIT_ANGLE(0.77590966224670), + SCALE_SPLIT_ANGLE(0.78613227605820), + SCALE_SPLIT_ANGLE(0.80752640962601), + SCALE_SPLIT_ANGLE(0.86987829208374), + SCALE_SPLIT_ANGLE(0.97863066196442)}, + {SCALE_SPLIT_ANGLE(0.68631619215012), + SCALE_SPLIT_ANGLE(0.68841683864594), + SCALE_SPLIT_ANGLE(0.69181632995605), + SCALE_SPLIT_ANGLE(0.70162522792816), + SCALE_SPLIT_ANGLE(0.71342813968658), + SCALE_SPLIT_ANGLE(0.73910331726074), + SCALE_SPLIT_ANGLE(0.82307606935501), + SCALE_SPLIT_ANGLE(1.03223013877869)}, + {SCALE_SPLIT_ANGLE(0.60781323909760), + SCALE_SPLIT_ANGLE(0.61001545190811), + SCALE_SPLIT_ANGLE(0.61359488964081), + SCALE_SPLIT_ANGLE(0.62403196096420), + SCALE_SPLIT_ANGLE(0.63681113719940), + SCALE_SPLIT_ANGLE(0.66548818349838), + SCALE_SPLIT_ANGLE(0.76931142807007), + SCALE_SPLIT_ANGLE(1.19638144969940)}, + {SCALE_SPLIT_ANGLE(0.53021633625031), + SCALE_SPLIT_ANGLE(0.53240889310837), + SCALE_SPLIT_ANGLE(0.53598147630692), + SCALE_SPLIT_ANGLE(0.54646170139313), + SCALE_SPLIT_ANGLE(0.55942362546921), + SCALE_SPLIT_ANGLE(0.58904862403870), + SCALE_SPLIT_ANGLE(0.70326197147369), + SCALE_SPLIT_ANGLE(1.46822571754456)}, + {SCALE_SPLIT_ANGLE(0.45655798912048), + SCALE_SPLIT_ANGLE(0.45864027738571), + SCALE_SPLIT_ANGLE(0.46203431487083), + SCALE_SPLIT_ANGLE(0.47199890017509), + SCALE_SPLIT_ANGLE(0.48433950543404), + SCALE_SPLIT_ANGLE(0.51260900497437), + SCALE_SPLIT_ANGLE(0.62212866544724), + SCALE_SPLIT_ANGLE(1.20720028877258)}, + {SCALE_SPLIT_ANGLE(0.38893291354179), + SCALE_SPLIT_ANGLE(0.39082619547844), + SCALE_SPLIT_ANGLE(0.39390671253204), + SCALE_SPLIT_ANGLE(0.40291145443916), + SCALE_SPLIT_ANGLE(0.41398161649704), + SCALE_SPLIT_ANGLE(0.43899387121201), + SCALE_SPLIT_ANGLE(0.53091615438461), + SCALE_SPLIT_ANGLE(0.85221332311630)}, + {SCALE_SPLIT_ANGLE(0.32840186357498), + SCALE_SPLIT_ANGLE(0.33005380630493), + SCALE_SPLIT_ANGLE(0.33273181319237), + SCALE_SPLIT_ANGLE(0.34049156308174), + SCALE_SPLIT_ANGLE(0.34989202022552), + SCALE_SPLIT_ANGLE(0.37057083845139), + SCALE_SPLIT_ANGLE(0.43990376591682), + SCALE_SPLIT_ANGLE(0.60593068599701)}, + {SCALE_SPLIT_ANGLE(0.27521029114723), + SCALE_SPLIT_ANGLE(0.27659532427788), + SCALE_SPLIT_ANGLE(0.27882957458496), + SCALE_SPLIT_ANGLE(0.28522574901581), + SCALE_SPLIT_ANGLE(0.29282194375992), + SCALE_SPLIT_ANGLE(0.30895602703094), + SCALE_SPLIT_ANGLE(0.35752716660500), + SCALE_SPLIT_ANGLE(0.44366976618767)}, + {SCALE_SPLIT_ANGLE(0.22909799218178), + SCALE_SPLIT_ANGLE(0.23021572828293), + SCALE_SPLIT_ANGLE(0.23200811445713), + SCALE_SPLIT_ANGLE(0.23706816136837), + SCALE_SPLIT_ANGLE(0.24294251203537), + SCALE_SPLIT_ANGLE(0.25494652986526), + SCALE_SPLIT_ANGLE(0.28743273019791), + SCALE_SPLIT_ANGLE(0.33326253294945)}, + {SCALE_SPLIT_ANGLE(0.17204397916794), + SCALE_SPLIT_ANGLE(0.17280195653439), + SCALE_SPLIT_ANGLE(0.17400608956814), + SCALE_SPLIT_ANGLE(0.17733128368855), + SCALE_SPLIT_ANGLE(0.18105845153332), + SCALE_SPLIT_ANGLE(0.18825364112854), + SCALE_SPLIT_ANGLE(0.20519739389420), + SCALE_SPLIT_ANGLE(0.22397252917290)}, + {SCALE_SPLIT_ANGLE(0.12763081490994), + SCALE_SPLIT_ANGLE(0.12810991704464), + SCALE_SPLIT_ANGLE(0.12886413931847), + SCALE_SPLIT_ANGLE(0.13090407848358), + SCALE_SPLIT_ANGLE(0.13311788439751), + SCALE_SPLIT_ANGLE(0.13718488812447), + SCALE_SPLIT_ANGLE(0.14578336477280), + SCALE_SPLIT_ANGLE(0.15392093360424)}, + {SCALE_SPLIT_ANGLE(0.09368771314621), + SCALE_SPLIT_ANGLE(0.09397350251675), + SCALE_SPLIT_ANGLE(0.09441984444857), + SCALE_SPLIT_ANGLE(0.09560553729534), + SCALE_SPLIT_ANGLE(0.09685769677162), + SCALE_SPLIT_ANGLE(0.09906788915396), + SCALE_SPLIT_ANGLE(0.10338338464499), + SCALE_SPLIT_ANGLE(0.10706327855587)}, + {SCALE_SPLIT_ANGLE(0.06817039847374), + SCALE_SPLIT_ANGLE(0.06833326816559), + SCALE_SPLIT_ANGLE(0.06858598440886), + SCALE_SPLIT_ANGLE(0.06924756616354), + SCALE_SPLIT_ANGLE(0.06993119418621), + SCALE_SPLIT_ANGLE(0.07110133767128), + SCALE_SPLIT_ANGLE(0.07325870543718), + SCALE_SPLIT_ANGLE(0.07497421652079)}, + {SCALE_SPLIT_ANGLE(0.04925633221865), + SCALE_SPLIT_ANGLE(0.04934597760439), + SCALE_SPLIT_ANGLE(0.04948436096311), + SCALE_SPLIT_ANGLE(0.04984252527356), + SCALE_SPLIT_ANGLE(0.05020647495985), + SCALE_SPLIT_ANGLE(0.05081529542804), + SCALE_SPLIT_ANGLE(0.05189275369048), + SCALE_SPLIT_ANGLE(0.05270983651280)}, + {SCALE_SPLIT_ANGLE(0.02833298407495), + SCALE_SPLIT_ANGLE(0.02836437709630), + SCALE_SPLIT_ANGLE(0.02841254509985), + SCALE_SPLIT_ANGLE(0.02853557839990), + SCALE_SPLIT_ANGLE(0.02865825034678), + SCALE_SPLIT_ANGLE(0.02885829657316), + SCALE_SPLIT_ANGLE(0.02919724024832), + SCALE_SPLIT_ANGLE(0.02944211289287)}, + {SCALE_SPLIT_ANGLE(0.01614447496831), + SCALE_SPLIT_ANGLE(0.01615499891341), + SCALE_SPLIT_ANGLE(0.01617109030485), + SCALE_SPLIT_ANGLE(0.01621186546981), + SCALE_SPLIT_ANGLE(0.01625206694007), + SCALE_SPLIT_ANGLE(0.01631666347384), + SCALE_SPLIT_ANGLE(0.01642346009612), + SCALE_SPLIT_ANGLE(0.01649860665202)}, + {SCALE_SPLIT_ANGLE(0.00914775021374), + SCALE_SPLIT_ANGLE(0.00915119145066), + SCALE_SPLIT_ANGLE(0.00915644038469), + SCALE_SPLIT_ANGLE(0.00916968286037), + SCALE_SPLIT_ANGLE(0.00918265152723), + SCALE_SPLIT_ANGLE(0.00920331478119), + SCALE_SPLIT_ANGLE(0.00923701003194), + SCALE_SPLIT_ANGLE(0.00926037877798)}, + {SCALE_SPLIT_ANGLE(0.00516638066620), + SCALE_SPLIT_ANGLE(0.00516748987138), + SCALE_SPLIT_ANGLE(0.00516917929053), + SCALE_SPLIT_ANGLE(0.00517342984676), + SCALE_SPLIT_ANGLE(0.00517757656053), + SCALE_SPLIT_ANGLE(0.00518415356055), + SCALE_SPLIT_ANGLE(0.00519479578361), + SCALE_SPLIT_ANGLE(0.00520211551338)}, + {SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564)}, + }, + { + {SCALE_SPLIT_ANGLE(1.57079637050629), + SCALE_SPLIT_ANGLE(1.57079637050629), + SCALE_SPLIT_ANGLE(1.57079637050629), + SCALE_SPLIT_ANGLE(1.57079637050629), + SCALE_SPLIT_ANGLE(1.57079637050629), + SCALE_SPLIT_ANGLE(1.57079637050629), + SCALE_SPLIT_ANGLE(1.57079637050629), + SCALE_SPLIT_ANGLE(1.57079637050629)}, + {SCALE_SPLIT_ANGLE(1.56514155864716), + SCALE_SPLIT_ANGLE(1.56514346599579), + SCALE_SPLIT_ANGLE(1.56514656543732), + SCALE_SPLIT_ANGLE(1.56515407562256), + SCALE_SPLIT_ANGLE(1.56516146659851), + SCALE_SPLIT_ANGLE(1.56517302989960), + SCALE_SPLIT_ANGLE(1.56519174575806), + SCALE_SPLIT_ANGLE(1.56520450115204)}, + {SCALE_SPLIT_ANGLE(1.56069743633270), + SCALE_SPLIT_ANGLE(1.56070363521576), + SCALE_SPLIT_ANGLE(1.56071317195892), + SCALE_SPLIT_ANGLE(1.56073689460754), + SCALE_SPLIT_ANGLE(1.56076002120972), + SCALE_SPLIT_ANGLE(1.56079673767090), + SCALE_SPLIT_ANGLE(1.56085586547852), + SCALE_SPLIT_ANGLE(1.56089639663696)}, + {SCALE_SPLIT_ANGLE(1.55270349979401), + SCALE_SPLIT_ANGLE(1.55272293090820), + SCALE_SPLIT_ANGLE(1.55275249481201), + SCALE_SPLIT_ANGLE(1.55282700061798), + SCALE_SPLIT_ANGLE(1.55289983749390), + SCALE_SPLIT_ANGLE(1.55301547050476), + SCALE_SPLIT_ANGLE(1.55320310592651), + SCALE_SPLIT_ANGLE(1.55333256721497)}, + {SCALE_SPLIT_ANGLE(1.53820896148682), + SCALE_SPLIT_ANGLE(1.53826904296875), + SCALE_SPLIT_ANGLE(1.53836083412170), + SCALE_SPLIT_ANGLE(1.53859281539917), + SCALE_SPLIT_ANGLE(1.53882038593292), + SCALE_SPLIT_ANGLE(1.53918409347534), + SCALE_SPLIT_ANGLE(1.53978037834167), + SCALE_SPLIT_ANGLE(1.54019629955292)}, + {SCALE_SPLIT_ANGLE(1.51160359382629), + SCALE_SPLIT_ANGLE(1.51178681850433), + SCALE_SPLIT_ANGLE(1.51206707954407), + SCALE_SPLIT_ANGLE(1.51277923583984), + SCALE_SPLIT_ANGLE(1.51348364353180), + SCALE_SPLIT_ANGLE(1.51462137699127), + SCALE_SPLIT_ANGLE(1.51652014255524), + SCALE_SPLIT_ANGLE(1.51787149906158)}, + {SCALE_SPLIT_ANGLE(1.48564028739929), + SCALE_SPLIT_ANGLE(1.48599278926849), + SCALE_SPLIT_ANGLE(1.48653328418732), + SCALE_SPLIT_ANGLE(1.48791313171387), + SCALE_SPLIT_ANGLE(1.48928797245026), + SCALE_SPLIT_ANGLE(1.49152994155884), + SCALE_SPLIT_ANGLE(1.49533641338348), + SCALE_SPLIT_ANGLE(1.49810016155243)}, + {SCALE_SPLIT_ANGLE(1.44770443439484), + SCALE_SPLIT_ANGLE(1.44837117195129), + SCALE_SPLIT_ANGLE(1.44939684867859), + SCALE_SPLIT_ANGLE(1.45203149318695), + SCALE_SPLIT_ANGLE(1.45468175411224), + SCALE_SPLIT_ANGLE(1.45906186103821), + SCALE_SPLIT_ANGLE(1.46668362617493), + SCALE_SPLIT_ANGLE(1.47238755226135)}, + {SCALE_SPLIT_ANGLE(1.39214622974396), + SCALE_SPLIT_ANGLE(1.39337480068207), + SCALE_SPLIT_ANGLE(1.39527153968811), + SCALE_SPLIT_ANGLE(1.40018463134766), + SCALE_SPLIT_ANGLE(1.40518975257874), + SCALE_SPLIT_ANGLE(1.41361439228058), + SCALE_SPLIT_ANGLE(1.42880713939667), + SCALE_SPLIT_ANGLE(1.44072246551514)}, + {SCALE_SPLIT_ANGLE(1.31133699417114), + SCALE_SPLIT_ANGLE(1.31350564956665), + SCALE_SPLIT_ANGLE(1.31686961650848), + SCALE_SPLIT_ANGLE(1.32567906379700), + SCALE_SPLIT_ANGLE(1.33480501174927), + SCALE_SPLIT_ANGLE(1.35055577754974), + SCALE_SPLIT_ANGLE(1.38048458099365), + SCALE_SPLIT_ANGLE(1.40579915046692)}, + {SCALE_SPLIT_ANGLE(1.19695901870728), + SCALE_SPLIT_ANGLE(1.20052528381348), + SCALE_SPLIT_ANGLE(1.20609176158905), + SCALE_SPLIT_ANGLE(1.22087836265564), + SCALE_SPLIT_ANGLE(1.23654139041901), + SCALE_SPLIT_ANGLE(1.26451897621155), + SCALE_SPLIT_ANGLE(1.32194638252258), + SCALE_SPLIT_ANGLE(1.37709856033325)}, + {SCALE_SPLIT_ANGLE(1.09969496726990), + SCALE_SPLIT_ANGLE(1.10437381267548), + SCALE_SPLIT_ANGLE(1.11171460151672), + SCALE_SPLIT_ANGLE(1.13144767284393), + SCALE_SPLIT_ANGLE(1.15274536609650), + SCALE_SPLIT_ANGLE(1.19192278385162), + SCALE_SPLIT_ANGLE(1.27820122241974), + SCALE_SPLIT_ANGLE(1.37287366390228)}, + {SCALE_SPLIT_ANGLE(0.98739641904831), + SCALE_SPLIT_ANGLE(0.99314504861832), + SCALE_SPLIT_ANGLE(1.00221848487854), + SCALE_SPLIT_ANGLE(1.02694928646088), + SCALE_SPLIT_ANGLE(1.05423069000244), + SCALE_SPLIT_ANGLE(1.10619938373566), + SCALE_SPLIT_ANGLE(1.23116791248322), + SCALE_SPLIT_ANGLE(1.39771795272827)}, + {SCALE_SPLIT_ANGLE(0.86566168069839), + SCALE_SPLIT_ANGLE(0.87219274044037), + SCALE_SPLIT_ANGLE(0.88256764411926), + SCALE_SPLIT_ANGLE(0.91127204895020), + SCALE_SPLIT_ANGLE(0.94370108842850), + SCALE_SPLIT_ANGLE(1.00792455673218), + SCALE_SPLIT_ANGLE(1.17914211750031), + SCALE_SPLIT_ANGLE(1.48121190071106)}, + {SCALE_SPLIT_ANGLE(0.74293035268784), + SCALE_SPLIT_ANGLE(0.74975663423538), + SCALE_SPLIT_ANGLE(0.76066619157791), + SCALE_SPLIT_ANGLE(0.79128372669220), + SCALE_SPLIT_ANGLE(0.82667875289917), + SCALE_SPLIT_ANGLE(0.89952337741852), + SCALE_SPLIT_ANGLE(1.11571300029755), + SCALE_SPLIT_ANGLE(1.67431199550629)}, + {SCALE_SPLIT_ANGLE(0.62761706113815), + SCALE_SPLIT_ANGLE(0.63421267271042), + SCALE_SPLIT_ANGLE(0.64480352401733), + SCALE_SPLIT_ANGLE(0.67486244440079), + SCALE_SPLIT_ANGLE(0.71025311946869), + SCALE_SPLIT_ANGLE(0.78539818525314), + SCALE_SPLIT_ANGLE(1.02937340736389), + SCALE_SPLIT_ANGLE(1.92301487922668)}, + {SCALE_SPLIT_ANGLE(0.52522456645966), + SCALE_SPLIT_ANGLE(0.53118568658829), + SCALE_SPLIT_ANGLE(0.54078328609467), + SCALE_SPLIT_ANGLE(0.56819748878479), + SCALE_SPLIT_ANGLE(0.60080903768539), + SCALE_SPLIT_ANGLE(0.67127299308777), + SCALE_SPLIT_ANGLE(0.91114157438278), + SCALE_SPLIT_ANGLE(1.73398244380951)}, + {SCALE_SPLIT_ANGLE(0.43751955032349), + SCALE_SPLIT_ANGLE(0.44262495636940), + SCALE_SPLIT_ANGLE(0.45084837079048), + SCALE_SPLIT_ANGLE(0.47435709834099), + SCALE_SPLIT_ANGLE(0.50235128402710), + SCALE_SPLIT_ANGLE(0.56287181377411), + SCALE_SPLIT_ANGLE(0.76705121994019), + SCALE_SPLIT_ANGLE(1.34888231754303)}, + {SCALE_SPLIT_ANGLE(0.36364197731018), + SCALE_SPLIT_ANGLE(0.36782836914063), + SCALE_SPLIT_ANGLE(0.37456014752388), + SCALE_SPLIT_ANGLE(0.39372295141220), + SCALE_SPLIT_ANGLE(0.41636970639229), + SCALE_SPLIT_ANGLE(0.46459695696831), + SCALE_SPLIT_ANGLE(0.61803084611893), + SCALE_SPLIT_ANGLE(0.96275907754898)}, + {SCALE_SPLIT_ANGLE(0.30166232585907), + SCALE_SPLIT_ANGLE(0.30497136712074), + SCALE_SPLIT_ANGLE(0.31027451157570), + SCALE_SPLIT_ANGLE(0.32524627447128), + SCALE_SPLIT_ANGLE(0.34269109368324), + SCALE_SPLIT_ANGLE(0.37887358665466), + SCALE_SPLIT_ANGLE(0.48432540893555), + SCALE_SPLIT_ANGLE(0.66878592967987)}, + {SCALE_SPLIT_ANGLE(0.24960109591484), + SCALE_SPLIT_ANGLE(0.25213342905045), + SCALE_SPLIT_ANGLE(0.25617361068726), + SCALE_SPLIT_ANGLE(0.26745575666428), + SCALE_SPLIT_ANGLE(0.28036275506020), + SCALE_SPLIT_ANGLE(0.30627736449242), + SCALE_SPLIT_ANGLE(0.37490701675415), + SCALE_SPLIT_ANGLE(0.47145301103592)}, + {SCALE_SPLIT_ANGLE(0.18661488592625), + SCALE_SPLIT_ANGLE(0.18822197616100), + SCALE_SPLIT_ANGLE(0.19076596200466), + SCALE_SPLIT_ANGLE(0.19773863255978), + SCALE_SPLIT_ANGLE(0.20547652244568), + SCALE_SPLIT_ANGLE(0.22024063766003), + SCALE_SPLIT_ANGLE(0.25452125072479), + SCALE_SPLIT_ANGLE(0.29236793518066)}, + {SCALE_SPLIT_ANGLE(0.13821771740913), + SCALE_SPLIT_ANGLE(0.13918289542198), + SCALE_SPLIT_ANGLE(0.14069861173630), + SCALE_SPLIT_ANGLE(0.14477686583996), + SCALE_SPLIT_ANGLE(0.14917233586311), + SCALE_SPLIT_ANGLE(0.15718193352222), + SCALE_SPLIT_ANGLE(0.17394064366817), + SCALE_SPLIT_ANGLE(0.18971265852451)}, + {SCALE_SPLIT_ANGLE(0.10140904784203), + SCALE_SPLIT_ANGLE(0.10196315497160), + SCALE_SPLIT_ANGLE(0.10282710194588), + SCALE_SPLIT_ANGLE(0.10511382669210), + SCALE_SPLIT_ANGLE(0.10751703381538), + SCALE_SPLIT_ANGLE(0.11173453181982), + SCALE_SPLIT_ANGLE(0.11990433931351), + SCALE_SPLIT_ANGLE(0.12683042883873)}, + {SCALE_SPLIT_ANGLE(0.07378087192774), + SCALE_SPLIT_ANGLE(0.07408788800240), + SCALE_SPLIT_ANGLE(0.07456368207932), + SCALE_SPLIT_ANGLE(0.07580613344908), + SCALE_SPLIT_ANGLE(0.07708553224802), + SCALE_SPLIT_ANGLE(0.07926639169455), + SCALE_SPLIT_ANGLE(0.08326309919357), + SCALE_SPLIT_ANGLE(0.08642497658730)}, + {SCALE_SPLIT_ANGLE(0.05331044271588), + SCALE_SPLIT_ANGLE(0.05347600579262), + SCALE_SPLIT_ANGLE(0.05373133346438), + SCALE_SPLIT_ANGLE(0.05439101532102), + SCALE_SPLIT_ANGLE(0.05505970120430), + SCALE_SPLIT_ANGLE(0.05617496743798), + SCALE_SPLIT_ANGLE(0.05813983827829), + SCALE_SPLIT_ANGLE(0.05962376296520)}, + {SCALE_SPLIT_ANGLE(0.03066622652113), + SCALE_SPLIT_ANGLE(0.03072291985154), + SCALE_SPLIT_ANGLE(0.03080986253917), + SCALE_SPLIT_ANGLE(0.03103173524141), + SCALE_SPLIT_ANGLE(0.03125262632966), + SCALE_SPLIT_ANGLE(0.03161224350333), + SCALE_SPLIT_ANGLE(0.03221991285682), + SCALE_SPLIT_ANGLE(0.03265778720379)}, + {SCALE_SPLIT_ANGLE(0.01747439615428), + SCALE_SPLIT_ANGLE(0.01749316416681), + SCALE_SPLIT_ANGLE(0.01752184517682), + SCALE_SPLIT_ANGLE(0.01759449020028), + SCALE_SPLIT_ANGLE(0.01766604930162), + SCALE_SPLIT_ANGLE(0.01778092049062), + SCALE_SPLIT_ANGLE(0.01797054335475), + SCALE_SPLIT_ANGLE(0.01810375973582)}, + {SCALE_SPLIT_ANGLE(0.00990140344948), + SCALE_SPLIT_ANGLE(0.00990749336779), + SCALE_SPLIT_ANGLE(0.00991678331047), + SCALE_SPLIT_ANGLE(0.00994021166116), + SCALE_SPLIT_ANGLE(0.00996314454824), + SCALE_SPLIT_ANGLE(0.00999966636300), + SCALE_SPLIT_ANGLE(0.01005917042494), + SCALE_SPLIT_ANGLE(0.01010039448738)}, + {SCALE_SPLIT_ANGLE(0.00559204118326), + SCALE_SPLIT_ANGLE(0.00559399509802), + SCALE_SPLIT_ANGLE(0.00559697346762), + SCALE_SPLIT_ANGLE(0.00560446362942), + SCALE_SPLIT_ANGLE(0.00561177125201), + SCALE_SPLIT_ANGLE(0.00562335411087), + SCALE_SPLIT_ANGLE(0.00564208766446), + SCALE_SPLIT_ANGLE(0.00565496599302)}, + {SCALE_SPLIT_ANGLE(0.00000003162278), + SCALE_SPLIT_ANGLE(0.00000003162278), + SCALE_SPLIT_ANGLE(0.00000003162278), + SCALE_SPLIT_ANGLE(0.00000003162278), + SCALE_SPLIT_ANGLE(0.00000003162278), + SCALE_SPLIT_ANGLE(0.00000003162278), + SCALE_SPLIT_ANGLE(0.00000003162278), + SCALE_SPLIT_ANGLE(0.00000003162278)}, + }, + { + {SCALE_SPLIT_ANGLE(1.96349537372589), + SCALE_SPLIT_ANGLE(1.96349537372589), + SCALE_SPLIT_ANGLE(1.96349537372589), + SCALE_SPLIT_ANGLE(1.96349537372589), + SCALE_SPLIT_ANGLE(1.96349537372589), + SCALE_SPLIT_ANGLE(1.96349537372589), + SCALE_SPLIT_ANGLE(1.96349537372589), + SCALE_SPLIT_ANGLE(1.96349537372589)}, + {SCALE_SPLIT_ANGLE(1.95824837684631), + SCALE_SPLIT_ANGLE(1.95825088024139), + SCALE_SPLIT_ANGLE(1.95825481414795), + SCALE_SPLIT_ANGLE(1.95826447010040), + SCALE_SPLIT_ANGLE(1.95827388763428), + SCALE_SPLIT_ANGLE(1.95828890800476), + SCALE_SPLIT_ANGLE(1.95831274986267), + SCALE_SPLIT_ANGLE(1.95832908153534)}, + {SCALE_SPLIT_ANGLE(1.95409297943115), + SCALE_SPLIT_ANGLE(1.95410108566284), + SCALE_SPLIT_ANGLE(1.95411336421967), + SCALE_SPLIT_ANGLE(1.95414412021637), + SCALE_SPLIT_ANGLE(1.95417404174805), + SCALE_SPLIT_ANGLE(1.95422136783600), + SCALE_SPLIT_ANGLE(1.95429730415344), + SCALE_SPLIT_ANGLE(1.95434916019440)}, + {SCALE_SPLIT_ANGLE(1.94654774665833), + SCALE_SPLIT_ANGLE(1.94657325744629), + SCALE_SPLIT_ANGLE(1.94661211967468), + SCALE_SPLIT_ANGLE(1.94670987129211), + SCALE_SPLIT_ANGLE(1.94680488109589), + SCALE_SPLIT_ANGLE(1.94695508480072), + SCALE_SPLIT_ANGLE(1.94719684123993), + SCALE_SPLIT_ANGLE(1.94736230373383)}, + {SCALE_SPLIT_ANGLE(1.93263375759125), + SCALE_SPLIT_ANGLE(1.93271493911743), + SCALE_SPLIT_ANGLE(1.93283843994141), + SCALE_SPLIT_ANGLE(1.93314898014069), + SCALE_SPLIT_ANGLE(1.93345153331757), + SCALE_SPLIT_ANGLE(1.93393051624298), + SCALE_SPLIT_ANGLE(1.93470382690430), + SCALE_SPLIT_ANGLE(1.93523514270782)}, + {SCALE_SPLIT_ANGLE(1.90630435943604), + SCALE_SPLIT_ANGLE(1.90656292438507), + SCALE_SPLIT_ANGLE(1.90695691108704), + SCALE_SPLIT_ANGLE(1.90794765949249), + SCALE_SPLIT_ANGLE(1.90891444683075), + SCALE_SPLIT_ANGLE(1.91044902801514), + SCALE_SPLIT_ANGLE(1.91294109821320), + SCALE_SPLIT_ANGLE(1.91466653347015)}, + {SCALE_SPLIT_ANGLE(1.87960743904114), + SCALE_SPLIT_ANGLE(1.88012742996216), + SCALE_SPLIT_ANGLE(1.88091933727264), + SCALE_SPLIT_ANGLE(1.88291192054749), + SCALE_SPLIT_ANGLE(1.88485777378082), + SCALE_SPLIT_ANGLE(1.88795232772827), + SCALE_SPLIT_ANGLE(1.89300394058228), + SCALE_SPLIT_ANGLE(1.89652991294861)}, + {SCALE_SPLIT_ANGLE(1.83877396583557), + SCALE_SPLIT_ANGLE(1.83982229232788), + SCALE_SPLIT_ANGLE(1.84141862392426), + SCALE_SPLIT_ANGLE(1.84543347358704), + SCALE_SPLIT_ANGLE(1.84935534000397), + SCALE_SPLIT_ANGLE(1.85560429096222), + SCALE_SPLIT_ANGLE(1.86587727069855), + SCALE_SPLIT_ANGLE(1.87314081192017)}, + {SCALE_SPLIT_ANGLE(1.77493417263031), + SCALE_SPLIT_ANGLE(1.77705264091492), + SCALE_SPLIT_ANGLE(1.78027474880219), + SCALE_SPLIT_ANGLE(1.78836548328400), + SCALE_SPLIT_ANGLE(1.79626095294952), + SCALE_SPLIT_ANGLE(1.80886054039001), + SCALE_SPLIT_ANGLE(1.82978034019470), + SCALE_SPLIT_ANGLE(1.84489548206329)}, + {SCALE_SPLIT_ANGLE(1.67321813106537), + SCALE_SPLIT_ANGLE(1.67747652530670), + SCALE_SPLIT_ANGLE(1.68394017219543), + SCALE_SPLIT_ANGLE(1.70011746883392), + SCALE_SPLIT_ANGLE(1.71586501598358), + SCALE_SPLIT_ANGLE(1.74102878570557), + SCALE_SPLIT_ANGLE(1.78345441818237), + SCALE_SPLIT_ANGLE(1.81531298160553)}, + {SCALE_SPLIT_ANGLE(1.51132118701935), + SCALE_SPLIT_ANGLE(1.51959395408630), + SCALE_SPLIT_ANGLE(1.53212559223175), + SCALE_SPLIT_ANGLE(1.56339788436890), + SCALE_SPLIT_ANGLE(1.59380054473877), + SCALE_SPLIT_ANGLE(1.64260375499725), + SCALE_SPLIT_ANGLE(1.72719120979309), + SCALE_SPLIT_ANGLE(1.79549276828766)}, + {SCALE_SPLIT_ANGLE(1.35904061794281), + SCALE_SPLIT_ANGLE(1.37121617794037), + SCALE_SPLIT_ANGLE(1.38967239856720), + SCALE_SPLIT_ANGLE(1.43583393096924), + SCALE_SPLIT_ANGLE(1.48093688488007), + SCALE_SPLIT_ANGLE(1.55410325527191), + SCALE_SPLIT_ANGLE(1.68521773815155), + SCALE_SPLIT_ANGLE(1.80024886131287)}, + {SCALE_SPLIT_ANGLE(1.17258906364441), + SCALE_SPLIT_ANGLE(1.18893885612488), + SCALE_SPLIT_ANGLE(1.21383893489838), + SCALE_SPLIT_ANGLE(1.27678310871124), + SCALE_SPLIT_ANGLE(1.33930420875549), + SCALE_SPLIT_ANGLE(1.44322526454926), + SCALE_SPLIT_ANGLE(1.64006817340851), + SCALE_SPLIT_ANGLE(1.83627605438232)}, + {SCALE_SPLIT_ANGLE(0.96933782100677), + SCALE_SPLIT_ANGLE(0.98854482173920), + SCALE_SPLIT_ANGLE(1.01807177066803), + SCALE_SPLIT_ANGLE(1.09429967403412), + SCALE_SPLIT_ANGLE(1.17245352268219), + SCALE_SPLIT_ANGLE(1.30826878547668), + SCALE_SPLIT_ANGLE(1.58911180496216), + SCALE_SPLIT_ANGLE(1.92719435691834)}, + {SCALE_SPLIT_ANGLE(0.77729862928391), + SCALE_SPLIT_ANGLE(0.79675698280334), + SCALE_SPLIT_ANGLE(0.82701611518860), + SCALE_SPLIT_ANGLE(0.90724968910217), + SCALE_SPLIT_ANGLE(0.99302649497986), + SCALE_SPLIT_ANGLE(1.15163993835449), + SCALE_SPLIT_ANGLE(1.52265202999115), + SCALE_SPLIT_ANGLE(2.09869623184204)}, + {SCALE_SPLIT_ANGLE(0.61765128374100), + SCALE_SPLIT_ANGLE(0.63503885269165), + SCALE_SPLIT_ANGLE(0.66235077381134), + SCALE_SPLIT_ANGLE(0.73653638362885), + SCALE_SPLIT_ANGLE(0.81904613971710), + SCALE_SPLIT_ANGLE(0.98174768686295), + SCALE_SPLIT_ANGLE(1.42110538482666), + SCALE_SPLIT_ANGLE(2.28386068344116)}, + {SCALE_SPLIT_ANGLE(0.49486333131790), + SCALE_SPLIT_ANGLE(0.50909578800201), + SCALE_SPLIT_ANGLE(0.53160983324051), + SCALE_SPLIT_ANGLE(0.59379214048386), + SCALE_SPLIT_ANGLE(0.66487491130829), + SCALE_SPLIT_ANGLE(0.81185549497604), + SCALE_SPLIT_ANGLE(1.26233386993408), + SCALE_SPLIT_ANGLE(2.16925764083862)}, + {SCALE_SPLIT_ANGLE(0.40230560302734), + SCALE_SPLIT_ANGLE(0.41332274675369), + SCALE_SPLIT_ANGLE(0.43082228302956), + SCALE_SPLIT_ANGLE(0.47957953810692), + SCALE_SPLIT_ANGLE(0.53603589534760), + SCALE_SPLIT_ANGLE(0.65522658824921), + SCALE_SPLIT_ANGLE(1.04503858089447), + SCALE_SPLIT_ANGLE(1.87041807174683)}, + {SCALE_SPLIT_ANGLE(0.33104607462883), + SCALE_SPLIT_ANGLE(0.33927726745605), + SCALE_SPLIT_ANGLE(0.35237133502960), + SCALE_SPLIT_ANGLE(0.38892474770546), + SCALE_SPLIT_ANGLE(0.43126159906387), + SCALE_SPLIT_ANGLE(0.52027010917664), + SCALE_SPLIT_ANGLE(0.80654186010361), + SCALE_SPLIT_ANGLE(1.41960310935974)}, + {SCALE_SPLIT_ANGLE(0.27415537834167), + SCALE_SPLIT_ANGLE(0.28015670180321), + SCALE_SPLIT_ANGLE(0.28969678282738), + SCALE_SPLIT_ANGLE(0.31623730063438), + SCALE_SPLIT_ANGLE(0.34670370817184), + SCALE_SPLIT_ANGLE(0.40939208865166), + SCALE_SPLIT_ANGLE(0.59604310989380), + SCALE_SPLIT_ANGLE(0.94309806823730)}, + {SCALE_SPLIT_ANGLE(0.22730343043804), + SCALE_SPLIT_ANGLE(0.23159568011761), + SCALE_SPLIT_ANGLE(0.23840220272541), + SCALE_SPLIT_ANGLE(0.25720024108887), + SCALE_SPLIT_ANGLE(0.27846288681030), + SCALE_SPLIT_ANGLE(0.32089167833328), + SCALE_SPLIT_ANGLE(0.43515858054161), + SCALE_SPLIT_ANGLE(0.60621982812881)}, + {SCALE_SPLIT_ANGLE(0.17074465751648), + SCALE_SPLIT_ANGLE(0.17326098680496), + SCALE_SPLIT_ANGLE(0.17722852528095), + SCALE_SPLIT_ANGLE(0.18802370131016), + SCALE_SPLIT_ANGLE(0.19990929961205), + SCALE_SPLIT_ANGLE(0.22246663272381), + SCALE_SPLIT_ANGLE(0.27514943480492), + SCALE_SPLIT_ANGLE(0.33505329489708)}, + {SCALE_SPLIT_ANGLE(0.12695817649364), + SCALE_SPLIT_ANGLE(0.12838459014893), + SCALE_SPLIT_ANGLE(0.13061878085136), + SCALE_SPLIT_ANGLE(0.13660037517548), + SCALE_SPLIT_ANGLE(0.14301040768623), + SCALE_SPLIT_ANGLE(0.15463486313820), + SCALE_SPLIT_ANGLE(0.17893929779530), + SCALE_SPLIT_ANGLE(0.20203559100628)}, + {SCALE_SPLIT_ANGLE(0.09338590502739), + SCALE_SPLIT_ANGLE(0.09417138993740), + SCALE_SPLIT_ANGLE(0.09539390355349), + SCALE_SPLIT_ANGLE(0.09861853718758), + SCALE_SPLIT_ANGLE(0.10199318081141), + SCALE_SPLIT_ANGLE(0.10789106786251), + SCALE_SPLIT_ANGLE(0.11927830427885), + SCALE_SPLIT_ANGLE(0.12894381582737)}, + {SCALE_SPLIT_ANGLE(0.06804535537958), + SCALE_SPLIT_ANGLE(0.06846775114536), + SCALE_SPLIT_ANGLE(0.06912153959274), + SCALE_SPLIT_ANGLE(0.07082461565733), + SCALE_SPLIT_ANGLE(0.07257289439440), + SCALE_SPLIT_ANGLE(0.07554303854704), + SCALE_SPLIT_ANGLE(0.08096561580896), + SCALE_SPLIT_ANGLE(0.08524779230356)}, + {SCALE_SPLIT_ANGLE(0.04920704290271), + SCALE_SPLIT_ANGLE(0.04942999407649), + SCALE_SPLIT_ANGLE(0.04977354034781), + SCALE_SPLIT_ANGLE(0.05065960064530), + SCALE_SPLIT_ANGLE(0.05155571550131), + SCALE_SPLIT_ANGLE(0.05304637551308), + SCALE_SPLIT_ANGLE(0.05566369369626), + SCALE_SPLIT_ANGLE(0.05763531476259)}, + {SCALE_SPLIT_ANGLE(0.02832321822643), + SCALE_SPLIT_ANGLE(0.02839783765376), + SCALE_SPLIT_ANGLE(0.02851220779121), + SCALE_SPLIT_ANGLE(0.02880378998816), + SCALE_SPLIT_ANGLE(0.02909369394183), + SCALE_SPLIT_ANGLE(0.02956490404904), + SCALE_SPLIT_ANGLE(0.03035926818848), + SCALE_SPLIT_ANGLE(0.03093044832349)}, + {SCALE_SPLIT_ANGLE(0.01614263281226), + SCALE_SPLIT_ANGLE(0.01616701297462), + SCALE_SPLIT_ANGLE(0.01620426215231), + SCALE_SPLIT_ANGLE(0.01629856042564), + SCALE_SPLIT_ANGLE(0.01639137230814), + SCALE_SPLIT_ANGLE(0.01654022186995), + SCALE_SPLIT_ANGLE(0.01678557507694), + SCALE_SPLIT_ANGLE(0.01695770025253)}, + {SCALE_SPLIT_ANGLE(0.00914741214365), + SCALE_SPLIT_ANGLE(0.00915526598692), + SCALE_SPLIT_ANGLE(0.00916724558920), + SCALE_SPLIT_ANGLE(0.00919744372368), + SCALE_SPLIT_ANGLE(0.00922699086368), + SCALE_SPLIT_ANGLE(0.00927402079105), + SCALE_SPLIT_ANGLE(0.00935057550669), + SCALE_SPLIT_ANGLE(0.00940357148647)}, + {SCALE_SPLIT_ANGLE(0.00516631966457), + SCALE_SPLIT_ANGLE(0.00516883004457), + SCALE_SPLIT_ANGLE(0.00517265405506), + SCALE_SPLIT_ANGLE(0.00518227089196), + SCALE_SPLIT_ANGLE(0.00519165024161), + SCALE_SPLIT_ANGLE(0.00520651414990), + SCALE_SPLIT_ANGLE(0.00523054087535), + SCALE_SPLIT_ANGLE(0.00524705136195)}, + {SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564), + SCALE_SPLIT_ANGLE(0.00000002921564)}, + }, + { + {SCALE_SPLIT_ANGLE(2.35619449615479), + SCALE_SPLIT_ANGLE(2.35619449615479), + SCALE_SPLIT_ANGLE(2.35619449615479), + SCALE_SPLIT_ANGLE(2.35619449615479), + SCALE_SPLIT_ANGLE(2.35619449615479), + SCALE_SPLIT_ANGLE(2.35619449615479), + SCALE_SPLIT_ANGLE(2.35619449615479), + SCALE_SPLIT_ANGLE(2.35619449615479)}, + {SCALE_SPLIT_ANGLE(2.35216379165649), + SCALE_SPLIT_ANGLE(2.35216617584229), + SCALE_SPLIT_ANGLE(2.35216999053955), + SCALE_SPLIT_ANGLE(2.35217905044556), + SCALE_SPLIT_ANGLE(2.35218811035156), + SCALE_SPLIT_ANGLE(2.35220217704773), + SCALE_SPLIT_ANGLE(2.35222482681274), + SCALE_SPLIT_ANGLE(2.35224032402039)}, + {SCALE_SPLIT_ANGLE(2.34895062446594), + SCALE_SPLIT_ANGLE(2.34895825386047), + SCALE_SPLIT_ANGLE(2.34897017478943), + SCALE_SPLIT_ANGLE(2.34899950027466), + SCALE_SPLIT_ANGLE(2.34902811050415), + SCALE_SPLIT_ANGLE(2.34907317161560), + SCALE_SPLIT_ANGLE(2.34914517402649), + SCALE_SPLIT_ANGLE(2.34919428825378)}, + {SCALE_SPLIT_ANGLE(2.34306812286377), + SCALE_SPLIT_ANGLE(2.34309291839600), + SCALE_SPLIT_ANGLE(2.34313082695007), + SCALE_SPLIT_ANGLE(2.34322524070740), + SCALE_SPLIT_ANGLE(2.34331679344177), + SCALE_SPLIT_ANGLE(2.34346079826355), + SCALE_SPLIT_ANGLE(2.34369087219238), + SCALE_SPLIT_ANGLE(2.34384727478027)}, + {SCALE_SPLIT_ANGLE(2.33205723762512), + SCALE_SPLIT_ANGLE(2.33213782310486), + SCALE_SPLIT_ANGLE(2.33226013183594), + SCALE_SPLIT_ANGLE(2.33256578445435), + SCALE_SPLIT_ANGLE(2.33286166191101), + SCALE_SPLIT_ANGLE(2.33332633972168), + SCALE_SPLIT_ANGLE(2.33406686782837), + SCALE_SPLIT_ANGLE(2.33456921577454)}, + {SCALE_SPLIT_ANGLE(2.31062912940979), + SCALE_SPLIT_ANGLE(2.31089663505554), + SCALE_SPLIT_ANGLE(2.31130218505859), + SCALE_SPLIT_ANGLE(2.31231284141541), + SCALE_SPLIT_ANGLE(2.31328654289246), + SCALE_SPLIT_ANGLE(2.31480789184570), + SCALE_SPLIT_ANGLE(2.31722092628479), + SCALE_SPLIT_ANGLE(2.31885290145874)}, + {SCALE_SPLIT_ANGLE(2.28808355331421), + SCALE_SPLIT_ANGLE(2.28864479064941), + SCALE_SPLIT_ANGLE(2.28949403762817), + SCALE_SPLIT_ANGLE(2.29160070419312), + SCALE_SPLIT_ANGLE(2.29361891746521), + SCALE_SPLIT_ANGLE(2.29675459861755), + SCALE_SPLIT_ANGLE(2.30169844627380), + SCALE_SPLIT_ANGLE(2.30503511428833)}, + {SCALE_SPLIT_ANGLE(2.25191521644592), + SCALE_SPLIT_ANGLE(2.25312566757202), + SCALE_SPLIT_ANGLE(2.25494909286499), + SCALE_SPLIT_ANGLE(2.25943517684937), + SCALE_SPLIT_ANGLE(2.26368880271912), + SCALE_SPLIT_ANGLE(2.27023100852966), + SCALE_SPLIT_ANGLE(2.28044486045837), + SCALE_SPLIT_ANGLE(2.28732299804688)}, + {SCALE_SPLIT_ANGLE(2.19093585014343), + SCALE_SPLIT_ANGLE(2.19366121292114), + SCALE_SPLIT_ANGLE(2.19773292541504), + SCALE_SPLIT_ANGLE(2.20759749412537), + SCALE_SPLIT_ANGLE(2.21677780151367), + SCALE_SPLIT_ANGLE(2.23064494132996), + SCALE_SPLIT_ANGLE(2.25193929672241), + SCALE_SPLIT_ANGLE(2.26625943183899)}, + {SCALE_SPLIT_ANGLE(2.08102917671204), + SCALE_SPLIT_ANGLE(2.08757281303406), + SCALE_SPLIT_ANGLE(2.09720706939697), + SCALE_SPLIT_ANGLE(2.11991167068481), + SCALE_SPLIT_ANGLE(2.14035654067993), + SCALE_SPLIT_ANGLE(2.17029213905334), + SCALE_SPLIT_ANGLE(2.21503138542175), + SCALE_SPLIT_ANGLE(2.24518108367920)}, + {SCALE_SPLIT_ANGLE(1.86738610267639), + SCALE_SPLIT_ANGLE(1.88426077365875), + SCALE_SPLIT_ANGLE(1.90853273868561), + SCALE_SPLIT_ANGLE(1.96333324909210), + SCALE_SPLIT_ANGLE(2.01024460792542), + SCALE_SPLIT_ANGLE(2.07577633857727), + SCALE_SPLIT_ANGLE(2.16986608505249), + SCALE_SPLIT_ANGLE(2.23406052589417)}, + {SCALE_SPLIT_ANGLE(1.61812174320221), + SCALE_SPLIT_ANGLE(1.64943754673004), + SCALE_SPLIT_ANGLE(1.69389235973358), + SCALE_SPLIT_ANGLE(1.79176020622253), + SCALE_SPLIT_ANGLE(1.87292492389679), + SCALE_SPLIT_ANGLE(1.98277986049652), + SCALE_SPLIT_ANGLE(2.13605809211731), + SCALE_SPLIT_ANGLE(2.24282979965210)}, + {SCALE_SPLIT_ANGLE(1.26556181907654), + SCALE_SPLIT_ANGLE(1.31512010097504), + SCALE_SPLIT_ANGLE(1.38608694076538), + SCALE_SPLIT_ANGLE(1.54419934749603), + SCALE_SPLIT_ANGLE(1.67621040344238), + SCALE_SPLIT_ANGLE(1.85417342185974), + SCALE_SPLIT_ANGLE(2.09956336021423), + SCALE_SPLIT_ANGLE(2.27729439735413)}, + {SCALE_SPLIT_ANGLE(0.88984864950180), + SCALE_SPLIT_ANGLE(0.94673132896423), + SCALE_SPLIT_ANGLE(1.03102219104767), + SCALE_SPLIT_ANGLE(1.23219704627991), + SCALE_SPLIT_ANGLE(1.41468584537506), + SCALE_SPLIT_ANGLE(1.67807435989380), + SCALE_SPLIT_ANGLE(2.05749273300171), + SCALE_SPLIT_ANGLE(2.35138511657715)}, + {SCALE_SPLIT_ANGLE(0.60630625486374), + SCALE_SPLIT_ANGLE(0.65551131963730), + SCALE_SPLIT_ANGLE(0.73032128810883), + SCALE_SPLIT_ANGLE(0.92225730419159), + SCALE_SPLIT_ANGLE(1.11866605281830), + SCALE_SPLIT_ANGLE(1.44806647300720), + SCALE_SPLIT_ANGLE(1.99872636795044), + SCALE_SPLIT_ANGLE(2.47302055358887)}, + {SCALE_SPLIT_ANGLE(0.43393731117249), + SCALE_SPLIT_ANGLE(0.47099208831787), + SCALE_SPLIT_ANGLE(0.52780759334564), + SCALE_SPLIT_ANGLE(0.67895972728729), + SCALE_SPLIT_ANGLE(0.84712409973145), + SCALE_SPLIT_ANGLE(1.17809724807739), + SCALE_SPLIT_ANGLE(1.89703977108002), + SCALE_SPLIT_ANGLE(2.59155654907227)}, + {SCALE_SPLIT_ANGLE(0.33522719144821), + SCALE_SPLIT_ANGLE(0.36133098602295), + SCALE_SPLIT_ANGLE(0.40159517526627), + SCALE_SPLIT_ANGLE(0.51039946079254), + SCALE_SPLIT_ANGLE(0.63590413331985), + SCALE_SPLIT_ANGLE(0.90812796354294), + SCALE_SPLIT_ANGLE(1.70793557167053), + SCALE_SPLIT_ANGLE(2.52852439880371)}, + {SCALE_SPLIT_ANGLE(0.27478924393654), + SCALE_SPLIT_ANGLE(0.29251149296761), + SCALE_SPLIT_ANGLE(0.32007756829262), + SCALE_SPLIT_ANGLE(0.39531299471855), + SCALE_SPLIT_ANGLE(0.48291319608688), + SCALE_SPLIT_ANGLE(0.67812001705170), + SCALE_SPLIT_ANGLE(1.39007341861725), + SCALE_SPLIT_ANGLE(2.34402561187744)}, + {SCALE_SPLIT_ANGLE(0.23185738921165), + SCALE_SPLIT_ANGLE(0.24370795488358), + SCALE_SPLIT_ANGLE(0.26227980852127), + SCALE_SPLIT_ANGLE(0.31327381730080), + SCALE_SPLIT_ANGLE(0.37241828441620), + SCALE_SPLIT_ANGLE(0.50202107429504), + SCALE_SPLIT_ANGLE(0.99085599184036), + SCALE_SPLIT_ANGLE(1.96553468704224)}, + {SCALE_SPLIT_ANGLE(0.19698308408260), + SCALE_SPLIT_ANGLE(0.20488271117210), + SCALE_SPLIT_ANGLE(0.21731524169445), + SCALE_SPLIT_ANGLE(0.25148212909698), + SCALE_SPLIT_ANGLE(0.29065516591072), + SCALE_SPLIT_ANGLE(0.37341466546059), + SCALE_SPLIT_ANGLE(0.65295964479446), + SCALE_SPLIT_ANGLE(1.28865826129913)}, + {SCALE_SPLIT_ANGLE(0.16667704284191), + SCALE_SPLIT_ANGLE(0.17194211483002), + SCALE_SPLIT_ANGLE(0.18023577332497), + SCALE_SPLIT_ANGLE(0.20293866097927), + SCALE_SPLIT_ANGLE(0.22855134308338), + SCALE_SPLIT_ANGLE(0.28041818737984), + SCALE_SPLIT_ANGLE(0.43142420053482), + SCALE_SPLIT_ANGLE(0.70030152797699)}, + {SCALE_SPLIT_ANGLE(0.12773877382278), + SCALE_SPLIT_ANGLE(0.13059370219707), + SCALE_SPLIT_ANGLE(0.13507819175720), + SCALE_SPLIT_ANGLE(0.14721076190472), + SCALE_SPLIT_ANGLE(0.16052412986755), + SCALE_SPLIT_ANGLE(0.18590225279331), + SCALE_SPLIT_ANGLE(0.24703904986382), + SCALE_SPLIT_ANGLE(0.32153329253197)}, + {SCALE_SPLIT_ANGLE(0.09603263437748), + SCALE_SPLIT_ANGLE(0.09756572544575), + SCALE_SPLIT_ANGLE(0.09996145218611), + SCALE_SPLIT_ANGLE(0.10635073482990), + SCALE_SPLIT_ANGLE(0.11317526549101), + SCALE_SPLIT_ANGLE(0.12554961442947), + SCALE_SPLIT_ANGLE(0.15168419480324), + SCALE_SPLIT_ANGLE(0.17713627219200)}, + {SCALE_SPLIT_ANGLE(0.07104731351137), + SCALE_SPLIT_ANGLE(0.07186015695333), + SCALE_SPLIT_ANGLE(0.07312334328890), + SCALE_SPLIT_ANGLE(0.07644616067410), + SCALE_SPLIT_ANGLE(0.07991369813681), + SCALE_SPLIT_ANGLE(0.08596338331699), + SCALE_SPLIT_ANGLE(0.09766443818808), + SCALE_SPLIT_ANGLE(0.10767273604870)}, + {SCALE_SPLIT_ANGLE(0.05192205682397), + SCALE_SPLIT_ANGLE(0.05234766751528), + SCALE_SPLIT_ANGLE(0.05300576984882), + SCALE_SPLIT_ANGLE(0.05471667647362), + SCALE_SPLIT_ANGLE(0.05646898597479), + SCALE_SPLIT_ANGLE(0.05943991243839), + SCALE_SPLIT_ANGLE(0.06485754251480), + SCALE_SPLIT_ANGLE(0.06914159655571)}, + {SCALE_SPLIT_ANGLE(0.03760399296880), + SCALE_SPLIT_ANGLE(0.03782445564866), + SCALE_SPLIT_ANGLE(0.03816393017769), + SCALE_SPLIT_ANGLE(0.03903824463487), + SCALE_SPLIT_ANGLE(0.03992090374231), + SCALE_SPLIT_ANGLE(0.04138650372624), + SCALE_SPLIT_ANGLE(0.04395476728678), + SCALE_SPLIT_ANGLE(0.04588782787323)}, + {SCALE_SPLIT_ANGLE(0.02166714705527), + SCALE_SPLIT_ANGLE(0.02173948101699), + SCALE_SPLIT_ANGLE(0.02185030654073), + SCALE_SPLIT_ANGLE(0.02213260531425), + SCALE_SPLIT_ANGLE(0.02241298183799), + SCALE_SPLIT_ANGLE(0.02286812849343), + SCALE_SPLIT_ANGLE(0.02363408915699), + SCALE_SPLIT_ANGLE(0.02418405190110)}, + {SCALE_SPLIT_ANGLE(0.01235313806683), + SCALE_SPLIT_ANGLE(0.01237650960684), + SCALE_SPLIT_ANGLE(0.01241220813245), + SCALE_SPLIT_ANGLE(0.01250253710896), + SCALE_SPLIT_ANGLE(0.01259138900787), + SCALE_SPLIT_ANGLE(0.01273377332836), + SCALE_SPLIT_ANGLE(0.01296819839627), + SCALE_SPLIT_ANGLE(0.01313247997314)}, + {SCALE_SPLIT_ANGLE(0.00700078532100), + SCALE_SPLIT_ANGLE(0.00700826756656), + SCALE_SPLIT_ANGLE(0.00701967673376), + SCALE_SPLIT_ANGLE(0.00704843224958), + SCALE_SPLIT_ANGLE(0.00707655772567), + SCALE_SPLIT_ANGLE(0.00712130358443), + SCALE_SPLIT_ANGLE(0.00719408970326), + SCALE_SPLIT_ANGLE(0.00724443979561)}, + {SCALE_SPLIT_ANGLE(0.00395406875759), + SCALE_SPLIT_ANGLE(0.00395645201206), + SCALE_SPLIT_ANGLE(0.00396008137614), + SCALE_SPLIT_ANGLE(0.00396920880303), + SCALE_SPLIT_ANGLE(0.00397810759023), + SCALE_SPLIT_ANGLE(0.00399220688269), + SCALE_SPLIT_ANGLE(0.00401498842984), + SCALE_SPLIT_ANGLE(0.00403063697740)}, + {SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068), + SCALE_SPLIT_ANGLE(0.00000002236068)}, + }, + { + {SCALE_SPLIT_ANGLE(2.74889349937439), + SCALE_SPLIT_ANGLE(2.74889349937439), + SCALE_SPLIT_ANGLE(2.74889349937439), + SCALE_SPLIT_ANGLE(2.74889349937439), + SCALE_SPLIT_ANGLE(2.74889349937439), + SCALE_SPLIT_ANGLE(2.74889349937439), + SCALE_SPLIT_ANGLE(2.74889349937439), + SCALE_SPLIT_ANGLE(2.74889349937439)}, + {SCALE_SPLIT_ANGLE(2.74670672416687), + SCALE_SPLIT_ANGLE(2.74670815467834), + SCALE_SPLIT_ANGLE(2.74671053886414), + SCALE_SPLIT_ANGLE(2.74671602249146), + SCALE_SPLIT_ANGLE(2.74672174453735), + SCALE_SPLIT_ANGLE(2.74673032760620), + SCALE_SPLIT_ANGLE(2.74674415588379), + SCALE_SPLIT_ANGLE(2.74675345420837)}, + {SCALE_SPLIT_ANGLE(2.74495577812195), + SCALE_SPLIT_ANGLE(2.74496054649353), + SCALE_SPLIT_ANGLE(2.74496769905090), + SCALE_SPLIT_ANGLE(2.74498581886292), + SCALE_SPLIT_ANGLE(2.74500346183777), + SCALE_SPLIT_ANGLE(2.74503111839294), + SCALE_SPLIT_ANGLE(2.74507498741150), + SCALE_SPLIT_ANGLE(2.74510502815247)}, + {SCALE_SPLIT_ANGLE(2.74173212051392), + SCALE_SPLIT_ANGLE(2.74174761772156), + SCALE_SPLIT_ANGLE(2.74177098274231), + SCALE_SPLIT_ANGLE(2.74182939529419), + SCALE_SPLIT_ANGLE(2.74188613891602), + SCALE_SPLIT_ANGLE(2.74197483062744), + SCALE_SPLIT_ANGLE(2.74211573600769), + SCALE_SPLIT_ANGLE(2.74221110343933)}, + {SCALE_SPLIT_ANGLE(2.73563575744629), + SCALE_SPLIT_ANGLE(2.73568630218506), + SCALE_SPLIT_ANGLE(2.73576331138611), + SCALE_SPLIT_ANGLE(2.73595523834229), + SCALE_SPLIT_ANGLE(2.73614001274109), + SCALE_SPLIT_ANGLE(2.73642849922180), + SCALE_SPLIT_ANGLE(2.73688435554504), + SCALE_SPLIT_ANGLE(2.73719072341919)}, + {SCALE_SPLIT_ANGLE(2.72353148460388), + SCALE_SPLIT_ANGLE(2.72370529174805), + SCALE_SPLIT_ANGLE(2.72396802902222), + SCALE_SPLIT_ANGLE(2.72461819648743), + SCALE_SPLIT_ANGLE(2.72523880004883), + SCALE_SPLIT_ANGLE(2.72619819641113), + SCALE_SPLIT_ANGLE(2.72769498825073), + SCALE_SPLIT_ANGLE(2.72869181632996)}, + {SCALE_SPLIT_ANGLE(2.71044087409973), + SCALE_SPLIT_ANGLE(2.71081781387329), + SCALE_SPLIT_ANGLE(2.71138477325439), + SCALE_SPLIT_ANGLE(2.71277689933777), + SCALE_SPLIT_ANGLE(2.71409153938293), + SCALE_SPLIT_ANGLE(2.71610021591187), + SCALE_SPLIT_ANGLE(2.71919155120850), + SCALE_SPLIT_ANGLE(2.72123122215271)}, + {SCALE_SPLIT_ANGLE(2.68862843513489), + SCALE_SPLIT_ANGLE(2.68948626518250), + SCALE_SPLIT_ANGLE(2.69076681137085), + SCALE_SPLIT_ANGLE(2.69386243820190), + SCALE_SPLIT_ANGLE(2.69673037528992), + SCALE_SPLIT_ANGLE(2.70102667808533), + SCALE_SPLIT_ANGLE(2.70749115943909), + SCALE_SPLIT_ANGLE(2.71170210838318)}, + {SCALE_SPLIT_ANGLE(2.64932370185852), + SCALE_SPLIT_ANGLE(2.65145039558411), + SCALE_SPLIT_ANGLE(2.65457701683044), + SCALE_SPLIT_ANGLE(2.66191530227661), + SCALE_SPLIT_ANGLE(2.66847491264343), + SCALE_SPLIT_ANGLE(2.67795729637146), + SCALE_SPLIT_ANGLE(2.69169545173645), + SCALE_SPLIT_ANGLE(2.70048093795776)}, + {SCALE_SPLIT_ANGLE(2.56864428520203), + SCALE_SPLIT_ANGLE(2.57483482360840), + SCALE_SPLIT_ANGLE(2.58364057540894), + SCALE_SPLIT_ANGLE(2.60311055183411), + SCALE_SPLIT_ANGLE(2.61933612823486), + SCALE_SPLIT_ANGLE(2.64129805564880), + SCALE_SPLIT_ANGLE(2.67107844352722), + SCALE_SPLIT_ANGLE(2.68960857391357)}, + {SCALE_SPLIT_ANGLE(2.35773015022278), + SCALE_SPLIT_ANGLE(2.38251185417175), + SCALE_SPLIT_ANGLE(2.41520094871521), + SCALE_SPLIT_ANGLE(2.47876882553101), + SCALE_SPLIT_ANGLE(2.52468156814575), + SCALE_SPLIT_ANGLE(2.57956743240356), + SCALE_SPLIT_ANGLE(2.64563941955566), + SCALE_SPLIT_ANGLE(2.68501615524292)}, + {SCALE_SPLIT_ANGLE(1.95455360412598), + SCALE_SPLIT_ANGLE(2.03550028800964), + SCALE_SPLIT_ANGLE(2.13431143760681), + SCALE_SPLIT_ANGLE(2.30167627334595), + SCALE_SPLIT_ANGLE(2.40472936630249), + SCALE_SPLIT_ANGLE(2.51241874694824), + SCALE_SPLIT_ANGLE(2.62649774551392), + SCALE_SPLIT_ANGLE(2.69151234626770)}, + {SCALE_SPLIT_ANGLE(1.08639848232269), + SCALE_SPLIT_ANGLE(1.25607907772064), + SCALE_SPLIT_ANGLE(1.49360668659210), + SCALE_SPLIT_ANGLE(1.93062829971313), + SCALE_SPLIT_ANGLE(2.18087863922119), + SCALE_SPLIT_ANGLE(2.40583086013794), + SCALE_SPLIT_ANGLE(2.60574340820313), + SCALE_SPLIT_ANGLE(2.71224212646484)}, + {SCALE_SPLIT_ANGLE(0.46298864483833), + SCALE_SPLIT_ANGLE(0.57069420814514), + SCALE_SPLIT_ANGLE(0.74941867589951), + SCALE_SPLIT_ANGLE(1.27059137821198), + SCALE_SPLIT_ANGLE(1.74987781047821), + SCALE_SPLIT_ANGLE(2.22410750389099), + SCALE_SPLIT_ANGLE(2.58140015602112), + SCALE_SPLIT_ANGLE(2.75301027297974)}, + {SCALE_SPLIT_ANGLE(0.23063218593597), + SCALE_SPLIT_ANGLE(0.29689303040504), + SCALE_SPLIT_ANGLE(0.39820966124535), + SCALE_SPLIT_ANGLE(0.70773023366928), + SCALE_SPLIT_ANGLE(1.13546586036682), + SCALE_SPLIT_ANGLE(1.89722001552582), + SCALE_SPLIT_ANGLE(2.54544758796692), + SCALE_SPLIT_ANGLE(2.81490159034729)}, + {SCALE_SPLIT_ANGLE(0.14590546488762), + SCALE_SPLIT_ANGLE(0.19153353571892), + SCALE_SPLIT_ANGLE(0.25519019365311), + SCALE_SPLIT_ANGLE(0.43163710832596), + SCALE_SPLIT_ANGLE(0.67776858806610), + SCALE_SPLIT_ANGLE(1.37444674968719), + SCALE_SPLIT_ANGLE(2.47591257095337), + SCALE_SPLIT_ANGLE(2.87223863601685)}, + {SCALE_SPLIT_ANGLE(0.12191537022591), + SCALE_SPLIT_ANGLE(0.15053890645504), + SCALE_SPLIT_ANGLE(0.19072309136391), + SCALE_SPLIT_ANGLE(0.29725375771523), + SCALE_SPLIT_ANGLE(0.43550044298172), + SCALE_SPLIT_ANGLE(0.85167354345322), + SCALE_SPLIT_ANGLE(2.31663155555725), + SCALE_SPLIT_ANGLE(2.84442567825317)}, + {SCALE_SPLIT_ANGLE(0.11467454582453), + SCALE_SPLIT_ANGLE(0.13146138191223), + SCALE_SPLIT_ANGLE(0.15621000528336), + SCALE_SPLIT_ANGLE(0.22212918102741), + SCALE_SPLIT_ANGLE(0.30330246686935), + SCALE_SPLIT_ANGLE(0.52478593587875), + SCALE_SPLIT_ANGLE(1.91173267364502), + SCALE_SPLIT_ANGLE(2.75908088684082)}, + {SCALE_SPLIT_ANGLE(0.10720870643854), + SCALE_SPLIT_ANGLE(0.11720535159111), + SCALE_SPLIT_ANGLE(0.13246683776379), + SCALE_SPLIT_ANGLE(0.17369449138641), + SCALE_SPLIT_ANGLE(0.22279064357281), + SCALE_SPLIT_ANGLE(0.34306266903877), + SCALE_SPLIT_ANGLE(1.11311781406403), + SCALE_SPLIT_ANGLE(2.55312228202820)}, + {SCALE_SPLIT_ANGLE(0.09705757349730), + SCALE_SPLIT_ANGLE(0.10320189595222), + SCALE_SPLIT_ANGLE(0.11274837702513), + SCALE_SPLIT_ANGLE(0.13873106241226), + SCALE_SPLIT_ANGLE(0.16888953745365), + SCALE_SPLIT_ANGLE(0.23647473752499), + SCALE_SPLIT_ANGLE(0.53898406028748), + SCALE_SPLIT_ANGLE(1.80699026584625)}, + {SCALE_SPLIT_ANGLE(0.08528346568346), + SCALE_SPLIT_ANGLE(0.08915080130100), + SCALE_SPLIT_ANGLE(0.09520188719034), + SCALE_SPLIT_ANGLE(0.11166745424271), + SCALE_SPLIT_ANGLE(0.13034184277058), + SCALE_SPLIT_ANGLE(0.16932605206966), + SCALE_SPLIT_ANGLE(0.29887470602989), + SCALE_SPLIT_ANGLE(0.63077676296234)}, + {SCALE_SPLIT_ANGLE(0.06733843684196), + SCALE_SPLIT_ANGLE(0.06931617110968), + SCALE_SPLIT_ANGLE(0.07241340726614), + SCALE_SPLIT_ANGLE(0.08076417446136), + SCALE_SPLIT_ANGLE(0.08993341028690), + SCALE_SPLIT_ANGLE(0.10759533941746), + SCALE_SPLIT_ANGLE(0.15204638242722), + SCALE_SPLIT_ANGLE(0.21143139898777)}, + {SCALE_SPLIT_ANGLE(0.05132640898228), + SCALE_SPLIT_ANGLE(0.05234802886844), + SCALE_SPLIT_ANGLE(0.05394187942147), + SCALE_SPLIT_ANGLE(0.05818277224898), + SCALE_SPLIT_ANGLE(0.06270807981491), + SCALE_SPLIT_ANGLE(0.07093632966280), + SCALE_SPLIT_ANGLE(0.08856786042452), + SCALE_SPLIT_ANGLE(0.10623694956303)}, + {SCALE_SPLIT_ANGLE(0.03821930661798), + SCALE_SPLIT_ANGLE(0.03874678537250), + SCALE_SPLIT_ANGLE(0.03956566005945), + SCALE_SPLIT_ANGLE(0.04171610623598), + SCALE_SPLIT_ANGLE(0.04395710676908), + SCALE_SPLIT_ANGLE(0.04786692932248), + SCALE_SPLIT_ANGLE(0.05546034500003), + SCALE_SPLIT_ANGLE(0.06201593577862)}, + {SCALE_SPLIT_ANGLE(0.02801758050919), + SCALE_SPLIT_ANGLE(0.02828873321414), + SCALE_SPLIT_ANGLE(0.02870770171285), + SCALE_SPLIT_ANGLE(0.02979558333755), + SCALE_SPLIT_ANGLE(0.03090834617615), + SCALE_SPLIT_ANGLE(0.03279331326485), + SCALE_SPLIT_ANGLE(0.03623208031058), + SCALE_SPLIT_ANGLE(0.03895835205913)}, + {SCALE_SPLIT_ANGLE(0.02032180689275), + SCALE_SPLIT_ANGLE(0.02046046219766), + SCALE_SPLIT_ANGLE(0.02067386545241), + SCALE_SPLIT_ANGLE(0.02122297696769), + SCALE_SPLIT_ANGLE(0.02177673391998), + SCALE_SPLIT_ANGLE(0.02269527874887), + SCALE_SPLIT_ANGLE(0.02430364489555), + SCALE_SPLIT_ANGLE(0.02551441825926)}, + {SCALE_SPLIT_ANGLE(0.01172095164657), + SCALE_SPLIT_ANGLE(0.01176583208144), + SCALE_SPLIT_ANGLE(0.01183457672596), + SCALE_SPLIT_ANGLE(0.01200959738344), + SCALE_SPLIT_ANGLE(0.01218330394477), + SCALE_SPLIT_ANGLE(0.01246506255120), + SCALE_SPLIT_ANGLE(0.01293875463307), + SCALE_SPLIT_ANGLE(0.01327861472964)}, + {SCALE_SPLIT_ANGLE(0.00668454170227), + SCALE_SPLIT_ANGLE(0.00669893343002), + SCALE_SPLIT_ANGLE(0.00672091403976), + SCALE_SPLIT_ANGLE(0.00677651492879), + SCALE_SPLIT_ANGLE(0.00683118170127), + SCALE_SPLIT_ANGLE(0.00691874232143), + SCALE_SPLIT_ANGLE(0.00706279883161), + SCALE_SPLIT_ANGLE(0.00716368528083)}, + {SCALE_SPLIT_ANGLE(0.00378863257356), + SCALE_SPLIT_ANGLE(0.00379322143272), + SCALE_SPLIT_ANGLE(0.00380021659657), + SCALE_SPLIT_ANGLE(0.00381784536876), + SCALE_SPLIT_ANGLE(0.00383508414961), + SCALE_SPLIT_ANGLE(0.00386250065640), + SCALE_SPLIT_ANGLE(0.00390707794577), + SCALE_SPLIT_ANGLE(0.00393790053204)}, + {SCALE_SPLIT_ANGLE(0.00213989755139), + SCALE_SPLIT_ANGLE(0.00214135553688), + SCALE_SPLIT_ANGLE(0.00214357557707), + SCALE_SPLIT_ANGLE(0.00214915862307), + SCALE_SPLIT_ANGLE(0.00215460127220), + SCALE_SPLIT_ANGLE(0.00216322275810), + SCALE_SPLIT_ANGLE(0.00217714952305), + SCALE_SPLIT_ANGLE(0.00218671280891)}, + {SCALE_SPLIT_ANGLE(0.00000001210151), + SCALE_SPLIT_ANGLE(0.00000001210151), + SCALE_SPLIT_ANGLE(0.00000001210151), + SCALE_SPLIT_ANGLE(0.00000001210152), + SCALE_SPLIT_ANGLE(0.00000001210152), + SCALE_SPLIT_ANGLE(0.00000001210152), + SCALE_SPLIT_ANGLE(0.00000001210152), + SCALE_SPLIT_ANGLE(0.00000001210152)}, + }, + { + {SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-3.14159226417542), + SCALE_SPLIT_ANGLE(-3.14159226417542), + SCALE_SPLIT_ANGLE(-3.14159226417542), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-0.00000036774148), + SCALE_SPLIT_ANGLE(-0.00000066993488), + SCALE_SPLIT_ANGLE(-0.00001151842844), + SCALE_SPLIT_ANGLE(-3.14159226417542), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-0.00000008554968), + SCALE_SPLIT_ANGLE(-0.00000012210570), + SCALE_SPLIT_ANGLE(-0.00000019699247), + SCALE_SPLIT_ANGLE(-0.00000110842382), + SCALE_SPLIT_ANGLE(-3.14159202575684), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-0.00000003016602), + SCALE_SPLIT_ANGLE(-0.00000005321843), + SCALE_SPLIT_ANGLE(-0.00000008440014), + SCALE_SPLIT_ANGLE(-0.00000020468090), + SCALE_SPLIT_ANGLE(-0.00000071846705), + SCALE_SPLIT_ANGLE(-3.14159226417542), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-0.00000000024720), + SCALE_SPLIT_ANGLE(-0.00000003226497), + SCALE_SPLIT_ANGLE(-0.00000005171609), + SCALE_SPLIT_ANGLE(-0.00000010526998), + SCALE_SPLIT_ANGLE(-0.00000020551137), + SCALE_SPLIT_ANGLE(-1.57079637050629), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-0.00000001688349), + SCALE_SPLIT_ANGLE(-0.00000002741881), + SCALE_SPLIT_ANGLE(-0.00000003926384), + SCALE_SPLIT_ANGLE(-0.00000006928260), + SCALE_SPLIT_ANGLE(-0.00000011240582), + SCALE_SPLIT_ANGLE(-0.00000033763689), + SCALE_SPLIT_ANGLE(-3.14159250259399), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-0.00000002143362), + SCALE_SPLIT_ANGLE(-0.00000002640935), + SCALE_SPLIT_ANGLE(-0.00000003328325), + SCALE_SPLIT_ANGLE(-0.00000005112437), + SCALE_SPLIT_ANGLE(-0.00000007399619), + SCALE_SPLIT_ANGLE(-0.00000014946792), + SCALE_SPLIT_ANGLE(-3.14159226417542), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-0.00000002225921), + SCALE_SPLIT_ANGLE(-0.00000002497380), + SCALE_SPLIT_ANGLE(-0.00000002903169), + SCALE_SPLIT_ANGLE(-0.00000003987020), + SCALE_SPLIT_ANGLE(-0.00000005300816), + SCALE_SPLIT_ANGLE(-0.00000008783893), + SCALE_SPLIT_ANGLE(-0.00000093762065), + SCALE_SPLIT_ANGLE(-3.14159250259399)}, + {SCALE_SPLIT_ANGLE(-0.00000002109218), + SCALE_SPLIT_ANGLE(-0.00000002269230), + SCALE_SPLIT_ANGLE(-0.00000002515904), + SCALE_SPLIT_ANGLE(-0.00000003183984), + SCALE_SPLIT_ANGLE(-0.00000003965878), + SCALE_SPLIT_ANGLE(-0.00000005782364), + SCALE_SPLIT_ANGLE(-0.00000016152633), + SCALE_SPLIT_ANGLE(-3.14159226417542)}, + {SCALE_SPLIT_ANGLE(-0.00000001895314), + SCALE_SPLIT_ANGLE(-0.00000001993623), + SCALE_SPLIT_ANGLE(-0.00000002146927), + SCALE_SPLIT_ANGLE(-0.00000002563087), + SCALE_SPLIT_ANGLE(-0.00000003036888), + SCALE_SPLIT_ANGLE(-0.00000004043087), + SCALE_SPLIT_ANGLE(-0.00000007667983), + SCALE_SPLIT_ANGLE(-0.00000021028936)}, + {SCALE_SPLIT_ANGLE(-0.00000001519980), + SCALE_SPLIT_ANGLE(-0.00000001569144), + SCALE_SPLIT_ANGLE(-0.00000001646043), + SCALE_SPLIT_ANGLE(-0.00000001853141), + SCALE_SPLIT_ANGLE(-0.00000002080756), + SCALE_SPLIT_ANGLE(-0.00000002521688), + SCALE_SPLIT_ANGLE(-0.00000003656274), + SCALE_SPLIT_ANGLE(-0.00000005247700)}, + {SCALE_SPLIT_ANGLE(-0.00000001166148), + SCALE_SPLIT_ANGLE(-0.00000001191188), + SCALE_SPLIT_ANGLE(-0.00000001230229), + SCALE_SPLIT_ANGLE(-0.00000001334031), + SCALE_SPLIT_ANGLE(-0.00000001444787), + SCALE_SPLIT_ANGLE(-0.00000001646512), + SCALE_SPLIT_ANGLE(-0.00000002081803), + SCALE_SPLIT_ANGLE(-0.00000002523831)}, + {SCALE_SPLIT_ANGLE(-0.00000000870876), + SCALE_SPLIT_ANGLE(-0.00000000883681), + SCALE_SPLIT_ANGLE(-0.00000000903554), + SCALE_SPLIT_ANGLE(-0.00000000955712), + SCALE_SPLIT_ANGLE(-0.00000001010047), + SCALE_SPLIT_ANGLE(-0.00000001104868), + SCALE_SPLIT_ANGLE(-0.00000001289412), + SCALE_SPLIT_ANGLE(-0.00000001449405)}, + {SCALE_SPLIT_ANGLE(-0.00000000639270), + SCALE_SPLIT_ANGLE(-0.00000000645810), + SCALE_SPLIT_ANGLE(-0.00000000655912), + SCALE_SPLIT_ANGLE(-0.00000000682132), + SCALE_SPLIT_ANGLE(-0.00000000708940), + SCALE_SPLIT_ANGLE(-0.00000000754343), + SCALE_SPLIT_ANGLE(-0.00000000837207), + SCALE_SPLIT_ANGLE(-0.00000000902983)}, + {SCALE_SPLIT_ANGLE(-0.00000000463970), + SCALE_SPLIT_ANGLE(-0.00000000467299), + SCALE_SPLIT_ANGLE(-0.00000000472421), + SCALE_SPLIT_ANGLE(-0.00000000485598), + SCALE_SPLIT_ANGLE(-0.00000000498881), + SCALE_SPLIT_ANGLE(-0.00000000520907), + SCALE_SPLIT_ANGLE(-0.00000000559469), + SCALE_SPLIT_ANGLE(-0.00000000588504)}, + {SCALE_SPLIT_ANGLE(-0.00000000267713), + SCALE_SPLIT_ANGLE(-0.00000000268785), + SCALE_SPLIT_ANGLE(-0.00000000270428), + SCALE_SPLIT_ANGLE(-0.00000000274608), + SCALE_SPLIT_ANGLE(-0.00000000278756), + SCALE_SPLIT_ANGLE(-0.00000000285483), + SCALE_SPLIT_ANGLE(-0.00000000296788), + SCALE_SPLIT_ANGLE(-0.00000000304897)}, + {SCALE_SPLIT_ANGLE(-0.00000000152698), + SCALE_SPLIT_ANGLE(-0.00000000153041), + SCALE_SPLIT_ANGLE(-0.00000000153564), + SCALE_SPLIT_ANGLE(-0.00000000154889), + SCALE_SPLIT_ANGLE(-0.00000000156191), + SCALE_SPLIT_ANGLE(-0.00000000158277), + SCALE_SPLIT_ANGLE(-0.00000000161707), + SCALE_SPLIT_ANGLE(-0.00000000164109)}, + {SCALE_SPLIT_ANGLE(-0.00000000086549), + SCALE_SPLIT_ANGLE(-0.00000000086658), + SCALE_SPLIT_ANGLE(-0.00000000086824), + SCALE_SPLIT_ANGLE(-0.00000000087244), + SCALE_SPLIT_ANGLE(-0.00000000087654), + SCALE_SPLIT_ANGLE(-0.00000000088306), + SCALE_SPLIT_ANGLE(-0.00000000089366), + SCALE_SPLIT_ANGLE(-0.00000000090099)}, + {SCALE_SPLIT_ANGLE(-0.00000000048885), + SCALE_SPLIT_ANGLE(-0.00000000048920), + SCALE_SPLIT_ANGLE(-0.00000000048972), + SCALE_SPLIT_ANGLE(-0.00000000049105), + SCALE_SPLIT_ANGLE(-0.00000000049235), + SCALE_SPLIT_ANGLE(-0.00000000049439), + SCALE_SPLIT_ANGLE(-0.00000000049770), + SCALE_SPLIT_ANGLE(-0.00000000049998)}, + {SCALE_SPLIT_ANGLE(-0.00000000000000), + SCALE_SPLIT_ANGLE(-0.00000000000000), + SCALE_SPLIT_ANGLE(-0.00000000000000), + SCALE_SPLIT_ANGLE(-0.00000000000000), + SCALE_SPLIT_ANGLE(-0.00000000000000), + SCALE_SPLIT_ANGLE(-0.00000000000000), + SCALE_SPLIT_ANGLE(-0.00000000000000), + SCALE_SPLIT_ANGLE(-0.00000000000000)}, + }, + { + {SCALE_SPLIT_ANGLE(-2.74889349937439), + SCALE_SPLIT_ANGLE(-2.74889349937439), + SCALE_SPLIT_ANGLE(-2.74889349937439), + SCALE_SPLIT_ANGLE(-2.74889349937439), + SCALE_SPLIT_ANGLE(-2.74889349937439), + SCALE_SPLIT_ANGLE(-2.74889349937439), + SCALE_SPLIT_ANGLE(-2.74889349937439), + SCALE_SPLIT_ANGLE(-2.74889349937439)}, + {SCALE_SPLIT_ANGLE(-2.74670672416687), + SCALE_SPLIT_ANGLE(-2.74670815467834), + SCALE_SPLIT_ANGLE(-2.74671053886414), + SCALE_SPLIT_ANGLE(-2.74671626091003), + SCALE_SPLIT_ANGLE(-2.74672174453735), + SCALE_SPLIT_ANGLE(-2.74673032760620), + SCALE_SPLIT_ANGLE(-2.74674415588379), + SCALE_SPLIT_ANGLE(-2.74675369262695)}, + {SCALE_SPLIT_ANGLE(-2.74495577812195), + SCALE_SPLIT_ANGLE(-2.74496054649353), + SCALE_SPLIT_ANGLE(-2.74496769905090), + SCALE_SPLIT_ANGLE(-2.74498581886292), + SCALE_SPLIT_ANGLE(-2.74500346183777), + SCALE_SPLIT_ANGLE(-2.74503111839294), + SCALE_SPLIT_ANGLE(-2.74507522583008), + SCALE_SPLIT_ANGLE(-2.74510502815247)}, + {SCALE_SPLIT_ANGLE(-2.74173235893250), + SCALE_SPLIT_ANGLE(-2.74174761772156), + SCALE_SPLIT_ANGLE(-2.74177098274231), + SCALE_SPLIT_ANGLE(-2.74182963371277), + SCALE_SPLIT_ANGLE(-2.74188613891602), + SCALE_SPLIT_ANGLE(-2.74197483062744), + SCALE_SPLIT_ANGLE(-2.74211597442627), + SCALE_SPLIT_ANGLE(-2.74221134185791)}, + {SCALE_SPLIT_ANGLE(-2.73563575744629), + SCALE_SPLIT_ANGLE(-2.73568654060364), + SCALE_SPLIT_ANGLE(-2.73576331138611), + SCALE_SPLIT_ANGLE(-2.73595523834229), + SCALE_SPLIT_ANGLE(-2.73614001274109), + SCALE_SPLIT_ANGLE(-2.73642849922180), + SCALE_SPLIT_ANGLE(-2.73688435554504), + SCALE_SPLIT_ANGLE(-2.73719096183777)}, + {SCALE_SPLIT_ANGLE(-2.72353172302246), + SCALE_SPLIT_ANGLE(-2.72370529174805), + SCALE_SPLIT_ANGLE(-2.72396802902222), + SCALE_SPLIT_ANGLE(-2.72461819648743), + SCALE_SPLIT_ANGLE(-2.72523903846741), + SCALE_SPLIT_ANGLE(-2.72619819641113), + SCALE_SPLIT_ANGLE(-2.72769522666931), + SCALE_SPLIT_ANGLE(-2.72869181632996)}, + {SCALE_SPLIT_ANGLE(-2.71044111251831), + SCALE_SPLIT_ANGLE(-2.71081781387329), + SCALE_SPLIT_ANGLE(-2.71138477325439), + SCALE_SPLIT_ANGLE(-2.71277689933777), + SCALE_SPLIT_ANGLE(-2.71409153938293), + SCALE_SPLIT_ANGLE(-2.71610021591187), + SCALE_SPLIT_ANGLE(-2.71919155120850), + SCALE_SPLIT_ANGLE(-2.72123122215271)}, + {SCALE_SPLIT_ANGLE(-2.68862843513489), + SCALE_SPLIT_ANGLE(-2.68948626518250), + SCALE_SPLIT_ANGLE(-2.69076681137085), + SCALE_SPLIT_ANGLE(-2.69386243820190), + SCALE_SPLIT_ANGLE(-2.69673061370850), + SCALE_SPLIT_ANGLE(-2.70102667808533), + SCALE_SPLIT_ANGLE(-2.70749115943909), + SCALE_SPLIT_ANGLE(-2.71170234680176)}, + {SCALE_SPLIT_ANGLE(-2.64932370185852), + SCALE_SPLIT_ANGLE(-2.65145063400269), + SCALE_SPLIT_ANGLE(-2.65457701683044), + SCALE_SPLIT_ANGLE(-2.66191530227661), + SCALE_SPLIT_ANGLE(-2.66847491264343), + SCALE_SPLIT_ANGLE(-2.67795729637146), + SCALE_SPLIT_ANGLE(-2.69169569015503), + SCALE_SPLIT_ANGLE(-2.70048117637634)}, + {SCALE_SPLIT_ANGLE(-2.56864428520203), + SCALE_SPLIT_ANGLE(-2.57483482360840), + SCALE_SPLIT_ANGLE(-2.58364057540894), + SCALE_SPLIT_ANGLE(-2.60311055183411), + SCALE_SPLIT_ANGLE(-2.61933612823486), + SCALE_SPLIT_ANGLE(-2.64129829406738), + SCALE_SPLIT_ANGLE(-2.67107868194580), + SCALE_SPLIT_ANGLE(-2.68960881233215)}, + {SCALE_SPLIT_ANGLE(-2.35773015022278), + SCALE_SPLIT_ANGLE(-2.38251185417175), + SCALE_SPLIT_ANGLE(-2.41520094871521), + SCALE_SPLIT_ANGLE(-2.47876906394959), + SCALE_SPLIT_ANGLE(-2.52468156814575), + SCALE_SPLIT_ANGLE(-2.57956743240356), + SCALE_SPLIT_ANGLE(-2.64563965797424), + SCALE_SPLIT_ANGLE(-2.68501615524292)}, + {SCALE_SPLIT_ANGLE(-1.95455360412598), + SCALE_SPLIT_ANGLE(-2.03550028800964), + SCALE_SPLIT_ANGLE(-2.13431143760681), + SCALE_SPLIT_ANGLE(-2.30167627334595), + SCALE_SPLIT_ANGLE(-2.40472936630249), + SCALE_SPLIT_ANGLE(-2.51241874694824), + SCALE_SPLIT_ANGLE(-2.62649774551392), + SCALE_SPLIT_ANGLE(-2.69151234626770)}, + {SCALE_SPLIT_ANGLE(-1.08639836311340), + SCALE_SPLIT_ANGLE(-1.25607907772064), + SCALE_SPLIT_ANGLE(-1.49360668659210), + SCALE_SPLIT_ANGLE(-1.93062829971313), + SCALE_SPLIT_ANGLE(-2.18087887763977), + SCALE_SPLIT_ANGLE(-2.40583086013794), + SCALE_SPLIT_ANGLE(-2.60574340820313), + SCALE_SPLIT_ANGLE(-2.71224212646484)}, + {SCALE_SPLIT_ANGLE(-0.46298858523369), + SCALE_SPLIT_ANGLE(-0.57069414854050), + SCALE_SPLIT_ANGLE(-0.74941855669022), + SCALE_SPLIT_ANGLE(-1.27059125900269), + SCALE_SPLIT_ANGLE(-1.74987781047821), + SCALE_SPLIT_ANGLE(-2.22410750389099), + SCALE_SPLIT_ANGLE(-2.58140015602112), + SCALE_SPLIT_ANGLE(-2.75301027297974)}, + {SCALE_SPLIT_ANGLE(-0.23063215613365), + SCALE_SPLIT_ANGLE(-0.29689297080040), + SCALE_SPLIT_ANGLE(-0.39820960164070), + SCALE_SPLIT_ANGLE(-0.70773017406464), + SCALE_SPLIT_ANGLE(-1.13546574115753), + SCALE_SPLIT_ANGLE(-1.89722001552582), + SCALE_SPLIT_ANGLE(-2.54544782638550), + SCALE_SPLIT_ANGLE(-2.81490182876587)}, + {SCALE_SPLIT_ANGLE(-0.14590544998646), + SCALE_SPLIT_ANGLE(-0.19153350591660), + SCALE_SPLIT_ANGLE(-0.25519016385078), + SCALE_SPLIT_ANGLE(-0.43163704872131), + SCALE_SPLIT_ANGLE(-0.67776852846146), + SCALE_SPLIT_ANGLE(-1.37444674968719), + SCALE_SPLIT_ANGLE(-2.47591280937195), + SCALE_SPLIT_ANGLE(-2.87223863601685)}, + {SCALE_SPLIT_ANGLE(-0.12191534787416), + SCALE_SPLIT_ANGLE(-0.15053887665272), + SCALE_SPLIT_ANGLE(-0.19072306156158), + SCALE_SPLIT_ANGLE(-0.29725372791290), + SCALE_SPLIT_ANGLE(-0.43550038337708), + SCALE_SPLIT_ANGLE(-0.85167348384857), + SCALE_SPLIT_ANGLE(-2.31663155555725), + SCALE_SPLIT_ANGLE(-2.84442567825317)}, + {SCALE_SPLIT_ANGLE(-0.11467452347279), + SCALE_SPLIT_ANGLE(-0.13146135210991), + SCALE_SPLIT_ANGLE(-0.15620997548103), + SCALE_SPLIT_ANGLE(-0.22212913632393), + SCALE_SPLIT_ANGLE(-0.30330240726471), + SCALE_SPLIT_ANGLE(-0.52478587627411), + SCALE_SPLIT_ANGLE(-1.91173267364502), + SCALE_SPLIT_ANGLE(-2.75908088684082)}, + {SCALE_SPLIT_ANGLE(-0.10720869153738), + SCALE_SPLIT_ANGLE(-0.11720532923937), + SCALE_SPLIT_ANGLE(-0.13246680796146), + SCALE_SPLIT_ANGLE(-0.17369446158409), + SCALE_SPLIT_ANGLE(-0.22279061377048), + SCALE_SPLIT_ANGLE(-0.34306260943413), + SCALE_SPLIT_ANGLE(-1.11311769485474), + SCALE_SPLIT_ANGLE(-2.55312228202820)}, + {SCALE_SPLIT_ANGLE(-0.09705755859613), + SCALE_SPLIT_ANGLE(-0.10320188105106), + SCALE_SPLIT_ANGLE(-0.11274836212397), + SCALE_SPLIT_ANGLE(-0.13873104751110), + SCALE_SPLIT_ANGLE(-0.16888950765133), + SCALE_SPLIT_ANGLE(-0.23647469282150), + SCALE_SPLIT_ANGLE(-0.53898400068283), + SCALE_SPLIT_ANGLE(-1.80699026584625)}, + {SCALE_SPLIT_ANGLE(-0.08528345078230), + SCALE_SPLIT_ANGLE(-0.08915078639984), + SCALE_SPLIT_ANGLE(-0.09520187228918), + SCALE_SPLIT_ANGLE(-0.11166743934155), + SCALE_SPLIT_ANGLE(-0.13034182786942), + SCALE_SPLIT_ANGLE(-0.16932602226734), + SCALE_SPLIT_ANGLE(-0.29887464642525), + SCALE_SPLIT_ANGLE(-0.63077670335770)}, + {SCALE_SPLIT_ANGLE(-0.06733842939138), + SCALE_SPLIT_ANGLE(-0.06931615620852), + SCALE_SPLIT_ANGLE(-0.07241339236498), + SCALE_SPLIT_ANGLE(-0.08076415956020), + SCALE_SPLIT_ANGLE(-0.08993339538574), + SCALE_SPLIT_ANGLE(-0.10759532451630), + SCALE_SPLIT_ANGLE(-0.15204635262489), + SCALE_SPLIT_ANGLE(-0.21143136918545)}, + {SCALE_SPLIT_ANGLE(-0.05132640153170), + SCALE_SPLIT_ANGLE(-0.05234802141786), + SCALE_SPLIT_ANGLE(-0.05394186824560), + SCALE_SPLIT_ANGLE(-0.05818276479840), + SCALE_SPLIT_ANGLE(-0.06270807236433), + SCALE_SPLIT_ANGLE(-0.07093632221222), + SCALE_SPLIT_ANGLE(-0.08856784552336), + SCALE_SPLIT_ANGLE(-0.10623692721128)}, + {SCALE_SPLIT_ANGLE(-0.03821930289268), + SCALE_SPLIT_ANGLE(-0.03874678164721), + SCALE_SPLIT_ANGLE(-0.03956565260887), + SCALE_SPLIT_ANGLE(-0.04171609878540), + SCALE_SPLIT_ANGLE(-0.04395709931850), + SCALE_SPLIT_ANGLE(-0.04786692187190), + SCALE_SPLIT_ANGLE(-0.05546033382416), + SCALE_SPLIT_ANGLE(-0.06201592460275)}, + {SCALE_SPLIT_ANGLE(-0.02801757678390), + SCALE_SPLIT_ANGLE(-0.02828872948885), + SCALE_SPLIT_ANGLE(-0.02870769798756), + SCALE_SPLIT_ANGLE(-0.02979557774961), + SCALE_SPLIT_ANGLE(-0.03090834245086), + SCALE_SPLIT_ANGLE(-0.03279330953956), + SCALE_SPLIT_ANGLE(-0.03623207286000), + SCALE_SPLIT_ANGLE(-0.03895834833384)}, + {SCALE_SPLIT_ANGLE(-0.02032180316746), + SCALE_SPLIT_ANGLE(-0.02046045847237), + SCALE_SPLIT_ANGLE(-0.02067386172712), + SCALE_SPLIT_ANGLE(-0.02122297324240), + SCALE_SPLIT_ANGLE(-0.02177673205733), + SCALE_SPLIT_ANGLE(-0.02269527502358), + SCALE_SPLIT_ANGLE(-0.02430364117026), + SCALE_SPLIT_ANGLE(-0.02551441267133)}, + {SCALE_SPLIT_ANGLE(-0.01172094978392), + SCALE_SPLIT_ANGLE(-0.01176583021879), + SCALE_SPLIT_ANGLE(-0.01183457486331), + SCALE_SPLIT_ANGLE(-0.01200959552079), + SCALE_SPLIT_ANGLE(-0.01218330208212), + SCALE_SPLIT_ANGLE(-0.01246506068856), + SCALE_SPLIT_ANGLE(-0.01293875277042), + SCALE_SPLIT_ANGLE(-0.01327861286700)}, + {SCALE_SPLIT_ANGLE(-0.00668454030529), + SCALE_SPLIT_ANGLE(-0.00669893249869), + SCALE_SPLIT_ANGLE(-0.00672091310844), + SCALE_SPLIT_ANGLE(-0.00677651399747), + SCALE_SPLIT_ANGLE(-0.00683118030429), + SCALE_SPLIT_ANGLE(-0.00691874139011), + SCALE_SPLIT_ANGLE(-0.00706279790029), + SCALE_SPLIT_ANGLE(-0.00716368434951)}, + {SCALE_SPLIT_ANGLE(-0.00378863210790), + SCALE_SPLIT_ANGLE(-0.00379322096705), + SCALE_SPLIT_ANGLE(-0.00380021613091), + SCALE_SPLIT_ANGLE(-0.00381784490310), + SCALE_SPLIT_ANGLE(-0.00383508345112), + SCALE_SPLIT_ANGLE(-0.00386250019073), + SCALE_SPLIT_ANGLE(-0.00390707701445), + SCALE_SPLIT_ANGLE(-0.00393790006638)}, + {SCALE_SPLIT_ANGLE(-0.00213989731856), + SCALE_SPLIT_ANGLE(-0.00214135507122), + SCALE_SPLIT_ANGLE(-0.00214357534423), + SCALE_SPLIT_ANGLE(-0.00214915839024), + SCALE_SPLIT_ANGLE(-0.00215460080653), + SCALE_SPLIT_ANGLE(-0.00216322229244), + SCALE_SPLIT_ANGLE(-0.00217714929022), + SCALE_SPLIT_ANGLE(-0.00218671257608)}, + {SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151)}, + }, + { + {SCALE_SPLIT_ANGLE(-2.35619449615479), + SCALE_SPLIT_ANGLE(-2.35619449615479), + SCALE_SPLIT_ANGLE(-2.35619449615479), + SCALE_SPLIT_ANGLE(-2.35619449615479), + SCALE_SPLIT_ANGLE(-2.35619449615479), + SCALE_SPLIT_ANGLE(-2.35619449615479), + SCALE_SPLIT_ANGLE(-2.35619449615479), + SCALE_SPLIT_ANGLE(-2.35619449615479)}, + {SCALE_SPLIT_ANGLE(-2.35216379165649), + SCALE_SPLIT_ANGLE(-2.35216617584229), + SCALE_SPLIT_ANGLE(-2.35216999053955), + SCALE_SPLIT_ANGLE(-2.35217928886414), + SCALE_SPLIT_ANGLE(-2.35218811035156), + SCALE_SPLIT_ANGLE(-2.35220241546631), + SCALE_SPLIT_ANGLE(-2.35222506523132), + SCALE_SPLIT_ANGLE(-2.35224032402039)}, + {SCALE_SPLIT_ANGLE(-2.34895062446594), + SCALE_SPLIT_ANGLE(-2.34895849227905), + SCALE_SPLIT_ANGLE(-2.34897017478943), + SCALE_SPLIT_ANGLE(-2.34899973869324), + SCALE_SPLIT_ANGLE(-2.34902834892273), + SCALE_SPLIT_ANGLE(-2.34907317161560), + SCALE_SPLIT_ANGLE(-2.34914541244507), + SCALE_SPLIT_ANGLE(-2.34919428825378)}, + {SCALE_SPLIT_ANGLE(-2.34306836128235), + SCALE_SPLIT_ANGLE(-2.34309315681458), + SCALE_SPLIT_ANGLE(-2.34313082695007), + SCALE_SPLIT_ANGLE(-2.34322524070740), + SCALE_SPLIT_ANGLE(-2.34331679344177), + SCALE_SPLIT_ANGLE(-2.34346079826355), + SCALE_SPLIT_ANGLE(-2.34369087219238), + SCALE_SPLIT_ANGLE(-2.34384727478027)}, + {SCALE_SPLIT_ANGLE(-2.33205747604370), + SCALE_SPLIT_ANGLE(-2.33213782310486), + SCALE_SPLIT_ANGLE(-2.33226013183594), + SCALE_SPLIT_ANGLE(-2.33256602287292), + SCALE_SPLIT_ANGLE(-2.33286190032959), + SCALE_SPLIT_ANGLE(-2.33332633972168), + SCALE_SPLIT_ANGLE(-2.33406710624695), + SCALE_SPLIT_ANGLE(-2.33456921577454)}, + {SCALE_SPLIT_ANGLE(-2.31062936782837), + SCALE_SPLIT_ANGLE(-2.31089687347412), + SCALE_SPLIT_ANGLE(-2.31130218505859), + SCALE_SPLIT_ANGLE(-2.31231284141541), + SCALE_SPLIT_ANGLE(-2.31328654289246), + SCALE_SPLIT_ANGLE(-2.31480813026428), + SCALE_SPLIT_ANGLE(-2.31722092628479), + SCALE_SPLIT_ANGLE(-2.31885290145874)}, + {SCALE_SPLIT_ANGLE(-2.28808355331421), + SCALE_SPLIT_ANGLE(-2.28864479064941), + SCALE_SPLIT_ANGLE(-2.28949403762817), + SCALE_SPLIT_ANGLE(-2.29160070419312), + SCALE_SPLIT_ANGLE(-2.29361891746521), + SCALE_SPLIT_ANGLE(-2.29675459861755), + SCALE_SPLIT_ANGLE(-2.30169844627380), + SCALE_SPLIT_ANGLE(-2.30503511428833)}, + {SCALE_SPLIT_ANGLE(-2.25191521644592), + SCALE_SPLIT_ANGLE(-2.25312590599060), + SCALE_SPLIT_ANGLE(-2.25494933128357), + SCALE_SPLIT_ANGLE(-2.25943517684937), + SCALE_SPLIT_ANGLE(-2.26368904113770), + SCALE_SPLIT_ANGLE(-2.27023124694824), + SCALE_SPLIT_ANGLE(-2.28044486045837), + SCALE_SPLIT_ANGLE(-2.28732323646545)}, + {SCALE_SPLIT_ANGLE(-2.19093608856201), + SCALE_SPLIT_ANGLE(-2.19366121292114), + SCALE_SPLIT_ANGLE(-2.19773292541504), + SCALE_SPLIT_ANGLE(-2.20759749412537), + SCALE_SPLIT_ANGLE(-2.21677803993225), + SCALE_SPLIT_ANGLE(-2.23064494132996), + SCALE_SPLIT_ANGLE(-2.25193929672241), + SCALE_SPLIT_ANGLE(-2.26625943183899)}, + {SCALE_SPLIT_ANGLE(-2.08102917671204), + SCALE_SPLIT_ANGLE(-2.08757305145264), + SCALE_SPLIT_ANGLE(-2.09720730781555), + SCALE_SPLIT_ANGLE(-2.11991167068481), + SCALE_SPLIT_ANGLE(-2.14035677909851), + SCALE_SPLIT_ANGLE(-2.17029237747192), + SCALE_SPLIT_ANGLE(-2.21503162384033), + SCALE_SPLIT_ANGLE(-2.24518132209778)}, + {SCALE_SPLIT_ANGLE(-1.86738622188568), + SCALE_SPLIT_ANGLE(-1.88426077365875), + SCALE_SPLIT_ANGLE(-1.90853285789490), + SCALE_SPLIT_ANGLE(-1.96333336830139), + SCALE_SPLIT_ANGLE(-2.01024460792542), + SCALE_SPLIT_ANGLE(-2.07577633857727), + SCALE_SPLIT_ANGLE(-2.16986608505249), + SCALE_SPLIT_ANGLE(-2.23406052589417)}, + {SCALE_SPLIT_ANGLE(-1.61812186241150), + SCALE_SPLIT_ANGLE(-1.64943766593933), + SCALE_SPLIT_ANGLE(-1.69389247894287), + SCALE_SPLIT_ANGLE(-1.79176032543182), + SCALE_SPLIT_ANGLE(-1.87292504310608), + SCALE_SPLIT_ANGLE(-1.98277997970581), + SCALE_SPLIT_ANGLE(-2.13605833053589), + SCALE_SPLIT_ANGLE(-2.24282979965210)}, + {SCALE_SPLIT_ANGLE(-1.26556181907654), + SCALE_SPLIT_ANGLE(-1.31512010097504), + SCALE_SPLIT_ANGLE(-1.38608694076538), + SCALE_SPLIT_ANGLE(-1.54419946670532), + SCALE_SPLIT_ANGLE(-1.67621028423309), + SCALE_SPLIT_ANGLE(-1.85417354106903), + SCALE_SPLIT_ANGLE(-2.09956336021423), + SCALE_SPLIT_ANGLE(-2.27729439735413)}, + {SCALE_SPLIT_ANGLE(-0.88984858989716), + SCALE_SPLIT_ANGLE(-0.94673115015030), + SCALE_SPLIT_ANGLE(-1.03102219104767), + SCALE_SPLIT_ANGLE(-1.23219704627991), + SCALE_SPLIT_ANGLE(-1.41468596458435), + SCALE_SPLIT_ANGLE(-1.67807447910309), + SCALE_SPLIT_ANGLE(-2.05749273300171), + SCALE_SPLIT_ANGLE(-2.35138511657715)}, + {SCALE_SPLIT_ANGLE(-0.60630625486374), + SCALE_SPLIT_ANGLE(-0.65551131963730), + SCALE_SPLIT_ANGLE(-0.73032110929489), + SCALE_SPLIT_ANGLE(-0.92225730419159), + SCALE_SPLIT_ANGLE(-1.11866605281830), + SCALE_SPLIT_ANGLE(-1.44806659221649), + SCALE_SPLIT_ANGLE(-1.99872648715973), + SCALE_SPLIT_ANGLE(-2.47302079200745)}, + {SCALE_SPLIT_ANGLE(-0.43393719196320), + SCALE_SPLIT_ANGLE(-0.47099208831787), + SCALE_SPLIT_ANGLE(-0.52780753374100), + SCALE_SPLIT_ANGLE(-0.67895972728729), + SCALE_SPLIT_ANGLE(-0.84712409973145), + SCALE_SPLIT_ANGLE(-1.17809724807739), + SCALE_SPLIT_ANGLE(-1.89703977108002), + SCALE_SPLIT_ANGLE(-2.59155678749084)}, + {SCALE_SPLIT_ANGLE(-0.33522716164589), + SCALE_SPLIT_ANGLE(-0.36133098602295), + SCALE_SPLIT_ANGLE(-0.40159514546394), + SCALE_SPLIT_ANGLE(-0.51039946079254), + SCALE_SPLIT_ANGLE(-0.63590413331985), + SCALE_SPLIT_ANGLE(-0.90812796354294), + SCALE_SPLIT_ANGLE(-1.70793569087982), + SCALE_SPLIT_ANGLE(-2.52852439880371)}, + {SCALE_SPLIT_ANGLE(-0.27478921413422), + SCALE_SPLIT_ANGLE(-0.29251146316528), + SCALE_SPLIT_ANGLE(-0.32007753849030), + SCALE_SPLIT_ANGLE(-0.39531296491623), + SCALE_SPLIT_ANGLE(-0.48291319608688), + SCALE_SPLIT_ANGLE(-0.67812001705170), + SCALE_SPLIT_ANGLE(-1.39007341861725), + SCALE_SPLIT_ANGLE(-2.34402585029602)}, + {SCALE_SPLIT_ANGLE(-0.23185737431049), + SCALE_SPLIT_ANGLE(-0.24370788037777), + SCALE_SPLIT_ANGLE(-0.26227977871895), + SCALE_SPLIT_ANGLE(-0.31327378749847), + SCALE_SPLIT_ANGLE(-0.37241828441620), + SCALE_SPLIT_ANGLE(-0.50202107429504), + SCALE_SPLIT_ANGLE(-0.99085599184036), + SCALE_SPLIT_ANGLE(-1.96553480625153)}, + {SCALE_SPLIT_ANGLE(-0.19698302447796), + SCALE_SPLIT_ANGLE(-0.20488265156746), + SCALE_SPLIT_ANGLE(-0.21731522679329), + SCALE_SPLIT_ANGLE(-0.25148209929466), + SCALE_SPLIT_ANGLE(-0.29065513610840), + SCALE_SPLIT_ANGLE(-0.37341463565826), + SCALE_SPLIT_ANGLE(-0.65295964479446), + SCALE_SPLIT_ANGLE(-1.28865838050842)}, + {SCALE_SPLIT_ANGLE(-0.16667704284191), + SCALE_SPLIT_ANGLE(-0.17194209992886), + SCALE_SPLIT_ANGLE(-0.18023575842381), + SCALE_SPLIT_ANGLE(-0.20293866097927), + SCALE_SPLIT_ANGLE(-0.22855132818222), + SCALE_SPLIT_ANGLE(-0.28041815757751), + SCALE_SPLIT_ANGLE(-0.43142417073250), + SCALE_SPLIT_ANGLE(-0.70030152797699)}, + {SCALE_SPLIT_ANGLE(-0.12773875892162), + SCALE_SPLIT_ANGLE(-0.13059368729591), + SCALE_SPLIT_ANGLE(-0.13507817685604), + SCALE_SPLIT_ANGLE(-0.14721076190472), + SCALE_SPLIT_ANGLE(-0.16052411496639), + SCALE_SPLIT_ANGLE(-0.18590225279331), + SCALE_SPLIT_ANGLE(-0.24703903496265), + SCALE_SPLIT_ANGLE(-0.32153329253197)}, + {SCALE_SPLIT_ANGLE(-0.09603262692690), + SCALE_SPLIT_ANGLE(-0.09756571799517), + SCALE_SPLIT_ANGLE(-0.09996144473553), + SCALE_SPLIT_ANGLE(-0.10635072737932), + SCALE_SPLIT_ANGLE(-0.11317525804043), + SCALE_SPLIT_ANGLE(-0.12554959952831), + SCALE_SPLIT_ANGLE(-0.15168417990208), + SCALE_SPLIT_ANGLE(-0.17713625729084)}, + {SCALE_SPLIT_ANGLE(-0.07104730606079), + SCALE_SPLIT_ANGLE(-0.07186015695333), + SCALE_SPLIT_ANGLE(-0.07312334328890), + SCALE_SPLIT_ANGLE(-0.07644615322351), + SCALE_SPLIT_ANGLE(-0.07991369068623), + SCALE_SPLIT_ANGLE(-0.08596337586641), + SCALE_SPLIT_ANGLE(-0.09766443073750), + SCALE_SPLIT_ANGLE(-0.10767272859812)}, + {SCALE_SPLIT_ANGLE(-0.05192205309868), + SCALE_SPLIT_ANGLE(-0.05234766378999), + SCALE_SPLIT_ANGLE(-0.05300575867295), + SCALE_SPLIT_ANGLE(-0.05471667274833), + SCALE_SPLIT_ANGLE(-0.05646898224950), + SCALE_SPLIT_ANGLE(-0.05943990871310), + SCALE_SPLIT_ANGLE(-0.06485753506422), + SCALE_SPLIT_ANGLE(-0.06914159655571)}, + {SCALE_SPLIT_ANGLE(-0.03760398924351), + SCALE_SPLIT_ANGLE(-0.03782445192337), + SCALE_SPLIT_ANGLE(-0.03816392645240), + SCALE_SPLIT_ANGLE(-0.03903824090958), + SCALE_SPLIT_ANGLE(-0.03992090001702), + SCALE_SPLIT_ANGLE(-0.04138650000095), + SCALE_SPLIT_ANGLE(-0.04395476356149), + SCALE_SPLIT_ANGLE(-0.04588782414794)}, + {SCALE_SPLIT_ANGLE(-0.02166714519262), + SCALE_SPLIT_ANGLE(-0.02173947915435), + SCALE_SPLIT_ANGLE(-0.02185030654073), + SCALE_SPLIT_ANGLE(-0.02213260345161), + SCALE_SPLIT_ANGLE(-0.02241297997534), + SCALE_SPLIT_ANGLE(-0.02286812663078), + SCALE_SPLIT_ANGLE(-0.02363408729434), + SCALE_SPLIT_ANGLE(-0.02418405003846)}, + {SCALE_SPLIT_ANGLE(-0.01235313713551), + SCALE_SPLIT_ANGLE(-0.01237650867552), + SCALE_SPLIT_ANGLE(-0.01241220720112), + SCALE_SPLIT_ANGLE(-0.01250253617764), + SCALE_SPLIT_ANGLE(-0.01259138714522), + SCALE_SPLIT_ANGLE(-0.01273377239704), + SCALE_SPLIT_ANGLE(-0.01296819653362), + SCALE_SPLIT_ANGLE(-0.01313247904181)}, + {SCALE_SPLIT_ANGLE(-0.00700078438967), + SCALE_SPLIT_ANGLE(-0.00700826710090), + SCALE_SPLIT_ANGLE(-0.00701967626810), + SCALE_SPLIT_ANGLE(-0.00704843178391), + SCALE_SPLIT_ANGLE(-0.00707655726001), + SCALE_SPLIT_ANGLE(-0.00712130265310), + SCALE_SPLIT_ANGLE(-0.00719408923760), + SCALE_SPLIT_ANGLE(-0.00724443932995)}, + {SCALE_SPLIT_ANGLE(-0.00395406875759), + SCALE_SPLIT_ANGLE(-0.00395645154640), + SCALE_SPLIT_ANGLE(-0.00396008091047), + SCALE_SPLIT_ANGLE(-0.00396920833737), + SCALE_SPLIT_ANGLE(-0.00397810759023), + SCALE_SPLIT_ANGLE(-0.00399220641702), + SCALE_SPLIT_ANGLE(-0.00401498842984), + SCALE_SPLIT_ANGLE(-0.00403063651174)}, + {SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068)}, + }, + { + {SCALE_SPLIT_ANGLE(-1.96349549293518), + SCALE_SPLIT_ANGLE(-1.96349549293518), + SCALE_SPLIT_ANGLE(-1.96349549293518), + SCALE_SPLIT_ANGLE(-1.96349549293518), + SCALE_SPLIT_ANGLE(-1.96349549293518), + SCALE_SPLIT_ANGLE(-1.96349549293518), + SCALE_SPLIT_ANGLE(-1.96349549293518), + SCALE_SPLIT_ANGLE(-1.96349549293518)}, + {SCALE_SPLIT_ANGLE(-1.95824849605560), + SCALE_SPLIT_ANGLE(-1.95825111865997), + SCALE_SPLIT_ANGLE(-1.95825493335724), + SCALE_SPLIT_ANGLE(-1.95826470851898), + SCALE_SPLIT_ANGLE(-1.95827412605286), + SCALE_SPLIT_ANGLE(-1.95828902721405), + SCALE_SPLIT_ANGLE(-1.95831298828125), + SCALE_SPLIT_ANGLE(-1.95832931995392)}, + {SCALE_SPLIT_ANGLE(-1.95409321784973), + SCALE_SPLIT_ANGLE(-1.95410120487213), + SCALE_SPLIT_ANGLE(-1.95411348342896), + SCALE_SPLIT_ANGLE(-1.95414435863495), + SCALE_SPLIT_ANGLE(-1.95417428016663), + SCALE_SPLIT_ANGLE(-1.95422148704529), + SCALE_SPLIT_ANGLE(-1.95429742336273), + SCALE_SPLIT_ANGLE(-1.95434927940369)}, + {SCALE_SPLIT_ANGLE(-1.94654786586761), + SCALE_SPLIT_ANGLE(-1.94657349586487), + SCALE_SPLIT_ANGLE(-1.94661235809326), + SCALE_SPLIT_ANGLE(-1.94671010971069), + SCALE_SPLIT_ANGLE(-1.94680511951447), + SCALE_SPLIT_ANGLE(-1.94695532321930), + SCALE_SPLIT_ANGLE(-1.94719707965851), + SCALE_SPLIT_ANGLE(-1.94736242294312)}, + {SCALE_SPLIT_ANGLE(-1.93263387680054), + SCALE_SPLIT_ANGLE(-1.93271505832672), + SCALE_SPLIT_ANGLE(-1.93283867835999), + SCALE_SPLIT_ANGLE(-1.93314921855927), + SCALE_SPLIT_ANGLE(-1.93345177173615), + SCALE_SPLIT_ANGLE(-1.93393063545227), + SCALE_SPLIT_ANGLE(-1.93470406532288), + SCALE_SPLIT_ANGLE(-1.93523526191711)}, + {SCALE_SPLIT_ANGLE(-1.90630447864532), + SCALE_SPLIT_ANGLE(-1.90656316280365), + SCALE_SPLIT_ANGLE(-1.90695703029633), + SCALE_SPLIT_ANGLE(-1.90794789791107), + SCALE_SPLIT_ANGLE(-1.90891468524933), + SCALE_SPLIT_ANGLE(-1.91044914722443), + SCALE_SPLIT_ANGLE(-1.91294133663177), + SCALE_SPLIT_ANGLE(-1.91466677188873)}, + {SCALE_SPLIT_ANGLE(-1.87960767745972), + SCALE_SPLIT_ANGLE(-1.88012754917145), + SCALE_SPLIT_ANGLE(-1.88091945648193), + SCALE_SPLIT_ANGLE(-1.88291203975677), + SCALE_SPLIT_ANGLE(-1.88485789299011), + SCALE_SPLIT_ANGLE(-1.88795256614685), + SCALE_SPLIT_ANGLE(-1.89300417900085), + SCALE_SPLIT_ANGLE(-1.89653015136719)}, + {SCALE_SPLIT_ANGLE(-1.83877408504486), + SCALE_SPLIT_ANGLE(-1.83982253074646), + SCALE_SPLIT_ANGLE(-1.84141874313354), + SCALE_SPLIT_ANGLE(-1.84543371200562), + SCALE_SPLIT_ANGLE(-1.84935557842255), + SCALE_SPLIT_ANGLE(-1.85560452938080), + SCALE_SPLIT_ANGLE(-1.86587750911713), + SCALE_SPLIT_ANGLE(-1.87314093112946)}, + {SCALE_SPLIT_ANGLE(-1.77493441104889), + SCALE_SPLIT_ANGLE(-1.77705287933350), + SCALE_SPLIT_ANGLE(-1.78027486801147), + SCALE_SPLIT_ANGLE(-1.78836560249329), + SCALE_SPLIT_ANGLE(-1.79626119136810), + SCALE_SPLIT_ANGLE(-1.80886065959930), + SCALE_SPLIT_ANGLE(-1.82978057861328), + SCALE_SPLIT_ANGLE(-1.84489572048187)}, + {SCALE_SPLIT_ANGLE(-1.67321836948395), + SCALE_SPLIT_ANGLE(-1.67747676372528), + SCALE_SPLIT_ANGLE(-1.68394041061401), + SCALE_SPLIT_ANGLE(-1.70011758804321), + SCALE_SPLIT_ANGLE(-1.71586525440216), + SCALE_SPLIT_ANGLE(-1.74102890491486), + SCALE_SPLIT_ANGLE(-1.78345453739166), + SCALE_SPLIT_ANGLE(-1.81531310081482)}, + {SCALE_SPLIT_ANGLE(-1.51132130622864), + SCALE_SPLIT_ANGLE(-1.51959407329559), + SCALE_SPLIT_ANGLE(-1.53212583065033), + SCALE_SPLIT_ANGLE(-1.56339812278748), + SCALE_SPLIT_ANGLE(-1.59380078315735), + SCALE_SPLIT_ANGLE(-1.64260387420654), + SCALE_SPLIT_ANGLE(-1.72719144821167), + SCALE_SPLIT_ANGLE(-1.79549288749695)}, + {SCALE_SPLIT_ANGLE(-1.35904073715210), + SCALE_SPLIT_ANGLE(-1.37121629714966), + SCALE_SPLIT_ANGLE(-1.38967263698578), + SCALE_SPLIT_ANGLE(-1.43583405017853), + SCALE_SPLIT_ANGLE(-1.48093712329865), + SCALE_SPLIT_ANGLE(-1.55410349369049), + SCALE_SPLIT_ANGLE(-1.68521809577942), + SCALE_SPLIT_ANGLE(-1.80024909973145)}, + {SCALE_SPLIT_ANGLE(-1.17258918285370), + SCALE_SPLIT_ANGLE(-1.18893885612488), + SCALE_SPLIT_ANGLE(-1.21383893489838), + SCALE_SPLIT_ANGLE(-1.27678334712982), + SCALE_SPLIT_ANGLE(-1.33930444717407), + SCALE_SPLIT_ANGLE(-1.44322550296783), + SCALE_SPLIT_ANGLE(-1.64006841182709), + SCALE_SPLIT_ANGLE(-1.83627629280090)}, + {SCALE_SPLIT_ANGLE(-0.96933782100677), + SCALE_SPLIT_ANGLE(-0.98854482173920), + SCALE_SPLIT_ANGLE(-1.01807177066803), + SCALE_SPLIT_ANGLE(-1.09429979324341), + SCALE_SPLIT_ANGLE(-1.17245376110077), + SCALE_SPLIT_ANGLE(-1.30826890468597), + SCALE_SPLIT_ANGLE(-1.58911192417145), + SCALE_SPLIT_ANGLE(-1.92719459533691)}, + {SCALE_SPLIT_ANGLE(-0.77729856967926), + SCALE_SPLIT_ANGLE(-0.79675692319870), + SCALE_SPLIT_ANGLE(-0.82701623439789), + SCALE_SPLIT_ANGLE(-0.90724974870682), + SCALE_SPLIT_ANGLE(-0.99302661418915), + SCALE_SPLIT_ANGLE(-1.15164005756378), + SCALE_SPLIT_ANGLE(-1.52265238761902), + SCALE_SPLIT_ANGLE(-2.09869647026062)}, + {SCALE_SPLIT_ANGLE(-0.61765122413635), + SCALE_SPLIT_ANGLE(-0.63503879308701), + SCALE_SPLIT_ANGLE(-0.66235071420670), + SCALE_SPLIT_ANGLE(-0.73653644323349), + SCALE_SPLIT_ANGLE(-0.81904625892639), + SCALE_SPLIT_ANGLE(-0.98174780607224), + SCALE_SPLIT_ANGLE(-1.42110574245453), + SCALE_SPLIT_ANGLE(-2.28386068344116)}, + {SCALE_SPLIT_ANGLE(-0.49486327171326), + SCALE_SPLIT_ANGLE(-0.50909572839737), + SCALE_SPLIT_ANGLE(-0.53160977363586), + SCALE_SPLIT_ANGLE(-0.59379214048386), + SCALE_SPLIT_ANGLE(-0.66487479209900), + SCALE_SPLIT_ANGLE(-0.81185555458069), + SCALE_SPLIT_ANGLE(-1.26233398914337), + SCALE_SPLIT_ANGLE(-2.16925764083862)}, + {SCALE_SPLIT_ANGLE(-0.40230554342270), + SCALE_SPLIT_ANGLE(-0.41332268714905), + SCALE_SPLIT_ANGLE(-0.43082219362259), + SCALE_SPLIT_ANGLE(-0.47957947850227), + SCALE_SPLIT_ANGLE(-0.53603595495224), + SCALE_SPLIT_ANGLE(-0.65522664785385), + SCALE_SPLIT_ANGLE(-1.04503870010376), + SCALE_SPLIT_ANGLE(-1.87041819095612)}, + {SCALE_SPLIT_ANGLE(-0.33104604482651), + SCALE_SPLIT_ANGLE(-0.33927723765373), + SCALE_SPLIT_ANGLE(-0.35237133502960), + SCALE_SPLIT_ANGLE(-0.38892474770546), + SCALE_SPLIT_ANGLE(-0.43126162886620), + SCALE_SPLIT_ANGLE(-0.52027010917664), + SCALE_SPLIT_ANGLE(-0.80654197931290), + SCALE_SPLIT_ANGLE(-1.41960346698761)}, + {SCALE_SPLIT_ANGLE(-0.27415531873703), + SCALE_SPLIT_ANGLE(-0.28015667200089), + SCALE_SPLIT_ANGLE(-0.28969678282738), + SCALE_SPLIT_ANGLE(-0.31623727083206), + SCALE_SPLIT_ANGLE(-0.34670370817184), + SCALE_SPLIT_ANGLE(-0.40939208865166), + SCALE_SPLIT_ANGLE(-0.59604328870773), + SCALE_SPLIT_ANGLE(-0.94309812784195)}, + {SCALE_SPLIT_ANGLE(-0.22730343043804), + SCALE_SPLIT_ANGLE(-0.23159568011761), + SCALE_SPLIT_ANGLE(-0.23840220272541), + SCALE_SPLIT_ANGLE(-0.25720024108887), + SCALE_SPLIT_ANGLE(-0.27846288681030), + SCALE_SPLIT_ANGLE(-0.32089167833328), + SCALE_SPLIT_ANGLE(-0.43515858054161), + SCALE_SPLIT_ANGLE(-0.60622000694275)}, + {SCALE_SPLIT_ANGLE(-0.17074464261532), + SCALE_SPLIT_ANGLE(-0.17326098680496), + SCALE_SPLIT_ANGLE(-0.17722851037979), + SCALE_SPLIT_ANGLE(-0.18802368640900), + SCALE_SPLIT_ANGLE(-0.19990929961205), + SCALE_SPLIT_ANGLE(-0.22246663272381), + SCALE_SPLIT_ANGLE(-0.27514943480492), + SCALE_SPLIT_ANGLE(-0.33505329489708)}, + {SCALE_SPLIT_ANGLE(-0.12695816159248), + SCALE_SPLIT_ANGLE(-0.12838459014893), + SCALE_SPLIT_ANGLE(-0.13061878085136), + SCALE_SPLIT_ANGLE(-0.13660037517548), + SCALE_SPLIT_ANGLE(-0.14301039278507), + SCALE_SPLIT_ANGLE(-0.15463486313820), + SCALE_SPLIT_ANGLE(-0.17893928289413), + SCALE_SPLIT_ANGLE(-0.20203559100628)}, + {SCALE_SPLIT_ANGLE(-0.09338590502739), + SCALE_SPLIT_ANGLE(-0.09417138248682), + SCALE_SPLIT_ANGLE(-0.09539389610291), + SCALE_SPLIT_ANGLE(-0.09861853718758), + SCALE_SPLIT_ANGLE(-0.10199318081141), + SCALE_SPLIT_ANGLE(-0.10789106041193), + SCALE_SPLIT_ANGLE(-0.11927829682827), + SCALE_SPLIT_ANGLE(-0.12894384562969)}, + {SCALE_SPLIT_ANGLE(-0.06804534792900), + SCALE_SPLIT_ANGLE(-0.06846774369478), + SCALE_SPLIT_ANGLE(-0.06912153959274), + SCALE_SPLIT_ANGLE(-0.07082460820675), + SCALE_SPLIT_ANGLE(-0.07257289439440), + SCALE_SPLIT_ANGLE(-0.07554303109646), + SCALE_SPLIT_ANGLE(-0.08096560835838), + SCALE_SPLIT_ANGLE(-0.08524779230356)}, + {SCALE_SPLIT_ANGLE(-0.04920703917742), + SCALE_SPLIT_ANGLE(-0.04942998290062), + SCALE_SPLIT_ANGLE(-0.04977353662252), + SCALE_SPLIT_ANGLE(-0.05065960064530), + SCALE_SPLIT_ANGLE(-0.05155571177602), + SCALE_SPLIT_ANGLE(-0.05304637178779), + SCALE_SPLIT_ANGLE(-0.05566369369626), + SCALE_SPLIT_ANGLE(-0.05763531103730)}, + {SCALE_SPLIT_ANGLE(-0.02832321636379), + SCALE_SPLIT_ANGLE(-0.02839783579111), + SCALE_SPLIT_ANGLE(-0.02851220592856), + SCALE_SPLIT_ANGLE(-0.02880378812551), + SCALE_SPLIT_ANGLE(-0.02909369207919), + SCALE_SPLIT_ANGLE(-0.02956490218639), + SCALE_SPLIT_ANGLE(-0.03035926632583), + SCALE_SPLIT_ANGLE(-0.03093044646084)}, + {SCALE_SPLIT_ANGLE(-0.01614263094962), + SCALE_SPLIT_ANGLE(-0.01616701111197), + SCALE_SPLIT_ANGLE(-0.01620426028967), + SCALE_SPLIT_ANGLE(-0.01629855856299), + SCALE_SPLIT_ANGLE(-0.01639137044549), + SCALE_SPLIT_ANGLE(-0.01654022000730), + SCALE_SPLIT_ANGLE(-0.01678557321429), + SCALE_SPLIT_ANGLE(-0.01695770025253)}, + {SCALE_SPLIT_ANGLE(-0.00914741121233), + SCALE_SPLIT_ANGLE(-0.00915526598692), + SCALE_SPLIT_ANGLE(-0.00916724465787), + SCALE_SPLIT_ANGLE(-0.00919744279236), + SCALE_SPLIT_ANGLE(-0.00922699086368), + SCALE_SPLIT_ANGLE(-0.00927401985973), + SCALE_SPLIT_ANGLE(-0.00935057457536), + SCALE_SPLIT_ANGLE(-0.00940357148647)}, + {SCALE_SPLIT_ANGLE(-0.00516631966457), + SCALE_SPLIT_ANGLE(-0.00516883004457), + SCALE_SPLIT_ANGLE(-0.00517265358940), + SCALE_SPLIT_ANGLE(-0.00518227042630), + SCALE_SPLIT_ANGLE(-0.00519164977595), + SCALE_SPLIT_ANGLE(-0.00520651368424), + SCALE_SPLIT_ANGLE(-0.00523054040968), + SCALE_SPLIT_ANGLE(-0.00524705089629)}, + {SCALE_SPLIT_ANGLE(-0.00000002921564), + SCALE_SPLIT_ANGLE(-0.00000002921564), + SCALE_SPLIT_ANGLE(-0.00000002921564), + SCALE_SPLIT_ANGLE(-0.00000002921564), + SCALE_SPLIT_ANGLE(-0.00000002921564), + SCALE_SPLIT_ANGLE(-0.00000002921564), + SCALE_SPLIT_ANGLE(-0.00000002921564), + SCALE_SPLIT_ANGLE(-0.00000002921564)}, + }, + { + {SCALE_SPLIT_ANGLE(-1.57079625129700), + SCALE_SPLIT_ANGLE(-1.57079625129700), + SCALE_SPLIT_ANGLE(-1.57079625129700), + SCALE_SPLIT_ANGLE(-1.57079625129700), + SCALE_SPLIT_ANGLE(-1.57079625129700), + SCALE_SPLIT_ANGLE(-1.57079625129700), + SCALE_SPLIT_ANGLE(-1.57079625129700), + SCALE_SPLIT_ANGLE(-1.57079625129700)}, + {SCALE_SPLIT_ANGLE(-1.56514143943787), + SCALE_SPLIT_ANGLE(-1.56514346599579), + SCALE_SPLIT_ANGLE(-1.56514644622803), + SCALE_SPLIT_ANGLE(-1.56515395641327), + SCALE_SPLIT_ANGLE(-1.56516134738922), + SCALE_SPLIT_ANGLE(-1.56517291069031), + SCALE_SPLIT_ANGLE(-1.56519162654877), + SCALE_SPLIT_ANGLE(-1.56520438194275)}, + {SCALE_SPLIT_ANGLE(-1.56069743633270), + SCALE_SPLIT_ANGLE(-1.56070363521576), + SCALE_SPLIT_ANGLE(-1.56071305274963), + SCALE_SPLIT_ANGLE(-1.56073689460754), + SCALE_SPLIT_ANGLE(-1.56076002120972), + SCALE_SPLIT_ANGLE(-1.56079661846161), + SCALE_SPLIT_ANGLE(-1.56085574626923), + SCALE_SPLIT_ANGLE(-1.56089639663696)}, + {SCALE_SPLIT_ANGLE(-1.55270349979401), + SCALE_SPLIT_ANGLE(-1.55272293090820), + SCALE_SPLIT_ANGLE(-1.55275249481201), + SCALE_SPLIT_ANGLE(-1.55282700061798), + SCALE_SPLIT_ANGLE(-1.55289971828461), + SCALE_SPLIT_ANGLE(-1.55301535129547), + SCALE_SPLIT_ANGLE(-1.55320298671722), + SCALE_SPLIT_ANGLE(-1.55333244800568)}, + {SCALE_SPLIT_ANGLE(-1.53820896148682), + SCALE_SPLIT_ANGLE(-1.53826904296875), + SCALE_SPLIT_ANGLE(-1.53836083412170), + SCALE_SPLIT_ANGLE(-1.53859269618988), + SCALE_SPLIT_ANGLE(-1.53882038593292), + SCALE_SPLIT_ANGLE(-1.53918409347534), + SCALE_SPLIT_ANGLE(-1.53978025913239), + SCALE_SPLIT_ANGLE(-1.54019618034363)}, + {SCALE_SPLIT_ANGLE(-1.51160359382629), + SCALE_SPLIT_ANGLE(-1.51178681850433), + SCALE_SPLIT_ANGLE(-1.51206707954407), + SCALE_SPLIT_ANGLE(-1.51277911663055), + SCALE_SPLIT_ANGLE(-1.51348364353180), + SCALE_SPLIT_ANGLE(-1.51462137699127), + SCALE_SPLIT_ANGLE(-1.51652014255524), + SCALE_SPLIT_ANGLE(-1.51787149906158)}, + {SCALE_SPLIT_ANGLE(-1.48564028739929), + SCALE_SPLIT_ANGLE(-1.48599267005920), + SCALE_SPLIT_ANGLE(-1.48653328418732), + SCALE_SPLIT_ANGLE(-1.48791313171387), + SCALE_SPLIT_ANGLE(-1.48928785324097), + SCALE_SPLIT_ANGLE(-1.49152994155884), + SCALE_SPLIT_ANGLE(-1.49533629417419), + SCALE_SPLIT_ANGLE(-1.49810016155243)}, + {SCALE_SPLIT_ANGLE(-1.44770431518555), + SCALE_SPLIT_ANGLE(-1.44837117195129), + SCALE_SPLIT_ANGLE(-1.44939672946930), + SCALE_SPLIT_ANGLE(-1.45203149318695), + SCALE_SPLIT_ANGLE(-1.45468175411224), + SCALE_SPLIT_ANGLE(-1.45906174182892), + SCALE_SPLIT_ANGLE(-1.46668362617493), + SCALE_SPLIT_ANGLE(-1.47238755226135)}, + {SCALE_SPLIT_ANGLE(-1.39214622974396), + SCALE_SPLIT_ANGLE(-1.39337480068207), + SCALE_SPLIT_ANGLE(-1.39527142047882), + SCALE_SPLIT_ANGLE(-1.40018463134766), + SCALE_SPLIT_ANGLE(-1.40518975257874), + SCALE_SPLIT_ANGLE(-1.41361439228058), + SCALE_SPLIT_ANGLE(-1.42880713939667), + SCALE_SPLIT_ANGLE(-1.44072234630585)}, + {SCALE_SPLIT_ANGLE(-1.31133687496185), + SCALE_SPLIT_ANGLE(-1.31350564956665), + SCALE_SPLIT_ANGLE(-1.31686961650848), + SCALE_SPLIT_ANGLE(-1.32567894458771), + SCALE_SPLIT_ANGLE(-1.33480489253998), + SCALE_SPLIT_ANGLE(-1.35055565834045), + SCALE_SPLIT_ANGLE(-1.38048458099365), + SCALE_SPLIT_ANGLE(-1.40579903125763)}, + {SCALE_SPLIT_ANGLE(-1.19695889949799), + SCALE_SPLIT_ANGLE(-1.20052516460419), + SCALE_SPLIT_ANGLE(-1.20609176158905), + SCALE_SPLIT_ANGLE(-1.22087824344635), + SCALE_SPLIT_ANGLE(-1.23654139041901), + SCALE_SPLIT_ANGLE(-1.26451897621155), + SCALE_SPLIT_ANGLE(-1.32194638252258), + SCALE_SPLIT_ANGLE(-1.37709844112396)}, + {SCALE_SPLIT_ANGLE(-1.09969496726990), + SCALE_SPLIT_ANGLE(-1.10437369346619), + SCALE_SPLIT_ANGLE(-1.11171460151672), + SCALE_SPLIT_ANGLE(-1.13144767284393), + SCALE_SPLIT_ANGLE(-1.15274536609650), + SCALE_SPLIT_ANGLE(-1.19192278385162), + SCALE_SPLIT_ANGLE(-1.27820122241974), + SCALE_SPLIT_ANGLE(-1.37287354469299)}, + {SCALE_SPLIT_ANGLE(-0.98739635944366), + SCALE_SPLIT_ANGLE(-0.99314498901367), + SCALE_SPLIT_ANGLE(-1.00221848487854), + SCALE_SPLIT_ANGLE(-1.02694928646088), + SCALE_SPLIT_ANGLE(-1.05423069000244), + SCALE_SPLIT_ANGLE(-1.10619938373566), + SCALE_SPLIT_ANGLE(-1.23116791248322), + SCALE_SPLIT_ANGLE(-1.39771783351898)}, + {SCALE_SPLIT_ANGLE(-0.86566168069839), + SCALE_SPLIT_ANGLE(-0.87219274044037), + SCALE_SPLIT_ANGLE(-0.88256770372391), + SCALE_SPLIT_ANGLE(-0.91127198934555), + SCALE_SPLIT_ANGLE(-0.94370102882385), + SCALE_SPLIT_ANGLE(-1.00792455673218), + SCALE_SPLIT_ANGLE(-1.17914199829102), + SCALE_SPLIT_ANGLE(-1.48121190071106)}, + {SCALE_SPLIT_ANGLE(-0.74293029308319), + SCALE_SPLIT_ANGLE(-0.74975663423538), + SCALE_SPLIT_ANGLE(-0.76066619157791), + SCALE_SPLIT_ANGLE(-0.79128366708755), + SCALE_SPLIT_ANGLE(-0.82667875289917), + SCALE_SPLIT_ANGLE(-0.89952337741852), + SCALE_SPLIT_ANGLE(-1.11571288108826), + SCALE_SPLIT_ANGLE(-1.67431199550629)}, + {SCALE_SPLIT_ANGLE(-0.62761706113815), + SCALE_SPLIT_ANGLE(-0.63421267271042), + SCALE_SPLIT_ANGLE(-0.64480352401733), + SCALE_SPLIT_ANGLE(-0.67486244440079), + SCALE_SPLIT_ANGLE(-0.71025305986404), + SCALE_SPLIT_ANGLE(-0.78539818525314), + SCALE_SPLIT_ANGLE(-1.02937340736389), + SCALE_SPLIT_ANGLE(-1.92301476001740)}, + {SCALE_SPLIT_ANGLE(-0.52522456645966), + SCALE_SPLIT_ANGLE(-0.53118568658829), + SCALE_SPLIT_ANGLE(-0.54078328609467), + SCALE_SPLIT_ANGLE(-0.56819742918015), + SCALE_SPLIT_ANGLE(-0.60080897808075), + SCALE_SPLIT_ANGLE(-0.67127293348312), + SCALE_SPLIT_ANGLE(-0.91114157438278), + SCALE_SPLIT_ANGLE(-1.73398244380951)}, + {SCALE_SPLIT_ANGLE(-0.43751952052116), + SCALE_SPLIT_ANGLE(-0.44262495636940), + SCALE_SPLIT_ANGLE(-0.45084837079048), + SCALE_SPLIT_ANGLE(-0.47435706853867), + SCALE_SPLIT_ANGLE(-0.50235128402710), + SCALE_SPLIT_ANGLE(-0.56287175416946), + SCALE_SPLIT_ANGLE(-0.76705116033554), + SCALE_SPLIT_ANGLE(-1.34888231754303)}, + {SCALE_SPLIT_ANGLE(-0.36364197731018), + SCALE_SPLIT_ANGLE(-0.36782836914063), + SCALE_SPLIT_ANGLE(-0.37456014752388), + SCALE_SPLIT_ANGLE(-0.39372298121452), + SCALE_SPLIT_ANGLE(-0.41636970639229), + SCALE_SPLIT_ANGLE(-0.46459695696831), + SCALE_SPLIT_ANGLE(-0.61803078651428), + SCALE_SPLIT_ANGLE(-0.96275907754898)}, + {SCALE_SPLIT_ANGLE(-0.30166232585907), + SCALE_SPLIT_ANGLE(-0.30497136712074), + SCALE_SPLIT_ANGLE(-0.31027451157570), + SCALE_SPLIT_ANGLE(-0.32524627447128), + SCALE_SPLIT_ANGLE(-0.34269106388092), + SCALE_SPLIT_ANGLE(-0.37887355685234), + SCALE_SPLIT_ANGLE(-0.48432540893555), + SCALE_SPLIT_ANGLE(-0.66878592967987)}, + {SCALE_SPLIT_ANGLE(-0.24960109591484), + SCALE_SPLIT_ANGLE(-0.25213342905045), + SCALE_SPLIT_ANGLE(-0.25617361068726), + SCALE_SPLIT_ANGLE(-0.26745575666428), + SCALE_SPLIT_ANGLE(-0.28036275506020), + SCALE_SPLIT_ANGLE(-0.30627736449242), + SCALE_SPLIT_ANGLE(-0.37490698695183), + SCALE_SPLIT_ANGLE(-0.47145301103592)}, + {SCALE_SPLIT_ANGLE(-0.18661488592625), + SCALE_SPLIT_ANGLE(-0.18822199106216), + SCALE_SPLIT_ANGLE(-0.19076594710350), + SCALE_SPLIT_ANGLE(-0.19773861765862), + SCALE_SPLIT_ANGLE(-0.20547652244568), + SCALE_SPLIT_ANGLE(-0.22024063766003), + SCALE_SPLIT_ANGLE(-0.25452125072479), + SCALE_SPLIT_ANGLE(-0.29236793518066)}, + {SCALE_SPLIT_ANGLE(-0.13821771740913), + SCALE_SPLIT_ANGLE(-0.13918289542198), + SCALE_SPLIT_ANGLE(-0.14069861173630), + SCALE_SPLIT_ANGLE(-0.14477686583996), + SCALE_SPLIT_ANGLE(-0.14917232096195), + SCALE_SPLIT_ANGLE(-0.15718193352222), + SCALE_SPLIT_ANGLE(-0.17394064366817), + SCALE_SPLIT_ANGLE(-0.18971265852451)}, + {SCALE_SPLIT_ANGLE(-0.10140904784203), + SCALE_SPLIT_ANGLE(-0.10196315497160), + SCALE_SPLIT_ANGLE(-0.10282710194588), + SCALE_SPLIT_ANGLE(-0.10511382669210), + SCALE_SPLIT_ANGLE(-0.10751703381538), + SCALE_SPLIT_ANGLE(-0.11173453181982), + SCALE_SPLIT_ANGLE(-0.11990433931351), + SCALE_SPLIT_ANGLE(-0.12683042883873)}, + {SCALE_SPLIT_ANGLE(-0.07378087192774), + SCALE_SPLIT_ANGLE(-0.07408788800240), + SCALE_SPLIT_ANGLE(-0.07456368207932), + SCALE_SPLIT_ANGLE(-0.07580613344908), + SCALE_SPLIT_ANGLE(-0.07708552479744), + SCALE_SPLIT_ANGLE(-0.07926639169455), + SCALE_SPLIT_ANGLE(-0.08326309919357), + SCALE_SPLIT_ANGLE(-0.08642497658730)}, + {SCALE_SPLIT_ANGLE(-0.05331044271588), + SCALE_SPLIT_ANGLE(-0.05347600579262), + SCALE_SPLIT_ANGLE(-0.05373133346438), + SCALE_SPLIT_ANGLE(-0.05439101532102), + SCALE_SPLIT_ANGLE(-0.05505971238017), + SCALE_SPLIT_ANGLE(-0.05617496743798), + SCALE_SPLIT_ANGLE(-0.05813983827829), + SCALE_SPLIT_ANGLE(-0.05962376296520)}, + {SCALE_SPLIT_ANGLE(-0.03066622652113), + SCALE_SPLIT_ANGLE(-0.03072291985154), + SCALE_SPLIT_ANGLE(-0.03080986253917), + SCALE_SPLIT_ANGLE(-0.03103173524141), + SCALE_SPLIT_ANGLE(-0.03125262632966), + SCALE_SPLIT_ANGLE(-0.03161224350333), + SCALE_SPLIT_ANGLE(-0.03221990913153), + SCALE_SPLIT_ANGLE(-0.03265778720379)}, + {SCALE_SPLIT_ANGLE(-0.01747439615428), + SCALE_SPLIT_ANGLE(-0.01749316416681), + SCALE_SPLIT_ANGLE(-0.01752184517682), + SCALE_SPLIT_ANGLE(-0.01759449020028), + SCALE_SPLIT_ANGLE(-0.01766604930162), + SCALE_SPLIT_ANGLE(-0.01778092049062), + SCALE_SPLIT_ANGLE(-0.01797054335475), + SCALE_SPLIT_ANGLE(-0.01810375973582)}, + {SCALE_SPLIT_ANGLE(-0.00990140344948), + SCALE_SPLIT_ANGLE(-0.00990749336779), + SCALE_SPLIT_ANGLE(-0.00991678331047), + SCALE_SPLIT_ANGLE(-0.00994021166116), + SCALE_SPLIT_ANGLE(-0.00996314454824), + SCALE_SPLIT_ANGLE(-0.00999966636300), + SCALE_SPLIT_ANGLE(-0.01005917042494), + SCALE_SPLIT_ANGLE(-0.01010039448738)}, + {SCALE_SPLIT_ANGLE(-0.00559204118326), + SCALE_SPLIT_ANGLE(-0.00559399509802), + SCALE_SPLIT_ANGLE(-0.00559697346762), + SCALE_SPLIT_ANGLE(-0.00560446362942), + SCALE_SPLIT_ANGLE(-0.00561177125201), + SCALE_SPLIT_ANGLE(-0.00562335411087), + SCALE_SPLIT_ANGLE(-0.00564208766446), + SCALE_SPLIT_ANGLE(-0.00565496599302)}, + {SCALE_SPLIT_ANGLE(-0.00000003162278), + SCALE_SPLIT_ANGLE(-0.00000003162278), + SCALE_SPLIT_ANGLE(-0.00000003162278), + SCALE_SPLIT_ANGLE(-0.00000003162278), + SCALE_SPLIT_ANGLE(-0.00000003162278), + SCALE_SPLIT_ANGLE(-0.00000003162278), + SCALE_SPLIT_ANGLE(-0.00000003162278), + SCALE_SPLIT_ANGLE(-0.00000003162278)}, + }, + { + {SCALE_SPLIT_ANGLE(-1.17809700965881), + SCALE_SPLIT_ANGLE(-1.17809700965881), + SCALE_SPLIT_ANGLE(-1.17809700965881), + SCALE_SPLIT_ANGLE(-1.17809700965881), + SCALE_SPLIT_ANGLE(-1.17809700965881), + SCALE_SPLIT_ANGLE(-1.17809700965881), + SCALE_SPLIT_ANGLE(-1.17809700965881), + SCALE_SPLIT_ANGLE(-1.17809700965881)}, + {SCALE_SPLIT_ANGLE(-1.17289507389069), + SCALE_SPLIT_ANGLE(-1.17289614677429), + SCALE_SPLIT_ANGLE(-1.17289793491364), + SCALE_SPLIT_ANGLE(-1.17290210723877), + SCALE_SPLIT_ANGLE(-1.17290627956390), + SCALE_SPLIT_ANGLE(-1.17291295528412), + SCALE_SPLIT_ANGLE(-1.17292356491089), + SCALE_SPLIT_ANGLE(-1.17293083667755)}, + {SCALE_SPLIT_ANGLE(-1.16883778572083), + SCALE_SPLIT_ANGLE(-1.16884136199951), + SCALE_SPLIT_ANGLE(-1.16884660720825), + SCALE_SPLIT_ANGLE(-1.16885995864868), + SCALE_SPLIT_ANGLE(-1.16887307167053), + SCALE_SPLIT_ANGLE(-1.16889369487762), + SCALE_SPLIT_ANGLE(-1.16892731189728), + SCALE_SPLIT_ANGLE(-1.16895043849945)}, + {SCALE_SPLIT_ANGLE(-1.16160643100739), + SCALE_SPLIT_ANGLE(-1.16161715984344), + SCALE_SPLIT_ANGLE(-1.16163349151611), + SCALE_SPLIT_ANGLE(-1.16167497634888), + SCALE_SPLIT_ANGLE(-1.16171550750732), + SCALE_SPLIT_ANGLE(-1.16178035736084), + SCALE_SPLIT_ANGLE(-1.16188645362854), + SCALE_SPLIT_ANGLE(-1.16196036338806)}, + {SCALE_SPLIT_ANGLE(-1.14870381355286), + SCALE_SPLIT_ANGLE(-1.14873635768890), + SCALE_SPLIT_ANGLE(-1.14878606796265), + SCALE_SPLIT_ANGLE(-1.14891242980957), + SCALE_SPLIT_ANGLE(-1.14903736114502), + SCALE_SPLIT_ANGLE(-1.14923870563507), + SCALE_SPLIT_ANGLE(-1.14957380294800), + SCALE_SPLIT_ANGLE(-1.14981114864349)}, + {SCALE_SPLIT_ANGLE(-1.12567472457886), + SCALE_SPLIT_ANGLE(-1.12576985359192), + SCALE_SPLIT_ANGLE(-1.12591588497162), + SCALE_SPLIT_ANGLE(-1.12629044055939), + SCALE_SPLIT_ANGLE(-1.12666571140289), + SCALE_SPLIT_ANGLE(-1.12728178501129), + SCALE_SPLIT_ANGLE(-1.12833738327026), + SCALE_SPLIT_ANGLE(-1.12910985946655)}, + {SCALE_SPLIT_ANGLE(-1.10394370555878), + SCALE_SPLIT_ANGLE(-1.10411989688873), + SCALE_SPLIT_ANGLE(-1.10439169406891), + SCALE_SPLIT_ANGLE(-1.10509419441223), + SCALE_SPLIT_ANGLE(-1.10580670833588), + SCALE_SPLIT_ANGLE(-1.10699570178986), + SCALE_SPLIT_ANGLE(-1.10909187793732), + SCALE_SPLIT_ANGLE(-1.11067557334900)}, + {SCALE_SPLIT_ANGLE(-1.07335841655731), + SCALE_SPLIT_ANGLE(-1.07367491722107), + SCALE_SPLIT_ANGLE(-1.07416582107544), + SCALE_SPLIT_ANGLE(-1.07544875144959), + SCALE_SPLIT_ANGLE(-1.07677149772644), + SCALE_SPLIT_ANGLE(-1.07902920246124), + SCALE_SPLIT_ANGLE(-1.08317422866821), + SCALE_SPLIT_ANGLE(-1.08645880222321)}, + {SCALE_SPLIT_ANGLE(-1.03070914745331), + SCALE_SPLIT_ANGLE(-1.03125369548798), + SCALE_SPLIT_ANGLE(-1.03210353851318), + SCALE_SPLIT_ANGLE(-1.03435730934143), + SCALE_SPLIT_ANGLE(-1.03673195838928), + SCALE_SPLIT_ANGLE(-1.04091215133667), + SCALE_SPLIT_ANGLE(-1.04904508590698), + SCALE_SPLIT_ANGLE(-1.05597043037415)}, + {SCALE_SPLIT_ANGLE(-0.97233015298843), + SCALE_SPLIT_ANGLE(-0.97321158647537), + SCALE_SPLIT_ANGLE(-0.97459846735001), + SCALE_SPLIT_ANGLE(-0.97834426164627), + SCALE_SPLIT_ANGLE(-0.98240232467651), + SCALE_SPLIT_ANGLE(-0.98984342813492), + SCALE_SPLIT_ANGLE(-1.00556397438049), + SCALE_SPLIT_ANGLE(-1.02053022384644)}, + {SCALE_SPLIT_ANGLE(-0.89506632089615), + SCALE_SPLIT_ANGLE(-0.89638078212738), + SCALE_SPLIT_ANGLE(-0.89846837520599), + SCALE_SPLIT_ANGLE(-0.90423023700714), + SCALE_SPLIT_ANGLE(-0.91068559885025), + SCALE_SPLIT_ANGLE(-0.92315053939819), + SCALE_SPLIT_ANGLE(-0.95268231630325), + SCALE_SPLIT_ANGLE(-0.98626488447189)}, + {SCALE_SPLIT_ANGLE(-0.83257317543030), + SCALE_SPLIT_ANGLE(-0.83419388532639), + SCALE_SPLIT_ANGLE(-0.83678513765335), + SCALE_SPLIT_ANGLE(-0.84404873847961), + SCALE_SPLIT_ANGLE(-0.85238862037659), + SCALE_SPLIT_ANGLE(-0.86914104223251), + SCALE_SPLIT_ANGLE(-0.91285753250122), + SCALE_SPLIT_ANGLE(-0.97222834825516)}, + {SCALE_SPLIT_ANGLE(-0.76227325201035), + SCALE_SPLIT_ANGLE(-0.76417011022568), + SCALE_SPLIT_ANGLE(-0.76722222566605), + SCALE_SPLIT_ANGLE(-0.77590954303741), + SCALE_SPLIT_ANGLE(-0.78613209724426), + SCALE_SPLIT_ANGLE(-0.80752629041672), + SCALE_SPLIT_ANGLE(-0.86987817287445), + SCALE_SPLIT_ANGLE(-0.97863042354584)}, + {SCALE_SPLIT_ANGLE(-0.68631613254547), + SCALE_SPLIT_ANGLE(-0.68841677904129), + SCALE_SPLIT_ANGLE(-0.69181627035141), + SCALE_SPLIT_ANGLE(-0.70162516832352), + SCALE_SPLIT_ANGLE(-0.71342802047729), + SCALE_SPLIT_ANGLE(-0.73910319805145), + SCALE_SPLIT_ANGLE(-0.82307589054108), + SCALE_SPLIT_ANGLE(-1.03222990036011)}, + {SCALE_SPLIT_ANGLE(-0.60781323909760), + SCALE_SPLIT_ANGLE(-0.61001539230347), + SCALE_SPLIT_ANGLE(-0.61359477043152), + SCALE_SPLIT_ANGLE(-0.62403184175491), + SCALE_SPLIT_ANGLE(-0.63681107759476), + SCALE_SPLIT_ANGLE(-0.66548812389374), + SCALE_SPLIT_ANGLE(-0.76931124925613), + SCALE_SPLIT_ANGLE(-1.19638121128082)}, + {SCALE_SPLIT_ANGLE(-0.53021627664566), + SCALE_SPLIT_ANGLE(-0.53240883350372), + SCALE_SPLIT_ANGLE(-0.53598141670227), + SCALE_SPLIT_ANGLE(-0.54646164178848), + SCALE_SPLIT_ANGLE(-0.55942356586456), + SCALE_SPLIT_ANGLE(-0.58904850482941), + SCALE_SPLIT_ANGLE(-0.70326185226440), + SCALE_SPLIT_ANGLE(-1.46822547912598)}, + {SCALE_SPLIT_ANGLE(-0.45655792951584), + SCALE_SPLIT_ANGLE(-0.45864021778107), + SCALE_SPLIT_ANGLE(-0.46203425526619), + SCALE_SPLIT_ANGLE(-0.47199884057045), + SCALE_SPLIT_ANGLE(-0.48433950543404), + SCALE_SPLIT_ANGLE(-0.51260894536972), + SCALE_SPLIT_ANGLE(-0.62212854623795), + SCALE_SPLIT_ANGLE(-1.20720005035400)}, + {SCALE_SPLIT_ANGLE(-0.38893285393715), + SCALE_SPLIT_ANGLE(-0.39082619547844), + SCALE_SPLIT_ANGLE(-0.39390665292740), + SCALE_SPLIT_ANGLE(-0.40291139483452), + SCALE_SPLIT_ANGLE(-0.41398155689240), + SCALE_SPLIT_ANGLE(-0.43899381160736), + SCALE_SPLIT_ANGLE(-0.53091597557068), + SCALE_SPLIT_ANGLE(-0.85221308469772)}, + {SCALE_SPLIT_ANGLE(-0.32840180397034), + SCALE_SPLIT_ANGLE(-0.33005377650261), + SCALE_SPLIT_ANGLE(-0.33273178339005), + SCALE_SPLIT_ANGLE(-0.34049153327942), + SCALE_SPLIT_ANGLE(-0.34989196062088), + SCALE_SPLIT_ANGLE(-0.37057077884674), + SCALE_SPLIT_ANGLE(-0.43990370631218), + SCALE_SPLIT_ANGLE(-0.60593050718307)}, + {SCALE_SPLIT_ANGLE(-0.27521026134491), + SCALE_SPLIT_ANGLE(-0.27659529447556), + SCALE_SPLIT_ANGLE(-0.27882954478264), + SCALE_SPLIT_ANGLE(-0.28522571921349), + SCALE_SPLIT_ANGLE(-0.29282191395760), + SCALE_SPLIT_ANGLE(-0.30895599722862), + SCALE_SPLIT_ANGLE(-0.35752710700035), + SCALE_SPLIT_ANGLE(-0.44366964697838)}, + {SCALE_SPLIT_ANGLE(-0.22909800708294), + SCALE_SPLIT_ANGLE(-0.23021571338177), + SCALE_SPLIT_ANGLE(-0.23200808465481), + SCALE_SPLIT_ANGLE(-0.23706813156605), + SCALE_SPLIT_ANGLE(-0.24294249713421), + SCALE_SPLIT_ANGLE(-0.25494650006294), + SCALE_SPLIT_ANGLE(-0.28743270039558), + SCALE_SPLIT_ANGLE(-0.33326250314713)}, + {SCALE_SPLIT_ANGLE(-0.17204396426678), + SCALE_SPLIT_ANGLE(-0.17280194163322), + SCALE_SPLIT_ANGLE(-0.17400610446930), + SCALE_SPLIT_ANGLE(-0.17733126878738), + SCALE_SPLIT_ANGLE(-0.18105843663216), + SCALE_SPLIT_ANGLE(-0.18825362622738), + SCALE_SPLIT_ANGLE(-0.20519737899303), + SCALE_SPLIT_ANGLE(-0.22397245466709)}, + {SCALE_SPLIT_ANGLE(-0.12763081490994), + SCALE_SPLIT_ANGLE(-0.12810991704464), + SCALE_SPLIT_ANGLE(-0.12886415421963), + SCALE_SPLIT_ANGLE(-0.13090406358242), + SCALE_SPLIT_ANGLE(-0.13311786949635), + SCALE_SPLIT_ANGLE(-0.13718487322330), + SCALE_SPLIT_ANGLE(-0.14578334987164), + SCALE_SPLIT_ANGLE(-0.15392091870308)}, + {SCALE_SPLIT_ANGLE(-0.09368772059679), + SCALE_SPLIT_ANGLE(-0.09397349506617), + SCALE_SPLIT_ANGLE(-0.09441984444857), + SCALE_SPLIT_ANGLE(-0.09560552984476), + SCALE_SPLIT_ANGLE(-0.09685768932104), + SCALE_SPLIT_ANGLE(-0.09906788170338), + SCALE_SPLIT_ANGLE(-0.10338337719440), + SCALE_SPLIT_ANGLE(-0.10706327110529)}, + {SCALE_SPLIT_ANGLE(-0.06817039847374), + SCALE_SPLIT_ANGLE(-0.06833326816559), + SCALE_SPLIT_ANGLE(-0.06858597695827), + SCALE_SPLIT_ANGLE(-0.06924756616354), + SCALE_SPLIT_ANGLE(-0.06993118673563), + SCALE_SPLIT_ANGLE(-0.07110133022070), + SCALE_SPLIT_ANGLE(-0.07325870543718), + SCALE_SPLIT_ANGLE(-0.07497420907021)}, + {SCALE_SPLIT_ANGLE(-0.04925632849336), + SCALE_SPLIT_ANGLE(-0.04934597387910), + SCALE_SPLIT_ANGLE(-0.04948435723782), + SCALE_SPLIT_ANGLE(-0.04984252154827), + SCALE_SPLIT_ANGLE(-0.05020647123456), + SCALE_SPLIT_ANGLE(-0.05081529170275), + SCALE_SPLIT_ANGLE(-0.05189274996519), + SCALE_SPLIT_ANGLE(-0.05270983278751)}, + {SCALE_SPLIT_ANGLE(-0.02833298221231), + SCALE_SPLIT_ANGLE(-0.02836437523365), + SCALE_SPLIT_ANGLE(-0.02841254323721), + SCALE_SPLIT_ANGLE(-0.02853557653725), + SCALE_SPLIT_ANGLE(-0.02865824848413), + SCALE_SPLIT_ANGLE(-0.02885829471052), + SCALE_SPLIT_ANGLE(-0.02919723838568), + SCALE_SPLIT_ANGLE(-0.02944211103022)}, + {SCALE_SPLIT_ANGLE(-0.01614447496831), + SCALE_SPLIT_ANGLE(-0.01615499891341), + SCALE_SPLIT_ANGLE(-0.01617108844221), + SCALE_SPLIT_ANGLE(-0.01621186546981), + SCALE_SPLIT_ANGLE(-0.01625206507742), + SCALE_SPLIT_ANGLE(-0.01631666161120), + SCALE_SPLIT_ANGLE(-0.01642346009612), + SCALE_SPLIT_ANGLE(-0.01649860478938)}, + {SCALE_SPLIT_ANGLE(-0.00914774928242), + SCALE_SPLIT_ANGLE(-0.00915119051933), + SCALE_SPLIT_ANGLE(-0.00915643945336), + SCALE_SPLIT_ANGLE(-0.00916968192905), + SCALE_SPLIT_ANGLE(-0.00918265059590), + SCALE_SPLIT_ANGLE(-0.00920331384987), + SCALE_SPLIT_ANGLE(-0.00923701003194), + SCALE_SPLIT_ANGLE(-0.00926037784666)}, + {SCALE_SPLIT_ANGLE(-0.00516638066620), + SCALE_SPLIT_ANGLE(-0.00516748940572), + SCALE_SPLIT_ANGLE(-0.00516917882487), + SCALE_SPLIT_ANGLE(-0.00517342938110), + SCALE_SPLIT_ANGLE(-0.00517757609487), + SCALE_SPLIT_ANGLE(-0.00518415309489), + SCALE_SPLIT_ANGLE(-0.00519479531795), + SCALE_SPLIT_ANGLE(-0.00520211551338)}, + {SCALE_SPLIT_ANGLE(-0.00000002921563), + SCALE_SPLIT_ANGLE(-0.00000002921563), + SCALE_SPLIT_ANGLE(-0.00000002921563), + SCALE_SPLIT_ANGLE(-0.00000002921563), + SCALE_SPLIT_ANGLE(-0.00000002921563), + SCALE_SPLIT_ANGLE(-0.00000002921563), + SCALE_SPLIT_ANGLE(-0.00000002921563), + SCALE_SPLIT_ANGLE(-0.00000002921563)}, + }, + { + {SCALE_SPLIT_ANGLE(-0.78539830446243), + SCALE_SPLIT_ANGLE(-0.78539830446243), + SCALE_SPLIT_ANGLE(-0.78539830446243), + SCALE_SPLIT_ANGLE(-0.78539830446243), + SCALE_SPLIT_ANGLE(-0.78539830446243), + SCALE_SPLIT_ANGLE(-0.78539830446243), + SCALE_SPLIT_ANGLE(-0.78539830446243), + SCALE_SPLIT_ANGLE(-0.78539830446243)}, + {SCALE_SPLIT_ANGLE(-0.78143131732941), + SCALE_SPLIT_ANGLE(-0.78143173456192), + SCALE_SPLIT_ANGLE(-0.78143233060837), + SCALE_SPLIT_ANGLE(-0.78143388032913), + SCALE_SPLIT_ANGLE(-0.78143537044525), + SCALE_SPLIT_ANGLE(-0.78143775463104), + SCALE_SPLIT_ANGLE(-0.78144156932831), + SCALE_SPLIT_ANGLE(-0.78144425153732)}, + {SCALE_SPLIT_ANGLE(-0.77835690975189), + SCALE_SPLIT_ANGLE(-0.77835816144943), + SCALE_SPLIT_ANGLE(-0.77836006879807), + SCALE_SPLIT_ANGLE(-0.77836489677429), + SCALE_SPLIT_ANGLE(-0.77836954593658), + SCALE_SPLIT_ANGLE(-0.77837705612183), + SCALE_SPLIT_ANGLE(-0.77838915586472), + SCALE_SPLIT_ANGLE(-0.77839756011963)}, + {SCALE_SPLIT_ANGLE(-0.77291876077652), + SCALE_SPLIT_ANGLE(-0.77292257547379), + SCALE_SPLIT_ANGLE(-0.77292835712433), + SCALE_SPLIT_ANGLE(-0.77294307947159), + SCALE_SPLIT_ANGLE(-0.77295756340027), + SCALE_SPLIT_ANGLE(-0.77298080921173), + SCALE_SPLIT_ANGLE(-0.77301901578903), + SCALE_SPLIT_ANGLE(-0.77304589748383)}, + {SCALE_SPLIT_ANGLE(-0.76334208250046), + SCALE_SPLIT_ANGLE(-0.76335340738297), + SCALE_SPLIT_ANGLE(-0.76337069272995), + SCALE_SPLIT_ANGLE(-0.76341491937637), + SCALE_SPLIT_ANGLE(-0.76345884799957), + SCALE_SPLIT_ANGLE(-0.76353019475937), + SCALE_SPLIT_ANGLE(-0.76365041732788), + SCALE_SPLIT_ANGLE(-0.76373666524887)}, + {SCALE_SPLIT_ANGLE(-0.74662196636200), + SCALE_SPLIT_ANGLE(-0.74665397405624), + SCALE_SPLIT_ANGLE(-0.74670332670212), + SCALE_SPLIT_ANGLE(-0.74683076143265), + SCALE_SPLIT_ANGLE(-0.74695968627930), + SCALE_SPLIT_ANGLE(-0.74717408418655), + SCALE_SPLIT_ANGLE(-0.74754965305328), + SCALE_SPLIT_ANGLE(-0.74783110618591)}, + {SCALE_SPLIT_ANGLE(-0.73124068975449), + SCALE_SPLIT_ANGLE(-0.73129838705063), + SCALE_SPLIT_ANGLE(-0.73138779401779), + SCALE_SPLIT_ANGLE(-0.73162090778351), + SCALE_SPLIT_ANGLE(-0.73186063766479), + SCALE_SPLIT_ANGLE(-0.73226791620255), + SCALE_SPLIT_ANGLE(-0.73300850391388), + SCALE_SPLIT_ANGLE(-0.73358756303787)}, + {SCALE_SPLIT_ANGLE(-0.71016567945480), + SCALE_SPLIT_ANGLE(-0.71026563644409), + SCALE_SPLIT_ANGLE(-0.71042138338089), + SCALE_SPLIT_ANGLE(-0.71083360910416), + SCALE_SPLIT_ANGLE(-0.71126639842987), + SCALE_SPLIT_ANGLE(-0.71202349662781), + SCALE_SPLIT_ANGLE(-0.71347558498383), + SCALE_SPLIT_ANGLE(-0.71468466520309)}, + {SCALE_SPLIT_ANGLE(-0.68173074722290), + SCALE_SPLIT_ANGLE(-0.68189489841461), + SCALE_SPLIT_ANGLE(-0.68215286731720), + SCALE_SPLIT_ANGLE(-0.68284797668457), + SCALE_SPLIT_ANGLE(-0.68359792232513), + SCALE_SPLIT_ANGLE(-0.68496227264404), + SCALE_SPLIT_ANGLE(-0.68778377771378), + SCALE_SPLIT_ANGLE(-0.69036662578583)}, + {SCALE_SPLIT_ANGLE(-0.64424312114716), + SCALE_SPLIT_ANGLE(-0.64449483156204), + SCALE_SPLIT_ANGLE(-0.64489442110062), + SCALE_SPLIT_ANGLE(-0.64599496126175), + SCALE_SPLIT_ANGLE(-0.64722281694412), + SCALE_SPLIT_ANGLE(-0.64957284927368), + SCALE_SPLIT_ANGLE(-0.65497392416000), + SCALE_SPLIT_ANGLE(-0.66069275140762)}, + {SCALE_SPLIT_ANGLE(-0.59645897150040), + SCALE_SPLIT_ANGLE(-0.59681385755539), + SCALE_SPLIT_ANGLE(-0.59738302230835), + SCALE_SPLIT_ANGLE(-0.59898990392685), + SCALE_SPLIT_ANGLE(-0.60085391998291), + SCALE_SPLIT_ANGLE(-0.60464876890182), + SCALE_SPLIT_ANGLE(-0.61471670866013), + SCALE_SPLIT_ANGLE(-0.62811452150345)}, + {SCALE_SPLIT_ANGLE(-0.55878317356110), + SCALE_SPLIT_ANGLE(-0.55920612812042), + SCALE_SPLIT_ANGLE(-0.55988919734955), + SCALE_SPLIT_ANGLE(-0.56185036897659), + SCALE_SPLIT_ANGLE(-0.56418758630753), + SCALE_SPLIT_ANGLE(-0.56916558742523), + SCALE_SPLIT_ANGLE(-0.58402240276337), + SCALE_SPLIT_ANGLE(-0.60877454280853)}, + {SCALE_SPLIT_ANGLE(-0.51690876483917), + SCALE_SPLIT_ANGLE(-0.51739066839218), + SCALE_SPLIT_ANGLE(-0.51817417144775), + SCALE_SPLIT_ANGLE(-0.52045887708664), + SCALE_SPLIT_ANGLE(-0.52325236797333), + SCALE_SPLIT_ANGLE(-0.52947425842285), + SCALE_SPLIT_ANGLE(-0.55062580108643), + SCALE_SPLIT_ANGLE(-0.59875679016113)}, + {SCALE_SPLIT_ANGLE(-0.47171202301979), + SCALE_SPLIT_ANGLE(-0.47223755717278), + SCALE_SPLIT_ANGLE(-0.47309651970863), + SCALE_SPLIT_ANGLE(-0.47563409805298), + SCALE_SPLIT_ANGLE(-0.47880497574806), + SCALE_SPLIT_ANGLE(-0.48615178465843), + SCALE_SPLIT_ANGLE(-0.51456993818283), + SCALE_SPLIT_ANGLE(-0.61478376388550)}, + {SCALE_SPLIT_ANGLE(-0.42445346713066), + SCALE_SPLIT_ANGLE(-0.42500337958336), + SCALE_SPLIT_ANGLE(-0.42590552568436), + SCALE_SPLIT_ANGLE(-0.42859482765198), + SCALE_SPLIT_ANGLE(-0.43200704455376), + SCALE_SPLIT_ANGLE(-0.44014206528664), + SCALE_SPLIT_ANGLE(-0.47505456209183), + SCALE_SPLIT_ANGLE(-0.70435559749603)}, + {SCALE_SPLIT_ANGLE(-0.37662348151207), + SCALE_SPLIT_ANGLE(-0.37717759609222), + SCALE_SPLIT_ANGLE(-0.37808811664581), + SCALE_SPLIT_ANGLE(-0.38081312179565), + SCALE_SPLIT_ANGLE(-0.38429382443428), + SCALE_SPLIT_ANGLE(-0.39269915223122), + SCALE_SPLIT_ANGLE(-0.43061137199402), + SCALE_SPLIT_ANGLE(-0.89949661493301)}, + {SCALE_SPLIT_ANGLE(-0.32972770929337), + SCALE_SPLIT_ANGLE(-0.33026665449142), + SCALE_SPLIT_ANGLE(-0.33115166425705), + SCALE_SPLIT_ANGLE(-0.33379596471786), + SCALE_SPLIT_ANGLE(-0.33716449141502), + SCALE_SPLIT_ANGLE(-0.34525626897812), + SCALE_SPLIT_ANGLE(-0.38098806142807), + SCALE_SPLIT_ANGLE(-0.66312354803085)}, + {SCALE_SPLIT_ANGLE(-0.28508266806602), + SCALE_SPLIT_ANGLE(-0.28558865189552), + SCALE_SPLIT_ANGLE(-0.28641721606255), + SCALE_SPLIT_ANGLE(-0.28887599706650), + SCALE_SPLIT_ANGLE(-0.29197183251381), + SCALE_SPLIT_ANGLE(-0.29924651980400), + SCALE_SPLIT_ANGLE(-0.32879725098610), + SCALE_SPLIT_ANGLE(-0.45467042922974)}, + {SCALE_SPLIT_ANGLE(-0.24368351697922), + SCALE_SPLIT_ANGLE(-0.24414126574993), + SCALE_SPLIT_ANGLE(-0.24488742649555), + SCALE_SPLIT_ANGLE(-0.24707718193531), + SCALE_SPLIT_ANGLE(-0.24978290498257), + SCALE_SPLIT_ANGLE(-0.25592407584190), + SCALE_SPLIT_ANGLE(-0.27806493639946), + SCALE_SPLIT_ANGLE(-0.33706212043762)}, + {SCALE_SPLIT_ANGLE(-0.20616291463375), + SCALE_SPLIT_ANGLE(-0.20656123757362), + SCALE_SPLIT_ANGLE(-0.20720669627190), + SCALE_SPLIT_ANGLE(-0.20907410979271), + SCALE_SPLIT_ANGLE(-0.21132779121399), + SCALE_SPLIT_ANGLE(-0.21623276174068), + SCALE_SPLIT_ANGLE(-0.23178002238274), + SCALE_SPLIT_ANGLE(-0.26115795969963)}, + {SCALE_SPLIT_ANGLE(-0.17282113432884), + SCALE_SPLIT_ANGLE(-0.17315419018269), + SCALE_SPLIT_ANGLE(-0.17369027435780), + SCALE_SPLIT_ANGLE(-0.17521676421165), + SCALE_SPLIT_ANGLE(-0.17701183259487), + SCALE_SPLIT_ANGLE(-0.18074958026409), + SCALE_SPLIT_ANGLE(-0.19124273955822), + SCALE_SPLIT_ANGLE(-0.20666226744652)}, + {SCALE_SPLIT_ANGLE(-0.13066087663174), + SCALE_SPLIT_ANGLE(-0.13089761137962), + SCALE_SPLIT_ANGLE(-0.13127478957176), + SCALE_SPLIT_ANGLE(-0.13232274353504), + SCALE_SPLIT_ANGLE(-0.13350811600685), + SCALE_SPLIT_ANGLE(-0.13582547008991), + SCALE_SPLIT_ANGLE(-0.14140743017197), + SCALE_SPLIT_ANGLE(-0.14774034917355)}, + {SCALE_SPLIT_ANGLE(-0.09729288518429), + SCALE_SPLIT_ANGLE(-0.09744837880135), + SCALE_SPLIT_ANGLE(-0.09769365936518), + SCALE_SPLIT_ANGLE(-0.09835996478796), + SCALE_SPLIT_ANGLE(-0.09908770024776), + SCALE_SPLIT_ANGLE(-0.10043605417013), + SCALE_SPLIT_ANGLE(-0.10332851856947), + SCALE_SPLIT_ANGLE(-0.10610698908567)}, + {SCALE_SPLIT_ANGLE(-0.07155896723270), + SCALE_SPLIT_ANGLE(-0.07165452837944), + SCALE_SPLIT_ANGLE(-0.07180399447680), + SCALE_SPLIT_ANGLE(-0.07220225781202), + SCALE_SPLIT_ANGLE(-0.07262473553419), + SCALE_SPLIT_ANGLE(-0.07337480783463), + SCALE_SPLIT_ANGLE(-0.07485358417034), + SCALE_SPLIT_ANGLE(-0.07612710446119)}, + {SCALE_SPLIT_ANGLE(-0.05212157964706), + SCALE_SPLIT_ANGLE(-0.05217728391290), + SCALE_SPLIT_ANGLE(-0.05226380378008), + SCALE_SPLIT_ANGLE(-0.05249079316854), + SCALE_SPLIT_ANGLE(-0.05272606760263), + SCALE_SPLIT_ANGLE(-0.05313043296337), + SCALE_SPLIT_ANGLE(-0.05388086661696), + SCALE_SPLIT_ANGLE(-0.05448163300753)}, + {SCALE_SPLIT_ANGLE(-0.03767966106534), + SCALE_SPLIT_ANGLE(-0.03771083801985), + SCALE_SPLIT_ANGLE(-0.03775899857283), + SCALE_SPLIT_ANGLE(-0.03788383677602), + SCALE_SPLIT_ANGLE(-0.03801096975803), + SCALE_SPLIT_ANGLE(-0.03822424262762), + SCALE_SPLIT_ANGLE(-0.03860339894891), + SCALE_SPLIT_ANGLE(-0.03889227285981)}, + {SCALE_SPLIT_ANGLE(-0.02168159000576), + SCALE_SPLIT_ANGLE(-0.02169271185994), + SCALE_SPLIT_ANGLE(-0.02170977741480), + SCALE_SPLIT_ANGLE(-0.02175341919065), + SCALE_SPLIT_ANGLE(-0.02179697901011), + SCALE_SPLIT_ANGLE(-0.02186813205481), + SCALE_SPLIT_ANGLE(-0.02198898792267), + SCALE_SPLIT_ANGLE(-0.02207653038204)}, + {SCALE_SPLIT_ANGLE(-0.01235581189394), + SCALE_SPLIT_ANGLE(-0.01235958002508), + SCALE_SPLIT_ANGLE(-0.01236534304917), + SCALE_SPLIT_ANGLE(-0.01237995456904), + SCALE_SPLIT_ANGLE(-0.01239436771721), + SCALE_SPLIT_ANGLE(-0.01241754833609), + SCALE_SPLIT_ANGLE(-0.01245592441410), + SCALE_SPLIT_ANGLE(-0.01248297002167)}, + {SCALE_SPLIT_ANGLE(-0.00700127193704), + SCALE_SPLIT_ANGLE(-0.00700251199305), + SCALE_SPLIT_ANGLE(-0.00700440304354), + SCALE_SPLIT_ANGLE(-0.00700917467475), + SCALE_SPLIT_ANGLE(-0.00701385131106), + SCALE_SPLIT_ANGLE(-0.00702130468562), + SCALE_SPLIT_ANGLE(-0.00703346915543), + SCALE_SPLIT_ANGLE(-0.00704191112891)}, + {SCALE_SPLIT_ANGLE(-0.00395415676758), + SCALE_SPLIT_ANGLE(-0.00395455863327), + SCALE_SPLIT_ANGLE(-0.00395516911522), + SCALE_SPLIT_ANGLE(-0.00395670579746), + SCALE_SPLIT_ANGLE(-0.00395820569247), + SCALE_SPLIT_ANGLE(-0.00396058475599), + SCALE_SPLIT_ANGLE(-0.00396443624049), + SCALE_SPLIT_ANGLE(-0.00396708631888)}, + {SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068), + SCALE_SPLIT_ANGLE(-0.00000002236068)}, + }, + { + {SCALE_SPLIT_ANGLE(-0.39269906282425), + SCALE_SPLIT_ANGLE(-0.39269906282425), + SCALE_SPLIT_ANGLE(-0.39269906282425), + SCALE_SPLIT_ANGLE(-0.39269906282425), + SCALE_SPLIT_ANGLE(-0.39269906282425), + SCALE_SPLIT_ANGLE(-0.39269906282425), + SCALE_SPLIT_ANGLE(-0.39269906282425), + SCALE_SPLIT_ANGLE(-0.39269906282425)}, + {SCALE_SPLIT_ANGLE(-0.39055728912354), + SCALE_SPLIT_ANGLE(-0.39055734872818), + SCALE_SPLIT_ANGLE(-0.39055743813515), + SCALE_SPLIT_ANGLE(-0.39055764675140), + SCALE_SPLIT_ANGLE(-0.39055785536766), + SCALE_SPLIT_ANGLE(-0.39055821299553), + SCALE_SPLIT_ANGLE(-0.39055874943733), + SCALE_SPLIT_ANGLE(-0.39055910706520)}, + {SCALE_SPLIT_ANGLE(-0.38890448212624), + SCALE_SPLIT_ANGLE(-0.38890466094017), + SCALE_SPLIT_ANGLE(-0.38890489935875), + SCALE_SPLIT_ANGLE(-0.38890558481216), + SCALE_SPLIT_ANGLE(-0.38890624046326), + SCALE_SPLIT_ANGLE(-0.38890728354454), + SCALE_SPLIT_ANGLE(-0.38890898227692), + SCALE_SPLIT_ANGLE(-0.38891017436981)}, + {SCALE_SPLIT_ANGLE(-0.38599535822868), + SCALE_SPLIT_ANGLE(-0.38599589467049), + SCALE_SPLIT_ANGLE(-0.38599669933319), + SCALE_SPLIT_ANGLE(-0.38599872589111), + SCALE_SPLIT_ANGLE(-0.38600075244904), + SCALE_SPLIT_ANGLE(-0.38600397109985), + SCALE_SPLIT_ANGLE(-0.38600933551788), + SCALE_SPLIT_ANGLE(-0.38601312041283)}, + {SCALE_SPLIT_ANGLE(-0.38091570138931), + SCALE_SPLIT_ANGLE(-0.38091725111008), + SCALE_SPLIT_ANGLE(-0.38091960549355), + SCALE_SPLIT_ANGLE(-0.38092568516731), + SCALE_SPLIT_ANGLE(-0.38093173503876), + SCALE_SPLIT_ANGLE(-0.38094159960747), + SCALE_SPLIT_ANGLE(-0.38095837831497), + SCALE_SPLIT_ANGLE(-0.38097053766251)}, + {SCALE_SPLIT_ANGLE(-0.37216994166374), + SCALE_SPLIT_ANGLE(-0.37217423319817), + SCALE_SPLIT_ANGLE(-0.37218084931374), + SCALE_SPLIT_ANGLE(-0.37219804525375), + SCALE_SPLIT_ANGLE(-0.37221553921700), + SCALE_SPLIT_ANGLE(-0.37224486470222), + SCALE_SPLIT_ANGLE(-0.37229701876640), + SCALE_SPLIT_ANGLE(-0.37233671545982)}, + {SCALE_SPLIT_ANGLE(-0.36424961686134), + SCALE_SPLIT_ANGLE(-0.36425721645355), + SCALE_SPLIT_ANGLE(-0.36426901817322), + SCALE_SPLIT_ANGLE(-0.36429998278618), + SCALE_SPLIT_ANGLE(-0.36433207988739), + SCALE_SPLIT_ANGLE(-0.36438727378845), + SCALE_SPLIT_ANGLE(-0.36448964476585), + SCALE_SPLIT_ANGLE(-0.36457160115242)}, + {SCALE_SPLIT_ANGLE(-0.35356882214546), + SCALE_SPLIT_ANGLE(-0.35358169674873), + SCALE_SPLIT_ANGLE(-0.35360184311867), + SCALE_SPLIT_ANGLE(-0.35365554690361), + SCALE_SPLIT_ANGLE(-0.35371255874634), + SCALE_SPLIT_ANGLE(-0.35381379723549), + SCALE_SPLIT_ANGLE(-0.35401359200478), + SCALE_SPLIT_ANGLE(-0.35418573021889)}, + {SCALE_SPLIT_ANGLE(-0.33942580223083), + SCALE_SPLIT_ANGLE(-0.33944639563560), + SCALE_SPLIT_ANGLE(-0.33947893977165), + SCALE_SPLIT_ANGLE(-0.33956736326218), + SCALE_SPLIT_ANGLE(-0.33966410160065), + SCALE_SPLIT_ANGLE(-0.33984366059303), + SCALE_SPLIT_ANGLE(-0.34023004770279), + SCALE_SPLIT_ANGLE(-0.34060218930244)}, + {SCALE_SPLIT_ANGLE(-0.32115444540977), + SCALE_SPLIT_ANGLE(-0.32118517160416), + SCALE_SPLIT_ANGLE(-0.32123413681984), + SCALE_SPLIT_ANGLE(-0.32137045264244), + SCALE_SPLIT_ANGLE(-0.32152506709099), + SCALE_SPLIT_ANGLE(-0.32182860374451), + SCALE_SPLIT_ANGLE(-0.32256555557251), + SCALE_SPLIT_ANGLE(-0.32340887188911)}, + {SCALE_SPLIT_ANGLE(-0.29830518364906), + SCALE_SPLIT_ANGLE(-0.29834720492363), + SCALE_SPLIT_ANGLE(-0.29841497540474), + SCALE_SPLIT_ANGLE(-0.29860857129097), + SCALE_SPLIT_ANGLE(-0.29883739352226), + SCALE_SPLIT_ANGLE(-0.29931783676147), + SCALE_SPLIT_ANGLE(-0.30069103837013), + SCALE_SPLIT_ANGLE(-0.30275768041611)}, + {SCALE_SPLIT_ANGLE(-0.28050783276558), + SCALE_SPLIT_ANGLE(-0.28055709600449), + SCALE_SPLIT_ANGLE(-0.28063705563545), + SCALE_SPLIT_ANGLE(-0.28086939454079), + SCALE_SPLIT_ANGLE(-0.28115186095238), + SCALE_SPLIT_ANGLE(-0.28177401423454), + SCALE_SPLIT_ANGLE(-0.28380542993546), + SCALE_SPLIT_ANGLE(-0.28782635927200)}, + {SCALE_SPLIT_ANGLE(-0.26083284616470), + SCALE_SPLIT_ANGLE(-0.26088821887970), + SCALE_SPLIT_ANGLE(-0.26097869873047), + SCALE_SPLIT_ANGLE(-0.26124575734138), + SCALE_SPLIT_ANGLE(-0.26157894730568), + SCALE_SPLIT_ANGLE(-0.26234790682793), + SCALE_SPLIT_ANGLE(-0.26525342464447), + SCALE_SPLIT_ANGLE(-0.27373573184013)}, + {SCALE_SPLIT_ANGLE(-0.23960019648075), + SCALE_SPLIT_ANGLE(-0.23966008424759), + SCALE_SPLIT_ANGLE(-0.23975844681263), + SCALE_SPLIT_ANGLE(-0.24005250632763), + SCALE_SPLIT_ANGLE(-0.24042734503746), + SCALE_SPLIT_ANGLE(-0.24132779240608), + SCALE_SPLIT_ANGLE(-0.24525122344494), + SCALE_SPLIT_ANGLE(-0.26534584164619)}, + {SCALE_SPLIT_ANGLE(-0.21727462112904), + SCALE_SPLIT_ANGLE(-0.21733717620373), + SCALE_SPLIT_ANGLE(-0.21744027733803), + SCALE_SPLIT_ANGLE(-0.21775110065937), + SCALE_SPLIT_ANGLE(-0.21815298497677), + SCALE_SPLIT_ANGLE(-0.21914556622505), + SCALE_SPLIT_ANGLE(-0.22397416830063), + SCALE_SPLIT_ANGLE(-0.27997338771820)}, + {SCALE_SPLIT_ANGLE(-0.19442924857140), + SCALE_SPLIT_ANGLE(-0.19449259340763), + SCALE_SPLIT_ANGLE(-0.19459711015224), + SCALE_SPLIT_ANGLE(-0.19491319358349), + SCALE_SPLIT_ANGLE(-0.19532407820225), + SCALE_SPLIT_ANGLE(-0.19634953141212), + SCALE_SPLIT_ANGLE(-0.20156541466713), + SCALE_SPLIT_ANGLE(-0.33650863170624)}, + {SCALE_SPLIT_ANGLE(-0.17168678343296), + SCALE_SPLIT_ANGLE(-0.17174907028675), + SCALE_SPLIT_ANGLE(-0.17185172438622), + SCALE_SPLIT_ANGLE(-0.17216137051582), + SCALE_SPLIT_ANGLE(-0.17256210744381), + SCALE_SPLIT_ANGLE(-0.17355349659920), + SCALE_SPLIT_ANGLE(-0.17841055989265), + SCALE_SPLIT_ANGLE(-0.23922458291054)}, + {SCALE_SPLIT_ANGLE(-0.14965106546879), + SCALE_SPLIT_ANGLE(-0.14971044659615), + SCALE_SPLIT_ANGLE(-0.14980801939964), + SCALE_SPLIT_ANGLE(-0.15010000765324), + SCALE_SPLIT_ANGLE(-0.15047281980515), + SCALE_SPLIT_ANGLE(-0.15137127041817), + SCALE_SPLIT_ANGLE(-0.15533344447613), + SCALE_SPLIT_ANGLE(-0.17691853642464)}, + {SCALE_SPLIT_ANGLE(-0.12884500622749), + SCALE_SPLIT_ANGLE(-0.12889972329140), + SCALE_SPLIT_ANGLE(-0.12898920476437), + SCALE_SPLIT_ANGLE(-0.12925371527672), + SCALE_SPLIT_ANGLE(-0.12958449125290), + SCALE_SPLIT_ANGLE(-0.13035115599632), + SCALE_SPLIT_ANGLE(-0.13329000771046), + SCALE_SPLIT_ANGLE(-0.14226882159710)}, + {SCALE_SPLIT_ANGLE(-0.10966771095991), + SCALE_SPLIT_ANGLE(-0.10971628129482), + SCALE_SPLIT_ANGLE(-0.10979521274567), + SCALE_SPLIT_ANGLE(-0.11002496629953), + SCALE_SPLIT_ANGLE(-0.11030505597591), + SCALE_SPLIT_ANGLE(-0.11092507094145), + SCALE_SPLIT_ANGLE(-0.11297955363989), + SCALE_SPLIT_ANGLE(-0.11718675494194)}, + {SCALE_SPLIT_ANGLE(-0.09237615764141), + SCALE_SPLIT_ANGLE(-0.09241757541895), + SCALE_SPLIT_ANGLE(-0.09248440712690), + SCALE_SPLIT_ANGLE(-0.09267570078373), + SCALE_SPLIT_ANGLE(-0.09290252625942), + SCALE_SPLIT_ANGLE(-0.09338124096394), + SCALE_SPLIT_ANGLE(-0.09476861357689), + SCALE_SPLIT_ANGLE(-0.09691139310598)}, + {SCALE_SPLIT_ANGLE(-0.07020132243633), + SCALE_SPLIT_ANGLE(-0.07023159414530), + SCALE_SPLIT_ANGLE(-0.07027988135815), + SCALE_SPLIT_ANGLE(-0.07041461765766), + SCALE_SPLIT_ANGLE(-0.07056794315577), + SCALE_SPLIT_ANGLE(-0.07087046653032), + SCALE_SPLIT_ANGLE(-0.07161350548267), + SCALE_SPLIT_ANGLE(-0.07247892767191)}, + {SCALE_SPLIT_ANGLE(-0.05244029313326), + SCALE_SPLIT_ANGLE(-0.05246063694358), + SCALE_SPLIT_ANGLE(-0.05249277129769), + SCALE_SPLIT_ANGLE(-0.05258031189442), + SCALE_SPLIT_ANGLE(-0.05267634615302), + SCALE_SPLIT_ANGLE(-0.05285539105535), + SCALE_SPLIT_ANGLE(-0.05324416607618), + SCALE_SPLIT_ANGLE(-0.05362325906754)}, + {SCALE_SPLIT_ANGLE(-0.03864165395498), + SCALE_SPLIT_ANGLE(-0.03865438699722), + SCALE_SPLIT_ANGLE(-0.03867433220148), + SCALE_SPLIT_ANGLE(-0.03872758150101), + SCALE_SPLIT_ANGLE(-0.03878423944116), + SCALE_SPLIT_ANGLE(-0.03888526186347), + SCALE_SPLIT_ANGLE(-0.03908598423004), + SCALE_SPLIT_ANGLE(-0.03926040232182)}, + {SCALE_SPLIT_ANGLE(-0.02817477099597), + SCALE_SPLIT_ANGLE(-0.02818230539560), + SCALE_SPLIT_ANGLE(-0.02819401212037), + SCALE_SPLIT_ANGLE(-0.02822477370501), + SCALE_SPLIT_ANGLE(-0.02825672924519), + SCALE_SPLIT_ANGLE(-0.02831180207431), + SCALE_SPLIT_ANGLE(-0.02841453626752), + SCALE_SPLIT_ANGLE(-0.02849724888802)}, + {SCALE_SPLIT_ANGLE(-0.02037952840328), + SCALE_SPLIT_ANGLE(-0.02038379199803), + SCALE_SPLIT_ANGLE(-0.02039037644863), + SCALE_SPLIT_ANGLE(-0.02040746808052), + SCALE_SPLIT_ANGLE(-0.02042490057647), + SCALE_SPLIT_ANGLE(-0.02045419998467), + SCALE_SPLIT_ANGLE(-0.02050646580756), + SCALE_SPLIT_ANGLE(-0.02054643817246)}, + {SCALE_SPLIT_ANGLE(-0.01173160132021), + SCALE_SPLIT_ANGLE(-0.01173313893378), + SCALE_SPLIT_ANGLE(-0.01173550169915), + SCALE_SPLIT_ANGLE(-0.01174154412001), + SCALE_SPLIT_ANGLE(-0.01174758281559), + SCALE_SPLIT_ANGLE(-0.01175745390356), + SCALE_SPLIT_ANGLE(-0.01177425216883), + SCALE_SPLIT_ANGLE(-0.01178644038737)}, + {SCALE_SPLIT_ANGLE(-0.00668647419661), + SCALE_SPLIT_ANGLE(-0.00668699899688), + SCALE_SPLIT_ANGLE(-0.00668780226260), + SCALE_SPLIT_ANGLE(-0.00668983859941), + SCALE_SPLIT_ANGLE(-0.00669184979051), + SCALE_SPLIT_ANGLE(-0.00669508427382), + SCALE_SPLIT_ANGLE(-0.00670044496655), + SCALE_SPLIT_ANGLE(-0.00670422706753)}, + {SCALE_SPLIT_ANGLE(-0.00378898018971), + SCALE_SPLIT_ANGLE(-0.00378915364854), + SCALE_SPLIT_ANGLE(-0.00378941860981), + SCALE_SPLIT_ANGLE(-0.00379008613527), + SCALE_SPLIT_ANGLE(-0.00379074038938), + SCALE_SPLIT_ANGLE(-0.00379178440198), + SCALE_SPLIT_ANGLE(-0.00379348848946), + SCALE_SPLIT_ANGLE(-0.00379467150196)}, + {SCALE_SPLIT_ANGLE(-0.00213995948434), + SCALE_SPLIT_ANGLE(-0.00214001582935), + SCALE_SPLIT_ANGLE(-0.00214010151103), + SCALE_SPLIT_ANGLE(-0.00214031687938), + SCALE_SPLIT_ANGLE(-0.00214052735828), + SCALE_SPLIT_ANGLE(-0.00214086123742), + SCALE_SPLIT_ANGLE(-0.00214140163735), + SCALE_SPLIT_ANGLE(-0.00214177393354)}, + {SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151), + SCALE_SPLIT_ANGLE(-0.00000001210151)}, + }, +}; + +#define SCALE_CLD(a) (FL2FXCONST_CFG(a)) + +const FIXP_CFG dequantCLD_c_l[31] = { + SCALE_CLD(0.0000000316f), + SCALE_CLD(0.0056233243f), + SCALE_CLD(0.0099994997f), + SCALE_CLD(0.0177799836f), + SCALE_CLD(0.0316069759f), + SCALE_CLD(0.0561454296f), + SCALE_CLD(0.0791834071f), + SCALE_CLD(0.1115021780f), + SCALE_CLD(0.1565355062f), + SCALE_CLD(0.2184644639f), + SCALE_CLD(0.3015113473f), + SCALE_CLD(0.3698741496f), + SCALE_CLD(0.4480624795f), + SCALE_CLD(0.5336171389f), + SCALE_CLD(0.6219832301f), + SCALE_CLD(0.7071067691f), + SCALE_CLD(0.7830305696f), + SCALE_CLD(0.8457261920f), + SCALE_CLD(0.8940021992f), + SCALE_CLD(0.9290818572f), + SCALE_CLD(0.9534626007f), + SCALE_CLD(0.9758449197f), + SCALE_CLD(0.9876723289f), + SCALE_CLD(0.9937641621f), + SCALE_CLD(0.9968600869f), + SCALE_CLD(0.9984226227f), + SCALE_CLD(0.9995003939f), + SCALE_CLD(0.9998419285f), + SCALE_CLD(0.9999499917f), + SCALE_CLD(0.9999842048f), + /*SCALE_CLD(1.0000000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL)}; + +#define SC_H(a) (FL2FXCONST_CFG(a)) +#define DATA_TYPE_H FIXP_CFG + +/* not correlated tables */ +const DATA_TYPE_H H11_nc[31][8] = { + {SC_H(0.0000000316f), SC_H(0.0000000296f), SC_H(0.0000000266f), + SC_H(0.0000000190f), SC_H(0.0000000116f), SC_H(0.0000000000f), + SC_H(-0.0000000186f), SC_H(-0.0000000313f)}, + {SC_H(0.0056233243f), SC_H(0.0052728835f), SC_H(0.0047394098f), + SC_H(0.0033992692f), SC_H(0.0020946222f), SC_H(0.0000316215f), + SC_H(-0.0032913829f), SC_H(-0.0055664564f)}, + {SC_H(0.0099994997f), SC_H(0.0093815643f), SC_H(0.0084402543f), + SC_H(0.0060722125f), SC_H(0.0037622179f), SC_H(0.0000999898f), + SC_H(-0.0058238208f), SC_H(-0.0098974844f)}, + {SC_H(0.0177799836f), SC_H(0.0166974831f), SC_H(0.0150465844f), + SC_H(0.0108831404f), SC_H(0.0068073822f), SC_H(0.0003161267f), + SC_H(-0.0102626514f), SC_H(-0.0175957214f)}, + {SC_H(0.0316069759f), SC_H(0.0297324844f), SC_H(0.0268681273f), + SC_H(0.0196138974f), SC_H(0.0124691967f), SC_H(0.0009989988f), + SC_H(-0.0179452803f), SC_H(-0.0312700421f)}, + {SC_H(0.0561454296f), SC_H(0.0529650487f), SC_H(0.0480896905f), + SC_H(0.0356564634f), SC_H(0.0232860073f), SC_H(0.0031523081f), + SC_H(-0.0309029408f), SC_H(-0.0555154830f)}, + {SC_H(0.0791834071f), SC_H(0.0748842582f), SC_H(0.0682762116f), + SC_H(0.0513241664f), SC_H(0.0343080349f), SC_H(0.0062700072f), + SC_H(-0.0422340371f), SC_H(-0.0782499388f)}, + {SC_H(0.1115021780f), SC_H(0.1057924852f), SC_H(0.0969873071f), + SC_H(0.0742305145f), SC_H(0.0511277616f), SC_H(0.0124327289f), + SC_H(-0.0566596612f), SC_H(-0.1100896299f)}, + {SC_H(0.1565355062f), SC_H(0.1491366178f), SC_H(0.1376826316f), + SC_H(0.1078186408f), SC_H(0.0770794004f), SC_H(0.0245033558f), + SC_H(-0.0735980421f), SC_H(-0.1543303132f)}, + {SC_H(0.2184644639f), SC_H(0.2091979682f), SC_H(0.1947948188f), + SC_H(0.1568822265f), SC_H(0.1172478944f), SC_H(0.0477267131f), + SC_H(-0.0899507254f), SC_H(-0.2148526460f)}, + {SC_H(0.3015113473f), SC_H(0.2904391289f), SC_H(0.2731673419f), + SC_H(0.2273024023f), SC_H(0.1786239147f), SC_H(0.0909090787f), + SC_H(-0.0964255333f), SC_H(-0.2951124907f)}, + {SC_H(0.3698741496f), SC_H(0.3578284085f), SC_H(0.3390066922f), + SC_H(0.2888108492f), SC_H(0.2351117432f), SC_H(0.1368068755f), + SC_H(-0.0850296095f), SC_H(-0.3597966135f)}, + {SC_H(0.4480624795f), SC_H(0.4354025424f), SC_H(0.4156077504f), + SC_H(0.3627120256f), SC_H(0.3058823943f), SC_H(0.2007599771f), + SC_H(-0.0484020934f), SC_H(-0.4304940701f)}, + {SC_H(0.5336171389f), SC_H(0.5208471417f), SC_H(0.5008935928f), + SC_H(0.4476420581f), SC_H(0.3905044496f), SC_H(0.2847472429f), + SC_H(0.0276676007f), SC_H(-0.4966579080f)}, + {SC_H(0.6219832301f), SC_H(0.6096963882f), SC_H(0.5905415416f), + SC_H(0.5396950245f), SC_H(0.4856070578f), SC_H(0.3868631124f), + SC_H(0.1531652957f), SC_H(-0.5045361519f)}, + {SC_H(0.7071067691f), SC_H(0.6958807111f), SC_H(0.6784504056f), + SC_H(0.6326373219f), SC_H(0.5847306848f), SC_H(0.4999999702f), + SC_H(0.3205464482f), SC_H(0.0500000045f)}, + {SC_H(0.7830305696f), SC_H(0.7733067870f), SC_H(0.7582961321f), + SC_H(0.7194055915f), SC_H(0.6797705293f), SC_H(0.6131368876f), + SC_H(0.4997332692f), SC_H(0.6934193969f)}, + {SC_H(0.8457261920f), SC_H(0.8377274871f), SC_H(0.8254694939f), + SC_H(0.7942851782f), SC_H(0.7635439038f), SC_H(0.7152527571f), + SC_H(0.6567122936f), SC_H(0.8229061961f)}, + {SC_H(0.8940021992f), SC_H(0.8877248168f), SC_H(0.8781855106f), + SC_H(0.8544237614f), SC_H(0.8318918347f), SC_H(0.7992399335f), + SC_H(0.7751275301f), SC_H(0.8853276968f)}, + {SC_H(0.9290818572f), SC_H(0.9243524075f), SC_H(0.9172304869f), + SC_H(0.8998877406f), SC_H(0.8841174841f), SC_H(0.8631930947f), + SC_H(0.8565139771f), SC_H(0.9251161218f)}, + {SC_H(0.9534626007f), SC_H(0.9500193000f), SC_H(0.9448821545f), + SC_H(0.9326565266f), SC_H(0.9220023751f), SC_H(0.9090909362f), + SC_H(0.9096591473f), SC_H(0.9514584541f)}, + {SC_H(0.9758449197f), SC_H(0.9738122821f), SC_H(0.9708200693f), + SC_H(0.9639287591f), SC_H(0.9582763910f), SC_H(0.9522733092f), + SC_H(0.9553207159f), SC_H(0.9750427008f)}, + {SC_H(0.9876723289f), SC_H(0.9865267277f), SC_H(0.9848603010f), + SC_H(0.9811310172f), SC_H(0.9782302976f), SC_H(0.9754966497f), + SC_H(0.9779621363f), SC_H(0.9873252511f)}, + {SC_H(0.9937641621f), SC_H(0.9931397438f), SC_H(0.9922404289f), + SC_H(0.9902750254f), SC_H(0.9888116717f), SC_H(0.9875672460f), + SC_H(0.9891131520f), SC_H(0.9936066866f)}, + {SC_H(0.9968600869f), SC_H(0.9965277910f), SC_H(0.9960530400f), + SC_H(0.9950347543f), SC_H(0.9943022728f), SC_H(0.9937300086f), + SC_H(0.9946073294f), SC_H(0.9967863560f)}, + {SC_H(0.9984226227f), SC_H(0.9982488155f), SC_H(0.9980020523f), + SC_H(0.9974802136f), SC_H(0.9971146584f), SC_H(0.9968476892f), + SC_H(0.9973216057f), SC_H(0.9983873963f)}, + {SC_H(0.9995003939f), SC_H(0.9994428754f), SC_H(0.9993617535f), + SC_H(0.9991930723f), SC_H(0.9990783334f), SC_H(0.9990010262f), + SC_H(0.9991616607f), SC_H(0.9994897842f)}, + {SC_H(0.9998419285f), SC_H(0.9998232722f), SC_H(0.9997970462f), + SC_H(0.9997430444f), SC_H(0.9997069836f), SC_H(0.9996838570f), + SC_H(0.9997364879f), SC_H(0.9998386502f)}, + {SC_H(0.9999499917f), SC_H(0.9999440312f), SC_H(0.9999356270f), + SC_H(0.9999184012f), SC_H(0.9999070764f), SC_H(0.9998999834f), + SC_H(0.9999169707f), SC_H(0.9999489784f)}, + {SC_H(0.9999842048f), SC_H(0.9999822974f), SC_H(0.9999796152f), + SC_H(0.9999741912f), SC_H(0.9999706149f), SC_H(0.9999684095f), + SC_H(0.9999738336f), SC_H(0.9999839067f)}, + /* { SC_H( 1.0000000000f), SC_H( 1.0000000000f), SC_H( 1.0000000000f), + SC_H( 1.0000000000f), SC_H( 1.0000000000f), SC_H( 1.0000000000f), + SC_H( 1.0000000000f), SC_H( 1.0000000000f)} */ + {FX_DBL2FX_CFG(MAXVAL_DBL), FX_DBL2FX_CFG(MAXVAL_DBL), + FX_DBL2FX_CFG(MAXVAL_DBL), FX_DBL2FX_CFG(MAXVAL_DBL), + FX_DBL2FX_CFG(MAXVAL_DBL), FX_DBL2FX_CFG(MAXVAL_DBL), + FX_DBL2FX_CFG(MAXVAL_DBL), FX_DBL2FX_CFG(MAXVAL_DBL)}}; +const DATA_TYPE_H H12_nc[31][8] = { + {SC_H(0.0000000000f), SC_H(0.0000000110f), SC_H(0.0000000171f), + SC_H(0.0000000253f), SC_H(0.0000000294f), SC_H(0.0000000316f), + SC_H(0.0000000256f), SC_H(0.0000000045f)}, + {SC_H(0.0000000000f), SC_H(0.0019540924f), SC_H(0.0030265113f), + SC_H(0.0044795922f), SC_H(0.0052186525f), SC_H(0.0056232354f), + SC_H(0.0045594489f), SC_H(0.0007977085f)}, + {SC_H(0.0000000000f), SC_H(0.0034606720f), SC_H(0.0053620986f), + SC_H(0.0079446984f), SC_H(0.0092647560f), SC_H(0.0099989995f), + SC_H(0.0081285369f), SC_H(0.0014247064f)}, + {SC_H(0.0000000000f), SC_H(0.0061091618f), SC_H(0.0094724922f), + SC_H(0.0140600521f), SC_H(0.0164252054f), SC_H(0.0177771728f), + SC_H(0.0145191532f), SC_H(0.0025531140f)}, + {SC_H(0.0000000000f), SC_H(0.0107228858f), SC_H(0.0166464616f), + SC_H(0.0247849934f), SC_H(0.0290434174f), SC_H(0.0315911844f), + SC_H(0.0260186065f), SC_H(0.0046027615f)}, + {SC_H(0.0000000000f), SC_H(0.0186282862f), SC_H(0.0289774220f), + SC_H(0.0433696397f), SC_H(0.0510888547f), SC_H(0.0560568646f), + SC_H(0.0468755551f), SC_H(0.0083869267f)}, + {SC_H(0.0000000000f), SC_H(0.0257363543f), SC_H(0.0401044972f), + SC_H(0.0602979437f), SC_H(0.0713650510f), SC_H(0.0789347738f), + SC_H(0.0669798329f), SC_H(0.0121226767f)}, + {SC_H(0.0000000000f), SC_H(0.0352233723f), SC_H(0.0550108925f), + SC_H(0.0832019597f), SC_H(0.0990892947f), SC_H(0.1108068749f), + SC_H(0.0960334241f), SC_H(0.0176920593f)}, + {SC_H(0.0000000000f), SC_H(0.0475566536f), SC_H(0.0744772255f), + SC_H(0.1134835035f), SC_H(0.1362429112f), SC_H(0.1546057910f), + SC_H(0.1381545961f), SC_H(0.0261824392f)}, + {SC_H(0.0000000000f), SC_H(0.0629518181f), SC_H(0.0989024863f), + SC_H(0.1520351619f), SC_H(0.1843357086f), SC_H(0.2131874412f), + SC_H(0.1990868896f), SC_H(0.0395608991f)}, + {SC_H(0.0000000000f), SC_H(0.0809580907f), SC_H(0.1276271492f), + SC_H(0.1980977356f), SC_H(0.2429044843f), SC_H(0.2874797881f), + SC_H(0.2856767476f), SC_H(0.0617875643f)}, + {SC_H(0.0000000000f), SC_H(0.0936254337f), SC_H(0.1479234397f), + SC_H(0.2310739607f), SC_H(0.2855334580f), SC_H(0.3436433673f), + SC_H(0.3599678576f), SC_H(0.0857512727f)}, + {SC_H(0.0000000000f), SC_H(0.1057573780f), SC_H(0.1674221754f), + SC_H(0.2630588412f), SC_H(0.3274079263f), SC_H(0.4005688727f), + SC_H(0.4454404712f), SC_H(0.1242370531f)}, + {SC_H(0.0000000000f), SC_H(0.1160409302f), SC_H(0.1839915067f), + SC_H(0.2904545665f), SC_H(0.3636667728f), SC_H(0.4512939751f), + SC_H(0.5328993797f), SC_H(0.1951362640f)}, + {SC_H(0.0000000000f), SC_H(0.1230182052f), SC_H(0.1952532977f), + SC_H(0.3091802597f), SC_H(0.3886501491f), SC_H(0.4870318770f), + SC_H(0.6028295755f), SC_H(0.3637395203f)}, + {SC_H(0.0000000000f), SC_H(0.1254990250f), SC_H(0.1992611140f), + SC_H(0.3158638775f), SC_H(0.3976053298f), SC_H(0.5000000000f), + SC_H(0.6302776933f), SC_H(0.7053368092f)}, + {SC_H(0.0000000000f), SC_H(0.1230182052f), SC_H(0.1952533126f), + SC_H(0.3091802597f), SC_H(0.3886501491f), SC_H(0.4870319068f), + SC_H(0.6028295755f), SC_H(0.3637394905f)}, + {SC_H(0.0000000000f), SC_H(0.1160409302f), SC_H(0.1839915216f), + SC_H(0.2904545665f), SC_H(0.3636668026f), SC_H(0.4512939751f), + SC_H(0.5328993797f), SC_H(0.1951362044f)}, + {SC_H(0.0000000000f), SC_H(0.1057573855f), SC_H(0.1674221754f), + SC_H(0.2630588710f), SC_H(0.3274079263f), SC_H(0.4005688727f), + SC_H(0.4454405010f), SC_H(0.1242370382f)}, + {SC_H(0.0000000000f), SC_H(0.0936254337f), SC_H(0.1479234397f), + SC_H(0.2310739607f), SC_H(0.2855334580f), SC_H(0.3436433673f), + SC_H(0.3599678576f), SC_H(0.0857512653f)}, + {SC_H(0.0000000000f), SC_H(0.0809580907f), SC_H(0.1276271492f), + SC_H(0.1980977207f), SC_H(0.2429044843f), SC_H(0.2874797881f), + SC_H(0.2856767476f), SC_H(0.0617875606f)}, + {SC_H(0.0000000000f), SC_H(0.0629518107f), SC_H(0.0989024863f), + SC_H(0.1520351619f), SC_H(0.1843357235f), SC_H(0.2131874412f), + SC_H(0.1990868896f), SC_H(0.0395609401f)}, + {SC_H(0.0000000000f), SC_H(0.0475566462f), SC_H(0.0744772255f), + SC_H(0.1134835184f), SC_H(0.1362429112f), SC_H(0.1546057761f), + SC_H(0.1381545961f), SC_H(0.0261824802f)}, + {SC_H(0.0000000000f), SC_H(0.0352233797f), SC_H(0.0550108962f), + SC_H(0.0832019448f), SC_H(0.0990892798f), SC_H(0.1108068526f), + SC_H(0.0960334465f), SC_H(0.0176920686f)}, + {SC_H(0.0000000000f), SC_H(0.0257363524f), SC_H(0.0401044935f), + SC_H(0.0602979474f), SC_H(0.0713650808f), SC_H(0.0789347589f), + SC_H(0.0669797957f), SC_H(0.0121226516f)}, + {SC_H(0.0000000000f), SC_H(0.0186282881f), SC_H(0.0289774258f), + SC_H(0.0433696248f), SC_H(0.0510888547f), SC_H(0.0560568906f), + SC_H(0.0468755886f), SC_H(0.0083869714f)}, + {SC_H(0.0000000000f), SC_H(0.0107228830f), SC_H(0.0166464727f), + SC_H(0.0247849822f), SC_H(0.0290434249f), SC_H(0.0315911621f), + SC_H(0.0260186475f), SC_H(0.0046027377f)}, + {SC_H(0.0000000000f), SC_H(0.0061091576f), SC_H(0.0094724894f), + SC_H(0.0140600465f), SC_H(0.0164251942f), SC_H(0.0177771524f), + SC_H(0.0145191504f), SC_H(0.0025530567f)}, + {SC_H(0.0000000000f), SC_H(0.0034606743f), SC_H(0.0053620976f), + SC_H(0.0079446994f), SC_H(0.0092647672f), SC_H(0.0099990256f), + SC_H(0.0081285043f), SC_H(0.0014247177f)}, + {SC_H(0.0000000000f), SC_H(0.0019540912f), SC_H(0.0030265225f), + SC_H(0.0044795908f), SC_H(0.0052186381f), SC_H(0.0056232223f), + SC_H(0.0045594289f), SC_H(0.0007977359f)}, + {SC_H(0.0000000000f), SC_H(0.0000000149f), SC_H(0.0000000298f), + SC_H(0.0000000298f), SC_H(0.0000000000f), SC_H(0.0000000596f), + SC_H(0.0000000000f), SC_H(0.0000000000f)}}; + +/* + for (i=0; i<31; i++) { + cld = dequantCLD[i]; + val = (float)(FDKexp(cld/dbe)/(1+FDKexp(cld/dbe))); + val = (float)(dbe*FDKlog(val)); + } +*/ +#define SCALE_CLD_C1C2(a) (FL2FXCONST_DBL(a / (float)(1 << SF_CLD_C1C2))) +const FIXP_DBL dequantCLD_c1[31] = {SCALE_CLD_C1C2(-1.5000000000000000e+002f), + SCALE_CLD_C1C2(-4.5000137329101563e+001f), + SCALE_CLD_C1C2(-4.0000434875488281e+001f), + SCALE_CLD_C1C2(-3.5001373291015625e+001f), + SCALE_CLD_C1C2(-3.0004341125488281e+001f), + SCALE_CLD_C1C2(-2.5013711929321289e+001f), + SCALE_CLD_C1C2(-2.2027315139770508e+001f), + SCALE_CLD_C1C2(-1.9054332733154297e+001f), + SCALE_CLD_C1C2(-1.6107742309570313e+001f), + SCALE_CLD_C1C2(-1.3212384223937988e+001f), + SCALE_CLD_C1C2(-1.0413927078247070e+001f), + SCALE_CLD_C1C2(-8.6389207839965820e+000f), + SCALE_CLD_C1C2(-6.9732279777526855e+000f), + SCALE_CLD_C1C2(-5.4554042816162109e+000f), + SCALE_CLD_C1C2(-4.1244258880615234e+000f), + SCALE_CLD_C1C2(-3.0102999210357666e+000f), + SCALE_CLD_C1C2(-2.1244258880615234e+000f), + SCALE_CLD_C1C2(-1.4554045200347900e+000f), + SCALE_CLD_C1C2(-9.7322785854339600e-001f), + SCALE_CLD_C1C2(-6.3892036676406860e-001f), + SCALE_CLD_C1C2(-4.1392669081687927e-001f), + SCALE_CLD_C1C2(-2.1238386631011963e-001f), + SCALE_CLD_C1C2(-1.0774217545986176e-001f), + SCALE_CLD_C1C2(-5.4333221167325974e-002f), + SCALE_CLD_C1C2(-2.7315950021147728e-002f), + SCALE_CLD_C1C2(-1.3711934909224510e-002f), + SCALE_CLD_C1C2(-4.3406565673649311e-003f), + SCALE_CLD_C1C2(-1.3732088264077902e-003f), + SCALE_CLD_C1C2(-4.3438826105557382e-004f), + SCALE_CLD_C1C2(-1.3745666365139186e-004f), + SCALE_CLD_C1C2(0.0000000000000000e+000f)}; + +/* sac_stp */ +/* none scaled */ +const FIXP_CFG BP__FDK[] = {FL2FXCONST_CFG(0.73919999599457), + FL2FXCONST_CFG(0.97909998893738), + FL2FXCONST_CFG(0.99930000305176)}; + +/* scaled with 26 bits */ +const FIXP_CFG BP_GF__FDK[] = { + FL2FXCONST_CFG(0.00000000643330), FL2FXCONST_CFG(0.00004396850232), + FL2FXCONST_CFG(0.00087456948552), FL2FXCONST_CFG(0.00474648220243), + FL2FXCONST_CFG(0.01717987244800), FL2FXCONST_CFG(0.04906742491073), + FL2FXCONST_CFG(0.10569518656729), FL2FXCONST_CFG(0.21165767592653), + FL2FXCONST_CFG(0.36036762478024), FL2FXCONST_CFG(0.59894182766948), + FL2FXCONST_CFG(0.81641678929129), FL2FXCONST_CFG(0.97418481133397), + FL2FXCONST_CFG(0.99575411610845), FL2FXCONST_CFG(0.88842666281361), + FL2FXCONST_CFG(0.79222317063736), FL2FXCONST_CFG(0.70828604318604), + FL2FXCONST_CFG(0.66395054816338), FL2FXCONST_CFG(0.64633739516952), + FL2FXCONST_CFG(0.66098278185255)}; + +/* sac_bitdec */ +const INT samplingFreqTable[16] = {96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, + 7350, 0, 0, 0}; + +const UCHAR freqResTable[] = {0, 28, 20, 14, 10, 7, 5, 4}; + +const UCHAR freqResTable_LD[] = {0, 23, 15, 12, 9, 7, 5, 4}; + +const UCHAR tempShapeChanTable[][8] = {{5, 5, 4, 6, 6, 4, 4, 2}, + {5, 5, 5, 7, 7, 4, 4, 2}}; + +const TREEPROPERTIES treePropertyTable[] = { + {1, 6, 5, 0, {0, 0, 0, 0, 1}}, {1, 6, 5, 0, {0, 0, 1, 0, 0}}, + {2, 6, 3, 1, {1, 0, 0, 0, 0}}, {2, 8, 5, 1, {1, 0, 0, 0, 0}}, + {2, 8, 5, 1, {1, 0, 0, 0, 0}}, {6, 8, 2, 0, {0, 0, 0, 0, 0}}, + {6, 8, 2, 0, {0, 0, 0, 0, 0}}, {1, 2, 1, 0, {0, 0, 0, 0, 0}}}; + +const SCHAR kernels_4_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; + +const SCHAR kernels_5_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; + +const SCHAR kernels_7_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}; + +const SCHAR kernels_10_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; + +const SCHAR kernels_14_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 0, 0, 1, 1, 2, 3, 4, 4, 5, 6, 6, 7, 7, 8, 8, + 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13}; + +const SCHAR kernels_20_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 14, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19}; + +const SCHAR kernels_28_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 21, 22, 22, 22, 23, + 23, 23, 23, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27}; + +const SCHAR kernels_4_to_64[MAX_HYBRID_BANDS] = { + 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; + +const SCHAR kernels_5_to_64[MAX_HYBRID_BANDS] = { + 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; + +const SCHAR kernels_7_to_64[MAX_HYBRID_BANDS] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}; + +const SCHAR kernels_9_to_64[MAX_HYBRID_BANDS] = { + 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; + +const SCHAR kernels_12_to_64[MAX_HYBRID_BANDS] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}; + +const SCHAR kernels_15_to_64[MAX_HYBRID_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + +const SCHAR kernels_23_to_64[MAX_HYBRID_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, 14, 14, 15, + 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}; + +const UCHAR mapping_15_to_23[MAX_PARAMETER_BANDS_LD] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14}; + +const UCHAR mapping_12_to_23[MAX_PARAMETER_BANDS_LD] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11}; + +const UCHAR mapping_9_to_23[MAX_PARAMETER_BANDS_LD] = { + 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8}; + +const UCHAR mapping_7_to_23[MAX_PARAMETER_BANDS_LD] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6}; + +const UCHAR mapping_5_to_23[MAX_PARAMETER_BANDS_LD] = { + 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4}; + +const UCHAR mapping_4_to_23[MAX_PARAMETER_BANDS_LD] = { + 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3}; + +const FIXP_CFG clipGainTable__FDK[] = { + /*CLIP_PROTECT_GAIN_0(1.000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL), + CLIP_PROTECT_GAIN_1(1.189207f), + CLIP_PROTECT_GAIN_1(1.414213f), + CLIP_PROTECT_GAIN_1(1.681792f), + /*CLIP_PROTECT_GAIN_1(2.000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL), + CLIP_PROTECT_GAIN_2(2.378414f), + CLIP_PROTECT_GAIN_2(2.828427f), + /*CLIP_PROTECT_GAIN_2(4.000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL)}; + +const UCHAR clipGainSFTable__FDK[] = {0, 1, 1, 1, 1, 2, 2, 2}; + +const UCHAR pbStrideTable[] = {1, 2, 5, 28}; + +const int smgTimeTable[] = {64, 128, 256, 512}; + +/* table is scaled by factor 0.5 */ +const FIXP_CFG envShapeDataTable__FDK[5][2] = { + {FL2FXCONST_CFG(0.25000000000000f), FL2FXCONST_CFG(0.25000000000000f)}, + {FL2FXCONST_CFG(0.35355339059327f), FL2FXCONST_CFG(0.31498026247372f)}, + {FL2FXCONST_CFG(0.50000000000000f), FL2FXCONST_CFG(0.39685026299205f)}, + {FL2FXCONST_CFG(0.70710678118655f), FL2FXCONST_CFG(0.50000000000000f)}, + {/*FL2FXCONST_CFG( 1.00000000000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL), + FL2FXCONST_CFG(0.62996052494744f)}}; + +/* sac_calcM1andM2 */ +const SCHAR row2channelSTP[][MAX_M2_INPUT] = {{0, 1}, {0, 3}, {0, 2}, {0, 4}, + {0, 4}, {0, 2}, {-1, 2}, {0, 1}}; + +const SCHAR row2channelGES[][MAX_M2_INPUT] = {{0, 1}, {0, 3}, {0, 3}, {0, 5}, + {0, 5}, {0, 2}, {-1, 2}, {0, 1}}; + +const SCHAR row2residual[][MAX_M2_INPUT] = {{-1, 0}, {-1, 0}, {-1, -1}, + {-1, -1}, {-1, -1}, {-1, -1}, + {-1, -1}, {-1, 0}}; + +/******************************************************************************* + Functionname: sac_getCLDValues + ******************************************************************************* + + Description: Get CLD values from table index. + + Arguments: + index: Table index + *cu, *cl : Pointer to locations where resulting values will be written to. + + Return: nothing + +*******************************************************************************/ +void SpatialDequantGetCLDValues(int index, FIXP_DBL* cu, FIXP_DBL* cl) { + *cu = FX_CFG2FX_DBL(dequantCLD_c_l[index]); + *cl = FX_CFG2FX_DBL(dequantCLD_c_l[31 - 1 - index]); +} + +void SpatialDequantGetCLD2Values(int idx, FIXP_DBL* x) { + *x = FX_CFG2FX_DBL(dequantCLD__FDK[idx]); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_rom.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_rom.h new file mode 100644 index 0000000000000..d31785667daeb --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_rom.h @@ -0,0 +1,216 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec tables + +*******************************************************************************/ + +#ifndef SAC_ROM_H +#define SAC_ROM_H + +#include "FDK_archdef.h" +#include "sac_dec_interface.h" + +#include "huff_nodes.h" +#include "sac_bitdec.h" +#include "machine_type.h" + +/* Global ROM table data type: */ +#define FIXP_CFG FIXP_DBL +#define FX_CFG2FX_DBL +#define FX_CFG2FX_SGL FX_DBL2FX_SGL +#define CFG(a) FIXP_DBL(a) +#define FL2FXCONST_CFG FL2FXCONST_DBL +#define FX_DBL2FX_CFG(x) ((FIXP_DBL)(x)) + +/* others */ +#define SCALE_INV_ICC (2) +#define G_dd_SCALE (2) + +#define QCC_SCALE 1 +#define M1M2_DATA FIXP_DBL +#define M1M2_CDATA FIXP_DBL +#define M1M2_CDATA2FX_DBL(a) (a) +#define FX_DBL2M1M2_CDATA(a) (a) + +#define CLIP_PROTECT_GAIN_0(x) FL2FXCONST_CFG(((x) / (float)(1 << 0))) +#define CLIP_PROTECT_GAIN_1(x) FL2FXCONST_CFG(((x) / (float)(1 << 1))) +#define CLIP_PROTECT_GAIN_2(x) FL2FXCONST_CFG(((x) / (float)(1 << 2))) + +#define SF_CLD_C1C2 (9) + +extern const FIXP_CFG dequantCPC__FDK[]; +extern const FIXP_CFG dequantICC__FDK[8]; +extern const FIXP_CFG dequantCLD__FDK[31]; + +#define IPD_SCALE (5) +#define PI__IPD (FL2FXCONST_DBL(3.1415926535897932f / (float)(1 << IPD_SCALE))) +/* Define for PI*2 for better precision in SpatialDecApplyPhase() */ +#define PIx2__IPD \ + (FL2FXCONST_DBL(3.1415926535897932f / (float)(1 << (IPD_SCALE - 1)))) + +extern const FIXP_CFG dequantIPD__FDK[16]; +extern const FIXP_DBL dequantIPD_CLD_ICC_splitAngle__FDK[15][31][8]; + +extern const FIXP_CFG H11_nc[31][8]; +extern const FIXP_CFG H12_nc[31][8]; + +extern const FIXP_DBL dequantCLD_c1[31]; + +extern const FIXP_CFG BP__FDK[]; +extern const FIXP_CFG BP_GF__FDK[]; +extern const SCHAR row2channelSTP[][MAX_M2_INPUT]; + +/* sac_bitdec */ +extern const INT samplingFreqTable[16]; +extern const UCHAR freqResTable[]; +extern const UCHAR freqResTable_LD[]; +extern const UCHAR tempShapeChanTable[2][8]; +extern const TREEPROPERTIES treePropertyTable[]; + +extern const SCHAR kernels_4_to_71[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_5_to_71[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_7_to_71[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_10_to_71[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_14_to_71[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_20_to_71[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_28_to_71[MAX_HYBRID_BANDS]; + +extern const UCHAR mapping_4_to_28[MAX_PARAMETER_BANDS]; +extern const UCHAR mapping_5_to_28[MAX_PARAMETER_BANDS]; +extern const UCHAR mapping_7_to_28[MAX_PARAMETER_BANDS]; +extern const UCHAR mapping_10_to_28[MAX_PARAMETER_BANDS]; +extern const UCHAR mapping_14_to_28[MAX_PARAMETER_BANDS]; +extern const UCHAR mapping_20_to_28[MAX_PARAMETER_BANDS]; +extern const SCHAR kernels_4_to_64[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_5_to_64[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_7_to_64[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_9_to_64[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_12_to_64[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_15_to_64[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_23_to_64[MAX_HYBRID_BANDS]; + +extern const UCHAR mapping_15_to_23[MAX_PARAMETER_BANDS_LD]; +extern const UCHAR mapping_12_to_23[MAX_PARAMETER_BANDS_LD]; +extern const UCHAR mapping_9_to_23[MAX_PARAMETER_BANDS_LD]; +extern const UCHAR mapping_7_to_23[MAX_PARAMETER_BANDS_LD]; +extern const UCHAR mapping_5_to_23[MAX_PARAMETER_BANDS_LD]; +extern const UCHAR mapping_4_to_23[MAX_PARAMETER_BANDS_LD]; + +extern const FIXP_CFG clipGainTable__FDK[]; +extern const UCHAR clipGainSFTable__FDK[]; + +extern const UCHAR pbStrideTable[]; +extern const int smgTimeTable[]; + +extern const FIXP_CFG envShapeDataTable__FDK[5][2]; +extern const SCHAR row2channelGES[][MAX_M2_INPUT]; + +/* sac_calcM1andM2 */ +extern const SCHAR row2residual[][MAX_M2_INPUT]; + +void SpatialDequantGetCLDValues(int index, FIXP_DBL* cu, FIXP_DBL* cl); + +void SpatialDequantGetCLD2Values(int index, FIXP_DBL* x); + +/* External helper functions */ +static inline int SacGetHybridSubbands(int qmfSubbands) { + return qmfSubbands - MAX_QMF_BANDS_TO_HYBRID + 10; +} + +#endif /* SAC_ROM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_smoothing.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_smoothing.cpp new file mode 100644 index 0000000000000..bee655184bd3d --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_smoothing.cpp @@ -0,0 +1,295 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec parameter smoothing + +*******************************************************************************/ + +#include "sac_dec.h" +#include "sac_bitdec.h" +#include "sac_smoothing.h" +#include "sac_rom.h" + +/******************************************************************************* + Functionname: calcFilterCoeff + ******************************************************************************* + + Description: + + Arguments: + + Input: + + Output: + + +*******************************************************************************/ +static FIXP_DBL calcFilterCoeff__FDK(spatialDec *self, int ps, + const SPATIAL_BS_FRAME *frame) { + int dSlots; + FIXP_DBL delta; + + dSlots = frame->paramSlot[ps] - self->smoothState->prevParamSlot; + + if (dSlots <= 0) { + dSlots += self->timeSlots; + } + + delta = fDivNorm(dSlots, self->smgTime[ps]); + + return delta; +} + +/******************************************************************************* + Functionname: getSmoothOnOff + ******************************************************************************* + + Description: + + Arguments: + + Input: + + Output: + + +*******************************************************************************/ +static int getSmoothOnOff(spatialDec *self, int ps, int pb) { + int smoothBand = 0; + + smoothBand = self->smgData[ps][pb]; + + return smoothBand; +} + +void SpatialDecSmoothM1andM2(spatialDec *self, const SPATIAL_BS_FRAME *frame, + int ps) { + FIXP_DBL delta__FDK; + FIXP_DBL one_minus_delta__FDK; + + int pb, row, col; + int residualBands = 0; + + if (self->residualCoding) { + int i; + int boxes = self->numOttBoxes; + for (i = 0; i < boxes; i++) { + if (self->residualBands[i] > residualBands) { + residualBands = self->residualBands[i]; + } + } + } + + delta__FDK = calcFilterCoeff__FDK(self, ps, frame); + if (delta__FDK == /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL) + one_minus_delta__FDK = FL2FXCONST_DBL(0.0f); + else if (delta__FDK == FL2FXCONST_DBL(0.0f)) + one_minus_delta__FDK = /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL; + else + one_minus_delta__FDK = (FL2FXCONST_DBL(0.5f) - (delta__FDK >> 1)) << 1; + + for (pb = 0; pb < self->numParameterBands; pb++) { + int smoothBand; + + smoothBand = getSmoothOnOff(self, ps, pb); + + if (smoothBand && (pb >= residualBands)) { + for (row = 0; row < self->numM2rows; row++) { + for (col = 0; col < self->numVChannels; col++) { + self->M2Real__FDK[row][col][pb] = + ((fMultDiv2(delta__FDK, self->M2Real__FDK[row][col][pb]) + + fMultDiv2(one_minus_delta__FDK, + self->M2RealPrev__FDK[row][col][pb])) + << 1); + if (0 || (self->phaseCoding == 3)) { + self->M2Imag__FDK[row][col][pb] = + ((fMultDiv2(delta__FDK, self->M2Imag__FDK[row][col][pb]) + + fMultDiv2(one_minus_delta__FDK, + self->M2ImagPrev__FDK[row][col][pb])) + << 1); + } + } + } + } + } + self->smoothState->prevParamSlot = frame->paramSlot[ps]; +} + +/* init states */ +void initParameterSmoothing(spatialDec *self) { + self->smoothState->prevParamSlot = 0; +} + +void SpatialDecSmoothOPD(spatialDec *self, const SPATIAL_BS_FRAME *frame, + int ps) { + int pb; + int dSlots; + FIXP_DBL delta__FDK; + FIXP_DBL one_minus_delta__FDK; + FIXP_DBL *phaseLeftSmooth__FDK = self->smoothState->opdLeftState__FDK; + FIXP_DBL *phaseRightSmooth__FDK = self->smoothState->opdRightState__FDK; + int quantCoarse; + + quantCoarse = frame->IPDLosslessData[0].bsQuantCoarseXXX[ps]; + + if (frame->OpdSmoothingMode == 0) { + FDKmemcpy(phaseLeftSmooth__FDK, self->PhaseLeft__FDK, + self->numParameterBands * sizeof(FIXP_DBL)); + FDKmemcpy(phaseRightSmooth__FDK, self->PhaseRight__FDK, + self->numParameterBands * sizeof(FIXP_DBL)); + } else { + if (ps == 0) { + dSlots = frame->paramSlot[ps] + 1; + } else { + dSlots = frame->paramSlot[ps] - frame->paramSlot[ps - 1]; + } + + delta__FDK = (FIXP_DBL)((INT)(FL2FXCONST_DBL(0.0078125f)) * dSlots); + + if (delta__FDK == (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/) + one_minus_delta__FDK = FL2FXCONST_DBL(0.0f); + else if (delta__FDK == FL2FXCONST_DBL(0.0f)) + one_minus_delta__FDK = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/; + else + one_minus_delta__FDK = (FL2FXCONST_DBL(0.5f) - (delta__FDK >> 1)) << 1; + + for (pb = 0; pb < self->numParameterBands; pb++) { + FIXP_DBL tmpL, tmpR, tmp; + + tmpL = self->PhaseLeft__FDK[pb]; + tmpR = self->PhaseRight__FDK[pb]; + + while (tmpL > phaseLeftSmooth__FDK[pb] + PI__IPD) tmpL -= PI__IPD << 1; + while (tmpL < phaseLeftSmooth__FDK[pb] - PI__IPD) tmpL += PI__IPD << 1; + while (tmpR > phaseRightSmooth__FDK[pb] + PI__IPD) tmpR -= PI__IPD << 1; + while (tmpR < phaseRightSmooth__FDK[pb] - PI__IPD) tmpR += PI__IPD << 1; + + phaseLeftSmooth__FDK[pb] = + fMult(delta__FDK, tmpL) + + fMult(one_minus_delta__FDK, phaseLeftSmooth__FDK[pb]); + phaseRightSmooth__FDK[pb] = + fMult(delta__FDK, tmpR) + + fMult(one_minus_delta__FDK, phaseRightSmooth__FDK[pb]); + + tmp = (((tmpL >> 1) - (tmpR >> 1)) - ((phaseLeftSmooth__FDK[pb] >> 1) - + (phaseRightSmooth__FDK[pb] >> 1))) + << 1; + while (tmp > PI__IPD) tmp -= PI__IPD << 1; + while (tmp < -PI__IPD) tmp += PI__IPD << 1; + if (fixp_abs(tmp) > fMult((quantCoarse ? FL2FXCONST_DBL(50.f / 180.f) + : FL2FXCONST_DBL(25.f / 180.f)), + PI__IPD)) { + phaseLeftSmooth__FDK[pb] = tmpL; + phaseRightSmooth__FDK[pb] = tmpR; + } + + while (phaseLeftSmooth__FDK[pb] > PI__IPD << 1) + phaseLeftSmooth__FDK[pb] -= PI__IPD << 1; + while (phaseLeftSmooth__FDK[pb] < (FIXP_DBL)0) + phaseLeftSmooth__FDK[pb] += PI__IPD << 1; + while (phaseRightSmooth__FDK[pb] > PI__IPD << 1) + phaseRightSmooth__FDK[pb] -= PI__IPD << 1; + while (phaseRightSmooth__FDK[pb] < (FIXP_DBL)0) + phaseRightSmooth__FDK[pb] += PI__IPD << 1; + + self->PhaseLeft__FDK[pb] = phaseLeftSmooth__FDK[pb]; + self->PhaseRight__FDK[pb] = phaseRightSmooth__FDK[pb]; + } + } + return; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_smoothing.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_smoothing.h new file mode 100644 index 0000000000000..fdf3f5bd71982 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_smoothing.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec parameter smoothing + +*******************************************************************************/ + +#ifndef SAC_SMOOTHING_H +#define SAC_SMOOTHING_H + +#include "sac_dec.h" + +void initParameterSmoothing(spatialDec *self); +void SpatialDecSmoothM1andM2(spatialDec *self, const SPATIAL_BS_FRAME *frame, + int ps); +void SpatialDecSmoothOPD(spatialDec *self, const SPATIAL_BS_FRAME *frame, + int ps); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_stp.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_stp.cpp new file mode 100644 index 0000000000000..0e6affa8b3fa8 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_stp.cpp @@ -0,0 +1,567 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec subband processing + +*******************************************************************************/ + +#include "sac_stp.h" +#include "sac_calcM1andM2.h" +#include "sac_bitdec.h" +#include "FDK_matrixCalloc.h" +#include "sac_rom.h" + +#define SF_FREQ_DOMAIN_HEADROOM (2 * (1)) + +#define BP_GF_START 6 +#define BP_GF_SIZE 25 +#define HP_SIZE 9 +#define STP_UPDATE_ENERGY_RATE 32 + +#define SF_WET 5 +#define SF_DRY \ + 3 /* SF_DRY == 2 would produce good conformance test results as well */ +#define SF_DRY_NRG \ + (4 - 1) /* 8.495f = sum(BP_GF__FDK[i]) \ + i=0,..,(sizeof(BP_GF__FDK)/sizeof(FIXP_CFG)-1) => energy \ + calculation needs 4 bits headroom, headroom can be reduced by 1 \ + bit due to fPow2Div2() usage */ +#define SF_WET_NRG \ + (4 - 1) /* 8.495f = sum(BP_GF__FDK[i]) \ + i=0,..,(sizeof(BP_GF__FDK)/sizeof(FIXP_CFG)-1) => energy \ + calculation needs 4 bits headroom, headroom can be reduced by 1 \ + bit due to fPow2Div2() usage */ +#define SF_PRODUCT_BP_GF 13 +#define SF_PRODUCT_BP_GF_GF 26 +#define SF_SCALE 2 + +#define SF_SCALE_LD64 FL2FXCONST_DBL(0.03125) /* LD64((1<= scale2 >= 1/STP_SCALE_LIMIT + => STP_SCALE_LIMIT >= (0.1 + 0.9 * scale) >= 1/STP_SCALE_LIMIT + => (STP_SCALE_LIMIT-0.1)/0.9 >= scale >= + (1/STP_SCALE_LIMIT-0.1)/0.9 + + 3. Limiting of scale factor before sqrt calculation + ((STP_SCALE_LIMIT-0.1)/0.9)^2 >= (scale^2) >= + ((1/STP_SCALE_LIMIT-0.1)/0.9)^2 (STP_SCALE_LIMIT_HI)^2 >= (scale^2) >= + (STP_SCALE_LIMIT_LO)^2 + + 4. Thresholds for limiting of scale factor + STP_SCALE_LIMIT_HI = ((2.82-0.1)/0.9) + STP_SCALE_LIMIT_LO = (((1.0/2.82)-0.1)/0.9) + STP_SCALE_LIMIT_HI_LD64 = LD64(STP_SCALE_LIMIT_HI*STP_SCALE_LIMIT_HI) + STP_SCALE_LIMIT_LO_LD64 = LD64(STP_SCALE_LIMIT_LO*STP_SCALE_LIMIT_LO) +*/ + +#define CALC_WET_SCALE(dryIdx, wetIdx) \ + if ((DryEnerLD64[dryIdx] - STP_SCALE_LIMIT_HI_LD64) > WetEnerLD64[wetIdx]) { \ + scale[wetIdx] = STP_SCALE_LIMIT_HI; \ + } else if (DryEnerLD64[dryIdx] < \ + (WetEnerLD64[wetIdx] - STP_SCALE_LIMIT_LO_LD64)) { \ + scale[wetIdx] = STP_SCALE_LIMIT_LO; \ + } else { \ + tmp = ((DryEnerLD64[dryIdx] - WetEnerLD64[wetIdx]) >> 1) - SF_SCALE_LD64; \ + scale[wetIdx] = CalcInvLdData(tmp); \ + } + +struct STP_DEC { + FIXP_DBL runDryEner[MAX_INPUT_CHANNELS]; + FIXP_DBL runWetEner[MAX_OUTPUT_CHANNELS]; + FIXP_DBL oldDryEnerLD64[MAX_INPUT_CHANNELS]; + FIXP_DBL oldWetEnerLD64[MAX_OUTPUT_CHANNELS]; + FIXP_DBL prev_tp_scale[MAX_OUTPUT_CHANNELS]; + const FIXP_CFG *BP; + const FIXP_CFG *BP_GF; + int update_old_ener; +}; + +inline void combineSignalCplx(FIXP_DBL *hybOutputRealDry, + FIXP_DBL *hybOutputImagDry, + FIXP_DBL *hybOutputRealWet, + FIXP_DBL *hybOutputImagWet, int bands) { + int n; + + for (n = bands - 1; n >= 0; n--) { + *hybOutputRealDry = fAddSaturate(*hybOutputRealDry, *hybOutputRealWet); + *hybOutputImagDry = fAddSaturate(*hybOutputImagDry, *hybOutputImagWet); + hybOutputRealDry++, hybOutputRealWet++; + hybOutputImagDry++, hybOutputImagWet++; + } +} + +inline void combineSignalCplxScale1(FIXP_DBL *hybOutputRealDry, + FIXP_DBL *hybOutputImagDry, + FIXP_DBL *hybOutputRealWet, + FIXP_DBL *hybOutputImagWet, + const FIXP_CFG *pBP, FIXP_DBL scaleX, + int bands) { + int n; + FIXP_DBL scaleY; + for (n = bands - 1; n >= 0; n--) { + scaleY = fMult(scaleX, *pBP); + *hybOutputRealDry = SATURATE_LEFT_SHIFT( + (*hybOutputRealDry >> SF_SCALE) + fMult(*hybOutputRealWet, scaleY), + SF_SCALE, DFRACT_BITS); + *hybOutputImagDry = SATURATE_LEFT_SHIFT( + (*hybOutputImagDry >> SF_SCALE) + fMult(*hybOutputImagWet, scaleY), + SF_SCALE, DFRACT_BITS); + hybOutputRealDry++, hybOutputRealWet++; + hybOutputImagDry++, hybOutputImagWet++; + pBP++; + } +} + +inline void combineSignalCplxScale2(FIXP_DBL *hybOutputRealDry, + FIXP_DBL *hybOutputImagDry, + FIXP_DBL *hybOutputRealWet, + FIXP_DBL *hybOutputImagWet, FIXP_DBL scaleX, + int bands) { + int n; + + for (n = bands - 1; n >= 0; n--) { + *hybOutputRealDry = SATURATE_LEFT_SHIFT( + (*hybOutputRealDry >> SF_SCALE) + fMult(*hybOutputRealWet, scaleX), + SF_SCALE, DFRACT_BITS); + *hybOutputImagDry = SATURATE_LEFT_SHIFT( + (*hybOutputImagDry >> SF_SCALE) + fMult(*hybOutputImagWet, scaleX), + SF_SCALE, DFRACT_BITS); + hybOutputRealDry++, hybOutputRealWet++; + hybOutputImagDry++, hybOutputImagWet++; + } +} + +/******************************************************************************* + Functionname: subbandTPCreate + ******************************************************************************/ +SACDEC_ERROR subbandTPCreate(HANDLE_STP_DEC *hStpDec) { + HANDLE_STP_DEC self = NULL; + FDK_ALLOCATE_MEMORY_1D(self, 1, struct STP_DEC) + if (hStpDec != NULL) { + *hStpDec = self; + } + + return MPS_OK; +bail: + return MPS_OUTOFMEMORY; +} + +SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self) { + SACDEC_ERROR err = MPS_OK; + int ch; + + for (ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) { + self->prev_tp_scale[ch] = FL2FXCONST_DBL(1.0f / (1 << SF_SCALE)); + self->oldWetEnerLD64[ch] = FL2FXCONST_DBL(0.0); + } + for (ch = 0; ch < MAX_INPUT_CHANNELS; ch++) { + self->oldDryEnerLD64[ch] = FL2FXCONST_DBL(0.0); + } + + self->BP = BP__FDK; + self->BP_GF = BP_GF__FDK; + + self->update_old_ener = 0; + + return err; +} + +/******************************************************************************* + Functionname: subbandTPDestroy + ******************************************************************************/ +void subbandTPDestroy(HANDLE_STP_DEC *hStpDec) { + if (hStpDec != NULL) { + FDK_FREE_MEMORY_1D(*hStpDec); + } +} + +/******************************************************************************* + Functionname: subbandTPApply + ******************************************************************************/ +SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) { + FIXP_DBL *qmfOutputRealDry[MAX_OUTPUT_CHANNELS]; + FIXP_DBL *qmfOutputImagDry[MAX_OUTPUT_CHANNELS]; + FIXP_DBL *qmfOutputRealWet[MAX_OUTPUT_CHANNELS]; + FIXP_DBL *qmfOutputImagWet[MAX_OUTPUT_CHANNELS]; + + FIXP_DBL DryEner[MAX_INPUT_CHANNELS]; + FIXP_DBL scale[MAX_OUTPUT_CHANNELS]; + + FIXP_DBL DryEnerLD64[MAX_INPUT_CHANNELS]; + FIXP_DBL WetEnerLD64[MAX_OUTPUT_CHANNELS]; + + FIXP_DBL DryEner0 = FL2FXCONST_DBL(0.0f); + FIXP_DBL WetEnerX, damp, tmp; + FIXP_DBL dmxReal0, dmxImag0; + int skipChannels[MAX_OUTPUT_CHANNELS]; + int n, ch, cplxBands, cplxHybBands; + int dry_scale_dmx, wet_scale_dmx; + int i_LF, i_RF; + HANDLE_STP_DEC hStpDec; + const FIXP_CFG *pBP; + + int nrgScale = (2 * self->clipProtectGainSF__FDK); + + hStpDec = self->hStpDec; + + /* set scalefactor and loop counter */ + FDK_ASSERT(SF_DRY >= 1); + { + cplxBands = BP_GF_SIZE; + cplxHybBands = self->hybridBands; + if (self->treeConfig == TREE_212) { + dry_scale_dmx = 2; /* 2 bits to compensate fMultDiv2() and fPow2Div2() + used in energy calculation */ + } else { + dry_scale_dmx = (2 * SF_DRY) - 2; + } + wet_scale_dmx = 2; + } + + /* setup pointer for forming the direct downmix signal */ + for (ch = 0; ch < self->numOutputChannels; ch++) { + qmfOutputRealDry[ch] = &self->hybOutputRealDry__FDK[ch][7]; + qmfOutputRealWet[ch] = &self->hybOutputRealWet__FDK[ch][7]; + qmfOutputImagDry[ch] = &self->hybOutputImagDry__FDK[ch][7]; + qmfOutputImagWet[ch] = &self->hybOutputImagWet__FDK[ch][7]; + } + + /* clear skipping flag for all output channels */ + FDKmemset(skipChannels, 0, self->numOutputChannels * sizeof(int)); + + /* set scale values to zero */ + FDKmemset(scale, 0, self->numOutputChannels * sizeof(FIXP_DBL)); + + /* update normalisation energy with latest smoothed energy */ + if (hStpDec->update_old_ener == STP_UPDATE_ENERGY_RATE) { + hStpDec->update_old_ener = 1; + for (ch = 0; ch < self->numInputChannels; ch++) { + hStpDec->oldDryEnerLD64[ch] = + CalcLdData(fAddSaturate(hStpDec->runDryEner[ch], ABS_THR__FDK)); + } + for (ch = 0; ch < self->numOutputChannels; ch++) { + if (self->treeConfig == TREE_212) + hStpDec->oldWetEnerLD64[ch] = + CalcLdData(fAddSaturate(hStpDec->runWetEner[ch], ABS_THR__FDK)); + else + hStpDec->oldWetEnerLD64[ch] = + CalcLdData(fAddSaturate(hStpDec->runWetEner[ch], ABS_THR2__FDK)); + } + } else { + hStpDec->update_old_ener++; + } + + /* get channel configuration */ + switch (self->treeConfig) { + case TREE_212: + i_LF = 0; + i_RF = 1; + break; + default: + return MPS_WRONG_TREECONFIG; + } + + /* form the 'direct' downmix signal */ + pBP = hStpDec->BP_GF - BP_GF_START; + switch (self->treeConfig) { + case TREE_212: + INT sMin, sNorm, sReal, sImag; + + sReal = fMin(getScalefactor(&qmfOutputRealDry[i_LF][BP_GF_START], + cplxBands - BP_GF_START), + getScalefactor(&qmfOutputRealDry[i_RF][BP_GF_START], + cplxBands - BP_GF_START)); + sImag = fMin(getScalefactor(&qmfOutputImagDry[i_LF][BP_GF_START], + cplxBands - BP_GF_START), + getScalefactor(&qmfOutputImagDry[i_RF][BP_GF_START], + cplxBands - BP_GF_START)); + sMin = fMin(sReal, sImag) - 1; + + for (n = BP_GF_START; n < cplxBands; n++) { + dmxReal0 = scaleValue(qmfOutputRealDry[i_LF][n], sMin) + + scaleValue(qmfOutputRealDry[i_RF][n], sMin); + dmxImag0 = scaleValue(qmfOutputImagDry[i_LF][n], sMin) + + scaleValue(qmfOutputImagDry[i_RF][n], sMin); + + DryEner0 += (fMultDiv2(fPow2Div2(dmxReal0), pBP[n]) + + fMultDiv2(fPow2Div2(dmxImag0), pBP[n])) >> + SF_DRY_NRG; + } + + sNorm = SF_FREQ_DOMAIN_HEADROOM + SF_DRY_NRG + dry_scale_dmx - + (2 * sMin) + nrgScale; + DryEner0 = scaleValueSaturate( + DryEner0, fMax(fMin(sNorm, DFRACT_BITS - 1), -(DFRACT_BITS - 1))); + break; + default:; + } + DryEner[0] = DryEner0; + + /* normalise the 'direct' signals */ + for (ch = 0; ch < self->numInputChannels; ch++) { + if (self->treeConfig != TREE_212) DryEner[ch] = DryEner[ch] << nrgScale; + hStpDec->runDryEner[ch] = + fMult(STP_LPF_COEFF1__FDK, hStpDec->runDryEner[ch]) + + fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, DryEner[ch]); + if (DryEner[ch] != FL2FXCONST_DBL(0.0f)) { + DryEnerLD64[ch] = + fixMax((CalcLdData(DryEner[ch]) - hStpDec->oldDryEnerLD64[ch]), + FL2FXCONST_DBL(-0.484375f)); + } else { + DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f); + } + } + for (; ch < MAX_INPUT_CHANNELS; ch++) { + DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f); + } + + /* normalise the 'diffuse' signals */ + pBP = hStpDec->BP_GF - BP_GF_START; + for (ch = 0; ch < self->numOutputChannels; ch++) { + if (skipChannels[ch]) { + continue; + } + + WetEnerX = FL2FXCONST_DBL(0.0f); + + if (self->treeConfig == TREE_212) { + INT sMin, sNorm; + + sMin = fMin(getScalefactor(&qmfOutputRealWet[ch][BP_GF_START], + cplxBands - BP_GF_START), + getScalefactor(&qmfOutputImagWet[ch][BP_GF_START], + cplxBands - BP_GF_START)); + + for (n = BP_GF_START; n < cplxBands; n++) { + WetEnerX += + (fMultDiv2(fPow2Div2(scaleValue(qmfOutputRealWet[ch][n], sMin)), + pBP[n]) + + fMultDiv2(fPow2Div2(scaleValue(qmfOutputImagWet[ch][n], sMin)), + pBP[n])) >> + SF_WET_NRG; + } + sNorm = SF_FREQ_DOMAIN_HEADROOM + SF_WET_NRG + wet_scale_dmx - + (2 * sMin) + nrgScale; + WetEnerX = scaleValueSaturate( + WetEnerX, fMax(fMin(sNorm, DFRACT_BITS - 1), -(DFRACT_BITS - 1))); + } else + FDK_ASSERT(self->treeConfig == TREE_212); + + hStpDec->runWetEner[ch] = + fMult(STP_LPF_COEFF1__FDK, hStpDec->runWetEner[ch]) + + fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, WetEnerX); + + if (WetEnerX == FL2FXCONST_DBL(0.0f)) { + WetEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f); + } else { + WetEnerLD64[ch] = + fixMax((CalcLdData(WetEnerX) - hStpDec->oldWetEnerLD64[ch]), + FL2FXCONST_DBL(-0.484375f)); + } + } + + /* compute scale factor for the 'diffuse' signals */ + switch (self->treeConfig) { + case TREE_212: + if (DryEner[0] != FL2FXCONST_DBL(0.0f)) { + CALC_WET_SCALE(0, i_LF); + CALC_WET_SCALE(0, i_RF); + } + break; + default:; + } + + damp = FL2FXCONST_DBL(0.1f / (1 << SF_SCALE)); + for (ch = 0; ch < self->numOutputChannels; ch++) { + /* damp the scaling factor */ + scale[ch] = damp + fMult(FL2FXCONST_DBL(0.9f), scale[ch]); + + /* limiting the scale factor */ + if (scale[ch] > STP_SCALE_LIMIT__FDK) { + scale[ch] = STP_SCALE_LIMIT__FDK; + } + if (scale[ch] < ONE_DIV_STP_SCALE_LIMIT__FDK) { + scale[ch] = ONE_DIV_STP_SCALE_LIMIT__FDK; + } + + /* low pass filter the scaling factor */ + scale[ch] = + fMult(STP_LPF_COEFF2__FDK, scale[ch]) + + fMult(ONE_MINUS_STP_LPF_COEFF2__FDK, hStpDec->prev_tp_scale[ch]); + hStpDec->prev_tp_scale[ch] = scale[ch]; + } + + /* combine 'direct' and scaled 'diffuse' signal */ + FDK_ASSERT((HP_SIZE - 3 + 10 - 1) == PC_NUM_HYB_BANDS); + const SCHAR *channlIndex = row2channelSTP[self->treeConfig]; + + for (ch = 0; ch < self->numOutputChannels; ch++) { + int no_scaling; + + no_scaling = !frame->tempShapeEnableChannelSTP[channlIndex[ch]]; + if (no_scaling) { + combineSignalCplx( + &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder], + &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder], + &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder], + &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder], + cplxHybBands - self->tp_hybBandBorder); + + } else { + FIXP_DBL scaleX; + scaleX = scale[ch]; + pBP = hStpDec->BP - self->tp_hybBandBorder; + /* Band[HP_SIZE-3+10-1] needs not to be processed in + combineSignalCplxScale1(), because pB[HP_SIZE-3+10-1] would be 1.0 */ + combineSignalCplxScale1( + &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder], + &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder], + &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder], + &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder], + &pBP[self->tp_hybBandBorder], scaleX, + (HP_SIZE - 3 + 10 - 1) - self->tp_hybBandBorder); + + { + combineSignalCplxScale2( + &self->hybOutputRealDry__FDK[ch][HP_SIZE - 3 + 10 - 1], + &self->hybOutputImagDry__FDK[ch][HP_SIZE - 3 + 10 - 1], + &self->hybOutputRealWet__FDK[ch][HP_SIZE - 3 + 10 - 1], + &self->hybOutputImagWet__FDK[ch][HP_SIZE - 3 + 10 - 1], scaleX, + cplxHybBands - (HP_SIZE - 3 + 10 - 1)); + } + } + } + + return (SACDEC_ERROR)MPS_OK; + ; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_stp.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_stp.h new file mode 100644 index 0000000000000..18471bd4a12a3 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_stp.h @@ -0,0 +1,115 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec subband processing + +*******************************************************************************/ + +#ifndef SAC_STP_H +#define SAC_STP_H + +#include "sac_dec.h" + +SACDEC_ERROR subbandTPCreate(HANDLE_STP_DEC *hStpDec); + +SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self); + +SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame); +void subbandTPDestroy(HANDLE_STP_DEC *hStpDec); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_tsd.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_tsd.cpp new file mode 100644 index 0000000000000..a07447bbf921c --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_tsd.cpp @@ -0,0 +1,359 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): Matthias Hildenbrand + + Description: USAC MPS212 Transient Steering Decorrelator (TSD) + +*******************************************************************************/ + +#include "sac_tsd.h" + +#define TSD_START_BAND (7) +#define SIZE_S (4) +#define SIZE_C (5) + +/*** Tables ***/ +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const UCHAR nBitsTsdCW_32slots[32] = { + 5, 9, 13, 16, 18, 20, 22, 24, 25, 26, 27, 28, 29, 29, 30, 30, + 30, 29, 29, 28, 27, 26, 25, 24, 22, 20, 18, 16, 13, 9, 5, 0}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const UCHAR nBitsTsdCW_64slots[64] = { + 6, 11, 16, 20, 23, 27, 30, 33, 35, 38, 40, 42, 44, 46, 48, 49, + 51, 52, 53, 55, 56, 57, 58, 58, 59, 60, 60, 60, 61, 61, 61, 61, + 61, 61, 61, 60, 60, 60, 59, 58, 58, 57, 56, 55, 53, 52, 51, 49, + 48, 46, 44, 42, 40, 38, 35, 33, 30, 27, 23, 20, 16, 11, 6, 0}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_DPK phiTsd[8] = { + {{(FIXP_DBL)0x7fffffff, (FIXP_DBL)0x00000000}}, + {{(FIXP_DBL)0x5a82799a, (FIXP_DBL)0x5a82799a}}, + {{(FIXP_DBL)0x00000000, (FIXP_DBL)0x7fffffff}}, + {{(FIXP_DBL)0xa57d8666, (FIXP_DBL)0x5a82799a}}, + {{(FIXP_DBL)0x80000000, (FIXP_DBL)0x00000000}}, + {{(FIXP_DBL)0xa57d8666, (FIXP_DBL)0xa57d8666}}, + {{(FIXP_DBL)0x00000000, (FIXP_DBL)0x80000000}}, + {{(FIXP_DBL)0x5a82799a, (FIXP_DBL)0xa57d8666}}}; + +/*** Static Functions ***/ +static void longmult1(USHORT a[], USHORT b, USHORT d[], int len) { + int k; + ULONG tmp; + ULONG b0 = (ULONG)b; + + tmp = ((ULONG)a[0]) * b0; + d[0] = (USHORT)tmp; + + for (k = 1; k < len; k++) { + tmp = (tmp >> 16) + ((ULONG)a[k]) * b0; + d[k] = (USHORT)tmp; + } +} + +static void longdiv(USHORT b[], USHORT a, USHORT d[], USHORT *pr, int len) { + ULONG r; + ULONG tmp; + int k; + + FDK_ASSERT(a != 0); + + r = 0; + + for (k = len - 1; k >= 0; k--) { + tmp = ((ULONG)b[k]) + (r << 16); + + if (tmp) { + d[k] = (USHORT)(tmp / a); + r = tmp - d[k] * a; + } else { + d[k] = 0; + } + } + *pr = (USHORT)r; +} + +static void longsub(USHORT a[], USHORT b[], int lena, int lenb) { + int h; + LONG carry = 0; + + FDK_ASSERT(lena >= lenb); + for (h = 0; h < lenb; h++) { + carry += ((LONG)a[h]) - ((LONG)b[h]); + a[h] = (USHORT)carry; + carry = carry >> 16; + } + + for (; h < lena; h++) { + carry = ((LONG)a[h]) + carry; + a[h] = (USHORT)carry; + carry = carry >> 16; + } + + FDK_ASSERT(carry == + 0); /* carry != 0 indicates subtraction underflow, e.g. b > a */ + return; +} + +static int longcompare(USHORT a[], USHORT b[], int len) { + int i; + + for (i = len - 1; i > 0; i--) { + if (a[i] != b[i]) break; + } + return (a[i] >= b[i]) ? 1 : 0; +} + +FDK_INLINE int isTrSlot(const TSD_DATA *pTsdData, const int ts) { + return (pTsdData->bsTsdTrPhaseData[ts] >= 0); +} + +/*** Public Functions ***/ +int TsdRead(HANDLE_FDK_BITSTREAM hBs, const int numSlots, TSD_DATA *pTsdData) { + int nBitsTrSlots = 0; + int bsTsdNumTrSlots; + const UCHAR *nBitsTsdCW_tab = NULL; + + switch (numSlots) { + case 32: + nBitsTrSlots = 4; + nBitsTsdCW_tab = nBitsTsdCW_32slots; + break; + case 64: + nBitsTrSlots = 5; + nBitsTsdCW_tab = nBitsTsdCW_64slots; + break; + default: + return 1; + } + + /*** Read TempShapeData for bsTempShapeConfig == 3 ***/ + pTsdData->bsTsdEnable = FDKreadBit(hBs); + if (!pTsdData->bsTsdEnable) { + return 0; + } + + /*** Parse/Decode TsdData() ***/ + pTsdData->numSlots = numSlots; + + bsTsdNumTrSlots = FDKreadBits(hBs, nBitsTrSlots); + + /* Decode transient slot positions */ + { + int nBitsTsdCW = (int)nBitsTsdCW_tab[bsTsdNumTrSlots]; + SCHAR *phaseData = pTsdData->bsTsdTrPhaseData; + int p = bsTsdNumTrSlots + 1; + int k, h; + USHORT s[SIZE_S] = {0}; + USHORT c[SIZE_C] = {0}; + USHORT r[1]; + + /* Init with TsdSepData[k] = 0 */ + for (k = 0; k < numSlots; k++) { + phaseData[k] = -1; /* means TsdSepData[] = 0 */ + } + + for (h = (SIZE_S - 1); h >= 0; h--) { + if (nBitsTsdCW > h * 16) { + s[h] = (USHORT)FDKreadBits(hBs, nBitsTsdCW - h * 16); + nBitsTsdCW = h * 16; + } + } + + /* c = prod_{h=1}^{p} (k-p+h)/h */ + k = numSlots - 1; + c[0] = k - p + 1; + for (h = 2; h <= p; h++) { + longmult1(c, (k - p + h), c, 5); /* c *= k - p + h; */ + longdiv(c, h, c, r, 5); /* c /= h; */ + FDK_ASSERT(*r == 0); + } + + /* go through all slots */ + for (; k >= 0; k--) { + if (p > k) { + for (; k >= 0; k--) { + phaseData[k] = 1; /* means TsdSepData[] = 1 */ + } + break; + } + if (longcompare(s, c, 4)) { /* (s >= c) */ + longsub(s, c, 4, 4); /* s -= c; */ + phaseData[k] = 1; /* means TsdSepData[] = 1 */ + if (p == 1) { + break; + } + /* Update c for next iteration: c_new = c_old * p / k */ + longmult1(c, p, c, 5); + p--; + } else { + /* Update c for next iteration: c_new = c_old * (k-p) / k */ + longmult1(c, (k - p), c, 5); + } + longdiv(c, k, c, r, 5); + FDK_ASSERT(*r == 0); + } + + /* Read phase data */ + for (k = 0; k < numSlots; k++) { + if (phaseData[k] == 1) { + phaseData[k] = FDKreadBits(hBs, 3); + } + } + } + + return 0; +} + +void TsdGenerateNonTr(const int numHybridBands, const TSD_DATA *pTsdData, + const int ts, FIXP_DBL *pVdirectReal, + FIXP_DBL *pVdirectImag, FIXP_DBL *pVnonTrReal, + FIXP_DBL *pVnonTrImag, FIXP_DBL **ppDecorrInReal, + FIXP_DBL **ppDecorrInImag) { + int k = 0; + + if (!isTrSlot(pTsdData, ts)) { + /* Let allpass based decorrelator read from direct input. */ + *ppDecorrInReal = pVdirectReal; + *ppDecorrInImag = pVdirectImag; + return; + } + + /* Generate nonTr input signal for allpass based decorrelator */ + for (; k < TSD_START_BAND; k++) { + pVnonTrReal[k] = pVdirectReal[k]; + pVnonTrImag[k] = pVdirectImag[k]; + } + for (; k < numHybridBands; k++) { + pVnonTrReal[k] = (FIXP_DBL)0; + pVnonTrImag[k] = (FIXP_DBL)0; + } + *ppDecorrInReal = pVnonTrReal; + *ppDecorrInImag = pVnonTrImag; +} + +void TsdApply(const int numHybridBands, const TSD_DATA *pTsdData, int *pTsdTs, + const FIXP_DBL *pVdirectReal, const FIXP_DBL *pVdirectImag, + FIXP_DBL *pDnonTrReal, FIXP_DBL *pDnonTrImag) { + const int ts = *pTsdTs; + + if (isTrSlot(pTsdData, ts)) { + int k; + const FIXP_DPK *phi = &phiTsd[pTsdData->bsTsdTrPhaseData[ts]]; + FDK_ASSERT((pTsdData->bsTsdTrPhaseData[ts] >= 0) && + (pTsdData->bsTsdTrPhaseData[ts] < 8)); + + /* d = d_nonTr + v_direct * exp(j * bsTsdTrPhaseData[ts]/4 * pi ) */ + for (k = TSD_START_BAND; k < numHybridBands; k++) { + FIXP_DBL tempReal, tempImag; + cplxMultDiv2(&tempReal, &tempImag, pVdirectReal[k], pVdirectImag[k], + *phi); + pDnonTrReal[k] = SATURATE_LEFT_SHIFT( + (pDnonTrReal[k] >> 2) + (tempReal >> 1), 2, DFRACT_BITS); + pDnonTrImag[k] = SATURATE_LEFT_SHIFT( + (pDnonTrImag[k] >> 2) + (tempImag >> 1), 2, DFRACT_BITS); + } + } + + /* The modulo MAX_TSD_TIME_SLOTS operation is to avoid illegal memory accesses + * in case of errors. */ + *pTsdTs = (ts + 1) & (MAX_TSD_TIME_SLOTS - 1); + return; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_tsd.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_tsd.h new file mode 100644 index 0000000000000..2521e27fc3940 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACdec/src/sac_tsd.h @@ -0,0 +1,167 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): Matthias Hildenbrand + + Description: USAC MPS212 Transient Steering Decorrelator (TSD) + +*******************************************************************************/ + +#ifndef SAC_TSD_H +#define SAC_TSD_H + +#include "FDK_bitstream.h" +#include "common_fix.h" + +#define MAX_TSD_TIME_SLOTS (64) + +/** Structure which holds the data needed to apply TSD to current frame. */ +typedef struct { + UCHAR bsTsdEnable; /**< for current frame TSD is (0:disabled, 1:enabled) */ + UCHAR numSlots; /**< total number of QMF slots per frame */ + SCHAR + bsTsdTrPhaseData[MAX_TSD_TIME_SLOTS]; /**< -1 => TsdSepData[ts]=0; 0-7: + values of bsTsdTrPhaseData[ts] + and TsdSepData[ts]=1 */ +} TSD_DATA; + +FDK_INLINE int isTsdActive(const TSD_DATA *pTsdData) { + return (int)pTsdData->bsTsdEnable; +} + +/** + * \brief Parse and Decode TSD data. + * \param[in] hBs bitstream handle to read data from. + * \param[in] numSlots number of QMF slots per frame. + * \param[out] pTsdData pointer to TSD data structure. + * \return 0 on succes, 1 on error. + */ +int TsdRead(HANDLE_FDK_BITSTREAM hBs, const int numSlots, TSD_DATA *pTsdData); + +/** + * \brief Perform transient seperation (v_{x,nonTr} signal). + * \param[in] numHybridBands number of hybrid bands. + * \param[in] pTsdData pointer to TSD data structure. + * \param[in] pVdirectReal pointer to array with direct signal. + * \param[in] pVdirectImag pointer to array with direct signal. + * \param[out] pVnonTrReal pointer to array with nonTr signal. + * \param[out] pVnonTrImag pointer to array with nonTr signal. + * \param[out] ppDecorrInReal handle to array where allpass based decorrelator + * should read from (modified by this function). + * \param[out] ppDecorrInImag handle to array where allpass based decorrelator + * should read from (modified by this function). + */ +void TsdGenerateNonTr(const int numHybridBands, const TSD_DATA *pTsdData, + const int ts, FIXP_DBL *pVdirectReal, + FIXP_DBL *pVdirectImag, FIXP_DBL *pVnonTrReal, + FIXP_DBL *pVnonTrImag, FIXP_DBL **ppDecorrInReal, + FIXP_DBL **ppDecorrInImag); + +/** + * \brief Generate d_{x,Tr} signal and add to d_{x,nonTr} signal + * \param[in] numHybridBands + * \param[in,out] pTsdData + * \param pTsdTs pointer to persistent time slot counter + * \param[in] pVdirectReal + * \param[in] pVdirectImag + * \param[out] pDnonTrReal + * \param[out] pDnonTrImag + */ +void TsdApply(const int numHybridBands, const TSD_DATA *pTsdData, int *pTsdTs, + const FIXP_DBL *pVdirectReal, const FIXP_DBL *pVdirectImag, + FIXP_DBL *pDnonTrReal, FIXP_DBL *pDnonTrImag); + +#endif /* #ifndef SAC_TSD_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/include/sacenc_lib.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/include/sacenc_lib.h new file mode 100644 index 0000000000000..758cc0fd6e80a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/include/sacenc_lib.h @@ -0,0 +1,405 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Encoder API + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + ******************************************************************************/ + +#ifndef SACENC_LIB_H +#define SACENC_LIB_H + +/* Includes ******************************************************************/ +#include "machine_type.h" +#include "FDK_audio.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ + +/** + * Space encoder error codes. + */ +typedef enum { + SACENC_OK = 0x00000000, /*!< No error happened. All fine. */ + SACENC_INVALID_HANDLE = + 0x00000080, /*!< Handle passed to function call was invalid. */ + SACENC_MEMORY_ERROR = 0x00000800, /*!< Memory allocation failed. */ + SACENC_INIT_ERROR = 0x00008000, /*!< General initialization error. */ + SACENC_ENCODE_ERROR = + 0x00080000, /*!< The encoding process was interrupted by an unexpected + error. */ + SACENC_PARAM_ERROR = 0x00800000, /*!< Invalid runtime parameter. */ + SACENC_UNSUPPORTED_PARAMETER = 0x00800001, /*!< Parameter not available. */ + SACENC_INVALID_CONFIG = 0x00800002, /*!< Configuration not provided. */ + SACENC_UNKNOWN_ERROR = 0x08000000 /*!< Unknown error. */ + +} FDK_SACENC_ERROR; + +typedef enum { + SACENC_INVALID_MODE = 0, + SACENC_212 = 8, + SACENC_ESCAPE = 15 + +} MP4SPACEENC_MODE; + +typedef enum { + SACENC_BANDS_INVALID = 0, + SACENC_BANDS_4 = 4, + SACENC_BANDS_5 = 5, + SACENC_BANDS_7 = 7, + SACENC_BANDS_9 = 9, + SACENC_BANDS_12 = 12, + SACENC_BANDS_15 = 15, + SACENC_BANDS_23 = 23 + +} MP4SPACEENC_BANDS_CONFIG; + +typedef enum { + SACENC_QUANTMODE_INVALID = -1, + SACENC_QUANTMODE_FINE = 0, + SACENC_QUANTMODE_EBQ1 = 1, + SACENC_QUANTMODE_EBQ2 = 2, + SACENC_QUANTMODE_RSVD3 = 3 + +} MP4SPACEENC_QUANTMODE; + +typedef enum { + SACENC_DMXGAIN_INVALID = -1, + SACENC_DMXGAIN_0_dB = 0, + SACENC_DMXGAIN_1_5_dB = 1, + SACENC_DMXGAIN_3_dB = 2, + SACENC_DMXGAIN_4_5_dB = 3, + SACENC_DMXGAIN_6_dB = 4, + SACENC_DMXGAIN_7_5_dB = 5, + SACENC_DMXGAIN_9_dB = 6, + SACENC_DMXGAIN_12_dB = 7 + +} MP4SPACEENC_DMX_GAIN; + +/** + * \brief Space Encoder setting parameters. + * + * Use FDK_sacenc_setParam() function to configure the internal status of the + * following parameters. + */ +typedef enum { + SACENC_LOWDELAY, /*!< Configure lowdelay MPEG Surround. + - 0: Disable Lowdelay. (default) + - 1: Enable Lowdelay. + - 2: Enable Lowdelay including keep frame. */ + + SACENC_ENC_MODE, /*!< Configure encoder tree mode. See ::MP4SPACEENC_MODE for + available values. */ + + SACENC_SAMPLERATE, /*!< Configure encoder sampling rate. */ + + SACENC_FRAME_TIME_SLOTS, /*!< Configure number of slots per spatial frame. */ + + SACENC_PARAM_BANDS, /*!< Configure number of parameter bands. See + ::MP4SPACEENC_BANDS_CONFIG for available values. */ + + SACENC_TIME_DOM_DMX, /*!< Configure time domain downmix. + - 0: No time domain downmix. (default) + - 1: Static time domain downmix. + - 2: Enhanced time domain downmix, stereo to mono + only. */ + + SACENC_DMX_GAIN, /*!< Configure downmix gain. See ::MP4SPACEENC_DMX_GAIN for + available values. */ + + SACENC_COARSE_QUANT, /*!< Use coarse parameter quantization. + - 0: No (default) + - 1: Yes */ + + SACENC_QUANT_MODE, /*!< Configure quanitzation mode. See + ::MP4SPACEENC_QUANTMODE for available values. */ + + SACENC_TIME_ALIGNMENT, /*!< Configure time alignment in samples. */ + + SACENC_INDEPENDENCY_COUNT, /*!< Configure the independency count. (count == 0 + means independencyFlag == 1) */ + + SACENC_INDEPENDENCY_FACTOR, /*!< How often should we set the independency flag + */ + + SACENC_NONE /*!< ------ */ + +} SPACEENC_PARAM; + +/** + * Describes Spatial Specific Config. + */ +typedef struct { + INT nSscSizeBits; /*!< Number of valid bits in pSsc buffer. */ + UCHAR *pSsc; /*!< SpatialSpecificConfig buffer in binary format. */ + +} MPEG4SPACEENC_SSCBUF; + +/** + * Provides some info about the encoder configuration. + */ +typedef struct { + INT nSampleRate; /*!< Configured sampling rate.*/ + INT nSamplesFrame; /*!< Frame length in samples. */ + INT nTotalInputChannels; /*!< Number of expected audio input channels. */ + INT nDmxDelay; /*!< Delay of the downmixed signal. */ + INT nCodecDelay; /*!< Delay of the whole en-/decoded signal, including + core-coder delay. */ + INT nDecoderDelay; /*!< Delay added by the MP4SPACE decoder. */ + INT nPayloadDelay; /*!< Delay of the payload. */ + INT nDiscardOutFrames; /*!< Number of dmx frames to discard for alignment with + bitstream. */ + + MPEG4SPACEENC_SSCBUF + *pSscBuf; /*!< Pointer to Spatial Specific Config structure. */ + +} MP4SPACEENC_INFO; + +/** + * MPEG Surround encoder handle. + */ +typedef struct MP4SPACE_ENCODER *HANDLE_MP4SPACE_ENCODER; + +/** + * Defines the input arguments for a FDK_sacenc_encode() call. + */ +typedef struct { + INT nInputSamples; /*!< Number of valid input audio samples (multiple of input + channels). */ + UINT inputBufferSizePerChannel; /*!< Size of input buffer (input audio + samples) per channel. */ + UINT isInputInterleaved; /*!< Indicates if input audio samples are represented + in blocks or interleaved: + - 0 : in blocks. + - 1 : interleaved. */ + +} SACENC_InArgs; + +/** + * Defines the output arguments for a FDK_sacenc_encode() call. + */ +typedef struct { + INT nOutputBits; /*!< Number of valid payload bits generated during + FDK_sacenc_encode(). */ + INT nOutputSamples; /*!< Number of valid output audio samples generated during + FDK_sacenc_encode(). */ + UINT nSamplesConsumed; /*!< Number of input audio samples consumed in + FDK_sacenc_encode(). */ + +} SACENC_OutArgs; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/** + * \brief Opens a new instace of the MPEG Surround encoder. + * + * \param phMp4SpaceEnc Pointer to the encoder handle to be deallocated. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, SACENC_MEMORY_ERROR, on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_open(HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc); + +/** + * \brief Finalizes opening process of MPEG Surround encoder. + * + * Shows, how many samples are needed as input + * + * \param hMp4SpaceEnc A valid MPEG Surround encoder handle. + * \param dmxDelay Downmix delay. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, SACENC_INIT_ERROR, SACENC_INVALID_CONFIG, + * on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_init(HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + const INT dmxDelay); + +/** + * \brief Close the MPEG Surround encoder instance. + * + * Deallocate encoder instance and free whole memory. + * + * \param phMp4SpaceEnc Pointer to the encoder handle to be deallocated. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_close(HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc); + +/** + * \brief MPEG surround parameter extraction, framwise. + * + * \param hMp4SpaceEnc A valid MPEG Surround encoder handle. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_encode(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + const FDK_bufDescr *inBufDesc, + const FDK_bufDescr *outBufDesc, + const SACENC_InArgs *inargs, + SACENC_OutArgs *outargs); + +/** + * \brief Provides information on produced bitstream. + * + * \param hMp4SpaceEnc A valid MPEG Surround encoder handle. + * \param pInfo Pointer to an encoder info struct, filled on + * return. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_getInfo(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + MP4SPACEENC_INFO *const pInfo); + +/** + * \brief Set one single MPEG Surround encoder parameter. + * + * This function allows configuration of all encoder parameters specified in + * ::SPACEENC_PARAM. Each parameter must be set with a separate function call. + * An internal validation of the configuration value range will be done. + * + * \param hMp4SpaceEnc A valid MPEG Surround encoder handle. + * \param param Parameter to be set. See ::SPACEENC_PARAM. + * \param value Parameter value. See parameter description in + * ::SPACEENC_PARAM. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, SACENC_UNSUPPORTED_PARAMETER, + * SACENC_INVALID_CONFIG, on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_setParam(HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + const SPACEENC_PARAM param, + const UINT value); + +/** + * \brief Get information about MPEG Surround encoder library build. + * + * Fill a given LIB_INFO structure with library version information. + * + * \param info Pointer to an allocated LIB_INFO struct. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, SACENC_INIT_ERROR, on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_getLibInfo(LIB_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif /* SACENC_LIB_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_bitstream.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_bitstream.cpp new file mode 100644 index 0000000000000..dacfc27fda1f9 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_bitstream.cpp @@ -0,0 +1,826 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): + + Description: Encoder Library Interface + Bitstream Writer + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_bitstream.h" +#include "sacenc_const.h" + +#include "genericStds.h" +#include "common_fix.h" + +#include "FDK_matrixCalloc.h" +#include "sacenc_nlc_enc.h" + +/* Defines *******************************************************************/ +#define MAX_FREQ_RES_INDEX 8 +#define MAX_SAMPLING_FREQUENCY_INDEX 13 +#define SAMPLING_FREQUENCY_INDEX_ESCAPE 15 + +/* Data Types ****************************************************************/ +typedef struct { + SCHAR cld_old[SACENC_MAX_NUM_BOXES][MAX_NUM_BINS]; + SCHAR icc_old[SACENC_MAX_NUM_BOXES][MAX_NUM_BINS]; + UCHAR quantCoarseCldPrev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + UCHAR quantCoarseIccPrev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + +} PREV_OTTDATA; + +typedef struct { + PREV_OTTDATA prevOttData; + +} STATIC_SPATIALFRAME; + +typedef struct BSF_INSTANCE { + SPATIALSPECIFICCONFIG spatialSpecificConfig; + SPATIALFRAME frame; + STATIC_SPATIALFRAME prevFrameData; + +} BSF_INSTANCE; + +/* Constants *****************************************************************/ +static const INT SampleRateTable[MAX_SAMPLING_FREQUENCY_INDEX] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, + 22050, 16000, 12000, 11025, 8000, 7350}; + +static const UCHAR FreqResBinTable_LD[MAX_FREQ_RES_INDEX] = {0, 23, 15, 12, + 9, 7, 5, 4}; +static const UCHAR FreqResStrideTable_LD[] = {1, 2, 5, 23}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static FDK_SACENC_ERROR DuplicateLosslessData( + const INT startBox, const INT stopBox, + const LOSSLESSDATA *const hLosslessDataFrom, const INT setFrom, + LOSSLESSDATA *const hLosslessDataTo, const INT setTo) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hLosslessDataFrom) || (NULL == hLosslessDataTo)) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + + for (i = startBox; i < stopBox; i++) { + hLosslessDataTo->bsXXXDataMode[i][setTo] = + hLosslessDataFrom->bsXXXDataMode[i][setFrom]; + hLosslessDataTo->bsDataPair[i][setTo] = + hLosslessDataFrom->bsDataPair[i][setFrom]; + hLosslessDataTo->bsQuantCoarseXXX[i][setTo] = + hLosslessDataFrom->bsQuantCoarseXXX[i][setFrom]; + hLosslessDataTo->bsFreqResStrideXXX[i][setTo] = + hLosslessDataFrom->bsFreqResStrideXXX[i][setFrom]; + } + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_duplicateParameterSet( + const SPATIALFRAME *const hFrom, const INT setFrom, SPATIALFRAME *const hTo, + const INT setTo) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hFrom) || (NULL == hTo)) { + error = SACENC_INVALID_HANDLE; + } else { + int box; + /* Only Copy Parameter Set selective stuff */ + + /* OTT-Data */ + for (box = 0; box < SACENC_MAX_NUM_BOXES; box++) { + FDKmemcpy(hTo->ottData.cld[box][setTo], hFrom->ottData.cld[box][setFrom], + sizeof(hFrom->ottData.cld[0][0])); + FDKmemcpy(hTo->ottData.icc[box][setTo], hFrom->ottData.icc[box][setFrom], + sizeof(hFrom->ottData.icc[0][0])); + } + + /* LOSSLESSDATA */ + DuplicateLosslessData(0, SACENC_MAX_NUM_BOXES, &hFrom->CLDLosslessData, + setFrom, &hTo->CLDLosslessData, setTo); + DuplicateLosslessData(0, SACENC_MAX_NUM_BOXES, &hFrom->ICCLosslessData, + setFrom, &hTo->ICCLosslessData, setTo); + + } /* valid handle */ + + return error; +} + +/* set frame defaults */ +static void clearFrame(SPATIALFRAME *const pFrame) { + FDKmemclear(pFrame, sizeof(SPATIALFRAME)); + + pFrame->bsIndependencyFlag = 1; + pFrame->framingInfo.numParamSets = 1; +} + +static void fine2coarse(SCHAR *const data, const DATA_TYPE dataType, + const INT startBand, const INT numBands) { + int i; + if (dataType == t_CLD) { + for (i = startBand; i < startBand + numBands; i++) { + data[i] /= 2; + } + } else { + for (i = startBand; i < startBand + numBands; i++) { + data[i] >>= 1; + } + } +} + +static void coarse2fine(SCHAR *const data, const DATA_TYPE dataType, + const INT startBand, const INT numBands) { + int i; + + for (i = startBand; i < startBand + numBands; i++) { + data[i] <<= 1; + } + + if (dataType == t_CLD) { + for (i = startBand; i < startBand + numBands; i++) { + if (data[i] == -14) { + data[i] = -15; + } else if (data[i] == 14) { + data[i] = 15; + } + } + } /* (dataType == t_CLD) */ +} + +static UCHAR getBsFreqResStride(const INT index) { + const UCHAR *pFreqResStrideTable = NULL; + int freqResStrideTableSize = 0; + + pFreqResStrideTable = FreqResStrideTable_LD; + freqResStrideTableSize = + sizeof(FreqResStrideTable_LD) / sizeof(*FreqResStrideTable_LD); + + return (((NULL != pFreqResStrideTable) && (index >= 0) && + (index < freqResStrideTableSize)) + ? pFreqResStrideTable[index] + : 1); +} + +/* write data to bitstream */ +static void ecData(HANDLE_FDK_BITSTREAM bitstream, + SCHAR data[MAX_NUM_PARAMS][MAX_NUM_BINS], + SCHAR oldData[MAX_NUM_BINS], + UCHAR quantCoarseXXXprev[MAX_NUM_PARAMS], + LOSSLESSDATA *const losslessData, const DATA_TYPE dataType, + const INT paramIdx, const INT numParamSets, + const INT independencyFlag, const INT startBand, + const INT stopBand, const INT defaultValue) { + int ps, pb, strOffset, pbStride, dataBands, i; + int aStrides[MAX_NUM_BINS + 1] = {0}; + SHORT cmpIdxData[2][MAX_NUM_BINS] = {{0}}; + SHORT cmpOldData[MAX_NUM_BINS] = {0}; + + /* bsXXXDataMode */ + if (independencyFlag || (losslessData->bsQuantCoarseXXX[paramIdx][0] != + quantCoarseXXXprev[paramIdx])) { + losslessData->bsXXXDataMode[paramIdx][0] = FINECOARSE; + } else { + losslessData->bsXXXDataMode[paramIdx][0] = KEEP; + for (i = startBand; i < stopBand; i++) { + if (data[0][i] != oldData[i]) { + losslessData->bsXXXDataMode[paramIdx][0] = FINECOARSE; + break; + } + } + } + + FDKwriteBits(bitstream, losslessData->bsXXXDataMode[paramIdx][0], 2); + + for (ps = 1; ps < numParamSets; ps++) { + if (losslessData->bsQuantCoarseXXX[paramIdx][ps] != + losslessData->bsQuantCoarseXXX[paramIdx][ps - 1]) { + losslessData->bsXXXDataMode[paramIdx][ps] = FINECOARSE; + } else { + losslessData->bsXXXDataMode[paramIdx][ps] = KEEP; + for (i = startBand; i < stopBand; i++) { + if (data[ps][i] != data[ps - 1][i]) { + losslessData->bsXXXDataMode[paramIdx][ps] = FINECOARSE; + break; + } + } + } + + FDKwriteBits(bitstream, losslessData->bsXXXDataMode[paramIdx][ps], 2); + } /* for ps */ + + /* Create data pairs if possible */ + for (ps = 0; ps < (numParamSets - 1); ps++) { + if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE) { + /* Check if next parameter set is FINCOARSE */ + if (losslessData->bsXXXDataMode[paramIdx][ps + 1] == FINECOARSE) { + /* We have to check if ps and ps+1 use the same bsXXXQuantMode */ + /* and also have the same stride */ + if ((losslessData->bsQuantCoarseXXX[paramIdx][ps + 1] == + losslessData->bsQuantCoarseXXX[paramIdx][ps]) && + (losslessData->bsFreqResStrideXXX[paramIdx][ps + 1] == + losslessData->bsFreqResStrideXXX[paramIdx][ps])) { + losslessData->bsDataPair[paramIdx][ps] = 1; + losslessData->bsDataPair[paramIdx][ps + 1] = 1; + + /* We have a data pair -> Jump to the ps after next ps*/ + ps++; + continue; + } + } + /* dataMode of next ps is not FINECOARSE or does not use the same + * bsXXXQuantMode/stride */ + /* -> no dataPair possible */ + losslessData->bsDataPair[paramIdx][ps] = 0; + + /* Initialize ps after next ps to Zero (only important for the last + * parameter set) */ + losslessData->bsDataPair[paramIdx][ps + 1] = 0; + } else { + /* No FINECOARSE -> no data pair possible */ + losslessData->bsDataPair[paramIdx][ps] = 0; + + /* Initialize ps after next ps to Zero (only important for the last + * parameter set) */ + losslessData->bsDataPair[paramIdx][ps + 1] = 0; + } + } /* for ps */ + + for (ps = 0; ps < numParamSets; ps++) { + if (losslessData->bsXXXDataMode[paramIdx][ps] == DEFAULT) { + /* Prepare old data */ + for (i = startBand; i < stopBand; i++) { + oldData[i] = defaultValue; + } + quantCoarseXXXprev[paramIdx] = 0; /* Default data are always fine */ + } + + if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE) { + FDKwriteBits(bitstream, losslessData->bsDataPair[paramIdx][ps], 1); + FDKwriteBits(bitstream, losslessData->bsQuantCoarseXXX[paramIdx][ps], 1); + FDKwriteBits(bitstream, losslessData->bsFreqResStrideXXX[paramIdx][ps], + 2); + + if (losslessData->bsQuantCoarseXXX[paramIdx][ps] != + quantCoarseXXXprev[paramIdx]) { + if (quantCoarseXXXprev[paramIdx]) { + coarse2fine(oldData, dataType, startBand, stopBand - startBand); + } else { + fine2coarse(oldData, dataType, startBand, stopBand - startBand); + } + } + + /* Handle strides */ + pbStride = + getBsFreqResStride(losslessData->bsFreqResStrideXXX[paramIdx][ps]); + dataBands = (stopBand - startBand - 1) / pbStride + 1; + + aStrides[0] = startBand; + for (pb = 1; pb <= dataBands; pb++) { + aStrides[pb] = aStrides[pb - 1] + pbStride; + } + + strOffset = 0; + while (aStrides[dataBands] > stopBand) { + if (strOffset < dataBands) { + strOffset++; + } + for (i = strOffset; i <= dataBands; i++) { + aStrides[i]--; + } + } /* while */ + + for (pb = 0; pb < dataBands; pb++) { + cmpOldData[startBand + pb] = oldData[aStrides[pb]]; + cmpIdxData[0][startBand + pb] = data[ps][aStrides[pb]]; + + if (losslessData->bsDataPair[paramIdx][ps]) { + cmpIdxData[1][startBand + pb] = data[ps + 1][aStrides[pb]]; + } + } /* for pb*/ + + /* Finally encode */ + if (losslessData->bsDataPair[paramIdx][ps]) { + fdk_sacenc_ecDataPairEnc(bitstream, cmpIdxData, cmpOldData, dataType, 0, + startBand, dataBands, + losslessData->bsQuantCoarseXXX[paramIdx][ps], + independencyFlag && (ps == 0)); + } else { + fdk_sacenc_ecDataSingleEnc(bitstream, cmpIdxData, cmpOldData, dataType, + 0, startBand, dataBands, + losslessData->bsQuantCoarseXXX[paramIdx][ps], + independencyFlag && (ps == 0)); + } + + /* Overwrite old data */ + for (i = startBand; i < stopBand; i++) { + if (losslessData->bsDataPair[paramIdx][ps]) { + oldData[i] = data[ps + 1][i]; + } else { + oldData[i] = data[ps][i]; + } + } + + quantCoarseXXXprev[paramIdx] = + losslessData->bsQuantCoarseXXX[paramIdx][ps]; + + /* Jump forward if we have encoded a data pair */ + if (losslessData->bsDataPair[paramIdx][ps]) { + ps++; + } + + } /* if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE ) */ + } /* for ps */ +} + +/****************************************************************************/ +/* Bitstream formatter interface functions */ +/****************************************************************************/ +static FDK_SACENC_ERROR getBsFreqResIndex(const INT numBands, + INT *const pbsFreqResIndex) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pbsFreqResIndex) { + error = SACENC_INVALID_HANDLE; + } else { + const UCHAR *pFreqResBinTable = FreqResBinTable_LD; + int i; + *pbsFreqResIndex = -1; + + for (i = 0; i < MAX_FREQ_RES_INDEX; i++) { + if (numBands == pFreqResBinTable[i]) { + *pbsFreqResIndex = i; + break; + } + } + if (*pbsFreqResIndex < 0 || *pbsFreqResIndex >= MAX_FREQ_RES_INDEX) { + error = SACENC_INVALID_CONFIG; + } + } + return error; +} + +static FDK_SACENC_ERROR getSamplingFrequencyIndex( + const INT bsSamplingFrequency, INT *const pbsSamplingFrequencyIndex) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pbsSamplingFrequencyIndex) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + *pbsSamplingFrequencyIndex = SAMPLING_FREQUENCY_INDEX_ESCAPE; + + for (i = 0; i < MAX_SAMPLING_FREQUENCY_INDEX; i++) { + if (bsSamplingFrequency == SampleRateTable[i]) { /*spatial sampling rate*/ + *pbsSamplingFrequencyIndex = i; + break; + } + } + } + return error; +} + +/* destroy encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_destroySpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE *selfPtr) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((selfPtr == NULL) || (*selfPtr == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + if (*selfPtr != NULL) { + FDK_FREE_MEMORY_1D(*selfPtr); + } + } + return error; +} + +/* create encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_createSpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE *selfPtr) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == selfPtr) { + error = SACENC_INVALID_HANDLE; + } else { + /* allocate encoder struct */ + FDK_ALLOCATE_MEMORY_1D(*selfPtr, 1, BSF_INSTANCE); + } + return error; + +bail: + fdk_sacenc_destroySpatialBitstreamEncoder(selfPtr); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +/* init encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_initSpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE selfPtr) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (selfPtr == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + /* init/clear */ + clearFrame(&selfPtr->frame); + + } /* valid handle */ + return error; +} + +/* get SpatialSpecificConfig struct */ +SPATIALSPECIFICCONFIG *fdk_sacenc_getSpatialSpecificConfig( + HANDLE_BSF_INSTANCE selfPtr) { + return ((selfPtr == NULL) ? NULL : &(selfPtr->spatialSpecificConfig)); +} + +/* write SpatialSpecificConfig to stream */ +FDK_SACENC_ERROR fdk_sacenc_writeSpatialSpecificConfig( + SPATIALSPECIFICCONFIG *const spatialSpecificConfig, + UCHAR *const pOutputBuffer, const INT outputBufferSize, + INT *const pnOutputBits) { + FDK_SACENC_ERROR error = SACENC_OK; + INT bsSamplingFrequencyIndex = 0; + INT bsFreqRes = 0; + + if ((spatialSpecificConfig == NULL) || (pOutputBuffer == NULL) || + (pnOutputBits == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_BITSTREAM bitstream; + + /* Find FreqRes */ + if (SACENC_OK != (error = getBsFreqResIndex(spatialSpecificConfig->numBands, + &bsFreqRes))) + goto bail; + + /* Find SamplingFrequencyIndex */ + if (SACENC_OK != (error = getSamplingFrequencyIndex( + spatialSpecificConfig->bsSamplingFrequency, + &bsSamplingFrequencyIndex))) + goto bail; + + /* bind extern buffer to bitstream handle */ + FDKinitBitStream(&bitstream, pOutputBuffer, outputBufferSize, 0, BS_WRITER); + + /****************************************************************************/ + /* write to bitstream */ + + FDKwriteBits(&bitstream, bsSamplingFrequencyIndex, 4); + + if (bsSamplingFrequencyIndex == 15) { + FDKwriteBits(&bitstream, spatialSpecificConfig->bsSamplingFrequency, 24); + } + + FDKwriteBits(&bitstream, spatialSpecificConfig->bsFrameLength, 5); + + FDKwriteBits(&bitstream, bsFreqRes, 3); + FDKwriteBits(&bitstream, spatialSpecificConfig->bsTreeConfig, 4); + FDKwriteBits(&bitstream, spatialSpecificConfig->bsQuantMode, 2); + + FDKwriteBits(&bitstream, 0, 1); /* bsArbitraryDownmix */ + + FDKwriteBits(&bitstream, spatialSpecificConfig->bsFixedGainDMX, 3); + + FDKwriteBits(&bitstream, TEMPSHAPE_OFF, 2); + FDKwriteBits(&bitstream, spatialSpecificConfig->bsDecorrConfig, 2); + + FDKbyteAlign(&bitstream, 0); /* byte alignment */ + + /* return number of valid bits in bitstream */ + if ((*pnOutputBits = FDKgetValidBits(&bitstream)) > + (outputBufferSize * 8)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* terminate buffer with alignment */ + FDKbyteAlign(&bitstream, 0); + + } /* valid handle */ + +bail: + return error; +} + +/* get SpatialFrame struct */ +SPATIALFRAME *fdk_sacenc_getSpatialFrame(HANDLE_BSF_INSTANCE selfPtr, + const SPATIALFRAME_TYPE frameType) { + int idx = -1; + + switch (frameType) { + case READ_SPATIALFRAME: + case WRITE_SPATIALFRAME: + idx = 0; + break; + default: + idx = -1; /* invalid configuration */ + } /* switch frameType */ + + return (((selfPtr == NULL) || (idx == -1)) ? NULL : &selfPtr->frame); +} + +static FDK_SACENC_ERROR writeFramingInfo(HANDLE_FDK_BITSTREAM hBitstream, + const FRAMINGINFO *const pFramingInfo, + const INT frameLength) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hBitstream == NULL) || (pFramingInfo == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKwriteBits(hBitstream, pFramingInfo->bsFramingType, 1); + FDKwriteBits(hBitstream, pFramingInfo->numParamSets - 1, 1); + + if (pFramingInfo->bsFramingType) { + int ps = 0; + int numParamSets = pFramingInfo->numParamSets; + + { + for (ps = 0; ps < numParamSets; ps++) { + int bitsParamSlot = 0; + while ((1 << bitsParamSlot) < (frameLength + 1)) bitsParamSlot++; + if (bitsParamSlot > 0) + FDKwriteBits(hBitstream, pFramingInfo->bsParamSlots[ps], + bitsParamSlot); + } + } + } /* pFramingInfo->bsFramingType */ + } /* valid handle */ + + return error; +} + +static FDK_SACENC_ERROR writeSmgData(HANDLE_FDK_BITSTREAM hBitstream, + const SMGDATA *const pSmgData, + const INT numParamSets, + const INT dataBands) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hBitstream == NULL) || (pSmgData == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int i, j; + + for (i = 0; i < numParamSets; i++) { + FDKwriteBits(hBitstream, pSmgData->bsSmoothMode[i], 2); + + if (pSmgData->bsSmoothMode[i] >= 2) { + FDKwriteBits(hBitstream, pSmgData->bsSmoothTime[i], 2); + } + if (pSmgData->bsSmoothMode[i] == 3) { + const int stride = getBsFreqResStride(pSmgData->bsFreqResStride[i]); + FDKwriteBits(hBitstream, pSmgData->bsFreqResStride[i], 2); + for (j = 0; j < dataBands; j += stride) { + FDKwriteBits(hBitstream, pSmgData->bsSmgData[i][j], 1); + } + } + } /* for i */ + } /* valid handle */ + + return error; +} + +static FDK_SACENC_ERROR writeOttData( + HANDLE_FDK_BITSTREAM hBitstream, PREV_OTTDATA *const pPrevOttData, + OTTDATA *const pOttData, const OTTCONFIG ottConfig[SACENC_MAX_NUM_BOXES], + LOSSLESSDATA *const pCLDLosslessData, LOSSLESSDATA *const pICCLosslessData, + const INT numOttBoxes, const INT numBands, const INT numParamSets, + const INT bsIndependencyFlag) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hBitstream == NULL) || (pPrevOttData == NULL) || (pOttData == NULL) || + (ottConfig == NULL) || (pCLDLosslessData == NULL) || + (pICCLosslessData == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + for (i = 0; i < numOttBoxes; i++) { + ecData(hBitstream, pOttData->cld[i], pPrevOttData->cld_old[i], + pPrevOttData->quantCoarseCldPrev[i], pCLDLosslessData, t_CLD, i, + numParamSets, bsIndependencyFlag, 0, ottConfig[i].bsOttBands, 15); + } + { + for (i = 0; i < numOttBoxes; i++) { + { + ecData(hBitstream, pOttData->icc[i], pPrevOttData->icc_old[i], + pPrevOttData->quantCoarseIccPrev[i], pICCLosslessData, t_ICC, + i, numParamSets, bsIndependencyFlag, 0, numBands, 0); + } + } /* for i */ + } + } /* valid handle */ + + return error; +} + +/* write extension frame data to stream */ +static FDK_SACENC_ERROR WriteSpatialExtensionFrame( + HANDLE_FDK_BITSTREAM bitstream, HANDLE_BSF_INSTANCE self) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((bitstream == NULL) || (self == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKbyteAlign(bitstream, 0); + } /* valid handle */ + + return error; +} + +/* write frame data to stream */ +FDK_SACENC_ERROR fdk_sacenc_writeSpatialFrame(UCHAR *const pOutputBuffer, + const INT outputBufferSize, + INT *const pnOutputBits, + HANDLE_BSF_INSTANCE selfPtr) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((pOutputBuffer == NULL) || (pnOutputBits == NULL) || (selfPtr == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + SPATIALFRAME *frame = NULL; + SPATIALSPECIFICCONFIG *config = NULL; + FDK_BITSTREAM bitstream; + + int i, j, numParamSets, numOttBoxes; + + if ((NULL == + (frame = fdk_sacenc_getSpatialFrame(selfPtr, READ_SPATIALFRAME))) || + (NULL == (config = &(selfPtr->spatialSpecificConfig)))) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + numOttBoxes = selfPtr->spatialSpecificConfig.treeDescription.numOttBoxes; + + numParamSets = frame->framingInfo.numParamSets; + + if (frame->bUseBBCues) { + for (i = 0; i < SACENC_MAX_NUM_BOXES; i++) { + /* If a transient was detected, force only the second ps broad band */ + if (numParamSets == 1) { + frame->CLDLosslessData.bsFreqResStrideXXX[i][0] = 3; + frame->ICCLosslessData.bsFreqResStrideXXX[i][0] = 3; + } else { + for (j = 1; j < MAX_NUM_PARAMS; j++) { + frame->CLDLosslessData.bsFreqResStrideXXX[i][j] = 3; + frame->ICCLosslessData.bsFreqResStrideXXX[i][j] = 3; + } + } + } + } /* frame->bUseBBCues */ + + /* bind extern buffer to bitstream handle */ + FDKinitBitStream(&bitstream, pOutputBuffer, outputBufferSize, 0, BS_WRITER); + + if (SACENC_OK != (error = writeFramingInfo( + &bitstream, &(frame->framingInfo), + selfPtr->spatialSpecificConfig.bsFrameLength))) { + goto bail; + } + + /* write bsIndependencyFlag */ + FDKwriteBits(&bitstream, frame->bsIndependencyFlag, 1); + + /* write spatial data to bitstream */ + if (SACENC_OK != + (error = writeOttData(&bitstream, &selfPtr->prevFrameData.prevOttData, + &frame->ottData, config->ottConfig, + &frame->CLDLosslessData, &frame->ICCLosslessData, + numOttBoxes, config->numBands, numParamSets, + frame->bsIndependencyFlag))) { + goto bail; + } + if (SACENC_OK != (error = writeSmgData(&bitstream, &frame->smgData, + numParamSets, config->numBands))) { + goto bail; + } + + /* byte alignment */ + FDKbyteAlign(&bitstream, 0); + + /* Write SpatialExtensionFrame */ + if (SACENC_OK != + (error = WriteSpatialExtensionFrame(&bitstream, selfPtr))) { + goto bail; + } + + if (NULL == + (frame = fdk_sacenc_getSpatialFrame(selfPtr, WRITE_SPATIALFRAME))) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + clearFrame(frame); + + /* return number of valid bits in bitstream */ + if ((*pnOutputBits = FDKgetValidBits(&bitstream)) > + (outputBufferSize * 8)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* terminate buffer with alignment */ + FDKbyteAlign(&bitstream, 0); + + } /* valid handle */ + +bail: + return error; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_bitstream.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_bitstream.h new file mode 100644 index 0000000000000..67b7b5a336854 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_bitstream.h @@ -0,0 +1,296 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): + + Description: Encoder Library Interface + Bitstream Writer + +*******************************************************************************/ + +#ifndef SACENC_BITSTREAM_H +#define SACENC_BITSTREAM_H + +/* Includes ******************************************************************/ +#include "FDK_bitstream.h" +#include "FDK_matrixCalloc.h" +#include "sacenc_lib.h" +#include "sacenc_const.h" + +/* Defines *******************************************************************/ +#define MAX_NUM_BINS 23 +#define MAX_NUM_PARAMS 2 +#define MAX_NUM_OUTPUTCHANNELS SACENC_MAX_OUTPUT_CHANNELS +#define MAX_TIME_SLOTS 32 + +typedef enum { + TREE_212 = 7, + TREE_ESCAPE = 15 + +} TREECONFIG; + +typedef enum { + FREQ_RES_40 = 0, + FREQ_RES_20 = 1, + FREQ_RES_10 = 2, + FREQ_RES_5 = 3 + +} FREQ; + +typedef enum { + QUANTMODE_INVALID = -1, + QUANTMODE_FINE = 0, + QUANTMODE_EBQ1 = 1, + QUANTMODE_EBQ2 = 2 + +} QUANTMODE; + +typedef enum { + TEMPSHAPE_OFF = 0 + +} TEMPSHAPECONFIG; + +typedef enum { + FIXEDGAINDMX_INVALID = -1, + FIXEDGAINDMX_0 = 0, + FIXEDGAINDMX_1 = 1, + FIXEDGAINDMX_2 = 2, + FIXEDGAINDMX_3 = 3, + FIXEDGAINDMX_4 = 4, + FIXEDGAINDMX_5 = 5, + FIXEDGAINDMX_6 = 6, + FIXEDGAINDMX_7 = 7 + +} FIXEDGAINDMXCONFIG; + +typedef enum { + DECORR_INVALID = -1, + DECORR_QMFSPLIT0 = 0, /* QMF splitfreq: 3, 15, 24, 65 */ + DECORR_QMFSPLIT1 = 1, /* QMF splitfreq: 3, 50, 65, 65 */ + DECORR_QMFSPLIT2 = 2 /* QMF splitfreq: 0, 15, 65, 65 */ + +} DECORRCONFIG; + +typedef enum { + DEFAULT = 0, + KEEP = 1, + INTERPOLATE = 2, + FINECOARSE = 3 + +} DATA_MODE; + +typedef enum { + READ_SPATIALFRAME = 0, + WRITE_SPATIALFRAME = 1 + +} SPATIALFRAME_TYPE; + +/* Data Types ****************************************************************/ +typedef struct { + INT numOttBoxes; + INT numInChan; + INT numOutChan; + +} TREEDESCRIPTION; + +typedef struct { + INT bsOttBands; + +} OTTCONFIG; + +typedef struct { + INT bsSamplingFrequency; /* for bsSamplingFrequencyIndex */ + INT bsFrameLength; + INT numBands; /* for bsFreqRes */ + TREECONFIG bsTreeConfig; + QUANTMODE bsQuantMode; + FIXEDGAINDMXCONFIG bsFixedGainDMX; + int bsEnvQuantMode; + DECORRCONFIG bsDecorrConfig; + TREEDESCRIPTION treeDescription; + OTTCONFIG ottConfig[SACENC_MAX_NUM_BOXES]; + +} SPATIALSPECIFICCONFIG; + +typedef struct { + UCHAR bsFramingType; + UCHAR numParamSets; + UCHAR bsParamSlots[MAX_NUM_PARAMS]; + +} FRAMINGINFO; + +typedef struct { + SCHAR cld[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS][MAX_NUM_BINS]; + SCHAR icc[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS][MAX_NUM_BINS]; + +} OTTDATA; + +typedef struct { + UCHAR bsSmoothMode[MAX_NUM_PARAMS]; + UCHAR bsSmoothTime[MAX_NUM_PARAMS]; + UCHAR bsFreqResStride[MAX_NUM_PARAMS]; + UCHAR bsSmgData[MAX_NUM_PARAMS][MAX_NUM_BINS]; + +} SMGDATA; + +typedef struct { + UCHAR bsEnvShapeChannel[MAX_NUM_OUTPUTCHANNELS]; + UCHAR bsEnvShapeData[MAX_NUM_OUTPUTCHANNELS][MAX_TIME_SLOTS]; + +} TEMPSHAPEDATA; + +typedef struct { + UCHAR bsXXXDataMode[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + UCHAR bsDataPair[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + UCHAR bsQuantCoarseXXX[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + UCHAR bsFreqResStrideXXX[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + +} LOSSLESSDATA; + +typedef struct { + FRAMINGINFO framingInfo; + UCHAR bsIndependencyFlag; + OTTDATA ottData; + SMGDATA smgData; + TEMPSHAPEDATA tempShapeData; + LOSSLESSDATA CLDLosslessData; + LOSSLESSDATA ICCLosslessData; + UCHAR bUseBBCues; + +} SPATIALFRAME; + +typedef struct BSF_INSTANCE *HANDLE_BSF_INSTANCE; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +/* destroy encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_destroySpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE *selfPtr); + +/* create encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_createSpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE *selfPtr); + +FDK_SACENC_ERROR fdk_sacenc_initSpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE selfPtr); + +/* get SpatialSpecificConfig struct */ +SPATIALSPECIFICCONFIG *fdk_sacenc_getSpatialSpecificConfig( + HANDLE_BSF_INSTANCE selfPtr); + +/* write SpatialSpecificConfig to stream */ +FDK_SACENC_ERROR fdk_sacenc_writeSpatialSpecificConfig( + SPATIALSPECIFICCONFIG *const spatialSpecificConfig, + UCHAR *const pOutputBuffer, const INT outputBufferSize, + INT *const pnOutputBits); + +/* get SpatialFrame struct */ +SPATIALFRAME *fdk_sacenc_getSpatialFrame(HANDLE_BSF_INSTANCE selfPtr, + const SPATIALFRAME_TYPE frameType); + +/* write frame data to stream */ +FDK_SACENC_ERROR fdk_sacenc_writeSpatialFrame(UCHAR *const pOutputBuffer, + const INT outputBufferSize, + INT *const pnOutputBits, + HANDLE_BSF_INSTANCE selfPtr); + +/* Copy/Save spatial frame data for one parameter set */ +FDK_SACENC_ERROR fdk_sacenc_duplicateParameterSet( + const SPATIALFRAME *const hFrom, const INT setFrom, SPATIALFRAME *const hTo, + const INT setTo); + +#endif /* SACENC_BITSTREAM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_const.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_const.h new file mode 100644 index 0000000000000..c86e765865ead --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_const.h @@ -0,0 +1,126 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Markus Multrus + + Description: Encoder Library Interface + constants to MPEG-4 spatial encoder lib + +*******************************************************************************/ + +#ifndef SACENC_CONST_H +#define SACENC_CONST_H + +/* Includes ******************************************************************/ +#include "machine_type.h" + +/* Defines *******************************************************************/ +#define NUM_QMF_BANDS 64 +#define MAX_QMF_BANDS 128 + +#define SACENC_MAX_NUM_BOXES 1 +#define SACENC_MAX_INPUT_CHANNELS 2 +#define SACENC_MAX_OUTPUT_CHANNELS 1 + +#define SACENC_FLOAT_EPSILON (1e-9f) + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +#endif /* SACENC_CONST_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_delay.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_delay.cpp new file mode 100644 index 0000000000000..f2ed6b0fafb63 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_delay.cpp @@ -0,0 +1,472 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Christian Goettlinger + + Description: Encoder Library Interface + delay management of the encoder + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + This file contains all delay infrastructure + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_delay.h" +#include "sacenc_const.h" +#include "FDK_matrixCalloc.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +struct DELAY { + struct DELAY_CONFIG { + /* Routing Config Switches*/ + INT bDmxAlign; + INT bTimeDomDmx; + INT bMinimizeDelay; + INT bSacTimeAlignmentDynamicOut; + + /* Needed Input Variables*/ + INT nQmfLen; + INT nFrameLen; + INT nSurroundDelay; + INT nArbDmxDelay; + INT nLimiterDelay; + INT nCoreCoderDelay; + INT nSacStreamMuxDelay; + INT nSacTimeAlignment; /* Overwritten, if bSacTimeAlignmentDynamicOut */ + } config; + + /* Variable Delaybuffers -> Delays */ + INT nDmxAlignBuffer; + INT nSurroundAnalysisBuffer; + INT nArbDmxAnalysisBuffer; + INT nOutputAudioBuffer; + INT nBitstreamFrameBuffer; + INT nOutputAudioQmfFrameBuffer; + INT nDiscardOutFrames; + + /* Variable Delaybuffers Computation Variables */ + INT nBitstreamFrameBufferSize; + + /* Output: Infos */ + INT nInfoDmxDelay; /* Delay of the downmixed signal after the space encoder */ + INT nInfoCodecDelay; /* Delay of the whole en-/decoder including CoreCoder */ + INT nInfoDecoderDelay; /* Delay of the Mpeg Surround decoder */ +}; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_delay_Open() +description: initializes Delays +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_delay_Open(HANDLE_DELAY *phDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phDelay) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(*phDelay, 1, struct DELAY); + } + return error; + +bail: + fdk_sacenc_delay_Close(phDelay); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_delay_Close() +description: destructs Delay +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_delay_Close(HANDLE_DELAY *phDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phDelay) { + error = SACENC_INVALID_HANDLE; + } else { + if (NULL != *phDelay) { + FDK_FREE_MEMORY_1D(*phDelay); + } + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_delay_Init(HANDLE_DELAY hDelay, const INT nQmfLen, + const INT nFrameLen, + const INT nCoreCoderDelay, + const INT nSacStreamMuxDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hDelay) { + error = SACENC_INVALID_HANDLE; + } else { + /* Fill structure before calculation */ + FDKmemclear(&hDelay->config, sizeof(hDelay->config)); + + hDelay->config.nQmfLen = nQmfLen; + hDelay->config.nFrameLen = nFrameLen; + hDelay->config.nCoreCoderDelay = nCoreCoderDelay; + hDelay->config.nSacStreamMuxDelay = nSacStreamMuxDelay; + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_delay_SubCalulateBufferDelays() +description: Calculates the Delays of the buffers +returns: Error Code +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_delay_SubCalulateBufferDelays(HANDLE_DELAY hDel) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hDel) { + error = SACENC_INVALID_HANDLE; + } else { + int nEncoderAnDelay, nEncoderSynDelay, nEncoderWinDelay, nDecoderAnDelay, + nDecoderSynDelay, nResidualCoderFrameDelay, + nArbDmxResidualCoderFrameDelay; + + if (hDel->config.bSacTimeAlignmentDynamicOut > 0) { + hDel->config.nSacTimeAlignment = 0; + } + + { + nEncoderAnDelay = + 2 * hDel->config.nQmfLen + + hDel->config.nQmfLen / 2; /* Only Ld-QMF Delay, no hybrid */ + nEncoderSynDelay = 1 * hDel->config.nQmfLen + hDel->config.nQmfLen / 2; + nDecoderAnDelay = 2 * hDel->config.nQmfLen + hDel->config.nQmfLen / 2; + nDecoderSynDelay = 1 * hDel->config.nQmfLen + hDel->config.nQmfLen / 2; + nEncoderWinDelay = + hDel->config.nFrameLen / 2; /* WindowLookahead is just half a frame */ + } + + { nResidualCoderFrameDelay = 0; } + + { nArbDmxResidualCoderFrameDelay = 0; } + + /* Calculate variable Buffer-Delays */ + if (hDel->config.bTimeDomDmx == 0) { + /* ArbitraryDmx and TdDmx off */ + int tempDelay; + + hDel->nSurroundAnalysisBuffer = 0; + hDel->nArbDmxAnalysisBuffer = 0; + tempDelay = nEncoderSynDelay + hDel->config.nLimiterDelay + + hDel->config.nCoreCoderDelay + + hDel->config.nSacTimeAlignment + nDecoderAnDelay; + tempDelay = (nResidualCoderFrameDelay * hDel->config.nFrameLen) + + hDel->config.nSacStreamMuxDelay - tempDelay; + + if (tempDelay > 0) { + hDel->nBitstreamFrameBuffer = 0; + hDel->nOutputAudioBuffer = tempDelay; + } else { + tempDelay = -tempDelay; + hDel->nBitstreamFrameBuffer = + (tempDelay + hDel->config.nFrameLen - 1) / hDel->config.nFrameLen; + hDel->nOutputAudioBuffer = + (hDel->nBitstreamFrameBuffer * hDel->config.nFrameLen) - tempDelay; + } + + hDel->nOutputAudioQmfFrameBuffer = + (hDel->nOutputAudioBuffer + (hDel->config.nQmfLen / 2) - 1) / + hDel->config.nQmfLen; + + if (hDel->config.bDmxAlign > 0) { + tempDelay = nEncoderWinDelay + nEncoderAnDelay + nEncoderSynDelay + + hDel->nOutputAudioBuffer + hDel->config.nLimiterDelay + + hDel->config.nCoreCoderDelay; + hDel->nDiscardOutFrames = + (tempDelay + hDel->config.nFrameLen - 1) / hDel->config.nFrameLen; + hDel->nDmxAlignBuffer = + hDel->nDiscardOutFrames * hDel->config.nFrameLen - tempDelay; + } else { + hDel->nDiscardOutFrames = 0; + hDel->nDmxAlignBuffer = 0; + } + + /* Output: Info-Variables */ + hDel->nInfoDmxDelay = hDel->nSurroundAnalysisBuffer + nEncoderAnDelay + + nEncoderWinDelay + nEncoderSynDelay + + hDel->nOutputAudioBuffer + + hDel->config.nLimiterDelay; + hDel->nInfoCodecDelay = + hDel->nInfoDmxDelay + hDel->config.nCoreCoderDelay + + hDel->config.nSacTimeAlignment + nDecoderAnDelay + nDecoderSynDelay; + + } else { + /* ArbitraryDmx or TdDmx on */ + int tempDelay1, tempDelay2, tempDelay12, tempDelay3; + + tempDelay1 = hDel->config.nArbDmxDelay - hDel->config.nSurroundDelay; + + if (tempDelay1 >= 0) { + hDel->nSurroundAnalysisBuffer = tempDelay1; + hDel->nArbDmxAnalysisBuffer = 0; + } else { + hDel->nSurroundAnalysisBuffer = 0; + hDel->nArbDmxAnalysisBuffer = -tempDelay1; + } + + tempDelay1 = nEncoderWinDelay + hDel->config.nSurroundDelay + + hDel->nSurroundAnalysisBuffer + + nEncoderAnDelay; /*Surround Path*/ + tempDelay2 = nEncoderWinDelay + hDel->config.nArbDmxDelay + + hDel->nArbDmxAnalysisBuffer + + nEncoderAnDelay; /* ArbDmx Compare Path */ + tempDelay3 = hDel->config.nArbDmxDelay + hDel->config.nLimiterDelay + + hDel->config.nCoreCoderDelay + + hDel->config.nSacTimeAlignment + + nDecoderAnDelay; /* ArbDmx Passthrough*/ + + tempDelay12 = + FDKmax(nResidualCoderFrameDelay, nArbDmxResidualCoderFrameDelay) * + hDel->config.nFrameLen; + tempDelay12 += hDel->config.nSacStreamMuxDelay; + + if (tempDelay1 > tempDelay2) { + tempDelay12 += tempDelay1; + } else { + tempDelay12 += tempDelay2; + } + + if (tempDelay3 > tempDelay12) { + if (hDel->config.bMinimizeDelay > 0) { + hDel->nBitstreamFrameBuffer = + (tempDelay3 - tempDelay12) / hDel->config.nFrameLen; /*floor*/ + hDel->nOutputAudioBuffer = 0; + hDel->nSurroundAnalysisBuffer += + (tempDelay3 - tempDelay12 - + (hDel->nBitstreamFrameBuffer * hDel->config.nFrameLen)); + hDel->nArbDmxAnalysisBuffer += + (tempDelay3 - tempDelay12 - + (hDel->nBitstreamFrameBuffer * hDel->config.nFrameLen)); + } else { + hDel->nBitstreamFrameBuffer = + ((tempDelay3 - tempDelay12) + hDel->config.nFrameLen - 1) / + hDel->config.nFrameLen; + hDel->nOutputAudioBuffer = + hDel->nBitstreamFrameBuffer * hDel->config.nFrameLen + + tempDelay12 - tempDelay3; + } + } else { + hDel->nBitstreamFrameBuffer = 0; + hDel->nOutputAudioBuffer = tempDelay12 - tempDelay3; + } + + if (hDel->config.bDmxAlign > 0) { + int tempDelay = hDel->config.nArbDmxDelay + hDel->nOutputAudioBuffer + + hDel->config.nLimiterDelay + + hDel->config.nCoreCoderDelay; + hDel->nDiscardOutFrames = + (tempDelay + hDel->config.nFrameLen - 1) / hDel->config.nFrameLen; + hDel->nDmxAlignBuffer = + hDel->nDiscardOutFrames * hDel->config.nFrameLen - tempDelay; + } else { + hDel->nDiscardOutFrames = 0; + hDel->nDmxAlignBuffer = 0; + } + + /* Output: Info-Variables */ + hDel->nInfoDmxDelay = hDel->config.nArbDmxDelay + + hDel->nOutputAudioBuffer + + hDel->config.nLimiterDelay; + hDel->nInfoCodecDelay = + hDel->nInfoDmxDelay + hDel->config.nCoreCoderDelay + + hDel->config.nSacTimeAlignment + nDecoderAnDelay + nDecoderSynDelay; + hDel->nInfoDecoderDelay = nDecoderAnDelay + nDecoderSynDelay; + + } /* ArbitraryDmx or TdDmx on */ + + /* Additonal Variables needed for Computation Issues */ + hDel->nBitstreamFrameBufferSize = hDel->nBitstreamFrameBuffer + 1; + } + + return error; +} + +static FDK_SACENC_ERROR assignParameterInRange( + const INT startRange, /* including startRange */ + const INT stopRange, /* including stopRange */ + const INT value, /* value to write*/ + INT *const ptr /* destination pointer*/ +) { + FDK_SACENC_ERROR error = SACENC_INVALID_CONFIG; + + if ((startRange <= value) && (value <= stopRange)) { + *ptr = value; + error = SACENC_OK; + } + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetDmxAlign(HANDLE_DELAY hDelay, + const INT bDmxAlignIn) { + return (assignParameterInRange(0, 1, bDmxAlignIn, &hDelay->config.bDmxAlign)); +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetTimeDomDmx(HANDLE_DELAY hDelay, + const INT bTimeDomDmxIn) { + return ( + assignParameterInRange(0, 1, bTimeDomDmxIn, &hDelay->config.bTimeDomDmx)); +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetSacTimeAlignmentDynamicOut( + HANDLE_DELAY hDelay, const INT bSacTimeAlignmentDynamicOutIn) { + return (assignParameterInRange(0, 1, bSacTimeAlignmentDynamicOutIn, + &hDelay->config.bSacTimeAlignmentDynamicOut)); +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetNSacTimeAlignment( + HANDLE_DELAY hDelay, const INT nSacTimeAlignmentIn) { + return (assignParameterInRange(-32768, 32767, nSacTimeAlignmentIn, + &hDelay->config.nSacTimeAlignment)); +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetMinimizeDelay(HANDLE_DELAY hDelay, + const INT bMinimizeDelay) { + return (assignParameterInRange(0, 1, bMinimizeDelay, + &hDelay->config.bMinimizeDelay)); +} + +INT fdk_sacenc_delay_GetOutputAudioBufferDelay(HANDLE_DELAY hDelay) { + return (hDelay->nOutputAudioBuffer); +} + +INT fdk_sacenc_delay_GetSurroundAnalysisBufferDelay(HANDLE_DELAY hDelay) { + return (hDelay->nSurroundAnalysisBuffer); +} + +INT fdk_sacenc_delay_GetArbDmxAnalysisBufferDelay(HANDLE_DELAY hDelay) { + return (hDelay->nArbDmxAnalysisBuffer); +} + +INT fdk_sacenc_delay_GetBitstreamFrameBufferSize(HANDLE_DELAY hDelay) { + return (hDelay->nBitstreamFrameBufferSize); +} + +INT fdk_sacenc_delay_GetDmxAlignBufferDelay(HANDLE_DELAY hDelay) { + return (hDelay->nDmxAlignBuffer); +} + +INT fdk_sacenc_delay_GetDiscardOutFrames(HANDLE_DELAY hDelay) { + return (hDelay->nDiscardOutFrames); +} + +INT fdk_sacenc_delay_GetInfoDmxDelay(HANDLE_DELAY hDelay) { + return (hDelay->nInfoDmxDelay); +} + +INT fdk_sacenc_delay_GetInfoCodecDelay(HANDLE_DELAY hDelay) { + return (hDelay->nInfoCodecDelay); +} + +INT fdk_sacenc_delay_GetInfoDecoderDelay(HANDLE_DELAY hDelay) { + return (hDelay->nInfoDecoderDelay); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_delay.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_delay.h new file mode 100644 index 0000000000000..38bfbc5bfa8ea --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_delay.h @@ -0,0 +1,175 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Christian Goettlinger + + Description: Encoder Library Interface + delay management of the encoder + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + ******************************************************************************/ +#ifndef SACENC_DELAY_H +#define SACENC_DELAY_H + +/* Includes ******************************************************************/ +#include "sacenc_lib.h" +#include "machine_type.h" +#include "FDK_matrixCalloc.h" + +/* Defines *******************************************************************/ +#define MAX_DELAY_INPUT 1024 +#define MAX_DELAY_OUTPUT 4096 +/* bumped from 0 to 5. this should be equal or larger to the dualrate sbr + * resampler filter length */ +#define MAX_DELAY_SURROUND_ANALYSIS 5 +#define MAX_BITSTREAM_DELAY 1 + +/* Data Types ****************************************************************/ +typedef struct DELAY *HANDLE_DELAY; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_delay_Open(HANDLE_DELAY *phDelay); + +FDK_SACENC_ERROR fdk_sacenc_delay_Close(HANDLE_DELAY *phDelay); + +FDK_SACENC_ERROR fdk_sacenc_delay_Init(HANDLE_DELAY hDelay, const INT nQmfLen, + const INT nFrameLen, + const INT nCoreCoderDelay, + const INT nSacStreamMuxDelay); + +FDK_SACENC_ERROR fdk_sacenc_delay_SubCalulateBufferDelays(HANDLE_DELAY hDel); + +/* Set Expert Config Parameters */ +FDK_SACENC_ERROR fdk_sacenc_delay_SetDmxAlign(HANDLE_DELAY hDelay, + const INT bDmxAlignIn); + +FDK_SACENC_ERROR fdk_sacenc_delay_SetTimeDomDmx(HANDLE_DELAY hDelay, + const INT bTimeDomDmxIn); + +FDK_SACENC_ERROR fdk_sacenc_delay_SetSacTimeAlignmentDynamicOut( + HANDLE_DELAY hDelay, const INT bSacTimeAlignmentDynamicOutIn); + +FDK_SACENC_ERROR fdk_sacenc_delay_SetNSacTimeAlignment( + HANDLE_DELAY hDelay, const INT nSacTimeAlignmentIn); + +FDK_SACENC_ERROR fdk_sacenc_delay_SetMinimizeDelay(HANDLE_DELAY hDelay, + const INT bMinimizeDelay); + +/* Get Internal Variables */ +INT fdk_sacenc_delay_GetOutputAudioBufferDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetSurroundAnalysisBufferDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetArbDmxAnalysisBufferDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetBitstreamFrameBufferSize(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetDmxAlignBufferDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetDiscardOutFrames(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetInfoDmxDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetInfoCodecDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetInfoDecoderDelay(HANDLE_DELAY hDelay); + +#endif /* SACENC_DELAY_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_dmx_tdom_enh.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_dmx_tdom_enh.cpp new file mode 100644 index 0000000000000..be66c83809cf1 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_dmx_tdom_enh.cpp @@ -0,0 +1,639 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Luis Valero + + Description: Enhanced Time Domain Downmix + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_dmx_tdom_enh.h" + +#include "FDK_matrixCalloc.h" +#include "FDK_trigFcts.h" +#include "fixpoint_math.h" + +/* Defines *******************************************************************/ +#define PI_FLT 3.1415926535897931f +#define ALPHA_FLT 0.0001f + +#define PI_E (2) +#define PI_M (FL2FXCONST_DBL(PI_FLT / (1 << PI_E))) + +#define ALPHA_E (13) +#define ALPHA_M (FL2FXCONST_DBL(ALPHA_FLT * (1 << ALPHA_E))) + +enum { L = 0, R = 1 }; + +/* Data Types ****************************************************************/ +typedef struct T_ENHANCED_TIME_DOMAIN_DMX { + int maxFramelength; + + int framelength; + + FIXP_DBL prev_gain_m[2]; + INT prev_gain_e; + FIXP_DBL prev_H1_m[2]; + INT prev_H1_e; + + FIXP_DBL *sinusWindow_m; + SCHAR sinusWindow_e; + + FIXP_DBL prev_Left_m; + INT prev_Left_e; + FIXP_DBL prev_Right_m; + INT prev_Right_e; + FIXP_DBL prev_XNrg_m; + INT prev_XNrg_e; + + FIXP_DBL lin_bbCld_weight_m; + INT lin_bbCld_weight_e; + FIXP_DBL gain_weight_m[2]; + INT gain_weight_e; + +} ENHANCED_TIME_DOMAIN_DMX; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +static void calculateRatio(const FIXP_DBL sqrt_linCld_m, + const INT sqrt_linCld_e, const FIXP_DBL lin_Cld_m, + const INT lin_Cld_e, const FIXP_DBL Icc_m, + const INT Icc_e, FIXP_DBL G_m[2], INT *G_e); + +static void calculateDmxGains(const FIXP_DBL lin_Cld_m, const INT lin_Cld_e, + const FIXP_DBL lin_Cld2_m, const INT lin_Cld2_e, + const FIXP_DBL Icc_m, const INT Icc_e, + const FIXP_DBL G_m[2], const INT G_e, + FIXP_DBL H1_m[2], INT *pH1_e); + +/* Function / Class Definition ***********************************************/ +static FIXP_DBL invSqrtNorm2(const FIXP_DBL op_m, const INT op_e, + INT *const result_e) { + FIXP_DBL src_m = op_m; + int src_e = op_e; + + if (src_e & 1) { + src_m >>= 1; + src_e += 1; + } + + src_m = invSqrtNorm2(src_m, result_e); + *result_e = (*result_e) - (src_e >> 1); + + return src_m; +} + +static FIXP_DBL sqrtFixp(const FIXP_DBL op_m, const INT op_e, + INT *const result_e) { + FIXP_DBL src_m = op_m; + int src_e = op_e; + + if (src_e & 1) { + src_m >>= 1; + src_e += 1; + } + + *result_e = (src_e >> 1); + return sqrtFixp(src_m); +} + +static FIXP_DBL fixpAdd(const FIXP_DBL src1_m, const INT src1_e, + const FIXP_DBL src2_m, const INT src2_e, + INT *const dst_e) { + FIXP_DBL dst_m; + + if (src1_m == FL2FXCONST_DBL(0.f)) { + *dst_e = src2_e; + dst_m = src2_m; + } else if (src2_m == FL2FXCONST_DBL(0.f)) { + *dst_e = src1_e; + dst_m = src1_m; + } else { + *dst_e = fixMax(src1_e, src2_e) + 1; + dst_m = + scaleValue(src1_m, fixMax((src1_e - (*dst_e)), -(DFRACT_BITS - 1))) + + scaleValue(src2_m, fixMax((src2_e - (*dst_e)), -(DFRACT_BITS - 1))); + } + return dst_m; +} + +/** + * \brief Sum up fixpoint values with best possible accuracy. + * + * \param value1 First input value. + * \param q1 Scaling factor of first input value. + * \param pValue2 Pointer to second input value, will be modified on + * return. + * \param pQ2 Pointer to second scaling factor, will be modified on + * return. + * + * \return void + */ +static void fixpAddNorm(const FIXP_DBL value1, const INT q1, + FIXP_DBL *const pValue2, INT *const pQ2) { + const int headroom1 = fNormz(fixp_abs(value1)) - 1; + const int headroom2 = fNormz(fixp_abs(*pValue2)) - 1; + int resultScale = fixMax(q1 - headroom1, (*pQ2) - headroom2); + + if ((value1 != FL2FXCONST_DBL(0.f)) && (*pValue2 != FL2FXCONST_DBL(0.f))) { + resultScale++; + } + + *pValue2 = + scaleValue(value1, q1 - resultScale) + + scaleValue(*pValue2, fixMax(-(DFRACT_BITS - 1), ((*pQ2) - resultScale))); + *pQ2 = (*pValue2 != (FIXP_DBL)0) ? resultScale : DFRACT_BITS - 1; +} + +FDK_SACENC_ERROR fdk_sacenc_open_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX *phEnhancedTimeDmx, const INT framelength) { + FDK_SACENC_ERROR error = SACENC_OK; + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx = NULL; + + if (NULL == phEnhancedTimeDmx) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(hEnhancedTimeDmx, 1, ENHANCED_TIME_DOMAIN_DMX); + FDK_ALLOCATE_MEMORY_1D(hEnhancedTimeDmx->sinusWindow_m, 1 + framelength, + FIXP_DBL); + hEnhancedTimeDmx->maxFramelength = framelength; + *phEnhancedTimeDmx = hEnhancedTimeDmx; + } + return error; + +bail: + fdk_sacenc_close_enhancedTimeDomainDmx(&hEnhancedTimeDmx); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_init_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx, + const FIXP_DBL *const pInputGain_m, const INT inputGain_e, + const FIXP_DBL outputGain_m, const INT outputGain_e, + const INT framelength) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (hEnhancedTimeDmx == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + int smp; + if (framelength > hEnhancedTimeDmx->maxFramelength) { + error = SACENC_INIT_ERROR; + goto bail; + } + + hEnhancedTimeDmx->framelength = framelength; + + INT deltax_e; + FIXP_DBL deltax_m; + + deltax_m = fDivNormHighPrec( + PI_M, (FIXP_DBL)(2 * hEnhancedTimeDmx->framelength), &deltax_e); + deltax_m = scaleValue(deltax_m, PI_E + deltax_e - (DFRACT_BITS - 1) - 1); + deltax_e = 1; + + for (smp = 0; smp < hEnhancedTimeDmx->framelength + 1; smp++) { + hEnhancedTimeDmx->sinusWindow_m[smp] = + fMult(ALPHA_M, fPow2(fixp_sin(smp * deltax_m, deltax_e))); + } + hEnhancedTimeDmx->sinusWindow_e = -ALPHA_E; + + hEnhancedTimeDmx->prev_Left_m = hEnhancedTimeDmx->prev_Right_m = + hEnhancedTimeDmx->prev_XNrg_m = FL2FXCONST_DBL(0.f); + hEnhancedTimeDmx->prev_Left_e = hEnhancedTimeDmx->prev_Right_e = + hEnhancedTimeDmx->prev_XNrg_e = DFRACT_BITS - 1; + + hEnhancedTimeDmx->lin_bbCld_weight_m = + fDivNormHighPrec(fPow2(pInputGain_m[L]), fPow2(pInputGain_m[R]), + &hEnhancedTimeDmx->lin_bbCld_weight_e); + + hEnhancedTimeDmx->gain_weight_m[L] = fMult(pInputGain_m[L], outputGain_m); + hEnhancedTimeDmx->gain_weight_m[R] = fMult(pInputGain_m[R], outputGain_m); + hEnhancedTimeDmx->gain_weight_e = + -fNorm(fixMax(hEnhancedTimeDmx->gain_weight_m[L], + hEnhancedTimeDmx->gain_weight_m[R])); + + hEnhancedTimeDmx->gain_weight_m[L] = scaleValue( + hEnhancedTimeDmx->gain_weight_m[L], -hEnhancedTimeDmx->gain_weight_e); + hEnhancedTimeDmx->gain_weight_m[R] = scaleValue( + hEnhancedTimeDmx->gain_weight_m[R], -hEnhancedTimeDmx->gain_weight_e); + hEnhancedTimeDmx->gain_weight_e += inputGain_e + outputGain_e; + + hEnhancedTimeDmx->prev_gain_m[L] = hEnhancedTimeDmx->gain_weight_m[L] >> 1; + hEnhancedTimeDmx->prev_gain_m[R] = hEnhancedTimeDmx->gain_weight_m[R] >> 1; + hEnhancedTimeDmx->prev_gain_e = hEnhancedTimeDmx->gain_weight_e + 1; + + hEnhancedTimeDmx->prev_H1_m[L] = + scaleValue(hEnhancedTimeDmx->gain_weight_m[L], -4); + hEnhancedTimeDmx->prev_H1_m[R] = + scaleValue(hEnhancedTimeDmx->gain_weight_m[R], -4); + hEnhancedTimeDmx->prev_H1_e = 2 + 2 + hEnhancedTimeDmx->gain_weight_e; + } +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_apply_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx, + const INT_PCM *const *const inputTime, INT_PCM *const outputTimeDmx, + const INT InputDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hEnhancedTimeDmx) || (NULL == inputTime) || + (NULL == inputTime[L]) || (NULL == inputTime[R]) || + (NULL == outputTimeDmx)) { + error = SACENC_INVALID_HANDLE; + } else { + int smp; + FIXP_DBL lin_bbCld_m, lin_Cld_m, bbCorr_m, sqrt_linCld_m, G_m[2], H1_m[2], + gainLeft_m, gainRight_m; + FIXP_DBL bbNrgLeft_m, bbNrgRight_m, bbXNrg_m, nrgLeft_m, nrgRight_m, nrgX_m; + INT lin_bbCld_e, lin_Cld_e, bbCorr_e, sqrt_linCld_e, G_e, H1_e; + INT bbNrgLeft_e, bbNrgRight_e, bbXNrg_e, nrgLeft_e, nrgRight_e, nrgX_e; + + /* Increase energy time resolution with shorter processing blocks. 128 is an + * empiric value. */ + const int granuleLength = fixMin(128, hEnhancedTimeDmx->framelength); + int granuleShift = + (granuleLength > 1) + ? ((DFRACT_BITS - 1) - fNorm((FIXP_DBL)(granuleLength - 1))) + : 0; + granuleShift = fixMax( + 3, granuleShift + + 1); /* one bit more headroom for worst case accumulation */ + + smp = 0; + + /* Prevent division by zero. */ + bbNrgLeft_m = bbNrgRight_m = bbXNrg_m = (FIXP_DBL)(1); + bbNrgLeft_e = bbNrgRight_e = bbXNrg_e = 0; + + do { + const int offset = smp; + FIXP_DBL partialL, partialR, partialX; + partialL = partialR = partialX = FL2FXCONST_DBL(0.f); + + int in_margin = FDKmin( + getScalefactorPCM( + &inputTime[L][offset], + fixMin(offset + granuleLength, hEnhancedTimeDmx->framelength) - + offset, + 1), + getScalefactorPCM( + &inputTime[R][offset], + fixMin(offset + granuleLength, hEnhancedTimeDmx->framelength) - + offset, + 1)); + + /* partial energy */ + for (smp = offset; + smp < fixMin(offset + granuleLength, hEnhancedTimeDmx->framelength); + smp++) { + FIXP_PCM inputL = + scaleValue((FIXP_PCM)inputTime[L][smp], in_margin - 1); + FIXP_PCM inputR = + scaleValue((FIXP_PCM)inputTime[R][smp], in_margin - 1); + + partialL += fPow2Div2(inputL) >> (granuleShift - 3); + partialR += fPow2Div2(inputR) >> (granuleShift - 3); + partialX += fMultDiv2(inputL, inputR) >> (granuleShift - 3); + } + + fixpAddNorm(partialL, granuleShift - 2 * in_margin, &bbNrgLeft_m, + &bbNrgLeft_e); + fixpAddNorm(partialR, granuleShift - 2 * in_margin, &bbNrgRight_m, + &bbNrgRight_e); + fixpAddNorm(partialX, granuleShift - 2 * in_margin, &bbXNrg_m, &bbXNrg_e); + } while (smp < hEnhancedTimeDmx->framelength); + + nrgLeft_m = + fixpAdd(hEnhancedTimeDmx->prev_Left_m, hEnhancedTimeDmx->prev_Left_e, + bbNrgLeft_m, bbNrgLeft_e, &nrgLeft_e); + nrgRight_m = + fixpAdd(hEnhancedTimeDmx->prev_Right_m, hEnhancedTimeDmx->prev_Right_e, + bbNrgRight_m, bbNrgRight_e, &nrgRight_e); + nrgX_m = + fixpAdd(hEnhancedTimeDmx->prev_XNrg_m, hEnhancedTimeDmx->prev_XNrg_e, + bbXNrg_m, bbXNrg_e, &nrgX_e); + + lin_bbCld_m = fMult(hEnhancedTimeDmx->lin_bbCld_weight_m, + fDivNorm(nrgLeft_m, nrgRight_m, &lin_bbCld_e)); + lin_bbCld_e += + hEnhancedTimeDmx->lin_bbCld_weight_e + nrgLeft_e - nrgRight_e; + + bbCorr_m = fMult(nrgX_m, invSqrtNorm2(fMult(nrgLeft_m, nrgRight_m), + nrgLeft_e + nrgRight_e, &bbCorr_e)); + bbCorr_e += nrgX_e; + + hEnhancedTimeDmx->prev_Left_m = bbNrgLeft_m; + hEnhancedTimeDmx->prev_Left_e = bbNrgLeft_e; + hEnhancedTimeDmx->prev_Right_m = bbNrgRight_m; + hEnhancedTimeDmx->prev_Right_e = bbNrgRight_e; + hEnhancedTimeDmx->prev_XNrg_m = bbXNrg_m; + hEnhancedTimeDmx->prev_XNrg_e = bbXNrg_e; + + /* + bbCld = 10.f*log10(lin_bbCld) + + lin_Cld = pow(10,bbCld/20) + = pow(10,10.f*log10(lin_bbCld)/20.f) + = sqrt(lin_bbCld) + + lin_Cld2 = lin_Cld*lin_Cld + = sqrt(lin_bbCld)*sqrt(lin_bbCld) + = lin_bbCld + */ + lin_Cld_m = sqrtFixp(lin_bbCld_m, lin_bbCld_e, &lin_Cld_e); + sqrt_linCld_m = sqrtFixp(lin_Cld_m, lin_Cld_e, &sqrt_linCld_e); + + /*calculate how much right and how much left signal, to avoid signal + * cancellations*/ + calculateRatio(sqrt_linCld_m, sqrt_linCld_e, lin_Cld_m, lin_Cld_e, bbCorr_m, + bbCorr_e, G_m, &G_e); + + /*calculate downmix gains*/ + calculateDmxGains(lin_Cld_m, lin_Cld_e, lin_bbCld_m, lin_bbCld_e, bbCorr_m, + bbCorr_e, G_m, G_e, H1_m, &H1_e); + + /*adapt output gains*/ + H1_m[L] = fMult(H1_m[L], hEnhancedTimeDmx->gain_weight_m[L]); + H1_m[R] = fMult(H1_m[R], hEnhancedTimeDmx->gain_weight_m[R]); + H1_e += hEnhancedTimeDmx->gain_weight_e; + + gainLeft_m = hEnhancedTimeDmx->prev_gain_m[L]; + gainRight_m = hEnhancedTimeDmx->prev_gain_m[R]; + + INT intermediate_gain_e = + +hEnhancedTimeDmx->sinusWindow_e + H1_e - hEnhancedTimeDmx->prev_gain_e; + + for (smp = 0; smp < hEnhancedTimeDmx->framelength; smp++) { + const INT N = hEnhancedTimeDmx->framelength; + FIXP_DBL intermediate_gainLeft_m, intermediate_gainRight_m, tmp; + + intermediate_gainLeft_m = + scaleValue((fMult(hEnhancedTimeDmx->sinusWindow_m[smp], H1_m[L]) + + fMult(hEnhancedTimeDmx->sinusWindow_m[N - smp], + hEnhancedTimeDmx->prev_H1_m[L])), + intermediate_gain_e); + intermediate_gainRight_m = + scaleValue((fMult(hEnhancedTimeDmx->sinusWindow_m[smp], H1_m[R]) + + fMult(hEnhancedTimeDmx->sinusWindow_m[N - smp], + hEnhancedTimeDmx->prev_H1_m[R])), + intermediate_gain_e); + + gainLeft_m = intermediate_gainLeft_m + + fMult(FL2FXCONST_DBL(1.f - ALPHA_FLT), gainLeft_m); + gainRight_m = intermediate_gainRight_m + + fMult(FL2FXCONST_DBL(1.f - ALPHA_FLT), gainRight_m); + + tmp = fMultDiv2(gainLeft_m, (FIXP_PCM)inputTime[L][smp + InputDelay]) + + fMultDiv2(gainRight_m, (FIXP_PCM)inputTime[R][smp + InputDelay]); + outputTimeDmx[smp] = (INT_PCM)SATURATE_SHIFT( + tmp, + -(hEnhancedTimeDmx->prev_gain_e + 1 - (DFRACT_BITS - SAMPLE_BITS)), + SAMPLE_BITS); + } + + hEnhancedTimeDmx->prev_gain_m[L] = gainLeft_m; + hEnhancedTimeDmx->prev_gain_m[R] = gainRight_m; + + hEnhancedTimeDmx->prev_H1_m[L] = H1_m[L]; + hEnhancedTimeDmx->prev_H1_m[R] = H1_m[R]; + hEnhancedTimeDmx->prev_H1_e = H1_e; + } + + return error; +} + +static void calculateRatio(const FIXP_DBL sqrt_linCld_m, + const INT sqrt_linCld_e, const FIXP_DBL lin_Cld_m, + const INT lin_Cld_e, const FIXP_DBL Icc_m, + const INT Icc_e, FIXP_DBL G_m[2], INT *G_e) { +#define G_SCALE_FACTOR (2) + + if (Icc_m >= FL2FXCONST_DBL(0.f)) { + G_m[0] = G_m[1] = FL2FXCONST_DBL(1.f / (float)(1 << G_SCALE_FACTOR)); + G_e[0] = G_SCALE_FACTOR; + } else { + const FIXP_DBL max_gain_factor = + FL2FXCONST_DBL(2.f / (float)(1 << G_SCALE_FACTOR)); + FIXP_DBL tmp1_m, tmp2_m, numerator_m, denominator_m, r_m, r4_m, q; + INT tmp1_e, tmp2_e, numerator_e, denominator_e, r_e, r4_e; + + /* r = (lin_Cld + 1 + 2*Icc*sqrt_linCld) / (lin_Cld + 1 - + * 2*Icc*sqrt_linCld) = (tmp1 + tmp2) / (tmp1 - tmp2) + */ + tmp1_m = + fixpAdd(lin_Cld_m, lin_Cld_e, FL2FXCONST_DBL(1.f / 2.f), 1, &tmp1_e); + + tmp2_m = fMult(Icc_m, sqrt_linCld_m); + tmp2_e = 1 + Icc_e + sqrt_linCld_e; + numerator_m = fixpAdd(tmp1_m, tmp1_e, tmp2_m, tmp2_e, &numerator_e); + denominator_m = fixpAdd(tmp1_m, tmp1_e, -tmp2_m, tmp2_e, &denominator_e); + + if ((numerator_m > FL2FXCONST_DBL(0.f)) && + (denominator_m > FL2FXCONST_DBL(0.f))) { + r_m = fDivNorm(numerator_m, denominator_m, &r_e); + r_e += numerator_e - denominator_e; + + /* r_4 = sqrt( sqrt( r ) ) */ + r4_m = sqrtFixp(r_m, r_e, &r4_e); + r4_m = sqrtFixp(r4_m, r4_e, &r4_e); + + r4_e -= G_SCALE_FACTOR; + + /* q = min(r4_m, max_gain_factor) */ + q = ((r4_e >= 0) && (r4_m >= (max_gain_factor >> r4_e))) + ? max_gain_factor + : scaleValue(r4_m, r4_e); + } else { + q = FL2FXCONST_DBL(0.f); + } + + G_m[0] = max_gain_factor - q; + G_m[1] = q; + + *G_e = G_SCALE_FACTOR; + } +} + +static void calculateDmxGains(const FIXP_DBL lin_Cld_m, const INT lin_Cld_e, + const FIXP_DBL lin_Cld2_m, const INT lin_Cld2_e, + const FIXP_DBL Icc_m, const INT Icc_e, + const FIXP_DBL G_m[2], const INT G_e, + FIXP_DBL H1_m[2], INT *pH1_e) { +#define H1_SCALE_FACTOR (2) + const FIXP_DBL max_gain_factor = + FL2FXCONST_DBL(2.f / (float)(1 << H1_SCALE_FACTOR)); + + FIXP_DBL nrgRight_m, nrgLeft_m, crossNrg_m, inv_weight_num_m, + inv_weight_denom_m, inverse_weight_m, inverse_weight_limited; + INT nrgRight_e, nrgLeft_e, crossNrg_e, inv_weight_num_e, inv_weight_denom_e, + inverse_weight_e; + + /* nrgRight = sqrt(1/(lin_Cld2 + 1) */ + nrgRight_m = fixpAdd(lin_Cld2_m, lin_Cld2_e, FL2FXCONST_DBL(1.f / 2.f), 1, + &nrgRight_e); + nrgRight_m = invSqrtNorm2(nrgRight_m, nrgRight_e, &nrgRight_e); + + /* nrgLeft = lin_Cld * nrgRight */ + nrgLeft_m = fMult(lin_Cld_m, nrgRight_m); + nrgLeft_e = lin_Cld_e + nrgRight_e; + + /* crossNrg = sqrt(nrgLeft*nrgRight) */ + crossNrg_m = sqrtFixp(fMult(nrgLeft_m, nrgRight_m), nrgLeft_e + nrgRight_e, + &crossNrg_e); + + /* inverse_weight = sqrt((nrgLeft + nrgRight) / ( (G[0]*G[0]*nrgLeft) + + * (G[1]*G[1]*nrgRight) + 2*G[0]*G[1]*Icc*crossNrg)) = sqrt(inv_weight_num / + * inv_weight_denom) + */ + inv_weight_num_m = + fixpAdd(nrgRight_m, nrgRight_e, nrgLeft_m, nrgLeft_e, &inv_weight_num_e); + + inv_weight_denom_m = + fixpAdd(fMult(fPow2(G_m[0]), nrgLeft_m), 2 * G_e + nrgLeft_e, + fMult(fPow2(G_m[1]), nrgRight_m), 2 * G_e + nrgRight_e, + &inv_weight_denom_e); + + inv_weight_denom_m = + fixpAdd(fMult(fMult(fMult(G_m[0], G_m[1]), crossNrg_m), Icc_m), + 1 + 2 * G_e + crossNrg_e + Icc_e, inv_weight_denom_m, + inv_weight_denom_e, &inv_weight_denom_e); + + if (inv_weight_denom_m > FL2FXCONST_DBL(0.f)) { + inverse_weight_m = + fDivNorm(inv_weight_num_m, inv_weight_denom_m, &inverse_weight_e); + inverse_weight_m = + sqrtFixp(inverse_weight_m, + inverse_weight_e + inv_weight_num_e - inv_weight_denom_e, + &inverse_weight_e); + inverse_weight_e -= H1_SCALE_FACTOR; + + /* inverse_weight_limited = min(max_gain_factor, inverse_weight) */ + inverse_weight_limited = + ((inverse_weight_e >= 0) && + (inverse_weight_m >= (max_gain_factor >> inverse_weight_e))) + ? max_gain_factor + : scaleValue(inverse_weight_m, inverse_weight_e); + } else { + inverse_weight_limited = max_gain_factor; + } + + H1_m[0] = fMult(G_m[0], inverse_weight_limited); + H1_m[1] = fMult(G_m[1], inverse_weight_limited); + + *pH1_e = G_e + H1_SCALE_FACTOR; +} + +FDK_SACENC_ERROR fdk_sacenc_close_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX *phEnhancedTimeDmx) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (phEnhancedTimeDmx == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + if (*phEnhancedTimeDmx != NULL) { + if ((*phEnhancedTimeDmx)->sinusWindow_m != NULL) { + FDK_FREE_MEMORY_1D((*phEnhancedTimeDmx)->sinusWindow_m); + } + FDK_FREE_MEMORY_1D(*phEnhancedTimeDmx); + } + } + return error; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_dmx_tdom_enh.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_dmx_tdom_enh.h new file mode 100644 index 0000000000000..0b39911d0aa90 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_dmx_tdom_enh.h @@ -0,0 +1,134 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Luis Valero + + Description: Enhanced Time Domain Downmix + +*******************************************************************************/ + +#ifndef SACENC_DMX_TDOM_ENH_H +#define SACENC_DMX_TDOM_ENH_H + +/* Includes ******************************************************************/ +#include "sacenc_lib.h" +#include "common_fix.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +typedef struct T_ENHANCED_TIME_DOMAIN_DMX *HANDLE_ENHANCED_TIME_DOMAIN_DMX; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_open_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX *hEnhancedTimeDmx, const INT framelength); + +FDK_SACENC_ERROR fdk_sacenc_init_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx, + const FIXP_DBL *const pInputGain_m, const INT inputGain_e, + const FIXP_DBL outputGain_m, const INT outputGain_e, const INT framelength); + +FDK_SACENC_ERROR fdk_sacenc_apply_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx, + const INT_PCM *const *const inputTime, INT_PCM *const outputTimeDmx, + const INT InputDelay); + +FDK_SACENC_ERROR fdk_sacenc_close_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX *hEnhancedTimeDmx); + +#endif /* SACENC_DMX_TDOM_ENH_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_filter.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_filter.cpp new file mode 100644 index 0000000000000..79f0797b2c019 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_filter.cpp @@ -0,0 +1,207 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Encoder Library + Filter functions + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_filter.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +typedef struct T_DC_FILTER { + FIXP_DBL c__FDK; + FIXP_DBL state__FDK; + +} DC_FILTER; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +FDK_SACENC_ERROR fdk_sacenc_createDCFilter(HANDLE_DC_FILTER *hDCFilter) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hDCFilter) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(*hDCFilter, 1, DC_FILTER); + } + return error; + +bail: + fdk_sacenc_destroyDCFilter(hDCFilter); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_initDCFilter(HANDLE_DC_FILTER hDCFilter, + const UINT sampleRate) { + FDK_SACENC_ERROR error = SACENC_OK; + + FIXP_DBL expC; + int s; + + /* Conversion for use of CalcInvLdData: e^x = 2^(x*log10(e)/log10(2) = + CalcInvLdData(x*log10(e)/log10(2)/64.0) 1.44269504089 = log10(e)/log10(2) + 0.5 = scale constant value with 1 Bits + */ + expC = fDivNormHighPrec((FIXP_DBL)20, (FIXP_DBL)sampleRate, &s); + expC = fMultDiv2(FL2FXCONST_DBL(-1.44269504089 * 0.5), expC) >> + (LD_DATA_SHIFT - 1 - 1); + + if (s < 0) + expC = expC >> (-s); + else + expC = expC << (s); + + expC = CalcInvLdData(expC); + + hDCFilter->c__FDK = expC; + hDCFilter->state__FDK = FL2FXCONST_DBL(0.0f); + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_destroyDCFilter(HANDLE_DC_FILTER *hDCFilter) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hDCFilter != NULL) && (*hDCFilter != NULL)) { + FDKfree(*hDCFilter); + + *hDCFilter = NULL; + } + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_applyDCFilter(HANDLE_DC_FILTER hDCFilter, + const INT_PCM *const signalIn, + INT_PCM *const signalOut, + const INT signalLength) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hDCFilter == NULL) || (signalIn == NULL) || (signalOut == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + const INT_PCM *const x = signalIn; + INT_PCM *const y = signalOut; + const FIXP_DBL c = hDCFilter->c__FDK; + FIXP_DBL *const state = &hDCFilter->state__FDK; + int i; + FIXP_DBL x0, x1, y1; + + x1 = x0 = FX_PCM2FX_DBL(x[0]) >> DC_FILTER_SF; + y1 = x0 + (*state); + + for (i = 1; i < signalLength; i++) { + x0 = FX_PCM2FX_DBL(x[i]) >> DC_FILTER_SF; + y[i - 1] = FX_DBL2FX_PCM(y1); + y1 = x0 - x1 + fMult(c, y1); + x1 = x0; + } + + *state = fMult(c, y1) - x1; + y[i - 1] = FX_DBL2FX_PCM(y1); + } + + return error; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_filter.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_filter.h new file mode 100644 index 0000000000000..10e3abd60e433 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_filter.h @@ -0,0 +1,133 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Encoder Library Interface + Filter functions + +*******************************************************************************/ + +#ifndef SACENC_FILTER_H +#define SACENC_FILTER_H + +/* Includes ******************************************************************/ +#include "common_fix.h" +#include "sacenc_lib.h" +#include "FDK_matrixCalloc.h" + +/* Defines *******************************************************************/ +#define DC_FILTER_SF 1 + +/* Data Types ****************************************************************/ +typedef struct T_DC_FILTER *HANDLE_DC_FILTER; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_createDCFilter(HANDLE_DC_FILTER *hDCFilter); + +FDK_SACENC_ERROR fdk_sacenc_initDCFilter(HANDLE_DC_FILTER hDCFilter, + const UINT sampleRate); + +FDK_SACENC_ERROR fdk_sacenc_destroyDCFilter(HANDLE_DC_FILTER *hDCFilter); + +FDK_SACENC_ERROR fdk_sacenc_applyDCFilter(HANDLE_DC_FILTER hDCFilter, + const INT_PCM *const signalIn, + INT_PCM *const signalOut, + const INT signalLength); + +#endif /* SACENC_FILTER_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_framewindowing.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_framewindowing.cpp new file mode 100644 index 0000000000000..15f0f0ad26b10 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_framewindowing.cpp @@ -0,0 +1,568 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Get windows for framing + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + Description of file contents + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_framewindowing.h" +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +typedef struct T_FRAMEWINDOW { + INT nTimeSlotsMax; + INT bFrameKeep; + INT startSlope; + INT stopSlope; + INT startRect; + INT stopRect; + + INT taperAnaLen; + INT taperSynLen; + FIXP_WIN pTaperAna__FDK[MAX_TIME_SLOTS]; + FIXP_WIN pTaperSyn__FDK[MAX_TIME_SLOTS]; + +} FRAMEWINDOW; + +typedef enum { + FIX_INVALID = -1, + FIX_RECT_SMOOTH = 0, + FIX_SMOOTH_RECT = 1, + FIX_LARGE_SMOOTH = 2, + FIX_RECT_TRIANG = 3 + +} FIX_TYPE; + +typedef enum { + VAR_INVALID = -1, + VAR_HOLD = 0, + VAR_ISOLATE = 1 + +} VAR_TYPE; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static void calcTaperWin(FIXP_WIN *pTaperWin, INT timeSlots) { + FIXP_DBL x; + int i, scale; + + for (i = 0; i < timeSlots; i++) { + x = fDivNormHighPrec((FIXP_DBL)i, (FIXP_DBL)timeSlots, &scale); + + if (scale < 0) { + pTaperWin[i] = FX_DBL2FX_WIN(x >> (-scale)); + } else { + pTaperWin[i] = FX_DBL2FX_WIN(x << (scale)); + } + } + pTaperWin[timeSlots] = FX_DBL2FX_WIN((FIXP_DBL)MAXVAL_DBL); +} + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Create( + HANDLE_FRAMEWINDOW *phFrameWindow) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phFrameWindow) { + error = SACENC_INVALID_HANDLE; + } else { + /* Memory Allocation */ + FDK_ALLOCATE_MEMORY_1D(*phFrameWindow, 1, FRAMEWINDOW); + } + return error; + +bail: + fdk_sacenc_frameWindow_Destroy(phFrameWindow); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Init( + HANDLE_FRAMEWINDOW hFrameWindow, + const FRAMEWINDOW_CONFIG *const pFrameWindowConfig) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hFrameWindow == NULL) || (pFrameWindowConfig == NULL)) { + error = SACENC_INVALID_HANDLE; + } else if (pFrameWindowConfig->nTimeSlotsMax < 0) { + error = SACENC_INIT_ERROR; + } else { + int ts; + hFrameWindow->bFrameKeep = pFrameWindowConfig->bFrameKeep; + hFrameWindow->nTimeSlotsMax = pFrameWindowConfig->nTimeSlotsMax; + + FIXP_WIN winMaxVal = FX_DBL2FX_WIN((FIXP_DBL)MAXVAL_DBL); + int timeSlots = pFrameWindowConfig->nTimeSlotsMax; + { + hFrameWindow->startSlope = 0; + hFrameWindow->stopSlope = ((3 * timeSlots) >> 1) - 1; + hFrameWindow->startRect = timeSlots >> 1; + hFrameWindow->stopRect = timeSlots; + calcTaperWin(hFrameWindow->pTaperSyn__FDK, timeSlots >> 1); + hFrameWindow->taperSynLen = timeSlots >> 1; + } + + /* Calculate Taper for non-rect. ana. windows */ + hFrameWindow->taperAnaLen = + hFrameWindow->startRect - hFrameWindow->startSlope; + for (ts = 0; ts < hFrameWindow->taperAnaLen; ts++) { + { hFrameWindow->pTaperAna__FDK[ts] = winMaxVal; } + } + } + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Destroy( + HANDLE_FRAMEWINDOW *phFrameWindow) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL != phFrameWindow) && (NULL != *phFrameWindow)) { + FDKfree(*phFrameWindow); + *phFrameWindow = NULL; + } + return error; +} + +static FDK_SACENC_ERROR FrameWinList_Reset(FRAMEWIN_LIST *const pFrameWinList) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pFrameWinList) { + error = SACENC_INVALID_HANDLE; + } else { + int k = 0; + for (k = 0; k < MAX_NUM_PARAMS; k++) { + pFrameWinList->dat[k].slot = -1; + pFrameWinList->dat[k].hold = FW_INTP; + } + pFrameWinList->n = 0; + } + return error; +} + +static FDK_SACENC_ERROR FrameWindowList_Add(FRAMEWIN_LIST *const pFrameWinList, + const INT slot, + const FW_SLOTTYPE hold) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pFrameWinList) { + error = SACENC_INVALID_HANDLE; + } else { + if (pFrameWinList->n >= MAX_NUM_PARAMS) { /* Place left in List ?*/ + error = SACENC_PARAM_ERROR; + } else if (pFrameWinList->n > 0 && + pFrameWinList->dat[pFrameWinList->n - 1].slot - slot > 0) { + error = SACENC_PARAM_ERROR; + } else { + pFrameWinList->dat[pFrameWinList->n].slot = slot; + pFrameWinList->dat[pFrameWinList->n].hold = hold; + pFrameWinList->n++; + } + } + return error; +} + +static FDK_SACENC_ERROR FrameWindowList_Remove( + FRAMEWIN_LIST *const pFrameWinList, const INT idx) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pFrameWinList) { + error = SACENC_INVALID_HANDLE; + } else { + int k = 0; + if (idx < 0 || idx >= MAX_NUM_PARAMS) { + error = SACENC_PARAM_ERROR; + } else if (pFrameWinList->n > 0) { + if (idx == MAX_NUM_PARAMS - 1) { + pFrameWinList->dat[idx].slot = -1; + pFrameWinList->dat[idx].hold = FW_INTP; + } else { + for (k = idx; k < MAX_NUM_PARAMS - 1; k++) { + pFrameWinList->dat[k] = pFrameWinList->dat[k + 1]; + } + } + pFrameWinList->n--; + } + } + return error; +} + +static FDK_SACENC_ERROR FrameWindowList_Limit( + FRAMEWIN_LIST *const pFrameWinList, const INT ll /*lower limit*/, + const INT ul /*upper limit*/ +) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pFrameWinList) { + error = SACENC_INVALID_HANDLE; + } else { + int k = 0; + for (k = 0; k < pFrameWinList->n; k++) { + if (pFrameWinList->dat[k].slot < ll || pFrameWinList->dat[k].slot > ul) { + FrameWindowList_Remove(pFrameWinList, k); + --k; + } + } + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_GetWindow( + HANDLE_FRAMEWINDOW hFrameWindow, INT tr_pos[MAX_NUM_PARAMS], + const INT timeSlots, FRAMINGINFO *const pFramingInfo, + FIXP_WIN *pWindowAna__FDK[MAX_NUM_PARAMS], + FRAMEWIN_LIST *const pFrameWinList, const INT avoid_keep) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hFrameWindow == NULL) || (tr_pos == NULL) || (pFramingInfo == NULL) || + (pFrameWinList == NULL) || (pWindowAna__FDK == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + const VAR_TYPE varType = VAR_HOLD; + const int tranL = 4; + int winCnt = 0; + int w, ps; + + int startSlope = hFrameWindow->startSlope; + int stopSlope = hFrameWindow->stopSlope; + int startRect = hFrameWindow->startRect; + int stopRect = hFrameWindow->stopRect; + int taperAnaLen = hFrameWindow->taperAnaLen; + + FIXP_WIN winMaxVal = FX_DBL2FX_WIN((FIXP_DBL)MAXVAL_DBL); + FIXP_WIN applyRightWindowGain__FDK[MAX_NUM_PARAMS]; + FIXP_WIN *pTaperAna__FDK = hFrameWindow->pTaperAna__FDK; + + /* sanity check */ + for (ps = 0; ps < MAX_NUM_PARAMS; ps++) { + if (pWindowAna__FDK[ps] == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + } + + if ((timeSlots > hFrameWindow->nTimeSlotsMax) || (timeSlots < 0)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* Reset */ + if (SACENC_OK != (error = FrameWinList_Reset(pFrameWinList))) goto bail; + + FDKmemclear(applyRightWindowGain__FDK, sizeof(applyRightWindowGain__FDK)); + + if (tr_pos[0] > -1) { /* Transients in first (left) half? */ + int p_l = tr_pos[0]; + winCnt = 0; + + /* Create Parameter Positions */ + switch (varType) { + case VAR_HOLD: + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, p_l - 1, FW_HOLD))) + goto bail; + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, p_l, FW_INTP))) + goto bail; + break; + case VAR_ISOLATE: + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, p_l - 1, FW_HOLD))) + goto bail; + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, p_l, FW_INTP))) + goto bail; + if (SACENC_OK != (error = FrameWindowList_Add(pFrameWinList, + p_l + tranL, FW_HOLD))) + goto bail; + if (SACENC_OK != (error = FrameWindowList_Add( + pFrameWinList, p_l + tranL + 1, FW_INTP))) + goto bail; + break; + default: + error = SACENC_INVALID_CONFIG; + break; + } + + /* Outside of frame? => Kick Out */ + if (SACENC_OK != + (error = FrameWindowList_Limit(pFrameWinList, 0, timeSlots - 1))) + goto bail; + + /* Add timeSlots as temporary border for window creation */ + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, timeSlots - 1, FW_HOLD))) + goto bail; + + /* Create Windows */ + for (ps = 0; ps < pFrameWinList->n - 1; ps++) { + if (FW_HOLD != pFrameWinList->dat[ps].hold) { + int const start = pFrameWinList->dat[ps].slot; + int const stop = pFrameWinList->dat[ps + 1].slot; + + /* Analysis Window */ + FDKmemset_flex(pWindowAna__FDK[winCnt], FX_DBL2FX_WIN((FIXP_DBL)0), + start); + FDKmemset_flex(&pWindowAna__FDK[winCnt][start], winMaxVal, + stop - start + 1); + FDKmemset_flex(&pWindowAna__FDK[winCnt][stop + 1], + FX_DBL2FX_WIN((FIXP_DBL)0), timeSlots - stop - 1); + + applyRightWindowGain__FDK[winCnt] = + pWindowAna__FDK[winCnt][timeSlots - 1]; + winCnt++; + } + } /* ps */ + + /* Pop temporary frame border */ + if (SACENC_OK != + (error = FrameWindowList_Remove(pFrameWinList, pFrameWinList->n - 1))) + goto bail; + } else { /* No transient in left half of ana. window */ + winCnt = 0; + + /* Add paramter set at end of frame */ + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, timeSlots - 1, FW_INTP))) + goto bail; + /* Analysis Window */ + FDKmemset_flex(pWindowAna__FDK[winCnt], FX_DBL2FX_WIN((FIXP_DBL)0), + startSlope); + FDKmemcpy_flex(&pWindowAna__FDK[winCnt][startSlope], 1, pTaperAna__FDK, 1, + taperAnaLen); + FDKmemset_flex(&pWindowAna__FDK[winCnt][startRect], winMaxVal, + timeSlots - startRect); + + applyRightWindowGain__FDK[winCnt] = winMaxVal; + winCnt++; + } /* if (tr_pos[0] > -1) */ + + for (w = 0; w < winCnt; w++) { + if (applyRightWindowGain__FDK[w] > (FIXP_WIN)0) { + if (tr_pos[1] > -1) { /* Transients in second (right) half? */ + int p_r = tr_pos[1]; + + /* Analysis Window */ + FDKmemset_flex(&pWindowAna__FDK[w][timeSlots], winMaxVal, + p_r - timeSlots); + FDKmemset_flex(&pWindowAna__FDK[w][p_r], FX_DBL2FX_WIN((FIXP_DBL)0), + 2 * timeSlots - p_r); + + } else { /* No transient in right half of ana. window */ + /* Analysis Window */ + FDKmemset_flex(&pWindowAna__FDK[w][timeSlots], winMaxVal, + stopRect - timeSlots + 1); + FDKmemcpy_flex(&pWindowAna__FDK[w][stopRect], 1, + &pTaperAna__FDK[taperAnaLen - 1], -1, taperAnaLen); + FDKmemset_flex(&pWindowAna__FDK[w][stopSlope + 1], + FX_DBL2FX_WIN((FIXP_DBL)0), + 2 * timeSlots - stopSlope - 1); + + } /* if (tr_pos[1] > -1) */ + + /* Weight */ + if (applyRightWindowGain__FDK[w] < winMaxVal) { + int ts; + for (ts = 0; ts < timeSlots; ts++) { + pWindowAna__FDK[w][timeSlots + ts] = + FX_DBL2FX_WIN(fMult(pWindowAna__FDK[w][timeSlots + ts], + applyRightWindowGain__FDK[w])); + } + } + } /* if (applyRightWindowGain[w] > 0.0f) */ + else { + /* All Zero */ + FDKmemset_flex(&pWindowAna__FDK[w][timeSlots], + FX_DBL2FX_WIN((FIXP_DBL)0), timeSlots); + } + } /* loop over windows */ + + if (hFrameWindow->bFrameKeep == 1) { + FDKmemcpy_flex(&pWindowAna__FDK[0][2 * timeSlots], 1, + &pWindowAna__FDK[0][timeSlots], 1, timeSlots); + FDKmemcpy_flex(&pWindowAna__FDK[0][timeSlots], 1, pWindowAna__FDK[0], 1, + timeSlots); + + if (avoid_keep != 0) { + FDKmemset_flex(pWindowAna__FDK[0], FX_DBL2FX_WIN((FIXP_DBL)0), + timeSlots); + } else { + FDKmemset_flex(pWindowAna__FDK[0], winMaxVal, timeSlots); + } + } /* if (hFrameWindow->bFrameKeep==1) */ + + /* Feed Info to Bitstream Formatter */ + pFramingInfo->numParamSets = pFrameWinList->n; + pFramingInfo->bsFramingType = 1; /* variable framing */ + for (ps = 0; ps < pFramingInfo->numParamSets; ps++) { + pFramingInfo->bsParamSlots[ps] = pFrameWinList->dat[ps].slot; + } + + /* if there is just one param set at last slot, + use fixed framing to save some bits */ + if ((pFramingInfo->numParamSets == 1) && + (pFramingInfo->bsParamSlots[0] == timeSlots - 1)) { + pFramingInfo->bsFramingType = 0; + } + + } /* valid handle */ + +bail: + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_analysisWindowing( + const INT nTimeSlots, const INT startTimeSlot, + FIXP_WIN *pFrameWindowAna__FDK, const FIXP_DPK *const *const ppDataIn__FDK, + FIXP_DPK *const *const ppDataOut__FDK, const INT nHybridBands, + const INT dim) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((pFrameWindowAna__FDK == NULL) || (ppDataIn__FDK == NULL) || + (ppDataOut__FDK == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int i, ts; + FIXP_WIN maxVal = FX_DBL2FX_WIN((FIXP_DBL)MAXVAL_DBL); + + if (dim == FW_CHANGE_DIM) { + for (ts = startTimeSlot; ts < nTimeSlots; ts++) { + FIXP_WIN win = pFrameWindowAna__FDK[ts]; + if (win == maxVal) { + for (i = 0; i < nHybridBands; i++) { + ppDataOut__FDK[i][ts].v.re = ppDataIn__FDK[ts][i].v.re; + ppDataOut__FDK[i][ts].v.im = ppDataIn__FDK[ts][i].v.im; + } + } else { + for (i = 0; i < nHybridBands; i++) { + ppDataOut__FDK[i][ts].v.re = fMult(win, ppDataIn__FDK[ts][i].v.re); + ppDataOut__FDK[i][ts].v.im = fMult(win, ppDataIn__FDK[ts][i].v.im); + } + } + } /* ts */ + } else { + for (ts = startTimeSlot; ts < nTimeSlots; ts++) { + FIXP_WIN win = pFrameWindowAna__FDK[ts]; + if (win == maxVal) { + for (i = 0; i < nHybridBands; i++) { + ppDataOut__FDK[ts][i].v.re = ppDataIn__FDK[ts][i].v.re; + ppDataOut__FDK[ts][i].v.im = ppDataIn__FDK[ts][i].v.im; + } + } else { + for (i = 0; i < nHybridBands; i++) { + ppDataOut__FDK[ts][i].v.re = fMult(win, ppDataIn__FDK[ts][i].v.re); + ppDataOut__FDK[ts][i].v.im = fMult(win, ppDataIn__FDK[ts][i].v.im); + } + } + } /* ts */ + } + } + + return error; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_framewindowing.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_framewindowing.h new file mode 100644 index 0000000000000..6b22dc9b269a6 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_framewindowing.h @@ -0,0 +1,181 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Get windows for framing + +*******************************************************************************/ + +#ifndef SACENC_FRAMEWINDOWING_H +#define SACENC_FRAMEWINDOWING_H + +/**************************************************************************/ /** + \file + Description of file contents + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "genericStds.h" +#include "common_fix.h" +#include "sacenc_lib.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ +#define FIXP_WIN FIXP_DBL +#define FX_DBL2FX_WIN(x) (x) +#define DALDATATYPE_WIN DALDATATYPE_DFRACT + +typedef enum { + FW_INTP = 0, + FW_HOLD = 1 + +} FW_SLOTTYPE; + +typedef enum { + FW_LEAVE_DIM = 0, + FW_CHANGE_DIM = 1 + +} FW_DIMENSION; + +/* Data Types ****************************************************************/ +typedef struct T_FRAMEWINDOW *HANDLE_FRAMEWINDOW; + +typedef struct T_FRAMEWINDOW_CONFIG { + INT nTimeSlotsMax; + INT bFrameKeep; + +} FRAMEWINDOW_CONFIG; + +typedef struct { + INT slot; + FW_SLOTTYPE hold; + +} FRAMEWIN_DATA; + +typedef struct { + FRAMEWIN_DATA dat[MAX_NUM_PARAMS]; + INT n; + +} FRAMEWIN_LIST; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Create( + HANDLE_FRAMEWINDOW *phFrameWindow); + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Init( + HANDLE_FRAMEWINDOW hFrameWindow, + const FRAMEWINDOW_CONFIG *const pFrameWindowConfig); + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Destroy( + HANDLE_FRAMEWINDOW *phFrameWindow); + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_GetWindow( + HANDLE_FRAMEWINDOW hFrameWindow, INT tr_pos[MAX_NUM_PARAMS], + const INT timeSlots, FRAMINGINFO *const pFramingInfo, + FIXP_WIN *pWindowAna__FDK[MAX_NUM_PARAMS], + FRAMEWIN_LIST *const pFrameWinList, const INT avoid_keep); + +FDK_SACENC_ERROR fdk_sacenc_analysisWindowing( + const INT nTimeSlots, const INT startTimeSlot, + FIXP_WIN *pFrameWindowAna__FDK, const FIXP_DPK *const *const ppDataIn__FDK, + FIXP_DPK *const *const ppDataOut__FDK, const INT nHybridBands, + const INT dim); + +#endif /* SACENC_FRAMEWINDOWING_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_huff_tab.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_huff_tab.cpp new file mode 100644 index 0000000000000..7b28ecd1364db --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_huff_tab.cpp @@ -0,0 +1,997 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Markus Lohwasser + + Description: SAC-Encoder constant huffman tables + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_huff_tab.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ +const HUFF_CLD_TABLE fdk_sacenc_huffCLDTab = { + {/* h1D[2][31] */ + {HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000002, 2), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x000001fe, 9), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000007fe, 11), HUFF_PACK(0x00000ffe, 12), + HUFF_PACK(0x00001ffe, 13), HUFF_PACK(0x00007ffe, 15), + HUFF_PACK(0x00007ffc, 15), HUFF_PACK(0x0000fffe, 16), + HUFF_PACK(0x0000fffa, 16), HUFF_PACK(0x0001fffe, 17), + HUFF_PACK(0x0001fff6, 17), HUFF_PACK(0x0003fffe, 18), + HUFF_PACK(0x0003ffff, 18), HUFF_PACK(0x0007ffde, 19), + HUFF_PACK(0x0003ffee, 18), HUFF_PACK(0x000fffbe, 20), + HUFF_PACK(0x001fff7e, 21), HUFF_PACK(0x00fffbfc, 24), + HUFF_PACK(0x00fffbfd, 24), HUFF_PACK(0x00fffbfe, 24), + HUFF_PACK(0x00fffbff, 24), HUFF_PACK(0x007ffdfc, 23), + HUFF_PACK(0x007ffdfd, 23)}, + {HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000002, 2), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x000001fc, 9), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000003fa, 10), HUFF_PACK(0x000007fe, 11), + HUFF_PACK(0x000007f6, 11), HUFF_PACK(0x00000ffe, 12), + HUFF_PACK(0x00000fee, 12), HUFF_PACK(0x00001ffe, 13), + HUFF_PACK(0x00001fde, 13), HUFF_PACK(0x00003ffe, 14), + HUFF_PACK(0x00003fbe, 14), HUFF_PACK(0x00003fbf, 14), + HUFF_PACK(0x00007ffe, 15), HUFF_PACK(0x0000fffe, 16), + HUFF_PACK(0x0001fffe, 17), HUFF_PACK(0x0007fffe, 19), + HUFF_PACK(0x0007fffc, 19), HUFF_PACK(0x000ffffa, 20), + HUFF_PACK(0x001ffffc, 21), HUFF_PACK(0x001ffffd, 21), + HUFF_PACK(0x001ffffe, 21), HUFF_PACK(0x001fffff, 21), + HUFF_PACK(0x000ffffb, 20)}}, + { /* HUFF_CLD_TAB_2D */ + { /* HUFF_CLD_TAB_2D[0][] */ + {/* HUFF_CLD_TAB_2D[0][0] */ + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000002, 3), + HUFF_PACK(0x00000004, 5), HUFF_PACK(0x0000003e, 8)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000007, 4), + HUFF_PACK(0x0000000e, 6), HUFF_PACK(0x000000fe, 10)}, + {HUFF_PACK(0x0000007e, 9), HUFF_PACK(0x0000001e, 7), + HUFF_PACK(0x0000000c, 6), HUFF_PACK(0x00000005, 5)}, + {HUFF_PACK(0x000000ff, 10), HUFF_PACK(0x0000000d, 6), + HUFF_PACK(0x00000000, 3), HUFF_PACK(0x00000003, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000002, 3), HUFF_PACK(0x00000003, 3), + HUFF_PACK(0x00000010, 5), HUFF_PACK(0x0000007c, 7), + HUFF_PACK(0x000000d6, 8), HUFF_PACK(0x000003ee, 10)}, + {HUFF_PACK(0x0000000a, 4), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x00000016, 5), HUFF_PACK(0x00000034, 6), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x00001f7e, 13)}, + {HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x00000036, 6), + HUFF_PACK(0x00000026, 6), HUFF_PACK(0x00000046, 7), + HUFF_PACK(0x0000011e, 9), HUFF_PACK(0x000001f6, 9)}, + {HUFF_PACK(0x0000011f, 9), HUFF_PACK(0x000000d7, 8), + HUFF_PACK(0x0000008e, 8), HUFF_PACK(0x000000ff, 8), + HUFF_PACK(0x0000006a, 7), HUFF_PACK(0x0000004e, 7)}, + {HUFF_PACK(0x00000fbe, 12), HUFF_PACK(0x000007de, 11), + HUFF_PACK(0x0000004f, 7), HUFF_PACK(0x00000037, 6), + HUFF_PACK(0x00000017, 5), HUFF_PACK(0x0000001e, 5)}, + {HUFF_PACK(0x00001f7f, 13), HUFF_PACK(0x000000fa, 8), + HUFF_PACK(0x00000022, 6), HUFF_PACK(0x00000012, 5), + HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000007c, 7), + HUFF_PACK(0x000000be, 8), HUFF_PACK(0x0000017a, 9), + HUFF_PACK(0x000000ee, 9), HUFF_PACK(0x000007b6, 11)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x00000016, 5), HUFF_PACK(0x00000026, 6), + HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x0000002e, 7), + HUFF_PACK(0x000001ec, 9), HUFF_PACK(0x000047ce, 15)}, + {HUFF_PACK(0x00000016, 6), HUFF_PACK(0x0000003c, 6), + HUFF_PACK(0x00000022, 6), HUFF_PACK(0x0000004e, 7), + HUFF_PACK(0x0000003f, 7), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x000008fa, 12), HUFF_PACK(0x000008fb, 12)}, + {HUFF_PACK(0x0000005f, 8), HUFF_PACK(0x000000fa, 8), + HUFF_PACK(0x000000bf, 8), HUFF_PACK(0x0000003a, 7), + HUFF_PACK(0x000001f6, 9), HUFF_PACK(0x000001de, 10), + HUFF_PACK(0x000003da, 10), HUFF_PACK(0x000007b7, 11)}, + {HUFF_PACK(0x000001df, 10), HUFF_PACK(0x000003ee, 10), + HUFF_PACK(0x0000017b, 9), HUFF_PACK(0x000003ef, 10), + HUFF_PACK(0x000001ee, 9), HUFF_PACK(0x0000008e, 8), + HUFF_PACK(0x000001ef, 9), HUFF_PACK(0x000001fe, 9)}, + {HUFF_PACK(0x000008f8, 12), HUFF_PACK(0x0000047e, 11), + HUFF_PACK(0x0000047f, 11), HUFF_PACK(0x00000076, 8), + HUFF_PACK(0x0000003c, 7), HUFF_PACK(0x00000046, 7), + HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x0000007e, 7)}, + {HUFF_PACK(0x000023e6, 14), HUFF_PACK(0x000011f2, 13), + HUFF_PACK(0x000001ff, 9), HUFF_PACK(0x0000003d, 7), + HUFF_PACK(0x0000004f, 7), HUFF_PACK(0x0000002e, 6), + HUFF_PACK(0x00000012, 5), HUFF_PACK(0x00000004, 4)}, + {HUFF_PACK(0x000047cf, 15), HUFF_PACK(0x0000011e, 9), + HUFF_PACK(0x000000bc, 8), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x0000001c, 6), HUFF_PACK(0x00000010, 5), + HUFF_PACK(0x0000000d, 4), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV9_2D */ + {{HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000007, 4), + HUFF_PACK(0x00000006, 5), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x0000000a, 7), HUFF_PACK(0x0000001e, 8), + HUFF_PACK(0x0000008a, 9), HUFF_PACK(0x0000004e, 10), + HUFF_PACK(0x00000276, 10), HUFF_PACK(0x000002e2, 11)}, + {HUFF_PACK(0x00000000, 4), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x00000016, 5), HUFF_PACK(0x00000026, 6), + HUFF_PACK(0x00000076, 7), HUFF_PACK(0x000000f2, 8), + HUFF_PACK(0x00000012, 8), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x0000008b, 9), HUFF_PACK(0x00002e76, 15)}, + {HUFF_PACK(0x00000012, 6), HUFF_PACK(0x00000007, 5), + HUFF_PACK(0x00000038, 6), HUFF_PACK(0x0000007c, 7), + HUFF_PACK(0x00000008, 7), HUFF_PACK(0x00000046, 8), + HUFF_PACK(0x000000f6, 8), HUFF_PACK(0x000001ca, 9), + HUFF_PACK(0x0000173a, 14), HUFF_PACK(0x00001738, 14)}, + {HUFF_PACK(0x0000009e, 8), HUFF_PACK(0x0000004a, 7), + HUFF_PACK(0x00000026, 7), HUFF_PACK(0x0000000c, 7), + HUFF_PACK(0x0000004e, 8), HUFF_PACK(0x000000f7, 8), + HUFF_PACK(0x0000013a, 9), HUFF_PACK(0x0000009e, 11), + HUFF_PACK(0x000009fe, 12), HUFF_PACK(0x0000013e, 12)}, + {HUFF_PACK(0x00000026, 9), HUFF_PACK(0x0000001a, 8), + HUFF_PACK(0x000001e6, 9), HUFF_PACK(0x000001e2, 9), + HUFF_PACK(0x000000ee, 8), HUFF_PACK(0x000001ce, 9), + HUFF_PACK(0x00000277, 10), HUFF_PACK(0x000003ce, 10), + HUFF_PACK(0x000002e6, 11), HUFF_PACK(0x000004fc, 11)}, + {HUFF_PACK(0x000002e3, 11), HUFF_PACK(0x00000170, 10), + HUFF_PACK(0x00000172, 10), HUFF_PACK(0x000000ba, 9), + HUFF_PACK(0x0000003e, 9), HUFF_PACK(0x000001e3, 9), + HUFF_PACK(0x0000001b, 8), HUFF_PACK(0x0000003f, 9), + HUFF_PACK(0x0000009e, 9), HUFF_PACK(0x0000009f, 9)}, + {HUFF_PACK(0x00000b9e, 13), HUFF_PACK(0x000009ff, 12), + HUFF_PACK(0x000004fd, 11), HUFF_PACK(0x000004fe, 11), + HUFF_PACK(0x000001cf, 9), HUFF_PACK(0x000000ef, 8), + HUFF_PACK(0x00000044, 8), HUFF_PACK(0x0000005f, 8), + HUFF_PACK(0x000000e4, 8), HUFF_PACK(0x000000f0, 8)}, + {HUFF_PACK(0x00002e72, 15), HUFF_PACK(0x0000013f, 12), + HUFF_PACK(0x00000b9f, 13), HUFF_PACK(0x0000013e, 9), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x00000047, 8), + HUFF_PACK(0x0000000e, 7), HUFF_PACK(0x0000007d, 7), + HUFF_PACK(0x00000010, 6), HUFF_PACK(0x00000024, 6)}, + {HUFF_PACK(0x00002e77, 15), HUFF_PACK(0x00005ce6, 16), + HUFF_PACK(0x000000bb, 9), HUFF_PACK(0x000000e6, 8), + HUFF_PACK(0x00000016, 8), HUFF_PACK(0x000000ff, 8), + HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x0000003a, 6), + HUFF_PACK(0x00000017, 5), HUFF_PACK(0x00000002, 4)}, + {HUFF_PACK(0x00005ce7, 16), HUFF_PACK(0x000003cf, 10), + HUFF_PACK(0x00000017, 8), HUFF_PACK(0x000001cb, 9), + HUFF_PACK(0x0000009c, 8), HUFF_PACK(0x0000004b, 7), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x0000000a, 5), + HUFF_PACK(0x00000008, 4), HUFF_PACK(0x00000006, 3)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }}, + {/* HUFF_CLD_TAB_2D[0][1] */ + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000076e, 11), HUFF_PACK(0x00000ede, 12)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000003f, 6), + HUFF_PACK(0x000003b6, 10), HUFF_PACK(0x0000003a, 6)}, + {HUFF_PACK(0x0000001c, 5), HUFF_PACK(0x000000ee, 8), + HUFF_PACK(0x000001da, 9), HUFF_PACK(0x0000001e, 5)}, + {HUFF_PACK(0x000000ef, 8), HUFF_PACK(0x00000edf, 12), + HUFF_PACK(0x000000ec, 8), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000001c, 5), + HUFF_PACK(0x0000007e, 8), HUFF_PACK(0x00000efc, 12), + HUFF_PACK(0x0000effe, 16), HUFF_PACK(0x0001dffe, 17)}, + {HUFF_PACK(0x00000004, 3), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x00000efe, 12), + HUFF_PACK(0x000077fe, 15), HUFF_PACK(0x00000076, 7)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000016, 5), + HUFF_PACK(0x000000be, 8), HUFF_PACK(0x00000efd, 12), + HUFF_PACK(0x000000ee, 8), HUFF_PACK(0x0000000e, 5)}, + {HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000002e, 6), + HUFF_PACK(0x000001de, 9), HUFF_PACK(0x000003be, 10), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000001e, 5)}, + {HUFF_PACK(0x0000007f, 7), HUFF_PACK(0x0000005e, 7), + HUFF_PACK(0x00003bfe, 14), HUFF_PACK(0x000000fe, 9), + HUFF_PACK(0x0000001e, 6), HUFF_PACK(0x00000002, 3)}, + {HUFF_PACK(0x000000bf, 8), HUFF_PACK(0x0001dfff, 17), + HUFF_PACK(0x00001dfe, 13), HUFF_PACK(0x000000ff, 9), + HUFF_PACK(0x0000003a, 6), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000002, 3), HUFF_PACK(0x0000001c, 5), + HUFF_PACK(0x000000bc, 8), HUFF_PACK(0x000005fc, 11), + HUFF_PACK(0x00005ffe, 15), HUFF_PACK(0x0002ffde, 18), + HUFF_PACK(0x000bff7e, 20), HUFF_PACK(0x0017feff, 21)}, + {HUFF_PACK(0x00000004, 3), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x0000000e, 7), HUFF_PACK(0x000002fa, 10), + HUFF_PACK(0x000001fe, 13), HUFF_PACK(0x0000bff2, 16), + HUFF_PACK(0x0005ffbe, 19), HUFF_PACK(0x000000ee, 8)}, + {HUFF_PACK(0x00000002, 4), HUFF_PACK(0x00000016, 5), + HUFF_PACK(0x000000f6, 8), HUFF_PACK(0x000005fe, 11), + HUFF_PACK(0x000001ff, 13), HUFF_PACK(0x0000bff6, 16), + HUFF_PACK(0x000001de, 9), HUFF_PACK(0x0000007e, 7)}, + {HUFF_PACK(0x00000000, 5), HUFF_PACK(0x0000003c, 6), + HUFF_PACK(0x0000000e, 8), HUFF_PACK(0x0000003e, 10), + HUFF_PACK(0x00002ffe, 14), HUFF_PACK(0x000002fb, 10), + HUFF_PACK(0x000000f7, 8), HUFF_PACK(0x0000002e, 6)}, + {HUFF_PACK(0x00000006, 6), HUFF_PACK(0x0000007a, 7), + HUFF_PACK(0x0000000a, 8), HUFF_PACK(0x0000007e, 11), + HUFF_PACK(0x000000fe, 12), HUFF_PACK(0x00000016, 9), + HUFF_PACK(0x00000006, 7), HUFF_PACK(0x00000002, 5)}, + {HUFF_PACK(0x0000000f, 7), HUFF_PACK(0x00000076, 7), + HUFF_PACK(0x00000017, 9), HUFF_PACK(0x00005ff8, 15), + HUFF_PACK(0x00000bfe, 12), HUFF_PACK(0x0000001e, 9), + HUFF_PACK(0x0000007f, 7), HUFF_PACK(0x00000003, 4)}, + {HUFF_PACK(0x00000004, 7), HUFF_PACK(0x000000bd, 8), + HUFF_PACK(0x0000bff3, 16), HUFF_PACK(0x00005fff, 15), + HUFF_PACK(0x00000bfa, 12), HUFF_PACK(0x0000017c, 9), + HUFF_PACK(0x0000003a, 6), HUFF_PACK(0x00000003, 3)}, + {HUFF_PACK(0x0000017e, 9), HUFF_PACK(0x0017fefe, 21), + HUFF_PACK(0x00017fee, 17), HUFF_PACK(0x00005ffa, 15), + HUFF_PACK(0x00000bfb, 12), HUFF_PACK(0x000001df, 9), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x00000006, 3)}}, + HUFF_PACK(0x0017feff, 21) /* escape */ + }, + { + /* LAV9_2D */ + {{HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x00000014, 5), + HUFF_PACK(0x0000008e, 8), HUFF_PACK(0x000004fe, 11), + HUFF_PACK(0x000023fe, 14), HUFF_PACK(0x00008ffe, 16), + HUFF_PACK(0x0005ffbc, 19), HUFF_PACK(0x0017fef7, 21), + HUFF_PACK(0x0017fef7, 21), HUFF_PACK(0x0017fef7, 21)}, + {HUFF_PACK(0x00000002, 3), HUFF_PACK(0x00000002, 4), + HUFF_PACK(0x00000044, 7), HUFF_PACK(0x0000027e, 10), + HUFF_PACK(0x000017fc, 13), HUFF_PACK(0x0000bff6, 16), + HUFF_PACK(0x0005ffbe, 19), HUFF_PACK(0x00011ff8, 17), + HUFF_PACK(0x000bff7a, 20), HUFF_PACK(0x000000bc, 8)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000016, 5), + HUFF_PACK(0x0000001a, 7), HUFF_PACK(0x000000fe, 10), + HUFF_PACK(0x000011f6, 13), HUFF_PACK(0x0000bffe, 16), + HUFF_PACK(0x00011ff9, 17), HUFF_PACK(0x0017fef6, 21), + HUFF_PACK(0x0000011e, 9), HUFF_PACK(0x00000056, 7)}, + {HUFF_PACK(0x00000010, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000009e, 8), HUFF_PACK(0x000007fe, 11), + HUFF_PACK(0x000011f7, 13), HUFF_PACK(0x00005ff8, 15), + HUFF_PACK(0x00017fee, 17), HUFF_PACK(0x000007ff, 11), + HUFF_PACK(0x000000ae, 8), HUFF_PACK(0x0000001e, 7)}, + {HUFF_PACK(0x00000026, 6), HUFF_PACK(0x0000000e, 6), + HUFF_PACK(0x000001ee, 9), HUFF_PACK(0x0000047e, 11), + HUFF_PACK(0x00000bfc, 12), HUFF_PACK(0x0000bfff, 16), + HUFF_PACK(0x000008fa, 12), HUFF_PACK(0x0000006e, 9), + HUFF_PACK(0x000001ef, 9), HUFF_PACK(0x0000007e, 7)}, + {HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x0000004e, 7), + HUFF_PACK(0x0000007e, 9), HUFF_PACK(0x000000de, 10), + HUFF_PACK(0x000011fe, 13), HUFF_PACK(0x00002ffe, 14), + HUFF_PACK(0x000004ff, 11), HUFF_PACK(0x000000ff, 10), + HUFF_PACK(0x000000bd, 8), HUFF_PACK(0x0000002e, 6)}, + {HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x000000af, 8), + HUFF_PACK(0x000001ec, 9), HUFF_PACK(0x000001be, 11), + HUFF_PACK(0x00011ffe, 17), HUFF_PACK(0x00002ffa, 14), + HUFF_PACK(0x000008fe, 12), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x00000046, 7), HUFF_PACK(0x00000012, 5)}, + {HUFF_PACK(0x0000003e, 8), HUFF_PACK(0x00000045, 7), + HUFF_PACK(0x000002fe, 10), HUFF_PACK(0x000bff7e, 20), + HUFF_PACK(0x00005ff9, 15), HUFF_PACK(0x00005ffa, 15), + HUFF_PACK(0x00000bfd, 12), HUFF_PACK(0x0000013e, 9), + HUFF_PACK(0x0000000c, 6), HUFF_PACK(0x00000007, 4)}, + {HUFF_PACK(0x000000be, 8), HUFF_PACK(0x00000036, 8), + HUFF_PACK(0x000bff7f, 20), HUFF_PACK(0x00023ffe, 18), + HUFF_PACK(0x00011ffa, 17), HUFF_PACK(0x00005ffe, 15), + HUFF_PACK(0x000001bf, 11), HUFF_PACK(0x000001ed, 9), + HUFF_PACK(0x0000002a, 6), HUFF_PACK(0x00000000, 3)}, + {HUFF_PACK(0x0000017e, 9), HUFF_PACK(0x0017fef7, 21), + HUFF_PACK(0x00047ffe, 19), HUFF_PACK(0x00047fff, 19), + HUFF_PACK(0x00011ffb, 17), HUFF_PACK(0x00002ffb, 14), + HUFF_PACK(0x0000047c, 11), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x0000003c, 6), HUFF_PACK(0x00000006, 3)}}, + HUFF_PACK(0x0017fef7, 21) /* escape */ + }}}, + { /* HUFF_CLD_TAB_2D[1][] */ + {/* HUFF_CLD_TAB_2D[1][0] */ + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000001e, 5), + HUFF_PACK(0x000003be, 10), HUFF_PACK(0x00000efe, 12)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000001c, 5), + HUFF_PACK(0x000001de, 9), HUFF_PACK(0x000000ea, 8)}, + {HUFF_PACK(0x00000074, 7), HUFF_PACK(0x000000ee, 8), + HUFF_PACK(0x000000eb, 8), HUFF_PACK(0x0000001f, 5)}, + {HUFF_PACK(0x0000077e, 11), HUFF_PACK(0x00000eff, 12), + HUFF_PACK(0x00000076, 7), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x00000006, 4), + HUFF_PACK(0x00000024, 7), HUFF_PACK(0x0000025e, 11), + HUFF_PACK(0x00003cfe, 14), HUFF_PACK(0x000079fe, 15)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000007, 4), + HUFF_PACK(0x00000078, 7), HUFF_PACK(0x000003ce, 10), + HUFF_PACK(0x00001e7e, 13), HUFF_PACK(0x000000be, 9)}, + {HUFF_PACK(0x00000008, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x00000026, 7), HUFF_PACK(0x0000012e, 10), + HUFF_PACK(0x000000bf, 9), HUFF_PACK(0x0000002e, 7)}, + {HUFF_PACK(0x00000027, 7), HUFF_PACK(0x0000007a, 7), + HUFF_PACK(0x000001e4, 9), HUFF_PACK(0x00000096, 9), + HUFF_PACK(0x0000007b, 7), HUFF_PACK(0x0000003f, 6)}, + {HUFF_PACK(0x000001e6, 9), HUFF_PACK(0x000001e5, 9), + HUFF_PACK(0x00000f3e, 12), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x0000079e, 11), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x0000025f, 11), HUFF_PACK(0x0000004a, 8), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x00000006, 4), + HUFF_PACK(0x000000de, 8), HUFF_PACK(0x0000069e, 11), + HUFF_PACK(0x000034fe, 14), HUFF_PACK(0x0001a7fe, 17), + HUFF_PACK(0x00069ff6, 19), HUFF_PACK(0x00069ff7, 19)}, + {HUFF_PACK(0x00000002, 3), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x0000006a, 7), HUFF_PACK(0x0000034e, 10), + HUFF_PACK(0x00001fde, 13), HUFF_PACK(0x000069fe, 15), + HUFF_PACK(0x0001a7fc, 17), HUFF_PACK(0x00000372, 10)}, + {HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000003c, 6), + HUFF_PACK(0x000000df, 8), HUFF_PACK(0x000001ee, 10), + HUFF_PACK(0x00000dde, 12), HUFF_PACK(0x000069fa, 15), + HUFF_PACK(0x00000373, 10), HUFF_PACK(0x0000007a, 8)}, + {HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x00000068, 7), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x000003f6, 10), + HUFF_PACK(0x00000d3e, 12), HUFF_PACK(0x0000034c, 10), + HUFF_PACK(0x000001fa, 9), HUFF_PACK(0x000000d2, 8)}, + {HUFF_PACK(0x0000007e, 8), HUFF_PACK(0x0000007f, 8), + HUFF_PACK(0x000001f8, 9), HUFF_PACK(0x000006ee, 11), + HUFF_PACK(0x000003de, 11), HUFF_PACK(0x000001b8, 9), + HUFF_PACK(0x000001fc, 9), HUFF_PACK(0x0000006b, 7)}, + {HUFF_PACK(0x000000f6, 9), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x0000034d, 10), HUFF_PACK(0x00003fbe, 14), + HUFF_PACK(0x000007f6, 11), HUFF_PACK(0x000003fa, 10), + HUFF_PACK(0x0000003c, 7), HUFF_PACK(0x0000003d, 6)}, + {HUFF_PACK(0x000003f7, 10), HUFF_PACK(0x00000376, 10), + HUFF_PACK(0x0001a7ff, 17), HUFF_PACK(0x00003fbf, 14), + HUFF_PACK(0x00000ddf, 12), HUFF_PACK(0x000001f9, 9), + HUFF_PACK(0x00000036, 6), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x000003df, 11), HUFF_PACK(0x00034ffa, 18), + HUFF_PACK(0x000069fb, 15), HUFF_PACK(0x000034fc, 14), + HUFF_PACK(0x00000fee, 12), HUFF_PACK(0x000001ff, 9), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV9_2D */ + {{HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x00000012, 7), HUFF_PACK(0x000007fe, 11), + HUFF_PACK(0x00001f7e, 13), HUFF_PACK(0x0000fbfe, 16), + HUFF_PACK(0x0001f7fe, 17), HUFF_PACK(0x000b7dfe, 21), + HUFF_PACK(0x000b7dff, 21), HUFF_PACK(0x000b7dff, 21)}, + {HUFF_PACK(0x00000000, 3), HUFF_PACK(0x00000006, 4), + HUFF_PACK(0x0000007c, 7), HUFF_PACK(0x00000046, 9), + HUFF_PACK(0x000007d0, 12), HUFF_PACK(0x00001f4e, 14), + HUFF_PACK(0x0000b7fe, 17), HUFF_PACK(0x00005bee, 16), + HUFF_PACK(0x00016fbe, 18), HUFF_PACK(0x000003ee, 10)}, + {HUFF_PACK(0x00000006, 5), HUFF_PACK(0x0000000a, 5), + HUFF_PACK(0x0000002e, 7), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000007d2, 12), HUFF_PACK(0x00001f4f, 14), + HUFF_PACK(0x00002dfe, 15), HUFF_PACK(0x0000b7de, 17), + HUFF_PACK(0x000001fe, 10), HUFF_PACK(0x0000002e, 8)}, + {HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x0000007a, 8), HUFF_PACK(0x000001fa, 10), + HUFF_PACK(0x000007fe, 12), HUFF_PACK(0x00001f7c, 13), + HUFF_PACK(0x000016fa, 14), HUFF_PACK(0x0000009e, 10), + HUFF_PACK(0x00000020, 8), HUFF_PACK(0x00000021, 8)}, + {HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x00000016, 7), + HUFF_PACK(0x000000fe, 9), HUFF_PACK(0x0000016e, 10), + HUFF_PACK(0x0000009f, 10), HUFF_PACK(0x00000b7c, 13), + HUFF_PACK(0x000003de, 11), HUFF_PACK(0x000000b6, 9), + HUFF_PACK(0x000000be, 9), HUFF_PACK(0x0000007c, 8)}, + {HUFF_PACK(0x0000005a, 8), HUFF_PACK(0x00000078, 8), + HUFF_PACK(0x00000047, 9), HUFF_PACK(0x00000044, 9), + HUFF_PACK(0x000007ff, 12), HUFF_PACK(0x000007d1, 12), + HUFF_PACK(0x000001f6, 10), HUFF_PACK(0x000001f7, 10), + HUFF_PACK(0x0000002f, 8), HUFF_PACK(0x0000002c, 7)}, + {HUFF_PACK(0x000000fc, 9), HUFF_PACK(0x000001f6, 9), + HUFF_PACK(0x000000f6, 9), HUFF_PACK(0x000007ff, 11), + HUFF_PACK(0x000016fe, 14), HUFF_PACK(0x000002de, 11), + HUFF_PACK(0x000003ea, 11), HUFF_PACK(0x000000bf, 9), + HUFF_PACK(0x000000fa, 8), HUFF_PACK(0x0000000a, 6)}, + {HUFF_PACK(0x0000004e, 9), HUFF_PACK(0x00000026, 8), + HUFF_PACK(0x000001ee, 10), HUFF_PACK(0x00005bfe, 16), + HUFF_PACK(0x00003efe, 14), HUFF_PACK(0x00000b7e, 13), + HUFF_PACK(0x000003eb, 11), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x0000007b, 7), HUFF_PACK(0x00000007, 5)}, + {HUFF_PACK(0x000001fb, 10), HUFF_PACK(0x00000045, 9), + HUFF_PACK(0x00016ffe, 18), HUFF_PACK(0x0001f7ff, 17), + HUFF_PACK(0x00002df6, 15), HUFF_PACK(0x00001f7d, 13), + HUFF_PACK(0x000003fe, 11), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x0000003c, 6), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x000003df, 11), HUFF_PACK(0x0005befe, 20), + HUFF_PACK(0x0002df7e, 19), HUFF_PACK(0x00016fff, 18), + HUFF_PACK(0x00007dfe, 15), HUFF_PACK(0x00000fa6, 13), + HUFF_PACK(0x000007de, 11), HUFF_PACK(0x00000079, 8), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x000b7dff, 21) /* escape */ + }}, + {/* HUFF_CLD_TAB_2D[1][1] */ + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x000000fa, 8), HUFF_PACK(0x000007de, 11)}, + {HUFF_PACK(0x0000000c, 4), HUFF_PACK(0x0000001e, 5), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x000001f6, 9)}, + {HUFF_PACK(0x000000ff, 8), HUFF_PACK(0x0000007c, 7), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000001a, 5)}, + {HUFF_PACK(0x000007df, 11), HUFF_PACK(0x000003ee, 10), + HUFF_PACK(0x0000001b, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000007c, 7), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x00000fbe, 12), HUFF_PACK(0x00003efe, 14)}, + {HUFF_PACK(0x00000000, 3), HUFF_PACK(0x00000001, 3), + HUFF_PACK(0x0000003c, 6), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x000007de, 11), HUFF_PACK(0x000007be, 11)}, + {HUFF_PACK(0x0000001e, 6), HUFF_PACK(0x0000000a, 5), + HUFF_PACK(0x0000001f, 6), HUFF_PACK(0x0000005f, 8), + HUFF_PACK(0x000001ee, 9), HUFF_PACK(0x000001f6, 9)}, + {HUFF_PACK(0x000001fe, 9), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x000000f6, 8), HUFF_PACK(0x000000fa, 8), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x00000016, 6)}, + {HUFF_PACK(0x000007bf, 11), HUFF_PACK(0x000003de, 10), + HUFF_PACK(0x000003ee, 10), HUFF_PACK(0x0000007a, 7), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x00000006, 4)}, + {HUFF_PACK(0x00003eff, 14), HUFF_PACK(0x00001f7e, 13), + HUFF_PACK(0x000003ff, 10), HUFF_PACK(0x0000002e, 7), + HUFF_PACK(0x00000004, 4), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000002, 3), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x0000001a, 6), HUFF_PACK(0x000001be, 9), + HUFF_PACK(0x000006e6, 11), HUFF_PACK(0x0000067a, 12), + HUFF_PACK(0x00000cf2, 13), HUFF_PACK(0x000033de, 15)}, + {HUFF_PACK(0x0000000c, 4), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x000000de, 8), + HUFF_PACK(0x00000372, 10), HUFF_PACK(0x000003d6, 11), + HUFF_PACK(0x00000678, 12), HUFF_PACK(0x00000cf6, 13)}, + {HUFF_PACK(0x00000036, 6), HUFF_PACK(0x00000012, 5), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000003c, 7), + HUFF_PACK(0x000001b8, 9), HUFF_PACK(0x000003d4, 11), + HUFF_PACK(0x0000033e, 11), HUFF_PACK(0x0000033f, 11)}, + {HUFF_PACK(0x0000007e, 8), HUFF_PACK(0x0000006a, 7), + HUFF_PACK(0x0000004e, 7), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x000000ce, 9), + HUFF_PACK(0x000000f6, 9), HUFF_PACK(0x000001ee, 10)}, + {HUFF_PACK(0x000001ef, 10), HUFF_PACK(0x0000013e, 9), + HUFF_PACK(0x0000007f, 8), HUFF_PACK(0x00000066, 8), + HUFF_PACK(0x000000d6, 8), HUFF_PACK(0x0000003e, 7), + HUFF_PACK(0x000000d7, 8), HUFF_PACK(0x0000009e, 8)}, + {HUFF_PACK(0x000007ae, 12), HUFF_PACK(0x000001e8, 10), + HUFF_PACK(0x000001e9, 10), HUFF_PACK(0x0000027e, 10), + HUFF_PACK(0x00000032, 7), HUFF_PACK(0x00000018, 6), + HUFF_PACK(0x00000026, 6), HUFF_PACK(0x00000034, 6)}, + {HUFF_PACK(0x00000cf3, 13), HUFF_PACK(0x000007aa, 12), + HUFF_PACK(0x000007ab, 12), HUFF_PACK(0x0000027f, 10), + HUFF_PACK(0x000001bf, 9), HUFF_PACK(0x0000001b, 6), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000b, 4)}, + {HUFF_PACK(0x000033df, 15), HUFF_PACK(0x000019ee, 14), + HUFF_PACK(0x000007af, 12), HUFF_PACK(0x000006e7, 11), + HUFF_PACK(0x000001bb, 9), HUFF_PACK(0x0000007f, 7), + HUFF_PACK(0x00000008, 4), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV9_2D */ + {{HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x00000008, 4), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x000001ba, 10), HUFF_PACK(0x00000dbe, 12), + HUFF_PACK(0x00000d7e, 13), HUFF_PACK(0x00001af6, 14), + HUFF_PACK(0x00007fec, 15), HUFF_PACK(0x0001ffb6, 17)}, + {HUFF_PACK(0x0000000a, 4), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x0000000c, 5), HUFF_PACK(0x00000036, 7), + HUFF_PACK(0x000000de, 9), HUFF_PACK(0x000005fe, 11), + HUFF_PACK(0x000006be, 12), HUFF_PACK(0x00001b7e, 13), + HUFF_PACK(0x00007fee, 15), HUFF_PACK(0x00006dfe, 15)}, + {HUFF_PACK(0x0000001e, 6), HUFF_PACK(0x0000000e, 5), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000006a, 7), + HUFF_PACK(0x000001ae, 9), HUFF_PACK(0x000006fe, 11), + HUFF_PACK(0x00000376, 11), HUFF_PACK(0x00000dfe, 13), + HUFF_PACK(0x00000dff, 13), HUFF_PACK(0x00000d7f, 13)}, + {HUFF_PACK(0x000000b6, 8), HUFF_PACK(0x0000005e, 7), + HUFF_PACK(0x0000007c, 7), HUFF_PACK(0x0000006e, 7), + HUFF_PACK(0x0000006a, 8), HUFF_PACK(0x0000016a, 9), + HUFF_PACK(0x00000ffe, 12), HUFF_PACK(0x00000dfe, 12), + HUFF_PACK(0x00000ffc, 12), HUFF_PACK(0x00001bfe, 13)}, + {HUFF_PACK(0x0000035e, 10), HUFF_PACK(0x000001b6, 9), + HUFF_PACK(0x0000005e, 8), HUFF_PACK(0x000000b4, 8), + HUFF_PACK(0x0000006c, 7), HUFF_PACK(0x0000017e, 9), + HUFF_PACK(0x0000036e, 10), HUFF_PACK(0x000003ee, 10), + HUFF_PACK(0x0000037e, 11), HUFF_PACK(0x00000377, 11)}, + {HUFF_PACK(0x00000fff, 12), HUFF_PACK(0x000001ae, 10), + HUFF_PACK(0x000001be, 10), HUFF_PACK(0x000001f6, 9), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x000000da, 8), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x0000016b, 9), + HUFF_PACK(0x000000d6, 9), HUFF_PACK(0x0000037e, 10)}, + {HUFF_PACK(0x000017fe, 13), HUFF_PACK(0x00000bfe, 12), + HUFF_PACK(0x000007de, 11), HUFF_PACK(0x000006de, 11), + HUFF_PACK(0x000001b8, 10), HUFF_PACK(0x000000d6, 8), + HUFF_PACK(0x0000002e, 7), HUFF_PACK(0x00000034, 7), + HUFF_PACK(0x000000de, 8), HUFF_PACK(0x000000be, 8)}, + {HUFF_PACK(0x00007fef, 15), HUFF_PACK(0x000006bc, 12), + HUFF_PACK(0x00001bff, 13), HUFF_PACK(0x00001ffa, 13), + HUFF_PACK(0x000001b9, 10), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000000fa, 8), HUFF_PACK(0x0000002e, 6), + HUFF_PACK(0x00000034, 6), HUFF_PACK(0x0000001f, 6)}, + {HUFF_PACK(0x00006dff, 15), HUFF_PACK(0x00001af7, 14), + HUFF_PACK(0x000036fe, 14), HUFF_PACK(0x000006fe, 12), + HUFF_PACK(0x00000fbe, 12), HUFF_PACK(0x0000035f, 10), + HUFF_PACK(0x000000b7, 8), HUFF_PACK(0x0000002c, 6), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x00000009, 4)}, + {HUFF_PACK(0x0001ffb7, 17), HUFF_PACK(0x0000ffda, 16), + HUFF_PACK(0x00000d7a, 13), HUFF_PACK(0x000017ff, 13), + HUFF_PACK(0x00000fbf, 12), HUFF_PACK(0x000002fe, 10), + HUFF_PACK(0x0000005f, 8), HUFF_PACK(0x00000016, 6), + HUFF_PACK(0x00000004, 4), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }}}}}; + +const HUFF_ICC_TABLE fdk_sacenc_huffICCTab = { + {/* h1D[2][8] */ + {HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000002, 2), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000007f, 7)}, + {HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000002, 2), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000007f, 7)}}, + { /* HUFF_ICC_TAB_2D */ + { /* HUFF_ICC_TAB_2D[0][] */ + {/* HUFF_ICC_TAB_2D[0][0] */ + { + /* LAV1_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000006, 3)}, + {HUFF_PACK(0x00000007, 3), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000000, 2), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000007e, 8)}, + {HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x000003fe, 11)}, + {HUFF_PACK(0x000001fe, 10), HUFF_PACK(0x000000fe, 9), + HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x0000001e, 6)}, + {HUFF_PACK(0x000003ff, 11), HUFF_PACK(0x00000017, 6), + HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000003, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x00000002, 3), + HUFF_PACK(0x0000000c, 5), HUFF_PACK(0x0000006a, 7), + HUFF_PACK(0x000000dc, 8), HUFF_PACK(0x000006ee, 11)}, + {HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x0000000d, 5), HUFF_PACK(0x0000001e, 6), + HUFF_PACK(0x000001ae, 9), HUFF_PACK(0x0000ddff, 16)}, + {HUFF_PACK(0x000000de, 8), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x0000001f, 6), HUFF_PACK(0x000001be, 9), + HUFF_PACK(0x00006efe, 15), HUFF_PACK(0x0000ddfe, 16)}, + {HUFF_PACK(0x0000377e, 14), HUFF_PACK(0x00001bbe, 13), + HUFF_PACK(0x00000dde, 12), HUFF_PACK(0x000001bf, 9), + HUFF_PACK(0x000000d6, 8), HUFF_PACK(0x00000376, 10)}, + {HUFF_PACK(0x0000ddff, 16), HUFF_PACK(0x0000ddff, 16), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x00000034, 6), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000000e, 5)}, + {HUFF_PACK(0x0000ddff, 16), HUFF_PACK(0x000001af, 9), + HUFF_PACK(0x0000007f, 7), HUFF_PACK(0x00000036, 6), + HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x0000ddff, 16) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x0000002e, 6), HUFF_PACK(0x00000044, 7), + HUFF_PACK(0x00000086, 8), HUFF_PACK(0x0000069e, 11), + HUFF_PACK(0x0000043e, 11), HUFF_PACK(0x0000087a, 12)}, + {HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000002a, 6), HUFF_PACK(0x00000046, 7), + HUFF_PACK(0x0000015e, 9), HUFF_PACK(0x00000047, 7), + HUFF_PACK(0x0000034a, 10), HUFF_PACK(0x0000087b, 12)}, + {HUFF_PACK(0x000000d6, 8), HUFF_PACK(0x00000026, 6), + HUFF_PACK(0x0000002f, 6), HUFF_PACK(0x000000d7, 8), + HUFF_PACK(0x0000006a, 7), HUFF_PACK(0x0000034e, 10), + HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12)}, + {HUFF_PACK(0x000002be, 10), HUFF_PACK(0x000001a6, 9), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x00000012, 5), + HUFF_PACK(0x000001bf, 9), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12)}, + {HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x00000036, 6), HUFF_PACK(0x000000d0, 8), + HUFF_PACK(0x0000043c, 11), HUFF_PACK(0x0000043f, 11)}, + {HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000034b, 10), + HUFF_PACK(0x00000027, 6), HUFF_PACK(0x00000020, 6), + HUFF_PACK(0x00000042, 7), HUFF_PACK(0x000000d1, 8)}, + {HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x000002bf, 10), HUFF_PACK(0x000000de, 8), + HUFF_PACK(0x000000ae, 8), HUFF_PACK(0x00000056, 7), + HUFF_PACK(0x00000016, 5), HUFF_PACK(0x00000014, 5)}, + {HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000069f, 11), + HUFF_PACK(0x000001a4, 9), HUFF_PACK(0x0000010e, 9), + HUFF_PACK(0x00000045, 7), HUFF_PACK(0x0000006e, 7), + HUFF_PACK(0x0000001f, 5), HUFF_PACK(0x00000001, 2)}}, + HUFF_PACK(0x0000087b, 12) /* escape */ + }}, + {/* HUFF_ICC_TAB_2D[0][1] */ + { + /* LAV1_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000006, 3)}, + {HUFF_PACK(0x00000007, 3), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x0000017e, 10), HUFF_PACK(0x000002fe, 11)}, + {HUFF_PACK(0x00000000, 2), HUFF_PACK(0x0000000e, 5), + HUFF_PACK(0x000000be, 9), HUFF_PACK(0x00000016, 6)}, + {HUFF_PACK(0x0000000f, 5), HUFF_PACK(0x00000014, 6), + HUFF_PACK(0x0000005e, 8), HUFF_PACK(0x00000006, 4)}, + {HUFF_PACK(0x0000002e, 7), HUFF_PACK(0x000002ff, 11), + HUFF_PACK(0x00000015, 6), HUFF_PACK(0x00000003, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x0000001e, 5), + HUFF_PACK(0x000003fc, 10), HUFF_PACK(0x0000fffa, 16), + HUFF_PACK(0x000fff9e, 20), HUFF_PACK(0x000fff9f, 20)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x000000be, 9), HUFF_PACK(0x00007ffe, 15), + HUFF_PACK(0x0007ffce, 19), HUFF_PACK(0x000000fe, 8)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x0000001e, 6), + HUFF_PACK(0x000003fd, 10), HUFF_PACK(0x0000fffb, 16), + HUFF_PACK(0x00000ffe, 12), HUFF_PACK(0x0000003e, 6)}, + {HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x00001ffe, 13), HUFF_PACK(0x00007fff, 15), + HUFF_PACK(0x0000005e, 8), HUFF_PACK(0x0000000e, 5)}, + {HUFF_PACK(0x0000001f, 6), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x0001fff2, 17), HUFF_PACK(0x00000ffc, 12), + HUFF_PACK(0x0000002e, 7), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x000000bf, 9), HUFF_PACK(0x0003ffe6, 18), + HUFF_PACK(0x0000fff8, 16), HUFF_PACK(0x00000ffd, 12), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x0000001e, 6), + HUFF_PACK(0x00000ffe, 12), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000fffe, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000008, 5), + HUFF_PACK(0x000007fe, 11), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000005a, 8)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x0000007a, 7), + HUFF_PACK(0x00000164, 10), HUFF_PACK(0x00007ffa, 15), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x00001fee, 13), HUFF_PACK(0x0000003c, 6)}, + {HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x000002ce, 11), HUFF_PACK(0x000002cf, 11), + HUFF_PACK(0x00007ffb, 15), HUFF_PACK(0x00001fec, 13), + HUFF_PACK(0x000000b0, 9), HUFF_PACK(0x0000002e, 7)}, + {HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x00000165, 10), HUFF_PACK(0x00007ffc, 15), + HUFF_PACK(0x00001fef, 13), HUFF_PACK(0x000007fa, 11), + HUFF_PACK(0x000007f8, 11), HUFF_PACK(0x0000001f, 6)}, + {HUFF_PACK(0x0000002f, 7), HUFF_PACK(0x000000f6, 8), + HUFF_PACK(0x00001fed, 13), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x00007ffd, 15), HUFF_PACK(0x00000ff2, 12), + HUFF_PACK(0x000000b1, 9), HUFF_PACK(0x0000000a, 5)}, + {HUFF_PACK(0x00000009, 5), HUFF_PACK(0x00000166, 10), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x00007ffe, 15), HUFF_PACK(0x00003ffc, 14), + HUFF_PACK(0x0000005b, 8), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x00000ff3, 12), + HUFF_PACK(0x000000f7, 8), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x0000ffff, 16) /* escape */ + }}}, + { /* HUFF_ICC_TAB_2D[1][] */ + {/* HUFF_ICC_TAB_2D[1][0] */ + { + /* LAV1_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000006, 3)}, + {HUFF_PACK(0x00000007, 3), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000037e, 10), HUFF_PACK(0x00000dfe, 12)}, + {HUFF_PACK(0x0000000f, 4), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x000001bb, 9)}, + {HUFF_PACK(0x000000de, 8), HUFF_PACK(0x000000dc, 8), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x0000001a, 5)}, + {HUFF_PACK(0x000006fe, 11), HUFF_PACK(0x00000dff, 12), + HUFF_PACK(0x00000036, 6), HUFF_PACK(0x00000000, 1)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x000001b6, 9), HUFF_PACK(0x00001b7c, 13), + HUFF_PACK(0x0000dbfe, 16), HUFF_PACK(0x00036fff, 18)}, + {HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x0000001e, 5), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x00000dfe, 12), + HUFF_PACK(0x00036ffe, 18), HUFF_PACK(0x0000036e, 10)}, + {HUFF_PACK(0x0000006e, 7), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x000000d8, 8), HUFF_PACK(0x000036fe, 14), + HUFF_PACK(0x000006de, 11), HUFF_PACK(0x000000de, 8)}, + {HUFF_PACK(0x000001fa, 9), HUFF_PACK(0x000000da, 8), + HUFF_PACK(0x00000dff, 12), HUFF_PACK(0x00001b7e, 13), + HUFF_PACK(0x000000d9, 8), HUFF_PACK(0x000000ff, 8)}, + {HUFF_PACK(0x000003f6, 10), HUFF_PACK(0x000006fe, 11), + HUFF_PACK(0x00006dfe, 15), HUFF_PACK(0x0000037e, 10), + HUFF_PACK(0x000000fc, 8), HUFF_PACK(0x0000001a, 5)}, + {HUFF_PACK(0x000007ee, 11), HUFF_PACK(0x0001b7fe, 17), + HUFF_PACK(0x00001b7d, 13), HUFF_PACK(0x000007ef, 11), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00036fff, 18) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x000007ee, 11), HUFF_PACK(0x00001e7e, 13), + HUFF_PACK(0x00003cfe, 14), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000079ff, 15)}, + {HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x0000001a, 5), + HUFF_PACK(0x000001e6, 9), HUFF_PACK(0x00001fbe, 13), + HUFF_PACK(0x000079fe, 15), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000006fc, 11)}, + {HUFF_PACK(0x0000006c, 7), HUFF_PACK(0x000000f6, 8), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x00000dfc, 12), + HUFF_PACK(0x00000dfd, 12), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x00000f3e, 12), HUFF_PACK(0x000001bb, 9)}, + {HUFF_PACK(0x000000dc, 8), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x0000036e, 10), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x00000fde, 12), + HUFF_PACK(0x000001ee, 9), HUFF_PACK(0x000000f2, 8)}, + {HUFF_PACK(0x000001fa, 9), HUFF_PACK(0x000003f6, 10), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x00001fbf, 13), HUFF_PACK(0x000003ce, 10), + HUFF_PACK(0x000003ff, 10), HUFF_PACK(0x000000de, 8)}, + {HUFF_PACK(0x00000078, 7), HUFF_PACK(0x000000da, 8), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000006fd, 11), HUFF_PACK(0x0000036c, 10), + HUFF_PACK(0x000001ef, 9), HUFF_PACK(0x000000fe, 8)}, + {HUFF_PACK(0x0000036f, 10), HUFF_PACK(0x00000dfe, 12), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x0000036d, 10), + HUFF_PACK(0x000000fc, 8), HUFF_PACK(0x0000003e, 6)}, + {HUFF_PACK(0x00000dff, 12), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x0000079e, 11), + HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x000079ff, 15) /* escape */ + }}, + {/* HUFF_ICC_TAB_2D[1][1] */ + { + /* LAV1_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000006, 3)}, + {HUFF_PACK(0x00000007, 3), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x000000fc, 8), HUFF_PACK(0x00000fde, 12)}, + {HUFF_PACK(0x0000000c, 4), HUFF_PACK(0x0000000d, 4), + HUFF_PACK(0x000001fe, 9), HUFF_PACK(0x000007ee, 11)}, + {HUFF_PACK(0x000001fa, 9), HUFF_PACK(0x000001ff, 9), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x0000003e, 6)}, + {HUFF_PACK(0x00000fdf, 12), HUFF_PACK(0x000003f6, 10), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x00000000, 1)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000003a, 7), HUFF_PACK(0x00000676, 11), + HUFF_PACK(0x000019fe, 13), HUFF_PACK(0x0000cebe, 16)}, + {HUFF_PACK(0x0000000f, 4), HUFF_PACK(0x00000002, 3), + HUFF_PACK(0x0000001e, 6), HUFF_PACK(0x000000fe, 9), + HUFF_PACK(0x000019d6, 13), HUFF_PACK(0x0000675e, 15)}, + {HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x00000032, 6), + HUFF_PACK(0x00000018, 5), HUFF_PACK(0x0000033e, 10), + HUFF_PACK(0x00000cfe, 12), HUFF_PACK(0x00000677, 11)}, + {HUFF_PACK(0x00000674, 11), HUFF_PACK(0x0000019c, 9), + HUFF_PACK(0x000000ff, 9), HUFF_PACK(0x0000003b, 7), + HUFF_PACK(0x0000001c, 6), HUFF_PACK(0x0000007e, 8)}, + {HUFF_PACK(0x000033fe, 14), HUFF_PACK(0x000033ff, 14), + HUFF_PACK(0x00000cea, 12), HUFF_PACK(0x00000066, 7), + HUFF_PACK(0x0000001a, 5), HUFF_PACK(0x00000006, 4)}, + {HUFF_PACK(0x0000cebf, 16), HUFF_PACK(0x000033ae, 14), + HUFF_PACK(0x0000067e, 11), HUFF_PACK(0x0000019e, 9), + HUFF_PACK(0x0000001b, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000002, 4), + HUFF_PACK(0x000000fe, 9), HUFF_PACK(0x000007be, 12), + HUFF_PACK(0x00000ffc, 13), HUFF_PACK(0x00000ffd, 13), + HUFF_PACK(0x00001efe, 15), HUFF_PACK(0x00003dfe, 16)}, + {HUFF_PACK(0x00000004, 4), HUFF_PACK(0x00000000, 3), + HUFF_PACK(0x0000003c, 7), HUFF_PACK(0x000000f6, 10), + HUFF_PACK(0x000001da, 11), HUFF_PACK(0x000003fe, 12), + HUFF_PACK(0x00003dfe, 15), HUFF_PACK(0x00003dff, 16)}, + {HUFF_PACK(0x0000003c, 8), HUFF_PACK(0x0000003e, 7), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000003a, 8), + HUFF_PACK(0x000003de, 11), HUFF_PACK(0x000007be, 13), + HUFF_PACK(0x00000f7e, 14), HUFF_PACK(0x00001efe, 14)}, + {HUFF_PACK(0x000001de, 11), HUFF_PACK(0x000000ec, 10), + HUFF_PACK(0x0000007e, 9), HUFF_PACK(0x0000000c, 5), + HUFF_PACK(0x000001ee, 10), HUFF_PACK(0x00000f7e, 13), + HUFF_PACK(0x000007fc, 12), HUFF_PACK(0x00003dff, 15)}, + {HUFF_PACK(0x00007ffe, 16), HUFF_PACK(0x000003be, 12), + HUFF_PACK(0x000000fe, 10), HUFF_PACK(0x000001fe, 10), + HUFF_PACK(0x0000001a, 6), HUFF_PACK(0x0000001c, 7), + HUFF_PACK(0x000007fd, 12), HUFF_PACK(0x00000ffe, 13)}, + {HUFF_PACK(0x00003dff, 16), HUFF_PACK(0x000003bf, 12), + HUFF_PACK(0x00001ffe, 14), HUFF_PACK(0x000003ff, 12), + HUFF_PACK(0x0000003e, 8), HUFF_PACK(0x0000001b, 6), + HUFF_PACK(0x0000007e, 8), HUFF_PACK(0x000000f6, 9)}, + {HUFF_PACK(0x00007fff, 16), HUFF_PACK(0x00003dff, 16), + HUFF_PACK(0x00003ffe, 15), HUFF_PACK(0x000001db, 11), + HUFF_PACK(0x000000ee, 10), HUFF_PACK(0x0000007a, 8), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x0000000b, 5)}, + {HUFF_PACK(0x00003dff, 16), HUFF_PACK(0x00003dff, 16), + HUFF_PACK(0x000003de, 12), HUFF_PACK(0x000001fe, 11), + HUFF_PACK(0x000001ee, 11), HUFF_PACK(0x0000007a, 9), + HUFF_PACK(0x00000006, 5), HUFF_PACK(0x00000003, 2)}}, + HUFF_PACK(0x00003dff, 16) /* escape */ + }}}}}; + +const HUFF_PT0_TABLE fdk_sacenc_huffPart0Tab = { + {/* CLD */ + HUFF_PACK(0x00000052, 8), HUFF_PACK(0x000000ae, 9), + HUFF_PACK(0x000000af, 9), HUFF_PACK(0x00000028, 7), + HUFF_PACK(0x0000006e, 7), HUFF_PACK(0x00000036, 6), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000000c, 4), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x00000002, 4), HUFF_PACK(0x00000016, 5), + HUFF_PACK(0x00000012, 5), HUFF_PACK(0x00000017, 5), + HUFF_PACK(0x00000000, 4), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000008, 4), + HUFF_PACK(0x00000007, 4), HUFF_PACK(0x00000003, 4), + HUFF_PACK(0x00000001, 4), HUFF_PACK(0x0000001a, 5), + HUFF_PACK(0x00000013, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x00000017, 6), + HUFF_PACK(0x0000006f, 7), HUFF_PACK(0x0000002a, 7), + HUFF_PACK(0x00000056, 8), HUFF_PACK(0x00000053, 8), + HUFF_PACK(0x0000003f, 6)}, + {/* ICC */ + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000000, 2), + HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000001, 2), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000003f, 6)}}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_huff_tab.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_huff_tab.h new file mode 100644 index 0000000000000..7d6c331dcf378 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_huff_tab.h @@ -0,0 +1,222 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Markus Lohwasser + + Description: SAC-Encoder constant huffman tables + +*******************************************************************************/ + +#ifndef SACENC_HUFF_TAB_H +#define SACENC_HUFF_TAB_H + +/* Includes ******************************************************************/ +#include "machine_type.h" + +/* Defines *******************************************************************/ +#define HUFF_PACK(a, b) \ + { \ + ((((ULONG)a) & 0x00FFFFFF) << 8) | (((ULONG)b) & 0xFF) \ + } /*!< Pack huffman value and length information. */ +#define HUFF_VALUE(a) \ + (((a.packed >> 8) & 0x00FFFFFF)) /*!< Return value from packed table entry. \ + */ +#define HUFF_LENGTH(a) \ + ((a.packed & 0xFF)) /*!< Return length from packed table entry. */ + +/* Data Types ****************************************************************/ +/** + * \brief This struct contains packed huffman entries. + * + * The packed entry consist of hffman value and length information. + * + * |---------------------------------| + * | value | length | + * |---------------------------------| + * |<------- 31...8 ------->|< 7..0 >| + */ +typedef struct { + ULONG packed; /*! Packed huffman entry: + - lower 8 bit are reservoed for length information + - upper 24 bit contains huffman value */ +} HUFF_ENTRY; + +typedef struct { + HUFF_ENTRY entry[2][2]; + HUFF_ENTRY escape; + +} LAV1_2D; + +typedef struct { + HUFF_ENTRY entry[4][4]; + HUFF_ENTRY escape; + +} LAV3_2D; + +typedef struct { + HUFF_ENTRY entry[6][6]; + HUFF_ENTRY escape; + +} LAV5_2D; + +typedef struct { + HUFF_ENTRY entry[7][7]; + HUFF_ENTRY escape; + +} LAV6_2D; + +typedef struct { + HUFF_ENTRY entry[8][8]; + HUFF_ENTRY escape; + +} LAV7_2D; + +typedef struct { + HUFF_ENTRY entry[10][10]; + HUFF_ENTRY escape; + +} LAV9_2D; + +typedef struct { + HUFF_ENTRY entry[13][13]; + HUFF_ENTRY escape; + +} LAV12_2D; + +typedef struct { + LAV3_2D lav3; + LAV5_2D lav5; + LAV7_2D lav7; + LAV9_2D lav9; + +} HUFF_CLD_TAB_2D; + +typedef struct { + LAV1_2D lav1; + LAV3_2D lav3; + LAV5_2D lav5; + LAV7_2D lav7; + +} HUFF_ICC_TAB_2D; + +typedef struct { + HUFF_ENTRY h1D[2][31]; + HUFF_CLD_TAB_2D h2D[2][2]; + +} HUFF_CLD_TABLE; + +typedef struct { + HUFF_ENTRY h1D[2][8]; + HUFF_ICC_TAB_2D h2D[2][2]; + +} HUFF_ICC_TABLE; + +typedef struct { + HUFF_ENTRY cld[31]; + HUFF_ENTRY icc[8]; + +} HUFF_PT0_TABLE; + +typedef HUFF_ENTRY HUFF_RES_TABLE[5][8]; + +/* Constants *****************************************************************/ +extern const HUFF_CLD_TABLE fdk_sacenc_huffCLDTab; +extern const HUFF_ICC_TABLE fdk_sacenc_huffICCTab; +extern const HUFF_PT0_TABLE fdk_sacenc_huffPart0Tab; + +/* Function / Class Declarations *********************************************/ + +#endif /* SACENC_HUFF_TAB_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_lib.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_lib.cpp new file mode 100644 index 0000000000000..fcfe39bf45d0f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_lib.cpp @@ -0,0 +1,2042 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Interface to Spacial Audio Coding Encoder lib + +*******************************************************************************/ + +/**************************************************************************** +\file +Description of file contents +******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_lib.h" +#include "sacenc_const.h" +#include "genericStds.h" +#include "FDK_core.h" +#include "sacenc_tree.h" +#include "sacenc_bitstream.h" +#include "sacenc_onsetdetect.h" +#include "sacenc_framewindowing.h" +#include "sacenc_filter.h" +#include "sacenc_paramextract.h" +#include "sacenc_staticgain.h" +#include "sacenc_delay.h" +#include "sacenc_dmx_tdom_enh.h" +#include "sacenc_vectorfunctions.h" +#include "qmf.h" + +/* Defines *******************************************************************/ + +/* Encoder library info */ +#define SACENC_LIB_VL0 2 +#define SACENC_LIB_VL1 0 +#define SACENC_LIB_VL2 0 +#define SACENC_LIB_TITLE "MPEG Surround Encoder" +#ifdef SUPPRESS_BUILD_DATE_INFO +#define SACENC_LIB_BUILD_DATE "" +#define SACENC_LIB_BUILD_TIME "" +#else +#define SACENC_LIB_BUILD_DATE __DATE__ +#define SACENC_LIB_BUILD_TIME __TIME__ +#endif + +#define MAX_MPEGS_BYTES (1 << 14) +#define MAX_SSC_BYTES (1 << 6) + +#define MAX_SPACE_TREE_CHANNELS 2 +#define NUM_KEEP_WINDOWS 3 + +/* Data Types ****************************************************************/ +typedef struct { + MP4SPACEENC_MODE encMode; + MP4SPACEENC_BANDS_CONFIG nParamBands; + MP4SPACEENC_QUANTMODE quantMode; + UCHAR bUseCoarseQuant; + UCHAR bLdMode; + UCHAR bTimeDomainDmx; + UINT sampleRate; + UINT frameTimeSlots; /* e.g. 32 when used with HE-AAC */ + UINT independencyFactor; /* how often should we set the independency flag */ + INT timeAlignment; /* additional delay for downmix */ + +} MP4SPACEENC_SETUP, *HANDLE_MP4SPACEENC_SETUP; + +struct ENC_CONFIG_SETUP { + UCHAR bEncMode_212; + UCHAR maxHybridInStaticSlots; + LONG maxSamplingrate; + INT maxAnalysisLengthTimeSlots; + INT maxHybridBands; + INT maxQmfBands; + INT maxChIn; + INT maxFrameTimeSlots; + INT maxFrameLength; + INT maxChOut; + INT maxChTotOut; +}; + +struct MP4SPACE_ENCODER { + MP4SPACEENC_SETUP user; + + ENC_CONFIG_SETUP setup; /* describe allocated instance */ + + HANDLE_FRAMEWINDOW + hFrameWindow; /* Windowing, only created+updated, but not used */ + INT nSamplesValid; /* Input Buffer Handling */ + + /* Routing Sensible Switches/Variables */ + MP4SPACEENC_BANDS_CONFIG nParamBands; + UCHAR useTimeDomDownmix; + + /* not Routing Sensible Switches/Varibles - must be contained in Check */ + MP4SPACEENC_MODE encMode; + UCHAR bEncMode_212_only; + + /* not Routing Sensible Switches/Varibles + lower Classes */ + UCHAR useFrameKeep; + UINT independencyFactor; + UINT nSampleRate; + UCHAR nInputChannels; + UCHAR nOutputChannels; + UCHAR nFrameTimeSlots; /* e.g. 32 when used with HE-AAC */ + UCHAR nQmfBands; + UCHAR nHybridBands; + UINT nFrameLength; /* number of output waveform samples/channel/frame */ + + /* not Routing Sensible Switches/Varibles + lower Classes, secondary computed + */ + INT nSamplesNext; + INT nAnalysisLengthTimeSlots; + INT nAnalysisLookaheadTimeSlots; + INT nUpdateHybridPositionTimeSlots; + INT *pnOutputBits; + INT nInputDelay; + INT nOutputBufferDelay; + INT nSurroundAnalysisBufferDelay; + INT nBitstreamDelayBuffer; + INT nBitstreamBufferRead; + INT nBitstreamBufferWrite; + INT nDiscardOutFrames; + INT avoid_keep; + + /* not Routing Sensible Switches/Varibles -> moved to lower Classes */ + UCHAR useCoarseQuantCld; /* Only Used in SpaceTreeSetup */ + UCHAR useCoarseQuantIcc; /* Only Used in SpaceTreeSetup */ + UCHAR useCoarseQuantCpc; /* Only Used in SpaceTreeSetup */ + UCHAR useCoarseQuantArbDmx; /* ArbitraryDmx,... not available yet */ + MP4SPACEENC_QUANTMODE + quantMode; /* Used for quanitzation and in bitstream writer */ + INT coreCoderDelay; /* Used in delay compensation */ + INT timeAlignment; /* Used in delay compensation */ + + /* Local Processing Variables */ + INT independencyCount; + INT independencyFlag; + INT **ppTrCurrPos; /* belongs somehow to Onset Detection */ + INT trPrevPos[2 * MAX_NUM_TRANS]; /* belongs somehow to Onset Detection */ + + FRAMEWIN_LIST frameWinList; + SPATIALFRAME saveFrame; + + /* Module-Handles */ + SPACE_TREE_SETUP spaceTreeSetup; + MPEG4SPACEENC_SSCBUF sscBuf; + FIXP_WIN *pFrameWindowAna__FDK[MAX_NUM_PARAMS]; + HANDLE_QMF_FILTER_BANK *phQmfFiltIn__FDK; + HANDLE_DC_FILTER phDCFilterSigIn[SACENC_MAX_INPUT_CHANNELS]; + HANDLE_ONSET_DETECT phOnset[SACENC_MAX_INPUT_CHANNELS]; + HANDLE_SPACE_TREE hSpaceTree; + HANDLE_BSF_INSTANCE hBitstreamFormatter; + HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig; + HANDLE_STATIC_GAIN hStaticGain; + HANDLE_DELAY hDelay; + + /* enhanced time domain downmix (for stereo input) */ + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx; + + /* Data Buffers */ + INT_PCM **ppTimeSigIn__FDK; + INT_PCM **ppTimeSigDelayIn__FDK; + INT_PCM **ppTimeSigOut__FDK; + FIXP_DPK ***pppHybridIn__FDK; + FIXP_DPK ***pppHybridInStatic__FDK; + FIXP_DPK ***pppProcDataIn__FDK; + INT_PCM *pOutputDelayBuffer__FDK; + + UCHAR **ppBitstreamDelayBuffer; + + UCHAR *pParameterBand2HybridBandOffset; + INT staticGainScale; + + INT *pEncoderInputChScale; + INT *staticTimeDomainDmxInScale; +}; + +/* Constants *****************************************************************/ +static const UCHAR pValidBands_Ld[8] = {4, 5, 7, 9, 12, 15, 23, 40}; + +static const UCHAR qmf2qmf[] = /* Bypass the HybridAnylyis/Synthesis*/ + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}; + +/* Function / Class Declarations *********************************************/ +static FDK_SACENC_ERROR mp4SpaceEnc_create( + HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc); + +static FDK_SACENC_ERROR FillSpatialSpecificConfig( + const HANDLE_MP4SPACE_ENCODER hEnc, SPATIALSPECIFICCONFIG *const hSsc); + +static FDK_SACENC_ERROR mp4SpaceEnc_FillSpaceTreeSetup( + const HANDLE_MP4SPACE_ENCODER hEnc, + SPACE_TREE_SETUP *const hSpaceTreeSetup); + +static FDK_SACENC_ERROR mp4SpaceEnc_InitDelayCompensation( + HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, const INT coreCoderDelay); + +static FDK_SACENC_ERROR mp4SpaceEnc_InitDefault( + HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc); + +static DECORRCONFIG mp4SpaceEnc_GetDecorrConfig(const MP4SPACEENC_MODE encMode); + +static FDK_SACENC_ERROR mp4SpaceEnc_InitNumParamBands( + HANDLE_MP4SPACE_ENCODER hEnc, const MP4SPACEENC_BANDS_CONFIG nParamBands); + +/* Function / Class Definition ***********************************************/ +static UINT mp4SpaceEnc_GetNumQmfBands(const UINT nSampleRate) { + UINT nQmfBands = 0; + + if (nSampleRate < 27713) + nQmfBands = 32; + else if (nSampleRate < 55426) + nQmfBands = 64; + + return nQmfBands; +} + +static UINT updateQmfFlags(const UINT flags, const INT keepStates) { + UINT qmfFlags = flags; + + qmfFlags = (qmfFlags & (~(UINT)QMF_FLAG_LP)); + qmfFlags = (qmfFlags | QMF_FLAG_MPSLDFB); + qmfFlags = (keepStates) ? (qmfFlags | QMF_FLAG_KEEP_STATES) + : (qmfFlags & (~(UINT)QMF_FLAG_KEEP_STATES)); + + return qmfFlags; +} + +static INT freq2HybridBand(const UINT nFrequency, const UINT nSampleRate, + const UINT nQmfBands) { + /* + nQmfSlotWidth = (nSampleRate/2) / nQmfBands; + nQmfBand = nFrequency / nQmfSlotWidth; + */ + int nHybridBand = -1; + int scale = 0; + const FIXP_DBL temp = fDivNorm((FIXP_DBL)(2 * nFrequency * nQmfBands), + (FIXP_DBL)nSampleRate, &scale); + const int nQmfBand = scaleValue(temp, scale - (DFRACT_BITS - 1)); + + if ((nQmfBand > -1) && (nQmfBand < (int)nQmfBands)) { + nHybridBand = qmf2qmf[nQmfBand]; + } + + return nHybridBand; +} + +/* + * Examine buffer descriptor regarding choosen type. + * + * \param pBufDesc Pointer to buffer descriptor + * \param type Buffer type to look for. + + * \return - Buffer descriptor index. + * -1, if there is no entry available. + */ +static INT getBufDescIdx(const FDK_bufDescr *pBufDesc, const UINT type) { + INT i, idx = -1; + + for (i = 0; i < (int)pBufDesc->numBufs; i++) { + if (pBufDesc->pBufType[i] == type) { + idx = i; + break; + } + } + return idx; +} + +FDK_SACENC_ERROR FDK_sacenc_open(HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc) { + return mp4SpaceEnc_create(phMp4SpaceEnc); +} + +static FDK_SACENC_ERROR mp4SpaceEnc_create( + HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc) { + FDK_SACENC_ERROR error = SACENC_OK; + HANDLE_MP4SPACE_ENCODER hEnc = NULL; + ENC_CONFIG_SETUP setup; + + if (NULL == phMp4SpaceEnc) { + error = SACENC_INVALID_HANDLE; + } else { + int i, ch; + FDKmemclear(&setup, sizeof(ENC_CONFIG_SETUP)); + + /* Allocate Encoder Instance */ + FDK_ALLOCATE_MEMORY_1D(hEnc, 1, struct MP4SPACE_ENCODER); + + /* Clear everything, also pointers. */ + if (NULL != hEnc) { + FDKmemclear(hEnc, sizeof(struct MP4SPACE_ENCODER)); + } + + setup.maxSamplingrate = 48000; + setup.maxFrameTimeSlots = 16; + + setup.maxAnalysisLengthTimeSlots = 3 * setup.maxFrameTimeSlots; + setup.maxQmfBands = mp4SpaceEnc_GetNumQmfBands(setup.maxSamplingrate); + ; + setup.maxHybridBands = setup.maxQmfBands; + setup.maxFrameLength = setup.maxQmfBands * setup.maxFrameTimeSlots; + + setup.maxChIn = 2; + setup.maxChOut = 1; + setup.maxChTotOut = setup.maxChOut; + setup.bEncMode_212 = 1; + setup.maxHybridInStaticSlots = 24; + + /* Open Static Gain*/ + if (SACENC_OK != + (error = fdk_sacenc_staticGain_OpenConfig(&hEnc->hStaticGainConfig))) { + goto bail; + } + + /* enhanced time domain downmix (for stereo input) */ + if (SACENC_OK != (error = fdk_sacenc_open_enhancedTimeDomainDmx( + &hEnc->hEnhancedTimeDmx, setup.maxFrameLength))) { + goto bail; + } + + FDK_ALLOCATE_MEMORY_1D(hEnc->pParameterBand2HybridBandOffset, + MAX_NUM_PARAM_BANDS, UCHAR); + + /* Create Space Tree first, to get number of in-/output channels */ + if (SACENC_OK != (error = fdk_sacenc_spaceTree_Open(&hEnc->hSpaceTree))) { + goto bail; + } + + FDK_ALLOCATE_MEMORY_1D(hEnc->pEncoderInputChScale, setup.maxChIn, INT); + FDK_ALLOCATE_MEMORY_1D(hEnc->staticTimeDomainDmxInScale, setup.maxChIn, + INT); + + FDK_ALLOCATE_MEMORY_1D(hEnc->phQmfFiltIn__FDK, setup.maxChIn, + HANDLE_QMF_FILTER_BANK); + + /* Allocate Analysis Filterbank Structs */ + for (ch = 0; ch < setup.maxChIn; ch++) { + FDK_ALLOCATE_MEMORY_1D_INT(hEnc->phQmfFiltIn__FDK[ch], 1, + struct QMF_FILTER_BANK, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_1D_INT(hEnc->phQmfFiltIn__FDK[ch]->FilterStates, + 2 * 5 * setup.maxQmfBands, FIXP_QAS, + SECT_DATA_L2) + } + + /* Allocate Synthesis Filterbank Structs for arbitrary downmix */ + + /* Allocate DC Filter Struct for normal signal input */ + for (ch = 0; ch < setup.maxChIn; ch++) { + if (SACENC_OK != + (error = fdk_sacenc_createDCFilter(&hEnc->phDCFilterSigIn[ch]))) { + goto bail; + } + } + + /* Open Onset Detection */ + for (ch = 0; ch < setup.maxChIn; ch++) { + if (SACENC_OK != (error = fdk_sacenc_onsetDetect_Open( + &hEnc->phOnset[ch], setup.maxFrameTimeSlots))) { + goto bail; + } + } + + FDK_ALLOCATE_MEMORY_2D(hEnc->ppTrCurrPos, setup.maxChIn, MAX_NUM_TRANS, + INT); + + /* Create Windowing */ + if (SACENC_OK != + (error = fdk_sacenc_frameWindow_Create(&hEnc->hFrameWindow))) { + goto bail; + } + + /* Open static gain */ + if (SACENC_OK != (error = fdk_sacenc_staticGain_Open(&hEnc->hStaticGain))) { + goto bail; + } + + /* create bitstream encoder */ + if (SACENC_OK != (error = fdk_sacenc_createSpatialBitstreamEncoder( + &hEnc->hBitstreamFormatter))) { + goto bail; + } + + FDK_ALLOCATE_MEMORY_1D(hEnc->sscBuf.pSsc, MAX_SSC_BYTES, UCHAR); + + { + FDK_ALLOCATE_MEMORY_2D(hEnc->ppTimeSigIn__FDK, setup.maxChIn, + setup.maxFrameLength + MAX_DELAY_SURROUND_ANALYSIS, + INT_PCM); + } + FDK_ALLOCATE_MEMORY_2D(hEnc->ppTimeSigDelayIn__FDK, setup.maxChIn, + MAX_DELAY_SURROUND_ANALYSIS, INT_PCM); + + /* Create new buffers for several signals (including arbitrary downmix) */ + if (setup.bEncMode_212 == 0) { + /* pOutputDelayBuffer__FDK buffer is not needed for SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_1D( + hEnc->pOutputDelayBuffer__FDK, + (setup.maxFrameLength + MAX_DELAY_OUTPUT) * setup.maxChOut, INT_PCM); + } + + /* allocate buffers */ + if (setup.bEncMode_212 == 0) { + /* ppTimeSigOut__FDK buffer is not needed for SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_2D(hEnc->ppTimeSigOut__FDK, setup.maxChTotOut, + setup.maxFrameLength, INT_PCM); + } + + if (setup.bEncMode_212 == 1) { + /* pppHybridIn__FDK buffer can be reduced by maxFrameTimeSlots/2 slots for + * SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_3D( + hEnc->pppHybridIn__FDK, setup.maxChIn, + setup.maxAnalysisLengthTimeSlots - (setup.maxFrameTimeSlots >> 1), + setup.maxHybridBands, FIXP_DPK); + FDK_ALLOCATE_MEMORY_3D(hEnc->pppHybridInStatic__FDK, setup.maxChIn, + setup.maxHybridInStaticSlots, setup.maxHybridBands, + FIXP_DPK); + } else { + FDK_ALLOCATE_MEMORY_3D(hEnc->pppHybridIn__FDK, setup.maxChIn, + setup.maxAnalysisLengthTimeSlots, + setup.maxHybridBands, FIXP_DPK); + } + + if (setup.bEncMode_212 == 0) { + /* pppProcDataIn__FDK buffer is not needed for SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_3D(hEnc->pppProcDataIn__FDK, MAX_SPACE_TREE_CHANNELS, + setup.maxAnalysisLengthTimeSlots, + setup.maxHybridBands, FIXP_DPK); + } + for (i = 0; i < MAX_NUM_PARAMS; i++) { + FDK_ALLOCATE_MEMORY_1D(hEnc->pFrameWindowAna__FDK[i], + setup.maxAnalysisLengthTimeSlots, FIXP_WIN); + } /* for i */ + + if (SACENC_OK != (error = fdk_sacenc_delay_Open(&hEnc->hDelay))) { + goto bail; + } + + if (setup.bEncMode_212 == 0) { + /* ppBitstreamDelayBuffer buffer is not needed for SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_2D(hEnc->ppBitstreamDelayBuffer, MAX_BITSTREAM_DELAY, + MAX_MPEGS_BYTES, UCHAR); + } + FDK_ALLOCATE_MEMORY_1D(hEnc->pnOutputBits, MAX_BITSTREAM_DELAY, INT); + + hEnc->setup = setup; /* save configuration used while encoder allocation. */ + mp4SpaceEnc_InitDefault(hEnc); + + if (NULL != phMp4SpaceEnc) { + *phMp4SpaceEnc = hEnc; /* return encoder handle */ + } + + } /* valid handle */ + + return error; + +bail: + if (NULL != hEnc) { + hEnc->setup = setup; + FDK_sacenc_close(&hEnc); + } + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +static FDK_SACENC_ERROR mp4SpaceEnc_InitDefault(HANDLE_MP4SPACE_ENCODER hEnc) { + FDK_SACENC_ERROR err = SACENC_OK; + + /* Get default static gain configuration. */ + if (SACENC_OK != (err = fdk_sacenc_staticGain_InitDefaultConfig( + hEnc->hStaticGainConfig))) { + goto bail; + } + +bail: + return err; +} + +static FDK_SACENC_ERROR FDK_sacenc_configure( + HANDLE_MP4SPACE_ENCODER hEnc, const HANDLE_MP4SPACEENC_SETUP hSetup) { + FDK_SACENC_ERROR error = SACENC_OK; + + hEnc->nSampleRate = hSetup->sampleRate; + hEnc->encMode = hSetup->encMode; + hEnc->nQmfBands = mp4SpaceEnc_GetNumQmfBands(hEnc->nSampleRate); + + /* Make sure that we have set time domain downmix for 212 */ + if (hSetup->encMode == SACENC_212 && hSetup->bTimeDomainDmx == 0) { + error = SACENC_INVALID_CONFIG; + } else { + hEnc->useTimeDomDownmix = hSetup->bTimeDomainDmx; + } + + hEnc->timeAlignment = hSetup->timeAlignment; + hEnc->quantMode = hSetup->quantMode; + + hEnc->useCoarseQuantCld = hSetup->bUseCoarseQuant; + hEnc->useCoarseQuantCpc = hSetup->bUseCoarseQuant; + hEnc->useFrameKeep = (hSetup->bLdMode == 2); + hEnc->useCoarseQuantIcc = 0; /* not available */ + hEnc->useCoarseQuantArbDmx = 0; /* not available for user right now */ + hEnc->independencyFactor = hSetup->independencyFactor; + hEnc->independencyCount = 0; + hEnc->independencyFlag = 1; + + /* set number of Hybrid bands */ + hEnc->nHybridBands = hEnc->nQmfBands; + hEnc->nFrameTimeSlots = hSetup->frameTimeSlots; + mp4SpaceEnc_InitNumParamBands(hEnc, hSetup->nParamBands); + + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_init(HANDLE_MP4SPACE_ENCODER hEnc, + const INT dmxDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* Sanity Checks */ + if (NULL == hEnc) { + error = SACENC_INVALID_HANDLE; + } else { + const int initStatesFlag = 1; + + int ch; /* loop counter */ + int nChInArbDmx; + + if (SACENC_OK != (error = FDK_sacenc_configure(hEnc, &hEnc->user))) { + goto bail; + } + + hEnc->bEncMode_212_only = hEnc->setup.bEncMode_212; + + /* Slots per Frame and Frame Length */ + if (hEnc->nFrameTimeSlots < 1) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + hEnc->nFrameLength = hEnc->nQmfBands * hEnc->nFrameTimeSlots; + + if (hEnc->useFrameKeep == 1) { + hEnc->nAnalysisLengthTimeSlots = 3 * hEnc->nFrameTimeSlots; + hEnc->nUpdateHybridPositionTimeSlots = hEnc->nFrameTimeSlots; + } else { + hEnc->nAnalysisLengthTimeSlots = 2 * hEnc->nFrameTimeSlots; + hEnc->nUpdateHybridPositionTimeSlots = 0; + } + + { + hEnc->nAnalysisLookaheadTimeSlots = + hEnc->nAnalysisLengthTimeSlots - 3 * hEnc->nFrameTimeSlots / 2; + } + + /* init parameterBand2hybridBandOffset table */ + fdk_sacenc_calcParameterBand2HybridBandOffset( + (BOX_SUBBAND_CONFIG)hEnc->nParamBands, hEnc->nHybridBands, + hEnc->pParameterBand2HybridBandOffset); + + /* Fill Setup structure for Space Tree */ + if (SACENC_OK != + (error = mp4SpaceEnc_FillSpaceTreeSetup(hEnc, &hEnc->spaceTreeSetup))) { + goto bail; + } + + /* Init space tree configuration */ + if (SACENC_OK != + (error = fdk_sacenc_spaceTree_Init( + hEnc->hSpaceTree, &hEnc->spaceTreeSetup, + hEnc->pParameterBand2HybridBandOffset, hEnc->useFrameKeep))) { + goto bail; + } + + /* Get space tree description and resulting number of input/output channels + */ + { + SPACE_TREE_DESCRIPTION spaceTreeDescription; + + if (SACENC_OK != (error = fdk_sacenc_spaceTree_GetDescription( + hEnc->hSpaceTree, &spaceTreeDescription))) { + goto bail; + } + + hEnc->nInputChannels = + spaceTreeDescription.nOutChannels; /* space tree description + describes decoder + configuration */ + hEnc->nOutputChannels = + spaceTreeDescription.nInChannels; /* space tree description + describes decoder + configuration */ + } + + nChInArbDmx = 0; + + /* INITIALIZATION */ + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + /* scaling in analysis qmf filterbank (7) */ + hEnc->pEncoderInputChScale[ch] = 7; + + { + /* additional scaling in qmf prototype filter for low delay */ + hEnc->pEncoderInputChScale[ch] += 1; + } + + { hEnc->pEncoderInputChScale[ch] += DC_FILTER_SF; } + } /* nInputChannels */ + + /* Init analysis filterbank */ + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + hEnc->phQmfFiltIn__FDK[ch]->flags = + updateQmfFlags(hEnc->phQmfFiltIn__FDK[ch]->flags, !initStatesFlag); + + if (0 != qmfInitAnalysisFilterBank( + hEnc->phQmfFiltIn__FDK[ch], + (FIXP_QAS *)hEnc->phQmfFiltIn__FDK[ch]->FilterStates, 1, + hEnc->nQmfBands, hEnc->nQmfBands, hEnc->nQmfBands, + hEnc->phQmfFiltIn__FDK[ch]->flags)) { + error = SACENC_INIT_ERROR; + goto bail; + } + } + + /* Initialize DC Filter. */ + { + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + if (SACENC_OK != (error = fdk_sacenc_initDCFilter( + hEnc->phDCFilterSigIn[ch], hEnc->nSampleRate))) { + goto bail; + } + } + } + + /* Init onset detect. */ + { + /* init onset detect configuration struct */ + ONSET_DETECT_CONFIG onsetDetectConfig; + onsetDetectConfig.maxTimeSlots = hEnc->nFrameTimeSlots; + onsetDetectConfig.lowerBoundOnsetDetection = + freq2HybridBand(1725, hEnc->nSampleRate, hEnc->nQmfBands); + onsetDetectConfig.upperBoundOnsetDetection = hEnc->nHybridBands; + + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + if (SACENC_OK != (error = fdk_sacenc_onsetDetect_Init( + hEnc->phOnset[ch], &onsetDetectConfig, 1))) { + goto bail; + } + } + } + + { + /* init windowing */ + FRAMEWINDOW_CONFIG framewindowConfig; + framewindowConfig.nTimeSlotsMax = hEnc->nFrameTimeSlots; + framewindowConfig.bFrameKeep = hEnc->useFrameKeep; + + if (SACENC_OK != (error = fdk_sacenc_frameWindow_Init( + hEnc->hFrameWindow, &framewindowConfig))) { + goto bail; + } + } + + /* Set encoder mode for static gain initialization. */ + if (SACENC_OK != (error = fdk_sacenc_staticGain_SetEncMode( + hEnc->hStaticGainConfig, hEnc->encMode))) { + goto bail; + } + + /* Init static gain. */ + if (SACENC_OK != (error = fdk_sacenc_staticGain_Init( + hEnc->hStaticGain, hEnc->hStaticGainConfig, + &(hEnc->staticGainScale)))) { + goto bail; + } + + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + hEnc->pEncoderInputChScale[ch] += hEnc->staticGainScale; + } + + /* enhanced downmix for stereo input*/ + if (hEnc->useTimeDomDownmix != 0) { + if (SACENC_OK != (error = fdk_sacenc_init_enhancedTimeDomainDmx( + hEnc->hEnhancedTimeDmx, + fdk_sacenc_getPreGainPtrFDK(hEnc->hStaticGain), + hEnc->staticGainScale, + fdk_sacenc_getPostGainFDK(hEnc->hStaticGain), + hEnc->staticGainScale, hEnc->nFrameLength))) { + goto bail; + } + } + + /* Create config structure for bitstream formatter including arbitrary + * downmix residual */ + if (SACENC_OK != (error = fdk_sacenc_initSpatialBitstreamEncoder( + hEnc->hBitstreamFormatter))) { + goto bail; + } + + if (SACENC_OK != (error = FillSpatialSpecificConfig( + hEnc, fdk_sacenc_getSpatialSpecificConfig( + hEnc->hBitstreamFormatter)))) { + goto bail; + } + + if (SACENC_OK != + (error = fdk_sacenc_writeSpatialSpecificConfig( + fdk_sacenc_getSpatialSpecificConfig(hEnc->hBitstreamFormatter), + hEnc->sscBuf.pSsc, MAX_SSC_BYTES, &hEnc->sscBuf.nSscSizeBits))) { + goto bail; + } + + /* init delay compensation with dmx core coder delay; if no core coder is + * used, many other buffers are initialized nevertheless */ + if (SACENC_OK != + (error = mp4SpaceEnc_InitDelayCompensation(hEnc, dmxDelay))) { + goto bail; + } + + /* How much input do we need? */ + hEnc->nSamplesNext = + hEnc->nFrameLength * (hEnc->nInputChannels + nChInArbDmx); + hEnc->nSamplesValid = 0; + } /* valid handle */ + +bail: + return error; +} + +static INT getAnalysisLengthTimeSlots(FIXP_WIN *pFrameWindowAna, + INT nTimeSlots) { + int i; + for (i = nTimeSlots - 1; i >= 0; i--) { + if (pFrameWindowAna[i] != (FIXP_WIN)0) { + break; + } + } + nTimeSlots = i + 1; + return nTimeSlots; +} + +static INT getAnalysisStartTimeSlot(FIXP_WIN *pFrameWindowAna, INT nTimeSlots) { + int startTimeSlot = 0; + int i; + for (i = 0; i < nTimeSlots; i++) { + if (pFrameWindowAna[i] != (FIXP_WIN)0) { + break; + } + } + startTimeSlot = i; + return startTimeSlot; +} + +static FDK_SACENC_ERROR __FeedDeinterPreScale( + HANDLE_MP4SPACE_ENCODER hEnc, INT_PCM const *const pSamples, + INT_PCM *const pOutputSamples, INT const nSamples, + UINT const isInputInterleaved, UINT const inputBufferSizePerChannel, + UINT *const pnSamplesFed) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hEnc == NULL) || (pSamples == NULL) || (pnSamplesFed == NULL)) { + error = SACENC_INVALID_HANDLE; + } else if (nSamples == 0) { + error = SACENC_INVALID_CONFIG; /* Flushing not implemented */ + } else { + int ch; + const INT nChIn = hEnc->nInputChannels; + const INT nChInWithDmx = nChIn; + const INT samplesToFeed = + FDKmin(nSamples, hEnc->nSamplesNext - hEnc->nSamplesValid); + const INT nSamplesPerChannel = samplesToFeed / nChInWithDmx; + + if ((samplesToFeed < 0) || (samplesToFeed % nChInWithDmx != 0) || + (samplesToFeed > nChInWithDmx * (INT)hEnc->nFrameLength)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + int i; + + const INT_PCM *pInput__FDK; + const INT_PCM *pInput2__FDK; + + { /* no dmx align = default*/ + pInput__FDK = pSamples; + pInput2__FDK = pSamples + (hEnc->nInputDelay * nChInWithDmx); + } + + for (i = 0; i < hEnc->nInputChannels; i++) { + hEnc->staticTimeDomainDmxInScale[i] = hEnc->staticGainScale; + } + + /***** N-channel-input *****/ + for (ch = 0; ch < nChIn; ch++) { + /* Write delayed time signal into time signal buffer */ + FDKmemcpy(&(hEnc->ppTimeSigIn__FDK[ch][0]), + &(hEnc->ppTimeSigDelayIn__FDK[ch][0]), + hEnc->nSurroundAnalysisBufferDelay * sizeof(INT_PCM)); + + if (isInputInterleaved) { + /* Add the new frame de-interleaved. Apply nSurroundAnalysisBufferDelay. + */ + FDKmemcpy_flex( + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay]), + 1, pInput__FDK + ch, nChInWithDmx, hEnc->nInputDelay); + FDKmemcpy_flex( + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay + + hEnc->nInputDelay]), + 1, pInput2__FDK + ch, nChInWithDmx, + nSamplesPerChannel - hEnc->nInputDelay); + } else { + /* Input is already deinterleaved, just copy */ + FDKmemcpy( + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay]), + pInput__FDK + ch * inputBufferSizePerChannel, + hEnc->nInputDelay * sizeof(INT_PCM)); + FDKmemcpy( + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay + + hEnc->nInputDelay]), + pInput2__FDK + ch * inputBufferSizePerChannel, + (nSamplesPerChannel - hEnc->nInputDelay) * sizeof(INT_PCM)); + } + + /* Update time signal delay buffer */ + FDKmemcpy(&(hEnc->ppTimeSigDelayIn__FDK[ch][0]), + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nFrameLength]), + hEnc->nSurroundAnalysisBufferDelay * sizeof(INT_PCM)); + } /* for ch */ + + /***** No Arbitrary Downmix *****/ + /* "Crude TD Dmx": Time DomainDownmix + NO Arbitrary Downmix, Delay Added at + * pOutputBuffer */ + if ((hEnc->useTimeDomDownmix > 0)) { + if ((hEnc->useTimeDomDownmix == 1) || (hEnc->nInputChannels != 2)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } else { + /* enhanced time domain downmix (for stereo input) */ + if (hEnc->encMode == SACENC_212) { + if (pOutputSamples == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + fdk_sacenc_apply_enhancedTimeDomainDmx( + hEnc->hEnhancedTimeDmx, hEnc->ppTimeSigIn__FDK, pOutputSamples, + hEnc->nSurroundAnalysisBufferDelay); + } else { + if (&hEnc->ppTimeSigOut__FDK[0][0] == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + fdk_sacenc_apply_enhancedTimeDomainDmx( + hEnc->hEnhancedTimeDmx, hEnc->ppTimeSigIn__FDK, + &hEnc->ppTimeSigOut__FDK[0][0], + hEnc->nSurroundAnalysisBufferDelay); + } + } + } + + /* update number of samples still to process */ + hEnc->nSamplesValid += samplesToFeed; + + /*return number of fed samples */ + *pnSamplesFed = samplesToFeed; + } +bail: + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_encode(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + const FDK_bufDescr *inBufDesc, + const FDK_bufDescr *outBufDesc, + const SACENC_InArgs *inargs, + SACENC_OutArgs *outargs) { + FDK_SACENC_ERROR error = SACENC_OK; + + const INT_PCM *pInputSamples = + (const INT_PCM *)inBufDesc->ppBase[getBufDescIdx( + inBufDesc, (FDK_BUF_TYPE_INPUT | FDK_BUF_TYPE_PCM_DATA))]; + + INT_PCM *const pOutputSamples = (INT_PCM *)outBufDesc->ppBase[getBufDescIdx( + outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA))]; + + const int nOutputSamplesBufferSize = + outBufDesc->pBufSize[getBufDescIdx( + outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA))] / + outBufDesc->pEleSize[getBufDescIdx( + outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA))]; + + if ((hMp4SpaceEnc == NULL) || (pInputSamples == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int nOutputSamples; + int i, ch, ps, winCnt, ts, slot; + INT currTransPos = -1; + SPATIALFRAME *pFrameData = NULL; + + /* Improve Code Readability */ + const int nChIn = hMp4SpaceEnc->nInputChannels; + const int nChInWithDmx = nChIn; + const int nChOut = hMp4SpaceEnc->nOutputChannels; + const int nSamplesPerChannel = inargs->nInputSamples / nChInWithDmx; + const int nOutputSamplesMax = nSamplesPerChannel * nChOut; + const int nFrameTimeSlots = hMp4SpaceEnc->nFrameTimeSlots; + + INT encoderInputChScale[SACENC_MAX_INPUT_CHANNELS]; + INT nFrameTimeSlotsReduction = 0; + + if (hMp4SpaceEnc->encMode == SACENC_212) { + nFrameTimeSlotsReduction = hMp4SpaceEnc->nFrameTimeSlots >> 1; + } + + for (i = 0; i < nChIn; i++) + encoderInputChScale[i] = hMp4SpaceEnc->pEncoderInputChScale[i]; + + /* Sanity Check */ + if ((0 != inargs->nInputSamples % nChInWithDmx)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* + * Get Frame Data Handle. + */ + + /* get bitstream handle (for storage of cld's, icc's and so on) + * get spatialframe 2 frames in the future; NOTE: this is necessary to + * synchronise spatial data and audio data */ + if (NULL == (pFrameData = fdk_sacenc_getSpatialFrame( + hMp4SpaceEnc->hBitstreamFormatter, WRITE_SPATIALFRAME))) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + /* Independent Frames Counters*/ + if (hMp4SpaceEnc->nDiscardOutFrames > + 0) { /* Independent Frames if they should be discarded, Reset Counter*/ + hMp4SpaceEnc->independencyCount = + 0; /* Reset the counter, first valid frame is an independent one*/ + hMp4SpaceEnc->independencyFlag = 1; + } else { /*hMp4SpaceEnc->nDiscardOutFrames == 0*/ + hMp4SpaceEnc->independencyFlag = + (hMp4SpaceEnc->independencyCount == 0) ? 1 : 0; + if (hMp4SpaceEnc->independencyFactor > 0) { + hMp4SpaceEnc->independencyCount++; + hMp4SpaceEnc->independencyCount = + hMp4SpaceEnc->independencyCount % + ((int)hMp4SpaceEnc->independencyFactor); + } else { /* independencyFactor == 0 */ + hMp4SpaceEnc->independencyCount = -1; + } + } + + /* + * Time signal preprocessing: + * - Feed input buffer + * - Prescale time signal + * - Apply DC filter on input signal + */ + + /* Feed, Deinterleave, Pre-Scale the input time signals */ + if (SACENC_OK != + (error = __FeedDeinterPreScale( + hMp4SpaceEnc, pInputSamples, pOutputSamples, inargs->nInputSamples, + inargs->isInputInterleaved, inargs->inputBufferSizePerChannel, + &outargs->nSamplesConsumed))) { + goto bail; + } + + if (hMp4SpaceEnc->nSamplesNext != hMp4SpaceEnc->nSamplesValid) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + if (hMp4SpaceEnc->encMode == SACENC_212 && + hMp4SpaceEnc->bEncMode_212_only) { + for (ch = 0; ch < nChIn; ch++) { + for (slot = 0; slot < nFrameTimeSlots; slot++) { + setCplxVec( + hMp4SpaceEnc->pppHybridIn__FDK + [ch][hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction + slot], + (FIXP_DBL)0, hMp4SpaceEnc->nHybridBands); + } + } + } + + /* + * Time / Frequency: + * - T/F audio input channels + * - T/F arbitrary downmix input channels + */ + for (ch = 0; ch < nChIn; ch++) { + C_AALLOC_SCRATCH_START(pQmfInReal, FIXP_DBL, MAX_QMF_BANDS) + C_AALLOC_SCRATCH_START(pQmfInImag, FIXP_DBL, MAX_QMF_BANDS) + FIXP_GAIN *pPreGain = + fdk_sacenc_getPreGainPtrFDK(hMp4SpaceEnc->hStaticGain); + + for (ts = 0; ts < nFrameTimeSlots; ts++) { + FIXP_DBL *pSpecReal; + FIXP_DBL *pSpecImag; + + INT_PCM *pTimeIn = + &hMp4SpaceEnc->ppTimeSigIn__FDK[ch][(ts * hMp4SpaceEnc->nQmfBands)]; + + { + /* Apply DC filter on input channels */ + if (SACENC_OK != (error = fdk_sacenc_applyDCFilter( + hMp4SpaceEnc->phDCFilterSigIn[ch], pTimeIn, + pTimeIn, hMp4SpaceEnc->nQmfBands))) { + goto bail; + } + } + + /* QMF filterbank */ + C_ALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (MAX_QMF_BANDS << 1)); + + qmfAnalysisFilteringSlot(hMp4SpaceEnc->phQmfFiltIn__FDK[ch], pQmfInReal, + pQmfInImag, pTimeIn, 1, pWorkBuffer); + + C_ALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (MAX_QMF_BANDS << 1)); + + pSpecReal = pQmfInReal; + pSpecImag = pQmfInImag; + + /* Apply pre-scale after filterbank */ + if (MAXVAL_GAIN != pPreGain[ch]) { + for (i = 0; i < hMp4SpaceEnc->nHybridBands; i++) { + hMp4SpaceEnc + ->pppHybridIn__FDK[ch] + [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots + + ts][i] + .v.re = fMult(pSpecReal[i], pPreGain[ch]); + hMp4SpaceEnc + ->pppHybridIn__FDK[ch] + [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots + + ts][i] + .v.im = fMult(pSpecImag[i], pPreGain[ch]); + } + } else { + for (i = 0; i < hMp4SpaceEnc->nHybridBands; i++) { + hMp4SpaceEnc + ->pppHybridIn__FDK[ch] + [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots + + ts][i] + .v.re = pSpecReal[i]; + hMp4SpaceEnc + ->pppHybridIn__FDK[ch] + [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots + + ts][i] + .v.im = pSpecImag[i]; + } + } + } /* ts */ + C_AALLOC_SCRATCH_END(pQmfInImag, FIXP_DBL, MAX_QMF_BANDS) + C_AALLOC_SCRATCH_END(pQmfInReal, FIXP_DBL, MAX_QMF_BANDS) + + if (SACENC_OK != error) { + goto bail; + } + } /* ch */ + + if (hMp4SpaceEnc->encMode == SACENC_212 && + hMp4SpaceEnc->bEncMode_212_only) { + for (ch = 0; ch < nChIn; ch++) { + for (slot = 0; + slot < (int)(hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction); + slot++) { + copyCplxVec(hMp4SpaceEnc->pppHybridIn__FDK[ch][slot], + hMp4SpaceEnc->pppHybridInStatic__FDK[ch][slot], + hMp4SpaceEnc->nHybridBands); + } + } + for (ch = 0; ch < nChIn; ch++) { + for (slot = 0; + slot < (int)(hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction); + slot++) { + copyCplxVec( + hMp4SpaceEnc->pppHybridInStatic__FDK[ch][slot], + hMp4SpaceEnc->pppHybridIn__FDK[ch][nFrameTimeSlots + slot], + hMp4SpaceEnc->nHybridBands); + } + } + } + + /* + * Onset Detection: + * - detection of transients + * - build framing + */ + for (ch = 0; ch < nChIn; ch++) { + if (ch != 3) { /* !LFE */ + if (SACENC_OK != + (error = fdk_sacenc_onsetDetect_Apply( + hMp4SpaceEnc->phOnset[ch], nFrameTimeSlots, + hMp4SpaceEnc->nHybridBands, + &hMp4SpaceEnc->pppHybridIn__FDK + [ch][hMp4SpaceEnc->nAnalysisLookaheadTimeSlots], + encoderInputChScale[ch], + hMp4SpaceEnc->trPrevPos[1], /* contains previous Transient */ + hMp4SpaceEnc->ppTrCurrPos[ch]))) { + goto bail; + } + + if ((1) && (hMp4SpaceEnc->useFrameKeep == 0)) { + hMp4SpaceEnc->ppTrCurrPos[ch][0] = -1; + } + + /* Find first Transient Position */ + if ((hMp4SpaceEnc->ppTrCurrPos[ch][0] >= 0) && + ((currTransPos < 0) || + (hMp4SpaceEnc->ppTrCurrPos[ch][0] < currTransPos))) { + currTransPos = hMp4SpaceEnc->ppTrCurrPos[ch][0]; + } + } /* !LFE */ + } /* ch */ + + if (hMp4SpaceEnc->useFrameKeep == 1) { + if ((currTransPos != -1) || (hMp4SpaceEnc->independencyFlag == 1)) { + hMp4SpaceEnc->avoid_keep = NUM_KEEP_WINDOWS; + currTransPos = -1; + } + } + + /* Save previous Transient Position */ + hMp4SpaceEnc->trPrevPos[0] = + FDKmax(-1, hMp4SpaceEnc->trPrevPos[1] - (INT)nFrameTimeSlots); + hMp4SpaceEnc->trPrevPos[1] = currTransPos; + + /* Update Onset Detection Energy Buffer */ + for (ch = 0; ch < nChIn; ch++) { + if (SACENC_OK != (error = fdk_sacenc_onsetDetect_Update( + hMp4SpaceEnc->phOnset[ch], nFrameTimeSlots))) { + goto bail; + } + } + + /* Framing */ + if (SACENC_OK != + (error = fdk_sacenc_frameWindow_GetWindow( + hMp4SpaceEnc->hFrameWindow, hMp4SpaceEnc->trPrevPos, + nFrameTimeSlots, &pFrameData->framingInfo, + hMp4SpaceEnc->pFrameWindowAna__FDK, &hMp4SpaceEnc->frameWinList, + hMp4SpaceEnc->avoid_keep))) { + goto bail; + } + + /* + * MPS Processing: + */ + for (ps = 0, winCnt = 0; ps < hMp4SpaceEnc->frameWinList.n; ++ps) { + /* Analysis Windowing */ + if (hMp4SpaceEnc->frameWinList.dat[ps].hold == FW_HOLD) { + /* ************************************** */ + /* ONLY COPY AND HOLD PREVIOUS PARAMETERS */ + if (SACENC_OK != (error = fdk_sacenc_duplicateParameterSet( + &hMp4SpaceEnc->saveFrame, 0, pFrameData, ps))) { + goto bail; + } + + } else { /* !FW_HOLD */ + /* ************************************** */ + /* NEW WINDOW */ + + INT nAnalysisLengthTimeSlots, analysisStartTimeSlot; + + nAnalysisLengthTimeSlots = getAnalysisLengthTimeSlots( + hMp4SpaceEnc->pFrameWindowAna__FDK[winCnt], + hMp4SpaceEnc->nAnalysisLengthTimeSlots); + + analysisStartTimeSlot = + getAnalysisStartTimeSlot(hMp4SpaceEnc->pFrameWindowAna__FDK[winCnt], + hMp4SpaceEnc->nAnalysisLengthTimeSlots); + + /* perform main signal analysis windowing in + * fdk_sacenc_spaceTree_Apply() */ + FIXP_WIN *pFrameWindowAna__FDK = + hMp4SpaceEnc->pFrameWindowAna__FDK[winCnt]; + FIXP_DPK ***pppHybridIn__FDK = hMp4SpaceEnc->pppHybridIn__FDK; + FIXP_DPK ***pppProcDataIn__FDK = hMp4SpaceEnc->pppProcDataIn__FDK; + + if (hMp4SpaceEnc->encMode == SACENC_212 && + hMp4SpaceEnc->bEncMode_212_only) { + pppProcDataIn__FDK = pppHybridIn__FDK; + } + + if (SACENC_OK != + (error = fdk_sacenc_spaceTree_Apply( + hMp4SpaceEnc->hSpaceTree, ps, nChIn, nAnalysisLengthTimeSlots, + analysisStartTimeSlot, hMp4SpaceEnc->nHybridBands, + pFrameWindowAna__FDK, pppHybridIn__FDK, + pppProcDataIn__FDK, /* multi-channel input */ + pFrameData, hMp4SpaceEnc->avoid_keep, encoderInputChScale))) { + goto bail; + } + + /* Save spatial frame for potential hold parameter set */ + if (SACENC_OK != (error = fdk_sacenc_duplicateParameterSet( + pFrameData, ps, &hMp4SpaceEnc->saveFrame, 0))) { + goto bail; + } + + ++winCnt; + } + if (hMp4SpaceEnc->avoid_keep > 0) { + hMp4SpaceEnc->avoid_keep--; + } + } /* Loop over Parameter Sets */ + /* ---- End of Processing Loop ---- */ + + /* + * Update hybridInReal/Imag buffer and do the same for arbDmx + * this means to move the hybrid data of the current frame to the beginning + * of the 2*nFrameLength-long buffer + */ + if (!(hMp4SpaceEnc->encMode == SACENC_212 && + hMp4SpaceEnc->bEncMode_212_only)) { + for (ch = 0; ch < nChIn; ch++) { /* for automatic downmix */ + for (slot = 0; + slot < (int)(hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction); + slot++) { + copyCplxVec( + hMp4SpaceEnc->pppHybridIn__FDK[ch][slot], + hMp4SpaceEnc->pppHybridIn__FDK[ch][nFrameTimeSlots + slot], + hMp4SpaceEnc->nHybridBands); + } + for (slot = 0; slot < nFrameTimeSlots; slot++) { + setCplxVec( + hMp4SpaceEnc->pppHybridIn__FDK + [ch][hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction + slot], + (FIXP_DBL)0, hMp4SpaceEnc->nHybridBands); + } + } + } + /* + * Spatial Tonality: + */ + { + /* Smooth config off. */ + FDKmemclear(&pFrameData->smgData, sizeof(pFrameData->smgData)); + } + + /* + * Create bitstream + * - control independecy flag + * - write spatial frame + * - return bitstream + */ + UCHAR *pBitstreamDelayBuffer; + + if (hMp4SpaceEnc->encMode == SACENC_212) { + /* no bitstream delay buffer for SACENC_212 mode, write bitstream directly + * into the sacOutBuffer buffer which is provided by the core routine */ + pBitstreamDelayBuffer = (UCHAR *)outBufDesc->ppBase[1]; + } else { + /* bitstream delay is handled in ppBitstreamDelayBuffer buffer */ + pBitstreamDelayBuffer = + hMp4SpaceEnc + ->ppBitstreamDelayBuffer[hMp4SpaceEnc->nBitstreamBufferWrite]; + } + if (pBitstreamDelayBuffer == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + pFrameData->bsIndependencyFlag = hMp4SpaceEnc->independencyFlag; + + if (SACENC_OK != + (error = fdk_sacenc_writeSpatialFrame( + pBitstreamDelayBuffer, MAX_MPEGS_BYTES, + &hMp4SpaceEnc->pnOutputBits[hMp4SpaceEnc->nBitstreamBufferWrite], + hMp4SpaceEnc->hBitstreamFormatter))) { + goto bail; + } + + /* return bitstream info */ + if ((hMp4SpaceEnc->nDiscardOutFrames == 0) && + (getBufDescIdx(outBufDesc, + (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_BS_DATA)) != -1)) { + const INT idx = getBufDescIdx( + outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_BS_DATA)); + const INT outBits = + hMp4SpaceEnc->pnOutputBits[hMp4SpaceEnc->nBitstreamBufferRead]; + + if (((outBits + 7) / 8) > + (INT)(outBufDesc->pBufSize[idx] / outBufDesc->pEleSize[idx])) { + outargs->nOutputBits = 0; + error = SACENC_ENCODE_ERROR; + goto bail; + } + + /* return bitstream buffer, copy delayed bitstream for all configurations + * except for the SACENC_212 mode */ + if (hMp4SpaceEnc->encMode != SACENC_212) { + FDKmemcpy( + outBufDesc->ppBase[idx], + hMp4SpaceEnc + ->ppBitstreamDelayBuffer[hMp4SpaceEnc->nBitstreamBufferRead], + (outBits + 7) / 8); + } + + /* return number of valid bits */ + outargs->nOutputBits = outBits; + } else { /* No spatial data should be returned if the current frame is to be + discarded. */ + outargs->nOutputBits = 0; + } + + /* update pointers */ + hMp4SpaceEnc->nBitstreamBufferRead = + (hMp4SpaceEnc->nBitstreamBufferRead + 1) % + hMp4SpaceEnc->nBitstreamDelayBuffer; + hMp4SpaceEnc->nBitstreamBufferWrite = + (hMp4SpaceEnc->nBitstreamBufferWrite + 1) % + hMp4SpaceEnc->nBitstreamDelayBuffer; + + /* Set Output Parameters */ + nOutputSamples = + (hMp4SpaceEnc->nDiscardOutFrames == 0) + ? (nOutputSamplesMax) + : 0; /* don't output samples in case frames to be discarded */ + if (nOutputSamples > nOutputSamplesBufferSize) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + outargs->nOutputSamples = nOutputSamples; + + { /* !bQmfOutput */ + + if (hMp4SpaceEnc->encMode != SACENC_212) { + /* delay output samples and interleave them */ + /* note: in case of arbitrary downmix this will always be processed, + * because nOutputSamples != 0, even if bDMXAlign is switched on */ + /* always run copy-func, so nOutputSamplesMax instead of nOutputSamples + */ + for (ch = 0; ch < nChOut; ch++) { + FDKmemcpy_flex( + &hMp4SpaceEnc->pOutputDelayBuffer__FDK + [ch + (hMp4SpaceEnc->nOutputBufferDelay) * nChOut], + nChOut, hMp4SpaceEnc->ppTimeSigOut__FDK[ch], 1, + nOutputSamplesMax / nChOut); + } + + /* write delayed data in output pcm stream */ + /* always calculate, limiter must have a lookahead!!! */ + FDKmemcpy(pOutputSamples, hMp4SpaceEnc->pOutputDelayBuffer__FDK, + nOutputSamplesMax * sizeof(INT_PCM)); + + /* update delay buffer (move back end to the beginning of the buffer) */ + FDKmemmove( + hMp4SpaceEnc->pOutputDelayBuffer__FDK, + &hMp4SpaceEnc->pOutputDelayBuffer__FDK[nOutputSamplesMax], + nChOut * (hMp4SpaceEnc->nOutputBufferDelay) * sizeof(INT_PCM)); + } + + if (hMp4SpaceEnc->useTimeDomDownmix <= 0) { + if (SACENC_OK != (error = fdk_sacenc_staticPostGain_ApplyFDK( + hMp4SpaceEnc->hStaticGain, pOutputSamples, + nOutputSamplesMax, 0))) { + goto bail; + } + } + + } /* !bQmfOutput */ + + if (hMp4SpaceEnc->nDiscardOutFrames > 0) { + hMp4SpaceEnc->nDiscardOutFrames--; + } + + /* Invalidate Input Buffer */ + hMp4SpaceEnc->nSamplesValid = 0; + + } /* valid handle */ +bail: + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_close(HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL != phMp4SpaceEnc) { + if (NULL != *phMp4SpaceEnc) { + int ch, i; + HANDLE_MP4SPACE_ENCODER const hEnc = *phMp4SpaceEnc; + + if (hEnc->pParameterBand2HybridBandOffset != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pParameterBand2HybridBandOffset); + } + /* Free Analysis Filterbank Structs */ + if (hEnc->pEncoderInputChScale != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pEncoderInputChScale); + } + if (hEnc->staticTimeDomainDmxInScale != NULL) { + FDK_FREE_MEMORY_1D(hEnc->staticTimeDomainDmxInScale); + } + if (hEnc->phQmfFiltIn__FDK != NULL) { + for (ch = 0; ch < hEnc->setup.maxChIn; ch++) { + if (hEnc->phQmfFiltIn__FDK[ch] != NULL) { + if (hEnc->phQmfFiltIn__FDK[ch]->FilterStates != NULL) { + FDK_FREE_MEMORY_1D(hEnc->phQmfFiltIn__FDK[ch]->FilterStates); + } + FDK_FREE_MEMORY_1D(hEnc->phQmfFiltIn__FDK[ch]); + } + } + FDK_FREE_MEMORY_1D(hEnc->phQmfFiltIn__FDK); + } + for (ch = 0; ch < hEnc->setup.maxChIn; ch++) { + if (NULL != hEnc->phDCFilterSigIn[ch]) { + fdk_sacenc_destroyDCFilter(&hEnc->phDCFilterSigIn[ch]); + } + } + /* Close Onset Detection */ + for (ch = 0; ch < hEnc->setup.maxChIn; ch++) { + if (NULL != hEnc->phOnset[ch]) { + fdk_sacenc_onsetDetect_Close(&hEnc->phOnset[ch]); + } + } + if (hEnc->ppTrCurrPos) { + FDK_FREE_MEMORY_2D(hEnc->ppTrCurrPos); + } + if (hEnc->hFrameWindow) { + fdk_sacenc_frameWindow_Destroy(&hEnc->hFrameWindow); + } + /* Close Space Tree */ + if (NULL != hEnc->hSpaceTree) { + fdk_sacenc_spaceTree_Close(&hEnc->hSpaceTree); + } + if (NULL != hEnc->hEnhancedTimeDmx) { + fdk_sacenc_close_enhancedTimeDomainDmx(&hEnc->hEnhancedTimeDmx); + } + /* Close Static Gain */ + if (NULL != hEnc->hStaticGain) { + fdk_sacenc_staticGain_Close(&hEnc->hStaticGain); + } + if (NULL != hEnc->hStaticGainConfig) { + fdk_sacenc_staticGain_CloseConfig(&hEnc->hStaticGainConfig); + } + /* Close Delay*/ + if (NULL != hEnc->hDelay) { + fdk_sacenc_delay_Close(&hEnc->hDelay); + } + /* Delete Bitstream Stuff */ + if (NULL != hEnc->hBitstreamFormatter) { + fdk_sacenc_destroySpatialBitstreamEncoder(&(hEnc->hBitstreamFormatter)); + } + if (hEnc->pppHybridIn__FDK != NULL) { + if (hEnc->setup.bEncMode_212 == 1) { + FDK_FREE_MEMORY_3D(hEnc->pppHybridIn__FDK); + FDK_FREE_MEMORY_3D(hEnc->pppHybridInStatic__FDK); + } else { + FDK_FREE_MEMORY_3D(hEnc->pppHybridIn__FDK); + } + } + if (hEnc->pppProcDataIn__FDK != NULL) { + FDK_FREE_MEMORY_3D(hEnc->pppProcDataIn__FDK); + } + if (hEnc->pOutputDelayBuffer__FDK != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pOutputDelayBuffer__FDK); + } + if (hEnc->ppTimeSigIn__FDK != NULL) { + { FDK_FREE_MEMORY_2D(hEnc->ppTimeSigIn__FDK); } + } + if (hEnc->ppTimeSigDelayIn__FDK != NULL) { + FDK_FREE_MEMORY_2D(hEnc->ppTimeSigDelayIn__FDK); + } + if (hEnc->ppTimeSigOut__FDK != NULL) { + FDK_FREE_MEMORY_2D(hEnc->ppTimeSigOut__FDK); + } + for (i = 0; i < MAX_NUM_PARAMS; i++) { + if (hEnc->pFrameWindowAna__FDK[i] != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pFrameWindowAna__FDK[i]); + } + } + if (hEnc->pnOutputBits != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pnOutputBits); + } + if (hEnc->ppBitstreamDelayBuffer != NULL) { + FDK_FREE_MEMORY_2D(hEnc->ppBitstreamDelayBuffer); + } + if (hEnc->sscBuf.pSsc != NULL) { + FDK_FREE_MEMORY_1D(hEnc->sscBuf.pSsc); + } + FDK_FREE_MEMORY_1D(*phMp4SpaceEnc); + } + } + + return error; +} + +/*----------------------------------------------------------------------------- + functionname: mp4SpaceEnc_InitDelayCompensation() + description: initialzes delay compensation + returns: noError on success, an apropriate error code else + -----------------------------------------------------------------------------*/ +static FDK_SACENC_ERROR mp4SpaceEnc_InitDelayCompensation( + HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, const INT coreCoderDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* Sanity Check */ + if (hMp4SpaceEnc == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + hMp4SpaceEnc->coreCoderDelay = coreCoderDelay; + + if (SACENC_OK != (error = fdk_sacenc_delay_Init( + hMp4SpaceEnc->hDelay, hMp4SpaceEnc->nQmfBands, + hMp4SpaceEnc->nFrameLength, coreCoderDelay, + hMp4SpaceEnc->timeAlignment))) { + goto bail; + } + + fdk_sacenc_delay_SetDmxAlign(hMp4SpaceEnc->hDelay, 0); + fdk_sacenc_delay_SetTimeDomDmx( + hMp4SpaceEnc->hDelay, (hMp4SpaceEnc->useTimeDomDownmix >= 1) ? 1 : 0); + fdk_sacenc_delay_SetMinimizeDelay(hMp4SpaceEnc->hDelay, 1); + + if (SACENC_OK != (error = fdk_sacenc_delay_SubCalulateBufferDelays( + hMp4SpaceEnc->hDelay))) { + goto bail; + } + + /* init output delay compensation */ + hMp4SpaceEnc->nBitstreamDelayBuffer = + fdk_sacenc_delay_GetBitstreamFrameBufferSize(hMp4SpaceEnc->hDelay); + hMp4SpaceEnc->nOutputBufferDelay = + fdk_sacenc_delay_GetOutputAudioBufferDelay(hMp4SpaceEnc->hDelay); + hMp4SpaceEnc->nSurroundAnalysisBufferDelay = + fdk_sacenc_delay_GetSurroundAnalysisBufferDelay(hMp4SpaceEnc->hDelay); + hMp4SpaceEnc->nBitstreamBufferRead = 0; + hMp4SpaceEnc->nBitstreamBufferWrite = + hMp4SpaceEnc->nBitstreamDelayBuffer - 1; + + if (hMp4SpaceEnc->encMode == SACENC_212) { + /* mode 212 expects no bitstream delay */ + if (hMp4SpaceEnc->nBitstreamBufferWrite != + hMp4SpaceEnc->nBitstreamBufferRead) { + error = SACENC_PARAM_ERROR; + goto bail; + } + + /* mode 212 expects no output buffer delay */ + if (hMp4SpaceEnc->nOutputBufferDelay != 0) { + error = SACENC_PARAM_ERROR; + goto bail; + } + } + + /*** Input delay to obtain a net encoder delay that is a multiple + of the used framelength to ensure synchronization of framing + in artistic down-mix with the corresponding spatial data. ***/ + hMp4SpaceEnc->nDiscardOutFrames = + fdk_sacenc_delay_GetDiscardOutFrames(hMp4SpaceEnc->hDelay); + hMp4SpaceEnc->nInputDelay = + fdk_sacenc_delay_GetDmxAlignBufferDelay(hMp4SpaceEnc->hDelay); + + /* reset independency Flag counter */ + hMp4SpaceEnc->independencyCount = 0; + hMp4SpaceEnc->independencyFlag = 1; + + int i; + + /* write some parameters to bitstream */ + for (i = 0; i < hMp4SpaceEnc->nBitstreamDelayBuffer - 1; i++) { + SPATIALFRAME *pFrameData = NULL; + + if (NULL == (pFrameData = fdk_sacenc_getSpatialFrame( + hMp4SpaceEnc->hBitstreamFormatter, READ_SPATIALFRAME))) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + pFrameData->bsIndependencyFlag = 1; + pFrameData->framingInfo.numParamSets = 1; + pFrameData->framingInfo.bsFramingType = 0; + + fdk_sacenc_writeSpatialFrame( + hMp4SpaceEnc->ppBitstreamDelayBuffer[i], MAX_MPEGS_BYTES, + &hMp4SpaceEnc->pnOutputBits[i], hMp4SpaceEnc->hBitstreamFormatter); + } + + if ((hMp4SpaceEnc->nInputDelay > MAX_DELAY_INPUT) || + (hMp4SpaceEnc->nOutputBufferDelay > MAX_DELAY_OUTPUT) || + (hMp4SpaceEnc->nSurroundAnalysisBufferDelay > + MAX_DELAY_SURROUND_ANALYSIS) || + (hMp4SpaceEnc->nBitstreamDelayBuffer > MAX_BITSTREAM_DELAY)) { + error = SACENC_INIT_ERROR; + goto bail; + } + } + +bail: + + return error; +} + +static QUANTMODE __mapQuantMode(const MP4SPACEENC_QUANTMODE quantMode) { + QUANTMODE bsQuantMode = QUANTMODE_INVALID; + + switch (quantMode) { + case SACENC_QUANTMODE_FINE: + bsQuantMode = QUANTMODE_FINE; + break; + case SACENC_QUANTMODE_EBQ1: + bsQuantMode = QUANTMODE_EBQ1; + break; + case SACENC_QUANTMODE_EBQ2: + bsQuantMode = QUANTMODE_EBQ2; + break; + case SACENC_QUANTMODE_RSVD3: + case SACENC_QUANTMODE_INVALID: + default: + bsQuantMode = QUANTMODE_INVALID; + } /* switch hEnc->quantMode */ + + return bsQuantMode; +} + +static FDK_SACENC_ERROR FillSpatialSpecificConfig( + const HANDLE_MP4SPACE_ENCODER hEnc, SPATIALSPECIFICCONFIG *const hSsc) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hEnc) || (NULL == hSsc)) { + error = SACENC_INVALID_HANDLE; + } else { + SPACE_TREE_DESCRIPTION spaceTreeDescription; + int i; + + /* Get tree description */ + if (SACENC_OK != (error = fdk_sacenc_spaceTree_GetDescription( + hEnc->hSpaceTree, &spaceTreeDescription))) { + goto bail; + } + + /* Fill SSC */ + FDKmemclear(hSsc, sizeof(SPATIALSPECIFICCONFIG)); /* reset */ + + hSsc->numBands = hEnc->spaceTreeSetup.nParamBands; /* for bsFreqRes */ + + /* Fill tree configuration */ + hSsc->treeDescription.numOttBoxes = spaceTreeDescription.nOttBoxes; + hSsc->treeDescription.numInChan = spaceTreeDescription.nInChannels; + hSsc->treeDescription.numOutChan = spaceTreeDescription.nOutChannels; + + for (i = 0; i < SACENC_MAX_NUM_BOXES; i++) { + hSsc->ottConfig[i].bsOttBands = hSsc->numBands; + } + + switch (hEnc->encMode) { + case SACENC_212: + hSsc->bsTreeConfig = TREE_212; + break; + case SACENC_INVALID_MODE: + default: + error = SACENC_INVALID_CONFIG; + goto bail; + } + + hSsc->bsSamplingFrequency = + hEnc->nSampleRate; /* for bsSamplingFrequencyIndex */ + hSsc->bsFrameLength = hEnc->nFrameTimeSlots - 1; + + /* map decorr type */ + if (DECORR_INVALID == + (hSsc->bsDecorrConfig = mp4SpaceEnc_GetDecorrConfig(hEnc->encMode))) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* map quantMode */ + if (QUANTMODE_INVALID == + (hSsc->bsQuantMode = __mapQuantMode(hEnc->quantMode))) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* Configure Gains*/ + hSsc->bsFixedGainDMX = fdk_sacenc_staticGain_GetDmxGain(hEnc->hStaticGain); + hSsc->bsEnvQuantMode = 0; + + } /* valid handle */ + +bail: + return error; +} + +static FDK_SACENC_ERROR mp4SpaceEnc_FillSpaceTreeSetup( + const HANDLE_MP4SPACE_ENCODER hEnc, + SPACE_TREE_SETUP *const hSpaceTreeSetup) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* Sanity Check */ + if (NULL == hEnc || NULL == hSpaceTreeSetup) { + error = SACENC_INVALID_HANDLE; + } else { + QUANTMODE tmpQuantmode = QUANTMODE_INVALID; + + /* map quantMode */ + if (QUANTMODE_INVALID == (tmpQuantmode = __mapQuantMode(hEnc->quantMode))) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + hSpaceTreeSetup->nParamBands = hEnc->nParamBands; + hSpaceTreeSetup->bUseCoarseQuantTtoCld = hEnc->useCoarseQuantCld; + hSpaceTreeSetup->bUseCoarseQuantTtoIcc = hEnc->useCoarseQuantIcc; + hSpaceTreeSetup->quantMode = tmpQuantmode; + hSpaceTreeSetup->nHybridBandsMax = hEnc->nHybridBands; + + switch (hEnc->encMode) { + case SACENC_212: + hSpaceTreeSetup->mode = SPACETREE_212; + hSpaceTreeSetup->nChannelsInMax = 2; + break; + case SACENC_INVALID_MODE: + default: + error = SACENC_INVALID_CONFIG; + goto bail; + } /* switch hEnc->encMode */ + + } /* valid handle */ +bail: + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_getInfo(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + MP4SPACEENC_INFO *const pInfo) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hMp4SpaceEnc) || (NULL == pInfo)) { + error = SACENC_INVALID_HANDLE; + } else { + pInfo->nSampleRate = hMp4SpaceEnc->nSampleRate; + pInfo->nSamplesFrame = hMp4SpaceEnc->nFrameLength; + pInfo->nTotalInputChannels = hMp4SpaceEnc->nInputChannels; + pInfo->nDmxDelay = fdk_sacenc_delay_GetInfoDmxDelay(hMp4SpaceEnc->hDelay); + pInfo->nCodecDelay = + fdk_sacenc_delay_GetInfoCodecDelay(hMp4SpaceEnc->hDelay); + pInfo->nDecoderDelay = + fdk_sacenc_delay_GetInfoDecoderDelay(hMp4SpaceEnc->hDelay); + pInfo->nPayloadDelay = + fdk_sacenc_delay_GetBitstreamFrameBufferSize(hMp4SpaceEnc->hDelay) - 1; + pInfo->nDiscardOutFrames = hMp4SpaceEnc->nDiscardOutFrames; + + pInfo->pSscBuf = &hMp4SpaceEnc->sscBuf; + } + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_setParam(HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + const SPACEENC_PARAM param, + const UINT value) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* check encoder handle */ + if (hMp4SpaceEnc == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + /* apply param value */ + switch (param) { + case SACENC_LOWDELAY: + if (!((value == 0) || (value == 1) || (value == 2))) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.bLdMode = value; + break; + + case SACENC_ENC_MODE: + switch ((MP4SPACEENC_MODE)value) { + case SACENC_212: + hMp4SpaceEnc->user.encMode = (MP4SPACEENC_MODE)value; + break; + default: + error = SACENC_INVALID_CONFIG; + } + break; + + case SACENC_SAMPLERATE: + if (((int)value < 0) || + ((int)value > hMp4SpaceEnc->setup.maxSamplingrate)) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.sampleRate = value; + break; + + case SACENC_FRAME_TIME_SLOTS: + if (((int)value < 0) || + ((int)value > hMp4SpaceEnc->setup.maxFrameTimeSlots)) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.frameTimeSlots = value; + break; + + case SACENC_PARAM_BANDS: + switch ((MP4SPACEENC_BANDS_CONFIG)value) { + case SACENC_BANDS_4: + case SACENC_BANDS_5: + case SACENC_BANDS_7: + case SACENC_BANDS_9: + case SACENC_BANDS_12: + case SACENC_BANDS_15: + case SACENC_BANDS_23: + hMp4SpaceEnc->user.nParamBands = (MP4SPACEENC_BANDS_CONFIG)value; + break; + default: + error = SACENC_INVALID_CONFIG; + } + break; + + case SACENC_TIME_DOM_DMX: + if (!((value == 0) || (value == 2))) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.bTimeDomainDmx = value; + break; + + case SACENC_DMX_GAIN: + if (!((value == 0) || (value == 1) || (value == 2) || (value == 3) || + (value == 4) || (value == 5) || (value == 6) || (value == 7))) { + error = SACENC_INVALID_CONFIG; + break; + } + error = fdk_sacenc_staticGain_SetDmxGain(hMp4SpaceEnc->hStaticGainConfig, + (MP4SPACEENC_DMX_GAIN)value); + break; + + case SACENC_COARSE_QUANT: + if (!((value == 0) || (value == 1))) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.bUseCoarseQuant = value; + break; + + case SACENC_QUANT_MODE: + switch ((MP4SPACEENC_QUANTMODE)value) { + case SACENC_QUANTMODE_FINE: + case SACENC_QUANTMODE_EBQ1: + case SACENC_QUANTMODE_EBQ2: + hMp4SpaceEnc->user.quantMode = (MP4SPACEENC_QUANTMODE)value; + break; + default: + error = SACENC_INVALID_CONFIG; + } + break; + + case SACENC_TIME_ALIGNMENT: + if ((INT)value < -32768 || (INT)value > 32767) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.timeAlignment = value; + break; + + case SACENC_INDEPENDENCY_COUNT: + hMp4SpaceEnc->independencyCount = value; + break; + + case SACENC_INDEPENDENCY_FACTOR: + hMp4SpaceEnc->user.independencyFactor = value; + break; + + default: + error = SACENC_UNSUPPORTED_PARAMETER; + break; + } /* switch(param) */ +bail: + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_getLibInfo(LIB_INFO *info) { + int i = 0; + + if (info == NULL) { + return SACENC_INVALID_HANDLE; + } + + FDK_toolsGetLibInfo(info); + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return SACENC_INIT_ERROR; + } + + info[i].module_id = FDK_MPSENC; + info[i].build_date = SACENC_LIB_BUILD_DATE; + info[i].build_time = SACENC_LIB_BUILD_TIME; + info[i].title = SACENC_LIB_TITLE; + info[i].version = LIB_VERSION(SACENC_LIB_VL0, SACENC_LIB_VL1, SACENC_LIB_VL2); + LIB_VERSION_STRING(&info[i]); + + /* Capability flags */ + info[i].flags = 0; + /* End of flags */ + + return SACENC_OK; +} + +static DECORRCONFIG mp4SpaceEnc_GetDecorrConfig( + const MP4SPACEENC_MODE encMode) { + DECORRCONFIG decorrConfig = DECORR_INVALID; + + /* set decorrConfig dependent on tree mode */ + switch (encMode) { + case SACENC_212: + decorrConfig = DECORR_QMFSPLIT0; + break; + case SACENC_INVALID_MODE: + default: + decorrConfig = DECORR_INVALID; + } + return decorrConfig; +} + +static FDK_SACENC_ERROR mp4SpaceEnc_InitNumParamBands( + HANDLE_MP4SPACE_ENCODER hEnc, const MP4SPACEENC_BANDS_CONFIG nParamBands) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* Set/Check nParamBands */ + int k = 0; + const int n = sizeof(pValidBands_Ld) / sizeof(UCHAR); + const UCHAR *pBands = pValidBands_Ld; + + while (k < n && pBands[k] != (UCHAR)nParamBands) ++k; + if (k == n) { + hEnc->nParamBands = SACENC_BANDS_INVALID; + } else { + hEnc->nParamBands = nParamBands; + } + return error; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_nlc_enc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_nlc_enc.cpp new file mode 100644 index 0000000000000..0ba6cc9f2b588 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_nlc_enc.cpp @@ -0,0 +1,1442 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Karsten Linzmeier + + Description: Noiseless Coding + Huffman encoder + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_nlc_enc.h" + +#include "genericStds.h" +#include "fixpoint_math.h" + +#include "sacenc_const.h" +#include "sacenc_huff_tab.h" +#include "sacenc_paramextract.h" + +/* Defines *******************************************************************/ +#define PAIR_SHIFT 4 +#define PAIR_MASK 0xf + +#define PBC_MIN_BANDS 5 + +typedef enum { + BACKWARDS = 0x0, + FORWARDS = 0x1 + +} DIRECTION; + +typedef enum { + DIFF_FREQ = 0x0, + DIFF_TIME = 0x1 + +} DIFF_TYPE; + +typedef enum { + HUFF_1D = 0x0, + HUFF_2D = 0x1 + +} CODING_SCHEME; + +typedef enum { + FREQ_PAIR = 0x0, + TIME_PAIR = 0x1 + +} PAIRING; + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ +static const UCHAR lavHuffVal[4] = {0, 2, 6, 7}; +static const UCHAR lavHuffLen[4] = {1, 2, 3, 3}; + +static const UCHAR lav_step_CLD[] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3}; +static const UCHAR lav_step_ICC[] = {0, 0, 1, 1, 2, 2, 3, 3}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static void split_lsb(const SHORT *const in_data, SHORT offset, + const INT num_val, SHORT *const out_data_lsb, + SHORT *const out_data_msb) { + int i; + + for (i = 0; i < num_val; i++) { + SHORT val = in_data[i] + offset; + if (out_data_lsb != NULL) out_data_lsb[i] = val & 0x0001; + if (out_data_msb != NULL) out_data_msb[i] = val >> 1; + } +} + +static void apply_lsb_coding(HANDLE_FDK_BITSTREAM strm, + const SHORT *const in_data_lsb, const UINT num_lsb, + const INT num_val) { + int i; + + for (i = 0; i < num_val; i++) { + FDKwriteBits(strm, in_data_lsb[i], num_lsb); + } +} + +static void calc_diff_freq(const SHORT *const in_data, SHORT *const out_data, + const INT num_val) { + int i; + out_data[0] = in_data[0]; + + for (i = 1; i < num_val; i++) { + out_data[i] = in_data[i] - in_data[i - 1]; + } +} + +static void calc_diff_time(const SHORT *const in_data, + const SHORT *const prev_data, SHORT *const out_data, + const INT num_val) { + int i; + out_data[0] = in_data[0]; + out_data[1] = prev_data[0]; + + for (i = 0; i < num_val; i++) { + out_data[i + 2] = in_data[i] - prev_data[i]; + } +} + +static INT sym_check(SHORT data[2], const INT lav, SHORT *const pSym_bits) { + UCHAR symBits = 0; + int sum_val = data[0] + data[1]; + int diff_val = data[0] - data[1]; + int num_sbits = 0; + + if (sum_val != 0) { + int sum_neg = (sum_val < 0) ? 1 : 0; + if (sum_neg) { + sum_val = -sum_val; + diff_val = -diff_val; + } + symBits = (symBits << 1) | sum_neg; + num_sbits++; + } + + if (diff_val != 0) { + int diff_neg = (diff_val < 0) ? 1 : 0; + if (diff_neg) { + diff_val = -diff_val; + } + symBits = (symBits << 1) | diff_neg; + num_sbits++; + } + + if (pSym_bits != NULL) { + *pSym_bits = symBits; + } + + if (sum_val % 2) { + data[0] = lav - sum_val / 2; + data[1] = lav - diff_val / 2; + } else { + data[0] = sum_val / 2; + data[1] = diff_val / 2; + } + + return num_sbits; +} + +static INT ilog2(UINT i) { + int l = 0; + + if (i) i--; + while (i > 0) { + i >>= 1; + l++; + } + + return l; +} + +static SHORT calc_pcm_bits(const SHORT num_val, const SHORT num_levels) { + SHORT num_complete_chunks = 0, rest_chunk_size = 0; + SHORT max_grp_len = 0, bits_pcm = 0; + int chunk_levels, i; + + switch (num_levels) { + case 3: + max_grp_len = 5; + break; + case 6: + max_grp_len = 5; + break; + case 7: + max_grp_len = 6; + break; + case 11: + max_grp_len = 2; + break; + case 13: + max_grp_len = 4; + break; + case 19: + max_grp_len = 4; + break; + case 25: + max_grp_len = 3; + break; + case 51: + max_grp_len = 4; + break; + default: + max_grp_len = 1; + } + + num_complete_chunks = num_val / max_grp_len; + rest_chunk_size = num_val % max_grp_len; + + chunk_levels = 1; + for (i = 1; i <= max_grp_len; i++) { + chunk_levels *= num_levels; + } + + bits_pcm = (SHORT)(ilog2(chunk_levels) * num_complete_chunks); + bits_pcm += (SHORT)(ilog2(num_levels) * rest_chunk_size); + + return bits_pcm; +} + +static void apply_pcm_coding(HANDLE_FDK_BITSTREAM strm, + const SHORT *const in_data_1, + const SHORT *const in_data_2, const SHORT offset, + const SHORT num_val, const SHORT num_levels) { + SHORT i = 0, j = 0, idx = 0; + SHORT max_grp_len = 0, grp_len = 0, next_val = 0; + int grp_val = 0, chunk_levels = 0; + + SHORT pcm_chunk_size[7] = {0}; + + switch (num_levels) { + case 3: + max_grp_len = 5; + break; + case 5: + max_grp_len = 3; + break; + case 6: + max_grp_len = 5; + break; + case 7: + max_grp_len = 6; + break; + case 9: + max_grp_len = 5; + break; + case 11: + max_grp_len = 2; + break; + case 13: + max_grp_len = 4; + break; + case 19: + max_grp_len = 4; + break; + case 25: + max_grp_len = 3; + break; + case 51: + max_grp_len = 4; + break; + default: + max_grp_len = 1; + } + + chunk_levels = 1; + for (i = 1; i <= max_grp_len; i++) { + chunk_levels *= num_levels; + pcm_chunk_size[i] = ilog2(chunk_levels); + } + + for (i = 0; i < num_val; i += max_grp_len) { + grp_len = FDKmin(max_grp_len, num_val - i); + grp_val = 0; + for (j = 0; j < grp_len; j++) { + idx = i + j; + if (in_data_2 == NULL) { + next_val = in_data_1[idx]; + } else if (in_data_1 == NULL) { + next_val = in_data_2[idx]; + } else { + next_val = ((idx % 2) ? in_data_2[idx / 2] : in_data_1[idx / 2]); + } + next_val += offset; + grp_val = grp_val * num_levels + next_val; + } + + FDKwriteBits(strm, grp_val, pcm_chunk_size[grp_len]); + } +} + +static UINT huff_enc_1D(HANDLE_FDK_BITSTREAM strm, const DATA_TYPE data_type, + const INT dim1, SHORT *const in_data, + const SHORT num_val, const SHORT p0_flag) { + int i, offset = 0; + UINT huffBits = 0; + + HUFF_ENTRY part0 = {0}; + const HUFF_ENTRY *pHuffTab = NULL; + + switch (data_type) { + case t_CLD: + pHuffTab = fdk_sacenc_huffCLDTab.h1D[dim1]; + break; + case t_ICC: + pHuffTab = fdk_sacenc_huffICCTab.h1D[dim1]; + break; + } + + if (p0_flag) { + switch (data_type) { + case t_CLD: + part0 = fdk_sacenc_huffPart0Tab.cld[in_data[0]]; + break; + case t_ICC: + part0 = fdk_sacenc_huffPart0Tab.icc[in_data[0]]; + break; + } + huffBits += FDKwriteBits(strm, HUFF_VALUE(part0), HUFF_LENGTH(part0)); + offset = 1; + } + + for (i = offset; i < num_val; i++) { + int id_sign = 0; + int id = in_data[i]; + + if (id != 0) { + id_sign = 0; + if (id < 0) { + id = -id; + id_sign = 1; + } + } + + huffBits += + FDKwriteBits(strm, HUFF_VALUE(pHuffTab[id]), HUFF_LENGTH(pHuffTab[id])); + + if (id != 0) { + huffBits += FDKwriteBits(strm, id_sign, 1); + } + } /* for i */ + + return huffBits; +} + +static void getHuffEntry(const INT lav, const DATA_TYPE data_type, const INT i, + const SHORT tab_idx_2D[2], const SHORT in_data[][2], + HUFF_ENTRY *const pEntry, HUFF_ENTRY *const pEscape) { + const HUFF_CLD_TAB_2D *pCLD2dTab = + &fdk_sacenc_huffCLDTab.h2D[tab_idx_2D[0]][tab_idx_2D[1]]; + const HUFF_ICC_TAB_2D *pICC2dTab = + &fdk_sacenc_huffICCTab.h2D[tab_idx_2D[0]][tab_idx_2D[1]]; + + switch (lav) { + case 1: { + const LAV1_2D *pLav1 = NULL; + switch (data_type) { + case t_CLD: + pLav1 = NULL; + break; + case t_ICC: + pLav1 = &pICC2dTab->lav1; + break; + } + if (pLav1 != NULL) { + *pEntry = pLav1->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav1->escape; + } + } break; + case 3: { + const LAV3_2D *pLav3 = NULL; + switch (data_type) { + case t_CLD: + pLav3 = &pCLD2dTab->lav3; + break; + case t_ICC: + pLav3 = &pICC2dTab->lav3; + break; + } + if (pLav3 != NULL) { + *pEntry = pLav3->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav3->escape; + } + } break; + case 5: { + const LAV5_2D *pLav5 = NULL; + switch (data_type) { + case t_CLD: + pLav5 = &pCLD2dTab->lav5; + break; + case t_ICC: + pLav5 = &pICC2dTab->lav5; + break; + } + if (pLav5 != NULL) { + *pEntry = pLav5->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav5->escape; + } + } break; + case 7: { + const LAV7_2D *pLav7 = NULL; + switch (data_type) { + case t_CLD: + pLav7 = &pCLD2dTab->lav7; + break; + case t_ICC: + pLav7 = &pICC2dTab->lav7; + break; + } + if (pLav7 != NULL) { + *pEntry = pLav7->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav7->escape; + } + } break; + case 9: { + const LAV9_2D *pLav9 = NULL; + switch (data_type) { + case t_CLD: + pLav9 = &pCLD2dTab->lav9; + break; + case t_ICC: + pLav9 = NULL; + break; + } + if (pLav9 != NULL) { + *pEntry = pLav9->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav9->escape; + } + } break; + } +} + +static UINT huff_enc_2D(HANDLE_FDK_BITSTREAM strm, const DATA_TYPE data_type, + SHORT tab_idx_2D[2], SHORT lav_idx, SHORT in_data[][2], + SHORT num_val, SHORT stride, SHORT *p0_data[2]) { + SHORT i = 0, lav = 0, num_sbits = 0, sym_bits = 0, escIdx = 0; + SHORT esc_data[2][MAXBANDS] = {{0}}; + + UINT huffBits = 0; + + const HUFF_ENTRY *pHuffEntry = NULL; + + switch (data_type) { + case t_CLD: + lav = 2 * lav_idx + 3; /* LAV */ + pHuffEntry = fdk_sacenc_huffPart0Tab.cld; + break; + case t_ICC: + lav = 2 * lav_idx + 1; /* LAV */ + pHuffEntry = fdk_sacenc_huffPart0Tab.icc; + break; + } + + /* Partition 0 */ + if (p0_data[0] != NULL) { + HUFF_ENTRY entry = pHuffEntry[*p0_data[0]]; + huffBits += FDKwriteBits(strm, HUFF_VALUE(entry), HUFF_LENGTH(entry)); + } + if (p0_data[1] != NULL) { + HUFF_ENTRY entry = pHuffEntry[*p0_data[1]]; + huffBits += FDKwriteBits(strm, HUFF_VALUE(entry), HUFF_LENGTH(entry)); + } + + for (i = 0; i < num_val; i += stride) { + HUFF_ENTRY entry = {0}; + HUFF_ENTRY escape = {0}; + + esc_data[0][escIdx] = in_data[i][0] + lav; + esc_data[1][escIdx] = in_data[i][1] + lav; + + num_sbits = sym_check(in_data[i], lav, &sym_bits); + + getHuffEntry(lav, data_type, i, tab_idx_2D, in_data, &entry, &escape); + + huffBits += FDKwriteBits(strm, HUFF_VALUE(entry), HUFF_LENGTH(entry)); + + if ((HUFF_VALUE(entry) == HUFF_VALUE(escape)) && + (HUFF_LENGTH(entry) == HUFF_LENGTH(escape))) { + escIdx++; + } else { + huffBits += FDKwriteBits(strm, sym_bits, num_sbits); + } + } /* for i */ + + if (escIdx > 0) { + huffBits += calc_pcm_bits(2 * escIdx, (2 * lav + 1)); + if (strm != NULL) { + apply_pcm_coding(strm, esc_data[0], esc_data[1], 0 /*offset*/, 2 * escIdx, + (2 * lav + 1)); + } + } + + return huffBits; +} + +static SCHAR get_next_lav_step(const INT lav, const DATA_TYPE data_type) { + SCHAR lav_step = 0; + + switch (data_type) { + case t_CLD: + lav_step = (lav > 9) ? -1 : lav_step_CLD[lav]; + break; + case t_ICC: + lav_step = (lav > 7) ? -1 : lav_step_ICC[lav]; + break; + } + + return lav_step; +} + +static INT diff_type_offset(const DIFF_TYPE diff_type) { + int offset = 0; + switch (diff_type) { + case DIFF_FREQ: + offset = 0; + break; + case DIFF_TIME: + offset = 2; + break; + } + return offset; +} + +static SHORT calc_huff_bits(SHORT *in_data_1, SHORT *in_data_2, + const DATA_TYPE data_type, + const DIFF_TYPE diff_type_1, + const DIFF_TYPE diff_type_2, const SHORT num_val, + SHORT *const lav_idx, SHORT *const cdg_scheme) { + SHORT tab_idx_2D[2][2] = {{0}}; + SHORT tab_idx_1D[2] = {0}; + SHORT df_rest_flag[2] = {0}; + SHORT p0_flag[2] = {0}; + + SHORT pair_vec[MAXBANDS][2] = {{0}}; + + SHORT *p0_data_1[2] = {NULL}; + SHORT *p0_data_2[2] = {NULL}; + + SHORT i = 0; + SHORT lav_fp[2] = {0}; + + SHORT bit_count_1D = 0; + SHORT bit_count_2D_freq = 0; + SHORT bit_count_min = 0; + + SHORT num_val_1_short = 0; + SHORT num_val_2_short = 0; + + SHORT *in_data_1_short = NULL; + SHORT *in_data_2_short = NULL; + + /* 1D Huffman coding */ + bit_count_1D = 1; /* HUFF_1D */ + + num_val_1_short = num_val; + num_val_2_short = num_val; + + if (in_data_1 != NULL) { + in_data_1_short = in_data_1 + diff_type_offset(diff_type_1); + } + if (in_data_2 != NULL) { + in_data_2_short = in_data_2 + diff_type_offset(diff_type_2); + } + + p0_flag[0] = (diff_type_1 == DIFF_FREQ); + p0_flag[1] = (diff_type_2 == DIFF_FREQ); + + tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; + tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; + + if (in_data_1 != NULL) { + bit_count_1D += huff_enc_1D(NULL, data_type, tab_idx_1D[0], in_data_1_short, + num_val_1_short, p0_flag[0]); + } + if (in_data_2 != NULL) { + bit_count_1D += huff_enc_1D(NULL, data_type, tab_idx_1D[1], in_data_2_short, + num_val_2_short, p0_flag[1]); + } + + bit_count_min = bit_count_1D; + *cdg_scheme = HUFF_1D << PAIR_SHIFT; + lav_idx[0] = lav_idx[1] = -1; + + /* Huffman 2D frequency pairs */ + bit_count_2D_freq = 1; /* HUFF_2D */ + + num_val_1_short = num_val; + num_val_2_short = num_val; + + if (in_data_1 != NULL) { + in_data_1_short = in_data_1 + diff_type_offset(diff_type_1); + } + if (in_data_2 != NULL) { + in_data_2_short = in_data_2 + diff_type_offset(diff_type_2); + } + + lav_fp[0] = lav_fp[1] = 0; + + p0_data_1[0] = NULL; + p0_data_1[1] = NULL; + p0_data_2[0] = NULL; + p0_data_2[1] = NULL; + + if (in_data_1 != NULL) { + if (diff_type_1 == DIFF_FREQ) { + p0_data_1[0] = &in_data_1[0]; + p0_data_1[1] = NULL; + + num_val_1_short -= 1; + in_data_1_short += 1; + } + + df_rest_flag[0] = num_val_1_short % 2; + + if (df_rest_flag[0]) num_val_1_short -= 1; + + for (i = 0; i < num_val_1_short - 1; i += 2) { + pair_vec[i][0] = in_data_1_short[i]; + pair_vec[i][1] = in_data_1_short[i + 1]; + + lav_fp[0] = FDKmax(lav_fp[0], fAbs(pair_vec[i][0])); + lav_fp[0] = FDKmax(lav_fp[0], fAbs(pair_vec[i][1])); + } + + tab_idx_2D[0][0] = (diff_type_1 == DIFF_TIME) ? 1 : 0; + tab_idx_2D[0][1] = 0; + + tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; + + lav_fp[0] = get_next_lav_step(lav_fp[0], data_type); + + if (lav_fp[0] != -1) bit_count_2D_freq += lavHuffLen[lav_fp[0]]; + } + + if (in_data_2 != NULL) { + if (diff_type_2 == DIFF_FREQ) { + p0_data_2[0] = NULL; + p0_data_2[1] = &in_data_2[0]; + + num_val_2_short -= 1; + in_data_2_short += 1; + } + + df_rest_flag[1] = num_val_2_short % 2; + + if (df_rest_flag[1]) num_val_2_short -= 1; + + for (i = 0; i < num_val_2_short - 1; i += 2) { + pair_vec[i + 1][0] = in_data_2_short[i]; + pair_vec[i + 1][1] = in_data_2_short[i + 1]; + + lav_fp[1] = FDKmax(lav_fp[1], fAbs(pair_vec[i + 1][0])); + lav_fp[1] = FDKmax(lav_fp[1], fAbs(pair_vec[i + 1][1])); + } + + tab_idx_2D[1][0] = (diff_type_2 == DIFF_TIME) ? 1 : 0; + tab_idx_2D[1][1] = 0; + + tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; + + lav_fp[1] = get_next_lav_step(lav_fp[1], data_type); + + if (lav_fp[1] != -1) bit_count_2D_freq += lavHuffLen[lav_fp[1]]; + } + + if ((lav_fp[0] != -1) && (lav_fp[1] != -1)) { + if (in_data_1 != NULL) { + bit_count_2D_freq += + huff_enc_2D(NULL, data_type, tab_idx_2D[0], lav_fp[0], pair_vec, + num_val_1_short, 2, p0_data_1); + } + if (in_data_2 != NULL) { + bit_count_2D_freq += + huff_enc_2D(NULL, data_type, tab_idx_2D[1], lav_fp[1], pair_vec + 1, + num_val_2_short, 2, p0_data_2); + } + if (in_data_1 != NULL) { + if (df_rest_flag[0]) + bit_count_2D_freq += + huff_enc_1D(NULL, data_type, tab_idx_1D[0], + in_data_1_short + num_val_1_short, 1, 0); + } + if (in_data_2 != NULL) { + if (df_rest_flag[1]) + bit_count_2D_freq += + huff_enc_1D(NULL, data_type, tab_idx_1D[1], + in_data_2_short + num_val_2_short, 1, 0); + } + + if (bit_count_2D_freq < bit_count_min) { + bit_count_min = bit_count_2D_freq; + *cdg_scheme = HUFF_2D << PAIR_SHIFT | FREQ_PAIR; + lav_idx[0] = lav_fp[0]; + lav_idx[1] = lav_fp[1]; + } + } + + return bit_count_min; +} + +static void apply_huff_coding(HANDLE_FDK_BITSTREAM strm, SHORT *const in_data_1, + SHORT *const in_data_2, const DATA_TYPE data_type, + const DIFF_TYPE diff_type_1, + const DIFF_TYPE diff_type_2, const SHORT num_val, + const SHORT *const lav_idx, + const SHORT cdg_scheme) { + SHORT tab_idx_2D[2][2] = {{0}}; + SHORT tab_idx_1D[2] = {0}; + SHORT df_rest_flag[2] = {0}; + SHORT p0_flag[2] = {0}; + + SHORT pair_vec[MAXBANDS][2] = {{0}}; + + SHORT *p0_data_1[2] = {NULL}; + SHORT *p0_data_2[2] = {NULL}; + + SHORT i = 0; + + SHORT num_val_1_short = num_val; + SHORT num_val_2_short = num_val; + + SHORT *in_data_1_short = NULL; + SHORT *in_data_2_short = NULL; + + /* Offset */ + if (in_data_1 != NULL) { + in_data_1_short = in_data_1 + diff_type_offset(diff_type_1); + } + if (in_data_2 != NULL) { + in_data_2_short = in_data_2 + diff_type_offset(diff_type_2); + } + + /* Signalize coding scheme */ + FDKwriteBits(strm, cdg_scheme >> PAIR_SHIFT, 1); + + switch (cdg_scheme >> PAIR_SHIFT) { + case HUFF_1D: + + p0_flag[0] = (diff_type_1 == DIFF_FREQ); + p0_flag[1] = (diff_type_2 == DIFF_FREQ); + + tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; + tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; + + if (in_data_1 != NULL) { + huff_enc_1D(strm, data_type, tab_idx_1D[0], in_data_1_short, + num_val_1_short, p0_flag[0]); + } + if (in_data_2 != NULL) { + huff_enc_1D(strm, data_type, tab_idx_1D[1], in_data_2_short, + num_val_2_short, p0_flag[1]); + } + break; /* HUFF_1D */ + + case HUFF_2D: + + switch (cdg_scheme & PAIR_MASK) { + case FREQ_PAIR: + + if (in_data_1 != NULL) { + if (diff_type_1 == DIFF_FREQ) { + p0_data_1[0] = &in_data_1[0]; + p0_data_1[1] = NULL; + + num_val_1_short -= 1; + in_data_1_short += 1; + } + + df_rest_flag[0] = num_val_1_short % 2; + + if (df_rest_flag[0]) num_val_1_short -= 1; + + for (i = 0; i < num_val_1_short - 1; i += 2) { + pair_vec[i][0] = in_data_1_short[i]; + pair_vec[i][1] = in_data_1_short[i + 1]; + } + + tab_idx_2D[0][0] = (diff_type_1 == DIFF_TIME) ? 1 : 0; + tab_idx_2D[0][1] = 0; + + tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; + } /* if( in_data_1 != NULL ) */ + + if (in_data_2 != NULL) { + if (diff_type_2 == DIFF_FREQ) { + p0_data_2[0] = NULL; + p0_data_2[1] = &in_data_2[0]; + + num_val_2_short -= 1; + in_data_2_short += 1; + } + + df_rest_flag[1] = num_val_2_short % 2; + + if (df_rest_flag[1]) num_val_2_short -= 1; + + for (i = 0; i < num_val_2_short - 1; i += 2) { + pair_vec[i + 1][0] = in_data_2_short[i]; + pair_vec[i + 1][1] = in_data_2_short[i + 1]; + } + + tab_idx_2D[1][0] = (diff_type_2 == DIFF_TIME) ? 1 : 0; + tab_idx_2D[1][1] = 0; + + tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; + } /* if( in_data_2 != NULL ) */ + + if (in_data_1 != NULL) { + FDKwriteBits(strm, lavHuffVal[lav_idx[0]], lavHuffLen[lav_idx[0]]); + huff_enc_2D(strm, data_type, tab_idx_2D[0], lav_idx[0], pair_vec, + num_val_1_short, 2, p0_data_1); + if (df_rest_flag[0]) { + huff_enc_1D(strm, data_type, tab_idx_1D[0], + in_data_1_short + num_val_1_short, 1, 0); + } + } + if (in_data_2 != NULL) { + FDKwriteBits(strm, lavHuffVal[lav_idx[1]], lavHuffLen[lav_idx[1]]); + huff_enc_2D(strm, data_type, tab_idx_2D[1], lav_idx[1], + pair_vec + 1, num_val_2_short, 2, p0_data_2); + if (df_rest_flag[1]) { + huff_enc_1D(strm, data_type, tab_idx_1D[1], + in_data_2_short + num_val_2_short, 1, 0); + } + } + break; /* FREQ_PAIR */ + + case TIME_PAIR: + + if ((diff_type_1 == DIFF_FREQ) || (diff_type_2 == DIFF_FREQ)) { + p0_data_1[0] = &in_data_1[0]; + p0_data_1[1] = &in_data_2[0]; + + in_data_1_short += 1; + in_data_2_short += 1; + + num_val_1_short -= 1; + } + + for (i = 0; i < num_val_1_short; i++) { + pair_vec[i][0] = in_data_1_short[i]; + pair_vec[i][1] = in_data_2_short[i]; + } + + tab_idx_2D[0][0] = + ((diff_type_1 == DIFF_TIME) || (diff_type_2 == DIFF_TIME)) ? 1 + : 0; + tab_idx_2D[0][1] = 1; + + FDKwriteBits(strm, lavHuffVal[lav_idx[0]], lavHuffLen[lav_idx[0]]); + + huff_enc_2D(strm, data_type, tab_idx_2D[0], lav_idx[0], pair_vec, + num_val_1_short, 1, p0_data_1); + + break; /* TIME_PAIR */ + } /* switch( cdg_scheme & PAIR_MASK ) */ + + break; /* HUFF_2D */ + + default: + break; + } /* switch( cdg_scheme >> PAIR_SHIFT ) */ +} + +INT fdk_sacenc_ecDataPairEnc(HANDLE_FDK_BITSTREAM strm, + SHORT aaInData[][MAXBANDS], + SHORT aHistory[MAXBANDS], + const DATA_TYPE data_type, const INT setIdx, + const INT startBand, const INT dataBands, + const INT coarse_flag, + const INT independency_flag) { + SHORT reset = 0, pb = 0; + SHORT quant_levels = 0, quant_offset = 0, num_pcm_val = 0; + + SHORT splitLsb_flag = 0; + SHORT pcmCoding_flag = 0; + + SHORT allowDiffTimeBack_flag = !independency_flag || (setIdx > 0); + + SHORT num_lsb_bits = -1; + SHORT num_pcm_bits = -1; + + SHORT quant_data_lsb[2][MAXBANDS]; + SHORT quant_data_msb[2][MAXBANDS]; + + SHORT quant_data_hist_lsb[MAXBANDS]; + SHORT quant_data_hist_msb[MAXBANDS]; + + SHORT data_diff_freq[2][MAXBANDS]; + SHORT data_diff_time[2][MAXBANDS + 2]; + + SHORT *p_quant_data_msb[2]; + SHORT *p_quant_data_hist_msb = NULL; + + SHORT min_bits_all = 0; + SHORT min_found = 0; + + SHORT min_bits_df_df = -1; + SHORT min_bits_df_dt = -1; + SHORT min_bits_dtbw_df = -1; + SHORT min_bits_dt_dt = -1; + + SHORT lav_df_df[2] = {-1, -1}; + SHORT lav_df_dt[2] = {-1, -1}; + SHORT lav_dtbw_df[2] = {-1, -1}; + SHORT lav_dt_dt[2] = {-1, -1}; + + SHORT coding_scheme_df_df = 0; + SHORT coding_scheme_df_dt = 0; + SHORT coding_scheme_dtbw_df = 0; + SHORT coding_scheme_dt_dt = 0; + + switch (data_type) { + case t_CLD: + if (coarse_flag) { + splitLsb_flag = 0; + quant_levels = 15; + quant_offset = 7; + } else { + splitLsb_flag = 0; + quant_levels = 31; + quant_offset = 15; + } + break; + case t_ICC: + if (coarse_flag) { + splitLsb_flag = 0; + quant_levels = 4; + quant_offset = 0; + } else { + splitLsb_flag = 0; + quant_levels = 8; + quant_offset = 0; + } + break; + } /* switch( data_type ) */ + + /* Split off LSB */ + if (splitLsb_flag) { + split_lsb(aaInData[setIdx] + startBand, quant_offset, dataBands, + quant_data_lsb[0], quant_data_msb[0]); + + split_lsb(aaInData[setIdx + 1] + startBand, quant_offset, dataBands, + quant_data_lsb[1], quant_data_msb[1]); + + p_quant_data_msb[0] = quant_data_msb[0]; + p_quant_data_msb[1] = quant_data_msb[1]; + + num_lsb_bits = 2 * dataBands; + } else if (quant_offset != 0) { + for (pb = 0; pb < dataBands; pb++) { + quant_data_msb[0][pb] = aaInData[setIdx][startBand + pb] + quant_offset; + quant_data_msb[1][pb] = + aaInData[setIdx + 1][startBand + pb] + quant_offset; + } + + p_quant_data_msb[0] = quant_data_msb[0]; + p_quant_data_msb[1] = quant_data_msb[1]; + + num_lsb_bits = 0; + } else { + p_quant_data_msb[0] = aaInData[setIdx] + startBand; + p_quant_data_msb[1] = aaInData[setIdx + 1] + startBand; + + num_lsb_bits = 0; + } + + if (allowDiffTimeBack_flag) { + if (splitLsb_flag) { + split_lsb(aHistory + startBand, quant_offset, dataBands, + quant_data_hist_lsb, quant_data_hist_msb); + + p_quant_data_hist_msb = quant_data_hist_msb; + } else if (quant_offset != 0) { + for (pb = 0; pb < dataBands; pb++) { + quant_data_hist_msb[pb] = aHistory[startBand + pb] + quant_offset; + } + p_quant_data_hist_msb = quant_data_hist_msb; + } else { + p_quant_data_hist_msb = aHistory + startBand; + } + } + + /* Calculate frequency differences */ + calc_diff_freq(p_quant_data_msb[0], data_diff_freq[0], dataBands); + + calc_diff_freq(p_quant_data_msb[1], data_diff_freq[1], dataBands); + + /* Calculate time differences */ + if (allowDiffTimeBack_flag) { + calc_diff_time(p_quant_data_msb[0], p_quant_data_hist_msb, + data_diff_time[0], dataBands); + } + + calc_diff_time(p_quant_data_msb[1], p_quant_data_msb[0], data_diff_time[1], + dataBands); + + /* Calculate coding scheme with minumum bit consumption */ + + /**********************************************************/ + num_pcm_bits = calc_pcm_bits(2 * dataBands, quant_levels); + num_pcm_val = 2 * dataBands; + + /**********************************************************/ + + min_bits_all = num_pcm_bits; + + /**********************************************************/ + /**********************************************************/ + + /**********************************************************/ + min_bits_df_df = + calc_huff_bits(data_diff_freq[0], data_diff_freq[1], data_type, DIFF_FREQ, + DIFF_FREQ, dataBands, lav_df_df, &coding_scheme_df_df); + + min_bits_df_df += 2; + + min_bits_df_df += num_lsb_bits; + + if (min_bits_df_df < min_bits_all) { + min_bits_all = min_bits_df_df; + } + /**********************************************************/ + + /**********************************************************/ + min_bits_df_dt = + calc_huff_bits(data_diff_freq[0], data_diff_time[1], data_type, DIFF_FREQ, + DIFF_TIME, dataBands, lav_df_dt, &coding_scheme_df_dt); + + min_bits_df_dt += 2; + + min_bits_df_dt += num_lsb_bits; + + if (min_bits_df_dt < min_bits_all) { + min_bits_all = min_bits_df_dt; + } + /**********************************************************/ + + /**********************************************************/ + /**********************************************************/ + + if (allowDiffTimeBack_flag) { + /**********************************************************/ + min_bits_dtbw_df = calc_huff_bits( + data_diff_time[0], data_diff_freq[1], data_type, DIFF_TIME, DIFF_FREQ, + dataBands, lav_dtbw_df, &coding_scheme_dtbw_df); + + min_bits_dtbw_df += 2; + + min_bits_dtbw_df += num_lsb_bits; + + if (min_bits_dtbw_df < min_bits_all) { + min_bits_all = min_bits_dtbw_df; + } + /**********************************************************/ + + /**********************************************************/ + min_bits_dt_dt = calc_huff_bits(data_diff_time[0], data_diff_time[1], + data_type, DIFF_TIME, DIFF_TIME, dataBands, + lav_dt_dt, &coding_scheme_dt_dt); + + min_bits_dt_dt += 2; + + min_bits_dt_dt += num_lsb_bits; + + if (min_bits_dt_dt < min_bits_all) { + min_bits_all = min_bits_dt_dt; + } + /**********************************************************/ + + } /* if( allowDiffTimeBack_flag ) */ + + /***************************/ + /* Start actual coding now */ + /***************************/ + + /* PCM or Diff/Huff Coding? */ + pcmCoding_flag = (min_bits_all == num_pcm_bits); + + FDKwriteBits(strm, pcmCoding_flag, 1); + + if (pcmCoding_flag) { + /* Grouped PCM Coding */ + apply_pcm_coding(strm, aaInData[setIdx] + startBand, + aaInData[setIdx + 1] + startBand, quant_offset, + num_pcm_val, quant_levels); + } else { + /* Diff/Huff Coding */ + + min_found = 0; + + /*******************************************/ + if (min_bits_all == min_bits_df_df) { + FDKwriteBits(strm, DIFF_FREQ, 1); + FDKwriteBits(strm, DIFF_FREQ, 1); + + apply_huff_coding(strm, data_diff_freq[0], data_diff_freq[1], data_type, + DIFF_FREQ, DIFF_FREQ, dataBands, lav_df_df, + coding_scheme_df_df); + + min_found = 1; + } + /*******************************************/ + + /*******************************************/ + if (!min_found && (min_bits_all == min_bits_df_dt)) { + FDKwriteBits(strm, DIFF_FREQ, 1); + FDKwriteBits(strm, DIFF_TIME, 1); + + apply_huff_coding(strm, data_diff_freq[0], data_diff_time[1], data_type, + DIFF_FREQ, DIFF_TIME, dataBands, lav_df_dt, + coding_scheme_df_dt); + + min_found = 1; + } + /*******************************************/ + + /*******************************************/ + /*******************************************/ + + if (allowDiffTimeBack_flag) { + /*******************************************/ + if (!min_found && (min_bits_all == min_bits_dtbw_df)) { + FDKwriteBits(strm, DIFF_TIME, 1); + FDKwriteBits(strm, DIFF_FREQ, 1); + + apply_huff_coding(strm, data_diff_time[0], data_diff_freq[1], data_type, + DIFF_TIME, DIFF_FREQ, dataBands, lav_dtbw_df, + coding_scheme_dtbw_df); + + min_found = 1; + } + /*******************************************/ + + /*******************************************/ + if (!min_found && (min_bits_all == min_bits_dt_dt)) { + FDKwriteBits(strm, DIFF_TIME, 1); + FDKwriteBits(strm, DIFF_TIME, 1); + + apply_huff_coding(strm, data_diff_time[0], data_diff_time[1], data_type, + DIFF_TIME, DIFF_TIME, dataBands, lav_dt_dt, + coding_scheme_dt_dt); + } + /*******************************************/ + + } /* if( allowDiffTimeBack_flag ) */ + + /* LSB coding */ + if (splitLsb_flag) { + apply_lsb_coding(strm, quant_data_lsb[0], 1, dataBands); + + apply_lsb_coding(strm, quant_data_lsb[1], 1, dataBands); + } + + } /* Diff/Huff/LSB coding */ + + return reset; +} + +INT fdk_sacenc_ecDataSingleEnc(HANDLE_FDK_BITSTREAM strm, + SHORT aaInData[][MAXBANDS], + SHORT aHistory[MAXBANDS], + const DATA_TYPE data_type, const INT setIdx, + const INT startBand, const INT dataBands, + const INT coarse_flag, + const INT independency_flag) { + SHORT reset = 0, pb = 0; + SHORT quant_levels = 0, quant_offset = 0, num_pcm_val = 0; + + SHORT splitLsb_flag = 0; + SHORT pcmCoding_flag = 0; + + SHORT allowDiffTimeBack_flag = !independency_flag || (setIdx > 0); + + SHORT num_lsb_bits = -1; + SHORT num_pcm_bits = -1; + + SHORT quant_data_lsb[MAXBANDS]; + SHORT quant_data_msb[MAXBANDS]; + + SHORT quant_data_hist_lsb[MAXBANDS]; + SHORT quant_data_hist_msb[MAXBANDS]; + + SHORT data_diff_freq[MAXBANDS]; + SHORT data_diff_time[MAXBANDS + 2]; + + SHORT *p_quant_data_msb; + SHORT *p_quant_data_hist_msb = NULL; + + SHORT min_bits_all = 0; + SHORT min_found = 0; + + SHORT min_bits_df = -1; + SHORT min_bits_dt = -1; + + SHORT lav_df[2] = {-1, -1}; + SHORT lav_dt[2] = {-1, -1}; + + SHORT coding_scheme_df = 0; + SHORT coding_scheme_dt = 0; + + switch (data_type) { + case t_CLD: + if (coarse_flag) { + splitLsb_flag = 0; + quant_levels = 15; + quant_offset = 7; + } else { + splitLsb_flag = 0; + quant_levels = 31; + quant_offset = 15; + } + break; + case t_ICC: + if (coarse_flag) { + splitLsb_flag = 0; + quant_levels = 4; + quant_offset = 0; + } else { + splitLsb_flag = 0; + quant_levels = 8; + quant_offset = 0; + } + break; + } /* switch( data_type ) */ + + /* Split off LSB */ + if (splitLsb_flag) { + split_lsb(aaInData[setIdx] + startBand, quant_offset, dataBands, + quant_data_lsb, quant_data_msb); + + p_quant_data_msb = quant_data_msb; + num_lsb_bits = dataBands; + } else if (quant_offset != 0) { + for (pb = 0; pb < dataBands; pb++) { + quant_data_msb[pb] = aaInData[setIdx][startBand + pb] + quant_offset; + } + + p_quant_data_msb = quant_data_msb; + num_lsb_bits = 0; + } else { + p_quant_data_msb = aaInData[setIdx] + startBand; + num_lsb_bits = 0; + } + + if (allowDiffTimeBack_flag) { + if (splitLsb_flag) { + split_lsb(aHistory + startBand, quant_offset, dataBands, + quant_data_hist_lsb, quant_data_hist_msb); + + p_quant_data_hist_msb = quant_data_hist_msb; + } else if (quant_offset != 0) { + for (pb = 0; pb < dataBands; pb++) { + quant_data_hist_msb[pb] = aHistory[startBand + pb] + quant_offset; + } + p_quant_data_hist_msb = quant_data_hist_msb; + } else { + p_quant_data_hist_msb = aHistory + startBand; + } + } + + /* Calculate frequency differences */ + calc_diff_freq(p_quant_data_msb, data_diff_freq, dataBands); + + /* Calculate time differences */ + if (allowDiffTimeBack_flag) { + calc_diff_time(p_quant_data_msb, p_quant_data_hist_msb, data_diff_time, + dataBands); + } + + /* Calculate coding scheme with minumum bit consumption */ + + /**********************************************************/ + num_pcm_bits = calc_pcm_bits(dataBands, quant_levels); + num_pcm_val = dataBands; + + /**********************************************************/ + + min_bits_all = num_pcm_bits; + + /**********************************************************/ + /**********************************************************/ + + /**********************************************************/ + min_bits_df = calc_huff_bits(data_diff_freq, NULL, data_type, DIFF_FREQ, + DIFF_FREQ, dataBands, lav_df, &coding_scheme_df); + + if (allowDiffTimeBack_flag) min_bits_df += 1; + + min_bits_df += num_lsb_bits; + + if (min_bits_df < min_bits_all) { + min_bits_all = min_bits_df; + } + /**********************************************************/ + + /**********************************************************/ + if (allowDiffTimeBack_flag) { + min_bits_dt = + calc_huff_bits(data_diff_time, NULL, data_type, DIFF_TIME, DIFF_TIME, + dataBands, lav_dt, &coding_scheme_dt); + + min_bits_dt += 1; + min_bits_dt += num_lsb_bits; + + if (min_bits_dt < min_bits_all) { + min_bits_all = min_bits_dt; + } + } /* if( allowDiffTimeBack_flag ) */ + + /***************************/ + /* Start actual coding now */ + /***************************/ + + /* PCM or Diff/Huff Coding? */ + pcmCoding_flag = (min_bits_all == num_pcm_bits); + + FDKwriteBits(strm, pcmCoding_flag, 1); + + if (pcmCoding_flag) { + /* Grouped PCM Coding */ + apply_pcm_coding(strm, aaInData[setIdx] + startBand, NULL, quant_offset, + num_pcm_val, quant_levels); + } else { + /* Diff/Huff Coding */ + + min_found = 0; + + /*******************************************/ + if (min_bits_all == min_bits_df) { + if (allowDiffTimeBack_flag) { + FDKwriteBits(strm, DIFF_FREQ, 1); + } + + apply_huff_coding(strm, data_diff_freq, NULL, data_type, DIFF_FREQ, + DIFF_FREQ, dataBands, lav_df, coding_scheme_df); + + min_found = 1; + } /* if( min_bits_all == min_bits_df ) */ + /*******************************************/ + + /*******************************************/ + if (allowDiffTimeBack_flag) { + /*******************************************/ + if (!min_found && (min_bits_all == min_bits_dt)) { + FDKwriteBits(strm, DIFF_TIME, 1); + + apply_huff_coding(strm, data_diff_time, NULL, data_type, DIFF_TIME, + DIFF_TIME, dataBands, lav_dt, coding_scheme_dt); + } + /*******************************************/ + + } /* if( allowDiffTimeBack_flag ) */ + + /* LSB coding */ + if (splitLsb_flag) { + apply_lsb_coding(strm, quant_data_lsb, 1, dataBands); + } + + } /* Diff/Huff/LSB coding */ + + return reset; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_nlc_enc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_nlc_enc.h new file mode 100644 index 0000000000000..506b30839e22f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_nlc_enc.h @@ -0,0 +1,141 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Karsten Linzmeier + + Description: Noiseless Coding + Huffman encoder + +*******************************************************************************/ + +#ifndef SACENC_NLC_ENC_H +#define SACENC_NLC_ENC_H + +/* Includes ******************************************************************/ +#include "sacenc_const.h" +#include "FDK_bitstream.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ +#define MAXBANDS MAX_NUM_BINS /* maximum number of frequency bands */ + +/* Data Types ****************************************************************/ +typedef enum { + t_CLD, + t_ICC + +} DATA_TYPE; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +INT fdk_sacenc_ecDataPairEnc(HANDLE_FDK_BITSTREAM strm, + SHORT aaInData[][MAXBANDS], + SHORT aHistory[MAXBANDS], + const DATA_TYPE data_type, const INT setIdx, + const INT startBand, const INT dataBands, + const INT coarse_flag, + const INT independency_flag); + +INT fdk_sacenc_ecDataSingleEnc(HANDLE_FDK_BITSTREAM strm, + SHORT aaInData[][MAXBANDS], + SHORT aHistory[MAXBANDS], + const DATA_TYPE data_type, const INT setIdx, + const INT startBand, const INT dataBands, + const INT coarse_flag, + const INT independency_flag); + +#endif /* SACENC_NLC_ENC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_onsetdetect.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_onsetdetect.cpp new file mode 100644 index 0000000000000..7e9aee174d7f3 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_onsetdetect.cpp @@ -0,0 +1,381 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Detect Onset in current frame + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + Description of file contents + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_onsetdetect.h" +#include "genericStds.h" +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ +#define SPACE_ONSET_THRESHOLD (3.0) +#define SPACE_ONSET_THRESHOLD_SF (3) +#define SPACE_ONSET_THRESHOLD_SQUARE \ + (FL2FXCONST_DBL((1.0 / (SPACE_ONSET_THRESHOLD * SPACE_ONSET_THRESHOLD)) * \ + (float)(1 << SPACE_ONSET_THRESHOLD_SF))) + +/* Data Types ****************************************************************/ +struct ONSET_DETECT { + INT maxTimeSlots; + INT minTransientDistance; + INT avgEnergyDistance; + INT lowerBoundOnsetDetection; + INT upperBoundOnsetDetection; + FIXP_DBL *pEnergyHist__FDK; + SCHAR *pEnergyHistScale; + SCHAR avgEnergyDistanceScale; +}; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Open(HANDLE_ONSET_DETECT *phOnset, + const UINT maxTimeSlots) { + FDK_SACENC_ERROR error = SACENC_OK; + HANDLE_ONSET_DETECT hOnset = NULL; + + if (NULL == phOnset) { + error = SACENC_INVALID_HANDLE; + } else { + /* Memory Allocation */ + FDK_ALLOCATE_MEMORY_1D(hOnset, 1, struct ONSET_DETECT); + FDK_ALLOCATE_MEMORY_1D(hOnset->pEnergyHist__FDK, 16 + maxTimeSlots, + FIXP_DBL); + FDK_ALLOCATE_MEMORY_1D(hOnset->pEnergyHistScale, 16 + maxTimeSlots, SCHAR); + + hOnset->maxTimeSlots = maxTimeSlots; + hOnset->minTransientDistance = + 8; /* minimum distance between detected transients */ + hOnset->avgEnergyDistance = 16; /* average energy distance */ + + hOnset->avgEnergyDistanceScale = 4; + *phOnset = hOnset; + } + return error; + +bail: + fdk_sacenc_onsetDetect_Close(&hOnset); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Init( + HANDLE_ONSET_DETECT hOnset, + const ONSET_DETECT_CONFIG *const pOnsetDetectConfig, const UINT initFlags) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hOnset) || (pOnsetDetectConfig == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + if ((pOnsetDetectConfig->maxTimeSlots > hOnset->maxTimeSlots) || + (pOnsetDetectConfig->upperBoundOnsetDetection < + hOnset->lowerBoundOnsetDetection)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + hOnset->maxTimeSlots = pOnsetDetectConfig->maxTimeSlots; + hOnset->lowerBoundOnsetDetection = + pOnsetDetectConfig->lowerBoundOnsetDetection; + hOnset->upperBoundOnsetDetection = + pOnsetDetectConfig->upperBoundOnsetDetection; + + hOnset->minTransientDistance = + 8; /* minimum distance between detected transients */ + hOnset->avgEnergyDistance = 16; /* average energy distance */ + + hOnset->avgEnergyDistanceScale = 4; + + /* Init / Reset */ + if (initFlags) { + int i; + for (i = 0; i < hOnset->avgEnergyDistance + hOnset->maxTimeSlots; i++) + hOnset->pEnergyHistScale[i] = -(DFRACT_BITS - 3); + + FDKmemset_flex( + hOnset->pEnergyHist__FDK, + FL2FXCONST_DBL(SACENC_FLOAT_EPSILON * (1 << (DFRACT_BITS - 3))), + hOnset->avgEnergyDistance + hOnset->maxTimeSlots); + } + } + +bail: + return error; +} + +/**************************************************************************/ + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Close(HANDLE_ONSET_DETECT *phOnset) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL != phOnset) && (NULL != *phOnset)) { + if (NULL != (*phOnset)->pEnergyHist__FDK) { + FDKfree((*phOnset)->pEnergyHist__FDK); + } + (*phOnset)->pEnergyHist__FDK = NULL; + + if (NULL != (*phOnset)->pEnergyHistScale) { + FDKfree((*phOnset)->pEnergyHistScale); + } + (*phOnset)->pEnergyHistScale = NULL; + FDKfree(*phOnset); + *phOnset = NULL; + } + return error; +} + +/**************************************************************************/ + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Update(HANDLE_ONSET_DETECT hOnset, + const INT timeSlots) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hOnset) { + error = SACENC_INVALID_HANDLE; + } else { + if (timeSlots > hOnset->maxTimeSlots) { + error = SACENC_INVALID_CONFIG; + } else { + int i; + /* Shift old data */ + for (i = 0; i < hOnset->avgEnergyDistance; i++) { + hOnset->pEnergyHist__FDK[i] = hOnset->pEnergyHist__FDK[i + timeSlots]; + hOnset->pEnergyHistScale[i] = hOnset->pEnergyHistScale[i + timeSlots]; + } + + /* Clear for new data */ + FDKmemset_flex(&hOnset->pEnergyHist__FDK[hOnset->avgEnergyDistance], + FL2FXCONST_DBL(SACENC_FLOAT_EPSILON), timeSlots); + } + } + return error; +} + +/**************************************************************************/ + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Apply( + HANDLE_ONSET_DETECT hOnset, const INT nTimeSlots, const INT nHybridBands, + FIXP_DPK *const *const ppHybridData__FDK, const INT hybridDataScale, + const INT prevPos, INT pTransientPos[MAX_NUM_TRANS]) { + FDK_SACENC_ERROR error = SACENC_OK; + + C_ALLOC_SCRATCH_START(envs, FIXP_DBL, (16 + MAX_TIME_SLOTS)) + FDKmemclear(envs, (16 + MAX_TIME_SLOTS) * sizeof(FIXP_DBL)); + + if ((hOnset == NULL) || (pTransientPos == NULL) || + (ppHybridData__FDK == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int i, ts, trCnt, currPos; + + if ((nTimeSlots < 0) || (nTimeSlots > hOnset->maxTimeSlots) || + (hOnset->lowerBoundOnsetDetection < -1) || + (hOnset->upperBoundOnsetDetection > nHybridBands)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + const int lowerBoundOnsetDetection = hOnset->lowerBoundOnsetDetection; + const int upperBoundOnsetDetection = hOnset->upperBoundOnsetDetection; + const int M = hOnset->avgEnergyDistance; + + { + SCHAR *envScale = hOnset->pEnergyHistScale; + FIXP_DBL *env = hOnset->pEnergyHist__FDK; + const FIXP_DBL threshold_square = SPACE_ONSET_THRESHOLD_SQUARE; + + trCnt = 0; + + /* reset transient array */ + FDKmemset_flex(pTransientPos, -1, MAX_NUM_TRANS); + + /* minimum transient distance of minTransDist QMF samples */ + if (prevPos > 0) { + currPos = FDKmax(nTimeSlots, + prevPos - nTimeSlots + hOnset->minTransientDistance); + } else { + currPos = nTimeSlots; + } + + /* get energy and scalefactor for each time slot */ + int outScale; + int inScale = 3; /* scale factor determined empirically */ + for (ts = 0; ts < nTimeSlots; ts++) { + env[M + ts] = sumUpCplxPow2( + &ppHybridData__FDK[ts][lowerBoundOnsetDetection + 1], + SUM_UP_DYNAMIC_SCALE, inScale, &outScale, + upperBoundOnsetDetection - lowerBoundOnsetDetection - 1); + envScale[M + ts] = outScale + (hybridDataScale << 1); + } + + /* calculate common scale for all time slots */ + SCHAR maxScale = -(DFRACT_BITS - 1); + for (i = 0; i < (nTimeSlots + M); i++) { + maxScale = fixMax(maxScale, envScale[i]); + } + + /* apply common scale and store energy in temporary buffer */ + for (i = 0; i < (nTimeSlots + M); i++) { + envs[i] = env[i] >> fixMin((maxScale - envScale[i]), (DFRACT_BITS - 1)); + } + + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + for (i = 0; i < (nTimeSlots + M); i++) { + maxVal |= fAbs(envs[i]); + } + + int s = fixMax(0, CntLeadingZeros(maxVal) - 1); + + for (i = 0; i < (nTimeSlots + M); i++) { + envs[i] = envs[i] << s; + } + + int currPosPrev = currPos; + FIXP_DBL p1, p2; + p2 = FL2FXCONST_DBL(0.0f); + for (; (currPos < (nTimeSlots << 1)) && (trCnt < MAX_NUM_TRANS); + currPos++) { + p1 = fMultDiv2(envs[currPos - nTimeSlots + M], threshold_square) >> + (SPACE_ONSET_THRESHOLD_SF - 1); + + /* Calculate average of past M energy values */ + if (currPosPrev == (currPos - 1)) { + /* remove last and add new element */ + p2 -= (envs[currPosPrev - nTimeSlots] >> + (int)hOnset->avgEnergyDistanceScale); + p2 += (envs[currPos - nTimeSlots + M - 1] >> + (int)hOnset->avgEnergyDistanceScale); + } else { + /* calculate complete vector */ + p2 = FL2FXCONST_DBL(0.0f); + for (ts = 0; ts < M; ts++) { + p2 += (envs[currPos - nTimeSlots + ts] >> + (int)hOnset->avgEnergyDistanceScale); + } + } + currPosPrev = currPos; + + { + /* save position if transient found */ + if (p1 > p2) { + pTransientPos[trCnt++] = currPos; + currPos += hOnset->minTransientDistance; + } + } + } /* for currPos */ + } + + } /* valid handle*/ +bail: + + C_ALLOC_SCRATCH_END(envs, FIXP_DBL, (16 + MAX_TIME_SLOTS)) + + return error; +} + +/**************************************************************************/ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_onsetdetect.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_onsetdetect.h new file mode 100644 index 0000000000000..5f3f0bd10340d --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_onsetdetect.h @@ -0,0 +1,154 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Determine TES flags + +*******************************************************************************/ + +#ifndef SACENC_ONSETDETECT_H +#define SACENC_ONSETDETECT_H + +/**************************************************************************/ /** + \file + Description of file contents + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "common_fix.h" +#include "FDK_matrixCalloc.h" +#include "sacenc_lib.h" +#include "sacenc_bitstream.h" /* for def. of MAX_NUM_PARAMS */ + +/* Defines *******************************************************************/ +#define MAX_NUM_TRANS (MAX_NUM_PARAMS / 2) + +/* Data Types ****************************************************************/ +typedef struct T_ONSET_DETECT_CONFIG { + INT maxTimeSlots; + + /* calc transien detection in ]lowerBoundOnsetDetection; + * upperBoundOnsetDetection[ */ + INT lowerBoundOnsetDetection; + INT upperBoundOnsetDetection; + +} ONSET_DETECT_CONFIG; + +typedef struct ONSET_DETECT *HANDLE_ONSET_DETECT; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Open(HANDLE_ONSET_DETECT *phOnset, + const UINT maxTimeSlots); + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Init( + HANDLE_ONSET_DETECT hOnset, + const ONSET_DETECT_CONFIG *const pOnsetDetectConfig, const UINT initFlags); + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Close(HANDLE_ONSET_DETECT *phOnset); + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Update(HANDLE_ONSET_DETECT hOnset, + const INT timeSlots); + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Apply( + HANDLE_ONSET_DETECT hOnset, const INT nTimeSlots, const INT nHybridBands, + FIXP_DPK *const *const ppHybridData__FDK, const INT hybridDataScale, + const INT prevPos, INT pTransientPos[MAX_NUM_TRANS]); + +#endif /* SACENC_ONSETDETECT_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_paramextract.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_paramextract.cpp new file mode 100644 index 0000000000000..dcbce1e0e05fc --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_paramextract.cpp @@ -0,0 +1,725 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Parameter Extraction + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_paramextract.h" +#include "sacenc_tree.h" +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ +#define LOG10_2_10 (3.01029995664f) /* 10.0f*log10(2.f) */ +#define SCALE_CLDE_SF (7) /* maxVal in Quant tab is +/- 50 */ +#define SCALE_CLDD_SF (8) /* maxVal in Quant tab is +/- 150 */ + +/* Data Types ****************************************************************/ +typedef struct T_TTO_BOX { + FIXP_DBL pCld__FDK[MAX_NUM_PARAM_BANDS]; + FIXP_DBL pIcc__FDK[MAX_NUM_PARAM_BANDS]; + FIXP_DBL pCldQuant__FDK[MAX_NUM_PARAM_BANDS]; + + const FIXP_DBL *pIccQuantTable__FDK; + const FIXP_DBL *pCldQuantTableDec__FDK; + const FIXP_DBL *pCldQuantTableEnc__FDK; + + SCHAR pCldEbQIdx[MAX_NUM_PARAM_BANDS]; + SCHAR pIccDownmixIdx[MAX_NUM_PARAM_BANDS]; + + UCHAR *pParameterBand2HybridBandOffset; + const INT *pSubbandImagSign; + UCHAR nHybridBandsMax; + UCHAR nParameterBands; + UCHAR bFrameKeep; + + UCHAR iccCorrelationCoherenceBorder; + BOX_QUANTMODE boxQuantMode; + + UCHAR nIccQuantSteps; + UCHAR nIccQuantOffset; + + UCHAR nCldQuantSteps; + UCHAR nCldQuantOffset; + + UCHAR bUseCoarseQuantCld; + UCHAR bUseCoarseQuantIcc; + +} TTO_BOX; + +struct BOX_SUBBAND_SETUP { + BOX_SUBBAND_CONFIG subbandConfig; + UCHAR nParameterBands; + const UCHAR *pSubband2ParameterIndexLd; + UCHAR iccCorrelationCoherenceBorder; +}; + +/* Constants *****************************************************************/ +static const UCHAR subband2Parameter4_Ld[NUM_QMF_BANDS] = { + 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; + +static const UCHAR subband2Parameter5_Ld[NUM_QMF_BANDS] = { + 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; + +static const UCHAR subband2Parameter7_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}; + +static const UCHAR subband2Parameter9_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; + +static const UCHAR subband2Parameter12_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}; + +static const UCHAR subband2Parameter15_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 10, 11, 11, + 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + +static const UCHAR subband2Parameter23_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, + 14, 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19, + 19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}; + +static const INT subbandImagSign_Ld[NUM_QMF_BANDS] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; + +#define SCALE_CLDE(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDE_SF))) +static const FIXP_DBL cldQuantTableFineEnc__FDK[MAX_CLD_QUANT_FINE] = { + SCALE_CLDE(-50.0), SCALE_CLDE(-45.0), SCALE_CLDE(-40.0), SCALE_CLDE(-35.0), + SCALE_CLDE(-30.0), SCALE_CLDE(-25.0), SCALE_CLDE(-22.0), SCALE_CLDE(-19.0), + SCALE_CLDE(-16.0), SCALE_CLDE(-13.0), SCALE_CLDE(-10.0), SCALE_CLDE(-8.0), + SCALE_CLDE(-6.0), SCALE_CLDE(-4.0), SCALE_CLDE(-2.0), SCALE_CLDE(0.0), + SCALE_CLDE(2.0), SCALE_CLDE(4.0), SCALE_CLDE(6.0), SCALE_CLDE(8.0), + SCALE_CLDE(10.0), SCALE_CLDE(13.0), SCALE_CLDE(16.0), SCALE_CLDE(19.0), + SCALE_CLDE(22.0), SCALE_CLDE(25.0), SCALE_CLDE(30.0), SCALE_CLDE(35.0), + SCALE_CLDE(40.0), SCALE_CLDE(45.0), SCALE_CLDE(50.0)}; + +static const FIXP_DBL cldQuantTableCoarseEnc__FDK[MAX_CLD_QUANT_COARSE] = { + SCALE_CLDE(-50.0), SCALE_CLDE(-35.0), SCALE_CLDE(-25.0), SCALE_CLDE(-19.0), + SCALE_CLDE(-13.0), SCALE_CLDE(-8.0), SCALE_CLDE(-4.0), SCALE_CLDE(0.0), + SCALE_CLDE(4.0), SCALE_CLDE(8.0), SCALE_CLDE(13.0), SCALE_CLDE(19.0), + SCALE_CLDE(25.0), SCALE_CLDE(35.0), SCALE_CLDE(50.0)}; + +#define SCALE_CLDD(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDD_SF))) +static const FIXP_DBL cldQuantTableFineDec__FDK[MAX_CLD_QUANT_FINE] = { + SCALE_CLDD(-150.0), SCALE_CLDD(-45.0), SCALE_CLDD(-40.0), SCALE_CLDD(-35.0), + SCALE_CLDD(-30.0), SCALE_CLDD(-25.0), SCALE_CLDD(-22.0), SCALE_CLDD(-19.0), + SCALE_CLDD(-16.0), SCALE_CLDD(-13.0), SCALE_CLDD(-10.0), SCALE_CLDD(-8.0), + SCALE_CLDD(-6.0), SCALE_CLDD(-4.0), SCALE_CLDD(-2.0), SCALE_CLDD(0.0), + SCALE_CLDD(2.0), SCALE_CLDD(4.0), SCALE_CLDD(6.0), SCALE_CLDD(8.0), + SCALE_CLDD(10.0), SCALE_CLDD(13.0), SCALE_CLDD(16.0), SCALE_CLDD(19.0), + SCALE_CLDD(22.0), SCALE_CLDD(25.0), SCALE_CLDD(30.0), SCALE_CLDD(35.0), + SCALE_CLDD(40.0), SCALE_CLDD(45.0), SCALE_CLDD(150.0)}; + +static const FIXP_DBL cldQuantTableCoarseDec__FDK[MAX_CLD_QUANT_COARSE] = { + SCALE_CLDD(-150.0), SCALE_CLDD(-35.0), SCALE_CLDD(-25.0), SCALE_CLDD(-19.0), + SCALE_CLDD(-13.0), SCALE_CLDD(-8.0), SCALE_CLDD(-4.0), SCALE_CLDD(0.0), + SCALE_CLDD(4.0), SCALE_CLDD(8.0), SCALE_CLDD(13.0), SCALE_CLDD(19.0), + SCALE_CLDD(25.0), SCALE_CLDD(35.0), SCALE_CLDD(150.0)}; + +#define SCALE_ICC(a) (FL2FXCONST_DBL(a)) +static const FIXP_DBL iccQuantTableFine__FDK[MAX_ICC_QUANT_FINE] = { + SCALE_ICC(0.99999999953), SCALE_ICC(0.937f), SCALE_ICC(0.84118f), + SCALE_ICC(0.60092f), SCALE_ICC(0.36764f), SCALE_ICC(0.0f), + SCALE_ICC(-0.589f), SCALE_ICC(-0.99f)}; + +static const FIXP_DBL iccQuantTableCoarse__FDK[MAX_ICC_QUANT_COARSE] = { + SCALE_ICC(0.99999999953), SCALE_ICC(0.84118f), SCALE_ICC(0.36764f), + SCALE_ICC(-0.5890f)}; + +static const BOX_SUBBAND_SETUP boxSubbandSetup[] = { + {BOX_SUBBANDS_4, 4, subband2Parameter4_Ld, 1}, + {BOX_SUBBANDS_5, 5, subband2Parameter5_Ld, 2}, + {BOX_SUBBANDS_7, 7, subband2Parameter7_Ld, 3}, + {BOX_SUBBANDS_9, 9, subband2Parameter9_Ld, 4}, + {BOX_SUBBANDS_12, 12, subband2Parameter12_Ld, 4}, + {BOX_SUBBANDS_15, 15, subband2Parameter15_Ld, 5}, + {BOX_SUBBANDS_23, 23, subband2Parameter23_Ld, 8}}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static const BOX_SUBBAND_SETUP *getBoxSubbandSetup( + const BOX_SUBBAND_CONFIG subbandConfig) { + int i; + const BOX_SUBBAND_SETUP *setup = NULL; + + for (i = 0; i < (int)(sizeof(boxSubbandSetup) / sizeof(BOX_SUBBAND_SETUP)); + i++) { + if (boxSubbandSetup[i].subbandConfig == subbandConfig) { + setup = &boxSubbandSetup[i]; + break; + } + } + return setup; +} + +static inline void ApplyBBCuesFDK(FIXP_DBL *const pData, + const INT nParamBands) { + int i, s; + FIXP_DBL tmp, invParamBands; + + invParamBands = fDivNormHighPrec((FIXP_DBL)1, (FIXP_DBL)nParamBands, &s); + s = -s; + + tmp = fMult(pData[0], invParamBands) >> s; + for (i = 1; i < nParamBands; i++) { + tmp += fMult(pData[i], invParamBands) >> s; + } + + for (i = 0; i < nParamBands; i++) { + pData[i] = tmp; + } +} + +static INT getNumberParameterBands(const BOX_SUBBAND_CONFIG subbandConfig) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + return ((setup == NULL) ? 0 : setup->nParameterBands); +} + +static const UCHAR *getSubband2ParameterIndex( + const BOX_SUBBAND_CONFIG subbandConfig) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + + return ((setup == NULL) ? NULL : (setup->pSubband2ParameterIndexLd)); +} + +void fdk_sacenc_calcParameterBand2HybridBandOffset( + const BOX_SUBBAND_CONFIG subbandConfig, const INT nHybridBands, + UCHAR *pParameterBand2HybridBandOffset) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + const UCHAR *pSubband2ParameterIndex; + + int i, pb; + + pSubband2ParameterIndex = setup->pSubband2ParameterIndexLd; + + for (pb = 0, i = 0; i < nHybridBands - 1; i++) { + if (pSubband2ParameterIndex[i + 1] - pSubband2ParameterIndex[i]) { + pParameterBand2HybridBandOffset[pb++] = (i + 1); + } + } + pParameterBand2HybridBandOffset[pb++] = (i + 1); +} + +const INT *fdk_sacenc_getSubbandImagSign() { + const INT *pImagSign = NULL; + + pImagSign = subbandImagSign_Ld; + + return (pImagSign); +} + +static INT getIccCorrelationCoherenceBorder( + const BOX_SUBBAND_CONFIG subbandConfig, const INT bUseCoherenceOnly) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + return ( + (setup == NULL) + ? 0 + : ((bUseCoherenceOnly) ? 0 : setup->iccCorrelationCoherenceBorder)); +} + +FDK_SACENC_ERROR fdk_sacenc_createTtoBox(HANDLE_TTO_BOX *hTtoBox) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hTtoBox) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(*hTtoBox, 1, TTO_BOX); + } + return error; + +bail: + fdk_sacenc_destroyTtoBox(hTtoBox); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_initTtoBox(HANDLE_TTO_BOX hTtoBox, + const TTO_BOX_CONFIG *const ttoBoxConfig, + UCHAR *pParameterBand2HybridBandOffset) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hTtoBox == NULL) || (ttoBoxConfig == NULL) || + (pParameterBand2HybridBandOffset == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKmemclear(hTtoBox, sizeof(TTO_BOX)); + + hTtoBox->bUseCoarseQuantCld = ttoBoxConfig->bUseCoarseQuantCld; + hTtoBox->bUseCoarseQuantIcc = ttoBoxConfig->bUseCoarseQuantIcc; + hTtoBox->boxQuantMode = ttoBoxConfig->boxQuantMode; + hTtoBox->iccCorrelationCoherenceBorder = getIccCorrelationCoherenceBorder( + ttoBoxConfig->subbandConfig, ttoBoxConfig->bUseCoherenceIccOnly); + hTtoBox->nHybridBandsMax = ttoBoxConfig->nHybridBandsMax; + hTtoBox->nParameterBands = + getNumberParameterBands(ttoBoxConfig->subbandConfig); + hTtoBox->bFrameKeep = ttoBoxConfig->bFrameKeep; + + hTtoBox->nIccQuantSteps = + fdk_sacenc_getNumberIccQuantLevels(hTtoBox->bUseCoarseQuantIcc); + hTtoBox->nIccQuantOffset = + fdk_sacenc_getIccQuantOffset(hTtoBox->bUseCoarseQuantIcc); + + hTtoBox->pIccQuantTable__FDK = hTtoBox->bUseCoarseQuantIcc + ? iccQuantTableCoarse__FDK + : iccQuantTableFine__FDK; + hTtoBox->pCldQuantTableDec__FDK = hTtoBox->bUseCoarseQuantCld + ? cldQuantTableCoarseDec__FDK + : cldQuantTableFineDec__FDK; + hTtoBox->pCldQuantTableEnc__FDK = hTtoBox->bUseCoarseQuantCld + ? cldQuantTableCoarseEnc__FDK + : cldQuantTableFineEnc__FDK; + + hTtoBox->nCldQuantSteps = + fdk_sacenc_getNumberCldQuantLevels(hTtoBox->bUseCoarseQuantCld); + hTtoBox->nCldQuantOffset = + fdk_sacenc_getCldQuantOffset(hTtoBox->bUseCoarseQuantCld); + + /* sanity */ + if (NULL == (hTtoBox->pParameterBand2HybridBandOffset = + pParameterBand2HybridBandOffset)) { + error = SACENC_INIT_ERROR; + goto bail; + } + + if (NULL == (hTtoBox->pSubbandImagSign = fdk_sacenc_getSubbandImagSign())) { + error = SACENC_INIT_ERROR; + } + + if ((hTtoBox->boxQuantMode != BOX_QUANTMODE_FINE) && + (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ1) && + (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ2)) { + error = SACENC_INIT_ERROR; + goto bail; + } + } +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_destroyTtoBox(HANDLE_TTO_BOX *hTtoBox) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (*hTtoBox != NULL) { + FDKfree(*hTtoBox); + *hTtoBox = NULL; + } + + return error; +} + +static FDK_SACENC_ERROR calculateIccFDK(const INT nParamBand, + const INT correlationCoherenceBorder, + const FIXP_DBL *const pPwr1, + const FIXP_DBL *const pPwr2, + const FIXP_DBL *const pProdReal, + FIXP_DBL const *const pProdImag, + FIXP_DBL *const pIcc) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((pPwr1 == NULL) || (pPwr2 == NULL) || (pProdReal == NULL) || + (pProdImag == NULL) || (pIcc == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + /* sanity check border */ + if (correlationCoherenceBorder > nParamBand) { + error = SACENC_INVALID_CONFIG; + } else { + /* correlation */ + FDKcalcCorrelationVec(pIcc, pProdReal, pPwr1, pPwr2, + correlationCoherenceBorder); + + /* coherence */ + calcCoherenceVec(&pIcc[correlationCoherenceBorder], + &pProdReal[correlationCoherenceBorder], + &pProdImag[correlationCoherenceBorder], + &pPwr1[correlationCoherenceBorder], + &pPwr2[correlationCoherenceBorder], 0, 0, + nParamBand - correlationCoherenceBorder); + + } /* valid configuration */ + } /* valid handle */ + + return error; +} + +static void QuantizeCoefFDK(const FIXP_DBL *const input, const INT nBands, + const FIXP_DBL *const quantTable, + const INT idxOffset, const INT nQuantSteps, + SCHAR *const quantOut) { + int band; + const int reverse = (quantTable[0] > quantTable[1]); + + for (band = 0; band < nBands; band++) { + FIXP_DBL qVal; + FIXP_DBL curVal = input[band]; + + int lower = 0; + int upper = nQuantSteps - 1; + + if (reverse) { + while (upper - lower > 1) { + int idx = (lower + upper) >> 1; + qVal = quantTable[idx]; + if (curVal >= qVal) { + upper = idx; + } else { + lower = idx; + } + } /* while */ + + if ((curVal - quantTable[lower]) >= (quantTable[upper] - curVal)) { + quantOut[band] = lower - idxOffset; + } else { + quantOut[band] = upper - idxOffset; + } + } /* if reverse */ + else { + while (upper - lower > 1) { + int idx = (lower + upper) >> 1; + qVal = quantTable[idx]; + if (curVal <= qVal) { + upper = idx; + } else { + lower = idx; + } + } /* while */ + + if ((curVal - quantTable[lower]) <= (quantTable[upper] - curVal)) { + quantOut[band] = lower - idxOffset; + } else { + quantOut[band] = upper - idxOffset; + } + } /* else reverse */ + } /* for band */ +} + +static void deQuantizeCoefFDK(const SCHAR *const input, const INT nBands, + const FIXP_DBL *const quantTable, + const INT idxOffset, FIXP_DBL *const dequantOut) { + int band; + + for (band = 0; band < nBands; band++) { + dequantOut[band] = quantTable[input[band] + idxOffset]; + } +} + +static void CalculateCldFDK(FIXP_DBL *const pCld, const FIXP_DBL *const pPwr1, + const FIXP_DBL *const pPwr2, const INT scaleCh1, + const INT *const pbScaleCh1, const INT scaleCh2, + const INT *const pbScaleCh2, const int nParamBand) { + INT i; + FIXP_DBL ldPwr1, ldPwr2, cld; + FIXP_DBL maxPwr = FL2FXCONST_DBL( + 30.0f / + (1 << (LD_DATA_SHIFT + + 1))); /* consider SACENC_FLOAT_EPSILON in power calculation */ + + for (i = 0; i < nParamBand; i++) { + ldPwr1 = + (CalcLdData(pPwr1[i]) >> 1) + ((FIXP_DBL)(scaleCh1 + pbScaleCh1[i]) + << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + ldPwr2 = + (CalcLdData(pPwr2[i]) >> 1) + ((FIXP_DBL)(scaleCh2 + pbScaleCh2[i]) + << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + + ldPwr1 = fixMax(fixMin(ldPwr1, maxPwr), -maxPwr); + ldPwr2 = fixMax(fixMin(ldPwr2, maxPwr), -maxPwr); + + /* ldPwr1 and ldPwr2 are scaled by LD_DATA_SHIFT and additional 1 bit; 1 bit + * scale by fMultDiv2() */ + cld = fMultDiv2(FL2FXCONST_DBL(LOG10_2_10 / (1 << SCALE_CLDE_SF)), + ldPwr1 - ldPwr2); + + cld = + fixMin(cld, (FIXP_DBL)(((FIXP_DBL)MAXVAL_DBL) >> (LD_DATA_SHIFT + 2))); + cld = + fixMax(cld, (FIXP_DBL)(((FIXP_DBL)MINVAL_DBL) >> (LD_DATA_SHIFT + 2))); + pCld[i] = cld << (LD_DATA_SHIFT + 2); + } +} + +FDK_SACENC_ERROR fdk_sacenc_applyTtoBox( + HANDLE_TTO_BOX hTtoBox, const INT nTimeSlots, const INT startTimeSlot, + const INT nHybridBands, const FIXP_DPK *const *const ppHybridData1__FDK, + const FIXP_DPK *const *const ppHybridData2__FDK, SCHAR *const pIccIdx, + UCHAR *const pbIccQuantCoarse, SCHAR *const pCldIdx, + UCHAR *const pbCldQuantCoarse, const INT bUseBBCues, INT *scaleCh1, + INT *scaleCh2) { + FDK_SACENC_ERROR error = SACENC_OK; + + C_ALLOC_SCRATCH_START(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + + C_ALLOC_SCRATCH_START(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS) + + if ((hTtoBox == NULL) || (pCldIdx == NULL) || (pbCldQuantCoarse == NULL) || + (ppHybridData1__FDK == NULL) || (ppHybridData2__FDK == NULL) || + (pIccIdx == NULL) || (pbIccQuantCoarse == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int j, pb; + const int nParamBands = hTtoBox->nParameterBands; + const int bUseEbQ = (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ1) || + (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ2); + + /* sanity check */ + if ((nHybridBands < 0) || (nHybridBands > hTtoBox->nHybridBandsMax)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + int outScale; /* scalefactor will not be evaluated */ + int inScale = 5; /* scale factor determined empirically */ + + /* calculate the headroom of the hybrid data for each parameter band */ + FDKcalcPbScaleFactor(ppHybridData1__FDK, + hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh1, + startTimeSlot, nTimeSlots, nParamBands); + FDKcalcPbScaleFactor(ppHybridData2__FDK, + hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh2, + startTimeSlot, nTimeSlots, nParamBands); + + for (j = 0, pb = 0; pb < nParamBands; pb++) { + FIXP_DBL data1, data2; + data1 = data2 = (FIXP_DBL)0; + for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) { + data1 += sumUpCplxPow2Dim2(ppHybridData1__FDK, SUM_UP_STATIC_SCALE, + inScale + pbScaleCh1[pb], &outScale, + startTimeSlot, nTimeSlots, j, j + 1); + data2 += sumUpCplxPow2Dim2(ppHybridData2__FDK, SUM_UP_STATIC_SCALE, + inScale + pbScaleCh2[pb], &outScale, + startTimeSlot, nTimeSlots, j, j + 1); + } /* for j */ + powerHybridData1__FDK[pb] = data1; + powerHybridData2__FDK[pb] = data2; + } /* pb */ + + { + for (j = 0, pb = 0; pb < nParamBands; pb++) { + FIXP_DBL dataReal, dataImag; + dataReal = dataImag = (FIXP_DBL)0; + for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) { + FIXP_DPK scalarProd; + cplx_cplxScalarProduct(&scalarProd, ppHybridData1__FDK, + ppHybridData2__FDK, inScale + pbScaleCh1[pb], + inScale + pbScaleCh2[pb], &outScale, + startTimeSlot, nTimeSlots, j, j + 1); + dataReal += scalarProd.v.re; + if (hTtoBox->pSubbandImagSign[j] < 0) { + dataImag -= scalarProd.v.im; + } else { + dataImag += scalarProd.v.im; + } + } /* for j */ + prodHybridDataReal__FDK[pb] = dataReal; + prodHybridDataImag__FDK[pb] = dataImag; + } /* pb */ + + if (SACENC_OK != (error = calculateIccFDK( + nParamBands, hTtoBox->iccCorrelationCoherenceBorder, + powerHybridData1__FDK, powerHybridData2__FDK, + prodHybridDataReal__FDK, prodHybridDataImag__FDK, + hTtoBox->pIcc__FDK))) { + goto bail; + } + + /* calculate correlation based Icc for downmix */ + if (SACENC_OK != (error = calculateIccFDK( + nParamBands, nParamBands, powerHybridData1__FDK, + powerHybridData2__FDK, prodHybridDataReal__FDK, + prodHybridDataImag__FDK, IccDownmix__FDK))) { + goto bail; + } + } + + if (!bUseEbQ) { + CalculateCldFDK(hTtoBox->pCld__FDK, powerHybridData1__FDK, + powerHybridData2__FDK, *scaleCh1 + inScale + 1, + pbScaleCh1, *scaleCh2 + inScale + 1, pbScaleCh2, + nParamBands); + } + + if (bUseBBCues) { + ApplyBBCuesFDK(&hTtoBox->pCld__FDK[0], nParamBands); + + { ApplyBBCuesFDK(&hTtoBox->pIcc__FDK[0], nParamBands); } + + } /* bUseBBCues */ + + /* quantize/de-quantize icc */ + { + QuantizeCoefFDK(hTtoBox->pIcc__FDK, nParamBands, + hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, + hTtoBox->nIccQuantSteps, pIccIdx); + QuantizeCoefFDK(IccDownmix__FDK, nParamBands, + hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, + hTtoBox->nIccQuantSteps, hTtoBox->pIccDownmixIdx); + deQuantizeCoefFDK(hTtoBox->pIccDownmixIdx, nParamBands, + hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, + IccDownmixQuant__FDK); + + *pbIccQuantCoarse = hTtoBox->bUseCoarseQuantIcc; + } + + /* quantize/de-quantize cld */ + if (!bUseEbQ) { + QuantizeCoefFDK(hTtoBox->pCld__FDK, nParamBands, + hTtoBox->pCldQuantTableEnc__FDK, hTtoBox->nCldQuantOffset, + hTtoBox->nCldQuantSteps, pCldIdx); + deQuantizeCoefFDK(pCldIdx, nParamBands, hTtoBox->pCldQuantTableDec__FDK, + hTtoBox->nCldQuantOffset, hTtoBox->pCldQuant__FDK); + } else { + FDKmemcpy(pCldIdx, hTtoBox->pCldEbQIdx, nParamBands * sizeof(SCHAR)); + } + *pbCldQuantCoarse = hTtoBox->bUseCoarseQuantCld; + + } /* valid handle */ + +bail: + C_ALLOC_SCRATCH_END(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + + C_ALLOC_SCRATCH_END(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + + return error; +} + +INT fdk_sacenc_subband2ParamBand(const BOX_SUBBAND_CONFIG boxSubbandConfig, + const INT nSubband) { + INT nParamBand = -1; + const UCHAR *pSubband2ParameterIndex = + getSubband2ParameterIndex(boxSubbandConfig); + + if (pSubband2ParameterIndex != NULL) { + const int hybrid_resolution = 64; + + if ((nSubband > -1) && (nSubband < hybrid_resolution)) { + nParamBand = pSubband2ParameterIndex[nSubband]; + } + } + + return nParamBand; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_paramextract.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_paramextract.h new file mode 100644 index 0000000000000..9ebb902357ba2 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_paramextract.h @@ -0,0 +1,214 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Parameter Extraction + +*******************************************************************************/ + +#ifndef SACENC_PARAMEXTRACT_H +#define SACENC_PARAMEXTRACT_H + +/* Includes ******************************************************************/ +#include "common_fix.h" +#include "sacenc_lib.h" +#include "sacenc_const.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ +#define MAX_CLD_QUANT_FINE (31) +#define MAX_CLD_QUANT_COARSE (15) +#define OFFSET_CLD_QUANT_COARSE (7) +#define OFFSET_CLD_QUANT_FINE (15) + +#define MAX_ICC_QUANT_COARSE (4) +#define MAX_ICC_QUANT_FINE (8) +#define OFFSET_ICC_QUANT_COARSE (0) +#define OFFSET_ICC_QUANT_FINE (0) + +#define MAX_NUM_PARAM_BANDS (28) + +#define NUM_MAPPED_HYBRID_BANDS (16) + +/* Data Types ****************************************************************/ +typedef struct T_TTO_BOX *HANDLE_TTO_BOX; + +typedef enum { + BOX_SUBBANDS_INVALID = 0, + BOX_SUBBANDS_4 = 4, + BOX_SUBBANDS_5 = 5, + BOX_SUBBANDS_7 = 7, + BOX_SUBBANDS_9 = 9, + BOX_SUBBANDS_12 = 12, + BOX_SUBBANDS_15 = 15, + BOX_SUBBANDS_23 = 23 + +} BOX_SUBBAND_CONFIG; + +typedef enum { + BOX_QUANTMODE_INVALID = -1, + BOX_QUANTMODE_FINE = 0, + BOX_QUANTMODE_EBQ1 = 1, + BOX_QUANTMODE_EBQ2 = 2, + BOX_QUANTMODE_RESERVED3 = 3, + BOX_QUANTMODE_RESERVED4 = 4, + BOX_QUANTMODE_RESERVED5 = 5, + BOX_QUANTMODE_RESERVED6 = 6, + BOX_QUANTMODE_RESERVED7 = 7 + +} BOX_QUANTMODE; + +typedef struct T_TTO_BOX_CONFIG { + UCHAR bUseCoarseQuantCld; + UCHAR bUseCoarseQuantIcc; + UCHAR bUseCoherenceIccOnly; + + BOX_SUBBAND_CONFIG subbandConfig; + BOX_QUANTMODE boxQuantMode; + + UCHAR nHybridBandsMax; + + UCHAR bFrameKeep; + +} TTO_BOX_CONFIG; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_createTtoBox(HANDLE_TTO_BOX *hTtoBox); + +FDK_SACENC_ERROR fdk_sacenc_initTtoBox(HANDLE_TTO_BOX hTtoBox, + const TTO_BOX_CONFIG *const ttoBoxConfig, + UCHAR *pParameterBand2HybridBandOffset); + +FDK_SACENC_ERROR fdk_sacenc_destroyTtoBox(HANDLE_TTO_BOX *hTtoBox); + +FDK_SACENC_ERROR fdk_sacenc_applyTtoBox( + HANDLE_TTO_BOX hTtoBox, const INT nTimeSlots, const INT startTimeSlot, + const INT nHybridBands, const FIXP_DPK *const *const ppHybridData1__FDK, + const FIXP_DPK *const *const ppHybridData2__FDK, SCHAR *const pIccIdx, + UCHAR *const pbIccQuantCoarse, SCHAR *const pCldIdx, + UCHAR *const pbCldQuantCoarse, const INT bUseBBCues, INT *scaleCh0, + INT *scaleCh1); + +INT fdk_sacenc_subband2ParamBand(const BOX_SUBBAND_CONFIG boxSubbandConfig, + const INT nSubband); + +const INT *fdk_sacenc_getSubbandImagSign(); + +void fdk_sacenc_calcParameterBand2HybridBandOffset( + const BOX_SUBBAND_CONFIG subbandConfig, const INT nHybridBands, + UCHAR *pParameterBand2HybridBandOffset); + +/* Function / Class Definition ***********************************************/ +static inline UCHAR fdk_sacenc_getCldQuantOffset(const INT bUseCoarseQuant) { + return ((bUseCoarseQuant) ? OFFSET_CLD_QUANT_COARSE : OFFSET_CLD_QUANT_FINE); +} +static inline UCHAR fdk_sacenc_getIccQuantOffset(const INT bUseCoarseQuant) { + return ((bUseCoarseQuant) ? OFFSET_ICC_QUANT_COARSE : OFFSET_ICC_QUANT_FINE); +} + +static inline UCHAR fdk_sacenc_getNumberCldQuantLevels( + const INT bUseCoarseQuant) { + return ((bUseCoarseQuant) ? MAX_CLD_QUANT_COARSE : MAX_CLD_QUANT_FINE); +} +static inline UCHAR fdk_sacenc_getNumberIccQuantLevels( + const INT bUseCoarseQuant) { + return ((bUseCoarseQuant) ? MAX_ICC_QUANT_COARSE : MAX_ICC_QUANT_FINE); +} + +#endif /* SACENC_PARAMEXTRACT_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_staticgain.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_staticgain.cpp new file mode 100644 index 0000000000000..fef9f8d5749ef --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_staticgain.cpp @@ -0,0 +1,446 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Christian Goettlinger + + Description: Encoder Library Interface + gain management of the encoder + +*******************************************************************************/ + +/***************************************************************************** +\file +This file contains all static gain infrastructure +******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_staticgain.h" + +/* Defines *******************************************************************/ +#define MP4SPACEENC_DMX_GAIN_DEFAULT SACENC_DMXGAIN_3_dB +#define GAINCF_SF (4) +#define GAINCT1(x) FL2FXCONST_DBL(x) +#define GAINCF(x) FL2FXCONST_DBL(x) + +#define GAINCT2(x) FL2FXCONST_DBL(x) +#define FX_DBL2FX_GAIN(x) (x) + +/* Data Types ****************************************************************/ +struct STATIC_GAIN { + /* External Config Values */ + MP4SPACEENC_MODE encMode; + MP4SPACEENC_DMX_GAIN fixedGainDMX; + INT preGainFactorDb; + + /* Internal Values */ + FIXP_GAIN PostGain__FDK; + FIXP_GAIN pPreGain__FDK[SACENC_MAX_INPUT_CHANNELS]; +}; + +/* Constants *****************************************************************/ +/* + preGainFactorTable: + + pre calculation: (float)pow(10.f,(((float) x)/20.f))/(float)(1<encMode = SACENC_INVALID_MODE; + + /* Optional Configs Set to Default Values */ + hStaticGainConfig->fixedGainDMX = MP4SPACEENC_DMX_GAIN_DEFAULT; + hStaticGainConfig->preGainFactorDb = 0; + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticGain_CloseConfig() +description: destructs Static Gain Config Structure +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticGain_CloseConfig( + HANDLE_STATIC_GAIN_CONFIG *phStaticGainConfig) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((phStaticGainConfig == NULL) || (*phStaticGainConfig == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKfree(*phStaticGainConfig); + *phStaticGainConfig = NULL; + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticGain_Open() +description: initializes Static Gains +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticGain_Open(HANDLE_STATIC_GAIN *phStaticGain) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phStaticGain) { + error = SACENC_INVALID_HANDLE; + } else { + /* Allocate Instance */ + FDK_ALLOCATE_MEMORY_1D(*phStaticGain, 1, struct STATIC_GAIN); + } + return error; + +bail: + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_staticGain_Init( + HANDLE_STATIC_GAIN hStaticGain, + const HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig, INT *const scale) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hStaticGain == NULL) || (hStaticGainConfig == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + hStaticGain->encMode = hStaticGainConfig->encMode; + hStaticGain->fixedGainDMX = hStaticGainConfig->fixedGainDMX; + hStaticGain->preGainFactorDb = hStaticGainConfig->preGainFactorDb; + + if ((hStaticGain->preGainFactorDb < -20) || + (hStaticGain->preGainFactorDb > 20)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + FIXP_DBL fPreGainFactor__FDK; + + if (hStaticGain->preGainFactorDb == 0) { + fPreGainFactor__FDK = (FIXP_DBL)MAXVAL_DBL; + *scale = 0; + } else { + int s; + fPreGainFactor__FDK = + preGainFactorTable__FDK[hStaticGain->preGainFactorDb + 20]; + s = fixMax(0, CntLeadingZeros(fPreGainFactor__FDK) - 1); + fPreGainFactor__FDK = fPreGainFactor__FDK << (s); + *scale = GAINCF_SF - s; + } + + if (hStaticGain->fixedGainDMX == 0) + hStaticGain->PostGain__FDK = MAXVAL_GAIN; + else + hStaticGain->PostGain__FDK = + dmxGainTable__FDK[hStaticGain->fixedGainDMX - 1]; + + FDKmemclear( + hStaticGain->pPreGain__FDK, + sizeof(hStaticGain->pPreGain__FDK)); /* zero all input channels */ + + /* Configure PreGain-Vector */ + if (hStaticGain->encMode == SACENC_212) { + hStaticGain->pPreGain__FDK[0] = + FX_DBL2FX_GAIN(fPreGainFactor__FDK); /* L */ + hStaticGain->pPreGain__FDK[1] = + FX_DBL2FX_GAIN(fPreGainFactor__FDK); /* R */ + } else { + error = SACENC_INVALID_CONFIG; + } + + } /* valid handle */ + +bail: + + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticGain_Close() +description: destructs Static Gains +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticGain_Close(HANDLE_STATIC_GAIN *phStaticGain) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((phStaticGain == NULL) || (*phStaticGain == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKfree(*phStaticGain); + *phStaticGain = NULL; + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticPostGain_Apply +description: multiply the Output samples with the PostGain +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticPostGain_ApplyFDK( + const HANDLE_STATIC_GAIN hStaticGain, INT_PCM *const pOutputSamples, + const INT nOutputSamples, const INT scale) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hStaticGain) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + FIXP_GAIN postGain = hStaticGain->PostGain__FDK; + + if (scale < 0) { + if (postGain == MAXVAL_GAIN) { + for (i = 0; i < nOutputSamples; i++) { + pOutputSamples[i] = pOutputSamples[i] >> (-scale); + } + } else { + for (i = 0; i < nOutputSamples; i++) { + pOutputSamples[i] = FX_DBL2FX_PCM( + fMult(postGain, FX_PCM2FX_DBL(pOutputSamples[i])) >> (-scale)); + } + } + } else { + if (postGain == MAXVAL_GAIN) { + for (i = 0; i < nOutputSamples; i++) { + pOutputSamples[i] = FX_DBL2FX_PCM(SATURATE_LEFT_SHIFT( + FX_PCM2FX_DBL(pOutputSamples[i]), scale, DFRACT_BITS)); + } + } else { + for (i = 0; i < nOutputSamples; i++) { + pOutputSamples[i] = FX_DBL2FX_PCM(SATURATE_LEFT_SHIFT( + fMult(postGain, FX_PCM2FX_DBL(pOutputSamples[i])), scale, + DFRACT_BITS)); + } + } + } + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_getPreGainPtr()/ fdk_sacenc_getPostGain() +description: get Gain-Pointers from struct +returns: Pointer to PreGain or postGain +-----------------------------------------------------------------------------*/ +FIXP_GAIN *fdk_sacenc_getPreGainPtrFDK(HANDLE_STATIC_GAIN hStaticGain) { + return ((hStaticGain == NULL) ? NULL : hStaticGain->pPreGain__FDK); +} + +FIXP_GAIN fdk_sacenc_getPostGainFDK(HANDLE_STATIC_GAIN hStaticGain) { + return (hStaticGain->PostGain__FDK); +} + +/* get fixed downmix gain and map it to bitstream enum */ +FIXEDGAINDMXCONFIG fdk_sacenc_staticGain_GetDmxGain( + const HANDLE_STATIC_GAIN hStaticGain) { + FIXEDGAINDMXCONFIG dmxGain = FIXEDGAINDMX_INVALID; + + switch (hStaticGain->fixedGainDMX) { + case 0: + dmxGain = FIXEDGAINDMX_0; + break; + case 1: + dmxGain = FIXEDGAINDMX_1; + break; + case 2: + dmxGain = FIXEDGAINDMX_2; + break; + case 3: + dmxGain = FIXEDGAINDMX_3; + break; + case 4: + dmxGain = FIXEDGAINDMX_4; + break; + case 5: + dmxGain = FIXEDGAINDMX_5; + break; + case 6: + dmxGain = FIXEDGAINDMX_6; + break; + case 7: + dmxGain = FIXEDGAINDMX_7; + break; + default: + dmxGain = FIXEDGAINDMX_INVALID; + } + return dmxGain; +} + +FDK_SACENC_ERROR fdk_sacenc_staticGain_SetDmxGain( + HANDLE_STATIC_GAIN_CONFIG hStaticGainCfg, + const MP4SPACEENC_DMX_GAIN dmxGain) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hStaticGainCfg) { + error = SACENC_INVALID_HANDLE; + } else { + hStaticGainCfg->fixedGainDMX = dmxGain; + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_staticGain_SetEncMode( + HANDLE_STATIC_GAIN_CONFIG hStaticGainCfg, const MP4SPACEENC_MODE encMode) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hStaticGainCfg) { + error = SACENC_INVALID_HANDLE; + } else { + hStaticGainCfg->encMode = encMode; + } + return error; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_staticgain.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_staticgain.h new file mode 100644 index 0000000000000..5db3becfa90c4 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_staticgain.h @@ -0,0 +1,177 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Christian Goettlinger + + Description: Encoder Library Interfac + gain management of the encoder + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + ******************************************************************************/ + +#ifndef SACENC_STATICGAIN_H +#define SACENC_STATICGAIN_H + +/* Includes ******************************************************************/ +#include "common_fix.h" +#include "sacenc_lib.h" +#include "sacenc_const.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ +#define FIXP_GAIN FIXP_DBL +#define MAXVAL_GAIN ((FIXP_DBL)MAXVAL_DBL) + +/* Data Types ****************************************************************/ +struct STATIC_GAIN_CONFIG { + MP4SPACEENC_MODE encMode; + MP4SPACEENC_DMX_GAIN fixedGainDMX; + INT preGainFactorDb; +}; + +typedef struct STATIC_GAIN_CONFIG *HANDLE_STATIC_GAIN_CONFIG; +typedef struct STATIC_GAIN *HANDLE_STATIC_GAIN; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Initializes Static Gain Computation Config */ +FDK_SACENC_ERROR fdk_sacenc_staticGain_OpenConfig( + HANDLE_STATIC_GAIN_CONFIG *phStaticGainConfig); + +FDK_SACENC_ERROR fdk_sacenc_staticGain_InitDefaultConfig( + HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig); + +/* Deletes Static Gain Computation Config ~Destructor */ +FDK_SACENC_ERROR fdk_sacenc_staticGain_CloseConfig( + HANDLE_STATIC_GAIN_CONFIG *phStaticGainConfig); + +/* Initializes Static Gain Computation ~Constructor */ +FDK_SACENC_ERROR fdk_sacenc_staticGain_Open(HANDLE_STATIC_GAIN *phStaticGain); + +FDK_SACENC_ERROR fdk_sacenc_staticGain_Init( + HANDLE_STATIC_GAIN hStaticGain, + const HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig, INT *const scale); + +/* Deletes Static Gain Computation Infrastucture ~Destructor */ +FDK_SACENC_ERROR fdk_sacenc_staticGain_Close(HANDLE_STATIC_GAIN *phStaticGain); + +/* Apply PostGain to the output PCM Downmix-Signal */ +FDK_SACENC_ERROR fdk_sacenc_staticPostGain_ApplyFDK( + const HANDLE_STATIC_GAIN hStaticGain, INT_PCM *const pOutputSamples, + const INT nOutputSamples, const INT scale); + +/* Get Pointer to PreGain-vector */ +FIXP_GAIN *fdk_sacenc_getPreGainPtrFDK(HANDLE_STATIC_GAIN hStaticGain); + +/* Get Pointer to PostGain-coef */ +FIXP_GAIN fdk_sacenc_getPostGainFDK(HANDLE_STATIC_GAIN hStaticGain); + +FIXEDGAINDMXCONFIG fdk_sacenc_staticGain_GetDmxGain( + const HANDLE_STATIC_GAIN hStaticGain); + +FDK_SACENC_ERROR fdk_sacenc_staticGain_SetDmxGain( + HANDLE_STATIC_GAIN_CONFIG hStaticGainCfg, + const MP4SPACEENC_DMX_GAIN dmxGain); + +FDK_SACENC_ERROR fdk_sacenc_staticGain_SetEncMode( + HANDLE_STATIC_GAIN_CONFIG hStaticGainCfg, const MP4SPACEENC_MODE encMode); + +#endif /* SACENC_STATICGAIN_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_tree.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_tree.cpp new file mode 100644 index 0000000000000..c7d312861720e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_tree.cpp @@ -0,0 +1,488 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Tree Structure for Space Encoder + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_tree.h" +#include "genericStds.h" +#include "sacenc_const.h" +#include "sacenc_paramextract.h" +#include "sacenc_framewindowing.h" +#include "FDK_matrixCalloc.h" + +/* Defines *******************************************************************/ +enum { BOX_0 = 0, BOX_1 = 1 }; + +enum { CH_L = 0, CH_R = 1 }; + +enum { TTO_CH_0 = 0, TTO_CH_1 = 1 }; + +enum { WIN_INACTIV = 0, WIN_ACTIV = 1 }; + +enum { MAX_KEEP_FRAMECOUNT = 100 }; + +/* Data Types ****************************************************************/ +struct SPACE_TREE { + SPACETREE_MODE mode; + SPACE_TREE_DESCRIPTION descr; + HANDLE_TTO_BOX ttoBox[SACENC_MAX_NUM_BOXES]; + UCHAR nParamBands; + UCHAR bUseCoarseQuantTtoIcc; + UCHAR bUseCoarseQuantTtoCld; + QUANTMODE quantMode; + INT frameCount; + UCHAR bFrameKeep; + + /* Intermediate buffers */ + UCHAR pCld_prev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAM_BANDS]; + UCHAR pIcc_prev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAM_BANDS]; + + UCHAR nChannelsInMax; + UCHAR nHybridBandsMax; +}; + +typedef struct { + UCHAR boxId; + UCHAR inCh1; + UCHAR inCh2; + UCHAR inCh3; + UCHAR inCh4; + UCHAR wCh1; + UCHAR wCh2; + +} TTO_DESCRIPTOR; + +typedef struct { + SPACETREE_MODE mode; + SPACE_TREE_DESCRIPTION treeDescription; + +} TREE_CONFIG; + +typedef struct { + SPACETREE_MODE mode; + UCHAR nChannelsIn; + UCHAR nChannelsOut; + UCHAR nTtoBoxes; + TTO_DESCRIPTOR tto_descriptor[1]; + +} TREE_SETUP; + +/* Constants *****************************************************************/ +static const TREE_CONFIG treeConfigTable[] = { + {SPACETREE_INVALID_MODE, {0, 0, 0}}, {SPACETREE_212, {1, 1, 2}}}; + +static const TREE_SETUP treeSetupTable[] = { + {SPACETREE_INVALID_MODE, 0, 0, 0, {{0, 0, 0, 0, 0, 0, 0}}}, + {SPACETREE_212, + 2, + 1, + 1, + {{BOX_0, CH_L, CH_R, TTO_CH_0, TTO_CH_1, WIN_ACTIV, WIN_ACTIV}}}}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static FDK_SACENC_ERROR getTreeConfig( + const SPACETREE_MODE mode, SPACE_TREE_DESCRIPTION *pTreeDescription) { + FDK_SACENC_ERROR error = SACENC_INIT_ERROR; + + if (pTreeDescription == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + for (i = 0; i < (int)(sizeof(treeConfigTable) / sizeof(TREE_CONFIG)); i++) { + if (treeConfigTable[i].mode == mode) { + *pTreeDescription = treeConfigTable[i].treeDescription; + error = SACENC_OK; + break; + } + } + } /* valid handle */ + return error; +} + +static const TREE_SETUP *getTreeSetup(const SPACETREE_MODE mode) { + int i; + const TREE_SETUP *setup = NULL; + + for (i = 0; i < (int)(sizeof(treeSetupTable) / sizeof(TREE_SETUP)); i++) { + if (treeSetupTable[i].mode == mode) { + setup = &treeSetupTable[i]; + break; + } + } + return setup; +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Open(HANDLE_SPACE_TREE *phSpaceTree) { + FDK_SACENC_ERROR error = SACENC_OK; + HANDLE_SPACE_TREE hSpaceTree = NULL; + + if (NULL == phSpaceTree) { + error = SACENC_INVALID_HANDLE; + } else { + int box; + + FDK_ALLOCATE_MEMORY_1D(hSpaceTree, 1, struct SPACE_TREE); + + for (box = 0; box < SACENC_MAX_NUM_BOXES; box++) { + HANDLE_TTO_BOX ttoBox = NULL; + if (SACENC_OK != (error = fdk_sacenc_createTtoBox(&ttoBox))) { + goto bail; + } + if (NULL != hSpaceTree) { + hSpaceTree->ttoBox[box] = ttoBox; + } + } + *phSpaceTree = hSpaceTree; + } + return error; + +bail: + fdk_sacenc_spaceTree_Close(&hSpaceTree); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Init( + HANDLE_SPACE_TREE hST, const SPACE_TREE_SETUP *const hSetup, + UCHAR *pParameterBand2HybridBandOffset, const INT bFrameKeep) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hST == NULL) || (hSetup == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int bTtoBoxFrontBackCombin[SACENC_MAX_NUM_BOXES] = {0}; + int box = 0; + + hST->frameCount = 0; + hST->bFrameKeep = bFrameKeep; + + /* Init */ + hST->mode = hSetup->mode; + hST->nParamBands = hSetup->nParamBands; + hST->bUseCoarseQuantTtoIcc = hSetup->bUseCoarseQuantTtoIcc; + hST->bUseCoarseQuantTtoCld = hSetup->bUseCoarseQuantTtoCld; + hST->quantMode = hSetup->quantMode; + hST->nChannelsInMax = hSetup->nChannelsInMax; + hST->nHybridBandsMax = hSetup->nHybridBandsMax; + + if (SACENC_OK != (error = getTreeConfig(hST->mode, &hST->descr))) { + goto bail; + } + + switch (hST->mode) { + case SPACETREE_212: + bTtoBoxFrontBackCombin[BOX_0] = 0; + break; + case SPACETREE_INVALID_MODE: + default: + error = SACENC_INIT_ERROR; + goto bail; + } /* switch (hST->mode) */ + + if (hST->descr.nOttBoxes > SACENC_MAX_NUM_BOXES) { + error = SACENC_INIT_ERROR; + goto bail; + } + + for (box = 0; box < hST->descr.nOttBoxes; box++) { + TTO_BOX_CONFIG boxConfig; + boxConfig.subbandConfig = (BOX_SUBBAND_CONFIG)hST->nParamBands; + boxConfig.bUseCoarseQuantCld = hST->bUseCoarseQuantTtoCld; + boxConfig.bUseCoarseQuantIcc = hST->bUseCoarseQuantTtoIcc; + boxConfig.bUseCoherenceIccOnly = bTtoBoxFrontBackCombin[box]; + boxConfig.boxQuantMode = (BOX_QUANTMODE)hST->quantMode; + boxConfig.nHybridBandsMax = hST->nHybridBandsMax; + boxConfig.bFrameKeep = hST->bFrameKeep; + + if (SACENC_OK != + (error = fdk_sacenc_initTtoBox(hST->ttoBox[box], &boxConfig, + pParameterBand2HybridBandOffset))) { + goto bail; + } + } /* for box */ + + } /* valid handle */ + +bail: + return error; +} + +static void SpaceTree_FrameKeep212(const HANDLE_SPACE_TREE hST, + SPATIALFRAME *const hSTOut, + const INT avoid_keep) { + int pb; + + if (avoid_keep == 0) { + if (hST->frameCount % 2 == 0) { + for (pb = 0; pb < hST->nParamBands; pb++) { + hST->pIcc_prev[BOX_0][pb] = hSTOut->ottData.icc[BOX_0][0][pb]; + hSTOut->ottData.cld[BOX_0][0][pb] = hST->pCld_prev[BOX_0][pb]; + } + } else { + for (pb = 0; pb < hST->nParamBands; pb++) { + hSTOut->ottData.icc[BOX_0][0][pb] = hST->pIcc_prev[BOX_0][pb]; + hST->pCld_prev[BOX_0][pb] = hSTOut->ottData.cld[BOX_0][0][pb]; + } + } + } else { + for (pb = 0; pb < hST->nParamBands; pb++) { + hST->pIcc_prev[BOX_0][pb] = hSTOut->ottData.icc[BOX_0][0][pb]; + hST->pCld_prev[BOX_0][pb] = hSTOut->ottData.cld[BOX_0][0][pb]; + } + } + hST->frameCount++; + if (hST->frameCount == MAX_KEEP_FRAMECOUNT) { + hST->frameCount = 0; + } +} + +static FDK_SACENC_ERROR SpaceTree_FrameKeep(const HANDLE_SPACE_TREE hST, + SPATIALFRAME *const hSTOut, + const INT avoid_keep) { + FDK_SACENC_ERROR error = SACENC_OK; + + switch (hST->mode) { + case SPACETREE_212: + SpaceTree_FrameKeep212(hST, hSTOut, avoid_keep); + break; + case SPACETREE_INVALID_MODE: + default: + error = SACENC_INVALID_CONFIG; + break; + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Apply( + HANDLE_SPACE_TREE hST, const INT paramSet, const INT nChannelsIn, + const INT nTimeSlots, const INT startTimeSlot, const INT nHybridBands, + FIXP_WIN *pFrameWindowAna__FDK, + FIXP_DPK *const *const *const pppHybrid__FDK, + FIXP_DPK *const *const *const pppHybridIn__FDK, SPATIALFRAME *const hSTOut, + const INT avoid_keep, INT *pEncoderInputChScale) { + /** \verbatim + ============================================================================================================================= + TREE_212 + ============================================================================================================================= + _______ + L -- TTO_CH_0 --| | + | TTO_0 |-- TTO_CH_0 + R -- TTO_CH_1 --|_______| + + \endverbatim */ + + FDK_SACENC_ERROR error = SACENC_OK; + int k; + const TREE_SETUP *treeSetup = NULL; + + if ((hST == NULL) || (hSTOut == NULL) || (pppHybrid__FDK == NULL) || + (pppHybridIn__FDK == NULL)) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + if ((treeSetup = getTreeSetup(hST->mode)) == NULL) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* Sanity Checks */ + if ((nChannelsIn != treeSetup->nChannelsIn) || + (nChannelsIn > hST->nChannelsInMax) || + (nHybridBands > hST->nHybridBandsMax)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* Apply all TTO boxes. */ + for (k = 0; k < treeSetup->nTtoBoxes; k++) { + const TTO_DESCRIPTOR *pTTO = &treeSetup->tto_descriptor[k]; + + int i, inCh[2], outCh[2], win[2]; + + inCh[0] = pTTO->inCh1; + outCh[0] = pTTO->inCh3; + win[0] = pTTO->wCh1; + inCh[1] = pTTO->inCh2; + outCh[1] = pTTO->inCh4; + win[1] = pTTO->wCh2; + + for (i = 0; i < 2; i++) { + if (win[i] == WIN_ACTIV) { + fdk_sacenc_analysisWindowing( + nTimeSlots, startTimeSlot, pFrameWindowAna__FDK, + pppHybrid__FDK[inCh[i]], pppHybridIn__FDK[outCh[i]], nHybridBands, + FW_LEAVE_DIM); + } + } + + /* Calculate output downmix within last TTO box, if no TTT box is applied. + */ + if (SACENC_OK != + (error = fdk_sacenc_applyTtoBox( + hST->ttoBox[pTTO->boxId], nTimeSlots, startTimeSlot, nHybridBands, + pppHybridIn__FDK[pTTO->inCh3], pppHybridIn__FDK[pTTO->inCh4], + hSTOut->ottData.icc[pTTO->boxId][paramSet], + &(hSTOut->ICCLosslessData.bsQuantCoarseXXX[pTTO->boxId][paramSet]), + hSTOut->ottData.cld[pTTO->boxId][paramSet], + &(hSTOut->CLDLosslessData.bsQuantCoarseXXX[pTTO->boxId][paramSet]), + hSTOut->bUseBBCues, &pEncoderInputChScale[inCh[0]], + &pEncoderInputChScale[inCh[1]]))) { + goto bail; + } + } + + if (hST->bFrameKeep == 1) { + if (SACENC_OK != (error = SpaceTree_FrameKeep(hST, hSTOut, avoid_keep))) { + goto bail; + } + } + +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Close(HANDLE_SPACE_TREE *phSpaceTree) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((phSpaceTree == NULL) || (*phSpaceTree == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int box; + HANDLE_SPACE_TREE const hST = *phSpaceTree; + + /* for (box = 0; box < hST->descr.nOttBoxes; ++box) { */ + for (box = 0; box < SACENC_MAX_NUM_BOXES; ++box) { + if (SACENC_OK != (error = fdk_sacenc_destroyTtoBox(&hST->ttoBox[box]))) { + goto bail; + } + } + + FDKfree(*phSpaceTree); + *phSpaceTree = NULL; + } +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_GetDescription( + const HANDLE_SPACE_TREE hSpaceTree, + SPACE_TREE_DESCRIPTION *pSpaceTreeDescription) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hSpaceTree == NULL) || (pSpaceTreeDescription == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + *pSpaceTreeDescription = hSpaceTree->descr; + } + return error; +} + +INT fdk_sacenc_spaceTree_Hybrid2ParamBand(const INT nParamBands, + const INT nHybridBand) { + return fdk_sacenc_subband2ParamBand((BOX_SUBBAND_CONFIG)nParamBands, + nHybridBand); +} + +/***************************************************************************** +******************************************************************************/ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_tree.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_tree.h new file mode 100644 index 0000000000000..09f5b2b27d683 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_tree.h @@ -0,0 +1,168 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Tree Structure for Space Encoder + +*******************************************************************************/ + +#ifndef SACENC_TREE_H +#define SACENC_TREE_H + +/* Includes ******************************************************************/ +#include "sacenc_framewindowing.h" +#include "sacenc_lib.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +typedef enum { + SPACETREE_INVALID_MODE = 0, + SPACETREE_212 = 8 + +} SPACETREE_MODE; + +typedef struct SPACE_TREE *HANDLE_SPACE_TREE; + +typedef struct { + UCHAR nParamBands; + UCHAR bUseCoarseQuantTtoCld; + UCHAR bUseCoarseQuantTtoIcc; + QUANTMODE quantMode; + SPACETREE_MODE mode; + + UCHAR nChannelsInMax; + UCHAR nHybridBandsMax; + +} SPACE_TREE_SETUP; + +typedef struct { + UCHAR nOttBoxes; + UCHAR nInChannels; + UCHAR nOutChannels; + +} SPACE_TREE_DESCRIPTION; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Open(HANDLE_SPACE_TREE *phSpaceTree); + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Init( + HANDLE_SPACE_TREE hST, const SPACE_TREE_SETUP *const hSetup, + UCHAR *pParameterBand2HybridBandOffset, const INT bFrameKeep); + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Apply( + HANDLE_SPACE_TREE hST, const INT paramSet, const INT nChannelsIn, + const INT nTimeSlots, const INT startTimeSlot, const INT nHybridBands, + FIXP_WIN *pFrameWindowAna__FDK, + FIXP_DPK *const *const *const pppHybrid__FDK, + FIXP_DPK *const *const *const pppHybridIn__FDK, SPATIALFRAME *const hSTOut, + const INT avoid_keep, INT *pEncoderInputChScale); + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Close(HANDLE_SPACE_TREE *phSpaceTree); + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_GetDescription( + const HANDLE_SPACE_TREE hSpaceTree, + SPACE_TREE_DESCRIPTION *pSpaceTreeDescription); + +INT fdk_sacenc_spaceTree_Hybrid2ParamBand(const INT nParamBands, + const INT nHybridBand); + +#endif /* SACENC_TREE_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_vectorfunctions.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_vectorfunctions.cpp new file mode 100644 index 0000000000000..c1e24b7ef309f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_vectorfunctions.cpp @@ -0,0 +1,450 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Josef Hoepfl + + Description: Encoder Library Interface + vector functions + +*******************************************************************************/ + +/***************************************************************************** +\file +This file contains vector functions +******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ + +FIXP_DBL sumUpCplxPow2(const FIXP_DPK *const x, const INT scaleMode, + const INT inScaleFactor, INT *const outScaleFactor, + const INT n) { + int i, cs; + + if (scaleMode == SUM_UP_DYNAMIC_SCALE) { + /* calculate headroom */ + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + for (i = 0; i < n; i++) { + maxVal |= fAbs(x[i].v.re); + maxVal |= fAbs(x[i].v.im); + } + cs = inScaleFactor - fixMax(0, CntLeadingZeros(maxVal) - 1); + } else { + cs = inScaleFactor; + } + + /* consider scaling of energy and scaling in fPow2Div2 and addition */ + *outScaleFactor = 2 * cs + 2; + + /* make sure that the scalefactor is in the range of -(DFRACT_BITS-1), ... , + * (DFRACT_BITS-1) */ + cs = fixMax(fixMin(cs, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + + /* sum up complex energy samples */ + FIXP_DBL re, im, sum; + + re = im = sum = FL2FXCONST_DBL(0.0); + if (cs < 0) { + cs = -cs; + for (i = 0; i < n; i++) { + re += fPow2Div2(x[i].v.re << cs); + im += fPow2Div2(x[i].v.im << cs); + } + } else { + cs = 2 * cs; + for (i = 0; i < n; i++) { + re += fPow2Div2(x[i].v.re) >> cs; + im += fPow2Div2(x[i].v.im) >> cs; + } + } + + sum = (re >> 1) + (im >> 1); + + return (sum); +} + +FIXP_DBL sumUpCplxPow2Dim2(const FIXP_DPK *const *const x, const INT scaleMode, + const INT inScaleFactor, INT *const outScaleFactor, + const INT sDim1, const INT nDim1, const INT sDim2, + const INT nDim2) { + int i, j, cs; + + if (scaleMode == SUM_UP_DYNAMIC_SCALE) { + /* calculate headroom */ + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + maxVal |= fAbs(x[i][j].v.re); + maxVal |= fAbs(x[i][j].v.im); + } + } + cs = inScaleFactor - fixMax(0, CntLeadingZeros(maxVal) - 1); + } else { + cs = inScaleFactor; + } + + /* consider scaling of energy and scaling in fPow2Div2 and addition */ + *outScaleFactor = 2 * cs + 2; + + /* make sure that the scalefactor is in the range of -(DFRACT_BITS-1), ... , + * (DFRACT_BITS-1) */ + cs = fixMax(fixMin(cs, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + + /* sum up complex energy samples */ + FIXP_DBL re, im, sum; + + re = im = sum = FL2FXCONST_DBL(0.0); + if (cs < 0) { + cs = -cs; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + re += fPow2Div2(x[i][j].v.re << cs); + im += fPow2Div2(x[i][j].v.im << cs); + } + } + } else { + cs = 2 * cs; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + re += fPow2Div2(x[i][j].v.re) >> cs; + im += fPow2Div2(x[i][j].v.im) >> cs; + } + } + } + + sum = (re >> 1) + (im >> 1); + + return (sum); +} + +void copyCplxVec(FIXP_DPK *const Z, const FIXP_DPK *const X, const INT n) { + FDKmemmove(Z, X, sizeof(FIXP_DPK) * n); +} + +void setCplxVec(FIXP_DPK *const Z, const FIXP_DBL a, const INT n) { + int i; + + for (i = 0; i < n; i++) { + Z[i].v.re = a; + Z[i].v.im = a; + } +} + +void cplx_cplxScalarProduct(FIXP_DPK *const Z, const FIXP_DPK *const *const X, + const FIXP_DPK *const *const Y, const INT scaleX, + const INT scaleY, INT *const scaleZ, + const INT sDim1, const INT nDim1, const INT sDim2, + const INT nDim2) { + int i, j, sx, sy; + FIXP_DBL xre, yre, xim, yim, re, im; + + /* make sure that the scalefactor is in the range of -(DFRACT_BITS-1), ... , + * (DFRACT_BITS-1) */ + sx = fixMax(fixMin(scaleX, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + sy = fixMax(fixMin(scaleY, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + + /* consider scaling of energy and scaling in fMultDiv2 and shift of result + * values */ + *scaleZ = sx + sy + 2; + + re = (FIXP_DBL)0; + im = (FIXP_DBL)0; + if ((sx < 0) && (sy < 0)) { + sx = -sx; + sy = -sy; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + xre = X[i][j].v.re << sx; + xim = X[i][j].v.im << sx; + yre = Y[i][j].v.re << sy; + yim = Y[i][j].v.im << sy; + re += fMultDiv2(xre, yre) + fMultDiv2(xim, yim); + im += fMultDiv2(xim, yre) - fMultDiv2(xre, yim); + } + } + } else if ((sx >= 0) && (sy >= 0)) { + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + xre = X[i][j].v.re; + xim = X[i][j].v.im; + yre = Y[i][j].v.re; + yim = Y[i][j].v.im; + re += (fMultDiv2(xre, yre) + fMultDiv2(xim, yim)) >> (sx + sy); + im += (fMultDiv2(xim, yre) - fMultDiv2(xre, yim)) >> (sx + sy); + } + } + } else if ((sx < 0) && (sy >= 0)) { + sx = -sx; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + xre = X[i][j].v.re << sx; + xim = X[i][j].v.im << sx; + yre = Y[i][j].v.re; + yim = Y[i][j].v.im; + re += (fMultDiv2(xre, yre) + fMultDiv2(xim, yim)) >> sy; + im += (fMultDiv2(xim, yre) - fMultDiv2(xre, yim)) >> sy; + } + } + } else { + sy = -sy; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + xre = X[i][j].v.re; + xim = X[i][j].v.im; + yre = Y[i][j].v.re << sy; + yim = Y[i][j].v.im << sy; + re += (fMultDiv2(xre, yre) + fMultDiv2(xim, yim)) >> sx; + im += (fMultDiv2(xim, yre) - fMultDiv2(xre, yim)) >> sx; + } + } + } + + Z->v.re = re >> 1; + Z->v.im = im >> 1; +} + +void FDKcalcCorrelationVec(FIXP_DBL *const z, const FIXP_DBL *const pr12, + const FIXP_DBL *const p1, const FIXP_DBL *const p2, + const INT n) { + int i, s; + FIXP_DBL p12, cor; + + /* correlation */ + for (i = 0; i < n; i++) { + p12 = fMult(p1[i], p2[i]); + if (p12 > FL2FXCONST_DBL(0.0f)) { + p12 = invSqrtNorm2(p12, &s); + cor = fMult(pr12[i], p12); + z[i] = SATURATE_LEFT_SHIFT(cor, s, DFRACT_BITS); + } else { + z[i] = (FIXP_DBL)MAXVAL_DBL; + } + } +} + +void calcCoherenceVec(FIXP_DBL *const z, const FIXP_DBL *const p12r, + const FIXP_DBL *const p12i, const FIXP_DBL *const p1, + const FIXP_DBL *const p2, const INT scaleP12, + const INT scaleP, const INT n) { + int i, s, s1, s2; + FIXP_DBL coh, p12, p12ri; + + for (i = 0; i < n; i++) { + s2 = fixMin(fixMax(0, CountLeadingBits(p12r[i]) - 1), + fixMax(0, CountLeadingBits(p12i[i]) - 1)); + p12ri = sqrtFixp(fPow2Div2(p12r[i] << s2) + fPow2Div2(p12i[i] << s2)); + s1 = fixMin(fixMax(0, CountLeadingBits(p1[i]) - 1), + fixMax(0, CountLeadingBits(p2[i]) - 1)); + p12 = fMultDiv2(p1[i] << s1, p2[i] << s1); + + if (p12 > FL2FXCONST_DBL(0.0f)) { + p12 = invSqrtNorm2(p12, &s); + coh = fMult(p12ri, p12); + s = fixMax(fixMin((scaleP12 - scaleP + s + s1 - s2), DFRACT_BITS - 1), + -(DFRACT_BITS - 1)); + if (s < 0) { + z[i] = coh >> (-s); + } else { + z[i] = SATURATE_LEFT_SHIFT(coh, s, DFRACT_BITS); + } + } else { + z[i] = (FIXP_DBL)MAXVAL_DBL; + } + } +} + +void addWeightedCplxVec(FIXP_DPK *const *const Z, const FIXP_DBL *const a, + const FIXP_DPK *const *const X, const FIXP_DBL *const b, + const FIXP_DPK *const *const Y, const INT scale, + INT *const scaleCh1, const INT scaleCh2, + const UCHAR *const pParameterBand2HybridBandOffset, + const INT nParameterBands, const INT nTimeSlots, + const INT startTimeSlot) { + int pb, j, i; + int cs, s1, s2; + + /* determine maximum scale of both channels */ + cs = fixMax(*scaleCh1, scaleCh2); + s1 = cs - (*scaleCh1); + s2 = cs - scaleCh2; + + /* scalefactor 1 is updated with common scale of channel 1 and channel2 */ + *scaleCh1 = cs; + + /* scale of a and b; additional scale for fMultDiv2() */ + for (j = 0, pb = 0; pb < nParameterBands; pb++) { + FIXP_DBL aPb, bPb; + aPb = a[pb], bPb = b[pb]; + for (; j < pParameterBand2HybridBandOffset[pb]; j++) { + for (i = startTimeSlot; i < nTimeSlots; i++) { + Z[j][i].v.re = ((fMultDiv2(aPb, X[j][i].v.re) >> s1) + + (fMultDiv2(bPb, Y[j][i].v.re) >> s2)) + << (scale + 1); + Z[j][i].v.im = ((fMultDiv2(aPb, X[j][i].v.im) >> s1) + + (fMultDiv2(bPb, Y[j][i].v.im) >> s2)) + << (scale + 1); + } + } + } +} + +void FDKcalcPbScaleFactor(const FIXP_DPK *const *const x, + const UCHAR *const pParameterBand2HybridBandOffset, + INT *const outScaleFactor, const INT startTimeSlot, + const INT nTimeSlots, const INT nParamBands) { + int i, j, pb; + + /* calculate headroom */ + for (j = 0, pb = 0; pb < nParamBands; pb++) { + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + for (; j < pParameterBand2HybridBandOffset[pb]; j++) { + for (i = startTimeSlot; i < nTimeSlots; i++) { + maxVal |= fAbs(x[i][j].v.re); + maxVal |= fAbs(x[i][j].v.im); + } + } + outScaleFactor[pb] = -fixMax(0, CntLeadingZeros(maxVal) - 1); + } +} + +INT FDKcalcScaleFactor(const FIXP_DBL *const x, const FIXP_DBL *const y, + const INT n) { + int i; + + /* calculate headroom */ + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + if (x != NULL) { + for (i = 0; i < n; i++) { + maxVal |= fAbs(x[i]); + } + } + + if (y != NULL) { + for (i = 0; i < n; i++) { + maxVal |= fAbs(y[i]); + } + } + + if (maxVal == (FIXP_DBL)0) + return (-(DFRACT_BITS - 1)); + else + return (-CountLeadingBits(maxVal)); +} + +INT FDKcalcScaleFactorDPK(const FIXP_DPK *RESTRICT x, const INT startBand, + const INT bands) { + INT qs, clz; + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + + for (qs = startBand; qs < bands; qs++) { + maxVal |= fAbs(x[qs].v.re); + maxVal |= fAbs(x[qs].v.im); + } + + clz = -fixMax(0, CntLeadingZeros(maxVal) - 1); + + return (clz); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_vectorfunctions.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_vectorfunctions.h new file mode 100644 index 0000000000000..e9c4abd7bd7d6 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSACenc/src/sacenc_vectorfunctions.h @@ -0,0 +1,488 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Josef Hoepfl + + Description: Encoder Library Interface + vector functions + +*******************************************************************************/ + +/***************************************************************************** +\file +This file contains vector functions +******************************************************************************/ + +#ifndef SACENC_VECTORFUNCTIONS_H +#define SACENC_VECTORFUNCTIONS_H + +/* Includes ******************************************************************/ +#include "common_fix.h" + +/* Defines *******************************************************************/ +#define SUM_UP_STATIC_SCALE 0 +#define SUM_UP_DYNAMIC_SCALE 1 + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/** + * \brief Vector function : Sum up complex power + * + * Description : ret = sum( re{X[i]} * re{X[i]} + im{X[i]} * + * im{X[i]} ), i=0,...,n-1 ret is scaled by outScaleFactor + * + * \param const FIXP_DPK x[] + * Input: complex vector of the length n + * + * \param int scaleMode + * Input: choose static or dynamic scaling + * (SUM_UP_DYNAMIC_SCALE/SUM_UP_STATIC_SCALE) + * + * \param int inScaleFactor + * Input: determine headroom bits for the complex input vector + * + * \param int outScaleFactor + * Output: complete scaling in energy calculation + * + * \return FIXP_DBL ret + */ +FIXP_DBL sumUpCplxPow2(const FIXP_DPK *const x, const INT scaleMode, + const INT inScaleFactor, INT *const outScaleFactor, + const INT n); + +/** + * \brief Vector function : Sum up complex power + * + * Description : ret = sum( re{X[i][j]} * re{X[i][]} + + * im{X[i][]} * im{X[i][]} ), i=sDim1,...,nDim1-1 i=sDim2,...,nDim2-1 ret is + * scaled by outScaleFactor + * + * \param const FIXP_DPK x[] + * Input: complex vector of the length n + * + * \param int scaleMode + * Input: choose static or dynamic scaling + * (SUM_UP_DYNAMIC_SCALE/SUM_UP_STATIC_SCALE) + * + * \param int inScaleFactor + * Input: determine headroom bits for the complex input vector + * + * \param int outScaleFactor + * Output: complete scaling in energy calculation + * + * \param int sDim1 + * Input: start index for loop counter in dimension 1 + * + * \param int nDim1 + * Input: loop counter in dimension 1 + * + * \param int sDim2 + * Input: start index for loop counter in dimension 2 + * + * \param int nDim2 + * Input: loop counter in dimension 2 + * + * \return FIXP_DBL ret + */ +FIXP_DBL sumUpCplxPow2Dim2(const FIXP_DPK *const *const x, const INT scaleMode, + const INT inScaleFactor, INT *const outScaleFactor, + const INT sDim1, const INT nDim1, const INT sDim2, + const INT nDim2); + +/** + * \brief Vector function : Z[i] = X[i], i=0,...,n-1 + * + * Description : re{Z[i]} = re{X[i]}, i=0,...,n-1 + * im{Z[i]} = im{X[i]}, i=0,...,n-1 + * + * Copy complex vector X[] to complex vector Z[]. + * It is allowed to overlay X[] with Z[]. + * + * \param FIXP_DPK Z[] + * Output: vector of the length n + * + * \param const FIXP_DPK X[] + * Input: vector of the length n + * + * \param int n + * Input: length of vector Z[] and X[] + * + * \return void + */ +void copyCplxVec(FIXP_DPK *const Z, const FIXP_DPK *const X, const INT n); + +/** + * \brief Vector function : Z[i] = a, i=0,...,n-1 + * + * Description : re{Z[i]} = a, i=0,...,n-1 + * im{Z[i]} = a, i=0,...,n-1 + * + * Set real and imaginary part of the complex value Z to a. + * + * \param FIPX_DPK Z[] + * Output: vector of the length n + * + * \param const FIXP_DBL a + * Input: constant value + * + * \param int n + * Input: length of vector Z[] + * + * \return void + */ +void setCplxVec(FIXP_DPK *const Z, const FIXP_DBL a, const INT n); + +/** + * \brief Vector function : Calculate complex-valued result of complex + * scalar product + * + * Description : re{Z} = sum( re{X[i]} * re{Y[i]} + im{X[i]} * + * im{Y[i]}, i=0,...,n-1 ) im{Z} = sum( im{X[i]} * re{Y[i]} - re{X[i]} * + * im{Y[i]}, i=0,...,n-1 ) + * + * The function returns the complex-valued result of the complex + * scalar product at the address of Z. The result is scaled by scaleZ. + * + * \param FIXP_DPK *Z + * Output: pointer to Z + * + * \param const FIXP_DPK *const *const X + * Input: vector of the length n + * + * \param const FIXP_DPK *const *const Y + * Input: vector of the length n + * + * \param int scaleX + * Input: scalefactor of vector X[] + * + * \param int scaleY + * Input: scalefactor of vector Y[] + * + * \param int scaleZ + * Output: scalefactor of vector Z[] + * + * \param int sDim1 + * Input: start index for loop counter in dimension 1 + * + * \param int nDim1 + * Input: loop counter in dimension 1 + * + * \param int sDim2 + * Input: start index for loop counter in dimension 2 + * + * \param int nDim2 + * Input: loop counter in dimension 2 + * + * \return void + */ +void cplx_cplxScalarProduct(FIXP_DPK *const Z, const FIXP_DPK *const *const X, + const FIXP_DPK *const *const Y, const INT scaleX, + const INT scaleY, INT *const scaleZ, + const INT sDim1, const INT nDim1, const INT sDim2, + const INT nDim2); + +/** + * \brief Vector function : Calculate correlation + * + * Description : z[i] = pr12[i] / sqrt(p1[i]*p2[i]) , + * i=0,...,n-1 + * + * \param FIXP_DBL z[] + * Output: vector of length n + * + * \param const FIXP_DBL pr12[] + * Input: vector of the length n + * + * \param const FIXP_DBL p1[] + * Input: vector of the length n + * + * \param const FIXP_DBL p2[] + * Input: vector of the length n + * + * \param int n + * Input: length of vector pr12[], p1[] and p2[] + * + * \return void + */ +void FDKcalcCorrelationVec(FIXP_DBL *const z, const FIXP_DBL *const pr12, + const FIXP_DBL *const p1, const FIXP_DBL *const p2, + const INT n); + +/** + * \brief Vector function : Calculate coherence + * + * Description : z[i] = sqrt( (p12r[i]*p12r[i] + + * p12i[i]*p12i[i]) / (p1[i]*p2[i]) ), i=0,...,n-1 + * + * \param FIXP_DBL z[] + * Output: vector of length n + * + * \param const FIXP_DBL p12r[] + * Input: vector of the length n + * + * \param const FIXP_DBL p12i[] + * Input: vector of the length n + * + * \param const FIXP_DBL p1[] + * Input: vector of the length n + * + * \param const FIXP_DBL p2[] + * Input: vector of the length n + * + * \param int scaleP12[] + * Input: scalefactor of p12r and p12i + * + * \param int scaleP + * Input: scalefactor of p1 and p2 + * + * \param int n + * Input: length of vector p12r[], p12i[], p1[] and p2[] + * + * \return void + */ +void calcCoherenceVec(FIXP_DBL *const z, const FIXP_DBL *const p12r, + const FIXP_DBL *const p12i, const FIXP_DBL *const p1, + const FIXP_DBL *const p2, const INT scaleP12, + const INT scaleP, const INT n); + +/** + * \brief Vector function : Z[j][i] = a[pb] * X[j][i] + b[pb] * + * Y[j][i], j=0,...,nHybridBands-1; i=startTimeSlot,...,nTimeSlots-1; + * pb=0,...,nParameterBands-1 + * + * Description : re{Z[j][i]} = a[pb] * re{X[j][i]} + b[pb] * + * re{Y[j][i]}, j=0,...,nHybridBands-1; i=startTimeSlot,...,nTimeSlots-1; + * pb=0,...,nParameterBands-1 im{Z[j][i]} = a[pb] * im{X[j][i]} + b[pb] * + * im{Y[j][i]}, j=0,...,nHybridBands-1; + * i=startTimeSlot,...,nTimeSlots-1; pb=0,...,nParameterBands-1 + * + * It is allowed to overlay X[] or Y[] with Z[]. The scalefactor + * of channel 1 is updated with the common scalefactor of channel 1 and + * channel 2. + * + * \param FIXP_DPK **Z + * Output: vector of the length nHybridBands*nTimeSlots + * + * \param const FIXP_DBL *a + * Input: vector of length nParameterBands + * + * \param const FIXP_DPK **X + * Input: vector of the length nHybridBands*nTimeSlots + * + * \param const FIXP_DBL *b + * Input: vector of length nParameterBands + * + * \param const FIXP_DPK **Y + * Input: vector of the length nHybridBands*nTimeSlots + * + * \param int scale + * Input: scale of vector a and b + * + * \param int *scaleCh1 + * Input: scale of ch1 + * + * \param int scaleCh2 + * Input: scale of ch2 + * + * \param UCHAR *pParameterBand2HybridBandOffset + * Input: vector of length nParameterBands + * + * \param int nTimeSlots + * Input: number of time slots + * + * \param int startTimeSlot + * Input: start time slot + * + * \return void + */ +void addWeightedCplxVec(FIXP_DPK *const *const Z, const FIXP_DBL *const a, + const FIXP_DPK *const *const X, const FIXP_DBL *const b, + const FIXP_DPK *const *const Y, const INT scale, + INT *const scaleCh1, const INT scaleCh2, + const UCHAR *const pParameterBand2HybridBandOffset, + const INT nParameterBands, const INT nTimeSlots, + const INT startTimeSlot); + +/** + * \brief Vector function : Calculate the headroom of a complex vector + * in a parameter band grid + * + * \param FIXP_DPK **x + * Input: pointer to complex input vector + * + * \param UCHAR *pParameterBand2HybridBandOffset + * Input: pointer to hybrid band offsets + * + * \param int *outScaleFactor + * Input: pointer to ouput scalefactor + * + * \param int startTimeSlot + * Input: start time slot + * + * \param int nTimeSlots + * Input: number of time slot + * + * \param int nParamBands + * Input: number of parameter bands + * + * \return void + */ +void FDKcalcPbScaleFactor(const FIXP_DPK *const *const x, + const UCHAR *const pParameterBand2HybridBandOffset, + INT *const outScaleFactor, const INT startTimeSlot, + const INT nTimeSlots, const INT nParamBands); + +/** + * \brief Vector function : Calculate the common headroom of two + * sparate vectors + * + * \param FIXP_DBL *x + * Input: pointer to first input vector + * + * \param FIXP_DBL *y + * Input: pointer to second input vector + * + * \param int n + * Input: number of samples + * + * \return int headromm in bits + */ +INT FDKcalcScaleFactor(const FIXP_DBL *const x, const FIXP_DBL *const y, + const INT n); + +/** + * \brief Vector function : Calculate the headroom of a complex vector + * + * \param FIXP_DPK *x + * Input: pointer to complex input vector + * + * \param INT startBand + * Input: start band + * + * \param INT bands + * Input: number of bands + * + * \return int headromm in bits + */ +INT FDKcalcScaleFactorDPK(const FIXP_DPK *RESTRICT x, const INT startBand, + const INT bands); + +/* Function / Class Definition ***********************************************/ +template +inline void FDKmemcpy_flex(T *const dst, const INT dstStride, + const T *const src, const INT srcStride, + const INT nSamples) { + int i; + + for (i = 0; i < nSamples; i++) { + dst[i * dstStride] = src[i * srcStride]; + } +} + +template +inline void FDKmemset_flex(T *const x, const T c, const INT nSamples) { + int i; + + for (i = 0; i < nSamples; i++) { + x[i] = c; + } +} + +#endif /* SACENC_VECTORFUNCTIONS_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/include/sbrdecoder.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/include/sbrdecoder.h new file mode 100644 index 0000000000000..c09c985adea3a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/include/sbrdecoder.h @@ -0,0 +1,406 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: SBR decoder front-end prototypes and definitions. + +*******************************************************************************/ + +#ifndef SBRDECODER_H +#define SBRDECODER_H + +#include "common_fix.h" + +#include "FDK_bitstream.h" +#include "FDK_audio.h" + +#include "FDK_qmf_domain.h" + +#define SBR_DEBUG_EXTHLP \ + "\ +--- SBR ---\n\ + 0x00000010 Ancillary data and SBR-Header\n\ + 0x00000020 SBR-Side info\n\ + 0x00000040 Decoded SBR-bitstream data, e.g. envelope data\n\ + 0x00000080 SBR-Bitstream statistics\n\ + 0x00000100 Miscellaneous SBR-messages\n\ + 0x00000200 SBR-Energies and gains in the adjustor\n\ + 0x00000400 Fatal SBR errors\n\ + 0x00000800 Transposer coefficients for inverse filtering\n\ +" + +/* Capability flags */ +#define CAPF_SBR_LP \ + 0x00000001 /*!< Flag indicating library's capability of Low Power mode. */ +#define CAPF_SBR_HQ \ + 0x00000002 /*!< Flag indicating library's capability of High Quality mode. \ + */ +#define CAPF_SBR_DRM_BS \ + 0x00000004 /*!< Flag indicating library's capability to decode DRM SBR data. \ + */ +#define CAPF_SBR_CONCEALMENT \ + 0x00000008 /*!< Flag indicating library's capability to conceal erroneous \ + frames. */ +#define CAPF_SBR_DRC \ + 0x00000010 /*!< Flag indicating library's capability for Dynamic Range \ + Control. */ +#define CAPF_SBR_PS_MPEG \ + 0x00000020 /*!< Flag indicating library's capability to do MPEG Parametric \ + Stereo. */ +#define CAPF_SBR_PS_DRM \ + 0x00000040 /*!< Flag indicating library's capability to do DRM Parametric \ + Stereo. */ +#define CAPF_SBR_ELD_DOWNSCALE \ + 0x00000080 /*!< Flag indicating library's capability to do ELD decoding in \ + downscaled mode */ +#define CAPF_SBR_HBEHQ \ + 0x00000100 /*!< Flag indicating library's capability to do HQ Harmonic \ + transposing */ + +typedef enum { + SBRDEC_OK = 0, /*!< All fine. */ + /* SBRDEC_CONCEAL, */ + /* SBRDEC_NOSYNCH, */ + /* SBRDEC_ILLEGAL_PROGRAM, */ + /* SBRDEC_ILLEGAL_TAG, */ + /* SBRDEC_ILLEGAL_CHN_CONFIG, */ + /* SBRDEC_ILLEGAL_SECTION, */ + /* SBRDEC_ILLEGAL_SCFACTORS, */ + /* SBRDEC_ILLEGAL_PULSE_DATA, */ + /* SBRDEC_MAIN_PROFILE_NOT_IMPLEMENTED, */ + /* SBRDEC_GC_NOT_IMPLEMENTED, */ + /* SBRDEC_ILLEGAL_PLUS_ELE_ID, */ + SBRDEC_INVALID_ARGUMENT, /*!< */ + SBRDEC_CREATE_ERROR, /*!< */ + SBRDEC_NOT_INITIALIZED, /*!< */ + SBRDEC_MEM_ALLOC_FAILED, /*!< Memory allocation failed. Probably not enough + memory available. */ + SBRDEC_PARSE_ERROR, /*!< */ + SBRDEC_UNSUPPORTED_CONFIG, /*!< */ + SBRDEC_SET_PARAM_FAIL, /*!< */ + SBRDEC_OUTPUT_BUFFER_TOO_SMALL /*!< */ +} SBR_ERROR; + +typedef enum { + SBR_SYSTEM_BITSTREAM_DELAY, /*!< System: Switch to enable an additional SBR + bitstream delay of one frame. */ + SBR_QMF_MODE, /*!< Set QMF mode, either complex or low power. */ + SBR_LD_QMF_TIME_ALIGN, /*!< Set QMF type, either LD-MPS or CLDFB. Relevant for + ELD streams only. */ + SBR_FLUSH_DATA, /*!< Set internal state to flush the decoder with the next + process call. */ + SBR_CLEAR_HISTORY, /*!< Clear all internal states (delay lines, QMF states, + ...). */ + SBR_BS_INTERRUPTION /*!< Signal bit stream interruption. Value is ignored. */ + , + SBR_SKIP_QMF /*!< Enable skipping of QMF step: 1 skip analysis, 2 skip + synthesis */ +} SBRDEC_PARAM; + +typedef struct SBR_DECODER_INSTANCE *HANDLE_SBRDECODER; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Allocates and initializes one SBR decoder instance. + * \param pSelf Pointer to where a SBR decoder handle is copied into. + * \param pQmfDomain Pointer to QMF domain data structure. + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_Open(HANDLE_SBRDECODER *pSelf, + HANDLE_FDK_QMF_DOMAIN pQmfDomain); + +/** + * \brief Initialize a SBR decoder runtime instance. Must be called before + * decoding starts. + * + * \param self Handle to a SBR decoder instance. + * \param sampleRateIn Input samplerate of the SBR decoder instance. + * \param sampleRateOut Output samplerate of the SBR decoder instance. + * \param samplesPerFrame Number of samples per frames. + * \param coreCodec Audio Object Type (AOT) of the core codec. + * \param elementID Table with MPEG-4 element Ids in canonical order. + * \param elementIndex SBR element index + * \param harmonicSBR + * \param stereoConfigIndex + * \param downscaleFactor ELD downscale factor + * \param configMode Table with MPEG-4 element Ids in canonical order. + * \param configChanged Flag that enforces a complete decoder reset. + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_InitElement( + HANDLE_SBRDECODER self, const int sampleRateIn, const int sampleRateOut, + const int samplesPerFrame, const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const int elementIndex, + const UCHAR harmonicSBR, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, const INT downscaleFactor); + +/** + * \brief Free config dependent SBR memory. + * \param self SBR decoder instance handle + */ +SBR_ERROR sbrDecoder_FreeMem(HANDLE_SBRDECODER *self); + +/** + * \brief pass out of band SBR header to SBR decoder + * + * \param self Handle to a SBR decoder instance. + * \param hBs bit stream handle data source. + * \param sampleRateIn SBR input sampling rate + * \param sampleRateOut SBR output sampling rate + * \param samplesPerFrame frame length + * \param elementID SBR element ID. + * \param elementIndex SBR element index. + * \param harmonicSBR + * \param stereoConfigIndex + * \param downscaleFactor ELD downscale factor + * + * \return Error code. + */ +INT sbrDecoder_Header(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const INT elementIndex, + const UCHAR harmonicSBR, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor); + +/** + * \brief Set a parameter of the SBR decoder runtime instance. + * \param self SBR decoder handle. + * \param param Parameter which will be set if successfull. + * \param value New parameter value. + * \return Error code. + */ +SBR_ERROR sbrDecoder_SetParam(HANDLE_SBRDECODER self, const SBRDEC_PARAM param, + const INT value); + +/** + * \brief Feed DRC channel data into a SBR decoder runtime instance. + * + * \param self SBR decoder handle. + * \param ch Channel number to which the DRC data is + * associated to. + * \param numBands Number of DRC bands. + * \param pNextFact_mag Pointer to a table with the DRC factor + * magnitudes. + * \param nextFact_exp Exponent for all DRC factors. + * \param drcInterpolationScheme DRC interpolation scheme. + * \param winSequence Window sequence from core coder (eight short + * or one long window). + * \param pBandTop Pointer to a table with the top borders for + * all DRC bands. + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_drcFeedChannel(HANDLE_SBRDECODER self, INT ch, + UINT numBands, FIXP_DBL *pNextFact_mag, + INT nextFact_exp, + SHORT drcInterpolationScheme, + UCHAR winSequence, USHORT *pBandTop); + +/** + * \brief Disable SBR DRC for a certain channel. + * + * \param hSbrDecoder SBR decoder handle. + * \param ch Number of the channel that has to be disabled. + * + * \return None. + */ +void sbrDecoder_drcDisable(HANDLE_SBRDECODER self, INT ch); + +/** + * \brief Parse one SBR element data extension data block. The bit stream + * position will be placed at the end of the SBR payload block. The remaining + * bits will be returned into *count if a payload length is given + * (byPayLen > 0). If no SBR payload length is given (bsPayLen < 0) then + * the bit stream position on return will be random after this function + * call in case of errors, and any further decoding will be completely + * pointless. This function accepts either normal ordered SBR data or reverse + * ordered DRM SBR data. + * + * \param self SBR decoder handle. + * \param hBs Bit stream handle as data source. + * \param count Pointer to an integer where the amount of parsed SBR + * payload bits is stored into. + * \param bsPayLen If > 0 this value is the SBR payload length. If < 0, + * the SBR payload length is unknown. + * \param flags CRC flag (0: EXT_SBR_DATA; 1: EXT_SBR_DATA_CRC) + * \param prev_element Previous MPEG-4 element ID. + * \param element_index Index of the current element. + * \param acFlags Audio codec flags + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_Parse(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs, + UCHAR *pDrmBsBuffer, USHORT drmBsBufferSize, + int *count, int bsPayLen, int crcFlag, + MP4_ELEMENT_ID prev_element, int element_index, + UINT acFlags, UINT acElFlags[]); + +/** + * \brief This function decodes the given SBR bitstreams and applies SBR to the + * given time data. + * + * SBR-processing works InPlace. I.e. the calling function has to provide + * a time domain buffer timeData which can hold the completely decoded + * result. + * + * Left and right channel are read and stored according to the + * interleaving flag, frame length and number of channels. + * + * \param self Handle of an open SBR decoder instance. + * \param hSbrBs SBR Bitstream handle. + * \param input Pointer to input data. + * \param timeData Pointer to upsampled output data. + * \param timeDataSize Size of timeData. + * \param numChannels Pointer to a buffer holding the number of channels in + * time data buffer. + * \param sampleRate Output samplerate. + * \param channelMapping Channel mapping indices. + * \param coreDecodedOk Flag indicating if the core decoder did not find any + * error (0: core decoder found errors, 1: no errors). + * \param psDecoded Pointer to a buffer holding a flag. Input: PS is + * possible, Output: PS has been rendered. + * \param inDataHeadroom Headroom of the SBR input time signal to prevent + * clipping. + * \param outDataHeadroom Pointer to headroom of the SBR output time signal to + * prevent clipping. + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, LONG *input, LONG *timeData, + const int timeDataSize, int *numChannels, + int *sampleRate, + const FDK_channelMapDescr *const mapDescr, + const int mapIdx, const int coreDecodedOk, + UCHAR *psDecoded, const INT inDataHeadroom, + INT *outDataHeadroom); + +/** + * \brief Close SBR decoder instance and free memory. + * \param self SBR decoder handle. + * \return Error Code. + */ +SBR_ERROR sbrDecoder_Close(HANDLE_SBRDECODER *self); + +/** + * \brief Get SBR decoder library information. + * \param info Pointer to a LIB_INFO struct, where library information is + * written to. + * \return 0 on success, -1 if invalid handle or if no free element is + * available to write information to. + */ +INT sbrDecoder_GetLibInfo(LIB_INFO *info); + +/** + * \brief Determine the modules output signal delay in samples. + * \param self SBR decoder handle. + * \return The number of samples signal delay added by the module. + */ +UINT sbrDecoder_GetDelay(const HANDLE_SBRDECODER self); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/HFgen_preFlat.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/HFgen_preFlat.cpp new file mode 100644 index 0000000000000..ad4caba8d562b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/HFgen_preFlat.cpp @@ -0,0 +1,994 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): Oliver Moser, Manuel Jander, Matthias Hildenbrand + + Description: QMF frequency pre-whitening for SBR. + In the documentation the terms "scale factor" and "exponent" + mean the same. Variables containing such information have + the suffix "_sf". + +*******************************************************************************/ + +#include "HFgen_preFlat.h" + +#define POLY_ORDER 3 +#define MAXLOWBANDS 32 +#define LOG10FAC 0.752574989159953f /* == 10/log2(10) * 2^-2 */ +#define LOG10FAC_INV 0.664385618977472f /* == log2(10)/20 * 2^2 */ + +#define FIXP_CHB FIXP_SGL /* STB sinus Tab used in transformation */ +#define CHC(a) (FX_DBL2FXCONST_SGL(a)) +#define FX_CHB2FX_DBL(a) FX_SGL2FX_DBL(a) + +typedef struct backsubst_data { + FIXP_CHB Lnorm1d[3]; /*!< Normalized L matrix */ + SCHAR Lnorm1d_sf[3]; + FIXP_CHB Lnormii + [3]; /*!< The diagonal data points [i][i] of the normalized L matrix */ + SCHAR Lnormii_sf[3]; + FIXP_CHB Bmul0 + [4]; /*!< To normalize L*x=b, Bmul0 is what we need to multiply b with. */ + SCHAR Bmul0_sf[4]; + FIXP_CHB LnormInv1d[6]; /*!< Normalized inverted L matrix (L') */ + SCHAR LnormInv1d_sf[6]; + FIXP_CHB + Bmul1[4]; /*!< To normalize L'*x=b, Bmul1 is what we need to multiply b + with. */ + SCHAR Bmul1_sf[4]; +} backsubst_data; + +/* for each element n do, f(n) = trunc(log2(n))+1 */ +const UCHAR getLog2[32] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}; + +/** \def BSD_IDX_OFFSET + * + * bsd[] begins at index 0 with data for numBands=5. The correct bsd[] is + * indexed like bsd[numBands-BSD_IDX_OFFSET]. + */ +#define BSD_IDX_OFFSET 5 + +#define N_NUMBANDS \ + MAXLOWBANDS - BSD_IDX_OFFSET + \ + 1 /*!< Number of backsubst_data elements in bsd */ + +const backsubst_data bsd[N_NUMBANDS] = { + { + /* numBands=5 */ + {CHC(0x66c85a52), CHC(0x4278e587), CHC(0x697dcaff)}, + {-1, 0, 0}, + {CHC(0x66a61789), CHC(0x5253b8e3), CHC(0x5addad81)}, + {3, 4, 1}, + {CHC(0x7525ee90), CHC(0x6e2a1210), CHC(0x6523bb40), CHC(0x59822ead)}, + {-6, -4, -2, 0}, + {CHC(0x609e4cad), CHC(0x59c7e312), CHC(0x681eecac), CHC(0x440ea893), + CHC(0x4a214bb3), CHC(0x53c345a1)}, + {1, 0, -1, -1, -3, -5}, + {CHC(0x7525ee90), CHC(0x58587936), CHC(0x410d0b38), CHC(0x7f1519d6)}, + {-6, -1, 2, 0}, + }, + { + /* numBands=6 */ + {CHC(0x68943285), CHC(0x4841d2c3), CHC(0x6a6214c7)}, + {-1, 0, 0}, + {CHC(0x63c5923e), CHC(0x4e906e18), CHC(0x6285af8a)}, + {3, 4, 1}, + {CHC(0x7263940b), CHC(0x424a69a5), CHC(0x4ae8383a), CHC(0x517b7730)}, + {-7, -4, -2, 0}, + {CHC(0x518aee5f), CHC(0x4823a096), CHC(0x43764a39), CHC(0x6e6faf23), + CHC(0x61bba44f), CHC(0x59d8b132)}, + {1, 0, -1, -2, -4, -6}, + {CHC(0x7263940b), CHC(0x6757bff2), CHC(0x5bf40fe0), CHC(0x7d6f4292)}, + {-7, -2, 1, 0}, + }, + { + /* numBands=7 */ + {CHC(0x699b4c3c), CHC(0x4b8b702f), CHC(0x6ae51a4f)}, + {-1, 0, 0}, + {CHC(0x623a7f49), CHC(0x4ccc91fc), CHC(0x68f048dd)}, + {3, 4, 1}, + {CHC(0x7e6ebe18), CHC(0x5701daf2), CHC(0x74a8198b), CHC(0x4b399aa1)}, + {-8, -5, -3, 0}, + {CHC(0x464a64a6), CHC(0x78e42633), CHC(0x5ee174ba), CHC(0x5d0008c8), + CHC(0x455cff0f), CHC(0x6b9100e7)}, + {1, -1, -2, -2, -4, -7}, + {CHC(0x7e6ebe18), CHC(0x42c52efe), CHC(0x45fe401f), CHC(0x7b5808ef)}, + {-8, -2, 1, 0}, + }, + { + /* numBands=8 */ + {CHC(0x6a3fd9b4), CHC(0x4d99823f), CHC(0x6b372a94)}, + {-1, 0, 0}, + {CHC(0x614c6ef7), CHC(0x4bd06699), CHC(0x6e59cfca)}, + {3, 4, 1}, + {CHC(0x4c389cc5), CHC(0x79686681), CHC(0x5e2544c2), CHC(0x46305b43)}, + {-8, -6, -3, 0}, + {CHC(0x7b4ca7c6), CHC(0x68270ac5), CHC(0x467c644c), CHC(0x505c1b0f), + CHC(0x67a14778), CHC(0x45801767)}, + {0, -1, -2, -2, -5, -7}, + {CHC(0x4c389cc5), CHC(0x5c499ceb), CHC(0x6f863c9f), CHC(0x79059bfc)}, + {-8, -3, 0, 0}, + }, + { + /* numBands=9 */ + {CHC(0x6aad9988), CHC(0x4ef8ac18), CHC(0x6b6df116)}, + {-1, 0, 0}, + {CHC(0x60b159b0), CHC(0x4b33f772), CHC(0x72f5573d)}, + {3, 4, 1}, + {CHC(0x6206cb18), CHC(0x58a7d8dc), CHC(0x4e0b2d0b), CHC(0x4207ad84)}, + {-9, -6, -3, 0}, + {CHC(0x6dadadae), CHC(0x5b8b2cfc), CHC(0x6cf61db2), CHC(0x46c3c90b), + CHC(0x506314ea), CHC(0x5f034acd)}, + {0, -1, -3, -2, -5, -8}, + {CHC(0x6206cb18), CHC(0x42f8b8de), CHC(0x5bb4776f), CHC(0x769acc79)}, + {-9, -3, 0, 0}, + }, + { + /* numBands=10 */ + {CHC(0x6afa7252), CHC(0x4feed3ed), CHC(0x6b94504d)}, + {-1, 0, 0}, + {CHC(0x60467899), CHC(0x4acbafba), CHC(0x76eb327f)}, + {3, 4, 1}, + {CHC(0x42415b15), CHC(0x431080da), CHC(0x420f1c32), CHC(0x7d0c1aeb)}, + {-9, -6, -3, -1}, + {CHC(0x62b2c7a4), CHC(0x51b040a6), CHC(0x56caddb4), CHC(0x7e74a2c8), + CHC(0x4030adf5), CHC(0x43d1dc4f)}, + {0, -1, -3, -3, -5, -8}, + {CHC(0x42415b15), CHC(0x64e299b3), CHC(0x4d33b5e8), CHC(0x742cee5f)}, + {-9, -4, 0, 0}, + }, + { + /* numBands=11 */ + {CHC(0x6b3258bb), CHC(0x50a21233), CHC(0x6bb03c19)}, + {-1, 0, 0}, + {CHC(0x5ff997c6), CHC(0x4a82706e), CHC(0x7a5aae36)}, + {3, 4, 1}, + {CHC(0x5d2fb4fb), CHC(0x685bddd8), CHC(0x71b5e983), CHC(0x7708c90b)}, + {-10, -7, -4, -1}, + {CHC(0x59aceea2), CHC(0x49c428a0), CHC(0x46ca5527), CHC(0x724be884), + CHC(0x68e586da), CHC(0x643485b6)}, + {0, -1, -3, -3, -6, -9}, + {CHC(0x5d2fb4fb), CHC(0x4e3fad1a), CHC(0x42310ba2), CHC(0x71c8b3ce)}, + {-10, -4, 0, 0}, + }, + { + /* numBands=12 */ + {CHC(0x6b5c4726), CHC(0x5128a4a8), CHC(0x6bc52ee1)}, + {-1, 0, 0}, + {CHC(0x5fc06618), CHC(0x4a4ce559), CHC(0x7d5c16e9)}, + {3, 4, 1}, + {CHC(0x43af8342), CHC(0x531533d3), CHC(0x633660a6), CHC(0x71ce6052)}, + {-10, -7, -4, -1}, + {CHC(0x522373d7), CHC(0x434150cb), CHC(0x75b58afc), CHC(0x68474f2d), + CHC(0x575348a5), CHC(0x4c20973f)}, + {0, -1, -4, -3, -6, -9}, + {CHC(0x43af8342), CHC(0x7c4d3d11), CHC(0x732e13db), CHC(0x6f756ac4)}, + {-10, -5, -1, 0}, + }, + { + /* numBands=13 */ + {CHC(0x6b7c8953), CHC(0x51903fcd), CHC(0x6bd54d2e)}, + {-1, 0, 0}, + {CHC(0x5f94abf0), CHC(0x4a2480fa), CHC(0x40013553)}, + {3, 4, 2}, + {CHC(0x6501236e), CHC(0x436b9c4e), CHC(0x578d7881), CHC(0x6d34f92e)}, + {-11, -7, -4, -1}, + {CHC(0x4bc0e2b2), CHC(0x7b9d12ac), CHC(0x636c1c1b), CHC(0x5fe15c2b), + CHC(0x49d54879), CHC(0x7662cfa5)}, + {0, -2, -4, -3, -6, -10}, + {CHC(0x6501236e), CHC(0x64b059fe), CHC(0x656d8359), CHC(0x6d370900)}, + {-11, -5, -1, 0}, + }, + { + /* numBands=14 */ + {CHC(0x6b95e276), CHC(0x51e1b637), CHC(0x6be1f7ed)}, + {-1, 0, 0}, + {CHC(0x5f727a1c), CHC(0x4a053e9c), CHC(0x412e528c)}, + {3, 4, 2}, + {CHC(0x4d178bd4), CHC(0x6f33b4e8), CHC(0x4e028f7f), CHC(0x691ee104)}, + {-11, -8, -4, -1}, + {CHC(0x46473d3f), CHC(0x725bd0a6), CHC(0x55199885), CHC(0x58bcc56b), + CHC(0x7e7e6288), CHC(0x5ddef6eb)}, + {0, -2, -4, -3, -7, -10}, + {CHC(0x4d178bd4), CHC(0x52ebd467), CHC(0x5a395a6e), CHC(0x6b0f724f)}, + {-11, -5, -1, 0}, + }, + { + /* numBands=15 */ + {CHC(0x6baa2a22), CHC(0x5222eb91), CHC(0x6bec1a86)}, + {-1, 0, 0}, + {CHC(0x5f57393b), CHC(0x49ec8934), CHC(0x423b5b58)}, + {3, 4, 2}, + {CHC(0x77fd2486), CHC(0x5cfbdf2c), CHC(0x46153bd1), CHC(0x65757ed9)}, + {-12, -8, -4, -1}, + {CHC(0x41888ee6), CHC(0x6a661db3), CHC(0x49abc8c8), CHC(0x52965848), + CHC(0x6d9301b7), CHC(0x4bb04721)}, + {0, -2, -4, -3, -7, -10}, + {CHC(0x77fd2486), CHC(0x45424c68), CHC(0x50f33cc6), CHC(0x68ff43f0)}, + {-12, -5, -1, 0}, + }, + { + /* numBands=16 */ + {CHC(0x6bbaa499), CHC(0x5257ed94), CHC(0x6bf456e4)}, + {-1, 0, 0}, + {CHC(0x5f412594), CHC(0x49d8a766), CHC(0x432d1dbd)}, + {3, 4, 2}, + {CHC(0x5ef5cfde), CHC(0x4eafcd2d), CHC(0x7ed36893), CHC(0x62274b45)}, + {-12, -8, -5, -1}, + {CHC(0x7ac438f5), CHC(0x637aab21), CHC(0x4067617a), CHC(0x4d3c6ec7), + CHC(0x5fd6e0dd), CHC(0x7bd5f024)}, + {-1, -2, -4, -3, -7, -11}, + {CHC(0x5ef5cfde), CHC(0x751d0d4f), CHC(0x492b3c41), CHC(0x67065409)}, + {-12, -6, -1, 0}, + }, + { + /* numBands=17 */ + {CHC(0x6bc836c9), CHC(0x5283997e), CHC(0x6bfb1f5e)}, + {-1, 0, 0}, + {CHC(0x5f2f02b6), CHC(0x49c868e9), CHC(0x44078151)}, + {3, 4, 2}, + {CHC(0x4c43b65a), CHC(0x4349dcf6), CHC(0x73799e2d), CHC(0x5f267274)}, + {-12, -8, -5, -1}, + {CHC(0x73726394), CHC(0x5d68511a), CHC(0x7191bbcc), CHC(0x48898c70), + CHC(0x548956e1), CHC(0x66981ce8)}, + {-1, -2, -5, -3, -7, -11}, + {CHC(0x4c43b65a), CHC(0x64131116), CHC(0x429028e2), CHC(0x65240211)}, + {-12, -6, -1, 0}, + }, + { + /* numBands=18 */ + {CHC(0x6bd3860d), CHC(0x52a80156), CHC(0x6c00c68d)}, + {-1, 0, 0}, + {CHC(0x5f1fed86), CHC(0x49baf636), CHC(0x44cdb9dc)}, + {3, 4, 2}, + {CHC(0x7c189389), CHC(0x742666d8), CHC(0x69b8c776), CHC(0x5c67e27d)}, + {-13, -9, -5, -1}, + {CHC(0x6cf1ea76), CHC(0x58095703), CHC(0x64e351a9), CHC(0x4460da90), + CHC(0x4b1f8083), CHC(0x55f2d3e1)}, + {-1, -2, -5, -3, -7, -11}, + {CHC(0x7c189389), CHC(0x5651792a), CHC(0x79cb9b3d), CHC(0x635769c0)}, + {-13, -6, -2, 0}, + }, + { + /* numBands=19 */ + {CHC(0x6bdd0c40), CHC(0x52c6abf6), CHC(0x6c058950)}, + {-1, 0, 0}, + {CHC(0x5f133f88), CHC(0x49afb305), CHC(0x45826d73)}, + {3, 4, 2}, + {CHC(0x6621a164), CHC(0x6512528e), CHC(0x61449fc8), CHC(0x59e2a0c0)}, + {-13, -9, -5, -1}, + {CHC(0x6721cadb), CHC(0x53404cd4), CHC(0x5a389e91), CHC(0x40abcbd2), + CHC(0x43332f01), CHC(0x48b82e46)}, + {-1, -2, -5, -3, -7, -11}, + {CHC(0x6621a164), CHC(0x4b12cc28), CHC(0x6ffd4df8), CHC(0x619f835e)}, + {-13, -6, -2, 0}, + }, + { + /* numBands=20 */ + {CHC(0x6be524c5), CHC(0x52e0beb3), CHC(0x6c099552)}, + {-1, 0, 0}, + {CHC(0x5f087c68), CHC(0x49a62bb5), CHC(0x4627d175)}, + {3, 4, 2}, + {CHC(0x54ec6afe), CHC(0x58991a42), CHC(0x59e23e8c), CHC(0x578f4ef4)}, + {-13, -9, -5, -1}, + {CHC(0x61e78f6f), CHC(0x4ef5e1e9), CHC(0x5129c3b8), CHC(0x7ab0f7b2), + CHC(0x78efb076), CHC(0x7c2567ea)}, + {-1, -2, -5, -4, -8, -12}, + {CHC(0x54ec6afe), CHC(0x41c7812c), CHC(0x676f6f8d), CHC(0x5ffb383f)}, + {-13, -6, -2, 0}, + }, + { + /* numBands=21 */ + {CHC(0x6bec1542), CHC(0x52f71929), CHC(0x6c0d0d5e)}, + {-1, 0, 0}, + {CHC(0x5eff45c5), CHC(0x499e092d), CHC(0x46bfc0c9)}, + {3, 4, 2}, + {CHC(0x47457a78), CHC(0x4e2d99b3), CHC(0x53637ea5), CHC(0x5567d0e9)}, + {-13, -9, -5, -1}, + {CHC(0x5d2dc61b), CHC(0x4b1760c8), CHC(0x4967cf39), CHC(0x74b113d8), + CHC(0x6d6676b6), CHC(0x6ad114e9)}, + {-1, -2, -5, -4, -8, -12}, + {CHC(0x47457a78), CHC(0x740accaa), CHC(0x5feb6609), CHC(0x5e696f95)}, + {-13, -7, -2, 0}, + }, + { + /* numBands=22 */ + {CHC(0x6bf21387), CHC(0x530a683c), CHC(0x6c100c59)}, + {-1, 0, 0}, + {CHC(0x5ef752ea), CHC(0x499708c6), CHC(0x474bcd1b)}, + {3, 4, 2}, + {CHC(0x78a21ab7), CHC(0x45658aec), CHC(0x4da3c4fe), CHC(0x5367094b)}, + {-14, -9, -5, -1}, + {CHC(0x58e2df6a), CHC(0x4795990e), CHC(0x42b5e0f7), CHC(0x6f408c64), + CHC(0x6370bebf), CHC(0x5c91ca85)}, + {-1, -2, -5, -4, -8, -12}, + {CHC(0x78a21ab7), CHC(0x66f951d6), CHC(0x594605bb), CHC(0x5ce91657)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=23 */ + {CHC(0x6bf749b2), CHC(0x531b3348), CHC(0x6c12a750)}, + {-1, 0, 0}, + {CHC(0x5ef06b17), CHC(0x4990f6c9), CHC(0x47cd4c5b)}, + {3, 4, 2}, + {CHC(0x66dede36), CHC(0x7bdf90a9), CHC(0x4885b2b9), CHC(0x5188a6b7)}, + {-14, -10, -5, -1}, + {CHC(0x54f85812), CHC(0x446414ae), CHC(0x79c8d519), CHC(0x6a4c2f31), + CHC(0x5ac8325f), CHC(0x50bf9200)}, + {-1, -2, -6, -4, -8, -12}, + {CHC(0x66dede36), CHC(0x5be0d90e), CHC(0x535cc453), CHC(0x5b7923f0)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=24 */ + {CHC(0x6bfbd91d), CHC(0x5329e580), CHC(0x6c14eeed)}, + {-1, 0, 0}, + {CHC(0x5eea6179), CHC(0x498baa90), CHC(0x4845635d)}, + {3, 4, 2}, + {CHC(0x58559b7e), CHC(0x6f1b231f), CHC(0x43f1789b), CHC(0x4fc8fcb8)}, + {-14, -10, -5, -1}, + {CHC(0x51621775), CHC(0x417881a3), CHC(0x6f9ba9b6), CHC(0x65c412b2), + CHC(0x53352c61), CHC(0x46db9caf)}, + {-1, -2, -6, -4, -8, -12}, + {CHC(0x58559b7e), CHC(0x52636003), CHC(0x4e13b316), CHC(0x5a189cdf)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=25 */ + {CHC(0x6bffdc73), CHC(0x5336d4af), CHC(0x6c16f084)}, + {-1, 0, 0}, + {CHC(0x5ee51249), CHC(0x498703cc), CHC(0x48b50e4f)}, + {3, 4, 2}, + {CHC(0x4c5616cf), CHC(0x641b9fad), CHC(0x7fa735e0), CHC(0x4e24e57a)}, + {-14, -10, -6, -1}, + {CHC(0x4e15f47a), CHC(0x7d9481d6), CHC(0x66a82f8a), CHC(0x619ae971), + CHC(0x4c8b2f5f), CHC(0x7d09ec11)}, + {-1, -3, -6, -4, -8, -13}, + {CHC(0x4c5616cf), CHC(0x4a3770fb), CHC(0x495402de), CHC(0x58c693fa)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=26 */ + {CHC(0x6c036943), CHC(0x53424625), CHC(0x6c18b6dc)}, + {-1, 0, 0}, + {CHC(0x5ee060aa), CHC(0x4982e88a), CHC(0x491d277f)}, + {3, 4, 2}, + {CHC(0x425ada5b), CHC(0x5a9368ac), CHC(0x78380a42), CHC(0x4c99aa05)}, + {-14, -10, -6, -1}, + {CHC(0x4b0b569c), CHC(0x78a420da), CHC(0x5ebdf203), CHC(0x5dc57e63), + CHC(0x46a650ff), CHC(0x6ee13fb8)}, + {-1, -3, -6, -4, -8, -13}, + {CHC(0x425ada5b), CHC(0x4323073c), CHC(0x450ae92b), CHC(0x57822ad5)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=27 */ + {CHC(0x6c06911a), CHC(0x534c7261), CHC(0x6c1a4aba)}, + {-1, 0, 0}, + {CHC(0x5edc3524), CHC(0x497f43c0), CHC(0x497e6cd8)}, + {3, 4, 2}, + {CHC(0x73fb550e), CHC(0x5244894f), CHC(0x717aad78), CHC(0x4b24ef6c)}, + {-15, -10, -6, -1}, + {CHC(0x483aebe4), CHC(0x74139116), CHC(0x57b58037), CHC(0x5a3a4f3c), + CHC(0x416950fe), CHC(0x62c7f4f2)}, + {-1, -3, -6, -4, -8, -13}, + {CHC(0x73fb550e), CHC(0x79efb994), CHC(0x4128cab7), CHC(0x564a919a)}, + {-15, -8, -2, 0}, + }, + { + /* numBands=28 */ + {CHC(0x6c096264), CHC(0x535587cd), CHC(0x6c1bb355)}, + {-1, 0, 0}, + {CHC(0x5ed87c76), CHC(0x497c0439), CHC(0x49d98452)}, + {3, 4, 2}, + {CHC(0x65dec5bf), CHC(0x4afd1ba3), CHC(0x6b58b4b3), CHC(0x49c4a7b0)}, + {-15, -10, -6, -1}, + {CHC(0x459e6eb1), CHC(0x6fd850b7), CHC(0x516e7be9), CHC(0x56f13d05), + CHC(0x79785594), CHC(0x58617de7)}, + {-1, -3, -6, -4, -9, -13}, + {CHC(0x65dec5bf), CHC(0x6f2168aa), CHC(0x7b41310f), CHC(0x551f0692)}, + {-15, -8, -3, 0}, + }, + { + /* numBands=29 */ + {CHC(0x6c0be913), CHC(0x535dacd5), CHC(0x6c1cf6a3)}, + {-1, 0, 0}, + {CHC(0x5ed526b4), CHC(0x49791bc5), CHC(0x4a2eff99)}, + {3, 4, 2}, + {CHC(0x59e44afe), CHC(0x44949ada), CHC(0x65bf36f5), CHC(0x487705a0)}, + {-15, -10, -6, -1}, + {CHC(0x43307779), CHC(0x6be959c4), CHC(0x4bce2122), CHC(0x53e34d89), + CHC(0x7115ff82), CHC(0x4f6421a1)}, + {-1, -3, -6, -4, -9, -13}, + {CHC(0x59e44afe), CHC(0x659eab7d), CHC(0x74cea459), CHC(0x53fed574)}, + {-15, -8, -3, 0}, + }, + { + /* numBands=30 */ + {CHC(0x6c0e2f17), CHC(0x53650181), CHC(0x6c1e199d)}, + {-1, 0, 0}, + {CHC(0x5ed2269f), CHC(0x49767e9e), CHC(0x4a7f5f0b)}, + {3, 4, 2}, + {CHC(0x4faa4ae6), CHC(0x7dd3bf11), CHC(0x609e2732), CHC(0x473a72e9)}, + {-15, -11, -6, -1}, + {CHC(0x40ec57c6), CHC(0x683ee147), CHC(0x46be261d), CHC(0x510a7983), + CHC(0x698a84cb), CHC(0x4794a927)}, + {-1, -3, -6, -4, -9, -13}, + {CHC(0x4faa4ae6), CHC(0x5d3615ad), CHC(0x6ee74773), CHC(0x52e956a1)}, + {-15, -8, -3, 0}, + }, + { + /* numBands=31 */ + {CHC(0x6c103cc9), CHC(0x536ba0ac), CHC(0x6c1f2070)}, + {-1, 0, 0}, + {CHC(0x5ecf711e), CHC(0x497422ea), CHC(0x4acb1438)}, + {3, 4, 2}, + {CHC(0x46e322ad), CHC(0x73c32f3c), CHC(0x5be7d172), CHC(0x460d8800)}, + {-15, -11, -6, -1}, + {CHC(0x7d9bf8ad), CHC(0x64d22351), CHC(0x422bdc81), CHC(0x4e6184aa), + CHC(0x62ba2375), CHC(0x40c325de)}, + {-2, -3, -6, -4, -9, -13}, + {CHC(0x46e322ad), CHC(0x55bef2a3), CHC(0x697b3135), CHC(0x51ddee4d)}, + {-15, -8, -3, 0}, + }, + { + // numBands=32 + {CHC(0x6c121933), CHC(0x5371a104), CHC(0x6c200ea0)}, + {-1, 0, 0}, + {CHC(0x5eccfcd3), CHC(0x49720060), CHC(0x4b1283f0)}, + {3, 4, 2}, + {CHC(0x7ea12a52), CHC(0x6aca3303), CHC(0x579072bf), CHC(0x44ef056e)}, + {-16, -11, -6, -1}, + {CHC(0x79a3a9ab), CHC(0x619d38fc), CHC(0x7c0f0734), CHC(0x4be3dd5d), + CHC(0x5c8d7163), CHC(0x7591065f)}, + {-2, -3, -7, -4, -9, -14}, + {CHC(0x7ea12a52), CHC(0x4f1782a6), CHC(0x647cbcb2), CHC(0x50dc0bb1)}, + {-16, -8, -3, 0}, + }, +}; + +/** \def SUM_SAFETY + * + * SUM_SAFTEY defines the bits needed to right-shift every summand in + * order to be overflow-safe. In the two backsubst functions we sum up 4 + * values. Since one of which is definitely not MAXVAL_DBL (the L[x][y]), + * we spare just 2 safety bits instead of 3. + */ +#define SUM_SAFETY 2 + +/** + * \brief Solves L*x=b via backsubstitution according to the following + * structure: + * + * x[0] = b[0]; + * x[1] = (b[1] - x[0]) / L[1][1]; + * x[2] = (b[2] - x[1]*L[2][1] - x[0]) / L[2][2]; + * x[3] = (b[3] - x[2]*L[3][2] - x[1]*L[3][1] - x[0]) / L[3][3]; + * + * \param[in] numBands SBR crossover band index + * \param[in] b the b in L*x=b (one-dimensional) + * \param[out] x output polynomial coefficients (mantissa) + * \param[out] x_sf exponents of x[] + */ +static void backsubst_fw(const int numBands, const FIXP_DBL *const b, + FIXP_DBL *RESTRICT x, int *RESTRICT x_sf) { + int i, k; + int m; /* the trip counter that indexes incrementally through Lnorm1d[] */ + + const FIXP_CHB *RESTRICT pLnorm1d = bsd[numBands - BSD_IDX_OFFSET].Lnorm1d; + const SCHAR *RESTRICT pLnorm1d_sf = bsd[numBands - BSD_IDX_OFFSET].Lnorm1d_sf; + const FIXP_CHB *RESTRICT pLnormii = bsd[numBands - BSD_IDX_OFFSET].Lnormii; + const SCHAR *RESTRICT pLnormii_sf = bsd[numBands - BSD_IDX_OFFSET].Lnormii_sf; + + x[0] = b[0]; + + for (i = 1, m = 0; i <= POLY_ORDER; ++i) { + FIXP_DBL sum = b[i] >> SUM_SAFETY; + int sum_sf = x_sf[i]; + for (k = i - 1; k > 0; --k, ++m) { + int e; + FIXP_DBL mult = fMultNorm(FX_CHB2FX_DBL(pLnorm1d[m]), x[k], &e); + int mult_sf = pLnorm1d_sf[m] + x_sf[k] + e; + + /* check if the new summand mult has a different sf than the sum currently + * has */ + int diff = mult_sf - sum_sf; + + if (diff > 0) { + /* yes, and it requires the sum to be adjusted (scaled down) */ + sum >>= diff; + sum_sf = mult_sf; + } else if (diff < 0) { + /* yes, but here mult needs to be scaled down */ + mult >>= -diff; + } + sum -= (mult >> SUM_SAFETY); + } + + /* - x[0] */ + if (x_sf[0] > sum_sf) { + sum >>= (x_sf[0] - sum_sf); + sum_sf = x_sf[0]; + } + sum -= (x[0] >> (sum_sf - x_sf[0] + SUM_SAFETY)); + + /* instead of the division /L[i][i], we multiply by the inverse */ + int e; + x[i] = fMultNorm(sum, FX_CHB2FX_DBL(pLnormii[i - 1]), &e); + x_sf[i] = sum_sf + pLnormii_sf[i - 1] + e + SUM_SAFETY; + } +} + +/** + * \brief Solves L*x=b via backsubstitution according to the following + * structure: + * + * x[3] = b[3]; + * x[2] = b[2] - L[2][3]*x[3]; + * x[1] = b[1] - L[1][2]*x[2] - L[1][3]*x[3]; + * x[0] = b[0] - L[0][1]*x[1] - L[0][2]*x[2] - L[0][3]*x[3]; + * + * \param[in] numBands SBR crossover band index + * \param[in] b the b in L*x=b (one-dimensional) + * \param[out] x solution vector + * \param[out] x_sf exponents of x[] + */ +static void backsubst_bw(const int numBands, const FIXP_DBL *const b, + FIXP_DBL *RESTRICT x, int *RESTRICT x_sf) { + int i, k; + int m; /* the trip counter that indexes incrementally through LnormInv1d[] */ + + const FIXP_CHB *RESTRICT pLnormInv1d = + bsd[numBands - BSD_IDX_OFFSET].LnormInv1d; + const SCHAR *RESTRICT pLnormInv1d_sf = + bsd[numBands - BSD_IDX_OFFSET].LnormInv1d_sf; + + x[POLY_ORDER] = b[POLY_ORDER]; + + for (i = POLY_ORDER - 1, m = 0; i >= 0; i--) { + FIXP_DBL sum = b[i] >> SUM_SAFETY; + int sum_sf = x_sf[i]; /* sum's sf but disregarding SUM_SAFETY (added at the + iteration's end) */ + + for (k = i + 1; k <= POLY_ORDER; ++k, ++m) { + int e; + FIXP_DBL mult = fMultNorm(FX_CHB2FX_DBL(pLnormInv1d[m]), x[k], &e); + int mult_sf = pLnormInv1d_sf[m] + x_sf[k] + e; + + /* check if the new summand mult has a different sf than sum currently has + */ + int diff = mult_sf - sum_sf; + + if (diff > 0) { + /* yes, and it requires the sum v to be adjusted (scaled down) */ + sum >>= diff; + sum_sf = mult_sf; + } else if (diff < 0) { + /* yes, but here mult needs to be scaled down */ + mult >>= -diff; + } + + /* mult has now the same sf than what it is about to be added to. */ + /* scale mult down additionally so that building the sum is overflow-safe. + */ + sum -= (mult >> SUM_SAFETY); + } + + x_sf[i] = sum_sf + SUM_SAFETY; + x[i] = sum; + } +} + +/** + * \brief Solves a system of linear equations (L*x=b) with the Cholesky + * algorithm. + * + * \param[in] numBands SBR crossover band index + * \param[in,out] b input: vector b, output: solution vector p. + * \param[in,out] b_sf input: exponent of b; output: exponent of solution + * p. + */ +static void choleskySolve(const int numBands, FIXP_DBL *RESTRICT b, + int *RESTRICT b_sf) { + int i, e; + + const FIXP_CHB *RESTRICT pBmul0 = bsd[numBands - BSD_IDX_OFFSET].Bmul0; + const SCHAR *RESTRICT pBmul0_sf = bsd[numBands - BSD_IDX_OFFSET].Bmul0_sf; + const FIXP_CHB *RESTRICT pBmul1 = bsd[numBands - BSD_IDX_OFFSET].Bmul1; + const SCHAR *RESTRICT pBmul1_sf = bsd[numBands - BSD_IDX_OFFSET].Bmul1_sf; + + /* normalize b */ + FIXP_DBL bnormed[POLY_ORDER + 1]; + for (i = 0; i <= POLY_ORDER; ++i) { + bnormed[i] = fMultNorm(b[i], FX_CHB2FX_DBL(pBmul0[i]), &e); + b_sf[i] += pBmul0_sf[i] + e; + } + + backsubst_fw(numBands, bnormed, b, b_sf); + + /* normalize b again */ + for (i = 0; i <= POLY_ORDER; ++i) { + bnormed[i] = fMultNorm(b[i], FX_CHB2FX_DBL(pBmul1[i]), &e); + b_sf[i] += pBmul1_sf[i] + e; + } + + backsubst_bw(numBands, bnormed, b, b_sf); +} + +/** + * \brief Find polynomial approximation of vector y with implicit abscisas + * x=0,1,2,3..n-1 + * + * The problem (V^T * V * p = V^T * y) is solved with Cholesky. + * V is the Vandermode Matrix constructed with x = 0...n-1; + * A = V^T * V; b = V^T * y; + * + * \param[in] numBands SBR crossover band index (BSD_IDX_OFFSET <= numBands <= + * MAXLOWBANDS) + * \param[in] y input vector (mantissa) + * \param[in] y_sf exponents of y[] + * \param[out] p output polynomial coefficients (mantissa) + * \param[out] p_sf exponents of p[] + */ +static void polyfit(const int numBands, const FIXP_DBL *const y, const int y_sf, + FIXP_DBL *RESTRICT p, int *RESTRICT p_sf) { + int i, k; + LONG v[POLY_ORDER + 1]; + int sum_saftey = getLog2[numBands - 1]; + + FDK_ASSERT((numBands >= BSD_IDX_OFFSET) && (numBands <= MAXLOWBANDS)); + + /* construct vector b[] temporarily stored in array p[] */ + FDKmemclear(p, (POLY_ORDER + 1) * sizeof(FIXP_DBL)); + + /* p[] are the sums over n values and each p[i] has its own sf */ + for (i = 0; i <= POLY_ORDER; ++i) p_sf[i] = 1 - DFRACT_BITS; + + for (k = 0; k < numBands; k++) { + v[0] = (LONG)1; + for (i = 1; i <= POLY_ORDER; i++) { + v[i] = k * v[i - 1]; + } + + for (i = 0; i <= POLY_ORDER; i++) { + if (v[POLY_ORDER - i] != 0 && y[k] != FIXP_DBL(0)) { + int e; + FIXP_DBL mult = fMultNorm((FIXP_DBL)v[POLY_ORDER - i], y[k], &e); + int sf = DFRACT_BITS - 1 + y_sf + e; + + /* check if the new summand has a different sf than the sum p[i] + * currently has */ + int diff = sf - p_sf[i]; + + if (diff > 0) { + /* yes, and it requires the sum p[i] to be adjusted (scaled down) */ + p[i] >>= fMin(DFRACT_BITS - 1, diff); + p_sf[i] = sf; + } else if (diff < 0) { + /* yes, but here mult needs to be scaled down */ + mult >>= -diff; + } + + /* mult has now the same sf than what it is about to be added to. + scale mult down additionally so that building the sum is + overflow-safe. */ + p[i] += mult >> sum_saftey; + } + } + } + + p_sf[0] += sum_saftey; + p_sf[1] += sum_saftey; + p_sf[2] += sum_saftey; + p_sf[3] += sum_saftey; + + choleskySolve(numBands, p, p_sf); +} + +/** + * \brief Calculates the output of a POLY_ORDER-degree polynomial function + * with Horner scheme: + * + * y(x) = p3 + p2*x + p1*x^2 + p0*x^3 + * = p3 + x*(p2 + x*(p1 + x*p0)) + * + * The for loop iterates through the mult/add parts in y(x) as above, + * during which regular upscaling ensures a stable exponent of the + * result. + * + * \param[in] p coefficients as in y(x) + * \param[in] p_sf exponents of p[] + * \param[in] x_int non-fractional integer representation of x as in y(x) + * \param[out] out_sf exponent of return value + * + * \return result y(x) + */ +static FIXP_DBL polyval(const FIXP_DBL *const p, const int *const p_sf, + const int x_int, int *out_sf) { + FDK_ASSERT(x_int <= 31); /* otherwise getLog2[] needs more elements */ + + int k, x_sf; + int result_sf; /* working space to compute return value *out_sf */ + FIXP_DBL x; /* fractional value of x_int */ + FIXP_DBL result; /* return value */ + + /* if x == 0, then y(x) is just p3 */ + if (x_int != 0) { + x_sf = getLog2[x_int]; + x = (FIXP_DBL)x_int << (DFRACT_BITS - 1 - x_sf); + } else { + *out_sf = p_sf[3]; + return p[3]; + } + + result = p[0]; + result_sf = p_sf[0]; + + for (k = 1; k <= POLY_ORDER; ++k) { + FIXP_DBL mult = fMult(x, result); + int mult_sf = x_sf + result_sf; + + int room = CountLeadingBits(mult); + mult <<= room; + mult_sf -= room; + + FIXP_DBL pp = p[k]; + int pp_sf = p_sf[k]; + + /* equalize the shift factors of pp and mult so that we can sum them up */ + int diff = pp_sf - mult_sf; + + if (diff > 0) { + diff = fMin(diff, DFRACT_BITS - 1); + mult >>= diff; + } else if (diff < 0) { + diff = fMax(diff, 1 - DFRACT_BITS); + pp >>= -diff; + } + + /* downshift by 1 to ensure safe summation */ + mult >>= 1; + mult_sf++; + pp >>= 1; + pp_sf++; + + result_sf = fMax(pp_sf, mult_sf); + + result = mult + pp; + /* rarely, mult and pp happen to be almost equal except their sign, + and then upon summation, result becomes so small, that it is within + the inaccuracy range of a few bits, and then the relative error + produced by this function may become HUGE */ + } + + *out_sf = result_sf; + return result; +} + +void sbrDecoder_calculateGainVec(FIXP_DBL **sourceBufferReal, + FIXP_DBL **sourceBufferImag, + int sourceBuf_e_overlap, + int sourceBuf_e_current, int overlap, + FIXP_DBL *RESTRICT GainVec, int *GainVec_exp, + int numBands, const int startSample, + const int stopSample) { + FIXP_DBL p[POLY_ORDER + 1]; + FIXP_DBL meanNrg; + FIXP_DBL LowEnv[MAXLOWBANDS]; + FIXP_DBL invNumBands = GetInvInt(numBands); + FIXP_DBL invNumSlots = GetInvInt(stopSample - startSample); + int i, loBand, exp, scale_nrg, scale_nrg_ov; + int sum_scale = 5, sum_scale_ov = 3; + + if (overlap > 8) { + FDK_ASSERT(overlap <= 16); + sum_scale_ov += 1; + sum_scale += 1; + } + + /* exponents of energy values */ + sourceBuf_e_overlap = sourceBuf_e_overlap * 2 + sum_scale_ov; + sourceBuf_e_current = sourceBuf_e_current * 2 + sum_scale; + exp = fMax(sourceBuf_e_overlap, sourceBuf_e_current); + scale_nrg = sourceBuf_e_current - exp; + scale_nrg_ov = sourceBuf_e_overlap - exp; + + meanNrg = (FIXP_DBL)0; + /* Calculate the spectral envelope in dB over the current copy-up frame. */ + for (loBand = 0; loBand < numBands; loBand++) { + FIXP_DBL nrg_ov, nrg; + INT reserve = 0, exp_new; + FIXP_DBL maxVal = FL2FX_DBL(0.0f); + + for (i = startSample; i < stopSample; i++) { + maxVal |= + (FIXP_DBL)((LONG)(sourceBufferReal[i][loBand]) ^ + ((LONG)sourceBufferReal[i][loBand] >> (DFRACT_BITS - 1))); + maxVal |= + (FIXP_DBL)((LONG)(sourceBufferImag[i][loBand]) ^ + ((LONG)sourceBufferImag[i][loBand] >> (DFRACT_BITS - 1))); + } + + if (maxVal != FL2FX_DBL(0.0f)) { + reserve = CntLeadingZeros(maxVal) - 2; + } + + nrg_ov = nrg = (FIXP_DBL)0; + if (scale_nrg_ov > -31) { + for (i = startSample; i < overlap; i++) { + nrg_ov += + (fPow2Div2(scaleValue(sourceBufferReal[i][loBand], reserve)) + + fPow2Div2(scaleValue(sourceBufferImag[i][loBand], reserve))) >> + sum_scale_ov; + } + } else { + scale_nrg_ov = 0; + } + if (scale_nrg > -31) { + for (i = overlap; i < stopSample; i++) { + nrg += (fPow2Div2(scaleValue(sourceBufferReal[i][loBand], reserve)) + + fPow2Div2(scaleValue(sourceBufferImag[i][loBand], reserve))) >> + sum_scale; + } + } else { + scale_nrg = 0; + } + + nrg = (scaleValue(nrg_ov, scale_nrg_ov) >> 1) + + (scaleValue(nrg, scale_nrg) >> 1); + nrg = fMult(nrg, invNumSlots); + + exp_new = + exp - (2 * reserve) + + 2; /* +1 for addition directly above, +1 for fPow2Div2 in loops above */ + + /* LowEnv = 10*log10(nrg) = log2(nrg) * 10/log2(10) */ + /* exponent of logarithmic energy is 8 */ + if (nrg > (FIXP_DBL)0) { + int exp_log2; + nrg = CalcLog2(nrg, exp_new, &exp_log2); + nrg = scaleValue(nrg, exp_log2 - 6); + nrg = fMult(FL2FXCONST_SGL(LOG10FAC), nrg); + } else { + nrg = (FIXP_DBL)0; + } + LowEnv[loBand] = nrg; + meanNrg += fMult(nrg, invNumBands); + } + exp = 6 + 2; /* exponent of LowEnv: +2 is exponent of LOG10FAC */ + + /* subtract mean before polynomial approximation to reduce dynamic of p[] */ + for (loBand = 0; loBand < numBands; loBand++) { + LowEnv[loBand] = meanNrg - LowEnv[loBand]; + } + + /* For numBands < BSD_IDX_OFFSET (== POLY_ORDER+2) we dont get an + overdetermined equation system. The calculated polynomial will exactly fit + the input data and evaluating the polynomial will lead to the same vector + than the original input vector: lowEnvSlope[] == lowEnv[] + */ + if (numBands > POLY_ORDER + 1) { + /* Find polynomial approximation of LowEnv */ + int p_sf[POLY_ORDER + 1]; + + polyfit(numBands, LowEnv, exp, p, p_sf); + + for (i = 0; i < numBands; i++) { + int sf; + + /* lowBandEnvSlope[i] = tmp; */ + FIXP_DBL tmp = polyval(p, p_sf, i, &sf); + + /* GainVec = 10^((mean(y)-y)/20) = 2^( (mean(y)-y) * log2(10)/20 ) */ + tmp = fMult(tmp, FL2FXCONST_SGL(LOG10FAC_INV)); + GainVec[i] = f2Pow(tmp, sf - 2, + &GainVec_exp[i]); /* -2 is exponent of LOG10FAC_INV */ + } + } else { /* numBands <= POLY_ORDER+1 */ + for (i = 0; i < numBands; i++) { + int sf = exp; /* exponent of LowEnv[] */ + + /* lowBandEnvSlope[i] = LowEnv[i]; */ + FIXP_DBL tmp = LowEnv[i]; + + /* GainVec = 10^((mean(y)-y)/20) = 2^( (mean(y)-y) * log2(10)/20 ) */ + tmp = fMult(tmp, FL2FXCONST_SGL(LOG10FAC_INV)); + GainVec[i] = f2Pow(tmp, sf - 2, + &GainVec_exp[i]); /* -2 is exponent of LOG10FAC_INV */ + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/HFgen_preFlat.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/HFgen_preFlat.h new file mode 100644 index 0000000000000..c1fc49dbd2a15 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/HFgen_preFlat.h @@ -0,0 +1,132 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): Manuel Jander, Matthias Hildenbrand + + Description: QMF frequency pre whitening for SBR + +*******************************************************************************/ + +#include "common_fix.h" + +#ifndef HFGEN_PREFLAT_H +#define HFGEN_PREFLAT_H + +#define GAIN_VEC_EXP 6 /* exponent of GainVec[] */ + +/** + * \brief Find gain vector to flatten the QMF frequency bands whithout loosing + * the fine structure. + * \param[in] sourceBufferReal real part of QMF domain data. + * \param[in] sourceBufferImag imaginary part of QMF domain data. + * \param[in] sourceBuffer_e_overlap exponent of sourceBufferReal. + * \param[in] sourceBuffer_e_current exponent of sourceBufferImag. + * \param[in] overlap number of overlap samples. + * \param[out] GainVec array of gain values (one for each QMF band). + * \param[out] GainVec_exp exponents of GainVec (one for each QMF band). + * \param[in] numBands number of low bands (k_0). + * \param[in] startSample time slot start. + * \param[in] stopSample time slot stop. + */ +void sbrDecoder_calculateGainVec(FIXP_DBL **sourceBufferReal, + FIXP_DBL **sourceBufferImag, + int sourceBuffer_e_overlap, + int sourceBuffer_e_current, int overlap, + FIXP_DBL GainVec[], int GainVec_exp[], + const int numBands, const int startSample, + const int stopSample); + +#endif /* __HFGEN_PREFLAT_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_calc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_calc.cpp new file mode 100644 index 0000000000000..cefa61293a4e7 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_calc.cpp @@ -0,0 +1,3202 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Envelope calculation + + The envelope adjustor compares the energies present in the transposed + highband to the reference energies conveyed with the bitstream. + The highband is amplified (sometimes) or attenuated (mostly) to the + desired level. + + The spectral shape of the reference energies can be changed several times per + frame if necessary. Each set of energy values corresponding to a certain range + in time will be called an envelope here. + The bitstream supports several frequency scales and two resolutions. Normally, + one or more QMF-subbands are grouped to one SBR-band. An envelope contains + reference energies for each SBR-band. + In addition to the energy envelopes, noise envelopes are transmitted that + define the ratio of energy which is generated by adding noise instead of + transposing the lowband. The noise envelopes are given in a coarser time + and frequency resolution. + If a signal contains strong tonal components, synthetic sines can be + generated in individual SBR bands. + + An overlap buffer of 6 QMF-timeslots is used to allow a more + flexible alignment of the envelopes in time that is not restricted to the + core codec's frame borders. + Therefore the envelope adjustor has access to the spectral data of the + current frame as well as the last 6 QMF-timeslots of the previous frame. + However, in average only the data of 1 frame is being processed as + the adjustor is called once per frame. + + Depending on the frequency range set in the bitstream, only QMF-subbands + between lowSubband and highSubband are adjusted. + + Scaling of spectral data to maximize SNR (see #QMF_SCALE_FACTOR) as well as a + special Mantissa-Exponent format ( see calculateSbrEnvelope() ) are being + used. The main entry point for this modules is calculateSbrEnvelope(). + + \sa sbr_scale.h, #QMF_SCALE_FACTOR, calculateSbrEnvelope(), \ref + documentationOverview +*/ + +#include "env_calc.h" + +#include "sbrdec_freq_sca.h" +#include "env_extr.h" +#include "transcendent.h" +#include "sbr_ram.h" +#include "sbr_rom.h" + +#include "genericStds.h" /* need FDKpow() for debug outputs */ + +#define MAX_SFB_NRG_HEADROOM (1) +#define MAX_VAL_NRG_HEADROOM ((((FIXP_DBL)MAXVAL_DBL) >> MAX_SFB_NRG_HEADROOM)) + +typedef struct { + FIXP_DBL nrgRef[MAX_FREQ_COEFFS]; + FIXP_DBL nrgEst[MAX_FREQ_COEFFS]; + FIXP_DBL nrgGain[MAX_FREQ_COEFFS]; + FIXP_DBL noiseLevel[MAX_FREQ_COEFFS]; + FIXP_DBL nrgSine[MAX_FREQ_COEFFS]; + + SCHAR nrgRef_e[MAX_FREQ_COEFFS]; + SCHAR nrgEst_e[MAX_FREQ_COEFFS]; + SCHAR nrgGain_e[MAX_FREQ_COEFFS]; + SCHAR noiseLevel_e[MAX_FREQ_COEFFS]; + SCHAR nrgSine_e[MAX_FREQ_COEFFS]; + /* yet another exponent [0]: for ts < no_cols; [1]: for ts >= no_cols */ + SCHAR exponent[2]; +} ENV_CALC_NRGS; + +static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, SCHAR *filtBuffer_e, + FIXP_DBL *NrgGain, SCHAR *NrgGain_e, + int subbands); + +static void calcNrgPerSubband(FIXP_DBL **analysBufferReal, + FIXP_DBL **analysBufferImag, int lowSubband, + int highSubband, int start_pos, int next_pos, + SCHAR frameExp, FIXP_DBL *nrgEst, + SCHAR *nrgEst_e); + +static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, + FIXP_DBL **analysBufferImag, int nSfb, + UCHAR *freqBandTable, int start_pos, int next_pos, + SCHAR input_e, FIXP_DBL *nrg_est, SCHAR *nrg_est_e); + +static void calcSubbandGain(FIXP_DBL nrgRef, SCHAR nrgRef_e, + ENV_CALC_NRGS *nrgs, int c, FIXP_DBL tmpNoise, + SCHAR tmpNoise_e, UCHAR sinePresentFlag, + UCHAR sineMapped, int noNoiseFlag); + +static void calcAvgGain(ENV_CALC_NRGS *nrgs, int lowSubband, int highSubband, + FIXP_DBL *sumRef_m, SCHAR *sumRef_e, + FIXP_DBL *ptrAvgGain_m, SCHAR *ptrAvgGain_e); + +static void adjustTimeSlot_EldGrid(FIXP_DBL *ptrReal, ENV_CALC_NRGS *nrgs, + UCHAR *ptrHarmIndex, int lowSubbands, + int noSubbands, int scale_change, + int noNoiseFlag, int *ptrPhaseIndex, + int scale_diff_low); + +static void adjustTimeSlotLC(FIXP_DBL *ptrReal, ENV_CALC_NRGS *nrgs, + UCHAR *ptrHarmIndex, int lowSubbands, + int noSubbands, int scale_change, int noNoiseFlag, + int *ptrPhaseIndex); + +/** + * \brief Variant of adjustTimeSlotHQ() which only regards gain and noise but no + * additional harmonics + */ +static void adjustTimeSlotHQ_GainAndNoise( + FIXP_DBL *ptrReal, FIXP_DBL *ptrImag, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubbands, int noSubbands, int scale_change, FIXP_SGL smooth_ratio, + int noNoiseFlag, int filtBufferNoiseShift); +/** + * \brief Variant of adjustTimeSlotHQ() which only adds the additional harmonics + */ +static void adjustTimeSlotHQ_AddHarmonics( + FIXP_DBL *ptrReal, FIXP_DBL *ptrImag, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubbands, int noSubbands, int scale_change); + +static void adjustTimeSlotHQ(FIXP_DBL *ptrReal, FIXP_DBL *ptrImag, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, + ENV_CALC_NRGS *nrgs, int lowSubbands, + int noSubbands, int scale_change, + FIXP_SGL smooth_ratio, int noNoiseFlag, + int filtBufferNoiseShift); + +/*! + \brief Map sine flags from bitstream to QMF bands + + The bitstream carries only 1 sine flag per band (Sfb) and frame. + This function maps every sine flag from the bitstream to a specific QMF + subband and to a specific envelope where the sine shall start. The result is + stored in the vector sineMapped which contains one entry per QMF subband. The + value of an entry specifies the envelope where a sine shall start. A value of + 32 indicates that no sine is present in the subband. The missing harmonics + flags from the previous frame (harmFlagsPrev) determine if a sine starts at + the beginning of the frame or at the transient position. Additionally, the + flags in harmFlagsPrev are being updated by this function for the next frame. +*/ +static void mapSineFlags( + UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per band) */ + int nSfb, /*!< Number of bands in the table */ + ULONG *addHarmonics, /*!< Packed addHarmonics of current frame (aligned to + the MSB) */ + ULONG *harmFlagsPrev, /*!< Packed addHarmonics of previous frame (aligned to + the LSB) */ + ULONG *harmFlagsPrevActive, /*!< Packed sineMapped of previous frame + (aligned to the LSB) */ + int tranEnv, /*!< Transient position */ + SCHAR *sineMapped) /*!< Resulting vector of sine start positions for each + QMF band */ + +{ + int i; + int bitcount = 31; + ULONG harmFlagsQmfBands[ADD_HARMONICS_FLAGS_SIZE] = {0}; + ULONG *curFlags = addHarmonics; + + /* + Format of addHarmonics (aligned to MSB): + + Up to MAX_FREQ_COEFFS sfb bands can be flagged for a sign. + first word = flags for lowest 32 sfb bands in use + second word = flags for higest 32 sfb bands (if present) + + Format of harmFlagsPrev (aligned to LSB): + + Index is absolute (not relative to lsb) so it is correct even if lsb + changes first word = flags for lowest 32 qmf bands (0...31) second word = + flags for next higher 32 qmf bands (32...63) + + */ + + /* Reset the output vector first */ + FDKmemset(sineMapped, 32, + MAX_FREQ_COEFFS * sizeof(SCHAR)); /* 32 means 'no sine' */ + FDKmemclear(harmFlagsPrevActive, ADD_HARMONICS_FLAGS_SIZE * sizeof(ULONG)); + for (i = 0; i < nSfb; i++) { + ULONG maskSfb = + 1 << bitcount; /* mask to extract addHarmonics flag of current Sfb */ + + if (*curFlags & maskSfb) { /* There is a sine in this band */ + const int lsb = freqBandTable[0]; /* start of sbr range */ + /* qmf band to which sine should be added */ + const int qmfBand = (freqBandTable[i] + freqBandTable[i + 1]) >> 1; + const int qmfBandDiv32 = qmfBand >> 5; + const int maskQmfBand = + 1 << (qmfBand & + 31); /* mask to extract harmonic flag from prevFlags */ + + /* mapping of sfb with sine to a certain qmf band -> for harmFlagsPrev */ + harmFlagsQmfBands[qmfBandDiv32] |= maskQmfBand; + + /* + If there was a sine in the last frame, let it continue from the first + envelope on else start at the transient position. Indexing of sineMapped + starts relative to lsb. + */ + sineMapped[qmfBand - lsb] = + (harmFlagsPrev[qmfBandDiv32] & maskQmfBand) ? 0 : tranEnv; + if (sineMapped[qmfBand - lsb] < PVC_NTIMESLOT) { + harmFlagsPrevActive[qmfBandDiv32] |= maskQmfBand; + } + } + + if (bitcount-- == 0) { + bitcount = 31; + curFlags++; + } + } + FDKmemcpy(harmFlagsPrev, harmFlagsQmfBands, + sizeof(ULONG) * ADD_HARMONICS_FLAGS_SIZE); +} + +/*! + \brief Restore sineMapped of previous frame + + For PVC it might happen that the PVC framing (always 0) is out of sync with + the SBR framing. The adding of additional harmonics is done based on the SBR + framing. If the SBR framing is trailing the PVC framing the sine mapping of + the previous SBR frame needs to be used for the overlapping time slots. +*/ +/*static*/ void mapSineFlagsPvc( + UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per + band) */ + int nSfb, /*!< Number of bands in the table */ + ULONG *harmFlagsPrev, /*!< Packed addHarmonics of previous frame + (aligned to the MSB) */ + ULONG *harmFlagsPrevActive, /*!< Packed sineMapped of previous + frame (aligned to the LSB) */ + SCHAR *sineMapped, /*!< Resulting vector of sine start positions + for each QMF band */ + int sinusoidalPos, /*!< sinusoidal position */ + SCHAR *sinusoidalPosPrev, /*!< sinusoidal position of previous + frame */ + int trailingSbrFrame) /*!< indication if the SBR framing is + trailing the PVC framing */ +{ + /* Reset the output vector first */ + FDKmemset(sineMapped, 32, MAX_FREQ_COEFFS); /* 32 means 'no sine' */ + + if (trailingSbrFrame) { + /* restore sineMapped[] of previous frame */ + int i; + const int lsb = freqBandTable[0]; + const int usb = freqBandTable[nSfb]; + for (i = lsb; i < usb; i++) { + const int qmfBandDiv32 = i >> 5; + const int maskQmfBand = + 1 << (i & 31); /* mask to extract harmonic flag from prevFlags */ + + /* Two cases need to be distinguished ... */ + if (harmFlagsPrevActive[qmfBandDiv32] & maskQmfBand) { + /* the sine mapping already started last PVC frame -> seamlessly + * continue */ + sineMapped[i - lsb] = 0; + } else if (harmFlagsPrev[qmfBandDiv32] & maskQmfBand) { + /* sinusoidalPos of prev PVC frame was >= PVC_NTIMESLOT -> sine starts + * in this frame */ + sineMapped[i - lsb] = + *sinusoidalPosPrev - PVC_NTIMESLOT; /* we are 16 sbr time slots + ahead of last frame now */ + } + } + } + *sinusoidalPosPrev = sinusoidalPos; +} + +/*! + \brief Reduce gain-adjustment induced aliasing for real valued filterbank. +*/ +/*static*/ void aliasingReduction( + FIXP_DBL *degreeAlias, /*!< estimated aliasing for each QMF + channel */ + ENV_CALC_NRGS *nrgs, + UCHAR *useAliasReduction, /*!< synthetic sine energy for each + subband, used as flag */ + int noSubbands) /*!< number of QMF channels to process */ +{ + FIXP_DBL *nrgGain = nrgs->nrgGain; /*!< subband gains to be modified */ + SCHAR *nrgGain_e = + nrgs->nrgGain_e; /*!< subband gains to be modified (exponents) */ + FIXP_DBL *nrgEst = nrgs->nrgEst; /*!< subband energy before amplification */ + SCHAR *nrgEst_e = + nrgs->nrgEst_e; /*!< subband energy before amplification (exponents) */ + int grouping = 0, index = 0, noGroups, k; + int groupVector[MAX_FREQ_COEFFS]; + + /* Calculate grouping*/ + for (k = 0; k < noSubbands - 1; k++) { + if ((degreeAlias[k + 1] != FL2FXCONST_DBL(0.0f)) && useAliasReduction[k]) { + if (grouping == 0) { + groupVector[index++] = k; + grouping = 1; + } else { + if (groupVector[index - 1] + 3 == k) { + groupVector[index++] = k + 1; + grouping = 0; + } + } + } else { + if (grouping) { + if (useAliasReduction[k]) + groupVector[index++] = k + 1; + else + groupVector[index++] = k; + grouping = 0; + } + } + } + + if (grouping) { + groupVector[index++] = noSubbands; + } + noGroups = index >> 1; + + /*Calculate new gain*/ + for (int group = 0; group < noGroups; group++) { + FIXP_DBL nrgOrig = FL2FXCONST_DBL( + 0.0f); /* Original signal energy in current group of bands */ + SCHAR nrgOrig_e = 0; + FIXP_DBL nrgAmp = FL2FXCONST_DBL( + 0.0f); /* Amplified signal energy in group (using current gains) */ + SCHAR nrgAmp_e = 0; + FIXP_DBL nrgMod = FL2FXCONST_DBL( + 0.0f); /* Signal energy in group when applying modified gains */ + SCHAR nrgMod_e = 0; + FIXP_DBL groupGain; /* Total energy gain in group */ + SCHAR groupGain_e; + FIXP_DBL compensation; /* Compensation factor for the energy change when + applying modified gains */ + SCHAR compensation_e; + + int startGroup = groupVector[2 * group]; + int stopGroup = groupVector[2 * group + 1]; + + /* Calculate total energy in group before and after amplification with + * current gains: */ + for (k = startGroup; k < stopGroup; k++) { + /* Get original band energy */ + FIXP_DBL tmp = nrgEst[k]; + SCHAR tmp_e = nrgEst_e[k]; + + FDK_add_MantExp(tmp, tmp_e, nrgOrig, nrgOrig_e, &nrgOrig, &nrgOrig_e); + + /* Multiply band energy with current gain */ + tmp = fMult(tmp, nrgGain[k]); + tmp_e = tmp_e + nrgGain_e[k]; + + FDK_add_MantExp(tmp, tmp_e, nrgAmp, nrgAmp_e, &nrgAmp, &nrgAmp_e); + } + + /* Calculate total energy gain in group */ + FDK_divide_MantExp(nrgAmp, nrgAmp_e, nrgOrig, nrgOrig_e, &groupGain, + &groupGain_e); + + for (k = startGroup; k < stopGroup; k++) { + FIXP_DBL tmp; + SCHAR tmp_e; + + FIXP_DBL alpha = degreeAlias[k]; + if (k < noSubbands - 1) { + if (degreeAlias[k + 1] > alpha) alpha = degreeAlias[k + 1]; + } + + /* Modify gain depending on the degree of aliasing */ + FDK_add_MantExp( + fMult(alpha, groupGain), groupGain_e, + fMult(/*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - alpha, + nrgGain[k]), + nrgGain_e[k], &nrgGain[k], &nrgGain_e[k]); + + /* Apply modified gain to original energy */ + tmp = fMult(nrgGain[k], nrgEst[k]); + tmp_e = nrgGain_e[k] + nrgEst_e[k]; + + /* Accumulate energy with modified gains applied */ + FDK_add_MantExp(tmp, tmp_e, nrgMod, nrgMod_e, &nrgMod, &nrgMod_e); + } + + /* Calculate compensation factor to retain the energy of the amplified + * signal */ + FDK_divide_MantExp(nrgAmp, nrgAmp_e, nrgMod, nrgMod_e, &compensation, + &compensation_e); + + /* Apply compensation factor to all gains of the group */ + for (k = startGroup; k < stopGroup; k++) { + nrgGain[k] = fMult(nrgGain[k], compensation); + nrgGain_e[k] = nrgGain_e[k] + compensation_e; + } + } +} + +#define INTER_TES_SF_CHANGE 4 + +typedef struct { + FIXP_DBL subsample_power_low[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL subsample_power_high[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL gain[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + SCHAR subsample_power_low_sf[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + SCHAR subsample_power_high_sf[(((1024) / (32) * (4) / 2) + (3 * (4)))]; +} ITES_TEMP; + +static void apply_inter_tes(FIXP_DBL **qmfReal, FIXP_DBL **qmfImag, + const QMF_SCALE_FACTOR *sbrScaleFactor, + const SCHAR exp[2], const int RATE, + const int startPos, const int stopPos, + const int lowSubband, const int nbSubband, + const UCHAR gamma_idx) { + int highSubband = lowSubband + nbSubband; + FIXP_DBL *subsample_power_high, *subsample_power_low; + SCHAR *subsample_power_high_sf, *subsample_power_low_sf; + FIXP_DBL total_power_high = (FIXP_DBL)0; + FIXP_DBL total_power_low = (FIXP_DBL)0; + FIXP_DBL *gain; + int gain_sf[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + + /* gamma[gamma_idx] = {0.0f, 1.0f, 2.0f, 4.0f} */ + int gamma_sf = + (int)gamma_idx - 1; /* perhaps +1 to save one bit? (0.99999f vs 1.f) */ + + int nbSubsample = stopPos - startPos; + int i, j; + + C_ALLOC_SCRATCH_START(pTmp, ITES_TEMP, 1); + subsample_power_high = pTmp->subsample_power_high; + subsample_power_low = pTmp->subsample_power_low; + subsample_power_high_sf = pTmp->subsample_power_high_sf; + subsample_power_low_sf = pTmp->subsample_power_low_sf; + gain = pTmp->gain; + + if (gamma_idx > 0) { + int preShift2 = 32 - fNormz((FIXP_DBL)nbSubsample); + int total_power_low_sf = 1 - DFRACT_BITS; + int total_power_high_sf = 1 - DFRACT_BITS; + + for (i = 0; i < nbSubsample; ++i) { + FIXP_DBL bufferReal[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL bufferImag[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL maxVal = (FIXP_DBL)0; + + int ts = startPos + i; + + int low_sf = (ts < 3 * RATE) ? sbrScaleFactor->ov_lb_scale + : sbrScaleFactor->lb_scale; + low_sf = 15 - low_sf; + + for (j = 0; j < lowSubband; ++j) { + bufferImag[j] = qmfImag[startPos + i][j]; + maxVal |= (FIXP_DBL)((LONG)(bufferImag[j]) ^ + ((LONG)bufferImag[j] >> (DFRACT_BITS - 1))); + bufferReal[j] = qmfReal[startPos + i][j]; + maxVal |= (FIXP_DBL)((LONG)(bufferReal[j]) ^ + ((LONG)bufferReal[j] >> (DFRACT_BITS - 1))); + } + + subsample_power_low[i] = (FIXP_DBL)0; + subsample_power_low_sf[i] = 0; + + if (maxVal != FL2FXCONST_DBL(0.f)) { + /* multiply first, then shift for safe summation */ + int preShift = 1 - CntLeadingZeros(maxVal); + int postShift = 32 - fNormz((FIXP_DBL)lowSubband); + + /* reduce preShift because otherwise we risk to square -1.f */ + if (preShift != 0) preShift++; + + subsample_power_low_sf[i] += (low_sf + preShift) * 2 + postShift + 1; + + scaleValues(bufferReal, lowSubband, -preShift); + scaleValues(bufferImag, lowSubband, -preShift); + for (j = 0; j < lowSubband; ++j) { + FIXP_DBL addme; + addme = fPow2Div2(bufferReal[j]); + subsample_power_low[i] += addme >> postShift; + addme = fPow2Div2(bufferImag[j]); + subsample_power_low[i] += addme >> postShift; + } + } + + /* now get high */ + + maxVal = (FIXP_DBL)0; + + int high_sf = exp[(ts < 16 * RATE) ? 0 : 1]; + + for (j = lowSubband; j < highSubband; ++j) { + bufferImag[j] = qmfImag[startPos + i][j]; + maxVal |= (FIXP_DBL)((LONG)(bufferImag[j]) ^ + ((LONG)bufferImag[j] >> (DFRACT_BITS - 1))); + bufferReal[j] = qmfReal[startPos + i][j]; + maxVal |= (FIXP_DBL)((LONG)(bufferReal[j]) ^ + ((LONG)bufferReal[j] >> (DFRACT_BITS - 1))); + } + + subsample_power_high[i] = (FIXP_DBL)0; + subsample_power_high_sf[i] = 0; + + if (maxVal != FL2FXCONST_DBL(0.f)) { + int preShift = 1 - CntLeadingZeros(maxVal); + /* reduce preShift because otherwise we risk to square -1.f */ + if (preShift != 0) preShift++; + + int postShift = 32 - fNormz((FIXP_DBL)(highSubband - lowSubband)); + subsample_power_high_sf[i] += (high_sf + preShift) * 2 + postShift + 1; + + scaleValues(&bufferReal[lowSubband], highSubband - lowSubband, + -preShift); + scaleValues(&bufferImag[lowSubband], highSubband - lowSubband, + -preShift); + for (j = lowSubband; j < highSubband; j++) { + subsample_power_high[i] += fPow2Div2(bufferReal[j]) >> postShift; + subsample_power_high[i] += fPow2Div2(bufferImag[j]) >> postShift; + } + } + + /* sum all together */ + FIXP_DBL new_summand = subsample_power_low[i]; + int new_summand_sf = subsample_power_low_sf[i]; + + /* make sure the current sum, and the new summand have the same SF */ + if (new_summand_sf > total_power_low_sf) { + int diff = fMin(DFRACT_BITS - 1, new_summand_sf - total_power_low_sf); + total_power_low >>= diff; + total_power_low_sf = new_summand_sf; + } else if (new_summand_sf < total_power_low_sf) { + new_summand >>= + fMin(DFRACT_BITS - 1, total_power_low_sf - new_summand_sf); + } + + total_power_low += (new_summand >> preShift2); + + new_summand = subsample_power_high[i]; + new_summand_sf = subsample_power_high_sf[i]; + if (new_summand_sf > total_power_high_sf) { + total_power_high >>= + fMin(DFRACT_BITS - 1, new_summand_sf - total_power_high_sf); + total_power_high_sf = new_summand_sf; + } else if (new_summand_sf < total_power_high_sf) { + new_summand >>= + fMin(DFRACT_BITS - 1, total_power_high_sf - new_summand_sf); + } + + total_power_high += (new_summand >> preShift2); + } + + total_power_low_sf += preShift2; + total_power_high_sf += preShift2; + + /* gain[i] = e_LOW[i] */ + for (i = 0; i < nbSubsample; ++i) { + int sf2; + FIXP_DBL mult = + fMultNorm(subsample_power_low[i], (FIXP_DBL)nbSubsample, &sf2); + int mult_sf = subsample_power_low_sf[i] + DFRACT_BITS - 1 + sf2; + + if (total_power_low != FIXP_DBL(0)) { + gain[i] = fDivNorm(mult, total_power_low, &sf2); + gain_sf[i] = mult_sf - total_power_low_sf + sf2; + gain[i] = sqrtFixp_lookup(gain[i], &gain_sf[i]); + if (gain_sf[i] < 0) { + gain[i] >>= fMin(DFRACT_BITS - 1, -gain_sf[i]); + gain_sf[i] = 0; + } + } else { + if (mult == FIXP_DBL(0)) { + gain[i] = FIXP_DBL(0); + gain_sf[i] = 0; + } else { + gain[i] = (FIXP_DBL)MAXVAL_DBL; + gain_sf[i] = 0; + } + } + } + + FIXP_DBL total_power_high_after = (FIXP_DBL)0; + int total_power_high_after_sf = 1 - DFRACT_BITS; + + /* gain[i] = g_inter[i] */ + for (i = 0; i < nbSubsample; ++i) { + /* calculate: gain[i] = 1.0f + gamma * (gain[i] - 1.0f); */ + FIXP_DBL one = (FIXP_DBL)MAXVAL_DBL >> + gain_sf[i]; /* to substract this from gain[i] */ + + /* gamma is actually always 1 according to the table, so skip the + * fMultDiv2 */ + FIXP_DBL mult = (gain[i] - one) >> 1; + int mult_sf = gain_sf[i] + gamma_sf; + + one = FL2FXCONST_DBL(0.5f) >> mult_sf; + gain[i] = one + mult; + gain_sf[i] += gamma_sf + 1; /* +1 because of fMultDiv2() */ + + /* set gain to at least 0.2f */ + /* limit and calculate gain[i]^2 too */ + FIXP_DBL gain_pow2; + int gain_pow2_sf; + + if (fIsLessThan(gain[i], gain_sf[i], FL2FXCONST_DBL(0.2f), 0)) { + gain[i] = FL2FXCONST_DBL(0.8f); + gain_sf[i] = -2; + gain_pow2 = FL2FXCONST_DBL(0.64f); + gain_pow2_sf = -4; + } else { + /* this upscaling seems quite important */ + int r = CountLeadingBits(gain[i]); + gain[i] <<= r; + gain_sf[i] -= r; + + gain_pow2 = fPow2(gain[i]); + gain_pow2_sf = gain_sf[i] << 1; + } + + int room; + subsample_power_high[i] = + fMultNorm(subsample_power_high[i], gain_pow2, &room); + subsample_power_high_sf[i] = + subsample_power_high_sf[i] + gain_pow2_sf + room; + + int new_summand_sf = subsample_power_high_sf[i]; /* + gain_pow2_sf; */ + if (new_summand_sf > total_power_high_after_sf) { + total_power_high_after >>= + fMin(DFRACT_BITS - 1, new_summand_sf - total_power_high_after_sf); + total_power_high_after_sf = new_summand_sf; + } else if (new_summand_sf < total_power_high_after_sf) { + subsample_power_high[i] >>= + fMin(DFRACT_BITS - 1, total_power_high_after_sf - new_summand_sf); + } + total_power_high_after += subsample_power_high[i] >> preShift2; + } + + total_power_high_after_sf += preShift2; + + int sf2 = 0; + FIXP_DBL gain_adj_2 = FL2FX_DBL(0.5f); + int gain_adj_2_sf = 1; + + if ((total_power_high != (FIXP_DBL)0) && + (total_power_high_after != (FIXP_DBL)0)) { + gain_adj_2 = fDivNorm(total_power_high, total_power_high_after, &sf2); + gain_adj_2_sf = total_power_high_sf - total_power_high_after_sf + sf2; + } + + FIXP_DBL gain_adj = sqrtFixp_lookup(gain_adj_2, &gain_adj_2_sf); + int gain_adj_sf = gain_adj_2_sf; + + for (i = 0; i < nbSubsample; ++i) { + int gain_e = fMax( + fMin(gain_sf[i] + gain_adj_sf - INTER_TES_SF_CHANGE, DFRACT_BITS - 1), + -(DFRACT_BITS - 1)); + FIXP_DBL gain_final = fMult(gain[i], gain_adj); + gain_final = scaleValueSaturate(gain_final, gain_e); + + for (j = lowSubband; j < highSubband; j++) { + qmfReal[startPos + i][j] = fMult(qmfReal[startPos + i][j], gain_final); + qmfImag[startPos + i][j] = fMult(qmfImag[startPos + i][j], gain_final); + } + } + } else { /* gamma_idx == 0 */ + /* Inter-TES is not active. Still perform the scale change to have a + * consistent scaling for all envelopes of this frame. */ + for (i = 0; i < nbSubsample; ++i) { + for (j = lowSubband; j < highSubband; j++) { + qmfReal[startPos + i][j] >>= INTER_TES_SF_CHANGE; + qmfImag[startPos + i][j] >>= INTER_TES_SF_CHANGE; + } + } + } + C_ALLOC_SCRATCH_END(pTmp, ITES_TEMP, 1); +} + +/*! + \brief Apply spectral envelope to subband samples + + This function is called from sbr_dec.cpp in each frame. + + To enhance accuracy and due to the usage of tables for squareroots and + inverse, some calculations are performed with the operands being split + into mantissa and exponent. The variable names in the source code carry + the suffixes _m and _e respectively. The control data + in #hFrameData containts envelope data which is represented by this format but + stored in single words. (See requantizeEnvelopeData() for details). This data + is unpacked within calculateSbrEnvelope() to follow the described suffix + convention. + + The actual value (comparable to the corresponding float-variable in the + research-implementation) of a mantissa/exponent-pair can be calculated as + + \f$ value = value\_m * 2^{value\_e} \f$ + + All energies and noise levels decoded from the bitstream suit for an + original signal magnitude of \f$\pm 32768 \f$ rather than \f$ \pm 1\f$. + Therefore, the scale factor hb_scale passed into this function will + be converted to an 'input exponent' (#input_e), which fits the internal + representation. + + Before the actual processing, an exponent #adj_e for resulting adjusted + samples is derived from the maximum reference energy. + + Then, for each envelope, the following steps are performed: + + \li Calculate energy in the signal to be adjusted. Depending on the the value + of #interpolFreq (interpolation mode), this is either done seperately for each + QMF-subband or for each SBR-band. The resulting energies are stored in + #nrgEst_m[#MAX_FREQ_COEFFS] (mantissas) and #nrgEst_e[#MAX_FREQ_COEFFS] + (exponents). \li Calculate gain and noise level for each subband:
\f$ gain + = \sqrt{ \frac{nrgRef}{nrgEst} \cdot (1 - noiseRatio) } \hspace{2cm} noise = + \sqrt{ nrgRef \cdot noiseRatio } \f$
where noiseRatio and + nrgRef are extracted from the bitstream and nrgEst is the + subband energy before adjustment. The resulting gains are stored in + #nrgGain_m[#MAX_FREQ_COEFFS] (mantissas) and #nrgGain_e[#MAX_FREQ_COEFFS] + (exponents), the noise levels are stored in #noiseLevel_m[#MAX_FREQ_COEFFS] + and #noiseLevel_e[#MAX_FREQ_COEFFS] (exponents). The sine levels are stored in + #nrgSine_m[#MAX_FREQ_COEFFS] and #nrgSine_e[#MAX_FREQ_COEFFS]. \li Noise + limiting: The gain for each subband is limited both absolutely and relatively + compared to the total gain over all subbands. \li Boost gain: Calculate and + apply boost factor for each limiter band in order to compensate for the energy + loss imposed by the limiting. \li Apply gains and add noise: The gains and + noise levels are applied to all timeslots of the current envelope. A short + FIR-filter (length 4 QMF-timeslots) can be used to smooth the sudden change at + the envelope borders. Each complex subband sample of the current timeslot is + multiplied by the smoothed gain, then random noise with the calculated level + is added. + + \note + To reduce the stack size, some of the local arrays could be located within + the time output buffer. Of the 512 samples temporarily available there, + about half the size is already used by #SBR_FRAME_DATA. A pointer to the + remaining free memory could be supplied by an additional argument to + calculateSbrEnvelope() in sbr_dec: + + \par + \code + calculateSbrEnvelope (&hSbrDec->sbrScaleFactor, + &hSbrDec->SbrCalculateEnvelope, + hHeaderData, + hFrameData, + QmfBufferReal, + QmfBufferImag, + timeOutPtr + sizeof(SBR_FRAME_DATA)/sizeof(Float) + + 1); \endcode + + \par + Within calculateSbrEnvelope(), some pointers could be defined instead of the + arrays #nrgRef_m, #nrgRef_e, #nrgEst_m, #nrgEst_e, #noiseLevel_m: + + \par + \code + fract* nrgRef_m = timeOutPtr; + SCHAR* nrgRef_e = nrgRef_m + MAX_FREQ_COEFFS; + fract* nrgEst_m = nrgRef_e + MAX_FREQ_COEFFS; + SCHAR* nrgEst_e = nrgEst_m + MAX_FREQ_COEFFS; + fract* noiseLevel_m = nrgEst_e + MAX_FREQ_COEFFS; + \endcode + +
+*/ +void calculateSbrEnvelope( + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + HANDLE_SBR_CALCULATE_ENVELOPE + h_sbr_cal_env, /*!< Handle to struct filled by the create-function */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + PVC_DYNAMIC_DATA *pPvcDynamicData, + FIXP_DBL * + *analysBufferReal, /*!< Real part of subband samples to be processed */ + FIXP_DBL * + *analysBufferImag, /*!< Imag part of subband samples to be processed */ + const int useLP, + FIXP_DBL *degreeAlias, /*!< Estimated aliasing for each QMF channel */ + const UINT flags, const int frameErrorFlag) { + int c, i, i_stop, j, envNoise = 0; + UCHAR *borders = hFrameData->frameInfo.borders; + UCHAR *bordersPvc = hFrameData->frameInfo.pvcBorders; + int pvc_mode = pPvcDynamicData->pvc_mode; + int first_start = + ((pvc_mode > 0) ? bordersPvc[0] : borders[0]) * hHeaderData->timeStep; + FIXP_SGL *noiseLevels = hFrameData->sbrNoiseFloorLevel; + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + UCHAR **pFreqBandTable = hFreq->freqBandTable; + UCHAR *pFreqBandTableNoise = hFreq->freqBandTableNoise; + + int lowSubband = hFreq->lowSubband; + int highSubband = hFreq->highSubband; + int noSubbands = highSubband - lowSubband; + + /* old high subband before headerchange + we asume no headerchange here */ + int ov_highSubband = hFreq->highSubband; + + int noNoiseBands = hFreq->nNfb; + UCHAR *noSubFrameBands = hFreq->nSfb; + int no_cols = hHeaderData->numberTimeSlots * hHeaderData->timeStep; + + SCHAR sineMapped[MAX_FREQ_COEFFS]; + SCHAR ov_adj_e = SCALE2EXP(sbrScaleFactor->ov_hb_scale); + SCHAR adj_e = 0; + SCHAR output_e; + SCHAR final_e = 0; + /* inter-TES is active in one or more envelopes of the current SBR frame */ + const int iTES_enable = hFrameData->iTESactive; + const int iTES_scale_change = (iTES_enable) ? INTER_TES_SF_CHANGE : 0; + SCHAR maxGainLimit_e = (frameErrorFlag) ? MAX_GAIN_CONCEAL_EXP : MAX_GAIN_EXP; + + UCHAR smooth_length = 0; + + FIXP_SGL *pIenv = hFrameData->iEnvelope; + + C_ALLOC_SCRATCH_START(useAliasReduction, UCHAR, 64) + + /* if values differ we had a headerchange; if old highband is bigger then new + one we need to patch overlap-highband-scaling for this frame (see use of + ov_highSubband) as overlap contains higher frequency components which would + get lost */ + if (hFreq->highSubband < hFreq->ov_highSubband) { + ov_highSubband = hFreq->ov_highSubband; + } + + if (pvc_mode > 0) { + if (hFrameData->frameInfo.bordersNoise[0] > bordersPvc[0]) { + /* noise envelope of previous frame is trailing into current PVC frame */ + envNoise = -1; + noiseLevels = h_sbr_cal_env->prevSbrNoiseFloorLevel; + noNoiseBands = h_sbr_cal_env->prevNNfb; + noSubFrameBands = h_sbr_cal_env->prevNSfb; + lowSubband = h_sbr_cal_env->prevLoSubband; + highSubband = h_sbr_cal_env->prevHiSubband; + + noSubbands = highSubband - lowSubband; + ov_highSubband = highSubband; + if (highSubband < h_sbr_cal_env->prev_ov_highSubband) { + ov_highSubband = h_sbr_cal_env->prev_ov_highSubband; + } + + pFreqBandTable[0] = h_sbr_cal_env->prevFreqBandTableLo; + pFreqBandTable[1] = h_sbr_cal_env->prevFreqBandTableHi; + pFreqBandTableNoise = h_sbr_cal_env->prevFreqBandTableNoise; + } + + mapSineFlagsPvc(pFreqBandTable[1], noSubFrameBands[1], + h_sbr_cal_env->harmFlagsPrev, + h_sbr_cal_env->harmFlagsPrevActive, sineMapped, + hFrameData->sinusoidal_position, + &h_sbr_cal_env->sinusoidal_positionPrev, + (borders[0] > bordersPvc[0]) ? 1 : 0); + } else { + /* + Extract sine flags for all QMF bands + */ + mapSineFlags(pFreqBandTable[1], noSubFrameBands[1], + hFrameData->addHarmonics, h_sbr_cal_env->harmFlagsPrev, + h_sbr_cal_env->harmFlagsPrevActive, + hFrameData->frameInfo.tranEnv, sineMapped); + } + + /* + Scan for maximum in bufferd noise levels. + This is needed in case that we had strong noise in the previous frame + which is smoothed into the current frame. + The resulting exponent is used as start value for the maximum search + in reference energies + */ + if (!useLP) + adj_e = h_sbr_cal_env->filtBufferNoise_e - + getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands) + + (INT)MAX_SFB_NRG_HEADROOM; + + /* + Scan for maximum reference energy to be able + to select appropriate values for adj_e and final_e. + */ + if (pvc_mode > 0) { + INT maxSfbNrg_e = pPvcDynamicData->predEsg_expMax; + + /* Energy -> magnitude (sqrt halfens exponent) */ + maxSfbNrg_e = + (maxSfbNrg_e + 1) >> 1; /* +1 to go safe (round to next higher int) */ + + /* Some safety margin is needed for 2 reasons: + - The signal energy is not equally spread over all subband samples in + a specific sfb of an envelope (Nrg could be too high by a factor of + envWidth * sfbWidth) + - Smoothing can smear high gains of the previous envelope into the + current + */ + maxSfbNrg_e += (6 + MAX_SFB_NRG_HEADROOM); + + adj_e = maxSfbNrg_e; + // final_e should not exist for PVC fixfix framing + } else { + for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) { + INT maxSfbNrg_e = + -FRACT_BITS + NRG_EXP_OFFSET; /* start value for maximum search */ + + /* Fetch frequency resolution for current envelope: */ + for (j = noSubFrameBands[hFrameData->frameInfo.freqRes[i]]; j != 0; j--) { + maxSfbNrg_e = fixMax(maxSfbNrg_e, (INT)((LONG)(*pIenv++) & MASK_E)); + } + maxSfbNrg_e -= NRG_EXP_OFFSET; + + /* Energy -> magnitude (sqrt halfens exponent) */ + maxSfbNrg_e = + (maxSfbNrg_e + 1) >> 1; /* +1 to go safe (round to next higher int) */ + + /* Some safety margin is needed for 2 reasons: + - The signal energy is not equally spread over all subband samples in + a specific sfb of an envelope (Nrg could be too high by a factor of + envWidth * sfbWidth) + - Smoothing can smear high gains of the previous envelope into the + current + */ + maxSfbNrg_e += (6 + MAX_SFB_NRG_HEADROOM); + + if (borders[i] < hHeaderData->numberTimeSlots) + /* This envelope affects timeslots that belong to the output frame */ + adj_e = fMax(maxSfbNrg_e, adj_e); + + if (borders[i + 1] > hHeaderData->numberTimeSlots) + /* This envelope affects timeslots after the output frame */ + final_e = fMax(maxSfbNrg_e, final_e); + } + } + /* + Calculate adjustment factors and apply them for every envelope. + */ + pIenv = hFrameData->iEnvelope; + + if (pvc_mode > 0) { + /* iterate over SBR time slots starting with bordersPvc[i] */ + i = bordersPvc[0]; /* usually 0; can be >0 if switching from legacy SBR to + PVC */ + i_stop = PVC_NTIMESLOT; + FDK_ASSERT(bordersPvc[hFrameData->frameInfo.nEnvelopes] == PVC_NTIMESLOT); + } else { + /* iterate over SBR envelopes starting with 0 */ + i = 0; + i_stop = hFrameData->frameInfo.nEnvelopes; + } + for (; i < i_stop; i++) { + int k, noNoiseFlag; + SCHAR noise_e, input_e = SCALE2EXP(sbrScaleFactor->hb_scale); + C_ALLOC_SCRATCH_START(pNrgs, ENV_CALC_NRGS, 1); + + /* + Helper variables. + */ + int start_pos, stop_pos, freq_res; + if (pvc_mode > 0) { + start_pos = + hHeaderData->timeStep * + i; /* Start-position in time (subband sample) for current envelope. */ + stop_pos = hHeaderData->timeStep * (i + 1); /* Stop-position in time + (subband sample) for + current envelope. */ + freq_res = + hFrameData->frameInfo + .freqRes[0]; /* Frequency resolution for current envelope. */ + FDK_ASSERT( + freq_res == + hFrameData->frameInfo.freqRes[hFrameData->frameInfo.nEnvelopes - 1]); + } else { + start_pos = hHeaderData->timeStep * + borders[i]; /* Start-position in time (subband sample) for + current envelope. */ + stop_pos = hHeaderData->timeStep * + borders[i + 1]; /* Stop-position in time (subband sample) for + current envelope. */ + freq_res = + hFrameData->frameInfo + .freqRes[i]; /* Frequency resolution for current envelope. */ + } + + /* Always fully initialize the temporary energy table. This prevents + negative energies and extreme gain factors in cases where the number of + limiter bands exceeds the number of subbands. The latter can be caused by + undetected bit errors and is tested by some streams from the + certification set. */ + FDKmemclear(pNrgs, sizeof(ENV_CALC_NRGS)); + + if (pvc_mode > 0) { + /* get predicted energy values from PVC module */ + expandPredEsg(pPvcDynamicData, i, (int)MAX_FREQ_COEFFS, pNrgs->nrgRef, + pNrgs->nrgRef_e); + + if (i == borders[0]) { + mapSineFlags(pFreqBandTable[1], noSubFrameBands[1], + hFrameData->addHarmonics, h_sbr_cal_env->harmFlagsPrev, + h_sbr_cal_env->harmFlagsPrevActive, + hFrameData->sinusoidal_position, sineMapped); + } + + if (i >= hFrameData->frameInfo.bordersNoise[envNoise + 1]) { + if (envNoise >= 0) { + noiseLevels += noNoiseBands; /* The noise floor data is stored in a + row [noiseFloor1 noiseFloor2...].*/ + } else { + /* leave trailing noise envelope of past frame */ + noNoiseBands = hFreq->nNfb; + noSubFrameBands = hFreq->nSfb; + noiseLevels = hFrameData->sbrNoiseFloorLevel; + + lowSubband = hFreq->lowSubband; + highSubband = hFreq->highSubband; + + noSubbands = highSubband - lowSubband; + ov_highSubband = highSubband; + if (highSubband < hFreq->ov_highSubband) { + ov_highSubband = hFreq->ov_highSubband; + } + + pFreqBandTable[0] = hFreq->freqBandTableLo; + pFreqBandTable[1] = hFreq->freqBandTableHi; + pFreqBandTableNoise = hFreq->freqBandTableNoise; + } + envNoise++; + } + } else { + /* If the start-pos of the current envelope equals the stop pos of the + current noise envelope, increase the pointer (i.e. choose the next + noise-floor).*/ + if (borders[i] == hFrameData->frameInfo.bordersNoise[envNoise + 1]) { + noiseLevels += noNoiseBands; /* The noise floor data is stored in a row + [noiseFloor1 noiseFloor2...].*/ + envNoise++; + } + } + if (i == hFrameData->frameInfo.tranEnv || + i == h_sbr_cal_env->prevTranEnv) /* attack */ + { + noNoiseFlag = 1; + if (!useLP) smooth_length = 0; /* No smoothing on attacks! */ + } else { + noNoiseFlag = 0; + if (!useLP) + smooth_length = (1 - hHeaderData->bs_data.smoothingLength) + << 2; /* can become either 0 or 4 */ + } + + /* + Energy estimation in transposed highband. + */ + if (hHeaderData->bs_data.interpolFreq) + calcNrgPerSubband(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, highSubband, start_pos, stop_pos, input_e, + pNrgs->nrgEst, pNrgs->nrgEst_e); + else + calcNrgPerSfb(analysBufferReal, (useLP) ? NULL : analysBufferImag, + noSubFrameBands[freq_res], pFreqBandTable[freq_res], + start_pos, stop_pos, input_e, pNrgs->nrgEst, + pNrgs->nrgEst_e); + + /* + Calculate subband gains + */ + { + UCHAR *table = pFreqBandTable[freq_res]; + UCHAR *pUiNoise = + &pFreqBandTableNoise[1]; /*! Upper limit of the current noise floor + band. */ + + FIXP_SGL *pNoiseLevels = noiseLevels; + + FIXP_DBL tmpNoise = + FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); + SCHAR tmpNoise_e = + (UCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; + + int cc = 0; + c = 0; + if (pvc_mode > 0) { + for (j = 0; j < noSubFrameBands[freq_res]; j++) { + UCHAR sinePresentFlag = 0; + int li = table[j]; + int ui = table[j + 1]; + + for (k = li; k < ui; k++) { + sinePresentFlag |= (i >= sineMapped[cc]); + cc++; + } + + for (k = li; k < ui; k++) { + FIXP_DBL refNrg = pNrgs->nrgRef[k - lowSubband]; + SCHAR refNrg_e = pNrgs->nrgRef_e[k - lowSubband]; + + if (k >= *pUiNoise) { + tmpNoise = + FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); + tmpNoise_e = + (SCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; + + pUiNoise++; + } + + FDK_ASSERT(k >= lowSubband); + + if (useLP) useAliasReduction[k - lowSubband] = !sinePresentFlag; + + pNrgs->nrgSine[c] = FL2FXCONST_DBL(0.0f); + pNrgs->nrgSine_e[c] = 0; + + calcSubbandGain(refNrg, refNrg_e, pNrgs, c, tmpNoise, tmpNoise_e, + sinePresentFlag, i >= sineMapped[c], noNoiseFlag); + + c++; + } + } + } else { + for (j = 0; j < noSubFrameBands[freq_res]; j++) { + FIXP_DBL refNrg = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pIenv) & MASK_M)); + SCHAR refNrg_e = (SCHAR)((LONG)(*pIenv) & MASK_E) - NRG_EXP_OFFSET; + + UCHAR sinePresentFlag = 0; + int li = table[j]; + int ui = table[j + 1]; + + for (k = li; k < ui; k++) { + sinePresentFlag |= (i >= sineMapped[cc]); + cc++; + } + + for (k = li; k < ui; k++) { + if (k >= *pUiNoise) { + tmpNoise = + FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); + tmpNoise_e = + (SCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; + + pUiNoise++; + } + + FDK_ASSERT(k >= lowSubband); + + if (useLP) useAliasReduction[k - lowSubband] = !sinePresentFlag; + + pNrgs->nrgSine[c] = FL2FXCONST_DBL(0.0f); + pNrgs->nrgSine_e[c] = 0; + + calcSubbandGain(refNrg, refNrg_e, pNrgs, c, tmpNoise, tmpNoise_e, + sinePresentFlag, i >= sineMapped[c], noNoiseFlag); + + pNrgs->nrgRef[c] = refNrg; + pNrgs->nrgRef_e[c] = refNrg_e; + + c++; + } + pIenv++; + } + } + } + + /* + Noise limiting + */ + + for (c = 0; c < hFreq->noLimiterBands; c++) { + FIXP_DBL sumRef, boostGain, maxGain; + FIXP_DBL accu = FL2FXCONST_DBL(0.0f); + SCHAR sumRef_e, boostGain_e, maxGain_e, accu_e = 0; + int maxGainLimGainSum_e = 0; + + calcAvgGain(pNrgs, hFreq->limiterBandTable[c], + hFreq->limiterBandTable[c + 1], &sumRef, &sumRef_e, &maxGain, + &maxGain_e); + + /* Multiply maxGain with limiterGain: */ + maxGain = fMult( + maxGain, + FDK_sbrDecoder_sbr_limGains_m[hHeaderData->bs_data.limiterGains]); + /* maxGain_e += + * FDK_sbrDecoder_sbr_limGains_e[hHeaderData->bs_data.limiterGains]; */ + /* The addition of maxGain_e and FDK_sbrDecoder_sbr_limGains_e[3] might + yield values greater than 127 which doesn't fit into an SCHAR! In these + rare situations limit maxGain_e to 127. + */ + maxGainLimGainSum_e = + maxGain_e + + FDK_sbrDecoder_sbr_limGains_e[hHeaderData->bs_data.limiterGains]; + maxGain_e = + (maxGainLimGainSum_e > 127) ? (SCHAR)127 : (SCHAR)maxGainLimGainSum_e; + + /* Scale mantissa of MaxGain into range between 0.5 and 1: */ + if (maxGain == FL2FXCONST_DBL(0.0f)) + maxGain_e = -FRACT_BITS; + else { + SCHAR charTemp = CountLeadingBits(maxGain); + maxGain_e -= charTemp; + maxGain <<= (int)charTemp; + } + + if (maxGain_e >= maxGainLimit_e) { /* upper limit (e.g. 96 dB) */ + maxGain = FL2FXCONST_DBL(0.5f); + maxGain_e = maxGainLimit_e; + } + + /* Every subband gain is compared to the scaled "average gain" + and limited if necessary: */ + for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; + k++) { + if ((pNrgs->nrgGain_e[k] > maxGain_e) || + (pNrgs->nrgGain_e[k] == maxGain_e && pNrgs->nrgGain[k] > maxGain)) { + FIXP_DBL noiseAmp; + SCHAR noiseAmp_e; + + FDK_divide_MantExp(maxGain, maxGain_e, pNrgs->nrgGain[k], + pNrgs->nrgGain_e[k], &noiseAmp, &noiseAmp_e); + pNrgs->noiseLevel[k] = fMult(pNrgs->noiseLevel[k], noiseAmp); + pNrgs->noiseLevel_e[k] += noiseAmp_e; + pNrgs->nrgGain[k] = maxGain; + pNrgs->nrgGain_e[k] = maxGain_e; + } + } + + /* -- Boost gain + Calculate and apply boost factor for each limiter band: + 1. Check how much energy would be present when using the limited gain + 2. Calculate boost factor by comparison with reference energy + 3. Apply boost factor to compensate for the energy loss due to limiting + */ + for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; + k++) { + /* 1.a Add energy of adjusted signal (using preliminary gain) */ + FIXP_DBL tmp = fMult(pNrgs->nrgGain[k], pNrgs->nrgEst[k]); + SCHAR tmp_e = pNrgs->nrgGain_e[k] + pNrgs->nrgEst_e[k]; + FDK_add_MantExp(tmp, tmp_e, accu, accu_e, &accu, &accu_e); + + /* 1.b Add sine energy (if present) */ + if (pNrgs->nrgSine[k] != FL2FXCONST_DBL(0.0f)) { + FDK_add_MantExp(pNrgs->nrgSine[k], pNrgs->nrgSine_e[k], accu, accu_e, + &accu, &accu_e); + } else { + /* 1.c Add noise energy (if present) */ + if (noNoiseFlag == 0) { + FDK_add_MantExp(pNrgs->noiseLevel[k], pNrgs->noiseLevel_e[k], accu, + accu_e, &accu, &accu_e); + } + } + } + + /* 2.a Calculate ratio of wanted energy and accumulated energy */ + if (accu == (FIXP_DBL)0) { /* If divisor is 0, limit quotient to +4 dB */ + boostGain = FL2FXCONST_DBL(0.6279716f); + boostGain_e = 2; + } else { + INT div_e; + boostGain = fDivNorm(sumRef, accu, &div_e); + boostGain_e = sumRef_e - accu_e + div_e; + } + + /* 2.b Result too high? --> Limit the boost factor to +4 dB */ + if ((boostGain_e > 3) || + (boostGain_e == 2 && boostGain > FL2FXCONST_DBL(0.6279716f)) || + (boostGain_e == 3 && boostGain > FL2FXCONST_DBL(0.3139858f))) { + boostGain = FL2FXCONST_DBL(0.6279716f); + boostGain_e = 2; + } + /* 3. Multiply all signal components with the boost factor */ + for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; + k++) { + pNrgs->nrgGain[k] = fMultDiv2(pNrgs->nrgGain[k], boostGain); + pNrgs->nrgGain_e[k] = pNrgs->nrgGain_e[k] + boostGain_e + 1; + + pNrgs->nrgSine[k] = fMultDiv2(pNrgs->nrgSine[k], boostGain); + pNrgs->nrgSine_e[k] = pNrgs->nrgSine_e[k] + boostGain_e + 1; + + pNrgs->noiseLevel[k] = fMultDiv2(pNrgs->noiseLevel[k], boostGain); + pNrgs->noiseLevel_e[k] = pNrgs->noiseLevel_e[k] + boostGain_e + 1; + } + } + /* End of noise limiting */ + + if (useLP) + aliasingReduction(degreeAlias + lowSubband, pNrgs, useAliasReduction, + noSubbands); + + /* For the timeslots within the range for the output frame, + use the same scale for the noise levels. + Drawback: If the envelope exceeds the frame border, the noise levels + will have to be rescaled later to fit final_e of + the gain-values. + */ + noise_e = (start_pos < no_cols) ? adj_e : final_e; + + if (start_pos >= no_cols) { + int diff = h_sbr_cal_env->filtBufferNoise_e - noise_e; + if (diff > 0) { + int s = getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands); + if (diff > s) { + final_e += diff - s; + noise_e = final_e; + } + } + } + + /* + Convert energies to amplitude levels + */ + for (k = 0; k < noSubbands; k++) { + FDK_sqrt_MantExp(&pNrgs->nrgSine[k], &pNrgs->nrgSine_e[k], &noise_e); + FDK_sqrt_MantExp(&pNrgs->nrgGain[k], &pNrgs->nrgGain_e[k], + &pNrgs->nrgGain_e[k]); + FDK_sqrt_MantExp(&pNrgs->noiseLevel[k], &pNrgs->noiseLevel_e[k], + &noise_e); + } + + /* + Apply calculated gains and adaptive noise + */ + + /* assembleHfSignals() */ + { + int scale_change, sc_change; + FIXP_SGL smooth_ratio; + int filtBufferNoiseShift = 0; + + /* Initialize smoothing buffers with the first valid values */ + if (h_sbr_cal_env->startUp) { + if (!useLP) { + h_sbr_cal_env->filtBufferNoise_e = noise_e; + + FDKmemcpy(h_sbr_cal_env->filtBuffer_e, pNrgs->nrgGain_e, + noSubbands * sizeof(SCHAR)); + FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, + noSubbands * sizeof(FIXP_DBL)); + FDKmemcpy(h_sbr_cal_env->filtBuffer, pNrgs->nrgGain, + noSubbands * sizeof(FIXP_DBL)); + } + h_sbr_cal_env->startUp = 0; + } + + if (!useLP) { + equalizeFiltBufferExp(h_sbr_cal_env->filtBuffer, /* buffered */ + h_sbr_cal_env->filtBuffer_e, /* buffered */ + pNrgs->nrgGain, /* current */ + pNrgs->nrgGain_e, /* current */ + noSubbands); + + /* Adapt exponent of buffered noise levels to the current exponent + so they can easily be smoothed */ + if ((h_sbr_cal_env->filtBufferNoise_e - noise_e) >= 0) { + int shift = fixMin(DFRACT_BITS - 1, + (int)(h_sbr_cal_env->filtBufferNoise_e - noise_e)); + for (k = 0; k < noSubbands; k++) + h_sbr_cal_env->filtBufferNoise[k] <<= shift; + } else { + int shift = + fixMin(DFRACT_BITS - 1, + -(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e)); + for (k = 0; k < noSubbands; k++) + h_sbr_cal_env->filtBufferNoise[k] >>= shift; + } + + h_sbr_cal_env->filtBufferNoise_e = noise_e; + } + + /* find best scaling! */ + scale_change = -(DFRACT_BITS - 1); + for (k = 0; k < noSubbands; k++) { + scale_change = fixMax(scale_change, (int)pNrgs->nrgGain_e[k]); + } + sc_change = (start_pos < no_cols) ? adj_e - input_e : final_e - input_e; + + if ((scale_change - sc_change + 1) < 0) + scale_change -= (scale_change - sc_change + 1); + + scale_change = (scale_change - sc_change) + 1; + + for (k = 0; k < noSubbands; k++) { + int sc = scale_change - pNrgs->nrgGain_e[k] + (sc_change - 1); + pNrgs->nrgGain[k] >>= fixMin(sc, DFRACT_BITS - 1); + pNrgs->nrgGain_e[k] += sc; + } + + if (!useLP) { + for (k = 0; k < noSubbands; k++) { + int sc = + scale_change - h_sbr_cal_env->filtBuffer_e[k] + (sc_change - 1); + h_sbr_cal_env->filtBuffer[k] >>= fixMin(sc, DFRACT_BITS - 1); + } + } + + for (j = start_pos; j < stop_pos; j++) { + /* This timeslot is located within the first part of the processing + buffer and will be fed into the QMF-synthesis for the current frame. + adj_e - input_e + This timeslot will not yet be fed into the QMF so we do not care + about the adj_e. + sc_change = final_e - input_e + */ + if ((j == no_cols) && (start_pos < no_cols)) { + int shift = (int)(noise_e - final_e); + if (!useLP) + filtBufferNoiseShift = shift; /* shifting of + h_sbr_cal_env->filtBufferNoise[k] + will be applied in function + adjustTimeSlotHQ() */ + if (shift >= 0) { + shift = fixMin(DFRACT_BITS - 1, shift); + for (k = 0; k < noSubbands; k++) { + pNrgs->nrgSine[k] <<= shift; + pNrgs->noiseLevel[k] <<= shift; + /* + if (!useLP) + h_sbr_cal_env->filtBufferNoise[k] <<= shift; + */ + } + } else { + shift = fixMin(DFRACT_BITS - 1, -shift); + for (k = 0; k < noSubbands; k++) { + pNrgs->nrgSine[k] >>= shift; + pNrgs->noiseLevel[k] >>= shift; + /* + if (!useLP) + h_sbr_cal_env->filtBufferNoise[k] >>= shift; + */ + } + } + + /* update noise scaling */ + noise_e = final_e; + if (!useLP) + h_sbr_cal_env->filtBufferNoise_e = + noise_e; /* scaling value unused! */ + + /* update gain buffer*/ + sc_change -= (final_e - input_e); + + if (sc_change < 0) { + for (k = 0; k < noSubbands; k++) { + pNrgs->nrgGain[k] >>= -sc_change; + pNrgs->nrgGain_e[k] += -sc_change; + } + if (!useLP) { + for (k = 0; k < noSubbands; k++) { + h_sbr_cal_env->filtBuffer[k] >>= -sc_change; + } + } + } else { + scale_change += sc_change; + } + + } /* if */ + + if (!useLP) { + /* Prevent the smoothing filter from running on constant levels */ + if (j - start_pos < smooth_length) + smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j - start_pos]; + else + smooth_ratio = FL2FXCONST_SGL(0.0f); + + if (iTES_enable) { + /* adjustTimeSlotHQ() without adding of additional harmonics */ + adjustTimeSlotHQ_GainAndNoise( + &analysBufferReal[j][lowSubband], + &analysBufferImag[j][lowSubband], h_sbr_cal_env, pNrgs, + lowSubband, noSubbands, fMin(scale_change, DFRACT_BITS - 1), + smooth_ratio, noNoiseFlag, filtBufferNoiseShift); + } else { + adjustTimeSlotHQ(&analysBufferReal[j][lowSubband], + &analysBufferImag[j][lowSubband], h_sbr_cal_env, + pNrgs, lowSubband, noSubbands, + fMin(scale_change, DFRACT_BITS - 1), smooth_ratio, + noNoiseFlag, filtBufferNoiseShift); + } + } else { + FDK_ASSERT(!iTES_enable); /* not supported */ + if (flags & SBRDEC_ELD_GRID) { + /* FDKmemset(analysBufferReal[j], 0, 64 * sizeof(FIXP_DBL)); */ + adjustTimeSlot_EldGrid( + &analysBufferReal[j][lowSubband], pNrgs, + &h_sbr_cal_env->harmIndex, lowSubband, noSubbands, + fMin(scale_change, DFRACT_BITS - 1), noNoiseFlag, + &h_sbr_cal_env->phaseIndex, + fMax(EXP2SCALE(adj_e) - sbrScaleFactor->lb_scale, + -(DFRACT_BITS - 1))); + } else { + adjustTimeSlotLC(&analysBufferReal[j][lowSubband], pNrgs, + &h_sbr_cal_env->harmIndex, lowSubband, noSubbands, + fMin(scale_change, DFRACT_BITS - 1), noNoiseFlag, + &h_sbr_cal_env->phaseIndex); + } + } + /* In case the envelope spans accross the no_cols border both exponents + * are needed. */ + /* nrgGain_e[0...(noSubbands-1)] are equalized by + * equalizeFiltBufferExp() */ + pNrgs->exponent[(j < no_cols) ? 0 : 1] = + (SCHAR)((15 - sbrScaleFactor->hb_scale) + pNrgs->nrgGain_e[0] + 1 - + scale_change); + } /* for */ + + if (iTES_enable) { + apply_inter_tes( + analysBufferReal, /* pABufR, */ + analysBufferImag, /* pABufI, */ + sbrScaleFactor, pNrgs->exponent, hHeaderData->timeStep, start_pos, + stop_pos, lowSubband, noSubbands, + hFrameData + ->interTempShapeMode[i] /* frameData->interTempShapeMode[env] */ + ); + + /* add additional harmonics */ + for (j = start_pos; j < stop_pos; j++) { + /* match exponent of additional harmonics to scale change of QMF data + * caused by apply_inter_tes() */ + scale_change = 0; + + if ((start_pos <= no_cols) && (stop_pos > no_cols)) { + /* Scaling of analysBuffers was potentially changed within this + envelope. The pNrgs->nrgSine_e match the second part of the + envelope. For (j<=no_cols) the exponent of the sine energies has + to be adapted. */ + scale_change = pNrgs->exponent[1] - pNrgs->exponent[0]; + } + + adjustTimeSlotHQ_AddHarmonics( + &analysBufferReal[j][lowSubband], + &analysBufferImag[j][lowSubband], h_sbr_cal_env, pNrgs, + lowSubband, noSubbands, + -iTES_scale_change + ((j < no_cols) ? scale_change : 0)); + } + } + + if (!useLP) { + /* Update time-smoothing-buffers for gains and noise levels + The gains and the noise values of the current envelope are copied + into the buffer. This has to be done at the end of each envelope as + the values are required for a smooth transition to the next envelope. + */ + FDKmemcpy(h_sbr_cal_env->filtBuffer, pNrgs->nrgGain, + noSubbands * sizeof(FIXP_DBL)); + FDKmemcpy(h_sbr_cal_env->filtBuffer_e, pNrgs->nrgGain_e, + noSubbands * sizeof(SCHAR)); + FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, + noSubbands * sizeof(FIXP_DBL)); + } + } + C_ALLOC_SCRATCH_END(pNrgs, ENV_CALC_NRGS, 1); + } + + /* adapt adj_e to the scale change caused by apply_inter_tes() */ + adj_e += iTES_scale_change; + + /* Rescale output samples */ + { + FIXP_DBL maxVal; + int ov_reserve, reserve; + + /* Determine headroom in old adjusted samples */ + maxVal = + maxSubbandSample(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, ov_highSubband, 0, first_start); + + ov_reserve = fNorm(maxVal); + + /* Determine headroom in new adjusted samples */ + maxVal = + maxSubbandSample(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, highSubband, first_start, no_cols); + + reserve = fNorm(maxVal); + + /* Determine common output exponent */ + output_e = fMax(ov_adj_e - ov_reserve, adj_e - reserve); + + /* Rescale old samples */ + rescaleSubbandSamples(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, ov_highSubband, 0, first_start, + ov_adj_e - output_e); + + /* Rescale new samples */ + rescaleSubbandSamples(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, highSubband, first_start, no_cols, + adj_e - output_e); + } + + /* Update hb_scale */ + sbrScaleFactor->hb_scale = EXP2SCALE(output_e); + + /* Save the current final exponent for the next frame: */ + /* adapt final_e to the scale change caused by apply_inter_tes() */ + sbrScaleFactor->ov_hb_scale = EXP2SCALE(final_e + iTES_scale_change); + + /* We need to remember to the next frame that the transient + will occur in the first envelope (if tranEnv == nEnvelopes). */ + if (hFrameData->frameInfo.tranEnv == hFrameData->frameInfo.nEnvelopes) + h_sbr_cal_env->prevTranEnv = 0; + else + h_sbr_cal_env->prevTranEnv = -1; + + if (pvc_mode > 0) { + /* Not more than just the last noise envelope reaches into the next PVC + frame! This should be true because bs_noise_position is <= 15 */ + FDK_ASSERT(hFrameData->frameInfo + .bordersNoise[hFrameData->frameInfo.nNoiseEnvelopes - 1] < + PVC_NTIMESLOT); + if (hFrameData->frameInfo + .bordersNoise[hFrameData->frameInfo.nNoiseEnvelopes] > + PVC_NTIMESLOT) { + FDK_ASSERT(noiseLevels == + (hFrameData->sbrNoiseFloorLevel + + (hFrameData->frameInfo.nNoiseEnvelopes - 1) * noNoiseBands)); + h_sbr_cal_env->prevNNfb = noNoiseBands; + + h_sbr_cal_env->prevNSfb[0] = noSubFrameBands[0]; + h_sbr_cal_env->prevNSfb[1] = noSubFrameBands[1]; + + h_sbr_cal_env->prevLoSubband = lowSubband; + h_sbr_cal_env->prevHiSubband = highSubband; + h_sbr_cal_env->prev_ov_highSubband = ov_highSubband; + + FDKmemcpy(h_sbr_cal_env->prevFreqBandTableLo, pFreqBandTable[0], + noSubFrameBands[0] + 1); + FDKmemcpy(h_sbr_cal_env->prevFreqBandTableHi, pFreqBandTable[1], + noSubFrameBands[1] + 1); + FDKmemcpy(h_sbr_cal_env->prevFreqBandTableNoise, + hFreq->freqBandTableNoise, sizeof(hFreq->freqBandTableNoise)); + + FDKmemcpy(h_sbr_cal_env->prevSbrNoiseFloorLevel, noiseLevels, + MAX_NOISE_COEFFS * sizeof(FIXP_SGL)); + } + } + + C_ALLOC_SCRATCH_END(useAliasReduction, UCHAR, 64) +} + +/*! + \brief Create envelope instance + + Must be called once for each channel before calculateSbrEnvelope() can be + used. + + \return errorCode, 0 if successful +*/ +SBR_ERROR +createSbrEnvelopeCalc( + HANDLE_SBR_CALCULATE_ENVELOPE hs, /*!< pointer to envelope instance */ + HANDLE_SBR_HEADER_DATA + hHeaderData, /*!< static SBR control data, initialized with defaults */ + const int chan, /*!< Channel for which to assign buffers */ + const UINT flags) { + SBR_ERROR err = SBRDEC_OK; + int i; + + /* Clear previous missing harmonics flags */ + for (i = 0; i < ADD_HARMONICS_FLAGS_SIZE; i++) { + hs->harmFlagsPrev[i] = 0; + hs->harmFlagsPrevActive[i] = 0; + } + hs->harmIndex = 0; + + FDKmemclear(hs->prevSbrNoiseFloorLevel, sizeof(hs->prevSbrNoiseFloorLevel)); + hs->prevNNfb = 0; + FDKmemclear(hs->prevFreqBandTableNoise, sizeof(hs->prevFreqBandTableNoise)); + hs->sinusoidal_positionPrev = 0; + + /* + Setup pointers for time smoothing. + The buffer itself will be initialized later triggered by the startUp-flag. + */ + hs->prevTranEnv = -1; + + /* initialization */ + resetSbrEnvelopeCalc(hs); + + if (chan == 0) { /* do this only once */ + err = resetFreqBandTables(hHeaderData, flags); + } + + return err; +} + +/*! + \brief Create envelope instance + + Must be called once for each channel before calculateSbrEnvelope() can be + used. + + \return errorCode, 0 if successful +*/ +int deleteSbrEnvelopeCalc(HANDLE_SBR_CALCULATE_ENVELOPE hs) { return 0; } + +/*! + \brief Reset envelope instance + + This function must be called for each channel on a change of configuration. + Note that resetFreqBandTables should also be called in this case. + + \return errorCode, 0 if successful +*/ +void resetSbrEnvelopeCalc( + HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv) /*!< pointer to envelope instance */ +{ + hCalEnv->phaseIndex = 0; + + /* Noise exponent needs to be reset because the output exponent for the next + * frame depends on it */ + hCalEnv->filtBufferNoise_e = 0; + + hCalEnv->startUp = 1; +} + +/*! + \brief Equalize exponents of the buffered gain values and the new ones + + After equalization of exponents, the FIR-filter addition for smoothing + can be performed. + This function is called once for each envelope before adjusting. +*/ +static void equalizeFiltBufferExp( + FIXP_DBL *filtBuffer, /*!< bufferd gains */ + SCHAR *filtBuffer_e, /*!< exponents of bufferd gains */ + FIXP_DBL *nrgGain, /*!< gains for current envelope */ + SCHAR *nrgGain_e, /*!< exponents of gains for current envelope */ + int subbands) /*!< Number of QMF subbands */ +{ + int band; + int diff; + + for (band = 0; band < subbands; band++) { + diff = (int)(nrgGain_e[band] - filtBuffer_e[band]); + if (diff > 0) { + filtBuffer[band] >>= + fMin(diff, DFRACT_BITS - 1); /* Compensate for the scale change by + shifting the mantissa. */ + filtBuffer_e[band] += diff; /* New gain is bigger, use its exponent */ + } else if (diff < 0) { + /* The buffered gains seem to be larger, but maybe there + are some unused bits left in the mantissa */ + + int reserve = CntLeadingZeros(fixp_abs(filtBuffer[band])) - 1; + + if ((-diff) <= reserve) { + /* There is enough space in the buffered mantissa so + that we can take the new exponent as common. + */ + filtBuffer[band] <<= (-diff); + filtBuffer_e[band] += diff; /* becomes equal to *ptrNewExp */ + } else { + filtBuffer[band] <<= + reserve; /* Shift the mantissa as far as possible: */ + filtBuffer_e[band] -= reserve; /* Compensate in the exponent: */ + + /* For the remaining difference, change the new gain value */ + diff = -(reserve + diff); + nrgGain[band] >>= fMin(diff, DFRACT_BITS - 1); + nrgGain_e[band] += diff; + } + } + } +} + +/*! + \brief Shift left the mantissas of all subband samples + in the giventime and frequency range by the specified number of bits. + + This function is used to rescale the audio data in the overlap buffer + which has already been envelope adjusted with the last frame. +*/ +void rescaleSubbandSamples( + FIXP_DBL **re, /*!< Real part of input and output subband samples */ + FIXP_DBL **im, /*!< Imaginary part of input and output subband samples */ + int lowSubband, /*!< Begin of frequency range to process */ + int highSubband, /*!< End of frequency range to process */ + int start_pos, /*!< Begin of time rage (QMF-timeslot) */ + int next_pos, /*!< End of time rage (QMF-timeslot) */ + int shift) /*!< number of bits to shift */ +{ + int width = highSubband - lowSubband; + + if ((width > 0) && (shift != 0)) { + if (im != NULL) { + for (int l = start_pos; l < next_pos; l++) { + scaleValues(&re[l][lowSubband], width, shift); + scaleValues(&im[l][lowSubband], width, shift); + } + } else { + for (int l = start_pos; l < next_pos; l++) { + scaleValues(&re[l][lowSubband], width, shift); + } + } + } +} + +static inline FIXP_DBL FDK_get_maxval_real(FIXP_DBL maxVal, FIXP_DBL *reTmp, + INT width) { + maxVal = (FIXP_DBL)0; + while (width-- != 0) { + FIXP_DBL tmp = *(reTmp++); + maxVal |= (FIXP_DBL)((LONG)(tmp) ^ ((LONG)tmp >> (DFRACT_BITS - 1))); + } + + return maxVal; +} + +/*! + \brief Determine headroom for shifting + + Determine by how much the spectrum can be shifted left + for better accuracy in later processing. + + \return Number of free bits in the biggest spectral value +*/ + +FIXP_DBL maxSubbandSample( + FIXP_DBL **re, /*!< Real part of input and output subband samples */ + FIXP_DBL **im, /*!< Real part of input and output subband samples */ + int lowSubband, /*!< Begin of frequency range to process */ + int highSubband, /*!< Number of QMF bands to process */ + int start_pos, /*!< Begin of time rage (QMF-timeslot) */ + int next_pos /*!< End of time rage (QMF-timeslot) */ +) { + FIXP_DBL maxVal = FL2FX_DBL(0.0f); + unsigned int width = highSubband - lowSubband; + + FDK_ASSERT(width <= (64)); + + if (width > 0) { + if (im != NULL) { + for (int l = start_pos; l < next_pos; l++) { + int k = width; + FIXP_DBL *reTmp = &re[l][lowSubband]; + FIXP_DBL *imTmp = &im[l][lowSubband]; + do { + FIXP_DBL tmp1 = *(reTmp++); + FIXP_DBL tmp2 = *(imTmp++); + maxVal |= + (FIXP_DBL)((LONG)(tmp1) ^ ((LONG)tmp1 >> (DFRACT_BITS - 1))); + maxVal |= + (FIXP_DBL)((LONG)(tmp2) ^ ((LONG)tmp2 >> (DFRACT_BITS - 1))); + } while (--k != 0); + } + } else { + for (int l = start_pos; l < next_pos; l++) { + maxVal |= FDK_get_maxval_real(maxVal, &re[l][lowSubband], width); + } + } + } + + if (maxVal > (FIXP_DBL)0) { + /* For negative input values, maxVal is too small by 1. Add 1 only when + * necessary: if maxVal is a power of 2 */ + FIXP_DBL lowerPow2 = + (FIXP_DBL)(1 << (DFRACT_BITS - 1 - CntLeadingZeros(maxVal))); + if (maxVal == lowerPow2) maxVal += (FIXP_DBL)1; + } + + return (maxVal); +} + +/* #define SHIFT_BEFORE_SQUARE (3) */ /* (7/2) */ +/* Avoid assertion failures triggerd by overflows which occured in robustness + tests. Setting the SHIFT_BEFORE_SQUARE to 4 has negligible effect on (USAC) + conformance results. */ +#define SHIFT_BEFORE_SQUARE (4) /* ((8 - 0) / 2) */ + +/*!< + If the accumulator does not provide enough overflow bits or + does not provide a high dynamic range, the below energy calculation + requires an additional shift operation for each sample. + On the other hand, doing the shift allows using a single-precision + multiplication for the square (at least 16bit x 16bit). + For even values of OVRFLW_BITS (0, 2, 4, 6), saturated arithmetic + is required for the energy accumulation. + Theoretically, the sample-squares can sum up to a value of 76, + requiring 7 overflow bits. However since such situations are *very* + rare, accu can be limited to 64. + In case native saturated arithmetic is not available, overflows + can be prevented by replacing the above #define by + #define SHIFT_BEFORE_SQUARE ((8 - OVRFLW_BITS) / 2) + which will result in slightly reduced accuracy. +*/ + +/*! + \brief Estimates the mean energy of each filter-bank channel for the + duration of the current envelope + + This function is used when interpolFreq is true. +*/ +static void calcNrgPerSubband( + FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ + FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ + int lowSubband, /*!< Begin of the SBR frequency range */ + int highSubband, /*!< High end of the SBR frequency range */ + int start_pos, /*!< First QMF-slot of current envelope */ + int next_pos, /*!< Last QMF-slot of current envelope + 1 */ + SCHAR frameExp, /*!< Common exponent for all input samples */ + FIXP_DBL *nrgEst, /*!< resulting Energy (0..1) */ + SCHAR *nrgEst_e) /*!< Exponent of resulting Energy */ +{ + FIXP_SGL invWidth; + SCHAR preShift; + SCHAR shift; + FIXP_DBL sum; + int k; + + /* Divide by width of envelope later: */ + invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos)); + /* The common exponent needs to be doubled because all mantissas are squared: + */ + frameExp = frameExp << 1; + + for (k = lowSubband; k < highSubband; k++) { + FIXP_DBL bufferReal[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL bufferImag[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL maxVal; + + if (analysBufferImag != NULL) { + int l; + maxVal = FL2FX_DBL(0.0f); + for (l = start_pos; l < next_pos; l++) { + bufferImag[l] = analysBufferImag[l][k]; + maxVal |= (FIXP_DBL)((LONG)(bufferImag[l]) ^ + ((LONG)bufferImag[l] >> (DFRACT_BITS - 1))); + bufferReal[l] = analysBufferReal[l][k]; + maxVal |= (FIXP_DBL)((LONG)(bufferReal[l]) ^ + ((LONG)bufferReal[l] >> (DFRACT_BITS - 1))); + } + } else { + int l; + maxVal = FL2FX_DBL(0.0f); + for (l = start_pos; l < next_pos; l++) { + bufferReal[l] = analysBufferReal[l][k]; + maxVal |= (FIXP_DBL)((LONG)(bufferReal[l]) ^ + ((LONG)bufferReal[l] >> (DFRACT_BITS - 1))); + } + } + + if (maxVal != FL2FXCONST_DBL(0.f)) { + /* If the accu does not provide enough overflow bits, we cannot + shift the samples up to the limit. + Instead, keep up to 3 free bits in each sample, i.e. up to + 6 bits after calculation of square. + Please note the comment on saturated arithmetic above! + */ + FIXP_DBL accu; + preShift = CntLeadingZeros(maxVal) - 1; + preShift -= SHIFT_BEFORE_SQUARE; + + /* Limit preShift to a maximum value to prevent accumulator overflow in + exceptional situations where the signal in the analysis-buffer is very + small (small maxVal). + */ + preShift = fMin(preShift, (SCHAR)25); + + accu = FL2FXCONST_DBL(0.0f); + if (preShift >= 0) { + int l; + if (analysBufferImag != NULL) { + for (l = start_pos; l < next_pos; l++) { + FIXP_DBL temp1 = bufferReal[l] << (int)preShift; + FIXP_DBL temp2 = bufferImag[l] << (int)preShift; + accu = fPow2AddDiv2(accu, temp1); + accu = fPow2AddDiv2(accu, temp2); + } + } else { + for (l = start_pos; l < next_pos; l++) { + FIXP_DBL temp = bufferReal[l] << (int)preShift; + accu = fPow2AddDiv2(accu, temp); + } + } + } else { /* if negative shift value */ + int l; + int negpreShift = -preShift; + if (analysBufferImag != NULL) { + for (l = start_pos; l < next_pos; l++) { + FIXP_DBL temp1 = bufferReal[l] >> (int)negpreShift; + FIXP_DBL temp2 = bufferImag[l] >> (int)negpreShift; + accu = fPow2AddDiv2(accu, temp1); + accu = fPow2AddDiv2(accu, temp2); + } + } else { + for (l = start_pos; l < next_pos; l++) { + FIXP_DBL temp = bufferReal[l] >> (int)negpreShift; + accu = fPow2AddDiv2(accu, temp); + } + } + } + accu <<= 1; + + /* Convert double precision to Mantissa/Exponent: */ + shift = fNorm(accu); + sum = accu << (int)shift; + + /* Divide by width of envelope and apply frame scale: */ + *nrgEst++ = fMult(sum, invWidth); + shift += 2 * preShift; + if (analysBufferImag != NULL) + *nrgEst_e++ = frameExp - shift; + else + *nrgEst_e++ = frameExp - shift + 1; /* +1 due to missing imag. part */ + } /* maxVal!=0 */ + else { + /* Prevent a zero-mantissa-number from being misinterpreted + due to its exponent. */ + *nrgEst++ = FL2FXCONST_DBL(0.0f); + *nrgEst_e++ = 0; + } + } +} + +/*! + \brief Estimates the mean energy of each Scale factor band for the + duration of the current envelope. + + This function is used when interpolFreq is false. +*/ +static void calcNrgPerSfb( + FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ + FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ + int nSfb, /*!< Number of scale factor bands */ + UCHAR *freqBandTable, /*!< First Subband for each Sfb */ + int start_pos, /*!< First QMF-slot of current envelope */ + int next_pos, /*!< Last QMF-slot of current envelope + 1 */ + SCHAR input_e, /*!< Common exponent for all input samples */ + FIXP_DBL *nrgEst, /*!< resulting Energy (0..1) */ + SCHAR *nrgEst_e) /*!< Exponent of resulting Energy */ +{ + FIXP_SGL invWidth; + FIXP_DBL temp; + SCHAR preShift; + SCHAR shift, sum_e; + FIXP_DBL sum; + + int j, k, l, li, ui; + FIXP_DBL sumAll, sumLine; /* Single precision would be sufficient, + but overflow bits are required for accumulation */ + + /* Divide by width of envelope later: */ + invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos)); + /* The common exponent needs to be doubled because all mantissas are squared: + */ + input_e = input_e << 1; + + for (j = 0; j < nSfb; j++) { + li = freqBandTable[j]; + ui = freqBandTable[j + 1]; + + FIXP_DBL maxVal = maxSubbandSample(analysBufferReal, analysBufferImag, li, + ui, start_pos, next_pos); + + if (maxVal != FL2FXCONST_DBL(0.f)) { + preShift = CntLeadingZeros(maxVal) - 1; + + /* If the accu does not provide enough overflow bits, we cannot + shift the samples up to the limit. + Instead, keep up to 3 free bits in each sample, i.e. up to + 6 bits after calculation of square. + Please note the comment on saturated arithmetic above! + */ + preShift -= SHIFT_BEFORE_SQUARE; + + sumAll = FL2FXCONST_DBL(0.0f); + + for (k = li; k < ui; k++) { + sumLine = FL2FXCONST_DBL(0.0f); + + if (analysBufferImag != NULL) { + if (preShift >= 0) { + for (l = start_pos; l < next_pos; l++) { + temp = analysBufferReal[l][k] << (int)preShift; + sumLine += fPow2Div2(temp); + temp = analysBufferImag[l][k] << (int)preShift; + sumLine += fPow2Div2(temp); + } + } else { + for (l = start_pos; l < next_pos; l++) { + temp = analysBufferReal[l][k] >> -(int)preShift; + sumLine += fPow2Div2(temp); + temp = analysBufferImag[l][k] >> -(int)preShift; + sumLine += fPow2Div2(temp); + } + } + } else { + if (preShift >= 0) { + for (l = start_pos; l < next_pos; l++) { + temp = analysBufferReal[l][k] << (int)preShift; + sumLine += fPow2Div2(temp); + } + } else { + for (l = start_pos; l < next_pos; l++) { + temp = analysBufferReal[l][k] >> -(int)preShift; + sumLine += fPow2Div2(temp); + } + } + } + + /* The number of QMF-channels per SBR bands may be up to 15. + Shift right to avoid overflows in sum over all channels. */ + sumLine = sumLine >> (4 - 1); + sumAll += sumLine; + } + + /* Convert double precision to Mantissa/Exponent: */ + shift = fNorm(sumAll); + sum = sumAll << (int)shift; + + /* Divide by width of envelope: */ + sum = fMult(sum, invWidth); + + /* Divide by width of Sfb: */ + sum = fMult(sum, FX_DBL2FX_SGL(GetInvInt(ui - li))); + + /* Set all Subband energies in the Sfb to the average energy: */ + if (analysBufferImag != NULL) + sum_e = input_e + 4 - shift; /* -4 to compensate right-shift */ + else + sum_e = input_e + 4 + 1 - + shift; /* -4 to compensate right-shift; +1 due to missing + imag. part */ + + sum_e -= 2 * preShift; + } /* maxVal!=0 */ + else { + /* Prevent a zero-mantissa-number from being misinterpreted + due to its exponent. */ + sum = FL2FXCONST_DBL(0.0f); + sum_e = 0; + } + + for (k = li; k < ui; k++) { + *nrgEst++ = sum; + *nrgEst_e++ = sum_e; + } + } +} + +/*! + \brief Calculate gain, noise, and additional sine level for one subband. + + The resulting energy gain is given by mantissa and exponent. +*/ +static void calcSubbandGain( + FIXP_DBL nrgRef, /*!< Reference Energy according to envelope data */ + SCHAR + nrgRef_e, /*!< Reference Energy according to envelope data (exponent) */ + ENV_CALC_NRGS *nrgs, int i, FIXP_DBL tmpNoise, /*!< Relative noise level */ + SCHAR tmpNoise_e, /*!< Relative noise level (exponent) */ + UCHAR sinePresentFlag, /*!< Indicates if sine is present on band */ + UCHAR sineMapped, /*!< Indicates if sine must be added */ + int noNoiseFlag) /*!< Flag to suppress noise addition */ +{ + FIXP_DBL nrgEst = nrgs->nrgEst[i]; /*!< Energy in transposed signal */ + SCHAR nrgEst_e = + nrgs->nrgEst_e[i]; /*!< Energy in transposed signal (exponent) */ + FIXP_DBL *ptrNrgGain = &nrgs->nrgGain[i]; /*!< Resulting energy gain */ + SCHAR *ptrNrgGain_e = + &nrgs->nrgGain_e[i]; /*!< Resulting energy gain (exponent) */ + FIXP_DBL *ptrNoiseLevel = + &nrgs->noiseLevel[i]; /*!< Resulting absolute noise energy */ + SCHAR *ptrNoiseLevel_e = + &nrgs->noiseLevel_e[i]; /*!< Resulting absolute noise energy (exponent) */ + FIXP_DBL *ptrNrgSine = &nrgs->nrgSine[i]; /*!< Additional sine energy */ + SCHAR *ptrNrgSine_e = + &nrgs->nrgSine_e[i]; /*!< Additional sine energy (exponent) */ + + FIXP_DBL a, b, c; + SCHAR a_e, b_e, c_e; + + /* + This addition of 1 prevents divisions by zero in the reference code. + For very small energies in nrgEst, it prevents the gains from becoming + very high which could cause some trouble due to the smoothing. + */ + b_e = (int)(nrgEst_e - 1); + if (b_e >= 0) { + nrgEst = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e + 1, DFRACT_BITS - 1)) + + (nrgEst >> 1); + nrgEst_e += 1; /* shift by 1 bit to avoid overflow */ + + } else { + nrgEst = (nrgEst >> (INT)(fixMin(-b_e + 1, DFRACT_BITS - 1))) + + (FL2FXCONST_DBL(0.5f) >> 1); + nrgEst_e = 2; /* shift by 1 bit to avoid overflow */ + } + + /* A = NrgRef * TmpNoise */ + a = fMult(nrgRef, tmpNoise); + a_e = nrgRef_e + tmpNoise_e; + + /* B = 1 + TmpNoise */ + b_e = (int)(tmpNoise_e - 1); + if (b_e >= 0) { + b = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e + 1, DFRACT_BITS - 1)) + + (tmpNoise >> 1); + b_e = tmpNoise_e + 1; /* shift by 1 bit to avoid overflow */ + } else { + b = (tmpNoise >> (INT)(fixMin(-b_e + 1, DFRACT_BITS - 1))) + + (FL2FXCONST_DBL(0.5f) >> 1); + b_e = 2; /* shift by 1 bit to avoid overflow */ + } + + /* noiseLevel = A / B = (NrgRef * TmpNoise) / (1 + TmpNoise) */ + FDK_divide_MantExp(a, a_e, b, b_e, ptrNoiseLevel, ptrNoiseLevel_e); + + if (sinePresentFlag) { + /* C = (1 + TmpNoise) * NrgEst */ + c = fMult(b, nrgEst); + c_e = b_e + nrgEst_e; + + /* gain = A / C = (NrgRef * TmpNoise) / (1 + TmpNoise) * NrgEst */ + FDK_divide_MantExp(a, a_e, c, c_e, ptrNrgGain, ptrNrgGain_e); + + if (sineMapped) { + /* sineLevel = nrgRef/ (1 + TmpNoise) */ + FDK_divide_MantExp(nrgRef, nrgRef_e, b, b_e, ptrNrgSine, ptrNrgSine_e); + } + } else { + if (noNoiseFlag) { + /* B = NrgEst */ + b = nrgEst; + b_e = nrgEst_e; + } else { + /* B = NrgEst * (1 + TmpNoise) */ + b = fMult(b, nrgEst); + b_e = b_e + nrgEst_e; + } + + /* gain = nrgRef / B */ + INT result_exp = 0; + *ptrNrgGain = fDivNorm(nrgRef, b, &result_exp); + *ptrNrgGain_e = (SCHAR)result_exp + (nrgRef_e - b_e); + + /* There could be a one bit diffs. This is important to compensate, + because later in the code values are compared by exponent only. */ + int headroom = CountLeadingBits(*ptrNrgGain); + *ptrNrgGain <<= headroom; + *ptrNrgGain_e -= headroom; + } +} + +/*! + \brief Calculate "average gain" for the specified subband range. + + This is rather a gain of the average magnitude than the average + of gains! + The result is used as a relative limit for all gains within the + current "limiter band" (a certain frequency range). +*/ +static void calcAvgGain( + ENV_CALC_NRGS *nrgs, int lowSubband, /*!< Begin of the limiter band */ + int highSubband, /*!< High end of the limiter band */ + FIXP_DBL *ptrSumRef, SCHAR *ptrSumRef_e, + FIXP_DBL *ptrAvgGain, /*!< Resulting overall gain (mantissa) */ + SCHAR *ptrAvgGain_e) /*!< Resulting overall gain (exponent) */ +{ + FIXP_DBL *nrgRef = + nrgs->nrgRef; /*!< Reference Energy according to envelope data */ + SCHAR *nrgRef_e = + nrgs->nrgRef_e; /*!< Reference Energy according to envelope data + (exponent) */ + FIXP_DBL *nrgEst = nrgs->nrgEst; /*!< Energy in transposed signal */ + SCHAR *nrgEst_e = + nrgs->nrgEst_e; /*!< Energy in transposed signal (exponent) */ + + FIXP_DBL sumRef = 1; + FIXP_DBL sumEst = 1; + SCHAR sumRef_e = -FRACT_BITS; + SCHAR sumEst_e = -FRACT_BITS; + int k; + + for (k = lowSubband; k < highSubband; k++) { + /* Add nrgRef[k] to sumRef: */ + FDK_add_MantExp(sumRef, sumRef_e, nrgRef[k], nrgRef_e[k], &sumRef, + &sumRef_e); + + /* Add nrgEst[k] to sumEst: */ + FDK_add_MantExp(sumEst, sumEst_e, nrgEst[k], nrgEst_e[k], &sumEst, + &sumEst_e); + } + + FDK_divide_MantExp(sumRef, sumRef_e, sumEst, sumEst_e, ptrAvgGain, + ptrAvgGain_e); + + *ptrSumRef = sumRef; + *ptrSumRef_e = sumRef_e; +} + +static void adjustTimeSlot_EldGrid( + FIXP_DBL *RESTRICT + ptrReal, /*!< Subband samples to be adjusted, real part */ + ENV_CALC_NRGS *nrgs, UCHAR *ptrHarmIndex, /*!< Harmonic index */ + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + int noNoiseFlag, /*!< Flag to suppress noise addition */ + int *ptrPhaseIndex, /*!< Start index to random number array */ + int scale_diff_low) /*!< */ + +{ + int k; + FIXP_DBL signalReal, sbNoise; + int tone_count = 0; + + FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *RESTRICT pNoiseLevel = + nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + int phaseIndex = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; + + static const INT harmonicPhase[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + static const FIXP_DBL harmonicPhaseX[4][2] = { + {FL2FXCONST_DBL(2.0 * 1.245183154539139e-001), + FL2FXCONST_DBL(2.0 * 1.245183154539139e-001)}, + {FL2FXCONST_DBL(2.0 * -1.123767859325028e-001), + FL2FXCONST_DBL(2.0 * 1.123767859325028e-001)}, + {FL2FXCONST_DBL(2.0 * -1.245183154539139e-001), + FL2FXCONST_DBL(2.0 * -1.245183154539139e-001)}, + {FL2FXCONST_DBL(2.0 * 1.123767859325028e-001), + FL2FXCONST_DBL(2.0 * -1.123767859325028e-001)}}; + + const FIXP_DBL *p_harmonicPhaseX = &harmonicPhaseX[harmIndex][0]; + const INT *p_harmonicPhase = &harmonicPhase[harmIndex][0]; + + const FIXP_DBL max_val = MAX_VAL_NRG_HEADROOM >> scale_change; + const FIXP_DBL min_val = -max_val; + + *(ptrReal - 1) = fAddSaturate( + *(ptrReal - 1), + SATURATE_SHIFT(fMultDiv2(p_harmonicPhaseX[lowSubband & 1], pSineLevel[0]), + scale_diff_low, DFRACT_BITS)); + FIXP_DBL pSineLevel_prev = (FIXP_DBL)0; + + int idx_k = lowSubband & 1; + + for (k = 0; k < noSubbands; k++) { + FIXP_DBL sineLevel_curr = *pSineLevel++; + phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1); + + signalReal = fMax(fMin(fMultDiv2(*ptrReal, *pGain++), max_val), min_val) + << scale_change; + sbNoise = *pNoiseLevel++; + if (((INT)sineLevel_curr | noNoiseFlag) == 0) { + signalReal += + fMult(FDK_sbrDecoder_sbr_randomPhase[phaseIndex][0], sbNoise); + } + signalReal += sineLevel_curr * p_harmonicPhase[0]; + signalReal = + fMultAddDiv2(signalReal, pSineLevel_prev, p_harmonicPhaseX[idx_k]); + pSineLevel_prev = sineLevel_curr; + idx_k = !idx_k; + if (k < noSubbands - 1) { + signalReal = + fMultAddDiv2(signalReal, pSineLevel[0], p_harmonicPhaseX[idx_k]); + } else /* (k == noSubbands - 1) */ + { + if (k + lowSubband + 1 < 63) { + *(ptrReal + 1) += fMultDiv2(pSineLevel_prev, p_harmonicPhaseX[idx_k]); + } + } + *ptrReal++ = signalReal; + + if (pSineLevel_prev != FL2FXCONST_DBL(0.0f)) { + if (++tone_count == 16) { + k++; + break; + } + } + } + /* Run again, if previous loop got breaked with tone_count = 16 */ + for (; k < noSubbands; k++) { + FIXP_DBL sineLevel_curr = *pSineLevel++; + phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1); + + signalReal = fMax(fMin(fMultDiv2(*ptrReal, *pGain++), max_val), min_val) + << scale_change; + sbNoise = *pNoiseLevel++; + if (((INT)sineLevel_curr | noNoiseFlag) == 0) { + signalReal += + fMult(FDK_sbrDecoder_sbr_randomPhase[phaseIndex][0], sbNoise); + } + signalReal += sineLevel_curr * p_harmonicPhase[0]; + *ptrReal++ = signalReal; + } + + *ptrHarmIndex = (harmIndex + 1) & 3; + *ptrPhaseIndex = phaseIndex & (SBR_NF_NO_RANDOM_VAL - 1); +} + +/*! + \brief Amplify one timeslot of the signal with the calculated gains + and add the noisefloor. +*/ + +static void adjustTimeSlotLC( + FIXP_DBL *ptrReal, /*!< Subband samples to be adjusted, real part */ + ENV_CALC_NRGS *nrgs, UCHAR *ptrHarmIndex, /*!< Harmonic index */ + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + int noNoiseFlag, /*!< Flag to suppress noise addition */ + int *ptrPhaseIndex) /*!< Start index to random number array */ +{ + FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *pNoiseLevel = + nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + int k; + int index = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; + UCHAR freqInvFlag = (lowSubband & 1); + FIXP_DBL signalReal, sineLevel, sineLevelNext, sineLevelPrev; + int tone_count = 0; + int sineSign = 1; + const FIXP_DBL max_val = MAX_VAL_NRG_HEADROOM >> scale_change; + const FIXP_DBL min_val = -max_val; + +#define C1 ((FIXP_SGL)FL2FXCONST_SGL(2.f * 0.00815f)) +#define C1_CLDFB ((FIXP_SGL)FL2FXCONST_SGL(2.f * 0.16773f)) + + /* + First pass for k=0 pulled out of the loop: + */ + + index = (index + 1) & (SBR_NF_NO_RANDOM_VAL - 1); + + /* + The next multiplication constitutes the actual envelope adjustment + of the signal and should be carried out with full accuracy + (supplying #FRACT_BITS valid bits). + */ + signalReal = fMax(fMin(fMultDiv2(*ptrReal, *pGain++), max_val), min_val) + << scale_change; + sineLevel = *pSineLevel++; + sineLevelNext = (noSubbands > 1) ? pSineLevel[0] : FL2FXCONST_DBL(0.0f); + + if (sineLevel != FL2FXCONST_DBL(0.0f)) + tone_count++; + else if (!noNoiseFlag) + /* Add noisefloor to the amplified signal */ + signalReal += + fMult(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0]); + + { + if (!(harmIndex & 0x1)) { + /* harmIndex 0,2 */ + signalReal += (harmIndex & 0x2) ? -sineLevel : sineLevel; + *ptrReal++ = signalReal; + } else { + /* harmIndex 1,3 in combination with freqInvFlag */ + int shift = (int)(scale_change + 1); + shift = (shift >= 0) ? fixMin(DFRACT_BITS - 1, shift) + : fixMax(-(DFRACT_BITS - 1), shift); + + FIXP_DBL tmp1 = (shift >= 0) ? (fMultDiv2(C1, sineLevel) >> shift) + : (fMultDiv2(C1, sineLevel) << (-shift)); + FIXP_DBL tmp2 = fMultDiv2(C1, sineLevelNext); + + /* save switch and compare operations and reduce to XOR statement */ + if (((harmIndex >> 1) & 0x1) ^ freqInvFlag) { + *(ptrReal - 1) = fAddSaturate(*(ptrReal - 1), tmp1); + signalReal -= tmp2; + } else { + *(ptrReal - 1) = fAddSaturate(*(ptrReal - 1), -tmp1); + signalReal += tmp2; + } + *ptrReal++ = signalReal; + freqInvFlag = !freqInvFlag; + } + } + + pNoiseLevel++; + + if (noSubbands > 2) { + if (!(harmIndex & 0x1)) { + /* harmIndex 0,2 */ + if (!harmIndex) { + sineSign = 0; + } + + for (k = noSubbands - 2; k != 0; k--) { + FIXP_DBL sinelevel = *pSineLevel++; + index++; + if (((signalReal = (sineSign ? -sinelevel : sinelevel)) == + FL2FXCONST_DBL(0.0f)) && + !noNoiseFlag) { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + signalReal += + fMult(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0]); + } + + /* The next multiplication constitutes the actual envelope adjustment of + * the signal. */ + signalReal += + fMax(fMin(fMultDiv2(*ptrReal, *pGain++), max_val), min_val) + << scale_change; + + pNoiseLevel++; + *ptrReal++ = signalReal; + } /* for ... */ + } else { + /* harmIndex 1,3 in combination with freqInvFlag */ + if (harmIndex == 1) freqInvFlag = !freqInvFlag; + + for (k = noSubbands - 2; k != 0; k--) { + index++; + /* The next multiplication constitutes the actual envelope adjustment of + * the signal. */ + signalReal = fMax(fMin(fMultDiv2(*ptrReal, *pGain++), max_val), min_val) + << scale_change; + + if (*pSineLevel++ != FL2FXCONST_DBL(0.0f)) + tone_count++; + else if (!noNoiseFlag) { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + signalReal += + fMult(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0]); + } + + pNoiseLevel++; + + if (tone_count <= 16) { + FIXP_DBL addSine = fMultDiv2((pSineLevel[-2] - pSineLevel[0]), C1); + signalReal += (freqInvFlag) ? (-addSine) : (addSine); + } + + *ptrReal++ = signalReal; + freqInvFlag = !freqInvFlag; + } /* for ... */ + } + } + + if (noSubbands > -1) { + index++; + /* The next multiplication constitutes the actual envelope adjustment of the + * signal. */ + signalReal = fMax(fMin(fMultDiv2(*ptrReal, *pGain), max_val), min_val) + << scale_change; + sineLevelPrev = fMultDiv2(pSineLevel[-1], FL2FX_SGL(0.0163f)); + sineLevel = pSineLevel[0]; + + if (pSineLevel[0] != FL2FXCONST_DBL(0.0f)) + tone_count++; + else if (!noNoiseFlag) { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + signalReal = signalReal + fMult(FDK_sbrDecoder_sbr_randomPhase[index][0], + pNoiseLevel[0]); + } + + if (!(harmIndex & 0x1)) { + /* harmIndex 0,2 */ + *ptrReal = signalReal + ((sineSign) ? -sineLevel : sineLevel); + } else { + /* harmIndex 1,3 in combination with freqInvFlag */ + if (tone_count <= 16) { + if (freqInvFlag) { + *ptrReal++ = signalReal - sineLevelPrev; + if (noSubbands + lowSubband < 63) + *ptrReal = *ptrReal + fMultDiv2(C1, sineLevel); + } else { + *ptrReal++ = signalReal + sineLevelPrev; + if (noSubbands + lowSubband < 63) + *ptrReal = *ptrReal - fMultDiv2(C1, sineLevel); + } + } else + *ptrReal = signalReal; + } + } + *ptrHarmIndex = (harmIndex + 1) & 3; + *ptrPhaseIndex = index & (SBR_NF_NO_RANDOM_VAL - 1); +} + +static void adjustTimeSlotHQ_GainAndNoise( + FIXP_DBL *RESTRICT + ptrReal, /*!< Subband samples to be adjusted, real part */ + FIXP_DBL *RESTRICT + ptrImag, /*!< Subband samples to be adjusted, imag part */ + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + FIXP_SGL smooth_ratio, /*!< Impact of last envelope */ + int noNoiseFlag, /*!< Start index to random number array */ + int filtBufferNoiseShift) /*!< Shift factor of filtBufferNoise */ +{ + FIXP_DBL *RESTRICT gain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *RESTRICT noiseLevel = + nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + FIXP_DBL *RESTRICT filtBuffer = + h_sbr_cal_env->filtBuffer; /*!< Gains of last envelope */ + FIXP_DBL *RESTRICT filtBufferNoise = + h_sbr_cal_env->filtBufferNoise; /*!< Noise levels of last envelope */ + int *RESTRICT ptrPhaseIndex = + &h_sbr_cal_env->phaseIndex; /*!< Start index to random number array */ + + int k; + FIXP_DBL signalReal, signalImag; + FIXP_DBL noiseReal, noiseImag; + FIXP_DBL smoothedGain, smoothedNoise; + FIXP_SGL direct_ratio = + /*FL2FXCONST_SGL(1.0f) */ (FIXP_SGL)MAXVAL_SGL - smooth_ratio; + int index = *ptrPhaseIndex; + int shift; + FIXP_DBL max_val_noise = 0, min_val_noise = 0; + const FIXP_DBL max_val = MAX_VAL_NRG_HEADROOM >> scale_change; + const FIXP_DBL min_val = -max_val; + + *ptrPhaseIndex = (index + noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1); + + filtBufferNoiseShift += + 1; /* due to later use of fMultDiv2 instead of fMult */ + if (filtBufferNoiseShift < 0) { + shift = fixMin(DFRACT_BITS - 1, -filtBufferNoiseShift); + } else { + shift = fixMin(DFRACT_BITS - 1, filtBufferNoiseShift); + max_val_noise = MAX_VAL_NRG_HEADROOM >> shift; + min_val_noise = -max_val_noise; + } + + if (smooth_ratio > FL2FXCONST_SGL(0.0f)) { + for (k = 0; k < noSubbands; k++) { + /* + Smoothing: The old envelope has been bufferd and a certain ratio + of the old gains and noise levels is used. + */ + smoothedGain = + fMult(smooth_ratio, filtBuffer[k]) + fMult(direct_ratio, gain[k]); + + if (filtBufferNoiseShift < 0) { + smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) >> shift) + + fMult(direct_ratio, noiseLevel[k]); + } else { + smoothedNoise = fMultDiv2(smooth_ratio, filtBufferNoise[k]); + smoothedNoise = + (fMax(fMin(smoothedNoise, max_val_noise), min_val_noise) << shift) + + fMult(direct_ratio, noiseLevel[k]); + } + + smoothedNoise = fMax(fMin(smoothedNoise, (FIXP_DBL)(MAXVAL_DBL / 2)), + (FIXP_DBL)(MINVAL_DBL / 2)); + + /* + The next 2 multiplications constitute the actual envelope adjustment + of the signal and should be carried out with full accuracy + (supplying #DFRACT_BITS valid bits). + */ + signalReal = + fMax(fMin(fMultDiv2(*ptrReal, smoothedGain), max_val), min_val) + << scale_change; + signalImag = + fMax(fMin(fMultDiv2(*ptrImag, smoothedGain), max_val), min_val) + << scale_change; + + index++; + + if ((pSineLevel[k] != FL2FXCONST_DBL(0.0f)) || noNoiseFlag) { + /* Just the amplified signal is saved */ + *ptrReal++ = signalReal; + *ptrImag++ = signalImag; + } else { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + noiseReal = + fMult(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise); + noiseImag = + fMult(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise); + *ptrReal++ = (signalReal + noiseReal); + *ptrImag++ = (signalImag + noiseImag); + } + } + } else { + for (k = 0; k < noSubbands; k++) { + smoothedGain = gain[k]; + signalReal = + fMax(fMin(fMultDiv2(*ptrReal, smoothedGain), max_val), min_val) + << scale_change; + signalImag = + fMax(fMin(fMultDiv2(*ptrImag, smoothedGain), max_val), min_val) + << scale_change; + + index++; + + if ((pSineLevel[k] == FL2FXCONST_DBL(0.0f)) && (noNoiseFlag == 0)) { + /* Add noisefloor to the amplified signal */ + smoothedNoise = noiseLevel[k]; + index &= (SBR_NF_NO_RANDOM_VAL - 1); + noiseReal = + fMult(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise); + noiseImag = + fMult(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise); + + signalReal += noiseReal; + signalImag += noiseImag; + } + *ptrReal++ = signalReal; + *ptrImag++ = signalImag; + } + } +} + +static void adjustTimeSlotHQ_AddHarmonics( + FIXP_DBL *RESTRICT + ptrReal, /*!< Subband samples to be adjusted, real part */ + FIXP_DBL *RESTRICT + ptrImag, /*!< Subband samples to be adjusted, imag part */ + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change /*!< Scale mismatch between QMF input and sineLevel + exponent. */ +) { + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + UCHAR *RESTRICT ptrHarmIndex = + &h_sbr_cal_env->harmIndex; /*!< Harmonic index */ + + int k; + FIXP_DBL signalReal, signalImag; + UCHAR harmIndex = *ptrHarmIndex; + int freqInvFlag = (lowSubband & 1); + FIXP_DBL sineLevel; + + *ptrHarmIndex = (harmIndex + 1) & 3; + + for (k = 0; k < noSubbands; k++) { + sineLevel = pSineLevel[k]; + freqInvFlag ^= 1; + if (sineLevel != FL2FXCONST_DBL(0.f)) { + signalReal = ptrReal[k]; + signalImag = ptrImag[k]; + sineLevel = scaleValue(sineLevel, scale_change); + if (harmIndex & 2) { + /* case 2,3 */ + sineLevel = -sineLevel; + } + if (!(harmIndex & 1)) { + /* case 0,2: */ + ptrReal[k] = signalReal + sineLevel; + } else { + /* case 1,3 */ + if (!freqInvFlag) sineLevel = -sineLevel; + ptrImag[k] = signalImag + sineLevel; + } + } + } +} + +static void adjustTimeSlotHQ( + FIXP_DBL *RESTRICT + ptrReal, /*!< Subband samples to be adjusted, real part */ + FIXP_DBL *RESTRICT + ptrImag, /*!< Subband samples to be adjusted, imag part */ + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + FIXP_SGL smooth_ratio, /*!< Impact of last envelope */ + int noNoiseFlag, /*!< Start index to random number array */ + int filtBufferNoiseShift) /*!< Shift factor of filtBufferNoise */ +{ + FIXP_DBL *RESTRICT gain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *RESTRICT noiseLevel = + nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + FIXP_DBL *RESTRICT filtBuffer = + h_sbr_cal_env->filtBuffer; /*!< Gains of last envelope */ + FIXP_DBL *RESTRICT filtBufferNoise = + h_sbr_cal_env->filtBufferNoise; /*!< Noise levels of last envelope */ + UCHAR *RESTRICT ptrHarmIndex = + &h_sbr_cal_env->harmIndex; /*!< Harmonic index */ + int *RESTRICT ptrPhaseIndex = + &h_sbr_cal_env->phaseIndex; /*!< Start index to random number array */ + + int k; + FIXP_DBL signalReal, signalImag; + FIXP_DBL noiseReal, noiseImag; + FIXP_DBL smoothedGain, smoothedNoise; + FIXP_SGL direct_ratio = + /*FL2FXCONST_SGL(1.0f) */ (FIXP_SGL)MAXVAL_SGL - smooth_ratio; + int index = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; + int freqInvFlag = (lowSubband & 1); + FIXP_DBL sineLevel; + int shift; + FIXP_DBL max_val_noise = 0, min_val_noise = 0; + const FIXP_DBL max_val = MAX_VAL_NRG_HEADROOM >> scale_change; + const FIXP_DBL min_val = -max_val; + + *ptrPhaseIndex = (index + noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1); + *ptrHarmIndex = (harmIndex + 1) & 3; + + /* + Possible optimization: + smooth_ratio and harmIndex stay constant during the loop. + It might be faster to include a separate loop in each path. + + the check for smooth_ratio is now outside the loop and the workload + of the whole function decreased by about 20 % + */ + + filtBufferNoiseShift += + 1; /* due to later use of fMultDiv2 instead of fMult */ + if (filtBufferNoiseShift < 0) { + shift = fixMin(DFRACT_BITS - 1, -filtBufferNoiseShift); + } else { + shift = fixMin(DFRACT_BITS - 1, filtBufferNoiseShift); + max_val_noise = MAX_VAL_NRG_HEADROOM >> shift; + min_val_noise = -max_val_noise; + } + + if (smooth_ratio > FL2FXCONST_SGL(0.0f)) { + for (k = 0; k < noSubbands; k++) { + /* + Smoothing: The old envelope has been bufferd and a certain ratio + of the old gains and noise levels is used. + */ + + smoothedGain = + fMult(smooth_ratio, filtBuffer[k]) + fMult(direct_ratio, gain[k]); + + if (filtBufferNoiseShift < 0) { + smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) >> shift) + + fMult(direct_ratio, noiseLevel[k]); + } else { + smoothedNoise = fMultDiv2(smooth_ratio, filtBufferNoise[k]); + smoothedNoise = + (fMax(fMin(smoothedNoise, max_val_noise), min_val_noise) << shift) + + fMult(direct_ratio, noiseLevel[k]); + } + + smoothedNoise = fMax(fMin(smoothedNoise, (FIXP_DBL)(MAXVAL_DBL / 2)), + (FIXP_DBL)(MINVAL_DBL / 2)); + + /* + The next 2 multiplications constitute the actual envelope adjustment + of the signal and should be carried out with full accuracy + (supplying #DFRACT_BITS valid bits). + */ + signalReal = + fMax(fMin(fMultDiv2(*ptrReal, smoothedGain), max_val), min_val) + << scale_change; + signalImag = + fMax(fMin(fMultDiv2(*ptrImag, smoothedGain), max_val), min_val) + << scale_change; + + index++; + + if (pSineLevel[k] != FL2FXCONST_DBL(0.0f)) { + sineLevel = pSineLevel[k]; + + switch (harmIndex) { + case 0: + *ptrReal++ = (signalReal + sineLevel); + *ptrImag++ = (signalImag); + break; + case 2: + *ptrReal++ = (signalReal - sineLevel); + *ptrImag++ = (signalImag); + break; + case 1: + *ptrReal++ = (signalReal); + if (freqInvFlag) + *ptrImag++ = (signalImag - sineLevel); + else + *ptrImag++ = (signalImag + sineLevel); + break; + case 3: + *ptrReal++ = signalReal; + if (freqInvFlag) + *ptrImag++ = (signalImag + sineLevel); + else + *ptrImag++ = (signalImag - sineLevel); + break; + } + } else { + if (noNoiseFlag) { + /* Just the amplified signal is saved */ + *ptrReal++ = (signalReal); + *ptrImag++ = (signalImag); + } else { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + noiseReal = + fMult(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise); + noiseImag = + fMult(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise); + *ptrReal++ = (signalReal + noiseReal); + *ptrImag++ = (signalImag + noiseImag); + } + } + freqInvFlag ^= 1; + } + + } else { + for (k = 0; k < noSubbands; k++) { + smoothedGain = gain[k]; + signalReal = + fMax(fMin(fMultDiv2(*ptrReal, smoothedGain), max_val), min_val) + << scale_change; + signalImag = + fMax(fMin(fMultDiv2(*ptrImag, smoothedGain), max_val), min_val) + << scale_change; + + index++; + + if ((sineLevel = pSineLevel[k]) != FL2FXCONST_DBL(0.0f)) { + switch (harmIndex) { + case 0: + signalReal += sineLevel; + break; + case 1: + if (freqInvFlag) + signalImag -= sineLevel; + else + signalImag += sineLevel; + break; + case 2: + signalReal -= sineLevel; + break; + case 3: + if (freqInvFlag) + signalImag += sineLevel; + else + signalImag -= sineLevel; + break; + } + } else { + if (noNoiseFlag == 0) { + /* Add noisefloor to the amplified signal */ + smoothedNoise = noiseLevel[k]; + index &= (SBR_NF_NO_RANDOM_VAL - 1); + noiseReal = + fMult(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise); + noiseImag = + fMult(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise); + + signalReal += noiseReal; + signalImag += noiseImag; + } + } + *ptrReal++ = signalReal; + *ptrImag++ = signalImag; + + freqInvFlag ^= 1; + } + } +} + +/*! + \brief Reset limiter bands. + + Build frequency band table for the gain limiter dependent on + the previously generated transposer patch areas. + + \return SBRDEC_OK if ok, SBRDEC_UNSUPPORTED_CONFIG on error +*/ +SBR_ERROR +ResetLimiterBands( + UCHAR *limiterBandTable, /*!< Resulting band borders in QMF channels */ + UCHAR *noLimiterBands, /*!< Resulting number of limiter band */ + UCHAR *freqBandTable, /*!< Table with possible band borders */ + int noFreqBands, /*!< Number of bands in freqBandTable */ + const PATCH_PARAM *patchParam, /*!< Transposer patch parameters */ + int noPatches, /*!< Number of transposer patches */ + int limiterBands, /*!< Selected 'band density' from bitstream */ + UCHAR sbrPatchingMode, int xOverQmf[MAX_NUM_PATCHES], int b41Sbr) { + int i, k, isPatchBorder[2], loLimIndex, hiLimIndex, tempNoLim, nBands; + UCHAR workLimiterBandTable[MAX_FREQ_COEFFS / 2 + MAX_NUM_PATCHES + 1]; + int patchBorders[MAX_NUM_PATCHES + 1]; + int kx, k2; + + int lowSubband = freqBandTable[0]; + int highSubband = freqBandTable[noFreqBands]; + + /* 1 limiter band. */ + if (limiterBands == 0) { + limiterBandTable[0] = 0; + limiterBandTable[1] = highSubband - lowSubband; + nBands = 1; + } else { + if (!sbrPatchingMode && xOverQmf != NULL) { + noPatches = 0; + + if (b41Sbr == 1) { + for (i = 1; i < MAX_NUM_PATCHES_HBE; i++) + if (xOverQmf[i] != 0) noPatches++; + } else { + for (i = 1; i < MAX_STRETCH_HBE; i++) + if (xOverQmf[i] != 0) noPatches++; + } + for (i = 0; i < noPatches; i++) { + patchBorders[i] = xOverQmf[i] - lowSubband; + } + } else { + for (i = 0; i < noPatches; i++) { + patchBorders[i] = patchParam[i].guardStartBand - lowSubband; + } + } + patchBorders[i] = highSubband - lowSubband; + + /* 1.2, 2, or 3 limiter bands/octave plus bandborders at patchborders. */ + for (k = 0; k <= noFreqBands; k++) { + workLimiterBandTable[k] = freqBandTable[k] - lowSubband; + } + for (k = 1; k < noPatches; k++) { + workLimiterBandTable[noFreqBands + k] = patchBorders[k]; + } + + tempNoLim = nBands = noFreqBands + noPatches - 1; + shellsort(workLimiterBandTable, tempNoLim + 1); + + loLimIndex = 0; + hiLimIndex = 1; + + while (hiLimIndex <= tempNoLim) { + FIXP_DBL div_m, oct_m, temp; + INT div_e = 0, oct_e = 0, temp_e = 0; + + k2 = workLimiterBandTable[hiLimIndex] + lowSubband; + kx = workLimiterBandTable[loLimIndex] + lowSubband; + + div_m = fDivNorm(k2, kx, &div_e); + + /* calculate number of octaves */ + oct_m = fLog2(div_m, div_e, &oct_e); + + /* multiply with limiterbands per octave */ + /* values 1, 1.2, 2, 3 -> scale factor of 2 */ + temp = fMultNorm( + oct_m, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[limiterBands], + &temp_e); + + /* overall scale factor of temp ist addition of scalefactors from log2 + calculation, limiter bands scalefactor (2) and limiter bands + multiplication */ + temp_e += oct_e + 2; + + /* div can be a maximum of 64 (k2 = 64 and kx = 1) + -> oct can be a maximum of 6 + -> temp can be a maximum of 18 (as limiterBandsPerOctoave is a maximum + factor of 3) + -> we need a scale factor of 5 for comparisson + */ + if (temp >> (5 - temp_e) < FL2FXCONST_DBL(0.49f) >> 5) { + if (workLimiterBandTable[hiLimIndex] == + workLimiterBandTable[loLimIndex]) { + workLimiterBandTable[hiLimIndex] = highSubband; + nBands--; + hiLimIndex++; + continue; + } + isPatchBorder[0] = isPatchBorder[1] = 0; + for (k = 0; k <= noPatches; k++) { + if (workLimiterBandTable[hiLimIndex] == patchBorders[k]) { + isPatchBorder[1] = 1; + break; + } + } + if (!isPatchBorder[1]) { + workLimiterBandTable[hiLimIndex] = highSubband; + nBands--; + hiLimIndex++; + continue; + } + for (k = 0; k <= noPatches; k++) { + if (workLimiterBandTable[loLimIndex] == patchBorders[k]) { + isPatchBorder[0] = 1; + break; + } + } + if (!isPatchBorder[0]) { + workLimiterBandTable[loLimIndex] = highSubband; + nBands--; + } + } + loLimIndex = hiLimIndex; + hiLimIndex++; + } + shellsort(workLimiterBandTable, tempNoLim + 1); + + /* Test if algorithm exceeded maximum allowed limiterbands */ + if (nBands > MAX_NUM_LIMITERS || nBands <= 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Restrict maximum value of limiter band table */ + if (workLimiterBandTable[tempNoLim] > highSubband) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Copy limiterbands from working buffer into final destination */ + for (k = 0; k <= nBands; k++) { + limiterBandTable[k] = workLimiterBandTable[k]; + } + } + *noLimiterBands = nBands; + + return SBRDEC_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_calc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_calc.h new file mode 100644 index 0000000000000..cff365d0bd707 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_calc.h @@ -0,0 +1,182 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Envelope calculation prototypes +*/ +#ifndef ENV_CALC_H +#define ENV_CALC_H + +#include "sbrdecoder.h" +#include "env_extr.h" /* for HANDLE_SBR_HEADER_DATA */ + +typedef struct { + FIXP_DBL filtBuffer[MAX_FREQ_COEFFS]; /*!< previous gains (required for + smoothing) */ + FIXP_DBL filtBufferNoise[MAX_FREQ_COEFFS]; /*!< previous noise levels + (required for smoothing) */ + SCHAR filtBuffer_e[MAX_FREQ_COEFFS]; /*!< Exponents of previous gains */ + SCHAR filtBufferNoise_e; /*!< Common exponent of previous noise levels */ + + int startUp; /*!< flag to signal initial conditions in buffers */ + int phaseIndex; /*!< Index for randomPase array */ + int prevTranEnv; /*!< The transient envelope of the previous frame. */ + + ULONG harmFlagsPrev[ADD_HARMONICS_FLAGS_SIZE]; + /*!< Words with 16 flags each indicating where a sine was added in the + * previous frame.*/ + UCHAR harmIndex; /*!< Current phase of synthetic sine */ + int sbrPatchingMode; /*!< Current patching mode */ + + FIXP_SGL prevSbrNoiseFloorLevel[MAX_NOISE_COEFFS]; + UCHAR prevNNfb; + UCHAR prevNSfb[2]; + UCHAR prevLoSubband; + UCHAR prevHiSubband; + UCHAR prev_ov_highSubband; + UCHAR *prevFreqBandTable[2]; + UCHAR prevFreqBandTableLo[MAX_FREQ_COEFFS / 2 + 1]; + UCHAR prevFreqBandTableHi[MAX_FREQ_COEFFS + 1]; + UCHAR prevFreqBandTableNoise[MAX_NOISE_COEFFS + 1]; + SCHAR sinusoidal_positionPrev; + ULONG harmFlagsPrevActive[ADD_HARMONICS_FLAGS_SIZE]; +} SBR_CALCULATE_ENVELOPE; + +typedef SBR_CALCULATE_ENVELOPE *HANDLE_SBR_CALCULATE_ENVELOPE; + +void calculateSbrEnvelope( + QMF_SCALE_FACTOR *sbrScaleFactor, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, + HANDLE_SBR_HEADER_DATA hHeaderData, HANDLE_SBR_FRAME_DATA hFrameData, + PVC_DYNAMIC_DATA *pPvcDynamicData, FIXP_DBL **analysBufferReal, + FIXP_DBL * + *analysBufferImag, /*!< Imag part of subband samples to be processed */ + const int useLP, + FIXP_DBL *degreeAlias, /*!< Estimated aliasing for each QMF channel */ + const UINT flags, const int frameErrorFlag); + +SBR_ERROR +createSbrEnvelopeCalc(HANDLE_SBR_CALCULATE_ENVELOPE hSbrCalculateEnvelope, + HANDLE_SBR_HEADER_DATA hHeaderData, const int chan, + const UINT flags); + +int deleteSbrEnvelopeCalc(HANDLE_SBR_CALCULATE_ENVELOPE hSbrCalculateEnvelope); + +void resetSbrEnvelopeCalc(HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv); + +SBR_ERROR +ResetLimiterBands(UCHAR *limiterBandTable, UCHAR *noLimiterBands, + UCHAR *freqBandTable, int noFreqBands, + const PATCH_PARAM *patchParam, int noPatches, + int limiterBands, UCHAR sbrPatchingMode, + int xOverQmf[MAX_NUM_PATCHES], int sbrRatio); + +void rescaleSubbandSamples(FIXP_DBL **re, FIXP_DBL **im, int lowSubband, + int noSubbands, int start_pos, int next_pos, + int shift); + +FIXP_DBL maxSubbandSample(FIXP_DBL **analysBufferReal_m, + FIXP_DBL **analysBufferImag_m, int lowSubband, + int highSubband, int start_pos, int stop_pos); + +#endif // ENV_CALC_H diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_dec.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_dec.cpp new file mode 100644 index 0000000000000..95807c931012f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_dec.cpp @@ -0,0 +1,873 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief envelope decoding + This module provides envelope decoding and error concealment algorithms. The + main entry point is decodeSbrData(). + + \sa decodeSbrData(),\ref documentationOverview +*/ + +#include "env_dec.h" + +#include "env_extr.h" +#include "transcendent.h" + +#include "genericStds.h" + +static void decodeEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_otherChannel); +static void sbr_envelope_unmapping(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_data_left, + HANDLE_SBR_FRAME_DATA h_data_right); +static void requantizeEnvelopeData(HANDLE_SBR_FRAME_DATA h_sbr_data, + int ampResolution); +static void deltaToLinearPcmEnvelopeDecoding( + HANDLE_SBR_HEADER_DATA hHeaderData, HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); +static void decodeNoiseFloorlevels(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); +static void timeCompensateFirstEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); +static int checkEnvelopeData(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); + +#define SBR_ENERGY_PAN_OFFSET (12 << ENV_EXP_FRACT) +#define SBR_MAX_ENERGY (35 << ENV_EXP_FRACT) + +#define DECAY (1 << ENV_EXP_FRACT) + +#if ENV_EXP_FRACT +#define DECAY_COUPLING \ + (1 << (ENV_EXP_FRACT - 1)) /*!< corresponds to a value of 0.5 */ +#else +#define DECAY_COUPLING \ + 1 /*!< If the energy data is not shifted, use 1 instead of 0.5 */ +#endif + +/*! + \brief Convert table index +*/ +static int indexLow2High(int offset, /*!< mapping factor */ + int index, /*!< index to scalefactor band */ + int res) /*!< frequency resolution */ +{ + if (res == 0) { + if (offset >= 0) { + if (index < offset) + return (index); + else + return (2 * index - offset); + } else { + offset = -offset; + if (index < offset) + return (2 * index + index); + else + return (2 * index + offset); + } + } else + return (index); +} + +/*! + \brief Update previous envelope value for delta-coding + + The current envelope values needs to be stored for delta-coding + in the next frame. The stored envelope is always represented with + the high frequency resolution. If the current envelope uses the + low frequency resolution, the energy value will be mapped to the + corresponding high-res bands. +*/ +static void mapLowResEnergyVal( + FIXP_SGL currVal, /*!< current energy value */ + FIXP_SGL *prevData, /*!< pointer to previous data vector */ + int offset, /*!< mapping factor */ + int index, /*!< index to scalefactor band */ + int res) /*!< frequeny resolution */ +{ + if (res == 0) { + if (offset >= 0) { + if (index < offset) + prevData[index] = currVal; + else { + prevData[2 * index - offset] = currVal; + prevData[2 * index + 1 - offset] = currVal; + } + } else { + offset = -offset; + if (index < offset) { + prevData[3 * index] = currVal; + prevData[3 * index + 1] = currVal; + prevData[3 * index + 2] = currVal; + } else { + prevData[2 * index + offset] = currVal; + prevData[2 * index + 1 + offset] = currVal; + } + } + } else + prevData[index] = currVal; +} + +/*! + \brief Convert raw envelope and noisefloor data to energy levels + + This function is being called by sbrDecoder_ParseElement() and provides two + important algorithms: + + First the function decodes envelopes and noise floor levels as described in + requantizeEnvelopeData() and sbr_envelope_unmapping(). The function also + implements concealment algorithms in case there are errors within the sbr + data. For both operations fractional arithmetic is used. Therefore you might + encounter different output values on your target system compared to the + reference implementation. +*/ +void decodeSbrData( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA + h_data_left, /*!< pointer to left channel frame data */ + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data_left, /*!< pointer to left channel previous frame data */ + HANDLE_SBR_FRAME_DATA + h_data_right, /*!< pointer to right channel frame data */ + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data_right) /*!< pointer to right channel previous frame data */ +{ + FIXP_SGL tempSfbNrgPrev[MAX_FREQ_COEFFS]; + int errLeft; + + /* Save previous energy values to be able to reuse them later for concealment. + */ + FDKmemcpy(tempSfbNrgPrev, h_prev_data_left->sfb_nrg_prev, + MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + + if (hHeaderData->frameErrorFlag || hHeaderData->bs_info.pvc_mode == 0) { + decodeEnvelope(hHeaderData, h_data_left, h_prev_data_left, + h_prev_data_right); + } else { + FDK_ASSERT(h_data_right == NULL); + } + decodeNoiseFloorlevels(hHeaderData, h_data_left, h_prev_data_left); + + if (h_data_right != NULL) { + errLeft = hHeaderData->frameErrorFlag; + decodeEnvelope(hHeaderData, h_data_right, h_prev_data_right, + h_prev_data_left); + decodeNoiseFloorlevels(hHeaderData, h_data_right, h_prev_data_right); + + if (!errLeft && hHeaderData->frameErrorFlag) { + /* If an error occurs in the right channel where the left channel seemed + ok, we apply concealment also on the left channel. This ensures that + the coupling modes of both channels match and that we have the same + number of envelopes in coupling mode. However, as the left channel has + already been processed before, the resulting energy levels are not the + same as if the left channel had been concealed during the first call of + decodeEnvelope(). + */ + /* Restore previous energy values for concealment, because the values have + been overwritten by the first call of decodeEnvelope(). */ + FDKmemcpy(h_prev_data_left->sfb_nrg_prev, tempSfbNrgPrev, + MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + /* Do concealment */ + decodeEnvelope(hHeaderData, h_data_left, h_prev_data_left, + h_prev_data_right); + } + + if (h_data_left->coupling) { + sbr_envelope_unmapping(hHeaderData, h_data_left, h_data_right); + } + } + + /* Display the data for debugging: */ +} + +/*! + \brief Convert from coupled channels to independent L/R data +*/ +static void sbr_envelope_unmapping( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_data_left, /*!< pointer to left channel */ + HANDLE_SBR_FRAME_DATA h_data_right) /*!< pointer to right channel */ +{ + int i; + FIXP_SGL tempL_m, tempR_m, tempRplus1_m, newL_m, newR_m; + SCHAR tempL_e, tempR_e, tempRplus1_e, newL_e, newR_e; + + /* 1. Unmap (already dequantized) coupled envelope energies */ + + for (i = 0; i < h_data_left->nScaleFactors; i++) { + tempR_m = (FIXP_SGL)((LONG)h_data_right->iEnvelope[i] & MASK_M); + tempR_e = (SCHAR)((LONG)h_data_right->iEnvelope[i] & MASK_E); + + tempR_e -= (18 + NRG_EXP_OFFSET); /* -18 = ld(UNMAPPING_SCALE / + h_data_right->nChannels) */ + tempL_m = (FIXP_SGL)((LONG)h_data_left->iEnvelope[i] & MASK_M); + tempL_e = (SCHAR)((LONG)h_data_left->iEnvelope[i] & MASK_E); + + tempL_e -= NRG_EXP_OFFSET; + + /* Calculate tempRight+1 */ + FDK_add_MantExp(tempR_m, tempR_e, FL2FXCONST_SGL(0.5f), 1, /* 1.0 */ + &tempRplus1_m, &tempRplus1_e); + + FDK_divide_MantExp(tempL_m, tempL_e + 1, /* 2 * tempLeft */ + tempRplus1_m, tempRplus1_e, &newR_m, &newR_e); + + if (newR_m >= ((FIXP_SGL)MAXVAL_SGL - ROUNDING)) { + newR_m >>= 1; + newR_e += 1; + } + + newL_m = FX_DBL2FX_SGL(fMult(tempR_m, newR_m)); + newL_e = tempR_e + newR_e; + + h_data_right->iEnvelope[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)(newR_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newR_e + NRG_EXP_OFFSET) & MASK_E); + h_data_left->iEnvelope[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)(newL_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newL_e + NRG_EXP_OFFSET) & MASK_E); + } + + /* 2. Dequantize and unmap coupled noise floor levels */ + + for (i = 0; i < hHeaderData->freqBandData.nNfb * + h_data_left->frameInfo.nNoiseEnvelopes; + i++) { + tempL_e = (SCHAR)(6 - (LONG)h_data_left->sbrNoiseFloorLevel[i]); + tempR_e = (SCHAR)((LONG)h_data_right->sbrNoiseFloorLevel[i] - + 12) /*SBR_ENERGY_PAN_OFFSET*/; + + /* Calculate tempR+1 */ + FDK_add_MantExp(FL2FXCONST_SGL(0.5f), 1 + tempR_e, /* tempR */ + FL2FXCONST_SGL(0.5f), 1, /* 1.0 */ + &tempRplus1_m, &tempRplus1_e); + + /* Calculate 2*tempLeft/(tempR+1) */ + FDK_divide_MantExp(FL2FXCONST_SGL(0.5f), tempL_e + 2, /* 2 * tempLeft */ + tempRplus1_m, tempRplus1_e, &newR_m, &newR_e); + + /* if (newR_m >= ((FIXP_SGL)MAXVAL_SGL - ROUNDING)) { + newR_m >>= 1; + newR_e += 1; + } */ + + /* L = tempR * R */ + newL_m = newR_m; + newL_e = newR_e + tempR_e; + h_data_right->sbrNoiseFloorLevel[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)(newR_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newR_e + NOISE_EXP_OFFSET) & MASK_E); + h_data_left->sbrNoiseFloorLevel[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)(newL_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newL_e + NOISE_EXP_OFFSET) & MASK_E); + } +} + +/*! + \brief Simple alternative to the real SBR concealment + + If the real frameInfo is not available due to a frame loss, a replacement will + be constructed with 1 envelope spanning the whole frame (FIX-FIX). + The delta-coded energies are set to negative values, resulting in a fade-down. + In case of coupling, the balance-channel will move towards the center. +*/ +static void leanSbrConcealment( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data /*!< pointer to data of last frame */ +) { + FIXP_SGL target; /* targeted level for sfb_nrg_prev during fade-down */ + FIXP_SGL step; /* speed of fade */ + int i; + + int currentStartPos = + fMax(0, h_prev_data->stopPos - hHeaderData->numberTimeSlots); + int currentStopPos = hHeaderData->numberTimeSlots; + + /* Use some settings of the previous frame */ + h_sbr_data->ampResolutionCurrentFrame = h_prev_data->ampRes; + h_sbr_data->coupling = h_prev_data->coupling; + for (i = 0; i < MAX_INVF_BANDS; i++) + h_sbr_data->sbr_invf_mode[i] = h_prev_data->sbr_invf_mode[i]; + + /* Generate concealing control data */ + + h_sbr_data->frameInfo.nEnvelopes = 1; + h_sbr_data->frameInfo.borders[0] = currentStartPos; + h_sbr_data->frameInfo.borders[1] = currentStopPos; + h_sbr_data->frameInfo.freqRes[0] = 1; + h_sbr_data->frameInfo.tranEnv = -1; /* no transient */ + h_sbr_data->frameInfo.nNoiseEnvelopes = 1; + h_sbr_data->frameInfo.bordersNoise[0] = currentStartPos; + h_sbr_data->frameInfo.bordersNoise[1] = currentStopPos; + + h_sbr_data->nScaleFactors = hHeaderData->freqBandData.nSfb[1]; + + /* Generate fake envelope data */ + + h_sbr_data->domain_vec[0] = 1; + + if (h_sbr_data->coupling == COUPLING_BAL) { + target = (FIXP_SGL)SBR_ENERGY_PAN_OFFSET; + step = (FIXP_SGL)DECAY_COUPLING; + } else { + target = FL2FXCONST_SGL(0.0f); + step = (FIXP_SGL)DECAY; + } + if (hHeaderData->bs_info.ampResolution == 0) { + target <<= 1; + step <<= 1; + } + + for (i = 0; i < h_sbr_data->nScaleFactors; i++) { + if (h_prev_data->sfb_nrg_prev[i] > target) + h_sbr_data->iEnvelope[i] = -step; + else + h_sbr_data->iEnvelope[i] = step; + } + + /* Noisefloor levels are always cleared ... */ + + h_sbr_data->domain_vec_noise[0] = 1; + FDKmemclear(h_sbr_data->sbrNoiseFloorLevel, + sizeof(h_sbr_data->sbrNoiseFloorLevel)); + + /* ... and so are the sines */ + FDKmemclear(h_sbr_data->addHarmonics, + sizeof(ULONG) * ADD_HARMONICS_FLAGS_SIZE); +} + +/*! + \brief Build reference energies and noise levels from bitstream elements +*/ +static void decodeEnvelope( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data, /*!< pointer to data of last frame */ + HANDLE_SBR_PREV_FRAME_DATA + otherChannel /*!< other channel's last frame data */ +) { + int i; + int fFrameError = hHeaderData->frameErrorFlag; + FIXP_SGL tempSfbNrgPrev[MAX_FREQ_COEFFS]; + + if (!fFrameError) { + /* + To avoid distortions after bad frames, set the error flag if delta coding + in time occurs. However, SBR can take a little longer to come up again. + */ + if (h_prev_data->frameErrorFlag) { + if (h_sbr_data->domain_vec[0] != 0) { + fFrameError = 1; + } + } else { + /* Check that the previous stop position and the current start position + match. (Could be done in checkFrameInfo(), but the previous frame data + is not available there) */ + if (h_sbr_data->frameInfo.borders[0] != + h_prev_data->stopPos - hHeaderData->numberTimeSlots) { + /* Both the previous as well as the current frame are flagged to be ok, + * but they do not match! */ + if (h_sbr_data->domain_vec[0] == 1) { + /* Prefer concealment over delta-time coding between the mismatching + * frames */ + fFrameError = 1; + } else { + /* Close the gap in time by triggering timeCompensateFirstEnvelope() + */ + fFrameError = 1; + } + } + } + } + + if (fFrameError) /* Error is detected */ + { + leanSbrConcealment(hHeaderData, h_sbr_data, h_prev_data); + + /* decode the envelope data to linear PCM */ + deltaToLinearPcmEnvelopeDecoding(hHeaderData, h_sbr_data, h_prev_data); + } else /*Do a temporary dummy decoding and check that the envelope values are + within limits */ + { + if (h_prev_data->frameErrorFlag) { + timeCompensateFirstEnvelope(hHeaderData, h_sbr_data, h_prev_data); + if (h_sbr_data->coupling != h_prev_data->coupling) { + /* + Coupling mode has changed during concealment. + The stored energy levels need to be converted. + */ + for (i = 0; i < hHeaderData->freqBandData.nSfb[1]; i++) { + /* Former Level-Channel will be used for both channels */ + if (h_prev_data->coupling == COUPLING_BAL) { + h_prev_data->sfb_nrg_prev[i] = + (otherChannel != NULL) ? otherChannel->sfb_nrg_prev[i] + : (FIXP_SGL)SBR_ENERGY_PAN_OFFSET; + } + /* Former L/R will be combined as the new Level-Channel */ + else if (h_sbr_data->coupling == COUPLING_LEVEL && + otherChannel != NULL) { + h_prev_data->sfb_nrg_prev[i] = (h_prev_data->sfb_nrg_prev[i] + + otherChannel->sfb_nrg_prev[i]) >> + 1; + } else if (h_sbr_data->coupling == COUPLING_BAL) { + h_prev_data->sfb_nrg_prev[i] = (FIXP_SGL)SBR_ENERGY_PAN_OFFSET; + } + } + } + } + FDKmemcpy(tempSfbNrgPrev, h_prev_data->sfb_nrg_prev, + MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + + deltaToLinearPcmEnvelopeDecoding(hHeaderData, h_sbr_data, h_prev_data); + + fFrameError = checkEnvelopeData(hHeaderData, h_sbr_data, h_prev_data); + + if (fFrameError) { + hHeaderData->frameErrorFlag = 1; + FDKmemcpy(h_prev_data->sfb_nrg_prev, tempSfbNrgPrev, + MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + decodeEnvelope(hHeaderData, h_sbr_data, h_prev_data, otherChannel); + return; + } + } + + requantizeEnvelopeData(h_sbr_data, h_sbr_data->ampResolutionCurrentFrame); + + hHeaderData->frameErrorFlag = fFrameError; +} + +/*! + \brief Verify that envelope energies are within the allowed range + \return 0 if all is fine, 1 if an envelope value was too high +*/ +static int checkEnvelopeData( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data /*!< pointer to data of last frame */ +) { + FIXP_SGL *iEnvelope = h_sbr_data->iEnvelope; + FIXP_SGL *sfb_nrg_prev = h_prev_data->sfb_nrg_prev; + int i = 0, errorFlag = 0; + FIXP_SGL sbr_max_energy = (h_sbr_data->ampResolutionCurrentFrame == 1) + ? SBR_MAX_ENERGY + : (SBR_MAX_ENERGY << 1); + + /* + Range check for current energies + */ + for (i = 0; i < h_sbr_data->nScaleFactors; i++) { + if (iEnvelope[i] > sbr_max_energy) { + errorFlag = 1; + } + if (iEnvelope[i] < FL2FXCONST_SGL(0.0f)) { + errorFlag = 1; + /* iEnvelope[i] = FL2FXCONST_SGL(0.0f); */ + } + } + + /* + Range check for previous energies + */ + for (i = 0; i < hHeaderData->freqBandData.nSfb[1]; i++) { + sfb_nrg_prev[i] = fixMax(sfb_nrg_prev[i], FL2FXCONST_SGL(0.0f)); + sfb_nrg_prev[i] = fixMin(sfb_nrg_prev[i], sbr_max_energy); + } + + return (errorFlag); +} + +/*! + \brief Verify that the noise levels are within the allowed range + + The function is equivalent to checkEnvelopeData(). + When the noise-levels are being decoded, it is already too late for + concealment. Therefore the noise levels are simply limited here. +*/ +static void limitNoiseLevels( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data) /*!< pointer to current data */ +{ + int i; + int nNfb = hHeaderData->freqBandData.nNfb; + +/* + Set range limits. The exact values depend on the coupling mode. + However this limitation is primarily intended to avoid unlimited + accumulation of the delta-coded noise levels. +*/ +#define lowerLimit \ + ((FIXP_SGL)0) /* lowerLimit actually refers to the _highest_ noise energy */ +#define upperLimit \ + ((FIXP_SGL)35) /* upperLimit actually refers to the _lowest_ noise energy */ + + /* + Range check for current noise levels + */ + for (i = 0; i < h_sbr_data->frameInfo.nNoiseEnvelopes * nNfb; i++) { + h_sbr_data->sbrNoiseFloorLevel[i] = + fixMin(h_sbr_data->sbrNoiseFloorLevel[i], upperLimit); + h_sbr_data->sbrNoiseFloorLevel[i] = + fixMax(h_sbr_data->sbrNoiseFloorLevel[i], lowerLimit); + } +} + +/*! + \brief Compensate for the wrong timing that might occur after a frame error. +*/ +static void timeCompensateFirstEnvelope( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to actual data */ + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data) /*!< pointer to data of last frame */ +{ + int i, nScalefactors; + FRAME_INFO *pFrameInfo = &h_sbr_data->frameInfo; + UCHAR *nSfb = hHeaderData->freqBandData.nSfb; + int estimatedStartPos = + fMax(0, h_prev_data->stopPos - hHeaderData->numberTimeSlots); + int refLen, newLen, shift; + FIXP_SGL deltaExp; + + /* Original length of first envelope according to bitstream */ + refLen = pFrameInfo->borders[1] - pFrameInfo->borders[0]; + /* Corrected length of first envelope (concealing can make the first envelope + * longer) */ + newLen = pFrameInfo->borders[1] - estimatedStartPos; + + if (newLen <= 0) { + /* An envelope length of <= 0 would not work, so we don't use it. + May occur if the previous frame was flagged bad due to a mismatch + of the old and new frame infos. */ + newLen = refLen; + estimatedStartPos = pFrameInfo->borders[0]; + } + + deltaExp = FDK_getNumOctavesDiv8(newLen, refLen); + + /* Shift by -3 to rescale ld-table, ampRes-1 to enable coarser steps */ + shift = (FRACT_BITS - 1 - ENV_EXP_FRACT - 1 + + h_sbr_data->ampResolutionCurrentFrame - 3); + deltaExp = deltaExp >> shift; + pFrameInfo->borders[0] = estimatedStartPos; + pFrameInfo->bordersNoise[0] = estimatedStartPos; + + if (h_sbr_data->coupling != COUPLING_BAL) { + nScalefactors = (pFrameInfo->freqRes[0]) ? nSfb[1] : nSfb[0]; + + for (i = 0; i < nScalefactors; i++) + h_sbr_data->iEnvelope[i] = h_sbr_data->iEnvelope[i] + deltaExp; + } +} + +/*! + \brief Convert each envelope value from logarithmic to linear domain + + Energy levels are transmitted in powers of 2, i.e. only the exponent + is extracted from the bitstream. + Therefore, normally only integer exponents can occur. However during + fading (in case of a corrupt bitstream), a fractional part can also + occur. The data in the array iEnvelope is shifted left by ENV_EXP_FRACT + compared to an integer representation so that numbers smaller than 1 + can be represented. + + This function calculates a mantissa corresponding to the fractional + part of the exponent for each reference energy. The array iEnvelope + is converted in place to save memory. Input and output data must + be interpreted differently, as shown in the below figure: + + \image html EnvelopeData.png + + The data is then used in calculateSbrEnvelope(). +*/ +static void requantizeEnvelopeData(HANDLE_SBR_FRAME_DATA h_sbr_data, + int ampResolution) { + int i; + FIXP_SGL mantissa; + int ampShift = 1 - ampResolution; + int exponent; + + /* In case that ENV_EXP_FRACT is changed to something else but 0 or 8, + the initialization of this array has to be adapted! + */ +#if ENV_EXP_FRACT + static const FIXP_SGL pow2[ENV_EXP_FRACT] = { + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 1))), /* 0.7071 */ + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 2))), /* 0.5946 */ + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 3))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 4))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 5))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 6))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 7))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 8))) /* 0.5013 */ + }; + + int bit, mask; +#endif + + for (i = 0; i < h_sbr_data->nScaleFactors; i++) { + exponent = (LONG)h_sbr_data->iEnvelope[i]; + +#if ENV_EXP_FRACT + + exponent = exponent >> ampShift; + mantissa = 0.5f; + + /* Amplify mantissa according to the fractional part of the + exponent (result will be between 0.500000 and 0.999999) + */ + mask = 1; /* begin with lowest bit of exponent */ + + for (bit = ENV_EXP_FRACT - 1; bit >= 0; bit--) { + if (exponent & mask) { + /* The current bit of the exponent is set, + multiply mantissa with the corresponding factor: */ + mantissa = (FIXP_SGL)((mantissa * pow2[bit]) << 1); + } + /* Advance to next bit */ + mask = mask << 1; + } + + /* Make integer part of exponent right aligned */ + exponent = exponent >> ENV_EXP_FRACT; + +#else + /* In case of the high amplitude resolution, 1 bit of the exponent gets lost + by the shift. This will be compensated by a mantissa of 0.5*sqrt(2) + instead of 0.5 if that bit is 1. */ + mantissa = (exponent & ampShift) ? FL2FXCONST_SGL(0.707106781186548f) + : FL2FXCONST_SGL(0.5f); + exponent = exponent >> ampShift; +#endif + + /* + Mantissa was set to 0.5 (instead of 1.0, therefore increase exponent by + 1). Multiply by L=nChannels=64 by increasing exponent by another 6. + => Increase exponent by 7 + */ + exponent += 7 + NRG_EXP_OFFSET; + + /* Combine mantissa and exponent and write back the result */ + h_sbr_data->iEnvelope[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)mantissa & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)exponent & MASK_E); + } +} + +/*! + \brief Build new reference energies from old ones and delta coded data +*/ +static void deltaToLinearPcmEnvelopeDecoding( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data) /*!< pointer to previous data */ +{ + int i, domain, no_of_bands, band, freqRes; + + FIXP_SGL *sfb_nrg_prev = h_prev_data->sfb_nrg_prev; + FIXP_SGL *ptr_nrg = h_sbr_data->iEnvelope; + + int offset = + 2 * hHeaderData->freqBandData.nSfb[0] - hHeaderData->freqBandData.nSfb[1]; + + for (i = 0; i < h_sbr_data->frameInfo.nEnvelopes; i++) { + domain = h_sbr_data->domain_vec[i]; + freqRes = h_sbr_data->frameInfo.freqRes[i]; + + FDK_ASSERT(freqRes >= 0 && freqRes <= 1); + + no_of_bands = hHeaderData->freqBandData.nSfb[freqRes]; + + FDK_ASSERT(no_of_bands < (64)); + + if (domain == 0) { + mapLowResEnergyVal(*ptr_nrg, sfb_nrg_prev, offset, 0, freqRes); + ptr_nrg++; + for (band = 1; band < no_of_bands; band++) { + *ptr_nrg = *ptr_nrg + *(ptr_nrg - 1); + mapLowResEnergyVal(*ptr_nrg, sfb_nrg_prev, offset, band, freqRes); + ptr_nrg++; + } + } else { + for (band = 0; band < no_of_bands; band++) { + *ptr_nrg = + *ptr_nrg + sfb_nrg_prev[indexLow2High(offset, band, freqRes)]; + mapLowResEnergyVal(*ptr_nrg, sfb_nrg_prev, offset, band, freqRes); + ptr_nrg++; + } + } + } +} + +/*! + \brief Build new noise levels from old ones and delta coded data +*/ +static void decodeNoiseFloorlevels( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data) /*!< pointer to previous data */ +{ + int i; + int nNfb = hHeaderData->freqBandData.nNfb; + int nNoiseFloorEnvelopes = h_sbr_data->frameInfo.nNoiseEnvelopes; + + /* Decode first noise envelope */ + + if (h_sbr_data->domain_vec_noise[0] == 0) { + FIXP_SGL noiseLevel = h_sbr_data->sbrNoiseFloorLevel[0]; + for (i = 1; i < nNfb; i++) { + noiseLevel += h_sbr_data->sbrNoiseFloorLevel[i]; + h_sbr_data->sbrNoiseFloorLevel[i] = noiseLevel; + } + } else { + for (i = 0; i < nNfb; i++) { + h_sbr_data->sbrNoiseFloorLevel[i] += h_prev_data->prevNoiseLevel[i]; + } + } + + /* If present, decode the second noise envelope + Note: nNoiseFloorEnvelopes can only be 1 or 2 */ + + if (nNoiseFloorEnvelopes > 1) { + if (h_sbr_data->domain_vec_noise[1] == 0) { + FIXP_SGL noiseLevel = h_sbr_data->sbrNoiseFloorLevel[nNfb]; + for (i = nNfb + 1; i < 2 * nNfb; i++) { + noiseLevel += h_sbr_data->sbrNoiseFloorLevel[i]; + h_sbr_data->sbrNoiseFloorLevel[i] = noiseLevel; + } + } else { + for (i = 0; i < nNfb; i++) { + h_sbr_data->sbrNoiseFloorLevel[i + nNfb] += + h_sbr_data->sbrNoiseFloorLevel[i]; + } + } + } + + limitNoiseLevels(hHeaderData, h_sbr_data); + + /* Update prevNoiseLevel with the last noise envelope */ + for (i = 0; i < nNfb; i++) + h_prev_data->prevNoiseLevel[i] = + h_sbr_data->sbrNoiseFloorLevel[i + nNfb * (nNoiseFloorEnvelopes - 1)]; + + /* Requantize the noise floor levels in COUPLING_OFF-mode */ + if (!h_sbr_data->coupling) { + int nf_e; + + for (i = 0; i < nNoiseFloorEnvelopes * nNfb; i++) { + nf_e = 6 - (LONG)h_sbr_data->sbrNoiseFloorLevel[i] + 1 + NOISE_EXP_OFFSET; + /* +1 to compensate for a mantissa of 0.5 instead of 1.0 */ + + h_sbr_data->sbrNoiseFloorLevel[i] = + (FIXP_SGL)(((LONG)FL2FXCONST_SGL(0.5f)) + /* mantissa */ + (nf_e & MASK_E)); /* exponent */ + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_dec.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_dec.h new file mode 100644 index 0000000000000..0b11ce1a6fe20 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_dec.h @@ -0,0 +1,119 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Envelope decoding +*/ +#ifndef ENV_DEC_H +#define ENV_DEC_H + +#include "sbrdecoder.h" +#include "env_extr.h" + +void decodeSbrData(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_data_left, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_left, + HANDLE_SBR_FRAME_DATA h_data_right, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_right); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_extr.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_extr.cpp new file mode 100644 index 0000000000000..5b7a0b120cccd --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_extr.cpp @@ -0,0 +1,1732 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Envelope extraction + The functions provided by this module are mostly called by applySBR(). After + it is determined that there is valid SBR data, sbrGetHeaderData() might be + called if the current SBR data contains an \ref SBR_HEADER_ELEMENT as opposed + to a \ref SBR_STANDARD_ELEMENT. This function may return various error codes + as defined in #SBR_HEADER_STATUS . Most importantly it returns HEADER_RESET + when decoder settings need to be recalculated according to the SBR + specifications. In that case applySBR() will initiatite the required + re-configuration. + + The header data is stored in a #SBR_HEADER_DATA structure. + + The actual SBR data for the current frame is decoded into SBR_FRAME_DATA + stuctures by sbrGetChannelPairElement() [for stereo streams] and + sbrGetSingleChannelElement() [for mono streams]. There is no fractional + arithmetic involved. + + Once the information is extracted, the data needs to be further prepared + before the actual decoding process. This is done in decodeSbrData(). + + \sa Description of buffer management in applySBR(). \ref documentationOverview + +

About the SBR data format:

+ + Each frame includes SBR data (side chain information), and can be either the + \ref SBR_HEADER_ELEMENT or the \ref SBR_STANDARD_ELEMENT. Parts of the data + can be protected by a CRC checksum. + + \anchor SBR_HEADER_ELEMENT

The SBR_HEADER_ELEMENT

+ + The SBR_HEADER_ELEMENT can be transmitted with every frame, however, it + typically is send every second or so. It contains fundamental information such + as SBR sampling frequency and frequency range as well as control signals that + do not require frequent changes. It also includes the \ref + SBR_STANDARD_ELEMENT. + + Depending on the changes between the information in a current + SBR_HEADER_ELEMENT and the previous SBR_HEADER_ELEMENT, the SBR decoder might + need to be reset and reconfigured (e.g. new tables need to be calculated). + + \anchor SBR_STANDARD_ELEMENT

The SBR_STANDARD_ELEMENT

+ + This data can be subdivided into "side info" and "raw data", where side info + is defined as signals needed to decode the raw data and some decoder tuning + signals. Raw data is referred to as PCM and Huffman coded envelope and noise + floor estimates. The side info also includes information about the + time-frequency grid for the current frame. + + \sa \ref documentationOverview +*/ + +#include "env_extr.h" + +#include "sbr_ram.h" +#include "sbr_rom.h" +#include "huff_dec.h" + +#include "psbitdec.h" + +#define DRM_PARAMETRIC_STEREO 0 +#define EXTENSION_ID_PS_CODING 2 + +static int extractPvcFrameInfo( + HANDLE_FDK_BITSTREAM hBs, /*!< bitbuffer handle */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the + frame-info will be stored */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_frame_data, /*!< pointer to memory where + the previous frame-info + will be stored */ + UCHAR pvc_mode_last, /**< PVC mode of last frame */ + const UINT flags); +static int extractFrameInfo(HANDLE_FDK_BITSTREAM hBs, + HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_frame_data, + const UINT nrOfChannels, const UINT flags); + +static int sbrGetPvcEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_frame_data, + HANDLE_FDK_BITSTREAM hBs, const UINT flags, + const UINT pvcMode); +static int sbrGetEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_frame_data, + HANDLE_FDK_BITSTREAM hBs, const UINT flags); + +static void sbrGetDirectionControlData(HANDLE_SBR_FRAME_DATA hFrameData, + HANDLE_FDK_BITSTREAM hBs, + const UINT flags, const int bs_pvc_mode); + +static void sbrGetNoiseFloorData(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_frame_data, + HANDLE_FDK_BITSTREAM hBs); + +static int checkFrameInfo(FRAME_INFO *pFrameInfo, int numberOfTimeSlots, + int overlap, int timeStep); + +/* Mapping to std samplerate table according to 14496-3 (4.6.18.2.6) */ +typedef struct SR_MAPPING { + UINT fsRangeLo; /* If fsRangeLo(n+1)>fs>=fsRangeLo(n), it will be mapped to... + */ + UINT fsMapped; /* fsMapped. */ +} SR_MAPPING; + +static const SR_MAPPING stdSampleRatesMapping[] = { + {0, 8000}, {9391, 11025}, {11502, 12000}, {13856, 16000}, + {18783, 22050}, {23004, 24000}, {27713, 32000}, {37566, 44100}, + {46009, 48000}, {55426, 64000}, {75132, 88200}, {92017, 96000}}; +static const SR_MAPPING stdSampleRatesMappingUsac[] = { + {0, 16000}, {18783, 22050}, {23004, 24000}, {27713, 32000}, + {35777, 40000}, {42000, 44100}, {46009, 48000}, {55426, 64000}, + {75132, 88200}, {92017, 96000}}; + +UINT sbrdec_mapToStdSampleRate(UINT fs, + UINT isUsac) /*!< Output sampling frequency */ +{ + UINT fsMapped = fs, tableSize = 0; + const SR_MAPPING *mappingTable; + int i; + + if (!isUsac) { + mappingTable = stdSampleRatesMapping; + tableSize = sizeof(stdSampleRatesMapping) / sizeof(SR_MAPPING); + } else { + mappingTable = stdSampleRatesMappingUsac; + tableSize = sizeof(stdSampleRatesMappingUsac) / sizeof(SR_MAPPING); + } + + for (i = tableSize - 1; i >= 0; i--) { + if (fs >= mappingTable[i].fsRangeLo) { + fsMapped = mappingTable[i].fsMapped; + break; + } + } + + return (fsMapped); +} + +SBR_ERROR +initHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData, const int sampleRateIn, + const int sampleRateOut, const INT downscaleFactor, + const int samplesPerFrame, const UINT flags, + const int setDefaultHdr) { + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + SBR_ERROR sbrError = SBRDEC_OK; + int numAnalysisBands; + int sampleRateProc; + + if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) { + sampleRateProc = + sbrdec_mapToStdSampleRate(sampleRateOut * downscaleFactor, 0); + } else { + sampleRateProc = sampleRateOut * downscaleFactor; + } + + if (sampleRateIn == sampleRateOut) { + hHeaderData->sbrProcSmplRate = sampleRateProc << 1; + numAnalysisBands = 32; + } else { + hHeaderData->sbrProcSmplRate = sampleRateProc; + if ((sampleRateOut >> 1) == sampleRateIn) { + /* 1:2 */ + numAnalysisBands = 32; + } else if ((sampleRateOut >> 2) == sampleRateIn) { + /* 1:4 */ + numAnalysisBands = 16; + } else if ((sampleRateOut * 3) >> 3 == (sampleRateIn * 8) >> 3) { + /* 3:8, 3/4 core frame length */ + numAnalysisBands = 24; + } else { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + } + numAnalysisBands /= downscaleFactor; + + if (setDefaultHdr) { + /* Fill in default values first */ + hHeaderData->syncState = SBR_NOT_INITIALIZED; + hHeaderData->status = 0; + hHeaderData->frameErrorFlag = 0; + + hHeaderData->bs_info.ampResolution = 1; + hHeaderData->bs_info.xover_band = 0; + hHeaderData->bs_info.sbr_preprocessing = 0; + hHeaderData->bs_info.pvc_mode = 0; + + hHeaderData->bs_data.startFreq = 5; + hHeaderData->bs_data.stopFreq = 0; + hHeaderData->bs_data.freqScale = + 0; /* previously 2; for ELD reduced delay bitstreams + /samplerates initializing of the sbr decoder instance fails if + freqScale is set to 2 because no master table can be generated; in + ELD reduced delay bitstreams this value is always 0; gets overwritten + when header is read */ + hHeaderData->bs_data.alterScale = 1; + hHeaderData->bs_data.noise_bands = 2; + hHeaderData->bs_data.limiterBands = 2; + hHeaderData->bs_data.limiterGains = 2; + hHeaderData->bs_data.interpolFreq = 1; + hHeaderData->bs_data.smoothingLength = 1; + + /* Patch some entries */ + if (sampleRateOut * downscaleFactor >= 96000) { + hHeaderData->bs_data.startFreq = + 4; /* having read these frequency values from bit stream before. */ + hHeaderData->bs_data.stopFreq = 3; + } else if (sampleRateOut * downscaleFactor > + 24000) { /* Trigger an error if SBR is going to be processed + without */ + hHeaderData->bs_data.startFreq = + 7; /* having read these frequency values from bit stream before. */ + hHeaderData->bs_data.stopFreq = 3; + } + } + + if ((sampleRateOut >> 2) == sampleRateIn) { + hHeaderData->timeStep = 4; + } else { + hHeaderData->timeStep = (flags & SBRDEC_ELD_GRID) ? 1 : 2; + } + + /* Setup pointers to frequency band tables */ + hFreq->freqBandTable[0] = hFreq->freqBandTableLo; + hFreq->freqBandTable[1] = hFreq->freqBandTableHi; + + /* One SBR timeslot corresponds to the amount of samples equal to the amount + * of analysis bands, divided by the timestep. */ + hHeaderData->numberTimeSlots = + (samplesPerFrame / numAnalysisBands) >> (hHeaderData->timeStep - 1); + if (hHeaderData->numberTimeSlots > (16)) { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + } + + hHeaderData->numberOfAnalysisBands = numAnalysisBands; + if ((sampleRateOut >> 2) == sampleRateIn) { + hHeaderData->numberTimeSlots <<= 1; + } + +bail: + return sbrError; +} + +/*! + \brief Initialize the SBR_PREV_FRAME_DATA struct +*/ +void initSbrPrevFrameData( + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data, /*!< handle to struct SBR_PREV_FRAME_DATA */ + int timeSlots) /*!< Framelength in SBR-timeslots */ +{ + int i; + + /* Set previous energy and noise levels to 0 for the case + that decoding starts in the middle of a bitstream */ + for (i = 0; i < MAX_FREQ_COEFFS; i++) + h_prev_data->sfb_nrg_prev[i] = (FIXP_DBL)0; + for (i = 0; i < MAX_NOISE_COEFFS; i++) + h_prev_data->prevNoiseLevel[i] = (FIXP_DBL)0; + for (i = 0; i < MAX_INVF_BANDS; i++) h_prev_data->sbr_invf_mode[i] = INVF_OFF; + + h_prev_data->stopPos = timeSlots; + h_prev_data->coupling = COUPLING_OFF; + h_prev_data->ampRes = 0; + + FDKmemclear(&h_prev_data->prevFrameInfo, sizeof(h_prev_data->prevFrameInfo)); +} + +/*! + \brief Read header data from bitstream + + \return error status - 0 if ok +*/ +SBR_HEADER_STATUS +sbrGetHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData, HANDLE_FDK_BITSTREAM hBs, + const UINT flags, const int fIsSbrData, + const UCHAR configMode) { + SBR_HEADER_DATA_BS *pBsData; + SBR_HEADER_DATA_BS lastHeader; + SBR_HEADER_DATA_BS_INFO lastInfo; + int headerExtra1 = 0, headerExtra2 = 0; + + /* Read and discard new header in config change detection mode */ + if (configMode & AC_CM_DET_CFG_CHANGE) { + if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) { + /* ampResolution */ + FDKreadBits(hBs, 1); + } + /* startFreq, stopFreq */ + FDKpushFor(hBs, 8); + if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) { + /* xover_band */ + FDKreadBits(hBs, 3); + /* reserved bits */ + FDKreadBits(hBs, 2); + } + headerExtra1 = FDKreadBit(hBs); + headerExtra2 = FDKreadBit(hBs); + FDKpushFor(hBs, 5 * headerExtra1 + 6 * headerExtra2); + + return HEADER_OK; + } + + /* Copy SBR bit stream header to temporary header */ + lastHeader = hHeaderData->bs_data; + lastInfo = hHeaderData->bs_info; + + /* Read new header from bitstream */ + if ((flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC)) && !fIsSbrData) { + pBsData = &hHeaderData->bs_dflt; + } else { + pBsData = &hHeaderData->bs_data; + } + + if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) { + hHeaderData->bs_info.ampResolution = FDKreadBits(hBs, 1); + } + + pBsData->startFreq = FDKreadBits(hBs, 4); + pBsData->stopFreq = FDKreadBits(hBs, 4); + + if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) { + hHeaderData->bs_info.xover_band = FDKreadBits(hBs, 3); + FDKreadBits(hBs, 2); + } + + headerExtra1 = FDKreadBits(hBs, 1); + headerExtra2 = FDKreadBits(hBs, 1); + + /* Handle extra header information */ + if (headerExtra1) { + pBsData->freqScale = FDKreadBits(hBs, 2); + pBsData->alterScale = FDKreadBits(hBs, 1); + pBsData->noise_bands = FDKreadBits(hBs, 2); + } else { + pBsData->freqScale = 2; + pBsData->alterScale = 1; + pBsData->noise_bands = 2; + } + + if (headerExtra2) { + pBsData->limiterBands = FDKreadBits(hBs, 2); + pBsData->limiterGains = FDKreadBits(hBs, 2); + pBsData->interpolFreq = FDKreadBits(hBs, 1); + pBsData->smoothingLength = FDKreadBits(hBs, 1); + } else { + pBsData->limiterBands = 2; + pBsData->limiterGains = 2; + pBsData->interpolFreq = 1; + pBsData->smoothingLength = 1; + } + + /* Look for new settings. IEC 14496-3, 4.6.18.3.1 */ + if (hHeaderData->syncState < SBR_HEADER || + lastHeader.startFreq != pBsData->startFreq || + lastHeader.stopFreq != pBsData->stopFreq || + lastHeader.freqScale != pBsData->freqScale || + lastHeader.alterScale != pBsData->alterScale || + lastHeader.noise_bands != pBsData->noise_bands || + lastInfo.xover_band != hHeaderData->bs_info.xover_band) { + return HEADER_RESET; /* New settings */ + } + + return HEADER_OK; +} + +/*! + \brief Get missing harmonics parameters (only used for AAC+SBR) + + \return error status - 0 if ok +*/ +int sbrGetSyntheticCodedData(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA hFrameData, + HANDLE_FDK_BITSTREAM hBs, const UINT flags) { + int i, bitsRead = 0; + + int add_harmonic_flag = FDKreadBits(hBs, 1); + bitsRead++; + + if (add_harmonic_flag) { + int nSfb = hHeaderData->freqBandData.nSfb[1]; + for (i = 0; i < ADD_HARMONICS_FLAGS_SIZE; i++) { + /* read maximum 32 bits and align them to the MSB */ + int readBits = fMin(32, nSfb); + nSfb -= readBits; + if (readBits > 0) { + hFrameData->addHarmonics[i] = FDKreadBits(hBs, readBits) + << (32 - readBits); + } else { + hFrameData->addHarmonics[i] = 0; + } + + bitsRead += readBits; + } + /* bs_pvc_mode = 0 for Rsvd50 */ + if (flags & SBRDEC_SYNTAX_USAC) { + if (hHeaderData->bs_info.pvc_mode) { + int bs_sinusoidal_position = 31; + if (FDKreadBit(hBs) /* bs_sinusoidal_position_flag */) { + bs_sinusoidal_position = FDKreadBits(hBs, 5); + } + hFrameData->sinusoidal_position = bs_sinusoidal_position; + } + } + } else { + for (i = 0; i < ADD_HARMONICS_FLAGS_SIZE; i++) + hFrameData->addHarmonics[i] = 0; + } + + return (bitsRead); +} + +/*! + \brief Reads extension data from the bitstream + + The bitstream format allows up to 4 kinds of extended data element. + Extended data may contain several elements, each identified by a 2-bit-ID. + So far, no extended data elements are defined hence the first 2 parameters + are unused. The data should be skipped in order to update the number + of read bits for the consistency check in applySBR(). +*/ +static int extractExtendedData( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< handle to SBR header */ + HANDLE_FDK_BITSTREAM hBs /*!< Handle to the bit buffer */ + , + HANDLE_PS_DEC hParametricStereoDec /*!< Parametric Stereo Decoder */ +) { + INT nBitsLeft; + int extended_data; + int i, frameOk = 1; + + extended_data = FDKreadBits(hBs, 1); + + if (extended_data) { + int cnt; + int bPsRead = 0; + + cnt = FDKreadBits(hBs, 4); + if (cnt == (1 << 4) - 1) cnt += FDKreadBits(hBs, 8); + + nBitsLeft = 8 * cnt; + + /* sanity check for cnt */ + if (nBitsLeft > (INT)FDKgetValidBits(hBs)) { + /* limit nBitsLeft */ + nBitsLeft = (INT)FDKgetValidBits(hBs); + /* set frame error */ + frameOk = 0; + } + + while (nBitsLeft > 7) { + int extension_id = FDKreadBits(hBs, 2); + nBitsLeft -= 2; + + switch (extension_id) { + case EXTENSION_ID_PS_CODING: + + /* Read PS data from bitstream */ + + if (hParametricStereoDec != NULL) { + if (bPsRead && + !hParametricStereoDec->bsData[hParametricStereoDec->bsReadSlot] + .mpeg.bPsHeaderValid) { + cnt = nBitsLeft >> 3; /* number of remaining bytes */ + for (i = 0; i < cnt; i++) FDKreadBits(hBs, 8); + nBitsLeft -= cnt * 8; + } else { + nBitsLeft -= + (INT)ReadPsData(hParametricStereoDec, hBs, nBitsLeft); + bPsRead = 1; + } + } + + /* parametric stereo detected, could set channelMode accordingly here + */ + /* */ + /* "The usage of this parametric stereo extension to HE-AAC is */ + /* signalled implicitly in the bitstream. Hence, if an sbr_extension() + */ + /* with bs_extension_id==EXTENSION_ID_PS is found in the SBR part of + */ + /* the bitstream, a decoder supporting the combination of SBR and PS + */ + /* shall operate the PS tool to generate a stereo output signal." */ + /* source: ISO/IEC 14496-3:2001/FDAM 2:2004(E) */ + + break; + + default: + cnt = nBitsLeft >> 3; /* number of remaining bytes */ + for (i = 0; i < cnt; i++) FDKreadBits(hBs, 8); + nBitsLeft -= cnt * 8; + break; + } + } + + if (nBitsLeft < 0) { + frameOk = 0; + goto bail; + } else { + /* Read fill bits for byte alignment */ + FDKreadBits(hBs, nBitsLeft); + } + } + +bail: + return (frameOk); +} + +/*! + \brief Read bitstream elements of a SBR channel element + \return SbrFrameOK +*/ +int sbrGetChannelElement(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA hFrameDataLeft, + HANDLE_SBR_FRAME_DATA hFrameDataRight, + HANDLE_SBR_PREV_FRAME_DATA hFrameDataLeftPrev, + UCHAR pvc_mode_last, HANDLE_FDK_BITSTREAM hBs, + HANDLE_PS_DEC hParametricStereoDec, const UINT flags, + const int overlap) { + int i, bs_coupling = COUPLING_OFF; + const int nCh = (hFrameDataRight == NULL) ? 1 : 2; + + if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) { + /* Reserved bits */ + if (FDKreadBits(hBs, 1)) { /* bs_data_extra */ + FDKreadBits(hBs, 4); + if ((flags & SBRDEC_SYNTAX_SCAL) || (nCh == 2)) { + FDKreadBits(hBs, 4); + } + } + } + + if (nCh == 2) { + /* Read coupling flag */ + bs_coupling = FDKreadBits(hBs, 1); + if (bs_coupling) { + hFrameDataLeft->coupling = COUPLING_LEVEL; + hFrameDataRight->coupling = COUPLING_BAL; + } else { + hFrameDataLeft->coupling = COUPLING_OFF; + hFrameDataRight->coupling = COUPLING_OFF; + } + } else { + if (flags & SBRDEC_SYNTAX_SCAL) { + FDKreadBits(hBs, 1); /* bs_coupling */ + } + hFrameDataLeft->coupling = COUPLING_OFF; + } + + if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + if (flags & SBRDEC_USAC_HARMONICSBR) { + hFrameDataLeft->sbrPatchingMode = FDKreadBit(hBs); + if (hFrameDataLeft->sbrPatchingMode == 0) { + hFrameDataLeft->sbrOversamplingFlag = FDKreadBit(hBs); + if (FDKreadBit(hBs)) { /* sbrPitchInBinsFlag */ + hFrameDataLeft->sbrPitchInBins = FDKreadBits(hBs, 7); + } else { + hFrameDataLeft->sbrPitchInBins = 0; + } + } else { + hFrameDataLeft->sbrOversamplingFlag = 0; + hFrameDataLeft->sbrPitchInBins = 0; + } + + if (nCh == 2) { + if (bs_coupling) { + hFrameDataRight->sbrPatchingMode = hFrameDataLeft->sbrPatchingMode; + hFrameDataRight->sbrOversamplingFlag = + hFrameDataLeft->sbrOversamplingFlag; + hFrameDataRight->sbrPitchInBins = hFrameDataLeft->sbrPitchInBins; + } else { + hFrameDataRight->sbrPatchingMode = FDKreadBit(hBs); + if (hFrameDataRight->sbrPatchingMode == 0) { + hFrameDataRight->sbrOversamplingFlag = FDKreadBit(hBs); + if (FDKreadBit(hBs)) { /* sbrPitchInBinsFlag */ + hFrameDataRight->sbrPitchInBins = FDKreadBits(hBs, 7); + } else { + hFrameDataRight->sbrPitchInBins = 0; + } + } else { + hFrameDataRight->sbrOversamplingFlag = 0; + hFrameDataRight->sbrPitchInBins = 0; + } + } + } + } else { + if (nCh == 2) { + hFrameDataRight->sbrPatchingMode = 1; + hFrameDataRight->sbrOversamplingFlag = 0; + hFrameDataRight->sbrPitchInBins = 0; + } + + hFrameDataLeft->sbrPatchingMode = 1; + hFrameDataLeft->sbrOversamplingFlag = 0; + hFrameDataLeft->sbrPitchInBins = 0; + } + } else { + if (nCh == 2) { + hFrameDataRight->sbrPatchingMode = 1; + hFrameDataRight->sbrOversamplingFlag = 0; + hFrameDataRight->sbrPitchInBins = 0; + } + + hFrameDataLeft->sbrPatchingMode = 1; + hFrameDataLeft->sbrOversamplingFlag = 0; + hFrameDataLeft->sbrPitchInBins = 0; + } + + /* + sbr_grid(): Grid control + */ + if (hHeaderData->bs_info.pvc_mode) { + FDK_ASSERT(nCh == 1); /* PVC not possible for CPE */ + if (!extractPvcFrameInfo(hBs, hHeaderData, hFrameDataLeft, + hFrameDataLeftPrev, pvc_mode_last, flags)) + return 0; + + if (!checkFrameInfo(&hFrameDataLeft->frameInfo, + hHeaderData->numberTimeSlots, overlap, + hHeaderData->timeStep)) + return 0; + } else { + if (!extractFrameInfo(hBs, hHeaderData, hFrameDataLeft, 1, flags)) return 0; + + if (!checkFrameInfo(&hFrameDataLeft->frameInfo, + hHeaderData->numberTimeSlots, overlap, + hHeaderData->timeStep)) + return 0; + } + if (nCh == 2) { + if (hFrameDataLeft->coupling) { + FDKmemcpy(&hFrameDataRight->frameInfo, &hFrameDataLeft->frameInfo, + sizeof(FRAME_INFO)); + hFrameDataRight->ampResolutionCurrentFrame = + hFrameDataLeft->ampResolutionCurrentFrame; + } else { + if (!extractFrameInfo(hBs, hHeaderData, hFrameDataRight, 2, flags)) + return 0; + + if (!checkFrameInfo(&hFrameDataRight->frameInfo, + hHeaderData->numberTimeSlots, overlap, + hHeaderData->timeStep)) + return 0; + } + } + + /* + sbr_dtdf(): Fetch domain vectors (time or frequency direction for + delta-coding) + */ + sbrGetDirectionControlData(hFrameDataLeft, hBs, flags, + hHeaderData->bs_info.pvc_mode); + if (nCh == 2) { + sbrGetDirectionControlData(hFrameDataRight, hBs, flags, 0); + } + + /* sbr_invf() */ + for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) { + hFrameDataLeft->sbr_invf_mode[i] = (INVF_MODE)FDKreadBits(hBs, 2); + } + if (nCh == 2) { + if (hFrameDataLeft->coupling) { + for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) { + hFrameDataRight->sbr_invf_mode[i] = hFrameDataLeft->sbr_invf_mode[i]; + } + } else { + for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) { + hFrameDataRight->sbr_invf_mode[i] = (INVF_MODE)FDKreadBits(hBs, 2); + } + } + } + + if (nCh == 1) { + if (hHeaderData->bs_info.pvc_mode) { + if (!sbrGetPvcEnvelope(hHeaderData, hFrameDataLeft, hBs, flags, + hHeaderData->bs_info.pvc_mode)) + return 0; + } else if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags)) + return 0; + + sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs); + } else if (hFrameDataLeft->coupling) { + if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags)) { + return 0; + } + + sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs); + + if (!sbrGetEnvelope(hHeaderData, hFrameDataRight, hBs, flags)) { + return 0; + } + sbrGetNoiseFloorData(hHeaderData, hFrameDataRight, hBs); + } else { /* nCh == 2 && no coupling */ + + if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags)) return 0; + + if (!sbrGetEnvelope(hHeaderData, hFrameDataRight, hBs, flags)) return 0; + + sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs); + + sbrGetNoiseFloorData(hHeaderData, hFrameDataRight, hBs); + } + + sbrGetSyntheticCodedData(hHeaderData, hFrameDataLeft, hBs, flags); + if (nCh == 2) { + sbrGetSyntheticCodedData(hHeaderData, hFrameDataRight, hBs, flags); + } + + if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) { + if (!extractExtendedData(hHeaderData, hBs, hParametricStereoDec)) { + return 0; + } + } + + return 1; +} + +/*! + \brief Read direction control data from bitstream +*/ +void sbrGetDirectionControlData( + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */ + const UINT flags, const int bs_pvc_mode) + +{ + int i; + int indepFlag = 0; + + if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + indepFlag = flags & SBRDEC_USAC_INDEP; + } + + if (bs_pvc_mode == 0) { + i = 0; + if (indepFlag) { + h_frame_data->domain_vec[i++] = 0; + } + for (; i < h_frame_data->frameInfo.nEnvelopes; i++) { + h_frame_data->domain_vec[i] = FDKreadBits(hBs, 1); + } + } + + i = 0; + if (indepFlag) { + h_frame_data->domain_vec_noise[i++] = 0; + } + for (; i < h_frame_data->frameInfo.nNoiseEnvelopes; i++) { + h_frame_data->domain_vec_noise[i] = FDKreadBits(hBs, 1); + } +} + +/*! + \brief Read noise-floor-level data from bitstream +*/ +void sbrGetNoiseFloorData( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */ + HANDLE_FDK_BITSTREAM hBs) /*!< handle to struct BIT_BUF */ +{ + int i, j; + int delta; + COUPLING_MODE coupling; + int noNoiseBands = hHeaderData->freqBandData.nNfb; + + Huffman hcb_noiseF; + Huffman hcb_noise; + int envDataTableCompFactor; + + coupling = h_frame_data->coupling; + + /* + Select huffman codebook depending on coupling mode + */ + if (coupling == COUPLING_BAL) { + hcb_noise = (Huffman)&FDK_sbrDecoder_sbr_huffBook_NoiseBalance11T; + hcb_noiseF = + (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11F; /* "sbr_huffBook_NoiseBalance11F" + */ + envDataTableCompFactor = 1; + } else { + hcb_noise = (Huffman)&FDK_sbrDecoder_sbr_huffBook_NoiseLevel11T; + hcb_noiseF = + (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11F; /* "sbr_huffBook_NoiseLevel11F" + */ + envDataTableCompFactor = 0; + } + + /* + Read raw noise-envelope data + */ + for (i = 0; i < h_frame_data->frameInfo.nNoiseEnvelopes; i++) { + if (h_frame_data->domain_vec_noise[i] == 0) { + if (coupling == COUPLING_BAL) { + h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands] = + (FIXP_SGL)(((int)FDKreadBits(hBs, 5)) << envDataTableCompFactor); + } else { + h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands] = + (FIXP_SGL)(int)FDKreadBits(hBs, 5); + } + + for (j = 1; j < noNoiseBands; j++) { + delta = DecodeHuffmanCW(hcb_noiseF, hBs); + h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands + j] = + (FIXP_SGL)(delta << envDataTableCompFactor); + } + } else { + for (j = 0; j < noNoiseBands; j++) { + delta = DecodeHuffmanCW(hcb_noise, hBs); + h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands + j] = + (FIXP_SGL)(delta << envDataTableCompFactor); + } + } + } +} + +/* ns = mapNsMode2ns[pvcMode-1][nsMode] */ +static const UCHAR mapNsMode2ns[2][2] = { + {16, 4}, /* pvcMode = 1 */ + {12, 3} /* pvcMode = 2 */ +}; + +static int sbrGetPvcEnvelope( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */ + const UINT flags, const UINT pvcMode) { + int divMode, nsMode; + int indepFlag = flags & SBRDEC_USAC_INDEP; + UCHAR *pvcID = h_frame_data->pvcID; + + divMode = FDKreadBits(hBs, PVC_DIVMODE_BITS); + nsMode = FDKreadBit(hBs); + FDK_ASSERT((pvcMode == 1) || (pvcMode == 2)); + h_frame_data->ns = mapNsMode2ns[pvcMode - 1][nsMode]; + + if (divMode <= 3) { + int i, k = 1, sum_length = 0, reuse_pcvID; + + /* special treatment for first time slot k=0 */ + indepFlag ? (reuse_pcvID = 0) : (reuse_pcvID = FDKreadBit(hBs)); + if (reuse_pcvID) { + pvcID[0] = hHeaderData->pvcIDprev; + } else { + pvcID[0] = FDKreadBits(hBs, PVC_PVCID_BITS); + } + + /* other time slots k>0 */ + for (i = 0; i < divMode; i++) { + int length, numBits = 4; + + if (sum_length >= 13) { + numBits = 1; + } else if (sum_length >= 11) { + numBits = 2; + } else if (sum_length >= 7) { + numBits = 3; + } + + length = FDKreadBits(hBs, numBits); + sum_length += length + 1; + if (sum_length >= PVC_NTIMESLOT) { + return 0; /* parse error */ + } + for (; length--; k++) { + pvcID[k] = pvcID[k - 1]; + } + pvcID[k++] = FDKreadBits(hBs, PVC_PVCID_BITS); + } + for (; k < 16; k++) { + pvcID[k] = pvcID[k - 1]; + } + } else { /* divMode >= 4 */ + int num_grid_info, fixed_length, grid_info, j, k = 0; + + divMode -= 4; + num_grid_info = 2 << divMode; + fixed_length = 8 >> divMode; + FDK_ASSERT(num_grid_info * fixed_length == PVC_NTIMESLOT); + + /* special treatment for first time slot k=0 */ + indepFlag ? (grid_info = 1) : (grid_info = FDKreadBit(hBs)); + if (grid_info) { + pvcID[k++] = FDKreadBits(hBs, PVC_PVCID_BITS); + } else { + pvcID[k++] = hHeaderData->pvcIDprev; + } + j = fixed_length - 1; + for (; j--; k++) { + pvcID[k] = pvcID[k - 1]; + } + num_grid_info--; + + /* other time slots k>0 */ + for (; num_grid_info--;) { + j = fixed_length; + grid_info = FDKreadBit(hBs); + if (grid_info) { + pvcID[k++] = FDKreadBits(hBs, PVC_PVCID_BITS); + j--; + } + for (; j--; k++) { + pvcID[k] = pvcID[k - 1]; + } + } + } + + hHeaderData->pvcIDprev = pvcID[PVC_NTIMESLOT - 1]; + + /* usage of PVC excludes inter-TES tool */ + h_frame_data->iTESactive = (UCHAR)0; + + return 1; +} +/*! + \brief Read envelope data from bitstream +*/ +static int sbrGetEnvelope( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */ + const UINT flags) { + int i, j; + UCHAR no_band[MAX_ENVELOPES]; + int delta = 0; + int offset = 0; + COUPLING_MODE coupling = h_frame_data->coupling; + int ampRes = hHeaderData->bs_info.ampResolution; + int nEnvelopes = h_frame_data->frameInfo.nEnvelopes; + int envDataTableCompFactor; + int start_bits, start_bits_balance; + Huffman hcb_t, hcb_f; + + h_frame_data->nScaleFactors = 0; + + if ((h_frame_data->frameInfo.frameClass == 0) && (nEnvelopes == 1)) { + if (flags & SBRDEC_ELD_GRID) + ampRes = h_frame_data->ampResolutionCurrentFrame; + else + ampRes = 0; + } + h_frame_data->ampResolutionCurrentFrame = ampRes; + + /* + Set number of bits for first value depending on amplitude resolution + */ + if (ampRes == 1) { + start_bits = 6; + start_bits_balance = 5; + } else { + start_bits = 7; + start_bits_balance = 6; + } + + /* + Calculate number of values for each envelope and alltogether + */ + for (i = 0; i < nEnvelopes; i++) { + no_band[i] = + hHeaderData->freqBandData.nSfb[h_frame_data->frameInfo.freqRes[i]]; + h_frame_data->nScaleFactors += no_band[i]; + } + if (h_frame_data->nScaleFactors > MAX_NUM_ENVELOPE_VALUES) return 0; + + /* + Select Huffman codebook depending on coupling mode and amplitude resolution + */ + if (coupling == COUPLING_BAL) { + envDataTableCompFactor = 1; + if (ampRes == 0) { + hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance10T; + hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance10F; + } else { + hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11T; + hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11F; + } + } else { + envDataTableCompFactor = 0; + if (ampRes == 0) { + hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel10T; + hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel10F; + } else { + hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11T; + hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11F; + } + } + + h_frame_data->iTESactive = (UCHAR)0; /* disable inter-TES by default */ + /* + Now read raw envelope data + */ + for (j = 0, offset = 0; j < nEnvelopes; j++) { + if (h_frame_data->domain_vec[j] == 0) { + if (coupling == COUPLING_BAL) { + h_frame_data->iEnvelope[offset] = + (FIXP_SGL)(((int)FDKreadBits(hBs, start_bits_balance)) + << envDataTableCompFactor); + } else { + h_frame_data->iEnvelope[offset] = + (FIXP_SGL)(int)FDKreadBits(hBs, start_bits); + } + } + + for (i = (1 - h_frame_data->domain_vec[j]); i < no_band[j]; i++) { + if (h_frame_data->domain_vec[j] == 0) { + delta = DecodeHuffmanCW(hcb_f, hBs); + } else { + delta = DecodeHuffmanCW(hcb_t, hBs); + } + + h_frame_data->iEnvelope[offset + i] = + (FIXP_SGL)(delta << envDataTableCompFactor); + } + if ((flags & SBRDEC_SYNTAX_USAC) && (flags & SBRDEC_USAC_ITES)) { + int bs_temp_shape = FDKreadBit(hBs); + FDK_ASSERT(j < 8); + h_frame_data->iTESactive |= (UCHAR)(bs_temp_shape << j); + if (bs_temp_shape) { + h_frame_data->interTempShapeMode[j] = + FDKread2Bits(hBs); /* bs_inter_temp_shape_mode */ + } else { + h_frame_data->interTempShapeMode[j] = 0; + } + } + offset += no_band[j]; + } + +#if ENV_EXP_FRACT + /* Convert from int to scaled fract (ENV_EXP_FRACT bits for the fractional + * part) */ + for (i = 0; i < h_frame_data->nScaleFactors; i++) { + h_frame_data->iEnvelope[i] <<= ENV_EXP_FRACT; + } +#endif + + return 1; +} + +/***************************************************************************/ +/*! + \brief Generates frame info for FIXFIXonly frame class used for low delay + version + + \return zero for error, one for correct. + ****************************************************************************/ +static int generateFixFixOnly(FRAME_INFO *hSbrFrameInfo, int tranPosInternal, + int numberTimeSlots, const UINT flags) { + int nEnv, i, tranIdx; + const int *pTable; + + if (tranPosInternal >= numberTimeSlots) { + return 0; + } + + switch (numberTimeSlots) { + case 8: + pTable = FDK_sbrDecoder_envelopeTable_8[tranPosInternal]; + break; + case 15: + pTable = FDK_sbrDecoder_envelopeTable_15[tranPosInternal]; + break; + case 16: + pTable = FDK_sbrDecoder_envelopeTable_16[tranPosInternal]; + break; + default: + return 0; + } + + /* look number of envelopes in table */ + nEnv = pTable[0]; + /* look up envelope distribution in table */ + for (i = 1; i < nEnv; i++) hSbrFrameInfo->borders[i] = pTable[i + 2]; + /* open and close frame border */ + hSbrFrameInfo->borders[0] = 0; + hSbrFrameInfo->borders[nEnv] = numberTimeSlots; + hSbrFrameInfo->nEnvelopes = nEnv; + + /* transient idx */ + tranIdx = hSbrFrameInfo->tranEnv = pTable[1]; + + /* add noise floors */ + hSbrFrameInfo->bordersNoise[0] = 0; + hSbrFrameInfo->bordersNoise[1] = + hSbrFrameInfo->borders[tranIdx ? tranIdx : 1]; + hSbrFrameInfo->bordersNoise[2] = numberTimeSlots; + /* nEnv is always > 1, so nNoiseEnvelopes is always 2 (IEC 14496-3 4.6.19.3.2) + */ + hSbrFrameInfo->nNoiseEnvelopes = 2; + + return 1; +} + +/*! + \brief Extracts LowDelaySBR control data from the bitstream. + + \return zero for bitstream error, one for correct. +*/ +static int extractLowDelayGrid( + HANDLE_FDK_BITSTREAM hBitBuf, /*!< bitbuffer handle */ + HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA + h_frame_data, /*!< contains the FRAME_INFO struct to be filled */ + int timeSlots, const UINT flags) { + FRAME_INFO *pFrameInfo = &h_frame_data->frameInfo; + INT numberTimeSlots = hHeaderData->numberTimeSlots; + INT temp = 0, k; + + /* FIXFIXonly framing case */ + h_frame_data->frameInfo.frameClass = 0; + + /* get the transient position from the bitstream */ + switch (timeSlots) { + case 8: + /* 3bit transient position (temp={0;..;7}) */ + temp = FDKreadBits(hBitBuf, 3); + break; + + case 16: + case 15: + /* 4bit transient position (temp={0;..;15}) */ + temp = FDKreadBits(hBitBuf, 4); + break; + + default: + return 0; + } + + /* For "case 15" only*/ + if (temp >= timeSlots) { + return 0; + } + + /* calculate borders according to the transient position */ + if (!generateFixFixOnly(pFrameInfo, temp, numberTimeSlots, flags)) { + return 0; + } + + /* decode freq res: */ + for (k = 0; k < pFrameInfo->nEnvelopes; k++) { + pFrameInfo->freqRes[k] = + (UCHAR)FDKreadBits(hBitBuf, 1); /* f = F [1 bits] */ + } + + return 1; +} + +/*! + \brief Extract the PVC frame information (structure FRAME_INFO) from the + bitstream \return Zero for bitstream error, one for correct. +*/ +int extractPvcFrameInfo( + HANDLE_FDK_BITSTREAM hBs, /*!< bitbuffer handle */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the + frame-info will be stored */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_frame_data, /*!< pointer to memory where + the previous frame-info + will be stored */ + UCHAR pvc_mode_last, /**< PVC mode of last frame */ + const UINT flags) { + FRAME_INFO *pFrameInfo = &h_frame_data->frameInfo; + FRAME_INFO *pPrevFrameInfo = &h_prev_frame_data->prevFrameInfo; + int bs_var_len_hf, bs_noise_position; + bs_noise_position = FDKreadBits(hBs, 4); /* SBR_PVC_NOISEPOSITION_BITS 4 */ + bs_var_len_hf = FDKreadBit(hBs); + pFrameInfo->noisePosition = bs_noise_position; + pFrameInfo->tranEnv = -1; + + /* Init for bs_noise_position == 0 in case a parse error is found below. */ + pFrameInfo->nEnvelopes = 1; + pFrameInfo->nNoiseEnvelopes = 1; + pFrameInfo->freqRes[0] = 0; + + if (bs_var_len_hf) { /* 1 or 3 Bits */ + pFrameInfo->varLength = FDKreadBits(hBs, 2) + 1; + if (pFrameInfo->varLength > 3) { + pFrameInfo->varLength = + 0; /* assume bs_var_len_hf == 0 in case of error */ + return 0; /* reserved value -> parse error */ + } + } else { + pFrameInfo->varLength = 0; + } + + if (bs_noise_position) { + pFrameInfo->nEnvelopes = 2; + pFrameInfo->nNoiseEnvelopes = 2; + FDKmemclear(pFrameInfo->freqRes, sizeof(pFrameInfo->freqRes)); + } + + /* frame border calculation */ + if (hHeaderData->bs_info.pvc_mode > 0) { + /* See "7.5.1.4 HF adjustment of SBR envelope scalefactors" for reference. + */ + + FDK_ASSERT((pFrameInfo->nEnvelopes == 1) || (pFrameInfo->nEnvelopes == 2)); + + /* left timeborder-offset: use the timeborder of prev SBR frame */ + if (pPrevFrameInfo->nEnvelopes > 0) { + pFrameInfo->borders[0] = + pPrevFrameInfo->borders[pPrevFrameInfo->nEnvelopes] - PVC_NTIMESLOT; + FDK_ASSERT(pFrameInfo->borders[0] <= 3); + } else { + pFrameInfo->borders[0] = 0; + } + + /* right timeborder-offset: */ + pFrameInfo->borders[pFrameInfo->nEnvelopes] = 16 + pFrameInfo->varLength; + + if (pFrameInfo->nEnvelopes == 2) { + pFrameInfo->borders[1] = pFrameInfo->noisePosition; + } + + /* Calculation of PVC time borders t_EPVC */ + if (pvc_mode_last == 0) { + /* there was a legacy SBR frame before this frame => use bs_var_len' for + * first PVC timeslot */ + pFrameInfo->pvcBorders[0] = pFrameInfo->borders[0]; + } else { + pFrameInfo->pvcBorders[0] = 0; + } + if (pFrameInfo->nEnvelopes == 2) { + pFrameInfo->pvcBorders[1] = pFrameInfo->borders[1]; + } + pFrameInfo->pvcBorders[pFrameInfo->nEnvelopes] = 16; + + /* calculation of SBR noise-floor time-border vector: */ + for (INT i = 0; i <= pFrameInfo->nNoiseEnvelopes; i++) { + pFrameInfo->bordersNoise[i] = pFrameInfo->borders[i]; + } + + pFrameInfo->tranEnv = -1; /* tranEnv not used */ + } + return 1; +} + +/*! + \brief Extract the frame information (structure FRAME_INFO) from the + bitstream \return Zero for bitstream error, one for correct. +*/ +int extractFrameInfo( + HANDLE_FDK_BITSTREAM hBs, /*!< bitbuffer handle */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the + frame-info will be stored */ + const UINT nrOfChannels, const UINT flags) { + FRAME_INFO *pFrameInfo = &h_frame_data->frameInfo; + int numberTimeSlots = hHeaderData->numberTimeSlots; + int pointer_bits = 0, nEnv = 0, b = 0, border, i, n = 0, k, p, aL, aR, nL, nR, + temp = 0, staticFreqRes; + UCHAR frameClass; + + if (flags & SBRDEC_ELD_GRID) { + /* CODEC_AACLD (LD+SBR) only uses the normal 0 Grid for non-transient Frames + * and the LowDelayGrid for transient Frames */ + frameClass = FDKreadBits(hBs, 1); /* frameClass = [1 bit] */ + if (frameClass == 1) { + /* if frameClass == 1, extract LowDelaySbrGrid, otherwise extract normal + * SBR-Grid for FIXIFX */ + /* extract the AACLD-Sbr-Grid */ + pFrameInfo->frameClass = frameClass; + int err = 1; + err = extractLowDelayGrid(hBs, hHeaderData, h_frame_data, numberTimeSlots, + flags); + return err; + } + } else { + frameClass = FDKreadBits(hBs, 2); /* frameClass = C [2 bits] */ + } + + switch (frameClass) { + case 0: + temp = FDKreadBits(hBs, 2); /* E [2 bits ] */ + nEnv = (int)(1 << temp); /* E -> e */ + + if ((flags & SBRDEC_ELD_GRID) && (nEnv == 1)) + h_frame_data->ampResolutionCurrentFrame = + FDKreadBits(hBs, 1); /* new ELD Syntax 07-11-09 */ + + staticFreqRes = FDKreadBits(hBs, 1); + + if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + if (nEnv > MAX_ENVELOPES_USAC) return 0; + } else + + b = nEnv + 1; + switch (nEnv) { + case 1: + switch (numberTimeSlots) { + case 15: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info1_15, + sizeof(FRAME_INFO)); + break; + case 16: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info1_16, + sizeof(FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 2: + switch (numberTimeSlots) { + case 15: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info2_15, + sizeof(FRAME_INFO)); + break; + case 16: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info2_16, + sizeof(FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 4: + switch (numberTimeSlots) { + case 15: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info4_15, + sizeof(FRAME_INFO)); + break; + case 16: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info4_16, + sizeof(FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 8: +#if (MAX_ENVELOPES >= 8) + switch (numberTimeSlots) { + case 15: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info8_15, + sizeof(FRAME_INFO)); + break; + case 16: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info8_16, + sizeof(FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; +#else + return 0; +#endif + } + /* Apply correct freqRes (High is default) */ + if (!staticFreqRes) { + for (i = 0; i < nEnv; i++) pFrameInfo->freqRes[i] = 0; + } + + break; + case 1: + case 2: + temp = FDKreadBits(hBs, 2); /* A [2 bits] */ + + n = FDKreadBits(hBs, 2); /* n = N [2 bits] */ + + nEnv = n + 1; /* # envelopes */ + b = nEnv + 1; /* # borders */ + + break; + } + + switch (frameClass) { + case 1: + /* Decode borders: */ + pFrameInfo->borders[0] = 0; /* first border */ + border = temp + numberTimeSlots; /* A -> aR */ + i = b - 1; /* frame info index for last border */ + pFrameInfo->borders[i] = border; /* last border */ + + for (k = 0; k < n; k++) { + temp = FDKreadBits(hBs, 2); /* R [2 bits] */ + border -= (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[--i] = border; + } + + /* Decode pointer: */ + pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(n + 1)); + p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */ + + if (p > n + 1) return 0; + + pFrameInfo->tranEnv = p ? n + 2 - p : -1; + + /* Decode freq res: */ + for (k = n; k >= 0; k--) { + pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */ + } + + /* Calculate noise floor middle border: */ + if (p == 0 || p == 1) + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[n]; + else + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[pFrameInfo->tranEnv]; + + break; + + case 2: + /* Decode borders: */ + border = temp; /* A -> aL */ + pFrameInfo->borders[0] = border; /* first border */ + + for (k = 1; k <= n; k++) { + temp = FDKreadBits(hBs, 2); /* R [2 bits] */ + border += (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[k] = border; + } + pFrameInfo->borders[k] = numberTimeSlots; /* last border */ + + /* Decode pointer: */ + pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(n + 1)); + p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */ + if (p > n + 1) return 0; + + if (p == 0 || p == 1) + pFrameInfo->tranEnv = -1; + else + pFrameInfo->tranEnv = p - 1; + + /* Decode freq res: */ + for (k = 0; k <= n; k++) { + pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */ + } + + /* Calculate noise floor middle border: */ + switch (p) { + case 0: + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[1]; + break; + case 1: + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[n]; + break; + default: + pFrameInfo->bordersNoise[1] = + pFrameInfo->borders[pFrameInfo->tranEnv]; + break; + } + + break; + + case 3: + /* v_ctrlSignal = [frameClass,aL,aR,nL,nR,v_rL,v_rR,p,v_fLR]; */ + + aL = FDKreadBits(hBs, 2); /* AL [2 bits], AL -> aL */ + + aR = FDKreadBits(hBs, 2) + numberTimeSlots; /* AR [2 bits], AR -> aR */ + + nL = FDKreadBits(hBs, 2); /* nL = NL [2 bits] */ + + nR = FDKreadBits(hBs, 2); /* nR = NR [2 bits] */ + + /*------------------------------------------------------------------------- + Calculate help variables + --------------------------------------------------------------------------*/ + + /* general: */ + nEnv = nL + nR + 1; /* # envelopes */ + if (nEnv > MAX_ENVELOPES) return 0; + b = nEnv + 1; /* # borders */ + + /*------------------------------------------------------------------------- + Decode envelopes + --------------------------------------------------------------------------*/ + + /* L-borders: */ + border = aL; /* first border */ + pFrameInfo->borders[0] = border; + + for (k = 1; k <= nL; k++) { + temp = FDKreadBits(hBs, 2); /* R [2 bits] */ + border += (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[k] = border; + } + + /* R-borders: */ + border = aR; /* last border */ + i = nEnv; + + pFrameInfo->borders[i] = border; + + for (k = 0; k < nR; k++) { + temp = FDKreadBits(hBs, 2); /* R [2 bits] */ + border -= (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[--i] = border; + } + + /* decode pointer: */ + pointer_bits = + DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(nL + nR + 1)); + p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */ + + if (p > nL + nR + 1) return 0; + + pFrameInfo->tranEnv = p ? b - p : -1; + + /* decode freq res: */ + for (k = 0; k < nEnv; k++) { + pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */ + } + + /*------------------------------------------------------------------------- + Decode noise floors + --------------------------------------------------------------------------*/ + pFrameInfo->bordersNoise[0] = aL; + + if (nEnv == 1) { + /* 1 noise floor envelope: */ + pFrameInfo->bordersNoise[1] = aR; + } else { + /* 2 noise floor envelopes */ + if (p == 0 || p == 1) + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[nEnv - 1]; + else + pFrameInfo->bordersNoise[1] = + pFrameInfo->borders[pFrameInfo->tranEnv]; + pFrameInfo->bordersNoise[2] = aR; + } + break; + } + + /* + Store number of envelopes, noise floor envelopes and frame class + */ + pFrameInfo->nEnvelopes = nEnv; + + if (nEnv == 1) + pFrameInfo->nNoiseEnvelopes = 1; + else + pFrameInfo->nNoiseEnvelopes = 2; + + pFrameInfo->frameClass = frameClass; + + if (pFrameInfo->frameClass == 2 || pFrameInfo->frameClass == 1) { + /* calculate noise floor first and last borders: */ + pFrameInfo->bordersNoise[0] = pFrameInfo->borders[0]; + pFrameInfo->bordersNoise[pFrameInfo->nNoiseEnvelopes] = + pFrameInfo->borders[nEnv]; + } + + return 1; +} + +/*! + \brief Check if the frameInfo vector has reasonable values. + \return Zero for error, one for correct +*/ +static int checkFrameInfo( + FRAME_INFO *pFrameInfo, /*!< pointer to frameInfo */ + int numberOfTimeSlots, /*!< QMF time slots per frame */ + int overlap, /*!< Amount of overlap QMF time slots */ + int timeStep) /*!< QMF slots to SBR slots step factor */ +{ + int maxPos, i, j; + int startPos; + int stopPos; + int tranEnv; + int startPosNoise; + int stopPosNoise; + int nEnvelopes = pFrameInfo->nEnvelopes; + int nNoiseEnvelopes = pFrameInfo->nNoiseEnvelopes; + + if (nEnvelopes < 1 || nEnvelopes > MAX_ENVELOPES) return 0; + + if (nNoiseEnvelopes > MAX_NOISE_ENVELOPES) return 0; + + startPos = pFrameInfo->borders[0]; + stopPos = pFrameInfo->borders[nEnvelopes]; + tranEnv = pFrameInfo->tranEnv; + startPosNoise = pFrameInfo->bordersNoise[0]; + stopPosNoise = pFrameInfo->bordersNoise[nNoiseEnvelopes]; + + if (overlap < 0 || overlap > (3 * (4))) { + return 0; + } + if (timeStep < 1 || timeStep > (4)) { + return 0; + } + maxPos = numberOfTimeSlots + (overlap / timeStep); + + /* Check that the start and stop positions of the frame are reasonable values. + */ + if ((startPos < 0) || (startPos >= stopPos)) return 0; + if (startPos > maxPos - numberOfTimeSlots) /* First env. must start in or + directly after the overlap + buffer */ + return 0; + if (stopPos < numberOfTimeSlots) /* One complete frame must be ready for + output after processing */ + return 0; + if (stopPos > maxPos) return 0; + + /* Check that the start border for every envelope is strictly later in time + */ + for (i = 0; i < nEnvelopes; i++) { + if (pFrameInfo->borders[i] >= pFrameInfo->borders[i + 1]) return 0; + } + + /* Check that the envelope to be shortened is actually among the envelopes */ + if (tranEnv > nEnvelopes) return 0; + + /* Check the noise borders */ + if (nEnvelopes == 1 && nNoiseEnvelopes > 1) return 0; + + if (startPos != startPosNoise || stopPos != stopPosNoise) return 0; + + /* Check that the start border for every noise-envelope is strictly later in + * time*/ + for (i = 0; i < nNoiseEnvelopes; i++) { + if (pFrameInfo->bordersNoise[i] >= pFrameInfo->bordersNoise[i + 1]) + return 0; + } + + /* Check that every noise border is the same as an envelope border*/ + for (i = 0; i < nNoiseEnvelopes; i++) { + startPosNoise = pFrameInfo->bordersNoise[i]; + + for (j = 0; j < nEnvelopes; j++) { + if (pFrameInfo->borders[j] == startPosNoise) break; + } + if (j == nEnvelopes) return 0; + } + + return 1; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_extr.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_extr.h new file mode 100644 index 0000000000000..38c04a30ecb3b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/env_extr.h @@ -0,0 +1,415 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Envelope extraction prototypes +*/ + +#ifndef ENV_EXTR_H +#define ENV_EXTR_H + +#include "sbrdecoder.h" + +#include "FDK_bitstream.h" +#include "lpp_tran.h" + +#include "psdec.h" +#include "pvc_dec.h" + +#define ENV_EXP_FRACT 0 +/*!< Shift raw envelope data to support fractional numbers. + Can be set to 8 instead of 0 to enhance accuracy during concealment. + This is not required for conformance and #requantizeEnvelopeData() will + become more expensive. +*/ + +#define EXP_BITS 6 +/*!< Size of exponent-part of a pseudo float envelope value (should be at least + 6). The remaining bits in each word are used for the mantissa (should be at + least 10). This format is used in the arrays iEnvelope[] and + sbrNoiseFloorLevel[] in the FRAME_DATA struct which must fit in a certain part + of the output buffer (See buffer management in sbr_dec.cpp). Exponents and + mantissas could also be stored in separate arrays. Accessing the exponent or + the mantissa would be simplified and the masks #MASK_E resp. #MASK_M would + no longer be required. +*/ + +#define MASK_M \ + (((1 << (FRACT_BITS - EXP_BITS)) - 1) \ + << EXP_BITS) /*!< Mask for extracting the mantissa of a pseudo float \ + envelope value */ +#define MASK_E \ + ((1 << EXP_BITS) - 1) /*!< Mask for extracting the exponent of a pseudo \ + float envelope value */ + +#define SIGN_EXT \ + (((SCHAR)-1) ^ \ + MASK_E) /*!< a CHAR-constant with all bits above our sign-bit set */ +#define ROUNDING \ + ((FIXP_SGL)( \ + 1 << (EXP_BITS - 1))) /*!< 0.5-offset for rounding the mantissa of a \ + pseudo-float envelope value */ +#define NRG_EXP_OFFSET \ + 16 /*!< Will be added to the reference energy's exponent to prevent negative \ + numbers */ +#define NOISE_EXP_OFFSET \ + 38 /*!< Will be added to the noise level exponent to prevent negative \ + numbers */ + +#define ADD_HARMONICS_FLAGS_SIZE 2 /* ceil(MAX_FREQ_COEFFS/32) */ + +typedef enum { + HEADER_NOT_PRESENT, + HEADER_ERROR, + HEADER_OK, + HEADER_RESET +} SBR_HEADER_STATUS; + +typedef enum { + SBR_NOT_INITIALIZED = 0, + UPSAMPLING = 1, + SBR_HEADER = 2, + SBR_ACTIVE = 3 +} SBR_SYNC_STATE; + +typedef enum { COUPLING_OFF = 0, COUPLING_LEVEL, COUPLING_BAL } COUPLING_MODE; + +typedef struct { + UCHAR nSfb[2]; /*!< Number of SBR-bands for low and high freq-resolution */ + UCHAR nNfb; /*!< Actual number of noise bands to read from the bitstream*/ + UCHAR numMaster; /*!< Number of SBR-bands in v_k_master */ + UCHAR lowSubband; /*!< QMF-band where SBR frequency range starts */ + UCHAR highSubband; /*!< QMF-band where SBR frequency range ends */ + UCHAR ov_highSubband; /*!< if headerchange applies this value holds the old + highband value -> highband value of overlap area; + required for overlap in usac when headerchange + occurs between XVAR and VARX frame */ + UCHAR limiterBandTable[MAX_NUM_LIMITERS + 1]; /*!< Limiter band table. */ + UCHAR noLimiterBands; /*!< Number of limiter bands. */ + UCHAR nInvfBands; /*!< Number of bands for inverse filtering */ + UCHAR + *freqBandTable[2]; /*!< Pointers to freqBandTableLo and freqBandTableHi */ + UCHAR freqBandTableLo[MAX_FREQ_COEFFS / 2 + 1]; + /*!< Mapping of SBR bands to QMF bands for low frequency resolution */ + UCHAR freqBandTableHi[MAX_FREQ_COEFFS + 1]; + /*!< Mapping of SBR bands to QMF bands for high frequency resolution */ + UCHAR freqBandTableNoise[MAX_NOISE_COEFFS + 1]; + /*!< Mapping of SBR noise bands to QMF bands */ + UCHAR v_k_master[MAX_FREQ_COEFFS + 1]; + /*!< Master BandTable which freqBandTable is derived from */ +} FREQ_BAND_DATA; + +typedef FREQ_BAND_DATA *HANDLE_FREQ_BAND_DATA; + +#define SBRDEC_ELD_GRID 1 +#define SBRDEC_SYNTAX_SCAL 2 +#define SBRDEC_SYNTAX_USAC 4 +#define SBRDEC_SYNTAX_RSVD50 8 +#define SBRDEC_USAC_INDEP \ + 16 /* Flag indicating that USAC global independency flag is active. */ +#define SBRDEC_LOW_POWER \ + 32 /* Flag indicating that Low Power QMF mode shall be used. */ +#define SBRDEC_PS_DECODED \ + 64 /* Flag indicating that PS was decoded and rendered. */ +#define SBRDEC_QUAD_RATE \ + 128 /* Flag indicating that USAC SBR 4:1 is active. \ + */ +#define SBRDEC_USAC_HARMONICSBR \ + 256 /* Flag indicating that USAC HBE tool is active. */ +#define SBRDEC_LD_MPS_QMF \ + 512 /* Flag indicating that the LD-MPS QMF shall be used. */ +#define SBRDEC_USAC_ITES \ + 1024 /* Flag indicating that USAC inter TES tool is active. */ +#define SBRDEC_SYNTAX_DRM \ + 2048 /* Flag indicating that DRM30/DRM+ reverse syntax is being used. */ +#define SBRDEC_ELD_DOWNSCALE \ + 4096 /* Flag indicating that ELD downscaled mode decoding is used */ +#define SBRDEC_DOWNSAMPLE \ + 8192 /* Flag indicating that the downsampling mode is used. */ +#define SBRDEC_FLUSH 16384 /* Flag is used to flush all elements in use. */ +#define SBRDEC_FORCE_RESET \ + 32768 /* Flag is used to force a reset of all elements in use. */ +#define SBRDEC_SKIP_QMF_ANA \ + (1 << 21) /* Flag indicating that the input data is provided in the QMF \ + domain. */ +#define SBRDEC_SKIP_QMF_SYN \ + (1 << 22) /* Flag indicating that the output data is exported in the QMF \ + domain. */ + +#define SBRDEC_HDR_STAT_RESET 1 +#define SBRDEC_HDR_STAT_UPDATE 2 + +typedef struct { + UCHAR ampResolution; /*!< Amplitude resolution of envelope values (0: 1.5dB, + 1: 3dB) */ + UCHAR + xover_band; /*!< Start index in #v_k_master[] used for dynamic crossover + frequency */ + UCHAR sbr_preprocessing; /*!< SBR prewhitening flag. */ + UCHAR pvc_mode; /*!< Predictive vector coding mode */ +} SBR_HEADER_DATA_BS_INFO; + +typedef struct { + /* Changes in these variables causes a reset of the decoder */ + UCHAR startFreq; /*!< Index for SBR start frequency */ + UCHAR stopFreq; /*!< Index for SBR highest frequency */ + UCHAR freqScale; /*!< 0: linear scale, 1-3 logarithmic scales */ + UCHAR alterScale; /*!< Flag for coarser frequency resolution */ + UCHAR noise_bands; /*!< Noise bands per octave, read from bitstream*/ + + /* don't require reset */ + UCHAR limiterBands; /*!< Index for number of limiter bands per octave */ + UCHAR limiterGains; /*!< Index to select gain limit */ + UCHAR interpolFreq; /*!< Select gain calculation method (1: per QMF channel, + 0: per SBR band) */ + UCHAR smoothingLength; /*!< Smoothing of gains over time (0: on 1: off) */ + +} SBR_HEADER_DATA_BS; + +typedef struct { + SBR_SYNC_STATE + syncState; /*!< The current initialization status of the header */ + + UCHAR status; /*!< Flags field used for signaling a reset right before the + processing starts and an update from config (e.g. ASC). */ + UCHAR + frameErrorFlag; /*!< Frame data valid flag. CAUTION: This variable will be + overwritten by the flag stored in the element + structure. This is necessary because of the frame + delay. There it might happen that different slots use + the same header. */ + UCHAR numberTimeSlots; /*!< AAC: 16,15 */ + UCHAR numberOfAnalysisBands; /*!< Number of QMF analysis bands */ + UCHAR timeStep; /*!< Time resolution of SBR in QMF-slots */ + UINT + sbrProcSmplRate; /*!< SBR processing sampling frequency (!= + OutputSamplingRate) (always: CoreSamplingRate * + UpSamplingFactor; even in single rate mode) */ + + SBR_HEADER_DATA_BS bs_data; /*!< current SBR header. */ + SBR_HEADER_DATA_BS bs_dflt; /*!< Default sbr header. */ + SBR_HEADER_DATA_BS_INFO bs_info; /*!< SBR info. */ + + FREQ_BAND_DATA freqBandData; /*!< Pointer to struct #FREQ_BAND_DATA */ + UCHAR pvcIDprev; +} SBR_HEADER_DATA; + +typedef SBR_HEADER_DATA *HANDLE_SBR_HEADER_DATA; + +typedef struct { + UCHAR frameClass; /*!< Select grid type */ + UCHAR nEnvelopes; /*!< Number of envelopes */ + UCHAR borders[MAX_ENVELOPES + 1]; /*!< Envelope borders (in SBR-timeslots, + e.g. mp3PRO: 0..11) */ + UCHAR freqRes[MAX_ENVELOPES]; /*!< Frequency resolution for each envelope + (0=low, 1=high) */ + SCHAR tranEnv; /*!< Transient envelope, -1 if none */ + UCHAR nNoiseEnvelopes; /*!< Number of noise envelopes */ + UCHAR + bordersNoise[MAX_NOISE_ENVELOPES + 1]; /*!< borders of noise envelopes */ + UCHAR pvcBorders[MAX_PVC_ENVELOPES + 1]; + UCHAR noisePosition; + UCHAR varLength; +} FRAME_INFO; + +typedef struct { + FIXP_SGL sfb_nrg_prev[MAX_FREQ_COEFFS]; /*!< Previous envelope (required for + differential-coded values) */ + FIXP_SGL + prevNoiseLevel[MAX_NOISE_COEFFS]; /*!< Previous noise envelope (required + for differential-coded values) */ + COUPLING_MODE coupling; /*!< Stereo-mode of previous frame */ + INVF_MODE sbr_invf_mode[MAX_INVF_BANDS]; /*!< Previous strength of filtering + in transposer */ + UCHAR ampRes; /*!< Previous amplitude resolution (0: 1.5dB, 1: 3dB) */ + UCHAR stopPos; /*!< Position in time where last envelope ended */ + UCHAR frameErrorFlag; /*!< Previous frame status */ + UCHAR prevSbrPitchInBins; /*!< Previous frame pitchInBins */ + FRAME_INFO prevFrameInfo; +} SBR_PREV_FRAME_DATA; + +typedef SBR_PREV_FRAME_DATA *HANDLE_SBR_PREV_FRAME_DATA; + +typedef struct { + int nScaleFactors; /*!< total number of scalefactors in frame */ + + FRAME_INFO frameInfo; /*!< time grid for current frame */ + UCHAR domain_vec[MAX_ENVELOPES]; /*!< Bitfield containing direction of + delta-coding for each envelope + (0:frequency, 1:time) */ + UCHAR domain_vec_noise + [MAX_NOISE_ENVELOPES]; /*!< Same as above, but for noise envelopes */ + + INVF_MODE + sbr_invf_mode[MAX_INVF_BANDS]; /*!< Strength of filtering in transposer */ + COUPLING_MODE coupling; /*!< Stereo-mode */ + int ampResolutionCurrentFrame; /*!< Amplitude resolution of envelope values + (0: 1.5dB, 1: 3dB) */ + + ULONG addHarmonics[ADD_HARMONICS_FLAGS_SIZE]; /*!< Flags for synthetic sine + addition (aligned to MSB) */ + + FIXP_SGL iEnvelope[MAX_NUM_ENVELOPE_VALUES]; /*!< Envelope data */ + FIXP_SGL sbrNoiseFloorLevel[MAX_NUM_NOISE_VALUES]; /*!< Noise envelope data */ + UCHAR iTESactive; /*!< One flag for each envelope to enable USAC inter-TES */ + UCHAR + interTempShapeMode[MAX_ENVELOPES]; /*!< USAC inter-TES: + bs_inter_temp_shape_mode[ch][env] + value */ + UCHAR pvcID[PVC_NTIMESLOT]; /*!< One PVC ID value for each time slot */ + UCHAR ns; + UCHAR sinusoidal_position; + + UCHAR sbrPatchingMode; + UCHAR sbrOversamplingFlag; + UCHAR sbrPitchInBins; +} SBR_FRAME_DATA; + +typedef SBR_FRAME_DATA *HANDLE_SBR_FRAME_DATA; + +/*! +\brief Maps sampling frequencies to frequencies for which setup tables are +available + +Maps arbitary sampling frequency to nearest neighbors for which setup tables +are available (e.g. 25600 -> 24000). +Used for startFreq calculation. +The mapping is defined in 14496-3 (4.6.18.2.6), fs(SBR), and table 4.82 + +\return mapped sampling frequency +*/ +UINT sbrdec_mapToStdSampleRate(UINT fs, + UINT isUsac); /*!< Output sampling frequency */ + +void initSbrPrevFrameData(HANDLE_SBR_PREV_FRAME_DATA h_prev_data, + int timeSlots); + +int sbrGetChannelElement(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA hFrameDataLeft, + HANDLE_SBR_FRAME_DATA hFrameDataRight, + HANDLE_SBR_PREV_FRAME_DATA hFrameDataLeftPrev, + UCHAR pvc_mode_last, HANDLE_FDK_BITSTREAM hBitBuf, + HANDLE_PS_DEC hParametricStereoDec, const UINT flags, + const int overlap); + +SBR_HEADER_STATUS +sbrGetHeaderData(HANDLE_SBR_HEADER_DATA headerData, + HANDLE_FDK_BITSTREAM hBitBuf, const UINT flags, + const int fIsSbrData, const UCHAR configMode); + +/*! + \brief Initialize SBR header data + + Copy default values to the header data struct and patch some entries + depending on the core codec. +*/ +SBR_ERROR +initHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData, const int sampleRateIn, + const int sampleRateOut, const INT downscaleFactor, + const int samplesPerFrame, const UINT flags, + const int setDefaultHdr); +#endif + +/* Convert headroom bits to exponent */ +#define SCALE2EXP(s) (15 - (s)) +#define EXP2SCALE(e) (15 - (e)) diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/hbe.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/hbe.cpp new file mode 100644 index 0000000000000..9485823c5b9ff --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/hbe.cpp @@ -0,0 +1,2187 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Fast FFT routines prototypes + \author Fabian Haussel +*/ + +#include "hbe.h" +#include "qmf.h" +#include "env_extr.h" + +#define HBE_MAX_QMF_BANDS (40) + +#define HBE_MAX_OUT_SLOTS (11) + +#define QMF_WIN_LEN \ + (12 + 6 - 4 - 1) /* 6 subband slots extra delay to align with HQ - 4 slots \ + to compensate for critical sampling delay - 1 slot to \ + align critical sampling exactly (w additional time \ + domain delay)*/ + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +static const int xProducts[MAX_STRETCH_HBE - 1] = { + 1, 1, 1}; /* Cross products on(1)/off(0) for T=2,3,4. */ +static const int startSubband2kL[33] = { + 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, + 6, 8, 8, 8, 8, 8, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12}; + +static const int pmin = 12; + +static const FIXP_DBL hintReal_F[4][3] = { + {FL2FXCONST_DBL(0.39840335f), FL2FXCONST_DBL(0.39840335f), + FL2FXCONST_DBL(-0.39840335f)}, + {FL2FXCONST_DBL(0.39840335f), FL2FXCONST_DBL(-0.39840335f), + FL2FXCONST_DBL(-0.39840335f)}, + {FL2FXCONST_DBL(-0.39840335f), FL2FXCONST_DBL(-0.39840335f), + FL2FXCONST_DBL(0.39840335f)}, + {FL2FXCONST_DBL(-0.39840335f), FL2FXCONST_DBL(0.39840335f), + FL2FXCONST_DBL(0.39840335f)}}; + +static const FIXP_DBL factors[4] = { + FL2FXCONST_DBL(0.39840335f), FL2FXCONST_DBL(-0.39840335f), + FL2FXCONST_DBL(-0.39840335f), FL2FXCONST_DBL(0.39840335f)}; + +#define PSCALE 32 + +static const FIXP_DBL p_F[128] = {FL2FXCONST_DBL(0.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(1.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(2.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(3.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(4.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(5.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(6.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(7.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(8.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(9.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(10.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(11.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(12.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(13.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(14.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(15.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(16.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(17.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(18.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(19.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(20.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(21.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(22.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(23.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(24.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(25.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(26.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(27.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(28.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(29.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(30.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(31.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(32.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(33.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(34.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(35.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(36.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(37.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(38.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(39.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(40.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(41.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(42.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(43.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(44.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(45.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(46.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(47.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(48.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(49.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(50.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(51.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(52.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(53.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(54.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(55.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(56.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(57.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(58.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(59.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(60.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(61.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(62.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(63.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(64.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(65.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(66.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(67.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(68.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(69.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(70.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(71.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(72.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(73.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(74.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(75.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(76.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(77.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(78.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(79.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(80.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(81.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(82.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(83.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(84.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(85.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(86.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(87.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(88.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(89.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(90.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(91.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(92.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(93.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(94.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(95.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(96.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(97.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(98.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(99.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(100.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(101.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(102.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(103.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(104.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(105.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(106.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(107.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(108.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(109.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(110.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(111.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(112.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(113.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(114.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(115.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(116.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(117.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(118.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(119.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(120.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(121.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(122.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(123.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(124.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(125.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(126.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(127.f / (PSCALE * 12.f))}; + +static const FIXP_DBL band_F[64] = { + FL2FXCONST_DBL((0.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((1.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((2.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((3.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((4.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((5.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((6.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((7.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((8.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((9.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((10.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((11.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((12.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((13.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((14.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((15.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((16.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((17.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((18.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((19.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((20.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((21.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((22.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((23.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((24.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((25.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((26.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((27.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((28.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((29.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((30.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((31.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((32.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((33.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((34.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((35.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((36.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((37.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((38.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((39.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((40.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((41.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((42.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((43.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((44.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((45.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((46.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((47.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((48.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((49.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((50.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((51.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((52.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((53.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((54.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((55.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((56.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((57.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((58.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((59.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((60.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((61.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((62.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((63.f * 2.f + 1) / (PSCALE << 2))}; + +static const FIXP_DBL tr_str[3] = {FL2FXCONST_DBL(1.f / 4.f), + FL2FXCONST_DBL(2.f / 4.f), + FL2FXCONST_DBL(3.f / 4.f)}; + +static const FIXP_DBL stretchfac[3] = {FL2FXCONST_DBL(1.f / 2.f), + FL2FXCONST_DBL(1.f / 3.f), + FL2FXCONST_DBL(1.f / 4.f)}; + +static const FIXP_DBL cos_F[64] = { + 26353028, -79043208, 131685776, -184244944, 236697216, -289006912, + 341142496, -393072608, 444773984, -496191392, 547325824, -598114752, + 648559104, -698597248, 748230016, -797411904, 846083200, -894275136, + 941928192, -989013760, 1035474624, -1081340672, 1126555136, -1171063296, + 1214893696, -1257992192, 1300332544, -1341889408, 1382612736, -1422503808, + 1461586944, -1499741440, 1537039104, -1573364864, 1608743808, -1643196672, + 1676617344, -1709028992, 1740450560, -1770784896, 1800089472, -1828273536, + 1855357440, -1881356288, 1906190080, -1929876608, 1952428928, -1973777664, + 1993962880, -2012922240, 2030670208, -2047216000, 2062508288, -2076559488, + 2089376128, -2100932224, 2111196800, -2120214784, 2127953792, -2134394368, + 2139565056, -2143444864, 2146026624, -2147321856}; + +static const FIXP_DBL twiddle[121] = {1073741824, + 1071442860, + 1064555814, + 1053110176, + 1037154959, + 1016758484, + 992008094, + 963009773, + 929887697, + 892783698, + 851856663, + 807281846, + 759250125, + 707967178, + 653652607, + 596538995, + 536870912, + 474903865, + 410903207, + 345142998, + 277904834, + 209476638, + 140151432, + 70226075, + 0, + -70226075, + -140151432, + -209476638, + -277904834, + -345142998, + -410903207, + -474903865, + -536870912, + -596538995, + -653652607, + -707967178, + -759250125, + -807281846, + -851856663, + -892783698, + -929887697, + -963009773, + -992008094, + -1016758484, + -1037154959, + -1053110176, + -1064555814, + -1071442860, + -1073741824, + -1071442860, + -1064555814, + -1053110176, + -1037154959, + -1016758484, + -992008094, + -963009773, + -929887697, + -892783698, + -851856663, + -807281846, + -759250125, + -707967178, + -653652607, + -596538995, + -536870912, + -474903865, + -410903207, + -345142998, + -277904834, + -209476638, + -140151432, + -70226075, + 0, + 70226075, + 140151432, + 209476638, + 277904834, + 345142998, + 410903207, + 474903865, + 536870912, + 596538995, + 653652607, + 707967178, + 759250125, + 807281846, + 851856663, + 892783698, + 929887697, + 963009773, + 992008094, + 1016758484, + 1037154959, + 1053110176, + 1064555814, + 1071442860, + 1073741824, + 1071442860, + 1064555814, + 1053110176, + 1037154959, + 1016758484, + 992008094, + 963009773, + 929887697, + 892783698, + 851856663, + 807281846, + 759250125, + 707967178, + 653652607, + 596538995, + 536870912, + 474903865, + 410903207, + 345142998, + 277904834, + 209476638, + 140151432, + 70226075, + 0}; + +#if FIXP_QTW == FIXP_SGL +#define HTW(x) (x) +#else +#define HTW(x) FX_DBL2FX_QTW(FX_SGL2FX_DBL((const FIXP_SGL)x)) +#endif + +static const FIXP_QTW post_twiddle_cos_8[8] = { + HTW(-1606), HTW(4756), HTW(-7723), HTW(10394), + HTW(-12665), HTW(14449), HTW(-15679), HTW(16305)}; + +static const FIXP_QTW post_twiddle_cos_16[16] = { + HTW(-804), HTW(2404), HTW(-3981), HTW(5520), HTW(-7005), HTW(8423), + HTW(-9760), HTW(11003), HTW(-12140), HTW(13160), HTW(-14053), HTW(14811), + HTW(-15426), HTW(15893), HTW(-16207), HTW(16364)}; + +static const FIXP_QTW post_twiddle_cos_24[24] = { + HTW(-536), HTW(1606), HTW(-2669), HTW(3720), HTW(-4756), HTW(5771), + HTW(-6762), HTW(7723), HTW(-8652), HTW(9543), HTW(-10394), HTW(11200), + HTW(-11958), HTW(12665), HTW(-13318), HTW(13913), HTW(-14449), HTW(14924), + HTW(-15334), HTW(15679), HTW(-15956), HTW(16165), HTW(-16305), HTW(16375)}; + +static const FIXP_QTW post_twiddle_cos_32[32] = { + HTW(-402), HTW(1205), HTW(-2006), HTW(2801), HTW(-3590), HTW(4370), + HTW(-5139), HTW(5897), HTW(-6639), HTW(7366), HTW(-8076), HTW(8765), + HTW(-9434), HTW(10080), HTW(-10702), HTW(11297), HTW(-11866), HTW(12406), + HTW(-12916), HTW(13395), HTW(-13842), HTW(14256), HTW(-14635), HTW(14978), + HTW(-15286), HTW(15557), HTW(-15791), HTW(15986), HTW(-16143), HTW(16261), + HTW(-16340), HTW(16379)}; + +static const FIXP_QTW post_twiddle_cos_40[40] = { + HTW(-322), HTW(965), HTW(-1606), HTW(2245), HTW(-2880), HTW(3511), + HTW(-4137), HTW(4756), HTW(-5368), HTW(5971), HTW(-6566), HTW(7150), + HTW(-7723), HTW(8285), HTW(-8833), HTW(9368), HTW(-9889), HTW(10394), + HTW(-10883), HTW(11356), HTW(-11810), HTW(12247), HTW(-12665), HTW(13063), + HTW(-13441), HTW(13799), HTW(-14135), HTW(14449), HTW(-14741), HTW(15011), + HTW(-15257), HTW(15480), HTW(-15679), HTW(15853), HTW(-16003), HTW(16129), + HTW(-16229), HTW(16305), HTW(-16356), HTW(16381)}; + +static const FIXP_QTW post_twiddle_sin_8[8] = { + HTW(16305), HTW(-15679), HTW(14449), HTW(-12665), + HTW(10394), HTW(-7723), HTW(4756), HTW(-1606)}; + +static const FIXP_QTW post_twiddle_sin_16[16] = { + HTW(16364), HTW(-16207), HTW(15893), HTW(-15426), HTW(14811), HTW(-14053), + HTW(13160), HTW(-12140), HTW(11003), HTW(-9760), HTW(8423), HTW(-7005), + HTW(5520), HTW(-3981), HTW(2404), HTW(-804)}; + +static const FIXP_QTW post_twiddle_sin_24[24] = { + HTW(16375), HTW(-16305), HTW(16165), HTW(-15956), HTW(15679), HTW(-15334), + HTW(14924), HTW(-14449), HTW(13913), HTW(-13318), HTW(12665), HTW(-11958), + HTW(11200), HTW(-10394), HTW(9543), HTW(-8652), HTW(7723), HTW(-6762), + HTW(5771), HTW(-4756), HTW(3720), HTW(-2669), HTW(1606), HTW(-536)}; + +static const FIXP_QTW post_twiddle_sin_32[32] = { + HTW(16379), HTW(-16340), HTW(16261), HTW(-16143), HTW(15986), HTW(-15791), + HTW(15557), HTW(-15286), HTW(14978), HTW(-14635), HTW(14256), HTW(-13842), + HTW(13395), HTW(-12916), HTW(12406), HTW(-11866), HTW(11297), HTW(-10702), + HTW(10080), HTW(-9434), HTW(8765), HTW(-8076), HTW(7366), HTW(-6639), + HTW(5897), HTW(-5139), HTW(4370), HTW(-3590), HTW(2801), HTW(-2006), + HTW(1205), HTW(-402)}; + +static const FIXP_QTW post_twiddle_sin_40[40] = { + HTW(16381), HTW(-16356), HTW(16305), HTW(-16229), HTW(16129), HTW(-16003), + HTW(15853), HTW(-15679), HTW(15480), HTW(-15257), HTW(15011), HTW(-14741), + HTW(14449), HTW(-14135), HTW(13799), HTW(-13441), HTW(13063), HTW(-12665), + HTW(12247), HTW(-11810), HTW(11356), HTW(-10883), HTW(10394), HTW(-9889), + HTW(9368), HTW(-8833), HTW(8285), HTW(-7723), HTW(7150), HTW(-6566), + HTW(5971), HTW(-5368), HTW(4756), HTW(-4137), HTW(3511), HTW(-2880), + HTW(2245), HTW(-1606), HTW(965), HTW(-322)}; + +static const FIXP_DBL preModCos[32] = { + -749875776, 786681536, 711263552, -821592064, -670937792, 854523392, + 628995648, -885396032, -585538240, 914135680, 540670208, -940673088, + -494499680, 964944384, 447137824, -986891008, -398698816, 1006460096, + 349299264, -1023604544, -299058240, 1038283072, 248096752, -1050460288, + -196537584, 1060106816, 144504928, -1067199488, -92124160, 1071721152, + 39521456, -1073660992}; + +static const FIXP_DBL preModSin[32] = { + 768510144, 730789760, -804379072, -691308864, 838310208, 650162560, + -870221760, -607449920, 900036928, 563273856, -927683776, -517740896, + 953095808, 470960608, -976211712, -423045728, 996975808, 374111712, + -1015338112, -324276416, 1031254400, 273659904, -1044686336, -222384144, + 1055601472, 170572640, -1063973632, -118350192, 1069782528, 65842640, + -1073014208, -13176464}; + +/* The cube root function */ +/***************************************************************************** + + functionname: invCubeRootNorm2 + description: delivers 1/cuberoot(op) in Q1.31 format and modified exponent + +*****************************************************************************/ +#define CUBE_ROOT_BITS 7 +#define CUBE_ROOT_VALUES (128 + 2) +#define CUBE_ROOT_BITS_MASK 0x7f +#define CUBE_ROOT_FRACT_BITS_MASK 0x007FFFFF +/* Inverse cube root table for operands running from 0.5 to 1.0 */ +/* (INT) (1.0/cuberoot((op))); */ +/* Implicit exponent is 1. */ + +LNK_SECTION_CONSTDATA +static const FIXP_DBL invCubeRootTab[CUBE_ROOT_VALUES] = { + (0x50a28be6), (0x506d1172), (0x503823c4), (0x5003c05a), (0x4fcfe4c0), + (0x4f9c8e92), (0x4f69bb7d), (0x4f37693b), (0x4f059594), (0x4ed43e5f), + (0x4ea36181), (0x4e72fcea), (0x4e430e98), (0x4e139495), (0x4de48cf5), + (0x4db5f5db), (0x4d87cd73), (0x4d5a11f2), (0x4d2cc19c), (0x4cffdabb), + (0x4cd35ba4), (0x4ca742b7), (0x4c7b8e5c), (0x4c503d05), (0x4c254d2a), + (0x4bfabd50), (0x4bd08c00), (0x4ba6b7cd), (0x4b7d3f53), (0x4b542134), + (0x4b2b5c18), (0x4b02eeb1), (0x4adad7b8), (0x4ab315ea), (0x4a8ba80d), + (0x4a648cec), (0x4a3dc35b), (0x4a174a30), (0x49f1204a), (0x49cb448d), + (0x49a5b5e2), (0x49807339), (0x495b7b86), (0x4936cdc2), (0x491268ec), + (0x48ee4c08), (0x48ca761f), (0x48a6e63e), (0x48839b76), (0x486094de), + (0x483dd190), (0x481b50ad), (0x47f91156), (0x47d712b3), (0x47b553f0), + (0x4793d43c), (0x477292c9), (0x47518ece), (0x4730c785), (0x47103c2d), + (0x46efec06), (0x46cfd655), (0x46affa61), (0x46905777), (0x4670ece4), + (0x4651b9f9), (0x4632be0b), (0x4613f871), (0x45f56885), (0x45d70da5), + (0x45b8e72f), (0x459af487), (0x457d3511), (0x455fa835), (0x45424d5d), + (0x452523f6), (0x45082b6e), (0x44eb6337), (0x44cecac5), (0x44b2618d), + (0x44962708), (0x447a1ab1), (0x445e3c02), (0x44428a7c), (0x4427059e), + (0x440bacec), (0x43f07fe9), (0x43d57e1c), (0x43baa70e), (0x439ffa48), + (0x43857757), (0x436b1dc8), (0x4350ed2b), (0x4336e511), (0x431d050c), + (0x43034cb2), (0x42e9bb98), (0x42d05156), (0x42b70d85), (0x429defc0), + (0x4284f7a2), (0x426c24cb), (0x425376d8), (0x423aed6a), (0x42228823), + (0x420a46a6), (0x41f22898), (0x41da2d9f), (0x41c25561), (0x41aa9f86), + (0x41930bba), (0x417b99a5), (0x416448f5), (0x414d1956), (0x41360a76), + (0x411f1c06), (0x41084db5), (0x40f19f35), (0x40db1039), (0x40c4a074), + (0x40ae4f9b), (0x40981d64), (0x40820985), (0x406c13b6), (0x40563bb1), + (0x4040812e), (0x402ae3e7), (0x40156399), (0x40000000), (0x3FEAB8D9)}; +/* n.a. */ +static const FIXP_DBL invCubeRootCorrection[3] = {0x40000000, 0x50A28BE6, + 0x6597FA95}; + +/***************************************************************************** + * \brief calculate 1.0/cube_root(op), op contains mantissa and exponent + * \param op_m: (i) mantissa of operand, must not be zero (0x0000.0000) or + * negative + * \param op_e: (i) pointer to the exponent of the operand (must be initialized) + * and .. (o) pointer to the exponent of the result + * \return: (o) mantissa of the result + * \description: + * This routine calculates the cube root of the input operand, that is + * given with its mantissa in Q31 format (FIXP_DBL) and its exponent (INT). + * The resulting mantissa is returned in format Q31. The exponent (*op_e) + * is modified accordingly. It is not assured, that the result is fully + * left-aligned but assumed to have not more than 2 bits headroom. There is one + * macro to activate the use of this algorithm: FUNCTION_invCubeRootNorm2 By + * means of activating the macro INVCUBEROOTNORM2_LINEAR_INTERPOLATE_HQ, a + * slightly higher precision is reachable (by default, not active). For DEBUG + * purpose only: a FDK_ASSERT macro validates, if the input mantissa is greater + * zero. + * + */ +static +#ifdef __arm__ + FIXP_DBL FDK_FORCEINLINE + invCubeRootNorm2(FIXP_DBL op_m, INT* op_e) +#else + FIXP_DBL + invCubeRootNorm2(FIXP_DBL op_m, INT* op_e) +#endif +{ + FDK_ASSERT(op_m > FIXP_DBL(0)); + + /* normalize input, calculate shift value */ + INT exponent = (INT)fNormz(op_m) - 1; + op_m <<= exponent; + + INT index = (INT)(op_m >> (DFRACT_BITS - 1 - (CUBE_ROOT_BITS + 1))) & + CUBE_ROOT_BITS_MASK; + FIXP_DBL fract = (FIXP_DBL)(((INT)op_m & CUBE_ROOT_FRACT_BITS_MASK) + << (CUBE_ROOT_BITS + 1)); + FIXP_DBL diff = invCubeRootTab[index + 1] - invCubeRootTab[index]; + op_m = fMultAddDiv2(invCubeRootTab[index], diff << 1, fract); +#if defined(INVCUBEROOTNORM2_LINEAR_INTERPOLATE_HQ) + /* reg1 = t[i] + (t[i+1]-t[i])*fract ... already computed ... + + * (1-fract)fract*(t[i+2]-t[i+1])/2 */ + if (fract != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + fract = fMultDiv2(fract, (FIXP_DBL)((LONG)0x80000000 - (LONG)fract)) << 1; + diff = diff - (invCubeRootTab[index + 2] - invCubeRootTab[index + 1]); + op_m = fMultAddDiv2(op_m, fract, diff); + } +#endif /* INVCUBEROOTNORM2_LINEAR_INTERPOLATE_HQ */ + + /* calculate the output exponent = input * exp/3 = cubicroot(m)*2^(exp/3) + * where 2^(exp/3) = 2^k'*2 or 2^k'*2^(1/3) or 2^k'*2^(2/3) */ + exponent = exponent - *op_e + 3; + INT shift_tmp = + ((INT)fMultDiv2((FIXP_SGL)fAbs(exponent), (FIXP_SGL)0x5556)) >> 16; + if (exponent < 0) { + shift_tmp = -shift_tmp; + } + INT rem = exponent - 3 * shift_tmp; + if (rem < 0) { + rem += 3; + shift_tmp--; + } + + *op_e = shift_tmp; + op_m = fMultDiv2(op_m, invCubeRootCorrection[rem]) << 2; + + return (op_m); +} + + /***************************************************************************** + + functionname: invFourthRootNorm2 + description: delivers 1/FourthRoot(op) in Q1.31 format and modified + exponent + + *****************************************************************************/ + +#define FOURTHROOT_BITS 7 +#define FOURTHROOT_VALUES (128 + 2) +#define FOURTHROOT_BITS_MASK 0x7f +#define FOURTHROOT_FRACT_BITS_MASK 0x007FFFFF + +LNK_SECTION_CONSTDATA +static const FIXP_DBL invFourthRootTab[FOURTHROOT_VALUES] = { + (0x4c1bf829), (0x4bf61977), (0x4bd09843), (0x4bab72ef), (0x4b86a7eb), + (0x4b6235ac), (0x4b3e1ab6), (0x4b1a5592), (0x4af6e4d4), (0x4ad3c718), + (0x4ab0fb03), (0x4a8e7f42), (0x4a6c5288), (0x4a4a7393), (0x4a28e126), + (0x4a079a0c), (0x49e69d16), (0x49c5e91f), (0x49a57d04), (0x498557ac), + (0x49657802), (0x4945dcf9), (0x49268588), (0x490770ac), (0x48e89d6a), + (0x48ca0ac9), (0x48abb7d6), (0x488da3a6), (0x486fcd4f), (0x485233ed), + (0x4834d6a3), (0x4817b496), (0x47faccf0), (0x47de1ee0), (0x47c1a999), + (0x47a56c51), (0x47896643), (0x476d96af), (0x4751fcd6), (0x473697ff), + (0x471b6773), (0x47006a81), (0x46e5a079), (0x46cb08ae), (0x46b0a279), + (0x46966d34), (0x467c683d), (0x466292f4), (0x4648ecbc), (0x462f74fe), + (0x46162b20), (0x45fd0e91), (0x45e41ebe), (0x45cb5b19), (0x45b2c315), + (0x459a562a), (0x458213cf), (0x4569fb81), (0x45520cbc), (0x453a4701), + (0x4522a9d1), (0x450b34b0), (0x44f3e726), (0x44dcc0ba), (0x44c5c0f7), + (0x44aee768), (0x4498339e), (0x4481a527), (0x446b3b96), (0x4454f67e), + (0x443ed576), (0x4428d815), (0x4412fdf3), (0x43fd46ad), (0x43e7b1de), + (0x43d23f23), (0x43bcee1e), (0x43a7be6f), (0x4392afb8), (0x437dc19d), + (0x4368f3c5), (0x435445d6), (0x433fb779), (0x432b4856), (0x4316f81a), + (0x4302c66f), (0x42eeb305), (0x42dabd8a), (0x42c6e5ad), (0x42b32b21), + (0x429f8d96), (0x428c0cc2), (0x4278a859), (0x42656010), (0x4252339e), + (0x423f22bc), (0x422c2d23), (0x4219528b), (0x420692b2), (0x41f3ed51), + (0x41e16228), (0x41cef0f2), (0x41bc9971), (0x41aa5b62), (0x41983687), + (0x41862aa2), (0x41743775), (0x41625cc3), (0x41509a50), (0x413eefe2), + (0x412d5d3e), (0x411be22b), (0x410a7e70), (0x40f931d5), (0x40e7fc23), + (0x40d6dd24), (0x40c5d4a2), (0x40b4e268), (0x40a40642), (0x40933ffc), + (0x40828f64), (0x4071f447), (0x40616e73), (0x4050fdb9), (0x4040a1e6), + (0x40305acc), (0x4020283c), (0x40100a08), (0x40000000), (0x3ff009f9), +}; + +static const FIXP_DBL invFourthRootCorrection[4] = {0x40000000, 0x4C1BF829, + 0x5A82799A, 0x6BA27E65}; + +/* The fourth root function */ +/***************************************************************************** + * \brief calculate 1.0/fourth_root(op), op contains mantissa and exponent + * \param op_m: (i) mantissa of operand, must not be zero (0x0000.0000) or + * negative + * \param op_e: (i) pointer to the exponent of the operand (must be initialized) + * and .. (o) pointer to the exponent of the result + * \return: (o) mantissa of the result + * \description: + * This routine calculates the cube root of the input operand, that is + * given with its mantissa in Q31 format (FIXP_DBL) and its exponent (INT). + * The resulting mantissa is returned in format Q31. The exponent (*op_e) + * is modified accordingly. It is not assured, that the result is fully + * left-aligned but assumed to have not more than 2 bits headroom. There is one + * macro to activate the use of this algorithm: FUNCTION_invFourthRootNorm2 By + * means of activating the macro INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ, a + * slightly higher precision is reachable (by default, not active). For DEBUG + * purpose only: a FDK_ASSERT macro validates, if the input mantissa is greater + * zero. + * + */ + +/* #define INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + +static +#ifdef __arm__ + FIXP_DBL FDK_FORCEINLINE + invFourthRootNorm2(FIXP_DBL op_m, INT* op_e) +#else + FIXP_DBL + invFourthRootNorm2(FIXP_DBL op_m, INT* op_e) +#endif +{ + FDK_ASSERT(op_m > FL2FXCONST_DBL(0.0)); + + /* normalize input, calculate shift value */ + INT exponent = (INT)fNormz(op_m) - 1; + op_m <<= exponent; + + INT index = (INT)(op_m >> (DFRACT_BITS - 1 - (FOURTHROOT_BITS + 1))) & + FOURTHROOT_BITS_MASK; + FIXP_DBL fract = (FIXP_DBL)(((INT)op_m & FOURTHROOT_FRACT_BITS_MASK) + << (FOURTHROOT_BITS + 1)); + FIXP_DBL diff = invFourthRootTab[index + 1] - invFourthRootTab[index]; + op_m = invFourthRootTab[index] + (fMultDiv2(diff, fract) << 1); + +#if defined(INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ) + /* reg1 = t[i] + (t[i+1]-t[i])*fract ... already computed ... + + * (1-fract)fract*(t[i+2]-t[i+1])/2 */ + if (fract != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + fract = fMultDiv2(fract, (FIXP_DBL)((LONG)0x80000000 - (LONG)fract)) << 1; + diff = diff - (invFourthRootTab[index + 2] - invFourthRootTab[index + 1]); + op_m = fMultAddDiv2(op_m, fract, diff); + } +#endif /* INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + + exponent = exponent - *op_e + 4; + INT rem = exponent & 0x00000003; + INT shift_tmp = (exponent >> 2); + + *op_e = shift_tmp; + op_m = fMultDiv2(op_m, invFourthRootCorrection[rem]) << 2; + + return (op_m); +} + +/***************************************************************************** + + functionname: inv3EigthRootNorm2 + description: delivers 1/cubert(op) normalized to .5...1 and the shift value +of the OUTPUT + +*****************************************************************************/ +#define THREEIGTHROOT_BITS 7 +#define THREEIGTHROOT_VALUES (128 + 2) +#define THREEIGTHROOT_BITS_MASK 0x7f +#define THREEIGTHROOT_FRACT_BITS_MASK 0x007FFFFF + +LNK_SECTION_CONSTDATA +static const FIXP_DBL inv3EigthRootTab[THREEIGTHROOT_VALUES] = { + (0x45cae0f2), (0x45b981bf), (0x45a8492a), (0x45973691), (0x45864959), + (0x457580e6), (0x4564dca4), (0x45545c00), (0x4543fe6b), (0x4533c35a), + (0x4523aa44), (0x4513b2a4), (0x4503dbf7), (0x44f425be), (0x44e48f7b), + (0x44d518b6), (0x44c5c0f7), (0x44b687c8), (0x44a76cb8), (0x44986f58), + (0x44898f38), (0x447acbef), (0x446c2514), (0x445d9a3f), (0x444f2b0d), + (0x4440d71a), (0x44329e07), (0x44247f73), (0x44167b04), (0x4408905e), + (0x43fabf28), (0x43ed070b), (0x43df67b0), (0x43d1e0c5), (0x43c471f7), + (0x43b71af6), (0x43a9db71), (0x439cb31c), (0x438fa1ab), (0x4382a6d2), + (0x4375c248), (0x4368f3c5), (0x435c3b03), (0x434f97bc), (0x434309ac), + (0x43369091), (0x432a2c28), (0x431ddc30), (0x4311a06c), (0x4305789c), + (0x42f96483), (0x42ed63e5), (0x42e17688), (0x42d59c30), (0x42c9d4a6), + (0x42be1fb1), (0x42b27d1a), (0x42a6ecac), (0x429b6e2f), (0x42900172), + (0x4284a63f), (0x42795c64), (0x426e23b0), (0x4262fbf2), (0x4257e4f9), + (0x424cde96), (0x4241e89a), (0x423702d8), (0x422c2d23), (0x4221674d), + (0x4216b12c), (0x420c0a94), (0x4201735b), (0x41f6eb57), (0x41ec725f), + (0x41e2084b), (0x41d7acf3), (0x41cd6030), (0x41c321db), (0x41b8f1ce), + (0x41aecfe5), (0x41a4bbf8), (0x419ab5e6), (0x4190bd89), (0x4186d2bf), + (0x417cf565), (0x41732558), (0x41696277), (0x415faca1), (0x415603b4), + (0x414c6792), (0x4142d818), (0x4139552a), (0x412fdea6), (0x41267470), + (0x411d1668), (0x4113c472), (0x410a7e70), (0x41014445), (0x40f815d4), + (0x40eef302), (0x40e5dbb4), (0x40dccfcd), (0x40d3cf33), (0x40cad9cb), + (0x40c1ef7b), (0x40b9102a), (0x40b03bbd), (0x40a7721c), (0x409eb32e), + (0x4095feda), (0x408d5508), (0x4084b5a0), (0x407c208b), (0x407395b2), + (0x406b14fd), (0x40629e56), (0x405a31a6), (0x4051ced8), (0x404975d5), + (0x40412689), (0x4038e0dd), (0x4030a4bd), (0x40287215), (0x402048cf), + (0x401828d7), (0x4010121a), (0x40080483), (0x40000000), (0x3ff8047d), +}; + +/* The last value is rounded in order to avoid any overflow due to the values + * range of the root table */ +static const FIXP_DBL inv3EigthRootCorrection[8] = { + 0x40000000, 0x45CAE0F2, 0x4C1BF829, 0x52FF6B55, + 0x5A82799A, 0x62B39509, 0x6BA27E65, 0x75606373}; + +/* The 3/8 root function */ +/***************************************************************************** + * \brief calculate 1.0/3Eigth_root(op) = 1.0/(x)^(3/8), op contains mantissa + * and exponent + * \param op_m: (i) mantissa of operand, must not be zero (0x0000.0000) or + * negative + * \param op_e: (i) pointer to the exponent of the operand (must be initialized) + * and .. (o) pointer to the exponent of the result + * \return: (o) mantissa of the result + * \description: + * This routine calculates the cube root of the input operand, that is + * given with its mantissa in Q31 format (FIXP_DBL) and its exponent (INT). + * The resulting mantissa is returned in format Q31. The exponent (*op_e) + * is modified accordingly. It is not assured, that the result is fully + * left-aligned but assumed to have not more than 2 bits headroom. There is one + * macro to activate the use of this algorithm: FUNCTION_inv3EigthRootNorm2 By + * means of activating the macro INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ, a + * slightly higher precision is reachable (by default, not active). For DEBUG + * purpose only: a FDK_ASSERT macro validates, if the input mantissa is greater + * zero. + * + */ + +/* #define INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + +static +#ifdef __arm__ + FIXP_DBL FDK_FORCEINLINE + inv3EigthRootNorm2(FIXP_DBL op_m, INT* op_e) +#else + FIXP_DBL + inv3EigthRootNorm2(FIXP_DBL op_m, INT* op_e) +#endif +{ + FDK_ASSERT(op_m > FL2FXCONST_DBL(0.0)); + + /* normalize input, calculate shift op_mue */ + INT exponent = (INT)fNormz(op_m) - 1; + op_m <<= exponent; + + INT index = (INT)(op_m >> (DFRACT_BITS - 1 - (THREEIGTHROOT_BITS + 1))) & + THREEIGTHROOT_BITS_MASK; + FIXP_DBL fract = (FIXP_DBL)(((INT)op_m & THREEIGTHROOT_FRACT_BITS_MASK) + << (THREEIGTHROOT_BITS + 1)); + FIXP_DBL diff = inv3EigthRootTab[index + 1] - inv3EigthRootTab[index]; + op_m = inv3EigthRootTab[index] + (fMultDiv2(diff, fract) << 1); + +#if defined(INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ) + /* op_m = t[i] + (t[i+1]-t[i])*fract ... already computed ... + + * (1-fract)fract*(t[i+2]-t[i+1])/2 */ + if (fract != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + fract = fMultDiv2(fract, (FIXP_DBL)((LONG)0x80000000 - (LONG)fract)) << 1; + diff = diff - (inv3EigthRootTab[index + 2] - inv3EigthRootTab[index + 1]); + op_m = fMultAddDiv2(op_m, fract, diff); + } +#endif /* INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + + exponent = exponent - *op_e + 8; + INT rem = exponent & 0x00000007; + INT shift_tmp = (exponent >> 3); + + *op_e = shift_tmp * 3; + op_m = fMultDiv2(op_m, inv3EigthRootCorrection[rem]) << 2; + + return (fMult(op_m, fMult(op_m, op_m))); +} + +SBR_ERROR +QmfTransposerCreate(HANDLE_HBE_TRANSPOSER* hQmfTransposer, const int frameSize, + int bDisableCrossProducts, int bSbr41) { + HANDLE_HBE_TRANSPOSER hQmfTran = NULL; + + int i; + + if (hQmfTransposer != NULL) { + /* Memory allocation */ + /*--------------------------------------------------------------------------------------------*/ + hQmfTran = + (HANDLE_HBE_TRANSPOSER)FDKcalloc(1, sizeof(struct hbeTransposer)); + if (hQmfTran == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + for (i = 0; i < MAX_STRETCH_HBE - 1; i++) { + hQmfTran->bXProducts[i] = (bDisableCrossProducts ? 0 : xProducts[i]); + } + + hQmfTran->timeDomainWinLen = frameSize; + if (frameSize == 768) { + hQmfTran->noCols = + (8 * frameSize / 3) / QMF_SYNTH_CHANNELS; /* 32 for 24:64 */ + } else { + hQmfTran->noCols = + (bSbr41 + 1) * 2 * frameSize / + QMF_SYNTH_CHANNELS; /* 32 for 32:64 and 64 for 16:64 -> identical to + sbrdec->no_cols */ + } + + hQmfTran->noChannels = frameSize / hQmfTran->noCols; + + hQmfTran->qmfInBufSize = QMF_WIN_LEN; + hQmfTran->qmfOutBufSize = 2 * (hQmfTran->noCols / 2 + QMF_WIN_LEN - 1); + + hQmfTran->inBuf_F = + (LONG*)FDKcalloc(QMF_SYNTH_CHANNELS + 20 + 1, sizeof(LONG)); + /* buffered time signal needs to be delayed by synthesis_size; max + * synthesis_size = 20; */ + if (hQmfTran->inBuf_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + hQmfTran->qmfInBufReal_F = + (FIXP_DBL**)FDKcalloc(hQmfTran->qmfInBufSize, sizeof(FIXP_DBL*)); + hQmfTran->qmfInBufImag_F = + (FIXP_DBL**)FDKcalloc(hQmfTran->qmfInBufSize, sizeof(FIXP_DBL*)); + + if (hQmfTran->qmfInBufReal_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfInBufImag_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + for (i = 0; i < hQmfTran->qmfInBufSize; i++) { + hQmfTran->qmfInBufReal_F[i] = (FIXP_DBL*)FDKaalloc( + QMF_SYNTH_CHANNELS * sizeof(FIXP_DBL), ALIGNMENT_DEFAULT); + hQmfTran->qmfInBufImag_F[i] = (FIXP_DBL*)FDKaalloc( + QMF_SYNTH_CHANNELS * sizeof(FIXP_DBL), ALIGNMENT_DEFAULT); + if (hQmfTran->qmfInBufReal_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfInBufImag_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + } + + hQmfTran->qmfHBEBufReal_F = + (FIXP_DBL**)FDKcalloc(HBE_MAX_OUT_SLOTS, sizeof(FIXP_DBL*)); + hQmfTran->qmfHBEBufImag_F = + (FIXP_DBL**)FDKcalloc(HBE_MAX_OUT_SLOTS, sizeof(FIXP_DBL*)); + + if (hQmfTran->qmfHBEBufReal_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfHBEBufImag_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + hQmfTran->qmfHBEBufReal_F[i] = + (FIXP_DBL*)FDKcalloc(QMF_SYNTH_CHANNELS, sizeof(FIXP_DBL)); + hQmfTran->qmfHBEBufImag_F[i] = + (FIXP_DBL*)FDKcalloc(QMF_SYNTH_CHANNELS, sizeof(FIXP_DBL)); + if (hQmfTran->qmfHBEBufReal_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfHBEBufImag_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + } + + hQmfTran->qmfBufferCodecTempSlot_F = + (FIXP_DBL*)FDKcalloc(QMF_SYNTH_CHANNELS / 2, sizeof(FIXP_DBL)); + if (hQmfTran->qmfBufferCodecTempSlot_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + hQmfTran->bSbr41 = bSbr41; + + hQmfTran->highband_exp[0] = 0; + hQmfTran->highband_exp[1] = 0; + hQmfTran->target_exp[0] = 0; + hQmfTran->target_exp[1] = 0; + + *hQmfTransposer = hQmfTran; + } + + return SBRDEC_OK; +} + +SBR_ERROR QmfTransposerReInit(HANDLE_HBE_TRANSPOSER hQmfTransposer, + UCHAR* FreqBandTable[2], UCHAR NSfb[2]) +/* removed bSbr41 from parameterlist: + don't know where to get this value from + at call-side */ +{ + int L, sfb, patch, stopPatch, qmfErr; + + if (hQmfTransposer != NULL) { + const FIXP_QTW* tmp_t_cos; + const FIXP_QTW* tmp_t_sin; + + hQmfTransposer->startBand = FreqBandTable[0][0]; + FDK_ASSERT((!hQmfTransposer->bSbr41 && hQmfTransposer->startBand <= 32) || + (hQmfTransposer->bSbr41 && + hQmfTransposer->startBand <= + 16)); /* is checked by resetFreqBandTables() */ + hQmfTransposer->stopBand = FreqBandTable[0][NSfb[0]]; + + hQmfTransposer->synthSize = + 4 * ((hQmfTransposer->startBand + 4) / 8 + 1); /* 8, 12, 16, 20 */ + hQmfTransposer->kstart = startSubband2kL[hQmfTransposer->startBand]; + + /* don't know where to take this information from */ + /* hQmfTransposer->bSbr41 = bSbr41; */ + + if (hQmfTransposer->bSbr41) { + if (hQmfTransposer->kstart + hQmfTransposer->synthSize > 16) + hQmfTransposer->kstart = 16 - hQmfTransposer->synthSize; + } else if (hQmfTransposer->timeDomainWinLen == 768) { + if (hQmfTransposer->kstart + hQmfTransposer->synthSize > 24) + hQmfTransposer->kstart = 24 - hQmfTransposer->synthSize; + } + + hQmfTransposer->synthesisQmfPreModCos_F = + &preModCos[hQmfTransposer->kstart]; + hQmfTransposer->synthesisQmfPreModSin_F = + &preModSin[hQmfTransposer->kstart]; + + L = 2 * hQmfTransposer->synthSize; /* 8, 16, 24, 32, 40 */ + /* Change analysis post twiddles */ + + switch (L) { + case 8: + tmp_t_cos = post_twiddle_cos_8; + tmp_t_sin = post_twiddle_sin_8; + break; + case 16: + tmp_t_cos = post_twiddle_cos_16; + tmp_t_sin = post_twiddle_sin_16; + break; + case 24: + tmp_t_cos = post_twiddle_cos_24; + tmp_t_sin = post_twiddle_sin_24; + break; + case 32: + tmp_t_cos = post_twiddle_cos_32; + tmp_t_sin = post_twiddle_sin_32; + break; + case 40: + tmp_t_cos = post_twiddle_cos_40; + tmp_t_sin = post_twiddle_sin_40; + break; + default: + return SBRDEC_UNSUPPORTED_CONFIG; + } + + qmfErr = qmfInitSynthesisFilterBank( + &hQmfTransposer->HBESynthesisQMF, hQmfTransposer->synQmfStates, + hQmfTransposer->noCols, 0, hQmfTransposer->synthSize, + hQmfTransposer->synthSize, 1); + if (qmfErr != 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + qmfErr = qmfInitAnalysisFilterBank( + &hQmfTransposer->HBEAnalysiscQMF, hQmfTransposer->anaQmfStates, + hQmfTransposer->noCols / 2, 0, 2 * hQmfTransposer->synthSize, + 2 * hQmfTransposer->synthSize, 0); + + if (qmfErr != 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + hQmfTransposer->HBEAnalysiscQMF.t_cos = tmp_t_cos; + hQmfTransposer->HBEAnalysiscQMF.t_sin = tmp_t_sin; + + FDKmemset(hQmfTransposer->xOverQmf, 0, + MAX_NUM_PATCHES * sizeof(int)); /* global */ + sfb = 0; + if (hQmfTransposer->bSbr41) { + stopPatch = MAX_NUM_PATCHES; + hQmfTransposer->maxStretch = MAX_STRETCH_HBE; + } else { + stopPatch = MAX_STRETCH_HBE; + } + + for (patch = 1; patch <= stopPatch; patch++) { + while (sfb <= NSfb[0] && + FreqBandTable[0][sfb] <= patch * hQmfTransposer->startBand) + sfb++; + if (sfb <= NSfb[0]) { + /* If the distance is larger than three QMF bands - try aligning to high + * resolution frequency bands instead. */ + if ((patch * hQmfTransposer->startBand - FreqBandTable[0][sfb - 1]) <= + 3) { + hQmfTransposer->xOverQmf[patch - 1] = FreqBandTable[0][sfb - 1]; + } else { + int sfb_tmp = 0; + while (sfb_tmp <= NSfb[1] && + FreqBandTable[1][sfb_tmp] <= patch * hQmfTransposer->startBand) + sfb_tmp++; + hQmfTransposer->xOverQmf[patch - 1] = FreqBandTable[1][sfb_tmp - 1]; + } + } else { + hQmfTransposer->xOverQmf[patch - 1] = hQmfTransposer->stopBand; + hQmfTransposer->maxStretch = fMin(patch, MAX_STRETCH_HBE); + break; + } + } + + hQmfTransposer->highband_exp[0] = 0; + hQmfTransposer->highband_exp[1] = 0; + hQmfTransposer->target_exp[0] = 0; + hQmfTransposer->target_exp[1] = 0; + } + + return SBRDEC_OK; +} + +void QmfTransposerClose(HANDLE_HBE_TRANSPOSER hQmfTransposer) { + int i; + + if (hQmfTransposer != NULL) { + if (hQmfTransposer->inBuf_F) FDKfree(hQmfTransposer->inBuf_F); + + if (hQmfTransposer->qmfInBufReal_F) { + for (i = 0; i < hQmfTransposer->qmfInBufSize; i++) { + FDKafree(hQmfTransposer->qmfInBufReal_F[i]); + } + FDKfree(hQmfTransposer->qmfInBufReal_F); + } + + if (hQmfTransposer->qmfInBufImag_F) { + for (i = 0; i < hQmfTransposer->qmfInBufSize; i++) { + FDKafree(hQmfTransposer->qmfInBufImag_F[i]); + } + FDKfree(hQmfTransposer->qmfInBufImag_F); + } + + if (hQmfTransposer->qmfHBEBufReal_F) { + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + FDKfree(hQmfTransposer->qmfHBEBufReal_F[i]); + } + FDKfree(hQmfTransposer->qmfHBEBufReal_F); + } + + if (hQmfTransposer->qmfHBEBufImag_F) { + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + FDKfree(hQmfTransposer->qmfHBEBufImag_F[i]); + } + FDKfree(hQmfTransposer->qmfHBEBufImag_F); + } + + FDKfree(hQmfTransposer->qmfBufferCodecTempSlot_F); + + FDKfree(hQmfTransposer); + } +} + +inline void scaleUp(FIXP_DBL* real_m, FIXP_DBL* imag_m, INT* _e) { + INT reserve; + /* shift gc_r and gc_i up if possible */ + reserve = CntLeadingZeros((INT(*real_m) ^ INT((*real_m >> 31))) | + (INT(*imag_m) ^ INT((*imag_m >> 31)))) - + 1; + reserve = fMax(reserve - 1, + 0); /* Leave one bit headroom such that (real_m^2 + imag_m^2) + does not overflow later if both are 0x80000000. */ + reserve = fMin(reserve, *_e); + FDK_ASSERT(reserve >= 0); + *real_m <<= reserve; + *imag_m <<= reserve; + *_e -= reserve; +} + +static void calculateCenterFIXP(FIXP_DBL gammaVecReal, FIXP_DBL gammaVecImag, + FIXP_DBL* centerReal, FIXP_DBL* centerImag, + INT* exponent, int stretch, int mult) { + scaleUp(&gammaVecReal, &gammaVecImag, exponent); + FIXP_DBL energy = fPow2Div2(gammaVecReal) + fPow2Div2(gammaVecImag); + + if (energy != FL2FXCONST_DBL(0.f)) { + FIXP_DBL gc_r_m, gc_i_m, factor_m = (FIXP_DBL)0; + INT factor_e, gc_e; + factor_e = 2 * (*exponent) + 1; + + switch (stretch) { + case 2: + factor_m = invFourthRootNorm2(energy, &factor_e); + break; + case 3: + factor_m = invCubeRootNorm2(energy, &factor_e); + break; + case 4: + factor_m = inv3EigthRootNorm2(energy, &factor_e); + break; + } + + gc_r_m = fMultDiv2(gammaVecReal, + factor_m); /* exponent = HBE_SCALE + factor_e + 1 */ + gc_i_m = fMultDiv2(gammaVecImag, + factor_m); /* exponent = HBE_SCALE + factor_e + 1*/ + gc_e = *exponent + factor_e + 1; + + scaleUp(&gc_r_m, &gc_i_m, &gc_e); + + switch (mult) { + case 0: + *centerReal = gc_r_m; + *centerImag = gc_i_m; + break; + case 1: + *centerReal = fPow2Div2(gc_r_m) - fPow2Div2(gc_i_m); + *centerImag = fMult(gc_r_m, gc_i_m); + gc_e = 2 * gc_e + 1; + break; + case 2: + FIXP_DBL tmp_r = gc_r_m; + FIXP_DBL tmp_i = gc_i_m; + gc_r_m = fPow2Div2(gc_r_m) - fPow2Div2(gc_i_m); + gc_i_m = fMult(tmp_r, gc_i_m); + gc_e = 3 * gc_e + 1 + 1; + cplxMultDiv2(¢erReal[0], ¢erImag[0], gc_r_m, gc_i_m, tmp_r, + tmp_i); + break; + } + + scaleUp(centerReal, centerImag, &gc_e); + + FDK_ASSERT(gc_e >= 0); + *exponent = gc_e; + } else { + *centerReal = energy; /* energy = 0 */ + *centerImag = energy; /* energy = 0 */ + *exponent = (INT)energy; + } +} + +static int getHBEScaleFactorFrame(const int bSbr41, const int maxStretch, + const int pitchInBins) { + if (pitchInBins >= pmin * (1 + bSbr41)) { + /* crossproducts enabled */ + return 26; + } else { + return (maxStretch == 2) ? 24 : 25; + } +} + +static void addHighBandPart(FIXP_DBL g_r_m, FIXP_DBL g_i_m, INT g_e, + FIXP_DBL mult, FIXP_DBL gammaCenterReal_m, + FIXP_DBL gammaCenterImag_m, INT gammaCenter_e, + INT stretch, INT scale_factor_hbe, + FIXP_DBL* qmfHBEBufReal_F, + FIXP_DBL* qmfHBEBufImag_F) { + if ((g_r_m | g_i_m) != FL2FXCONST_DBL(0.f)) { + FIXP_DBL factor_m = (FIXP_DBL)0; + INT factor_e; + INT add = (stretch == 4) ? 1 : 0; + INT shift = (stretch == 4) ? 1 : 2; + + scaleUp(&g_r_m, &g_i_m, &g_e); + FIXP_DBL energy = fPow2AddDiv2(fPow2Div2(g_r_m), g_i_m); + factor_e = 2 * g_e + 1; + + switch (stretch) { + case 2: + factor_m = invFourthRootNorm2(energy, &factor_e); + break; + case 3: + factor_m = invCubeRootNorm2(energy, &factor_e); + break; + case 4: + factor_m = inv3EigthRootNorm2(energy, &factor_e); + break; + } + + factor_m = fMult(factor_m, mult); + + FIXP_DBL tmp_r, tmp_i; + cplxMultDiv2(&tmp_r, &tmp_i, g_r_m, g_i_m, gammaCenterReal_m, + gammaCenterImag_m); + + g_r_m = fMultDiv2(tmp_r, factor_m) << shift; + g_i_m = fMultDiv2(tmp_i, factor_m) << shift; + g_e = scale_factor_hbe - (g_e + factor_e + gammaCenter_e + add); + g_e = fMax((INT)0, g_e); + *qmfHBEBufReal_F += g_r_m >> g_e; + *qmfHBEBufImag_F += g_i_m >> g_e; + } +} + +void QmfTransposerApply(HANDLE_HBE_TRANSPOSER hQmfTransposer, + FIXP_DBL** qmfBufferCodecReal, + FIXP_DBL** qmfBufferCodecImag, int nColsIn, + FIXP_DBL** ppQmfBufferOutReal_F, + FIXP_DBL** ppQmfBufferOutImag_F, + FIXP_DBL lpcFilterStatesReal[2 + (3 * (4))][(64)], + FIXP_DBL lpcFilterStatesImag[2 + (3 * (4))][(64)], + int pitchInBins, int scale_lb, int scale_hbe, + int* scale_hb, int timeStep, int firstSlotOffsset, + int ov_len, + KEEP_STATES_SYNCED_MODE keepStatesSyncedMode) { + int i, j, stretch, band, sourceband, r, s; + int qmfVocoderColsIn = hQmfTransposer->noCols / 2; + int bSbr41 = hQmfTransposer->bSbr41; + + const int winLength[3] = {10, 8, 6}; + const int slotOffset = 6; /* hQmfTransposer->winLen-6; */ + + int qmfOffset = 2 * hQmfTransposer->kstart; + int scale_border = (nColsIn == 64) ? 32 : nColsIn; + + INT slot_stretch4[9] = {0, 0, 0, 0, 2, 4, 6, 8, 10}; + INT slot_stretch2[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + INT slot_stretch3[10] = {0, 0, 0, 1, 3, 4, 6, 7, 9, 10}; + INT filt_stretch3[10] = {0, 0, 0, 1, 0, 1, 0, 1, 0, 1}; + INT filt_dummy[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + INT* pSlotStretch; + INT* pFilt; + + int offset = 0; /* where to take QmfTransposer data */ + + int signPreMod = + (hQmfTransposer->synthesisQmfPreModCos_F[0] < FL2FXCONST_DBL(0.f)) ? 1 + : -1; + + int scale_factor_hbe = + getHBEScaleFactorFrame(bSbr41, hQmfTransposer->maxStretch, pitchInBins); + + if (keepStatesSyncedMode != KEEP_STATES_SYNCED_OFF) { + offset = hQmfTransposer->noCols - ov_len - LPC_ORDER; + } + + hQmfTransposer->highband_exp[0] = hQmfTransposer->highband_exp[1]; + hQmfTransposer->target_exp[0] = hQmfTransposer->target_exp[1]; + + hQmfTransposer->highband_exp[1] = scale_factor_hbe; + hQmfTransposer->target_exp[1] = + fixMax(hQmfTransposer->highband_exp[1], hQmfTransposer->highband_exp[0]); + + scale_factor_hbe = hQmfTransposer->target_exp[1]; + + int shift_ov = hQmfTransposer->target_exp[0] - hQmfTransposer->target_exp[1]; + + if (shift_ov != 0) { + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + scaleValuesSaturate(&hQmfTransposer->qmfHBEBufReal_F[i][0], + QMF_SYNTH_CHANNELS, shift_ov); + scaleValuesSaturate(&hQmfTransposer->qmfHBEBufImag_F[i][0], + QMF_SYNTH_CHANNELS, shift_ov); + } + + if (keepStatesSyncedMode == KEEP_STATES_SYNCED_OFF) { + int nBands = + fMax(0, hQmfTransposer->stopBand - hQmfTransposer->startBand); + + for (i = timeStep * firstSlotOffsset; i < ov_len; i++) { + scaleValuesSaturate(&ppQmfBufferOutReal_F[i][hQmfTransposer->startBand], + nBands, shift_ov); + scaleValuesSaturate(&ppQmfBufferOutImag_F[i][hQmfTransposer->startBand], + nBands, shift_ov); + } + + /* shift lpc filterstates */ + for (i = 0; i < timeStep * firstSlotOffsset + LPC_ORDER; i++) { + scaleValuesSaturate(&lpcFilterStatesReal[i][0], (64), shift_ov); + scaleValuesSaturate(&lpcFilterStatesImag[i][0], (64), shift_ov); + } + } + } + + FIXP_DBL twid_m_new[3][2]; /* [stretch][cos/sin] */ + INT stepsize = 1 + !bSbr41, sine_offset = 24, mod = 96; + INT mult[3] = {1, 2, 3}; + + for (s = 0; s <= MAX_STRETCH_HBE - 2; s++) { + twid_m_new[s][0] = twiddle[(mult[s] * (stepsize * pitchInBins)) % mod]; + twid_m_new[s][1] = + twiddle[((mult[s] * (stepsize * pitchInBins)) + sine_offset) % mod]; + } + + /* Time-stretch */ + for (j = 0; j < qmfVocoderColsIn; j++) { + int sign = -1, k, z, addrshift, codecTemp_e; + /* update inbuf */ + for (i = 0; i < hQmfTransposer->synthSize; i++) { + hQmfTransposer->inBuf_F[i] = + hQmfTransposer->inBuf_F[i + 2 * hQmfTransposer->synthSize]; + } + + /* run synthesis for two sbr slots as transposer uses + half slots double bands representation */ + for (z = 0; z < 2; z++) { + int scale_factor = ((nColsIn == 64) && ((2 * j + z) < scale_border)) + ? scale_lb + : scale_hbe; + codecTemp_e = scale_factor - 1; /* -2 for Div2 and cos/sin scale of 1 */ + + for (k = 0; k < hQmfTransposer->synthSize; k++) { + int ki = hQmfTransposer->kstart + k; + hQmfTransposer->qmfBufferCodecTempSlot_F[k] = + fMultDiv2(signPreMod * hQmfTransposer->synthesisQmfPreModCos_F[k], + qmfBufferCodecReal[2 * j + z][ki]); + hQmfTransposer->qmfBufferCodecTempSlot_F[k] += + fMultDiv2(signPreMod * hQmfTransposer->synthesisQmfPreModSin_F[k], + qmfBufferCodecImag[2 * j + z][ki]); + } + + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + + qmfSynthesisFilteringSlot( + &hQmfTransposer->HBESynthesisQMF, + hQmfTransposer->qmfBufferCodecTempSlot_F, NULL, 0, + -7 - hQmfTransposer->HBESynthesisQMF.filterScale - codecTemp_e + 1, + hQmfTransposer->inBuf_F + hQmfTransposer->synthSize * (z + 1), 1, + pWorkBuffer); + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + } + + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + + qmfAnalysisFilteringSlot(&hQmfTransposer->HBEAnalysiscQMF, + hQmfTransposer->qmfInBufReal_F[QMF_WIN_LEN - 1], + hQmfTransposer->qmfInBufImag_F[QMF_WIN_LEN - 1], + hQmfTransposer->inBuf_F + 1, 1, pWorkBuffer); + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + + if ((keepStatesSyncedMode == KEEP_STATES_SYNCED_NORMAL) && + j <= qmfVocoderColsIn - ((LPC_ORDER + ov_len + QMF_WIN_LEN - 1) >> 1)) { + /* update in buffer */ + for (i = 0; i < QMF_WIN_LEN - 1; i++) { + FDKmemcpy( + hQmfTransposer->qmfInBufReal_F[i], + hQmfTransposer->qmfInBufReal_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + FDKmemcpy( + hQmfTransposer->qmfInBufImag_F[i], + hQmfTransposer->qmfInBufImag_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + } + continue; + } + + for (stretch = 2; stretch <= hQmfTransposer->maxStretch; stretch++) { + int start = slotOffset - winLength[stretch - 2] / 2; + int stop = slotOffset + winLength[stretch - 2] / 2; + + FIXP_DBL factor = FL2FXCONST_DBL(1.f / 3.f); + + for (band = hQmfTransposer->xOverQmf[stretch - 2]; + band < hQmfTransposer->xOverQmf[stretch - 1]; band++) { + FIXP_DBL gammaCenterReal_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}, + gammaCenterImag_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}; + INT gammaCenter_e[2] = {0, 0}; + + FIXP_DBL gammaVecReal_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}, + gammaVecImag_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}; + INT gammaVec_e[2] = {0, 0}; + + FIXP_DBL wingain = (FIXP_DBL)0; + + gammaCenter_e[0] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaCenter_e[1] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + /* interpolation filters for 3rd order */ + sourceband = 2 * band / stretch - qmfOffset; + FDK_ASSERT(sourceband >= 0); + + /* maximum gammaCenter_e == 20 */ + calculateCenterFIXP( + hQmfTransposer->qmfInBufReal_F[slotOffset][sourceband], + hQmfTransposer->qmfInBufImag_F[slotOffset][sourceband], + &gammaCenterReal_m[0], &gammaCenterImag_m[0], &gammaCenter_e[0], + stretch, stretch - 2); + + if (stretch == 4) { + r = band - 2 * (band / 2); + sourceband += (r == 0) ? -1 : 1; + pSlotStretch = slot_stretch4; + factor = FL2FXCONST_DBL(2.f / 3.f); + pFilt = filt_dummy; + } else if (stretch == 2) { + r = 0; + sourceband = 2 * band / stretch - qmfOffset; + pSlotStretch = slot_stretch2; + factor = FL2FXCONST_DBL(1.f / 3.f); + pFilt = filt_dummy; + } else { + r = 2 * band - 3 * (2 * band / 3); + sourceband = 2 * band / stretch - qmfOffset; + pSlotStretch = slot_stretch3; + factor = FL2FXCONST_DBL(1.4142f / 3.0f); + pFilt = filt_stretch3; + } + + if (r == 2) { + calculateCenterFIXP( + hQmfTransposer->qmfInBufReal_F[slotOffset][sourceband + 1], + hQmfTransposer->qmfInBufImag_F[slotOffset][sourceband + 1], + &gammaCenterReal_m[1], &gammaCenterImag_m[1], &gammaCenter_e[1], + stretch, stretch - 2); + + factor = FL2FXCONST_DBL(1.4142f / 6.0f); + } + + if (r == 2) { + for (k = start; k < stop; k++) { + gammaVecReal_m[0] = + hQmfTransposer->qmfInBufReal_F[pSlotStretch[k]][sourceband]; + gammaVecReal_m[1] = + hQmfTransposer->qmfInBufReal_F[pSlotStretch[k]][sourceband + 1]; + gammaVecImag_m[0] = + hQmfTransposer->qmfInBufImag_F[pSlotStretch[k]][sourceband]; + gammaVecImag_m[1] = + hQmfTransposer->qmfInBufImag_F[pSlotStretch[k]][sourceband + 1]; + gammaVec_e[0] = gammaVec_e[1] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + if (pFilt[k] == 1) { + FIXP_DBL tmpRealF = gammaVecReal_m[0], tmpImagF; + gammaVecReal_m[0] = + (fMult(gammaVecReal_m[0], hintReal_F[sourceband % 4][1]) - + fMult(gammaVecImag_m[0], + hintReal_F[(sourceband + 3) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] = + (fMult(tmpRealF, hintReal_F[(sourceband + 3) % 4][1]) + + fMult(gammaVecImag_m[0], hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + + tmpRealF = hQmfTransposer + ->qmfInBufReal_F[pSlotStretch[k] + 1][sourceband]; + tmpImagF = hQmfTransposer + ->qmfInBufImag_F[pSlotStretch[k] + 1][sourceband]; + + gammaVecReal_m[0] += + (fMult(tmpRealF, hintReal_F[sourceband % 4][1]) - + fMult(tmpImagF, hintReal_F[(sourceband + 1) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] += + (fMult(tmpRealF, hintReal_F[(sourceband + 1) % 4][1]) + + fMult(tmpImagF, hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVec_e[0]++; + + tmpRealF = gammaVecReal_m[1]; + + gammaVecReal_m[1] = + (fMult(gammaVecReal_m[1], hintReal_F[sourceband % 4][2]) - + fMult(gammaVecImag_m[1], + hintReal_F[(sourceband + 3) % 4][2])) >> + 1; + gammaVecImag_m[1] = + (fMult(tmpRealF, hintReal_F[(sourceband + 3) % 4][2]) + + fMult(gammaVecImag_m[1], hintReal_F[sourceband % 4][2])) >> + 1; + + tmpRealF = + hQmfTransposer + ->qmfInBufReal_F[pSlotStretch[k] + 1][sourceband + 1]; + tmpImagF = + hQmfTransposer + ->qmfInBufImag_F[pSlotStretch[k] + 1][sourceband + 1]; + + gammaVecReal_m[1] += + (fMult(tmpRealF, hintReal_F[sourceband % 4][2]) - + fMult(tmpImagF, hintReal_F[(sourceband + 1) % 4][2])) >> + 1; + gammaVecImag_m[1] += + (fMult(tmpRealF, hintReal_F[(sourceband + 1) % 4][2]) + + fMult(tmpImagF, hintReal_F[sourceband % 4][2])) >> + 1; + gammaVec_e[1]++; + } + + addHighBandPart(gammaVecReal_m[1], gammaVecImag_m[1], gammaVec_e[1], + factor, gammaCenterReal_m[0], gammaCenterImag_m[0], + gammaCenter_e[0], stretch, scale_factor_hbe, + &hQmfTransposer->qmfHBEBufReal_F[k][band], + &hQmfTransposer->qmfHBEBufImag_F[k][band]); + + addHighBandPart(gammaVecReal_m[0], gammaVecImag_m[0], gammaVec_e[0], + factor, gammaCenterReal_m[1], gammaCenterImag_m[1], + gammaCenter_e[1], stretch, scale_factor_hbe, + &hQmfTransposer->qmfHBEBufReal_F[k][band], + &hQmfTransposer->qmfHBEBufImag_F[k][band]); + } + } else { + for (k = start; k < stop; k++) { + gammaVecReal_m[0] = + hQmfTransposer->qmfInBufReal_F[pSlotStretch[k]][sourceband]; + gammaVecImag_m[0] = + hQmfTransposer->qmfInBufImag_F[pSlotStretch[k]][sourceband]; + gammaVec_e[0] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + if (pFilt[k] == 1) { + FIXP_DBL tmpRealF = gammaVecReal_m[0], tmpImagF; + gammaVecReal_m[0] = + (fMult(gammaVecReal_m[0], hintReal_F[sourceband % 4][1]) - + fMult(gammaVecImag_m[0], + hintReal_F[(sourceband + 3) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] = + (fMult(tmpRealF, hintReal_F[(sourceband + 3) % 4][1]) + + fMult(gammaVecImag_m[0], hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + + tmpRealF = hQmfTransposer + ->qmfInBufReal_F[pSlotStretch[k] + 1][sourceband]; + tmpImagF = hQmfTransposer + ->qmfInBufImag_F[pSlotStretch[k] + 1][sourceband]; + + gammaVecReal_m[0] += + (fMult(tmpRealF, hintReal_F[sourceband % 4][1]) - + fMult(tmpImagF, hintReal_F[(sourceband + 1) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] += + (fMult(tmpRealF, hintReal_F[(sourceband + 1) % 4][1]) + + fMult(tmpImagF, hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVec_e[0]++; + } + + addHighBandPart(gammaVecReal_m[0], gammaVecImag_m[0], gammaVec_e[0], + factor, gammaCenterReal_m[0], gammaCenterImag_m[0], + gammaCenter_e[0], stretch, scale_factor_hbe, + &hQmfTransposer->qmfHBEBufReal_F[k][band], + &hQmfTransposer->qmfHBEBufImag_F[k][band]); + } + } + + /* pitchInBins is given with the resolution of a 768 bins FFT and we + * need 64 QMF units so factor 768/64 = 12 */ + if (pitchInBins >= pmin * (1 + bSbr41)) { + int tr, ti1, ti2, mTr = 0, ts1 = 0, ts2 = 0, mVal_e = 0, temp_e = 0; + int sqmag0_e = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + FIXP_DBL mVal_F = FL2FXCONST_DBL(0.f), sqmag0_F, sqmag1_F, sqmag2_F, + temp_F, f1_F; /* all equal exponent */ + sign = -1; + + sourceband = 2 * band / stretch - qmfOffset; /* consistent with the + already computed for + stretch = 3,4. */ + FDK_ASSERT(sourceband >= 0); + + FIXP_DBL sqmag0R_F = + hQmfTransposer->qmfInBufReal_F[slotOffset][sourceband]; + FIXP_DBL sqmag0I_F = + hQmfTransposer->qmfInBufImag_F[slotOffset][sourceband]; + scaleUp(&sqmag0R_F, &sqmag0I_F, &sqmag0_e); + + sqmag0_F = fPow2Div2(sqmag0R_F); + sqmag0_F += fPow2Div2(sqmag0I_F); + sqmag0_e = 2 * sqmag0_e + 1; + + for (tr = 1; tr < stretch; tr++) { + int sqmag1_e = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + int sqmag2_e = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + FIXP_DBL tmp_band = band_F[band]; + FIXP_DBL tr_p = + fMult(p_F[pitchInBins] >> bSbr41, tr_str[tr - 1]); /* scale 7 */ + f1_F = + fMult(tmp_band - tr_p, stretchfac[stretch - 2]); /* scale 7 */ + ti1 = (INT)(f1_F >> (DFRACT_BITS - 1 - 7)) - qmfOffset; + ti2 = (INT)(((f1_F) + ((p_F[pitchInBins] >> bSbr41) >> 2)) >> + (DFRACT_BITS - 1 - 7)) - + qmfOffset; + + if (ti1 >= 0 && ti2 < 2 * hQmfTransposer->synthSize) { + FIXP_DBL sqmag1R_F = + hQmfTransposer->qmfInBufReal_F[slotOffset][ti1]; + FIXP_DBL sqmag1I_F = + hQmfTransposer->qmfInBufImag_F[slotOffset][ti1]; + scaleUp(&sqmag1R_F, &sqmag1I_F, &sqmag1_e); + sqmag1_F = fPow2Div2(sqmag1R_F); + sqmag1_F += fPow2Div2(sqmag1I_F); + sqmag1_e = 2 * sqmag1_e + 1; + + FIXP_DBL sqmag2R_F = + hQmfTransposer->qmfInBufReal_F[slotOffset][ti2]; + FIXP_DBL sqmag2I_F = + hQmfTransposer->qmfInBufImag_F[slotOffset][ti2]; + scaleUp(&sqmag2R_F, &sqmag2I_F, &sqmag2_e); + sqmag2_F = fPow2Div2(sqmag2R_F); + sqmag2_F += fPow2Div2(sqmag2I_F); + sqmag2_e = 2 * sqmag2_e + 1; + + int shift1 = fMin(fMax(sqmag1_e, sqmag2_e) - sqmag1_e, 31); + int shift2 = fMin(fMax(sqmag1_e, sqmag2_e) - sqmag2_e, 31); + + temp_F = fMin((sqmag1_F >> shift1), (sqmag2_F >> shift2)); + temp_e = fMax(sqmag1_e, sqmag2_e); + + int shift3 = fMin(fMax(temp_e, mVal_e) - temp_e, 31); + int shift4 = fMin(fMax(temp_e, mVal_e) - mVal_e, 31); + + if ((temp_F >> shift3) > (mVal_F >> shift4)) { + mVal_F = temp_F; + mVal_e = temp_e; /* equals sqmag2_e + shift2 */ + mTr = tr; + ts1 = ti1; + ts2 = ti2; + } + } + } + + int shift1 = fMin(fMax(sqmag0_e, mVal_e) - sqmag0_e, 31); + int shift2 = fMin(fMax(sqmag0_e, mVal_e) - mVal_e, 31); + + if ((mVal_F >> shift2) > (sqmag0_F >> shift1) && ts1 >= 0 && + ts2 < 2 * hQmfTransposer->synthSize) { + INT gammaOut_e[2]; + FIXP_DBL gammaOutReal_m[2], gammaOutImag_m[2]; + FIXP_DBL tmpReal_m = (FIXP_DBL)0, tmpImag_m = (FIXP_DBL)0; + + int Tcenter, Tvec; + + Tcenter = stretch - mTr; /* default phase power parameters */ + Tvec = mTr; + switch (stretch) /* 2 tap block creation design depends on stretch + order */ + { + case 2: + wingain = + FL2FXCONST_DBL(5.f / 12.f); /* sum of taps divided by two */ + + if (hQmfTransposer->bXProducts[0]) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer->qmfInBufReal_F[slotOffset - 1 + k][ts2]; + gammaVecImag_m[k] = + hQmfTransposer->qmfInBufImag_F[slotOffset - 1 + k][ts2]; + } + + gammaCenter_e[0] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaVec_e[0] = gammaVec_e[1] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + } + break; + + case 4: + wingain = + FL2FXCONST_DBL(6.f / 12.f); /* sum of taps divided by two */ + if (hQmfTransposer->bXProducts[2]) { + if (mTr == 1) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer + ->qmfInBufReal_F[slotOffset + 2 * (k - 1)][ts2]; + gammaVecImag_m[k] = + hQmfTransposer + ->qmfInBufImag_F[slotOffset + 2 * (k - 1)][ts2]; + } + } else if (mTr == 2) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer + ->qmfInBufReal_F[slotOffset + (k - 1)][ts2]; + gammaVecImag_m[k] = + hQmfTransposer + ->qmfInBufImag_F[slotOffset + (k - 1)][ts2]; + } + } else /* (mTr == 3) */ + { + sign = 1; + Tcenter = mTr; /* opposite phase power parameters as ts2 is + center */ + Tvec = stretch - mTr; + + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts2]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts2]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer + ->qmfInBufReal_F[slotOffset + 2 * (k - 1)][ts1]; + gammaVecImag_m[k] = + hQmfTransposer + ->qmfInBufImag_F[slotOffset + 2 * (k - 1)][ts1]; + } + } + + gammaCenter_e[0] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaVec_e[0] = gammaVec_e[1] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + } + break; + + case 3: + wingain = FL2FXCONST_DBL(5.6568f / + 12.f); /* sum of taps divided by two */ + + if (hQmfTransposer->bXProducts[1]) { + FIXP_DBL tmpReal_F, tmpImag_F; + if (mTr == 1) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + gammaVecReal_m[1] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts2]; + gammaVecImag_m[1] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts2]; + + addrshift = -2; + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + slotOffset][ts2]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + slotOffset][ts2]; + + gammaVecReal_m[0] = + (fMult(factors[ts2 % 4], tmpReal_F) - + fMult(factors[(ts2 + 3) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] = + (fMult(factors[(ts2 + 3) % 4], tmpReal_F) + + fMult(factors[ts2 % 4], tmpImag_F)) >> + 1; + + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + 1 + slotOffset][ts2]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + 1 + slotOffset][ts2]; + + gammaVecReal_m[0] += + (fMult(factors[ts2 % 4], tmpReal_F) - + fMult(factors[(ts2 + 1) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] += + (fMult(factors[(ts2 + 1) % 4], tmpReal_F) + + fMult(factors[ts2 % 4], tmpImag_F)) >> + 1; + + } else /* (mTr == 2) */ + { + sign = 1; + Tcenter = mTr; /* opposite phase power parameters as ts2 is + center */ + Tvec = stretch - mTr; + + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts2]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts2]; + gammaVecReal_m[1] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaVecImag_m[1] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + addrshift = -2; + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + slotOffset][ts1]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + slotOffset][ts1]; + + gammaVecReal_m[0] = + (fMult(factors[ts1 % 4], tmpReal_F) - + fMult(factors[(ts1 + 3) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] = + (fMult(factors[(ts1 + 3) % 4], tmpReal_F) + + fMult(factors[ts1 % 4], tmpImag_F)) >> + 1; + + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + 1 + slotOffset][ts1]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + 1 + slotOffset][ts1]; + + gammaVecReal_m[0] += + (fMult(factors[ts1 % 4], tmpReal_F) - + fMult(factors[(ts1 + 1) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] += + (fMult(factors[(ts1 + 1) % 4], tmpReal_F) + + fMult(factors[ts1 % 4], tmpImag_F)) >> + 1; + } + + gammaCenter_e[0] = gammaVec_e[1] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaVec_e[0] = + SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor) + + 1; + } + break; + default: + FDK_ASSERT(0); + break; + } /* stretch cases */ + + /* parameter controlled phase modification parts */ + /* maximum *_e == 20 */ + calculateCenterFIXP(gammaCenterReal_m[0], gammaCenterImag_m[0], + &gammaCenterReal_m[0], &gammaCenterImag_m[0], + &gammaCenter_e[0], stretch, Tcenter - 1); + calculateCenterFIXP(gammaVecReal_m[0], gammaVecImag_m[0], + &gammaVecReal_m[0], &gammaVecImag_m[0], + &gammaVec_e[0], stretch, Tvec - 1); + calculateCenterFIXP(gammaVecReal_m[1], gammaVecImag_m[1], + &gammaVecReal_m[1], &gammaVecImag_m[1], + &gammaVec_e[1], stretch, Tvec - 1); + + /* Final multiplication of prepared parts */ + for (k = 0; k < 2; k++) { + gammaOutReal_m[k] = + fMultDiv2(gammaVecReal_m[k], gammaCenterReal_m[0]) - + fMultDiv2(gammaVecImag_m[k], gammaCenterImag_m[0]); + gammaOutImag_m[k] = + fMultDiv2(gammaVecReal_m[k], gammaCenterImag_m[0]) + + fMultDiv2(gammaVecImag_m[k], gammaCenterReal_m[0]); + gammaOut_e[k] = gammaCenter_e[0] + gammaVec_e[k] + 1; + } + + scaleUp(&gammaOutReal_m[0], &gammaOutImag_m[0], &gammaOut_e[0]); + scaleUp(&gammaOutReal_m[1], &gammaOutImag_m[1], &gammaOut_e[1]); + FDK_ASSERT(gammaOut_e[0] >= 0); + FDK_ASSERT(gammaOut_e[0] < 32); + + tmpReal_m = gammaOutReal_m[0]; + tmpImag_m = gammaOutImag_m[0]; + + INT modstretch4 = ((stretch == 4) && (mTr == 2)); + + FIXP_DBL cos_twid = twid_m_new[stretch - 2 - modstretch4][0]; + FIXP_DBL sin_twid = sign * twid_m_new[stretch - 2 - modstretch4][1]; + + gammaOutReal_m[0] = + fMult(tmpReal_m, cos_twid) - + fMult(tmpImag_m, sin_twid); /* sum should be <= 1 because of + sin/cos multiplication */ + gammaOutImag_m[0] = + fMult(tmpImag_m, cos_twid) + + fMult(tmpReal_m, sin_twid); /* sum should be <= 1 because of + sin/cos multiplication */ + + /* wingain */ + for (k = 0; k < 2; k++) { + gammaOutReal_m[k] = (fMult(gammaOutReal_m[k], wingain) << 1); + gammaOutImag_m[k] = (fMult(gammaOutImag_m[k], wingain) << 1); + } + + gammaOutReal_m[1] >>= 1; + gammaOutImag_m[1] >>= 1; + gammaOut_e[0] += 2; + gammaOut_e[1] += 2; + + /* OLA including window scaling by wingain/3 */ + for (k = 0; k < 2; k++) /* need k=1 to correspond to + grainModImag[slotOffset] -> out to + j*2+(slotOffset-offset) */ + { + hQmfTransposer->qmfHBEBufReal_F[(k + slotOffset - 1)][band] += + gammaOutReal_m[k] >> (scale_factor_hbe - gammaOut_e[k]); + hQmfTransposer->qmfHBEBufImag_F[(k + slotOffset - 1)][band] += + gammaOutImag_m[k] >> (scale_factor_hbe - gammaOut_e[k]); + } + } /* mVal > qThrQMF * qThrQMF * sqmag0 && ts1 > 0 && ts2 < 64 */ + } /* p >= pmin */ + } /* for band */ + } /* for stretch */ + + for (i = 0; i < QMF_WIN_LEN - 1; i++) { + FDKmemcpy(hQmfTransposer->qmfInBufReal_F[i], + hQmfTransposer->qmfInBufReal_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + FDKmemcpy(hQmfTransposer->qmfInBufImag_F[i], + hQmfTransposer->qmfInBufImag_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + } + + if (keepStatesSyncedMode != KEEP_STATES_SYNCED_NOOUT) { + if (2 * j >= offset) { + /* copy first two slots of internal buffer to output */ + if (keepStatesSyncedMode == KEEP_STATES_SYNCED_OUTDIFF) { + for (i = 0; i < 2; i++) { + FDKmemcpy(&ppQmfBufferOutReal_F[2 * j - offset + i] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufReal_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemcpy(&ppQmfBufferOutImag_F[2 * j - offset + i] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufImag_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + } else { + for (i = 0; i < 2; i++) { + FDKmemcpy(&ppQmfBufferOutReal_F[2 * j + i + ov_len] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufReal_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemcpy(&ppQmfBufferOutImag_F[2 * j + i + ov_len] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufImag_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + } + } + } + + /* move slots up */ + for (i = 0; i < HBE_MAX_OUT_SLOTS - 2; i++) { + FDKmemcpy( + &hQmfTransposer->qmfHBEBufReal_F[i][hQmfTransposer->xOverQmf[0]], + &hQmfTransposer->qmfHBEBufReal_F[i + 2][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemcpy( + &hQmfTransposer->qmfHBEBufImag_F[i][hQmfTransposer->xOverQmf[0]], + &hQmfTransposer->qmfHBEBufImag_F[i + 2][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + + /* finally set last two slot to zero */ + for (i = 0; i < 2; i++) { + FDKmemset(&hQmfTransposer->qmfHBEBufReal_F[HBE_MAX_OUT_SLOTS - 1 - i] + [hQmfTransposer->xOverQmf[0]], + 0, + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemset(&hQmfTransposer->qmfHBEBufImag_F[HBE_MAX_OUT_SLOTS - 1 - i] + [hQmfTransposer->xOverQmf[0]], + 0, + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + } /* qmfVocoderColsIn */ + + if (keepStatesSyncedMode != KEEP_STATES_SYNCED_NOOUT) { + if (keepStatesSyncedMode == KEEP_STATES_SYNCED_OUTDIFF) { + for (i = 0; i < ov_len + LPC_ORDER; i++) { + for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand; + band++) { + FIXP_DBL tmpR = ppQmfBufferOutReal_F[i][band]; + FIXP_DBL tmpI = ppQmfBufferOutImag_F[i][band]; + + ppQmfBufferOutReal_F[i][band] = + fMult(tmpR, cos_F[band]) - + fMult(tmpI, (-cos_F[64 - band - 1])); /* sum should be <= 1 + because of sin/cos + multiplication */ + ppQmfBufferOutImag_F[i][band] = + fMult(tmpR, (-cos_F[64 - band - 1])) + + fMult(tmpI, cos_F[band]); /* sum should by <= 1 because of sin/cos + multiplication */ + } + } + } else { + for (i = offset; i < hQmfTransposer->noCols; i++) { + for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand; + band++) { + FIXP_DBL tmpR = ppQmfBufferOutReal_F[i + ov_len][band]; + FIXP_DBL tmpI = ppQmfBufferOutImag_F[i + ov_len][band]; + + ppQmfBufferOutReal_F[i + ov_len][band] = + fMult(tmpR, cos_F[band]) - + fMult(tmpI, (-cos_F[64 - band - 1])); /* sum should be <= 1 + because of sin/cos + multiplication */ + ppQmfBufferOutImag_F[i + ov_len][band] = + fMult(tmpR, (-cos_F[64 - band - 1])) + + fMult(tmpI, cos_F[band]); /* sum should by <= 1 because of sin/cos + multiplication */ + } + } + } + } + + *scale_hb = EXP2SCALE(scale_factor_hbe); +} + +int* GetxOverBandQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer) { + if (hQmfTransposer) + return hQmfTransposer->xOverQmf; + else + return NULL; +} + +int Get41SbrQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer) { + if (hQmfTransposer != NULL) + return hQmfTransposer->bSbr41; + else + return 0; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/hbe.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/hbe.h new file mode 100644 index 0000000000000..3556783b1b50b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/hbe.h @@ -0,0 +1,200 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef HBE_H +#define HBE_H + +#include "sbrdecoder.h" + +#ifndef QMF_SYNTH_CHANNELS +#define QMF_SYNTH_CHANNELS (64) +#endif + +#define HBE_QMF_FILTER_STATE_ANA_SIZE (400) +#define HBE_QMF_FILTER_STATE_SYN_SIZE (200) + +#ifndef MAX_NUM_PATCHES_HBE +#define MAX_NUM_PATCHES_HBE (6) +#endif +#define MAX_STRETCH_HBE (4) + +typedef enum { + KEEP_STATES_SYNCED_OFF = 0, /*!< normal QMF transposer behaviour */ + KEEP_STATES_SYNCED_NORMAL = 1, /*!< QMF transposer called for syncing of + states the last 8/14 slots are calculated in + case next frame is HBE */ + KEEP_STATES_SYNCED_OUTDIFF = + 2, /*!< QMF transposer behaviour as in normal case, but the calculated + slots are directly written to overlap area of buffer; only used in + resetSbrDec function */ + KEEP_STATES_SYNCED_NOOUT = + 3 /*!< QMF transposer is called for syncing of states only, not output + is generated at all; only used in resetSbrDec function */ +} KEEP_STATES_SYNCED_MODE; + +struct hbeTransposer { + FIXP_DBL anaQmfStates[HBE_QMF_FILTER_STATE_ANA_SIZE]; + FIXP_QSS synQmfStates[HBE_QMF_FILTER_STATE_SYN_SIZE]; + + int xOverQmf[MAX_NUM_PATCHES_HBE]; + + int maxStretch; + int timeDomainWinLen; + int qmfInBufSize; + int qmfOutBufSize; + int noCols; + int noChannels; + int startBand; + int stopBand; + int bSbr41; + + LONG *inBuf_F; + FIXP_DBL **qmfInBufReal_F; + FIXP_DBL **qmfInBufImag_F; + + FIXP_DBL *qmfBufferCodecTempSlot_F; + + QMF_FILTER_BANK HBEAnalysiscQMF; + QMF_FILTER_BANK HBESynthesisQMF; + + FIXP_DBL const *synthesisQmfPreModCos_F; + FIXP_DBL const *synthesisQmfPreModSin_F; + + FIXP_DBL **qmfHBEBufReal_F; + FIXP_DBL **qmfHBEBufImag_F; + + int bXProducts[MAX_STRETCH_HBE]; + + int kstart; + int synthSize; + + int highband_exp[2]; + int target_exp[2]; +}; + +typedef struct hbeTransposer *HANDLE_HBE_TRANSPOSER; + +SBR_ERROR QmfTransposerCreate(HANDLE_HBE_TRANSPOSER *hQmfTransposer, + const int frameSize, int bDisableCrossProducts, + int bSbr41); + +SBR_ERROR QmfTransposerReInit(HANDLE_HBE_TRANSPOSER hQmfTransposer, + UCHAR *FreqBandTable[2], UCHAR NSfb[2]); + +void QmfTransposerClose(HANDLE_HBE_TRANSPOSER hQmfTransposer); + +void QmfTransposerApply(HANDLE_HBE_TRANSPOSER hQmfTransposer, + FIXP_DBL **qmfBufferCodecReal, + FIXP_DBL **qmfBufferCodecImag, int nColsIn, + FIXP_DBL **ppQmfBufferOutReal_F, + FIXP_DBL **ppQmfBufferOutImag_F, + FIXP_DBL lpcFilterStatesReal[2 + (3 * (4))][(64)], + FIXP_DBL lpcFilterStatesImag[2 + (3 * (4))][(64)], + int pitchInBins, int scale_lb, int scale_hbe, + int *scale_hb, int timeStep, int firstSlotOffsset, + int ov_len, + KEEP_STATES_SYNCED_MODE keepStatesSyncedMode); + +int *GetxOverBandQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer); + +int Get41SbrQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer); +#endif /* HBE_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/huff_dec.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/huff_dec.cpp new file mode 100644 index 0000000000000..90c954159b30f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/huff_dec.cpp @@ -0,0 +1,137 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Huffman Decoder +*/ + +#include "huff_dec.h" + +/***************************************************************************/ +/*! + \brief Decodes one huffman code word + + Reads bits from the bitstream until a valid codeword is found. + The table entries are interpreted either as index to the next entry + or - if negative - as the codeword. + + \return decoded value + + \author + +****************************************************************************/ +int DecodeHuffmanCW(Huffman h, /*!< pointer to huffman codebook table */ + HANDLE_FDK_BITSTREAM hBs) /*!< Handle to Bitbuffer */ +{ + SCHAR index = 0; + int value, bit; + + while (index >= 0) { + bit = FDKreadBits(hBs, 1); + index = h[index][bit]; + } + + value = index + 64; /* Add offset */ + + return value; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/huff_dec.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/huff_dec.h new file mode 100644 index 0000000000000..9aa62b42e7e64 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/huff_dec.h @@ -0,0 +1,117 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Huffman Decoder +*/ +#ifndef HUFF_DEC_H +#define HUFF_DEC_H + +#include "sbrdecoder.h" +#include "FDK_bitstream.h" + +typedef const SCHAR (*Huffman)[2]; + +int DecodeHuffmanCW(Huffman h, HANDLE_FDK_BITSTREAM hBitBuf); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/lpp_tran.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/lpp_tran.cpp new file mode 100644 index 0000000000000..68a25bff087df --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/lpp_tran.cpp @@ -0,0 +1,1488 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Low Power Profile Transposer + This module provides the transposer. The main entry point is lppTransposer(). + The function generates high frequency content by copying data from the low + band (provided by core codec) into the high band. This process is also + referred to as "patching". The function also implements spectral whitening by + means of inverse filtering based on LPC coefficients. + + Together with the QMF filterbank the transposer can be tested using a supplied + test program. See main_audio.cpp for details. This module does use fractional + arithmetic and the accuracy of the computations has an impact on the overall + sound quality. The module also needs to take into account the different + scaling of spectral data. + + \sa lppTransposer(), main_audio.cpp, sbr_scale.h, \ref documentationOverview +*/ + +#ifdef __ANDROID__ +#include "log/log.h" +#endif + +#include "lpp_tran.h" + +#include "sbr_ram.h" +#include "sbr_rom.h" + +#include "genericStds.h" +#include "autocorr2nd.h" + +#include "HFgen_preFlat.h" + +#define LPC_SCALE_FACTOR 2 + +/*! + * + * \brief Get bandwidth expansion factor from filtering level + * + * Returns a filter parameter (bandwidth expansion factor) depending on + * the desired filtering level signalled in the bitstream. + * When switching the filtering level from LOW to OFF, an additional + * level is being inserted to achieve a smooth transition. + */ + +static FIXP_DBL mapInvfMode(INVF_MODE mode, INVF_MODE prevMode, + WHITENING_FACTORS whFactors) { + switch (mode) { + case INVF_LOW_LEVEL: + if (prevMode == INVF_OFF) + return whFactors.transitionLevel; + else + return whFactors.lowLevel; + + case INVF_MID_LEVEL: + return whFactors.midLevel; + + case INVF_HIGH_LEVEL: + return whFactors.highLevel; + + default: + if (prevMode == INVF_LOW_LEVEL) + return whFactors.transitionLevel; + else + return whFactors.off; + } +} + +/*! + * + * \brief Perform inverse filtering level emphasis + * + * Retrieve bandwidth expansion factor and apply smoothing for each filter band + * + */ + +static void inverseFilteringLevelEmphasis( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + UCHAR nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev, /*!< Previous inverse filtering modes */ + FIXP_DBL *bwVector /*!< Resulting filtering levels */ +) { + for (int i = 0; i < nInvfBands; i++) { + FIXP_DBL accu; + FIXP_DBL bwTmp = mapInvfMode(sbr_invf_mode[i], sbr_invf_mode_prev[i], + hLppTrans->pSettings->whFactors); + + if (bwTmp < hLppTrans->bwVectorOld[i]) { + accu = fMultDiv2(FL2FXCONST_DBL(0.75f), bwTmp) + + fMultDiv2(FL2FXCONST_DBL(0.25f), hLppTrans->bwVectorOld[i]); + } else { + accu = fMultDiv2(FL2FXCONST_DBL(0.90625f), bwTmp) + + fMultDiv2(FL2FXCONST_DBL(0.09375f), hLppTrans->bwVectorOld[i]); + } + + if (accu> 1) { + bwVector[i] = FL2FXCONST_DBL(0.0f); + } else { + bwVector[i] = fixMin(accu << 1, FL2FXCONST_DBL(0.99609375f)); + } + } +} + +/* Resulting autocorrelation determinant exponent */ +#define ACDET_EXP \ + (2 * (DFRACT_BITS + sbrScaleFactor->lb_scale + 10 - ac.det_scale)) +#define AC_EXP (-sbrScaleFactor->lb_scale + LPC_SCALE_FACTOR) +#define ALPHA_EXP (-sbrScaleFactor->lb_scale + LPC_SCALE_FACTOR + 1) +/* Resulting transposed QMF values exponent 16 bit normalized samplebits + * assumed. */ +#define QMFOUT_EXP ((SAMPLE_BITS - 15) - sbrScaleFactor->lb_scale) + +static inline void calc_qmfBufferReal(FIXP_DBL **qmfBufferReal, + const FIXP_DBL *const lowBandReal, + const int startSample, + const int stopSample, const UCHAR hiBand, + const int dynamicScale, + const FIXP_SGL a0r, const FIXP_SGL a1r) { + const int dynscale = fixMax(0, dynamicScale - 1) + 1; + const int rescale = -fixMin(0, dynamicScale - 1) + 1; + const int descale = + fixMin(DFRACT_BITS - 1, LPC_SCALE_FACTOR + dynamicScale + rescale); + + for (int i = 0; i < stopSample - startSample; i++) { + FIXP_DBL accu; + + accu = fMultDiv2(a1r, lowBandReal[i]) + fMultDiv2(a0r, lowBandReal[i + 1]); + accu = (lowBandReal[i + 2] >> descale) + (accu >> dynscale); + + qmfBufferReal[i + startSample][hiBand] = + SATURATE_LEFT_SHIFT(accu, rescale, DFRACT_BITS); + } +} + +/*! + * + * \brief Perform transposition by patching of subband samples. + * This function serves as the main entry point into the module. The function + * determines the areas for the patching process (these are the source range as + * well as the target range) and implements spectral whitening by means of + * inverse filtering. The function autoCorrelation2nd() is an auxiliary function + * for calculating the LPC coefficients for the filtering. The actual + * calculation of the LPC coefficients and the implementation of the filtering + * are done as part of lppTransposer(). + * + * Note that the filtering is done on all available QMF subsamples, whereas the + * patching is only done on those QMF subsamples that will be used in the next + * QMF synthesis. The filtering is also implemented before the patching includes + * further dependencies on parameters from the SBR data. + * + */ + +void lppTransposer( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband + samples (source) */ + + FIXP_DBL *degreeAlias, /*!< Vector for results of aliasing estimation */ + FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of + subband samples (source) */ + const int useLP, const int fPreWhitening, const int v_k_master0, + const int timeStep, /*!< Time step of envelope */ + const int firstSlotOffs, /*!< Start position in time */ + const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ + const int nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ +) { + INT bwIndex[MAX_NUM_PATCHES]; + FIXP_DBL bwVector[MAX_NUM_PATCHES]; /*!< pole moving factors */ + FIXP_DBL preWhiteningGains[(64) / 2]; + int preWhiteningGains_exp[(64) / 2]; + + int i; + int loBand, start, stop; + TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; + PATCH_PARAM *patchParam = pSettings->patchParam; + int patch; + + FIXP_SGL alphar[LPC_ORDER], a0r, a1r; + FIXP_SGL alphai[LPC_ORDER], a0i = 0, a1i = 0; + FIXP_SGL bw = FL2FXCONST_SGL(0.0f); + + int autoCorrLength; + + FIXP_DBL k1, k1_below = 0, k1_below2 = 0; + + ACORR_COEFS ac; + int startSample; + int stopSample; + int stopSampleClear; + + int comLowBandScale; + int ovLowBandShift; + int lowBandShift; + /* int ovHighBandShift;*/ + + alphai[0] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + + startSample = firstSlotOffs * timeStep; + stopSample = pSettings->nCols + lastSlotOffs * timeStep; + FDK_ASSERT((lastSlotOffs * timeStep) <= pSettings->overlap); + + inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode, + sbr_invf_mode_prev, bwVector); + + stopSampleClear = stopSample; + + autoCorrLength = pSettings->nCols + pSettings->overlap; + + if (pSettings->noOfPatches > 0) { + /* Set upper subbands to zero: + This is required in case that the patches do not cover the complete + highband (because the last patch would be too short). Possible + optimization: Clearing bands up to usb would be sufficient here. */ + int targetStopBand = + patchParam[pSettings->noOfPatches - 1].targetStartBand + + patchParam[pSettings->noOfPatches - 1].numBandsInPatch; + + int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL); + + if (!useLP) { + for (i = startSample; i < stopSampleClear; i++) { + FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); + FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize); + } + } else { + for (i = startSample; i < stopSampleClear; i++) { + FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); + } + } + } +#ifdef __ANDROID__ + else { + // Safetynet logging + android_errorWriteLog(0x534e4554, "112160868"); + } +#endif + + /* init bwIndex for each patch */ + FDKmemclear(bwIndex, sizeof(bwIndex)); + + /* + Calc common low band scale factor + */ + comLowBandScale = + fixMin(sbrScaleFactor->ov_lb_scale, sbrScaleFactor->lb_scale); + + ovLowBandShift = sbrScaleFactor->ov_lb_scale - comLowBandScale; + lowBandShift = sbrScaleFactor->lb_scale - comLowBandScale; + /* ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/ + + if (fPreWhitening) { + sbrDecoder_calculateGainVec( + qmfBufferReal, qmfBufferImag, + DFRACT_BITS - 1 - 16 - + sbrScaleFactor->ov_lb_scale, /* convert scale to exponent */ + DFRACT_BITS - 1 - 16 - + sbrScaleFactor->lb_scale, /* convert scale to exponent */ + pSettings->overlap, preWhiteningGains, preWhiteningGains_exp, + v_k_master0, startSample, stopSample); + } + + /* outer loop over bands to do analysis only once for each band */ + + if (!useLP) { + start = pSettings->lbStartPatching; + stop = pSettings->lbStopPatching; + } else { + start = fixMax(1, pSettings->lbStartPatching - 2); + stop = patchParam[0].targetStartBand; + } + + for (loBand = start; loBand < stop; loBand++) { + FIXP_DBL lowBandReal[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; + FIXP_DBL *plowBandReal = lowBandReal; + FIXP_DBL **pqmfBufferReal = + qmfBufferReal + firstSlotOffs * timeStep /* + pSettings->overlap */; + FIXP_DBL lowBandImag[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; + FIXP_DBL *plowBandImag = lowBandImag; + FIXP_DBL **pqmfBufferImag = + qmfBufferImag + firstSlotOffs * timeStep /* + pSettings->overlap */; + int resetLPCCoeffs = 0; + int dynamicScale = DFRACT_BITS - 1 - LPC_SCALE_FACTOR; + int acDetScale = 0; /* scaling of autocorrelation determinant */ + + for (i = 0; + i < LPC_ORDER + firstSlotOffs * timeStep /*+pSettings->overlap*/; + i++) { + *plowBandReal++ = hLppTrans->lpcFilterStatesRealLegSBR[i][loBand]; + if (!useLP) + *plowBandImag++ = hLppTrans->lpcFilterStatesImagLegSBR[i][loBand]; + } + + /* + Take old slope length qmf slot source values out of (overlap)qmf buffer + */ + if (!useLP) { + for (i = 0; + i < pSettings->nCols + pSettings->overlap - firstSlotOffs * timeStep; + i++) { + *plowBandReal++ = (*pqmfBufferReal++)[loBand]; + *plowBandImag++ = (*pqmfBufferImag++)[loBand]; + } + } else { + /* pSettings->overlap is always even */ + FDK_ASSERT((pSettings->overlap & 1) == 0); + for (i = 0; i < ((pSettings->nCols + pSettings->overlap - + firstSlotOffs * timeStep) >> + 1); + i++) { + *plowBandReal++ = (*pqmfBufferReal++)[loBand]; + *plowBandReal++ = (*pqmfBufferReal++)[loBand]; + } + if (pSettings->nCols & 1) { + *plowBandReal++ = (*pqmfBufferReal++)[loBand]; + } + } + + /* + Determine dynamic scaling value. + */ + dynamicScale = + fixMin(dynamicScale, + getScalefactor(lowBandReal, LPC_ORDER + pSettings->overlap) + + ovLowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(&lowBandReal[LPC_ORDER + pSettings->overlap], + pSettings->nCols) + + lowBandShift); + if (!useLP) { + dynamicScale = + fixMin(dynamicScale, + getScalefactor(lowBandImag, LPC_ORDER + pSettings->overlap) + + ovLowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(&lowBandImag[LPC_ORDER + pSettings->overlap], + pSettings->nCols) + + lowBandShift); + } + + if (dynamicScale == 0) { + /* In this special case the available headroom bits as well as + ovLowBandShift and lowBandShift are zero. The spectrum is limited to + prevent -1.0, so negative values for dynamicScale can be avoided. */ + for (i = 0; i < (LPC_ORDER + pSettings->overlap + pSettings->nCols); + i++) { + lowBandReal[i] = fixMax(lowBandReal[i], (FIXP_DBL)0x80000001); + } + if (!useLP) { + for (i = 0; i < (LPC_ORDER + pSettings->overlap + pSettings->nCols); + i++) { + lowBandImag[i] = fixMax(lowBandImag[i], (FIXP_DBL)0x80000001); + } + } + } else { + dynamicScale = + fixMax(0, dynamicScale - + 1); /* one additional bit headroom to prevent -1.0 */ + } + + /* + Scale temporal QMF buffer. + */ + scaleValues(&lowBandReal[0], LPC_ORDER + pSettings->overlap, + dynamicScale - ovLowBandShift); + scaleValues(&lowBandReal[LPC_ORDER + pSettings->overlap], pSettings->nCols, + dynamicScale - lowBandShift); + + if (!useLP) { + scaleValues(&lowBandImag[0], LPC_ORDER + pSettings->overlap, + dynamicScale - ovLowBandShift); + scaleValues(&lowBandImag[LPC_ORDER + pSettings->overlap], + pSettings->nCols, dynamicScale - lowBandShift); + } + + if (!useLP) { + acDetScale += autoCorr2nd_cplx(&ac, lowBandReal + LPC_ORDER, + lowBandImag + LPC_ORDER, autoCorrLength); + } else { + acDetScale += + autoCorr2nd_real(&ac, lowBandReal + LPC_ORDER, autoCorrLength); + } + + /* Examine dynamic of determinant in autocorrelation. */ + acDetScale += 2 * (comLowBandScale + dynamicScale); + acDetScale *= 2; /* two times reflection coefficent scaling */ + acDetScale += ac.det_scale; /* ac scaling of determinant */ + + /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */ + if (acDetScale > 126) { + resetLPCCoeffs = 1; + } + + alphar[1] = FL2FXCONST_SGL(0.0f); + if (!useLP) alphai[1] = FL2FXCONST_SGL(0.0f); + + if (ac.det != FL2FXCONST_DBL(0.0f)) { + FIXP_DBL tmp, absTmp, absDet; + + absDet = fixp_abs(ac.det); + + if (!useLP) { + tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) - + ((fMultDiv2(ac.r01i, ac.r12i) + fMultDiv2(ac.r02r, ac.r11r)) >> + (LPC_SCALE_FACTOR - 1)); + } else { + tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) - + (fMultDiv2(ac.r02r, ac.r11r) >> (LPC_SCALE_FACTOR - 1)); + } + absTmp = fixp_abs(tmp); + + /* + Quick check: is first filter coeff >= 1(4) + */ + { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); + scale = scale + ac.det_scale; + + if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) { + resetLPCCoeffs = 1; + } else { + alphar[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale)); + if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { + alphar[1] = -alphar[1]; + } + } + } + + if (!useLP) { + tmp = (fMultDiv2(ac.r01i, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) + + ((fMultDiv2(ac.r01r, ac.r12i) - + (FIXP_DBL)fMultDiv2(ac.r02i, ac.r11r)) >> + (LPC_SCALE_FACTOR - 1)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is second filter coeff >= 1(4) + */ + { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); + scale = scale + ac.det_scale; + + if ((scale > 0) && + (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >> + scale)) { + resetLPCCoeffs = 1; + } else { + alphai[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale)); + if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { + alphai[1] = -alphai[1]; + } + } + } + } + } + + alphar[0] = FL2FXCONST_SGL(0.0f); + if (!useLP) alphai[0] = FL2FXCONST_SGL(0.0f); + + if (ac.r11r != FL2FXCONST_DBL(0.0f)) { + /* ac.r11r is always >=0 */ + FIXP_DBL tmp, absTmp; + + if (!useLP) { + tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) + + (fMultDiv2(alphar[1], ac.r12r) + fMultDiv2(alphai[1], ac.r12i)); + } else { + if (ac.r01r >= FL2FXCONST_DBL(0.0f)) + tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) + + fMultDiv2(alphar[1], ac.r12r); + else + tmp = -((-ac.r01r) >> (LPC_SCALE_FACTOR + 1)) + + fMultDiv2(alphar[1], ac.r12r); + } + + absTmp = fixp_abs(tmp); + + /* + Quick check: is first filter coeff >= 1(4) + */ + + if (absTmp >= (ac.r11r >> 1)) { + resetLPCCoeffs = 1; + } else { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); + alphar[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1)); + + if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) + alphar[0] = -alphar[0]; + } + + if (!useLP) { + tmp = (ac.r01i >> (LPC_SCALE_FACTOR + 1)) + + (fMultDiv2(alphai[1], ac.r12r) - fMultDiv2(alphar[1], ac.r12i)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is second filter coeff >= 1(4) + */ + if (absTmp >= (ac.r11r >> 1)) { + resetLPCCoeffs = 1; + } else { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); + alphai[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1)); + if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) + alphai[0] = -alphai[0]; + } + } + } + + if (!useLP) { + /* Now check the quadratic criteria */ + if ((fMultDiv2(alphar[0], alphar[0]) + fMultDiv2(alphai[0], alphai[0])) >= + FL2FXCONST_DBL(0.5f)) + resetLPCCoeffs = 1; + if ((fMultDiv2(alphar[1], alphar[1]) + fMultDiv2(alphai[1], alphai[1])) >= + FL2FXCONST_DBL(0.5f)) + resetLPCCoeffs = 1; + } + + if (resetLPCCoeffs) { + alphar[0] = FL2FXCONST_SGL(0.0f); + alphar[1] = FL2FXCONST_SGL(0.0f); + if (!useLP) { + alphai[0] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + } + } + + if (useLP) { + /* Aliasing detection */ + if (ac.r11r == FL2FXCONST_DBL(0.0f)) { + k1 = FL2FXCONST_DBL(0.0f); + } else { + if (fixp_abs(ac.r01r) >= fixp_abs(ac.r11r)) { + if (fMultDiv2(ac.r01r, ac.r11r) < FL2FX_DBL(0.0f)) { + k1 = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_SGL(1.0f)*/; + } else { + /* Since this value is squared later, it must not ever become -1.0f. + */ + k1 = (FIXP_DBL)(MINVAL_DBL + 1) /*FL2FXCONST_SGL(-1.0f)*/; + } + } else { + INT scale; + FIXP_DBL result = + fDivNorm(fixp_abs(ac.r01r), fixp_abs(ac.r11r), &scale); + k1 = scaleValueSaturate(result, scale); + + if (!((ac.r01r < FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))) { + k1 = -k1; + } + } + } + if ((loBand > 1) && (loBand < v_k_master0)) { + /* Check if the gain should be locked */ + FIXP_DBL deg = + /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - fPow2(k1_below); + degreeAlias[loBand] = FL2FXCONST_DBL(0.0f); + if (((loBand & 1) == 0) && (k1 < FL2FXCONST_DBL(0.0f))) { + if (k1_below < FL2FXCONST_DBL(0.0f)) { /* 2-Ch Aliasing Detection */ + degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/; + if (k1_below2 > + FL2FXCONST_DBL(0.0f)) { /* 3-Ch Aliasing Detection */ + degreeAlias[loBand - 1] = deg; + } + } else if (k1_below2 > + FL2FXCONST_DBL(0.0f)) { /* 3-Ch Aliasing Detection */ + degreeAlias[loBand] = deg; + } + } + if (((loBand & 1) == 1) && (k1 > FL2FXCONST_DBL(0.0f))) { + if (k1_below > FL2FXCONST_DBL(0.0f)) { /* 2-CH Aliasing Detection */ + degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/; + if (k1_below2 < + FL2FXCONST_DBL(0.0f)) { /* 3-CH Aliasing Detection */ + degreeAlias[loBand - 1] = deg; + } + } else if (k1_below2 < + FL2FXCONST_DBL(0.0f)) { /* 3-CH Aliasing Detection */ + degreeAlias[loBand] = deg; + } + } + } + /* remember k1 values of the 2 QMF channels below the current channel */ + k1_below2 = k1_below; + k1_below = k1; + } + + patch = 0; + + while (patch < pSettings->noOfPatches) { /* inner loop over every patch */ + + int hiBand = loBand + patchParam[patch].targetBandOffs; + + if (loBand < patchParam[patch].sourceStartBand || + loBand >= patchParam[patch].sourceStopBand + //|| hiBand >= hLppTrans->pSettings->noChannels + ) { + /* Lowband not in current patch - proceed */ + patch++; + continue; + } + + FDK_ASSERT(hiBand < (64)); + + /* bwIndex[patch] is already initialized with value from previous band + * inside this patch */ + while (hiBand >= pSettings->bwBorders[bwIndex[patch]] && + bwIndex[patch] < MAX_NUM_PATCHES - 1) { + bwIndex[patch]++; + } + + /* + Filter Step 2: add the left slope with the current filter to the buffer + pure source values are already in there + */ + bw = FX_DBL2FX_SGL(bwVector[bwIndex[patch]]); + + a0r = FX_DBL2FX_SGL( + fMult(bw, alphar[0])); /* Apply current bandwidth expansion factor */ + + if (!useLP) a0i = FX_DBL2FX_SGL(fMult(bw, alphai[0])); + bw = FX_DBL2FX_SGL(fPow2(bw)); + a1r = FX_DBL2FX_SGL(fMult(bw, alphar[1])); + if (!useLP) a1i = FX_DBL2FX_SGL(fMult(bw, alphai[1])); + + /* + Filter Step 3: insert the middle part which won't be windowed + */ + if (bw <= FL2FXCONST_SGL(0.0f)) { + if (!useLP) { + int descale = + fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); + for (i = startSample; i < stopSample; i++) { + FIXP_DBL accu1, accu2; + accu1 = lowBandReal[LPC_ORDER + i] >> descale; + accu2 = lowBandImag[LPC_ORDER + i] >> descale; + if (fPreWhitening) { + accu1 = scaleValueSaturate( + fMultDiv2(accu1, preWhiteningGains[loBand]), + preWhiteningGains_exp[loBand] + 1); + accu2 = scaleValueSaturate( + fMultDiv2(accu2, preWhiteningGains[loBand]), + preWhiteningGains_exp[loBand] + 1); + } + qmfBufferReal[i][hiBand] = accu1; + qmfBufferImag[i][hiBand] = accu2; + } + } else { + int descale = + fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); + for (i = startSample; i < stopSample; i++) { + qmfBufferReal[i][hiBand] = lowBandReal[LPC_ORDER + i] >> descale; + } + } + } else { /* bw <= 0 */ + + if (!useLP) { + const int dynscale = fixMax(0, dynamicScale - 2) + 1; + const int rescale = -fixMin(0, dynamicScale - 2) + 1; + const int descale = fixMin(DFRACT_BITS - 1, + LPC_SCALE_FACTOR + dynamicScale + rescale); + + for (i = startSample; i < stopSample; i++) { + FIXP_DBL accu1, accu2; + + accu1 = ((fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) - + fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1])) >> + 1) + + ((fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) - + fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >> + 1); + accu2 = ((fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) + + fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1])) >> + 1) + + ((fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) + + fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >> + 1); + + accu1 = + (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 >> dynscale); + accu2 = + (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 >> dynscale); + if (fPreWhitening) { + qmfBufferReal[i][hiBand] = scaleValueSaturate( + fMultDiv2(accu1, preWhiteningGains[loBand]), + preWhiteningGains_exp[loBand] + 1 + rescale); + qmfBufferImag[i][hiBand] = scaleValueSaturate( + fMultDiv2(accu2, preWhiteningGains[loBand]), + preWhiteningGains_exp[loBand] + 1 + rescale); + } else { + qmfBufferReal[i][hiBand] = + SATURATE_LEFT_SHIFT(accu1, rescale, DFRACT_BITS); + qmfBufferImag[i][hiBand] = + SATURATE_LEFT_SHIFT(accu2, rescale, DFRACT_BITS); + } + } + } else { + FDK_ASSERT(dynamicScale >= 0); + calc_qmfBufferReal( + qmfBufferReal, &(lowBandReal[LPC_ORDER + startSample - 2]), + startSample, stopSample, hiBand, dynamicScale, a0r, a1r); + } + } /* bw <= 0 */ + + patch++; + + } /* inner loop over patches */ + + /* + * store the unmodified filter coefficients if there is + * an overlapping envelope + *****************************************************************/ + + } /* outer loop over bands (loBand) */ + + if (useLP) { + for (loBand = pSettings->lbStartPatching; + loBand < pSettings->lbStopPatching; loBand++) { + patch = 0; + while (patch < pSettings->noOfPatches) { + UCHAR hiBand = loBand + patchParam[patch].targetBandOffs; + + if (loBand < patchParam[patch].sourceStartBand || + loBand >= patchParam[patch].sourceStopBand || + hiBand >= (64) /* Highband out of range (biterror) */ + ) { + /* Lowband not in current patch or highband out of range (might be + * caused by biterrors)- proceed */ + patch++; + continue; + } + + if (hiBand != patchParam[patch].targetStartBand) + degreeAlias[hiBand] = degreeAlias[loBand]; + + patch++; + } + } /* end for loop */ + } + + for (i = 0; i < nInvfBands; i++) { + hLppTrans->bwVectorOld[i] = bwVector[i]; + } + + /* + set high band scale factor + */ + sbrScaleFactor->hb_scale = comLowBandScale - (LPC_SCALE_FACTOR); +} + +void lppTransposerHBE( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + HANDLE_HBE_TRANSPOSER hQmfTransposer, + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband + samples (source) */ + FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of + subband samples (source) */ + const int timeStep, /*!< Time step of envelope */ + const int firstSlotOffs, /*!< Start position in time */ + const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ + const int nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ +) { + INT bwIndex; + FIXP_DBL bwVector[MAX_NUM_PATCHES_HBE]; /*!< pole moving factors */ + + int i; + int loBand, start, stop; + TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; + PATCH_PARAM *patchParam = pSettings->patchParam; + + FIXP_SGL alphar[LPC_ORDER], a0r, a1r; + FIXP_SGL alphai[LPC_ORDER], a0i = 0, a1i = 0; + FIXP_SGL bw = FL2FXCONST_SGL(0.0f); + + int autoCorrLength; + + ACORR_COEFS ac; + int startSample; + int stopSample; + int stopSampleClear; + + int comBandScale; + int ovLowBandShift; + int lowBandShift; + /* int ovHighBandShift;*/ + + alphai[0] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + + startSample = firstSlotOffs * timeStep; + stopSample = pSettings->nCols + lastSlotOffs * timeStep; + + inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode, + sbr_invf_mode_prev, bwVector); + + stopSampleClear = stopSample; + + autoCorrLength = pSettings->nCols + pSettings->overlap; + + if (pSettings->noOfPatches > 0) { + /* Set upper subbands to zero: + This is required in case that the patches do not cover the complete + highband (because the last patch would be too short). Possible + optimization: Clearing bands up to usb would be sufficient here. */ + int targetStopBand = + patchParam[pSettings->noOfPatches - 1].targetStartBand + + patchParam[pSettings->noOfPatches - 1].numBandsInPatch; + + int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL); + + for (i = startSample; i < stopSampleClear; i++) { + FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); + FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize); + } + } +#ifdef __ANDROID__ + else { + // Safetynet logging + android_errorWriteLog(0x534e4554, "112160868"); + } +#endif + + /* + Calc common low band scale factor + */ + comBandScale = sbrScaleFactor->hb_scale; + + ovLowBandShift = sbrScaleFactor->hb_scale - comBandScale; + lowBandShift = sbrScaleFactor->hb_scale - comBandScale; + /* ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/ + + /* outer loop over bands to do analysis only once for each band */ + + start = hQmfTransposer->startBand; + stop = hQmfTransposer->stopBand; + + for (loBand = start; loBand < stop; loBand++) { + bwIndex = 0; + + FIXP_DBL lowBandReal[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; + FIXP_DBL lowBandImag[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; + + int resetLPCCoeffs = 0; + int dynamicScale = DFRACT_BITS - 1 - LPC_SCALE_FACTOR; + int acDetScale = 0; /* scaling of autocorrelation determinant */ + + for (i = 0; i < LPC_ORDER; i++) { + lowBandReal[i] = hLppTrans->lpcFilterStatesRealHBE[i][loBand]; + lowBandImag[i] = hLppTrans->lpcFilterStatesImagHBE[i][loBand]; + } + + for (; i < LPC_ORDER + firstSlotOffs * timeStep; i++) { + lowBandReal[i] = hLppTrans->lpcFilterStatesRealHBE[i][loBand]; + lowBandImag[i] = hLppTrans->lpcFilterStatesImagHBE[i][loBand]; + } + + /* + Take old slope length qmf slot source values out of (overlap)qmf buffer + */ + for (i = firstSlotOffs * timeStep; + i < pSettings->nCols + pSettings->overlap; i++) { + lowBandReal[i + LPC_ORDER] = qmfBufferReal[i][loBand]; + lowBandImag[i + LPC_ORDER] = qmfBufferImag[i][loBand]; + } + + /* store unmodified values to buffer */ + for (i = 0; i < LPC_ORDER + pSettings->overlap; i++) { + hLppTrans->lpcFilterStatesRealHBE[i][loBand] = + qmfBufferReal[pSettings->nCols - LPC_ORDER + i][loBand]; + hLppTrans->lpcFilterStatesImagHBE[i][loBand] = + qmfBufferImag[pSettings->nCols - LPC_ORDER + i][loBand]; + } + + /* + Determine dynamic scaling value. + */ + dynamicScale = + fixMin(dynamicScale, + getScalefactor(lowBandReal, LPC_ORDER + pSettings->overlap) + + ovLowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(&lowBandReal[LPC_ORDER + pSettings->overlap], + pSettings->nCols) + + lowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(lowBandImag, LPC_ORDER + pSettings->overlap) + + ovLowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(&lowBandImag[LPC_ORDER + pSettings->overlap], + pSettings->nCols) + + lowBandShift); + + dynamicScale = + dynamicScale - 1; /* one additional bit headroom to prevent -1.0 */ + + /* + Scale temporal QMF buffer. + */ + scaleValues(&lowBandReal[0], LPC_ORDER + pSettings->overlap, + dynamicScale - ovLowBandShift); + scaleValues(&lowBandReal[LPC_ORDER + pSettings->overlap], pSettings->nCols, + dynamicScale - lowBandShift); + scaleValues(&lowBandImag[0], LPC_ORDER + pSettings->overlap, + dynamicScale - ovLowBandShift); + scaleValues(&lowBandImag[LPC_ORDER + pSettings->overlap], pSettings->nCols, + dynamicScale - lowBandShift); + + acDetScale += autoCorr2nd_cplx(&ac, lowBandReal + LPC_ORDER, + lowBandImag + LPC_ORDER, autoCorrLength); + + /* Examine dynamic of determinant in autocorrelation. */ + acDetScale += 2 * (comBandScale + dynamicScale); + acDetScale *= 2; /* two times reflection coefficent scaling */ + acDetScale += ac.det_scale; /* ac scaling of determinant */ + + /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */ + if (acDetScale > 126) { + resetLPCCoeffs = 1; + } + + alphar[1] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + + if (ac.det != FL2FXCONST_DBL(0.0f)) { + FIXP_DBL tmp, absTmp, absDet; + + absDet = fixp_abs(ac.det); + + tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) - + ((fMultDiv2(ac.r01i, ac.r12i) + fMultDiv2(ac.r02r, ac.r11r)) >> + (LPC_SCALE_FACTOR - 1)); + absTmp = fixp_abs(tmp); + + /* + Quick check: is first filter coeff >= 1(4) + */ + { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); + scale = scale + ac.det_scale; + + if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) { + resetLPCCoeffs = 1; + } else { + alphar[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale)); + if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { + alphar[1] = -alphar[1]; + } + } + } + + tmp = (fMultDiv2(ac.r01i, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) + + ((fMultDiv2(ac.r01r, ac.r12i) - + (FIXP_DBL)fMultDiv2(ac.r02i, ac.r11r)) >> + (LPC_SCALE_FACTOR - 1)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is second filter coeff >= 1(4) + */ + { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); + scale = scale + ac.det_scale; + + if ((scale > 0) && + (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >> scale)) { + resetLPCCoeffs = 1; + } else { + alphai[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale)); + if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { + alphai[1] = -alphai[1]; + } + } + } + } + + alphar[0] = FL2FXCONST_SGL(0.0f); + alphai[0] = FL2FXCONST_SGL(0.0f); + + if (ac.r11r != FL2FXCONST_DBL(0.0f)) { + /* ac.r11r is always >=0 */ + FIXP_DBL tmp, absTmp; + + tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) + + (fMultDiv2(alphar[1], ac.r12r) + fMultDiv2(alphai[1], ac.r12i)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is first filter coeff >= 1(4) + */ + + if (absTmp >= (ac.r11r >> 1)) { + resetLPCCoeffs = 1; + } else { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); + alphar[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1)); + + if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) + alphar[0] = -alphar[0]; + } + + tmp = (ac.r01i >> (LPC_SCALE_FACTOR + 1)) + + (fMultDiv2(alphai[1], ac.r12r) - fMultDiv2(alphar[1], ac.r12i)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is second filter coeff >= 1(4) + */ + if (absTmp >= (ac.r11r >> 1)) { + resetLPCCoeffs = 1; + } else { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); + alphai[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1)); + if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) { + alphai[0] = -alphai[0]; + } + } + } + + /* Now check the quadratic criteria */ + if ((fMultDiv2(alphar[0], alphar[0]) + fMultDiv2(alphai[0], alphai[0])) >= + FL2FXCONST_DBL(0.5f)) { + resetLPCCoeffs = 1; + } + if ((fMultDiv2(alphar[1], alphar[1]) + fMultDiv2(alphai[1], alphai[1])) >= + FL2FXCONST_DBL(0.5f)) { + resetLPCCoeffs = 1; + } + + if (resetLPCCoeffs) { + alphar[0] = FL2FXCONST_SGL(0.0f); + alphar[1] = FL2FXCONST_SGL(0.0f); + alphai[0] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + } + + while (bwIndex < MAX_NUM_PATCHES - 1 && + loBand >= pSettings->bwBorders[bwIndex]) { + bwIndex++; + } + + /* + Filter Step 2: add the left slope with the current filter to the buffer + pure source values are already in there + */ + bw = FX_DBL2FX_SGL(bwVector[bwIndex]); + + a0r = FX_DBL2FX_SGL( + fMult(bw, alphar[0])); /* Apply current bandwidth expansion factor */ + a0i = FX_DBL2FX_SGL(fMult(bw, alphai[0])); + bw = FX_DBL2FX_SGL(fPow2(bw)); + a1r = FX_DBL2FX_SGL(fMult(bw, alphar[1])); + a1i = FX_DBL2FX_SGL(fMult(bw, alphai[1])); + + /* + Filter Step 3: insert the middle part which won't be windowed + */ + if (bw <= FL2FXCONST_SGL(0.0f)) { + int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); + for (i = startSample; i < stopSample; i++) { + qmfBufferReal[i][loBand] = lowBandReal[LPC_ORDER + i] >> descale; + qmfBufferImag[i][loBand] = lowBandImag[LPC_ORDER + i] >> descale; + } + } else { /* bw <= 0 */ + + int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); + dynamicScale += + 1; /* prevent negativ scale factor due to 'one additional bit + headroom' */ + + for (i = startSample; i < stopSample; i++) { + FIXP_DBL accu1, accu2; + + accu1 = (fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) - + fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1]) + + fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) - + fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >> + dynamicScale; + accu2 = (fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) + + fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1]) + + fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) + + fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >> + dynamicScale; + + qmfBufferReal[i][loBand] = + (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << (1 + 1)); + qmfBufferImag[i][loBand] = + (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << (1 + 1)); + } + } /* bw <= 0 */ + + /* + * store the unmodified filter coefficients if there is + * an overlapping envelope + *****************************************************************/ + + } /* outer loop over bands (loBand) */ + + for (i = 0; i < nInvfBands; i++) { + hLppTrans->bwVectorOld[i] = bwVector[i]; + } + + /* + set high band scale factor + */ + sbrScaleFactor->hb_scale = comBandScale - (LPC_SCALE_FACTOR); +} + +/*! + * + * \brief Initialize one low power transposer instance + * + * + */ +SBR_ERROR +createLppTransposer( + HANDLE_SBR_LPP_TRANS hs, /*!< Handle of low power transposer */ + TRANSPOSER_SETTINGS *pSettings, /*!< Pointer to settings */ + const int highBandStartSb, /*!< ? */ + UCHAR *v_k_master, /*!< Master table */ + const int numMaster, /*!< Valid entries in master table */ + const int usb, /*!< Highband area stop subband */ + const int timeSlots, /*!< Number of time slots */ + const int nCols, /*!< Number of colums (codec qmf bank) */ + UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */ + const int noNoiseBands, /*!< Number of noise bands */ + UINT fs, /*!< Sample Frequency */ + const int chan, /*!< Channel number */ + const int overlap) { + /* FB inverse filtering settings */ + hs->pSettings = pSettings; + + pSettings->nCols = nCols; + pSettings->overlap = overlap; + + switch (timeSlots) { + case 15: + case 16: + break; + + default: + return SBRDEC_UNSUPPORTED_CONFIG; /* Unimplemented */ + } + + if (chan == 0) { + /* Init common data only once */ + hs->pSettings->nCols = nCols; + + return resetLppTransposer(hs, highBandStartSb, v_k_master, numMaster, + noiseBandTable, noNoiseBands, usb, fs); + } + return SBRDEC_OK; +} + +static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster, + UCHAR direction) { + int index; + + if (goalSb <= v_k_master[0]) return v_k_master[0]; + + if (goalSb >= v_k_master[numMaster]) return v_k_master[numMaster]; + + if (direction) { + index = 0; + while (v_k_master[index] < goalSb) { + index++; + } + } else { + index = numMaster; + while (v_k_master[index] > goalSb) { + index--; + } + } + + return v_k_master[index]; +} + +/*! + * + * \brief Reset memory for one lpp transposer instance + * + * \return SBRDEC_OK on success, SBRDEC_UNSUPPORTED_CONFIG on error + */ +SBR_ERROR +resetLppTransposer( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + UCHAR highBandStartSb, /*!< High band area: start subband */ + UCHAR *v_k_master, /*!< Master table */ + UCHAR numMaster, /*!< Valid entries in master table */ + UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */ + UCHAR noNoiseBands, /*!< Number of noise bands */ + UCHAR usb, /*!< High band area: stop subband */ + UINT fs /*!< SBR output sampling frequency */ +) { + TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; + PATCH_PARAM *patchParam = pSettings->patchParam; + + int i, patch; + int targetStopBand; + int sourceStartBand; + int patchDistance; + int numBandsInPatch; + + int lsb = v_k_master[0]; /* Start subband expressed in "non-critical" sampling + terms*/ + int xoverOffset = highBandStartSb - + lsb; /* Calculate distance in QMF bands between k0 and kx */ + int startFreqHz; + + int desiredBorder; + + usb = fixMin(usb, v_k_master[numMaster]); /* Avoid endless loops (compare with + float code). */ + + /* + * Plausibility check + */ + + if (pSettings->nCols == 64) { + if (lsb < 4) { + /* 4:1 SBR Requirement k0 >= 4 missed! */ + return SBRDEC_UNSUPPORTED_CONFIG; + } + } else if (lsb - SHIFT_START_SB < 4) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* + * Initialize the patching parameter + */ + /* ISO/IEC 14496-3 (Figure 4.48): goalSb = round( 2.048e6 / fs ) */ + desiredBorder = (((2048000 * 2) / fs) + 1) >> 1; + + desiredBorder = findClosestEntry(desiredBorder, v_k_master, numMaster, + 1); /* Adapt region to master-table */ + + /* First patch */ + sourceStartBand = SHIFT_START_SB + xoverOffset; + targetStopBand = lsb + xoverOffset; /* upperBand */ + + /* Even (odd) numbered channel must be patched to even (odd) numbered channel + */ + patch = 0; + while (targetStopBand < usb) { + /* Too many patches? + Allow MAX_NUM_PATCHES+1 patches here. + we need to check later again, since patch might be the highest patch + AND contain less than 3 bands => actual number of patches will be reduced + by 1. + */ + if (patch > MAX_NUM_PATCHES) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + patchParam[patch].guardStartBand = targetStopBand; + patchParam[patch].targetStartBand = targetStopBand; + + numBandsInPatch = + desiredBorder - targetStopBand; /* Get the desired range of the patch */ + + if (numBandsInPatch >= lsb - sourceStartBand) { + /* Desired number bands are not available -> patch whole source range */ + patchDistance = + targetStopBand - sourceStartBand; /* Get the targetOffset */ + patchDistance = + patchDistance & ~1; /* Rounding off odd numbers and make all even */ + numBandsInPatch = + lsb - (targetStopBand - + patchDistance); /* Update number of bands to be patched */ + numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch, + v_k_master, numMaster, 0) - + targetStopBand; /* Adapt region to master-table */ + } + + if (pSettings->nCols == 64) { + if (numBandsInPatch == 0 && sourceStartBand == SHIFT_START_SB) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + } + + /* Desired number bands are available -> get the minimal even patching + * distance */ + patchDistance = + numBandsInPatch + targetStopBand - lsb; /* Get minimal distance */ + patchDistance = (patchDistance + 1) & + ~1; /* Rounding up odd numbers and make all even */ + + if (numBandsInPatch > 0) { + patchParam[patch].sourceStartBand = targetStopBand - patchDistance; + patchParam[patch].targetBandOffs = patchDistance; + patchParam[patch].numBandsInPatch = numBandsInPatch; + patchParam[patch].sourceStopBand = + patchParam[patch].sourceStartBand + numBandsInPatch; + + targetStopBand += patchParam[patch].numBandsInPatch; + patch++; + } + + /* All patches but first */ + sourceStartBand = SHIFT_START_SB; + + /* Check if we are close to desiredBorder */ + if (desiredBorder - targetStopBand < 3) /* MPEG doc */ + { + desiredBorder = usb; + } + } + + patch--; + + /* If highest patch contains less than three subband: skip it */ + if ((patch > 0) && (patchParam[patch].numBandsInPatch < 3)) { + patch--; + targetStopBand = + patchParam[patch].targetStartBand + patchParam[patch].numBandsInPatch; + } + + /* now check if we don't have one too many */ + if (patch >= MAX_NUM_PATCHES) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + pSettings->noOfPatches = patch + 1; + + /* Check lowest and highest source subband */ + pSettings->lbStartPatching = targetStopBand; + pSettings->lbStopPatching = 0; + for (patch = 0; patch < pSettings->noOfPatches; patch++) { + pSettings->lbStartPatching = + fixMin(pSettings->lbStartPatching, patchParam[patch].sourceStartBand); + pSettings->lbStopPatching = + fixMax(pSettings->lbStopPatching, patchParam[patch].sourceStopBand); + } + + for (i = 0; i < noNoiseBands; i++) { + pSettings->bwBorders[i] = noiseBandTable[i + 1]; + } + for (; i < MAX_NUM_NOISE_VALUES; i++) { + pSettings->bwBorders[i] = 255; + } + + /* + * Choose whitening factors + */ + + startFreqHz = + ((lsb + xoverOffset) * fs) >> 7; /* Shift does a division by 2*(64) */ + + for (i = 1; i < NUM_WHFACTOR_TABLE_ENTRIES; i++) { + if (startFreqHz < FDK_sbrDecoder_sbr_whFactorsIndex[i]) break; + } + i--; + + pSettings->whFactors.off = FDK_sbrDecoder_sbr_whFactorsTable[i][0]; + pSettings->whFactors.transitionLevel = + FDK_sbrDecoder_sbr_whFactorsTable[i][1]; + pSettings->whFactors.lowLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][2]; + pSettings->whFactors.midLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][3]; + pSettings->whFactors.highLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][4]; + + return SBRDEC_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/lpp_tran.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/lpp_tran.h new file mode 100644 index 0000000000000..21c41011115d1 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/lpp_tran.h @@ -0,0 +1,275 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Low Power Profile Transposer +*/ + +#ifndef LPP_TRAN_H +#define LPP_TRAN_H + +#include "sbrdecoder.h" +#include "hbe.h" +#include "qmf.h" + +/* + Common +*/ +#define QMF_OUT_SCALE 8 + +/* + Frequency scales +*/ + +/* + Env-Adjust +*/ +#define MAX_NOISE_ENVELOPES 2 +#define MAX_NOISE_COEFFS 5 +#define MAX_NUM_NOISE_VALUES (MAX_NOISE_ENVELOPES * MAX_NOISE_COEFFS) +#define MAX_NUM_LIMITERS 12 + +/* Set MAX_ENVELOPES to the largest value of all supported BSFORMATs + by overriding MAX_ENVELOPES in the correct order: */ +#define MAX_ENVELOPES_LEGACY 5 +#define MAX_ENVELOPES_USAC 8 +#define MAX_ENVELOPES MAX_ENVELOPES_USAC + +#define MAX_FREQ_COEFFS_DUAL_RATE 48 +#define MAX_FREQ_COEFFS_QUAD_RATE 56 +#define MAX_FREQ_COEFFS MAX_FREQ_COEFFS_QUAD_RATE + +#define MAX_FREQ_COEFFS_FS44100 35 +#define MAX_FREQ_COEFFS_FS48000 32 + +#define MAX_NUM_ENVELOPE_VALUES (MAX_ENVELOPES * MAX_FREQ_COEFFS) + +#define MAX_GAIN_EXP 34 +/* Maximum gain will be sqrt(0.5 * 2^MAX_GAIN_EXP) + example: 34=99dB */ +#define MAX_GAIN_CONCEAL_EXP 1 +/* Maximum gain will be sqrt(0.5 * 2^MAX_GAIN_CONCEAL_EXP) in concealment case + * (0dB) */ + +/* + LPP Transposer +*/ +#define LPC_ORDER 2 + +#define MAX_INVF_BANDS MAX_NOISE_COEFFS + +#define MAX_NUM_PATCHES 6 +#define SHIFT_START_SB 1 /*!< lowest subband of source range */ + +typedef enum { + INVF_OFF = 0, + INVF_LOW_LEVEL, + INVF_MID_LEVEL, + INVF_HIGH_LEVEL, + INVF_SWITCHED /* not a real choice but used here to control behaviour */ +} INVF_MODE; + +/** parameter set for one single patch */ +typedef struct { + UCHAR sourceStartBand; /*!< first band in lowbands where to take the samples + from */ + UCHAR + sourceStopBand; /*!< first band in lowbands which is not included in the + patch anymore */ + UCHAR guardStartBand; /*!< first band in highbands to be filled with zeros in + order to reduce interferences between patches */ + UCHAR + targetStartBand; /*!< first band in highbands to be filled with whitened + lowband signal */ + UCHAR targetBandOffs; /*!< difference between 'startTargetBand' and + 'startSourceBand' */ + UCHAR numBandsInPatch; /*!< number of consecutive bands in this one patch */ +} PATCH_PARAM; + +/** whitening factors for different levels of whitening + need to be initialized corresponding to crossover frequency */ +typedef struct { + FIXP_DBL off; /*!< bw factor for signal OFF */ + FIXP_DBL transitionLevel; + FIXP_DBL lowLevel; /*!< bw factor for signal LOW_LEVEL */ + FIXP_DBL midLevel; /*!< bw factor for signal MID_LEVEL */ + FIXP_DBL highLevel; /*!< bw factor for signal HIGH_LEVEL */ +} WHITENING_FACTORS; + +/*! The transposer settings are calculated on a header reset and are shared by + * both channels. */ +typedef struct { + UCHAR nCols; /*!< number subsamples of a codec frame */ + UCHAR noOfPatches; /*!< number of patches */ + UCHAR lbStartPatching; /*!< first band of lowbands that will be patched */ + UCHAR lbStopPatching; /*!< first band that won't be patched anymore*/ + UCHAR bwBorders[MAX_NUM_NOISE_VALUES]; /*!< spectral bands with different + inverse filtering levels */ + + PATCH_PARAM + patchParam[MAX_NUM_PATCHES + 1]; /*!< new parameter set for patching */ + WHITENING_FACTORS + whFactors; /*!< the pole moving factors for certain + whitening levels as indicated in the bitstream + depending on the crossover frequency */ + UCHAR overlap; /*!< Overlap size */ +} TRANSPOSER_SETTINGS; + +typedef struct { + TRANSPOSER_SETTINGS *pSettings; /*!< Common settings for both channels */ + FIXP_DBL + bwVectorOld[MAX_NUM_PATCHES]; /*!< pole moving factors of past frame */ + FIXP_DBL lpcFilterStatesRealLegSBR[LPC_ORDER + (3 * (4))][( + 32)]; /*!< pointer array to save filter states */ + + FIXP_DBL lpcFilterStatesImagLegSBR[LPC_ORDER + (3 * (4))][( + 32)]; /*!< pointer array to save filter states */ + + FIXP_DBL lpcFilterStatesRealHBE[LPC_ORDER + (3 * (4))][( + 64)]; /*!< pointer array to save filter states */ + FIXP_DBL lpcFilterStatesImagHBE[LPC_ORDER + (3 * (4))][( + 64)]; /*!< pointer array to save filter states */ +} SBR_LPP_TRANS; + +typedef SBR_LPP_TRANS *HANDLE_SBR_LPP_TRANS; + +void lppTransposer(HANDLE_SBR_LPP_TRANS hLppTrans, + QMF_SCALE_FACTOR *sbrScaleFactor, FIXP_DBL **qmfBufferReal, + + FIXP_DBL *degreeAlias, FIXP_DBL **qmfBufferImag, + const int useLP, const int fPreWhitening, + const int v_k_master0, const int timeStep, + const int firstSlotOffset, const int lastSlotOffset, + const int nInvfBands, INVF_MODE *sbr_invf_mode, + INVF_MODE *sbr_invf_mode_prev); + +void lppTransposerHBE( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + HANDLE_HBE_TRANSPOSER hQmfTransposer, + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband + samples (source) */ + FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of + subband samples (source) */ + const int timeStep, /*!< Time step of envelope */ + const int firstSlotOffs, /*!< Start position in time */ + const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ + const int nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ +); + +SBR_ERROR +createLppTransposer(HANDLE_SBR_LPP_TRANS hLppTrans, + TRANSPOSER_SETTINGS *pSettings, const int highBandStartSb, + UCHAR *v_k_master, const int numMaster, const int usb, + const int timeSlots, const int nCols, UCHAR *noiseBandTable, + const int noNoiseBands, UINT fs, const int chan, + const int overlap); + +SBR_ERROR +resetLppTransposer(HANDLE_SBR_LPP_TRANS hLppTrans, UCHAR highBandStartSb, + UCHAR *v_k_master, UCHAR numMaster, UCHAR *noiseBandTable, + UCHAR noNoiseBands, UCHAR usb, UINT fs); + +#endif /* LPP_TRAN_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psbitdec.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psbitdec.cpp new file mode 100644 index 0000000000000..82bb65b0fa52f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psbitdec.cpp @@ -0,0 +1,594 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "psbitdec.h" + +#include "sbr_rom.h" +#include "huff_dec.h" + +/* PS dec privat functions */ +SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d); + +/***************************************************************************/ +/*! + \brief huffman decoding by codebook table + + \return index of huffman codebook table + +****************************************************************************/ +static SCHAR decode_huff_cw( + Huffman h, /*!< pointer to huffman codebook table */ + HANDLE_FDK_BITSTREAM hBitBuf, /*!< Handle to Bitbuffer */ + int *length) /*!< length of huffman codeword (or NULL) */ +{ + UCHAR bit = 0; + SCHAR index = 0; + UCHAR bitCount = 0; + + while (index >= 0) { + bit = FDKreadBits(hBitBuf, 1); + bitCount++; + index = h[index][bit]; + } + if (length) { + *length = bitCount; + } + return (index + 64); /* Add offset */ +} + +/***************************************************************************/ +/*! + \brief helper function - limiting of value to min/max values + + \return limited value + +****************************************************************************/ + +static SCHAR limitMinMax(SCHAR i, SCHAR min, SCHAR max) { + if (i < min) + return min; + else if (i > max) + return max; + else + return i; +} + +/***************************************************************************/ +/*! + \brief Decodes delta values in-place and updates + data buffers according to quantization classes. + + When delta coded in frequency the first element is deltacode from zero. + aIndex buffer is decoded from delta values to actual values. + + \return none + +****************************************************************************/ +static void deltaDecodeArray( + SCHAR enable, SCHAR *aIndex, /*!< ICC/IID parameters */ + SCHAR *aPrevFrameIndex, /*!< ICC/IID parameters of previous frame */ + SCHAR DtDf, UCHAR nrElements, /*!< as conveyed in bitstream */ + /*!< output array size: nrElements*stride */ + UCHAR stride, /*!< 1=dflt, 2=half freq. resolution */ + SCHAR minIdx, SCHAR maxIdx) { + int i; + + /* Delta decode */ + if (enable == 1) { + if (DtDf == 0) { /* Delta coded in freq */ + aIndex[0] = 0 + aIndex[0]; + aIndex[0] = limitMinMax(aIndex[0], minIdx, maxIdx); + for (i = 1; i < nrElements; i++) { + aIndex[i] = aIndex[i - 1] + aIndex[i]; + aIndex[i] = limitMinMax(aIndex[i], minIdx, maxIdx); + } + } else { /* Delta time */ + for (i = 0; i < nrElements; i++) { + aIndex[i] = aPrevFrameIndex[i * stride] + aIndex[i]; + aIndex[i] = limitMinMax(aIndex[i], minIdx, maxIdx); + } + } + } else { /* No data is sent, set index to zero */ + for (i = 0; i < nrElements; i++) { + aIndex[i] = 0; + } + } + if (stride == 2) { + for (i = nrElements * stride - 1; i > 0; i--) { + aIndex[i] = aIndex[i >> 1]; + } + } +} + +/***************************************************************************/ +/*! + \brief Mapping of ICC/IID parameters to 20 stereo bands + + \return none + +****************************************************************************/ +static void map34IndexTo20(SCHAR *aIndex, /*!< decoded ICC/IID parameters */ + UCHAR noBins) /*!< number of stereo bands */ +{ + aIndex[0] = (2 * aIndex[0] + aIndex[1]) / 3; + aIndex[1] = (aIndex[1] + 2 * aIndex[2]) / 3; + aIndex[2] = (2 * aIndex[3] + aIndex[4]) / 3; + aIndex[3] = (aIndex[4] + 2 * aIndex[5]) / 3; + aIndex[4] = (aIndex[6] + aIndex[7]) / 2; + aIndex[5] = (aIndex[8] + aIndex[9]) / 2; + aIndex[6] = aIndex[10]; + aIndex[7] = aIndex[11]; + aIndex[8] = (aIndex[12] + aIndex[13]) / 2; + aIndex[9] = (aIndex[14] + aIndex[15]) / 2; + aIndex[10] = aIndex[16]; + /* For IPD/OPD it stops here */ + + if (noBins == NO_HI_RES_BINS) { + aIndex[11] = aIndex[17]; + aIndex[12] = aIndex[18]; + aIndex[13] = aIndex[19]; + aIndex[14] = (aIndex[20] + aIndex[21]) / 2; + aIndex[15] = (aIndex[22] + aIndex[23]) / 2; + aIndex[16] = (aIndex[24] + aIndex[25]) / 2; + aIndex[17] = (aIndex[26] + aIndex[27]) / 2; + aIndex[18] = (aIndex[28] + aIndex[29] + aIndex[30] + aIndex[31]) / 4; + aIndex[19] = (aIndex[32] + aIndex[33]) / 2; + } +} + +/***************************************************************************/ +/*! + \brief Decodes delta coded IID, ICC, IPD and OPD indices + + \return PS processing flag. If set to 1 + +****************************************************************************/ +int DecodePs(struct PS_DEC *h_ps_d, /*!< PS handle */ + const UCHAR frameError, /*!< Flag telling that frame had errors */ + PS_DEC_COEFFICIENTS *pScratch) { + MPEG_PS_BS_DATA *pBsData; + UCHAR gr, env; + int bPsHeaderValid, bPsDataAvail; + + /* Assign Scratch */ + h_ps_d->specificTo.mpeg.pCoef = pScratch; + + /* Shortcuts to avoid deferencing and keep the code readable */ + pBsData = &h_ps_d->bsData[h_ps_d->processSlot].mpeg; + bPsHeaderValid = pBsData->bPsHeaderValid; + bPsDataAvail = + (h_ps_d->bPsDataAvail[h_ps_d->processSlot] == ppt_mpeg) ? 1 : 0; + + /*************************************************************************************** + * Decide whether to process or to conceal PS data or not. */ + + if ((h_ps_d->psDecodedPrv && !frameError && !bPsDataAvail) || + (!h_ps_d->psDecodedPrv && + (frameError || !bPsDataAvail || !bPsHeaderValid))) { + /* Don't apply PS processing. + * Declare current PS header and bitstream data invalid. */ + pBsData->bPsHeaderValid = 0; + h_ps_d->bPsDataAvail[h_ps_d->processSlot] = ppt_none; + return (0); + } + + if (frameError || + !bPsHeaderValid) { /* no new PS data available (e.g. frame loss) */ + /* => keep latest data constant (i.e. FIX with noEnv=0) */ + pBsData->noEnv = 0; + } + + /*************************************************************************************** + * Decode bitstream payload or prepare parameter for concealment: + */ + for (env = 0; env < pBsData->noEnv; env++) { + SCHAR *aPrevIidIndex; + SCHAR *aPrevIccIndex; + + UCHAR noIidSteps = pBsData->bFineIidQ ? NO_IID_STEPS_FINE : NO_IID_STEPS; + + if (env == 0) { + aPrevIidIndex = h_ps_d->specificTo.mpeg.aIidPrevFrameIndex; + aPrevIccIndex = h_ps_d->specificTo.mpeg.aIccPrevFrameIndex; + } else { + aPrevIidIndex = pBsData->aaIidIndex[env - 1]; + aPrevIccIndex = pBsData->aaIccIndex[env - 1]; + } + + deltaDecodeArray(pBsData->bEnableIid, pBsData->aaIidIndex[env], + aPrevIidIndex, pBsData->abIidDtFlag[env], + FDK_sbrDecoder_aNoIidBins[pBsData->freqResIid], + (pBsData->freqResIid) ? 1 : 2, -noIidSteps, noIidSteps); + + deltaDecodeArray(pBsData->bEnableIcc, pBsData->aaIccIndex[env], + aPrevIccIndex, pBsData->abIccDtFlag[env], + FDK_sbrDecoder_aNoIccBins[pBsData->freqResIcc], + (pBsData->freqResIcc) ? 1 : 2, 0, NO_ICC_STEPS - 1); + } /* for (env=0; envnoEnv; env++) */ + + /* handling of FIX noEnv=0 */ + if (pBsData->noEnv == 0) { + /* set noEnv=1, keep last parameters or force 0 if not enabled */ + pBsData->noEnv = 1; + + if (pBsData->bEnableIid) { + pBsData->bFineIidQ = h_ps_d->specificTo.mpeg.bPrevFrameFineIidQ; + pBsData->freqResIid = h_ps_d->specificTo.mpeg.prevFreqResIid; + for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { + pBsData->aaIidIndex[pBsData->noEnv - 1][gr] = + h_ps_d->specificTo.mpeg.aIidPrevFrameIndex[gr]; + } + } else { + for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { + pBsData->aaIidIndex[pBsData->noEnv - 1][gr] = 0; + } + } + + if (pBsData->bEnableIcc) { + pBsData->freqResIcc = h_ps_d->specificTo.mpeg.prevFreqResIcc; + for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { + pBsData->aaIccIndex[pBsData->noEnv - 1][gr] = + h_ps_d->specificTo.mpeg.aIccPrevFrameIndex[gr]; + } + } else { + for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { + pBsData->aaIccIndex[pBsData->noEnv - 1][gr] = 0; + } + } + } + + /* Update previous frame Iid quantization */ + h_ps_d->specificTo.mpeg.bPrevFrameFineIidQ = pBsData->bFineIidQ; + + /* Update previous frequency resolution for IID */ + h_ps_d->specificTo.mpeg.prevFreqResIid = pBsData->freqResIid; + + /* Update previous frequency resolution for ICC */ + h_ps_d->specificTo.mpeg.prevFreqResIcc = pBsData->freqResIcc; + + /* Update previous frame index buffers */ + for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { + h_ps_d->specificTo.mpeg.aIidPrevFrameIndex[gr] = + pBsData->aaIidIndex[pBsData->noEnv - 1][gr]; + } + for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { + h_ps_d->specificTo.mpeg.aIccPrevFrameIndex[gr] = + pBsData->aaIccIndex[pBsData->noEnv - 1][gr]; + } + + /* PS data from bitstream (if avail) was decoded now */ + h_ps_d->bPsDataAvail[h_ps_d->processSlot] = ppt_none; + + /* handling of env borders for FIX & VAR */ + if (pBsData->bFrameClass == 0) { + /* FIX_BORDERS NoEnv=0,1,2,4 */ + pBsData->aEnvStartStop[0] = 0; + for (env = 1; env < pBsData->noEnv; env++) { + pBsData->aEnvStartStop[env] = + (env * h_ps_d->noSubSamples) / pBsData->noEnv; + } + pBsData->aEnvStartStop[pBsData->noEnv] = h_ps_d->noSubSamples; + /* 1024 (32 slots) env borders: 0, 8, 16, 24, 32 */ + /* 960 (30 slots) env borders: 0, 7, 15, 22, 30 */ + } else { /* if (h_ps_d->bFrameClass == 0) */ + /* VAR_BORDERS NoEnv=1,2,3,4 */ + pBsData->aEnvStartStop[0] = 0; + + /* handle case aEnvStartStop[noEnv]aEnvStartStop[pBsData->noEnv] < h_ps_d->noSubSamples) { + for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { + pBsData->aaIidIndex[pBsData->noEnv][gr] = + pBsData->aaIidIndex[pBsData->noEnv - 1][gr]; + } + for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { + pBsData->aaIccIndex[pBsData->noEnv][gr] = + pBsData->aaIccIndex[pBsData->noEnv - 1][gr]; + } + pBsData->noEnv++; + pBsData->aEnvStartStop[pBsData->noEnv] = h_ps_d->noSubSamples; + } + + /* enforce strictly monotonic increasing borders */ + for (env = 1; env < pBsData->noEnv; env++) { + UCHAR thr; + thr = (UCHAR)h_ps_d->noSubSamples - (pBsData->noEnv - env); + if (pBsData->aEnvStartStop[env] > thr) { + pBsData->aEnvStartStop[env] = thr; + } else { + thr = pBsData->aEnvStartStop[env - 1] + 1; + if (pBsData->aEnvStartStop[env] < thr) { + pBsData->aEnvStartStop[env] = thr; + } + } + } + } /* if (h_ps_d->bFrameClass == 0) ... else */ + + /* copy data prior to possible 20<->34 in-place mapping */ + for (env = 0; env < pBsData->noEnv; env++) { + UCHAR i; + for (i = 0; i < NO_HI_RES_IID_BINS; i++) { + h_ps_d->specificTo.mpeg.pCoef->aaIidIndexMapped[env][i] = + pBsData->aaIidIndex[env][i]; + } + for (i = 0; i < NO_HI_RES_ICC_BINS; i++) { + h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][i] = + pBsData->aaIccIndex[env][i]; + } + } + + /* MPEG baseline PS */ + /* Baseline version of PS always uses the hybrid filter structure with 20 + * stereo bands. */ + /* If ICC/IID parameters for 34 stereo bands are decoded they have to be + * mapped to 20 */ + /* stereo bands. */ + /* Additionaly the IPD/OPD parameters won't be used. */ + + for (env = 0; env < pBsData->noEnv; env++) { + if (pBsData->freqResIid == 2) + map34IndexTo20(h_ps_d->specificTo.mpeg.pCoef->aaIidIndexMapped[env], + NO_HI_RES_IID_BINS); + if (pBsData->freqResIcc == 2) + map34IndexTo20(h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env], + NO_HI_RES_ICC_BINS); + + /* IPD/OPD is disabled in baseline version and thus was removed here */ + } + + return (1); +} + +/***************************************************************************/ +/*! + + \brief Reads parametric stereo data from bitstream + + \return + +****************************************************************************/ +unsigned int ReadPsData( + HANDLE_PS_DEC h_ps_d, /*!< handle to struct PS_DEC */ + HANDLE_FDK_BITSTREAM hBitBuf, /*!< handle to struct BIT_BUF */ + int nBitsLeft /*!< max number of bits available */ +) { + MPEG_PS_BS_DATA *pBsData; + + UCHAR gr, env; + SCHAR dtFlag; + INT startbits; + Huffman CurrentTable; + SCHAR bEnableHeader; + + if (!h_ps_d) return 0; + + pBsData = &h_ps_d->bsData[h_ps_d->bsReadSlot].mpeg; + + if (h_ps_d->bsReadSlot != h_ps_d->bsLastSlot) { + /* Copy last header data */ + FDKmemcpy(pBsData, &h_ps_d->bsData[h_ps_d->bsLastSlot].mpeg, + sizeof(MPEG_PS_BS_DATA)); + } + + startbits = (INT)FDKgetValidBits(hBitBuf); + + bEnableHeader = (SCHAR)FDKreadBits(hBitBuf, 1); + + /* Read header */ + if (bEnableHeader) { + pBsData->bPsHeaderValid = 1; + pBsData->bEnableIid = (UCHAR)FDKreadBits(hBitBuf, 1); + if (pBsData->bEnableIid) { + pBsData->modeIid = (UCHAR)FDKreadBits(hBitBuf, 3); + } + + pBsData->bEnableIcc = (UCHAR)FDKreadBits(hBitBuf, 1); + if (pBsData->bEnableIcc) { + pBsData->modeIcc = (UCHAR)FDKreadBits(hBitBuf, 3); + } + + pBsData->bEnableExt = (UCHAR)FDKreadBits(hBitBuf, 1); + } + + pBsData->bFrameClass = (UCHAR)FDKreadBits(hBitBuf, 1); + if (pBsData->bFrameClass == 0) { + /* FIX_BORDERS NoEnv=0,1,2,4 */ + pBsData->noEnv = + FDK_sbrDecoder_aFixNoEnvDecode[(UCHAR)FDKreadBits(hBitBuf, 2)]; + /* all additional handling of env borders is now in DecodePs() */ + } else { + /* VAR_BORDERS NoEnv=1,2,3,4 */ + pBsData->noEnv = 1 + (UCHAR)FDKreadBits(hBitBuf, 2); + for (env = 1; env < pBsData->noEnv + 1; env++) + pBsData->aEnvStartStop[env] = ((UCHAR)FDKreadBits(hBitBuf, 5)) + 1; + /* all additional handling of env borders is now in DecodePs() */ + } + + /* verify that IID & ICC modes (quant grid, freq res) are supported */ + if ((pBsData->modeIid > 5) || (pBsData->modeIcc > 5)) { + /* no useful PS data could be read from bitstream */ + h_ps_d->bPsDataAvail[h_ps_d->bsReadSlot] = ppt_none; + /* discard all remaining bits */ + nBitsLeft -= startbits - (INT)FDKgetValidBits(hBitBuf); + while (nBitsLeft > 0) { + int i = nBitsLeft; + if (i > 8) { + i = 8; + } + FDKreadBits(hBitBuf, i); + nBitsLeft -= i; + } + return (UINT)(startbits - (INT)FDKgetValidBits(hBitBuf)); + } + + if (pBsData->modeIid > 2) { + pBsData->freqResIid = pBsData->modeIid - 3; + pBsData->bFineIidQ = 1; + } else { + pBsData->freqResIid = pBsData->modeIid; + pBsData->bFineIidQ = 0; + } + + if (pBsData->modeIcc > 2) { + pBsData->freqResIcc = pBsData->modeIcc - 3; + } else { + pBsData->freqResIcc = pBsData->modeIcc; + } + + /* Extract IID data */ + if (pBsData->bEnableIid) { + for (env = 0; env < pBsData->noEnv; env++) { + dtFlag = (SCHAR)FDKreadBits(hBitBuf, 1); + if (!dtFlag) { + if (pBsData->bFineIidQ) + CurrentTable = (Huffman)&aBookPsIidFineFreqDecode; + else + CurrentTable = (Huffman)&aBookPsIidFreqDecode; + } else { + if (pBsData->bFineIidQ) + CurrentTable = (Huffman)&aBookPsIidFineTimeDecode; + else + CurrentTable = (Huffman)&aBookPsIidTimeDecode; + } + + for (gr = 0; gr < FDK_sbrDecoder_aNoIidBins[pBsData->freqResIid]; gr++) + pBsData->aaIidIndex[env][gr] = + decode_huff_cw(CurrentTable, hBitBuf, NULL); + pBsData->abIidDtFlag[env] = dtFlag; + } + } + + /* Extract ICC data */ + if (pBsData->bEnableIcc) { + for (env = 0; env < pBsData->noEnv; env++) { + dtFlag = (SCHAR)FDKreadBits(hBitBuf, 1); + if (!dtFlag) + CurrentTable = (Huffman)&aBookPsIccFreqDecode; + else + CurrentTable = (Huffman)&aBookPsIccTimeDecode; + + for (gr = 0; gr < FDK_sbrDecoder_aNoIccBins[pBsData->freqResIcc]; gr++) + pBsData->aaIccIndex[env][gr] = + decode_huff_cw(CurrentTable, hBitBuf, NULL); + pBsData->abIccDtFlag[env] = dtFlag; + } + } + + if (pBsData->bEnableExt) { + /*! + Decoders that support only the baseline version of the PS tool are allowed + to ignore the IPD/OPD data, but according header data has to be parsed. + ISO/IEC 14496-3 Subpart 8 Annex 4 + */ + + int cnt = FDKreadBits(hBitBuf, PS_EXTENSION_SIZE_BITS); + if (cnt == (1 << PS_EXTENSION_SIZE_BITS) - 1) { + cnt += FDKreadBits(hBitBuf, PS_EXTENSION_ESC_COUNT_BITS); + } + while (cnt--) FDKreadBits(hBitBuf, 8); + } + + /* new PS data was read from bitstream */ + h_ps_d->bPsDataAvail[h_ps_d->bsReadSlot] = ppt_mpeg; + + return (startbits - (INT)FDKgetValidBits(hBitBuf)); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psbitdec.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psbitdec.h new file mode 100644 index 0000000000000..f0fc43ab95208 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psbitdec.h @@ -0,0 +1,116 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef PSBITDEC_H +#define PSBITDEC_H + +#include "sbrdecoder.h" + +#include "psdec.h" + +unsigned int ReadPsData(struct PS_DEC *h_ps_d, HANDLE_FDK_BITSTREAM hBs, + int nBitsLeft); + +int DecodePs(struct PS_DEC *h_ps_d, const UCHAR frameError, + PS_DEC_COEFFICIENTS *pCoef); + +#endif /* PSBITDEC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec.cpp new file mode 100644 index 0000000000000..13a21bfbfccbe --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec.cpp @@ -0,0 +1,714 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief parametric stereo decoder +*/ + +#include "psdec.h" + +#include "FDK_bitbuffer.h" + +#include "sbr_rom.h" +#include "sbr_ram.h" + +#include "FDK_tools_rom.h" + +#include "genericStds.h" + +#include "FDK_trigFcts.h" + +/********************************************************************/ +/* MLQUAL DEFINES */ +/********************************************************************/ + +#define FRACT_ZERO FRACT_BITS - 1 +/********************************************************************/ + +SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d); + +/***** HELPERS *****/ + +/***************************************************************************/ +/*! + \brief Creates one instance of the PS_DEC struct + + \return Error info + +****************************************************************************/ +int CreatePsDec(HANDLE_PS_DEC *h_PS_DEC, /*!< pointer to the module state */ + int aacSamplesPerFrame) { + SBR_ERROR errorInfo = SBRDEC_OK; + HANDLE_PS_DEC h_ps_d; + int i; + + if (*h_PS_DEC == NULL) { + /* Get ps dec ram */ + h_ps_d = GetRam_ps_dec(); + if (h_ps_d == NULL) { + goto bail; + } + } else { + /* Reset an open instance */ + h_ps_d = *h_PS_DEC; + } + + /* + * Create Analysis Hybrid filterbank. + */ + FDKhybridAnalysisOpen(&h_ps_d->specificTo.mpeg.hybridAnalysis, + h_ps_d->specificTo.mpeg.pHybridAnaStatesLFdmx, + sizeof(h_ps_d->specificTo.mpeg.pHybridAnaStatesLFdmx), + NULL, 0); + + /* initialisation */ + switch (aacSamplesPerFrame) { + case 960: + h_ps_d->noSubSamples = 30; /* col */ + break; + case 1024: + h_ps_d->noSubSamples = 32; /* col */ + break; + default: + h_ps_d->noSubSamples = -1; + break; + } + + if (h_ps_d->noSubSamples > MAX_NUM_COL || h_ps_d->noSubSamples <= 0) { + goto bail; + } + h_ps_d->noChannels = NO_QMF_CHANNELS; /* row */ + + h_ps_d->psDecodedPrv = 0; + h_ps_d->procFrameBased = -1; + for (i = 0; i < (1) + 1; i++) { + h_ps_d->bPsDataAvail[i] = ppt_none; + } + { + int error; + error = FDKdecorrelateOpen(&(h_ps_d->specificTo.mpeg.apDecor), + h_ps_d->specificTo.mpeg.decorrBufferCplx, + (2 * ((825) + (373)))); + if (error) goto bail; + } + + for (i = 0; i < (1) + 1; i++) { + FDKmemclear(&h_ps_d->bsData[i].mpeg, sizeof(MPEG_PS_BS_DATA)); + } + + errorInfo = ResetPsDec(h_ps_d); + + if (errorInfo != SBRDEC_OK) goto bail; + + *h_PS_DEC = h_ps_d; + + return 0; + +bail: + if (h_ps_d != NULL) { + DeletePsDec(&h_ps_d); + } + + return -1; +} /*END CreatePsDec */ + +/***************************************************************************/ +/*! + \brief Delete one instance of the PS_DEC struct + + \return Error info + +****************************************************************************/ +int DeletePsDec(HANDLE_PS_DEC *h_PS_DEC) /*!< pointer to the module state */ +{ + if (*h_PS_DEC == NULL) { + return -1; + } + + { + HANDLE_PS_DEC h_ps_d = *h_PS_DEC; + FDKdecorrelateClose(&(h_ps_d->specificTo.mpeg.apDecor)); + } + + FreeRam_ps_dec(h_PS_DEC); + + return 0; +} /*END DeletePsDec */ + +/***************************************************************************/ +/*! + \brief resets some values of the PS handle to default states + + \return + +****************************************************************************/ +SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d) /*!< pointer to the module state */ +{ + SBR_ERROR errorInfo = SBRDEC_OK; + INT i; + + /* explicitly init state variables to safe values (until first ps header + * arrives) */ + + h_ps_d->specificTo.mpeg.lastUsb = 0; + + /* + * Initialize Analysis Hybrid filterbank. + */ + FDKhybridAnalysisInit(&h_ps_d->specificTo.mpeg.hybridAnalysis, THREE_TO_TEN, + NO_QMF_BANDS_HYBRID20, NO_QMF_BANDS_HYBRID20, 1); + + /* + * Initialize Synthesis Hybrid filterbank. + */ + for (i = 0; i < 2; i++) { + FDKhybridSynthesisInit(&h_ps_d->specificTo.mpeg.hybridSynthesis[i], + THREE_TO_TEN, NO_QMF_CHANNELS, NO_QMF_CHANNELS); + } + { + INT error; + error = FDKdecorrelateInit(&h_ps_d->specificTo.mpeg.apDecor, 71, DECORR_PS, + DUCKER_AUTOMATIC, 0, 0, 0, 0, 1, /* isLegacyPS */ + 1); + if (error) return SBRDEC_NOT_INITIALIZED; + } + + for (i = 0; i < NO_IID_GROUPS; i++) { + h_ps_d->specificTo.mpeg.h11rPrev[i] = FL2FXCONST_DBL(0.5f); + h_ps_d->specificTo.mpeg.h12rPrev[i] = FL2FXCONST_DBL(0.5f); + } + + FDKmemclear(h_ps_d->specificTo.mpeg.h21rPrev, + sizeof(h_ps_d->specificTo.mpeg.h21rPrev)); + FDKmemclear(h_ps_d->specificTo.mpeg.h22rPrev, + sizeof(h_ps_d->specificTo.mpeg.h22rPrev)); + + return errorInfo; +} + +/***************************************************************************/ +/*! + \brief Feed delaylines when parametric stereo is switched on. + \return +****************************************************************************/ +void PreparePsProcessing(HANDLE_PS_DEC h_ps_d, + const FIXP_DBL *const *const rIntBufferLeft, + const FIXP_DBL *const *const iIntBufferLeft, + const int scaleFactorLowBand) { + if (h_ps_d->procFrameBased == + 1) /* If we have switched from frame to slot based processing */ + { /* fill hybrid delay buffer. */ + int i, j; + + for (i = 0; i < HYBRID_FILTER_DELAY; i++) { + FIXP_DBL qmfInputData[2][NO_QMF_BANDS_HYBRID20]; + FIXP_DBL hybridOutputData[2][NO_SUB_QMF_CHANNELS]; + + for (j = 0; j < NO_QMF_BANDS_HYBRID20; j++) { + qmfInputData[0][j] = + scaleValue(rIntBufferLeft[i][j], scaleFactorLowBand); + qmfInputData[1][j] = + scaleValue(iIntBufferLeft[i][j], scaleFactorLowBand); + } + + FDKhybridAnalysisApply(&h_ps_d->specificTo.mpeg.hybridAnalysis, + qmfInputData[0], qmfInputData[1], + hybridOutputData[0], hybridOutputData[1]); + } + h_ps_d->procFrameBased = 0; /* switch to slot based processing. */ + + } /* procFrameBased==1 */ +} + +void initSlotBasedRotation( + HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ + int env, int usb) { + INT group = 0; + INT bin = 0; + INT noIidSteps; + + FIXP_SGL invL; + FIXP_DBL ScaleL, ScaleR; + FIXP_DBL Alpha, Beta; + FIXP_DBL h11r, h12r, h21r, h22r; + + const FIXP_DBL *PScaleFactors; + + if (h_ps_d->bsData[h_ps_d->processSlot].mpeg.bFineIidQ) { + PScaleFactors = ScaleFactorsFine; /* values are shiftet right by one */ + noIidSteps = NO_IID_STEPS_FINE; + } else { + PScaleFactors = ScaleFactors; /* values are shiftet right by one */ + noIidSteps = NO_IID_STEPS; + } + + /* dequantize and decode */ + for (group = 0; group < NO_IID_GROUPS; group++) { + bin = bins2groupMap20[group]; + + /*! +

type 'A' rotation

+ mixing procedure R_a, used in baseline version
+ + Scale-factor vectors c1 and c2 are precalculated in initPsTables () and + stored in scaleFactors[] and scaleFactorsFine[] = pScaleFactors []. From the + linearized IID parameters (intensity differences), two scale factors are + calculated. They are used to obtain the coefficients h11... h22. + */ + + /* ScaleR and ScaleL are scaled by 1 shift right */ + + ScaleR = PScaleFactors[noIidSteps + h_ps_d->specificTo.mpeg.pCoef + ->aaIidIndexMapped[env][bin]]; + ScaleL = PScaleFactors[noIidSteps - h_ps_d->specificTo.mpeg.pCoef + ->aaIidIndexMapped[env][bin]]; + + Beta = fMult( + fMult(Alphas[h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][bin]], + (ScaleR - ScaleL)), + FIXP_SQRT05); + Alpha = + Alphas[h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][bin]] >> 1; + + /* Alpha and Beta are now both scaled by 2 shifts right */ + + /* calculate the coefficients h11... h22 from scale-factors and ICC + * parameters */ + + /* h values are scaled by 1 shift right */ + { + FIXP_DBL trigData[4]; + + inline_fixp_cos_sin(Beta + Alpha, Beta - Alpha, 2, trigData); + h11r = fMult(ScaleL, trigData[0]); + h12r = fMult(ScaleR, trigData[2]); + h21r = fMult(ScaleL, trigData[1]); + h22r = fMult(ScaleR, trigData[3]); + } + /*****************************************************************************************/ + /* Interpolation of the matrices H11... H22: */ + /* */ + /* H11(k,n) = H11(k,n[e]) + (n-n[e]) * (H11(k,n[e+1] - H11(k,n[e])) / + * (n[e+1] - n[e]) */ + /* ... */ + /*****************************************************************************************/ + + /* invL = 1/(length of envelope) */ + invL = FX_DBL2FX_SGL(GetInvInt( + h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env + 1] - + h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env])); + + h_ps_d->specificTo.mpeg.pCoef->H11r[group] = + h_ps_d->specificTo.mpeg.h11rPrev[group]; + h_ps_d->specificTo.mpeg.pCoef->H12r[group] = + h_ps_d->specificTo.mpeg.h12rPrev[group]; + h_ps_d->specificTo.mpeg.pCoef->H21r[group] = + h_ps_d->specificTo.mpeg.h21rPrev[group]; + h_ps_d->specificTo.mpeg.pCoef->H22r[group] = + h_ps_d->specificTo.mpeg.h22rPrev[group]; + + h_ps_d->specificTo.mpeg.pCoef->DeltaH11r[group] = + fMult(h11r - h_ps_d->specificTo.mpeg.pCoef->H11r[group], invL); + h_ps_d->specificTo.mpeg.pCoef->DeltaH12r[group] = + fMult(h12r - h_ps_d->specificTo.mpeg.pCoef->H12r[group], invL); + h_ps_d->specificTo.mpeg.pCoef->DeltaH21r[group] = + fMult(h21r - h_ps_d->specificTo.mpeg.pCoef->H21r[group], invL); + h_ps_d->specificTo.mpeg.pCoef->DeltaH22r[group] = + fMult(h22r - h_ps_d->specificTo.mpeg.pCoef->H22r[group], invL); + + /* update prev coefficients for interpolation in next envelope */ + + h_ps_d->specificTo.mpeg.h11rPrev[group] = h11r; + h_ps_d->specificTo.mpeg.h12rPrev[group] = h12r; + h_ps_d->specificTo.mpeg.h21rPrev[group] = h21r; + h_ps_d->specificTo.mpeg.h22rPrev[group] = h22r; + + } /* group loop */ +} + +static const UCHAR groupTable[NO_IID_GROUPS + 1] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71}; + +static void applySlotBasedRotation( + HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ + + FIXP_DBL *mHybridRealLeft, /*!< hybrid values real left */ + FIXP_DBL *mHybridImagLeft, /*!< hybrid values imag left */ + + FIXP_DBL *mHybridRealRight, /*!< hybrid values real right */ + FIXP_DBL *mHybridImagRight /*!< hybrid values imag right */ +) { + INT group; + INT subband; + + /**********************************************************************************************/ + /*! +

Mapping

+ + The number of stereo bands that is actually used depends on the number of + availble parameters for IID and ICC:
 nr. of IID para.| nr. of ICC para.
+  | nr. of Stereo bands
+   ----------------|------------------|-------------------
+     10,20         |     10,20        |        20
+     10,20         |     34           |        34
+     34            |     10,20        |        34
+     34            |     34           |        34
+  
+ In the case the number of parameters for IIS and ICC differs from the number + of stereo bands, a mapping from the lower number to the higher number of + parameters is applied. Index mapping of IID and ICC parameters is already done + in psbitdec.cpp. Further mapping is not needed here in baseline version. + **********************************************************************************************/ + + /************************************************************************************************/ + /*! +

Mixing

+ + To generate the QMF subband signals for the subband samples n = n[e]+1 ,,, + n_[e+1] the parameters at position n[e] and n[e+1] are required as well as the + subband domain signals s_k(n) and d_k(n) for n = n[e]+1... n_[e+1]. n[e] + represents the start position for envelope e. The border positions n[e] are + handled in DecodePS(). + + The stereo sub subband signals are constructed as: +
+  l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n)
+  r_k(n) = H21(k,n) s_k(n) + H22(k,n) d_k(n)
+  
+ In order to obtain the matrices H11(k,n)... H22 (k,n), the vectors h11(b)... + h22(b) need to be calculated first (b: parameter index). Depending on ICC mode + either mixing procedure R_a or R_b is used for that. For both procedures, the + parameters for parameter position n[e+1] is used. + ************************************************************************************************/ + + /************************************************************************************************/ + /*! +

Phase parameters

+ With disabled phase parameters (which is the case in baseline version), the + H-matrices are just calculated by: + +
+  H11(k,n[e+1] = h11(b(k))
+  (...)
+  b(k): parameter index according to mapping table
+  
+ +

Processing of the samples in the sub subbands

+ this loop includes the interpolation of the coefficients Hxx + ************************************************************************************************/ + + /******************************************************/ + /* construct stereo sub subband signals according to: */ + /* */ + /* l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n) */ + /* r_k(n) = H12(k,n) s_k(n) + H22(k,n) d_k(n) */ + /******************************************************/ + PS_DEC_COEFFICIENTS *pCoef = h_ps_d->specificTo.mpeg.pCoef; + + for (group = 0; group < NO_IID_GROUPS; group++) { + pCoef->H11r[group] += pCoef->DeltaH11r[group]; + pCoef->H12r[group] += pCoef->DeltaH12r[group]; + pCoef->H21r[group] += pCoef->DeltaH21r[group]; + pCoef->H22r[group] += pCoef->DeltaH22r[group]; + + const int start = groupTable[group]; + const int stop = groupTable[group + 1]; + for (subband = start; subband < stop; subband++) { + FIXP_DBL tmpLeft = + fMultAdd(fMultDiv2(pCoef->H11r[group], mHybridRealLeft[subband]), + pCoef->H21r[group], mHybridRealRight[subband]); + FIXP_DBL tmpRight = + fMultAdd(fMultDiv2(pCoef->H12r[group], mHybridRealLeft[subband]), + pCoef->H22r[group], mHybridRealRight[subband]); + mHybridRealLeft[subband] = tmpLeft; + mHybridRealRight[subband] = tmpRight; + + tmpLeft = + fMultAdd(fMultDiv2(pCoef->H11r[group], mHybridImagLeft[subband]), + pCoef->H21r[group], mHybridImagRight[subband]); + tmpRight = + fMultAdd(fMultDiv2(pCoef->H12r[group], mHybridImagLeft[subband]), + pCoef->H22r[group], mHybridImagRight[subband]); + mHybridImagLeft[subband] = tmpLeft; + mHybridImagRight[subband] = tmpRight; + } /* subband */ + } +} + +/***************************************************************************/ +/*! + \brief Applies IID, ICC, IPD and OPD parameters to the current frame. + + \return none + +****************************************************************************/ +void ApplyPsSlot( + HANDLE_PS_DEC h_ps_d, /*!< handle PS_DEC*/ + FIXP_DBL **rIntBufferLeft, /*!< real bands left qmf channel (38x64) */ + FIXP_DBL **iIntBufferLeft, /*!< imag bands left qmf channel (38x64) */ + FIXP_DBL *rIntBufferRight, /*!< real bands right qmf channel (38x64) */ + FIXP_DBL *iIntBufferRight, /*!< imag bands right qmf channel (38x64) */ + const int scaleFactorLowBand_no_ov, const int scaleFactorLowBand, + const int scaleFactorHighBand, const int lsb, const int usb) { +/*! +The 64-band QMF representation of the monaural signal generated by the SBR tool +is used as input of the PS tool. After the PS processing, the outputs of the +left and right hybrid synthesis filterbanks are used to generate the stereo +output signal. + +
+
+           -------------            ----------            -------------
+          | Hybrid      | M_n[k,m] |          | L_n[k,m] | Hybrid      | l[n]
+ m[n] --->| analysis    |--------->|          |--------->| synthesis   |----->
+           -------------           | Stereo   |           -------------
+                 |                 | recon-   |
+                 |                 | stuction |
+                \|/                |          |
+           -------------           |          |
+          | De-         | D_n[k,m] |          |
+          | correlation |--------->|          |
+           -------------           |          |           -------------
+                                   |          | R_n[k,m] | Hybrid      | r[n]
+                                   |          |--------->| synthesis   |----->
+ IID, ICC ------------------------>|          |          | filter bank |
+(IPD, OPD)                          ----------            -------------
+
+m[n]:      QMF represantation of the mono input
+M_n[k,m]:  (sub-)sub-band domain signals of the mono input
+D_n[k,m]:  decorrelated (sub-)sub-band domain signals
+L_n[k,m]:  (sub-)sub-band domain signals of the left output
+R_n[k,m]:  (sub-)sub-band domain signals of the right output
+l[n],r[n]: left/right output signals
+
+
+*/ +#define NO_HYBRID_DATA_BANDS (71) + + int i; + FIXP_DBL qmfInputData[2][NO_QMF_BANDS_HYBRID20]; + FIXP_DBL *hybridData[2][2]; + C_ALLOC_SCRATCH_START(pHybridData, FIXP_DBL, 4 * NO_HYBRID_DATA_BANDS); + + hybridData[0][0] = + pHybridData + 0 * NO_HYBRID_DATA_BANDS; /* left real hybrid data */ + hybridData[0][1] = + pHybridData + 1 * NO_HYBRID_DATA_BANDS; /* left imag hybrid data */ + hybridData[1][0] = + pHybridData + 2 * NO_HYBRID_DATA_BANDS; /* right real hybrid data */ + hybridData[1][1] = + pHybridData + 3 * NO_HYBRID_DATA_BANDS; /* right imag hybrid data */ + + /*! + Hybrid analysis filterbank: + The lower 3 (5) of the 64 QMF subbands are further split to provide better + frequency resolution. for PS processing. For the 10 and 20 stereo bands + configuration, the QMF band H_0(w) is split up into 8 (sub-) sub-bands and the + QMF bands H_1(w) and H_2(w) are spit into 2 (sub-) 4th. (See figures 8.20 + and 8.22 of ISO/IEC 14496-3:2001/FDAM 2:2004(E) ) + */ + + /* + * Hybrid analysis. + */ + + /* Get qmf input data and apply descaling */ + for (i = 0; i < NO_QMF_BANDS_HYBRID20; i++) { + qmfInputData[0][i] = scaleValue(rIntBufferLeft[HYBRID_FILTER_DELAY][i], + scaleFactorLowBand_no_ov); + qmfInputData[1][i] = scaleValue(iIntBufferLeft[HYBRID_FILTER_DELAY][i], + scaleFactorLowBand_no_ov); + } + + /* LF - part */ + FDKhybridAnalysisApply(&h_ps_d->specificTo.mpeg.hybridAnalysis, + qmfInputData[0], qmfInputData[1], hybridData[0][0], + hybridData[0][1]); + + /* HF - part */ + /* bands up to lsb */ + scaleValues(&hybridData[0][0][NO_SUB_QMF_CHANNELS - 2], + &rIntBufferLeft[0][NO_QMF_BANDS_HYBRID20], + lsb - NO_QMF_BANDS_HYBRID20, scaleFactorLowBand); + scaleValues(&hybridData[0][1][NO_SUB_QMF_CHANNELS - 2], + &iIntBufferLeft[0][NO_QMF_BANDS_HYBRID20], + lsb - NO_QMF_BANDS_HYBRID20, scaleFactorLowBand); + + /* bands from lsb to usb */ + scaleValues(&hybridData[0][0][lsb + (NO_SUB_QMF_CHANNELS - 2 - + NO_QMF_BANDS_HYBRID20)], + &rIntBufferLeft[0][lsb], usb - lsb, scaleFactorHighBand); + scaleValues(&hybridData[0][1][lsb + (NO_SUB_QMF_CHANNELS - 2 - + NO_QMF_BANDS_HYBRID20)], + &iIntBufferLeft[0][lsb], usb - lsb, scaleFactorHighBand); + + /* bands from usb to NO_SUB_QMF_CHANNELS which should be zero for non-overlap + slots but can be non-zero for overlap slots */ + FDKmemcpy( + &hybridData[0][0] + [usb + (NO_SUB_QMF_CHANNELS - 2 - NO_QMF_BANDS_HYBRID20)], + &rIntBufferLeft[0][usb], sizeof(FIXP_DBL) * (NO_QMF_CHANNELS - usb)); + FDKmemcpy( + &hybridData[0][1] + [usb + (NO_SUB_QMF_CHANNELS - 2 - NO_QMF_BANDS_HYBRID20)], + &iIntBufferLeft[0][usb], sizeof(FIXP_DBL) * (NO_QMF_CHANNELS - usb)); + + /*! + Decorrelation: + By means of all-pass filtering and delaying, the (sub-)sub-band samples s_k(n) + are converted into de-correlated (sub-)sub-band samples d_k(n). + - k: frequency in hybrid spectrum + - n: time index + */ + + FDKdecorrelateApply(&h_ps_d->specificTo.mpeg.apDecor, + &hybridData[0][0][0], /* left real hybrid data */ + &hybridData[0][1][0], /* left imag hybrid data */ + &hybridData[1][0][0], /* right real hybrid data */ + &hybridData[1][1][0], /* right imag hybrid data */ + 0 /* startHybBand */ + ); + + /*! + Stereo Processing: + The sets of (sub-)sub-band samples s_k(n) and d_k(n) are processed according + to the stereo cues which are defined per stereo band. + */ + + applySlotBasedRotation(h_ps_d, + &hybridData[0][0][0], /* left real hybrid data */ + &hybridData[0][1][0], /* left imag hybrid data */ + &hybridData[1][0][0], /* right real hybrid data */ + &hybridData[1][1][0] /* right imag hybrid data */ + ); + + /*! + Hybrid synthesis filterbank: + The stereo processed hybrid subband signals l_k(n) and r_k(n) are fed into the + hybrid synthesis filterbanks which are identical to the 64 complex synthesis + filterbank of the SBR tool. The input to the filterbank are slots of 64 QMF + samples. For each slot the filterbank outputs one block of 64 samples of one + reconstructed stereo channel. The hybrid synthesis filterbank is computed + seperatly for the left and right channel. + */ + + /* + * Hybrid synthesis. + */ + for (i = 0; i < 2; i++) { + FDKhybridSynthesisApply( + &h_ps_d->specificTo.mpeg.hybridSynthesis[i], + hybridData[i][0], /* real hybrid data */ + hybridData[i][1], /* imag hybrid data */ + (i == 0) ? rIntBufferLeft[0] + : rIntBufferRight, /* output real qmf buffer */ + (i == 0) ? iIntBufferLeft[0] + : iIntBufferRight /* output imag qmf buffer */ + ); + } + + /* free temporary hybrid qmf values of one timeslot */ + C_ALLOC_SCRATCH_END(pHybridData, FIXP_DBL, 4 * NO_HYBRID_DATA_BANDS); + +} /* END ApplyPsSlot */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec.h new file mode 100644 index 0000000000000..029eac4e62a39 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec.h @@ -0,0 +1,333 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Sbr decoder +*/ +#ifndef PSDEC_H +#define PSDEC_H + +#include "sbrdecoder.h" +#include "FDK_hybrid.h" + +#include "FDK_decorrelate.h" + +/* This PS decoder implements the baseline version. So it always uses the */ +/* hybrid filter structure for 20 stereo bands and does not implemet IPD/OPD */ +/* synthesis. The baseline version has to support the complete PS bitstream */ +/* syntax. But IPD/OPD data is ignored and set to 0. If 34 stereo band config */ +/* is used in the bitstream for IIS/ICC the decoded parameters are mapped to */ +/* 20 stereo bands. */ + +#include "FDK_bitstream.h" + +#define SCAL_HEADROOM (2) + +#define PS_EXTENSION_SIZE_BITS (4) +#define PS_EXTENSION_ESC_COUNT_BITS (8) + +#define NO_QMF_CHANNELS (64) +#define MAX_NUM_COL (32) + +#define NO_QMF_BANDS_HYBRID20 (3) +#define NO_SUB_QMF_CHANNELS (12) +#define HYBRID_FILTER_DELAY (6) + +#define MAX_NO_PS_ENV (4 + 1) /* +1 needed for VAR_BORDER */ + +#define NO_HI_RES_BINS (34) +#define NO_MID_RES_BINS (20) +#define NO_LOW_RES_BINS (10) + +#define NO_HI_RES_IID_BINS (NO_HI_RES_BINS) +#define NO_HI_RES_ICC_BINS (NO_HI_RES_BINS) + +#define NO_MID_RES_IID_BINS (NO_MID_RES_BINS) +#define NO_MID_RES_ICC_BINS (NO_MID_RES_BINS) + +#define NO_LOW_RES_IID_BINS (NO_LOW_RES_BINS) +#define NO_LOW_RES_ICC_BINS (NO_LOW_RES_BINS) + +#define SUBQMF_GROUPS (10) +#define QMF_GROUPS (12) + +//#define SUBQMF_GROUPS_HI_RES ( 32 ) +//#define QMF_GROUPS_HI_RES ( 18 ) + +#define NO_IID_GROUPS (SUBQMF_GROUPS + QMF_GROUPS) +//#define NO_IID_GROUPS_HI_RES ( SUBQMF_GROUPS_HI_RES + +// QMF_GROUPS_HI_RES ) + +#define NO_IID_STEPS (7) /* 1 .. + 7 */ +#define NO_IID_STEPS_FINE (15) /* 1 .. +15 */ +#define NO_ICC_STEPS (8) /* 0 .. + 7 */ + +#define NO_IID_LEVELS (2 * NO_IID_STEPS + 1) /* - 7 .. + 7 */ +#define NO_IID_LEVELS_FINE (2 * NO_IID_STEPS_FINE + 1) /* -15 .. +15 */ +#define NO_ICC_LEVELS (NO_ICC_STEPS) /* 0 .. + 7 */ + +#define FIXP_SQRT05 ((FIXP_DBL)0x5a827980) /* 1/SQRT2 */ + +struct PS_DEC_COEFFICIENTS { + FIXP_DBL H11r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL H12r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL H21r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL H22r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + + FIXP_DBL + DeltaH11r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL + DeltaH12r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL + DeltaH21r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL + DeltaH22r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + + SCHAR + aaIidIndexMapped[MAX_NO_PS_ENV] + [NO_HI_RES_IID_BINS]; /*!< The mapped IID index for all + envelopes and all IID bins */ + SCHAR + aaIccIndexMapped[MAX_NO_PS_ENV] + [NO_HI_RES_ICC_BINS]; /*!< The mapped ICC index for all + envelopes and all ICC bins */ +}; + +typedef enum { ppt_none = 0, ppt_mpeg = 1, ppt_drm = 2 } PS_PAYLOAD_TYPE; + +typedef struct { + UCHAR bPsHeaderValid; /*!< set if new header is available from bitstream */ + + UCHAR bEnableIid; /*!< One bit denoting the presence of IID parameters */ + UCHAR bEnableIcc; /*!< One bit denoting the presence of ICC parameters */ + UCHAR bEnableExt; /*!< The PS extension layer is enabled using the enable_ext + bit. If it is set to %1 the IPD and OPD parameters are + sent. If it is disabled, i.e. %0, the extension layer is + skipped. */ + + UCHAR + modeIid; /*!< The configuration of IID parameters (number of bands and + quantisation grid, iid_quant) is determined by iid_mode. */ + UCHAR modeIcc; /*!< The configuration of Inter-channel Coherence parameters + (number of bands and quantisation grid) is determined by + icc_mode. */ + + UCHAR freqResIid; /*!< 0=low, 1=mid or 2=high frequency resolution for iid */ + UCHAR freqResIcc; /*!< 0=low, 1=mid or 2=high frequency resolution for icc */ + + UCHAR bFineIidQ; /*!< Use fine Iid quantisation. */ + + UCHAR bFrameClass; /*!< The frame_class bit determines whether the parameter + positions of the current frame are uniformly spaced + accross the frame or they are defined using the + positions described by border_position. + */ + + UCHAR noEnv; /*!< The number of envelopes per frame */ + UCHAR aEnvStartStop[MAX_NO_PS_ENV + 1]; /*!< In case of variable parameter + spacing the parameter positions are + determined by border_position */ + + SCHAR abIidDtFlag[MAX_NO_PS_ENV]; /*!< Deltacoding time/freq flag for IID, 0 + => freq */ + SCHAR abIccDtFlag[MAX_NO_PS_ENV]; /*!< Deltacoding time/freq flag for ICC, 0 + => freq */ + + SCHAR + aaIidIndex[MAX_NO_PS_ENV] + [NO_HI_RES_IID_BINS]; /*!< The IID index for all envelopes and + all IID bins */ + SCHAR + aaIccIndex[MAX_NO_PS_ENV] + [NO_HI_RES_ICC_BINS]; /*!< The ICC index for all envelopes and + all ICC bins */ + +} MPEG_PS_BS_DATA; + +struct PS_DEC { + SCHAR noSubSamples; + SCHAR noChannels; + + SCHAR procFrameBased; /*!< Helper to detected switching from frame based to + slot based processing + */ + + PS_PAYLOAD_TYPE + bPsDataAvail[(1) + 1]; /*!< set if new data available from bitstream */ + UCHAR psDecodedPrv; /*!< set if PS has been processed in the last frame */ + + /* helpers for frame delay line */ + UCHAR bsLastSlot; /*!< Index of last read slot. */ + UCHAR bsReadSlot; /*!< Index of current read slot for additional delay. */ + UCHAR processSlot; /*!< Index of current slot for processing (need for add. + delay). */ + + union { /* Bitstream data */ + MPEG_PS_BS_DATA + mpeg; /*!< Struct containing all MPEG specific PS data from bitstream. + */ + } bsData[(1) + 1]; + + shouldBeUnion { /* Static data */ + struct { + SCHAR aIidPrevFrameIndex[NO_HI_RES_IID_BINS]; /*!< The IID index for + previous frame */ + SCHAR aIccPrevFrameIndex[NO_HI_RES_ICC_BINS]; /*!< The ICC index for + previous frame */ + UCHAR + bPrevFrameFineIidQ; /*!< The IID quantization of the previous frame */ + UCHAR prevFreqResIid; /*!< Frequency resolution for IID of the previous + frame */ + UCHAR prevFreqResIcc; /*!< Frequency resolution for ICC of the previous + frame */ + UCHAR lastUsb; /*!< uppermost WMF delay band of last frame */ + + FIXP_DBL pHybridAnaStatesLFdmx + [2 * 13 * NO_QMF_BANDS_HYBRID20]; /*!< Memory used in hybrid analysis + for filter states. */ + FDK_ANA_HYB_FILTER hybridAnalysis; + FDK_SYN_HYB_FILTER hybridSynthesis[2]; + + DECORR_DEC apDecor; /*!< Decorrelator instance. */ + FIXP_DBL decorrBufferCplx[(2 * ((825) + (373)))]; + + FIXP_DBL h11rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) + coefficients */ + FIXP_DBL h12rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) + coefficients */ + FIXP_DBL h21rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) + coefficients */ + FIXP_DBL h22rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) + coefficients */ + + PS_DEC_COEFFICIENTS + *pCoef; /*!< temporal coefficients are on reusable scratch memory */ + + } mpeg; + } + specificTo; +}; + +typedef struct PS_DEC *HANDLE_PS_DEC; + +int CreatePsDec(HANDLE_PS_DEC *h_PS_DEC, int aacSamplesPerFrame); + +int DeletePsDec(HANDLE_PS_DEC *h_PS_DEC); + +void PreparePsProcessing(HANDLE_PS_DEC h_ps_d, + const FIXP_DBL *const *const rIntBufferLeft, + const FIXP_DBL *const *const iIntBufferLeft, + const int scaleFactorLowBand); + +void initSlotBasedRotation(HANDLE_PS_DEC h_ps_d, int env, int usb); + +void ApplyPsSlot( + HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */ + FIXP_DBL **rIntBufferLeft, /* real values of left qmf timeslot */ + FIXP_DBL **iIntBufferLeft, /* imag values of left qmf timeslot */ + FIXP_DBL *rIntBufferRight, /* real values of right qmf timeslot */ + FIXP_DBL *iIntBufferRight, /* imag values of right qmf timeslot */ + const int scaleFactorLowBand_no_ov, const int scaleFactorLowBand, + const int scaleFactorHighBand, const int lsb, const int usb); + +#endif /* PSDEC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec_drm.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec_drm.cpp new file mode 100644 index 0000000000000..6971f53df265c --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec_drm.cpp @@ -0,0 +1,108 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief parametric stereo decoder for Digital radio mondial +*/ + +#include "psdec_drm.h" diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec_drm.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec_drm.h new file mode 100644 index 0000000000000..5e2575d63a0c1 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdec_drm.h @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief parametric stereo decoder for digital radio mondial +*/ + +#ifndef PSDEC_DRM_H +#define PSDEC_DRM_H + +#include "sbrdecoder.h" + +#endif /* PSDEC_DRM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdecrom_drm.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdecrom_drm.cpp new file mode 100644 index 0000000000000..2033a8378e6f2 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/psdecrom_drm.cpp @@ -0,0 +1,108 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief rom tables for Drm parametric stereo decoder +*/ + +#include "psdec_drm.h" diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/pvc_dec.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/pvc_dec.cpp new file mode 100644 index 0000000000000..e1e3c2c05124f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/pvc_dec.cpp @@ -0,0 +1,684 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: Decode Predictive Vector Coding Data + +*******************************************************************************/ + +#include "pvc_dec.h" + +/* PVC interal definitions */ +#define PVC_DIVMODE_BITS 3 +#define PVC_NSMODE_BITS 1 +#define PVC_REUSEPVCID_BITS 1 +#define PVC_PVCID_BITS 7 +#define PVC_GRIDINFO_BITS 1 +#define PVC_NQMFBAND 64 +#define PVC_NBLOW 3 /* max. number of grouped QMF subbands below SBR range */ + +#define PVC_NTAB1 3 +#define PVC_NTAB2 128 +#define PVC_ID_NBIT 7 + +/* Exponent of pPvcStaticData->Esg and predictedEsg in dB domain. + max(Esg) = 10*log10(2^15*2^15) = 90.30; + min(Esg) = 10*log10(0.1) = -10 + max of predicted Esg seems to be higher than 90dB but 7 Bit should be enough. +*/ +#define PVC_ESG_EXP 7 + +#define LOG10FAC 0.752574989159953f /* == 10/log2(10) * 2^-2 */ +#define LOG10FAC_INV 0.664385618977472f /* == log2(10)/10 * 2^1 */ + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_SGL pvc_SC_16[] = { + FX_DBL2FXCONST_SGL(0x14413695), FX_DBL2FXCONST_SGL(0x1434b6cb), + FX_DBL2FXCONST_SGL(0x140f27c7), FX_DBL2FXCONST_SGL(0x13d0591d), + FX_DBL2FXCONST_SGL(0x1377f502), FX_DBL2FXCONST_SGL(0x130577d6), + FX_DBL2FXCONST_SGL(0x12782266), FX_DBL2FXCONST_SGL(0x11cee459), + FX_DBL2FXCONST_SGL(0x11083a2a), FX_DBL2FXCONST_SGL(0x1021f5e9), + FX_DBL2FXCONST_SGL(0x0f18e17c), FX_DBL2FXCONST_SGL(0x0de814ca), + FX_DBL2FXCONST_SGL(0x0c87a568), FX_DBL2FXCONST_SGL(0x0ae9b167), + FX_DBL2FXCONST_SGL(0x08f24226), FX_DBL2FXCONST_SGL(0x06575ed5), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_SGL pvc_SC_12[] = { + FX_DBL2FXCONST_SGL(0x1aba6b3e), FX_DBL2FXCONST_SGL(0x1a9d164e), + FX_DBL2FXCONST_SGL(0x1a44d56d), FX_DBL2FXCONST_SGL(0x19b0d742), + FX_DBL2FXCONST_SGL(0x18df969a), FX_DBL2FXCONST_SGL(0x17ce91a0), + FX_DBL2FXCONST_SGL(0x1679c3fa), FX_DBL2FXCONST_SGL(0x14daabfc), + FX_DBL2FXCONST_SGL(0x12e65221), FX_DBL2FXCONST_SGL(0x1088d125), + FX_DBL2FXCONST_SGL(0x0d9907b3), FX_DBL2FXCONST_SGL(0x09a80e9d), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_SGL pvc_SC_4[] = { + FX_DBL2FXCONST_SGL(0x4ad6ab0f), + FX_DBL2FXCONST_SGL(0x47ef0dbe), + FX_DBL2FXCONST_SGL(0x3eee7496), + FX_DBL2FXCONST_SGL(0x2e4bd29d), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_SGL pvc_SC_3[] = { + FX_DBL2FXCONST_SGL(0x610dc761), + FX_DBL2FXCONST_SGL(0x5a519a3d), + FX_DBL2FXCONST_SGL(0x44a09e62), +}; + +static const UCHAR g_3a_pvcTab1_mode1[PVC_NTAB1][PVC_NBLOW][PVC_NBHIGH_MODE1] = + {{{0x4F, 0x5B, 0x57, 0x52, 0x4D, 0x65, 0x45, 0x57}, + {0xF3, 0x0F, 0x18, 0x20, 0x19, 0x4F, 0x3D, 0x23}, + {0x78, 0x57, 0x55, 0x50, 0x50, 0x20, 0x36, 0x37}}, + {{0x4C, 0x5F, 0x53, 0x37, 0x1E, 0xFD, 0x15, 0x0A}, + {0x05, 0x0E, 0x28, 0x41, 0x48, 0x6E, 0x54, 0x5B}, + {0x59, 0x47, 0x40, 0x40, 0x3D, 0x33, 0x3F, 0x39}}, + {{0x47, 0x5F, 0x57, 0x34, 0x3C, 0x2E, 0x2E, 0x31}, + {0xFA, 0x13, 0x23, 0x4E, 0x44, 0x7C, 0x34, 0x38}, + {0x63, 0x43, 0x41, 0x3D, 0x35, 0x19, 0x3D, 0x33}}}; + +static const UCHAR g_2a_pvcTab2_mode1[PVC_NTAB2][PVC_NBHIGH_MODE1] = { + {0xCB, 0xD1, 0xCC, 0xD2, 0xE2, 0xEB, 0xE7, 0xE8}, + {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, + {0x84, 0x8C, 0x88, 0x83, 0x90, 0x93, 0x86, 0x80}, + {0xD7, 0xD8, 0xC0, 0xC7, 0xCF, 0xE5, 0xF1, 0xF6}, + {0xA5, 0xA6, 0xAA, 0xA8, 0xB0, 0xB1, 0xB8, 0xB8}, + {0xD7, 0xCB, 0xC1, 0xC3, 0xC5, 0xC9, 0xC9, 0xCE}, + {0xCA, 0xB5, 0xB8, 0xB3, 0xAC, 0xB6, 0xBB, 0xB8}, + {0xC1, 0xC4, 0xC3, 0xC5, 0xC6, 0xCA, 0xCA, 0xCB}, + {0xE0, 0xE1, 0xD8, 0xCD, 0xCB, 0xCB, 0xCE, 0xCC}, + {0xDB, 0xE1, 0xDF, 0xDB, 0xDC, 0xD9, 0xD9, 0xD6}, + {0xE0, 0xDE, 0xDD, 0xDD, 0xE0, 0xE3, 0xE5, 0xE6}, + {0xCA, 0xD2, 0xCD, 0xCE, 0xD5, 0xDB, 0xD9, 0xDB}, + {0xD2, 0xE0, 0xDB, 0xD5, 0xDB, 0xDE, 0xE3, 0xE1}, + {0xE5, 0xDB, 0xD0, 0xD2, 0xD8, 0xDD, 0xDB, 0xDD}, + {0xC0, 0xB5, 0xBF, 0xDD, 0xE3, 0xDC, 0xDC, 0xE4}, + {0xDB, 0xCE, 0xC6, 0xCF, 0xCF, 0xD1, 0xD3, 0xD4}, + {0xC9, 0xD7, 0xDA, 0xE2, 0xE9, 0xE7, 0xDF, 0xDC}, + {0x0A, 0x07, 0x0A, 0x08, 0x19, 0x24, 0x1F, 0x22}, + {0x1E, 0x1F, 0x11, 0x0E, 0x22, 0x2D, 0x33, 0x32}, + {0xF0, 0xDA, 0xDC, 0x18, 0x1F, 0x19, 0x0A, 0x1E}, + {0x09, 0xF8, 0xE6, 0x05, 0x19, 0x11, 0x0E, 0x0B}, + {0x09, 0x10, 0x0E, 0xE6, 0xF4, 0x20, 0x22, 0xFA}, + {0xF2, 0xE5, 0xF8, 0x0E, 0x18, 0x15, 0x0D, 0x10}, + {0x15, 0x13, 0x16, 0x0A, 0x0D, 0x1F, 0x1D, 0x1B}, + {0xFA, 0xFF, 0xFE, 0xFF, 0x09, 0x11, 0x03, 0x0B}, + {0xFE, 0xFA, 0xF2, 0xF8, 0x0C, 0x1E, 0x11, 0x12}, + {0xFA, 0xF8, 0x0B, 0x17, 0x1D, 0x17, 0x0E, 0x16}, + {0x00, 0xF3, 0xFD, 0x0A, 0x1C, 0x17, 0xFD, 0x08}, + {0xEA, 0xEA, 0x03, 0x12, 0x1E, 0x14, 0x09, 0x04}, + {0x02, 0xFE, 0x04, 0xFB, 0x0C, 0x0E, 0x07, 0x02}, + {0xF6, 0x02, 0x07, 0x0B, 0x17, 0x17, 0x01, 0xFF}, + {0xF5, 0xFB, 0xFE, 0x04, 0x12, 0x14, 0x0C, 0x0D}, + {0x10, 0x10, 0x0E, 0x04, 0x07, 0x11, 0x0F, 0x13}, + {0x0C, 0x0F, 0xFB, 0xF2, 0x0A, 0x12, 0x09, 0x0D}, + {0x0D, 0x1D, 0xF1, 0xF4, 0x2A, 0x06, 0x3B, 0x32}, + {0xFC, 0x08, 0x06, 0x02, 0x0E, 0x17, 0x08, 0x0E}, + {0x07, 0x02, 0xEE, 0xEE, 0x2B, 0xF6, 0x23, 0x13}, + {0x04, 0x02, 0x05, 0x08, 0x0B, 0x0E, 0xFB, 0xFB}, + {0x00, 0x04, 0x10, 0x18, 0x22, 0x25, 0x1D, 0x1F}, + {0xFB, 0x0D, 0x07, 0x00, 0x0C, 0x0F, 0xFC, 0x02}, + {0x00, 0x00, 0x00, 0x01, 0x05, 0x07, 0x03, 0x05}, + {0x04, 0x05, 0x08, 0x13, 0xFF, 0xEB, 0x0C, 0x06}, + {0x05, 0x13, 0x0E, 0x0B, 0x12, 0x15, 0x09, 0x0A}, + {0x09, 0x03, 0x09, 0x05, 0x12, 0x16, 0x11, 0x12}, + {0x14, 0x1A, 0x06, 0x01, 0x10, 0x11, 0xFE, 0x02}, + {0x01, 0x0B, 0x0B, 0x0C, 0x18, 0x21, 0x10, 0x13}, + {0x12, 0x0D, 0x0A, 0x10, 0x1C, 0x1D, 0x0D, 0x10}, + {0x03, 0x09, 0x14, 0x15, 0x1B, 0x1A, 0x01, 0xFF}, + {0x08, 0x12, 0x13, 0x0E, 0x16, 0x1D, 0x14, 0x1B}, + {0x07, 0x15, 0x1C, 0x1B, 0x20, 0x21, 0x11, 0x0E}, + {0x12, 0x18, 0x19, 0x17, 0x20, 0x25, 0x1A, 0x1E}, + {0x0C, 0x1A, 0x1D, 0x22, 0x2F, 0x33, 0x27, 0x28}, + {0x0E, 0x1A, 0x17, 0x10, 0x0A, 0x0E, 0xFF, 0x06}, + {0x1A, 0x1C, 0x18, 0x14, 0x1A, 0x16, 0x0A, 0x0E}, + {0x1E, 0x27, 0x25, 0x26, 0x27, 0x2A, 0x21, 0x21}, + {0xF1, 0x0A, 0x16, 0x1C, 0x28, 0x25, 0x15, 0x19}, + {0x08, 0x12, 0x09, 0x08, 0x16, 0x17, 0xEF, 0xF6}, + {0x0C, 0x0B, 0x00, 0xFC, 0x04, 0x09, 0xFC, 0x03}, + {0xFB, 0xF1, 0xF8, 0x26, 0x24, 0x18, 0x1D, 0x20}, + {0xF9, 0x01, 0x0C, 0x0F, 0x07, 0x08, 0x06, 0x07}, + {0x07, 0x06, 0x08, 0x04, 0x07, 0x0D, 0x07, 0x09}, + {0xFE, 0x01, 0x06, 0x05, 0x13, 0x1B, 0x14, 0x19}, + {0x09, 0x0C, 0x0E, 0x01, 0x08, 0x05, 0xFB, 0xFD}, + {0x07, 0x06, 0x03, 0x0A, 0x16, 0x12, 0x04, 0x07}, + {0x04, 0x01, 0x00, 0x04, 0x1F, 0x20, 0x0E, 0x0A}, + {0x03, 0xFF, 0xF6, 0xFB, 0x15, 0x1A, 0x00, 0x03}, + {0xFC, 0x18, 0x0B, 0x2D, 0x35, 0x23, 0x12, 0x09}, + {0x02, 0xFE, 0x01, 0xFF, 0x0C, 0x11, 0x0D, 0x0F}, + {0xFA, 0xE9, 0xD9, 0xFF, 0x0D, 0x05, 0x0D, 0x10}, + {0xF1, 0xE0, 0xF0, 0x01, 0x06, 0x06, 0x06, 0x10}, + {0xE9, 0xD4, 0xD7, 0x0F, 0x14, 0x0B, 0x0D, 0x16}, + {0x00, 0xFF, 0xEE, 0xE5, 0xFF, 0x08, 0x02, 0xF9}, + {0xE0, 0xDA, 0xE5, 0xFE, 0x09, 0x02, 0xF9, 0x04}, + {0xE0, 0xE2, 0xF4, 0x09, 0x13, 0x0C, 0x0D, 0x09}, + {0xFC, 0x02, 0x04, 0xFF, 0x00, 0xFF, 0xF8, 0xF7}, + {0xFE, 0xFB, 0xED, 0xF2, 0xFE, 0xFE, 0x08, 0x0C}, + {0xF3, 0xEF, 0xD0, 0xE3, 0x05, 0x11, 0xFD, 0xFF}, + {0xFA, 0xEF, 0xEA, 0xFE, 0x0D, 0x0E, 0xFE, 0x02}, + {0xF7, 0xFB, 0xDB, 0xDF, 0x14, 0xDD, 0x07, 0xFE}, + {0xFE, 0x08, 0x00, 0xDB, 0xE5, 0x1A, 0x13, 0xED}, + {0xF9, 0xFE, 0xFF, 0xF4, 0xF3, 0x00, 0x05, 0x02}, + {0xEF, 0xDE, 0xD8, 0xEB, 0xEA, 0xF5, 0x0E, 0x19}, + {0xFB, 0xFC, 0xFA, 0xEC, 0xEB, 0xED, 0xEE, 0xE8}, + {0xEE, 0xFC, 0xFD, 0x00, 0x04, 0xFC, 0xF0, 0xF5}, + {0x00, 0xFA, 0xF4, 0xF1, 0xF5, 0xFA, 0xFB, 0xF9}, + {0xEB, 0xF0, 0xDF, 0xE3, 0xEF, 0x07, 0x02, 0x05}, + {0xF7, 0xF0, 0xE6, 0xE7, 0x06, 0x15, 0x06, 0x0C}, + {0xF1, 0xE4, 0xD8, 0xEA, 0x06, 0xF2, 0x07, 0x09}, + {0xFF, 0xFE, 0xFE, 0xF9, 0xFF, 0xFF, 0x02, 0xF9}, + {0xDD, 0xF4, 0xF0, 0xF1, 0xFF, 0xFF, 0xEA, 0xF1}, + {0xF0, 0xF1, 0xFD, 0x03, 0x03, 0xFE, 0x00, 0x05}, + {0xF1, 0xF6, 0xE0, 0xDF, 0xF5, 0x01, 0xF4, 0xF8}, + {0x02, 0x03, 0xE5, 0xDC, 0xE7, 0xFD, 0x02, 0x08}, + {0xEC, 0xF1, 0xF5, 0xEC, 0xF2, 0xF8, 0xF6, 0xEE}, + {0xF3, 0xF4, 0xF6, 0xF4, 0xF5, 0xF1, 0xE7, 0xEA}, + {0xF7, 0xF3, 0xEC, 0xEA, 0xEF, 0xF0, 0xEE, 0xF1}, + {0xEB, 0xF6, 0xFB, 0xFA, 0xEF, 0xF3, 0xF3, 0xF7}, + {0x01, 0x03, 0xF1, 0xF6, 0x05, 0xF8, 0xE1, 0xEB}, + {0xF5, 0xF6, 0xF6, 0xF4, 0xFB, 0xFB, 0xFF, 0x00}, + {0xF8, 0x01, 0xFB, 0xFA, 0xFF, 0x03, 0xFE, 0x04}, + {0x04, 0xFB, 0x03, 0xFD, 0xF5, 0xF7, 0xF6, 0xFB}, + {0x06, 0x09, 0xFB, 0xF4, 0xF9, 0xFA, 0xFC, 0xFF}, + {0xF5, 0xF6, 0xF1, 0xEE, 0xF5, 0xF8, 0xF5, 0xF9}, + {0xF5, 0xF9, 0xFA, 0xFC, 0x07, 0x09, 0x01, 0xFB}, + {0xD7, 0xE9, 0xE8, 0xEC, 0x00, 0x0C, 0xFE, 0xF1}, + {0xEC, 0x04, 0xE9, 0xDF, 0x03, 0xE8, 0x00, 0xFA}, + {0xE6, 0xE2, 0xFF, 0x0A, 0x13, 0x01, 0x00, 0xF7}, + {0xF1, 0xFA, 0xF7, 0xF5, 0x01, 0x06, 0x05, 0x0A}, + {0xF6, 0xF6, 0xFC, 0xF6, 0xE8, 0x11, 0xF2, 0xFE}, + {0xFE, 0x08, 0x05, 0x12, 0xFD, 0xD0, 0x0E, 0x07}, + {0xF1, 0xFE, 0xF7, 0xF2, 0xFB, 0x02, 0xFA, 0xF8}, + {0xF4, 0xEA, 0xEC, 0xF3, 0xFE, 0x01, 0xF7, 0xF6}, + {0xFF, 0xFA, 0xFB, 0xF9, 0xFF, 0x01, 0x04, 0x03}, + {0x00, 0xF9, 0xF4, 0xFC, 0x05, 0xFC, 0xF7, 0xFB}, + {0xF8, 0xFF, 0xEF, 0xEC, 0xFB, 0x04, 0xF8, 0x03}, + {0xEB, 0xF1, 0xED, 0xF4, 0x02, 0x0E, 0x0B, 0x04}, + {0xF7, 0x01, 0xF8, 0xF4, 0xF8, 0xEF, 0xF8, 0x04}, + {0xEB, 0xF0, 0xF7, 0xFC, 0x10, 0x0D, 0xF8, 0xF8}, + {0xE8, 0xFE, 0xEE, 0xE8, 0xED, 0xF7, 0xF5, 0xF8}, + {0xED, 0xEB, 0xE9, 0xEA, 0xF2, 0xF5, 0xF4, 0xF9}, + {0xEA, 0xF2, 0xEF, 0xEE, 0xF9, 0xFE, 0xFD, 0x02}, + {0xFA, 0xFD, 0x02, 0x0D, 0xFA, 0xE4, 0x0F, 0x01}, + {0xFF, 0x08, 0x05, 0xF6, 0xF7, 0xFB, 0xF1, 0xF1}, + {0xF4, 0xEC, 0xEE, 0xF6, 0xEE, 0xEE, 0xF8, 0x06}, + {0xE8, 0xFA, 0xF8, 0xE8, 0xF8, 0xE9, 0xEE, 0xF9}, + {0xE5, 0xE9, 0xF0, 0x00, 0x00, 0xEF, 0xF3, 0xF8}, + {0xF7, 0xFB, 0xFB, 0xF7, 0xF9, 0xF9, 0xF5, 0xF0}, + {0xFD, 0xFF, 0xF2, 0xEE, 0xF2, 0xF5, 0xF1, 0xF3}}; + +static const UCHAR g_3a_pvcTab1_mode2[PVC_NTAB1][PVC_NBLOW][PVC_NBHIGH_MODE2] = + {{{0x11, 0x27, 0x0F, 0xFD, 0x04, 0xFC}, + {0x00, 0xBE, 0xE3, 0xF4, 0xDB, 0xF0}, + {0x09, 0x1E, 0x18, 0x1A, 0x21, 0x1B}}, + {{0x16, 0x28, 0x2B, 0x29, 0x25, 0x32}, + {0xF2, 0xE9, 0xE4, 0xE5, 0xE2, 0xD4}, + {0x0E, 0x0B, 0x0C, 0x0D, 0x0D, 0x0E}}, + {{0x2E, 0x3C, 0x20, 0x16, 0x1B, 0x1A}, + {0xE4, 0xC6, 0xE5, 0xF4, 0xDC, 0xDC}, + {0x0F, 0x1B, 0x18, 0x14, 0x1E, 0x1A}}}; + +static const UCHAR g_2a_pvcTab2_mode2[PVC_NTAB2][PVC_NBHIGH_MODE2] = { + {0x26, 0x25, 0x11, 0x0C, 0xFA, 0x15}, {0x1B, 0x18, 0x11, 0x0E, 0x0E, 0x0E}, + {0x12, 0x10, 0x10, 0x10, 0x11, 0x10}, {0x1E, 0x24, 0x19, 0x15, 0x14, 0x12}, + {0x24, 0x16, 0x12, 0x13, 0x15, 0x1C}, {0xEA, 0xED, 0xEB, 0xEA, 0xEC, 0xEB}, + {0xFC, 0xFD, 0xFD, 0xFC, 0xFE, 0xFE}, {0x0F, 0x0C, 0x0B, 0x0A, 0x0B, 0x0B}, + {0x22, 0x0B, 0x16, 0x18, 0x13, 0x19}, {0x1C, 0x14, 0x1D, 0x20, 0x19, 0x1A}, + {0x10, 0x08, 0x00, 0xFF, 0x02, 0x05}, {0x06, 0x07, 0x05, 0x03, 0x05, 0x04}, + {0x2A, 0x1F, 0x12, 0x12, 0x11, 0x18}, {0x19, 0x19, 0x02, 0x04, 0x00, 0x04}, + {0x18, 0x17, 0x17, 0x15, 0x16, 0x15}, {0x21, 0x1E, 0x1B, 0x19, 0x1C, 0x1B}, + {0x3C, 0x35, 0x20, 0x1D, 0x30, 0x34}, {0x3A, 0x1F, 0x37, 0x38, 0x33, 0x31}, + {0x37, 0x34, 0x25, 0x27, 0x35, 0x34}, {0x34, 0x2E, 0x32, 0x31, 0x34, 0x31}, + {0x36, 0x33, 0x2F, 0x2F, 0x32, 0x2F}, {0x35, 0x20, 0x2F, 0x32, 0x2F, 0x2C}, + {0x2E, 0x2B, 0x2F, 0x34, 0x36, 0x30}, {0x3F, 0x39, 0x30, 0x28, 0x29, 0x29}, + {0x3C, 0x30, 0x32, 0x37, 0x39, 0x36}, {0x37, 0x36, 0x30, 0x2B, 0x26, 0x24}, + {0x44, 0x38, 0x2F, 0x2D, 0x2D, 0x2D}, {0x38, 0x2B, 0x2C, 0x2C, 0x30, 0x2D}, + {0x37, 0x36, 0x2F, 0x23, 0x2D, 0x32}, {0x3C, 0x39, 0x29, 0x2E, 0x38, 0x37}, + {0x3B, 0x3A, 0x35, 0x32, 0x31, 0x2D}, {0x32, 0x31, 0x2F, 0x2C, 0x2D, 0x28}, + {0x2C, 0x31, 0x32, 0x30, 0x32, 0x2D}, {0x35, 0x34, 0x34, 0x34, 0x35, 0x33}, + {0x34, 0x38, 0x3B, 0x3C, 0x3E, 0x3A}, {0x3E, 0x3C, 0x3B, 0x3A, 0x3C, 0x39}, + {0x3D, 0x41, 0x46, 0x41, 0x3D, 0x38}, {0x44, 0x41, 0x40, 0x3E, 0x3F, 0x3A}, + {0x47, 0x47, 0x47, 0x42, 0x44, 0x40}, {0x4C, 0x4A, 0x4A, 0x46, 0x49, 0x45}, + {0x53, 0x52, 0x52, 0x4C, 0x4E, 0x49}, {0x41, 0x3D, 0x39, 0x2C, 0x2E, 0x2E}, + {0x2D, 0x37, 0x36, 0x30, 0x28, 0x36}, {0x3B, 0x32, 0x2E, 0x2D, 0x2D, 0x29}, + {0x40, 0x39, 0x36, 0x35, 0x36, 0x32}, {0x30, 0x2D, 0x2D, 0x2E, 0x31, 0x30}, + {0x38, 0x3D, 0x3B, 0x37, 0x35, 0x34}, {0x44, 0x3D, 0x3C, 0x38, 0x37, 0x33}, + {0x3A, 0x36, 0x37, 0x37, 0x39, 0x36}, {0x32, 0x36, 0x37, 0x30, 0x2E, 0x2A}, + {0x3C, 0x33, 0x33, 0x31, 0x33, 0x30}, {0x30, 0x31, 0x36, 0x37, 0x38, 0x34}, + {0x26, 0x27, 0x2E, 0x29, 0x1C, 0x16}, {0x14, 0x15, 0x1F, 0x17, 0x15, 0x1C}, + {0x38, 0x2D, 0x18, 0x13, 0x1E, 0x2B}, {0x30, 0x22, 0x17, 0x1A, 0x26, 0x2B}, + {0x24, 0x20, 0x1F, 0x10, 0x0C, 0x11}, {0x27, 0x1F, 0x13, 0x17, 0x24, 0x2A}, + {0x2F, 0x13, 0x18, 0x13, 0x2A, 0x32}, {0x31, 0x1E, 0x1E, 0x1E, 0x21, 0x28}, + {0x2A, 0x12, 0x19, 0x17, 0x16, 0x24}, {0x27, 0x0F, 0x16, 0x1D, 0x17, 0x1C}, + {0x2F, 0x26, 0x25, 0x22, 0x20, 0x22}, {0x1E, 0x1B, 0x1E, 0x18, 0x1E, 0x24}, + {0x31, 0x26, 0x0E, 0x15, 0x15, 0x25}, {0x2D, 0x22, 0x1E, 0x14, 0x10, 0x22}, + {0x25, 0x1B, 0x18, 0x11, 0x13, 0x1F}, {0x2F, 0x1B, 0x13, 0x1B, 0x18, 0x22}, + {0x21, 0x24, 0x1D, 0x1C, 0x1D, 0x1B}, {0x23, 0x1E, 0x28, 0x29, 0x27, 0x25}, + {0x2E, 0x2A, 0x1D, 0x17, 0x26, 0x2D}, {0x31, 0x2C, 0x1A, 0x0E, 0x1A, 0x24}, + {0x26, 0x16, 0x20, 0x1D, 0x14, 0x1E}, {0x29, 0x20, 0x1B, 0x1B, 0x17, 0x17}, + {0x1D, 0x06, 0x1A, 0x1E, 0x1B, 0x1D}, {0x2B, 0x23, 0x1F, 0x1F, 0x1D, 0x1C}, + {0x27, 0x1A, 0x0C, 0x0E, 0x0F, 0x1A}, {0x29, 0x1D, 0x1E, 0x22, 0x22, 0x24}, + {0x20, 0x21, 0x1B, 0x18, 0x13, 0x21}, {0x27, 0x0E, 0x10, 0x14, 0x10, 0x1A}, + {0x26, 0x24, 0x25, 0x25, 0x26, 0x28}, {0x1A, 0x24, 0x25, 0x29, 0x26, 0x24}, + {0x1D, 0x1D, 0x15, 0x12, 0x0F, 0x18}, {0x1E, 0x14, 0x13, 0x12, 0x14, 0x18}, + {0x16, 0x13, 0x13, 0x1A, 0x1B, 0x1D}, {0x20, 0x27, 0x22, 0x24, 0x1A, 0x19}, + {0x1F, 0x17, 0x19, 0x18, 0x17, 0x18}, {0x20, 0x1B, 0x1C, 0x1C, 0x1B, 0x1A}, + {0x23, 0x19, 0x1D, 0x1F, 0x1E, 0x21}, {0x26, 0x1F, 0x1D, 0x1B, 0x19, 0x1A}, + {0x23, 0x1E, 0x1F, 0x20, 0x1F, 0x1E}, {0x29, 0x20, 0x22, 0x20, 0x20, 0x1F}, + {0x26, 0x23, 0x21, 0x22, 0x23, 0x23}, {0x29, 0x1F, 0x24, 0x25, 0x26, 0x29}, + {0x2B, 0x22, 0x25, 0x27, 0x23, 0x21}, {0x29, 0x21, 0x19, 0x0E, 0x22, 0x2D}, + {0x32, 0x29, 0x1F, 0x1C, 0x1B, 0x21}, {0x1E, 0x1A, 0x1E, 0x24, 0x25, 0x25}, + {0x24, 0x1D, 0x21, 0x22, 0x22, 0x25}, {0x2C, 0x25, 0x21, 0x22, 0x23, 0x25}, + {0x24, 0x1E, 0x21, 0x26, 0x2B, 0x2C}, {0x28, 0x24, 0x1B, 0x1F, 0x28, 0x2D}, + {0x23, 0x13, 0x16, 0x22, 0x22, 0x29}, {0x1B, 0x23, 0x1C, 0x20, 0x14, 0x0D}, + {0x1E, 0x16, 0x1A, 0x1E, 0x1C, 0x1D}, {0x2B, 0x1C, 0x1D, 0x20, 0x1B, 0x1C}, + {0x1C, 0x1B, 0x23, 0x1F, 0x19, 0x1E}, {0x21, 0x23, 0x26, 0x20, 0x20, 0x22}, + {0x1D, 0x0B, 0x19, 0x1E, 0x11, 0x19}, {0x18, 0x17, 0x16, 0x17, 0x14, 0x16}, + {0x16, 0x19, 0x1C, 0x20, 0x21, 0x22}, {0x30, 0x1E, 0x22, 0x24, 0x25, 0x26}, + {0x1B, 0x1F, 0x17, 0x1D, 0x1E, 0x21}, {0x32, 0x2B, 0x27, 0x1F, 0x1B, 0x1A}, + {0x28, 0x20, 0x1A, 0x1B, 0x1F, 0x23}, {0x32, 0x21, 0x20, 0x21, 0x1D, 0x1F}, + {0x22, 0x18, 0x12, 0x15, 0x1B, 0x20}, {0x27, 0x27, 0x2A, 0x24, 0x21, 0x21}, + {0x1E, 0x0F, 0x0D, 0x1A, 0x1D, 0x23}, {0x28, 0x25, 0x27, 0x21, 0x17, 0x25}, + {0x2B, 0x27, 0x23, 0x19, 0x13, 0x14}, {0x25, 0x2B, 0x22, 0x22, 0x20, 0x21}, + {0x27, 0x1B, 0x16, 0x17, 0x0F, 0x15}, {0x29, 0x26, 0x23, 0x15, 0x1E, 0x28}, + {0x24, 0x1C, 0x19, 0x1A, 0x18, 0x19}, {0x2D, 0x15, 0x27, 0x2B, 0x24, 0x23}, + {0x2C, 0x12, 0x1F, 0x23, 0x1F, 0x20}, {0x25, 0x0F, 0x22, 0x27, 0x1F, 0x21}}; + +static const UCHAR g_a_pvcTab1_dp_mode1[PVC_NTAB1 - 1] = {17, 68}; +static const UCHAR g_a_pvcTab1_dp_mode2[PVC_NTAB1 - 1] = {16, 52}; +/* fractional exponent which corresponds to Q representation value */ +static const SCHAR g_a_scalingCoef_mode1[PVC_NBLOW + 1] = { + -1, -1, 0, 6}; /* { 8, 8, 7, 1 }; Q scaling */ +static const SCHAR g_a_scalingCoef_mode2[PVC_NBLOW + 1] = { + 0, 0, 1, 7}; /* { 7, 7, 6, 0 }; Q scaling */ + +int pvcInitFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, const UCHAR pvcMode, + const UCHAR ns, const int RATE, const int kx, + const int pvcBorder0, const UCHAR *pPvcID) { + int lbw, hbw, i, temp; + pPvcDynamicData->pvc_mode = pvcMode; + pPvcDynamicData->kx = kx; + pPvcDynamicData->RATE = RATE; + + switch (pvcMode) { + case 0: + /* legacy SBR, nothing to do */ + return 0; + case 1: + pPvcDynamicData->nbHigh = 8; + pPvcDynamicData->pPVCTab1 = (const UCHAR *)g_3a_pvcTab1_mode1; + pPvcDynamicData->pPVCTab2 = (const UCHAR *)g_2a_pvcTab2_mode1; + pPvcDynamicData->pPVCTab1_dp = g_a_pvcTab1_dp_mode1; + pPvcDynamicData->pScalingCoef = g_a_scalingCoef_mode1; + hbw = 8 / RATE; + break; + case 2: + pPvcDynamicData->nbHigh = 6; + pPvcDynamicData->pPVCTab1 = (const UCHAR *)g_3a_pvcTab1_mode2; + pPvcDynamicData->pPVCTab2 = (const UCHAR *)g_2a_pvcTab2_mode2; + pPvcDynamicData->pPVCTab1_dp = g_a_pvcTab1_dp_mode2; + pPvcDynamicData->pScalingCoef = g_a_scalingCoef_mode2; + hbw = 12 / RATE; + break; + default: + /* invalid pvcMode */ + return 1; + } + + pPvcDynamicData->pvcBorder0 = pvcBorder0; + UCHAR pvcBorder0_last = pPvcStaticData->pvcBorder0; + pPvcStaticData->pvcBorder0 = pvcBorder0; + pPvcDynamicData->pPvcID = pPvcID; + + pPvcDynamicData->ns = ns; + switch (ns) { + case 16: + pPvcDynamicData->pSCcoeffs = pvc_SC_16; + break; + case 12: + pPvcDynamicData->pSCcoeffs = pvc_SC_12; + break; + case 4: + pPvcDynamicData->pSCcoeffs = pvc_SC_4; + break; + case 3: + pPvcDynamicData->pSCcoeffs = pvc_SC_3; + break; + default: + return 1; + } + + /* in the lower part of Esg-array there are previous values of Esg (from last + call to this function In case of an previous legay-SBR frame, or if there + was a change in cross-over FQ the value of first PVC SBR timeslot is + propagated to prev-values in order to have reasonable values for + smooth-filtering + */ + if ((pPvcStaticData->pvc_mode_last == 0) || (pPvcStaticData->kx_last != kx)) { + pPvcDynamicData->pastEsgSlotsAvail = 0; + } else { + pPvcDynamicData->pastEsgSlotsAvail = PVC_NS_MAX - pvcBorder0_last; + } + + lbw = 8 / RATE; + + temp = kx; + for (i = PVC_NBLOW; i >= 0; i--) { + pPvcDynamicData->sg_offset_low[i] = temp; + temp -= lbw; + } + + temp = 0; + for (i = 0; i <= pPvcDynamicData->nbHigh; i++) { + pPvcDynamicData->sg_offset_high_kx[i] = temp; + temp += hbw; + } + + return 0; +} + +/* call if pvcMode = 1,2 */ +void pvcDecodeFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, FIXP_DBL **qmfBufferReal, + FIXP_DBL **qmfBufferImag, const int overlap, + const int qmfExponentOverlap, + const int qmfExponentCurrent) { + int t; + FIXP_DBL *predictedEsgSlot; + int RATE = pPvcDynamicData->RATE; + int pvcBorder0 = pPvcDynamicData->pvcBorder0; + + for (t = pvcBorder0; t < PVC_NTIMESLOT; t++) { + int *pPredEsg_exp = &pPvcDynamicData->predEsg_exp[t]; + predictedEsgSlot = pPvcDynamicData->predEsg[t]; + + pvcDecodeTimeSlot( + pPvcStaticData, pPvcDynamicData, &qmfBufferReal[t * RATE], + &qmfBufferImag[t * RATE], + (t * RATE < overlap) ? qmfExponentOverlap : qmfExponentCurrent, + pvcBorder0, t, predictedEsgSlot, pPredEsg_exp); + } + + return; +} + +void pvcDecodeTimeSlot(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, + FIXP_DBL **qmfSlotReal, FIXP_DBL **qmfSlotImag, + const int qmfExponent, const int pvcBorder0, + const int timeSlotNumber, FIXP_DBL predictedEsgSlot[], + int *predictedEsg_exp) { + int i, band, ksg, ksg_start = 0; + int RATE = pPvcDynamicData->RATE; + int Esg_index = pPvcStaticData->Esg_slot_index; + const SCHAR *sg_borders = pPvcDynamicData->sg_offset_low; + FIXP_DBL *pEsg = pPvcStaticData->Esg[Esg_index]; + FIXP_DBL E[PVC_NBLOW] = {0}; + + /* Subband grouping in QMF subbands below SBR range */ + /* Within one timeslot ( i = [0...(RATE-1)] QMF subsamples) calculate energy + E(ib,t) and group them to Esg(ksg,t). Then transfer values to logarithmical + domain and store them for time domain smoothing. (7.5.6.3 Subband grouping + in QMF subbands below SBR range) + */ + for (ksg = 0; sg_borders[ksg] < 0; ksg++) { + pEsg[ksg] = FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP)); /* 10*log10(0.1) */ + ksg_start++; + } + + for (i = 0; i < RATE; i++) { + FIXP_DBL *qmfR, *qmfI; + qmfR = qmfSlotReal[i]; + qmfI = qmfSlotImag[i]; + for (ksg = ksg_start; ksg < PVC_NBLOW; ksg++) { + for (band = sg_borders[ksg]; band < sg_borders[ksg + 1]; band++) { + /* The division by 8 == (RATE*lbw) is required algorithmically */ + E[ksg] += + ((fPow2Div2(qmfR[band]) >> 1) + (fPow2Div2(qmfI[band]) >> 1)) >> 3; + } + } + } + for (ksg = ksg_start; ksg < PVC_NBLOW; ksg++) { + if (E[ksg] > (FIXP_DBL)0) { + /* 10/log2(10) = 0.752574989159953 * 2^2 */ + int exp_log; + FIXP_DBL nrg = CalcLog2(E[ksg], 2 * qmfExponent + 2, &exp_log); + nrg = fMult(nrg, FL2FXCONST_SGL(LOG10FAC)); + nrg = scaleValue(nrg, exp_log - PVC_ESG_EXP + 2); + pEsg[ksg] = fMax(nrg, FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP))); + } else { + pEsg[ksg] = + FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP)); /* 10*log10(0.1) */ + } + } + + /* Time domain smoothing of subband-grouped energy */ + { + int idx = pPvcStaticData->Esg_slot_index; + FIXP_DBL *pEsg_filt; + FIXP_SGL SCcoeff; + + E[0] = E[1] = E[2] = (FIXP_DBL)0; + for (i = 0; i < pPvcDynamicData->ns; i++) { + SCcoeff = pPvcDynamicData->pSCcoeffs[i]; + pEsg_filt = pPvcStaticData->Esg[idx]; + /* Div2 is compensated by scaling of coeff table */ + E[0] = fMultAddDiv2(E[0], pEsg_filt[0], SCcoeff); + E[1] = fMultAddDiv2(E[1], pEsg_filt[1], SCcoeff); + E[2] = fMultAddDiv2(E[2], pEsg_filt[2], SCcoeff); + if (i >= pPvcDynamicData->pastEsgSlotsAvail) { + /* if past Esg values are not available use the ones from the last valid + * slot */ + continue; + } + if (idx > 0) { + idx--; + } else { + idx += PVC_NS_MAX - 1; + } + } + } + + /* SBR envelope scalefactor prediction */ + { + int E_high_exp[PVC_NBHIGH_MAX]; + int E_high_exp_max = 0; + int pvcTab1ID; + int pvcTab2ID = (int)pPvcDynamicData->pPvcID[timeSlotNumber]; + const UCHAR *pTab1, *pTab2; + if (pvcTab2ID < pPvcDynamicData->pPVCTab1_dp[0]) { + pvcTab1ID = 0; + } else if (pvcTab2ID < pPvcDynamicData->pPVCTab1_dp[1]) { + pvcTab1ID = 1; + } else { + pvcTab1ID = 2; + } + pTab1 = &(pPvcDynamicData + ->pPVCTab1[pvcTab1ID * PVC_NBLOW * pPvcDynamicData->nbHigh]); + pTab2 = &(pPvcDynamicData->pPVCTab2[pvcTab2ID * pPvcDynamicData->nbHigh]); + for (ksg = 0; ksg < pPvcDynamicData->nbHigh; ksg++) { + FIXP_SGL predCoeff; + FIXP_DBL accu; + int predCoeff_exp, kb; + E_high_exp[ksg] = 0; + + /* residual part */ + accu = ((LONG)(SCHAR)*pTab2++) << (DFRACT_BITS - 8 - PVC_ESG_EXP - 2 + + pPvcDynamicData->pScalingCoef[3]); + + /* linear combination of lower grouped energies part */ + for (kb = 0; kb < PVC_NBLOW; kb++) { + predCoeff = (FIXP_SGL)( + (SHORT)(SCHAR)pTab1[kb * pPvcDynamicData->nbHigh + ksg] << 8); + predCoeff_exp = -(pPvcDynamicData->pScalingCoef[kb] + 1 - + 2); /* +1 to compensate for Div2; -2 for accu */ + accu += fMultDiv2(E[kb], predCoeff) >> predCoeff_exp; + } + /* convert back to linear domain */ + accu = fMult(accu, FL2FXCONST_SGL(LOG10FAC_INV)); + accu = f2Pow(accu, PVC_ESG_EXP - 1 + 2, + &predCoeff_exp); /* -1 compensates for exponent of + LOG10FAC_INV; +2 for accu */ + predictedEsgSlot[ksg] = accu; + E_high_exp[ksg] = predCoeff_exp; + if (predCoeff_exp > E_high_exp_max) { + E_high_exp_max = predCoeff_exp; + } + } + + /* rescale output vector according to largest exponent */ + for (ksg = 0; ksg < pPvcDynamicData->nbHigh; ksg++) { + int scale = fMin(E_high_exp_max - E_high_exp[ksg], DFRACT_BITS - 1); + predictedEsgSlot[ksg] = predictedEsgSlot[ksg] >> scale; + } + *predictedEsg_exp = E_high_exp_max; + } + + pPvcStaticData->Esg_slot_index = + (pPvcStaticData->Esg_slot_index + 1) & (PVC_NS_MAX - 1); + pPvcDynamicData->pastEsgSlotsAvail = + fMin(pPvcDynamicData->pastEsgSlotsAvail + 1, PVC_NS_MAX - 1); + return; +} + +/* call if pvcMode = 0,1,2 */ +void pvcEndFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData) { + pPvcStaticData->pvc_mode_last = pPvcDynamicData->pvc_mode; + pPvcStaticData->kx_last = pPvcDynamicData->kx; + + if (pPvcDynamicData->pvc_mode == 0) return; + + { + int t, max = -100; + for (t = pPvcDynamicData->pvcBorder0; t < PVC_NTIMESLOT; t++) { + if (pPvcDynamicData->predEsg_exp[t] > max) { + max = pPvcDynamicData->predEsg_exp[t]; + } + } + pPvcDynamicData->predEsg_expMax = max; + } + return; +} + +void expandPredEsg(const PVC_DYNAMIC_DATA *pPvcDynamicData, const int timeSlot, + const int lengthOutputVector, FIXP_DBL *pOutput, + SCHAR *pOutput_exp) { + int k = 0, ksg; + const FIXP_DBL *predEsg = pPvcDynamicData->predEsg[timeSlot]; + + for (ksg = 0; ksg < pPvcDynamicData->nbHigh; ksg++) { + for (; k < pPvcDynamicData->sg_offset_high_kx[ksg + 1]; k++) { + pOutput[k] = predEsg[ksg]; + pOutput_exp[k] = (SCHAR)pPvcDynamicData->predEsg_exp[timeSlot]; + } + } + ksg--; + for (; k < lengthOutputVector; k++) { + pOutput[k] = predEsg[ksg]; + pOutput_exp[k] = (SCHAR)pPvcDynamicData->predEsg_exp[timeSlot]; + } + + return; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/pvc_dec.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/pvc_dec.h new file mode 100644 index 0000000000000..f5a467f7fe9d4 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/pvc_dec.h @@ -0,0 +1,238 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: Decode Predictive Vector Coding Data + +*******************************************************************************/ + +#ifndef PVC_DEC_H +#define PVC_DEC_H + +#include "common_fix.h" + +#define PVC_DIVMODE_BITS 3 +#define PVC_REUSEPVCID_BITS 1 +#define PVC_PVCID_BITS 7 +#define PVC_GRIDINFO_BITS 1 + +#define MAX_PVC_ENVELOPES 2 +#define PVC_NTIMESLOT 16 +#define PVC_NBLOW 3 /* max. number of grouped QMF subbands below SBR range */ + +#define PVC_NBHIGH_MODE1 8 +#define PVC_NBHIGH_MODE2 6 +#define PVC_NBHIGH_MAX (PVC_NBHIGH_MODE1) +#define PVC_NS_MAX 16 + +/** Data for each PVC instance which needs to be persistent accross SBR frames + */ +typedef struct { + UCHAR kx_last; /**< Xover frequency of last frame */ + UCHAR pvc_mode_last; /**< PVC mode of last frame */ + UCHAR Esg_slot_index; /**< Ring buffer index to current Esg time slot */ + UCHAR pvcBorder0; /**< Start SBR time slot of PVC frame */ + FIXP_DBL Esg[PVC_NS_MAX][PVC_NBLOW]; /**< Esg(ksg,t) of current and 15 + previous time slots (ring buffer) in + logarithmical domain */ +} PVC_STATIC_DATA; + +/** Data for each PVC instance which is valid during one SBR frame */ +typedef struct { + UCHAR pvc_mode; /**< PVC mode 1 or 2, 0 means legacy SBR */ + UCHAR pvcBorder0; /**< Start SBR time slot of PVC frame */ + UCHAR kx; /**< Index of the first QMF subband in the SBR range */ + UCHAR RATE; /**< Number of QMF subband samples per time slot (2 or 4) */ + UCHAR ns; /**< Number of time slots for time-domain smoothing of Esg(ksg,t) */ + const UCHAR + *pPvcID; /**< Pointer to prediction coefficient matrix index table */ + UCHAR pastEsgSlotsAvail; /**< Number of past Esg(ksg,t) which are available + for smoothing filter */ + const FIXP_SGL *pSCcoeffs; /**< Pointer to smoothing window table */ + SCHAR + sg_offset_low[PVC_NBLOW + 1]; /**< Offset table for PVC grouping of SBR + subbands below SBR range */ + SCHAR sg_offset_high_kx[PVC_NBHIGH_MAX + 1]; /**< Offset table for PVC + grouping of SBR subbands in + SBR range (relativ to kx) */ + UCHAR nbHigh; /**< Number of grouped QMF subbands in the SBR range */ + const SCHAR *pScalingCoef; /**< Pointer to scaling coeff table */ + const UCHAR *pPVCTab1; /**< PVC mode 1 table */ + const UCHAR *pPVCTab2; /**< PVC mode 2 table */ + const UCHAR *pPVCTab1_dp; /**< Mapping of pvcID to PVC mode 1 table */ + FIXP_DBL predEsg[PVC_NTIMESLOT] + [PVC_NBHIGH_MAX]; /**< Predicted Energy in linear domain */ + int predEsg_exp[PVC_NTIMESLOT]; /**< Exponent of predicted Energy in linear + domain */ + int predEsg_expMax; /**< Maximum of predEsg_exp[] */ +} PVC_DYNAMIC_DATA; + +/** + * \brief Initialize PVC data structures for current frame (call if pvcMode = + * 0,1,2) + * \param[in] pPvcStaticData Pointer to PVC persistent data + * \param[out] pPvcDynamicData Pointer to PVC dynamic data + * \param[in] pvcMode PVC mode 1 or 2, 0 means legacy SBR + * \param[in] ns Number of time slots for time-domain smoothing of Esg(ksg,t) + * \param[in] RATE Number of QMF subband samples per time slot (2 or 4) + * \param[in] kx Index of the first QMF subband in the SBR range + * \param[in] pvcBorder0 Start SBR time slot of PVC frame + * \param[in] pPvcID Pointer to array of PvcIDs read from bitstream + */ +int pvcInitFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, const UCHAR pvcMode, + const UCHAR ns, const int RATE, const int kx, + const int pvcBorder0, const UCHAR *pPvcID); + +/** + * \brief Wrapper function for pvcDecodeTimeSlot() to decode PVC data of one + * frame (call if pvcMode = 1,2) + * \param[in,out] pPvcStaticData Pointer to PVC persistent data + * \param[in,out] pPvcDynamicData Pointer to PVC dynamic data + * \param[in] qmfBufferReal Pointer to array with real QMF subbands + * \param[in] qmfBufferImag Pointer to array with imag QMF subbands + * \param[in] overlap Number of QMF overlap slots + * \param[in] qmfExponentOverlap Exponent of qmfBuffer (low part) of overlap + * slots + * \param[in] qmfExponentCurrent Exponent of qmfBuffer (low part) + */ +void pvcDecodeFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, FIXP_DBL **qmfBufferReal, + FIXP_DBL **qmfBufferImag, const int overlap, + const int qmfExponentOverlap, const int qmfExponentCurrent); + +/** + * \brief Decode PVC data for one SBR time slot (call if pvcMode = 1,2) + * \param[in,out] pPvcStaticData Pointer to PVC persistent data + * \param[in,out] pPvcDynamicData Pointer to PVC dynamic data + * \param[in] qmfBufferReal Pointer to array with real QMF subbands + * \param[in] qmfBufferImag Pointer to array with imag QMF subbands + * \param[in] qmfExponent Exponent of qmfBuffer of current time slot + * \param[in] pvcBorder0 Start SBR time slot of PVC frame + * \param[in] timeSlotNumber Number of current SBR time slot (0..15) + * \param[out] predictedEsgSlot Predicted Energy of current time slot + * \param[out] predictedEsg_exp Exponent of predicted Energy of current time + * slot + */ +void pvcDecodeTimeSlot(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, + FIXP_DBL **qmfSlotReal, FIXP_DBL **qmfSlotImag, + const int qmfExponent, const int pvcBorder0, + const int timeSlotNumber, FIXP_DBL predictedEsgSlot[], + int *predictedEsg_exp); + +/** + * \brief Finish the current PVC frame (call if pvcMode = 0,1,2) + * \param[in,out] pPvcStaticData Pointer to PVC persistent data + * \param[in,out] pPvcDynamicData Pointer to PVC dynamic data + */ +void pvcEndFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData); + +/** + * \brief Expand predicted PVC grouped energies to full QMF subband resolution + * \param[in] pPvcDynamicData Pointer to PVC dynamic data + * \param[in] timeSlot Number of current SBR time slot (0..15) + * \param[in] lengthOutputVector Lenght of output vector + * \param[out] pOutput Output array for predicted energies + * \param[out] pOutput_exp Exponent of predicted energies + */ +void expandPredEsg(const PVC_DYNAMIC_DATA *pPvcDynamicData, const int timeSlot, + const int lengthOutputVector, FIXP_DBL *pOutput, + SCHAR *pOutput_exp); + +#endif /* PVC_DEC_H*/ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_deb.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_deb.cpp new file mode 100644 index 0000000000000..13cd211409db7 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_deb.cpp @@ -0,0 +1,108 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Print selected debug messages +*/ + +#include "sbr_deb.h" diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_deb.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_deb.h new file mode 100644 index 0000000000000..97d572a182b1d --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_deb.h @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Debugging aids +*/ + +#ifndef SBR_DEB_H +#define SBR_DEB_H + +#include "sbrdecoder.h" + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_dec.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_dec.cpp new file mode 100644 index 0000000000000..919e9bbb915c6 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_dec.cpp @@ -0,0 +1,1482 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Sbr decoder + This module provides the actual decoder implementation. The SBR data (side + information) is already decoded. Only three functions are provided: + + \li 1.) createSbrDec(): One time initialization + \li 2.) resetSbrDec(): Called by sbr_Apply() when the information contained in + an SBR_HEADER_ELEMENT requires a reset and recalculation of important SBR + structures. \li 3.) sbr_dec(): The actual decoder. Calls the different tools + such as filterbanks, lppTransposer(), and calculateSbrEnvelope() [the envelope + adjuster]. + + \sa sbr_dec(), \ref documentationOverview +*/ + +#include "sbr_dec.h" + +#include "sbr_ram.h" +#include "env_extr.h" +#include "env_calc.h" +#include "scale.h" +#include "FDK_matrixCalloc.h" +#include "hbe.h" + +#include "genericStds.h" + +#include "sbrdec_drc.h" + +static void copyHarmonicSpectrum(int *xOverQmf, FIXP_DBL **qmfReal, + FIXP_DBL **qmfImag, int noCols, int overlap, + KEEP_STATES_SYNCED_MODE keepStatesSynced) { + int patchBands; + int patch, band, col, target, sourceBands, i; + int numPatches = 0; + int slotOffset = 0; + + FIXP_DBL **ppqmfReal = qmfReal + overlap; + FIXP_DBL **ppqmfImag = qmfImag + overlap; + + if (keepStatesSynced == KEEP_STATES_SYNCED_NORMAL) { + slotOffset = noCols - overlap - LPC_ORDER; + } + + if (keepStatesSynced == KEEP_STATES_SYNCED_OUTDIFF) { + ppqmfReal = qmfReal; + ppqmfImag = qmfImag; + } + + for (i = 1; i < MAX_NUM_PATCHES; i++) { + if (xOverQmf[i] != 0) { + numPatches++; + } + } + + for (patch = (MAX_STRETCH_HBE - 1); patch < numPatches; patch++) { + patchBands = xOverQmf[patch + 1] - xOverQmf[patch]; + target = xOverQmf[patch]; + sourceBands = xOverQmf[MAX_STRETCH_HBE - 1] - xOverQmf[MAX_STRETCH_HBE - 2]; + + while (patchBands > 0) { + int numBands = sourceBands; + int startBand = xOverQmf[MAX_STRETCH_HBE - 1] - 1; + if (target + numBands >= xOverQmf[patch + 1]) { + numBands = xOverQmf[patch + 1] - target; + } + if ((((target + numBands - 1) % 2) + + ((xOverQmf[MAX_STRETCH_HBE - 1] - 1) % 2)) % + 2) { + if (numBands == sourceBands) { + numBands--; + } else { + startBand--; + } + } + if (keepStatesSynced == KEEP_STATES_SYNCED_OUTDIFF) { + for (col = slotOffset; col < overlap + LPC_ORDER; col++) { + i = 0; + for (band = numBands; band > 0; band--) { + if ((target + band - 1 < 64) && + (target + band - 1 < xOverQmf[patch + 1])) { + ppqmfReal[col][target + band - 1] = ppqmfReal[col][startBand - i]; + ppqmfImag[col][target + band - 1] = ppqmfImag[col][startBand - i]; + i++; + } + } + } + } else { + for (col = slotOffset; col < noCols; col++) { + i = 0; + for (band = numBands; band > 0; band--) { + if ((target + band - 1 < 64) && + (target + band - 1 < xOverQmf[patch + 1])) { + ppqmfReal[col][target + band - 1] = ppqmfReal[col][startBand - i]; + ppqmfImag[col][target + band - 1] = ppqmfImag[col][startBand - i]; + i++; + } + } + } + } + target += numBands; + patchBands -= numBands; + } + } +} + +/*! + \brief SBR decoder core function for one channel + + \image html BufferMgmtDetailed-1632.png + + Besides the filter states of the QMF filter bank and the LPC-states of + the LPP-Transposer, processing is mainly based on four buffers: + #timeIn, #timeOut, #WorkBuffer2 and #OverlapBuffer. The #WorkBuffer2 + is reused for all channels and might be used by the core decoder, a + static overlap buffer is required for each channel. Due to in-place + processing, #timeIn and #timeOut point to identical locations. + + The spectral data is organized in so-called slots. Each slot + contains 64 bands of complex data. The number of slots per frame + depends on the frame size. For mp3PRO, there are 18 slots per frame + and 6 slots per #OverlapBuffer. It is not necessary to have the slots + in located consecutive address ranges. + + To optimize memory usage and to minimize the number of memory + accesses, the memory management is organized as follows (slot numbers + based on mp3PRO): + + 1.) Input time domain signal is located in #timeIn. The last slots + (0..5) of the spectral data of the previous frame are located in the + #OverlapBuffer. In addition, #frameData of the current frame resides + in the upper part of #timeIn. + + 2.) During the cplxAnalysisQmfFiltering(), 32 samples from #timeIn are + transformed into a slot of up to 32 complex spectral low band values at a + time. The first spectral slot -- nr. 6 -- is written at slot number + zero of #WorkBuffer2. #WorkBuffer2 will be completely filled with + spectral data. + + 3.) LPP-Transposition in lppTransposer() is processed on 24 slots. During the + transposition, the high band part of the spectral data is replicated + based on the low band data. + + Envelope Adjustment is processed on the high band part of the spectral + data only by calculateSbrEnvelope(). + + 4.) The cplxSynthesisQmfFiltering() creates 64 time domain samples out + of a slot of 64 complex spectral values at a time. The first 6 slots + in #timeOut are filled from the results of spectral slots 0..5 in the + #OverlapBuffer. The consecutive slots in timeOut are now filled with + the results of spectral slots 6..17. + + 5.) The preprocessed slots 18..23 have to be stored in the + #OverlapBuffer. + +*/ + +void sbr_dec( + HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ + LONG *timeIn, /*!< pointer to input time signal */ + LONG *timeOut, /*!< pointer to output time signal */ + HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ + LONG *timeOutRight, /*!< pointer to output time signal */ + const int strideOut, /*!< Time data traversal strideOut */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + HANDLE_SBR_PREV_FRAME_DATA + hPrevFrameData, /*!< Some control data of last frame */ + const int applyProcessing, /*!< Flag for SBR operation */ + HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize, + const INT sbrInDataHeadroom) { + int i, slot, reserve; + int saveLbScale; + int lastSlotOffs; + FIXP_DBL maxVal; + + /* temporary pointer / variable for QMF; + required as we want to use temporary buffer + creating one frame delay for HBE in LP mode */ + LONG *pTimeInQmf = timeIn; + + /* Number of QMF timeslots in the overlap buffer: */ + int ov_len = hSbrDec->LppTrans.pSettings->overlap; + + /* Number of QMF slots per frame */ + int noCols = hHeaderData->numberTimeSlots * hHeaderData->timeStep; + + /* create pointer array for data to use for HBE and legacy sbr */ + FIXP_DBL *pLowBandReal[(3 * 4) + 2 * ((1024) / (32) * (4) / 2)]; + FIXP_DBL *pLowBandImag[(3 * 4) + 2 * ((1024) / (32) * (4) / 2)]; + + /* set pReal to where QMF analysis writes in case of legacy SBR */ + FIXP_DBL **pReal = pLowBandReal + ov_len; + FIXP_DBL **pImag = pLowBandImag + ov_len; + + /* map QMF buffer to pointer array (Overlap + Frame)*/ + for (i = 0; i < noCols + ov_len; i++) { + pLowBandReal[i] = hSbrDec->qmfDomainInCh->hQmfSlotsReal[i]; + pLowBandImag[i] = hSbrDec->qmfDomainInCh->hQmfSlotsImag[i]; + } + + if ((flags & SBRDEC_USAC_HARMONICSBR)) { + /* in case of harmonic SBR and no HBE_LP map additional buffer for + one more frame to pointer arry */ + for (i = 0; i < noCols; i++) { + pLowBandReal[i + noCols + ov_len] = hSbrDec->hQmfHBESlotsReal[i]; + pLowBandImag[i + noCols + ov_len] = hSbrDec->hQmfHBESlotsImag[i]; + } + + /* shift scale values according to buffer */ + hSbrDec->scale_ov = hSbrDec->scale_lb; + hSbrDec->scale_lb = hSbrDec->scale_hbe; + + /* set pReal to where QMF analysis writes in case of HBE */ + pReal += noCols; + pImag += noCols; + if (flags & SBRDEC_SKIP_QMF_ANA) { + /* stereoCfgIndex3 with HBE */ + FDK_QmfDomain_QmfData2HBE(hSbrDec->qmfDomainInCh, + hSbrDec->hQmfHBESlotsReal, + hSbrDec->hQmfHBESlotsImag); + } else { + /* We have to move old hbe frame data to lb area of buffer */ + for (i = 0; i < noCols; i++) { + FDKmemcpy(pLowBandReal[ov_len + i], hSbrDec->hQmfHBESlotsReal[i], + hHeaderData->numberOfAnalysisBands * sizeof(FIXP_DBL)); + FDKmemcpy(pLowBandImag[ov_len + i], hSbrDec->hQmfHBESlotsImag[i], + hHeaderData->numberOfAnalysisBands * sizeof(FIXP_DBL)); + } + } + } + + /* + low band codec signal subband filtering + */ + + if (flags & SBRDEC_SKIP_QMF_ANA) { + if (!(flags & SBRDEC_USAC_HARMONICSBR)) /* stereoCfgIndex3 w/o HBE */ + FDK_QmfDomain_WorkBuffer2ProcChannel(hSbrDec->qmfDomainInCh); + } else { + C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * (64)); + qmfAnalysisFiltering(&hSbrDec->qmfDomainInCh->fb, pReal, pImag, + &hSbrDec->qmfDomainInCh->scaling, pTimeInQmf, + 0 + sbrInDataHeadroom, 1, qmfTemp); + + C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * (64)); + } + + /* + Clear upper half of spectrum + */ + if (!((flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode == 0))) { + int nAnalysisBands = hHeaderData->numberOfAnalysisBands; + + if (!(flags & SBRDEC_LOW_POWER)) { + for (slot = ov_len; slot < noCols + ov_len; slot++) { + FDKmemclear(&pLowBandReal[slot][nAnalysisBands], + ((64) - nAnalysisBands) * sizeof(FIXP_DBL)); + FDKmemclear(&pLowBandImag[slot][nAnalysisBands], + ((64) - nAnalysisBands) * sizeof(FIXP_DBL)); + } + } else { + for (slot = ov_len; slot < noCols + ov_len; slot++) { + FDKmemclear(&pLowBandReal[slot][nAnalysisBands], + ((64) - nAnalysisBands) * sizeof(FIXP_DBL)); + } + } + } + + /* + Shift spectral data left to gain accuracy in transposer and adjustor + */ + /* Range was increased from lsb to no_channels because in some cases (e.g. + USAC conf eSbr_4_Pvc.mp4 and some HBE cases) it could be observed that the + signal between lsb and no_channels is used for the patching process. + */ + maxVal = maxSubbandSample(pReal, (flags & SBRDEC_LOW_POWER) ? NULL : pImag, 0, + hSbrDec->qmfDomainInCh->fb.no_channels, 0, noCols); + + reserve = fixMax(0, CntLeadingZeros(maxVal) - 1); + reserve = fixMin(reserve, + DFRACT_BITS - 1 - hSbrDec->qmfDomainInCh->scaling.lb_scale); + + /* If all data is zero, lb_scale could become too large */ + rescaleSubbandSamples(pReal, (flags & SBRDEC_LOW_POWER) ? NULL : pImag, 0, + hSbrDec->qmfDomainInCh->fb.no_channels, 0, noCols, + reserve); + + hSbrDec->qmfDomainInCh->scaling.lb_scale += reserve; + + if ((flags & SBRDEC_USAC_HARMONICSBR)) { + /* actually this is our hbe_scale */ + hSbrDec->scale_hbe = hSbrDec->qmfDomainInCh->scaling.lb_scale; + /* the real lb_scale is stored in scale_lb from sbr */ + hSbrDec->qmfDomainInCh->scaling.lb_scale = hSbrDec->scale_lb; + } + /* + save low band scale, wavecoding or parametric stereo may modify it + */ + saveLbScale = hSbrDec->qmfDomainInCh->scaling.lb_scale; + + if (applyProcessing) { + UCHAR *borders = hFrameData->frameInfo.borders; + lastSlotOffs = borders[hFrameData->frameInfo.nEnvelopes] - + hHeaderData->numberTimeSlots; + + FIXP_DBL degreeAlias[(64)]; + PVC_DYNAMIC_DATA pvcDynamicData; + pvcInitFrame( + &hSbrDec->PvcStaticData, &pvcDynamicData, + (hHeaderData->frameErrorFlag ? 0 : hHeaderData->bs_info.pvc_mode), + hFrameData->ns, hHeaderData->timeStep, + hHeaderData->freqBandData.lowSubband, + hFrameData->frameInfo.pvcBorders[0], hFrameData->pvcID); + + if (!hHeaderData->frameErrorFlag && (hHeaderData->bs_info.pvc_mode > 0)) { + pvcDecodeFrame(&hSbrDec->PvcStaticData, &pvcDynamicData, pLowBandReal, + pLowBandImag, ov_len, + SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale), + SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.lb_scale)); + } + pvcEndFrame(&hSbrDec->PvcStaticData, &pvcDynamicData); + + /* The transposer will override most values in degreeAlias[]. + The array needs to be cleared at least from lowSubband to highSubband + before. */ + if (flags & SBRDEC_LOW_POWER) + FDKmemclear(°reeAlias[hHeaderData->freqBandData.lowSubband], + (hHeaderData->freqBandData.highSubband - + hHeaderData->freqBandData.lowSubband) * + sizeof(FIXP_DBL)); + + /* + Inverse filtering of lowband and transposition into the SBR-frequency + range + */ + + { + KEEP_STATES_SYNCED_MODE keepStatesSyncedMode = + ((flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode != 0)) + ? KEEP_STATES_SYNCED_NORMAL + : KEEP_STATES_SYNCED_OFF; + + if (flags & SBRDEC_USAC_HARMONICSBR) { + if (flags & SBRDEC_QUAD_RATE) { + pReal -= 32; + pImag -= 32; + } + + if ((hSbrDec->savedStates == 0) && (hFrameData->sbrPatchingMode == 1)) { + /* copy saved states from previous frame to legacy SBR lpc filterstate + * buffer */ + for (i = 0; i < LPC_ORDER + ov_len; i++) { + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + hSbrDec->codecQMFBufferReal[noCols - LPC_ORDER - ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], + hSbrDec->codecQMFBufferImag[noCols - LPC_ORDER - ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + } + } + + /* saving unmodified QMF states in case we are switching from legacy SBR + * to HBE */ + for (i = 0; i < hSbrDec->hHBE->noCols; i++) { + FDKmemcpy(hSbrDec->codecQMFBufferReal[i], pLowBandReal[ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->codecQMFBufferImag[i], pLowBandImag[ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + } + + QmfTransposerApply( + hSbrDec->hHBE, pReal, pImag, noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + hFrameData->sbrPitchInBins, hSbrDec->scale_lb, hSbrDec->scale_hbe, + &hSbrDec->qmfDomainInCh->scaling.hb_scale, hHeaderData->timeStep, + borders[0], ov_len, keepStatesSyncedMode); + + if (flags & SBRDEC_QUAD_RATE) { + int *xOverQmf = GetxOverBandQmfTransposer(hSbrDec->hHBE); + + copyHarmonicSpectrum(xOverQmf, pLowBandReal, pLowBandImag, noCols, + ov_len, keepStatesSyncedMode); + } + } + } + + if ((flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode == 0)) { + hSbrDec->prev_frame_lSbr = 0; + hSbrDec->prev_frame_hbeSbr = 1; + + lppTransposerHBE( + &hSbrDec->LppTrans, hSbrDec->hHBE, &hSbrDec->qmfDomainInCh->scaling, + pLowBandReal, pLowBandImag, hHeaderData->timeStep, borders[0], + lastSlotOffs, hHeaderData->freqBandData.nInvfBands, + hFrameData->sbr_invf_mode, hPrevFrameData->sbr_invf_mode); + + } else { + if (flags & SBRDEC_USAC_HARMONICSBR) { + for (i = 0; i < LPC_ORDER + hSbrDec->LppTrans.pSettings->overlap; i++) { + /* + Store the unmodified qmf Slots values for upper part of spectrum + (required for LPC filtering) required if next frame is a HBE frame + */ + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealHBE[i], + hSbrDec->qmfDomainInCh + ->hQmfSlotsReal[hSbrDec->hHBE->noCols - LPC_ORDER + i], + (64) * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImagHBE[i], + hSbrDec->qmfDomainInCh + ->hQmfSlotsImag[hSbrDec->hHBE->noCols - LPC_ORDER + i], + (64) * sizeof(FIXP_DBL)); + } + } + { + hSbrDec->prev_frame_lSbr = 1; + hSbrDec->prev_frame_hbeSbr = 0; + } + + lppTransposer( + &hSbrDec->LppTrans, &hSbrDec->qmfDomainInCh->scaling, pLowBandReal, + degreeAlias, // only used if useLP = 1 + pLowBandImag, flags & SBRDEC_LOW_POWER, + hHeaderData->bs_info.sbr_preprocessing, + hHeaderData->freqBandData.v_k_master[0], hHeaderData->timeStep, + borders[0], lastSlotOffs, hHeaderData->freqBandData.nInvfBands, + hFrameData->sbr_invf_mode, hPrevFrameData->sbr_invf_mode); + } + + /* + Adjust envelope of current frame. + */ + + if ((hFrameData->sbrPatchingMode != + hSbrDec->SbrCalculateEnvelope.sbrPatchingMode)) { + ResetLimiterBands(hHeaderData->freqBandData.limiterBandTable, + &hHeaderData->freqBandData.noLimiterBands, + hHeaderData->freqBandData.freqBandTable[0], + hHeaderData->freqBandData.nSfb[0], + hSbrDec->LppTrans.pSettings->patchParam, + hSbrDec->LppTrans.pSettings->noOfPatches, + hHeaderData->bs_data.limiterBands, + hFrameData->sbrPatchingMode, + (flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode == 0) + ? GetxOverBandQmfTransposer(hSbrDec->hHBE) + : NULL, + Get41SbrQmfTransposer(hSbrDec->hHBE)); + + hSbrDec->SbrCalculateEnvelope.sbrPatchingMode = + hFrameData->sbrPatchingMode; + } + + calculateSbrEnvelope( + &hSbrDec->qmfDomainInCh->scaling, &hSbrDec->SbrCalculateEnvelope, + hHeaderData, hFrameData, &pvcDynamicData, pLowBandReal, pLowBandImag, + flags & SBRDEC_LOW_POWER, + + degreeAlias, flags, + (hHeaderData->frameErrorFlag || hPrevFrameData->frameErrorFlag)); + +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + /* Avoid hard onsets of high band */ + if (hHeaderData->frameErrorFlag) { + if (hSbrDec->highBandFadeCnt < SBRDEC_MAX_HB_FADE_FRAMES) { + hSbrDec->highBandFadeCnt += 1; + } + } else { + if (hSbrDec->highBandFadeCnt > + 0) { /* Manipulate high band scale factor to get a smooth fade-in */ + hSbrDec->qmfDomainInCh->scaling.hb_scale += hSbrDec->highBandFadeCnt; + hSbrDec->qmfDomainInCh->scaling.hb_scale = + fMin(hSbrDec->qmfDomainInCh->scaling.hb_scale, DFRACT_BITS - 1); + hSbrDec->highBandFadeCnt -= 1; + } + } + +#endif + /* + Update hPrevFrameData (to be used in the next frame) + */ + for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) { + hPrevFrameData->sbr_invf_mode[i] = hFrameData->sbr_invf_mode[i]; + } + hPrevFrameData->coupling = hFrameData->coupling; + hPrevFrameData->stopPos = borders[hFrameData->frameInfo.nEnvelopes]; + hPrevFrameData->ampRes = hFrameData->ampResolutionCurrentFrame; + hPrevFrameData->prevSbrPitchInBins = hFrameData->sbrPitchInBins; + /* could be done in extractFrameInfo_pvc() but hPrevFrameData is not + * available there */ + FDKmemcpy(&hPrevFrameData->prevFrameInfo, &hFrameData->frameInfo, + sizeof(FRAME_INFO)); + } else { + /* rescale from lsb to nAnalysisBands in order to compensate scaling with + * hb_scale in this area, done by synthesisFiltering*/ + int rescale; + int lsb; + int length; + + /* Reset hb_scale if no highband is present, because hb_scale is considered + * in the QMF-synthesis */ + hSbrDec->qmfDomainInCh->scaling.hb_scale = saveLbScale; + + rescale = hSbrDec->qmfDomainInCh->scaling.hb_scale - + hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + lsb = hSbrDec->qmfDomainOutCh->fb.lsb; + length = (hSbrDec->qmfDomainInCh->fb.no_channels - lsb); + + if ((rescale < 0) && (length > 0)) { + if (!(flags & SBRDEC_LOW_POWER)) { + for (i = 0; i < ov_len; i++) { + scaleValues(&pLowBandReal[i][lsb], length, rescale); + scaleValues(&pLowBandImag[i][lsb], length, rescale); + } + } else { + for (i = 0; i < ov_len; i++) { + scaleValues(&pLowBandReal[i][lsb], length, rescale); + } + } + } + } + + if (!(flags & SBRDEC_USAC_HARMONICSBR)) { + int length = hSbrDec->qmfDomainInCh->fb.lsb; + if (flags & SBRDEC_SYNTAX_USAC) { + length = hSbrDec->qmfDomainInCh->fb.no_channels; + } + + /* in case of legacy sbr saving of filter states here */ + for (i = 0; i < LPC_ORDER + ov_len; i++) { + /* + Store the unmodified qmf Slots values (required for LPC filtering) + */ + if (!(flags & SBRDEC_LOW_POWER)) { + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + pLowBandReal[noCols - LPC_ORDER + i], + length * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], + pLowBandImag[noCols - LPC_ORDER + i], + length * sizeof(FIXP_DBL)); + } else + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + pLowBandReal[noCols - LPC_ORDER + i], + length * sizeof(FIXP_DBL)); + } + } + + /* + Synthesis subband filtering. + */ + + if (!(flags & SBRDEC_PS_DECODED)) { + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + int outScalefactor = -(8); + + if (h_ps_d != NULL) { + h_ps_d->procFrameBased = 1; /* we here do frame based processing */ + } + + sbrDecoder_drcApply(&hSbrDec->sbrDrcChannel, pLowBandReal, + (flags & SBRDEC_LOW_POWER) ? NULL : pLowBandImag, + hSbrDec->qmfDomainOutCh->fb.no_col, &outScalefactor); + + qmfChangeOutScalefactor(&hSbrDec->qmfDomainOutCh->fb, outScalefactor); + + { + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + int save_usb = hSbrDec->qmfDomainOutCh->fb.usb; + +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_START(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif + if (hSbrDec->qmfDomainOutCh->fb.usb < hFreq->ov_highSubband) { + /* we need to patch usb for this frame as overlap may contain higher + frequency range if headerchange occured; fb. usb is always limited + to maximum fb.no_channels; In case of wrongly decoded headers it + might be that ov_highSubband is higher than the number of synthesis + channels (fb.no_channels), which is forbidden, therefore we need to + limit ov_highSubband with fMin function to avoid not allowed usb in + synthesis filterbank. */ + hSbrDec->qmfDomainOutCh->fb.usb = + fMin((UINT)hFreq->ov_highSubband, + (UINT)hSbrDec->qmfDomainOutCh->fb.no_channels); + } + { + qmfSynthesisFiltering( + &hSbrDec->qmfDomainOutCh->fb, pLowBandReal, + (flags & SBRDEC_LOW_POWER) ? NULL : pLowBandImag, + &hSbrDec->qmfDomainInCh->scaling, + hSbrDec->LppTrans.pSettings->overlap, timeOut, strideOut, + qmfTemp); + } + /* restore saved value */ + hSbrDec->qmfDomainOutCh->fb.usb = save_usb; + hFreq->ov_highSubband = save_usb; +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_END(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif + } + } + + } else { /* (flags & SBRDEC_PS_DECODED) */ + INT sdiff; + INT scaleFactorHighBand, scaleFactorLowBand_ov, scaleFactorLowBand_no_ov, + outScalefactor, outScalefactorR, outScalefactorL; + + HANDLE_QMF_FILTER_BANK synQmf = &hSbrDec->qmfDomainOutCh->fb; + HANDLE_QMF_FILTER_BANK synQmfRight = &hSbrDecRight->qmfDomainOutCh->fb; + + /* adapt scaling */ + sdiff = hSbrDec->qmfDomainInCh->scaling.lb_scale - + reserve; /* Scaling difference */ + scaleFactorHighBand = sdiff - hSbrDec->qmfDomainInCh->scaling.hb_scale; + scaleFactorLowBand_ov = sdiff - hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + scaleFactorLowBand_no_ov = sdiff - hSbrDec->qmfDomainInCh->scaling.lb_scale; + + /* Scale of low band overlapping QMF data */ + scaleFactorLowBand_ov = + fMin(DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorLowBand_ov)); + /* Scale of low band current QMF data */ + scaleFactorLowBand_no_ov = fMin( + DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorLowBand_no_ov)); + /* Scale of current high band */ + scaleFactorHighBand = + fMin(DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorHighBand)); + + if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot + based processing copy filter states */ + { /* procFrameBased will be unset later */ + /* copy filter states from left to right */ + /* was ((640)-(64))*sizeof(FIXP_QSS) + flexible amount of synthesis bands needed for QMF based resampling + */ + FDK_ASSERT(hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis <= + QMF_MAX_SYNTHESIS_BANDS); + synQmfRight->outScalefactor = synQmf->outScalefactor; + FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates, + 9 * hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis * + sizeof(FIXP_QSS)); + } + + /* Feed delaylines when parametric stereo is switched on. */ + PreparePsProcessing(h_ps_d, pLowBandReal, pLowBandImag, + scaleFactorLowBand_ov); + + /* use the same synthese qmf values for left and right channel */ + synQmfRight->no_col = synQmf->no_col; + synQmfRight->lsb = synQmf->lsb; + synQmfRight->usb = synQmf->usb; + + int env = 0; + + { +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, + 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_START(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif + + int maxShift = 0; + + if (hSbrDec->sbrDrcChannel.enable != 0) { + if (hSbrDec->sbrDrcChannel.prevFact_exp > maxShift) { + maxShift = hSbrDec->sbrDrcChannel.prevFact_exp; + } + if (hSbrDec->sbrDrcChannel.currFact_exp > maxShift) { + maxShift = hSbrDec->sbrDrcChannel.currFact_exp; + } + if (hSbrDec->sbrDrcChannel.nextFact_exp > maxShift) { + maxShift = hSbrDec->sbrDrcChannel.nextFact_exp; + } + } + + /* copy DRC data to right channel (with PS both channels use the same DRC + * gains) */ + FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel, + sizeof(SBRDEC_DRC_CHANNEL)); + + outScalefactor = maxShift - (8); + outScalefactorL = outScalefactorR = + sbrInDataHeadroom + 1; /* +1: psDiffScale! (MPEG-PS) */ + + for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */ + + /* qmf timeslot of right channel */ + FIXP_DBL *rQmfReal = pWorkBuffer; + FIXP_DBL *rQmfImag = pWorkBuffer + synQmf->no_channels; + + { + if (i == + h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env]) { + initSlotBasedRotation(h_ps_d, env, + hHeaderData->freqBandData.highSubband); + env++; + } + + ApplyPsSlot( + h_ps_d, /* parametric stereo decoder handle */ + (pLowBandReal + i), /* one timeslot of left/mono channel */ + (pLowBandImag + i), /* one timeslot of left/mono channel */ + rQmfReal, /* one timeslot or right channel */ + rQmfImag, /* one timeslot or right channel */ + scaleFactorLowBand_no_ov, + (i < hSbrDec->LppTrans.pSettings->overlap) + ? scaleFactorLowBand_ov + : scaleFactorLowBand_no_ov, + scaleFactorHighBand, synQmf->lsb, synQmf->usb); + } + + sbrDecoder_drcApplySlot(/* right channel */ + &hSbrDecRight->sbrDrcChannel, rQmfReal, + rQmfImag, i, synQmfRight->no_col, maxShift); + + sbrDecoder_drcApplySlot(/* left channel */ + &hSbrDec->sbrDrcChannel, *(pLowBandReal + i), + *(pLowBandImag + i), i, synQmf->no_col, + maxShift); + + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + qmfChangeOutScalefactor(synQmf, outScalefactor); + qmfChangeOutScalefactor(synQmfRight, outScalefactor); + + qmfSynthesisFilteringSlot( + synQmfRight, rQmfReal, /* QMF real buffer */ + rQmfImag, /* QMF imag buffer */ + outScalefactorL, outScalefactorL, + timeOutRight + (i * synQmf->no_channels * strideOut), strideOut, + pWorkBuffer); + + qmfSynthesisFilteringSlot( + synQmf, *(pLowBandReal + i), /* QMF real buffer */ + *(pLowBandImag + i), /* QMF imag buffer */ + outScalefactorR, outScalefactorR, + timeOut + (i * synQmf->no_channels * strideOut), strideOut, + pWorkBuffer); + } + } /* no_col loop i */ +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_END(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif + } + } + + sbrDecoder_drcUpdateChannel(&hSbrDec->sbrDrcChannel); + + /* + Update overlap buffer + Even bands above usb are copied to avoid outdated spectral data in case + the stop frequency raises. + */ + + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + { + FDK_QmfDomain_SaveOverlap(hSbrDec->qmfDomainInCh, 0); + FDK_ASSERT(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale == saveLbScale); + } + } + + hSbrDec->savedStates = 0; + + /* Save current frame status */ + hPrevFrameData->frameErrorFlag = hHeaderData->frameErrorFlag; + hSbrDec->applySbrProc_old = applyProcessing; + +} /* sbr_dec() */ + +/*! + \brief Creates sbr decoder structure + \return errorCode, 0 if successful +*/ +SBR_ERROR +createSbrDec(SBR_CHANNEL *hSbrChannel, + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + TRANSPOSER_SETTINGS *pSettings, + const int downsampleFac, /*!< Downsampling factor */ + const UINT qmfFlags, /*!< flags -> 1: HQ/LP selector, 2: CLDFB */ + const UINT flags, const int overlap, + int chan, /*!< Channel for which to assign buffers etc. */ + int codecFrameSize) + +{ + SBR_ERROR err = SBRDEC_OK; + int timeSlots = + hHeaderData->numberTimeSlots; /* Number of SBR slots per frame */ + int noCols = + timeSlots * hHeaderData->timeStep; /* Number of QMF slots per frame */ + HANDLE_SBR_DEC hs = &(hSbrChannel->SbrDec); + +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + hs->highBandFadeCnt = SBRDEC_MAX_HB_FADE_FRAMES; + +#endif + hs->scale_hbe = 15; + hs->scale_lb = 15; + hs->scale_ov = 15; + + hs->prev_frame_lSbr = 0; + hs->prev_frame_hbeSbr = 0; + + hs->codecFrameSize = codecFrameSize; + + /* + create envelope calculator + */ + err = createSbrEnvelopeCalc(&hs->SbrCalculateEnvelope, hHeaderData, chan, + flags); + if (err != SBRDEC_OK) { + return err; + } + + initSbrPrevFrameData(&hSbrChannel->prevFrameData, timeSlots); + + /* + create transposer + */ + err = createLppTransposer( + &hs->LppTrans, pSettings, hHeaderData->freqBandData.lowSubband, + hHeaderData->freqBandData.v_k_master, hHeaderData->freqBandData.numMaster, + hHeaderData->freqBandData.highSubband, timeSlots, noCols, + hHeaderData->freqBandData.freqBandTableNoise, + hHeaderData->freqBandData.nNfb, hHeaderData->sbrProcSmplRate, chan, + overlap); + if (err != SBRDEC_OK) { + return err; + } + + if (flags & SBRDEC_USAC_HARMONICSBR) { + int noChannels, bSbr41 = flags & SBRDEC_QUAD_RATE ? 1 : 0; + + noChannels = + QMF_SYNTH_CHANNELS / + ((bSbr41 + 1) * 2); /* 32 for (32:64 and 24:64) and 16 for 16:64 */ + + /* shared memory between hbeLightTimeDelayBuffer and hQmfHBESlotsReal if + * SBRDEC_HBE_ENABLE */ + hSbrChannel->SbrDec.tmp_memory = (FIXP_DBL **)fdkCallocMatrix2D_aligned( + noCols, noChannels, sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.tmp_memory == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + hSbrChannel->SbrDec.hQmfHBESlotsReal = hSbrChannel->SbrDec.tmp_memory; + hSbrChannel->SbrDec.hQmfHBESlotsImag = + (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels, + sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.hQmfHBESlotsImag == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + /* buffers containing unmodified qmf data; required when switching from + * legacy SBR to HBE */ + /* buffer can be used as LPCFilterstates buffer because legacy SBR needs + * exactly these values for LPC filtering */ + hSbrChannel->SbrDec.codecQMFBufferReal = + (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels, + sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.codecQMFBufferReal == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + hSbrChannel->SbrDec.codecQMFBufferImag = + (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels, + sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.codecQMFBufferImag == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + err = QmfTransposerCreate(&hs->hHBE, codecFrameSize, 0, bSbr41); + if (err != SBRDEC_OK) { + return err; + } + } + + return err; +} + +/*! + \brief Delete sbr decoder structure + \return errorCode, 0 if successful +*/ +int deleteSbrDec(SBR_CHANNEL *hSbrChannel) { + HANDLE_SBR_DEC hs = &hSbrChannel->SbrDec; + + deleteSbrEnvelopeCalc(&hs->SbrCalculateEnvelope); + + if (hs->tmp_memory != NULL) { + FDK_FREE_MEMORY_2D_ALIGNED(hs->tmp_memory); + } + + /* modify here */ + FDK_FREE_MEMORY_2D_ALIGNED(hs->hQmfHBESlotsImag); + + if (hs->hHBE != NULL) QmfTransposerClose(hs->hHBE); + + if (hs->codecQMFBufferReal != NULL) { + FDK_FREE_MEMORY_2D_ALIGNED(hs->codecQMFBufferReal); + } + + if (hs->codecQMFBufferImag != NULL) { + FDK_FREE_MEMORY_2D_ALIGNED(hs->codecQMFBufferImag); + } + + return 0; +} + +/*! + \brief resets sbr decoder structure + \return errorCode, 0 if successful +*/ +SBR_ERROR +resetSbrDec(HANDLE_SBR_DEC hSbrDec, HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, const int downsampleFac, + const UINT flags, HANDLE_SBR_FRAME_DATA hFrameData) { + SBR_ERROR sbrError = SBRDEC_OK; + int i; + FIXP_DBL *pLowBandReal[128]; + FIXP_DBL *pLowBandImag[128]; + int useLP = flags & SBRDEC_LOW_POWER; + + int old_lsb = hSbrDec->qmfDomainInCh->fb.lsb; + int old_usb = hSbrDec->qmfDomainInCh->fb.usb; + int new_lsb = hHeaderData->freqBandData.lowSubband; + /* int new_usb = hHeaderData->freqBandData.highSubband; */ + int l, startBand, stopBand, startSlot, size; + + FIXP_DBL **OverlapBufferReal = hSbrDec->qmfDomainInCh->hQmfSlotsReal; + FIXP_DBL **OverlapBufferImag = hSbrDec->qmfDomainInCh->hQmfSlotsImag; + + /* in case the previous frame was not active in terms of SBR processing, the + full band from 0 to no_channels was rescaled and not overwritten. Thats why + the scaling factor lb_scale can be seen as assigned to all bands from 0 to + no_channels in the previous frame. The same states for the current frame if + the current frame is not active in terms of SBR processing + */ + int applySbrProc = (hHeaderData->syncState == SBR_ACTIVE || + (hHeaderData->frameErrorFlag == 0 && + hHeaderData->syncState == SBR_HEADER)); + int applySbrProc_old = hSbrDec->applySbrProc_old; + + if (!applySbrProc) { + new_lsb = (hSbrDec->qmfDomainInCh->fb).no_channels; + } + if (!applySbrProc_old) { + old_lsb = (hSbrDec->qmfDomainInCh->fb).no_channels; + old_usb = old_lsb; + } + + resetSbrEnvelopeCalc(&hSbrDec->SbrCalculateEnvelope); + + /* Change lsb and usb */ + /* Synthesis */ + FDK_ASSERT(hSbrDec->qmfDomainOutCh != NULL); + hSbrDec->qmfDomainOutCh->fb.lsb = + fixMin((INT)hSbrDec->qmfDomainOutCh->fb.no_channels, + (INT)hHeaderData->freqBandData.lowSubband); + hSbrDec->qmfDomainOutCh->fb.usb = + fixMin((INT)hSbrDec->qmfDomainOutCh->fb.no_channels, + (INT)hHeaderData->freqBandData.highSubband); + /* Analysis */ + FDK_ASSERT(hSbrDec->qmfDomainInCh != NULL); + hSbrDec->qmfDomainInCh->fb.lsb = hSbrDec->qmfDomainOutCh->fb.lsb; + hSbrDec->qmfDomainInCh->fb.usb = hSbrDec->qmfDomainOutCh->fb.usb; + + /* + The following initialization of spectral data in the overlap buffer + is required for dynamic x-over or a change of the start-freq for 2 reasons: + + 1. If the lowband gets _wider_, unadjusted data would remain + + 2. If the lowband becomes _smaller_, the highest bands of the old lowband + must be cleared because the whitening would be affected + */ + startBand = old_lsb; + stopBand = new_lsb; + startSlot = fMax(0, hHeaderData->timeStep * (hPrevFrameData->stopPos - + hHeaderData->numberTimeSlots)); + size = fMax(0, stopBand - startBand); + + /* in case of USAC we don't want to zero out the memory, as this can lead to + holes in the spectrum; fix shall only be applied for USAC not for MPEG-4 + SBR, in this case setting zero remains */ + if (!(flags & SBRDEC_SYNTAX_USAC)) { + /* keep already adjusted data in the x-over-area */ + if (!useLP) { + for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) { + FDKmemclear(&OverlapBufferReal[l][startBand], size * sizeof(FIXP_DBL)); + FDKmemclear(&OverlapBufferImag[l][startBand], size * sizeof(FIXP_DBL)); + } + } else { + for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) { + FDKmemclear(&OverlapBufferReal[l][startBand], size * sizeof(FIXP_DBL)); + } + } + + /* + reset LPC filter states + */ + startBand = fixMin(old_lsb, new_lsb); + stopBand = fixMax(old_lsb, new_lsb); + size = fixMax(0, stopBand - startBand); + + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[0][startBand], + size * sizeof(FIXP_DBL)); + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[1][startBand], + size * sizeof(FIXP_DBL)); + if (!useLP) { + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[0][startBand], + size * sizeof(FIXP_DBL)); + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[1][startBand], + size * sizeof(FIXP_DBL)); + } + } + + if (startSlot != 0) { + int source_exp, target_exp, delta_exp, target_lsb, target_usb, reserve; + FIXP_DBL maxVal; + + /* + Rescale already processed spectral data between old and new x-over + frequency. This must be done because of the separate scalefactors for + lowband and highband. + */ + + /* We have four relevant transitions to cover: + 1. old_usb is lower than new_lsb; old SBR area is completely below new SBR + area. + -> entire old area was highband and belongs to lowband now + and has to be rescaled. + 2. old_lsb is higher than new_usb; new SBR area is completely below old SBR + area. + -> old area between new_lsb and old_lsb was lowband and belongs to + highband now and has to be rescaled to match new highband scale. + 3. old_lsb is lower and old_usb is higher than new_lsb; old and new SBR + areas overlap. + -> old area between old_lsb and new_lsb was highband and belongs to + lowband now and has to be rescaled to match new lowband scale. + 4. new_lsb is lower and new_usb_is higher than old_lsb; old and new SBR + areas overlap. + -> old area between new_lsb and old_usb was lowband and belongs to + highband now and has to be rescaled to match new highband scale. + */ + + if (new_lsb > old_lsb) { + /* case 1 and 3 */ + source_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_hb_scale); + target_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale); + + startBand = old_lsb; + + if (new_lsb >= old_usb) { + /* case 1 */ + stopBand = old_usb; + } else { + /* case 3 */ + stopBand = new_lsb; + } + + target_lsb = 0; + target_usb = old_lsb; + } else { + /* case 2 and 4 */ + source_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale); + target_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_hb_scale); + + startBand = new_lsb; + stopBand = old_lsb; + + target_lsb = old_lsb; + target_usb = old_usb; + } + + maxVal = + maxSubbandSample(OverlapBufferReal, (useLP) ? NULL : OverlapBufferImag, + startBand, stopBand, 0, startSlot); + + reserve = ((LONG)maxVal != 0 ? CntLeadingZeros(maxVal) - 1 : 0); + reserve = fixMin( + reserve, + DFRACT_BITS - 1 - + EXP2SCALE( + source_exp)); /* what is this line for, why do we need it? */ + + /* process only if x-over-area is not dominant after rescale; + otherwise I'm not sure if all buffers are scaled correctly; + */ + if (target_exp - (source_exp - reserve) >= 0) { + rescaleSubbandSamples(OverlapBufferReal, + (useLP) ? NULL : OverlapBufferImag, startBand, + stopBand, 0, startSlot, reserve); + source_exp -= reserve; + } + + delta_exp = target_exp - source_exp; + + if (delta_exp < 0) { /* x-over-area is dominant */ + startBand = target_lsb; + stopBand = target_usb; + delta_exp = -delta_exp; + + if (new_lsb > old_lsb) { + /* The lowband has to be rescaled */ + hSbrDec->qmfDomainInCh->scaling.ov_lb_scale = EXP2SCALE(source_exp); + } else { + /* The highband has to be rescaled */ + hSbrDec->qmfDomainInCh->scaling.ov_hb_scale = EXP2SCALE(source_exp); + } + } + + FDK_ASSERT(startBand <= stopBand); + + if (!useLP) { + for (l = 0; l < startSlot; l++) { + scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand, + -delta_exp); + scaleValues(OverlapBufferImag[l] + startBand, stopBand - startBand, + -delta_exp); + } + } else + for (l = 0; l < startSlot; l++) { + scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand, + -delta_exp); + } + } /* startSlot != 0 */ + + /* + Initialize transposer and limiter + */ + sbrError = resetLppTransposer( + &hSbrDec->LppTrans, hHeaderData->freqBandData.lowSubband, + hHeaderData->freqBandData.v_k_master, hHeaderData->freqBandData.numMaster, + hHeaderData->freqBandData.freqBandTableNoise, + hHeaderData->freqBandData.nNfb, hHeaderData->freqBandData.highSubband, + hHeaderData->sbrProcSmplRate); + if (sbrError != SBRDEC_OK) return sbrError; + + hSbrDec->savedStates = 0; + + if ((flags & SBRDEC_USAC_HARMONICSBR) && applySbrProc) { + sbrError = QmfTransposerReInit(hSbrDec->hHBE, + hHeaderData->freqBandData.freqBandTable, + hHeaderData->freqBandData.nSfb); + if (sbrError != SBRDEC_OK) return sbrError; + + /* copy saved states from previous frame to legacy SBR lpc filterstate + * buffer */ + for (i = 0; i < LPC_ORDER + hSbrDec->LppTrans.pSettings->overlap; i++) { + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + hSbrDec->codecQMFBufferReal[hSbrDec->hHBE->noCols - LPC_ORDER - + hSbrDec->LppTrans.pSettings->overlap + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], + hSbrDec->codecQMFBufferImag[hSbrDec->hHBE->noCols - LPC_ORDER - + hSbrDec->LppTrans.pSettings->overlap + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + } + hSbrDec->savedStates = 1; + + { + /* map QMF buffer to pointer array (Overlap + Frame)*/ + for (i = 0; i < hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER; i++) { + pLowBandReal[i] = hSbrDec->LppTrans.lpcFilterStatesRealHBE[i]; + pLowBandImag[i] = hSbrDec->LppTrans.lpcFilterStatesImagHBE[i]; + } + + /* map QMF buffer to pointer array (Overlap + Frame)*/ + for (i = 0; i < hSbrDec->hHBE->noCols; i++) { + pLowBandReal[i + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->codecQMFBufferReal[i]; + pLowBandImag[i + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->codecQMFBufferImag[i]; + } + + if (flags & SBRDEC_QUAD_RATE) { + if (hFrameData->sbrPatchingMode == 0) { + int *xOverQmf = GetxOverBandQmfTransposer(hSbrDec->hHBE); + + /* in case of harmonic SBR and no HBE_LP map additional buffer for + one more frame to pointer arry */ + for (i = 0; i < hSbrDec->hHBE->noCols / 2; i++) { + pLowBandReal[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsReal[i]; + pLowBandImag[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsImag[i]; + } + + QmfTransposerApply( + hSbrDec->hHBE, + pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols / 2 + LPC_ORDER, + pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols / 2 + LPC_ORDER, + hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + hPrevFrameData->prevSbrPitchInBins, hSbrDec->scale_lb, + hSbrDec->scale_hbe, &hSbrDec->qmfDomainInCh->scaling.hb_scale, + hHeaderData->timeStep, hFrameData->frameInfo.borders[0], + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF); + + copyHarmonicSpectrum( + xOverQmf, pLowBandReal, pLowBandImag, hSbrDec->hHBE->noCols, + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF); + } + } else { + /* in case of harmonic SBR and no HBE_LP map additional buffer for + one more frame to pointer arry */ + for (i = 0; i < hSbrDec->hHBE->noCols; i++) { + pLowBandReal[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsReal[i]; + pLowBandImag[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsImag[i]; + } + + if (hFrameData->sbrPatchingMode == 0) { + QmfTransposerApply( + hSbrDec->hHBE, + pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER, + pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER, + hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + 0 /* not required for keeping states updated in this frame*/, + hSbrDec->scale_lb, hSbrDec->scale_lb, + &hSbrDec->qmfDomainInCh->scaling.hb_scale, hHeaderData->timeStep, + hFrameData->frameInfo.borders[0], + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_NOOUT); + } + + QmfTransposerApply( + hSbrDec->hHBE, + pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols + LPC_ORDER, + pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols + LPC_ORDER, + hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + hPrevFrameData->prevSbrPitchInBins, hSbrDec->scale_lb, + hSbrDec->scale_hbe, &hSbrDec->qmfDomainInCh->scaling.hb_scale, + hHeaderData->timeStep, hFrameData->frameInfo.borders[0], + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF); + } + + if (hFrameData->sbrPatchingMode == 0) { + for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) { + /* + Store the unmodified qmf Slots values for upper part of spectrum + (required for LPC filtering) required if next frame is a HBE frame + */ + FDKmemcpy(hSbrDec->qmfDomainInCh->hQmfSlotsReal[i], + hSbrDec->LppTrans.lpcFilterStatesRealHBE[i + LPC_ORDER], + (64) * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->qmfDomainInCh->hQmfSlotsImag[i], + hSbrDec->LppTrans.lpcFilterStatesImagHBE[i + LPC_ORDER], + (64) * sizeof(FIXP_DBL)); + } + + for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) { + /* + Store the unmodified qmf Slots values for upper part of spectrum + (required for LPC filtering) required if next frame is a HBE frame + */ + FDKmemcpy( + hSbrDec->qmfDomainInCh->hQmfSlotsReal[i], + hSbrDec->codecQMFBufferReal[hSbrDec->hHBE->noCols - + hSbrDec->LppTrans.pSettings->overlap + + i], + new_lsb * sizeof(FIXP_DBL)); + FDKmemcpy( + hSbrDec->qmfDomainInCh->hQmfSlotsImag[i], + hSbrDec->codecQMFBufferImag[hSbrDec->hHBE->noCols - + hSbrDec->LppTrans.pSettings->overlap + + i], + new_lsb * sizeof(FIXP_DBL)); + } + } + } + } + + { + int adapt_lb = 0, diff = 0, + new_scale = hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + + if ((hSbrDec->qmfDomainInCh->scaling.ov_lb_scale != + hSbrDec->qmfDomainInCh->scaling.lb_scale) && + startSlot != 0) { + /* we need to adapt spectrum to have equal scale factor, always larger + * than zero */ + diff = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale) - + SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.lb_scale); + + if (diff > 0) { + adapt_lb = 1; + diff = -diff; + new_scale = hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + } + + stopBand = new_lsb; + } + + if (hFrameData->sbrPatchingMode == 1) { + /* scale states from LegSBR filterstates buffer */ + for (i = 0; i < hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER; i++) { + scaleValues(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], new_lsb, + diff); + if (!useLP) { + scaleValues(hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], new_lsb, + diff); + } + } + + if (flags & SBRDEC_SYNTAX_USAC) { + /* get missing states between old and new x_over from LegSBR + * filterstates buffer */ + /* in case of legacy SBR we leave these values zeroed out */ + for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) { + FDKmemcpy(&OverlapBufferReal[i][old_lsb], + &hSbrDec->LppTrans + .lpcFilterStatesRealLegSBR[LPC_ORDER + i][old_lsb], + fMax(new_lsb - old_lsb, 0) * sizeof(FIXP_DBL)); + if (!useLP) { + FDKmemcpy(&OverlapBufferImag[i][old_lsb], + &hSbrDec->LppTrans + .lpcFilterStatesImagLegSBR[LPC_ORDER + i][old_lsb], + fMax(new_lsb - old_lsb, 0) * sizeof(FIXP_DBL)); + } + } + } + + if (new_lsb > old_lsb) { + stopBand = old_lsb; + } + } + if ((adapt_lb == 1) && (stopBand > startBand)) { + for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) { + scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand, + diff); + if (!useLP) { + scaleValues(OverlapBufferImag[l] + startBand, stopBand - startBand, + diff); + } + } + } + hSbrDec->qmfDomainInCh->scaling.ov_lb_scale = new_scale; + } + + sbrError = ResetLimiterBands(hHeaderData->freqBandData.limiterBandTable, + &hHeaderData->freqBandData.noLimiterBands, + hHeaderData->freqBandData.freqBandTable[0], + hHeaderData->freqBandData.nSfb[0], + hSbrDec->LppTrans.pSettings->patchParam, + hSbrDec->LppTrans.pSettings->noOfPatches, + hHeaderData->bs_data.limiterBands, + hFrameData->sbrPatchingMode, + GetxOverBandQmfTransposer(hSbrDec->hHBE), + Get41SbrQmfTransposer(hSbrDec->hHBE)); + + hSbrDec->SbrCalculateEnvelope.sbrPatchingMode = hFrameData->sbrPatchingMode; + + return sbrError; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_dec.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_dec.h new file mode 100644 index 0000000000000..eb9c39412fa3e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_dec.h @@ -0,0 +1,205 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Sbr decoder +*/ +#ifndef SBR_DEC_H +#define SBR_DEC_H + +#include "sbrdecoder.h" + +#include "lpp_tran.h" +#include "qmf.h" +#include "env_calc.h" +#include "FDK_audio.h" + +#include "sbrdec_drc.h" + +#include "pvc_dec.h" + +#include "hbe.h" + +enum SBRDEC_QMF_SKIP { + qmfSkipNothing = 0, + qmfSkipAnalysis = 1 << 0, + qmfSkipSynthesis = 1 << 1 +}; + +typedef struct { + SBR_CALCULATE_ENVELOPE SbrCalculateEnvelope; + SBR_LPP_TRANS LppTrans; + PVC_STATIC_DATA PvcStaticData; + + /* do scale handling in sbr an not in qmf */ + SHORT scale_ov; + SHORT scale_lb; + SHORT scale_hbe; + + SHORT prev_frame_lSbr; + SHORT prev_frame_hbeSbr; + + int codecFrameSize; + + HANDLE_HBE_TRANSPOSER hHBE; + + HANDLE_FDK_QMF_DOMAIN_IN qmfDomainInCh; + HANDLE_FDK_QMF_DOMAIN_OUT qmfDomainOutCh; + + SBRDEC_DRC_CHANNEL sbrDrcChannel; + +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + INT highBandFadeCnt; /* counter for fading in high-band signal smoothly */ + +#endif + FIXP_DBL **tmp_memory; /* shared memory between hbeLightTimeDelayBuffer and + hQmfHBESlotsReal */ + + FIXP_DBL **hQmfHBESlotsReal; + FIXP_DBL **hQmfHBESlotsImag; + + FIXP_DBL **codecQMFBufferReal; + FIXP_DBL **codecQMFBufferImag; + UCHAR savedStates; + int applySbrProc_old; +} SBR_DEC; + +typedef SBR_DEC *HANDLE_SBR_DEC; + +typedef struct { + SBR_FRAME_DATA frameData[(1) + 1]; + SBR_PREV_FRAME_DATA prevFrameData; + SBR_DEC SbrDec; +} SBR_CHANNEL; + +typedef SBR_CHANNEL *HANDLE_SBR_CHANNEL; + +void sbr_dec( + HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ + LONG *timeIn, /*!< pointer to input time signal */ + LONG *timeOut, /*!< pointer to output time signal */ + HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ + LONG *timeOutRight, /*!< pointer to output time signal */ + INT strideOut, /*!< Time data traversal strideOut */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + HANDLE_SBR_PREV_FRAME_DATA + hPrevFrameData, /*!< Some control data of last frame */ + const int applyProcessing, /*!< Flag for SBR operation */ + HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize, + const INT sbrInDataHeadroom); + +SBR_ERROR +createSbrDec(SBR_CHANNEL *hSbrChannel, HANDLE_SBR_HEADER_DATA hHeaderData, + TRANSPOSER_SETTINGS *pSettings, const int downsampleFac, + const UINT qmfFlags, const UINT flags, const int overlap, int chan, + int codecFrameSize); + +int deleteSbrDec(SBR_CHANNEL *hSbrChannel); + +SBR_ERROR +resetSbrDec(HANDLE_SBR_DEC hSbrDec, HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, const int downsampleFac, + const UINT flags, HANDLE_SBR_FRAME_DATA hFrameData); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_ram.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_ram.cpp new file mode 100644 index 0000000000000..a759d71e33c1f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_ram.cpp @@ -0,0 +1,188 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Memory layout + + This module declares all static and dynamic memory spaces +*/ + +#include "sbr_ram.h" + +/*! + \name StaticSbrData + + Static memory areas, must not be overwritten in other sections of the decoder +*/ +/* @{ */ + +/*! SBR Decoder main structure */ +C_ALLOC_MEM(Ram_SbrDecoder, struct SBR_DECODER_INSTANCE, 1) +/*! SBR Decoder element data
+ Dimension: (8) */ +C_ALLOC_MEM2(Ram_SbrDecElement, SBR_DECODER_ELEMENT, 1, (8)) +/*! SBR Decoder individual channel data
+ Dimension: (8) */ +C_ALLOC_MEM2(Ram_SbrDecChannel, SBR_CHANNEL, 1, (8) + 1) + +/*! Static Data of PS */ + +C_ALLOC_MEM(Ram_ps_dec, struct PS_DEC, 1) + +/* @} */ + +/*! + \name DynamicSbrData + + Dynamic memory areas, might be reused in other algorithm sections, + e.g. the core decoder +
+ Depending on the mode set by DONT_USE_CORE_WORKBUFFER, workbuffers are + defined additionally to the CoreWorkbuffer. +
+ The size of WorkBuffers is ((1024) / (32) * (4) / 2)*(64) = 2048. +
+ WorkBuffer2 is a pointer to the CoreWorkBuffer wich is reused here in the SBR + part. In case of DONT_USE_CORE_WORKBUFFER, the CoreWorkbuffer is not used and + the according Workbuffer2 is defined locally in this file.
WorkBuffer1 is + reused in the AAC core (-> aacdecoder.cpp, aac_ram.cpp)
+ + Use of WorkBuffers: +
+
+    -------------------------------------------------------------
+    AAC core:
+
+      CoreWorkbuffer: spectral coefficients
+      WorkBuffer1:    CAacDecoderChannelInfo, CAacDecoderDynamicData
+
+    -------------------------------------------------------------
+    SBR part:
+      ----------------------------------------------
+      Low Power Mode (useLP=1 or LOW_POWER_SBR_ONLY), see assignLcTimeSlots()
+
+        SLOT_BASED_PROTOTYPE_SYN_FILTER
+
+        WorkBuffer1                                WorkBuffer2(=CoreWorkbuffer)
+         ________________                           ________________
+        | RealLeft       |                         | RealRight      |
+        |________________|                         |________________|
+
+      ----------------------------------------------
+      High Quality Mode (!LOW_POWER_SBR_ONLY and useLP=0), see
+  assignHqTimeSlots()
+
+         SLOTBASED_PS
+
+         WorkBuffer1                                WorkBuffer2(=CoreWorkbuffer)
+         ________________                           ________________
+        | Real/Imag      |  interleaved            | Real/Imag      |
+  interleaved
+        |________________|  first half actual ch   |________________|  second
+  half actual ch
+
+    -------------------------------------------------------------
+
+  
+ +*/ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_ram.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_ram.h new file mode 100644 index 0000000000000..452f8350b35ab --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_ram.h @@ -0,0 +1,189 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! +\file +\brief Memory layout +*/ +#ifndef SBR_RAM_H +#define SBR_RAM_H + +#include "sbrdecoder.h" + +#include "env_extr.h" +#include "sbr_dec.h" + +#define SBRDEC_MAX_CH_PER_ELEMENT (2) + +#define FRAME_OK (0) +#define FRAME_ERROR (1) +#define FRAME_ERROR_ALLSLOTS (2) + +typedef struct { + SBR_CHANNEL *pSbrChannel[SBRDEC_MAX_CH_PER_ELEMENT]; + TRANSPOSER_SETTINGS + transposerSettings; /* Common transport settings for each individual + channel of an element */ + HANDLE_FDK_BITSTREAM hBs; + + MP4_ELEMENT_ID + elementID; /* Element ID set during initialization. Can be used for + concealment */ + int nChannels; /* Number of elements output channels (=2 in case of PS) */ + + UCHAR frameErrorFlag[(1) + 1]; /* Frame error status (for every slot in the + delay line). Will be copied into header at + the very beginning of decodeElement() + routine. */ + + UCHAR useFrameSlot; /* Index which defines which slot will be decoded/filled + next (used with additional delay) */ + UCHAR useHeaderSlot[(1) + 1]; /* Index array that provides the link between + header and frame data (important when + processing with additional delay). */ +} SBR_DECODER_ELEMENT; + +struct SBR_DECODER_INSTANCE { + SBR_DECODER_ELEMENT *pSbrElement[(8)]; + SBR_HEADER_DATA sbrHeader[( + 8)][(1) + 1]; /* Sbr header for each individual channel of an element */ + + HANDLE_FDK_QMF_DOMAIN pQmfDomain; + + HANDLE_PS_DEC hParametricStereoDec; + + /* Global parameters */ + AUDIO_OBJECT_TYPE coreCodec; /* AOT of core codec */ + int numSbrElements; + int numSbrChannels; + INT sampleRateIn; /* SBR decoder input sampling rate; might be different than + the transposer input sampling rate. */ + INT sampleRateOut; /* Sampling rate of the SBR decoder output audio samples. + */ + USHORT codecFrameSize; + UCHAR synDownsampleFac; + INT downscaleFactor; + UCHAR numDelayFrames; /* The current number of additional delay frames used + for processing. */ + UCHAR harmonicSBR; + UCHAR + numFlushedFrames; /* The variable counts the number of frames which are + flushed consecutively. */ + + UINT flags; + + INT sbrInDataHeadroom; /* Headroom of the SBR input time signal to prevent + clipping */ +}; + +H_ALLOC_MEM(Ram_SbrDecElement, SBR_DECODER_ELEMENT) +H_ALLOC_MEM(Ram_SbrDecChannel, SBR_CHANNEL) +H_ALLOC_MEM(Ram_SbrDecoder, struct SBR_DECODER_INSTANCE) + +H_ALLOC_MEM(Ram_sbr_QmfStatesSynthesis, FIXP_QSS) +H_ALLOC_MEM(Ram_sbr_OverlapBuffer, FIXP_DBL) + +H_ALLOC_MEM(Ram_sbr_HBEOverlapBuffer, FIXP_DBL) + +H_ALLOC_MEM(Ram_ps_dec, PS_DEC) + +#endif /* SBR_RAM_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_rom.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_rom.cpp new file mode 100644 index 0000000000000..4c7e74a5d97eb --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbr_rom.cpp @@ -0,0 +1,1193 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Definition of constant tables + + This module contains most of the constant data that can be stored in ROM. +*/ + +#include "sbr_rom.h" + +/*! + \name StartStopBands + \brief Start and stop subbands of the highband. + + k_o = startMin + offset[bs_start_freq]; + startMin = {3000,4000,5000} * (128/FS_sbr) / FS_sbr < 32Khz, 32Khz <= FS_sbr < + 64KHz, 64KHz <= FS_sbr The stop subband can also be calculated to save memory + by defining #CALC_STOP_BAND. +*/ +//@{ +/* tables were created with ../addon/octave/sbr_start_freq_table.m */ +const UCHAR FDK_sbrDecoder_sbr_start_freq_16[][16] = { + {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, + {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_22[][16] = { + {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 28, 30}, + {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_24[][16] = { + {11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32}, + {3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 21, 24}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_32[][16] = { + {10, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32}, + {2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 21, 24}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_40[][16] = { + {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 26, 28, 30, 32}, + {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 21, 23, 25}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_44[][16] = { + {8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 28, 32}, + {2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19, 22, 26}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_48[][16] = { + {7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 27, 31}, + {1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 21, 25}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_64[][16] = { + {6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 23, 26, 30}, + {1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 21, 25}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_88[][16] = { + {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 23, 27, 31}, + {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 20, 24, 28}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_192[16] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 19, 23, 27}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_176[16] = { + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 20, 24, 28}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_128[16] = { + 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 21, 25}; + +//@} + +/*! + \name Whitening + \brief Coefficients for spectral whitening in the transposer +*/ +//@{ +/*! Assignment of whitening tuning depending on the crossover frequency */ +const USHORT FDK_sbrDecoder_sbr_whFactorsIndex[NUM_WHFACTOR_TABLE_ENTRIES] = { + 0, 5000, 6000, 6500, 7000, 7500, 8000, 9000, 10000}; + +/*! + \brief Whithening levels tuning table + + With the current tuning, there are some redundant entries: + + \li NUM_WHFACTOR_TABLE_ENTRIES can be reduced by 3, + \li the first coloumn can be eliminated. + +*/ +const FIXP_DBL + FDK_sbrDecoder_sbr_whFactorsTable[NUM_WHFACTOR_TABLE_ENTRIES][6] = { + /* OFF_LEVEL, TRANSITION_LEVEL, LOW_LEVEL, MID_LEVEL, HIGH_LEVEL */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* < 5000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 5000 < 6000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 6000 < 6500 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 6500 < 7000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 7000 < 7500 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 7500 < 8000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 8000 < 9000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 9000 < 10000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* > 10000 */ +}; + +//@} + +/*! + \name EnvAdj + \brief Constants and tables used for envelope adjustment +*/ +//@{ + +/*! Mantissas of gain limits */ +const FIXP_SGL FDK_sbrDecoder_sbr_limGains_m[4] = { + FL2FXCONST_SGL(0.5011932025f), /*!< -3 dB. Gain limit when limiterGains in + frameData is 0 */ + FL2FXCONST_SGL( + 0.5f), /*!< 0 dB. Gain limit when limiterGains in frameData is 1 */ + FL2FXCONST_SGL(0.9976346258f), /*!< +3 dB. Gain limit when limiterGains in + frameData is 2 */ + FL2FXCONST_SGL(0.6776263578f) /*!< Inf. Gain limit when limiterGains in + frameData is 3 */ +}; + +/*! Exponents of gain limits */ +const UCHAR FDK_sbrDecoder_sbr_limGains_e[4] = {0, 1, 1, 67}; + +/*! Constants for calculating the number of limiter bands */ +const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[4] = { + FL2FXCONST_SGL(1.0f / 4.0f), FL2FXCONST_SGL(1.2f / 4.0f), + FL2FXCONST_SGL(2.0f / 4.0f), FL2FXCONST_SGL(3.0f / 4.0f)}; + +/*! Constants for calculating the number of limiter bands */ +const FIXP_DBL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[4] = { + FL2FXCONST_DBL(1.0f / 4.0f), FL2FXCONST_DBL(1.2f / 4.0f), + FL2FXCONST_DBL(2.0f / 4.0f), FL2FXCONST_DBL(3.0f / 4.0f)}; + +/*! Ratio of old gains and noise levels for the first 4 timeslots of an envelope + */ +const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4] = { + FL2FXCONST_SGL(0.66666666666666f), FL2FXCONST_SGL(0.36516383427084f), + FL2FXCONST_SGL(0.14699433520835f), FL2FXCONST_SGL(0.03183050093751f)}; + +/*! Real and imaginary part of random noise which will be modulated + to the desired level. An accuracy of 13 bits is sufficient for these + random numbers. +*/ +const FIXP_SGL FDK_sbrDecoder_sbr_randomPhase[SBR_NF_NO_RANDOM_VAL][2] = { + {FL2FXCONST_SGL(-0.99948153278296f), FL2FXCONST_SGL(-0.59483417516607f)}, + {FL2FXCONST_SGL(0.97113454393991f), FL2FXCONST_SGL(-0.67528515225647f)}, + {FL2FXCONST_SGL(0.14130051758487f), FL2FXCONST_SGL(-0.95090983575689f)}, + {FL2FXCONST_SGL(-0.47005496701697f), FL2FXCONST_SGL(-0.37340549728647f)}, + {FL2FXCONST_SGL(0.80705063769351f), FL2FXCONST_SGL(0.29653668284408f)}, + {FL2FXCONST_SGL(-0.38981478896926f), FL2FXCONST_SGL(0.89572605717087f)}, + {FL2FXCONST_SGL(-0.01053049862020f), FL2FXCONST_SGL(-0.66959058036166f)}, + {FL2FXCONST_SGL(-0.91266367957293f), FL2FXCONST_SGL(-0.11522938140034f)}, + {FL2FXCONST_SGL(0.54840422910309f), FL2FXCONST_SGL(0.75221367176302f)}, + {FL2FXCONST_SGL(0.40009252867955f), FL2FXCONST_SGL(-0.98929400334421f)}, + {FL2FXCONST_SGL(-0.99867974711855f), FL2FXCONST_SGL(-0.88147068645358f)}, + {FL2FXCONST_SGL(-0.95531076805040f), FL2FXCONST_SGL(0.90908757154593f)}, + {FL2FXCONST_SGL(-0.45725933317144f), FL2FXCONST_SGL(-0.56716323646760f)}, + {FL2FXCONST_SGL(-0.72929675029275f), FL2FXCONST_SGL(-0.98008272727324f)}, + {FL2FXCONST_SGL(0.75622801399036f), FL2FXCONST_SGL(0.20950329995549f)}, + {FL2FXCONST_SGL(0.07069442601050f), FL2FXCONST_SGL(-0.78247898470706f)}, + {FL2FXCONST_SGL(0.74496252926055f), FL2FXCONST_SGL(-0.91169004445807f)}, + {FL2FXCONST_SGL(-0.96440182703856f), FL2FXCONST_SGL(-0.94739918296622f)}, + {FL2FXCONST_SGL(0.30424629369539f), FL2FXCONST_SGL(-0.49438267012479f)}, + {FL2FXCONST_SGL(0.66565033746925f), FL2FXCONST_SGL(0.64652935542491f)}, + {FL2FXCONST_SGL(0.91697008020594f), FL2FXCONST_SGL(0.17514097332009f)}, + {FL2FXCONST_SGL(-0.70774918760427f), FL2FXCONST_SGL(0.52548653416543f)}, + {FL2FXCONST_SGL(-0.70051415345560f), FL2FXCONST_SGL(-0.45340028808763f)}, + {FL2FXCONST_SGL(-0.99496513054797f), FL2FXCONST_SGL(-0.90071908066973f)}, + {FL2FXCONST_SGL(0.98164490790123f), FL2FXCONST_SGL(-0.77463155528697f)}, + {FL2FXCONST_SGL(-0.54671580548181f), FL2FXCONST_SGL(-0.02570928536004f)}, + {FL2FXCONST_SGL(-0.01689629065389f), FL2FXCONST_SGL(0.00287506445732f)}, + {FL2FXCONST_SGL(-0.86110349531986f), FL2FXCONST_SGL(0.42548583726477f)}, + {FL2FXCONST_SGL(-0.98892980586032f), FL2FXCONST_SGL(-0.87881132267556f)}, + {FL2FXCONST_SGL(0.51756627678691f), FL2FXCONST_SGL(0.66926784710139f)}, + {FL2FXCONST_SGL(-0.99635026409640f), FL2FXCONST_SGL(-0.58107730574765f)}, + {FL2FXCONST_SGL(-0.99969370862163f), FL2FXCONST_SGL(0.98369989360250f)}, + {FL2FXCONST_SGL(0.55266258627194f), FL2FXCONST_SGL(0.59449057465591f)}, + {FL2FXCONST_SGL(0.34581177741673f), FL2FXCONST_SGL(0.94879421061866f)}, + {FL2FXCONST_SGL(0.62664209577999f), FL2FXCONST_SGL(-0.74402970906471f)}, + {FL2FXCONST_SGL(-0.77149701404973f), FL2FXCONST_SGL(-0.33883658042801f)}, + {FL2FXCONST_SGL(-0.91592244254432f), FL2FXCONST_SGL(0.03687901376713f)}, + {FL2FXCONST_SGL(-0.76285492357887f), FL2FXCONST_SGL(-0.91371867919124f)}, + {FL2FXCONST_SGL(0.79788337195331f), FL2FXCONST_SGL(-0.93180971199849f)}, + {FL2FXCONST_SGL(0.54473080610200f), FL2FXCONST_SGL(-0.11919206037186f)}, + {FL2FXCONST_SGL(-0.85639281671058f), FL2FXCONST_SGL(0.42429854760451f)}, + {FL2FXCONST_SGL(-0.92882402971423f), FL2FXCONST_SGL(0.27871809078609f)}, + {FL2FXCONST_SGL(-0.11708371046774f), FL2FXCONST_SGL(-0.99800843444966f)}, + {FL2FXCONST_SGL(0.21356749817493f), FL2FXCONST_SGL(-0.90716295627033f)}, + {FL2FXCONST_SGL(-0.76191692573909f), FL2FXCONST_SGL(0.99768118356265f)}, + {FL2FXCONST_SGL(0.98111043100884f), FL2FXCONST_SGL(-0.95854459734407f)}, + {FL2FXCONST_SGL(-0.85913269895572f), FL2FXCONST_SGL(0.95766566168880f)}, + {FL2FXCONST_SGL(-0.93307242253692f), FL2FXCONST_SGL(0.49431757696466f)}, + {FL2FXCONST_SGL(0.30485754879632f), FL2FXCONST_SGL(-0.70540034357529f)}, + {FL2FXCONST_SGL(0.85289650925190f), FL2FXCONST_SGL(0.46766131791044f)}, + {FL2FXCONST_SGL(0.91328082618125f), FL2FXCONST_SGL(-0.99839597361769f)}, + {FL2FXCONST_SGL(-0.05890199924154f), FL2FXCONST_SGL(0.70741827819497f)}, + {FL2FXCONST_SGL(0.28398686150148f), FL2FXCONST_SGL(0.34633555702188f)}, + {FL2FXCONST_SGL(0.95258164539612f), FL2FXCONST_SGL(-0.54893416026939f)}, + {FL2FXCONST_SGL(-0.78566324168507f), FL2FXCONST_SGL(-0.75568541079691f)}, + {FL2FXCONST_SGL(-0.95789495447877f), FL2FXCONST_SGL(-0.20423194696966f)}, + {FL2FXCONST_SGL(0.82411158711197f), FL2FXCONST_SGL(0.96654618432562f)}, + {FL2FXCONST_SGL(-0.65185446735885f), FL2FXCONST_SGL(-0.88734990773289f)}, + {FL2FXCONST_SGL(-0.93643603134666f), FL2FXCONST_SGL(0.99870790442385f)}, + {FL2FXCONST_SGL(0.91427159529618f), FL2FXCONST_SGL(-0.98290505544444f)}, + {FL2FXCONST_SGL(-0.70395684036886f), FL2FXCONST_SGL(0.58796798221039f)}, + {FL2FXCONST_SGL(0.00563771969365f), FL2FXCONST_SGL(0.61768196727244f)}, + {FL2FXCONST_SGL(0.89065051931895f), FL2FXCONST_SGL(0.52783352697585f)}, + {FL2FXCONST_SGL(-0.68683707712762f), FL2FXCONST_SGL(0.80806944710339f)}, + {FL2FXCONST_SGL(0.72165342518718f), FL2FXCONST_SGL(-0.69259857349564f)}, + {FL2FXCONST_SGL(-0.62928247730667f), FL2FXCONST_SGL(0.13627037407335f)}, + {FL2FXCONST_SGL(0.29938434065514f), FL2FXCONST_SGL(-0.46051329682246f)}, + {FL2FXCONST_SGL(-0.91781958879280f), FL2FXCONST_SGL(-0.74012716684186f)}, + {FL2FXCONST_SGL(0.99298717043688f), FL2FXCONST_SGL(0.40816610075661f)}, + {FL2FXCONST_SGL(0.82368298622748f), FL2FXCONST_SGL(-0.74036047190173f)}, + {FL2FXCONST_SGL(-0.98512833386833f), FL2FXCONST_SGL(-0.99972330709594f)}, + {FL2FXCONST_SGL(-0.95915368242257f), FL2FXCONST_SGL(-0.99237800466040f)}, + {FL2FXCONST_SGL(-0.21411126572790f), FL2FXCONST_SGL(-0.93424819052545f)}, + {FL2FXCONST_SGL(-0.68821476106884f), FL2FXCONST_SGL(-0.26892306315457f)}, + {FL2FXCONST_SGL(0.91851997982317f), FL2FXCONST_SGL(0.09358228901785f)}, + {FL2FXCONST_SGL(-0.96062769559127f), FL2FXCONST_SGL(0.36099095133739f)}, + {FL2FXCONST_SGL(0.51646184922287f), FL2FXCONST_SGL(-0.71373332873917f)}, + {FL2FXCONST_SGL(0.61130721139669f), FL2FXCONST_SGL(0.46950141175917f)}, + {FL2FXCONST_SGL(0.47336129371299f), FL2FXCONST_SGL(-0.27333178296162f)}, + {FL2FXCONST_SGL(0.90998308703519f), FL2FXCONST_SGL(0.96715662938132f)}, + {FL2FXCONST_SGL(0.44844799194357f), FL2FXCONST_SGL(0.99211574628306f)}, + {FL2FXCONST_SGL(0.66614891079092f), FL2FXCONST_SGL(0.96590176169121f)}, + {FL2FXCONST_SGL(0.74922239129237f), FL2FXCONST_SGL(-0.89879858826087f)}, + {FL2FXCONST_SGL(-0.99571588506485f), FL2FXCONST_SGL(0.52785521494349f)}, + {FL2FXCONST_SGL(0.97401082477563f), FL2FXCONST_SGL(-0.16855870075190f)}, + {FL2FXCONST_SGL(0.72683747733879f), FL2FXCONST_SGL(-0.48060774432251f)}, + {FL2FXCONST_SGL(0.95432193457128f), FL2FXCONST_SGL(0.68849603408441f)}, + {FL2FXCONST_SGL(-0.72962208425191f), FL2FXCONST_SGL(-0.76608443420917f)}, + {FL2FXCONST_SGL(-0.85359479233537f), FL2FXCONST_SGL(0.88738125901579f)}, + {FL2FXCONST_SGL(-0.81412430338535f), FL2FXCONST_SGL(-0.97480768049637f)}, + {FL2FXCONST_SGL(-0.87930772356786f), FL2FXCONST_SGL(0.74748307690436f)}, + {FL2FXCONST_SGL(-0.71573331064977f), FL2FXCONST_SGL(-0.98570608178923f)}, + {FL2FXCONST_SGL(0.83524300028228f), FL2FXCONST_SGL(0.83702537075163f)}, + {FL2FXCONST_SGL(-0.48086065601423f), FL2FXCONST_SGL(-0.98848504923531f)}, + {FL2FXCONST_SGL(0.97139128574778f), FL2FXCONST_SGL(0.80093621198236f)}, + {FL2FXCONST_SGL(0.51992825347895f), FL2FXCONST_SGL(0.80247631400510f)}, + {FL2FXCONST_SGL(-0.00848591195325f), FL2FXCONST_SGL(-0.76670128000486f)}, + {FL2FXCONST_SGL(-0.70294374303036f), FL2FXCONST_SGL(0.55359910445577f)}, + {FL2FXCONST_SGL(-0.95894428168140f), FL2FXCONST_SGL(-0.43265504344783f)}, + {FL2FXCONST_SGL(0.97079252950321f), FL2FXCONST_SGL(0.09325857238682f)}, + {FL2FXCONST_SGL(-0.92404293670797f), FL2FXCONST_SGL(0.85507704027855f)}, + {FL2FXCONST_SGL(-0.69506469500450f), FL2FXCONST_SGL(0.98633412625459f)}, + {FL2FXCONST_SGL(0.26559203620024f), FL2FXCONST_SGL(0.73314307966524f)}, + {FL2FXCONST_SGL(0.28038443336943f), FL2FXCONST_SGL(0.14537913654427f)}, + {FL2FXCONST_SGL(-0.74138124825523f), FL2FXCONST_SGL(0.99310339807762f)}, + {FL2FXCONST_SGL(-0.01752795995444f), FL2FXCONST_SGL(-0.82616635284178f)}, + {FL2FXCONST_SGL(-0.55126773094930f), FL2FXCONST_SGL(-0.98898543862153f)}, + {FL2FXCONST_SGL(0.97960898850996f), FL2FXCONST_SGL(-0.94021446752851f)}, + {FL2FXCONST_SGL(-0.99196309146936f), FL2FXCONST_SGL(0.67019017358456f)}, + {FL2FXCONST_SGL(-0.67684928085260f), FL2FXCONST_SGL(0.12631491649378f)}, + {FL2FXCONST_SGL(0.09140039465500f), FL2FXCONST_SGL(-0.20537731453108f)}, + {FL2FXCONST_SGL(-0.71658965751996f), FL2FXCONST_SGL(-0.97788200391224f)}, + {FL2FXCONST_SGL(0.81014640078925f), FL2FXCONST_SGL(0.53722648362443f)}, + {FL2FXCONST_SGL(0.40616991671205f), FL2FXCONST_SGL(-0.26469008598449f)}, + {FL2FXCONST_SGL(-0.67680188682972f), FL2FXCONST_SGL(0.94502052337695f)}, + {FL2FXCONST_SGL(0.86849774348749f), FL2FXCONST_SGL(-0.18333598647899f)}, + {FL2FXCONST_SGL(-0.99500381284851f), FL2FXCONST_SGL(-0.02634122068550f)}, + {FL2FXCONST_SGL(0.84329189340667f), FL2FXCONST_SGL(0.10406957462213f)}, + {FL2FXCONST_SGL(-0.09215968531446f), FL2FXCONST_SGL(0.69540012101253f)}, + {FL2FXCONST_SGL(0.99956173327206f), FL2FXCONST_SGL(-0.12358542001404f)}, + {FL2FXCONST_SGL(-0.79732779473535f), FL2FXCONST_SGL(-0.91582524736159f)}, + {FL2FXCONST_SGL(0.96349973642406f), FL2FXCONST_SGL(0.96640458041000f)}, + {FL2FXCONST_SGL(-0.79942778496547f), FL2FXCONST_SGL(0.64323902822857f)}, + {FL2FXCONST_SGL(-0.11566039853896f), FL2FXCONST_SGL(0.28587846253726f)}, + {FL2FXCONST_SGL(-0.39922954514662f), FL2FXCONST_SGL(0.94129601616966f)}, + {FL2FXCONST_SGL(0.99089197565987f), FL2FXCONST_SGL(-0.92062625581587f)}, + {FL2FXCONST_SGL(0.28631285179909f), FL2FXCONST_SGL(-0.91035047143603f)}, + {FL2FXCONST_SGL(-0.83302725605608f), FL2FXCONST_SGL(-0.67330410892084f)}, + {FL2FXCONST_SGL(0.95404443402072f), FL2FXCONST_SGL(0.49162765398743f)}, + {FL2FXCONST_SGL(-0.06449863579434f), FL2FXCONST_SGL(0.03250560813135f)}, + {FL2FXCONST_SGL(-0.99575054486311f), FL2FXCONST_SGL(0.42389784469507f)}, + {FL2FXCONST_SGL(-0.65501142790847f), FL2FXCONST_SGL(0.82546114655624f)}, + {FL2FXCONST_SGL(-0.81254441908887f), FL2FXCONST_SGL(-0.51627234660629f)}, + {FL2FXCONST_SGL(-0.99646369485481f), FL2FXCONST_SGL(0.84490533520752f)}, + {FL2FXCONST_SGL(0.00287840603348f), FL2FXCONST_SGL(0.64768261158166f)}, + {FL2FXCONST_SGL(0.70176989408455f), FL2FXCONST_SGL(-0.20453028573322f)}, + {FL2FXCONST_SGL(0.96361882270190f), FL2FXCONST_SGL(0.40706967140989f)}, + {FL2FXCONST_SGL(-0.68883758192426f), FL2FXCONST_SGL(0.91338958840772f)}, + {FL2FXCONST_SGL(-0.34875585502238f), FL2FXCONST_SGL(0.71472290693300f)}, + {FL2FXCONST_SGL(0.91980081243087f), FL2FXCONST_SGL(0.66507455644919f)}, + {FL2FXCONST_SGL(-0.99009048343881f), FL2FXCONST_SGL(0.85868021604848f)}, + {FL2FXCONST_SGL(0.68865791458395f), FL2FXCONST_SGL(0.55660316809678f)}, + {FL2FXCONST_SGL(-0.99484402129368f), FL2FXCONST_SGL(-0.20052559254934f)}, + {FL2FXCONST_SGL(0.94214511408023f), FL2FXCONST_SGL(-0.99696425367461f)}, + {FL2FXCONST_SGL(-0.67414626793544f), FL2FXCONST_SGL(0.49548221180078f)}, + {FL2FXCONST_SGL(-0.47339353684664f), FL2FXCONST_SGL(-0.85904328834047f)}, + {FL2FXCONST_SGL(0.14323651387360f), FL2FXCONST_SGL(-0.94145598222488f)}, + {FL2FXCONST_SGL(-0.29268293575672f), FL2FXCONST_SGL(0.05759224927952f)}, + {FL2FXCONST_SGL(0.43793861458754f), FL2FXCONST_SGL(-0.78904969892724f)}, + {FL2FXCONST_SGL(-0.36345126374441f), FL2FXCONST_SGL(0.64874435357162f)}, + {FL2FXCONST_SGL(-0.08750604656825f), FL2FXCONST_SGL(0.97686944362527f)}, + {FL2FXCONST_SGL(-0.96495267812511f), FL2FXCONST_SGL(-0.53960305946511f)}, + {FL2FXCONST_SGL(0.55526940659947f), FL2FXCONST_SGL(0.78891523734774f)}, + {FL2FXCONST_SGL(0.73538215752630f), FL2FXCONST_SGL(0.96452072373404f)}, + {FL2FXCONST_SGL(-0.30889773919437f), FL2FXCONST_SGL(-0.80664389776860f)}, + {FL2FXCONST_SGL(0.03574995626194f), FL2FXCONST_SGL(-0.97325616900959f)}, + {FL2FXCONST_SGL(0.98720684660488f), FL2FXCONST_SGL(0.48409133691962f)}, + {FL2FXCONST_SGL(-0.81689296271203f), FL2FXCONST_SGL(-0.90827703628298f)}, + {FL2FXCONST_SGL(0.67866860118215f), FL2FXCONST_SGL(0.81284503870856f)}, + {FL2FXCONST_SGL(-0.15808569732583f), FL2FXCONST_SGL(0.85279555024382f)}, + {FL2FXCONST_SGL(0.80723395114371f), FL2FXCONST_SGL(-0.24717418514605f)}, + {FL2FXCONST_SGL(0.47788757329038f), FL2FXCONST_SGL(-0.46333147839295f)}, + {FL2FXCONST_SGL(0.96367554763201f), FL2FXCONST_SGL(0.38486749303242f)}, + {FL2FXCONST_SGL(-0.99143875716818f), FL2FXCONST_SGL(-0.24945277239809f)}, + {FL2FXCONST_SGL(0.83081876925833f), FL2FXCONST_SGL(-0.94780851414763f)}, + {FL2FXCONST_SGL(-0.58753191905341f), FL2FXCONST_SGL(0.01290772389163f)}, + {FL2FXCONST_SGL(0.95538108220960f), FL2FXCONST_SGL(-0.85557052096538f)}, + {FL2FXCONST_SGL(-0.96490920476211f), FL2FXCONST_SGL(-0.64020970923102f)}, + {FL2FXCONST_SGL(-0.97327101028521f), FL2FXCONST_SGL(0.12378128133110f)}, + {FL2FXCONST_SGL(0.91400366022124f), FL2FXCONST_SGL(0.57972471346930f)}, + {FL2FXCONST_SGL(-0.99925837363824f), FL2FXCONST_SGL(0.71084847864067f)}, + {FL2FXCONST_SGL(-0.86875903507313f), FL2FXCONST_SGL(-0.20291699203564f)}, + {FL2FXCONST_SGL(-0.26240034795124f), FL2FXCONST_SGL(-0.68264554369108f)}, + {FL2FXCONST_SGL(-0.24664412953388f), FL2FXCONST_SGL(-0.87642273115183f)}, + {FL2FXCONST_SGL(0.02416275806869f), FL2FXCONST_SGL(0.27192914288905f)}, + {FL2FXCONST_SGL(0.82068619590515f), FL2FXCONST_SGL(-0.85087787994476f)}, + {FL2FXCONST_SGL(0.88547373760759f), FL2FXCONST_SGL(-0.89636802901469f)}, + {FL2FXCONST_SGL(-0.18173078152226f), FL2FXCONST_SGL(-0.26152145156800f)}, + {FL2FXCONST_SGL(0.09355476558534f), FL2FXCONST_SGL(0.54845123045604f)}, + {FL2FXCONST_SGL(-0.54668414224090f), FL2FXCONST_SGL(0.95980774020221f)}, + {FL2FXCONST_SGL(0.37050990604091f), FL2FXCONST_SGL(-0.59910140383171f)}, + {FL2FXCONST_SGL(-0.70373594262891f), FL2FXCONST_SGL(0.91227665827081f)}, + {FL2FXCONST_SGL(-0.34600785879594f), FL2FXCONST_SGL(-0.99441426144200f)}, + {FL2FXCONST_SGL(-0.68774481731008f), FL2FXCONST_SGL(-0.30238837956299f)}, + {FL2FXCONST_SGL(-0.26843291251234f), FL2FXCONST_SGL(0.83115668004362f)}, + {FL2FXCONST_SGL(0.49072334613242f), FL2FXCONST_SGL(-0.45359708737775f)}, + {FL2FXCONST_SGL(0.38975993093975f), FL2FXCONST_SGL(0.95515358099121f)}, + {FL2FXCONST_SGL(-0.97757125224150f), FL2FXCONST_SGL(0.05305894580606f)}, + {FL2FXCONST_SGL(-0.17325552859616f), FL2FXCONST_SGL(-0.92770672250494f)}, + {FL2FXCONST_SGL(0.99948035025744f), FL2FXCONST_SGL(0.58285545563426f)}, + {FL2FXCONST_SGL(-0.64946246527458f), FL2FXCONST_SGL(0.68645507104960f)}, + {FL2FXCONST_SGL(-0.12016920576437f), FL2FXCONST_SGL(-0.57147322153312f)}, + {FL2FXCONST_SGL(-0.58947456517751f), FL2FXCONST_SGL(-0.34847132454388f)}, + {FL2FXCONST_SGL(-0.41815140454465f), FL2FXCONST_SGL(0.16276422358861f)}, + {FL2FXCONST_SGL(0.99885650204884f), FL2FXCONST_SGL(0.11136095490444f)}, + {FL2FXCONST_SGL(-0.56649614128386f), FL2FXCONST_SGL(-0.90494866361587f)}, + {FL2FXCONST_SGL(0.94138021032330f), FL2FXCONST_SGL(0.35281916733018f)}, + {FL2FXCONST_SGL(-0.75725076534641f), FL2FXCONST_SGL(0.53650549640587f)}, + {FL2FXCONST_SGL(0.20541973692630f), FL2FXCONST_SGL(-0.94435144369918f)}, + {FL2FXCONST_SGL(0.99980371023351f), FL2FXCONST_SGL(0.79835913565599f)}, + {FL2FXCONST_SGL(0.29078277605775f), FL2FXCONST_SGL(0.35393777921520f)}, + {FL2FXCONST_SGL(-0.62858772103030f), FL2FXCONST_SGL(0.38765693387102f)}, + {FL2FXCONST_SGL(0.43440904467688f), FL2FXCONST_SGL(-0.98546330463232f)}, + {FL2FXCONST_SGL(-0.98298583762390f), FL2FXCONST_SGL(0.21021524625209f)}, + {FL2FXCONST_SGL(0.19513029146934f), FL2FXCONST_SGL(-0.94239832251867f)}, + {FL2FXCONST_SGL(-0.95476662400101f), FL2FXCONST_SGL(0.98364554179143f)}, + {FL2FXCONST_SGL(0.93379635304810f), FL2FXCONST_SGL(-0.70881994583682f)}, + {FL2FXCONST_SGL(-0.85235410573336f), FL2FXCONST_SGL(-0.08342347966410f)}, + {FL2FXCONST_SGL(-0.86425093011245f), FL2FXCONST_SGL(-0.45795025029466f)}, + {FL2FXCONST_SGL(0.38879779059045f), FL2FXCONST_SGL(0.97274429344593f)}, + {FL2FXCONST_SGL(0.92045124735495f), FL2FXCONST_SGL(-0.62433652524220f)}, + {FL2FXCONST_SGL(0.89162532251878f), FL2FXCONST_SGL(0.54950955570563f)}, + {FL2FXCONST_SGL(-0.36834336949252f), FL2FXCONST_SGL(0.96458298020975f)}, + {FL2FXCONST_SGL(0.93891760988045f), FL2FXCONST_SGL(-0.89968353740388f)}, + {FL2FXCONST_SGL(0.99267657565094f), FL2FXCONST_SGL(-0.03757034316958f)}, + {FL2FXCONST_SGL(-0.94063471614176f), FL2FXCONST_SGL(0.41332338538963f)}, + {FL2FXCONST_SGL(0.99740224117019f), FL2FXCONST_SGL(-0.16830494996370f)}, + {FL2FXCONST_SGL(-0.35899413170555f), FL2FXCONST_SGL(-0.46633226649613f)}, + {FL2FXCONST_SGL(0.05237237274947f), FL2FXCONST_SGL(-0.25640361602661f)}, + {FL2FXCONST_SGL(0.36703583957424f), FL2FXCONST_SGL(-0.38653265641875f)}, + {FL2FXCONST_SGL(0.91653180367913f), FL2FXCONST_SGL(-0.30587628726597f)}, + {FL2FXCONST_SGL(0.69000803499316f), FL2FXCONST_SGL(0.90952171386132f)}, + {FL2FXCONST_SGL(-0.38658751133527f), FL2FXCONST_SGL(0.99501571208985f)}, + {FL2FXCONST_SGL(-0.29250814029851f), FL2FXCONST_SGL(0.37444994344615f)}, + {FL2FXCONST_SGL(-0.60182204677608f), FL2FXCONST_SGL(0.86779651036123f)}, + {FL2FXCONST_SGL(-0.97418588163217f), FL2FXCONST_SGL(0.96468523666475f)}, + {FL2FXCONST_SGL(0.88461574003963f), FL2FXCONST_SGL(0.57508405276414f)}, + {FL2FXCONST_SGL(0.05198933055162f), FL2FXCONST_SGL(0.21269661669964f)}, + {FL2FXCONST_SGL(-0.53499621979720f), FL2FXCONST_SGL(0.97241553731237f)}, + {FL2FXCONST_SGL(-0.49429560226497f), FL2FXCONST_SGL(0.98183865291903f)}, + {FL2FXCONST_SGL(-0.98935142339139f), FL2FXCONST_SGL(-0.40249159006933f)}, + {FL2FXCONST_SGL(-0.98081380091130f), FL2FXCONST_SGL(-0.72856895534041f)}, + {FL2FXCONST_SGL(-0.27338148835532f), FL2FXCONST_SGL(0.99950922447209f)}, + {FL2FXCONST_SGL(0.06310802338302f), FL2FXCONST_SGL(-0.54539587529618f)}, + {FL2FXCONST_SGL(-0.20461677199539f), FL2FXCONST_SGL(-0.14209977628489f)}, + {FL2FXCONST_SGL(0.66223843141647f), FL2FXCONST_SGL(0.72528579940326f)}, + {FL2FXCONST_SGL(-0.84764345483665f), FL2FXCONST_SGL(0.02372316801261f)}, + {FL2FXCONST_SGL(-0.89039863483811f), FL2FXCONST_SGL(0.88866581484602f)}, + {FL2FXCONST_SGL(0.95903308477986f), FL2FXCONST_SGL(0.76744927173873f)}, + {FL2FXCONST_SGL(0.73504123909879f), FL2FXCONST_SGL(-0.03747203173192f)}, + {FL2FXCONST_SGL(-0.31744434966056f), FL2FXCONST_SGL(-0.36834111883652f)}, + {FL2FXCONST_SGL(-0.34110827591623f), FL2FXCONST_SGL(0.40211222807691f)}, + {FL2FXCONST_SGL(0.47803883714199f), FL2FXCONST_SGL(-0.39423219786288f)}, + {FL2FXCONST_SGL(0.98299195879514f), FL2FXCONST_SGL(0.01989791390047f)}, + {FL2FXCONST_SGL(-0.30963073129751f), FL2FXCONST_SGL(-0.18076720599336f)}, + {FL2FXCONST_SGL(0.99992588229018f), FL2FXCONST_SGL(-0.26281872094289f)}, + {FL2FXCONST_SGL(-0.93149731080767f), FL2FXCONST_SGL(-0.98313162570490f)}, + {FL2FXCONST_SGL(0.99923472302773f), FL2FXCONST_SGL(-0.80142993767554f)}, + {FL2FXCONST_SGL(-0.26024169633417f), FL2FXCONST_SGL(-0.75999759855752f)}, + {FL2FXCONST_SGL(-0.35712514743563f), FL2FXCONST_SGL(0.19298963768574f)}, + {FL2FXCONST_SGL(-0.99899084509530f), FL2FXCONST_SGL(0.74645156992493f)}, + {FL2FXCONST_SGL(0.86557171579452f), FL2FXCONST_SGL(0.55593866696299f)}, + {FL2FXCONST_SGL(0.33408042438752f), FL2FXCONST_SGL(0.86185953874709f)}, + {FL2FXCONST_SGL(0.99010736374716f), FL2FXCONST_SGL(0.04602397576623f)}, + {FL2FXCONST_SGL(-0.66694269691195f), FL2FXCONST_SGL(-0.91643611810148f)}, + {FL2FXCONST_SGL(0.64016792079480f), FL2FXCONST_SGL(0.15649530836856f)}, + {FL2FXCONST_SGL(0.99570534804836f), FL2FXCONST_SGL(0.45844586038111f)}, + {FL2FXCONST_SGL(-0.63431466947340f), FL2FXCONST_SGL(0.21079116459234f)}, + {FL2FXCONST_SGL(-0.07706847005931f), FL2FXCONST_SGL(-0.89581437101329f)}, + {FL2FXCONST_SGL(0.98590090577724f), FL2FXCONST_SGL(0.88241721133981f)}, + {FL2FXCONST_SGL(0.80099335254678f), FL2FXCONST_SGL(-0.36851896710853f)}, + {FL2FXCONST_SGL(0.78368131392666f), FL2FXCONST_SGL(0.45506999802597f)}, + {FL2FXCONST_SGL(0.08707806671691f), FL2FXCONST_SGL(0.80938994918745f)}, + {FL2FXCONST_SGL(-0.86811883080712f), FL2FXCONST_SGL(0.39347308654705f)}, + {FL2FXCONST_SGL(-0.39466529740375f), FL2FXCONST_SGL(-0.66809432114456f)}, + {FL2FXCONST_SGL(0.97875325649683f), FL2FXCONST_SGL(-0.72467840967746f)}, + {FL2FXCONST_SGL(-0.95038560288864f), FL2FXCONST_SGL(0.89563219587625f)}, + {FL2FXCONST_SGL(0.17005239424212f), FL2FXCONST_SGL(0.54683053962658f)}, + {FL2FXCONST_SGL(-0.76910792026848f), FL2FXCONST_SGL(-0.96226617549298f)}, + {FL2FXCONST_SGL(0.99743281016846f), FL2FXCONST_SGL(0.42697157037567f)}, + {FL2FXCONST_SGL(0.95437383549973f), FL2FXCONST_SGL(0.97002324109952f)}, + {FL2FXCONST_SGL(0.99578905365569f), FL2FXCONST_SGL(-0.54106826257356f)}, + {FL2FXCONST_SGL(0.28058259829990f), FL2FXCONST_SGL(-0.85361420634036f)}, + {FL2FXCONST_SGL(0.85256524470573f), FL2FXCONST_SGL(-0.64567607735589f)}, + {FL2FXCONST_SGL(-0.50608540105128f), FL2FXCONST_SGL(-0.65846015480300f)}, + {FL2FXCONST_SGL(-0.97210735183243f), FL2FXCONST_SGL(-0.23095213067791f)}, + {FL2FXCONST_SGL(0.95424048234441f), FL2FXCONST_SGL(-0.99240147091219f)}, + {FL2FXCONST_SGL(-0.96926570524023f), FL2FXCONST_SGL(0.73775654896574f)}, + {FL2FXCONST_SGL(0.30872163214726f), FL2FXCONST_SGL(0.41514960556126f)}, + {FL2FXCONST_SGL(-0.24523839572639f), FL2FXCONST_SGL(0.63206633394807f)}, + {FL2FXCONST_SGL(-0.33813265086024f), FL2FXCONST_SGL(-0.38661779441897f)}, + {FL2FXCONST_SGL(-0.05826828420146f), FL2FXCONST_SGL(-0.06940774188029f)}, + {FL2FXCONST_SGL(-0.22898461455054f), FL2FXCONST_SGL(0.97054853316316f)}, + {FL2FXCONST_SGL(-0.18509915019881f), FL2FXCONST_SGL(0.47565762892084f)}, + {FL2FXCONST_SGL(-0.10488238045009f), FL2FXCONST_SGL(-0.87769947402394f)}, + {FL2FXCONST_SGL(-0.71886586182037f), FL2FXCONST_SGL(0.78030982480538f)}, + {FL2FXCONST_SGL(0.99793873738654f), FL2FXCONST_SGL(0.90041310491497f)}, + {FL2FXCONST_SGL(0.57563307626120f), FL2FXCONST_SGL(-0.91034337352097f)}, + {FL2FXCONST_SGL(0.28909646383717f), FL2FXCONST_SGL(0.96307783970534f)}, + {FL2FXCONST_SGL(0.42188998312520f), FL2FXCONST_SGL(0.48148651230437f)}, + {FL2FXCONST_SGL(0.93335049681047f), FL2FXCONST_SGL(-0.43537023883588f)}, + {FL2FXCONST_SGL(-0.97087374418267f), FL2FXCONST_SGL(0.86636445711364f)}, + {FL2FXCONST_SGL(0.36722871286923f), FL2FXCONST_SGL(0.65291654172961f)}, + {FL2FXCONST_SGL(-0.81093025665696f), FL2FXCONST_SGL(0.08778370229363f)}, + {FL2FXCONST_SGL(-0.26240603062237f), FL2FXCONST_SGL(-0.92774095379098f)}, + {FL2FXCONST_SGL(0.83996497984604f), FL2FXCONST_SGL(0.55839849139647f)}, + {FL2FXCONST_SGL(-0.99909615720225f), FL2FXCONST_SGL(-0.96024605713970f)}, + {FL2FXCONST_SGL(0.74649464155061f), FL2FXCONST_SGL(0.12144893606462f)}, + {FL2FXCONST_SGL(-0.74774595569805f), FL2FXCONST_SGL(-0.26898062008959f)}, + {FL2FXCONST_SGL(0.95781667469567f), FL2FXCONST_SGL(-0.79047927052628f)}, + {FL2FXCONST_SGL(0.95472308713099f), FL2FXCONST_SGL(-0.08588776019550f)}, + {FL2FXCONST_SGL(0.48708332746299f), MAXVAL_SGL}, + {FL2FXCONST_SGL(0.46332038247497f), FL2FXCONST_SGL(0.10964126185063f)}, + {FL2FXCONST_SGL(-0.76497004940162f), FL2FXCONST_SGL(0.89210929242238f)}, + {FL2FXCONST_SGL(0.57397389364339f), FL2FXCONST_SGL(0.35289703373760f)}, + {FL2FXCONST_SGL(0.75374316974495f), FL2FXCONST_SGL(0.96705214651335f)}, + {FL2FXCONST_SGL(-0.59174397685714f), FL2FXCONST_SGL(-0.89405370422752f)}, + {FL2FXCONST_SGL(0.75087906691890f), FL2FXCONST_SGL(-0.29612672982396f)}, + {FL2FXCONST_SGL(-0.98607857336230f), FL2FXCONST_SGL(0.25034911730023f)}, + {FL2FXCONST_SGL(-0.40761056640505f), FL2FXCONST_SGL(-0.90045573444695f)}, + {FL2FXCONST_SGL(0.66929266740477f), FL2FXCONST_SGL(0.98629493401748f)}, + {FL2FXCONST_SGL(-0.97463695257310f), FL2FXCONST_SGL(-0.00190223301301f)}, + {FL2FXCONST_SGL(0.90145509409859f), FL2FXCONST_SGL(0.99781390365446f)}, + {FL2FXCONST_SGL(-0.87259289048043f), FL2FXCONST_SGL(0.99233587353666f)}, + {FL2FXCONST_SGL(-0.91529461447692f), FL2FXCONST_SGL(-0.15698707534206f)}, + {FL2FXCONST_SGL(-0.03305738840705f), FL2FXCONST_SGL(-0.37205262859764f)}, + {FL2FXCONST_SGL(0.07223051368337f), FL2FXCONST_SGL(-0.88805001733626f)}, + {FL2FXCONST_SGL(0.99498012188353f), FL2FXCONST_SGL(0.97094358113387f)}, + {FL2FXCONST_SGL(-0.74904939500519f), FL2FXCONST_SGL(0.99985483641521f)}, + {FL2FXCONST_SGL(0.04585228574211f), FL2FXCONST_SGL(0.99812337444082f)}, + {FL2FXCONST_SGL(-0.89054954257993f), FL2FXCONST_SGL(-0.31791913188064f)}, + {FL2FXCONST_SGL(-0.83782144651251f), FL2FXCONST_SGL(0.97637632547466f)}, + {FL2FXCONST_SGL(0.33454804933804f), FL2FXCONST_SGL(-0.86231516800408f)}, + {FL2FXCONST_SGL(-0.99707579362824f), FL2FXCONST_SGL(0.93237990079441f)}, + {FL2FXCONST_SGL(-0.22827527843994f), FL2FXCONST_SGL(0.18874759397997f)}, + {FL2FXCONST_SGL(0.67248046289143f), FL2FXCONST_SGL(-0.03646211390569f)}, + {FL2FXCONST_SGL(-0.05146538187944f), FL2FXCONST_SGL(-0.92599700120679f)}, + {FL2FXCONST_SGL(0.99947295749905f), FL2FXCONST_SGL(0.93625229707912f)}, + {FL2FXCONST_SGL(0.66951124390363f), FL2FXCONST_SGL(0.98905825623893f)}, + {FL2FXCONST_SGL(-0.99602956559179f), FL2FXCONST_SGL(-0.44654715757688f)}, + {FL2FXCONST_SGL(0.82104905483590f), FL2FXCONST_SGL(0.99540741724928f)}, + {FL2FXCONST_SGL(0.99186510988782f), FL2FXCONST_SGL(0.72023001312947f)}, + {FL2FXCONST_SGL(-0.65284592392918f), FL2FXCONST_SGL(0.52186723253637f)}, + {FL2FXCONST_SGL(0.93885443798188f), FL2FXCONST_SGL(-0.74895312615259f)}, + {FL2FXCONST_SGL(0.96735248738388f), FL2FXCONST_SGL(0.90891816978629f)}, + {FL2FXCONST_SGL(-0.22225968841114f), FL2FXCONST_SGL(0.57124029781228f)}, + {FL2FXCONST_SGL(-0.44132783753414f), FL2FXCONST_SGL(-0.92688840659280f)}, + {FL2FXCONST_SGL(-0.85694974219574f), FL2FXCONST_SGL(0.88844532719844f)}, + {FL2FXCONST_SGL(0.91783042091762f), FL2FXCONST_SGL(-0.46356892383970f)}, + {FL2FXCONST_SGL(0.72556974415690f), FL2FXCONST_SGL(-0.99899555770747f)}, + {FL2FXCONST_SGL(-0.99711581834508f), FL2FXCONST_SGL(0.58211560180426f)}, + {FL2FXCONST_SGL(0.77638976371966f), FL2FXCONST_SGL(0.94321834873819f)}, + {FL2FXCONST_SGL(0.07717324253925f), FL2FXCONST_SGL(0.58638399856595f)}, + {FL2FXCONST_SGL(-0.56049829194163f), FL2FXCONST_SGL(0.82522301569036f)}, + {FL2FXCONST_SGL(0.98398893639988f), FL2FXCONST_SGL(0.39467440420569f)}, + {FL2FXCONST_SGL(0.47546946844938f), FL2FXCONST_SGL(0.68613044836811f)}, + {FL2FXCONST_SGL(0.65675089314631f), FL2FXCONST_SGL(0.18331637134880f)}, + {FL2FXCONST_SGL(0.03273375457980f), FL2FXCONST_SGL(-0.74933109564108f)}, + {FL2FXCONST_SGL(-0.38684144784738f), FL2FXCONST_SGL(0.51337349030406f)}, + {FL2FXCONST_SGL(-0.97346267944545f), FL2FXCONST_SGL(-0.96549364384098f)}, + {FL2FXCONST_SGL(-0.53282156061942f), FL2FXCONST_SGL(-0.91423265091354f)}, + {FL2FXCONST_SGL(0.99817310731176f), FL2FXCONST_SGL(0.61133572482148f)}, + {FL2FXCONST_SGL(-0.50254500772635f), FL2FXCONST_SGL(-0.88829338134294f)}, + {FL2FXCONST_SGL(0.01995873238855f), FL2FXCONST_SGL(0.85223515096765f)}, + {FL2FXCONST_SGL(0.99930381973804f), FL2FXCONST_SGL(0.94578896296649f)}, + {FL2FXCONST_SGL(0.82907767600783f), FL2FXCONST_SGL(-0.06323442598128f)}, + {FL2FXCONST_SGL(-0.58660709669728f), FL2FXCONST_SGL(0.96840773806582f)}, + {FL2FXCONST_SGL(-0.17573736667267f), FL2FXCONST_SGL(-0.48166920859485f)}, + {FL2FXCONST_SGL(0.83434292401346f), FL2FXCONST_SGL(-0.13023450646997f)}, + {FL2FXCONST_SGL(0.05946491307025f), FL2FXCONST_SGL(0.20511047074866f)}, + {FL2FXCONST_SGL(0.81505484574602f), FL2FXCONST_SGL(-0.94685947861369f)}, + {FL2FXCONST_SGL(-0.44976380954860f), FL2FXCONST_SGL(0.40894572671545f)}, + {FL2FXCONST_SGL(-0.89746474625671f), FL2FXCONST_SGL(0.99846578838537f)}, + {FL2FXCONST_SGL(0.39677256130792f), FL2FXCONST_SGL(-0.74854668609359f)}, + {FL2FXCONST_SGL(-0.07588948563079f), FL2FXCONST_SGL(0.74096214084170f)}, + {FL2FXCONST_SGL(0.76343198951445f), FL2FXCONST_SGL(0.41746629422634f)}, + {FL2FXCONST_SGL(-0.74490104699626f), FL2FXCONST_SGL(0.94725911744610f)}, + {FL2FXCONST_SGL(0.64880119792759f), FL2FXCONST_SGL(0.41336660830571f)}, + {FL2FXCONST_SGL(0.62319537462542f), FL2FXCONST_SGL(-0.93098313552599f)}, + {FL2FXCONST_SGL(0.42215817594807f), FL2FXCONST_SGL(-0.07712787385208f)}, + {FL2FXCONST_SGL(0.02704554141885f), FL2FXCONST_SGL(-0.05417518053666f)}, + {FL2FXCONST_SGL(0.80001773566818f), FL2FXCONST_SGL(0.91542195141039f)}, + {FL2FXCONST_SGL(-0.79351832348816f), FL2FXCONST_SGL(-0.36208897989136f)}, + {FL2FXCONST_SGL(0.63872359151636f), FL2FXCONST_SGL(0.08128252493444f)}, + {FL2FXCONST_SGL(0.52890520960295f), FL2FXCONST_SGL(0.60048872455592f)}, + {FL2FXCONST_SGL(0.74238552914587f), FL2FXCONST_SGL(0.04491915291044f)}, + {FL2FXCONST_SGL(0.99096131449250f), FL2FXCONST_SGL(-0.19451182854402f)}, + {FL2FXCONST_SGL(-0.80412329643109f), FL2FXCONST_SGL(-0.88513818199457f)}, + {FL2FXCONST_SGL(-0.64612616129736f), FL2FXCONST_SGL(0.72198674804544f)}, + {FL2FXCONST_SGL(0.11657770663191f), FL2FXCONST_SGL(-0.83662833815041f)}, + {FL2FXCONST_SGL(-0.95053182488101f), FL2FXCONST_SGL(-0.96939905138082f)}, + {FL2FXCONST_SGL(-0.62228872928622f), FL2FXCONST_SGL(0.82767262846661f)}, + {FL2FXCONST_SGL(0.03004475787316f), FL2FXCONST_SGL(-0.99738896333384f)}, + {FL2FXCONST_SGL(-0.97987214341034f), FL2FXCONST_SGL(0.36526129686425f)}, + {FL2FXCONST_SGL(-0.99986980746200f), FL2FXCONST_SGL(-0.36021610299715f)}, + {FL2FXCONST_SGL(0.89110648599879f), FL2FXCONST_SGL(-0.97894250343044f)}, + {FL2FXCONST_SGL(0.10407960510582f), FL2FXCONST_SGL(0.77357793811619f)}, + {FL2FXCONST_SGL(0.95964737821728f), FL2FXCONST_SGL(-0.35435818285502f)}, + {FL2FXCONST_SGL(0.50843233159162f), FL2FXCONST_SGL(0.96107691266205f)}, + {FL2FXCONST_SGL(0.17006334670615f), FL2FXCONST_SGL(-0.76854025314829f)}, + {FL2FXCONST_SGL(0.25872675063360f), FL2FXCONST_SGL(0.99893303933816f)}, + {FL2FXCONST_SGL(-0.01115998681937f), FL2FXCONST_SGL(0.98496019742444f)}, + {FL2FXCONST_SGL(-0.79598702973261f), FL2FXCONST_SGL(0.97138411318894f)}, + {FL2FXCONST_SGL(-0.99264708948101f), FL2FXCONST_SGL(-0.99542822402536f)}, + {FL2FXCONST_SGL(-0.99829663752818f), FL2FXCONST_SGL(0.01877138824311f)}, + {FL2FXCONST_SGL(-0.70801016548184f), FL2FXCONST_SGL(0.33680685948117f)}, + {FL2FXCONST_SGL(-0.70467057786826f), FL2FXCONST_SGL(0.93272777501857f)}, + {FL2FXCONST_SGL(0.99846021905254f), FL2FXCONST_SGL(-0.98725746254433f)}, + {FL2FXCONST_SGL(-0.63364968534650f), FL2FXCONST_SGL(-0.16473594423746f)}, + {FL2FXCONST_SGL(-0.16258217500792f), FL2FXCONST_SGL(-0.95939125400802f)}, + {FL2FXCONST_SGL(-0.43645594360633f), FL2FXCONST_SGL(-0.94805030113284f)}, + {FL2FXCONST_SGL(-0.99848471702976f), FL2FXCONST_SGL(0.96245166923809f)}, + {FL2FXCONST_SGL(-0.16796458968998f), FL2FXCONST_SGL(-0.98987511890470f)}, + {FL2FXCONST_SGL(-0.87979225745213f), FL2FXCONST_SGL(-0.71725725041680f)}, + {FL2FXCONST_SGL(0.44183099021786f), FL2FXCONST_SGL(-0.93568974498761f)}, + {FL2FXCONST_SGL(0.93310180125532f), FL2FXCONST_SGL(-0.99913308068246f)}, + {FL2FXCONST_SGL(-0.93941931782002f), FL2FXCONST_SGL(-0.56409379640356f)}, + {FL2FXCONST_SGL(-0.88590003188677f), FL2FXCONST_SGL(0.47624600491382f)}, + {FL2FXCONST_SGL(0.99971463703691f), FL2FXCONST_SGL(-0.83889954253462f)}, + {FL2FXCONST_SGL(-0.75376385639978f), FL2FXCONST_SGL(0.00814643438625f)}, + {FL2FXCONST_SGL(0.93887685615875f), FL2FXCONST_SGL(-0.11284528204636f)}, + {FL2FXCONST_SGL(0.85126435782309f), FL2FXCONST_SGL(0.52349251543547f)}, + {FL2FXCONST_SGL(0.39701421446381f), FL2FXCONST_SGL(0.81779634174316f)}, + {FL2FXCONST_SGL(-0.37024464187437f), FL2FXCONST_SGL(-0.87071656222959f)}, + {FL2FXCONST_SGL(-0.36024828242896f), FL2FXCONST_SGL(0.34655735648287f)}, + {FL2FXCONST_SGL(-0.93388812549209f), FL2FXCONST_SGL(-0.84476541096429f)}, + {FL2FXCONST_SGL(-0.65298804552119f), FL2FXCONST_SGL(-0.18439575450921f)}, + {FL2FXCONST_SGL(0.11960319006843f), FL2FXCONST_SGL(0.99899346780168f)}, + {FL2FXCONST_SGL(0.94292565553160f), FL2FXCONST_SGL(0.83163906518293f)}, + {FL2FXCONST_SGL(0.75081145286948f), FL2FXCONST_SGL(-0.35533223142265f)}, + {FL2FXCONST_SGL(0.56721979748394f), FL2FXCONST_SGL(-0.24076836414499f)}, + {FL2FXCONST_SGL(0.46857766746029f), FL2FXCONST_SGL(-0.30140233457198f)}, + {FL2FXCONST_SGL(0.97312313923635f), FL2FXCONST_SGL(-0.99548191630031f)}, + {FL2FXCONST_SGL(-0.38299976567017f), FL2FXCONST_SGL(0.98516909715427f)}, + {FL2FXCONST_SGL(0.41025800019463f), FL2FXCONST_SGL(0.02116736935734f)}, + {FL2FXCONST_SGL(0.09638062008048f), FL2FXCONST_SGL(0.04411984381457f)}, + {FL2FXCONST_SGL(-0.85283249275397f), FL2FXCONST_SGL(0.91475563922421f)}, + {FL2FXCONST_SGL(0.88866808958124f), FL2FXCONST_SGL(-0.99735267083226f)}, + {FL2FXCONST_SGL(-0.48202429536989f), FL2FXCONST_SGL(-0.96805608884164f)}, + {FL2FXCONST_SGL(0.27572582416567f), FL2FXCONST_SGL(0.58634753335832f)}, + {FL2FXCONST_SGL(-0.65889129659168f), FL2FXCONST_SGL(0.58835634138583f)}, + {FL2FXCONST_SGL(0.98838086953732f), FL2FXCONST_SGL(0.99994349600236f)}, + {FL2FXCONST_SGL(-0.20651349620689f), FL2FXCONST_SGL(0.54593044066355f)}, + {FL2FXCONST_SGL(-0.62126416356920f), FL2FXCONST_SGL(-0.59893681700392f)}, + {FL2FXCONST_SGL(0.20320105410437f), FL2FXCONST_SGL(-0.86879180355289f)}, + {FL2FXCONST_SGL(-0.97790548600584f), FL2FXCONST_SGL(0.96290806999242f)}, + {FL2FXCONST_SGL(0.11112534735126f), FL2FXCONST_SGL(0.21484763313301f)}, + {FL2FXCONST_SGL(-0.41368337314182f), FL2FXCONST_SGL(0.28216837680365f)}, + {FL2FXCONST_SGL(0.24133038992960f), FL2FXCONST_SGL(0.51294362630238f)}, + {FL2FXCONST_SGL(-0.66393410674885f), FL2FXCONST_SGL(-0.08249679629081f)}, + {FL2FXCONST_SGL(-0.53697829178752f), FL2FXCONST_SGL(-0.97649903936228f)}, + {FL2FXCONST_SGL(-0.97224737889348f), FL2FXCONST_SGL(0.22081333579837f)}, + {FL2FXCONST_SGL(0.87392477144549f), FL2FXCONST_SGL(-0.12796173740361f)}, + {FL2FXCONST_SGL(0.19050361015753f), FL2FXCONST_SGL(0.01602615387195f)}, + {FL2FXCONST_SGL(-0.46353441212724f), FL2FXCONST_SGL(-0.95249041539006f)}, + {FL2FXCONST_SGL(-0.07064096339021f), FL2FXCONST_SGL(-0.94479803205886f)}, + {FL2FXCONST_SGL(-0.92444085484466f), FL2FXCONST_SGL(-0.10457590187436f)}, + {FL2FXCONST_SGL(-0.83822593578728f), FL2FXCONST_SGL(-0.01695043208885f)}, + {FL2FXCONST_SGL(0.75214681811150f), FL2FXCONST_SGL(-0.99955681042665f)}, + {FL2FXCONST_SGL(-0.42102998829339f), FL2FXCONST_SGL(0.99720941999394f)}, + {FL2FXCONST_SGL(-0.72094786237696f), FL2FXCONST_SGL(-0.35008961934255f)}, + {FL2FXCONST_SGL(0.78843311019251f), FL2FXCONST_SGL(0.52851398958271f)}, + {FL2FXCONST_SGL(0.97394027897442f), FL2FXCONST_SGL(-0.26695944086561f)}, + {FL2FXCONST_SGL(0.99206463477946f), FL2FXCONST_SGL(-0.57010120849429f)}, + {FL2FXCONST_SGL(0.76789609461795f), FL2FXCONST_SGL(-0.76519356730966f)}, + {FL2FXCONST_SGL(-0.82002421836409f), FL2FXCONST_SGL(-0.73530179553767f)}, + {FL2FXCONST_SGL(0.81924990025724f), FL2FXCONST_SGL(0.99698425250579f)}, + {FL2FXCONST_SGL(-0.26719850873357f), FL2FXCONST_SGL(0.68903369776193f)}, + {FL2FXCONST_SGL(-0.43311260380975f), FL2FXCONST_SGL(0.85321815947490f)}, + {FL2FXCONST_SGL(0.99194979673836f), FL2FXCONST_SGL(0.91876249766422f)}, + {FL2FXCONST_SGL(-0.80692001248487f), FL2FXCONST_SGL(-0.32627540663214f)}, + {FL2FXCONST_SGL(0.43080003649976f), FL2FXCONST_SGL(-0.21919095636638f)}, + {FL2FXCONST_SGL(0.67709491937357f), FL2FXCONST_SGL(-0.95478075822906f)}, + {FL2FXCONST_SGL(0.56151770568316f), FL2FXCONST_SGL(-0.70693811747778f)}, + {FL2FXCONST_SGL(0.10831862810749f), FL2FXCONST_SGL(-0.08628837174592f)}, + {FL2FXCONST_SGL(0.91229417540436f), FL2FXCONST_SGL(-0.65987351408410f)}, + {FL2FXCONST_SGL(-0.48972893932274f), FL2FXCONST_SGL(0.56289246362686f)}, + {FL2FXCONST_SGL(-0.89033658689697f), FL2FXCONST_SGL(-0.71656563987082f)}, + {FL2FXCONST_SGL(0.65269447475094f), FL2FXCONST_SGL(0.65916004833932f)}, + {FL2FXCONST_SGL(0.67439478141121f), FL2FXCONST_SGL(-0.81684380846796f)}, + {FL2FXCONST_SGL(-0.47770832416973f), FL2FXCONST_SGL(-0.16789556203025f)}, + {FL2FXCONST_SGL(-0.99715979260878f), FL2FXCONST_SGL(-0.93565784007648f)}, + {FL2FXCONST_SGL(-0.90889593602546f), FL2FXCONST_SGL(0.62034397054380f)}, + {FL2FXCONST_SGL(-0.06618622548177f), FL2FXCONST_SGL(-0.23812217221359f)}, + {FL2FXCONST_SGL(0.99430266919728f), FL2FXCONST_SGL(0.18812555317553f)}, + {FL2FXCONST_SGL(0.97686402381843f), FL2FXCONST_SGL(-0.28664534366620f)}, + {FL2FXCONST_SGL(0.94813650221268f), FL2FXCONST_SGL(-0.97506640027128f)}, + {FL2FXCONST_SGL(-0.95434497492853f), FL2FXCONST_SGL(-0.79607978501983f)}, + {FL2FXCONST_SGL(-0.49104783137150f), FL2FXCONST_SGL(0.32895214359663f)}, + {FL2FXCONST_SGL(0.99881175120751f), FL2FXCONST_SGL(0.88993983831354f)}, + {FL2FXCONST_SGL(0.50449166760303f), FL2FXCONST_SGL(-0.85995072408434f)}, + {FL2FXCONST_SGL(0.47162891065108f), FL2FXCONST_SGL(-0.18680204049569f)}, + {FL2FXCONST_SGL(-0.62081581361840f), FL2FXCONST_SGL(0.75000676218956f)}, + {FL2FXCONST_SGL(-0.43867015250812f), FL2FXCONST_SGL(0.99998069244322f)}, + {FL2FXCONST_SGL(0.98630563232075f), FL2FXCONST_SGL(-0.53578899600662f)}, + {FL2FXCONST_SGL(-0.61510362277374f), FL2FXCONST_SGL(-0.89515019899997f)}, + {FL2FXCONST_SGL(-0.03841517601843f), FL2FXCONST_SGL(-0.69888815681179f)}, + {FL2FXCONST_SGL(-0.30102157304644f), FL2FXCONST_SGL(-0.07667808922205f)}, + {FL2FXCONST_SGL(0.41881284182683f), FL2FXCONST_SGL(0.02188098922282f)}, + {FL2FXCONST_SGL(-0.86135454941237f), FL2FXCONST_SGL(0.98947480909359f)}, + {FL2FXCONST_SGL(0.67226861393788f), FL2FXCONST_SGL(-0.13494389011014f)}, + {FL2FXCONST_SGL(-0.70737398842068f), FL2FXCONST_SGL(-0.76547349325992f)}, + {FL2FXCONST_SGL(0.94044946687963f), FL2FXCONST_SGL(0.09026201157416f)}, + {FL2FXCONST_SGL(-0.82386352534327f), FL2FXCONST_SGL(0.08924768823676f)}, + {FL2FXCONST_SGL(-0.32070666698656f), FL2FXCONST_SGL(0.50143421908753f)}, + {FL2FXCONST_SGL(0.57593163224487f), FL2FXCONST_SGL(-0.98966422921509f)}, + {FL2FXCONST_SGL(-0.36326018419965f), FL2FXCONST_SGL(0.07440243123228f)}, + {FL2FXCONST_SGL(0.99979044674350f), FL2FXCONST_SGL(-0.14130287347405f)}, + {FL2FXCONST_SGL(-0.92366023326932f), FL2FXCONST_SGL(-0.97979298068180f)}, + {FL2FXCONST_SGL(-0.44607178518598f), FL2FXCONST_SGL(-0.54233252016394f)}, + {FL2FXCONST_SGL(0.44226800932956f), FL2FXCONST_SGL(0.71326756742752f)}, + {FL2FXCONST_SGL(0.03671907158312f), FL2FXCONST_SGL(0.63606389366675f)}, + {FL2FXCONST_SGL(0.52175424682195f), FL2FXCONST_SGL(-0.85396826735705f)}, + {FL2FXCONST_SGL(-0.94701139690956f), FL2FXCONST_SGL(-0.01826348194255f)}, + {FL2FXCONST_SGL(-0.98759606946049f), FL2FXCONST_SGL(0.82288714303073f)}, + {FL2FXCONST_SGL(0.87434794743625f), FL2FXCONST_SGL(0.89399495655433f)}, + {FL2FXCONST_SGL(-0.93412041758744f), FL2FXCONST_SGL(0.41374052024363f)}, + {FL2FXCONST_SGL(0.96063943315511f), FL2FXCONST_SGL(0.93116709541280f)}, + {FL2FXCONST_SGL(0.97534253457837f), FL2FXCONST_SGL(0.86150930812689f)}, + {FL2FXCONST_SGL(0.99642466504163f), FL2FXCONST_SGL(0.70190043427512f)}, + {FL2FXCONST_SGL(-0.94705089665984f), FL2FXCONST_SGL(-0.29580042814306f)}, + {FL2FXCONST_SGL(0.91599807087376f), FL2FXCONST_SGL(-0.98147830385781f)}}; +//@} + +/* +static const FIXP_SGL harmonicPhase [2][4] = { + { 1.0, 0.0, -1.0, 0.0}, + { 0.0, 1.0, 0.0, -1.0} +}; +*/ + +/* tables for SBR and AAC LD */ +/* table for 8 time slot index */ +const int FDK_sbrDecoder_envelopeTable_8[8][5] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* borders from left to right side; -1 = not in use */ + /*[|T-|------]*/ {2, 0, 0, 1, -1}, + /*[|-T-|-----]*/ {2, 0, 0, 2, -1}, + /*[--|T-|----]*/ {3, 1, 1, 2, 4}, + /*[---|T-|---]*/ {3, 1, 1, 3, 5}, + /*[----|T-|--]*/ {3, 1, 1, 4, 6}, + /*[-----|T--|]*/ {2, 1, 1, 5, -1}, + /*[------|T-|]*/ {2, 1, 1, 6, -1}, + /*[-------|T|]*/ {2, 1, 1, 7, -1}, +}; + +/* table for 15 time slot index */ +const int FDK_sbrDecoder_envelopeTable_15[15][6] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* length from left to right side; -1 = not in use */ + /*[|T---|------------]*/ {2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------]*/ {2, 0, 0, 5, -1, -1}, + /*[|--|T---|---------]*/ {3, 1, 1, 2, 6, -1}, + /*[|---|T---|--------]*/ {3, 1, 1, 3, 7, -1}, + /*[|----|T---|-------]*/ {3, 1, 1, 4, 8, -1}, + /*[|-----|T---|------]*/ {3, 1, 1, 5, 9, -1}, + /*[|------|T---|-----]*/ {3, 1, 1, 6, 10, -1}, + /*[|-------|T---|----]*/ {3, 1, 1, 7, 11, -1}, + /*[|--------|T---|---]*/ {3, 1, 1, 8, 12, -1}, + /*[|---------|T---|--]*/ {3, 1, 1, 9, 13, -1}, + /*[|----------|T----|]*/ {2, 1, 1, 10, -1, -1}, + /*[|-----------|T---|]*/ {2, 1, 1, 11, -1, -1}, + /*[|------------|T--|]*/ {2, 1, 1, 12, -1, -1}, + /*[|-------------|T-|]*/ {2, 1, 1, 13, -1, -1}, + /*[|--------------|T|]*/ {2, 1, 1, 14, -1, -1}, +}; + +/* table for 16 time slot index */ +const int FDK_sbrDecoder_envelopeTable_16[16][6] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* length from left to right side; -1 = not in use */ + /*[|T---|------------|]*/ {2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------|]*/ {2, 0, 0, 5, -1, -1}, + /*[|--|T---|----------]*/ {3, 1, 1, 2, 6, -1}, + /*[|---|T---|---------]*/ {3, 1, 1, 3, 7, -1}, + /*[|----|T---|--------]*/ {3, 1, 1, 4, 8, -1}, + /*[|-----|T---|-------]*/ {3, 1, 1, 5, 9, -1}, + /*[|------|T---|------]*/ {3, 1, 1, 6, 10, -1}, + /*[|-------|T---|-----]*/ {3, 1, 1, 7, 11, -1}, + /*[|--------|T---|----]*/ {3, 1, 1, 8, 12, -1}, + /*[|---------|T---|---]*/ {3, 1, 1, 9, 13, -1}, + /*[|----------|T---|--]*/ {3, 1, 1, 10, 14, -1}, + /*[|-----------|T----|]*/ {2, 1, 1, 11, -1, -1}, + /*[|------------|T---|]*/ {2, 1, 1, 12, -1, -1}, + /*[|-------------|T--|]*/ {2, 1, 1, 13, -1, -1}, + /*[|--------------|T-|]*/ {2, 1, 1, 14, -1, -1}, + /*[|---------------|T|]*/ {2, 1, 1, 15, -1, -1}, +}; + +/*! + \name FrameInfoDefaults + + Predefined envelope positions for the FIX-FIX case (static framing) +*/ +//@{ +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info1_15 = { + 0, 1, {0, 15, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, -1, 1, {0, 15, 0}, {0, 0, 0}, + 0, 0}; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info2_15 = { + 0, 2, {0, 8, 15, 0, 0, 0}, {1, 1, 0, 0, 0}, -1, 2, {0, 8, 15}, {0, 0, 0}, + 0, 0}; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info4_15 = { + 0, 4, {0, 4, 8, 12, 15, 0}, {1, 1, 1, 1, 0}, -1, 2, {0, 8, 15}, {0, 0, 0}, + 0, 0}; +#if (MAX_ENVELOPES >= 8) +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info8_15 = { + 0, + 8, + {0, 2, 4, 6, 8, 10, 12, 14, 15}, + {1, 1, 1, 1, 1, 1, 1, 1}, + -1, + 2, + {0, 8, 15}, + {0, 0, 0}, + 0, + 0}; +#endif + +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info1_16 = { + 0, 1, {0, 16, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, -1, 1, {0, 16, 0}, {0, 0, 0}, + 0, 0}; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info2_16 = { + 0, 2, {0, 8, 16, 0, 0, 0}, {1, 1, 0, 0, 0}, -1, 2, {0, 8, 16}, {0, 0, 0}, + 0, 0}; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info4_16 = { + 0, 4, {0, 4, 8, 12, 16, 0}, {1, 1, 1, 1, 0}, -1, 2, {0, 8, 16}, {0, 0, 0}, + 0, 0}; + +#if (MAX_ENVELOPES >= 8) +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info8_16 = { + 0, + 8, + {0, 2, 4, 6, 8, 10, 12, 14, 16}, + {1, 1, 1, 1, 1, 1, 1, 1}, + -1, + 2, + {0, 8, 16}, + {0, 0, 0}, + 0, + 0}; +#endif + +//@} + +/*! + \name SBR_HuffmanTables + + SBR Huffman Table Overview: \n + \n + o envelope level, 1.5 dB: \n + 1) sbr_huffBook_EnvLevel10T[120][2] \n + 2) sbr_huffBook_EnvLevel10F[120][2] \n + \n + o envelope balance, 1.5 dB: \n + 3) sbr_huffBook_EnvBalance10T[48][2] \n + 4) sbr_huffBook_EnvBalance10F[48][2] \n + \n + o envelope level, 3.0 dB: \n + 5) sbr_huffBook_EnvLevel11T[62][2] \n + 6) sbr_huffBook_EnvLevel11F[62][2] \n + \n + o envelope balance, 3.0 dB: \n + 7) sbr_huffBook_EnvBalance11T[24][2] \n + 8) sbr_huffBook_EnvBalance11F[24][2] \n + \n + o noise level, 3.0 dB: \n + 9) sbr_huffBook_NoiseLevel11T[62][2] \n + -) (sbr_huffBook_EnvLevel11F[62][2] is used for freq dir)\n + \n + o noise balance, 3.0 dB: \n + 10) sbr_huffBook_NoiseBalance11T[24][2]\n + -) (sbr_huffBook_EnvBalance11F[24][2] is used for freq dir)\n + \n + (1.5 dB is never used for noise) + +*/ +//@{ +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel10T[120][2] = { + {1, 2}, {-64, -65}, {3, 4}, {-63, -66}, {5, 6}, + {-62, -67}, {7, 8}, {-61, -68}, {9, 10}, {-60, -69}, + {11, 12}, {-59, -70}, {13, 14}, {-58, -71}, {15, 16}, + {-57, -72}, {17, 18}, {-73, -56}, {19, 21}, {-74, 20}, + {-55, -75}, {22, 26}, {23, 24}, {-54, -76}, {-77, 25}, + {-53, -78}, {27, 34}, {28, 29}, {-52, -79}, {30, 31}, + {-80, -51}, {32, 33}, {-83, -82}, {-81, -50}, {35, 57}, + {36, 40}, {37, 38}, {-88, -84}, {-48, 39}, {-90, -85}, + {41, 46}, {42, 43}, {-49, -87}, {44, 45}, {-89, -86}, + {-124, -123}, {47, 50}, {48, 49}, {-122, -121}, {-120, -119}, + {51, 54}, {52, 53}, {-118, -117}, {-116, -115}, {55, 56}, + {-114, -113}, {-112, -111}, {58, 89}, {59, 74}, {60, 67}, + {61, 64}, {62, 63}, {-110, -109}, {-108, -107}, {65, 66}, + {-106, -105}, {-104, -103}, {68, 71}, {69, 70}, {-102, -101}, + {-100, -99}, {72, 73}, {-98, -97}, {-96, -95}, {75, 82}, + {76, 79}, {77, 78}, {-94, -93}, {-92, -91}, {80, 81}, + {-47, -46}, {-45, -44}, {83, 86}, {84, 85}, {-43, -42}, + {-41, -40}, {87, 88}, {-39, -38}, {-37, -36}, {90, 105}, + {91, 98}, {92, 95}, {93, 94}, {-35, -34}, {-33, -32}, + {96, 97}, {-31, -30}, {-29, -28}, {99, 102}, {100, 101}, + {-27, -26}, {-25, -24}, {103, 104}, {-23, -22}, {-21, -20}, + {106, 113}, {107, 110}, {108, 109}, {-19, -18}, {-17, -16}, + {111, 112}, {-15, -14}, {-13, -12}, {114, 117}, {115, 116}, + {-11, -10}, {-9, -8}, {118, 119}, {-7, -6}, {-5, -4}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel10F[120][2] = { + {1, 2}, {-64, -65}, {3, 4}, {-63, -66}, {5, 6}, + {-67, -62}, {7, 8}, {-68, -61}, {9, 10}, {-69, -60}, + {11, 13}, {-70, 12}, {-59, -71}, {14, 16}, {-58, 15}, + {-72, -57}, {17, 19}, {-73, 18}, {-56, -74}, {20, 23}, + {21, 22}, {-55, -75}, {-54, -53}, {24, 27}, {25, 26}, + {-76, -52}, {-77, -51}, {28, 31}, {29, 30}, {-50, -78}, + {-79, -49}, {32, 36}, {33, 34}, {-48, -47}, {-80, 35}, + {-81, -82}, {37, 47}, {38, 41}, {39, 40}, {-83, -46}, + {-45, -84}, {42, 44}, {-85, 43}, {-44, -43}, {45, 46}, + {-88, -87}, {-86, -90}, {48, 66}, {49, 56}, {50, 53}, + {51, 52}, {-92, -42}, {-41, -39}, {54, 55}, {-105, -89}, + {-38, -37}, {57, 60}, {58, 59}, {-94, -91}, {-40, -36}, + {61, 63}, {-20, 62}, {-115, -110}, {64, 65}, {-108, -107}, + {-101, -97}, {67, 89}, {68, 75}, {69, 72}, {70, 71}, + {-95, -93}, {-34, -27}, {73, 74}, {-22, -17}, {-16, -124}, + {76, 82}, {77, 79}, {-123, 78}, {-122, -121}, {80, 81}, + {-120, -119}, {-118, -117}, {83, 86}, {84, 85}, {-116, -114}, + {-113, -112}, {87, 88}, {-111, -109}, {-106, -104}, {90, 105}, + {91, 98}, {92, 95}, {93, 94}, {-103, -102}, {-100, -99}, + {96, 97}, {-98, -96}, {-35, -33}, {99, 102}, {100, 101}, + {-32, -31}, {-30, -29}, {103, 104}, {-28, -26}, {-25, -24}, + {106, 113}, {107, 110}, {108, 109}, {-23, -21}, {-19, -18}, + {111, 112}, {-15, -14}, {-13, -12}, {114, 117}, {115, 116}, + {-11, -10}, {-9, -8}, {118, 119}, {-7, -6}, {-5, -4}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance10T[48][2] = { + {-64, 1}, {-63, 2}, {-65, 3}, {-62, 4}, {-66, 5}, {-61, 6}, + {-67, 7}, {-60, 8}, {-68, 9}, {10, 11}, {-69, -59}, {12, 13}, + {-70, -58}, {14, 28}, {15, 21}, {16, 18}, {-57, 17}, {-71, -56}, + {19, 20}, {-88, -87}, {-86, -85}, {22, 25}, {23, 24}, {-84, -83}, + {-82, -81}, {26, 27}, {-80, -79}, {-78, -77}, {29, 36}, {30, 33}, + {31, 32}, {-76, -75}, {-74, -73}, {34, 35}, {-72, -55}, {-54, -53}, + {37, 41}, {38, 39}, {-52, -51}, {-50, 40}, {-49, -48}, {42, 45}, + {43, 44}, {-47, -46}, {-45, -44}, {46, 47}, {-43, -42}, {-41, -40}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance10F[48][2] = { + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-61, 6}, + {-67, 7}, {-68, 8}, {-60, 9}, {10, 11}, {-69, -59}, {-70, 12}, + {-58, 13}, {14, 17}, {-71, 15}, {-57, 16}, {-56, -73}, {18, 32}, + {19, 25}, {20, 22}, {-72, 21}, {-88, -87}, {23, 24}, {-86, -85}, + {-84, -83}, {26, 29}, {27, 28}, {-82, -81}, {-80, -79}, {30, 31}, + {-78, -77}, {-76, -75}, {33, 40}, {34, 37}, {35, 36}, {-74, -55}, + {-54, -53}, {38, 39}, {-52, -51}, {-50, -49}, {41, 44}, {42, 43}, + {-48, -47}, {-46, -45}, {45, 46}, {-44, -43}, {-42, 47}, {-41, -40}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel11T[62][2] = { + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-67, 6}, + {-61, 7}, {-68, 8}, {-60, 9}, {10, 11}, {-69, -59}, {12, 14}, + {-70, 13}, {-71, -58}, {15, 18}, {16, 17}, {-72, -57}, {-73, -74}, + {19, 22}, {-56, 20}, {-55, 21}, {-54, -77}, {23, 31}, {24, 25}, + {-75, -76}, {26, 27}, {-78, -53}, {28, 29}, {-52, -95}, {-94, 30}, + {-93, -92}, {32, 47}, {33, 40}, {34, 37}, {35, 36}, {-91, -90}, + {-89, -88}, {38, 39}, {-87, -86}, {-85, -84}, {41, 44}, {42, 43}, + {-83, -82}, {-81, -80}, {45, 46}, {-79, -51}, {-50, -49}, {48, 55}, + {49, 52}, {50, 51}, {-48, -47}, {-46, -45}, {53, 54}, {-44, -43}, + {-42, -41}, {56, 59}, {57, 58}, {-40, -39}, {-38, -37}, {60, 61}, + {-36, -35}, {-34, -33}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel11F[62][2] = { + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-67, 6}, + {7, 8}, {-61, -68}, {9, 10}, {-60, -69}, {11, 12}, {-59, -70}, + {13, 14}, {-58, -71}, {15, 16}, {-57, -72}, {17, 19}, {-56, 18}, + {-55, -73}, {20, 24}, {21, 22}, {-74, -54}, {-53, 23}, {-75, -76}, + {25, 30}, {26, 27}, {-52, -51}, {28, 29}, {-77, -79}, {-50, -49}, + {31, 39}, {32, 35}, {33, 34}, {-78, -46}, {-82, -88}, {36, 37}, + {-83, -48}, {-47, 38}, {-86, -85}, {40, 47}, {41, 44}, {42, 43}, + {-80, -44}, {-43, -42}, {45, 46}, {-39, -87}, {-84, -40}, {48, 55}, + {49, 52}, {50, 51}, {-95, -94}, {-93, -92}, {53, 54}, {-91, -90}, + {-89, -81}, {56, 59}, {57, 58}, {-45, -41}, {-38, -37}, {60, 61}, + {-36, -35}, {-34, -33}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance11T[24][2] = { + {-64, 1}, {-63, 2}, {-65, 3}, {-66, 4}, {-62, 5}, {-61, 6}, + {-67, 7}, {-68, 8}, {-60, 9}, {10, 16}, {11, 13}, {-69, 12}, + {-76, -75}, {14, 15}, {-74, -73}, {-72, -71}, {17, 20}, {18, 19}, + {-70, -59}, {-58, -57}, {21, 22}, {-56, -55}, {-54, 23}, {-53, -52}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance11F[24][2] = { + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-61, 6}, + {-67, 7}, {-68, 8}, {-60, 9}, {10, 13}, {-69, 11}, {-59, 12}, + {-58, -76}, {14, 17}, {15, 16}, {-75, -74}, {-73, -72}, {18, 21}, + {19, 20}, {-71, -70}, {-57, -56}, {22, 23}, {-55, -54}, {-53, -52}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_NoiseLevel11T[62][2] = { + {-64, 1}, {-63, 2}, {-65, 3}, {-66, 4}, {-62, 5}, {-67, 6}, + {7, 8}, {-61, -68}, {9, 30}, {10, 15}, {-60, 11}, {-69, 12}, + {13, 14}, {-59, -53}, {-95, -94}, {16, 23}, {17, 20}, {18, 19}, + {-93, -92}, {-91, -90}, {21, 22}, {-89, -88}, {-87, -86}, {24, 27}, + {25, 26}, {-85, -84}, {-83, -82}, {28, 29}, {-81, -80}, {-79, -78}, + {31, 46}, {32, 39}, {33, 36}, {34, 35}, {-77, -76}, {-75, -74}, + {37, 38}, {-73, -72}, {-71, -70}, {40, 43}, {41, 42}, {-58, -57}, + {-56, -55}, {44, 45}, {-54, -52}, {-51, -50}, {47, 54}, {48, 51}, + {49, 50}, {-49, -48}, {-47, -46}, {52, 53}, {-45, -44}, {-43, -42}, + {55, 58}, {56, 57}, {-41, -40}, {-39, -38}, {59, 60}, {-37, -36}, + {-35, 61}, {-34, -33}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_NoiseBalance11T[24][2] = { + {-64, 1}, {-65, 2}, {-63, 3}, {4, 9}, {-66, 5}, {-62, 6}, + {7, 8}, {-76, -75}, {-74, -73}, {10, 17}, {11, 14}, {12, 13}, + {-72, -71}, {-70, -69}, {15, 16}, {-68, -67}, {-61, -60}, {18, 21}, + {19, 20}, {-59, -58}, {-57, -56}, {22, 23}, {-55, -54}, {-53, -52}}; +//@} + +/*! + \name parametric stereo + \brief constants used by the parametric stereo part of the decoder + +*/ + +/* constants used in psbitdec.cpp */ + +/* FIX_BORDER can have 0, 1, 2, 4 envelopes */ +const UCHAR FDK_sbrDecoder_aFixNoEnvDecode[4] = {0, 1, 2, 4}; + +/* IID & ICC Huffman codebooks */ +const SCHAR aBookPsIidTimeDecode[28][2] = { + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-67, 6}, + {-61, 7}, {-68, 8}, {-60, 9}, {-69, 10}, {-59, 11}, {-70, 12}, + {-58, 13}, {-57, 14}, {-71, 15}, {16, 17}, {-56, -72}, {18, 21}, + {19, 20}, {-55, -78}, {-77, -76}, {22, 25}, {23, 24}, {-75, -74}, + {-73, -54}, {26, 27}, {-53, -52}, {-51, -50}}; + +const SCHAR aBookPsIidFreqDecode[28][2] = { + {-64, 1}, {2, 3}, {-63, -65}, {4, 5}, {-62, -66}, {6, 7}, + {-61, -67}, {8, 9}, {-68, -60}, {-59, 10}, {-69, 11}, {-58, 12}, + {-70, 13}, {-71, 14}, {-57, 15}, {16, 17}, {-56, -72}, {18, 19}, + {-55, -54}, {20, 21}, {-73, -53}, {22, 24}, {-74, 23}, {-75, -78}, + {25, 26}, {-77, -76}, {-52, 27}, {-51, -50}}; + +const SCHAR aBookPsIccTimeDecode[14][2] = { + {-64, 1}, {-63, 2}, {-65, 3}, {-62, 4}, {-66, 5}, {-61, 6}, {-67, 7}, + {-60, 8}, {-68, 9}, {-59, 10}, {-69, 11}, {-58, 12}, {-70, 13}, {-71, -57}}; + +const SCHAR aBookPsIccFreqDecode[14][2] = { + {-64, 1}, {-63, 2}, {-65, 3}, {-62, 4}, {-66, 5}, {-61, 6}, {-67, 7}, + {-60, 8}, {-59, 9}, {-68, 10}, {-58, 11}, {-69, 12}, {-57, 13}, {-70, -71}}; + +/* IID-fine Huffman codebooks */ + +const SCHAR aBookPsIidFineTimeDecode[60][2] = { + {1, -64}, {-63, 2}, {3, -65}, {4, 59}, {5, 7}, {6, -67}, + {-68, -60}, {-61, 8}, {9, 11}, {-59, 10}, {-70, -58}, {12, 41}, + {13, 20}, {14, -71}, {-55, 15}, {-53, 16}, {17, -77}, {18, 19}, + {-85, -84}, {-46, -45}, {-57, 21}, {22, 40}, {23, 29}, {-51, 24}, + {25, 26}, {-83, -82}, {27, 28}, {-90, -38}, {-92, -91}, {30, 37}, + {31, 34}, {32, 33}, {-35, -34}, {-37, -36}, {35, 36}, {-94, -93}, + {-89, -39}, {38, -79}, {39, -81}, {-88, -40}, {-74, -54}, {42, -69}, + {43, 44}, {-72, -56}, {45, 52}, {46, 50}, {47, -76}, {-49, 48}, + {-47, 49}, {-87, -41}, {-52, 51}, {-78, -50}, {53, -73}, {54, -75}, + {55, 57}, {56, -80}, {-86, -42}, {-48, 58}, {-44, -43}, {-66, -62}}; + +const SCHAR aBookPsIidFineFreqDecode[60][2] = { + {1, -64}, {2, 4}, {3, -65}, {-66, -62}, {-63, 5}, {6, 7}, + {-67, -61}, {8, 9}, {-68, -60}, {10, 11}, {-69, -59}, {12, 13}, + {-70, -58}, {14, 18}, {-57, 15}, {16, -72}, {-54, 17}, {-75, -53}, + {19, 37}, {-56, 20}, {21, -73}, {22, 29}, {23, -76}, {24, -78}, + {25, 28}, {26, 27}, {-85, -43}, {-83, -45}, {-81, -47}, {-52, 30}, + {-50, 31}, {32, -79}, {33, 34}, {-82, -46}, {35, 36}, {-90, -89}, + {-92, -91}, {38, -71}, {-55, 39}, {40, -74}, {41, 50}, {42, -77}, + {-49, 43}, {44, 47}, {45, 46}, {-86, -42}, {-88, -87}, {48, 49}, + {-39, -38}, {-41, -40}, {-51, 51}, {52, 59}, {53, 56}, {54, 55}, + {-35, -34}, {-37, -36}, {57, 58}, {-94, -93}, {-84, -44}, {-80, -48}}; + +/* constants used in psdec.cpp */ + +/* the values of the following 3 tables are shiftet right by 1 ! */ +const FIXP_DBL ScaleFactors[NO_IID_LEVELS] = { + + 0x5a5ded00, 0x59cd0400, 0x58c29680, 0x564c2e80, 0x52a3d480, + 0x4c8be080, 0x46df3080, 0x40000000, 0x384ba5c0, 0x304c2980, + 0x24e9f640, 0x1b4a2940, 0x11b5c0a0, 0x0b4e2540, 0x0514ea90}; + +const FIXP_DBL ScaleFactorsFine[NO_IID_LEVELS_FINE] = { + + 0x5a825c00, 0x5a821c00, 0x5a815100, 0x5a7ed000, 0x5a76e600, 0x5a5ded00, + 0x5a39b880, 0x59f1fd00, 0x5964d680, 0x5852ca00, 0x564c2e80, 0x54174480, + 0x50ea7500, 0x4c8be080, 0x46df3080, 0x40000000, 0x384ba5c0, 0x304c2980, + 0x288dd240, 0x217a2900, 0x1b4a2940, 0x13c5ece0, 0x0e2b0090, 0x0a178ef0, + 0x072ab798, 0x0514ea90, 0x02dc5944, 0x019bf87c, 0x00e7b173, 0x00824b8b, + 0x00494568}; +const FIXP_DBL Alphas[NO_ICC_LEVELS] = { + + 0x00000000, 0x0b6b5be0, 0x12485f80, 0x1da2fa40, + 0x2637ebc0, 0x3243f6c0, 0x466b7480, 0x6487ed80}; + +const UCHAR bins2groupMap20[NO_IID_GROUPS] = { + 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +const UCHAR FDK_sbrDecoder_aNoIidBins[3] = { + NO_LOW_RES_IID_BINS, NO_MID_RES_IID_BINS, NO_HI_RES_IID_BINS}; + +const UCHAR FDK_sbrDecoder_aNoIccBins[3] = { + NO_LOW_RES_ICC_BINS, NO_MID_RES_ICC_BINS, NO_HI_RES_ICC_BINS}; + +/************************************************************************/ +/*! + \brief Create lookup tables for some arithmetic functions + + The tables would normally be defined as const arrays, + but initialization at run time allows to specify their accuracy. +*/ +/************************************************************************/ + +/* 1/x-table: (example for INV_TABLE_BITS 8) + + The table covers an input range from 0.5 to 1.0 with a step size of 1/512, + starting at 0.5 + 1/512. + Each table entry corresponds to an input interval starting 1/1024 below the + exact value and ending 1/1024 above it. + + The table is actually a 0.5/x-table, so that the output range is again + 0.5...1.0 and the exponent of the result must be increased by 1. + + Input range Index in table result + ------------------------------------------------------------------- + 0.500000...0.500976 - 0.5 / 0.500000 = 1.000000 + 0.500976...0.502930 0 0.5 / 0.501953 = 0.996109 + 0.502930...0.500488 1 0.5 / 0.503906 = 0.992248 + ... + 0.999023...1.000000 255 0.5 / 1.000000 = 0.500000 + + for (i=0; iprevFact_mag[band] = FL2FXCONST_DBL(0.5f); + } + + for (band = 0; band < SBRDEC_MAX_DRC_BANDS; band++) { + hDrcData->currFact_mag[band] = FL2FXCONST_DBL(0.5f); + hDrcData->nextFact_mag[band] = FL2FXCONST_DBL(0.5f); + } + + hDrcData->prevFact_exp = 1; + hDrcData->currFact_exp = 1; + hDrcData->nextFact_exp = 1; + + hDrcData->numBandsCurr = 1; + hDrcData->numBandsNext = 1; + + hDrcData->winSequenceCurr = 0; + hDrcData->winSequenceNext = 0; + + hDrcData->drcInterpolationSchemeCurr = 0; + hDrcData->drcInterpolationSchemeNext = 0; + + hDrcData->enable = 0; +} + +/*! + \brief Swap DRC QMF scaling factors after they have been applied. + + \hDrcData Handle to DRC channel data. + + \return none +*/ +void sbrDecoder_drcUpdateChannel(HANDLE_SBR_DRC_CHANNEL hDrcData) { + if (hDrcData == NULL) { + return; + } + if (hDrcData->enable != 1) { + return; + } + + /* swap previous data */ + FDKmemcpy(hDrcData->currFact_mag, hDrcData->nextFact_mag, + SBRDEC_MAX_DRC_BANDS * sizeof(FIXP_DBL)); + + hDrcData->currFact_exp = hDrcData->nextFact_exp; + + hDrcData->numBandsCurr = hDrcData->numBandsNext; + + FDKmemcpy(hDrcData->bandTopCurr, hDrcData->bandTopNext, + SBRDEC_MAX_DRC_BANDS * sizeof(USHORT)); + + hDrcData->drcInterpolationSchemeCurr = hDrcData->drcInterpolationSchemeNext; + + hDrcData->winSequenceCurr = hDrcData->winSequenceNext; +} + +/*! + \brief Apply DRC factors slot based. + + \hDrcData Handle to DRC channel data. + \qmfRealSlot Pointer to real valued QMF data of one time slot. + \qmfImagSlot Pointer to the imaginary QMF data of one time slot. + \col Number of the time slot. + \numQmfSubSamples Total number of time slots for one frame. + \scaleFactor Pointer to the out scale factor of the time slot. + + \return None. +*/ +void sbrDecoder_drcApplySlot(HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL *qmfRealSlot, FIXP_DBL *qmfImagSlot, + int col, int numQmfSubSamples, int maxShift) { + const UCHAR *winBorderToColMap; + + int band, bottomMdct, topMdct, bin, useLP; + int indx = numQmfSubSamples - (numQmfSubSamples >> 1) - 10; /* l_border */ + int frameLenFlag = (numQmfSubSamples == 30) ? 1 : 0; + int frameSize = (frameLenFlag == 1) ? 960 : 1024; + + const FIXP_DBL *fact_mag = NULL; + INT fact_exp = 0; + UINT numBands = 0; + USHORT *bandTop = NULL; + int shortDrc = 0; + + FIXP_DBL alphaValue = FL2FXCONST_DBL(0.0f); + + if (hDrcData == NULL) { + return; + } + if (hDrcData->enable != 1) { + return; + } + + winBorderToColMap = winBorderToColMappingTab[frameLenFlag]; + + useLP = (qmfImagSlot == NULL) ? 1 : 0; + + col += indx; + bottomMdct = 0; + + /* get respective data and calc interpolation factor */ + if (col < (numQmfSubSamples >> 1)) { /* first half of current frame */ + if (hDrcData->winSequenceCurr != 2) { /* long window */ + int j = col + (numQmfSubSamples >> 1); + + if (j < winBorderToColMap[15]) { + if (hDrcData->drcInterpolationSchemeCurr == 0) { + INT k = (frameLenFlag) ? 0x4444445 : 0x4000000; + + alphaValue = (FIXP_DBL)(j * k); + } else { + if (j >= + (int)winBorderToColMap[hDrcData->drcInterpolationSchemeCurr]) { + alphaValue = (FIXP_DBL)MAXVAL_DBL; + } + } + } else { + alphaValue = (FIXP_DBL)MAXVAL_DBL; + } + } else { /* short windows */ + shortDrc = 1; + } + + fact_mag = hDrcData->currFact_mag; + fact_exp = hDrcData->currFact_exp; + numBands = hDrcData->numBandsCurr; + bandTop = hDrcData->bandTopCurr; + } else if (col < numQmfSubSamples) { /* second half of current frame */ + if (hDrcData->winSequenceNext != 2) { /* next: long window */ + int j = col - (numQmfSubSamples >> 1); + + if (j < winBorderToColMap[15]) { + if (hDrcData->drcInterpolationSchemeNext == 0) { + INT k = (frameLenFlag) ? 0x4444445 : 0x4000000; + + alphaValue = (FIXP_DBL)(j * k); + } else { + if (j >= + (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) { + alphaValue = (FIXP_DBL)MAXVAL_DBL; + } + } + } else { + alphaValue = (FIXP_DBL)MAXVAL_DBL; + } + + fact_mag = hDrcData->nextFact_mag; + fact_exp = hDrcData->nextFact_exp; + numBands = hDrcData->numBandsNext; + bandTop = hDrcData->bandTopNext; + } else { /* next: short windows */ + if (hDrcData->winSequenceCurr != 2) { /* current: long window */ + alphaValue = (FIXP_DBL)0; + + fact_mag = hDrcData->nextFact_mag; + fact_exp = hDrcData->nextFact_exp; + numBands = hDrcData->numBandsNext; + bandTop = hDrcData->bandTopNext; + } else { /* current: short windows */ + shortDrc = 1; + + fact_mag = hDrcData->currFact_mag; + fact_exp = hDrcData->currFact_exp; + numBands = hDrcData->numBandsCurr; + bandTop = hDrcData->bandTopCurr; + } + } + } else { /* first half of next frame */ + if (hDrcData->winSequenceNext != 2) { /* long window */ + int j = col - (numQmfSubSamples >> 1); + + if (j < winBorderToColMap[15]) { + if (hDrcData->drcInterpolationSchemeNext == 0) { + INT k = (frameLenFlag) ? 0x4444445 : 0x4000000; + + alphaValue = (FIXP_DBL)(j * k); + } else { + if (j >= + (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) { + alphaValue = (FIXP_DBL)MAXVAL_DBL; + } + } + } else { + alphaValue = (FIXP_DBL)MAXVAL_DBL; + } + } else { /* short windows */ + shortDrc = 1; + } + + fact_mag = hDrcData->nextFact_mag; + fact_exp = hDrcData->nextFact_exp; + numBands = hDrcData->numBandsNext; + bandTop = hDrcData->bandTopNext; + + col -= numQmfSubSamples; + } + + /* process bands */ + for (band = 0; band < (int)numBands; band++) { + int bottomQmf, topQmf; + + FIXP_DBL drcFact_mag = (FIXP_DBL)MAXVAL_DBL; + + topMdct = (bandTop[band] + 1) << 2; + + if (!shortDrc) { /* long window */ + if (frameLenFlag) { + /* 960 framing */ + bottomQmf = fMultIfloor((FIXP_DBL)0x4444445, bottomMdct); + topQmf = fMultIfloor((FIXP_DBL)0x4444445, topMdct); + + topMdct = 30 * topQmf; + } else { + /* 1024 framing */ + topMdct &= ~0x1f; + + bottomQmf = bottomMdct >> 5; + topQmf = topMdct >> 5; + } + + if (band == ((int)numBands - 1)) { + topQmf = (64); + } + + for (bin = bottomQmf; bin < topQmf; bin++) { + FIXP_DBL drcFact1_mag = hDrcData->prevFact_mag[bin]; + FIXP_DBL drcFact2_mag = fact_mag[band]; + + /* normalize scale factors */ + if (hDrcData->prevFact_exp < maxShift) { + drcFact1_mag >>= maxShift - hDrcData->prevFact_exp; + } + if (fact_exp < maxShift) { + drcFact2_mag >>= maxShift - fact_exp; + } + + /* interpolate */ + if (alphaValue == (FIXP_DBL)0) { + drcFact_mag = drcFact1_mag; + } else if (alphaValue == (FIXP_DBL)MAXVAL_DBL) { + drcFact_mag = drcFact2_mag; + } else { + drcFact_mag = + fMult(alphaValue, drcFact2_mag) + + fMult(((FIXP_DBL)MAXVAL_DBL - alphaValue), drcFact1_mag); + } + + /* apply scaling */ + qmfRealSlot[bin] = fMult(qmfRealSlot[bin], drcFact_mag); + if (!useLP) { + qmfImagSlot[bin] = fMult(qmfImagSlot[bin], drcFact_mag); + } + + /* save previous factors */ + if (col == (numQmfSubSamples >> 1) - 1) { + hDrcData->prevFact_mag[bin] = fact_mag[band]; + } + } + } else { /* short windows */ + unsigned startWinIdx, stopWinIdx; + int startCol, stopCol; + FIXP_DBL invFrameSizeDiv8 = + (frameLenFlag) ? (FIXP_DBL)0x1111112 : (FIXP_DBL)0x1000000; + + /* limit top at the frame borders */ + if (topMdct < 0) { + topMdct = 0; + } + if (topMdct >= frameSize) { + topMdct = frameSize - 1; + } + + if (frameLenFlag) { + /* 960 framing */ + topMdct = fMultIfloor((FIXP_DBL)0x78000000, + fMultIfloor((FIXP_DBL)0x22222223, topMdct) << 2); + + startWinIdx = fMultIfloor(invFrameSizeDiv8, bottomMdct) + + 1; /* winBorderToColMap table has offset of 1 */ + stopWinIdx = fMultIceil(invFrameSizeDiv8 - (FIXP_DBL)1, topMdct) + 1; + } else { + /* 1024 framing */ + topMdct &= ~0x03; + + startWinIdx = fMultIfloor(invFrameSizeDiv8, bottomMdct) + 1; + stopWinIdx = fMultIceil(invFrameSizeDiv8, topMdct) + 1; + } + + /* startCol is truncated to the nearest corresponding start subsample in + the QMF of the short window bottom is present in:*/ + startCol = (int)winBorderToColMap[startWinIdx]; + + /* stopCol is rounded upwards to the nearest corresponding stop subsample + in the QMF of the short window top is present in. */ + stopCol = (int)winBorderToColMap[stopWinIdx]; + + bottomQmf = fMultIfloor(invFrameSizeDiv8, + ((bottomMdct % (numQmfSubSamples << 2)) << 5)); + topQmf = fMultIfloor(invFrameSizeDiv8, + ((topMdct % (numQmfSubSamples << 2)) << 5)); + + /* extend last band */ + if (band == ((int)numBands - 1)) { + topQmf = (64); + stopCol = numQmfSubSamples; + stopWinIdx = 10; + } + + if (topQmf == 0) { + if (frameLenFlag) { + FIXP_DBL rem = fMult(invFrameSizeDiv8, + (FIXP_DBL)(topMdct << (DFRACT_BITS - 12))); + if ((LONG)rem & (LONG)0x1F) { + stopWinIdx -= 1; + stopCol = (int)winBorderToColMap[stopWinIdx]; + } + } + topQmf = (64); + } + + /* save previous factors */ + if (stopCol == numQmfSubSamples) { + int tmpBottom = bottomQmf; + + if ((int)winBorderToColMap[8] > startCol) { + tmpBottom = 0; /* band starts in previous short window */ + } + + for (bin = tmpBottom; bin < topQmf; bin++) { + hDrcData->prevFact_mag[bin] = fact_mag[band]; + } + } + + /* apply */ + if ((col >= startCol) && (col < stopCol)) { + if (col >= (int)winBorderToColMap[startWinIdx + 1]) { + bottomQmf = 0; /* band starts in previous short window */ + } + if (col < (int)winBorderToColMap[stopWinIdx - 1]) { + topQmf = (64); /* band ends in next short window */ + } + + drcFact_mag = fact_mag[band]; + + /* normalize scale factor */ + if (fact_exp < maxShift) { + drcFact_mag >>= maxShift - fact_exp; + } + + /* apply scaling */ + for (bin = bottomQmf; bin < topQmf; bin++) { + qmfRealSlot[bin] = fMult(qmfRealSlot[bin], drcFact_mag); + if (!useLP) { + qmfImagSlot[bin] = fMult(qmfImagSlot[bin], drcFact_mag); + } + } + } + } + + bottomMdct = topMdct; + } /* end of bands loop */ + + if (col == (numQmfSubSamples >> 1) - 1) { + hDrcData->prevFact_exp = fact_exp; + } +} + +/*! + \brief Apply DRC factors frame based. + + \hDrcData Handle to DRC channel data. + \qmfRealSlot Pointer to real valued QMF data of the whole frame. + \qmfImagSlot Pointer to the imaginary QMF data of the whole frame. + \numQmfSubSamples Total number of time slots for one frame. + \scaleFactor Pointer to the out scale factor of the frame. + + \return None. +*/ +void sbrDecoder_drcApply(HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL **QmfBufferReal, FIXP_DBL **QmfBufferImag, + int numQmfSubSamples, int *scaleFactor) { + int col; + int maxShift = 0; + + if (hDrcData == NULL) { + return; + } + if (hDrcData->enable == 0) { + return; /* Avoid changing the scaleFactor even though the processing is + disabled. */ + } + + /* get max scale factor */ + if (hDrcData->prevFact_exp > maxShift) { + maxShift = hDrcData->prevFact_exp; + } + if (hDrcData->currFact_exp > maxShift) { + maxShift = hDrcData->currFact_exp; + } + if (hDrcData->nextFact_exp > maxShift) { + maxShift = hDrcData->nextFact_exp; + } + + for (col = 0; col < numQmfSubSamples; col++) { + FIXP_DBL *qmfSlotReal = QmfBufferReal[col]; + FIXP_DBL *qmfSlotImag = (QmfBufferImag == NULL) ? NULL : QmfBufferImag[col]; + + sbrDecoder_drcApplySlot(hDrcData, qmfSlotReal, qmfSlotImag, col, + numQmfSubSamples, maxShift); + } + + *scaleFactor += maxShift; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_drc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_drc.h new file mode 100644 index 0000000000000..2eb0e20e90586 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_drc.h @@ -0,0 +1,149 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): Christian Griebel + + Description: Dynamic range control (DRC) decoder tool for SBR + +*******************************************************************************/ + +#ifndef SBRDEC_DRC_H +#define SBRDEC_DRC_H + +#include "sbrdecoder.h" + +#define SBRDEC_MAX_DRC_CHANNELS (8) +#define SBRDEC_MAX_DRC_BANDS (16) + +typedef struct { + FIXP_DBL prevFact_mag[(64)]; + INT prevFact_exp; + + FIXP_DBL currFact_mag[SBRDEC_MAX_DRC_BANDS]; + FIXP_DBL nextFact_mag[SBRDEC_MAX_DRC_BANDS]; + INT currFact_exp; + INT nextFact_exp; + + UINT numBandsCurr; + UINT numBandsNext; + USHORT bandTopCurr[SBRDEC_MAX_DRC_BANDS]; + USHORT bandTopNext[SBRDEC_MAX_DRC_BANDS]; + + SHORT drcInterpolationSchemeCurr; + SHORT drcInterpolationSchemeNext; + + SHORT enable; + + UCHAR winSequenceCurr; + UCHAR winSequenceNext; + +} SBRDEC_DRC_CHANNEL; + +typedef SBRDEC_DRC_CHANNEL *HANDLE_SBR_DRC_CHANNEL; + +void sbrDecoder_drcInitChannel(HANDLE_SBR_DRC_CHANNEL hDrcData); + +void sbrDecoder_drcUpdateChannel(HANDLE_SBR_DRC_CHANNEL hDrcData); + +void sbrDecoder_drcApplySlot(HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL *qmfRealSlot, FIXP_DBL *qmfImagSlot, + int col, int numQmfSubSamples, int maxShift); + +void sbrDecoder_drcApply(HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL **QmfBufferReal, FIXP_DBL **QmfBufferImag, + int numQmfSubSamples, int *scaleFactor); + +#endif /* SBRDEC_DRC_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_freq_sca.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_freq_sca.cpp new file mode 100644 index 0000000000000..daa3554d9cd93 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_freq_sca.cpp @@ -0,0 +1,838 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Frequency scale calculation +*/ + +#include "sbrdec_freq_sca.h" + +#include "transcendent.h" +#include "sbr_rom.h" +#include "env_extr.h" + +#include "genericStds.h" /* need log() for debug-code only */ + +#define MAX_OCTAVE 29 +#define MAX_SECOND_REGION 50 + +static int numberOfBands(FIXP_SGL bpo_div16, int start, int stop, int warpFlag); +static void CalcBands(UCHAR *diff, UCHAR start, UCHAR stop, UCHAR num_bands); +static SBR_ERROR modifyBands(UCHAR max_band, UCHAR *diff, UCHAR length); +static void cumSum(UCHAR start_value, UCHAR *diff, UCHAR length, + UCHAR *start_adress); + +/*! + \brief Retrieve QMF-band where the SBR range starts + + Convert startFreq which was read from the bitstream into a + QMF-channel number. + + \return Number of start band +*/ +static UCHAR getStartBand( + UINT fs, /*!< Output sampling frequency */ + UCHAR startFreq, /*!< Index to table of possible start bands */ + UINT headerDataFlags) /*!< Info to SBR mode */ +{ + INT band; + UINT fsMapped = fs; + SBR_RATE rate = DUAL; + + if (headerDataFlags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + if (headerDataFlags & SBRDEC_QUAD_RATE) { + rate = QUAD; + } + fsMapped = sbrdec_mapToStdSampleRate(fs, 1); + } + + FDK_ASSERT(2 * (rate + 1) <= (4)); + + switch (fsMapped) { + case 192000: + band = FDK_sbrDecoder_sbr_start_freq_192[startFreq]; + break; + case 176400: + band = FDK_sbrDecoder_sbr_start_freq_176[startFreq]; + break; + case 128000: + band = FDK_sbrDecoder_sbr_start_freq_128[startFreq]; + break; + case 96000: + case 88200: + band = FDK_sbrDecoder_sbr_start_freq_88[rate][startFreq]; + break; + case 64000: + band = FDK_sbrDecoder_sbr_start_freq_64[rate][startFreq]; + break; + case 48000: + band = FDK_sbrDecoder_sbr_start_freq_48[rate][startFreq]; + break; + case 44100: + band = FDK_sbrDecoder_sbr_start_freq_44[rate][startFreq]; + break; + case 40000: + band = FDK_sbrDecoder_sbr_start_freq_40[rate][startFreq]; + break; + case 32000: + band = FDK_sbrDecoder_sbr_start_freq_32[rate][startFreq]; + break; + case 24000: + band = FDK_sbrDecoder_sbr_start_freq_24[rate][startFreq]; + break; + case 22050: + band = FDK_sbrDecoder_sbr_start_freq_22[rate][startFreq]; + break; + case 16000: + band = FDK_sbrDecoder_sbr_start_freq_16[rate][startFreq]; + break; + default: + band = 255; + } + + return band; +} + +/*! + \brief Retrieve QMF-band where the SBR range starts + + Convert startFreq which was read from the bitstream into a + QMF-channel number. + + \return Number of start band +*/ +static UCHAR getStopBand( + UINT fs, /*!< Output sampling frequency */ + UCHAR stopFreq, /*!< Index to table of possible start bands */ + UINT headerDataFlags, /*!< Info to SBR mode */ + UCHAR k0) /*!< Start freq index */ +{ + UCHAR k2; + + if (stopFreq < 14) { + INT stopMin; + INT num = 2 * (64); + UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + UCHAR *diff0 = diff_tot; + UCHAR *diff1 = diff_tot + MAX_OCTAVE; + + if (headerDataFlags & SBRDEC_QUAD_RATE) { + num >>= 1; + } + + if (fs < 32000) { + stopMin = (((2 * 6000 * num) / fs) + 1) >> 1; + } else { + if (fs < 64000) { + stopMin = (((2 * 8000 * num) / fs) + 1) >> 1; + } else { + stopMin = (((2 * 10000 * num) / fs) + 1) >> 1; + } + } + + stopMin = fMin(stopMin, 64); + + /* + Choose a stop band between k1 and 64 depending on stopFreq (0..13), + based on a logarithmic scale. + The vectors diff0 and diff1 are used temporarily here. + */ + CalcBands(diff0, stopMin, 64, 13); + shellsort(diff0, 13); + cumSum(stopMin, diff0, 13, diff1); + k2 = diff1[stopFreq]; + } else if (stopFreq == 14) + k2 = 2 * k0; + else + k2 = 3 * k0; + + /* Limit to Nyquist */ + if (k2 > (64)) k2 = (64); + + /* Range checks */ + /* 1 <= difference <= 48; 1 <= fs <= 96000 */ + { + UCHAR max_freq_coeffs = (headerDataFlags & SBRDEC_QUAD_RATE) + ? MAX_FREQ_COEFFS_QUAD_RATE + : MAX_FREQ_COEFFS; + if (((k2 - k0) > max_freq_coeffs) || (k2 <= k0)) { + return 255; + } + } + + if (headerDataFlags & SBRDEC_QUAD_RATE) { + return k2; /* skip other checks: (k2 - k0) must be <= + MAX_FREQ_COEFFS_QUAD_RATE for all fs */ + } + if (headerDataFlags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + /* 1 <= difference <= 35; 42000 <= fs <= 96000 */ + if ((fs >= 42000) && ((k2 - k0) > MAX_FREQ_COEFFS_FS44100)) { + return 255; + } + /* 1 <= difference <= 32; 46009 <= fs <= 96000 */ + if ((fs >= 46009) && ((k2 - k0) > MAX_FREQ_COEFFS_FS48000)) { + return 255; + } + } else { + /* 1 <= difference <= 35; fs == 44100 */ + if ((fs == 44100) && ((k2 - k0) > MAX_FREQ_COEFFS_FS44100)) { + return 255; + } + /* 1 <= difference <= 32; 48000 <= fs <= 96000 */ + if ((fs >= 48000) && ((k2 - k0) > MAX_FREQ_COEFFS_FS48000)) { + return 255; + } + } + + return k2; +} + +/*! + \brief Generates master frequency tables + + Frequency tables are calculated according to the selected domain + (linear/logarithmic) and granularity. + IEC 14496-3 4.6.18.3.2.1 + + \return errorCode, 0 if successful +*/ +SBR_ERROR +sbrdecUpdateFreqScale( + UCHAR *v_k_master, /*!< Master table to be created */ + UCHAR *numMaster, /*!< Number of entries in master table */ + UINT fs, /*!< SBR working sampling rate */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Control data from bitstream */ + UINT flags) { + FIXP_SGL bpo_div16; /* bands_per_octave divided by 16 */ + INT dk = 0; + + /* Internal variables */ + UCHAR k0, k2, i; + UCHAR num_bands0 = 0; + UCHAR num_bands1 = 0; + UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + UCHAR *diff0 = diff_tot; + UCHAR *diff1 = diff_tot + MAX_OCTAVE; + INT k2_achived; + INT k2_diff; + INT incr = 0; + + /* + Determine start band + */ + if (flags & SBRDEC_QUAD_RATE) { + fs >>= 1; + } + + k0 = getStartBand(fs, hHeaderData->bs_data.startFreq, flags); + if (k0 == 255) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* + Determine stop band + */ + k2 = getStopBand(fs, hHeaderData->bs_data.stopFreq, flags, k0); + if (k2 == 255) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + if (hHeaderData->bs_data.freqScale > 0) { /* Bark */ + INT k1; + + if (hHeaderData->bs_data.freqScale == 1) { + bpo_div16 = FL2FXCONST_SGL(12.0f / 16.0f); + } else if (hHeaderData->bs_data.freqScale == 2) { + bpo_div16 = FL2FXCONST_SGL(10.0f / 16.0f); + } else { + bpo_div16 = FL2FXCONST_SGL(8.0f / 16.0f); + } + + /* Ref: ISO/IEC 23003-3, Figure 12 - Flowchart calculation of fMaster for + * 4:1 system when bs_freq_scale > 0 */ + if (flags & SBRDEC_QUAD_RATE) { + if ((SHORT)k0 < (SHORT)(bpo_div16 >> ((FRACT_BITS - 1) - 4))) { + bpo_div16 = (FIXP_SGL)(k0 & (UCHAR)0xfe) + << ((FRACT_BITS - 1) - 4); /* bpo_div16 = floor(k0/2)*2 */ + } + } + + if (1000 * k2 > 2245 * k0) { /* Two or more regions */ + k1 = 2 * k0; + + num_bands0 = numberOfBands(bpo_div16, k0, k1, 0); + num_bands1 = + numberOfBands(bpo_div16, k1, k2, hHeaderData->bs_data.alterScale); + if (num_bands0 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + if (num_bands1 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + CalcBands(diff0, k0, k1, num_bands0); + shellsort(diff0, num_bands0); + if (diff0[0] == 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + cumSum(k0, diff0, num_bands0, v_k_master); + + CalcBands(diff1, k1, k2, num_bands1); + shellsort(diff1, num_bands1); + if (diff0[num_bands0 - 1] > diff1[0]) { + SBR_ERROR err; + + err = modifyBands(diff0[num_bands0 - 1], diff1, num_bands1); + if (err) return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Add 2nd region */ + cumSum(k1, diff1, num_bands1, &v_k_master[num_bands0]); + *numMaster = num_bands0 + num_bands1; /* Output nr of bands */ + + } else { /* Only one region */ + k1 = k2; + + num_bands0 = numberOfBands(bpo_div16, k0, k1, 0); + if (num_bands0 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + CalcBands(diff0, k0, k1, num_bands0); + shellsort(diff0, num_bands0); + if (diff0[0] == 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + cumSum(k0, diff0, num_bands0, v_k_master); + *numMaster = num_bands0; /* Output nr of bands */ + } + } else { /* Linear mode */ + if (hHeaderData->bs_data.alterScale == 0) { + dk = 1; + /* FLOOR to get to few number of bands (next lower even number) */ + num_bands0 = (k2 - k0) & 254; + } else { + dk = 2; + num_bands0 = (((k2 - k0) >> 1) + 1) & 254; /* ROUND to the closest fit */ + } + + if (num_bands0 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + /* We must return already here because 'i' can become negative below. */ + } + + k2_achived = k0 + num_bands0 * dk; + k2_diff = k2 - k2_achived; + + for (i = 0; i < num_bands0; i++) diff_tot[i] = dk; + + /* If linear scale wasn't achieved */ + /* and we got too wide SBR area */ + if (k2_diff < 0) { + incr = 1; + i = 0; + } + + /* If linear scale wasn't achieved */ + /* and we got too small SBR area */ + if (k2_diff > 0) { + incr = -1; + i = num_bands0 - 1; + } + + /* Adjust diff vector to get sepc. SBR range */ + while (k2_diff != 0) { + diff_tot[i] = diff_tot[i] - incr; + i = i + incr; + k2_diff = k2_diff + incr; + } + + cumSum(k0, diff_tot, num_bands0, v_k_master); /* cumsum */ + *numMaster = num_bands0; /* Output nr of bands */ + } + + if (*numMaster < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Ref: ISO/IEC 23003-3 Cor.3, "In 7.5.5.2, add to the requirements:"*/ + if (flags & SBRDEC_QUAD_RATE) { + int k; + for (k = 1; k < *numMaster; k++) { + if (!(v_k_master[k] - v_k_master[k - 1] <= k0 - 2)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + } + } + + /* + Print out the calculated table + */ + + return SBRDEC_OK; +} + +/*! + \brief Calculate frequency ratio of one SBR band + + All SBR bands should span a constant frequency range in the logarithmic + domain. This function calculates the ratio of any SBR band's upper and lower + frequency. + + \return num_band-th root of k_start/k_stop +*/ +static FIXP_SGL calcFactorPerBand(int k_start, int k_stop, int num_bands) { + /* Scaled bandfactor and step 1 bit right to avoid overflow + * use double data type */ + FIXP_DBL bandfactor = FL2FXCONST_DBL(0.25f); /* Start value */ + FIXP_DBL step = FL2FXCONST_DBL(0.125f); /* Initial increment for factor */ + + int direction = 1; + + /* Because saturation can't be done in INT IIS, + * changed start and stop data type from FIXP_SGL to FIXP_DBL */ + FIXP_DBL start = k_start << (DFRACT_BITS - 8); + FIXP_DBL stop = k_stop << (DFRACT_BITS - 8); + + FIXP_DBL temp; + + int j, i = 0; + + while (step > FL2FXCONST_DBL(0.0f)) { + i++; + temp = stop; + + /* Calculate temp^num_bands: */ + for (j = 0; j < num_bands; j++) + // temp = fMult(temp,bandfactor); + temp = fMultDiv2(temp, bandfactor) << 2; + + if (temp < start) { /* Factor too strong, make it weaker */ + if (direction == 0) + /* Halfen step. Right shift is not done as fract because otherwise the + lowest bit cannot be cleared due to rounding */ + step = (FIXP_DBL)((LONG)step >> 1); + direction = 1; + bandfactor = bandfactor + step; + } else { /* Factor is too weak: make it stronger */ + if (direction == 1) step = (FIXP_DBL)((LONG)step >> 1); + direction = 0; + bandfactor = bandfactor - step; + } + + if (i > 100) { + step = FL2FXCONST_DBL(0.0f); + } + } + return (bandfactor >= FL2FXCONST_DBL(0.5)) ? (FIXP_SGL)MAXVAL_SGL + : FX_DBL2FX_SGL(bandfactor << 1); +} + +/*! + \brief Calculate number of SBR bands between start and stop band + + Given the number of bands per octave, this function calculates how many + bands fit in the given frequency range. + When the warpFlag is set, the 'band density' is decreased by a factor + of 1/1.3 + + \return number of bands +*/ +static int numberOfBands( + FIXP_SGL bpo_div16, /*!< Input: number of bands per octave divided by 16 */ + int start, /*!< First QMF band of SBR frequency range */ + int stop, /*!< Last QMF band of SBR frequency range + 1 */ + int warpFlag) /*!< Stretching flag */ +{ + FIXP_SGL num_bands_div128; + int num_bands; + + num_bands_div128 = + FX_DBL2FX_SGL(fMult(FDK_getNumOctavesDiv8(start, stop), bpo_div16)); + + if (warpFlag) { + /* Apply the warp factor of 1.3 to get wider bands. We use a value + of 32768/25200 instead of the exact value to avoid critical cases + of rounding. + */ + num_bands_div128 = FX_DBL2FX_SGL( + fMult(num_bands_div128, FL2FXCONST_SGL(25200.0 / 32768.0))); + } + + /* add scaled 1 for rounding to even numbers: */ + num_bands_div128 = num_bands_div128 + FL2FXCONST_SGL(1.0f / 128.0f); + /* scale back to right aligned integer and double the value: */ + num_bands = 2 * ((LONG)num_bands_div128 >> (FRACT_BITS - 7)); + + return (num_bands); +} + +/*! + \brief Calculate width of SBR bands + + Given the desired number of bands within the SBR frequency range, + this function calculates the width of each SBR band in QMF channels. + The bands get wider from start to stop (bark scale). +*/ +static void CalcBands(UCHAR *diff, /*!< Vector of widths to be calculated */ + UCHAR start, /*!< Lower end of subband range */ + UCHAR stop, /*!< Upper end of subband range */ + UCHAR num_bands) /*!< Desired number of bands */ +{ + int i; + int previous; + int current; + FIXP_SGL exact, temp; + FIXP_SGL bandfactor = calcFactorPerBand(start, stop, num_bands); + + previous = stop; /* Start with highest QMF channel */ + exact = (FIXP_SGL)( + stop << (FRACT_BITS - 8)); /* Shift left to gain some accuracy */ + + for (i = num_bands - 1; i >= 0; i--) { + /* Calculate border of next lower sbr band */ + exact = FX_DBL2FX_SGL(fMult(exact, bandfactor)); + + /* Add scaled 0.5 for rounding: + We use a value 128/256 instead of 0.5 to avoid some critical cases of + rounding. */ + temp = exact + FL2FXCONST_SGL(128.0 / 32768.0); + + /* scale back to right alinged integer: */ + current = (LONG)temp >> (FRACT_BITS - 8); + + /* Save width of band i */ + diff[i] = previous - current; + previous = current; + } +} + +/*! + \brief Calculate cumulated sum vector from delta vector +*/ +static void cumSum(UCHAR start_value, UCHAR *diff, UCHAR length, + UCHAR *start_adress) { + int i; + start_adress[0] = start_value; + for (i = 1; i <= length; i++) + start_adress[i] = start_adress[i - 1] + diff[i - 1]; +} + +/*! + \brief Adapt width of frequency bands in the second region + + If SBR spans more than 2 octaves, the upper part of a bark-frequency-scale + is calculated separately. This function tries to avoid that the second region + starts with a band smaller than the highest band of the first region. +*/ +static SBR_ERROR modifyBands(UCHAR max_band_previous, UCHAR *diff, + UCHAR length) { + int change = max_band_previous - diff[0]; + + /* Limit the change so that the last band cannot get narrower than the first + * one */ + if (change > (diff[length - 1] - diff[0]) >> 1) + change = (diff[length - 1] - diff[0]) >> 1; + + diff[0] += change; + diff[length - 1] -= change; + shellsort(diff, length); + + return SBRDEC_OK; +} + +/*! + \brief Update high resolution frequency band table +*/ +static void sbrdecUpdateHiRes(UCHAR *h_hires, UCHAR *num_hires, + UCHAR *v_k_master, UCHAR num_bands, + UCHAR xover_band) { + UCHAR i; + + *num_hires = num_bands - xover_band; + + for (i = xover_band; i <= num_bands; i++) { + h_hires[i - xover_band] = v_k_master[i]; + } +} + +/*! + \brief Build low resolution table out of high resolution table +*/ +static void sbrdecUpdateLoRes(UCHAR *h_lores, UCHAR *num_lores, UCHAR *h_hires, + UCHAR num_hires) { + UCHAR i; + + if ((num_hires & 1) == 0) { + /* If even number of hires bands */ + *num_lores = num_hires >> 1; + /* Use every second lores=hires[0,2,4...] */ + for (i = 0; i <= *num_lores; i++) h_lores[i] = h_hires[i * 2]; + } else { + /* Odd number of hires, which means xover is odd */ + *num_lores = (num_hires + 1) >> 1; + /* Use lores=hires[0,1,3,5 ...] */ + h_lores[0] = h_hires[0]; + for (i = 1; i <= *num_lores; i++) { + h_lores[i] = h_hires[i * 2 - 1]; + } + } +} + +/*! + \brief Derive a low-resolution frequency-table from the master frequency + table +*/ +void sbrdecDownSampleLoRes(UCHAR *v_result, UCHAR num_result, + UCHAR *freqBandTableRef, UCHAR num_Ref) { + int step; + int i, j; + int org_length, result_length; + int v_index[MAX_FREQ_COEFFS >> 1]; + + /* init */ + org_length = num_Ref; + result_length = num_result; + + v_index[0] = 0; /* Always use left border */ + i = 0; + while (org_length > 0) { + /* Create downsample vector */ + i++; + step = org_length / result_length; + org_length = org_length - step; + result_length--; + v_index[i] = v_index[i - 1] + step; + } + + for (j = 0; j <= i; j++) { + /* Use downsample vector to index LoResolution vector */ + v_result[j] = freqBandTableRef[v_index[j]]; + } +} + +/*! + \brief Sorting routine +*/ +void shellsort(UCHAR *in, UCHAR n) { + int i, j, v, w; + int inc = 1; + + do + inc = 3 * inc + 1; + while (inc <= n); + + do { + inc = inc / 3; + for (i = inc; i < n; i++) { + v = in[i]; + j = i; + while ((w = in[j - inc]) > v) { + in[j] = w; + j -= inc; + if (j < inc) break; + } + in[j] = v; + } + } while (inc > 1); +} + +/*! + \brief Reset frequency band tables + \return errorCode, 0 if successful +*/ +SBR_ERROR +resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags) { + SBR_ERROR err = SBRDEC_OK; + int k2, kx, lsb, usb; + int intTemp; + UCHAR nBandsLo, nBandsHi; + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + + /* Calculate master frequency function */ + err = sbrdecUpdateFreqScale(hFreq->v_k_master, &hFreq->numMaster, + hHeaderData->sbrProcSmplRate, hHeaderData, flags); + + if (err || (hHeaderData->bs_info.xover_band > hFreq->numMaster)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Derive Hiresolution from master frequency function */ + sbrdecUpdateHiRes(hFreq->freqBandTable[1], &nBandsHi, hFreq->v_k_master, + hFreq->numMaster, hHeaderData->bs_info.xover_band); + /* Derive Loresolution from Hiresolution */ + sbrdecUpdateLoRes(hFreq->freqBandTable[0], &nBandsLo, hFreq->freqBandTable[1], + nBandsHi); + + /* Check index to freqBandTable[0] */ + if (!(nBandsLo > 0) || + (nBandsLo > (((hHeaderData->numberOfAnalysisBands == 16) + ? MAX_FREQ_COEFFS_QUAD_RATE + : MAX_FREQ_COEFFS_DUAL_RATE) >> + 1))) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + hFreq->nSfb[0] = nBandsLo; + hFreq->nSfb[1] = nBandsHi; + + lsb = hFreq->freqBandTable[0][0]; + usb = hFreq->freqBandTable[0][nBandsLo]; + + /* Check for start frequency border k_x: + - ISO/IEC 14496-3 4.6.18.3.6 Requirements + - ISO/IEC 23003-3 7.5.5.2 Modifications and additions to the MPEG-4 SBR + tool + */ + /* Note that lsb > as hHeaderData->numberOfAnalysisBands is a valid SBR config + * for 24 band QMF analysis. */ + if ((lsb > ((flags & SBRDEC_QUAD_RATE) ? 16 : (32))) || (lsb >= usb)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Calculate number of noise bands */ + + k2 = hFreq->freqBandTable[1][nBandsHi]; + kx = hFreq->freqBandTable[1][0]; + + if (hHeaderData->bs_data.noise_bands == 0) { + hFreq->nNfb = 1; + } else /* Calculate no of noise bands 1,2 or 3 bands/octave */ + { + /* Fetch number of octaves divided by 32 */ + intTemp = (LONG)FDK_getNumOctavesDiv8(kx, k2) >> 2; + + /* Integer-Multiplication with number of bands: */ + intTemp = intTemp * hHeaderData->bs_data.noise_bands; + + /* Add scaled 0.5 for rounding: */ + intTemp = intTemp + (LONG)FL2FXCONST_SGL(0.5f / 32.0f); + + /* Convert to right-aligned integer: */ + intTemp = intTemp >> (FRACT_BITS - 1 /*sign*/ - 5 /* rescale */); + + if (intTemp == 0) intTemp = 1; + + if (intTemp > MAX_NOISE_COEFFS) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + hFreq->nNfb = intTemp; + } + + hFreq->nInvfBands = hFreq->nNfb; + + /* Get noise bands */ + sbrdecDownSampleLoRes(hFreq->freqBandTableNoise, hFreq->nNfb, + hFreq->freqBandTable[0], nBandsLo); + + /* save old highband; required for overlap in usac + when headerchange occurs at XVAR and VARX frame; */ + hFreq->ov_highSubband = hFreq->highSubband; + + hFreq->lowSubband = lsb; + hFreq->highSubband = usb; + + return SBRDEC_OK; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_freq_sca.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_freq_sca.h new file mode 100644 index 0000000000000..7e6b8e84c415a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdec_freq_sca.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Frequency scale prototypes +*/ +#ifndef SBRDEC_FREQ_SCA_H +#define SBRDEC_FREQ_SCA_H + +#include "sbrdecoder.h" +#include "env_extr.h" + +typedef enum { DUAL, QUAD } SBR_RATE; + +SBR_ERROR +sbrdecUpdateFreqScale(UCHAR *v_k_master, UCHAR *numMaster, UINT fs, + HANDLE_SBR_HEADER_DATA headerData, UINT flags); + +void sbrdecDownSampleLoRes(UCHAR *v_result, UCHAR num_result, + UCHAR *freqBandTableRef, UCHAR num_Ref); + +void shellsort(UCHAR *in, UCHAR n); + +SBR_ERROR +resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdecoder.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdecoder.cpp new file mode 100644 index 0000000000000..7718695a86ce1 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/sbrdecoder.cpp @@ -0,0 +1,2015 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief SBR decoder frontend + This module provides a frontend to the SBR decoder. The function openSBR() is + called for initialization. The function sbrDecoder_Apply() is called for each + frame. sbr_Apply() will call the required functions to decode the raw SBR data + (provided by env_extr.cpp), to decode the envelope data and noise floor levels + [decodeSbrData()], and to finally apply SBR to the current frame [sbr_dec()]. + + \sa sbrDecoder_Apply(), \ref documentationOverview +*/ + +/*! + \page documentationOverview Overview of important information resources and + source code documentation + + As part of this documentation you can find more extensive descriptions about + key concepts and algorithms at the following locations: + +

Programming

+ + \li Buffer management: sbrDecoder_Apply() and sbr_dec() + \li Internal scale factors to maximize SNR on fixed point processors: + #QMF_SCALE_FACTOR \li Special mantissa-exponent format: Created in + requantizeEnvelopeData() and used in calculateSbrEnvelope() + +

Algorithmic details

+ \li About the SBR data format: \ref SBR_HEADER_ELEMENT and \ref + SBR_STANDARD_ELEMENT \li Details about the bitstream decoder: env_extr.cpp \li + Details about the QMF filterbank and the provided polyphase implementation: + qmf_dec.cpp \li Details about the transposer: lpp_tran.cpp \li Details about + the envelope adjuster: env_calc.cpp + +*/ + +#include "sbrdecoder.h" + +#include "FDK_bitstream.h" + +#include "sbrdec_freq_sca.h" +#include "env_extr.h" +#include "sbr_dec.h" +#include "env_dec.h" +#include "FDK_crc.h" +#include "sbr_ram.h" +#include "sbr_rom.h" +#include "lpp_tran.h" +#include "transcendent.h" + +#include "sbrdec_drc.h" + +#include "psbitdec.h" + +/* Decoder library info */ +#define SBRDECODER_LIB_VL0 3 +#define SBRDECODER_LIB_VL1 1 +#define SBRDECODER_LIB_VL2 0 +#define SBRDECODER_LIB_TITLE "SBR Decoder" +#ifdef SUPPRESS_BUILD_DATE_INFO +#define SBRDECODER_LIB_BUILD_DATE "" +#define SBRDECODER_LIB_BUILD_TIME "" +#else +#define SBRDECODER_LIB_BUILD_DATE __DATE__ +#define SBRDECODER_LIB_BUILD_TIME __TIME__ +#endif + +static void setFrameErrorFlag(SBR_DECODER_ELEMENT *pSbrElement, UCHAR value) { + if (pSbrElement != NULL) { + switch (value) { + case FRAME_ERROR_ALLSLOTS: + FDKmemset(pSbrElement->frameErrorFlag, FRAME_ERROR, + sizeof(pSbrElement->frameErrorFlag)); + break; + default: + pSbrElement->frameErrorFlag[pSbrElement->useFrameSlot] = value; + } + } +} + +static UCHAR getHeaderSlot(UCHAR currentSlot, UCHAR hdrSlotUsage[(1) + 1]) { + UINT occupied = 0; + int s; + UCHAR slot = hdrSlotUsage[currentSlot]; + + FDK_ASSERT((1) + 1 < 32); + + for (s = 0; s < (1) + 1; s++) { + if ((hdrSlotUsage[s] == slot) && (s != slot)) { + occupied = 1; + break; + } + } + + if (occupied) { + occupied = 0; + + for (s = 0; s < (1) + 1; s++) { + occupied |= 1 << hdrSlotUsage[s]; + } + for (s = 0; s < (1) + 1; s++) { + if (!(occupied & 0x1)) { + slot = s; + break; + } + occupied >>= 1; + } + } + + return slot; +} + +static void copySbrHeader(HANDLE_SBR_HEADER_DATA hDst, + const HANDLE_SBR_HEADER_DATA hSrc) { + /* copy the whole header memory (including pointers) */ + FDKmemcpy(hDst, hSrc, sizeof(SBR_HEADER_DATA)); + + /* update pointers */ + hDst->freqBandData.freqBandTable[0] = hDst->freqBandData.freqBandTableLo; + hDst->freqBandData.freqBandTable[1] = hDst->freqBandData.freqBandTableHi; +} + +static int compareSbrHeader(const HANDLE_SBR_HEADER_DATA hHdr1, + const HANDLE_SBR_HEADER_DATA hHdr2) { + int result = 0; + + /* compare basic data */ + result |= (hHdr1->syncState != hHdr2->syncState) ? 1 : 0; + result |= (hHdr1->status != hHdr2->status) ? 1 : 0; + result |= (hHdr1->frameErrorFlag != hHdr2->frameErrorFlag) ? 1 : 0; + result |= (hHdr1->numberTimeSlots != hHdr2->numberTimeSlots) ? 1 : 0; + result |= + (hHdr1->numberOfAnalysisBands != hHdr2->numberOfAnalysisBands) ? 1 : 0; + result |= (hHdr1->timeStep != hHdr2->timeStep) ? 1 : 0; + result |= (hHdr1->sbrProcSmplRate != hHdr2->sbrProcSmplRate) ? 1 : 0; + + /* compare bitstream data */ + result |= + FDKmemcmp(&hHdr1->bs_data, &hHdr2->bs_data, sizeof(SBR_HEADER_DATA_BS)); + result |= + FDKmemcmp(&hHdr1->bs_dflt, &hHdr2->bs_dflt, sizeof(SBR_HEADER_DATA_BS)); + result |= FDKmemcmp(&hHdr1->bs_info, &hHdr2->bs_info, + sizeof(SBR_HEADER_DATA_BS_INFO)); + + /* compare frequency band data */ + result |= FDKmemcmp(&hHdr1->freqBandData, &hHdr2->freqBandData, + (8 + MAX_NUM_LIMITERS + 1) * sizeof(UCHAR)); + result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableLo, + hHdr2->freqBandData.freqBandTableLo, + (MAX_FREQ_COEFFS / 2 + 1) * sizeof(UCHAR)); + result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableHi, + hHdr2->freqBandData.freqBandTableHi, + (MAX_FREQ_COEFFS + 1) * sizeof(UCHAR)); + result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableNoise, + hHdr2->freqBandData.freqBandTableNoise, + (MAX_NOISE_COEFFS + 1) * sizeof(UCHAR)); + result |= + FDKmemcmp(hHdr1->freqBandData.v_k_master, hHdr2->freqBandData.v_k_master, + (MAX_FREQ_COEFFS + 1) * sizeof(UCHAR)); + + return result; +} + +/*! + \brief Reset SBR decoder. + + Reset should only be called if SBR has been sucessfully detected by + an appropriate checkForPayload() function. + + \return Error code. +*/ +static SBR_ERROR sbrDecoder_ResetElement(HANDLE_SBRDECODER self, + int sampleRateIn, int sampleRateOut, + int samplesPerFrame, + const MP4_ELEMENT_ID elementID, + const int elementIndex, + const int overlap) { + SBR_ERROR sbrError = SBRDEC_OK; + HANDLE_SBR_HEADER_DATA hSbrHeader; + UINT qmfFlags = 0; + + int i, synDownsampleFac; + + /* USAC: assuming theoretical case 8 kHz output sample rate with 4:1 SBR */ + const int sbr_min_sample_rate_in = IS_USAC(self->coreCodec) ? 2000 : 6400; + + /* Check in/out samplerates */ + if (sampleRateIn < sbr_min_sample_rate_in || sampleRateIn > (96000)) { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + + if (sampleRateOut > (96000)) { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + + /* Set QMF mode flags */ + if (self->flags & SBRDEC_LOW_POWER) qmfFlags |= QMF_FLAG_LP; + + if (self->coreCodec == AOT_ER_AAC_ELD) { + if (self->flags & SBRDEC_LD_MPS_QMF) { + qmfFlags |= QMF_FLAG_MPSLDFB; + } else { + qmfFlags |= QMF_FLAG_CLDFB; + } + } + + /* Set downsampling factor for synthesis filter bank */ + if (sampleRateOut == 0) { + /* no single rate mode */ + sampleRateOut = + sampleRateIn + << 1; /* In case of implicit signalling, assume dual rate SBR */ + } + + if (sampleRateIn == sampleRateOut) { + synDownsampleFac = 2; + self->flags |= SBRDEC_DOWNSAMPLE; + } else { + synDownsampleFac = 1; + self->flags &= ~SBRDEC_DOWNSAMPLE; + } + + self->synDownsampleFac = synDownsampleFac; + self->sampleRateOut = sampleRateOut; + + { + for (i = 0; i < (1) + 1; i++) { + int setDflt; + hSbrHeader = &(self->sbrHeader[elementIndex][i]); + setDflt = ((hSbrHeader->syncState == SBR_NOT_INITIALIZED) || + (self->flags & SBRDEC_FORCE_RESET)) + ? 1 + : 0; + + /* init a default header such that we can at least do upsampling later */ + sbrError = initHeaderData(hSbrHeader, sampleRateIn, sampleRateOut, + self->downscaleFactor, samplesPerFrame, + self->flags, setDflt); + + /* Set synchState to UPSAMPLING in case it already is initialized */ + hSbrHeader->syncState = hSbrHeader->syncState > UPSAMPLING + ? UPSAMPLING + : hSbrHeader->syncState; + } + } + + if (sbrError != SBRDEC_OK) { + goto bail; + } + + if (!self->pQmfDomain->globalConf.qmfDomainExplicitConfig) { + self->pQmfDomain->globalConf.flags_requested |= qmfFlags; + self->pQmfDomain->globalConf.nBandsAnalysis_requested = + self->sbrHeader[elementIndex][0].numberOfAnalysisBands; + self->pQmfDomain->globalConf.nBandsSynthesis_requested = + (synDownsampleFac == 1) ? 64 : 32; /* may be overwritten by MPS */ + self->pQmfDomain->globalConf.nBandsSynthesis_requested /= + self->downscaleFactor; + self->pQmfDomain->globalConf.nQmfTimeSlots_requested = + self->sbrHeader[elementIndex][0].numberTimeSlots * + self->sbrHeader[elementIndex][0].timeStep; + self->pQmfDomain->globalConf.nQmfOvTimeSlots_requested = overlap; + self->pQmfDomain->globalConf.nQmfProcBands_requested = 64; /* always 64 */ + self->pQmfDomain->globalConf.nQmfProcChannels_requested = + 1; /* may be overwritten by MPS */ + } + + /* Init SBR channels going to be assigned to a SBR element */ + { + int ch; + for (ch = 0; ch < self->pSbrElement[elementIndex]->nChannels; ch++) { + int headerIndex = + getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, + self->pSbrElement[elementIndex]->useHeaderSlot); + + /* and create sbrDec */ + sbrError = + createSbrDec(self->pSbrElement[elementIndex]->pSbrChannel[ch], + &self->sbrHeader[elementIndex][headerIndex], + &self->pSbrElement[elementIndex]->transposerSettings, + synDownsampleFac, qmfFlags, self->flags, overlap, ch, + self->codecFrameSize); + + if (sbrError != SBRDEC_OK) { + goto bail; + } + } + } + + // FDKmemclear(sbr_OverlapBuffer, sizeof(sbr_OverlapBuffer)); + + if (self->numSbrElements == 1) { + switch (self->coreCodec) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_SCAL: + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + if (CreatePsDec(&self->hParametricStereoDec, samplesPerFrame)) { + sbrError = SBRDEC_CREATE_ERROR; + goto bail; + } + break; + default: + break; + } + } + + /* Init frame delay slot handling */ + self->pSbrElement[elementIndex]->useFrameSlot = 0; + for (i = 0; i < ((1) + 1); i++) { + self->pSbrElement[elementIndex]->useHeaderSlot[i] = i; + } + +bail: + + return sbrError; +} + +/*! + \brief Assign QMF domain provided QMF channels to SBR channels. + + \return void +*/ +static void sbrDecoder_AssignQmfChannels2SbrChannels(HANDLE_SBRDECODER self) { + int ch, el, absCh_offset = 0; + for (el = 0; el < self->numSbrElements; el++) { + if (self->pSbrElement[el] != NULL) { + for (ch = 0; ch < self->pSbrElement[el]->nChannels; ch++) { + FDK_ASSERT(((absCh_offset + ch) < ((8) + (1))) && + ((absCh_offset + ch) < ((8) + (1)))); + self->pSbrElement[el]->pSbrChannel[ch]->SbrDec.qmfDomainInCh = + &self->pQmfDomain->QmfDomainIn[absCh_offset + ch]; + self->pSbrElement[el]->pSbrChannel[ch]->SbrDec.qmfDomainOutCh = + &self->pQmfDomain->QmfDomainOut[absCh_offset + ch]; + } + absCh_offset += self->pSbrElement[el]->nChannels; + } + } +} + +SBR_ERROR sbrDecoder_Open(HANDLE_SBRDECODER *pSelf, + HANDLE_FDK_QMF_DOMAIN pQmfDomain) { + HANDLE_SBRDECODER self = NULL; + SBR_ERROR sbrError = SBRDEC_OK; + int elIdx; + + if ((pSelf == NULL) || (pQmfDomain == NULL)) { + return SBRDEC_INVALID_ARGUMENT; + } + + /* Get memory for this instance */ + self = GetRam_SbrDecoder(); + if (self == NULL) { + sbrError = SBRDEC_MEM_ALLOC_FAILED; + goto bail; + } + + self->pQmfDomain = pQmfDomain; + + /* + Already zero because of calloc + self->numSbrElements = 0; + self->numSbrChannels = 0; + self->codecFrameSize = 0; + */ + + self->numDelayFrames = (1); /* set to the max value by default */ + + /* Initialize header sync state */ + for (elIdx = 0; elIdx < (8); elIdx += 1) { + int i; + for (i = 0; i < (1) + 1; i += 1) { + self->sbrHeader[elIdx][i].syncState = SBR_NOT_INITIALIZED; + } + } + + *pSelf = self; + +bail: + return sbrError; +} + +/** + * \brief determine if the given core codec AOT can be processed or not. + * \param coreCodec core codec audio object type. + * \return 1 if SBR can be processed, 0 if SBR cannot be processed/applied. + */ +static int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec) { + switch (coreCodec) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_SCAL: + case AOT_ER_AAC_ELD: + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + case AOT_USAC: + return 1; + default: + return 0; + } +} + +static void sbrDecoder_DestroyElement(HANDLE_SBRDECODER self, + const int elementIndex) { + if (self->pSbrElement[elementIndex] != NULL) { + int ch; + + for (ch = 0; ch < SBRDEC_MAX_CH_PER_ELEMENT; ch++) { + if (self->pSbrElement[elementIndex]->pSbrChannel[ch] != NULL) { + deleteSbrDec(self->pSbrElement[elementIndex]->pSbrChannel[ch]); + FreeRam_SbrDecChannel( + &self->pSbrElement[elementIndex]->pSbrChannel[ch]); + self->numSbrChannels -= 1; + } + } + FreeRam_SbrDecElement(&self->pSbrElement[elementIndex]); + self->numSbrElements -= 1; + } +} + +SBR_ERROR sbrDecoder_InitElement( + HANDLE_SBRDECODER self, const int sampleRateIn, const int sampleRateOut, + const int samplesPerFrame, const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const int elementIndex, + const UCHAR harmonicSBR, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, const INT downscaleFactor) { + SBR_ERROR sbrError = SBRDEC_OK; + int chCnt = 0; + int nSbrElementsStart; + int nSbrChannelsStart; + if (self == NULL) { + return SBRDEC_INVALID_ARGUMENT; + } + + nSbrElementsStart = self->numSbrElements; + nSbrChannelsStart = self->numSbrChannels; + + /* Check core codec AOT */ + if (!sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (8)) { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + + if (elementID != ID_SCE && elementID != ID_CPE && elementID != ID_LFE) { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + + if (self->sampleRateIn == sampleRateIn && + self->codecFrameSize == samplesPerFrame && self->coreCodec == coreCodec && + self->pSbrElement[elementIndex] != NULL && + self->pSbrElement[elementIndex]->elementID == elementID && + !(self->flags & SBRDEC_FORCE_RESET) && + ((sampleRateOut == 0) ? 1 : (self->sampleRateOut == sampleRateOut)) && + ((harmonicSBR == 2) ? 1 + : (self->harmonicSBR == + harmonicSBR)) /* The value 2 signalizes that + harmonicSBR shall be ignored in + the config change detection */ + ) { + /* Nothing to do */ + return SBRDEC_OK; + } else { + if (configMode & AC_CM_DET_CFG_CHANGE) { + *configChanged = 1; + } + } + + /* reaching this point the SBR-decoder gets (re-)configured */ + + /* The flags field is used for all elements! */ + self->flags &= + (SBRDEC_FORCE_RESET | SBRDEC_FLUSH); /* Keep the global flags. They will + be reset after decoding. */ + self->flags |= (downscaleFactor > 1) ? SBRDEC_ELD_DOWNSCALE : 0; + self->flags |= (coreCodec == AOT_ER_AAC_ELD) ? SBRDEC_ELD_GRID : 0; + self->flags |= (coreCodec == AOT_ER_AAC_SCAL) ? SBRDEC_SYNTAX_SCAL : 0; + self->flags |= + (coreCodec == AOT_DRM_AAC) ? SBRDEC_SYNTAX_SCAL | SBRDEC_SYNTAX_DRM : 0; + self->flags |= (coreCodec == AOT_DRM_SURROUND) + ? SBRDEC_SYNTAX_SCAL | SBRDEC_SYNTAX_DRM + : 0; + self->flags |= (coreCodec == AOT_USAC) ? SBRDEC_SYNTAX_USAC : 0; + /* Robustness: Take integer division rounding into consideration. E.g. 22050 + * Hz with 4:1 SBR => 5512 Hz core sampling rate. */ + self->flags |= (sampleRateIn == sampleRateOut / 4) ? SBRDEC_QUAD_RATE : 0; + self->flags |= (harmonicSBR == 1) ? SBRDEC_USAC_HARMONICSBR : 0; + + if (configMode & AC_CM_DET_CFG_CHANGE) { + return SBRDEC_OK; + } + + self->sampleRateIn = sampleRateIn; + self->codecFrameSize = samplesPerFrame; + self->coreCodec = coreCodec; + self->harmonicSBR = harmonicSBR; + self->downscaleFactor = downscaleFactor; + + /* Init SBR elements */ + { + int elChannels, ch; + + if (self->pSbrElement[elementIndex] == NULL) { + self->pSbrElement[elementIndex] = GetRam_SbrDecElement(elementIndex); + if (self->pSbrElement[elementIndex] == NULL) { + sbrError = SBRDEC_MEM_ALLOC_FAILED; + goto bail; + } + self->numSbrElements++; + } else { + self->numSbrChannels -= self->pSbrElement[elementIndex]->nChannels; + } + + /* Determine amount of channels for this element */ + switch (elementID) { + case ID_NONE: + case ID_CPE: + elChannels = 2; + break; + case ID_LFE: + case ID_SCE: + elChannels = 1; + break; + default: + elChannels = 0; + break; + } + + /* Handle case of Parametric Stereo */ + if (elementIndex == 0 && elementID == ID_SCE) { + switch (coreCodec) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_SCAL: + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + elChannels = 2; + break; + default: + break; + } + } + + /* Sanity check to avoid memory leaks */ + if (elChannels < self->pSbrElement[elementIndex]->nChannels || + (self->numSbrChannels + elChannels) > (8) + (1)) { + self->numSbrChannels += self->pSbrElement[elementIndex]->nChannels; + sbrError = SBRDEC_PARSE_ERROR; + goto bail; + } + + /* Save element ID for sanity checks and to have a fallback for concealment. + */ + self->pSbrElement[elementIndex]->elementID = elementID; + self->pSbrElement[elementIndex]->nChannels = elChannels; + + for (ch = 0; ch < elChannels; ch++) { + if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) { + self->pSbrElement[elementIndex]->pSbrChannel[ch] = + GetRam_SbrDecChannel(chCnt); + if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) { + sbrError = SBRDEC_MEM_ALLOC_FAILED; + goto bail; + } + } + self->numSbrChannels++; + + sbrDecoder_drcInitChannel(&self->pSbrElement[elementIndex] + ->pSbrChannel[ch] + ->SbrDec.sbrDrcChannel); + + chCnt++; + } + } + + if (!self->pQmfDomain->globalConf.qmfDomainExplicitConfig) { + self->pQmfDomain->globalConf.nInputChannels_requested = + self->numSbrChannels; + self->pQmfDomain->globalConf.nOutputChannels_requested = + fMax((INT)self->numSbrChannels, + (INT)self->pQmfDomain->globalConf.nOutputChannels_requested); + } + + /* Make sure each SBR channel has one QMF channel assigned even if + * numSbrChannels or element set-up has changed. */ + sbrDecoder_AssignQmfChannels2SbrChannels(self); + + /* clear error flags for all delay slots */ + FDKmemclear(self->pSbrElement[elementIndex]->frameErrorFlag, + ((1) + 1) * sizeof(UCHAR)); + + { + int overlap; + + if (coreCodec == AOT_ER_AAC_ELD) { + overlap = 0; + } else if (self->flags & SBRDEC_QUAD_RATE) { + overlap = (3 * 4); + } else { + overlap = (3 * 2); + } + /* Initialize this instance */ + sbrError = sbrDecoder_ResetElement(self, sampleRateIn, sampleRateOut, + samplesPerFrame, elementID, elementIndex, + overlap); + } + +bail: + if (sbrError != SBRDEC_OK) { + if ((nSbrElementsStart < self->numSbrElements) || + (nSbrChannelsStart < self->numSbrChannels)) { + /* Free the memory allocated for this element */ + sbrDecoder_DestroyElement(self, elementIndex); + } else if ((elementIndex < (8)) && + (self->pSbrElement[elementIndex] != + NULL)) { /* Set error flag to trigger concealment */ + setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR); + } + } + + return sbrError; +} + +/** + * \brief Free config dependent SBR memory. + * \param self SBR decoder instance handle + */ +SBR_ERROR sbrDecoder_FreeMem(HANDLE_SBRDECODER *self) { + int i; + int elIdx; + + if (self != NULL && *self != NULL) { + for (i = 0; i < (8); i++) { + sbrDecoder_DestroyElement(*self, i); + } + + for (elIdx = 0; elIdx < (8); elIdx += 1) { + for (i = 0; i < (1) + 1; i += 1) { + (*self)->sbrHeader[elIdx][i].syncState = SBR_NOT_INITIALIZED; + } + } + } + + return SBRDEC_OK; +} + +/** + * \brief Apply decoded SBR header for one element. + * \param self SBR decoder instance handle + * \param hSbrHeader SBR header handle to be processed. + * \param hSbrChannel pointer array to the SBR element channels corresponding to + * the SBR header. + * \param headerStatus header status value returned from SBR header parser. + * \param numElementChannels amount of channels for the SBR element whos header + * is to be processed. + */ +static SBR_ERROR sbrDecoder_HeaderUpdate(HANDLE_SBRDECODER self, + HANDLE_SBR_HEADER_DATA hSbrHeader, + SBR_HEADER_STATUS headerStatus, + HANDLE_SBR_CHANNEL hSbrChannel[], + const int numElementChannels) { + SBR_ERROR errorStatus = SBRDEC_OK; + + /* + change of control data, reset decoder + */ + errorStatus = resetFreqBandTables(hSbrHeader, self->flags); + + if (errorStatus == SBRDEC_OK) { + if (hSbrHeader->syncState == UPSAMPLING && headerStatus != HEADER_RESET) { +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + int ch; + for (ch = 0; ch < numElementChannels; ch += 1) { + hSbrChannel[ch]->SbrDec.highBandFadeCnt = SBRDEC_MAX_HB_FADE_FRAMES; + } + +#endif + /* As the default header would limit the frequency range, + lowSubband and highSubband must be patched. */ + hSbrHeader->freqBandData.lowSubband = hSbrHeader->numberOfAnalysisBands; + hSbrHeader->freqBandData.highSubband = hSbrHeader->numberOfAnalysisBands; + } + + /* Trigger a reset before processing this slot */ + hSbrHeader->status |= SBRDEC_HDR_STAT_RESET; + } + + return errorStatus; +} + +INT sbrDecoder_Header(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const INT elementIndex, + const UCHAR harmonicSBR, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor) { + SBR_HEADER_STATUS headerStatus; + HANDLE_SBR_HEADER_DATA hSbrHeader; + SBR_ERROR sbrError = SBRDEC_OK; + int headerIndex; + UINT flagsSaved = + 0; /* flags should not be changed in AC_CM_DET_CFG_CHANGE - mode after + parsing */ + + if (self == NULL || elementIndex >= (8)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + if (!sbrDecoder_isCoreCodecValid(coreCodec)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + if (configMode & AC_CM_DET_CFG_CHANGE) { + flagsSaved = self->flags; /* store */ + } + + sbrError = sbrDecoder_InitElement( + self, sampleRateIn, sampleRateOut, samplesPerFrame, coreCodec, elementID, + elementIndex, harmonicSBR, stereoConfigIndex, configMode, configChanged, + downscaleFactor); + + if ((sbrError != SBRDEC_OK) || (elementID == ID_LFE)) { + goto bail; + } + + if (configMode & AC_CM_DET_CFG_CHANGE) { + hSbrHeader = NULL; + } else { + headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, + self->pSbrElement[elementIndex]->useHeaderSlot); + + hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]); + } + + headerStatus = sbrGetHeaderData(hSbrHeader, hBs, self->flags, 0, configMode); + + if (coreCodec == AOT_USAC) { + if (configMode & AC_CM_DET_CFG_CHANGE) { + self->flags = flagsSaved; /* restore */ + } + return sbrError; + } + + if (configMode & AC_CM_ALLOC_MEM) { + SBR_DECODER_ELEMENT *pSbrElement; + + pSbrElement = self->pSbrElement[elementIndex]; + + /* Sanity check */ + if (pSbrElement != NULL) { + if ((elementID == ID_CPE && pSbrElement->nChannels != 2) || + (elementID != ID_CPE && pSbrElement->nChannels != 1)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + if (headerStatus == HEADER_RESET) { + sbrError = sbrDecoder_HeaderUpdate(self, hSbrHeader, headerStatus, + pSbrElement->pSbrChannel, + pSbrElement->nChannels); + + if (sbrError == SBRDEC_OK) { + hSbrHeader->syncState = SBR_HEADER; + hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE; + } else { + hSbrHeader->syncState = SBR_NOT_INITIALIZED; + hSbrHeader->status = HEADER_ERROR; + } + } + } + } +bail: + if (configMode & AC_CM_DET_CFG_CHANGE) { + self->flags = flagsSaved; /* restore */ + } + return sbrError; +} + +SBR_ERROR sbrDecoder_SetParam(HANDLE_SBRDECODER self, const SBRDEC_PARAM param, + const INT value) { + SBR_ERROR errorStatus = SBRDEC_OK; + + /* configure the subsystems */ + switch (param) { + case SBR_SYSTEM_BITSTREAM_DELAY: + if (value < 0 || value > (1)) { + errorStatus = SBRDEC_SET_PARAM_FAIL; + break; + } + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->numDelayFrames = (UCHAR)value; + } + break; + case SBR_QMF_MODE: + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + if (value == 1) { + self->flags |= SBRDEC_LOW_POWER; + } else { + self->flags &= ~SBRDEC_LOW_POWER; + } + } + break; + case SBR_LD_QMF_TIME_ALIGN: + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + if (value == 1) { + self->flags |= SBRDEC_LD_MPS_QMF; + } else { + self->flags &= ~SBRDEC_LD_MPS_QMF; + } + } + break; + case SBR_FLUSH_DATA: + if (value != 0) { + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->flags |= SBRDEC_FLUSH; + } + } + break; + case SBR_CLEAR_HISTORY: + if (value != 0) { + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->flags |= SBRDEC_FORCE_RESET; + } + } + break; + case SBR_BS_INTERRUPTION: { + int elementIndex; + + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + break; + } + + /* Loop over SBR elements */ + for (elementIndex = 0; elementIndex < self->numSbrElements; + elementIndex++) { + if (self->pSbrElement[elementIndex] != NULL) { + HANDLE_SBR_HEADER_DATA hSbrHeader; + int headerIndex = + getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, + self->pSbrElement[elementIndex]->useHeaderSlot); + + hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]); + + /* Set sync state UPSAMPLING for the corresponding slot. + This switches off bitstream parsing until a new header arrives. */ + if (hSbrHeader->syncState != SBR_NOT_INITIALIZED) { + hSbrHeader->syncState = UPSAMPLING; + hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE; + } + } + } + } break; + + case SBR_SKIP_QMF: + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + if (value == 1) { + self->flags |= SBRDEC_SKIP_QMF_ANA; + } else { + self->flags &= ~SBRDEC_SKIP_QMF_ANA; + } + if (value == 2) { + self->flags |= SBRDEC_SKIP_QMF_SYN; + } else { + self->flags &= ~SBRDEC_SKIP_QMF_SYN; + } + } + break; + default: + errorStatus = SBRDEC_SET_PARAM_FAIL; + break; + } /* switch(param) */ + + return (errorStatus); +} + +static SBRDEC_DRC_CHANNEL *sbrDecoder_drcGetChannel( + const HANDLE_SBRDECODER self, const INT channel) { + SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; + int elementIndex, elChanIdx = 0, numCh = 0; + + for (elementIndex = 0; (elementIndex < (8)) && (numCh <= channel); + elementIndex++) { + SBR_DECODER_ELEMENT *pSbrElement = self->pSbrElement[elementIndex]; + int c, elChannels; + + elChanIdx = 0; + if (pSbrElement == NULL) break; + + /* Determine amount of channels for this element */ + switch (pSbrElement->elementID) { + case ID_CPE: + elChannels = 2; + break; + case ID_LFE: + case ID_SCE: + elChannels = 1; + break; + case ID_NONE: + default: + elChannels = 0; + break; + } + + /* Limit with actual allocated element channels */ + elChannels = fMin(elChannels, pSbrElement->nChannels); + + for (c = 0; (c < elChannels) && (numCh <= channel); c++) { + if (pSbrElement->pSbrChannel[elChanIdx] != NULL) { + numCh++; + elChanIdx++; + } + } + } + elementIndex -= 1; + elChanIdx -= 1; + + if (elChanIdx < 0 || elementIndex < 0) { + return NULL; + } + + if (self->pSbrElement[elementIndex] != NULL) { + if (self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx] != NULL) { + pSbrDrcChannelData = &self->pSbrElement[elementIndex] + ->pSbrChannel[elChanIdx] + ->SbrDec.sbrDrcChannel; + } + } + + return (pSbrDrcChannelData); +} + +SBR_ERROR sbrDecoder_drcFeedChannel(HANDLE_SBRDECODER self, INT ch, + UINT numBands, FIXP_DBL *pNextFact_mag, + INT nextFact_exp, + SHORT drcInterpolationScheme, + UCHAR winSequence, USHORT *pBandTop) { + SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; + int band, isValidData = 0; + + if (self == NULL) { + return SBRDEC_NOT_INITIALIZED; + } + if (ch > (8) || pNextFact_mag == NULL) { + return SBRDEC_SET_PARAM_FAIL; + } + + /* Search for gain values different to 1.0f */ + for (band = 0; band < (int)numBands; band += 1) { + if (!((pNextFact_mag[band] == FL2FXCONST_DBL(0.5)) && + (nextFact_exp == 1)) && + !((pNextFact_mag[band] == (FIXP_DBL)MAXVAL_DBL) && + (nextFact_exp == 0))) { + isValidData = 1; + break; + } + } + + /* Find the right SBR channel */ + pSbrDrcChannelData = sbrDecoder_drcGetChannel(self, ch); + + if (pSbrDrcChannelData != NULL) { + if (pSbrDrcChannelData->enable || + isValidData) { /* Activate processing only with real and valid data */ + int i; + + pSbrDrcChannelData->enable = 1; + pSbrDrcChannelData->numBandsNext = numBands; + + pSbrDrcChannelData->winSequenceNext = winSequence; + pSbrDrcChannelData->drcInterpolationSchemeNext = drcInterpolationScheme; + pSbrDrcChannelData->nextFact_exp = nextFact_exp; + + for (i = 0; i < (int)numBands; i++) { + pSbrDrcChannelData->bandTopNext[i] = pBandTop[i]; + pSbrDrcChannelData->nextFact_mag[i] = pNextFact_mag[i]; + } + } + } + + return SBRDEC_OK; +} + +void sbrDecoder_drcDisable(HANDLE_SBRDECODER self, INT ch) { + SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; + + if ((self == NULL) || (ch > (8)) || (self->numSbrElements == 0) || + (self->numSbrChannels == 0)) { + return; + } + + /* Find the right SBR channel */ + pSbrDrcChannelData = sbrDecoder_drcGetChannel(self, ch); + + if (pSbrDrcChannelData != NULL) { + sbrDecoder_drcInitChannel(pSbrDrcChannelData); + } +} + +SBR_ERROR sbrDecoder_Parse(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs, + UCHAR *pDrmBsBuffer, USHORT drmBsBufferSize, + int *count, int bsPayLen, int crcFlag, + MP4_ELEMENT_ID prevElement, int elementIndex, + UINT acFlags, UINT acElFlags[]) { + SBR_DECODER_ELEMENT *hSbrElement = NULL; + HANDLE_SBR_HEADER_DATA hSbrHeader = NULL; + HANDLE_SBR_CHANNEL *pSbrChannel; + + SBR_FRAME_DATA *hFrameDataLeft = NULL; + SBR_FRAME_DATA *hFrameDataRight = NULL; + SBR_FRAME_DATA frameDataLeftCopy; + SBR_FRAME_DATA frameDataRightCopy; + + SBR_ERROR errorStatus = SBRDEC_OK; + SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT; + + INT startPos = FDKgetValidBits(hBs); + FDK_CRCINFO crcInfo; + INT crcReg = 0; + USHORT sbrCrc = 0; + UINT crcPoly; + UINT crcStartValue = 0; + UINT crcLen; + + HANDLE_FDK_BITSTREAM hBsOriginal = hBs; + FDK_BITSTREAM bsBwd; + + const int fGlobalIndependencyFlag = acFlags & AC_INDEP; + const int bs_pvc = acElFlags[elementIndex] & AC_EL_USAC_PVC; + const int bs_interTes = acElFlags[elementIndex] & AC_EL_USAC_ITES; + int stereo; + int fDoDecodeSbrData = 1; + int alignBits = 0; + + int lastSlot, lastHdrSlot = 0, thisHdrSlot = 0; + + if (*count <= 0) { + setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR); + return SBRDEC_OK; + } + + /* SBR sanity checks */ + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + goto bail; + } + + /* Reverse bits of DRM SBR payload */ + if ((self->flags & SBRDEC_SYNTAX_DRM) && *count > 0) { + int dataBytes, dataBits; + + FDK_ASSERT(drmBsBufferSize >= (512)); + dataBits = *count; + + if (dataBits > ((512) * 8)) { + /* do not flip more data than needed */ + dataBits = (512) * 8; + } + + dataBytes = (dataBits + 7) >> 3; + + int j; + + if ((j = (int)FDKgetValidBits(hBs)) != 8) { + FDKpushBiDirectional(hBs, (j - 8)); + } + + j = 0; + for (; dataBytes > 0; dataBytes--) { + int i; + UCHAR tmpByte; + UCHAR buffer = 0x00; + + tmpByte = (UCHAR)FDKreadBits(hBs, 8); + for (i = 0; i < 4; i++) { + int shift = 2 * i + 1; + buffer |= (tmpByte & (0x08 >> i)) << shift; + buffer |= (tmpByte & (0x10 << i)) >> shift; + } + pDrmBsBuffer[j++] = buffer; + FDKpushBack(hBs, 16); + } + + FDKinitBitStream(&bsBwd, pDrmBsBuffer, (512), dataBits, BS_READER); + + /* Use reversed data */ + hBs = &bsBwd; + bsPayLen = *count; + } + + /* Remember start position of SBR element */ + startPos = FDKgetValidBits(hBs); + + /* SBR sanity checks */ + if (self->pSbrElement[elementIndex] == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + goto bail; + } + hSbrElement = self->pSbrElement[elementIndex]; + + lastSlot = (hSbrElement->useFrameSlot > 0) ? hSbrElement->useFrameSlot - 1 + : self->numDelayFrames; + lastHdrSlot = hSbrElement->useHeaderSlot[lastSlot]; + thisHdrSlot = getHeaderSlot( + hSbrElement->useFrameSlot, + hSbrElement->useHeaderSlot); /* Get a free header slot not used by + frames not processed yet. */ + + /* Assign the free slot to store a new header if there is one. */ + hSbrHeader = &self->sbrHeader[elementIndex][thisHdrSlot]; + + pSbrChannel = hSbrElement->pSbrChannel; + stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0; + + hFrameDataLeft = &self->pSbrElement[elementIndex] + ->pSbrChannel[0] + ->frameData[hSbrElement->useFrameSlot]; + if (stereo) { + hFrameDataRight = &self->pSbrElement[elementIndex] + ->pSbrChannel[1] + ->frameData[hSbrElement->useFrameSlot]; + } + + /* store frameData; new parsed frameData possibly corrupted */ + FDKmemcpy(&frameDataLeftCopy, hFrameDataLeft, sizeof(SBR_FRAME_DATA)); + if (stereo) { + FDKmemcpy(&frameDataRightCopy, hFrameDataRight, sizeof(SBR_FRAME_DATA)); + } + + /* reset PS flag; will be set after PS was found */ + self->flags &= ~SBRDEC_PS_DECODED; + + if (hSbrHeader->status & SBRDEC_HDR_STAT_UPDATE) { + /* Got a new header from extern (e.g. from an ASC) */ + headerStatus = HEADER_OK; + hSbrHeader->status &= ~SBRDEC_HDR_STAT_UPDATE; + } else if (thisHdrSlot != lastHdrSlot) { + /* Copy the last header into this slot otherwise the + header compare will trigger more HEADER_RESETs than needed. */ + copySbrHeader(hSbrHeader, &self->sbrHeader[elementIndex][lastHdrSlot]); + } + + /* + Check if bit stream data is valid and matches the element context + */ + if (((prevElement != ID_SCE) && (prevElement != ID_CPE)) || + prevElement != hSbrElement->elementID) { + /* In case of LFE we also land here, since there is no LFE SBR element (do + * upsampling only) */ + fDoDecodeSbrData = 0; + } + + if (fDoDecodeSbrData) { + if ((INT)FDKgetValidBits(hBs) <= 0) { + fDoDecodeSbrData = 0; + } + } + + /* + SBR CRC-check + */ + if (fDoDecodeSbrData) { + if (crcFlag) { + switch (self->coreCodec) { + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + crcPoly = 0x001d; + crcLen = 8; + crcStartValue = 0x000000ff; + break; + default: + crcPoly = 0x0633; + crcLen = 10; + crcStartValue = 0x00000000; + break; + } + sbrCrc = (USHORT)FDKreadBits(hBs, crcLen); + /* Setup CRC decoder */ + FDKcrcInit(&crcInfo, crcPoly, crcStartValue, crcLen); + /* Start CRC region */ + crcReg = FDKcrcStartReg(&crcInfo, hBs, 0); + } + } /* if (fDoDecodeSbrData) */ + + /* + Read in the header data and issue a reset if change occured + */ + if (fDoDecodeSbrData) { + int sbrHeaderPresent; + + if (self->flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC)) { + SBR_HEADER_DATA_BS_INFO newSbrInfo; + int sbrInfoPresent; + + if (bs_interTes) { + self->flags |= SBRDEC_USAC_ITES; + } else { + self->flags &= ~SBRDEC_USAC_ITES; + } + + if (fGlobalIndependencyFlag) { + self->flags |= SBRDEC_USAC_INDEP; + sbrInfoPresent = 1; + sbrHeaderPresent = 1; + } else { + self->flags &= ~SBRDEC_USAC_INDEP; + sbrInfoPresent = FDKreadBit(hBs); + if (sbrInfoPresent) { + sbrHeaderPresent = FDKreadBit(hBs); + } else { + sbrHeaderPresent = 0; + } + } + + if (sbrInfoPresent) { + newSbrInfo.ampResolution = FDKreadBit(hBs); + newSbrInfo.xover_band = FDKreadBits(hBs, 4); + newSbrInfo.sbr_preprocessing = FDKreadBit(hBs); + if (bs_pvc) { + newSbrInfo.pvc_mode = FDKreadBits(hBs, 2); + /* bs_pvc_mode: 0 -> no PVC, 1 -> PVC mode 1, 2 -> PVC mode 2, 3 -> + * reserved */ + if (newSbrInfo.pvc_mode > 2) { + headerStatus = HEADER_ERROR; + } + if (stereo && newSbrInfo.pvc_mode > 0) { + /* bs_pvc is always transmitted but pvc_mode is set to zero in case + * of stereo SBR. The config might be wrong but we cannot tell for + * sure. */ + newSbrInfo.pvc_mode = 0; + } + } else { + newSbrInfo.pvc_mode = 0; + } + if (headerStatus != HEADER_ERROR) { + if (FDKmemcmp(&hSbrHeader->bs_info, &newSbrInfo, + sizeof(SBR_HEADER_DATA_BS_INFO))) { + /* in case of ampResolution and preprocessing change no full reset + * required */ + /* HEADER reset would trigger HBE transposer reset which breaks + * eSbr_3_Eaa.mp4 */ + if ((hSbrHeader->bs_info.pvc_mode != newSbrInfo.pvc_mode) || + (hSbrHeader->bs_info.xover_band != newSbrInfo.xover_band)) { + headerStatus = HEADER_RESET; + } else { + headerStatus = HEADER_OK; + } + + hSbrHeader->bs_info = newSbrInfo; + } else { + headerStatus = HEADER_OK; + } + } + } + if (headerStatus == HEADER_ERROR) { + /* Corrupt SBR info data, do not decode and switch to UPSAMPLING */ + hSbrHeader->syncState = hSbrHeader->syncState > UPSAMPLING + ? UPSAMPLING + : hSbrHeader->syncState; + fDoDecodeSbrData = 0; + sbrHeaderPresent = 0; + } + + if (sbrHeaderPresent && fDoDecodeSbrData) { + int useDfltHeader; + + useDfltHeader = FDKreadBit(hBs); + + if (useDfltHeader) { + sbrHeaderPresent = 0; + if (FDKmemcmp(&hSbrHeader->bs_data, &hSbrHeader->bs_dflt, + sizeof(SBR_HEADER_DATA_BS)) || + hSbrHeader->syncState != SBR_ACTIVE) { + hSbrHeader->bs_data = hSbrHeader->bs_dflt; + headerStatus = HEADER_RESET; + } + } + } + } else { + sbrHeaderPresent = FDKreadBit(hBs); + } + + if (sbrHeaderPresent) { + headerStatus = sbrGetHeaderData(hSbrHeader, hBs, self->flags, 1, 0); + } + + if (headerStatus == HEADER_RESET) { + errorStatus = sbrDecoder_HeaderUpdate( + self, hSbrHeader, headerStatus, pSbrChannel, hSbrElement->nChannels); + + if (errorStatus == SBRDEC_OK) { + hSbrHeader->syncState = SBR_HEADER; + } else { + hSbrHeader->syncState = SBR_NOT_INITIALIZED; + headerStatus = HEADER_ERROR; + } + } + + if (errorStatus != SBRDEC_OK) { + fDoDecodeSbrData = 0; + } + } /* if (fDoDecodeSbrData) */ + + /* + Print debugging output only if state has changed + */ + + /* read frame data */ + if ((hSbrHeader->syncState >= SBR_HEADER) && fDoDecodeSbrData) { + int sbrFrameOk; + /* read the SBR element data */ + if (!stereo && (self->hParametricStereoDec != NULL)) { + /* update slot index for PS bitstream parsing */ + self->hParametricStereoDec->bsLastSlot = + self->hParametricStereoDec->bsReadSlot; + self->hParametricStereoDec->bsReadSlot = hSbrElement->useFrameSlot; + } + sbrFrameOk = sbrGetChannelElement( + hSbrHeader, hFrameDataLeft, (stereo) ? hFrameDataRight : NULL, + &pSbrChannel[0]->prevFrameData, + pSbrChannel[0]->SbrDec.PvcStaticData.pvc_mode_last, hBs, + (stereo) ? NULL : self->hParametricStereoDec, self->flags, + self->pSbrElement[elementIndex]->transposerSettings.overlap); + + if (!sbrFrameOk) { + fDoDecodeSbrData = 0; + } else { + INT valBits; + + if (bsPayLen > 0) { + valBits = bsPayLen - ((INT)startPos - (INT)FDKgetValidBits(hBs)); + } else { + valBits = (INT)FDKgetValidBits(hBs); + } + + /* sanity check of remaining bits */ + if (valBits < 0) { + fDoDecodeSbrData = 0; + } else { + switch (self->coreCodec) { + case AOT_SBR: + case AOT_PS: + case AOT_AAC_LC: { + /* This sanity check is only meaningful with General Audio + * bitstreams */ + alignBits = valBits & 0x7; + + if (valBits > alignBits) { + fDoDecodeSbrData = 0; + } + } break; + default: + /* No sanity check available */ + break; + } + } + } + } else { + /* The returned bit count will not be the actual payload size since we did + not parse the frame data. Return an error so that the caller can react + respectively. */ + errorStatus = SBRDEC_PARSE_ERROR; + } + + if (crcFlag && (hSbrHeader->syncState >= SBR_HEADER) && fDoDecodeSbrData) { + FDKpushFor(hBs, alignBits); + FDKcrcEndReg(&crcInfo, hBs, crcReg); /* End CRC region */ + FDKpushBack(hBs, alignBits); + /* Check CRC */ + if ((FDKcrcGetCRC(&crcInfo) ^ crcStartValue) != sbrCrc) { + fDoDecodeSbrData = 0; + if (headerStatus != HEADER_NOT_PRESENT) { + headerStatus = HEADER_ERROR; + hSbrHeader->syncState = SBR_NOT_INITIALIZED; + } + } + } + + if (!fDoDecodeSbrData) { + /* Set error flag for this slot to trigger concealment */ + setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR); + /* restore old frameData for concealment */ + FDKmemcpy(hFrameDataLeft, &frameDataLeftCopy, sizeof(SBR_FRAME_DATA)); + if (stereo) { + FDKmemcpy(hFrameDataRight, &frameDataRightCopy, sizeof(SBR_FRAME_DATA)); + } + errorStatus = SBRDEC_PARSE_ERROR; + } else { + /* Everything seems to be ok so clear the error flag */ + setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_OK); + } + + if (!stereo) { + /* Turn coupling off explicitely to avoid access to absent right frame data + that might occur with corrupt bitstreams. */ + hFrameDataLeft->coupling = COUPLING_OFF; + } + +bail: + + if (self != NULL) { + if (self->flags & SBRDEC_SYNTAX_DRM) { + hBs = hBsOriginal; + } + + if (errorStatus != SBRDEC_NOT_INITIALIZED) { + int useOldHdr = + ((headerStatus == HEADER_NOT_PRESENT) || + (headerStatus == HEADER_ERROR) || + (headerStatus == HEADER_RESET && errorStatus == SBRDEC_PARSE_ERROR)) + ? 1 + : 0; + + if (!useOldHdr && (thisHdrSlot != lastHdrSlot) && (hSbrHeader != NULL)) { + useOldHdr |= + (compareSbrHeader(hSbrHeader, + &self->sbrHeader[elementIndex][lastHdrSlot]) == 0) + ? 1 + : 0; + } + + if (hSbrElement != NULL) { + if (useOldHdr != 0) { + /* Use the old header for this frame */ + hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot; + } else { + /* Use the new header for this frame */ + hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = thisHdrSlot; + } + + /* Move frame pointer to the next slot which is up to be decoded/applied + * next */ + hSbrElement->useFrameSlot = + (hSbrElement->useFrameSlot + 1) % (self->numDelayFrames + 1); + } + } + } + + *count -= startPos - (INT)FDKgetValidBits(hBs); + + return errorStatus; +} + +/** + * \brief Render one SBR element into time domain signal. + * \param self SBR decoder handle + * \param timeData pointer to output buffer + * \param channelMapping pointer to UCHAR array where next 2 channel offsets are + * stored. + * \param elementIndex enumerating index of the SBR element to render. + * \param numInChannels number of channels from core coder. + * \param numOutChannels pointer to a location to return number of output + * channels. + * \param psPossible flag indicating if PS is possible or not. + * \return SBRDEC_OK if successfull, else error code + */ +static SBR_ERROR sbrDecoder_DecodeElement( + HANDLE_SBRDECODER self, LONG *input, LONG *timeData, const int timeDataSize, + const FDK_channelMapDescr *const mapDescr, const int mapIdx, + int channelIndex, const int elementIndex, const int numInChannels, + int *numOutChannels, const int psPossible) { + SBR_DECODER_ELEMENT *hSbrElement = self->pSbrElement[elementIndex]; + HANDLE_SBR_CHANNEL *pSbrChannel = + self->pSbrElement[elementIndex]->pSbrChannel; + HANDLE_SBR_HEADER_DATA hSbrHeader = + &self->sbrHeader[elementIndex] + [hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]]; + HANDLE_PS_DEC h_ps_d = self->hParametricStereoDec; + + /* get memory for frame data from scratch */ + SBR_FRAME_DATA *hFrameDataLeft = NULL; + SBR_FRAME_DATA *hFrameDataRight = NULL; + + SBR_ERROR errorStatus = SBRDEC_OK; + + INT strideOut, offset0 = 255, offset0_block = 0, offset1 = 255, + offset1_block = 0; + INT codecFrameSize = self->codecFrameSize; + + int stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0; + int numElementChannels = + hSbrElement + ->nChannels; /* Number of channels of the current SBR element */ + + hFrameDataLeft = + &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; + if (stereo) { + hFrameDataRight = + &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + } + + if (self->flags & SBRDEC_FLUSH) { + if (self->numFlushedFrames > self->numDelayFrames) { + int hdrIdx; + /* No valid SBR payload available, hence switch to upsampling (in all + * headers) */ + for (hdrIdx = 0; hdrIdx < ((1) + 1); hdrIdx += 1) { + if (self->sbrHeader[elementIndex][hdrIdx].syncState > UPSAMPLING) { + self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING; + } + } + } else { + /* Move frame pointer to the next slot which is up to be decoded/applied + * next */ + hSbrElement->useFrameSlot = + (hSbrElement->useFrameSlot + 1) % (self->numDelayFrames + 1); + /* Update header and frame data pointer because they have already been set + */ + hSbrHeader = + &self->sbrHeader[elementIndex] + [hSbrElement + ->useHeaderSlot[hSbrElement->useFrameSlot]]; + hFrameDataLeft = + &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; + if (stereo) { + hFrameDataRight = + &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + } + } + } + + /* Update the header error flag */ + hSbrHeader->frameErrorFlag = + hSbrElement->frameErrorFlag[hSbrElement->useFrameSlot]; + + /* + Prepare filterbank for upsampling if no valid bit stream data is available. + */ + if (hSbrHeader->syncState == SBR_NOT_INITIALIZED) { + errorStatus = + initHeaderData(hSbrHeader, self->sampleRateIn, self->sampleRateOut, + self->downscaleFactor, codecFrameSize, self->flags, + 1 /* SET_DEFAULT_HDR */ + ); + + if (errorStatus != SBRDEC_OK) { + return errorStatus; + } + + hSbrHeader->syncState = UPSAMPLING; + + errorStatus = sbrDecoder_HeaderUpdate(self, hSbrHeader, HEADER_NOT_PRESENT, + pSbrChannel, hSbrElement->nChannels); + + if (errorStatus != SBRDEC_OK) { + hSbrHeader->syncState = SBR_NOT_INITIALIZED; + return errorStatus; + } + } + + /* reset */ + if (hSbrHeader->status & SBRDEC_HDR_STAT_RESET) { + int ch; + int applySbrProc = (hSbrHeader->syncState == SBR_ACTIVE || + (hSbrHeader->frameErrorFlag == 0 && + hSbrHeader->syncState == SBR_HEADER)); + for (ch = 0; ch < numElementChannels; ch++) { + SBR_ERROR errorStatusTmp = SBRDEC_OK; + + errorStatusTmp = resetSbrDec( + &pSbrChannel[ch]->SbrDec, hSbrHeader, &pSbrChannel[ch]->prevFrameData, + self->synDownsampleFac, self->flags, pSbrChannel[ch]->frameData); + + if (errorStatusTmp != SBRDEC_OK) { + hSbrHeader->syncState = UPSAMPLING; + } + } + if (applySbrProc) { + hSbrHeader->status &= ~SBRDEC_HDR_STAT_RESET; + } + } + + /* decoding */ + if ((hSbrHeader->syncState == SBR_ACTIVE) || + ((hSbrHeader->syncState == SBR_HEADER) && + (hSbrHeader->frameErrorFlag == 0))) { + errorStatus = SBRDEC_OK; + + decodeSbrData(hSbrHeader, hFrameDataLeft, &pSbrChannel[0]->prevFrameData, + (stereo) ? hFrameDataRight : NULL, + (stereo) ? &pSbrChannel[1]->prevFrameData : NULL); + + /* Now we have a full parameter set and can do parameter + based concealment instead of plain upsampling. */ + hSbrHeader->syncState = SBR_ACTIVE; + } + + if (timeDataSize < + hSbrHeader->numberTimeSlots * hSbrHeader->timeStep * + self->pQmfDomain->globalConf.nBandsSynthesis * + (psPossible ? fMax(2, numInChannels) : numInChannels)) { + return SBRDEC_OUTPUT_BUFFER_TOO_SMALL; + } + + { + self->flags &= ~SBRDEC_PS_DECODED; + C_ALLOC_SCRATCH_START(pPsScratch, struct PS_DEC_COEFFICIENTS, 1) + + /* decode PS data if available */ + if (h_ps_d != NULL && psPossible && (hSbrHeader->syncState == SBR_ACTIVE)) { + int applyPs = 1; + + /* define which frame delay line slot to process */ + h_ps_d->processSlot = hSbrElement->useFrameSlot; + + applyPs = DecodePs(h_ps_d, hSbrHeader->frameErrorFlag, pPsScratch); + self->flags |= (applyPs) ? SBRDEC_PS_DECODED : 0; + } + + offset0 = FDK_chMapDescr_getMapValue(mapDescr, channelIndex, mapIdx); + offset0_block = offset0 * codecFrameSize; + if (stereo || psPossible) { + /* the value of offset1 only matters if the condition is true, however if + it is not true channelIndex+1 may exceed the channel map resutling in an + error, though the value of offset1 is actually meaningless. This is + prevented here. */ + offset1 = FDK_chMapDescr_getMapValue(mapDescr, channelIndex + 1, mapIdx); + offset1_block = offset1 * codecFrameSize; + } + /* Set strides for reading and writing */ + if (psPossible) + strideOut = (numInChannels < 2) ? 2 : numInChannels; + else + strideOut = numInChannels; + + /* use same buffers for left and right channel and apply PS per timeslot */ + /* Process left channel */ + sbr_dec(&pSbrChannel[0]->SbrDec, input + offset0_block, timeData + offset0, + (self->flags & SBRDEC_PS_DECODED) ? &pSbrChannel[1]->SbrDec : NULL, + timeData + offset1, strideOut, hSbrHeader, hFrameDataLeft, + &pSbrChannel[0]->prevFrameData, + (hSbrHeader->syncState == SBR_ACTIVE), h_ps_d, self->flags, + codecFrameSize, self->sbrInDataHeadroom); + + if (stereo) { + /* Process right channel */ + sbr_dec(&pSbrChannel[1]->SbrDec, input + offset1_block, + timeData + offset1, NULL, NULL, strideOut, hSbrHeader, + hFrameDataRight, &pSbrChannel[1]->prevFrameData, + (hSbrHeader->syncState == SBR_ACTIVE), NULL, self->flags, + codecFrameSize, self->sbrInDataHeadroom); + } + + C_ALLOC_SCRATCH_END(pPsScratch, struct PS_DEC_COEFFICIENTS, 1) + } + + if (h_ps_d != NULL) { + /* save PS status for next run */ + h_ps_d->psDecodedPrv = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0; + } + + if (psPossible && !(self->flags & SBRDEC_SKIP_QMF_SYN)) { + FDK_ASSERT(strideOut > 1); + if (!(self->flags & SBRDEC_PS_DECODED)) { + /* A decoder which is able to decode PS has to produce a stereo output + * even if no PS data is available. */ + /* So copy left channel to right channel. */ + int copyFrameSize = + codecFrameSize * self->pQmfDomain->QmfDomainOut->fb.no_channels; + copyFrameSize /= self->pQmfDomain->QmfDomainIn->fb.no_channels; + LONG *ptr; + INT i; + FDK_ASSERT(strideOut == 2); + + ptr = timeData; + for (i = copyFrameSize >> 1; i--;) { + LONG tmp; /* This temporal variable is required because some compilers + can't do *ptr++ = *ptr++ correctly. */ + tmp = *ptr++; + *ptr++ = tmp; + tmp = *ptr++; + *ptr++ = tmp; + } + } + *numOutChannels = 2; /* Output minimum two channels when PS is enabled. */ + } + + return errorStatus; +} + +SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, LONG *input, LONG *timeData, + const int timeDataSize, int *numChannels, + int *sampleRate, + const FDK_channelMapDescr *const mapDescr, + const int mapIdx, const int coreDecodedOk, + UCHAR *psDecoded, const INT inDataHeadroom, + INT *outDataHeadroom) { + SBR_ERROR errorStatus = SBRDEC_OK; + + int psPossible; + int sbrElementNum; + int numCoreChannels; + int numSbrChannels = 0; + + if ((self == NULL) || (timeData == NULL) || (numChannels == NULL) || + (sampleRate == NULL) || (psDecoded == NULL) || + !FDK_chMapDescr_isValid(mapDescr)) { + return SBRDEC_INVALID_ARGUMENT; + } + + psPossible = *psDecoded; + numCoreChannels = *numChannels; + if (numCoreChannels <= 0) { + return SBRDEC_INVALID_ARGUMENT; + } + + if (self->numSbrElements < 1) { + /* exit immediately to avoid access violations */ + return SBRDEC_NOT_INITIALIZED; + } + + /* Sanity check of allocated SBR elements. */ + for (sbrElementNum = 0; sbrElementNum < self->numSbrElements; + sbrElementNum++) { + if (self->pSbrElement[sbrElementNum] == NULL) { + return SBRDEC_NOT_INITIALIZED; + } + } + + if (self->numSbrElements != 1 || self->pSbrElement[0]->elementID != ID_SCE) { + psPossible = 0; + } + + self->sbrInDataHeadroom = inDataHeadroom; + *outDataHeadroom = (INT)(8); + + /* Make sure that even if no SBR data was found/parsed *psDecoded is returned + * 1 if psPossible was 0. */ + if (psPossible == 0) { + self->flags &= ~SBRDEC_PS_DECODED; + } + + /* replaces channel based reset inside sbr_dec() */ + if (((self->flags & SBRDEC_LOW_POWER) ? 1 : 0) != + ((self->pQmfDomain->globalConf.flags & QMF_FLAG_LP) ? 1 : 0)) { + if (self->flags & SBRDEC_LOW_POWER) { + self->pQmfDomain->globalConf.flags |= QMF_FLAG_LP; + self->pQmfDomain->globalConf.flags_requested |= QMF_FLAG_LP; + } else { + self->pQmfDomain->globalConf.flags &= ~QMF_FLAG_LP; + self->pQmfDomain->globalConf.flags_requested &= ~QMF_FLAG_LP; + } + if (FDK_QmfDomain_InitFilterBank(self->pQmfDomain, QMF_FLAG_KEEP_STATES)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + } + if (self->numSbrChannels > self->pQmfDomain->globalConf.nInputChannels) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + if (self->flags & SBRDEC_FLUSH) { + /* flushing is signalized, hence increment the flush frame counter */ + self->numFlushedFrames++; + } else { + /* no flushing is signalized, hence reset the flush frame counter */ + self->numFlushedFrames = 0; + } + + /* Loop over SBR elements */ + for (sbrElementNum = 0; sbrElementNum < self->numSbrElements; + sbrElementNum++) { + int numElementChan; + + if (psPossible && + self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) { + /* Disable PS and try decoding SBR mono. */ + psPossible = 0; + } + + numElementChan = + (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1; + + /* If core signal is bad then force upsampling */ + if (!coreDecodedOk) { + setFrameErrorFlag(self->pSbrElement[sbrElementNum], FRAME_ERROR_ALLSLOTS); + } + + errorStatus = sbrDecoder_DecodeElement( + self, input, timeData, timeDataSize, mapDescr, mapIdx, numSbrChannels, + sbrElementNum, + numCoreChannels, /* is correct even for USC SCI==2 case */ + &numElementChan, psPossible); + + if (errorStatus != SBRDEC_OK) { + goto bail; + } + + numSbrChannels += numElementChan; + + if (numSbrChannels >= numCoreChannels) { + break; + } + } + + /* Update numChannels and samplerate */ + /* Do not mess with output channels in case of USAC. numSbrChannels != + * numChannels for stereoConfigIndex == 2 */ + if (!(self->flags & SBRDEC_SYNTAX_USAC)) { + *numChannels = numSbrChannels; + } + *sampleRate = self->sampleRateOut; + *psDecoded = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0; + + /* Clear reset and flush flag because everything seems to be done + * successfully. */ + self->flags &= ~SBRDEC_FORCE_RESET; + self->flags &= ~SBRDEC_FLUSH; + +bail: + + return errorStatus; +} + +SBR_ERROR sbrDecoder_Close(HANDLE_SBRDECODER *pSelf) { + HANDLE_SBRDECODER self = *pSelf; + int i; + + if (self != NULL) { + if (self->hParametricStereoDec != NULL) { + DeletePsDec(&self->hParametricStereoDec); + } + + for (i = 0; i < (8); i++) { + sbrDecoder_DestroyElement(self, i); + } + + FreeRam_SbrDecoder(pSelf); + } + + return SBRDEC_OK; +} + +INT sbrDecoder_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return -1; + } + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) return -1; + info += i; + + info->module_id = FDK_SBRDEC; + info->version = + LIB_VERSION(SBRDECODER_LIB_VL0, SBRDECODER_LIB_VL1, SBRDECODER_LIB_VL2); + LIB_VERSION_STRING(info); + info->build_date = SBRDECODER_LIB_BUILD_DATE; + info->build_time = SBRDECODER_LIB_BUILD_TIME; + info->title = SBRDECODER_LIB_TITLE; + + /* Set flags */ + info->flags = 0 | CAPF_SBR_HQ | CAPF_SBR_LP | CAPF_SBR_PS_MPEG | + CAPF_SBR_DRM_BS | CAPF_SBR_CONCEALMENT | CAPF_SBR_DRC | + CAPF_SBR_ELD_DOWNSCALE | CAPF_SBR_HBEHQ; + /* End of flags */ + + return 0; +} + +UINT sbrDecoder_GetDelay(const HANDLE_SBRDECODER self) { + UINT outputDelay = 0; + + if (self != NULL) { + UINT flags = self->flags; + + /* See chapter 1.6.7.2 of ISO/IEC 14496-3 for the GA-SBR figures below. */ + + /* Are we initialized? */ + if ((self->numSbrChannels > 0) && (self->numSbrElements > 0)) { + /* Add QMF synthesis delay */ + if ((flags & SBRDEC_ELD_GRID) && IS_LOWDELAY(self->coreCodec)) { + /* Low delay SBR: */ + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + outputDelay += + (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */ + if (flags & SBRDEC_LD_MPS_QMF) { + outputDelay += 32; + } + } + } else if (!IS_USAC(self->coreCodec)) { + /* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...) + * branch: */ + outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 481 : 962; + if (flags & SBRDEC_SKIP_QMF_SYN) { + outputDelay -= 257; /* QMF synthesis */ + } + } + } + } + + return (outputDelay); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/transcendent.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/transcendent.h new file mode 100644 index 0000000000000..0e815c2da030f --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRdec/src/transcendent.h @@ -0,0 +1,372 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief FDK Fixed Point Arithmetic Library Interface +*/ + +#ifndef TRANSCENDENT_H +#define TRANSCENDENT_H + +#include "sbrdecoder.h" +#include "sbr_rom.h" + +/************************************************************************/ +/*! + \brief Get number of octaves between frequencies a and b + + The Result is scaled with 1/8. + The valid range for a and b is 1 to LOG_DUALIS_TABLE_SIZE. + + \return ld(a/b) / 8 +*/ +/************************************************************************/ +static inline FIXP_SGL FDK_getNumOctavesDiv8(INT a, /*!< lower band */ + INT b) /*!< upper band */ +{ + return ((SHORT)((LONG)(CalcLdInt(b) - CalcLdInt(a)) >> (FRACT_BITS - 3))); +} + +/************************************************************************/ +/*! + \brief Add two values given by mantissa and exponent. + + Mantissas are in fract format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+*/ +/************************************************************************/ +inline void FDK_add_MantExp(FIXP_SGL a_m, /*!< Mantissa of 1st operand a */ + SCHAR a_e, /*!< Exponent of 1st operand a */ + FIXP_SGL b_m, /*!< Mantissa of 2nd operand b */ + SCHAR b_e, /*!< Exponent of 2nd operand b */ + FIXP_SGL *ptrSum_m, /*!< Mantissa of result */ + SCHAR *ptrSum_e) /*!< Exponent of result */ +{ + FIXP_DBL accu; + int shift; + int shiftAbs; + + FIXP_DBL shiftedMantissa; + FIXP_DBL otherMantissa; + + /* Equalize exponents of the summands. + For the smaller summand, the exponent is adapted and + for compensation, the mantissa is shifted right. */ + + shift = (int)(a_e - b_e); + + shiftAbs = (shift > 0) ? shift : -shift; + shiftAbs = (shiftAbs < DFRACT_BITS - 1) ? shiftAbs : DFRACT_BITS - 1; + shiftedMantissa = (shift > 0) ? (FX_SGL2FX_DBL(b_m) >> shiftAbs) + : (FX_SGL2FX_DBL(a_m) >> shiftAbs); + otherMantissa = (shift > 0) ? FX_SGL2FX_DBL(a_m) : FX_SGL2FX_DBL(b_m); + *ptrSum_e = (shift > 0) ? a_e : b_e; + + accu = (shiftedMantissa >> 1) + (otherMantissa >> 1); + /* shift by 1 bit to avoid overflow */ + + if ((accu >= (FL2FXCONST_DBL(0.5f) - (FIXP_DBL)1)) || + (accu <= FL2FXCONST_DBL(-0.5f))) + *ptrSum_e += 1; + else + accu = (shiftedMantissa + otherMantissa); + + *ptrSum_m = FX_DBL2FX_SGL(accu); +} + +inline void FDK_add_MantExp(FIXP_DBL a, /*!< Mantissa of 1st operand a */ + SCHAR a_e, /*!< Exponent of 1st operand a */ + FIXP_DBL b, /*!< Mantissa of 2nd operand b */ + SCHAR b_e, /*!< Exponent of 2nd operand b */ + FIXP_DBL *ptrSum, /*!< Mantissa of result */ + SCHAR *ptrSum_e) /*!< Exponent of result */ +{ + FIXP_DBL accu; + int shift; + int shiftAbs; + + FIXP_DBL shiftedMantissa; + FIXP_DBL otherMantissa; + + /* Equalize exponents of the summands. + For the smaller summand, the exponent is adapted and + for compensation, the mantissa is shifted right. */ + + shift = (int)(a_e - b_e); + + shiftAbs = (shift > 0) ? shift : -shift; + shiftAbs = (shiftAbs < DFRACT_BITS - 1) ? shiftAbs : DFRACT_BITS - 1; + shiftedMantissa = (shift > 0) ? (b >> shiftAbs) : (a >> shiftAbs); + otherMantissa = (shift > 0) ? a : b; + *ptrSum_e = (shift > 0) ? a_e : b_e; + + accu = (shiftedMantissa >> 1) + (otherMantissa >> 1); + /* shift by 1 bit to avoid overflow */ + + if ((accu >= (FL2FXCONST_DBL(0.5f) - (FIXP_DBL)1)) || + (accu <= FL2FXCONST_DBL(-0.5f))) + *ptrSum_e += 1; + else + accu = (shiftedMantissa + otherMantissa); + + *ptrSum = accu; +} + +/************************************************************************/ +/*! + \brief Divide two values given by mantissa and exponent. + + Mantissas are in fract format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ + For performance reasons, the division is based on a table lookup + which limits accuracy. +*/ +/************************************************************************/ +static inline void FDK_divide_MantExp( + FIXP_SGL a_m, /*!< Mantissa of dividend a */ + SCHAR a_e, /*!< Exponent of dividend a */ + FIXP_SGL b_m, /*!< Mantissa of divisor b */ + SCHAR b_e, /*!< Exponent of divisor b */ + FIXP_SGL *ptrResult_m, /*!< Mantissa of quotient a/b */ + SCHAR *ptrResult_e) /*!< Exponent of quotient a/b */ + +{ + int preShift, postShift, index, shift; + FIXP_DBL ratio_m; + FIXP_SGL bInv_m = FL2FXCONST_SGL(0.0f); + + preShift = CntLeadingZeros(FX_SGL2FX_DBL(b_m)); + + /* + Shift b into the range from 0..INV_TABLE_SIZE-1, + + E.g. 10 bits must be skipped for INV_TABLE_BITS 8: + - leave 8 bits as index for table + - skip sign bit, + - skip first bit of mantissa, because this is always the same (>0.5) + + We are dealing with energies, so we need not care + about negative numbers + */ + + /* + The first interval has half width so the lowest bit of the index is + needed for a doubled resolution. + */ + shift = (FRACT_BITS - 2 - INV_TABLE_BITS - preShift); + + index = (shift < 0) ? (LONG)b_m << (-shift) : (LONG)b_m >> shift; + + /* The index has INV_TABLE_BITS +1 valid bits here. Clear the other bits. */ + index &= (1 << (INV_TABLE_BITS + 1)) - 1; + + /* Remove offset of half an interval */ + index--; + + /* Now the lowest bit is shifted out */ + index = index >> 1; + + /* Fetch inversed mantissa from table: */ + bInv_m = (index < 0) ? bInv_m : FDK_sbrDecoder_invTable[index]; + + /* Multiply a with the inverse of b: */ + ratio_m = (index < 0) ? FX_SGL2FX_DBL(a_m >> 1) : fMultDiv2(bInv_m, a_m); + + postShift = CntLeadingZeros(ratio_m) - 1; + + *ptrResult_m = FX_DBL2FX_SGL(ratio_m << postShift); + *ptrResult_e = a_e - b_e + 1 + preShift - postShift; +} + +static inline void FDK_divide_MantExp( + FIXP_DBL a_m, /*!< Mantissa of dividend a */ + SCHAR a_e, /*!< Exponent of dividend a */ + FIXP_DBL b_m, /*!< Mantissa of divisor b */ + SCHAR b_e, /*!< Exponent of divisor b */ + FIXP_DBL *ptrResult_m, /*!< Mantissa of quotient a/b */ + SCHAR *ptrResult_e) /*!< Exponent of quotient a/b */ + +{ + int preShift, postShift, index, shift; + FIXP_DBL ratio_m; + FIXP_SGL bInv_m = FL2FXCONST_SGL(0.0f); + + preShift = CntLeadingZeros(b_m); + + /* + Shift b into the range from 0..INV_TABLE_SIZE-1, + + E.g. 10 bits must be skipped for INV_TABLE_BITS 8: + - leave 8 bits as index for table + - skip sign bit, + - skip first bit of mantissa, because this is always the same (>0.5) + + We are dealing with energies, so we need not care + about negative numbers + */ + + /* + The first interval has half width so the lowest bit of the index is + needed for a doubled resolution. + */ + shift = (DFRACT_BITS - 2 - INV_TABLE_BITS - preShift); + + index = (shift < 0) ? (LONG)b_m << (-shift) : (LONG)b_m >> shift; + + /* The index has INV_TABLE_BITS +1 valid bits here. Clear the other bits. */ + index &= (1 << (INV_TABLE_BITS + 1)) - 1; + + /* Remove offset of half an interval */ + index--; + + /* Now the lowest bit is shifted out */ + index = index >> 1; + + /* Fetch inversed mantissa from table: */ + bInv_m = (index < 0) ? bInv_m : FDK_sbrDecoder_invTable[index]; + + /* Multiply a with the inverse of b: */ + ratio_m = (index < 0) ? (a_m >> 1) : fMultDiv2(bInv_m, a_m); + + postShift = CntLeadingZeros(ratio_m) - 1; + + *ptrResult_m = ratio_m << postShift; + *ptrResult_e = a_e - b_e + 1 + preShift - postShift; +} + +/*! + \brief Calculate the squareroot of a number given by mantissa and exponent + + Mantissa is in fract format with values between 0 and 1.
+ The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ The operand is addressed via pointers and will be overwritten with the result. + + For performance reasons, the square root is based on a table lookup + which limits accuracy. +*/ +static inline void FDK_sqrt_MantExp( + FIXP_DBL *mantissa, /*!< Pointer to mantissa */ + SCHAR *exponent, const SCHAR *destScale) { + FIXP_DBL input_m = *mantissa; + int input_e = (int)*exponent; + FIXP_DBL result = FL2FXCONST_DBL(0.0f); + int result_e = -FRACT_BITS; + + /* Call lookup square root, which does internally normalization. */ + result = sqrtFixp_lookup(input_m, &input_e); + result_e = input_e; + + /* Write result */ + if (exponent == destScale) { + *mantissa = result; + *exponent = result_e; + } else { + int shift = result_e - *destScale; + *mantissa = (shift >= 0) ? result << (INT)fixMin(DFRACT_BITS - 1, shift) + : result >> (INT)fixMin(DFRACT_BITS - 1, -shift); + *exponent = *destScale; + } +} + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/include/sbr_encoder.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/include/sbr_encoder.h new file mode 100644 index 0000000000000..d979ba6c784dd --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/include/sbr_encoder.h @@ -0,0 +1,483 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: SBR encoder top level processing prototype + +*******************************************************************************/ + +#ifndef SBR_ENCODER_H +#define SBR_ENCODER_H + +#include "common_fix.h" +#include "FDK_audio.h" + +#include "FDK_bitstream.h" + +/* core coder helpers */ +#define MAX_TRANS_FAC 8 +#define MAX_CODEC_FRAME_RATIO 2 +#define MAX_PAYLOAD_SIZE 256 + +typedef enum codecType { + CODEC_AAC = 0, + CODEC_AACLD = 1, + CODEC_UNSPECIFIED = 99 +} CODEC_TYPE; + +typedef struct { + INT bitRate; + INT nChannels; + INT sampleFreq; + INT transFac; + INT standardBitrate; +} CODEC_PARAM; + +typedef enum { + SBR_MONO, + SBR_LEFT_RIGHT, + SBR_COUPLING, + SBR_SWITCH_LRC +} SBR_STEREO_MODE; + +/* bitstream syntax flags */ +enum { + SBR_SYNTAX_LOW_DELAY = 0x0001, + SBR_SYNTAX_SCALABLE = 0x0002, + SBR_SYNTAX_CRC = 0x0004, + SBR_SYNTAX_DRM_CRC = 0x0008, + SBR_SYNTAX_ELD_REDUCED_DELAY = 0x0010 +}; + +typedef enum { FREQ_RES_LOW = 0, FREQ_RES_HIGH } FREQ_RES; + +typedef struct { + CODEC_TYPE coreCoder; /*!< LC or ELD */ + UINT bitrateFrom; /*!< inclusive */ + UINT bitrateTo; /*!< exclusive */ + + UINT sampleRate; /*!< */ + UCHAR numChannels; /*!< */ + + UCHAR startFreq; /*!< bs_start_freq */ + UCHAR startFreqSpeech; /*!< bs_start_freq for speech config flag */ + UCHAR stopFreq; /*!< bs_stop_freq */ + UCHAR stopFreqSpeech; /*!< bs_stop_freq for speech config flag */ + + UCHAR numNoiseBands; /*!< */ + UCHAR noiseFloorOffset; /*!< */ + SCHAR noiseMaxLevel; /*!< */ + SBR_STEREO_MODE stereoMode; /*!< */ + UCHAR freqScale; /*!< */ +} sbrTuningTable_t; + +typedef struct sbrConfiguration { + /* + core coder dependent configurations + */ + CODEC_PARAM + codecSettings; /*!< Core coder settings. To be set from core coder. */ + INT SendHeaderDataTime; /*!< SBR header send update frequency in ms. */ + INT useWaveCoding; /*!< Flag: usage of wavecoding tool. */ + INT crcSbr; /*!< Flag: usage of SBR-CRC. */ + INT dynBwSupported; /*!< Flag: support for dynamic bandwidth in this + combination. */ + INT parametricCoding; /*!< Flag: usage of parametric coding tool. */ + INT downSampleFactor; /*!< Sampling rate relation between the SBR and the core + encoder. */ + FREQ_RES freq_res_fixfix[2]; /*!< Frequency resolution of envelopes in frame + class FIXFIX, for non-split case and split + case */ + UCHAR fResTransIsLow; /*!< Frequency resolution of envelopes in transient + frames: low (0) or variable (1) */ + + /* + core coder dependent tuning parameters + */ + INT tran_thr; /*!< SBR transient detector threshold (* 100). */ + INT noiseFloorOffset; /*!< Noise floor offset. */ + UINT useSpeechConfig; /*!< Flag: adapt tuning parameters according to speech. + */ + + /* + core coder independent configurations + */ + INT sbrFrameSize; /*!< SBR frame size in samples. Will be calculated from core + coder settings. */ + INT sbr_data_extra; /*!< Flag usage of data extra. */ + INT amp_res; /*!< Amplitude resolution. */ + INT ana_max_level; /*!< Noise insertion maximum level. */ + INT tran_fc; /*!< Transient detector start frequency. */ + INT tran_det_mode; /*!< Transient detector mode. */ + INT spread; /*!< Flag: usage of SBR spread. */ + INT stat; /*!< Flag: usage of static framing. */ + INT e; /*!< Number of envelopes when static framing is chosen. */ + SBR_STEREO_MODE stereoMode; /*!< SBR stereo mode. */ + INT deltaTAcrossFrames; /*!< Flag: allow time-delta coding. */ + FIXP_DBL dF_edge_1stEnv; /*!< Extra fraction delta-F coding is allowed to be + more expensive. */ + FIXP_DBL dF_edge_incr; /*!< Increment dF_edge_1stEnv this much if dT-coding + was used this frame. */ + INT sbr_invf_mode; /*!< Inverse filtering mode. */ + INT sbr_xpos_mode; /*!< Transposer mode. */ + INT sbr_xpos_ctrl; /*!< Transposer control. */ + INT sbr_xpos_level; /*!< Transposer 3rd order level. */ + INT startFreq; /*!< The start frequency table index. */ + INT stopFreq; /*!< The stop frequency table index. */ + INT useSaPan; /*!< Flag: usage of SAPAN stereo. */ + INT dynBwEnabled; /*!< Flag: usage of dynamic bandwidth. */ + INT bParametricStereo; /*!< Flag: usage of parametric stereo coding tool. */ + + /* + header_extra1 configuration + */ + UCHAR freqScale; /*!< Frequency grouping. */ + INT alterScale; /*!< Scale resolution. */ + INT sbr_noise_bands; /*!< Number of noise bands. */ + + /* + header_extra2 configuration + */ + INT sbr_limiter_bands; /*!< Number of limiter bands. */ + INT sbr_limiter_gains; /*!< Gain of limiter. */ + INT sbr_interpol_freq; /*!< Flag: use interpolation in freq. direction. */ + INT sbr_smoothing_length; /*!< Flag: choose length 4 or 0 (=on, off). */ + UCHAR init_amp_res_FF; + FIXP_DBL threshold_AmpRes_FF_m; + SCHAR threshold_AmpRes_FF_e; +} sbrConfiguration, *sbrConfigurationPtr; + +typedef struct SBR_CONFIG_DATA { + UINT sbrSyntaxFlags; /**< SBR syntax flags derived from AOT. */ + INT nChannels; /**< Number of channels. */ + + INT nSfb[2]; /**< Number of SBR scalefactor bands for LO_RES and HI_RES (?) */ + INT num_Master; /**< Number of elements in v_k_master. */ + INT sampleFreq; /**< SBR sampling frequency. */ + INT frameSize; + INT xOverFreq; /**< The SBR start frequency. */ + INT dynXOverFreq; /**< Used crossover frequency when dynamic bandwidth is + enabled. */ + + INT noQmfBands; /**< Number of QMF frequency bands. */ + INT noQmfSlots; /**< Number of QMF slots. */ + + UCHAR *freqBandTable[2]; /**< Frequency table for low and hires, only + MAX_FREQ_COEFFS/2 +1 coeffs actually needed for + lowres. */ + UCHAR + *v_k_master; /**< Master BandTable where freqBandTable is derived from. */ + + SBR_STEREO_MODE stereoMode; + INT noEnvChannels; /**< Number of envelope channels. */ + + INT useWaveCoding; /**< Flag indicates whether to use wave coding at all. */ + INT useParametricCoding; /**< Flag indicates whether to use para coding at + all. */ + INT xposCtrlSwitch; /**< Flag indicates whether to switch xpos ctrl on the + fly. */ + INT switchTransposers; /**< Flag indicates whether to switch xpos on the fly . + */ + UCHAR initAmpResFF; + FIXP_DBL thresholdAmpResFF_m; + SCHAR thresholdAmpResFF_e; +} SBR_CONFIG_DATA, *HANDLE_SBR_CONFIG_DATA; + +typedef struct { + MP4_ELEMENT_ID elType; + INT bitRate; + int instanceTag; + UCHAR fParametricStereo; + UCHAR fDualMono; /**< This flags allows to disable coupling in sbr channel + pair element */ + UCHAR nChannelsInEl; + UCHAR ChannelIndex[2]; +} SBR_ELEMENT_INFO; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct SBR_ENCODER *HANDLE_SBR_ENCODER; + +/** + * \brief Get the max required input buffer size including delay balancing + * space for N audio channels. + * \param noChannels Number of audio channels. + * \return Max required input buffer size in bytes. + */ +INT sbrEncoder_GetInBufferSize(int noChannels); + +INT sbrEncoder_Open(HANDLE_SBR_ENCODER *phSbrEncoder, INT nElements, + INT nChannels, INT supportPS); + +/** + * \brief Get closest working bitrate to specified desired + * bitrate for a single SBR element. + * \param bitRate The desired target bit rate + * \param numChannels The amount of audio channels + * \param coreSampleRate The sample rate of the core coder + * \param aot The current Audio Object Type + * \return Closest working bit rate to bitRate value + */ +UINT sbrEncoder_LimitBitRate(UINT bitRate, UINT numChannels, + UINT coreSampleRate, AUDIO_OBJECT_TYPE aot); + +/** + * \brief Check whether downsampled SBR single rate is possible + * with given audio object type. + * \param aot The Audio object type. + * \return 0 when downsampled SBR is not possible, + * 1 when downsampled SBR is possible. + */ +UINT sbrEncoder_IsSingleRatePossible(AUDIO_OBJECT_TYPE aot); + +/** + * \brief Initialize SBR Encoder instance. + * \param phSbrEncoder Pointer to a SBR Encoder instance. + * \param elInfo Structure that describes the element/channel + * arrangement. + * \param noElements Amount of elements described in elInfo. + * \param inputBuffer Pointer to the encoder audio buffer + * \param inputBufferBufSize Buffer offset of one channel (frameSize + delay) + * \param bandwidth Returns the core audio encoder bandwidth (output) + * \param bufferOffset Returns the offset for the audio input data in order + * to do delay balancing. + * \param numChannels Input: Encoder input channels. output: core encoder + * channels. + * \param sampleRate Input: Encoder samplerate. output core encoder + * samplerate. + * \param downSampleFactor Input: Relation between SBR and core coder sampling + * rate; + * \param frameLength Input: Encoder frameLength. output core encoder + * frameLength. + * \param aot Input: AOT.. + * \param delay Input: core encoder delay. Output: total delay + * because of SBR. + * \param transformFactor The core encoder transform factor (blockswitching). + * \param headerPeriod Repetition rate of the SBR header: + * - (-1) means intern configuration. + * - (1-10) corresponds to header repetition rate in + * frames. + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_Init(HANDLE_SBR_ENCODER hSbrEncoder, + SBR_ELEMENT_INFO elInfo[(8)], int noElements, + INT_PCM *inputBuffer, UINT inputBufferBufSize, + INT *coreBandwidth, INT *inputBufferOffset, + INT *numChannels, const UINT syntaxFlags, INT *sampleRate, + UINT *downSampleFactor, INT *frameLength, + AUDIO_OBJECT_TYPE aot, int *delay, int transformFactor, + const int headerPeriod, ULONG statesInitFlag); + +/** + * \brief Do delay line buffers housekeeping. To be called after + * each encoded audio frame. + * \param hEnvEnc SBR Encoder handle. + * \param timeBuffer Pointer to the encoder audio buffer. + * \param timeBufferBufSIze buffer size for one channel + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_UpdateBuffers(HANDLE_SBR_ENCODER hEnvEnc, INT_PCM *timeBuffer, + UINT timeBufferBufSIze); + +/** + * \brief Close SBR encoder instance. + * \param phEbrEncoder Handle of SBR encoder instance to be closed. + * \return void + */ +void sbrEncoder_Close(HANDLE_SBR_ENCODER *phEbrEncoder); + +/** + * \brief Encode SBR data of one complete audio frame. + * \param hEnvEncoder Handle of SBR encoder instance. + * \param samples Time samples, not interleaved. + * \param timeInStride Channel offset of samples buffer. + * \param sbrDataBits Size of SBR payload in bits. + * \param sbrData SBR payload. + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_EncodeFrame(HANDLE_SBR_ENCODER hEnvEncoder, INT_PCM *samples, + UINT samplesBufSize, UINT sbrDataBits[(8)], + UCHAR sbrData[(8)][MAX_PAYLOAD_SIZE]); + +/** + * \brief Write SBR headers of one SBR element. + * \param sbrEncoder Handle of the SBR encoder instance. + * \param hBs Handle of bit stream handle to write SBR header to. + * \param element_index Index of the SBR element which header should be written. + * \param fSendHeaders Flag indicating that the SBR encoder should send more + * headers in the SBR payload or not. + * \return void + */ +void sbrEncoder_GetHeader(HANDLE_SBR_ENCODER sbrEncoder, + HANDLE_FDK_BITSTREAM hBs, INT element_index, + int fSendHeaders); + +/** + * \brief Request to write SBR header. + * \param hSbrEncoder SBR encoder handle. + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_SendHeader(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Request if last sbr payload contains an SBR header. + * \param hSbrEncoder SBR encoder handle. + * \return 1 contains sbr header, 0 without sbr header. + */ +INT sbrEncoder_ContainsHeader(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief SBR header delay in frames. + * \param hSbrEncoder SBR encoder handle. + * \return Delay in frames, -1 on failure. + */ +INT sbrEncoder_GetHeaderDelay(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Bitstrem delay in SBR frames. + * \param hSbrEncoder SBR encoder handle. + * \return Delay in frames, -1 on failure. + */ +INT sbrEncoder_GetBsDelay(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Prepare SBR payload for SAP. + * \param hSbrEncoder SBR encoder handle. + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_SAPPrepare(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief SBR encoder bitrate estimation. + * \param hSbrEncoder SBR encoder handle. + * \return Estimated bitrate. + */ +INT sbrEncoder_GetEstimateBitrate(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Delay between input data and downsampled output data. + * \param hSbrEncoder SBR encoder handle. + * \return Delay. + */ +INT sbrEncoder_GetInputDataDelay(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Delay caused by the SBR decoder. + * \param hSbrEncoder SBR encoder handle. + * \return Delay. + */ +INT sbrEncoder_GetSbrDecDelay(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Get decoder library version info. + * \param info Pointer to an allocated LIB_INFO struct, where library info is + * written to. + * \return 0 on sucess. + */ +INT sbrEncoder_GetLibInfo(LIB_INFO *info); + +void sbrPrintRAM(void); + +void sbrPrintROM(void); + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef __SBR_MAIN_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/bit_sbr.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/bit_sbr.cpp new file mode 100644 index 0000000000000..5a65e98f7ecfe --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/bit_sbr.cpp @@ -0,0 +1,1049 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief SBR bit writing routines $Revision: 93300 $ +*/ + +#include "bit_sbr.h" + +#include "code_env.h" +#include "cmondata.h" +#include "sbr.h" + +#include "ps_main.h" + +typedef enum { SBR_ID_SCE = 1, SBR_ID_CPE } SBR_ELEMENT_TYPE; + +static INT encodeSbrData(HANDLE_SBR_ENV_DATA sbrEnvDataLeft, + HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_COMMON_DATA cmonData, SBR_ELEMENT_TYPE sbrElem, + INT coupling, UINT sbrSyntaxFlags); + +static INT encodeSbrHeader(HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_COMMON_DATA cmonData); + +static INT encodeSbrHeaderData(HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_FDK_BITSTREAM hBitStream); + +static INT encodeSbrSingleChannelElement( + HANDLE_SBR_ENV_DATA sbrEnvData, HANDLE_FDK_BITSTREAM hBitStream, + HANDLE_PARAMETRIC_STEREO hParametricStereo, const UINT sbrSyntaxFlags); + +static INT encodeSbrChannelPairElement( + HANDLE_SBR_ENV_DATA sbrEnvDataLeft, HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_PARAMETRIC_STEREO hParametricStereo, HANDLE_FDK_BITSTREAM hBitStream, + const INT coupling, const UINT sbrSyntaxFlags); + +static INT encodeSbrGrid(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream); + +static int encodeLowDelaySbrGrid(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, + const int transmitFreqs, + const UINT sbrSyntaxFlags); + +static INT encodeSbrDtdf(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream); + +static INT writeNoiseLevelData(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, INT coupling); + +static INT writeEnvelopeData(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, INT coupling); + +static INT writeSyntheticCodingData(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream); + +static INT encodeExtendedData(HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitStream); + +static INT getSbrExtendedDataSize(HANDLE_PARAMETRIC_STEREO hParametricStereo); + +/***************************************************************************** + + functionname: FDKsbrEnc_WriteEnvSingleChannelElement + description: writes pure SBR single channel data element + returns: number of bits written + input: + output: + +*****************************************************************************/ +INT FDKsbrEnc_WriteEnvSingleChannelElement( + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_COMMON_DATA cmonData, UINT sbrSyntaxFlags) + +{ + INT payloadBits = 0; + + cmonData->sbrHdrBits = 0; + cmonData->sbrDataBits = 0; + + /* write pure sbr data */ + if (sbrEnvData != NULL) { + /* write header */ + payloadBits += encodeSbrHeader(sbrHeaderData, sbrBitstreamData, cmonData); + + /* write data */ + payloadBits += encodeSbrData(sbrEnvData, NULL, hParametricStereo, cmonData, + SBR_ID_SCE, 0, sbrSyntaxFlags); + } + return payloadBits; +} + +/***************************************************************************** + + functionname: FDKsbrEnc_WriteEnvChannelPairElement + description: writes pure SBR channel pair data element + returns: number of bits written + input: + output: + +*****************************************************************************/ +INT FDKsbrEnc_WriteEnvChannelPairElement( + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_SBR_ENV_DATA sbrEnvDataLeft, HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_COMMON_DATA cmonData, UINT sbrSyntaxFlags) + +{ + INT payloadBits = 0; + cmonData->sbrHdrBits = 0; + cmonData->sbrDataBits = 0; + + /* write pure sbr data */ + if ((sbrEnvDataLeft != NULL) && (sbrEnvDataRight != NULL)) { + /* write header */ + payloadBits += encodeSbrHeader(sbrHeaderData, sbrBitstreamData, cmonData); + + /* write data */ + payloadBits += encodeSbrData(sbrEnvDataLeft, sbrEnvDataRight, + hParametricStereo, cmonData, SBR_ID_CPE, + sbrHeaderData->coupling, sbrSyntaxFlags); + } + return payloadBits; +} + +INT FDKsbrEnc_CountSbrChannelPairElement( + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_SBR_ENV_DATA sbrEnvDataLeft, HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_COMMON_DATA cmonData, UINT sbrSyntaxFlags) { + INT payloadBits; + INT bitPos = FDKgetValidBits(&cmonData->sbrBitbuf); + + payloadBits = FDKsbrEnc_WriteEnvChannelPairElement( + sbrHeaderData, hParametricStereo, sbrBitstreamData, sbrEnvDataLeft, + sbrEnvDataRight, cmonData, sbrSyntaxFlags); + + FDKpushBack(&cmonData->sbrBitbuf, + (FDKgetValidBits(&cmonData->sbrBitbuf) - bitPos)); + + return payloadBits; +} + +void sbrEncoder_GetHeader(SBR_ENCODER *sbrEncoder, HANDLE_FDK_BITSTREAM hBs, + INT element_index, int fSendHeaders) { + encodeSbrHeaderData(&sbrEncoder->sbrElement[element_index]->sbrHeaderData, + hBs); + + if (fSendHeaders == 0) { + /* Prevent header being embedded into the SBR payload. */ + sbrEncoder->sbrElement[element_index]->sbrBitstreamData.NrSendHeaderData = + -1; + sbrEncoder->sbrElement[element_index]->sbrBitstreamData.HeaderActive = 0; + sbrEncoder->sbrElement[element_index] + ->sbrBitstreamData.CountSendHeaderData = -1; + } +} + +/***************************************************************************** + + functionname: encodeSbrHeader + description: encodes SBR Header information + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT encodeSbrHeader(HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_COMMON_DATA cmonData) { + INT payloadBits = 0; + + if (sbrBitstreamData->HeaderActive) { + payloadBits += FDKwriteBits(&cmonData->sbrBitbuf, 1, 1); + payloadBits += encodeSbrHeaderData(sbrHeaderData, &cmonData->sbrBitbuf); + } else { + payloadBits += FDKwriteBits(&cmonData->sbrBitbuf, 0, 1); + } + + cmonData->sbrHdrBits = payloadBits; + + return payloadBits; +} + +/***************************************************************************** + + functionname: encodeSbrHeaderData + description: writes sbr_header() + bs_protocol_version through bs_header_extra_2 + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT encodeSbrHeaderData(HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_FDK_BITSTREAM hBitStream) + +{ + INT payloadBits = 0; + if (sbrHeaderData != NULL) { + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_amp_res, + SI_SBR_AMP_RES_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_start_frequency, + SI_SBR_START_FREQ_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_stop_frequency, + SI_SBR_STOP_FREQ_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_xover_band, + SI_SBR_XOVER_BAND_BITS); + + payloadBits += FDKwriteBits(hBitStream, 0, SI_SBR_RESERVED_BITS); + + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->header_extra_1, + SI_SBR_HEADER_EXTRA_1_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->header_extra_2, + SI_SBR_HEADER_EXTRA_2_BITS); + + if (sbrHeaderData->header_extra_1) { + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->freqScale, + SI_SBR_FREQ_SCALE_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->alterScale, + SI_SBR_ALTER_SCALE_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_noise_bands, + SI_SBR_NOISE_BANDS_BITS); + } /* sbrHeaderData->header_extra_1 */ + + if (sbrHeaderData->header_extra_2) { + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_limiter_bands, + SI_SBR_LIMITER_BANDS_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_limiter_gains, + SI_SBR_LIMITER_GAINS_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_interpol_freq, + SI_SBR_INTERPOL_FREQ_BITS); + payloadBits += + FDKwriteBits(hBitStream, sbrHeaderData->sbr_smoothing_length, + SI_SBR_SMOOTHING_LENGTH_BITS); + + } /* sbrHeaderData->header_extra_2 */ + } /* sbrHeaderData != NULL */ + + return payloadBits; +} + +/***************************************************************************** + + functionname: encodeSbrData + description: encodes sbr Data information + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT encodeSbrData(HANDLE_SBR_ENV_DATA sbrEnvDataLeft, + HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_COMMON_DATA cmonData, SBR_ELEMENT_TYPE sbrElem, + INT coupling, UINT sbrSyntaxFlags) { + INT payloadBits = 0; + + switch (sbrElem) { + case SBR_ID_SCE: + payloadBits += + encodeSbrSingleChannelElement(sbrEnvDataLeft, &cmonData->sbrBitbuf, + hParametricStereo, sbrSyntaxFlags); + break; + case SBR_ID_CPE: + payloadBits += encodeSbrChannelPairElement( + sbrEnvDataLeft, sbrEnvDataRight, hParametricStereo, + &cmonData->sbrBitbuf, coupling, sbrSyntaxFlags); + break; + default: + /* we never should apply SBR to any other element type */ + FDK_ASSERT(0); + } + + cmonData->sbrDataBits = payloadBits; + + return payloadBits; +} + +#define MODE_FREQ_TANS 1 +#define MODE_NO_FREQ_TRAN 0 +#define LD_TRANSMISSION MODE_FREQ_TANS +static int encodeFreqs(int mode) { return ((mode & MODE_FREQ_TANS) ? 1 : 0); } + +/***************************************************************************** + + functionname: encodeSbrSingleChannelElement + description: encodes sbr SCE information + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT encodeSbrSingleChannelElement( + HANDLE_SBR_ENV_DATA sbrEnvData, HANDLE_FDK_BITSTREAM hBitStream, + HANDLE_PARAMETRIC_STEREO hParametricStereo, const UINT sbrSyntaxFlags) { + INT i, payloadBits = 0; + + payloadBits += FDKwriteBits(hBitStream, 0, + SI_SBR_DATA_EXTRA_BITS); /* no reserved bits */ + + if (sbrEnvData->ldGrid) { + if (sbrEnvData->hSbrBSGrid->frameClass != FIXFIXonly) { + /* encode normal SbrGrid */ + payloadBits += encodeSbrGrid(sbrEnvData, hBitStream); + } else { + /* use FIXFIXonly frame Grid */ + payloadBits += encodeLowDelaySbrGrid( + sbrEnvData, hBitStream, encodeFreqs(LD_TRANSMISSION), sbrSyntaxFlags); + } + } else { + if (sbrSyntaxFlags & SBR_SYNTAX_SCALABLE) { + payloadBits += FDKwriteBits(hBitStream, 1, SI_SBR_COUPLING_BITS); + } + payloadBits += encodeSbrGrid(sbrEnvData, hBitStream); + } + + payloadBits += encodeSbrDtdf(sbrEnvData, hBitStream); + + for (i = 0; i < sbrEnvData->noOfnoisebands; i++) { + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->sbr_invf_mode_vec[i], + SI_SBR_INVF_MODE_BITS); + } + + payloadBits += writeEnvelopeData(sbrEnvData, hBitStream, 0); + payloadBits += writeNoiseLevelData(sbrEnvData, hBitStream, 0); + + payloadBits += writeSyntheticCodingData(sbrEnvData, hBitStream); + + payloadBits += encodeExtendedData(hParametricStereo, hBitStream); + + return payloadBits; +} + +/***************************************************************************** + + functionname: encodeSbrChannelPairElement + description: encodes sbr CPE information + returns: + input: + output: + +*****************************************************************************/ +static INT encodeSbrChannelPairElement( + HANDLE_SBR_ENV_DATA sbrEnvDataLeft, HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_PARAMETRIC_STEREO hParametricStereo, HANDLE_FDK_BITSTREAM hBitStream, + const INT coupling, const UINT sbrSyntaxFlags) { + INT payloadBits = 0; + INT i = 0; + + payloadBits += FDKwriteBits(hBitStream, 0, + SI_SBR_DATA_EXTRA_BITS); /* no reserved bits */ + + payloadBits += FDKwriteBits(hBitStream, coupling, SI_SBR_COUPLING_BITS); + + if (coupling) { + if (sbrEnvDataLeft->ldGrid) { + if (sbrEnvDataLeft->hSbrBSGrid->frameClass != FIXFIXonly) { + /* normal SbrGrid */ + payloadBits += encodeSbrGrid(sbrEnvDataLeft, hBitStream); + + } else { + /* FIXFIXonly frame Grid */ + payloadBits += + encodeLowDelaySbrGrid(sbrEnvDataLeft, hBitStream, + encodeFreqs(LD_TRANSMISSION), sbrSyntaxFlags); + } + } else + payloadBits += encodeSbrGrid(sbrEnvDataLeft, hBitStream); + + payloadBits += encodeSbrDtdf(sbrEnvDataLeft, hBitStream); + payloadBits += encodeSbrDtdf(sbrEnvDataRight, hBitStream); + + for (i = 0; i < sbrEnvDataLeft->noOfnoisebands; i++) { + payloadBits += + FDKwriteBits(hBitStream, sbrEnvDataLeft->sbr_invf_mode_vec[i], + SI_SBR_INVF_MODE_BITS); + } + + payloadBits += writeEnvelopeData(sbrEnvDataLeft, hBitStream, 1); + payloadBits += writeNoiseLevelData(sbrEnvDataLeft, hBitStream, 1); + payloadBits += writeEnvelopeData(sbrEnvDataRight, hBitStream, 1); + payloadBits += writeNoiseLevelData(sbrEnvDataRight, hBitStream, 1); + + payloadBits += writeSyntheticCodingData(sbrEnvDataLeft, hBitStream); + payloadBits += writeSyntheticCodingData(sbrEnvDataRight, hBitStream); + + } else { /* no coupling */ + FDK_ASSERT(sbrEnvDataLeft->ldGrid == sbrEnvDataRight->ldGrid); + + if (sbrEnvDataLeft->ldGrid || sbrEnvDataRight->ldGrid) { + /* sbrEnvDataLeft (left channel) */ + if (sbrEnvDataLeft->hSbrBSGrid->frameClass != FIXFIXonly) { + /* no FIXFIXonly Frame so we dont need encodeLowDelaySbrGrid */ + /* normal SbrGrid */ + payloadBits += encodeSbrGrid(sbrEnvDataLeft, hBitStream); + + } else { + /* FIXFIXonly frame Grid */ + payloadBits += + encodeLowDelaySbrGrid(sbrEnvDataLeft, hBitStream, + encodeFreqs(LD_TRANSMISSION), sbrSyntaxFlags); + } + + /* sbrEnvDataRight (right channel) */ + if (sbrEnvDataRight->hSbrBSGrid->frameClass != FIXFIXonly) { + /* no FIXFIXonly Frame so we dont need encodeLowDelaySbrGrid */ + /* normal SbrGrid */ + payloadBits += encodeSbrGrid(sbrEnvDataRight, hBitStream); + + } else { + /* FIXFIXonly frame Grid */ + payloadBits += + encodeLowDelaySbrGrid(sbrEnvDataRight, hBitStream, + encodeFreqs(LD_TRANSMISSION), sbrSyntaxFlags); + } + } else { + payloadBits += encodeSbrGrid(sbrEnvDataLeft, hBitStream); + payloadBits += encodeSbrGrid(sbrEnvDataRight, hBitStream); + } + payloadBits += encodeSbrDtdf(sbrEnvDataLeft, hBitStream); + payloadBits += encodeSbrDtdf(sbrEnvDataRight, hBitStream); + + for (i = 0; i < sbrEnvDataLeft->noOfnoisebands; i++) { + payloadBits += + FDKwriteBits(hBitStream, sbrEnvDataLeft->sbr_invf_mode_vec[i], + SI_SBR_INVF_MODE_BITS); + } + for (i = 0; i < sbrEnvDataRight->noOfnoisebands; i++) { + payloadBits += + FDKwriteBits(hBitStream, sbrEnvDataRight->sbr_invf_mode_vec[i], + SI_SBR_INVF_MODE_BITS); + } + + payloadBits += writeEnvelopeData(sbrEnvDataLeft, hBitStream, 0); + payloadBits += writeEnvelopeData(sbrEnvDataRight, hBitStream, 0); + payloadBits += writeNoiseLevelData(sbrEnvDataLeft, hBitStream, 0); + payloadBits += writeNoiseLevelData(sbrEnvDataRight, hBitStream, 0); + + payloadBits += writeSyntheticCodingData(sbrEnvDataLeft, hBitStream); + payloadBits += writeSyntheticCodingData(sbrEnvDataRight, hBitStream); + + } /* coupling */ + + payloadBits += encodeExtendedData(hParametricStereo, hBitStream); + + return payloadBits; +} + +static INT ceil_ln2(INT x) { + INT tmp = -1; + while ((1 << ++tmp) < x) + ; + return (tmp); +} + +/***************************************************************************** + + functionname: encodeSbrGrid + description: if hBitStream != NULL writes bits that describes the + time/frequency grouping of a frame; else counts them only + returns: number of bits written or counted + input: + output: + +*****************************************************************************/ +static INT encodeSbrGrid(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream) { + INT payloadBits = 0; + INT i, temp; + INT bufferFrameStart = sbrEnvData->hSbrBSGrid->bufferFrameStart; + INT numberTimeSlots = sbrEnvData->hSbrBSGrid->numberTimeSlots; + + if (sbrEnvData->ldGrid) + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->frameClass, + SBR_CLA_BITS_LD); + else + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->frameClass, + SBR_CLA_BITS); + + switch (sbrEnvData->hSbrBSGrid->frameClass) { + case FIXFIXonly: + FDK_ASSERT(0 /* Fatal error in encodeSbrGrid! */); + break; + case FIXFIX: + temp = ceil_ln2(sbrEnvData->hSbrBSGrid->bs_num_env); + payloadBits += FDKwriteBits(hBitStream, temp, SBR_ENV_BITS); + if ((sbrEnvData->ldGrid) && (sbrEnvData->hSbrBSGrid->bs_num_env == 1)) + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->currentAmpResFF, + SI_SBR_AMP_RES_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->v_f[0], + SBR_RES_BITS); + + break; + + case FIXVAR: + case VARFIX: + if (sbrEnvData->hSbrBSGrid->frameClass == FIXVAR) + temp = sbrEnvData->hSbrBSGrid->bs_abs_bord - + (bufferFrameStart + numberTimeSlots); + else + temp = sbrEnvData->hSbrBSGrid->bs_abs_bord - bufferFrameStart; + + payloadBits += FDKwriteBits(hBitStream, temp, SBR_ABS_BITS); + payloadBits += + FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->n, SBR_NUM_BITS); + + for (i = 0; i < sbrEnvData->hSbrBSGrid->n; i++) { + temp = (sbrEnvData->hSbrBSGrid->bs_rel_bord[i] - 2) >> 1; + payloadBits += FDKwriteBits(hBitStream, temp, SBR_REL_BITS); + } + + temp = ceil_ln2(sbrEnvData->hSbrBSGrid->n + 2); + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->p, temp); + + for (i = 0; i < sbrEnvData->hSbrBSGrid->n + 1; i++) { + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->v_f[i], + SBR_RES_BITS); + } + break; + + case VARVAR: + temp = sbrEnvData->hSbrBSGrid->bs_abs_bord_0 - bufferFrameStart; + payloadBits += FDKwriteBits(hBitStream, temp, SBR_ABS_BITS); + temp = sbrEnvData->hSbrBSGrid->bs_abs_bord_1 - + (bufferFrameStart + numberTimeSlots); + payloadBits += FDKwriteBits(hBitStream, temp, SBR_ABS_BITS); + + payloadBits += FDKwriteBits( + hBitStream, sbrEnvData->hSbrBSGrid->bs_num_rel_0, SBR_NUM_BITS); + payloadBits += FDKwriteBits( + hBitStream, sbrEnvData->hSbrBSGrid->bs_num_rel_1, SBR_NUM_BITS); + + for (i = 0; i < sbrEnvData->hSbrBSGrid->bs_num_rel_0; i++) { + temp = (sbrEnvData->hSbrBSGrid->bs_rel_bord_0[i] - 2) >> 1; + payloadBits += FDKwriteBits(hBitStream, temp, SBR_REL_BITS); + } + + for (i = 0; i < sbrEnvData->hSbrBSGrid->bs_num_rel_1; i++) { + temp = (sbrEnvData->hSbrBSGrid->bs_rel_bord_1[i] - 2) >> 1; + payloadBits += FDKwriteBits(hBitStream, temp, SBR_REL_BITS); + } + + temp = ceil_ln2(sbrEnvData->hSbrBSGrid->bs_num_rel_0 + + sbrEnvData->hSbrBSGrid->bs_num_rel_1 + 2); + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->p, temp); + + temp = sbrEnvData->hSbrBSGrid->bs_num_rel_0 + + sbrEnvData->hSbrBSGrid->bs_num_rel_1 + 1; + + for (i = 0; i < temp; i++) { + payloadBits += FDKwriteBits( + hBitStream, sbrEnvData->hSbrBSGrid->v_fLR[i], SBR_RES_BITS); + } + break; + } + + return payloadBits; +} + +#define SBR_CLA_BITS_LD 1 +/***************************************************************************** + + functionname: encodeLowDelaySbrGrid + description: if hBitStream != NULL writes bits that describes the + time/frequency grouping of a frame; + else counts them only + (this function only write the FIXFIXonly Bitstream data) + returns: number of bits written or counted + input: + output: + +*****************************************************************************/ +static int encodeLowDelaySbrGrid(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, + const int transmitFreqs, + const UINT sbrSyntaxFlags) { + int payloadBits = 0; + int i; + + /* write FIXFIXonly Grid */ + /* write frameClass [1 bit] for FIXFIXonly Grid */ + payloadBits += FDKwriteBits(hBitStream, 1, SBR_CLA_BITS_LD); + + /* absolute Borders are fix: 0,X,X,X,nTimeSlots; so we dont have to transmit + * them */ + /* only transmit the transient position! */ + /* with this info (b1) we can reconstruct the Frame on Decoder side : */ + /* border[0] = 0; border[1] = b1; border[2]=b1+2; border[3] = nrTimeSlots */ + + /* use 3 or 4bits for transient border (border) */ + if (sbrEnvData->hSbrBSGrid->numberTimeSlots == 8) + payloadBits += + FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->bs_abs_bord, 3); + else + payloadBits += + FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->bs_abs_bord, 4); + + if (transmitFreqs) { + /* write FreqRes grid */ + for (i = 0; i < sbrEnvData->hSbrBSGrid->bs_num_env; i++) { + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->v_f[i], + SBR_RES_BITS); + } + } + + return payloadBits; +} + +/***************************************************************************** + + functionname: encodeSbrDtdf + description: writes bits that describes the direction of the envelopes of a +frame returns: number of bits written input: output: + +*****************************************************************************/ +static INT encodeSbrDtdf(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream) { + INT i, payloadBits = 0, noOfNoiseEnvelopes; + + noOfNoiseEnvelopes = sbrEnvData->noOfEnvelopes > 1 ? 2 : 1; + + for (i = 0; i < sbrEnvData->noOfEnvelopes; ++i) { + payloadBits += + FDKwriteBits(hBitStream, sbrEnvData->domain_vec[i], SBR_DIR_BITS); + } + for (i = 0; i < noOfNoiseEnvelopes; ++i) { + payloadBits += + FDKwriteBits(hBitStream, sbrEnvData->domain_vec_noise[i], SBR_DIR_BITS); + } + + return payloadBits; +} + +/***************************************************************************** + + functionname: writeNoiseLevelData + description: writes bits corresponding to the noise-floor-level + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT writeNoiseLevelData(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, INT coupling) { + INT j, i, payloadBits = 0; + INT nNoiseEnvelopes = sbrEnvData->noOfEnvelopes > 1 ? 2 : 1; + + for (i = 0; i < nNoiseEnvelopes; i++) { + switch (sbrEnvData->domain_vec_noise[i]) { + case FREQ: + if (coupling && sbrEnvData->balance) { + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData->sbr_noise_levels[i * sbrEnvData->noOfnoisebands], + sbrEnvData->si_sbr_start_noise_bits_balance); + } else { + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData->sbr_noise_levels[i * sbrEnvData->noOfnoisebands], + sbrEnvData->si_sbr_start_noise_bits); + } + + for (j = 1 + i * sbrEnvData->noOfnoisebands; + j < (sbrEnvData->noOfnoisebands * (1 + i)); j++) { + if (coupling) { + if (sbrEnvData->balance) { + /* coupling && balance */ + payloadBits += FDKwriteBits(hBitStream, + sbrEnvData->hufftableNoiseBalanceFreqC + [sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV_BALANCE11], + sbrEnvData->hufftableNoiseBalanceFreqL + [sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV_BALANCE11]); + } else { + /* coupling && !balance */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData->hufftableNoiseLevelFreqC + [sbrEnvData->sbr_noise_levels[j] + CODE_BOOK_SCF_LAV11], + sbrEnvData->hufftableNoiseLevelFreqL + [sbrEnvData->sbr_noise_levels[j] + CODE_BOOK_SCF_LAV11]); + } + } else { + /* !coupling */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData + ->hufftableNoiseFreqC[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11], + sbrEnvData + ->hufftableNoiseFreqL[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11]); + } + } + break; + + case TIME: + for (j = i * sbrEnvData->noOfnoisebands; + j < (sbrEnvData->noOfnoisebands * (1 + i)); j++) { + if (coupling) { + if (sbrEnvData->balance) { + /* coupling && balance */ + payloadBits += FDKwriteBits(hBitStream, + sbrEnvData->hufftableNoiseBalanceTimeC + [sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV_BALANCE11], + sbrEnvData->hufftableNoiseBalanceTimeL + [sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV_BALANCE11]); + } else { + /* coupling && !balance */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData->hufftableNoiseLevelTimeC + [sbrEnvData->sbr_noise_levels[j] + CODE_BOOK_SCF_LAV11], + sbrEnvData->hufftableNoiseLevelTimeL + [sbrEnvData->sbr_noise_levels[j] + CODE_BOOK_SCF_LAV11]); + } + } else { + /* !coupling */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData + ->hufftableNoiseLevelTimeC[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11], + sbrEnvData + ->hufftableNoiseLevelTimeL[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11]); + } + } + break; + } + } + return payloadBits; +} + +/***************************************************************************** + + functionname: writeEnvelopeData + description: writes bits corresponding to the envelope + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT writeEnvelopeData(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, INT coupling) { + INT payloadBits = 0, j, i, delta; + + for (j = 0; j < sbrEnvData->noOfEnvelopes; + j++) { /* loop over all envelopes */ + if (sbrEnvData->domain_vec[j] == FREQ) { + if (coupling && sbrEnvData->balance) { + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->ienvelope[j][0], + sbrEnvData->si_sbr_start_env_bits_balance); + } else { + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->ienvelope[j][0], + sbrEnvData->si_sbr_start_env_bits); + } + } + + for (i = 1 - sbrEnvData->domain_vec[j]; i < sbrEnvData->noScfBands[j]; + i++) { + delta = sbrEnvData->ienvelope[j][i]; + if (coupling && sbrEnvData->balance) { + FDK_ASSERT(fixp_abs(delta) <= sbrEnvData->codeBookScfLavBalance); + } else { + FDK_ASSERT(fixp_abs(delta) <= sbrEnvData->codeBookScfLav); + } + if (coupling) { + if (sbrEnvData->balance) { + if (sbrEnvData->domain_vec[j]) { + /* coupling && balance && TIME */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData + ->hufftableBalanceTimeC[delta + + sbrEnvData->codeBookScfLavBalance], + sbrEnvData + ->hufftableBalanceTimeL[delta + + sbrEnvData->codeBookScfLavBalance]); + } else { + /* coupling && balance && FREQ */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData + ->hufftableBalanceFreqC[delta + + sbrEnvData->codeBookScfLavBalance], + sbrEnvData + ->hufftableBalanceFreqL[delta + + sbrEnvData->codeBookScfLavBalance]); + } + } else { + if (sbrEnvData->domain_vec[j]) { + /* coupling && !balance && TIME */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData + ->hufftableLevelTimeC[delta + sbrEnvData->codeBookScfLav], + sbrEnvData + ->hufftableLevelTimeL[delta + sbrEnvData->codeBookScfLav]); + } else { + /* coupling && !balance && FREQ */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData + ->hufftableLevelFreqC[delta + sbrEnvData->codeBookScfLav], + sbrEnvData + ->hufftableLevelFreqL[delta + sbrEnvData->codeBookScfLav]); + } + } + } else { + if (sbrEnvData->domain_vec[j]) { + /* !coupling && TIME */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData->hufftableTimeC[delta + sbrEnvData->codeBookScfLav], + sbrEnvData->hufftableTimeL[delta + sbrEnvData->codeBookScfLav]); + } else { + /* !coupling && FREQ */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData->hufftableFreqC[delta + sbrEnvData->codeBookScfLav], + sbrEnvData->hufftableFreqL[delta + sbrEnvData->codeBookScfLav]); + } + } + } + } + return payloadBits; +} + +/***************************************************************************** + + functionname: encodeExtendedData + description: writes bits corresponding to the extended data + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT encodeExtendedData(HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitStream) { + INT extDataSize; + INT payloadBits = 0; + + extDataSize = getSbrExtendedDataSize(hParametricStereo); + + if (extDataSize != 0) { + INT maxExtSize = (1 << SI_SBR_EXTENSION_SIZE_BITS) - 1; + INT writtenNoBits = 0; /* needed to byte align the extended data */ + + payloadBits += FDKwriteBits(hBitStream, 1, SI_SBR_EXTENDED_DATA_BITS); + FDK_ASSERT(extDataSize <= SBR_EXTENDED_DATA_MAX_CNT); + + if (extDataSize < maxExtSize) { + payloadBits += + FDKwriteBits(hBitStream, extDataSize, SI_SBR_EXTENSION_SIZE_BITS); + } else { + payloadBits += + FDKwriteBits(hBitStream, maxExtSize, SI_SBR_EXTENSION_SIZE_BITS); + payloadBits += FDKwriteBits(hBitStream, extDataSize - maxExtSize, + SI_SBR_EXTENSION_ESC_COUNT_BITS); + } + + /* parametric coding signalled here? */ + if (hParametricStereo) { + writtenNoBits += FDKwriteBits(hBitStream, EXTENSION_ID_PS_CODING, + SI_SBR_EXTENSION_ID_BITS); + writtenNoBits += + FDKsbrEnc_PSEnc_WritePSData(hParametricStereo, hBitStream); + } + + payloadBits += writtenNoBits; + + /* byte alignment */ + writtenNoBits = writtenNoBits % 8; + if (writtenNoBits) + payloadBits += FDKwriteBits(hBitStream, 0, (8 - writtenNoBits)); + } else { + payloadBits += FDKwriteBits(hBitStream, 0, SI_SBR_EXTENDED_DATA_BITS); + } + + return payloadBits; +} + +/***************************************************************************** + + functionname: writeSyntheticCodingData + description: writes bits corresponding to the "synthetic-coding"-extension + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT writeSyntheticCodingData(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream) + +{ + INT i; + INT payloadBits = 0; + + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->addHarmonicFlag, 1); + + if (sbrEnvData->addHarmonicFlag) { + for (i = 0; i < sbrEnvData->noHarmonics; i++) { + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->addHarmonic[i], 1); + } + } + + return payloadBits; +} + +/***************************************************************************** + + functionname: getSbrExtendedDataSize + description: counts the number of bits needed for encoding the + extended data (including extension id) + + returns: number of bits needed for the extended data + input: + output: + +*****************************************************************************/ +static INT getSbrExtendedDataSize(HANDLE_PARAMETRIC_STEREO hParametricStereo) { + INT extDataBits = 0; + + /* add your new extended data counting methods here */ + + /* + no extended data + */ + + if (hParametricStereo) { + /* PS extended data */ + extDataBits += SI_SBR_EXTENSION_ID_BITS; + extDataBits += FDKsbrEnc_PSEnc_WritePSData(hParametricStereo, NULL); + } + + return (extDataBits + 7) >> 3; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/bit_sbr.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/bit_sbr.h new file mode 100644 index 0000000000000..e90f52c867ecd --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/bit_sbr.h @@ -0,0 +1,267 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief SBR bit writing $Revision: 92790 $ +*/ +#ifndef BIT_SBR_H +#define BIT_SBR_H + +#include "sbr_def.h" +#include "cmondata.h" +#include "fram_gen.h" + +struct SBR_ENV_DATA; + +struct SBR_BITSTREAM_DATA { + INT TotalBits; + INT PayloadBits; + INT FillBits; + INT HeaderActive; + INT HeaderActiveDelay; /**< sbr payload and its header is delayed depending on + encoder configuration*/ + INT NrSendHeaderData; /**< input from commandline */ + INT CountSendHeaderData; /**< modulo count. If < 0 then no counting is done + (no SBR headers) */ + INT rightBorderFIX; /**< force VARFIX or FIXFIX frames */ +}; + +typedef struct SBR_BITSTREAM_DATA *HANDLE_SBR_BITSTREAM_DATA; + +struct SBR_HEADER_DATA { + AMP_RES sbr_amp_res; + INT sbr_start_frequency; + INT sbr_stop_frequency; + INT sbr_xover_band; + INT sbr_noise_bands; + INT sbr_data_extra; + INT header_extra_1; + INT header_extra_2; + INT sbr_lc_stereo_mode; + INT sbr_limiter_bands; + INT sbr_limiter_gains; + INT sbr_interpol_freq; + INT sbr_smoothing_length; + INT alterScale; + INT freqScale; + + /* + element of channelpairelement + */ + INT coupling; + INT prev_coupling; + + /* + element of singlechannelelement + */ +}; +typedef struct SBR_HEADER_DATA *HANDLE_SBR_HEADER_DATA; + +struct SBR_ENV_DATA { + INT sbr_xpos_ctrl; + FREQ_RES freq_res_fixfix[2]; + UCHAR fResTransIsLow; + + INVF_MODE sbr_invf_mode; + INVF_MODE sbr_invf_mode_vec[MAX_NUM_NOISE_VALUES]; + + XPOS_MODE sbr_xpos_mode; + + INT ienvelope[MAX_ENVELOPES][MAX_FREQ_COEFFS]; + + INT codeBookScfLavBalance; + INT codeBookScfLav; + const INT *hufftableTimeC; + const INT *hufftableFreqC; + const UCHAR *hufftableTimeL; + const UCHAR *hufftableFreqL; + + const INT *hufftableLevelTimeC; + const INT *hufftableBalanceTimeC; + const INT *hufftableLevelFreqC; + const INT *hufftableBalanceFreqC; + const UCHAR *hufftableLevelTimeL; + const UCHAR *hufftableBalanceTimeL; + const UCHAR *hufftableLevelFreqL; + const UCHAR *hufftableBalanceFreqL; + + const UCHAR *hufftableNoiseTimeL; + const INT *hufftableNoiseTimeC; + const UCHAR *hufftableNoiseFreqL; + const INT *hufftableNoiseFreqC; + + const UCHAR *hufftableNoiseLevelTimeL; + const INT *hufftableNoiseLevelTimeC; + const UCHAR *hufftableNoiseBalanceTimeL; + const INT *hufftableNoiseBalanceTimeC; + const UCHAR *hufftableNoiseLevelFreqL; + const INT *hufftableNoiseLevelFreqC; + const UCHAR *hufftableNoiseBalanceFreqL; + const INT *hufftableNoiseBalanceFreqC; + + HANDLE_SBR_GRID hSbrBSGrid; + + INT noHarmonics; + INT addHarmonicFlag; + UCHAR addHarmonic[MAX_FREQ_COEFFS]; + + /* calculated helper vars */ + INT si_sbr_start_env_bits_balance; + INT si_sbr_start_env_bits; + INT si_sbr_start_noise_bits_balance; + INT si_sbr_start_noise_bits; + + INT noOfEnvelopes; + INT noScfBands[MAX_ENVELOPES]; + INT domain_vec[MAX_ENVELOPES]; + INT domain_vec_noise[MAX_ENVELOPES]; + SCHAR sbr_noise_levels[MAX_FREQ_COEFFS]; + INT noOfnoisebands; + + INT balance; + AMP_RES init_sbr_amp_res; + AMP_RES currentAmpResFF; + FIXP_DBL + ton_HF[SBR_GLOBAL_TONALITY_VALUES]; /* tonality is scaled by + 2^19/0.524288f (fract part of + RELAXATION) */ + FIXP_DBL global_tonality; + + /* extended data */ + INT extended_data; + INT extension_size; + INT extension_id; + UCHAR extended_data_buffer[SBR_EXTENDED_DATA_MAX_CNT]; + + UCHAR ldGrid; +}; +typedef struct SBR_ENV_DATA *HANDLE_SBR_ENV_DATA; + +INT FDKsbrEnc_WriteEnvSingleChannelElement( + struct SBR_HEADER_DATA *sbrHeaderData, + struct T_PARAMETRIC_STEREO *hParametricStereo, + struct SBR_BITSTREAM_DATA *sbrBitstreamData, + struct SBR_ENV_DATA *sbrEnvData, struct COMMON_DATA *cmonData, + UINT sbrSyntaxFlags); + +INT FDKsbrEnc_WriteEnvChannelPairElement( + struct SBR_HEADER_DATA *sbrHeaderData, + struct T_PARAMETRIC_STEREO *hParametricStereo, + struct SBR_BITSTREAM_DATA *sbrBitstreamData, + struct SBR_ENV_DATA *sbrEnvDataLeft, struct SBR_ENV_DATA *sbrEnvDataRight, + struct COMMON_DATA *cmonData, UINT sbrSyntaxFlags); + +INT FDKsbrEnc_CountSbrChannelPairElement( + struct SBR_HEADER_DATA *sbrHeaderData, + struct T_PARAMETRIC_STEREO *hParametricStereo, + struct SBR_BITSTREAM_DATA *sbrBitstreamData, + struct SBR_ENV_DATA *sbrEnvDataLeft, struct SBR_ENV_DATA *sbrEnvDataRight, + struct COMMON_DATA *cmonData, UINT sbrSyntaxFlags); + +/* debugging and tuning functions */ + +/*#define SBR_ENV_STATISTICS */ + +/*#define SBR_PAYLOAD_MONITOR*/ + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/cmondata.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/cmondata.h new file mode 100644 index 0000000000000..0779b4df4170a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/cmondata.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Core Coder's and SBR's shared data structure definition $Revision: + 92790 $ +*/ +#ifndef CMONDATA_H +#define CMONDATA_H + +#include "FDK_bitstream.h" + +struct COMMON_DATA { + INT sbrHdrBits; /**< number of SBR header bits */ + INT sbrDataBits; /**< number of SBR data bits */ + INT sbrFillBits; /**< number of SBR fill bits */ + FDK_BITSTREAM sbrBitbuf; /**< the SBR data bitbuffer */ + FDK_BITSTREAM tmpWriteBitbuf; /**< helper var for writing header*/ + INT xOverFreq; /**< the SBR crossover frequency */ + INT dynBwEnabled; /**< indicates if dynamic bandwidth is enabled */ + INT sbrNumChannels; /**< number of channels (meaning mono or stereo) */ + INT dynXOverFreqEnc; /**< encoder dynamic crossover frequency */ +}; + +typedef struct COMMON_DATA *HANDLE_COMMON_DATA; + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/code_env.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/code_env.cpp new file mode 100644 index 0000000000000..fb0f6a459239e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/code_env.cpp @@ -0,0 +1,602 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "code_env.h" +#include "sbrenc_rom.h" + +/***************************************************************************** + + functionname: FDKsbrEnc_InitSbrHuffmanTables + description: initializes Huffman Tables dependent on chosen amp_res + returns: error handle + input: + output: + +*****************************************************************************/ +INT FDKsbrEnc_InitSbrHuffmanTables(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_SBR_CODE_ENVELOPE henv, + HANDLE_SBR_CODE_ENVELOPE hnoise, + AMP_RES amp_res) { + if ((!henv) || (!hnoise) || (!sbrEnvData)) return (1); /* not init. */ + + sbrEnvData->init_sbr_amp_res = amp_res; + + switch (amp_res) { + case SBR_AMP_RES_3_0: + /*envelope data*/ + + /*Level/Pan - coding */ + sbrEnvData->hufftableLevelTimeC = v_Huff_envelopeLevelC11T; + sbrEnvData->hufftableLevelTimeL = v_Huff_envelopeLevelL11T; + sbrEnvData->hufftableBalanceTimeC = bookSbrEnvBalanceC11T; + sbrEnvData->hufftableBalanceTimeL = bookSbrEnvBalanceL11T; + + sbrEnvData->hufftableLevelFreqC = v_Huff_envelopeLevelC11F; + sbrEnvData->hufftableLevelFreqL = v_Huff_envelopeLevelL11F; + sbrEnvData->hufftableBalanceFreqC = bookSbrEnvBalanceC11F; + sbrEnvData->hufftableBalanceFreqL = bookSbrEnvBalanceL11F; + + /*Right/Left - coding */ + sbrEnvData->hufftableTimeC = v_Huff_envelopeLevelC11T; + sbrEnvData->hufftableTimeL = v_Huff_envelopeLevelL11T; + sbrEnvData->hufftableFreqC = v_Huff_envelopeLevelC11F; + sbrEnvData->hufftableFreqL = v_Huff_envelopeLevelL11F; + + sbrEnvData->codeBookScfLavBalance = CODE_BOOK_SCF_LAV_BALANCE11; + sbrEnvData->codeBookScfLav = CODE_BOOK_SCF_LAV11; + + sbrEnvData->si_sbr_start_env_bits = SI_SBR_START_ENV_BITS_AMP_RES_3_0; + sbrEnvData->si_sbr_start_env_bits_balance = + SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_3_0; + break; + + case SBR_AMP_RES_1_5: + /*envelope data*/ + + /*Level/Pan - coding */ + sbrEnvData->hufftableLevelTimeC = v_Huff_envelopeLevelC10T; + sbrEnvData->hufftableLevelTimeL = v_Huff_envelopeLevelL10T; + sbrEnvData->hufftableBalanceTimeC = bookSbrEnvBalanceC10T; + sbrEnvData->hufftableBalanceTimeL = bookSbrEnvBalanceL10T; + + sbrEnvData->hufftableLevelFreqC = v_Huff_envelopeLevelC10F; + sbrEnvData->hufftableLevelFreqL = v_Huff_envelopeLevelL10F; + sbrEnvData->hufftableBalanceFreqC = bookSbrEnvBalanceC10F; + sbrEnvData->hufftableBalanceFreqL = bookSbrEnvBalanceL10F; + + /*Right/Left - coding */ + sbrEnvData->hufftableTimeC = v_Huff_envelopeLevelC10T; + sbrEnvData->hufftableTimeL = v_Huff_envelopeLevelL10T; + sbrEnvData->hufftableFreqC = v_Huff_envelopeLevelC10F; + sbrEnvData->hufftableFreqL = v_Huff_envelopeLevelL10F; + + sbrEnvData->codeBookScfLavBalance = CODE_BOOK_SCF_LAV_BALANCE10; + sbrEnvData->codeBookScfLav = CODE_BOOK_SCF_LAV10; + + sbrEnvData->si_sbr_start_env_bits = SI_SBR_START_ENV_BITS_AMP_RES_1_5; + sbrEnvData->si_sbr_start_env_bits_balance = + SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_1_5; + break; + + default: + return (1); /* undefined amp_res mode */ + } + + /* these are common to both amp_res values */ + /*Noise data*/ + + /*Level/Pan - coding */ + sbrEnvData->hufftableNoiseLevelTimeC = v_Huff_NoiseLevelC11T; + sbrEnvData->hufftableNoiseLevelTimeL = v_Huff_NoiseLevelL11T; + sbrEnvData->hufftableNoiseBalanceTimeC = bookSbrNoiseBalanceC11T; + sbrEnvData->hufftableNoiseBalanceTimeL = bookSbrNoiseBalanceL11T; + + sbrEnvData->hufftableNoiseLevelFreqC = v_Huff_envelopeLevelC11F; + sbrEnvData->hufftableNoiseLevelFreqL = v_Huff_envelopeLevelL11F; + sbrEnvData->hufftableNoiseBalanceFreqC = bookSbrEnvBalanceC11F; + sbrEnvData->hufftableNoiseBalanceFreqL = bookSbrEnvBalanceL11F; + + /*Right/Left - coding */ + sbrEnvData->hufftableNoiseTimeC = v_Huff_NoiseLevelC11T; + sbrEnvData->hufftableNoiseTimeL = v_Huff_NoiseLevelL11T; + sbrEnvData->hufftableNoiseFreqC = v_Huff_envelopeLevelC11F; + sbrEnvData->hufftableNoiseFreqL = v_Huff_envelopeLevelL11F; + + sbrEnvData->si_sbr_start_noise_bits = SI_SBR_START_NOISE_BITS_AMP_RES_3_0; + sbrEnvData->si_sbr_start_noise_bits_balance = + SI_SBR_START_NOISE_BITS_BALANCE_AMP_RES_3_0; + + /* init envelope tables and codebooks */ + henv->codeBookScfLavBalanceTime = sbrEnvData->codeBookScfLavBalance; + henv->codeBookScfLavBalanceFreq = sbrEnvData->codeBookScfLavBalance; + henv->codeBookScfLavLevelTime = sbrEnvData->codeBookScfLav; + henv->codeBookScfLavLevelFreq = sbrEnvData->codeBookScfLav; + henv->codeBookScfLavTime = sbrEnvData->codeBookScfLav; + henv->codeBookScfLavFreq = sbrEnvData->codeBookScfLav; + + henv->hufftableLevelTimeL = sbrEnvData->hufftableLevelTimeL; + henv->hufftableBalanceTimeL = sbrEnvData->hufftableBalanceTimeL; + henv->hufftableTimeL = sbrEnvData->hufftableTimeL; + henv->hufftableLevelFreqL = sbrEnvData->hufftableLevelFreqL; + henv->hufftableBalanceFreqL = sbrEnvData->hufftableBalanceFreqL; + henv->hufftableFreqL = sbrEnvData->hufftableFreqL; + + henv->codeBookScfLavFreq = sbrEnvData->codeBookScfLav; + henv->codeBookScfLavTime = sbrEnvData->codeBookScfLav; + + henv->start_bits = sbrEnvData->si_sbr_start_env_bits; + henv->start_bits_balance = sbrEnvData->si_sbr_start_env_bits_balance; + + /* init noise tables and codebooks */ + + hnoise->codeBookScfLavBalanceTime = CODE_BOOK_SCF_LAV_BALANCE11; + hnoise->codeBookScfLavBalanceFreq = CODE_BOOK_SCF_LAV_BALANCE11; + hnoise->codeBookScfLavLevelTime = CODE_BOOK_SCF_LAV11; + hnoise->codeBookScfLavLevelFreq = CODE_BOOK_SCF_LAV11; + hnoise->codeBookScfLavTime = CODE_BOOK_SCF_LAV11; + hnoise->codeBookScfLavFreq = CODE_BOOK_SCF_LAV11; + + hnoise->hufftableLevelTimeL = sbrEnvData->hufftableNoiseLevelTimeL; + hnoise->hufftableBalanceTimeL = sbrEnvData->hufftableNoiseBalanceTimeL; + hnoise->hufftableTimeL = sbrEnvData->hufftableNoiseTimeL; + hnoise->hufftableLevelFreqL = sbrEnvData->hufftableNoiseLevelFreqL; + hnoise->hufftableBalanceFreqL = sbrEnvData->hufftableNoiseBalanceFreqL; + hnoise->hufftableFreqL = sbrEnvData->hufftableNoiseFreqL; + + hnoise->start_bits = sbrEnvData->si_sbr_start_noise_bits; + hnoise->start_bits_balance = sbrEnvData->si_sbr_start_noise_bits_balance; + + /* No delta coding in time from the previous frame due to 1.5dB FIx-FIX rule + */ + henv->upDate = 0; + hnoise->upDate = 0; + return (0); +} + +/******************************************************************************* + Functionname: indexLow2High + ******************************************************************************* + + Description: Nice small patch-functions in order to cope with non-factor-2 + ratios between high-res and low-res + + Arguments: INT offset, INT index, FREQ_RES res + + Return: INT + +*******************************************************************************/ +static INT indexLow2High(INT offset, INT index, FREQ_RES res) { + if (res == FREQ_RES_LOW) { + if (offset >= 0) { + if (index < offset) + return (index); + else + return (2 * index - offset); + } else { + offset = -offset; + if (index < offset) + return (2 * index + index); + else + return (2 * index + offset); + } + } else + return (index); +} + +/******************************************************************************* + Functionname: mapLowResEnergyVal + ******************************************************************************* + + Description: + + Arguments: INT currVal,INT* prevData, INT offset, INT index, FREQ_RES res + + Return: none + +*******************************************************************************/ +static void mapLowResEnergyVal(SCHAR currVal, SCHAR *prevData, INT offset, + INT index, FREQ_RES res) { + if (res == FREQ_RES_LOW) { + if (offset >= 0) { + if (index < offset) + prevData[index] = currVal; + else { + prevData[2 * index - offset] = currVal; + prevData[2 * index + 1 - offset] = currVal; + } + } else { + offset = -offset; + if (index < offset) { + prevData[3 * index] = currVal; + prevData[3 * index + 1] = currVal; + prevData[3 * index + 2] = currVal; + } else { + prevData[2 * index + offset] = currVal; + prevData[2 * index + 1 + offset] = currVal; + } + } + } else + prevData[index] = currVal; +} + +/******************************************************************************* + Functionname: computeBits + ******************************************************************************* + + Description: + + Arguments: INT delta, + INT codeBookScfLavLevel, + INT codeBookScfLavBalance, + const UCHAR * hufftableLevel, + const UCHAR * hufftableBalance, INT coupling, INT channel) + + Return: INT + +*******************************************************************************/ +static INT computeBits(SCHAR *delta, INT codeBookScfLavLevel, + INT codeBookScfLavBalance, const UCHAR *hufftableLevel, + const UCHAR *hufftableBalance, INT coupling, + INT channel) { + INT index; + INT delta_bits = 0; + + if (coupling) { + if (channel == 1) { + if (*delta < 0) + index = fixMax(*delta, -codeBookScfLavBalance); + else + index = fixMin(*delta, codeBookScfLavBalance); + + if (index != *delta) { + *delta = index; + return (10000); + } + + delta_bits = hufftableBalance[index + codeBookScfLavBalance]; + } else { + if (*delta < 0) + index = fixMax(*delta, -codeBookScfLavLevel); + else + index = fixMin(*delta, codeBookScfLavLevel); + + if (index != *delta) { + *delta = index; + return (10000); + } + delta_bits = hufftableLevel[index + codeBookScfLavLevel]; + } + } else { + if (*delta < 0) + index = fixMax(*delta, -codeBookScfLavLevel); + else + index = fixMin(*delta, codeBookScfLavLevel); + + if (index != *delta) { + *delta = index; + return (10000); + } + delta_bits = hufftableLevel[index + codeBookScfLavLevel]; + } + + return (delta_bits); +} + +/******************************************************************************* + Functionname: FDKsbrEnc_codeEnvelope + ******************************************************************************* + + Description: + + Arguments: INT *sfb_nrg, + const FREQ_RES *freq_res, + SBR_CODE_ENVELOPE * h_sbrCodeEnvelope, + INT *directionVec, INT scalable, INT nEnvelopes, INT channel, + INT headerActive) + + Return: none + h_sbrCodeEnvelope->sfb_nrg_prev is modified ! + sfb_nrg is modified + h_sbrCodeEnvelope->update is modfied ! + *directionVec is modified + +*******************************************************************************/ +void FDKsbrEnc_codeEnvelope(SCHAR *sfb_nrg, const FREQ_RES *freq_res, + SBR_CODE_ENVELOPE *h_sbrCodeEnvelope, + INT *directionVec, INT coupling, INT nEnvelopes, + INT channel, INT headerActive) { + INT i, no_of_bands, band; + FIXP_DBL tmp1, tmp2, tmp3, dF_edge_1stEnv; + SCHAR *ptr_nrg; + + INT codeBookScfLavLevelTime; + INT codeBookScfLavLevelFreq; + INT codeBookScfLavBalanceTime; + INT codeBookScfLavBalanceFreq; + const UCHAR *hufftableLevelTimeL; + const UCHAR *hufftableBalanceTimeL; + const UCHAR *hufftableLevelFreqL; + const UCHAR *hufftableBalanceFreqL; + + INT offset = h_sbrCodeEnvelope->offset; + INT envDataTableCompFactor; + + INT delta_F_bits = 0, delta_T_bits = 0; + INT use_dT; + + SCHAR delta_F[MAX_FREQ_COEFFS]; + SCHAR delta_T[MAX_FREQ_COEFFS]; + SCHAR last_nrg, curr_nrg; + + tmp1 = FL2FXCONST_DBL(0.5f) >> (DFRACT_BITS - 16 - 1); + tmp2 = h_sbrCodeEnvelope->dF_edge_1stEnv >> (DFRACT_BITS - 16); + tmp3 = (FIXP_DBL)fMult(h_sbrCodeEnvelope->dF_edge_incr, + ((FIXP_DBL)h_sbrCodeEnvelope->dF_edge_incr_fac) << 15); + + dF_edge_1stEnv = tmp1 + tmp2 + tmp3; + + if (coupling) { + codeBookScfLavLevelTime = h_sbrCodeEnvelope->codeBookScfLavLevelTime; + codeBookScfLavLevelFreq = h_sbrCodeEnvelope->codeBookScfLavLevelFreq; + codeBookScfLavBalanceTime = h_sbrCodeEnvelope->codeBookScfLavBalanceTime; + codeBookScfLavBalanceFreq = h_sbrCodeEnvelope->codeBookScfLavBalanceFreq; + hufftableLevelTimeL = h_sbrCodeEnvelope->hufftableLevelTimeL; + hufftableBalanceTimeL = h_sbrCodeEnvelope->hufftableBalanceTimeL; + hufftableLevelFreqL = h_sbrCodeEnvelope->hufftableLevelFreqL; + hufftableBalanceFreqL = h_sbrCodeEnvelope->hufftableBalanceFreqL; + } else { + codeBookScfLavLevelTime = h_sbrCodeEnvelope->codeBookScfLavTime; + codeBookScfLavLevelFreq = h_sbrCodeEnvelope->codeBookScfLavFreq; + codeBookScfLavBalanceTime = h_sbrCodeEnvelope->codeBookScfLavTime; + codeBookScfLavBalanceFreq = h_sbrCodeEnvelope->codeBookScfLavFreq; + hufftableLevelTimeL = h_sbrCodeEnvelope->hufftableTimeL; + hufftableBalanceTimeL = h_sbrCodeEnvelope->hufftableTimeL; + hufftableLevelFreqL = h_sbrCodeEnvelope->hufftableFreqL; + hufftableBalanceFreqL = h_sbrCodeEnvelope->hufftableFreqL; + } + + if (coupling == 1 && channel == 1) + envDataTableCompFactor = + 1; /*should be one when the new huffman-tables are ready*/ + else + envDataTableCompFactor = 0; + + if (h_sbrCodeEnvelope->deltaTAcrossFrames == 0) h_sbrCodeEnvelope->upDate = 0; + + /* no delta coding in time in case of a header */ + if (headerActive) h_sbrCodeEnvelope->upDate = 0; + + for (i = 0; i < nEnvelopes; i++) { + if (freq_res[i] == FREQ_RES_HIGH) + no_of_bands = h_sbrCodeEnvelope->nSfb[FREQ_RES_HIGH]; + else + no_of_bands = h_sbrCodeEnvelope->nSfb[FREQ_RES_LOW]; + + ptr_nrg = sfb_nrg; + curr_nrg = *ptr_nrg; + + delta_F[0] = curr_nrg >> envDataTableCompFactor; + + if (coupling && channel == 1) + delta_F_bits = h_sbrCodeEnvelope->start_bits_balance; + else + delta_F_bits = h_sbrCodeEnvelope->start_bits; + + if (h_sbrCodeEnvelope->upDate != 0) { + delta_T[0] = (curr_nrg - h_sbrCodeEnvelope->sfb_nrg_prev[0]) >> + envDataTableCompFactor; + + delta_T_bits = computeBits(&delta_T[0], codeBookScfLavLevelTime, + codeBookScfLavBalanceTime, hufftableLevelTimeL, + hufftableBalanceTimeL, coupling, channel); + } + + mapLowResEnergyVal(curr_nrg, h_sbrCodeEnvelope->sfb_nrg_prev, offset, 0, + freq_res[i]); + + /* ensure that nrg difference is not higher than codeBookScfLavXXXFreq */ + if (coupling && channel == 1) { + for (band = no_of_bands - 1; band > 0; band--) { + if (ptr_nrg[band] - ptr_nrg[band - 1] > codeBookScfLavBalanceFreq) { + ptr_nrg[band - 1] = ptr_nrg[band] - codeBookScfLavBalanceFreq; + } + } + for (band = 1; band < no_of_bands; band++) { + if (ptr_nrg[band - 1] - ptr_nrg[band] > codeBookScfLavBalanceFreq) { + ptr_nrg[band] = ptr_nrg[band - 1] - codeBookScfLavBalanceFreq; + } + } + } else { + for (band = no_of_bands - 1; band > 0; band--) { + if (ptr_nrg[band] - ptr_nrg[band - 1] > codeBookScfLavLevelFreq) { + ptr_nrg[band - 1] = ptr_nrg[band] - codeBookScfLavLevelFreq; + } + } + for (band = 1; band < no_of_bands; band++) { + if (ptr_nrg[band - 1] - ptr_nrg[band] > codeBookScfLavLevelFreq) { + ptr_nrg[band] = ptr_nrg[band - 1] - codeBookScfLavLevelFreq; + } + } + } + + /* Coding loop*/ + for (band = 1; band < no_of_bands; band++) { + last_nrg = (*ptr_nrg); + ptr_nrg++; + curr_nrg = (*ptr_nrg); + + delta_F[band] = (curr_nrg - last_nrg) >> envDataTableCompFactor; + + delta_F_bits += computeBits( + &delta_F[band], codeBookScfLavLevelFreq, codeBookScfLavBalanceFreq, + hufftableLevelFreqL, hufftableBalanceFreqL, coupling, channel); + + if (h_sbrCodeEnvelope->upDate != 0) { + delta_T[band] = + curr_nrg - + h_sbrCodeEnvelope + ->sfb_nrg_prev[indexLow2High(offset, band, freq_res[i])]; + delta_T[band] = delta_T[band] >> envDataTableCompFactor; + } + + mapLowResEnergyVal(curr_nrg, h_sbrCodeEnvelope->sfb_nrg_prev, offset, + band, freq_res[i]); + + if (h_sbrCodeEnvelope->upDate != 0) { + delta_T_bits += computeBits( + &delta_T[band], codeBookScfLavLevelTime, codeBookScfLavBalanceTime, + hufftableLevelTimeL, hufftableBalanceTimeL, coupling, channel); + } + } + + /* Replace sfb_nrg with deltacoded samples and set flag */ + if (i == 0) { + INT tmp_bits; + tmp_bits = (((delta_T_bits * dF_edge_1stEnv) >> (DFRACT_BITS - 18)) + + (FIXP_DBL)1) >> + 1; + use_dT = (h_sbrCodeEnvelope->upDate != 0 && (delta_F_bits > tmp_bits)); + } else + use_dT = (delta_T_bits < delta_F_bits && h_sbrCodeEnvelope->upDate != 0); + + if (use_dT) { + directionVec[i] = TIME; + FDKmemcpy(sfb_nrg, delta_T, no_of_bands * sizeof(SCHAR)); + } else { + h_sbrCodeEnvelope->upDate = 0; + directionVec[i] = FREQ; + FDKmemcpy(sfb_nrg, delta_F, no_of_bands * sizeof(SCHAR)); + } + sfb_nrg += no_of_bands; + h_sbrCodeEnvelope->upDate = 1; + } +} + +/******************************************************************************* + Functionname: FDKsbrEnc_InitSbrCodeEnvelope + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +INT FDKsbrEnc_InitSbrCodeEnvelope(HANDLE_SBR_CODE_ENVELOPE h_sbrCodeEnvelope, + INT *nSfb, INT deltaTAcrossFrames, + FIXP_DBL dF_edge_1stEnv, + FIXP_DBL dF_edge_incr) { + FDKmemclear(h_sbrCodeEnvelope, sizeof(SBR_CODE_ENVELOPE)); + + h_sbrCodeEnvelope->deltaTAcrossFrames = deltaTAcrossFrames; + h_sbrCodeEnvelope->dF_edge_1stEnv = dF_edge_1stEnv; + h_sbrCodeEnvelope->dF_edge_incr = dF_edge_incr; + h_sbrCodeEnvelope->dF_edge_incr_fac = 0; + h_sbrCodeEnvelope->upDate = 0; + h_sbrCodeEnvelope->nSfb[FREQ_RES_LOW] = nSfb[FREQ_RES_LOW]; + h_sbrCodeEnvelope->nSfb[FREQ_RES_HIGH] = nSfb[FREQ_RES_HIGH]; + h_sbrCodeEnvelope->offset = 2 * h_sbrCodeEnvelope->nSfb[FREQ_RES_LOW] - + h_sbrCodeEnvelope->nSfb[FREQ_RES_HIGH]; + + return (0); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/code_env.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/code_env.h new file mode 100644 index 0000000000000..673a783bb3867 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/code_env.h @@ -0,0 +1,161 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief DPCM Envelope coding $Revision: 92790 $ +*/ + +#ifndef CODE_ENV_H +#define CODE_ENV_H + +#include "sbr_def.h" +#include "bit_sbr.h" +#include "fram_gen.h" + +typedef struct { + INT offset; + INT upDate; + INT nSfb[2]; + SCHAR sfb_nrg_prev[MAX_FREQ_COEFFS]; + INT deltaTAcrossFrames; + FIXP_DBL dF_edge_1stEnv; + FIXP_DBL dF_edge_incr; + INT dF_edge_incr_fac; + + INT codeBookScfLavTime; + INT codeBookScfLavFreq; + + INT codeBookScfLavLevelTime; + INT codeBookScfLavLevelFreq; + INT codeBookScfLavBalanceTime; + INT codeBookScfLavBalanceFreq; + + INT start_bits; + INT start_bits_balance; + + const UCHAR *hufftableTimeL; + const UCHAR *hufftableFreqL; + + const UCHAR *hufftableLevelTimeL; + const UCHAR *hufftableBalanceTimeL; + const UCHAR *hufftableLevelFreqL; + const UCHAR *hufftableBalanceFreqL; +} SBR_CODE_ENVELOPE; +typedef SBR_CODE_ENVELOPE *HANDLE_SBR_CODE_ENVELOPE; + +void FDKsbrEnc_codeEnvelope(SCHAR *sfb_nrg, const FREQ_RES *freq_res, + SBR_CODE_ENVELOPE *h_sbrCodeEnvelope, + INT *directionVec, INT coupling, INT nEnvelopes, + INT channel, INT headerActive); + +INT FDKsbrEnc_InitSbrCodeEnvelope(HANDLE_SBR_CODE_ENVELOPE h_sbrCodeEnvelope, + INT *nSfb, INT deltaTAcrossFrames, + FIXP_DBL dF_edge_1stEnv, + FIXP_DBL dF_edge_incr); + +INT FDKsbrEnc_InitSbrHuffmanTables(struct SBR_ENV_DATA *sbrEnvData, + HANDLE_SBR_CODE_ENVELOPE henv, + HANDLE_SBR_CODE_ENVELOPE hnoise, + AMP_RES amp_res); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_bit.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_bit.cpp new file mode 100644 index 0000000000000..41812acb5b240 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_bit.cpp @@ -0,0 +1,257 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Remaining SBR Bit Writing Routines +*/ + +#include "env_bit.h" +#include "cmondata.h" + +#ifndef min +#define min(a, b) (a < b ? a : b) +#endif + +#ifndef max +#define max(a, b) (a > b ? a : b) +#endif + +/* ***************************** crcAdvance **********************************/ +/** + * @fn + * @brief updates crc data register + * @return none + * + * This function updates the crc register + * + */ +static void crcAdvance(USHORT crcPoly, USHORT crcMask, USHORT *crc, + ULONG bValue, INT bBits) { + INT i; + USHORT flag; + + for (i = bBits - 1; i >= 0; i--) { + flag = ((*crc) & crcMask) ? (1) : (0); + flag ^= (bValue & (1 << i)) ? (1) : (0); + + (*crc) <<= 1; + if (flag) (*crc) ^= crcPoly; + } +} + +/* ***************************** FDKsbrEnc_InitSbrBitstream + * **********************************/ +/** + * @fn + * @brief Inittialisation of sbr bitstream, write of dummy header and CRC + * @return none + * + * + * + */ + +INT FDKsbrEnc_InitSbrBitstream( + HANDLE_COMMON_DATA hCmonData, + UCHAR *memoryBase, /*!< Pointer to bitstream buffer */ + INT memorySize, /*!< Length of bitstream buffer in bytes */ + HANDLE_FDK_CRCINFO hCrcInfo, UINT sbrSyntaxFlags) /*!< SBR syntax flags */ +{ + INT crcRegion = 0; + + /* reset bit buffer */ + FDKresetBitbuffer(&hCmonData->sbrBitbuf, BS_WRITER); + + FDKinitBitStream(&hCmonData->tmpWriteBitbuf, memoryBase, memorySize, 0, + BS_WRITER); + + if (sbrSyntaxFlags & SBR_SYNTAX_CRC) { + if (sbrSyntaxFlags & SBR_SYNTAX_DRM_CRC) { /* Init and start CRC region */ + FDKwriteBits(&hCmonData->sbrBitbuf, 0x0, SI_SBR_DRM_CRC_BITS); + FDKcrcInit(hCrcInfo, 0x001d, 0xFFFF, SI_SBR_DRM_CRC_BITS); + crcRegion = FDKcrcStartReg(hCrcInfo, &hCmonData->sbrBitbuf, 0); + } else { + FDKwriteBits(&hCmonData->sbrBitbuf, 0x0, SI_SBR_CRC_BITS); + } + } + + return (crcRegion); +} + +/* ************************** FDKsbrEnc_AssembleSbrBitstream + * *******************************/ +/** + * @fn + * @brief Formats the SBR payload + * @return nothing + * + * Also the CRC will be calculated here. + * + */ + +void FDKsbrEnc_AssembleSbrBitstream(HANDLE_COMMON_DATA hCmonData, + HANDLE_FDK_CRCINFO hCrcInfo, INT crcRegion, + UINT sbrSyntaxFlags) { + USHORT crcReg = SBR_CRCINIT; + INT numCrcBits, i; + + /* check if SBR is present */ + if (hCmonData == NULL) return; + + hCmonData->sbrFillBits = 0; /* Fill bits are written only for GA streams */ + + if (sbrSyntaxFlags & SBR_SYNTAX_DRM_CRC) { + /* + * Calculate and write DRM CRC + */ + FDKcrcEndReg(hCrcInfo, &hCmonData->sbrBitbuf, crcRegion); + FDKwriteBits(&hCmonData->tmpWriteBitbuf, FDKcrcGetCRC(hCrcInfo) ^ 0xFF, + SI_SBR_DRM_CRC_BITS); + } else { + if (!(sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)) { + /* Do alignment here, because its defined as part of the + * sbr_extension_data */ + int sbrLoad = hCmonData->sbrHdrBits + hCmonData->sbrDataBits; + + if (sbrSyntaxFlags & SBR_SYNTAX_CRC) { + sbrLoad += SI_SBR_CRC_BITS; + } + + sbrLoad += 4; /* Do byte Align with 4 bit offset. ISO/IEC 14496-3:2005(E) + page 39. */ + + hCmonData->sbrFillBits = (8 - (sbrLoad % 8)) % 8; + + /* + append fill bits + */ + FDKwriteBits(&hCmonData->sbrBitbuf, 0, hCmonData->sbrFillBits); + + FDK_ASSERT(FDKgetValidBits(&hCmonData->sbrBitbuf) % 8 == 4); + } + + /* + calculate crc + */ + if (sbrSyntaxFlags & SBR_SYNTAX_CRC) { + FDK_BITSTREAM tmpCRCBuf = hCmonData->sbrBitbuf; + FDKresetBitbuffer(&tmpCRCBuf, BS_READER); + + numCrcBits = hCmonData->sbrHdrBits + hCmonData->sbrDataBits + + hCmonData->sbrFillBits; + + for (i = 0; i < numCrcBits; i++) { + INT bit; + bit = FDKreadBits(&tmpCRCBuf, 1); + crcAdvance(SBR_CRC_POLY, SBR_CRC_MASK, &crcReg, bit, 1); + } + crcReg &= (SBR_CRC_RANGE); + + /* + * Write CRC data. + */ + FDKwriteBits(&hCmonData->tmpWriteBitbuf, crcReg, SI_SBR_CRC_BITS); + } + } + + FDKsyncCache(&hCmonData->tmpWriteBitbuf); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_bit.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_bit.h new file mode 100644 index 0000000000000..b91802cb7aa05 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_bit.h @@ -0,0 +1,135 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Remaining SBR Bit Writing Routines +*/ + +#ifndef ENV_BIT_H +#define ENV_BIT_H + +#include "sbr_encoder.h" +#include "FDK_crc.h" + +/* G(x) = x^10 + x^9 + x^5 + x^4 + x + 1 */ +#define SBR_CRC_POLY (0x0233) +#define SBR_CRC_MASK (0x0200) +#define SBR_CRC_RANGE (0x03FF) +#define SBR_CRC_MAXREGS 1 +#define SBR_CRCINIT (0x0) + +#define SI_SBR_CRC_ENABLE_BITS 0 +#define SI_SBR_CRC_BITS 10 +#define SI_SBR_DRM_CRC_BITS 8 + +struct COMMON_DATA; + +INT FDKsbrEnc_InitSbrBitstream(struct COMMON_DATA *hCmonData, UCHAR *memoryBase, + INT memorySize, HANDLE_FDK_CRCINFO hCrcInfo, + UINT sbrSyntaxFlags); + +void FDKsbrEnc_AssembleSbrBitstream(struct COMMON_DATA *hCmonData, + HANDLE_FDK_CRCINFO hCrcInfo, INT crcRegion, + UINT sbrSyntaxFlags); + +#endif /* #ifndef ENV_BIT_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_est.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_est.cpp new file mode 100644 index 0000000000000..e7eea37950c2b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_est.cpp @@ -0,0 +1,1993 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "env_est.h" +#include "tran_det.h" + +#include "qmf.h" + +#include "fram_gen.h" +#include "bit_sbr.h" +#include "cmondata.h" +#include "sbrenc_ram.h" + +#include "genericStds.h" + +#define QUANT_ERROR_THRES 200 +#define Y_NRG_SCALE 5 /* noCols = 32 -> shift(5) */ +#define MAX_NRG_SLOTS_LD 16 + +static const UCHAR panTable[2][10] = {{0, 2, 4, 6, 8, 12, 16, 20, 24}, + {0, 2, 4, 8, 12, 0, 0, 0, 0}}; +static const UCHAR maxIndex[2] = {9, 5}; + +/****************************************************************************** + Functionname: FDKsbrEnc_GetTonality +******************************************************************************/ +/***************************************************************************/ +/*! + + \brief Calculates complete energy per band from the energy values + of the QMF subsamples. + + \brief quotaMatrix - calculated in FDKsbrEnc_CalculateTonalityQuotas() + \brief noEstPerFrame - number of estimations per frame + \brief startIndex - start index for the quota matrix + \brief Energies - energy matrix + \brief startBand - start band + \brief stopBand - number of QMF bands + \brief numberCols - number of QMF subsamples + + \return mean tonality of the 5 bands with the highest energy + scaled by 2^(RELAXATION_SHIFT+2)*RELAXATION_FRACT + +****************************************************************************/ +static FIXP_DBL FDKsbrEnc_GetTonality(const FIXP_DBL *const *quotaMatrix, + const INT noEstPerFrame, + const INT startIndex, + const FIXP_DBL *const *Energies, + const UCHAR startBand, const INT stopBand, + const INT numberCols) { + UCHAR b, e, k; + INT no_enMaxBand[SBR_MAX_ENERGY_VALUES] = {-1, -1, -1, -1, -1}; + FIXP_DBL energyMax[SBR_MAX_ENERGY_VALUES] = { + FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), + FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f)}; + FIXP_DBL energyMaxMin = MAXVAL_DBL; /* min. energy in energyMax array */ + UCHAR posEnergyMaxMin = 0; /* min. energy in energyMax array position */ + FIXP_DBL tonalityBand[SBR_MAX_ENERGY_VALUES] = { + FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), + FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f)}; + FIXP_DBL globalTonality = FL2FXCONST_DBL(0.0f); + FIXP_DBL energyBand[64]; + INT maxNEnergyValues; /* max. number of max. energy values */ + + /*** Sum up energies for each band ***/ + FDK_ASSERT(numberCols == 15 || numberCols == 16); + /* numberCols is always 15 or 16 for ELD. In case of 16 bands, the + energyBands are initialized with the [15]th column. + The rest of the column energies are added in the next step. */ + if (numberCols == 15) { + for (b = startBand; b < stopBand; b++) { + energyBand[b] = FL2FXCONST_DBL(0.0f); + } + } else { + for (b = startBand; b < stopBand; b++) { + energyBand[b] = Energies[15][b] >> 4; + } + } + + for (k = 0; k < 15; k++) { + for (b = startBand; b < stopBand; b++) { + energyBand[b] += Energies[k][b] >> 4; + } + } + + /*** Determine 5 highest band-energies ***/ + maxNEnergyValues = fMin(SBR_MAX_ENERGY_VALUES, stopBand - startBand); + + /* Get min. value in energyMax array */ + energyMaxMin = energyMax[0] = energyBand[startBand]; + no_enMaxBand[0] = startBand; + posEnergyMaxMin = 0; + for (k = 1; k < maxNEnergyValues; k++) { + energyMax[k] = energyBand[startBand + k]; + no_enMaxBand[k] = startBand + k; + if (energyMaxMin > energyMax[k]) { + energyMaxMin = energyMax[k]; + posEnergyMaxMin = k; + } + } + + for (b = startBand + maxNEnergyValues; b < stopBand; b++) { + if (energyBand[b] > energyMaxMin) { + energyMax[posEnergyMaxMin] = energyBand[b]; + no_enMaxBand[posEnergyMaxMin] = b; + + /* Again, get min. value in energyMax array */ + energyMaxMin = energyMax[0]; + posEnergyMaxMin = 0; + for (k = 1; k < maxNEnergyValues; k++) { + if (energyMaxMin > energyMax[k]) { + energyMaxMin = energyMax[k]; + posEnergyMaxMin = k; + } + } + } + } + /*** End determine 5 highest band-energies ***/ + + /* Get tonality values for 5 highest energies */ + for (e = 0; e < maxNEnergyValues; e++) { + tonalityBand[e] = FL2FXCONST_DBL(0.0f); + for (k = 0; k < noEstPerFrame; k++) { + tonalityBand[e] += quotaMatrix[startIndex + k][no_enMaxBand[e]] >> 1; + } + globalTonality += + tonalityBand[e] >> 2; /* headroom of 2+1 (max. 5 additions) */ + } + + return globalTonality; +} + +/***************************************************************************/ +/*! + + \brief Calculates energy form real and imaginary part of + the QMF subsamples + + \return none + +****************************************************************************/ +LNK_SECTION_CODE_L1 +static void FDKsbrEnc_getEnergyFromCplxQmfData( + FIXP_DBL **RESTRICT energyValues, /*!< the result of the operation */ + FIXP_DBL **RESTRICT realValues, /*!< the real part of the QMF subsamples */ + FIXP_DBL **RESTRICT + imagValues, /*!< the imaginary part of the QMF subsamples */ + INT numberBands, /*!< number of QMF bands */ + INT numberCols, /*!< number of QMF subsamples */ + INT *qmfScale, /*!< sclefactor of QMF subsamples */ + INT *energyScale) /*!< scalefactor of energies */ +{ + int j, k; + int scale; + FIXP_DBL max_val = FL2FXCONST_DBL(0.0f); + + /* Get Scratch buffer */ + C_ALLOC_SCRATCH_START(tmpNrg, FIXP_DBL, 32 * 64 / 2) + + /* Get max possible scaling of QMF data */ + scale = DFRACT_BITS; + for (k = 0; k < numberCols; k++) { + scale = fixMin(scale, fixMin(getScalefactor(realValues[k], numberBands), + getScalefactor(imagValues[k], numberBands))); + } + + /* Tweak scaling stability for zero signal to non-zero signal transitions */ + if (scale >= DFRACT_BITS - 1) { + scale = (FRACT_BITS - 1 - *qmfScale); + } + /* prevent scaling of QMF values to -1.f */ + scale = fixMax(0, scale - 1); + + /* Update QMF scale */ + *qmfScale += scale; + + /* + Calculate energy of each time slot pair, max energy + and shift QMF values as far as possible to the left. + */ + { + FIXP_DBL *nrgValues = tmpNrg; + for (k = 0; k < numberCols; k += 2) { + /* Load band vector addresses of 2 consecutive timeslots */ + FIXP_DBL *RESTRICT r0 = realValues[k]; + FIXP_DBL *RESTRICT i0 = imagValues[k]; + FIXP_DBL *RESTRICT r1 = realValues[k + 1]; + FIXP_DBL *RESTRICT i1 = imagValues[k + 1]; + for (j = 0; j < numberBands; j++) { + FIXP_DBL energy; + FIXP_DBL tr0, tr1, ti0, ti1; + + /* Read QMF values of 2 timeslots */ + tr0 = r0[j]; + tr1 = r1[j]; + ti0 = i0[j]; + ti1 = i1[j]; + + /* Scale QMF Values and Calc Energy average of both timeslots */ + tr0 <<= scale; + ti0 <<= scale; + energy = fPow2AddDiv2(fPow2Div2(tr0), ti0) >> 1; + + tr1 <<= scale; + ti1 <<= scale; + energy += fPow2AddDiv2(fPow2Div2(tr1), ti1) >> 1; + + /* Write timeslot pair energy to scratch */ + *nrgValues++ = energy; + max_val = fixMax(max_val, energy); + + /* Write back scaled QMF values */ + r0[j] = tr0; + r1[j] = tr1; + i0[j] = ti0; + i1[j] = ti1; + } + } + } + /* energyScale: scalefactor energies of current frame */ + *energyScale = + 2 * (*qmfScale) - + 1; /* if qmfScale > 0: nr of right shifts otherwise nr of left shifts */ + + /* Scale timeslot pair energies and write to output buffer */ + scale = CountLeadingBits(max_val); + { + FIXP_DBL *nrgValues = tmpNrg; + for (k = 0; k> 1; k++) { + scaleValues(energyValues[k], nrgValues, numberBands, scale); + nrgValues += numberBands; + } + *energyScale += scale; + } + + /* Free Scratch buffer */ + C_ALLOC_SCRATCH_END(tmpNrg, FIXP_DBL, 32 * 64 / 2) +} + +LNK_SECTION_CODE_L1 +static void FDKsbrEnc_getEnergyFromCplxQmfDataFull( + FIXP_DBL **RESTRICT energyValues, /*!< the result of the operation */ + FIXP_DBL **RESTRICT realValues, /*!< the real part of the QMF subsamples */ + FIXP_DBL **RESTRICT + imagValues, /*!< the imaginary part of the QMF subsamples */ + int numberBands, /*!< number of QMF bands */ + int numberCols, /*!< number of QMF subsamples */ + int *qmfScale, /*!< scalefactor of QMF subsamples */ + int *energyScale) /*!< scalefactor of energies */ +{ + int j, k; + int scale; + FIXP_DBL max_val = FL2FXCONST_DBL(0.0f); + + /* Get Scratch buffer */ + C_ALLOC_SCRATCH_START(tmpNrg, FIXP_DBL, MAX_NRG_SLOTS_LD * 64) + + FDK_ASSERT(numberCols <= MAX_NRG_SLOTS_LD); + FDK_ASSERT(numberBands <= 64); + + /* Get max possible scaling of QMF data */ + scale = DFRACT_BITS; + for (k = 0; k < numberCols; k++) { + scale = fixMin(scale, fixMin(getScalefactor(realValues[k], numberBands), + getScalefactor(imagValues[k], numberBands))); + } + + /* Tweak scaling stability for zero signal to non-zero signal transitions */ + if (scale >= DFRACT_BITS - 1) { + scale = (FRACT_BITS - 1 - *qmfScale); + } + /* prevent scaling of QFM values to -1.f */ + scale = fixMax(0, scale - 1); + + /* Update QMF scale */ + *qmfScale += scale; + + /* + Calculate energy of each time slot pair, max energy + and shift QMF values as far as possible to the left. + */ + { + FIXP_DBL *nrgValues = tmpNrg; + for (k = 0; k < numberCols; k++) { + /* Load band vector addresses of 1 timeslot */ + FIXP_DBL *RESTRICT r0 = realValues[k]; + FIXP_DBL *RESTRICT i0 = imagValues[k]; + for (j = 0; j < numberBands; j++) { + FIXP_DBL energy; + FIXP_DBL tr0, ti0; + + /* Read QMF values of 1 timeslot */ + tr0 = r0[j]; + ti0 = i0[j]; + + /* Scale QMF Values and Calc Energy */ + tr0 <<= scale; + ti0 <<= scale; + energy = fPow2AddDiv2(fPow2Div2(tr0), ti0); + *nrgValues++ = energy; + + max_val = fixMax(max_val, energy); + + /* Write back scaled QMF values */ + r0[j] = tr0; + i0[j] = ti0; + } + } + } + /* energyScale: scalefactor energies of current frame */ + *energyScale = + 2 * (*qmfScale) - + 1; /* if qmfScale > 0: nr of right shifts otherwise nr of left shifts */ + + /* Scale timeslot pair energies and write to output buffer */ + scale = CountLeadingBits(max_val); + { + FIXP_DBL *nrgValues = tmpNrg; + for (k = 0; k < numberCols; k++) { + scaleValues(energyValues[k], nrgValues, numberBands, scale); + nrgValues += numberBands; + } + *energyScale += scale; + } + + /* Free Scratch buffer */ + C_ALLOC_SCRATCH_END(tmpNrg, FIXP_DBL, MAX_NRG_SLOTS_LD * 64) +} + +/***************************************************************************/ +/*! + + \brief Quantisation of the panorama value (balance) + + \return the quantized pan value + +****************************************************************************/ +static INT mapPanorama(INT nrgVal, /*! integer value of the energy */ + INT ampRes, /*! amplitude resolution [1.5/3dB] */ + INT *quantError /*! quantization error of energy val*/ +) { + int i; + INT min_val, val; + UCHAR panIndex; + INT sign; + + sign = nrgVal > 0 ? 1 : -1; + + nrgVal *= sign; + + min_val = FDK_INT_MAX; + panIndex = 0; + for (i = 0; i < maxIndex[ampRes]; i++) { + val = fixp_abs((nrgVal - (INT)panTable[ampRes][i])); + + if (val < min_val) { + min_val = val; + panIndex = i; + } + } + + *quantError = min_val; + + return panTable[ampRes][maxIndex[ampRes] - 1] + + sign * panTable[ampRes][panIndex]; +} + +/***************************************************************************/ +/*! + + \brief Quantisation of the noise floor levels + + \return void + +****************************************************************************/ +static void sbrNoiseFloorLevelsQuantisation( + SCHAR *RESTRICT iNoiseLevels, /*! quantized noise levels */ + FIXP_DBL *RESTRICT + NoiseLevels, /*! the noise levels. Exponent = LD_DATA_SHIFT */ + INT coupling /*! the coupling flag */ +) { + INT i; + INT tmp, dummy; + + /* Quantisation, similar to sfb quant... */ + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) { + /* tmp = NoiseLevels[i] > (PFLOAT)30.0f ? 30: (INT) (NoiseLevels[i] + + * (PFLOAT)0.5); */ + /* 30>>LD_DATA_SHIFT = 0.46875 */ + if ((FIXP_DBL)NoiseLevels[i] > FL2FXCONST_DBL(0.46875f)) { + tmp = 30; + } else { + /* tmp = (INT)((FIXP_DBL)NoiseLevels[i] + (FL2FXCONST_DBL(0.5f)>>(*/ + /* FRACT_BITS+ */ /* 6-1)));*/ + /* tmp = tmp >> (DFRACT_BITS-1-LD_DATA_SHIFT); */ /* conversion to integer + happens here */ + /* rounding is done by shifting one bit less than necessary to the right, + * adding '1' and then shifting the final bit */ + tmp = ((((INT)NoiseLevels[i]) >> + (DFRACT_BITS - 1 - LD_DATA_SHIFT))); /* conversion to integer */ + if (tmp != 0) tmp += 1; + } + + if (coupling) { + tmp = tmp < -30 ? -30 : tmp; + tmp = mapPanorama(tmp, 1, &dummy); + } + iNoiseLevels[i] = tmp; + } +} + +/***************************************************************************/ +/*! + + \brief Calculation of noise floor for coupling + + \return void + +****************************************************************************/ +static void coupleNoiseFloor( + FIXP_DBL *RESTRICT noise_level_left, /*! noise level left (modified)*/ + FIXP_DBL *RESTRICT noise_level_right /*! noise level right (modified)*/ +) { + FIXP_DBL cmpValLeft, cmpValRight; + INT i; + FIXP_DBL temp1, temp2; + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) { + /* Calculation of the power function using ld64: + z = x^y; + z' = CalcLd64(z) = y*CalcLd64(x)/64; + z = CalcInvLd64(z'); + */ + cmpValLeft = NOISE_FLOOR_OFFSET_64 - noise_level_left[i]; + cmpValRight = NOISE_FLOOR_OFFSET_64 - noise_level_right[i]; + + if (cmpValRight < FL2FXCONST_DBL(0.0f)) { + temp1 = CalcInvLdData(NOISE_FLOOR_OFFSET_64 - noise_level_right[i]); + } else { + temp1 = CalcInvLdData(NOISE_FLOOR_OFFSET_64 - noise_level_right[i]); + temp1 = temp1 << (DFRACT_BITS - 1 - LD_DATA_SHIFT - + 1); /* INT to fract conversion of result, if input of + CalcInvLdData is positiv */ + } + + if (cmpValLeft < FL2FXCONST_DBL(0.0f)) { + temp2 = CalcInvLdData(NOISE_FLOOR_OFFSET_64 - noise_level_left[i]); + } else { + temp2 = CalcInvLdData(NOISE_FLOOR_OFFSET_64 - noise_level_left[i]); + temp2 = temp2 << (DFRACT_BITS - 1 - LD_DATA_SHIFT - + 1); /* INT to fract conversion of result, if input of + CalcInvLdData is positiv */ + } + + if ((cmpValLeft < FL2FXCONST_DBL(0.0f)) && + (cmpValRight < FL2FXCONST_DBL(0.0f))) { + noise_level_left[i] = + NOISE_FLOOR_OFFSET_64 - + (CalcLdData( + ((temp1 >> 1) + + (temp2 >> 1)))); /* no scaling needed! both values are dfract */ + noise_level_right[i] = CalcLdData(temp2) - CalcLdData(temp1); + } + + if ((cmpValLeft >= FL2FXCONST_DBL(0.0f)) && + (cmpValRight >= FL2FXCONST_DBL(0.0f))) { + noise_level_left[i] = NOISE_FLOOR_OFFSET_64 - + (CalcLdData(((temp1 >> 1) + (temp2 >> 1))) + + FL2FXCONST_DBL(0.109375f)); /* scaled with 7/64 */ + noise_level_right[i] = CalcLdData(temp2) - CalcLdData(temp1); + } + + if ((cmpValLeft >= FL2FXCONST_DBL(0.0f)) && + (cmpValRight < FL2FXCONST_DBL(0.0f))) { + noise_level_left[i] = NOISE_FLOOR_OFFSET_64 - + (CalcLdData(((temp1 >> (7 + 1)) + (temp2 >> 1))) + + FL2FXCONST_DBL(0.109375f)); /* scaled with 7/64 */ + noise_level_right[i] = + (CalcLdData(temp2) + FL2FXCONST_DBL(0.109375f)) - CalcLdData(temp1); + } + + if ((cmpValLeft < FL2FXCONST_DBL(0.0f)) && + (cmpValRight >= FL2FXCONST_DBL(0.0f))) { + noise_level_left[i] = NOISE_FLOOR_OFFSET_64 - + (CalcLdData(((temp1 >> 1) + (temp2 >> (7 + 1)))) + + FL2FXCONST_DBL(0.109375f)); /* scaled with 7/64 */ + noise_level_right[i] = CalcLdData(temp2) - + (CalcLdData(temp1) + + FL2FXCONST_DBL(0.109375f)); /* scaled with 7/64 */ + } + } +} + +/***************************************************************************/ +/*! + + \brief Calculation of energy starting in lower band (li) up to upper band +(ui) over slots (start_pos) to (stop_pos) + + \return void + +****************************************************************************/ + +static FIXP_DBL getEnvSfbEnergy( + INT li, /*! lower band */ + INT ui, /*! upper band */ + INT start_pos, /*! start slot */ + INT stop_pos, /*! stop slot */ + INT border_pos, /*! slots scaling border */ + FIXP_DBL **YBuffer, /*! sfb energy buffer */ + INT YBufferSzShift, /*! Energy buffer index scale */ + INT scaleNrg0, /*! scaling of lower slots */ + INT scaleNrg1) /*! scaling of upper slots */ +{ + /* use dynamic scaling for outer energy loop; + energies are critical and every bit is important */ + int sc0, sc1, k, l; + + FIXP_DBL nrgSum, nrg1, nrg2, accu1, accu2; + INT dynScale, dynScale1, dynScale2; + if (ui - li == 0) + dynScale = DFRACT_BITS - 1; + else + dynScale = CalcLdInt(ui - li) >> (DFRACT_BITS - 1 - LD_DATA_SHIFT); + + sc0 = fixMin(scaleNrg0, Y_NRG_SCALE); + sc1 = fixMin(scaleNrg1, Y_NRG_SCALE); + /* dynScale{1,2} is set such that the right shift below is positive */ + dynScale1 = fixMin((scaleNrg0 - sc0), dynScale); + dynScale2 = fixMin((scaleNrg1 - sc1), dynScale); + nrgSum = accu1 = accu2 = (FIXP_DBL)0; + + for (k = li; k < ui; k++) { + nrg1 = nrg2 = (FIXP_DBL)0; + for (l = start_pos; l < border_pos; l++) { + nrg1 += YBuffer[l >> YBufferSzShift][k] >> sc0; + } + for (; l < stop_pos; l++) { + nrg2 += YBuffer[l >> YBufferSzShift][k] >> sc1; + } + accu1 = fAddSaturate(accu1, (nrg1 >> dynScale1)); + accu2 = fAddSaturate(accu2, (nrg2 >> dynScale2)); + } + /* This shift factor is always positive. See comment above. */ + nrgSum += + (accu1 >> fixMin((scaleNrg0 - sc0 - dynScale1), (DFRACT_BITS - 1))) + + (accu2 >> fixMin((scaleNrg1 - sc1 - dynScale2), (DFRACT_BITS - 1))); + + return nrgSum; +} + +/***************************************************************************/ +/*! + + \brief Energy compensation in missing harmonic mode + + \return void + +****************************************************************************/ +static FIXP_DBL mhLoweringEnergy(FIXP_DBL nrg, INT M) { + /* + Compensating for the fact that we in the decoder map the "average energy to + every QMF band, and use this when we calculate the boost-factor. Since the + mapped energy isn't the average energy but the maximum energy in case of + missing harmonic creation, we will in the boost function calculate that too + much limiting has been applied and hence we will boost the signal although + it isn't called for. Hence we need to compensate for this by lowering the + transmitted energy values for the sines so they will get the correct level + after the boost is applied. + */ + if (M > 2) { + INT tmpScale; + tmpScale = CountLeadingBits(nrg); + nrg <<= tmpScale; + nrg = fMult(nrg, FL2FXCONST_DBL(0.398107267f)); /* The maximum boost + is 1.584893, so the + maximum attenuation + should be + square(1/1.584893) = + 0.398107267 */ + nrg >>= tmpScale; + } else { + if (M > 1) { + nrg >>= 1; + } + } + + return nrg; +} + +/***************************************************************************/ +/*! + + \brief Energy compensation in none missing harmonic mode + + \return void + +****************************************************************************/ +static FIXP_DBL nmhLoweringEnergy(FIXP_DBL nrg, const FIXP_DBL nrgSum, + const INT nrgSum_scale, const INT M) { + if (nrg > FL2FXCONST_DBL(0)) { + int sc = 0; + /* gain = nrgSum / (nrg*(M+1)) */ + FIXP_DBL gain = fMult(fDivNorm(nrgSum, nrg, &sc), GetInvInt(M + 1)); + sc += nrgSum_scale; + + /* reduce nrg if gain smaller 1.f */ + if (!((sc >= 0) && (gain > ((FIXP_DBL)MAXVAL_DBL >> sc)))) { + nrg = fMult(scaleValue(gain, sc), nrg); + } + } + return nrg; +} + +/***************************************************************************/ +/*! + + \brief calculates the envelope values from the energies, depending on + framing and stereo mode + + \return void + +****************************************************************************/ +static void calculateSbrEnvelope( + FIXP_DBL **RESTRICT YBufferLeft, /*! energy buffer left */ + FIXP_DBL **RESTRICT YBufferRight, /*! energy buffer right */ + int *RESTRICT YBufferScaleLeft, /*! scale energy buffer left */ + int *RESTRICT YBufferScaleRight, /*! scale energy buffer right */ + const SBR_FRAME_INFO *frame_info, /*! frame info vector */ + SCHAR *RESTRICT sfb_nrgLeft, /*! sfb energy buffer left */ + SCHAR *RESTRICT sfb_nrgRight, /*! sfb energy buffer right */ + HANDLE_SBR_CONFIG_DATA h_con, /*! handle to config data */ + HANDLE_ENV_CHANNEL h_sbr, /*! envelope channel handle */ + SBR_STEREO_MODE stereoMode, /*! stereo coding mode */ + INT *maxQuantError, /*! maximum quantization error, for panorama. */ + int YBufferSzShift) /*! Energy buffer index scale */ + +{ + int env, j, m = 0; + INT no_of_bands, start_pos, stop_pos, li, ui; + FREQ_RES freq_res; + + INT ca = 2 - h_sbr->encEnvData.init_sbr_amp_res; + INT oneBitLess = 0; + if (ca == 2) + oneBitLess = + 1; /* LD_DATA_SHIFT => ld64 scaling; one bit less for rounding */ + + INT quantError; + INT nEnvelopes = frame_info->nEnvelopes; + INT short_env = frame_info->shortEnv - 1; + INT timeStep = h_sbr->sbrExtractEnvelope.time_step; + INT commonScale, scaleLeft0, scaleLeft1; + INT scaleRight0 = 0, scaleRight1 = 0; + + commonScale = fixMin(YBufferScaleLeft[0], YBufferScaleLeft[1]); + + if (stereoMode == SBR_COUPLING) { + commonScale = fixMin(commonScale, YBufferScaleRight[0]); + commonScale = fixMin(commonScale, YBufferScaleRight[1]); + } + + commonScale = commonScale - 7; + + scaleLeft0 = YBufferScaleLeft[0] - commonScale; + scaleLeft1 = YBufferScaleLeft[1] - commonScale; + FDK_ASSERT((scaleLeft0 >= 0) && (scaleLeft1 >= 0)); + + if (stereoMode == SBR_COUPLING) { + scaleRight0 = YBufferScaleRight[0] - commonScale; + scaleRight1 = YBufferScaleRight[1] - commonScale; + FDK_ASSERT((scaleRight0 >= 0) && (scaleRight1 >= 0)); + *maxQuantError = 0; + } + + for (env = 0; env < nEnvelopes; env++) { + FIXP_DBL pNrgLeft[32]; + FIXP_DBL pNrgRight[32]; + int envNrg_scale; + FIXP_DBL envNrgLeft = FL2FXCONST_DBL(0.0f); + FIXP_DBL envNrgRight = FL2FXCONST_DBL(0.0f); + int missingHarmonic[32]; + int count[32]; + + start_pos = timeStep * frame_info->borders[env]; + stop_pos = timeStep * frame_info->borders[env + 1]; + freq_res = frame_info->freqRes[env]; + no_of_bands = h_con->nSfb[freq_res]; + envNrg_scale = DFRACT_BITS - fNormz((FIXP_DBL)no_of_bands); + if (env == short_env) { + j = fMax(2, timeStep); /* consider at least 2 QMF slots less for short + envelopes (envelopes just before transients) */ + if ((stop_pos - start_pos - j) > 0) { + stop_pos = stop_pos - j; + } + } + for (j = 0; j < no_of_bands; j++) { + FIXP_DBL nrgLeft = FL2FXCONST_DBL(0.0f); + FIXP_DBL nrgRight = FL2FXCONST_DBL(0.0f); + + li = h_con->freqBandTable[freq_res][j]; + ui = h_con->freqBandTable[freq_res][j + 1]; + + if (freq_res == FREQ_RES_HIGH) { + if (j == 0 && ui - li > 1) { + li++; + } + } else { + if (j == 0 && ui - li > 2) { + li++; + } + } + + /* + Find out whether a sine will be missing in the scale-factor + band that we're currently processing. + */ + missingHarmonic[j] = 0; + + if (h_sbr->encEnvData.addHarmonicFlag) { + if (freq_res == FREQ_RES_HIGH) { + if (h_sbr->encEnvData + .addHarmonic[j]) { /*A missing sine in the current band*/ + missingHarmonic[j] = 1; + } + } else { + INT i; + INT startBandHigh = 0; + INT stopBandHigh = 0; + + while (h_con->freqBandTable[FREQ_RES_HIGH][startBandHigh] < + h_con->freqBandTable[FREQ_RES_LOW][j]) + startBandHigh++; + while (h_con->freqBandTable[FREQ_RES_HIGH][stopBandHigh] < + h_con->freqBandTable[FREQ_RES_LOW][j + 1]) + stopBandHigh++; + + for (i = startBandHigh; i < stopBandHigh; i++) { + if (h_sbr->encEnvData.addHarmonic[i]) { + missingHarmonic[j] = 1; + } + } + } + } + + /* + If a sine is missing in a scalefactorband, with more than one qmf + channel use the nrg from the channel with the largest nrg rather than + the mean. Compensate for the boost calculation in the decdoder. + */ + int border_pos = + fixMin(stop_pos, h_sbr->sbrExtractEnvelope.YBufferWriteOffset + << YBufferSzShift); + + if (missingHarmonic[j]) { + int k; + count[j] = stop_pos - start_pos; + nrgLeft = FL2FXCONST_DBL(0.0f); + + for (k = li; k < ui; k++) { + FIXP_DBL tmpNrg; + tmpNrg = getEnvSfbEnergy(k, k + 1, start_pos, stop_pos, border_pos, + YBufferLeft, YBufferSzShift, scaleLeft0, + scaleLeft1); + + nrgLeft = fixMax(nrgLeft, tmpNrg); + } + + /* Energy lowering compensation */ + nrgLeft = mhLoweringEnergy(nrgLeft, ui - li); + + if (stereoMode == SBR_COUPLING) { + nrgRight = FL2FXCONST_DBL(0.0f); + + for (k = li; k < ui; k++) { + FIXP_DBL tmpNrg; + tmpNrg = getEnvSfbEnergy(k, k + 1, start_pos, stop_pos, border_pos, + YBufferRight, YBufferSzShift, scaleRight0, + scaleRight1); + + nrgRight = fixMax(nrgRight, tmpNrg); + } + + /* Energy lowering compensation */ + nrgRight = mhLoweringEnergy(nrgRight, ui - li); + } + } /* end missingHarmonic */ + else { + count[j] = (stop_pos - start_pos) * (ui - li); + + nrgLeft = getEnvSfbEnergy(li, ui, start_pos, stop_pos, border_pos, + YBufferLeft, YBufferSzShift, scaleLeft0, + scaleLeft1); + + if (stereoMode == SBR_COUPLING) { + nrgRight = getEnvSfbEnergy(li, ui, start_pos, stop_pos, border_pos, + YBufferRight, YBufferSzShift, scaleRight0, + scaleRight1); + } + } /* !missingHarmonic */ + + /* save energies */ + pNrgLeft[j] = nrgLeft; + pNrgRight[j] = nrgRight; + envNrgLeft += (nrgLeft >> envNrg_scale); + envNrgRight += (nrgRight >> envNrg_scale); + } /* j */ + + for (j = 0; j < no_of_bands; j++) { + FIXP_DBL nrgLeft2 = FL2FXCONST_DBL(0.0f); + FIXP_DBL nrgLeft = pNrgLeft[j]; + FIXP_DBL nrgRight = pNrgRight[j]; + + /* None missing harmonic Energy lowering compensation */ + if (!missingHarmonic[j] && h_sbr->fLevelProtect) { + /* in case of missing energy in base band, + reduce reference energy to prevent overflows in decoder output */ + nrgLeft = + nmhLoweringEnergy(nrgLeft, envNrgLeft, envNrg_scale, no_of_bands); + if (stereoMode == SBR_COUPLING) { + nrgRight = nmhLoweringEnergy(nrgRight, envNrgRight, envNrg_scale, + no_of_bands); + } + } + + if (stereoMode == SBR_COUPLING) { + /* calc operation later with log */ + nrgLeft2 = nrgLeft; + nrgLeft = (nrgRight + nrgLeft) >> 1; + } + + /* nrgLeft = f20_log2(nrgLeft / (PFLOAT)(count * 64))+(PFLOAT)44; */ + /* If nrgLeft == 0 then the Log calculations below do fail. */ + if (nrgLeft > FL2FXCONST_DBL(0.0f)) { + FIXP_DBL tmp0, tmp1, tmp2, tmp3; + INT tmpScale; + + tmpScale = CountLeadingBits(nrgLeft); + nrgLeft = nrgLeft << tmpScale; + + tmp0 = CalcLdData(nrgLeft); /* scaled by 1/64 */ + tmp1 = ((FIXP_DBL)(commonScale + tmpScale)) + << (DFRACT_BITS - 1 - LD_DATA_SHIFT - 1); /* scaled by 1/64 */ + tmp2 = ((FIXP_DBL)(count[j] * 64)) << (DFRACT_BITS - 1 - 14 - 1); + tmp2 = CalcLdData(tmp2); /* scaled by 1/64 */ + tmp3 = FL2FXCONST_DBL(0.6875f - 0.21875f - 0.015625f) >> + 1; /* scaled by 1/64 */ + + nrgLeft = ((tmp0 - tmp2) >> 1) + (tmp3 - tmp1); + } else { + nrgLeft = FL2FXCONST_DBL(-1.0f); + } + + /* ld64 to integer conversion */ + nrgLeft = fixMin(fixMax(nrgLeft, FL2FXCONST_DBL(0.0f)), + (FL2FXCONST_DBL(0.5f) >> oneBitLess)); + nrgLeft = (FIXP_DBL)(LONG)nrgLeft >> + (DFRACT_BITS - 1 - LD_DATA_SHIFT - 1 - oneBitLess - 1); + sfb_nrgLeft[m] = ((INT)nrgLeft + 1) >> 1; /* rounding */ + + if (stereoMode == SBR_COUPLING) { + FIXP_DBL scaleFract; + int sc0, sc1; + + nrgLeft2 = fixMax((FIXP_DBL)0x1, nrgLeft2); + nrgRight = fixMax((FIXP_DBL)0x1, nrgRight); + + sc0 = CountLeadingBits(nrgLeft2); + sc1 = CountLeadingBits(nrgRight); + + scaleFract = + ((FIXP_DBL)(sc0 - sc1)) + << (DFRACT_BITS - 1 - + LD_DATA_SHIFT); /* scale value in ld64 representation */ + nrgRight = CalcLdData(nrgLeft2 << sc0) - CalcLdData(nrgRight << sc1) - + scaleFract; + + /* ld64 to integer conversion */ + nrgRight = (FIXP_DBL)(LONG)(nrgRight) >> + (DFRACT_BITS - 1 - LD_DATA_SHIFT - 1 - oneBitLess); + nrgRight = (nrgRight + (FIXP_DBL)1) >> 1; /* rounding */ + + sfb_nrgRight[m] = mapPanorama( + nrgRight, h_sbr->encEnvData.init_sbr_amp_res, &quantError); + + *maxQuantError = fixMax(quantError, *maxQuantError); + } + + m++; + } /* j */ + + /* Do energy compensation for sines that are present in two + QMF-bands in the original, but will only occur in one band in + the decoder due to the synthetic sine coding.*/ + if (h_con->useParametricCoding) { + m -= no_of_bands; + for (j = 0; j < no_of_bands; j++) { + if (freq_res == FREQ_RES_HIGH && + h_sbr->sbrExtractEnvelope.envelopeCompensation[j]) { + sfb_nrgLeft[m] -= + (ca * + fixp_abs( + (INT)h_sbr->sbrExtractEnvelope.envelopeCompensation[j])); + } + sfb_nrgLeft[m] = fixMax(0, sfb_nrgLeft[m]); + m++; + } + } /* useParametricCoding */ + + } /* env loop */ +} + +/***************************************************************************/ +/*! + + \brief calculates the noise floor and the envelope values from the + energies, depending on framing and stereo mode + + FDKsbrEnc_extractSbrEnvelope is the main function for encoding and writing the + envelope and the noise floor. The function includes the following processes: + + -Analysis subband filtering. + -Encoding SA and pan parameters (if enabled). + -Transient detection. + +****************************************************************************/ + +LNK_SECTION_CODE_L1 +void FDKsbrEnc_extractSbrEnvelope1( + HANDLE_SBR_CONFIG_DATA h_con, /*! handle to config data */ + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, HANDLE_ENV_CHANNEL hEnvChan, + HANDLE_COMMON_DATA hCmonData, SBR_ENV_TEMP_DATA *eData, + SBR_FRAME_TEMP_DATA *fData) { + HANDLE_SBR_EXTRACT_ENVELOPE sbrExtrEnv = &hEnvChan->sbrExtractEnvelope; + + if (sbrExtrEnv->YBufferSzShift == 0) + FDKsbrEnc_getEnergyFromCplxQmfDataFull( + &sbrExtrEnv->YBuffer[sbrExtrEnv->YBufferWriteOffset], + sbrExtrEnv->rBuffer + sbrExtrEnv->rBufferReadOffset, + sbrExtrEnv->iBuffer + sbrExtrEnv->rBufferReadOffset, h_con->noQmfBands, + sbrExtrEnv->no_cols, &hEnvChan->qmfScale, &sbrExtrEnv->YBufferScale[1]); + else + FDKsbrEnc_getEnergyFromCplxQmfData( + &sbrExtrEnv->YBuffer[sbrExtrEnv->YBufferWriteOffset], + sbrExtrEnv->rBuffer + sbrExtrEnv->rBufferReadOffset, + sbrExtrEnv->iBuffer + sbrExtrEnv->rBufferReadOffset, h_con->noQmfBands, + sbrExtrEnv->no_cols, &hEnvChan->qmfScale, &sbrExtrEnv->YBufferScale[1]); + + /* Energie values = + * sbrExtrEnv->YBuffer[sbrExtrEnv->YBufferWriteOffset][x].floatVal * + * (1<<2*7-sbrExtrEnv->YBufferScale[1]) */ + + /* + Precalculation of Tonality Quotas COEFF Transform OK + */ + FDKsbrEnc_CalculateTonalityQuotas( + &hEnvChan->TonCorr, sbrExtrEnv->rBuffer, sbrExtrEnv->iBuffer, + h_con->freqBandTable[HI][h_con->nSfb[HI]], hEnvChan->qmfScale); + + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + FIXP_DBL tonality = FDKsbrEnc_GetTonality( + hEnvChan->TonCorr.quotaMatrix, + hEnvChan->TonCorr.numberOfEstimatesPerFrame, + hEnvChan->TonCorr.startIndexMatrix, + sbrExtrEnv->YBuffer + sbrExtrEnv->YBufferWriteOffset, + h_con->freqBandTable[HI][0] + 1, h_con->noQmfBands, + sbrExtrEnv->no_cols); + + hEnvChan->encEnvData.ton_HF[1] = hEnvChan->encEnvData.ton_HF[0]; + hEnvChan->encEnvData.ton_HF[0] = tonality; + + /* tonality is scaled by 2^19/0.524288f (fract part of RELAXATION) */ + hEnvChan->encEnvData.global_tonality = + (hEnvChan->encEnvData.ton_HF[0] >> 1) + + (hEnvChan->encEnvData.ton_HF[1] >> 1); + } + + /* + Transient detection COEFF Transform OK + */ + + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + FDKsbrEnc_fastTransientDetect(&hEnvChan->sbrFastTransientDetector, + sbrExtrEnv->YBuffer, sbrExtrEnv->YBufferScale, + sbrExtrEnv->YBufferWriteOffset, + eData->transient_info); + + } else { + FDKsbrEnc_transientDetect( + &hEnvChan->sbrTransientDetector, sbrExtrEnv->YBuffer, + sbrExtrEnv->YBufferScale, eData->transient_info, + sbrExtrEnv->YBufferWriteOffset, sbrExtrEnv->YBufferSzShift, + sbrExtrEnv->time_step, hEnvChan->SbrEnvFrame.frameMiddleSlot); + } + + /* + Generate flags for 2 env in a FIXFIX-frame. + Remove this function to get always 1 env per FIXFIX-frame. + */ + + /* + frame Splitter COEFF Transform OK + */ + FDKsbrEnc_frameSplitter( + sbrExtrEnv->YBuffer, sbrExtrEnv->YBufferScale, + &hEnvChan->sbrTransientDetector, h_con->freqBandTable[1], + eData->transient_info, sbrExtrEnv->YBufferWriteOffset, + sbrExtrEnv->YBufferSzShift, h_con->nSfb[1], sbrExtrEnv->time_step, + sbrExtrEnv->no_cols, &hEnvChan->encEnvData.global_tonality); +} + +/***************************************************************************/ +/*! + + \brief calculates the noise floor and the envelope values from the + energies, depending on framing and stereo mode + + FDKsbrEnc_extractSbrEnvelope is the main function for encoding and writing the + envelope and the noise floor. The function includes the following processes: + + -Determine time/frequency division of current granule. + -Sending transient info to bitstream. + -Set amp_res to 1.5 dB if the current frame contains only one envelope. + -Lock dynamic bandwidth frequency change if the next envelope not starts on a + frame boundary. + -MDCT transposer (needed to detect where harmonics will be missing). + -Spectrum Estimation (used for pulse train and missing harmonics detection). + -Pulse train detection. + -Inverse Filtering detection. + -Waveform Coding. + -Missing Harmonics detection. + -Extract envelope of current frame. + -Noise floor estimation. + -Noise floor quantisation and coding. + -Encode envelope of current frame. + -Send the encoded data to the bitstream. + -Write to bitstream. + +****************************************************************************/ + +LNK_SECTION_CODE_L1 +void FDKsbrEnc_extractSbrEnvelope2( + HANDLE_SBR_CONFIG_DATA h_con, /*! handle to config data */ + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, HANDLE_ENV_CHANNEL h_envChan0, + HANDLE_ENV_CHANNEL h_envChan1, HANDLE_COMMON_DATA hCmonData, + SBR_ENV_TEMP_DATA *eData, SBR_FRAME_TEMP_DATA *fData, int clearOutput) { + HANDLE_ENV_CHANNEL h_envChan[MAX_NUM_CHANNELS] = {h_envChan0, h_envChan1}; + int ch, i, j, c, YSzShift = h_envChan[0]->sbrExtractEnvelope.YBufferSzShift; + + SBR_STEREO_MODE stereoMode = h_con->stereoMode; + int nChannels = h_con->nChannels; + const int *v_tuning; + static const int v_tuningHEAAC[6] = {0, 2, 4, 0, 0, 0}; + + static const int v_tuningELD[6] = {0, 2, 3, 0, 0, 0}; + + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + v_tuning = v_tuningELD; + else + v_tuning = v_tuningHEAAC; + + /* + Select stereo mode. + */ + if (stereoMode == SBR_COUPLING) { + if (eData[0].transient_info[1] && eData[1].transient_info[1]) { + eData[0].transient_info[0] = + fixMin(eData[1].transient_info[0], eData[0].transient_info[0]); + eData[1].transient_info[0] = eData[0].transient_info[0]; + } else { + if (eData[0].transient_info[1] && !eData[1].transient_info[1]) { + eData[1].transient_info[0] = eData[0].transient_info[0]; + } else { + if (!eData[0].transient_info[1] && eData[1].transient_info[1]) + eData[0].transient_info[0] = eData[1].transient_info[0]; + else { + eData[0].transient_info[0] = + fixMax(eData[1].transient_info[0], eData[0].transient_info[0]); + eData[1].transient_info[0] = eData[0].transient_info[0]; + } + } + } + } + + /* + Determine time/frequency division of current granule + */ + eData[0].frame_info = FDKsbrEnc_frameInfoGenerator( + &h_envChan[0]->SbrEnvFrame, eData[0].transient_info, + sbrBitstreamData->rightBorderFIX, + h_envChan[0]->sbrExtractEnvelope.pre_transient_info, + h_envChan[0]->encEnvData.ldGrid, v_tuning); + + h_envChan[0]->encEnvData.hSbrBSGrid = &h_envChan[0]->SbrEnvFrame.SbrGrid; + + /* AAC LD patch for transient prediction */ + if (h_envChan[0]->encEnvData.ldGrid && eData[0].transient_info[2]) { + /* if next frame will start with transient, set shortEnv to + * numEnvelopes(shortend Envelope = shortEnv-1)*/ + h_envChan[0]->SbrEnvFrame.SbrFrameInfo.shortEnv = + h_envChan[0]->SbrEnvFrame.SbrFrameInfo.nEnvelopes; + } + + switch (stereoMode) { + case SBR_LEFT_RIGHT: + case SBR_SWITCH_LRC: + eData[1].frame_info = FDKsbrEnc_frameInfoGenerator( + &h_envChan[1]->SbrEnvFrame, eData[1].transient_info, + sbrBitstreamData->rightBorderFIX, + h_envChan[1]->sbrExtractEnvelope.pre_transient_info, + h_envChan[1]->encEnvData.ldGrid, v_tuning); + + h_envChan[1]->encEnvData.hSbrBSGrid = &h_envChan[1]->SbrEnvFrame.SbrGrid; + + if (h_envChan[1]->encEnvData.ldGrid && eData[1].transient_info[2]) { + /* if next frame will start with transient, set shortEnv to + * numEnvelopes(shortend Envelope = shortEnv-1)*/ + h_envChan[1]->SbrEnvFrame.SbrFrameInfo.shortEnv = + h_envChan[1]->SbrEnvFrame.SbrFrameInfo.nEnvelopes; + } + + /* compare left and right frame_infos */ + if (eData[0].frame_info->nEnvelopes != eData[1].frame_info->nEnvelopes) { + stereoMode = SBR_LEFT_RIGHT; + } else { + for (i = 0; i < eData[0].frame_info->nEnvelopes + 1; i++) { + if (eData[0].frame_info->borders[i] != + eData[1].frame_info->borders[i]) { + stereoMode = SBR_LEFT_RIGHT; + break; + } + } + for (i = 0; i < eData[0].frame_info->nEnvelopes; i++) { + if (eData[0].frame_info->freqRes[i] != + eData[1].frame_info->freqRes[i]) { + stereoMode = SBR_LEFT_RIGHT; + break; + } + } + if (eData[0].frame_info->shortEnv != eData[1].frame_info->shortEnv) { + stereoMode = SBR_LEFT_RIGHT; + } + } + break; + case SBR_COUPLING: + eData[1].frame_info = eData[0].frame_info; + h_envChan[1]->encEnvData.hSbrBSGrid = &h_envChan[0]->SbrEnvFrame.SbrGrid; + break; + case SBR_MONO: + /* nothing to do */ + break; + default: + FDK_ASSERT(0); + } + + for (ch = 0; ch < nChannels; ch++) { + HANDLE_ENV_CHANNEL hEnvChan = h_envChan[ch]; + HANDLE_SBR_EXTRACT_ENVELOPE sbrExtrEnv = &hEnvChan->sbrExtractEnvelope; + SBR_ENV_TEMP_DATA *ed = &eData[ch]; + + /* + Send transient info to bitstream and store for next call + */ + sbrExtrEnv->pre_transient_info[0] = ed->transient_info[0]; /* tran_pos */ + sbrExtrEnv->pre_transient_info[1] = ed->transient_info[1]; /* tran_flag */ + hEnvChan->encEnvData.noOfEnvelopes = ed->nEnvelopes = + ed->frame_info->nEnvelopes; /* number of envelopes of current frame */ + hEnvChan->encEnvData.currentAmpResFF = (AMP_RES)h_con->initAmpResFF; + + /* + Check if the current frame is divided into one envelope only. If so, set + the amplitude resolution to 1.5 dB, otherwise may set back to chosen value + */ + if ((hEnvChan->encEnvData.hSbrBSGrid->frameClass == FIXFIX) && + (ed->nEnvelopes == 1)) { + AMP_RES currentAmpResFF = SBR_AMP_RES_1_5; + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + /* Note: global_tonality_float_value == + ((float)hEnvChan->encEnvData.global_tonality/((INT64)(1)<<(31-(19+2)))/0.524288*(2.0/3.0))); + threshold_float_value == + ((float)h_con->thresholdAmpResFF_m/((INT64)(1)<<(31-(h_con->thresholdAmpResFF_e)))/0.524288*(2.0/3.0))); + */ + /* decision of SBR_AMP_RES */ + if (fIsLessThan(/* global_tonality > threshold ? */ + h_con->thresholdAmpResFF_m, h_con->thresholdAmpResFF_e, + hEnvChan->encEnvData.global_tonality, + RELAXATION_SHIFT + 2)) { + hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5; + } else { + hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_3_0; + } + currentAmpResFF = hEnvChan->encEnvData.currentAmpResFF; + } + + if (currentAmpResFF != hEnvChan->encEnvData.init_sbr_amp_res) { + FDKsbrEnc_InitSbrHuffmanTables( + &hEnvChan->encEnvData, &hEnvChan->sbrCodeEnvelope, + &hEnvChan->sbrCodeNoiseFloor, currentAmpResFF); + } + } else { + if (sbrHeaderData->sbr_amp_res != hEnvChan->encEnvData.init_sbr_amp_res) { + FDKsbrEnc_InitSbrHuffmanTables( + &hEnvChan->encEnvData, &hEnvChan->sbrCodeEnvelope, + &hEnvChan->sbrCodeNoiseFloor, sbrHeaderData->sbr_amp_res); + } + } + + if (!clearOutput) { + /* + Tonality correction parameter extraction (inverse filtering level, noise + floor additional sines). + */ + FDKsbrEnc_TonCorrParamExtr( + &hEnvChan->TonCorr, hEnvChan->encEnvData.sbr_invf_mode_vec, + ed->noiseFloor, &hEnvChan->encEnvData.addHarmonicFlag, + hEnvChan->encEnvData.addHarmonic, sbrExtrEnv->envelopeCompensation, + ed->frame_info, ed->transient_info, h_con->freqBandTable[HI], + h_con->nSfb[HI], hEnvChan->encEnvData.sbr_xpos_mode, + h_con->sbrSyntaxFlags); + } + + /* Low energy in low band fix */ + if (hEnvChan->sbrTransientDetector.prevLowBandEnergy < + hEnvChan->sbrTransientDetector.prevHighBandEnergy && + hEnvChan->sbrTransientDetector.prevHighBandEnergy > FL2FX_DBL(0.03) + /* The fix needs the non-fast transient detector running. + It sets prevLowBandEnergy and prevHighBandEnergy. */ + && !(h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)) { + hEnvChan->fLevelProtect = 1; + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + hEnvChan->encEnvData.sbr_invf_mode_vec[i] = INVF_HIGH_LEVEL; + } else { + hEnvChan->fLevelProtect = 0; + } + + hEnvChan->encEnvData.sbr_invf_mode = + hEnvChan->encEnvData.sbr_invf_mode_vec[0]; + + hEnvChan->encEnvData.noOfnoisebands = + hEnvChan->TonCorr.sbrNoiseFloorEstimate.noNoiseBands; + + } /* ch */ + + /* + Save number of scf bands per envelope + */ + for (ch = 0; ch < nChannels; ch++) { + for (i = 0; i < eData[ch].nEnvelopes; i++) { + h_envChan[ch]->encEnvData.noScfBands[i] = + (eData[ch].frame_info->freqRes[i] == FREQ_RES_HIGH + ? h_con->nSfb[FREQ_RES_HIGH] + : h_con->nSfb[FREQ_RES_LOW]); + } + } + + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY && + stereoMode == SBR_SWITCH_LRC && + h_envChan[0]->encEnvData.currentAmpResFF != + h_envChan[1]->encEnvData.currentAmpResFF) { + stereoMode = SBR_LEFT_RIGHT; + } + + /* + Extract envelope of current frame. + */ + switch (stereoMode) { + case SBR_MONO: + calculateSbrEnvelope(h_envChan[0]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, NULL, + eData[0].frame_info, eData[0].sfb_nrg, NULL, h_con, + h_envChan[0], SBR_MONO, NULL, YSzShift); + break; + case SBR_LEFT_RIGHT: + calculateSbrEnvelope(h_envChan[0]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, NULL, + eData[0].frame_info, eData[0].sfb_nrg, NULL, h_con, + h_envChan[0], SBR_MONO, NULL, YSzShift); + calculateSbrEnvelope(h_envChan[1]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[1]->sbrExtractEnvelope.YBufferScale, NULL, + eData[1].frame_info, eData[1].sfb_nrg, NULL, h_con, + h_envChan[1], SBR_MONO, NULL, YSzShift); + break; + case SBR_COUPLING: + calculateSbrEnvelope(h_envChan[0]->sbrExtractEnvelope.YBuffer, + h_envChan[1]->sbrExtractEnvelope.YBuffer, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, + h_envChan[1]->sbrExtractEnvelope.YBufferScale, + eData[0].frame_info, eData[0].sfb_nrg, + eData[1].sfb_nrg, h_con, h_envChan[0], SBR_COUPLING, + &fData->maxQuantError, YSzShift); + break; + case SBR_SWITCH_LRC: + calculateSbrEnvelope(h_envChan[0]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, NULL, + eData[0].frame_info, eData[0].sfb_nrg, NULL, h_con, + h_envChan[0], SBR_MONO, NULL, YSzShift); + calculateSbrEnvelope(h_envChan[1]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[1]->sbrExtractEnvelope.YBufferScale, NULL, + eData[1].frame_info, eData[1].sfb_nrg, NULL, h_con, + h_envChan[1], SBR_MONO, NULL, YSzShift); + calculateSbrEnvelope(h_envChan[0]->sbrExtractEnvelope.YBuffer, + h_envChan[1]->sbrExtractEnvelope.YBuffer, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, + h_envChan[1]->sbrExtractEnvelope.YBufferScale, + eData[0].frame_info, eData[0].sfb_nrg_coupling, + eData[1].sfb_nrg_coupling, h_con, h_envChan[0], + SBR_COUPLING, &fData->maxQuantError, YSzShift); + break; + } + + /* + Noise floor quantisation and coding. + */ + + switch (stereoMode) { + case SBR_MONO: + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level, eData[0].noiseFloor, + 0); + + FDKsbrEnc_codeEnvelope(eData[0].noise_level, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 0, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + break; + case SBR_LEFT_RIGHT: + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level, eData[0].noiseFloor, + 0); + + FDKsbrEnc_codeEnvelope(eData[0].noise_level, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 0, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + sbrNoiseFloorLevelsQuantisation(eData[1].noise_level, eData[1].noiseFloor, + 0); + + FDKsbrEnc_codeEnvelope(eData[1].noise_level, fData->res, + &h_envChan[1]->sbrCodeNoiseFloor, + h_envChan[1]->encEnvData.domain_vec_noise, 0, + (eData[1].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + break; + + case SBR_COUPLING: + coupleNoiseFloor(eData[0].noiseFloor, eData[1].noiseFloor); + + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level, eData[0].noiseFloor, + 0); + + FDKsbrEnc_codeEnvelope(eData[0].noise_level, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 1, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + sbrNoiseFloorLevelsQuantisation(eData[1].noise_level, eData[1].noiseFloor, + 1); + + FDKsbrEnc_codeEnvelope(eData[1].noise_level, fData->res, + &h_envChan[1]->sbrCodeNoiseFloor, + h_envChan[1]->encEnvData.domain_vec_noise, 1, + (eData[1].frame_info->nEnvelopes > 1 ? 2 : 1), 1, + sbrBitstreamData->HeaderActive); + + break; + case SBR_SWITCH_LRC: + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level, eData[0].noiseFloor, + 0); + sbrNoiseFloorLevelsQuantisation(eData[1].noise_level, eData[1].noiseFloor, + 0); + coupleNoiseFloor(eData[0].noiseFloor, eData[1].noiseFloor); + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level_coupling, + eData[0].noiseFloor, 0); + sbrNoiseFloorLevelsQuantisation(eData[1].noise_level_coupling, + eData[1].noiseFloor, 1); + break; + } + + /* + Encode envelope of current frame. + */ + switch (stereoMode) { + case SBR_MONO: + sbrHeaderData->coupling = 0; + h_envChan[0]->encEnvData.balance = 0; + FDKsbrEnc_codeEnvelope( + eData[0].sfb_nrg, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, h_envChan[0]->encEnvData.domain_vec, + sbrHeaderData->coupling, eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + break; + case SBR_LEFT_RIGHT: + sbrHeaderData->coupling = 0; + + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 0; + + FDKsbrEnc_codeEnvelope( + eData[0].sfb_nrg, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, h_envChan[0]->encEnvData.domain_vec, + sbrHeaderData->coupling, eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + FDKsbrEnc_codeEnvelope( + eData[1].sfb_nrg, eData[1].frame_info->freqRes, + &h_envChan[1]->sbrCodeEnvelope, h_envChan[1]->encEnvData.domain_vec, + sbrHeaderData->coupling, eData[1].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + break; + case SBR_COUPLING: + sbrHeaderData->coupling = 1; + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 1; + + FDKsbrEnc_codeEnvelope( + eData[0].sfb_nrg, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, h_envChan[0]->encEnvData.domain_vec, + sbrHeaderData->coupling, eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + FDKsbrEnc_codeEnvelope( + eData[1].sfb_nrg, eData[1].frame_info->freqRes, + &h_envChan[1]->sbrCodeEnvelope, h_envChan[1]->encEnvData.domain_vec, + sbrHeaderData->coupling, eData[1].frame_info->nEnvelopes, 1, + sbrBitstreamData->HeaderActive); + break; + case SBR_SWITCH_LRC: { + INT payloadbitsLR; + INT payloadbitsCOUPLING; + + SCHAR sfbNrgPrevTemp[MAX_NUM_CHANNELS][MAX_FREQ_COEFFS]; + SCHAR noisePrevTemp[MAX_NUM_CHANNELS][MAX_NUM_NOISE_COEFFS]; + INT upDateNrgTemp[MAX_NUM_CHANNELS]; + INT upDateNoiseTemp[MAX_NUM_CHANNELS]; + INT domainVecTemp[MAX_NUM_CHANNELS][MAX_ENVELOPES]; + INT domainVecNoiseTemp[MAX_NUM_CHANNELS][MAX_ENVELOPES]; + + INT tempFlagRight = 0; + INT tempFlagLeft = 0; + + /* + Store previous values, in order to be able to "undo" what is being + done. + */ + + for (ch = 0; ch < nChannels; ch++) { + FDKmemcpy(sfbNrgPrevTemp[ch], + h_envChan[ch]->sbrCodeEnvelope.sfb_nrg_prev, + MAX_FREQ_COEFFS * sizeof(SCHAR)); + + FDKmemcpy(noisePrevTemp[ch], + h_envChan[ch]->sbrCodeNoiseFloor.sfb_nrg_prev, + MAX_NUM_NOISE_COEFFS * sizeof(SCHAR)); + + upDateNrgTemp[ch] = h_envChan[ch]->sbrCodeEnvelope.upDate; + upDateNoiseTemp[ch] = h_envChan[ch]->sbrCodeNoiseFloor.upDate; + + /* + forbid time coding in the first envelope in case of a different + previous stereomode + */ + if (sbrHeaderData->prev_coupling) { + h_envChan[ch]->sbrCodeEnvelope.upDate = 0; + h_envChan[ch]->sbrCodeNoiseFloor.upDate = 0; + } + } /* ch */ + + /* + Code ordinary Left/Right stereo + */ + FDKsbrEnc_codeEnvelope(eData[0].sfb_nrg, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, + h_envChan[0]->encEnvData.domain_vec, 0, + eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + FDKsbrEnc_codeEnvelope(eData[1].sfb_nrg, eData[1].frame_info->freqRes, + &h_envChan[1]->sbrCodeEnvelope, + h_envChan[1]->encEnvData.domain_vec, 0, + eData[1].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + + c = 0; + for (i = 0; i < eData[0].nEnvelopes; i++) { + for (j = 0; j < h_envChan[0]->encEnvData.noScfBands[i]; j++) { + h_envChan[0]->encEnvData.ienvelope[i][j] = eData[0].sfb_nrg[c]; + h_envChan[1]->encEnvData.ienvelope[i][j] = eData[1].sfb_nrg[c]; + c++; + } + } + + FDKsbrEnc_codeEnvelope(eData[0].noise_level, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 0, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + h_envChan[0]->encEnvData.sbr_noise_levels[i] = eData[0].noise_level[i]; + + FDKsbrEnc_codeEnvelope(eData[1].noise_level, fData->res, + &h_envChan[1]->sbrCodeNoiseFloor, + h_envChan[1]->encEnvData.domain_vec_noise, 0, + (eData[1].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + h_envChan[1]->encEnvData.sbr_noise_levels[i] = eData[1].noise_level[i]; + + sbrHeaderData->coupling = 0; + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 0; + + payloadbitsLR = FDKsbrEnc_CountSbrChannelPairElement( + sbrHeaderData, hParametricStereo, sbrBitstreamData, + &h_envChan[0]->encEnvData, &h_envChan[1]->encEnvData, hCmonData, + h_con->sbrSyntaxFlags); + + /* + swap saved stored with current values + */ + for (ch = 0; ch < nChannels; ch++) { + INT itmp; + for (i = 0; i < MAX_FREQ_COEFFS; i++) { + /* + swap sfb energies + */ + itmp = h_envChan[ch]->sbrCodeEnvelope.sfb_nrg_prev[i]; + h_envChan[ch]->sbrCodeEnvelope.sfb_nrg_prev[i] = + sfbNrgPrevTemp[ch][i]; + sfbNrgPrevTemp[ch][i] = itmp; + } + for (i = 0; i < MAX_NUM_NOISE_COEFFS; i++) { + /* + swap noise energies + */ + itmp = h_envChan[ch]->sbrCodeNoiseFloor.sfb_nrg_prev[i]; + h_envChan[ch]->sbrCodeNoiseFloor.sfb_nrg_prev[i] = + noisePrevTemp[ch][i]; + noisePrevTemp[ch][i] = itmp; + } + /* swap update flags */ + itmp = h_envChan[ch]->sbrCodeEnvelope.upDate; + h_envChan[ch]->sbrCodeEnvelope.upDate = upDateNrgTemp[ch]; + upDateNrgTemp[ch] = itmp; + + itmp = h_envChan[ch]->sbrCodeNoiseFloor.upDate; + h_envChan[ch]->sbrCodeNoiseFloor.upDate = upDateNoiseTemp[ch]; + upDateNoiseTemp[ch] = itmp; + + /* + save domain vecs + */ + FDKmemcpy(domainVecTemp[ch], h_envChan[ch]->encEnvData.domain_vec, + sizeof(INT) * MAX_ENVELOPES); + FDKmemcpy(domainVecNoiseTemp[ch], + h_envChan[ch]->encEnvData.domain_vec_noise, + sizeof(INT) * MAX_ENVELOPES); + + /* + forbid time coding in the first envelope in case of a different + previous stereomode + */ + + if (!sbrHeaderData->prev_coupling) { + h_envChan[ch]->sbrCodeEnvelope.upDate = 0; + h_envChan[ch]->sbrCodeNoiseFloor.upDate = 0; + } + } /* ch */ + + /* + Coupling + */ + + FDKsbrEnc_codeEnvelope( + eData[0].sfb_nrg_coupling, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, h_envChan[0]->encEnvData.domain_vec, + 1, eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + + FDKsbrEnc_codeEnvelope( + eData[1].sfb_nrg_coupling, eData[1].frame_info->freqRes, + &h_envChan[1]->sbrCodeEnvelope, h_envChan[1]->encEnvData.domain_vec, + 1, eData[1].frame_info->nEnvelopes, 1, + sbrBitstreamData->HeaderActive); + + c = 0; + for (i = 0; i < eData[0].nEnvelopes; i++) { + for (j = 0; j < h_envChan[0]->encEnvData.noScfBands[i]; j++) { + h_envChan[0]->encEnvData.ienvelope[i][j] = + eData[0].sfb_nrg_coupling[c]; + h_envChan[1]->encEnvData.ienvelope[i][j] = + eData[1].sfb_nrg_coupling[c]; + c++; + } + } + + FDKsbrEnc_codeEnvelope(eData[0].noise_level_coupling, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 1, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + h_envChan[0]->encEnvData.sbr_noise_levels[i] = + eData[0].noise_level_coupling[i]; + + FDKsbrEnc_codeEnvelope(eData[1].noise_level_coupling, fData->res, + &h_envChan[1]->sbrCodeNoiseFloor, + h_envChan[1]->encEnvData.domain_vec_noise, 1, + (eData[1].frame_info->nEnvelopes > 1 ? 2 : 1), 1, + sbrBitstreamData->HeaderActive); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + h_envChan[1]->encEnvData.sbr_noise_levels[i] = + eData[1].noise_level_coupling[i]; + + sbrHeaderData->coupling = 1; + + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 1; + + tempFlagLeft = h_envChan[0]->encEnvData.addHarmonicFlag; + tempFlagRight = h_envChan[1]->encEnvData.addHarmonicFlag; + + payloadbitsCOUPLING = FDKsbrEnc_CountSbrChannelPairElement( + sbrHeaderData, hParametricStereo, sbrBitstreamData, + &h_envChan[0]->encEnvData, &h_envChan[1]->encEnvData, hCmonData, + h_con->sbrSyntaxFlags); + + h_envChan[0]->encEnvData.addHarmonicFlag = tempFlagLeft; + h_envChan[1]->encEnvData.addHarmonicFlag = tempFlagRight; + + if (payloadbitsCOUPLING < payloadbitsLR) { + /* + copy coded coupling envelope and noise data to l/r + */ + for (ch = 0; ch < nChannels; ch++) { + SBR_ENV_TEMP_DATA *ed = &eData[ch]; + FDKmemcpy(ed->sfb_nrg, ed->sfb_nrg_coupling, + MAX_NUM_ENVELOPE_VALUES * sizeof(SCHAR)); + FDKmemcpy(ed->noise_level, ed->noise_level_coupling, + MAX_NUM_NOISE_VALUES * sizeof(SCHAR)); + } + + sbrHeaderData->coupling = 1; + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 1; + } else { + /* + restore saved l/r items + */ + for (ch = 0; ch < nChannels; ch++) { + FDKmemcpy(h_envChan[ch]->sbrCodeEnvelope.sfb_nrg_prev, + sfbNrgPrevTemp[ch], MAX_FREQ_COEFFS * sizeof(SCHAR)); + + h_envChan[ch]->sbrCodeEnvelope.upDate = upDateNrgTemp[ch]; + + FDKmemcpy(h_envChan[ch]->sbrCodeNoiseFloor.sfb_nrg_prev, + noisePrevTemp[ch], MAX_NUM_NOISE_COEFFS * sizeof(SCHAR)); + + FDKmemcpy(h_envChan[ch]->encEnvData.domain_vec, domainVecTemp[ch], + sizeof(INT) * MAX_ENVELOPES); + FDKmemcpy(h_envChan[ch]->encEnvData.domain_vec_noise, + domainVecNoiseTemp[ch], sizeof(INT) * MAX_ENVELOPES); + + h_envChan[ch]->sbrCodeNoiseFloor.upDate = upDateNoiseTemp[ch]; + } + + sbrHeaderData->coupling = 0; + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 0; + } + } break; + } /* switch */ + + /* tell the envelope encoders how long it has been, since we last sent + a frame starting with a dF-coded envelope */ + if (stereoMode == SBR_MONO) { + if (h_envChan[0]->encEnvData.domain_vec[0] == TIME) + h_envChan[0]->sbrCodeEnvelope.dF_edge_incr_fac++; + else + h_envChan[0]->sbrCodeEnvelope.dF_edge_incr_fac = 0; + } else { + if (h_envChan[0]->encEnvData.domain_vec[0] == TIME || + h_envChan[1]->encEnvData.domain_vec[0] == TIME) { + h_envChan[0]->sbrCodeEnvelope.dF_edge_incr_fac++; + h_envChan[1]->sbrCodeEnvelope.dF_edge_incr_fac++; + } else { + h_envChan[0]->sbrCodeEnvelope.dF_edge_incr_fac = 0; + h_envChan[1]->sbrCodeEnvelope.dF_edge_incr_fac = 0; + } + } + + /* + Send the encoded data to the bitstream + */ + for (ch = 0; ch < nChannels; ch++) { + SBR_ENV_TEMP_DATA *ed = &eData[ch]; + c = 0; + for (i = 0; i < ed->nEnvelopes; i++) { + for (j = 0; j < h_envChan[ch]->encEnvData.noScfBands[i]; j++) { + h_envChan[ch]->encEnvData.ienvelope[i][j] = ed->sfb_nrg[c]; + + c++; + } + } + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) { + h_envChan[ch]->encEnvData.sbr_noise_levels[i] = ed->noise_level[i]; + } + } /* ch */ + + /* + Write bitstream + */ + if (nChannels == 2) { + FDKsbrEnc_WriteEnvChannelPairElement( + sbrHeaderData, hParametricStereo, sbrBitstreamData, + &h_envChan[0]->encEnvData, &h_envChan[1]->encEnvData, hCmonData, + h_con->sbrSyntaxFlags); + } else { + FDKsbrEnc_WriteEnvSingleChannelElement( + sbrHeaderData, hParametricStereo, sbrBitstreamData, + &h_envChan[0]->encEnvData, hCmonData, h_con->sbrSyntaxFlags); + } + + /* + * Update buffers. + */ + for (ch = 0; ch < nChannels; ch++) { + int YBufferLength = h_envChan[ch]->sbrExtractEnvelope.no_cols >> + h_envChan[ch]->sbrExtractEnvelope.YBufferSzShift; + for (i = 0; i < h_envChan[ch]->sbrExtractEnvelope.YBufferWriteOffset; i++) { + FDKmemcpy(h_envChan[ch]->sbrExtractEnvelope.YBuffer[i], + h_envChan[ch]->sbrExtractEnvelope.YBuffer[i + YBufferLength], + sizeof(FIXP_DBL) * 64); + } + h_envChan[ch]->sbrExtractEnvelope.YBufferScale[0] = + h_envChan[ch]->sbrExtractEnvelope.YBufferScale[1]; + } + + sbrHeaderData->prev_coupling = sbrHeaderData->coupling; +} + +/***************************************************************************/ +/*! + + \brief creates an envelope extractor handle + + \return error status + +****************************************************************************/ +INT FDKsbrEnc_CreateExtractSbrEnvelope(HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut, + INT channel, INT chInEl, + UCHAR *dynamic_RAM) { + INT i; + FIXP_DBL *rBuffer, *iBuffer; + INT n; + FIXP_DBL *YBufferDyn; + + FDKmemclear(hSbrCut, sizeof(SBR_EXTRACT_ENVELOPE)); + + if (NULL == (hSbrCut->p_YBuffer = GetRam_Sbr_envYBuffer(channel))) { + goto bail; + } + + for (i = 0; i < (32 >> 1); i++) { + hSbrCut->YBuffer[i] = hSbrCut->p_YBuffer + (i * 64); + } + YBufferDyn = GetRam_Sbr_envYBuffer(chInEl, dynamic_RAM); + for (n = 0; i < 32; i++, n++) { + hSbrCut->YBuffer[i] = YBufferDyn + (n * 64); + } + + rBuffer = GetRam_Sbr_envRBuffer(0, dynamic_RAM); + iBuffer = GetRam_Sbr_envIBuffer(0, dynamic_RAM); + + for (i = 0; i < 32; i++) { + hSbrCut->rBuffer[i] = rBuffer + (i * 64); + hSbrCut->iBuffer[i] = iBuffer + (i * 64); + } + + return 0; + +bail: + FDKsbrEnc_deleteExtractSbrEnvelope(hSbrCut); + + return -1; +} + +/***************************************************************************/ +/*! + + \brief Initialize an envelope extractor instance. + + \return error status + +****************************************************************************/ +INT FDKsbrEnc_InitExtractSbrEnvelope(HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut, + int no_cols, int no_rows, int start_index, + int time_slots, int time_step, + int tran_off, ULONG statesInitFlag, + int chInEl, UCHAR *dynamic_RAM, + UINT sbrSyntaxFlags) { + int YBufferLength, rBufferLength; + int i; + + if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + int off = TRANSIENT_OFFSET_LD; + hSbrCut->YBufferWriteOffset = (no_cols >> 1) + off * time_step; + } else { + hSbrCut->YBufferWriteOffset = tran_off * time_step; + } + hSbrCut->rBufferReadOffset = 0; + + YBufferLength = hSbrCut->YBufferWriteOffset + no_cols; + rBufferLength = no_cols; + + hSbrCut->pre_transient_info[0] = 0; + hSbrCut->pre_transient_info[1] = 0; + + hSbrCut->no_cols = no_cols; + hSbrCut->no_rows = no_rows; + hSbrCut->start_index = start_index; + + hSbrCut->time_slots = time_slots; + hSbrCut->time_step = time_step; + + FDK_ASSERT(no_rows <= 64); + + /* Use half the Energy values if time step is 2 or greater */ + if (time_step >= 2) + hSbrCut->YBufferSzShift = 1; + else + hSbrCut->YBufferSzShift = 0; + + YBufferLength >>= hSbrCut->YBufferSzShift; + hSbrCut->YBufferWriteOffset >>= hSbrCut->YBufferSzShift; + + FDK_ASSERT(YBufferLength <= 32); + + FIXP_DBL *YBufferDyn = GetRam_Sbr_envYBuffer(chInEl, dynamic_RAM); + INT n = 0; + for (i = (32 >> 1); i < 32; i++, n++) { + hSbrCut->YBuffer[i] = YBufferDyn + (n * 64); + } + + if (statesInitFlag) { + for (i = 0; i < YBufferLength; i++) { + FDKmemclear(hSbrCut->YBuffer[i], 64 * sizeof(FIXP_DBL)); + } + } + + for (i = 0; i < rBufferLength; i++) { + FDKmemclear(hSbrCut->rBuffer[i], 64 * sizeof(FIXP_DBL)); + FDKmemclear(hSbrCut->iBuffer[i], 64 * sizeof(FIXP_DBL)); + } + + FDKmemclear(hSbrCut->envelopeCompensation, sizeof(UCHAR) * MAX_FREQ_COEFFS); + + if (statesInitFlag) { + hSbrCut->YBufferScale[0] = hSbrCut->YBufferScale[1] = FRACT_BITS - 1; + } + + return (0); +} + +/***************************************************************************/ +/*! + + \brief deinitializes an envelope extractor handle + + \return void + +****************************************************************************/ + +void FDKsbrEnc_deleteExtractSbrEnvelope(HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut) { + if (hSbrCut) { + FreeRam_Sbr_envYBuffer(&hSbrCut->p_YBuffer); + } +} + +INT FDKsbrEnc_GetEnvEstDelay(HANDLE_SBR_EXTRACT_ENVELOPE hSbr) { + return hSbr->no_rows * + ((hSbr->YBufferWriteOffset) * + 2 /* mult 2 because nrg's are grouped half */ + - hSbr->rBufferReadOffset); /* in reference hold half spec and calc + nrg's on overlapped spec */ +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_est.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_est.h new file mode 100644 index 0000000000000..006f55bf21454 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/env_est.h @@ -0,0 +1,223 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Envelope estimation structs and prototypes $Revision: 92790 $ +*/ +#ifndef ENV_EST_H +#define ENV_EST_H + +#include "sbr_def.h" +#include "sbr_encoder.h" /* SBR econfig structs */ +#include "ps_main.h" +#include "bit_sbr.h" +#include "fram_gen.h" +#include "tran_det.h" +#include "code_env.h" +#include "ton_corr.h" + +typedef struct { + FIXP_DBL *rBuffer[32]; + FIXP_DBL *iBuffer[32]; + + FIXP_DBL *p_YBuffer; + + FIXP_DBL *YBuffer[32]; + int YBufferScale[2]; + + UCHAR envelopeCompensation[MAX_FREQ_COEFFS]; + UCHAR pre_transient_info[2]; + + int YBufferWriteOffset; + int YBufferSzShift; + int rBufferReadOffset; + + int no_cols; + int no_rows; + int start_index; + + int time_slots; + int time_step; +} SBR_EXTRACT_ENVELOPE; +typedef SBR_EXTRACT_ENVELOPE *HANDLE_SBR_EXTRACT_ENVELOPE; + +struct ENV_CHANNEL { + FAST_TRAN_DETECTOR sbrFastTransientDetector; + SBR_TRANSIENT_DETECTOR sbrTransientDetector; + SBR_CODE_ENVELOPE sbrCodeEnvelope; + SBR_CODE_ENVELOPE sbrCodeNoiseFloor; + SBR_EXTRACT_ENVELOPE sbrExtractEnvelope; + + SBR_ENVELOPE_FRAME SbrEnvFrame; + SBR_TON_CORR_EST TonCorr; + + struct SBR_ENV_DATA encEnvData; + + int qmfScale; + UCHAR fLevelProtect; +}; +typedef struct ENV_CHANNEL *HANDLE_ENV_CHANNEL; + +/************ Function Declarations ***************/ + +INT FDKsbrEnc_CreateExtractSbrEnvelope(HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut, + INT channel, INT chInEl, + UCHAR *dynamic_RAM); + +INT FDKsbrEnc_InitExtractSbrEnvelope(HANDLE_SBR_EXTRACT_ENVELOPE hSbr, + int no_cols, int no_rows, int start_index, + int time_slots, int time_step, + int tran_off, ULONG statesInitFlag, + int chInEl, UCHAR *dynamic_RAM, + UINT sbrSyntaxFlags); + +void FDKsbrEnc_deleteExtractSbrEnvelope(HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut); + +typedef struct { + FREQ_RES res[MAX_NUM_NOISE_VALUES]; + int maxQuantError; + +} SBR_FRAME_TEMP_DATA; + +typedef struct { + const SBR_FRAME_INFO *frame_info; + FIXP_DBL noiseFloor[MAX_NUM_NOISE_VALUES]; + SCHAR sfb_nrg_coupling + [MAX_NUM_ENVELOPE_VALUES]; /* only used if stereomode = SWITCH_L_R_C */ + SCHAR sfb_nrg[MAX_NUM_ENVELOPE_VALUES]; + SCHAR noise_level_coupling + [MAX_NUM_NOISE_VALUES]; /* only used if stereomode = SWITCH_L_R_C */ + SCHAR noise_level[MAX_NUM_NOISE_VALUES]; + UCHAR transient_info[3]; + UCHAR nEnvelopes; +} SBR_ENV_TEMP_DATA; + +/* + * Extract features from QMF data. Afterwards, the QMF data is not required + * anymore. + */ +void FDKsbrEnc_extractSbrEnvelope1(HANDLE_SBR_CONFIG_DATA h_con, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_ENV_CHANNEL h_envChan, + HANDLE_COMMON_DATA cmonData, + SBR_ENV_TEMP_DATA *eData, + SBR_FRAME_TEMP_DATA *fData); + +/* + * Process the previously features extracted by FDKsbrEnc_extractSbrEnvelope1 + * and create/encode SBR envelopes. + */ +void FDKsbrEnc_extractSbrEnvelope2(HANDLE_SBR_CONFIG_DATA h_con, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_ENV_CHANNEL sbrEnvChannel0, + HANDLE_ENV_CHANNEL sbrEnvChannel1, + HANDLE_COMMON_DATA cmonData, + SBR_ENV_TEMP_DATA *eData, + SBR_FRAME_TEMP_DATA *fData, int clearOutput); + +INT FDKsbrEnc_GetEnvEstDelay(HANDLE_SBR_EXTRACT_ENVELOPE hSbr); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/fram_gen.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/fram_gen.cpp new file mode 100644 index 0000000000000..7ed6e79fff107 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/fram_gen.cpp @@ -0,0 +1,1965 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "fram_gen.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +static const SBR_FRAME_INFO frameInfo1_2048 = {1, {0, 16}, {FREQ_RES_HIGH}, + 0, 1, {0, 16}}; + +static const SBR_FRAME_INFO frameInfo2_2048 = { + 2, {0, 8, 16}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 8, 16}}; + +static const SBR_FRAME_INFO frameInfo4_2048 = { + 4, + {0, 4, 8, 12, 16}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + {0, 8, 16}}; + +static const SBR_FRAME_INFO frameInfo1_2304 = {1, {0, 18}, {FREQ_RES_HIGH}, + 0, 1, {0, 18}}; + +static const SBR_FRAME_INFO frameInfo2_2304 = { + 2, {0, 9, 18}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 9, 18}}; + +static const SBR_FRAME_INFO frameInfo4_2304 = { + 4, + {0, 5, 9, 14, 18}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + {0, 9, 18}}; + +static const SBR_FRAME_INFO frameInfo1_1920 = {1, {0, 15}, {FREQ_RES_HIGH}, + 0, 1, {0, 15}}; + +static const SBR_FRAME_INFO frameInfo2_1920 = { + 2, {0, 8, 15}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 8, 15}}; + +static const SBR_FRAME_INFO frameInfo4_1920 = { + 4, + {0, 4, 8, 12, 15}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + {0, 8, 15}}; + +static const SBR_FRAME_INFO frameInfo1_1152 = {1, {0, 9}, {FREQ_RES_HIGH}, + 0, 1, {0, 9}}; + +static const SBR_FRAME_INFO frameInfo2_1152 = { + 2, {0, 5, 9}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 5, 9}}; + +static const SBR_FRAME_INFO frameInfo4_1152 = { + 4, + {0, 2, 5, 7, 9}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + {0, 5, 9}}; + +/* AACLD frame info */ +static const SBR_FRAME_INFO frameInfo1_512LD = {1, {0, 8}, {FREQ_RES_HIGH}, + 0, 1, {0, 8}}; + +static const SBR_FRAME_INFO frameInfo2_512LD = { + 2, {0, 4, 8}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 4, 8}}; + +static const SBR_FRAME_INFO frameInfo4_512LD = { + 4, + {0, 2, 4, 6, 8}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + {0, 4, 8}}; + +static int calcFillLengthMax( + int tranPos, /*!< input : transient position (ref: tran det) */ + int numberTimeSlots /*!< input : number of timeslots */ +); + +static void fillFrameTran( + const int *v_tuningSegm, /*!< tuning: desired segment lengths */ + const int *v_tuningFreq, /*!< tuning: desired frequency resolutions */ + int tran, /*!< input : position of transient */ + int *v_bord, /*!< memNew: borders */ + int *length_v_bord, /*!< memNew: # borders */ + int *v_freq, /*!< memNew: frequency resolutions */ + int *length_v_freq, /*!< memNew: # frequency resolutions */ + int *bmin, /*!< hlpNew: first mandatory border */ + int *bmax /*!< hlpNew: last mandatory border */ +); + +static void fillFramePre(INT dmax, INT *v_bord, INT *length_v_bord, INT *v_freq, + INT *length_v_freq, INT bmin, INT rest); + +static void fillFramePost(INT *parts, INT *d, INT dmax, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT *length_v_freq, + INT bmax, INT bufferFrameStart, INT numberTimeSlots, + INT fmax); + +static void fillFrameInter(INT *nL, const int *v_tuningSegm, INT *v_bord, + INT *length_v_bord, INT bmin, INT *v_freq, + INT *length_v_freq, INT *v_bordFollow, + INT *length_v_bordFollow, INT *v_freqFollow, + INT *length_v_freqFollow, INT i_fillFollow, INT dmin, + INT dmax, INT numberTimeSlots); + +static void calcFrameClass(FRAME_CLASS *frameClass, FRAME_CLASS *frameClassOld, + INT tranFlag, INT *spreadFlag); + +static void specialCase(INT *spreadFlag, INT allowSpread, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT *length_v_freq, + INT *parts, INT d); + +static void calcCmonBorder(INT *i_cmon, INT *i_tran, INT *v_bord, + INT *length_v_bord, INT tran, INT bufferFrameStart, + INT numberTimeSlots); + +static void keepForFollowUp(INT *v_bordFollow, INT *length_v_bordFollow, + INT *v_freqFollow, INT *length_v_freqFollow, + INT *i_tranFollow, INT *i_fillFollow, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT i_cmon, + INT i_tran, INT parts, INT numberTimeSlots); + +static void calcCtrlSignal(HANDLE_SBR_GRID hSbrGrid, FRAME_CLASS frameClass, + INT *v_bord, INT length_v_bord, INT *v_freq, + INT length_v_freq, INT i_cmon, INT i_tran, + INT spreadFlag, INT nL); + +static void ctrlSignal2FrameInfo(HANDLE_SBR_GRID hSbrGrid, + HANDLE_SBR_FRAME_INFO hFrameInfo, + FREQ_RES *freq_res_fixfix); + +/* table for 8 time slot index */ +static const int envelopeTable_8[8][5] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* borders from left to right side; -1 = not in use */ + /*[|T-|------]*/ {2, 0, 0, 1, -1}, + /*[|-T-|-----]*/ {2, 0, 0, 2, -1}, + /*[--|T-|----]*/ {3, 1, 1, 2, 4}, + /*[---|T-|---]*/ {3, 1, 1, 3, 5}, + /*[----|T-|--]*/ {3, 1, 1, 4, 6}, + /*[-----|T--|]*/ {2, 1, 1, 5, -1}, + /*[------|T-|]*/ {2, 1, 1, 6, -1}, + /*[-------|T|]*/ {2, 1, 1, 7, -1}, +}; + +/* table for 16 time slot index */ +static const int envelopeTable_16[16][6] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* length from left to right side; -1 = not in use */ + /*[|T---|------------|]*/ {2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------|]*/ {2, 0, 0, 5, -1, -1}, + /*[|--|T---|----------]*/ {3, 1, 1, 2, 6, -1}, + /*[|---|T---|---------]*/ {3, 1, 1, 3, 7, -1}, + /*[|----|T---|--------]*/ {3, 1, 1, 4, 8, -1}, + /*[|-----|T---|-------]*/ {3, 1, 1, 5, 9, -1}, + /*[|------|T---|------]*/ {3, 1, 1, 6, 10, -1}, + /*[|-------|T---|-----]*/ {3, 1, 1, 7, 11, -1}, + /*[|--------|T---|----]*/ {3, 1, 1, 8, 12, -1}, + /*[|---------|T---|---]*/ {3, 1, 1, 9, 13, -1}, + /*[|----------|T---|--]*/ {3, 1, 1, 10, 14, -1}, + /*[|-----------|T----|]*/ {2, 1, 1, 11, -1, -1}, + /*[|------------|T---|]*/ {2, 1, 1, 12, -1, -1}, + /*[|-------------|T--|]*/ {2, 1, 1, 13, -1, -1}, + /*[|--------------|T-|]*/ {2, 1, 1, 14, -1, -1}, + /*[|---------------|T|]*/ {2, 1, 1, 15, -1, -1}, +}; + +/* table for 15 time slot index */ +static const int envelopeTable_15[15][6] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* length from left to right side; -1 = not in use */ + /*[|T---|------------]*/ {2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------]*/ {2, 0, 0, 5, -1, -1}, + /*[|--|T---|---------]*/ {3, 1, 1, 2, 6, -1}, + /*[|---|T---|--------]*/ {3, 1, 1, 3, 7, -1}, + /*[|----|T---|-------]*/ {3, 1, 1, 4, 8, -1}, + /*[|-----|T---|------]*/ {3, 1, 1, 5, 9, -1}, + /*[|------|T---|-----]*/ {3, 1, 1, 6, 10, -1}, + /*[|-------|T---|----]*/ {3, 1, 1, 7, 11, -1}, + /*[|--------|T---|---]*/ {3, 1, 1, 8, 12, -1}, + /*[|---------|T---|--]*/ {3, 1, 1, 9, 13, -1}, + /*[|----------|T----|]*/ {2, 1, 1, 10, -1, -1}, + /*[|-----------|T---|]*/ {2, 1, 1, 11, -1, -1}, + /*[|------------|T--|]*/ {2, 1, 1, 12, -1, -1}, + /*[|-------------|T-|]*/ {2, 1, 1, 13, -1, -1}, + /*[|--------------|T|]*/ {2, 1, 1, 14, -1, -1}, +}; + +static const int minFrameTranDistance = 4; + +static const FREQ_RES freqRes_table_8[] = { + FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, + FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}; + +static const FREQ_RES freqRes_table_16[16] = { + /* size of envelope */ + /* 0-4 */ FREQ_RES_LOW, + FREQ_RES_LOW, + FREQ_RES_LOW, + FREQ_RES_LOW, + FREQ_RES_LOW, + /* 5-9 */ FREQ_RES_LOW, + FREQ_RES_HIGH, + FREQ_RES_HIGH, + FREQ_RES_HIGH, + FREQ_RES_HIGH, + /* 10-16 */ FREQ_RES_HIGH, + FREQ_RES_HIGH, + FREQ_RES_HIGH, + FREQ_RES_HIGH, + FREQ_RES_HIGH, + FREQ_RES_HIGH}; + +static void generateFixFixOnly(HANDLE_SBR_FRAME_INFO hSbrFrameInfo, + HANDLE_SBR_GRID hSbrGrid, int tranPosInternal, + int numberTimeSlots, UCHAR fResTransIsLow); + +/*! + Functionname: FDKsbrEnc_frameInfoGenerator + + Description: produces the FRAME_INFO struct for the current frame + + Arguments: hSbrEnvFrame - pointer to sbr envelope handle + v_pre_transient_info - pointer to transient info vector + v_transient_info - pointer to previous transient info +vector v_tuning - pointer to tuning vector + + Return: frame_info - pointer to SBR_FRAME_INFO struct + +*******************************************************************************/ +HANDLE_SBR_FRAME_INFO +FDKsbrEnc_frameInfoGenerator(HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + UCHAR *v_transient_info, const INT rightBorderFIX, + UCHAR *v_transient_info_pre, int ldGrid, + const int *v_tuning) { + INT numEnv, tranPosInternal = 0, bmin = 0, bmax = 0, parts, d, i_cmon = 0, + i_tran = 0, nL; + INT fmax = 0; + + INT *v_bord = hSbrEnvFrame->v_bord; + INT *v_freq = hSbrEnvFrame->v_freq; + INT *v_bordFollow = hSbrEnvFrame->v_bordFollow; + INT *v_freqFollow = hSbrEnvFrame->v_freqFollow; + + INT *length_v_bordFollow = &hSbrEnvFrame->length_v_bordFollow; + INT *length_v_freqFollow = &hSbrEnvFrame->length_v_freqFollow; + INT *length_v_bord = &hSbrEnvFrame->length_v_bord; + INT *length_v_freq = &hSbrEnvFrame->length_v_freq; + INT *spreadFlag = &hSbrEnvFrame->spreadFlag; + INT *i_tranFollow = &hSbrEnvFrame->i_tranFollow; + INT *i_fillFollow = &hSbrEnvFrame->i_fillFollow; + FRAME_CLASS *frameClassOld = &hSbrEnvFrame->frameClassOld; + FRAME_CLASS frameClass = FIXFIX; + + INT allowSpread = hSbrEnvFrame->allowSpread; + INT numEnvStatic = hSbrEnvFrame->numEnvStatic; + INT staticFraming = hSbrEnvFrame->staticFraming; + INT dmin = hSbrEnvFrame->dmin; + INT dmax = hSbrEnvFrame->dmax; + + INT bufferFrameStart = hSbrEnvFrame->SbrGrid.bufferFrameStart; + INT numberTimeSlots = hSbrEnvFrame->SbrGrid.numberTimeSlots; + INT frameMiddleSlot = hSbrEnvFrame->frameMiddleSlot; + + INT tranPos = v_transient_info[0]; + INT tranFlag = v_transient_info[1]; + + const int *v_tuningSegm = v_tuning; + const int *v_tuningFreq = v_tuning + 3; + + hSbrEnvFrame->v_tuningSegm = v_tuningSegm; + + if (ldGrid) { + /* in case there was a transient at the very end of the previous frame, + * start with a transient envelope */ + if (!tranFlag && v_transient_info_pre[1] && + (numberTimeSlots - v_transient_info_pre[0] < minFrameTranDistance)) { + tranFlag = 1; + tranPos = 0; + } + } + + /* + * Synopsis: + * + * The frame generator creates the time-/frequency-grid for one SBR frame. + * Input signals are provided by the transient detector and the frame + * splitter (transientDetectNew() & FrameSplitter() in tran_det.c). The + * framing is controlled by adjusting tuning parameters stored in + * FRAME_GEN_TUNING. The parameter values are dependent on frame lengths + * and bitrates, and may in the future be signal dependent. + * + * The envelope borders are stored for frame generator internal use in + * aBorders. The contents of aBorders represent positions along the time + * axis given in the figures in fram_gen.h (the "frame-generator" rows). + * The unit is "time slot". The figures in fram_gen.h also define the + * detection ranges for the transient detector. For every border in + * aBorders, there is a corresponding entry in aFreqRes, which defines the + * frequency resolution of the envelope following (delimited by) the + * border. + * + * When no transients are present, FIXFIX class frames are used. The + * frame splitter decides whether to use one or two envelopes in the + * FIXFIX frame. "Sparse transients" (separated by a few frames without + * transients) are handeled by [FIXVAR, VARFIX] pairs or (depending on + * tuning and transient position relative the nominal frame boundaries) + * by [FIXVAR, VARVAR, VARFIX] triples. "Tight transients" (in + * consecutive frames) are handeled by [..., VARVAR, VARVAR, ...] + * sequences. + * + * The generator assumes that transients are "sparse", and designs + * borders for [FIXVAR, VARFIX] pairs right away, where the first frame + * corresponds to the present frame. At the next call of the generator + * it is known whether the transient actually is "sparse" or not. If + * 'yes', the already calculated VARFIX borders are used. If 'no', new + * borders, meeting the requirements of the "tight" transient, are + * calculated. + * + * The generator produces two outputs: A "clear-text bitstream" stored in + * SBR_GRID, and a straight-forward representation of the grid stored in + * SBR_FRAME_INFO. The former is subsequently converted to the actual + * bitstream sbr_grid() (encodeSbrGrid() in bit_sbr.c). The latter is + * used by other encoder functions, such as the envelope estimator + * (calculateSbrEnvelope() in env_est.c) and the noise floor and missing + * harmonics detector (TonCorrParamExtr() in nf_est.c). + */ + + if (staticFraming) { + /*-------------------------------------------------------------------------- + Ignore transient detector + ---------------------------------------------------------------------------*/ + + frameClass = FIXFIX; + numEnv = numEnvStatic; /* {1,2,4,8} */ + *frameClassOld = FIXFIX; /* for change to dyn */ + hSbrEnvFrame->SbrGrid.bs_num_env = numEnv; + hSbrEnvFrame->SbrGrid.frameClass = frameClass; + } else { + /*-------------------------------------------------------------------------- + Calculate frame class to use + ---------------------------------------------------------------------------*/ + if (rightBorderFIX) { + tranFlag = 0; + *spreadFlag = 0; + } + calcFrameClass(&frameClass, frameClassOld, tranFlag, spreadFlag); + + /* patch for new frame class FIXFIXonly for AAC LD */ + if (tranFlag && ldGrid) { + frameClass = FIXFIXonly; + *frameClassOld = FIXFIX; + } + + /* + * every transient is processed below by inserting + * + * - one border at the onset of the transient + * - one or more "decay borders" (after the onset of the transient) + * - optionally one "attack border" (before the onset of the transient) + * + * those borders are referred to as "mandatory borders" and are + * defined by the 'segmentLength' array in FRAME_GEN_TUNING + * + * the frequency resolutions of the corresponding envelopes are + * defined by the 'segmentRes' array in FRAME_GEN_TUNING + */ + + /*-------------------------------------------------------------------------- + Design frame (or follow-up old design) + ---------------------------------------------------------------------------*/ + if (tranFlag) { + /* Always for FixVar, often but not always for VarVar */ + + /*-------------------------------------------------------------------------- + Design part of T/F-grid around the new transient + ---------------------------------------------------------------------------*/ + + tranPosInternal = + frameMiddleSlot + tranPos + bufferFrameStart; /* FH 00-06-26 */ + /* + add mandatory borders around transient + */ + + fillFrameTran(v_tuningSegm, v_tuningFreq, tranPosInternal, v_bord, + length_v_bord, v_freq, length_v_freq, &bmin, &bmax); + + /* make sure we stay within the maximum SBR frame overlap */ + fmax = calcFillLengthMax(tranPos, numberTimeSlots); + } + + switch (frameClass) { + case FIXFIXonly: + FDK_ASSERT(ldGrid); + tranPosInternal = tranPos; + generateFixFixOnly(&(hSbrEnvFrame->SbrFrameInfo), + &(hSbrEnvFrame->SbrGrid), tranPosInternal, + numberTimeSlots, hSbrEnvFrame->fResTransIsLow); + + return &(hSbrEnvFrame->SbrFrameInfo); + + case FIXVAR: + + /*-------------------------------------------------------------------------- + Design remaining parts of T/F-grid (assuming next frame is VarFix) + ---------------------------------------------------------------------------*/ + + /*-------------------------------------------------------------------------- + Fill region before new transient: + ---------------------------------------------------------------------------*/ + fillFramePre(dmax, v_bord, length_v_bord, v_freq, length_v_freq, bmin, + bmin - bufferFrameStart); /* FH 00-06-26 */ + + /*-------------------------------------------------------------------------- + Fill region after new transient: + ---------------------------------------------------------------------------*/ + fillFramePost(&parts, &d, dmax, v_bord, length_v_bord, v_freq, + length_v_freq, bmax, bufferFrameStart, numberTimeSlots, + fmax); + + /*-------------------------------------------------------------------------- + Take care of special case: + ---------------------------------------------------------------------------*/ + if (parts == 1 && d < dmin) /* no fill, short last envelope */ + specialCase(spreadFlag, allowSpread, v_bord, length_v_bord, v_freq, + length_v_freq, &parts, d); + + /*-------------------------------------------------------------------------- + Calculate common border (split-point) + ---------------------------------------------------------------------------*/ + calcCmonBorder(&i_cmon, &i_tran, v_bord, length_v_bord, tranPosInternal, + bufferFrameStart, numberTimeSlots); /* FH 00-06-26 */ + + /*-------------------------------------------------------------------------- + Extract data for proper follow-up in next frame + ---------------------------------------------------------------------------*/ + keepForFollowUp(v_bordFollow, length_v_bordFollow, v_freqFollow, + length_v_freqFollow, i_tranFollow, i_fillFollow, v_bord, + length_v_bord, v_freq, i_cmon, i_tran, parts, + numberTimeSlots); /* FH 00-06-26 */ + + /*-------------------------------------------------------------------------- + Calculate control signal + ---------------------------------------------------------------------------*/ + calcCtrlSignal(&hSbrEnvFrame->SbrGrid, frameClass, v_bord, + *length_v_bord, v_freq, *length_v_freq, i_cmon, i_tran, + *spreadFlag, DC); + break; + case VARFIX: + /*-------------------------------------------------------------------------- + Follow-up old transient - calculate control signal + ---------------------------------------------------------------------------*/ + calcCtrlSignal(&hSbrEnvFrame->SbrGrid, frameClass, v_bordFollow, + *length_v_bordFollow, v_freqFollow, *length_v_freqFollow, + DC, *i_tranFollow, *spreadFlag, DC); + break; + case VARVAR: + if (*spreadFlag) { /* spread across three frames */ + /*-------------------------------------------------------------------------- + Follow-up old transient - calculate control signal + ---------------------------------------------------------------------------*/ + calcCtrlSignal(&hSbrEnvFrame->SbrGrid, frameClass, v_bordFollow, + *length_v_bordFollow, v_freqFollow, + *length_v_freqFollow, DC, *i_tranFollow, *spreadFlag, + DC); + + *spreadFlag = 0; + + /*-------------------------------------------------------------------------- + Extract data for proper follow-up in next frame + ---------------------------------------------------------------------------*/ + v_bordFollow[0] = hSbrEnvFrame->SbrGrid.bs_abs_bord_1 - + numberTimeSlots; /* FH 00-06-26 */ + v_freqFollow[0] = 1; + *length_v_bordFollow = 1; + *length_v_freqFollow = 1; + + *i_tranFollow = -DC; + *i_fillFollow = -DC; + } else { + /*-------------------------------------------------------------------------- + Design remaining parts of T/F-grid (assuming next frame is VarFix) + adapt or fill region before new transient: + ---------------------------------------------------------------------------*/ + fillFrameInter(&nL, v_tuningSegm, v_bord, length_v_bord, bmin, v_freq, + length_v_freq, v_bordFollow, length_v_bordFollow, + v_freqFollow, length_v_freqFollow, *i_fillFollow, dmin, + dmax, numberTimeSlots); + + /*-------------------------------------------------------------------------- + Fill after transient: + ---------------------------------------------------------------------------*/ + fillFramePost(&parts, &d, dmax, v_bord, length_v_bord, v_freq, + length_v_freq, bmax, bufferFrameStart, numberTimeSlots, + fmax); + + /*-------------------------------------------------------------------------- + Take care of special case: + ---------------------------------------------------------------------------*/ + if (parts == 1 && d < dmin) /*% no fill, short last envelope */ + specialCase(spreadFlag, allowSpread, v_bord, length_v_bord, v_freq, + length_v_freq, &parts, d); + + /*-------------------------------------------------------------------------- + Calculate common border (split-point) + ---------------------------------------------------------------------------*/ + calcCmonBorder(&i_cmon, &i_tran, v_bord, length_v_bord, + tranPosInternal, bufferFrameStart, numberTimeSlots); + + /*-------------------------------------------------------------------------- + Extract data for proper follow-up in next frame + ---------------------------------------------------------------------------*/ + keepForFollowUp(v_bordFollow, length_v_bordFollow, v_freqFollow, + length_v_freqFollow, i_tranFollow, i_fillFollow, + v_bord, length_v_bord, v_freq, i_cmon, i_tran, parts, + numberTimeSlots); + + /*-------------------------------------------------------------------------- + Calculate control signal + ---------------------------------------------------------------------------*/ + calcCtrlSignal(&hSbrEnvFrame->SbrGrid, frameClass, v_bord, + *length_v_bord, v_freq, *length_v_freq, i_cmon, i_tran, + 0, nL); + } + break; + case FIXFIX: + if (tranPos == 0) + numEnv = 1; + else + numEnv = 2; + + hSbrEnvFrame->SbrGrid.bs_num_env = numEnv; + hSbrEnvFrame->SbrGrid.frameClass = frameClass; + + break; + default: + FDK_ASSERT(0); + } + } + + /*------------------------------------------------------------------------- + Convert control signal to frame info struct + ---------------------------------------------------------------------------*/ + ctrlSignal2FrameInfo(&hSbrEnvFrame->SbrGrid, &hSbrEnvFrame->SbrFrameInfo, + hSbrEnvFrame->freq_res_fixfix); + + return &hSbrEnvFrame->SbrFrameInfo; +} + +/***************************************************************************/ +/*! + \brief Gnerates frame info for FIXFIXonly frame class used for low delay + version + + \return nothing + ****************************************************************************/ +static void generateFixFixOnly(HANDLE_SBR_FRAME_INFO hSbrFrameInfo, + HANDLE_SBR_GRID hSbrGrid, int tranPosInternal, + int numberTimeSlots, UCHAR fResTransIsLow) { + int nEnv, i, k = 0, tranIdx; + const int *pTable = NULL; + const FREQ_RES *freqResTable = NULL; + + switch (numberTimeSlots) { + case 8: { + pTable = envelopeTable_8[tranPosInternal]; + } + freqResTable = freqRes_table_8; + break; + case 15: + pTable = envelopeTable_15[tranPosInternal]; + freqResTable = freqRes_table_16; + break; + case 16: + pTable = envelopeTable_16[tranPosInternal]; + freqResTable = freqRes_table_16; + break; + } + + /* look number of envolpes in table */ + nEnv = pTable[0]; + /* look up envolpe distribution in table */ + for (i = 1; i < nEnv; i++) hSbrFrameInfo->borders[i] = pTable[i + 2]; + + /* open and close frame border */ + hSbrFrameInfo->borders[0] = 0; + hSbrFrameInfo->borders[nEnv] = numberTimeSlots; + + /* adjust segment-frequency-resolution according to the segment-length */ + for (i = 0; i < nEnv; i++) { + k = hSbrFrameInfo->borders[i + 1] - hSbrFrameInfo->borders[i]; + if (!fResTransIsLow) + hSbrFrameInfo->freqRes[i] = freqResTable[k]; + else + hSbrFrameInfo->freqRes[i] = FREQ_RES_LOW; + + hSbrGrid->v_f[i] = hSbrFrameInfo->freqRes[i]; + } + + hSbrFrameInfo->nEnvelopes = nEnv; + hSbrFrameInfo->shortEnv = pTable[2]; + /* transient idx */ + tranIdx = pTable[1]; + + /* add noise floors */ + hSbrFrameInfo->bordersNoise[0] = 0; + hSbrFrameInfo->bordersNoise[1] = + hSbrFrameInfo->borders[tranIdx ? tranIdx : 1]; + hSbrFrameInfo->bordersNoise[2] = numberTimeSlots; + hSbrFrameInfo->nNoiseEnvelopes = 2; + + hSbrGrid->frameClass = FIXFIXonly; + hSbrGrid->bs_abs_bord = tranPosInternal; + hSbrGrid->bs_num_env = nEnv; +} + +/******************************************************************************* + Functionname: FDKsbrEnc_initFrameInfoGenerator + ******************************************************************************* + + Description: + + Arguments: hSbrEnvFrame - pointer to sbr envelope handle + allowSpread - commandline parameter + numEnvStatic - commandline parameter + staticFraming - commandline parameter + + Return: none + +*******************************************************************************/ +void FDKsbrEnc_initFrameInfoGenerator(HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + INT allowSpread, INT numEnvStatic, + INT staticFraming, INT timeSlots, + const FREQ_RES *freq_res_fixfix, + UCHAR fResTransIsLow, + INT ldGrid) { /* FH 00-06-26 */ + + FDKmemclear(hSbrEnvFrame, sizeof(SBR_ENVELOPE_FRAME)); + + /* Initialisation */ + hSbrEnvFrame->frameClassOld = FIXFIX; + hSbrEnvFrame->spreadFlag = 0; + + hSbrEnvFrame->allowSpread = allowSpread; + hSbrEnvFrame->numEnvStatic = numEnvStatic; + hSbrEnvFrame->staticFraming = staticFraming; + hSbrEnvFrame->freq_res_fixfix[0] = freq_res_fixfix[0]; + hSbrEnvFrame->freq_res_fixfix[1] = freq_res_fixfix[1]; + hSbrEnvFrame->fResTransIsLow = fResTransIsLow; + + hSbrEnvFrame->length_v_bord = 0; + hSbrEnvFrame->length_v_bordFollow = 0; + + hSbrEnvFrame->length_v_freq = 0; + hSbrEnvFrame->length_v_freqFollow = 0; + + hSbrEnvFrame->i_tranFollow = 0; + hSbrEnvFrame->i_fillFollow = 0; + + hSbrEnvFrame->SbrGrid.numberTimeSlots = timeSlots; + + if (ldGrid) { + /*case CODEC_AACLD:*/ + hSbrEnvFrame->dmin = 2; + hSbrEnvFrame->dmax = 16; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_512LD; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + } else + switch (timeSlots) { + case NUMBER_TIME_SLOTS_1920: + hSbrEnvFrame->dmin = 4; + hSbrEnvFrame->dmax = 12; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_1920; + break; + case NUMBER_TIME_SLOTS_2048: + hSbrEnvFrame->dmin = 4; + hSbrEnvFrame->dmax = 12; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_2048; + break; + case NUMBER_TIME_SLOTS_1152: + hSbrEnvFrame->dmin = 2; + hSbrEnvFrame->dmax = 8; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_1152; + break; + case NUMBER_TIME_SLOTS_2304: + hSbrEnvFrame->dmin = 4; + hSbrEnvFrame->dmax = 15; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_2304; + break; + default: + FDK_ASSERT(0); + } +} + +/******************************************************************************* + Functionname: fillFrameTran + ******************************************************************************* + + Description: Add mandatory borders, as described by the tuning vector + and the current transient position + + Arguments: + modified: + v_bord - int pointer to v_bord vector + length_v_bord - length of v_bord vector + v_freq - int pointer to v_freq vector + length_v_freq - length of v_freq vector + bmin - int pointer to bmin (call by reference) + bmax - int pointer to bmax (call by reference) + not modified: + tran - position of transient + v_tuningSegm - int pointer to v_tuningSegm vector + v_tuningFreq - int pointer to v_tuningFreq vector + + Return: none + +*******************************************************************************/ +static void fillFrameTran( + const int *v_tuningSegm, /*!< tuning: desired segment lengths */ + const int *v_tuningFreq, /*!< tuning: desired frequency resolutions */ + int tran, /*!< input : position of transient */ + int *v_bord, /*!< memNew: borders */ + int *length_v_bord, /*!< memNew: # borders */ + int *v_freq, /*!< memNew: frequency resolutions */ + int *length_v_freq, /*!< memNew: # frequency resolutions */ + int *bmin, /*!< hlpNew: first mandatory border */ + int *bmax /*!< hlpNew: last mandatory border */ +) { + int bord, i; + + *length_v_bord = 0; + *length_v_freq = 0; + + /* add attack env leading border (optional) */ + if (v_tuningSegm[0]) { + /* v_bord = [(Ba)] start of attack env */ + FDKsbrEnc_AddRight(v_bord, length_v_bord, (tran - v_tuningSegm[0])); + + /* v_freq = [(Fa)] res of attack env */ + FDKsbrEnc_AddRight(v_freq, length_v_freq, v_tuningFreq[0]); + } + + /* add attack env trailing border/first decay env leading border */ + bord = tran; + FDKsbrEnc_AddRight(v_bord, length_v_bord, tran); /* v_bord = [(Ba),Bd1] */ + + /* add first decay env trailing border/2:nd decay env leading border */ + if (v_tuningSegm[1]) { + bord += v_tuningSegm[1]; + + /* v_bord = [(Ba),Bd1,Bd2] */ + FDKsbrEnc_AddRight(v_bord, length_v_bord, bord); + + /* v_freq = [(Fa),Fd1] */ + FDKsbrEnc_AddRight(v_freq, length_v_freq, v_tuningFreq[1]); + } + + /* add 2:nd decay env trailing border (optional) */ + if (v_tuningSegm[2] != 0) { + bord += v_tuningSegm[2]; + + /* v_bord = [(Ba),Bd1, Bd2,(Bd3)] */ + FDKsbrEnc_AddRight(v_bord, length_v_bord, bord); + + /* v_freq = [(Fa),Fd1,(Fd2)] */ + FDKsbrEnc_AddRight(v_freq, length_v_freq, v_tuningFreq[2]); + } + + /* v_freq = [(Fa),Fd1,(Fd2),1] */ + FDKsbrEnc_AddRight(v_freq, length_v_freq, 1); + + /* calc min and max values of mandatory borders */ + *bmin = v_bord[0]; + for (i = 0; i < *length_v_bord; i++) + if (v_bord[i] < *bmin) *bmin = v_bord[i]; + + *bmax = v_bord[0]; + for (i = 0; i < *length_v_bord; i++) + if (v_bord[i] > *bmax) *bmax = v_bord[i]; +} + +/******************************************************************************* + Functionname: fillFramePre + ******************************************************************************* + + Description: Add borders before mandatory borders, if needed + + Arguments: + modified: + v_bord - int pointer to v_bord vector + length_v_bord - length of v_bord vector + v_freq - int pointer to v_freq vector + length_v_freq - length of v_freq vector + not modified: + dmax - int value + bmin - int value + rest - int value + + Return: none + +*******************************************************************************/ +static void fillFramePre(INT dmax, INT *v_bord, INT *length_v_bord, INT *v_freq, + INT *length_v_freq, INT bmin, INT rest) { + /* + input state: + v_bord = [(Ba),Bd1, Bd2 ,(Bd3)] + v_freq = [(Fa),Fd1,(Fd2),1 ] + */ + + INT parts, d, j, S, s = 0, segm, bord; + + /* + start with one envelope + */ + + parts = 1; + d = rest; + + /* + calc # of additional envelopes and corresponding lengths + */ + + while (d > dmax) { + parts++; + + segm = rest / parts; + S = (segm - 2) >> 1; + s = fixMin(8, 2 * S + 2); + d = rest - (parts - 1) * s; + } + + /* + add borders before mandatory borders + */ + + bord = bmin; + + for (j = 0; j <= parts - 2; j++) { + bord = bord - s; + + /* v_bord = [...,(Bf),(Ba),Bd1, Bd2 ,(Bd3)] */ + FDKsbrEnc_AddLeft(v_bord, length_v_bord, bord); + + /* v_freq = [...,(1 ),(Fa),Fd1,(Fd2), 1 ] */ + FDKsbrEnc_AddLeft(v_freq, length_v_freq, 1); + } +} + +/***************************************************************************/ +/*! + \brief Overlap control + + Calculate max length of trailing fill segments, such that we always get a + border within the frame overlap region + + \return void + +****************************************************************************/ +static int calcFillLengthMax( + int tranPos, /*!< input : transient position (ref: tran det) */ + int numberTimeSlots /*!< input : number of timeslots */ +) { + int fmax; + + /* + calculate transient position within envelope buffer + */ + switch (numberTimeSlots) { + case NUMBER_TIME_SLOTS_2048: + if (tranPos < 4) + fmax = 6; + else if (tranPos == 4 || tranPos == 5) + fmax = 4; + else + fmax = 8; + break; + + case NUMBER_TIME_SLOTS_1920: + if (tranPos < 4) + fmax = 5; + else if (tranPos == 4 || tranPos == 5) + fmax = 3; + else + fmax = 7; + break; + + default: + fmax = 8; + break; + } + + return fmax; +} + +/******************************************************************************* + Functionname: fillFramePost + ******************************************************************************* + + Description: -Add borders after mandatory borders, if needed + Make a preliminary design of next frame, + assuming no transient is present there + + Arguments: + modified: + parts - int pointer to parts (call by reference) + d - int pointer to d (call by reference) + v_bord - int pointer to v_bord vector + length_v_bord - length of v_bord vector + v_freq - int pointer to v_freq vector + length_v_freq - length of v_freq vector + not modified: + bmax - int value + dmax - int value + + Return: none + +*******************************************************************************/ +static void fillFramePost(INT *parts, INT *d, INT dmax, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT *length_v_freq, + INT bmax, INT bufferFrameStart, INT numberTimeSlots, + INT fmax) { + INT j, rest, segm, S, s = 0, bord; + + /* + input state: + v_bord = [...,(Bf),(Ba),Bd1, Bd2 ,(Bd3)] + v_freq = [...,(1 ),(Fa),Fd1,(Fd2),1 ] + */ + + rest = bufferFrameStart + 2 * numberTimeSlots - bmax; + *d = rest; + + if (*d > 0) { + *parts = 1; /* start with one envelope */ + + /* calc # of additional envelopes and corresponding lengths */ + + while (*d > dmax) { + *parts = *parts + 1; + + segm = rest / (*parts); + S = (segm - 2) >> 1; + s = fixMin(fmax, 2 * S + 2); + *d = rest - (*parts - 1) * s; + } + + /* add borders after mandatory borders */ + + bord = bmax; + for (j = 0; j <= *parts - 2; j++) { + bord += s; + + /* v_bord = [...,(Bf),(Ba),Bd1, Bd2 ,(Bd3),(Bf)] */ + FDKsbrEnc_AddRight(v_bord, length_v_bord, bord); + + /* v_freq = [...,(1 ),(Fa),Fd1,(Fd2), 1 , 1! ,1] */ + FDKsbrEnc_AddRight(v_freq, length_v_freq, 1); + } + } else { + *parts = 1; + + /* remove last element from v_bord and v_freq */ + + *length_v_bord = *length_v_bord - 1; + *length_v_freq = *length_v_freq - 1; + } +} + +/******************************************************************************* + Functionname: fillFrameInter + ******************************************************************************* + + Description: + + Arguments: nL - + v_tuningSegm - + v_bord - + length_v_bord - + bmin - + v_freq - + length_v_freq - + v_bordFollow - + length_v_bordFollow - + v_freqFollow - + length_v_freqFollow - + i_fillFollow - + dmin - + dmax - + + Return: none + +*******************************************************************************/ +static void fillFrameInter(INT *nL, const int *v_tuningSegm, INT *v_bord, + INT *length_v_bord, INT bmin, INT *v_freq, + INT *length_v_freq, INT *v_bordFollow, + INT *length_v_bordFollow, INT *v_freqFollow, + INT *length_v_freqFollow, INT i_fillFollow, INT dmin, + INT dmax, INT numberTimeSlots) { + INT middle, b_new, numBordFollow, bordMaxFollow, i; + + if (numberTimeSlots != NUMBER_TIME_SLOTS_1152) { + /* % remove fill borders: */ + if (i_fillFollow >= 1) { + *length_v_bordFollow = i_fillFollow; + *length_v_freqFollow = i_fillFollow; + } + + numBordFollow = *length_v_bordFollow; + bordMaxFollow = v_bordFollow[numBordFollow - 1]; + + /* remove even more borders if needed */ + middle = bmin - bordMaxFollow; + while (middle < 0) { + numBordFollow--; + bordMaxFollow = v_bordFollow[numBordFollow - 1]; + middle = bmin - bordMaxFollow; + } + + *length_v_bordFollow = numBordFollow; + *length_v_freqFollow = numBordFollow; + *nL = numBordFollow - 1; + + b_new = *length_v_bord; + + if (middle <= dmax) { + if (middle >= dmin) { /* concatenate */ + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + + else { + if (v_tuningSegm[0] != 0) { /* remove one new border and concatenate */ + *length_v_bord = b_new - 1; + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + + *length_v_freq = b_new - 1; + FDKsbrEnc_AddVecLeft(v_freq + 1, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } else { + if (*length_v_bordFollow > + 1) { /* remove one old border and concatenate */ + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow - 1); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_bordFollow - 1); + + *nL = *nL - 1; + } else { /* remove new "transient" border and concatenate */ + + for (i = 0; i < *length_v_bord - 1; i++) v_bord[i] = v_bord[i + 1]; + + for (i = 0; i < *length_v_freq - 1; i++) v_freq[i] = v_freq[i + 1]; + + *length_v_bord = b_new - 1; + *length_v_freq = b_new - 1; + + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + } + } + } else { /* middle > dmax */ + + fillFramePre(dmax, v_bord, length_v_bord, v_freq, length_v_freq, bmin, + middle); + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + + } else { /* numberTimeSlots==NUMBER_TIME_SLOTS_1152 */ + + INT l, m; + + /*------------------------------------------------------------------------ + remove fill borders + ------------------------------------------------------------------------*/ + if (i_fillFollow >= 1) { + *length_v_bordFollow = i_fillFollow; + *length_v_freqFollow = i_fillFollow; + } + + numBordFollow = *length_v_bordFollow; + bordMaxFollow = v_bordFollow[numBordFollow - 1]; + + /*------------------------------------------------------------------------ + remove more borders if necessary to eliminate overlap + ------------------------------------------------------------------------*/ + + /* check for overlap */ + middle = bmin - bordMaxFollow; + + /* intervals: + i) middle < 0 : overlap, must remove borders + ii) 0 <= middle < dmin : no overlap but too tight, must remove + borders iii) dmin <= middle <= dmax : ok, just concatenate iv) dmax + <= middle : too wide, must add borders + */ + + /* first remove old non-fill-borders... */ + while (middle < 0) { + /* ...but don't remove all of them */ + if (numBordFollow == 1) break; + + numBordFollow--; + bordMaxFollow = v_bordFollow[numBordFollow - 1]; + middle = bmin - bordMaxFollow; + } + + /* if this isn't enough, remove new non-fill borders */ + if (middle < 0) { + for (l = 0, m = 0; l < *length_v_bord; l++) { + if (v_bord[l] > bordMaxFollow) { + v_bord[m] = v_bord[l]; + v_freq[m] = v_freq[l]; + m++; + } + } + + *length_v_bord = l; + *length_v_freq = l; + + bmin = v_bord[0]; + } + + /*------------------------------------------------------------------------ + update modified follow-up data + ------------------------------------------------------------------------*/ + + *length_v_bordFollow = numBordFollow; + *length_v_freqFollow = numBordFollow; + + /* left relative borders correspond to follow-up */ + *nL = numBordFollow - 1; + + /*------------------------------------------------------------------------ + take care of intervals ii through iv + ------------------------------------------------------------------------*/ + + /* now middle should be >= 0 */ + middle = bmin - bordMaxFollow; + + if (middle <= dmin) /* (ii) */ + { + b_new = *length_v_bord; + + if (v_tuningSegm[0] != 0) { + /* remove new "luxury" border and concatenate */ + *length_v_bord = b_new - 1; + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + + *length_v_freq = b_new - 1; + FDKsbrEnc_AddVecLeft(v_freq + 1, length_v_freq, v_freqFollow, + *length_v_freqFollow); + + } else if (*length_v_bordFollow > 1) { + /* remove old border and concatenate */ + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow - 1); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_bordFollow - 1); + + *nL = *nL - 1; + } else { + /* remove new border and concatenate */ + for (i = 0; i < *length_v_bord - 1; i++) v_bord[i] = v_bord[i + 1]; + + for (i = 0; i < *length_v_freq - 1; i++) v_freq[i] = v_freq[i + 1]; + + *length_v_bord = b_new - 1; + *length_v_freq = b_new - 1; + + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + } else if ((middle >= dmin) && (middle <= dmax)) /* (iii) */ + { + /* concatenate */ + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + + } else /* (iv) */ + { + fillFramePre(dmax, v_bord, length_v_bord, v_freq, length_v_freq, bmin, + middle); + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + } +} + +/******************************************************************************* + Functionname: calcFrameClass + ******************************************************************************* + + Description: + + Arguments: INT* frameClass, INT* frameClassOld, INT tranFlag, INT* spreadFlag) + + Return: none + +*******************************************************************************/ +static void calcFrameClass(FRAME_CLASS *frameClass, FRAME_CLASS *frameClassOld, + INT tranFlag, INT *spreadFlag) { + switch (*frameClassOld) { + case FIXFIXonly: + case FIXFIX: + if (tranFlag) + *frameClass = FIXVAR; + else + *frameClass = FIXFIX; + break; + case FIXVAR: + if (tranFlag) { + *frameClass = VARVAR; + *spreadFlag = 0; + } else { + if (*spreadFlag) + *frameClass = VARVAR; + else + *frameClass = VARFIX; + } + break; + case VARFIX: + if (tranFlag) + *frameClass = FIXVAR; + else + *frameClass = FIXFIX; + break; + case VARVAR: + if (tranFlag) { + *frameClass = VARVAR; + *spreadFlag = 0; + } else { + if (*spreadFlag) + *frameClass = VARVAR; + else + *frameClass = VARFIX; + } + break; + }; + + *frameClassOld = *frameClass; +} + +/******************************************************************************* + Functionname: specialCase + ******************************************************************************* + + Description: + + Arguments: spreadFlag + allowSpread + v_bord + length_v_bord + v_freq + length_v_freq + parts + d + + Return: none + +*******************************************************************************/ +static void specialCase(INT *spreadFlag, INT allowSpread, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT *length_v_freq, + INT *parts, INT d) { + INT L; + + L = *length_v_bord; + + if (allowSpread) { /* add one "step 8" */ + *spreadFlag = 1; + FDKsbrEnc_AddRight(v_bord, length_v_bord, v_bord[L - 1] + 8); + FDKsbrEnc_AddRight(v_freq, length_v_freq, 1); + (*parts)++; + } else { + if (d == 1) { /* stretch one slot */ + *length_v_bord = L - 1; + *length_v_freq = L - 1; + } else { + if ((v_bord[L - 1] - v_bord[L - 2]) > 2) { /* compress one quant step */ + v_bord[L - 1] = v_bord[L - 1] - 2; + v_freq[*length_v_freq - 1] = 0; /* use low res for short segment */ + } + } + } +} + +/******************************************************************************* + Functionname: calcCmonBorder + ******************************************************************************* + + Description: + + Arguments: i_cmon + i_tran + v_bord + length_v_bord + tran + + Return: none + +*******************************************************************************/ +static void calcCmonBorder(INT *i_cmon, INT *i_tran, INT *v_bord, + INT *length_v_bord, INT tran, INT bufferFrameStart, + INT numberTimeSlots) { /* FH 00-06-26 */ + INT i; + + for (i = 0; i < *length_v_bord; i++) + if (v_bord[i] >= bufferFrameStart + numberTimeSlots) { /* FH 00-06-26 */ + *i_cmon = i; + break; + } + + /* keep track of transient: */ + for (i = 0; i < *length_v_bord; i++) + if (v_bord[i] >= tran) { + *i_tran = i; + break; + } else + *i_tran = EMPTY; +} + +/******************************************************************************* + Functionname: keepForFollowUp + ******************************************************************************* + + Description: + + Arguments: v_bordFollow + length_v_bordFollow + v_freqFollow + length_v_freqFollow + i_tranFollow + i_fillFollow + v_bord + length_v_bord + v_freq + i_cmon + i_tran + parts) + + Return: none + +*******************************************************************************/ +static void keepForFollowUp(INT *v_bordFollow, INT *length_v_bordFollow, + INT *v_freqFollow, INT *length_v_freqFollow, + INT *i_tranFollow, INT *i_fillFollow, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT i_cmon, + INT i_tran, INT parts, + INT numberTimeSlots) { /* FH 00-06-26 */ + INT L, i, j; + + L = *length_v_bord; + + (*length_v_bordFollow) = 0; + (*length_v_freqFollow) = 0; + + for (j = 0, i = i_cmon; i < L; i++, j++) { + v_bordFollow[j] = v_bord[i] - numberTimeSlots; /* FH 00-06-26 */ + v_freqFollow[j] = v_freq[i]; + (*length_v_bordFollow)++; + (*length_v_freqFollow)++; + } + if (i_tran != EMPTY) + *i_tranFollow = i_tran - i_cmon; + else + *i_tranFollow = EMPTY; + *i_fillFollow = L - (parts - 1) - i_cmon; +} + +/******************************************************************************* + Functionname: calcCtrlSignal + ******************************************************************************* + + Description: + + Arguments: hSbrGrid + frameClass + v_bord + length_v_bord + v_freq + length_v_freq + i_cmon + i_tran + spreadFlag + nL + + Return: none + +*******************************************************************************/ +static void calcCtrlSignal(HANDLE_SBR_GRID hSbrGrid, FRAME_CLASS frameClass, + INT *v_bord, INT length_v_bord, INT *v_freq, + INT length_v_freq, INT i_cmon, INT i_tran, + INT spreadFlag, INT nL) { + INT i, r, a, n, p, b, aL, aR, ntot, nmax, nR; + + INT *v_f = hSbrGrid->v_f; + INT *v_fLR = hSbrGrid->v_fLR; + INT *v_r = hSbrGrid->bs_rel_bord; + INT *v_rL = hSbrGrid->bs_rel_bord_0; + INT *v_rR = hSbrGrid->bs_rel_bord_1; + + INT length_v_r = 0; + INT length_v_rR = 0; + INT length_v_rL = 0; + + switch (frameClass) { + case FIXVAR: + /* absolute border: */ + + a = v_bord[i_cmon]; + + /* relative borders: */ + length_v_r = 0; + i = i_cmon; + + while (i >= 1) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight(v_r, &length_v_r, r); + i--; + } + + /* number of relative borders: */ + n = length_v_r; + + /* freq res: */ + for (i = 0; i < i_cmon; i++) v_f[i] = v_freq[i_cmon - 1 - i]; + v_f[i_cmon] = 1; + + /* pointer: */ + p = (i_cmon >= i_tran && i_tran != EMPTY) ? (i_cmon - i_tran + 1) : (0); + + hSbrGrid->frameClass = frameClass; + hSbrGrid->bs_abs_bord = a; + hSbrGrid->n = n; + hSbrGrid->p = p; + + break; + case VARFIX: + /* absolute border: */ + a = v_bord[0]; + + /* relative borders: */ + length_v_r = 0; + + for (i = 1; i < length_v_bord; i++) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight(v_r, &length_v_r, r); + } + + /* number of relative borders: */ + n = length_v_r; + + /* freq res: */ + FDKmemcpy(v_f, v_freq, length_v_freq * sizeof(INT)); + + /* pointer: */ + p = (i_tran >= 0 && i_tran != EMPTY) ? (i_tran + 1) : (0); + + hSbrGrid->frameClass = frameClass; + hSbrGrid->bs_abs_bord = a; + hSbrGrid->n = n; + hSbrGrid->p = p; + + break; + case VARVAR: + if (spreadFlag) { + /* absolute borders: */ + b = length_v_bord; + + aL = v_bord[0]; + aR = v_bord[b - 1]; + + /* number of relative borders: */ + ntot = b - 2; + + nmax = 2; /* n: {0,1,2} */ + if (ntot > nmax) { + nL = nmax; + nR = ntot - nmax; + } else { + nL = ntot; + nR = 0; + } + + /* relative borders: */ + length_v_rL = 0; + for (i = 1; i <= nL; i++) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight(v_rL, &length_v_rL, r); + } + + length_v_rR = 0; + i = b - 1; + while (i >= b - nR) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight(v_rR, &length_v_rR, r); + i--; + } + + /* pointer (only one due to constraint in frame info): */ + p = (i_tran > 0 && i_tran != EMPTY) ? (b - i_tran) : (0); + + /* freq res: */ + + for (i = 0; i < b - 1; i++) v_fLR[i] = v_freq[i]; + } else { + length_v_bord = i_cmon + 1; + + /* absolute borders: */ + b = length_v_bord; + + aL = v_bord[0]; + aR = v_bord[b - 1]; + + /* number of relative borders: */ + ntot = b - 2; + nR = ntot - nL; + + /* relative borders: */ + length_v_rL = 0; + for (i = 1; i <= nL; i++) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight(v_rL, &length_v_rL, r); + } + + length_v_rR = 0; + i = b - 1; + while (i >= b - nR) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight(v_rR, &length_v_rR, r); + i--; + } + + /* pointer (only one due to constraint in frame info): */ + p = (i_cmon >= i_tran && i_tran != EMPTY) ? (i_cmon - i_tran + 1) : (0); + + /* freq res: */ + for (i = 0; i < b - 1; i++) v_fLR[i] = v_freq[i]; + } + + hSbrGrid->frameClass = frameClass; + hSbrGrid->bs_abs_bord_0 = aL; + hSbrGrid->bs_abs_bord_1 = aR; + hSbrGrid->bs_num_rel_0 = nL; + hSbrGrid->bs_num_rel_1 = nR; + hSbrGrid->p = p; + + break; + + default: + /* do nothing */ + break; + } +} + +/******************************************************************************* + Functionname: createDefFrameInfo + ******************************************************************************* + + Description: Copies the default (static) frameInfo structs to the frameInfo + passed by reference; only used for FIXFIX frames + + Arguments: hFrameInfo - HANLDE_SBR_FRAME_INFO + nEnv - INT + nTimeSlots - INT + + Return: none; hSbrFrameInfo contains a copy of the default frameInfo + + Written: Andreas Schneider + Revised: +*******************************************************************************/ +static void createDefFrameInfo(HANDLE_SBR_FRAME_INFO hSbrFrameInfo, INT nEnv, + INT nTimeSlots) { + switch (nEnv) { + case 1: + switch (nTimeSlots) { + case NUMBER_TIME_SLOTS_1920: + FDKmemcpy(hSbrFrameInfo, &frameInfo1_1920, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2048: + FDKmemcpy(hSbrFrameInfo, &frameInfo1_2048, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_1152: + FDKmemcpy(hSbrFrameInfo, &frameInfo1_1152, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2304: + FDKmemcpy(hSbrFrameInfo, &frameInfo1_2304, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_512LD: + FDKmemcpy(hSbrFrameInfo, &frameInfo1_512LD, sizeof(SBR_FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 2: + switch (nTimeSlots) { + case NUMBER_TIME_SLOTS_1920: + FDKmemcpy(hSbrFrameInfo, &frameInfo2_1920, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2048: + FDKmemcpy(hSbrFrameInfo, &frameInfo2_2048, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_1152: + FDKmemcpy(hSbrFrameInfo, &frameInfo2_1152, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2304: + FDKmemcpy(hSbrFrameInfo, &frameInfo2_2304, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_512LD: + FDKmemcpy(hSbrFrameInfo, &frameInfo2_512LD, sizeof(SBR_FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 4: + switch (nTimeSlots) { + case NUMBER_TIME_SLOTS_1920: + FDKmemcpy(hSbrFrameInfo, &frameInfo4_1920, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2048: + FDKmemcpy(hSbrFrameInfo, &frameInfo4_2048, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_1152: + FDKmemcpy(hSbrFrameInfo, &frameInfo4_1152, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2304: + FDKmemcpy(hSbrFrameInfo, &frameInfo4_2304, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_512LD: + FDKmemcpy(hSbrFrameInfo, &frameInfo4_512LD, sizeof(SBR_FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + default: + FDK_ASSERT(0); + } +} + +/******************************************************************************* + Functionname: ctrlSignal2FrameInfo + ******************************************************************************* + + Description: Convert "clear-text" sbr_grid() to "frame info" used by the + envelope and noise floor estimators. + This is basically (except for "low level" calculations) the + bitstream decoder defined in the MPEG-4 standard, sub clause + 4.6.18.3.3, Time / Frequency Grid. See inline comments for + explanation of the shorten and noise border algorithms. + + Arguments: hSbrGrid - source + hSbrFrameInfo - destination + freq_res_fixfix - frequency resolution for FIXFIX frames + + Return: void; hSbrFrameInfo contains the updated FRAME_INFO struct + +*******************************************************************************/ +static void ctrlSignal2FrameInfo( + HANDLE_SBR_GRID hSbrGrid, /* input : the grid handle */ + HANDLE_SBR_FRAME_INFO hSbrFrameInfo, /* output: the frame info handle */ + FREQ_RES + *freq_res_fixfix /* in/out: frequency resolution for FIXFIX frames */ +) { + INT frameSplit = 0; + INT nEnv = 0, border = 0, i, k, p /*?*/; + INT *v_r = hSbrGrid->bs_rel_bord; + INT *v_f = hSbrGrid->v_f; + + FRAME_CLASS frameClass = hSbrGrid->frameClass; + INT bufferFrameStart = hSbrGrid->bufferFrameStart; + INT numberTimeSlots = hSbrGrid->numberTimeSlots; + + switch (frameClass) { + case FIXFIX: + createDefFrameInfo(hSbrFrameInfo, hSbrGrid->bs_num_env, numberTimeSlots); + + frameSplit = (hSbrFrameInfo->nEnvelopes > 1); + for (i = 0; i < hSbrFrameInfo->nEnvelopes; i++) { + hSbrGrid->v_f[i] = hSbrFrameInfo->freqRes[i] = + freq_res_fixfix[frameSplit]; + } + break; + + case FIXVAR: + case VARFIX: + nEnv = hSbrGrid->n + 1; /* read n [SBR_NUM_BITS bits] */ /*? snd*/ + FDK_ASSERT(nEnv <= MAX_ENVELOPES_FIXVAR_VARFIX); + + hSbrFrameInfo->nEnvelopes = nEnv; + + border = hSbrGrid->bs_abs_bord; /* read the absolute border */ + + if (nEnv == 1) + hSbrFrameInfo->nNoiseEnvelopes = 1; + else + hSbrFrameInfo->nNoiseEnvelopes = 2; + + break; + + default: + /* do nothing */ + break; + } + + switch (frameClass) { + case FIXVAR: + hSbrFrameInfo->borders[0] = + bufferFrameStart; /* start-position of 1st envelope */ + + hSbrFrameInfo->borders[nEnv] = border; + + for (k = 0, i = nEnv - 1; k < nEnv - 1; k++, i--) { + border -= v_r[k]; + hSbrFrameInfo->borders[i] = border; + } + + /* make either envelope nr. nEnv + 1 - p short; or don't shorten if p == 0 + */ + p = hSbrGrid->p; + if (p == 0) { + hSbrFrameInfo->shortEnv = 0; + } else { + hSbrFrameInfo->shortEnv = nEnv + 1 - p; + } + + for (k = 0, i = nEnv - 1; k < nEnv; k++, i--) { + hSbrFrameInfo->freqRes[i] = (FREQ_RES)v_f[k]; + } + + /* if either there is no short envelope or the last envelope is short... + */ + if (p == 0 || p == 1) { + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv - 1]; + } else { + hSbrFrameInfo->bordersNoise[1] = + hSbrFrameInfo->borders[hSbrFrameInfo->shortEnv]; + } + + break; + + case VARFIX: + /* in this case 'border' indicates the start of the 1st envelope */ + hSbrFrameInfo->borders[0] = border; + + for (k = 0; k < nEnv - 1; k++) { + border += v_r[k]; + hSbrFrameInfo->borders[k + 1] = border; + } + + hSbrFrameInfo->borders[nEnv] = bufferFrameStart + numberTimeSlots; + + p = hSbrGrid->p; + if (p == 0 || p == 1) { + hSbrFrameInfo->shortEnv = 0; + } else { + hSbrFrameInfo->shortEnv = p - 1; + } + + for (k = 0; k < nEnv; k++) { + hSbrFrameInfo->freqRes[k] = (FREQ_RES)v_f[k]; + } + + switch (p) { + case 0: + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[1]; + break; + case 1: + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv - 1]; + break; + default: + hSbrFrameInfo->bordersNoise[1] = + hSbrFrameInfo->borders[hSbrFrameInfo->shortEnv]; + break; + } + break; + + case VARVAR: + nEnv = hSbrGrid->bs_num_rel_0 + hSbrGrid->bs_num_rel_1 + 1; + FDK_ASSERT(nEnv <= MAX_ENVELOPES_VARVAR); /* just to be sure */ + hSbrFrameInfo->nEnvelopes = nEnv; + + hSbrFrameInfo->borders[0] = border = hSbrGrid->bs_abs_bord_0; + + for (k = 0, i = 1; k < hSbrGrid->bs_num_rel_0; k++, i++) { + border += hSbrGrid->bs_rel_bord_0[k]; + hSbrFrameInfo->borders[i] = border; + } + + border = hSbrGrid->bs_abs_bord_1; + hSbrFrameInfo->borders[nEnv] = border; + + for (k = 0, i = nEnv - 1; k < hSbrGrid->bs_num_rel_1; k++, i--) { + border -= hSbrGrid->bs_rel_bord_1[k]; + hSbrFrameInfo->borders[i] = border; + } + + p = hSbrGrid->p; + if (p == 0) { + hSbrFrameInfo->shortEnv = 0; + } else { + hSbrFrameInfo->shortEnv = nEnv + 1 - p; + } + + for (k = 0; k < nEnv; k++) { + hSbrFrameInfo->freqRes[k] = (FREQ_RES)hSbrGrid->v_fLR[k]; + } + + if (nEnv == 1) { + hSbrFrameInfo->nNoiseEnvelopes = 1; + hSbrFrameInfo->bordersNoise[0] = hSbrGrid->bs_abs_bord_0; + hSbrFrameInfo->bordersNoise[1] = hSbrGrid->bs_abs_bord_1; + } else { + hSbrFrameInfo->nNoiseEnvelopes = 2; + hSbrFrameInfo->bordersNoise[0] = hSbrGrid->bs_abs_bord_0; + + if (p == 0 || p == 1) { + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv - 1]; + } else { + hSbrFrameInfo->bordersNoise[1] = + hSbrFrameInfo->borders[hSbrFrameInfo->shortEnv]; + } + hSbrFrameInfo->bordersNoise[2] = hSbrGrid->bs_abs_bord_1; + } + break; + + default: + /* do nothing */ + break; + } + + if (frameClass == VARFIX || frameClass == FIXVAR) { + hSbrFrameInfo->bordersNoise[0] = hSbrFrameInfo->borders[0]; + if (nEnv == 1) { + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv]; + } else { + hSbrFrameInfo->bordersNoise[2] = hSbrFrameInfo->borders[nEnv]; + } + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/fram_gen.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/fram_gen.h new file mode 100644 index 0000000000000..0c5edc36a2d69 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/fram_gen.h @@ -0,0 +1,343 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Framing generator prototypes and structs $Revision: 92790 $ +*/ +#ifndef FRAM_GEN_H +#define FRAM_GEN_H + +#include "sbr_def.h" /* for MAX_ENVELOPES and MAX_NOISE_ENVELOPES in struct FRAME_INFO and CODEC_TYPE */ +#include "sbr_encoder.h" /* for FREQ_RES */ + +#define MAX_ENVELOPES_VARVAR \ + MAX_ENVELOPES /*!< worst case number of envelopes in a VARVAR frame */ +#define MAX_ENVELOPES_FIXVAR_VARFIX \ + 4 /*!< worst case number of envelopes in VARFIX and FIXVAR frames */ +#define MAX_NUM_REL \ + 3 /*!< maximum number of relative borders in any VAR frame */ + +/* SBR frame class definitions */ +typedef enum { + FIXFIX = + 0, /*!< bs_frame_class: leading and trailing frame borders are fixed */ + FIXVAR, /*!< bs_frame_class: leading frame border is fixed, trailing frame + border is variable */ + VARFIX, /*!< bs_frame_class: leading frame border is variable, trailing frame + border is fixed */ + VARVAR /*!< bs_frame_class: leading and trailing frame borders are variable */ + , + FIXFIXonly /*!< bs_frame_class: leading border fixed (0), trailing border + fixed (nrTimeSlots) and encased borders are dynamically derived + from the tranPos */ +} FRAME_CLASS; + +/* helper constants */ +#define DC 4711 /*!< helper constant: don't care */ +#define EMPTY (-99) /*!< helper constant: empty */ + +/* system constants: AAC+SBR, DRM Frame-Length */ +#define FRAME_MIDDLE_SLOT_1920 4 +#define NUMBER_TIME_SLOTS_1920 15 + +#define LD_PRETRAN_OFF 3 +#define FRAME_MIDDLE_SLOT_512LD 4 +#define NUMBER_TIME_SLOTS_512LD 8 +#define TRANSIENT_OFFSET_LD 0 + +/* +system constants: AAC+SBR or aacPRO (hybrid format), Standard Frame-Length, +Multi-Rate +--------------------------------------------------------------------------- +Number of slots (numberTimeSlots): 16 (NUMBER_TIME_SLOTS_2048) +Detector-offset (frameMiddleSlot): 4 +Overlap : 3 +Buffer-offset : 8 (BUFFER_FRAME_START_2048 = 0) + + + |<------------tranPos---------->| + |c|d|e|f|0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f| + FixFix | | + FixVar | :<- ->: + VarFix :<- ->: | + VarVar :<- ->: :<- ->: + 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 +................................................................................ + +|-|-|-|-|-|-|-|-B-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-B-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-| + +frame-generator:0 16 24 32 +analysis-buffer:8 24 32 40 +*/ +#define FRAME_MIDDLE_SLOT_2048 4 +#define NUMBER_TIME_SLOTS_2048 16 + +/* +system constants: mp3PRO, Multi-Rate & Single-Rate +-------------------------------------------------- +Number of slots (numberTimeSlots): 9 (NUMBER_TIME_SLOTS_1152) +Detector-offset (frameMiddleSlot): 4 (FRAME_MIDDLE_SLOT_1152) +Overlap : 3 +Buffer-offset : 4.5 (BUFFER_FRAME_START_1152 = 0) + + + |<----tranPos---->| + |5|6|7|8|0|1|2|3|4|5|6|7|8| + FixFix | | + FixVar | :<- ->: + VarFix :<- ->: | + VarVar :<- ->: :<- ->: + 0 1 2 3 4 5 6 7 8 0 1 2 3 + ............................................. + + -|-|-|-|-B-|-|-|-|-|-|-|-|-B-|-|-|-|-|-|-|-|-| + +frame-generator: 0 9 13 18 +analysis-buffer: 4.5 13.5 22.5 +*/ +#define FRAME_MIDDLE_SLOT_1152 4 +#define NUMBER_TIME_SLOTS_1152 9 + +/* system constants: Layer2+SBR */ +#define FRAME_MIDDLE_SLOT_2304 8 +#define NUMBER_TIME_SLOTS_2304 18 + +/*! + \struct SBR_GRID + \brief sbr_grid() signals to be converted to bitstream elements + + The variables hold the signals (e.g. lengths and numbers) in "clear text" +*/ + +typedef struct { + /* system constants */ + INT bufferFrameStart; /*!< frame generator vs analysis buffer time alignment + (currently set to 0, offset added elsewhere) */ + INT numberTimeSlots; /*!< number of SBR timeslots per frame */ + + /* will be adjusted for every frame */ + FRAME_CLASS frameClass; /*!< SBR frame class */ + INT bs_num_env; /*!< bs_num_env, number of envelopes for FIXFIX */ + INT bs_abs_bord; /*!< bs_abs_bord, absolute border for VARFIX and FIXVAR */ + INT n; /*!< number of relative borders for VARFIX and FIXVAR */ + INT p; /*!< pointer-to-transient-border */ + INT bs_rel_bord[MAX_NUM_REL]; /*!< bs_rel_bord, relative borders for all VAR + */ + INT v_f[MAX_ENVELOPES_FIXVAR_VARFIX]; /*!< envelope frequency resolutions for + FIXVAR and VARFIX */ + + INT bs_abs_bord_0; /*!< bs_abs_bord_0, leading absolute border for VARVAR */ + INT bs_abs_bord_1; /*!< bs_abs_bord_1, trailing absolute border for VARVAR */ + INT bs_num_rel_0; /*!< bs_num_rel_0, number of relative borders associated + with leading absolute border for VARVAR */ + INT bs_num_rel_1; /*!< bs_num_rel_1, number of relative borders associated + with trailing absolute border for VARVAR */ + INT bs_rel_bord_0[MAX_NUM_REL]; /*!< bs_rel_bord_0, relative borders + associated with leading absolute border + for VARVAR */ + INT bs_rel_bord_1[MAX_NUM_REL]; /*!< bs_rel_bord_1, relative borders + associated with trailing absolute border + for VARVAR */ + INT v_fLR[MAX_ENVELOPES_VARVAR]; /*!< envelope frequency resolutions for + VARVAR */ + +} SBR_GRID; +typedef SBR_GRID *HANDLE_SBR_GRID; + +/*! + \struct SBR_FRAME_INFO + \brief time/frequency grid description for one frame +*/ +typedef struct { + INT nEnvelopes; /*!< number of envelopes */ + INT borders[MAX_ENVELOPES + 1]; /*!< envelope borders in SBR timeslots */ + FREQ_RES freqRes[MAX_ENVELOPES]; /*!< frequency resolution of each envelope */ + INT shortEnv; /*!< number of an envelope to be shortened (starting at 1) or 0 + for no shortened envelope */ + INT nNoiseEnvelopes; /*!< number of noise floors */ + INT bordersNoise[MAX_NOISE_ENVELOPES + + 1]; /*!< noise floor borders in SBR timeslots */ +} SBR_FRAME_INFO; +/* WARNING: When rearranging the elements of this struct keep in mind that the + * static initializations in the corresponding C-file have to be rearranged as + * well! snd 2002/01/23 + */ +typedef SBR_FRAME_INFO *HANDLE_SBR_FRAME_INFO; + +/*! + \struct SBR_ENVELOPE_FRAME + \brief frame generator main struct + + Contains tuning parameters, time/frequency grid description, sbr_grid() + bitstream elements, and generator internal signals +*/ +typedef struct { + /* system constants */ + INT frameMiddleSlot; /*!< transient detector offset in SBR timeslots */ + + /* basic tuning parameters */ + INT staticFraming; /*!< 1: run static framing in time, i.e. exclusive use of + bs_frame_class = FIXFIX */ + INT numEnvStatic; /*!< number of envelopes per frame for static framing */ + FREQ_RES + freq_res_fixfix[2]; /*!< envelope frequency resolution to use for + bs_frame_class = FIXFIX; single env and split */ + UCHAR + fResTransIsLow; /*!< frequency resolution for transient frames - always + low (0) or according to table (1) */ + + /* expert tuning parameters */ + const int *v_tuningSegm; /*!< segment lengths to use around transient */ + const int *v_tuningFreq; /*!< frequency resolutions to use around transient */ + INT dmin; /*!< minimum length of dependent segments */ + INT dmax; /*!< maximum length of dependent segments */ + INT allowSpread; /*!< 1: allow isolated transient to influence grid of 3 + consecutive frames */ + + /* internally used signals */ + FRAME_CLASS frameClassOld; /*!< frame class used for previous frame */ + INT spreadFlag; /*!< 1: use VARVAR instead of VARFIX to follow up old + transient */ + + INT v_bord[2 * MAX_ENVELOPES_VARVAR + 1]; /*!< borders for current frame and + preliminary borders for next + frame (fixed borders excluded) */ + INT length_v_bord; /*!< helper variable: length of v_bord */ + INT v_freq[2 * MAX_ENVELOPES_VARVAR + 1]; /*!< frequency resolutions for + current frame and preliminary + resolutions for next frame */ + INT length_v_freq; /*!< helper variable: length of v_freq */ + + INT v_bordFollow[MAX_ENVELOPES_VARVAR]; /*!< preliminary borders for current + frame (calculated during previous + frame) */ + INT length_v_bordFollow; /*!< helper variable: length of v_bordFollow */ + INT i_tranFollow; /*!< points to transient border in v_bordFollow (may be + negative, see keepForFollowUp()) */ + INT i_fillFollow; /*!< points to first fill border in v_bordFollow */ + INT v_freqFollow[MAX_ENVELOPES_VARVAR]; /*!< preliminary frequency resolutions + for current frame (calculated + during previous frame) */ + INT length_v_freqFollow; /*!< helper variable: length of v_freqFollow */ + + /* externally needed signals */ + SBR_GRID + SbrGrid; /*!< sbr_grid() signals to be converted to bitstream elements */ + SBR_FRAME_INFO + SbrFrameInfo; /*!< time/frequency grid description for one frame */ +} SBR_ENVELOPE_FRAME; +typedef SBR_ENVELOPE_FRAME *HANDLE_SBR_ENVELOPE_FRAME; + +void FDKsbrEnc_initFrameInfoGenerator(HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + INT allowSpread, INT numEnvStatic, + INT staticFraming, INT timeSlots, + const FREQ_RES *freq_res_fixfix, + UCHAR fResTransIsLow, INT ldGrid); + +HANDLE_SBR_FRAME_INFO +FDKsbrEnc_frameInfoGenerator(HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + UCHAR *v_transient_info, const INT rightBorderFIX, + UCHAR *v_transient_info_pre, int ldGrid, + const int *v_tuning); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/invf_est.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/invf_est.cpp new file mode 100644 index 0000000000000..53b47ac888128 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/invf_est.cpp @@ -0,0 +1,610 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "invf_est.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +#define MAX_NUM_REGIONS 10 +#define SCALE_FAC_QUO 512.0f +#define SCALE_FAC_NRG 256.0f + +#ifndef min +#define min(a, b) (a < b ? a : b) +#endif + +#ifndef max +#define max(a, b) (a > b ? a : b) +#endif + +static const FIXP_DBL quantStepsSbr[4] = { + 0x00400000, 0x02800000, 0x03800000, + 0x04c00000}; /* table scaled with SCALE_FAC_QUO */ +static const FIXP_DBL quantStepsOrig[4] = { + 0x00000000, 0x00c00000, 0x01c00000, + 0x02800000}; /* table scaled with SCALE_FAC_QUO */ +static const FIXP_DBL nrgBorders[4] = { + 0x0c800000, 0x0f000000, 0x11800000, + 0x14000000}; /* table scaled with SCALE_FAC_NRG */ + +static const DETECTOR_PARAMETERS detectorParamsAAC = { + quantStepsSbr, + quantStepsOrig, + nrgBorders, + 4, /* Number of borders SBR. */ + 4, /* Number of borders orig. */ + 4, /* Number of borders Nrg. */ + { + /* Region space. */ + {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* regionSbr */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF} /* | */ + }, /*------------------------ regionOrig ---------------------------------*/ + { + /* Region space transient. */ + {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* regionSbr */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF} /* | */ + }, /*------------------------ regionOrig ---------------------------------*/ + {-4, -3, -2, -1, + 0} /* Reduction factor of the inverse filtering for low energies.*/ +}; + +static const FIXP_DBL hysteresis = + 0x00400000; /* Delta value for hysteresis. scaled with SCALE_FAC_QUO */ + +/* + * AAC+SBR PARAMETERS for Speech + *********************************/ +static const DETECTOR_PARAMETERS detectorParamsAACSpeech = { + quantStepsSbr, + quantStepsOrig, + nrgBorders, + 4, /* Number of borders SBR. */ + 4, /* Number of borders orig. */ + 4, /* Number of borders Nrg. */ + { + /* Region space. */ + {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* regionSbr */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF} /* | */ + }, /*------------------------ regionOrig ---------------------------------*/ + { + /* Region space transient. */ + {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* regionSbr */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF} /* | */ + }, /*------------------------ regionOrig ---------------------------------*/ + {-4, -3, -2, -1, + 0} /* Reduction factor of the inverse filtering for low energies.*/ +}; + +/* + * Smoothing filters. + ************************/ +typedef const FIXP_DBL FIR_FILTER[5]; + +static const FIR_FILTER fir_0 = {0x7fffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000}; +static const FIR_FILTER fir_1 = {0x2aaaaa80, 0x555554ff, 0x00000000, 0x00000000, + 0x00000000}; +static const FIR_FILTER fir_2 = {0x10000000, 0x30000000, 0x40000000, 0x00000000, + 0x00000000}; +static const FIR_FILTER fir_3 = {0x077f80e8, 0x199999a0, 0x2bb3b240, 0x33333340, + 0x00000000}; +static const FIR_FILTER fir_4 = {0x04130598, 0x0ebdb000, 0x1becfa60, 0x2697a4c0, + 0x2aaaaa80}; + +static const FIR_FILTER *const fir_table[5] = {&fir_0, &fir_1, &fir_2, &fir_3, + &fir_4}; + +/**************************************************************************/ +/*! + \brief Calculates the values used for the detector. + + + \return none + +*/ +/**************************************************************************/ +static void calculateDetectorValues( + FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the tonality values of the + original. */ + SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ + FIXP_DBL *nrgVector, /*!< Energy vector. */ + DETECTOR_VALUES *detectorValues, /*!< pointer to DETECTOR_VALUES struct. */ + INT startChannel, /*!< Start channel. */ + INT stopChannel, /*!< Stop channel. */ + INT startIndex, /*!< Start index. */ + INT stopIndex, /*!< Stop index. */ + INT numberOfStrongest /*!< The number of sorted tonal components to be + considered. */ +) { + INT i, temp, j; + + const FIXP_DBL *filter = *fir_table[INVF_SMOOTHING_LENGTH]; + FIXP_DBL origQuotaMeanStrongest, sbrQuotaMeanStrongest; + FIXP_DBL origQuota, sbrQuota; + FIXP_DBL invIndex, invChannel, invTemp; + FIXP_DBL quotaVecOrig[64], quotaVecSbr[64]; + + FDKmemclear(quotaVecOrig, 64 * sizeof(FIXP_DBL)); + FDKmemclear(quotaVecSbr, 64 * sizeof(FIXP_DBL)); + + invIndex = GetInvInt(stopIndex - startIndex); + invChannel = GetInvInt(stopChannel - startChannel); + + /* + Calculate the mean value, over the current time segment, for the original, + the HFR and the difference, over all channels in the current frequency range. + NOTE: the averaging is done on the values quota/(1 - quota + RELAXATION). + */ + + /* The original, the sbr signal and the total energy */ + detectorValues->avgNrg = FL2FXCONST_DBL(0.0f); + for (j = startIndex; j < stopIndex; j++) { + for (i = startChannel; i < stopChannel; i++) { + quotaVecOrig[i] += fMult(quotaMatrixOrig[j][i], invIndex); + + if (indexVector[i] != -1) + quotaVecSbr[i] += fMult(quotaMatrixOrig[j][indexVector[i]], invIndex); + } + detectorValues->avgNrg += fMult(nrgVector[j], invIndex); + } + + /* + Calculate the mean value, over the current frequency range, for the original, + the HFR and the difference. Also calculate the same mean values for the three + vectors, but only includeing the x strongest copmponents. + */ + + origQuota = FL2FXCONST_DBL(0.0f); + sbrQuota = FL2FXCONST_DBL(0.0f); + for (i = startChannel; i < stopChannel; i++) { + origQuota += fMultDiv2(quotaVecOrig[i], invChannel); + sbrQuota += fMultDiv2(quotaVecSbr[i], invChannel); + } + + /* + Calculate the mean value for the x strongest components + */ + FDKsbrEnc_Shellsort_fract(quotaVecOrig + startChannel, + stopChannel - startChannel); + FDKsbrEnc_Shellsort_fract(quotaVecSbr + startChannel, + stopChannel - startChannel); + + origQuotaMeanStrongest = FL2FXCONST_DBL(0.0f); + sbrQuotaMeanStrongest = FL2FXCONST_DBL(0.0f); + + temp = min(stopChannel - startChannel, numberOfStrongest); + invTemp = GetInvInt(temp); + + for (i = 0; i < temp; i++) { + origQuotaMeanStrongest += + fMultDiv2(quotaVecOrig[i + stopChannel - temp], invTemp); + sbrQuotaMeanStrongest += + fMultDiv2(quotaVecSbr[i + stopChannel - temp], invTemp); + } + + /* + The value for the strongest component + */ + detectorValues->origQuotaMax = quotaVecOrig[stopChannel - 1]; + detectorValues->sbrQuotaMax = quotaVecSbr[stopChannel - 1]; + + /* + Buffer values + */ + FDKmemmove(detectorValues->origQuotaMean, detectorValues->origQuotaMean + 1, + INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL)); + FDKmemmove(detectorValues->sbrQuotaMean, detectorValues->sbrQuotaMean + 1, + INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL)); + FDKmemmove(detectorValues->origQuotaMeanStrongest, + detectorValues->origQuotaMeanStrongest + 1, + INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL)); + FDKmemmove(detectorValues->sbrQuotaMeanStrongest, + detectorValues->sbrQuotaMeanStrongest + 1, + INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL)); + + detectorValues->origQuotaMean[INVF_SMOOTHING_LENGTH] = origQuota << 1; + detectorValues->sbrQuotaMean[INVF_SMOOTHING_LENGTH] = sbrQuota << 1; + detectorValues->origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = + origQuotaMeanStrongest << 1; + detectorValues->sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = + sbrQuotaMeanStrongest << 1; + + /* + Filter values + */ + detectorValues->origQuotaMeanFilt = FL2FXCONST_DBL(0.0f); + detectorValues->sbrQuotaMeanFilt = FL2FXCONST_DBL(0.0f); + detectorValues->origQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f); + detectorValues->sbrQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f); + + for (i = 0; i < INVF_SMOOTHING_LENGTH + 1; i++) { + detectorValues->origQuotaMeanFilt += + fMult(detectorValues->origQuotaMean[i], filter[i]); + detectorValues->sbrQuotaMeanFilt += + fMult(detectorValues->sbrQuotaMean[i], filter[i]); + detectorValues->origQuotaMeanStrongestFilt += + fMult(detectorValues->origQuotaMeanStrongest[i], filter[i]); + detectorValues->sbrQuotaMeanStrongestFilt += + fMult(detectorValues->sbrQuotaMeanStrongest[i], filter[i]); + } +} + +/**************************************************************************/ +/*! + \brief Returns the region in which the input value belongs. + + + + \return region. + +*/ +/**************************************************************************/ +static INT findRegion( + FIXP_DBL currVal, /*!< The current value. */ + const FIXP_DBL *borders, /*!< The border of the regions. */ + const INT numBorders /*!< The number of borders. */ +) { + INT i; + + if (currVal < borders[0]) { + return 0; + } + + for (i = 1; i < numBorders; i++) { + if (currVal >= borders[i - 1] && currVal < borders[i]) { + return i; + } + } + + if (currVal >= borders[numBorders - 1]) { + return numBorders; + } + + return 0; /* We never get here, it's just to avoid compiler warnings.*/ +} + +/**************************************************************************/ +/*! + \brief Makes a clever decision based on the quota vector. + + + \return decision on which invf mode to use + +*/ +/**************************************************************************/ +static INVF_MODE decisionAlgorithm( + const DETECTOR_PARAMETERS + *detectorParams, /*!< Struct with the detector parameters. */ + DETECTOR_VALUES *detectorValues, /*!< Struct with the detector values. */ + INT transientFlag, /*!< Flag indicating if there is a transient present.*/ + INT *prevRegionSbr, /*!< The previous region in which the Sbr value was. */ + INT *prevRegionOrig /*!< The previous region in which the Orig value was. */ +) { + INT invFiltLevel, regionSbr, regionOrig, regionNrg; + + /* + Current thresholds. + */ + const INT numRegionsSbr = detectorParams->numRegionsSbr; + const INT numRegionsOrig = detectorParams->numRegionsOrig; + const INT numRegionsNrg = detectorParams->numRegionsNrg; + + FIXP_DBL quantStepsSbrTmp[MAX_NUM_REGIONS]; + FIXP_DBL quantStepsOrigTmp[MAX_NUM_REGIONS]; + + /* + Current detector values. + */ + FIXP_DBL origQuotaMeanFilt; + FIXP_DBL sbrQuotaMeanFilt; + FIXP_DBL nrg; + + /* 0.375 = 3.0 / 8.0; 0.31143075889 = log2(RELAXATION)/64.0; 0.625 = + * log(16)/64.0; 0.6875 = 44/64.0 */ + origQuotaMeanFilt = + (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f), + (FIXP_DBL)(CalcLdData(max(detectorValues->origQuotaMeanFilt, + (FIXP_DBL)1)) + + FL2FXCONST_DBL(0.31143075889f)))) + << 0; /* scaled by 1/2^9 */ + sbrQuotaMeanFilt = + (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f), + (FIXP_DBL)(CalcLdData(max(detectorValues->sbrQuotaMeanFilt, + (FIXP_DBL)1)) + + FL2FXCONST_DBL(0.31143075889f)))) + << 0; /* scaled by 1/2^9 */ + /* If energy is zero then we will get different results for different word + * lengths. */ + nrg = + (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f), + (FIXP_DBL)(CalcLdData(detectorValues->avgNrg + (FIXP_DBL)1) + + FL2FXCONST_DBL(0.0625f) + FL2FXCONST_DBL(0.6875f)))) + << 0; /* scaled by 1/2^8; 2^44 -> qmf energy scale */ + + FDKmemcpy(quantStepsSbrTmp, detectorParams->quantStepsSbr, + numRegionsSbr * sizeof(FIXP_DBL)); + FDKmemcpy(quantStepsOrigTmp, detectorParams->quantStepsOrig, + numRegionsOrig * sizeof(FIXP_DBL)); + + if (*prevRegionSbr < numRegionsSbr) + quantStepsSbrTmp[*prevRegionSbr] = + detectorParams->quantStepsSbr[*prevRegionSbr] + hysteresis; + if (*prevRegionSbr > 0) + quantStepsSbrTmp[*prevRegionSbr - 1] = + detectorParams->quantStepsSbr[*prevRegionSbr - 1] - hysteresis; + + if (*prevRegionOrig < numRegionsOrig) + quantStepsOrigTmp[*prevRegionOrig] = + detectorParams->quantStepsOrig[*prevRegionOrig] + hysteresis; + if (*prevRegionOrig > 0) + quantStepsOrigTmp[*prevRegionOrig - 1] = + detectorParams->quantStepsOrig[*prevRegionOrig - 1] - hysteresis; + + regionSbr = findRegion(sbrQuotaMeanFilt, quantStepsSbrTmp, numRegionsSbr); + regionOrig = findRegion(origQuotaMeanFilt, quantStepsOrigTmp, numRegionsOrig); + regionNrg = findRegion(nrg, detectorParams->nrgBorders, numRegionsNrg); + + *prevRegionSbr = regionSbr; + *prevRegionOrig = regionOrig; + + /* Use different settings if a transient is present*/ + invFiltLevel = + (transientFlag == 1) + ? detectorParams->regionSpaceTransient[regionSbr][regionOrig] + : detectorParams->regionSpace[regionSbr][regionOrig]; + + /* Compensate for low energy.*/ + invFiltLevel = + max(invFiltLevel + detectorParams->EnergyCompFactor[regionNrg], 0); + + return (INVF_MODE)(invFiltLevel); +} + +/**************************************************************************/ +/*! + \brief Estiamtion of the inverse filtering level required + in the decoder. + + A second order LPC is calculated for every filterbank channel, using + the covariance method. THe ratio between the energy of the predicted + signal and the energy of the non-predictable signal is calcualted. + + \return none. + +*/ +/**************************************************************************/ +void FDKsbrEnc_qmfInverseFilteringDetector( + HANDLE_SBR_INV_FILT_EST + hInvFilt, /*!< Handle to the SBR_INV_FILT_EST struct. */ + FIXP_DBL **quotaMatrix, /*!< The matrix holding the tonality values of the + original. */ + FIXP_DBL *nrgVector, /*!< The energy vector. */ + SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ + INT startIndex, /*!< Start index. */ + INT stopIndex, /*!< Stop index. */ + INT transientFlag, /*!< Flag indicating if a transient is present or not.*/ + INVF_MODE *infVec /*!< Vector holding the inverse filtering levels. */ +) { + INT band; + + /* + * Do the inverse filtering level estimation. + *****************************************************/ + for (band = 0; band < hInvFilt->noDetectorBands; band++) { + INT startChannel = hInvFilt->freqBandTableInvFilt[band]; + INT stopChannel = hInvFilt->freqBandTableInvFilt[band + 1]; + + calculateDetectorValues(quotaMatrix, indexVector, nrgVector, + &hInvFilt->detectorValues[band], startChannel, + stopChannel, startIndex, stopIndex, + hInvFilt->numberOfStrongest); + + infVec[band] = decisionAlgorithm( + hInvFilt->detectorParams, &hInvFilt->detectorValues[band], + transientFlag, &hInvFilt->prevRegionSbr[band], + &hInvFilt->prevRegionOrig[band]); + } +} + +/**************************************************************************/ +/*! + \brief Initialize an instance of the inverse filtering level estimator. + + + \return errorCode, noError if successful. + +*/ +/**************************************************************************/ +INT FDKsbrEnc_initInvFiltDetector( + HANDLE_SBR_INV_FILT_EST + hInvFilt, /*!< Pointer to a handle to the SBR_INV_FILT_EST struct. */ + INT *freqBandTableDetector, /*!< Frequency band table for the inverse + filtering. */ + INT numDetectorBands, /*!< Number of inverse filtering bands. */ + UINT + useSpeechConfig /*!< Flag: adapt tuning parameters according to speech*/ +) { + INT i; + + FDKmemclear(hInvFilt, sizeof(SBR_INV_FILT_EST)); + + hInvFilt->detectorParams = + (useSpeechConfig) ? &detectorParamsAACSpeech : &detectorParamsAAC; + + hInvFilt->noDetectorBandsMax = numDetectorBands; + + /* + Memory initialisation + */ + for (i = 0; i < hInvFilt->noDetectorBandsMax; i++) { + FDKmemclear(&hInvFilt->detectorValues[i], sizeof(DETECTOR_VALUES)); + hInvFilt->prevInvfMode[i] = INVF_OFF; + hInvFilt->prevRegionOrig[i] = 0; + hInvFilt->prevRegionSbr[i] = 0; + } + + /* + Reset the inverse fltering detector. + */ + FDKsbrEnc_resetInvFiltDetector(hInvFilt, freqBandTableDetector, + hInvFilt->noDetectorBandsMax); + + return (0); +} + +/**************************************************************************/ +/*! + \brief resets sbr inverse filtering structure. + + + + \return errorCode, noError if successful. + +*/ +/**************************************************************************/ +INT FDKsbrEnc_resetInvFiltDetector( + HANDLE_SBR_INV_FILT_EST + hInvFilt, /*!< Handle to the SBR_INV_FILT_EST struct. */ + INT *freqBandTableDetector, /*!< Frequency band table for the inverse + filtering. */ + INT numDetectorBands) /*!< Number of inverse filtering bands. */ +{ + hInvFilt->numberOfStrongest = 1; + FDKmemcpy(hInvFilt->freqBandTableInvFilt, freqBandTableDetector, + (numDetectorBands + 1) * sizeof(INT)); + hInvFilt->noDetectorBands = numDetectorBands; + + return (0); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/invf_est.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/invf_est.h new file mode 100644 index 0000000000000..3ab6726a38401 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/invf_est.h @@ -0,0 +1,181 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Inverse Filtering detection prototypes $Revision: 92790 $ +*/ +#ifndef INVF_EST_H +#define INVF_EST_H + +#include "sbr_encoder.h" +#include "sbr_def.h" + +#define INVF_SMOOTHING_LENGTH 2 + +typedef struct { + const FIXP_DBL *quantStepsSbr; + const FIXP_DBL *quantStepsOrig; + const FIXP_DBL *nrgBorders; + INT numRegionsSbr; + INT numRegionsOrig; + INT numRegionsNrg; + INVF_MODE regionSpace[5][5]; + INVF_MODE regionSpaceTransient[5][5]; + INT EnergyCompFactor[5]; + +} DETECTOR_PARAMETERS; + +typedef struct { + FIXP_DBL origQuotaMean[INVF_SMOOTHING_LENGTH + 1]; + FIXP_DBL sbrQuotaMean[INVF_SMOOTHING_LENGTH + 1]; + FIXP_DBL origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH + 1]; + FIXP_DBL sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH + 1]; + + FIXP_DBL origQuotaMeanFilt; + FIXP_DBL sbrQuotaMeanFilt; + FIXP_DBL origQuotaMeanStrongestFilt; + FIXP_DBL sbrQuotaMeanStrongestFilt; + + FIXP_DBL origQuotaMax; + FIXP_DBL sbrQuotaMax; + + FIXP_DBL avgNrg; +} DETECTOR_VALUES; + +typedef struct { + INT numberOfStrongest; + + INT prevRegionSbr[MAX_NUM_NOISE_VALUES]; + INT prevRegionOrig[MAX_NUM_NOISE_VALUES]; + + INT freqBandTableInvFilt[MAX_NUM_NOISE_VALUES]; + INT noDetectorBands; + INT noDetectorBandsMax; + + const DETECTOR_PARAMETERS *detectorParams; + + INVF_MODE prevInvfMode[MAX_NUM_NOISE_VALUES]; + DETECTOR_VALUES detectorValues[MAX_NUM_NOISE_VALUES]; + + FIXP_DBL nrgAvg; + FIXP_DBL wmQmf[MAX_NUM_NOISE_VALUES]; +} SBR_INV_FILT_EST; + +typedef SBR_INV_FILT_EST *HANDLE_SBR_INV_FILT_EST; + +void FDKsbrEnc_qmfInverseFilteringDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, + FIXP_DBL **quotaMatrix, + FIXP_DBL *nrgVector, + SCHAR *indexVector, INT startIndex, + INT stopIndex, INT transientFlag, + INVF_MODE *infVec); + +INT FDKsbrEnc_initInvFiltDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, + INT *freqBandTableDetector, + INT numDetectorBands, UINT useSpeechConfig); + +INT FDKsbrEnc_resetInvFiltDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, + INT *freqBandTableDetector, + INT numDetectorBands); + +#endif /* _QMF_INV_FILT_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/mh_det.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/mh_det.cpp new file mode 100644 index 0000000000000..2f3b3867d9b72 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/mh_det.cpp @@ -0,0 +1,1396 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "mh_det.h" + +#include "sbrenc_ram.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +#define SFM_SHIFT 2 /* Attention: SFM_SCALE depends on SFM_SHIFT */ +#define SFM_SCALE (MAXVAL_DBL >> SFM_SHIFT) /* 1.0 >> SFM_SHIFT */ + +/*!< Detector Parameters for AAC core codec. */ +static const DETECTOR_PARAMETERS_MH paramsAac = { + 9, /*!< deltaTime */ + { + FL2FXCONST_DBL(20.0f * RELAXATION_FLOAT), /*!< thresHoldDiff */ + FL2FXCONST_DBL(1.26f * RELAXATION_FLOAT), /*!< thresHoldDiffGuide */ + FL2FXCONST_DBL(15.0f * RELAXATION_FLOAT), /*!< thresHoldTone */ + FL2FXCONST_DBL((1.0f / 15.0f) * + RELAXATION_FLOAT), /*!< invThresHoldTone */ + FL2FXCONST_DBL(1.26f * RELAXATION_FLOAT), /*!< thresHoldToneGuide */ + FL2FXCONST_DBL(0.3f) >> SFM_SHIFT, /*!< sfmThresSbr */ + FL2FXCONST_DBL(0.1f) >> SFM_SHIFT, /*!< sfmThresOrig */ + FL2FXCONST_DBL(0.3f), /*!< decayGuideOrig */ + FL2FXCONST_DBL(0.5f), /*!< decayGuideDiff */ + FL2FXCONST_DBL(-0.000112993269), + /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresMaxLD64 */ + FL2FXCONST_DBL(-0.000112993269), + /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresBelowLD64 */ + FL2FXCONST_DBL( + -0.005030126483f) /* LD64(FL2FXCONST_DBL(0.8f)) */ /*!< + derivThresAboveLD64 + */ + }, + 50 /*!< maxComp */ +}; + +/*!< Detector Parameters for AAC LD core codec. */ +static const DETECTOR_PARAMETERS_MH paramsAacLd = { + 16, /*!< Delta time. */ + { + FL2FXCONST_DBL(25.0f * RELAXATION_FLOAT), /*!< thresHoldDiff */ + FL2FXCONST_DBL(1.26f * RELAXATION_FLOAT), /*!< tresHoldDiffGuide */ + FL2FXCONST_DBL(15.0f * RELAXATION_FLOAT), /*!< thresHoldTone */ + FL2FXCONST_DBL((1.0f / 15.0f) * + RELAXATION_FLOAT), /*!< invThresHoldTone */ + FL2FXCONST_DBL(1.26f * RELAXATION_FLOAT), /*!< thresHoldToneGuide */ + FL2FXCONST_DBL(0.3f) >> SFM_SHIFT, /*!< sfmThresSbr */ + FL2FXCONST_DBL(0.1f) >> SFM_SHIFT, /*!< sfmThresOrig */ + FL2FXCONST_DBL(0.3f), /*!< decayGuideOrig */ + FL2FXCONST_DBL(0.2f), /*!< decayGuideDiff */ + FL2FXCONST_DBL(-0.000112993269), + /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresMaxLD64 */ + FL2FXCONST_DBL(-0.000112993269), + /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresBelowLD64 */ + FL2FXCONST_DBL( + -0.005030126483f) /* LD64(FL2FXCONST_DBL(0.8f)) */ /*!< + derivThresAboveLD64 + */ + }, + 50 /*!< maxComp */ +}; + +/**************************************************************************/ +/*! + \brief Calculates the difference in tonality between original and SBR + for a given time and frequency region. + + The values for pDiffMapped2Scfb are scaled by RELAXATION + + \return none. + +*/ +/**************************************************************************/ +static void diff(FIXP_DBL *RESTRICT pTonalityOrig, FIXP_DBL *pDiffMapped2Scfb, + const UCHAR *RESTRICT pFreqBandTable, INT nScfb, + SCHAR *indexVector) { + UCHAR i, ll, lu, k; + FIXP_DBL maxValOrig, maxValSbr, tmp; + INT scale; + + for (i = 0; i < nScfb; i++) { + ll = pFreqBandTable[i]; + lu = pFreqBandTable[i + 1]; + + maxValOrig = FL2FXCONST_DBL(0.0f); + maxValSbr = FL2FXCONST_DBL(0.0f); + + for (k = ll; k < lu; k++) { + maxValOrig = fixMax(maxValOrig, pTonalityOrig[k]); + maxValSbr = fixMax(maxValSbr, pTonalityOrig[indexVector[k]]); + } + + if ((maxValSbr >= RELAXATION)) { + tmp = fDivNorm(maxValOrig, maxValSbr, &scale); + pDiffMapped2Scfb[i] = + scaleValue(fMult(tmp, RELAXATION_FRACT), + fixMax(-(DFRACT_BITS - 1), (scale - RELAXATION_SHIFT))); + } else { + pDiffMapped2Scfb[i] = maxValOrig; + } + } +} + +/**************************************************************************/ +/*! + \brief Calculates a flatness measure of the tonality measures. + + Calculation of the power function and using scalefactor for basis: + Using log2: + z = (2^k * x)^y; + z' = CalcLd(z) = y*CalcLd(x) + y*k; + z = CalcInvLd(z'); + + Using ld64: + z = (2^k * x)^y; + z' = CalcLd64(z) = y*CalcLd64(x)/64 + y*k/64; + z = CalcInvLd64(z'); + + The values pSfmOrigVec and pSfmSbrVec are scaled by the factor 1/4.0 + + \return none. + +*/ +/**************************************************************************/ +static void calculateFlatnessMeasure(FIXP_DBL *pQuotaBuffer, SCHAR *indexVector, + FIXP_DBL *pSfmOrigVec, + FIXP_DBL *pSfmSbrVec, + const UCHAR *pFreqBandTable, INT nSfb) { + INT i, j; + FIXP_DBL invBands, tmp1, tmp2; + INT shiftFac0, shiftFacSum0; + INT shiftFac1, shiftFacSum1; + FIXP_DBL accu; + + for (i = 0; i < nSfb; i++) { + INT ll = pFreqBandTable[i]; + INT lu = pFreqBandTable[i + 1]; + pSfmOrigVec[i] = (FIXP_DBL)(MAXVAL_DBL >> 2); + pSfmSbrVec[i] = (FIXP_DBL)(MAXVAL_DBL >> 2); + + if (lu - ll > 1) { + FIXP_DBL amOrig, amTransp, gmOrig, gmTransp, sfmOrig, sfmTransp; + invBands = GetInvInt(lu - ll); + shiftFacSum0 = 0; + shiftFacSum1 = 0; + amOrig = amTransp = FL2FXCONST_DBL(0.0f); + gmOrig = gmTransp = (FIXP_DBL)MAXVAL_DBL; + + for (j = ll; j < lu; j++) { + sfmOrig = pQuotaBuffer[j]; + sfmTransp = pQuotaBuffer[indexVector[j]]; + + amOrig += fMult(sfmOrig, invBands); + amTransp += fMult(sfmTransp, invBands); + + shiftFac0 = CountLeadingBits(sfmOrig); + shiftFac1 = CountLeadingBits(sfmTransp); + + gmOrig = fMult(gmOrig, sfmOrig << shiftFac0); + gmTransp = fMult(gmTransp, sfmTransp << shiftFac1); + + shiftFacSum0 += shiftFac0; + shiftFacSum1 += shiftFac1; + } + + if (gmOrig > FL2FXCONST_DBL(0.0f)) { + tmp1 = CalcLdData(gmOrig); /* CalcLd64(x)/64 */ + tmp1 = fMult(invBands, tmp1); /* y*CalcLd64(x)/64 */ + + /* y*k/64 */ + accu = (FIXP_DBL)-shiftFacSum0 << (DFRACT_BITS - 1 - 8); + tmp2 = fMultDiv2(invBands, accu) << (2 + 1); + + tmp2 = tmp1 + tmp2; /* y*CalcLd64(x)/64 + y*k/64 */ + gmOrig = CalcInvLdData(tmp2); /* CalcInvLd64(z'); */ + } else { + gmOrig = FL2FXCONST_DBL(0.0f); + } + + if (gmTransp > FL2FXCONST_DBL(0.0f)) { + tmp1 = CalcLdData(gmTransp); /* CalcLd64(x)/64 */ + tmp1 = fMult(invBands, tmp1); /* y*CalcLd64(x)/64 */ + + /* y*k/64 */ + accu = (FIXP_DBL)-shiftFacSum1 << (DFRACT_BITS - 1 - 8); + tmp2 = fMultDiv2(invBands, accu) << (2 + 1); + + tmp2 = tmp1 + tmp2; /* y*CalcLd64(x)/64 + y*k/64 */ + gmTransp = CalcInvLdData(tmp2); /* CalcInvLd64(z'); */ + } else { + gmTransp = FL2FXCONST_DBL(0.0f); + } + if (amOrig != FL2FXCONST_DBL(0.0f)) + pSfmOrigVec[i] = + FDKsbrEnc_LSI_divide_scale_fract(gmOrig, amOrig, SFM_SCALE); + + if (amTransp != FL2FXCONST_DBL(0.0f)) + pSfmSbrVec[i] = + FDKsbrEnc_LSI_divide_scale_fract(gmTransp, amTransp, SFM_SCALE); + } + } +} + +/**************************************************************************/ +/*! + \brief Calculates the input to the missing harmonics detection. + + + \return none. + +*/ +/**************************************************************************/ +static void calculateDetectorInput( + FIXP_DBL **RESTRICT pQuotaBuffer, /*!< Pointer to tonality matrix. */ + SCHAR *RESTRICT indexVector, FIXP_DBL **RESTRICT tonalityDiff, + FIXP_DBL **RESTRICT pSfmOrig, FIXP_DBL **RESTRICT pSfmSbr, + const UCHAR *freqBandTable, INT nSfb, INT noEstPerFrame, INT move) { + INT est; + + /* + New estimate. + */ + for (est = 0; est < noEstPerFrame; est++) { + diff(pQuotaBuffer[est + move], tonalityDiff[est + move], freqBandTable, + nSfb, indexVector); + + calculateFlatnessMeasure(pQuotaBuffer[est + move], indexVector, + pSfmOrig[est + move], pSfmSbr[est + move], + freqBandTable, nSfb); + } +} + +/**************************************************************************/ +/*! + \brief Checks that the detection is not due to a LP filter + + This function determines if a newly detected missing harmonics is not + in fact just a low-pass filtere input signal. If so, the detection is + removed. + + \return none. + +*/ +/**************************************************************************/ +static void removeLowPassDetection(UCHAR *RESTRICT pAddHarmSfb, + UCHAR **RESTRICT pDetectionVectors, + INT start, INT stop, INT nSfb, + const UCHAR *RESTRICT pFreqBandTable, + FIXP_DBL *RESTRICT pNrgVector, + THRES_HOLDS mhThresh) + +{ + INT i, est; + INT maxDerivPos = pFreqBandTable[nSfb]; + INT numBands = pFreqBandTable[nSfb]; + FIXP_DBL nrgLow, nrgHigh; + FIXP_DBL nrgLD64, nrgLowLD64, nrgHighLD64, nrgDiffLD64; + FIXP_DBL valLD64, maxValLD64, maxValAboveLD64; + INT bLPsignal = 0; + + maxValLD64 = FL2FXCONST_DBL(-1.0f); + for (i = numBands - 1 - 2; i > pFreqBandTable[0]; i--) { + nrgLow = pNrgVector[i]; + nrgHigh = pNrgVector[i + 2]; + + if (nrgLow != FL2FXCONST_DBL(0.0f) && nrgLow > nrgHigh) { + nrgLowLD64 = CalcLdData(nrgLow >> 1); + nrgDiffLD64 = CalcLdData((nrgLow >> 1) - (nrgHigh >> 1)); + valLD64 = nrgDiffLD64 - nrgLowLD64; + if (valLD64 > maxValLD64) { + maxDerivPos = i; + maxValLD64 = valLD64; + } + if (maxValLD64 > mhThresh.derivThresMaxLD64) { + break; + } + } + } + + /* Find the largest "gradient" above. (should be relatively flat, hence we + expect a low value if the signal is LP.*/ + maxValAboveLD64 = FL2FXCONST_DBL(-1.0f); + for (i = numBands - 1 - 2; i > maxDerivPos + 2; i--) { + nrgLow = pNrgVector[i]; + nrgHigh = pNrgVector[i + 2]; + + if (nrgLow != FL2FXCONST_DBL(0.0f) && nrgLow > nrgHigh) { + nrgLowLD64 = CalcLdData(nrgLow >> 1); + nrgDiffLD64 = CalcLdData((nrgLow >> 1) - (nrgHigh >> 1)); + valLD64 = nrgDiffLD64 - nrgLowLD64; + if (valLD64 > maxValAboveLD64) { + maxValAboveLD64 = valLD64; + } + } else { + if (nrgHigh != FL2FXCONST_DBL(0.0f) && nrgHigh > nrgLow) { + nrgHighLD64 = CalcLdData(nrgHigh >> 1); + nrgDiffLD64 = CalcLdData((nrgHigh >> 1) - (nrgLow >> 1)); + valLD64 = nrgDiffLD64 - nrgHighLD64; + if (valLD64 > maxValAboveLD64) { + maxValAboveLD64 = valLD64; + } + } + } + } + + if (maxValLD64 > mhThresh.derivThresMaxLD64 && + maxValAboveLD64 < mhThresh.derivThresAboveLD64) { + bLPsignal = 1; + + for (i = maxDerivPos - 1; i > maxDerivPos - 5 && i >= 0; i--) { + if (pNrgVector[i] != FL2FXCONST_DBL(0.0f) && + pNrgVector[i] > pNrgVector[maxDerivPos + 2]) { + nrgDiffLD64 = CalcLdData((pNrgVector[i] >> 1) - + (pNrgVector[maxDerivPos + 2] >> 1)); + nrgLD64 = CalcLdData(pNrgVector[i] >> 1); + valLD64 = nrgDiffLD64 - nrgLD64; + if (valLD64 < mhThresh.derivThresBelowLD64) { + bLPsignal = 0; + break; + } + } else { + bLPsignal = 0; + break; + } + } + } + + if (bLPsignal) { + for (i = 0; i < nSfb; i++) { + if (maxDerivPos >= pFreqBandTable[i] && + maxDerivPos < pFreqBandTable[i + 1]) + break; + } + + if (pAddHarmSfb[i]) { + pAddHarmSfb[i] = 0; + for (est = start; est < stop; est++) { + pDetectionVectors[est][i] = 0; + } + } + } +} + +/**************************************************************************/ +/*! + \brief Checks if it is allowed to detect a missing tone, that wasn't + detected previously. + + + \return newDetectionAllowed flag. + +*/ +/**************************************************************************/ +static INT isDetectionOfNewToneAllowed( + const SBR_FRAME_INFO *pFrameInfo, INT *pDetectionStartPos, + INT noEstPerFrame, INT prevTransientFrame, INT prevTransientPos, + INT prevTransientFlag, INT transientPosOffset, INT transientFlag, + INT transientPos, INT deltaTime, + HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector) { + INT transientFrame, newDetectionAllowed; + + /* Determine if this is a frame where a transient starts... + * If the transient flag was set the previous frame but not the + * transient frame flag, the transient frame flag is set in the current frame. + *****************************************************************************/ + transientFrame = 0; + if (transientFlag) { + if (transientPos + transientPosOffset < + pFrameInfo->borders[pFrameInfo->nEnvelopes]) { + transientFrame = 1; + if (noEstPerFrame > 1) { + if (transientPos + transientPosOffset > + h_sbrMissingHarmonicsDetector->timeSlots >> 1) { + *pDetectionStartPos = noEstPerFrame; + } else { + *pDetectionStartPos = noEstPerFrame >> 1; + } + + } else { + *pDetectionStartPos = noEstPerFrame; + } + } + } else { + if (prevTransientFlag && !prevTransientFrame) { + transientFrame = 1; + *pDetectionStartPos = 0; + } + } + + /* + * Determine if detection of new missing harmonics are allowed. + * If the frame contains a transient it's ok. If the previous + * frame contained a transient it needs to be sufficiently close + * to the start of the current frame. + ****************************************************************/ + newDetectionAllowed = 0; + if (transientFrame) { + newDetectionAllowed = 1; + } else { + if (prevTransientFrame && + fixp_abs(pFrameInfo->borders[0] - + (prevTransientPos + transientPosOffset - + h_sbrMissingHarmonicsDetector->timeSlots)) < deltaTime) { + newDetectionAllowed = 1; + *pDetectionStartPos = 0; + } + } + + h_sbrMissingHarmonicsDetector->previousTransientFlag = transientFlag; + h_sbrMissingHarmonicsDetector->previousTransientFrame = transientFrame; + h_sbrMissingHarmonicsDetector->previousTransientPos = transientPos; + + return (newDetectionAllowed); +} + +/**************************************************************************/ +/*! + \brief Cleans up the detection after a transient. + + + \return none. + +*/ +/**************************************************************************/ +static void transientCleanUp(FIXP_DBL **quotaBuffer, INT nSfb, + UCHAR **detectionVectors, UCHAR *pAddHarmSfb, + UCHAR *pPrevAddHarmSfb, INT **signBuffer, + const UCHAR *pFreqBandTable, INT start, INT stop, + INT newDetectionAllowed, FIXP_DBL *pNrgVector, + THRES_HOLDS mhThresh) { + INT i, j, est; + + for (est = start; est < stop; est++) { + for (i = 0; i < nSfb; i++) { + pAddHarmSfb[i] = pAddHarmSfb[i] || detectionVectors[est][i]; + } + } + + if (newDetectionAllowed == 1) { + /* + * Check for duplication of sines located + * on the border of two scf-bands. + *************************************************/ + for (i = 0; i < nSfb - 1; i++) { + /* detection in adjacent channels.*/ + if (pAddHarmSfb[i] && pAddHarmSfb[i + 1]) { + FIXP_DBL maxVal1, maxVal2; + INT maxPos1, maxPos2, maxPosTime1, maxPosTime2; + + INT li = pFreqBandTable[i]; + INT ui = pFreqBandTable[i + 1]; + + /* Find maximum tonality in the the two scf bands.*/ + maxPosTime1 = start; + maxPos1 = li; + maxVal1 = quotaBuffer[start][li]; + for (est = start; est < stop; est++) { + for (j = li; j < ui; j++) { + if (quotaBuffer[est][j] > maxVal1) { + maxVal1 = quotaBuffer[est][j]; + maxPos1 = j; + maxPosTime1 = est; + } + } + } + + li = pFreqBandTable[i + 1]; + ui = pFreqBandTable[i + 2]; + + /* Find maximum tonality in the the two scf bands.*/ + maxPosTime2 = start; + maxPos2 = li; + maxVal2 = quotaBuffer[start][li]; + for (est = start; est < stop; est++) { + for (j = li; j < ui; j++) { + if (quotaBuffer[est][j] > maxVal2) { + maxVal2 = quotaBuffer[est][j]; + maxPos2 = j; + maxPosTime2 = est; + } + } + } + + /* If the maximum values are in adjacent QMF-channels, we need to remove + the lowest of the two.*/ + if (maxPos2 - maxPos1 < 2) { + if (pPrevAddHarmSfb[i] == 1 && pPrevAddHarmSfb[i + 1] == 0) { + /* Keep the lower, remove the upper.*/ + pAddHarmSfb[i + 1] = 0; + for (est = start; est < stop; est++) { + detectionVectors[est][i + 1] = 0; + } + } else { + if (pPrevAddHarmSfb[i] == 0 && pPrevAddHarmSfb[i + 1] == 1) { + /* Keep the upper, remove the lower.*/ + pAddHarmSfb[i] = 0; + for (est = start; est < stop; est++) { + detectionVectors[est][i] = 0; + } + } else { + /* If the maximum values are in adjacent QMF-channels, and if the + signs indicate that it is the same sine, we need to remove the + lowest of the two.*/ + if (maxVal1 > maxVal2) { + if (signBuffer[maxPosTime1][maxPos2] < 0 && + signBuffer[maxPosTime1][maxPos1] > 0) { + /* Keep the lower, remove the upper.*/ + pAddHarmSfb[i + 1] = 0; + for (est = start; est < stop; est++) { + detectionVectors[est][i + 1] = 0; + } + } + } else { + if (signBuffer[maxPosTime2][maxPos2] < 0 && + signBuffer[maxPosTime2][maxPos1] > 0) { + /* Keep the upper, remove the lower.*/ + pAddHarmSfb[i] = 0; + for (est = start; est < stop; est++) { + detectionVectors[est][i] = 0; + } + } + } + } + } + } + } + } + + /* Make sure that the detection is not the cut-off of a low pass filter. */ + removeLowPassDetection(pAddHarmSfb, detectionVectors, start, stop, nSfb, + pFreqBandTable, pNrgVector, mhThresh); + } else { + /* + * If a missing harmonic wasn't missing the previous frame + * the transient-flag needs to be set in order to be allowed to detect it. + *************************************************************************/ + for (i = 0; i < nSfb; i++) { + if (pAddHarmSfb[i] - pPrevAddHarmSfb[i] > 0) pAddHarmSfb[i] = 0; + } + } +} + +/*****************************************************************************/ +/*! + \brief Detection for one tonality estimate. + + This is the actual missing harmonics detection, using information from the + previous detection. + + If a missing harmonic was detected (in a previous frame) due to too high + tonality differences, but there was not enough tonality difference in the + current frame, the detection algorithm still continues to trace the strongest + tone in the scalefactor band (assuming that this is the tone that is going to + be replaced in the decoder). This is done to avoid abrupt endings of sines + fading out (e.g. in the glockenspiel). + + The function also tries to estimate where one sine is going to be replaced + with multiple sines (due to the patching). This is done by comparing the + tonality flatness measure of the original and the SBR signal. + + The function also tries to estimate (for the scalefactor bands only + containing one qmf subband) when a strong tone in the original will be + replaced by a strong tone in the adjacent QMF subband. + + \return none. + +*/ +/**************************************************************************/ +static void detection(FIXP_DBL *quotaBuffer, FIXP_DBL *pDiffVecScfb, INT nSfb, + UCHAR *pHarmVec, const UCHAR *pFreqBandTable, + FIXP_DBL *sfmOrig, FIXP_DBL *sfmSbr, + GUIDE_VECTORS guideVectors, GUIDE_VECTORS newGuideVectors, + THRES_HOLDS mhThresh) { + INT i, j, ll, lu; + FIXP_DBL thresTemp, thresOrig; + + /* + * Do detection on the difference vector, i.e. the difference between + * the original and the transposed. + *********************************************************************/ + for (i = 0; i < nSfb; i++) { + thresTemp = (guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)) + ? fMax(fMult(mhThresh.decayGuideDiff, + guideVectors.guideVectorDiff[i]), + mhThresh.thresHoldDiffGuide) + : mhThresh.thresHoldDiff; + + thresTemp = fMin(thresTemp, mhThresh.thresHoldDiff); + + if (pDiffVecScfb[i] > thresTemp) { + pHarmVec[i] = 1; + newGuideVectors.guideVectorDiff[i] = pDiffVecScfb[i]; + } else { + /* If the guide wasn't zero, but the current level is to low, + start tracking the decay on the tone in the original rather + than the difference.*/ + if (guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)) { + guideVectors.guideVectorOrig[i] = mhThresh.thresHoldToneGuide; + } + } + } + + /* + * Trace tones in the original signal that at one point + * have been detected because they will be replaced by + * multiple tones in the sbr signal. + ****************************************************/ + + for (i = 0; i < nSfb; i++) { + ll = pFreqBandTable[i]; + lu = pFreqBandTable[i + 1]; + + thresOrig = + fixMax(fMult(guideVectors.guideVectorOrig[i], mhThresh.decayGuideOrig), + mhThresh.thresHoldToneGuide); + thresOrig = fixMin(thresOrig, mhThresh.thresHoldTone); + + if (guideVectors.guideVectorOrig[i] != FL2FXCONST_DBL(0.0f)) { + for (j = ll; j < lu; j++) { + if (quotaBuffer[j] > thresOrig) { + pHarmVec[i] = 1; + newGuideVectors.guideVectorOrig[i] = quotaBuffer[j]; + } + } + } + } + + /* + * Check for multiple sines in the transposed signal, + * where there is only one in the original. + ****************************************************/ + thresOrig = mhThresh.thresHoldTone; + + for (i = 0; i < nSfb; i++) { + ll = pFreqBandTable[i]; + lu = pFreqBandTable[i + 1]; + + if (pHarmVec[i] == 0) { + if (lu - ll > 1) { + for (j = ll; j < lu; j++) { + if (quotaBuffer[j] > thresOrig && + (sfmSbr[i] > mhThresh.sfmThresSbr && + sfmOrig[i] < mhThresh.sfmThresOrig)) { + pHarmVec[i] = 1; + newGuideVectors.guideVectorOrig[i] = quotaBuffer[j]; + } + } + } else { + if (i < nSfb - 1) { + ll = pFreqBandTable[i]; + + if (i > 0) { + if (quotaBuffer[ll] > mhThresh.thresHoldTone && + (pDiffVecScfb[i + 1] < mhThresh.invThresHoldTone || + pDiffVecScfb[i - 1] < mhThresh.invThresHoldTone)) { + pHarmVec[i] = 1; + newGuideVectors.guideVectorOrig[i] = quotaBuffer[ll]; + } + } else { + if (quotaBuffer[ll] > mhThresh.thresHoldTone && + pDiffVecScfb[i + 1] < mhThresh.invThresHoldTone) { + pHarmVec[i] = 1; + newGuideVectors.guideVectorOrig[i] = quotaBuffer[ll]; + } + } + } + } + } + } +} + +/**************************************************************************/ +/*! + \brief Do detection for every tonality estimate, using forward prediction. + + + \return none. + +*/ +/**************************************************************************/ +static void detectionWithPrediction( + FIXP_DBL **quotaBuffer, FIXP_DBL **pDiffVecScfb, INT **signBuffer, INT nSfb, + const UCHAR *pFreqBandTable, FIXP_DBL **sfmOrig, FIXP_DBL **sfmSbr, + UCHAR **detectionVectors, UCHAR *pPrevAddHarmSfb, + GUIDE_VECTORS *guideVectors, INT noEstPerFrame, INT detectionStart, + INT totNoEst, INT newDetectionAllowed, INT *pAddHarmFlag, + UCHAR *pAddHarmSfb, FIXP_DBL *pNrgVector, + const DETECTOR_PARAMETERS_MH *mhParams) { + INT est = 0, i; + INT start; + + FDKmemclear(pAddHarmSfb, nSfb * sizeof(UCHAR)); + + if (newDetectionAllowed) { + /* Since we don't want to use the transient region for detection (since the + tonality values tend to be a bit unreliable for this region) the + guide-values are copied to the current starting point. */ + if (totNoEst > 1) { + start = detectionStart + 1; + + if (start != 0) { + FDKmemcpy(guideVectors[start].guideVectorDiff, + guideVectors[0].guideVectorDiff, nSfb * sizeof(FIXP_DBL)); + FDKmemcpy(guideVectors[start].guideVectorOrig, + guideVectors[0].guideVectorOrig, nSfb * sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[start - 1].guideVectorDetected, + nSfb * sizeof(UCHAR)); + } + } else { + start = 0; + } + } else { + start = 0; + } + + for (est = start; est < totNoEst; est++) { + /* + * Do detection on the current frame using + * guide-info from the previous. + *******************************************/ + if (est > 0) { + FDKmemcpy(guideVectors[est].guideVectorDetected, + detectionVectors[est - 1], nSfb * sizeof(UCHAR)); + } + + FDKmemclear(detectionVectors[est], nSfb * sizeof(UCHAR)); + + if (est < totNoEst - 1) { + FDKmemclear(guideVectors[est + 1].guideVectorDiff, + nSfb * sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[est + 1].guideVectorOrig, + nSfb * sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[est + 1].guideVectorDetected, + nSfb * sizeof(UCHAR)); + + detection(quotaBuffer[est], pDiffVecScfb[est], nSfb, + detectionVectors[est], pFreqBandTable, sfmOrig[est], + sfmSbr[est], guideVectors[est], guideVectors[est + 1], + mhParams->thresHolds); + } else { + FDKmemclear(guideVectors[est].guideVectorDiff, nSfb * sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[est].guideVectorOrig, nSfb * sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[est].guideVectorDetected, nSfb * sizeof(UCHAR)); + + detection(quotaBuffer[est], pDiffVecScfb[est], nSfb, + detectionVectors[est], pFreqBandTable, sfmOrig[est], + sfmSbr[est], guideVectors[est], guideVectors[est], + mhParams->thresHolds); + } + } + + /* Clean up the detection.*/ + transientCleanUp(quotaBuffer, nSfb, detectionVectors, pAddHarmSfb, + pPrevAddHarmSfb, signBuffer, pFreqBandTable, start, totNoEst, + newDetectionAllowed, pNrgVector, mhParams->thresHolds); + + /* Set flag... */ + *pAddHarmFlag = 0; + for (i = 0; i < nSfb; i++) { + if (pAddHarmSfb[i]) { + *pAddHarmFlag = 1; + break; + } + } + + FDKmemcpy(pPrevAddHarmSfb, pAddHarmSfb, nSfb * sizeof(UCHAR)); + FDKmemcpy(guideVectors[0].guideVectorDetected, pAddHarmSfb, + nSfb * sizeof(INT)); + + for (i = 0; i < nSfb; i++) { + guideVectors[0].guideVectorDiff[i] = FL2FXCONST_DBL(0.0f); + guideVectors[0].guideVectorOrig[i] = FL2FXCONST_DBL(0.0f); + + if (pAddHarmSfb[i] == 1) { + /* If we had a detection use the guide-value in the next frame from the + last estimate were the detection was done.*/ + for (est = start; est < totNoEst; est++) { + if (guideVectors[est].guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)) { + guideVectors[0].guideVectorDiff[i] = + guideVectors[est].guideVectorDiff[i]; + } + if (guideVectors[est].guideVectorOrig[i] != FL2FXCONST_DBL(0.0f)) { + guideVectors[0].guideVectorOrig[i] = + guideVectors[est].guideVectorOrig[i]; + } + } + } + } +} + +/**************************************************************************/ +/*! + \brief Calculates a compensation vector for the energy data. + + This function calculates a compensation vector for the energy data (i.e. + envelope data) that is calculated elsewhere. This is since, one sine on + the border of two scalefactor bands, will be replace by one sine in the + middle of either scalefactor band. However, since the sine that is replaced + will influence the energy estimate in both scalefactor bands (in the envelops + calculation function) a compensation value is required in order to avoid + noise substitution in the decoder next to the synthetic sine. + + \return none. + +*/ +/**************************************************************************/ +static void calculateCompVector(UCHAR *pAddHarmSfb, FIXP_DBL **pTonalityMatrix, + INT **pSignMatrix, UCHAR *pEnvComp, INT nSfb, + const UCHAR *freqBandTable, INT totNoEst, + INT maxComp, UCHAR *pPrevEnvComp, + INT newDetectionAllowed) { + INT scfBand, est, l, ll, lu, maxPosF, maxPosT; + FIXP_DBL maxVal; + INT compValue; + FIXP_DBL tmp; + + FDKmemclear(pEnvComp, nSfb * sizeof(UCHAR)); + + for (scfBand = 0; scfBand < nSfb; scfBand++) { + if (pAddHarmSfb[scfBand]) { /* A missing sine was detected */ + ll = freqBandTable[scfBand]; + lu = freqBandTable[scfBand + 1]; + + maxPosF = 0; /* First find the maximum*/ + maxPosT = 0; + maxVal = FL2FXCONST_DBL(0.0f); + + for (est = 0; est < totNoEst; est++) { + for (l = ll; l < lu; l++) { + if (pTonalityMatrix[est][l] > maxVal) { + maxVal = pTonalityMatrix[est][l]; + maxPosF = l; + maxPosT = est; + } + } + } + + /* + * If the maximum tonality is at the lower border of the + * scalefactor band, we check the sign of the adjacent channels + * to see if this sine is shared by the lower channel. If so, the + * energy of the single sine will be present in two scalefactor bands + * in the SBR data, which will cause problems in the decoder, when we + * add a sine to just one of the channels. + *********************************************************************/ + if (maxPosF == ll && scfBand) { + if (!pAddHarmSfb[scfBand - 1]) { /* No detection below*/ + if (pSignMatrix[maxPosT][maxPosF - 1] > 0 && + pSignMatrix[maxPosT][maxPosF] < 0) { + /* The comp value is calulated as the tonallity value, i.e we want + to reduce the envelope data for this channel with as much as the + tonality that is spread from the channel above. (ld64(RELAXATION) + = 0.31143075889) */ + tmp = fixp_abs( + (FIXP_DBL)CalcLdData(pTonalityMatrix[maxPosT][maxPosF - 1]) + + RELAXATION_LD64); + tmp = (tmp >> (DFRACT_BITS - 1 - LD_DATA_SHIFT - 1)) + + (FIXP_DBL)1; /* shift one bit less for rounding */ + compValue = ((INT)(LONG)tmp) >> 1; + + /* limit the comp-value*/ + if (compValue > maxComp) compValue = maxComp; + + pEnvComp[scfBand - 1] = compValue; + } + } + } + + /* + * Same as above, but for the upper end of the scalefactor-band. + ***************************************************************/ + if (maxPosF == lu - 1 && scfBand + 1 < nSfb) { /* Upper border*/ + if (!pAddHarmSfb[scfBand + 1]) { + if (pSignMatrix[maxPosT][maxPosF] > 0 && + pSignMatrix[maxPosT][maxPosF + 1] < 0) { + tmp = fixp_abs( + (FIXP_DBL)CalcLdData(pTonalityMatrix[maxPosT][maxPosF + 1]) + + RELAXATION_LD64); + tmp = (tmp >> (DFRACT_BITS - 1 - LD_DATA_SHIFT - 1)) + + (FIXP_DBL)1; /* shift one bit less for rounding */ + compValue = ((INT)(LONG)tmp) >> 1; + + if (compValue > maxComp) compValue = maxComp; + + pEnvComp[scfBand + 1] = compValue; + } + } + } + } + } + + if (newDetectionAllowed == 0) { + for (scfBand = 0; scfBand < nSfb; scfBand++) { + if (pEnvComp[scfBand] != 0 && pPrevEnvComp[scfBand] == 0) + pEnvComp[scfBand] = 0; + } + } + + /* remember the value for the next frame.*/ + FDKmemcpy(pPrevEnvComp, pEnvComp, nSfb * sizeof(UCHAR)); +} + +/**************************************************************************/ +/*! + \brief Detects where strong tonal components will be missing after + HFR in the decoder. + + + \return none. + +*/ +/**************************************************************************/ +void FDKsbrEnc_SbrMissingHarmonicsDetectorQmf( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMHDet, FIXP_DBL **pQuotaBuffer, + INT **pSignBuffer, SCHAR *indexVector, const SBR_FRAME_INFO *pFrameInfo, + const UCHAR *pTranInfo, INT *pAddHarmonicsFlag, + UCHAR *pAddHarmonicsScaleFactorBands, const UCHAR *freqBandTable, INT nSfb, + UCHAR *envelopeCompensation, FIXP_DBL *pNrgVector) { + INT transientFlag = pTranInfo[1]; + INT transientPos = pTranInfo[0]; + INT newDetectionAllowed; + INT transientDetStart = 0; + + UCHAR **detectionVectors = h_sbrMHDet->detectionVectors; + INT move = h_sbrMHDet->move; + INT noEstPerFrame = h_sbrMHDet->noEstPerFrame; + INT totNoEst = h_sbrMHDet->totNoEst; + INT prevTransientFlag = h_sbrMHDet->previousTransientFlag; + INT prevTransientFrame = h_sbrMHDet->previousTransientFrame; + INT transientPosOffset = h_sbrMHDet->transientPosOffset; + INT prevTransientPos = h_sbrMHDet->previousTransientPos; + GUIDE_VECTORS *guideVectors = h_sbrMHDet->guideVectors; + INT deltaTime = h_sbrMHDet->mhParams->deltaTime; + INT maxComp = h_sbrMHDet->mhParams->maxComp; + + int est; + + /* + Buffer values. + */ + FDK_ASSERT(move <= (MAX_NO_OF_ESTIMATES >> 1)); + FDK_ASSERT(noEstPerFrame <= (MAX_NO_OF_ESTIMATES >> 1)); + + FIXP_DBL *sfmSbr[MAX_NO_OF_ESTIMATES]; + FIXP_DBL *sfmOrig[MAX_NO_OF_ESTIMATES]; + FIXP_DBL *tonalityDiff[MAX_NO_OF_ESTIMATES]; + + for (est = 0; est < MAX_NO_OF_ESTIMATES / 2; est++) { + sfmSbr[est] = h_sbrMHDet->sfmSbr[est]; + sfmOrig[est] = h_sbrMHDet->sfmOrig[est]; + tonalityDiff[est] = h_sbrMHDet->tonalityDiff[est]; + } + + C_ALLOC_SCRATCH_START(_scratch, FIXP_DBL, + 3 * MAX_NO_OF_ESTIMATES / 2 * MAX_FREQ_COEFFS) + FIXP_DBL *scratch = _scratch; + for (; est < MAX_NO_OF_ESTIMATES; est++) { + sfmSbr[est] = scratch; + scratch += MAX_FREQ_COEFFS; + sfmOrig[est] = scratch; + scratch += MAX_FREQ_COEFFS; + tonalityDiff[est] = scratch; + scratch += MAX_FREQ_COEFFS; + } + + /* Determine if we're allowed to detect "missing harmonics" that wasn't + detected before. In order to be allowed to do new detection, there must be + a transient in the current frame, or a transient in the previous frame + sufficiently close to the current frame. */ + newDetectionAllowed = isDetectionOfNewToneAllowed( + pFrameInfo, &transientDetStart, noEstPerFrame, prevTransientFrame, + prevTransientPos, prevTransientFlag, transientPosOffset, transientFlag, + transientPos, deltaTime, h_sbrMHDet); + + /* Calulate the variables that will be used subsequently for the actual + * detection */ + calculateDetectorInput(pQuotaBuffer, indexVector, tonalityDiff, sfmOrig, + sfmSbr, freqBandTable, nSfb, noEstPerFrame, move); + + /* Do the actual detection using information from previous detections */ + detectionWithPrediction(pQuotaBuffer, tonalityDiff, pSignBuffer, nSfb, + freqBandTable, sfmOrig, sfmSbr, detectionVectors, + h_sbrMHDet->guideScfb, guideVectors, noEstPerFrame, + transientDetStart, totNoEst, newDetectionAllowed, + pAddHarmonicsFlag, pAddHarmonicsScaleFactorBands, + pNrgVector, h_sbrMHDet->mhParams); + + /* Calculate the comp vector, so that the energy can be + compensated for a sine between two QMF-bands. */ + calculateCompVector(pAddHarmonicsScaleFactorBands, pQuotaBuffer, pSignBuffer, + envelopeCompensation, nSfb, freqBandTable, totNoEst, + maxComp, h_sbrMHDet->prevEnvelopeCompensation, + newDetectionAllowed); + + for (est = 0; est < move; est++) { + FDKmemcpy(tonalityDiff[est], tonalityDiff[est + noEstPerFrame], + sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + FDKmemcpy(sfmOrig[est], sfmOrig[est + noEstPerFrame], + sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + FDKmemcpy(sfmSbr[est], sfmSbr[est + noEstPerFrame], + sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + } + C_ALLOC_SCRATCH_END(_scratch, FIXP_DBL, + 3 * MAX_NO_OF_ESTIMATES / 2 * MAX_FREQ_COEFFS) +} + +/**************************************************************************/ +/*! + \brief Initialize an instance of the missing harmonics detector. + + + \return errorCode, noError if OK. + +*/ +/**************************************************************************/ +INT FDKsbrEnc_CreateSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet, INT chan) { + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet; + INT i; + + UCHAR *detectionVectors = GetRam_Sbr_detectionVectors(chan); + UCHAR *guideVectorDetected = GetRam_Sbr_guideVectorDetected(chan); + FIXP_DBL *guideVectorDiff = GetRam_Sbr_guideVectorDiff(chan); + FIXP_DBL *guideVectorOrig = GetRam_Sbr_guideVectorOrig(chan); + + FDKmemclear(hs, sizeof(SBR_MISSING_HARMONICS_DETECTOR)); + + hs->prevEnvelopeCompensation = GetRam_Sbr_prevEnvelopeCompensation(chan); + hs->guideScfb = GetRam_Sbr_guideScfb(chan); + + if ((NULL == detectionVectors) || (NULL == guideVectorDetected) || + (NULL == guideVectorDiff) || (NULL == guideVectorOrig) || + (NULL == hs->prevEnvelopeCompensation) || (NULL == hs->guideScfb)) { + goto bail; + } + + for (i = 0; i < MAX_NO_OF_ESTIMATES; i++) { + hs->guideVectors[i].guideVectorDiff = + guideVectorDiff + (i * MAX_FREQ_COEFFS); + hs->guideVectors[i].guideVectorOrig = + guideVectorOrig + (i * MAX_FREQ_COEFFS); + hs->detectionVectors[i] = detectionVectors + (i * MAX_FREQ_COEFFS); + hs->guideVectors[i].guideVectorDetected = + guideVectorDetected + (i * MAX_FREQ_COEFFS); + } + + return 0; + +bail: + hs->guideVectors[0].guideVectorDiff = guideVectorDiff; + hs->guideVectors[0].guideVectorOrig = guideVectorOrig; + hs->detectionVectors[0] = detectionVectors; + hs->guideVectors[0].guideVectorDetected = guideVectorDetected; + + FDKsbrEnc_DeleteSbrMissingHarmonicsDetector(hs); + return -1; +} + +/**************************************************************************/ +/*! + \brief Initialize an instance of the missing harmonics detector. + + + \return errorCode, noError if OK. + +*/ +/**************************************************************************/ +INT FDKsbrEnc_InitSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet, INT sampleFreq, + INT frameSize, INT nSfb, INT qmfNoChannels, INT totNoEst, INT move, + INT noEstPerFrame, UINT sbrSyntaxFlags) { + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet; + int i; + + FDK_ASSERT(totNoEst <= MAX_NO_OF_ESTIMATES); + + if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + switch (frameSize) { + case 1024: + case 512: + hs->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; + hs->timeSlots = 16; + break; + case 960: + case 480: + hs->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; + hs->timeSlots = 15; + break; + default: + return -1; + } + } else { + switch (frameSize) { + case 2048: + case 1024: + hs->transientPosOffset = FRAME_MIDDLE_SLOT_2048; + hs->timeSlots = NUMBER_TIME_SLOTS_2048; + break; + case 1920: + case 960: + hs->transientPosOffset = FRAME_MIDDLE_SLOT_1920; + hs->timeSlots = NUMBER_TIME_SLOTS_1920; + break; + default: + return -1; + } + } + + if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + hs->mhParams = ¶msAacLd; + } else + hs->mhParams = ¶msAac; + + hs->qmfNoChannels = qmfNoChannels; + hs->sampleFreq = sampleFreq; + hs->nSfb = nSfb; + + hs->totNoEst = totNoEst; + hs->move = move; + hs->noEstPerFrame = noEstPerFrame; + + for (i = 0; i < totNoEst; i++) { + FDKmemclear(hs->guideVectors[i].guideVectorDiff, + sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + FDKmemclear(hs->guideVectors[i].guideVectorOrig, + sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + FDKmemclear(hs->detectionVectors[i], sizeof(UCHAR) * MAX_FREQ_COEFFS); + FDKmemclear(hs->guideVectors[i].guideVectorDetected, + sizeof(UCHAR) * MAX_FREQ_COEFFS); + } + + // for(i=0; itonalityDiff[i], sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + FDKmemclear(hs->sfmOrig[i], sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + FDKmemclear(hs->sfmSbr[i], sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + } + + FDKmemclear(hs->prevEnvelopeCompensation, sizeof(UCHAR) * MAX_FREQ_COEFFS); + FDKmemclear(hs->guideScfb, sizeof(UCHAR) * MAX_FREQ_COEFFS); + + hs->previousTransientFlag = 0; + hs->previousTransientFrame = 0; + hs->previousTransientPos = 0; + + return (0); +} + +/**************************************************************************/ +/*! + \brief Deletes an instance of the missing harmonics detector. + + + \return none. + +*/ +/**************************************************************************/ +void FDKsbrEnc_DeleteSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet) { + if (hSbrMHDet) { + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet; + + FreeRam_Sbr_detectionVectors(&hs->detectionVectors[0]); + FreeRam_Sbr_guideVectorDetected(&hs->guideVectors[0].guideVectorDetected); + FreeRam_Sbr_guideVectorDiff(&hs->guideVectors[0].guideVectorDiff); + FreeRam_Sbr_guideVectorOrig(&hs->guideVectors[0].guideVectorOrig); + FreeRam_Sbr_prevEnvelopeCompensation(&hs->prevEnvelopeCompensation); + FreeRam_Sbr_guideScfb(&hs->guideScfb); + } +} + +/**************************************************************************/ +/*! + \brief Resets an instance of the missing harmonics detector. + + + \return error code, noError if OK. + +*/ +/**************************************************************************/ +INT FDKsbrEnc_ResetSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMissingHarmonicsDetector, + INT nSfb) { + int i; + FIXP_DBL tempGuide[MAX_FREQ_COEFFS]; + UCHAR tempGuideInt[MAX_FREQ_COEFFS]; + INT nSfbPrev; + + nSfbPrev = hSbrMissingHarmonicsDetector->nSfb; + hSbrMissingHarmonicsDetector->nSfb = nSfb; + + FDKmemcpy(tempGuideInt, hSbrMissingHarmonicsDetector->guideScfb, + nSfbPrev * sizeof(UCHAR)); + + if (nSfb > nSfbPrev) { + for (i = 0; i < (nSfb - nSfbPrev); i++) { + hSbrMissingHarmonicsDetector->guideScfb[i] = 0; + } + + for (i = 0; i < nSfbPrev; i++) { + hSbrMissingHarmonicsDetector->guideScfb[i + (nSfb - nSfbPrev)] = + tempGuideInt[i]; + } + } else { + for (i = 0; i < nSfb; i++) { + hSbrMissingHarmonicsDetector->guideScfb[i] = + tempGuideInt[i + (nSfbPrev - nSfb)]; + } + } + + FDKmemcpy(tempGuide, + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff, + nSfbPrev * sizeof(FIXP_DBL)); + + if (nSfb > nSfbPrev) { + for (i = 0; i < (nSfb - nSfbPrev); i++) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i] = + FL2FXCONST_DBL(0.0f); + } + + for (i = 0; i < nSfbPrev; i++) { + hSbrMissingHarmonicsDetector->guideVectors[0] + .guideVectorDiff[i + (nSfb - nSfbPrev)] = tempGuide[i]; + } + } else { + for (i = 0; i < nSfb; i++) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i] = + tempGuide[i + (nSfbPrev - nSfb)]; + } + } + + FDKmemcpy(tempGuide, + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig, + nSfbPrev * sizeof(FIXP_DBL)); + + if (nSfb > nSfbPrev) { + for (i = 0; i < (nSfb - nSfbPrev); i++) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i] = + FL2FXCONST_DBL(0.0f); + } + + for (i = 0; i < nSfbPrev; i++) { + hSbrMissingHarmonicsDetector->guideVectors[0] + .guideVectorOrig[i + (nSfb - nSfbPrev)] = tempGuide[i]; + } + } else { + for (i = 0; i < nSfb; i++) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i] = + tempGuide[i + (nSfbPrev - nSfb)]; + } + } + + FDKmemcpy(tempGuideInt, + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected, + nSfbPrev * sizeof(UCHAR)); + + if (nSfb > nSfbPrev) { + for (i = 0; i < (nSfb - nSfbPrev); i++) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i] = 0; + } + + for (i = 0; i < nSfbPrev; i++) { + hSbrMissingHarmonicsDetector->guideVectors[0] + .guideVectorDetected[i + (nSfb - nSfbPrev)] = tempGuideInt[i]; + } + } else { + for (i = 0; i < nSfb; i++) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i] = + tempGuideInt[i + (nSfbPrev - nSfb)]; + } + } + + FDKmemcpy(tempGuideInt, + hSbrMissingHarmonicsDetector->prevEnvelopeCompensation, + nSfbPrev * sizeof(UCHAR)); + + if (nSfb > nSfbPrev) { + for (i = 0; i < (nSfb - nSfbPrev); i++) { + hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i] = 0; + } + + for (i = 0; i < nSfbPrev; i++) { + hSbrMissingHarmonicsDetector + ->prevEnvelopeCompensation[i + (nSfb - nSfbPrev)] = tempGuideInt[i]; + } + } else { + for (i = 0; i < nSfb; i++) { + hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i] = + tempGuideInt[i + (nSfbPrev - nSfb)]; + } + } + + return 0; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/mh_det.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/mh_det.h new file mode 100644 index 0000000000000..89d81b5f373f8 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/mh_det.h @@ -0,0 +1,204 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief missing harmonics detection header file $Revision: 92790 $ +*/ + +#ifndef MH_DET_H +#define MH_DET_H + +#include "sbr_encoder.h" +#include "fram_gen.h" + +typedef struct { + FIXP_DBL thresHoldDiff; /*!< threshold for tonality difference */ + FIXP_DBL thresHoldDiffGuide; /*!< threshold for tonality difference for the + guide */ + FIXP_DBL thresHoldTone; /*!< threshold for tonality for a sine */ + FIXP_DBL invThresHoldTone; + FIXP_DBL thresHoldToneGuide; /*!< threshold for tonality for a sine for the + guide */ + FIXP_DBL sfmThresSbr; /*!< tonality flatness measure threshold for the SBR + signal.*/ + FIXP_DBL sfmThresOrig; /*!< tonality flatness measure threshold for the + original signal.*/ + FIXP_DBL decayGuideOrig; /*!< decay value of the tonality value of the guide + for the tone. */ + FIXP_DBL decayGuideDiff; /*!< decay value of the tonality value of the guide + for the tonality difference. */ + FIXP_DBL derivThresMaxLD64; /*!< threshold for detecting LP character in a + signal. */ + FIXP_DBL derivThresBelowLD64; /*!< threshold for detecting LP character in a + signal. */ + FIXP_DBL derivThresAboveLD64; /*!< threshold for detecting LP character in a + signal. */ +} THRES_HOLDS; + +typedef struct { + INT deltaTime; /*!< maximum allowed transient distance (from frame border in + number of qmf subband sample) for a frame to be considered a + transient frame.*/ + THRES_HOLDS thresHolds; /*!< the thresholds used for detection. */ + INT maxComp; /*!< maximum alllowed compensation factor for the envelope data. + */ +} DETECTOR_PARAMETERS_MH; + +typedef struct { + FIXP_DBL *guideVectorDiff; + FIXP_DBL *guideVectorOrig; + UCHAR *guideVectorDetected; +} GUIDE_VECTORS; + +typedef struct { + INT qmfNoChannels; + INT nSfb; + INT sampleFreq; + INT previousTransientFlag; + INT previousTransientFrame; + INT previousTransientPos; + + INT noVecPerFrame; + INT transientPosOffset; + + INT move; + INT totNoEst; + INT noEstPerFrame; + INT timeSlots; + + UCHAR *guideScfb; + UCHAR *prevEnvelopeCompensation; + UCHAR *detectionVectors[MAX_NO_OF_ESTIMATES]; + FIXP_DBL tonalityDiff[MAX_NO_OF_ESTIMATES / 2][MAX_FREQ_COEFFS]; + FIXP_DBL sfmOrig[MAX_NO_OF_ESTIMATES / 2][MAX_FREQ_COEFFS]; + FIXP_DBL sfmSbr[MAX_NO_OF_ESTIMATES / 2][MAX_FREQ_COEFFS]; + const DETECTOR_PARAMETERS_MH *mhParams; + GUIDE_VECTORS guideVectors[MAX_NO_OF_ESTIMATES]; +} SBR_MISSING_HARMONICS_DETECTOR; + +typedef SBR_MISSING_HARMONICS_DETECTOR *HANDLE_SBR_MISSING_HARMONICS_DETECTOR; + +void FDKsbrEnc_SbrMissingHarmonicsDetectorQmf( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector, + FIXP_DBL **pQuotaBuffer, INT **pSignBuffer, SCHAR *indexVector, + const SBR_FRAME_INFO *pFrameInfo, const UCHAR *pTranInfo, + INT *pAddHarmonicsFlag, UCHAR *pAddHarmonicsScaleFactorBands, + const UCHAR *freqBandTable, INT nSfb, UCHAR *envelopeCompensation, + FIXP_DBL *pNrgVector); + +INT FDKsbrEnc_CreateSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet, INT chan); + +INT FDKsbrEnc_InitSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector, + INT sampleFreq, INT frameSize, INT nSfb, INT qmfNoChannels, INT totNoEst, + INT move, INT noEstPerFrame, UINT sbrSyntaxFlags); + +void FDKsbrEnc_DeleteSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector); + +INT FDKsbrEnc_ResetSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMissingHarmonicsDetector, + INT nSfb); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/nf_est.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/nf_est.cpp new file mode 100644 index 0000000000000..290ec354ed321 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/nf_est.cpp @@ -0,0 +1,612 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "nf_est.h" + +#include "sbr_misc.h" + +#include "genericStds.h" + +/* smoothFilter[4] = {0.05857864376269f, 0.2f, 0.34142135623731f, 0.4f}; */ +static const FIXP_DBL smoothFilter[4] = {0x077f813d, 0x19999995, 0x2bb3b1f5, + 0x33333335}; + +/* static const INT smoothFilterLength = 4; */ + +static const FIXP_DBL QuantOffset = (INT)0xfc000000; /* ld64(0.25) */ + +#ifndef min +#define min(a, b) (a < b ? a : b) +#endif + +#ifndef max +#define max(a, b) (a > b ? a : b) +#endif + +#define NOISE_FLOOR_OFFSET_SCALING (4) + +/**************************************************************************/ +/*! + \brief The function applies smoothing to the noise levels. + + + + \return none + +*/ +/**************************************************************************/ +static void smoothingOfNoiseLevels( + FIXP_DBL *NoiseLevels, /*!< pointer to noise-floor levels.*/ + INT nEnvelopes, /*!< Number of noise floor envelopes.*/ + INT noNoiseBands, /*!< Number of noise bands for every noise floor envelope. + */ + FIXP_DBL prevNoiseLevels[NF_SMOOTHING_LENGTH] + [MAX_NUM_NOISE_VALUES], /*!< Previous noise floor + envelopes. */ + const FIXP_DBL * + pSmoothFilter, /*!< filter used for smoothing the noise floor levels. */ + INT transientFlag) /*!< flag indicating if a transient is present*/ + +{ + INT i, band, env; + FIXP_DBL accu; + + for (env = 0; env < nEnvelopes; env++) { + if (transientFlag) { + for (i = 0; i < NF_SMOOTHING_LENGTH; i++) { + FDKmemcpy(prevNoiseLevels[i], NoiseLevels + env * noNoiseBands, + noNoiseBands * sizeof(FIXP_DBL)); + } + } else { + for (i = 1; i < NF_SMOOTHING_LENGTH; i++) { + FDKmemcpy(prevNoiseLevels[i - 1], prevNoiseLevels[i], + noNoiseBands * sizeof(FIXP_DBL)); + } + FDKmemcpy(prevNoiseLevels[NF_SMOOTHING_LENGTH - 1], + NoiseLevels + env * noNoiseBands, + noNoiseBands * sizeof(FIXP_DBL)); + } + + for (band = 0; band < noNoiseBands; band++) { + accu = FL2FXCONST_DBL(0.0f); + for (i = 0; i < NF_SMOOTHING_LENGTH; i++) { + accu += fMultDiv2(pSmoothFilter[i], prevNoiseLevels[i][band]); + } + FDK_ASSERT((band + env * noNoiseBands) < MAX_NUM_NOISE_VALUES); + NoiseLevels[band + env * noNoiseBands] = accu << 1; + } + } +} + +/**************************************************************************/ +/*! + \brief Does the noise floor level estiamtion. + + The noiseLevel samples are scaled by the factor 0.25 + + \return none + +*/ +/**************************************************************************/ +static void qmfBasedNoiseFloorDetection( + FIXP_DBL *noiseLevel, /*!< Pointer to vector to + store the noise levels + in.*/ + FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the quota + values of the original. */ + SCHAR *indexVector, /*!< Index vector to obtain the + patched data. */ + INT startIndex, /*!< Start index. */ + INT stopIndex, /*!< Stop index. */ + INT startChannel, /*!< Start channel of the current + noise floor band.*/ + INT stopChannel, /*!< Stop channel of the current + noise floor band. */ + FIXP_DBL ana_max_level, /*!< Maximum level of the + adaptive noise.*/ + FIXP_DBL noiseFloorOffset, /*!< Noise floor offset. */ + INT missingHarmonicFlag, /*!< Flag indicating if a + strong tonal component + is missing.*/ + FIXP_DBL weightFac, /*!< Weightening factor for the + difference between orig and sbr. + */ + INVF_MODE diffThres, /*!< Threshold value to control the + inverse filtering decision.*/ + INVF_MODE inverseFilteringLevel) /*!< Inverse filtering + level of the current + band.*/ +{ + INT scale, l, k; + FIXP_DBL meanOrig = FL2FXCONST_DBL(0.0f), meanSbr = FL2FXCONST_DBL(0.0f), + diff; + FIXP_DBL invIndex = GetInvInt(stopIndex - startIndex); + FIXP_DBL invChannel = GetInvInt(stopChannel - startChannel); + FIXP_DBL accu; + + /* + Calculate the mean value, over the current time segment, for the original, the + HFR and the difference, over all channels in the current frequency range. + */ + + if (missingHarmonicFlag == 1) { + for (l = startChannel; l < stopChannel; l++) { + /* tonalityOrig */ + accu = FL2FXCONST_DBL(0.0f); + for (k = startIndex; k < stopIndex; k++) { + accu += fMultDiv2(quotaMatrixOrig[k][l], invIndex); + } + meanOrig = fixMax(meanOrig, (accu << 1)); + + /* tonalitySbr */ + accu = FL2FXCONST_DBL(0.0f); + for (k = startIndex; k < stopIndex; k++) { + accu += fMultDiv2(quotaMatrixOrig[k][indexVector[l]], invIndex); + } + meanSbr = fixMax(meanSbr, (accu << 1)); + } + } else { + for (l = startChannel; l < stopChannel; l++) { + /* tonalityOrig */ + accu = FL2FXCONST_DBL(0.0f); + for (k = startIndex; k < stopIndex; k++) { + accu += fMultDiv2(quotaMatrixOrig[k][l], invIndex); + } + meanOrig += fMult((accu << 1), invChannel); + + /* tonalitySbr */ + accu = FL2FXCONST_DBL(0.0f); + for (k = startIndex; k < stopIndex; k++) { + accu += fMultDiv2(quotaMatrixOrig[k][indexVector[l]], invIndex); + } + meanSbr += fMult((accu << 1), invChannel); + } + } + + /* Small fix to avoid noise during silent passages.*/ + if (meanOrig <= FL2FXCONST_DBL(0.000976562f * RELAXATION_FLOAT) && + meanSbr <= FL2FXCONST_DBL(0.000976562f * RELAXATION_FLOAT)) { + meanOrig = FL2FXCONST_DBL(101.5936673f * RELAXATION_FLOAT); + meanSbr = FL2FXCONST_DBL(101.5936673f * RELAXATION_FLOAT); + } + + meanOrig = fixMax(meanOrig, RELAXATION); + meanSbr = fixMax(meanSbr, RELAXATION); + + if (missingHarmonicFlag == 1 || inverseFilteringLevel == INVF_MID_LEVEL || + inverseFilteringLevel == INVF_LOW_LEVEL || + inverseFilteringLevel == INVF_OFF || inverseFilteringLevel <= diffThres) { + diff = RELAXATION; + } else { + accu = fDivNorm(meanSbr, meanOrig, &scale); + + diff = fixMax(RELAXATION, fMult(RELAXATION_FRACT, fMult(weightFac, accu)) >> + (RELAXATION_SHIFT - scale)); + } + + /* + * noise Level is now a positive value, i.e. + * the more harmonic the signal is the higher noise level, + * this makes no sense so we change the sign. + *********************************************************/ + accu = fDivNorm(diff, meanOrig, &scale); + scale -= 2; + + if ((scale > 0) && (accu > ((FIXP_DBL)MAXVAL_DBL) >> scale)) { + *noiseLevel = (FIXP_DBL)MAXVAL_DBL; + } else { + *noiseLevel = scaleValue(accu, scale); + } + + /* + * Add a noise floor offset to compensate for bias in the detector + *****************************************************************/ + if (!missingHarmonicFlag) { + *noiseLevel = fixMin(fMult(*noiseLevel, noiseFloorOffset), + (FIXP_DBL)MAXVAL_DBL >> NOISE_FLOOR_OFFSET_SCALING) + << NOISE_FLOOR_OFFSET_SCALING; + } + + /* + * check to see that we don't exceed the maximum allowed level + **************************************************************/ + *noiseLevel = + fixMin(*noiseLevel, + ana_max_level); /* ana_max_level is scaled with factor 0.25 */ +} + +/**************************************************************************/ +/*! + \brief Does the noise floor level estiamtion. + The function calls the Noisefloor estimation function + for the time segments decided based upon the transient + information. The block is always divided into one or two segments. + + + \return none + +*/ +/**************************************************************************/ +void FDKsbrEnc_sbrNoiseFloorEstimateQmf( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + const SBR_FRAME_INFO + *frame_info, /*!< Time frequency grid of the current frame. */ + FIXP_DBL + *noiseLevels, /*!< Pointer to vector to store the noise levels in.*/ + FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the quota values of the + original. */ + SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ + INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component + will be missing. */ + INT startIndex, /*!< Start index. */ + UINT numberOfEstimatesPerFrame, /*!< The number of tonality estimates per + frame. */ + int transientFrame, /*!< A flag indicating if a transient is present. */ + INVF_MODE *pInvFiltLevels, /*!< Pointer to the vector holding the inverse + filtering levels. */ + UINT sbrSyntaxFlags) + +{ + INT nNoiseEnvelopes, startPos[2], stopPos[2], env, band; + + INT noNoiseBands = h_sbrNoiseFloorEstimate->noNoiseBands; + INT *freqBandTable = h_sbrNoiseFloorEstimate->freqBandTableQmf; + + nNoiseEnvelopes = frame_info->nNoiseEnvelopes; + + startPos[0] = startIndex; + + if (nNoiseEnvelopes == 1) { + stopPos[0] = startIndex + min(numberOfEstimatesPerFrame, 2); + } else { + stopPos[0] = startIndex + 1; + startPos[1] = startIndex + 1; + stopPos[1] = startIndex + min(numberOfEstimatesPerFrame, 2); + } + + /* + * Estimate the noise floor. + **************************************/ + for (env = 0; env < nNoiseEnvelopes; env++) { + for (band = 0; band < noNoiseBands; band++) { + FDK_ASSERT((band + env * noNoiseBands) < MAX_NUM_NOISE_VALUES); + qmfBasedNoiseFloorDetection( + &noiseLevels[band + env * noNoiseBands], quotaMatrixOrig, indexVector, + startPos[env], stopPos[env], freqBandTable[band], + freqBandTable[band + 1], h_sbrNoiseFloorEstimate->ana_max_level, + h_sbrNoiseFloorEstimate->noiseFloorOffset[band], missingHarmonicsFlag, + h_sbrNoiseFloorEstimate->weightFac, + h_sbrNoiseFloorEstimate->diffThres, pInvFiltLevels[band]); + } + } + + /* + * Smoothing of the values. + **************************/ + smoothingOfNoiseLevels(noiseLevels, nNoiseEnvelopes, + h_sbrNoiseFloorEstimate->noNoiseBands, + h_sbrNoiseFloorEstimate->prevNoiseLevels, + h_sbrNoiseFloorEstimate->smoothFilter, transientFrame); + + /* quantisation*/ + for (env = 0; env < nNoiseEnvelopes; env++) { + for (band = 0; band < noNoiseBands; band++) { + FDK_ASSERT((band + env * noNoiseBands) < MAX_NUM_NOISE_VALUES); + noiseLevels[band + env * noNoiseBands] = + (FIXP_DBL)NOISE_FLOOR_OFFSET_64 - + (FIXP_DBL)CalcLdData(noiseLevels[band + env * noNoiseBands] + + (FIXP_DBL)1) + + QuantOffset; + } + } +} + +/**************************************************************************/ +/*! + \brief + + + \return errorCode, noError if successful + +*/ +/**************************************************************************/ +static INT downSampleLoRes(INT *v_result, /*!< */ + INT num_result, /*!< */ + const UCHAR *freqBandTableRef, /*!< */ + INT num_Ref) /*!< */ +{ + INT step; + INT i, j; + INT org_length, result_length; + INT v_index[MAX_FREQ_COEFFS / 2]; + + /* init */ + org_length = num_Ref; + result_length = num_result; + + v_index[0] = 0; /* Always use left border */ + i = 0; + while (org_length > 0) /* Create downsample vector */ + { + i++; + step = org_length / result_length; /* floor; */ + org_length = org_length - step; + result_length--; + v_index[i] = v_index[i - 1] + step; + } + + if (i != num_result) /* Should never happen */ + return (1); /* error downsampling */ + + for (j = 0; j <= i; + j++) /* Use downsample vector to index LoResolution vector. */ + { + v_result[j] = freqBandTableRef[v_index[j]]; + } + + return (0); +} + +/**************************************************************************/ +/*! + \brief Initialize an instance of the noise floor level estimation module. + + + \return errorCode, noError if successful + +*/ +/**************************************************************************/ +INT FDKsbrEnc_InitSbrNoiseFloorEstimate( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + INT ana_max_level, /*!< Maximum level of the adaptive noise. */ + const UCHAR *freqBandTable, /*!< Frequency band table. */ + INT nSfb, /*!< Number of frequency bands. */ + INT noiseBands, /*!< Number of noise bands per octave. */ + INT noiseFloorOffset, /*!< Noise floor offset. */ + INT timeSlots, /*!< Number of time slots in a frame. */ + UINT useSpeechConfig /*!< Flag: adapt tuning parameters according to speech + */ +) { + INT i, qexp, qtmp; + FIXP_DBL tmp, exp; + + FDKmemclear(h_sbrNoiseFloorEstimate, sizeof(SBR_NOISE_FLOOR_ESTIMATE)); + + h_sbrNoiseFloorEstimate->smoothFilter = smoothFilter; + if (useSpeechConfig) { + h_sbrNoiseFloorEstimate->weightFac = (FIXP_DBL)MAXVAL_DBL; + h_sbrNoiseFloorEstimate->diffThres = INVF_LOW_LEVEL; + } else { + h_sbrNoiseFloorEstimate->weightFac = FL2FXCONST_DBL(0.25f); + h_sbrNoiseFloorEstimate->diffThres = INVF_MID_LEVEL; + } + + h_sbrNoiseFloorEstimate->timeSlots = timeSlots; + h_sbrNoiseFloorEstimate->noiseBands = noiseBands; + + /* h_sbrNoiseFloorEstimate->ana_max_level is scaled by 0.25 */ + switch (ana_max_level) { + case 6: + h_sbrNoiseFloorEstimate->ana_max_level = (FIXP_DBL)MAXVAL_DBL; + break; + case 3: + h_sbrNoiseFloorEstimate->ana_max_level = FL2FXCONST_DBL(0.5); + break; + case -3: + h_sbrNoiseFloorEstimate->ana_max_level = FL2FXCONST_DBL(0.125); + break; + default: + /* Should not enter here */ + h_sbrNoiseFloorEstimate->ana_max_level = (FIXP_DBL)MAXVAL_DBL; + break; + } + + /* + calculate number of noise bands and allocate + */ + if (FDKsbrEnc_resetSbrNoiseFloorEstimate(h_sbrNoiseFloorEstimate, + freqBandTable, nSfb)) + return (1); + + if (noiseFloorOffset == 0) { + tmp = ((FIXP_DBL)MAXVAL_DBL) >> NOISE_FLOOR_OFFSET_SCALING; + } else { + /* noiseFloorOffset has to be smaller than 12, because + the result of the calculation below must be smaller than 1: + (2^(noiseFloorOffset/3))*2^4<1 */ + FDK_ASSERT(noiseFloorOffset < 12); + + /* Assumes the noise floor offset in tuning table are in q31 */ + /* Change the qformat here when non-zero values would be filled */ + exp = fDivNorm((FIXP_DBL)noiseFloorOffset, 3, &qexp); + tmp = fPow(2, DFRACT_BITS - 1, exp, qexp, &qtmp); + tmp = scaleValue(tmp, qtmp - NOISE_FLOOR_OFFSET_SCALING); + } + + for (i = 0; i < h_sbrNoiseFloorEstimate->noNoiseBands; i++) { + h_sbrNoiseFloorEstimate->noiseFloorOffset[i] = tmp; + } + + return (0); +} + +/**************************************************************************/ +/*! + \brief Resets the current instance of the noise floor estiamtion + module. + + + \return errorCode, noError if successful + +*/ +/**************************************************************************/ +INT FDKsbrEnc_resetSbrNoiseFloorEstimate( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + const UCHAR *freqBandTable, /*!< Frequency band table. */ + INT nSfb /*!< Number of bands in the frequency band table. */ +) { + INT k2, kx; + + /* + * Calculate number of noise bands + ***********************************/ + k2 = freqBandTable[nSfb]; + kx = freqBandTable[0]; + if (h_sbrNoiseFloorEstimate->noiseBands == 0) { + h_sbrNoiseFloorEstimate->noNoiseBands = 1; + } else { + /* + * Calculate number of noise bands 1,2 or 3 bands/octave + ********************************************************/ + FIXP_DBL tmp, ratio, lg2; + INT ratio_e, qlg2, nNoiseBands; + + ratio = fDivNorm(k2, kx, &ratio_e); + lg2 = fLog2(ratio, ratio_e, &qlg2); + tmp = fMult((FIXP_DBL)(h_sbrNoiseFloorEstimate->noiseBands << 24), lg2); + tmp = scaleValue(tmp, qlg2 - 23); + + nNoiseBands = (INT)((tmp + (FIXP_DBL)1) >> 1); + + if (nNoiseBands > MAX_NUM_NOISE_COEFFS) { + nNoiseBands = MAX_NUM_NOISE_COEFFS; + } + + if (nNoiseBands == 0) { + nNoiseBands = 1; + } + + h_sbrNoiseFloorEstimate->noNoiseBands = nNoiseBands; + } + + return (downSampleLoRes(h_sbrNoiseFloorEstimate->freqBandTableQmf, + h_sbrNoiseFloorEstimate->noNoiseBands, freqBandTable, + nSfb)); +} + +/**************************************************************************/ +/*! + \brief Deletes the current instancce of the noise floor level + estimation module. + + + \return none + +*/ +/**************************************************************************/ +void FDKsbrEnc_deleteSbrNoiseFloorEstimate( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate) /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ +{ + if (h_sbrNoiseFloorEstimate) { + /* + nothing to do + */ + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/nf_est.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/nf_est.h new file mode 100644 index 0000000000000..c2f16e9bde60b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/nf_est.h @@ -0,0 +1,185 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Noise floor estimation structs and prototypes $Revision: 92790 $ +*/ + +#ifndef NF_EST_H +#define NF_EST_H + +#include "sbr_encoder.h" +#include "fram_gen.h" + +#define NF_SMOOTHING_LENGTH 4 /*!< Smoothing length of the noise floors. */ + +typedef struct { + FIXP_DBL + prevNoiseLevels[NF_SMOOTHING_LENGTH] + [MAX_NUM_NOISE_VALUES]; /*!< The previous noise levels. */ + FIXP_DBL noiseFloorOffset + [MAX_NUM_NOISE_VALUES]; /*!< Noise floor offset, scaled with + NOISE_FLOOR_OFFSET_SCALING */ + const FIXP_DBL *smoothFilter; /*!< Smoothing filter to use. */ + FIXP_DBL ana_max_level; /*!< Max level allowed. */ + FIXP_DBL weightFac; /*!< Weightening factor for the difference between orig + and sbr. */ + INT freqBandTableQmf[MAX_NUM_NOISE_VALUES + + 1]; /*!< Frequncy band table for the noise floor bands.*/ + INT noNoiseBands; /*!< Number of noisebands. */ + INT noiseBands; /*!< NoiseBands switch 4 bit.*/ + INT timeSlots; /*!< Number of timeslots in a frame. */ + INVF_MODE diffThres; /*!< Threshold value to control the inverse filtering + decision */ +} SBR_NOISE_FLOOR_ESTIMATE; + +typedef SBR_NOISE_FLOOR_ESTIMATE *HANDLE_SBR_NOISE_FLOOR_ESTIMATE; + +void FDKsbrEnc_sbrNoiseFloorEstimateQmf( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + const SBR_FRAME_INFO + *frame_info, /*!< Time frequency grid of the current frame. */ + FIXP_DBL + *noiseLevels, /*!< Pointer to vector to store the noise levels in.*/ + FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the quota values of the + original. */ + SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ + INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component + will be missing. */ + INT startIndex, /*!< Start index. */ + UINT numberOfEstimatesPerFrame, /*!< The number of tonality estimates per + frame. */ + INT transientFrame, /*!< A flag indicating if a transient is present. */ + INVF_MODE *pInvFiltLevels, /*!< Pointer to the vector holding the inverse + filtering levels. */ + UINT sbrSyntaxFlags); + +INT FDKsbrEnc_InitSbrNoiseFloorEstimate( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + INT ana_max_level, /*!< Maximum level of the adaptive noise. */ + const UCHAR *freqBandTable, /*!< Frequany band table. */ + INT nSfb, /*!< Number of frequency bands. */ + INT noiseBands, /*!< Number of noise bands per octave. */ + INT noiseFloorOffset, /*!< Noise floor offset. */ + INT timeSlots, /*!< Number of time slots in a frame. */ + UINT useSpeechConfig /*!< Flag: adapt tuning parameters according to speech + */ +); + +INT FDKsbrEnc_resetSbrNoiseFloorEstimate( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + const UCHAR *freqBandTable, /*!< Frequany band table. */ + INT nSfb); /*!< Number of bands in the frequency band table. */ + +void FDKsbrEnc_deleteSbrNoiseFloorEstimate( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate); /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_bitenc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_bitenc.cpp new file mode 100644 index 0000000000000..e30af2a8b85c3 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_bitenc.cpp @@ -0,0 +1,624 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): N. Rettelbach + + Description: Parametric Stereo bitstream encoder + +*******************************************************************************/ + +#include "ps_bitenc.h" + +#include "ps_main.h" + +static inline UCHAR FDKsbrEnc_WriteBits_ps(HANDLE_FDK_BITSTREAM hBitStream, + UINT value, + const UINT numberOfBits) { + /* hBitStream == NULL happens here intentionally */ + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, value, numberOfBits); + } + return numberOfBits; +} + +#define SI_SBR_EXTENSION_SIZE_BITS 4 +#define SI_SBR_EXTENSION_ESC_COUNT_BITS 8 +#define SI_SBR_EXTENSION_ID_BITS 2 +#define EXTENSION_ID_PS_CODING 2 +#define PS_EXT_ID_V0 0 + +static const INT iidDeltaCoarse_Offset = 14; +static const INT iidDeltaCoarse_MaxVal = 28; +static const INT iidDeltaFine_Offset = 30; +static const INT iidDeltaFine_MaxVal = 60; + +/* PS Stereo Huffmantable: iidDeltaFreqCoarse */ +static const UINT iidDeltaFreqCoarse_Length[] = { + 17, 17, 17, 17, 16, 15, 13, 10, 9, 7, 6, 5, 4, 3, 1, + 3, 4, 5, 6, 6, 8, 11, 13, 14, 14, 15, 17, 18, 18}; +static const UINT iidDeltaFreqCoarse_Code[] = { + 0x0001fffb, 0x0001fffc, 0x0001fffd, 0x0001fffa, 0x0000fffc, 0x00007ffc, + 0x00001ffd, 0x000003fe, 0x000001fe, 0x0000007e, 0x0000003c, 0x0000001d, + 0x0000000d, 0x00000005, 0000000000, 0x00000004, 0x0000000c, 0x0000001c, + 0x0000003d, 0x0000003e, 0x000000fe, 0x000007fe, 0x00001ffc, 0x00003ffc, + 0x00003ffd, 0x00007ffd, 0x0001fffe, 0x0003fffe, 0x0003ffff}; + +/* PS Stereo Huffmantable: iidDeltaFreqFine */ +static const UINT iidDeltaFreqFine_Length[] = { + 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, 18, 17, 17, 16, 16, 15, + 14, 14, 13, 12, 12, 11, 10, 10, 8, 7, 6, 5, 4, 3, 1, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 16, 16, + 17, 17, 18, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18}; +static const UINT iidDeltaFreqFine_Code[] = { + 0x0001feb4, 0x0001feb5, 0x0001fd76, 0x0001fd77, 0x0001fd74, 0x0001fd75, + 0x0001fe8a, 0x0001fe8b, 0x0001fe88, 0x0000fe80, 0x0001feb6, 0x0000fe82, + 0x0000feb8, 0x00007f42, 0x00007fae, 0x00003faf, 0x00001fd1, 0x00001fe9, + 0x00000fe9, 0x000007ea, 0x000007fb, 0x000003fb, 0x000001fb, 0x000001ff, + 0x0000007c, 0x0000003c, 0x0000001c, 0x0000000c, 0000000000, 0x00000001, + 0x00000001, 0x00000002, 0x00000001, 0x0000000d, 0x0000001d, 0x0000003d, + 0x0000007d, 0x000000fc, 0x000001fc, 0x000003fc, 0x000003f4, 0x000007eb, + 0x00000fea, 0x00001fea, 0x00001fd6, 0x00003fd0, 0x00007faf, 0x00007f43, + 0x0000feb9, 0x0000fe83, 0x0001feb7, 0x0000fe81, 0x0001fe89, 0x0001fe8e, + 0x0001fe8f, 0x0001fe8c, 0x0001fe8d, 0x0001feb2, 0x0001feb3, 0x0001feb0, + 0x0001feb1}; + +/* PS Stereo Huffmantable: iidDeltaTimeCoarse */ +static const UINT iidDeltaTimeCoarse_Length[] = { + 19, 19, 19, 20, 20, 20, 17, 15, 12, 10, 8, 6, 4, 2, 1, + 3, 5, 7, 9, 11, 13, 14, 17, 19, 20, 20, 20, 20, 20}; +static const UINT iidDeltaTimeCoarse_Code[] = { + 0x0007fff9, 0x0007fffa, 0x0007fffb, 0x000ffff8, 0x000ffff9, 0x000ffffa, + 0x0001fffd, 0x00007ffe, 0x00000ffe, 0x000003fe, 0x000000fe, 0x0000003e, + 0x0000000e, 0x00000002, 0000000000, 0x00000006, 0x0000001e, 0x0000007e, + 0x000001fe, 0x000007fe, 0x00001ffe, 0x00003ffe, 0x0001fffc, 0x0007fff8, + 0x000ffffb, 0x000ffffc, 0x000ffffd, 0x000ffffe, 0x000fffff}; + +/* PS Stereo Huffmantable: iidDeltaTimeFine */ +static const UINT iidDeltaTimeFine_Length[] = { + 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, + 14, 13, 13, 13, 12, 12, 11, 10, 9, 9, 7, 6, 5, 3, 1, 2, + 5, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; +static const UINT iidDeltaTimeFine_Code[] = { + 0x00004ed4, 0x00004ed5, 0x00004ece, 0x00004ecf, 0x00004ecc, 0x00004ed6, + 0x00004ed8, 0x00004f46, 0x00004f60, 0x00002718, 0x00002719, 0x00002764, + 0x00002765, 0x0000276d, 0x000027b1, 0x000013b7, 0x000013d6, 0x000009c7, + 0x000009e9, 0x000009ed, 0x000004ee, 0x000004f7, 0x00000278, 0x00000139, + 0x0000009a, 0x0000009f, 0x00000020, 0x00000011, 0x0000000a, 0x00000003, + 0x00000001, 0000000000, 0x0000000b, 0x00000012, 0x00000021, 0x0000004c, + 0x0000009b, 0x0000013a, 0x00000279, 0x00000270, 0x000004ef, 0x000004e2, + 0x000009ea, 0x000009d8, 0x000013d7, 0x000013d0, 0x000027b2, 0x000027a2, + 0x0000271a, 0x0000271b, 0x00004f66, 0x00004f67, 0x00004f61, 0x00004f47, + 0x00004ed9, 0x00004ed7, 0x00004ecd, 0x00004ed2, 0x00004ed3, 0x00004ed0, + 0x00004ed1}; + +static const INT iccDelta_Offset = 7; +static const INT iccDelta_MaxVal = 14; +/* PS Stereo Huffmantable: iccDeltaFreq */ +static const UINT iccDeltaFreq_Length[] = {14, 14, 12, 10, 7, 5, 3, 1, + 2, 4, 6, 8, 9, 11, 13}; +static const UINT iccDeltaFreq_Code[] = { + 0x00003fff, 0x00003ffe, 0x00000ffe, 0x000003fe, 0x0000007e, + 0x0000001e, 0x00000006, 0000000000, 0x00000002, 0x0000000e, + 0x0000003e, 0x000000fe, 0x000001fe, 0x000007fe, 0x00001ffe}; + +/* PS Stereo Huffmantable: iccDeltaTime */ +static const UINT iccDeltaTime_Length[] = {14, 13, 11, 9, 7, 5, 3, 1, + 2, 4, 6, 8, 10, 12, 14}; +static const UINT iccDeltaTime_Code[] = { + 0x00003ffe, 0x00001ffe, 0x000007fe, 0x000001fe, 0x0000007e, + 0x0000001e, 0x00000006, 0000000000, 0x00000002, 0x0000000e, + 0x0000003e, 0x000000fe, 0x000003fe, 0x00000ffe, 0x00003fff}; + +static const INT ipdDelta_Offset = 0; +static const INT ipdDelta_MaxVal = 7; +/* PS Stereo Huffmantable: ipdDeltaFreq */ +static const UINT ipdDeltaFreq_Length[] = {1, 3, 4, 4, 4, 4, 4, 4}; +static const UINT ipdDeltaFreq_Code[] = {0x00000001, 0000000000, 0x00000006, + 0x00000004, 0x00000002, 0x00000003, + 0x00000005, 0x00000007}; + +/* PS Stereo Huffmantable: ipdDeltaTime */ +static const UINT ipdDeltaTime_Length[] = {1, 3, 4, 5, 5, 4, 4, 3}; +static const UINT ipdDeltaTime_Code[] = {0x00000001, 0x00000002, 0x00000002, + 0x00000003, 0x00000002, 0000000000, + 0x00000003, 0x00000003}; + +static const INT opdDelta_Offset = 0; +static const INT opdDelta_MaxVal = 7; +/* PS Stereo Huffmantable: opdDeltaFreq */ +static const UINT opdDeltaFreq_Length[] = {1, 3, 4, 4, 5, 5, 4, 3}; +static const UINT opdDeltaFreq_Code[] = { + 0x00000001, 0x00000001, 0x00000006, 0x00000004, + 0x0000000f, 0x0000000e, 0x00000005, 0000000000, +}; + +/* PS Stereo Huffmantable: opdDeltaTime */ +static const UINT opdDeltaTime_Length[] = {1, 3, 4, 5, 5, 4, 4, 3}; +static const UINT opdDeltaTime_Code[] = {0x00000001, 0x00000002, 0x00000001, + 0x00000007, 0x00000006, 0000000000, + 0x00000002, 0x00000003}; + +static INT getNoBands(const INT mode) { + INT noBands = 0; + + switch (mode) { + case 0: + case 3: /* coarse */ + noBands = PS_BANDS_COARSE; + break; + case 1: + case 4: /* mid */ + noBands = PS_BANDS_MID; + break; + case 2: + case 5: /* fine not supported */ + default: /* coarse as default */ + noBands = PS_BANDS_COARSE; + } + + return noBands; +} + +static INT getIIDRes(INT iidMode) { + if (iidMode < 3) + return PS_IID_RES_COARSE; + else + return PS_IID_RES_FINE; +} + +static INT encodeDeltaFreq(HANDLE_FDK_BITSTREAM hBitBuf, const INT *val, + const INT nBands, const UINT *codeTable, + const UINT *lengthTable, const INT tableOffset, + const INT maxVal, INT *error) { + INT bitCnt = 0; + INT lastVal = 0; + INT band; + + for (band = 0; band < nBands; band++) { + INT delta = (val[band] - lastVal) + tableOffset; + lastVal = val[band]; + if ((delta > maxVal) || (delta < 0)) { + *error = 1; + delta = delta > 0 ? maxVal : 0; + } + bitCnt += + FDKsbrEnc_WriteBits_ps(hBitBuf, codeTable[delta], lengthTable[delta]); + } + + return bitCnt; +} + +static INT encodeDeltaTime(HANDLE_FDK_BITSTREAM hBitBuf, const INT *val, + const INT *valLast, const INT nBands, + const UINT *codeTable, const UINT *lengthTable, + const INT tableOffset, const INT maxVal, + INT *error) { + INT bitCnt = 0; + INT band; + + for (band = 0; band < nBands; band++) { + INT delta = (val[band] - valLast[band]) + tableOffset; + if ((delta > maxVal) || (delta < 0)) { + *error = 1; + delta = delta > 0 ? maxVal : 0; + } + bitCnt += + FDKsbrEnc_WriteBits_ps(hBitBuf, codeTable[delta], lengthTable[delta]); + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeIid(HANDLE_FDK_BITSTREAM hBitBuf, const INT *iidVal, + const INT *iidValLast, const INT nBands, + const PS_IID_RESOLUTION res, const PS_DELTA mode, + INT *error) { + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + bitCnt = 0; + + switch (mode) { + case PS_DELTA_FREQ: + switch (res) { + case PS_IID_RES_COARSE: + codeTable = iidDeltaFreqCoarse_Code; + lengthTable = iidDeltaFreqCoarse_Length; + bitCnt += encodeDeltaFreq(hBitBuf, iidVal, nBands, codeTable, + lengthTable, iidDeltaCoarse_Offset, + iidDeltaCoarse_MaxVal, error); + break; + case PS_IID_RES_FINE: + codeTable = iidDeltaFreqFine_Code; + lengthTable = iidDeltaFreqFine_Length; + bitCnt += + encodeDeltaFreq(hBitBuf, iidVal, nBands, codeTable, lengthTable, + iidDeltaFine_Offset, iidDeltaFine_MaxVal, error); + break; + default: + *error = 1; + } + break; + + case PS_DELTA_TIME: + switch (res) { + case PS_IID_RES_COARSE: + codeTable = iidDeltaTimeCoarse_Code; + lengthTable = iidDeltaTimeCoarse_Length; + bitCnt += encodeDeltaTime( + hBitBuf, iidVal, iidValLast, nBands, codeTable, lengthTable, + iidDeltaCoarse_Offset, iidDeltaCoarse_MaxVal, error); + break; + case PS_IID_RES_FINE: + codeTable = iidDeltaTimeFine_Code; + lengthTable = iidDeltaTimeFine_Length; + bitCnt += encodeDeltaTime(hBitBuf, iidVal, iidValLast, nBands, + codeTable, lengthTable, iidDeltaFine_Offset, + iidDeltaFine_MaxVal, error); + break; + default: + *error = 1; + } + break; + + default: + *error = 1; + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeIcc(HANDLE_FDK_BITSTREAM hBitBuf, const INT *iccVal, + const INT *iccValLast, const INT nBands, + const PS_DELTA mode, INT *error) { + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + switch (mode) { + case PS_DELTA_FREQ: + codeTable = iccDeltaFreq_Code; + lengthTable = iccDeltaFreq_Length; + bitCnt += encodeDeltaFreq(hBitBuf, iccVal, nBands, codeTable, lengthTable, + iccDelta_Offset, iccDelta_MaxVal, error); + break; + + case PS_DELTA_TIME: + codeTable = iccDeltaTime_Code; + lengthTable = iccDeltaTime_Length; + + bitCnt += + encodeDeltaTime(hBitBuf, iccVal, iccValLast, nBands, codeTable, + lengthTable, iccDelta_Offset, iccDelta_MaxVal, error); + break; + + default: + *error = 1; + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeIpd(HANDLE_FDK_BITSTREAM hBitBuf, const INT *ipdVal, + const INT *ipdValLast, const INT nBands, + const PS_DELTA mode, INT *error) { + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + switch (mode) { + case PS_DELTA_FREQ: + codeTable = ipdDeltaFreq_Code; + lengthTable = ipdDeltaFreq_Length; + bitCnt += encodeDeltaFreq(hBitBuf, ipdVal, nBands, codeTable, lengthTable, + ipdDelta_Offset, ipdDelta_MaxVal, error); + break; + + case PS_DELTA_TIME: + codeTable = ipdDeltaTime_Code; + lengthTable = ipdDeltaTime_Length; + + bitCnt += + encodeDeltaTime(hBitBuf, ipdVal, ipdValLast, nBands, codeTable, + lengthTable, ipdDelta_Offset, ipdDelta_MaxVal, error); + break; + + default: + *error = 1; + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeOpd(HANDLE_FDK_BITSTREAM hBitBuf, const INT *opdVal, + const INT *opdValLast, const INT nBands, + const PS_DELTA mode, INT *error) { + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + switch (mode) { + case PS_DELTA_FREQ: + codeTable = opdDeltaFreq_Code; + lengthTable = opdDeltaFreq_Length; + bitCnt += encodeDeltaFreq(hBitBuf, opdVal, nBands, codeTable, lengthTable, + opdDelta_Offset, opdDelta_MaxVal, error); + break; + + case PS_DELTA_TIME: + codeTable = opdDeltaTime_Code; + lengthTable = opdDeltaTime_Length; + + bitCnt += + encodeDeltaTime(hBitBuf, opdVal, opdValLast, nBands, codeTable, + lengthTable, opdDelta_Offset, opdDelta_MaxVal, error); + break; + + default: + *error = 1; + } + + return bitCnt; +} + +static INT encodeIpdOpd(HANDLE_PS_OUT psOut, HANDLE_FDK_BITSTREAM hBitBuf) { + INT bitCnt = 0; + INT error = 0; + INT env; + + FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enableIpdOpd, 1); + + if (psOut->enableIpdOpd == 1) { + INT *ipdLast = psOut->ipdLast; + INT *opdLast = psOut->opdLast; + + for (env = 0; env < psOut->nEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->deltaIPD[env], 1); + bitCnt += FDKsbrEnc_EncodeIpd(hBitBuf, psOut->ipd[env], ipdLast, + getNoBands(psOut->iidMode), + psOut->deltaIPD[env], &error); + + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->deltaOPD[env], 1); + bitCnt += FDKsbrEnc_EncodeOpd(hBitBuf, psOut->opd[env], opdLast, + getNoBands(psOut->iidMode), + psOut->deltaOPD[env], &error); + } + /* reserved bit */ + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, 0, 1); + } + + return bitCnt; +} + +static INT getEnvIdx(const INT nEnvelopes, const INT frameClass) { + INT envIdx = 0; + + switch (nEnvelopes) { + case 0: + envIdx = 0; + break; + + case 1: + if (frameClass == 0) + envIdx = 1; + else + envIdx = 0; + break; + + case 2: + if (frameClass == 0) + envIdx = 2; + else + envIdx = 1; + break; + + case 3: + envIdx = 2; + break; + + case 4: + envIdx = 3; + break; + + default: + /* unsupported number of envelopes */ + envIdx = 0; + } + + return envIdx; +} + +static INT encodePSExtension(const HANDLE_PS_OUT psOut, + HANDLE_FDK_BITSTREAM hBitBuf) { + INT bitCnt = 0; + + if (psOut->enableIpdOpd == 1) { + INT ipdOpdBits = 0; + INT extSize = (2 + encodeIpdOpd(psOut, NULL) + 7) >> 3; + + if (extSize < 15) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, extSize, 4); + } else { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, 15, 4); + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, (extSize - 15), 8); + } + + /* write ipd opd data */ + ipdOpdBits += FDKsbrEnc_WriteBits_ps(hBitBuf, PS_EXT_ID_V0, 2); + ipdOpdBits += encodeIpdOpd(psOut, hBitBuf); + + /* byte align the ipd opd data */ + if (ipdOpdBits % 8) + ipdOpdBits += FDKsbrEnc_WriteBits_ps(hBitBuf, 0, (8 - (ipdOpdBits % 8))); + + bitCnt += ipdOpdBits; + } + + return (bitCnt); +} + +INT FDKsbrEnc_WritePSBitstream(const HANDLE_PS_OUT psOut, + HANDLE_FDK_BITSTREAM hBitBuf) { + INT psExtEnable = 0; + INT bitCnt = 0; + INT error = 0; + INT env; + + if (psOut != NULL) { + /* PS HEADER */ + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enablePSHeader, 1); + + if (psOut->enablePSHeader) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enableIID, 1); + if (psOut->enableIID) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->iidMode, 3); + } + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enableICC, 1); + if (psOut->enableICC) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->iccMode, 3); + } + if (psOut->enableIpdOpd) { + psExtEnable = 1; + } + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psExtEnable, 1); + } + + /* Frame class, number of envelopes */ + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->frameClass, 1); + bitCnt += FDKsbrEnc_WriteBits_ps( + hBitBuf, getEnvIdx(psOut->nEnvelopes, psOut->frameClass), 2); + + if (psOut->frameClass == 1) { + for (env = 0; env < psOut->nEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->frameBorder[env], 5); + } + } + + if (psOut->enableIID == 1) { + INT *iidLast = psOut->iidLast; + for (env = 0; env < psOut->nEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->deltaIID[env], 1); + bitCnt += FDKsbrEnc_EncodeIid( + hBitBuf, psOut->iid[env], iidLast, getNoBands(psOut->iidMode), + (PS_IID_RESOLUTION)getIIDRes(psOut->iidMode), psOut->deltaIID[env], + &error); + + iidLast = psOut->iid[env]; + } + } + + if (psOut->enableICC == 1) { + INT *iccLast = psOut->iccLast; + for (env = 0; env < psOut->nEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->deltaICC[env], 1); + bitCnt += FDKsbrEnc_EncodeIcc(hBitBuf, psOut->icc[env], iccLast, + getNoBands(psOut->iccMode), + psOut->deltaICC[env], &error); + + iccLast = psOut->icc[env]; + } + } + + if (psExtEnable != 0) { + bitCnt += encodePSExtension(psOut, hBitBuf); + } + + } /* if(psOut != NULL) */ + + return bitCnt; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_bitenc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_bitenc.h new file mode 100644 index 0000000000000..1d383e3c0b857 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_bitenc.h @@ -0,0 +1,173 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): N. Rettelbach + + Description: Parametric Stereo bitstream encoder + +*******************************************************************************/ + +#include "ps_main.h" +#include "ps_const.h" +#include "FDK_bitstream.h" + +#ifndef PS_BITENC_H +#define PS_BITENC_H + +typedef struct T_PS_OUT { + INT enablePSHeader; + INT enableIID; + INT iidMode; + INT enableICC; + INT iccMode; + INT enableIpdOpd; + + INT frameClass; + INT nEnvelopes; + /* ENV data */ + INT frameBorder[PS_MAX_ENVELOPES]; + + /* iid data */ + PS_DELTA deltaIID[PS_MAX_ENVELOPES]; + INT iid[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iidLast[PS_MAX_BANDS]; + + /* icc data */ + PS_DELTA deltaICC[PS_MAX_ENVELOPES]; + INT icc[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iccLast[PS_MAX_BANDS]; + + /* ipd data */ + PS_DELTA deltaIPD[PS_MAX_ENVELOPES]; + INT ipd[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT ipdLast[PS_MAX_BANDS]; + + /* opd data */ + PS_DELTA deltaOPD[PS_MAX_ENVELOPES]; + INT opd[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT opdLast[PS_MAX_BANDS]; + +} PS_OUT, *HANDLE_PS_OUT; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +INT FDKsbrEnc_EncodeIid(HANDLE_FDK_BITSTREAM hBitBuf, const INT *iidVal, + const INT *iidValLast, const INT nBands, + const PS_IID_RESOLUTION res, const PS_DELTA mode, + INT *error); + +INT FDKsbrEnc_EncodeIcc(HANDLE_FDK_BITSTREAM hBitBuf, const INT *iccVal, + const INT *iccValLast, const INT nBands, + const PS_DELTA mode, INT *error); + +INT FDKsbrEnc_EncodeIpd(HANDLE_FDK_BITSTREAM hBitBuf, const INT *ipdVal, + const INT *ipdValLast, const INT nBands, + const PS_DELTA mode, INT *error); + +INT FDKsbrEnc_EncodeOpd(HANDLE_FDK_BITSTREAM hBitBuf, const INT *opdVal, + const INT *opdValLast, const INT nBands, + const PS_DELTA mode, INT *error); + +INT FDKsbrEnc_WritePSBitstream(const HANDLE_PS_OUT psOut, + HANDLE_FDK_BITSTREAM hBitBuf); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(PSENC_ENABLE) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_const.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_const.h new file mode 100644 index 0000000000000..b9a33f986896e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_const.h @@ -0,0 +1,150 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): N. Rettelbach + + Description: Parametric Stereo constants + +*******************************************************************************/ + +#ifndef PS_CONST_H +#define PS_CONST_H + +#define MAX_PS_CHANNELS (2) +#define HYBRID_MAX_QMF_BANDS (3) +#define HYBRID_FILTER_LENGTH (13) +#define HYBRID_FILTER_DELAY ((HYBRID_FILTER_LENGTH - 1) / 2) + +#define HYBRID_FRAMESIZE (32) +#define HYBRID_READ_OFFSET (10) + +#define MAX_HYBRID_BANDS ((64 - HYBRID_MAX_QMF_BANDS + 10)) + +typedef enum { + PS_RES_COARSE = 0, + PS_RES_MID = 1, + PS_RES_FINE = 2 +} PS_RESOLUTION; + +typedef enum { + PS_BANDS_COARSE = 10, + PS_BANDS_MID = 20, + PS_MAX_BANDS = PS_BANDS_MID +} PS_BANDS; + +typedef enum { PS_IID_RES_COARSE = 0, PS_IID_RES_FINE } PS_IID_RESOLUTION; + +typedef enum { PS_ICC_ROT_A = 0, PS_ICC_ROT_B } PS_ICC_ROTATION_MODE; + +typedef enum { PS_DELTA_FREQ, PS_DELTA_TIME } PS_DELTA; + +typedef enum { + PS_MAX_ENVELOPES = 4 + +} PS_CONSTS; + +typedef enum { + PSENC_OK = 0x0000, /*!< No error happened. All fine. */ + PSENC_INVALID_HANDLE = + 0x0020, /*!< Handle passed to function call was invalid. */ + PSENC_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */ + PSENC_INIT_ERROR = 0x0040, /*!< General initialization error. */ + PSENC_ENCODE_ERROR = 0x0060 /*!< The encoding process was interrupted by an + unexpected error. */ + +} FDK_PSENC_ERROR; + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_encode.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_encode.cpp new file mode 100644 index 0000000000000..88d3131431e49 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_encode.cpp @@ -0,0 +1,1031 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): M. Neuendorf, N. Rettelbach, M. Multrus + + Description: PS parameter extraction, encoding + +*******************************************************************************/ + +/*! + \file + \brief PS parameter extraction, encoding functions $Revision: 96441 $ +*/ + +#include "ps_main.h" +#include "ps_encode.h" +#include "qmf.h" +#include "sbr_misc.h" +#include "sbrenc_ram.h" + +#include "genericStds.h" + +inline void FDKsbrEnc_addFIXP_DBL(const FIXP_DBL *X, const FIXP_DBL *Y, + FIXP_DBL *Z, INT n) { + for (INT i = 0; i < n; i++) Z[i] = (X[i] >> 1) + (Y[i] >> 1); +} + +#define LOG10_2_10 3.01029995664f /* 10.0f*log10(2.f) */ + +static const INT + iidGroupBordersLoRes[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES + 1] = { + 0, 1, 2, 3, 4, 5, /* 6 subqmf subbands - 0th qmf subband */ + 6, 7, /* 2 subqmf subbands - 1st qmf subband */ + 8, 9, /* 2 subqmf subbands - 2nd qmf subband */ + 10, 11, 12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71}; + +static const UCHAR + iidGroupWidthLdLoRes[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 4, 5}; + +static const INT subband2parameter20[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES] = + {1, 0, 0, 1, 2, 3, /* 6 subqmf subbands - 0th qmf subband */ + 4, 5, /* 2 subqmf subbands - 1st qmf subband */ + 6, 7, /* 2 subqmf subbands - 2nd qmf subband */ + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +typedef enum { + MAX_TIME_DIFF_FRAMES = 20, + MAX_PS_NOHEADER_CNT = 10, + MAX_NOENV_CNT = 10, + DO_NOT_USE_THIS_MODE = 0x7FFFFF +} __PS_CONSTANTS; + +static const FIXP_DBL iidQuant_fx[15] = { + (FIXP_DBL)0xce000000, (FIXP_DBL)0xdc000000, (FIXP_DBL)0xe4000000, + (FIXP_DBL)0xec000000, (FIXP_DBL)0xf2000000, (FIXP_DBL)0xf8000000, + (FIXP_DBL)0xfc000000, (FIXP_DBL)0x00000000, (FIXP_DBL)0x04000000, + (FIXP_DBL)0x08000000, (FIXP_DBL)0x0e000000, (FIXP_DBL)0x14000000, + (FIXP_DBL)0x1c000000, (FIXP_DBL)0x24000000, (FIXP_DBL)0x32000000}; + +static const FIXP_DBL iidQuantFine_fx[31] = { + (FIXP_DBL)0x9c000001, (FIXP_DBL)0xa6000001, (FIXP_DBL)0xb0000001, + (FIXP_DBL)0xba000001, (FIXP_DBL)0xc4000000, (FIXP_DBL)0xce000000, + (FIXP_DBL)0xd4000000, (FIXP_DBL)0xda000000, (FIXP_DBL)0xe0000000, + (FIXP_DBL)0xe6000000, (FIXP_DBL)0xec000000, (FIXP_DBL)0xf0000000, + (FIXP_DBL)0xf4000000, (FIXP_DBL)0xf8000000, (FIXP_DBL)0xfc000000, + (FIXP_DBL)0x00000000, (FIXP_DBL)0x04000000, (FIXP_DBL)0x08000000, + (FIXP_DBL)0x0c000000, (FIXP_DBL)0x10000000, (FIXP_DBL)0x14000000, + (FIXP_DBL)0x1a000000, (FIXP_DBL)0x20000000, (FIXP_DBL)0x26000000, + (FIXP_DBL)0x2c000000, (FIXP_DBL)0x32000000, (FIXP_DBL)0x3c000000, + (FIXP_DBL)0x45ffffff, (FIXP_DBL)0x4fffffff, (FIXP_DBL)0x59ffffff, + (FIXP_DBL)0x63ffffff}; + +static const FIXP_DBL iccQuant[8] = { + (FIXP_DBL)0x7fffffff, (FIXP_DBL)0x77ef9d7f, (FIXP_DBL)0x6babc97f, + (FIXP_DBL)0x4ceaf27f, (FIXP_DBL)0x2f0ed3c0, (FIXP_DBL)0x00000000, + (FIXP_DBL)0xb49ba601, (FIXP_DBL)0x80000000}; + +static FDK_PSENC_ERROR InitPSData(HANDLE_PS_DATA hPsData) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (hPsData == NULL) { + error = PSENC_INVALID_HANDLE; + } else { + int i, env; + FDKmemclear(hPsData, sizeof(PS_DATA)); + + for (i = 0; i < PS_MAX_BANDS; i++) { + hPsData->iidIdxLast[i] = 0; + hPsData->iccIdxLast[i] = 0; + } + + hPsData->iidEnable = hPsData->iidEnableLast = 0; + hPsData->iccEnable = hPsData->iccEnableLast = 0; + hPsData->iidQuantMode = hPsData->iidQuantModeLast = PS_IID_RES_COARSE; + hPsData->iccQuantMode = hPsData->iccQuantModeLast = PS_ICC_ROT_A; + + for (env = 0; env < PS_MAX_ENVELOPES; env++) { + hPsData->iccDiffMode[env] = PS_DELTA_FREQ; + hPsData->iccDiffMode[env] = PS_DELTA_FREQ; + + for (i = 0; i < PS_MAX_BANDS; i++) { + hPsData->iidIdx[env][i] = 0; + hPsData->iccIdx[env][i] = 0; + } + } + + hPsData->nEnvelopesLast = 0; + + hPsData->headerCnt = MAX_PS_NOHEADER_CNT; + hPsData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; + hPsData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; + hPsData->noEnvCnt = MAX_NOENV_CNT; + } + + return error; +} + +static FIXP_DBL quantizeCoef(const FIXP_DBL *RESTRICT input, const INT nBands, + const FIXP_DBL *RESTRICT quantTable, + const INT idxOffset, const INT nQuantSteps, + INT *RESTRICT quantOut) { + INT idx, band; + FIXP_DBL quantErr = FL2FXCONST_DBL(0.f); + + for (band = 0; band < nBands; band++) { + for (idx = 0; idx < nQuantSteps - 1; idx++) { + if (fixp_abs((input[band] >> 1) - (quantTable[idx + 1] >> 1)) > + fixp_abs((input[band] >> 1) - (quantTable[idx] >> 1))) { + break; + } + } + quantErr += (fixp_abs(input[band] - quantTable[idx]) >> + PS_QUANT_SCALE); /* don't scale before subtraction; diff + smaller (64-25)/64 */ + quantOut[band] = idx - idxOffset; + } + + return quantErr; +} + +static INT getICCMode(const INT nBands, const INT rotType) { + INT mode = 0; + + switch (nBands) { + case PS_BANDS_COARSE: + mode = PS_RES_COARSE; + break; + case PS_BANDS_MID: + mode = PS_RES_MID; + break; + default: + mode = 0; + } + if (rotType == PS_ICC_ROT_B) { + mode += 3; + } + + return mode; +} + +static INT getIIDMode(const INT nBands, const INT iidRes) { + INT mode = 0; + + switch (nBands) { + case PS_BANDS_COARSE: + mode = PS_RES_COARSE; + break; + case PS_BANDS_MID: + mode = PS_RES_MID; + break; + default: + mode = 0; + break; + } + + if (iidRes == PS_IID_RES_FINE) { + mode += 3; + } + + return mode; +} + +static INT envelopeReducible(FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], + INT psBands, INT nEnvelopes) { +#define THRESH_SCALE 7 + + INT reducible = 1; /* true */ + INT e = 0, b = 0; + FIXP_DBL dIid = FL2FXCONST_DBL(0.f); + FIXP_DBL dIcc = FL2FXCONST_DBL(0.f); + + FIXP_DBL iidErrThreshold, iccErrThreshold; + FIXP_DBL iidMeanError, iccMeanError; + + /* square values to prevent sqrt, + multiply bands to prevent division; bands shifted DFRACT_BITS instead + (DFRACT_BITS-1) because fMultDiv2 used*/ + iidErrThreshold = + fMultDiv2(FL2FXCONST_DBL(6.5f * 6.5f / (IID_SCALE_FT * IID_SCALE_FT)), + (FIXP_DBL)(psBands << ((DFRACT_BITS)-THRESH_SCALE))); + iccErrThreshold = + fMultDiv2(FL2FXCONST_DBL(0.75f * 0.75f), + (FIXP_DBL)(psBands << ((DFRACT_BITS)-THRESH_SCALE))); + + if (nEnvelopes <= 1) { + reducible = 0; + } else { + /* mean error criterion */ + for (e = 0; (e < nEnvelopes / 2) && (reducible != 0); e++) { + iidMeanError = iccMeanError = FL2FXCONST_DBL(0.f); + for (b = 0; b < psBands; b++) { + dIid = (iid[2 * e][b] >> 1) - + (iid[2 * e + 1][b] >> 1); /* scale 1 bit; squared -> 2 bit */ + dIcc = (icc[2 * e][b] >> 1) - (icc[2 * e + 1][b] >> 1); + iidMeanError += fPow2Div2(dIid) >> (5 - 1); /* + (bands=20) scale = 5 */ + iccMeanError += fPow2Div2(dIcc) >> (5 - 1); + } /* --> scaling = 7 bit = THRESH_SCALE !! */ + + /* instead sqrt values are squared! + instead of division, multiply threshold with psBands + scaling necessary!! */ + + /* quit as soon as threshold is reached */ + if ((iidMeanError > (iidErrThreshold)) || + (iccMeanError > (iccErrThreshold))) { + reducible = 0; + } + } + } /* nEnvelopes != 1 */ + + return reducible; +} + +static void processIidData(PS_DATA *psData, + FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS], + const INT psBands, const INT nEnvelopes, + const FIXP_DBL quantErrorThreshold) { + INT iidIdxFine[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iidIdxCoarse[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + + FIXP_DBL errIID = FL2FXCONST_DBL(0.f); + FIXP_DBL errIIDFine = FL2FXCONST_DBL(0.f); + INT bitsIidFreq = 0; + INT bitsIidTime = 0; + INT bitsFineTot = 0; + INT bitsCoarseTot = 0; + INT error = 0; + INT env, band; + INT diffMode[PS_MAX_ENVELOPES], diffModeFine[PS_MAX_ENVELOPES]; + INT loudnDiff = 0; + INT iidTransmit = 0; + + /* Quantize IID coefficients */ + for (env = 0; env < nEnvelopes; env++) { + errIID += + quantizeCoef(iid[env], psBands, iidQuant_fx, 7, 15, iidIdxCoarse[env]); + errIIDFine += quantizeCoef(iid[env], psBands, iidQuantFine_fx, 15, 31, + iidIdxFine[env]); + } + + /* normalize error to number of envelopes, ps bands + errIID /= psBands*nEnvelopes; + errIIDFine /= psBands*nEnvelopes; */ + + /* Check if IID coefficients should be used in this frame */ + psData->iidEnable = 0; + for (env = 0; env < nEnvelopes; env++) { + for (band = 0; band < psBands; band++) { + loudnDiff += fixp_abs(iidIdxCoarse[env][band]); + iidTransmit++; + } + } + + if (loudnDiff > + fMultI(FL2FXCONST_DBL(0.7f), iidTransmit)) { /* 0.7f empiric value */ + psData->iidEnable = 1; + } + + /* if iid not active -> RESET data */ + if (psData->iidEnable == 0) { + psData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; + for (env = 0; env < nEnvelopes; env++) { + psData->iidDiffMode[env] = PS_DELTA_FREQ; + FDKmemclear(psData->iidIdx[env], sizeof(INT) * psBands); + } + return; + } + + /* count COARSE quantization bits for first envelope*/ + bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[0], NULL, psBands, + PS_IID_RES_COARSE, PS_DELTA_FREQ, &error); + + if ((psData->iidTimeCnt >= MAX_TIME_DIFF_FRAMES) || + (psData->iidQuantModeLast == PS_IID_RES_FINE)) { + bitsIidTime = DO_NOT_USE_THIS_MODE; + } else { + bitsIidTime = + FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[0], psData->iidIdxLast, psBands, + PS_IID_RES_COARSE, PS_DELTA_TIME, &error); + } + + /* decision DELTA_FREQ vs DELTA_TIME */ + if (bitsIidTime > bitsIidFreq) { + diffMode[0] = PS_DELTA_FREQ; + bitsCoarseTot = bitsIidFreq; + } else { + diffMode[0] = PS_DELTA_TIME; + bitsCoarseTot = bitsIidTime; + } + + /* count COARSE quantization bits for following envelopes*/ + for (env = 1; env < nEnvelopes; env++) { + bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[env], NULL, psBands, + PS_IID_RES_COARSE, PS_DELTA_FREQ, &error); + bitsIidTime = + FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[env], iidIdxCoarse[env - 1], + psBands, PS_IID_RES_COARSE, PS_DELTA_TIME, &error); + + /* decision DELTA_FREQ vs DELTA_TIME */ + if (bitsIidTime > bitsIidFreq) { + diffMode[env] = PS_DELTA_FREQ; + bitsCoarseTot += bitsIidFreq; + } else { + diffMode[env] = PS_DELTA_TIME; + bitsCoarseTot += bitsIidTime; + } + } + + /* count FINE quantization bits for first envelope*/ + bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxFine[0], NULL, psBands, + PS_IID_RES_FINE, PS_DELTA_FREQ, &error); + + if ((psData->iidTimeCnt >= MAX_TIME_DIFF_FRAMES) || + (psData->iidQuantModeLast == PS_IID_RES_COARSE)) { + bitsIidTime = DO_NOT_USE_THIS_MODE; + } else { + bitsIidTime = + FDKsbrEnc_EncodeIid(NULL, iidIdxFine[0], psData->iidIdxLast, psBands, + PS_IID_RES_FINE, PS_DELTA_TIME, &error); + } + + /* decision DELTA_FREQ vs DELTA_TIME */ + if (bitsIidTime > bitsIidFreq) { + diffModeFine[0] = PS_DELTA_FREQ; + bitsFineTot = bitsIidFreq; + } else { + diffModeFine[0] = PS_DELTA_TIME; + bitsFineTot = bitsIidTime; + } + + /* count FINE quantization bits for following envelopes*/ + for (env = 1; env < nEnvelopes; env++) { + bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxFine[env], NULL, psBands, + PS_IID_RES_FINE, PS_DELTA_FREQ, &error); + bitsIidTime = + FDKsbrEnc_EncodeIid(NULL, iidIdxFine[env], iidIdxFine[env - 1], psBands, + PS_IID_RES_FINE, PS_DELTA_TIME, &error); + + /* decision DELTA_FREQ vs DELTA_TIME */ + if (bitsIidTime > bitsIidFreq) { + diffModeFine[env] = PS_DELTA_FREQ; + bitsFineTot += bitsIidFreq; + } else { + diffModeFine[env] = PS_DELTA_TIME; + bitsFineTot += bitsIidTime; + } + } + + if (bitsFineTot == bitsCoarseTot) { + /* if same number of bits is needed, use the quantization with lower error + */ + if (errIIDFine < errIID) { + bitsCoarseTot = DO_NOT_USE_THIS_MODE; + } else { + bitsFineTot = DO_NOT_USE_THIS_MODE; + } + } else { + /* const FIXP_DBL minThreshold = + * FL2FXCONST_DBL(0.2f/(IID_SCALE_FT*PS_QUANT_SCALE_FT)*(psBands*nEnvelopes)); + */ + const FIXP_DBL minThreshold = + (FIXP_DBL)((LONG)0x00019999 * (psBands * nEnvelopes)); + + /* decision RES_FINE vs RES_COARSE */ + /* test if errIIDFine*quantErrorThreshold < errIID */ + /* shiftVal 2 comes from scaling of quantErrorThreshold */ + if (fixMax(((errIIDFine >> 1) + (minThreshold >> 1)) >> 1, + fMult(quantErrorThreshold, errIIDFine)) < (errIID >> 2)) { + bitsCoarseTot = DO_NOT_USE_THIS_MODE; + } else if (fixMax(((errIID >> 1) + (minThreshold >> 1)) >> 1, + fMult(quantErrorThreshold, errIID)) < (errIIDFine >> 2)) { + bitsFineTot = DO_NOT_USE_THIS_MODE; + } + } + + /* decision RES_FINE vs RES_COARSE */ + if (bitsFineTot < bitsCoarseTot) { + psData->iidQuantMode = PS_IID_RES_FINE; + for (env = 0; env < nEnvelopes; env++) { + psData->iidDiffMode[env] = diffModeFine[env]; + FDKmemcpy(psData->iidIdx[env], iidIdxFine[env], psBands * sizeof(INT)); + } + } else { + psData->iidQuantMode = PS_IID_RES_COARSE; + for (env = 0; env < nEnvelopes; env++) { + psData->iidDiffMode[env] = diffMode[env]; + FDKmemcpy(psData->iidIdx[env], iidIdxCoarse[env], psBands * sizeof(INT)); + } + } + + /* Count DELTA_TIME encoding streaks */ + for (env = 0; env < nEnvelopes; env++) { + if (psData->iidDiffMode[env] == PS_DELTA_TIME) + psData->iidTimeCnt++; + else + psData->iidTimeCnt = 0; + } +} + +static INT similarIid(PS_DATA *psData, const INT psBands, + const INT nEnvelopes) { + const INT diffThr = (psData->iidQuantMode == PS_IID_RES_COARSE) ? 2 : 3; + const INT sumDiffThr = diffThr * psBands / 4; + INT similar = 0; + INT diff = 0; + INT sumDiff = 0; + INT env = 0; + INT b = 0; + if ((nEnvelopes == psData->nEnvelopesLast) && (nEnvelopes == 1)) { + similar = 1; + for (env = 0; env < nEnvelopes; env++) { + sumDiff = 0; + b = 0; + do { + diff = fixp_abs(psData->iidIdx[env][b] - psData->iidIdxLast[b]); + sumDiff += diff; + if ((diff > diffThr) /* more than x quantization steps in any band */ + || (sumDiff > sumDiffThr)) { /* more than x quantisations steps + overall difference */ + similar = 0; + } + b++; + } while ((b < psBands) && (similar > 0)); + } + } /* nEnvelopes==1 */ + + return similar; +} + +static INT similarIcc(PS_DATA *psData, const INT psBands, + const INT nEnvelopes) { + const INT diffThr = 2; + const INT sumDiffThr = diffThr * psBands / 4; + INT similar = 0; + INT diff = 0; + INT sumDiff = 0; + INT env = 0; + INT b = 0; + if ((nEnvelopes == psData->nEnvelopesLast) && (nEnvelopes == 1)) { + similar = 1; + for (env = 0; env < nEnvelopes; env++) { + sumDiff = 0; + b = 0; + do { + diff = fixp_abs(psData->iccIdx[env][b] - psData->iccIdxLast[b]); + sumDiff += diff; + if ((diff > diffThr) /* more than x quantisation step in any band */ + || (sumDiff > sumDiffThr)) { /* more than x quantisations steps + overall difference */ + similar = 0; + } + b++; + } while ((b < psBands) && (similar > 0)); + } + } /* nEnvelopes==1 */ + + return similar; +} + +static void processIccData( + PS_DATA *psData, + FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], /* const input values: + unable to declare as + const, since it does + not poINT to const + memory */ + const INT psBands, const INT nEnvelopes) { + FIXP_DBL errICC = FL2FXCONST_DBL(0.f); + INT env, band; + INT bitsIccFreq, bitsIccTime; + INT error = 0; + INT inCoherence = 0, iccTransmit = 0; + INT *iccIdxLast; + + iccIdxLast = psData->iccIdxLast; + + /* Quantize ICC coefficients */ + for (env = 0; env < nEnvelopes; env++) { + errICC += + quantizeCoef(icc[env], psBands, iccQuant, 0, 8, psData->iccIdx[env]); + } + + /* Check if ICC coefficients should be used */ + psData->iccEnable = 0; + for (env = 0; env < nEnvelopes; env++) { + for (band = 0; band < psBands; band++) { + inCoherence += psData->iccIdx[env][band]; + iccTransmit++; + } + } + if (inCoherence > + fMultI(FL2FXCONST_DBL(0.5f), iccTransmit)) { /* 0.5f empiric value */ + psData->iccEnable = 1; + } + + if (psData->iccEnable == 0) { + psData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; + for (env = 0; env < nEnvelopes; env++) { + psData->iccDiffMode[env] = PS_DELTA_FREQ; + FDKmemclear(psData->iccIdx[env], sizeof(INT) * psBands); + } + return; + } + + for (env = 0; env < nEnvelopes; env++) { + bitsIccFreq = FDKsbrEnc_EncodeIcc(NULL, psData->iccIdx[env], NULL, psBands, + PS_DELTA_FREQ, &error); + + if (psData->iccTimeCnt < MAX_TIME_DIFF_FRAMES) { + bitsIccTime = FDKsbrEnc_EncodeIcc(NULL, psData->iccIdx[env], iccIdxLast, + psBands, PS_DELTA_TIME, &error); + } else { + bitsIccTime = DO_NOT_USE_THIS_MODE; + } + + if (bitsIccFreq > bitsIccTime) { + psData->iccDiffMode[env] = PS_DELTA_TIME; + psData->iccTimeCnt++; + } else { + psData->iccDiffMode[env] = PS_DELTA_FREQ; + psData->iccTimeCnt = 0; + } + iccIdxLast = psData->iccIdx[env]; + } +} + +static void calculateIID(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS], + INT nEnvelopes, INT psBands) { + INT i = 0; + INT env = 0; + for (env = 0; env < nEnvelopes; env++) { + for (i = 0; i < psBands; i++) { + /* iid[env][i] = 10.0f*(float)log10(pwrL[env][i]/pwrR[env][i]); + */ + FIXP_DBL IID = fMultDiv2(FL2FXCONST_DBL(LOG10_2_10 / IID_SCALE_FT), + (ldPwrL[env][i] - ldPwrR[env][i])); + + IID = fixMin(IID, (FIXP_DBL)(MAXVAL_DBL >> (LD_DATA_SHIFT + 1))); + IID = fixMax(IID, (FIXP_DBL)(MINVAL_DBL >> (LD_DATA_SHIFT + 1))); + iid[env][i] = IID << (LD_DATA_SHIFT + 1); + } + } +} + +static void calculateICC(FIXP_DBL pwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL pwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], + INT nEnvelopes, INT psBands) { + INT i = 0; + INT env = 0; + INT border = psBands; + + switch (psBands) { + case PS_BANDS_COARSE: + border = 5; + break; + case PS_BANDS_MID: + border = 11; + break; + default: + break; + } + + for (env = 0; env < nEnvelopes; env++) { + for (i = 0; i < border; i++) { + /* icc[env][i] = min( pwrCr[env][i] / (float) sqrt(pwrL[env][i] * + * pwrR[env][i]) , 1.f); + */ + int scale; + FIXP_DBL invNrg = invSqrtNorm2( + fMax(fMult(pwrL[env][i], pwrR[env][i]), (FIXP_DBL)1), &scale); + icc[env][i] = + SATURATE_LEFT_SHIFT(fMult(pwrCr[env][i], invNrg), scale, DFRACT_BITS); + } + + for (; i < psBands; i++) { + int denom_e; + FIXP_DBL denom_m = fMultNorm(pwrL[env][i], pwrR[env][i], &denom_e); + + if (denom_m == (FIXP_DBL)0) { + icc[env][i] = (FIXP_DBL)MAXVAL_DBL; + } else { + int num_e, result_e; + FIXP_DBL num_m, result_m; + + num_e = CountLeadingBits( + fixMax(fixp_abs(pwrCr[env][i]), fixp_abs(pwrCi[env][i]))); + num_m = fPow2Div2((pwrCr[env][i] << num_e)) + + fPow2Div2((pwrCi[env][i] << num_e)); + + result_m = fDivNorm(num_m, denom_m, &result_e); + result_e += (-2 * num_e + 1) - denom_e; + icc[env][i] = scaleValueSaturate(sqrtFixp(result_m >> (result_e & 1)), + (result_e + (result_e & 1)) >> 1); + } + } + } +} + +void FDKsbrEnc_initPsBandNrgScale(HANDLE_PS_ENCODE hPsEncode) { + INT group, bin; + INT nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; + + FDKmemclear(hPsEncode->psBandNrgScale, PS_MAX_BANDS * sizeof(SCHAR)); + + for (group = 0; group < nIidGroups; group++) { + /* Translate group to bin */ + bin = hPsEncode->subband2parameterIndex[group]; + + /* Translate from 20 bins to 10 bins */ + if (hPsEncode->psEncMode == PS_BANDS_COARSE) { + bin = bin >> 1; + } + + hPsEncode->psBandNrgScale[bin] = + (hPsEncode->psBandNrgScale[bin] == 0) + ? (hPsEncode->iidGroupWidthLd[group] + 5) + : (fixMax(hPsEncode->iidGroupWidthLd[group], + hPsEncode->psBandNrgScale[bin]) + + 1); + } +} + +FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode(HANDLE_PS_ENCODE *phPsEncode) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (phPsEncode == NULL) { + error = PSENC_INVALID_HANDLE; + } else { + HANDLE_PS_ENCODE hPsEncode = NULL; + if (NULL == (hPsEncode = GetRam_PsEncode())) { + error = PSENC_MEMORY_ERROR; + goto bail; + } + FDKmemclear(hPsEncode, sizeof(PS_ENCODE)); + *phPsEncode = hPsEncode; /* return allocated handle */ + } +bail: + return error; +} + +FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode(HANDLE_PS_ENCODE hPsEncode, + const PS_BANDS psEncMode, + const FIXP_DBL iidQuantErrorThreshold) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (NULL == hPsEncode) { + error = PSENC_INVALID_HANDLE; + } else { + if (PSENC_OK != (InitPSData(&hPsEncode->psData))) { + goto bail; + } + + switch (psEncMode) { + case PS_BANDS_COARSE: + case PS_BANDS_MID: + hPsEncode->nQmfIidGroups = QMF_GROUPS_LO_RES; + hPsEncode->nSubQmfIidGroups = SUBQMF_GROUPS_LO_RES; + FDKmemcpy(hPsEncode->iidGroupBorders, iidGroupBordersLoRes, + (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups + 1) * + sizeof(INT)); + FDKmemcpy(hPsEncode->subband2parameterIndex, subband2parameter20, + (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) * + sizeof(INT)); + FDKmemcpy(hPsEncode->iidGroupWidthLd, iidGroupWidthLdLoRes, + (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) * + sizeof(UCHAR)); + break; + default: + error = PSENC_INIT_ERROR; + goto bail; + } + + hPsEncode->psEncMode = psEncMode; + hPsEncode->iidQuantErrorThreshold = iidQuantErrorThreshold; + FDKsbrEnc_initPsBandNrgScale(hPsEncode); + } +bail: + return error; +} + +FDK_PSENC_ERROR FDKsbrEnc_DestroyPSEncode(HANDLE_PS_ENCODE *phPsEncode) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (NULL != phPsEncode) { + FreeRam_PsEncode(phPsEncode); + } + + return error; +} + +typedef struct { + FIXP_DBL pwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL pwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + +} PS_PWR_DATA; + +FDK_PSENC_ERROR FDKsbrEnc_PSEncode( + HANDLE_PS_ENCODE hPsEncode, HANDLE_PS_OUT hPsOut, UCHAR *dynBandScale, + UINT maxEnvelopes, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + const INT frameSize, const INT sendHeader) { + FDK_PSENC_ERROR error = PSENC_OK; + + HANDLE_PS_DATA hPsData = &hPsEncode->psData; + FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + int envBorder[PS_MAX_ENVELOPES + 1]; + + int group, bin, col, subband, band; + int i = 0; + + int env = 0; + int psBands = (int)hPsEncode->psEncMode; + int nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; + int nEnvelopes = fixMin(maxEnvelopes, (UINT)PS_MAX_ENVELOPES); + + C_ALLOC_SCRATCH_START(pwrData, PS_PWR_DATA, 1) + + for (env = 0; env < nEnvelopes + 1; env++) { + envBorder[env] = fMultI(GetInvInt(nEnvelopes), frameSize * env); + } + + for (env = 0; env < nEnvelopes; env++) { + /* clear energy array */ + for (band = 0; band < psBands; band++) { + pwrData->pwrL[env][band] = pwrData->pwrR[env][band] = + pwrData->pwrCr[env][band] = pwrData->pwrCi[env][band] = FIXP_DBL(1); + } + + /**** calculate energies and correlation ****/ + + /* start with hybrid data */ + for (group = 0; group < nIidGroups; group++) { + /* Translate group to bin */ + bin = hPsEncode->subband2parameterIndex[group]; + + /* Translate from 20 bins to 10 bins */ + if (hPsEncode->psEncMode == PS_BANDS_COARSE) { + bin >>= 1; + } + + /* determine group border */ + int bScale = hPsEncode->psBandNrgScale[bin]; + + FIXP_DBL pwrL_env_bin = pwrData->pwrL[env][bin]; + FIXP_DBL pwrR_env_bin = pwrData->pwrR[env][bin]; + FIXP_DBL pwrCr_env_bin = pwrData->pwrCr[env][bin]; + FIXP_DBL pwrCi_env_bin = pwrData->pwrCi[env][bin]; + + int scale = (int)dynBandScale[bin]; + for (col = envBorder[env]; col < envBorder[env + 1]; col++) { + for (subband = hPsEncode->iidGroupBorders[group]; + subband < hPsEncode->iidGroupBorders[group + 1]; subband++) { + FIXP_DBL l_real = (hybridData[col][0][0][subband]) << scale; + FIXP_DBL l_imag = (hybridData[col][0][1][subband]) << scale; + FIXP_DBL r_real = (hybridData[col][1][0][subband]) << scale; + FIXP_DBL r_imag = (hybridData[col][1][1][subband]) << scale; + + pwrL_env_bin += (fPow2Div2(l_real) + fPow2Div2(l_imag)) >> bScale; + pwrR_env_bin += (fPow2Div2(r_real) + fPow2Div2(r_imag)) >> bScale; + pwrCr_env_bin += + (fMultDiv2(l_real, r_real) + fMultDiv2(l_imag, r_imag)) >> bScale; + pwrCi_env_bin += + (fMultDiv2(r_real, l_imag) - fMultDiv2(l_real, r_imag)) >> bScale; + } + } + /* assure, nrg's of left and right channel are not negative; necessary on + * 16 bit multiply units */ + pwrData->pwrL[env][bin] = fixMax((FIXP_DBL)0, pwrL_env_bin); + pwrData->pwrR[env][bin] = fixMax((FIXP_DBL)0, pwrR_env_bin); + + pwrData->pwrCr[env][bin] = pwrCr_env_bin; + pwrData->pwrCi[env][bin] = pwrCi_env_bin; + + } /* nIidGroups */ + + /* calc logarithmic energy */ + LdDataVector(pwrData->pwrL[env], pwrData->ldPwrL[env], psBands); + LdDataVector(pwrData->pwrR[env], pwrData->ldPwrR[env], psBands); + + } /* nEnvelopes */ + + /* calculate iid and icc */ + calculateIID(pwrData->ldPwrL, pwrData->ldPwrR, iid, nEnvelopes, psBands); + calculateICC(pwrData->pwrL, pwrData->pwrR, pwrData->pwrCr, pwrData->pwrCi, + icc, nEnvelopes, psBands); + + /*** Envelope Reduction ***/ + while (envelopeReducible(iid, icc, psBands, nEnvelopes)) { + int e = 0; + /* sum energies of two neighboring envelopes */ + nEnvelopes >>= 1; + for (e = 0; e < nEnvelopes; e++) { + FDKsbrEnc_addFIXP_DBL(pwrData->pwrL[2 * e], pwrData->pwrL[2 * e + 1], + pwrData->pwrL[e], psBands); + FDKsbrEnc_addFIXP_DBL(pwrData->pwrR[2 * e], pwrData->pwrR[2 * e + 1], + pwrData->pwrR[e], psBands); + FDKsbrEnc_addFIXP_DBL(pwrData->pwrCr[2 * e], pwrData->pwrCr[2 * e + 1], + pwrData->pwrCr[e], psBands); + FDKsbrEnc_addFIXP_DBL(pwrData->pwrCi[2 * e], pwrData->pwrCi[2 * e + 1], + pwrData->pwrCi[e], psBands); + + /* calc logarithmic energy */ + LdDataVector(pwrData->pwrL[e], pwrData->ldPwrL[e], psBands); + LdDataVector(pwrData->pwrR[e], pwrData->ldPwrR[e], psBands); + + /* reduce number of envelopes and adjust borders */ + envBorder[e] = envBorder[2 * e]; + } + envBorder[nEnvelopes] = envBorder[2 * nEnvelopes]; + + /* re-calculate iid and icc */ + calculateIID(pwrData->ldPwrL, pwrData->ldPwrR, iid, nEnvelopes, psBands); + calculateICC(pwrData->pwrL, pwrData->pwrR, pwrData->pwrCr, pwrData->pwrCi, + icc, nEnvelopes, psBands); + } + + /* */ + if (sendHeader) { + hPsData->headerCnt = MAX_PS_NOHEADER_CNT; + hPsData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; + hPsData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; + hPsData->noEnvCnt = MAX_NOENV_CNT; + } + + /*** Parameter processing, quantisation etc ***/ + processIidData(hPsData, iid, psBands, nEnvelopes, + hPsEncode->iidQuantErrorThreshold); + processIccData(hPsData, icc, psBands, nEnvelopes); + + /*** Initialize output struct ***/ + + /* PS Header on/off ? */ + if ((hPsData->headerCnt < MAX_PS_NOHEADER_CNT) && + ((hPsData->iidQuantMode == hPsData->iidQuantModeLast) && + (hPsData->iccQuantMode == hPsData->iccQuantModeLast)) && + ((hPsData->iidEnable == hPsData->iidEnableLast) && + (hPsData->iccEnable == hPsData->iccEnableLast))) { + hPsOut->enablePSHeader = 0; + } else { + hPsOut->enablePSHeader = 1; + hPsData->headerCnt = 0; + } + + /* nEnvelopes = 0 ? */ + if ((hPsData->noEnvCnt < MAX_NOENV_CNT) && + (similarIid(hPsData, psBands, nEnvelopes)) && + (similarIcc(hPsData, psBands, nEnvelopes))) { + hPsOut->nEnvelopes = nEnvelopes = 0; + hPsData->noEnvCnt++; + } else { + hPsData->noEnvCnt = 0; + } + + if (nEnvelopes > 0) { + hPsOut->enableIID = hPsData->iidEnable; + hPsOut->iidMode = getIIDMode(psBands, hPsData->iidQuantMode); + + hPsOut->enableICC = hPsData->iccEnable; + hPsOut->iccMode = getICCMode(psBands, hPsData->iccQuantMode); + + hPsOut->enableIpdOpd = 0; + hPsOut->frameClass = 0; + hPsOut->nEnvelopes = nEnvelopes; + + for (env = 0; env < nEnvelopes; env++) { + hPsOut->frameBorder[env] = envBorder[env + 1]; + hPsOut->deltaIID[env] = (PS_DELTA)hPsData->iidDiffMode[env]; + hPsOut->deltaICC[env] = (PS_DELTA)hPsData->iccDiffMode[env]; + for (band = 0; band < psBands; band++) { + hPsOut->iid[env][band] = hPsData->iidIdx[env][band]; + hPsOut->icc[env][band] = hPsData->iccIdx[env][band]; + } + } + + /* IPD OPD not supported right now */ + FDKmemclear(hPsOut->ipd, + PS_MAX_ENVELOPES * PS_MAX_BANDS * sizeof(PS_DELTA)); + for (env = 0; env < PS_MAX_ENVELOPES; env++) { + hPsOut->deltaIPD[env] = PS_DELTA_FREQ; + hPsOut->deltaOPD[env] = PS_DELTA_FREQ; + } + + FDKmemclear(hPsOut->ipdLast, PS_MAX_BANDS * sizeof(INT)); + FDKmemclear(hPsOut->opdLast, PS_MAX_BANDS * sizeof(INT)); + + for (band = 0; band < PS_MAX_BANDS; band++) { + hPsOut->iidLast[band] = hPsData->iidIdxLast[band]; + hPsOut->iccLast[band] = hPsData->iccIdxLast[band]; + } + + /* save iids and iccs for differential time coding in the next frame */ + hPsData->nEnvelopesLast = nEnvelopes; + hPsData->iidEnableLast = hPsData->iidEnable; + hPsData->iccEnableLast = hPsData->iccEnable; + hPsData->iidQuantModeLast = hPsData->iidQuantMode; + hPsData->iccQuantModeLast = hPsData->iccQuantMode; + for (i = 0; i < psBands; i++) { + hPsData->iidIdxLast[i] = hPsData->iidIdx[nEnvelopes - 1][i]; + hPsData->iccIdxLast[i] = hPsData->iccIdx[nEnvelopes - 1][i]; + } + } /* Envelope > 0 */ + + C_ALLOC_SCRATCH_END(pwrData, PS_PWR_DATA, 1) + + return error; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_encode.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_encode.h new file mode 100644 index 0000000000000..4237a00c35de2 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_encode.h @@ -0,0 +1,185 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): M. Neuendorf, N. Rettelbach, M. Multrus + + Description: PS Parameter extraction, encoding + +*******************************************************************************/ + +/*! + \file + \brief PS parameter extraction, encoding functions $Revision: 92790 $ +*/ + +#ifndef PS_ENCODE_H +#define PS_ENCODE_H + +#include "ps_const.h" +#include "ps_bitenc.h" + +#define IID_SCALE_FT (64.f) /* maxVal in Quant tab is +/- 50 */ +#define IID_SCALE 6 /* maxVal in Quant tab is +/- 50 */ +#define IID_MAXVAL (1 << IID_SCALE) + +#define PS_QUANT_SCALE_FT \ + (64.f) /* error smaller (64-25)/64 * 20 bands * 4 env -> QuantScale 64 */ +#define PS_QUANT_SCALE \ + 6 /* error smaller (64-25)/64 * 20 bands * 4 env -> QuantScale 6 bit */ + +#define QMF_GROUPS_LO_RES 12 +#define SUBQMF_GROUPS_LO_RES 10 +#define QMF_GROUPS_HI_RES 18 +#define SUBQMF_GROUPS_HI_RES 30 + +typedef struct T_PS_DATA { + INT iidEnable; + INT iidEnableLast; + INT iidQuantMode; + INT iidQuantModeLast; + INT iidDiffMode[PS_MAX_ENVELOPES]; + INT iidIdx[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iidIdxLast[PS_MAX_BANDS]; + + INT iccEnable; + INT iccEnableLast; + INT iccQuantMode; + INT iccQuantModeLast; + INT iccDiffMode[PS_MAX_ENVELOPES]; + INT iccIdx[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iccIdxLast[PS_MAX_BANDS]; + + INT nEnvelopesLast; + + INT headerCnt; + INT iidTimeCnt; + INT iccTimeCnt; + INT noEnvCnt; + +} PS_DATA, *HANDLE_PS_DATA; + +typedef struct T_PS_ENCODE { + PS_DATA psData; + + PS_BANDS psEncMode; + INT nQmfIidGroups; + INT nSubQmfIidGroups; + INT iidGroupBorders[QMF_GROUPS_HI_RES + SUBQMF_GROUPS_HI_RES + 1]; + INT subband2parameterIndex[QMF_GROUPS_HI_RES + SUBQMF_GROUPS_HI_RES]; + UCHAR iidGroupWidthLd[QMF_GROUPS_HI_RES + SUBQMF_GROUPS_HI_RES]; + FIXP_DBL iidQuantErrorThreshold; + + UCHAR psBandNrgScale[PS_MAX_BANDS]; + +} PS_ENCODE; + +typedef struct T_PS_ENCODE *HANDLE_PS_ENCODE; + +FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode(HANDLE_PS_ENCODE *phPsEncode); + +FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode(HANDLE_PS_ENCODE hPsEncode, + const PS_BANDS psEncMode, + const FIXP_DBL iidQuantErrorThreshold); + +FDK_PSENC_ERROR FDKsbrEnc_DestroyPSEncode(HANDLE_PS_ENCODE *phPsEncode); + +FDK_PSENC_ERROR FDKsbrEnc_PSEncode( + HANDLE_PS_ENCODE hPsEncode, HANDLE_PS_OUT hPsOut, UCHAR *dynBandScale, + UINT maxEnvelopes, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + const INT frameSize, const INT sendHeader); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_main.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_main.cpp new file mode 100644 index 0000000000000..4d7a7a576ad9b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_main.cpp @@ -0,0 +1,606 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): M. Multrus + + Description: PS Wrapper, Downmix + +*******************************************************************************/ + +#include "ps_main.h" + +/* Includes ******************************************************************/ +#include "ps_bitenc.h" +#include "sbrenc_ram.h" + +/*--------------- function declarations --------------------*/ +static void psFindBestScaling( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + UCHAR *dynBandScale, FIXP_DBL *maxBandValue, SCHAR *dmxScale); + +/*------------- function definitions ----------------*/ +FDK_PSENC_ERROR PSEnc_Create(HANDLE_PARAMETRIC_STEREO *phParametricStereo) { + FDK_PSENC_ERROR error = PSENC_OK; + HANDLE_PARAMETRIC_STEREO hParametricStereo = NULL; + + if (phParametricStereo == NULL) { + error = PSENC_INVALID_HANDLE; + } else { + int i; + + if (NULL == (hParametricStereo = GetRam_ParamStereo())) { + error = PSENC_MEMORY_ERROR; + goto bail; + } + FDKmemclear(hParametricStereo, sizeof(PARAMETRIC_STEREO)); + + if (PSENC_OK != + (error = FDKsbrEnc_CreatePSEncode(&hParametricStereo->hPsEncode))) { + error = PSENC_MEMORY_ERROR; + goto bail; + } + + for (i = 0; i < MAX_PS_CHANNELS; i++) { + if (FDKhybridAnalysisOpen( + &hParametricStereo->fdkHybAnaFilter[i], + hParametricStereo->__staticHybAnaStatesLF[i], + sizeof(hParametricStereo->__staticHybAnaStatesLF[i]), + hParametricStereo->__staticHybAnaStatesHF[i], + sizeof(hParametricStereo->__staticHybAnaStatesHF[i])) != 0) { + error = PSENC_MEMORY_ERROR; + goto bail; + } + } + } + +bail: + if (phParametricStereo != NULL) { + *phParametricStereo = hParametricStereo; /* return allocated handle */ + } + + if (error != PSENC_OK) { + PSEnc_Destroy(phParametricStereo); + } + return error; +} + +FDK_PSENC_ERROR PSEnc_Init(HANDLE_PARAMETRIC_STEREO hParametricStereo, + const HANDLE_PSENC_CONFIG hPsEncConfig, + INT noQmfSlots, INT noQmfBands, UCHAR *dynamic_RAM) { + FDK_PSENC_ERROR error = PSENC_OK; + + if ((NULL == hParametricStereo) || (NULL == hPsEncConfig)) { + error = PSENC_INVALID_HANDLE; + } else { + int ch, i; + + hParametricStereo->initPS = 1; + hParametricStereo->noQmfSlots = noQmfSlots; + hParametricStereo->noQmfBands = noQmfBands; + + /* clear delay lines */ + FDKmemclear(hParametricStereo->qmfDelayLines, + sizeof(hParametricStereo->qmfDelayLines)); + + hParametricStereo->qmfDelayScale = FRACT_BITS - 1; + + /* create configuration for hybrid filter bank */ + for (ch = 0; ch < MAX_PS_CHANNELS; ch++) { + FDKhybridAnalysisInit(&hParametricStereo->fdkHybAnaFilter[ch], + THREE_TO_TEN, 64, 64, 1); + } /* ch */ + + FDKhybridSynthesisInit(&hParametricStereo->fdkHybSynFilter, THREE_TO_TEN, + 64, 64); + + /* determine average delay */ + hParametricStereo->psDelay = + (HYBRID_FILTER_DELAY * hParametricStereo->noQmfBands); + + if ((hPsEncConfig->maxEnvelopes < PSENC_NENV_1) || + (hPsEncConfig->maxEnvelopes > PSENC_NENV_MAX)) { + hPsEncConfig->maxEnvelopes = PSENC_NENV_DEFAULT; + } + hParametricStereo->maxEnvelopes = hPsEncConfig->maxEnvelopes; + + if (PSENC_OK != + (error = FDKsbrEnc_InitPSEncode( + hParametricStereo->hPsEncode, (PS_BANDS)hPsEncConfig->nStereoBands, + hPsEncConfig->iidQuantErrorThreshold))) { + goto bail; + } + + for (ch = 0; ch < MAX_PS_CHANNELS; ch++) { + FIXP_DBL *pDynReal = GetRam_Sbr_envRBuffer(ch, dynamic_RAM); + FIXP_DBL *pDynImag = GetRam_Sbr_envIBuffer(ch, dynamic_RAM); + + for (i = 0; i < HYBRID_FRAMESIZE; i++) { + hParametricStereo->pHybridData[i + HYBRID_READ_OFFSET][ch][0] = + &pDynReal[i * MAX_HYBRID_BANDS]; + hParametricStereo->pHybridData[i + HYBRID_READ_OFFSET][ch][1] = + &pDynImag[i * MAX_HYBRID_BANDS]; + ; + } + + for (i = 0; i < HYBRID_READ_OFFSET; i++) { + hParametricStereo->pHybridData[i][ch][0] = + hParametricStereo->__staticHybridData[i][ch][0]; + hParametricStereo->pHybridData[i][ch][1] = + hParametricStereo->__staticHybridData[i][ch][1]; + } + } /* ch */ + + /* clear static hybrid buffer */ + FDKmemclear(hParametricStereo->__staticHybridData, + sizeof(hParametricStereo->__staticHybridData)); + + /* clear bs buffer */ + FDKmemclear(hParametricStereo->psOut, sizeof(hParametricStereo->psOut)); + + hParametricStereo->psOut[0].enablePSHeader = + 1; /* write ps header in first frame */ + + /* clear scaling buffer */ + FDKmemclear(hParametricStereo->dynBandScale, sizeof(UCHAR) * PS_MAX_BANDS); + FDKmemclear(hParametricStereo->maxBandValue, + sizeof(FIXP_DBL) * PS_MAX_BANDS); + + } /* valid handle */ +bail: + return error; +} + +FDK_PSENC_ERROR PSEnc_Destroy(HANDLE_PARAMETRIC_STEREO *phParametricStereo) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (NULL != phParametricStereo) { + HANDLE_PARAMETRIC_STEREO hParametricStereo = *phParametricStereo; + if (hParametricStereo != NULL) { + FDKsbrEnc_DestroyPSEncode(&hParametricStereo->hPsEncode); + FreeRam_ParamStereo(phParametricStereo); + } + } + + return error; +} + +static FDK_PSENC_ERROR ExtractPSParameters( + HANDLE_PARAMETRIC_STEREO hParametricStereo, const int sendHeader, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2]) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (hParametricStereo == NULL) { + error = PSENC_INVALID_HANDLE; + } else { + /* call ps encode function */ + if (hParametricStereo->initPS) { + hParametricStereo->psOut[1] = hParametricStereo->psOut[0]; + } + hParametricStereo->psOut[0] = hParametricStereo->psOut[1]; + + if (PSENC_OK != + (error = FDKsbrEnc_PSEncode( + hParametricStereo->hPsEncode, &hParametricStereo->psOut[1], + hParametricStereo->dynBandScale, hParametricStereo->maxEnvelopes, + hybridData, hParametricStereo->noQmfSlots, sendHeader))) { + goto bail; + } + + if (hParametricStereo->initPS) { + hParametricStereo->psOut[0] = hParametricStereo->psOut[1]; + hParametricStereo->initPS = 0; + } + } +bail: + return error; +} + +static FDK_PSENC_ERROR DownmixPSQmfData( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_QMF_FILTER_BANK sbrSynthQmf, FIXP_DBL **RESTRICT mixRealQmfData, + FIXP_DBL **RESTRICT mixImagQmfData, INT_PCM *downsampledOutSignal, + const UINT downsampledOutSignalBufSize, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + const INT noQmfSlots, const INT psQmfScale[MAX_PS_CHANNELS], + SCHAR *qmfScale) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (hParametricStereo == NULL) { + error = PSENC_INVALID_HANDLE; + } else { + int n, k; + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, 2 * 64) + + /* define scalings */ + int dynQmfScale = fixMax( + 0, hParametricStereo->dmxScale - + 1); /* scale one bit more for addition of left and right */ + int downmixScale = psQmfScale[0] - dynQmfScale; + const FIXP_DBL maxStereoScaleFactor = MAXVAL_DBL; /* 2.f/2.f */ + + for (n = 0; n < noQmfSlots; n++) { + FIXP_DBL tmpHybrid[2][MAX_HYBRID_BANDS]; + + for (k = 0; k < 71; k++) { + int dynScale, sc; /* scaling */ + FIXP_DBL tmpLeftReal, tmpRightReal, tmpLeftImag, tmpRightImag; + FIXP_DBL tmpScaleFactor, stereoScaleFactor; + + tmpLeftReal = hybridData[n][0][0][k]; + tmpLeftImag = hybridData[n][0][1][k]; + tmpRightReal = hybridData[n][1][0][k]; + tmpRightImag = hybridData[n][1][1][k]; + + sc = fixMax( + 0, CntLeadingZeros(fixMax( + fixMax(fixp_abs(tmpLeftReal), fixp_abs(tmpLeftImag)), + fixMax(fixp_abs(tmpRightReal), fixp_abs(tmpRightImag)))) - + 2); + + tmpLeftReal <<= sc; + tmpLeftImag <<= sc; + tmpRightReal <<= sc; + tmpRightImag <<= sc; + dynScale = fixMin(sc - dynQmfScale, DFRACT_BITS - 1); + + /* calc stereo scale factor to avoid loss of energy in bands */ + /* stereo scale factor = min(2.0f, sqrt( (abs(l(k, n)^2 + abs(r(k, n)^2 + * )))/(0.5f*abs(l(k, n) + r(k, n))) )) */ + stereoScaleFactor = fPow2Div2(tmpLeftReal) + fPow2Div2(tmpLeftImag) + + fPow2Div2(tmpRightReal) + fPow2Div2(tmpRightImag); + + /* might be that tmpScaleFactor becomes negative, so fabs(.) */ + tmpScaleFactor = + fixp_abs(stereoScaleFactor + fMult(tmpLeftReal, tmpRightReal) + + fMult(tmpLeftImag, tmpRightImag)); + + /* min(2.0f, sqrt(stereoScaleFactor/(0.5f*tmpScaleFactor))) */ + if ((stereoScaleFactor >> 1) < + fMult(maxStereoScaleFactor, tmpScaleFactor)) { + int sc_num = CountLeadingBits(stereoScaleFactor); + int sc_denum = CountLeadingBits(tmpScaleFactor); + sc = -(sc_num - sc_denum); + + tmpScaleFactor = schur_div((stereoScaleFactor << (sc_num)) >> 1, + tmpScaleFactor << sc_denum, 16); + + /* prevent odd scaling for next sqrt calculation */ + if (sc & 0x1) { + sc++; + tmpScaleFactor >>= 1; + } + stereoScaleFactor = sqrtFixp(tmpScaleFactor); + stereoScaleFactor <<= (sc >> 1); + } else { + stereoScaleFactor = maxStereoScaleFactor; + } + + /* write data to hybrid output */ + tmpHybrid[0][k] = fMultDiv2(stereoScaleFactor, + (FIXP_DBL)(tmpLeftReal + tmpRightReal)) >> + dynScale; + tmpHybrid[1][k] = fMultDiv2(stereoScaleFactor, + (FIXP_DBL)(tmpLeftImag + tmpRightImag)) >> + dynScale; + + } /* hybrid bands - k */ + + FDKhybridSynthesisApply(&hParametricStereo->fdkHybSynFilter, tmpHybrid[0], + tmpHybrid[1], mixRealQmfData[n], + mixImagQmfData[n]); + + qmfSynthesisFilteringSlot( + sbrSynthQmf, mixRealQmfData[n], mixImagQmfData[n], downmixScale - 7, + downmixScale - 7, + downsampledOutSignal + (n * sbrSynthQmf->no_channels), 1, + pWorkBuffer); + + } /* slots */ + + *qmfScale = -downmixScale + 7; + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2 * 64) + + { + const INT noQmfSlots2 = hParametricStereo->noQmfSlots >> 1; + const int noQmfBands = hParametricStereo->noQmfBands; + + INT scale, i, j, slotOffset; + + FIXP_DBL tmp[2][64]; + + for (i = 0; i < noQmfSlots2; i++) { + FDKmemcpy(tmp[0], hParametricStereo->qmfDelayLines[0][i], + noQmfBands * sizeof(FIXP_DBL)); + FDKmemcpy(tmp[1], hParametricStereo->qmfDelayLines[1][i], + noQmfBands * sizeof(FIXP_DBL)); + + FDKmemcpy(hParametricStereo->qmfDelayLines[0][i], + mixRealQmfData[i + noQmfSlots2], + noQmfBands * sizeof(FIXP_DBL)); + FDKmemcpy(hParametricStereo->qmfDelayLines[1][i], + mixImagQmfData[i + noQmfSlots2], + noQmfBands * sizeof(FIXP_DBL)); + + FDKmemcpy(mixRealQmfData[i + noQmfSlots2], mixRealQmfData[i], + noQmfBands * sizeof(FIXP_DBL)); + FDKmemcpy(mixImagQmfData[i + noQmfSlots2], mixImagQmfData[i], + noQmfBands * sizeof(FIXP_DBL)); + + FDKmemcpy(mixRealQmfData[i], tmp[0], noQmfBands * sizeof(FIXP_DBL)); + FDKmemcpy(mixImagQmfData[i], tmp[1], noQmfBands * sizeof(FIXP_DBL)); + } + + if (hParametricStereo->qmfDelayScale > *qmfScale) { + scale = hParametricStereo->qmfDelayScale - *qmfScale; + slotOffset = 0; + } else { + scale = *qmfScale - hParametricStereo->qmfDelayScale; + slotOffset = noQmfSlots2; + } + + for (i = 0; i < noQmfSlots2; i++) { + for (j = 0; j < noQmfBands; j++) { + mixRealQmfData[i + slotOffset][j] >>= scale; + mixImagQmfData[i + slotOffset][j] >>= scale; + } + } + + scale = *qmfScale; + *qmfScale = fMin(*qmfScale, hParametricStereo->qmfDelayScale); + hParametricStereo->qmfDelayScale = scale; + } + + } /* valid handle */ + + return error; +} + +INT FDKsbrEnc_PSEnc_WritePSData(HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitstream) { + return ( + (hParametricStereo != NULL) + ? FDKsbrEnc_WritePSBitstream(&hParametricStereo->psOut[0], hBitstream) + : 0); +} + +FDK_PSENC_ERROR FDKsbrEnc_PSEnc_ParametricStereoProcessing( + HANDLE_PARAMETRIC_STEREO hParametricStereo, INT_PCM *samples[2], + UINT samplesBufSize, QMF_FILTER_BANK **hQmfAnalysis, + FIXP_DBL **RESTRICT downmixedRealQmfData, + FIXP_DBL **RESTRICT downmixedImagQmfData, INT_PCM *downsampledOutSignal, + HANDLE_QMF_FILTER_BANK sbrSynthQmf, SCHAR *qmfScale, const int sendHeader) { + FDK_PSENC_ERROR error = PSENC_OK; + INT psQmfScale[MAX_PS_CHANNELS] = {0}; + int psCh, i; + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, 4 * 64) + + for (psCh = 0; psCh < MAX_PS_CHANNELS; psCh++) { + for (i = 0; i < hQmfAnalysis[psCh]->no_col; i++) { + qmfAnalysisFilteringSlot( + hQmfAnalysis[psCh], &pWorkBuffer[2 * 64], /* qmfReal[64] */ + &pWorkBuffer[3 * 64], /* qmfImag[64] */ + samples[psCh] + i * hQmfAnalysis[psCh]->no_channels, 1, + &pWorkBuffer[0 * 64] /* qmf workbuffer 2*64 */ + ); + + FDKhybridAnalysisApply( + &hParametricStereo->fdkHybAnaFilter[psCh], + &pWorkBuffer[2 * 64], /* qmfReal[64] */ + &pWorkBuffer[3 * 64], /* qmfImag[64] */ + hParametricStereo->pHybridData[i + HYBRID_READ_OFFSET][psCh][0], + hParametricStereo->pHybridData[i + HYBRID_READ_OFFSET][psCh][1]); + + } /* no_col loop i */ + + psQmfScale[psCh] = hQmfAnalysis[psCh]->outScalefactor; + + } /* for psCh */ + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 4 * 64) + + /* find best scaling in new QMF and Hybrid data */ + psFindBestScaling( + hParametricStereo, &hParametricStereo->pHybridData[HYBRID_READ_OFFSET], + hParametricStereo->dynBandScale, hParametricStereo->maxBandValue, + &hParametricStereo->dmxScale); + + /* extract the ps parameters */ + if (PSENC_OK != + (error = ExtractPSParameters(hParametricStereo, sendHeader, + &hParametricStereo->pHybridData[0]))) { + goto bail; + } + + /* save hybrid date for next frame */ + for (i = 0; i < HYBRID_READ_OFFSET; i++) { + FDKmemcpy( + hParametricStereo->pHybridData[i][0][0], + hParametricStereo->pHybridData[hParametricStereo->noQmfSlots + i][0][0], + MAX_HYBRID_BANDS * sizeof(FIXP_DBL)); /* left, real */ + FDKmemcpy( + hParametricStereo->pHybridData[i][0][1], + hParametricStereo->pHybridData[hParametricStereo->noQmfSlots + i][0][1], + MAX_HYBRID_BANDS * sizeof(FIXP_DBL)); /* left, imag */ + FDKmemcpy( + hParametricStereo->pHybridData[i][1][0], + hParametricStereo->pHybridData[hParametricStereo->noQmfSlots + i][1][0], + MAX_HYBRID_BANDS * sizeof(FIXP_DBL)); /* right, real */ + FDKmemcpy( + hParametricStereo->pHybridData[i][1][1], + hParametricStereo->pHybridData[hParametricStereo->noQmfSlots + i][1][1], + MAX_HYBRID_BANDS * sizeof(FIXP_DBL)); /* right, imag */ + } + + /* downmix and hybrid synthesis */ + if (PSENC_OK != + (error = DownmixPSQmfData( + hParametricStereo, sbrSynthQmf, downmixedRealQmfData, + downmixedImagQmfData, downsampledOutSignal, samplesBufSize, + &hParametricStereo->pHybridData[HYBRID_READ_OFFSET], + hParametricStereo->noQmfSlots, psQmfScale, qmfScale))) { + goto bail; + } + +bail: + + return error; +} + +static void psFindBestScaling( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + UCHAR *dynBandScale, FIXP_DBL *maxBandValue, SCHAR *dmxScale) { + HANDLE_PS_ENCODE hPsEncode = hParametricStereo->hPsEncode; + + INT group, bin, col, band; + const INT frameSize = hParametricStereo->noQmfSlots; + const INT psBands = (INT)hPsEncode->psEncMode; + const INT nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; + + /* group wise scaling */ + FIXP_DBL maxVal[2][PS_MAX_BANDS]; + FIXP_DBL maxValue = FL2FXCONST_DBL(0.f); + + FDKmemclear(maxVal, sizeof(maxVal)); + + /* start with hybrid data */ + for (group = 0; group < nIidGroups; group++) { + /* Translate group to bin */ + bin = hPsEncode->subband2parameterIndex[group]; + + /* Translate from 20 bins to 10 bins */ + if (hPsEncode->psEncMode == PS_BANDS_COARSE) { + bin >>= 1; + } + + /* QMF downmix scaling */ + for (col = 0; col < frameSize; col++) { + int i, section = (col < frameSize - HYBRID_READ_OFFSET) ? 0 : 1; + FIXP_DBL tmp = maxVal[section][bin]; + for (i = hPsEncode->iidGroupBorders[group]; + i < hPsEncode->iidGroupBorders[group + 1]; i++) { + tmp = fixMax(tmp, (FIXP_DBL)fixp_abs(hybridData[col][0][0][i])); + tmp = fixMax(tmp, (FIXP_DBL)fixp_abs(hybridData[col][0][1][i])); + tmp = fixMax(tmp, (FIXP_DBL)fixp_abs(hybridData[col][1][0][i])); + tmp = fixMax(tmp, (FIXP_DBL)fixp_abs(hybridData[col][1][1][i])); + } + maxVal[section][bin] = tmp; + } + } /* nIidGroups */ + + /* convert maxSpec to maxScaling, find scaling space */ + for (band = 0; band < psBands; band++) { +#ifndef MULT_16x16 + dynBandScale[band] = + CountLeadingBits(fixMax(maxVal[0][band], maxBandValue[band])); +#else + dynBandScale[band] = fixMax( + 0, CountLeadingBits(fixMax(maxVal[0][band], maxBandValue[band])) - + FRACT_BITS); +#endif + maxValue = fixMax(maxValue, fixMax(maxVal[0][band], maxVal[1][band])); + maxBandValue[band] = fixMax(maxVal[0][band], maxVal[1][band]); + } + + /* calculate maximal scaling for QMF downmix */ +#ifndef MULT_16x16 + *dmxScale = fixMin(DFRACT_BITS, CountLeadingBits(maxValue)); +#else + *dmxScale = fixMax(0, fixMin(FRACT_BITS, CountLeadingBits((maxValue)))); +#endif +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_main.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_main.h new file mode 100644 index 0000000000000..88b2993cef5d1 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ps_main.h @@ -0,0 +1,270 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): Markus Multrus + + Description: PS Wrapper, Downmix header file + +*******************************************************************************/ + +#ifndef PS_MAIN_H +#define PS_MAIN_H + +/* Includes ******************************************************************/ + +#include "sbr_def.h" +#include "qmf.h" +#include "ps_encode.h" +#include "FDK_bitstream.h" +#include "FDK_hybrid.h" + +/* Data Types ****************************************************************/ +typedef enum { + PSENC_STEREO_BANDS_INVALID = 0, + PSENC_STEREO_BANDS_10 = 10, + PSENC_STEREO_BANDS_20 = 20 + +} PSENC_STEREO_BANDS_CONFIG; + +typedef enum { + PSENC_NENV_1 = 1, + PSENC_NENV_2 = 2, + PSENC_NENV_4 = 4, + PSENC_NENV_DEFAULT = PSENC_NENV_2, + PSENC_NENV_MAX = PSENC_NENV_4 + +} PSENC_NENV_CONFIG; + +typedef struct { + UINT bitrateFrom; /* inclusive */ + UINT bitrateTo; /* exclusive */ + PSENC_STEREO_BANDS_CONFIG nStereoBands; + PSENC_NENV_CONFIG nEnvelopes; + LONG iidQuantErrorThreshold; /* quantization threshold to switch between + coarse and fine iid quantization */ + +} psTuningTable_t; + +/* Function / Class Declarations *********************************************/ + +typedef struct T_PARAMETRIC_STEREO { + HANDLE_PS_ENCODE hPsEncode; + PS_OUT psOut[2]; + + FIXP_DBL __staticHybridData[HYBRID_READ_OFFSET][MAX_PS_CHANNELS][2] + [MAX_HYBRID_BANDS]; + FIXP_DBL + *pHybridData[HYBRID_READ_OFFSET + HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2]; + + FIXP_DBL qmfDelayLines[2][32 >> 1][64]; + int qmfDelayScale; + + INT psDelay; + UINT maxEnvelopes; + UCHAR dynBandScale[PS_MAX_BANDS]; + FIXP_DBL maxBandValue[PS_MAX_BANDS]; + SCHAR dmxScale; + INT initPS; + INT noQmfSlots; + INT noQmfBands; + + FIXP_DBL __staticHybAnaStatesLF[MAX_PS_CHANNELS][2 * HYBRID_FILTER_LENGTH * + HYBRID_MAX_QMF_BANDS]; + FIXP_DBL __staticHybAnaStatesHF[MAX_PS_CHANNELS][2 * HYBRID_FILTER_DELAY * + (64 - HYBRID_MAX_QMF_BANDS)]; + FDK_ANA_HYB_FILTER fdkHybAnaFilter[MAX_PS_CHANNELS]; + FDK_SYN_HYB_FILTER fdkHybSynFilter; + +} PARAMETRIC_STEREO; + +typedef struct T_PSENC_CONFIG { + INT frameSize; + INT qmfFilterMode; + INT sbrPsDelay; + PSENC_STEREO_BANDS_CONFIG nStereoBands; + PSENC_NENV_CONFIG maxEnvelopes; + FIXP_DBL iidQuantErrorThreshold; + +} PSENC_CONFIG, *HANDLE_PSENC_CONFIG; + +typedef struct T_PARAMETRIC_STEREO *HANDLE_PARAMETRIC_STEREO; + +/** + * \brief Create a parametric stereo encoder instance. + * + * \param phParametricStereo A pointer to a parametric stereo handle to be + * allocated. Initialized on return. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, PSENC_MEMORY_ERROR, on failure. + */ +FDK_PSENC_ERROR PSEnc_Create(HANDLE_PARAMETRIC_STEREO *phParametricStereo); + +/** + * \brief Initialize a parametric stereo encoder instance. + * + * \param hParametricStereo Meta Data handle. + * \param hPsEncConfig Filled parametric stereo configuration + * structure. + * \param noQmfSlots Number of slots within one audio frame. + * \param noQmfBands Number of QMF bands. + * \param dynamic_RAM Pointer to preallocated workbuffer. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, PSENC_INIT_ERROR, on failure. + */ +FDK_PSENC_ERROR PSEnc_Init(HANDLE_PARAMETRIC_STEREO hParametricStereo, + const HANDLE_PSENC_CONFIG hPsEncConfig, + INT noQmfSlots, INT noQmfBands, UCHAR *dynamic_RAM); + +/** + * \brief Destroy parametric stereo encoder instance. + * + * Deallocate instance and free whole memory. + * + * \param phParametricStereo Pointer to the parametric stereo handle to be + * deallocated. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, on failure. + */ +FDK_PSENC_ERROR PSEnc_Destroy(HANDLE_PARAMETRIC_STEREO *phParametricStereo); + +/** + * \brief Apply parametric stereo processing. + * + * \param hParametricStereo Meta Data handle. + * \param samples Pointer to 2 channel audio input signal. + * \param timeInStride, Stride factor of input buffer. + * \param hQmfAnalysis, Pointer to QMF analysis filterbanks. + * \param downmixedRealQmfData Pointer to real QMF buffer to be written to. + * \param downmixedImagQmfData Pointer to imag QMF buffer to be written to. + * \param downsampledOutSignal Pointer to buffer where to write downmixed + * timesignal. + * \param sbrSynthQmf Pointer to QMF synthesis filterbank. + * \param qmfScale Return scaling factor of the qmf data. + * \param sendHeader Signal whether to write header data. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, PSENC_ENCODE_ERROR, on failure. + */ +FDK_PSENC_ERROR FDKsbrEnc_PSEnc_ParametricStereoProcessing( + HANDLE_PARAMETRIC_STEREO hParametricStereo, INT_PCM *samples[2], + UINT timeInStride, QMF_FILTER_BANK **hQmfAnalysis, + FIXP_DBL **RESTRICT downmixedRealQmfData, + FIXP_DBL **RESTRICT downmixedImagQmfData, INT_PCM *downsampledOutSignal, + HANDLE_QMF_FILTER_BANK sbrSynthQmf, SCHAR *qmfScale, const int sendHeader); + +/** + * \brief Write parametric stereo bitstream. + * + * Write ps_data() element to bitstream and return number of written bits. + * Returns number of written bits only, if hBitstream == NULL. + * + * \param hParametricStereo Meta Data handle. + * \param hBitstream Bitstream buffer handle. + * + * \return + * - number of written bits. + */ +INT FDKsbrEnc_PSEnc_WritePSData(HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitstream); + +#endif /* PS_MAIN_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/resampler.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/resampler.cpp new file mode 100644 index 0000000000000..b1781a7a228c0 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/resampler.cpp @@ -0,0 +1,444 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief FDK resampler tool box:$Revision: 91655 $ + \author M. Werner +*/ + +#include "resampler.h" + +#include "genericStds.h" + +/**************************************************************************/ +/* BIQUAD Filter Specifications */ +/**************************************************************************/ + +#define B1 0 +#define B2 1 +#define A1 2 +#define A2 3 + +#define BQC(x) FL2FXCONST_SGL(x / 2) + +struct FILTER_PARAM { + const FIXP_SGL *coeffa; /*! SOS matrix One row/section. Scaled using BQC(). + Order of coefficients: B1,B2,A1,A2. B0=A0=1.0 */ + FIXP_DBL g; /*! overall gain */ + int Wc; /*! normalized passband bandwidth at input samplerate * 1000 */ + int noCoeffs; /*! number of filter coeffs */ + int delay; /*! delay in samples at input samplerate */ +}; + +#define BIQUAD_COEFSTEP 4 + +/** + *\brief Low Pass + Wc = 0,5, order 30, Stop Band -96dB. Wc criteria is "almost 0dB passband", not + the usual -3db gain point. [b,a]=cheby2(30,96,0.505) [sos,g]=tf2sos(b,a) + bandwidth 0.48 + */ +static const FIXP_SGL sos48[] = { + BQC(1.98941075681938), BQC(0.999999996890811), + BQC(0.863264527201963), BQC(0.189553799960663), + BQC(1.90733804822445), BQC(1.00000001736189), + BQC(0.836321575841691), BQC(0.203505809266564), + BQC(1.75616665495325), BQC(0.999999946079721), + BQC(0.784699225121588), BQC(0.230471265506986), + BQC(1.55727745512726), BQC(1.00000011737815), + BQC(0.712515423588351), BQC(0.268752723900498), + BQC(1.33407591943643), BQC(0.999999795953228), + BQC(0.625059117330989), BQC(0.316194685288965), + BQC(1.10689898412458), BQC(1.00000035057114), + BQC(0.52803514366398), BQC(0.370517843224669), + BQC(0.89060371078454), BQC(0.999999343962822), + BQC(0.426920462165257), BQC(0.429608200207746), + BQC(0.694438261209433), BQC(1.0000008629792), + BQC(0.326530699561716), BQC(0.491714450654174), + BQC(0.523237800935322), BQC(1.00000101349782), + BQC(0.230829556274851), BQC(0.555559034843281), + BQC(0.378631165929563), BQC(0.99998986482665), + BQC(0.142906422036095), BQC(0.620338874442411), + BQC(0.260786911308437), BQC(1.00003261460178), + BQC(0.0651008576256505), BQC(0.685759923926262), + BQC(0.168409429188098), BQC(0.999933049695828), + BQC(-0.000790067789975562), BQC(0.751905896602325), + BQC(0.100724533818628), BQC(1.00009472669872), + BQC(-0.0533772830257041), BQC(0.81930744384525), + BQC(0.0561434357867363), BQC(0.999911636304276), + BQC(-0.0913550299236405), BQC(0.88883625875915), + BQC(0.0341680678662057), BQC(1.00003667508676), + BQC(-0.113405185536697), BQC(0.961756638268446)}; + +static const FIXP_DBL g48 = + FL2FXCONST_DBL(0.002712866530047) - (FIXP_DBL)0x8000; + +static const struct FILTER_PARAM param_set48 = { + sos48, g48, 480, 15, 4 /* LF 2 */ +}; + +/** + *\brief Low Pass + Wc = 0,5, order 24, Stop Band -96dB. Wc criteria is "almost 0dB passband", not + the usual -3db gain point. [b,a]=cheby2(24,96,0.5) [sos,g]=tf2sos(b,a) + bandwidth 0.45 + */ +static const FIXP_SGL sos45[] = { + BQC(1.982962601444), BQC(1.00000000007504), BQC(0.646113303737836), + BQC(0.10851149979981), BQC(1.85334094281111), BQC(0.999999999677192), + BQC(0.612073220102006), BQC(0.130022141698044), BQC(1.62541051415425), + BQC(1.00000000080398), BQC(0.547879702855959), BQC(0.171165825133192), + BQC(1.34554656923247), BQC(0.9999999980169), BQC(0.460373914508491), + BQC(0.228677463376354), BQC(1.05656568503116), BQC(1.00000000569363), + BQC(0.357891894038287), BQC(0.298676843912185), BQC(0.787967587877312), + BQC(0.999999984415017), BQC(0.248826893211877), BQC(0.377441803512978), + BQC(0.555480971120497), BQC(1.00000003583307), BQC(0.140614263345315), + BQC(0.461979302213679), BQC(0.364986207070964), BQC(0.999999932084303), + BQC(0.0392669446074516), BQC(0.55033451180825), BQC(0.216827267631558), + BQC(1.00000010534682), BQC(-0.0506232228865103), BQC(0.641691581560946), + BQC(0.108951672277119), BQC(0.999999871167516), BQC(-0.125584840183225), + BQC(0.736367748771803), BQC(0.0387988607229035), BQC(1.00000011205574), + BQC(-0.182814849097974), BQC(0.835802108714964), BQC(0.0042866175809225), + BQC(0.999999954830813), BQC(-0.21965740617151), BQC(0.942623047782363)}; + +static const FIXP_DBL g45 = + FL2FXCONST_DBL(0.00242743980909524) - (FIXP_DBL)0x8000; + +static const struct FILTER_PARAM param_set45 = { + sos45, g45, 450, 12, 4 /* LF 2 */ +}; + +/* + Created by Octave 2.1.73, Mon Oct 13 17:31:32 2008 CEST + Wc = 0,5, order 16, Stop Band -96dB damping. + [b,a]=cheby2(16,96,0.5) + [sos,g]=tf2sos(b,a) + bandwidth = 0.41 + */ + +static const FIXP_SGL sos41[] = { + BQC(1.96193625292), BQC(0.999999999999964), BQC(0.169266178786789), + BQC(0.0128823300475907), BQC(1.68913437662092), BQC(1.00000000000053), + BQC(0.124751503206552), BQC(0.0537472273950989), BQC(1.27274692366017), + BQC(0.999999999995674), BQC(0.0433108625178357), BQC(0.131015753236317), + BQC(0.85214175088395), BQC(1.00000000001813), BQC(-0.0625658152550408), + BQC(0.237763778993806), BQC(0.503841579939009), BQC(0.999999999953223), + BQC(-0.179176128722865), BQC(0.367475236424474), BQC(0.249990711986162), + BQC(1.00000000007952), BQC(-0.294425165824676), BQC(0.516594857170212), + BQC(0.087971668680286), BQC(0.999999999915528), BQC(-0.398956566777928), + BQC(0.686417767801123), BQC(0.00965373325350294), BQC(1.00000000003744), + BQC(-0.48579173764817), BQC(0.884931534239068)}; + +static const FIXP_DBL g41 = FL2FXCONST_DBL(0.00155956951169248); + +static const struct FILTER_PARAM param_set41 = { + sos41, g41, 410, 8, 5 /* LF 3 */ +}; + +/* + # Created by Octave 2.1.73, Mon Oct 13 17:55:33 2008 CEST + Wc = 0,5, order 12, Stop Band -96dB damping. + [b,a]=cheby2(12,96,0.5); + [sos,g]=tf2sos(b,a) +*/ +static const FIXP_SGL sos35[] = { + BQC(1.93299325235762), BQC(0.999999999999985), BQC(-0.140733187246596), + BQC(0.0124139497836062), BQC(1.4890416764109), BQC(1.00000000000011), + BQC(-0.198215402588504), BQC(0.0746730616584138), BQC(0.918450161309795), + BQC(0.999999999999619), BQC(-0.30133912791941), BQC(0.192276468839529), + BQC(0.454877024246818), BQC(1.00000000000086), BQC(-0.432337328809815), + BQC(0.356852933642815), BQC(0.158017147118507), BQC(0.999999999998876), + BQC(-0.574817494249777), BQC(0.566380436970833), BQC(0.0171834649478749), + BQC(1.00000000000055), BQC(-0.718581178041165), BQC(0.83367484487889)}; + +static const FIXP_DBL g35 = FL2FXCONST_DBL(0.00162580994125131); + +static const struct FILTER_PARAM param_set35 = {sos35, g35, 350, 6, 4}; + +/* + # Created by Octave 2.1.73, Mon Oct 13 18:15:38 2008 CEST + Wc = 0,5, order 8, Stop Band -96dB damping. + [b,a]=cheby2(8,96,0.5); + [sos,g]=tf2sos(b,a) +*/ +static const FIXP_SGL sos25[] = { + BQC(1.85334094301225), BQC(1.0), + BQC(-0.702127214212663), BQC(0.132452403998767), + BQC(1.056565682167), BQC(0.999999999999997), + BQC(-0.789503667880785), BQC(0.236328693569128), + BQC(0.364986307455489), BQC(0.999999999999996), + BQC(-0.955191189843375), BQC(0.442966457936379), + BQC(0.0387985751642125), BQC(1.0), + BQC(-1.19817786088084), BQC(0.770493895456328)}; + +static const FIXP_DBL g25 = FL2FXCONST_DBL(0.000945182835294559); + +static const struct FILTER_PARAM param_set25 = {sos25, g25, 250, 4, 5}; + +/* Must be sorted in descending order */ +static const struct FILTER_PARAM *const filter_paramSet[] = { + ¶m_set48, ¶m_set45, ¶m_set41, ¶m_set35, ¶m_set25}; + +/**************************************************************************/ +/* Resampler Functions */ +/**************************************************************************/ + +/*! + \brief Reset downsampler instance and clear delay lines + + \return success of operation +*/ + +INT FDKaacEnc_InitDownsampler( + DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ + int Wc, /*!< normalized cutoff freq * 1000* */ + int ratio) /*!< downsampler ratio */ + +{ + UINT i; + const struct FILTER_PARAM *currentSet = NULL; + + FDKmemclear(DownSampler->downFilter.states, + sizeof(DownSampler->downFilter.states)); + DownSampler->downFilter.ptr = 0; + + /* + find applicable parameter set + */ + currentSet = filter_paramSet[0]; + for (i = 1; i < sizeof(filter_paramSet) / sizeof(struct FILTER_PARAM *); + i++) { + if (filter_paramSet[i]->Wc <= Wc) { + break; + } + currentSet = filter_paramSet[i]; + } + + DownSampler->downFilter.coeffa = currentSet->coeffa; + + DownSampler->downFilter.gain = currentSet->g; + FDK_ASSERT(currentSet->noCoeffs <= MAXNR_SECTIONS * 2); + + DownSampler->downFilter.noCoeffs = currentSet->noCoeffs; + DownSampler->delay = currentSet->delay; + DownSampler->downFilter.Wc = currentSet->Wc; + + DownSampler->ratio = ratio; + DownSampler->pending = ratio - 1; + return (1); +} + +/*! + \brief faster simple folding operation + Filter: + H(z) = A(z)/B(z) + with + A(z) = a[0]*z^0 + a[1]*z^1 + a[2]*z^2 ... a[n]*z^n + + \return filtered value +*/ + +static inline INT_PCM AdvanceFilter( + LP_FILTER *downFilter, /*!< pointer to iir filter instance */ + INT_PCM *pInput, /*!< input of filter */ + int downRatio) { + INT_PCM output; + int i, n; + +#define BIQUAD_SCALE 12 + + FIXP_DBL y = FL2FXCONST_DBL(0.0f); + FIXP_DBL input; + + for (n = 0; n < downRatio; n++) { + FIXP_BQS(*states)[2] = downFilter->states; + const FIXP_SGL *coeff = downFilter->coeffa; + int s1, s2; + + s1 = downFilter->ptr; + s2 = s1 ^ 1; + +#if (SAMPLE_BITS == 16) + input = ((FIXP_DBL)pInput[n]) << (DFRACT_BITS - SAMPLE_BITS - BIQUAD_SCALE); +#elif (SAMPLE_BITS == 32) + input = pInput[n] >> BIQUAD_SCALE; +#else +#error NOT IMPLEMENTED +#endif + + FIXP_BQS state1, state2, state1b, state2b; + + state1 = states[0][s1]; + state2 = states[0][s2]; + + /* Loop over sections */ + for (i = 0; i < downFilter->noCoeffs; i++) { + FIXP_DBL state0; + + /* Load merged states (from next section) */ + state1b = states[i + 1][s1]; + state2b = states[i + 1][s2]; + + state0 = input + fMult(state1, coeff[B1]) + fMult(state2, coeff[B2]); + y = state0 - fMult(state1b, coeff[A1]) - fMult(state2b, coeff[A2]); + + /* Store new feed forward merge state */ + states[i + 1][s2] = y << 1; + /* Store new feed backward state */ + states[i][s2] = input << 1; + + /* Feedback output to next section. */ + input = y; + + /* Transfer merged states */ + state1 = state1b; + state2 = state2b; + + /* Step to next coef set */ + coeff += BIQUAD_COEFSTEP; + } + downFilter->ptr ^= 1; + } + /* Apply global gain */ + y = fMult(y, downFilter->gain); + + /* Apply final gain/scaling to output */ +#if (SAMPLE_BITS == 16) + output = (INT_PCM)SATURATE_RIGHT_SHIFT( + y + (FIXP_DBL)(1 << (DFRACT_BITS - SAMPLE_BITS - BIQUAD_SCALE - 1)), + DFRACT_BITS - SAMPLE_BITS - BIQUAD_SCALE, SAMPLE_BITS); + // output = (INT_PCM) SATURATE_RIGHT_SHIFT(y, + // DFRACT_BITS-SAMPLE_BITS-BIQUAD_SCALE, SAMPLE_BITS); +#else + output = SATURATE_LEFT_SHIFT(y, BIQUAD_SCALE, SAMPLE_BITS); +#endif + + return output; +} + +/*! + \brief FDKaacEnc_Downsample numInSamples of type INT_PCM + Returns number of output samples in numOutSamples + + \return success of operation +*/ + +INT FDKaacEnc_Downsample( + DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ + INT_PCM *inSamples, /*!< pointer to input samples */ + INT numInSamples, /*!< number of input samples */ + INT_PCM *outSamples, /*!< pointer to output samples */ + INT *numOutSamples /*!< pointer tp number of output samples */ +) { + INT i; + *numOutSamples = 0; + + for (i = 0; i < numInSamples; i += DownSampler->ratio) { + *outSamples = AdvanceFilter(&(DownSampler->downFilter), &inSamples[i], + DownSampler->ratio); + outSamples++; + } + *numOutSamples = numInSamples / DownSampler->ratio; + + return 0; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/resampler.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/resampler.h new file mode 100644 index 0000000000000..7aa1cae61b9a9 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/resampler.h @@ -0,0 +1,159 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef RESAMPLER_H +#define RESAMPLER_H +/*! + \file + \brief Fixed Point Resampler Tool Box $Revision: 92790 $ +*/ + +#include "common_fix.h" + +/**************************************************************************/ +/* BIQUAD Filter Structure */ +/**************************************************************************/ + +#define MAXNR_SECTIONS (15) + +typedef FIXP_DBL FIXP_BQS; + +typedef struct { + FIXP_BQS states[MAXNR_SECTIONS + 1][2]; /*! state buffer */ + const FIXP_SGL *coeffa; /*! pointer to filter coeffs */ + FIXP_DBL gain; /*! overall gain factor */ + int Wc; /*! normalized cutoff freq * 1000 */ + int noCoeffs; /*! number of filter coeffs sets */ + int ptr; /*! index to rinbuffers */ +} LP_FILTER; + +/**************************************************************************/ +/* Downsampler Structure */ +/**************************************************************************/ + +typedef struct { + LP_FILTER downFilter; /*! filter instance */ + int ratio; /*! downsampling ration */ + int delay; /*! downsampling delay (source fs) */ + int pending; /*! number of pending output samples */ +} DOWNSAMPLER; + +/** + * \brief Initialized a given downsampler structure. + */ +INT FDKaacEnc_InitDownsampler( + DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ + INT Wc, /*!< normalized cutoff freq * 1000 */ + INT ratio); /*!< downsampler ratio */ + +/** + * \brief Downsample a set of audio samples. numInSamples must be at least equal + * to the downsampler ratio. + */ +INT FDKaacEnc_Downsample( + DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ + INT_PCM *inSamples, /*!< pointer to input samples */ + INT numInSamples, /*!< number of input samples */ + INT_PCM *outSamples, /*!< pointer to output samples */ + INT *numOutSamples); /*!< pointer tp number of output samples */ + +#endif /* RESAMPLER_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr.h new file mode 100644 index 0000000000000..341dcabca62aa --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr.h @@ -0,0 +1,194 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Main SBR structs definitions $Revision: 92790 $ +*/ + +#ifndef SBR_H +#define SBR_H + +#include "fram_gen.h" +#include "bit_sbr.h" +#include "tran_det.h" +#include "code_env.h" +#include "env_est.h" +#include "cmondata.h" + +#include "qmf.h" +#include "resampler.h" + +#include "ton_corr.h" + +/* SBR bitstream delay */ +#define MAX_DELAY_FRAMES 2 + +/* sbr encoder downsampling type */ +typedef enum { SBRENC_DS_NONE, SBRENC_DS_TIME, SBRENC_DS_QMF } SBRENC_DS_TYPE; + +typedef struct SBR_CHANNEL { + struct ENV_CHANNEL hEnvChannel; + // INT_PCM *pDSOutBuffer; /**< Pointer to + // downsampled audio output of SBR encoder */ + DOWNSAMPLER downSampler; + +} SBR_CHANNEL; +typedef SBR_CHANNEL* HANDLE_SBR_CHANNEL; + +typedef struct SBR_ELEMENT { + HANDLE_SBR_CHANNEL sbrChannel[2]; + QMF_FILTER_BANK* hQmfAnalysis[2]; + SBR_CONFIG_DATA sbrConfigData; + SBR_HEADER_DATA sbrHeaderData; + SBR_BITSTREAM_DATA sbrBitstreamData; + COMMON_DATA CmonData; + INT dynXOverFreqDelay[5]; /**< to delay a frame (I don't like it that much + that way - hrc) */ + SBR_ELEMENT_INFO elInfo; + + UCHAR payloadDelayLine[1 + MAX_DELAY_FRAMES][MAX_PAYLOAD_SIZE]; + UINT payloadDelayLineSize[1 + MAX_DELAY_FRAMES]; /* Sizes in bits */ + +} SBR_ELEMENT, *HANDLE_SBR_ELEMENT; + +typedef struct SBR_ENCODER { + HANDLE_SBR_ELEMENT sbrElement[(8)]; + HANDLE_SBR_CHANNEL pSbrChannel[(8)]; + QMF_FILTER_BANK QmfAnalysis[(8)]; + DOWNSAMPLER lfeDownSampler; + int lfeChIdx; /* -1 default for no lfe, else assign channel index. */ + int noElements; /* Number of elements. */ + int nChannels; /* Total channel count across all elements. */ + int frameSize; /* SBR framelength. */ + int bufferOffset; /* Offset for SBR parameter extraction in time domain input + buffer. */ + int downsampledOffset; /* Offset of downsampled/mixed output for core encoder. + */ + int downmixSize; /* Size in samples of downsampled/mixed output for core + encoder. */ + INT downSampleFactor; /* Sampling rate relation between the SBR and the core + encoder. */ + SBRENC_DS_TYPE + downsamplingMethod; /* Method of downsmapling, time-domain, QMF or none. + */ + int nBitstrDelay; /* Amount of SBR frames to be delayed in bitstream domain. + */ + int sbrDecDelay; /* SBR decoder delay in samples */ + INT estimateBitrate; /* Estimate bitrate of SBR encoder. */ + INT inputDataDelay; /* Delay caused by downsampler, in/out buffer at + sbrEncoder_EncodeFrame. */ + + UCHAR* dynamicRam; + UCHAR* pSBRdynamic_RAM; + + HANDLE_PARAMETRIC_STEREO hParametricStereo; + QMF_FILTER_BANK qmfSynthesisPS; + + /* parameters describing allocation volume of present instance */ + INT maxElements; + INT maxChannels; + INT supportPS; + +} SBR_ENCODER; + +#endif /* SBR_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_def.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_def.h new file mode 100644 index 0000000000000..53eba71ec5823 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_def.h @@ -0,0 +1,276 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief SBR main definitions $Revision: 92790 $ +*/ +#ifndef SBR_DEF_H +#define SBR_DEF_H + +#include "common_fix.h" + +#define noError 0 +#define HANDLE_ERROR_INFO INT +#define ERROR(a, b) 1 + +/* #define SBR_ENV_STATISTICS_BITRATE */ +#undef SBR_ENV_STATISTICS_BITRATE + +/* #define SBR_ENV_STATISTICS */ +#undef SBR_ENV_STATISTICS + +/* #define SBR_PAYLOAD_MONITOR */ +#undef SBR_PAYLOAD_MONITOR + +#define SWAP(a, b) tempr = a, a = b, b = tempr +#define TRUE 1 +#define FALSE 0 + +/* Constants */ +#define EPS 1e-12 +#define LOG2 0.69314718056f /* natural logarithm of 2 */ +#define ILOG2 1.442695041f /* 1/LOG2 */ +#define RELAXATION_FLOAT (1e-6f) +#define RELAXATION (FL2FXCONST_DBL(RELAXATION_FLOAT)) +#define RELAXATION_FRACT \ + (FL2FXCONST_DBL(0.524288f)) /* 0.524288f is fractional part of RELAXATION */ +#define RELAXATION_SHIFT (19) +#define RELAXATION_LD64 \ + (FL2FXCONST_DBL(0.31143075889f)) /* (ld64(RELAXATION) \ + */ + +/************ Definitions ***************/ +#define SBR_COMP_MODE_DELTA 0 +#define SBR_COMP_MODE_CTS 1 +#define SBR_MAX_ENERGY_VALUES 5 +#define SBR_GLOBAL_TONALITY_VALUES 2 + +#define MAX_NUM_CHANNELS 2 + +#define MAX_NOISE_ENVELOPES 2 +#define MAX_NUM_NOISE_COEFFS 5 +#define MAX_NUM_NOISE_VALUES (MAX_NUM_NOISE_COEFFS * MAX_NOISE_ENVELOPES) + +#define MAX_NUM_ENVELOPE_VALUES (MAX_ENVELOPES * MAX_FREQ_COEFFS) +#define MAX_ENVELOPES 5 +#define MAX_FREQ_COEFFS 48 + +#define MAX_FREQ_COEFFS_FS44100 35 +#define MAX_FREQ_COEFFS_FS48000 32 + +#define NO_OF_ESTIMATES_LC 4 +#define NO_OF_ESTIMATES_LD 3 +#define MAX_NO_OF_ESTIMATES 4 + +#define NOISE_FLOOR_OFFSET 6 +#define NOISE_FLOOR_OFFSET_64 (FL2FXCONST_DBL(0.09375f)) + +#define LOW_RES 0 +#define HIGH_RES 1 + +#define LO 0 +#define HI 1 + +#define LENGTH_SBR_FRAME_INFO 35 /* 19 */ + +#define SBR_NSFB_LOW_RES 9 /* 8 */ +#define SBR_NSFB_HIGH_RES 18 /* 16 */ + +#define SBR_XPOS_CTRL_DEFAULT 2 + +#define SBR_FREQ_SCALE_DEFAULT 2 +#define SBR_ALTER_SCALE_DEFAULT 1 +#define SBR_NOISE_BANDS_DEFAULT 2 + +#define SBR_LIMITER_BANDS_DEFAULT 2 +#define SBR_LIMITER_GAINS_DEFAULT 2 +#define SBR_LIMITER_GAINS_INFINITE 3 +#define SBR_INTERPOL_FREQ_DEFAULT 1 +#define SBR_SMOOTHING_LENGTH_DEFAULT 0 + +/* sbr_header */ +#define SI_SBR_AMP_RES_BITS 1 +#define SI_SBR_COUPLING_BITS 1 +#define SI_SBR_START_FREQ_BITS 4 +#define SI_SBR_STOP_FREQ_BITS 4 +#define SI_SBR_XOVER_BAND_BITS 3 +#define SI_SBR_RESERVED_BITS 2 +#define SI_SBR_DATA_EXTRA_BITS 1 +#define SI_SBR_HEADER_EXTRA_1_BITS 1 +#define SI_SBR_HEADER_EXTRA_2_BITS 1 + +/* sbr_header extra 1 */ +#define SI_SBR_FREQ_SCALE_BITS 2 +#define SI_SBR_ALTER_SCALE_BITS 1 +#define SI_SBR_NOISE_BANDS_BITS 2 + +/* sbr_header extra 2 */ +#define SI_SBR_LIMITER_BANDS_BITS 2 +#define SI_SBR_LIMITER_GAINS_BITS 2 +#define SI_SBR_INTERPOL_FREQ_BITS 1 +#define SI_SBR_SMOOTHING_LENGTH_BITS 1 + +/* sbr_grid */ +#define SBR_CLA_BITS 2 /*!< size of bs_frame_class */ +#define SBR_CLA_BITS_LD 1 /*!< size of bs_frame_class */ +#define SBR_ENV_BITS 2 /*!< size of bs_num_env_raw */ +#define SBR_ABS_BITS 2 /*!< size of bs_abs_bord_raw for HE-AAC */ +#define SBR_NUM_BITS 2 /*!< size of bs_num_rel */ +#define SBR_REL_BITS 2 /*!< size of bs_rel_bord_raw */ +#define SBR_RES_BITS 1 /*!< size of bs_freq_res_flag */ +#define SBR_DIR_BITS 1 /*!< size of bs_df_flag */ + +/* sbr_data */ +#define SI_SBR_INVF_MODE_BITS 2 + +#define SI_SBR_START_ENV_BITS_AMP_RES_3_0 6 +#define SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_3_0 5 +#define SI_SBR_START_NOISE_BITS_AMP_RES_3_0 5 +#define SI_SBR_START_NOISE_BITS_BALANCE_AMP_RES_3_0 5 + +#define SI_SBR_START_ENV_BITS_AMP_RES_1_5 7 +#define SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_1_5 6 + +#define SI_SBR_EXTENDED_DATA_BITS 1 +#define SI_SBR_EXTENSION_SIZE_BITS 4 +#define SI_SBR_EXTENSION_ESC_COUNT_BITS 8 +#define SI_SBR_EXTENSION_ID_BITS 2 + +#define SBR_EXTENDED_DATA_MAX_CNT (15 + 255) + +#define EXTENSION_ID_PS_CODING 2 + +/* Envelope coding constants */ +#define FREQ 0 +#define TIME 1 + +/* qmf data scaling */ +#define QMF_SCALE_OFFSET 7 + +/* huffman tables */ +#define CODE_BOOK_SCF_LAV00 60 +#define CODE_BOOK_SCF_LAV01 31 +#define CODE_BOOK_SCF_LAV10 60 +#define CODE_BOOK_SCF_LAV11 31 +#define CODE_BOOK_SCF_LAV_BALANCE11 12 +#define CODE_BOOK_SCF_LAV_BALANCE10 24 + +typedef enum { SBR_AMP_RES_1_5 = 0, SBR_AMP_RES_3_0 } AMP_RES; + +typedef enum { + XPOS_MDCT, + XPOS_MDCT_CROSS, + XPOS_LC, + XPOS_RESERVED, + XPOS_SWITCHED /* not a real choice but used here to control behaviour */ +} XPOS_MODE; + +typedef enum { + INVF_OFF = 0, + INVF_LOW_LEVEL, + INVF_MID_LEVEL, + INVF_HIGH_LEVEL, + INVF_SWITCHED /* not a real choice but used here to control behaviour */ +} INVF_MODE; + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_encoder.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_encoder.cpp new file mode 100644 index 0000000000000..c3da072862f8b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_encoder.cpp @@ -0,0 +1,2576 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): Andreas Ehret, Tobias Chalupka + + Description: SBR encoder top level processing. + +*******************************************************************************/ + +#include "sbr_encoder.h" + +#include "sbrenc_ram.h" +#include "sbrenc_rom.h" +#include "sbrenc_freq_sca.h" +#include "env_bit.h" +#include "cmondata.h" +#include "sbr_misc.h" +#include "sbr.h" +#include "qmf.h" + +#include "ps_main.h" + +#define SBRENCODER_LIB_VL0 4 +#define SBRENCODER_LIB_VL1 0 +#define SBRENCODER_LIB_VL2 0 + +/***************************************************************************/ +/* + * SBR Delay balancing definitions. + */ + +/* + input buffer (1ch) + + |------------ 1537 -------------|-----|---------- 2048 -------------| + (core2sbr delay ) ds (read, core and ds area) +*/ + +#define SFB(dwnsmp) \ + (32 << (dwnsmp - \ + 1)) /* SBR Frequency bands: 64 for dual-rate, 32 for single-rate */ +#define STS(fl) \ + (((fl) == 1024) ? 32 \ + : 30) /* SBR Time Slots: 32 for core frame length 1024, 30 \ + for core frame length 960 */ + +#define DELAY_QMF_ANA(dwnsmp) \ + ((320 << ((dwnsmp)-1)) - (32 << ((dwnsmp)-1))) /* Full bandwidth */ +#define DELAY_HYB_ANA (10 * 64) /* + 0.5 */ /* */ +#define DELAY_HYB_SYN (6 * 64 - 32) /* */ +#define DELAY_QMF_POSTPROC(dwnsmp) \ + (32 * (dwnsmp)) /* QMF postprocessing delay */ +#define DELAY_DEC_QMF(dwnsmp) (6 * SFB(dwnsmp)) /* Decoder QMF overlap */ +#define DELAY_QMF_SYN(dwnsmp) \ + (1 << (dwnsmp - \ + 1)) /* QMF_NO_POLY/2=2.5, rounded down to 2, half for single-rate */ +#define DELAY_QMF_DS (32) /* QMF synthesis for downsampled time signal */ + +/* Delay in QMF paths */ +#define DELAY_SBR(fl, dwnsmp) \ + (DELAY_QMF_ANA(dwnsmp) + (SFB(dwnsmp) * STS(fl) - 1) + DELAY_QMF_SYN(dwnsmp)) +#define DELAY_PS(fl, dwnsmp) \ + (DELAY_QMF_ANA(dwnsmp) + DELAY_HYB_ANA + DELAY_DEC_QMF(dwnsmp) + \ + (SFB(dwnsmp) * STS(fl) - 1) + DELAY_HYB_SYN + DELAY_QMF_SYN(dwnsmp)) +#define DELAY_ELDSBR(fl, dwnsmp) \ + ((((fl) / 2) * (dwnsmp)) - 1 + DELAY_QMF_POSTPROC(dwnsmp)) +#define DELAY_ELDv2SBR(fl, dwnsmp) \ + ((((fl) / 2) * (dwnsmp)) - 1 + 80 * (dwnsmp)) /* 80 is the delay caused \ + by the sum of the CLD \ + analysis and the MPSLD \ + synthesis filterbank */ + +/* Delay in core path (core and downsampler not taken into account) */ +#define DELAY_COREPATH_SBR(fl, dwnsmp) \ + ((DELAY_QMF_ANA(dwnsmp) + DELAY_DEC_QMF(dwnsmp) + DELAY_QMF_SYN(dwnsmp))) +#define DELAY_COREPATH_ELDSBR(fl, dwnsmp) ((DELAY_QMF_POSTPROC(dwnsmp))) +#define DELAY_COREPATH_ELDv2SBR(fl, dwnsmp) (128 * (dwnsmp)) /* 4 slots */ +#define DELAY_COREPATH_PS(fl, dwnsmp) \ + ((DELAY_QMF_ANA(dwnsmp) + DELAY_QMF_DS + \ + /*(DELAY_AAC(fl)*2) + */ DELAY_QMF_ANA(dwnsmp) + DELAY_DEC_QMF(dwnsmp) + \ + DELAY_HYB_SYN + DELAY_QMF_SYN(dwnsmp))) /* 2048 - 463*2 */ + +/* Delay differences between SBR- and downsampled path for SBR and SBR+PS */ +#define DELAY_AAC2SBR(fl, dwnsmp) \ + ((DELAY_COREPATH_SBR(fl, dwnsmp)) - DELAY_SBR((fl), (dwnsmp))) +#define DELAY_ELD2SBR(fl, dwnsmp) \ + ((DELAY_COREPATH_ELDSBR(fl, dwnsmp)) - DELAY_ELDSBR(fl, dwnsmp)) +#define DELAY_AAC2PS(fl, dwnsmp) \ + ((DELAY_COREPATH_PS(fl, dwnsmp)) - DELAY_PS(fl, dwnsmp)) /* 2048 - 463*2 */ + +/* Assumption: The sample delay resulting of of DELAY_AAC2PS is always smaller + * than the sample delay implied by DELAY_AAC2SBR */ +#define MAX_DS_FILTER_DELAY \ + (5) /* the additional max downsampler filter delay (source fs) */ +#define MAX_SAMPLE_DELAY \ + (DELAY_AAC2SBR(1024, 2) + MAX_DS_FILTER_DELAY) /* maximum delay: frame \ + length of 1024 and \ + dual-rate sbr */ + +/***************************************************************************/ + +/*************** Delay parameters for sbrEncoder_Init_delay() **************/ +typedef struct { + int dsDelay; /* the delay of the (time-domain) downsampler itself */ + int delay; /* overall delay / samples */ + int sbrDecDelay; /* SBR decoder's delay */ + int corePathOffset; /* core path offset / samples; added by + sbrEncoder_Init_delay() */ + int sbrPathOffset; /* SBR path offset / samples; added by + sbrEncoder_Init_delay() */ + int bitstrDelay; /* bitstream delay / frames; added by sbrEncoder_Init_delay() + */ + int delayInput2Core; /* delay of the input to the core / samples */ +} DELAY_PARAM; +/***************************************************************************/ + +#define INVALID_TABLE_IDX -1 + +/***************************************************************************/ +/*! + + \brief Selects the SBR tuning settings to use dependent on number of + channels, bitrate, sample rate and core coder + + \return Index to the appropriate table + +****************************************************************************/ +#define DISTANCE_CEIL_VALUE 5000000 +static INT getSbrTuningTableIndex( + UINT bitrate, /*! the total bitrate in bits/sec */ + UINT numChannels, /*! the number of channels for the core coder */ + UINT sampleRate, /*! the sampling rate of the core coder */ + AUDIO_OBJECT_TYPE core, UINT *pBitRateClosest) { + int i, bitRateClosestLowerIndex = -1, bitRateClosestUpperIndex = -1, + found = 0; + UINT bitRateClosestUpper = 0, bitRateClosestLower = DISTANCE_CEIL_VALUE; + +#define isForThisCore(i) \ + ((sbrTuningTable[i].coreCoder == CODEC_AACLD && core == AOT_ER_AAC_ELD) || \ + (sbrTuningTable[i].coreCoder == CODEC_AAC && core != AOT_ER_AAC_ELD)) + + for (i = 0; i < sbrTuningTableSize; i++) { + if (isForThisCore(i)) /* tuning table is for this core codec */ + { + if (numChannels == sbrTuningTable[i].numChannels && + sampleRate == sbrTuningTable[i].sampleRate) { + found = 1; + if ((bitrate >= sbrTuningTable[i].bitrateFrom) && + (bitrate < sbrTuningTable[i].bitrateTo)) { + return i; + } else { + if (sbrTuningTable[i].bitrateFrom > bitrate) { + if (sbrTuningTable[i].bitrateFrom < bitRateClosestLower) { + bitRateClosestLower = sbrTuningTable[i].bitrateFrom; + bitRateClosestLowerIndex = i; + } + } + if (sbrTuningTable[i].bitrateTo <= bitrate) { + if (sbrTuningTable[i].bitrateTo > bitRateClosestUpper) { + bitRateClosestUpper = sbrTuningTable[i].bitrateTo - 1; + bitRateClosestUpperIndex = i; + } + } + } + } + } + } + + if (bitRateClosestUpperIndex >= 0) { + return bitRateClosestUpperIndex; + } + + if (pBitRateClosest != NULL) { + /* If there was at least one matching tuning entry pick the least distance + * bit rate */ + if (found) { + int distanceUpper = DISTANCE_CEIL_VALUE, + distanceLower = DISTANCE_CEIL_VALUE; + if (bitRateClosestLowerIndex >= 0) { + distanceLower = + sbrTuningTable[bitRateClosestLowerIndex].bitrateFrom - bitrate; + } + if (bitRateClosestUpperIndex >= 0) { + distanceUpper = + bitrate - sbrTuningTable[bitRateClosestUpperIndex].bitrateTo; + } + if (distanceUpper < distanceLower) { + *pBitRateClosest = bitRateClosestUpper; + } else { + *pBitRateClosest = bitRateClosestLower; + } + } else { + *pBitRateClosest = 0; + } + } + + return INVALID_TABLE_IDX; +} + +/***************************************************************************/ +/*! + + \brief Selects the PS tuning settings to use dependent on bitrate + and core coder + + \return Index to the appropriate table + +****************************************************************************/ +static INT getPsTuningTableIndex(UINT bitrate, UINT *pBitRateClosest) { + INT i, paramSets = sizeof(psTuningTable) / sizeof(psTuningTable[0]); + int bitRateClosestLowerIndex = -1, bitRateClosestUpperIndex = -1; + UINT bitRateClosestUpper = 0, bitRateClosestLower = DISTANCE_CEIL_VALUE; + + for (i = 0; i < paramSets; i++) { + if ((bitrate >= psTuningTable[i].bitrateFrom) && + (bitrate < psTuningTable[i].bitrateTo)) { + return i; + } else { + if (psTuningTable[i].bitrateFrom > bitrate) { + if (psTuningTable[i].bitrateFrom < bitRateClosestLower) { + bitRateClosestLower = psTuningTable[i].bitrateFrom; + bitRateClosestLowerIndex = i; + } + } + if (psTuningTable[i].bitrateTo <= bitrate) { + if (psTuningTable[i].bitrateTo > bitRateClosestUpper) { + bitRateClosestUpper = psTuningTable[i].bitrateTo - 1; + bitRateClosestUpperIndex = i; + } + } + } + } + + if (bitRateClosestUpperIndex >= 0) { + return bitRateClosestUpperIndex; + } + + if (pBitRateClosest != NULL) { + int distanceUpper = DISTANCE_CEIL_VALUE, + distanceLower = DISTANCE_CEIL_VALUE; + if (bitRateClosestLowerIndex >= 0) { + distanceLower = + sbrTuningTable[bitRateClosestLowerIndex].bitrateFrom - bitrate; + } + if (bitRateClosestUpperIndex >= 0) { + distanceUpper = + bitrate - sbrTuningTable[bitRateClosestUpperIndex].bitrateTo; + } + if (distanceUpper < distanceLower) { + *pBitRateClosest = bitRateClosestUpper; + } else { + *pBitRateClosest = bitRateClosestLower; + } + } + + return INVALID_TABLE_IDX; +} + +/***************************************************************************/ +/*! + + \brief In case of downsampled SBR we may need to lower the stop freq + of a tuning setting to fit into the lower half of the + spectrum ( which is sampleRate/4 ) + + \return the adapted stop frequency index (-1 -> error) + + \ingroup SbrEncCfg + +****************************************************************************/ +static INT FDKsbrEnc_GetDownsampledStopFreq(const INT sampleRateCore, + const INT startFreq, INT stopFreq, + const INT downSampleFactor) { + INT maxStopFreqRaw = sampleRateCore / 2; + INT startBand, stopBand; + HANDLE_ERROR_INFO err; + + while (stopFreq > 0 && FDKsbrEnc_getSbrStopFreqRAW(stopFreq, sampleRateCore) > + maxStopFreqRaw) { + stopFreq--; + } + + if (FDKsbrEnc_getSbrStopFreqRAW(stopFreq, sampleRateCore) > maxStopFreqRaw) + return -1; + + err = FDKsbrEnc_FindStartAndStopBand( + sampleRateCore << (downSampleFactor - 1), sampleRateCore, + 32 << (downSampleFactor - 1), startFreq, stopFreq, &startBand, &stopBand); + if (err) return -1; + + return stopFreq; +} + +/***************************************************************************/ +/*! + + \brief tells us, if for the given coreCoder, bitrate, number of channels + and input sampling rate an SBR setting is available. If yes, it + tells us also the core sampling rate we would need to run with + + \return a flag indicating success: yes (1) or no (0) + +****************************************************************************/ +static UINT FDKsbrEnc_IsSbrSettingAvail( + UINT bitrate, /*! the total bitrate in bits/sec */ + UINT vbrMode, /*! the vbr paramter, 0 means constant bitrate */ + UINT numOutputChannels, /*! the number of channels for the core coder */ + UINT sampleRateInput, /*! the input sample rate [in Hz] */ + UINT sampleRateCore, /*! the core's sampling rate */ + AUDIO_OBJECT_TYPE core) { + INT idx = INVALID_TABLE_IDX; + + if (sampleRateInput < 16000) return 0; + + if (bitrate == 0) { + /* map vbr quality to bitrate */ + if (vbrMode < 30) + bitrate = 24000; + else if (vbrMode < 40) + bitrate = 28000; + else if (vbrMode < 60) + bitrate = 32000; + else if (vbrMode < 75) + bitrate = 40000; + else + bitrate = 48000; + bitrate *= numOutputChannels; + } + + idx = getSbrTuningTableIndex(bitrate, numOutputChannels, sampleRateCore, core, + NULL); + + return (idx == INVALID_TABLE_IDX ? 0 : 1); +} + +/***************************************************************************/ +/*! + + \brief Adjusts the SBR settings according to the chosen core coder + settings which are accessible via config->codecSettings + + \return A flag indicating success: yes (1) or no (0) + +****************************************************************************/ +static UINT FDKsbrEnc_AdjustSbrSettings( + const sbrConfigurationPtr config, /*! output, modified */ + UINT bitRate, /*! the total bitrate in bits/sec */ + UINT numChannels, /*! the core coder number of channels */ + UINT sampleRateCore, /*! the core coder sampling rate in Hz */ + UINT sampleRateSbr, /*! the sbr coder sampling rate in Hz */ + UINT transFac, /*! the short block to long block ratio */ + UINT standardBitrate, /*! the standard bitrate per channel in bits/sec */ + UINT vbrMode, /*! the vbr paramter, 0 poor quality .. 100 high quality*/ + UINT useSpeechConfig, /*!< adapt tuning parameters for speech ? */ + UINT lcsMode, /*! the low complexity stereo mode */ + UINT bParametricStereo, /*!< use parametric stereo */ + AUDIO_OBJECT_TYPE core) /* Core audio codec object type */ +{ + INT idx = INVALID_TABLE_IDX; + /* set the core codec settings */ + config->codecSettings.bitRate = bitRate; + config->codecSettings.nChannels = numChannels; + config->codecSettings.sampleFreq = sampleRateCore; + config->codecSettings.transFac = transFac; + config->codecSettings.standardBitrate = standardBitrate; + + if (bitRate < 28000) { + config->threshold_AmpRes_FF_m = (FIXP_DBL)MAXVAL_DBL; + config->threshold_AmpRes_FF_e = 7; + } else if (bitRate >= 28000 && bitRate <= 48000) { + /* The float threshold is 75 + 0.524288f is fractional part of RELAXATION, the quotaMatrix and therefore + tonality are scaled by this 2/3 is because the original implementation + divides the tonality values by 3, here it's divided by 2 128 compensates + the necessary shiftfactor of 7 */ + config->threshold_AmpRes_FF_m = + FL2FXCONST_DBL(75.0f * 0.524288f / (2.0f / 3.0f) / 128.0f); + config->threshold_AmpRes_FF_e = 7; + } else if (bitRate > 48000) { + config->threshold_AmpRes_FF_m = FL2FXCONST_DBL(0); + config->threshold_AmpRes_FF_e = 0; + } + + if (bitRate == 0) { + /* map vbr quality to bitrate */ + if (vbrMode < 30) + bitRate = 24000; + else if (vbrMode < 40) + bitRate = 28000; + else if (vbrMode < 60) + bitRate = 32000; + else if (vbrMode < 75) + bitRate = 40000; + else + bitRate = 48000; + bitRate *= numChannels; + /* fix to enable mono vbrMode<40 @ 44.1 of 48kHz */ + if (numChannels == 1) { + if (sampleRateSbr == 44100 || sampleRateSbr == 48000) { + if (vbrMode < 40) bitRate = 32000; + } + } + } + + idx = + getSbrTuningTableIndex(bitRate, numChannels, sampleRateCore, core, NULL); + + if (idx != INVALID_TABLE_IDX) { + config->startFreq = sbrTuningTable[idx].startFreq; + config->stopFreq = sbrTuningTable[idx].stopFreq; + if (useSpeechConfig) { + config->startFreq = sbrTuningTable[idx].startFreqSpeech; + config->stopFreq = sbrTuningTable[idx].stopFreqSpeech; + } + + /* Adapt stop frequency in case of downsampled SBR - only 32 bands then */ + if (1 == config->downSampleFactor) { + INT dsStopFreq = FDKsbrEnc_GetDownsampledStopFreq( + sampleRateCore, config->startFreq, config->stopFreq, + config->downSampleFactor); + if (dsStopFreq < 0) { + return 0; + } + + config->stopFreq = dsStopFreq; + } + + config->sbr_noise_bands = sbrTuningTable[idx].numNoiseBands; + if (core == AOT_ER_AAC_ELD) config->init_amp_res_FF = SBR_AMP_RES_1_5; + config->noiseFloorOffset = sbrTuningTable[idx].noiseFloorOffset; + + config->ana_max_level = sbrTuningTable[idx].noiseMaxLevel; + config->stereoMode = sbrTuningTable[idx].stereoMode; + config->freqScale = sbrTuningTable[idx].freqScale; + + if (numChannels == 1) { + /* stereo case */ + switch (core) { + case AOT_AAC_LC: + if (bitRate <= (useSpeechConfig ? 24000U : 20000U)) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency + resolution for + non-split frames */ + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency + resolution for split + frames */ + } + break; + case AOT_ER_AAC_ELD: + if (bitRate < 36000) + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency + resolution for split + frames */ + if (bitRate < 26000) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency + resolution for + non-split frames */ + config->fResTransIsLow = + 1; /* for transient frames, set low frequency resolution */ + } + break; + default: + break; + } + } else { + /* stereo case */ + switch (core) { + case AOT_AAC_LC: + if (bitRate <= 28000) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency + resolution for + non-split frames */ + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency + resolution for split + frames */ + } + break; + case AOT_ER_AAC_ELD: + if (bitRate < 72000) { + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency + resolution for split + frames */ + } + if (bitRate < 52000) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency + resolution for + non-split frames */ + config->fResTransIsLow = + 1; /* for transient frames, set low frequency resolution */ + } + break; + default: + break; + } + if (bitRate <= 28000) { + /* + additionally restrict frequency resolution in FIXFIX frames + to further reduce SBR payload size */ + config->freq_res_fixfix[0] = FREQ_RES_LOW; + config->freq_res_fixfix[1] = FREQ_RES_LOW; + } + } + + /* adjust usage of parametric coding dependent on bitrate and speech config + * flag */ + if (useSpeechConfig) config->parametricCoding = 0; + + if (core == AOT_ER_AAC_ELD) { + if (bitRate < 28000) config->init_amp_res_FF = SBR_AMP_RES_3_0; + config->SendHeaderDataTime = -1; + } + + if (numChannels == 1) { + if (bitRate < 16000) { + config->parametricCoding = 0; + } + } else { + if (bitRate < 20000) { + config->parametricCoding = 0; + } + } + + config->useSpeechConfig = useSpeechConfig; + + /* PS settings */ + config->bParametricStereo = bParametricStereo; + + return 1; + } else { + return 0; + } +} + +/***************************************************************************** + + functionname: FDKsbrEnc_InitializeSbrDefaults + description: initializes the SBR configuration + returns: error status + input: - core codec type, + - factor of SBR to core frame length, + - core frame length + output: initialized SBR configuration + +*****************************************************************************/ +static UINT FDKsbrEnc_InitializeSbrDefaults(sbrConfigurationPtr config, + INT downSampleFactor, + UINT codecGranuleLen, + const INT isLowDelay) { + if ((downSampleFactor < 1 || downSampleFactor > 2) || + (codecGranuleLen * downSampleFactor > 64 * 32)) + return (0); /* error */ + + config->SendHeaderDataTime = 1000; + config->useWaveCoding = 0; + config->crcSbr = 0; + config->dynBwSupported = 1; + if (isLowDelay) + config->tran_thr = 6000; + else + config->tran_thr = 13000; + + config->parametricCoding = 1; + + config->sbrFrameSize = codecGranuleLen * downSampleFactor; + config->downSampleFactor = downSampleFactor; + + /* sbr default parameters */ + config->sbr_data_extra = 0; + config->amp_res = SBR_AMP_RES_3_0; + config->tran_fc = 0; + config->tran_det_mode = 1; + config->spread = 1; + config->stat = 0; + config->e = 1; + config->deltaTAcrossFrames = 1; + config->dF_edge_1stEnv = FL2FXCONST_DBL(0.3f); + config->dF_edge_incr = FL2FXCONST_DBL(0.3f); + + config->sbr_invf_mode = INVF_SWITCHED; + config->sbr_xpos_mode = XPOS_LC; + config->sbr_xpos_ctrl = SBR_XPOS_CTRL_DEFAULT; + config->sbr_xpos_level = 0; + config->useSaPan = 0; + config->dynBwEnabled = 0; + + /* the following parameters are overwritten by the + FDKsbrEnc_AdjustSbrSettings() function since they are included in the + tuning table */ + config->stereoMode = SBR_SWITCH_LRC; + config->ana_max_level = 6; + config->noiseFloorOffset = 0; + config->startFreq = 5; /* 5.9 respectively 6.0 kHz at fs = 44.1/48 kHz */ + config->stopFreq = 9; /* 16.2 respectively 16.8 kHz at fs = 44.1/48 kHz */ + config->freq_res_fixfix[0] = FREQ_RES_HIGH; /* non-split case */ + config->freq_res_fixfix[1] = FREQ_RES_HIGH; /* split case */ + config->fResTransIsLow = 0; /* for transient frames, set variable frequency + resolution according to freqResTable */ + + /* header_extra_1 */ + config->freqScale = SBR_FREQ_SCALE_DEFAULT; + config->alterScale = SBR_ALTER_SCALE_DEFAULT; + config->sbr_noise_bands = SBR_NOISE_BANDS_DEFAULT; + + /* header_extra_2 */ + config->sbr_limiter_bands = SBR_LIMITER_BANDS_DEFAULT; + config->sbr_limiter_gains = SBR_LIMITER_GAINS_DEFAULT; + config->sbr_interpol_freq = SBR_INTERPOL_FREQ_DEFAULT; + config->sbr_smoothing_length = SBR_SMOOTHING_LENGTH_DEFAULT; + + return 1; +} + +/***************************************************************************** + + functionname: DeleteEnvChannel + description: frees memory of one SBR channel + returns: - + input: handle of channel + output: released handle + +*****************************************************************************/ +static void deleteEnvChannel(HANDLE_ENV_CHANNEL hEnvCut) { + if (hEnvCut) { + FDKsbrEnc_DeleteTonCorrParamExtr(&hEnvCut->TonCorr); + + FDKsbrEnc_deleteExtractSbrEnvelope(&hEnvCut->sbrExtractEnvelope); + } +} + +/***************************************************************************** + + functionname: sbrEncoder_ChannelClose + description: close the channel coding handle + returns: + input: phSbrChannel + output: + +*****************************************************************************/ +static void sbrEncoder_ChannelClose(HANDLE_SBR_CHANNEL hSbrChannel) { + if (hSbrChannel != NULL) { + deleteEnvChannel(&hSbrChannel->hEnvChannel); + } +} + +/***************************************************************************** + + functionname: sbrEncoder_ElementClose + description: close the channel coding handle + returns: + input: phSbrChannel + output: + +*****************************************************************************/ +static void sbrEncoder_ElementClose(HANDLE_SBR_ELEMENT *phSbrElement) { + HANDLE_SBR_ELEMENT hSbrElement = *phSbrElement; + + if (hSbrElement != NULL) { + if (hSbrElement->sbrConfigData.v_k_master) + FreeRam_Sbr_v_k_master(&hSbrElement->sbrConfigData.v_k_master); + if (hSbrElement->sbrConfigData.freqBandTable[LO]) + FreeRam_Sbr_freqBandTableLO( + &hSbrElement->sbrConfigData.freqBandTable[LO]); + if (hSbrElement->sbrConfigData.freqBandTable[HI]) + FreeRam_Sbr_freqBandTableHI( + &hSbrElement->sbrConfigData.freqBandTable[HI]); + + FreeRam_SbrElement(phSbrElement); + } + return; +} + +void sbrEncoder_Close(HANDLE_SBR_ENCODER *phSbrEncoder) { + HANDLE_SBR_ENCODER hSbrEncoder = *phSbrEncoder; + + if (hSbrEncoder != NULL) { + int el, ch; + + for (el = 0; el < (8); el++) { + if (hSbrEncoder->sbrElement[el] != NULL) { + sbrEncoder_ElementClose(&hSbrEncoder->sbrElement[el]); + } + } + + /* Close sbr Channels */ + for (ch = 0; ch < (8); ch++) { + if (hSbrEncoder->pSbrChannel[ch]) { + sbrEncoder_ChannelClose(hSbrEncoder->pSbrChannel[ch]); + FreeRam_SbrChannel(&hSbrEncoder->pSbrChannel[ch]); + } + + if (hSbrEncoder->QmfAnalysis[ch].FilterStates) + FreeRam_Sbr_QmfStatesAnalysis( + (FIXP_QAS **)&hSbrEncoder->QmfAnalysis[ch].FilterStates); + } + + if (hSbrEncoder->hParametricStereo) + PSEnc_Destroy(&hSbrEncoder->hParametricStereo); + if (hSbrEncoder->qmfSynthesisPS.FilterStates) + FreeRam_PsQmfStatesSynthesis( + (FIXP_DBL **)&hSbrEncoder->qmfSynthesisPS.FilterStates); + + /* Release Overlay */ + if (hSbrEncoder->pSBRdynamic_RAM) + FreeRam_SbrDynamic_RAM((FIXP_DBL **)&hSbrEncoder->pSBRdynamic_RAM); + + FreeRam_SbrEncoder(phSbrEncoder); + } +} + +/***************************************************************************** + + functionname: updateFreqBandTable + description: updates vk_master + returns: - + input: config handle + output: error info + +*****************************************************************************/ +static INT updateFreqBandTable(HANDLE_SBR_CONFIG_DATA sbrConfigData, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + const INT downSampleFactor) { + INT k0, k2; + + if (FDKsbrEnc_FindStartAndStopBand( + sbrConfigData->sampleFreq, + sbrConfigData->sampleFreq >> (downSampleFactor - 1), + sbrConfigData->noQmfBands, sbrHeaderData->sbr_start_frequency, + sbrHeaderData->sbr_stop_frequency, &k0, &k2)) + return (1); + + if (FDKsbrEnc_UpdateFreqScale( + sbrConfigData->v_k_master, &sbrConfigData->num_Master, k0, k2, + sbrHeaderData->freqScale, sbrHeaderData->alterScale)) + return (1); + + sbrHeaderData->sbr_xover_band = 0; + + if (FDKsbrEnc_UpdateHiRes(sbrConfigData->freqBandTable[HI], + &sbrConfigData->nSfb[HI], sbrConfigData->v_k_master, + sbrConfigData->num_Master, + &sbrHeaderData->sbr_xover_band)) + return (1); + + FDKsbrEnc_UpdateLoRes( + sbrConfigData->freqBandTable[LO], &sbrConfigData->nSfb[LO], + sbrConfigData->freqBandTable[HI], sbrConfigData->nSfb[HI]); + + sbrConfigData->xOverFreq = + (sbrConfigData->freqBandTable[LOW_RES][0] * sbrConfigData->sampleFreq / + sbrConfigData->noQmfBands + + 1) >> + 1; + + return (0); +} + +/***************************************************************************** + + functionname: resetEnvChannel + description: resets parameters and allocates memory + returns: error status + input: + output: hEnv + +*****************************************************************************/ +static INT resetEnvChannel(HANDLE_SBR_CONFIG_DATA sbrConfigData, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_ENV_CHANNEL hEnv) { + /* note !!! hEnv->encEnvData.noOfnoisebands will be updated later in function + * FDKsbrEnc_extractSbrEnvelope !!!*/ + hEnv->TonCorr.sbrNoiseFloorEstimate.noiseBands = + sbrHeaderData->sbr_noise_bands; + + if (FDKsbrEnc_ResetTonCorrParamExtr( + &hEnv->TonCorr, sbrConfigData->xposCtrlSwitch, + sbrConfigData->freqBandTable[HI][0], sbrConfigData->v_k_master, + sbrConfigData->num_Master, sbrConfigData->sampleFreq, + sbrConfigData->freqBandTable, sbrConfigData->nSfb, + sbrConfigData->noQmfBands)) + return (1); + + hEnv->sbrCodeNoiseFloor.nSfb[LO] = + hEnv->TonCorr.sbrNoiseFloorEstimate.noNoiseBands; + hEnv->sbrCodeNoiseFloor.nSfb[HI] = + hEnv->TonCorr.sbrNoiseFloorEstimate.noNoiseBands; + + hEnv->sbrCodeEnvelope.nSfb[LO] = sbrConfigData->nSfb[LO]; + hEnv->sbrCodeEnvelope.nSfb[HI] = sbrConfigData->nSfb[HI]; + + hEnv->encEnvData.noHarmonics = sbrConfigData->nSfb[HI]; + + hEnv->sbrCodeEnvelope.upDate = 0; + hEnv->sbrCodeNoiseFloor.upDate = 0; + + return (0); +} + +/* ****************************** FDKsbrEnc_SbrGetXOverFreq + * ******************************/ +/** + * @fn + * @brief calculates the closest possible crossover frequency + * @return the crossover frequency SBR accepts + * + */ +static INT FDKsbrEnc_SbrGetXOverFreq( + HANDLE_SBR_ELEMENT hEnv, /*!< handle to SBR encoder instance */ + INT xoverFreq) /*!< from core coder suggested crossover frequency */ +{ + INT band; + INT lastDiff, newDiff; + INT cutoffSb; + + UCHAR *RESTRICT pVKMaster = hEnv->sbrConfigData.v_k_master; + + /* Check if there is a matching cutoff frequency in the master table */ + cutoffSb = (4 * xoverFreq * hEnv->sbrConfigData.noQmfBands / + hEnv->sbrConfigData.sampleFreq + + 1) >> + 1; + lastDiff = cutoffSb; + for (band = 0; band < hEnv->sbrConfigData.num_Master; band++) { + newDiff = fixp_abs((INT)pVKMaster[band] - cutoffSb); + + if (newDiff >= lastDiff) { + band--; + break; + } + + lastDiff = newDiff; + } + + return ((pVKMaster[band] * hEnv->sbrConfigData.sampleFreq / + hEnv->sbrConfigData.noQmfBands + + 1) >> + 1); +} + +/***************************************************************************** + + functionname: FDKsbrEnc_EnvEncodeFrame + description: performs the sbr envelope calculation for one element + returns: + input: + output: + +*****************************************************************************/ +INT FDKsbrEnc_EnvEncodeFrame( + HANDLE_SBR_ENCODER hEnvEncoder, int iElement, + INT_PCM *samples, /*!< time samples, always deinterleaved */ + UINT samplesBufSize, /*!< time buffer channel stride */ + UINT *sbrDataBits, /*!< Size of SBR payload */ + UCHAR *sbrData, /*!< SBR payload */ + int clearOutput /*!< Do not consider any input signal */ +) { + HANDLE_SBR_ELEMENT hSbrElement = NULL; + FDK_CRCINFO crcInfo; + INT crcReg; + INT ch; + INT band; + INT cutoffSb; + INT newXOver; + + if (hEnvEncoder == NULL) return -1; + + hSbrElement = hEnvEncoder->sbrElement[iElement]; + + if (hSbrElement == NULL) return -1; + + /* header bitstream handling */ + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData = &hSbrElement->sbrBitstreamData; + + INT psHeaderActive = 0; + sbrBitstreamData->HeaderActive = 0; + + /* Anticipate PS header because of internal PS bitstream delay in order to be + * in sync with SBR header. */ + if (sbrBitstreamData->CountSendHeaderData == + (sbrBitstreamData->NrSendHeaderData - 1)) { + psHeaderActive = 1; + } + + /* Signal SBR header to be written into bitstream */ + if (sbrBitstreamData->CountSendHeaderData == 0) { + sbrBitstreamData->HeaderActive = 1; + } + + /* Increment header interval counter */ + if (sbrBitstreamData->NrSendHeaderData == 0) { + sbrBitstreamData->CountSendHeaderData = 1; + } else { + if (sbrBitstreamData->CountSendHeaderData >= 0) { + sbrBitstreamData->CountSendHeaderData++; + sbrBitstreamData->CountSendHeaderData %= + sbrBitstreamData->NrSendHeaderData; + } + } + + if (hSbrElement->CmonData.dynBwEnabled) { + INT i; + for (i = 4; i > 0; i--) + hSbrElement->dynXOverFreqDelay[i] = hSbrElement->dynXOverFreqDelay[i - 1]; + + hSbrElement->dynXOverFreqDelay[0] = hSbrElement->CmonData.dynXOverFreqEnc; + if (hSbrElement->dynXOverFreqDelay[1] > hSbrElement->dynXOverFreqDelay[2]) + newXOver = hSbrElement->dynXOverFreqDelay[2]; + else + newXOver = hSbrElement->dynXOverFreqDelay[1]; + + /* has the crossover frequency changed? */ + if (hSbrElement->sbrConfigData.dynXOverFreq != newXOver) { + /* get corresponding master band */ + cutoffSb = ((4 * newXOver * hSbrElement->sbrConfigData.noQmfBands / + hSbrElement->sbrConfigData.sampleFreq) + + 1) >> + 1; + + for (band = 0; band < hSbrElement->sbrConfigData.num_Master; band++) { + if (cutoffSb == hSbrElement->sbrConfigData.v_k_master[band]) break; + } + FDK_ASSERT(band < hSbrElement->sbrConfigData.num_Master); + + hSbrElement->sbrConfigData.dynXOverFreq = newXOver; + hSbrElement->sbrHeaderData.sbr_xover_band = band; + hSbrElement->sbrBitstreamData.HeaderActive = 1; + psHeaderActive = 1; /* ps header is one frame delayed */ + + /* + update vk_master table + */ + if (updateFreqBandTable(&hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + hEnvEncoder->downSampleFactor)) + return (1); + + /* reset SBR channels */ + INT nEnvCh = hSbrElement->sbrConfigData.nChannels; + for (ch = 0; ch < nEnvCh; ch++) { + if (resetEnvChannel(&hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + &hSbrElement->sbrChannel[ch]->hEnvChannel)) + return (1); + } + } + } + + /* + allocate space for dummy header and crc + */ + crcReg = FDKsbrEnc_InitSbrBitstream( + &hSbrElement->CmonData, + hSbrElement->payloadDelayLine[hEnvEncoder->nBitstrDelay], + MAX_PAYLOAD_SIZE * sizeof(UCHAR), &crcInfo, + hSbrElement->sbrConfigData.sbrSyntaxFlags); + + /* Temporal Envelope Data */ + SBR_FRAME_TEMP_DATA _fData; + SBR_FRAME_TEMP_DATA *fData = &_fData; + SBR_ENV_TEMP_DATA eData[MAX_NUM_CHANNELS]; + + /* Init Temporal Envelope Data */ + { + int i; + + FDKmemclear(&eData[0], sizeof(SBR_ENV_TEMP_DATA)); + FDKmemclear(&eData[1], sizeof(SBR_ENV_TEMP_DATA)); + FDKmemclear(fData, sizeof(SBR_FRAME_TEMP_DATA)); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) fData->res[i] = FREQ_RES_HIGH; + } + + if (!clearOutput) { + /* + * Transform audio data into QMF domain + */ + for (ch = 0; ch < hSbrElement->sbrConfigData.nChannels; ch++) { + HANDLE_ENV_CHANNEL h_envChan = &hSbrElement->sbrChannel[ch]->hEnvChannel; + HANDLE_SBR_EXTRACT_ENVELOPE sbrExtrEnv = &h_envChan->sbrExtractEnvelope; + + if (hSbrElement->elInfo.fParametricStereo == 0) { + QMF_SCALE_FACTOR tmpScale; + FIXP_DBL **pQmfReal, **pQmfImag; + C_AALLOC_SCRATCH_START(qmfWorkBuffer, FIXP_DBL, 64 * 2) + + /* Obtain pointers to QMF buffers. */ + pQmfReal = sbrExtrEnv->rBuffer; + pQmfImag = sbrExtrEnv->iBuffer; + + qmfAnalysisFiltering( + hSbrElement->hQmfAnalysis[ch], pQmfReal, pQmfImag, &tmpScale, + samples + hSbrElement->elInfo.ChannelIndex[ch] * samplesBufSize, 0, + 1, qmfWorkBuffer); + + h_envChan->qmfScale = tmpScale.lb_scale + 7; + + C_AALLOC_SCRATCH_END(qmfWorkBuffer, FIXP_DBL, 64 * 2) + + } /* fParametricStereo == 0 */ + + /* + Parametric Stereo processing + */ + if (hSbrElement->elInfo.fParametricStereo) { + INT error = noError; + + /* Limit Parametric Stereo to one instance */ + FDK_ASSERT(ch == 0); + + if (error == noError) { + /* parametric stereo processing: + - input: + o left and right time domain samples + - processing: + o stereo qmf analysis + o stereo hybrid analysis + o ps parameter extraction + o downmix + hybrid synthesis + - output: + o downmixed qmf data is written to sbrExtrEnv->rBuffer and + sbrExtrEnv->iBuffer + */ + SCHAR qmfScale; + INT_PCM *pSamples[2] = { + samples + hSbrElement->elInfo.ChannelIndex[0] * samplesBufSize, + samples + hSbrElement->elInfo.ChannelIndex[1] * samplesBufSize}; + error = FDKsbrEnc_PSEnc_ParametricStereoProcessing( + hEnvEncoder->hParametricStereo, pSamples, samplesBufSize, + hSbrElement->hQmfAnalysis, sbrExtrEnv->rBuffer, + sbrExtrEnv->iBuffer, + samples + hSbrElement->elInfo.ChannelIndex[ch] * samplesBufSize, + &hEnvEncoder->qmfSynthesisPS, &qmfScale, psHeaderActive); + h_envChan->qmfScale = (int)qmfScale; + } + + } /* if (hEnvEncoder->hParametricStereo) */ + + /* + + Extract Envelope relevant things from QMF data + + */ + FDKsbrEnc_extractSbrEnvelope1(&hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + &hSbrElement->sbrBitstreamData, h_envChan, + &hSbrElement->CmonData, &eData[ch], fData); + + } /* hEnvEncoder->sbrConfigData.nChannels */ + } + + /* + Process Envelope relevant things and calculate envelope data and write + payload + */ + FDKsbrEnc_extractSbrEnvelope2( + &hSbrElement->sbrConfigData, &hSbrElement->sbrHeaderData, + (hSbrElement->elInfo.fParametricStereo) ? hEnvEncoder->hParametricStereo + : NULL, + &hSbrElement->sbrBitstreamData, &hSbrElement->sbrChannel[0]->hEnvChannel, + (hSbrElement->sbrConfigData.stereoMode != SBR_MONO) + ? &hSbrElement->sbrChannel[1]->hEnvChannel + : NULL, + &hSbrElement->CmonData, eData, fData, clearOutput); + + hSbrElement->sbrBitstreamData.rightBorderFIX = 0; + + /* + format payload, calculate crc + */ + FDKsbrEnc_AssembleSbrBitstream(&hSbrElement->CmonData, &crcInfo, crcReg, + hSbrElement->sbrConfigData.sbrSyntaxFlags); + + /* + save new payload, set to zero length if greater than MAX_PAYLOAD_SIZE + */ + hSbrElement->payloadDelayLineSize[hEnvEncoder->nBitstrDelay] = + FDKgetValidBits(&hSbrElement->CmonData.sbrBitbuf); + + if (hSbrElement->payloadDelayLineSize[hEnvEncoder->nBitstrDelay] > + (MAX_PAYLOAD_SIZE << 3)) + hSbrElement->payloadDelayLineSize[hEnvEncoder->nBitstrDelay] = 0; + + /* While filling the Delay lines, sbrData is NULL */ + if (sbrData) { + *sbrDataBits = hSbrElement->payloadDelayLineSize[0]; + FDKmemcpy(sbrData, hSbrElement->payloadDelayLine[0], + (hSbrElement->payloadDelayLineSize[0] + 7) >> 3); + } + + /* delay header active flag */ + if (hSbrElement->sbrBitstreamData.HeaderActive == 1) { + hSbrElement->sbrBitstreamData.HeaderActiveDelay = + 1 + hEnvEncoder->nBitstrDelay; + } else { + if (hSbrElement->sbrBitstreamData.HeaderActiveDelay > 0) { + hSbrElement->sbrBitstreamData.HeaderActiveDelay--; + } + } + + return (0); +} + +/***************************************************************************** + + functionname: FDKsbrEnc_Downsample + description: performs downsampling and delay compensation of the core path + returns: + input: + output: + +*****************************************************************************/ +INT FDKsbrEnc_Downsample( + HANDLE_SBR_ENCODER hSbrEncoder, + INT_PCM *samples, /*!< time samples, always deinterleaved */ + UINT samplesBufSize, /*!< time buffer size per channel */ + UINT numChannels, /*!< number of channels */ + UINT *sbrDataBits, /*!< Size of SBR payload */ + UCHAR *sbrData, /*!< SBR payload */ + int clearOutput /*!< Do not consider any input signal */ +) { + HANDLE_SBR_ELEMENT hSbrElement = NULL; + INT nOutSamples; + int el; + if (hSbrEncoder->downSampleFactor > 1) { + /* Do downsampling */ + + /* Loop over elements (LFE is handled later) */ + for (el = 0; el < hSbrEncoder->noElements; el++) { + hSbrElement = hSbrEncoder->sbrElement[el]; + if (hSbrEncoder->sbrElement[el] != NULL) { + if (hSbrEncoder->downsamplingMethod == SBRENC_DS_TIME) { + int ch; + int nChannels = hSbrElement->sbrConfigData.nChannels; + + for (ch = 0; ch < nChannels; ch++) { + FDKaacEnc_Downsample( + &hSbrElement->sbrChannel[ch]->downSampler, + samples + + hSbrElement->elInfo.ChannelIndex[ch] * samplesBufSize + + hSbrEncoder->bufferOffset / numChannels, + hSbrElement->sbrConfigData.frameSize, + samples + hSbrElement->elInfo.ChannelIndex[ch] * samplesBufSize, + &nOutSamples); + } + } + } + } + + /* Handle LFE (if existing) */ + if (hSbrEncoder->lfeChIdx != -1) { /* lfe downsampler */ + FDKaacEnc_Downsample(&hSbrEncoder->lfeDownSampler, + samples + hSbrEncoder->lfeChIdx * samplesBufSize + + hSbrEncoder->bufferOffset / numChannels, + hSbrEncoder->frameSize, + samples + hSbrEncoder->lfeChIdx * samplesBufSize, + &nOutSamples); + } + } else { + /* No downsampling. Still, some buffer shifting for correct delay */ + int samples2Copy = hSbrEncoder->frameSize; + if (hSbrEncoder->bufferOffset / (int)numChannels < samples2Copy) { + for (int c = 0; c < (int)numChannels; c++) { + /* Do memmove while taking care of overlapping memory areas. (memcpy + does not necessarily take care) Distinguish between oeverlapping and + non overlapping version due to reasons of complexity. */ + FDKmemmove(samples + c * samplesBufSize, + samples + c * samplesBufSize + + hSbrEncoder->bufferOffset / numChannels, + samples2Copy * sizeof(INT_PCM)); + } + } else { + for (int c = 0; c < (int)numChannels; c++) { + /* Simple memcpy since the memory areas are not overlapping */ + FDKmemcpy(samples + c * samplesBufSize, + samples + c * samplesBufSize + + hSbrEncoder->bufferOffset / numChannels, + samples2Copy * sizeof(INT_PCM)); + } + } + } + + return 0; +} + +/***************************************************************************** + + functionname: createEnvChannel + description: initializes parameters and allocates memory + returns: error status + input: + output: hEnv + +*****************************************************************************/ + +static INT createEnvChannel(HANDLE_ENV_CHANNEL hEnv, INT channel, + UCHAR *dynamic_RAM) { + FDKmemclear(hEnv, sizeof(struct ENV_CHANNEL)); + + if (FDKsbrEnc_CreateTonCorrParamExtr(&hEnv->TonCorr, channel)) { + return (1); + } + + if (FDKsbrEnc_CreateExtractSbrEnvelope(&hEnv->sbrExtractEnvelope, channel, + /*chan*/ 0, dynamic_RAM)) { + return (1); + } + + return 0; +} + +/***************************************************************************** + + functionname: initEnvChannel + description: initializes parameters + returns: error status + input: + output: + +*****************************************************************************/ +static INT initEnvChannel(HANDLE_SBR_CONFIG_DATA sbrConfigData, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_ENV_CHANNEL hEnv, sbrConfigurationPtr params, + ULONG statesInitFlag, INT chanInEl, + UCHAR *dynamic_RAM) { + int frameShift, tran_off = 0; + INT e; + INT tran_fc; + INT timeSlots, timeStep, startIndex; + INT noiseBands[2] = {3, 3}; + + e = 1 << params->e; + + FDK_ASSERT(params->e >= 0); + + hEnv->encEnvData.freq_res_fixfix[0] = params->freq_res_fixfix[0]; + hEnv->encEnvData.freq_res_fixfix[1] = params->freq_res_fixfix[1]; + hEnv->encEnvData.fResTransIsLow = params->fResTransIsLow; + + hEnv->fLevelProtect = 0; + + hEnv->encEnvData.ldGrid = + (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) ? 1 : 0; + + hEnv->encEnvData.sbr_xpos_mode = (XPOS_MODE)params->sbr_xpos_mode; + + if (hEnv->encEnvData.sbr_xpos_mode == XPOS_SWITCHED) { + /* + no other type than XPOS_MDCT or XPOS_SPEECH allowed, + but enable switching + */ + sbrConfigData->switchTransposers = TRUE; + hEnv->encEnvData.sbr_xpos_mode = XPOS_MDCT; + } else { + sbrConfigData->switchTransposers = FALSE; + } + + hEnv->encEnvData.sbr_xpos_ctrl = params->sbr_xpos_ctrl; + + /* extended data */ + if (params->parametricCoding) { + hEnv->encEnvData.extended_data = 1; + } else { + hEnv->encEnvData.extended_data = 0; + } + + hEnv->encEnvData.extension_size = 0; + + startIndex = QMF_FILTER_PROTOTYPE_SIZE - sbrConfigData->noQmfBands; + + switch (params->sbrFrameSize) { + case 2304: + timeSlots = 18; + break; + case 2048: + case 1024: + case 512: + timeSlots = 16; + break; + case 1920: + case 960: + case 480: + timeSlots = 15; + break; + case 1152: + timeSlots = 9; + break; + default: + return (1); /* Illegal frame size */ + } + + timeStep = sbrConfigData->noQmfSlots / timeSlots; + + if (FDKsbrEnc_InitTonCorrParamExtr( + params->sbrFrameSize, &hEnv->TonCorr, sbrConfigData, timeSlots, + params->sbr_xpos_ctrl, params->ana_max_level, + sbrHeaderData->sbr_noise_bands, params->noiseFloorOffset, + params->useSpeechConfig)) + return (1); + + hEnv->encEnvData.noOfnoisebands = + hEnv->TonCorr.sbrNoiseFloorEstimate.noNoiseBands; + + noiseBands[0] = hEnv->encEnvData.noOfnoisebands; + noiseBands[1] = hEnv->encEnvData.noOfnoisebands; + + hEnv->encEnvData.sbr_invf_mode = (INVF_MODE)params->sbr_invf_mode; + + if (hEnv->encEnvData.sbr_invf_mode == INVF_SWITCHED) { + hEnv->encEnvData.sbr_invf_mode = INVF_MID_LEVEL; + hEnv->TonCorr.switchInverseFilt = TRUE; + } else { + hEnv->TonCorr.switchInverseFilt = FALSE; + } + + tran_fc = params->tran_fc; + + if (tran_fc == 0) { + tran_fc = fixMin( + 5000, FDKsbrEnc_getSbrStartFreqRAW(sbrHeaderData->sbr_start_frequency, + params->codecSettings.sampleFreq)); + } + + tran_fc = + (tran_fc * 4 * sbrConfigData->noQmfBands / sbrConfigData->sampleFreq + + 1) >> + 1; + + if (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + frameShift = LD_PRETRAN_OFF; + tran_off = LD_PRETRAN_OFF + FRAME_MIDDLE_SLOT_512LD * timeStep; + } else { + frameShift = 0; + switch (timeSlots) { + /* The factor of 2 is by definition. */ + case NUMBER_TIME_SLOTS_2048: + tran_off = 8 + FRAME_MIDDLE_SLOT_2048 * timeStep; + break; + case NUMBER_TIME_SLOTS_1920: + tran_off = 7 + FRAME_MIDDLE_SLOT_1920 * timeStep; + break; + default: + return 1; + } + } + if (FDKsbrEnc_InitExtractSbrEnvelope( + &hEnv->sbrExtractEnvelope, sbrConfigData->noQmfSlots, + sbrConfigData->noQmfBands, startIndex, timeSlots, timeStep, tran_off, + statesInitFlag, chanInEl, dynamic_RAM, sbrConfigData->sbrSyntaxFlags)) + return (1); + + if (FDKsbrEnc_InitSbrCodeEnvelope(&hEnv->sbrCodeEnvelope, sbrConfigData->nSfb, + params->deltaTAcrossFrames, + params->dF_edge_1stEnv, + params->dF_edge_incr)) + return (1); + + if (FDKsbrEnc_InitSbrCodeEnvelope(&hEnv->sbrCodeNoiseFloor, noiseBands, + params->deltaTAcrossFrames, 0, 0)) + return (1); + + if (FDKsbrEnc_InitSbrHuffmanTables(&hEnv->encEnvData, &hEnv->sbrCodeEnvelope, + &hEnv->sbrCodeNoiseFloor, + sbrHeaderData->sbr_amp_res)) + return (1); + + FDKsbrEnc_initFrameInfoGenerator( + &hEnv->SbrEnvFrame, params->spread, e, params->stat, timeSlots, + hEnv->encEnvData.freq_res_fixfix, hEnv->encEnvData.fResTransIsLow, + hEnv->encEnvData.ldGrid); + + if (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + + { + INT bandwidth_qmf_slot = + (sbrConfigData->sampleFreq >> 1) / (sbrConfigData->noQmfBands); + if (FDKsbrEnc_InitSbrFastTransientDetector( + &hEnv->sbrFastTransientDetector, sbrConfigData->noQmfSlots, + bandwidth_qmf_slot, sbrConfigData->noQmfBands, + sbrConfigData->freqBandTable[0][0])) + return (1); + } + + /* The transient detector has to be initialized also if the fast transient + detector was active, because the values from the transient detector + structure are used. */ + if (FDKsbrEnc_InitSbrTransientDetector( + &hEnv->sbrTransientDetector, sbrConfigData->sbrSyntaxFlags, + sbrConfigData->frameSize, sbrConfigData->sampleFreq, params, tran_fc, + sbrConfigData->noQmfSlots, sbrConfigData->noQmfBands, + hEnv->sbrExtractEnvelope.YBufferWriteOffset, + hEnv->sbrExtractEnvelope.YBufferSzShift, frameShift, tran_off)) + return (1); + + sbrConfigData->xposCtrlSwitch = params->sbr_xpos_ctrl; + + hEnv->encEnvData.noHarmonics = sbrConfigData->nSfb[HI]; + hEnv->encEnvData.addHarmonicFlag = 0; + + return (0); +} + +INT sbrEncoder_Open(HANDLE_SBR_ENCODER *phSbrEncoder, INT nElements, + INT nChannels, INT supportPS) { + INT i; + INT errorStatus = 1; + HANDLE_SBR_ENCODER hSbrEncoder = NULL; + + if (phSbrEncoder == NULL) { + goto bail; + } + + hSbrEncoder = GetRam_SbrEncoder(); + if (hSbrEncoder == NULL) { + goto bail; + } + FDKmemclear(hSbrEncoder, sizeof(SBR_ENCODER)); + + if (NULL == + (hSbrEncoder->pSBRdynamic_RAM = (UCHAR *)GetRam_SbrDynamic_RAM())) { + goto bail; + } + hSbrEncoder->dynamicRam = hSbrEncoder->pSBRdynamic_RAM; + + /* Create SBR elements */ + for (i = 0; i < nElements; i++) { + hSbrEncoder->sbrElement[i] = GetRam_SbrElement(i); + if (hSbrEncoder->sbrElement[i] == NULL) { + goto bail; + } + FDKmemclear(hSbrEncoder->sbrElement[i], sizeof(SBR_ELEMENT)); + hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[LO] = + GetRam_Sbr_freqBandTableLO(i); + hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[HI] = + GetRam_Sbr_freqBandTableHI(i); + hSbrEncoder->sbrElement[i]->sbrConfigData.v_k_master = + GetRam_Sbr_v_k_master(i); + if ((hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[LO] == NULL) || + (hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[HI] == NULL) || + (hSbrEncoder->sbrElement[i]->sbrConfigData.v_k_master == NULL)) { + goto bail; + } + } + + /* Create SBR channels */ + for (i = 0; i < nChannels; i++) { + hSbrEncoder->pSbrChannel[i] = GetRam_SbrChannel(i); + if (hSbrEncoder->pSbrChannel[i] == NULL) { + goto bail; + } + + if (createEnvChannel(&hSbrEncoder->pSbrChannel[i]->hEnvChannel, i, + hSbrEncoder->dynamicRam)) { + goto bail; + } + } + + /* Create QMF States */ + for (i = 0; i < fixMax(nChannels, (supportPS) ? 2 : 0); i++) { + hSbrEncoder->QmfAnalysis[i].FilterStates = GetRam_Sbr_QmfStatesAnalysis(i); + if (hSbrEncoder->QmfAnalysis[i].FilterStates == NULL) { + goto bail; + } + } + + /* Create Parametric Stereo handle */ + if (supportPS) { + if (PSEnc_Create(&hSbrEncoder->hParametricStereo)) { + goto bail; + } + + hSbrEncoder->qmfSynthesisPS.FilterStates = GetRam_PsQmfStatesSynthesis(); + if (hSbrEncoder->qmfSynthesisPS.FilterStates == NULL) { + goto bail; + } + } /* supportPS */ + + *phSbrEncoder = hSbrEncoder; + + errorStatus = 0; + return errorStatus; + +bail: + /* Close SBR encoder instance */ + sbrEncoder_Close(&hSbrEncoder); + return errorStatus; +} + +static INT FDKsbrEnc_Reallocate(HANDLE_SBR_ENCODER hSbrEncoder, + SBR_ELEMENT_INFO elInfo[(8)], + const INT noElements) { + INT totalCh = 0; + INT totalQmf = 0; + INT coreEl; + INT el = -1; + + hSbrEncoder->lfeChIdx = -1; /* default value, until lfe found */ + + for (coreEl = 0; coreEl < noElements; coreEl++) { + /* SBR only handles SCE and CPE's */ + if (elInfo[coreEl].elType == ID_SCE || elInfo[coreEl].elType == ID_CPE) { + el++; + } else { + if (elInfo[coreEl].elType == ID_LFE) { + hSbrEncoder->lfeChIdx = elInfo[coreEl].ChannelIndex[0]; + } + continue; + } + + SBR_ELEMENT_INFO *pelInfo = &elInfo[coreEl]; + HANDLE_SBR_ELEMENT hSbrElement = hSbrEncoder->sbrElement[el]; + + int ch; + for (ch = 0; ch < pelInfo->nChannelsInEl; ch++) { + hSbrElement->sbrChannel[ch] = hSbrEncoder->pSbrChannel[totalCh]; + totalCh++; + } + /* analysis QMF */ + for (ch = 0; + ch < ((pelInfo->fParametricStereo) ? 2 : pelInfo->nChannelsInEl); + ch++) { + hSbrElement->elInfo.ChannelIndex[ch] = pelInfo->ChannelIndex[ch]; + hSbrElement->hQmfAnalysis[ch] = &hSbrEncoder->QmfAnalysis[totalQmf++]; + } + + /* Copy Element info */ + hSbrElement->elInfo.elType = pelInfo->elType; + hSbrElement->elInfo.instanceTag = pelInfo->instanceTag; + hSbrElement->elInfo.nChannelsInEl = pelInfo->nChannelsInEl; + hSbrElement->elInfo.fParametricStereo = pelInfo->fParametricStereo; + hSbrElement->elInfo.fDualMono = pelInfo->fDualMono; + } /* coreEl */ + + return 0; +} + +/***************************************************************************** + + functionname: FDKsbrEnc_bsBufInit + description: initializes bitstream buffer + returns: initialized bitstream buffer in env encoder + input: + output: hEnv + +*****************************************************************************/ +static INT FDKsbrEnc_bsBufInit(HANDLE_SBR_ELEMENT hSbrElement, + int nBitstrDelay) { + UCHAR *bitstreamBuffer; + + /* initialize the bitstream buffer */ + bitstreamBuffer = hSbrElement->payloadDelayLine[nBitstrDelay]; + FDKinitBitStream(&hSbrElement->CmonData.sbrBitbuf, bitstreamBuffer, + MAX_PAYLOAD_SIZE * sizeof(UCHAR), 0, BS_WRITER); + + return (0); +} + +/***************************************************************************** + + functionname: FDKsbrEnc_EnvInit + description: initializes parameters + returns: error status + input: + output: hEnv + +*****************************************************************************/ +static INT FDKsbrEnc_EnvInit(HANDLE_SBR_ELEMENT hSbrElement, + sbrConfigurationPtr params, INT *coreBandWith, + AUDIO_OBJECT_TYPE aot, int nElement, + const int headerPeriod, ULONG statesInitFlag, + const SBRENC_DS_TYPE downsamplingMethod, + UCHAR *dynamic_RAM) { + int ch, i; + + if ((params->codecSettings.nChannels < 1) || + (params->codecSettings.nChannels > MAX_NUM_CHANNELS)) { + return (1); + } + + /* init and set syntax flags */ + hSbrElement->sbrConfigData.sbrSyntaxFlags = 0; + + switch (aot) { + case AOT_ER_AAC_ELD: + hSbrElement->sbrConfigData.sbrSyntaxFlags |= SBR_SYNTAX_LOW_DELAY; + break; + default: + break; + } + if (params->crcSbr) { + hSbrElement->sbrConfigData.sbrSyntaxFlags |= SBR_SYNTAX_CRC; + } + + hSbrElement->sbrConfigData.noQmfBands = 64 >> (2 - params->downSampleFactor); + switch (hSbrElement->sbrConfigData.noQmfBands) { + case 64: + hSbrElement->sbrConfigData.noQmfSlots = params->sbrFrameSize >> 6; + break; + case 32: + hSbrElement->sbrConfigData.noQmfSlots = params->sbrFrameSize >> 5; + break; + default: + hSbrElement->sbrConfigData.noQmfSlots = params->sbrFrameSize >> 6; + return (2); + } + + /* + now initialize sbrConfigData, sbrHeaderData and sbrBitstreamData, + */ + hSbrElement->sbrConfigData.nChannels = params->codecSettings.nChannels; + + if (params->codecSettings.nChannels == 2) { + if ((hSbrElement->elInfo.elType == ID_CPE) && + ((hSbrElement->elInfo.fDualMono == 1))) { + hSbrElement->sbrConfigData.stereoMode = SBR_LEFT_RIGHT; + } else { + hSbrElement->sbrConfigData.stereoMode = params->stereoMode; + } + } else { + hSbrElement->sbrConfigData.stereoMode = SBR_MONO; + } + + hSbrElement->sbrConfigData.frameSize = params->sbrFrameSize; + + hSbrElement->sbrConfigData.sampleFreq = + params->downSampleFactor * params->codecSettings.sampleFreq; + + hSbrElement->sbrBitstreamData.CountSendHeaderData = 0; + if (params->SendHeaderDataTime > 0) { + if (headerPeriod == -1) { + hSbrElement->sbrBitstreamData.NrSendHeaderData = (INT)( + params->SendHeaderDataTime * hSbrElement->sbrConfigData.sampleFreq / + (1000 * hSbrElement->sbrConfigData.frameSize)); + hSbrElement->sbrBitstreamData.NrSendHeaderData = + fixMax(hSbrElement->sbrBitstreamData.NrSendHeaderData, 1); + } else { + /* assure header period at least once per second */ + hSbrElement->sbrBitstreamData.NrSendHeaderData = fixMin( + fixMax(headerPeriod, 1), (hSbrElement->sbrConfigData.sampleFreq / + hSbrElement->sbrConfigData.frameSize)); + } + } else { + hSbrElement->sbrBitstreamData.NrSendHeaderData = 0; + } + + hSbrElement->sbrHeaderData.sbr_data_extra = params->sbr_data_extra; + hSbrElement->sbrBitstreamData.HeaderActive = 0; + hSbrElement->sbrBitstreamData.rightBorderFIX = 0; + hSbrElement->sbrHeaderData.sbr_start_frequency = params->startFreq; + hSbrElement->sbrHeaderData.sbr_stop_frequency = params->stopFreq; + hSbrElement->sbrHeaderData.sbr_xover_band = 0; + hSbrElement->sbrHeaderData.sbr_lc_stereo_mode = 0; + + /* data_extra */ + if (params->sbr_xpos_ctrl != SBR_XPOS_CTRL_DEFAULT) + hSbrElement->sbrHeaderData.sbr_data_extra = 1; + + hSbrElement->sbrHeaderData.sbr_amp_res = (AMP_RES)params->amp_res; + hSbrElement->sbrConfigData.initAmpResFF = params->init_amp_res_FF; + + /* header_extra_1 */ + hSbrElement->sbrHeaderData.freqScale = params->freqScale; + hSbrElement->sbrHeaderData.alterScale = params->alterScale; + hSbrElement->sbrHeaderData.sbr_noise_bands = params->sbr_noise_bands; + hSbrElement->sbrHeaderData.header_extra_1 = 0; + + if ((params->freqScale != SBR_FREQ_SCALE_DEFAULT) || + (params->alterScale != SBR_ALTER_SCALE_DEFAULT) || + (params->sbr_noise_bands != SBR_NOISE_BANDS_DEFAULT)) { + hSbrElement->sbrHeaderData.header_extra_1 = 1; + } + + /* header_extra_2 */ + hSbrElement->sbrHeaderData.sbr_limiter_bands = params->sbr_limiter_bands; + hSbrElement->sbrHeaderData.sbr_limiter_gains = params->sbr_limiter_gains; + + if ((hSbrElement->sbrConfigData.sampleFreq > 48000) && + (hSbrElement->sbrHeaderData.sbr_start_frequency >= 9)) { + hSbrElement->sbrHeaderData.sbr_limiter_gains = SBR_LIMITER_GAINS_INFINITE; + } + + hSbrElement->sbrHeaderData.sbr_interpol_freq = params->sbr_interpol_freq; + hSbrElement->sbrHeaderData.sbr_smoothing_length = + params->sbr_smoothing_length; + hSbrElement->sbrHeaderData.header_extra_2 = 0; + + if ((params->sbr_limiter_bands != SBR_LIMITER_BANDS_DEFAULT) || + (params->sbr_limiter_gains != SBR_LIMITER_GAINS_DEFAULT) || + (params->sbr_interpol_freq != SBR_INTERPOL_FREQ_DEFAULT) || + (params->sbr_smoothing_length != SBR_SMOOTHING_LENGTH_DEFAULT)) { + hSbrElement->sbrHeaderData.header_extra_2 = 1; + } + + /* other switches */ + hSbrElement->sbrConfigData.useWaveCoding = params->useWaveCoding; + hSbrElement->sbrConfigData.useParametricCoding = params->parametricCoding; + hSbrElement->sbrConfigData.thresholdAmpResFF_m = + params->threshold_AmpRes_FF_m; + hSbrElement->sbrConfigData.thresholdAmpResFF_e = + params->threshold_AmpRes_FF_e; + + /* init freq band table */ + if (updateFreqBandTable(&hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + params->downSampleFactor)) { + return (1); + } + + /* now create envelope ext and QMF for each available channel */ + for (ch = 0; ch < hSbrElement->sbrConfigData.nChannels; ch++) { + if (initEnvChannel(&hSbrElement->sbrConfigData, &hSbrElement->sbrHeaderData, + &hSbrElement->sbrChannel[ch]->hEnvChannel, params, + statesInitFlag, ch, dynamic_RAM)) { + return (1); + } + + } /* nChannels */ + + /* reset and intialize analysis qmf */ + for (ch = 0; ch < ((hSbrElement->elInfo.fParametricStereo) + ? 2 + : hSbrElement->sbrConfigData.nChannels); + ch++) { + int err; + UINT qmfFlags = + (hSbrElement->sbrConfigData.sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + ? QMF_FLAG_CLDFB + : 0; + if (statesInitFlag) + qmfFlags &= ~QMF_FLAG_KEEP_STATES; + else + qmfFlags |= QMF_FLAG_KEEP_STATES; + + err = qmfInitAnalysisFilterBank( + hSbrElement->hQmfAnalysis[ch], + (FIXP_QAS *)hSbrElement->hQmfAnalysis[ch]->FilterStates, + hSbrElement->sbrConfigData.noQmfSlots, + hSbrElement->sbrConfigData.noQmfBands, + hSbrElement->sbrConfigData.noQmfBands, + hSbrElement->sbrConfigData.noQmfBands, qmfFlags); + if (0 != err) { + return err; + } + } + + /* */ + hSbrElement->CmonData.xOverFreq = hSbrElement->sbrConfigData.xOverFreq; + hSbrElement->CmonData.dynBwEnabled = + (params->dynBwSupported && params->dynBwEnabled); + hSbrElement->CmonData.dynXOverFreqEnc = + FDKsbrEnc_SbrGetXOverFreq(hSbrElement, hSbrElement->CmonData.xOverFreq); + for (i = 0; i < 5; i++) + hSbrElement->dynXOverFreqDelay[i] = hSbrElement->CmonData.dynXOverFreqEnc; + hSbrElement->CmonData.sbrNumChannels = hSbrElement->sbrConfigData.nChannels; + hSbrElement->sbrConfigData.dynXOverFreq = hSbrElement->CmonData.xOverFreq; + + /* Update Bandwith to be passed to the core encoder */ + *coreBandWith = hSbrElement->CmonData.xOverFreq; + + return (0); +} + +INT sbrEncoder_GetInBufferSize(int noChannels) { + INT temp; + + temp = (2048); + temp += 1024 + MAX_SAMPLE_DELAY; + temp *= noChannels; + temp *= sizeof(INT_PCM); + return temp; +} + +/* + * Encode Dummy SBR payload frames to fill the delay lines. + */ +static INT FDKsbrEnc_DelayCompensation(HANDLE_SBR_ENCODER hEnvEnc, + INT_PCM *timeBuffer, + UINT timeBufferBufSize) { + int n, el; + + for (n = hEnvEnc->nBitstrDelay; n > 0; n--) { + for (el = 0; el < hEnvEnc->noElements; el++) { + if (FDKsbrEnc_EnvEncodeFrame( + hEnvEnc, el, + timeBuffer + hEnvEnc->downsampledOffset / hEnvEnc->nChannels, + timeBufferBufSize, NULL, NULL, 1)) + return -1; + } + sbrEncoder_UpdateBuffers(hEnvEnc, timeBuffer, timeBufferBufSize); + } + return 0; +} + +UINT sbrEncoder_LimitBitRate(UINT bitRate, UINT numChannels, + UINT coreSampleRate, AUDIO_OBJECT_TYPE aot) { + UINT newBitRate = bitRate; + INT index; + + FDK_ASSERT(numChannels > 0 && numChannels <= 2); + if (aot == AOT_PS) { + if (numChannels == 1) { + index = getPsTuningTableIndex(bitRate, &newBitRate); + if (index == INVALID_TABLE_IDX) { + bitRate = newBitRate; + } + } else { + return 0; + } + } + index = getSbrTuningTableIndex(bitRate, numChannels, coreSampleRate, aot, + &newBitRate); + if (index != INVALID_TABLE_IDX) { + newBitRate = bitRate; + } + + return newBitRate; +} + +UINT sbrEncoder_IsSingleRatePossible(AUDIO_OBJECT_TYPE aot) { + UINT isPossible = (AOT_PS == aot) ? 0 : 1; + return isPossible; +} + +/*****************************************************************************/ +/* */ +/*functionname: sbrEncoder_Init_delay */ +/*description: Determine Delay balancing and new encoder delay */ +/* */ +/*returns: - error status */ +/*input: - frame length of the core (i.e. e.g. AAC) */ +/* - number of channels */ +/* - downsample factor (1 for downsampled, 2 for dual-rate SBR) */ +/* - low delay presence */ +/* - ps presence */ +/* - downsampling method: QMF-, time domain or no downsampling */ +/* - various delay values (see DELAY_PARAM struct description) */ +/* */ +/*Example: Delay balancing for a HE-AACv1 encoder (time-domain downsampling) */ +/*========================================================================== */ +/* */ +/* +--------+ +--------+ +--------+ +--------+ +--------+ */ +/* |core | |ds 2:1 | |AAC | |QMF | |QMF | */ +/* +-+path +------------+ +-+core +-+analysis+-+overlap +-+ */ +/* | |offset | | | | | |32 bands| | | | */ +/* | +--------+ +--------+ +--------+ +--------+ +--------+ | */ +/* | core path +-------++ */ +/* | |QMF | */ +/*->+ +synth. +-> */ +/* | |64 bands| */ +/* | +-------++ */ +/* | +--------+ +--------+ +--------+ +--------+ | */ +/* | |SBR path| |QMF | |subband | |bs delay| | */ +/* +-+offset +-+analysis+-+sample +-+(full +-----------------------+ */ +/* | | |64 bands| |buffer | | frames)| */ +/* +--------+ +--------+ +--------+ +--------+ */ +/* SBR path */ +/* */ +/*****************************************************************************/ +static INT sbrEncoder_Init_delay( + const int coreFrameLength, /* input */ + const int numChannels, /* input */ + const int downSampleFactor, /* input */ + const int lowDelay, /* input */ + const int usePs, /* input */ + const int is212, /* input */ + const SBRENC_DS_TYPE downsamplingMethod, /* input */ + DELAY_PARAM *hDelayParam /* input/output */ +) { + int delayCorePath = 0; /* delay in core path */ + int delaySbrPath = 0; /* delay difference in QMF aka SBR path */ + int delayInput2Core = 0; /* delay from the input to the core */ + int delaySbrDec = 0; /* delay of the decoder's SBR module */ + + int delayCore = hDelayParam->delay; /* delay of the core */ + + /* Added delay by the SBR delay initialization */ + int corePathOffset = 0; /* core path */ + int sbrPathOffset = 0; /* sbr path */ + int bitstreamDelay = 0; /* sbr path, framewise */ + + int flCore = coreFrameLength; /* core frame length */ + + int returnValue = 0; /* return value - 0 means: no error */ + + /* 1) Calculate actual delay for core and SBR path */ + if (is212) { + delayCorePath = DELAY_COREPATH_ELDv2SBR(flCore, downSampleFactor); + delaySbrPath = DELAY_ELDv2SBR(flCore, downSampleFactor); + delaySbrDec = ((flCore) / 2) * (downSampleFactor); + } else if (lowDelay) { + delayCorePath = DELAY_COREPATH_ELDSBR(flCore, downSampleFactor); + delaySbrPath = DELAY_ELDSBR(flCore, downSampleFactor); + delaySbrDec = DELAY_QMF_POSTPROC(downSampleFactor); + } else if (usePs) { + delayCorePath = DELAY_COREPATH_PS(flCore, downSampleFactor); + delaySbrPath = DELAY_PS(flCore, downSampleFactor); + delaySbrDec = DELAY_COREPATH_SBR(flCore, downSampleFactor); + } else { + delayCorePath = DELAY_COREPATH_SBR(flCore, downSampleFactor); + delaySbrPath = DELAY_SBR(flCore, downSampleFactor); + delaySbrDec = DELAY_COREPATH_SBR(flCore, downSampleFactor); + } + delayCorePath += delayCore * downSampleFactor; + delayCorePath += + (downsamplingMethod == SBRENC_DS_TIME) ? hDelayParam->dsDelay : 0; + + /* 2) Manage coupling of paths */ + if (downsamplingMethod == SBRENC_DS_QMF && delayCorePath > delaySbrPath) { + /* In case of QMF downsampling, both paths are coupled, i.e. the SBR path + offset would be added to both the SBR path and to the core path + as well, thus making it impossible to achieve delay balancing. + To overcome that problem, a framewise delay is added to the SBR path + first, until the overall delay of the core path is shorter than + the delay of the SBR path. When this is achieved, the missing delay + difference can be added as downsampled offset to the core path. + */ + while (delayCorePath > delaySbrPath) { + /* Add one frame delay to SBR path */ + delaySbrPath += flCore * downSampleFactor; + bitstreamDelay += 1; + } + } + + /* 3) Calculate necessary additional delay to balance the paths */ + if (delayCorePath > delaySbrPath) { + /* Delay QMF input */ + while (delayCorePath > delaySbrPath + (int)flCore * (int)downSampleFactor) { + /* Do bitstream frame-wise delay balancing if there are + more than SBR framelength samples delay difference */ + delaySbrPath += flCore * downSampleFactor; + bitstreamDelay += 1; + } + /* Multiply input offset by input channels */ + corePathOffset = 0; + sbrPathOffset = (delayCorePath - delaySbrPath) * numChannels; + } else { + /* Delay AAC data */ + /* Multiply downsampled offset by AAC core channels. Divide by 2 because of + half samplerate of downsampled data. */ + corePathOffset = ((delaySbrPath - delayCorePath) * numChannels) >> + (downSampleFactor - 1); + sbrPathOffset = 0; + } + + /* 4) Calculate delay from input to core */ + if (usePs) { + delayInput2Core = + (DELAY_QMF_ANA(downSampleFactor) + DELAY_QMF_DS + DELAY_HYB_SYN) + + (downSampleFactor * corePathOffset) + 1; + } else if (downsamplingMethod == SBRENC_DS_TIME) { + delayInput2Core = corePathOffset + hDelayParam->dsDelay; + } else { + delayInput2Core = corePathOffset; + } + + /* 6) Set output parameters */ + hDelayParam->delay = FDKmax(delayCorePath, delaySbrPath); /* overall delay */ + hDelayParam->sbrDecDelay = delaySbrDec; /* SBR decoder delay */ + hDelayParam->delayInput2Core = delayInput2Core; /* delay input - core */ + hDelayParam->bitstrDelay = bitstreamDelay; /* bitstream delay, in frames */ + hDelayParam->corePathOffset = corePathOffset; /* offset added to core path */ + hDelayParam->sbrPathOffset = sbrPathOffset; /* offset added to SBR path */ + + return returnValue; +} + +/***************************************************************************** + + functionname: sbrEncoder_Init + description: initializes the SBR encoder + returns: error status + +*****************************************************************************/ +INT sbrEncoder_Init(HANDLE_SBR_ENCODER hSbrEncoder, + SBR_ELEMENT_INFO elInfo[(8)], int noElements, + INT_PCM *inputBuffer, UINT inputBufferBufSize, + INT *coreBandwidth, INT *inputBufferOffset, + INT *numChannels, const UINT syntaxFlags, + INT *coreSampleRate, UINT *downSampleFactor, + INT *frameLength, AUDIO_OBJECT_TYPE aot, int *delay, + int transformFactor, const int headerPeriod, + ULONG statesInitFlag) { + HANDLE_ERROR_INFO errorInfo = noError; + sbrConfiguration sbrConfig[(8)]; + INT error = 0; + INT lowestBandwidth; + /* Save input parameters */ + INT inputSampleRate = *coreSampleRate; + int coreFrameLength = *frameLength; + int inputBandWidth = *coreBandwidth; + int inputChannels = *numChannels; + + SBRENC_DS_TYPE downsamplingMethod = SBRENC_DS_NONE; + int highestSbrStartFreq, highestSbrStopFreq; + int lowDelay = 0; + int usePs = 0; + int is212 = 0; + + DELAY_PARAM delayParam; + + /* check whether SBR setting is available for the current encoder + * configuration (bitrate, samplerate) */ + if (!sbrEncoder_IsSingleRatePossible(aot)) { + *downSampleFactor = 2; + } + + if (aot == AOT_PS) { + usePs = 1; + } + if (aot == AOT_ER_AAC_ELD) { + lowDelay = 1; + } else if (aot == AOT_ER_AAC_LD) { + error = 1; + goto bail; + } + + /* Parametric Stereo */ + if (usePs) { + if (*numChannels == 2 && noElements == 1) { + /* Override Element type in case of Parametric stereo */ + elInfo[0].elType = ID_SCE; + elInfo[0].fParametricStereo = 1; + elInfo[0].nChannelsInEl = 1; + /* core encoder gets downmixed mono signal */ + *numChannels = 1; + } else { + error = 1; + goto bail; + } + } /* usePs */ + + /* set the core's sample rate */ + switch (*downSampleFactor) { + case 1: + *coreSampleRate = inputSampleRate; + downsamplingMethod = SBRENC_DS_NONE; + break; + case 2: + *coreSampleRate = inputSampleRate >> 1; + downsamplingMethod = usePs ? SBRENC_DS_QMF : SBRENC_DS_TIME; + break; + default: + *coreSampleRate = inputSampleRate >> 1; + return 0; /* return error */ + } + + /* check whether SBR setting is available for the current encoder + * configuration (bitrate, coreSampleRate) */ + { + int el, coreEl; + + /* Check if every element config is feasible */ + for (coreEl = 0; coreEl < noElements; coreEl++) { + /* SBR only handles SCE and CPE's */ + if (elInfo[coreEl].elType != ID_SCE && elInfo[coreEl].elType != ID_CPE) { + continue; + } + /* check if desired configuration is available */ + if (!FDKsbrEnc_IsSbrSettingAvail(elInfo[coreEl].bitRate, 0, + elInfo[coreEl].nChannelsInEl, + inputSampleRate, *coreSampleRate, aot)) { + error = 1; + goto bail; + } + } + + hSbrEncoder->nChannels = *numChannels; + hSbrEncoder->frameSize = coreFrameLength * *downSampleFactor; + hSbrEncoder->downsamplingMethod = downsamplingMethod; + hSbrEncoder->downSampleFactor = *downSampleFactor; + hSbrEncoder->estimateBitrate = 0; + hSbrEncoder->inputDataDelay = 0; + is212 = ((aot == AOT_ER_AAC_ELD) && (syntaxFlags & AC_LD_MPS)) ? 1 : 0; + + /* Open SBR elements */ + el = -1; + highestSbrStartFreq = highestSbrStopFreq = 0; + lowestBandwidth = 99999; + + /* Loop through each core encoder element and get a matching SBR element + * config */ + for (coreEl = 0; coreEl < noElements; coreEl++) { + /* SBR only handles SCE and CPE's */ + if (elInfo[coreEl].elType == ID_SCE || elInfo[coreEl].elType == ID_CPE) { + el++; + } else { + continue; + } + + /* Set parametric Stereo Flag. */ + if (usePs) { + elInfo[coreEl].fParametricStereo = 1; + } else { + elInfo[coreEl].fParametricStereo = 0; + } + + /* + * Init sbrConfig structure + */ + if (!FDKsbrEnc_InitializeSbrDefaults(&sbrConfig[el], *downSampleFactor, + coreFrameLength, IS_LOWDELAY(aot))) { + error = 1; + goto bail; + } + + /* + * Modify sbrConfig structure according to Element parameters + */ + if (!FDKsbrEnc_AdjustSbrSettings( + &sbrConfig[el], elInfo[coreEl].bitRate, + elInfo[coreEl].nChannelsInEl, *coreSampleRate, inputSampleRate, + transformFactor, 24000, 0, 0, /* useSpeechConfig */ + 0, /* lcsMode */ + usePs, /* bParametricStereo */ + aot)) { + error = 1; + goto bail; + } + + /* Find common frequency border for all SBR elements */ + highestSbrStartFreq = + fixMax(highestSbrStartFreq, sbrConfig[el].startFreq); + highestSbrStopFreq = fixMax(highestSbrStopFreq, sbrConfig[el].stopFreq); + + } /* first element loop */ + + /* Set element count (can be less than core encoder element count) */ + hSbrEncoder->noElements = el + 1; + + FDKsbrEnc_Reallocate(hSbrEncoder, elInfo, noElements); + + for (el = 0; el < hSbrEncoder->noElements; el++) { + int bandwidth = *coreBandwidth; + + /* Use lowest common bandwidth */ + sbrConfig[el].startFreq = highestSbrStartFreq; + sbrConfig[el].stopFreq = highestSbrStopFreq; + + /* initialize SBR element, and get core bandwidth */ + error = FDKsbrEnc_EnvInit(hSbrEncoder->sbrElement[el], &sbrConfig[el], + &bandwidth, aot, el, headerPeriod, + statesInitFlag, hSbrEncoder->downsamplingMethod, + hSbrEncoder->dynamicRam); + + if (error != 0) { + error = 2; + goto bail; + } + + /* Get lowest core encoder bandwidth to be returned later. */ + lowestBandwidth = fixMin(lowestBandwidth, bandwidth); + + } /* second element loop */ + + /* Initialize a downsampler for each channel in each SBR element */ + if (hSbrEncoder->downsamplingMethod == SBRENC_DS_TIME) { + for (el = 0; el < hSbrEncoder->noElements; el++) { + HANDLE_SBR_ELEMENT hSbrEl = hSbrEncoder->sbrElement[el]; + INT Wc, ch; + + Wc = 500; /* Cutoff frequency with full bandwidth */ + + for (ch = 0; ch < hSbrEl->elInfo.nChannelsInEl; ch++) { + FDKaacEnc_InitDownsampler(&hSbrEl->sbrChannel[ch]->downSampler, Wc, + *downSampleFactor); + FDK_ASSERT(hSbrEl->sbrChannel[ch]->downSampler.delay <= + MAX_DS_FILTER_DELAY); + } + } /* third element loop */ + + /* lfe */ + FDKaacEnc_InitDownsampler(&hSbrEncoder->lfeDownSampler, 0, + *downSampleFactor); + } + + /* Get delay information */ + delayParam.dsDelay = + hSbrEncoder->sbrElement[0]->sbrChannel[0]->downSampler.delay; + delayParam.delay = *delay; + + error = sbrEncoder_Init_delay(coreFrameLength, *numChannels, + *downSampleFactor, lowDelay, usePs, is212, + downsamplingMethod, &delayParam); + + if (error != 0) { + error = 3; + goto bail; + } + + hSbrEncoder->nBitstrDelay = delayParam.bitstrDelay; + hSbrEncoder->sbrDecDelay = delayParam.sbrDecDelay; + hSbrEncoder->inputDataDelay = delayParam.delayInput2Core; + + /* Assign core encoder Bandwidth */ + *coreBandwidth = lowestBandwidth; + + /* Estimate sbr bitrate, 2.5 kBit/s per sbr channel */ + hSbrEncoder->estimateBitrate += 2500 * (*numChannels); + + /* Initialize bitstream buffer for each element */ + for (el = 0; el < hSbrEncoder->noElements; el++) { + FDKsbrEnc_bsBufInit(hSbrEncoder->sbrElement[el], delayParam.bitstrDelay); + } + + /* initialize parametric stereo */ + if (usePs) { + PSENC_CONFIG psEncConfig; + FDK_ASSERT(hSbrEncoder->noElements == 1); + INT psTuningTableIdx = getPsTuningTableIndex(elInfo[0].bitRate, NULL); + + psEncConfig.frameSize = coreFrameLength; // sbrConfig.sbrFrameSize; + psEncConfig.qmfFilterMode = 0; + psEncConfig.sbrPsDelay = 0; + + /* tuning parameters */ + if (psTuningTableIdx != INVALID_TABLE_IDX) { + psEncConfig.nStereoBands = psTuningTable[psTuningTableIdx].nStereoBands; + psEncConfig.maxEnvelopes = psTuningTable[psTuningTableIdx].nEnvelopes; + psEncConfig.iidQuantErrorThreshold = + (FIXP_DBL)psTuningTable[psTuningTableIdx].iidQuantErrorThreshold; + + /* calculation is not quite linear, increased number of envelopes causes + * more bits */ + /* assume avg. 50 bits per frame for 10 stereo bands / 1 envelope + * configuration */ + hSbrEncoder->estimateBitrate += + ((((*coreSampleRate) * 5 * psEncConfig.nStereoBands * + psEncConfig.maxEnvelopes) / + hSbrEncoder->frameSize)); + + } else { + error = ERROR(CDI, "Invalid ps tuning table index."); + goto bail; + } + + qmfInitSynthesisFilterBank( + &hSbrEncoder->qmfSynthesisPS, + (FIXP_DBL *)hSbrEncoder->qmfSynthesisPS.FilterStates, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfSlots, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands >> 1, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands >> 1, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands >> 1, + (statesInitFlag) ? 0 : QMF_FLAG_KEEP_STATES); + + if (errorInfo == noError) { + /* update delay */ + psEncConfig.sbrPsDelay = + FDKsbrEnc_GetEnvEstDelay(&hSbrEncoder->sbrElement[0] + ->sbrChannel[0] + ->hEnvChannel.sbrExtractEnvelope); + + errorInfo = + PSEnc_Init(hSbrEncoder->hParametricStereo, &psEncConfig, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfSlots, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands, + hSbrEncoder->dynamicRam); + } + } + + hSbrEncoder->downsampledOffset = delayParam.corePathOffset; + hSbrEncoder->bufferOffset = delayParam.sbrPathOffset; + *delay = delayParam.delay; + + { hSbrEncoder->downmixSize = coreFrameLength * (*numChannels); } + + /* Delay Compensation: fill bitstream delay buffer with zero input signal */ + if (hSbrEncoder->nBitstrDelay > 0) { + error = FDKsbrEnc_DelayCompensation(hSbrEncoder, inputBuffer, + inputBufferBufSize); + if (error != 0) goto bail; + } + + /* Set Output frame length */ + *frameLength = coreFrameLength * *downSampleFactor; + /* Input buffer offset */ + *inputBufferOffset = + fixMax(delayParam.sbrPathOffset, delayParam.corePathOffset); + } + + return error; + +bail: + /* Restore input settings */ + *coreSampleRate = inputSampleRate; + *frameLength = coreFrameLength; + *numChannels = inputChannels; + *coreBandwidth = inputBandWidth; + + return error; +} + +INT sbrEncoder_EncodeFrame(HANDLE_SBR_ENCODER hSbrEncoder, INT_PCM *samples, + UINT samplesBufSize, UINT sbrDataBits[(8)], + UCHAR sbrData[(8)][MAX_PAYLOAD_SIZE]) { + INT error; + int el; + + for (el = 0; el < hSbrEncoder->noElements; el++) { + if (hSbrEncoder->sbrElement[el] != NULL) { + error = FDKsbrEnc_EnvEncodeFrame( + hSbrEncoder, el, + samples + hSbrEncoder->downsampledOffset / hSbrEncoder->nChannels, + samplesBufSize, &sbrDataBits[el], sbrData[el], 0); + if (error) return error; + } + } + + error = FDKsbrEnc_Downsample( + hSbrEncoder, + samples + hSbrEncoder->downsampledOffset / hSbrEncoder->nChannels, + samplesBufSize, hSbrEncoder->nChannels, &sbrDataBits[el], sbrData[el], 0); + if (error) return error; + + return 0; +} + +INT sbrEncoder_UpdateBuffers(HANDLE_SBR_ENCODER hSbrEncoder, + INT_PCM *timeBuffer, UINT timeBufferBufSize) { + if (hSbrEncoder->downsampledOffset > 0) { + int c; + int nd = hSbrEncoder->downmixSize / hSbrEncoder->nChannels; + + for (c = 0; c < hSbrEncoder->nChannels; c++) { + /* Move delayed downsampled data */ + FDKmemcpy(timeBuffer + timeBufferBufSize * c, + timeBuffer + timeBufferBufSize * c + nd, + sizeof(INT_PCM) * + (hSbrEncoder->downsampledOffset / hSbrEncoder->nChannels)); + } + } else { + int c; + + for (c = 0; c < hSbrEncoder->nChannels; c++) { + /* Move delayed input data */ + FDKmemcpy( + timeBuffer + timeBufferBufSize * c, + timeBuffer + timeBufferBufSize * c + hSbrEncoder->frameSize, + sizeof(INT_PCM) * hSbrEncoder->bufferOffset / hSbrEncoder->nChannels); + } + } + if (hSbrEncoder->nBitstrDelay > 0) { + int el; + + for (el = 0; el < hSbrEncoder->noElements; el++) { + FDKmemmove( + hSbrEncoder->sbrElement[el]->payloadDelayLine[0], + hSbrEncoder->sbrElement[el]->payloadDelayLine[1], + sizeof(UCHAR) * (hSbrEncoder->nBitstrDelay * MAX_PAYLOAD_SIZE)); + + FDKmemmove(&hSbrEncoder->sbrElement[el]->payloadDelayLineSize[0], + &hSbrEncoder->sbrElement[el]->payloadDelayLineSize[1], + sizeof(UINT) * (hSbrEncoder->nBitstrDelay)); + } + } + return 0; +} + +INT sbrEncoder_SendHeader(HANDLE_SBR_ENCODER hSbrEncoder) { + INT error = -1; + if (hSbrEncoder) { + int el; + for (el = 0; el < hSbrEncoder->noElements; el++) { + if ((hSbrEncoder->noElements == 1) && + (hSbrEncoder->sbrElement[0]->elInfo.fParametricStereo == 1)) { + hSbrEncoder->sbrElement[el]->sbrBitstreamData.CountSendHeaderData = + hSbrEncoder->sbrElement[el]->sbrBitstreamData.NrSendHeaderData - 1; + } else { + hSbrEncoder->sbrElement[el]->sbrBitstreamData.CountSendHeaderData = 0; + } + } + error = 0; + } + return error; +} + +INT sbrEncoder_ContainsHeader(HANDLE_SBR_ENCODER hSbrEncoder) { + INT sbrHeader = 1; + if (hSbrEncoder) { + int el; + for (el = 0; el < hSbrEncoder->noElements; el++) { + sbrHeader &= + (hSbrEncoder->sbrElement[el]->sbrBitstreamData.HeaderActiveDelay == 1) + ? 1 + : 0; + } + } + return sbrHeader; +} + +INT sbrEncoder_GetHeaderDelay(HANDLE_SBR_ENCODER hSbrEncoder) { + INT delay = -1; + + if (hSbrEncoder) { + if ((hSbrEncoder->noElements == 1) && + (hSbrEncoder->sbrElement[0]->elInfo.fParametricStereo == 1)) { + delay = hSbrEncoder->nBitstrDelay + 1; + } else { + delay = hSbrEncoder->nBitstrDelay; + } + } + return delay; +} +INT sbrEncoder_GetBsDelay(HANDLE_SBR_ENCODER hSbrEncoder) { + INT delay = -1; + + if (hSbrEncoder) { + delay = hSbrEncoder->nBitstrDelay; + } + return delay; +} + +INT sbrEncoder_SAPPrepare(HANDLE_SBR_ENCODER hSbrEncoder) { + INT error = -1; + if (hSbrEncoder) { + int el; + for (el = 0; el < hSbrEncoder->noElements; el++) { + hSbrEncoder->sbrElement[el]->sbrBitstreamData.rightBorderFIX = 1; + } + error = 0; + } + return error; +} + +INT sbrEncoder_GetEstimateBitrate(HANDLE_SBR_ENCODER hSbrEncoder) { + INT estimateBitrate = 0; + + if (hSbrEncoder) { + estimateBitrate += hSbrEncoder->estimateBitrate; + } + + return estimateBitrate; +} + +INT sbrEncoder_GetInputDataDelay(HANDLE_SBR_ENCODER hSbrEncoder) { + INT delay = -1; + + if (hSbrEncoder) { + delay = hSbrEncoder->inputDataDelay; + } + return delay; +} + +INT sbrEncoder_GetSbrDecDelay(HANDLE_SBR_ENCODER hSbrEncoder) { + INT delay = -1; + + if (hSbrEncoder) { + delay = hSbrEncoder->sbrDecDelay; + } + return delay; +} + +INT sbrEncoder_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return -1; + } + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return -1; + } + info += i; + + info->module_id = FDK_SBRENC; + info->version = + LIB_VERSION(SBRENCODER_LIB_VL0, SBRENCODER_LIB_VL1, SBRENCODER_LIB_VL2); + LIB_VERSION_STRING(info); +#ifdef SUPPRESS_BUILD_DATE_INFO + info->build_date = ""; + info->build_time = ""; +#else + info->build_date = __DATE__; + info->build_time = __TIME__; +#endif + info->title = "SBR Encoder"; + + /* Set flags */ + info->flags = 0 | CAPF_SBR_HQ | CAPF_SBR_PS_MPEG; + /* End of flags */ + + return 0; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_misc.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_misc.cpp new file mode 100644 index 0000000000000..83d7e36b17fc2 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_misc.cpp @@ -0,0 +1,265 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Sbr miscellaneous helper functions $Revision: 36750 $ +*/ +#include "sbr_misc.h" + +void FDKsbrEnc_Shellsort_fract(FIXP_DBL *in, INT n) { + FIXP_DBL v; + INT i, j; + INT inc = 1; + + do + inc = 3 * inc + 1; + while (inc <= n); + + do { + inc = inc / 3; + for (i = inc + 1; i <= n; i++) { + v = in[i - 1]; + j = i; + while (in[j - inc - 1] > v) { + in[j - 1] = in[j - inc - 1]; + j -= inc; + if (j <= inc) break; + } + in[j - 1] = v; + } + } while (inc > 1); +} + +/* Sorting routine */ +void FDKsbrEnc_Shellsort_int(INT *in, INT n) { + INT i, j, v; + INT inc = 1; + + do + inc = 3 * inc + 1; + while (inc <= n); + + do { + inc = inc / 3; + for (i = inc + 1; i <= n; i++) { + v = in[i - 1]; + j = i; + while (in[j - inc - 1] > v) { + in[j - 1] = in[j - inc - 1]; + j -= inc; + if (j <= inc) break; + } + in[j - 1] = v; + } + } while (inc > 1); +} + +/******************************************************************************* + Functionname: FDKsbrEnc_AddVecLeft + ******************************************************************************* + + Description: + + Arguments: INT* dst, INT* length_dst, INT* src, INT length_src + + Return: none + +*******************************************************************************/ +void FDKsbrEnc_AddVecLeft(INT *dst, INT *length_dst, INT *src, INT length_src) { + INT i; + + for (i = length_src - 1; i >= 0; i--) + FDKsbrEnc_AddLeft(dst, length_dst, src[i]); +} + +/******************************************************************************* + Functionname: FDKsbrEnc_AddLeft + ******************************************************************************* + + Description: + + Arguments: INT* vector, INT* length_vector, INT value + + Return: none + +*******************************************************************************/ +void FDKsbrEnc_AddLeft(INT *vector, INT *length_vector, INT value) { + INT i; + + for (i = *length_vector; i > 0; i--) vector[i] = vector[i - 1]; + vector[0] = value; + (*length_vector)++; +} + +/******************************************************************************* + Functionname: FDKsbrEnc_AddRight + ******************************************************************************* + + Description: + + Arguments: INT* vector, INT* length_vector, INT value + + Return: none + +*******************************************************************************/ +void FDKsbrEnc_AddRight(INT *vector, INT *length_vector, INT value) { + vector[*length_vector] = value; + (*length_vector)++; +} + +/******************************************************************************* + Functionname: FDKsbrEnc_AddVecRight + ******************************************************************************* + + Description: + + Arguments: INT* dst, INT* length_dst, INT* src, INT length_src) + + Return: none + +*******************************************************************************/ +void FDKsbrEnc_AddVecRight(INT *dst, INT *length_dst, INT *src, + INT length_src) { + INT i; + for (i = 0; i < length_src; i++) FDKsbrEnc_AddRight(dst, length_dst, src[i]); +} + +/***************************************************************************** + + functionname: FDKsbrEnc_LSI_divide_scale_fract + + description: Calculates division with best precision and scales the result. + + return: num*scale/denom + +*****************************************************************************/ +FIXP_DBL FDKsbrEnc_LSI_divide_scale_fract(FIXP_DBL num, FIXP_DBL denom, + FIXP_DBL scale) { + FIXP_DBL tmp = FL2FXCONST_DBL(0.0f); + if (num != FL2FXCONST_DBL(0.0f)) { + INT shiftCommon; + INT shiftNum = CountLeadingBits(num); + INT shiftDenom = CountLeadingBits(denom); + INT shiftScale = CountLeadingBits(scale); + + num = num << shiftNum; + scale = scale << shiftScale; + + tmp = fMultDiv2(num, scale); + + if (denom > (tmp >> fixMin(shiftNum + shiftScale - 1, (DFRACT_BITS - 1)))) { + denom = denom << shiftDenom; + tmp = schur_div(tmp, denom, 15); + shiftCommon = + fixMin((shiftNum - shiftDenom + shiftScale - 1), (DFRACT_BITS - 1)); + if (shiftCommon < 0) + tmp <<= -shiftCommon; + else + tmp >>= shiftCommon; + } else { + tmp = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL; + } + } + + return (tmp); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_misc.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_misc.h new file mode 100644 index 0000000000000..fad853f933b7a --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbr_misc.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Sbr miscellaneous helper functions prototypes $Revision: 92790 $ + \author +*/ + +#ifndef SBR_MISC_H +#define SBR_MISC_H + +#include "sbr_encoder.h" + +/* Sorting routines */ +void FDKsbrEnc_Shellsort_fract(FIXP_DBL *in, INT n); +void FDKsbrEnc_Shellsort_int(INT *in, INT n); + +void FDKsbrEnc_AddLeft(INT *vector, INT *length_vector, INT value); +void FDKsbrEnc_AddRight(INT *vector, INT *length_vector, INT value); +void FDKsbrEnc_AddVecLeft(INT *dst, INT *length_dst, INT *src, INT length_src); +void FDKsbrEnc_AddVecRight(INT *dst, INT *length_vector_dst, INT *src, + INT length_src); + +FIXP_DBL FDKsbrEnc_LSI_divide_scale_fract(FIXP_DBL num, FIXP_DBL denom, + FIXP_DBL scale); + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_freq_sca.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_freq_sca.cpp new file mode 100644 index 0000000000000..c86e047301683 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_freq_sca.cpp @@ -0,0 +1,674 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief frequency scale $Revision: 95225 $ +*/ + +#include "sbrenc_freq_sca.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +/* StartFreq */ +static INT getStartFreq(INT fsCore, const INT start_freq); + +/* StopFreq */ +static INT getStopFreq(INT fsCore, const INT stop_freq); + +static INT numberOfBands(INT b_p_o, INT start, INT stop, FIXP_DBL warp_factor); +static void CalcBands(INT *diff, INT start, INT stop, INT num_bands); +static INT modifyBands(INT max_band, INT *diff, INT length); +static void cumSum(INT start_value, INT *diff, INT length, UCHAR *start_adress); + +/******************************************************************************* + Functionname: FDKsbrEnc_getSbrStartFreqRAW + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ + +INT FDKsbrEnc_getSbrStartFreqRAW(INT startFreq, INT fsCore) { + INT result; + + if (startFreq < 0 || startFreq > 15) { + return -1; + } + /* Update startFreq struct */ + result = getStartFreq(fsCore, startFreq); + + result = + (result * (fsCore >> 5) + 1) >> 1; /* (result*fsSBR/QMFbands+1)>>1; */ + + return (result); + +} /* End FDKsbrEnc_getSbrStartFreqRAW */ + +/******************************************************************************* + Functionname: getSbrStopFreq + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ +INT FDKsbrEnc_getSbrStopFreqRAW(INT stopFreq, INT fsCore) { + INT result; + + if (stopFreq < 0 || stopFreq > 13) return -1; + + /* Uppdate stopFreq struct */ + result = getStopFreq(fsCore, stopFreq); + result = + (result * (fsCore >> 5) + 1) >> 1; /* (result*fsSBR/QMFbands+1)>>1; */ + + return (result); +} /* End getSbrStopFreq */ + +/******************************************************************************* + Functionname: getStartFreq + ******************************************************************************* + Description: + + Arguments: fsCore - core sampling rate + + + Return: + *******************************************************************************/ +static INT getStartFreq(INT fsCore, const INT start_freq) { + INT k0_min; + + switch (fsCore) { + case 8000: + k0_min = 24; /* (3000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 11025: + k0_min = 17; /* (3000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 12000: + k0_min = 16; /* (3000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 16000: + k0_min = 16; /* (4000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 22050: + k0_min = 12; /* (4000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 24000: + k0_min = 11; /* (4000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 32000: + k0_min = 10; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 44100: + k0_min = 7; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 48000: + k0_min = 7; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 96000: + k0_min = 3; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + default: + k0_min = 11; /* illegal fs */ + } + + switch (fsCore) { + case 8000: { + INT v_offset[] = {-8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}; + return (k0_min + v_offset[start_freq]); + } + case 11025: { + INT v_offset[] = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13}; + return (k0_min + v_offset[start_freq]); + } + case 12000: { + INT v_offset[] = {-5, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16}; + return (k0_min + v_offset[start_freq]); + } + case 16000: { + INT v_offset[] = {-6, -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16}; + return (k0_min + v_offset[start_freq]); + } + case 22050: + case 24000: + case 32000: { + INT v_offset[] = {-4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20}; + return (k0_min + v_offset[start_freq]); + } + case 44100: + case 48000: + case 96000: { + INT v_offset[] = {-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24}; + return (k0_min + v_offset[start_freq]); + } + default: { + INT v_offset[] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24, 28, 33}; + return (k0_min + v_offset[start_freq]); + } + } +} /* End getStartFreq */ + +/******************************************************************************* + Functionname: getStopFreq + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ +static INT getStopFreq(INT fsCore, const INT stop_freq) { + INT result, i; + INT k1_min; + INT v_dstop[13]; + + INT *v_stop_freq = NULL; + INT v_stop_freq_16[14] = {48, 49, 50, 51, 52, 54, 55, + 56, 57, 59, 60, 61, 63, 64}; + INT v_stop_freq_22[14] = {35, 37, 38, 40, 42, 44, 46, + 48, 51, 53, 56, 58, 61, 64}; + INT v_stop_freq_24[14] = {32, 34, 36, 38, 40, 42, 44, + 46, 49, 52, 55, 58, 61, 64}; + INT v_stop_freq_32[14] = {32, 34, 36, 38, 40, 42, 44, + 46, 49, 52, 55, 58, 61, 64}; + INT v_stop_freq_44[14] = {23, 25, 27, 29, 32, 34, 37, + 40, 43, 47, 51, 55, 59, 64}; + INT v_stop_freq_48[14] = {21, 23, 25, 27, 30, 32, 35, + 38, 42, 45, 49, 54, 59, 64}; + INT v_stop_freq_64[14] = {20, 22, 24, 26, 29, 31, 34, + 37, 41, 45, 49, 54, 59, 64}; + INT v_stop_freq_88[14] = {15, 17, 19, 21, 23, 26, 29, + 33, 37, 41, 46, 51, 57, 64}; + INT v_stop_freq_96[14] = {13, 15, 17, 19, 21, 24, 27, + 31, 35, 39, 44, 50, 57, 64}; + INT v_stop_freq_192[14] = {7, 8, 10, 12, 14, 16, 19, + 23, 27, 32, 38, 46, 54, 64}; + + switch (fsCore) { + case 8000: + k1_min = 48; + v_stop_freq = v_stop_freq_16; + break; + case 11025: + k1_min = 35; + v_stop_freq = v_stop_freq_22; + break; + case 12000: + k1_min = 32; + v_stop_freq = v_stop_freq_24; + break; + case 16000: + k1_min = 32; + v_stop_freq = v_stop_freq_32; + break; + case 22050: + k1_min = 23; + v_stop_freq = v_stop_freq_44; + break; + case 24000: + k1_min = 21; + v_stop_freq = v_stop_freq_48; + break; + case 32000: + k1_min = 20; + v_stop_freq = v_stop_freq_64; + break; + case 44100: + k1_min = 15; + v_stop_freq = v_stop_freq_88; + break; + case 48000: + k1_min = 13; + v_stop_freq = v_stop_freq_96; + break; + case 96000: + k1_min = 7; + v_stop_freq = v_stop_freq_192; + break; + default: + k1_min = 21; /* illegal fs */ + } + + /* Ensure increasing bandwidth */ + for (i = 0; i <= 12; i++) { + v_dstop[i] = v_stop_freq[i + 1] - v_stop_freq[i]; + } + + FDKsbrEnc_Shellsort_int(v_dstop, 13); /* Sort bandwidth changes */ + + result = k1_min; + for (i = 0; i < stop_freq; i++) { + result = result + v_dstop[i]; + } + + return (result); + +} /* End getStopFreq */ + +/******************************************************************************* + Functionname: FDKsbrEnc_FindStartAndStopBand + ******************************************************************************* + Description: + + Arguments: srSbr SBR sampling freqency + srCore AAC core sampling freqency + noChannels Number of QMF channels + startFreq SBR start frequency in QMF bands + stopFreq SBR start frequency in QMF bands + + *k0 Output parameter + *k2 Output parameter + + Return: Error code (0 is OK) + *******************************************************************************/ +INT FDKsbrEnc_FindStartAndStopBand(const INT srSbr, const INT srCore, + const INT noChannels, const INT startFreq, + const INT stopFreq, INT *k0, INT *k2) { + /* Update startFreq struct */ + *k0 = getStartFreq(srCore, startFreq); + + /* Test if start freq is outside corecoder range */ + if (srSbr * noChannels < *k0 * srCore) { + return ( + 1); /* raise the cross-over frequency and/or lower the number + of target bands per octave (or lower the sampling frequency) */ + } + + /*Update stopFreq struct */ + if (stopFreq < 14) { + *k2 = getStopFreq(srCore, stopFreq); + } else if (stopFreq == 14) { + *k2 = 2 * *k0; + } else { + *k2 = 3 * *k0; + } + + /* limit to Nyqvist */ + if (*k2 > noChannels) { + *k2 = noChannels; + } + + /* Test for invalid k0 k2 combinations */ + if ((srCore == 22050) && ((*k2 - *k0) > MAX_FREQ_COEFFS_FS44100)) + return (1); /* Number of bands exceeds valid range of MAX_FREQ_COEFFS for + fs=44.1kHz */ + + if ((srCore >= 24000) && ((*k2 - *k0) > MAX_FREQ_COEFFS_FS48000)) + return (1); /* Number of bands exceeds valid range of MAX_FREQ_COEFFS for + fs>=48kHz */ + + if ((*k2 - *k0) > MAX_FREQ_COEFFS) + return (1); /*Number of bands exceeds valid range of MAX_FREQ_COEFFS */ + + if ((*k2 - *k0) < 0) return (1); /* Number of bands is negative */ + + return (0); +} + +/******************************************************************************* + Functionname: FDKsbrEnc_UpdateFreqScale + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ +INT FDKsbrEnc_UpdateFreqScale(UCHAR *v_k_master, INT *h_num_bands, const INT k0, + const INT k2, const INT freqScale, + const INT alterScale) + +{ + INT b_p_o = 0; /* bands_per_octave */ + FIXP_DBL warp = FL2FXCONST_DBL(0.0f); + INT dk = 0; + + /* Internal variables */ + INT k1 = 0, i; + INT num_bands0; + INT num_bands1; + INT diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + INT *diff0 = diff_tot; + INT *diff1 = diff_tot + MAX_OCTAVE; + INT k2_achived; + INT k2_diff; + INT incr = 0; + + /* Init */ + if (freqScale == 1) b_p_o = 12; + if (freqScale == 2) b_p_o = 10; + if (freqScale == 3) b_p_o = 8; + + if (freqScale > 0) /*Bark*/ + { + if (alterScale == 0) + warp = FL2FXCONST_DBL(0.5f); /* 1.0/(1.0*2.0) */ + else + warp = FL2FXCONST_DBL(1.0f / 2.6f); /* 1.0/(1.3*2.0); */ + + if (4 * k2 >= 9 * k0) /*two or more regions (how many times the basis band + is copied)*/ + { + k1 = 2 * k0; + + num_bands0 = numberOfBands(b_p_o, k0, k1, FL2FXCONST_DBL(0.5f)); + num_bands1 = numberOfBands(b_p_o, k1, k2, warp); + + CalcBands(diff0, k0, k1, num_bands0); /*CalcBands1 => diff0 */ + FDKsbrEnc_Shellsort_int(diff0, num_bands0); /*SortBands sort diff0 */ + + if (diff0[0] == 0) /* too wide FB bands for target tuning */ + { + return (1); /* raise the cross-over frequency and/or lower the number + of target bands per octave (or lower the sampling + frequency */ + } + + cumSum(k0, diff0, num_bands0, v_k_master); /* cumsum */ + + CalcBands(diff1, k1, k2, num_bands1); /* CalcBands2 => diff1 */ + FDKsbrEnc_Shellsort_int(diff1, num_bands1); /* SortBands sort diff1 */ + if (diff0[num_bands0 - 1] > diff1[0]) /* max(1) > min(2) */ + { + if (modifyBands(diff0[num_bands0 - 1], diff1, num_bands1)) return (1); + } + + /* Add 2'nd region */ + cumSum(k1, diff1, num_bands1, &v_k_master[num_bands0]); + *h_num_bands = num_bands0 + num_bands1; /* Output nr of bands */ + + } else /* one region */ + { + k1 = k2; + + num_bands0 = numberOfBands(b_p_o, k0, k1, FL2FXCONST_DBL(0.5f)); + CalcBands(diff0, k0, k1, num_bands0); /* CalcBands1 => diff0 */ + FDKsbrEnc_Shellsort_int(diff0, num_bands0); /* SortBands sort diff0 */ + + if (diff0[0] == 0) /* too wide FB bands for target tuning */ + { + return (1); /* raise the cross-over frequency and/or lower the number + of target bands per octave (or lower the sampling + frequency */ + } + + cumSum(k0, diff0, num_bands0, v_k_master); /* cumsum */ + *h_num_bands = num_bands0; /* Output nr of bands */ + } + } else /* Linear mode */ + { + if (alterScale == 0) { + dk = 1; + num_bands0 = 2 * ((k2 - k0) / 2); /* FLOOR to get to few number of bands*/ + } else { + dk = 2; + num_bands0 = + 2 * (((k2 - k0) / dk + 1) / 2); /* ROUND to get closest fit */ + } + + k2_achived = k0 + num_bands0 * dk; + k2_diff = k2 - k2_achived; + + for (i = 0; i < num_bands0; i++) diff_tot[i] = dk; + + /* If linear scale wasn't achived */ + /* and we got wide SBR are */ + if (k2_diff < 0) { + incr = 1; + i = 0; + } + + /* If linear scale wasn't achived */ + /* and we got small SBR are */ + if (k2_diff > 0) { + incr = -1; + i = num_bands0 - 1; + } + + /* Adjust diff vector to get sepc. SBR range */ + while (k2_diff != 0) { + diff_tot[i] = diff_tot[i] - incr; + i = i + incr; + k2_diff = k2_diff + incr; + } + + cumSum(k0, diff_tot, num_bands0, v_k_master); /* cumsum */ + *h_num_bands = num_bands0; /* Output nr of bands */ + } + + if (*h_num_bands < 1) return (1); /*To small sbr area */ + + return (0); +} /* End FDKsbrEnc_UpdateFreqScale */ + +static INT numberOfBands(INT b_p_o, INT start, INT stop, FIXP_DBL warp_factor) { + INT result = 0; + /* result = 2* (INT) ( (double)b_p_o * + * (double)(FDKlog((double)stop/(double)start)/FDKlog((double)2)) * + * (double)FX_DBL2FL(warp_factor) + 0.5); */ + result = ((b_p_o * fMult((CalcLdInt(stop) - CalcLdInt(start)), warp_factor) + + (FL2FX_DBL(0.5f) >> LD_DATA_SHIFT)) >> + ((DFRACT_BITS - 1) - LD_DATA_SHIFT)) + << 1; /* do not optimize anymore (rounding!!) */ + + return (result); +} + +static void CalcBands(INT *diff, INT start, INT stop, INT num_bands) { + INT i, qb, qe, qtmp; + INT previous; + INT current; + FIXP_DBL base, exp, tmp; + + previous = start; + for (i = 1; i <= num_bands; i++) { + base = fDivNorm((FIXP_DBL)stop, (FIXP_DBL)start, &qb); + exp = fDivNorm((FIXP_DBL)i, (FIXP_DBL)num_bands, &qe); + tmp = fPow(base, qb, exp, qe, &qtmp); + tmp = fMult(tmp, (FIXP_DBL)(start << 24)); + current = (INT)scaleValue(tmp, qtmp - 23); + current = (current + 1) >> 1; /* rounding*/ + diff[i - 1] = current - previous; + previous = current; + } + +} /* End CalcBands */ + +static void cumSum(INT start_value, INT *diff, INT length, + UCHAR *start_adress) { + INT i; + start_adress[0] = start_value; + for (i = 1; i <= length; i++) + start_adress[i] = start_adress[i - 1] + diff[i - 1]; +} /* End cumSum */ + +static INT modifyBands(INT max_band_previous, INT *diff, INT length) { + INT change = max_band_previous - diff[0]; + + /* Limit the change so that the last band cannot get narrower than the first + * one */ + if (change > (diff[length - 1] - diff[0]) / 2) + change = (diff[length - 1] - diff[0]) / 2; + + diff[0] += change; + diff[length - 1] -= change; + FDKsbrEnc_Shellsort_int(diff, length); + + return (0); +} /* End modifyBands */ + +/******************************************************************************* + Functionname: FDKsbrEnc_UpdateHiRes + ******************************************************************************* + Description: + + + Arguments: + + Return: + *******************************************************************************/ +INT FDKsbrEnc_UpdateHiRes(UCHAR *h_hires, INT *num_hires, UCHAR *v_k_master, + INT num_master, INT *xover_band) { + INT i; + INT max1, max2; + + if ((v_k_master[*xover_band] > + 32) || /* v_k_master[*xover_band] > noQMFChannels(dualRate)/divider */ + (*xover_band > num_master)) { + /* xover_band error, too big for this startFreq. Will be clipped */ + + /* Calculate maximum value for xover_band */ + max1 = 0; + max2 = num_master; + while ((v_k_master[max1 + 1] < 32) && /* noQMFChannels(dualRate)/divider */ + ((max1 + 1) < max2)) { + max1++; + } + + *xover_band = max1; + } + + *num_hires = num_master - *xover_band; + for (i = *xover_band; i <= num_master; i++) { + h_hires[i - *xover_band] = v_k_master[i]; + } + + return (0); +} /* End FDKsbrEnc_UpdateHiRes */ + +/******************************************************************************* + Functionname: FDKsbrEnc_UpdateLoRes + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ +void FDKsbrEnc_UpdateLoRes(UCHAR *h_lores, INT *num_lores, UCHAR *h_hires, + INT num_hires) { + INT i; + + if (num_hires % 2 == 0) /* if even number of hires bands */ + { + *num_lores = num_hires / 2; + /* Use every second lores=hires[0,2,4...] */ + for (i = 0; i <= *num_lores; i++) h_lores[i] = h_hires[i * 2]; + + } else /* odd number of hires which means xover is odd */ + { + *num_lores = (num_hires + 1) / 2; + + /* Use lores=hires[0,1,3,5 ...] */ + h_lores[0] = h_hires[0]; + for (i = 1; i <= *num_lores; i++) { + h_lores[i] = h_hires[i * 2 - 1]; + } + } + +} /* End FDKsbrEnc_UpdateLoRes */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_freq_sca.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_freq_sca.h new file mode 100644 index 0000000000000..9b8d360c3d359 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_freq_sca.h @@ -0,0 +1,132 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief frequency scale prototypes $Revision: 92790 $ +*/ +#ifndef SBRENC_FREQ_SCA_H +#define SBRENC_FREQ_SCA_H + +#include "sbr_encoder.h" +#include "sbr_def.h" + +#define MAX_OCTAVE 29 +#define MAX_SECOND_REGION 50 + +INT FDKsbrEnc_UpdateFreqScale(UCHAR *v_k_master, INT *h_num_bands, const INT k0, + const INT k2, const INT freq_scale, + const INT alter_scale); + +INT FDKsbrEnc_UpdateHiRes(UCHAR *h_hires, INT *num_hires, UCHAR *v_k_master, + INT num_master, INT *xover_band); + +void FDKsbrEnc_UpdateLoRes(UCHAR *v_lores, INT *num_lores, UCHAR *v_hires, + INT num_hires); + +INT FDKsbrEnc_FindStartAndStopBand(const INT srSbr, const INT srCore, + const INT noChannels, const INT startFreq, + const INT stop_freq, INT *k0, INT *k2); + +INT FDKsbrEnc_getSbrStartFreqRAW(INT startFreq, INT fsCore); +INT FDKsbrEnc_getSbrStopFreqRAW(INT stopFreq, INT fsCore); +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_ram.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_ram.cpp new file mode 100644 index 0000000000000..fb30fa2263fba --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_ram.cpp @@ -0,0 +1,249 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Memory layout + $Revision: 92864 $ + + This module declares all static and dynamic memory spaces +*/ +#include "sbrenc_ram.h" + +#include "sbr.h" +#include "genericStds.h" + +C_AALLOC_MEM(Ram_SbrDynamic_RAM, FIXP_DBL, + ((SBR_ENC_DYN_RAM_SIZE) / sizeof(FIXP_DBL))) + +/*! + \name StaticSbrData + + Static memory areas, must not be overwritten in other sections of the encoder +*/ +/* @{ */ + +/*! static sbr encoder instance for one encoder (2 channels) + all major static and dynamic memory areas are located + in module sbr_ram and sbr rom +*/ +C_ALLOC_MEM(Ram_SbrEncoder, SBR_ENCODER, 1) +C_ALLOC_MEM2(Ram_SbrChannel, SBR_CHANNEL, 1, (8)) +C_ALLOC_MEM2(Ram_SbrElement, SBR_ELEMENT, 1, (8)) + +/*! Filter states for QMF-analysis.
+ Dimension: #MAXNRSBRCHANNELS * #SBR_QMF_FILTER_LENGTH +*/ +C_AALLOC_MEM2_L(Ram_Sbr_QmfStatesAnalysis, FIXP_QAS, 640, (8), SECT_DATA_L1) + +/*! Matrix holding the quota values for all estimates, all channels + Dimension #MAXNRSBRCHANNELS * +#SBR_QMF_CHANNELS* #MAX_NO_OF_ESTIMATES +*/ +C_ALLOC_MEM2_L(Ram_Sbr_quotaMatrix, FIXP_DBL, (MAX_NO_OF_ESTIMATES * 64), (8), + SECT_DATA_L1) + +/*! Matrix holding the sign values for all estimates, all channels + Dimension #MAXNRSBRCHANNELS * +#SBR_QMF_CHANNELS* #MAX_NO_OF_ESTIMATES +*/ +C_ALLOC_MEM2(Ram_Sbr_signMatrix, INT, (MAX_NO_OF_ESTIMATES * 64), (8)) + +/*! Frequency band table (low res)
+ Dimension #MAX_FREQ_COEFFS/2+1 +*/ +C_ALLOC_MEM2(Ram_Sbr_freqBandTableLO, UCHAR, (MAX_FREQ_COEFFS / 2 + 1), (8)) + +/*! Frequency band table (high res)
+ Dimension #MAX_FREQ_COEFFS +1 +*/ +C_ALLOC_MEM2(Ram_Sbr_freqBandTableHI, UCHAR, (MAX_FREQ_COEFFS + 1), (8)) + +/*! vk matser table
+ Dimension #MAX_FREQ_COEFFS +1 +*/ +C_ALLOC_MEM2(Ram_Sbr_v_k_master, UCHAR, (MAX_FREQ_COEFFS + 1), (8)) + +/* + Missing harmonics detection +*/ + +/*! sbr_detectionVectors
+ Dimension #MAX_NUM_CHANNELS*#MAX_NO_OF_ESTIMATES*#MAX_FREQ_COEFFS] +*/ +C_ALLOC_MEM2(Ram_Sbr_detectionVectors, UCHAR, + (MAX_NO_OF_ESTIMATES * MAX_FREQ_COEFFS), (8)) + +/*! sbr_prevCompVec[
+ Dimension #MAX_NUM_CHANNELS*#MAX_FREQ_COEFFS] +*/ +C_ALLOC_MEM2(Ram_Sbr_prevEnvelopeCompensation, UCHAR, MAX_FREQ_COEFFS, (8)) +/*! sbr_guideScfb[
+ Dimension #MAX_NUM_CHANNELS*#MAX_FREQ_COEFFS] +*/ +C_ALLOC_MEM2(Ram_Sbr_guideScfb, UCHAR, MAX_FREQ_COEFFS, (8)) + +/*! sbr_guideVectorDetected
+ Dimension #MAX_NUM_CHANNELS*#MAX_NO_OF_ESTIMATES*#MAX_FREQ_COEFFS] +*/ +C_ALLOC_MEM2(Ram_Sbr_guideVectorDetected, UCHAR, + (MAX_NO_OF_ESTIMATES * MAX_FREQ_COEFFS), (8)) +C_ALLOC_MEM2(Ram_Sbr_guideVectorDiff, FIXP_DBL, + (MAX_NO_OF_ESTIMATES * MAX_FREQ_COEFFS), (8)) +C_ALLOC_MEM2(Ram_Sbr_guideVectorOrig, FIXP_DBL, + (MAX_NO_OF_ESTIMATES * MAX_FREQ_COEFFS), (8)) + +/* + Static Parametric Stereo memory +*/ +C_AALLOC_MEM_L(Ram_PsQmfStatesSynthesis, FIXP_DBL, 640 / 2, SECT_DATA_L1) + +C_ALLOC_MEM_L(Ram_PsEncode, PS_ENCODE, 1, SECT_DATA_L1) +C_ALLOC_MEM(Ram_ParamStereo, PARAMETRIC_STEREO, 1) + +/* @} */ + +/*! + \name DynamicSbrData + + Dynamic memory areas, might be reused in other algorithm sections, + e.g. the core encoder. +*/ +/* @{ */ + +/*! Energy buffer for envelope extraction
+ Dimension #MAXNRSBRCHANNELS * +#SBR_QMF_SLOTS * #SBR_QMF_CHANNELS +*/ +C_ALLOC_MEM2(Ram_Sbr_envYBuffer, FIXP_DBL, (32 / 2 * 64), (8)) + +FIXP_DBL* GetRam_Sbr_envYBuffer(int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + OFFSET_NRG + (n*Y_2_BUF_BYTE)) is sufficiently aligned, so + * the cast is safe */ + return reinterpret_cast( + reinterpret_cast(dynamic_RAM + OFFSET_NRG + (n * Y_2_BUF_BYTE))); +} + +/* + * QMF data + */ +/* The SBR encoder uses a single channel overlapping buffer set (always n=0), + * but PS does not. */ +FIXP_DBL* GetRam_Sbr_envRBuffer(int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + OFFSET_QMF + (n*(ENV_R_BUFF_BYTE+ENV_I_BUFF_BYTE))) is + * sufficiently aligned, so the cast is safe */ + return reinterpret_cast(reinterpret_cast( + dynamic_RAM + OFFSET_QMF + (n * (ENV_R_BUFF_BYTE + ENV_I_BUFF_BYTE)))); +} +FIXP_DBL* GetRam_Sbr_envIBuffer(int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + OFFSET_QMF + (ENV_R_BUFF_BYTE) + + * (n*(ENV_R_BUFF_BYTE+ENV_I_BUFF_BYTE))) is sufficiently aligned, so the cast + * is safe */ + return reinterpret_cast( + reinterpret_cast(dynamic_RAM + OFFSET_QMF + (ENV_R_BUFF_BYTE) + + (n * (ENV_R_BUFF_BYTE + ENV_I_BUFF_BYTE)))); +} + +/* @} */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_ram.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_ram.h new file mode 100644 index 0000000000000..cf23378107398 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_ram.h @@ -0,0 +1,199 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! +\file +\brief Memory layout +$Revision: 92790 $ +*/ +#ifndef SBRENC_RAM_H +#define SBRENC_RAM_H + +#include "sbr_def.h" +#include "env_est.h" +#include "sbr_encoder.h" +#include "sbr.h" + +#include "ps_main.h" +#include "ps_encode.h" + +#define ENV_TRANSIENTS_BYTE ((sizeof(FIXP_DBL) * (MAX_NUM_CHANNELS * 3 * 32))) + +#define ENV_R_BUFF_BYTE ((sizeof(FIXP_DBL) * ((32) * MAX_HYBRID_BANDS))) +#define ENV_I_BUFF_BYTE ((sizeof(FIXP_DBL) * ((32) * MAX_HYBRID_BANDS))) +#define Y_BUF_CH_BYTE \ + ((2 * sizeof(FIXP_DBL) * (((32) - (32 / 2)) * MAX_HYBRID_BANDS))) + +#define ENV_R_BUF_PS_BYTE ((sizeof(FIXP_DBL) * 32 * 64 / 2)) +#define ENV_I_BUF_PS_BYTE ((sizeof(FIXP_DBL) * 32 * 64 / 2)) + +#define TON_BUF_CH_BYTE \ + ((sizeof(FIXP_DBL) * (MAX_NO_OF_ESTIMATES * MAX_FREQ_COEFFS))) + +#define Y_2_BUF_BYTE (Y_BUF_CH_BYTE) + +/* Workbuffer RAM - Allocation */ +/* + ++++++++++++++++++++++++++++++++++++++++++++++++++++ + | OFFSET_QMF | OFFSET_NRG | + ++++++++++++++++++++++++++++++++++++++++++++++++++++ + ------------------------- ------------------------- + | | 0.5 * | + | sbr_envRBuffer | sbr_envYBuffer_size | + | sbr_envIBuffer | | + ------------------------- ------------------------- + +*/ +#define BUF_NRG_SIZE ((MAX_NUM_CHANNELS * Y_2_BUF_BYTE)) +#define BUF_QMF_SIZE (ENV_R_BUFF_BYTE + ENV_I_BUFF_BYTE) + +/* Size of the shareable memory region than can be reused */ +#define SBR_ENC_DYN_RAM_SIZE (BUF_QMF_SIZE + BUF_NRG_SIZE) + +#define OFFSET_QMF (0) +#define OFFSET_NRG (OFFSET_QMF + BUF_QMF_SIZE) + +/* + ***************************************************************************************************** + */ + +H_ALLOC_MEM(Ram_SbrDynamic_RAM, FIXP_DBL) + +H_ALLOC_MEM(Ram_SbrEncoder, SBR_ENCODER) +H_ALLOC_MEM(Ram_SbrChannel, SBR_CHANNEL) +H_ALLOC_MEM(Ram_SbrElement, SBR_ELEMENT) + +H_ALLOC_MEM(Ram_Sbr_quotaMatrix, FIXP_DBL) +H_ALLOC_MEM(Ram_Sbr_signMatrix, INT) + +H_ALLOC_MEM(Ram_Sbr_QmfStatesAnalysis, FIXP_QAS) + +H_ALLOC_MEM(Ram_Sbr_freqBandTableLO, UCHAR) +H_ALLOC_MEM(Ram_Sbr_freqBandTableHI, UCHAR) +H_ALLOC_MEM(Ram_Sbr_v_k_master, UCHAR) + +H_ALLOC_MEM(Ram_Sbr_detectionVectors, UCHAR) +H_ALLOC_MEM(Ram_Sbr_prevEnvelopeCompensation, UCHAR) +H_ALLOC_MEM(Ram_Sbr_guideScfb, UCHAR) +H_ALLOC_MEM(Ram_Sbr_guideVectorDetected, UCHAR) + +/* Dynamic Memory Allocation */ + +H_ALLOC_MEM(Ram_Sbr_envYBuffer, FIXP_DBL) +FIXP_DBL* GetRam_Sbr_envYBuffer(int n, UCHAR* dynamic_RAM); +FIXP_DBL* GetRam_Sbr_envRBuffer(int n, UCHAR* dynamic_RAM); +FIXP_DBL* GetRam_Sbr_envIBuffer(int n, UCHAR* dynamic_RAM); + +H_ALLOC_MEM(Ram_Sbr_guideVectorDiff, FIXP_DBL) +H_ALLOC_MEM(Ram_Sbr_guideVectorOrig, FIXP_DBL) + +H_ALLOC_MEM(Ram_PsQmfStatesSynthesis, FIXP_DBL) + +H_ALLOC_MEM(Ram_PsEncode, PS_ENCODE) + +FIXP_DBL* FDKsbrEnc_SliceRam_PsRqmf(FIXP_DBL* rQmfData, UCHAR* dynamic_RAM, + int n, int i, int qmfSlots); +FIXP_DBL* FDKsbrEnc_SliceRam_PsIqmf(FIXP_DBL* iQmfData, UCHAR* dynamic_RAM, + int n, int i, int qmfSlots); + +H_ALLOC_MEM(Ram_ParamStereo, PARAMETRIC_STEREO) +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_rom.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_rom.cpp new file mode 100644 index 0000000000000..737afaf5d5269 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_rom.cpp @@ -0,0 +1,910 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): Tobias Chalupka + + Description: Definition of constant tables + +*******************************************************************************/ + +/*! + \file + \brief Definition of constant tables + $Revision: 95404 $ + + This module contains most of the constant data that can be stored in ROM. +*/ + +#include "sbrenc_rom.h" +#include "genericStds.h" + +//@{ +/******************************************************************************* + + Table Overview: + + o envelope level, 1.5 dB: + 1a) v_Huff_envelopeLevelC10T[121] + 1b) v_Huff_envelopeLevelL10T[121] + 2a) v_Huff_envelopeLevelC10F[121] + 2b) v_Huff_envelopeLevelL10F[121] + + o envelope balance, 1.5 dB: + 3a) bookSbrEnvBalanceC10T[49] + 3b) bookSbrEnvBalanceL10T[49] + 4a) bookSbrEnvBalanceC10F[49] + 4b) bookSbrEnvBalanceL10F[49] + + o envelope level, 3.0 dB: + 5a) v_Huff_envelopeLevelC11T[63] + 5b) v_Huff_envelopeLevelL11T[63] + 6a) v_Huff_envelopeLevelC11F[63] + 6b) v_Huff_envelopeLevelC11F[63] + + o envelope balance, 3.0 dB: + 7a) bookSbrEnvBalanceC11T[25] + 7b) bookSbrEnvBalanceL11T[25] + 8a) bookSbrEnvBalanceC11F[25] + 8b) bookSbrEnvBalanceL11F[25] + + o noise level, 3.0 dB: + 9a) v_Huff_NoiseLevelC11T[63] + 9b) v_Huff_NoiseLevelL11T[63] + - ) (v_Huff_envelopeLevelC11F[63] is used for freq dir) + - ) (v_Huff_envelopeLevelL11F[63] is used for freq dir) + + o noise balance, 3.0 dB: + 10a) bookSbrNoiseBalanceC11T[25] + 10b) bookSbrNoiseBalanceL11T[25] + - ) (bookSbrEnvBalanceC11F[25] is used for freq dir) + - ) (bookSbrEnvBalanceL11F[25] is used for freq dir) + + + (1.5 dB is never used for noise) + +********************************************************************************/ + +/*******************************************************************************/ +/* table : envelope level, 1.5 dB */ +/* theor range : [-58,58], CODE_BOOK_SCF_LAV = 58 */ +/* implem range: [-60,60], CODE_BOOK_SCF_LAV10 = 60 */ +/* raw stats : envelopeLevel_00 (yes, wrong suffix in name) KK 01-03-09 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode3C2FIX.m/envelopeLevel_00T_cF.mat/v_nChex_cF + built by : FH 01-07-05 */ + +const INT v_Huff_envelopeLevelC10T[121] = { + 0x0003FFD6, 0x0003FFD7, 0x0003FFD8, 0x0003FFD9, 0x0003FFDA, 0x0003FFDB, + 0x0007FFB8, 0x0007FFB9, 0x0007FFBA, 0x0007FFBB, 0x0007FFBC, 0x0007FFBD, + 0x0007FFBE, 0x0007FFBF, 0x0007FFC0, 0x0007FFC1, 0x0007FFC2, 0x0007FFC3, + 0x0007FFC4, 0x0007FFC5, 0x0007FFC6, 0x0007FFC7, 0x0007FFC8, 0x0007FFC9, + 0x0007FFCA, 0x0007FFCB, 0x0007FFCC, 0x0007FFCD, 0x0007FFCE, 0x0007FFCF, + 0x0007FFD0, 0x0007FFD1, 0x0007FFD2, 0x0007FFD3, 0x0001FFE6, 0x0003FFD4, + 0x0000FFF0, 0x0001FFE9, 0x0003FFD5, 0x0001FFE7, 0x0000FFF1, 0x0000FFEC, + 0x0000FFED, 0x0000FFEE, 0x00007FF4, 0x00003FF9, 0x00003FF7, 0x00001FFA, + 0x00001FF9, 0x00000FFB, 0x000007FC, 0x000003FC, 0x000001FD, 0x000000FD, + 0x0000007D, 0x0000003D, 0x0000001D, 0x0000000D, 0x00000005, 0x00000001, + 0x00000000, 0x00000004, 0x0000000C, 0x0000001C, 0x0000003C, 0x0000007C, + 0x000000FC, 0x000001FC, 0x000003FD, 0x00000FFA, 0x00001FF8, 0x00003FF6, + 0x00003FF8, 0x00007FF5, 0x0000FFEF, 0x0001FFE8, 0x0000FFF2, 0x0007FFD4, + 0x0007FFD5, 0x0007FFD6, 0x0007FFD7, 0x0007FFD8, 0x0007FFD9, 0x0007FFDA, + 0x0007FFDB, 0x0007FFDC, 0x0007FFDD, 0x0007FFDE, 0x0007FFDF, 0x0007FFE0, + 0x0007FFE1, 0x0007FFE2, 0x0007FFE3, 0x0007FFE4, 0x0007FFE5, 0x0007FFE6, + 0x0007FFE7, 0x0007FFE8, 0x0007FFE9, 0x0007FFEA, 0x0007FFEB, 0x0007FFEC, + 0x0007FFED, 0x0007FFEE, 0x0007FFEF, 0x0007FFF0, 0x0007FFF1, 0x0007FFF2, + 0x0007FFF3, 0x0007FFF4, 0x0007FFF5, 0x0007FFF6, 0x0007FFF7, 0x0007FFF8, + 0x0007FFF9, 0x0007FFFA, 0x0007FFFB, 0x0007FFFC, 0x0007FFFD, 0x0007FFFE, + 0x0007FFFF}; + +/* direction: time + contents : codeword lengths + raw table: HuffCode3C2FIX.m/envelopeLevel_00T_cF.mat/v_nLhex_cF + built by : FH 01-07-05 */ + +const UCHAR v_Huff_envelopeLevelL10T[121] = { + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x11, 0x12, 0x10, 0x11, 0x12, 0x11, 0x10, 0x10, 0x10, 0x10, + 0x0F, 0x0E, 0x0E, 0x0D, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, + 0x06, 0x05, 0x04, 0x03, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0C, 0x0D, 0x0E, 0x0E, 0x0F, 0x10, 0x11, 0x10, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13}; + +/* direction: freq + contents : codewords + raw table: HuffCode3C2FIX.m/envelopeLevel_00F_cF.mat/v_nChex_cF + built by : FH 01-07-05 */ + +const INT v_Huff_envelopeLevelC10F[121] = { + 0x0007FFE7, 0x0007FFE8, 0x000FFFD2, 0x000FFFD3, 0x000FFFD4, 0x000FFFD5, + 0x000FFFD6, 0x000FFFD7, 0x000FFFD8, 0x0007FFDA, 0x000FFFD9, 0x000FFFDA, + 0x000FFFDB, 0x000FFFDC, 0x0007FFDB, 0x000FFFDD, 0x0007FFDC, 0x0007FFDD, + 0x000FFFDE, 0x0003FFE4, 0x000FFFDF, 0x000FFFE0, 0x000FFFE1, 0x0007FFDE, + 0x000FFFE2, 0x000FFFE3, 0x000FFFE4, 0x0007FFDF, 0x000FFFE5, 0x0007FFE0, + 0x0003FFE8, 0x0007FFE1, 0x0003FFE0, 0x0003FFE9, 0x0001FFEF, 0x0003FFE5, + 0x0001FFEC, 0x0001FFED, 0x0001FFEE, 0x0000FFF4, 0x0000FFF3, 0x0000FFF0, + 0x00007FF7, 0x00007FF6, 0x00003FFA, 0x00001FFA, 0x00001FF9, 0x00000FFA, + 0x00000FF8, 0x000007F9, 0x000003FB, 0x000001FC, 0x000001FA, 0x000000FB, + 0x0000007C, 0x0000003C, 0x0000001C, 0x0000000C, 0x00000005, 0x00000001, + 0x00000000, 0x00000004, 0x0000000D, 0x0000001D, 0x0000003D, 0x000000FA, + 0x000000FC, 0x000001FB, 0x000003FA, 0x000007F8, 0x000007FA, 0x000007FB, + 0x00000FF9, 0x00000FFB, 0x00001FF8, 0x00001FFB, 0x00003FF8, 0x00003FF9, + 0x0000FFF1, 0x0000FFF2, 0x0001FFEA, 0x0001FFEB, 0x0003FFE1, 0x0003FFE2, + 0x0003FFEA, 0x0003FFE3, 0x0003FFE6, 0x0003FFE7, 0x0003FFEB, 0x000FFFE6, + 0x0007FFE2, 0x000FFFE7, 0x000FFFE8, 0x000FFFE9, 0x000FFFEA, 0x000FFFEB, + 0x000FFFEC, 0x0007FFE3, 0x000FFFED, 0x000FFFEE, 0x000FFFEF, 0x000FFFF0, + 0x0007FFE4, 0x000FFFF1, 0x0003FFEC, 0x000FFFF2, 0x000FFFF3, 0x0007FFE5, + 0x0007FFE6, 0x000FFFF4, 0x000FFFF5, 0x000FFFF6, 0x000FFFF7, 0x000FFFF8, + 0x000FFFF9, 0x000FFFFA, 0x000FFFFB, 0x000FFFFC, 0x000FFFFD, 0x000FFFFE, + 0x000FFFFF}; + +/* direction: freq + contents : codeword lengths + raw table: HuffCode3C2FIX.m/envelopeLevel_00F_cF.mat/v_nLhex_cF + built by : FH 01-07-05 */ + +const UCHAR v_Huff_envelopeLevelL10F[121] = { + 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x14, + 0x14, 0x14, 0x14, 0x13, 0x14, 0x13, 0x13, 0x14, 0x12, 0x14, 0x14, + 0x14, 0x13, 0x14, 0x14, 0x14, 0x13, 0x14, 0x13, 0x12, 0x13, 0x12, + 0x12, 0x11, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x10, 0x0F, 0x0F, + 0x0E, 0x0D, 0x0D, 0x0C, 0x0C, 0x0B, 0x0A, 0x09, 0x09, 0x08, 0x07, + 0x06, 0x05, 0x04, 0x03, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, + 0x08, 0x09, 0x0A, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0D, 0x0D, 0x0E, + 0x0E, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x14, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x14, + 0x14, 0x14, 0x14, 0x13, 0x14, 0x12, 0x14, 0x14, 0x13, 0x13, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}; + +/*******************************************************************************/ +/* table : envelope balance, 1.5 dB */ +/* theor range : [-48,48], CODE_BOOK_SCF_LAV = 48 */ +/* implem range: same but mapped to [-24,24], CODE_BOOK_SCF_LAV_BALANCE10 = 24 + */ +/* raw stats : envelopePan_00 (yes, wrong suffix in name) KK 01-03-09 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode3C.m/envelopePan_00T.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrEnvBalanceC10T[49] = { + 0x0000FFE4, 0x0000FFE5, 0x0000FFE6, 0x0000FFE7, 0x0000FFE8, 0x0000FFE9, + 0x0000FFEA, 0x0000FFEB, 0x0000FFEC, 0x0000FFED, 0x0000FFEE, 0x0000FFEF, + 0x0000FFF0, 0x0000FFF1, 0x0000FFF2, 0x0000FFF3, 0x0000FFF4, 0x0000FFE2, + 0x00000FFC, 0x000007FC, 0x000001FE, 0x0000007E, 0x0000001E, 0x00000006, + 0x00000000, 0x00000002, 0x0000000E, 0x0000003E, 0x000000FE, 0x000007FD, + 0x00000FFD, 0x00007FF0, 0x0000FFE3, 0x0000FFF5, 0x0000FFF6, 0x0000FFF7, + 0x0000FFF8, 0x0000FFF9, 0x0000FFFA, 0x0001FFF6, 0x0001FFF7, 0x0001FFF8, + 0x0001FFF9, 0x0001FFFA, 0x0001FFFB, 0x0001FFFC, 0x0001FFFD, 0x0001FFFE, + 0x0001FFFF}; + +/* direction: time + contents : codeword lengths + raw table: HuffCode3C.m/envelopePan_00T.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrEnvBalanceL10T[49] = { + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0C, 0x0B, + 0x09, 0x07, 0x05, 0x03, 0x01, 0x02, 0x04, 0x06, 0x08, 0x0B, + 0x0C, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}; + +/* direction: freq + contents : codewords + raw table: HuffCode3C.m/envelopePan_00F.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrEnvBalanceC10F[49] = { + 0x0003FFE2, 0x0003FFE3, 0x0003FFE4, 0x0003FFE5, 0x0003FFE6, 0x0003FFE7, + 0x0003FFE8, 0x0003FFE9, 0x0003FFEA, 0x0003FFEB, 0x0003FFEC, 0x0003FFED, + 0x0003FFEE, 0x0003FFEF, 0x0003FFF0, 0x0000FFF7, 0x0001FFF0, 0x00003FFC, + 0x000007FE, 0x000007FC, 0x000000FE, 0x0000007E, 0x0000000E, 0x00000002, + 0x00000000, 0x00000006, 0x0000001E, 0x0000003E, 0x000001FE, 0x000007FD, + 0x00000FFE, 0x00007FFA, 0x0000FFF6, 0x0003FFF1, 0x0003FFF2, 0x0003FFF3, + 0x0003FFF4, 0x0003FFF5, 0x0003FFF6, 0x0003FFF7, 0x0003FFF8, 0x0003FFF9, + 0x0003FFFA, 0x0003FFFB, 0x0003FFFC, 0x0003FFFD, 0x0003FFFE, 0x0007FFFE, + 0x0007FFFF}; + +/* direction: freq + contents : codeword lengths + raw table: HuffCode3C.m/envelopePan_00F.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrEnvBalanceL10F[49] = { + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x10, 0x11, 0x0E, 0x0B, 0x0B, + 0x08, 0x07, 0x04, 0x02, 0x01, 0x03, 0x05, 0x06, 0x09, 0x0B, + 0x0C, 0x0F, 0x10, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13}; + +/*******************************************************************************/ +/* table : envelope level, 3.0 dB */ +/* theor range : [-29,29], CODE_BOOK_SCF_LAV = 29 */ +/* implem range: [-31,31], CODE_BOOK_SCF_LAV11 = 31 */ +/* raw stats : envelopeLevel_11 KK 00-02-03 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const INT v_Huff_envelopeLevelC11T[63] = { + 0x0003FFED, 0x0003FFEE, 0x0007FFDE, 0x0007FFDF, 0x0007FFE0, 0x0007FFE1, + 0x0007FFE2, 0x0007FFE3, 0x0007FFE4, 0x0007FFE5, 0x0007FFE6, 0x0007FFE7, + 0x0007FFE8, 0x0007FFE9, 0x0007FFEA, 0x0007FFEB, 0x0007FFEC, 0x0001FFF4, + 0x0000FFF7, 0x0000FFF9, 0x0000FFF8, 0x00003FFB, 0x00003FFA, 0x00003FF8, + 0x00001FFA, 0x00000FFC, 0x000007FC, 0x000000FE, 0x0000003E, 0x0000000E, + 0x00000002, 0x00000000, 0x00000006, 0x0000001E, 0x0000007E, 0x000001FE, + 0x000007FD, 0x00001FFB, 0x00003FF9, 0x00003FFC, 0x00007FFA, 0x0000FFF6, + 0x0001FFF5, 0x0003FFEC, 0x0007FFED, 0x0007FFEE, 0x0007FFEF, 0x0007FFF0, + 0x0007FFF1, 0x0007FFF2, 0x0007FFF3, 0x0007FFF4, 0x0007FFF5, 0x0007FFF6, + 0x0007FFF7, 0x0007FFF8, 0x0007FFF9, 0x0007FFFA, 0x0007FFFB, 0x0007FFFC, + 0x0007FFFD, 0x0007FFFE, 0x0007FFFF}; + +/* direction: time + contents : codeword lengths + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const UCHAR v_Huff_envelopeLevelL11T[63] = { + 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x11, 0x10, 0x10, 0x10, 0x0E, + 0x0E, 0x0E, 0x0D, 0x0C, 0x0B, 0x08, 0x06, 0x04, 0x02, 0x01, 0x03, + 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0E, 0x0E, 0x0F, 0x10, 0x11, 0x12, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13}; + +/* direction: freq + contents : codewords + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const INT v_Huff_envelopeLevelC11F[63] = { + 0x000FFFF0, 0x000FFFF1, 0x000FFFF2, 0x000FFFF3, 0x000FFFF4, 0x000FFFF5, + 0x000FFFF6, 0x0003FFF3, 0x0007FFF5, 0x0007FFEE, 0x0007FFEF, 0x0007FFF6, + 0x0003FFF4, 0x0003FFF2, 0x000FFFF7, 0x0007FFF0, 0x0001FFF5, 0x0003FFF0, + 0x0001FFF4, 0x0000FFF7, 0x0000FFF6, 0x00007FF8, 0x00003FFB, 0x00000FFD, + 0x000007FD, 0x000003FD, 0x000001FD, 0x000000FD, 0x0000003E, 0x0000000E, + 0x00000002, 0x00000000, 0x00000006, 0x0000001E, 0x000000FC, 0x000001FC, + 0x000003FC, 0x000007FC, 0x00000FFC, 0x00001FFC, 0x00003FFA, 0x00007FF9, + 0x00007FFA, 0x0000FFF8, 0x0000FFF9, 0x0001FFF6, 0x0001FFF7, 0x0003FFF5, + 0x0003FFF6, 0x0003FFF1, 0x000FFFF8, 0x0007FFF1, 0x0007FFF2, 0x0007FFF3, + 0x000FFFF9, 0x0007FFF7, 0x0007FFF4, 0x000FFFFA, 0x000FFFFB, 0x000FFFFC, + 0x000FFFFD, 0x000FFFFE, 0x000FFFFF}; + +/* direction: freq + contents : codeword lengths + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const UCHAR v_Huff_envelopeLevelL11F[63] = { + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x12, 0x13, 0x13, 0x13, + 0x13, 0x12, 0x12, 0x14, 0x13, 0x11, 0x12, 0x11, 0x10, 0x10, 0x0F, + 0x0E, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01, 0x03, + 0x05, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x0F, 0x10, + 0x10, 0x11, 0x11, 0x12, 0x12, 0x12, 0x14, 0x13, 0x13, 0x13, 0x14, + 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}; + +/*******************************************************************************/ +/* table : envelope balance, 3.0 dB */ +/* theor range : [-24,24], CODE_BOOK_SCF_LAV = 24 */ +/* implem range: same but mapped to [-12,12], CODE_BOOK_SCF_LAV_BALANCE11 = 12 + */ +/* raw stats : envelopeBalance_11 KK 00-02-03 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode3C.m/envelopeBalance_11T.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrEnvBalanceC11T[25] = { + 0x00001FF2, 0x00001FF3, 0x00001FF4, 0x00001FF5, 0x00001FF6, + 0x00001FF7, 0x00001FF8, 0x00000FF8, 0x000000FE, 0x0000007E, + 0x0000000E, 0x00000006, 0x00000000, 0x00000002, 0x0000001E, + 0x0000003E, 0x000001FE, 0x00001FF9, 0x00001FFA, 0x00001FFB, + 0x00001FFC, 0x00001FFD, 0x00001FFE, 0x00003FFE, 0x00003FFF}; + +/* direction: time + contents : codeword lengths + raw table: HuffCode3C.m/envelopeBalance_11T.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrEnvBalanceL11T[25] = { + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x08, + 0x07, 0x04, 0x03, 0x01, 0x02, 0x05, 0x06, 0x09, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E}; + +/* direction: freq + contents : codewords + raw table: HuffCode3C.m/envelopeBalance_11F.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrEnvBalanceC11F[25] = { + 0x00001FF7, 0x00001FF8, 0x00001FF9, 0x00001FFA, 0x00001FFB, + 0x00003FF8, 0x00003FF9, 0x000007FC, 0x000000FE, 0x0000007E, + 0x0000000E, 0x00000002, 0x00000000, 0x00000006, 0x0000001E, + 0x0000003E, 0x000001FE, 0x00000FFA, 0x00001FF6, 0x00003FFA, + 0x00003FFB, 0x00003FFC, 0x00003FFD, 0x00003FFE, 0x00003FFF}; + +/* direction: freq + contents : codeword lengths + raw table: HuffCode3C.m/envelopeBalance_11F.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrEnvBalanceL11F[25] = { + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x0B, 0x08, + 0x07, 0x04, 0x02, 0x01, 0x03, 0x05, 0x06, 0x09, 0x0C, + 0x0D, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E}; + +/*******************************************************************************/ +/* table : noise level, 3.0 dB */ +/* theor range : [-29,29], CODE_BOOK_SCF_LAV = 29 */ +/* implem range: [-31,31], CODE_BOOK_SCF_LAV11 = 31 */ +/* raw stats : noiseLevel_11 KK 00-02-03 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const INT v_Huff_NoiseLevelC11T[63] = { + 0x00001FCE, 0x00001FCF, 0x00001FD0, 0x00001FD1, 0x00001FD2, 0x00001FD3, + 0x00001FD4, 0x00001FD5, 0x00001FD6, 0x00001FD7, 0x00001FD8, 0x00001FD9, + 0x00001FDA, 0x00001FDB, 0x00001FDC, 0x00001FDD, 0x00001FDE, 0x00001FDF, + 0x00001FE0, 0x00001FE1, 0x00001FE2, 0x00001FE3, 0x00001FE4, 0x00001FE5, + 0x00001FE6, 0x00001FE7, 0x000007F2, 0x000000FD, 0x0000003E, 0x0000000E, + 0x00000006, 0x00000000, 0x00000002, 0x0000001E, 0x000000FC, 0x000003F8, + 0x00001FCC, 0x00001FE8, 0x00001FE9, 0x00001FEA, 0x00001FEB, 0x00001FEC, + 0x00001FCD, 0x00001FED, 0x00001FEE, 0x00001FEF, 0x00001FF0, 0x00001FF1, + 0x00001FF2, 0x00001FF3, 0x00001FF4, 0x00001FF5, 0x00001FF6, 0x00001FF7, + 0x00001FF8, 0x00001FF9, 0x00001FFA, 0x00001FFB, 0x00001FFC, 0x00001FFD, + 0x00001FFE, 0x00003FFE, 0x00003FFF}; + +/* direction: time + contents : codeword lengths + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const UCHAR v_Huff_NoiseLevelL11T[63] = { + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000B, 0x00000008, 0x00000006, 0x00000004, + 0x00000003, 0x00000001, 0x00000002, 0x00000005, 0x00000008, 0x0000000A, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000E, 0x0000000E}; + +/*******************************************************************************/ +/* table : noise balance, 3.0 dB */ +/* theor range : [-24,24], CODE_BOOK_SCF_LAV = 24 */ +/* implem range: same but mapped to [-12,12], CODE_BOOK_SCF_LAV_BALANCE11 = 12 + */ +/* raw stats : noiseBalance_11 KK 00-02-03 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode3C.m/noiseBalance_11.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrNoiseBalanceC11T[25] = { + 0x000000EC, 0x000000ED, 0x000000EE, 0x000000EF, 0x000000F0, + 0x000000F1, 0x000000F2, 0x000000F3, 0x000000F4, 0x000000F5, + 0x0000001C, 0x00000002, 0x00000000, 0x00000006, 0x0000003A, + 0x000000F6, 0x000000F7, 0x000000F8, 0x000000F9, 0x000000FA, + 0x000000FB, 0x000000FC, 0x000000FD, 0x000000FE, 0x000000FF}; + +/* direction: time + contents : codeword lengths + raw table: HuffCode3C.m/noiseBalance_11.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrNoiseBalanceL11T[25] = { + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x05, 0x02, 0x01, 0x03, 0x06, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; + +/* + tuningTable +*/ +const sbrTuningTable_t sbrTuningTable[] = { + /* Some of the low bitrates are commented out here, this is because the + encoder could lose frames at those bitrates and throw an error + because it has insufficient bits to encode for some test items. + */ + + /*** HE-AAC section ***/ + /* sf,sfsp,sf,sfsp,nnb,nfo,saml,SM,FS*/ + + /*** mono ***/ + + /* 8/16 kHz dual rate */ + {CODEC_AAC, 8000, 10000, 8000, 1, 7, 6, 11, 10, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 10000, 12000, 8000, 1, 11, 7, 13, 12, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 12000, 16001, 8000, 1, 14, 10, 13, 13, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 16000, 24000, 8000, 1, 14, 10, 14, 14, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 24000, 32000, 8000, 1, 14, 10, 14, 14, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 32000, 48001, 8000, 1, 14, 11, 15, 15, 2, 0, 3, SBR_MONO, 2}, + + /* 11/22 kHz dual rate */ + {CODEC_AAC, 8000, 10000, 11025, 1, 5, 4, 6, 6, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 10000, 12000, 11025, 1, 8, 5, 12, 9, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 12000, 16000, 11025, 1, 12, 8, 13, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 16000, 20000, 11025, 1, 12, 8, 13, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 20000, 24001, 11025, 1, 13, 9, 13, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 24000, 32000, 11025, 1, 14, 10, 14, 9, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 32000, 48000, 11025, 1, 15, 11, 15, 10, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 48000, 64001, 11025, 1, 15, 11, 15, 10, 2, 0, 3, SBR_MONO, 1}, + + /* 12/24 kHz dual rate */ + {CODEC_AAC, 8000, 10000, 12000, 1, 4, 3, 6, 6, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 10000, 12000, 12000, 1, 7, 4, 11, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 12000, 16000, 12000, 1, 11, 7, 12, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 16000, 20000, 12000, 1, 11, 7, 12, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 20000, 24001, 12000, 1, 12, 8, 12, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 24000, 32000, 12000, 1, 13, 9, 13, 9, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 32000, 48000, 12000, 1, 14, 10, 14, 10, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 48000, 64001, 12000, 1, 14, 11, 15, 11, 2, 0, 3, SBR_MONO, 1}, + + /* 16/32 kHz dual rate */ + {CODEC_AAC, 8000, 10000, 16000, 1, 1, 1, 0, 0, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 10000, 12000, 16000, 1, 2, 1, 6, 0, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 12000, 16000, 16000, 1, 4, 2, 6, 0, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 16000, 18000, 16000, 1, 4, 2, 8, 3, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 18000, 22000, 16000, 1, 6, 5, 11, 7, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AAC, 22000, 28000, 16000, 1, 10, 9, 12, 8, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AAC, 28000, 36000, 16000, 1, 12, 12, 13, 13, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 36000, 44000, 16000, 1, 14, 14, 13, 13, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 44000, 64001, 16000, 1, 14, 14, 13, 13, 2, 0, 3, SBR_MONO, 1}, + + /* 22.05/44.1 kHz dual rate */ + /* { CODEC_AAC, 8000, 11369, 22050, 1, 1, 1, 1, 1, 1, 0, 6, + SBR_MONO, 3 }, */ + {CODEC_AAC, 11369, 16000, 22050, 1, 3, 1, 4, 4, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 16000, 18000, 22050, 1, 3, 1, 5, 4, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 18000, 22000, 22050, 1, 4, 4, 8, 5, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AAC, 22000, 28000, 22050, 1, 7, 6, 8, 6, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AAC, 28000, 36000, 22050, 1, 10, 10, 9, 9, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 36000, 44000, 22050, 1, 11, 11, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 44000, 64001, 22050, 1, 13, 13, 12, 12, 2, 0, 3, SBR_MONO, 1}, + + /* 24/48 kHz dual rate */ + /* { CODEC_AAC, 8000, 12000, 24000, 1, 1, 1, 1, 1, 1, 0, 6, + SBR_MONO, 3 }, */ + {CODEC_AAC, 12000, 16000, 24000, 1, 3, 1, 4, 4, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 16000, 18000, 24000, 1, 3, 1, 5, 4, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 18000, 22000, 24000, 1, 4, 3, 8, 5, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AAC, 22000, 28000, 24000, 1, 7, 6, 8, 6, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AAC, 28000, 36000, 24000, 1, 10, 10, 9, 9, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 36000, 44000, 24000, 1, 11, 11, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 44000, 64001, 24000, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, 1}, + + /* 32/64 kHz dual rate */ + {CODEC_AAC, 24000, 36000, 32000, 1, 4, 4, 4, 4, 2, 0, 3, SBR_MONO, 3}, + {CODEC_AAC, 36000, 60000, 32000, 1, 7, 7, 6, 6, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 60000, 72000, 32000, 1, 9, 9, 8, 8, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 72000, 100000, 32000, 1, 11, 11, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 100000, 160001, 32000, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, 1}, + + /* 44.1/88.2 kHz dual rate */ + {CODEC_AAC, 24000, 36000, 44100, 1, 4, 4, 4, 4, 2, 0, 3, SBR_MONO, 3}, + {CODEC_AAC, 36000, 60000, 44100, 1, 7, 7, 6, 6, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 60000, 72000, 44100, 1, 9, 9, 8, 8, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 72000, 100000, 44100, 1, 11, 11, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 100000, 160001, 44100, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, 1}, + + /* 48/96 kHz dual rate */ + {CODEC_AAC, 32000, 36000, 48000, 1, 4, 4, 9, 9, 2, 0, 3, SBR_MONO, 3}, + {CODEC_AAC, 36000, 60000, 48000, 1, 7, 7, 10, 10, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 60000, 72000, 48000, 1, 9, 9, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 72000, 100000, 48000, 1, 11, 11, 11, 11, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 100000, 160001, 48000, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, 1}, + + /*** stereo ***/ + /* 08/16 kHz dual rate */ + {CODEC_AAC, 16000, 24000, 8000, 2, 6, 6, 9, 7, 1, 0, -3, SBR_SWITCH_LRC, 3}, + {CODEC_AAC, 24000, 28000, 8000, 2, 9, 9, 11, 9, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 28000, 36000, 8000, 2, 11, 9, 11, 9, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 36000, 44000, 8000, 2, 13, 11, 13, 11, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 44000, 52000, 8000, 2, 14, 12, 13, 12, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 52000, 60000, 8000, 2, 14, 14, 13, 13, 3, 0, -3, SBR_SWITCH_LRC, + 1}, + {CODEC_AAC, 60000, 76000, 8000, 2, 14, 14, 13, 13, 3, 0, -3, SBR_LEFT_RIGHT, + 1}, + {CODEC_AAC, 76000, 128001, 8000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 11/22 kHz dual rate */ + {CODEC_AAC, 16000, 24000, 11025, 2, 7, 5, 9, 7, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 24000, 28000, 11025, 2, 10, 8, 10, 8, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 28000, 36000, 11025, 2, 12, 8, 12, 8, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 36000, 44000, 11025, 2, 13, 9, 13, 9, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 44000, 52000, 11025, 2, 14, 11, 13, 11, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AAC, 52000, 60000, 11025, 2, 15, 15, 13, 13, 3, 0, -3, + SBR_SWITCH_LRC, 1}, + {CODEC_AAC, 60000, 76000, 11025, 2, 15, 15, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 76000, 128001, 11025, 2, 15, 15, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 12/24 kHz dual rate */ + {CODEC_AAC, 16000, 24000, 12000, 2, 6, 4, 9, 7, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 24000, 28000, 12000, 2, 9, 7, 10, 8, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 28000, 36000, 12000, 2, 11, 7, 12, 8, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 36000, 44000, 12000, 2, 12, 9, 12, 9, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 44000, 52000, 12000, 2, 13, 12, 13, 12, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AAC, 52000, 60000, 12000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_SWITCH_LRC, 1}, + {CODEC_AAC, 60000, 76000, 12000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 76000, 128001, 12000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 16/32 kHz dual rate */ + {CODEC_AAC, 16000, 24000, 16000, 2, 4, 2, 1, 0, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 24000, 28000, 16000, 2, 8, 7, 10, 8, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 28000, 36000, 16000, 2, 10, 9, 12, 11, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 36000, 44000, 16000, 2, 13, 13, 13, 13, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AAC, 44000, 52000, 16000, 2, 14, 14, 13, 13, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AAC, 52000, 60000, 16000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_SWITCH_LRC, 1}, + {CODEC_AAC, 60000, 76000, 16000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 76000, 128001, 16000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 22.05/44.1 kHz dual rate */ + {CODEC_AAC, 16000, 24000, 22050, 2, 2, 1, 1, 0, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 24000, 28000, 22050, 2, 5, 4, 6, 5, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 28000, 32000, 22050, 2, 5, 4, 8, 7, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 32000, 36000, 22050, 2, 7, 6, 8, 7, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 36000, 44000, 22050, 2, 10, 10, 9, 9, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 44000, 52000, 22050, 2, 12, 12, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 52000, 60000, 22050, 2, 13, 13, 10, 10, 3, 0, -3, + SBR_SWITCH_LRC, 1}, + {CODEC_AAC, 60000, 76000, 22050, 2, 14, 14, 12, 12, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 76000, 128001, 22050, 2, 14, 14, 12, 12, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 24/48 kHz dual rate */ + {CODEC_AAC, 16000, 24000, 24000, 2, 2, 1, 1, 0, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 24000, 28000, 24000, 2, 5, 5, 6, 6, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 28000, 36000, 24000, 2, 7, 6, 8, 7, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 36000, 44000, 24000, 2, 10, 10, 9, 9, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 44000, 52000, 24000, 2, 12, 12, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 52000, 60000, 24000, 2, 13, 13, 10, 10, 3, 0, -3, + SBR_SWITCH_LRC, 1}, + {CODEC_AAC, 60000, 76000, 24000, 2, 14, 14, 12, 12, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 76000, 128001, 24000, 2, 14, 14, 12, 12, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 32/64 kHz dual rate */ + {CODEC_AAC, 32000, 60000, 32000, 2, 4, 4, 4, 4, 2, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 60000, 80000, 32000, 2, 7, 7, 6, 6, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 80000, 112000, 32000, 2, 9, 9, 8, 8, 3, 0, -3, SBR_LEFT_RIGHT, + 1}, + {CODEC_AAC, 112000, 144000, 32000, 2, 11, 11, 10, 10, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 144000, 256001, 32000, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 44.1/88.2 kHz dual rate */ + {CODEC_AAC, 32000, 60000, 44100, 2, 4, 4, 4, 4, 2, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 60000, 80000, 44100, 2, 7, 7, 6, 6, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 80000, 112000, 44100, 2, 9, 9, 8, 8, 3, 0, -3, SBR_LEFT_RIGHT, + 1}, + {CODEC_AAC, 112000, 144000, 44100, 2, 11, 11, 10, 10, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 144000, 256001, 44100, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 48/96 kHz dual rate */ + {CODEC_AAC, 36000, 60000, 48000, 2, 4, 4, 9, 9, 2, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 60000, 80000, 48000, 2, 7, 7, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 80000, 112000, 48000, 2, 9, 9, 10, 10, 3, 0, -3, SBR_LEFT_RIGHT, + 1}, + {CODEC_AAC, 112000, 144000, 48000, 2, 11, 11, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 144000, 256001, 48000, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /** AAC LOW DELAY SECTION **/ + + /* 24 kHz dual rate - 12kHz singlerate is not allowed (deactivated in + FDKsbrEnc_IsSbrSettingAvail()) */ + {CODEC_AACLD, 8000, 32000, 12000, 1, 1, 1, 0, 0, 1, 0, 6, SBR_MONO, 3}, + + /*** mono ***/ + /* 16/32 kHz dual rate */ + {CODEC_AACLD, 16000, 18000, 16000, 1, 4, 5, 9, 7, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AACLD, 18000, 22000, 16000, 1, 7, 7, 12, 12, 1, 6, 9, SBR_MONO, 3}, + {CODEC_AACLD, 22000, 28000, 16000, 1, 6, 6, 9, 9, 2, 3, 6, SBR_MONO, 3}, + {CODEC_AACLD, 28000, 36000, 16000, 1, 8, 8, 12, 7, 2, 9, 12, SBR_MONO, 3}, + {CODEC_AACLD, 36000, 44000, 16000, 1, 10, 14, 12, 13, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 44000, 64001, 16000, 1, 11, 14, 13, 13, 2, 0, 3, SBR_MONO, 1}, + + /* 22.05/44.1 kHz dual rate */ + {CODEC_AACLD, 18000, 22000, 22050, 1, 4, 4, 5, 5, 2, 0, 6, SBR_MONO, 3}, + {CODEC_AACLD, 22000, 28000, 22050, 1, 5, 5, 6, 6, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AACLD, 28000, 36000, 22050, 1, 7, 8, 8, 8, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AACLD, 36000, 44000, 22050, 1, 9, 9, 9, 9, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 44000, 52000, 22050, 1, 12, 11, 11, 11, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 52000, 64001, 22050, 1, 13, 11, 11, 10, 2, 0, 3, SBR_MONO, 1}, + + /* 24/48 kHz dual rate */ + {CODEC_AACLD, 20000, 22000, 24000, 1, 3, 4, 8, 8, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AACLD, 22000, 28000, 24000, 1, 3, 8, 8, 7, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AACLD, 28000, 36000, 24000, 1, 4, 8, 8, 7, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AACLD, 36000, 56000, 24000, 1, 8, 9, 9, 8, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 56000, 64001, 24000, 1, 13, 11, 11, 10, 2, 0, 3, SBR_MONO, 1}, + + /* 32/64 kHz dual rate */ + {CODEC_AACLD, 24000, 36000, 32000, 1, 4, 4, 4, 4, 2, 0, 3, SBR_MONO, 3}, + {CODEC_AACLD, 36000, 60000, 32000, 1, 7, 7, 6, 6, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AACLD, 60000, 72000, 32000, 1, 9, 9, 8, 8, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 72000, 100000, 32000, 1, 11, 11, 10, 10, 2, 0, 3, SBR_MONO, + 1}, + {CODEC_AACLD, 100000, 160001, 32000, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, + 1}, + + /* 44/88 kHz dual rate */ + {CODEC_AACLD, 36000, 60000, 44100, 1, 8, 7, 6, 9, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AACLD, 60000, 72000, 44100, 1, 9, 9, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 72000, 100000, 44100, 1, 11, 11, 11, 11, 2, 0, 3, SBR_MONO, + 1}, + {CODEC_AACLD, 100000, 160001, 44100, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, + 1}, + + /* 48/96 kHz dual rate */ /* 32 and 40kbps line tuned for dual-rate SBR + */ + {CODEC_AACLD, 36000, 60000, 48000, 1, 4, 7, 4, 4, 2, 0, 3, SBR_MONO, 3}, + {CODEC_AACLD, 60000, 72000, 48000, 1, 9, 9, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 72000, 100000, 48000, 1, 11, 11, 11, 11, 2, 0, 3, SBR_MONO, + 1}, + {CODEC_AACLD, 100000, 160001, 48000, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, + 1}, + + /*** stereo ***/ + /* 16/32 kHz dual rate */ + {CODEC_AACLD, 32000, 36000, 16000, 2, 10, 9, 12, 11, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AACLD, 36000, 44000, 16000, 2, 13, 13, 13, 13, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AACLD, 44000, 52000, 16000, 2, 10, 9, 11, 9, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AACLD, 52000, 60000, 16000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_SWITCH_LRC, 1}, + {CODEC_AACLD, 60000, 76000, 16000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 76000, 128001, 16000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 22.05/44.1 kHz dual rate */ + {CODEC_AACLD, 32000, 36000, 22050, 2, 5, 4, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 36000, 44000, 22050, 2, 5, 8, 8, 8, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 44000, 52000, 22050, 2, 7, 10, 8, 8, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 52000, 60000, 22050, 2, 9, 11, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, + 1}, + {CODEC_AACLD, 60000, 76000, 22050, 2, 10, 12, 10, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 76000, 82000, 22050, 2, 12, 12, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 82000, 128001, 22050, 2, 13, 12, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 24/48 kHz dual rate */ + {CODEC_AACLD, 32000, 36000, 24000, 2, 5, 4, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 36000, 44000, 24000, 2, 4, 8, 8, 8, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 44000, 52000, 24000, 2, 6, 10, 8, 8, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 52000, 60000, 24000, 2, 9, 11, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, + 1}, + {CODEC_AACLD, 60000, 76000, 24000, 2, 11, 12, 10, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 76000, 88000, 24000, 2, 12, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 88000, 128001, 24000, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 32/64 kHz dual rate */ + {CODEC_AACLD, 60000, 80000, 32000, 2, 7, 7, 6, 6, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 80000, 112000, 32000, 2, 9, 9, 8, 8, 3, 0, -3, SBR_LEFT_RIGHT, + 1}, + {CODEC_AACLD, 112000, 144000, 32000, 2, 11, 11, 10, 10, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 144000, 256001, 32000, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 44.1/88.2 kHz dual rate */ + {CODEC_AACLD, 60000, 80000, 44100, 2, 7, 7, 6, 6, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 80000, 112000, 44100, 2, 10, 10, 8, 8, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 112000, 144000, 44100, 2, 12, 12, 10, 10, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 144000, 256001, 44100, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 48/96 kHz dual rate */ + {CODEC_AACLD, 60000, 80000, 48000, 2, 7, 7, 10, 10, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AACLD, 80000, 112000, 48000, 2, 9, 9, 10, 10, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 112000, 144000, 48000, 2, 11, 11, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 144000, 176000, 48000, 2, 12, 12, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 176000, 256001, 48000, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + +}; + +const int sbrTuningTableSize = + sizeof(sbrTuningTable) / sizeof(sbrTuningTable[0]); + +const psTuningTable_t psTuningTable[4] = { + {8000, 22000, PSENC_STEREO_BANDS_10, PSENC_NENV_1, + FL2FXCONST_DBL(3.0f / 4.0f)}, + {22000, 28000, PSENC_STEREO_BANDS_20, PSENC_NENV_1, + FL2FXCONST_DBL(2.0f / 4.0f)}, + {28000, 36000, PSENC_STEREO_BANDS_20, PSENC_NENV_2, + FL2FXCONST_DBL(1.5f / 4.0f)}, + {36000, 160001, PSENC_STEREO_BANDS_20, PSENC_NENV_4, + FL2FXCONST_DBL(1.1f / 4.0f)}, +}; + +//@} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_rom.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_rom.h new file mode 100644 index 0000000000000..18c1fb9a67b97 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/sbrenc_rom.h @@ -0,0 +1,145 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! +\file +\brief Declaration of constant tables +$Revision: 92790 $ +*/ +#ifndef SBRENC_ROM_H +#define SBRENC_ROM_H + +#include "sbr_def.h" +#include "sbr_encoder.h" + +#include "ps_main.h" + +/* + huffman tables +*/ +extern const INT v_Huff_envelopeLevelC10T[121]; +extern const UCHAR v_Huff_envelopeLevelL10T[121]; +extern const INT v_Huff_envelopeLevelC10F[121]; +extern const UCHAR v_Huff_envelopeLevelL10F[121]; +extern const INT bookSbrEnvBalanceC10T[49]; +extern const UCHAR bookSbrEnvBalanceL10T[49]; +extern const INT bookSbrEnvBalanceC10F[49]; +extern const UCHAR bookSbrEnvBalanceL10F[49]; +extern const INT v_Huff_envelopeLevelC11T[63]; +extern const UCHAR v_Huff_envelopeLevelL11T[63]; +extern const INT v_Huff_envelopeLevelC11F[63]; +extern const UCHAR v_Huff_envelopeLevelL11F[63]; +extern const INT bookSbrEnvBalanceC11T[25]; +extern const UCHAR bookSbrEnvBalanceL11T[25]; +extern const INT bookSbrEnvBalanceC11F[25]; +extern const UCHAR bookSbrEnvBalanceL11F[25]; +extern const INT v_Huff_NoiseLevelC11T[63]; +extern const UCHAR v_Huff_NoiseLevelL11T[63]; +extern const INT bookSbrNoiseBalanceC11T[25]; +extern const UCHAR bookSbrNoiseBalanceL11T[25]; + +extern const sbrTuningTable_t sbrTuningTable[]; +extern const int sbrTuningTableSize; + +extern const psTuningTable_t psTuningTable[4]; + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ton_corr.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ton_corr.cpp new file mode 100644 index 0000000000000..1c050e2aeb216 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ton_corr.cpp @@ -0,0 +1,891 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "ton_corr.h" + +#include "sbrenc_ram.h" +#include "sbr_misc.h" +#include "genericStds.h" +#include "autocorr2nd.h" + +#define BAND_V_SIZE 32 +#define NUM_V_COMBINE \ + 8 /* Must be a divisor of 64 and fulfill the ASSERTs below */ + +/**************************************************************************/ +/*! + \brief Calculates the tonal to noise ration for different frequency bands + and time segments. + + The ratio between the predicted energy (tonal energy A) and the total + energy (A + B) is calculated. This is converted to the ratio between + the predicted energy (tonal energy A) and the non-predictable energy + (noise energy B). Hence the quota-matrix contains A/B = q/(1-q). + + The samples in nrgVector are scaled by 1.0/16.0 + The samples in pNrgVectorFreq are scaled by 1.0/2.0 + The samples in quotaMatrix are scaled by RELAXATION + + \return none. + +*/ +/**************************************************************************/ + +void FDKsbrEnc_CalculateTonalityQuotas( + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + FIXP_DBL **RESTRICT + sourceBufferReal, /*!< The real part of the QMF-matrix. */ + FIXP_DBL **RESTRICT + sourceBufferImag, /*!< The imaginary part of the QMF-matrix. */ + INT usb, /*!< upper side band, highest + 1 QMF band in the SBR range. */ + INT qmfScale /*!< sclefactor of QMF subsamples */ +) { + INT i, k, r, r2, timeIndex, autoCorrScaling; + + INT startIndexMatrix = hTonCorr->startIndexMatrix; + INT totNoEst = hTonCorr->numberOfEstimates; + INT noEstPerFrame = hTonCorr->numberOfEstimatesPerFrame; + INT move = hTonCorr->move; + INT noQmfChannels = hTonCorr->noQmfChannels; /* Number of Bands */ + INT buffLen = hTonCorr->bufferLength; /* Number of Slots */ + INT stepSize = hTonCorr->stepSize; + INT *pBlockLength = hTonCorr->lpcLength; + INT **RESTRICT signMatrix = hTonCorr->signMatrix; + FIXP_DBL *RESTRICT nrgVector = hTonCorr->nrgVector; + FIXP_DBL **RESTRICT quotaMatrix = hTonCorr->quotaMatrix; + FIXP_DBL *RESTRICT pNrgVectorFreq = hTonCorr->nrgVectorFreq; + + FIXP_DBL *realBuf; + FIXP_DBL *imagBuf; + + FIXP_DBL alphar[2], alphai[2], fac; + + C_ALLOC_SCRATCH_START(ac, ACORR_COEFS, 1) + C_ALLOC_SCRATCH_START(realBufRef, FIXP_DBL, 2 * BAND_V_SIZE * NUM_V_COMBINE) + realBuf = realBufRef; + imagBuf = realBuf + BAND_V_SIZE * NUM_V_COMBINE; + + FDK_ASSERT(buffLen <= BAND_V_SIZE); + FDK_ASSERT(sizeof(FIXP_DBL) * NUM_V_COMBINE * BAND_V_SIZE * 2 < + (1024 * sizeof(FIXP_DBL) - sizeof(ACORR_COEFS))); + + /* + * Buffering of the quotaMatrix and the quotaMatrixTransp. + *********************************************************/ + for (i = 0; i < move; i++) { + FDKmemcpy(quotaMatrix[i], quotaMatrix[i + noEstPerFrame], + noQmfChannels * sizeof(FIXP_DBL)); + FDKmemcpy(signMatrix[i], signMatrix[i + noEstPerFrame], + noQmfChannels * sizeof(INT)); + } + + FDKmemmove(nrgVector, nrgVector + noEstPerFrame, move * sizeof(FIXP_DBL)); + FDKmemclear(nrgVector + startIndexMatrix, + (totNoEst - startIndexMatrix) * sizeof(FIXP_DBL)); + FDKmemclear(pNrgVectorFreq, noQmfChannels * sizeof(FIXP_DBL)); + + /* + * Calculate the quotas for the current time steps. + **************************************************/ + + for (r = 0; r < usb; r++) { + int blockLength; + + k = hTonCorr->nextSample; /* startSample */ + timeIndex = startIndexMatrix; + /* Copy as many as possible Band across all Slots at once */ + if (realBuf != realBufRef) { + realBuf -= BAND_V_SIZE; + imagBuf -= BAND_V_SIZE; + } else { + realBuf += BAND_V_SIZE * (NUM_V_COMBINE - 1); + imagBuf += BAND_V_SIZE * (NUM_V_COMBINE - 1); + + for (i = 0; i < buffLen; i++) { + int v; + FIXP_DBL *ptr; + ptr = realBuf + i; + for (v = 0; v < NUM_V_COMBINE; v++) { + ptr[0] = sourceBufferReal[i][r + v]; + ptr[0 + BAND_V_SIZE * NUM_V_COMBINE] = sourceBufferImag[i][r + v]; + ptr -= BAND_V_SIZE; + } + } + } + + blockLength = pBlockLength[0]; + + while (k <= buffLen - blockLength) { + autoCorrScaling = fixMin( + getScalefactor(&realBuf[k - LPC_ORDER], LPC_ORDER + blockLength), + getScalefactor(&imagBuf[k - LPC_ORDER], LPC_ORDER + blockLength)); + autoCorrScaling = fixMax(0, autoCorrScaling - 1); + + scaleValues(&realBuf[k - LPC_ORDER], LPC_ORDER + blockLength, + autoCorrScaling); + scaleValues(&imagBuf[k - LPC_ORDER], LPC_ORDER + blockLength, + autoCorrScaling); + + autoCorrScaling <<= 1; /* consider qmf buffer scaling twice */ + autoCorrScaling += + autoCorr2nd_cplx(ac, realBuf + k, imagBuf + k, blockLength); + + if (ac->det == FL2FXCONST_DBL(0.0f)) { + alphar[1] = alphai[1] = FL2FXCONST_DBL(0.0f); + + alphar[0] = (ac->r01r) >> 2; + alphai[0] = (ac->r01i) >> 2; + + fac = fMultDiv2(ac->r00r, ac->r11r) >> 1; + } else { + alphar[1] = (fMultDiv2(ac->r01r, ac->r12r) >> 1) - + (fMultDiv2(ac->r01i, ac->r12i) >> 1) - + (fMultDiv2(ac->r02r, ac->r11r) >> 1); + alphai[1] = (fMultDiv2(ac->r01i, ac->r12r) >> 1) + + (fMultDiv2(ac->r01r, ac->r12i) >> 1) - + (fMultDiv2(ac->r02i, ac->r11r) >> 1); + + alphar[0] = (fMultDiv2(ac->r01r, ac->det) >> (ac->det_scale + 1)) + + fMult(alphar[1], ac->r12r) + fMult(alphai[1], ac->r12i); + alphai[0] = (fMultDiv2(ac->r01i, ac->det) >> (ac->det_scale + 1)) + + fMult(alphai[1], ac->r12r) - fMult(alphar[1], ac->r12i); + + fac = fMultDiv2(ac->r00r, fMult(ac->det, ac->r11r)) >> + (ac->det_scale + 1); + } + + if (fac == FL2FXCONST_DBL(0.0f)) { + quotaMatrix[timeIndex][r] = FL2FXCONST_DBL(0.0f); + signMatrix[timeIndex][r] = 0; + } else { + /* quotaMatrix is scaled with the factor RELAXATION + parse RELAXATION in fractional part and shift factor: 1/(1/0.524288 * + 2^RELAXATION_SHIFT) */ + FIXP_DBL tmp, num, denom; + INT numShift, denomShift, commonShift; + INT sign; + + num = fMultDiv2(alphar[0], ac->r01r) + fMultDiv2(alphai[0], ac->r01i) - + fMultDiv2(alphar[1], fMult(ac->r02r, ac->r11r)) - + fMultDiv2(alphai[1], fMult(ac->r02i, ac->r11r)); + num = fixp_abs(num); + + denom = (fac >> 1) + + (fMultDiv2(fac, RELAXATION_FRACT) >> RELAXATION_SHIFT) - num; + denom = fixp_abs(denom); + + num = fMult(num, RELAXATION_FRACT); + + numShift = CountLeadingBits(num) - 2; + num = scaleValue(num, numShift); + + denomShift = CountLeadingBits(denom); + denom = (FIXP_DBL)denom << denomShift; + + if ((num > FL2FXCONST_DBL(0.0f)) && (denom != FL2FXCONST_DBL(0.0f))) { + commonShift = + fixMin(numShift - denomShift + RELAXATION_SHIFT, DFRACT_BITS - 1); + if (commonShift < 0) { + commonShift = -commonShift; + tmp = schur_div(num, denom, 16); + commonShift = fixMin(commonShift, CountLeadingBits(tmp)); + quotaMatrix[timeIndex][r] = tmp << commonShift; + } else { + quotaMatrix[timeIndex][r] = + schur_div(num, denom, 16) >> commonShift; + } + } else { + quotaMatrix[timeIndex][r] = FL2FXCONST_DBL(0.0f); + } + + if (ac->r11r != FL2FXCONST_DBL(0.0f)) { + if (((ac->r01r >= FL2FXCONST_DBL(0.0f)) && + (ac->r11r >= FL2FXCONST_DBL(0.0f))) || + ((ac->r01r < FL2FXCONST_DBL(0.0f)) && + (ac->r11r < FL2FXCONST_DBL(0.0f)))) { + sign = 1; + } else { + sign = -1; + } + } else { + sign = 1; + } + + if (sign < 0) { + r2 = r; /* (INT) pow(-1, band); */ + } else { + r2 = r + 1; /* (INT) pow(-1, band+1); */ + } + signMatrix[timeIndex][r] = 1 - 2 * (r2 & 0x1); + } + + nrgVector[timeIndex] += + ((ac->r00r) >> + fixMin(DFRACT_BITS - 1, + (2 * qmfScale + autoCorrScaling + SCALE_NRGVEC))); + /* pNrgVectorFreq[r] finally has to be divided by noEstPerFrame, replaced + * division by shifting with one */ + pNrgVectorFreq[r] = + pNrgVectorFreq[r] + + ((ac->r00r) >> + fixMin(DFRACT_BITS - 1, + (2 * qmfScale + autoCorrScaling + SCALE_NRGVEC))); + + blockLength = pBlockLength[1]; + k += stepSize; + timeIndex++; + } + } + + C_ALLOC_SCRATCH_END(realBufRef, FIXP_DBL, 2 * BAND_V_SIZE * NUM_V_COMBINE) + C_ALLOC_SCRATCH_END(ac, ACORR_COEFS, 1) +} + +/**************************************************************************/ +/*! + \brief Extracts the parameters required in the decoder to obtain the + correct tonal to noise ratio after SBR. + + Estimates the tonal to noise ratio of the original signal (using LPC). + Predicts the tonal to noise ration of the SBR signal (in the decoder) by + patching the tonal to noise ratio values similar to the patching of the + lowband in the decoder. Given the tonal to noise ratio of the original + and the SBR signal, it estimates the required amount of inverse filtering, + additional noise as well as any additional sines. + + \return none. + +*/ +/**************************************************************************/ +void FDKsbrEnc_TonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INVF_MODE *infVec, /*!< Vector where the inverse filtering levels will be + stored. */ + FIXP_DBL *noiseLevels, /*!< Vector where the noise levels will be stored. */ + INT *missingHarmonicFlag, /*!< Flag set to one or zero, dependent on if any + strong sines are missing.*/ + UCHAR *missingHarmonicsIndex, /*!< Vector indicating where sines are + missing. */ + UCHAR *envelopeCompensation, /*!< Vector to store compensation values for + the energies in. */ + const SBR_FRAME_INFO *frameInfo, /*!< Frame info struct, contains the time + and frequency grid of the current + frame.*/ + UCHAR *transientInfo, /*!< Transient info.*/ + UCHAR *freqBandTable, /*!< Frequency band tables for high-res.*/ + INT nSfb, /*!< Number of scalefactor bands for high-res. */ + XPOS_MODE xposType, /*!< Type of transposer used in the decoder.*/ + UINT sbrSyntaxFlags) { + INT band; + INT transientFlag = transientInfo[1]; /*!< Flag indicating if a transient is + present in the current frame. */ + INT transientPos = transientInfo[0]; /*!< Position of the transient.*/ + INT transientFrame, transientFrameInvfEst; + INVF_MODE *infVecPtr; + + /* Determine if this is a frame where a transient starts... + + The detection of noise-floor, missing harmonics and invf_est, is not in sync + for the non-buf-opt decoder such as AAC. Hence we need to keep track on the + transient in the present frame as well as in the next. + */ + transientFrame = 0; + if (hTonCorr->transientNextFrame) { /* The transient was detected in the + previous frame, but is actually */ + transientFrame = 1; + hTonCorr->transientNextFrame = 0; + + if (transientFlag) { + if (transientPos + hTonCorr->transientPosOffset >= + frameInfo->borders[frameInfo->nEnvelopes]) { + hTonCorr->transientNextFrame = 1; + } + } + } else { + if (transientFlag) { + if (transientPos + hTonCorr->transientPosOffset < + frameInfo->borders[frameInfo->nEnvelopes]) { + transientFrame = 1; + hTonCorr->transientNextFrame = 0; + } else { + hTonCorr->transientNextFrame = 1; + } + } + } + transientFrameInvfEst = transientFrame; + + /* + Estimate the required invese filtereing level. + */ + if (hTonCorr->switchInverseFilt) + FDKsbrEnc_qmfInverseFilteringDetector( + &hTonCorr->sbrInvFilt, hTonCorr->quotaMatrix, hTonCorr->nrgVector, + hTonCorr->indexVector, hTonCorr->frameStartIndexInvfEst, + hTonCorr->numberOfEstimatesPerFrame + hTonCorr->frameStartIndexInvfEst, + transientFrameInvfEst, infVec); + + /* + Detect what tones will be missing. + */ + if (xposType == XPOS_LC) { + FDKsbrEnc_SbrMissingHarmonicsDetectorQmf( + &hTonCorr->sbrMissingHarmonicsDetector, hTonCorr->quotaMatrix, + hTonCorr->signMatrix, hTonCorr->indexVector, frameInfo, transientInfo, + missingHarmonicFlag, missingHarmonicsIndex, freqBandTable, nSfb, + envelopeCompensation, hTonCorr->nrgVectorFreq); + } else { + *missingHarmonicFlag = 0; + FDKmemclear(missingHarmonicsIndex, nSfb * sizeof(UCHAR)); + } + + /* + Noise floor estimation + */ + + infVecPtr = hTonCorr->sbrInvFilt.prevInvfMode; + + FDKsbrEnc_sbrNoiseFloorEstimateQmf( + &hTonCorr->sbrNoiseFloorEstimate, frameInfo, noiseLevels, + hTonCorr->quotaMatrix, hTonCorr->indexVector, *missingHarmonicFlag, + hTonCorr->frameStartIndex, hTonCorr->numberOfEstimatesPerFrame, + transientFrame, infVecPtr, sbrSyntaxFlags); + + /* Store the invfVec data for the next frame...*/ + for (band = 0; band < hTonCorr->sbrInvFilt.noDetectorBands; band++) { + hTonCorr->sbrInvFilt.prevInvfMode[band] = infVec[band]; + } +} + +/**************************************************************************/ +/*! + \brief Searches for the closest match in the frequency master table. + + + + \return closest entry. + +*/ +/**************************************************************************/ +static INT findClosestEntry(INT goalSb, UCHAR *v_k_master, INT numMaster, + INT direction) { + INT index; + + if (goalSb <= v_k_master[0]) return v_k_master[0]; + + if (goalSb >= v_k_master[numMaster]) return v_k_master[numMaster]; + + if (direction) { + index = 0; + while (v_k_master[index] < goalSb) { + index++; + } + } else { + index = numMaster; + while (v_k_master[index] > goalSb) { + index--; + } + } + + return v_k_master[index]; +} + +/**************************************************************************/ +/*! + \brief resets the patch + + + + \return errorCode, noError if successful. + +*/ +/**************************************************************************/ +static INT resetPatch( + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INT xposctrl, /*!< Different patch modes. */ + INT highBandStartSb, /*!< Start band of the SBR range. */ + UCHAR *v_k_master, /*!< Master frequency table from which all other table + are derived.*/ + INT numMaster, /*!< Number of elements in the master table. */ + INT fs, /*!< Sampling frequency. */ + INT noChannels) /*!< Number of QMF-channels. */ +{ + INT patch, k, i; + INT targetStopBand; + + PATCH_PARAM *patchParam = hTonCorr->patchParam; + + INT sbGuard = hTonCorr->guard; + INT sourceStartBand; + INT patchDistance; + INT numBandsInPatch; + + INT lsb = + v_k_master[0]; /* Lowest subband related to the synthesis filterbank */ + INT usb = v_k_master[numMaster]; /* Stop subband related to the synthesis + filterbank */ + INT xoverOffset = + highBandStartSb - + v_k_master[0]; /* Calculate distance in subbands between k0 and kx */ + + INT goalSb; + + /* + * Initialize the patching parameter + */ + + if (xposctrl == 1) { + lsb += xoverOffset; + xoverOffset = 0; + } + + goalSb = (INT)((2 * noChannels * 16000 + (fs >> 1)) / fs); /* 16 kHz band */ + goalSb = findClosestEntry(goalSb, v_k_master, numMaster, + 1); /* Adapt region to master-table */ + + /* First patch */ + sourceStartBand = hTonCorr->shiftStartSb + xoverOffset; + targetStopBand = lsb + xoverOffset; + + /* even (odd) numbered channel must be patched to even (odd) numbered channel + */ + patch = 0; + while (targetStopBand < usb) { + /* To many patches */ + if (patch >= MAX_NUM_PATCHES) return (1); /*Number of patches to high */ + + patchParam[patch].guardStartBand = targetStopBand; + targetStopBand += sbGuard; + patchParam[patch].targetStartBand = targetStopBand; + + numBandsInPatch = + goalSb - targetStopBand; /* get the desired range of the patch */ + + if (numBandsInPatch >= lsb - sourceStartBand) { + /* desired number bands are not available -> patch whole source range */ + patchDistance = + targetStopBand - sourceStartBand; /* get the targetOffset */ + patchDistance = + patchDistance & ~1; /* rounding off odd numbers and make all even */ + numBandsInPatch = lsb - (targetStopBand - patchDistance); + numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch, + v_k_master, numMaster, 0) - + targetStopBand; /* Adapt region to master-table */ + } + + /* desired number bands are available -> get the minimal even patching + * distance */ + patchDistance = + numBandsInPatch + targetStopBand - lsb; /* get minimal distance */ + patchDistance = (patchDistance + 1) & + ~1; /* rounding up odd numbers and make all even */ + + if (numBandsInPatch <= 0) { + patch--; + } else { + patchParam[patch].sourceStartBand = targetStopBand - patchDistance; + patchParam[patch].targetBandOffs = patchDistance; + patchParam[patch].numBandsInPatch = numBandsInPatch; + patchParam[patch].sourceStopBand = + patchParam[patch].sourceStartBand + numBandsInPatch; + + targetStopBand += patchParam[patch].numBandsInPatch; + } + + /* All patches but first */ + sourceStartBand = hTonCorr->shiftStartSb; + + /* Check if we are close to goalSb */ + if (fixp_abs(targetStopBand - goalSb) < 3) { + goalSb = usb; + } + + patch++; + } + + patch--; + + /* if highest patch contains less than three subband: skip it */ + if (patchParam[patch].numBandsInPatch < 3 && patch > 0) { + patch--; + } + + hTonCorr->noOfPatches = patch + 1; + + /* Assign the index-vector, so we know where to look for the high-band. + -1 represents a guard-band. */ + for (k = 0; k < hTonCorr->patchParam[0].guardStartBand; k++) + hTonCorr->indexVector[k] = k; + + for (i = 0; i < hTonCorr->noOfPatches; i++) { + INT sourceStart = hTonCorr->patchParam[i].sourceStartBand; + INT targetStart = hTonCorr->patchParam[i].targetStartBand; + INT numberOfBands = hTonCorr->patchParam[i].numBandsInPatch; + INT startGuardBand = hTonCorr->patchParam[i].guardStartBand; + + for (k = 0; k < (targetStart - startGuardBand); k++) + hTonCorr->indexVector[startGuardBand + k] = -1; + + for (k = 0; k < numberOfBands; k++) + hTonCorr->indexVector[targetStart + k] = sourceStart + k; + } + + return (0); +} + +/**************************************************************************/ +/*! + \brief Creates an instance of the tonality correction parameter module. + + The module includes modules for inverse filtering level estimation, + missing harmonics detection and noise floor level estimation. + + \return errorCode, noError if successful. +*/ +/**************************************************************************/ +INT FDKsbrEnc_CreateTonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST + hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */ + INT chan) /*!< Channel index, needed for mem allocation */ +{ + INT i; + FIXP_DBL *quotaMatrix = GetRam_Sbr_quotaMatrix(chan); + INT *signMatrix = GetRam_Sbr_signMatrix(chan); + + if ((NULL == quotaMatrix) || (NULL == signMatrix)) { + goto bail; + } + + FDKmemclear(hTonCorr, sizeof(SBR_TON_CORR_EST)); + + for (i = 0; i < MAX_NO_OF_ESTIMATES; i++) { + hTonCorr->quotaMatrix[i] = quotaMatrix + (i * 64); + hTonCorr->signMatrix[i] = signMatrix + (i * 64); + } + + if (0 != FDKsbrEnc_CreateSbrMissingHarmonicsDetector( + &hTonCorr->sbrMissingHarmonicsDetector, chan)) { + goto bail; + } + + return 0; + +bail: + hTonCorr->quotaMatrix[0] = quotaMatrix; + hTonCorr->signMatrix[0] = signMatrix; + + FDKsbrEnc_DeleteTonCorrParamExtr(hTonCorr); + + return -1; +} + +/**************************************************************************/ +/*! + \brief Initialize an instance of the tonality correction parameter module. + + The module includes modules for inverse filtering level estimation, + missing harmonics detection and noise floor level estimation. + + \return errorCode, noError if successful. +*/ +/**************************************************************************/ +INT FDKsbrEnc_InitTonCorrParamExtr( + INT frameSize, /*!< Current SBR frame size. */ + HANDLE_SBR_TON_CORR_EST + hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */ + HANDLE_SBR_CONFIG_DATA + sbrCfg, /*!< Pointer to SBR configuration parameters. */ + INT timeSlots, /*!< Number of time-slots per frame */ + INT xposCtrl, /*!< Different patch modes. */ + INT ana_max_level, /*!< Maximum level of the adaptive noise. */ + INT noiseBands, /*!< Number of noise bands per octave. */ + INT noiseFloorOffset, /*!< Noise floor offset. */ + UINT useSpeechConfig) /*!< Speech or music tuning. */ +{ + INT nCols = sbrCfg->noQmfSlots; + INT fs = sbrCfg->sampleFreq; + INT noQmfChannels = sbrCfg->noQmfBands; + + INT highBandStartSb = sbrCfg->freqBandTable[LOW_RES][0]; + UCHAR *v_k_master = sbrCfg->v_k_master; + INT numMaster = sbrCfg->num_Master; + + UCHAR **freqBandTable = sbrCfg->freqBandTable; + INT *nSfb = sbrCfg->nSfb; + + INT i; + + /* + Reset the patching and allocate memory for the quota matrix. + Assuming parameters for the LPC analysis. + */ + if (sbrCfg->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + switch (timeSlots) { + case NUMBER_TIME_SLOTS_1920: + hTonCorr->lpcLength[0] = 8 - LPC_ORDER; + hTonCorr->lpcLength[1] = 7 - LPC_ORDER; + hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD; + hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 7 */ + hTonCorr->frameStartIndexInvfEst = 0; + hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; + break; + case NUMBER_TIME_SLOTS_2048: + hTonCorr->lpcLength[0] = 8 - LPC_ORDER; + hTonCorr->lpcLength[1] = 8 - LPC_ORDER; + hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD; + hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 8 */ + hTonCorr->frameStartIndexInvfEst = 0; + hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; + break; + } + } else + switch (timeSlots) { + case NUMBER_TIME_SLOTS_2048: + hTonCorr->lpcLength[0] = 16 - LPC_ORDER; /* blockLength[0] */ + hTonCorr->lpcLength[1] = 16 - LPC_ORDER; /* blockLength[0] */ + hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LC; + hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 16; + hTonCorr->frameStartIndexInvfEst = 0; + hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_2048; + break; + case NUMBER_TIME_SLOTS_1920: + hTonCorr->lpcLength[0] = 15 - LPC_ORDER; /* blockLength[0] */ + hTonCorr->lpcLength[1] = 15 - LPC_ORDER; /* blockLength[0] */ + hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LC; + hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 15; + hTonCorr->frameStartIndexInvfEst = 0; + hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_1920; + break; + default: + return -1; + } + + hTonCorr->bufferLength = nCols; + hTonCorr->stepSize = + hTonCorr->lpcLength[0] + LPC_ORDER; /* stepSize[0] implicitly 0. */ + + hTonCorr->nextSample = LPC_ORDER; /* firstSample */ + hTonCorr->move = hTonCorr->numberOfEstimates - + hTonCorr->numberOfEstimatesPerFrame; /* Number of estimates + to move when + buffering.*/ + if (hTonCorr->move < 0) { + return -1; + } + hTonCorr->startIndexMatrix = + hTonCorr->numberOfEstimates - + hTonCorr->numberOfEstimatesPerFrame; /* Where to store the latest + estimations in the tonality + Matrix.*/ + hTonCorr->frameStartIndex = 0; /* Where in the tonality matrix the current + frame (to be sent to the decoder) starts. */ + hTonCorr->prevTransientFlag = 0; + hTonCorr->transientNextFrame = 0; + + hTonCorr->noQmfChannels = noQmfChannels; + + for (i = 0; i < hTonCorr->numberOfEstimates; i++) { + FDKmemclear(hTonCorr->quotaMatrix[i], sizeof(FIXP_DBL) * noQmfChannels); + FDKmemclear(hTonCorr->signMatrix[i], sizeof(INT) * noQmfChannels); + } + + /* Reset the patch.*/ + hTonCorr->guard = 0; + hTonCorr->shiftStartSb = 1; + + if (resetPatch(hTonCorr, xposCtrl, highBandStartSb, v_k_master, numMaster, fs, + noQmfChannels)) + return (1); + + if (FDKsbrEnc_InitSbrNoiseFloorEstimate( + &hTonCorr->sbrNoiseFloorEstimate, ana_max_level, freqBandTable[LO], + nSfb[LO], noiseBands, noiseFloorOffset, timeSlots, useSpeechConfig)) + return (1); + + if (FDKsbrEnc_initInvFiltDetector( + &hTonCorr->sbrInvFilt, + hTonCorr->sbrNoiseFloorEstimate.freqBandTableQmf, + hTonCorr->sbrNoiseFloorEstimate.noNoiseBands, useSpeechConfig)) + return (1); + + if (FDKsbrEnc_InitSbrMissingHarmonicsDetector( + &hTonCorr->sbrMissingHarmonicsDetector, fs, frameSize, nSfb[HI], + noQmfChannels, hTonCorr->numberOfEstimates, hTonCorr->move, + hTonCorr->numberOfEstimatesPerFrame, sbrCfg->sbrSyntaxFlags)) + return (1); + + return (0); +} + +/**************************************************************************/ +/*! + \brief resets tonality correction parameter module. + + + + \return errorCode, noError if successful. + +*/ +/**************************************************************************/ +INT FDKsbrEnc_ResetTonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INT xposctrl, /*!< Different patch modes. */ + INT highBandStartSb, /*!< Start band of the SBR range. */ + UCHAR *v_k_master, /*!< Master frequency table from which all other table + are derived.*/ + INT numMaster, /*!< Number of elements in the master table. */ + INT fs, /*!< Sampling frequency (of the SBR part). */ + UCHAR * + *freqBandTable, /*!< Frequency band table for low-res and high-res. */ + INT *nSfb, /*!< Number of frequency bands (hig-res and low-res). */ + INT noQmfChannels /*!< Number of QMF channels. */ +) { + /* Reset the patch.*/ + hTonCorr->guard = 0; + hTonCorr->shiftStartSb = 1; + + if (resetPatch(hTonCorr, xposctrl, highBandStartSb, v_k_master, numMaster, fs, + noQmfChannels)) + return (1); + + /* Reset the noise floor estimate.*/ + if (FDKsbrEnc_resetSbrNoiseFloorEstimate(&hTonCorr->sbrNoiseFloorEstimate, + freqBandTable[LO], nSfb[LO])) + return (1); + + /* + Reset the inveerse filtereing detector. + */ + if (FDKsbrEnc_resetInvFiltDetector( + &hTonCorr->sbrInvFilt, + hTonCorr->sbrNoiseFloorEstimate.freqBandTableQmf, + hTonCorr->sbrNoiseFloorEstimate.noNoiseBands)) + return (1); + /* Reset the missing harmonics detector. */ + if (FDKsbrEnc_ResetSbrMissingHarmonicsDetector( + &hTonCorr->sbrMissingHarmonicsDetector, nSfb[HI])) + return (1); + + return (0); +} + +/**************************************************************************/ +/*! + \brief Deletes the tonality correction paramtere module. + + + + \return none + +*/ +/**************************************************************************/ +void FDKsbrEnc_DeleteTonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST hTonCorr) /*!< Handle to SBR_TON_CORR struct. */ +{ + if (hTonCorr) { + FreeRam_Sbr_quotaMatrix(hTonCorr->quotaMatrix); + + FreeRam_Sbr_signMatrix(hTonCorr->signMatrix); + + FDKsbrEnc_DeleteSbrMissingHarmonicsDetector( + &hTonCorr->sbrMissingHarmonicsDetector); + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ton_corr.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ton_corr.h new file mode 100644 index 0000000000000..91aa278522532 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/ton_corr.h @@ -0,0 +1,258 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief General tonality correction detector module. +*/ +#ifndef TON_CORR_H +#define TON_CORR_H + +#include "sbr_encoder.h" +#include "mh_det.h" +#include "nf_est.h" +#include "invf_est.h" + +#define MAX_NUM_PATCHES 6 +#define SCALE_NRGVEC 4 + +/** parameter set for one single patch */ +typedef struct { + INT sourceStartBand; /*!< first band in lowbands where to take the samples + from */ + INT sourceStopBand; /*!< first band in lowbands which is not included in the + patch anymore */ + INT guardStartBand; /*!< first band in highbands to be filled with zeros in + order to reduce interferences between patches */ + INT targetStartBand; /*!< first band in highbands to be filled with whitened + lowband signal */ + INT targetBandOffs; /*!< difference between 'startTargetBand' and + 'startSourceBand' */ + INT numBandsInPatch; /*!< number of consecutive bands in this one patch */ +} PATCH_PARAM; + +typedef struct { + INT switchInverseFilt; /*!< Flag to enable dynamic adaption of invf. detection + */ + INT noQmfChannels; + INT bufferLength; /*!< Length of the r and i buffers. */ + INT stepSize; /*!< Stride for the lpc estimate. */ + INT numberOfEstimates; /*!< The total number of estiamtes, available in the + quotaMatrix.*/ + UINT numberOfEstimatesPerFrame; /*!< The number of estimates per frame + available in the quotaMatrix.*/ + INT lpcLength[2]; /*!< Segment length used for second order LPC analysis.*/ + INT nextSample; /*!< Where to start the LPC analysis of the current frame.*/ + INT move; /*!< How many estimates to move in the quotaMatrix, when buffering. + */ + INT frameStartIndex; /*!< The start index for the current frame in the r and i + buffers. */ + INT startIndexMatrix; /*!< The start index for the current frame in the + quotaMatrix. */ + INT frameStartIndexInvfEst; /*!< The start index of the inverse filtering, not + the same as the others, dependent on what + decoder is used (buffer opt, or no buffer opt). + */ + INT prevTransientFlag; /*!< The transisent flag (from the transient detector) + for the previous frame. */ + INT transientNextFrame; /*!< Flag to indicate that the transient will show up + in the next frame. */ + INT transientPosOffset; /*!< An offset value to match the transient pos as + calculated by the transient detector with the + actual position in the frame.*/ + + INT* signMatrix[MAX_NO_OF_ESTIMATES]; /*!< Matrix holding the sign of each + channe, i.e. indicating in what part + of a QMF channel a possible sine is. + */ + + FIXP_DBL* quotaMatrix[MAX_NO_OF_ESTIMATES]; /*!< Matrix holding the quota + values for all estimates, all + channels. */ + + FIXP_DBL nrgVector[MAX_NO_OF_ESTIMATES]; /*!< Vector holding the averaged + energies for every QMF band. */ + FIXP_DBL nrgVectorFreq[64]; /*!< Vector holding the averaged energies for + every QMF channel */ + + SCHAR indexVector[64]; /*!< Index vector poINTing to the correct lowband + channel, when indexing a highband channel, -1 + represents a guard band */ + PATCH_PARAM + patchParam[MAX_NUM_PATCHES]; /*!< new parameter set for patching */ + INT guard; /*!< number of guardbands between every patch */ + INT shiftStartSb; /*!< lowest subband of source range to be included in the + patches */ + INT noOfPatches; /*!< number of patches */ + + SBR_MISSING_HARMONICS_DETECTOR + sbrMissingHarmonicsDetector; /*!< SBR_MISSING_HARMONICS_DETECTOR struct. + */ + SBR_NOISE_FLOOR_ESTIMATE + sbrNoiseFloorEstimate; /*!< SBR_NOISE_FLOOR_ESTIMATE struct. */ + SBR_INV_FILT_EST sbrInvFilt; /*!< SBR_INV_FILT_EST struct. */ +} SBR_TON_CORR_EST; + +typedef SBR_TON_CORR_EST* HANDLE_SBR_TON_CORR_EST; + +void FDKsbrEnc_TonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INVF_MODE* infVec, /*!< Vector where the inverse filtering levels will be + stored. */ + FIXP_DBL* noiseLevels, /*!< Vector where the noise levels will be stored. */ + INT* missingHarmonicFlag, /*!< Flag set to one or zero, dependent on if any + strong sines are missing.*/ + UCHAR* missingHarmonicsIndex, /*!< Vector indicating where sines are + missing. */ + UCHAR* envelopeCompensation, /*!< Vector to store compensation values for + the energies in. */ + const SBR_FRAME_INFO* frameInfo, /*!< Frame info struct, contains the time + and frequency grid of the current + frame.*/ + UCHAR* transientInfo, /*!< Transient info.*/ + UCHAR* freqBandTable, /*!< Frequency band tables for high-res.*/ + INT nSfb, /*!< Number of scalefactor bands for high-res. */ + XPOS_MODE xposType, /*!< Type of transposer used in the decoder.*/ + UINT sbrSyntaxFlags); + +INT FDKsbrEnc_CreateTonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST + hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */ + INT chan); /*!< Channel index, needed for mem allocation */ + +INT FDKsbrEnc_InitTonCorrParamExtr( + INT frameSize, /*!< Current SBR frame size. */ + HANDLE_SBR_TON_CORR_EST + hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */ + HANDLE_SBR_CONFIG_DATA + sbrCfg, /*!< Pointer to SBR configuration parameters. */ + INT timeSlots, /*!< Number of time-slots per frame */ + INT xposCtrl, /*!< Different patch modes. */ + INT ana_max_level, /*!< Maximum level of the adaptive noise. */ + INT noiseBands, /*!< Number of noise bands per octave. */ + INT noiseFloorOffset, /*!< Noise floor offset. */ + UINT useSpeechConfig /*!< Speech or music tuning. */ +); + +void FDKsbrEnc_DeleteTonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST hTonCorr); /*!< Handle to SBR_TON_CORR struct. */ + +void FDKsbrEnc_CalculateTonalityQuotas( + HANDLE_SBR_TON_CORR_EST hTonCorr, FIXP_DBL** sourceBufferReal, + FIXP_DBL** sourceBufferImag, INT usb, + INT qmfScale /*!< sclefactor of QMF subsamples */ +); + +INT FDKsbrEnc_ResetTonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INT xposctrl, /*!< Different patch modes. */ + INT highBandStartSb, /*!< Start band of the SBR range. */ + UCHAR* v_k_master, /*!< Master frequency table from which all other table + are derived.*/ + INT numMaster, /*!< Number of elements in the master table. */ + INT fs, /*!< Sampling frequency (of the SBR part). */ + UCHAR** + freqBandTable, /*!< Frequency band table for low-res and high-res. */ + INT* nSfb, /*!< Number of frequency bands (hig-res and low-res). */ + INT noQmfChannels /*!< Number of QMF channels. */ +); +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/tran_det.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/tran_det.cpp new file mode 100644 index 0000000000000..3b6765a64f245 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/tran_det.cpp @@ -0,0 +1,1092 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): Tobias Chalupka + + Description: SBR encoder transient detector + +*******************************************************************************/ + +#include "tran_det.h" + +#include "fram_gen.h" +#include "sbrenc_ram.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +#define NORM_QMF_ENERGY 9.31322574615479E-10 /* 2^-30 */ + +/* static FIXP_DBL ABS_THRES = fixMax( FL2FXCONST_DBL(1.28e5 * + * NORM_QMF_ENERGY), (FIXP_DBL)1) Minimum threshold for detecting changes */ +#define ABS_THRES ((FIXP_DBL)16) + +/******************************************************************************* + Functionname: spectralChange + ******************************************************************************* + \brief Calculates a measure for the spectral change within the frame + + The function says how good it would be to split the frame at the given border + position into 2 envelopes. + + The return value delta_sum is scaled with the factor 1/64 + + \return calculated value +*******************************************************************************/ +#define NRG_SHIFT 3 /* for energy summation */ + +static FIXP_DBL spectralChange( + FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], + INT *scaleEnergies, FIXP_DBL EnergyTotal, INT nSfb, INT start, INT border, + INT YBufferWriteOffset, INT stop, INT *result_e) { + INT i, j; + INT len1, len2; + SCHAR energies_e_diff[NUMBER_TIME_SLOTS_2304], energies_e, energyTotal_e = 19, + energies_e_add; + SCHAR prevEnergies_e_diff, newEnergies_e_diff; + FIXP_DBL tmp0, tmp1; + FIXP_DBL delta, delta_sum; + INT accu_e, tmp_e; + + delta_sum = FL2FXCONST_DBL(0.0f); + *result_e = 0; + + len1 = border - start; + len2 = stop - border; + + /* prefer borders near the middle of the frame */ + FIXP_DBL pos_weight; + pos_weight = FL2FXCONST_DBL(0.5f) - (len1 * GetInvInt(len1 + len2)); + pos_weight = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL - + (fMult(pos_weight, pos_weight) << 2); + + /*** Calc scaling for energies ***/ + FDK_ASSERT(scaleEnergies[0] >= 0); + FDK_ASSERT(scaleEnergies[1] >= 0); + + energies_e = 19 - fMin(scaleEnergies[0], scaleEnergies[1]); + + /* limit shift for energy accumulation, energies_e can be -10 min. */ + if (energies_e < -10) { + energies_e_add = -10 - energies_e; + energies_e = -10; + } else if (energies_e > 17) { + energies_e_add = energies_e - 17; + energies_e = 17; + } else { + energies_e_add = 0; + } + + /* compensate scaling differences between scaleEnergies[0] and + * scaleEnergies[1] */ + prevEnergies_e_diff = scaleEnergies[0] - + fMin(scaleEnergies[0], scaleEnergies[1]) + + energies_e_add + NRG_SHIFT; + newEnergies_e_diff = scaleEnergies[1] - + fMin(scaleEnergies[0], scaleEnergies[1]) + + energies_e_add + NRG_SHIFT; + + prevEnergies_e_diff = fMin(prevEnergies_e_diff, DFRACT_BITS - 1); + newEnergies_e_diff = fMin(newEnergies_e_diff, DFRACT_BITS - 1); + + for (i = start; i < YBufferWriteOffset; i++) { + energies_e_diff[i] = prevEnergies_e_diff; + } + for (i = YBufferWriteOffset; i < stop; i++) { + energies_e_diff[i] = newEnergies_e_diff; + } + + /* Sum up energies of all QMF-timeslots for both halfs */ + FDK_ASSERT(len1 <= 8); /* otherwise an overflow is possible */ + FDK_ASSERT(len2 <= 8); /* otherwise an overflow is possible */ + + for (j = 0; j < nSfb; j++) { + FIXP_DBL accu1 = FL2FXCONST_DBL(0.f); + FIXP_DBL accu2 = FL2FXCONST_DBL(0.f); + accu_e = energies_e + 3; + + /* Sum up energies in first half */ + for (i = start; i < border; i++) { + accu1 += scaleValue(Energies[i][j], -energies_e_diff[i]); + } + + /* Sum up energies in second half */ + for (i = border; i < stop; i++) { + accu2 += scaleValue(Energies[i][j], -energies_e_diff[i]); + } + + /* Ensure certain energy to prevent division by zero and to prevent + * splitting for very low levels */ + accu1 = fMax(accu1, (FIXP_DBL)len1); + accu2 = fMax(accu2, (FIXP_DBL)len2); + +/* Energy change in current band */ +#define LN2 FL2FXCONST_DBL(0.6931471806f) /* ln(2) */ + tmp0 = fLog2(accu2, accu_e) - fLog2(accu1, accu_e); + tmp1 = fLog2((FIXP_DBL)len1, 31) - fLog2((FIXP_DBL)len2, 31); + delta = fMult(LN2, (tmp0 + tmp1)); + delta = (FIXP_DBL)fAbs(delta); + + /* Weighting with amplitude ratio of this band */ + accu_e++; /* scale at least one bit due to (accu1+accu2) */ + accu1 >>= 1; + accu2 >>= 1; + + if (accu_e & 1) { + accu_e++; /* for a defined square result exponent, the exponent has to be + even */ + accu1 >>= 1; + accu2 >>= 1; + } + + delta_sum += fMult(sqrtFixp(accu1 + accu2), delta); + *result_e = ((accu_e >> 1) + LD_DATA_SHIFT); + } + + if (energyTotal_e & 1) { + energyTotal_e += 1; /* for a defined square result exponent, the exponent + has to be even */ + EnergyTotal >>= 1; + } + + delta_sum = fMult(delta_sum, invSqrtNorm2(EnergyTotal, &tmp_e)); + *result_e = *result_e + (tmp_e - (energyTotal_e >> 1)); + + return fMult(delta_sum, pos_weight); +} + +/******************************************************************************* + Functionname: addLowbandEnergies + ******************************************************************************* + \brief Calculates total lowband energy + + The input values Energies[0] (low-band) are scaled by the factor + 2^(14-*scaleEnergies[0]) + The input values Energies[1] (high-band) are scaled by the factor + 2^(14-*scaleEnergies[1]) + + \return total energy in the lowband, scaled by the factor 2^19 +*******************************************************************************/ +static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies, int *scaleEnergies, + int YBufferWriteOffset, int nrgSzShift, + int tran_off, UCHAR *freqBandTable, + int slots) { + INT nrgTotal_e; + FIXP_DBL nrgTotal_m; + FIXP_DBL accu1 = FL2FXCONST_DBL(0.0f); + FIXP_DBL accu2 = FL2FXCONST_DBL(0.0f); + int tran_offdiv2 = tran_off >> nrgSzShift; + const int sc1 = + DFRACT_BITS - + fNormz((FIXP_DBL)fMax( + 1, (freqBandTable[0] * (YBufferWriteOffset - tran_offdiv2) - 1))); + const int sc2 = + DFRACT_BITS - + fNormz((FIXP_DBL)fMax( + 1, (freqBandTable[0] * + (tran_offdiv2 + (slots >> nrgSzShift) - YBufferWriteOffset) - + 1))); + int ts, k; + + /* Sum up lowband energy from one frame at offset tran_off */ + /* freqBandTable[LORES] has MAX_FREQ_COEFFS/2 +1 coeefs max. */ + for (ts = tran_offdiv2; ts < YBufferWriteOffset; ts++) { + for (k = 0; k < freqBandTable[0]; k++) { + accu1 += Energies[ts][k] >> sc1; + } + } + for (; ts < tran_offdiv2 + (slots >> nrgSzShift); ts++) { + for (k = 0; k < freqBandTable[0]; k++) { + accu2 += Energies[ts][k] >> sc2; + } + } + + nrgTotal_m = fAddNorm(accu1, (sc1 - 5) - scaleEnergies[0], accu2, + (sc2 - 5) - scaleEnergies[1], &nrgTotal_e); + nrgTotal_m = scaleValueSaturate(nrgTotal_m, nrgTotal_e); + + return (nrgTotal_m); +} + +/******************************************************************************* + Functionname: addHighbandEnergies + ******************************************************************************* + \brief Add highband energies + + Highband energies are mapped to an array with smaller dimension: + Its time resolution is only 1 SBR-timeslot and its frequency resolution + is 1 SBR-band. Therefore the data to be fed into the spectralChange + function is reduced. + + The values EnergiesM are scaled by the factor (2^19-scaleEnergies[0]) for + slots=YBufferWriteOffset. + + \return total energy in the highband, scaled by factor 2^19 +*******************************************************************************/ + +static FIXP_DBL addHighbandEnergies( + FIXP_DBL **RESTRICT Energies, /*!< input */ + INT *scaleEnergies, INT YBufferWriteOffset, + FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304] + [MAX_FREQ_COEFFS], /*!< Combined output */ + UCHAR *RESTRICT freqBandTable, INT nSfb, INT sbrSlots, INT timeStep) { + INT i, j, k, slotIn, slotOut, scale[2]; + INT li, ui; + FIXP_DBL nrgTotal; + FIXP_DBL accu = FL2FXCONST_DBL(0.0f); + + /* Combine QMF-timeslots to SBR-timeslots, + combine QMF-bands to SBR-bands, + combine Left and Right channel */ + for (slotOut = 0; slotOut < sbrSlots; slotOut++) { + /* Note: Below slotIn = slotOut and not slotIn = timeStep*slotOut + because the Energies[] time resolution is always the SBR slot resolution + regardless of the timeStep. */ + slotIn = slotOut; + + for (j = 0; j < nSfb; j++) { + accu = FL2FXCONST_DBL(0.0f); + + li = freqBandTable[j]; + ui = freqBandTable[j + 1]; + + for (k = li; k < ui; k++) { + for (i = 0; i < timeStep; i++) { + accu += Energies[slotIn][k] >> 5; + } + } + EnergiesM[slotOut][j] = accu; + } + } + + /* scale energies down before add up */ + scale[0] = fixMin(8, scaleEnergies[0]); + scale[1] = fixMin(8, scaleEnergies[1]); + + if ((scaleEnergies[0] - scale[0]) > (DFRACT_BITS - 1) || + (scaleEnergies[1] - scale[1]) > (DFRACT_BITS - 1)) + nrgTotal = FL2FXCONST_DBL(0.0f); + else { + /* Now add all energies */ + accu = FL2FXCONST_DBL(0.0f); + + for (slotOut = 0; slotOut < YBufferWriteOffset; slotOut++) { + for (j = 0; j < nSfb; j++) { + accu += (EnergiesM[slotOut][j] >> scale[0]); + } + } + nrgTotal = accu >> (scaleEnergies[0] - scale[0]); + + for (slotOut = YBufferWriteOffset; slotOut < sbrSlots; slotOut++) { + for (j = 0; j < nSfb; j++) { + accu += (EnergiesM[slotOut][j] >> scale[0]); + } + } + nrgTotal = fAddSaturate(nrgTotal, accu >> (scaleEnergies[1] - scale[1])); + } + + return (nrgTotal); +} + +/******************************************************************************* + Functionname: FDKsbrEnc_frameSplitter + ******************************************************************************* + \brief Decides if a FIXFIX-frame shall be splitted into 2 envelopes + + If no transient has been detected before, the frame can still be splitted + into 2 envelopes. +*******************************************************************************/ +void FDKsbrEnc_frameSplitter( + FIXP_DBL **Energies, INT *scaleEnergies, + HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, UCHAR *freqBandTable, + UCHAR *tran_vector, int YBufferWriteOffset, int YBufferSzShift, int nSfb, + int timeStep, int no_cols, FIXP_DBL *tonality) { + if (tran_vector[1] == 0) /* no transient was detected */ + { + FIXP_DBL delta; + INT delta_e; + FIXP_DBL(*EnergiesM)[MAX_FREQ_COEFFS]; + FIXP_DBL EnergyTotal, newLowbandEnergy, newHighbandEnergy; + INT border; + INT sbrSlots = fMultI(GetInvInt(timeStep), no_cols); + C_ALLOC_SCRATCH_START(_EnergiesM, FIXP_DBL, + NUMBER_TIME_SLOTS_2304 * MAX_FREQ_COEFFS) + + FDK_ASSERT(sbrSlots * timeStep == no_cols); + + EnergiesM = (FIXP_DBL(*)[MAX_FREQ_COEFFS])_EnergiesM; + + /* + Get Lowband-energy over a range of 2 frames (Look half a frame back and + ahead). + */ + newLowbandEnergy = addLowbandEnergies( + Energies, scaleEnergies, YBufferWriteOffset, YBufferSzShift, + h_sbrTransientDetector->tran_off, freqBandTable, no_cols); + + newHighbandEnergy = + addHighbandEnergies(Energies, scaleEnergies, YBufferWriteOffset, + EnergiesM, freqBandTable, nSfb, sbrSlots, timeStep); + + { + /* prevLowBandEnergy: Corresponds to 1 frame, starting with half a frame + look-behind newLowbandEnergy: Corresponds to 1 frame, starting in the + middle of the current frame */ + EnergyTotal = (newLowbandEnergy >> 1) + + (h_sbrTransientDetector->prevLowBandEnergy >> + 1); /* mean of new and prev LB NRG */ + EnergyTotal = + fAddSaturate(EnergyTotal, newHighbandEnergy); /* Add HB NRG */ + /* The below border should specify the same position as the middle border + of a FIXFIX-frame with 2 envelopes. */ + border = (sbrSlots + 1) >> 1; + + if ((INT)EnergyTotal & 0xffffffe0 && + (scaleEnergies[0] < 32 || scaleEnergies[1] < 32)) /* i.e. > 31 */ { + delta = spectralChange(EnergiesM, scaleEnergies, EnergyTotal, nSfb, 0, + border, YBufferWriteOffset, sbrSlots, &delta_e); + } else { + delta = FL2FXCONST_DBL(0.0f); + delta_e = 0; + + /* set tonality to 0 when energy is very low, since the amplitude + resolution should then be low as well */ + *tonality = FL2FXCONST_DBL(0.0f); + } + + if (fIsLessThan(h_sbrTransientDetector->split_thr_m, + h_sbrTransientDetector->split_thr_e, delta, delta_e)) { + tran_vector[0] = 1; /* Set flag for splitting */ + } else { + tran_vector[0] = 0; + } + } + + /* Update prevLowBandEnergy */ + h_sbrTransientDetector->prevLowBandEnergy = newLowbandEnergy; + h_sbrTransientDetector->prevHighBandEnergy = newHighbandEnergy; + C_ALLOC_SCRATCH_END(_EnergiesM, FIXP_DBL, + NUMBER_TIME_SLOTS_2304 * MAX_FREQ_COEFFS) + } +} + +/* + * Calculate transient energy threshold for each QMF band + */ +static void calculateThresholds(FIXP_DBL **RESTRICT Energies, + INT *RESTRICT scaleEnergies, + FIXP_DBL *RESTRICT thresholds, + int YBufferWriteOffset, int YBufferSzShift, + int noCols, int noRows, int tran_off) { + FIXP_DBL mean_val, std_val, temp; + FIXP_DBL i_noCols; + FIXP_DBL i_noCols1; + FIXP_DBL accu, accu0, accu1; + int scaleFactor0, scaleFactor1, commonScale; + int i, j; + + i_noCols = GetInvInt(noCols + tran_off) << YBufferSzShift; + i_noCols1 = GetInvInt(noCols + tran_off - 1) << YBufferSzShift; + + /* calc minimum scale of energies of previous and current frame */ + commonScale = fixMin(scaleEnergies[0], scaleEnergies[1]); + + /* calc scalefactors to adapt energies to common scale */ + scaleFactor0 = fixMin((scaleEnergies[0] - commonScale), (DFRACT_BITS - 1)); + scaleFactor1 = fixMin((scaleEnergies[1] - commonScale), (DFRACT_BITS - 1)); + + FDK_ASSERT((scaleFactor0 >= 0) && (scaleFactor1 >= 0)); + + /* calculate standard deviation in every subband */ + for (i = 0; i < noRows; i++) { + int startEnergy = (tran_off >> YBufferSzShift); + int endEnergy = ((noCols >> YBufferSzShift) + tran_off); + int shift; + + /* calculate mean value over decimated energy values (downsampled by 2). */ + accu0 = accu1 = FL2FXCONST_DBL(0.0f); + + for (j = startEnergy; j < YBufferWriteOffset; j++) + accu0 = fMultAddDiv2(accu0, Energies[j][i], i_noCols); + for (; j < endEnergy; j++) + accu1 = fMultAddDiv2(accu1, Energies[j][i], i_noCols); + + mean_val = ((accu0 << 1) >> scaleFactor0) + + ((accu1 << 1) >> scaleFactor1); /* average */ + shift = fixMax( + 0, CountLeadingBits(mean_val) - + 6); /* -6 to keep room for accumulating upto N = 24 values */ + + /* calculate standard deviation */ + accu = FL2FXCONST_DBL(0.0f); + + /* summe { ((mean_val-nrg)^2) * i_noCols1 } */ + for (j = startEnergy; j < YBufferWriteOffset; j++) { + temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor0)) + << shift; + temp = fPow2Div2(temp); + accu = fMultAddDiv2(accu, temp, i_noCols1); + } + for (; j < endEnergy; j++) { + temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor1)) + << shift; + temp = fPow2Div2(temp); + accu = fMultAddDiv2(accu, temp, i_noCols1); + } + accu <<= 2; + std_val = sqrtFixp(accu) >> shift; /* standard deviation */ + + /* + Take new threshold as average of calculated standard deviation ratio + and old threshold if greater than absolute threshold + */ + temp = (commonScale <= (DFRACT_BITS - 1)) + ? fMult(FL2FXCONST_DBL(0.66f), thresholds[i]) + + (fMult(FL2FXCONST_DBL(0.34f), std_val) >> commonScale) + : (FIXP_DBL)0; + + thresholds[i] = fixMax(ABS_THRES, temp); + + FDK_ASSERT(commonScale >= 0); + } +} + +/* + * Calculate transient levels for each QMF time slot. + */ +static void extractTransientCandidates( + FIXP_DBL **RESTRICT Energies, INT *RESTRICT scaleEnergies, + FIXP_DBL *RESTRICT thresholds, FIXP_DBL *RESTRICT transients, + int YBufferWriteOffset, int YBufferSzShift, int noCols, int start_band, + int stop_band, int tran_off, int addPrevSamples) { + FIXP_DBL i_thres; + C_ALLOC_SCRATCH_START(EnergiesTemp, FIXP_DBL, 2 * 32) + int tmpScaleEnergies0, tmpScaleEnergies1; + int endCond; + int startEnerg, endEnerg; + int i, j, jIndex, jpBM; + + tmpScaleEnergies0 = scaleEnergies[0]; + tmpScaleEnergies1 = scaleEnergies[1]; + + /* Scale value for first energies, upto YBufferWriteOffset */ + tmpScaleEnergies0 = fixMin(tmpScaleEnergies0, MAX_SHIFT_DBL); + /* Scale value for first energies, from YBufferWriteOffset upwards */ + tmpScaleEnergies1 = fixMin(tmpScaleEnergies1, MAX_SHIFT_DBL); + + FDK_ASSERT((tmpScaleEnergies0 >= 0) && (tmpScaleEnergies1 >= 0)); + + /* Keep addPrevSamples extra previous transient candidates. */ + FDKmemmove(transients, transients + noCols - addPrevSamples, + (tran_off + addPrevSamples) * sizeof(FIXP_DBL)); + FDKmemclear(transients + tran_off + addPrevSamples, + noCols * sizeof(FIXP_DBL)); + + endCond = noCols; /* Amount of new transient values to be calculated. */ + startEnerg = (tran_off - 3) >> YBufferSzShift; /* >>YBufferSzShift because of + amount of energy values. -3 + because of neighbors being + watched. */ + endEnerg = + ((noCols + (YBufferWriteOffset << YBufferSzShift)) - 1) >> + YBufferSzShift; /* YBufferSzShift shifts because of half energy values. */ + + /* Compute differential values with two different weightings in every subband + */ + for (i = start_band; i < stop_band; i++) { + FIXP_DBL thres = thresholds[i]; + + if ((LONG)thresholds[i] >= 256) + i_thres = (LONG)((LONG)MAXVAL_DBL / ((((LONG)thresholds[i])) + 1)) + << (32 - 24); + else + i_thres = (LONG)MAXVAL_DBL; + + /* Copy one timeslot and de-scale and de-squish */ + if (YBufferSzShift == 1) { + for (j = startEnerg; j < YBufferWriteOffset; j++) { + FIXP_DBL tmp = Energies[j][i]; + EnergiesTemp[(j << 1) + 1] = EnergiesTemp[j << 1] = + tmp >> tmpScaleEnergies0; + } + for (; j <= endEnerg; j++) { + FIXP_DBL tmp = Energies[j][i]; + EnergiesTemp[(j << 1) + 1] = EnergiesTemp[j << 1] = + tmp >> tmpScaleEnergies1; + } + } else { + for (j = startEnerg; j < YBufferWriteOffset; j++) { + FIXP_DBL tmp = Energies[j][i]; + EnergiesTemp[j] = tmp >> tmpScaleEnergies0; + } + for (; j <= endEnerg; j++) { + FIXP_DBL tmp = Energies[j][i]; + EnergiesTemp[j] = tmp >> tmpScaleEnergies1; + } + } + + /* Detect peaks in energy values. */ + + jIndex = tran_off; + jpBM = jIndex + addPrevSamples; + + for (j = endCond; j--; jIndex++, jpBM++) { + FIXP_DBL delta, tran; + int d; + + delta = (FIXP_DBL)0; + tran = (FIXP_DBL)0; + + for (d = 1; d < 4; d++) { + delta += EnergiesTemp[jIndex + d]; /* R */ + delta -= EnergiesTemp[jIndex - d]; /* L */ + delta -= thres; + + if (delta > (FIXP_DBL)0) { + tran = fMultAddDiv2(tran, i_thres, delta); + } + } + transients[jpBM] += (tran << 1); + } + } + C_ALLOC_SCRATCH_END(EnergiesTemp, FIXP_DBL, 2 * 32) +} + +void FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTran, + FIXP_DBL **Energies, INT *scaleEnergies, + UCHAR *transient_info, int YBufferWriteOffset, + int YBufferSzShift, int timeStep, + int frameMiddleBorder) { + int no_cols = h_sbrTran->no_cols; + int qmfStartSample; + int addPrevSamples; + int timeStepShift = 0; + int i, cond; + + /* Where to start looking for transients in the transient candidate buffer */ + qmfStartSample = timeStep * frameMiddleBorder; + /* We need to look one value backwards in the transients, so we might need one + * more previous value. */ + addPrevSamples = (qmfStartSample > 0) ? 0 : 1; + + switch (timeStep) { + case 1: + timeStepShift = 0; + break; + case 2: + timeStepShift = 1; + break; + case 4: + timeStepShift = 2; + break; + } + + calculateThresholds(Energies, scaleEnergies, h_sbrTran->thresholds, + YBufferWriteOffset, YBufferSzShift, h_sbrTran->no_cols, + h_sbrTran->no_rows, h_sbrTran->tran_off); + + extractTransientCandidates( + Energies, scaleEnergies, h_sbrTran->thresholds, h_sbrTran->transients, + YBufferWriteOffset, YBufferSzShift, h_sbrTran->no_cols, 0, + h_sbrTran->no_rows, h_sbrTran->tran_off, addPrevSamples); + + transient_info[0] = 0; + transient_info[1] = 0; + transient_info[2] = 0; + + /* Offset by the amount of additional previous transient candidates being + * kept. */ + qmfStartSample += addPrevSamples; + + /* Check for transients in second granule (pick the last value of subsequent + * values) */ + for (i = qmfStartSample; i < qmfStartSample + no_cols; i++) { + cond = (h_sbrTran->transients[i] < + fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1])) && + (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr); + + if (cond) { + transient_info[0] = (i - qmfStartSample) >> timeStepShift; + transient_info[1] = 1; + break; + } + } + + if (h_sbrTran->frameShift != 0) { + /* transient prediction for LDSBR */ + /* Check for transients in first qmf-slots of second frame */ + for (i = qmfStartSample + no_cols; + i < qmfStartSample + no_cols + h_sbrTran->frameShift; i++) { + cond = (h_sbrTran->transients[i] < + fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1])) && + (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr); + + if (cond) { + int pos = (int)((i - qmfStartSample - no_cols) >> timeStepShift); + if ((pos < 3) && (transient_info[1] == 0)) { + transient_info[2] = 1; + } + break; + } + } + } +} + +int FDKsbrEnc_InitSbrTransientDetector( + HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, + UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */ + INT frameSize, INT sampleFreq, sbrConfigurationPtr params, int tran_fc, + int no_cols, int no_rows, int YBufferWriteOffset, int YBufferSzShift, + int frameShift, int tran_off) { + INT totalBitrate = + params->codecSettings.standardBitrate * params->codecSettings.nChannels; + INT codecBitrate = params->codecSettings.bitRate; + FIXP_DBL bitrateFactor_m, framedur_fix; + INT bitrateFactor_e, tmp_e; + + FDKmemclear(h_sbrTransientDetector, sizeof(SBR_TRANSIENT_DETECTOR)); + + h_sbrTransientDetector->frameShift = frameShift; + h_sbrTransientDetector->tran_off = tran_off; + + if (codecBitrate) { + bitrateFactor_m = fDivNorm((FIXP_DBL)totalBitrate, + (FIXP_DBL)(codecBitrate << 2), &bitrateFactor_e); + bitrateFactor_e += 2; + } else { + bitrateFactor_m = FL2FXCONST_DBL(1.0 / 4.0); + bitrateFactor_e = 2; + } + + framedur_fix = fDivNorm(frameSize, sampleFreq); + + /* The longer the frames, the more often should the FIXFIX- + case transmit 2 envelopes instead of 1. + Frame durations below 10 ms produce the highest threshold + so that practically always only 1 env is transmitted. */ + FIXP_DBL tmp = framedur_fix - FL2FXCONST_DBL(0.010); + + tmp = fixMax(tmp, FL2FXCONST_DBL(0.0001)); + tmp = fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp), &tmp_e); + + bitrateFactor_e = (tmp_e + bitrateFactor_e); + + if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + bitrateFactor_e--; /* divide by 2 */ + } + + FDK_ASSERT(no_cols <= 32); + FDK_ASSERT(no_rows <= 64); + + h_sbrTransientDetector->no_cols = no_cols; + h_sbrTransientDetector->tran_thr = + (FIXP_DBL)((params->tran_thr << (32 - 24 - 1)) / no_rows); + h_sbrTransientDetector->tran_fc = tran_fc; + h_sbrTransientDetector->split_thr_m = fMult(tmp, bitrateFactor_m); + h_sbrTransientDetector->split_thr_e = bitrateFactor_e; + h_sbrTransientDetector->no_rows = no_rows; + h_sbrTransientDetector->mode = params->tran_det_mode; + h_sbrTransientDetector->prevLowBandEnergy = FL2FXCONST_DBL(0.0f); + + return (0); +} + +#define ENERGY_SCALING_SIZE 32 + +INT FDKsbrEnc_InitSbrFastTransientDetector( + HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const INT time_slots_per_frame, const INT bandwidth_qmf_slot, + const INT no_qmf_channels, const INT sbr_qmf_1st_band) { + int i; + int buff_size; + FIXP_DBL myExp; + FIXP_DBL myExpSlot; + + h_sbrFastTransientDetector->lookahead = TRAN_DET_LOOKAHEAD; + h_sbrFastTransientDetector->nTimeSlots = time_slots_per_frame; + + buff_size = h_sbrFastTransientDetector->nTimeSlots + + h_sbrFastTransientDetector->lookahead; + + for (i = 0; i < buff_size; i++) { + h_sbrFastTransientDetector->delta_energy[i] = FL2FXCONST_DBL(0.0f); + h_sbrFastTransientDetector->energy_timeSlots[i] = FL2FXCONST_DBL(0.0f); + h_sbrFastTransientDetector->lowpass_energy[i] = FL2FXCONST_DBL(0.0f); + h_sbrFastTransientDetector->transientCandidates[i] = 0; + } + + FDK_ASSERT(bandwidth_qmf_slot > 0.f); + h_sbrFastTransientDetector->stopBand = + fMin(TRAN_DET_STOP_FREQ / bandwidth_qmf_slot, no_qmf_channels); + h_sbrFastTransientDetector->startBand = + fMin(sbr_qmf_1st_band, + h_sbrFastTransientDetector->stopBand - TRAN_DET_MIN_QMFBANDS); + + FDK_ASSERT(h_sbrFastTransientDetector->startBand < no_qmf_channels); + FDK_ASSERT(h_sbrFastTransientDetector->startBand < + h_sbrFastTransientDetector->stopBand); + FDK_ASSERT(h_sbrFastTransientDetector->startBand > 1); + FDK_ASSERT(h_sbrFastTransientDetector->stopBand > 1); + + /* the energy weighting and adding up has a headroom of 6 Bits, + so up to 64 bands can be added without potential overflow. */ + FDK_ASSERT(h_sbrFastTransientDetector->stopBand - + h_sbrFastTransientDetector->startBand <= + 64); + +/* QMF_HP_dB_SLOPE_FIX says that we want a 20 dB per 16 kHz HP filter. + The following lines map this to the QMF bandwidth. */ +#define EXP_E 7 /* 64 (=64) multiplications max, max. allowed sum is 0.5 */ + myExp = fMultNorm(QMF_HP_dBd_SLOPE_FIX, 0, (FIXP_DBL)bandwidth_qmf_slot, + DFRACT_BITS - 1, EXP_E); + myExpSlot = myExp; + + for (i = 0; i < 64; i++) { + /* Calculate dBf over all qmf bands: + dBf = (10^(0.002266f/10*bw(slot)))^(band) = + = 2^(log2(10)*0.002266f/10*bw(slot)*band) = + = 2^(0.00075275f*bw(slot)*band) */ + + FIXP_DBL dBf_m; /* dBf mantissa */ + INT dBf_e; /* dBf exponent */ + INT tmp; + + INT dBf_int; /* dBf integer part */ + FIXP_DBL dBf_fract; /* dBf fractional part */ + + /* myExp*(i+1) = myExp_int - myExp_fract + myExp*(i+1) is split up here for better accuracy of CalcInvLdData(), + for its result can be split up into an integer and a fractional part */ + + /* Round up to next integer */ + FIXP_DBL myExp_int = + (myExpSlot & (FIXP_DBL)0xfe000000) + (FIXP_DBL)0x02000000; + + /* This is the fractional part that needs to be substracted */ + FIXP_DBL myExp_fract = myExp_int - myExpSlot; + + /* Calc integer part */ + dBf_int = CalcInvLdData(myExp_int); + /* The result needs to be re-scaled. The ld(myExp_int) had been scaled by + EXP_E, the CalcInvLdData expects the operand to be scaled by + LD_DATA_SHIFT. Therefore, the correctly scaled result is + dBf_int^(2^(EXP_E-LD_DATA_SHIFT)), which is dBf_int^2 */ + + if (dBf_int <= + 46340) { /* compare with maximum allowed value for signed integer + multiplication, 46340 = + (INT)floor(sqrt((double)(((UINT)1<<(DFRACT_BITS-1))-1))) */ + dBf_int *= dBf_int; + + /* Calc fractional part */ + dBf_fract = CalcInvLdData(-myExp_fract); + /* The result needs to be re-scaled. The ld(myExp_fract) had been scaled + by EXP_E, the CalcInvLdData expects the operand to be scaled by + LD_DATA_SHIFT. Therefore, the correctly scaled result is + dBf_fract^(2^(EXP_E-LD_DATA_SHIFT)), which is dBf_fract^2 */ + dBf_fract = fMultNorm(dBf_fract, dBf_fract, &tmp); + + /* Get worst case scaling of multiplication result */ + dBf_e = (DFRACT_BITS - 1 - tmp) - CountLeadingBits(dBf_int); + + /* Now multiply integer with fractional part of the result, thus resulting + in the overall accurate fractional result */ + dBf_m = fMultNorm(dBf_int, DFRACT_BITS - 1, dBf_fract, tmp, dBf_e); + + myExpSlot += myExp; + } else { + dBf_m = (FIXP_DBL)0; + dBf_e = 0; + } + + /* Keep the results */ + h_sbrFastTransientDetector->dBf_m[i] = dBf_m; + h_sbrFastTransientDetector->dBf_e[i] = dBf_e; + } + + /* Make sure that dBf is greater than 1.0 (because it should be a highpass) */ + /* ... */ + + return 0; +} + +void FDKsbrEnc_fastTransientDetect( + const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const FIXP_DBL *const *Energies, const int *const scaleEnergies, + const INT YBufferWriteOffset, UCHAR *const tran_vector) { + int timeSlot, band; + + FIXP_DBL max_delta_energy; /* helper to store maximum energy ratio */ + int max_delta_energy_scale; /* helper to store scale of maximum energy ratio + */ + int ind_max = 0; /* helper to store index of maximum energy ratio */ + int isTransientInFrame = 0; + + const int nTimeSlots = h_sbrFastTransientDetector->nTimeSlots; + const int lookahead = h_sbrFastTransientDetector->lookahead; + const int startBand = h_sbrFastTransientDetector->startBand; + const int stopBand = h_sbrFastTransientDetector->stopBand; + + int *transientCandidates = h_sbrFastTransientDetector->transientCandidates; + + FIXP_DBL *energy_timeSlots = h_sbrFastTransientDetector->energy_timeSlots; + int *energy_timeSlots_scale = + h_sbrFastTransientDetector->energy_timeSlots_scale; + + FIXP_DBL *delta_energy = h_sbrFastTransientDetector->delta_energy; + int *delta_energy_scale = h_sbrFastTransientDetector->delta_energy_scale; + + const FIXP_DBL thr = TRAN_DET_THRSHLD; + const INT thr_scale = TRAN_DET_THRSHLD_SCALE; + + /*reset transient info*/ + tran_vector[2] = 0; + + /* reset transient candidates */ + FDKmemclear(transientCandidates + lookahead, nTimeSlots * sizeof(int)); + + for (timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) { + int i, norm; + FIXP_DBL tmpE = FL2FXCONST_DBL(0.0f); + int headroomEnSlot = DFRACT_BITS - 1; + + FIXP_DBL smallNRG = FL2FXCONST_DBL(1e-2f); + FIXP_DBL denominator; + INT denominator_scale; + + /* determine minimum headroom of energy values for this timeslot */ + for (band = startBand; band < stopBand; band++) { + int tmp_headroom = fNormz(Energies[timeSlot][band]) - 1; + if (tmp_headroom < headroomEnSlot) { + headroomEnSlot = tmp_headroom; + } + } + + for (i = 0, band = startBand; band < stopBand; band++, i++) { + /* energy is weighted by weightingfactor stored in dBf_m array */ + /* dBf_m index runs from 0 to stopBand-startband */ + /* energy shifted by calculated headroom for maximum precision */ + FIXP_DBL weightedEnergy = + fMult(Energies[timeSlot][band] << headroomEnSlot, + h_sbrFastTransientDetector->dBf_m[i]); + + /* energy is added up */ + /* shift by 6 to have a headroom for maximum 64 additions */ + /* shift by dBf_e to handle weighting factor dependent scale factors */ + tmpE += + weightedEnergy >> (6 + (10 - h_sbrFastTransientDetector->dBf_e[i])); + } + + /* store calculated energy for timeslot */ + energy_timeSlots[timeSlot] = tmpE; + + /* calculate overall scale factor for energy of this timeslot */ + /* = original scale factor of energies + * (-scaleEnergies[0]+2*QMF_SCALE_OFFSET or + * -scaleEnergies[1]+2*QMF_SCALE_OFFSET */ + /* depending on YBufferWriteOffset) */ + /* + weighting factor scale (10) */ + /* + adding up scale factor ( 6) */ + /* - headroom of energy value (headroomEnSlot) */ + if (timeSlot < YBufferWriteOffset) { + energy_timeSlots_scale[timeSlot] = + (-scaleEnergies[0] + 2 * QMF_SCALE_OFFSET) + (10 + 6) - + headroomEnSlot; + } else { + energy_timeSlots_scale[timeSlot] = + (-scaleEnergies[1] + 2 * QMF_SCALE_OFFSET) + (10 + 6) - + headroomEnSlot; + } + + /* Add a small energy to the denominator, thus making the transient + detection energy-dependent. Loud transients are being detected, + silent ones not. */ + + /* make sure that smallNRG does not overflow */ + if (-energy_timeSlots_scale[timeSlot - 1] + 1 > 5) { + denominator = smallNRG; + denominator_scale = 0; + } else { + /* Leave an additional headroom of 1 bit for this addition. */ + smallNRG = + scaleValue(smallNRG, -(energy_timeSlots_scale[timeSlot - 1] + 1)); + denominator = (energy_timeSlots[timeSlot - 1] >> 1) + smallNRG; + denominator_scale = energy_timeSlots_scale[timeSlot - 1] + 1; + } + + delta_energy[timeSlot] = + fDivNorm(energy_timeSlots[timeSlot], denominator, &norm); + delta_energy_scale[timeSlot] = + energy_timeSlots_scale[timeSlot] - denominator_scale + norm; + } + + /*get transient candidates*/ + /* For every timeslot, check if delta(E) exceeds the threshold. If it did, + it could potentially be marked as a transient candidate. However, the 2 + slots before the current one must not be transients with an energy higher + than 1.4*E(current). If both aren't transients or if the energy of the + current timesolot is more than 1.4 times higher than the energy in the + last or the one before the last slot, it is marked as a transient.*/ + + FDK_ASSERT(lookahead >= 2); + for (timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) { + FIXP_DBL energy_cur_slot_weighted = + fMult(energy_timeSlots[timeSlot], FL2FXCONST_DBL(1.0f / 1.4f)); + if (!fIsLessThan(delta_energy[timeSlot], delta_energy_scale[timeSlot], thr, + thr_scale) && + (((transientCandidates[timeSlot - 2] == 0) && + (transientCandidates[timeSlot - 1] == 0)) || + !fIsLessThan(energy_cur_slot_weighted, + energy_timeSlots_scale[timeSlot], + energy_timeSlots[timeSlot - 1], + energy_timeSlots_scale[timeSlot - 1]) || + !fIsLessThan(energy_cur_slot_weighted, + energy_timeSlots_scale[timeSlot], + energy_timeSlots[timeSlot - 2], + energy_timeSlots_scale[timeSlot - 2]))) { + /* in case of strong transients, subsequent + * qmf slots might be recognized as transients. */ + transientCandidates[timeSlot] = 1; + } + } + + /*get transient with max energy*/ + max_delta_energy = FL2FXCONST_DBL(0.0f); + max_delta_energy_scale = 0; + ind_max = 0; + isTransientInFrame = 0; + for (timeSlot = 0; timeSlot < nTimeSlots; timeSlot++) { + int scale = fMax(delta_energy_scale[timeSlot], max_delta_energy_scale); + if (transientCandidates[timeSlot] && + ((delta_energy[timeSlot] >> (scale - delta_energy_scale[timeSlot])) > + (max_delta_energy >> (scale - max_delta_energy_scale)))) { + max_delta_energy = delta_energy[timeSlot]; + max_delta_energy_scale = scale; + ind_max = timeSlot; + isTransientInFrame = 1; + } + } + + /*from all transient candidates take the one with the biggest energy*/ + if (isTransientInFrame) { + tran_vector[0] = ind_max; + tran_vector[1] = 1; + } else { + /*reset transient info*/ + tran_vector[0] = tran_vector[1] = 0; + } + + /*check for transients in lookahead*/ + for (timeSlot = nTimeSlots; timeSlot < nTimeSlots + lookahead; timeSlot++) { + if (transientCandidates[timeSlot]) { + tran_vector[2] = 1; + } + } + + /*update buffers*/ + for (timeSlot = 0; timeSlot < lookahead; timeSlot++) { + transientCandidates[timeSlot] = transientCandidates[nTimeSlots + timeSlot]; + + /* fixpoint stuff */ + energy_timeSlots[timeSlot] = energy_timeSlots[nTimeSlots + timeSlot]; + energy_timeSlots_scale[timeSlot] = + energy_timeSlots_scale[nTimeSlots + timeSlot]; + + delta_energy[timeSlot] = delta_energy[nTimeSlots + timeSlot]; + delta_energy_scale[timeSlot] = delta_energy_scale[nTimeSlots + timeSlot]; + } +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/tran_det.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/tran_det.h new file mode 100644 index 0000000000000..d10a7dbb4922b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSBRenc/src/tran_det.h @@ -0,0 +1,191 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Transient detector prototypes $Revision: 95111 $ +*/ +#ifndef TRAN_DET_H +#define TRAN_DET_H + +#include "sbr_encoder.h" +#include "sbr_def.h" + +typedef struct { + FIXP_DBL transients[32 + (32 / 2)]; + FIXP_DBL thresholds[64]; + FIXP_DBL tran_thr; /* Master threshold for transient signals */ + FIXP_DBL split_thr_m; /* Threshold for splitting FIXFIX-frames into 2 env */ + INT split_thr_e; /* Scale for splitting threshold */ + FIXP_DBL prevLowBandEnergy; /* Energy of low band */ + FIXP_DBL prevHighBandEnergy; /* Energy of high band */ + INT tran_fc; /* Number of lowband subbands to discard */ + INT no_cols; + INT no_rows; + INT mode; + + int frameShift; + int tran_off; /* Offset for reading energy values. */ +} SBR_TRANSIENT_DETECTOR; + +typedef SBR_TRANSIENT_DETECTOR *HANDLE_SBR_TRANSIENT_DETECTOR; + +#define TRAN_DET_LOOKAHEAD 2 +#define TRAN_DET_START_FREQ 4500 /*start frequency for transient detection*/ +#define TRAN_DET_STOP_FREQ 13500 /*stop frequency for transient detection*/ +#define TRAN_DET_MIN_QMFBANDS \ + 4 /* minimum qmf bands for transient detection \ + */ +#define QMF_HP_dBd_SLOPE_FIX \ + FL2FXCONST_DBL(0.00075275f) /* 0.002266f/10 * log2(10) */ +#define TRAN_DET_THRSHLD FL2FXCONST_DBL(5.0f / 8.0f) +#define TRAN_DET_THRSHLD_SCALE (3) + +typedef struct { + INT transientCandidates[32 + TRAN_DET_LOOKAHEAD]; + INT nTimeSlots; + INT lookahead; + INT startBand; + INT stopBand; + + FIXP_DBL dBf_m[64]; + INT dBf_e[64]; + + FIXP_DBL energy_timeSlots[32 + TRAN_DET_LOOKAHEAD]; + INT energy_timeSlots_scale[32 + TRAN_DET_LOOKAHEAD]; + + FIXP_DBL delta_energy[32 + TRAN_DET_LOOKAHEAD]; + INT delta_energy_scale[32 + TRAN_DET_LOOKAHEAD]; + + FIXP_DBL lowpass_energy[32 + TRAN_DET_LOOKAHEAD]; + INT lowpass_energy_scale[32 + TRAN_DET_LOOKAHEAD]; +} FAST_TRAN_DETECTOR; +typedef FAST_TRAN_DETECTOR *HANDLE_FAST_TRAN_DET; + +INT FDKsbrEnc_InitSbrFastTransientDetector( + HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const INT time_slots_per_frame, const INT bandwidth_qmf_slot, + const INT no_qmf_channels, const INT sbr_qmf_1st_band); + +void FDKsbrEnc_fastTransientDetect( + const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const FIXP_DBL *const *Energies, const int *const scaleEnergies, + const INT YBufferWriteOffset, UCHAR *const tran_vector); + +void FDKsbrEnc_transientDetect( + HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, FIXP_DBL **Energies, + INT *scaleEnergies, UCHAR *tran_vector, int YBufferWriteOffset, + int YBufferSzShift, int timeStep, int frameMiddleBorder); + +int FDKsbrEnc_InitSbrTransientDetector( + HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, + UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */ + INT frameSize, INT sampleFreq, sbrConfigurationPtr params, int tran_fc, + int no_cols, int no_rows, int YBufferWriteOffset, int YBufferSzShift, + int frameShift, int tran_off); + +void FDKsbrEnc_frameSplitter( + FIXP_DBL **Energies, INT *scaleEnergies, + HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, UCHAR *freqBandTable, + UCHAR *tran_vector, int YBufferWriteOffset, int YBufferSzShift, int nSfb, + int timeStep, int no_cols, FIXP_DBL *tonality); +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/FDK_audio.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/FDK_audio.h new file mode 100644 index 0000000000000..0e440c9e1cae5 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/FDK_audio.h @@ -0,0 +1,813 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* System integration library ************************** + + Author(s): Manuel Jander + + Description: + +*******************************************************************************/ + +/** \file FDK_audio.h + * \brief Global audio struct and constant definitions. + */ + +#ifndef FDK_AUDIO_H +#define FDK_AUDIO_H + +#include "machine_type.h" +#include "genericStds.h" +#include "syslib_channelMapDescr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * File format identifiers. + */ +typedef enum { + FF_UNKNOWN = -1, /**< Unknown format. */ + FF_RAW = 0, /**< No container, bit stream data conveyed "as is". */ + + FF_MP4_3GPP = 3, /**< 3GPP file format. */ + FF_MP4_MP4F = 4, /**< MPEG-4 File format. */ + + FF_RAWPACKETS = 5 /**< Proprietary raw packet file. */ + +} FILE_FORMAT; + +/** + * Transport type identifiers. + */ +typedef enum { + TT_UNKNOWN = -1, /**< Unknown format. */ + TT_MP4_RAW = 0, /**< "as is" access units (packet based since there is + obviously no sync layer) */ + TT_MP4_ADIF = 1, /**< ADIF bitstream format. */ + TT_MP4_ADTS = 2, /**< ADTS bitstream format. */ + + TT_MP4_LATM_MCP1 = 6, /**< Audio Mux Elements with muxConfigPresent = 1 */ + TT_MP4_LATM_MCP0 = 7, /**< Audio Mux Elements with muxConfigPresent = 0, out + of band StreamMuxConfig */ + + TT_MP4_LOAS = 10, /**< Audio Sync Stream. */ + + TT_DRM = 12 /**< Digital Radio Mondial (DRM30/DRM+) bitstream format. */ + +} TRANSPORT_TYPE; + +#define TT_IS_PACKET(x) \ + (((x) == TT_MP4_RAW) || ((x) == TT_DRM) || ((x) == TT_MP4_LATM_MCP0) || \ + ((x) == TT_MP4_LATM_MCP1)) + +/** + * Audio Object Type definitions. + */ +typedef enum { + AOT_NONE = -1, + AOT_NULL_OBJECT = 0, + AOT_AAC_MAIN = 1, /**< Main profile */ + AOT_AAC_LC = 2, /**< Low Complexity object */ + AOT_AAC_SSR = 3, + AOT_AAC_LTP = 4, + AOT_SBR = 5, + AOT_AAC_SCAL = 6, + AOT_TWIN_VQ = 7, + AOT_CELP = 8, + AOT_HVXC = 9, + AOT_RSVD_10 = 10, /**< (reserved) */ + AOT_RSVD_11 = 11, /**< (reserved) */ + AOT_TTSI = 12, /**< TTSI Object */ + AOT_MAIN_SYNTH = 13, /**< Main Synthetic object */ + AOT_WAV_TAB_SYNTH = 14, /**< Wavetable Synthesis object */ + AOT_GEN_MIDI = 15, /**< General MIDI object */ + AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */ + AOT_ER_AAC_LC = 17, /**< Error Resilient(ER) AAC Low Complexity */ + AOT_RSVD_18 = 18, /**< (reserved) */ + AOT_ER_AAC_LTP = 19, /**< Error Resilient(ER) AAC LTP object */ + AOT_ER_AAC_SCAL = 20, /**< Error Resilient(ER) AAC Scalable object */ + AOT_ER_TWIN_VQ = 21, /**< Error Resilient(ER) TwinVQ object */ + AOT_ER_BSAC = 22, /**< Error Resilient(ER) BSAC object */ + AOT_ER_AAC_LD = 23, /**< Error Resilient(ER) AAC LowDelay object */ + AOT_ER_CELP = 24, /**< Error Resilient(ER) CELP object */ + AOT_ER_HVXC = 25, /**< Error Resilient(ER) HVXC object */ + AOT_ER_HILN = 26, /**< Error Resilient(ER) HILN object */ + AOT_ER_PARA = 27, /**< Error Resilient(ER) Parametric object */ + AOT_RSVD_28 = 28, /**< might become SSC */ + AOT_PS = 29, /**< PS, Parametric Stereo (includes SBR) */ + AOT_MPEGS = 30, /**< MPEG Surround */ + + AOT_ESCAPE = 31, /**< Signal AOT uses more than 5 bits */ + + AOT_MP3ONMP4_L1 = 32, /**< MPEG-Layer1 in mp4 */ + AOT_MP3ONMP4_L2 = 33, /**< MPEG-Layer2 in mp4 */ + AOT_MP3ONMP4_L3 = 34, /**< MPEG-Layer3 in mp4 */ + AOT_RSVD_35 = 35, /**< might become DST */ + AOT_RSVD_36 = 36, /**< might become ALS */ + AOT_AAC_SLS = 37, /**< AAC + SLS */ + AOT_SLS = 38, /**< SLS */ + AOT_ER_AAC_ELD = 39, /**< AAC Enhanced Low Delay */ + + AOT_USAC = 42, /**< USAC */ + AOT_SAOC = 43, /**< SAOC */ + AOT_LD_MPEGS = 44, /**< Low Delay MPEG Surround */ + + /* Pseudo AOTs */ + AOT_MP2_AAC_LC = 129, /**< Virtual AOT MP2 Low Complexity profile */ + AOT_MP2_SBR = 132, /**< Virtual AOT MP2 Low Complexity Profile with SBR */ + + AOT_DRM_AAC = 143, /**< Virtual AOT for DRM (ER-AAC-SCAL without SBR) */ + AOT_DRM_SBR = 144, /**< Virtual AOT for DRM (ER-AAC-SCAL with SBR) */ + AOT_DRM_MPEG_PS = + 145, /**< Virtual AOT for DRM (ER-AAC-SCAL with SBR and MPEG-PS) */ + AOT_DRM_SURROUND = + 146, /**< Virtual AOT for DRM Surround (ER-AAC-SCAL (+SBR) +MPS) */ + AOT_DRM_USAC = 147 /**< Virtual AOT for DRM with USAC */ + +} AUDIO_OBJECT_TYPE; + +#define CAN_DO_PS(aot) \ + ((aot) == AOT_AAC_LC || (aot) == AOT_SBR || (aot) == AOT_PS || \ + (aot) == AOT_ER_BSAC || (aot) == AOT_DRM_AAC) + +#define IS_USAC(aot) ((aot) == AOT_USAC) + +#define IS_LOWDELAY(aot) ((aot) == AOT_ER_AAC_LD || (aot) == AOT_ER_AAC_ELD) + +/** Channel Mode ( 1-7 equals MPEG channel configurations, others are + * arbitrary). */ +typedef enum { + MODE_INVALID = -1, + MODE_UNKNOWN = 0, + MODE_1 = 1, /**< C */ + MODE_2 = 2, /**< L+R */ + MODE_1_2 = 3, /**< C, L+R */ + MODE_1_2_1 = 4, /**< C, L+R, Rear */ + MODE_1_2_2 = 5, /**< C, L+R, LS+RS */ + MODE_1_2_2_1 = 6, /**< C, L+R, LS+RS, LFE */ + MODE_1_2_2_2_1 = 7, /**< C, LC+RC, L+R, LS+RS, LFE */ + + MODE_6_1 = 11, /**< C, L+R, LS+RS, Crear, LFE */ + MODE_7_1_BACK = 12, /**< C, L+R, LS+RS, Lrear+Rrear, LFE */ + MODE_7_1_TOP_FRONT = 14, /**< C, L+R, LS+RS, LFE, Ltop+Rtop */ + + MODE_7_1_REAR_SURROUND = 33, /**< C, L+R, LS+RS, Lrear+Rrear, LFE */ + MODE_7_1_FRONT_CENTER = 34, /**< C, LC+RC, L+R, LS+RS, LFE */ + + MODE_212 = 128 /**< 212 configuration, used in ELDv2 */ + +} CHANNEL_MODE; + +/** + * Speaker description tags. + * Do not change the enumeration values unless it keeps the following + * segmentation: + * - Bit 0-3: Horizontal postion (0: none, 1: front, 2: side, 3: back, 4: lfe) + * - Bit 4-7: Vertical position (0: normal, 1: top, 2: bottom) + */ +typedef enum { + ACT_NONE = 0x00, + ACT_FRONT = 0x01, /*!< Front speaker position (at normal height) */ + ACT_SIDE = 0x02, /*!< Side speaker position (at normal height) */ + ACT_BACK = 0x03, /*!< Back speaker position (at normal height) */ + ACT_LFE = 0x04, /*!< Low frequency effect speaker postion (front) */ + + ACT_TOP = + 0x10, /*!< Top speaker area (for combination with speaker positions) */ + ACT_FRONT_TOP = 0x11, /*!< Top front speaker = (ACT_FRONT|ACT_TOP) */ + ACT_SIDE_TOP = 0x12, /*!< Top side speaker = (ACT_SIDE |ACT_TOP) */ + ACT_BACK_TOP = 0x13, /*!< Top back speaker = (ACT_BACK |ACT_TOP) */ + + ACT_BOTTOM = + 0x20, /*!< Bottom speaker area (for combination with speaker positions) */ + ACT_FRONT_BOTTOM = 0x21, /*!< Bottom front speaker = (ACT_FRONT|ACT_BOTTOM) */ + ACT_SIDE_BOTTOM = 0x22, /*!< Bottom side speaker = (ACT_SIDE |ACT_BOTTOM) */ + ACT_BACK_BOTTOM = 0x23 /*!< Bottom back speaker = (ACT_BACK |ACT_BOTTOM) */ + +} AUDIO_CHANNEL_TYPE; + +typedef enum { + SIG_UNKNOWN = -1, + SIG_IMPLICIT = 0, + SIG_EXPLICIT_BW_COMPATIBLE = 1, + SIG_EXPLICIT_HIERARCHICAL = 2 + +} SBR_PS_SIGNALING; + +/** + * Audio Codec flags. + */ +#define AC_ER_VCB11 \ + 0x000001 /*!< aacSectionDataResilienceFlag flag (from ASC): 1 means use \ + virtual codebooks */ +#define AC_ER_RVLC \ + 0x000002 /*!< aacSpectralDataResilienceFlag flag (from ASC): 1 means use \ + huffman codeword reordering */ +#define AC_ER_HCR \ + 0x000004 /*!< aacSectionDataResilienceFlag flag (from ASC): 1 means use \ + virtual codebooks */ +#define AC_SCALABLE 0x000008 /*!< AAC Scalable*/ +#define AC_ELD 0x000010 /*!< AAC-ELD */ +#define AC_LD 0x000020 /*!< AAC-LD */ +#define AC_ER 0x000040 /*!< ER syntax */ +#define AC_BSAC 0x000080 /*!< BSAC */ +#define AC_USAC 0x000100 /*!< USAC */ +#define AC_RSV603DA 0x000200 /*!< RSVD60 3D audio */ +#define AC_HDAAC 0x000400 /*!< HD-AAC */ +#define AC_RSVD50 0x004000 /*!< Rsvd50 */ +#define AC_SBR_PRESENT 0x008000 /*!< SBR present flag (from ASC) */ +#define AC_SBRCRC \ + 0x010000 /*!< SBR CRC present flag. Only relevant for AAC-ELD for now. */ +#define AC_PS_PRESENT 0x020000 /*!< PS present flag (from ASC or implicit) */ +#define AC_MPS_PRESENT \ + 0x040000 /*!< MPS present flag (from ASC or implicit) \ + */ +#define AC_DRM 0x080000 /*!< DRM bit stream syntax */ +#define AC_INDEP 0x100000 /*!< Independency flag */ +#define AC_MPEGD_RES 0x200000 /*!< MPEG-D residual individual channel data. */ +#define AC_SAOC_PRESENT 0x400000 /*!< SAOC Present Flag */ +#define AC_DAB 0x800000 /*!< DAB bit stream syntax */ +#define AC_ELD_DOWNSCALE 0x1000000 /*!< ELD Downscaled playout */ +#define AC_LD_MPS 0x2000000 /*!< Low Delay MPS. */ +#define AC_DRC_PRESENT \ + 0x4000000 /*!< Dynamic Range Control (DRC) data found. \ + */ +#define AC_USAC_SCFGI3 \ + 0x8000000 /*!< USAC flag: If stereoConfigIndex is 3 the flag is set. */ +/** + * Audio Codec flags (reconfiguration). + */ +#define AC_CM_DET_CFG_CHANGE \ + 0x000001 /*!< Config mode signalizes the callback to work in config change \ + detection mode */ +#define AC_CM_ALLOC_MEM \ + 0x000002 /*!< Config mode signalizes the callback to work in memory \ + allocation mode */ + +/** + * Audio Codec flags (element specific). + */ +#define AC_EL_USAC_TW 0x000001 /*!< USAC time warped filter bank is active */ +#define AC_EL_USAC_NOISE 0x000002 /*!< USAC noise filling is active */ +#define AC_EL_USAC_ITES 0x000004 /*!< USAC SBR inter-TES tool is active */ +#define AC_EL_USAC_PVC \ + 0x000008 /*!< USAC SBR predictive vector coding tool is active */ +#define AC_EL_USAC_MPS212 0x000010 /*!< USAC MPS212 tool is active */ +#define AC_EL_USAC_LFE 0x000020 /*!< USAC element is LFE */ +#define AC_EL_USAC_CP_POSSIBLE \ + 0x000040 /*!< USAC may use Complex Stereo Prediction in this channel element \ + */ +#define AC_EL_ENHANCED_NOISE 0x000080 /*!< Enhanced noise filling*/ +#define AC_EL_IGF_AFTER_TNS 0x000100 /*!< IGF after TNS */ +#define AC_EL_IGF_INDEP_TILING 0x000200 /*!< IGF independent tiling */ +#define AC_EL_IGF_USE_ENF 0x000400 /*!< IGF use enhanced noise filling */ +#define AC_EL_FULLBANDLPD 0x000800 /*!< enable fullband LPD tools */ +#define AC_EL_LPDSTEREOIDX 0x001000 /*!< LPD-stereo-tool stereo index */ +#define AC_EL_LFE 0x002000 /*!< The element is of type LFE. */ + +/* CODER_CONFIG::flags */ +#define CC_MPEG_ID 0x00100000 +#define CC_IS_BASELAYER 0x00200000 +#define CC_PROTECTION 0x00400000 +#define CC_SBR 0x00800000 +#define CC_SBRCRC 0x00010000 +#define CC_SAC 0x00020000 +#define CC_RVLC 0x01000000 +#define CC_VCB11 0x02000000 +#define CC_HCR 0x04000000 +#define CC_PSEUDO_SURROUND 0x08000000 +#define CC_USAC_NOISE 0x10000000 +#define CC_USAC_TW 0x20000000 +#define CC_USAC_HBE 0x40000000 + +/** Generic audio coder configuration structure. */ +typedef struct { + AUDIO_OBJECT_TYPE aot; /**< Audio Object Type (AOT). */ + AUDIO_OBJECT_TYPE extAOT; /**< Extension Audio Object Type (SBR). */ + CHANNEL_MODE channelMode; /**< Channel mode. */ + UCHAR channelConfigZero; /**< Use channel config zero + pce although a + standard channel config could be signaled. */ + INT samplingRate; /**< Sampling rate. */ + INT extSamplingRate; /**< Extended samplerate (SBR). */ + INT downscaleSamplingRate; /**< Downscale sampling rate (ELD downscaled mode) + */ + INT bitRate; /**< Average bitrate. */ + int samplesPerFrame; /**< Number of PCM samples per codec frame and audio + channel. */ + int noChannels; /**< Number of audio channels. */ + int bitsFrame; + int nSubFrames; /**< Amount of encoder subframes. 1 means no subframing. */ + int BSACnumOfSubFrame; /**< The number of the sub-frames which are grouped and + transmitted in a super-frame (BSAC). */ + int BSAClayerLength; /**< The average length of the large-step layers in bytes + (BSAC). */ + UINT flags; /**< flags */ + UCHAR matrixMixdownA; /**< Matrix mixdown index to put into PCE. Default value + 0 means no mixdown coefficient, valid values are 1-4 + which correspond to matrix_mixdown_idx 0-3. */ + UCHAR headerPeriod; /**< Frame period for sending in band configuration + buffers in the transport layer. */ + + UCHAR stereoConfigIndex; /**< USAC MPS stereo mode */ + UCHAR sbrMode; /**< USAC SBR mode */ + SBR_PS_SIGNALING sbrSignaling; /**< 0: implicit signaling, 1: backwards + compatible explicit signaling, 2: + hierarcical explicit signaling */ + + UCHAR rawConfig[64]; /**< raw codec specific config as bit stream */ + int rawConfigBits; /**< Size of rawConfig in bits */ + + UCHAR sbrPresent; + UCHAR psPresent; +} CODER_CONFIG; + +#define USAC_ID_BIT 16 /** USAC element IDs start at USAC_ID_BIT */ + +/** MP4 Element IDs. */ +typedef enum { + /* mp4 element IDs */ + ID_NONE = -1, /**< Invalid Element helper ID. */ + ID_SCE = 0, /**< Single Channel Element. */ + ID_CPE = 1, /**< Channel Pair Element. */ + ID_CCE = 2, /**< Coupling Channel Element. */ + ID_LFE = 3, /**< LFE Channel Element. */ + ID_DSE = 4, /**< Currently one Data Stream Element for ancillary data is + supported. */ + ID_PCE = 5, /**< Program Config Element. */ + ID_FIL = 6, /**< Fill Element. */ + ID_END = 7, /**< Arnie (End Element = Terminator). */ + ID_EXT = 8, /**< Extension Payload (ER only). */ + ID_SCAL = 9, /**< AAC scalable element (ER only). */ + /* USAC element IDs */ + ID_USAC_SCE = 0 + USAC_ID_BIT, /**< Single Channel Element. */ + ID_USAC_CPE = 1 + USAC_ID_BIT, /**< Channel Pair Element. */ + ID_USAC_LFE = 2 + USAC_ID_BIT, /**< LFE Channel Element. */ + ID_USAC_EXT = 3 + USAC_ID_BIT, /**< Extension Element. */ + ID_USAC_END = 4 + USAC_ID_BIT, /**< Arnie (End Element = Terminator). */ + ID_LAST +} MP4_ELEMENT_ID; + +/* usacConfigExtType q.v. ISO/IEC DIS 23008-3 Table 52 and ISO/IEC FDIS + * 23003-3:2011(E) Table 74*/ +typedef enum { + /* USAC and RSVD60 3DA */ + ID_CONFIG_EXT_FILL = 0, + /* RSVD60 3DA */ + ID_CONFIG_EXT_DOWNMIX = 1, + ID_CONFIG_EXT_LOUDNESS_INFO = 2, + ID_CONFIG_EXT_AUDIOSCENE_INFO = 3, + ID_CONFIG_EXT_HOA_MATRIX = 4, + ID_CONFIG_EXT_SIG_GROUP_INFO = 6 + /* 5-127 => reserved for ISO use */ + /* > 128 => reserved for use outside of ISO scope */ +} CONFIG_EXT_ID; + +#define IS_CHANNEL_ELEMENT(elementId) \ + ((elementId) == ID_SCE || (elementId) == ID_CPE || (elementId) == ID_LFE || \ + (elementId) == ID_USAC_SCE || (elementId) == ID_USAC_CPE || \ + (elementId) == ID_USAC_LFE) + +#define IS_MP4_CHANNEL_ELEMENT(elementId) \ + ((elementId) == ID_SCE || (elementId) == ID_CPE || (elementId) == ID_LFE) + +#define EXT_ID_BITS 4 /**< Size in bits of extension payload type tags. */ + +/** Extension payload types. */ +typedef enum { + EXT_FIL = 0x00, + EXT_FILL_DATA = 0x01, + EXT_DATA_ELEMENT = 0x02, + EXT_DATA_LENGTH = 0x03, + EXT_UNI_DRC = 0x04, + EXT_LDSAC_DATA = 0x09, + EXT_SAOC_DATA = 0x0a, + EXT_DYNAMIC_RANGE = 0x0b, + EXT_SAC_DATA = 0x0c, + EXT_SBR_DATA = 0x0d, + EXT_SBR_DATA_CRC = 0x0e +} EXT_PAYLOAD_TYPE; + +#define IS_USAC_CHANNEL_ELEMENT(elementId) \ + ((elementId) == ID_USAC_SCE || (elementId) == ID_USAC_CPE || \ + (elementId) == ID_USAC_LFE) + +/** MPEG-D USAC & RSVD60 3D audio Extension Element Types. */ +typedef enum { + /* usac */ + ID_EXT_ELE_FILL = 0x00, + ID_EXT_ELE_MPEGS = 0x01, + ID_EXT_ELE_SAOC = 0x02, + ID_EXT_ELE_AUDIOPREROLL = 0x03, + ID_EXT_ELE_UNI_DRC = 0x04, + /* rsv603da */ + ID_EXT_ELE_OBJ_METADATA = 0x05, + ID_EXT_ELE_SAOC_3D = 0x06, + ID_EXT_ELE_HOA = 0x07, + ID_EXT_ELE_FMT_CNVRTR = 0x08, + ID_EXT_ELE_MCT = 0x09, + ID_EXT_ELE_ENHANCED_OBJ_METADATA = 0x0d, + /* reserved for use outside of ISO scope */ + ID_EXT_ELE_VR_METADATA = 0x81, + ID_EXT_ELE_UNKNOWN = 0xFF +} USAC_EXT_ELEMENT_TYPE; + +/** + * Proprietary raw packet file configuration data type identifier. + */ +typedef enum { + TC_NOTHING = 0, /* No configuration available -> in-band configuration. */ + TC_RAW_ADTS = 2, /* Transfer type is ADTS. */ + TC_RAW_LATM_MCP1 = 6, /* Transfer type is LATM with SMC present. */ + TC_RAW_SDC = 21 /* Configuration data field is Drm SDC. */ + +} TP_CONFIG_TYPE; + +/* + * ############################################################################################## + * Library identification and error handling + * ############################################################################################## + */ +/* \cond */ + +typedef enum { + FDK_NONE = 0, + FDK_TOOLS = 1, + FDK_SYSLIB = 2, + FDK_AACDEC = 3, + FDK_AACENC = 4, + FDK_SBRDEC = 5, + FDK_SBRENC = 6, + FDK_TPDEC = 7, + FDK_TPENC = 8, + FDK_MPSDEC = 9, + FDK_MPEGFILEREAD = 10, + FDK_MPEGFILEWRITE = 11, + FDK_PCMDMX = 31, + FDK_MPSENC = 34, + FDK_TDLIMIT = 35, + FDK_UNIDRCDEC = 38, + + FDK_MODULE_LAST + +} FDK_MODULE_ID; + +/* AAC capability flags */ +#define CAPF_AAC_LC 0x00000001 /**< Support flag for AAC Low Complexity. */ +#define CAPF_ER_AAC_LD \ + 0x00000002 /**< Support flag for AAC Low Delay with Error Resilience tools. \ + */ +#define CAPF_ER_AAC_SCAL 0x00000004 /**< Support flag for AAC Scalable. */ +#define CAPF_ER_AAC_LC \ + 0x00000008 /**< Support flag for AAC Low Complexity with Error Resilience \ + tools. */ +#define CAPF_AAC_480 \ + 0x00000010 /**< Support flag for AAC with 480 framelength. */ +#define CAPF_AAC_512 \ + 0x00000020 /**< Support flag for AAC with 512 framelength. */ +#define CAPF_AAC_960 \ + 0x00000040 /**< Support flag for AAC with 960 framelength. */ +#define CAPF_AAC_1024 \ + 0x00000080 /**< Support flag for AAC with 1024 framelength. */ +#define CAPF_AAC_HCR \ + 0x00000100 /**< Support flag for AAC with Huffman Codeword Reordering. */ +#define CAPF_AAC_VCB11 \ + 0x00000200 /**< Support flag for AAC Virtual Codebook 11. */ +#define CAPF_AAC_RVLC \ + 0x00000400 /**< Support flag for AAC Reversible Variable Length Coding. */ +#define CAPF_AAC_MPEG4 0x00000800 /**< Support flag for MPEG file format. */ +#define CAPF_AAC_DRC \ + 0x00001000 /**< Support flag for AAC Dynamic Range Control. */ +#define CAPF_AAC_CONCEALMENT \ + 0x00002000 /**< Support flag for AAC concealment. */ +#define CAPF_AAC_DRM_BSFORMAT \ + 0x00004000 /**< Support flag for AAC DRM bistream format. */ +#define CAPF_ER_AAC_ELD \ + 0x00008000 /**< Support flag for AAC Enhanced Low Delay with Error \ + Resilience tools. */ +#define CAPF_ER_AAC_BSAC \ + 0x00010000 /**< Support flag for AAC BSAC. */ +#define CAPF_AAC_ELD_DOWNSCALE \ + 0x00040000 /**< Support flag for AAC-ELD Downscaling */ +#define CAPF_AAC_USAC_LP \ + 0x00100000 /**< Support flag for USAC low power mode. */ +#define CAPF_AAC_USAC \ + 0x00200000 /**< Support flag for Unified Speech and Audio Coding (USAC). */ +#define CAPF_ER_AAC_ELDV2 \ + 0x00800000 /**< Support flag for AAC Enhanced Low Delay with MPS 212. */ +#define CAPF_AAC_UNIDRC \ + 0x01000000 /**< Support flag for MPEG-D Dynamic Range Control (uniDrc). */ + +/* Transport capability flags */ +#define CAPF_ADTS \ + 0x00000001 /**< Support flag for ADTS transport format. */ +#define CAPF_ADIF \ + 0x00000002 /**< Support flag for ADIF transport format. */ +#define CAPF_LATM \ + 0x00000004 /**< Support flag for LATM transport format. */ +#define CAPF_LOAS \ + 0x00000008 /**< Support flag for LOAS transport format. */ +#define CAPF_RAWPACKETS \ + 0x00000010 /**< Support flag for RAW PACKETS transport format. */ +#define CAPF_DRM \ + 0x00000020 /**< Support flag for DRM/DRM+ transport format. */ +#define CAPF_RSVD50 \ + 0x00000040 /**< Support flag for RSVD50 transport format */ + +/* SBR capability flags */ +#define CAPF_SBR_LP \ + 0x00000001 /**< Support flag for SBR Low Power mode. */ +#define CAPF_SBR_HQ \ + 0x00000002 /**< Support flag for SBR High Quality mode. */ +#define CAPF_SBR_DRM_BS \ + 0x00000004 /**< Support flag for */ +#define CAPF_SBR_CONCEALMENT \ + 0x00000008 /**< Support flag for SBR concealment. */ +#define CAPF_SBR_DRC \ + 0x00000010 /**< Support flag for SBR Dynamic Range Control. */ +#define CAPF_SBR_PS_MPEG \ + 0x00000020 /**< Support flag for MPEG Parametric Stereo. */ +#define CAPF_SBR_PS_DRM \ + 0x00000040 /**< Support flag for DRM Parametric Stereo. */ +#define CAPF_SBR_ELD_DOWNSCALE \ + 0x00000080 /**< Support flag for ELD reduced delay mode */ +#define CAPF_SBR_HBEHQ \ + 0x00000100 /**< Support flag for HQ HBE */ + +/* PCM utils capability flags */ +#define CAPF_DMX_BLIND \ + 0x00000001 /**< Support flag for blind downmixing. */ +#define CAPF_DMX_PCE \ + 0x00000002 /**< Support flag for guided downmix with data from MPEG-2/4 \ + Program Config Elements (PCE). */ +#define CAPF_DMX_ARIB \ + 0x00000004 /**< Support flag for PCE guided downmix with slightly different \ + equations and levels to fulfill ARIB standard. */ +#define CAPF_DMX_DVB \ + 0x00000008 /**< Support flag for guided downmix with data from DVB ancillary \ + data fields. */ +#define CAPF_DMX_CH_EXP \ + 0x00000010 /**< Support flag for simple upmixing by dublicating channels or \ + adding zero channels. */ +#define CAPF_DMX_6_CH \ + 0x00000020 /**< Support flag for 5.1 channel configuration (input and \ + output). */ +#define CAPF_DMX_8_CH \ + 0x00000040 /**< Support flag for 6 and 7.1 channel configurations (input and \ + output). */ +#define CAPF_DMX_24_CH \ + 0x00000080 /**< Support flag for 22.2 channel configuration (input and \ + output). */ +#define CAPF_LIMITER \ + 0x00002000 /**< Support flag for signal level limiting. \ + */ + +/* MPEG Surround capability flags */ +#define CAPF_MPS_STD \ + 0x00000001 /**< Support flag for MPEG Surround. */ +#define CAPF_MPS_LD \ + 0x00000002 /**< Support flag for Low Delay MPEG Surround. \ + */ +#define CAPF_MPS_USAC \ + 0x00000004 /**< Support flag for USAC MPEG Surround. */ +#define CAPF_MPS_HQ \ + 0x00000010 /**< Support flag indicating if high quality processing is \ + supported */ +#define CAPF_MPS_LP \ + 0x00000020 /**< Support flag indicating if partially complex (low power) \ + processing is supported */ +#define CAPF_MPS_BLIND \ + 0x00000040 /**< Support flag indicating if blind processing is supported */ +#define CAPF_MPS_BINAURAL \ + 0x00000080 /**< Support flag indicating if binaural output is possible */ +#define CAPF_MPS_2CH_OUT \ + 0x00000100 /**< Support flag indicating if 2ch output is possible */ +#define CAPF_MPS_6CH_OUT \ + 0x00000200 /**< Support flag indicating if 6ch output is possible */ +#define CAPF_MPS_8CH_OUT \ + 0x00000400 /**< Support flag indicating if 8ch output is possible */ +#define CAPF_MPS_1CH_IN \ + 0x00001000 /**< Support flag indicating if 1ch dmx input is possible */ +#define CAPF_MPS_2CH_IN \ + 0x00002000 /**< Support flag indicating if 2ch dmx input is possible */ +#define CAPF_MPS_6CH_IN \ + 0x00004000 /**< Support flag indicating if 5ch dmx input is possible */ + +/* \endcond */ + +/* + * ############################################################################################## + * Library versioning + * ############################################################################################## + */ + +/** + * Convert each member of version numbers to one single numeric version + * representation. + * \param lev0 1st level of version number. + * \param lev1 2nd level of version number. + * \param lev2 3rd level of version number. + */ +#define LIB_VERSION(lev0, lev1, lev2) \ + ((lev0 << 24 & 0xff000000) | (lev1 << 16 & 0x00ff0000) | \ + (lev2 << 8 & 0x0000ff00)) + +/** + * Build text string of version. + */ +#define LIB_VERSION_STRING(info) \ + FDKsprintf((info)->versionStr, "%d.%d.%d", (((info)->version >> 24) & 0xff), \ + (((info)->version >> 16) & 0xff), \ + (((info)->version >> 8) & 0xff)) + +/** + * Library information. + */ +typedef struct LIB_INFO { + const char* title; + const char* build_date; + const char* build_time; + FDK_MODULE_ID module_id; + INT version; + UINT flags; + char versionStr[32]; +} LIB_INFO; + +#ifdef __cplusplus +#define FDK_AUDIO_INLINE inline +#else +#define FDK_AUDIO_INLINE +#endif + +/** Initialize library info. */ +static FDK_AUDIO_INLINE void FDKinitLibInfo(LIB_INFO* info) { + int i; + + for (i = 0; i < FDK_MODULE_LAST; i++) { + info[i].module_id = FDK_NONE; + } +} + +/** Aquire supported features of library. */ +static FDK_AUDIO_INLINE UINT +FDKlibInfo_getCapabilities(const LIB_INFO* info, FDK_MODULE_ID module_id) { + int i; + + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == module_id) { + return info[i].flags; + } + } + return 0; +} + +/** Search for next free tab. */ +static FDK_AUDIO_INLINE INT FDKlibInfo_lookup(const LIB_INFO* info, + FDK_MODULE_ID module_id) { + int i = -1; + + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == module_id) return -1; + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) return -1; + + return i; +} + +/* + * ############################################################################################## + * Buffer description + * ############################################################################################## + */ + +/** + * I/O buffer descriptor. + */ +typedef struct FDK_bufDescr { + void** ppBase; /*!< Pointer to an array containing buffer base addresses. + Set to NULL for buffer requirement info. */ + UINT* pBufSize; /*!< Pointer to an array containing the number of elements + that can be placed in the specific buffer. */ + UINT* pEleSize; /*!< Pointer to an array containing the element size for each + buffer in bytes. That is mostly the number returned by the + sizeof() operator for the data type used for the specific + buffer. */ + UINT* + pBufType; /*!< Pointer to an array of bit fields containing a description + for each buffer. See XXX below for more details. */ + UINT numBufs; /*!< Total number of buffers. */ + +} FDK_bufDescr; + +/** + * Buffer type description field. + */ +#define FDK_BUF_TYPE_MASK_IO ((UINT)0x03 << 30) +#define FDK_BUF_TYPE_MASK_DESCR ((UINT)0x3F << 16) +#define FDK_BUF_TYPE_MASK_ID ((UINT)0xFF) + +#define FDK_BUF_TYPE_INPUT ((UINT)0x1 << 30) +#define FDK_BUF_TYPE_OUTPUT ((UINT)0x2 << 30) + +#define FDK_BUF_TYPE_PCM_DATA ((UINT)0x1 << 16) +#define FDK_BUF_TYPE_ANC_DATA ((UINT)0x2 << 16) +#define FDK_BUF_TYPE_BS_DATA ((UINT)0x4 << 16) + +#ifdef __cplusplus +} +#endif + +#endif /* FDK_AUDIO_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/genericStds.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/genericStds.h new file mode 100644 index 0000000000000..8828ba77413a3 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/genericStds.h @@ -0,0 +1,584 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* System integration library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/** \file genericStds.h + \brief Generic Run-Time Support function wrappers and heap allocation + monitoring. + */ + +#if !defined(GENERICSTDS_H) +#define GENERICSTDS_H + +#include "machine_type.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 /*!< Pi. Only used in example projects. */ +#endif + +/** + * Identifiers for various memory locations. They are used along with memory + * allocation functions like FDKcalloc_L() to specify the requested memory's + * location. + */ +typedef enum { + /* Internal */ + SECT_DATA_L1 = 0x2000, + SECT_DATA_L2, + SECT_DATA_L1_A, + SECT_DATA_L1_B, + SECT_CONSTDATA_L1, + + /* External */ + SECT_DATA_EXTERN = 0x4000, + SECT_CONSTDATA_EXTERN + +} MEMORY_SECTION; + +/*! \addtogroup SYSLIB_MEMORY_MACROS FDK memory macros + * + * The \c H_ prefix indicates that the macro is to be used in a header file, the + * \c C_ prefix indicates that the macro is to be used in a source file. + * + * Declaring memory areas requires to specify a unique name and a data type. + * + * For defining a memory area you require additionally one or two sizes, + * depending if the memory should be organized into one or two dimensions. + * + * The macros containing the keyword \c AALLOC instead of \c ALLOC additionally + * take care of returning aligned memory addresses (beyond the natural alignment + * of its type). The preprocesor macro + * ::ALIGNMENT_DEFAULT indicates the aligment to be used (this is hardware + * specific). + * + * The \c _L suffix indicates that the memory will be located in a specific + * section. This is useful to allocate critical memory section into fast + * internal SRAM for example. + * + * @{ + */ + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define H_ALLOC_MEM(name, type) \ + type *Get##name(int n = 0); \ + void Free##name(type **p); \ + UINT GetRequiredMem##name(void); + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define H_ALLOC_MEM_OVERLAY(name, type) \ + type *Get##name(int n = 0); \ + void Free##name(type **p); \ + UINT GetRequiredMem##name(void); + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_MEM(name, type, num) \ + type *Get##name(int n) { \ + FDK_ASSERT((n) == 0); \ + return ((type *)FDKcalloc(num, sizeof(type))); \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKfree(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((num) * sizeof(type)); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_MEM2(name, type, n1, n2) \ + type *Get##name(int n) { \ + FDK_ASSERT((n) < (n2)); \ + return ((type *)FDKcalloc(n1, sizeof(type))); \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKfree(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((n1) * sizeof(type)) * (n2); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_MEM(name, type, num) \ + type *Get##name(int n) { \ + type *ap; \ + FDK_ASSERT((n) == 0); \ + ap = ((type *)FDKaalloc((num) * sizeof(type), ALIGNMENT_DEFAULT)); \ + return ap; \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKafree(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((num) * sizeof(type) + ALIGNMENT_DEFAULT + \ + sizeof(void *)); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_MEM2(name, type, n1, n2) \ + type *Get##name(int n) { \ + type *ap; \ + FDK_ASSERT((n) < (n2)); \ + ap = ((type *)FDKaalloc((n1) * sizeof(type), ALIGNMENT_DEFAULT)); \ + return ap; \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKafree(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((n1) * sizeof(type) + ALIGNMENT_DEFAULT + \ + sizeof(void *)) * \ + (n2); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_MEM_L(name, type, num, s) \ + type *Get##name(int n) { \ + FDK_ASSERT((n) == 0); \ + return ((type *)FDKcalloc_L(num, sizeof(type), s)); \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKfree_L(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((num) * sizeof(type)); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_MEM2_L(name, type, n1, n2, s) \ + type *Get##name(int n) { \ + FDK_ASSERT((n) < (n2)); \ + return (type *)FDKcalloc_L(n1, sizeof(type), s); \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKfree_L(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((n1) * sizeof(type)) * (n2); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_MEM_L(name, type, num, s) \ + type *Get##name(int n) { \ + type *ap; \ + FDK_ASSERT((n) == 0); \ + ap = ((type *)FDKaalloc_L((num) * sizeof(type), ALIGNMENT_DEFAULT, s)); \ + return ap; \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKafree_L(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((num) * sizeof(type) + ALIGNMENT_DEFAULT + \ + sizeof(void *)); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_MEM2_L(name, type, n1, n2, s) \ + type *Get##name(int n) { \ + type *ap; \ + FDK_ASSERT((n) < (n2)); \ + ap = ((type *)FDKaalloc_L((n1) * sizeof(type), ALIGNMENT_DEFAULT, s)); \ + return ap; \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKafree_L(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((n1) * sizeof(type) + ALIGNMENT_DEFAULT + \ + sizeof(void *)) * \ + (n2); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_MEM_OVERLAY(name, type, num, sect, tag) \ + C_AALLOC_MEM_L(name, type, num, sect) + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_SCRATCH_START(name, type, n) \ + type _##name[(n) + (ALIGNMENT_DEFAULT + sizeof(type) - 1)]; \ + type *name = (type *)ALIGN_PTR(_##name); \ + C_ALLOC_ALIGNED_REGISTER(name, (n) * sizeof(type)); + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_SCRATCH_START(name, type, n) type name[n]; + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_SCRATCH_END(name, type, n) C_ALLOC_ALIGNED_UNREGISTER(name); +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_SCRATCH_END(name, type, n) + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_STACK_START(name, type, n) \ + type _##name[(n) + (ALIGNMENT_DEFAULT + sizeof(type) - 1)]; \ + type *name = (type *)ALIGN_PTR(_##name); \ + C_ALLOC_ALIGNED_REGISTER(name, (n) * sizeof(type)); + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_STACK_END(name, type, n) C_ALLOC_ALIGNED_UNREGISTER(name); + +/*! @} */ + +#define C_ALLOC_ALIGNED_REGISTER(x, size) +#define C_ALLOC_ALIGNED_UNREGISTER(x) +#define C_ALLOC_ALIGNED_CHECK(x) +#define C_ALLOC_ALIGNED_CHECK2(x, y) +#define FDK_showBacktrace(a, b) + +/*! \addtogroup SYSLIB_EXITCODES Unified exit codes + * Exit codes to be used as return values of FDK software test and + * demonstration applications. Not as return values of product modules and/or + * libraries. + * @{ + */ +#define FDK_EXITCODE_OK 0 /*!< Successful termination. No errors. */ +#define FDK_EXITCODE_USAGE \ + 64 /*!< The command/application was used incorrectly, e.g. with the wrong \ + number of arguments, a bad flag, a bad syntax in a parameter, or \ + whatever. */ +#define FDK_EXITCODE_DATAERROR \ + 65 /*!< The input data was incorrect in some way. This should only be used \ + for user data and not system files. */ +#define FDK_EXITCODE_NOINPUT \ + 66 /*!< An input file (not a system file) did not exist or was not readable. \ + */ +#define FDK_EXITCODE_UNAVAILABLE \ + 69 /*!< A service is unavailable. This can occur if a support program or \ + file does not exist. This can also be used as a catchall message when \ + something you wanted to do doesn't work, but you don't know why. */ +#define FDK_EXITCODE_SOFTWARE \ + 70 /*!< An internal software error has been detected. This should be limited \ + to non- operating system related errors as possible. */ +#define FDK_EXITCODE_CANTCREATE \ + 73 /*!< A (user specified) output file cannot be created. */ +#define FDK_EXITCODE_IOERROR \ + 74 /*!< An error occurred while doing I/O on some file. */ +/*! @} */ + +/*-------------------------------------------- + * Runtime support declarations + *---------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif + +void FDKprintf(const char *szFmt, ...); + +void FDKprintfErr(const char *szFmt, ...); + +/** Wrapper for 's getchar(). */ +int FDKgetchar(void); + +INT FDKfprintf(void *stream, const char *format, ...); +INT FDKsprintf(char *str, const char *format, ...); + +char *FDKstrchr(char *s, INT c); +const char *FDKstrstr(const char *haystack, const char *needle); +char *FDKstrcpy(char *dest, const char *src); +char *FDKstrncpy(char *dest, const char *src, const UINT n); + +#define FDK_MAX_OVERLAYS 8 /**< Maximum number of memory overlays. */ + +void *FDKcalloc(const UINT n, const UINT size); +void *FDKmalloc(const UINT size); +void FDKfree(void *ptr); + +/** + * Allocate and clear an aligned memory area. Use FDKafree() instead of + * FDKfree() for these memory areas. + * + * \param size Size of requested memory in bytes. + * \param alignment Alignment of requested memory in bytes. + * \return Pointer to allocated memory. + */ +void *FDKaalloc(const UINT size, const UINT alignment); + +/** + * Free an aligned memory area. + * + * \param ptr Pointer to be freed. + */ +void FDKafree(void *ptr); + +/** + * Allocate memory in a specific memory section. + * Requests can be made for internal or external memory. If internal memory is + * requested, FDKcalloc_L() first tries to use L1 memory, which sizes are + * defined by ::DATA_L1_A_SIZE and ::DATA_L1_B_SIZE. If no L1 memory is + * available, then FDKcalloc_L() tries to use L2 memory. If that fails as well, + * the requested memory is allocated at an extern location using the fallback + * FDKcalloc(). + * + * \param n See MSDN documentation on calloc(). + * \param size See MSDN documentation on calloc(). + * \param s Memory section. + * \return See MSDN documentation on calloc(). + */ +void *FDKcalloc_L(const UINT n, const UINT size, MEMORY_SECTION s); + +/** + * Allocate aligned memory in a specific memory section. + * See FDKcalloc_L() description for details - same applies here. + */ +void *FDKaalloc_L(const UINT size, const UINT alignment, MEMORY_SECTION s); + +/** + * Free memory that was allocated in a specific memory section. + */ +void FDKfree_L(void *ptr); + +/** + * Free aligned memory that was allocated in a specific memory section. + */ +void FDKafree_L(void *ptr); + +/** + * Copy memory. Source and destination memory must not overlap. + * Either use implementation from a Standard Library, or, if no Standard Library + * is available, a generic implementation. + * The define ::USE_BUILTIN_MEM_FUNCTIONS in genericStds.cpp controls what to + * use. The function arguments correspond to the standard memcpy(). Please see + * MSDN documentation for details on how to use it. + */ +void FDKmemcpy(void *dst, const void *src, const UINT size); + +/** + * Copy memory. Source and destination memory are allowed to overlap. + * Either use implementation from a Standard Library, or, if no Standard Library + * is available, a generic implementation. + * The define ::USE_BUILTIN_MEM_FUNCTIONS in genericStds.cpp controls what to + * use. The function arguments correspond to the standard memmove(). Please see + * MSDN documentation for details on how to use it. + */ +void FDKmemmove(void *dst, const void *src, const UINT size); + +/** + * Clear memory. + * Either use implementation from a Standard Library, or, if no Standard Library + * is available, a generic implementation. + * The define ::USE_BUILTIN_MEM_FUNCTIONS in genericStds.cpp controls what to + * use. The function arguments correspond to the standard memclear(). Please see + * MSDN documentation for details on how to use it. + */ +void FDKmemclear(void *memPtr, const UINT size); + +/** + * Fill memory with values. + * The function arguments correspond to the standard memset(). Please see MSDN + * documentation for details on how to use it. + */ +void FDKmemset(void *memPtr, const INT value, const UINT size); + +/* Compare function wrappers */ +INT FDKmemcmp(const void *s1, const void *s2, const UINT size); +INT FDKstrcmp(const char *s1, const char *s2); +INT FDKstrncmp(const char *s1, const char *s2, const UINT size); + +UINT FDKstrlen(const char *s); + +#define FDKmax(a, b) ((a) > (b) ? (a) : (b)) +#define FDKmin(a, b) ((a) < (b) ? (a) : (b)) + +#define FDK_INT_MAX ((INT)0x7FFFFFFF) +#define FDK_INT_MIN ((INT)0x80000000) + +/* FILE I/O */ + +/*! + * Check platform for endianess. + * + * \return 1 if platform is little endian, non-1 if platform is big endian. + */ +int IS_LITTLE_ENDIAN(void); + +/*! + * Convert input value to little endian format. + * + * \param val Value to be converted. It may be in both big or little endian. + * \return Value in little endian format. + */ +UINT TO_LITTLE_ENDIAN(UINT val); + +/*! + * \fn FDKFILE *FDKfopen(const char *filename, const char *mode); + * Standard fopen() wrapper. + * \fn INT FDKfclose(FDKFILE *FP); + * Standard fclose() wrapper. + * \fn INT FDKfseek(FDKFILE *FP, LONG OFFSET, int WHENCE); + * Standard fseek() wrapper. + * \fn INT FDKftell(FDKFILE *FP); + * Standard ftell() wrapper. + * \fn INT FDKfflush(FDKFILE *fp); + * Standard fflush() wrapper. + * \fn UINT FDKfwrite(const void *ptrf, INT size, UINT nmemb, FDKFILE *fp); + * Standard fwrite() wrapper. + * \fn UINT FDKfread(void *dst, INT size, UINT nmemb, FDKFILE *fp); + * Standard fread() wrapper. + */ +typedef void FDKFILE; +extern const INT FDKSEEK_SET, FDKSEEK_CUR, FDKSEEK_END; + +FDKFILE *FDKfopen(const char *filename, const char *mode); +INT FDKfclose(FDKFILE *FP); +INT FDKfseek(FDKFILE *FP, LONG OFFSET, int WHENCE); +INT FDKftell(FDKFILE *FP); +INT FDKfflush(FDKFILE *fp); +UINT FDKfwrite(const void *ptrf, INT size, UINT nmemb, FDKFILE *fp); +UINT FDKfread(void *dst, INT size, UINT nmemb, FDKFILE *fp); +char *FDKfgets(void *dst, INT size, FDKFILE *fp); +void FDKrewind(FDKFILE *fp); +INT FDKfeof(FDKFILE *fp); + +/** + * \brief Write each member in little endian order. Convert automatically + * to host endianess. + * \param ptrf Pointer to memory where to read data from. + * \param size Size of each item to be written. + * \param nmemb Number of items to be written. + * \param fp File pointer of type FDKFILE. + * \return Number of items read on success and fread() error on failure. + */ +UINT FDKfwrite_EL(const void *ptrf, INT size, UINT nmemb, FDKFILE *fp); + +/** + * \brief Read variable of size "size" as little endian. Convert + * automatically to host endianess. 4-byte alignment is enforced for 24 bit + * data, at 32 bit full scale. + * \param dst Pointer to memory where to store data into. + * \param size Size of each item to be read. + * \param nmemb Number of items to be read. + * \param fp File pointer of type FDKFILE. + * \return Number of items read on success and fread() error on failure. + */ +UINT FDKfread_EL(void *dst, INT size, UINT nmemb, FDKFILE *fp); + +/** + * \brief Print FDK software disclaimer. + */ +void FDKprintDisclaimer(void); + +#ifdef __cplusplus +} +#endif + +#endif /* GENERICSTDS_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/machine_type.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/machine_type.h new file mode 100644 index 0000000000000..bd97669c36681 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/machine_type.h @@ -0,0 +1,411 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* System integration library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/** \file machine_type.h + * \brief Type defines for various processors and compiler tools. + */ + +#if !defined(MACHINE_TYPE_H) +#define MACHINE_TYPE_H + +#include /* Needed to define size_t */ + +#if defined(__ANDROID__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 4) && \ + (__GNUC_GNU_INLINE__ == 1) +typedef unsigned long long uint64_t; +#include +#endif + +/* Library calling convention spec. __cdecl and friends might be added here as + * required. */ +#define LINKSPEC_H +#define LINKSPEC_CPP + +/* for doxygen the following docu parts must be separated */ +/** \var SCHAR + * Data type representing at least 1 byte signed integer on all supported + * platforms. + */ +/** \var UCHAR + * Data type representing at least 1 byte unsigned integer on all + * supported platforms. + */ +/** \var INT + * Data type representing at least 4 byte signed integer on all supported + * platforms. + */ +/** \var UINT + * Data type representing at least 4 byte unsigned integer on all + * supported platforms. + */ +/** \var LONG + * Data type representing 4 byte signed integer on all supported + * platforms. + */ +/** \var ULONG + * Data type representing 4 byte unsigned integer on all supported + * platforms. + */ +/** \var SHORT + * Data type representing 2 byte signed integer on all supported + * platforms. + */ +/** \var USHORT + * Data type representing 2 byte unsigned integer on all supported + * platforms. + */ +/** \var INT64 + * Data type representing 8 byte signed integer on all supported + * platforms. + */ +/** \var UINT64 + * Data type representing 8 byte unsigned integer on all supported + * platforms. + */ +/** \def SHORT_BITS + * Number of bits the data type short represents. sizeof() is not suited + * to get this info, because a byte is not always defined as 8 bits. + */ +/** \def CHAR_BITS + * Number of bits the data type char represents. sizeof() is not suited + * to get this info, because a byte is not always defined as 8 bits. + */ +/** \var INT_PCM + * Data type representing the width of input and output PCM samples. + */ + +typedef signed int INT; +typedef unsigned int UINT; +#ifdef __LP64__ +/* force FDK long-datatypes to 4 byte */ +/* Use defines to avoid type alias problems on 64 bit machines. */ +#define LONG INT +#define ULONG UINT +#else /* __LP64__ */ +typedef signed long LONG; +typedef unsigned long ULONG; +#endif /* __LP64__ */ +typedef signed short SHORT; +typedef unsigned short USHORT; +typedef signed char SCHAR; +typedef unsigned char UCHAR; + +#define SHORT_BITS 16 +#define CHAR_BITS 8 + +/* Define 64 bit base integer type. */ +#ifdef _MSC_VER +typedef __int64 INT64; +typedef unsigned __int64 UINT64; +#else +typedef long long INT64; +typedef unsigned long long UINT64; +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#if ((defined(__i686__) || defined(__i586__) || defined(__i386__) || \ + defined(__x86_64__)) || \ + (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)))) && \ + !defined(FDK_ASSERT_ENABLE) +#define FDK_ASSERT_ENABLE +#endif + +#if defined(FDK_ASSERT_ENABLE) +#include +#define FDK_ASSERT(x) assert(x) +#else +#define FDK_ASSERT(ignore) +#endif + +typedef SHORT INT_PCM; +#define MAXVAL_PCM MAXVAL_SGL +#define MINVAL_PCM MINVAL_SGL +#define WAV_BITS 16 +#define SAMPLE_BITS 16 +#define SAMPLE_MAX ((INT_PCM)(((ULONG)1 << (SAMPLE_BITS - 1)) - 1)) +#define SAMPLE_MIN (~SAMPLE_MAX) + +/*! +* \def RAM_ALIGN +* Used to align memory as prefix before memory declaration. For example: + \code + RAM_ALIGN + int myArray[16]; + \endcode + + Note, that not all platforms support this mechanism. For example with TI +compilers a preprocessor pragma is used, but to do something like + + \code + #define RAM_ALIGN #pragma DATA_ALIGN(x) + \endcode + + would require the preprocessor to process this line twice to fully resolve +it. Hence, a fully platform-independant way to use alignment is not supported. + +* \def ALIGNMENT_DEFAULT +* Default alignment in bytes. +*/ + +#define ALIGNMENT_DEFAULT 8 + +/* RAM_ALIGN keyword causes memory alignment of global variables. */ +#if defined(_MSC_VER) +#define RAM_ALIGN __declspec(align(ALIGNMENT_DEFAULT)) +#elif defined(__GNUC__) +#define RAM_ALIGN __attribute__((aligned(ALIGNMENT_DEFAULT))) +#else +#define RAM_ALIGN +#endif + +/*! + * \def RESTRICT + * The restrict keyword is supported by some platforms and RESTRICT maps + * to either the corresponding keyword on each platform or to void if the + * compiler does not provide such feature. It tells the compiler that a + * pointer points to memory that does not overlap with other memories pointed to + * by other pointers. If this keyword is used and the assumption of no + * overlap is not true the resulting code might crash. + * + * \def WORD_ALIGNED(x) + * Tells the compiler that pointer x is 16 bit aligned. It does not cause + * the address itself to be aligned, but serves as a hint to the optimizer. The + * alignment of the pointer must be guarranteed, if not the code might + * crash. + * + * \def DWORD_ALIGNED(x) + * Tells the compiler that pointer x is 32 bit aligned. It does not cause + * the address itself to be aligned, but serves as a hint to the optimizer. The + * alignment of the pointer must be guarranteed, if not the code might + * crash. + * + */ +#define RESTRICT +#define WORD_ALIGNED(x) C_ALLOC_ALIGNED_CHECK2((const void *)(x), 2); +#define DWORD_ALIGNED(x) C_ALLOC_ALIGNED_CHECK2((const void *)(x), 4); + +/*----------------------------------------------------------------------------------- + * ALIGN_SIZE + *-----------------------------------------------------------------------------------*/ +/*! + * \brief This macro aligns a given value depending on ::ALIGNMENT_DEFAULT. + * + * For example if #ALIGNMENT_DEFAULT equals 8, then: + * - ALIGN_SIZE(3) returns 8 + * - ALIGN_SIZE(8) returns 8 + * - ALIGN_SIZE(9) returns 16 + */ +#define ALIGN_SIZE(a) \ + ((a) + (((INT)ALIGNMENT_DEFAULT - ((size_t)(a) & (ALIGNMENT_DEFAULT - 1))) & \ + (ALIGNMENT_DEFAULT - 1))) + +/*! + * \brief This macro aligns a given address depending on ::ALIGNMENT_DEFAULT. + */ +#define ALIGN_PTR(a) \ + ((void *)((unsigned char *)(a) + \ + ((((INT)ALIGNMENT_DEFAULT - \ + ((size_t)(a) & (ALIGNMENT_DEFAULT - 1))) & \ + (ALIGNMENT_DEFAULT - 1))))) + +/* Alignment macro for libSYS heap implementation */ +#define ALIGNMENT_EXTRES (ALIGNMENT_DEFAULT) +#define ALGN_SIZE_EXTRES(a) \ + ((a) + (((INT)ALIGNMENT_EXTRES - ((INT)(a) & (ALIGNMENT_EXTRES - 1))) & \ + (ALIGNMENT_EXTRES - 1))) + +/*! + * \def FDK_FORCEINLINE + * Sometimes compiler do not do what they are told to do, and in case of + * inlining some additional command might be necessary depending on the + * platform. + * + * \def FDK_INLINE + * Defines how the compiler is told to inline stuff. + */ +#ifndef FDK_FORCEINLINE +#if defined(__GNUC__) && !defined(__SDE_MIPS__) +#define FDK_FORCEINLINE inline __attribute((always_inline)) +#else +#define FDK_FORCEINLINE inline +#endif +#endif + +#define FDK_INLINE static inline + +/*! + * \def LNK_SECTION_DATA_L1 + * The LNK_SECTION_* defines allow memory to be drawn from specific memory + * sections. Used as prefix before variable declaration. + * + * \def LNK_SECTION_DATA_L2 + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_L1_DATA_A + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_L1_DATA_B + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_CONSTDATA_L1 + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_CONSTDATA + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_CODE_L1 + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_CODE_L2 + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_INITCODE + * See ::LNK_SECTION_DATA_L1 + */ +/************************************************** + * Code Section macros + **************************************************/ +#define LNK_SECTION_CODE_L1 +#define LNK_SECTION_CODE_L2 +#define LNK_SECTION_INITCODE + +/* Memory section macros. */ + +/* default fall back */ +#define LNK_SECTION_DATA_L1 +#define LNK_SECTION_DATA_L2 +#define LNK_SECTION_CONSTDATA +#define LNK_SECTION_CONSTDATA_L1 + +#define LNK_SECTION_L1_DATA_A +#define LNK_SECTION_L1_DATA_B + +/************************************************** + * Macros regarding static code analysis + **************************************************/ +#ifdef __cplusplus +#if !defined(__has_cpp_attribute) +#define __has_cpp_attribute(x) 0 +#endif +#if defined(__clang__) && __has_cpp_attribute(clang::fallthrough) +#define FDK_FALLTHROUGH [[clang::fallthrough]] +#endif +#endif + +#ifndef FDK_FALLTHROUGH +#if defined(__GNUC__) && (__GNUC__ >= 7) +#define FDK_FALLTHROUGH __attribute__((fallthrough)) +#else +#define FDK_FALLTHROUGH +#endif +#endif + +#ifdef _MSC_VER +/* + * Sometimes certain features are excluded from compilation and therefore the + * warning 4065 may occur: "switch statement contains 'default' but no 'case' + * labels" We consider this warning irrelevant and disable it. + */ +#pragma warning(disable : 4065) +#endif + +#endif /* MACHINE_TYPE_H */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/syslib_channelMapDescr.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/syslib_channelMapDescr.h new file mode 100644 index 0000000000000..375a24d6b3912 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/include/syslib_channelMapDescr.h @@ -0,0 +1,202 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* System integration library ************************** + + Author(s): Thomas Dietzen + + Description: + +*******************************************************************************/ + +/** \file syslib_channelMapDescr.h + * \brief Function and structure declarations for the channel map descriptor implementation. + */ + +#ifndef SYSLIB_CHANNELMAPDESCR_H +#define SYSLIB_CHANNELMAPDESCR_H + +#include "machine_type.h" + +/** + * \brief Contains information needed for a single channel map. + */ +typedef struct { + const UCHAR* + pChannelMap; /*!< Actual channel mapping for one single configuration. */ + UCHAR numChannels; /*!< The number of channels for the channel map which is + the maximum used channel index+1. */ +} CHANNEL_MAP_INFO; + +/** + * \brief This is the main data struct. It contains the mapping for all + * channel configurations such as administration information. + * + * CAUTION: Do not access this structure directly from a algorithm specific + * library. Always use one of the API access functions below! + */ +typedef struct { + const CHANNEL_MAP_INFO* pMapInfoTab; /*!< Table of channel maps. */ + UINT mapInfoTabLen; /*!< Length of the channel map table array. */ + UINT fPassThrough; /*!< Flag that defines whether the specified mapping shall + be applied (value: 0) or the input just gets passed + through (MPEG mapping). */ +} FDK_channelMapDescr; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize a given channel map descriptor. + * + * \param pMapDescr Pointer to a channel map descriptor to be initialized. + * \param pMapInfoTab Table of channel maps to initizalize the descriptor + with. + * If a NULL pointer is given a default table for + WAV-like mapping will be used. + * \param mapInfoTabLen Length of the channel map table array (pMapInfoTab). + If a zero length is given a default table for WAV-like mapping will be used. + * \param fPassThrough If the flag is set the reordering (given by + pMapInfoTab) will be bypassed. + */ +void FDK_chMapDescr_init(FDK_channelMapDescr* const pMapDescr, + const CHANNEL_MAP_INFO* const pMapInfoTab, + const UINT mapInfoTabLen, const UINT fPassThrough); + +/** + * \brief Change the channel reordering state of a given channel map + * descriptor. + * + * \param pMapDescr Pointer to a (initialized) channel map descriptor. + * \param fPassThrough If the flag is set the reordering (given by + * pMapInfoTab) will be bypassed. + * \return Value unequal to zero if set operation was not + * successful. And zero on success. + */ +int FDK_chMapDescr_setPassThrough(FDK_channelMapDescr* const pMapDescr, + UINT fPassThrough); + +/** + * \brief Get the mapping value for a specific channel and map index. + * + * \param pMapDescr Pointer to channel map descriptor. + * \param chIdx Channel index. + * \param mapIdx Mapping index (corresponding to the channel configuration + * index). + * \return Mapping value. + */ +UCHAR FDK_chMapDescr_getMapValue(const FDK_channelMapDescr* const pMapDescr, + const UCHAR chIdx, const UINT mapIdx); + +/** + * \brief Evaluate whether channel map descriptor is reasonable or not. + * + * \param pMapDescr Pointer to channel map descriptor. + * \return Value unequal to zero if descriptor is valid, otherwise + * zero. + */ +int FDK_chMapDescr_isValid(const FDK_channelMapDescr* const pMapDescr); + +/** + * Extra variables for setting up Wg4 channel mapping. + */ +extern const CHANNEL_MAP_INFO FDK_mapInfoTabWg4[]; +extern const UINT FDK_mapInfoTabLenWg4; + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(SYSLIB_CHANNELMAPDESCR_H) */ diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/src/genericStds.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/src/genericStds.cpp new file mode 100644 index 0000000000000..f98d0a95fc531 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/src/genericStds.cpp @@ -0,0 +1,419 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* System integration library ************************** + + Author(s): + + Description: - Generic memory, stdio, string, etc. function wrappers or + builtins. + - OS dependant function wrappers. + +*******************************************************************************/ + +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif + +#define __GENERICSTDS_CPP__ + +#include "genericStds.h" + +/* library info */ +#define SYS_LIB_VL0 2 +#define SYS_LIB_VL1 0 +#define SYS_LIB_VL2 0 +#define SYS_LIB_TITLE "System Integration Library" +#ifdef __ANDROID__ +#define SYS_LIB_BUILD_DATE "" +#define SYS_LIB_BUILD_TIME "" +#else +#define SYS_LIB_BUILD_DATE __DATE__ +#define SYS_LIB_BUILD_TIME __TIME__ +#endif + +#include +#include +#include +#include + +/*************************************************************** + * memory allocation monitoring variables + ***************************************************************/ + +/* Include OS/System specific implementations. */ + +#include +#include +#include + +void FDKprintf(const char *szFmt, ...) { + va_list ap; + va_start(ap, szFmt); + vprintf(szFmt, ap); + va_end(ap); +} + +void FDKprintfErr(const char *szFmt, ...) { + va_list ap; + va_start(ap, szFmt); + vfprintf(stderr, szFmt, ap); + va_end(ap); +} + +int FDKgetchar(void) { return getchar(); } + +INT FDKfprintf(FDKFILE *stream, const char *format, ...) { + INT chars = 0; + va_list ap; + va_start(ap, format); + chars += vfprintf((FILE *)stream, format, ap); + va_end(ap); + return chars; +} + +INT FDKsprintf(char *str, const char *format, ...) { + INT chars = 0; + va_list ap; + va_start(ap, format); + chars += vsprintf(str, format, ap); + va_end(ap); + return chars; +} + +/************************************************************************************************/ + +/************************************************************************************************/ + +char *FDKstrchr(char *s, INT c) { return strchr(s, c); } +const char *FDKstrstr(const char *haystack, const char *needle) { + return strstr(haystack, needle); +} +char *FDKstrcpy(char *dest, const char *src) { return strcpy(dest, src); } +char *FDKstrncpy(char *dest, const char *src, UINT n) { + return strncpy(dest, src, n); +} + +/************************************************************************* + * DYNAMIC MEMORY management (heap) + *************************************************************************/ + +void *FDKcalloc(const UINT n, const UINT size) { + void *ptr; + + ptr = calloc(n, size); + + return ptr; +} + +void *FDKmalloc(const UINT size) { + void *ptr; + + ptr = malloc(size); + + return ptr; +} + +void FDKfree(void *ptr) { free((INT *)ptr); } + +void *FDKaalloc(const UINT size, const UINT alignment) { + void *addr, *result = NULL; + addr = FDKcalloc(1, size + alignment + + (UINT)sizeof(void *)); /* Malloc and clear memory. */ + + if (addr != NULL) { + result = ALIGN_PTR((unsigned char *)addr + + sizeof(void *)); /* Get aligned memory base address. */ + *(((void **)result) - 1) = addr; /* Save malloc'ed memory pointer. */ + C_ALLOC_ALIGNED_REGISTER(result, size); + } + + return result; /* Return aligned address. */ +} + +void FDKafree(void *ptr) { + void *addr; + addr = *(((void **)ptr) - 1); /* Get pointer to malloc'ed memory. */ + + C_ALLOC_ALIGNED_UNREGISTER(ptr); + + FDKfree(addr); /* Free malloc'ed memory area. */ +} + +/*--------------------------------------------------------------------------* + * DATA MEMORY L1/L2 (fallback) + *--------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------* + * FDKcalloc_L + *--------------------------------------------------------------------------*/ +void *FDKcalloc_L(const UINT dim, const UINT size, MEMORY_SECTION s) { + return FDKcalloc(dim, size); +} + +void FDKfree_L(void *p) { FDKfree(p); } + +void *FDKaalloc_L(const UINT size, const UINT alignment, MEMORY_SECTION s) { + void *addr, *result = NULL; + addr = FDKcalloc_L(1, size + alignment + (UINT)sizeof(void *), + s); /* Malloc and clear memory. */ + + if (addr != NULL) { + result = ALIGN_PTR((unsigned char *)addr + + sizeof(void *)); /* Get aligned memory base address. */ + *(((void **)result) - 1) = addr; /* Save malloc'ed memory pointer. */ + C_ALLOC_ALIGNED_REGISTER(result, size); + } + + return result; /* Return aligned address. */ +} + +void FDKafree_L(void *ptr) { + void *addr; + + addr = *(((void **)ptr) - 1); /* Get pointer to malloc'ed memory. */ + + C_ALLOC_ALIGNED_UNREGISTER(ptr); + + FDKfree_L(addr); /* Free malloc'ed memory area. */ +} + +/*--------------------------------------------------------------------------------------- + * FUNCTION: FDKmemcpy + * DESCRIPTION: - copies memory from "src" to "dst" with length "size" bytes + * - compiled with FDK_DEBUG will give you warnings + *---------------------------------------------------------------------------------------*/ +void FDKmemcpy(void *dst, const void *src, const UINT size) { + /* -- check for overlapping memory areas -- */ + FDK_ASSERT(((const unsigned char *)dst - (const unsigned char *)src) >= + (ptrdiff_t)size || + ((const unsigned char *)src - (const unsigned char *)dst) >= + (ptrdiff_t)size); + + /* do the copy */ + memcpy(dst, src, size); +} + +void FDKmemmove(void *dst, const void *src, const UINT size) { + memmove(dst, src, size); +} + +void FDKmemset(void *memPtr, const INT value, const UINT size) { + memset(memPtr, value, size); +} + +void FDKmemclear(void *memPtr, const UINT size) { FDKmemset(memPtr, 0, size); } + +UINT FDKstrlen(const char *s) { return (UINT)strlen(s); } + +/* Compare function wrappers */ +INT FDKmemcmp(const void *s1, const void *s2, const UINT size) { + return memcmp(s1, s2, size); +} +INT FDKstrcmp(const char *s1, const char *s2) { return strcmp(s1, s2); } +INT FDKstrncmp(const char *s1, const char *s2, const UINT size) { + return strncmp(s1, s2, size); +} + +int IS_LITTLE_ENDIAN(void) { + int __dummy = 1; + return (*((UCHAR *)(&(__dummy)))); +} + +UINT TO_LITTLE_ENDIAN(UINT val) { + return IS_LITTLE_ENDIAN() + ? val + : (((val & 0xff) << 24) | ((val & 0xff00) << 8) | + ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24)); +} + +/* ==================== FILE I/O ====================== */ + +FDKFILE *FDKfopen(const char *filename, const char *mode) { + return fopen(filename, mode); +} +INT FDKfclose(FDKFILE *fp) { return fclose((FILE *)fp); } +INT FDKfseek(FDKFILE *fp, LONG OFFSET, int WHENCE) { + return fseek((FILE *)fp, OFFSET, WHENCE); +} +INT FDKftell(FDKFILE *fp) { return ftell((FILE *)fp); } +INT FDKfflush(FDKFILE *fp) { return fflush((FILE *)fp); } +const INT FDKSEEK_SET = SEEK_SET; +const INT FDKSEEK_CUR = SEEK_CUR; +const INT FDKSEEK_END = SEEK_END; + +UINT FDKfwrite(const void *ptrf, INT size, UINT nmemb, FDKFILE *fp) { + return (UINT)fwrite(ptrf, size, nmemb, (FILE *)fp); +} +UINT FDKfread(void *dst, INT size, UINT nmemb, FDKFILE *fp) { + return (UINT)fread(dst, size, nmemb, (FILE *)fp); +} +char *FDKfgets(void *dst, INT size, FDKFILE *fp) { + return fgets((char *)dst, size, (FILE *)fp); +} +void FDKrewind(FDKFILE *fp) { FDKfseek((FILE *)fp, 0, FDKSEEK_SET); } + +UINT FDKfwrite_EL(const void *ptrf, INT size, UINT nmemb, FDKFILE *fp) { + if (IS_LITTLE_ENDIAN()) { + FDKfwrite(ptrf, size, nmemb, fp); + } else { + UINT n; + INT s; + + const UCHAR *ptr = (const UCHAR *)ptrf; + + for (n = 0; n < nmemb; n++) { + for (s = size - 1; s >= 0; s--) { + FDKfwrite(ptr + s, 1, 1, fp); + } + ptr = ptr + size; + } + } + return nmemb; +} + +UINT FDKfread_EL(void *dst, INT size, UINT nmemb, FDKFILE *fp) { + UINT n, s0, s1, err; + UCHAR tmp, *ptr; + UCHAR tmp24[3]; + + /* Enforce alignment of 24 bit data. */ + if (size == 3) { + ptr = (UCHAR *)dst; + for (n = 0; n < nmemb; n++) { + if ((err = FDKfread(tmp24, 1, 3, fp)) != 3) { + return err; + } + *ptr++ = tmp24[0]; + *ptr++ = tmp24[1]; + *ptr++ = tmp24[2]; + /* Sign extension */ + if (tmp24[2] & 0x80) { + *ptr++ = 0xff; + } else { + *ptr++ = 0; + } + } + err = nmemb; + size = sizeof(LONG); + } else { + if ((err = FDKfread(dst, size, nmemb, fp)) != nmemb) { + return err; + } + } + if (!IS_LITTLE_ENDIAN() && size > 1) { + ptr = (UCHAR *)dst; + for (n = 0; n < nmemb; n++) { + for (s0 = 0, s1 = size - 1; s0 < s1; s0++, s1--) { + tmp = ptr[s0]; + ptr[s0] = ptr[s1]; + ptr[s1] = tmp; + } + ptr += size; + } + } + return err; +} + +INT FDKfeof(FDKFILE *fp) { return feof((FILE *)fp); } + +/* Global initialization/cleanup */ + +void FDKprintDisclaimer(void) { + FDKprintf( + "This program is protected by copyright law and international treaties.\n" + "Any reproduction or distribution of this program, or any portion\n" + "of it, may result in severe civil and criminal penalties, and will be\n" + "prosecuted to the maximum extent possible under law.\n\n"); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/src/syslib_channelMapDescr.cpp b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/src/syslib_channelMapDescr.cpp new file mode 100644 index 0000000000000..d22a30d220401 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/libSYS/src/syslib_channelMapDescr.cpp @@ -0,0 +1,315 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* System integration library ************************** + + Author(s): Thomas Dietzen + + Description: + +*******************************************************************************/ + +/** \file syslib_channelMapDescr.cpp + * \brief Implementation of routines that handle the channel map descriptor. + */ + +#include "syslib_channelMapDescr.h" + +#define DFLT_CH_MAP_TAB_LEN \ + (15) /* Length of the default channel map info table. */ + +/** + * \brief The following arrays provide a channel map for each channel config (0 + * to 14). + * + * The i-th channel will be mapped to the postion a[i-1]+1 + * with i>0 and a[] is one of the following mapping arrays. + */ +static const UCHAR mapFallback[] = {0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23}; +static const UCHAR mapCfg1[] = {0, 1}; +static const UCHAR mapCfg2[] = {0, 1}; +static const UCHAR mapCfg3[] = {2, 0, 1}; +static const UCHAR mapCfg4[] = {2, 0, 1, 3}; +static const UCHAR mapCfg5[] = {2, 0, 1, 3, 4}; +static const UCHAR mapCfg6[] = {2, 0, 1, 4, 5, 3}; +static const UCHAR mapCfg7[] = {2, 6, 7, 0, 1, 4, 5, 3}; +static const UCHAR mapCfg11[] = {2, 0, 1, 4, 5, 6, 3}; +static const UCHAR mapCfg12[] = {2, 0, 1, 6, 7, 4, 5, 3}; +static const UCHAR mapCfg13[] = {2, 6, 7, 0, 1, 10, 11, 4, + 5, 8, 3, 9, 14, 12, 13, 18, + 19, 15, 16, 17, 20, 21, 22, 23}; +static const UCHAR mapCfg14[] = {2, 0, 1, 4, 5, 3, 6, 7}; + +/** + * \brief Default table comprising channel map information for each channel + * config (0 to 14). + */ +static const CHANNEL_MAP_INFO mapInfoTabDflt[DFLT_CH_MAP_TAB_LEN] = + {/* chCfg, map, numCh */ + /* 0 */ {mapFallback, 24}, + /* 1 */ {mapCfg1, 2}, + /* 2 */ {mapCfg2, 2}, + /* 3 */ {mapCfg3, 3}, + /* 4 */ {mapCfg4, 4}, + /* 5 */ {mapCfg5, 5}, + /* 6 */ {mapCfg6, 6}, + /* 7 */ {mapCfg7, 8}, + /* 8 */ {mapFallback, 24}, + /* 9 */ {mapFallback, 24}, + /* 10 */ {mapFallback, 24}, + /* 11 */ {mapCfg11, 7}, + /* 12 */ {mapCfg12, 8}, + /* 13 */ {mapCfg13, 24}, + /* 14 */ {mapCfg14, 8}}; + + +static const UCHAR mapWg4Cfg1[] = {0, 1}; +static const UCHAR mapWg4Cfg2[] = {0, 1}; +static const UCHAR mapWg4Cfg3[] = {2, 0, 1}; +static const UCHAR mapWg4Cfg4[] = {3, 0, 1, 2}; +static const UCHAR mapWg4Cfg5[] = {4, 0, 1, 2, 3}; +static const UCHAR mapWg4Cfg6[] = {4, 0, 1, 2, 3, 5}; +static const UCHAR mapWg4Cfg7[] = {6, 0, 1, 2, 3, 4, 5, 7}; +static const UCHAR mapWg4Cfg14[] = {6, 0, 1, 2, 3, 4, 5, 7}; + +const CHANNEL_MAP_INFO FDK_mapInfoTabWg4[] = + {/* chCfg, map, numCh */ + /* 0 */ {mapFallback, 24}, + /* 1 */ {mapWg4Cfg1, 2}, + /* 2 */ {mapWg4Cfg2, 2}, + /* 3 */ {mapWg4Cfg3, 3}, + /* 4 */ {mapWg4Cfg4, 4}, + /* 5 */ {mapWg4Cfg5, 5}, + /* 6 */ {mapWg4Cfg6, 6}, + /* 7 */ {mapWg4Cfg7, 8}, + /* 8 */ {mapFallback, 24}, + /* 9 */ {mapFallback, 24}, + /* 10 */ {mapFallback, 24}, + /* 11 */ {mapFallback, 24}, // Unhandled for Wg4 yet + /* 12 */ {mapFallback, 24}, // Unhandled for Wg4 yet + /* 13 */ {mapFallback, 24}, // Unhandled for Wg4 yet + /* 14 */ {mapFallback, 24}}; // Unhandled for Wg4 yet + +const UINT FDK_mapInfoTabLenWg4 = sizeof(FDK_mapInfoTabWg4)/sizeof(FDK_mapInfoTabWg4[0]); + + +/** + * Get the mapping value for a specific channel and map index. + */ +UCHAR FDK_chMapDescr_getMapValue(const FDK_channelMapDescr* const pMapDescr, + const UCHAR chIdx, const UINT mapIdx) { + UCHAR mapValue = chIdx; /* Pass through by default. */ + + FDK_ASSERT(pMapDescr != NULL); + + if ((pMapDescr->fPassThrough == 0) && (pMapDescr->pMapInfoTab != NULL) && + (pMapDescr->mapInfoTabLen > mapIdx)) { /* Nest sanity check to avoid + possible memory access + violation. */ + if (chIdx < pMapDescr->pMapInfoTab[mapIdx].numChannels) { + mapValue = pMapDescr->pMapInfoTab[mapIdx].pChannelMap[chIdx]; + } + } + return mapValue; +} + +/** + * \brief Evaluate whether single channel map is reasonable or not. + * + * \param pMapInfo Pointer to channel map. + * \return Value unequal to zero if map is valid, otherwise zero. + */ +static int fdk_chMapDescr_isValidMap(const CHANNEL_MAP_INFO* const pMapInfo) { + int result = 1; + UINT i; + + if (pMapInfo == NULL) { + result = 0; + } else { + UINT numChannels = pMapInfo->numChannels; + + /* Check for all map values if they are inside the range 0 to numChannels-1 + * and unique. */ + if (numChannels < 32) { /* Optimized version for less than 32 channels. + Needs only one loop. */ + UINT mappedChMask = 0x0; + for (i = 0; i < numChannels; i += 1) { + mappedChMask |= 1 << pMapInfo->pChannelMap[i]; + } + if (mappedChMask != (((UINT)1 << numChannels) - 1)) { + result = 0; + } + } else { /* General case that can handle all number of channels but needs + one more loop. */ + for (i = 0; (i < numChannels) && result; i += 1) { + UINT j; + UCHAR value0 = pMapInfo->pChannelMap[i]; + + if (value0 > numChannels - 1) { /* out of range? */ + result = 0; + } + for (j = numChannels - 1; (j > i) && result; j -= 1) { + if (value0 == pMapInfo->pChannelMap[j]) { /* not unique */ + result = 0; + } + } + } + } + } + + return result; +} + +/** + * Evaluate whether channel map descriptor is reasonable or not. + */ +int FDK_chMapDescr_isValid(const FDK_channelMapDescr* const pMapDescr) { + int result = 0; + UINT i; + + if (pMapDescr != NULL) { + result = 1; + for (i = 0; (i < pMapDescr->mapInfoTabLen) && result; i += 1) { + if (!fdk_chMapDescr_isValidMap(&pMapDescr->pMapInfoTab[i])) { + result = 0; + } + } + } + return result; +} + +/** + * Initialize the complete channel map descriptor. + */ +void FDK_chMapDescr_init(FDK_channelMapDescr* const pMapDescr, + const CHANNEL_MAP_INFO* const pMapInfoTab, + const UINT mapInfoTabLen, const UINT fPassThrough) { + if (pMapDescr != NULL) { + int useDefaultTab = 1; + + pMapDescr->fPassThrough = (fPassThrough == 0) ? 0 : 1; + + if ((pMapInfoTab != NULL) && (mapInfoTabLen > 0)) { + /* Set the valid custom mapping table. */ + pMapDescr->pMapInfoTab = pMapInfoTab; + pMapDescr->mapInfoTabLen = mapInfoTabLen; + /* Validate the complete descriptor. */ + useDefaultTab = (FDK_chMapDescr_isValid(pMapDescr) == 0) ? 1 : 0; + } + if (useDefaultTab != 0) { + /* Set default table. */ + pMapDescr->pMapInfoTab = mapInfoTabDflt; + pMapDescr->mapInfoTabLen = DFLT_CH_MAP_TAB_LEN; + } + } +} + +/** + * Set channel mapping bypass flag in a given channel map descriptor. + */ +int FDK_chMapDescr_setPassThrough(FDK_channelMapDescr* const pMapDescr, + UINT fPassThrough) { + int err = 1; + + if (pMapDescr != NULL) { + if ((pMapDescr->pMapInfoTab != NULL) && (pMapDescr->mapInfoTabLen > 0)) { + pMapDescr->fPassThrough = (fPassThrough == 0) ? 0 : 1; + err = 0; + } + } + + return err; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/m4/.gitkeep b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/m4/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/sha1.c b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/sha1.c new file mode 100644 index 0000000000000..08a93d1de0772 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/sha1.c @@ -0,0 +1,399 @@ +/*! + * \copy + * Copyright (c) 1998, 2009 Paul E. Jones + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * Description: + * This file implements the Secure Hashing Standard as defined + * in FIPS PUB 180-1 published April 17, 1995. + * + * The Secure Hashing Standard, which uses the Secure Hashing + * Algorithm (SHA), produces a 160-bit message digest for a + * given data stream. In theory, it is highly improbable that + * two messages will produce the same message digest. Therefore, + * this algorithm can serve as a means of providing a "fingerprint" + * for a message. + * + * Portability Issues: + * SHA-1 is defined in terms of 32-bit "words". This code was + * written with the expectation that the processor has at least + * a 32-bit machine word size. If the machine word size is larger, + * the code should still function properly. One caveat to that + * is that the input functions taking characters and character + * arrays assume that only 8 bits of information are stored in each + * character. + * + * Caveats: + * SHA-1 is designed to work with messages less than 2^64 bits + * long. Although SHA-1 allows a message digest to be generated for + * messages of any number of bits less than 2^64, this + * implementation only works with messages with a length that is a + * multiple of the size of an 8-bit character. + * + */ + +#include "sha1.h" + +/* + * Define the circular shift macro + */ +#define SHA1CircularShift(bits,word) \ + ((((word) << (bits)) & 0xFFFFFFFF) | \ + ((word) >> (32-(bits)))) + +/* Function prototypes */ +void SHA1ProcessMessageBlock(SHA1Context *); +void SHA1PadMessage(SHA1Context *); + +/* + * SHA1Reset + * + * Description: + * This function will initialize the SHA1Context in preparation + * for computing a new message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * Nothing. + * + * Comments: + * + */ +void SHA1Reset(SHA1Context *context) +{ + context->Length_Low = 0; + context->Length_High = 0; + context->Message_Block_Index = 0; + + context->Message_Digest[0] = 0x67452301; + context->Message_Digest[1] = 0xEFCDAB89; + context->Message_Digest[2] = 0x98BADCFE; + context->Message_Digest[3] = 0x10325476; + context->Message_Digest[4] = 0xC3D2E1F0; + + context->Computed = 0; + context->Corrupted = 0; +} + +/* + * SHA1Result + * + * Description: + * This function will return the 160-bit message digest into the + * digest array provided as a parameter. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA-1 hash. + * digest: [out] + * An array of characters where the digest is written. + * + * Returns: + * 1 if successful, 0 if it failed. + * + * Comments: + * + */ +int SHA1Result(SHA1Context *context, unsigned char *digest) +{ + int i; + + if (context->Corrupted) + { + return 0; + } + + if (!context->Computed) + { + SHA1PadMessage(context); + context->Computed = 1; + } + + for (i = 0; i < SHA_DIGEST_LENGTH; i++) + digest[i] = context->Message_Digest[i / 4] >> (8 * (3 - (i % 4))); + + return 1; +} + +/* + * SHA1Input + * + * Description: + * This function accepts an array of octets as the next portion of + * the message. + * + * Parameters: + * context: [in/out] + * The SHA-1 context to update + * message_array: [in] + * An array of characters representing the next portion of the + * message. + * length: [in] + * The length of the message in message_array + * + * Returns: + * Nothing. + * + * Comments: + * + */ +void SHA1Input( SHA1Context *context, + const unsigned char *message_array, + unsigned length) +{ + if (!length) + { + return; + } + + if (context->Computed || context->Corrupted) + { + context->Corrupted = 1; + return; + } + + while(length-- && !context->Corrupted) + { + context->Message_Block[context->Message_Block_Index++] = + (*message_array & 0xFF); + + context->Length_Low += 8; + /* Force it to 32 bits */ + context->Length_Low &= 0xFFFFFFFF; + if (context->Length_Low == 0) + { + context->Length_High++; + /* Force it to 32 bits */ + context->Length_High &= 0xFFFFFFFF; + if (context->Length_High == 0) + { + /* Message is too long */ + context->Corrupted = 1; + } + } + + if (context->Message_Block_Index == 64) + { + SHA1ProcessMessageBlock(context); + } + + message_array++; + } +} + +/* + * SHA1ProcessMessageBlock + * + * Description: + * This function will process the next 512 bits of the message + * stored in the Message_Block array. + * + * Parameters: + * None. + * + * Returns: + * Nothing. + * + * Comments: + * Many of the variable names in the SHAContext, especially the + * single character names, were used because those were the names + * used in the publication. + * + * + */ +void SHA1ProcessMessageBlock(SHA1Context *context) +{ + const unsigned K[] = /* Constants defined in SHA-1 */ + { + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; /* Loop counter */ + unsigned temp; /* Temporary word value */ + unsigned W[80]; /* Word sequence */ + unsigned A, B, C, D, E; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for(t = 0; t < 16; t++) + { + W[t] = ((unsigned) context->Message_Block[t * 4]) << 24; + W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16; + W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8; + W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]); + } + + for(t = 16; t < 80; t++) + { + W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = context->Message_Digest[0]; + B = context->Message_Digest[1]; + C = context->Message_Digest[2]; + D = context->Message_Digest[3]; + E = context->Message_Digest[4]; + + for(t = 0; t < 20; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 20; t < 40; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 40; t < 60; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 60; t < 80; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + context->Message_Digest[0] = + (context->Message_Digest[0] + A) & 0xFFFFFFFF; + context->Message_Digest[1] = + (context->Message_Digest[1] + B) & 0xFFFFFFFF; + context->Message_Digest[2] = + (context->Message_Digest[2] + C) & 0xFFFFFFFF; + context->Message_Digest[3] = + (context->Message_Digest[3] + D) & 0xFFFFFFFF; + context->Message_Digest[4] = + (context->Message_Digest[4] + E) & 0xFFFFFFFF; + + context->Message_Block_Index = 0; +} + +/* + * SHA1PadMessage + * + * Description: + * According to the standard, the message must be padded to an even + * 512 bits. The first padding bit must be a '1'. The last 64 + * bits represent the length of the original message. All bits in + * between should be 0. This function will pad the message + * according to those rules by filling the Message_Block array + * accordingly. It will also call SHA1ProcessMessageBlock() + * appropriately. When it returns, it can be assumed that the + * message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad + * + * Returns: + * Nothing. + * + * Comments: + * + */ +void SHA1PadMessage(SHA1Context *context) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index > 55) + { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while(context->Message_Block_Index < 64) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + + SHA1ProcessMessageBlock(context); + + while(context->Message_Block_Index < 56) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + else + { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while(context->Message_Block_Index < 56) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = (context->Length_High >> 24) & 0xFF; + context->Message_Block[57] = (context->Length_High >> 16) & 0xFF; + context->Message_Block[58] = (context->Length_High >> 8) & 0xFF; + context->Message_Block[59] = (context->Length_High) & 0xFF; + context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF; + context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF; + context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF; + context->Message_Block[63] = (context->Length_Low) & 0xFF; + + SHA1ProcessMessageBlock(context); +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/sha1.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/sha1.h new file mode 100644 index 0000000000000..7ca10f8b42048 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/sha1.h @@ -0,0 +1,85 @@ +/*! + * \copy + * Copyright (c) 1998, 2009 Paul E. Jones + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * Description: + * This class implements the Secure Hashing Standard as defined + * in FIPS PUB 180-1 published April 17, 1995. + * + * Many of the variable names in the SHA1Context, especially the + * single character names, were used because those were the names + * used in the publication. + * + * Please read the file sha1.c for more information. + * + */ + +#ifndef _SHA1_H_ +#define _SHA1_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This structure will hold context information for the hashing + * operation + */ +typedef struct SHA1Context { + unsigned Message_Digest[5]; /* Message Digest (output) */ + + unsigned Length_Low; /* Message length in bits */ + unsigned Length_High; /* Message length in bits */ + + unsigned char Message_Block[64]; /* 512-bit message blocks */ + int Message_Block_Index; /* Index into message block array */ + + int Computed; /* Is the digest computed? */ + int Corrupted; /* Is the message digest corruped? */ +} SHA1Context; + +/* + * Function Prototypes + */ +void SHA1Reset (SHA1Context*); +int SHA1Result (SHA1Context*, unsigned char*); +void SHA1Input (SHA1Context*, + const unsigned char*, + unsigned); + +#define SHA_DIGEST_LENGTH 20 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test-encode-decode.c b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test-encode-decode.c new file mode 100644 index 0000000000000..a216c18489770 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test-encode-decode.c @@ -0,0 +1,383 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 2017 Martin Storsjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include "aacenc_lib.h" +#include "aacdecoder_lib.h" +#include "wavreader.h" +#include "sha1.h" + + +static int encoder_input_samples, encoder_input_size; +static int decoder_output_skip; +static int16_t *encoder_input; +static int max_diff; +static uint64_t diff_sum, diff_samples; +static SHA1Context encode_hash, decode_hash; + +static void init_encoder_input(void) { + encoder_input_samples = 0; + max_diff = 0; + diff_sum = diff_samples = 0; +} + +static void free_encoder_input(void) { + free(encoder_input); + encoder_input = NULL; + encoder_input_size = 0; +} + +static void append_encoder_input(const int16_t *input, int samples) { + if (encoder_input_samples + samples > encoder_input_size) { + int size = 2*(encoder_input_samples + samples); + int16_t *ptr = realloc(encoder_input, size * sizeof(*encoder_input)); + if (!ptr) + abort(); + encoder_input = ptr; + encoder_input_size = size; + } + memcpy(encoder_input + encoder_input_samples, input, samples * sizeof(*input)); + encoder_input_samples += samples; +} + +static void compare_decoder_output(const int16_t *output, int samples) { + int i; + // TODO: Stereo upconvert? + SHA1Input(&decode_hash, (const unsigned char*) output, samples * sizeof(*output)); + if (decoder_output_skip > 0) { + int n = samples; + if (n > decoder_output_skip) + n = decoder_output_skip; + output += n; + samples -= n; + decoder_output_skip -= n; + if (samples <= 0) + return; + } + if (samples > encoder_input_samples) + samples = encoder_input_samples; + for (i = 0; i < samples; i++) { + int diff = abs(encoder_input[i] - output[i]); + if (diff > max_diff) + max_diff = diff; + diff_sum += diff; + diff_samples++; + } + memmove(encoder_input, encoder_input + samples, (encoder_input_samples - samples) * sizeof(*encoder_input)); + encoder_input_samples -= samples; +} + +static int decode(HANDLE_AACDECODER decoder, const uint8_t *ptr, int size, uint8_t *decoder_buffer, int decoder_buffer_size, int channels) { + AAC_DECODER_ERROR err; + CStreamInfo *info; + UINT valid, buffer_size; + SHA1Input(&encode_hash, ptr, size); + do { + valid = buffer_size = size; + err = aacDecoder_Fill(decoder, (UCHAR**) &ptr, &buffer_size, &valid); + ptr += buffer_size - valid; + size -= buffer_size - valid; + if (err == AAC_DEC_NOT_ENOUGH_BITS) + continue; + if (err != AAC_DEC_OK) + break; + err = aacDecoder_DecodeFrame(decoder, (INT_PCM *) decoder_buffer, decoder_buffer_size / sizeof(INT_PCM), 0); + if (!ptr && err != AAC_DEC_OK) + break; + if (err == AAC_DEC_NOT_ENOUGH_BITS) + continue; + if (err != AAC_DEC_OK) { + fprintf(stderr, "Decoding failed\n"); + return 1; + } + info = aacDecoder_GetStreamInfo(decoder); + if (info->numChannels != channels) { + fprintf(stderr, "Mismatched number of channels, input %d, output %d\n", channels, info->numChannels); + return 1; + } + compare_decoder_output((int16_t*) decoder_buffer, info->numChannels * info->frameSize); + } while (size > 0); + return 0; +} + +static int test_encode_decode(const char *infile, int aot, int afterburner, int eld_sbr, int vbr, int bitrate, int adts) { + void *wav; + int format, sample_rate, channels, bits_per_sample; + int input_size; + uint8_t* input_buf; + int16_t* convert_buf; + HANDLE_AACENCODER encoder; + CHANNEL_MODE mode; + AACENC_InfoStruct info = { 0 }; + HANDLE_AACDECODER decoder; + int ret = 0; + int decoder_buffer_size = 2048 * 2 * 8; + uint8_t* decoder_buffer = malloc(decoder_buffer_size); + int avg_diff; + + fprintf(stderr, "Testing encoding with aot %d afterburner %d eld_sbr %d vbr %d bitrate %d adts %d\n", aot, afterburner, eld_sbr, vbr, bitrate, adts); + init_encoder_input(); + + wav = wav_read_open(infile); + if (!wav) { + fprintf(stderr, "Unable to open wav file %s\n", infile); + return 1; + } + if (!wav_get_header(wav, &format, &channels, &sample_rate, &bits_per_sample, NULL)) { + fprintf(stderr, "Bad wav file %s\n", infile); + return 1; + } + if (format != 1) { + fprintf(stderr, "Unsupported WAV format %d\n", format); + return 1; + } + if (bits_per_sample != 16) { + fprintf(stderr, "Unsupported WAV sample depth %d\n", bits_per_sample); + return 1; + } + switch (channels) { + case 1: mode = MODE_1; break; + case 2: mode = MODE_2; break; + case 3: mode = MODE_1_2; break; + case 4: mode = MODE_1_2_1; break; + case 5: mode = MODE_1_2_2; break; + case 6: mode = MODE_1_2_2_1; break; + default: + fprintf(stderr, "Unsupported WAV channels %d\n", channels); + return 1; + } + if (aacEncOpen(&encoder, 0, channels) != AACENC_OK) { + fprintf(stderr, "Unable to open encoder\n"); + return 1; + } + if (aacEncoder_SetParam(encoder, AACENC_AOT, aot) != AACENC_OK) { + fprintf(stderr, "Unable to set the AOT\n"); + return 1; + } + if (aot == 39 && eld_sbr) { + if (aacEncoder_SetParam(encoder, AACENC_SBR_MODE, 1) != AACENC_OK) { + fprintf(stderr, "Unable to set SBR mode for ELD\n"); + return 1; + } + } + if (aacEncoder_SetParam(encoder, AACENC_SAMPLERATE, sample_rate) != AACENC_OK) { + fprintf(stderr, "Unable to set the AOT\n"); + return 1; + } + if (aacEncoder_SetParam(encoder, AACENC_CHANNELMODE, mode) != AACENC_OK) { + fprintf(stderr, "Unable to set the channel mode\n"); + return 1; + } + if (aacEncoder_SetParam(encoder, AACENC_CHANNELORDER, 1) != AACENC_OK) { + fprintf(stderr, "Unable to set the wav channel order\n"); + return 1; + } + if (vbr) { + if (aacEncoder_SetParam(encoder, AACENC_BITRATEMODE, vbr) != AACENC_OK) { + fprintf(stderr, "Unable to set the VBR bitrate mode\n"); + return 1; + } + } else { + if (aacEncoder_SetParam(encoder, AACENC_BITRATE, bitrate) != AACENC_OK) { + fprintf(stderr, "Unable to set the bitrate\n"); + return 1; + } + } + if (aacEncoder_SetParam(encoder, AACENC_TRANSMUX, adts ? 2 : 0) != AACENC_OK) { + fprintf(stderr, "Unable to set the ADTS transmux\n"); + return 1; + } + if (aacEncoder_SetParam(encoder, AACENC_AFTERBURNER, afterburner) != AACENC_OK) { + fprintf(stderr, "Unable to set the afterburner mode\n"); + return 1; + } + if (aacEncEncode(encoder, NULL, NULL, NULL, NULL) != AACENC_OK) { + fprintf(stderr, "Unable to initialize the encoder\n"); + return 1; + } + if (aacEncInfo(encoder, &info) != AACENC_OK) { + fprintf(stderr, "Unable to get the encoder info\n"); + return 1; + } + + input_size = channels*2*info.frameLength; + input_buf = (uint8_t*) malloc(input_size); + convert_buf = (int16_t*) malloc(input_size); + + decoder_output_skip = channels * info.nDelay; + + decoder = aacDecoder_Open(adts ? TT_MP4_ADTS : TT_MP4_RAW, 1); + if (!adts) { + UCHAR *bufArray[] = { info.confBuf }; + if (aacDecoder_ConfigRaw(decoder, (UCHAR**) bufArray, &info.confSize) != AAC_DEC_OK) { + fprintf(stderr, "Unable to set ASC\n"); + ret = 1; + goto end; + } + } + aacDecoder_SetParam(decoder, AAC_CONCEAL_METHOD, 1); + aacDecoder_SetParam(decoder, AAC_PCM_LIMITER_ENABLE, 0); + while (1) { + AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 }; + AACENC_InArgs in_args = { 0 }; + AACENC_OutArgs out_args = { 0 }; + int in_identifier = IN_AUDIO_DATA; + int in_size, in_elem_size; + int out_identifier = OUT_BITSTREAM_DATA; + int out_size, out_elem_size; + int read, i; + void *in_ptr, *out_ptr; + uint8_t outbuf[20480]; + AACENC_ERROR err; + + read = wav_read_data(wav, input_buf, input_size); + for (i = 0; i < read/2; i++) { + const uint8_t* in = &input_buf[2*i]; + convert_buf[i] = in[0] | (in[1] << 8); + } + in_ptr = convert_buf; + in_size = read; + in_elem_size = 2; + + in_buf.numBufs = 1; + in_buf.bufs = &in_ptr; + in_buf.bufferIdentifiers = &in_identifier; + in_buf.bufSizes = &in_size; + in_buf.bufElSizes = &in_elem_size; + + if (read <= 0) { + in_args.numInSamples = -1; + } else { + in_args.numInSamples = read/2; + append_encoder_input(convert_buf, in_args.numInSamples); + } + out_ptr = outbuf; + out_size = sizeof(outbuf); + out_elem_size = 1; + out_buf.numBufs = 1; + out_buf.bufs = &out_ptr; + out_buf.bufferIdentifiers = &out_identifier; + out_buf.bufSizes = &out_size; + out_buf.bufElSizes = &out_elem_size; + + if ((err = aacEncEncode(encoder, &in_buf, &out_buf, &in_args, &out_args)) != AACENC_OK) { + if (err == AACENC_ENCODE_EOF) + break; + fprintf(stderr, "Encoding failed\n"); + ret = 1; + goto end; + } + if (out_args.numOutBytes == 0) + continue; + + if (decode(decoder, outbuf, out_args.numOutBytes, decoder_buffer, decoder_buffer_size, channels)) { + ret = 1; + goto end; + } + } + + if (encoder_input_samples > 0) { + fprintf(stderr, "%d unmatched samples left at the end\n", encoder_input_samples); + ret = 1; + goto end; + } + avg_diff = 0; + if (diff_samples > 0) + avg_diff = diff_sum / diff_samples; + if (/*max_diff > 10000 ||*/ avg_diff > ((aot == 23) ? 2500 : (aot == 29) ? 1500 : 300)) { + fprintf(stderr, "max_diff %d, avg_diff %d\n", max_diff, avg_diff); + ret = 1; + goto end; + } + +end: + free(input_buf); + free(convert_buf); + wav_read_close(wav); + aacEncClose(&encoder); + free(decoder_buffer); + aacDecoder_Close(decoder); + + return ret; +} + +int main(int argc, char *argv[]) { + const char* infile; + void *wav; + int sample_rate, channels; + int failures = 0; + int i; + unsigned char encode_digest[SHA_DIGEST_LENGTH], decode_digest[SHA_DIGEST_LENGTH]; + if (argc < 2) { + printf("%s input.wav\n", argv[0]); + return 1; + } + infile = argv[1]; + + wav = wav_read_open(infile); + if (!wav) { + fprintf(stderr, "Unable to open wav file %s\n", infile); + return 1; + } + if (!wav_get_header(wav, NULL, &channels, &sample_rate, NULL, NULL)) { + fprintf(stderr, "Bad wav file %s\n", infile); + return 1; + } + wav_read_close(wav); + + SHA1Reset(&encode_hash); + SHA1Reset(&decode_hash); + + failures += test_encode_decode(infile, 2, 0, 0, 0, 64000, 0); // AAC-LC, without afterburner + for (i = 0; i < 2; i++) + failures += test_encode_decode(infile, 2, 1, 0, 0, 64000, i); // AAC-LC + for (i = 1; i <= 5; i++) + failures += test_encode_decode(infile, 2, 1, 0, i, 0, 0); // AAC-LC VBR + if (channels == 2) { + // HE-AACv2 only works for stereo; HE-AACv1 gets upconverted to stereo (which we don't match properly) + for (i = 0; i < 2; i++) + failures += test_encode_decode(infile, 5, 1, 0, 0, 64000, i); // HE-AAC + for (i = 1; i <= 5; i++) + failures += test_encode_decode(infile, 5, 1, 0, i, 0, 0); // HE-AAC VBR + for (i = 0; i < 2; i++) + failures += test_encode_decode(infile, 29, 1, 0, 0, 64000, i); // HE-AACv2 + for (i = 1; i <= 5; i++) + failures += test_encode_decode(infile, 29, 1, 0, i, 0, 0); // HE-AACv2 VBR + } + if (channels == 1) + failures += test_encode_decode(infile, 23, 1, 0, 0, 64000, 0); // AAC-LD + failures += test_encode_decode(infile, 39, 1, 0, 0, 64000, 0); // AAC-ELD + failures += test_encode_decode(infile, 39, 1, 1, 0, 64000, 0); // AAC-ELD with SBR + + free_encoder_input(); + fprintf(stderr, "%d failures\n", failures); + SHA1Result(&encode_hash, encode_digest); + SHA1Result(&decode_hash, decode_digest); + printf("encode hash: "); + for (i = 0; i < SHA_DIGEST_LENGTH; i++) + printf("%02x", encode_digest[i]); + printf("\n"); + printf("decode hash: "); + for (i = 0; i < SHA_DIGEST_LENGTH; i++) + printf("%02x", decode_digest[i]); + printf("\n"); + return failures; +} diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test/ref-mono.txt b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test/ref-mono.txt new file mode 100644 index 0000000000000..39fa6dfb1150d --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test/ref-mono.txt @@ -0,0 +1,2 @@ +encode hash: 7f00e85a1eda67964e1b4044a5659a62e3952af2 +decode hash: af682b197a94e32fce09643857fa77b364574571 diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test/ref-stereo.txt b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test/ref-stereo.txt new file mode 100644 index 0000000000000..a765c9350488e --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test/ref-stereo.txt @@ -0,0 +1,2 @@ +encode hash: 8411e71bf6b32576d287764cfa577ea0e9b73280 +decode hash: 30ad42bc97b53c03139cca5437b7d9a861de0e92 diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test/run-test.sh b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test/run-test.sh new file mode 100755 index 0000000000000..b2ef5487457c9 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/test/run-test.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -e +set -o pipefail + +if [ ! -f Sample01_4.wav ]; then + curl -LO https://media.xiph.org/audio/HA_2011/Sample01_4.wav +fi + +if [ "$(md5sum Sample01_4.wav | awk '{print $1}')" != "a5c105544c64ce92c6c5c06d280e6b9c" ]; then + echo Incorrect checksum for Sample01_4.wav + exit 1 +fi + +if [ ! -f Sample01_4-mono.wav ]; then + ffmpeg -i Sample01_4.wav -ac 1 -fflags +bitexact -y Sample01_4-mono.wav +fi + +if [ "$(md5sum Sample01_4-mono.wav | awk '{print $1}')" != "3bfccac9f2e527ba3ef888874f09a409" ]; then + echo Incorrect checksum for Sample01_4-mono.wav + exit 1 +fi + +./test-encode-decode Sample01_4.wav | tee log-stereo.txt +./test-encode-decode Sample01_4-mono.wav | tee log-mono.txt + +diff -u log-stereo.txt $(dirname $0)/ref-stereo.txt +diff -u log-mono.txt $(dirname $0)/ref-mono.txt diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/wavreader.c b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/wavreader.c new file mode 100644 index 0000000000000..898eb9cf9866b --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/wavreader.c @@ -0,0 +1,193 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 2009 Martin Storsjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#include "wavreader.h" +#include +#include +#include +#include + +#define TAG(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) + +struct wav_reader { + FILE *wav; + uint32_t data_length; + + int format; + int sample_rate; + int bits_per_sample; + int channels; + int byte_rate; + int block_align; + + int streamed; +}; + +static uint32_t read_tag(struct wav_reader* wr) { + uint32_t tag = 0; + tag = (tag << 8) | fgetc(wr->wav); + tag = (tag << 8) | fgetc(wr->wav); + tag = (tag << 8) | fgetc(wr->wav); + tag = (tag << 8) | fgetc(wr->wav); + return tag; +} + +static uint32_t read_int32(struct wav_reader* wr) { + uint32_t value = 0; + value |= fgetc(wr->wav) << 0; + value |= fgetc(wr->wav) << 8; + value |= fgetc(wr->wav) << 16; + value |= fgetc(wr->wav) << 24; + return value; +} + +static uint16_t read_int16(struct wav_reader* wr) { + uint16_t value = 0; + value |= fgetc(wr->wav) << 0; + value |= fgetc(wr->wav) << 8; + return value; +} + +static void skip(FILE *f, int n) { + int i; + for (i = 0; i < n; i++) + fgetc(f); +} + +void* wav_read_open(const char *filename) { + struct wav_reader* wr = (struct wav_reader*) malloc(sizeof(*wr)); + long data_pos = 0; + memset(wr, 0, sizeof(*wr)); + + if (!strcmp(filename, "-")) + wr->wav = stdin; + else + wr->wav = fopen(filename, "rb"); + if (wr->wav == NULL) { + free(wr); + return NULL; + } + + while (1) { + uint32_t tag, tag2, length; + tag = read_tag(wr); + if (feof(wr->wav)) + break; + length = read_int32(wr); + if (!length || length >= 0x7fff0000) { + wr->streamed = 1; + length = ~0; + } + if (tag != TAG('R', 'I', 'F', 'F') || length < 4) { + fseek(wr->wav, length, SEEK_CUR); + continue; + } + tag2 = read_tag(wr); + length -= 4; + if (tag2 != TAG('W', 'A', 'V', 'E')) { + fseek(wr->wav, length, SEEK_CUR); + continue; + } + // RIFF chunk found, iterate through it + while (length >= 8) { + uint32_t subtag, sublength; + subtag = read_tag(wr); + if (feof(wr->wav)) + break; + sublength = read_int32(wr); + length -= 8; + if (length < sublength) + break; + if (subtag == TAG('f', 'm', 't', ' ')) { + if (sublength < 16) { + // Insufficient data for 'fmt ' + break; + } + wr->format = read_int16(wr); + wr->channels = read_int16(wr); + wr->sample_rate = read_int32(wr); + wr->byte_rate = read_int32(wr); + wr->block_align = read_int16(wr); + wr->bits_per_sample = read_int16(wr); + if (wr->format == 0xfffe) { + if (sublength < 28) { + // Insufficient data for waveformatex + break; + } + skip(wr->wav, 8); + wr->format = read_int32(wr); + skip(wr->wav, sublength - 28); + } else { + skip(wr->wav, sublength - 16); + } + } else if (subtag == TAG('d', 'a', 't', 'a')) { + data_pos = ftell(wr->wav); + wr->data_length = sublength; + if (!wr->data_length || wr->streamed) { + wr->streamed = 1; + return wr; + } + fseek(wr->wav, sublength, SEEK_CUR); + } else { + skip(wr->wav, sublength); + } + length -= sublength; + } + if (length > 0) { + // Bad chunk? + fseek(wr->wav, length, SEEK_CUR); + } + } + fseek(wr->wav, data_pos, SEEK_SET); + return wr; +} + +void wav_read_close(void* obj) { + struct wav_reader* wr = (struct wav_reader*) obj; + if (wr->wav != stdin) + fclose(wr->wav); + free(wr); +} + +int wav_get_header(void* obj, int* format, int* channels, int* sample_rate, int* bits_per_sample, unsigned int* data_length) { + struct wav_reader* wr = (struct wav_reader*) obj; + if (format) + *format = wr->format; + if (channels) + *channels = wr->channels; + if (sample_rate) + *sample_rate = wr->sample_rate; + if (bits_per_sample) + *bits_per_sample = wr->bits_per_sample; + if (data_length) + *data_length = wr->data_length; + return wr->format && wr->sample_rate; +} + +int wav_read_data(void* obj, unsigned char* data, unsigned int length) { + struct wav_reader* wr = (struct wav_reader*) obj; + int n; + if (wr->wav == NULL) + return -1; + if (length > wr->data_length && !wr->streamed) + length = wr->data_length; + n = fread(data, 1, length, wr->wav); + wr->data_length -= length; + return n; +} + diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/wavreader.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/wavreader.h new file mode 100644 index 0000000000000..57a13ffb08d52 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/wavreader.h @@ -0,0 +1,37 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 2009 Martin Storsjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#ifndef WAVREADER_H +#define WAVREADER_H + +#ifdef __cplusplus +extern "C" { +#endif + +void* wav_read_open(const char *filename); +void wav_read_close(void* obj); + +int wav_get_header(void* obj, int* format, int* channels, int* sample_rate, int* bits_per_sample, unsigned int* data_length); +int wav_read_data(void* obj, unsigned char* data, unsigned int length); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/win32/getopt.h b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/win32/getopt.h new file mode 100644 index 0000000000000..7402521e261d3 --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/fdk-aac-2.0.3/win32/getopt.h @@ -0,0 +1,904 @@ +#ifndef __GETOPT_H__ +/** + * DISCLAIMER + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * + * The mingw-w64 runtime package and its code is distributed in the hope that it + * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR + * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to + * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ +/* + * Implementation of the `getopt', `getopt_long' and `getopt_long_only' + * APIs, for inclusion in the MinGW runtime library. + * + * This file is part of the MinGW32 package set. + * + * Written by Keith Marshall + * Copyright (C) 2008, 2009, 2011, 2012, MinGW.org Project. + * + * --------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice, this permission notice, and the following + * disclaimer shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * --------------------------------------------------------------------------- + * + */ + +#define __GETOPT_H__ + +/* All the headers include this file. */ +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int optind; /* index of first non-option in argv */ +extern int optopt; /* single option character, as parsed */ +extern int opterr; /* flag to enable built-in diagnostics... */ + /* (user may set to zero, to suppress) */ + +extern char *optarg; /* pointer to argument of current option */ + +/* Identify how to get the calling program name, for use in messages... + */ +#ifdef __CYGWIN__ +/* + * CYGWIN uses this DLL reference... + */ +# define PROGNAME __progname +extern char __declspec(dllimport) *__progname; +#else +/* + * ...while elsewhere, we simply use the first argument passed. + */ +# define PROGNAME *argv +#endif + +extern int getopt(int nargc, char * const *nargv, const char *options); + +#ifdef _BSD_SOURCE +/* + * BSD adds the non-standard `optreset' feature, for reinitialisation + * of `getopt' parsing. We support this feature, for applications which + * proclaim their BSD heritage, before including this header; however, + * to maintain portability, developers are advised to avoid it. + */ +# define optreset __mingw_optreset +extern int optreset; +#endif +#ifdef __cplusplus +} +#endif +/* + * POSIX requires the `getopt' API to be specified in `unistd.h'; + * thus, `unistd.h' includes this header. However, we do not want + * to expose the `getopt_long' or `getopt_long_only' APIs, when + * included in this manner. Thus, close the standard __GETOPT_H__ + * declarations block, and open an additional __GETOPT_LONG_H__ + * specific block, only when *not* __UNISTD_H_SOURCED__, in which + * to declare the extended API. + */ +#endif /* !defined(__GETOPT_H__) */ + +#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) +#define __GETOPT_LONG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct option /* specification for a long form option... */ +{ + const char *name; /* option name, without leading hyphens */ + int has_arg; /* does it take an argument? */ + int *flag; /* where to save its status, or NULL */ + int val; /* its associated status value */ +}; + +enum /* permitted values for its `has_arg' field... */ +{ + no_argument = 0, /* option never takes an argument */ + required_argument, /* option always requires an argument */ + optional_argument /* option may take an argument */ +}; + +extern int getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx); +extern int getopt_long_only(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx); +/* + * Previous MinGW implementation had... + */ +#ifndef HAVE_DECL_GETOPT +/* + * ...for the long form API only; keep this for compatibility. + */ +# define HAVE_DECL_GETOPT 1 +#endif + + + +/* Identify how to get the calling program name, for use in messages... + */ +#ifdef __CYGWIN__ +/* + * CYGWIN uses this DLL reference... + */ +# define PROGNAME __progname +extern char __declspec(dllimport) *__progname; +#else +/* + * ...while elsewhere, we simply use the first argument passed. + */ +# define PROGNAME *argv +#endif + +/* Initialise the public variables. */ + +int optind = 1; /* index for first non-option arg */ +int opterr = 1; /* enable built-in error messages */ + +char *optarg = NULL; /* pointer to current option argument */ + +#define CHAR char /* argument type selector */ + +#define getopt_switchar '-' /* option prefix character in argv */ +#define getopt_pluschar '+' /* prefix for POSIX mode in optstring */ +#define getopt_takes_argument ':' /* marker for optarg in optstring */ +#define getopt_arg_assign '=' /* longopt argument field separator */ +#define getopt_unknown '?' /* return code for unmatched option */ +#define getopt_ordered 1 /* return code for ordered non-option */ + +#define getopt_all_done -1 /* return code to indicate completion */ + +enum +{ /* All `getopt' API functions are implemented via calls to the + * common static function `getopt_parse()'; these `mode' selectors + * determine the behaviour of `getopt_parse()', to deliver the + * appropriate result in each case. + */ + getopt_mode_standard = 0, /* getopt() */ + getopt_mode_long, /* getopt_long() */ + getopt_mode_long_only /* getopt_long_only() */ +}; + +enum +{ /* When attempting to match a command line argument to a long form option, + * these indicate the status of the match. + */ + getopt_no_match = 0, /* no successful match */ + getopt_abbreviated_match, /* argument is an abbreviation for an option */ + getopt_exact_match /* argument matches the full option name */ +}; + +int optopt = getopt_unknown; /* return value for option being evaluated */ + +/* Some BSD applications expect to be able to reinitialise `getopt' parsing + * by setting a global variable called `optreset'. We provide an obfuscated + * API, which allows applications to emulate this brain damage; however, any + * use of this is non-portable, and is strongly discouraged. + */ +#define optreset __mingw_optreset +int optreset = 0; + +static +int getopt_missing_arg( const CHAR *optstring ) +{ + /* Helper function to determine the appropriate return value, + * for the case where a required option argument is missing. + */ + if( (*optstring == getopt_pluschar) || (*optstring == getopt_switchar) ) + ++optstring; + return (*optstring == getopt_takes_argument) + ? getopt_takes_argument + : getopt_unknown; +} + +/* `complain' macro facilitates the generation of simple built-in + * error messages, displayed on various fault conditions, provided + * `opterr' is non-zero. + */ +#define complain( MSG, ARG ) if( opterr ) \ + fprintf( stderr, "%s: "MSG"\n", PROGNAME, ARG ) + +static +int getopt_argerror( int mode, char *fmt, CHAR *prog, struct option *opt, int retval ) +{ + /* Helper function, to generate more complex built-in error + * messages, for invalid arguments to long form options ... + */ + if( opterr ) + { + /* ... but, displayed only if `opterr' is non-zero. + */ + char flag[] = "--"; + if( mode != getopt_mode_long ) + /* + * only display one hyphen, for implicit long form options, + * improperly resolved by `getopt_long_only()'. + */ + flag[1] = 0; + /* + * always preface the program name ... + */ + fprintf( stderr, "%s: ", prog ); + /* + * to the appropriate, option specific message. + */ + fprintf( stderr, fmt, flag, opt->name ); + } + /* Whether displaying the message, or not, always set `optopt' + * to identify the faulty option ... + */ + optopt = opt->val; + /* + * and return the `invalid option' indicator. + */ + return retval; +} + +/* `getopt_conventions' establish behavioural options, to control + * the operation of `getopt_parse()', e.g. to select between POSIX + * and GNU style argument parsing behaviour. + */ +#define getopt_set_conventions 0x1000 +#define getopt_posixly_correct 0x0010 + +static +int getopt_conventions( int flags ) +{ + static int conventions = 0; + + if( (conventions == 0) && ((flags & getopt_set_conventions) == 0) ) + { + /* default conventions have not yet been established; + * initialise them now! + */ + conventions = getopt_set_conventions; + if( flags == getopt_pluschar ) + conventions |= getopt_posixly_correct; + } + + else if( flags & getopt_set_conventions ) + /* + * default conventions may have already been established, + * but this is a specific request to augment them. + */ + conventions |= flags; + + /* in any event, return the currently established conventions. + */ + return conventions; +} + +static +int is_switchar( CHAR flag ) +{ + /* A simple helper function, used to identify the switch character + * introducing an optional command line argument. + */ + return flag == getopt_switchar; +} + +static +const CHAR *getopt_match( CHAR lookup, const CHAR *opt_string ) +{ + /* Helper function, used to identify short form options. + */ + if( (*opt_string == getopt_pluschar) || (*opt_string == getopt_switchar) ) + ++opt_string; + if( *opt_string == getopt_takes_argument ) + ++opt_string; + do if( lookup == *opt_string ) return opt_string; + while( *++opt_string ); + return NULL; +} + +static +int getopt_match_long( const CHAR *nextchar, const CHAR *optname ) +{ + /* Helper function, used to identify potential matches for + * long form options. + */ + CHAR matchchar; + while( (matchchar = *nextchar++) && (matchchar == *optname) ) + /* + * skip over initial substring which DOES match. + */ + ++optname; + + if( matchchar ) + { + /* did NOT match the entire argument to an initial substring + * of a defined option name ... + */ + if( matchchar != getopt_arg_assign ) + /* + * ... and didn't stop at an `=' internal field separator, + * so this is NOT a possible match. + */ + return getopt_no_match; + + /* DID stop at an `=' internal field separator, + * so this IS a possible match, and what follows is an + * argument to the possibly matched option. + */ + optarg = (char *)(nextchar); + } + return *optname + /* + * if we DIDN'T match the ENTIRE text of the option name, + * then it's a possible abbreviated match ... + */ + ? getopt_abbreviated_match + /* + * but if we DID match the entire option name, + * then it's a DEFINITE EXACT match. + */ + : getopt_exact_match; +} + +static +int getopt_resolved( int mode, int argc, CHAR *const *argv, int *argind, +struct option *opt, int index, int *retindex, const CHAR *optstring ) +{ + /* Helper function to establish appropriate return conditions, + * on resolution of a long form option. + */ + if( retindex != NULL ) + *retindex = index; + + /* On return, `optind' should normally refer to the argument, if any, + * which follows the current one; it is convenient to set this, before + * checking for the presence of any `optarg'. + */ + optind = *argind + 1; + + if( optarg && (opt[index].has_arg == no_argument) ) + /* + * it is an error for the user to specify an option specific argument + * with an option which doesn't expect one! + */ + return getopt_argerror( mode, "option `%s%s' doesn't accept an argument\n", + PROGNAME, opt + index, getopt_unknown ); + + else if( (optarg == NULL) && (opt[index].has_arg == required_argument) ) + { + /* similarly, it is an error if no argument is specified + * with an option which requires one ... + */ + if( optind < argc ) + /* + * ... except that the requirement may be satisfied from + * the following command line argument, if any ... + */ + optarg = argv[*argind = optind++]; + + else + /* so fail this case, only if no such argument exists! + */ + return getopt_argerror( mode, "option `%s%s' requires an argument\n", + PROGNAME, opt + index, getopt_missing_arg( optstring ) ); + } + + /* when the caller has provided a return buffer ... + */ + if( opt[index].flag != NULL ) + { + /* ... then we place the proper return value there, + * and return a status code of zero ... + */ + *(opt[index].flag) = opt[index].val; + return 0; + } + /* ... otherwise, the return value becomes the status code. + */ + return opt[index].val; +} + +static +int getopt_verify( const CHAR *nextchar, const CHAR *optstring ) +{ + /* Helper function, called by getopt_parse() when invoked + * by getopt_long_only(), to verify when an unmatched or an + * ambiguously matched long form option string is valid as + * a short form option specification. + */ + if( ! (nextchar && *nextchar && optstring && *optstring) ) + /* + * There are no characters to be matched, or there are no + * valid short form option characters to which they can be + * matched, so this can never be valid. + */ + return 0; + + while( *nextchar ) + { + /* For each command line character in turn ... + */ + const CHAR *test; + if( (test = getopt_match( *nextchar++, optstring )) == NULL ) + /* + * ... there is no short form option to match the current + * candidate, so the entire argument fails. + */ + return 0; + + if( test[1] == getopt_takes_argument ) + /* + * The current candidate is valid, and it matches an option + * which takes an argument, so this command line argument is + * a valid short form option specification; accept it. + */ + return 1; + } + /* If we get to here, then every character in the command line + * argument was valid as a short form option; accept it. + */ + return 1; +} + +static +#define getopt_std_args int argc, CHAR *const argv[], const CHAR *optstring +int getopt_parse( int mode, getopt_std_args, ... ) +{ + /* Common core implementation for ALL `getopt' functions. + */ + static int argind = 0; + static int optbase = 0; + static const CHAR *nextchar = NULL; + static int optmark = 0; + + if( (optreset |= (optind < 1)) || (optind < optbase) ) + { + /* POSIX does not prescribe any definitive mechanism for restarting + * a `getopt' scan, but some applications may require such capability. + * We will support it, by allowing the caller to adjust the value of + * `optind' downwards, (nominally setting it to zero). Since POSIX + * wants `optind' to have an initial value of one, but we want all + * of our internal place holders to be initialised to zero, when we + * are called for the first time, we will handle such a reset by + * adjusting all of the internal place holders to one less than + * the adjusted `optind' value, (but never to less than zero). + */ + if( optreset ) + { + /* User has explicitly requested reinitialisation... + * We need to reset `optind' to it's normal initial value of 1, + * to avoid a potential infinitely recursive loop; by doing this + * up front, we also ensure that the remaining place holders + * will be correctly reinitialised to no less than zero. + */ + optind = 1; + + /* We also need to clear the `optreset' request... + */ + optreset = 0; + } + + /* Now, we may safely reinitialise the internal place holders, to + * one less than `optind', without fear of making them negative. + */ + optmark = optbase = argind = optind - 1; + nextchar = NULL; + } + + /* From a POSIX perspective, the following is `undefined behaviour'; + * we implement it thus, for compatibility with GNU and BSD getopt. + */ + else if( optind > (argind + 1) ) + { + /* Some applications expect to be able to manipulate `optind', + * causing `getopt' to skip over one or more elements of `argv'; + * POSIX doesn't require us to support this brain-damaged concept; + * (indeed, POSIX defines no particular behaviour, in the event of + * such usage, so it must be considered a bug for an application + * to rely on any particular outcome); nonetheless, Mac-OS-X and + * BSD actually provide *documented* support for this capability, + * so we ensure that our internal place holders keep track of + * external `optind' increments; (`argind' must lag by one). + */ + argind = optind - 1; + + /* When `optind' is misused, in this fashion, we also abandon any + * residual text in the argument we had been parsing; this is done + * without any further processing of such abandoned text, assuming + * that the caller is equipped to handle it appropriately. + */ + nextchar = NULL; + } + + if( nextchar && *nextchar ) + { + /* we are parsing a standard, or short format, option argument ... + */ + const CHAR *optchar; + if( (optchar = getopt_match( optopt = *nextchar++, optstring )) != NULL ) + { + /* we have identified it as valid ... + */ + if( optchar[1] == getopt_takes_argument ) + { + /* and determined that it requires an associated argument ... + */ + if( ! *(optarg = (char *)(nextchar)) ) + { + /* the argument is NOT attached ... + */ + if( optchar[2] == getopt_takes_argument ) + /* + * but this GNU extension marks it as optional, + * so we don't provide one on this occasion. + */ + optarg = NULL; + + /* otherwise this option takes a mandatory argument, + * so, provided there is one available ... + */ + else if( (argc - argind) > 1 ) + /* + * we take the following command line argument, + * as the appropriate option argument. + */ + optarg = argv[++argind]; + + /* but if no further argument is available, + * then there is nothing we can do, except for + * issuing the requisite diagnostic message. + */ + else + { + complain( "option requires an argument -- %c", optopt ); + return getopt_missing_arg( optstring ); + } + } + optind = argind + 1; + nextchar = NULL; + } + else + optarg = NULL; + optind = (nextchar && *nextchar) ? argind : argind + 1; + return optopt; + } + /* if we didn't find a valid match for the specified option character, + * then we fall through to here, so take appropriate diagnostic action. + */ + if( mode == getopt_mode_long_only ) + { + complain( "unrecognised option `-%s'", --nextchar ); + nextchar = NULL; + optopt = 0; + } + else + complain( "invalid option -- %c", optopt ); + optind = (nextchar && *nextchar) ? argind : argind + 1; + return getopt_unknown; + } + + if( optmark > optbase ) + { + /* This can happen, in GNU parsing mode ONLY, when we have + * skipped over non-option arguments, and found a subsequent + * option argument; in this case we permute the arguments. + */ + int index; + /* + * `optspan' specifies the number of contiguous arguments + * which are spanned by the current option, and so must be + * moved together during permutation. + */ + const int optspan = argind - optmark + 1; + /* + * we use `this_arg' to store these temporarily. + */ + CHAR **this_arg = malloc(sizeof(CHAR*) * optspan); + /* + * we cannot manipulate `argv' directly, since the `getopt' + * API prototypes it as `read-only'; this cast to `arglist' + * allows us to work around that restriction. + */ + CHAR **arglist = (char **)(argv); + + /* save temporary copies of the arguments which are associated + * with the current option ... + */ + for( index = 0; index < optspan; ++index ) + this_arg[index] = arglist[optmark + index]; + + /* move all preceding non-option arguments to the right, + * overwriting these saved arguments, while making space + * to replace them in their permuted location. + */ + for( --optmark; optmark >= optbase; --optmark ) + arglist[optmark + optspan] = arglist[optmark]; + + /* restore the temporarily saved option arguments to + * their permuted location. + */ + for( index = 0; index < optspan; ++index ) + arglist[optbase + index] = this_arg[index]; + + /* adjust `optbase', to account for the relocated option. + */ + optbase += optspan; + + free(this_arg); + } + + else + /* no permutation occurred ... + * simply adjust `optbase' for all options parsed so far. + */ + optbase = argind + 1; + + /* enter main parsing loop ... + */ + while( argc > ++argind ) + { + /* inspect each argument in turn, identifying possible options ... + */ + if( is_switchar( *(nextchar = argv[optmark = argind]) ) && *++nextchar ) + { + /* we've found a candidate option argument ... */ + + if( is_switchar( *nextchar ) ) + { + /* it's a double hyphen argument ... */ + + const CHAR *refchar = nextchar; + if( *++refchar ) + { + /* and it looks like a long format option ... + * `getopt_long' mode must be active to accept it as such, + * `getopt_long_only' also qualifies, but we must downgrade + * it to force explicit handling as a long format option. + */ + if( mode >= getopt_mode_long ) + { + nextchar = refchar; + mode = getopt_mode_long; + } + } + else + { + /* this is an explicit `--' end of options marker, so wrap up now! + */ + if( optmark > optbase ) + { + /* permuting the argument list as necessary ... + * (note use of `this_arg' and `arglist', as above). + */ + CHAR *this_arg = argv[optmark]; + CHAR **arglist = (CHAR **)(argv); + + /* move all preceding non-option arguments to the right ... + */ + do arglist[optmark] = arglist[optmark - 1]; + while( optmark-- > optbase ); + + /* reinstate the `--' marker, in its permuted location. + */ + arglist[optbase] = this_arg; + } + /* ... before finally bumping `optbase' past the `--' marker, + * and returning the `all done' completion indicator. + */ + optind = ++optbase; + return getopt_all_done; + } + } + else if( mode < getopt_mode_long_only ) + { + /* it's not an explicit long option, and `getopt_long_only' isn't active, + * so we must explicitly try to match it as a short option. + */ + mode = getopt_mode_standard; + } + + if( mode >= getopt_mode_long ) + { + /* the current argument is a long form option, (either explicitly, + * introduced by a double hyphen, or implicitly because we were called + * by `getopt_long_only'); this is where we parse it. + */ + int lookup; + int matched = -1; + + /* we need to fetch the `extra' function arguments, which are + * specified for the `getopt_long' APIs. + */ + va_list refptr; + struct option *longopts; + int *optindex; + va_start( refptr, optstring ); + longopts = va_arg( refptr, struct option * ); + optindex = va_arg( refptr, int * ); + va_end( refptr ); + + /* ensuring that `optarg' does not inherit any junk, from parsing + * preceding arguments ... + */ + optarg = NULL; + for( lookup = 0; longopts && longopts[lookup].name; ++lookup ) + { + /* scan the list of defined long form options ... + */ + switch( getopt_match_long( nextchar, longopts[lookup].name ) ) + { + /* looking for possible matches for the current argument. + */ + case getopt_exact_match: + /* + * when an exact match is found, + * return it immediately, setting `nextchar' to NULL, + * to ensure we don't mistakenly try to match any + * subsequent characters as short form options. + */ + nextchar = NULL; + return getopt_resolved( mode, argc, argv, &argind, + longopts, lookup, optindex, optstring ); + + case getopt_abbreviated_match: + /* + * but, for a partial (initial substring) match ... + */ + if( matched >= 0 ) + { + /* if this is not the first, then we have an ambiguity ... + */ + if( (mode == getopt_mode_long_only) + /* + * However, in the case of getopt_long_only(), if + * the entire ambiguously matched string represents + * a valid short option specification, then we may + * proceed to interpret it as such. + */ + && getopt_verify( nextchar, optstring ) ) + return getopt_parse( mode, argc, argv, optstring ); + + /* If we get to here, then the ambiguously matched + * partial long option isn't valid for short option + * evaluation; reset parser context to resume with + * the following command line argument, diagnose + * ambiguity, and bail out. + */ + optopt = 0; + nextchar = NULL; + optind = argind + 1; + complain( "option `%s' is ambiguous", argv[argind] ); + return getopt_unknown; + } + /* otherwise just note that we've found a possible match ... + */ + matched = lookup; + } + } + if( matched >= 0 ) + { + /* if we get to here, then we found exactly one partial match, + * so return it, as for an exact match. + */ + nextchar = NULL; + return getopt_resolved( mode, argc, argv, &argind, + longopts, matched, optindex, optstring ); + } + /* if here, then we had what SHOULD have been a long form option, + * but it is unmatched ... + */ + if( (mode < getopt_mode_long_only) + /* + * ... although paradoxically, `mode == getopt_mode_long_only' + * allows us to still try to match it as a short form option. + */ + || (getopt_verify( nextchar, optstring ) == 0) ) + { + /* When it cannot be matched, reset the parsing context to + * resume from the next argument, diagnose the failed match, + * and bail out. + */ + optopt = 0; + nextchar = NULL; + optind = argind + 1; + complain( "unrecognised option `%s'", argv[argind] ); + return getopt_unknown; + } + } + /* fall through to handle standard short form options... + * when the option argument format is neither explictly identified + * as long, nor implicitly matched as such, and the argument isn't + * just a bare hyphen, (which isn't an option), then we make one + * recursive call to explicitly interpret it as short format. + */ + if( *nextchar ) + return getopt_parse( mode, argc, argv, optstring ); + } + /* if we get to here, then we've parsed a non-option argument ... + * in GNU compatibility mode, we step over it, so we can permute + * any subsequent option arguments, but ... + */ + if( *optstring == getopt_switchar ) + { + /* if `optstring' begins with a `-' character, this special + * GNU specific behaviour requires us to return the non-option + * arguments in strict order, as pseudo-arguments to a special + * option, with return value defined as `getopt_ordered'. + */ + nextchar = NULL; + optind = argind + 1; + optarg = argv[argind]; + return getopt_ordered; + } + if( getopt_conventions( *optstring ) & getopt_posixly_correct ) + /* + * otherwise ... + * for POSIXLY_CORRECT behaviour, or if `optstring' begins with + * a `+' character, then we break out of the parsing loop, so that + * the scan ends at the current argument, with no permutation. + */ + break; + } + /* fall through when all arguments have been evaluated, + */ + optind = optbase; + return getopt_all_done; +} + +/* All three public API entry points are trivially defined, + * in terms of the internal `getopt_parse' function. + */ +int getopt( getopt_std_args ) +{ + return getopt_parse( getopt_mode_standard, argc, argv, optstring ); +} + +int getopt_long( getopt_std_args, const struct option *opts, int *index ) +{ + return getopt_parse( getopt_mode_long, argc, argv, optstring, opts, index ); +} + +int getopt_long_only( getopt_std_args, const struct option *opts, int *index ) +{ + return getopt_parse( getopt_mode_long_only, argc, argv, optstring, opts, index ); +} + +#ifdef __weak_alias +/* + * These Microsnot style uglified aliases are provided for compatibility + * with the previous MinGW implementation of the getopt API. + */ +__weak_alias( getopt, _getopt ) +__weak_alias( getopt_long, _getopt_long ) +__weak_alias( getopt_long_only, _getopt_long_only ) +#endif + + + + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */ From 3b2f7c8913ea00c566a2ed1825e85fcc0cba7f25 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 11:42:20 +0200 Subject: [PATCH 49/52] added aac writer --- src/framework/audio/common/audiotypes.h | 4 +- src/framework/audio/engine/CMakeLists.txt | 5 + .../engine/internal/export/aacencoder.cpp | 317 ++++++++++++++++++ .../audio/engine/internal/export/aacencoder.h | 46 +++ .../internal/export/soundtrackwriter.cpp | 2 + .../audio/thirdparty/fdk-aac/CMakeLists.txt | 51 +++ src/framework/cmake/MuseCreateModule.cmake | 13 +- src/importexport/audioexport/CMakeLists.txt | 2 + .../audioexport/audioexportmodule.cpp | 2 + .../audioexport/internal/aacwriter.cpp | 45 +++ .../audioexport/internal/aacwriter.h | 36 ++ src/project/internal/exporttype.h | 2 +- .../qml/MuseScore/Project/CMakeLists.txt | 1 + .../internal/Export/AacSettingsPage.qml | 43 +++ .../internal/Export/exportdialogmodel.cpp | 4 + 15 files changed, 569 insertions(+), 4 deletions(-) create mode 100644 src/framework/audio/engine/internal/export/aacencoder.cpp create mode 100644 src/framework/audio/engine/internal/export/aacencoder.h create mode 100644 src/framework/audio/thirdparty/fdk-aac/CMakeLists.txt create mode 100644 src/importexport/audioexport/internal/aacwriter.cpp create mode 100644 src/importexport/audioexport/internal/aacwriter.h create mode 100644 src/project/qml/MuseScore/Project/internal/Export/AacSettingsPage.qml diff --git a/src/framework/audio/common/audiotypes.h b/src/framework/audio/common/audiotypes.h index aa5650c32a50d..624a229bff75f 100644 --- a/src/framework/audio/common/audiotypes.h +++ b/src/framework/audio/common/audiotypes.h @@ -104,7 +104,8 @@ enum class SoundTrackType { MP3, OGG, FLAC, - WAV + WAV, + AAC }; enum class AudioSampleFormat { @@ -142,6 +143,7 @@ struct SoundTrackFormat { case SoundTrackType::MP3: case SoundTrackType::OGG: + case SoundTrackType::AAC: // For lossy, bitrate must be positive return bitRate > 0; diff --git a/src/framework/audio/engine/CMakeLists.txt b/src/framework/audio/engine/CMakeLists.txt index b68da4ec6408e..ab402452865e2 100644 --- a/src/framework/audio/engine/CMakeLists.txt +++ b/src/framework/audio/engine/CMakeLists.txt @@ -192,6 +192,8 @@ if (MUSE_MODULE_AUDIO_EXPORT) internal/export/flacencoder.h internal/export/wavencoder.cpp internal/export/wavencoder.h + internal/export/aacencoder.cpp + internal/export/aacencoder.h ) if(MUE_COMPILE_USE_SYSTEM_LAME) set(MUE_LAME_INCLUDE_DIR "" CACHE PATH "Path to directory containing lame/lame.h (optional)") @@ -226,6 +228,9 @@ if (MUSE_MODULE_AUDIO_EXPORT) include(../cmake/SetupFlac.cmake) target_link_libraries(muse_audio_engine PRIVATE ${FLAC_TARGETS}) + + add_subdirectory(../thirdparty/fdk-aac fdk_aac EXCLUDE_FROM_ALL) + target_link_libraries(muse_audio_engine PRIVATE fdk_aac) endif() # MUSE_MODULE_AUDIO_EXPORT target_link_libraries(muse_audio_engine PRIVATE muse_audio_common) diff --git a/src/framework/audio/engine/internal/export/aacencoder.cpp b/src/framework/audio/engine/internal/export/aacencoder.cpp new file mode 100644 index 0000000000000..616fb0fa88b3f --- /dev/null +++ b/src/framework/audio/engine/internal/export/aacencoder.cpp @@ -0,0 +1,317 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-CLA-applies + * + * MuseScore + * Music Composition & Notation + * + * Copyright (C) 2026 MuseScore Limited and others + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "aacencoder.h" + +#include "aacenc_lib.h" +#include "FDK_audio.h" + +#include "../dsp/audiomathutils.h" + +#include "log.h" + +using namespace muse::audio; +using namespace muse::audio::encode; + +struct AacEncoderHandler +{ + HANDLE_AACENCODER handle = nullptr; + AACENC_InfoStruct info = {}; + std::vector inputBuffer; + std::vector outputBuffer; + size_t frameLength = 0; + int channels = 0; + + ~AacEncoderHandler() + { + if (handle) { + aacEncClose(&handle); + } + } + + bool init(const SoundTrackFormat& format) + { + channels = format.outputSpec.audioChannelCount; + if (aacEncOpen(&handle, 0, channels) != AACENC_OK) { + LOGE() << "Failed to open AAC encoder"; + return false; + } + + if (aacEncoder_SetParam(handle, AACENC_AOT, AOT_AAC_LC) != AACENC_OK) { + LOGE() << "Failed to set AAC AOT"; + return false; + } + + if (aacEncoder_SetParam(handle, AACENC_SAMPLERATE, format.outputSpec.sampleRate) != AACENC_OK) { + LOGE() << "Failed to set sample rate"; + return false; + } + + CHANNEL_MODE mode = MODE_1; + switch (channels) { + case 1: mode = MODE_1; break; + case 2: mode = MODE_2; break; + case 3: mode = MODE_1_2; break; + case 4: mode = MODE_1_2_1; break; + case 5: mode = MODE_1_2_2; break; + case 6: mode = MODE_1_2_2_1; break; + default: + LOGE() << "Unsupported channel count:" << channels; + return false; + } + + if (aacEncoder_SetParam(handle, AACENC_CHANNELMODE, mode) != AACENC_OK) { + LOGE() << "Failed to set channel mode"; + return false; + } + + if (aacEncoder_SetParam(handle, AACENC_CHANNELORDER, 1) != AACENC_OK) { + LOGE() << "Failed to set channel order (WAV)"; + return false; + } + + if (aacEncoder_SetParam(handle, AACENC_BITRATE, format.bitRate * 1000) != AACENC_OK) { + LOGE() << "Failed to set bitrate"; + return false; + } + + if (aacEncoder_SetParam(handle, AACENC_TRANSMUX, TT_MP4_ADTS) != AACENC_OK) { + LOGE() << "Failed to set ADTS transport"; + return false; + } + + if (aacEncoder_SetParam(handle, AACENC_AFTERBURNER, 1) != AACENC_OK) { + LOGE() << "Failed to set afterburner"; + return false; + } + + if (aacEncEncode(handle, nullptr, nullptr, nullptr, nullptr) != AACENC_OK) { + LOGE() << "Failed to initialize AAC encoder"; + return false; + } + + if (aacEncInfo(handle, &info) != AACENC_OK) { + LOGE() << "Failed to get AAC encoder info"; + return false; + } + + frameLength = info.frameLength; + outputBuffer.resize(info.maxOutBufBytes); + inputBuffer.resize(channels * frameLength); + + return true; + } +}; + +AacEncoder::~AacEncoder() +{ + closeDestination(); +} + +bool AacEncoder::init(const io::path_t& path, const SoundTrackFormat& format, const samples_t totalSamplesNumber) +{ + if (!format.isValid()) { + return false; + } + + m_format = format; + m_handler = new AacEncoderHandler(); + + if (!m_handler->init(format)) { + delete m_handler; + m_handler = nullptr; + return false; + } + + if (!openDestination(path)) { + delete m_handler; + m_handler = nullptr; + return false; + } + + prepareOutputBuffer(totalSamplesNumber); + + return true; +} + +size_t AacEncoder::encode(samples_t samplesPerChannel, const float* input) +{ + IF_ASSERT_FAILED(m_handler && m_fileStream) { + return 0; + } + + const int channels = m_handler->channels; + const size_t frameLength = m_handler->frameLength; + const size_t samplesPerFrame = frameLength * channels; + + size_t totalBytesWritten = 0; + size_t inputOffset = 0; + const size_t totalSamples = samplesPerChannel * channels; + + while (inputOffset < totalSamples) { + size_t samplesToProcess = std::min(samplesPerFrame, totalSamples - inputOffset); + + for (size_t i = 0; i < samplesToProcess; ++i) { + m_handler->inputBuffer[i] = dsp::convertFloatSamples(input[inputOffset + i], 16); + } + + AACENC_BufDesc inBufDesc = {}; + AACENC_BufDesc outBufDesc = {}; + AACENC_InArgs inArgs = {}; + AACENC_OutArgs outArgs = {}; + + int inIdentifier = IN_AUDIO_DATA; + int inSize = static_cast(samplesToProcess * sizeof(INT_PCM)); + int inElemSize = sizeof(INT_PCM); + void* inPtr = m_handler->inputBuffer.data(); + + int outIdentifier = OUT_BITSTREAM_DATA; + int outSize = static_cast(m_handler->outputBuffer.size()); + int outElemSize = 1; + void* outPtr = m_handler->outputBuffer.data(); + + inBufDesc.numBufs = 1; + inBufDesc.bufs = &inPtr; + inBufDesc.bufferIdentifiers = &inIdentifier; + inBufDesc.bufSizes = &inSize; + inBufDesc.bufElSizes = &inElemSize; + + outBufDesc.numBufs = 1; + outBufDesc.bufs = &outPtr; + outBufDesc.bufferIdentifiers = &outIdentifier; + outBufDesc.bufSizes = &outSize; + outBufDesc.bufElSizes = &outElemSize; + + inArgs.numInSamples = static_cast(samplesToProcess); + + AACENC_ERROR err = aacEncEncode(m_handler->handle, &inBufDesc, &outBufDesc, &inArgs, &outArgs); + + if (err == AACENC_ENCODE_EOF) { + break; + } + if (err != AACENC_OK) { + LOGE() << "AAC encoding failed:" << err; + break; + } + + if (outArgs.numOutBytes > 0) { + size_t written = std::fwrite(m_handler->outputBuffer.data(), 1, outArgs.numOutBytes, m_fileStream); + totalBytesWritten += written; + } + + inputOffset += samplesToProcess; + + if (samplesToProcess < samplesPerFrame) { + break; + } + } + + return totalBytesWritten; +} + +size_t AacEncoder::flush() +{ + IF_ASSERT_FAILED(m_handler && m_fileStream) { + return 0; + } + + size_t totalBytesWritten = 0; + + AACENC_BufDesc inBufDesc = {}; + AACENC_BufDesc outBufDesc = {}; + AACENC_InArgs inArgs = {}; + AACENC_OutArgs outArgs = {}; + + int inIdentifier = IN_AUDIO_DATA; + int inSize = 0; + int inElemSize = sizeof(INT_PCM); + void* inPtr = nullptr; + + int outIdentifier = OUT_BITSTREAM_DATA; + int outSize = static_cast(m_handler->outputBuffer.size()); + int outElemSize = 1; + void* outPtr = m_handler->outputBuffer.data(); + + inBufDesc.numBufs = 1; + inBufDesc.bufs = &inPtr; + inBufDesc.bufferIdentifiers = &inIdentifier; + inBufDesc.bufSizes = &inSize; + inBufDesc.bufElSizes = &inElemSize; + + outBufDesc.numBufs = 1; + outBufDesc.bufs = &outPtr; + outBufDesc.bufferIdentifiers = &outIdentifier; + outBufDesc.bufSizes = &outSize; + outBufDesc.bufElSizes = &outElemSize; + + inArgs.numInSamples = -1; + + while (true) { + AACENC_ERROR err = aacEncEncode(m_handler->handle, &inBufDesc, &outBufDesc, &inArgs, &outArgs); + + if (err == AACENC_ENCODE_EOF) { + break; + } + if (err != AACENC_OK) { + break; + } + + if (outArgs.numOutBytes > 0) { + size_t written = std::fwrite(m_handler->outputBuffer.data(), 1, outArgs.numOutBytes, m_fileStream); + totalBytesWritten += written; + } + } + + return totalBytesWritten; +} + +size_t AacEncoder::requiredOutputBufferSize(samples_t totalSamplesNumber) const +{ + return totalSamplesNumber; +} + +bool AacEncoder::openDestination(const io::path_t& path) +{ + prepareWriting(); + m_fileStream = std::fopen(path.c_str(), "wb"); + + if (!m_fileStream) { + return false; + } + + return true; +} + +void AacEncoder::closeDestination() +{ + if (m_fileStream) { + std::fclose(m_fileStream); + m_fileStream = nullptr; + } + + if (m_handler) { + delete m_handler; + m_handler = nullptr; + } + + completeWriting(); +} diff --git a/src/framework/audio/engine/internal/export/aacencoder.h b/src/framework/audio/engine/internal/export/aacencoder.h new file mode 100644 index 0000000000000..ff2dc1e63d65f --- /dev/null +++ b/src/framework/audio/engine/internal/export/aacencoder.h @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-CLA-applies + * + * MuseScore + * Music Composition & Notation + * + * Copyright (C) 2026 MuseScore Limited and others + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "abstractaudioencoder.h" + +struct AacEncoderHandler; + +namespace muse::audio::encode { +class AacEncoder : public AbstractAudioEncoder +{ +public: + bool init(const io::path_t& path, const SoundTrackFormat& format, const samples_t totalSamplesNumber) override; + + size_t encode(samples_t samplesPerChannel, const float* input) override; + size_t flush() override; + +protected: + size_t requiredOutputBufferSize(samples_t totalSamplesNumber) const override; + bool openDestination(const io::path_t& path) override; + void closeDestination() override; + +private: + AacEncoderHandler* m_handler = nullptr; +}; +} diff --git a/src/framework/audio/engine/internal/export/soundtrackwriter.cpp b/src/framework/audio/engine/internal/export/soundtrackwriter.cpp index 779c7d8f96702..6bb3871f4dbcd 100644 --- a/src/framework/audio/engine/internal/export/soundtrackwriter.cpp +++ b/src/framework/audio/engine/internal/export/soundtrackwriter.cpp @@ -31,6 +31,7 @@ #include "oggencoder.h" #include "flacencoder.h" #include "wavencoder.h" +#include "aacencoder.h" #include "log.h" @@ -49,6 +50,7 @@ static encode::AbstractAudioEncoderPtr createEncoder(const SoundTrackFormat& for case SoundTrackType::OGG: return std::make_unique(format, dstDevice); case SoundTrackType::FLAC: return std::make_unique(format, dstDevice); case SoundTrackType::WAV: return std::make_unique(format, dstDevice); + case SoundTrackType::AAC: return std::make_unique(format, dstDevice); case SoundTrackType::Undefined: break; } diff --git a/src/framework/audio/thirdparty/fdk-aac/CMakeLists.txt b/src/framework/audio/thirdparty/fdk-aac/CMakeLists.txt new file mode 100644 index 0000000000000..4a1cb44f14bab --- /dev/null +++ b/src/framework/audio/thirdparty/fdk-aac/CMakeLists.txt @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: GPL-3.0-only +# MuseScore-Studio-CLA-applies +# +# MuseScore Studio +# Music Composition & Notation +# +# Copyright (C) 2026 MuseScore Limited +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Use static library for consistency with other MuseScore thirdparty libs +set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared library" FORCE) +set(BUILD_PROGRAMS OFF CACHE BOOL "Build extra utilities" FORCE) + +add_subdirectory(fdk-aac-2.0.3 EXCLUDE_FROM_ALL) + +muse_create_thirdparty_module(fdk_aac INTERFACE fdk-aac) + +target_no_warning(fdk-aac -Wno-unused-parameter) +target_no_warning(fdk-aac -Wno-unused-variable) +target_no_warning(fdk-aac -Wno-deprecated-declarations) +target_no_warning(fdk-aac -Wno-type-limits) +target_no_warning(fdk-aac -Wno-unknown-pragmas) +target_no_warning(fdk-aac -Wno-conversion) +target_no_warning(fdk-aac -Wno-uninitialized) +target_no_warning(fdk-aac -Wno-shift-negative-value) +target_no_warning(fdk-aac -Wno-implicit-fallthrough) +target_no_warning(fdk-aac -Wno-empty-body) +target_no_warning(fdk-aac -Wno-attributes) +target_no_warning(fdk-aac -Wc-no-absolute-value) +target_no_warning(fdk-aac -Wc-no-tautological-pointer-compare) +target_no_warning(fdk-aac -Wc-no-array-parameter) +target_no_warning(fdk-aac -Wno-unused-but-set-variable) +target_no_warning(fdk-aac -WMSVC-no-translation-unit-is-empty) +target_no_warning(fdk-aac -WMSVC-no-nonstandard-extension-used) +target_no_warning(fdk-aac -WMSVC-no-assignment-within-conditional-expression) +target_no_warning(fdk-aac -WMSVC-no-hides-previous) +target_no_warning(fdk-aac -WMSVC-no-undefined-assuming-extern) +target_no_warning(fdk-aac -WMSVC-named-type-definition-in-parentheses) +target_no_warning(fdk-aac -WMSVC-no-benign-redefinition) +target_no_warning(fdk-aac -WMSVC-no-unreachable) diff --git a/src/framework/cmake/MuseCreateModule.cmake b/src/framework/cmake/MuseCreateModule.cmake index b516ab5b4f7af..f51df59ae0026 100644 --- a/src/framework/cmake/MuseCreateModule.cmake +++ b/src/framework/cmake/MuseCreateModule.cmake @@ -150,8 +150,9 @@ endfunction() # - Creates a target and sets up common properties for Muse thirdparty modules function(muse_create_thirdparty_module target_name) + set(options INTERFACE) set(oneValueArgs ALIAS) - cmake_parse_arguments(PARSE_ARGV 1 arg "" "${oneValueArgs}" "") + cmake_parse_arguments(PARSE_ARGV 1 arg "${options}" "${oneValueArgs}" "") # Status message set(message "Configuring ${target_name}") @@ -162,7 +163,15 @@ function(muse_create_thirdparty_module target_name) # Create target # STATIC/SHARED based on BUILD_SHARED_LIBS, which is set in SetupBuildEnvironment.cmake - add_library(${target_name}) + + if (arg_INTERFACE) + add_library(${target_name} INTERFACE) + if (arg_UNPARSED_ARGUMENTS) + target_link_libraries(${target_name} INTERFACE ${arg_UNPARSED_ARGUMENTS}) + endif() + else() + add_library(${target_name}) + endif() set_target_properties(${target_name} PROPERTIES AUTOMOC OFF diff --git a/src/importexport/audioexport/CMakeLists.txt b/src/importexport/audioexport/CMakeLists.txt index a2d32d60b948d..15aef797553ce 100644 --- a/src/importexport/audioexport/CMakeLists.txt +++ b/src/importexport/audioexport/CMakeLists.txt @@ -36,4 +36,6 @@ target_sources(iex_audioexport PRIVATE internal/oggwriter.h internal/flacwriter.cpp internal/flacwriter.h + internal/aacwriter.cpp + internal/aacwriter.h ) diff --git a/src/importexport/audioexport/audioexportmodule.cpp b/src/importexport/audioexport/audioexportmodule.cpp index 42906b8eb6c39..b1355180fdcb4 100644 --- a/src/importexport/audioexport/audioexportmodule.cpp +++ b/src/importexport/audioexport/audioexportmodule.cpp @@ -28,6 +28,7 @@ #include "internal/wavewriter.h" #include "internal/oggwriter.h" #include "internal/flacwriter.h" +#include "internal/aacwriter.h" #include "internal/audioexportconfiguration.h" @@ -58,6 +59,7 @@ void AudioExportModule::resolveImports() writers->reg({ "mp3" }, std::make_shared(globalCtx())); writers->reg({ "ogg" }, std::make_shared(globalCtx())); writers->reg({ "flac" }, std::make_shared(globalCtx())); + writers->reg({ "aac" }, std::make_shared(globalCtx())); } } diff --git a/src/importexport/audioexport/internal/aacwriter.cpp b/src/importexport/audioexport/internal/aacwriter.cpp new file mode 100644 index 0000000000000..6bc1e4f4f67f2 --- /dev/null +++ b/src/importexport/audioexport/internal/aacwriter.cpp @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2026 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "aacwriter.h" + +#include "log.h" + +using namespace muse; +using namespace muse::audio; +using namespace mu::iex::audioexport; + +Ret AacWriter::write(notation::INotationPtr notation, io::IODevice& destinationDevice, const Options& options) +{ + const SoundTrackFormat format { + SoundTrackType::AAC, + { + static_cast(configuration()->exportSampleRate()), + configuration()->exportBufferSize(), + 2 /* audioChannelsNumber */ + }, + AudioSampleFormat::Undefined, + configuration()->exportMp3Bitrate() + }; + + return doWriteAndWait(notation, destinationDevice, format, options); +} diff --git a/src/importexport/audioexport/internal/aacwriter.h b/src/importexport/audioexport/internal/aacwriter.h new file mode 100644 index 0000000000000..380a04c972871 --- /dev/null +++ b/src/importexport/audioexport/internal/aacwriter.h @@ -0,0 +1,36 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2026 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "abstractaudiowriter.h" + +namespace mu::iex::audioexport { +class AacWriter : public AbstractAudioWriter +{ +public: + AacWriter(const muse::modularity::ContextPtr& iocCtx) + : AbstractAudioWriter(iocCtx) {} + + muse::Ret write(notation::INotationPtr notation, muse::io::IODevice& destinationDevice, const Options& options = Options()) override; +}; +} diff --git a/src/project/internal/exporttype.h b/src/project/internal/exporttype.h index 6d7e7c179a793..d7b319d7ffcd2 100644 --- a/src/project/internal/exporttype.h +++ b/src/project/internal/exporttype.h @@ -66,7 +66,7 @@ struct ExportType inline bool isAudioExport(const std::string& suffix) { static const std::unordered_set audioSuffixes { - "mp3", "wav", "ogg", "flac", + "mp3", "wav", "ogg", "flac", "aac", }; return muse::contains(audioSuffixes, suffix); diff --git a/src/project/qml/MuseScore/Project/CMakeLists.txt b/src/project/qml/MuseScore/Project/CMakeLists.txt index 0fcba96f96b3b..f9a68001ee6db 100644 --- a/src/project/qml/MuseScore/Project/CMakeLists.txt +++ b/src/project/qml/MuseScore/Project/CMakeLists.txt @@ -75,6 +75,7 @@ qt_add_qml_module(project_qml internal/Export/OggSettingsPage.qml internal/Export/FlacSettingsPage.qml internal/Export/WavSettingsPage.qml + internal/Export/AacSettingsPage.qml internal/Export/PdfSettingsPage.qml internal/Export/PngSettingsPage.qml internal/Export/SvgSettingsPage.qml diff --git a/src/project/qml/MuseScore/Project/internal/Export/AacSettingsPage.qml b/src/project/qml/MuseScore/Project/internal/Export/AacSettingsPage.qml new file mode 100644 index 0000000000000..4db2e055791a2 --- /dev/null +++ b/src/project/qml/MuseScore/Project/internal/Export/AacSettingsPage.qml @@ -0,0 +1,43 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2026 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import QtQuick + +import Muse.UiComponents +import MuseScore.Project + +ExportSettingsPage { + id: root + + AudioSettings { + model: root.model + navigationPanel: root.navigationPanel + navigationOrder: root.navigationOrder + showBitRateControl: true + } + + StyledTextLabel { + width: parent.width + text: qsTrc("project/export", "Each selected part will be exported as a separate audio file.") + horizontalAlignment: Text.AlignLeft + wrapMode: Text.WordWrap + } +} diff --git a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp index 84eb28eb1e034..4eb3f513ae3c4 100644 --- a/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp +++ b/src/project/qml/MuseScore/Project/internal/Export/exportdialogmodel.cpp @@ -91,6 +91,10 @@ ExportDialogModel::ExportDialogModel(QObject* parent) muse::qtrc("project/export", "FLAC audio"), muse::qtrc("project/export", "FLAC audio files"), "FlacSettingsPage.qml"), + ExportType::makeWithSuffixes({ "aac" }, + muse::qtrc("project/export", "AAC audio"), + muse::qtrc("project/export", "AAC audio files"), + "AacSettingsPage.qml"), #ifdef MUE_BUILD_IMPEXP_VIDEOEXPORT_MODULE ExportType::makeWithSuffixes({ "mp4" }, muse::qtrc("project/export", "MP4 video"), From cc5eea1c4679bb8fe6c1122512c58c30720e2ab1 Mon Sep 17 00:00:00 2001 From: Eism Date: Thu, 19 Mar 2026 14:13:35 +0200 Subject: [PATCH 50/52] use aac for video export --- .../engine/internal/export/aacencoder.cpp | 23 ++++++++++--------- .../videoexport/internal/videowriter.cpp | 6 ++--- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/framework/audio/engine/internal/export/aacencoder.cpp b/src/framework/audio/engine/internal/export/aacencoder.cpp index 616fb0fa88b3f..e581867c81fd4 100644 --- a/src/framework/audio/engine/internal/export/aacencoder.cpp +++ b/src/framework/audio/engine/internal/export/aacencoder.cpp @@ -68,12 +68,18 @@ struct AacEncoderHandler CHANNEL_MODE mode = MODE_1; switch (channels) { - case 1: mode = MODE_1; break; - case 2: mode = MODE_2; break; - case 3: mode = MODE_1_2; break; - case 4: mode = MODE_1_2_1; break; - case 5: mode = MODE_1_2_2; break; - case 6: mode = MODE_1_2_2_1; break; + case 1: mode = MODE_1; + break; + case 2: mode = MODE_2; + break; + case 3: mode = MODE_1_2; + break; + case 4: mode = MODE_1_2_1; + break; + case 5: mode = MODE_1_2_2; + break; + case 6: mode = MODE_1_2_2_1; + break; default: LOGE() << "Unsupported channel count:" << channels; return false; @@ -122,11 +128,6 @@ struct AacEncoderHandler } }; -AacEncoder::~AacEncoder() -{ - closeDestination(); -} - bool AacEncoder::init(const io::path_t& path, const SoundTrackFormat& format, const samples_t totalSamplesNumber) { if (!format.isValid()) { diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index 67e25228101e1..69dc051b10bb2 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -71,7 +71,7 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, Config cfg = makeConfig(); muse::io::path_t finalPath(filePath); - muse::io::path_t tempAudioPath = finalPath + ".tmp_audio.mp3"; + muse::io::path_t tempAudioPath = finalPath + ".tmp_audio.aac"; auto encoder = videoEncodeResolver()->currentVideoEncoder(); @@ -202,9 +202,9 @@ void VideoWriter::startVideoExport(muse::media::IVideoEncoderPtr encoder, INotat void VideoWriter::startAudioExport(INotationPtr notation, const muse::io::path_t& audioPath) { - m_audioWriter = writers()->writer("mp3"); + m_audioWriter = writers()->writer("aac"); if (!m_audioWriter) { - LOGE() << "mp3 writer not found"; + LOGE() << "aac writer not found"; m_audioRet = make_ret(muse::Ret::Code::InternalError); m_audioCompleted = true; return; From 6f8a9f25e4253b5570842873341bc20f6826522d Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 12:10:53 +0200 Subject: [PATCH 51/52] updated aac encoder to use IODevice (master update) --- .../engine/internal/export/aacencoder.cpp | 68 ++++--------------- .../audio/engine/internal/export/aacencoder.h | 22 +++--- 2 files changed, 29 insertions(+), 61 deletions(-) diff --git a/src/framework/audio/engine/internal/export/aacencoder.cpp b/src/framework/audio/engine/internal/export/aacencoder.cpp index e581867c81fd4..4ab22088d57f1 100644 --- a/src/framework/audio/engine/internal/export/aacencoder.cpp +++ b/src/framework/audio/engine/internal/export/aacencoder.cpp @@ -128,35 +128,29 @@ struct AacEncoderHandler } }; -bool AacEncoder::init(const io::path_t& path, const SoundTrackFormat& format, const samples_t totalSamplesNumber) +AacEncoder::AacEncoder(const SoundTrackFormat& format, io::IODevice& dstDevice) + : AbstractAudioEncoder(format), m_handler{std::make_unique()}, m_dstDevice{&dstDevice} { - if (!format.isValid()) { - return false; - } + DO_ASSERT(m_dstDevice); +} - m_format = format; - m_handler = new AacEncoderHandler(); +AacEncoder::~AacEncoder() noexcept = default; - if (!m_handler->init(format)) { - delete m_handler; - m_handler = nullptr; - return false; - } +bool AacEncoder::begin(const samples_t totalSamplesNumber) +{ + m_outputBuffer.resize(totalSamplesNumber); - if (!openDestination(path)) { - delete m_handler; - m_handler = nullptr; + if (!m_handler->init(m_format)) { + m_handler.reset(); return false; } - prepareOutputBuffer(totalSamplesNumber); - return true; } size_t AacEncoder::encode(samples_t samplesPerChannel, const float* input) { - IF_ASSERT_FAILED(m_handler && m_fileStream) { + IF_ASSERT_FAILED(m_handler) { return 0; } @@ -215,7 +209,7 @@ size_t AacEncoder::encode(samples_t samplesPerChannel, const float* input) } if (outArgs.numOutBytes > 0) { - size_t written = std::fwrite(m_handler->outputBuffer.data(), 1, outArgs.numOutBytes, m_fileStream); + const size_t written = m_dstDevice->write(m_outputBuffer.data(), static_cast(outArgs.numOutBytes)); totalBytesWritten += written; } @@ -229,9 +223,9 @@ size_t AacEncoder::encode(samples_t samplesPerChannel, const float* input) return totalBytesWritten; } -size_t AacEncoder::flush() +size_t AacEncoder::end() { - IF_ASSERT_FAILED(m_handler && m_fileStream) { + IF_ASSERT_FAILED(m_handler) { return 0; } @@ -277,42 +271,10 @@ size_t AacEncoder::flush() } if (outArgs.numOutBytes > 0) { - size_t written = std::fwrite(m_handler->outputBuffer.data(), 1, outArgs.numOutBytes, m_fileStream); + const size_t written = m_dstDevice->write(m_outputBuffer.data(), static_cast(outArgs.numOutBytes)); totalBytesWritten += written; } } return totalBytesWritten; } - -size_t AacEncoder::requiredOutputBufferSize(samples_t totalSamplesNumber) const -{ - return totalSamplesNumber; -} - -bool AacEncoder::openDestination(const io::path_t& path) -{ - prepareWriting(); - m_fileStream = std::fopen(path.c_str(), "wb"); - - if (!m_fileStream) { - return false; - } - - return true; -} - -void AacEncoder::closeDestination() -{ - if (m_fileStream) { - std::fclose(m_fileStream); - m_fileStream = nullptr; - } - - if (m_handler) { - delete m_handler; - m_handler = nullptr; - } - - completeWriting(); -} diff --git a/src/framework/audio/engine/internal/export/aacencoder.h b/src/framework/audio/engine/internal/export/aacencoder.h index ff2dc1e63d65f..d93a1cdbbef0e 100644 --- a/src/framework/audio/engine/internal/export/aacencoder.h +++ b/src/framework/audio/engine/internal/export/aacencoder.h @@ -24,23 +24,29 @@ #include "abstractaudioencoder.h" +#include + struct AacEncoderHandler; +namespace muse::io { +class IODevice; +} + namespace muse::audio::encode { class AacEncoder : public AbstractAudioEncoder { public: - bool init(const io::path_t& path, const SoundTrackFormat& format, const samples_t totalSamplesNumber) override; + AacEncoder(const SoundTrackFormat&, io::IODevice&); - size_t encode(samples_t samplesPerChannel, const float* input) override; - size_t flush() override; + ~AacEncoder() noexcept override; -protected: - size_t requiredOutputBufferSize(samples_t totalSamplesNumber) const override; - bool openDestination(const io::path_t& path) override; - void closeDestination() override; + bool begin(samples_t samplesPerChannel) override; + size_t encode(samples_t samplesPerChannel, const float* input) override; + size_t end() override; private: - AacEncoderHandler* m_handler = nullptr; + std::vector m_outputBuffer; + std::unique_ptr m_handler; + io::IODevice* m_dstDevice = nullptr; }; } From 84ae078c2b9c273b17bbfb1579d92c56de9f5b51 Mon Sep 17 00:00:00 2001 From: Eism Date: Mon, 23 Mar 2026 14:34:59 +0200 Subject: [PATCH 52/52] fixed build after conflicts resolving --- .../audioexport/internal/abstractaudiowriter.cpp | 2 ++ src/importexport/videoexport/internal/videowriter.cpp | 2 +- src/importexport/videoexport/internal/videowriter.h | 7 +++++-- src/importexport/videoexport/videoexportmodule.cpp | 4 ++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/importexport/audioexport/internal/abstractaudiowriter.cpp b/src/importexport/audioexport/internal/abstractaudiowriter.cpp index 3f0bb2ae7583d..b1577b14d19a1 100644 --- a/src/importexport/audioexport/internal/abstractaudiowriter.cpp +++ b/src/importexport/audioexport/internal/abstractaudiowriter.cpp @@ -132,6 +132,8 @@ void AbstractAudioWriter::doWrite(io::IODevice& dstDevice, const SoundTrackForma const std::string processingOnlineSoundsMsg = trc("iex_audio", "Processing online sounds…"); auto restoreState = [this]() { + muse::ContextInject playbackController = { m_iocContext }; + muse::ContextInject globalContext = { m_iocContext }; playbackController()->setIsExportingAudio(false); playbackController()->setNotation(globalContext()->currentNotation()); }; diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index 69dc051b10bb2..035694d513b94 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -109,7 +109,7 @@ muse::Ret VideoWriter::write(INotationPtr notation, muse::io::IODevice& device, } //! NOTE: we have to do it in main thread - notation->notationChanged().notify(); + notation->notationChanged().send(muse::RectF()); if (m_audioWriter) { m_audioWriter->progress()->finished().disconnect(this); diff --git a/src/importexport/videoexport/internal/videowriter.h b/src/importexport/videoexport/internal/videowriter.h index 73c569ed701de..da08b61f0cf1d 100644 --- a/src/importexport/videoexport/internal/videowriter.h +++ b/src/importexport/videoexport/internal/videowriter.h @@ -46,11 +46,14 @@ namespace mu::iex::videoexport { class VideoWriter : public project::INotationWriter, public muse::Contextable, public muse::async::Asyncable { muse::GlobalInject configuration; - muse::ContextInject application = { this }; + muse::GlobalInject application; + muse::GlobalInject writers; muse::ContextInject videoEncodeResolver = { this }; - muse::ContextInject writers = { this }; public: + VideoWriter(const muse::modularity::ContextPtr& iocCtx) + : muse::Contextable(iocCtx) {} + std::vector supportedUnitTypes() const override; bool supportsUnitType(UnitType unitType) const override; diff --git a/src/importexport/videoexport/videoexportmodule.cpp b/src/importexport/videoexport/videoexportmodule.cpp index 0da4cc4ecda2b..34cf6dbd1cf5a 100644 --- a/src/importexport/videoexport/videoexportmodule.cpp +++ b/src/importexport/videoexport/videoexportmodule.cpp @@ -46,8 +46,8 @@ void VideoExportModule::registerExports() void VideoExportModule::resolveImports() { - auto writers = ioc()->resolve(moduleName()); + auto writers = globalIoc()->resolve(moduleName()); if (writers) { - writers->reg({ "mp4" }, std::make_shared(iocContext())); + writers->reg({ "mp4" }, std::make_shared(globalCtx())); } }